提交 b960074f 编写于 作者: H Hans Verkuil 提交者: Mauro Carvalho Chehab

V4L/DVB (10271): saa7146: convert to video_ioctl2.

The conversion to video_ioctl2 is the first phase to converting this driver
to the latest v4l2 framework.
Signed-off-by: NHans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: NMauro Carvalho Chehab <mchehab@redhat.com>
上级 c9b8b04b
...@@ -308,14 +308,6 @@ static int fops_release(struct file *file) ...@@ -308,14 +308,6 @@ static int fops_release(struct file *file)
return 0; return 0;
} }
static long fops_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
/*
DEB_EE(("file:%p, cmd:%d, arg:%li\n", file, cmd, arg));
*/
return video_usercopy(file, cmd, arg, saa7146_video_do_ioctl);
}
static int fops_mmap(struct file *file, struct vm_area_struct * vma) static int fops_mmap(struct file *file, struct vm_area_struct * vma)
{ {
struct saa7146_fh *fh = file->private_data; struct saa7146_fh *fh = file->private_data;
...@@ -425,7 +417,7 @@ static const struct v4l2_file_operations video_fops = ...@@ -425,7 +417,7 @@ static const struct v4l2_file_operations video_fops =
.write = fops_write, .write = fops_write,
.poll = fops_poll, .poll = fops_poll,
.mmap = fops_mmap, .mmap = fops_mmap,
.ioctl = fops_ioctl, .ioctl = video_ioctl2,
}; };
static void vv_callback(struct saa7146_dev *dev, unsigned long status) static void vv_callback(struct saa7146_dev *dev, unsigned long status)
...@@ -452,19 +444,16 @@ static void vv_callback(struct saa7146_dev *dev, unsigned long status) ...@@ -452,19 +444,16 @@ static void vv_callback(struct saa7146_dev *dev, unsigned long status)
} }
} }
static struct video_device device_template =
{
.fops = &video_fops,
.minor = -1,
};
int saa7146_vv_init(struct saa7146_dev* dev, struct saa7146_ext_vv *ext_vv) int saa7146_vv_init(struct saa7146_dev* dev, struct saa7146_ext_vv *ext_vv)
{ {
struct saa7146_vv *vv = kzalloc (sizeof(struct saa7146_vv),GFP_KERNEL); struct saa7146_vv *vv = kzalloc(sizeof(struct saa7146_vv), GFP_KERNEL);
if( NULL == vv ) {
if (vv == NULL) {
ERR(("out of memory. aborting.\n")); ERR(("out of memory. aborting.\n"));
return -1; return -1;
} }
ext_vv->ops = saa7146_video_ioctl_ops;
ext_vv->core_ops = &saa7146_video_ioctl_ops;
DEB_EE(("dev:%p\n",dev)); DEB_EE(("dev:%p\n",dev));
...@@ -521,6 +510,7 @@ int saa7146_register_device(struct video_device **vid, struct saa7146_dev* dev, ...@@ -521,6 +510,7 @@ int saa7146_register_device(struct video_device **vid, struct saa7146_dev* dev,
{ {
struct saa7146_vv *vv = dev->vv_data; struct saa7146_vv *vv = dev->vv_data;
struct video_device *vfd; struct video_device *vfd;
int err;
DEB_EE(("dev:%p, name:'%s', type:%d\n",dev,name,type)); DEB_EE(("dev:%p, name:'%s', type:%d\n",dev,name,type));
...@@ -529,16 +519,18 @@ int saa7146_register_device(struct video_device **vid, struct saa7146_dev* dev, ...@@ -529,16 +519,18 @@ int saa7146_register_device(struct video_device **vid, struct saa7146_dev* dev,
if (vfd == NULL) if (vfd == NULL)
return -ENOMEM; return -ENOMEM;
memcpy(vfd, &device_template, sizeof(struct video_device)); vfd->fops = &video_fops;
strlcpy(vfd->name, name, sizeof(vfd->name)); vfd->ioctl_ops = dev->ext_vv_data ? &dev->ext_vv_data->ops :
&saa7146_video_ioctl_ops;
vfd->release = video_device_release; vfd->release = video_device_release;
strlcpy(vfd->name, name, sizeof(vfd->name));
video_set_drvdata(vfd, dev); video_set_drvdata(vfd, dev);
// fixme: -1 should be an insmod parameter *for the extension* (like "video_nr"); err = video_register_device(vfd, type, -1);
if (video_register_device(vfd, type, -1) < 0) { if (err < 0) {
ERR(("cannot register v4l2 device. skipping.\n")); ERR(("cannot register v4l2 device. skipping.\n"));
video_device_release(vfd); video_device_release(vfd);
return -1; return err;
} }
if( VFL_TYPE_GRABBER == type ) { if( VFL_TYPE_GRABBER == type ) {
......
...@@ -316,253 +316,260 @@ static int av7110_dvb_c_switch(struct saa7146_fh *fh) ...@@ -316,253 +316,260 @@ static int av7110_dvb_c_switch(struct saa7146_fh *fh)
return 0; return 0;
} }
static long av7110_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) static int vidioc_g_tuner(struct file *file, void *fh, struct v4l2_tuner *t)
{ {
struct saa7146_dev *dev = fh->dev; struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
struct av7110 *av7110 = (struct av7110*) dev->ext_priv; struct av7110 *av7110 = (struct av7110 *)dev->ext_priv;
dprintk(4, "saa7146_dev: %p\n", dev); u16 stereo_det;
s8 stereo;
switch (cmd) { dprintk(2, "VIDIOC_G_TUNER: %d\n", t->index);
case VIDIOC_G_TUNER:
{
struct v4l2_tuner *t = arg;
u16 stereo_det;
s8 stereo;
dprintk(2, "VIDIOC_G_TUNER: %d\n", t->index); if (!av7110->analog_tuner_flags || t->index != 0)
return -EINVAL;
if (!av7110->analog_tuner_flags || t->index != 0) memset(t, 0, sizeof(*t));
return -EINVAL; strcpy((char *)t->name, "Television");
t->type = V4L2_TUNER_ANALOG_TV;
t->capability = V4L2_TUNER_CAP_NORM | V4L2_TUNER_CAP_STEREO |
V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2 | V4L2_TUNER_CAP_SAP;
t->rangelow = 772; /* 48.25 MHZ / 62.5 kHz = 772, see fi1216mk2-specs, page 2 */
t->rangehigh = 13684; /* 855.25 MHz / 62.5 kHz = 13684 */
/* FIXME: add the real signal strength here */
t->signal = 0xffff;
t->afc = 0;
/* FIXME: standard / stereo detection is still broken */
msp_readreg(av7110, MSP_RD_DEM, 0x007e, &stereo_det);
dprintk(1, "VIDIOC_G_TUNER: msp3400 TV standard detection: 0x%04x\n", stereo_det);
msp_readreg(av7110, MSP_RD_DSP, 0x0018, &stereo_det);
dprintk(1, "VIDIOC_G_TUNER: msp3400 stereo detection: 0x%04x\n", stereo_det);
stereo = (s8)(stereo_det >> 8);
if (stereo > 0x10) {
/* stereo */
t->rxsubchans = V4L2_TUNER_SUB_STEREO | V4L2_TUNER_SUB_MONO;
t->audmode = V4L2_TUNER_MODE_STEREO;
} else if (stereo < -0x10) {
/* bilingual */
t->rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
t->audmode = V4L2_TUNER_MODE_LANG1;
} else /* mono */
t->rxsubchans = V4L2_TUNER_SUB_MONO;
memset(t, 0, sizeof(*t)); return 0;
strcpy((char *)t->name, "Television"); }
t->type = V4L2_TUNER_ANALOG_TV;
t->capability = V4L2_TUNER_CAP_NORM | V4L2_TUNER_CAP_STEREO |
V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2 | V4L2_TUNER_CAP_SAP;
t->rangelow = 772; /* 48.25 MHZ / 62.5 kHz = 772, see fi1216mk2-specs, page 2 */
t->rangehigh = 13684; /* 855.25 MHz / 62.5 kHz = 13684 */
/* FIXME: add the real signal strength here */
t->signal = 0xffff;
t->afc = 0;
// FIXME: standard / stereo detection is still broken
msp_readreg(av7110, MSP_RD_DEM, 0x007e, &stereo_det);
dprintk(1, "VIDIOC_G_TUNER: msp3400 TV standard detection: 0x%04x\n", stereo_det);
msp_readreg(av7110, MSP_RD_DSP, 0x0018, &stereo_det);
dprintk(1, "VIDIOC_G_TUNER: msp3400 stereo detection: 0x%04x\n", stereo_det);
stereo = (s8)(stereo_det >> 8);
if (stereo > 0x10) {
/* stereo */
t->rxsubchans = V4L2_TUNER_SUB_STEREO | V4L2_TUNER_SUB_MONO;
t->audmode = V4L2_TUNER_MODE_STEREO;
}
else if (stereo < -0x10) {
/* bilingual */
t->rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
t->audmode = V4L2_TUNER_MODE_LANG1;
}
else /* mono */
t->rxsubchans = V4L2_TUNER_SUB_MONO;
return 0; static int vidioc_s_tuner(struct file *file, void *fh, struct v4l2_tuner *t)
} {
case VIDIOC_S_TUNER: struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
{ struct av7110 *av7110 = (struct av7110 *)dev->ext_priv;
struct v4l2_tuner *t = arg; u16 fm_matrix, src;
u16 fm_matrix, src; dprintk(2, "VIDIOC_S_TUNER: %d\n", t->index);
dprintk(2, "VIDIOC_S_TUNER: %d\n", t->index);
if (!av7110->analog_tuner_flags || av7110->current_input != 1) if (!av7110->analog_tuner_flags || av7110->current_input != 1)
return -EINVAL; return -EINVAL;
switch (t->audmode) { switch (t->audmode) {
case V4L2_TUNER_MODE_STEREO: case V4L2_TUNER_MODE_STEREO:
dprintk(2, "VIDIOC_S_TUNER: V4L2_TUNER_MODE_STEREO\n"); dprintk(2, "VIDIOC_S_TUNER: V4L2_TUNER_MODE_STEREO\n");
fm_matrix = 0x3001; // stereo fm_matrix = 0x3001; /* stereo */
src = 0x0020; src = 0x0020;
break; break;
case V4L2_TUNER_MODE_LANG1_LANG2: case V4L2_TUNER_MODE_LANG1_LANG2:
dprintk(2, "VIDIOC_S_TUNER: V4L2_TUNER_MODE_LANG1_LANG2\n"); dprintk(2, "VIDIOC_S_TUNER: V4L2_TUNER_MODE_LANG1_LANG2\n");
fm_matrix = 0x3000; // bilingual fm_matrix = 0x3000; /* bilingual */
src = 0x0020; src = 0x0020;
break; break;
case V4L2_TUNER_MODE_LANG1: case V4L2_TUNER_MODE_LANG1:
dprintk(2, "VIDIOC_S_TUNER: V4L2_TUNER_MODE_LANG1\n"); dprintk(2, "VIDIOC_S_TUNER: V4L2_TUNER_MODE_LANG1\n");
fm_matrix = 0x3000; // mono fm_matrix = 0x3000; /* mono */
src = 0x0000; src = 0x0000;
break; break;
case V4L2_TUNER_MODE_LANG2: case V4L2_TUNER_MODE_LANG2:
dprintk(2, "VIDIOC_S_TUNER: V4L2_TUNER_MODE_LANG2\n"); dprintk(2, "VIDIOC_S_TUNER: V4L2_TUNER_MODE_LANG2\n");
fm_matrix = 0x3000; // mono fm_matrix = 0x3000; /* mono */
src = 0x0010; src = 0x0010;
break; break;
default: /* case V4L2_TUNER_MODE_MONO: */ default: /* case V4L2_TUNER_MODE_MONO: */
dprintk(2, "VIDIOC_S_TUNER: TDA9840_SET_MONO\n"); dprintk(2, "VIDIOC_S_TUNER: TDA9840_SET_MONO\n");
fm_matrix = 0x3000; // mono fm_matrix = 0x3000; /* mono */
src = 0x0030; src = 0x0030;
break; break;
}
msp_writereg(av7110, MSP_WR_DSP, 0x000e, fm_matrix);
msp_writereg(av7110, MSP_WR_DSP, 0x0008, src);
msp_writereg(av7110, MSP_WR_DSP, 0x0009, src);
msp_writereg(av7110, MSP_WR_DSP, 0x000a, src);
return 0;
} }
case VIDIOC_G_FREQUENCY: msp_writereg(av7110, MSP_WR_DSP, 0x000e, fm_matrix);
{ msp_writereg(av7110, MSP_WR_DSP, 0x0008, src);
struct v4l2_frequency *f = arg; msp_writereg(av7110, MSP_WR_DSP, 0x0009, src);
msp_writereg(av7110, MSP_WR_DSP, 0x000a, src);
return 0;
}
static int vidioc_g_frequency(struct file *file, void *fh, struct v4l2_frequency *f)
{
struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
struct av7110 *av7110 = (struct av7110 *)dev->ext_priv;
dprintk(2, "VIDIOC_G_FREQ: freq:0x%08x.\n", f->frequency); dprintk(2, "VIDIOC_G_FREQ: freq:0x%08x.\n", f->frequency);
if (!av7110->analog_tuner_flags || av7110->current_input != 1) if (!av7110->analog_tuner_flags || av7110->current_input != 1)
return -EINVAL; return -EINVAL;
memset(f, 0, sizeof(*f)); memset(f, 0, sizeof(*f));
f->type = V4L2_TUNER_ANALOG_TV; f->type = V4L2_TUNER_ANALOG_TV;
f->frequency = av7110->current_freq; f->frequency = av7110->current_freq;
return 0; return 0;
} }
case VIDIOC_S_FREQUENCY:
{
struct v4l2_frequency *f = arg;
dprintk(2, "VIDIOC_S_FREQUENCY: freq:0x%08x.\n", f->frequency); static int vidioc_s_frequency(struct file *file, void *fh, struct v4l2_frequency *f)
{
struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
struct av7110 *av7110 = (struct av7110 *)dev->ext_priv;
if (!av7110->analog_tuner_flags || av7110->current_input != 1) dprintk(2, "VIDIOC_S_FREQUENCY: freq:0x%08x.\n", f->frequency);
return -EINVAL;
if (V4L2_TUNER_ANALOG_TV != f->type) if (!av7110->analog_tuner_flags || av7110->current_input != 1)
return -EINVAL; return -EINVAL;
msp_writereg(av7110, MSP_WR_DSP, 0x0000, 0xffe0); // fast mute if (V4L2_TUNER_ANALOG_TV != f->type)
msp_writereg(av7110, MSP_WR_DSP, 0x0007, 0xffe0); return -EINVAL;
/* tune in desired frequency */ msp_writereg(av7110, MSP_WR_DSP, 0x0000, 0xffe0); /* fast mute */
if (av7110->analog_tuner_flags & ANALOG_TUNER_VES1820) { msp_writereg(av7110, MSP_WR_DSP, 0x0007, 0xffe0);
ves1820_set_tv_freq(dev, f->frequency);
} else if (av7110->analog_tuner_flags & ANALOG_TUNER_STV0297) {
stv0297_set_tv_freq(dev, f->frequency);
}
av7110->current_freq = f->frequency;
msp_writereg(av7110, MSP_WR_DSP, 0x0015, 0x003f); // start stereo detection /* tune in desired frequency */
msp_writereg(av7110, MSP_WR_DSP, 0x0015, 0x0000); if (av7110->analog_tuner_flags & ANALOG_TUNER_VES1820)
msp_writereg(av7110, MSP_WR_DSP, 0x0000, 0x4f00); // loudspeaker + headphone ves1820_set_tv_freq(dev, f->frequency);
msp_writereg(av7110, MSP_WR_DSP, 0x0007, 0x4f00); // SCART 1 volume else if (av7110->analog_tuner_flags & ANALOG_TUNER_STV0297)
return 0; stv0297_set_tv_freq(dev, f->frequency);
} av7110->current_freq = f->frequency;
case VIDIOC_ENUMINPUT:
{
struct v4l2_input *i = arg;
dprintk(2, "VIDIOC_ENUMINPUT: %d\n", i->index); msp_writereg(av7110, MSP_WR_DSP, 0x0015, 0x003f); /* start stereo detection */
msp_writereg(av7110, MSP_WR_DSP, 0x0015, 0x0000);
msp_writereg(av7110, MSP_WR_DSP, 0x0000, 0x4f00); /* loudspeaker + headphone */
msp_writereg(av7110, MSP_WR_DSP, 0x0007, 0x4f00); /* SCART 1 volume */
return 0;
}
if (av7110->analog_tuner_flags) { static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *i)
if (i->index < 0 || i->index >= 4) {
return -EINVAL; struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
} else { struct av7110 *av7110 = (struct av7110 *)dev->ext_priv;
if (i->index != 0)
return -EINVAL;
}
memcpy(i, &inputs[i->index], sizeof(struct v4l2_input)); dprintk(2, "VIDIOC_ENUMINPUT: %d\n", i->index);
return 0; if (av7110->analog_tuner_flags) {
if (i->index < 0 || i->index >= 4)
return -EINVAL;
} else {
if (i->index != 0)
return -EINVAL;
} }
case VIDIOC_G_INPUT:
{ memcpy(i, &inputs[i->index], sizeof(struct v4l2_input));
int *input = (int *)arg;
*input = av7110->current_input; return 0;
dprintk(2, "VIDIOC_G_INPUT: %d\n", *input); }
static int vidioc_g_input(struct file *file, void *fh, unsigned int *input)
{
struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
struct av7110 *av7110 = (struct av7110 *)dev->ext_priv;
*input = av7110->current_input;
dprintk(2, "VIDIOC_G_INPUT: %d\n", *input);
return 0;
}
static int vidioc_s_input(struct file *file, void *fh, unsigned int input)
{
struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
struct av7110 *av7110 = (struct av7110 *)dev->ext_priv;
dprintk(2, "VIDIOC_S_INPUT: %d\n", input);
if (!av7110->analog_tuner_flags)
return 0; return 0;
}
case VIDIOC_S_INPUT:
{
int input = *(int *)arg;
dprintk(2, "VIDIOC_S_INPUT: %d\n", input); if (input < 0 || input >= 4)
return -EINVAL;
if (!av7110->analog_tuner_flags) av7110->current_input = input;
return 0; return av7110_dvb_c_switch(fh);
}
if (input < 0 || input >= 4) static int vidioc_g_audio(struct file *file, void *fh, struct v4l2_audio *a)
return -EINVAL; {
dprintk(2, "VIDIOC_G_AUDIO: %d\n", a->index);
if (a->index != 0)
return -EINVAL;
memcpy(a, &msp3400_v4l2_audio, sizeof(struct v4l2_audio));
return 0;
}
av7110->current_input = input; static int vidioc_s_audio(struct file *file, void *fh, struct v4l2_audio *a)
return av7110_dvb_c_switch(fh); {
} dprintk(2, "VIDIOC_S_AUDIO: %d\n", a->index);
case VIDIOC_G_AUDIO: return 0;
{ }
struct v4l2_audio *a = arg;
dprintk(2, "VIDIOC_G_AUDIO: %d\n", a->index); static int vidioc_g_sliced_vbi_cap(struct file *file, void *fh,
if (a->index != 0) struct v4l2_sliced_vbi_cap *cap)
return -EINVAL; {
memcpy(a, &msp3400_v4l2_audio, sizeof(struct v4l2_audio)); struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
break; struct av7110 *av7110 = (struct av7110 *)dev->ext_priv;
}
case VIDIOC_S_AUDIO: dprintk(2, "VIDIOC_G_SLICED_VBI_CAP\n");
{ memset(cap, 0, sizeof(*cap));
struct v4l2_audio *a = arg; if (FW_VERSION(av7110->arm_app) >= 0x2623) {
dprintk(2, "VIDIOC_S_AUDIO: %d\n", a->index); cap->service_set = V4L2_SLICED_WSS_625;
break; cap->service_lines[0][23] = V4L2_SLICED_WSS_625;
}
case VIDIOC_G_SLICED_VBI_CAP:
{
struct v4l2_sliced_vbi_cap *cap = arg;
dprintk(2, "VIDIOC_G_SLICED_VBI_CAP\n");
memset(cap, 0, sizeof *cap);
if (FW_VERSION(av7110->arm_app) >= 0x2623) {
cap->service_set = V4L2_SLICED_WSS_625;
cap->service_lines[0][23] = V4L2_SLICED_WSS_625;
}
break;
}
case VIDIOC_G_FMT:
{
struct v4l2_format *f = arg;
dprintk(2, "VIDIOC_G_FMT:\n");
if (f->type != V4L2_BUF_TYPE_SLICED_VBI_OUTPUT ||
FW_VERSION(av7110->arm_app) < 0x2623)
return -EAGAIN; /* handled by core driver */
memset(&f->fmt.sliced, 0, sizeof f->fmt.sliced);
if (av7110->wssMode) {
f->fmt.sliced.service_set = V4L2_SLICED_WSS_625;
f->fmt.sliced.service_lines[0][23] = V4L2_SLICED_WSS_625;
f->fmt.sliced.io_size = sizeof (struct v4l2_sliced_vbi_data);
}
break;
} }
case VIDIOC_S_FMT: return 0;
{ }
struct v4l2_format *f = arg;
dprintk(2, "VIDIOC_S_FMT\n"); static int vidioc_g_fmt_sliced_vbi_out(struct file *file, void *fh,
if (f->type != V4L2_BUF_TYPE_SLICED_VBI_OUTPUT || struct v4l2_format *f)
FW_VERSION(av7110->arm_app) < 0x2623) {
return -EAGAIN; /* handled by core driver */ struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
if (f->fmt.sliced.service_set != V4L2_SLICED_WSS_625 && struct av7110 *av7110 = (struct av7110 *)dev->ext_priv;
f->fmt.sliced.service_lines[0][23] != V4L2_SLICED_WSS_625) {
memset(&f->fmt.sliced, 0, sizeof f->fmt.sliced); dprintk(2, "VIDIOC_G_FMT:\n");
/* WSS controlled by firmware */ if (FW_VERSION(av7110->arm_app) < 0x2623)
av7110->wssMode = 0; return -EINVAL;
av7110->wssData = 0; memset(&f->fmt.sliced, 0, sizeof f->fmt.sliced);
return av7110_fw_cmd(av7110, COMTYPE_ENCODER, if (av7110->wssMode) {
SetWSSConfig, 1, 0); f->fmt.sliced.service_set = V4L2_SLICED_WSS_625;
} else { f->fmt.sliced.service_lines[0][23] = V4L2_SLICED_WSS_625;
memset(&f->fmt.sliced, 0, sizeof f->fmt.sliced); f->fmt.sliced.io_size = sizeof(struct v4l2_sliced_vbi_data);
f->fmt.sliced.service_set = V4L2_SLICED_WSS_625;
f->fmt.sliced.service_lines[0][23] = V4L2_SLICED_WSS_625;
f->fmt.sliced.io_size = sizeof (struct v4l2_sliced_vbi_data);
/* WSS controlled by userspace */
av7110->wssMode = 1;
av7110->wssData = 0;
}
break;
} }
default: return 0;
printk("no such ioctl\n"); }
return -ENOIOCTLCMD;
static int vidioc_s_fmt_sliced_vbi_out(struct file *file, void *fh,
struct v4l2_format *f)
{
struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
struct av7110 *av7110 = (struct av7110 *)dev->ext_priv;
dprintk(2, "VIDIOC_S_FMT\n");
if (FW_VERSION(av7110->arm_app) < 0x2623)
return -EINVAL;
if (f->fmt.sliced.service_set != V4L2_SLICED_WSS_625 &&
f->fmt.sliced.service_lines[0][23] != V4L2_SLICED_WSS_625) {
memset(&f->fmt.sliced, 0, sizeof(f->fmt.sliced));
/* WSS controlled by firmware */
av7110->wssMode = 0;
av7110->wssData = 0;
return av7110_fw_cmd(av7110, COMTYPE_ENCODER,
SetWSSConfig, 1, 0);
} else {
memset(&f->fmt.sliced, 0, sizeof(f->fmt.sliced));
f->fmt.sliced.service_set = V4L2_SLICED_WSS_625;
f->fmt.sliced.service_lines[0][23] = V4L2_SLICED_WSS_625;
f->fmt.sliced.io_size = sizeof(struct v4l2_sliced_vbi_data);
/* WSS controlled by userspace */
av7110->wssMode = 1;
av7110->wssData = 0;
} }
return 0; return 0;
} }
...@@ -609,22 +616,6 @@ static ssize_t av7110_vbi_write(struct file *file, const char __user *data, size ...@@ -609,22 +616,6 @@ static ssize_t av7110_vbi_write(struct file *file, const char __user *data, size
* INITIALIZATION * INITIALIZATION
****************************************************************************/ ****************************************************************************/
static struct saa7146_extension_ioctls ioctls[] = {
{ VIDIOC_ENUMINPUT, SAA7146_EXCLUSIVE },
{ VIDIOC_G_INPUT, SAA7146_EXCLUSIVE },
{ VIDIOC_S_INPUT, SAA7146_EXCLUSIVE },
{ VIDIOC_G_FREQUENCY, SAA7146_EXCLUSIVE },
{ VIDIOC_S_FREQUENCY, SAA7146_EXCLUSIVE },
{ VIDIOC_G_TUNER, SAA7146_EXCLUSIVE },
{ VIDIOC_S_TUNER, SAA7146_EXCLUSIVE },
{ VIDIOC_G_AUDIO, SAA7146_EXCLUSIVE },
{ VIDIOC_S_AUDIO, SAA7146_EXCLUSIVE },
{ VIDIOC_G_SLICED_VBI_CAP, SAA7146_EXCLUSIVE },
{ VIDIOC_G_FMT, SAA7146_BEFORE },
{ VIDIOC_S_FMT, SAA7146_BEFORE },
{ 0, 0 }
};
static u8 saa7113_init_regs[] = { static u8 saa7113_init_regs[] = {
0x02, 0xd0, 0x02, 0xd0,
0x03, 0x23, 0x03, 0x23,
...@@ -788,20 +779,34 @@ int av7110_init_analog_module(struct av7110 *av7110) ...@@ -788,20 +779,34 @@ int av7110_init_analog_module(struct av7110 *av7110)
int av7110_init_v4l(struct av7110 *av7110) int av7110_init_v4l(struct av7110 *av7110)
{ {
struct saa7146_dev* dev = av7110->dev; struct saa7146_dev* dev = av7110->dev;
struct saa7146_ext_vv *vv_data;
int ret; int ret;
/* special case DVB-C: these cards have an analog tuner /* special case DVB-C: these cards have an analog tuner
plus need some special handling, so we have separate plus need some special handling, so we have separate
saa7146_ext_vv data for these... */ saa7146_ext_vv data for these... */
if (av7110->analog_tuner_flags) if (av7110->analog_tuner_flags)
ret = saa7146_vv_init(dev, &av7110_vv_data_c); vv_data = &av7110_vv_data_c;
else else
ret = saa7146_vv_init(dev, &av7110_vv_data_st); vv_data = &av7110_vv_data_st;
ret = saa7146_vv_init(dev, vv_data);
if (ret) { if (ret) {
ERR(("cannot init capture device. skipping.\n")); ERR(("cannot init capture device. skipping.\n"));
return -ENODEV; return -ENODEV;
} }
vv_data->ops.vidioc_enum_input = vidioc_enum_input;
vv_data->ops.vidioc_g_input = vidioc_g_input;
vv_data->ops.vidioc_s_input = vidioc_s_input;
vv_data->ops.vidioc_g_tuner = vidioc_g_tuner;
vv_data->ops.vidioc_s_tuner = vidioc_s_tuner;
vv_data->ops.vidioc_g_frequency = vidioc_g_frequency;
vv_data->ops.vidioc_s_frequency = vidioc_s_frequency;
vv_data->ops.vidioc_g_audio = vidioc_g_audio;
vv_data->ops.vidioc_s_audio = vidioc_s_audio;
vv_data->ops.vidioc_g_sliced_vbi_cap = vidioc_g_sliced_vbi_cap;
vv_data->ops.vidioc_g_fmt_sliced_vbi_out = vidioc_g_fmt_sliced_vbi_out;
vv_data->ops.vidioc_s_fmt_sliced_vbi_out = vidioc_s_fmt_sliced_vbi_out;
if (saa7146_register_device(&av7110->v4l_dev, dev, "av7110", VFL_TYPE_GRABBER)) { if (saa7146_register_device(&av7110->v4l_dev, dev, "av7110", VFL_TYPE_GRABBER)) {
ERR(("cannot register capture device. skipping.\n")); ERR(("cannot register capture device. skipping.\n"));
...@@ -900,9 +905,6 @@ static struct saa7146_ext_vv av7110_vv_data_st = { ...@@ -900,9 +905,6 @@ static struct saa7146_ext_vv av7110_vv_data_st = {
.num_stds = ARRAY_SIZE(standard), .num_stds = ARRAY_SIZE(standard),
.std_callback = &std_callback, .std_callback = &std_callback,
.ioctls = &ioctls[0],
.ioctl = av7110_ioctl,
.vbi_fops.open = av7110_vbi_reset, .vbi_fops.open = av7110_vbi_reset,
.vbi_fops.release = av7110_vbi_reset, .vbi_fops.release = av7110_vbi_reset,
.vbi_fops.write = av7110_vbi_write, .vbi_fops.write = av7110_vbi_write,
...@@ -918,9 +920,6 @@ static struct saa7146_ext_vv av7110_vv_data_c = { ...@@ -918,9 +920,6 @@ static struct saa7146_ext_vv av7110_vv_data_c = {
.num_stds = ARRAY_SIZE(standard), .num_stds = ARRAY_SIZE(standard),
.std_callback = &std_callback, .std_callback = &std_callback,
.ioctls = &ioctls[0],
.ioctl = av7110_ioctl,
.vbi_fops.open = av7110_vbi_reset, .vbi_fops.open = av7110_vbi_reset,
.vbi_fops.release = av7110_vbi_reset, .vbi_fops.release = av7110_vbi_reset,
.vbi_fops.write = av7110_vbi_write, .vbi_fops.write = av7110_vbi_write,
......
...@@ -1404,6 +1404,41 @@ static int budget_av_detach(struct saa7146_dev *dev) ...@@ -1404,6 +1404,41 @@ static int budget_av_detach(struct saa7146_dev *dev)
return err; return err;
} }
#define KNC1_INPUTS 2
static struct v4l2_input knc1_inputs[KNC1_INPUTS] = {
{0, "Composite", V4L2_INPUT_TYPE_TUNER, 1, 0, V4L2_STD_PAL_BG | V4L2_STD_NTSC_M, 0},
{1, "S-Video", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG | V4L2_STD_NTSC_M, 0},
};
static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *i)
{
dprintk(1, "VIDIOC_ENUMINPUT %d.\n", i->index);
if (i->index < 0 || i->index >= KNC1_INPUTS)
return -EINVAL;
memcpy(i, &knc1_inputs[i->index], sizeof(struct v4l2_input));
return 0;
}
static int vidioc_g_input(struct file *file, void *fh, unsigned int *i)
{
struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
struct budget_av *budget_av = (struct budget_av *)dev->ext_priv;
*i = budget_av->cur_input;
dprintk(1, "VIDIOC_G_INPUT %d.\n", *i);
return 0;
}
static int vidioc_s_input(struct file *file, void *fh, unsigned int input)
{
struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
struct budget_av *budget_av = (struct budget_av *)dev->ext_priv;
dprintk(1, "VIDIOC_S_INPUT %d.\n", input);
return saa7113_setinput(budget_av, input);
}
static struct saa7146_ext_vv vv_data; static struct saa7146_ext_vv vv_data;
static int budget_av_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data *info) static int budget_av_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data *info)
...@@ -1442,6 +1477,9 @@ static int budget_av_attach(struct saa7146_dev *dev, struct saa7146_pci_extensio ...@@ -1442,6 +1477,9 @@ static int budget_av_attach(struct saa7146_dev *dev, struct saa7146_pci_extensio
ERR(("cannot init vv subsystem.\n")); ERR(("cannot init vv subsystem.\n"));
return err; return err;
} }
vv_data.ops.vidioc_enum_input = vidioc_enum_input;
vv_data.ops.vidioc_g_input = vidioc_g_input;
vv_data.ops.vidioc_s_input = vidioc_s_input;
if ((err = saa7146_register_device(&budget_av->vd, dev, "knc1", VFL_TYPE_GRABBER))) { if ((err = saa7146_register_device(&budget_av->vd, dev, "knc1", VFL_TYPE_GRABBER))) {
/* fixme: proper cleanup here */ /* fixme: proper cleanup here */
...@@ -1480,54 +1518,6 @@ static int budget_av_attach(struct saa7146_dev *dev, struct saa7146_pci_extensio ...@@ -1480,54 +1518,6 @@ static int budget_av_attach(struct saa7146_dev *dev, struct saa7146_pci_extensio
return 0; return 0;
} }
#define KNC1_INPUTS 2
static struct v4l2_input knc1_inputs[KNC1_INPUTS] = {
{0, "Composite", V4L2_INPUT_TYPE_TUNER, 1, 0, V4L2_STD_PAL_BG | V4L2_STD_NTSC_M, 0},
{1, "S-Video", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG | V4L2_STD_NTSC_M, 0},
};
static struct saa7146_extension_ioctls ioctls[] = {
{VIDIOC_ENUMINPUT, SAA7146_EXCLUSIVE},
{VIDIOC_G_INPUT, SAA7146_EXCLUSIVE},
{VIDIOC_S_INPUT, SAA7146_EXCLUSIVE},
{0, 0}
};
static long av_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
{
struct saa7146_dev *dev = fh->dev;
struct budget_av *budget_av = (struct budget_av *) dev->ext_priv;
switch (cmd) {
case VIDIOC_ENUMINPUT:{
struct v4l2_input *i = arg;
dprintk(1, "VIDIOC_ENUMINPUT %d.\n", i->index);
if (i->index < 0 || i->index >= KNC1_INPUTS) {
return -EINVAL;
}
memcpy(i, &knc1_inputs[i->index], sizeof(struct v4l2_input));
return 0;
}
case VIDIOC_G_INPUT:{
int *input = (int *) arg;
*input = budget_av->cur_input;
dprintk(1, "VIDIOC_G_INPUT %d.\n", *input);
return 0;
}
case VIDIOC_S_INPUT:{
int input = *(int *) arg;
dprintk(1, "VIDIOC_S_INPUT %d.\n", input);
return saa7113_setinput(budget_av, input);
}
default:
return -ENOIOCTLCMD;
}
return 0;
}
static struct saa7146_standard standard[] = { static struct saa7146_standard standard[] = {
{.name = "PAL",.id = V4L2_STD_PAL, {.name = "PAL",.id = V4L2_STD_PAL,
.v_offset = 0x17,.v_field = 288, .v_offset = 0x17,.v_field = 288,
...@@ -1546,8 +1536,6 @@ static struct saa7146_ext_vv vv_data = { ...@@ -1546,8 +1536,6 @@ static struct saa7146_ext_vv vv_data = {
.flags = 0, .flags = 0,
.stds = &standard[0], .stds = &standard[0],
.num_stds = ARRAY_SIZE(standard), .num_stds = ARRAY_SIZE(standard),
.ioctls = &ioctls[0],
.ioctl = av_ioctl,
}; };
static struct saa7146_extension budget_extension; static struct saa7146_extension budget_extension;
......
...@@ -56,17 +56,6 @@ struct hexium_data ...@@ -56,17 +56,6 @@ struct hexium_data
u8 byte; u8 byte;
}; };
static struct saa7146_extension_ioctls ioctls[] = {
{ VIDIOC_G_INPUT, SAA7146_EXCLUSIVE },
{ VIDIOC_S_INPUT, SAA7146_EXCLUSIVE },
{ VIDIOC_QUERYCTRL, SAA7146_BEFORE },
{ VIDIOC_ENUMINPUT, SAA7146_EXCLUSIVE },
{ VIDIOC_S_STD, SAA7146_AFTER },
{ VIDIOC_G_CTRL, SAA7146_BEFORE },
{ VIDIOC_S_CTRL, SAA7146_BEFORE },
{ 0, 0 }
};
#define HEXIUM_CONTROLS 1 #define HEXIUM_CONTROLS 1
static struct v4l2_queryctrl hexium_controls[] = { static struct v4l2_queryctrl hexium_controls[] = {
{ V4L2_CID_PRIVATE_BASE, V4L2_CTRL_TYPE_BOOLEAN, "B/W", 0, 1, 1, 0, 0 }, { V4L2_CID_PRIVATE_BASE, V4L2_CTRL_TYPE_BOOLEAN, "B/W", 0, 1, 1, 0, 0 },
...@@ -231,6 +220,132 @@ static int hexium_set_standard(struct hexium *hexium, struct hexium_data *vdec) ...@@ -231,6 +220,132 @@ static int hexium_set_standard(struct hexium *hexium, struct hexium_data *vdec)
return 0; return 0;
} }
static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *i)
{
DEB_EE(("VIDIOC_ENUMINPUT %d.\n", i->index));
if (i->index < 0 || i->index >= HEXIUM_INPUTS)
return -EINVAL;
memcpy(i, &hexium_inputs[i->index], sizeof(struct v4l2_input));
DEB_D(("v4l2_ioctl: VIDIOC_ENUMINPUT %d.\n", i->index));
return 0;
}
static int vidioc_g_input(struct file *file, void *fh, unsigned int *input)
{
struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
struct hexium *hexium = (struct hexium *) dev->ext_priv;
*input = hexium->cur_input;
DEB_D(("VIDIOC_G_INPUT: %d\n", *input));
return 0;
}
static int vidioc_s_input(struct file *file, void *fh, unsigned int input)
{
struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
struct hexium *hexium = (struct hexium *) dev->ext_priv;
DEB_EE(("VIDIOC_S_INPUT %d.\n", input));
if (input < 0 || input >= HEXIUM_INPUTS)
return -EINVAL;
hexium->cur_input = input;
hexium_set_input(hexium, input);
return 0;
}
/* the saa7146 provides some controls (brightness, contrast, saturation)
which gets registered *after* this function. because of this we have
to return with a value != 0 even if the function succeded.. */
static int vidioc_queryctrl(struct file *file, void *fh, struct v4l2_queryctrl *qc)
{
struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
int i;
for (i = HEXIUM_CONTROLS - 1; i >= 0; i--) {
if (hexium_controls[i].id == qc->id) {
*qc = hexium_controls[i];
DEB_D(("VIDIOC_QUERYCTRL %d.\n", qc->id));
return 0;
}
}
return dev->ext_vv_data->core_ops->vidioc_queryctrl(file, fh, qc);
}
static int vidioc_g_ctrl(struct file *file, void *fh, struct v4l2_control *vc)
{
struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
struct hexium *hexium = (struct hexium *) dev->ext_priv;
int i;
for (i = HEXIUM_CONTROLS - 1; i >= 0; i--) {
if (hexium_controls[i].id == vc->id)
break;
}
if (i < 0)
return dev->ext_vv_data->core_ops->vidioc_g_ctrl(file, fh, vc);
if (vc->id == V4L2_CID_PRIVATE_BASE) {
vc->value = hexium->cur_bw;
DEB_D(("VIDIOC_G_CTRL BW:%d.\n", vc->value));
return 0;
}
return -EINVAL;
}
static int vidioc_s_ctrl(struct file *file, void *fh, struct v4l2_control *vc)
{
struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
struct hexium *hexium = (struct hexium *) dev->ext_priv;
int i = 0;
for (i = HEXIUM_CONTROLS - 1; i >= 0; i--) {
if (hexium_controls[i].id == vc->id)
break;
}
if (i < 0)
return dev->ext_vv_data->core_ops->vidioc_s_ctrl(file, fh, vc);
if (vc->id == V4L2_CID_PRIVATE_BASE)
hexium->cur_bw = vc->value;
DEB_D(("VIDIOC_S_CTRL BW:%d.\n", hexium->cur_bw));
if (0 == hexium->cur_bw && V4L2_STD_PAL == hexium->cur_std) {
hexium_set_standard(hexium, hexium_pal);
return 0;
}
if (0 == hexium->cur_bw && V4L2_STD_NTSC == hexium->cur_std) {
hexium_set_standard(hexium, hexium_ntsc);
return 0;
}
if (0 == hexium->cur_bw && V4L2_STD_SECAM == hexium->cur_std) {
hexium_set_standard(hexium, hexium_secam);
return 0;
}
if (1 == hexium->cur_bw && V4L2_STD_PAL == hexium->cur_std) {
hexium_set_standard(hexium, hexium_pal_bw);
return 0;
}
if (1 == hexium->cur_bw && V4L2_STD_NTSC == hexium->cur_std) {
hexium_set_standard(hexium, hexium_ntsc_bw);
return 0;
}
if (1 == hexium->cur_bw && V4L2_STD_SECAM == hexium->cur_std)
/* fixme: is there no bw secam mode? */
return -EINVAL;
return -EINVAL;
}
static struct saa7146_ext_vv vv_data; static struct saa7146_ext_vv vv_data;
/* this function only gets called when the probing was successful */ /* this function only gets called when the probing was successful */
...@@ -279,6 +394,12 @@ static int hexium_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_d ...@@ -279,6 +394,12 @@ static int hexium_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_d
hexium->cur_input = 0; hexium->cur_input = 0;
saa7146_vv_init(dev, &vv_data); saa7146_vv_init(dev, &vv_data);
vv_data.ops.vidioc_queryctrl = vidioc_queryctrl;
vv_data.ops.vidioc_g_ctrl = vidioc_g_ctrl;
vv_data.ops.vidioc_s_ctrl = vidioc_s_ctrl;
vv_data.ops.vidioc_enum_input = vidioc_enum_input;
vv_data.ops.vidioc_g_input = vidioc_g_input;
vv_data.ops.vidioc_s_input = vidioc_s_input;
if (0 != saa7146_register_device(&hexium->video_dev, dev, "hexium gemini", VFL_TYPE_GRABBER)) { if (0 != saa7146_register_device(&hexium->video_dev, dev, "hexium gemini", VFL_TYPE_GRABBER)) {
printk("hexium_gemini: cannot register capture v4l2 device. skipping.\n"); printk("hexium_gemini: cannot register capture v4l2 device. skipping.\n");
return -1; return -1;
...@@ -306,153 +427,6 @@ static int hexium_detach(struct saa7146_dev *dev) ...@@ -306,153 +427,6 @@ static int hexium_detach(struct saa7146_dev *dev)
return 0; return 0;
} }
static long hexium_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
{
struct saa7146_dev *dev = fh->dev;
struct hexium *hexium = (struct hexium *) dev->ext_priv;
/*
struct saa7146_vv *vv = dev->vv_data;
*/
switch (cmd) {
case VIDIOC_ENUMINPUT:
{
struct v4l2_input *i = arg;
DEB_EE(("VIDIOC_ENUMINPUT %d.\n", i->index));
if (i->index < 0 || i->index >= HEXIUM_INPUTS) {
return -EINVAL;
}
memcpy(i, &hexium_inputs[i->index], sizeof(struct v4l2_input));
DEB_D(("v4l2_ioctl: VIDIOC_ENUMINPUT %d.\n", i->index));
return 0;
}
case VIDIOC_G_INPUT:
{
int *input = (int *) arg;
*input = hexium->cur_input;
DEB_D(("VIDIOC_G_INPUT: %d\n", *input));
return 0;
}
case VIDIOC_S_INPUT:
{
int input = *(int *) arg;
DEB_EE(("VIDIOC_S_INPUT %d.\n", input));
if (input < 0 || input >= HEXIUM_INPUTS) {
return -EINVAL;
}
hexium->cur_input = input;
hexium_set_input(hexium, input);
return 0;
}
/* the saa7146 provides some controls (brightness, contrast, saturation)
which gets registered *after* this function. because of this we have
to return with a value != 0 even if the function succeded.. */
case VIDIOC_QUERYCTRL:
{
struct v4l2_queryctrl *qc = arg;
int i;
for (i = HEXIUM_CONTROLS - 1; i >= 0; i--) {
if (hexium_controls[i].id == qc->id) {
*qc = hexium_controls[i];
DEB_D(("VIDIOC_QUERYCTRL %d.\n", qc->id));
return 0;
}
}
return -EAGAIN;
}
case VIDIOC_G_CTRL:
{
struct v4l2_control *vc = arg;
int i;
for (i = HEXIUM_CONTROLS - 1; i >= 0; i--) {
if (hexium_controls[i].id == vc->id) {
break;
}
}
if (i < 0) {
return -EAGAIN;
}
switch (vc->id) {
case V4L2_CID_PRIVATE_BASE:{
vc->value = hexium->cur_bw;
DEB_D(("VIDIOC_G_CTRL BW:%d.\n", vc->value));
return 0;
}
}
return -EINVAL;
}
case VIDIOC_S_CTRL:
{
struct v4l2_control *vc = arg;
int i = 0;
for (i = HEXIUM_CONTROLS - 1; i >= 0; i--) {
if (hexium_controls[i].id == vc->id) {
break;
}
}
if (i < 0) {
return -EAGAIN;
}
switch (vc->id) {
case V4L2_CID_PRIVATE_BASE:{
hexium->cur_bw = vc->value;
break;
}
}
DEB_D(("VIDIOC_S_CTRL BW:%d.\n", hexium->cur_bw));
if (0 == hexium->cur_bw && V4L2_STD_PAL == hexium->cur_std) {
hexium_set_standard(hexium, hexium_pal);
return 0;
}
if (0 == hexium->cur_bw && V4L2_STD_NTSC == hexium->cur_std) {
hexium_set_standard(hexium, hexium_ntsc);
return 0;
}
if (0 == hexium->cur_bw && V4L2_STD_SECAM == hexium->cur_std) {
hexium_set_standard(hexium, hexium_secam);
return 0;
}
if (1 == hexium->cur_bw && V4L2_STD_PAL == hexium->cur_std) {
hexium_set_standard(hexium, hexium_pal_bw);
return 0;
}
if (1 == hexium->cur_bw && V4L2_STD_NTSC == hexium->cur_std) {
hexium_set_standard(hexium, hexium_ntsc_bw);
return 0;
}
if (1 == hexium->cur_bw && V4L2_STD_SECAM == hexium->cur_std) {
/* fixme: is there no bw secam mode? */
return -EINVAL;
}
return -EINVAL;
}
default:
/*
DEB_D(("hexium_ioctl() does not handle this ioctl.\n"));
*/
return -ENOIOCTLCMD;
}
return 0;
}
static int std_callback(struct saa7146_dev *dev, struct saa7146_standard *std) static int std_callback(struct saa7146_dev *dev, struct saa7146_standard *std)
{ {
struct hexium *hexium = (struct hexium *) dev->ext_priv; struct hexium *hexium = (struct hexium *) dev->ext_priv;
...@@ -514,8 +488,6 @@ static struct saa7146_ext_vv vv_data = { ...@@ -514,8 +488,6 @@ static struct saa7146_ext_vv vv_data = {
.stds = &hexium_standards[0], .stds = &hexium_standards[0],
.num_stds = sizeof(hexium_standards) / sizeof(struct saa7146_standard), .num_stds = sizeof(hexium_standards) / sizeof(struct saa7146_standard),
.std_callback = &std_callback, .std_callback = &std_callback,
.ioctls = &ioctls[0],
.ioctl = hexium_ioctl,
}; };
static struct saa7146_extension hexium_extension = { static struct saa7146_extension hexium_extension = {
......
...@@ -57,14 +57,6 @@ struct hexium_data ...@@ -57,14 +57,6 @@ struct hexium_data
u8 byte; u8 byte;
}; };
static struct saa7146_extension_ioctls ioctls[] = {
{ VIDIOC_G_INPUT, SAA7146_EXCLUSIVE },
{ VIDIOC_S_INPUT, SAA7146_EXCLUSIVE },
{ VIDIOC_ENUMINPUT, SAA7146_EXCLUSIVE },
{ VIDIOC_S_STD, SAA7146_AFTER },
{ 0, 0 }
};
struct hexium struct hexium
{ {
int type; int type;
...@@ -329,6 +321,44 @@ static int hexium_set_input(struct hexium *hexium, int input) ...@@ -329,6 +321,44 @@ static int hexium_set_input(struct hexium *hexium, int input)
return 0; return 0;
} }
static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *i)
{
DEB_EE(("VIDIOC_ENUMINPUT %d.\n", i->index));
if (i->index < 0 || i->index >= HEXIUM_INPUTS)
return -EINVAL;
memcpy(i, &hexium_inputs[i->index], sizeof(struct v4l2_input));
DEB_D(("v4l2_ioctl: VIDIOC_ENUMINPUT %d.\n", i->index));
return 0;
}
static int vidioc_g_input(struct file *file, void *fh, unsigned int *input)
{
struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
struct hexium *hexium = (struct hexium *) dev->ext_priv;
*input = hexium->cur_input;
DEB_D(("VIDIOC_G_INPUT: %d\n", *input));
return 0;
}
static int vidioc_s_input(struct file *file, void *fh, unsigned int input)
{
struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
struct hexium *hexium = (struct hexium *) dev->ext_priv;
if (input < 0 || input >= HEXIUM_INPUTS)
return -EINVAL;
hexium->cur_input = input;
hexium_set_input(hexium, input);
return 0;
}
static struct saa7146_ext_vv vv_data; static struct saa7146_ext_vv vv_data;
/* this function only gets called when the probing was successful */ /* this function only gets called when the probing was successful */
...@@ -339,6 +369,9 @@ static int hexium_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_d ...@@ -339,6 +369,9 @@ static int hexium_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_d
DEB_EE((".\n")); DEB_EE((".\n"));
saa7146_vv_init(dev, &vv_data); saa7146_vv_init(dev, &vv_data);
vv_data.ops.vidioc_enum_input = vidioc_enum_input;
vv_data.ops.vidioc_g_input = vidioc_g_input;
vv_data.ops.vidioc_s_input = vidioc_s_input;
if (0 != saa7146_register_device(&hexium->video_dev, dev, "hexium orion", VFL_TYPE_GRABBER)) { if (0 != saa7146_register_device(&hexium->video_dev, dev, "hexium orion", VFL_TYPE_GRABBER)) {
printk("hexium_orion: cannot register capture v4l2 device. skipping.\n"); printk("hexium_orion: cannot register capture v4l2 device. skipping.\n");
return -1; return -1;
...@@ -370,58 +403,6 @@ static int hexium_detach(struct saa7146_dev *dev) ...@@ -370,58 +403,6 @@ static int hexium_detach(struct saa7146_dev *dev)
return 0; return 0;
} }
static long hexium_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
{
struct saa7146_dev *dev = fh->dev;
struct hexium *hexium = (struct hexium *) dev->ext_priv;
/*
struct saa7146_vv *vv = dev->vv_data;
*/
switch (cmd) {
case VIDIOC_ENUMINPUT:
{
struct v4l2_input *i = arg;
DEB_EE(("VIDIOC_ENUMINPUT %d.\n", i->index));
if (i->index < 0 || i->index >= HEXIUM_INPUTS) {
return -EINVAL;
}
memcpy(i, &hexium_inputs[i->index], sizeof(struct v4l2_input));
DEB_D(("v4l2_ioctl: VIDIOC_ENUMINPUT %d.\n", i->index));
return 0;
}
case VIDIOC_G_INPUT:
{
int *input = (int *) arg;
*input = hexium->cur_input;
DEB_D(("VIDIOC_G_INPUT: %d\n", *input));
return 0;
}
case VIDIOC_S_INPUT:
{
int input = *(int *) arg;
if (input < 0 || input >= HEXIUM_INPUTS) {
return -EINVAL;
}
hexium->cur_input = input;
hexium_set_input(hexium, input);
return 0;
}
default:
/*
DEB_D(("hexium_ioctl() does not handle this ioctl.\n"));
*/
return -ENOIOCTLCMD;
}
return 0;
}
static int std_callback(struct saa7146_dev *dev, struct saa7146_standard *std) static int std_callback(struct saa7146_dev *dev, struct saa7146_standard *std)
{ {
return 0; return 0;
...@@ -479,8 +460,6 @@ static struct saa7146_ext_vv vv_data = { ...@@ -479,8 +460,6 @@ static struct saa7146_ext_vv vv_data = {
.stds = &hexium_standards[0], .stds = &hexium_standards[0],
.num_stds = sizeof(hexium_standards) / sizeof(struct saa7146_standard), .num_stds = sizeof(hexium_standards) / sizeof(struct saa7146_standard),
.std_callback = &std_callback, .std_callback = &std_callback,
.ioctls = &ioctls[0],
.ioctl = hexium_ioctl,
}; };
static struct saa7146_extension extension = { static struct saa7146_extension extension = {
......
此差异已折叠。
...@@ -150,16 +150,6 @@ struct saa7146_vv ...@@ -150,16 +150,6 @@ struct saa7146_vv
unsigned int resources; /* resource management for device */ unsigned int resources; /* resource management for device */
}; };
#define SAA7146_EXCLUSIVE 0x1
#define SAA7146_BEFORE 0x2
#define SAA7146_AFTER 0x4
struct saa7146_extension_ioctls
{
unsigned int cmd;
int flags;
};
/* flags */ /* flags */
#define SAA7146_USE_PORT_B_FOR_VBI 0x2 /* use input port b for vbi hardware bug workaround */ #define SAA7146_USE_PORT_B_FOR_VBI 0x2 /* use input port b for vbi hardware bug workaround */
...@@ -176,8 +166,10 @@ struct saa7146_ext_vv ...@@ -176,8 +166,10 @@ struct saa7146_ext_vv
int num_stds; int num_stds;
int (*std_callback)(struct saa7146_dev*, struct saa7146_standard *); int (*std_callback)(struct saa7146_dev*, struct saa7146_standard *);
struct saa7146_extension_ioctls *ioctls; /* the extension can override this */
long (*ioctl)(struct saa7146_fh *, unsigned int cmd, void *arg); struct v4l2_ioctl_ops ops;
/* pointer to the saa7146 core ops */
const struct v4l2_ioctl_ops *core_ops;
struct v4l2_file_operations vbi_fops; struct v4l2_file_operations vbi_fops;
}; };
...@@ -213,6 +205,7 @@ void saa7146_set_hps_source_and_sync(struct saa7146_dev *saa, int source, int sy ...@@ -213,6 +205,7 @@ void saa7146_set_hps_source_and_sync(struct saa7146_dev *saa, int source, int sy
void saa7146_set_gpio(struct saa7146_dev *saa, u8 pin, u8 data); void saa7146_set_gpio(struct saa7146_dev *saa, u8 pin, u8 data);
/* from saa7146_video.c */ /* from saa7146_video.c */
extern const struct v4l2_ioctl_ops saa7146_video_ioctl_ops;
extern struct saa7146_use_ops saa7146_video_uops; extern struct saa7146_use_ops saa7146_video_uops;
int saa7146_start_preview(struct saa7146_fh *fh); int saa7146_start_preview(struct saa7146_fh *fh);
int saa7146_stop_preview(struct saa7146_fh *fh); int saa7146_stop_preview(struct saa7146_fh *fh);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册