Merge git://git.kernel.org/pub/scm/linux/kernel/git/lethal/sh-2.6
[pandora-kernel.git] / drivers / media / video / cx231xx / cx231xx-video.c
index 585c031..b13b69f 100644 (file)
@@ -1009,22 +1009,6 @@ static int check_dev(struct cx231xx *dev)
        return 0;
 }
 
-static void get_scale(struct cx231xx *dev,
-                     unsigned int width, unsigned int height,
-                     unsigned int *hscale, unsigned int *vscale)
-{
-       unsigned int maxw = norm_maxw(dev);
-       unsigned int maxh = norm_maxh(dev);
-
-       *hscale = (((unsigned long)maxw) << 12) / width - 4096L;
-       if (*hscale >= 0x4000)
-               *hscale = 0x3fff;
-
-       *vscale = (((unsigned long)maxh) << 12) / height - 4096L;
-       if (*vscale >= 0x4000)
-               *vscale = 0x3fff;
-}
-
 /* ------------------------------------------------------------------
        IOCTL vidioc handling
    ------------------------------------------------------------------*/
@@ -1035,8 +1019,6 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
        struct cx231xx_fh *fh = priv;
        struct cx231xx *dev = fh->dev;
 
-       mutex_lock(&dev->lock);
-
        f->fmt.pix.width = dev->width;
        f->fmt.pix.height = dev->height;
        f->fmt.pix.pixelformat = dev->format->fourcc;
@@ -1046,8 +1028,6 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
 
        f->fmt.pix.field = V4L2_FIELD_INTERLACED;
 
-       mutex_unlock(&dev->lock);
-
        return 0;
 }
 
@@ -1071,7 +1051,6 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
        unsigned int height = f->fmt.pix.height;
        unsigned int maxw = norm_maxw(dev);
        unsigned int maxh = norm_maxh(dev);
-       unsigned int hscale, vscale;
        struct cx231xx_fmt *fmt;
 
        fmt = format_by_fourcc(f->fmt.pix.pixelformat);
@@ -1085,11 +1064,6 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
           height must be even because of interlacing */
        v4l_bound_align_image(&width, 48, maxw, 1, &height, 32, maxh, 1, 0);
 
-       get_scale(dev, width, height, &hscale, &vscale);
-
-       width = (((unsigned long)maxw) << 12) / (hscale + 4096L);
-       height = (((unsigned long)maxh) << 12) / (vscale + 4096L);
-
        f->fmt.pix.width = width;
        f->fmt.pix.height = height;
        f->fmt.pix.pixelformat = fmt->fourcc;
@@ -1114,43 +1088,31 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
        if (rc < 0)
                return rc;
 
-       mutex_lock(&dev->lock);
-
        vidioc_try_fmt_vid_cap(file, priv, f);
 
        fmt = format_by_fourcc(f->fmt.pix.pixelformat);
-       if (!fmt) {
-               rc = -EINVAL;
-               goto out;
-       }
+       if (!fmt)
+               return -EINVAL;
 
        if (videobuf_queue_is_busy(&fh->vb_vidq)) {
                cx231xx_errdev("%s queue busy\n", __func__);
-               rc = -EBUSY;
-               goto out;
+               return -EBUSY;
        }
 
        if (dev->stream_on && !fh->stream_on) {
                cx231xx_errdev("%s device in use by another fh\n", __func__);
-               rc = -EBUSY;
-               goto out;
+               return -EBUSY;
        }
 
        /* set new image size */
        dev->width = f->fmt.pix.width;
        dev->height = f->fmt.pix.height;
        dev->format = fmt;
-       get_scale(dev, dev->width, dev->height, &dev->hscale, &dev->vscale);
 
        v4l2_fill_mbus_format(&mbus_fmt, &f->fmt.pix, V4L2_MBUS_FMT_FIXED);
        call_all(dev, video, s_mbus_fmt, &mbus_fmt);
        v4l2_fill_pix_format(&f->fmt.pix, &mbus_fmt);
 
-       /* Set the correct alternate setting for this resolution */
-       cx231xx_resolution_set(dev);
-
-out:
-       mutex_unlock(&dev->lock);
        return rc;
 }
 
