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;
 }
 

-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
Alsa-user mailing list
Alsa-user@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/alsa-user

Reply via email to