mirror of
https://github.com/torvalds/linux.git
synced 2024-11-11 06:31:49 +00:00
ALSA: ens1371: fix Creative Ectiva support
To make the EV1938 chip work, add a magic bit and an extra delay. Signed-off-by: Clemens Ladisch <clemens@ladisch.de> Tested-by: Tino Schmidt <mailtinoshomepage@gmx.net> Cc: all 2.6.x <stable@kernel.org> Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
parent
6ff674615c
commit
6ebb8a4a43
@ -229,6 +229,7 @@ MODULE_PARM_DESC(lineio, "Line In to Rear Out (0 = auto, 1 = force).");
|
||||
#define ES_REG_1371_CODEC 0x14 /* W/R: Codec Read/Write register address */
|
||||
#define ES_1371_CODEC_RDY (1<<31) /* codec ready */
|
||||
#define ES_1371_CODEC_WIP (1<<30) /* codec register access in progress */
|
||||
#define EV_1938_CODEC_MAGIC (1<<26)
|
||||
#define ES_1371_CODEC_PIRD (1<<23) /* codec read/write select register */
|
||||
#define ES_1371_CODEC_WRITE(a,d) ((((a)&0x7f)<<16)|(((d)&0xffff)<<0))
|
||||
#define ES_1371_CODEC_READS(a) ((((a)&0x7f)<<16)|ES_1371_CODEC_PIRD)
|
||||
@ -603,12 +604,18 @@ static void snd_es1370_codec_write(struct snd_ak4531 *ak4531,
|
||||
|
||||
#ifdef CHIP1371
|
||||
|
||||
static inline bool is_ev1938(struct ensoniq *ensoniq)
|
||||
{
|
||||
return ensoniq->pci->device == 0x8938;
|
||||
}
|
||||
|
||||
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;
|
||||
unsigned int t, x, flag;
|
||||
|
||||
flag = is_ev1938(ensoniq) ? EV_1938_CODEC_MAGIC : 0;
|
||||
mutex_lock(&ensoniq->src_mutex);
|
||||
for (t = 0; t < POLL_COUNT; t++) {
|
||||
if (!(inl(ES_REG(ensoniq, 1371_CODEC)) & ES_1371_CODEC_WIP)) {
|
||||
@ -630,7 +637,8 @@ static void snd_es1371_codec_write(struct snd_ac97 *ac97,
|
||||
0x00010000)
|
||||
break;
|
||||
}
|
||||
outl(ES_1371_CODEC_WRITE(reg, val), ES_REG(ensoniq, 1371_CODEC));
|
||||
outl(ES_1371_CODEC_WRITE(reg, val) | flag,
|
||||
ES_REG(ensoniq, 1371_CODEC));
|
||||
/* restore SRC reg */
|
||||
snd_es1371_wait_src_ready(ensoniq);
|
||||
outl(x, ES_REG(ensoniq, 1371_SMPRATE));
|
||||
@ -647,8 +655,9 @@ 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 t, x, flag, fail = 0;
|
||||
|
||||
flag = is_ev1938(ensoniq) ? EV_1938_CODEC_MAGIC : 0;
|
||||
__again:
|
||||
mutex_lock(&ensoniq->src_mutex);
|
||||
for (t = 0; t < POLL_COUNT; t++) {
|
||||
@ -671,7 +680,8 @@ static unsigned short snd_es1371_codec_read(struct snd_ac97 *ac97,
|
||||
0x00010000)
|
||||
break;
|
||||
}
|
||||
outl(ES_1371_CODEC_READS(reg), ES_REG(ensoniq, 1371_CODEC));
|
||||
outl(ES_1371_CODEC_READS(reg) | flag,
|
||||
ES_REG(ensoniq, 1371_CODEC));
|
||||
/* restore SRC reg */
|
||||
snd_es1371_wait_src_ready(ensoniq);
|
||||
outl(x, ES_REG(ensoniq, 1371_SMPRATE));
|
||||
@ -683,6 +693,11 @@ static unsigned short snd_es1371_codec_read(struct snd_ac97 *ac97,
|
||||
/* 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) {
|
||||
if (is_ev1938(ensoniq)) {
|
||||
for (t = 0; t < 100; t++)
|
||||
inl(ES_REG(ensoniq, CONTROL));
|
||||
x = inl(ES_REG(ensoniq, 1371_CODEC));
|
||||
}
|
||||
mutex_unlock(&ensoniq->src_mutex);
|
||||
return ES_1371_CODEC_READ(x);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user