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-mobile
mailing list