V4L/DVB (5104): Moved several stuff that were at cx88-video to cx88-blackbird.c
authorMauro Carvalho Chehab <mchehab@infradead.org>
Sat, 20 Jan 2007 16:58:39 +0000 (13:58 -0300)
committerMauro Carvalho Chehab <mchehab@infradead.org>
Wed, 21 Feb 2007 15:34:44 +0000 (13:34 -0200)
cx88-blackbird were using some ioctl handling that were previously on
cx88-video.

Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
drivers/media/video/cx88/cx88-blackbird.c

index 9a7a299..2eb31ff 100644 (file)
@@ -53,6 +53,76 @@ 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,
+       }
+};
+int cx88_do_ioctl( struct inode *inode, struct file *file,
+                  int radio, struct cx88_core *core, unsigned int cmd,
+                  void *arg, v4l2_kioctl driver_ioctl );
+
 #define BLACKBIRD_FIRM_IMAGE_SIZE 256*1024
 
 /* defines below are from ivtv-driver.h */
@@ -520,7 +590,7 @@ static void blackbird_codec_settings(struct cx8802_dev *dev)
 
        dev->params.width = dev->width;
        dev->params.height = dev->height;
-       dev->params.is_50hz = (dev->core->tvnorm->id & V4L2_STD_625_50) != 0;
+       dev->params.is_50hz = (dev->core->tvnorm & V4L2_STD_625_50) != 0;
 
        cx2341x_update(dev, blackbird_mbox_func, NULL, &dev->params);
 }
@@ -918,6 +988,240 @@ static int mpeg_do_ioctl(struct inode *inode, struct file *file,
        return 0;
 }
 
+int cx88_do_ioctl(struct inode *inode, struct file *file, int radio,
+                 struct cx88_core *core, unsigned int cmd, void *arg, v4l2_kioctl driver_ioctl)
+{
+       int err;
+
+       if (debug) {
+              if (debug > 1) {
+                      if (_IOC_DIR(cmd) & _IOC_WRITE)
+                              v4l_printk_ioctl_arg("cx88(w)",cmd, arg);
+                      else if (!_IOC_DIR(cmd) & _IOC_READ) {
+                              v4l_print_ioctl("cx88", cmd);
+                      }
+              } else
+                      v4l_print_ioctl(core->name,cmd);
+
+       }
+
+       switch (cmd) {
+       /* ---------- tv norms ---------- */
+       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;
+               return 0;
+       }
+       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;
+       }
+
+       /* ------ input switching ---------- */
+       case VIDIOC_ENUMINPUT:
+       {
+               static const char *iname[] = {
+                       [ CX88_VMUX_COMPOSITE1 ] = "Composite1",
+                       [ CX88_VMUX_COMPOSITE2 ] = "Composite2",
+                       [ 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_INPUT:
+       {
+               unsigned int *i = arg;
+
+               *i = core->input;
+               return 0;
+       }
+       case VIDIOC_S_INPUT:
+       {
+               unsigned int *i = arg;
+
+               if (*i >= 4)
+                       return -EINVAL;
+               mutex_lock(&core->lock);
+               cx88_newstation(core);
+               cx88_video_mux(core,*i);
+               mutex_unlock(&core->lock);
+               return 0;
+       }
+
+
+
+       /* --- controls ---------------------------------------------- */
+       case VIDIOC_QUERYCTRL:
+       {
+               struct v4l2_queryctrl *qctrl = arg;
+
+               qctrl->id = v4l2_ctrl_next(ctrl_classes, qctrl->id);
+                       if (unlikely(qctrl->id == 0))
+                               return -EINVAL;
+               return cx8800_ctrl_query(qctrl);
+       }
+       case VIDIOC_G_CTRL:
+               return cx88_get_control(core,arg);
+       case VIDIOC_S_CTRL:
+               return cx88_set_control(core,arg);
+
+       /* --- tuner ioctls ------------------------------------------ */
+       case VIDIOC_G_TUNER:
+       {
+               struct v4l2_tuner *t = arg;
+               u32 reg;
+
+               if (UNSET == core->tuner_type)
+                       return -EINVAL;
+               if (0 != t->index)
+                       return -EINVAL;
+
+               memset(t,0,sizeof(*t));
+               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;
+       }
+       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;
+       }
+       case VIDIOC_G_FREQUENCY:
+       {
+               struct v4l2_frequency *f = arg;
+
+               memset(f,0,sizeof(*f));
+
+               if (UNSET == core->tuner_type)
+                       return -EINVAL;
+
+               /* f->type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; */
+               f->type = radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
+               f->frequency = core->freq;
+
+               cx88_call_i2c_clients(core,VIDIOC_G_FREQUENCY,f);
+
+               return 0;
+       }
+       case VIDIOC_S_FREQUENCY:
+       {
+               struct v4l2_frequency *f = arg;
+
+               if (UNSET == core->tuner_type)
+                       return -EINVAL;
+               if (f->tuner != 0)
+                       return -EINVAL;
+               if (0 == radio && f->type != V4L2_TUNER_ANALOG_TV)
+                       return -EINVAL;
+               if (1 == radio && f->type != V4L2_TUNER_RADIO)
+                       return -EINVAL;
+               mutex_lock(&core->lock);
+               core->freq = f->frequency;
+               cx88_newstation(core);
+               cx88_call_i2c_clients(core,VIDIOC_S_FREQUENCY,f);
+
+               /* When changing channels it is required to reset TVAUDIO */
+               msleep (10);
+               cx88_set_tvaudio(core);
+
+               mutex_unlock(&core->lock);
+               return 0;
+       }
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+       /* ioctls to allow direct acces to the cx2388x registers */
+       case VIDIOC_INT_G_REGISTER:
+       {
+               struct v4l2_register *reg = arg;
+
+               if (reg->i2c_id != 0)
+                       return -EINVAL;
+               /* cx2388x has a 24-bit register space */
+               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:
+               return v4l_compat_translate_ioctl(inode,file,cmd,arg,
+                                                 driver_ioctl);
+       }
+       return 0;
+}
+
 int (*cx88_ioctl_hook)(struct inode *inode, struct file *file,
                        unsigned int cmd, void *arg);
 unsigned int (*cx88_ioctl_translator)(unsigned int cmd);
@@ -1164,7 +1468,7 @@ static int cx8802_blackbird_probe(struct cx8802_driver *drv)
        cx2341x_fill_defaults(&dev->params);
        dev->params.port = CX2341X_PORT_STREAMING;
 
-       if (core->tvnorm->id & V4L2_STD_525_60) {
+       if (core->tvnorm & V4L2_STD_525_60) {
                dev->height = 480;
        } else {
                dev->height = 576;