summaryrefslogtreecommitdiff
path: root/drivers/media/platform/ti-vpe/vpe.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/platform/ti-vpe/vpe.c')
-rw-r--r--drivers/media/platform/ti-vpe/vpe.c71
1 files changed, 54 insertions, 17 deletions
diff --git a/drivers/media/platform/ti-vpe/vpe.c b/drivers/media/platform/ti-vpe/vpe.c
index ebde4f4586e6..32489d6369ca 100644
--- a/drivers/media/platform/ti-vpe/vpe.c
+++ b/drivers/media/platform/ti-vpe/vpe.c
@@ -2025,28 +2025,33 @@ static void vpe_buf_queue(struct vb2_buffer *vb)
v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf);
}
-static int vpe_start_streaming(struct vb2_queue *q, unsigned int count)
+static int check_srcdst_sizes(struct vpe_ctx *ctx)
{
- struct vpe_ctx *ctx = vb2_get_drv_priv(q);
+ struct vpe_q_data *s_q_data = &ctx->q_data[Q_DATA_SRC];
+ struct vpe_q_data *d_q_data = &ctx->q_data[Q_DATA_DST];
+ unsigned int src_w = s_q_data->c_rect.width;
+ unsigned int src_h = s_q_data->c_rect.height;
+ unsigned int dst_w = d_q_data->c_rect.width;
+ unsigned int dst_h = d_q_data->c_rect.height;
- if (ctx->deinterlacing)
- config_edi_input_mode(ctx, 0x0);
+ if (src_w == dst_w && src_h == dst_h)
+ return 0;
- if (ctx->sequence != 0)
- set_srcdst_params(ctx);
+ if (src_h <= SC_MAX_PIXEL_HEIGHT &&
+ src_w <= SC_MAX_PIXEL_WIDTH &&
+ dst_h <= SC_MAX_PIXEL_HEIGHT &&
+ dst_w <= SC_MAX_PIXEL_WIDTH)
+ return 0;
- return 0;
+ return -1;
}
-static void vpe_stop_streaming(struct vb2_queue *q)
+static void vpe_return_all_buffers(struct vpe_ctx *ctx, struct vb2_queue *q,
+ enum vb2_buffer_state state)
{
- struct vpe_ctx *ctx = vb2_get_drv_priv(q);
struct vb2_v4l2_buffer *vb;
unsigned long flags;
- vpe_dump_regs(ctx->dev);
- vpdma_dump_regs(ctx->dev->vpdma);
-
for (;;) {
if (V4L2_TYPE_IS_OUTPUT(q->type))
vb = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
@@ -2055,7 +2060,7 @@ static void vpe_stop_streaming(struct vb2_queue *q)
if (!vb)
break;
spin_lock_irqsave(&ctx->dev->lock, flags);
- v4l2_m2m_buf_done(vb, VB2_BUF_STATE_ERROR);
+ v4l2_m2m_buf_done(vb, state);
spin_unlock_irqrestore(&ctx->dev->lock, flags);
}
@@ -2068,15 +2073,15 @@ static void vpe_stop_streaming(struct vb2_queue *q)
spin_lock_irqsave(&ctx->dev->lock, flags);
if (ctx->src_vbs[2])
- v4l2_m2m_buf_done(ctx->src_vbs[2], VB2_BUF_STATE_ERROR);
+ v4l2_m2m_buf_done(ctx->src_vbs[2], state);
if (ctx->src_vbs[1] && (ctx->src_vbs[1] != ctx->src_vbs[2]))
- v4l2_m2m_buf_done(ctx->src_vbs[1], VB2_BUF_STATE_ERROR);
+ v4l2_m2m_buf_done(ctx->src_vbs[1], state);
if (ctx->src_vbs[0] &&
(ctx->src_vbs[0] != ctx->src_vbs[1]) &&
(ctx->src_vbs[0] != ctx->src_vbs[2]))
- v4l2_m2m_buf_done(ctx->src_vbs[0], VB2_BUF_STATE_ERROR);
+ v4l2_m2m_buf_done(ctx->src_vbs[0], state);
ctx->src_vbs[2] = NULL;
ctx->src_vbs[1] = NULL;
@@ -2087,13 +2092,45 @@ static void vpe_stop_streaming(struct vb2_queue *q)
if (ctx->dst_vb) {
spin_lock_irqsave(&ctx->dev->lock, flags);
- v4l2_m2m_buf_done(ctx->dst_vb, VB2_BUF_STATE_ERROR);
+ v4l2_m2m_buf_done(ctx->dst_vb, state);
ctx->dst_vb = NULL;
spin_unlock_irqrestore(&ctx->dev->lock, flags);
}
}
}
+static int vpe_start_streaming(struct vb2_queue *q, unsigned int count)
+{
+ struct vpe_ctx *ctx = vb2_get_drv_priv(q);
+
+ /* Check any of the size exceed maximum scaling sizes */
+ if (check_srcdst_sizes(ctx)) {
+ vpe_err(ctx->dev,
+ "Conversion setup failed, check source and destination parameters\n"
+ );
+ vpe_return_all_buffers(ctx, q, VB2_BUF_STATE_QUEUED);
+ return -EINVAL;
+ }
+
+ if (ctx->deinterlacing)
+ config_edi_input_mode(ctx, 0x0);
+
+ if (ctx->sequence != 0)
+ set_srcdst_params(ctx);
+
+ return 0;
+}
+
+static void vpe_stop_streaming(struct vb2_queue *q)
+{
+ struct vpe_ctx *ctx = vb2_get_drv_priv(q);
+
+ vpe_dump_regs(ctx->dev);
+ vpdma_dump_regs(ctx->dev->vpdma);
+
+ vpe_return_all_buffers(ctx, q, VB2_BUF_STATE_ERROR);
+}
+
static const struct vb2_ops vpe_qops = {
.queue_setup = vpe_queue_setup,
.buf_prepare = vpe_buf_prepare,