On 12/13/19 9:33 AM, Hans Verkuil wrote: > Hi Philipp, > > Two small comments: I've removed those two unused variables myself, so no need to do anything. Unless they actually shouldn't have been unused and something else is going on; in that case please post a follow-up patch. Regards, Hans > > On 12/12/19 3:02 PM, Philipp Zabel wrote: >> This patch adds JPEG encoding support for CODA960, handling the JPEG >> hardware directly. A separate JPEG encoder video device is created due >> to the separate hardware unit and different supported pixel formats. >> While the hardware can not change subsampling on the fly, it can encode >> 4:2:2 subsampled images into JPEGs of the same subsampling. >> >> There are two additional tracepoints added to the coda driver that can >> be used together with the v4l2:v4l2_qbuf and v4l2:v4l2_dqbuf tracepoints >> to to follow video frames through the mem2mem device when encoding or >> decoding with the CODA960 JPEG codec: >> coda:coda_jpeg_run >> coda:coda_jpeg_done >> >> Signed-off-by: Philipp Zabel <p.zabel@xxxxxxxxxxxxxx> >> Tested-by: Richard Leitner <richard.leitner@xxxxxxxxxxx> >> --- >> Changes since v1 [1]: >> - fixed platform_get_irq.cocci warnings >> - fixed encoder Huffman table generation, replaced broken pointer >> arithmetic with a structure definition >> - moved encoder Huffman table generation to start_streaming >> - dropped coda9_jpeg_load_qmat_tab return value >> >> [1] https://patchwork.linuxtv.org/patch/60107/ >> --- >> drivers/media/platform/coda/coda-common.c | 39 +- >> drivers/media/platform/coda/coda-jpeg.c | 708 ++++++++++++++++++++++ >> drivers/media/platform/coda/coda.h | 3 + >> drivers/media/platform/coda/trace.h | 10 + >> 4 files changed, 758 insertions(+), 2 deletions(-) >> >> diff --git a/drivers/media/platform/coda/coda-common.c b/drivers/media/platform/coda/coda-common.c >> index 556f8e0f52d7..0b5abae11012 100644 >> --- a/drivers/media/platform/coda/coda-common.c >> +++ b/drivers/media/platform/coda/coda-common.c >> @@ -155,6 +155,7 @@ static const struct coda_codec coda7_codecs[] = { >> static const struct coda_codec coda9_codecs[] = { >> CODA_CODEC(CODA9_MODE_ENCODE_H264, V4L2_PIX_FMT_YUV420, V4L2_PIX_FMT_H264, 1920, 1088), >> CODA_CODEC(CODA9_MODE_ENCODE_MP4, V4L2_PIX_FMT_YUV420, V4L2_PIX_FMT_MPEG4, 1920, 1088), >> + CODA_CODEC(CODA9_MODE_ENCODE_MJPG, V4L2_PIX_FMT_YUV420, V4L2_PIX_FMT_JPEG, 8192, 8192), >> CODA_CODEC(CODA9_MODE_DECODE_H264, V4L2_PIX_FMT_H264, V4L2_PIX_FMT_YUV420, 1920, 1088), >> CODA_CODEC(CODA9_MODE_DECODE_MP2, V4L2_PIX_FMT_MPEG2, V4L2_PIX_FMT_YUV420, 1920, 1088), >> CODA_CODEC(CODA9_MODE_DECODE_MP4, V4L2_PIX_FMT_MPEG4, V4L2_PIX_FMT_YUV420, 1920, 1088), >> @@ -235,6 +236,22 @@ static const struct coda_video_device coda_bit_jpeg_decoder = { >> }, >> }; >> >> +static const struct coda_video_device coda9_jpeg_encoder = { >> + .name = "coda-jpeg-encoder", >> + .type = CODA_INST_ENCODER, >> + .ops = &coda9_jpeg_encode_ops, >> + .direct = true, >> + .src_formats = { >> + V4L2_PIX_FMT_NV12, >> + V4L2_PIX_FMT_YUV420, >> + V4L2_PIX_FMT_YVU420, >> + V4L2_PIX_FMT_YUV422P, >> + }, >> + .dst_formats = { >> + V4L2_PIX_FMT_JPEG, >> + }, >> +}; >> + >> static const struct coda_video_device *codadx6_video_devices[] = { >> &coda_bit_encoder, >> }; >> @@ -252,6 +269,7 @@ static const struct coda_video_device *coda7_video_devices[] = { >> }; >> >> static const struct coda_video_device *coda9_video_devices[] = { >> + &coda9_jpeg_encoder, >> &coda_bit_encoder, >> &coda_bit_decoder, >> }; >> @@ -721,7 +739,8 @@ static int coda_s_fmt(struct coda_ctx *ctx, struct v4l2_format *f, >> ctx->tiled_map_type = GDI_TILED_FRAME_MB_RASTER_MAP; >> break; >> case V4L2_PIX_FMT_NV12: >> - if (!disable_tiling && ctx->dev->devtype->product == CODA_960) { >> + if (!disable_tiling && ctx->use_bit && >> + ctx->dev->devtype->product == CODA_960) { >> ctx->tiled_map_type = GDI_TILED_FRAME_MB_RASTER_MAP; >> break; >> } >> @@ -1787,7 +1806,7 @@ static void coda_buf_queue(struct vb2_buffer *vb) >> coda_queue_source_change_event(ctx); >> } >> } else { >> - if (ctx->inst_type == CODA_INST_ENCODER && >> + if ((ctx->inst_type == CODA_INST_ENCODER || !ctx->use_bit) && >> vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) >> vbuf->sequence = ctx->qsequence++; >> v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf); >> @@ -2996,6 +3015,22 @@ static int coda_probe(struct platform_device *pdev) >> return ret; >> } >> >> + /* JPEG IRQ */ >> + if (dev->devtype->product == CODA_960) { >> + irq = platform_get_irq_byname(pdev, "jpeg"); >> + if (irq < 0) >> + return irq; >> + >> + ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, >> + coda9_jpeg_irq_handler, >> + IRQF_ONESHOT, CODA_NAME " jpeg", >> + dev); >> + if (ret < 0) { >> + dev_err(&pdev->dev, "failed to request jpeg irq\n"); >> + return ret; >> + } >> + } >> + >> dev->rstc = devm_reset_control_get_optional_exclusive(&pdev->dev, >> NULL); >> if (IS_ERR(dev->rstc)) { >> diff --git a/drivers/media/platform/coda/coda-jpeg.c b/drivers/media/platform/coda/coda-jpeg.c >> index 27e20aee1a8c..983fac80a5a5 100644 >> --- a/drivers/media/platform/coda/coda-jpeg.c >> +++ b/drivers/media/platform/coda/coda-jpeg.c >> @@ -5,15 +5,40 @@ >> * Copyright (C) 2014 Philipp Zabel, Pengutronix >> */ >> >> +#include <asm/unaligned.h> >> +#include <linux/irqreturn.h> >> #include <linux/kernel.h> >> +#include <linux/ktime.h> >> +#include <linux/slab.h> >> #include <linux/swab.h> >> +#include <linux/videodev2.h> >> + >> +#include <media/v4l2-common.h> >> +#include <media/v4l2-fh.h> >> +#include <media/v4l2-mem2mem.h> >> +#include <media/videobuf2-core.h> >> +#include <media/videobuf2-dma-contig.h> >> >> #include "coda.h" >> #include "trace.h" >> >> #define SOI_MARKER 0xffd8 >> +#define DRI_MARKER 0xffdd >> +#define DQT_MARKER 0xffdb >> +#define DHT_MARKER 0xffc4 >> +#define SOF_MARKER 0xffc0 >> #define EOI_MARKER 0xffd9 >> >> +enum { >> + CODA9_JPEG_FORMAT_420, >> + CODA9_JPEG_FORMAT_422, >> + CODA9_JPEG_FORMAT_224, >> + CODA9_JPEG_FORMAT_444, >> + CODA9_JPEG_FORMAT_400, >> +}; >> + >> +#define CODA9_JPEG_ENC_HUFF_DATA_SIZE (256 + 256 + 16 + 16) >> + >> /* >> * Typical Huffman tables for 8-bit precision luminance and >> * chrominance from JPEG ITU-T.81 (ISO/IEC 10918-1) Annex K.3 >> @@ -120,6 +145,38 @@ static unsigned char chroma_q[64] = { >> 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, >> }; >> >> +static const unsigned char width_align[] = { >> + [CODA9_JPEG_FORMAT_420] = 16, >> + [CODA9_JPEG_FORMAT_422] = 16, >> + [CODA9_JPEG_FORMAT_224] = 8, >> + [CODA9_JPEG_FORMAT_444] = 8, >> + [CODA9_JPEG_FORMAT_400] = 8, >> +}; >> + >> +static const unsigned char height_align[] = { >> + [CODA9_JPEG_FORMAT_420] = 16, >> + [CODA9_JPEG_FORMAT_422] = 8, >> + [CODA9_JPEG_FORMAT_224] = 16, >> + [CODA9_JPEG_FORMAT_444] = 8, >> + [CODA9_JPEG_FORMAT_400] = 8, >> +}; >> + >> +static int coda9_jpeg_chroma_format(u32 pixfmt) >> +{ >> + switch (pixfmt) { >> + case V4L2_PIX_FMT_YUV420: >> + case V4L2_PIX_FMT_NV12: >> + return CODA9_JPEG_FORMAT_420; >> + case V4L2_PIX_FMT_YUV422P: >> + return CODA9_JPEG_FORMAT_422; >> + case V4L2_PIX_FMT_YUV444: >> + return CODA9_JPEG_FORMAT_444; >> + case V4L2_PIX_FMT_GREY: >> + return CODA9_JPEG_FORMAT_400; >> + } >> + return -EINVAL; >> +} >> + >> struct coda_memcpy_desc { >> int offset; >> const void *src; >> @@ -190,6 +247,380 @@ bool coda_jpeg_check_buffer(struct coda_ctx *ctx, struct vb2_buffer *vb) >> return false; >> } >> >> +static const int bus_req_num[] = { >> + [CODA9_JPEG_FORMAT_420] = 2, >> + [CODA9_JPEG_FORMAT_422] = 3, >> + [CODA9_JPEG_FORMAT_224] = 3, >> + [CODA9_JPEG_FORMAT_444] = 4, >> + [CODA9_JPEG_FORMAT_400] = 4, >> +}; >> + >> +#define MCU_INFO(mcu_block_num, comp_num, comp0_info, comp1_info, comp2_info) \ >> + (((mcu_block_num) << CODA9_JPEG_MCU_BLOCK_NUM_OFFSET) | \ >> + ((comp_num) << CODA9_JPEG_COMP_NUM_OFFSET) | \ >> + ((comp0_info) << CODA9_JPEG_COMP0_INFO_OFFSET) | \ >> + ((comp1_info) << CODA9_JPEG_COMP1_INFO_OFFSET) | \ >> + ((comp2_info) << CODA9_JPEG_COMP2_INFO_OFFSET)) >> + >> +static const u32 mcu_info[] = { >> + [CODA9_JPEG_FORMAT_420] = MCU_INFO(6, 3, 10, 5, 5), >> + [CODA9_JPEG_FORMAT_422] = MCU_INFO(4, 3, 9, 5, 5), >> + [CODA9_JPEG_FORMAT_224] = MCU_INFO(4, 3, 6, 5, 5), >> + [CODA9_JPEG_FORMAT_444] = MCU_INFO(3, 3, 5, 5, 5), >> + [CODA9_JPEG_FORMAT_400] = MCU_INFO(1, 1, 5, 0, 0), >> +}; >> + >> +/* >> + * Convert Huffman table specifcations to tables of codes and code lengths. >> + * For reference, see JPEG ITU-T.81 (ISO/IEC 10918-1) [1] >> + * >> + * [1] https://www.w3.org/Graphics/JPEG/itu-t81.pdf >> + */ >> +static int coda9_jpeg_gen_enc_huff_tab(struct coda_ctx *ctx, int tab_num, >> + int *ehufsi, int *ehufco) >> +{ >> + int i, j, k, lastk, si, code, maxsymbol; >> + const u8 *bits, *huffval; >> + struct { >> + int size[256]; >> + int code[256]; >> + } *huff; >> + static const unsigned char *huff_tabs[4] = { >> + luma_dc, luma_ac, chroma_dc, chroma_ac, >> + }; >> + int ret = -EINVAL; >> + >> + huff = kzalloc(sizeof(*huff), GFP_KERNEL); >> + if (!huff) >> + return -ENOMEM; >> + >> + bits = huff_tabs[tab_num]; >> + huffval = huff_tabs[tab_num] + 16; >> + >> + maxsymbol = tab_num & 1 ? 256 : 16; >> + >> + /* Figure C.1 - Generation of table of Huffman code sizes */ >> + k = 0; >> + for (i = 1; i <= 16; i++) { >> + j = bits[i - 1]; >> + if (k + j > maxsymbol) >> + goto out; >> + while (j--) >> + huff->size[k++] = i; >> + } >> + lastk = k; >> + >> + /* Figure C.2 - Generation of table of Huffman codes */ >> + k = 0; >> + code = 0; >> + si = huff->size[0]; >> + while (k < lastk) { >> + while (huff->size[k] == si) { >> + huff->code[k++] = code; >> + code++; >> + } >> + if (code >= (1 << si)) >> + goto out; >> + code <<= 1; >> + si++; >> + } >> + >> + /* Figure C.3 - Ordering procedure for encoding procedure code tables */ >> + for (k = 0; k < lastk; k++) { >> + i = huffval[k]; >> + if (i >= maxsymbol || ehufsi[i]) >> + goto out; >> + ehufco[i] = huff->code[k]; >> + ehufsi[i] = huff->size[k]; >> + } >> + >> + ret = 0; >> +out: >> + kfree(huff); >> + return ret; >> +} >> + >> +#define DC_TABLE_INDEX0 0 >> +#define AC_TABLE_INDEX0 1 >> +#define DC_TABLE_INDEX1 2 >> +#define AC_TABLE_INDEX1 3 >> + >> +static int coda9_jpeg_load_huff_tab(struct coda_ctx *ctx) >> +{ >> + struct { >> + int size[4][256]; >> + int code[4][256]; >> + } *huff; >> + u32 *huff_data; >> + int i, j, k; >> + int ret; >> + >> + huff = kzalloc(sizeof(*huff), GFP_KERNEL); >> + if (!huff) >> + return -ENOMEM; >> + >> + /* Generate all four (luma/chroma DC/AC) code/size lookup tables */ >> + for (i = 0; i < 4; i++) { >> + ret = coda9_jpeg_gen_enc_huff_tab(ctx, i, huff->size[i], >> + huff->code[i]); >> + if (ret) >> + goto out; >> + } >> + >> + if (!ctx->params.jpeg_huff_data) { >> + ctx->params.jpeg_huff_data = >> + kzalloc(sizeof(u32) * CODA9_JPEG_ENC_HUFF_DATA_SIZE, >> + GFP_KERNEL); >> + if (!ctx->params.jpeg_huff_data) { >> + ret = -ENOMEM; >> + goto out; >> + } >> + } >> + huff_data = ctx->params.jpeg_huff_data; >> + >> + k = 0; > > k is set to 0 here, but never used elsewhere. Can it be removed? > >> + for (j = 0; j < 4; j++) { >> + /* Store Huffman lookup tables in AC0, AC1, DC0, DC1 order */ >> + int t = (j == 0) ? AC_TABLE_INDEX0 : >> + (j == 1) ? AC_TABLE_INDEX1 : >> + (j == 2) ? DC_TABLE_INDEX0 : >> + DC_TABLE_INDEX1; >> + /* DC tables only have 16 entries */ >> + int len = (j < 2) ? 256 : 16; >> + >> + for (i = 0; i < len; i++) { >> + if (huff->size[t][i] == 0 && huff->code[t][i] == 0) >> + *(huff_data++) = 0; >> + else >> + *(huff_data++) = >> + ((huff->size[t][i] - 1) << 16) | >> + huff->code[t][i]; >> + } >> + } >> + >> + ret = 0; >> +out: >> + kfree(huff); >> + return ret; >> +} >> + >> +static void coda9_jpeg_write_huff_tab(struct coda_ctx *ctx) >> +{ >> + struct coda_dev *dev = ctx->dev; >> + u32 *huff_data = ctx->params.jpeg_huff_data; >> + int i; >> + >> + /* Write Huffman size/code lookup tables in AC0, AC1, DC0, DC1 order */ >> + coda_write(dev, 0x3, CODA9_REG_JPEG_HUFF_CTRL); >> + for (i = 0; i < CODA9_JPEG_ENC_HUFF_DATA_SIZE; i++) >> + coda_write(dev, *(huff_data++), CODA9_REG_JPEG_HUFF_DATA); >> + coda_write(dev, 0x0, CODA9_REG_JPEG_HUFF_CTRL); >> +} >> + >> +static inline void coda9_jpeg_write_qmat_quotients(struct coda_dev *dev, >> + u8 *qmat, int index) >> +{ >> + int i; >> + >> + coda_write(dev, index | 0x3, CODA9_REG_JPEG_QMAT_CTRL); >> + for (i = 0; i < 64; i++) >> + coda_write(dev, 0x80000 / qmat[i], CODA9_REG_JPEG_QMAT_DATA); >> + coda_write(dev, index, CODA9_REG_JPEG_QMAT_CTRL); >> +} >> + >> +static void coda9_jpeg_load_qmat_tab(struct coda_ctx *ctx) >> +{ >> + struct coda_dev *dev = ctx->dev; >> + u8 *luma_tab; >> + u8 *chroma_tab; >> + >> + luma_tab = ctx->params.jpeg_qmat_tab[0]; >> + if (!luma_tab) >> + luma_tab = luma_q; >> + >> + chroma_tab = ctx->params.jpeg_qmat_tab[1]; >> + if (!chroma_tab) >> + chroma_tab = chroma_q; >> + >> + coda9_jpeg_write_qmat_quotients(dev, luma_tab, 0x00); >> + coda9_jpeg_write_qmat_quotients(dev, chroma_tab, 0x40); >> + coda9_jpeg_write_qmat_quotients(dev, chroma_tab, 0x80); >> +} >> + >> +struct coda_jpeg_stream { >> + u8 *curr; >> + u8 *end; >> +}; >> + >> +static inline int coda_jpeg_put_byte(u8 byte, struct coda_jpeg_stream *stream) >> +{ >> + if (stream->curr >= stream->end) >> + return -EINVAL; >> + >> + *stream->curr++ = byte; >> + >> + return 0; >> +} >> + >> +static inline int coda_jpeg_put_word(u16 word, struct coda_jpeg_stream *stream) >> +{ >> + if (stream->curr + sizeof(__be16) > stream->end) >> + return -EINVAL; >> + >> + put_unaligned_be16(word, stream->curr); >> + stream->curr += sizeof(__be16); >> + >> + return 0; >> +} >> + >> +static int coda_jpeg_put_table(u16 marker, u8 index, const u8 *table, >> + size_t len, struct coda_jpeg_stream *stream) >> +{ >> + int i, ret; >> + >> + ret = coda_jpeg_put_word(marker, stream); >> + if (ret < 0) >> + return ret; >> + ret = coda_jpeg_put_word(3 + len, stream); >> + if (ret < 0) >> + return ret; >> + ret = coda_jpeg_put_byte(index, stream); >> + for (i = 0; i < len && ret == 0; i++) >> + ret = coda_jpeg_put_byte(table[i], stream); >> + >> + return ret; >> +} >> + >> +static int coda_jpeg_define_quantization_table(struct coda_ctx *ctx, u8 index, >> + struct coda_jpeg_stream *stream) >> +{ >> + return coda_jpeg_put_table(DQT_MARKER, index, >> + ctx->params.jpeg_qmat_tab[index], 64, >> + stream); >> +} >> + >> +static int coda_jpeg_define_huffman_table(u8 index, const u8 *table, size_t len, >> + struct coda_jpeg_stream *stream) >> +{ >> + return coda_jpeg_put_table(DHT_MARKER, index, table, len, stream); >> +} >> + >> +static int coda9_jpeg_encode_header(struct coda_ctx *ctx, int len, u8 *buf) >> +{ >> + struct coda_jpeg_stream stream = { buf, buf + len }; >> + struct coda_q_data *q_data_src; >> + int chroma_format, comp_num; >> + int i, ret, pad; >> + >> + q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); >> + chroma_format = coda9_jpeg_chroma_format(q_data_src->fourcc); >> + if (chroma_format < 0) >> + return 0; >> + >> + /* Start Of Image */ >> + ret = coda_jpeg_put_word(SOI_MARKER, &stream); >> + if (ret < 0) >> + return ret; >> + >> + /* Define Restart Interval */ >> + if (ctx->params.jpeg_restart_interval) { >> + ret = coda_jpeg_put_word(DRI_MARKER, &stream); >> + if (ret < 0) >> + return ret; >> + ret = coda_jpeg_put_word(4, &stream); >> + if (ret < 0) >> + return ret; >> + ret = coda_jpeg_put_word(ctx->params.jpeg_restart_interval, >> + &stream); >> + if (ret < 0) >> + return ret; >> + } >> + >> + /* Define Quantization Tables */ >> + ret = coda_jpeg_define_quantization_table(ctx, 0x00, &stream); >> + if (ret < 0) >> + return ret; >> + if (chroma_format != CODA9_JPEG_FORMAT_400) { >> + ret = coda_jpeg_define_quantization_table(ctx, 0x01, &stream); >> + if (ret < 0) >> + return ret; >> + } >> + >> + /* Define Huffman Tables */ >> + ret = coda_jpeg_define_huffman_table(0x00, luma_dc, 16 + 12, &stream); >> + if (ret < 0) >> + return ret; >> + ret = coda_jpeg_define_huffman_table(0x10, luma_ac, 16 + 162, &stream); >> + if (ret < 0) >> + return ret; >> + if (chroma_format != CODA9_JPEG_FORMAT_400) { >> + ret = coda_jpeg_define_huffman_table(0x01, chroma_dc, 16 + 12, >> + &stream); >> + if (ret < 0) >> + return ret; >> + ret = coda_jpeg_define_huffman_table(0x11, chroma_ac, 16 + 162, >> + &stream); >> + if (ret < 0) >> + return ret; >> + } >> + >> + /* Start Of Frame */ >> + ret = coda_jpeg_put_word(SOF_MARKER, &stream); >> + if (ret < 0) >> + return ret; >> + comp_num = (chroma_format == CODA9_JPEG_FORMAT_400) ? 1 : 3; >> + ret = coda_jpeg_put_word(8 + comp_num * 3, &stream); >> + if (ret < 0) >> + return ret; >> + ret = coda_jpeg_put_byte(0x08, &stream); >> + if (ret < 0) >> + return ret; >> + ret = coda_jpeg_put_word(q_data_src->height, &stream); >> + if (ret < 0) >> + return ret; >> + ret = coda_jpeg_put_word(q_data_src->width, &stream); >> + if (ret < 0) >> + return ret; >> + ret = coda_jpeg_put_byte(comp_num, &stream); >> + if (ret < 0) >> + return ret; >> + for (i = 0; i < comp_num; i++) { >> + static unsigned char subsampling[5][3] = { >> + [CODA9_JPEG_FORMAT_420] = { 0x22, 0x11, 0x11 }, >> + [CODA9_JPEG_FORMAT_422] = { 0x21, 0x11, 0x11 }, >> + [CODA9_JPEG_FORMAT_224] = { 0x12, 0x11, 0x11 }, >> + [CODA9_JPEG_FORMAT_444] = { 0x11, 0x11, 0x11 }, >> + [CODA9_JPEG_FORMAT_400] = { 0x11 }, >> + }; >> + >> + /* Component identifier, matches SOS */ >> + ret = coda_jpeg_put_byte(i + 1, &stream); >> + if (ret < 0) >> + return ret; >> + ret = coda_jpeg_put_byte(subsampling[chroma_format][i], >> + &stream); >> + if (ret < 0) >> + return ret; >> + /* Chroma table index */ >> + ret = coda_jpeg_put_byte((i == 0) ? 0 : 1, &stream); >> + if (ret < 0) >> + return ret; >> + } >> + >> + /* Pad to multiple of 8 bytes */ >> + pad = (stream.curr - buf) % 8; >> + if (pad) { >> + pad = 8 - pad; >> + while (pad--) { >> + ret = coda_jpeg_put_byte(0x00, &stream); >> + if (ret < 0) >> + return ret; >> + } >> + } >> + >> + return stream.curr - buf; >> +} >> + >> /* >> * Scale quantization table using nonlinear scaling factor >> * u8 qtab[64], scale [50,190] >> @@ -239,3 +670,280 @@ void coda_set_jpeg_compression_quality(struct coda_ctx *ctx, int quality) >> coda_scale_quant_table(ctx->params.jpeg_qmat_tab[1], scale); >> } >> } >> + >> +/* >> + * Encoder context operations >> + */ >> + >> +static int coda9_jpeg_start_encoding(struct coda_ctx *ctx) >> +{ >> + struct coda_dev *dev = ctx->dev; >> + int ret; >> + >> + ret = coda9_jpeg_load_huff_tab(ctx); >> + if (ret < 0) { >> + v4l2_err(&dev->v4l2_dev, "error loading Huffman tables\n"); >> + return ret; >> + } >> + if (!ctx->params.jpeg_qmat_tab[0]) >> + ctx->params.jpeg_qmat_tab[0] = kmalloc(64, GFP_KERNEL); >> + if (!ctx->params.jpeg_qmat_tab[1]) >> + ctx->params.jpeg_qmat_tab[1] = kmalloc(64, GFP_KERNEL); >> + coda_set_jpeg_compression_quality(ctx, ctx->params.jpeg_quality); >> + >> + return 0; >> +} >> + >> +static int coda9_jpeg_prepare_encode(struct coda_ctx *ctx) >> +{ >> + struct coda_q_data *q_data_src, *q_data_dst; > > q_data_dst is unused. > >> + struct vb2_v4l2_buffer *src_buf, *dst_buf; >> + struct coda_dev *dev = ctx->dev; >> + u32 start_addr, end_addr; >> + u16 aligned_width, aligned_height; >> + bool chroma_interleave; >> + int chroma_format; >> + int header_len; >> + int ret; >> + ktime_t timeout; >> + > > <snip> > > Regards, > > Hans >