[media] omap3isp: Cancel streaming when a fatal error occurs
[sfrench/cifs-2.6.git] / drivers / media / platform / omap3isp / isp.c
index 1c3608039663e281d23541f17aedcbce044c87fb..7e09c1dd137a0c16e915ba3c1b37dd0b73d3a76f 100644 (file)
@@ -290,9 +290,11 @@ static int isp_xclk_init(struct isp_device *isp)
        struct clk_init_data init;
        unsigned int i;
 
+       for (i = 0; i < ARRAY_SIZE(isp->xclks); ++i)
+               isp->xclks[i].clk = ERR_PTR(-EINVAL);
+
        for (i = 0; i < ARRAY_SIZE(isp->xclks); ++i) {
                struct isp_xclk *xclk = &isp->xclks[i];
-               struct clk *clk;
 
                xclk->isp = isp;
                xclk->id = i == 0 ? ISP_XCLK_A : ISP_XCLK_B;
@@ -305,10 +307,15 @@ static int isp_xclk_init(struct isp_device *isp)
                init.num_parents = 1;
 
                xclk->hw.init = &init;
-
-               clk = devm_clk_register(isp->dev, &xclk->hw);
-               if (IS_ERR(clk))
-                       return PTR_ERR(clk);
+               /*
+                * The first argument is NULL in order to avoid circular
+                * reference, as this driver takes reference on the
+                * sensor subdevice modules and the sensors would take
+                * reference on this module through clk_get().
+                */
+               xclk->clk = clk_register(NULL, &xclk->hw);
+               if (IS_ERR(xclk->clk))
+                       return PTR_ERR(xclk->clk);
 
                if (pdata->xclks[i].con_id == NULL &&
                    pdata->xclks[i].dev_id == NULL)
@@ -320,7 +327,7 @@ static int isp_xclk_init(struct isp_device *isp)
 
                xclk->lookup->con_id = pdata->xclks[i].con_id;
                xclk->lookup->dev_id = pdata->xclks[i].dev_id;
-               xclk->lookup->clk = clk;
+               xclk->lookup->clk = xclk->clk;
 
                clkdev_add(xclk->lookup);
        }
@@ -335,6 +342,9 @@ static void isp_xclk_cleanup(struct isp_device *isp)
        for (i = 0; i < ARRAY_SIZE(isp->xclks); ++i) {
                struct isp_xclk *xclk = &isp->xclks[i];
 
+               if (!IS_ERR(xclk->clk))
+                       clk_unregister(xclk->clk);
+
                if (xclk->lookup)
                        clkdev_drop(xclk->lookup);
        }
@@ -1046,6 +1056,23 @@ int omap3isp_pipeline_set_stream(struct isp_pipeline *pipe,
        return ret;
 }
 
+/*
+ * omap3isp_pipeline_cancel_stream - Cancel stream on a pipeline
+ * @pipe: ISP pipeline
+ *
+ * Cancelling a stream mark all buffers on all video nodes in the pipeline as
+ * erroneous and makes sure no new buffer can be queued. This function is called
+ * when a fatal error that prevents any further operation on the pipeline
+ * occurs.
+ */
+void omap3isp_pipeline_cancel_stream(struct isp_pipeline *pipe)
+{
+       if (pipe->input)
+               omap3isp_video_cancel_stream(pipe->input);
+       if (pipe->output)
+               omap3isp_video_cancel_stream(pipe->output);
+}
+
 /*
  * isp_pipeline_resume - Resume streaming on a pipeline
  * @pipe: ISP pipeline
@@ -1673,7 +1700,7 @@ void omap3isp_print_status(struct isp_device *isp)
  * ISP clocks get disabled in suspend(). Similarly, the clocks are reenabled in
  * resume(), and the the pipelines are restarted in complete().
  *
- * TODO: PM dependencies between the ISP and sensors are not modeled explicitly
+ * TODO: PM dependencies between the ISP and sensors are not modelled explicitly
  * yet.
  */
 static int isp_pm_prepare(struct device *dev)
@@ -2120,28 +2147,13 @@ static int isp_map_mem_resource(struct platform_device *pdev,
        /* request the mem region for the camera registers */
 
        mem = platform_get_resource(pdev, IORESOURCE_MEM, res);
-       if (!mem) {
-               dev_err(isp->dev, "no mem resource?\n");
-               return -ENODEV;
-       }
-
-       if (!devm_request_mem_region(isp->dev, mem->start, resource_size(mem),
-                                    pdev->name)) {
-               dev_err(isp->dev,
-                       "cannot reserve camera register I/O region\n");
-               return -ENODEV;
-       }
-       isp->mmio_base_phys[res] = mem->start;
-       isp->mmio_size[res] = resource_size(mem);
 
        /* map the region */
-       isp->mmio_base[res] = devm_ioremap_nocache(isp->dev,
-                                                  isp->mmio_base_phys[res],
-                                                  isp->mmio_size[res]);
-       if (!isp->mmio_base[res]) {
-               dev_err(isp->dev, "cannot map camera register I/O region\n");
-               return -ENODEV;
-       }
+       isp->mmio_base[res] = devm_ioremap_resource(isp->dev, mem);
+       if (IS_ERR(isp->mmio_base[res]))
+               return PTR_ERR(isp->mmio_base[res]);
+
+       isp->mmio_base_phys[res] = mem->start;
 
        return 0;
 }