[media] omap3isp: isp: Reset the ISP when the pipeline can't be stopped

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>
This commit is contained in:
Laurent Pinchart 2011-03-01 13:43:07 -03:00 committed by Mauro Carvalho Chehab
parent b5feda91c1
commit 994d5375a2
2 changed files with 13 additions and 2 deletions

View file

@ -872,6 +872,9 @@ static int isp_pipeline_disable(struct isp_pipeline *pipe)
} }
} }
if (failure < 0)
isp->needs_reset = true;
return failure; return failure;
} }
@ -884,7 +887,8 @@ static int isp_pipeline_disable(struct isp_pipeline *pipe)
* single-shot or continuous mode. * single-shot or continuous mode.
* *
* Return 0 if successful, or the return value of the failed video::s_stream * 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, int omap3isp_pipeline_set_stream(struct isp_pipeline *pipe,
enum isp_pipeline_stream_state state) enum isp_pipeline_stream_state state)
@ -895,7 +899,9 @@ int omap3isp_pipeline_set_stream(struct isp_pipeline *pipe,
ret = isp_pipeline_disable(pipe); ret = isp_pipeline_disable(pipe);
else else
ret = isp_pipeline_enable(pipe, state); ret = isp_pipeline_enable(pipe, state);
pipe->stream_state = state;
if (ret == 0 || state == ISP_PIPELINE_STREAM_STOPPED)
pipe->stream_state = state;
return ret; return ret;
} }
@ -1481,6 +1487,10 @@ void omap3isp_put(struct isp_device *isp)
if (--isp->ref_count == 0) { if (--isp->ref_count == 0) {
isp_disable_interrupts(isp); isp_disable_interrupts(isp);
isp_save_ctx(isp); isp_save_ctx(isp);
if (isp->needs_reset) {
isp_reset(isp);
isp->needs_reset = false;
}
isp_disable_clocks(isp); isp_disable_clocks(isp);
} }
mutex_unlock(&isp->isp_mutex); mutex_unlock(&isp->isp_mutex);

View file

@ -262,6 +262,7 @@ struct isp_device {
/* ISP Obj */ /* ISP Obj */
spinlock_t stat_lock; /* common lock for statistic drivers */ spinlock_t stat_lock; /* common lock for statistic drivers */
struct mutex isp_mutex; /* For handling ref_count field */ struct mutex isp_mutex; /* For handling ref_count field */
bool needs_reset;
int has_context; int has_context;
int ref_count; int ref_count;
unsigned int autoidle; unsigned int autoidle;