From deb2b372bfe428eccbb9d3115be6031a07bf4c48 Mon Sep 17 00:00:00 2001 From: Mirela Rabulea <mirela.rabulea@nxp.com> Date: Mon, 11 Jun 2018 19:48:20 +0300 Subject: [PATCH] MLK-18493: mxc-jpeg: Use image settings from jpeg markers inside jpeg decoder Image information can be extracted from the JPEG SOH marker: image format (YUV444/YUV420/YUV422/Gray), width & height, precision. Use that information and apply it to the JPEG-DEC_WRP control registers. Also fixed the decoder for non-square images. Replace pr_*() and printk() calls with dev_*(). Currently working image formats: YUV444, YUV422, Gray Not working formats: YUV420 Signed-off-by: Mirela Rabulea <mirela.rabulea@nxp.com> Reviewed-by: Robert Chiras <robert.chiras@nxp.com>, Sandor Yu <sandor.yu@nxp.com> --- drivers/media/platform/imx8/mxc-jpeg-hw.c | 135 +++++++++-------- drivers/media/platform/imx8/mxc-jpeg-hw.h | 35 ++++- drivers/media/platform/imx8/mxc-jpeg.c | 168 +++++++++++++++++----- drivers/media/platform/imx8/mxc-jpeg.h | 22 ++- 4 files changed, 249 insertions(+), 111 deletions(-) diff --git a/drivers/media/platform/imx8/mxc-jpeg-hw.c b/drivers/media/platform/imx8/mxc-jpeg-hw.c index 32e3efdcc1b8b2..88ba0fe4dcaedf 100644 --- a/drivers/media/platform/imx8/mxc-jpeg-hw.c +++ b/drivers/media/platform/imx8/mxc-jpeg-hw.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2017 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright 2018 NXP */ /* * The code contained herein is licensed under the GNU General Public @@ -14,24 +14,16 @@ #include <media/videobuf2-core.h> #include "mxc-jpeg-hw.h" -enum mxc_jpeg_image_format { - MXC_JPEG_YUV420 = 0x0, - MXC_JPEG_YUV422 = 0x1, - MXC_JPEG_RGB = 0x2, - MXC_JPEG_YUV444 = 0x3, - MXC_JPEG_Y = 0x4, - MXC_JPEG_ARGB = 0x6, -}; - -void print_descriptor_info(struct mxc_jpeg_desc *desc) +void print_descriptor_info(struct device *dev, struct mxc_jpeg_desc *desc) { - printk(KERN_DEBUG " MXC JPEG NEXT PTR %x\n", desc->next_descpt_ptr); - printk(KERN_DEBUG " MXC JPEG BUF BASE0 %x\n", desc->buf_base0); - printk(KERN_DEBUG " MXC JPEG PITCH %d\n", desc->line_pitch); - printk(KERN_DEBUG " MXC JPEG BUF BASE %x\n", desc->stm_bufbase); - printk(KERN_DEBUG " MXC JPEG BUF SIZE %d\n", desc->stm_bufsize); - printk(KERN_DEBUG " MXC JPEG IMGSIZE %dx%d\n", desc->w, desc->h); - printk(KERN_DEBUG " MXC JPEG STM CTRL %x\n", desc->stm_ctrl); + dev_info(dev, " MXC JPEG NEXT PTR 0x%x\n", desc->next_descpt_ptr); + dev_info(dev, " MXC JPEG BUF BASE0 0x%x\n", desc->buf_base0); + dev_info(dev, " MXC JPEG PITCH %d\n", desc->line_pitch); + dev_info(dev, " MXC JPEG BUF BASE 0x%x\n", desc->stm_bufbase); + dev_info(dev, " MXC JPEG BUF SIZE %d\n", desc->stm_bufsize); + dev_info(dev, " MXC JPEG IMGSIZE %x (%d x %d)\n", desc->imgsize, + desc->imgsize >> 16, desc->imgsize & 0xFFFF); + dev_info(dev, " MXC JPEG STM CTRL 0x%x\n", desc->stm_ctrl); } void mxc_jpeg_enable_irq(void __iomem *reg, int slot) @@ -54,13 +46,13 @@ void mxc_jpeg_enc_config(void __iomem *reg, struct mxc_jpeg_desc *cfg_desc, { u32 regval, slot; - writel(0x1e0, reg + CAST_STATUS0); - writel(0x3ff, reg + CAST_STATUS1); - writel(0x4b, reg + CAST_STATUS2); + writel(0x1e0, reg + CAST_STATUS0); /* X = Image width, RO reg */ + writel(0x3ff, reg + CAST_STATUS1); /* Y = Image height , RO reg */ + writel(0x4b, reg + CAST_STATUS2); /* HMCU , RO reg */ slot = mxc_jpeg_get_slot(reg); mxc_jpeg_enable_irq(reg, slot); - writel((1 << (slot + 4)), reg); + writel(MXC_SLOT_EN(slot), reg + GLB_CTRL); cfg_desc->next_descpt_ptr = 0; cfg_desc->buf_base0 = tbl_handle; @@ -68,16 +60,15 @@ void mxc_jpeg_enc_config(void __iomem *reg, struct mxc_jpeg_desc *cfg_desc, cfg_desc->line_pitch = 0x300; cfg_desc->stm_bufbase = jpg_handle; cfg_desc->stm_bufsize = 0x100000; - cfg_desc->w = 0x0100; - cfg_desc->h = 0x0100; + cfg_desc->imgsize = 0x01000100; cfg_desc->stm_ctrl = MXC_CONFIG_MOD; //print_descriptor_info(cfg_desc); writel(cfg_handle, reg + MXC_SLOT_OFFSET(slot, SLOT_NXT_DESCPT_PTR)); - writel(cfg_handle | 1, reg + + writel(cfg_handle | MXC_NXT_DESCPT_EN, reg + MXC_SLOT_OFFSET(slot, SLOT_NXT_DESCPT_PTR)); - writel((1 << (slot + 4)) | MXC_ENDIAN_MD | MXC_ENABLE_DEC | - MXC_DEC_GO, reg); + writel(MXC_SLOT_EN(slot) | MXC_ENDIAN_MD | MXC_ENABLE_DEC | + MXC_DEC_GO, reg + GLB_CTRL); regval = readl(reg + STM_BUFBASE); regval = readl(reg + MXC_SLOT_OFFSET(slot, SLOT_BUF_PTR)); } @@ -86,8 +77,7 @@ int mxc_jpeg_enable(void __iomem *reg) { u32 regval; - regval = readl(reg); - writel(MXC_ENABLE_DEC, reg); + writel(MXC_ENABLE_DEC, reg + GLB_CTRL); regval = readl(reg); return regval; } @@ -96,57 +86,60 @@ void mxc_jpeg_go(void __iomem *reg) { u32 val; - val = readl(reg); - writel(MXC_ENDIAN_MD | MXC_DEC_GO | val, reg); - writel(0x4, reg + 0x134); + val = readl(reg + GLB_CTRL); + writel(MXC_ENDIAN_MD | MXC_DEC_GO | val, reg + GLB_CTRL); + writel(MXC_DEC_EXIT_IDLE_MODE, reg + CAST_STATUS13); //print_cast_decoder_info(reg); } -void print_cast_decoder_info(void __iomem *reg) +void print_cast_decoder_info(struct device *dev, void __iomem *reg) { int regval; regval = readl(reg + MXC_SLOT_OFFSET(0, SLOT_CUR_DESCPT_PTR)); - printk(KERN_DEBUG " MXC_JPEG: CUR DESCPT PTR: %x\n", regval); - regval = readl(reg + 0x100); - printk(KERN_DEBUG " MXC_JPEG: CAST_INFO 1: %x\n", regval); - regval = readl(reg + 0x104); - printk(KERN_DEBUG " MXC_JPEG: CAST_INFO 2: %x\n", regval); - regval = readl(reg + 0x108); - printk(KERN_DEBUG " MXC_JPEG: CAST_INFO 3: %x\n", regval); - regval = readl(reg + 0x10c); - printk(KERN_DEBUG " MXC_JPEG: CAST_INFO 4: %x\n", regval); - regval = readl(reg + 0x110); - printk(KERN_DEBUG " MXC_JPEG: CAST_INFO 5: %x\n", regval); - regval = readl(reg + 0x114); - printk(KERN_DEBUG " MXC_JPEG: CAST_INFO 6: %x\n", regval); - regval = readl(reg + 0x118); - printk(KERN_DEBUG " MXC_JPEG: CAST_INFO 7: %x\n", regval); - regval = readl(reg + 0x11c); - printk(KERN_DEBUG " MXC_JPEG: CAST_INFO 8: %x\n", regval); - regval = readl(reg + 0x120); - printk(KERN_DEBUG " MXC_JPEG: CAST_INFO 9: %x\n", regval); - regval = readl(reg + 0x124); - printk(KERN_DEBUG " MXC_JPEG: CAST_INFO 10: %x\n", regval); - regval = readl(reg + 0x128); - printk(KERN_DEBUG " MXC_JPEG: CAST_INFO 11: %x\n", regval); - regval = readl(reg + 0x12c); - printk(KERN_DEBUG " MXC_JPEG: CAST_INFO 12: %x\n", regval); - regval = readl(reg + 0x130); - printk(KERN_DEBUG " MXC_JPEG: CAST_INFO 13: %x\n", regval); - regval = readl(reg + 0x134); - printk(KERN_DEBUG " MXC_JPEG: CAST_INFO 14: %x\n", regval); + dev_info(dev, " MXC_JPEG: CUR DESCPT PTR: %x\n", regval); + regval = readl(reg + CAST_STATUS0); + dev_info(dev, " MXC_JPEG: CAST_INFO 0: %x\n", regval); + regval = readl(reg + CAST_STATUS1); + dev_info(dev, " MXC_JPEG: CAST_INFO 1: %x\n", regval); + regval = readl(reg + CAST_STATUS2); + dev_info(dev, " MXC_JPEG: CAST_INFO 2: %x\n", regval); + regval = readl(reg + CAST_STATUS3); + dev_info(dev, " MXC_JPEG: CAST_INFO 3: %x\n", regval); + regval = readl(reg + CAST_STATUS4); + dev_info(dev, " MXC_JPEG: CAST_INFO 4: %x\n", regval); + regval = readl(reg + CAST_STATUS5); + dev_info(dev, " MXC_JPEG: CAST_INFO 5: %x\n", regval); + regval = readl(reg + CAST_STATUS6); + dev_info(dev, " MXC_JPEG: CAST_INFO 6: %x\n", regval); + regval = readl(reg + CAST_STATUS7); + dev_info(dev, " MXC_JPEG: CAST_INFO 7: %x\n", regval); + regval = readl(reg + CAST_STATUS8); + dev_info(dev, " MXC_JPEG: CAST_INFO 8: %x\n", regval); + regval = readl(reg + CAST_STATUS9); + dev_info(dev, " MXC_JPEG: CAST_INFO 9: %x\n", regval); + regval = readl(reg + CAST_STATUS10); + dev_info(dev, " MXC_JPEG: CAST_INFO 10: %x\n", regval); + regval = readl(reg + CAST_STATUS11); + dev_info(dev, " MXC_JPEG: CAST_INFO 11: %x\n", regval); + regval = readl(reg + CAST_STATUS12); + dev_info(dev, " MXC_JPEG: CAST_INFO 12: %x\n", regval); + regval = readl(reg + CAST_STATUS13); + dev_info(dev, " MXC_JPEG: CAST_INFO 13: %x\n", regval); } int mxc_jpeg_get_slot(void __iomem *reg) { int slot_val; int i = 0; - int tmp = MXC_SLOT_EN; + int tmp = MXC_SLOT_EN(0); + /* currently enabled slots */ slot_val = readl(reg) & 0xF0; + for (; tmp != tmp << 4; tmp = tmp << 1) { if ((slot_val & tmp) == 0) + /* first free slot */ return i; ++i; } @@ -157,13 +150,14 @@ void mxc_jpeg_enable_slot(void __iomem *reg, int slot) { u32 regval; - regval = readl(reg); - writel((1 << (slot + 4)) | regval, reg); + regval = readl(reg + GLB_CTRL); + writel(MXC_SLOT_EN(slot) | regval, reg + GLB_CTRL); } void mxc_jpeg_set_addrs(struct mxc_jpeg_desc *desc, u32 buf_base0, u32 bufbase) { desc->buf_base0 = buf_base0; + desc->buf_base1 = 0x0; desc->stm_bufbase = bufbase; } @@ -188,13 +182,18 @@ int mxc_jpeg_set_params(struct mxc_jpeg_desc *desc, u32 bufsize, return 0; } +void mxc_jpeg_set_bufsize(struct mxc_jpeg_desc *desc, u32 bufsize) +{ + desc->stm_bufsize = bufsize; +} + void mxc_jpeg_set_res(struct mxc_jpeg_desc *desc, u16 w, u16 h) { - desc->w = w; - desc->h = h; + desc->imgsize = w << 16 | h; } void mxc_jpeg_set_desc(u32 desc, void __iomem *reg, int slot) { - writel(desc | 1, reg + MXC_SLOT_OFFSET(slot, SLOT_NXT_DESCPT_PTR)); + writel(desc | MXC_NXT_DESCPT_EN, + reg + MXC_SLOT_OFFSET(slot, SLOT_NXT_DESCPT_PTR)); } diff --git a/drivers/media/platform/imx8/mxc-jpeg-hw.h b/drivers/media/platform/imx8/mxc-jpeg-hw.h index 8c2d77f9a26a87..613721f9259ecd 100644 --- a/drivers/media/platform/imx8/mxc-jpeg-hw.h +++ b/drivers/media/platform/imx8/mxc-jpeg-hw.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2017 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright 2018 NXP */ /* * The code contained herein is licensed under the GNU General Public @@ -11,6 +11,9 @@ */ #ifndef _MXC_JPEG_HW_H #define _MXC_JPEG_HW_H + +/* JPEG-Decoder Wrapper Register Map */ +#define GLB_CTRL 0x0 #define COM_STATUS 0x4 #define OUT_BUFFER0 0x14 #define OUT_BUFFER1 0x18 @@ -19,6 +22,8 @@ #define STM_BUFSIZE 0x24 #define IMG_SIZE 0x28 #define STM_CTRL 0x2C + +/* JPEG-Decoder Register Map */ #define CAST_STATUS0 0x100 #define CAST_STATUS1 0x104 #define CAST_STATUS2 0x108 @@ -33,6 +38,8 @@ #define CAST_STATUS11 0x12c #define CAST_STATUS12 0x130 #define CAST_STATUS13 0x134 + +/* JPEG-Decoder Wrapper Slot Registers 0..3 */ #define SLOT_BASE 0x10000 #define SLOT_STATUS 0x0 #define SLOT_IRQ_EN 0x4 @@ -45,11 +52,30 @@ #define MXC_RESET_DEC (0x1 << 1) #define MXC_DEC_GO (0x1 << 2) #define MXC_ENDIAN_MD (0x1 << 3) -#define MXC_SLOT_EN (0x1 << 4) +#define MXC_SLOT_EN(slot) (0x1 << (slot + 4)) #define MXC_CONFIG_MOD (0x1 << 9) +#define MXC_FRMDONE 0x8 +#define MXC_NXT_DESCPT_EN 0x1 +#define MXC_DEC_EXIT_IDLE_MODE 0x4 + +/* JPEG-Decoder Wrapper - STM_CTRL Register Fields */ +#define MXC_PIXEL_PRECISION(precision) ((precision)/8 << 2) +enum mxc_jpeg_image_format { + MXC_JPEG_YUV420 = 0x0, /* 2 Plannar, Y=1st plane UV=2nd plane */ + MXC_JPEG_YUV422 = 0x1, /* 1 Plannar, YUYV sequence */ + MXC_JPEG_RGB = 0x2, /* RGBRGB packed format */ + MXC_JPEG_YUV444 = 0x3, /* 1 Plannar, YUVYUV sequence */ + MXC_JPEG_GRAY = 0x4, /* Y8 or Y12 or Single Component */ + MXC_JPEG_RESERVED = 0x5, + MXC_JPEG_ARGB = 0x6, +}; +#define MXC_IMAGE_FORMAT(jpeg_img_fmt) ((jpeg_img_fmt) << 3) +#define MXC_BITBUF_PTR_CLR(clr) ((clr) << 7) +#define MXC_AUTO_START(go) ((go) << 8) + #include "mxc-jpeg.h" -void print_descriptor_info(struct mxc_jpeg_desc *desc); +void print_descriptor_info(struct device *dev, struct mxc_jpeg_desc *desc); void mxc_jpeg_reset(void __iomem *reg); int mxc_jpeg_enable(void __iomem *reg); void mxc_jpeg_enc_config(void __iomem *reg, struct mxc_jpeg_desc *cfg_desc, @@ -65,7 +91,8 @@ int mxc_jpeg_set_output(void __iomem *reg, u16 out_pitch, u32 out_buf, void mxc_jpeg_set_addrs(struct mxc_jpeg_desc *desc, u32 src_addr, u32 dst_addr); int mxc_jpeg_set_params(struct mxc_jpeg_desc *desc, u32 bufsize, u16 out_pitch, u32 format); +void mxc_jpeg_set_bufsize(struct mxc_jpeg_desc *desc, u32 bufsize); void mxc_jpeg_set_res(struct mxc_jpeg_desc *desc, u16 w, u16 h); void mxc_jpeg_set_desc(u32 desc, void __iomem *reg, int slot); -void print_cast_decoder_info(void __iomem *reg); +void print_cast_decoder_info(struct device *dev, void __iomem *reg); #endif diff --git a/drivers/media/platform/imx8/mxc-jpeg.c b/drivers/media/platform/imx8/mxc-jpeg.c index 1b4f53b32ee6f5..832c9ce490f31a 100644 --- a/drivers/media/platform/imx8/mxc-jpeg.c +++ b/drivers/media/platform/imx8/mxc-jpeg.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2017 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright 2018 NXP */ /* * The code contained herein is licensed under the GNU General Public @@ -250,10 +250,13 @@ static irqreturn_t mxc_jpeg_dec_irq(int irq, void *priv) void *testaddri; void *testaddro; - dec_ret = readl(reg + 0x10000); - writel(dec_ret, reg + 0x10000); - if (!(dec_ret & 0x8)) + + /* hardcoded slot 0 */ + dec_ret = readl(reg + MXC_SLOT_OFFSET(0, SLOT_STATUS)); + writel(dec_ret, reg + MXC_SLOT_OFFSET(0, SLOT_STATUS)); /* w1c */ + if (!(dec_ret & MXC_FRMDONE)) return IRQ_HANDLED; + ctx = v4l2_m2m_get_curr_priv(jpeg->m2m_dev); dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx); src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx); @@ -308,9 +311,9 @@ static void mxc_jpeg_device_run(void *priv) { struct mxc_jpeg_ctx *ctx = priv; struct mxc_jpeg_dev *jpeg = ctx->mxc_jpeg; + struct device *dev = jpeg->dev; struct vb2_buffer *src_buf, *dst_buf; unsigned long flags; - struct mxc_jpeg_q_data *cap_q_data = &ctx->cap_q; struct mxc_jpeg_src_buf *jpeg_src_buf; int slot; void *testaddri; @@ -337,13 +340,13 @@ static void mxc_jpeg_device_run(void *priv) } else { mxc_jpeg_addrs(desc, dst_buf, src_buf, 0); slot = mxc_jpeg_get_slot(jpeg->base_reg); + if (slot == -EINVAL) + dev_err(dev, "No more slots available!\n"); mxc_jpeg_enable_slot(jpeg->base_reg, slot); - mxc_jpeg_set_params(desc, - mxc_jpeg_align(vb2_plane_size(src_buf, 0), - 1024), - cap_q_data->bytesperline[0], - cap_q_data->fmt->fourcc); + mxc_jpeg_set_bufsize(desc, + mxc_jpeg_align(vb2_plane_size(src_buf, 0), 1024)); mxc_jpeg_enable_irq(jpeg->base_reg, slot); + print_descriptor_info(dev, desc); mxc_jpeg_set_desc(dma_handle, jpeg->base_reg, slot); mxc_jpeg_go(jpeg->base_reg); } @@ -351,10 +354,16 @@ static void mxc_jpeg_device_run(void *priv) } static int mxc_jpeg_job_ready(void *priv) { + struct mxc_jpeg_ctx *ctx = priv; + + dev_warn(ctx->mxc_jpeg->dev, "mxc_jpeg_job_ready unimplemented\n"); return 1; } static void mxc_jpeg_job_abort(void *priv) { + struct mxc_jpeg_ctx *ctx = priv; + + dev_warn(ctx->mxc_jpeg->dev, "mxc_jpeg_job_abort unimplemented\n"); } static struct mxc_jpeg_q_data *mxc_jpeg_get_q_data(struct mxc_jpeg_ctx *ctx, @@ -415,25 +424,108 @@ static u8 get_byte(struct mxc_jpeg_stream *stream) stream->loc++; return ret; } -static u16 get_word_be(struct mxc_jpeg_stream *stream, u32 *word) + +static void _bswap16(u16 *a) { - u16 ret1; - u16 ret2; + *a = ((*a & 0x00FF) << 8) | ((*a & 0xFF00) >> 8); +} - ret1 = get_byte(stream); - ret2 = get_byte(stream); - if (ret1 != -1 && ret2 != -1) { - *word = ((ret1 << 8) | ret2); - return 0; +static u8 get_sof(struct device *dev, + struct mxc_jpeg_stream *stream, + struct mxc_jpeg_sof *sof) +{ + int i; + + if (stream->loc + sizeof(struct mxc_jpeg_sof) >= stream->end) + return -1; + memcpy(sof, &stream->addr[stream->loc], sizeof(struct mxc_jpeg_sof)); + _bswap16(&sof->length); + _bswap16(&sof->height); + _bswap16(&sof->width); + dev_info(dev, "JPEG SOF: length=%d, precision=%d\n", + sof->length, sof->precision); + dev_info(dev, "JPEG SOF: height=%d, width=%d\n", + sof->height, sof->width); + for (i = 0; i < sof->components_no; i++) { + dev_info(dev, "JPEG SOF: comp_id=%d, H=0x%x, V=0x%x\n", + sof->comp[i].id, sof->comp[i].v, sof->comp[i].h); } - return -1; + return 0; } -static int mxc_jpeg_parse(struct mxc_jpeg_desc *desc, u8 *src_addr, u32 size) + +static enum mxc_jpeg_image_format mxc_jpeg_get_image_format( + struct device *dev, + const struct mxc_jpeg_sof *sof) +{ + if (sof->components_no == 1) { + dev_info(dev, "IMAGE_FORMAT is: MXC_JPEG_GRAY\n"); + return MXC_JPEG_GRAY; + } + if (sof->components_no == 3) { + if (sof->comp[0].h == 2 && sof->comp[0].v == 2 && + sof->comp[1].h == 1 && sof->comp[1].v == 1 && + sof->comp[2].h == 1 && sof->comp[2].v == 1){ + dev_info(dev, "IMAGE_FORMAT is: MXC_JPEG_YUV420\n"); + return MXC_JPEG_YUV420; + } + if (sof->comp[0].h == 2 && sof->comp[0].v == 1 && + sof->comp[1].h == 1 && sof->comp[1].v == 1 && + sof->comp[2].h == 1 && sof->comp[2].v == 1){ + dev_info(dev, "IMAGE_FORMAT is: MXC_JPEG_YUV422\n"); + return MXC_JPEG_YUV422; + } + if (sof->comp[0].h == 1 && sof->comp[0].v == 1 && + sof->comp[1].h == 1 && sof->comp[1].v == 1 && + sof->comp[2].h == 1 && sof->comp[2].v == 1){ + dev_info(dev, "IMAGE_FORMAT is: MXC_JPEG_YUV444\n"); + return MXC_JPEG_YUV444; + } + } + dev_info(dev, "IMAGE_FORMAT is: MXC_JPEG_RESERVED\n"); + return MXC_JPEG_RESERVED; +} + +static u32 mxc_jpeg_get_line_pitch( + struct device *dev, + const struct mxc_jpeg_sof *sof, + enum mxc_jpeg_image_format img_fmt) +{ + u32 line_pitch; + + switch (img_fmt) { + case MXC_JPEG_YUV420: + line_pitch = sof->width * (sof->precision/8) * 1; + break; + case MXC_JPEG_YUV422: + line_pitch = sof->width * (sof->precision/8) * 2; + break; + case MXC_JPEG_RGB: + line_pitch = sof->width * (sof->precision/8) * 3; + break; + case MXC_JPEG_YUV444: + line_pitch = sof->width * (sof->precision/8) * 3; + break; + case MXC_JPEG_GRAY: + line_pitch = sof->width * (sof->precision/8) * 1; + break; + default: + line_pitch = sof->width * (sof->precision/8) * 3; + break; + } + dev_info(dev, "line_pitch = %d\n", line_pitch); + return line_pitch; +} + +static int mxc_jpeg_parse(struct device *dev, + struct mxc_jpeg_desc *desc, u8 *src_addr, u32 size) { struct mxc_jpeg_stream stream; bool notfound = true; - int height, width, byte, length, word; + struct mxc_jpeg_sof sof; + int byte; + enum mxc_jpeg_image_format img_fmt; + memset(&sof, 0, sizeof(struct mxc_jpeg_sof)); stream.addr = src_addr; stream.end = size; stream.loc = 0; @@ -450,20 +542,10 @@ static int mxc_jpeg_parse(struct mxc_jpeg_desc *desc, u8 *src_addr, u32 size) return false; if (byte == 0) continue; - length = 0; switch (byte) { case SOF2: case SOF0: - if (get_word_be(&stream, &word)) - break; - length = (long)word - 2; - if (!length) - return false; - if (get_byte(&stream) == -1) - break; - if (get_word_be(&stream, &height)) - break; - if (get_word_be(&stream, &width)) + if (get_sof(dev, &stream, &sof) == -1) break; notfound = false; break; @@ -471,12 +553,25 @@ static int mxc_jpeg_parse(struct mxc_jpeg_desc *desc, u8 *src_addr, u32 size) notfound = true; } } - if (width % 8 != 0 || height % 8 != 0) + if (sof.width % 8 != 0 || sof.height % 8 != 0) { + dev_info(dev, "JPEG width or height not multiple of 8: %dx%d\n", + sof.width, sof.height); return -EINVAL; - desc->w = width; - desc->h = height; + } + if (sof.width > 0x2000 || sof.height > 0x2000) { + dev_info(dev, "JPEG width or height should be <= 8192: %dx%d\n", + sof.width, sof.height); + return -EINVAL; + } + desc->imgsize = sof.width << 16 | sof.height; + dev_info(dev, "JPEG imgsize = 0x%x (%dx%d)\n", desc->imgsize, + sof.width, sof.height); + img_fmt = mxc_jpeg_get_image_format(dev, &sof); + desc->stm_ctrl |= MXC_IMAGE_FORMAT(img_fmt); + desc->line_pitch = mxc_jpeg_get_line_pitch(dev, &sof, img_fmt); return 0; } + static void mxc_jpeg_buf_queue(struct vb2_buffer *vb) { int ret; @@ -492,7 +587,8 @@ static void mxc_jpeg_buf_queue(struct vb2_buffer *vb) &jpeg_src_buf->handle, 0); if (ctx->mode != MXC_JPEG_DECODE) goto end; - ret = mxc_jpeg_parse(jpeg_src_buf->desc, (u8 *)vb2_plane_vaddr(vb, 0), + ret = mxc_jpeg_parse(ctx->mxc_jpeg->dev, + jpeg_src_buf->desc, (u8 *)vb2_plane_vaddr(vb, 0), vb2_get_plane_payload(vb, 0)); if (ret) { v4l2_err(&ctx->mxc_jpeg->v4l2_dev, diff --git a/drivers/media/platform/imx8/mxc-jpeg.h b/drivers/media/platform/imx8/mxc-jpeg.h index 830ddc6a7a72df..8028f3041e06e5 100644 --- a/drivers/media/platform/imx8/mxc-jpeg.h +++ b/drivers/media/platform/imx8/mxc-jpeg.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2017 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright 2018 NXP */ /* * The code contained herein is licensed under the GNU General Public @@ -68,8 +68,7 @@ struct mxc_jpeg_desc { u32 line_pitch; u32 stm_bufbase; u32 stm_bufsize; - u16 w; - u16 h; + u32 imgsize; u32 stm_ctrl; } __packed; @@ -115,4 +114,21 @@ struct mxc_jpeg_dev { struct mxc_jpeg_desc *cfg_desc; dma_addr_t cfg_handle; }; + +/* JPEG Start Of Frame marker fields*/ +struct mxc_jpeg_sof_comp { + u8 id; /*component id*/ + u8 v :4; /* vertical sampling*/ + u8 h :4; /* horizontal sampling*/ + u8 quantization_table_no; +} __packed; + +struct mxc_jpeg_sof { + u16 length; + u8 precision; + u16 height, width; + u8 components_no; + struct mxc_jpeg_sof_comp comp[3]; +} __packed; + #endif -- GitLab