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 /* Default MPEG-2 quantization coefficients, from the specification. */ 17 18 static const u8 intra_quantization_matrix_default[64] = { 19 8, 16, 16, 19, 16, 19, 22, 22, 20 22, 22, 22, 22, 26, 24, 26, 27, 21 27, 27, 26, 26, 26, 26, 27, 27, 22 27, 29, 29, 29, 34, 34, 34, 29, 23 29, 29, 27, 27, 29, 29, 32, 32, 24 34, 34, 37, 38, 37, 35, 35, 34, 25 35, 38, 38, 40, 40, 40, 48, 48, 26 46, 46, 56, 56, 58, 69, 69, 83 27 }; 28 29 static const u8 non_intra_quantization_matrix_default[64] = { 30 16, 16, 16, 16, 16, 16, 16, 16, 31 16, 16, 16, 16, 16, 16, 16, 16, 32 16, 16, 16, 16, 16, 16, 16, 16, 33 16, 16, 16, 16, 16, 16, 16, 16, 34 16, 16, 16, 16, 16, 16, 16, 16, 35 16, 16, 16, 16, 16, 16, 16, 16, 36 16, 16, 16, 16, 16, 16, 16, 16, 37 16, 16, 16, 16, 16, 16, 16, 16 38 }; 39 40 static enum cedrus_irq_status cedrus_mpeg2_irq_status(struct cedrus_ctx *ctx) 41 { 42 struct cedrus_dev *dev = ctx->dev; 43 u32 reg; 44 45 reg = cedrus_read(dev, VE_DEC_MPEG_STATUS); 46 reg &= VE_DEC_MPEG_STATUS_CHECK_MASK; 47 48 if (!reg) 49 return CEDRUS_IRQ_NONE; 50 51 if (reg & VE_DEC_MPEG_STATUS_CHECK_ERROR || 52 !(reg & VE_DEC_MPEG_STATUS_SUCCESS)) 53 return CEDRUS_IRQ_ERROR; 54 55 return CEDRUS_IRQ_OK; 56 } 57 58 static void cedrus_mpeg2_irq_clear(struct cedrus_ctx *ctx) 59 { 60 struct cedrus_dev *dev = ctx->dev; 61 62 cedrus_write(dev, VE_DEC_MPEG_STATUS, VE_DEC_MPEG_STATUS_CHECK_MASK); 63 } 64 65 static void cedrus_mpeg2_irq_disable(struct cedrus_ctx *ctx) 66 { 67 struct cedrus_dev *dev = ctx->dev; 68 u32 reg = cedrus_read(dev, VE_DEC_MPEG_CTRL); 69 70 reg &= ~VE_DEC_MPEG_CTRL_IRQ_MASK; 71 72 cedrus_write(dev, VE_DEC_MPEG_CTRL, reg); 73 } 74 75 static void cedrus_mpeg2_setup(struct cedrus_ctx *ctx, struct cedrus_run *run) 76 { 77 const struct v4l2_ctrl_mpeg2_slice_params *slice_params; 78 const struct v4l2_mpeg2_sequence *sequence; 79 const struct v4l2_mpeg2_picture *picture; 80 const struct v4l2_ctrl_mpeg2_quantization *quantization; 81 dma_addr_t src_buf_addr, dst_luma_addr, dst_chroma_addr; 82 dma_addr_t fwd_luma_addr, fwd_chroma_addr; 83 dma_addr_t bwd_luma_addr, bwd_chroma_addr; 84 struct cedrus_dev *dev = ctx->dev; 85 struct vb2_queue *vq; 86 const u8 *matrix; 87 int forward_idx; 88 int backward_idx; 89 unsigned int i; 90 u32 reg; 91 92 slice_params = run->mpeg2.slice_params; 93 sequence = &slice_params->sequence; 94 picture = &slice_params->picture; 95 96 quantization = run->mpeg2.quantization; 97 98 /* Activate MPEG engine. */ 99 cedrus_engine_enable(ctx, CEDRUS_CODEC_MPEG2); 100 101 /* Set intra quantization matrix. */ 102 103 if (quantization && quantization->load_intra_quantiser_matrix) 104 matrix = quantization->intra_quantiser_matrix; 105 else 106 matrix = intra_quantization_matrix_default; 107 108 for (i = 0; i < 64; i++) { 109 reg = VE_DEC_MPEG_IQMINPUT_WEIGHT(i, matrix[i]); 110 reg |= VE_DEC_MPEG_IQMINPUT_FLAG_INTRA; 111 112 cedrus_write(dev, VE_DEC_MPEG_IQMINPUT, reg); 113 } 114 115 /* Set non-intra quantization matrix. */ 116 117 if (quantization && quantization->load_non_intra_quantiser_matrix) 118 matrix = quantization->non_intra_quantiser_matrix; 119 else 120 matrix = non_intra_quantization_matrix_default; 121 122 for (i = 0; i < 64; i++) { 123 reg = VE_DEC_MPEG_IQMINPUT_WEIGHT(i, matrix[i]); 124 reg |= VE_DEC_MPEG_IQMINPUT_FLAG_NON_INTRA; 125 126 cedrus_write(dev, VE_DEC_MPEG_IQMINPUT, reg); 127 } 128 129 /* Set MPEG picture header. */ 130 131 reg = VE_DEC_MPEG_MP12HDR_SLICE_TYPE(picture->picture_coding_type); 132 reg |= VE_DEC_MPEG_MP12HDR_F_CODE(0, 0, picture->f_code[0][0]); 133 reg |= VE_DEC_MPEG_MP12HDR_F_CODE(0, 1, picture->f_code[0][1]); 134 reg |= VE_DEC_MPEG_MP12HDR_F_CODE(1, 0, picture->f_code[1][0]); 135 reg |= VE_DEC_MPEG_MP12HDR_F_CODE(1, 1, picture->f_code[1][1]); 136 reg |= VE_DEC_MPEG_MP12HDR_INTRA_DC_PRECISION(picture->intra_dc_precision); 137 reg |= VE_DEC_MPEG_MP12HDR_INTRA_PICTURE_STRUCTURE(picture->picture_structure); 138 reg |= VE_DEC_MPEG_MP12HDR_TOP_FIELD_FIRST(picture->top_field_first); 139 reg |= VE_DEC_MPEG_MP12HDR_FRAME_PRED_FRAME_DCT(picture->frame_pred_frame_dct); 140 reg |= VE_DEC_MPEG_MP12HDR_CONCEALMENT_MOTION_VECTORS(picture->concealment_motion_vectors); 141 reg |= VE_DEC_MPEG_MP12HDR_Q_SCALE_TYPE(picture->q_scale_type); 142 reg |= VE_DEC_MPEG_MP12HDR_INTRA_VLC_FORMAT(picture->intra_vlc_format); 143 reg |= VE_DEC_MPEG_MP12HDR_ALTERNATE_SCAN(picture->alternate_scan); 144 reg |= VE_DEC_MPEG_MP12HDR_FULL_PEL_FORWARD_VECTOR(0); 145 reg |= VE_DEC_MPEG_MP12HDR_FULL_PEL_BACKWARD_VECTOR(0); 146 147 cedrus_write(dev, VE_DEC_MPEG_MP12HDR, reg); 148 149 /* Set frame dimensions. */ 150 151 reg = VE_DEC_MPEG_PICCODEDSIZE_WIDTH(sequence->horizontal_size); 152 reg |= VE_DEC_MPEG_PICCODEDSIZE_HEIGHT(sequence->vertical_size); 153 154 cedrus_write(dev, VE_DEC_MPEG_PICCODEDSIZE, reg); 155 156 reg = VE_DEC_MPEG_PICBOUNDSIZE_WIDTH(ctx->src_fmt.width); 157 reg |= VE_DEC_MPEG_PICBOUNDSIZE_HEIGHT(ctx->src_fmt.height); 158 159 cedrus_write(dev, VE_DEC_MPEG_PICBOUNDSIZE, reg); 160 161 /* Forward and backward prediction reference buffers. */ 162 163 vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); 164 165 forward_idx = vb2_find_timestamp(vq, slice_params->forward_ref_ts, 0); 166 fwd_luma_addr = cedrus_dst_buf_addr(ctx, forward_idx, 0); 167 fwd_chroma_addr = cedrus_dst_buf_addr(ctx, forward_idx, 1); 168 169 cedrus_write(dev, VE_DEC_MPEG_FWD_REF_LUMA_ADDR, fwd_luma_addr); 170 cedrus_write(dev, VE_DEC_MPEG_FWD_REF_CHROMA_ADDR, fwd_chroma_addr); 171 172 backward_idx = vb2_find_timestamp(vq, slice_params->backward_ref_ts, 0); 173 bwd_luma_addr = cedrus_dst_buf_addr(ctx, backward_idx, 0); 174 bwd_chroma_addr = cedrus_dst_buf_addr(ctx, backward_idx, 1); 175 176 cedrus_write(dev, VE_DEC_MPEG_BWD_REF_LUMA_ADDR, bwd_luma_addr); 177 cedrus_write(dev, VE_DEC_MPEG_BWD_REF_CHROMA_ADDR, bwd_chroma_addr); 178 179 /* Destination luma and chroma buffers. */ 180 181 dst_luma_addr = cedrus_dst_buf_addr(ctx, run->dst->vb2_buf.index, 0); 182 dst_chroma_addr = cedrus_dst_buf_addr(ctx, run->dst->vb2_buf.index, 1); 183 184 cedrus_write(dev, VE_DEC_MPEG_REC_LUMA, dst_luma_addr); 185 cedrus_write(dev, VE_DEC_MPEG_REC_CHROMA, dst_chroma_addr); 186 187 /* Source offset and length in bits. */ 188 189 cedrus_write(dev, VE_DEC_MPEG_VLD_OFFSET, 190 slice_params->data_bit_offset); 191 192 reg = slice_params->bit_size - slice_params->data_bit_offset; 193 cedrus_write(dev, VE_DEC_MPEG_VLD_LEN, reg); 194 195 /* Source beginning and end addresses. */ 196 197 src_buf_addr = vb2_dma_contig_plane_dma_addr(&run->src->vb2_buf, 0); 198 199 reg = VE_DEC_MPEG_VLD_ADDR_BASE(src_buf_addr); 200 reg |= VE_DEC_MPEG_VLD_ADDR_VALID_PIC_DATA; 201 reg |= VE_DEC_MPEG_VLD_ADDR_LAST_PIC_DATA; 202 reg |= VE_DEC_MPEG_VLD_ADDR_FIRST_PIC_DATA; 203 204 cedrus_write(dev, VE_DEC_MPEG_VLD_ADDR, reg); 205 206 reg = src_buf_addr + DIV_ROUND_UP(slice_params->bit_size, 8); 207 cedrus_write(dev, VE_DEC_MPEG_VLD_END_ADDR, reg); 208 209 /* Macroblock address: start at the beginning. */ 210 reg = VE_DEC_MPEG_MBADDR_Y(0) | VE_DEC_MPEG_MBADDR_X(0); 211 cedrus_write(dev, VE_DEC_MPEG_MBADDR, reg); 212 213 /* Clear previous errors. */ 214 cedrus_write(dev, VE_DEC_MPEG_ERROR, 0); 215 216 /* Clear correct macroblocks register. */ 217 cedrus_write(dev, VE_DEC_MPEG_CRTMBADDR, 0); 218 219 /* Enable appropriate interruptions and components. */ 220 221 reg = VE_DEC_MPEG_CTRL_IRQ_MASK | VE_DEC_MPEG_CTRL_MC_NO_WRITEBACK | 222 VE_DEC_MPEG_CTRL_MC_CACHE_EN; 223 224 cedrus_write(dev, VE_DEC_MPEG_CTRL, reg); 225 } 226 227 static void cedrus_mpeg2_trigger(struct cedrus_ctx *ctx) 228 { 229 struct cedrus_dev *dev = ctx->dev; 230 u32 reg; 231 232 /* Trigger MPEG engine. */ 233 reg = VE_DEC_MPEG_TRIGGER_HW_MPEG_VLD | VE_DEC_MPEG_TRIGGER_MPEG2 | 234 VE_DEC_MPEG_TRIGGER_MB_BOUNDARY; 235 236 cedrus_write(dev, VE_DEC_MPEG_TRIGGER, reg); 237 } 238 239 struct cedrus_dec_ops cedrus_dec_ops_mpeg2 = { 240 .irq_clear = cedrus_mpeg2_irq_clear, 241 .irq_disable = cedrus_mpeg2_irq_disable, 242 .irq_status = cedrus_mpeg2_irq_status, 243 .setup = cedrus_mpeg2_setup, 244 .trigger = cedrus_mpeg2_trigger, 245 }; 246