Re: HDA sound driver mod for sigmatel 92xx

Wesley Morgan <[email protected]>
Newsgroups gmane.os.freebsd.devel.mobile,gmane.os.freebsd.devel.multimedia
Message-ID <[email protected]>
On Wed, 12 Jul 2006, Eric Anderson wrote:

> On 07/09/06 09:11, Wesley Morgan wrote:
>> 
>> 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.
>
>
> I couldn't get this patch to work - all hunks fail.  What am I doing wrong?

Make sure your mailer didn't wrap long lines? It applies cleanly for me. 
I've attached a newer diff that makes the mixer work properly as well, but 
it's hard-coded to the correct widget for me so it might not work for 
everyone.


[morganw@catalyst:~$]: tar zxf hdac.tgz
[morganw@catalyst:~$]: cd hdac
[morganw@catalyst:~/hdac$]: patch < ../sigma.diff
Hmm...  Looks like a unified diff to me...
The text leading up to this was:
--------------------------
|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
--------------------------
Patching file hdac.c using Plan A...
Hunk #1 succeeded at 247.
Hunk #2 succeeded at 261.
Hunk #3 succeeded at 787.
Hunk #4 succeeded at 821.
Hunk #5 succeeded at 894.
Hunk #6 succeeded at 945.
Hunk #7 succeeded at 974.
Hunk #8 succeeded at 1270.
Hmm...  Ignoring the trailing garbage.
done




-- 
This .signature sanitized for your protection

_______________________________________________
[email protected] mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-mobile
To unsubscribe, send any mail to "[email protected]"
sigma.diff (text/plain, 5.9 KB)
diff -urb hdac/hdac.c hdac-sigma/hdac.c
--- hdac/hdac.c	Mon Jun  5 15:15:12 2006
+++ hdac-sigma/hdac.c	Wed Jul 12 21:02:32 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--;
 	}
@@ -273,6 +274,10 @@
 		device_printf(sc->dev, "Device stuck in reset\n");
 		return(ENXIO);
 	}
+/*
+	gctl = HDAC_READ_4(&sc->mem, HDAC_GCTL);
+	HDAC_WRITE_4(&sc->mem, HDAC_GCTL, gctl | HDAC_GCTL_UNSOL);
+*/
 
 	/*
 	 * Wait for codecs to finish their own reset sequence. The delay here
@@ -786,6 +791,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 +825,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)
@@ -854,12 +867,26 @@
 }
 
 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;
+	
+	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
@@ -885,8 +912,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 +963,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 (0 && type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX)
+	else if (type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR) {
+		sorbo_set_amp(sc, codecid, nodeid, 75, 75);
+	}	
+	else if (type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) {
 		sorbo_conf_pin(sc, codecid, nodeid);
+		sorbo_set_amp(sc, codecid, nodeid, 75, 75);
+	}
 }
 
 static void
@@ -955,19 +992,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 +1288,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;
@@ -1591,21 +1628,26 @@
 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<<5) - 1);
 	struct hdac_softc *sc = mix_getdevinfo(m);
-	vol = (left*63)/100;
 
-	if (left == 100 || vol > max)
-		vol = max;
+	left_vol = (left * max) / 100;
+	if ((left == 100) || (left_vol > max))
+		left_vol = max;
 
-//	printf("Vol = %d\n", vol);
-	if (sc->lame)
-		sorbo_set_amp(sc, 0, 5, vol);
+	right_vol = (right * max) / 100;
+	if ((right == 100) || (right_vol > max))
+		right_vol = max;
+
+	if (sc->lame) {
+/*		device_printf(sc->dev, "setting volume to %x:%x\n", left_vol, right_vol); */
+		sorbo_set_amp(sc, 0, 11, left_vol, right_vol);
+	}
 	
-	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.