@@ -1167,6 +1129,7 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *norm)
 {
        struct cx231xx_fh *fh = priv;
        struct cx231xx *dev = fh->dev;
+       struct v4l2_mbus_framefmt mbus_fmt;
        struct v4l2_format f;
        int rc;
 
@@ -1176,7 +1139,6 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *norm)
 
        cx231xx_info("vidioc_s_std : 0x%x\n", (unsigned int)*norm);
 
-       mutex_lock(&dev->lock);
        dev->norm = *norm;
 
        /* Adjusts width/height, if needed */
@@ -1184,16 +1146,18 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *norm)
        f.fmt.pix.height = dev->height;
        vidioc_try_fmt_vid_cap(file, priv, &f);
 
-       /* set new image size */
-       dev->width = f.fmt.pix.width;
-       dev->height = f.fmt.pix.height;
-       get_scale(dev, dev->width, dev->height, &dev->hscale, &dev->vscale);
-
        call_all(dev, core, s_std, dev->norm);
 
-       mutex_unlock(&dev->lock);
+       /* We need to reset basic properties in the decoder related to
+          resolution (since a standard change effects things like the number
+          of lines in VACT, etc) */
+       v4l2_fill_mbus_format(&mbus_fmt, &f.fmt.pix, V4L2_MBUS_FMT_FIXED);
+       call_all(dev, video, s_mbus_fmt, &mbus_fmt);
+       v4l2_fill_pix_format(&f.fmt.pix, &mbus_fmt);
 
-       cx231xx_resolution_set(dev);
+       /* set new image size */
+       dev->width = f.fmt.pix.width;
+       dev->height = f.fmt.pix.height;
 
        /* do mode control overrides */
        cx231xx_do_mode_ctrl_overrides(dev);
@@ -1253,18 +1217,6 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
        struct cx231xx *dev = fh->dev;
        int rc;
 
-       if (i == 10) {
-               dev->USE_ISO = 0;
-               cx231xx_info("trans-mode=BULK. USE_ISO = %d\n", dev->USE_ISO);
-               return 0;
-       }
-
-       if (i == 11) {
-               dev->USE_ISO = 1;
-               cx231xx_info("trans-mode=ISOC. USE_ISO = %d\n", dev->USE_ISO);
-               return 0;
-       }
-
        dev->mode_tv = 0;
        rc = check_dev(dev);
        if (rc < 0)
@@ -1275,11 +1227,16 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
        if (0 == INPUT(i)->type)
                return -EINVAL;
 
-       mutex_lock(&dev->lock);
-
        video_mux(dev, i);
 
-       mutex_unlock(&dev->lock);
+       if (INPUT(i)->type == CX231XX_VMUX_TELEVISION ||
+           INPUT(i)->type == CX231XX_VMUX_CABLE) {
+               /* There's a tuner, so reset the standard and put it on the
+                  last known frequency (since it was probably powered down
+                  until now */
+               call_all(dev, core, s_std, dev->norm);
+       }
+
        return 0;
 }
 
@@ -1355,9 +1312,7 @@ static int vidioc_queryctrl(struct file *file, void *priv,
        }
        *qc = cx231xx_ctls[i].v;
 
-       mutex_lock(&dev->lock);
        call_all(dev, core, queryctrl, qc);
-       mutex_unlock(&dev->lock);
 
        if (qc->type)
                return 0;
@@ -1376,9 +1331,7 @@ static int vidioc_g_ctrl(struct file *file, void *priv,
        if (rc < 0)
                return rc;
 
-       mutex_lock(&dev->lock);
        call_all(dev, core, g_ctrl, ctrl);
-       mutex_unlock(&dev->lock);
        return rc;
 }
 
@@ -1393,9 +1346,7 @@ static int vidioc_s_ctrl(struct file *file, void *priv,
        if (rc < 0)
                return rc;
 
-       mutex_lock(&dev->lock);
        call_all(dev, core, s_ctrl, ctrl);
-       mutex_unlock(&dev->lock);
        return rc;
 }
 
@@ -1435,9 +1386,7 @@ static int vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
        if (0 != t->index)
                return -EINVAL;
 #if 0
-       mutex_lock(&dev->lock);
        call_all(dev, tuner, s_tuner, t);
