diff --git a/drivers/media/platform/rockchip/rga/rga-buf.c b/drivers/media/platform/rockchip/rga/rga-buf.c index 092c2bdf6b67..c0ea6003336b 100644 --- a/drivers/media/platform/rockchip/rga/rga-buf.c +++ b/drivers/media/platform/rockchip/rga/rga-buf.c @@ -162,7 +162,7 @@ static int rga_buf_prepare(struct vb2_buffer *vb) } /* Fill the remaining planes */ - info = v4l2_format_info(f->fmt->fourcc); + info = v4l2_format_info(f->pix.pixelformat); for (i = info->mem_planes; i < info->comp_planes; i++) dma_addrs[i] = dma_addrs[0] + get_plane_offset(f, info, i); diff --git a/drivers/media/platform/rockchip/rga/rga-hw.c b/drivers/media/platform/rockchip/rga/rga-hw.c index fac3975e2d0c..616ea1bc1131 100644 --- a/drivers/media/platform/rockchip/rga/rga-hw.c +++ b/drivers/media/platform/rockchip/rga/rga-hw.c @@ -171,6 +171,8 @@ static void rga_cmd_set_trans_info(struct rga_ctx *ctx) union rga_dst_vir_info dst_vir_info; union rga_dst_act_info dst_act_info; u32 in_stride, out_stride; + struct rga_fmt *in_fmt = ctx->in.fmt; + struct rga_fmt *out_fmt = ctx->out.fmt; src_h = ctx->in.crop.height; src_w = ctx->in.crop.width; @@ -186,18 +188,18 @@ static void rga_cmd_set_trans_info(struct rga_ctx *ctx) dst_vir_info.val = dest[(RGA_DST_VIR_INFO - RGA_MODE_BASE_REG) >> 2]; dst_act_info.val = dest[(RGA_DST_ACT_INFO - RGA_MODE_BASE_REG) >> 2]; - src_info.data.format = ctx->in.fmt->hw_format; - src_info.data.swap = ctx->in.fmt->color_swap; - dst_info.data.format = ctx->out.fmt->hw_format; - dst_info.data.swap = ctx->out.fmt->color_swap; + src_info.data.format = in_fmt->hw_format; + src_info.data.swap = in_fmt->color_swap; + dst_info.data.format = out_fmt->hw_format; + dst_info.data.swap = out_fmt->color_swap; /* * CSC mode must only be set when the colorspace families differ between * input and output. It must remain unset (zeroed) if both are the same. */ - if (RGA_COLOR_FMT_IS_YUV(ctx->in.fmt->hw_format) && - RGA_COLOR_FMT_IS_RGB(ctx->out.fmt->hw_format)) { + if (RGA_COLOR_FMT_IS_YUV(in_fmt->hw_format) && + RGA_COLOR_FMT_IS_RGB(out_fmt->hw_format)) { switch (ctx->in.pix.colorspace) { case V4L2_COLORSPACE_REC709: src_info.data.csc_mode = RGA_SRC_CSC_MODE_BT709_R0; @@ -208,8 +210,8 @@ static void rga_cmd_set_trans_info(struct rga_ctx *ctx) } } - if (RGA_COLOR_FMT_IS_RGB(ctx->in.fmt->hw_format) && - RGA_COLOR_FMT_IS_YUV(ctx->out.fmt->hw_format)) { + if (RGA_COLOR_FMT_IS_RGB(in_fmt->hw_format) && + RGA_COLOR_FMT_IS_YUV(out_fmt->hw_format)) { switch (ctx->out.pix.colorspace) { case V4L2_COLORSPACE_REC709: dst_info.data.csc_mode = RGA_SRC_CSC_MODE_BT709_R0; @@ -563,11 +565,36 @@ static struct rga_fmt formats[] = { }, }; +static void *rga_adjust_and_map_format(struct rga_ctx *ctx, + struct v4l2_pix_format_mplane *format, + bool is_output) +{ + unsigned int i; + + if (!format) + return &formats[0]; + + for (i = 0; i < ARRAY_SIZE(formats); i++) { + if (formats[i].fourcc == format->pixelformat) + return &formats[i]; + } + + format->pixelformat = formats[0].fourcc; + return &formats[0]; +} + +static int rga_enum_format(struct v4l2_fmtdesc *f) +{ + if (f->index >= ARRAY_SIZE(formats)) + return -EINVAL; + + f->pixelformat = formats[f->index].fourcc; + return 0; +} + const struct rga_hw rga2_hw = { .card_type = "rga2", .has_internal_iommu = true, - .formats = formats, - .num_formats = ARRAY_SIZE(formats), .cmdbuf_size = RGA_CMDBUF_SIZE, .min_width = MIN_WIDTH, .max_width = MAX_WIDTH, @@ -580,4 +607,6 @@ const struct rga_hw rga2_hw = { .start = rga_hw_start, .handle_irq = rga_handle_irq, .get_version = rga_get_version, + .adjust_and_map_format = rga_adjust_and_map_format, + .enum_format = rga_enum_format, }; diff --git a/drivers/media/platform/rockchip/rga/rga-hw.h b/drivers/media/platform/rockchip/rga/rga-hw.h index 805ec23e5e3f..14ffa5ebd453 100644 --- a/drivers/media/platform/rockchip/rga/rga-hw.h +++ b/drivers/media/platform/rockchip/rga/rga-hw.h @@ -6,6 +6,8 @@ #ifndef __RGA_HW_H__ #define __RGA_HW_H__ +#include + #define RGA_CMDBUF_SIZE 0x80 /* Hardware limits */ @@ -431,4 +433,10 @@ union rga_pat_con { } data; }; +struct rga_fmt { + u32 fourcc; + u8 color_swap; + u8 hw_format; +}; + #endif diff --git a/drivers/media/platform/rockchip/rga/rga.c b/drivers/media/platform/rockchip/rga/rga.c index e52d0577b236..1878b4e26360 100644 --- a/drivers/media/platform/rockchip/rga/rga.c +++ b/drivers/media/platform/rockchip/rga/rga.c @@ -232,17 +232,6 @@ int rga_check_scaling(const struct rga_hw *hw, const struct v4l2_rect *crop_in, return 0; } -static struct rga_fmt *rga_fmt_find(struct rockchip_rga *rga, u32 pixelformat) -{ - unsigned int i; - - for (i = 0; i < rga->hw->num_formats; i++) { - if (rga->hw->formats[i].fourcc == pixelformat) - return &rga->hw->formats[i]; - } - return NULL; -} - struct rga_frame *rga_get_frame(struct rga_ctx *ctx, enum v4l2_buf_type type) { if (V4L2_TYPE_IS_OUTPUT(type)) @@ -264,7 +253,6 @@ static int rga_open(struct file *file) .crop.top = 0, .crop.width = def_width, .crop.height = def_height, - .fmt = &rga->hw->formats[0], }; ctx = kzalloc_obj(*ctx); @@ -286,9 +274,12 @@ static int rga_open(struct file *file) ctx->in = def_frame; ctx->out = def_frame; - v4l2_fill_pixfmt_mp_aligned(&ctx->in.pix, ctx->in.fmt->fourcc, + ctx->in.fmt = rga->hw->adjust_and_map_format(ctx, &ctx->in.pix, true); + v4l2_fill_pixfmt_mp_aligned(&ctx->in.pix, ctx->in.pix.pixelformat, def_width, def_height, rga->hw->stride_alignment); - v4l2_fill_pixfmt_mp_aligned(&ctx->out.pix, ctx->out.fmt->fourcc, + ctx->out.fmt = + rga->hw->adjust_and_map_format(ctx, &ctx->out.pix, false); + v4l2_fill_pixfmt_mp_aligned(&ctx->out.pix, ctx->out.pix.pixelformat, def_width, def_height, rga->hw->stride_alignment); if (mutex_lock_interruptible(&rga->mutex)) { @@ -370,13 +361,11 @@ vidioc_querycap(struct file *file, void *priv, struct v4l2_capability *cap) static int vidioc_enum_fmt(struct file *file, void *priv, struct v4l2_fmtdesc *f) { struct rockchip_rga *rga = video_drvdata(file); - struct rga_fmt *fmt; + int ret; - if (f->index >= rga->hw->num_formats) - return -EINVAL; - - fmt = &rga->hw->formats[f->index]; - f->pixelformat = fmt->fourcc; + ret = rga->hw->enum_format(f); + if (ret != 0) + return ret; if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE && f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) @@ -411,7 +400,6 @@ static int vidioc_try_fmt(struct file *file, void *priv, struct v4l2_format *f) struct v4l2_pix_format_mplane *pix_fmt = &f->fmt.pix_mp; struct rga_ctx *ctx = file_to_rga_ctx(file); const struct rga_hw *hw = ctx->rga->hw; - struct rga_fmt *fmt; struct v4l2_frmsize_stepwise frmsize = { .min_width = hw->min_width, .max_width = hw->max_width, @@ -442,12 +430,10 @@ static int vidioc_try_fmt(struct file *file, void *priv, struct v4l2_format *f) pix_fmt->xfer_func = frm->pix.xfer_func; } - fmt = rga_fmt_find(ctx->rga, pix_fmt->pixelformat); - if (!fmt) - fmt = &hw->formats[0]; + hw->adjust_and_map_format(ctx, pix_fmt, V4L2_TYPE_IS_OUTPUT(f->type)); v4l2_apply_frmsize_constraints(&pix_fmt->width, &pix_fmt->height, &frmsize); - v4l2_fill_pixfmt_mp_aligned(pix_fmt, fmt->fourcc, + v4l2_fill_pixfmt_mp_aligned(pix_fmt, pix_fmt->pixelformat, pix_fmt->width, pix_fmt->height, hw->stride_alignment); pix_fmt->field = V4L2_FIELD_NONE; @@ -478,7 +464,8 @@ static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f) frm = rga_get_frame(ctx, f->type); if (IS_ERR(frm)) return PTR_ERR(frm); - frm->fmt = rga_fmt_find(rga, pix_fmt->pixelformat); + frm->fmt = rga->hw->adjust_and_map_format(ctx, pix_fmt, + V4L2_TYPE_IS_OUTPUT(f->type)); /* * Copy colorimetry from output to capture as required by the @@ -503,7 +490,7 @@ static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f) v4l2_dbg(debug, 1, &rga->v4l2_dev, "[%s] fmt - %p4cc %dx%d (stride %d)\n", V4L2_TYPE_IS_OUTPUT(f->type) ? "OUTPUT" : "CAPTURE", - &frm->fmt->fourcc, pix_fmt->width, pix_fmt->height, + &pix_fmt->pixelformat, pix_fmt->width, pix_fmt->height, pix_fmt->plane_fmt[0].bytesperline); for (i = 0; i < pix_fmt->num_planes; i++) { diff --git a/drivers/media/platform/rockchip/rga/rga.h b/drivers/media/platform/rockchip/rga/rga.h index 227ab6c0532c..effe364a86b0 100644 --- a/drivers/media/platform/rockchip/rga/rga.h +++ b/drivers/media/platform/rockchip/rga/rga.h @@ -17,18 +17,12 @@ #define DEFAULT_WIDTH 100 #define DEFAULT_HEIGHT 100 -struct rga_fmt { - u32 fourcc; - u8 color_swap; - u8 hw_format; -}; - struct rga_frame { /* Crop */ struct v4l2_rect crop; /* Image format */ - struct rga_fmt *fmt; + void *fmt; struct v4l2_pix_format_mplane pix; }; @@ -146,8 +140,6 @@ static inline void rga_mod(struct rockchip_rga *rga, u32 reg, u32 val, u32 mask) struct rga_hw { const char *card_type; bool has_internal_iommu; - struct rga_fmt *formats; - u32 num_formats; size_t cmdbuf_size; u32 min_width, min_height; u32 max_width, max_height; @@ -159,6 +151,10 @@ struct rga_hw { struct rga_vb_buffer *src, struct rga_vb_buffer *dst); bool (*handle_irq)(struct rockchip_rga *rga); void (*get_version)(struct rockchip_rga *rga); + void *(*adjust_and_map_format)(struct rga_ctx *ctx, + struct v4l2_pix_format_mplane *format, + bool is_output); + int (*enum_format)(struct v4l2_fmtdesc *f); }; static inline bool rga_has_internal_iommu(const struct rockchip_rga *rga)