HDA sound driver hack for Acer Aspire 1641

Maxime Guillaud bsd-ports at mguillaud.net
Sat Jul 22 12:24:16 UTC 2006


After some tweaking of Andrea Bittau's code, I managed to get the sound 
(output only) working on my Acer Aspire 1641 WLMi.
You can get the driver from
http://www.mguillaud.net/acer1641/FreeBSD/hdac.tgz

I also attach a diff against Andrea's original code, FYI.

Maxime


-------------- next part --------------
diff -ur hdac-20060608/hda_reg.h /usr/src/sys/dev/hdac/hda_reg.h
--- hdac-20060608/hda_reg.h	Sun Jun  4 01:10:31 2006
+++ /usr/src/sys/dev/hdac/hda_reg.h	Wed Jul  5 18:49:17 2006
@@ -1192,4 +1192,35 @@
     (((param) & HDA_PARAM_VOLUME_KNOB_CAP_NUM_STEPS_MASK) >>		\
     HDA_PARAM_VOLUME_KNOB_CAP_NUM_STEPS_SHIFT)
 
+
+#define HDA_CONFIG_DEFAULTCONF_SEQUENCE_MASK		0x00000000f
+#define HDA_CONFIG_DEFAULTCONF_ASSOCIATION_MASK		0x0000000f0
+#define HDA_CONFIG_DEFAULTCONF_MISC_MASK			0x000000f00
+#define HDA_CONFIG_DEFAULTCONF_COLOR_MASK			0x00000f000
+#define HDA_CONFIG_DEFAULTCONF_CONNECTION_TYPE_MASK		0x000f00000
+#define HDA_CONFIG_DEFAULTCONF_DEVICE_MASK			0x000f00000
+#define HDA_CONFIG_DEFAULTCONF_LOCATION_MASK		0x03f000000
+#define HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK		0x0c0000000
+
+#define HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_JACK		(0<<30)
+#define HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE		(1<<30)
+#define HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED		(2<<30)
+#define HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_BOTH		(3<<30)
+
+#define HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_OUT			(0<<20)
+#define HDA_CONFIG_DEFAULTCONF_DEVICE_SPEAKER			(1<<20)
+#define HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT			(2<<20)
+#define HDA_CONFIG_DEFAULTCONF_DEVICE_CD			(3<<20)
+#define HDA_CONFIG_DEFAULTCONF_DEVICE_SPDIF_OUT			(4<<20)
+#define HDA_CONFIG_DEFAULTCONF_DEVICE_DIGITAL_OTHER_OUT		(5<<20)
+#define HDA_CONFIG_DEFAULTCONF_DEVICE_MODEM_LINE		(6<<20)
+#define HDA_CONFIG_DEFAULTCONF_DEVICE_MODEM_HANDSET		(7<<20)
+#define HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN			(8<<20)
+#define HDA_CONFIG_DEFAULTCONF_DEVICE_AUX			(9<<20)
+#define HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN			(10<<20)
+#define HDA_CONFIG_DEFAULTCONF_DEVICE_TELEPHONY			(11<<20)
+#define HDA_CONFIG_DEFAULTCONF_DEVICE_SPDIF_IN			(12<<20)
+#define HDA_CONFIG_DEFAULTCONF_DEVICE_DIGITAL_OTHER_IN		(13<<20)
+#define HDA_CONFIG_DEFAULTCONF_DEVICE_OTHER			(15<<20)
+
 #endif
diff -ur hdac-20060608/hdac.c /usr/src/sys/dev/hdac/hdac.c
--- hdac-20060608/hdac.c	Mon Jun  5 21:15:12 2006
+++ /usr/src/sys/dev/hdac/hdac.c	Sat Jul 15 12:02:49 2006
@@ -54,6 +54,7 @@
 
 #define INTEL_VENDORID	0x8086
 
+#define INTEL_82801F	0x2668
 #define INTEL_82801G	0x27d8
 
 
@@ -62,6 +63,8 @@
 	uint16_t	vendor;
 	char		*description;
 } hdac_devices[] = {
+	{ INTEL_82801F, INTEL_VENDORID,
+	    "Intel 82801F High Definition Audio Controller" },
 	{ INTEL_82801G, INTEL_VENDORID,
 	    "Intel 82801G High Definition Audio Controller" }
 };
@@ -247,7 +250,8 @@
 	 * Reset the controller. The reset must remain asserted for
 	 * a minimum of 100us.
 	 */