-       mutex_unlock(&dev->lock);
 #endif
        return 0;
 }
@@ -1448,14 +1397,11 @@ static int vidioc_g_frequency(struct file *file, void *priv,
        struct cx231xx_fh *fh = priv;
        struct cx231xx *dev = fh->dev;
 
-       mutex_lock(&dev->lock);
        f->type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
        f->frequency = dev->ctl_freq;
 
        call_all(dev, tuner, g_frequency, f);
 
-       mutex_unlock(&dev->lock);
-
        return 0;
 }
 
@@ -1486,13 +1432,9 @@ static int vidioc_s_frequency(struct file *file, void *priv,
        /* set pre channel change settings in DIF first */
        rc = cx231xx_tuner_pre_channel_change(dev);
 
-       mutex_lock(&dev->lock);
-
        dev->ctl_freq = f->frequency;
        call_all(dev, tuner, s_frequency, f);
 
-       mutex_unlock(&dev->lock);
-
        /* set post channel change settings in DIF first */
        rc = cx231xx_tuner_post_channel_change(dev);
 
@@ -1680,9 +1622,7 @@ static int vidioc_g_register(struct file *file, void *priv,
                        return -EINVAL;
        }
 
-       mutex_lock(&dev->lock);
        call_all(dev, core, g_register, reg);
-       mutex_unlock(&dev->lock);
 
        return ret;
 }
@@ -1847,9 +1787,7 @@ static int vidioc_s_register(struct file *file, void *priv,
                break;
        }
 
-       mutex_lock(&dev->lock);
        call_all(dev, core, s_register, reg);
-       mutex_unlock(&dev->lock);
 
        return ret;
 }
@@ -1886,7 +1824,6 @@ static int vidioc_streamon(struct file *file, void *priv,
        if (rc < 0)
                return rc;
 
-       mutex_lock(&dev->lock);
        rc = res_get(fh);
 
        if (likely(rc >= 0))
@@ -1894,8 +1831,6 @@ static int vidioc_streamon(struct file *file, void *priv,
 
        call_all(dev, video, s_stream, 1);
 
-       mutex_unlock(&dev->lock);
-
        return rc;
 }
 
@@ -1916,15 +1851,11 @@ static int vidioc_streamoff(struct file *file, void *priv,
        if (type != fh->type)
                return -EINVAL;
 
-       mutex_lock(&dev->lock);
-
        cx25840_call(dev, video, s_stream, 0);
 
        videobuf_streamoff(&fh->vb_vidq);
        res_free(fh);
 
-       mutex_unlock(&dev->lock);
-
        return 0;
 }
 
@@ -1979,8 +1910,6 @@ static int vidioc_g_fmt_sliced_vbi_cap(struct file *file, void *priv,
        if (rc < 0)
                return rc;
 
-       mutex_lock(&dev->lock);
-
        f->fmt.sliced.service_set = 0;
 
        call_all(dev, vbi, g_sliced_fmt, &f->fmt.sliced);
@@ -1988,7 +1917,6 @@ static int vidioc_g_fmt_sliced_vbi_cap(struct file *file, void *priv,
        if (f->fmt.sliced.service_set == 0)
                rc = -EINVAL;
 
-       mutex_unlock(&dev->lock);
        return rc;
 }
 
@@ -2003,9 +1931,7 @@ static int vidioc_try_set_sliced_vbi_cap(struct file *file, void *priv,
        if (rc < 0)
                return rc;
 
-       mutex_lock(&dev->lock);
        call_all(dev, vbi, g_sliced_fmt, &f->fmt.sliced);
-       mutex_unlock(&dev->lock);
 
        if (f->fmt.sliced.service_set == 0)
                return -EINVAL;
@@ -2155,9 +2081,7 @@ static int radio_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
        strcpy(t->name, "Radio");
        t->type = V4L2_TUNER_RADIO;
 
-       mutex_lock(&dev->lock);
        call_all(dev, tuner, s_tuner, t);
-       mutex_unlock(&dev->lock);
 
        return 0;
 }
@@ -2188,9 +2112,7 @@ static int radio_s_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
        if (0 != t->index)
                return -EINVAL;
 
-       mutex_lock(&dev->lock);
        call_all(dev, tuner, s_tuner, t);
-       mutex_unlock(&dev->lock);
 
        return 0;
 }
@@ -2249,8 +2171,6 @@ static int cx231xx_v4l2_open(struct file *filp)
                break;
        }
 
