V4L/DVB (8917): saa7134-empress: fix changing the capture standard for non-tuner...
[safe/jmp/linux-2.6] / drivers / media / video / saa7134 / saa7134-video.c
index a0baf2d..9aafd58 100644 (file)
@@ -628,6 +628,9 @@ void saa7134_set_tvnorm_hw(struct saa7134_dev *dev)
 
        if (card_in(dev, dev->ctl_input).tv)
                saa7134_i2c_call_clients(dev, VIDIOC_S_STD, &dev->tvnorm->id);
+       /* Set the correct norm for the saa6752hs. This function
+          does nothing if there is no saa6752hs. */
+       saa7134_i2c_call_saa6752(dev, VIDIOC_S_STD, &dev->tvnorm->id);
 }
 
 static void set_h_prescale(struct saa7134_dev *dev, int task, int prescale)
@@ -1112,10 +1115,8 @@ static struct videobuf_queue_ops video_qops = {
 
 /* ------------------------------------------------------------------ */
 
-int saa7134_g_ctrl(struct file *file, void *priv, struct v4l2_control *c)
+int saa7134_g_ctrl_internal(struct saa7134_dev *dev, struct saa7134_fh *fh, struct v4l2_control *c)
 {
-       struct saa7134_fh *fh = priv;
-       struct saa7134_dev *dev = fh->dev;
        const struct v4l2_queryctrl* ctrl;
 
        ctrl = ctrl_by_id(c->id);
@@ -1160,20 +1161,31 @@ int saa7134_g_ctrl(struct file *file, void *priv, struct v4l2_control *c)
        }
        return 0;
 }
-EXPORT_SYMBOL_GPL(saa7134_g_ctrl);
+EXPORT_SYMBOL_GPL(saa7134_g_ctrl_internal);
+
+static int saa7134_g_ctrl(struct file *file, void *priv, struct v4l2_control *c)
+{
+       struct saa7134_fh *fh = priv;
+
+       return saa7134_g_ctrl_internal(fh->dev, fh, c);
+}
 
-int saa7134_s_ctrl(struct file *file, void *f, struct v4l2_control *c)
+int saa7134_s_ctrl_internal(struct saa7134_dev *dev,  struct saa7134_fh *fh, struct v4l2_control *c)
 {
        const struct v4l2_queryctrl* ctrl;
-       struct saa7134_fh *fh = f;
-       struct saa7134_dev *dev = fh->dev;
        unsigned long flags;
        int restart_overlay = 0;
-       int err = -EINVAL;
+       int err;
 
-       err = v4l2_prio_check(&dev->prio, &fh->prio);
-       if (0 != err)
-               return err;
+       /* When called from the empress code fh == NULL.
+          That needs to be fixed somehow, but for now this is
+          good enough. */
+       if (fh) {
+               err = v4l2_prio_check(&dev->prio, &fh->prio);
+               if (0 != err)
+                       return err;
+       }
+       err = -EINVAL;
 
        mutex_lock(&dev->lock);
 
@@ -1274,7 +1286,14 @@ error:
        mutex_unlock(&dev->lock);
        return err;
 }
-EXPORT_SYMBOL_GPL(saa7134_s_ctrl);
+EXPORT_SYMBOL_GPL(saa7134_s_ctrl_internal);
+
+static int saa7134_s_ctrl(struct file *file, void *f, struct v4l2_control *c)
+{
+       struct saa7134_fh *fh = f;
+
+       return saa7134_s_ctrl_internal(fh->dev, fh, c);
+}
 
 /* ------------------------------------------------------------------ */
 
@@ -1314,6 +1333,8 @@ static int video_open(struct inode *inode, struct file *file)
        struct saa7134_fh *fh;
        enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        int radio = 0;
+
+       lock_kernel();
        list_for_each_entry(dev, &saa7134_devlist, devlist) {
                if (dev->video_dev && (dev->video_dev->minor == minor))
                        goto found;
@@ -1326,6 +1347,7 @@ static int video_open(struct inode *inode, struct file *file)
                        goto found;
                }
        }
+       unlock_kernel();
        return -ENODEV;
  found:
 