-	HDAC_WRITE_4(&sc->mem, HDAC_GCTL, 0x0);
+        gctl = HDAC_READ_4(&sc->mem, HDAC_GCTL);
+        HDAC_WRITE_4(&sc->mem, HDAC_GCTL, gctl | HDAC_GCTL_CRST);
 	count = 10000;
 	while (count) {
 		gctl = HDAC_READ_4(&sc->mem, HDAC_GCTL);
@@ -260,11 +264,11 @@
 		return (ENXIO);
 	}
 	DELAY(100);
-	HDAC_WRITE_4(&sc->mem, HDAC_GCTL, HDAC_GCTL_CRST);
+        gctl = HDAC_READ_4(&sc->mem, HDAC_GCTL);
+        HDAC_WRITE_4(&sc->mem, HDAC_GCTL, gctl | HDAC_GCTL_CRST);
 	count = 10000;
 	while (count) {
-		gctl = HDAC_READ_4(&sc->mem, HDAC_GCTL);
-		if ((gctl & HDAC_GCTL_CRST) == HDAC_GCTL_CRST)
+                if (HDAC_READ_4(&sc->mem, HDAC_GCTL) & HDAC_GCTL_CRST)
 			break;
 		count--;
 	}
@@ -785,7 +789,8 @@
 	devinfo->revision_id = HDA_PARAM_REVISION_ID_REVISION_ID(revisionid);
 	devinfo->stepping_id = HDA_PARAM_REVISION_ID_STEPPING_ID(revisionid);
 	devinfo->node_type = HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE(fctgrptype);
-
+	device_printf(sc->dev, "Vendor info: %x %x %x %x %x %x\n", vendorid, devinfo->vendor_id, devinfo->device_id,
+		devinfo->revision_id, devinfo->stepping_id, devinfo->node_type);
 	hdac_add_child(sc, devinfo);
 }
 
@@ -811,6 +816,40 @@
 }
 
 static void
+sorbo_print_conn(struct hdac_softc *sc, int cad, int nid)
+{
+	uint32_t rc,i,cll;
+	uint32_t l=0;
+	uint16_t payload;
+	char connection_list[1024];
+	char connection_string[256];
+
+        cll = hdac_command_sendone_internal(sc,
+	 HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_CONN_LIST_LENGTH), cad);
+
+	snprintf(connection_list, 1024, "node %d: %d connections, list: ", nid, cll);
+        for (i=0;i<cll;i++)
+	{
+	  if ((i % 4)==0)
+	    l = hdac_command_sendone_internal(sc, HDA_CMD_GET_CONN_LIST_ENTRY(cad, nid, i), cad);
+
+          payload =  (1 << 13) | i;  /* left, input i*/
+          rc = hdac_command_sendone_internal(sc, HDA_CMD_GET_AMP_GAIN_MUTE(cad, nid, payload), cad);
+ 	    
+	  snprintf(connection_string, 256, "input from node %d (input amp %d), ",(l>>8*(i%4)) & 0xff,rc);
+	  strlcat(connection_list, connection_string, 1024);
+        }
+	
+	payload = (1 << 15) | (1 << 13);  /* left, output */
+	rc = hdac_command_sendone_internal(sc, HDA_CMD_GET_AMP_GAIN_MUTE(cad, nid, payload), cad);
+	
+	snprintf(connection_string,256, "output amp %d\n",rc);
+	strlcat(connection_list, connection_string, 1024);
+	device_printf(sc->dev, connection_list);
+
+}
+
+static void
 sorbo_conf_output(struct hdac_softc *sc, int cad, int nid)
 {
 	uint32_t rc, sf, st;
@@ -830,7 +869,7 @@
 	st = hdac_command_sendone_internal(sc,
 	      HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_SUPP_STREAM_FORMATS), cad);
 
-	device_printf(sc->dev, "Cap %x sf %x st %x\n", rc, sf, st);
+	device_printf(sc->dev, "Output, Cap %x sf %x st %x\n", rc, sf, st);
 
 	rc = hdac_command_sendone_internal(sc,
 		HDA_CMD_GET_CONV_STREAM_CHAN(cad, nid), 0);
@@ -854,12 +893,25 @@
 }
 
 static void
