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 bitmore robust way (and clean-ups, too). Give it a try. Takashi ---diff --git a/sound/pci/ens1370.c b/sound/pci/ens1370.cindex 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 challengeBuild the coolest Linux based applications with Moblin SDK & win great prizesGrand prize is a trip for two to an Open Source event anywhere in the worldhttp://moblin-contest.org/redirect.php?banner_id=100&url=/_______________________________________________Alsa-user mailing listAlsa-user@xxxxxxxxxxxxxxxxxxxxxxxxxx://lists.sourceforge.net/lists/listinfo/alsa-user