unsigned int h_shift, v_shift;
int ret;
+ ret = sc_power_clk_enable(sc);
+ if (ret)
+ return ret;
+
spin_lock_irqsave(&sc->ctxlist_lock, flags);
if (sc->current_ctx || list_empty(&sc->context_list)) {
/* a job is currently being processed or no job is to run */
+ sc_clk_power_disable(sc);
+ spin_unlock_irqrestore(&sc->ctxlist_lock, flags);
+ return 0;
+ }
+
+ /*
+ * sc_run_next_job() must not reenter while sc->state is DEV_RUN.
+ * DEV_RUN is cleared when an operation is finished.
+ */
+ BUG_ON(test_bit(DEV_RUN, &sc->state));
+
+ set_bit(DEV_RUN, &sc->state);
+
+ if (test_bit(DEV_SUSPEND, &sc->state)) {
+ clear_bit(DEV_RUN, &sc->state);
+ sc_clk_power_disable(sc);
spin_unlock_irqrestore(&sc->ctxlist_lock, flags);
return 0;
}
ctx = list_first_entry(&sc->context_list, struct sc_ctx, node);
+ set_bit(CTX_RUN, &ctx->flags);
list_del_init(&ctx->node);
sc->current_ctx = ctx;
spin_unlock_irqrestore(&sc->ctxlist_lock, flags);
- /*
- * sc_run_next_job() must not reenter while sc->state is DEV_RUN.
- * DEV_RUN is cleared when an operation is finished.
- */
- BUG_ON(test_bit(DEV_RUN, &sc->state));
-
s_frame = &ctx->s_frame;
d_frame = &ctx->d_frame;
- ret = sc_power_clk_enable(sc);
- if (ret) {
- pm_runtime_put(sc->dev);
- return ret;
- }
-
sc_hwset_init(sc);
if (ctx->i_frame) {
sc_hwset_int_en(sc);
- set_bit(DEV_RUN, &sc->state);
- set_bit(CTX_RUN, &ctx->flags);
-
sc_set_prefetch_buffers(sc->dev, ctx);
mod_timer(&sc->wdt.timer, jiffies + SC_TIMEOUT);
{
unsigned long flags;
+ if (test_bit(CTX_ABORT, &ctx->flags)) {
+ dev_err(sc->dev, "aborted scaler device run\n");
+ return -EAGAIN;
+ }
+
spin_lock_irqsave(&sc->ctxlist_lock, flags);
list_add_tail(&ctx->node, &sc->context_list);
spin_unlock_irqrestore(&sc->ctxlist_lock, flags);
spin_lock(&sc->slock);
- clear_bit(DEV_RUN, &sc->state);
-
/*
* ok to access sc->current_ctx withot ctxlist_lock held
* because it is not modified until sc_run_next_job() is called.
if (!SCALER_INT_OK(irq_status))
sc_hwset_soft_reset(sc);
- sc_clk_power_disable(sc);
-
+ clear_bit(DEV_RUN, &sc->state);
clear_bit(CTX_RUN, &ctx->flags);
+ sc_clk_power_disable(sc);
+
if (ctx->context_type == SC_CTX_V4L2_TYPE) {
BUG_ON(ctx != v4l2_m2m_get_curr_priv(sc->m2m.m2m_dev));
SCALER_INT_OK(irq_status) ?
VB2_BUF_STATE_DONE : VB2_BUF_STATE_ERROR);
- if (test_bit(DEV_SUSPEND, &sc->state)) {
- sc_dbg("wake up blocked process by suspend\n");
- wake_up(&sc->wait);
- } else {
- v4l2_m2m_job_finish(sc->m2m.m2m_dev, ctx->m2m_ctx);
- }
+ v4l2_m2m_job_finish(sc->m2m.m2m_dev, ctx->m2m_ctx);
/* Wake up from CTX_ABORT state */
- if (test_and_clear_bit(CTX_ABORT, &ctx->flags))
- wake_up(&sc->wait);
+ clear_bit(CTX_ABORT, &ctx->flags);
} else {
struct m2m1shot_task *task =
m2m1shot_get_current_task(sc->m21dev);
sc->current_ctx = NULL;
spin_unlock(&sc->ctxlist_lock);
+ wake_up(&sc->wait);
+
sc_run_next_job(sc);
isr_unlock:
struct sc_dev *sc = ctx->sc_dev;
struct sc_frame *s_frame, *d_frame;
- if (test_bit(DEV_SUSPEND, &sc->state)) {
- dev_err(sc->dev, "Scaler is in suspend state\n");
- return;
- }
-
- if (test_bit(CTX_ABORT, &ctx->flags)) {
- dev_err(sc->dev, "aborted scaler device run\n");
- return;
- }
-
s_frame = &ctx->s_frame;
d_frame = &ctx->d_frame;
struct sc_dev *sc = ctx->sc_dev;
struct sc_frame *s_frame, *d_frame;
- if (test_bit(DEV_SUSPEND, &sc->state)) {
- dev_err(sc->dev, "Scaler is in suspend state\n");
- return -EAGAIN;
- }
-
- /* no aborted state is required for m2m1shot */
-
s_frame = &ctx->s_frame;
d_frame = &ctx->d_frame;
clear_bit(DEV_SUSPEND, &sc->state);
+ sc_run_next_job(sc);
+
return 0;
}
#endif
static void sc_shutdown(struct platform_device *pdev)
{
struct sc_dev *sc = platform_get_drvdata(pdev);
- unsigned long flags;
- spin_lock_irqsave(&sc->slock, flags);
set_bit(DEV_SUSPEND, &sc->state);
- spin_unlock_irqrestore(&sc->slock, flags);
wait_event(sc->wait,
!test_bit(DEV_RUN, &sc->state));