mirror of
https://github.com/torvalds/linux.git
synced 2024-12-25 12:21:37 +00:00
V4L/DVB (3099): Fixed device controls for em28xx on WinTV USB2 devices
- Controls now come from video and audio decoder driver for msp3400 and tvp5150. - Added audio and sound controls as provided by msp3400 and tvp5150. Signed-off-by: Mauro Carvalho Chehab <mchehab@brturbo.com.br>
This commit is contained in:
parent
c432a072b6
commit
c0477ad9fe
@ -32,6 +32,7 @@
|
||||
|
||||
#include "em28xx.h"
|
||||
#include <media/tuner.h>
|
||||
#include <media/v4l2-common.h>
|
||||
|
||||
#define DRIVER_AUTHOR "Ludovico Cavedon <cavedon@sssup.it>, " \
|
||||
"Markus Rechberger <mrechberger@gmail.com>, " \
|
||||
@ -106,7 +107,31 @@ static const unsigned char saa7114_i2c_init[] = {
|
||||
#define TVNORMS ARRAY_SIZE(tvnorms)
|
||||
|
||||
/* supported controls */
|
||||
/* Common to all boards */
|
||||
static struct v4l2_queryctrl em28xx_qctrl[] = {
|
||||
{
|
||||
.id = V4L2_CID_AUDIO_VOLUME,
|
||||
.type = V4L2_CTRL_TYPE_INTEGER,
|
||||
.name = "Volume",
|
||||
.minimum = 0x0,
|
||||
.maximum = 0x1f,
|
||||
.step = 0x1,
|
||||
.default_value = 0x1f,
|
||||
.flags = 0,
|
||||
},{
|
||||
.id = V4L2_CID_AUDIO_MUTE,
|
||||
.type = V4L2_CTRL_TYPE_BOOLEAN,
|
||||
.name = "Mute",
|
||||
.minimum = 0,
|
||||
.maximum = 1,
|
||||
.step = 1,
|
||||
.default_value = 1,
|
||||
.flags = 0,
|
||||
}
|
||||
};
|
||||
|
||||
/* FIXME: These are specific to saa711x - should be moved to its code */
|
||||
static struct v4l2_queryctrl saa711x_qctrl[] = {
|
||||
{
|
||||
.id = V4L2_CID_BRIGHTNESS,
|
||||
.type = V4L2_CTRL_TYPE_INTEGER,
|
||||
@ -134,24 +159,6 @@ static struct v4l2_queryctrl em28xx_qctrl[] = {
|
||||
.step = 0x1,
|
||||
.default_value = 0x10,
|
||||
.flags = 0,
|
||||
},{
|
||||
.id = V4L2_CID_AUDIO_VOLUME,
|
||||
.type = V4L2_CTRL_TYPE_INTEGER,
|
||||
.name = "Volume",
|
||||
.minimum = 0x0,
|
||||
.maximum = 0x1f,
|
||||
.step = 0x1,
|
||||
.default_value = 0x1f,
|
||||
.flags = 0,
|
||||
},{
|
||||
.id = V4L2_CID_AUDIO_MUTE,
|
||||
.type = V4L2_CTRL_TYPE_BOOLEAN,
|
||||
.name = "Mute",
|
||||
.minimum = 0,
|
||||
.maximum = 1,
|
||||
.step = 1,
|
||||
.default_value = 1,
|
||||
.flags = 0,
|
||||
},{
|
||||
.id = V4L2_CID_RED_BALANCE,
|
||||
.type = V4L2_CTRL_TYPE_INTEGER,
|
||||
@ -179,7 +186,7 @@ static struct v4l2_queryctrl em28xx_qctrl[] = {
|
||||
.step = 0x1,
|
||||
.default_value = 0x20,
|
||||
.flags = 0,
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static struct usb_driver em28xx_usb_driver;
|
||||
@ -674,7 +681,6 @@ static int em28xx_v4l2_mmap(struct file *filp, struct vm_area_struct *vma)
|
||||
*/
|
||||
static int em28xx_get_ctrl(struct em28xx *dev, struct v4l2_control *ctrl)
|
||||
{
|
||||
s32 tmp;
|
||||
switch (ctrl->id) {
|
||||
case V4L2_CID_AUDIO_MUTE:
|
||||
ctrl->value = dev->mute;
|
||||
@ -682,6 +688,16 @@ static int em28xx_get_ctrl(struct em28xx *dev, struct v4l2_control *ctrl)
|
||||
case V4L2_CID_AUDIO_VOLUME:
|
||||
ctrl->value = dev->volume;
|
||||
return 0;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
/*FIXME: should be moved to saa711x */
|
||||
static int saa711x_get_ctrl(struct em28xx *dev, struct v4l2_control *ctrl)
|
||||
{
|
||||
s32 tmp;
|
||||
switch (ctrl->id) {
|
||||
case V4L2_CID_BRIGHTNESS:
|
||||
if ((tmp = em28xx_brightness_get(dev)) < 0)
|
||||
return -EIO;
|
||||
@ -731,6 +747,15 @@ static int em28xx_set_ctrl(struct em28xx *dev, const struct v4l2_control *ctrl)
|
||||
case V4L2_CID_AUDIO_VOLUME:
|
||||
dev->volume = ctrl->value;
|
||||
return em28xx_audio_analog_set(dev);
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
/*FIXME: should be moved to saa711x */
|
||||
static int saa711x_set_ctrl(struct em28xx *dev, const struct v4l2_control *ctrl)
|
||||
{
|
||||
switch (ctrl->id) {
|
||||
case V4L2_CID_BRIGHTNESS:
|
||||
return em28xx_brightness_set(dev, ctrl->value);
|
||||
case V4L2_CID_CONTRAST:
|
||||
@ -994,14 +1019,34 @@ static int em28xx_do_ioctl(struct inode *inode, struct file *filp,
|
||||
case VIDIOC_QUERYCTRL:
|
||||
{
|
||||
struct v4l2_queryctrl *qc = arg;
|
||||
u8 i, n;
|
||||
n = sizeof(em28xx_qctrl) / sizeof(em28xx_qctrl[0]);
|
||||
for (i = 0; i < n; i++)
|
||||
if (qc->id && qc->id == em28xx_qctrl[i].id) {
|
||||
memcpy(qc, &(em28xx_qctrl[i]),
|
||||
int i, id=qc->id;
|
||||
|
||||
memset(qc,0,sizeof(*qc));
|
||||
qc->id=id;
|
||||
|
||||
if (!dev->has_msp34xx) {
|
||||
for (i = 0; i < ARRAY_SIZE(em28xx_qctrl); i++) {
|
||||
if (qc->id && qc->id == em28xx_qctrl[i].id) {
|
||||
memcpy(qc, &(em28xx_qctrl[i]),
|
||||
sizeof(*qc));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (dev->decoder == EM28XX_TVP5150) {
|
||||
em28xx_i2c_call_clients(dev,cmd,qc);
|
||||
if (qc->type)
|
||||
return 0;
|
||||
else
|
||||
return -EINVAL;
|
||||
}
|
||||
for (i = 0; i < ARRAY_SIZE(saa711x_qctrl); i++) {
|
||||
if (qc->id && qc->id == saa711x_qctrl[i].id) {
|
||||
memcpy(qc, &(saa711x_qctrl[i]),
|
||||
sizeof(*qc));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
@ -1009,29 +1054,66 @@ static int em28xx_do_ioctl(struct inode *inode, struct file *filp,
|
||||
case VIDIOC_G_CTRL:
|
||||
{
|
||||
struct v4l2_control *ctrl = arg;
|
||||
int retval=-EINVAL;
|
||||
|
||||
if (!dev->has_msp34xx)
|
||||
retval=em28xx_get_ctrl(dev, ctrl);
|
||||
if (retval==-EINVAL) {
|
||||
if (dev->decoder == EM28XX_TVP5150) {
|
||||
em28xx_i2c_call_clients(dev,cmd,arg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return em28xx_get_ctrl(dev, ctrl);
|
||||
return saa711x_get_ctrl(dev, ctrl);
|
||||
} else return retval;
|
||||
}
|
||||
|
||||
case VIDIOC_S_CTRL_OLD: /* ??? */
|
||||
case VIDIOC_S_CTRL:
|
||||
{
|
||||
struct v4l2_control *ctrl = arg;
|
||||
u8 i, n;
|
||||
u8 i;
|
||||
|
||||
|
||||
n = sizeof(em28xx_qctrl) / sizeof(em28xx_qctrl[0]);
|
||||
for (i = 0; i < n; i++)
|
||||
if (ctrl->id == em28xx_qctrl[i].id) {
|
||||
if (ctrl->value <
|
||||
em28xx_qctrl[i].minimum
|
||||
|| ctrl->value >
|
||||
em28xx_qctrl[i].maximum)
|
||||
return -ERANGE;
|
||||
|
||||
return em28xx_set_ctrl(dev, ctrl);
|
||||
if (!dev->has_msp34xx){
|
||||
for (i = 0; i < ARRAY_SIZE(em28xx_qctrl); i++) {
|
||||
if (ctrl->id == em28xx_qctrl[i].id) {
|
||||
if (ctrl->value <
|
||||
em28xx_qctrl[i].minimum
|
||||
|| ctrl->value >
|
||||
em28xx_qctrl[i].maximum)
|
||||
return -ERANGE;
|
||||
return em28xx_set_ctrl(dev, ctrl);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (dev->decoder == EM28XX_TVP5150) {
|
||||
em28xx_i2c_call_clients(dev,cmd,arg);
|
||||
return 0;
|
||||
} else {
|
||||
|
||||
if (!dev->has_msp34xx){
|
||||
for (i = 0; i < ARRAY_SIZE(em28xx_qctrl); i++) {
|
||||
if (ctrl->id == em28xx_qctrl[i].id) {
|
||||
if (ctrl->value <
|
||||
em28xx_qctrl[i].minimum
|
||||
|| ctrl->value >
|
||||
em28xx_qctrl[i].maximum)
|
||||
return -ERANGE;
|
||||
return em28xx_set_ctrl(dev, ctrl);
|
||||
}
|
||||
}
|
||||
for (i = 0; i < ARRAY_SIZE(saa711x_qctrl); i++) {
|
||||
if (ctrl->id == saa711x_qctrl[i].id) {
|
||||
if (ctrl->value <
|
||||
saa711x_qctrl[i].minimum
|
||||
|| ctrl->value >
|
||||
saa711x_qctrl[i].maximum)
|
||||
return -ERANGE;
|
||||
return saa711x_set_ctrl(dev, ctrl);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -1850,9 +1932,12 @@ static void em28xx_usb_disconnect(struct usb_interface *interface)
|
||||
struct em28xx *dev = usb_get_intfdata(interface);
|
||||
usb_set_intfdata(interface, NULL);
|
||||
|
||||
/*FIXME: IR should be disconnected */
|
||||
|
||||
if (!dev)
|
||||
return;
|
||||
|
||||
|
||||
down_write(&em28xx_disconnect);
|
||||
|
||||
down(&dev->lock);
|
||||
|
@ -1642,6 +1642,45 @@ static void msp_any_detect_stereo(struct i2c_client *client)
|
||||
}
|
||||
}
|
||||
|
||||
static struct v4l2_queryctrl msp34xx_qctrl[] = {
|
||||
{
|
||||
.id = V4L2_CID_AUDIO_VOLUME,
|
||||
.name = "Volume",
|
||||
.minimum = 0,
|
||||
.maximum = 65535,
|
||||
.step = 65535/100,
|
||||
.default_value = 58880,
|
||||
.flags = 0,
|
||||
.type = V4L2_CTRL_TYPE_INTEGER,
|
||||
},{
|
||||
.id = V4L2_CID_AUDIO_MUTE,
|
||||
.name = "Mute",
|
||||
.minimum = 0,
|
||||
.maximum = 1,
|
||||
.step = 1,
|
||||
.default_value = 1,
|
||||
.flags = 0,
|
||||
.type = V4L2_CTRL_TYPE_BOOLEAN,
|
||||
},{
|
||||
.id = V4L2_CID_AUDIO_BASS,
|
||||
.name = "Bass",
|
||||
.minimum = 0,
|
||||
.maximum = 65535,
|
||||
.step = 65535/100,
|
||||
.default_value = 32768,
|
||||
.type = V4L2_CTRL_TYPE_INTEGER,
|
||||
},{
|
||||
.id = V4L2_CID_AUDIO_TREBLE,
|
||||
.name = "Treble",
|
||||
.minimum = 0,
|
||||
.maximum = 65535,
|
||||
.step = 65535/100,
|
||||
.default_value = 32768,
|
||||
.type = V4L2_CTRL_TYPE_INTEGER,
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
static void msp_any_set_audmode(struct i2c_client *client, int audmode)
|
||||
{
|
||||
struct msp3400c *msp = i2c_get_clientdata(client);
|
||||
@ -1658,6 +1697,95 @@ static void msp_any_set_audmode(struct i2c_client *client, int audmode)
|
||||
}
|
||||
}
|
||||
|
||||
static int msp_get_ctrl(struct i2c_client *client, struct v4l2_control *ctrl)
|
||||
{
|
||||
struct msp3400c *msp = i2c_get_clientdata(client);
|
||||
|
||||
switch (ctrl->id) {
|
||||
case V4L2_CID_AUDIO_MUTE:
|
||||
ctrl->value = msp->muted;
|
||||
return 0;
|
||||
case V4L2_CID_AUDIO_BALANCE:
|
||||
{
|
||||
int volume = MAX(msp->left, msp->right);
|
||||
|
||||
ctrl->value = (32768 * MIN(msp->left, msp->right)) /
|
||||
(volume ? volume : 1);
|
||||
ctrl->value = (msp->left < msp->right) ?
|
||||
(65535 - ctrl->value) : ctrl->value;
|
||||
if (0 == volume)
|
||||
ctrl->value = 32768;
|
||||
return 0;
|
||||
}
|
||||
case V4L2_CID_AUDIO_BASS:
|
||||
ctrl->value = msp->bass;
|
||||
return 0;
|
||||
case V4L2_CID_AUDIO_TREBLE:
|
||||
ctrl->value = msp->treble;
|
||||
return 0;
|
||||
case V4L2_CID_AUDIO_VOLUME:
|
||||
ctrl->value = MAX(msp->left, msp->right);
|
||||
return 0;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static int msp_set_ctrl(struct i2c_client *client, struct v4l2_control *ctrl)
|
||||
{
|
||||
struct msp3400c *msp = i2c_get_clientdata(client);
|
||||
int set_volume=0, balance, volume;
|
||||
|
||||
switch (ctrl->id) {
|
||||
case V4L2_CID_AUDIO_MUTE:
|
||||
if (ctrl->value>=0 && ctrl->value<2)
|
||||
msp->muted = ctrl->value;
|
||||
else
|
||||
return -ERANGE;
|
||||
|
||||
msp3400c_setvolume(client, msp->muted, msp->left, msp->right);
|
||||
return 0;
|
||||
case V4L2_CID_AUDIO_BALANCE:
|
||||
balance=ctrl->value;
|
||||
volume = MAX(msp->left, msp->right);
|
||||
set_volume=1;
|
||||
break;
|
||||
case V4L2_CID_AUDIO_BASS:
|
||||
msp->bass=ctrl->value;
|
||||
msp3400c_setbass(client, msp->bass);
|
||||
return 0;
|
||||
case V4L2_CID_AUDIO_TREBLE:
|
||||
msp->treble=ctrl->value;
|
||||
msp3400c_settreble(client, msp->treble);
|
||||
return 0;
|
||||
case V4L2_CID_AUDIO_VOLUME:
|
||||
volume = MAX(msp->left, msp->right);
|
||||
|
||||
balance = (32768 * MIN(msp->left, msp->right)) /
|
||||
(volume ? volume : 1);
|
||||
balance = (msp->left < msp->right) ?
|
||||
(65535 - balance) : balance;
|
||||
if (0 == volume)
|
||||
balance = 32768;
|
||||
|
||||
volume=ctrl->value;
|
||||
set_volume=1;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (set_volume) {
|
||||
msp->left = (MIN(65536 - balance, 32768) * volume) / 32768;
|
||||
msp->right = (MIN(balance, 32768) * volume) / 32768;
|
||||
|
||||
msp3400_dbg("volume=%d, balance=%d, left=%d, right=%d",
|
||||
volume,balance,msp->left,msp->right);
|
||||
|
||||
msp3400c_setvolume(client, msp->muted, msp->left, msp->right);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg)
|
||||
{
|
||||
@ -2027,6 +2155,37 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg)
|
||||
|
||||
break;
|
||||
}
|
||||
case VIDIOC_QUERYCTRL:
|
||||
{
|
||||
struct v4l2_queryctrl *qc = arg;
|
||||
int i;
|
||||
|
||||
msp3400_dbg("VIDIOC_QUERYCTRL");
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(msp34xx_qctrl); i++)
|
||||
if (qc->id && qc->id == msp34xx_qctrl[i].id) {
|
||||
memcpy(qc, &(msp34xx_qctrl[i]),
|
||||
sizeof(*qc));
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
case VIDIOC_G_CTRL:
|
||||
{
|
||||
struct v4l2_control *ctrl = arg;
|
||||
msp3400_dbg("VIDIOC_G_CTRL\n");
|
||||
|
||||
return msp_get_ctrl(client, ctrl);
|
||||
}
|
||||
case VIDIOC_S_CTRL:
|
||||
{
|
||||
struct v4l2_control *ctrl = arg;
|
||||
|
||||
msp3400_dbg("VIDIOC_S_CTRL\n");
|
||||
|
||||
return msp_set_ctrl(client, ctrl);
|
||||
}
|
||||
|
||||
default:
|
||||
/* nothing */
|
||||
|
@ -37,24 +37,24 @@ MODULE_PARM_DESC(debug, "Debug level (0-1)");
|
||||
/* supported controls */
|
||||
static struct v4l2_queryctrl tvp5150_qctrl[] = {
|
||||
{
|
||||
.id = V4L2_CID_BRIGHTNESS,
|
||||
.type = V4L2_CTRL_TYPE_INTEGER,
|
||||
.name = "Brightness",
|
||||
.minimum = 0,
|
||||
.maximum = 255,
|
||||
.step = 1,
|
||||
.default_value = 0,
|
||||
.flags = 0,
|
||||
}, {
|
||||
.id = V4L2_CID_CONTRAST,
|
||||
.type = V4L2_CTRL_TYPE_INTEGER,
|
||||
.name = "Contrast",
|
||||
.minimum = 0,
|
||||
.maximum = 255,
|
||||
.step = 0x1,
|
||||
.default_value = 0x10,
|
||||
.flags = 0,
|
||||
}, {
|
||||
.id = V4L2_CID_BRIGHTNESS,
|
||||
.type = V4L2_CTRL_TYPE_INTEGER,
|
||||
.name = "Brightness",
|
||||
.minimum = 0,
|
||||
.maximum = 255,
|
||||
.step = 1,
|
||||
.default_value = 0,
|
||||
.flags = 0,
|
||||
}, {
|
||||
.id = V4L2_CID_CONTRAST,
|
||||
.type = V4L2_CTRL_TYPE_INTEGER,
|
||||
.name = "Contrast",
|
||||
.minimum = 0,
|
||||
.maximum = 255,
|
||||
.step = 0x1,
|
||||
.default_value = 0x10,
|
||||
.flags = 0,
|
||||
}, {
|
||||
.id = V4L2_CID_SATURATION,
|
||||
.type = V4L2_CTRL_TYPE_INTEGER,
|
||||
.name = "Saturation",
|
||||
@ -63,16 +63,16 @@ static struct v4l2_queryctrl tvp5150_qctrl[] = {
|
||||
.step = 0x1,
|
||||
.default_value = 0x10,
|
||||
.flags = 0,
|
||||
}, {
|
||||
.id = V4L2_CID_HUE,
|
||||
.type = V4L2_CTRL_TYPE_INTEGER,
|
||||
.name = "Hue",
|
||||
.minimum = -128,
|
||||
.maximum = 127,
|
||||
.step = 0x1,
|
||||
.default_value = 0x10,
|
||||
.flags = 0,
|
||||
}
|
||||
}, {
|
||||
.id = V4L2_CID_HUE,
|
||||
.type = V4L2_CTRL_TYPE_INTEGER,
|
||||
.name = "Hue",
|
||||
.minimum = -128,
|
||||
.maximum = 127,
|
||||
.step = 0x1,
|
||||
.default_value = 0x10,
|
||||
.flags = 0,
|
||||
}
|
||||
};
|
||||
|
||||
struct tvp5150 {
|
||||
@ -437,11 +437,24 @@ enum tvp5150_input {
|
||||
static inline void tvp5150_selmux(struct i2c_client *c,
|
||||
enum tvp5150_input input)
|
||||
{
|
||||
int opmode=0;
|
||||
|
||||
struct tvp5150 *decoder = i2c_get_clientdata(c);
|
||||
|
||||
if (!decoder->enable)
|
||||
input |= TVP5150_BLACK_SCREEN;
|
||||
|
||||
switch (input) {
|
||||
case TVP5150_ANALOG_CH0:
|
||||
case TVP5150_ANALOG_CH1:
|
||||
opmode=0x30; /* TV Mode */
|
||||
break;
|
||||
default:
|
||||
opmode=0; /* Auto Mode */
|
||||
break;
|
||||
}
|
||||
|
||||
tvp5150_write(c, TVP5150_OP_MODE_CTL, opmode);
|
||||
tvp5150_write(c, TVP5150_VD_IN_SRC_SEL_1, input);
|
||||
};
|
||||
|
||||
@ -498,9 +511,8 @@ static int tvp5150_get_ctrl(struct i2c_client *c, struct v4l2_control *ctrl)
|
||||
case V4L2_CID_HUE:
|
||||
ctrl->value = tvp5150_read(c, TVP5150_HUE_CTL);
|
||||
return 0;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int tvp5150_set_ctrl(struct i2c_client *c, struct v4l2_control *ctrl)
|
||||
@ -520,9 +532,8 @@ static int tvp5150_set_ctrl(struct i2c_client *c, struct v4l2_control *ctrl)
|
||||
case V4L2_CID_HUE:
|
||||
tvp5150_write(c, TVP5150_HUE_CTL, ctrl->value);
|
||||
return 0;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -627,12 +638,11 @@ static int tvp5150_command(struct i2c_client *client,
|
||||
case VIDIOC_QUERYCTRL:
|
||||
{
|
||||
struct v4l2_queryctrl *qc = arg;
|
||||
u8 i, n;
|
||||
int i;
|
||||
|
||||
dprintk(1, KERN_DEBUG "VIDIOC_QUERYCTRL");
|
||||
|
||||
n = sizeof(tvp5150_qctrl) / sizeof(tvp5150_qctrl[0]);
|
||||
for (i = 0; i < n; i++)
|
||||
for (i = 0; i < ARRAY_SIZE(tvp5150_qctrl); i++)
|
||||
if (qc->id && qc->id == tvp5150_qctrl[i].id) {
|
||||
memcpy(qc, &(tvp5150_qctrl[i]),
|
||||
sizeof(*qc));
|
||||
@ -648,7 +658,6 @@ static int tvp5150_command(struct i2c_client *client,
|
||||
|
||||
return tvp5150_get_ctrl(client, ctrl);
|
||||
}
|
||||
case VIDIOC_S_CTRL_OLD: /* ??? */
|
||||
case VIDIOC_S_CTRL:
|
||||
{
|
||||
struct v4l2_control *ctrl = arg;
|
||||
|
Loading…
Reference in New Issue
Block a user