media: rockchip/vpu: Add infra to support MPEG-2 decoding
authorJonas Karlman <jonas@kwiboo.se>
Tue, 28 May 2019 17:02:29 +0000 (13:02 -0400)
committerMauro Carvalho Chehab <mchehab+samsung@kernel.org>
Wed, 29 May 2019 15:10:12 +0000 (11:10 -0400)
Only adds structs and helpers to allow supporting MPEG-2 decoding on
rockchip SoCs. Support for RK3399 and RK3288 will be added in separate
commits

Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
Signed-off-by: Ezequiel Garcia <ezequiel@collabora.com>
Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
drivers/staging/media/rockchip/vpu/Makefile
drivers/staging/media/rockchip/vpu/rockchip_vpu.h
drivers/staging/media/rockchip/vpu/rockchip_vpu_drv.c
drivers/staging/media/rockchip/vpu/rockchip_vpu_hw.h
drivers/staging/media/rockchip/vpu/rockchip_vpu_mpeg2.c [new file with mode: 0644]

index 3360639..b3144e4 100644 (file)
@@ -8,4 +8,5 @@ rockchip-vpu-y += \
                rk3288_vpu_hw_jpeg_enc.o \
                rk3399_vpu_hw.o \
                rk3399_vpu_hw_jpeg_enc.o \
-               rockchip_vpu_jpeg.o
+               rockchip_vpu_jpeg.o \
+               rockchip_vpu_mpeg2.o
index ec7557a..3093821 100644 (file)
 
 #define ROCKCHIP_VPU_MAX_CLOCKS                4
 
+#define MPEG2_MB_DIM                   16
+#define MPEG2_MB_WIDTH(w)              DIV_ROUND_UP(w, MPEG2_MB_DIM)
+#define MPEG2_MB_HEIGHT(h)             DIV_ROUND_UP(h, MPEG2_MB_DIM)
+
 #define JPEG_MB_DIM                    16
 #define JPEG_MB_WIDTH(w)               DIV_ROUND_UP(w, JPEG_MB_DIM)
 #define JPEG_MB_HEIGHT(h)              DIV_ROUND_UP(h, JPEG_MB_DIM)
@@ -37,6 +41,7 @@ struct rockchip_vpu_codec_ops;
 #define RK_VPU_JPEG_ENCODER    BIT(0)
 #define RK_VPU_ENCODERS                0x0000ffff
 
+#define RK_VPU_MPEG2_DECODER   BIT(16)
 #define RK_VPU_DECODERS                0xffff0000
 
 /**
@@ -76,10 +81,12 @@ struct rockchip_vpu_variant {
  * enum rockchip_vpu_codec_mode - codec operating mode.
  * @RK_VPU_MODE_NONE:  No operating mode. Used for RAW video formats.
  * @RK_VPU_MODE_JPEG_ENC: JPEG encoder.
+ * @RK_VPU_MODE_MPEG2_DEC: MPEG-2 decoder.
  */
 enum rockchip_vpu_codec_mode {
        RK_VPU_MODE_NONE = -1,
        RK_VPU_MODE_JPEG_ENC,
+       RK_VPU_MODE_MPEG2_DEC,
 };
 
 /*
@@ -190,6 +197,7 @@ struct rockchip_vpu_dev {
  *                     calling v4l2_m2m_job_finish.
  * @codec_ops:         Set of operations related to codec mode.
  * @jpeg_enc:          JPEG-encoding context.
+ * @mpeg2_dec:         MPEG-2-decoding context.
  */
 struct rockchip_vpu_ctx {
        struct rockchip_vpu_dev *dev;
@@ -215,6 +223,7 @@ struct rockchip_vpu_ctx {
        /* Specific for particular codec modes. */
        union {
                struct rockchip_vpu_jpeg_enc_hw_ctx jpeg_enc;
+               struct rockchip_vpu_mpeg2_dec_hw_ctx mpeg2_dec;
        };
 };
 
@@ -319,4 +328,7 @@ static inline u32 vdpu_read(struct rockchip_vpu_dev *vpu, u32 reg)
 
 bool rockchip_vpu_is_encoder_ctx(const struct rockchip_vpu_ctx *ctx);
 
+void *rockchip_vpu_get_ctrl(struct rockchip_vpu_ctx *ctx, u32 id);
+dma_addr_t rockchip_vpu_get_ref(struct vb2_queue *q, u64 ts);
+
 #endif /* ROCKCHIP_VPU_H_ */
index 7510417..b94ff97 100644 (file)
@@ -35,6 +35,24 @@ module_param_named(debug, rockchip_vpu_debug, int, 0644);
 MODULE_PARM_DESC(debug,
                 "Debug level - higher value produces more verbose messages");
 
+void *rockchip_vpu_get_ctrl(struct rockchip_vpu_ctx *ctx, u32 id)
+{
+       struct v4l2_ctrl *ctrl;
+
+       ctrl = v4l2_ctrl_find(&ctx->ctrl_handler, id);
+       return ctrl ? ctrl->p_cur.p : NULL;
+}
+
+dma_addr_t rockchip_vpu_get_ref(struct vb2_queue *q, u64 ts)
+{
+       int index;
+
+       index = vb2_find_timestamp(q, ts, 0);
+       if (index >= 0)
+               return vb2_dma_contig_plane_dma_addr(q->bufs[index], 0);
+       return 0;
+}
+
 static int
 rockchip_vpu_enc_buf_finish(struct rockchip_vpu_ctx *ctx,
                            struct vb2_buffer *buf,
@@ -255,6 +273,18 @@ static struct rockchip_vpu_ctrl controls[] = {
                        .step = 1,
                        .def = 50,
                },
+       }, {
+               .id = V4L2_CID_MPEG_VIDEO_MPEG2_SLICE_PARAMS,
+               .codec = RK_VPU_MPEG2_DECODER,
+               .cfg = {
+                       .elem_size = sizeof(struct v4l2_ctrl_mpeg2_slice_params),
+               },
+       }, {
+               .id = V4L2_CID_MPEG_VIDEO_MPEG2_QUANTIZATION,
+               .codec = RK_VPU_MPEG2_DECODER,
+               .cfg = {
+                       .elem_size = sizeof(struct v4l2_ctrl_mpeg2_quantization),
+               },
        },
 };
 
