linux/drivers/staging/media/hantro/rockchip_vpu2_hw_jpeg_enc.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Hantro VPU codec driver
   4 *
   5 * Copyright (C) 2018 Rockchip Electronics Co., Ltd.
   6 *
   7 * JPEG encoder
   8 * ------------
   9 * The VPU JPEG encoder produces JPEG baseline sequential format.
  10 * The quantization coefficients are 8-bit values, complying with
  11 * the baseline specification. Therefore, it requires
  12 * luma and chroma quantization tables. The hardware does entropy
  13 * encoding using internal Huffman tables, as specified in the JPEG
  14 * specification.
  15 *
  16 * In other words, only the luma and chroma quantization tables are
  17 * required for the encoding operation.
  18 *
  19 * Quantization luma table values are written to registers
  20 * VEPU_swreg_0-VEPU_swreg_15, and chroma table values to
  21 * VEPU_swreg_16-VEPU_swreg_31. A special order is needed, neither
  22 * zigzag, nor linear.
  23 */
  24
  25#include <asm/unaligned.h>
  26#include <media/v4l2-mem2mem.h>
  27#include "hantro_jpeg.h"
  28#include "hantro.h"
  29#include "hantro_v4l2.h"
  30#include "hantro_hw.h"
  31#include "rockchip_vpu2_regs.h"
  32
  33#define VEPU_JPEG_QUANT_TABLE_COUNT 16
  34
  35static void rockchip_vpu2_set_src_img_ctrl(struct hantro_dev *vpu,
  36                                           struct hantro_ctx *ctx)
  37{
  38        struct v4l2_pix_format_mplane *pix_fmt = &ctx->src_fmt;
  39        u32 reg;
  40
  41        /*
  42         * The pix fmt width/height are already macroblock aligned
  43         * by .vidioc_s_fmt_vid_cap_mplane() callback
  44         */
  45        reg = VEPU_REG_IN_IMG_CTRL_ROW_LEN(pix_fmt->width);
  46        vepu_write_relaxed(vpu, reg, VEPU_REG_INPUT_LUMA_INFO);
  47
  48        reg = VEPU_REG_IN_IMG_CTRL_OVRFLR_D4(0) |
  49              VEPU_REG_IN_IMG_CTRL_OVRFLB(0);
  50        /*
  51         * This register controls the input crop, as the offset
  52         * from the right/bottom within the last macroblock. The offset from the
  53         * right must be divided by 4 and so the crop must be aligned to 4 pixels
  54         * horizontally.
  55         */
  56        vepu_write_relaxed(vpu, reg, VEPU_REG_ENC_OVER_FILL_STRM_OFFSET);
  57
  58        reg = VEPU_REG_IN_IMG_CTRL_FMT(ctx->vpu_src_fmt->enc_fmt);
  59        vepu_write_relaxed(vpu, reg, VEPU_REG_ENC_CTRL1);
  60}
  61
  62static void rockchip_vpu2_jpeg_enc_set_buffers(struct hantro_dev *vpu,
  63                                               struct hantro_ctx *ctx,
  64                                               struct vb2_buffer *src_buf)
  65{
  66        struct v4l2_pix_format_mplane *pix_fmt = &ctx->src_fmt;
  67        dma_addr_t src[3];
  68
  69        WARN_ON(pix_fmt->num_planes > 3);
  70
  71        vepu_write_relaxed(vpu, ctx->jpeg_enc.bounce_buffer.dma,
  72                           VEPU_REG_ADDR_OUTPUT_STREAM);
  73        vepu_write_relaxed(vpu, ctx->jpeg_enc.bounce_buffer.size,
  74                           VEPU_REG_STR_BUF_LIMIT);
  75
  76        if (pix_fmt->num_planes == 1) {
  77                src[0] = vb2_dma_contig_plane_dma_addr(src_buf, 0);
  78                vepu_write_relaxed(vpu, src[0], VEPU_REG_ADDR_IN_PLANE_0);
  79        } else if (pix_fmt->num_planes == 2) {
  80                src[0] = vb2_dma_contig_plane_dma_addr(src_buf, 0);
  81                src[1] = vb2_dma_contig_plane_dma_addr(src_buf, 1);
  82                vepu_write_relaxed(vpu, src[0], VEPU_REG_ADDR_IN_PLANE_0);
  83                vepu_write_relaxed(vpu, src[1], VEPU_REG_ADDR_IN_PLANE_1);
  84        } else {
  85                src[0] = vb2_dma_contig_plane_dma_addr(src_buf, 0);
  86                src[1] = vb2_dma_contig_plane_dma_addr(src_buf, 1);
  87                src[2] = vb2_dma_contig_plane_dma_addr(src_buf, 2);
  88                vepu_write_relaxed(vpu, src[0], VEPU_REG_ADDR_IN_PLANE_0);
  89                vepu_write_relaxed(vpu, src[1], VEPU_REG_ADDR_IN_PLANE_1);
  90                vepu_write_relaxed(vpu, src[2], VEPU_REG_ADDR_IN_PLANE_2);
  91        }
  92}
  93
  94static void
  95rockchip_vpu2_jpeg_enc_set_qtable(struct hantro_dev *vpu,
  96                                  unsigned char *luma_qtable,
  97                                  unsigned char *chroma_qtable)
  98{
  99        u32 reg, i;
 100        __be32 *luma_qtable_p;
 101        __be32 *chroma_qtable_p;
 102
 103        luma_qtable_p = (__be32 *)luma_qtable;
 104        chroma_qtable_p = (__be32 *)chroma_qtable;
 105
 106        /*
 107         * Quantization table registers must be written in contiguous blocks.
 108         * DO NOT collapse the below two "for" loops into one.
 109         */
 110        for (i = 0; i < VEPU_JPEG_QUANT_TABLE_COUNT; i++) {
 111                reg = get_unaligned_be32(&luma_qtable_p[i]);
 112                vepu_write_relaxed(vpu, reg, VEPU_REG_JPEG_LUMA_QUAT(i));
 113        }
 114
 115        for (i = 0; i < VEPU_JPEG_QUANT_TABLE_COUNT; i++) {
 116                reg = get_unaligned_be32(&chroma_qtable_p[i]);
 117                vepu_write_relaxed(vpu, reg, VEPU_REG_JPEG_CHROMA_QUAT(i));
 118        }
 119}
 120
 121int rockchip_vpu2_jpeg_enc_run(struct hantro_ctx *ctx)
 122{
 123        struct hantro_dev *vpu = ctx->dev;
 124        struct vb2_v4l2_buffer *src_buf, *dst_buf;
 125        struct hantro_jpeg_ctx jpeg_ctx;
 126        u32 reg;
 127
 128        src_buf = hantro_get_src_buf(ctx);
 129        dst_buf = hantro_get_dst_buf(ctx);
 130
 131        hantro_start_prepare_run(ctx);
 132
 133        memset(&jpeg_ctx, 0, sizeof(jpeg_ctx));
 134        jpeg_ctx.buffer = vb2_plane_vaddr(&dst_buf->vb2_buf, 0);
 135        jpeg_ctx.width = ctx->dst_fmt.width;
 136        jpeg_ctx.height = ctx->dst_fmt.height;
 137        jpeg_ctx.quality = ctx->jpeg_quality;
 138        hantro_jpeg_header_assemble(&jpeg_ctx);
 139
 140        /* Switch to JPEG encoder mode before writing registers */
 141        vepu_write_relaxed(vpu, VEPU_REG_ENCODE_FORMAT_JPEG,
 142                           VEPU_REG_ENCODE_START);
 143
 144        rockchip_vpu2_set_src_img_ctrl(vpu, ctx);
 145        rockchip_vpu2_jpeg_enc_set_buffers(vpu, ctx, &src_buf->vb2_buf);
 146        rockchip_vpu2_jpeg_enc_set_qtable(vpu,
 147                                          hantro_jpeg_get_qtable(0),
 148                                          hantro_jpeg_get_qtable(1));
 149
 150        reg = VEPU_REG_OUTPUT_SWAP32
 151                | VEPU_REG_OUTPUT_SWAP16
 152                | VEPU_REG_OUTPUT_SWAP8
 153                | VEPU_REG_INPUT_SWAP8
 154                | VEPU_REG_INPUT_SWAP16
 155                | VEPU_REG_INPUT_SWAP32;
 156        /* Make sure that all registers are written at this point. */
 157        vepu_write(vpu, reg, VEPU_REG_DATA_ENDIAN);
 158
 159        reg = VEPU_REG_AXI_CTRL_BURST_LEN(16);
 160        vepu_write_relaxed(vpu, reg, VEPU_REG_AXI_CTRL);
 161
 162        reg = VEPU_REG_MB_WIDTH(MB_WIDTH(ctx->src_fmt.width))
 163                | VEPU_REG_MB_HEIGHT(MB_HEIGHT(ctx->src_fmt.height))
 164                | VEPU_REG_FRAME_TYPE_INTRA
 165                | VEPU_REG_ENCODE_FORMAT_JPEG
 166                | VEPU_REG_ENCODE_ENABLE;
 167
 168        /* Kick the watchdog and start encoding */
 169        hantro_end_prepare_run(ctx);
 170        vepu_write(vpu, reg, VEPU_REG_ENCODE_START);
 171
 172        return 0;
 173}
 174