Subject: AD1845 wss audio
To: None <tech-kern@netbsd.org, port-alpha@netbsd.org>
From: ITOH Yasufumi <itohy@netbsd.org>
List: port-alpha
Date: 08/09/2001 10:48:14
Hello,

I had AD1845 wss audio device on AlphaStation 255 working.
Is it OK to commit this change?

I've find some differences between the AD1845 doc
<http://products.analog.com/products/info.asp?product=AD1845>
and the behavior of the actual device.

  - [mixer] If the line input is used, the DAC output can't be heard.
	If the device is treated as AD1848 about mixer, it works
	as expected.

  - [big endian] The doc says that AD1845 has slinear_be (big endian)
	wave format, but the mode behaves like as sliner_le (little endian).

How do think of them?
Does your AD1845 work with options BROKEN_AD1845=0 (see patch below)?

I thought the device was damaged, but I've got another AS255 and
it does the same behavior.  Further, OSF/1 (Digital UNIX 3.2D) has
no problem to drive it.
I'm not sure which of the chip, the usage in AS255, or the driver :)
has the problems.

By the way, AlphaStation 500 has CS4231A (marked as CS4231 but detected
as CS4231A) as the audio device and doesn't have such problems.

Thanks,
-- 
ITOH, Yasufumi
I will not respond 'til Aug. 20.


