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 
16 static 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 
34 static 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 
41 static 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 
51 static void 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 	dma_addr_t fwd_luma_addr, fwd_chroma_addr;
58 	dma_addr_t bwd_luma_addr, bwd_chroma_addr;
59 	struct cedrus_dev *dev = ctx->dev;
60 	struct vb2_queue *vq;
61 	const u8 *matrix;
62 	int forward_idx;
63 	int backward_idx;
64 	unsigned int i;
65 	u32 reg;
66 
67 	seq = run->mpeg2.sequence;
68 	pic = run->mpeg2.picture;
69 
70 	quantisation = run->mpeg2.quantisation;
71 
72 	/* Activate MPEG engine. */
73 	cedrus_engine_enable(ctx, CEDRUS_CODEC_MPEG2);
74 
75 	/* Set intra quantisation matrix. */
76 	matrix = quantisation->intra_quantiser_matrix;
77 	for (i = 0; i < 64; i++) {
78 		reg = VE_DEC_MPEG_IQMINPUT_WEIGHT(i, matrix[i]);
79 		reg |= VE_DEC_MPEG_IQMINPUT_FLAG_INTRA;
80 
81 		cedrus_write(dev, VE_DEC_MPEG_IQMINPUT, reg);
82 	}
83 
84 	/* Set non-intra quantisation matrix. */
85 	matrix = quantisation->non_intra_quantiser_matrix;
86 	for (i = 0; i < 64; i++) {
87 		reg = VE_DEC_MPEG_IQMINPUT_WEIGHT(i, matrix[i]);
88 		reg |= VE_DEC_MPEG_IQMINPUT_FLAG_NON_INTRA;
89 
90 		cedrus_write(dev, VE_DEC_MPEG_IQMINPUT, reg);
91 	}
92 
93 	/* Set MPEG picture header. */
94 
95 	reg = VE_DEC_MPEG_MP12HDR_SLICE_TYPE(pic->picture_coding_type);
96 	reg |= VE_DEC_MPEG_MP12HDR_F_CODE(0, 0, pic->f_code[0][0]);
97 	reg |= VE_DEC_MPEG_MP12HDR_F_CODE(0, 1, pic->f_code[0][1]);
98 	reg |= VE_DEC_MPEG_MP12HDR_F_CODE(1, 0, pic->f_code[1][0]);
99 	reg |= VE_DEC_MPEG_MP12HDR_F_CODE(1, 1, pic->f_code[1][1]);
100 	reg |= VE_DEC_MPEG_MP12HDR_INTRA_DC_PRECISION(pic->intra_dc_precision);
101 	reg |= VE_DEC_MPEG_MP12HDR_INTRA_PICTURE_STRUCTURE(pic->picture_structure);
102 	reg |= VE_DEC_MPEG_MP12HDR_TOP_FIELD_FIRST(pic->flags & V4L2_MPEG2_PIC_FLAG_TOP_FIELD_FIRST);
103 	reg |= VE_DEC_MPEG_MP12HDR_FRAME_PRED_FRAME_DCT(pic->flags & V4L2_MPEG2_PIC_FLAG_FRAME_PRED_DCT);
104 	reg |= VE_DEC_MPEG_MP12HDR_CONCEALMENT_MOTION_VECTORS(pic->flags & V4L2_MPEG2_PIC_FLAG_CONCEALMENT_MV);
105 	reg |= VE_DEC_MPEG_MP12HDR_Q_SCALE_TYPE(pic->flags & V4L2_MPEG2_PIC_FLAG_Q_SCALE_TYPE);
106 	reg |= VE_DEC_MPEG_MP12HDR_INTRA_VLC_FORMAT(pic->flags & V4L2_MPEG2_PIC_FLAG_INTRA_VLC);
107 	reg |= VE_DEC_MPEG_MP12HDR_ALTERNATE_SCAN(pic->flags & V4L2_MPEG2_PIC_FLAG_ALT_SCAN);
108 	reg |= VE_DEC_MPEG_MP12HDR_FULL_PEL_FORWARD_VECTOR(0);
109 	reg |= VE_DEC_MPEG_MP12HDR_FULL_PEL_BACKWARD_VECTOR(0);
110 
111 	cedrus_write(dev, VE_DEC_MPEG_MP12HDR, reg);
112 
113 	/* Set frame dimensions. */
114 
115 	reg = VE_DEC_MPEG_PICCODEDSIZE_WIDTH(seq->horizontal_size);
116 	reg |= VE_DEC_MPEG_PICCODEDSIZE_HEIGHT(seq->vertical_size);
117 
118 	cedrus_write(dev, VE_DEC_MPEG_PICCODEDSIZE, reg);
119 
120 	reg = VE_DEC_MPEG_PICBOUNDSIZE_WIDTH(ctx->src_fmt.width);
121 	reg |= VE_DEC_MPEG_PICBOUNDSIZE_HEIGHT(ctx->src_fmt.height);
122 
123 	cedrus_write(dev, VE_DEC_MPEG_PICBOUNDSIZE, reg);
124 
125 	/* Forward and backward prediction reference buffers. */
126 
127 	vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
128 
129 	forward_idx = vb2_find_timestamp(vq, pic->forward_ref_ts, 0);
130 	fwd_luma_addr = cedrus_dst_buf_addr(ctx, forward_idx, 0);
131 	fwd_chroma_addr = cedrus_dst_buf_addr(ctx, forward_idx, 1);
132 
133 	cedrus_write(dev, VE_DEC_MPEG_FWD_REF_LUMA_ADDR, fwd_luma_addr);
134 	cedrus_write(dev, VE_DEC_MPEG_FWD_REF_CHROMA_ADDR, fwd_chroma_addr);
135 
136 	backward_idx = vb2_find_timestamp(vq, pic->backward_ref_ts, 0);
137 	bwd_luma_addr = cedrus_dst_buf_addr(ctx, backward_idx, 0);
138 	bwd_chroma_addr = cedrus_dst_buf_addr(ctx, backward_idx, 1);
139 
140 	cedrus_write(dev, VE_DEC_MPEG_BWD_REF_LUMA_ADDR, bwd_luma_addr);
141 	cedrus_write(dev, VE_DEC_MPEG_BWD_REF_CHROMA_ADDR, bwd_chroma_addr);
142 
143 	/* Destination luma and chroma buffers. */
144 
145 	dst_luma_addr = cedrus_dst_buf_addr(ctx, run->dst->vb2_buf.index, 0);
146 	dst_chroma_addr = cedrus_dst_buf_addr(ctx, run->dst->vb2_buf.index, 1);
147 
148 	cedrus_write(dev, VE_DEC_MPEG_REC_LUMA, dst_luma_addr);
149 	cedrus_write(dev, VE_DEC_MPEG_REC_CHROMA, dst_chroma_addr);
150 
151 	/* Source offset and length in bits. */
152 
153 	cedrus_write(dev, VE_DEC_MPEG_VLD_OFFSET, 0);
154 
155 	reg = vb2_get_plane_payload(&run->src->vb2_buf, 0) * 8;
156 	cedrus_write(dev, VE_DEC_MPEG_VLD_LEN, reg);
157 
158 	/* Source beginning and end addresses. */
159 
160 	src_buf_addr = vb2_dma_contig_plane_dma_addr(&run->src->vb2_buf, 0);
161 
162 	reg = VE_DEC_MPEG_VLD_ADDR_BASE(src_buf_addr);
163 	reg |= VE_DEC_MPEG_VLD_ADDR_VALID_PIC_DATA;
164 	reg |= VE_DEC_MPEG_VLD_ADDR_LAST_PIC_DATA;
165 	reg |= VE_DEC_MPEG_VLD_ADDR_FIRST_PIC_DATA;
166 
167 	cedrus_write(dev, VE_DEC_MPEG_VLD_ADDR, reg);
168 
169 	reg = src_buf_addr + vb2_get_plane_payload(&run->src->vb2_buf, 0);
170 	cedrus_write(dev, VE_DEC_MPEG_VLD_END_ADDR, reg);
171 
172 	/* Macroblock address: start at the beginning. */
173 	reg = VE_DEC_MPEG_MBADDR_Y(0) | VE_DEC_MPEG_MBADDR_X(0);
174 	cedrus_write(dev, VE_DEC_MPEG_MBADDR, reg);
175 
176 	/* Clear previous errors. */
177 	cedrus_write(dev, VE_DEC_MPEG_ERROR, 0);
178 
179 	/* Clear correct macroblocks register. */
180 	cedrus_write(dev, VE_DEC_MPEG_CRTMBADDR, 0);
181 
182 	/* Enable appropriate interruptions and components. */
183 
184 	reg = VE_DEC_MPEG_CTRL_IRQ_MASK | VE_DEC_MPEG_CTRL_MC_NO_WRITEBACK |
185 	      VE_DEC_MPEG_CTRL_MC_CACHE_EN;
186 
187 	cedrus_write(dev, VE_DEC_MPEG_CTRL, reg);
188 }
189 
190 static void cedrus_mpeg2_trigger(struct cedrus_ctx *ctx)
191 {
192 	struct cedrus_dev *dev = ctx->dev;
193 	u32 reg;
194 
195 	/* Trigger MPEG engine. */
196 	reg = VE_DEC_MPEG_TRIGGER_HW_MPEG_VLD | VE_DEC_MPEG_TRIGGER_MPEG2 |
197 	      VE_DEC_MPEG_TRIGGER_MB_BOUNDARY;
198 
199 	cedrus_write(dev, VE_DEC_MPEG_TRIGGER, reg);
200 }
201 
202 struct cedrus_dec_ops cedrus_dec_ops_mpeg2 = {
203 	.irq_clear	= cedrus_mpeg2_irq_clear,
204 	.irq_disable	= cedrus_mpeg2_irq_disable,
205 	.irq_status	= cedrus_mpeg2_irq_status,
206 	.setup		= cedrus_mpeg2_setup,
207 	.trigger	= cedrus_mpeg2_trigger,
208 };
209