HDA sound driver hack for Acer Aspire 1641

Maxime Guillaud <[email protected]>
Newsgroups gmane.os.freebsd.devel.mobile,gmane.os.freebsd.devel.multimedia
Message-ID <[email protected]>
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

_______________________________________________
[email protected] mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-mobile
To unsubscribe, send any mail to "[email protected]"
diff-vs-andrea20060606 (text/plain, 17.8 KB)
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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.