Commit 00b8730f authored by Mauro Carvalho Chehab's avatar Mauro Carvalho Chehab

V4L/DVB (7163): em28xx: makes audio settings more stable

Improves audio configurations on em28xx:
        - mutes audio before changing amux;
        - adds a delay after setting audio src;
        - waits up to 50ms for ac97 busy.
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@infradead.org>
parent 0df8130f
...@@ -255,21 +255,26 @@ static int em28xx_write_reg_bits(struct em28xx *dev, u16 reg, u8 val, ...@@ -255,21 +255,26 @@ static int em28xx_write_reg_bits(struct em28xx *dev, u16 reg, u8 val,
*/ */
static int em28xx_write_ac97(struct em28xx *dev, u8 reg, u8 *val) static int em28xx_write_ac97(struct em28xx *dev, u8 reg, u8 *val)
{ {
int ret; int ret, i;
u8 addr = reg & 0x7f; u8 addr = reg & 0x7f;
if ((ret = em28xx_write_regs(dev, AC97LSB_REG, val, 2)) < 0) if ((ret = em28xx_write_regs(dev, AC97LSB_REG, val, 2)) < 0)
return ret; return ret;
if ((ret = em28xx_write_regs(dev, AC97ADDR_REG, &addr, 1)) < 0) if ((ret = em28xx_write_regs(dev, AC97ADDR_REG, &addr, 1)) < 0)
return ret; return ret;
if ((ret = em28xx_read_reg(dev, AC97BUSY_REG)) < 0)
return ret; /* Wait up to 50 ms for AC97 command to complete */
else if (((u8) ret) & 0x01) { for (i = 0; i < 10; i++) {
em28xx_warn ("AC97 command still being executed: not handled properly!\n"); if ((ret = em28xx_read_reg(dev, AC97BUSY_REG)) < 0)
return ret;
if (!((u8) ret) & 0x01)
return 0;
msleep(5);
} }
em28xx_warn ("AC97 command still being executed: not handled properly!\n");
return 0; return 0;
} }
int em28xx_set_audio_source(struct em28xx *dev) static int em28xx_set_audio_source(struct em28xx *dev)
{ {
static char *enable = "\x08\x08"; static char *enable = "\x08\x08";
static char *disable = "\x08\x88"; static char *disable = "\x08\x88";
...@@ -312,6 +317,7 @@ int em28xx_set_audio_source(struct em28xx *dev) ...@@ -312,6 +317,7 @@ int em28xx_set_audio_source(struct em28xx *dev)
ret = em28xx_write_reg_bits(dev, AUDIOSRC_REG, input, 0xc0); ret = em28xx_write_reg_bits(dev, AUDIOSRC_REG, input, 0xc0);
if (ret < 0) if (ret < 0)
return ret; return ret;
msleep(5);
/* Sets AC97 mixer registers /* Sets AC97 mixer registers
This is seems to be needed, even for non-ac97 configs This is seems to be needed, even for non-ac97 configs
...@@ -334,9 +340,10 @@ int em28xx_audio_analog_set(struct em28xx *dev) ...@@ -334,9 +340,10 @@ int em28xx_audio_analog_set(struct em28xx *dev)
s[0] |= 0x1f - dev->volume; s[0] |= 0x1f - dev->volume;
s[1] |= 0x1f - dev->volume; s[1] |= 0x1f - dev->volume;
if (dev->mute) /* Mute */
s[1] |= 0x80; s[1] |= 0x80;
ret = em28xx_write_ac97(dev, MASTER_AC97, s); ret = em28xx_write_ac97(dev, MASTER_AC97, s);
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -354,6 +361,11 @@ int em28xx_audio_analog_set(struct em28xx *dev) ...@@ -354,6 +361,11 @@ int em28xx_audio_analog_set(struct em28xx *dev)
/* Selects the proper audio input */ /* Selects the proper audio input */
ret = em28xx_set_audio_source(dev); ret = em28xx_set_audio_source(dev);
/* Unmute device */
if (!dev->mute)
s[1] &= ~0x80;
ret = em28xx_write_ac97(dev, MASTER_AC97, s);
return ret; return ret;
} }
EXPORT_SYMBOL_GPL(em28xx_audio_analog_set); EXPORT_SYMBOL_GPL(em28xx_audio_analog_set);
......
...@@ -189,7 +189,7 @@ static void video_mux(struct em28xx *dev, int index) ...@@ -189,7 +189,7 @@ static void video_mux(struct em28xx *dev, int index)
em28xx_i2c_call_clients(dev, VIDIOC_INT_S_AUDIO_ROUTING, &route); em28xx_i2c_call_clients(dev, VIDIOC_INT_S_AUDIO_ROUTING, &route);
} }
em28xx_set_audio_source(dev); em28xx_audio_analog_set(dev);
} }
/* Usage lock check functions */ /* Usage lock check functions */
...@@ -837,7 +837,6 @@ static int em28xx_reg_len(int reg) ...@@ -837,7 +837,6 @@ static int em28xx_reg_len(int reg)
case AC97LSB_REG: case AC97LSB_REG:
case HSCALELOW_REG: case HSCALELOW_REG:
case VSCALELOW_REG: case VSCALELOW_REG:
return 2; return 2;
default: default:
return 1; return 1;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment