From: Ming Qian Date: Tue, 3 Feb 2026 08:23:40 +0000 (+0800) Subject: media: imx-jpeg: Add encoder ops layer for hardware abstraction X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=03b5048a21bb542ee77990890ee1ad67732e94ff;p=thirdparty%2Fkernel%2Fstable.git media: imx-jpeg: Add encoder ops layer for hardware abstraction Introduce mxc_jpeg_enc_ops function pointer structure to abstract encoder configuration differences between hardware versions. Extract the existing two-phase manual configuration into dedicated functions (enter_config_mode/exit_config_mode) for v0 hardware. Add setup_desc callback placeholder for future v1 hardware support which will use descriptor-based configuration. Store the extended sequential mode flag in the context to avoid recalculating it during configuration phases. No functional change. Reviewed-by: Frank Li Signed-off-by: Ming Qian Signed-off-by: Nicolas Dufresne Signed-off-by: Hans Verkuil --- diff --git a/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c b/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c index 417d8fa5621e..515be2317e2d 100644 --- a/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c +++ b/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c @@ -64,6 +64,12 @@ #include "mxc-jpeg-hw.h" #include "mxc-jpeg.h" +#define call_void_jpeg_enc_ops(jpeg, op, args...) \ + do { \ + if ((jpeg)->enc_cfg_ops && (jpeg)->enc_cfg_ops->op) \ + (jpeg)->enc_cfg_ops->op(args); \ + } while (0) + static const struct mxc_jpeg_fmt mxc_formats[] = { { .name = "JPEG", @@ -1030,11 +1036,7 @@ static irqreturn_t mxc_jpeg_dec_irq(int irq, void *priv) if (jpeg->mode == MXC_JPEG_ENCODE && ctx->enc_state == MXC_JPEG_ENC_CONF) { - q_data = mxc_jpeg_get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); - ctx->enc_state = MXC_JPEG_ENCODING; - dev_dbg(dev, "Encoder config finished. Start encoding...\n"); - mxc_jpeg_enc_set_quality(dev, reg, ctx->jpeg_quality); - mxc_jpeg_enc_mode_go(dev, reg, mxc_jpeg_is_extended_sequential(q_data->fmt)); + call_void_jpeg_enc_ops(jpeg, exit_config_mode, ctx); goto job_unlock; } if (jpeg->mode == MXC_JPEG_DECODE && jpeg_src_buf->dht_needed && @@ -1272,6 +1274,7 @@ static void mxc_jpeg_config_dec_desc(struct vb2_buffer *out_buf, jpeg_src_buf = vb2_to_mxc_buf(src_buf); + ctx->extseq = mxc_jpeg_is_extended_sequential(jpeg_src_buf->fmt); /* setup the decoding descriptor */ desc->next_descpt_ptr = 0; /* end of chain */ q_data_cap = mxc_jpeg_get_q_data(ctx, cap_type); @@ -1335,8 +1338,12 @@ static void mxc_jpeg_config_enc_desc(struct vb2_buffer *out_buf, struct mxc_jpeg_q_data *q_data; enum mxc_jpeg_image_format img_fmt; int w, h; + bool extseq; q_data = mxc_jpeg_get_q_data(ctx, src_buf->vb2_queue->type); + extseq = mxc_jpeg_is_extended_sequential(q_data->fmt); + + ctx->extseq = extseq; memset(desc, 0, sizeof(struct mxc_jpeg_desc)); memset(cfg_desc, 0, sizeof(struct mxc_jpeg_desc)); @@ -1369,11 +1376,14 @@ static void mxc_jpeg_config_enc_desc(struct vb2_buffer *out_buf, desc->stm_ctrl = STM_CTRL_CONFIG_MOD(0) | STM_CTRL_IMAGE_FORMAT(img_fmt); desc->stm_ctrl |= STM_CTRL_BITBUF_PTR_CLR(1); - if (mxc_jpeg_is_extended_sequential(q_data->fmt)) + if (extseq) desc->stm_ctrl |= STM_CTRL_PIXEL_PRECISION; else desc->stm_ctrl &= ~STM_CTRL_PIXEL_PRECISION; mxc_jpeg_addrs(desc, src_buf, dst_buf, 0); + + call_void_jpeg_enc_ops(jpeg, setup_desc, ctx); + dev_dbg(jpeg->dev, "cfg_desc:\n"); print_descriptor_info(jpeg->dev, cfg_desc); dev_dbg(jpeg->dev, "enc desc:\n"); @@ -1385,6 +1395,33 @@ static void mxc_jpeg_config_enc_desc(struct vb2_buffer *out_buf, mxc_jpeg_set_desc(cfg_desc_handle, reg, slot); } +static void mxc_jpeg_enc_start_config_manually(struct mxc_jpeg_ctx *ctx) +{ + struct mxc_jpeg_dev *jpeg = ctx->mxc_jpeg; + void __iomem *reg = jpeg->base_reg; + struct device *dev = jpeg->dev; + + ctx->enc_state = MXC_JPEG_ENC_CONF; + mxc_jpeg_enc_mode_conf(dev, reg, ctx->extseq); +} + +static void mxc_jpeg_enc_finish_config_manually(struct mxc_jpeg_ctx *ctx) +{ + struct mxc_jpeg_dev *jpeg = ctx->mxc_jpeg; + void __iomem *reg = jpeg->base_reg; + struct device *dev = jpeg->dev; + + ctx->enc_state = MXC_JPEG_ENCODING; + dev_dbg(dev, "Encoder config finished. Start encoding...\n"); + mxc_jpeg_enc_set_quality(dev, reg, ctx->jpeg_quality); + mxc_jpeg_enc_mode_go(dev, reg, ctx->extseq); +} + +static const struct mxc_jpeg_enc_ops mxc_jpeg_enc_cfg_ops_v0 = { + .enter_config_mode = mxc_jpeg_enc_start_config_manually, + .exit_config_mode = mxc_jpeg_enc_finish_config_manually +}; + static const struct mxc_jpeg_fmt *mxc_jpeg_get_sibling_format(const struct mxc_jpeg_fmt *fmt) { int i; @@ -1590,12 +1627,10 @@ static void mxc_jpeg_device_run(void *priv) if (jpeg->mode == MXC_JPEG_ENCODE) { dev_dbg(dev, "Encoding on slot %d\n", ctx->slot); - ctx->enc_state = MXC_JPEG_ENC_CONF; mxc_jpeg_config_enc_desc(&dst_buf->vb2_buf, ctx, &src_buf->vb2_buf, &dst_buf->vb2_buf); /* start config phase */ - mxc_jpeg_enc_mode_conf(dev, reg, - mxc_jpeg_is_extended_sequential(q_data_out->fmt)); + call_void_jpeg_enc_ops(jpeg, enter_config_mode, ctx); } else { dev_dbg(dev, "Decoding on slot %d\n", ctx->slot); print_mxc_buf(jpeg, &src_buf->vb2_buf, 0); @@ -2977,6 +3012,9 @@ static int mxc_jpeg_probe(struct platform_device *pdev) goto err_pm; } + if (mode == MXC_JPEG_ENCODE) + jpeg->enc_cfg_ops = &mxc_jpeg_enc_cfg_ops_v0; + return 0; err_pm: diff --git a/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.h b/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.h index 9c5b4f053ded..cdfefb68346a 100644 --- a/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.h +++ b/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.h @@ -105,6 +105,7 @@ struct mxc_jpeg_ctx { unsigned int source_change; bool need_initial_source_change_evt; bool header_parsed; + bool extseq; struct v4l2_ctrl_handler ctrl_handler; u8 jpeg_quality; struct delayed_work task_timer; @@ -125,6 +126,15 @@ struct mxc_jpeg_slot_data { dma_addr_t cfg_dec_daddr; }; +struct mxc_jpeg_enc_ops { + /* Manual configuration (v0 hardware) - two-phase process */ + void (*enter_config_mode)(struct mxc_jpeg_ctx *ctx); + void (*exit_config_mode)(struct mxc_jpeg_ctx *ctx); + + /* Descriptor-based configuration (v1 hardware) - single-phase */ + void (*setup_desc)(struct mxc_jpeg_ctx *ctx); +}; + struct mxc_jpeg_dev { spinlock_t hw_lock; /* hardware access lock */ unsigned int mode; @@ -142,6 +152,7 @@ struct mxc_jpeg_dev { struct device **pd_dev; struct device_link **pd_link; struct gen_pool *sram_pool; + const struct mxc_jpeg_enc_ops *enc_cfg_ops; }; /**