diff options
Diffstat (limited to 'drivers/staging/media/hantro')
-rw-r--r-- | drivers/staging/media/hantro/Kconfig | 16 | ||||
-rw-r--r-- | drivers/staging/media/hantro/Makefile | 3 | ||||
-rw-r--r-- | drivers/staging/media/hantro/hantro.h | 2 | ||||
-rw-r--r-- | drivers/staging/media/hantro/hantro_drv.c | 15 | ||||
-rw-r--r-- | drivers/staging/media/hantro/hantro_h1_jpeg_enc.c | 19 | ||||
-rw-r--r-- | drivers/staging/media/hantro/hantro_hw.h | 1 | ||||
-rw-r--r-- | drivers/staging/media/hantro/hantro_jpeg.c | 76 | ||||
-rw-r--r-- | drivers/staging/media/hantro/hantro_jpeg.h | 2 | ||||
-rw-r--r-- | drivers/staging/media/hantro/hantro_v4l2.c | 2 | ||||
-rw-r--r-- | drivers/staging/media/hantro/imx8m_vpu_hw.c | 220 | ||||
-rw-r--r-- | drivers/staging/media/hantro/rk3399_vpu_hw_jpeg_enc.c | 24 |
11 files changed, 341 insertions, 39 deletions
diff --git a/drivers/staging/media/hantro/Kconfig b/drivers/staging/media/hantro/Kconfig index de77fe6554e7..99aed9a5b0b9 100644 --- a/drivers/staging/media/hantro/Kconfig +++ b/drivers/staging/media/hantro/Kconfig @@ -1,19 +1,27 @@ # SPDX-License-Identifier: GPL-2.0 config VIDEO_HANTRO tristate "Hantro VPU driver" - depends on ARCH_ROCKCHIP || COMPILE_TEST + depends on ARCH_MXC || ARCH_ROCKCHIP || COMPILE_TEST depends on VIDEO_DEV && VIDEO_V4L2 && MEDIA_CONTROLLER depends on MEDIA_CONTROLLER_REQUEST_API select VIDEOBUF2_DMA_CONTIG select VIDEOBUF2_VMALLOC select V4L2_MEM2MEM_DEV help - Support for the Hantro IP based Video Processing Unit present on - Rockchip SoC, which accelerates video and image encoding and - decoding. + Support for the Hantro IP based Video Processing Units present on + Rockchip and NXP i.MX8M SoCs, which accelerate video and image + encoding and decoding. To compile this driver as a module, choose M here: the module will be called hantro-vpu. +config VIDEO_HANTRO_IMX8M + bool "Hantro VPU i.MX8M support" + depends on VIDEO_HANTRO + depends on ARCH_MXC || COMPILE_TEST + default y + help + Enable support for i.MX8M SoCs. + config VIDEO_HANTRO_ROCKCHIP bool "Hantro VPU Rockchip support" depends on VIDEO_HANTRO diff --git a/drivers/staging/media/hantro/Makefile b/drivers/staging/media/hantro/Makefile index 496b30c3c396..68c29a9c4946 100644 --- a/drivers/staging/media/hantro/Makefile +++ b/drivers/staging/media/hantro/Makefile @@ -16,6 +16,9 @@ hantro-vpu-y += \ hantro_mpeg2.o \ hantro_vp8.o +hantro-vpu-$(CONFIG_VIDEO_HANTRO_IMX8M) += \ + imx8m_vpu_hw.o + hantro-vpu-$(CONFIG_VIDEO_HANTRO_ROCKCHIP) += \ rk3288_vpu_hw.o \ rk3399_vpu_hw.o diff --git a/drivers/staging/media/hantro/hantro.h b/drivers/staging/media/hantro/hantro.h index b0faa43b3f79..327ddef45345 100644 --- a/drivers/staging/media/hantro/hantro.h +++ b/drivers/staging/media/hantro/hantro.h @@ -423,7 +423,7 @@ hantro_get_dst_buf(struct hantro_ctx *ctx) static inline bool hantro_needs_postproc(struct hantro_ctx *ctx, const struct hantro_fmt *fmt) { - return fmt->fourcc != V4L2_PIX_FMT_NV12; + return !hantro_is_encoder_ctx(ctx) && fmt->fourcc != V4L2_PIX_FMT_NV12; } static inline dma_addr_t diff --git a/drivers/staging/media/hantro/hantro_drv.c b/drivers/staging/media/hantro/hantro_drv.c index c98835326135..ace13973e2d0 100644 --- a/drivers/staging/media/hantro/hantro_drv.c +++ b/drivers/staging/media/hantro/hantro_drv.c @@ -362,6 +362,16 @@ static const struct hantro_ctrl controls[] = { .max = V4L2_MPEG_VIDEO_H264_START_CODE_ANNEX_B, }, }, { + .codec = HANTRO_H264_DECODER, + .cfg = { + .id = V4L2_CID_MPEG_VIDEO_H264_PROFILE, + .min = V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE, + .max = V4L2_MPEG_VIDEO_H264_PROFILE_HIGH, + .menu_skip_mask = + BIT(V4L2_MPEG_VIDEO_H264_PROFILE_EXTENDED), + .def = V4L2_MPEG_VIDEO_H264_PROFILE_MAIN, + } + }, { }, }; @@ -489,6 +499,9 @@ static const struct of_device_id of_hantro_match[] = { { .compatible = "rockchip,rk3328-vpu", .data = &rk3328_vpu_variant, }, { .compatible = "rockchip,rk3288-vpu", .data = &rk3288_vpu_variant, }, #endif +#ifdef CONFIG_VIDEO_HANTRO_IMX8M + { .compatible = "nxp,imx8mq-vpu", .data = &imx8mq_vpu_variant, }, +#endif { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, of_hantro_match); @@ -664,7 +677,7 @@ static int hantro_add_func(struct hantro_dev *vpu, unsigned int funcid) video_set_drvdata(vfd, vpu); - ret = video_register_device(vfd, VFL_TYPE_GRABBER, -1); + ret = video_register_device(vfd, VFL_TYPE_VIDEO, -1); if (ret) { v4l2_err(&vpu->v4l2_dev, "Failed to register video device\n"); return ret; diff --git a/drivers/staging/media/hantro/hantro_h1_jpeg_enc.c b/drivers/staging/media/hantro/hantro_h1_jpeg_enc.c index 0d8afc3e5d71..b22418436823 100644 --- a/drivers/staging/media/hantro/hantro_h1_jpeg_enc.c +++ b/drivers/staging/media/hantro/hantro_h1_jpeg_enc.c @@ -67,12 +67,23 @@ hantro_h1_jpeg_enc_set_qtable(struct hantro_dev *vpu, unsigned char *chroma_qtable) { u32 reg, i; + __be32 *luma_qtable_p; + __be32 *chroma_qtable_p; + luma_qtable_p = (__be32 *)luma_qtable; + chroma_qtable_p = (__be32 *)chroma_qtable; + + /* + * Quantization table registers must be written in contiguous blocks. + * DO NOT collapse the below two "for" loops into one. + */ for (i = 0; i < H1_JPEG_QUANT_TABLE_COUNT; i++) { - reg = get_unaligned_be32(&luma_qtable[i]); + reg = get_unaligned_be32(&luma_qtable_p[i]); vepu_write_relaxed(vpu, reg, H1_REG_JPEG_LUMA_QUAT(i)); + } - reg = get_unaligned_be32(&chroma_qtable[i]); + for (i = 0; i < H1_JPEG_QUANT_TABLE_COUNT; i++) { + reg = get_unaligned_be32(&chroma_qtable_p[i]); vepu_write_relaxed(vpu, reg, H1_REG_JPEG_CHROMA_QUAT(i)); } } @@ -103,8 +114,8 @@ void hantro_h1_jpeg_enc_run(struct hantro_ctx *ctx) hantro_h1_set_src_img_ctrl(vpu, ctx); hantro_h1_jpeg_enc_set_buffers(vpu, ctx, &src_buf->vb2_buf); hantro_h1_jpeg_enc_set_qtable(vpu, - hantro_jpeg_get_qtable(&jpeg_ctx, 0), - hantro_jpeg_get_qtable(&jpeg_ctx, 1)); + hantro_jpeg_get_qtable(0), + hantro_jpeg_get_qtable(1)); reg = H1_REG_AXI_CTRL_OUTPUT_SWAP16 | H1_REG_AXI_CTRL_INPUT_SWAP16 diff --git a/drivers/staging/media/hantro/hantro_hw.h b/drivers/staging/media/hantro/hantro_hw.h index 2398d4c1f207..7dfc9bad7297 100644 --- a/drivers/staging/media/hantro/hantro_hw.h +++ b/drivers/staging/media/hantro/hantro_hw.h @@ -151,6 +151,7 @@ enum hantro_enc_fmt { extern const struct hantro_variant rk3399_vpu_variant; extern const struct hantro_variant rk3328_vpu_variant; extern const struct hantro_variant rk3288_vpu_variant; +extern const struct hantro_variant imx8mq_vpu_variant; extern const struct hantro_postproc_regs hantro_g1_postproc_regs; diff --git a/drivers/staging/media/hantro/hantro_jpeg.c b/drivers/staging/media/hantro/hantro_jpeg.c index 125eb41f2ede..36c140fc6a36 100644 --- a/drivers/staging/media/hantro/hantro_jpeg.c +++ b/drivers/staging/media/hantro/hantro_jpeg.c @@ -23,19 +23,21 @@ #define HUFF_CHROMA_AC_OFF 409 /* Default tables from JPEG ITU-T.81 - * (ISO/IEC 10918-1) Annex K.3, I + * (ISO/IEC 10918-1) Annex K, tables K.1 and K.2 */ static const unsigned char luma_q_table[] = { - 0x10, 0x0b, 0x0a, 0x10, 0x7c, 0x8c, 0x97, 0xa1, - 0x0c, 0x0c, 0x0e, 0x13, 0x7e, 0x9e, 0xa0, 0x9b, - 0x0e, 0x0d, 0x10, 0x18, 0x8c, 0x9d, 0xa9, 0x9c, - 0x0e, 0x11, 0x16, 0x1d, 0x97, 0xbb, 0xb4, 0xa2, - 0x12, 0x16, 0x25, 0x38, 0xa8, 0x6d, 0x67, 0xb1, - 0x18, 0x23, 0x37, 0x40, 0xb5, 0x68, 0x71, 0xc0, + 0x10, 0x0b, 0x0a, 0x10, 0x18, 0x28, 0x33, 0x3d, + 0x0c, 0x0c, 0x0e, 0x13, 0x1a, 0x3a, 0x3c, 0x37, + 0x0e, 0x0d, 0x10, 0x18, 0x28, 0x39, 0x45, 0x38, + 0x0e, 0x11, 0x16, 0x1d, 0x33, 0x57, 0x50, 0x3e, + 0x12, 0x16, 0x25, 0x38, 0x44, 0x6d, 0x67, 0x4d, + 0x18, 0x23, 0x37, 0x40, 0x51, 0x68, 0x71, 0x5c, 0x31, 0x40, 0x4e, 0x57, 0x67, 0x79, 0x78, 0x65, - 0x48, 0x5c, 0x5f, 0x62, 0x70, 0x64, 0x67, 0xc7, + 0x48, 0x5c, 0x5f, 0x62, 0x70, 0x64, 0x67, 0x63 }; +static unsigned char luma_q_table_reordered[ARRAY_SIZE(luma_q_table)]; + static const unsigned char chroma_q_table[] = { 0x11, 0x12, 0x18, 0x2f, 0x63, 0x63, 0x63, 0x63, 0x12, 0x15, 0x1a, 0x42, 0x63, 0x63, 0x63, 0x63, @@ -47,6 +49,30 @@ static const unsigned char chroma_q_table[] = { 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63 }; +static unsigned char chroma_q_table_reordered[ARRAY_SIZE(chroma_q_table)]; + +static const unsigned char zigzag[64] = { + 0, 1, 8, 16, 9, 2, 3, 10, + 17, 24, 32, 25, 18, 11, 4, 5, + 12, 19, 26, 33, 40, 48, 41, 34, + 27, 20, 13, 6, 7, 14, 21, 28, + 35, 42, 49, 56, 57, 50, 43, 36, + 29, 22, 15, 23, 30, 37, 44, 51, + 58, 59, 52, 45, 38, 31, 39, 46, + 53, 60, 61, 54, 47, 55, 62, 63 +}; + +static const u32 hw_reorder[64] = { + 0, 8, 16, 24, 1, 9, 17, 25, + 32, 40, 48, 56, 33, 41, 49, 57, + 2, 10, 18, 26, 3, 11, 19, 27, + 34, 42, 50, 58, 35, 43, 51, 59, + 4, 12, 20, 28, 5, 13, 21, 29, + 36, 44, 52, 60, 37, 45, 53, 61, + 6, 14, 22, 30, 7, 15, 23, 31, + 38, 46, 54, 62, 39, 47, 55, 63 +}; + /* Huffman tables are shared with CODA */ static const unsigned char luma_dc_table[] = { 0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, @@ -225,20 +251,29 @@ static const unsigned char hantro_jpeg_header[JPEG_HEADER_SIZE] = { 0x11, 0x03, 0x11, 0x00, 0x3f, 0x00, }; +static unsigned char jpeg_scale_qp(const unsigned char qp, int scale) +{ + unsigned int temp; + + temp = DIV_ROUND_CLOSEST((unsigned int)qp * scale, 100); + if (temp <= 0) + temp = 1; + if (temp > 255) + temp = 255; + + return (unsigned char)temp; +} + static void -jpeg_scale_quant_table(unsigned char *q_tab, +jpeg_scale_quant_table(unsigned char *file_q_tab, + unsigned char *reordered_q_tab, const unsigned char *tab, int scale) { - unsigned int temp; int i; for (i = 0; i < 64; i++) { - temp = DIV_ROUND_CLOSEST((unsigned int)tab[i] * scale, 100); - if (temp <= 0) - temp = 1; - if (temp > 255) - temp = 255; - q_tab[i] = (unsigned char)temp; + file_q_tab[i] = jpeg_scale_qp(tab[zigzag[i]], scale); + reordered_q_tab[i] = jpeg_scale_qp(tab[hw_reorder[i]], scale); } } @@ -256,17 +291,18 @@ static void jpeg_set_quality(unsigned char *buffer, int quality) scale = 200 - 2 * quality; jpeg_scale_quant_table(buffer + LUMA_QUANT_OFF, + luma_q_table_reordered, luma_q_table, scale); jpeg_scale_quant_table(buffer + CHROMA_QUANT_OFF, + chroma_q_table_reordered, chroma_q_table, scale); } -unsigned char * -hantro_jpeg_get_qtable(struct hantro_jpeg_ctx *ctx, int index) +unsigned char *hantro_jpeg_get_qtable(int index) { if (index == 0) - return ctx->buffer + LUMA_QUANT_OFF; - return ctx->buffer + CHROMA_QUANT_OFF; + return luma_q_table_reordered; + return chroma_q_table_reordered; } void hantro_jpeg_header_assemble(struct hantro_jpeg_ctx *ctx) diff --git a/drivers/staging/media/hantro/hantro_jpeg.h b/drivers/staging/media/hantro/hantro_jpeg.h index 9e8397c71388..9474a00277f8 100644 --- a/drivers/staging/media/hantro/hantro_jpeg.h +++ b/drivers/staging/media/hantro/hantro_jpeg.h @@ -9,5 +9,5 @@ struct hantro_jpeg_ctx { unsigned char *buffer; }; -unsigned char *hantro_jpeg_get_qtable(struct hantro_jpeg_ctx *ctx, int index); +unsigned char *hantro_jpeg_get_qtable(int index); void hantro_jpeg_header_assemble(struct hantro_jpeg_ctx *ctx); diff --git a/drivers/staging/media/hantro/hantro_v4l2.c b/drivers/staging/media/hantro/hantro_v4l2.c index 0198bcda26b7..f4ae2cee0f18 100644 --- a/drivers/staging/media/hantro/hantro_v4l2.c +++ b/drivers/staging/media/hantro/hantro_v4l2.c @@ -295,7 +295,7 @@ static int vidioc_try_fmt(struct file *file, void *priv, struct v4l2_format *f, * +---------------------------+ */ if (ctx->vpu_src_fmt->fourcc == V4L2_PIX_FMT_H264_SLICE && - !hantro_needs_postproc(ctx, ctx->vpu_dst_fmt)) + !hantro_needs_postproc(ctx, fmt)) pix_mp->plane_fmt[0].sizeimage += 64 * MB_WIDTH(pix_mp->width) * MB_WIDTH(pix_mp->height) + 32; diff --git a/drivers/staging/media/hantro/imx8m_vpu_hw.c b/drivers/staging/media/hantro/imx8m_vpu_hw.c new file mode 100644 index 000000000000..cb2420c5526e --- /dev/null +++ b/drivers/staging/media/hantro/imx8m_vpu_hw.c @@ -0,0 +1,220 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Hantro VPU codec driver + * + * Copyright (C) 2019 Pengutronix, Philipp Zabel <kernel@pengutronix.de> + */ + +#include <linux/clk.h> +#include <linux/delay.h> + +#include "hantro.h" +#include "hantro_jpeg.h" +#include "hantro_g1_regs.h" + +#define CTRL_SOFT_RESET 0x00 +#define RESET_G1 BIT(1) +#define RESET_G2 BIT(0) + +#define CTRL_CLOCK_ENABLE 0x04 +#define CLOCK_G1 BIT(1) +#define CLOCK_G2 BIT(0) + +#define CTRL_G1_DEC_FUSE 0x08 +#define CTRL_G1_PP_FUSE 0x0c +#define CTRL_G2_DEC_FUSE 0x10 + +static void imx8m_soft_reset(struct hantro_dev *vpu, u32 reset_bits) +{ + u32 val; + + /* Assert */ + val = readl(vpu->ctrl_base + CTRL_SOFT_RESET); + val &= ~reset_bits; + writel(val, vpu->ctrl_base + CTRL_SOFT_RESET); + + udelay(2); + + /* Release */ + val = readl(vpu->ctrl_base + CTRL_SOFT_RESET); + val |= reset_bits; + writel(val, vpu->ctrl_base + CTRL_SOFT_RESET); +} + +static void imx8m_clk_enable(struct hantro_dev *vpu, u32 clock_bits) +{ + u32 val; + + val = readl(vpu->ctrl_base + CTRL_CLOCK_ENABLE); + val |= clock_bits; + writel(val, vpu->ctrl_base + CTRL_CLOCK_ENABLE); +} + +static int imx8mq_runtime_resume(struct hantro_dev *vpu) +{ + int ret; + + ret = clk_bulk_prepare_enable(vpu->variant->num_clocks, vpu->clocks); + if (ret) { + dev_err(vpu->dev, "Failed to enable clocks\n"); + return ret; + } + + imx8m_soft_reset(vpu, RESET_G1 | RESET_G2); + imx8m_clk_enable(vpu, CLOCK_G1 | CLOCK_G2); + + /* Set values of the fuse registers */ + writel(0xffffffff, vpu->ctrl_base + CTRL_G1_DEC_FUSE); + writel(0xffffffff, vpu->ctrl_base + CTRL_G1_PP_FUSE); + writel(0xffffffff, vpu->ctrl_base + CTRL_G2_DEC_FUSE); + + clk_bulk_disable_unprepare(vpu->variant->num_clocks, vpu->clocks); + + return 0; +} + +/* + * Supported formats. + */ + +static const struct hantro_fmt imx8m_vpu_postproc_fmts[] = { + { + .fourcc = V4L2_PIX_FMT_YUYV, + .codec_mode = HANTRO_MODE_NONE, + }, +}; + +static const struct hantro_fmt imx8m_vpu_dec_fmts[] = { + { + .fourcc = V4L2_PIX_FMT_NV12, + .codec_mode = HANTRO_MODE_NONE, + }, + { + .fourcc = V4L2_PIX_FMT_MPEG2_SLICE, + .codec_mode = HANTRO_MODE_MPEG2_DEC, + .max_depth = 2, + .frmsize = { + .min_width = 48, + .max_width = 1920, + .step_width = MB_DIM, + .min_height = 48, + .max_height = 1088, + .step_height = MB_DIM, + }, + }, + { + .fourcc = V4L2_PIX_FMT_VP8_FRAME, + .codec_mode = HANTRO_MODE_VP8_DEC, + .max_depth = 2, + .frmsize = { + .min_width = 48, + .max_width = 3840, + .step_width = 16, + .min_height = 48, + .max_height = 2160, + .step_height = 16, + }, + }, + { + .fourcc = V4L2_PIX_FMT_H264_SLICE, + .codec_mode = HANTRO_MODE_H264_DEC, + .max_depth = 2, + .frmsize = { + .min_width = 48, + .max_width = 3840, + .step_width = MB_DIM, + .min_height = 48, + .max_height = 2160, + .step_height = MB_DIM, + }, + }, +}; + +static irqreturn_t imx8m_vpu_g1_irq(int irq, void *dev_id) +{ + struct hantro_dev *vpu = dev_id; + enum vb2_buffer_state state; + u32 status; + + status = vdpu_read(vpu, G1_REG_INTERRUPT); + state = (status & G1_REG_INTERRUPT_DEC_RDY_INT) ? + VB2_BUF_STATE_DONE : VB2_BUF_STATE_ERROR; + + vdpu_write(vpu, 0, G1_REG_INTERRUPT); + vdpu_write(vpu, G1_REG_CONFIG_DEC_CLK_GATE_E, G1_REG_CONFIG); + + hantro_irq_done(vpu, 0, state); + + return IRQ_HANDLED; +} + +static int imx8mq_vpu_hw_init(struct hantro_dev *vpu) +{ + vpu->dec_base = vpu->reg_bases[0]; + vpu->ctrl_base = vpu->reg_bases[vpu->variant->num_regs - 1]; + + return 0; +} + +static void imx8m_vpu_g1_reset(struct hantro_ctx *ctx) +{ + struct hantro_dev *vpu = ctx->dev; + + imx8m_soft_reset(vpu, RESET_G1); +} + +/* + * Supported codec ops. + */ + +static const struct hantro_codec_ops imx8mq_vpu_codec_ops[] = { + [HANTRO_MODE_MPEG2_DEC] = { + .run = hantro_g1_mpeg2_dec_run, + .reset = imx8m_vpu_g1_reset, + .init = hantro_mpeg2_dec_init, + .exit = hantro_mpeg2_dec_exit, + }, + [HANTRO_MODE_VP8_DEC] = { + .run = hantro_g1_vp8_dec_run, + .reset = imx8m_vpu_g1_reset, + .init = hantro_vp8_dec_init, + .exit = hantro_vp8_dec_exit, + }, + [HANTRO_MODE_H264_DEC] = { + .run = hantro_g1_h264_dec_run, + .reset = imx8m_vpu_g1_reset, + .init = hantro_h264_dec_init, + .exit = hantro_h264_dec_exit, + }, +}; + +/* + * VPU variants. + */ + +static const struct hantro_irq imx8mq_irqs[] = { + { "g1", imx8m_vpu_g1_irq }, + { "g2", NULL /* TODO: imx8m_vpu_g2_irq */ }, +}; + +static const char * const imx8mq_clk_names[] = { "g1", "g2", "bus" }; +static const char * const imx8mq_reg_names[] = { "g1", "g2", "ctrl" }; + +const struct hantro_variant imx8mq_vpu_variant = { + .dec_fmts = imx8m_vpu_dec_fmts, + .num_dec_fmts = ARRAY_SIZE(imx8m_vpu_dec_fmts), + .postproc_fmts = imx8m_vpu_postproc_fmts, + .num_postproc_fmts = ARRAY_SIZE(imx8m_vpu_postproc_fmts), + .postproc_regs = &hantro_g1_postproc_regs, + .codec = HANTRO_MPEG2_DECODER | HANTRO_VP8_DECODER | + HANTRO_H264_DECODER, + .codec_ops = imx8mq_vpu_codec_ops, + .init = imx8mq_vpu_hw_init, + .runtime_resume = imx8mq_runtime_resume, + .irqs = imx8mq_irqs, + .num_irqs = ARRAY_SIZE(imx8mq_irqs), + .clk_names = imx8mq_clk_names, + .num_clocks = ARRAY_SIZE(imx8mq_clk_names), + .reg_names = imx8mq_reg_names, + .num_regs = ARRAY_SIZE(imx8mq_reg_names) +}; diff --git a/drivers/staging/media/hantro/rk3399_vpu_hw_jpeg_enc.c b/drivers/staging/media/hantro/rk3399_vpu_hw_jpeg_enc.c index 4c2d43fb6fd1..3498e6124acd 100644 --- a/drivers/staging/media/hantro/rk3399_vpu_hw_jpeg_enc.c +++ b/drivers/staging/media/hantro/rk3399_vpu_hw_jpeg_enc.c @@ -18,9 +18,8 @@ * * Quantization luma table values are written to registers * VEPU_swreg_0-VEPU_swreg_15, and chroma table values to - * VEPU_swreg_16-VEPU_swreg_31. - * - * JPEG zigzag order is expected on the quantization tables. + * VEPU_swreg_16-VEPU_swreg_31. A special order is needed, neither + * zigzag, nor linear. */ #include <asm/unaligned.h> @@ -98,12 +97,23 @@ rk3399_vpu_jpeg_enc_set_qtable(struct hantro_dev *vpu, unsigned char *chroma_qtable) { u32 reg, i; + __be32 *luma_qtable_p; + __be32 *chroma_qtable_p; + + luma_qtable_p = (__be32 *)luma_qtable; + chroma_qtable_p = (__be32 *)chroma_qtable; + /* + * Quantization table registers must be written in contiguous blocks. + * DO NOT collapse the below two "for" loops into one. + */ for (i = 0; i < VEPU_JPEG_QUANT_TABLE_COUNT; i++) { - reg = get_unaligned_be32(&luma_qtable[i]); + reg = get_unaligned_be32(&luma_qtable_p[i]); vepu_write_relaxed(vpu, reg, VEPU_REG_JPEG_LUMA_QUAT(i)); + } - reg = get_unaligned_be32(&chroma_qtable[i]); + for (i = 0; i < VEPU_JPEG_QUANT_TABLE_COUNT; i++) { + reg = get_unaligned_be32(&chroma_qtable_p[i]); vepu_write_relaxed(vpu, reg, VEPU_REG_JPEG_CHROMA_QUAT(i)); } } @@ -134,8 +144,8 @@ void rk3399_vpu_jpeg_enc_run(struct hantro_ctx *ctx) rk3399_vpu_set_src_img_ctrl(vpu, ctx); rk3399_vpu_jpeg_enc_set_buffers(vpu, ctx, &src_buf->vb2_buf); rk3399_vpu_jpeg_enc_set_qtable(vpu, - hantro_jpeg_get_qtable(&jpeg_ctx, 0), - hantro_jpeg_get_qtable(&jpeg_ctx, 1)); + hantro_jpeg_get_qtable(0), + hantro_jpeg_get_qtable(1)); reg = VEPU_REG_OUTPUT_SWAP32 | VEPU_REG_OUTPUT_SWAP16 |