[media] omap3isp: isp: Reset the ISP when the pipeline can't be stopped
authorLaurent Pinchart <laurent.pinchart@ideasonboard.com>
Tue, 1 Mar 2011 16:43:07 +0000 (13:43 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Sun, 17 Apr 2011 10:44:02 +0000 (07:44 -0300)
When a failure to stop a module in the pipeline is detected, the only
way to recover is to reset the ISP. However, as other users can be using
a different pipeline with other modules, the ISP can't be reset
synchronously with the error detection.

Mark the ISP as needing a reset when a failure to stop a pipeline is
detected, and reset the ISP when the last user releases the last
reference to the ISP.

Modify the omap3isp_pipeline_set_stream() function to record the new ISP
pipeline state only when no error occurs, except when stopping the
pipeline in which case the pipeline is still marked as stopped.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
drivers/media/video/omap3isp/isp.c
drivers/media/video/omap3isp/isp.h

index 7d68b109d32fc16e5c903fc734802156834baf16..f380f09b119c35a604d5d0718e7b25be9f503ed0 100644 (file)
@@ -872,6 +872,9 @@ static int isp_pipeline_disable(struct isp_pipeline *pipe)
                }
        }
 
+       if (failure < 0)
+               isp->needs_reset = true;
+
        return failure;
 }
 
@@ -884,7 +887,8 @@ static int isp_pipeline_disable(struct isp_pipeline *pipe)
  * single-shot or continuous mode.
  *
  * Return 0 if successful, or the return value of the failed video::s_stream
- * operation otherwise.
+ * operation otherwise. The pipeline state is not updated when the operation
+ * fails, except when stopping the pipeline.
  */
 int omap3isp_pipeline_set_stream(struct isp_pipeline *pipe,
                                 enum isp_pipeline_stream_state state)
@@ -895,7 +899,9 @@ int omap3isp_pipeline_set_stream(struct isp_pipeline *pipe,
                ret = isp_pipeline_disable(pipe);
        else
                ret = isp_pipeline_enable(pipe, state);
-       pipe->stream_state = state;
+
+       if (ret == 0 || state == ISP_PIPELINE_STREAM_STOPPED)
+               pipe->stream_state = state;
 
        return ret;
 }
@@ -1481,6 +1487,10 @@ void omap3isp_put(struct isp_device *isp)
        if (--isp->ref_count == 0) {
                isp_disable_interrupts(isp);
                isp_save_ctx(isp);
+               if (isp->needs_reset) {
+                       isp_reset(isp);
+                       isp->needs_reset = false;
+               }
                isp_disable_clocks(isp);
        }
        mutex_unlock(&isp->isp_mutex);
index cf5214e95a920ca11bc1cea5bac2c6efede31fbf..5f87645565b8289396c2c1cfb23753a790925005 100644 (file)
@@ -262,6 +262,7 @@ struct isp_device {
        /* ISP Obj */
        spinlock_t stat_lock;   /* common lock for statistic drivers */
        struct mutex isp_mutex; /* For handling ref_count field */
+       bool needs_reset;
        int has_context;
        int ref_count;
        unsigned int autoidle;