[media] move soc_camera i2c drivers into its own dir
[deliverable/linux.git] / drivers / media / video / mx2_emmaprp.c
index 0bd5815de369413db01e4a023094591a18cbc91c..2810015d78f4ea253743b950a26e3a46ffe5efb7 100644 (file)
@@ -209,7 +209,7 @@ struct emmaprp_dev {
 
        int                     irq_emma;
        void __iomem            *base_emma;
-       struct clk              *clk_emma;
+       struct clk              *clk_emma_ahb, *clk_emma_ipg;
        struct resource         *res_emma;
 
        struct v4l2_m2m_dev     *m2m_dev;
@@ -396,9 +396,13 @@ static int vidioc_querycap(struct file *file, void *priv,
 {
        strncpy(cap->driver, MEM2MEM_NAME, sizeof(cap->driver) - 1);
        strncpy(cap->card, MEM2MEM_NAME, sizeof(cap->card) - 1);
-       cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT
-                         | V4L2_CAP_STREAMING;
-
+       /*
+        * This is only a mem-to-mem video device. The capture and output
+        * device capability flags are left only for backward compatibility
+        * and are scheduled for removal.
+        */
+       cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT |
+                           V4L2_CAP_VIDEO_M2M | V4L2_CAP_STREAMING;
        return 0;
 }
 
@@ -791,18 +795,26 @@ static int emmaprp_open(struct file *file)
        file->private_data = ctx;
        ctx->dev = pcdev;
 
+       if (mutex_lock_interruptible(&pcdev->dev_mutex)) {
+               kfree(ctx);
+               return -ERESTARTSYS;
+       }
+
        ctx->m2m_ctx = v4l2_m2m_ctx_init(pcdev->m2m_dev, ctx, &queue_init);
 
        if (IS_ERR(ctx->m2m_ctx)) {
                int ret = PTR_ERR(ctx->m2m_ctx);
 
+               mutex_unlock(&pcdev->dev_mutex);
                kfree(ctx);
                return ret;
        }
 
-       clk_enable(pcdev->clk_emma);
+       clk_prepare_enable(pcdev->clk_emma_ipg);
+       clk_prepare_enable(pcdev->clk_emma_ahb);
        ctx->q_data[V4L2_M2M_SRC].fmt = &formats[1];
        ctx->q_data[V4L2_M2M_DST].fmt = &formats[0];
+       mutex_unlock(&pcdev->dev_mutex);
 
        dprintk(pcdev, "Created instance %p, m2m_ctx: %p\n", ctx, ctx->m2m_ctx);
 
@@ -816,8 +828,11 @@ static int emmaprp_release(struct file *file)
 
        dprintk(pcdev, "Releasing instance %p\n", ctx);
 
-       clk_disable(pcdev->clk_emma);
+       mutex_lock(&pcdev->dev_mutex);
+       clk_disable_unprepare(pcdev->clk_emma_ahb);
+       clk_disable_unprepare(pcdev->clk_emma_ipg);
        v4l2_m2m_ctx_release(ctx->m2m_ctx);
+       mutex_unlock(&pcdev->dev_mutex);
        kfree(ctx);
 
        return 0;
@@ -826,16 +841,27 @@ static int emmaprp_release(struct file *file)
 static unsigned int emmaprp_poll(struct file *file,
                                 struct poll_table_struct *wait)
 {
+       struct emmaprp_dev *pcdev = video_drvdata(file);
        struct emmaprp_ctx *ctx = file->private_data;
+       unsigned int res;
 
-       return v4l2_m2m_poll(file, ctx->m2m_ctx, wait);
+       mutex_lock(&pcdev->dev_mutex);
+       res = v4l2_m2m_poll(file, ctx->m2m_ctx, wait);
+       mutex_unlock(&pcdev->dev_mutex);
+       return res;
 }
 
 static int emmaprp_mmap(struct file *file, struct vm_area_struct *vma)
 {
+       struct emmaprp_dev *pcdev = video_drvdata(file);
        struct emmaprp_ctx *ctx = file->private_data;
+       int ret;
 
-       return v4l2_m2m_mmap(file, ctx->m2m_ctx, vma);
+       if (mutex_lock_interruptible(&pcdev->dev_mutex))
+               return -ERESTARTSYS;
+       ret = v4l2_m2m_mmap(file, ctx->m2m_ctx, vma);
+       mutex_unlock(&pcdev->dev_mutex);
+       return ret;
 }
 
 static const struct v4l2_file_operations emmaprp_fops = {
@@ -876,9 +902,15 @@ static int emmaprp_probe(struct platform_device *pdev)
 
        spin_lock_init(&pcdev->irqlock);
 
-       pcdev->clk_emma = clk_get(&pdev->dev, NULL);
-       if (IS_ERR(pcdev->clk_emma)) {
-               ret = PTR_ERR(pcdev->clk_emma);
+       pcdev->clk_emma_ipg = devm_clk_get(&pdev->dev, "ipg");
+       if (IS_ERR(pcdev->clk_emma_ipg)) {
+               ret = PTR_ERR(pcdev->clk_emma_ipg);
+               goto free_dev;
+       }
+
+       pcdev->clk_emma_ahb = devm_clk_get(&pdev->dev, "ahb");
+       if (IS_ERR(pcdev->clk_emma_ipg)) {
+               ret = PTR_ERR(pcdev->clk_emma_ahb);
                goto free_dev;
        }
 
@@ -887,12 +919,12 @@ static int emmaprp_probe(struct platform_device *pdev)
        if (irq_emma < 0 || res_emma == NULL) {
                dev_err(&pdev->dev, "Missing platform resources data\n");
                ret = -ENODEV;
-               goto free_clk;
+               goto free_dev;
        }
 
        ret = v4l2_device_register(&pdev->dev, &pcdev->v4l2_dev);
        if (ret)
-               goto free_clk;
+               goto free_dev;
 
        mutex_init(&pcdev->dev_mutex);
 
@@ -904,10 +936,6 @@ static int emmaprp_probe(struct platform_device *pdev)
        }
 
        *vfd = emmaprp_videodev;
-       /* Locking in file operations other than ioctl should be done
-          by the driver, not the V4L2 core.
-          This driver needs auditing so that this flag can be removed. */
-       set_bit(V4L2_FL_LOCK_ALL_FOPS, &vfd->flags);
        vfd->lock = &pcdev->dev_mutex;
 
        video_set_drvdata(vfd, pcdev);
@@ -965,8 +993,6 @@ rel_vdev:
        video_device_release(vfd);
 unreg_dev:
        v4l2_device_unregister(&pcdev->v4l2_dev);
-free_clk:
-       clk_put(pcdev->clk_emma);
 free_dev:
        kfree(pcdev);
 
@@ -983,7 +1009,6 @@ static int emmaprp_remove(struct platform_device *pdev)
        v4l2_m2m_release(pcdev->m2m_dev);
        vb2_dma_contig_cleanup_ctx(pcdev->alloc_ctx);
        v4l2_device_unregister(&pcdev->v4l2_dev);
-       clk_put(pcdev->clk_emma);
        kfree(pcdev);
 
        return 0;
This page took 0.03437 seconds and 5 git commands to generate.