1640 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * drivers/media/platform/samsung/mfc5/s5p_mfc_opr_v5.c4 *5 * Samsung MFC (Multi Function Codec - FIMV) driver6 * This file contains hw related functions.7 *8 * Kamil Debski, Copyright (c) 2011 Samsung Electronics9 * http://www.samsung.com/10 */11 12#include "s5p_mfc_common.h"13#include "s5p_mfc_cmd.h"14#include "s5p_mfc_ctrl.h"15#include "s5p_mfc_debug.h"16#include "s5p_mfc_intr.h"17#include "s5p_mfc_pm.h"18#include "s5p_mfc_opr.h"19#include "s5p_mfc_opr_v5.h"20#include <asm/cacheflush.h>21#include <linux/delay.h>22#include <linux/dma-mapping.h>23#include <linux/err.h>24#include <linux/firmware.h>25#include <linux/io.h>26#include <linux/jiffies.h>27#include <linux/mm.h>28#include <linux/sched.h>29 30#define OFFSETA(x) (((x) - dev->dma_base[BANK_L_CTX]) >> MFC_OFFSET_SHIFT)31#define OFFSETB(x) (((x) - dev->dma_base[BANK_R_CTX]) >> MFC_OFFSET_SHIFT)32 33/* Allocate temporary buffers for decoding */34static int s5p_mfc_alloc_dec_temp_buffers_v5(struct s5p_mfc_ctx *ctx)35{36 struct s5p_mfc_dev *dev = ctx->dev;37 const struct s5p_mfc_buf_size_v5 *buf_size = dev->variant->buf_size->priv;38 int ret;39 40 ctx->dsc.size = buf_size->dsc;41 ret = s5p_mfc_alloc_priv_buf(dev, BANK_L_CTX, &ctx->dsc);42 if (ret) {43 mfc_err("Failed to allocate temporary buffer\n");44 return ret;45 }46 47 BUG_ON(ctx->dsc.dma & ((1 << MFC_BANK1_ALIGN_ORDER) - 1));48 memset(ctx->dsc.virt, 0, ctx->dsc.size);49 wmb();50 return 0;51}52 53 54/* Release temporary buffers for decoding */55static void s5p_mfc_release_dec_desc_buffer_v5(struct s5p_mfc_ctx *ctx)56{57 s5p_mfc_release_priv_buf(ctx->dev, &ctx->dsc);58}59 60/* Allocate codec buffers */61static int s5p_mfc_alloc_codec_buffers_v5(struct s5p_mfc_ctx *ctx)62{63 struct s5p_mfc_dev *dev = ctx->dev;64 unsigned int enc_ref_y_size = 0;65 unsigned int enc_ref_c_size = 0;66 unsigned int guard_width, guard_height;67 int ret;68 69 if (ctx->type == MFCINST_DECODER) {70 mfc_debug(2, "Luma size:%d Chroma size:%d MV size:%d\n",71 ctx->luma_size, ctx->chroma_size, ctx->mv_size);72 mfc_debug(2, "Totals bufs: %d\n", ctx->total_dpb_count);73 } else if (ctx->type == MFCINST_ENCODER) {74 enc_ref_y_size = ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN)75 * ALIGN(ctx->img_height, S5P_FIMV_NV12MT_VALIGN);76 enc_ref_y_size = ALIGN(enc_ref_y_size, S5P_FIMV_NV12MT_SALIGN);77 78 if (ctx->codec_mode == S5P_MFC_CODEC_H264_ENC) {79 enc_ref_c_size = ALIGN(ctx->img_width,80 S5P_FIMV_NV12MT_HALIGN)81 * ALIGN(ctx->img_height >> 1,82 S5P_FIMV_NV12MT_VALIGN);83 enc_ref_c_size = ALIGN(enc_ref_c_size,84 S5P_FIMV_NV12MT_SALIGN);85 } else {86 guard_width = ALIGN(ctx->img_width + 16,87 S5P_FIMV_NV12MT_HALIGN);88 guard_height = ALIGN((ctx->img_height >> 1) + 4,89 S5P_FIMV_NV12MT_VALIGN);90 enc_ref_c_size = ALIGN(guard_width * guard_height,91 S5P_FIMV_NV12MT_SALIGN);92 }93 mfc_debug(2, "recon luma size: %d chroma size: %d\n",94 enc_ref_y_size, enc_ref_c_size);95 } else {96 return -EINVAL;97 }98 /* Codecs have different memory requirements */99 switch (ctx->codec_mode) {100 case S5P_MFC_CODEC_H264_DEC:101 ctx->bank1.size =102 ALIGN(S5P_FIMV_DEC_NB_IP_SIZE +103 S5P_FIMV_DEC_VERT_NB_MV_SIZE,104 S5P_FIMV_DEC_BUF_ALIGN);105 ctx->bank2.size = ctx->total_dpb_count * ctx->mv_size;106 break;107 case S5P_MFC_CODEC_MPEG4_DEC:108 ctx->bank1.size =109 ALIGN(S5P_FIMV_DEC_NB_DCAC_SIZE +110 S5P_FIMV_DEC_UPNB_MV_SIZE +111 S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE +112 S5P_FIMV_DEC_STX_PARSER_SIZE +113 S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE,114 S5P_FIMV_DEC_BUF_ALIGN);115 ctx->bank2.size = 0;116 break;117 case S5P_MFC_CODEC_VC1RCV_DEC:118 case S5P_MFC_CODEC_VC1_DEC:119 ctx->bank1.size =120 ALIGN(S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE +121 S5P_FIMV_DEC_UPNB_MV_SIZE +122 S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE +123 S5P_FIMV_DEC_NB_DCAC_SIZE +124 3 * S5P_FIMV_DEC_VC1_BITPLANE_SIZE,125 S5P_FIMV_DEC_BUF_ALIGN);126 ctx->bank2.size = 0;127 break;128 case S5P_MFC_CODEC_MPEG2_DEC:129 ctx->bank1.size = 0;130 ctx->bank2.size = 0;131 break;132 case S5P_MFC_CODEC_H263_DEC:133 ctx->bank1.size =134 ALIGN(S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE +135 S5P_FIMV_DEC_UPNB_MV_SIZE +136 S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE +137 S5P_FIMV_DEC_NB_DCAC_SIZE,138 S5P_FIMV_DEC_BUF_ALIGN);139 ctx->bank2.size = 0;140 break;141 case S5P_MFC_CODEC_H264_ENC:142 ctx->bank1.size = (enc_ref_y_size * 2) +143 S5P_FIMV_ENC_UPMV_SIZE +144 S5P_FIMV_ENC_COLFLG_SIZE +145 S5P_FIMV_ENC_INTRAMD_SIZE +146 S5P_FIMV_ENC_NBORINFO_SIZE;147 ctx->bank2.size = (enc_ref_y_size * 2) +148 (enc_ref_c_size * 4) +149 S5P_FIMV_ENC_INTRAPRED_SIZE;150 break;151 case S5P_MFC_CODEC_MPEG4_ENC:152 ctx->bank1.size = (enc_ref_y_size * 2) +153 S5P_FIMV_ENC_UPMV_SIZE +154 S5P_FIMV_ENC_COLFLG_SIZE +155 S5P_FIMV_ENC_ACDCCOEF_SIZE;156 ctx->bank2.size = (enc_ref_y_size * 2) +157 (enc_ref_c_size * 4);158 break;159 case S5P_MFC_CODEC_H263_ENC:160 ctx->bank1.size = (enc_ref_y_size * 2) +161 S5P_FIMV_ENC_UPMV_SIZE +162 S5P_FIMV_ENC_ACDCCOEF_SIZE;163 ctx->bank2.size = (enc_ref_y_size * 2) +164 (enc_ref_c_size * 4);165 break;166 default:167 break;168 }169 /* Allocate only if memory from bank 1 is necessary */170 if (ctx->bank1.size > 0) {171 172 ret = s5p_mfc_alloc_priv_buf(dev, BANK_L_CTX, &ctx->bank1);173 if (ret) {174 mfc_err("Failed to allocate Bank1 temporary buffer\n");175 return ret;176 }177 BUG_ON(ctx->bank1.dma & ((1 << MFC_BANK1_ALIGN_ORDER) - 1));178 }179 /* Allocate only if memory from bank 2 is necessary */180 if (ctx->bank2.size > 0) {181 ret = s5p_mfc_alloc_priv_buf(dev, BANK_R_CTX, &ctx->bank2);182 if (ret) {183 mfc_err("Failed to allocate Bank2 temporary buffer\n");184 s5p_mfc_release_priv_buf(ctx->dev, &ctx->bank1);185 return ret;186 }187 BUG_ON(ctx->bank2.dma & ((1 << MFC_BANK2_ALIGN_ORDER) - 1));188 }189 return 0;190}191 192/* Release buffers allocated for codec */193static void s5p_mfc_release_codec_buffers_v5(struct s5p_mfc_ctx *ctx)194{195 s5p_mfc_release_priv_buf(ctx->dev, &ctx->bank1);196 s5p_mfc_release_priv_buf(ctx->dev, &ctx->bank2);197}198 199/* Allocate memory for instance data buffer */200static int s5p_mfc_alloc_instance_buffer_v5(struct s5p_mfc_ctx *ctx)201{202 struct s5p_mfc_dev *dev = ctx->dev;203 const struct s5p_mfc_buf_size_v5 *buf_size = dev->variant->buf_size->priv;204 int ret;205 206 if (ctx->codec_mode == S5P_MFC_CODEC_H264_DEC ||207 ctx->codec_mode == S5P_MFC_CODEC_H264_ENC)208 ctx->ctx.size = buf_size->h264_ctx;209 else210 ctx->ctx.size = buf_size->non_h264_ctx;211 212 ret = s5p_mfc_alloc_priv_buf(dev, BANK_L_CTX, &ctx->ctx);213 if (ret) {214 mfc_err("Failed to allocate instance buffer\n");215 return ret;216 }217 ctx->ctx.ofs = OFFSETA(ctx->ctx.dma);218 219 /* Zero content of the allocated memory */220 memset(ctx->ctx.virt, 0, ctx->ctx.size);221 wmb();222 223 /* Initialize shared memory */224 ctx->shm.size = buf_size->shm;225 ret = s5p_mfc_alloc_priv_buf(dev, BANK_L_CTX, &ctx->shm);226 if (ret) {227 mfc_err("Failed to allocate shared memory buffer\n");228 s5p_mfc_release_priv_buf(dev, &ctx->ctx);229 return ret;230 }231 232 /* shared memory offset only keeps the offset from base (port a) */233 ctx->shm.ofs = ctx->shm.dma - dev->dma_base[BANK_L_CTX];234 BUG_ON(ctx->shm.ofs & ((1 << MFC_BANK1_ALIGN_ORDER) - 1));235 236 memset(ctx->shm.virt, 0, buf_size->shm);237 wmb();238 return 0;239}240 241/* Release instance buffer */242static void s5p_mfc_release_instance_buffer_v5(struct s5p_mfc_ctx *ctx)243{244 s5p_mfc_release_priv_buf(ctx->dev, &ctx->ctx);245 s5p_mfc_release_priv_buf(ctx->dev, &ctx->shm);246}247 248static int s5p_mfc_alloc_dev_context_buffer_v5(struct s5p_mfc_dev *dev)249{250 /* NOP */251 252 return 0;253}254 255static void s5p_mfc_release_dev_context_buffer_v5(struct s5p_mfc_dev *dev)256{257 /* NOP */258}259 260static void s5p_mfc_write_info_v5(struct s5p_mfc_ctx *ctx, unsigned int data,261 unsigned int ofs)262{263 *(u32 *)(ctx->shm.virt + ofs) = data;264 wmb();265}266 267static unsigned int s5p_mfc_read_info_v5(struct s5p_mfc_ctx *ctx,268 unsigned long ofs)269{270 rmb();271 return *(u32 *)(ctx->shm.virt + ofs);272}273 274static void s5p_mfc_dec_calc_dpb_size_v5(struct s5p_mfc_ctx *ctx)275{276 unsigned int guard_width, guard_height;277 278 ctx->buf_width = ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN);279 ctx->buf_height = ALIGN(ctx->img_height, S5P_FIMV_NV12MT_VALIGN);280 mfc_debug(2,281 "SEQ Done: Movie dimensions %dx%d, buffer dimensions: %dx%d\n",282 ctx->img_width, ctx->img_height, ctx->buf_width,283 ctx->buf_height);284 285 if (ctx->codec_mode == S5P_MFC_CODEC_H264_DEC) {286 ctx->luma_size = ALIGN(ctx->buf_width * ctx->buf_height,287 S5P_FIMV_DEC_BUF_ALIGN);288 ctx->chroma_size = ALIGN(ctx->buf_width *289 ALIGN((ctx->img_height >> 1),290 S5P_FIMV_NV12MT_VALIGN),291 S5P_FIMV_DEC_BUF_ALIGN);292 ctx->mv_size = ALIGN(ctx->buf_width *293 ALIGN((ctx->buf_height >> 2),294 S5P_FIMV_NV12MT_VALIGN),295 S5P_FIMV_DEC_BUF_ALIGN);296 } else {297 guard_width =298 ALIGN(ctx->img_width + 24, S5P_FIMV_NV12MT_HALIGN);299 guard_height =300 ALIGN(ctx->img_height + 16, S5P_FIMV_NV12MT_VALIGN);301 ctx->luma_size = ALIGN(guard_width * guard_height,302 S5P_FIMV_DEC_BUF_ALIGN);303 304 guard_width =305 ALIGN(ctx->img_width + 16, S5P_FIMV_NV12MT_HALIGN);306 guard_height =307 ALIGN((ctx->img_height >> 1) + 4,308 S5P_FIMV_NV12MT_VALIGN);309 ctx->chroma_size = ALIGN(guard_width * guard_height,310 S5P_FIMV_DEC_BUF_ALIGN);311 312 ctx->mv_size = 0;313 }314}315 316static void s5p_mfc_enc_calc_src_size_v5(struct s5p_mfc_ctx *ctx)317{318 if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12M) {319 ctx->buf_width = ALIGN(ctx->img_width, S5P_FIMV_NV12M_HALIGN);320 321 ctx->luma_size = ALIGN(ctx->img_width, S5P_FIMV_NV12M_HALIGN)322 * ALIGN(ctx->img_height, S5P_FIMV_NV12M_LVALIGN);323 ctx->chroma_size = ALIGN(ctx->img_width, S5P_FIMV_NV12M_HALIGN)324 * ALIGN((ctx->img_height >> 1), S5P_FIMV_NV12M_CVALIGN);325 326 ctx->luma_size = ALIGN(ctx->luma_size, S5P_FIMV_NV12M_SALIGN);327 ctx->chroma_size =328 ALIGN(ctx->chroma_size, S5P_FIMV_NV12M_SALIGN);329 } else if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12MT) {330 ctx->buf_width = ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN);331 332 ctx->luma_size = ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN)333 * ALIGN(ctx->img_height, S5P_FIMV_NV12MT_VALIGN);334 ctx->chroma_size =335 ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN)336 * ALIGN((ctx->img_height >> 1), S5P_FIMV_NV12MT_VALIGN);337 338 ctx->luma_size = ALIGN(ctx->luma_size, S5P_FIMV_NV12MT_SALIGN);339 ctx->chroma_size =340 ALIGN(ctx->chroma_size, S5P_FIMV_NV12MT_SALIGN);341 }342}343 344/* Set registers for decoding temporary buffers */345static void s5p_mfc_set_dec_desc_buffer(struct s5p_mfc_ctx *ctx)346{347 struct s5p_mfc_dev *dev = ctx->dev;348 const struct s5p_mfc_buf_size_v5 *buf_size = dev->variant->buf_size->priv;349 350 mfc_write(dev, OFFSETA(ctx->dsc.dma), S5P_FIMV_SI_CH0_DESC_ADR);351 mfc_write(dev, buf_size->dsc, S5P_FIMV_SI_CH0_DESC_SIZE);352}353 354/* Set registers for shared buffer */355static void s5p_mfc_set_shared_buffer(struct s5p_mfc_ctx *ctx)356{357 struct s5p_mfc_dev *dev = ctx->dev;358 mfc_write(dev, ctx->shm.ofs, S5P_FIMV_SI_CH0_HOST_WR_ADR);359}360 361/* Set registers for decoding stream buffer */362static int s5p_mfc_set_dec_stream_buffer_v5(struct s5p_mfc_ctx *ctx,363 int buf_addr, unsigned int start_num_byte,364 unsigned int buf_size)365{366 struct s5p_mfc_dev *dev = ctx->dev;367 368 mfc_write(dev, OFFSETA(buf_addr), S5P_FIMV_SI_CH0_SB_ST_ADR);369 mfc_write(dev, ctx->dec_src_buf_size, S5P_FIMV_SI_CH0_CPB_SIZE);370 mfc_write(dev, buf_size, S5P_FIMV_SI_CH0_SB_FRM_SIZE);371 s5p_mfc_write_info_v5(ctx, start_num_byte, START_BYTE_NUM);372 return 0;373}374 375/* Set decoding frame buffer */376static int s5p_mfc_set_dec_frame_buffer_v5(struct s5p_mfc_ctx *ctx)377{378 unsigned int frame_size_lu, i;379 unsigned int frame_size_ch, frame_size_mv;380 struct s5p_mfc_dev *dev = ctx->dev;381 unsigned int dpb;382 size_t buf_addr1, buf_addr2;383 int buf_size1, buf_size2;384 385 buf_addr1 = ctx->bank1.dma;386 buf_size1 = ctx->bank1.size;387 buf_addr2 = ctx->bank2.dma;388 buf_size2 = ctx->bank2.size;389 dpb = mfc_read(dev, S5P_FIMV_SI_CH0_DPB_CONF_CTRL) &390 ~S5P_FIMV_DPB_COUNT_MASK;391 mfc_write(dev, ctx->total_dpb_count | dpb,392 S5P_FIMV_SI_CH0_DPB_CONF_CTRL);393 s5p_mfc_set_shared_buffer(ctx);394 switch (ctx->codec_mode) {395 case S5P_MFC_CODEC_H264_DEC:396 mfc_write(dev, OFFSETA(buf_addr1),397 S5P_FIMV_H264_VERT_NB_MV_ADR);398 buf_addr1 += S5P_FIMV_DEC_VERT_NB_MV_SIZE;399 buf_size1 -= S5P_FIMV_DEC_VERT_NB_MV_SIZE;400 mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H264_NB_IP_ADR);401 buf_addr1 += S5P_FIMV_DEC_NB_IP_SIZE;402 buf_size1 -= S5P_FIMV_DEC_NB_IP_SIZE;403 break;404 case S5P_MFC_CODEC_MPEG4_DEC:405 mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_MPEG4_NB_DCAC_ADR);406 buf_addr1 += S5P_FIMV_DEC_NB_DCAC_SIZE;407 buf_size1 -= S5P_FIMV_DEC_NB_DCAC_SIZE;408 mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_MPEG4_UP_NB_MV_ADR);409 buf_addr1 += S5P_FIMV_DEC_UPNB_MV_SIZE;410 buf_size1 -= S5P_FIMV_DEC_UPNB_MV_SIZE;411 mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_MPEG4_SA_MV_ADR);412 buf_addr1 += S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE;413 buf_size1 -= S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE;414 mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_MPEG4_SP_ADR);415 buf_addr1 += S5P_FIMV_DEC_STX_PARSER_SIZE;416 buf_size1 -= S5P_FIMV_DEC_STX_PARSER_SIZE;417 mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_MPEG4_OT_LINE_ADR);418 buf_addr1 += S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE;419 buf_size1 -= S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE;420 break;421 case S5P_MFC_CODEC_H263_DEC:422 mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H263_OT_LINE_ADR);423 buf_addr1 += S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE;424 buf_size1 -= S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE;425 mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H263_UP_NB_MV_ADR);426 buf_addr1 += S5P_FIMV_DEC_UPNB_MV_SIZE;427 buf_size1 -= S5P_FIMV_DEC_UPNB_MV_SIZE;428 mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H263_SA_MV_ADR);429 buf_addr1 += S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE;430 buf_size1 -= S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE;431 mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H263_NB_DCAC_ADR);432 buf_addr1 += S5P_FIMV_DEC_NB_DCAC_SIZE;433 buf_size1 -= S5P_FIMV_DEC_NB_DCAC_SIZE;434 break;435 case S5P_MFC_CODEC_VC1_DEC:436 case S5P_MFC_CODEC_VC1RCV_DEC:437 mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_VC1_NB_DCAC_ADR);438 buf_addr1 += S5P_FIMV_DEC_NB_DCAC_SIZE;439 buf_size1 -= S5P_FIMV_DEC_NB_DCAC_SIZE;440 mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_VC1_OT_LINE_ADR);441 buf_addr1 += S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE;442 buf_size1 -= S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE;443 mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_VC1_UP_NB_MV_ADR);444 buf_addr1 += S5P_FIMV_DEC_UPNB_MV_SIZE;445 buf_size1 -= S5P_FIMV_DEC_UPNB_MV_SIZE;446 mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_VC1_SA_MV_ADR);447 buf_addr1 += S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE;448 buf_size1 -= S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE;449 mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_VC1_BITPLANE3_ADR);450 buf_addr1 += S5P_FIMV_DEC_VC1_BITPLANE_SIZE;451 buf_size1 -= S5P_FIMV_DEC_VC1_BITPLANE_SIZE;452 mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_VC1_BITPLANE2_ADR);453 buf_addr1 += S5P_FIMV_DEC_VC1_BITPLANE_SIZE;454 buf_size1 -= S5P_FIMV_DEC_VC1_BITPLANE_SIZE;455 mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_VC1_BITPLANE1_ADR);456 buf_addr1 += S5P_FIMV_DEC_VC1_BITPLANE_SIZE;457 buf_size1 -= S5P_FIMV_DEC_VC1_BITPLANE_SIZE;458 break;459 case S5P_MFC_CODEC_MPEG2_DEC:460 break;461 default:462 mfc_err("Unknown codec for decoding (%x)\n",463 ctx->codec_mode);464 return -EINVAL;465 }466 frame_size_lu = ctx->luma_size;467 frame_size_ch = ctx->chroma_size;468 frame_size_mv = ctx->mv_size;469 mfc_debug(2, "Frm size: %d ch: %d mv: %d\n", frame_size_lu, frame_size_ch,470 frame_size_mv);471 for (i = 0; i < ctx->total_dpb_count; i++) {472 /* Bank2 */473 mfc_debug(2, "Luma %d: %zx\n", i,474 ctx->dst_bufs[i].cookie.raw.luma);475 mfc_write(dev, OFFSETB(ctx->dst_bufs[i].cookie.raw.luma),476 S5P_FIMV_DEC_LUMA_ADR + i * 4);477 mfc_debug(2, "\tChroma %d: %zx\n", i,478 ctx->dst_bufs[i].cookie.raw.chroma);479 mfc_write(dev, OFFSETA(ctx->dst_bufs[i].cookie.raw.chroma),480 S5P_FIMV_DEC_CHROMA_ADR + i * 4);481 if (ctx->codec_mode == S5P_MFC_CODEC_H264_DEC) {482 mfc_debug(2, "\tBuf2: %zx, size: %d\n",483 buf_addr2, buf_size2);484 mfc_write(dev, OFFSETB(buf_addr2),485 S5P_FIMV_H264_MV_ADR + i * 4);486 buf_addr2 += frame_size_mv;487 buf_size2 -= frame_size_mv;488 }489 }490 mfc_debug(2, "Buf1: %zu, buf_size1: %d\n", buf_addr1, buf_size1);491 mfc_debug(2, "Buf 1/2 size after: %d/%d (frames %d)\n",492 buf_size1, buf_size2, ctx->total_dpb_count);493 if (buf_size1 < 0 || buf_size2 < 0) {494 mfc_debug(2, "Not enough memory has been allocated\n");495 return -ENOMEM;496 }497 s5p_mfc_write_info_v5(ctx, frame_size_lu, ALLOC_LUMA_DPB_SIZE);498 s5p_mfc_write_info_v5(ctx, frame_size_ch, ALLOC_CHROMA_DPB_SIZE);499 if (ctx->codec_mode == S5P_MFC_CODEC_H264_DEC)500 s5p_mfc_write_info_v5(ctx, frame_size_mv, ALLOC_MV_SIZE);501 mfc_write(dev, ((S5P_FIMV_CH_INIT_BUFS & S5P_FIMV_CH_MASK)502 << S5P_FIMV_CH_SHIFT) | (ctx->inst_no),503 S5P_FIMV_SI_CH0_INST_ID);504 return 0;505}506 507/* Set registers for encoding stream buffer */508static int s5p_mfc_set_enc_stream_buffer_v5(struct s5p_mfc_ctx *ctx,509 unsigned long addr, unsigned int size)510{511 struct s5p_mfc_dev *dev = ctx->dev;512 513 mfc_write(dev, OFFSETA(addr), S5P_FIMV_ENC_SI_CH0_SB_ADR);514 mfc_write(dev, size, S5P_FIMV_ENC_SI_CH0_SB_SIZE);515 return 0;516}517 518static void s5p_mfc_set_enc_frame_buffer_v5(struct s5p_mfc_ctx *ctx,519 unsigned long y_addr, unsigned long c_addr,520 unsigned long c_1_addr)521{522 struct s5p_mfc_dev *dev = ctx->dev;523 524 mfc_write(dev, OFFSETB(y_addr), S5P_FIMV_ENC_SI_CH0_CUR_Y_ADR);525 mfc_write(dev, OFFSETB(c_addr), S5P_FIMV_ENC_SI_CH0_CUR_C_ADR);526}527 528static void s5p_mfc_get_enc_frame_buffer_v5(struct s5p_mfc_ctx *ctx,529 unsigned long *y_addr, unsigned long *c_addr,530 unsigned long *c_1_addr)531{532 struct s5p_mfc_dev *dev = ctx->dev;533 534 *y_addr = dev->dma_base[BANK_R_CTX] +535 (mfc_read(dev, S5P_FIMV_ENCODED_Y_ADDR) << MFC_OFFSET_SHIFT);536 *c_addr = dev->dma_base[BANK_R_CTX] +537 (mfc_read(dev, S5P_FIMV_ENCODED_C_ADDR) << MFC_OFFSET_SHIFT);538}539 540/* Set encoding ref & codec buffer */541static int s5p_mfc_set_enc_ref_buffer_v5(struct s5p_mfc_ctx *ctx)542{543 struct s5p_mfc_dev *dev = ctx->dev;544 size_t buf_addr1, buf_addr2;545 size_t buf_size1, buf_size2;546 unsigned int enc_ref_y_size, enc_ref_c_size;547 unsigned int guard_width, guard_height;548 int i;549 550 buf_addr1 = ctx->bank1.dma;551 buf_size1 = ctx->bank1.size;552 buf_addr2 = ctx->bank2.dma;553 buf_size2 = ctx->bank2.size;554 enc_ref_y_size = ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN)555 * ALIGN(ctx->img_height, S5P_FIMV_NV12MT_VALIGN);556 enc_ref_y_size = ALIGN(enc_ref_y_size, S5P_FIMV_NV12MT_SALIGN);557 if (ctx->codec_mode == S5P_MFC_CODEC_H264_ENC) {558 enc_ref_c_size = ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN)559 * ALIGN((ctx->img_height >> 1), S5P_FIMV_NV12MT_VALIGN);560 enc_ref_c_size = ALIGN(enc_ref_c_size, S5P_FIMV_NV12MT_SALIGN);561 } else {562 guard_width = ALIGN(ctx->img_width + 16,563 S5P_FIMV_NV12MT_HALIGN);564 guard_height = ALIGN((ctx->img_height >> 1) + 4,565 S5P_FIMV_NV12MT_VALIGN);566 enc_ref_c_size = ALIGN(guard_width * guard_height,567 S5P_FIMV_NV12MT_SALIGN);568 }569 mfc_debug(2, "buf_size1: %zu, buf_size2: %zu\n", buf_size1, buf_size2);570 switch (ctx->codec_mode) {571 case S5P_MFC_CODEC_H264_ENC:572 for (i = 0; i < 2; i++) {573 mfc_write(dev, OFFSETA(buf_addr1),574 S5P_FIMV_ENC_REF0_LUMA_ADR + (4 * i));575 buf_addr1 += enc_ref_y_size;576 buf_size1 -= enc_ref_y_size;577 578 mfc_write(dev, OFFSETB(buf_addr2),579 S5P_FIMV_ENC_REF2_LUMA_ADR + (4 * i));580 buf_addr2 += enc_ref_y_size;581 buf_size2 -= enc_ref_y_size;582 }583 for (i = 0; i < 4; i++) {584 mfc_write(dev, OFFSETB(buf_addr2),585 S5P_FIMV_ENC_REF0_CHROMA_ADR + (4 * i));586 buf_addr2 += enc_ref_c_size;587 buf_size2 -= enc_ref_c_size;588 }589 mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H264_UP_MV_ADR);590 buf_addr1 += S5P_FIMV_ENC_UPMV_SIZE;591 buf_size1 -= S5P_FIMV_ENC_UPMV_SIZE;592 mfc_write(dev, OFFSETA(buf_addr1),593 S5P_FIMV_H264_COZERO_FLAG_ADR);594 buf_addr1 += S5P_FIMV_ENC_COLFLG_SIZE;595 buf_size1 -= S5P_FIMV_ENC_COLFLG_SIZE;596 mfc_write(dev, OFFSETA(buf_addr1),597 S5P_FIMV_H264_UP_INTRA_MD_ADR);598 buf_addr1 += S5P_FIMV_ENC_INTRAMD_SIZE;599 buf_size1 -= S5P_FIMV_ENC_INTRAMD_SIZE;600 mfc_write(dev, OFFSETB(buf_addr2),601 S5P_FIMV_H264_UP_INTRA_PRED_ADR);602 buf_addr2 += S5P_FIMV_ENC_INTRAPRED_SIZE;603 buf_size2 -= S5P_FIMV_ENC_INTRAPRED_SIZE;604 mfc_write(dev, OFFSETA(buf_addr1),605 S5P_FIMV_H264_NBOR_INFO_ADR);606 buf_addr1 += S5P_FIMV_ENC_NBORINFO_SIZE;607 buf_size1 -= S5P_FIMV_ENC_NBORINFO_SIZE;608 mfc_debug(2, "buf_size1: %zu, buf_size2: %zu\n",609 buf_size1, buf_size2);610 break;611 case S5P_MFC_CODEC_MPEG4_ENC:612 for (i = 0; i < 2; i++) {613 mfc_write(dev, OFFSETA(buf_addr1),614 S5P_FIMV_ENC_REF0_LUMA_ADR + (4 * i));615 buf_addr1 += enc_ref_y_size;616 buf_size1 -= enc_ref_y_size;617 mfc_write(dev, OFFSETB(buf_addr2),618 S5P_FIMV_ENC_REF2_LUMA_ADR + (4 * i));619 buf_addr2 += enc_ref_y_size;620 buf_size2 -= enc_ref_y_size;621 }622 for (i = 0; i < 4; i++) {623 mfc_write(dev, OFFSETB(buf_addr2),624 S5P_FIMV_ENC_REF0_CHROMA_ADR + (4 * i));625 buf_addr2 += enc_ref_c_size;626 buf_size2 -= enc_ref_c_size;627 }628 mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_MPEG4_UP_MV_ADR);629 buf_addr1 += S5P_FIMV_ENC_UPMV_SIZE;630 buf_size1 -= S5P_FIMV_ENC_UPMV_SIZE;631 mfc_write(dev, OFFSETA(buf_addr1),632 S5P_FIMV_MPEG4_COZERO_FLAG_ADR);633 buf_addr1 += S5P_FIMV_ENC_COLFLG_SIZE;634 buf_size1 -= S5P_FIMV_ENC_COLFLG_SIZE;635 mfc_write(dev, OFFSETA(buf_addr1),636 S5P_FIMV_MPEG4_ACDC_COEF_ADR);637 buf_addr1 += S5P_FIMV_ENC_ACDCCOEF_SIZE;638 buf_size1 -= S5P_FIMV_ENC_ACDCCOEF_SIZE;639 mfc_debug(2, "buf_size1: %zu, buf_size2: %zu\n",640 buf_size1, buf_size2);641 break;642 case S5P_MFC_CODEC_H263_ENC:643 for (i = 0; i < 2; i++) {644 mfc_write(dev, OFFSETA(buf_addr1),645 S5P_FIMV_ENC_REF0_LUMA_ADR + (4 * i));646 buf_addr1 += enc_ref_y_size;647 buf_size1 -= enc_ref_y_size;648 mfc_write(dev, OFFSETB(buf_addr2),649 S5P_FIMV_ENC_REF2_LUMA_ADR + (4 * i));650 buf_addr2 += enc_ref_y_size;651 buf_size2 -= enc_ref_y_size;652 }653 for (i = 0; i < 4; i++) {654 mfc_write(dev, OFFSETB(buf_addr2),655 S5P_FIMV_ENC_REF0_CHROMA_ADR + (4 * i));656 buf_addr2 += enc_ref_c_size;657 buf_size2 -= enc_ref_c_size;658 }659 mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H263_UP_MV_ADR);660 buf_addr1 += S5P_FIMV_ENC_UPMV_SIZE;661 buf_size1 -= S5P_FIMV_ENC_UPMV_SIZE;662 mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H263_ACDC_COEF_ADR);663 buf_addr1 += S5P_FIMV_ENC_ACDCCOEF_SIZE;664 buf_size1 -= S5P_FIMV_ENC_ACDCCOEF_SIZE;665 mfc_debug(2, "buf_size1: %zu, buf_size2: %zu\n",666 buf_size1, buf_size2);667 break;668 default:669 mfc_err("Unknown codec set for encoding: %d\n",670 ctx->codec_mode);671 return -EINVAL;672 }673 return 0;674}675 676static int s5p_mfc_set_enc_params(struct s5p_mfc_ctx *ctx)677{678 struct s5p_mfc_dev *dev = ctx->dev;679 const struct s5p_mfc_enc_params *p = &ctx->enc_params;680 unsigned int reg;681 unsigned int shm;682 683 /* width */684 mfc_write(dev, ctx->img_width, S5P_FIMV_ENC_HSIZE_PX);685 /* height */686 mfc_write(dev, ctx->img_height, S5P_FIMV_ENC_VSIZE_PX);687 /* pictype : enable, IDR period */688 reg = mfc_read(dev, S5P_FIMV_ENC_PIC_TYPE_CTRL);689 reg |= (1 << 18);690 reg &= ~(0xFFFF);691 reg |= p->gop_size;692 mfc_write(dev, reg, S5P_FIMV_ENC_PIC_TYPE_CTRL);693 mfc_write(dev, 0, S5P_FIMV_ENC_B_RECON_WRITE_ON);694 /* multi-slice control */695 /* multi-slice MB number or bit size */696 mfc_write(dev, p->slice_mode, S5P_FIMV_ENC_MSLICE_CTRL);697 if (p->slice_mode == V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_MB) {698 mfc_write(dev, p->slice_mb, S5P_FIMV_ENC_MSLICE_MB);699 } else if (p->slice_mode == V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_BYTES) {700 mfc_write(dev, p->slice_bit, S5P_FIMV_ENC_MSLICE_BIT);701 } else {702 mfc_write(dev, 0, S5P_FIMV_ENC_MSLICE_MB);703 mfc_write(dev, 0, S5P_FIMV_ENC_MSLICE_BIT);704 }705 /* cyclic intra refresh */706 mfc_write(dev, p->intra_refresh_mb, S5P_FIMV_ENC_CIR_CTRL);707 /* memory structure cur. frame */708 if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12M)709 mfc_write(dev, 0, S5P_FIMV_ENC_MAP_FOR_CUR);710 else if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12MT)711 mfc_write(dev, 3, S5P_FIMV_ENC_MAP_FOR_CUR);712 /* padding control & value */713 reg = mfc_read(dev, S5P_FIMV_ENC_PADDING_CTRL);714 if (p->pad) {715 /** enable */716 reg |= (1UL << 31);717 /** cr value */718 reg &= ~(0xFF << 16);719 reg |= (p->pad_cr << 16);720 /** cb value */721 reg &= ~(0xFF << 8);722 reg |= (p->pad_cb << 8);723 /** y value */724 reg &= ~(0xFF);725 reg |= (p->pad_luma);726 } else {727 /** disable & all value clear */728 reg = 0;729 }730 mfc_write(dev, reg, S5P_FIMV_ENC_PADDING_CTRL);731 /* rate control config. */732 reg = mfc_read(dev, S5P_FIMV_ENC_RC_CONFIG);733 /** frame-level rate control */734 reg &= ~(0x1 << 9);735 reg |= (p->rc_frame << 9);736 mfc_write(dev, reg, S5P_FIMV_ENC_RC_CONFIG);737 /* bit rate */738 if (p->rc_frame)739 mfc_write(dev, p->rc_bitrate,740 S5P_FIMV_ENC_RC_BIT_RATE);741 else742 mfc_write(dev, 0, S5P_FIMV_ENC_RC_BIT_RATE);743 /* reaction coefficient */744 if (p->rc_frame)745 mfc_write(dev, p->rc_reaction_coeff, S5P_FIMV_ENC_RC_RPARA);746 shm = s5p_mfc_read_info_v5(ctx, EXT_ENC_CONTROL);747 /* seq header ctrl */748 shm &= ~(0x1 << 3);749 shm |= (p->seq_hdr_mode << 3);750 /* frame skip mode */751 shm &= ~(0x3 << 1);752 shm |= (p->frame_skip_mode << 1);753 s5p_mfc_write_info_v5(ctx, shm, EXT_ENC_CONTROL);754 /* fixed target bit */755 s5p_mfc_write_info_v5(ctx, p->fixed_target_bit, RC_CONTROL_CONFIG);756 return 0;757}758 759static int s5p_mfc_set_enc_params_h264(struct s5p_mfc_ctx *ctx)760{761 struct s5p_mfc_dev *dev = ctx->dev;762 const struct s5p_mfc_enc_params *p = &ctx->enc_params;763 const struct s5p_mfc_h264_enc_params *p_264 = &p->codec.h264;764 unsigned int reg;765 unsigned int shm;766 767 s5p_mfc_set_enc_params(ctx);768 /* pictype : number of B */769 reg = mfc_read(dev, S5P_FIMV_ENC_PIC_TYPE_CTRL);770 /* num_b_frame - 0 ~ 2 */771 reg &= ~(0x3 << 16);772 reg |= (p->num_b_frame << 16);773 mfc_write(dev, reg, S5P_FIMV_ENC_PIC_TYPE_CTRL);774 /* profile & level */775 reg = mfc_read(dev, S5P_FIMV_ENC_PROFILE);776 /* level */777 reg &= ~(0xFF << 8);778 reg |= (p_264->level << 8);779 /* profile - 0 ~ 2 */780 reg &= ~(0x3F);781 reg |= p_264->profile;782 mfc_write(dev, reg, S5P_FIMV_ENC_PROFILE);783 /* interlace */784 mfc_write(dev, p_264->interlace, S5P_FIMV_ENC_PIC_STRUCT);785 /* height */786 if (p_264->interlace)787 mfc_write(dev, ctx->img_height >> 1, S5P_FIMV_ENC_VSIZE_PX);788 /* loopfilter ctrl */789 mfc_write(dev, p_264->loop_filter_mode, S5P_FIMV_ENC_LF_CTRL);790 /* loopfilter alpha offset */791 if (p_264->loop_filter_alpha < 0) {792 reg = 0x10;793 reg |= (0xFF - p_264->loop_filter_alpha) + 1;794 } else {795 reg = 0x00;796 reg |= (p_264->loop_filter_alpha & 0xF);797 }798 mfc_write(dev, reg, S5P_FIMV_ENC_ALPHA_OFF);799 /* loopfilter beta offset */800 if (p_264->loop_filter_beta < 0) {801 reg = 0x10;802 reg |= (0xFF - p_264->loop_filter_beta) + 1;803 } else {804 reg = 0x00;805 reg |= (p_264->loop_filter_beta & 0xF);806 }807 mfc_write(dev, reg, S5P_FIMV_ENC_BETA_OFF);808 /* entropy coding mode */809 if (p_264->entropy_mode == V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC)810 mfc_write(dev, 1, S5P_FIMV_ENC_H264_ENTROPY_MODE);811 else812 mfc_write(dev, 0, S5P_FIMV_ENC_H264_ENTROPY_MODE);813 /* number of ref. picture */814 reg = mfc_read(dev, S5P_FIMV_ENC_H264_NUM_OF_REF);815 /* num of ref. pictures of P */816 reg &= ~(0x3 << 5);817 reg |= (p_264->num_ref_pic_4p << 5);818 /* max number of ref. pictures */819 reg &= ~(0x1F);820 reg |= p_264->max_ref_pic;821 mfc_write(dev, reg, S5P_FIMV_ENC_H264_NUM_OF_REF);822 /* 8x8 transform enable */823 mfc_write(dev, p_264->_8x8_transform, S5P_FIMV_ENC_H264_TRANS_FLAG);824 /* rate control config. */825 reg = mfc_read(dev, S5P_FIMV_ENC_RC_CONFIG);826 /* macroblock level rate control */827 reg &= ~(0x1 << 8);828 reg |= (p->rc_mb << 8);829 /* frame QP */830 reg &= ~(0x3F);831 reg |= p_264->rc_frame_qp;832 mfc_write(dev, reg, S5P_FIMV_ENC_RC_CONFIG);833 /* frame rate */834 if (p->rc_frame && p->rc_framerate_denom)835 mfc_write(dev, p->rc_framerate_num * 1000836 / p->rc_framerate_denom, S5P_FIMV_ENC_RC_FRAME_RATE);837 else838 mfc_write(dev, 0, S5P_FIMV_ENC_RC_FRAME_RATE);839 /* max & min value of QP */840 reg = mfc_read(dev, S5P_FIMV_ENC_RC_QBOUND);841 /* max QP */842 reg &= ~(0x3F << 8);843 reg |= (p_264->rc_max_qp << 8);844 /* min QP */845 reg &= ~(0x3F);846 reg |= p_264->rc_min_qp;847 mfc_write(dev, reg, S5P_FIMV_ENC_RC_QBOUND);848 /* macroblock adaptive scaling features */849 if (p->rc_mb) {850 reg = mfc_read(dev, S5P_FIMV_ENC_RC_MB_CTRL);851 /* dark region */852 reg &= ~(0x1 << 3);853 reg |= (p_264->rc_mb_dark << 3);854 /* smooth region */855 reg &= ~(0x1 << 2);856 reg |= (p_264->rc_mb_smooth << 2);857 /* static region */858 reg &= ~(0x1 << 1);859 reg |= (p_264->rc_mb_static << 1);860 /* high activity region */861 reg &= ~(0x1);862 reg |= p_264->rc_mb_activity;863 mfc_write(dev, reg, S5P_FIMV_ENC_RC_MB_CTRL);864 }865 if (!p->rc_frame && !p->rc_mb) {866 shm = s5p_mfc_read_info_v5(ctx, P_B_FRAME_QP);867 shm &= ~(0xFFF);868 shm |= ((p_264->rc_b_frame_qp & 0x3F) << 6);869 shm |= (p_264->rc_p_frame_qp & 0x3F);870 s5p_mfc_write_info_v5(ctx, shm, P_B_FRAME_QP);871 }872 /* extended encoder ctrl */873 shm = s5p_mfc_read_info_v5(ctx, EXT_ENC_CONTROL);874 /* AR VUI control */875 shm &= ~(0x1 << 15);876 shm |= (p_264->vui_sar << 1);877 s5p_mfc_write_info_v5(ctx, shm, EXT_ENC_CONTROL);878 if (p_264->vui_sar) {879 /* aspect ration IDC */880 shm = s5p_mfc_read_info_v5(ctx, SAMPLE_ASPECT_RATIO_IDC);881 shm &= ~(0xFF);882 shm |= p_264->vui_sar_idc;883 s5p_mfc_write_info_v5(ctx, shm, SAMPLE_ASPECT_RATIO_IDC);884 if (p_264->vui_sar_idc == 0xFF) {885 /* sample AR info */886 shm = s5p_mfc_read_info_v5(ctx, EXTENDED_SAR);887 shm &= ~(0xFFFFFFFF);888 shm |= p_264->vui_ext_sar_width << 16;889 shm |= p_264->vui_ext_sar_height;890 s5p_mfc_write_info_v5(ctx, shm, EXTENDED_SAR);891 }892 }893 /* intra picture period for H.264 */894 shm = s5p_mfc_read_info_v5(ctx, H264_I_PERIOD);895 /* control */896 shm &= ~(0x1 << 16);897 shm |= (p_264->open_gop << 16);898 /* value */899 if (p_264->open_gop) {900 shm &= ~(0xFFFF);901 shm |= p_264->open_gop_size;902 }903 s5p_mfc_write_info_v5(ctx, shm, H264_I_PERIOD);904 /* extended encoder ctrl */905 shm = s5p_mfc_read_info_v5(ctx, EXT_ENC_CONTROL);906 /* vbv buffer size */907 if (p->frame_skip_mode ==908 V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT) {909 shm &= ~(0xFFFF << 16);910 shm |= (p_264->cpb_size << 16);911 }912 s5p_mfc_write_info_v5(ctx, shm, EXT_ENC_CONTROL);913 return 0;914}915 916static int s5p_mfc_set_enc_params_mpeg4(struct s5p_mfc_ctx *ctx)917{918 struct s5p_mfc_dev *dev = ctx->dev;919 const struct s5p_mfc_enc_params *p = &ctx->enc_params;920 const struct s5p_mfc_mpeg4_enc_params *p_mpeg4 = &p->codec.mpeg4;921 unsigned int reg;922 unsigned int shm;923 unsigned int framerate;924 925 s5p_mfc_set_enc_params(ctx);926 /* pictype : number of B */927 reg = mfc_read(dev, S5P_FIMV_ENC_PIC_TYPE_CTRL);928 /* num_b_frame - 0 ~ 2 */929 reg &= ~(0x3 << 16);930 reg |= (p->num_b_frame << 16);931 mfc_write(dev, reg, S5P_FIMV_ENC_PIC_TYPE_CTRL);932 /* profile & level */933 reg = mfc_read(dev, S5P_FIMV_ENC_PROFILE);934 /* level */935 reg &= ~(0xFF << 8);936 reg |= (p_mpeg4->level << 8);937 /* profile - 0 ~ 2 */938 reg &= ~(0x3F);939 reg |= p_mpeg4->profile;940 mfc_write(dev, reg, S5P_FIMV_ENC_PROFILE);941 /* quarter_pixel */942 mfc_write(dev, p_mpeg4->quarter_pixel, S5P_FIMV_ENC_MPEG4_QUART_PXL);943 /* qp */944 if (!p->rc_frame) {945 shm = s5p_mfc_read_info_v5(ctx, P_B_FRAME_QP);946 shm &= ~(0xFFF);947 shm |= ((p_mpeg4->rc_b_frame_qp & 0x3F) << 6);948 shm |= (p_mpeg4->rc_p_frame_qp & 0x3F);949 s5p_mfc_write_info_v5(ctx, shm, P_B_FRAME_QP);950 }951 /* frame rate */952 if (p->rc_frame) {953 if (p->rc_framerate_denom > 0) {954 framerate = p->rc_framerate_num * 1000 /955 p->rc_framerate_denom;956 mfc_write(dev, framerate,957 S5P_FIMV_ENC_RC_FRAME_RATE);958 shm = s5p_mfc_read_info_v5(ctx, RC_VOP_TIMING);959 shm &= ~(0xFFFFFFFF);960 shm |= (1UL << 31);961 shm |= ((p->rc_framerate_num & 0x7FFF) << 16);962 shm |= (p->rc_framerate_denom & 0xFFFF);963 s5p_mfc_write_info_v5(ctx, shm, RC_VOP_TIMING);964 }965 } else {966 mfc_write(dev, 0, S5P_FIMV_ENC_RC_FRAME_RATE);967 }968 /* rate control config. */969 reg = mfc_read(dev, S5P_FIMV_ENC_RC_CONFIG);970 /* frame QP */971 reg &= ~(0x3F);972 reg |= p_mpeg4->rc_frame_qp;973 mfc_write(dev, reg, S5P_FIMV_ENC_RC_CONFIG);974 /* max & min value of QP */975 reg = mfc_read(dev, S5P_FIMV_ENC_RC_QBOUND);976 /* max QP */977 reg &= ~(0x3F << 8);978 reg |= (p_mpeg4->rc_max_qp << 8);979 /* min QP */980 reg &= ~(0x3F);981 reg |= p_mpeg4->rc_min_qp;982 mfc_write(dev, reg, S5P_FIMV_ENC_RC_QBOUND);983 /* extended encoder ctrl */984 shm = s5p_mfc_read_info_v5(ctx, EXT_ENC_CONTROL);985 /* vbv buffer size */986 if (p->frame_skip_mode ==987 V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT) {988 shm &= ~(0xFFFF << 16);989 shm |= (p->vbv_size << 16);990 }991 s5p_mfc_write_info_v5(ctx, shm, EXT_ENC_CONTROL);992 return 0;993}994 995static int s5p_mfc_set_enc_params_h263(struct s5p_mfc_ctx *ctx)996{997 struct s5p_mfc_dev *dev = ctx->dev;998 const struct s5p_mfc_enc_params *p = &ctx->enc_params;999 const struct s5p_mfc_mpeg4_enc_params *p_h263 = &p->codec.mpeg4;1000 unsigned int reg;1001 unsigned int shm;1002 1003 s5p_mfc_set_enc_params(ctx);1004 /* qp */1005 if (!p->rc_frame) {1006 shm = s5p_mfc_read_info_v5(ctx, P_B_FRAME_QP);1007 shm &= ~(0xFFF);1008 shm |= (p_h263->rc_p_frame_qp & 0x3F);1009 s5p_mfc_write_info_v5(ctx, shm, P_B_FRAME_QP);1010 }1011 /* frame rate */1012 if (p->rc_frame && p->rc_framerate_denom)1013 mfc_write(dev, p->rc_framerate_num * 10001014 / p->rc_framerate_denom, S5P_FIMV_ENC_RC_FRAME_RATE);1015 else1016 mfc_write(dev, 0, S5P_FIMV_ENC_RC_FRAME_RATE);1017 /* rate control config. */1018 reg = mfc_read(dev, S5P_FIMV_ENC_RC_CONFIG);1019 /* frame QP */1020 reg &= ~(0x3F);1021 reg |= p_h263->rc_frame_qp;1022 mfc_write(dev, reg, S5P_FIMV_ENC_RC_CONFIG);1023 /* max & min value of QP */1024 reg = mfc_read(dev, S5P_FIMV_ENC_RC_QBOUND);1025 /* max QP */1026 reg &= ~(0x3F << 8);1027 reg |= (p_h263->rc_max_qp << 8);1028 /* min QP */1029 reg &= ~(0x3F);1030 reg |= p_h263->rc_min_qp;1031 mfc_write(dev, reg, S5P_FIMV_ENC_RC_QBOUND);1032 /* extended encoder ctrl */1033 shm = s5p_mfc_read_info_v5(ctx, EXT_ENC_CONTROL);1034 /* vbv buffer size */1035 if (p->frame_skip_mode ==1036 V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT) {1037 shm &= ~(0xFFFF << 16);1038 shm |= (p->vbv_size << 16);1039 }1040 s5p_mfc_write_info_v5(ctx, shm, EXT_ENC_CONTROL);1041 return 0;1042}1043 1044/* Initialize decoding */1045static int s5p_mfc_init_decode_v5(struct s5p_mfc_ctx *ctx)1046{1047 struct s5p_mfc_dev *dev = ctx->dev;1048 1049 s5p_mfc_set_shared_buffer(ctx);1050 /* Setup loop filter, for decoding this is only valid for MPEG4 */1051 if (ctx->codec_mode == S5P_MFC_CODEC_MPEG4_DEC)1052 mfc_write(dev, ctx->loop_filter_mpeg4, S5P_FIMV_ENC_LF_CTRL);1053 else1054 mfc_write(dev, 0, S5P_FIMV_ENC_LF_CTRL);1055 mfc_write(dev, ((ctx->slice_interface & S5P_FIMV_SLICE_INT_MASK) <<1056 S5P_FIMV_SLICE_INT_SHIFT) | (ctx->display_delay_enable <<1057 S5P_FIMV_DDELAY_ENA_SHIFT) | ((ctx->display_delay &1058 S5P_FIMV_DDELAY_VAL_MASK) << S5P_FIMV_DDELAY_VAL_SHIFT),1059 S5P_FIMV_SI_CH0_DPB_CONF_CTRL);1060 mfc_write(dev,1061 ((S5P_FIMV_CH_SEQ_HEADER & S5P_FIMV_CH_MASK) << S5P_FIMV_CH_SHIFT)1062 | (ctx->inst_no), S5P_FIMV_SI_CH0_INST_ID);1063 return 0;1064}1065 1066static void s5p_mfc_set_flush(struct s5p_mfc_ctx *ctx, int flush)1067{1068 struct s5p_mfc_dev *dev = ctx->dev;1069 unsigned int dpb;1070 1071 if (flush)1072 dpb = mfc_read(dev, S5P_FIMV_SI_CH0_DPB_CONF_CTRL) | (1073 S5P_FIMV_DPB_FLUSH_MASK << S5P_FIMV_DPB_FLUSH_SHIFT);1074 else1075 dpb = mfc_read(dev, S5P_FIMV_SI_CH0_DPB_CONF_CTRL) &1076 ~(S5P_FIMV_DPB_FLUSH_MASK << S5P_FIMV_DPB_FLUSH_SHIFT);1077 mfc_write(dev, dpb, S5P_FIMV_SI_CH0_DPB_CONF_CTRL);1078}1079 1080/* Decode a single frame */1081static int s5p_mfc_decode_one_frame_v5(struct s5p_mfc_ctx *ctx,1082 enum s5p_mfc_decode_arg last_frame)1083{1084 struct s5p_mfc_dev *dev = ctx->dev;1085 1086 mfc_write(dev, ctx->dec_dst_flag, S5P_FIMV_SI_CH0_RELEASE_BUF);1087 s5p_mfc_set_shared_buffer(ctx);1088 s5p_mfc_set_flush(ctx, ctx->dpb_flush_flag);1089 /* Issue different commands to instance basing on whether it1090 * is the last frame or not. */1091 switch (last_frame) {1092 case MFC_DEC_FRAME:1093 mfc_write(dev, ((S5P_FIMV_CH_FRAME_START & S5P_FIMV_CH_MASK) <<1094 S5P_FIMV_CH_SHIFT) | (ctx->inst_no), S5P_FIMV_SI_CH0_INST_ID);1095 break;1096 case MFC_DEC_LAST_FRAME:1097 mfc_write(dev, ((S5P_FIMV_CH_LAST_FRAME & S5P_FIMV_CH_MASK) <<1098 S5P_FIMV_CH_SHIFT) | (ctx->inst_no), S5P_FIMV_SI_CH0_INST_ID);1099 break;1100 case MFC_DEC_RES_CHANGE:1101 mfc_write(dev, ((S5P_FIMV_CH_FRAME_START_REALLOC &1102 S5P_FIMV_CH_MASK) << S5P_FIMV_CH_SHIFT) | (ctx->inst_no),1103 S5P_FIMV_SI_CH0_INST_ID);1104 break;1105 }1106 mfc_debug(2, "Decoding a usual frame\n");1107 return 0;1108}1109 1110static int s5p_mfc_init_encode_v5(struct s5p_mfc_ctx *ctx)1111{1112 struct s5p_mfc_dev *dev = ctx->dev;1113 1114 if (ctx->codec_mode == S5P_MFC_CODEC_H264_ENC)1115 s5p_mfc_set_enc_params_h264(ctx);1116 else if (ctx->codec_mode == S5P_MFC_CODEC_MPEG4_ENC)1117 s5p_mfc_set_enc_params_mpeg4(ctx);1118 else if (ctx->codec_mode == S5P_MFC_CODEC_H263_ENC)1119 s5p_mfc_set_enc_params_h263(ctx);1120 else {1121 mfc_err("Unknown codec for encoding (%x)\n",1122 ctx->codec_mode);1123 return -EINVAL;1124 }1125 s5p_mfc_set_shared_buffer(ctx);1126 mfc_write(dev, ((S5P_FIMV_CH_SEQ_HEADER << 16) & 0x70000) |1127 (ctx->inst_no), S5P_FIMV_SI_CH0_INST_ID);1128 return 0;1129}1130 1131/* Encode a single frame */1132static int s5p_mfc_encode_one_frame_v5(struct s5p_mfc_ctx *ctx)1133{1134 struct s5p_mfc_dev *dev = ctx->dev;1135 int cmd;1136 /* memory structure cur. frame */1137 if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12M)1138 mfc_write(dev, 0, S5P_FIMV_ENC_MAP_FOR_CUR);1139 else if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12MT)1140 mfc_write(dev, 3, S5P_FIMV_ENC_MAP_FOR_CUR);1141 s5p_mfc_set_shared_buffer(ctx);1142 1143 if (ctx->state == MFCINST_FINISHING)1144 cmd = S5P_FIMV_CH_LAST_FRAME;1145 else1146 cmd = S5P_FIMV_CH_FRAME_START;1147 mfc_write(dev, ((cmd & S5P_FIMV_CH_MASK) << S5P_FIMV_CH_SHIFT)1148 | (ctx->inst_no), S5P_FIMV_SI_CH0_INST_ID);1149 1150 return 0;1151}1152 1153static void s5p_mfc_run_res_change(struct s5p_mfc_ctx *ctx)1154{1155 struct s5p_mfc_dev *dev = ctx->dev;1156 1157 s5p_mfc_set_dec_stream_buffer_v5(ctx, 0, 0, 0);1158 dev->curr_ctx = ctx->num;1159 s5p_mfc_decode_one_frame_v5(ctx, MFC_DEC_RES_CHANGE);1160}1161 1162static int s5p_mfc_run_dec_frame(struct s5p_mfc_ctx *ctx, int last_frame)1163{1164 struct s5p_mfc_dev *dev = ctx->dev;1165 struct s5p_mfc_buf *temp_vb;1166 1167 if (ctx->state == MFCINST_FINISHING) {1168 last_frame = MFC_DEC_LAST_FRAME;1169 s5p_mfc_set_dec_stream_buffer_v5(ctx, 0, 0, 0);1170 dev->curr_ctx = ctx->num;1171 s5p_mfc_decode_one_frame_v5(ctx, last_frame);1172 return 0;1173 }1174 1175 /* Frames are being decoded */1176 if (list_empty(&ctx->src_queue)) {1177 mfc_debug(2, "No src buffers\n");1178 return -EAGAIN;1179 }1180 /* Get the next source buffer */1181 temp_vb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);1182 temp_vb->flags |= MFC_BUF_FLAG_USED;1183 s5p_mfc_set_dec_stream_buffer_v5(ctx,1184 vb2_dma_contig_plane_dma_addr(&temp_vb->b->vb2_buf, 0),1185 ctx->consumed_stream, temp_vb->b->vb2_buf.planes[0].bytesused);1186 dev->curr_ctx = ctx->num;1187 if (temp_vb->b->vb2_buf.planes[0].bytesused == 0) {1188 last_frame = MFC_DEC_LAST_FRAME;1189 mfc_debug(2, "Setting ctx->state to FINISHING\n");1190 ctx->state = MFCINST_FINISHING;1191 }1192 s5p_mfc_decode_one_frame_v5(ctx, last_frame);1193 return 0;1194}1195 1196static int s5p_mfc_run_enc_frame(struct s5p_mfc_ctx *ctx)1197{1198 struct s5p_mfc_dev *dev = ctx->dev;1199 struct s5p_mfc_buf *dst_mb;1200 struct s5p_mfc_buf *src_mb;1201 unsigned long src_y_addr, src_c_addr, dst_addr;1202 unsigned int dst_size;1203 1204 if (list_empty(&ctx->src_queue) && ctx->state != MFCINST_FINISHING) {1205 mfc_debug(2, "no src buffers\n");1206 return -EAGAIN;1207 }1208 if (list_empty(&ctx->dst_queue)) {1209 mfc_debug(2, "no dst buffers\n");1210 return -EAGAIN;1211 }1212 if (list_empty(&ctx->src_queue)) {1213 /* send null frame */1214 s5p_mfc_set_enc_frame_buffer_v5(ctx, dev->dma_base[BANK_R_CTX],1215 dev->dma_base[BANK_R_CTX], 0);1216 src_mb = NULL;1217 } else {1218 src_mb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf,1219 list);1220 src_mb->flags |= MFC_BUF_FLAG_USED;1221 if (src_mb->b->vb2_buf.planes[0].bytesused == 0) {1222 /* send null frame */1223 s5p_mfc_set_enc_frame_buffer_v5(ctx,1224 dev->dma_base[BANK_R_CTX],1225 dev->dma_base[BANK_R_CTX], 0);1226 ctx->state = MFCINST_FINISHING;1227 } else {1228 src_y_addr = vb2_dma_contig_plane_dma_addr(1229 &src_mb->b->vb2_buf, 0);1230 src_c_addr = vb2_dma_contig_plane_dma_addr(1231 &src_mb->b->vb2_buf, 1);1232 s5p_mfc_set_enc_frame_buffer_v5(ctx, src_y_addr,1233 src_c_addr, 0);1234 if (src_mb->flags & MFC_BUF_FLAG_EOS)1235 ctx->state = MFCINST_FINISHING;1236 }1237 }1238 dst_mb = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list);1239 dst_mb->flags |= MFC_BUF_FLAG_USED;1240 dst_addr = vb2_dma_contig_plane_dma_addr(&dst_mb->b->vb2_buf, 0);1241 dst_size = vb2_plane_size(&dst_mb->b->vb2_buf, 0);1242 s5p_mfc_set_enc_stream_buffer_v5(ctx, dst_addr, dst_size);1243 dev->curr_ctx = ctx->num;1244 mfc_debug(2, "encoding buffer with index=%d state=%d\n",1245 src_mb ? src_mb->b->vb2_buf.index : -1, ctx->state);1246 s5p_mfc_encode_one_frame_v5(ctx);1247 return 0;1248}1249 1250static void s5p_mfc_run_init_dec(struct s5p_mfc_ctx *ctx)1251{1252 struct s5p_mfc_dev *dev = ctx->dev;1253 struct s5p_mfc_buf *temp_vb;1254 1255 /* Initializing decoding - parsing header */1256 mfc_debug(2, "Preparing to init decoding\n");1257 temp_vb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);1258 s5p_mfc_set_dec_desc_buffer(ctx);1259 mfc_debug(2, "Header size: %d\n",1260 temp_vb->b->vb2_buf.planes[0].bytesused);1261 s5p_mfc_set_dec_stream_buffer_v5(ctx,1262 vb2_dma_contig_plane_dma_addr(&temp_vb->b->vb2_buf, 0),1263 0, temp_vb->b->vb2_buf.planes[0].bytesused);1264 dev->curr_ctx = ctx->num;1265 s5p_mfc_init_decode_v5(ctx);1266}1267 1268static void s5p_mfc_run_init_enc(struct s5p_mfc_ctx *ctx)1269{1270 struct s5p_mfc_dev *dev = ctx->dev;1271 struct s5p_mfc_buf *dst_mb;1272 unsigned long dst_addr;1273 unsigned int dst_size;1274 1275 s5p_mfc_set_enc_ref_buffer_v5(ctx);1276 dst_mb = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list);1277 dst_addr = vb2_dma_contig_plane_dma_addr(&dst_mb->b->vb2_buf, 0);1278 dst_size = vb2_plane_size(&dst_mb->b->vb2_buf, 0);1279 s5p_mfc_set_enc_stream_buffer_v5(ctx, dst_addr, dst_size);1280 dev->curr_ctx = ctx->num;1281 s5p_mfc_init_encode_v5(ctx);1282}1283 1284static int s5p_mfc_run_init_dec_buffers(struct s5p_mfc_ctx *ctx)1285{1286 struct s5p_mfc_dev *dev = ctx->dev;1287 struct s5p_mfc_buf *temp_vb;1288 int ret;1289 1290 /*1291 * Header was parsed now starting processing1292 * First set the output frame buffers1293 */1294 if (ctx->capture_state != QUEUE_BUFS_MMAPED) {1295 mfc_err("It seems that not all destination buffers were mmapped\nMFC requires that all destination are mmapped before starting processing\n");1296 return -EAGAIN;1297 }1298 if (list_empty(&ctx->src_queue)) {1299 mfc_err("Header has been deallocated in the middle of initialization\n");1300 return -EIO;1301 }1302 temp_vb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);1303 mfc_debug(2, "Header size: %d\n",1304 temp_vb->b->vb2_buf.planes[0].bytesused);1305 s5p_mfc_set_dec_stream_buffer_v5(ctx,1306 vb2_dma_contig_plane_dma_addr(&temp_vb->b->vb2_buf, 0),1307 0, temp_vb->b->vb2_buf.planes[0].bytesused);1308 dev->curr_ctx = ctx->num;1309 ret = s5p_mfc_set_dec_frame_buffer_v5(ctx);1310 if (ret) {1311 mfc_err("Failed to alloc frame mem\n");1312 ctx->state = MFCINST_ERROR;1313 }1314 return ret;1315}1316 1317/* Try running an operation on hardware */1318static void s5p_mfc_try_run_v5(struct s5p_mfc_dev *dev)1319{1320 struct s5p_mfc_ctx *ctx;1321 int new_ctx;1322 unsigned int ret = 0;1323 1324 if (test_bit(0, &dev->enter_suspend)) {1325 mfc_debug(1, "Entering suspend so do not schedule any jobs\n");1326 return;1327 }1328 /* Check whether hardware is not running */1329 if (test_and_set_bit(0, &dev->hw_lock) != 0) {1330 /* This is perfectly ok, the scheduled ctx should wait */1331 mfc_debug(1, "Couldn't lock HW\n");1332 return;1333 }1334 /* Choose the context to run */1335 new_ctx = s5p_mfc_get_new_ctx(dev);1336 if (new_ctx < 0) {1337 /* No contexts to run */1338 if (test_and_clear_bit(0, &dev->hw_lock) == 0) {1339 mfc_err("Failed to unlock hardware\n");1340 return;1341 }1342 mfc_debug(1, "No ctx is scheduled to be run\n");1343 return;1344 }1345 ctx = dev->ctx[new_ctx];1346 /* Got context to run in ctx */1347 /*1348 * Last frame has already been sent to MFC.1349 * Now obtaining frames from MFC buffer1350 */1351 s5p_mfc_clock_on(dev);1352 s5p_mfc_clean_ctx_int_flags(ctx);1353 1354 if (ctx->type == MFCINST_DECODER) {1355 s5p_mfc_set_dec_desc_buffer(ctx);1356 switch (ctx->state) {1357 case MFCINST_FINISHING:1358 s5p_mfc_run_dec_frame(ctx, MFC_DEC_LAST_FRAME);1359 break;1360 case MFCINST_RUNNING:1361 ret = s5p_mfc_run_dec_frame(ctx, MFC_DEC_FRAME);1362 break;1363 case MFCINST_INIT:1364 ret = s5p_mfc_hw_call(dev->mfc_cmds, open_inst_cmd,1365 ctx);1366 break;1367 case MFCINST_RETURN_INST:1368 ret = s5p_mfc_hw_call(dev->mfc_cmds, close_inst_cmd,1369 ctx);1370 break;1371 case MFCINST_GOT_INST:1372 s5p_mfc_run_init_dec(ctx);1373 break;1374 case MFCINST_HEAD_PARSED:1375 ret = s5p_mfc_run_init_dec_buffers(ctx);1376 mfc_debug(1, "head parsed\n");1377 break;1378 case MFCINST_RES_CHANGE_INIT:1379 s5p_mfc_run_res_change(ctx);1380 break;1381 case MFCINST_RES_CHANGE_FLUSH:1382 s5p_mfc_run_dec_frame(ctx, MFC_DEC_FRAME);1383 break;1384 case MFCINST_RES_CHANGE_END:1385 mfc_debug(2, "Finished remaining frames after resolution change\n");1386 ctx->capture_state = QUEUE_FREE;1387 mfc_debug(2, "Will re-init the codec\n");1388 s5p_mfc_run_init_dec(ctx);1389 break;1390 default:1391 ret = -EAGAIN;1392 }1393 } else if (ctx->type == MFCINST_ENCODER) {1394 switch (ctx->state) {1395 case MFCINST_FINISHING:1396 case MFCINST_RUNNING:1397 ret = s5p_mfc_run_enc_frame(ctx);1398 break;1399 case MFCINST_INIT:1400 ret = s5p_mfc_hw_call(dev->mfc_cmds, open_inst_cmd,1401 ctx);1402 break;1403 case MFCINST_RETURN_INST:1404 ret = s5p_mfc_hw_call(dev->mfc_cmds, close_inst_cmd,1405 ctx);1406 break;1407 case MFCINST_GOT_INST:1408 s5p_mfc_run_init_enc(ctx);1409 break;1410 default:1411 ret = -EAGAIN;1412 }1413 } else {1414 mfc_err("Invalid context type: %d\n", ctx->type);1415 ret = -EAGAIN;1416 }1417 1418 if (ret) {1419 /* Free hardware lock */1420 if (test_and_clear_bit(0, &dev->hw_lock) == 0)1421 mfc_err("Failed to unlock hardware\n");1422 1423 /* This is indeed important, as no operation has been1424 * scheduled, reduce the clock count as no one will1425 * ever do this, because no interrupt related to this try_run1426 * will ever come from hardware. */1427 s5p_mfc_clock_off(dev);1428 }1429}1430 1431static void s5p_mfc_clear_int_flags_v5(struct s5p_mfc_dev *dev)1432{1433 mfc_write(dev, 0, S5P_FIMV_RISC_HOST_INT);1434 mfc_write(dev, 0, S5P_FIMV_RISC2HOST_CMD);1435 mfc_write(dev, 0xffff, S5P_FIMV_SI_RTN_CHID);1436}1437 1438static int s5p_mfc_get_dspl_y_adr_v5(struct s5p_mfc_dev *dev)1439{1440 return mfc_read(dev, S5P_FIMV_SI_DISPLAY_Y_ADR) << MFC_OFFSET_SHIFT;1441}1442 1443static int s5p_mfc_get_dec_y_adr_v5(struct s5p_mfc_dev *dev)1444{1445 return mfc_read(dev, S5P_FIMV_SI_DECODE_Y_ADR) << MFC_OFFSET_SHIFT;1446}1447 1448static int s5p_mfc_get_dspl_status_v5(struct s5p_mfc_dev *dev)1449{1450 return mfc_read(dev, S5P_FIMV_SI_DISPLAY_STATUS);1451}1452 1453static int s5p_mfc_get_dec_status_v5(struct s5p_mfc_dev *dev)1454{1455 return mfc_read(dev, S5P_FIMV_SI_DECODE_STATUS);1456}1457 1458static int s5p_mfc_get_dec_frame_type_v5(struct s5p_mfc_dev *dev)1459{1460 return mfc_read(dev, S5P_FIMV_DECODE_FRAME_TYPE) &1461 S5P_FIMV_DECODE_FRAME_MASK;1462}1463 1464static int s5p_mfc_get_disp_frame_type_v5(struct s5p_mfc_ctx *ctx)1465{1466 return (s5p_mfc_read_info_v5(ctx, DISP_PIC_FRAME_TYPE) >>1467 S5P_FIMV_SHARED_DISP_FRAME_TYPE_SHIFT) &1468 S5P_FIMV_DECODE_FRAME_MASK;1469}1470 1471static int s5p_mfc_get_consumed_stream_v5(struct s5p_mfc_dev *dev)1472{1473 return mfc_read(dev, S5P_FIMV_SI_CONSUMED_BYTES);1474}1475 1476static int s5p_mfc_get_int_reason_v5(struct s5p_mfc_dev *dev)1477{1478 int reason;1479 reason = mfc_read(dev, S5P_FIMV_RISC2HOST_CMD) &1480 S5P_FIMV_RISC2HOST_CMD_MASK;1481 switch (reason) {1482 case S5P_FIMV_R2H_CMD_OPEN_INSTANCE_RET:1483 reason = S5P_MFC_R2H_CMD_OPEN_INSTANCE_RET;1484 break;1485 case S5P_FIMV_R2H_CMD_CLOSE_INSTANCE_RET:1486 reason = S5P_MFC_R2H_CMD_CLOSE_INSTANCE_RET;1487 break;1488 case S5P_FIMV_R2H_CMD_SEQ_DONE_RET:1489 reason = S5P_MFC_R2H_CMD_SEQ_DONE_RET;1490 break;1491 case S5P_FIMV_R2H_CMD_FRAME_DONE_RET:1492 reason = S5P_MFC_R2H_CMD_FRAME_DONE_RET;1493 break;1494 case S5P_FIMV_R2H_CMD_SLICE_DONE_RET:1495 reason = S5P_MFC_R2H_CMD_SLICE_DONE_RET;1496 break;1497 case S5P_FIMV_R2H_CMD_SYS_INIT_RET:1498 reason = S5P_MFC_R2H_CMD_SYS_INIT_RET;1499 break;1500 case S5P_FIMV_R2H_CMD_FW_STATUS_RET:1501 reason = S5P_MFC_R2H_CMD_FW_STATUS_RET;1502 break;1503 case S5P_FIMV_R2H_CMD_SLEEP_RET:1504 reason = S5P_MFC_R2H_CMD_SLEEP_RET;1505 break;1506 case S5P_FIMV_R2H_CMD_WAKEUP_RET:1507 reason = S5P_MFC_R2H_CMD_WAKEUP_RET;1508 break;1509 case S5P_FIMV_R2H_CMD_INIT_BUFFERS_RET:1510 reason = S5P_MFC_R2H_CMD_INIT_BUFFERS_RET;1511 break;1512 case S5P_FIMV_R2H_CMD_ENC_COMPLETE_RET:1513 reason = S5P_MFC_R2H_CMD_COMPLETE_SEQ_RET;1514 break;1515 case S5P_FIMV_R2H_CMD_ERR_RET:1516 reason = S5P_MFC_R2H_CMD_ERR_RET;1517 break;1518 default:1519 reason = S5P_MFC_R2H_CMD_EMPTY;1520 }1521 return reason;1522}1523 1524static int s5p_mfc_get_int_err_v5(struct s5p_mfc_dev *dev)1525{1526 return mfc_read(dev, S5P_FIMV_RISC2HOST_ARG2);1527}1528 1529static int s5p_mfc_err_dec_v5(unsigned int err)1530{1531 return (err & S5P_FIMV_ERR_DEC_MASK) >> S5P_FIMV_ERR_DEC_SHIFT;1532}1533 1534static int s5p_mfc_get_img_width_v5(struct s5p_mfc_dev *dev)1535{1536 return mfc_read(dev, S5P_FIMV_SI_HRESOL);1537}1538 1539static int s5p_mfc_get_img_height_v5(struct s5p_mfc_dev *dev)1540{1541 return mfc_read(dev, S5P_FIMV_SI_VRESOL);1542}1543 1544static int s5p_mfc_get_dpb_count_v5(struct s5p_mfc_dev *dev)1545{1546 return mfc_read(dev, S5P_FIMV_SI_BUF_NUMBER);1547}1548 1549static int s5p_mfc_get_mv_count_v5(struct s5p_mfc_dev *dev)1550{1551 /* NOP */1552 return -1;1553}1554 1555static int s5p_mfc_get_inst_no_v5(struct s5p_mfc_dev *dev)1556{1557 return mfc_read(dev, S5P_FIMV_RISC2HOST_ARG1);1558}1559 1560static int s5p_mfc_get_enc_strm_size_v5(struct s5p_mfc_dev *dev)1561{1562 return mfc_read(dev, S5P_FIMV_ENC_SI_STRM_SIZE);1563}1564 1565static int s5p_mfc_get_enc_slice_type_v5(struct s5p_mfc_dev *dev)1566{1567 return mfc_read(dev, S5P_FIMV_ENC_SI_SLICE_TYPE);1568}1569 1570static int s5p_mfc_get_enc_dpb_count_v5(struct s5p_mfc_dev *dev)1571{1572 return -1;1573}1574 1575static unsigned int s5p_mfc_get_pic_type_top_v5(struct s5p_mfc_ctx *ctx)1576{1577 return s5p_mfc_read_info_v5(ctx, PIC_TIME_TOP);1578}1579 1580static unsigned int s5p_mfc_get_pic_type_bot_v5(struct s5p_mfc_ctx *ctx)1581{1582 return s5p_mfc_read_info_v5(ctx, PIC_TIME_BOT);1583}1584 1585static unsigned int s5p_mfc_get_crop_info_h_v5(struct s5p_mfc_ctx *ctx)1586{1587 return s5p_mfc_read_info_v5(ctx, CROP_INFO_H);1588}1589 1590static unsigned int s5p_mfc_get_crop_info_v_v5(struct s5p_mfc_ctx *ctx)1591{1592 return s5p_mfc_read_info_v5(ctx, CROP_INFO_V);1593}1594 1595/* Initialize opr function pointers for MFC v5 */1596static const struct s5p_mfc_hw_ops s5p_mfc_ops_v5 = {1597 .alloc_dec_temp_buffers = s5p_mfc_alloc_dec_temp_buffers_v5,1598 .release_dec_desc_buffer = s5p_mfc_release_dec_desc_buffer_v5,1599 .alloc_codec_buffers = s5p_mfc_alloc_codec_buffers_v5,1600 .release_codec_buffers = s5p_mfc_release_codec_buffers_v5,1601 .alloc_instance_buffer = s5p_mfc_alloc_instance_buffer_v5,1602 .release_instance_buffer = s5p_mfc_release_instance_buffer_v5,1603 .alloc_dev_context_buffer = s5p_mfc_alloc_dev_context_buffer_v5,1604 .release_dev_context_buffer = s5p_mfc_release_dev_context_buffer_v5,1605 .dec_calc_dpb_size = s5p_mfc_dec_calc_dpb_size_v5,1606 .enc_calc_src_size = s5p_mfc_enc_calc_src_size_v5,1607 .set_enc_stream_buffer = s5p_mfc_set_enc_stream_buffer_v5,1608 .set_enc_frame_buffer = s5p_mfc_set_enc_frame_buffer_v5,1609 .get_enc_frame_buffer = s5p_mfc_get_enc_frame_buffer_v5,1610 .try_run = s5p_mfc_try_run_v5,1611 .clear_int_flags = s5p_mfc_clear_int_flags_v5,1612 .get_dspl_y_adr = s5p_mfc_get_dspl_y_adr_v5,1613 .get_dec_y_adr = s5p_mfc_get_dec_y_adr_v5,1614 .get_dspl_status = s5p_mfc_get_dspl_status_v5,1615 .get_dec_status = s5p_mfc_get_dec_status_v5,1616 .get_dec_frame_type = s5p_mfc_get_dec_frame_type_v5,1617 .get_disp_frame_type = s5p_mfc_get_disp_frame_type_v5,1618 .get_consumed_stream = s5p_mfc_get_consumed_stream_v5,1619 .get_int_reason = s5p_mfc_get_int_reason_v5,1620 .get_int_err = s5p_mfc_get_int_err_v5,1621 .err_dec = s5p_mfc_err_dec_v5,1622 .get_img_width = s5p_mfc_get_img_width_v5,1623 .get_img_height = s5p_mfc_get_img_height_v5,1624 .get_dpb_count = s5p_mfc_get_dpb_count_v5,1625 .get_mv_count = s5p_mfc_get_mv_count_v5,1626 .get_inst_no = s5p_mfc_get_inst_no_v5,1627 .get_enc_strm_size = s5p_mfc_get_enc_strm_size_v5,1628 .get_enc_slice_type = s5p_mfc_get_enc_slice_type_v5,1629 .get_enc_dpb_count = s5p_mfc_get_enc_dpb_count_v5,1630 .get_pic_type_top = s5p_mfc_get_pic_type_top_v5,1631 .get_pic_type_bot = s5p_mfc_get_pic_type_bot_v5,1632 .get_crop_info_h = s5p_mfc_get_crop_info_h_v5,1633 .get_crop_info_v = s5p_mfc_get_crop_info_v_v5,1634};1635 1636const struct s5p_mfc_hw_ops *s5p_mfc_init_hw_ops_v5(void)1637{1638 return &s5p_mfc_ops_v5;1639}1640