svn commit: r236745 - stable/8/sys/dev/sound/pcm

Alexander Motin mav at FreeBSD.org
Fri Jun 8 11:58:29 UTC 2012


Author: mav
Date: Fri Jun  8 11:58:28 2012
New Revision: 236745
URL: http://svn.freebsd.org/changeset/base/236745

Log:
  MFC r222826:
  Make automatic hw.snd.default_unit choice a bit more intelligent. Instead
  of just setting it to the first registered device, reevaluate it for each
  device registered, trying to choose best candidate, unless one was forced.
  For now use such preference order: play&rec, play, rec.
  
  As side effect, this should workaround the situation when HDMI audio output
  of the video card, usually not connected to anything, becomes default, that
  requires manual user intervention to make sound working. If at some point
  this won't be enough, we can try to fetch some additional priority flags
  from the device driver.

Modified:
  stable/8/sys/dev/sound/pcm/sound.c
Directory Properties:
  stable/8/sys/   (props changed)

Modified: stable/8/sys/dev/sound/pcm/sound.c
==============================================================================
--- stable/8/sys/dev/sound/pcm/sound.c	Fri Jun  8 11:53:51 2012	(r236744)
+++ stable/8/sys/dev/sound/pcm/sound.c	Fri Jun  8 11:58:28 2012	(r236745)
@@ -51,7 +51,7 @@ int pcm_veto_load = 1;
 int snd_unit = -1;
 TUNABLE_INT("hw.snd.default_unit", &snd_unit);
 
-static int snd_unit_auto = 0;
+static int snd_unit_auto = -1;
 TUNABLE_INT("hw.snd.default_auto", &snd_unit_auto);
 SYSCTL_INT(_hw_snd, OID_AUTO, default_auto, CTLFLAG_RW,
     &snd_unit_auto, 0, "assign default unit to a newly attached device");
@@ -443,6 +443,7 @@ sysctl_hw_snd_default_unit(SYSCTL_HANDLE
 		if (!PCM_REGISTERED(d) || CHN_EMPTY(d, channels.pcm))
 			return EINVAL;
 		snd_unit = unit;
+		snd_unit_auto = 0;
 	}
 	return (error);
 }
@@ -737,6 +738,32 @@ pcm_killchan(device_t dev)
 	return (pcm_chn_destroy(ch));
 }
 
+static int
+pcm_best_unit(int old)
+{
+	struct snddev_info *d;
+	int i, best, bestprio, prio;
+
+	best = -1;
+	bestprio = -100;
+	for (i = 0; pcm_devclass != NULL &&
+	    i < devclass_get_maxunit(pcm_devclass); i++) {
+		d = devclass_get_softc(pcm_devclass, i);
+		if (!PCM_REGISTERED(d))
+			continue;
+		prio = 0;
+		if (d->playcount == 0)
+			prio -= 10;
+		if (d->reccount == 0)
+			prio -= 2;
+		if (prio > bestprio || (prio == bestprio && i == old)) {
+			best = i;
+			bestprio = prio;
+		}
+	}
+	return (best);
+}
+
 int
 pcm_setstatus(device_t dev, char *str)
 {
@@ -770,8 +797,12 @@ pcm_setstatus(device_t dev, char *str)
 
 	PCM_UNLOCK(d);
 
-	if (snd_unit < 0 || snd_unit_auto != 0)
+	if (snd_unit_auto < 0)
+		snd_unit_auto = (snd_unit < 0) ? 1 : 0;
+	if (snd_unit < 0 || snd_unit_auto > 1)
 		snd_unit = device_get_unit(dev);
+	else if (snd_unit_auto == 1)
+		snd_unit = pcm_best_unit(snd_unit);
 
 	return (0);
 }
@@ -1113,7 +1144,6 @@ pcm_unregister(device_t dev)
 	struct snddev_info *d;
 	struct pcm_channel *ch;
 	struct thread *td;
-	int i;
 
 	td = curthread;
 	d = device_get_softc(dev);
@@ -1216,21 +1246,9 @@ pcm_unregister(device_t dev)
 	sndstat_release(td);
 
 	if (snd_unit == device_get_unit(dev)) {
-		/*
-		 * Reassign default unit to the next available dev, but
-		 * first, reset snd_unit to something ridiculous.
-		 */
-		snd_unit = -1;
-		for (i = 0; pcm_devclass != NULL &&
-		    i < devclass_get_maxunit(pcm_devclass); i++) {
-			if (device_get_unit(dev) == i)
-				continue;
-			d = devclass_get_softc(pcm_devclass, i);
-			if (PCM_REGISTERED(d)) {
-				snd_unit = i;
-				break;
-			}
-		}
+		snd_unit = pcm_best_unit(-1);
+		if (snd_unit_auto == 0)
+			snd_unit_auto = 1;
 	}
 
 	return (0);


More information about the svn-src-stable-8 mailing list