[alsa-devel] [Alsa-user] is this card supported by ALSA?

Takashi Iwai tiwai at suse.de
Tue Jul 15 16:19:40 CEST 2008


At Tue, 15 Jul 2008 15:11:09 +0200,
I wrote:
> 
> At Tue, 15 Jul 2008 02:11:41 +0200,
> Rene Herman wrote:
> > 
> > On 15-07-08 01:36, Landis McGauhey wrote:
> > 
> > It seems there's just a bit too much oddness going on. Takashi, you know 
> > more about ac97. Also bringing in alsa-devel...
> > 
> > > # cat /proc/asound/AudioPCI/codec97#0/ac97#0-0=
> > > 
> > > 0-0/0: 0x76058384 F�S
> > 
> > Eep? A 0x83847605 would be a SigmaTel STAC9704. And:
> > 
> > [ ... ]
> > 
> > > # cat /proc/asound/AudioPCI/codec97#0/ac97#0-0+regs=
> > 
> > [ ... ]
> > 
> > > 0:7c = 0000
> > > 0:7e = 8384
> > 
> > does't fit the above ID. Do we just have a crummy codec that needs delay 
> > between acceses somewhere or something?
> 
> I guess it's rather the controller code.  Will check this later.

The below is a patch to improve the codec access routines in a bit
more robust way (and clean-ups, too).  Give it a try.


Takashi

---
diff --git a/sound/pci/ens1370.c b/sound/pci/ens1370.c
index fbf1124..5c962b6 100644
--- a/sound/pci/ens1370.c
+++ b/sound/pci/ens1370.c
@@ -461,8 +461,6 @@ MODULE_DEVICE_TABLE(pci, snd_audiopci_ids);
  *  constants
  */
 
-#define POLL_COUNT	0xa000
-
 #ifdef CHIP1370
 static unsigned int snd_es1370_fixed_rates[] =
 	{5512, 11025, 22050, 44100};
