Commit 831f8742 authored by Ming Qian's avatar Ming Qian Committed by Mauro Carvalho Chehab
Browse files

media: imx-jpeg: Handle source change in a function



Refine code to support dynamic resolution change

Signed-off-by: default avatarMing Qian <ming.qian@nxp.com>
Reviewed-by: default avatarMirela Rabulea <mirela.rabulea@nxp.com>
Signed-off-by: default avatarHans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@kernel.org>
parent ef2feed1
Loading
Loading
Loading
Loading
+65 −49
Original line number Diff line number Diff line
@@ -315,6 +315,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)
@@ -327,6 +330,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);
@@ -922,6 +928,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;
@@ -1211,8 +1270,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) {
@@ -1263,9 +1321,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;
@@ -1333,51 +1389,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);
	jpeg_src_buf->fmt = mxc_jpeg_find_format(ctx, fourcc);
	jpeg_src_buf->w = header.frame.width;
	jpeg_src_buf->h = header.frame.height;

	/* setup bytesperline/sizeimage for capture queue */
	mxc_jpeg_bytesperline(q_data_cap, q_data_cap->fmt->precision);
	mxc_jpeg_sizeimage(q_data_cap);

	/*
	 * 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;
}