Merge branch 'mxs/for-arnd' of git://git.linaro.org/people/shawnguo/linux-2.6 into...
[pandora-kernel.git] / drivers / media / video / omap1_camera.c
index e7cfc85..e87ae2f 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/interrupt.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
-#include <linux/version.h>
 
 #include <media/omap1_camera.h>
 #include <media/soc_camera.h>
@@ -38,7 +37,7 @@
 
 
 #define DRIVER_NAME            "omap1-camera"
-#define VERSION_CODE           KERNEL_VERSION(0, 0, 1)
+#define DRIVER_VERSION         "0.0.2"
 
 
 /*
 /* end of OMAP1 Camera Interface registers */
 
 
-#define SOCAM_BUS_FLAGS        (SOCAM_MASTER | \
-                       SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_HIGH | \
-                       SOCAM_PCLK_SAMPLE_RISING | SOCAM_PCLK_SAMPLE_FALLING | \
-                       SOCAM_DATA_ACTIVE_HIGH | SOCAM_DATAWIDTH_8)
+#define SOCAM_BUS_FLAGS        (V4L2_MBUS_MASTER | \
+                       V4L2_MBUS_HSYNC_ACTIVE_HIGH | V4L2_MBUS_VSYNC_ACTIVE_HIGH | \
+                       V4L2_MBUS_PCLK_SAMPLE_RISING | V4L2_MBUS_PCLK_SAMPLE_FALLING | \
+                       V4L2_MBUS_DATA_ACTIVE_HIGH)
 
 
 #define FIFO_SIZE              ((THRESHOLD_MASK >> THRESHOLD_SHIFT) + 1)
@@ -208,7 +207,7 @@ static int omap1_videobuf_setup(struct videobuf_queue *vq, unsigned int *count,
        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);
-       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
        struct omap1_cam_dev *pcdev = ici->priv;
 
        if (bytes_per_line < 0)