@@ -514,14 +512,16 @@ static const unsigned int snd_ensoniq_sample_shift[] =
 
 static unsigned int snd_es1371_wait_src_ready(struct ensoniq * ensoniq)
 {
-	unsigned int t, r = 0;
+	unsigned int r = 0;
+	unsigned long end_time;
 
-	for (t = 0; t < POLL_COUNT; t++) {
+	end_time = jiffies + msecs_to_jiffies(100);
+	do {
 		r = inl(ES_REG(ensoniq, 1371_SMPRATE));
 		if ((r & ES_1371_SRC_RAM_BUSY) == 0)
 			return r;
-		cond_resched();
-	}
+		schedule_timeout_uninterruptible(1);
+	} while (time_after_eq(end_time, jiffies));
 	snd_printk(KERN_ERR "wait source ready timeout 0x%lx [0x%x]\n",
 		   ES_REG(ensoniq, 1371_SMPRATE), r);
 	return 0;
@@ -529,7 +529,7 @@ static unsigned int snd_es1371_wait_src_ready(struct ensoniq * ensoniq)
 
 static unsigned int snd_es1371_src_read(struct ensoniq * ensoniq, unsigned short reg)
 {
-	unsigned int temp, i, orig, r;
+	unsigned int temp, orig, r;
 
 	/* wait for ready */
 	temp = orig = snd_es1371_wait_src_ready(ensoniq);
@@ -545,11 +545,13 @@ static unsigned int snd_es1371_src_read(struct ensoniq * ensoniq, unsigned short
 	
 	if ((temp & 0x00870000) != 0x00010000) {
 		/* wait for the right state */
-		for (i = 0; i < POLL_COUNT; i++) {
+		unsigned long end_time = jiffies + msecs_to_jiffies(100);
+		do {
 			temp = inl(ES_REG(ensoniq, 1371_SMPRATE));
 			if ((temp & 0x00870000) == 0x00010000)
 				break;
-		}
+			schedule_timeout_uninterruptible(1);
+		} while (time_after_eq(end_time, jiffies));
 	}
 
 	/* hide the state bits */	
@@ -602,104 +604,90 @@ static void snd_es1370_codec_write(struct snd_ak4531 *ak4531,
 
 #ifdef CHIP1371
 
+static int _es1371_wait_wip(struct ensoniq *ensoniq)
+{
+	unsigned long end_time;
+
+	end_time = jiffies + msecs_to_jiffies(100);
+	do {
+		if (!(inl(ES_REG(ensoniq, 1371_CODEC)) & ES_1371_CODEC_WIP))
+			return 0;
+	} while (time_after_eq(end_time, jiffies));
+	snd_printk(KERN_ERR "codec wait timeout, status = 0x%x\n",
+		   inl(ES_REG(ensoniq, 1371_CODEC)));
+	return -EINVAL;
+}
+
+static void _es1371_codec_write(struct ensoniq *ensoniq,
+				unsigned int val)
+{
+	unsigned int x;
+	unsigned long end_time;
+
+	_es1371_wait_wip(ensoniq);
+	/* save the current state for latter */
+	x = snd_es1371_wait_src_ready(ensoniq);
+	outl((x & (ES_1371_SRC_DISABLE | ES_1371_DIS_P1 |
+		   ES_1371_DIS_P2 | ES_1371_DIS_R1)) | 0x00010000,
+	     ES_REG(ensoniq, 1371_SMPRATE));
+	/* wait for not busy (state 0) first to avoid
+	   transition states */
+	end_time = jiffies + msecs_to_jiffies(100);
+	do {
+		if ((inl(ES_REG(ensoniq, 1371_SMPRATE)) & 0x00870000) ==
+		    0x00000000)
+			break;
+	} while (time_after_eq(end_time, jiffies));
+	/* wait for a SAFE time to write addr/data and then do it, dammit */
+	end_time = jiffies + msecs_to_jiffies(100);
+	do {
+		if ((inl(ES_REG(ensoniq, 1371_SMPRATE)) & 0x00870000) ==
+		    0x00010000)
+			break;
+	} while (time_after_eq(end_time, jiffies));
+	outl(val, ES_REG(ensoniq, 1371_CODEC));
+	/* restore SRC reg */
+	snd_es1371_wait_src_ready(ensoniq);
+	outl(x, ES_REG(ensoniq, 1371_SMPRATE));
+}
+
 static void snd_es1371_codec_write(struct snd_ac97 *ac97,
 				   unsigned short reg, unsigned short val)
 {
 	struct ensoniq *ensoniq = ac97->private_data;
-	unsigned int t, x;
 
 	mutex_lock(&ensoniq->src_mutex);
-	for (t = 0; t < POLL_COUNT; t++) {
-		if (!(inl(ES_REG(ensoniq, 1371_CODEC)) & ES_1371_CODEC_WIP)) {
-			/* save the current state for latter */
-			x = snd_es1371_wait_src_ready(ensoniq);
-			outl((x & (ES_1371_SRC_DISABLE | ES_1371_DIS_P1 |
-			           ES_1371_DIS_P2 | ES_1371_DIS_R1)) | 0x00010000,
-			     ES_REG(ensoniq, 1371_SMPRATE));
-			/* wait for not busy (state 0) first to avoid
-			   transition states */
-			for (t = 0; t < POLL_COUNT; t++) {
-				if ((inl(ES_REG(ensoniq, 1371_SMPRATE)) & 0x00870000) ==
-				    0x00000000)
-					break;
-			}
-			/* wait for a SAFE time to write addr/data and then do it, dammit */
-			for (t = 0; t < POLL_COUNT; t++) {
-				if ((inl(ES_REG(ensoniq, 1371_SMPRATE)) & 0x00870000) ==
-				    0x00010000)
-					break;
-			}
-			outl(ES_1371_CODEC_WRITE(reg, val), ES_REG(ensoniq, 1371_CODEC));
-			/* restore SRC reg */
-			snd_es1371_wait_src_ready(ensoniq);
-			outl(x, ES_REG(ensoniq, 1371_SMPRATE));
-			mutex_unlock(&ensoniq->src_mutex);
-			return;
-		}
-	}
+	_es1371_codec_write(ensoniq, ES_1371_CODEC_WRITE(reg, val));
 	mutex_unlock(&ensoniq->src_mutex);
-	snd_printk(KERN_ERR "codec write timeout at 0x%lx [0x%x]\n",
-		   ES_REG(ensoniq, 1371_CODEC), inl(ES_REG(ensoniq, 1371_CODEC)));
 }
 
 static unsigned short snd_es1371_codec_read(struct snd_ac97 *ac97,
 					    unsigned short reg)
 {
 	struct ensoniq *ensoniq = ac97->private_data;
-	unsigned int t, x, fail = 0;
+	unsigned int fail;
+	unsigned long end_time;
 
-      __again:
 	mutex_lock(&ensoniq->src_mutex);
-	for (t = 0; t < POLL_COUNT; t++) {
-		if (!(inl(ES_REG(ensoniq, 1371_CODEC)) & ES_1371_CODEC_WIP)) {
-			/* save the current state for latter */
-			x = snd_es1371_wait_src_ready(ensoniq);
-			outl((x & (ES_1371_SRC_DISABLE | ES_1371_DIS_P1 |
-			           ES_1371_DIS_P2 | ES_1371_DIS_R1)) | 0x00010000,
-			     ES_REG(ensoniq, 1371_SMPRATE));
-			/* wait for not busy (state 0) first to avoid
-			   transition states */
-			for (t = 0; t < POLL_COUNT; t++) {
-				if ((inl(ES_REG(ensoniq, 1371_SMPRATE)) & 0x00870000) ==
-				    0x00000000)
-					break;
+	for (fail = 0; fail < 10; fail++) {
+		_es1371_codec_write(ensoniq, ES_1371_CODEC_READS(reg));
+		/* wait for WIP again */
+		_es1371_wait_wip(ensoniq);
+		/* now wait for the stinkin' data (RDY) */
+		end_time = jiffies + msecs_to_jiffies(100);
+		do {
+			unsigned int x = inl(ES_REG(ensoniq, 1371_CODEC));
+			if (x & ES_1371_CODEC_RDY) {
+				mutex_unlock(&ensoniq->src_mutex);
+				return ES_1371_CODEC_READ(x);
 			}
-			/* wait for a SAFE time to write addr/data and then do it, dammit */
-			for (t = 0; t < POLL_COUNT; t++) {
-				if ((inl(ES_REG(ensoniq, 1371_SMPRATE)) & 0x00870000) ==
-				    0x00010000)
-					break;
-			}
-			outl(ES_1371_CODEC_READS(reg), ES_REG(ensoniq, 1371_CODEC));
-			/* restore SRC reg */
-			snd_es1371_wait_src_ready(ensoniq);
-			outl(x, ES_REG(ensoniq, 1371_SMPRATE));
-			/* wait for WIP again */
-			for (t = 0; t < POLL_COUNT; t++) {
-				if (!(inl(ES_REG(ensoniq, 1371_CODEC)) & ES_1371_CODEC_WIP))
-					break;		
-			}
-			/* now wait for the stinkin' data (RDY) */
-			for (t = 0; t < POLL_COUNT; t++) {
-				if ((x = inl(ES_REG(ensoniq, 1371_CODEC))) & ES_1371_CODEC_RDY) {
-					mutex_unlock(&ensoniq->src_mutex);
-					return ES_1371_CODEC_READ(x);
-				}
-			}
-			mutex_unlock(&ensoniq->src_mutex);
-			if (++fail > 10) {
-				snd_printk(KERN_ERR "codec read timeout (final) "
-					   "at 0x%lx, reg = 0x%x [0x%x]\n",
-					   ES_REG(ensoniq, 1371_CODEC), reg,
-					   inl(ES_REG(ensoniq, 1371_CODEC)));
-				return 0;
-			}
-			goto __again;
-		}
+		} while (time_after_eq(end_time, jiffies));
 	}
+	snd_printk(KERN_ERR "codec read timeout (final) "
+		   "at 0x%lx, reg = 0x%x [0x%x]\n",
+		   ES_REG(ensoniq, 1371_CODEC), reg,
+		   inl(ES_REG(ensoniq, 1371_CODEC)));
 	mutex_unlock(&ensoniq->src_mutex);
-	snd_printk(KERN_ERR "es1371: codec read timeout at 0x%lx [0x%x]\n",
-		   ES_REG(ensoniq, 1371_CODEC), inl(ES_REG(ensoniq, 1371_CODEC)));
 	return 0;
 }
 


More information about the Alsa-devel mailing list