summaryrefslogtreecommitdiff
path: root/linux/drivers/media/video/bt8xx/bttv-driver.c
diff options
context:
space:
mode:
Diffstat (limited to 'linux/drivers/media/video/bt8xx/bttv-driver.c')
-rw-r--r--linux/drivers/media/video/bt8xx/bttv-driver.c129
1 files changed, 92 insertions, 37 deletions
diff --git a/linux/drivers/media/video/bt8xx/bttv-driver.c b/linux/drivers/media/video/bt8xx/bttv-driver.c
index 83458f993..56ba5940e 100644
--- a/linux/drivers/media/video/bt8xx/bttv-driver.c
+++ b/linux/drivers/media/video/bt8xx/bttv-driver.c
@@ -37,6 +37,8 @@
#include <linux/kdev_t.h>
#include "bttvp.h"
#include <media/v4l2-common.h>
+#include <media/tvaudio.h>
+#include <media/msp3400.h>
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
#include <linux/dma-mapping.h>
@@ -942,50 +944,103 @@ video_mux(struct bttv *btv, unsigned int input)
static char *audio_modes[] = {
"audio: tuner", "audio: radio", "audio: extern",
- "audio: intern", "audio: off"
+ "audio: intern", "audio: mute"
};
static int
-audio_mux(struct bttv *btv, int mode)
+audio_mux(struct bttv *btv, int input, int mute)
{
- int val,mux,i2c_mux,signal;
+ int gpio_val, signal;
+ struct v4l2_control ctrl;
+ struct i2c_client *c;
gpio_inout(bttv_tvcards[btv->c.type].gpiomask,
bttv_tvcards[btv->c.type].gpiomask);
signal = btread(BT848_DSTATUS) & BT848_DSTATUS_HLOC;
- switch (mode) {
- case AUDIO_MUTE:
- btv->audio |= AUDIO_MUTE;
- break;
- case AUDIO_UNMUTE:
- btv->audio &= ~AUDIO_MUTE;
- break;
- case AUDIO_TUNER:
- case AUDIO_RADIO:
- case AUDIO_EXTERN:
- case AUDIO_INTERN:
- btv->audio &= AUDIO_MUTE;
- btv->audio |= mode;
- }
- i2c_mux = mux = (btv->audio & AUDIO_MUTE) ? AUDIO_OFF : btv->audio;
- if (btv->opt_automute && !signal && !btv->radio_user)
- mux = AUDIO_OFF;
+ btv->mute = mute;
+ btv->audio = input;
+
+ /* automute */
+ mute = mute || (btv->opt_automute && !signal && !btv->radio_user);
+
+ if (mute)
+ gpio_val = bttv_tvcards[btv->c.type].gpiomute;
+ else
+ gpio_val = bttv_tvcards[btv->c.type].gpiomux[input];
#if 0
- printk("bttv%d: amux: mode=%d audio=%d signal=%s mux=%d/%d irq=%s\n",
- btv->c.nr, mode, btv->audio, signal ? "yes" : "no",
- mux, i2c_mux, in_interrupt() ? "yes" : "no");
+ printk("bttv%d: amux: input=%d mute=%d signal=%s gpio_mux=%d irq=%s\n",
+ btv->c.nr, input, mute, signal ? "yes" : "no",
+ gpio_val, in_interrupt() ? "yes" : "no");
#endif
- val = bttv_tvcards[btv->c.type].audiomux[mux];
- gpio_bits(bttv_tvcards[btv->c.type].gpiomask,val);
+ gpio_bits(bttv_tvcards[btv->c.type].gpiomask, gpio_val);
if (bttv_gpio)
- bttv_gpio_tracking(btv,audio_modes[mux]);
- if (!in_interrupt())
- bttv_call_i2c_clients(btv,AUDC_SET_INPUT,&(i2c_mux));
+ bttv_gpio_tracking(btv, audio_modes[mute ? 4 : input]);
+ if (in_interrupt())
+ return 0;
+
+ ctrl.id = V4L2_CID_AUDIO_MUTE;
+ ctrl.value = btv->mute;
+ bttv_call_i2c_clients(btv, VIDIOC_S_CTRL, &ctrl);
+ c = btv->i2c_msp34xx_client;
+ if (c) {
+ struct v4l2_routing route;
+
+ /* Note: the inputs tuner/radio/extern/intern are translated
+ to msp routings. This assumes common behavior for all msp3400
+ based TV cards. When this assumption fails, then the
+ specific MSP routing must be added to the card table.
+ For now this is sufficient. */
+ switch (input) {
+ case TVAUDIO_INPUT_RADIO:
+ route.input = MSP_INPUT(MSP_IN_SCART_2, MSP_IN_TUNER_1,
+ MSP_DSP_OUT_SCART, MSP_DSP_OUT_SCART);
+ break;
+ case TVAUDIO_INPUT_EXTERN:
+ route.input = MSP_INPUT(MSP_IN_SCART_1, MSP_IN_TUNER_1,
+ MSP_DSP_OUT_SCART, MSP_DSP_OUT_SCART);
+ break;
+ case TVAUDIO_INPUT_INTERN:
+ /* Yes, this is the same input as for RADIO. I doubt
+ if this is ever used. The only board with an INTERN
+ input is the BTTV_BOARD_AVERMEDIA98. I wonder how
+ that was tested. My guess is that the whole INTERN
+ input does not work. */
+ route.input = MSP_INPUT(MSP_IN_SCART_2, MSP_IN_TUNER_1,
+ MSP_DSP_OUT_SCART, MSP_DSP_OUT_SCART);
+ break;
+ case TVAUDIO_INPUT_TUNER:
+ default:
+ route.input = MSP_INPUT_DEFAULT;
+ break;
+ }
+ route.output = MSP_OUTPUT_DEFAULT;
+ c->driver->command(c, VIDIOC_INT_S_AUDIO_ROUTING, &route);
+ }
+ c = btv->i2c_tvaudio_client;
+ if (c) {
+ struct v4l2_routing route;
+
+ route.input = input;
+ route.output = 0;
+ c->driver->command(c, VIDIOC_INT_S_AUDIO_ROUTING, &route);
+ }
return 0;
}
+static inline int
+audio_mute(struct bttv *btv, int mute)
+{
+ return audio_mux(btv, btv->audio, mute);
+}
+
+static inline int
+audio_input(struct bttv *btv, int input)
+{
+ return audio_mux(btv, input, btv->mute);
+}
+
static void
i2c_vidiocschan(struct bttv *btv)
{
@@ -1049,8 +1104,8 @@ set_input(struct bttv *btv, unsigned int input)
} else {
video_mux(btv,input);
}
- audio_mux(btv,(input == bttv_tvcards[btv->c.type].tuner ?
- AUDIO_TUNER : AUDIO_EXTERN));
+ audio_input(btv,(input == bttv_tvcards[btv->c.type].tuner ?
+ TVAUDIO_INPUT_TUNER : TVAUDIO_INPUT_EXTERN));
set_tvnorm(btv,btv->tvnorm);
i2c_vidiocschan(btv);
}
@@ -1262,10 +1317,10 @@ static int set_control(struct bttv *btv, struct v4l2_control *c)
case V4L2_CID_AUDIO_MUTE:
if (c->value) {
va.flags |= VIDEO_AUDIO_MUTE;
- audio_mux(btv, AUDIO_MUTE);
+ audio_mute(btv, 1);
} else {
va.flags &= ~VIDEO_AUDIO_MUTE;
- audio_mux(btv, AUDIO_UNMUTE);
+ audio_mute(btv, 0);
}
break;
@@ -1680,7 +1735,7 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg)
return -EINVAL;
mutex_lock(&btv->lock);
- audio_mux(btv, (v->flags&VIDEO_AUDIO_MUTE) ? AUDIO_MUTE : AUDIO_UNMUTE);
+ audio_mute(btv, (v->flags&VIDEO_AUDIO_MUTE) ? 1 : 0);
bttv_call_i2c_clients(btv,cmd,v);
/* card specific hooks */
@@ -3191,8 +3246,8 @@ static int radio_open(struct inode *inode, struct file *file)
file->private_data = btv;
- bttv_call_i2c_clients(btv,AUDC_SET_RADIO,&btv->tuner_type);
- audio_mux(btv,AUDIO_RADIO);
+ bttv_call_i2c_clients(btv,AUDC_SET_RADIO,NULL);
+ audio_input(btv,TVAUDIO_INPUT_RADIO);
mutex_unlock(&btv->lock);
return 0;
@@ -3782,7 +3837,7 @@ static irqreturn_t bttv_irq(int irq, void *dev_id, struct pt_regs * regs)
bttv_irq_switch_video(btv);
if ((astat & BT848_INT_HLOCK) && btv->opt_automute)
- audio_mux(btv, -1);
+ audio_mute(btv, btv->mute); /* trigger automute */
if (astat & (BT848_INT_SCERR|BT848_INT_OCERR)) {
printk(KERN_INFO "bttv%d: %s%s @ %08x,",btv->c.nr,
@@ -4091,7 +4146,7 @@ static int __devinit bttv_probe(struct pci_dev *dev,
bt848_contrast(btv,32768);
bt848_hue(btv,32768);
bt848_sat(btv,32768);
- audio_mux(btv,AUDIO_MUTE);
+ audio_mute(btv, 1);
set_input(btv,0);
}