diff options
Diffstat (limited to 'drivers/media/platform/exynos-gsc')
| -rw-r--r-- | drivers/media/platform/exynos-gsc/gsc-core.c | 22 | ||||
| -rw-r--r-- | drivers/media/platform/exynos-gsc/gsc-core.h | 2 | ||||
| -rw-r--r-- | drivers/media/platform/exynos-gsc/gsc-m2m.c | 46 |
3 files changed, 44 insertions, 26 deletions
diff --git a/drivers/media/platform/exynos-gsc/gsc-core.c b/drivers/media/platform/exynos-gsc/gsc-core.c index 559fab2a2d6..9d0cc04d7ab 100644 --- a/drivers/media/platform/exynos-gsc/gsc-core.c +++ b/drivers/media/platform/exynos-gsc/gsc-core.c @@ -1122,10 +1122,14 @@ static int gsc_probe(struct platform_device *pdev) goto err_clk; } - ret = gsc_register_m2m_device(gsc); + ret = v4l2_device_register(dev, &gsc->v4l2_dev); if (ret) goto err_clk; + ret = gsc_register_m2m_device(gsc); + if (ret) + goto err_v4l2; + platform_set_drvdata(pdev, gsc); pm_runtime_enable(dev); ret = pm_runtime_get_sync(&pdev->dev); @@ -1147,6 +1151,8 @@ err_pm: pm_runtime_put(dev); err_m2m: gsc_unregister_m2m_device(gsc); +err_v4l2: + v4l2_device_unregister(&gsc->v4l2_dev); err_clk: gsc_clk_put(gsc); return ret; @@ -1157,6 +1163,7 @@ static int gsc_remove(struct platform_device *pdev) struct gsc_dev *gsc = platform_get_drvdata(pdev); gsc_unregister_m2m_device(gsc); + v4l2_device_unregister(&gsc->v4l2_dev); vb2_dma_contig_cleanup_ctx(gsc->alloc_ctx); pm_runtime_disable(&pdev->dev); @@ -1210,12 +1217,12 @@ static int gsc_resume(struct device *dev) spin_unlock_irqrestore(&gsc->slock, flags); return 0; } - gsc_hw_set_sw_reset(gsc); - gsc_wait_reset(gsc); - spin_unlock_irqrestore(&gsc->slock, flags); - return gsc_m2m_resume(gsc); + if (!pm_runtime_suspended(dev)) + return gsc_runtime_resume(dev); + + return 0; } static int gsc_suspend(struct device *dev) @@ -1227,7 +1234,10 @@ static int gsc_suspend(struct device *dev) if (test_and_set_bit(ST_SUSPEND, &gsc->state)) return 0; - return gsc_m2m_suspend(gsc); + if (!pm_runtime_suspended(dev)) + return gsc_runtime_suspend(dev); + + return 0; } static const struct dev_pm_ops gsc_pm_ops = { diff --git a/drivers/media/platform/exynos-gsc/gsc-core.h b/drivers/media/platform/exynos-gsc/gsc-core.h index cc19bba09bd..ef0a6564cef 100644 --- a/drivers/media/platform/exynos-gsc/gsc-core.h +++ b/drivers/media/platform/exynos-gsc/gsc-core.h @@ -45,6 +45,7 @@ #define GSC_DST_FMT (1 << 2) #define GSC_CTX_M2M (1 << 3) #define GSC_CTX_STOP_REQ (1 << 6) +#define GSC_CTX_ABORT (1 << 7) enum gsc_dev_flags { /* for global */ @@ -343,6 +344,7 @@ struct gsc_dev { unsigned long state; struct vb2_alloc_ctx *alloc_ctx; struct video_device vdev; + struct v4l2_device v4l2_dev; }; /** diff --git a/drivers/media/platform/exynos-gsc/gsc-m2m.c b/drivers/media/platform/exynos-gsc/gsc-m2m.c index 40a73f7d20d..e434f1f03d7 100644 --- a/drivers/media/platform/exynos-gsc/gsc-m2m.c +++ b/drivers/media/platform/exynos-gsc/gsc-m2m.c @@ -46,6 +46,17 @@ static int gsc_m2m_ctx_stop_req(struct gsc_ctx *ctx) return ret == 0 ? -ETIMEDOUT : ret; } +static void __gsc_m2m_job_abort(struct gsc_ctx *ctx) +{ + int ret; + + ret = gsc_m2m_ctx_stop_req(ctx); + if ((ret == -ETIMEDOUT) || (ctx->state & GSC_CTX_ABORT)) { + gsc_ctx_state_lock_clear(GSC_CTX_STOP_REQ | GSC_CTX_ABORT, ctx); + gsc_m2m_job_finish(ctx, VB2_BUF_STATE_ERROR); + } +} + static int gsc_m2m_start_streaming(struct vb2_queue *q, unsigned int count) { struct gsc_ctx *ctx = q->drv_priv; @@ -55,18 +66,13 @@ static int gsc_m2m_start_streaming(struct vb2_queue *q, unsigned int count) return ret > 0 ? 0 : ret; } -static int gsc_m2m_stop_streaming(struct vb2_queue *q) +static void gsc_m2m_stop_streaming(struct vb2_queue *q) { struct gsc_ctx *ctx = q->drv_priv; - int ret; - ret = gsc_m2m_ctx_stop_req(ctx); - if (ret == -ETIMEDOUT) - gsc_m2m_job_finish(ctx, VB2_BUF_STATE_ERROR); + __gsc_m2m_job_abort(ctx); pm_runtime_put(&ctx->gsc_dev->pdev->dev); - - return 0; } void gsc_m2m_job_finish(struct gsc_ctx *ctx, int vb_state) @@ -80,8 +86,12 @@ void gsc_m2m_job_finish(struct gsc_ctx *ctx, int vb_state) dst_vb = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx); if (src_vb && dst_vb) { - src_vb->v4l2_buf.timestamp = dst_vb->v4l2_buf.timestamp; - src_vb->v4l2_buf.timecode = dst_vb->v4l2_buf.timecode; + dst_vb->v4l2_buf.timestamp = src_vb->v4l2_buf.timestamp; + dst_vb->v4l2_buf.timecode = src_vb->v4l2_buf.timecode; + dst_vb->v4l2_buf.flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK; + dst_vb->v4l2_buf.flags |= + src_vb->v4l2_buf.flags + & V4L2_BUF_FLAG_TSTAMP_SRC_MASK; v4l2_m2m_buf_done(src_vb, vb_state); v4l2_m2m_buf_done(dst_vb, vb_state); @@ -91,15 +101,9 @@ void gsc_m2m_job_finish(struct gsc_ctx *ctx, int vb_state) } } - static void gsc_m2m_job_abort(void *priv) { - struct gsc_ctx *ctx = priv; - int ret; - - ret = gsc_m2m_ctx_stop_req(ctx); - if (ret == -ETIMEDOUT) - gsc_m2m_job_finish(ctx, VB2_BUF_STATE_ERROR); + __gsc_m2m_job_abort((struct gsc_ctx *)priv); } static int gsc_get_bufs(struct gsc_ctx *ctx) @@ -150,9 +154,10 @@ static void gsc_m2m_device_run(void *priv) gsc->m2m.ctx = ctx; } - is_set = (ctx->state & GSC_CTX_STOP_REQ) ? 1 : 0; - ctx->state &= ~GSC_CTX_STOP_REQ; + is_set = ctx->state & GSC_CTX_STOP_REQ; if (is_set) { + ctx->state &= ~GSC_CTX_STOP_REQ; + ctx->state |= GSC_CTX_ABORT; wake_up(&gsc->irq_queue); goto put_device; } @@ -587,7 +592,7 @@ static int queue_init(void *priv, struct vb2_queue *src_vq, src_vq->ops = &gsc_m2m_qops; src_vq->mem_ops = &vb2_dma_contig_memops; src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer); - src_vq->timestamp_type = V4L2_BUF_FLAG_TIMESTAMP_COPY; + src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; ret = vb2_queue_init(src_vq); if (ret) @@ -600,7 +605,7 @@ static int queue_init(void *priv, struct vb2_queue *src_vq, dst_vq->ops = &gsc_m2m_qops; dst_vq->mem_ops = &vb2_dma_contig_memops; dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer); - dst_vq->timestamp_type = V4L2_BUF_FLAG_TIMESTAMP_COPY; + dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; return vb2_queue_init(dst_vq); } @@ -751,6 +756,7 @@ int gsc_register_m2m_device(struct gsc_dev *gsc) gsc->vdev.release = video_device_release_empty; gsc->vdev.lock = &gsc->lock; gsc->vdev.vfl_dir = VFL_DIR_M2M; + gsc->vdev.v4l2_dev = &gsc->v4l2_dev; snprintf(gsc->vdev.name, sizeof(gsc->vdev.name), "%s.%d:m2m", GSC_MODULE_NAME, gsc->id); |
