aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab@redhat.com>2008-11-20 12:40:51 -0300
committerMauro Carvalho Chehab <mchehab@redhat.com>2008-12-29 17:53:37 -0200
commit35ae6f04ad3e4c3ed8a83382b6511bd9beb5c768 (patch)
treeac482c50af4af87bab959b6e839a8383811d8daa /drivers
parentV4L/DVB (9669): em28xx: Fix a stupid cut-and-paste error (diff)
downloadlinux-dev-35ae6f04ad3e4c3ed8a83382b6511bd9beb5c768.tar.xz
linux-dev-35ae6f04ad3e4c3ed8a83382b6511bd9beb5c768.zip
V4L/DVB (9670): em28xx: allow specifying audio output
Some boards use different AC97 setups for output. This patch adds the capability of specifying the output to be used. Currently, only one output is selected, but the better is to allow user to select it via a mixer, on alsa driver. Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/media/video/em28xx/em28xx-core.c24
-rw-r--r--drivers/media/video/em28xx/em28xx-video.c42
-rw-r--r--drivers/media/video/em28xx/em28xx.h10
3 files changed, 57 insertions, 19 deletions
diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c
index 2842ddf6ddac..8aead5e84d0f 100644
--- a/drivers/media/video/em28xx/em28xx-core.c
+++ b/drivers/media/video/em28xx/em28xx-core.c
@@ -388,9 +388,17 @@ static int em28xx_set_audio_source(struct em28xx *dev)
return ret;
}
+static int outputs[] = {
+ [EM28XX_AOUT_MASTER] = AC97_MASTER_VOL,
+ [EM28XX_AOUT_LINE] = AC97_LINE_LEVEL_VOL,
+ [EM28XX_AOUT_MONO] = AC97_MASTER_MONO_VOL,
+ [EM28XX_AOUT_LFE] = AC97_LFE_MASTER_VOL,
+ [EM28XX_AOUT_SURR] = AC97_SURR_MASTER_VOL,
+};
+
int em28xx_audio_analog_set(struct em28xx *dev)
{
- int ret;
+ int ret, i;
u8 xclk = 0x07;
if (!dev->audio_mode.has_audio)
@@ -400,11 +408,13 @@ int em28xx_audio_analog_set(struct em28xx *dev)
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);
-
- if (ret < 0)
- return ret;
+ /* Mute all outputs */
+ for (i = 0; i < ARRAY_SIZE(outputs); i++) {
+ ret = em28xx_write_ac97(dev, outputs[i], 0x8000);
+ if (ret < 0)
+ em28xx_warn("couldn't setup AC97 register %d\n",
+ outputs[i]);
+ }
}
if (dev->has_12mhz_i2s)
@@ -433,7 +443,7 @@ int em28xx_audio_analog_set(struct em28xx *dev)
vol |= 0x8000;
/* Sets volume */
- ret = em28xx_write_ac97(dev, AC97_MASTER_VOL, vol);
+ ret = em28xx_write_ac97(dev, outputs[dev->ctl_aoutput], vol);
}
return ret;
diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c
index 6b7d44a7117f..bea74fd9a520 100644
--- a/drivers/media/video/em28xx/em28xx-video.c
+++ b/drivers/media/video/em28xx/em28xx-video.c
@@ -566,6 +566,7 @@ static void video_mux(struct em28xx *dev, int index)
route.output = 0;
dev->ctl_input = index;
dev->ctl_ainput = INPUT(index)->amux;
+ dev->ctl_aoutput = INPUT(index)->aout;
em28xx_i2c_call_clients(dev, VIDIOC_INT_S_VIDEO_ROUTING, &route);
@@ -928,20 +929,38 @@ static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
{
struct em28xx_fh *fh = priv;
struct em28xx *dev = fh->dev;
- unsigned int index = a->index;
- if (a->index > 1)
- return -EINVAL;
-
- index = dev->ctl_ainput;
-
- if (index == 0)
+ switch (a->index) {
+ case EM28XX_AMUX_VIDEO:
strcpy(a->name, "Television");
- else
+ break;
+ case EM28XX_AMUX_LINE_IN:
strcpy(a->name, "Line In");
+ break;
+ case EM28XX_AMUX_VIDEO2:
+ strcpy(a->name, "Television alt");
+ break;
+ case EM28XX_AMUX_PHONE:
+ strcpy(a->name, "Phone");
+ break;
+ case EM28XX_AMUX_MIC:
+ strcpy(a->name, "Mic");
+ break;
+ case EM28XX_AMUX_CD:
+ strcpy(a->name, "CD");
+ break;
+ case EM28XX_AMUX_AUX:
+ strcpy(a->name, "Aux");
+ break;
+ case EM28XX_AMUX_PCM_OUT:
+ strcpy(a->name, "PCM");
+ break;
+ default:
+ return -EINVAL;
+ }
+ a->index = dev->ctl_ainput;
a->capability = V4L2_AUDCAP_STEREO;
- a->index = index;
return 0;
}
@@ -951,9 +970,8 @@ static int vidioc_s_audio(struct file *file, void *priv, struct v4l2_audio *a)
struct em28xx_fh *fh = priv;
struct em28xx *dev = fh->dev;
- if (a->index != dev->ctl_ainput)
- return -EINVAL;
-
+ dev->ctl_ainput = INPUT(a->index)->amux;
+ dev->ctl_aoutput = INPUT(a->index)->aout;
return 0;
}
diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h
index 4fde52bd7e97..89e13c599f8d 100644
--- a/drivers/media/video/em28xx/em28xx.h
+++ b/drivers/media/video/em28xx/em28xx.h
@@ -295,10 +295,19 @@ enum em28xx_amux {
EM28XX_AMUX_PCM_OUT,
};
+enum em28xx_aout {
+ EM28XX_AOUT_MASTER = 0, /* should be the default */
+ EM28XX_AOUT_LINE,
+ EM28XX_AOUT_MONO,
+ EM28XX_AOUT_LFE,
+ EM28XX_AOUT_SURR,
+};
+
struct em28xx_input {
enum enum28xx_itype type;
unsigned int vmux;
enum em28xx_amux amux;
+ enum em28xx_aout aout;
};
#define INPUT(nr) (&em28xx_boards[dev->model].input[nr])
@@ -450,6 +459,7 @@ struct em28xx {
int ctl_freq; /* selected frequency */
unsigned int ctl_input; /* selected input */
unsigned int ctl_ainput;/* selected audio input */
+ unsigned int ctl_aoutput;/* selected audio output */
int mute;
int volume;
/* frame properties */