-       mutex_lock(&dev->lock);
-
        cx231xx_videodbg("open dev=%s type=%s users=%d\n",
                         video_device_node_name(vdev), v4l2_type_names[fh_type],
                         dev->users);
@@ -2260,7 +2180,6 @@ static int cx231xx_v4l2_open(struct file *filp)
        if (errCode < 0) {
                cx231xx_errdev
                    ("Device locked on digital mode. Can't open analog\n");
-               mutex_unlock(&dev->lock);
                return -EBUSY;
        }
 #endif
@@ -2268,7 +2187,6 @@ static int cx231xx_v4l2_open(struct file *filp)
        fh = kzalloc(sizeof(struct cx231xx_fh), GFP_KERNEL);
        if (!fh) {
                cx231xx_errdev("cx231xx-video.c: Out of memory?!\n");
-               mutex_unlock(&dev->lock);
                return -ENOMEM;
        }
        fh->dev = dev;
@@ -2279,11 +2197,10 @@ static int cx231xx_v4l2_open(struct file *filp)
        if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && dev->users == 0) {
                dev->width = norm_maxw(dev);
                dev->height = norm_maxh(dev);
-               dev->hscale = 0;
-               dev->vscale = 0;
 
                /* Power up in Analog TV mode */
-               if (dev->model == CX231XX_BOARD_CNXT_VIDEO_GRABBER)
+               if (dev->model == CX231XX_BOARD_CNXT_VIDEO_GRABBER ||
+                   dev->model == CX231XX_BOARD_HAUPPAUGE_USBLIVE2)
                        cx231xx_set_power_mode(dev,
                                 POLARIS_AVMODE_ENXTERNAL_AV);
                else
@@ -2292,7 +2209,6 @@ static int cx231xx_v4l2_open(struct file *filp)
 #if 0
                cx231xx_set_mode(dev, CX231XX_ANALOG_MODE);
 #endif
-               cx231xx_resolution_set(dev);
 
                /* set video alternate setting */
                cx231xx_set_video_alternate(dev);
@@ -2320,22 +2236,21 @@ static int cx231xx_v4l2_open(struct file *filp)
                                            NULL, &dev->video_mode.slock,
                                            fh->type, V4L2_FIELD_INTERLACED,
                                            sizeof(struct cx231xx_buffer),
-                                           fh, NULL);
+                                           fh, &dev->lock);
        if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
                /* Set the required alternate setting  VBI interface works in
                   Bulk mode only */
-               if (dev->model != CX231XX_BOARD_CNXT_VIDEO_GRABBER)
+               if (dev->model != CX231XX_BOARD_CNXT_VIDEO_GRABBER &&
+                   dev->model != CX231XX_BOARD_HAUPPAUGE_USBLIVE2)
                        cx231xx_set_alt_setting(dev, INDEX_VANC, 0);
 
                videobuf_queue_vmalloc_init(&fh->vb_vidq, &cx231xx_vbi_qops,
                                            NULL, &dev->vbi_mode.slock,
                                            fh->type, V4L2_FIELD_SEQ_TB,
                                            sizeof(struct cx231xx_buffer),
-                                           fh, NULL);
+                                           fh, &dev->lock);
        }
 
-       mutex_unlock(&dev->lock);
-
        return errCode;
 }
 
@@ -2392,14 +2307,14 @@ static int cx231xx_v4l2_close(struct file *filp)
 
        cx231xx_videodbg("users=%d\n", dev->users);
 
-       mutex_lock(&dev->lock);
        cx231xx_videodbg("users=%d\n", dev->users);
        if (res_check(fh))
                res_free(fh);
 
        /*To workaround error number=-71 on EP0 for VideoGrabber,
                 need exclude following.*/
