diff options
author | Mauro Carvalho Chehab <mchehab@redhat.com> | 2008-11-20 09:06:09 -0300 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2008-12-29 17:53:35 -0200 |
commit | 5faff78904d9c07f38ac0e227b322e9f58d5447c (patch) | |
tree | 431d2e8c8fc7a17396e806f778293629226fc892 /drivers/media/video/em28xx/em28xx-core.c | |
parent | 16c7bcadff2222b297d13951dc30e133f56d0154 (diff) |
V4L/DVB (9653): em28xx: improve AC97 handling
AC97 devices provide several input and outputs. However, before this
patch, em28xx device weren't properly allowing the usage of ac97
possible combinations. Also, several input volumes were left untouched,
instead of making sure that the volumes were set on mute state.
This patch improves support for ac97 devices by allowing to use any
inputs, and making sure that unused inputs are set on mute state.
Yet, some work is still needed to select the AC97 output.
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/em28xx/em28xx-core.c')
-rw-r--r-- | drivers/media/video/em28xx/em28xx-core.c | 73 |
1 files changed, 43 insertions, 30 deletions
diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c index b0a238421f2..1cf5b443092 100644 --- a/drivers/media/video/em28xx/em28xx-core.c +++ b/drivers/media/video/em28xx/em28xx-core.c @@ -298,29 +298,44 @@ static int em28xx_write_ac97(struct em28xx *dev, u8 reg, u16 val) return 0; } -static int set_ac97_em202_input(struct em28xx *dev) +struct em28xx_input_table { + enum em28xx_amux amux; + u8 reg; +}; + +static struct em28xx_input_table inputs[] = { + { EM28XX_AMUX_VIDEO, AC97_VIDEO_VOL }, + { EM28XX_AMUX_LINE_IN, AC97_LINEIN_VOL }, + { EM28XX_AMUX_PHONE, AC97_PHONE_VOL }, + { EM28XX_AMUX_MIC, AC97_MIC_VOL }, + { EM28XX_AMUX_CD, AC97_CD_VOL }, + { EM28XX_AMUX_AUX, AC97_AUX_VOL }, + { EM28XX_AMUX_PCM_OUT, AC97_PCM_OUT_VOL }, +}; + +static int set_ac97_input(struct em28xx *dev) { - int ret; - u16 enable = 0x0808; /* 12 dB attenuation Left/Right */ - u16 disable = 0x8808; /* bit 15 - mute volumme */ - u16 video, line; - - if (dev->ctl_ainput == EM28XX_AMUX_VIDEO) { - video = enable; - line = disable; - } else { - video = disable; - line = enable; - } + int ret, i; + enum em28xx_amux amux = dev->ctl_ainput; - /* Sets em202 AC97 mixer registers */ - ret = em28xx_write_ac97(dev, AC97_VIDEO_VOL, video); - if (ret < 0) - return ret; + /* EM28XX_AMUX_VIDEO2 is a special case used to indicate that + em28xx should point to LINE IN, while AC97 should use VIDEO + */ + if (amux == EM28XX_AMUX_VIDEO2) + amux = dev->ctl_ainput; - ret = em28xx_write_ac97(dev, AC97_LINEIN_VOL, line); + /* Mute all entres but the one that were selected */ + for (i = 0; i < ARRAY_SIZE(inputs); i++) { + if (amux == inputs[i].amux) + ret = em28xx_write_ac97(dev, inputs[i].reg, 0x0808); + else + ret = em28xx_write_ac97(dev, inputs[i].reg, 0x8000); - return ret; + if (ret < 0) + em28xx_warn("couldn't setup AC97 register %d\n", + inputs[i].reg); + } + return 0; } static int em28xx_set_audio_source(struct em28xx *dev) @@ -329,10 +344,10 @@ static int em28xx_set_audio_source(struct em28xx *dev) u8 input; if (dev->is_em2800) { - if (dev->ctl_ainput) - input = EM2800_AUDIO_SRC_LINE; - else + if (dev->ctl_ainput == EM28XX_AMUX_VIDEO) input = EM2800_AUDIO_SRC_TUNER; + else + input = EM2800_AUDIO_SRC_LINE; ret = em28xx_write_regs(dev, EM2800_R08_AUDIOSRC, &input, 1); if (ret < 0) @@ -360,16 +375,11 @@ static int em28xx_set_audio_source(struct em28xx *dev) switch (dev->audio_mode.ac97) { case EM28XX_NO_AC97: break; - case EM28XX_AC97_OTHER: - /* We don't know how to handle this chip. - Let's hope it is close enough to em202 to work - */ - case EM28XX_AC97_EM202: - ret = set_ac97_em202_input(dev); - break; + default: + ret = set_ac97_input(dev); } - return 0; + return ret; } int em28xx_audio_analog_set(struct em28xx *dev) @@ -380,6 +390,9 @@ int em28xx_audio_analog_set(struct em28xx *dev) if (!dev->audio_mode.has_audio) return 0; + /* It is assumed that all devices use master volume for output. + It would be possible to use also line output. + */ if (dev->audio_mode.ac97 != EM28XX_NO_AC97) { /* Mute */ ret = em28xx_write_ac97(dev, AC97_MASTER_VOL, 0x8000); |