Commit 7cdedc3f authored by Jonas Karlman's avatar Jonas Karlman Committed by Mauro Carvalho Chehab
Browse files

media: rockchip/vpu: Add infra to support MPEG-2 decoding



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: default avatarJonas Karlman <jonas@kwiboo.se>
Signed-off-by: default avatarEzequiel Garcia <ezequiel@collabora.com>
Signed-off-by: default avatarBoris Brezillon <boris.brezillon@collabora.com>
Signed-off-by: default avatarHans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab+samsung@kernel.org>
parent 6d9a39cf
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -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
+12 −0
Original line number Diff line number Diff line
@@ -27,6 +27,10 @@

#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_ */
+30 −0
Original line number Diff line number Diff line
@@ -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),
		},
	},
};

+14 −0
Original line number Diff line number Diff line
@@ -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;
@@ -38,6 +39,14 @@ struct rockchip_vpu_jpeg_enc_hw_ctx {
	struct rockchip_vpu_aux_buf bounce_buffer;
};

/**
 * 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
 *
@@ -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_ */
+61 −0
Original line number Diff line number Diff line
// 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);
}