-sorbo_set_amp(struct hdac_softc *sc, int cda, int ni, int amp)
+sorbo_set_amp(struct hdac_softc *sc, int cda, int ni, int left, int right)
 {
-	uint16_t pay = (1 << 15) | (3 << 12) | amp;
+	uint16_t pay = 0;
 
-	hdac_command_sendone_internal(sc,
-		HDA_CMD_SET_AMP_GAIN_MUTE(cda, ni, pay), cda);
+	if (left != right) {
+		pay = (1 << 15) | (1 << 13) | left;
+		hdac_command_sendone_internal(sc,
+			HDA_CMD_SET_AMP_GAIN_MUTE(cda, ni, pay), cda);
+
+		pay = (1 << 15) | (1 << 12) | right;
+
+		hdac_command_sendone_internal(sc,
+			HDA_CMD_SET_AMP_GAIN_MUTE(cda, ni, pay), cda);
+	} else {
+		pay = (1 << 15) | (3 << 12) | left;
+
+		hdac_command_sendone_internal(sc,
+			HDA_CMD_SET_AMP_GAIN_MUTE(cda, ni, pay), cda);
+	}
 }
 
 static void
@@ -871,6 +923,80 @@
 	uint32_t ct = 0;
 	uint32_t capa = 0;
 	uint32_t sense = 0;
+	char connection_type_string[32], device_string[32];
+	int defaultconf;
+
+        defaultconf=HDA_CMD_GET_CONFIGURATION_DEFAULT(cad, nid);
+        switch (defaultconf & HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK)
+	{
+	  case HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_JACK:
+  	    strncpy(connection_type_string,"jack", 32);
+	    break;
+	  case HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE:
+  	    strncpy(connection_type_string,"none", 32);
+	    break;
+	  case HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED:
+  	    strncpy(connection_type_string,"fixed", 32);
+	    break;
+	  case HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_BOTH:
+  	    strncpy(connection_type_string,"jack and fixed", 32);
+	    break;
+	  default:
+  	    strncpy(connection_type_string,"unknown", 32);
+	    break;
+	}
+
+        switch (defaultconf & HDA_CONFIG_DEFAULTCONF_DEVICE_MASK)
+	{
+          case HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_OUT:
+  	    strncpy(device_string,"line out", 32);
+	    break;
+          case HDA_CONFIG_DEFAULTCONF_DEVICE_SPEAKER:
+  	    strncpy(device_string,"speaker", 32);
+	    break;
+          case HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT:
+  	    strncpy(device_string,"headphones out", 32);
+	    break;
+          case HDA_CONFIG_DEFAULTCONF_DEVICE_CD:
+  	    strncpy(device_string,"CD", 32);
+	    break;
+          case HDA_CONFIG_DEFAULTCONF_DEVICE_SPDIF_OUT:
+  	    strncpy(device_string,"SPDIF out", 32);
+	    break;
+          case HDA_CONFIG_DEFAULTCONF_DEVICE_DIGITAL_OTHER_OUT:
+  	    strncpy(device_string,"digital (other) out", 32);
+	    break;
+          case HDA_CONFIG_DEFAULTCONF_DEVICE_MODEM_LINE:
+  	    strncpy(device_string,"modem, line side", 32);
+	    break;
+          case HDA_CONFIG_DEFAULTCONF_DEVICE_MODEM_HANDSET:
+  	    strncpy(device_string,"modem, handset side", 32);
+	    break;
+          case HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN:
+  	    strncpy(device_string,"line in", 32);
+	    break;
+          case HDA_CONFIG_DEFAULTCONF_DEVICE_AUX:
+  	    strncpy(device_string,"AUX", 32);
+	    break;
+          case HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN:
+  	    strncpy(device_string,"Mic in", 32);
+	    break;
+          case HDA_CONFIG_DEFAULTCONF_DEVICE_TELEPHONY:
+  	    strncpy(device_string,"telephony", 32);
+	    break;
+          case HDA_CONFIG_DEFAULTCONF_DEVICE_SPDIF_IN:
+  	    strncpy(device_string,"SPDIF in", 32);
+	    break;
+          case HDA_CONFIG_DEFAULTCONF_DEVICE_DIGITAL_OTHER_IN:
+  	    strncpy(device_string,"digital (other) in", 32);
+	    break;
+          case HDA_CONFIG_DEFAULTCONF_DEVICE_OTHER:
+  	    strncpy(device_string,"other", 32);
+	    break;
+	  default:
+  	    strncpy(device_string,"unknown", 32);
+	    break;
+	}
 
 	rc = hdac_command_sendone_internal(sc,
 	HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_CONN_LIST_LENGTH), cad);
