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