Skip site navigation (1)Skip section navigation (2)
Date:      Thu,  4 Nov 2004 05:04:40 +0800 (MYT)
From:      Ariff Abdullah <skywizard@MyBSD.org.my>
To:        FreeBSD-gnats-submit@FreeBSD.org
Subject:   kern/73498: No sound from CT4730 (EV1938) based soundcard
Message-ID:  <20041103210440.13CEB6CC24@tomoyo.MyBSD.org.my>
Resent-Message-ID: <200411032110.iA3LAWHm052958@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help

>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:



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20041103210440.13CEB6CC24>