Commit 8c2d66b0 authored by Ezequiel Garcia's avatar Ezequiel Garcia Committed by Mauro Carvalho Chehab
Browse files

media: hantro: Support color conversion via post-processing



The Hantro G1 decoder is able to enable a post-processor
on the decoding pipeline, which can be used to perform
scaling and color conversion.

The post-processor is integrated to the decoder, and it's
possible to use it in a way that is completely transparent
to the user.

This commit enables color conversion via post-processing,
which means the driver now exposes YUV packed, in addition to NV12.

Signed-off-by: default avatarEzequiel Garcia <ezequiel@collabora.com>
Reviewed-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+huawei@kernel.org>
parent 3143f8a1
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -3,6 +3,7 @@ obj-$(CONFIG_VIDEO_HANTRO) += hantro-vpu.o
hantro-vpu-y += \
		hantro_drv.o \
		hantro_v4l2.o \
		hantro_postproc.o \
		hantro_h1_jpeg_enc.o \
		hantro_g1_h264_dec.o \
		hantro_g1_mpeg2_dec.o \
+62 −4
Original line number Diff line number Diff line
@@ -60,6 +60,8 @@ struct hantro_irq {
 * @num_enc_fmts:		Number of encoder formats.
 * @dec_fmts:			Decoder formats.
 * @num_dec_fmts:		Number of decoder formats.
 * @postproc_fmts:		Post-processor formats.
 * @num_postproc_fmts:		Number of post-processor formats.
 * @codec:			Supported codecs
 * @codec_ops:			Codec ops.
 * @init:			Initialize hardware.
@@ -70,6 +72,7 @@ struct hantro_irq {
 * @num_clocks:			number of clocks in the array
 * @reg_names:			array of register range names
 * @num_regs:			number of register range names in the array
 * @postproc_regs:		&struct hantro_postproc_regs pointer
 */
struct hantro_variant {
	unsigned int enc_offset;
@@ -78,6 +81,8 @@ struct hantro_variant {
	unsigned int num_enc_fmts;
	const struct hantro_fmt *dec_fmts;
	unsigned int num_dec_fmts;
	const struct hantro_fmt *postproc_fmts;
	unsigned int num_postproc_fmts;
	unsigned int codec;
	const struct hantro_codec_ops *codec_ops;
	int (*init)(struct hantro_dev *vpu);
@@ -88,6 +93,7 @@ struct hantro_variant {
	int num_clocks;
	const char * const *reg_names;
	int num_regs;
	const struct hantro_postproc_regs *postproc_regs;
};

/**
@@ -213,6 +219,7 @@ struct hantro_dev {
 *			context, and it's called right before
 *			calling v4l2_m2m_job_finish.
 * @codec_ops:		Set of operations related to codec mode.
 * @postproc:		Post-processing context.
 * @jpeg_enc:		JPEG-encoding context.
 * @mpeg2_dec:		MPEG-2-decoding context.
 * @vp8_dec:		VP8-decoding context.
@@ -237,6 +244,7 @@ struct hantro_ctx {
			  unsigned int bytesused);

	const struct hantro_codec_ops *codec_ops;
	struct hantro_postproc_ctx postproc;

	/* Specific for particular codec modes. */
	union {
@@ -274,6 +282,23 @@ struct hantro_reg {
	u32 mask;
};

struct hantro_postproc_regs {
	struct hantro_reg pipeline_en;
	struct hantro_reg max_burst;
	struct hantro_reg clk_gate;
	struct hantro_reg out_swap32;
	struct hantro_reg out_endian;
	struct hantro_reg out_luma_base;
	struct hantro_reg input_width;
	struct hantro_reg input_height;
	struct hantro_reg output_width;
	struct hantro_reg output_height;
	struct hantro_reg input_fmt;
	struct hantro_reg output_fmt;
	struct hantro_reg orig_width;
	struct hantro_reg display_width;
};

/* Logging helpers */

/**
@@ -352,7 +377,7 @@ static inline u32 vdpu_read(struct hantro_dev *vpu, u32 reg)
	return val;
}

static inline void hantro_reg_write(struct hantro_dev *vpu,
static inline u32 vdpu_read_mask(struct hantro_dev *vpu,
				 const struct hantro_reg *reg,
				 u32 val)
{
@@ -361,7 +386,21 @@ static inline void hantro_reg_write(struct hantro_dev *vpu,
	v = vdpu_read(vpu, reg->base);
	v &= ~(reg->mask << reg->shift);
	v |= ((val & reg->mask) << reg->shift);
	vdpu_write_relaxed(vpu, v, reg->base);
	return v;
}

static inline void hantro_reg_write(struct hantro_dev *vpu,
				    const struct hantro_reg *reg,
				    u32 val)
{
	vdpu_write_relaxed(vpu, vdpu_read_mask(vpu, reg, val), reg->base);
}

static inline void hantro_reg_write_s(struct hantro_dev *vpu,
				      const struct hantro_reg *reg,
				      u32 val)
{
	vdpu_write(vpu, vdpu_read_mask(vpu, reg, val), reg->base);
}

bool hantro_is_encoder_ctx(const struct hantro_ctx *ctx);
@@ -381,4 +420,23 @@ hantro_get_dst_buf(struct hantro_ctx *ctx)
	return v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
}

static inline bool
hantro_needs_postproc(struct hantro_ctx *ctx, const struct hantro_fmt *fmt)
{
	return fmt->fourcc != V4L2_PIX_FMT_NV12;
}

static inline dma_addr_t
hantro_get_dec_buf_addr(struct hantro_ctx *ctx, struct vb2_buffer *vb)
{
	if (hantro_needs_postproc(ctx, ctx->vpu_dst_fmt))
		return ctx->postproc.dec_q[vb->index].dma;
	return vb2_dma_contig_plane_dma_addr(vb, 0);
}

void hantro_postproc_disable(struct hantro_ctx *ctx);
void hantro_postproc_enable(struct hantro_ctx *ctx);
void hantro_postproc_free(struct hantro_ctx *ctx);
int hantro_postproc_alloc(struct hantro_ctx *ctx);

#endif /* HANTRO_H_ */
+6 −1
Original line number Diff line number Diff line
@@ -53,7 +53,7 @@ dma_addr_t hantro_get_ref(struct hantro_ctx *ctx, u64 ts)
	if (index < 0)
		return 0;
	buf = vb2_get_buffer(q, index);
	return vb2_dma_contig_plane_dma_addr(buf, 0);
	return hantro_get_dec_buf_addr(ctx, buf);
}

static int
@@ -159,6 +159,11 @@ void hantro_start_prepare_run(struct hantro_ctx *ctx)
	src_buf = hantro_get_src_buf(ctx);
	v4l2_ctrl_request_setup(src_buf->vb2_buf.req_obj.req,
				&ctx->ctrl_handler);

	if (hantro_needs_postproc(ctx, ctx->vpu_dst_fmt))
		hantro_postproc_enable(ctx);
	else
		hantro_postproc_disable(ctx);
}

void hantro_end_prepare_run(struct hantro_ctx *ctx)
+1 −1
Original line number Diff line number Diff line
@@ -244,7 +244,7 @@ static void set_buffers(struct hantro_ctx *ctx)
	vdpu_write_relaxed(vpu, src_dma, G1_REG_ADDR_STR);

	/* Destination (decoded frame) buffer. */
	dst_dma = vb2_dma_contig_plane_dma_addr(&dst_buf->vb2_buf, 0);
	dst_dma = hantro_get_dec_buf_addr(ctx, &dst_buf->vb2_buf);
	/* Adjust dma addr to start at second line for bottom field */
	if (ctrls->slices[0].flags & V4L2_H264_SLICE_FLAG_BOTTOM_FIELD)
		offset = ALIGN(ctx->src_fmt.width, MB_DIM);
+1 −1
Original line number Diff line number Diff line
@@ -121,7 +121,7 @@ hantro_g1_mpeg2_dec_set_buffers(struct hantro_dev *vpu, struct hantro_ctx *ctx,
	vdpu_write_relaxed(vpu, addr, G1_REG_RLC_VLC_BASE);

	/* Destination frame buffer */
	addr = vb2_dma_contig_plane_dma_addr(dst_buf, 0);
	addr = hantro_get_dec_buf_addr(ctx, dst_buf);
	current_addr = addr;

	if (picture->picture_structure == PICT_BOTTOM_FIELD)
Loading