diff -uF^[a-zA-Z_][a-z 	A-Z0-9_]*([^;]*$ ic/ad1848.c.orig ic/ad1848.c
--- ic/ad1848.c.orig	Mon Jan 22 15:44:59 2001
+++ ic/ad1848.c	Thu Aug  9 08:36:11 2001
@@ -126,6 +126,15 @@
 #include <dev/isa/cs4231var.h>
 #endif
 
+/*
+ * AD1845 on AlphaStation 255 doesn't match the AD1845 doc
+ * and defining BROKEN_AD1845 to 1 works around the problems.
+ * options BROKEN_AD1845=0  should work if you have ``correct'' one.
+ */
+#ifndef BROKEN_AD1845
+#define BROKEN_AD1845	1	/* weird mixer, can't play slinear_be */
+#endif
+
 #ifdef AUDIO_DEBUG
 #define DPRINTF(x)	if (ad1848debug) printf x
 int	ad1848debug = 0;
@@ -415,7 +424,11 @@ ad1848_attach(sc)
 	ad1848_set_channel_gain(sc, AD1848_MONITOR_CHANNEL, &vol_0);
 	ad1848_set_channel_gain(sc, AD1848_AUX1_CHANNEL, &vol_mid);	/* CD volume */
 	sc->mute[AD1848_MONITOR_CHANNEL] = MUTE_ALL;
-	if (sc->mode >= 2) {
+	if (sc->mode >= 2
+#if BROKEN_AD1845
+	    && sc->is_ad1845 == 0
+#endif
+		) {
 		ad1848_set_channel_gain(sc, AD1848_AUX2_CHANNEL, &vol_mid); /* CD volume */
 		ad1848_set_channel_gain(sc, AD1848_LINE_CHANNEL, &vol_mid);
 		ad1848_set_channel_gain(sc, AD1848_MONO_CHANNEL, &vol_0);
@@ -845,7 +858,11 @@ ad1848_query_encoding(addr, fp)
 		strcpy(fp->name, AudioEslinear_be);
 		fp->encoding = AUDIO_ENCODING_SLINEAR_BE;
 		fp->precision = 16;
-		fp->flags = sc->mode == 1 ? AUDIO_ENCODINGFLAG_EMULATED : 0;
+		fp->flags = sc->mode == 1
+#if BROKEN_AD1845
+		    || sc->is_ad1845
+#endif
+			? AUDIO_ENCODINGFLAG_EMULATED : 0;
 		break;
 
 		/* emulate some modes */
@@ -869,7 +886,7 @@ ad1848_query_encoding(addr, fp)
 		break;
 
 	case 8: /* only on CS4231 */
-		if (sc->mode == 1)
+		if (sc->mode == 1 || sc->is_ad1845)
 			return EINVAL;
 		strcpy(fp->name, AudioEadpcm);
 		fp->encoding = AUDIO_ENCODING_ADPCM;
@@ -907,7 +924,11 @@ ad1848_set_params(addr, setmode, usemode
 		}
 		break;
 	case AUDIO_ENCODING_SLINEAR_BE:
-		if (p->precision == 16 && sc->mode == 1) {
+		if (p->precision == 16 && (sc->mode == 1
+#if BROKEN_AD1845
+		    || sc->is_ad1845
+#endif
+			)) {
 			enc = AUDIO_ENCODING_SLINEAR_LE;
 			pswcode = rswcode = swap_bytes;
 		}
@@ -920,7 +941,11 @@ ad1848_set_params(addr, setmode, usemode
 		break;
 	case AUDIO_ENCODING_ULINEAR_BE:
 		if (p->precision == 16) {
-			if (sc->mode == 1) {
+			if (sc->mode == 1
+#if BROKEN_AD1845
+			    || sc->is_ad1845
+#endif
+				) {
 				enc = AUDIO_ENCODING_SLINEAR_LE;
 				pswcode = swap_bytes_change_sign16_le;
 				rswcode = change_sign16_swap_bytes_le;
diff -u ic/ad1848var.h.orig ic/ad1848var.h
--- ic/ad1848var.h.orig	Tue Jun 27 12:57:59 2000
+++ ic/ad1848var.h	Wed Aug  8 22:18:19 2001
@@ -101,6 +101,7 @@
 
 	char	*chip_name;
 	int	mode;
+	int	is_ad1845;
 
 	u_int	precision;		/* 8/16 bits */
 	int	channels;
diff -uF^[a-zA-Z_][a-z 	A-Z0-9_]*([^;]*$ isa/ad1848_isa.c.orig isa/ad1848_isa.c
--- isa/ad1848_isa.c.orig	Thu Dec 21 14:31:39 2000
+++ isa/ad1848_isa.c	Thu Aug  9 08:38:50 2001
@@ -191,7 +191,7 @@ ad1848_isa_probe(isc)
 {
 	struct ad1848_softc *sc = &isc->sc_ad1848;
 	u_char tmp, tmp1 = 0xff, tmp2 = 0xff;
-	int i;
+	int i, t;
 
 	sc->sc_readreg = ad1848_isa_read;
 	sc->sc_writereg = ad1848_isa_write;
@@ -249,6 +249,14 @@ ad1848_isa_probe(isc)
 	tmp = ad_read(sc, SP_MISC_INFO);
 	ad_write(sc, SP_MISC_INFO, (~tmp) & 0x0f);
 
+	/* Here, AD1845 may sometimes be busy.  Wait til it becomes ready. */
+	for (t = 0; t < 100000 && ADREAD(sc, AD1848_IADDR) & SP_IN_INIT; t++)
+		;
+#ifdef AUDIO_DEBUG
+	if (t)
+		DPRINTF(("ad1848_isa_probe: t %d\n", t));
+#endif
+
 	if ((tmp & 0x0f) != ((tmp1 = ad_read(sc, SP_MISC_INFO)) & 0x0f)) {
 		DPRINTF(("ad_detect_D (%x)\n", tmp1));
 		goto bad;
@@ -344,7 +352,15 @@ ad1848_isa_probe(isc)
 					break;
 				case 0x80:
 					/*  XXX I25 no good, AD1845 same as CS4231 */
-					sc->chip_name = "CS4231 or AD1845";
+					/*
+					 * XXX
+					 * This test is correct only after reset
+					 */
+					if (ad_read(sc, 17) & 0xf0) {
+						sc->chip_name = "AD1845";
+						sc->is_ad1845 = 1;
+					} else
+						sc->chip_name = "CS4231";
 					break;
 				case 0x82:
 					sc->chip_name = "CS4232";