root/drivers/staging/media/sunxi/cedrus/cedrus_mpeg2.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. cedrus_mpeg2_irq_status
  2. cedrus_mpeg2_irq_clear
  3. cedrus_mpeg2_irq_disable
  4. cedrus_mpeg2_setup
  5. cedrus_mpeg2_trigger

   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(dev, 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 };

/* [<][>][^][v][top][bottom][index][help] */