HDA sound driver mod for sigmatel 92xx

Wesley Morgan morganw at chemikals.org
Sun Jul 9 14:12:00 UTC 2006


With a little help from the netbsd azalia driver (a wonderful piece of 
work, by the way) and the hda specs, I've been able to get Andrea's hdac 
code to work with my laptop. I believe the problem was that the codec and 
dac started out in some kind of low-power mode and needed to be woken up 
before they would work.

Hopefully someone is still working on a proper driver, but for now, I can 
watch movies again!

A diff against Andrea's work is attached.

-- 
This .signature sanitized for your protection
-------------- next part --------------
diff -urb hdac/hdac.c hdac-sigma/hdac.c
--- hdac/hdac.c	Mon Jun  5 15:15:12 2006
+++ hdac-sigma/hdac.c	Sun Jul  9 10:10:37 2006
@@ -247,7 +247,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 +261,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--;
 	}
@@ -786,6 +787,10 @@
 	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);
 }
 
@@ -816,6 +821,10 @@
 	uint32_t rc, sf, st;
 	uint32_t fmt = sorbo_get_fmt(sc);
 
+
+	rc = HDA_CMD_GET_CONFIGURATION_DEFAULT(cad, nid);
+	device_printf(sc->dev, "Config %x\n", rc);
+
 	rc = hdac_command_sendone_internal(sc,
 		HDA_CMD_SET_CONV_STREAM_CHAN(cad, nid, 1 << 4), 0);
 	if (rc)
@@ -885,8 +894,10 @@
 
 	ct = hdac_command_sendone_internal(sc,
 		HDA_CMD_GET_PIN_WIDGET_CTRL(cad, nid), cad);
-	ct |= (1 << 6) | (1 << 7);
-	ct = hdac_command_sendone_internal(sc,
+
+	ct |= (1 << 6) | (1 << 2) | (1);
+
+	hdac_command_sendone_internal(sc,
 		HDA_CMD_SET_PIN_WIDGET_CTRL(cad, nid, ct), cad);
 
 	capa = hdac_command_sendone_internal(sc,
@@ -934,18 +945,26 @@
 	
 	device_printf(sc->dev, "node %d type %x cap %x\n", nodeid, type, rc);
 
-	if (0)
-	sorbo_set_amp(sc, codecid, nodeid, 40);
+	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 && 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);
+		device_printf(sc->dev, "sorbo_conf_output: codec: %d node: %d\n", codecid, nodeid);
+	}	
+	else if (type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR) {
+		sorbo_set_amp(sc, codecid, nodeid, 40);
 	}	
-	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);
+		sorbo_set_amp(sc, codecid, nodeid, 40);
+	}
 }
 
 static void
@@ -955,19 +974,22 @@
 	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);
@@ -1248,15 +1270,12 @@
 
 	hdac_scan_codecs(sc);
 
-	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_alloc_bdl(sc, 256);
 	sorbo_enable_stream_interrupts(sc);	
 	sc->lame = 1;
Only in hdac-sigma: hdac.c~


More information about the freebsd-multimedia mailing list