V4L/DVB (8917): saa7134-empress: fix changing the capture standard for non-tuner...
Hans Verkuil [Sat, 6 Sep 2008 09:34:44 +0000 (06:34 -0300)]
When changing the standard the saa6752hs was not updated unless the input
was the TV tuner. The saa6752hs should be updated regardless of the input.

In addition the S_STD and G_STD ioctls for the mpeg video device didn't do
anything. This is now fixed: they behave just like S_STD and G_STD on the
video0 device.

Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>

drivers/media/video/saa7134/saa7134-empress.c
drivers/media/video/saa7134/saa7134-i2c.c
drivers/media/video/saa7134/saa7134-video.c
drivers/media/video/saa7134/saa7134.h

index 946edf6..9a8766a 100644 (file)
@@ -303,15 +303,6 @@ static int empress_streamoff(struct file *file, void *priv,
        return videobuf_streamoff(&dev->empress_tsq);
 }
 
-static int saa7134_i2c_call_saa6752(struct saa7134_dev *dev,
-                                             unsigned int cmd, void *arg)
-{
-       if (dev->mpeg_i2c_client == NULL)
-               return -EINVAL;
-       return dev->mpeg_i2c_client->driver->command(dev->mpeg_i2c_client,
-                                                               cmd, arg);
-}
-
 static int empress_s_ext_ctrls(struct file *file, void *priv,
                               struct v4l2_ext_controls *ctrls)
 {
@@ -431,6 +422,20 @@ static int empress_g_chip_ident(struct file *file, void *fh,
        return -EINVAL;
 }
 
+static int empress_s_std(struct file *file, void *priv, v4l2_std_id *id)
+{
+       struct saa7134_dev *dev = file->private_data;
+
+       return saa7134_s_std_internal(dev, NULL, id);
+}
+
+static int empress_g_std(struct file *file, void *priv, v4l2_std_id *id)
+{
+       struct saa7134_dev *dev = file->private_data;
+
+       *id = dev->tvnorm->id;
+       return 0;
+}
 
 static const struct file_operations ts_fops =
 {
@@ -465,6 +470,8 @@ static const struct v4l2_ioctl_ops ts_ioctl_ops = {
        .vidioc_g_ctrl                  = empress_g_ctrl,
        .vidioc_s_ctrl                  = empress_s_ctrl,
        .vidioc_g_chip_ident            = empress_g_chip_ident,
+       .vidioc_s_std                   = empress_s_std,
+       .vidioc_g_std                   = empress_g_std,
 };
 
 /* ----------------------------------------------------------- */
index 5f713e6..b02965c 100644 (file)
@@ -427,6 +427,16 @@ void saa7134_i2c_call_clients(struct saa7134_dev *dev,
        i2c_clients_command(&dev->i2c_adap, cmd, arg);
 }
 
+int saa7134_i2c_call_saa6752(struct saa7134_dev *dev,
+                                             unsigned int cmd, void *arg)
+{
+       if (dev->mpeg_i2c_client == NULL)
+               return -EINVAL;
+       return dev->mpeg_i2c_client->driver->command(dev->mpeg_i2c_client,
+                                                               cmd, arg);
+}
+EXPORT_SYMBOL_GPL(saa7134_i2c_call_saa6752);
+
 int saa7134_i2c_register(struct saa7134_dev *dev)
 {
        dev->i2c_adap = saa7134_adap_template;
index 8fd3113..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)
@@ -1796,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)
@@ -1840,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);
@@ -1857,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)
@@ -2397,6 +2424,7 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = {
        .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,
index a1e0dad..5e7fc73 100644 (file)
@@ -662,6 +662,8 @@ int saa7134_i2c_register(struct saa7134_dev *dev);
 int saa7134_i2c_unregister(struct saa7134_dev *dev);
 void saa7134_i2c_call_clients(struct saa7134_dev *dev,
                              unsigned int cmd, void *arg);
+int saa7134_i2c_call_saa6752(struct saa7134_dev *dev,
+                             unsigned int cmd, void *arg);
 
 
 /* ----------------------------------------------------------- */
@@ -674,6 +676,7 @@ extern struct video_device saa7134_radio_template;
 int saa7134_s_ctrl_internal(struct saa7134_dev *dev,  struct saa7134_fh *fh, struct v4l2_control *c);
 int saa7134_g_ctrl_internal(struct saa7134_dev *dev,  struct saa7134_fh *fh, struct v4l2_control *c);
 int saa7134_queryctrl(struct file *file, void *priv, struct v4l2_queryctrl *c);
+int saa7134_s_std_internal(struct saa7134_dev *dev,  struct saa7134_fh *fh, v4l2_std_id *id);
 
 int saa7134_videoport_init(struct saa7134_dev *dev);
 void saa7134_set_tvnorm_hw(struct saa7134_dev *dev);