diff options
author | Mauro Carvalho Chehab <mchehab@infradead.org> | 2008-02-06 16:34:13 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@infradead.org> | 2008-02-18 09:15:16 -0500 |
commit | 00b8730f5db19f9ea0985d7f14f869df79a0bf76 (patch) | |
tree | 043a721acdae940c0f26fadce689a3e0fb421655 /drivers/media/video/em28xx | |
parent | 0df8130fe80ebde052516c1d729aa5d1c69ebc5c (diff) |
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>
Diffstat (limited to 'drivers/media/video/em28xx')
-rw-r--r-- | drivers/media/video/em28xx/em28xx-core.c | 28 | ||||
-rw-r--r-- | drivers/media/video/em28xx/em28xx-video.c | 3 |
2 files changed, 21 insertions, 10 deletions
diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c index 6965bafe54a1..275f1e936304 100644 --- a/drivers/media/video/em28xx/em28xx-core.c +++ b/drivers/media/video/em28xx/em28xx-core.c | |||
@@ -255,21 +255,26 @@ static int em28xx_write_reg_bits(struct em28xx *dev, u16 reg, u8 val, | |||
255 | */ | 255 | */ |
256 | static int em28xx_write_ac97(struct em28xx *dev, u8 reg, u8 *val) | 256 | static int em28xx_write_ac97(struct em28xx *dev, u8 reg, u8 *val) |
257 | { | 257 | { |
258 | int ret; | 258 | int ret, i; |
259 | u8 addr = reg & 0x7f; | 259 | u8 addr = reg & 0x7f; |
260 | if ((ret = em28xx_write_regs(dev, AC97LSB_REG, val, 2)) < 0) | 260 | if ((ret = em28xx_write_regs(dev, AC97LSB_REG, val, 2)) < 0) |
261 | return ret; | 261 | return ret; |
262 | if ((ret = em28xx_write_regs(dev, AC97ADDR_REG, &addr, 1)) < 0) | 262 | if ((ret = em28xx_write_regs(dev, AC97ADDR_REG, &addr, 1)) < 0) |
263 | return ret; | 263 | return ret; |
264 | if ((ret = em28xx_read_reg(dev, AC97BUSY_REG)) < 0) | 264 | |
265 | return ret; | 265 | /* Wait up to 50 ms for AC97 command to complete */ |
266 | else if (((u8) ret) & 0x01) { | 266 | for (i = 0; i < 10; i++) { |
267 | em28xx_warn ("AC97 command still being executed: not handled properly!\n"); | 267 | if ((ret = em28xx_read_reg(dev, AC97BUSY_REG)) < 0) |
268 | return ret; | ||
269 | if (!((u8) ret) & 0x01) | ||
270 | return 0; | ||
271 | msleep(5); | ||
268 | } | 272 | } |
273 | em28xx_warn ("AC97 command still being executed: not handled properly!\n"); | ||
269 | return 0; | 274 | return 0; |
270 | } | 275 | } |
271 | 276 | ||
272 | int em28xx_set_audio_source(struct em28xx *dev) | 277 | static int em28xx_set_audio_source(struct em28xx *dev) |
273 | { | 278 | { |
274 | static char *enable = "\x08\x08"; | 279 | static char *enable = "\x08\x08"; |
275 | static char *disable = "\x08\x88"; | 280 | static char *disable = "\x08\x88"; |
@@ -312,6 +317,7 @@ int em28xx_set_audio_source(struct em28xx *dev) | |||
312 | ret = em28xx_write_reg_bits(dev, AUDIOSRC_REG, input, 0xc0); | 317 | ret = em28xx_write_reg_bits(dev, AUDIOSRC_REG, input, 0xc0); |
313 | if (ret < 0) | 318 | if (ret < 0) |
314 | return ret; | 319 | return ret; |
320 | msleep(5); | ||
315 | 321 | ||
316 | /* Sets AC97 mixer registers | 322 | /* Sets AC97 mixer registers |
317 | This is seems to be needed, even for non-ac97 configs | 323 | This is seems to be needed, even for non-ac97 configs |
@@ -334,9 +340,10 @@ int em28xx_audio_analog_set(struct em28xx *dev) | |||
334 | s[0] |= 0x1f - dev->volume; | 340 | s[0] |= 0x1f - dev->volume; |
335 | s[1] |= 0x1f - dev->volume; | 341 | s[1] |= 0x1f - dev->volume; |
336 | 342 | ||
337 | if (dev->mute) | 343 | /* Mute */ |
338 | s[1] |= 0x80; | 344 | s[1] |= 0x80; |
339 | ret = em28xx_write_ac97(dev, MASTER_AC97, s); | 345 | ret = em28xx_write_ac97(dev, MASTER_AC97, s); |
346 | |||
340 | if (ret < 0) | 347 | if (ret < 0) |
341 | return ret; | 348 | return ret; |
342 | 349 | ||
@@ -354,6 +361,11 @@ int em28xx_audio_analog_set(struct em28xx *dev) | |||
354 | /* Selects the proper audio input */ | 361 | /* Selects the proper audio input */ |
355 | ret = em28xx_set_audio_source(dev); | 362 | ret = em28xx_set_audio_source(dev); |
356 | 363 | ||
364 | /* Unmute device */ | ||
365 | if (!dev->mute) | ||
366 | s[1] &= ~0x80; | ||
367 | ret = em28xx_write_ac97(dev, MASTER_AC97, s); | ||
368 | |||
357 | return ret; | 369 | return ret; |
358 | } | 370 | } |
359 | EXPORT_SYMBOL_GPL(em28xx_audio_analog_set); | 371 | EXPORT_SYMBOL_GPL(em28xx_audio_analog_set); |
diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index f69f591eeaf6..eeda3b2faec8 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c | |||
@@ -189,7 +189,7 @@ static void video_mux(struct em28xx *dev, int index) | |||
189 | em28xx_i2c_call_clients(dev, VIDIOC_INT_S_AUDIO_ROUTING, &route); | 189 | em28xx_i2c_call_clients(dev, VIDIOC_INT_S_AUDIO_ROUTING, &route); |
190 | } | 190 | } |
191 | 191 | ||
192 | em28xx_set_audio_source(dev); | 192 | em28xx_audio_analog_set(dev); |
193 | } | 193 | } |
194 | 194 | ||
195 | /* Usage lock check functions */ | 195 | /* Usage lock check functions */ |
@@ -837,7 +837,6 @@ static int em28xx_reg_len(int reg) | |||
837 | case AC97LSB_REG: | 837 | case AC97LSB_REG: |
838 | case HSCALELOW_REG: | 838 | case HSCALELOW_REG: |
839 | case VSCALELOW_REG: | 839 | case VSCALELOW_REG: |
840 | |||
841 | return 2; | 840 | return 2; |
842 | default: | 841 | default: |
843 | return 1; | 842 | return 1; |