@@ -1334,8 +1356,10 @@ static int video_open(struct inode *inode, struct file *file)
 
        /* allocate + initialize per filehandle data */
        fh = kzalloc(sizeof(*fh),GFP_KERNEL);
-       if (NULL == fh)
+       if (NULL == fh) {
+               unlock_kernel();
                return -ENOMEM;
+       }
        file->private_data = fh;
        fh->dev      = dev;
        fh->radio    = radio;
@@ -1368,6 +1392,7 @@ static int video_open(struct inode *inode, struct file *file)
                /* switch to video/vbi mode */
                video_mux(dev,dev->ctl_input);
        }
+       unlock_kernel();
        return 0;
 }
 
@@ -1496,7 +1521,7 @@ static int video_mmap(struct file *file, struct vm_area_struct * vma)
 
 /* ------------------------------------------------------------------ */
 
-static int saa7134_try_get_set_fmt_vbi(struct file *file, void *priv,
+static int saa7134_try_get_set_fmt_vbi_cap(struct file *file, void *priv,
                                                struct v4l2_format *f)
 {
        struct saa7134_fh *fh = priv;
@@ -1516,7 +1541,7 @@ static int saa7134_try_get_set_fmt_vbi(struct file *file, void *priv,
        return 0;
 }
 
-static int saa7134_g_fmt_cap(struct file *file, void *priv,
+static int saa7134_g_fmt_vid_cap(struct file *file, void *priv,
                                struct v4l2_format *f)
 {
        struct saa7134_fh *fh = priv;
@@ -1532,7 +1557,7 @@ static int saa7134_g_fmt_cap(struct file *file, void *priv,
        return 0;
 }
 
-static int saa7134_g_fmt_overlay(struct file *file, void *priv,
+static int saa7134_g_fmt_vid_overlay(struct file *file, void *priv,
                                struct v4l2_format *f)
 {
        struct saa7134_fh *fh = priv;
@@ -1546,7 +1571,7 @@ static int saa7134_g_fmt_overlay(struct file *file, void *priv,
        return 0;
 }
 
-static int saa7134_try_fmt_cap(struct file *file, void *priv,
+static int saa7134_try_fmt_vid_cap(struct file *file, void *priv,
                                                struct v4l2_format *f)
 {
        struct saa7134_fh *fh = priv;
@@ -1597,7 +1622,7 @@ static int saa7134_try_fmt_cap(struct file *file, void *priv,
        return 0;
 }
 
-static int saa7134_try_fmt_overlay(struct file *file, void *priv,
+static int saa7134_try_fmt_vid_overlay(struct file *file, void *priv,
                                                struct v4l2_format *f)
 {
        struct saa7134_fh *fh = priv;
@@ -1611,13 +1636,13 @@ static int saa7134_try_fmt_overlay(struct file *file, void *priv,
        return verify_preview(dev, &f->fmt.win);
 }
 
-static int saa7134_s_fmt_cap(struct file *file, void *priv,
+static int saa7134_s_fmt_vid_cap(struct file *file, void *priv,
                                        struct v4l2_format *f)
 {
        struct saa7134_fh *fh = priv;
        int err;
 
-       err = saa7134_try_fmt_cap(file, priv, f);
+       err = saa7134_try_fmt_vid_cap(file, priv, f);
        if (0 != err)
                return err;
 
@@ -1628,13 +1653,13 @@ static int saa7134_s_fmt_cap(struct file *file, void *priv,
        return 0;
 }
 
-static int saa7134_s_fmt_overlay(struct file *file, void *priv,
+static int saa7134_s_fmt_vid_overlay(struct file *file, void *priv,
                                        struct v4l2_format *f)
 {
        struct saa7134_fh *fh = priv;
        struct saa7134_dev *dev = fh->dev;
        int err;
-       unsigned int flags;
+       unsigned long flags;
 
        if (saa7134_no_overlay > 0) {
                printk(KERN_ERR "V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n");
@@ -1774,18 +1799,25 @@ static int saa7134_querycap(struct file *file, void  *priv,
                return 0;
 }
 
-static int saa7134_s_std(struct file *file, void *priv, v4l2_std_id *id)
+int saa7134_s_std_internal(struct saa7134_dev *dev, struct saa7134_fh *fh, v4l2_std_id *id)
 {
-       struct saa7134_fh *fh = priv;
-       struct saa7134_dev *dev = fh->dev;
        unsigned long flags;
        unsigned int i;
        v4l2_std_id fixup;
        int err;
 
-       err = v4l2_prio_check(&dev->prio, &fh->prio);
-       if (0 != err)
-               return err;
+       /* When called from the empress code fh == NULL.
+          That needs to be fixed somehow, but for now this is
+          good enough. */
+       if (fh) {
+               err = v4l2_prio_check(&dev->prio, &fh->prio);
+               if (0 != err)
+                       return err;
+       } else if (res_locked(dev, RESOURCE_OVERLAY)) {
+               /* Don't change the std from the mpeg device
+                  if overlay is active. */
+               return -EBUSY;
+       }
 
        for (i = 0; i < TVNORMS; i++)
                if (*id == tvnorms[i].id)
@@ -1818,7 +1850,7 @@ static int saa7134_s_std(struct file *file, void *priv, v4l2_std_id *id)
        *id = tvnorms[i].id;
 
        mutex_lock(&dev->lock);
-       if (res_check(fh, RESOURCE_OVERLAY)) {
+       if (fh && res_check(fh, RESOURCE_OVERLAY)) {
                spin_lock_irqsave(&dev->slock, flags);
                stop_preview(dev, fh);
                spin_unlock_irqrestore(&dev->slock, flags);
@@ -1835,6 +1867,23 @@ static int saa7134_s_std(struct file *file, void *priv, v4l2_std_id *id)
        mutex_unlock(&dev->lock);
        return 0;
 }
+EXPORT_SYMBOL_GPL(saa7134_s_std_internal);
+
+static int saa7134_s_std(struct file *file, void *priv, v4l2_std_id *id)
+{
+       struct saa7134_fh *fh = priv;
+
+       return saa7134_s_std_internal(fh->dev, fh, id);
+}
+
+static int saa7134_g_std(struct file *file, void *priv, v4l2_std_id *id)
+{
+       struct saa7134_fh *fh = priv;
+       struct saa7134_dev *dev = fh->dev;
+
+       *id = dev->tvnorm->id;
+       return 0;
+}
 
 static int saa7134_cropcap(struct file *file, void *priv,
                                        struct v4l2_cropcap *cap)
@@ -2028,7 +2077,7 @@ static int saa7134_s_priority(struct file *file, void *f,
        return v4l2_prio_change(&dev->prio, &fh->prio, prio);
 }
 
-static int saa7134_enum_fmt_cap(struct file *file, void  *priv,
+static int saa7134_enum_fmt_vid_cap(struct file *file, void  *priv,
                                        struct v4l2_fmtdesc *f)
 {
        if (f->index >= FORMATS)
@@ -2042,7 +2091,7 @@ static int saa7134_enum_fmt_cap(struct file *file, void  *priv,
        return 0;
 }
 
-static int saa7134_enum_fmt_overlay(struct file *file, void  *priv,
+static int saa7134_enum_fmt_vid_overlay(struct file *file, void  *priv,
                                        struct v4l2_fmtdesc *f)
 {
        if (saa7134_no_overlay > 0) {
@@ -2061,7 +2110,7 @@ static int saa7134_enum_fmt_overlay(struct file *file, void  *priv,
        return 0;
 }
 
-static int saa7134_enum_fmt_vbi(struct file *file, void  *priv,
+static int saa7134_enum_fmt_vbi_cap(struct file *file, void  *priv,
                                        struct v4l2_fmtdesc *f)
 {
        if (0 != f->index)
@@ -2208,6 +2257,32 @@ static int saa7134_g_parm(struct file *file, void *fh,
        return 0;
 }
 
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static int vidioc_g_register (struct file *file, void *priv,
+                             struct v4l2_register *reg)
+{
+       struct saa7134_fh *fh = priv;
+       struct saa7134_dev *dev = fh->dev;
+
+       if (!v4l2_chip_match_host(reg->match_type, reg->match_chip))
+               return -EINVAL;
+       reg->val = saa_readb(reg->reg);
+       return 0;
+}
+
+static int vidioc_s_register (struct file *file, void *priv,
+                               struct v4l2_register *reg)
+{
+       struct saa7134_fh *fh = priv;
+       struct saa7134_dev *dev = fh->dev;
+
+       if (!v4l2_chip_match_host(reg->match_type, reg->match_chip))
+               return -EINVAL;
+       saa_writeb(reg->reg&0xffffff, reg->val);
+       return 0;
+}
+#endif
+
 static int radio_querycap(struct file *file, void *priv,
                                        struct v4l2_capability *cap)
 {
@@ -2327,39 +2402,20 @@ static const struct file_operations video_fops =
        .llseek   = no_llseek,
 };
 
-static const struct file_operations radio_fops =
-{
-       .owner    = THIS_MODULE,
-       .open     = video_open,
-       .release  = video_release,
-       .ioctl    = video_ioctl2,
-       .compat_ioctl   = v4l_compat_ioctl32,
-       .llseek   = no_llseek,
-};
-
-/* ----------------------------------------------------------- */
-/* exported stuff                                              */
-
-struct video_device saa7134_video_template =
-{
-       .name                           = "saa7134-video",
-       .type                           = VID_TYPE_CAPTURE|VID_TYPE_TUNER |
-                                       VID_TYPE_CLIPPING|VID_TYPE_SCALES,
-       .fops                           = &video_fops,
-       .minor                          = -1,
+static const struct v4l2_ioctl_ops video_ioctl_ops = {
        .vidioc_querycap                = saa7134_querycap,
-       .vidioc_enum_fmt_cap            = saa7134_enum_fmt_cap,
-       .vidioc_g_fmt_cap               = saa7134_g_fmt_cap,
-       .vidioc_try_fmt_cap             = saa7134_try_fmt_cap,
-       .vidioc_s_fmt_cap               = saa7134_s_fmt_cap,
-       .vidioc_enum_fmt_overlay        = saa7134_enum_fmt_overlay,
-       .vidioc_g_fmt_overlay           = saa7134_g_fmt_overlay,
-       .vidioc_try_fmt_overlay         = saa7134_try_fmt_overlay,
-       .vidioc_s_fmt_overlay           = saa7134_s_fmt_overlay,
-       .vidioc_enum_fmt_vbi            = saa7134_enum_fmt_vbi,
-       .vidioc_g_fmt_vbi               = saa7134_try_get_set_fmt_vbi,
-       .vidioc_try_fmt_vbi             = saa7134_try_get_set_fmt_vbi,
-       .vidioc_s_fmt_vbi               = saa7134_try_get_set_fmt_vbi,
+       .vidioc_enum_fmt_vid_cap        = saa7134_enum_fmt_vid_cap,
+       .vidioc_g_fmt_vid_cap           = saa7134_g_fmt_vid_cap,
+       .vidioc_try_fmt_vid_cap         = saa7134_try_fmt_vid_cap,
+       .vidioc_s_fmt_vid_cap           = saa7134_s_fmt_vid_cap,
+       .vidioc_enum_fmt_vid_overlay    = saa7134_enum_fmt_vid_overlay,
+       .vidioc_g_fmt_vid_overlay       = saa7134_g_fmt_vid_overlay,
+       .vidioc_try_fmt_vid_overlay     = saa7134_try_fmt_vid_overlay,
+       .vidioc_s_fmt_vid_overlay       = saa7134_s_fmt_vid_overlay,
+       .vidioc_enum_fmt_vbi_cap        = saa7134_enum_fmt_vbi_cap,
+       .vidioc_g_fmt_vbi_cap           = saa7134_try_get_set_fmt_vbi_cap,
+       .vidioc_try_fmt_vbi_cap         = saa7134_try_get_set_fmt_vbi_cap,
+       .vidioc_s_fmt_vbi_cap           = saa7134_try_get_set_fmt_vbi_cap,
        .vidioc_g_audio                 = saa7134_g_audio,
        .vidioc_s_audio                 = saa7134_s_audio,
        .vidioc_cropcap                 = saa7134_cropcap,
@@ -2368,6 +2424,7 @@ struct video_device saa7134_video_template =
        .vidioc_qbuf                    = saa7134_qbuf,
        .vidioc_dqbuf                   = saa7134_dqbuf,
        .vidioc_s_std                   = saa7134_s_std,
+       .vidioc_g_std                   = saa7134_g_std,
        .vidioc_enum_input              = saa7134_enum_input,
        .vidioc_g_input                 = saa7134_g_input,
        .vidioc_s_input                 = saa7134_s_input,
@@ -2391,16 +2448,22 @@ struct video_device saa7134_video_template =
        .vidioc_g_parm                  = saa7134_g_parm,
        .vidioc_g_frequency             = saa7134_g_frequency,
        .vidioc_s_frequency             = saa7134_s_frequency,
-       .tvnorms                        = SAA7134_NORMS,
-       .current_norm                   = V4L2_STD_PAL,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+       .vidioc_g_register              = vidioc_g_register,
+       .vidioc_s_register              = vidioc_s_register,
+#endif
 };
 
-struct video_device saa7134_radio_template =
-{
-       .name                   = "saa7134-radio",
-       .type                   = VID_TYPE_TUNER,
-       .fops                   = &radio_fops,
-       .minor                  = -1,
+static const struct file_operations radio_fops = {
+       .owner    = THIS_MODULE,
+       .open     = video_open,
+       .release  = video_release,
+       .ioctl    = video_ioctl2,
+       .compat_ioctl   = v4l_compat_ioctl32,
+       .llseek   = no_llseek,
+};
+
+static const struct v4l2_ioctl_ops radio_ioctl_ops = {
        .vidioc_querycap        = radio_querycap,
        .vidioc_g_tuner         = radio_g_tuner,
        .vidioc_enum_input      = radio_enum_input,
@@ -2417,6 +2480,25 @@ struct video_device saa7134_radio_template =
        .vidioc_s_frequency     = saa7134_s_frequency,
 };
 
+/* ----------------------------------------------------------- */
+/* exported stuff                                              */
+
+struct video_device saa7134_video_template = {
+       .name                           = "saa7134-video",
+       .fops                           = &video_fops,
+       .ioctl_ops                      = &video_ioctl_ops,
+       .minor                          = -1,
+       .tvnorms                        = SAA7134_NORMS,
+       .current_norm                   = V4L2_STD_PAL,
+};
+
+struct video_device saa7134_radio_template = {
+       .name                   = "saa7134-radio",
+       .fops                   = &radio_fops,
+       .ioctl_ops              = &radio_ioctl_ops,
+       .minor                  = -1,
+};
+
 int saa7134_video_init1(struct saa7134_dev *dev)
 {
        /* sanitycheck insmod options */
@@ -2458,13 +2540,14 @@ int saa7134_videoport_init(struct saa7134_dev *dev)
        int vo = saa7134_boards[dev->board].video_out;
        int video_reg;
        unsigned int vid_port_opts = saa7134_boards[dev->board].vid_port_opts;
+
+       /* Configure videoport */
        saa_writeb(SAA7134_VIDEO_PORT_CTRL0, video_out[vo][0]);
        video_reg = video_out[vo][1];
        if (vid_port_opts & SET_T_CODE_POLARITY_NON_INVERTED)
                video_reg &= ~VP_T_CODE_P_INVERTED;
        saa_writeb(SAA7134_VIDEO_PORT_CTRL1, video_reg);
        saa_writeb(SAA7134_VIDEO_PORT_CTRL2, video_out[vo][2]);
-       saa_writeb(SAA7134_VIDEO_PORT_CTRL3, video_out[vo][3]);
        saa_writeb(SAA7134_VIDEO_PORT_CTRL4, video_out[vo][4]);
        video_reg = video_out[vo][5];
        if (vid_port_opts & SET_CLOCK_NOT_DELAYED)
@@ -2481,6 +2564,9 @@ int saa7134_videoport_init(struct saa7134_dev *dev)
        saa_writeb(SAA7134_VIDEO_PORT_CTRL7, video_out[vo][7]);
        saa_writeb(SAA7134_VIDEO_PORT_CTRL8, video_out[vo][8]);
 
+       /* Start videoport */
+       saa_writeb(SAA7134_VIDEO_PORT_CTRL3, video_out[vo][3]);
+
        return 0;
 }