File Index
Files and directories
Sign in
FILE

cedrus_mpeg2.c

File preview with syntax highlighting.

linux-6.19.14/drivers/staging/media/sunxi/cedrus/cedrus_mpeg2.c C
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * Cedrus VPU driver
  4 *
  5 * Copyright (C) 2016 Florent Revest <florent.revest@free-electrons.com>
  6 * Copyright (C) 2018 Paul Kocialkowski <paul.kocialkowski@bootlin.com>
  7 * Copyright (C) 2018 Bootlin
  8 */
  9
 10#include <media/videobuf2-dma-contig.h>
 11
 12#include "cedrus.h"
 13#include "cedrus_hw.h"
 14#include "cedrus_regs.h"
 15
 16static enum cedrus_irq_status cedrus_mpeg2_irq_status(struct cedrus_ctx *ctx)
 17{
 18	struct cedrus_dev *dev = ctx->dev;
 19	u32 reg;
 20
 21	reg = cedrus_read(dev, VE_DEC_MPEG_STATUS);
 22	reg &= VE_DEC_MPEG_STATUS_CHECK_MASK;
 23
 24	if (!reg)
 25		return CEDRUS_IRQ_NONE;
 26
 27	if (reg & VE_DEC_MPEG_STATUS_CHECK_ERROR ||
 28	    !(reg & VE_DEC_MPEG_STATUS_SUCCESS))
 29		return CEDRUS_IRQ_ERROR;
 30
 31	return CEDRUS_IRQ_OK;
 32}
 33
 34static void cedrus_mpeg2_irq_clear(struct cedrus_ctx *ctx)
 35{
 36	struct cedrus_dev *dev = ctx->dev;
 37
 38	cedrus_write(dev, VE_DEC_MPEG_STATUS, VE_DEC_MPEG_STATUS_CHECK_MASK);
 39}
 40
 41static void cedrus_mpeg2_irq_disable(struct cedrus_ctx *ctx)
 42{
 43	struct cedrus_dev *dev = ctx->dev;
 44	u32 reg = cedrus_read(dev, VE_DEC_MPEG_CTRL);
 45
 46	reg &= ~VE_DEC_MPEG_CTRL_IRQ_MASK;
 47
 48	cedrus_write(dev, VE_DEC_MPEG_CTRL, reg);
 49}
 50
 51static int cedrus_mpeg2_setup(struct cedrus_ctx *ctx, struct cedrus_run *run)
 52{
 53	const struct v4l2_ctrl_mpeg2_sequence *seq;
 54	const struct v4l2_ctrl_mpeg2_picture *pic;
 55	const struct v4l2_ctrl_mpeg2_quantisation *quantisation;
 56	dma_addr_t src_buf_addr, dst_luma_addr, dst_chroma_addr;
 57	struct cedrus_dev *dev = ctx->dev;
 58	struct vb2_queue *vq;
 59	const u8 *matrix;
 60	unsigned int i;
 61	u32 reg;
 62
 63	seq = run->mpeg2.sequence;
 64	pic = run->mpeg2.picture;
 65
 66	quantisation = run->mpeg2.quantisation;
 67
 68	/* Activate MPEG engine. */
 69	cedrus_engine_enable(ctx);
 70
 71	/* Set intra quantisation matrix. */
 72	matrix = quantisation->intra_quantiser_matrix;
 73	for (i = 0; i < 64; i++) {
 74		reg = VE_DEC_MPEG_IQMINPUT_WEIGHT(i, matrix[i]);
 75		reg |= VE_DEC_MPEG_IQMINPUT_FLAG_INTRA;
 76
 77		cedrus_write(dev, VE_DEC_MPEG_IQMINPUT, reg);
 78	}
 79
 80	/* Set non-intra quantisation matrix. */
 81	matrix = quantisation->non_intra_quantiser_matrix;
 82	for (i = 0; i < 64; i++) {
 83		reg = VE_DEC_MPEG_IQMINPUT_WEIGHT(i, matrix[i]);
 84		reg |= VE_DEC_MPEG_IQMINPUT_FLAG_NON_INTRA;
 85
 86		cedrus_write(dev, VE_DEC_MPEG_IQMINPUT, reg);
 87	}
 88
 89	/* Set MPEG picture header. */
 90
 91	reg = VE_DEC_MPEG_MP12HDR_SLICE_TYPE(pic->picture_coding_type);
 92	reg |= VE_DEC_MPEG_MP12HDR_F_CODE(0, 0, pic->f_code[0][0]);
 93	reg |= VE_DEC_MPEG_MP12HDR_F_CODE(0, 1, pic->f_code[0][1]);
 94	reg |= VE_DEC_MPEG_MP12HDR_F_CODE(1, 0, pic->f_code[1][0]);
 95	reg |= VE_DEC_MPEG_MP12HDR_F_CODE(1, 1, pic->f_code[1][1]);
 96	reg |= VE_DEC_MPEG_MP12HDR_INTRA_DC_PRECISION(pic->intra_dc_precision);
 97	reg |= VE_DEC_MPEG_MP12HDR_INTRA_PICTURE_STRUCTURE(pic->picture_structure);
 98	reg |= VE_DEC_MPEG_MP12HDR_TOP_FIELD_FIRST(pic->flags & V4L2_MPEG2_PIC_FLAG_TOP_FIELD_FIRST);
 99	reg |= VE_DEC_MPEG_MP12HDR_FRAME_PRED_FRAME_DCT(pic->flags & V4L2_MPEG2_PIC_FLAG_FRAME_PRED_DCT);
100	reg |= VE_DEC_MPEG_MP12HDR_CONCEALMENT_MOTION_VECTORS(pic->flags & V4L2_MPEG2_PIC_FLAG_CONCEALMENT_MV);
101	reg |= VE_DEC_MPEG_MP12HDR_Q_SCALE_TYPE(pic->flags & V4L2_MPEG2_PIC_FLAG_Q_SCALE_TYPE);
102	reg |= VE_DEC_MPEG_MP12HDR_INTRA_VLC_FORMAT(pic->flags & V4L2_MPEG2_PIC_FLAG_INTRA_VLC);
103	reg |= VE_DEC_MPEG_MP12HDR_ALTERNATE_SCAN(pic->flags & V4L2_MPEG2_PIC_FLAG_ALT_SCAN);
104	reg |= VE_DEC_MPEG_MP12HDR_FULL_PEL_FORWARD_VECTOR(0);
105	reg |= VE_DEC_MPEG_MP12HDR_FULL_PEL_BACKWARD_VECTOR(0);
106
107	cedrus_write(dev, VE_DEC_MPEG_MP12HDR, reg);
108
109	/* Set frame dimensions. */
110
111	reg = VE_DEC_MPEG_PICCODEDSIZE_WIDTH(seq->horizontal_size);
112	reg |= VE_DEC_MPEG_PICCODEDSIZE_HEIGHT(seq->vertical_size);
113
114	cedrus_write(dev, VE_DEC_MPEG_PICCODEDSIZE, reg);
115
116	reg = VE_DEC_MPEG_PICBOUNDSIZE_WIDTH(ctx->src_fmt.width);
117	reg |= VE_DEC_MPEG_PICBOUNDSIZE_HEIGHT(ctx->src_fmt.height);
118
119	cedrus_write(dev, VE_DEC_MPEG_PICBOUNDSIZE, reg);
120
121	/* Forward and backward prediction reference buffers. */
122	vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
123
124	cedrus_write_ref_buf_addr(ctx, vq, pic->forward_ref_ts,
125				  VE_DEC_MPEG_FWD_REF_LUMA_ADDR,
126				  VE_DEC_MPEG_FWD_REF_CHROMA_ADDR);
127	cedrus_write_ref_buf_addr(ctx, vq, pic->backward_ref_ts,
128				  VE_DEC_MPEG_BWD_REF_LUMA_ADDR,
129				  VE_DEC_MPEG_BWD_REF_CHROMA_ADDR);
130
131	/* Destination luma and chroma buffers. */
132
133	dst_luma_addr = cedrus_dst_buf_addr(ctx, &run->dst->vb2_buf, 0);
134	dst_chroma_addr = cedrus_dst_buf_addr(ctx, &run->dst->vb2_buf, 1);
135
136	cedrus_write(dev, VE_DEC_MPEG_REC_LUMA, dst_luma_addr);
137	cedrus_write(dev, VE_DEC_MPEG_REC_CHROMA, dst_chroma_addr);
138
139	/* Source offset and length in bits. */
140
141	cedrus_write(dev, VE_DEC_MPEG_VLD_OFFSET, 0);
142
143	reg = vb2_get_plane_payload(&run->src->vb2_buf, 0) * 8;
144	cedrus_write(dev, VE_DEC_MPEG_VLD_LEN, reg);
145
146	/* Source beginning and end addresses. */
147
148	src_buf_addr = vb2_dma_contig_plane_dma_addr(&run->src->vb2_buf, 0);
149
150	reg = VE_DEC_MPEG_VLD_ADDR_BASE(src_buf_addr);
151	reg |= VE_DEC_MPEG_VLD_ADDR_VALID_PIC_DATA;
152	reg |= VE_DEC_MPEG_VLD_ADDR_LAST_PIC_DATA;
153	reg |= VE_DEC_MPEG_VLD_ADDR_FIRST_PIC_DATA;
154
155	cedrus_write(dev, VE_DEC_MPEG_VLD_ADDR, reg);
156
157	reg = src_buf_addr + vb2_get_plane_payload(&run->src->vb2_buf, 0);
158	cedrus_write(dev, VE_DEC_MPEG_VLD_END_ADDR, reg);
159
160	/* Macroblock address: start at the beginning. */
161	reg = VE_DEC_MPEG_MBADDR_Y(0) | VE_DEC_MPEG_MBADDR_X(0);
162	cedrus_write(dev, VE_DEC_MPEG_MBADDR, reg);
163
164	/* Clear previous errors. */
165	cedrus_write(dev, VE_DEC_MPEG_ERROR, 0);
166
167	/* Clear correct macroblocks register. */
168	cedrus_write(dev, VE_DEC_MPEG_CRTMBADDR, 0);
169
170	/* Enable appropriate interruptions and components. */
171
172	reg = VE_DEC_MPEG_CTRL_IRQ_MASK | VE_DEC_MPEG_CTRL_MC_NO_WRITEBACK |
173	      VE_DEC_MPEG_CTRL_MC_CACHE_EN;
174
175	cedrus_write(dev, VE_DEC_MPEG_CTRL, reg);
176
177	return 0;
178}
179
180static void cedrus_mpeg2_trigger(struct cedrus_ctx *ctx)
181{
182	struct cedrus_dev *dev = ctx->dev;
183	u32 reg;
184
185	/* Trigger MPEG engine. */
186	reg = VE_DEC_MPEG_TRIGGER_HW_MPEG_VLD | VE_DEC_MPEG_TRIGGER_MPEG2 |
187	      VE_DEC_MPEG_TRIGGER_MB_BOUNDARY;
188
189	cedrus_write(dev, VE_DEC_MPEG_TRIGGER, reg);
190}
191
192struct cedrus_dec_ops cedrus_dec_ops_mpeg2 = {
193	.irq_clear	= cedrus_mpeg2_irq_clear,
194	.irq_disable	= cedrus_mpeg2_irq_disable,
195	.irq_status	= cedrus_mpeg2_irq_status,
196	.setup		= cedrus_mpeg2_setup,
197	.trigger	= cedrus_mpeg2_trigger,
198};
~/ Read-only file preview.