Commit b3c4ee70 authored by Mauro Carvalho Chehab's avatar Mauro Carvalho Chehab

V4L/DVB (5109): Convert cx88-blackbird to use video_ioctl2

This patch finishes cx88-blackbird conversion to use video_ioctl2. Video
standards are generated automatically inside videodev.c. the big ioctl
parser is removed, using, instead, video_ioctl2.
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@infradead.org>
parent 7730bef9
...@@ -6,6 +6,9 @@ ...@@ -6,6 +6,9 @@
* (c) 2004 Jelle Foks <jelle@foks.8m.com> * (c) 2004 Jelle Foks <jelle@foks.8m.com>
* (c) 2004 Gerd Knorr <kraxel@bytesex.org> * (c) 2004 Gerd Knorr <kraxel@bytesex.org>
* *
* (c) 2005-2006 Mauro Carvalho Chehab <mchehab@infradead.org>
* - video_ioctl2 conversion
*
* Includes parts from the ivtv driver( http://ivtv.sourceforge.net/), * Includes parts from the ivtv driver( http://ivtv.sourceforge.net/),
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
...@@ -53,73 +56,6 @@ MODULE_PARM_DESC(debug,"enable debug messages [blackbird]"); ...@@ -53,73 +56,6 @@ MODULE_PARM_DESC(debug,"enable debug messages [blackbird]");
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
struct cx88_tvnorm {
char *name;
v4l2_std_id id;
u32 cxiformat;
u32 cxoformat;
};
static struct cx88_tvnorm tvnorms[] = {
{
.name = "NTSC-M",
.id = V4L2_STD_NTSC_M,
.cxiformat = VideoFormatNTSC,
.cxoformat = 0x181f0008,
},{
.name = "NTSC-JP",
.id = V4L2_STD_NTSC_M_JP,
.cxiformat = VideoFormatNTSCJapan,
.cxoformat = 0x181f0008,
},{
.name = "PAL-BG",
.id = V4L2_STD_PAL_BG,
.cxiformat = VideoFormatPAL,
.cxoformat = 0x181f0008,
},{
.name = "PAL-DK",
.id = V4L2_STD_PAL_DK,
.cxiformat = VideoFormatPAL,
.cxoformat = 0x181f0008,
},{
.name = "PAL-I",
.id = V4L2_STD_PAL_I,
.cxiformat = VideoFormatPAL,
.cxoformat = 0x181f0008,
},{
.name = "PAL-M",
.id = V4L2_STD_PAL_M,
.cxiformat = VideoFormatPALM,
.cxoformat = 0x1c1f0008,
},{
.name = "PAL-N",
.id = V4L2_STD_PAL_N,
.cxiformat = VideoFormatPALN,
.cxoformat = 0x1c1f0008,
},{
.name = "PAL-Nc",
.id = V4L2_STD_PAL_Nc,
.cxiformat = VideoFormatPALNC,
.cxoformat = 0x1c1f0008,
},{
.name = "PAL-60",
.id = V4L2_STD_PAL_60,
.cxiformat = VideoFormatPAL60,
.cxoformat = 0x181f0008,
},{
.name = "SECAM-L",
.id = V4L2_STD_SECAM_L,
.cxiformat = VideoFormatSECAM,
.cxoformat = 0x181f0008,
},{
.name = "SECAM-DK",
.id = V4L2_STD_SECAM_DK,
.cxiformat = VideoFormatSECAM,
.cxoformat = 0x181f0008,
}
};
#define BLACKBIRD_FIRM_IMAGE_SIZE 256*1024 #define BLACKBIRD_FIRM_IMAGE_SIZE 256*1024
/* defines below are from ivtv-driver.h */ /* defines below are from ivtv-driver.h */
...@@ -777,8 +713,13 @@ static int blackbird_queryctrl(struct cx8802_dev *dev, struct v4l2_queryctrl *qc ...@@ -777,8 +713,13 @@ static int blackbird_queryctrl(struct cx8802_dev *dev, struct v4l2_queryctrl *qc
return 0; return 0;
} }
static int blackbird_querymenu(struct cx8802_dev *dev, struct v4l2_querymenu *qmenu) /* ------------------------------------------------------------------ */
/* IOCTL Handlers */
static int vidioc_querymenu (struct file *file, void *priv,
struct v4l2_querymenu *qmenu)
{ {
struct cx8802_dev *dev = ((struct cx8802_fh *)priv)->dev;
struct v4l2_queryctrl qctrl; struct v4l2_queryctrl qctrl;
qctrl.id = qmenu->id; qctrl.id = qmenu->id;
...@@ -786,413 +727,347 @@ static int blackbird_querymenu(struct cx8802_dev *dev, struct v4l2_querymenu *qm ...@@ -786,413 +727,347 @@ static int blackbird_querymenu(struct cx8802_dev *dev, struct v4l2_querymenu *qm
return v4l2_ctrl_query_menu(qmenu, &qctrl, cx2341x_ctrl_get_menu(qmenu->id)); return v4l2_ctrl_query_menu(qmenu, &qctrl, cx2341x_ctrl_get_menu(qmenu->id));
} }
/* ------------------------------------------------------------------ */ static int vidioc_querycap (struct file *file, void *priv,
struct v4l2_capability *cap)
static int mpeg_do_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, void *arg)
{ {
struct cx8802_fh *fh = file->private_data; struct cx8802_dev *dev = ((struct cx8802_fh *)priv)->dev;
struct cx8802_dev *dev = fh->dev;
struct cx88_core *core = dev->core; struct cx88_core *core = dev->core;
if (debug > 1) strcpy(cap->driver, "cx88_blackbird");
v4l_print_ioctl(core->name,cmd); strlcpy(cap->card, cx88_boards[core->board].name,sizeof(cap->card));
sprintf(cap->bus_info,"PCI:%s",pci_name(dev->pci));
cap->version = CX88_VERSION_CODE;
cap->capabilities =
V4L2_CAP_VIDEO_CAPTURE |
V4L2_CAP_READWRITE |
V4L2_CAP_STREAMING;
if (UNSET != core->tuner_type)
cap->capabilities |= V4L2_CAP_TUNER;
return 0;
}
static int vidioc_enum_fmt_cap (struct file *file, void *priv,
struct v4l2_fmtdesc *f)
{
if (f->index != 0)
return -EINVAL;
switch (cmd) { strlcpy(f->description, "MPEG", sizeof(f->description));
f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
f->pixelformat = V4L2_PIX_FMT_MPEG;
return 0;
}
/* --- capabilities ------------------------------------------ */ static int vidioc_g_fmt_cap (struct file *file, void *priv,
case VIDIOC_QUERYCAP: struct v4l2_format *f)
{ {
struct v4l2_capability *cap = arg; struct cx8802_fh *fh = priv;
struct cx8802_dev *dev = fh->dev;
f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
f->fmt.pix.bytesperline = 0;
f->fmt.pix.sizeimage = dev->ts_packet_size * dev->ts_packet_count; /* 188 * 4 * 1024; */
f->fmt.pix.colorspace = 0;
f->fmt.pix.width = dev->width;
f->fmt.pix.height = dev->height;
f->fmt.pix.field = fh->mpegq.field;
dprintk(0,"VIDIOC_G_FMT: w: %d, h: %d, f: %d\n",
dev->width, dev->height, fh->mpegq.field );
return 0;
}
memset(cap,0,sizeof(*cap)); static int vidioc_try_fmt_cap (struct file *file, void *priv,
strcpy(cap->driver, "cx88_blackbird"); struct v4l2_format *f)
strlcpy(cap->card, cx88_boards[core->board].name,sizeof(cap->card)); {
sprintf(cap->bus_info,"PCI:%s",pci_name(dev->pci)); struct cx8802_fh *fh = priv;
cap->version = CX88_VERSION_CODE; struct cx8802_dev *dev = fh->dev;
cap->capabilities =
V4L2_CAP_VIDEO_CAPTURE | f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
V4L2_CAP_READWRITE | f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
V4L2_CAP_STREAMING; f->fmt.pix.bytesperline = 0;
if (UNSET != core->tuner_type) f->fmt.pix.sizeimage = dev->ts_packet_size * dev->ts_packet_count; /* 188 * 4 * 1024; */;
cap->capabilities |= V4L2_CAP_TUNER; f->fmt.pix.colorspace = 0;
dprintk(0,"VIDIOC_TRY_FMT: w: %d, h: %d, f: %d\n",
dev->width, dev->height, fh->mpegq.field );
return 0;
}
return 0; static int vidioc_s_fmt_cap (struct file *file, void *priv,
} struct v4l2_format *f)
{
struct cx8802_fh *fh = priv;
struct cx8802_dev *dev = fh->dev;
struct cx88_core *core = dev->core;
/* --- capture ioctls ---------------------------------------- */ f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
case VIDIOC_ENUM_FMT: f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
{ f->fmt.pix.bytesperline = 0;
struct v4l2_fmtdesc *f = arg; f->fmt.pix.sizeimage = dev->ts_packet_size * dev->ts_packet_count; /* 188 * 4 * 1024; */;
int index; f->fmt.pix.colorspace = 0;
dev->width = f->fmt.pix.width;
index = f->index; dev->height = f->fmt.pix.height;
if (index != 0) fh->mpegq.field = f->fmt.pix.field;
return -EINVAL; cx88_set_scale(core, f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.field);
blackbird_api_cmd(dev, CX2341X_ENC_SET_FRAME_SIZE, 2, 0,
memset(f,0,sizeof(*f)); f->fmt.pix.height, f->fmt.pix.width);
f->index = index; dprintk(0,"VIDIOC_S_FMT: w: %d, h: %d, f: %d\n",
strlcpy(f->description, "MPEG", sizeof(f->description)); f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.field );
f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; return 0;
f->pixelformat = V4L2_PIX_FMT_MPEG; }
return 0;
}
case VIDIOC_G_FMT:
{
struct v4l2_format *f = arg;
memset(f,0,sizeof(*f));
f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
f->fmt.pix.bytesperline = 0;
f->fmt.pix.sizeimage = dev->ts_packet_size * dev->ts_packet_count; /* 188 * 4 * 1024; */
f->fmt.pix.colorspace = 0;
f->fmt.pix.width = dev->width;
f->fmt.pix.height = dev->height;
f->fmt.pix.field = fh->mpegq.field;
dprintk(0,"VIDIOC_G_FMT: w: %d, h: %d, f: %d\n",
dev->width, dev->height, fh->mpegq.field );
return 0;
}
case VIDIOC_TRY_FMT:
{
struct v4l2_format *f = arg;
f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
f->fmt.pix.bytesperline = 0;
f->fmt.pix.sizeimage = dev->ts_packet_size * dev->ts_packet_count; /* 188 * 4 * 1024; */;
f->fmt.pix.colorspace = 0;
dprintk(0,"VIDIOC_TRY_FMT: w: %d, h: %d, f: %d\n",
dev->width, dev->height, fh->mpegq.field );
return 0;
}
case VIDIOC_S_FMT:
{
struct v4l2_format *f = arg;
f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
f->fmt.pix.bytesperline = 0;
f->fmt.pix.sizeimage = dev->ts_packet_size * dev->ts_packet_count; /* 188 * 4 * 1024; */;
f->fmt.pix.colorspace = 0;
dprintk(0,"VIDIOC_S_FMT: w: %d, h: %d, f: %d\n",
f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.field );
return 0;
}
/* --- streaming capture ------------------------------------- */ static int vidioc_reqbufs (struct file *file, void *priv, struct v4l2_requestbuffers *p)
case VIDIOC_REQBUFS: {
return videobuf_reqbufs(&fh->mpegq, arg); struct cx8802_fh *fh = priv;
return (videobuf_reqbufs(&fh->mpegq, p));
}
case VIDIOC_QUERYBUF: static int vidioc_querybuf (struct file *file, void *priv, struct v4l2_buffer *p)
return videobuf_querybuf(&fh->mpegq, arg); {
struct cx8802_fh *fh = priv;
return (videobuf_querybuf(&fh->mpegq, p));
}
case VIDIOC_QBUF: static int vidioc_qbuf (struct file *file, void *priv, struct v4l2_buffer *p)
return videobuf_qbuf(&fh->mpegq, arg); {
struct cx8802_fh *fh = priv;
return (videobuf_qbuf(&fh->mpegq, p));
}
case VIDIOC_DQBUF: static int vidioc_dqbuf (struct file *file, void *priv, struct v4l2_buffer *p)
return videobuf_dqbuf(&fh->mpegq, arg, {
file->f_flags & O_NONBLOCK); struct cx8802_fh *fh = priv;
return (videobuf_dqbuf(&fh->mpegq, p,
file->f_flags & O_NONBLOCK));
}
case VIDIOC_STREAMON: static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
return videobuf_streamon(&fh->mpegq); {
struct cx8802_fh *fh = priv;
return videobuf_streamon(&fh->mpegq);
}
case VIDIOC_STREAMOFF: static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
return videobuf_streamoff(&fh->mpegq); {
struct cx8802_fh *fh = priv;
return videobuf_streamoff(&fh->mpegq);
}
/* --- mpeg compression -------------------------------------- */ static int vidioc_g_mpegcomp (struct file *file, void *fh,
case VIDIOC_G_MPEGCOMP: struct v4l2_mpeg_compression *f)
{ {
struct v4l2_mpeg_compression *f = arg; printk(KERN_WARNING "VIDIOC_G_MPEGCOMP is obsolete. "
"Replace with VIDIOC_G_EXT_CTRLS!");
memcpy(f,&default_mpeg_params,sizeof(*f));
return 0;
}
printk(KERN_WARNING "VIDIOC_G_MPEGCOMP is obsolete. " static int vidioc_s_mpegcomp (struct file *file, void *fh,
"Replace with VIDIOC_G_EXT_CTRLS!"); struct v4l2_mpeg_compression *f)
memcpy(f,&default_mpeg_params,sizeof(*f)); {
return 0; printk(KERN_WARNING "VIDIOC_S_MPEGCOMP is obsolete. "
} "Replace with VIDIOC_S_EXT_CTRLS!");
case VIDIOC_S_MPEGCOMP: return 0;
printk(KERN_WARNING "VIDIOC_S_MPEGCOMP is obsolete. " }
"Replace with VIDIOC_S_EXT_CTRLS!");
return 0;
case VIDIOC_G_EXT_CTRLS:
{
struct v4l2_ext_controls *f = arg;
if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG) static int vidioc_g_ext_ctrls (struct file *file, void *priv,
return -EINVAL; struct v4l2_ext_controls *f)
return cx2341x_ext_ctrls(&dev->params, f, cmd); {
} struct cx8802_dev *dev = ((struct cx8802_fh *)priv)->dev;
case VIDIOC_S_EXT_CTRLS:
{
struct v4l2_ext_controls *f = arg;
struct cx2341x_mpeg_params p;
int err;
if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG)
return -EINVAL;
p = dev->params;
err = cx2341x_ext_ctrls(&p, VIDIOC_S_EXT_CTRLS, cmd);
if (err == 0 && cmd == VIDIOC_S_EXT_CTRLS) {
err = cx2341x_update(dev, blackbird_mbox_func, &dev->params, &p);
dev->params = p;
}
return err;
}
case VIDIOC_TRY_EXT_CTRLS:
{
struct v4l2_ext_controls *f = arg;
struct cx2341x_mpeg_params p;
int err;
if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG)
return -EINVAL;
p = dev->params;
err = cx2341x_ext_ctrls(&p, VIDIOC_TRY_EXT_CTRLS, cmd);
return err;
}
case VIDIOC_S_FREQUENCY:
{
struct v4l2_frequency *f = arg;
blackbird_api_cmd(fh->dev, CX2341X_ENC_STOP_CAPTURE, 3, 0, if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG)
BLACKBIRD_END_NOW, return -EINVAL;
BLACKBIRD_MPEG_CAPTURE, return cx2341x_ext_ctrls(&dev->params, f, VIDIOC_G_EXT_CTRLS);
BLACKBIRD_RAW_BITS_NONE); }
cx88_set_freq (core,f); static int vidioc_s_ext_ctrls (struct file *file, void *priv,
struct v4l2_ext_controls *f)
{
struct cx8802_dev *dev = ((struct cx8802_fh *)priv)->dev;
struct cx2341x_mpeg_params p;
int err;
blackbird_initialize_codec(dev); if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG)
cx88_set_scale(dev->core, dev->width, dev->height, return -EINVAL;
fh->mpegq.field); p = dev->params;
return 0; err = cx2341x_ext_ctrls(&p, f, VIDIOC_S_EXT_CTRLS);
} if (!err) {
case VIDIOC_LOG_STATUS: err = cx2341x_update(dev, blackbird_mbox_func, &dev->params, &p);
{ dev->params = p;
char name[32 + 2];
snprintf(name, sizeof(name), "%s/2", core->name);
printk("%s/2: ============ START LOG STATUS ============\n",
core->name);
cx88_call_i2c_clients(core, VIDIOC_LOG_STATUS, NULL);
cx2341x_log_status(&dev->params, name);
printk("%s/2: ============= END LOG STATUS =============\n",
core->name);
return 0;
} }
case VIDIOC_QUERYMENU: return err;
return blackbird_querymenu(dev, arg); }
case VIDIOC_QUERYCTRL:
{
struct v4l2_queryctrl *qctrl = arg;
if (blackbird_queryctrl(dev, qctrl) == 0) static int vidioc_try_ext_ctrls (struct file *file, void *priv,
return 0; struct v4l2_ext_controls *f)
{
struct cx8802_dev *dev = ((struct cx8802_fh *)priv)->dev;
struct cx2341x_mpeg_params p;
int err;
struct v4l2_queryctrl *qctrl = arg; if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG)
return -EINVAL;
p = dev->params;
err = cx2341x_ext_ctrls(&p, f, VIDIOC_TRY_EXT_CTRLS);
qctrl->id = v4l2_ctrl_next(ctrl_classes, qctrl->id); return err;
if (unlikely(qctrl->id == 0)) }
return -EINVAL;
return cx8800_ctrl_query(qctrl);
}
/* ------ input switching ---------- */ static int vidioc_s_frequency (struct file *file, void *priv,
case VIDIOC_ENUMINPUT: struct v4l2_frequency *f)
{ {
static const char *iname[] = { struct cx8802_fh *fh = priv;
[ CX88_VMUX_COMPOSITE1 ] = "Composite1", struct cx8802_dev *dev = fh->dev;
[ CX88_VMUX_COMPOSITE2 ] = "Composite2", struct cx88_core *core = dev->core;
[ CX88_VMUX_COMPOSITE3 ] = "Composite3",
[ CX88_VMUX_COMPOSITE4 ] = "Composite4",
[ CX88_VMUX_SVIDEO ] = "S-Video",
[ CX88_VMUX_TELEVISION ] = "Television",
[ CX88_VMUX_CABLE ] = "Cable TV",
[ CX88_VMUX_DVB ] = "DVB",
[ CX88_VMUX_DEBUG ] = "for debug only",
};
struct v4l2_input *i = arg;
unsigned int n;
n = i->index;
if (n >= 4)
return -EINVAL;
if (0 == INPUT(n)->type)
return -EINVAL;
memset(i,0,sizeof(*i));
i->index = n;
i->type = V4L2_INPUT_TYPE_CAMERA;
strcpy(i->name,iname[INPUT(n)->type]);
if ((CX88_VMUX_TELEVISION == INPUT(n)->type) ||
(CX88_VMUX_CABLE == INPUT(n)->type))
i->type = V4L2_INPUT_TYPE_TUNER;
for (n = 0; n < ARRAY_SIZE(tvnorms); n++)
i->std |= tvnorms[n].id;
return 0;
}
case VIDIOC_G_CTRL:
return cx88_get_control(core,arg);
case VIDIOC_S_CTRL:
return cx88_set_control(core,arg);
case VIDIOC_G_FREQUENCY: blackbird_api_cmd(fh->dev, CX2341X_ENC_STOP_CAPTURE, 3, 0,
{ BLACKBIRD_END_NOW,
struct v4l2_frequency *f = arg; BLACKBIRD_MPEG_CAPTURE,
BLACKBIRD_RAW_BITS_NONE);
cx88_set_freq (core,f);
blackbird_initialize_codec(dev);
cx88_set_scale(dev->core, dev->width, dev->height,
fh->mpegq.field);
return 0;
}
memset(f,0,sizeof(*f)); static int vidioc_log_status (struct file *file, void *priv)
{
struct cx8802_dev *dev = ((struct cx8802_fh *)priv)->dev;
struct cx88_core *core = dev->core;
char name[32 + 2];
snprintf(name, sizeof(name), "%s/2", core->name);
printk("%s/2: ============ START LOG STATUS ============\n",
core->name);
cx88_call_i2c_clients(core, VIDIOC_LOG_STATUS, NULL);
cx2341x_log_status(&dev->params, name);
printk("%s/2: ============= END LOG STATUS =============\n",
core->name);
return 0;
}
if (UNSET == core->tuner_type) static int vidioc_queryctrl (struct file *file, void *priv,
return -EINVAL; struct v4l2_queryctrl *qctrl)
{
struct cx8802_dev *dev = ((struct cx8802_fh *)priv)->dev;
/* f->type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; */ if (blackbird_queryctrl(dev, qctrl) == 0)
f->type = radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; return 0;
f->frequency = core->freq;
cx88_call_i2c_clients(core,VIDIOC_G_FREQUENCY,f); qctrl->id = v4l2_ctrl_next(ctrl_classes, qctrl->id);
if (unlikely(qctrl->id == 0))
return -EINVAL;
return cx8800_ctrl_query(qctrl);
}
return 0; static int vidioc_enum_input (struct file *file, void *priv,
} struct v4l2_input *i)
case VIDIOC_G_INPUT: {
{ struct cx88_core *core = ((struct cx8802_fh *)priv)->dev->core;
unsigned int *i = arg; return cx88_enum_input (core,i);
}
*i = core->input; static int vidioc_g_ctrl (struct file *file, void *priv,
return 0; struct v4l2_control *ctl)
} {
case VIDIOC_S_INPUT: struct cx88_core *core = ((struct cx8802_fh *)priv)->dev->core;
{ return
unsigned int *i = arg; cx88_get_control(core,ctl);
}
if (*i >= 4)
return -EINVAL;
mutex_lock(&core->lock);
cx88_newstation(core);
cx88_video_mux(core,*i);
mutex_unlock(&core->lock);
return 0;
}
static int vidioc_s_ctrl (struct file *file, void *priv,
struct v4l2_control *ctl)
{
struct cx88_core *core = ((struct cx8802_fh *)priv)->dev->core;
return
cx88_set_control(core,ctl);
}
case VIDIOC_G_TUNER: static int vidioc_g_frequency (struct file *file, void *priv,
{ struct v4l2_frequency *f)
struct v4l2_tuner *t = arg; {
u32 reg; struct cx8802_fh *fh = priv;
struct cx88_core *core = fh->dev->core;
if (UNSET == core->tuner_type) if (unlikely(UNSET == core->tuner_type))
return -EINVAL; return -EINVAL;
if (0 != t->index)
return -EINVAL;
memset(t,0,sizeof(*t)); f->type = V4L2_TUNER_ANALOG_TV;
strcpy(t->name, "Television"); f->frequency = core->freq;
t->type = V4L2_TUNER_ANALOG_TV; cx88_call_i2c_clients(core,VIDIOC_G_FREQUENCY,f);
t->capability = V4L2_TUNER_CAP_NORM;
t->rangehigh = 0xffffffffUL;
cx88_get_stereo(core ,t); return 0;
reg = cx_read(MO_DEVICE_STATUS); }
t->signal = (reg & (1<<5)) ? 0xffff : 0x0000;
return 0;
}
case VIDIOC_S_TUNER:
{
struct v4l2_tuner *t = arg;
if (UNSET == core->tuner_type)
return -EINVAL;
if (0 != t->index)
return -EINVAL;
cx88_set_stereo(core, t->audmode, 1);
return 0;
}
/* ---------- tv norms ---------- */
case VIDIOC_S_STD:
{
v4l2_std_id *id = arg;
unsigned int i;
for(i = 0; i < ARRAY_SIZE(tvnorms); i++)
if (*id & tvnorms[i].id)
break;
if (i == ARRAY_SIZE(tvnorms))
return -EINVAL;
mutex_lock(&core->lock);
cx88_set_tvnorm(core,tvnorms[i].id);
mutex_unlock(&core->lock);
return 0;
}
case VIDIOC_ENUMSTD:
{
struct v4l2_standard *e = arg;
unsigned int i;
i = e->index;
if (i >= ARRAY_SIZE(tvnorms))
return -EINVAL;
err = v4l2_video_std_construct(e, tvnorms[e->index].id,
tvnorms[e->index].name);
e->index = i;
if (err < 0)
return err;
return 0;
}
case VIDIOC_G_STD:
{
v4l2_std_id *id = arg;
*id = core->tvnorm; static int vidioc_g_input (struct file *file, void *priv, unsigned int *i)
return 0; {
} struct cx88_core *core = ((struct cx8802_fh *)priv)->dev->core;
#ifdef CONFIG_VIDEO_ADV_DEBUG *i = core->input;
/* ioctls to allow direct acces to the cx2388x registers */ return 0;
case VIDIOC_INT_G_REGISTER: }
{
struct v4l2_register *reg = arg;
if (reg->i2c_id != 0) static int vidioc_s_input (struct file *file, void *priv, unsigned int i)
return -EINVAL; {
/* cx2388x has a 24-bit register space */ struct cx88_core *core = ((struct cx8802_fh *)priv)->dev->core;
reg->val = cx_read(reg->reg&0xffffff);
return 0;
}
case VIDIOC_INT_S_REGISTER:
{
struct v4l2_register *reg = arg;
if (reg->i2c_id != 0)
return -EINVAL;
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
cx_write(reg->reg&0xffffff, reg->val);
return 0;
}
#endif
default: if (i >= 4)
return v4l_compat_translate_ioctl(inode,file,cmd,arg, return -EINVAL;
driver_ioctl);
} mutex_lock(&core->lock);
cx88_newstation(core);
cx88_video_mux(core,i);
mutex_unlock(&core->lock);
return 0; return 0;
} }
int (*cx88_ioctl_hook)(struct inode *inode, struct file *file, static int vidioc_g_tuner (struct file *file, void *priv,
unsigned int cmd, void *arg); struct v4l2_tuner *t)
unsigned int (*cx88_ioctl_translator)(unsigned int cmd); {
struct cx88_core *core = ((struct cx8802_fh *)priv)->dev->core;
u32 reg;
if (unlikely(UNSET == core->tuner_type))
return -EINVAL;
strcpy(t->name, "Television");
t->type = V4L2_TUNER_ANALOG_TV;
t->capability = V4L2_TUNER_CAP_NORM;
t->rangehigh = 0xffffffffUL;
cx88_get_stereo(core ,t);
reg = cx_read(MO_DEVICE_STATUS);
t->signal = (reg & (1<<5)) ? 0xffff : 0x0000;
return 0;
}
static unsigned int mpeg_translate_ioctl(unsigned int cmd) static int vidioc_s_tuner (struct file *file, void *priv,
struct v4l2_tuner *t)
{ {
return cmd; struct cx88_core *core = ((struct cx8802_fh *)priv)->dev->core;
if (UNSET == core->tuner_type)
return -EINVAL;
if (0 != t->index)
return -EINVAL;
cx88_set_stereo(core, t->audmode, 1);
return 0;
} }
static int mpeg_ioctl(struct inode *inode, struct file *file, static int vidioc_s_std (struct file *file, void *priv, v4l2_std_id *id)
unsigned int cmd, unsigned long arg)
{ {
cmd = cx88_ioctl_translator( cmd ); struct cx88_core *core = ((struct cx8802_fh *)priv)->dev->core;
return video_usercopy(inode, file, cmd, arg, cx88_ioctl_hook);
mutex_lock(&core->lock);
cx88_set_tvnorm(core,*id);
mutex_unlock(&core->lock);
return 0;
} }
/* FIXME: cx88_ioctl_hook not implemented */
static int mpeg_open(struct inode *inode, struct file *file) static int mpeg_open(struct inode *inode, struct file *file)
{ {
int minor = iminor(inode); int minor = iminor(inode);
...@@ -1318,17 +1193,47 @@ static const struct file_operations mpeg_fops = ...@@ -1318,17 +1193,47 @@ static const struct file_operations mpeg_fops =
.read = mpeg_read, .read = mpeg_read,
.poll = mpeg_poll, .poll = mpeg_poll,
.mmap = mpeg_mmap, .mmap = mpeg_mmap,
.ioctl = mpeg_ioctl, .ioctl = video_ioctl2,
.llseek = no_llseek, .llseek = no_llseek,
}; };
static struct video_device cx8802_mpeg_template = static struct video_device cx8802_mpeg_template =
{ {
.name = "cx8802", .name = "cx8802",
.type = VID_TYPE_CAPTURE|VID_TYPE_TUNER|VID_TYPE_SCALES|VID_TYPE_MPEG_ENCODER, .type = VID_TYPE_CAPTURE|VID_TYPE_TUNER|VID_TYPE_SCALES|VID_TYPE_MPEG_ENCODER,
.hardware = 0, .fops = &mpeg_fops,
.fops = &mpeg_fops, .minor = -1,
.minor = -1, .vidioc_querymenu = vidioc_querymenu,
.vidioc_querycap = vidioc_querycap,
.vidioc_enum_fmt_cap = vidioc_enum_fmt_cap,
.vidioc_g_fmt_cap = vidioc_g_fmt_cap,
.vidioc_try_fmt_cap = vidioc_try_fmt_cap,
.vidioc_s_fmt_cap = vidioc_s_fmt_cap,
.vidioc_reqbufs = vidioc_reqbufs,
.vidioc_querybuf = vidioc_querybuf,
.vidioc_qbuf = vidioc_qbuf,
.vidioc_dqbuf = vidioc_dqbuf,
.vidioc_streamon = vidioc_streamon,
.vidioc_streamoff = vidioc_streamoff,
.vidioc_g_mpegcomp = vidioc_g_mpegcomp,
.vidioc_s_mpegcomp = vidioc_s_mpegcomp,
.vidioc_g_ext_ctrls = vidioc_g_ext_ctrls,
.vidioc_s_ext_ctrls = vidioc_s_ext_ctrls,
.vidioc_try_ext_ctrls = vidioc_try_ext_ctrls,
.vidioc_s_frequency = vidioc_s_frequency,
.vidioc_log_status = vidioc_log_status,
.vidioc_queryctrl = vidioc_queryctrl,
.vidioc_enum_input = vidioc_enum_input,
.vidioc_g_ctrl = vidioc_g_ctrl,
.vidioc_s_ctrl = vidioc_s_ctrl,
.vidioc_g_frequency = vidioc_g_frequency,
.vidioc_g_input = vidioc_g_input,
.vidioc_s_input = vidioc_s_input,
.vidioc_g_tuner = vidioc_g_tuner,
.vidioc_s_tuner = vidioc_s_tuner,
.vidioc_s_std = vidioc_s_std,
.tvnorms = CX88_NORMS,
.current_norm = V4L2_STD_PAL_BG,
}; };
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
...@@ -1423,6 +1328,8 @@ static int cx8802_blackbird_probe(struct cx8802_driver *drv) ...@@ -1423,6 +1328,8 @@ static int cx8802_blackbird_probe(struct cx8802_driver *drv)
cx2341x_fill_defaults(&dev->params); cx2341x_fill_defaults(&dev->params);
dev->params.port = CX2341X_PORT_STREAMING; dev->params.port = CX2341X_PORT_STREAMING;
cx8802_mpeg_template.current_norm = core->tvnorm;
if (core->tvnorm & V4L2_STD_525_60) { if (core->tvnorm & V4L2_STD_525_60) {
dev->height = 480; dev->height = 480;
} else { } else {
...@@ -1437,6 +1344,11 @@ static int cx8802_blackbird_probe(struct cx8802_driver *drv) ...@@ -1437,6 +1344,11 @@ static int cx8802_blackbird_probe(struct cx8802_driver *drv)
blackbird_register_video(dev); blackbird_register_video(dev);
/* initial device configuration: needed ? */ /* initial device configuration: needed ? */
mutex_lock(&dev->core->lock);
// init_controls(core);
cx88_set_tvnorm(core,core->tvnorm);
cx88_video_mux(core,0);
mutex_unlock(&dev->core->lock);
return 0; return 0;
...@@ -1471,8 +1383,6 @@ static int blackbird_init(void) ...@@ -1471,8 +1383,6 @@ static int blackbird_init(void)
printk(KERN_INFO "cx2388x: snapshot date %04d-%02d-%02d\n", printk(KERN_INFO "cx2388x: snapshot date %04d-%02d-%02d\n",
SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100); SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100);
#endif #endif
cx88_ioctl_hook = mpeg_do_ioctl;
cx88_ioctl_translator = mpeg_translate_ioctl;
return cx8802_register_driver(&cx8802_blackbird_driver); return cx8802_register_driver(&cx8802_blackbird_driver);
} }
...@@ -1484,8 +1394,8 @@ static void blackbird_fini(void) ...@@ -1484,8 +1394,8 @@ static void blackbird_fini(void)
module_init(blackbird_init); module_init(blackbird_init);
module_exit(blackbird_fini); module_exit(blackbird_fini);
EXPORT_SYMBOL(cx88_ioctl_hook); module_param_named(video_debug,cx8802_mpeg_template.debug, int, 0644);
EXPORT_SYMBOL(cx88_ioctl_translator); MODULE_PARM_DESC(debug,"enable debug messages [video]");
/* ----------------------------------------------------------- */ /* ----------------------------------------------------------- */
/* /*
......
...@@ -645,13 +645,6 @@ int cx88_get_control(struct cx88_core *core, struct v4l2_control *ctl); ...@@ -645,13 +645,6 @@ int cx88_get_control(struct cx88_core *core, struct v4l2_control *ctl);
int cx88_set_control(struct cx88_core *core, struct v4l2_control *ctl); int cx88_set_control(struct cx88_core *core, struct v4l2_control *ctl);
int cx88_video_mux(struct cx88_core *core, unsigned int input); int cx88_video_mux(struct cx88_core *core, unsigned int input);
/* ----------------------------------------------------------- */
/* cx88-blackbird.c */
/* used by cx88-ivtv ioctl emulation layer */
extern int (*cx88_ioctl_hook)(struct inode *inode, struct file *file,
unsigned int cmd, void *arg);
extern unsigned int (*cx88_ioctl_translator)(unsigned int cmd);
/* /*
* Local variables: * Local variables:
* c-basic-offset: 8 * c-basic-offset: 8
......
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