@@ -222,7 +221,7 @@ static int omap1_videobuf_setup(struct videobuf_queue *vq, unsigned int *count,
        if (*size * *count > MAX_VIDEO_MEM * 1024 * 1024)
                *count = (MAX_VIDEO_MEM * 1024 * 1024) / *size;
 
-       dev_dbg(icd->dev.parent,
+       dev_dbg(icd->parent,
                        "%s: count=%d, size=%d\n", __func__, *count, *size);
 
        return 0;
@@ -241,7 +240,7 @@ static void free_buffer(struct videobuf_queue *vq, struct omap1_cam_buf *buf,
                videobuf_dma_contig_free(vq, vb);
        } else {
                struct soc_camera_device *icd = vq->priv_data;
-               struct device *dev = icd->dev.parent;
+               struct device *dev = icd->parent;
                struct videobuf_dmabuf *dma = videobuf_to_dma(vb);
 
                videobuf_dma_unmap(dev, dma);
@@ -258,7 +257,7 @@ static int omap1_videobuf_prepare(struct videobuf_queue *vq,
        struct omap1_cam_buf *buf = container_of(vb, struct omap1_cam_buf, vb);
        int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width,
                        icd->current_fmt->host_fmt);
-       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
        struct omap1_cam_dev *pcdev = ici->priv;
        int ret;
 
@@ -490,7 +489,7 @@ static void omap1_videobuf_queue(struct videobuf_queue *vq,
                                                struct videobuf_buffer *vb)
 {
        struct soc_camera_device *icd = vq->priv_data;
-       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
        struct omap1_cam_dev *pcdev = ici->priv;
        struct omap1_cam_buf *buf;
        u32 mode;
@@ -519,7 +518,7 @@ static void omap1_videobuf_queue(struct videobuf_queue *vq,
        pcdev->active = buf;
        pcdev->ready = NULL;
 
-       dev_dbg(icd->dev.parent,
+       dev_dbg(icd->parent,
                "%s: capture not active, setup FIFO, start DMA\n", __func__);
        mode = CAM_READ_CACHE(pcdev, MODE) & ~THRESHOLD_MASK;
        mode |= THRESHOLD_LEVEL(pcdev->vb_mode) << THRESHOLD_SHIFT;
@@ -543,8 +542,8 @@ static void omap1_videobuf_release(struct videobuf_queue *vq,
        struct omap1_cam_buf *buf =
                        container_of(vb, struct omap1_cam_buf, vb);
        struct soc_camera_device *icd = vq->priv_data;
-       struct device *dev = icd->dev.parent;
-       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+       struct device *dev = icd->parent;
+       struct soc_camera_host *ici = to_soc_camera_host(dev);
        struct omap1_cam_dev *pcdev = ici->priv;
 
        switch (vb->state) {
@@ -573,7 +572,7 @@ static void videobuf_done(struct omap1_cam_dev *pcdev,
 {
        struct omap1_cam_buf *buf = pcdev->active;
        struct videobuf_buffer *vb;
-       struct device *dev = pcdev->icd->dev.parent;
+       struct device *dev = pcdev->icd->parent;
 
        if (WARN_ON(!buf)) {
                suspend_capture(pcdev);
@@ -799,7 +798,7 @@ out:
 static irqreturn_t cam_isr(int irq, void *data)
 {
        struct omap1_cam_dev *pcdev = data;
-       struct device *dev = pcdev->icd->dev.parent;
+       struct device *dev = pcdev->icd->parent;
        struct omap1_cam_buf *buf = pcdev->active;
        u32 it_status;
        unsigned long flags;
@@ -909,7 +908,7 @@ static void sensor_reset(struct omap1_cam_dev *pcdev, bool reset)
  */
 static int omap1_cam_add_device(struct soc_camera_device *icd)
 {
-       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
        struct omap1_cam_dev *pcdev = ici->priv;
        u32 ctrlclock;
 
@@ -952,14 +951,14 @@ static int omap1_cam_add_device(struct soc_camera_device *icd)
 
        pcdev->icd = icd;
 
-       dev_dbg(icd->dev.parent, "OMAP1 Camera driver attached to camera %d\n",
+       dev_dbg(icd->parent, "OMAP1 Camera driver attached to camera %d\n",
                        icd->devnum);
        return 0;
 }
 
 static void omap1_cam_remove_device(struct soc_camera_device *icd)
 {
-       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
        struct omap1_cam_dev *pcdev = ici->priv;
        u32 ctrlclock;
 
@@ -985,7 +984,7 @@ static void omap1_cam_remove_device(struct soc_camera_device *icd)
 
        pcdev->icd = NULL;
 
-       dev_dbg(icd->dev.parent,
+       dev_dbg(icd->parent,
                "OMAP1 Camera driver detached from camera %d\n", icd->devnum);
 }
 
@@ -1070,7 +1069,7 @@ static int omap1_cam_get_formats(struct soc_camera_device *icd,
                unsigned int idx, struct soc_camera_format_xlate *xlate)
 {
        struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
-       struct device *dev = icd->dev.parent;
+       struct device *dev = icd->parent;
        int formats = 0, ret;
        enum v4l2_mbus_pixelcode code;
        const struct soc_mbus_pixelfmt *fmt;
@@ -1222,9 +1221,9 @@ static int omap1_cam_set_crop(struct soc_camera_device *icd,
        struct v4l2_rect *rect = &crop->c;
        const struct soc_camera_format_xlate *xlate = icd->current_fmt;
        struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
-       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+       struct device *dev = icd->parent;
+       struct soc_camera_host *ici = to_soc_camera_host(dev);
        struct omap1_cam_dev *pcdev = ici->priv;
-       struct device *dev = icd->dev.parent;
        struct v4l2_mbus_framefmt mf;
        int ret;
 
@@ -1270,8 +1269,8 @@ static int omap1_cam_set_fmt(struct soc_camera_device *icd,
 {
        struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
        const struct soc_camera_format_xlate *xlate;
-       struct device *dev = icd->dev.parent;
-       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+       struct device *dev = icd->parent;
+       struct soc_camera_host *ici = to_soc_camera_host(dev);
        struct omap1_cam_dev *pcdev = ici->priv;
        struct v4l2_pix_format *pix = &f->fmt.pix;
        struct v4l2_mbus_framefmt mf;
@@ -1326,7 +1325,7 @@ static int omap1_cam_try_fmt(struct soc_camera_device *icd,
 
        xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat);
        if (!xlate) {
-               dev_warn(icd->dev.parent, "Format %#x not found\n",
+               dev_warn(icd->parent, "Format %#x not found\n",
                         pix->pixelformat);
                return -EINVAL;
        }
@@ -1362,7 +1361,7 @@ static int omap1_cam_mmap_mapper(struct videobuf_queue *q,
                                  struct vm_area_struct *vma)
 {
        struct soc_camera_device *icd = q->priv_data;
-       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
        struct omap1_cam_dev *pcdev = ici->priv;
        int ret;
 
@@ -1377,17 +1376,17 @@ static int omap1_cam_mmap_mapper(struct videobuf_queue *q,
 static void omap1_cam_init_videobuf(struct videobuf_queue *q,
                                     struct soc_camera_device *icd)
 {
-       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
        struct omap1_cam_dev *pcdev = ici->priv;
 
        if (!sg_mode)
                videobuf_queue_dma_contig_init(q, &omap1_videobuf_ops,
-                               icd->dev.parent, &pcdev->lock,
+                               icd->parent, &pcdev->lock,
                                V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_NONE,
                                sizeof(struct omap1_cam_buf), icd, &icd->video_lock);
        else
                videobuf_queue_sg_init(q, &omap1_videobuf_ops,
-                               icd->dev.parent, &pcdev->lock,
+                               icd->parent, &pcdev->lock,
                                V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_NONE,
                                sizeof(struct omap1_cam_buf), icd, &icd->video_lock);
 
@@ -1431,7 +1430,6 @@ static int omap1_cam_querycap(struct soc_camera_host *ici,
 {
        /* cap->name is set by the friendly caller:-> */
        strlcpy(cap->card, "OMAP1 Camera", sizeof(cap->card));
-       cap->version = VERSION_CODE;
        cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
 
        return 0;
@@ -1440,41 +1438,55 @@ static int omap1_cam_querycap(struct soc_camera_host *ici,
 static int omap1_cam_set_bus_param(struct soc_camera_device *icd,
                __u32 pixfmt)
 {
-       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+       struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
+       struct device *dev = icd->parent;
+       struct soc_camera_host *ici = to_soc_camera_host(dev);
        struct omap1_cam_dev *pcdev = ici->priv;
-       struct device *dev = icd->dev.parent;
        const struct soc_camera_format_xlate *xlate;
        const struct soc_mbus_pixelfmt *fmt;
-       unsigned long camera_flags, common_flags;
+       struct v4l2_mbus_config cfg = {.type = V4L2_MBUS_PARALLEL,};
+       unsigned long common_flags;
        u32 ctrlclock, mode;
        int ret;
 
-       camera_flags = icd->ops->query_bus_param(icd);
-
-       common_flags = soc_camera_bus_param_compatible(camera_flags,
-                       SOCAM_BUS_FLAGS);
-       if (!common_flags)
-               return -EINVAL;
+       ret = v4l2_subdev_call(sd, video, g_mbus_config, &cfg);
+       if (!ret) {
+               common_flags = soc_mbus_config_compatible(&cfg, SOCAM_BUS_FLAGS);
+               if (!common_flags) {
+                       dev_warn(dev,
+                                "Flags incompatible: camera 0x%x, host 0x%x\n",
+                                cfg.flags, SOCAM_BUS_FLAGS);
+                       return -EINVAL;
+               }
+       } else if (ret != -ENOIOCTLCMD) {
+               return ret;
+       } else {
+               common_flags = SOCAM_BUS_FLAGS;
+       }
 
        /* Make choices, possibly based on platform configuration */
-       if ((common_flags & SOCAM_PCLK_SAMPLE_RISING) &&
-                       (common_flags & SOCAM_PCLK_SAMPLE_FALLING)) {
+       if ((common_flags & V4L2_MBUS_PCLK_SAMPLE_RISING) &&
+                       (common_flags & V4L2_MBUS_PCLK_SAMPLE_FALLING)) {
                if (!pcdev->pdata ||
                                pcdev->pdata->flags & OMAP1_CAMERA_LCLK_RISING)
-                       common_flags &= ~SOCAM_PCLK_SAMPLE_FALLING;
+                       common_flags &= ~V4L2_MBUS_PCLK_SAMPLE_FALLING;
                else
-                       common_flags &= ~SOCAM_PCLK_SAMPLE_RISING;
+                       common_flags &= ~V4L2_MBUS_PCLK_SAMPLE_RISING;
        }
 
-       ret = icd->ops->set_bus_param(icd, common_flags);
-       if (ret < 0)
+       cfg.flags = common_flags;
+       ret = v4l2_subdev_call(sd, video, s_mbus_config, &cfg);
+       if (ret < 0 && ret != -ENOIOCTLCMD) {
+               dev_dbg(dev, "camera s_mbus_config(0x%lx) returned %d\n",
+                       common_flags, ret);
                return ret;
+       }
 
        ctrlclock = CAM_READ_CACHE(pcdev, CTRLCLOCK);
        if (ctrlclock & LCLK_EN)
                CAM_WRITE(pcdev, CTRLCLOCK, ctrlclock & ~LCLK_EN);
 
-       if (common_flags & SOCAM_PCLK_SAMPLE_RISING) {
+       if (common_flags & V4L2_MBUS_PCLK_SAMPLE_RISING) {
                dev_dbg(dev, "CTRLCLOCK_REG |= POLCLK\n");
                ctrlclock |= POLCLK;
        } else {
@@ -1567,10 +1579,10 @@ static int __init omap1_cam_probe(struct platform_device *pdev)
        pcdev->clk = clk;
 
        pcdev->pdata = pdev->dev.platform_data;
-       pcdev->pflags = pcdev->pdata->flags;
-
-       if (pcdev->pdata)
+       if (pcdev->pdata) {
+               pcdev->pflags = pcdev->pdata->flags;
                pcdev->camexclk = pcdev->pdata->camexclk_khz * 1000;
+       }
 
        switch (pcdev->camexclk) {
        case 6000000:
@@ -1580,6 +1592,7 @@ static int __init omap1_cam_probe(struct platform_device *pdev)
        case 24000000:
                break;
        default:
+               /* pcdev->camexclk != 0 => pcdev->pdata != NULL */
                dev_warn(&pdev->dev,
                                "Incorrect sensor clock frequency %ld kHz, "
                                "should be one of 0, 6, 8, 9.6, 12 or 24 MHz, "
@@ -1587,8 +1600,7 @@ static int __init omap1_cam_probe(struct platform_device *pdev)
                                pcdev->pdata->camexclk_khz);
                pcdev->camexclk = 0;
        case 0:
-               dev_info(&pdev->dev,
-                               "Not providing sensor clock\n");
+               dev_info(&pdev->dev, "Not providing sensor clock\n");
        }
 
        INIT_LIST_HEAD(&pcdev->capture);
@@ -1718,4 +1730,5 @@ MODULE_PARM_DESC(sg_mode, "videobuf mode, 0: dma-contig (default), 1: dma-sg");
 MODULE_DESCRIPTION("OMAP1 Camera Interface driver");
 MODULE_AUTHOR("Janusz Krzysztofik <jkrzyszt@tis.icnet.pl>");
 MODULE_LICENSE("GPL v2");
+MODULE_VERSION(DRIVER_VERSION);
 MODULE_ALIAS("platform:" DRIVER_NAME);