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

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

DEFINITIONS

This source file includes following definitions.
  1. cedrus_h264_write_sram
  2. cedrus_h264_mv_col_buf_addr
  3. cedrus_fill_ref_pic
  4. cedrus_write_frame_list
  5. _cedrus_write_ref_list
  6. cedrus_write_ref_list0
  7. cedrus_write_ref_list1
  8. cedrus_write_scaling_lists
  9. cedrus_write_pred_weight_table
  10. cedrus_set_params
  11. cedrus_h264_irq_status
  12. cedrus_h264_irq_clear
  13. cedrus_h264_irq_disable
  14. cedrus_h264_setup
  15. cedrus_h264_start
  16. cedrus_h264_stop
  17. cedrus_h264_trigger

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  * Cedrus VPU driver
   4  *
   5  * Copyright (c) 2013 Jens Kuske <jenskuske@gmail.com>
   6  * Copyright (c) 2018 Bootlin
   7  */
   8 
   9 #include <linux/types.h>
  10 
  11 #include <media/videobuf2-dma-contig.h>
  12 
  13 #include "cedrus.h"
  14 #include "cedrus_hw.h"
  15 #include "cedrus_regs.h"
  16 
  17 enum cedrus_h264_sram_off {
  18         CEDRUS_SRAM_H264_PRED_WEIGHT_TABLE      = 0x000,
  19         CEDRUS_SRAM_H264_FRAMEBUFFER_LIST       = 0x100,
  20         CEDRUS_SRAM_H264_REF_LIST_0             = 0x190,
  21         CEDRUS_SRAM_H264_REF_LIST_1             = 0x199,
  22         CEDRUS_SRAM_H264_SCALING_LIST_8x8_0     = 0x200,
  23         CEDRUS_SRAM_H264_SCALING_LIST_8x8_1     = 0x210,
  24         CEDRUS_SRAM_H264_SCALING_LIST_4x4       = 0x220,
  25 };
  26 
  27 struct cedrus_h264_sram_ref_pic {
  28         __le32  top_field_order_cnt;
  29         __le32  bottom_field_order_cnt;
  30         __le32  frame_info;
  31         __le32  luma_ptr;
  32         __le32  chroma_ptr;
  33         __le32  mv_col_top_ptr;
  34         __le32  mv_col_bot_ptr;
  35         __le32  reserved;
  36 } __packed;
  37 
  38 #define CEDRUS_H264_FRAME_NUM           18
  39 
  40 #define CEDRUS_NEIGHBOR_INFO_BUF_SIZE   (16 * SZ_1K)
  41 #define CEDRUS_PIC_INFO_BUF_SIZE        (128 * SZ_1K)
  42 
  43 static void cedrus_h264_write_sram(struct cedrus_dev *dev,
  44                                    enum cedrus_h264_sram_off off,
  45                                    const void *data, size_t len)
  46 {
  47         const u32 *buffer = data;
  48         size_t count = DIV_ROUND_UP(len, 4);
  49 
  50         cedrus_write(dev, VE_AVC_SRAM_PORT_OFFSET, off << 2);
  51 
  52         while (count--)
  53                 cedrus_write(dev, VE_AVC_SRAM_PORT_DATA, *buffer++);
  54 }
  55 
  56 static dma_addr_t cedrus_h264_mv_col_buf_addr(struct cedrus_ctx *ctx,
  57                                               unsigned int position,
  58                                               unsigned int field)
  59 {
  60         dma_addr_t addr = ctx->codec.h264.mv_col_buf_dma;
  61 
  62         /* Adjust for the position */
  63         addr += position * ctx->codec.h264.mv_col_buf_field_size * 2;
  64 
  65         /* Adjust for the field */
  66         addr += field * ctx->codec.h264.mv_col_buf_field_size;
  67 
  68         return addr;
  69 }
  70 
  71 static void cedrus_fill_ref_pic(struct cedrus_ctx *ctx,
  72                                 struct cedrus_buffer *buf,
  73                                 unsigned int top_field_order_cnt,
  74                                 unsigned int bottom_field_order_cnt,
  75                                 struct cedrus_h264_sram_ref_pic *pic)
  76 {
  77         struct vb2_buffer *vbuf = &buf->m2m_buf.vb.vb2_buf;
  78         unsigned int position = buf->codec.h264.position;
  79 
  80         pic->top_field_order_cnt = cpu_to_le32(top_field_order_cnt);
  81         pic->bottom_field_order_cnt = cpu_to_le32(bottom_field_order_cnt);
  82         pic->frame_info = cpu_to_le32(buf->codec.h264.pic_type << 8);
  83 
  84         pic->luma_ptr = cpu_to_le32(cedrus_buf_addr(vbuf, &ctx->dst_fmt, 0));
  85         pic->chroma_ptr = cpu_to_le32(cedrus_buf_addr(vbuf, &ctx->dst_fmt, 1));
  86         pic->mv_col_top_ptr =
  87                 cpu_to_le32(cedrus_h264_mv_col_buf_addr(ctx, position, 0));
  88         pic->mv_col_bot_ptr =
  89                 cpu_to_le32(cedrus_h264_mv_col_buf_addr(ctx, position, 1));
  90 }
  91 
  92 static void cedrus_write_frame_list(struct cedrus_ctx *ctx,
  93                                     struct cedrus_run *run)
  94 {
  95         struct cedrus_h264_sram_ref_pic pic_list[CEDRUS_H264_FRAME_NUM];
  96         const struct v4l2_ctrl_h264_decode_params *decode = run->h264.decode_params;
  97         const struct v4l2_ctrl_h264_slice_params *slice = run->h264.slice_params;
  98         const struct v4l2_ctrl_h264_sps *sps = run->h264.sps;
  99         struct vb2_queue *cap_q;
 100         struct cedrus_buffer *output_buf;
 101         struct cedrus_dev *dev = ctx->dev;
 102         unsigned long used_dpbs = 0;
 103         unsigned int position;
 104         unsigned int output = 0;
 105         unsigned int i;
 106 
 107         cap_q = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
 108 
 109         memset(pic_list, 0, sizeof(pic_list));
 110 
 111         for (i = 0; i < ARRAY_SIZE(decode->dpb); i++) {
 112                 const struct v4l2_h264_dpb_entry *dpb = &decode->dpb[i];
 113                 struct cedrus_buffer *cedrus_buf;
 114                 int buf_idx;
 115 
 116                 if (!(dpb->flags & V4L2_H264_DPB_ENTRY_FLAG_VALID))
 117                         continue;
 118 
 119                 buf_idx = vb2_find_timestamp(cap_q, dpb->reference_ts, 0);
 120                 if (buf_idx < 0)
 121                         continue;
 122 
 123                 cedrus_buf = vb2_to_cedrus_buffer(cap_q->bufs[buf_idx]);
 124                 position = cedrus_buf->codec.h264.position;
 125                 used_dpbs |= BIT(position);
 126 
 127                 if (!(dpb->flags & V4L2_H264_DPB_ENTRY_FLAG_ACTIVE))
 128                         continue;
 129 
 130                 cedrus_fill_ref_pic(ctx, cedrus_buf,
 131                                     dpb->top_field_order_cnt,
 132                                     dpb->bottom_field_order_cnt,
 133                                     &pic_list[position]);
 134 
 135                 output = max(position, output);
 136         }
 137 
 138         position = find_next_zero_bit(&used_dpbs, CEDRUS_H264_FRAME_NUM,
 139                                       output);
 140         if (position >= CEDRUS_H264_FRAME_NUM)
 141                 position = find_first_zero_bit(&used_dpbs, CEDRUS_H264_FRAME_NUM);
 142 
 143         output_buf = vb2_to_cedrus_buffer(&run->dst->vb2_buf);
 144         output_buf->codec.h264.position = position;
 145 
 146         if (slice->flags & V4L2_H264_SLICE_FLAG_FIELD_PIC)
 147                 output_buf->codec.h264.pic_type = CEDRUS_H264_PIC_TYPE_FIELD;
 148         else if (sps->flags & V4L2_H264_SPS_FLAG_MB_ADAPTIVE_FRAME_FIELD)
 149                 output_buf->codec.h264.pic_type = CEDRUS_H264_PIC_TYPE_MBAFF;
 150         else
 151                 output_buf->codec.h264.pic_type = CEDRUS_H264_PIC_TYPE_FRAME;
 152 
 153         cedrus_fill_ref_pic(ctx, output_buf,
 154                             decode->top_field_order_cnt,
 155                             decode->bottom_field_order_cnt,
 156                             &pic_list[position]);
 157 
 158         cedrus_h264_write_sram(dev, CEDRUS_SRAM_H264_FRAMEBUFFER_LIST,
 159                                pic_list, sizeof(pic_list));
 160 
 161         cedrus_write(dev, VE_H264_OUTPUT_FRAME_IDX, position);
 162 }
 163 
 164 #define CEDRUS_MAX_REF_IDX      32
 165 
 166 static void _cedrus_write_ref_list(struct cedrus_ctx *ctx,
 167                                    struct cedrus_run *run,
 168                                    const u8 *ref_list, u8 num_ref,
 169                                    enum cedrus_h264_sram_off sram)
 170 {
 171         const struct v4l2_ctrl_h264_decode_params *decode = run->h264.decode_params;
 172         struct vb2_queue *cap_q;
 173         struct cedrus_dev *dev = ctx->dev;
 174         u8 sram_array[CEDRUS_MAX_REF_IDX];
 175         unsigned int i;
 176         size_t size;
 177 
 178         cap_q = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
 179 
 180         memset(sram_array, 0, sizeof(sram_array));
 181 
 182         for (i = 0; i < num_ref; i++) {
 183                 const struct v4l2_h264_dpb_entry *dpb;
 184                 const struct cedrus_buffer *cedrus_buf;
 185                 const struct vb2_v4l2_buffer *ref_buf;
 186                 unsigned int position;
 187                 int buf_idx;
 188                 u8 dpb_idx;
 189 
 190                 dpb_idx = ref_list[i];
 191                 dpb = &decode->dpb[dpb_idx];
 192 
 193                 if (!(dpb->flags & V4L2_H264_DPB_ENTRY_FLAG_ACTIVE))
 194                         continue;
 195 
 196                 buf_idx = vb2_find_timestamp(cap_q, dpb->reference_ts, 0);
 197                 if (buf_idx < 0)
 198                         continue;
 199 
 200                 ref_buf = to_vb2_v4l2_buffer(cap_q->bufs[buf_idx]);
 201                 cedrus_buf = vb2_v4l2_to_cedrus_buffer(ref_buf);
 202                 position = cedrus_buf->codec.h264.position;
 203 
 204                 sram_array[i] |= position << 1;
 205                 if (ref_buf->field == V4L2_FIELD_BOTTOM)
 206                         sram_array[i] |= BIT(0);
 207         }
 208 
 209         size = min_t(size_t, ALIGN(num_ref, 4), sizeof(sram_array));
 210         cedrus_h264_write_sram(dev, sram, &sram_array, size);
 211 }
 212 
 213 static void cedrus_write_ref_list0(struct cedrus_ctx *ctx,
 214                                    struct cedrus_run *run)
 215 {
 216         const struct v4l2_ctrl_h264_slice_params *slice = run->h264.slice_params;
 217 
 218         _cedrus_write_ref_list(ctx, run,
 219                                slice->ref_pic_list0,
 220                                slice->num_ref_idx_l0_active_minus1 + 1,
 221                                CEDRUS_SRAM_H264_REF_LIST_0);
 222 }
 223 
 224 static void cedrus_write_ref_list1(struct cedrus_ctx *ctx,
 225                                    struct cedrus_run *run)
 226 {
 227         const struct v4l2_ctrl_h264_slice_params *slice = run->h264.slice_params;
 228 
 229         _cedrus_write_ref_list(ctx, run,
 230                                slice->ref_pic_list1,
 231                                slice->num_ref_idx_l1_active_minus1 + 1,
 232                                CEDRUS_SRAM_H264_REF_LIST_1);
 233 }
 234 
 235 static void cedrus_write_scaling_lists(struct cedrus_ctx *ctx,
 236                                        struct cedrus_run *run)
 237 {
 238         const struct v4l2_ctrl_h264_scaling_matrix *scaling =
 239                 run->h264.scaling_matrix;
 240         struct cedrus_dev *dev = ctx->dev;
 241 
 242         cedrus_h264_write_sram(dev, CEDRUS_SRAM_H264_SCALING_LIST_8x8_0,
 243                                scaling->scaling_list_8x8[0],
 244                                sizeof(scaling->scaling_list_8x8[0]));
 245 
 246         cedrus_h264_write_sram(dev, CEDRUS_SRAM_H264_SCALING_LIST_8x8_1,
 247                                scaling->scaling_list_8x8[1],
 248                                sizeof(scaling->scaling_list_8x8[1]));
 249 
 250         cedrus_h264_write_sram(dev, CEDRUS_SRAM_H264_SCALING_LIST_4x4,
 251                                scaling->scaling_list_4x4,
 252                                sizeof(scaling->scaling_list_4x4));
 253 }
 254 
 255 static void cedrus_write_pred_weight_table(struct cedrus_ctx *ctx,
 256                                            struct cedrus_run *run)
 257 {
 258         const struct v4l2_ctrl_h264_slice_params *slice =
 259                 run->h264.slice_params;
 260         const struct v4l2_h264_pred_weight_table *pred_weight =
 261                 &slice->pred_weight_table;
 262         struct cedrus_dev *dev = ctx->dev;
 263         int i, j, k;
 264 
 265         cedrus_write(dev, VE_H264_SHS_WP,
 266                      ((pred_weight->chroma_log2_weight_denom & 0x7) << 4) |
 267                      ((pred_weight->luma_log2_weight_denom & 0x7) << 0));
 268 
 269         cedrus_write(dev, VE_AVC_SRAM_PORT_OFFSET,
 270                      CEDRUS_SRAM_H264_PRED_WEIGHT_TABLE << 2);
 271 
 272         for (i = 0; i < ARRAY_SIZE(pred_weight->weight_factors); i++) {
 273                 const struct v4l2_h264_weight_factors *factors =
 274                         &pred_weight->weight_factors[i];
 275 
 276                 for (j = 0; j < ARRAY_SIZE(factors->luma_weight); j++) {
 277                         u32 val;
 278 
 279                         val = (((u32)factors->luma_offset[j] & 0x1ff) << 16) |
 280                                 (factors->luma_weight[j] & 0x1ff);
 281                         cedrus_write(dev, VE_AVC_SRAM_PORT_DATA, val);
 282                 }
 283 
 284                 for (j = 0; j < ARRAY_SIZE(factors->chroma_weight); j++) {
 285                         for (k = 0; k < ARRAY_SIZE(factors->chroma_weight[0]); k++) {
 286                                 u32 val;
 287 
 288                                 val = (((u32)factors->chroma_offset[j][k] & 0x1ff) << 16) |
 289                                         (factors->chroma_weight[j][k] & 0x1ff);
 290                                 cedrus_write(dev, VE_AVC_SRAM_PORT_DATA, val);
 291                         }
 292                 }
 293         }
 294 }
 295 
 296 static void cedrus_set_params(struct cedrus_ctx *ctx,
 297                               struct cedrus_run *run)
 298 {
 299         const struct v4l2_ctrl_h264_decode_params *decode = run->h264.decode_params;
 300         const struct v4l2_ctrl_h264_slice_params *slice = run->h264.slice_params;
 301         const struct v4l2_ctrl_h264_pps *pps = run->h264.pps;
 302         const struct v4l2_ctrl_h264_sps *sps = run->h264.sps;
 303         struct vb2_buffer *src_buf = &run->src->vb2_buf;
 304         struct cedrus_dev *dev = ctx->dev;
 305         dma_addr_t src_buf_addr;
 306         u32 offset = slice->header_bit_size;
 307         u32 len = (slice->size * 8) - offset;
 308         u32 reg;
 309 
 310         cedrus_write(dev, VE_H264_VLD_LEN, len);
 311         cedrus_write(dev, VE_H264_VLD_OFFSET, offset);
 312 
 313         src_buf_addr = vb2_dma_contig_plane_dma_addr(src_buf, 0);
 314         cedrus_write(dev, VE_H264_VLD_END,
 315                      src_buf_addr + vb2_get_plane_payload(src_buf, 0));
 316         cedrus_write(dev, VE_H264_VLD_ADDR,
 317                      VE_H264_VLD_ADDR_VAL(src_buf_addr) |
 318                      VE_H264_VLD_ADDR_FIRST | VE_H264_VLD_ADDR_VALID |
 319                      VE_H264_VLD_ADDR_LAST);
 320 
 321         /*
 322          * FIXME: Since the bitstream parsing is done in software, and
 323          * in userspace, this shouldn't be needed anymore. But it
 324          * turns out that removing it breaks the decoding process,
 325          * without any clear indication why.
 326          */
 327         cedrus_write(dev, VE_H264_TRIGGER_TYPE,
 328                      VE_H264_TRIGGER_TYPE_INIT_SWDEC);
 329 
 330         if (((pps->flags & V4L2_H264_PPS_FLAG_WEIGHTED_PRED) &&
 331              (slice->slice_type == V4L2_H264_SLICE_TYPE_P ||
 332               slice->slice_type == V4L2_H264_SLICE_TYPE_SP)) ||
 333             (pps->weighted_bipred_idc == 1 &&
 334              slice->slice_type == V4L2_H264_SLICE_TYPE_B))
 335                 cedrus_write_pred_weight_table(ctx, run);
 336 
 337         if ((slice->slice_type == V4L2_H264_SLICE_TYPE_P) ||
 338             (slice->slice_type == V4L2_H264_SLICE_TYPE_SP) ||
 339             (slice->slice_type == V4L2_H264_SLICE_TYPE_B))
 340                 cedrus_write_ref_list0(ctx, run);
 341 
 342         if (slice->slice_type == V4L2_H264_SLICE_TYPE_B)
 343                 cedrus_write_ref_list1(ctx, run);
 344 
 345         // picture parameters
 346         reg = 0;
 347         /*
 348          * FIXME: the kernel headers are allowing the default value to
 349          * be passed, but the libva doesn't give us that.
 350          */
 351         reg |= (slice->num_ref_idx_l0_active_minus1 & 0x1f) << 10;
 352         reg |= (slice->num_ref_idx_l1_active_minus1 & 0x1f) << 5;
 353         reg |= (pps->weighted_bipred_idc & 0x3) << 2;
 354         if (pps->flags & V4L2_H264_PPS_FLAG_ENTROPY_CODING_MODE)
 355                 reg |= VE_H264_PPS_ENTROPY_CODING_MODE;
 356         if (pps->flags & V4L2_H264_PPS_FLAG_WEIGHTED_PRED)
 357                 reg |= VE_H264_PPS_WEIGHTED_PRED;
 358         if (pps->flags & V4L2_H264_PPS_FLAG_CONSTRAINED_INTRA_PRED)
 359                 reg |= VE_H264_PPS_CONSTRAINED_INTRA_PRED;
 360         if (pps->flags & V4L2_H264_PPS_FLAG_TRANSFORM_8X8_MODE)
 361                 reg |= VE_H264_PPS_TRANSFORM_8X8_MODE;
 362         cedrus_write(dev, VE_H264_PPS, reg);
 363 
 364         // sequence parameters
 365         reg = 0;
 366         reg |= (sps->chroma_format_idc & 0x7) << 19;
 367         reg |= (sps->pic_width_in_mbs_minus1 & 0xff) << 8;
 368         reg |= sps->pic_height_in_map_units_minus1 & 0xff;
 369         if (sps->flags & V4L2_H264_SPS_FLAG_FRAME_MBS_ONLY)
 370                 reg |= VE_H264_SPS_MBS_ONLY;
 371         if (sps->flags & V4L2_H264_SPS_FLAG_MB_ADAPTIVE_FRAME_FIELD)
 372                 reg |= VE_H264_SPS_MB_ADAPTIVE_FRAME_FIELD;
 373         if (sps->flags & V4L2_H264_SPS_FLAG_DIRECT_8X8_INFERENCE)
 374                 reg |= VE_H264_SPS_DIRECT_8X8_INFERENCE;
 375         cedrus_write(dev, VE_H264_SPS, reg);
 376 
 377         // slice parameters
 378         reg = 0;
 379         reg |= decode->nal_ref_idc ? BIT(12) : 0;
 380         reg |= (slice->slice_type & 0xf) << 8;
 381         reg |= slice->cabac_init_idc & 0x3;
 382         reg |= VE_H264_SHS_FIRST_SLICE_IN_PIC;
 383         if (slice->flags & V4L2_H264_SLICE_FLAG_FIELD_PIC)
 384                 reg |= VE_H264_SHS_FIELD_PIC;
 385         if (slice->flags & V4L2_H264_SLICE_FLAG_BOTTOM_FIELD)
 386                 reg |= VE_H264_SHS_BOTTOM_FIELD;
 387         if (slice->flags & V4L2_H264_SLICE_FLAG_DIRECT_SPATIAL_MV_PRED)
 388                 reg |= VE_H264_SHS_DIRECT_SPATIAL_MV_PRED;
 389         cedrus_write(dev, VE_H264_SHS, reg);
 390 
 391         reg = 0;
 392         reg |= VE_H264_SHS2_NUM_REF_IDX_ACTIVE_OVRD;
 393         reg |= (slice->num_ref_idx_l0_active_minus1 & 0x1f) << 24;
 394         reg |= (slice->num_ref_idx_l1_active_minus1 & 0x1f) << 16;
 395         reg |= (slice->disable_deblocking_filter_idc & 0x3) << 8;
 396         reg |= (slice->slice_alpha_c0_offset_div2 & 0xf) << 4;
 397         reg |= slice->slice_beta_offset_div2 & 0xf;
 398         cedrus_write(dev, VE_H264_SHS2, reg);
 399 
 400         reg = 0;
 401         reg |= (pps->second_chroma_qp_index_offset & 0x3f) << 16;
 402         reg |= (pps->chroma_qp_index_offset & 0x3f) << 8;
 403         reg |= (pps->pic_init_qp_minus26 + 26 + slice->slice_qp_delta) & 0x3f;
 404         cedrus_write(dev, VE_H264_SHS_QP, reg);
 405 
 406         // clear status flags
 407         cedrus_write(dev, VE_H264_STATUS, cedrus_read(dev, VE_H264_STATUS));
 408 
 409         // enable int
 410         cedrus_write(dev, VE_H264_CTRL,
 411                      VE_H264_CTRL_SLICE_DECODE_INT |
 412                      VE_H264_CTRL_DECODE_ERR_INT |
 413                      VE_H264_CTRL_VLD_DATA_REQ_INT);
 414 }
 415 
 416 static enum cedrus_irq_status
 417 cedrus_h264_irq_status(struct cedrus_ctx *ctx)
 418 {
 419         struct cedrus_dev *dev = ctx->dev;
 420         u32 reg = cedrus_read(dev, VE_H264_STATUS);
 421 
 422         if (reg & (VE_H264_STATUS_DECODE_ERR_INT |
 423                    VE_H264_STATUS_VLD_DATA_REQ_INT))
 424                 return CEDRUS_IRQ_ERROR;
 425 
 426         if (reg & VE_H264_CTRL_SLICE_DECODE_INT)
 427                 return CEDRUS_IRQ_OK;
 428 
 429         return CEDRUS_IRQ_NONE;
 430 }
 431 
 432 static void cedrus_h264_irq_clear(struct cedrus_ctx *ctx)
 433 {
 434         struct cedrus_dev *dev = ctx->dev;
 435 
 436         cedrus_write(dev, VE_H264_STATUS,
 437                      VE_H264_STATUS_INT_MASK);
 438 }
 439 
 440 static void cedrus_h264_irq_disable(struct cedrus_ctx *ctx)
 441 {
 442         struct cedrus_dev *dev = ctx->dev;
 443         u32 reg = cedrus_read(dev, VE_H264_CTRL);
 444 
 445         cedrus_write(dev, VE_H264_CTRL,
 446                      reg & ~VE_H264_CTRL_INT_MASK);
 447 }
 448 
 449 static void cedrus_h264_setup(struct cedrus_ctx *ctx,
 450                               struct cedrus_run *run)
 451 {
 452         struct cedrus_dev *dev = ctx->dev;
 453 
 454         cedrus_engine_enable(dev, CEDRUS_CODEC_H264);
 455 
 456         cedrus_write(dev, VE_H264_SDROT_CTRL, 0);
 457         cedrus_write(dev, VE_H264_EXTRA_BUFFER1,
 458                      ctx->codec.h264.pic_info_buf_dma);
 459         cedrus_write(dev, VE_H264_EXTRA_BUFFER2,
 460                      ctx->codec.h264.neighbor_info_buf_dma);
 461 
 462         cedrus_write_scaling_lists(ctx, run);
 463         cedrus_write_frame_list(ctx, run);
 464 
 465         cedrus_set_params(ctx, run);
 466 }
 467 
 468 static int cedrus_h264_start(struct cedrus_ctx *ctx)
 469 {
 470         struct cedrus_dev *dev = ctx->dev;
 471         unsigned int field_size;
 472         unsigned int mv_col_size;
 473         int ret;
 474 
 475         /*
 476          * FIXME: It seems that the H6 cedarX code is using a formula
 477          * here based on the size of the frame, while all the older
 478          * code is using a fixed size, so that might need to be
 479          * changed at some point.
 480          */
 481         ctx->codec.h264.pic_info_buf =
 482                 dma_alloc_coherent(dev->dev, CEDRUS_PIC_INFO_BUF_SIZE,
 483                                    &ctx->codec.h264.pic_info_buf_dma,
 484                                    GFP_KERNEL);
 485         if (!ctx->codec.h264.pic_info_buf)
 486                 return -ENOMEM;
 487 
 488         /*
 489          * That buffer is supposed to be 16kiB in size, and be aligned
 490          * on 16kiB as well. However, dma_alloc_coherent provides the
 491          * guarantee that we'll have a CPU and DMA address aligned on
 492          * the smallest page order that is greater to the requested
 493          * size, so we don't have to overallocate.
 494          */
 495         ctx->codec.h264.neighbor_info_buf =
 496                 dma_alloc_coherent(dev->dev, CEDRUS_NEIGHBOR_INFO_BUF_SIZE,
 497                                    &ctx->codec.h264.neighbor_info_buf_dma,
 498                                    GFP_KERNEL);
 499         if (!ctx->codec.h264.neighbor_info_buf) {
 500                 ret = -ENOMEM;
 501                 goto err_pic_buf;
 502         }
 503 
 504         field_size = DIV_ROUND_UP(ctx->src_fmt.width, 16) *
 505                 DIV_ROUND_UP(ctx->src_fmt.height, 16) * 16;
 506 
 507         /*
 508          * FIXME: This is actually conditional to
 509          * V4L2_H264_SPS_FLAG_DIRECT_8X8_INFERENCE not being set, we
 510          * might have to rework this if memory efficiency ever is
 511          * something we need to work on.
 512          */
 513         field_size = field_size * 2;
 514 
 515         /*
 516          * FIXME: This is actually conditional to
 517          * V4L2_H264_SPS_FLAG_FRAME_MBS_ONLY not being set, we might
 518          * have to rework this if memory efficiency ever is something
 519          * we need to work on.
 520          */
 521         field_size = field_size * 2;
 522         ctx->codec.h264.mv_col_buf_field_size = field_size;
 523 
 524         mv_col_size = field_size * 2 * CEDRUS_H264_FRAME_NUM;
 525         ctx->codec.h264.mv_col_buf_size = mv_col_size;
 526         ctx->codec.h264.mv_col_buf = dma_alloc_coherent(dev->dev,
 527                                                         ctx->codec.h264.mv_col_buf_size,
 528                                                         &ctx->codec.h264.mv_col_buf_dma,
 529                                                         GFP_KERNEL);
 530         if (!ctx->codec.h264.mv_col_buf) {
 531                 ret = -ENOMEM;
 532                 goto err_neighbor_buf;
 533         }
 534 
 535         return 0;
 536 
 537 err_neighbor_buf:
 538         dma_free_coherent(dev->dev, CEDRUS_NEIGHBOR_INFO_BUF_SIZE,
 539                           ctx->codec.h264.neighbor_info_buf,
 540                           ctx->codec.h264.neighbor_info_buf_dma);
 541 
 542 err_pic_buf:
 543         dma_free_coherent(dev->dev, CEDRUS_PIC_INFO_BUF_SIZE,
 544                           ctx->codec.h264.pic_info_buf,
 545                           ctx->codec.h264.pic_info_buf_dma);
 546         return ret;
 547 }
 548 
 549 static void cedrus_h264_stop(struct cedrus_ctx *ctx)
 550 {
 551         struct cedrus_dev *dev = ctx->dev;
 552 
 553         dma_free_coherent(dev->dev, ctx->codec.h264.mv_col_buf_size,
 554                           ctx->codec.h264.mv_col_buf,
 555                           ctx->codec.h264.mv_col_buf_dma);
 556         dma_free_coherent(dev->dev, CEDRUS_NEIGHBOR_INFO_BUF_SIZE,
 557                           ctx->codec.h264.neighbor_info_buf,
 558                           ctx->codec.h264.neighbor_info_buf_dma);
 559         dma_free_coherent(dev->dev, CEDRUS_PIC_INFO_BUF_SIZE,
 560                           ctx->codec.h264.pic_info_buf,
 561                           ctx->codec.h264.pic_info_buf_dma);
 562 }
 563 
 564 static void cedrus_h264_trigger(struct cedrus_ctx *ctx)
 565 {
 566         struct cedrus_dev *dev = ctx->dev;
 567 
 568         cedrus_write(dev, VE_H264_TRIGGER_TYPE,
 569                      VE_H264_TRIGGER_TYPE_AVC_SLICE_DECODE);
 570 }
 571 
 572 struct cedrus_dec_ops cedrus_dec_ops_h264 = {
 573         .irq_clear      = cedrus_h264_irq_clear,
 574         .irq_disable    = cedrus_h264_irq_disable,
 575         .irq_status     = cedrus_h264_irq_status,
 576         .setup          = cedrus_h264_setup,
 577         .start          = cedrus_h264_start,
 578         .stop           = cedrus_h264_stop,
 579         .trigger        = cedrus_h264_trigger,
 580 };

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