diff options
Diffstat (limited to 'drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c')
-rw-r--r-- | drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c | 132 |
1 files changed, 102 insertions, 30 deletions
diff --git a/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c b/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c index 1221b309a916..5c17bc58181e 100644 --- a/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c +++ b/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c @@ -535,7 +535,18 @@ static const unsigned char jpeg_sos_maximal[] = { }; static const unsigned char jpeg_image_red[] = { - 0xFC, 0x5F, 0xA2, 0xBF, 0xCA, 0x73, 0xFE, 0xFE, + 0xF9, 0xFE, 0x8A, 0xFC, 0x34, 0xFD, 0xC4, 0x28, + 0xA0, 0x02, 0x8A, 0x00, 0x28, 0xA0, 0x02, 0x8A, + 0x00, 0x28, 0xA0, 0x02, 0x8A, 0x00, 0x28, 0xA0, + 0x02, 0x8A, 0x00, 0x28, 0xA0, 0x02, 0x8A, 0x00, + 0x28, 0xA0, 0x02, 0x8A, 0x00, 0x28, 0xA0, 0x02, + 0x8A, 0x00, 0x28, 0xA0, 0x02, 0x8A, 0x00, 0x28, + 0xA0, 0x02, 0x8A, 0x00, 0x28, 0xA0, 0x02, 0x8A, + 0x00, 0x28, 0xA0, 0x02, 0x8A, 0x00, 0x28, 0xA0, + 0x02, 0x8A, 0x00, 0x28, 0xA0, 0x02, 0x8A, 0x00, + 0x28, 0xA0, 0x02, 0x8A, 0x00, 0x28, 0xA0, 0x02, + 0x8A, 0x00, 0x28, 0xA0, 0x0F, 0xFF, 0xD0, 0xF9, + 0xFE, 0x8A, 0xFC, 0x34, 0xFD, 0xC4, 0x28, 0xA0, 0x02, 0x8A, 0x00, 0x28, 0xA0, 0x02, 0x8A, 0x00, 0x28, 0xA0, 0x02, 0x8A, 0x00, 0x28, 0xA0, 0x02, 0x8A, 0x00, 0x28, 0xA0, 0x02, 0x8A, 0x00, 0x28, @@ -545,7 +556,7 @@ static const unsigned char jpeg_image_red[] = { 0x28, 0xA0, 0x02, 0x8A, 0x00, 0x28, 0xA0, 0x02, 0x8A, 0x00, 0x28, 0xA0, 0x02, 0x8A, 0x00, 0x28, 0xA0, 0x02, 0x8A, 0x00, 0x28, 0xA0, 0x02, 0x8A, - 0x00, 0x28, 0xA0, 0x02, 0x8A, 0x00 + 0x00, 0x28, 0xA0, 0x0F }; static const unsigned char jpeg_eoi[] = { @@ -752,6 +763,39 @@ static int mxc_get_free_slot(struct mxc_jpeg_slot_data *slot_data) return -1; } +static void mxc_jpeg_free_slot_data(struct mxc_jpeg_dev *jpeg) +{ + /* free descriptor for decoding/encoding phase */ + dma_free_coherent(jpeg->dev, sizeof(struct mxc_jpeg_desc), + jpeg->slot_data.desc, + jpeg->slot_data.desc_handle); + jpeg->slot_data.desc = NULL; + jpeg->slot_data.desc_handle = 0; + + /* free descriptor for encoder configuration phase / decoder DHT */ + dma_free_coherent(jpeg->dev, sizeof(struct mxc_jpeg_desc), + jpeg->slot_data.cfg_desc, + jpeg->slot_data.cfg_desc_handle); + jpeg->slot_data.cfg_desc_handle = 0; + jpeg->slot_data.cfg_desc = NULL; + + /* free configuration stream */ + dma_free_coherent(jpeg->dev, MXC_JPEG_MAX_CFG_STREAM, + jpeg->slot_data.cfg_stream_vaddr, + jpeg->slot_data.cfg_stream_handle); + jpeg->slot_data.cfg_stream_vaddr = NULL; + jpeg->slot_data.cfg_stream_handle = 0; + + dma_free_coherent(jpeg->dev, jpeg->slot_data.cfg_dec_size, + jpeg->slot_data.cfg_dec_vaddr, + jpeg->slot_data.cfg_dec_daddr); + jpeg->slot_data.cfg_dec_size = 0; + jpeg->slot_data.cfg_dec_vaddr = NULL; + jpeg->slot_data.cfg_dec_daddr = 0; + + jpeg->slot_data.used = false; +} + static bool mxc_jpeg_alloc_slot_data(struct mxc_jpeg_dev *jpeg) { struct mxc_jpeg_desc *desc; @@ -788,36 +832,25 @@ static bool mxc_jpeg_alloc_slot_data(struct mxc_jpeg_dev *jpeg) goto err; jpeg->slot_data.cfg_stream_vaddr = cfg_stm; + jpeg->slot_data.cfg_dec_size = MXC_JPEG_PATTERN_WIDTH * MXC_JPEG_PATTERN_HEIGHT * 2; + jpeg->slot_data.cfg_dec_vaddr = dma_alloc_coherent(jpeg->dev, + jpeg->slot_data.cfg_dec_size, + &jpeg->slot_data.cfg_dec_daddr, + GFP_ATOMIC); + if (!jpeg->slot_data.cfg_dec_vaddr) + goto err; + skip_alloc: jpeg->slot_data.used = true; return true; err: dev_err(jpeg->dev, "Could not allocate descriptors for slot %d", jpeg->slot_data.slot); + mxc_jpeg_free_slot_data(jpeg); return false; } -static void mxc_jpeg_free_slot_data(struct mxc_jpeg_dev *jpeg) -{ - /* free descriptor for decoding/encoding phase */ - dma_free_coherent(jpeg->dev, sizeof(struct mxc_jpeg_desc), - jpeg->slot_data.desc, - jpeg->slot_data.desc_handle); - - /* free descriptor for encoder configuration phase / decoder DHT */ - dma_free_coherent(jpeg->dev, sizeof(struct mxc_jpeg_desc), - jpeg->slot_data.cfg_desc, - jpeg->slot_data.cfg_desc_handle); - - /* free configuration stream */ - dma_free_coherent(jpeg->dev, MXC_JPEG_MAX_CFG_STREAM, - jpeg->slot_data.cfg_stream_vaddr, - jpeg->slot_data.cfg_stream_handle); - - jpeg->slot_data.used = false; -} - static void mxc_jpeg_check_and_set_last_buffer(struct mxc_jpeg_ctx *ctx, struct vb2_v4l2_buffer *src_buf, struct vb2_v4l2_buffer *dst_buf) @@ -877,6 +910,34 @@ static u32 mxc_jpeg_get_plane_size(struct mxc_jpeg_q_data *q_data, u32 plane_no) return size; } +static bool mxc_dec_is_ongoing(struct mxc_jpeg_ctx *ctx) +{ + struct mxc_jpeg_dev *jpeg = ctx->mxc_jpeg; + u32 curr_desc; + u32 slot_status; + + curr_desc = readl(jpeg->base_reg + MXC_SLOT_OFFSET(ctx->slot, SLOT_CUR_DESCPT_PTR)); + if (curr_desc == jpeg->slot_data.cfg_desc_handle) + return true; + + slot_status = readl(jpeg->base_reg + MXC_SLOT_OFFSET(ctx->slot, SLOT_STATUS)); + if (slot_status & SLOT_STATUS_ONGOING) + return true; + + /* + * The curr_desc register is updated when next_descpt_ptr is loaded, + * the ongoing bit of slot_status is set when the 32 bytes descriptor is loaded. + * So there will be a short time interval in between, which may cause fake false. + * Consider read register is quite slow compared with IP read 32byte from memory, + * read twice slot_status can avoid this situation. + */ + slot_status = readl(jpeg->base_reg + MXC_SLOT_OFFSET(ctx->slot, SLOT_STATUS)); + if (slot_status & SLOT_STATUS_ONGOING) + return true; + + return false; +} + static irqreturn_t mxc_jpeg_dec_irq(int irq, void *priv) { struct mxc_jpeg_dev *jpeg = priv; @@ -946,7 +1007,8 @@ static irqreturn_t mxc_jpeg_dec_irq(int irq, void *priv) mxc_jpeg_enc_mode_go(dev, reg, mxc_jpeg_is_extended_sequential(q_data->fmt)); goto job_unlock; } - if (jpeg->mode == MXC_JPEG_DECODE && jpeg_src_buf->dht_needed) { + if (jpeg->mode == MXC_JPEG_DECODE && jpeg_src_buf->dht_needed && + mxc_dec_is_ongoing(ctx)) { jpeg_src_buf->dht_needed = false; dev_dbg(dev, "Decoder DHT cfg finished. Start decoding...\n"); goto job_unlock; @@ -1209,14 +1271,14 @@ static void mxc_jpeg_config_dec_desc(struct vb2_buffer *out_buf, */ *cfg_size = mxc_jpeg_setup_cfg_stream(cfg_stream_vaddr, V4L2_PIX_FMT_YUYV, - MXC_JPEG_MIN_WIDTH, - MXC_JPEG_MIN_HEIGHT); + MXC_JPEG_PATTERN_WIDTH, + MXC_JPEG_PATTERN_HEIGHT); cfg_desc->next_descpt_ptr = desc_handle | MXC_NXT_DESCPT_EN; - cfg_desc->buf_base0 = vb2_dma_contig_plane_dma_addr(dst_buf, 0); + cfg_desc->buf_base0 = jpeg->slot_data.cfg_dec_daddr; cfg_desc->buf_base1 = 0; - cfg_desc->imgsize = MXC_JPEG_MIN_WIDTH << 16; - cfg_desc->imgsize |= MXC_JPEG_MIN_HEIGHT; - cfg_desc->line_pitch = MXC_JPEG_MIN_WIDTH * 2; + cfg_desc->imgsize = MXC_JPEG_PATTERN_WIDTH << 16; + cfg_desc->imgsize |= MXC_JPEG_PATTERN_HEIGHT; + cfg_desc->line_pitch = MXC_JPEG_PATTERN_WIDTH * 2; cfg_desc->stm_ctrl = STM_CTRL_IMAGE_FORMAT(MXC_JPEG_YUV422); cfg_desc->stm_ctrl |= STM_CTRL_BITBUF_PTR_CLR(1); cfg_desc->stm_bufbase = cfg_stream_handle; @@ -1918,9 +1980,19 @@ static void mxc_jpeg_buf_queue(struct vb2_buffer *vb) jpeg_src_buf = vb2_to_mxc_buf(vb); jpeg_src_buf->jpeg_parse_error = false; ret = mxc_jpeg_parse(ctx, vb); - if (ret) + if (ret) { jpeg_src_buf->jpeg_parse_error = true; + /* + * if the capture queue is not setup, the device_run() won't be scheduled, + * need to drop the error buffer, so that the decoding can continue + */ + if (!vb2_is_streaming(v4l2_m2m_get_dst_vq(ctx->fh.m2m_ctx))) { + v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_ERROR); + return; + } + } + end: v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf); } |