diff options
author | Sylwester Nawrocki <s.nawrocki@samsung.com> | 2013-01-30 13:54:06 +0100 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2013-02-05 20:52:41 +0100 |
commit | 81619ce1931a1d96e53b455ca2f35757f0c457a5 (patch) | |
tree | 2ec70dacd59aa087d9d8c13b2c22f8919959eb67 /drivers | |
parent | [media] s5p-fimc: Avoid null pointer dereference in fimc_capture_ctrls_create() (diff) | |
download | linux-81619ce1931a1d96e53b455ca2f35757f0c457a5.tar.xz linux-81619ce1931a1d96e53b455ca2f35757f0c457a5.zip |
[media] s5p-fimc: Set default image format at device open()
Make sure a valid image format is initially set on both the CAPTURE
and the OUTPUT buffer queue.
Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/media/platform/s5p-fimc/fimc-core.c | 20 | ||||
-rw-r--r-- | drivers/media/platform/s5p-fimc/fimc-core.h | 5 | ||||
-rw-r--r-- | drivers/media/platform/s5p-fimc/fimc-m2m.c | 131 |
3 files changed, 75 insertions, 81 deletions
diff --git a/drivers/media/platform/s5p-fimc/fimc-core.c b/drivers/media/platform/s5p-fimc/fimc-core.c index a9625414ea95..29f7bb71c7e1 100644 --- a/drivers/media/platform/s5p-fimc/fimc-core.c +++ b/drivers/media/platform/s5p-fimc/fimc-core.c @@ -525,7 +525,6 @@ static int __fimc_s_ctrl(struct fimc_ctx *ctx, struct v4l2_ctrl *ctrl) { struct fimc_dev *fimc = ctx->fimc_dev; const struct fimc_variant *variant = fimc->variant; - unsigned int flags = FIMC_DST_FMT | FIMC_SRC_FMT; int ret = 0; if (ctrl->flags & V4L2_CTRL_FLAG_INACTIVE) @@ -541,8 +540,7 @@ static int __fimc_s_ctrl(struct fimc_ctx *ctx, struct v4l2_ctrl *ctrl) break; case V4L2_CID_ROTATE: - if (fimc_capture_pending(fimc) || - (ctx->state & flags) == flags) { + if (fimc_capture_pending(fimc)) { ret = fimc_check_scaler_ratio(ctx, ctx->s_frame.width, ctx->s_frame.height, ctx->d_frame.width, ctx->d_frame.height, ctrl->val); @@ -709,22 +707,6 @@ void __fimc_get_format(struct fimc_frame *frame, struct v4l2_format *f) } } -void fimc_fill_frame(struct fimc_frame *frame, struct v4l2_format *f) -{ - struct v4l2_pix_format_mplane *pixm = &f->fmt.pix_mp; - - frame->f_width = pixm->plane_fmt[0].bytesperline; - if (frame->fmt->colplanes == 1) - frame->f_width = (frame->f_width * 8) / frame->fmt->depth[0]; - frame->f_height = pixm->height; - frame->width = pixm->width; - frame->height = pixm->height; - frame->o_width = pixm->width; - frame->o_height = pixm->height; - frame->offs_h = 0; - frame->offs_v = 0; -} - /** * fimc_adjust_mplane_format - adjust bytesperline/sizeimage for each plane * @fmt: fimc pixel format description (input) diff --git a/drivers/media/platform/s5p-fimc/fimc-core.h b/drivers/media/platform/s5p-fimc/fimc-core.h index cf760c364099..412d50708f75 100644 --- a/drivers/media/platform/s5p-fimc/fimc-core.h +++ b/drivers/media/platform/s5p-fimc/fimc-core.h @@ -112,9 +112,7 @@ enum fimc_color_fmt { /* The hardware context state. */ #define FIMC_PARAMS (1 << 0) -#define FIMC_SRC_FMT (1 << 3) -#define FIMC_DST_FMT (1 << 4) -#define FIMC_COMPOSE (1 << 5) +#define FIMC_COMPOSE (1 << 1) #define FIMC_CTX_M2M (1 << 16) #define FIMC_CTX_CAP (1 << 17) #define FIMC_CTX_SHUT (1 << 18) @@ -654,7 +652,6 @@ int fimc_prepare_addr(struct fimc_ctx *ctx, struct vb2_buffer *vb, struct fimc_frame *frame, struct fimc_addr *paddr); void fimc_prepare_dma_offset(struct fimc_ctx *ctx, struct fimc_frame *f); void fimc_set_yuv_order(struct fimc_ctx *ctx); -void fimc_fill_frame(struct fimc_frame *frame, struct v4l2_format *f); void fimc_capture_irq_handler(struct fimc_dev *fimc, int deq_buf); int fimc_register_m2m_device(struct fimc_dev *fimc, diff --git a/drivers/media/platform/s5p-fimc/fimc-m2m.c b/drivers/media/platform/s5p-fimc/fimc-m2m.c index 1eabd7e74849..f3d535cdd87f 100644 --- a/drivers/media/platform/s5p-fimc/fimc-m2m.c +++ b/drivers/media/platform/s5p-fimc/fimc-m2m.c @@ -1,8 +1,8 @@ /* * Samsung S5P/EXYNOS4 SoC series FIMC (video postprocessor) driver * - * Copyright (C) 2012 Samsung Electronics Co., Ltd. - * Sylwester Nawrocki, <s.nawrocki@samsung.com> + * Copyright (C) 2012 - 2013 Samsung Electronics Co., Ltd. + * Sylwester Nawrocki <s.nawrocki@samsung.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published @@ -160,8 +160,7 @@ static void fimc_device_run(void *priv) fimc_hw_set_output_addr(fimc, &df->paddr, -1); fimc_activate_capture(ctx); - ctx->state &= (FIMC_CTX_M2M | FIMC_CTX_CAP | - FIMC_SRC_FMT | FIMC_DST_FMT); + ctx->state &= (FIMC_CTX_M2M | FIMC_CTX_CAP); fimc_hw_activate_input_dma(fimc, true); dma_unlock: @@ -309,8 +308,6 @@ static int fimc_try_fmt_mplane(struct fimc_ctx *ctx, struct v4l2_format *f) if (!IS_M2M(f->type)) return -EINVAL; - dbg("w: %d, h: %d", pix->width, pix->height); - fmt = fimc_find_format(&pix->pixelformat, NULL, get_m2m_fmt_flags(f->type), 0); if (WARN(fmt == NULL, "Pixel format lookup failed")) @@ -350,19 +347,39 @@ static int fimc_m2m_try_fmt_mplane(struct file *file, void *fh, struct v4l2_format *f) { struct fimc_ctx *ctx = fh_to_ctx(fh); - return fimc_try_fmt_mplane(ctx, f); } +static void __set_frame_format(struct fimc_frame *frame, struct fimc_fmt *fmt, + struct v4l2_pix_format_mplane *pixm) +{ + int i; + + for (i = 0; i < fmt->colplanes; i++) { + frame->bytesperline[i] = pixm->plane_fmt[i].bytesperline; + frame->payload[i] = pixm->plane_fmt[i].sizeimage; + } + + frame->f_width = pixm->width; + frame->f_height = pixm->height; + frame->o_width = pixm->width; + frame->o_height = pixm->height; + frame->width = pixm->width; + frame->height = pixm->height; + frame->offs_h = 0; + frame->offs_v = 0; + frame->fmt = fmt; +} + static int fimc_m2m_s_fmt_mplane(struct file *file, void *fh, struct v4l2_format *f) { struct fimc_ctx *ctx = fh_to_ctx(fh); struct fimc_dev *fimc = ctx->fimc_dev; + struct fimc_fmt *fmt; struct vb2_queue *vq; struct fimc_frame *frame; - struct v4l2_pix_format_mplane *pix; - int i, ret = 0; + int ret; ret = fimc_try_fmt_mplane(ctx, f); if (ret) @@ -380,31 +397,16 @@ static int fimc_m2m_s_fmt_mplane(struct file *file, void *fh, else frame = &ctx->d_frame; - pix = &f->fmt.pix_mp; - frame->fmt = fimc_find_format(&pix->pixelformat, NULL, - get_m2m_fmt_flags(f->type), 0); - if (!frame->fmt) + fmt = fimc_find_format(&f->fmt.pix_mp.pixelformat, NULL, + get_m2m_fmt_flags(f->type), 0); + if (!fmt) return -EINVAL; + __set_frame_format(frame, fmt, &f->fmt.pix_mp); + /* Update RGB Alpha control state and value range */ fimc_alpha_ctrl_update(ctx); - for (i = 0; i < frame->fmt->colplanes; i++) { - frame->bytesperline[i] = pix->plane_fmt[i].bytesperline; - frame->payload[i] = pix->plane_fmt[i].sizeimage; - } - - fimc_fill_frame(frame, f); - - ctx->scaler.enabled = 1; - - if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) - fimc_ctx_state_set(FIMC_PARAMS | FIMC_DST_FMT, ctx); - else - fimc_ctx_state_set(FIMC_PARAMS | FIMC_SRC_FMT, ctx); - - dbg("f_w: %d, f_h: %d", frame->f_width, frame->f_height); - return 0; } @@ -412,7 +414,6 @@ static int fimc_m2m_reqbufs(struct file *file, void *fh, struct v4l2_requestbuffers *reqbufs) { struct fimc_ctx *ctx = fh_to_ctx(fh); - return v4l2_m2m_reqbufs(file, ctx->m2m_ctx, reqbufs); } @@ -420,7 +421,6 @@ static int fimc_m2m_querybuf(struct file *file, void *fh, struct v4l2_buffer *buf) { struct fimc_ctx *ctx = fh_to_ctx(fh); - return v4l2_m2m_querybuf(file, ctx->m2m_ctx, buf); } @@ -428,7 +428,6 @@ static int fimc_m2m_qbuf(struct file *file, void *fh, struct v4l2_buffer *buf) { struct fimc_ctx *ctx = fh_to_ctx(fh); - return v4l2_m2m_qbuf(file, ctx->m2m_ctx, buf); } @@ -436,7 +435,6 @@ static int fimc_m2m_dqbuf(struct file *file, void *fh, struct v4l2_buffer *buf) { struct fimc_ctx *ctx = fh_to_ctx(fh); - return v4l2_m2m_dqbuf(file, ctx->m2m_ctx, buf); } @@ -444,7 +442,6 @@ static int fimc_m2m_expbuf(struct file *file, void *fh, struct v4l2_exportbuffer *eb) { struct fimc_ctx *ctx = fh_to_ctx(fh); - return v4l2_m2m_expbuf(file, ctx->m2m_ctx, eb); } @@ -453,15 +450,6 @@ static int fimc_m2m_streamon(struct file *file, void *fh, enum v4l2_buf_type type) { struct fimc_ctx *ctx = fh_to_ctx(fh); - - /* The source and target color format need to be set */ - if (V4L2_TYPE_IS_OUTPUT(type)) { - if (!fimc_ctx_state_is_set(FIMC_SRC_FMT, ctx)) - return -EINVAL; - } else if (!fimc_ctx_state_is_set(FIMC_DST_FMT, ctx)) { - return -EINVAL; - } - return v4l2_m2m_streamon(file, ctx->m2m_ctx, type); } @@ -469,7 +457,6 @@ static int fimc_m2m_streamoff(struct file *file, void *fh, enum v4l2_buf_type type) { struct fimc_ctx *ctx = fh_to_ctx(fh); - return v4l2_m2m_streamoff(file, ctx->m2m_ctx, type); } @@ -577,20 +564,18 @@ static int fimc_m2m_s_crop(struct file *file, void *fh, const struct v4l2_crop * &ctx->s_frame : &ctx->d_frame; /* Check to see if scaling ratio is within supported range */ - if (fimc_ctx_state_is_set(FIMC_DST_FMT | FIMC_SRC_FMT, ctx)) { - if (cr.type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { - ret = fimc_check_scaler_ratio(ctx, cr.c.width, - cr.c.height, ctx->d_frame.width, - ctx->d_frame.height, ctx->rotation); - } else { - ret = fimc_check_scaler_ratio(ctx, ctx->s_frame.width, - ctx->s_frame.height, cr.c.width, - cr.c.height, ctx->rotation); - } - if (ret) { - v4l2_err(&fimc->m2m.vfd, "Out of scaler range\n"); - return -EINVAL; - } + if (cr.type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { + ret = fimc_check_scaler_ratio(ctx, cr.c.width, + cr.c.height, ctx->d_frame.width, + ctx->d_frame.height, ctx->rotation); + } else { + ret = fimc_check_scaler_ratio(ctx, ctx->s_frame.width, + ctx->s_frame.height, cr.c.width, + cr.c.height, ctx->rotation); + } + if (ret) { + v4l2_err(&fimc->m2m.vfd, "Out of scaler range\n"); + return -EINVAL; } f->offs_h = cr.c.left; @@ -653,6 +638,29 @@ static int queue_init(void *priv, struct vb2_queue *src_vq, return vb2_queue_init(dst_vq); } +static int fimc_m2m_set_default_format(struct fimc_ctx *ctx) +{ + struct v4l2_pix_format_mplane pixm = { + .pixelformat = V4L2_PIX_FMT_RGB32, + .width = 800, + .height = 600, + .plane_fmt[0] = { + .bytesperline = 800 * 4, + .sizeimage = 800 * 4 * 600, + }, + }; + struct fimc_fmt *fmt; + + fmt = fimc_find_format(&pixm.pixelformat, NULL, FMT_FLAGS_M2M, 0); + if (!fmt) + return -EINVAL; + + __set_frame_format(&ctx->s_frame, fmt, &pixm); + __set_frame_format(&ctx->d_frame, fmt, &pixm); + + return 0; +} + static int fimc_m2m_open(struct file *file) { struct fimc_dev *fimc = video_drvdata(file); @@ -697,6 +705,7 @@ static int fimc_m2m_open(struct file *file) ctx->flags = 0; ctx->in_path = FIMC_IO_DMA; ctx->out_path = FIMC_IO_DMA; + ctx->scaler.enabled = 1; ctx->m2m_ctx = v4l2_m2m_ctx_init(fimc->m2m.m2m_dev, ctx, queue_init); if (IS_ERR(ctx->m2m_ctx)) { @@ -707,9 +716,15 @@ static int fimc_m2m_open(struct file *file) if (fimc->m2m.refcnt++ == 0) set_bit(ST_M2M_RUN, &fimc->state); + ret = fimc_m2m_set_default_format(ctx); + if (ret < 0) + goto error_m2m_ctx; + mutex_unlock(&fimc->lock); return 0; +error_m2m_ctx: + v4l2_m2m_ctx_release(ctx->m2m_ctx); error_c: fimc_ctrls_delete(ctx); error_fh: |