V4L/DVB (11029): video: use videobuf_waiton() in sh_mobile_ceu free_buffer()
[safe/jmp/linux-2.6] / drivers / media / video / sh_mobile_ceu_camera.c
index ed3bfc4..b5e37a5 100644 (file)
@@ -94,7 +94,7 @@ struct sh_mobile_ceu_dev {
        spinlock_t lock;
        struct list_head capture;
        struct videobuf_buffer *active;
-       int is_interlace;
+       int is_interlaced;
 
        struct sh_mobile_ceu_info *pdata;
 
@@ -174,6 +174,7 @@ static void free_buffer(struct videobuf_queue *vq,
        if (in_interrupt())
                BUG();
 
+       videobuf_waiton(&buf->vb, 0, 0);
        videobuf_dma_contig_free(vq, &buf->vb);
        dev_dbg(&icd->dev, "%s freed\n", __func__);
        buf->vb.state = VIDEOBUF_NEEDS_INIT;
@@ -205,7 +206,7 @@ static void sh_mobile_ceu_capture(struct sh_mobile_ceu_dev *pcdev)
 
        phys_addr_top = videobuf_to_dma_contig(pcdev->active);
        ceu_write(pcdev, CDAYR, phys_addr_top);
-       if (pcdev->is_interlace) {
+       if (pcdev->is_interlaced) {
                phys_addr_bottom = phys_addr_top + icd->width;
                ceu_write(pcdev, CDBYR, phys_addr_bottom);
        }
@@ -217,7 +218,7 @@ static void sh_mobile_ceu_capture(struct sh_mobile_ceu_dev *pcdev)
        case V4L2_PIX_FMT_NV61:
                phys_addr_top += icd->width * icd->height;
                ceu_write(pcdev, CDACR, phys_addr_top);
-               if (pcdev->is_interlace) {
+               if (pcdev->is_interlaced) {
                        phys_addr_bottom = phys_addr_top + icd->width;
                        ceu_write(pcdev, CDBCR, phys_addr_bottom);
                }
@@ -481,7 +482,7 @@ static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd,
        ceu_write(pcdev, CAMCR, value);
 
        ceu_write(pcdev, CAPCR, 0x00300000);
-       ceu_write(pcdev, CAIFR, (pcdev->is_interlace) ? 0x101 : 0);
+       ceu_write(pcdev, CAIFR, pcdev->is_interlaced ? 0x101 : 0);
 
        mdelay(1);
 
@@ -497,7 +498,7 @@ static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd,
        }
 
        height = icd->height;
-       if (pcdev->is_interlace) {
+       if (pcdev->is_interlaced) {
                height /= 2;
                cdwdr_width *= 2;
        }
@@ -638,24 +639,30 @@ add_single_format:
        return formats;
 }
 
+static int sh_mobile_ceu_set_crop(struct soc_camera_device *icd,
+                                 struct v4l2_rect *rect)
+{
+       return icd->ops->set_crop(icd, rect);
+}
+
 static int sh_mobile_ceu_set_fmt(struct soc_camera_device *icd,
-                                __u32 pixfmt, struct v4l2_rect *rect)
+                                struct v4l2_format *f)
 {
        struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
        struct sh_mobile_ceu_dev *pcdev = ici->priv;
+       __u32 pixfmt = f->fmt.pix.pixelformat;
        const struct soc_camera_format_xlate *xlate;
+       struct v4l2_format cam_f = *f;
        int ret;
 
-       if (!pixfmt)
-               return icd->ops->set_fmt(icd, pixfmt, rect);
-
        xlate = soc_camera_xlate_by_fourcc(icd, pixfmt);
        if (!xlate) {
                dev_warn(&ici->dev, "Format %x not found\n", pixfmt);
                return -EINVAL;
        }
 
-       ret = icd->ops->set_fmt(icd, xlate->cam_fmt->fourcc, rect);
+       cam_f.fmt.pix.pixelformat = xlate->cam_fmt->fourcc;
+       ret = icd->ops->set_fmt(icd, &cam_f);
 
        if (!ret) {
                icd->buswidth = xlate->buswidth;
@@ -705,13 +712,13 @@ static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd,
 
        switch (f->fmt.pix.field) {
        case V4L2_FIELD_INTERLACED:
-               pcdev->is_interlace = 1;
+               pcdev->is_interlaced = 1;
                break;
        case V4L2_FIELD_ANY:
                f->fmt.pix.field = V4L2_FIELD_NONE;
                /* fall-through */
        case V4L2_FIELD_NONE:
-               pcdev->is_interlace = 0;
+               pcdev->is_interlaced = 0;
                break;
        default:
                ret = -EINVAL;
@@ -777,7 +784,8 @@ static void sh_mobile_ceu_init_videobuf(struct videobuf_queue *q,
                                       &sh_mobile_ceu_videobuf_ops,
                                       &ici->dev, &pcdev->lock,
                                       V4L2_BUF_TYPE_VIDEO_CAPTURE,
-                                      V4L2_FIELD_ANY,
+                                      pcdev->is_interlaced ?
+                                      V4L2_FIELD_INTERLACED : V4L2_FIELD_NONE,
                                       sizeof(struct sh_mobile_ceu_buffer),
                                       icd);
 }
@@ -787,6 +795,7 @@ static struct soc_camera_host_ops sh_mobile_ceu_host_ops = {
        .add            = sh_mobile_ceu_add_device,
        .remove         = sh_mobile_ceu_remove_device,
        .get_formats    = sh_mobile_ceu_get_formats,
+       .set_crop       = sh_mobile_ceu_set_crop,
        .set_fmt        = sh_mobile_ceu_set_fmt,
        .try_fmt        = sh_mobile_ceu_try_fmt,
        .reqbufs        = sh_mobile_ceu_reqbufs,