index 46716d1..1bdc5ce 100644 (file)
@@ -11,6 +11,7 @@
 
 #include <linux/interrupt.h>
 #include <linux/v4l2-controls.h>
+#include <media/mpeg2-ctrls.h>
 #include <media/videobuf2-core.h>
 
 struct rockchip_vpu_dev;
@@ -39,6 +40,14 @@ struct rockchip_vpu_jpeg_enc_hw_ctx {
 };
 
 /**
+ * struct rockchip_vpu_mpeg2_dec_hw_ctx
+ * @qtable:            Quantization table
+ */
+struct rockchip_vpu_mpeg2_dec_hw_ctx {
+       struct rockchip_vpu_aux_buf qtable;
+};
+
+/**
  * struct rockchip_vpu_codec_ops - codec mode specific operations
  *
  * @init:      If needed, can be used for initialization.
@@ -83,4 +92,9 @@ void rk3399_vpu_jpeg_enc_run(struct rockchip_vpu_ctx *ctx);
 int rockchip_vpu_jpeg_enc_init(struct rockchip_vpu_ctx *ctx);
 void rockchip_vpu_jpeg_enc_exit(struct rockchip_vpu_ctx *ctx);
 
+void rockchip_vpu_mpeg2_dec_copy_qtable(u8 *qtable,
+       const struct v4l2_ctrl_mpeg2_quantization *ctrl);
+int rockchip_vpu_mpeg2_dec_init(struct rockchip_vpu_ctx *ctx);
+void rockchip_vpu_mpeg2_dec_exit(struct rockchip_vpu_ctx *ctx);
+
 #endif /* ROCKCHIP_VPU_HW_H_ */
diff --git a/drivers/staging/media/rockchip/vpu/rockchip_vpu_mpeg2.c b/drivers/staging/media/rockchip/vpu/rockchip_vpu_mpeg2.c
new file mode 100644 (file)
index 0000000..5a5b9ea
--- /dev/null
@@ -0,0 +1,61 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Rockchip VPU codec driver
+ *
+ * Copyright (C) 2018 Rockchip Electronics Co., Ltd.
+ */
+
+#include "rockchip_vpu.h"
+
+static const u8 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
+};
+
+void rockchip_vpu_mpeg2_dec_copy_qtable(u8 *qtable,
+       const struct v4l2_ctrl_mpeg2_quantization *ctrl)
+{
+       int i, n;
+
+       if (!qtable || !ctrl)
+               return;
+
+       for (i = 0; i < ARRAY_SIZE(zigzag); i++) {
+               n = zigzag[i];
+               qtable[n + 0] = ctrl->intra_quantiser_matrix[i];
+               qtable[n + 64] = ctrl->non_intra_quantiser_matrix[i];
+               qtable[n + 128] = ctrl->chroma_intra_quantiser_matrix[i];
+               qtable[n + 192] = ctrl->chroma_non_intra_quantiser_matrix[i];
+       }
+}
+
+int rockchip_vpu_mpeg2_dec_init(struct rockchip_vpu_ctx *ctx)
+{
+       struct rockchip_vpu_dev *vpu = ctx->dev;
+
+       ctx->mpeg2_dec.qtable.size = ARRAY_SIZE(zigzag) * 4;
+       ctx->mpeg2_dec.qtable.cpu =
+               dma_alloc_coherent(vpu->dev,
+                                  ctx->mpeg2_dec.qtable.size,
+                                  &ctx->mpeg2_dec.qtable.dma,
+                                  GFP_KERNEL);
+       if (!ctx->mpeg2_dec.qtable.cpu)
+               return -ENOMEM;
+       return 0;
+}
+
+void rockchip_vpu_mpeg2_dec_exit(struct rockchip_vpu_ctx *ctx)
+{
+       struct rockchip_vpu_dev *vpu = ctx->dev;
+
+       dma_free_coherent(vpu->dev,
+                         ctx->mpeg2_dec.qtable.size,
+                         ctx->mpeg2_dec.qtable.cpu,
+                         ctx->mpeg2_dec.qtable.dma);
+}