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: Mauro Carvalho Chehab <mchehab@infradead.org>
This commit is contained in:
parent
0df8130fe8
commit
00b8730f5d
|
@ -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)
|
||||
{
|
||||
int ret;
|
||||
int ret, i;
|
||||
u8 addr = reg & 0x7f;
|
||||
if ((ret = em28xx_write_regs(dev, AC97LSB_REG, val, 2)) < 0)
|
||||
return ret;
|
||||
if ((ret = em28xx_write_regs(dev, AC97ADDR_REG, &addr, 1)) < 0)
|
||||
return ret;
|
||||
|
||||
/* Wait up to 50 ms for AC97 command to complete */
|
||||
for (i = 0; i < 10; i++) {
|
||||
if ((ret = em28xx_read_reg(dev, AC97BUSY_REG)) < 0)
|
||||
return ret;
|
||||
else if (((u8) ret) & 0x01) {
|
||||
em28xx_warn ("AC97 command still being executed: not handled properly!\n");
|
||||
if (!((u8) ret) & 0x01)
|
||||
return 0;
|
||||
msleep(5);
|
||||
}
|
||||
em28xx_warn ("AC97 command still being executed: not handled properly!\n");
|
||||
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 *disable = "\x08\x88";
|
||||
|
@ -312,6 +317,7 @@ int em28xx_set_audio_source(struct em28xx *dev)
|
|||
ret = em28xx_write_reg_bits(dev, AUDIOSRC_REG, input, 0xc0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
msleep(5);
|
||||
|
||||
/* Sets AC97 mixer registers
|
||||
This is seems to be needed, even for non-ac97 configs
|
||||
|
@ -334,9 +340,10 @@ int em28xx_audio_analog_set(struct em28xx *dev)
|
|||
s[0] |= 0x1f - dev->volume;
|
||||
s[1] |= 0x1f - dev->volume;
|
||||
|
||||
if (dev->mute)
|
||||
/* Mute */
|
||||
s[1] |= 0x80;
|
||||
ret = em28xx_write_ac97(dev, MASTER_AC97, s);
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
|
@ -354,6 +361,11 @@ int em28xx_audio_analog_set(struct em28xx *dev)
|
|||
/* Selects the proper audio input */
|
||||
ret = em28xx_set_audio_source(dev);
|
||||
|
||||
/* Unmute device */
|
||||
if (!dev->mute)
|
||||
s[1] &= ~0x80;
|
||||
ret = em28xx_write_ac97(dev, MASTER_AC97, s);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(em28xx_audio_analog_set);
|
||||
|
|
|
@ -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_set_audio_source(dev);
|
||||
em28xx_audio_analog_set(dev);
|
||||
}
|
||||
|
||||
/* Usage lock check functions */
|
||||
|
@ -837,7 +837,6 @@ static int em28xx_reg_len(int reg)
|
|||
case AC97LSB_REG:
|
||||
case HSCALELOW_REG:
|
||||
case VSCALELOW_REG:
|
||||
|
||||
return 2;
|
||||
default:
|
||||
return 1;
|
||||
|
|
Loading…
Reference in New Issue