-       if (dev->model != CX231XX_BOARD_CNXT_VIDEO_GRABBER)
+       if (dev->model != CX231XX_BOARD_CNXT_VIDEO_GRABBER &&
+           dev->model != CX231XX_BOARD_HAUPPAUGE_USBLIVE2)
                if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
                        videobuf_stop(&fh->vb_vidq);
                        videobuf_mmap_free(&fh->vb_vidq);
@@ -2409,12 +2324,10 @@ static int cx231xx_v4l2_close(struct file *filp)
                        if (dev->state & DEV_DISCONNECTED) {
                                if (atomic_read(&dev->devlist_count) > 0) {
                                        cx231xx_release_resources(dev);
-                                       mutex_unlock(&dev->lock);
                                        kfree(dev);
                                        dev = NULL;
                                        return 0;
                                }
-                               mutex_unlock(&dev->lock);
                                return 0;
                        }
 
@@ -2430,7 +2343,6 @@ static int cx231xx_v4l2_close(struct file *filp)
                        kfree(fh);
                        dev->users--;
                        wake_up_interruptible_nr(&dev->open, 1);
-                       mutex_unlock(&dev->lock);
                        return 0;
                }
 
@@ -2442,7 +2354,6 @@ static int cx231xx_v4l2_close(struct file *filp)
                   free the remaining resources */
                if (dev->state & DEV_DISCONNECTED) {
                        cx231xx_release_resources(dev);
-                       mutex_unlock(&dev->lock);
                        kfree(dev);
                        dev = NULL;
                        return 0;
@@ -2464,7 +2375,6 @@ static int cx231xx_v4l2_close(struct file *filp)
        kfree(fh);
        dev->users--;
        wake_up_interruptible_nr(&dev->open, 1);
-       mutex_unlock(&dev->lock);
        return 0;
 }
 
@@ -2486,9 +2396,7 @@ cx231xx_v4l2_read(struct file *filp, char __user *buf, size_t count,
 
        if ((fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) ||
            (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE)) {
-               mutex_lock(&dev->lock);
                rc = res_get(fh);
-               mutex_unlock(&dev->lock);
 
                if (unlikely(rc < 0))
                        return rc;
@@ -2513,9 +2421,7 @@ static unsigned int cx231xx_v4l2_poll(struct file *filp, poll_table *wait)
        if (rc < 0)
                return rc;
 
-       mutex_lock(&dev->lock);
        rc = res_get(fh);
-       mutex_unlock(&dev->lock);
 
        if (unlikely(rc < 0))
                return POLLERR;
@@ -2540,9 +2446,7 @@ static int cx231xx_v4l2_mmap(struct file *filp, struct vm_area_struct *vma)
        if (rc < 0)
                return rc;
 
-       mutex_lock(&dev->lock);
        rc = res_get(fh);
-       mutex_unlock(&dev->lock);
 
        if (unlikely(rc < 0))
                return rc;
@@ -2564,7 +2468,7 @@ static const struct v4l2_file_operations cx231xx_v4l_fops = {
        .read    = cx231xx_v4l2_read,
        .poll    = cx231xx_v4l2_poll,
        .mmap    = cx231xx_v4l2_mmap,
-       .ioctl   = video_ioctl2,
+       .unlocked_ioctl   = video_ioctl2,
 };
 
 static const struct v4l2_ioctl_ops video_ioctl_ops = {
@@ -2666,6 +2570,7 @@ static struct video_device *cx231xx_vdev_init(struct cx231xx *dev,
        vfd->v4l2_dev = &dev->v4l2_dev;
        vfd->release = video_device_release;
        vfd->debug = video_debug;
+       vfd->lock = &dev->lock;
 
        snprintf(vfd->name, sizeof(vfd->name), "%s %s", dev->name, type_name);
 
@@ -2688,12 +2593,12 @@ int cx231xx_register_analog_devices(struct cx231xx *dev)
        dev->width = norm_maxw(dev);
        dev->height = norm_maxh(dev);
        dev->interlaced = 0;
-       dev->hscale = 0;
-       dev->vscale = 0;
 
        /* Analog specific initialization */
        dev->format = &format[0];
-       /* video_mux(dev, dev->video_input); */
+
+       /* Set the initial input */
+       video_mux(dev, dev->video_input);
 
        /* Audio defaults */
        dev->mute = 1;