@@ -899,8 +1025,7 @@
 	sense = hdac_command_sendone_internal(sc,
 		HDA_CMD_GET_PIN_SENSE(cad, nid), cad);
 
-	device_printf(sc->dev, "nid %d entries %x list %x cur %d ctr %x cap %x s %x\n",
-		      nid, rc, l, p, ct, capa, sense);
+	device_printf(sc->dev, "node %d: entries %x list %x cur %d ctr %x cap %x s %x, default connectivity: %s, device type: %s\n", nid, rc, l, p, ct, capa, sense,connection_type_string,device_string);
 
 	sorbo_get_amp(sc, cad, nid);
 }
@@ -924,28 +1049,80 @@
 static void
 sorbo_print_widget(struct hdac_softc *sc, int codecid, int nodeid)
 {
-	uint32_t rc;
+	uint32_t rc,p;
 	int type;
+	char type_string[32];
 
 	rc = hdac_command_sendone_internal(sc,
-	      HDA_CMD_GET_PARAMETER(0, nodeid, HDA_PARAM_AUDIO_WIDGET_CAP), 0);
+	      HDA_CMD_GET_PARAMETER(0, nodeid, HDA_PARAM_AUDIO_WIDGET_CAP), codecid);
 
 	type = HDA_PARAM_AUDIO_WIDGET_CAP_TYPE(rc);
 	
-	device_printf(sc->dev, "node %d type %x cap %x\n", nodeid, type, rc);
+	switch (type)
+	{
+	  case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT:
+	    strncpy(type_string,"audio output", 32);
+	    break;
+	  case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT:
+	    strncpy(type_string,"audio input", 32);
+	    break;
+	  case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER:
+	    strncpy(type_string,"audio mixer", 32);
+	    break;
+	  case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR:
+	    strncpy(type_string,"audio selector", 32);
+	    break;
+	  case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX:
+	    strncpy(type_string,"pin", 32);
+	    break;
+	  case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_POWER_WIDGET:
+	    strncpy(type_string,"power widget", 32);
+	    break;
+	  case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_VOLUME_WIDGET:
+	    strncpy(type_string,"volume widget", 32);
+	    break;
+	  case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET:
+	    strncpy(type_string,"beep widget", 32);
+	    break;
+	  case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_VENDOR_WIDGET:
+	    strncpy(type_string,"vendor widget", 32);
+	    break;
+	  default:
+	    strncpy(type_string,"unknown type", 32);
+	    break;
+	}
+        
+
+	device_printf(sc->dev, "node %d: type %x (%s), cap %x,\n", nodeid, type, type_string,rc);
+
+	if (HDA_PARAM_AUDIO_WIDGET_CAP_POWER_CTRL(rc)) {
+		hdac_command_sendone_internal(sc,
+			HDA_CMD_SET_POWER_STATE(codecid, nodeid, HDA_CMD_POWER_STATE_D0), codecid);
+	}
 
-	if (0)
-	sorbo_set_amp(sc, codecid, nodeid, 40);
+	if (0)  
+	sorbo_set_amp(sc, codecid, nodeid, 40,40);
 
 	if (0 && HDA_PARAM_AUDIO_WIDGET_CAP_PROC_WIDGET(rc)) {
 		sorbo_own_proc(sc, codecid, nodeid);
 	}
 
-	if (0 && type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT) {
+	if (type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT) {
 		sorbo_conf_output(sc, codecid, nodeid);
 	}	
-	else if (0 && type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX)
+	else if (type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX)
 		sorbo_conf_pin(sc, codecid, nodeid);
+	else if ((type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR) || (type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER))
+		sorbo_print_conn(sc, codecid, nodeid);
+        if (type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR)
+	{
+          p = hdac_command_sendone_internal(sc,
+              HDA_CMD_GET_CONN_SELECT_CONTROL(codecid, nodeid), codecid); 
+	  device_printf(sc->dev, "current connection: %x\n",p);
+	}
+
+
+
 }
 
 static void
@@ -955,19 +1132,21 @@
 	int startnode;
 	int endnode;
 	int i;
-//	uint32_t pw;
+	uint32_t pw;
 	
 	subnode = hdac_command_sendone_internal(sc,
 	    HDA_CMD_GET_PARAMETER(0 , 1, HDA_PARAM_SUB_NODE_COUNT), 0);
 	startnode = HDA_PARAM_SUB_NODE_COUNT_START(subnode);
 	endnode = startnode + HDA_PARAM_SUB_NODE_COUNT_TOTAL(subnode);
 
