media: imx-jpeg: Handle source change in a function
authorMing Qian <ming.qian@nxp.com>
Wed, 23 Mar 2022 09:05:57 +0000 (10:05 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 17 Aug 2022 12:23:21 +0000 (14:23 +0200)
[ Upstream commit 831f87424dd3973612782983ef7352789795b4df ]

Refine code to support dynamic resolution change

Signed-off-by: Ming Qian <ming.qian@nxp.com>
Reviewed-by: Mirela Rabulea <mirela.rabulea@nxp.com>
Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/media/platform/imx-jpeg/mxc-jpeg.c

index 718de99..6289fec 100644 (file)
@@ -301,6 +301,9 @@ struct mxc_jpeg_src_buf {
        /* mxc-jpeg specific */
        bool                    dht_needed;
        bool                    jpeg_parse_error;
+       const struct mxc_jpeg_fmt       *fmt;
+       int                     w;
+       int                     h;
 };
 
 static inline struct mxc_jpeg_src_buf *vb2_to_mxc_buf(struct vb2_buffer *vb)
@@ -313,6 +316,9 @@ static unsigned int debug;
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "Debug level (0-3)");
 
+static void mxc_jpeg_bytesperline(struct mxc_jpeg_q_data *q, u32 precision);
+static void mxc_jpeg_sizeimage(struct mxc_jpeg_q_data *q);
+
 static void _bswap16(u16 *a)
 {
        *a = ((*a & 0x00FF) << 8) | ((*a & 0xFF00) >> 8);
@@ -908,6 +914,59 @@ static void mxc_jpeg_config_enc_desc(struct vb2_buffer *out_buf,
        mxc_jpeg_set_desc(cfg_desc_handle, reg, slot);
 }
 
+static bool mxc_jpeg_source_change(struct mxc_jpeg_ctx *ctx,
+                                  struct mxc_jpeg_src_buf *jpeg_src_buf)
+{
+       struct device *dev = ctx->mxc_jpeg->dev;
+       struct mxc_jpeg_q_data *q_data_cap;
+       bool src_chg = false;
+
+       if (!jpeg_src_buf->fmt)
+               return src_chg;
+
+       q_data_cap = mxc_jpeg_get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
+       if (q_data_cap->w != jpeg_src_buf->w || q_data_cap->h != jpeg_src_buf->h) {
+               dev_dbg(dev, "Detected jpeg res=(%dx%d)->(%dx%d), pixfmt=%c%c%c%c\n",
+                       q_data_cap->w, q_data_cap->h,
+                       jpeg_src_buf->w, jpeg_src_buf->h,
+                       (jpeg_src_buf->fmt->fourcc & 0xff),
+                       (jpeg_src_buf->fmt->fourcc >>  8) & 0xff,
+                       (jpeg_src_buf->fmt->fourcc >> 16) & 0xff,
+                       (jpeg_src_buf->fmt->fourcc >> 24) & 0xff);
+
+               /*
+                * set-up the capture queue with the pixelformat and resolution
+                * detected from the jpeg output stream
+                */
+               q_data_cap->w = jpeg_src_buf->w;
+               q_data_cap->h = jpeg_src_buf->h;
+               q_data_cap->fmt = jpeg_src_buf->fmt;
+               q_data_cap->w_adjusted = q_data_cap->w;
+               q_data_cap->h_adjusted = q_data_cap->h;
+
+               /*
+                * align up the resolution for CAST IP,
+                * but leave the buffer resolution unchanged
+                */
+               v4l_bound_align_image(&q_data_cap->w_adjusted,
+                                     q_data_cap->w_adjusted,  /* adjust up */
+                                     MXC_JPEG_MAX_WIDTH,
+                                     q_data_cap->fmt->h_align,
+                                     &q_data_cap->h_adjusted,
+                                     q_data_cap->h_adjusted, /* adjust up */
+                                     MXC_JPEG_MAX_HEIGHT,
+                                     q_data_cap->fmt->v_align,
+                                     0);
+
+               /* setup bytesperline/sizeimage for capture queue */
+               mxc_jpeg_bytesperline(q_data_cap, jpeg_src_buf->fmt->precision);
+               mxc_jpeg_sizeimage(q_data_cap);
+               notify_src_chg(ctx);
+               src_chg = true;
+       }
+       return src_chg;
+}
+
 static void mxc_jpeg_device_run(void *priv)
 {
        struct mxc_jpeg_ctx *ctx = priv;
@@ -1200,8 +1259,7 @@ static u32 mxc_jpeg_get_image_format(struct device *dev,
        return fourcc;
 }
 
-static void mxc_jpeg_bytesperline(struct mxc_jpeg_q_data *q,
-                                 u32 precision)
+static void mxc_jpeg_bytesperline(struct mxc_jpeg_q_data *q, u32 precision)
 {
        /* Bytes distance between the leftmost pixels in two adjacent lines */
        if (q->fmt->fourcc == V4L2_PIX_FMT_JPEG) {
@@ -1252,9 +1310,7 @@ static void mxc_jpeg_sizeimage(struct mxc_jpeg_q_data *q)
 static int mxc_jpeg_parse(struct mxc_jpeg_ctx *ctx, struct vb2_buffer *vb)
 {
        struct device *dev = ctx->mxc_jpeg->dev;
-       struct mxc_jpeg_q_data *q_data_out, *q_data_cap;
-       enum v4l2_buf_type cap_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
-       bool src_chg = false;
+       struct mxc_jpeg_q_data *q_data_out;
        u32 fourcc;
        struct v4l2_jpeg_header header;
        struct mxc_jpeg_sof *psof = NULL;
@@ -1322,51 +1378,11 @@ static int mxc_jpeg_parse(struct mxc_jpeg_ctx *ctx, struct vb2_buffer *vb)
        if (fourcc == 0)
                return -EINVAL;
 
-       /*
-        * set-up the capture queue with the pixelformat and resolution
-        * detected from the jpeg output stream
-        */
-       q_data_cap = mxc_jpeg_get_q_data(ctx, cap_type);
-       if (q_data_cap->w != header.frame.width ||
-           q_data_cap->h != header.frame.height)
-               src_chg = true;
-       q_data_cap->w = header.frame.width;
-       q_data_cap->h = header.frame.height;
-       q_data_cap->fmt = mxc_jpeg_find_format(ctx, fourcc);
-       q_data_cap->w_adjusted = q_data_cap->w;
-       q_data_cap->h_adjusted = q_data_cap->h;
-       /*
-        * align up the resolution for CAST IP,
-        * but leave the buffer resolution unchanged
-        */
-       v4l_bound_align_image(&q_data_cap->w_adjusted,
-                             q_data_cap->w_adjusted,  /* adjust up */
-                             MXC_JPEG_MAX_WIDTH,
-                             q_data_cap->fmt->h_align,
-                             &q_data_cap->h_adjusted,
-                             q_data_cap->h_adjusted, /* adjust up */
-                             MXC_JPEG_MAX_HEIGHT,
-                             q_data_cap->fmt->v_align,
-                             0);
-       dev_dbg(dev, "Detected jpeg res=(%dx%d)->(%dx%d), pixfmt=%c%c%c%c\n",
-               q_data_cap->w, q_data_cap->h,
-               q_data_cap->w_adjusted, q_data_cap->h_adjusted,
-               (fourcc & 0xff),
-               (fourcc >>  8) & 0xff,
-               (fourcc >> 16) & 0xff,
-               (fourcc >> 24) & 0xff);
-
-       /* setup bytesperline/sizeimage for capture queue */
-       mxc_jpeg_bytesperline(q_data_cap, q_data_cap->fmt->precision);
-       mxc_jpeg_sizeimage(q_data_cap);
+       jpeg_src_buf->fmt = mxc_jpeg_find_format(ctx, fourcc);
+       jpeg_src_buf->w = header.frame.width;
+       jpeg_src_buf->h = header.frame.height;
 
-       /*
-        * if the CAPTURE format was updated with new values, regardless of
-        * whether they match the values set by the client or not, signal
-        * a source change event
-        */
-       if (src_chg)
-               notify_src_chg(ctx);
+       mxc_jpeg_source_change(ctx, jpeg_src_buf);
 
        return 0;
 }