Merge branch 'topic/core-cleanup' into for-linus
[safe/jmp/linux-2.6] / drivers / media / video / pxa_camera.c
index a19bb76..04bf5c1 100644 (file)
 #include <linux/device.h>
 #include <linux/platform_device.h>
 #include <linux/clk.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
 
 #include <media/v4l2-common.h>
 #include <media/v4l2-dev.h>
 #include <media/videobuf-dma-sg.h>
 #include <media/soc_camera.h>
+#include <media/soc_mediabus.h>
 
 #include <linux/videodev2.h>
 
@@ -182,23 +185,21 @@ struct pxa_cam_dma {
 /* buffer for one video frame */
 struct pxa_buffer {
        /* common v4l buffer stuff -- must be first */
-       struct videobuf_buffer vb;
-
-       const struct soc_camera_data_format        *fmt;
-
+       struct videobuf_buffer          vb;
+       enum v4l2_mbus_pixelcode        code;
        /* our descriptor lists for Y, U and V channels */
-       struct pxa_cam_dma dmas[3];
-
-       int                     inwork;
-
-       enum pxa_camera_active_dma active_dma;
+       struct pxa_cam_dma              dmas[3];
+       int                             inwork;
+       enum pxa_camera_active_dma      active_dma;
 };
 
 struct pxa_camera_dev {
        struct soc_camera_host  soc_host;
-       /* PXA27x is only supposed to handle one camera on its Quick Capture
+       /*
+        * PXA27x is only supposed to handle one camera on its Quick Capture
         * interface. If anyone ever builds hardware to enable more than
-        * one camera, they will have to modify this driver too */
+        * one camera, they will have to modify this driver too
+        */
        struct soc_camera_device *icd;
        struct clk              *clk;
 
@@ -240,11 +241,15 @@ static int pxa_videobuf_setup(struct videobuf_queue *vq, unsigned int *count,
                              unsigned int *size)
 {
        struct soc_camera_device *icd = vq->priv_data;
+       int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width,
+                                               icd->current_fmt->host_fmt);
+
+       if (bytes_per_line < 0)
+               return bytes_per_line;
 
        dev_dbg(icd->dev.parent, "count=%d, size=%d\n", *count, *size);
 
-       *size = roundup(icd->user_width * icd->user_height *
-                       ((icd->current_fmt->depth + 7) >> 3), 8);
+       *size = bytes_per_line * icd->user_height;
 
        if (0 == *count)
                *count = 32;
@@ -266,15 +271,18 @@ static void free_buffer(struct videobuf_queue *vq, struct pxa_buffer *buf)
        dev_dbg(icd->dev.parent, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
                &buf->vb, buf->vb.baddr, buf->vb.bsize);
 
-       /* This waits until this buffer is out of danger, i.e., until it is no
-        * longer in STATE_QUEUED or STATE_ACTIVE */
+       /*
+        * This waits until this buffer is out of danger, i.e., until it is no
+        * longer in STATE_QUEUED or STATE_ACTIVE
+        */
        videobuf_waiton(&buf->vb, 0, 0);
        videobuf_dma_unmap(vq, dma);
        videobuf_dma_free(dma);
 
        for (i = 0; i < ARRAY_SIZE(buf->dmas); i++) {
                if (buf->dmas[i].sg_cpu)
-                       dma_free_coherent(ici->v4l2_dev.dev, buf->dmas[i].sg_size,
+                       dma_free_coherent(ici->v4l2_dev.dev,
+                                         buf->dmas[i].sg_size,
                                          buf->dmas[i].sg_cpu,
                                          buf->dmas[i].sg_dma);
                buf->dmas[i].sg_cpu = NULL;
@@ -427,6 +435,11 @@ static int pxa_videobuf_prepare(struct videobuf_queue *vq,
        struct pxa_buffer *buf = container_of(vb, struct pxa_buffer, vb);
        int ret;
        int size_y, size_u = 0, size_v = 0;
+       int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width,
+                                               icd->current_fmt->host_fmt);
+
+       if (bytes_per_line < 0)
+               return bytes_per_line;
 
        dev_dbg(dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
                vb, vb->baddr, vb->bsize);
@@ -435,29 +448,33 @@ static int pxa_videobuf_prepare(struct videobuf_queue *vq,
        WARN_ON(!list_empty(&vb->queue));
 
 #ifdef DEBUG
-       /* This can be useful if you want to see if we actually fill
-        * the buffer with something */
+       /*
+        * This can be useful if you want to see if we actually fill
+        * the buffer with something
+        */
        memset((void *)vb->baddr, 0xaa, vb->bsize);
 #endif
 
        BUG_ON(NULL == icd->current_fmt);
 
-       /* I think, in buf_prepare you only have to protect global data,
-        * the actual buffer is yours */
+       /*
+        * I think, in buf_prepare you only have to protect global data,
+        * the actual buffer is yours
+        */
        buf->inwork = 1;
 
-       if (buf->fmt    != icd->current_fmt ||
+       if (buf->code   != icd->current_fmt->code ||
            vb->width   != icd->user_width ||
            vb->height  != icd->user_height ||
            vb->field   != field) {
-               buf->fmt        = icd->current_fmt;
+               buf->code       = icd->current_fmt->code;
                vb->width       = icd->user_width;
                vb->height      = icd->user_height;
                vb->field       = field;
                vb->state       = VIDEOBUF_NEEDS_INIT;
        }
 
-       vb->size = vb->width * vb->height * ((buf->fmt->depth + 7) >> 3);
+       vb->size = bytes_per_line * vb->height;
        if (0 != vb->baddr && vb->bsize < vb->size) {
                ret = -EINVAL;
                goto out;
@@ -592,12 +609,9 @@ static void pxa_dma_add_tail_buf(struct pxa_camera_dev *pcdev,
  */
 static void pxa_camera_start_capture(struct pxa_camera_dev *pcdev)
 {
-       unsigned long cicr0, cifr;
+       unsigned long cicr0;
 
        dev_dbg(pcdev->soc_host.v4l2_dev.dev, "%s\n", __func__);
-       /* Reset the FIFOs */
-       cifr = __raw_readl(pcdev->base + CIFR) | CIFR_RESET_F;
-       __raw_writel(cifr, pcdev->base + CIFR);
        /* Enable End-Of-Frame Interrupt */
        cicr0 = __raw_readl(pcdev->base + CICR0) | CICR0_ENB;
        cicr0 &= ~CICR0_EOFM;
@@ -832,8 +846,10 @@ static void pxa_camera_init_videobuf(struct videobuf_queue *q,
        struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
        struct pxa_camera_dev *pcdev = ici->priv;
 
-       /* We must pass NULL as dev pointer, then all pci_* dma operations
-        * transform to normal dma_* ones. */
+       /*
+        * We must pass NULL as dev pointer, then all pci_* dma operations
+        * transform to normal dma_* ones.
+        */
        videobuf_queue_sg_init(q, &pxa_videobuf_ops, NULL, &pcdev->lock,
                                V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_NONE,
                                sizeof(struct pxa_buffer), icd);
@@ -880,18 +896,8 @@ static void recalculate_fifo_timeout(struct pxa_camera_dev *pcdev,
 
 static void pxa_camera_activate(struct pxa_camera_dev *pcdev)
 {
-       struct pxacamera_platform_data *pdata = pcdev->pdata;
-       struct device *dev = pcdev->soc_host.v4l2_dev.dev;
        u32 cicr4 = 0;
 
-       dev_dbg(dev, "Registered platform device at %p data %p\n",
-               pcdev, pdata);
-
-       if (pdata && pdata->init) {
-               dev_dbg(dev, "%s: Init gpios\n", __func__);
-               pdata->init(dev);
-       }
-
        /* disable all interrupts */
        __raw_writel(0x3ff, pcdev->base + CICR0);
 
@@ -926,7 +932,7 @@ static void pxa_camera_deactivate(struct pxa_camera_dev *pcdev)
 static irqreturn_t pxa_camera_irq(int irq, void *data)
 {
        struct pxa_camera_dev *pcdev = data;
-       unsigned long status, cicr0;
+       unsigned long status, cifr, cicr0;
        struct pxa_buffer *buf;
        struct videobuf_buffer *vb;
 
@@ -940,6 +946,10 @@ static irqreturn_t pxa_camera_irq(int irq, void *data)
        __raw_writel(status, pcdev->base + CISR);
 
        if (status & CISR_EOF) {
+               /* Reset the FIFOs */
+               cifr = __raw_readl(pcdev->base + CIFR) | CIFR_RESET_F;
+               __raw_writel(cifr, pcdev->base + CIFR);
+
                pcdev->active = list_first_entry(&pcdev->capture,
                                           struct pxa_buffer, vb.queue);
                vb = &pcdev->active->vb;
@@ -1049,11 +1059,18 @@ static void pxa_camera_setup_cicr(struct soc_camera_device *icd,
 {
        struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
        struct pxa_camera_dev *pcdev = ici->priv;
+       struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
        unsigned long dw, bpp;
-       u32 cicr0, cicr1, cicr2, cicr3, cicr4 = 0;
+       u32 cicr0, cicr1, cicr2, cicr3, cicr4 = 0, y_skip_top;
+       int ret = v4l2_subdev_call(sd, sensor, g_skip_top_lines, &y_skip_top);
 
-       /* Datawidth is now guaranteed to be equal to one of the three values.
-        * We fix bit-per-pixel equal to data-width... */
+       if (ret < 0)
+               y_skip_top = 0;
+
+       /*
+        * Datawidth is now guaranteed to be equal to one of the three values.
+        * We fix bit-per-pixel equal to data-width...
+        */
        switch (flags & SOCAM_DATAWIDTH_MASK) {
        case SOCAM_DATAWIDTH_10:
                dw = 4;
@@ -1064,8 +1081,10 @@ static void pxa_camera_setup_cicr(struct soc_camera_device *icd,
                bpp = 0x20;
                break;
        default:
-               /* Actually it can only be 8 now,
-                * default is just to silence compiler warnings */
+               /*
+                * Actually it can only be 8 now,
+                * default is just to silence compiler warnings
+                */
        case SOCAM_DATAWIDTH_8:
                dw = 2;
                bpp = 0;
@@ -1116,7 +1135,7 @@ static void pxa_camera_setup_cicr(struct soc_camera_device *icd,
 
        cicr2 = 0;
        cicr3 = CICR3_LPF_VAL(icd->user_height - 1) |
-               CICR3_BFW_VAL(min((unsigned short)255, icd->y_skip_top));
+               CICR3_BFW_VAL(min((u32)255, y_skip_top));
        cicr4 |= pcdev->mclk_divisor;
 
        __raw_writel(cicr1, pcdev->base + CICR1);
@@ -1136,9 +1155,15 @@ static int pxa_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt)
        struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
        struct pxa_camera_dev *pcdev = ici->priv;
        unsigned long bus_flags, camera_flags, common_flags;
-       int ret = test_platform_param(pcdev, icd->buswidth, &bus_flags);
+       const struct soc_mbus_pixelfmt *fmt;
+       int ret;
        struct pxa_cam *cam = icd->host_priv;
 
+       fmt = soc_mbus_get_fmtdesc(icd->current_fmt->code);
+       if (!fmt)
+               return -EINVAL;
+
+       ret = test_platform_param(pcdev, fmt->bits_per_sample, &bus_flags);
        if (ret < 0)
                return ret;
 
@@ -1202,59 +1227,49 @@ static int pxa_camera_try_bus_param(struct soc_camera_device *icd,
        return soc_camera_bus_param_compatible(camera_flags, bus_flags) ? 0 : -EINVAL;
 }
 
-static const struct soc_camera_data_format pxa_camera_formats[] = {
+static const struct soc_mbus_pixelfmt pxa_camera_formats[] = {
        {
-               .name           = "Planar YUV422 16 bit",
-               .depth          = 16,
-               .fourcc         = V4L2_PIX_FMT_YUV422P,
-               .colorspace     = V4L2_COLORSPACE_JPEG,
+               .fourcc                 = V4L2_PIX_FMT_YUV422P,
+               .name                   = "Planar YUV422 16 bit",
+               .bits_per_sample        = 8,
+               .packing                = SOC_MBUS_PACKING_2X8_PADHI,
+               .order                  = SOC_MBUS_ORDER_LE,
        },
 };
 
-static bool buswidth_supported(struct soc_camera_device *icd, int depth)
+/* This will be corrected as we get more formats */
+static bool pxa_camera_packing_supported(const struct soc_mbus_pixelfmt *fmt)
 {
-       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
-       struct pxa_camera_dev *pcdev = ici->priv;
-
-       switch (depth) {
-       case 8:
-               return !!(pcdev->platform_flags & PXA_CAMERA_DATAWIDTH_8);
-       case 9:
-               return !!(pcdev->platform_flags & PXA_CAMERA_DATAWIDTH_9);
-       case 10:
-               return !!(pcdev->platform_flags & PXA_CAMERA_DATAWIDTH_10);
-       }
-       return false;
-}
-
-static int required_buswidth(const struct soc_camera_data_format *fmt)
-{
-       switch (fmt->fourcc) {
-       case V4L2_PIX_FMT_UYVY:
-       case V4L2_PIX_FMT_VYUY:
-       case V4L2_PIX_FMT_YUYV:
-       case V4L2_PIX_FMT_YVYU:
-       case V4L2_PIX_FMT_RGB565:
-       case V4L2_PIX_FMT_RGB555:
-               return 8;
-       default:
-               return fmt->depth;
-       }
+       return  fmt->packing == SOC_MBUS_PACKING_NONE ||
+               (fmt->bits_per_sample == 8 &&
+                fmt->packing == SOC_MBUS_PACKING_2X8_PADHI) ||
+               (fmt->bits_per_sample > 8 &&
+                fmt->packing == SOC_MBUS_PACKING_EXTEND16);
 }
 
 static int pxa_camera_get_formats(struct soc_camera_device *icd, int idx,
                                  struct soc_camera_format_xlate *xlate)
 {
+       struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
        struct device *dev = icd->dev.parent;
-       int formats = 0, buswidth, ret;
+       int formats = 0, ret;
        struct pxa_cam *cam;
+       enum v4l2_mbus_pixelcode code;
+       const struct soc_mbus_pixelfmt *fmt;
 
-       buswidth = required_buswidth(icd->formats + idx);
+       ret = v4l2_subdev_call(sd, video, enum_mbus_fmt, idx, &code);
+       if (ret < 0)
+               /* No more formats */
+               return 0;
 
-       if (!buswidth_supported(icd, buswidth))
+       fmt = soc_mbus_get_fmtdesc(code);
+       if (!fmt) {
+               dev_err(dev, "Invalid format code #%d: %d\n", idx, code);
                return 0;
+       }
 
-       ret = pxa_camera_try_bus_param(icd, buswidth);
+       /* This also checks support for the requested bits-per-sample */
+       ret = pxa_camera_try_bus_param(icd, fmt->bits_per_sample);
        if (ret < 0)
                return 0;
 
@@ -1268,45 +1283,40 @@ static int pxa_camera_get_formats(struct soc_camera_device *icd, int idx,
                cam = icd->host_priv;
        }
 
-       switch (icd->formats[idx].fourcc) {
-       case V4L2_PIX_FMT_UYVY:
+       switch (code) {
+       case V4L2_MBUS_FMT_YUYV8_2X8_BE:
                formats++;
                if (xlate) {
-                       xlate->host_fmt = &pxa_camera_formats[0];
-                       xlate->cam_fmt = icd->formats + idx;
-                       xlate->buswidth = buswidth;
+                       xlate->host_fmt = &pxa_camera_formats[0];
+                       xlate->code     = code;
                        xlate++;
-                       dev_dbg(dev, "Providing format %s using %s\n",
-                               pxa_camera_formats[0].name,
-                               icd->formats[idx].name);
+                       dev_dbg(dev, "Providing format %s using code %d\n",
+                               pxa_camera_formats[0].name, code);
                }
-       case V4L2_PIX_FMT_VYUY:
-       case V4L2_PIX_FMT_YUYV:
-       case V4L2_PIX_FMT_YVYU:
-       case V4L2_PIX_FMT_RGB565:
-       case V4L2_PIX_FMT_RGB555:
-               formats++;
-               if (xlate) {
-                       xlate->host_fmt = icd->formats + idx;
-                       xlate->cam_fmt = icd->formats + idx;
-                       xlate->buswidth = buswidth;
-                       xlate++;
+       case V4L2_MBUS_FMT_YVYU8_2X8_BE:
+       case V4L2_MBUS_FMT_YUYV8_2X8_LE:
+       case V4L2_MBUS_FMT_YVYU8_2X8_LE:
+       case V4L2_MBUS_FMT_RGB565_2X8_LE:
+       case V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE:
+               if (xlate)
                        dev_dbg(dev, "Providing format %s packed\n",
-                               icd->formats[idx].name);
-               }
+                               fmt->name);
                break;
        default:
-               /* Generic pass-through */
-               formats++;
-               if (xlate) {
-                       xlate->host_fmt = icd->formats + idx;
-                       xlate->cam_fmt = icd->formats + idx;
-                       xlate->buswidth = icd->formats[idx].depth;
-                       xlate++;
+               if (!pxa_camera_packing_supported(fmt))
+                       return 0;
+               if (xlate)
                        dev_dbg(dev,
                                "Providing format %s in pass-through mode\n",
-                               icd->formats[idx].name);
-               }
+                               fmt->name);
+       }
+
+       /* Generic pass-through */
+       formats++;
+       if (xlate) {
+               xlate->host_fmt = fmt;
+               xlate->code     = code;
+               xlate++;
        }
 
        return formats;
@@ -1318,11 +1328,11 @@ static void pxa_camera_put_formats(struct soc_camera_device *icd)
        icd->host_priv = NULL;
 }
 
-static int pxa_camera_check_frame(struct v4l2_pix_format *pix)
+static int pxa_camera_check_frame(u32 width, u32 height)
 {
        /* limit to pxa hardware capabilities */
-       return pix->height < 32 || pix->height > 2048 || pix->width < 48 ||
-               pix->width > 2048 || (pix->width & 0x01);
+       return height < 32 || height > 2048 || width < 48 || width > 2048 ||
+               (width & 0x01);
 }
 
 static int pxa_camera_set_crop(struct soc_camera_device *icd,
@@ -1337,9 +1347,9 @@ static int pxa_camera_set_crop(struct soc_camera_device *icd,
                .master_clock = pcdev->mclk,
                .pixel_clock_max = pcdev->ciclk / 4,
        };
-       struct v4l2_format f;
-       struct v4l2_pix_format *pix = &f.fmt.pix, pix_tmp;
+       struct v4l2_mbus_framefmt mf;
        struct pxa_cam *cam = icd->host_priv;
+       u32 fourcc = icd->current_fmt->host_fmt->fourcc;
        int ret;
 
        /* If PCLK is used to latch data from the sensor, check sense */
@@ -1356,27 +1366,23 @@ static int pxa_camera_set_crop(struct soc_camera_device *icd,
                return ret;
        }
 
-       f.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-
-       ret = v4l2_subdev_call(sd, video, g_fmt, &f);
+       ret = v4l2_subdev_call(sd, video, g_mbus_fmt, &mf);
        if (ret < 0)
                return ret;
 
-       pix_tmp = *pix;
-       if (pxa_camera_check_frame(pix)) {
+       if (pxa_camera_check_frame(mf.width, mf.height)) {
                /*
                 * Camera cropping produced a frame beyond our capabilities.
                 * FIXME: just extract a subframe, that we can process.
                 */
-               v4l_bound_align_image(&pix->width, 48, 2048, 1,
-                       &pix->height, 32, 2048, 0,
-                       icd->current_fmt->fourcc == V4L2_PIX_FMT_YUV422P ?
-                               4 : 0);
-               ret = v4l2_subdev_call(sd, video, s_fmt, &f);
+               v4l_bound_align_image(&mf.width, 48, 2048, 1,
+                       &mf.height, 32, 2048, 0,
+                       fourcc == V4L2_PIX_FMT_YUV422P ? 4 : 0);
+               ret = v4l2_subdev_call(sd, video, s_mbus_fmt, &mf);
                if (ret < 0)
                        return ret;
 
-               if (pxa_camera_check_frame(pix)) {
+               if (pxa_camera_check_frame(mf.width, mf.height)) {
                        dev_warn(icd->dev.parent,
                                 "Inconsistent state. Use S_FMT to repair\n");
                        return -EINVAL;
@@ -1393,10 +1399,10 @@ static int pxa_camera_set_crop(struct soc_camera_device *icd,
                recalculate_fifo_timeout(pcdev, sense.pixel_clock);
        }
 
-       icd->user_width = pix->width;
-       icd->user_height = pix->height;
+       icd->user_width         = mf.width;
+       icd->user_height        = mf.height;
 
-       pxa_camera_setup_cicr(icd, cam->flags, icd->current_fmt->fourcc);
+       pxa_camera_setup_cicr(icd, cam->flags, fourcc);
 
        return ret;
 }
@@ -1408,14 +1414,13 @@ static int pxa_camera_set_fmt(struct soc_camera_device *icd,
        struct pxa_camera_dev *pcdev = ici->priv;
        struct device *dev = icd->dev.parent;
        struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
-       const struct soc_camera_data_format *cam_fmt = NULL;
        const struct soc_camera_format_xlate *xlate = NULL;
        struct soc_camera_sense sense = {
                .master_clock = pcdev->mclk,
                .pixel_clock_max = pcdev->ciclk / 4,
        };
        struct v4l2_pix_format *pix = &f->fmt.pix;
-       struct v4l2_format cam_f = *f;
+       struct v4l2_mbus_framefmt mf;
        int ret;
 
        xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat);
@@ -1424,24 +1429,31 @@ static int pxa_camera_set_fmt(struct soc_camera_device *icd,
                return -EINVAL;
        }
 
-       cam_fmt = xlate->cam_fmt;
-
        /* If PCLK is used to latch data from the sensor, check sense */
        if (pcdev->platform_flags & PXA_CAMERA_PCLK_EN)
+               /* The caller holds a mutex. */
                icd->sense = &sense;
 
-       cam_f.fmt.pix.pixelformat = cam_fmt->fourcc;
-       ret = v4l2_subdev_call(sd, video, s_fmt, f);
+       mf.width        = pix->width;
+       mf.height       = pix->height;
+       mf.field        = pix->field;
+       mf.colorspace   = pix->colorspace;
+       mf.code         = xlate->code;
+
+       ret = v4l2_subdev_call(sd, video, s_mbus_fmt, &mf);
+
+       if (mf.code != xlate->code)
+               return -EINVAL;
 
        icd->sense = NULL;
 
        if (ret < 0) {
                dev_warn(dev, "Failed to configure for format %x\n",
                         pix->pixelformat);
-       } else if (pxa_camera_check_frame(pix)) {
+       } else if (pxa_camera_check_frame(mf.width, mf.height)) {
                dev_warn(dev,
                         "Camera driver produced an unsupported frame %dx%d\n",
-                        pix->width, pix->height);
+                        mf.width, mf.height);
                ret = -EINVAL;
        } else if (sense.flags & SOCAM_SENSE_PCLK_CHANGED) {
                if (sense.pixel_clock > sense.pixel_clock_max) {
@@ -1453,10 +1465,14 @@ static int pxa_camera_set_fmt(struct soc_camera_device *icd,
                recalculate_fifo_timeout(pcdev, sense.pixel_clock);
        }
 
-       if (!ret) {
-               icd->buswidth = xlate->buswidth;
-               icd->current_fmt = xlate->host_fmt;
-       }
+       if (ret < 0)
+               return ret;
+
+       pix->width              = mf.width;
+       pix->height             = mf.height;
+       pix->field              = mf.field;
+       pix->colorspace         = mf.colorspace;
+       icd->current_fmt        = xlate;
 
        return ret;
 }
@@ -1464,17 +1480,16 @@ static int pxa_camera_set_fmt(struct soc_camera_device *icd,
 static int pxa_camera_try_fmt(struct soc_camera_device *icd,
                              struct v4l2_format *f)
 {
-       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
        struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
        const struct soc_camera_format_xlate *xlate;
        struct v4l2_pix_format *pix = &f->fmt.pix;
+       struct v4l2_mbus_framefmt mf;
        __u32 pixfmt = pix->pixelformat;
-       enum v4l2_field field;
        int ret;
 
        xlate = soc_camera_xlate_by_fourcc(icd, pixfmt);
        if (!xlate) {
-               dev_warn(ici->v4l2_dev.dev, "Format %x not found\n", pixfmt);
+               dev_warn(icd->dev.parent, "Format %x not found\n", pixfmt);
                return -EINVAL;
        }
 
@@ -1488,22 +1503,36 @@ static int pxa_camera_try_fmt(struct soc_camera_device *icd,
                              &pix->height, 32, 2048, 0,
                              pixfmt == V4L2_PIX_FMT_YUV422P ? 4 : 0);
 
-       pix->bytesperline = pix->width *
-               DIV_ROUND_UP(xlate->host_fmt->depth, 8);
+       pix->bytesperline = soc_mbus_bytes_per_line(pix->width,
+                                                   xlate->host_fmt);
+       if (pix->bytesperline < 0)
+               return pix->bytesperline;
        pix->sizeimage = pix->height * pix->bytesperline;
 
-       /* camera has to see its format, but the user the original one */
-       pix->pixelformat = xlate->cam_fmt->fourcc;
        /* limit to sensor capabilities */
-       ret = v4l2_subdev_call(sd, video, try_fmt, f);
-       pix->pixelformat = pixfmt;
+       mf.width        = pix->width;
+       mf.height       = pix->height;
+       mf.field        = pix->field;
+       mf.colorspace   = pix->colorspace;
+       mf.code         = xlate->code;
+
+       ret = v4l2_subdev_call(sd, video, try_mbus_fmt, &mf);
+       if (ret < 0)
+               return ret;
 
-       field = pix->field;
+       pix->width      = mf.width;
+       pix->height     = mf.height;
+       pix->colorspace = mf.colorspace;
 
-       if (field == V4L2_FIELD_ANY) {
-               pix->field = V4L2_FIELD_NONE;
-       } else if (field != V4L2_FIELD_NONE) {
-               dev_err(icd->dev.parent, "Field type %d unsupported.\n", field);
+       switch (mf.field) {
+       case V4L2_FIELD_ANY:
+       case V4L2_FIELD_NONE:
+               pix->field      = V4L2_FIELD_NONE;
+               break;
+       default:
+               /* TODO: support interlaced at least in pass-through mode */
+               dev_err(icd->dev.parent, "Field type %d unsupported.\n",
+                       mf.field);
                return -EINVAL;
        }
 
@@ -1515,10 +1544,12 @@ static int pxa_camera_reqbufs(struct soc_camera_file *icf,
 {
        int i;
 
-       /* This is for locking debugging only. I removed spinlocks and now I
+       /*
+        * This is for locking debugging only. I removed spinlocks and now I
         * check whether .prepare is ever called on a linked buffer, or whether
         * a dma IRQ can occur for an in-work or unlinked buffer. Until now
-        * it hadn't triggered */
+        * it hadn't triggered
+        */
        for (i = 0; i < p->count; i++) {
                struct pxa_buffer *buf = container_of(icf->vb_vidq.bufs[i],
                                                      struct pxa_buffer, vb);
@@ -1653,8 +1684,10 @@ static int __devinit pxa_camera_probe(struct platform_device *pdev)
        pcdev->platform_flags = pcdev->pdata->flags;
        if (!(pcdev->platform_flags & (PXA_CAMERA_DATAWIDTH_8 |
                        PXA_CAMERA_DATAWIDTH_9 | PXA_CAMERA_DATAWIDTH_10))) {
-               /* Platform hasn't set available data widths. This is bad.
-                * Warn and use a default. */
+               /*
+                * Platform hasn't set available data widths. This is bad.
+                * Warn and use a default.
+                */
                dev_warn(&pdev->dev, "WARNING! Platform hasn't set available "
                         "data widths, using default 10 bit\n");
                pcdev->platform_flags |= PXA_CAMERA_DATAWIDTH_10;