Subject: AD1845 wss audio
To: None <tech-kern@netbsd.org, port-alpha@netbsd.org>
From: ITOH Yasufumi <itohy@netbsd.org>
List: tech-kern
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";