kern/73498: No sound from CT4730 (EV1938) based soundcard
Ariff Abdullah
skywizard at MyBSD.org.my
Wed Nov 3 13:10:41 PST 2004
>Number: 73498
>Category: kern
>Synopsis: No sound from CT4730 (EV1938) based soundcard
>Confidential: no
>Severity: serious
>Priority: high
>Responsible: freebsd-bugs
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: sw-bug
>Submitter-Id: current-users
>Arrival-Date: Wed Nov 03 21:10:28 GMT 2004
>Closed-Date:
>Last-Modified:
>Originator: Ariff Abdullah
>Release: FreeBSD 5.3-STABLE
>Organization:
MyBSD
>Environment:
System: FreeBSD 5.3-STABLE/i386
>Description:
Broken register programming on CT4730/EV1938 soundcard causing
no sound at all, although detected. Possible race condition
occur during power-up, causing it failed totally.
>How-To-Repeat:
Get CT4730/EV1938 (or perhaps any EV1938 based chipset), boot,
play anything.
>Fix:
This patch not just tempering es137x.c, but also ac97.c.
It's really need proper review and testing before can be considered
*the proper way* to initialize mixer for any AC97 soundcards.
--- sys/dev/sound/pci/es137x.c.orig Tue Oct 19 20:12:14 2004
+++ sys/dev/sound/pci/es137x.c Wed Oct 20 01:32:42 2004
@@ -503,6 +503,8 @@
es->num = 0;
es->ctrl = 0;
es->sctrl = 0;
+ if (devid == CT4730_PCI_ID)
+ es->ctrl |= (1 << 16);
/* initialize the chips */
if ((devid == ES1371_PCI_ID && revid == ES1371REV_ES1373_8) ||
(devid == ES1371_PCI_ID && revid == ES1371REV_CT5880_A) ||
@@ -557,7 +559,7 @@
es1371_wrcd(kobj_t obj, void *s, int addr, u_int32_t data)
{
int sl;
- unsigned t, x;
+ unsigned t, x, orig;
struct es_info *es = (struct es_info*)s;
if (debug > 0) printf("wrcodec addr 0x%x data 0x%x\n", addr, data);
@@ -567,14 +569,18 @@
break;
sl = spltty();
/* save the current state for later */
- x = bus_space_read_4(es->st, es->sh, ES1371_REG_SMPRATE);
+ x = orig = bus_space_read_4(es->st, es->sh, ES1371_REG_SMPRATE);
/* enable SRC state data in SRC mux */
bus_space_write_4(es->st, es->sh, ES1371_REG_SMPRATE,
- (es1371_wait_src_ready(s) &
- (ES1371_DIS_SRC | ES1371_DIS_P1 | ES1371_DIS_P2 | ES1371_DIS_R1)));
+ (x &
+ (ES1371_DIS_SRC | ES1371_DIS_P1 | ES1371_DIS_P2 | ES1371_DIS_R1)) | 0x00010000);
+ /* busy wait */
+ for (t = 0; t < 0x1000; t++)
+ if ((bus_space_read_4(es->st, es->sh, ES1371_REG_SMPRATE) & 0x00870000) == 0x00000000)
+ break;
/* wait for a SAFE time to write addr/data and then do it, dammit */
for (t = 0; t < 0x1000; t++)
- if ((bus_space_read_4(es->st, es->sh, ES1371_REG_SMPRATE) & 0x00070000) == 0x00010000)
+ if ((bus_space_read_4(es->st, es->sh, ES1371_REG_SMPRATE) & 0x00870000) == 0x00010000)
break;
if (debug > 2)
@@ -591,7 +597,7 @@
if (debug > 2)
printf("two b_s_w: 0x%lx 0x%x 0x%x\n",
rman_get_start(es->reg), ES1371_REG_SMPRATE, x);
- bus_space_write_4(es->st, es->sh, ES1371_REG_SMPRATE, x);
+ bus_space_write_4(es->st, es->sh, ES1371_REG_SMPRATE, orig);
splx(sl);
return 0;
@@ -601,7 +607,7 @@
es1371_rdcd(kobj_t obj, void *s, int addr)
{
int sl;
- unsigned t, x = 0;
+ unsigned t, x = 0, orig;
struct es_info *es = (struct es_info *)s;
if (debug > 0) printf("rdcodec addr 0x%x ... ", addr);
@@ -614,22 +620,27 @@
sl = spltty();
/* save the current state for later */
- x = bus_space_read_4(es->st, es->sh, ES1371_REG_SMPRATE);
+ x = orig = bus_space_read_4(es->st, es->sh, ES1371_REG_SMPRATE);
/* enable SRC state data in SRC mux */
bus_space_write_4(es->st, es->sh, ES1371_REG_SMPRATE,
- (es1371_wait_src_ready(s) &
- (ES1371_DIS_SRC | ES1371_DIS_P1 | ES1371_DIS_P2 | ES1371_DIS_R1)));
+ (x &
+ (ES1371_DIS_SRC | ES1371_DIS_P1 | ES1371_DIS_P2 | ES1371_DIS_R1)) | 0x00010000);
+ /* busy wait */
+ for (t = 0; t < 0x1000; t++)
+ if ((x = bus_space_read_4(es->st, es->sh, ES1371_REG_SMPRATE) & 0x00870000) == 0x00000000)
+ break;
/* wait for a SAFE time to write addr/data and then do it, dammit */
- for (t = 0; t < 0x5000; t++)
- if ((x = bus_space_read_4(es->st, es->sh, ES1371_REG_SMPRATE) & 0x00070000) == 0x00010000)
+ for (t = 0; t < 0x1000; t++)
+ if ((x = bus_space_read_4(es->st, es->sh, ES1371_REG_SMPRATE) & 0x00870000) == 0x00010000)
break;
+
if (debug > 0) printf("loop 2 t 0x%x x 0x%x ", t, x);
bus_space_write_4(es->st, es->sh, ES1371_REG_CODEC,
((addr << CODEC_POADD_SHIFT) & CODEC_POADD_MASK) | CODEC_PORD);
/* restore SRC reg */
es1371_wait_src_ready(s);
- bus_space_write_4(es->st, es->sh, ES1371_REG_SMPRATE, x);
+ bus_space_write_4(es->st, es->sh, ES1371_REG_SMPRATE, orig);
splx(sl);
--- sys/dev/sound/pcm/ac97.c.orig Tue Oct 19 23:36:34 2004
+++ sys/dev/sound/pcm/ac97.c Thu Oct 21 01:41:46 2004
@@ -610,13 +610,21 @@
for (i = 0; i < 32; i++) {
k = codec->noext? codec->mix[i].enable : 1;
if (k && (codec->mix[i].reg > 0)) {
- old = ac97_rdcd(codec, codec->mix[i].reg);
- ac97_wrcd(codec, codec->mix[i].reg, 0x3f);
- j = ac97_rdcd(codec, codec->mix[i].reg);
+ j = old = ac97_rdcd(codec, codec->mix[i].reg);
+ if (!(j & 0x8000)) {
+ ac97_wrcd(codec, codec->mix[i].reg, j | 0x8000);
+ j = ac97_rdcd(codec, codec->mix[i].reg);
+ }
+ if ((j & 0x8000)) {
+ codec->mix[i].enable = 1;
+ codec->mix[i].bits = 6;
+ j = 0x8000 | 0x0020;
+ ac97_wrcd(codec, codec->mix[i].reg, j);
+ if (j != ac97_rdcd(codec, codec->mix[i].reg))
+ codec->mix[i].bits = 5;
+ } else
+ codec->mix[i].enable = 0;
ac97_wrcd(codec, codec->mix[i].reg, old);
- codec->mix[i].enable = (j != 0 && j != old)? 1 : 0;
- for (k = 1; j & (1 << k); k++);
- codec->mix[i].bits = j? k - codec->mix[i].ofs : 0;
}
/* printf("mixch %d, en=%d, b=%d\n", i, codec->mix[i].enable, codec->mix[i].bits); */
}
@@ -644,8 +652,16 @@
}
}
- if ((ac97_rdcd(codec, AC97_REG_POWER) & 2) == 0)
- device_printf(codec->dev, "ac97 codec reports dac not ready\n");
+ i = 0;
+ while ((ac97_rdcd(codec, AC97_REG_POWER) & 2) == 0) {
+ if (++i == 100) {
+ device_printf(codec->dev, "ac97 codec reports dac not ready\n");
+ break;
+ }
+ DELAY(1000);
+ }
+ if (bootverbose)
+ device_printf(codec->dev, "ac97 codec dac ready count: %d\n", i);
snd_mtxunlock(codec->lock);
return 0;
}
>Release-Note:
>Audit-Trail:
>Unformatted:
More information about the freebsd-bugs
mailing list