[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