-#if 0
+	hdac_command_sendone_internal(sc,
+		HDA_CMD_SET_POWER_STATE(0, 1, HDA_CMD_POWER_STATE_D0), 0);
+
 	pw = hdac_command_sendone_internal(sc,
 		HDA_CMD_GET_POWER_STATE(0, 1), 0);
 
 	device_printf(sc->dev, "PW %x\n", pw);
-#endif
+	device_printf(sc->dev, "start: %d endnode: %d\n", startnode, endnode);
 
 	for (i = startnode; i < endnode; i++) {
 		sorbo_print_widget(sc, 0, i);
@@ -1231,6 +1410,57 @@
 }
 
 static void
+sorbo_set_input_amp(struct hdac_softc *sc, int cda, int ni, int index, int mute, int left, int right)
+{
+	uint16_t payload = 0;
+
+	if (left != right) {
+		payload = (1 << 14) | (1 << 13) | (index << 8) | (mute<<7) | left;
+		hdac_command_sendone_internal(sc,
+			HDA_CMD_SET_AMP_GAIN_MUTE(cda, ni, payload), cda);
+
+		payload = (1 << 14) | (1 << 12) | (index << 8) | (mute<<7) | right;
+		hdac_command_sendone_internal(sc,
+			HDA_CMD_SET_AMP_GAIN_MUTE(cda, ni, payload), cda);
+	} else {
+		payload = (1 << 14) | (3 << 12) | (index << 8) | (mute<<7) | left;
+		hdac_command_sendone_internal(sc,
+			HDA_CMD_SET_AMP_GAIN_MUTE(cda, ni, payload), cda);
+	}
+
+}
+
+
+static void
+sorbo_set_output_amp(struct hdac_softc *sc, int cda, int ni, int mute, int left, int right)
+{
+	uint16_t payload = 0;
+
+	if (left != right) {
+		payload = (1 << 15) | (1 << 13) | (mute<<7) | left;
+		hdac_command_sendone_internal(sc,
+			HDA_CMD_SET_AMP_GAIN_MUTE(cda, ni, payload), cda);
+
+		payload = (1 << 15) | (1 << 12) | (mute<<7) | right;
+		hdac_command_sendone_internal(sc,
+			HDA_CMD_SET_AMP_GAIN_MUTE(cda, ni, payload), cda);
+	} else {
+		payload = (1 << 15) | (3 << 12) | (mute<<7) | left;
+		hdac_command_sendone_internal(sc,
+			HDA_CMD_SET_AMP_GAIN_MUTE(cda, ni, payload), cda);
+	}
+
+}
+
+
+static void
+sorbo_set_conn_select_control(struct hdac_softc *sc, int codecid, int nodeid, uint8_t index)
+{
+  hdac_command_sendone_internal(sc, HDA_CMD_SET_CONNECTION_SELECT_CONTROL(codecid, nodeid, index), codecid); 
+}
+
+
+static void
 hdac_attach2(void *arg)
 {
 	struct hdac_softc *sc;
@@ -1248,15 +1478,71 @@
 
 	hdac_scan_codecs(sc);
 
-	if (0)
+/*	if (0) */
 	sorbo_enum(sc);
 
+
 	sorbo_stop_stream(sc);
 	sorbo_reset_stream(sc);
 	sorbo_stream_setid(sc);
 
-	sorbo_conf_output(sc, 0, 3);
-	sorbo_set_amp(sc, 0, 5, 40);
+	sorbo_conf_output(sc, 0, 2);
+
+	sorbo_set_amp(sc, 0, 2, 40,40);
+	sorbo_set_amp(sc, 0, 3, 40,40);
+	sorbo_set_amp(sc, 0, 4, 40,40);
+	sorbo_set_amp(sc, 0, 5, 40,40);
+	sorbo_set_amp(sc, 0, 6, 40,40);
+	sorbo_set_amp(sc, 0, 7, 40,40);
+	sorbo_set_amp(sc, 0, 8, 40,40);
+	sorbo_set_amp(sc, 0, 9, 40,40);
+	sorbo_set_amp(sc, 0, 10, 40,40);
+	sorbo_set_amp(sc, 0, 11, 40,40);
+	sorbo_set_amp(sc, 0, 12, 40,40);
+	sorbo_set_amp(sc, 0, 13, 40,40);
+	sorbo_set_amp(sc, 0, 14, 40,40);
+	sorbo_set_amp(sc, 0, 15, 40,40);
+	sorbo_set_amp(sc, 0, 16, 40,40);
+	sorbo_set_amp(sc, 0, 17, 40,40);
+	sorbo_set_amp(sc, 0, 18, 40,40);
+	sorbo_set_amp(sc, 0, 19, 40,40);
+	sorbo_set_amp(sc, 0, 20, 40,40);
+	sorbo_set_amp(sc, 0, 21, 40,40);
+	sorbo_set_amp(sc, 0, 22, 40,40);
+	sorbo_set_amp(sc, 0, 23, 40,40);
+	sorbo_set_amp(sc, 0, 24, 40,40);
+	sorbo_set_amp(sc, 0, 25, 40,40);
+	sorbo_set_amp(sc, 0, 26, 40,40);
+	sorbo_set_amp(sc, 0, 27, 40,40);
+
+	
+	sorbo_set_input_amp(sc, 0, 8, 0, 0, 41,41);
+	sorbo_set_output_amp(sc, 0, 8, 0, 42,43);
+	sorbo_set_input_amp(sc, 0, 9, 0, 0, 43,44);
+	sorbo_set_output_amp(sc, 0, 9, 0, 45,45);
+        sorbo_set_conn_select_control(sc, 0, 11, 0);   /* select input from mixer 8 */
+	sorbo_set_input_amp(sc, 0, 10, 0, 0, 45,45);
+	sorbo_set_output_amp(sc, 0, 10, 0, 46,46);
+	sorbo_set_input_amp(sc, 0, 11, 0, 0, 47,47);
+	sorbo_set_output_amp(sc, 0, 11, 0, 48,48);
+
+/*	sorbo_set_amp(sc, 0, 8, 6); */
+
+
+        sorbo_print_widget(sc, 0, 2);  
+        sorbo_print_widget(sc, 0, 8);  
+        sorbo_print_widget(sc, 0, 9);  
+        sorbo_print_widget(sc, 0, 10);  
+        sorbo_print_widget(sc, 0, 11);  
+        sorbo_print_widget(sc, 0, 13);  
+        sorbo_print_widget(sc, 0, 16);  
+        sorbo_print_widget(sc, 0, 17);  
+        sorbo_print_widget(sc, 0, 18);  
+
+        sorbo_print_widget(sc, 0, 20);  
+	
+	
+
 	sorbo_alloc_bdl(sc, 256);
 	sorbo_enable_stream_interrupts(sc);	
 	sc->lame = 1;
@@ -1583,7 +1869,7 @@
 hdacmix_init(struct snd_mixer *m)
 {
         mix_setrecdevs(m, 0);
-        mix_setdevs(m, SOUND_MASK_VOLUME);
+        mix_setdevs(m, SOUND_MASK_VOLUME | SOUND_MASK_PCM);
 	
 	return 0;
 }
@@ -1591,21 +1877,32 @@
 static int
 hdacmix_set(struct snd_mixer *m, unsigned dev, unsigned left, unsigned right)
 {
-	int vol = 0;
-	int max = 63;
+	int left_vol = 0, right_vol = 0;
+	int max = ((1<<6) - 1);
 	struct hdac_softc *sc = mix_getdevinfo(m);
-	vol = (left*63)/100;
-
-	if (left == 100 || vol > max)
-		vol = max;
-
-//	printf("Vol = %d\n", vol);
-	if (sc->lame)
-		sorbo_set_amp(sc, 0, 5, vol);
+		
+	left_vol = (left * max) / 100;
+	if ((left == 100) || (left_vol > max))
+		left_vol = max;
+
+	right_vol = (right * max) / 100;
+	if ((right == 100) || (right_vol > max))
+		right_vol = max;
+
+	if (sc->lame) {
+		switch(dev) {
+		case SOUND_MIXER_VOLUME:
+			sorbo_set_output_amp(sc, 0, 8, 0, left_vol, right_vol);
+			break;
+		case SOUND_MIXER_PCM:
+			sorbo_set_input_amp(sc, 0, 8, 0, 0, left_vol, right_vol);
+			break;
+		}
+	}
 	
-	vol = left | (left << 8);
+	left_vol = left | (right << 8);
 
-	return vol;
+	return left_vol;
 }
 
 static int


More information about the freebsd-multimedia mailing list