media: imx-jpeg: Handle source change in a function
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>
This commit is contained in:
parent
ef2feed1ec
commit
831f87424d
|
@ -315,6 +315,9 @@ struct mxc_jpeg_src_buf {
|
||||||
/* mxc-jpeg specific */
|
/* mxc-jpeg specific */
|
||||||
bool dht_needed;
|
bool dht_needed;
|
||||||
bool jpeg_parse_error;
|
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)
|
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_param(debug, int, 0644);
|
||||||
MODULE_PARM_DESC(debug, "Debug level (0-3)");
|
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)
|
static void _bswap16(u16 *a)
|
||||||
{
|
{
|
||||||
*a = ((*a & 0x00FF) << 8) | ((*a & 0xFF00) >> 8);
|
*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);
|
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)
|
static void mxc_jpeg_device_run(void *priv)
|
||||||
{
|
{
|
||||||
struct mxc_jpeg_ctx *ctx = priv;
|
struct mxc_jpeg_ctx *ctx = priv;
|
||||||
|
@ -1211,8 +1270,7 @@ static u32 mxc_jpeg_get_image_format(struct device *dev,
|
||||||
return fourcc;
|
return fourcc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mxc_jpeg_bytesperline(struct mxc_jpeg_q_data *q,
|
static void mxc_jpeg_bytesperline(struct mxc_jpeg_q_data *q, u32 precision)
|
||||||
u32 precision)
|
|
||||||
{
|
{
|
||||||
/* Bytes distance between the leftmost pixels in two adjacent lines */
|
/* Bytes distance between the leftmost pixels in two adjacent lines */
|
||||||
if (q->fmt->fourcc == V4L2_PIX_FMT_JPEG) {
|
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)
|
static int mxc_jpeg_parse(struct mxc_jpeg_ctx *ctx, struct vb2_buffer *vb)
|
||||||
{
|
{
|
||||||
struct device *dev = ctx->mxc_jpeg->dev;
|
struct device *dev = ctx->mxc_jpeg->dev;
|
||||||
struct mxc_jpeg_q_data *q_data_out, *q_data_cap;
|
struct mxc_jpeg_q_data *q_data_out;
|
||||||
enum v4l2_buf_type cap_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
|
|
||||||
bool src_chg = false;
|
|
||||||
u32 fourcc;
|
u32 fourcc;
|
||||||
struct v4l2_jpeg_header header;
|
struct v4l2_jpeg_header header;
|
||||||
struct mxc_jpeg_sof *psof = NULL;
|
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)
|
if (fourcc == 0)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
/*
|
jpeg_src_buf->fmt = mxc_jpeg_find_format(ctx, fourcc);
|
||||||
* set-up the capture queue with the pixelformat and resolution
|
jpeg_src_buf->w = header.frame.width;
|
||||||
* detected from the jpeg output stream
|
jpeg_src_buf->h = header.frame.height;
|
||||||
*/
|
|
||||||
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_source_change(ctx, jpeg_src_buf);
|
||||||
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);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue