Commit 8bf2f8e7 authored by Hans Verkuil's avatar Hans Verkuil Committed by Mauro Carvalho Chehab

V4L/DVB (3577): Cleanup audio input handling

Cleanup audio input handling in bttv and tvaudio:
- inputs were specified that were never used
- mute was handled as a special input which led to confusing code
- confusing naming made it difficult to see if the setting was for
  i2c or gpio.
The old audiochip.h input names moved to tvaudio.h. Currently this
is used both by tvaudio and msp3400 until the msp3400 implements the
new msp3400-specific inputs.
Detect in bttv the tvaudio and msp3400 i2c clients and use these
client pointers to set the inputs directly instead of broadcasting the
command.
Removed AUDC_SET_INPUT. Now replaced by VIDIOC_S_AUDIO. This will be
replaced again later by the new ROUTING commands.
Removed VIDIOC_G_AUDIO implementations in i2c drivers: this command is
a user level command and not to be used internally. It wasn't called at
all anyway.
Signed-off-by: default avatarHans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@infradead.org>
parent ae62e3d4
...@@ -30,7 +30,6 @@ ...@@ -30,7 +30,6 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <media/audiochip.h>
#include <media/v4l2-common.h> #include <media/v4l2-common.h>
#include "bttv.h" #include "bttv.h"
......
This diff is collapsed.
...@@ -36,6 +36,7 @@ ...@@ -36,6 +36,7 @@
#include <linux/kdev_t.h> #include <linux/kdev_t.h>
#include "bttvp.h" #include "bttvp.h"
#include <media/v4l2-common.h> #include <media/v4l2-common.h>
#include <media/tvaudio.h>
#include <linux/dma-mapping.h> #include <linux/dma-mapping.h>
...@@ -926,45 +927,65 @@ video_mux(struct bttv *btv, unsigned int input) ...@@ -926,45 +927,65 @@ video_mux(struct bttv *btv, unsigned int input)
static char *audio_modes[] = { static char *audio_modes[] = {
"audio: tuner", "audio: radio", "audio: extern", "audio: tuner", "audio: radio", "audio: extern",
"audio: intern", "audio: off" "audio: intern", "audio: mute"
}; };
static int 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_audio aud_input;
struct v4l2_control ctrl;
struct i2c_client *c;
memset(&aud_input, 0, sizeof(aud_input));
gpio_inout(bttv_tvcards[btv->c.type].gpiomask, gpio_inout(bttv_tvcards[btv->c.type].gpiomask,
bttv_tvcards[btv->c.type].gpiomask); bttv_tvcards[btv->c.type].gpiomask);
signal = btread(BT848_DSTATUS) & BT848_DSTATUS_HLOC; signal = btread(BT848_DSTATUS) & BT848_DSTATUS_HLOC;
switch (mode) { btv->mute = mute;
case AUDIO_MUTE: btv->audio = input;
btv->audio |= AUDIO_MUTE;
break; /* automute */
case AUDIO_UNMUTE: mute = mute || (btv->opt_automute && !signal && !btv->radio_user);
btv->audio &= ~AUDIO_MUTE;
break; if (mute)
case AUDIO_TUNER: gpio_val = bttv_tvcards[btv->c.type].gpiomute;
case AUDIO_RADIO: else
case AUDIO_EXTERN: gpio_val = bttv_tvcards[btv->c.type].gpiomux[input];
case AUDIO_INTERN: aud_input.index = btv->audio;
btv->audio &= AUDIO_MUTE;
btv->audio |= mode; gpio_bits(bttv_tvcards[btv->c.type].gpiomask, gpio_val);
}
i2c_mux = mux = (btv->audio & AUDIO_MUTE) ? AUDIO_OFF : btv->audio;
if (btv->opt_automute && !signal && !btv->radio_user)
mux = AUDIO_OFF;
val = bttv_tvcards[btv->c.type].audiomux[mux];
gpio_bits(bttv_tvcards[btv->c.type].gpiomask,val);
if (bttv_gpio) if (bttv_gpio)
bttv_gpio_tracking(btv,audio_modes[mux]); bttv_gpio_tracking(btv, audio_modes[mute ? 4 : input]);
if (!in_interrupt()) if (in_interrupt())
bttv_call_i2c_clients(btv,AUDC_SET_INPUT,&(i2c_mux)); return 0;
ctrl.id = V4L2_CID_AUDIO_MUTE;
/* take automute into account, just btv->mute is not enough */
ctrl.value = mute;
bttv_call_i2c_clients(btv, VIDIOC_S_CTRL, &ctrl);
c = btv->i2c_msp34xx_client;
if (c)
c->driver->command(c, VIDIOC_S_AUDIO, &aud_input);
c = btv->i2c_tvaudio_client;
if (c)
c->driver->command(c, VIDIOC_S_AUDIO, &aud_input);
return 0; 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 static void
i2c_vidiocschan(struct bttv *btv) i2c_vidiocschan(struct bttv *btv)
{ {
...@@ -1023,8 +1044,8 @@ set_input(struct bttv *btv, unsigned int input) ...@@ -1023,8 +1044,8 @@ set_input(struct bttv *btv, unsigned int input)
} else { } else {
video_mux(btv,input); video_mux(btv,input);
} }
audio_mux(btv,(input == bttv_tvcards[btv->c.type].tuner ? audio_input(btv,(input == bttv_tvcards[btv->c.type].tuner ?
AUDIO_TUNER : AUDIO_EXTERN)); TVAUDIO_INPUT_TUNER : TVAUDIO_INPUT_EXTERN));
set_tvnorm(btv,btv->tvnorm); set_tvnorm(btv,btv->tvnorm);
i2c_vidiocschan(btv); i2c_vidiocschan(btv);
} }
...@@ -1236,10 +1257,10 @@ static int set_control(struct bttv *btv, struct v4l2_control *c) ...@@ -1236,10 +1257,10 @@ static int set_control(struct bttv *btv, struct v4l2_control *c)
case V4L2_CID_AUDIO_MUTE: case V4L2_CID_AUDIO_MUTE:
if (c->value) { if (c->value) {
va.flags |= VIDEO_AUDIO_MUTE; va.flags |= VIDEO_AUDIO_MUTE;
audio_mux(btv, AUDIO_MUTE); audio_mute(btv, 1);
} else { } else {
va.flags &= ~VIDEO_AUDIO_MUTE; va.flags &= ~VIDEO_AUDIO_MUTE;
audio_mux(btv, AUDIO_UNMUTE); audio_mute(btv, 0);
} }
break; break;
...@@ -1654,7 +1675,7 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg) ...@@ -1654,7 +1675,7 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg)
return -EINVAL; return -EINVAL;
mutex_lock(&btv->lock); 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); bttv_call_i2c_clients(btv,cmd,v);
/* card specific hooks */ /* card specific hooks */
...@@ -3163,8 +3184,8 @@ static int radio_open(struct inode *inode, struct file *file) ...@@ -3163,8 +3184,8 @@ static int radio_open(struct inode *inode, struct file *file)
file->private_data = btv; file->private_data = btv;
bttv_call_i2c_clients(btv,AUDC_SET_RADIO,&btv->tuner_type); bttv_call_i2c_clients(btv,AUDC_SET_RADIO,NULL);
audio_mux(btv,AUDIO_RADIO); audio_input(btv,TVAUDIO_INPUT_RADIO);
mutex_unlock(&btv->lock); mutex_unlock(&btv->lock);
return 0; return 0;
...@@ -3750,7 +3771,7 @@ static irqreturn_t bttv_irq(int irq, void *dev_id, struct pt_regs * regs) ...@@ -3750,7 +3771,7 @@ static irqreturn_t bttv_irq(int irq, void *dev_id, struct pt_regs * regs)
bttv_irq_switch_video(btv); bttv_irq_switch_video(btv);
if ((astat & BT848_INT_HLOCK) && btv->opt_automute) 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)) { if (astat & (BT848_INT_SCERR|BT848_INT_OCERR)) {
printk(KERN_INFO "bttv%d: %s%s @ %08x,",btv->c.nr, printk(KERN_INFO "bttv%d: %s%s @ %08x,",btv->c.nr,
...@@ -4051,7 +4072,7 @@ static int __devinit bttv_probe(struct pci_dev *dev, ...@@ -4051,7 +4072,7 @@ static int __devinit bttv_probe(struct pci_dev *dev,
bt848_contrast(btv,32768); bt848_contrast(btv,32768);
bt848_hue(btv,32768); bt848_hue(btv,32768);
bt848_sat(btv,32768); bt848_sat(btv,32768);
audio_mux(btv,AUDIO_MUTE); audio_mute(btv, 1);
set_input(btv,0); set_input(btv,0);
} }
......
...@@ -302,6 +302,10 @@ static int attach_inform(struct i2c_client *client) ...@@ -302,6 +302,10 @@ static int attach_inform(struct i2c_client *client)
if (!client->driver->command) if (!client->driver->command)
return 0; return 0;
if (client->driver->id == I2C_DRIVERID_MSP3400)
btv->i2c_msp34xx_client = client;
if (client->driver->id == I2C_DRIVERID_TVAUDIO)
btv->i2c_tvaudio_client = client;
if (btv->tuner_type != UNSET) { if (btv->tuner_type != UNSET) {
struct tuner_setup tun_setup; struct tuner_setup tun_setup;
......
...@@ -234,7 +234,8 @@ struct tvcard ...@@ -234,7 +234,8 @@ struct tvcard
unsigned int digital_mode; // DIGITAL_MODE_CAMERA or DIGITAL_MODE_VIDEO unsigned int digital_mode; // DIGITAL_MODE_CAMERA or DIGITAL_MODE_VIDEO
u32 gpiomask; u32 gpiomask;
u32 muxsel[16]; u32 muxsel[16];
u32 audiomux[6]; /* Tuner, Radio, external, internal, mute, stereo */ u32 gpiomux[4]; /* Tuner, Radio, external, internal */
u32 gpiomute; /* GPIO mute setting */
u32 gpiomask2; /* GPIO MUX mask */ u32 gpiomask2; /* GPIO MUX mask */
/* i2c audio flags */ /* i2c audio flags */
......
...@@ -41,7 +41,6 @@ ...@@ -41,7 +41,6 @@
#include <linux/device.h> #include <linux/device.h>
#include <media/video-buf.h> #include <media/video-buf.h>
#include <media/audiochip.h>
#include <media/tuner.h> #include <media/tuner.h>
#include <media/tveeprom.h> #include <media/tveeprom.h>
#include <media/ir-common.h> #include <media/ir-common.h>
...@@ -299,6 +298,8 @@ struct bttv { ...@@ -299,6 +298,8 @@ struct bttv {
int i2c_state, i2c_rc; int i2c_state, i2c_rc;
int i2c_done; int i2c_done;
wait_queue_head_t i2c_queue; wait_queue_head_t i2c_queue;
struct i2c_client *i2c_msp34xx_client;
struct i2c_client *i2c_tvaudio_client;
/* video4linux (1) */ /* video4linux (1) */
struct video_device *video_dev; struct video_device *video_dev;
...@@ -321,6 +322,7 @@ struct bttv { ...@@ -321,6 +322,7 @@ struct bttv {
/* video state */ /* video state */
unsigned int input; unsigned int input;
unsigned int audio; unsigned int audio;
unsigned int mute;
unsigned long freq; unsigned long freq;
int tvnorm,hue,contrast,bright,saturation; int tvnorm,hue,contrast,bright,saturation;
struct v4l2_framebuffer fbuf; struct v4l2_framebuffer fbuf;
......
...@@ -75,11 +75,6 @@ static int cs53l32a_command(struct i2c_client *client, unsigned int cmd, ...@@ -75,11 +75,6 @@ static int cs53l32a_command(struct i2c_client *client, unsigned int cmd,
cs53l32a_write(client, 0x01, 0x01 + (input->index << 4)); cs53l32a_write(client, 0x01, 0x01 + (input->index << 4));
break; break;
case VIDIOC_G_AUDIO:
memset(input, 0, sizeof(*input));
input->index = (cs53l32a_read(client, 0x01) >> 4) & 3;
break;
case VIDIOC_G_CTRL: case VIDIOC_G_CTRL:
if (ctrl->id == V4L2_CID_AUDIO_MUTE) { if (ctrl->id == V4L2_CID_AUDIO_MUTE) {
ctrl->value = (cs53l32a_read(client, 0x03) & 0xc0) != 0; ctrl->value = (cs53l32a_read(client, 0x03) & 0xc0) != 0;
......
...@@ -18,7 +18,6 @@ ...@@ -18,7 +18,6 @@
#include <linux/videodev2.h> #include <linux/videodev2.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <media/audiochip.h>
#include <media/v4l2-common.h> #include <media/v4l2-common.h>
#include "cx25840.h" #include "cx25840.h"
......
...@@ -31,7 +31,6 @@ ...@@ -31,7 +31,6 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/videodev2.h> #include <linux/videodev2.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <media/audiochip.h>
#include <media/v4l2-common.h> #include <media/v4l2-common.h>
#include "cx25840.h" #include "cx25840.h"
...@@ -764,16 +763,6 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd, ...@@ -764,16 +763,6 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd,
return set_input(client, state->vid_input, input->index); return set_input(client, state->vid_input, input->index);
} }
case VIDIOC_G_AUDIO:
{
struct v4l2_audio *input = arg;
memset(input, 0, sizeof(*input));
input->index = state->aud_input;
input->capability = V4L2_AUDCAP_STEREO;
break;
}
case VIDIOC_S_FREQUENCY: case VIDIOC_S_FREQUENCY:
input_change(client); input_change(client);
break; break;
......
...@@ -27,7 +27,6 @@ ...@@ -27,7 +27,6 @@
#include <media/tuner.h> #include <media/tuner.h>
#include <media/tveeprom.h> #include <media/tveeprom.h>
#include <media/audiochip.h>
#include <media/video-buf.h> #include <media/video-buf.h>
#include <media/video-buf-dvb.h> #include <media/video-buf-dvb.h>
......
...@@ -53,7 +53,7 @@ ...@@ -53,7 +53,7 @@
#include <linux/videodev.h> #include <linux/videodev.h>
#include <linux/videodev2.h> #include <linux/videodev2.h>
#include <media/v4l2-common.h> #include <media/v4l2-common.h>
#include <media/audiochip.h> #include <media/tvaudio.h>
#include <linux/kthread.h> #include <linux/kthread.h>
#include <linux/suspend.h> #include <linux/suspend.h>
#include "msp3400.h" #include "msp3400.h"
...@@ -585,51 +585,12 @@ static int msp_set_ctrl(struct i2c_client *client, struct v4l2_control *ctrl) ...@@ -585,51 +585,12 @@ static int msp_set_ctrl(struct i2c_client *client, struct v4l2_control *ctrl)
static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg)
{ {
struct msp_state *state = i2c_get_clientdata(client); struct msp_state *state = i2c_get_clientdata(client);
u16 *sarg = arg;
int scart = 0; int scart = 0;
if (msp_debug >= 2) if (msp_debug >= 2)
v4l_i2c_print_ioctl(client, cmd); v4l_i2c_print_ioctl(client, cmd);
switch (cmd) { switch (cmd) {
case AUDC_SET_INPUT:
if (*sarg == state->input)
break;
state->input = *sarg;
switch (*sarg) {
case AUDIO_RADIO:
/* Hauppauge uses IN2 for the radio */
state->mode = MSP_MODE_FM_RADIO;
scart = SCART_IN2;
break;
case AUDIO_EXTERN_1:
/* IN1 is often used for external input ... */
state->mode = MSP_MODE_EXTERN;
scart = SCART_IN1;
break;
case AUDIO_EXTERN_2:
/* ... sometimes it is IN2 through ;) */
state->mode = MSP_MODE_EXTERN;
scart = SCART_IN2;
break;
case AUDIO_TUNER:
state->mode = -1;
break;
default:
if (*sarg & AUDIO_MUTE)
msp_set_scart(client, SCART_MUTE, 0);
break;
}
if (scart) {
state->rxsubchans = V4L2_TUNER_SUB_STEREO;
msp_set_scart(client, scart, 0);
msp_write_dsp(client, 0x000d, 0x1900);
if (state->opmode != OPMODE_AUTOSELECT)
msp_set_audmode(client);
}
msp_wake_thread(client);
break;
case AUDC_SET_RADIO: case AUDC_SET_RADIO:
if (state->radio) if (state->radio)
return 0; return 0;
...@@ -750,82 +711,27 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) ...@@ -750,82 +711,27 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg)
return 0; return 0;
} }
case VIDIOC_ENUMINPUT:
{
struct v4l2_input *i = arg;
if (i->index != 0)
return -EINVAL;
i->type = V4L2_INPUT_TYPE_TUNER;
switch (i->index) {
case AUDIO_RADIO:
strcpy(i->name, "Radio");
break;
case AUDIO_EXTERN_1:
strcpy(i->name, "Extern 1");
break;
case AUDIO_EXTERN_2:
strcpy(i->name, "Extern 2");
break;
case AUDIO_TUNER:
strcpy(i->name, "Television");
break;
default:
return -EINVAL;
}
return 0;
}
case VIDIOC_G_AUDIO:
{
struct v4l2_audio *a = arg;
memset(a, 0, sizeof(*a));
switch (a->index) {
case AUDIO_RADIO:
strcpy(a->name, "Radio");
break;
case AUDIO_EXTERN_1:
strcpy(a->name, "Extern 1");
break;
case AUDIO_EXTERN_2:
strcpy(a->name, "Extern 2");
break;
case AUDIO_TUNER:
strcpy(a->name, "Television");
break;
default:
return -EINVAL;
}
a->capability = V4L2_AUDCAP_STEREO;
a->mode = 0; /* TODO: add support for AVL */
break;
}
case VIDIOC_S_AUDIO: case VIDIOC_S_AUDIO:
{ {
struct v4l2_audio *sarg = arg; struct v4l2_audio *sarg = arg;
switch (sarg->index) { switch (sarg->index) {
case AUDIO_RADIO: case TVAUDIO_INPUT_RADIO:
/* Hauppauge uses IN2 for the radio */ /* Hauppauge uses IN2 for the radio */
state->mode = MSP_MODE_FM_RADIO; state->mode = MSP_MODE_FM_RADIO;
scart = SCART_IN2; scart = SCART_IN2;
break; break;
case AUDIO_EXTERN_1: case TVAUDIO_INPUT_EXTERN:
/* IN1 is often used for external input ... */ /* IN1 is often used for external input ... */
state->mode = MSP_MODE_EXTERN; state->mode = MSP_MODE_EXTERN;
scart = SCART_IN1; scart = SCART_IN1;
break; break;
case AUDIO_EXTERN_2: case TVAUDIO_INPUT_INTERN:
/* ... sometimes it is IN2 through ;) */ /* ... sometimes it is IN2 through ;) */
state->mode = MSP_MODE_EXTERN; state->mode = MSP_MODE_EXTERN;
scart = SCART_IN2; scart = SCART_IN2;
break; break;
case AUDIO_TUNER: case TVAUDIO_INPUT_TUNER:
state->mode = -1; state->mode = -1;
break; break;
} }
......
...@@ -26,7 +26,6 @@ ...@@ -26,7 +26,6 @@
#include <linux/videodev.h> #include <linux/videodev.h>
#include <linux/videodev2.h> #include <linux/videodev2.h>
#include <media/v4l2-common.h> #include <media/v4l2-common.h>
#include <media/audiochip.h>
#include <linux/kthread.h> #include <linux/kthread.h>
#include <linux/suspend.h> #include <linux/suspend.h>
#include "msp3400.h" #include "msp3400.h"
......
...@@ -40,7 +40,6 @@ ...@@ -40,7 +40,6 @@
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/videodev2.h> #include <linux/videodev2.h>
#include <media/v4l2-common.h> #include <media/v4l2-common.h>
#include <media/audiochip.h>
#include <asm/div64.h> #include <asm/div64.h>
MODULE_DESCRIPTION("Philips SAA7113/SAA7114/SAA7115 video decoder driver"); MODULE_DESCRIPTION("Philips SAA7113/SAA7114/SAA7115 video decoder driver");
......
...@@ -34,7 +34,6 @@ ...@@ -34,7 +34,6 @@
#include <asm/io.h> #include <asm/io.h>
#include <media/tuner.h> #include <media/tuner.h>
#include <media/audiochip.h>
#include <media/ir-common.h> #include <media/ir-common.h>
#include <media/ir-kbd-i2c.h> #include <media/ir-kbd-i2c.h>
#include <media/video-buf.h> #include <media/video-buf.h>
......
...@@ -48,7 +48,6 @@ ...@@ -48,7 +48,6 @@
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/i2c-algo-bit.h> #include <linux/i2c-algo-bit.h>
#include <media/audiochip.h>
#include <media/v4l2-common.h> #include <media/v4l2-common.h>
#include <media/i2c-addr.h> #include <media/i2c-addr.h>
......
...@@ -30,7 +30,6 @@ ...@@ -30,7 +30,6 @@
#include <linux/i2c-algo-bit.h> #include <linux/i2c-algo-bit.h>
#include <linux/init.h> #include <linux/init.h>
#include <media/audiochip.h>
#include <media/i2c-addr.h> #include <media/i2c-addr.h>
...@@ -47,7 +46,6 @@ I2C_CLIENT_INSMOD; ...@@ -47,7 +46,6 @@ I2C_CLIENT_INSMOD;
/* This is a superset of the TDA9875 */ /* This is a superset of the TDA9875 */
struct tda9875 { struct tda9875 {
int mode;
int rvol, lvol; int rvol, lvol;
int bass, treble; int bass, treble;
struct i2c_client c; struct i2c_client c;
...@@ -197,7 +195,6 @@ static void do_tda9875_init(struct i2c_client *client) ...@@ -197,7 +195,6 @@ static void do_tda9875_init(struct i2c_client *client)
tda9875_write(client, TDA9875_MUT, 0xcc ); /* General mute */ tda9875_write(client, TDA9875_MUT, 0xcc ); /* General mute */
t->mode=AUDIO_UNMUTE;
t->lvol=t->rvol =0; /* 0dB */ t->lvol=t->rvol =0; /* 0dB */
t->bass=0; /* 0dB */ t->bass=0; /* 0dB */
t->treble=0; /* 0dB */ t->treble=0; /* 0dB */
......
...@@ -21,7 +21,6 @@ ...@@ -21,7 +21,6 @@
#include <media/tuner.h> #include <media/tuner.h>
#include <media/v4l2-common.h> #include <media/v4l2-common.h>
#include <media/audiochip.h>
#define UNSET (-1U) #define UNSET (-1U)
......
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/smp_lock.h> #include <linux/smp_lock.h>
#include <media/audiochip.h> #include <media/tvaudio.h>
#include <media/v4l2-common.h> #include <media/v4l2-common.h>
#include <media/i2c-addr.h> #include <media/i2c-addr.h>
...@@ -102,7 +102,7 @@ struct CHIPDESC { ...@@ -102,7 +102,7 @@ struct CHIPDESC {
/* input switch register + values for v4l inputs */ /* input switch register + values for v4l inputs */
int inputreg; int inputreg;
int inputmap[8]; int inputmap[4];
int inputmute; int inputmute;
int inputmask; int inputmask;
}; };
...@@ -119,9 +119,10 @@ struct CHIPSTATE { ...@@ -119,9 +119,10 @@ struct CHIPSTATE {
audiocmd shadow; audiocmd shadow;
/* current settings */ /* current settings */
__u16 left,right,treble,bass,mode; __u16 left,right,treble,bass,muted,mode;
int prevmode; int prevmode;
int radio; int radio;
int input;
/* thread */ /* thread */
pid_t tpid; pid_t tpid;
...@@ -1101,9 +1102,8 @@ static int tda8425_shift12(int val) { return (val >> 12) | 0xf0; } ...@@ -1101,9 +1102,8 @@ static int tda8425_shift12(int val) { return (val >> 12) | 0xf0; }
static int tda8425_initialize(struct CHIPSTATE *chip) static int tda8425_initialize(struct CHIPSTATE *chip)
{ {
struct CHIPDESC *desc = chiplist + chip->type; struct CHIPDESC *desc = chiplist + chip->type;
int inputmap[8] = { /* tuner */ TDA8425_S1_CH2, /* radio */ TDA8425_S1_CH1, int inputmap[4] = { /* tuner */ TDA8425_S1_CH2, /* radio */ TDA8425_S1_CH1,
/* extern */ TDA8425_S1_CH1, /* intern */ TDA8425_S1_OFF, /* extern */ TDA8425_S1_CH1, /* intern */ TDA8425_S1_OFF};
/* off */ TDA8425_S1_OFF, /* on */ TDA8425_S1_CH2};
if (chip->c.adapter->id == I2C_HW_B_RIVA) { if (chip->c.adapter->id == I2C_HW_B_RIVA) {
memcpy (desc->inputmap, inputmap, sizeof (inputmap)); memcpy (desc->inputmap, inputmap, sizeof (inputmap));
...@@ -1298,7 +1298,7 @@ static struct CHIPDESC chiplist[] = { ...@@ -1298,7 +1298,7 @@ static struct CHIPDESC chiplist[] = {
.init = { 4, { TDA9873_SW, 0xa4, 0x06, 0x03 } }, .init = { 4, { TDA9873_SW, 0xa4, 0x06, 0x03 } },
.inputreg = TDA9873_SW, .inputreg = TDA9873_SW,
.inputmute = TDA9873_MUTE | TDA9873_AUTOMUTE, .inputmute = TDA9873_MUTE | TDA9873_AUTOMUTE,
.inputmap = {0xa0, 0xa2, 0xa0, 0xa0, 0xc0}, .inputmap = {0xa0, 0xa2, 0xa0, 0xa0},
.inputmask = TDA9873_INP_MASK|TDA9873_MUTE|TDA9873_AUTOMUTE, .inputmask = TDA9873_INP_MASK|TDA9873_MUTE|TDA9873_AUTOMUTE,
}, },
...@@ -1446,8 +1446,7 @@ static struct CHIPDESC chiplist[] = { ...@@ -1446,8 +1446,7 @@ static struct CHIPDESC chiplist[] = {
.inputmap = {PIC16C54_MISC_SND_NOTMUTE|PIC16C54_MISC_SWITCH_TUNER, .inputmap = {PIC16C54_MISC_SND_NOTMUTE|PIC16C54_MISC_SWITCH_TUNER,
PIC16C54_MISC_SND_NOTMUTE|PIC16C54_MISC_SWITCH_LINE, PIC16C54_MISC_SND_NOTMUTE|PIC16C54_MISC_SWITCH_LINE,
PIC16C54_MISC_SND_NOTMUTE|PIC16C54_MISC_SWITCH_LINE, PIC16C54_MISC_SND_NOTMUTE|PIC16C54_MISC_SWITCH_LINE,
PIC16C54_MISC_SND_MUTE,PIC16C54_MISC_SND_MUTE, PIC16C54_MISC_SND_MUTE},
PIC16C54_MISC_SND_NOTMUTE},
.inputmute = PIC16C54_MISC_SND_MUTE, .inputmute = PIC16C54_MISC_SND_MUTE,
}, },
{ {
...@@ -1583,28 +1582,40 @@ static int chip_detach(struct i2c_client *client) ...@@ -1583,28 +1582,40 @@ static int chip_detach(struct i2c_client *client)
return 0; return 0;
} }
static int tvaudio_set_ctrl(struct CHIPSTATE *chip, struct v4l2_control *ctrl)
{
struct CHIPDESC *desc = chiplist + chip->type;
switch (ctrl->id) {
case V4L2_CID_AUDIO_MUTE:
if (ctrl->value < 0 || ctrl->value >= 2)
return -ERANGE;
chip->muted = ctrl->value;
if (chip->muted)
chip_write_masked(chip,desc->inputreg,desc->inputmute,desc->inputmask);
else
chip_write_masked(chip,desc->inputreg,
desc->inputmap[chip->input],desc->inputmask);
break;
default:
return -EINVAL;
}
return 0;
}
/* ---------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- */
/* video4linux interface */ /* video4linux interface */
static int chip_command(struct i2c_client *client, static int chip_command(struct i2c_client *client,
unsigned int cmd, void *arg) unsigned int cmd, void *arg)
{ {
__u16 *sarg = arg;
struct CHIPSTATE *chip = i2c_get_clientdata(client); struct CHIPSTATE *chip = i2c_get_clientdata(client);
struct CHIPDESC *desc = chiplist + chip->type; struct CHIPDESC *desc = chiplist + chip->type;
v4l_dbg(1, debug, &chip->c, "%s: chip_command 0x%x\n", chip->c.name, cmd); v4l_dbg(1, debug, &chip->c, "%s: chip_command 0x%x\n", chip->c.name, cmd);
switch (cmd) { switch (cmd) {
case AUDC_SET_INPUT:
if (desc->flags & CHIP_HAS_INPUTSEL) {
if (*sarg & 0x80)
chip_write_masked(chip,desc->inputreg,desc->inputmute,desc->inputmask);
else
chip_write_masked(chip,desc->inputreg,desc->inputmap[*sarg],desc->inputmask);
}
break;
case AUDC_SET_RADIO: case AUDC_SET_RADIO:
chip->radio = 1; chip->radio = 1;
chip->watch_stereo = 0; chip->watch_stereo = 0;
...@@ -1668,6 +1679,24 @@ static int chip_command(struct i2c_client *client, ...@@ -1668,6 +1679,24 @@ static int chip_command(struct i2c_client *client,
break; break;
} }
case VIDIOC_S_CTRL:
return tvaudio_set_ctrl(chip, arg);
case VIDIOC_S_AUDIO:
{
struct v4l2_audio *sarg = arg;
if (!(desc->flags & CHIP_HAS_INPUTSEL) || sarg->index >= 4)
return -EINVAL;
/* There are four inputs: tuner, radio, extern and intern. */
chip->input = sarg->index;
if (chip->muted)
break;
chip_write_masked(chip, desc->inputreg,
desc->inputmap[chip->input], desc->inputmask);
break;
}
case VIDIOC_S_TUNER: case VIDIOC_S_TUNER:
{ {
struct v4l2_tuner *vt = arg; struct v4l2_tuner *vt = arg;
......
...@@ -248,32 +248,32 @@ audioIC[] = ...@@ -248,32 +248,32 @@ audioIC[] =
{AUDIO_CHIP_MSP34XX, "MSP3410D"}, {AUDIO_CHIP_MSP34XX, "MSP3410D"},
{AUDIO_CHIP_MSP34XX, "MSP3415"}, {AUDIO_CHIP_MSP34XX, "MSP3415"},
{AUDIO_CHIP_MSP34XX, "MSP3430"}, {AUDIO_CHIP_MSP34XX, "MSP3430"},
{AUDIO_CHIP_UNKNOWN, "MSP3438"}, {AUDIO_CHIP_MSP34XX, "MSP3438"},
{AUDIO_CHIP_UNKNOWN, "CS5331"}, {AUDIO_CHIP_UNKNOWN, "CS5331"},
/* 10-14 */ /* 10-14 */
{AUDIO_CHIP_MSP34XX, "MSP3435"}, {AUDIO_CHIP_MSP34XX, "MSP3435"},
{AUDIO_CHIP_MSP34XX, "MSP3440"}, {AUDIO_CHIP_MSP34XX, "MSP3440"},
{AUDIO_CHIP_MSP34XX, "MSP3445"}, {AUDIO_CHIP_MSP34XX, "MSP3445"},
{AUDIO_CHIP_UNKNOWN, "MSP3411"}, {AUDIO_CHIP_MSP34XX, "MSP3411"},
{AUDIO_CHIP_UNKNOWN, "MSP3416"}, {AUDIO_CHIP_MSP34XX, "MSP3416"},
/* 15-19 */ /* 15-19 */
{AUDIO_CHIP_MSP34XX, "MSP3425"}, {AUDIO_CHIP_MSP34XX, "MSP3425"},
{AUDIO_CHIP_UNKNOWN, "MSP3451"}, {AUDIO_CHIP_MSP34XX, "MSP3451"},
{AUDIO_CHIP_UNKNOWN, "MSP3418"}, {AUDIO_CHIP_MSP34XX, "MSP3418"},
{AUDIO_CHIP_UNKNOWN, "Type 0x12"}, {AUDIO_CHIP_UNKNOWN, "Type 0x12"},
{AUDIO_CHIP_UNKNOWN, "OKI7716"}, {AUDIO_CHIP_UNKNOWN, "OKI7716"},
/* 20-24 */ /* 20-24 */
{AUDIO_CHIP_UNKNOWN, "MSP4410"}, {AUDIO_CHIP_MSP34XX, "MSP4410"},
{AUDIO_CHIP_UNKNOWN, "MSP4420"}, {AUDIO_CHIP_MSP34XX, "MSP4420"},
{AUDIO_CHIP_UNKNOWN, "MSP4440"}, {AUDIO_CHIP_MSP34XX, "MSP4440"},
{AUDIO_CHIP_UNKNOWN, "MSP4450"}, {AUDIO_CHIP_MSP34XX, "MSP4450"},
{AUDIO_CHIP_UNKNOWN, "MSP4408"}, {AUDIO_CHIP_MSP34XX, "MSP4408"},
/* 25-29 */ /* 25-29 */
{AUDIO_CHIP_UNKNOWN, "MSP4418"}, {AUDIO_CHIP_MSP34XX, "MSP4418"},
{AUDIO_CHIP_UNKNOWN, "MSP4428"}, {AUDIO_CHIP_MSP34XX, "MSP4428"},
{AUDIO_CHIP_UNKNOWN, "MSP4448"}, {AUDIO_CHIP_MSP34XX, "MSP4448"},
{AUDIO_CHIP_UNKNOWN, "MSP4458"}, {AUDIO_CHIP_MSP34XX, "MSP4458"},
{AUDIO_CHIP_UNKNOWN, "Type 0x1d"}, {AUDIO_CHIP_MSP34XX, "Type 0x1d"},
/* 30-34 */ /* 30-34 */
{AUDIO_CHIP_INTERNAL, "CX880"}, {AUDIO_CHIP_INTERNAL, "CX880"},
{AUDIO_CHIP_INTERNAL, "CX881"}, {AUDIO_CHIP_INTERNAL, "CX881"},
......
...@@ -312,7 +312,6 @@ static const char *v4l2_int_ioctls[] = { ...@@ -312,7 +312,6 @@ static const char *v4l2_int_ioctls[] = {
[_IOC_NR(DECODER_DUMP)] = "DECODER_DUMP", [_IOC_NR(DECODER_DUMP)] = "DECODER_DUMP",
#endif #endif
[_IOC_NR(AUDC_SET_RADIO)] = "AUDC_SET_RADIO", [_IOC_NR(AUDC_SET_RADIO)] = "AUDC_SET_RADIO",
[_IOC_NR(AUDC_SET_INPUT)] = "AUDC_SET_INPUT",
[_IOC_NR(MSP_SET_MATRIX)] = "MSP_SET_MATRIX", [_IOC_NR(MSP_SET_MATRIX)] = "MSP_SET_MATRIX",
[_IOC_NR(TUNER_SET_TYPE_ADDR)] = "TUNER_SET_TYPE_ADDR", [_IOC_NR(TUNER_SET_TYPE_ADDR)] = "TUNER_SET_TYPE_ADDR",
...@@ -419,7 +418,6 @@ void v4l_printk_ioctl_arg(char *s,unsigned int cmd, void *arg) ...@@ -419,7 +418,6 @@ void v4l_printk_ioctl_arg(char *s,unsigned int cmd, void *arg)
case TUNER_SET_TYPE_ADDR: case TUNER_SET_TYPE_ADDR:
case TUNER_SET_STANDBY: case TUNER_SET_STANDBY:
case TDA9887_SET_CONFIG: case TDA9887_SET_CONFIG:
case AUDC_SET_INPUT:
case VIDIOC_OVERLAY_OLD: case VIDIOC_OVERLAY_OLD:
case VIDIOC_STREAMOFF: case VIDIOC_STREAMOFF:
case VIDIOC_G_OUTPUT: case VIDIOC_G_OUTPUT:
......
...@@ -102,11 +102,6 @@ static int wm8775_command(struct i2c_client *client, unsigned int cmd, ...@@ -102,11 +102,6 @@ static int wm8775_command(struct i2c_client *client, unsigned int cmd,
wm8775_write(client, R21, 0x100 + state->input); wm8775_write(client, R21, 0x100 + state->input);
break; break;
case VIDIOC_G_AUDIO:
memset(input, 0, sizeof(*input));
input->index = state->input;
break;
case VIDIOC_G_CTRL: case VIDIOC_G_CTRL:
if (ctrl->id != V4L2_CID_AUDIO_MUTE) if (ctrl->id != V4L2_CID_AUDIO_MUTE)
return -EINVAL; return -EINVAL;
......
...@@ -21,18 +21,4 @@ enum audiochip { ...@@ -21,18 +21,4 @@ enum audiochip {
AUDIO_CHIP_MSP34XX AUDIO_CHIP_MSP34XX
}; };
/* ---------------------------------------------------------------------- */
/* audio inputs */
#define AUDIO_TUNER 0x00
#define AUDIO_RADIO 0x01
#define AUDIO_EXTERN 0x02
#define AUDIO_INTERN 0x03
#define AUDIO_OFF 0x04
#define AUDIO_ON 0x05
#define AUDIO_EXTERN_1 AUDIO_EXTERN
#define AUDIO_EXTERN_2 0x06
#define AUDIO_MUTE 0x80
#define AUDIO_UNMUTE 0x81
#endif /* AUDIOCHIP_H */ #endif /* AUDIOCHIP_H */
/*
tvaudio.h - definition for tvaudio inputs
Copyright (C) 2006 Hans Verkuil (hverkuil@xs4all.nl)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef _TVAUDIO_H
#define _TVAUDIO_H
/* The tvaudio module accepts the following inputs: */
#define TVAUDIO_INPUT_TUNER 0
#define TVAUDIO_INPUT_RADIO 1
#define TVAUDIO_INPUT_EXTERN 2
#define TVAUDIO_INPUT_INTERN 3
#endif
...@@ -123,9 +123,6 @@ enum v4l2_chip_ident { ...@@ -123,9 +123,6 @@ enum v4l2_chip_ident {
/* v4l device was opened in Radio mode, to be replaced by VIDIOC_INT_S_TUNER_MODE */ /* v4l device was opened in Radio mode, to be replaced by VIDIOC_INT_S_TUNER_MODE */
#define AUDC_SET_RADIO _IO('d',88) #define AUDC_SET_RADIO _IO('d',88)
/* select from TV,radio,extern,MUTE, to be replaced with VIDIOC_INT_S_AUDIO_ROUTING */
#define AUDC_SET_INPUT _IOW('d',89,int)
/* msp3400 ioctl: will be removed in the near future, to be replaced by /* msp3400 ioctl: will be removed in the near future, to be replaced by
VIDIOC_INT_S_AUDIO_ROUTING. */ VIDIOC_INT_S_AUDIO_ROUTING. */
struct msp_matrix { struct msp_matrix {
...@@ -209,10 +206,10 @@ struct v4l2_routing { ...@@ -209,10 +206,10 @@ struct v4l2_routing {
}; };
/* These internal commands should be used to define the inputs and outputs /* These internal commands should be used to define the inputs and outputs
of an audio/video chip. They will replace AUDC_SET_INPUT. of an audio/video chip. They will replace the v4l2 API commands
The v4l2 API commands VIDIOC_S/G_INPUT, VIDIOC_S/G_OUTPUT, VIDIOC_S/G_INPUT, VIDIOC_S/G_OUTPUT, VIDIOC_S/G_AUDIO and VIDIOC_S/G_AUDOUT
VIDIOC_S/G_AUDIO and VIDIOC_S/G_AUDOUT are meant to be used by the that are meant to be used by the user.
user. Internally these commands should be used to switch inputs/outputs The internal commands should be used to switch inputs/outputs
because only the driver knows how to map a 'Television' input to the precise because only the driver knows how to map a 'Television' input to the precise
input/output routing of an A/D converter, or a DSP, or a video digitizer. input/output routing of an A/D converter, or a DSP, or a video digitizer.
These four commands should only be sent directly to an i2c device, they These four commands should only be sent directly to an i2c device, they
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment