Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

media: mediatek: vcodec: Add encoder driver support for 34-bit iova

Encoder driver got iova from IOMMU is 34-bit, for example:

Here is the sample code:
encoder input frame buffer dma address is:
frm_buf =
vb2_dma_contig_plane_dma_addr(&vb2_v4l2_buffer->vb2_buf, 0);
the value of frm_buf is 0x1_ff30_0000.

encoder driver got the frm_buf and send the iova to SCP firmware
through SCP IPI message, then write to encoder hardware in SCP.
The iova is stored in IPI message as uint32_t data type, so the
value will be truncated from *0x1_ff30_0000* to *0xff30_0000*,
and then *0xff30_0000* will be written to encoder hardware, but
IOMMU will help to add the high *0x1_* bit back, so IOMMU can
translate the iova to PA correctly, encoder hardware can access
the correct memory for encoding.
Another reason to do this is the encoder hardware can't access
the 34-bit iova, IOMMU will help to add the remaining high bits
of iova. But for mt8188, encoder hardware can access 34-bit iova
directly, and encoder driver need write all 34 bits because
IOMMU can't help driver do this if the hardware support access
34-bit iova.
For the reasons above, this patch is added to support transfer
34-bit iova between kernel and SCP encoder driver. Use uint64_t
data type to store the iova, for compatibility with old chipsets,
add some new struct definitions for 34-bit.

[hverkuil: initialize wb and wb_34 to NULL]

Signed-off-by: Irui Wang <irui.wang@mediatek.com>
Reported-by: kernel test robot <lkp@intel.com>
Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab@kernel.org>

authored by

Irui Wang and committed by
Mauro Carvalho Chehab
34cb6947 d91105e0

+266 -37
+3
drivers/media/platform/mediatek/vcodec/mtk_vcodec_drv.h
··· 401 401 * @output_formats: array of supported output formats 402 402 * @num_output_formats: number of entries in output_formats 403 403 * @core_id: stand for h264 or vp8 encode index 404 + * @uses_34bit: whether the encoder uses 34-bit iova 404 405 */ 405 406 struct mtk_vcodec_enc_pdata { 406 407 bool uses_ext; ··· 412 411 const struct mtk_video_fmt *output_formats; 413 412 size_t num_output_formats; 414 413 int core_id; 414 + bool uses_34bit; 415 415 }; 416 416 417 417 #define MTK_ENC_CTX_IS_EXT(ctx) ((ctx)->dev->venc_pdata->uses_ext) 418 + #define MTK_ENC_IOVA_IS_34BIT(ctx) ((ctx)->dev->venc_pdata->uses_34bit) 418 419 419 420 /** 420 421 * struct mtk_vcodec_dev - driver data
+167 -33
drivers/media/platform/mediatek/vcodec/venc/venc_h264_if.c
··· 127 127 struct venc_h264_vpu_buf work_bufs[VENC_H264_VPU_WORK_BUF_MAX]; 128 128 }; 129 129 130 + /** 131 + * struct venc_h264_vpu_config_ext - Structure for h264 encoder configuration 132 + * AP-W/R : AP is writer/reader on this item 133 + * VPU-W/R: VPU is write/reader on this item 134 + * @input_fourcc: input fourcc 135 + * @bitrate: target bitrate (in bps) 136 + * @pic_w: picture width. Picture size is visible stream resolution, in pixels, 137 + * to be used for display purposes; must be smaller or equal to buffer 138 + * size. 139 + * @pic_h: picture height 140 + * @buf_w: buffer width. Buffer size is stream resolution in pixels aligned to 141 + * hardware requirements. 142 + * @buf_h: buffer height 143 + * @gop_size: group of picture size (idr frame) 144 + * @intra_period: intra frame period 145 + * @framerate: frame rate in fps 146 + * @profile: as specified in standard 147 + * @level: as specified in standard 148 + * @wfd: WFD mode 1:on, 0:off 149 + * @max_qp: max quant parameter 150 + * @min_qp: min quant parameter 151 + * @reserved: reserved configs 152 + */ 153 + struct venc_h264_vpu_config_ext { 154 + u32 input_fourcc; 155 + u32 bitrate; 156 + u32 pic_w; 157 + u32 pic_h; 158 + u32 buf_w; 159 + u32 buf_h; 160 + u32 gop_size; 161 + u32 intra_period; 162 + u32 framerate; 163 + u32 profile; 164 + u32 level; 165 + u32 wfd; 166 + u32 max_qp; 167 + u32 min_qp; 168 + u32 reserved[8]; 169 + }; 170 + 171 + /** 172 + * struct venc_h264_vpu_buf_34 - Structure for 34-bit buffer information 173 + * AP-W/R : AP is writer/reader on this item 174 + * VPU-W/R: VPU is write/reader on this item 175 + * @iova: 34-bit IO virtual address 176 + * @vpua: VPU side memory addr which is used by RC_CODE 177 + * @size: buffer size (in bytes) 178 + */ 179 + struct venc_h264_vpu_buf_34 { 180 + u64 iova; 181 + u32 vpua; 182 + u32 size; 183 + }; 184 + 185 + /** 186 + * struct venc_h264_vsi_34 - Structure for VPU driver control and info share 187 + * Used for 34-bit iova sharing 188 + * @config: h264 encoder configuration 189 + * @work_bufs: working buffer information in VPU side 190 + */ 191 + struct venc_h264_vsi_34 { 192 + struct venc_h264_vpu_config_ext config; 193 + struct venc_h264_vpu_buf_34 work_bufs[VENC_H264_VPU_WORK_BUF_MAX]; 194 + }; 195 + 130 196 /* 131 197 * struct venc_h264_inst - h264 encoder AP driver instance 132 198 * @hw_base: h264 encoder hardware register base ··· 206 140 * @vpu_inst: VPU instance to exchange information between AP and VPU 207 141 * @vsi: driver structure allocated by VPU side and shared to AP side for 208 142 * control and info share 143 + * @vsi_34: driver structure allocated by VPU side and shared to AP side for 144 + * control and info share, used for 34-bit iova sharing. 209 145 * @ctx: context for v4l2 layer integration 210 146 */ 211 147 struct venc_h264_inst { ··· 220 152 unsigned int prepend_hdr; 221 153 struct venc_vpu_inst vpu_inst; 222 154 struct venc_h264_vsi *vsi; 155 + struct venc_h264_vsi_34 *vsi_34; 223 156 struct mtk_vcodec_ctx *ctx; 224 157 }; 225 158 ··· 313 244 mtk_vcodec_debug_leave(inst); 314 245 } 315 246 316 - static int h264_enc_alloc_work_buf(struct venc_h264_inst *inst) 247 + static int h264_enc_alloc_work_buf(struct venc_h264_inst *inst, bool is_34bit) 317 248 { 249 + struct venc_h264_vpu_buf *wb = NULL; 250 + struct venc_h264_vpu_buf_34 *wb_34 = NULL; 318 251 int i; 252 + u32 vpua, wb_size; 319 253 int ret = 0; 320 - struct venc_h264_vpu_buf *wb = inst->vsi->work_bufs; 321 254 322 255 mtk_vcodec_debug_enter(inst); 256 + 257 + if (is_34bit) 258 + wb_34 = inst->vsi_34->work_bufs; 259 + else 260 + wb = inst->vsi->work_bufs; 323 261 324 262 for (i = 0; i < VENC_H264_VPU_WORK_BUF_MAX; i++) { 325 263 /* ··· 345 269 * address and do some memcpy access to move to bitstream buffer 346 270 * assigned by v4l2 layer. 347 271 */ 348 - inst->work_bufs[i].size = wb[i].size; 272 + if (is_34bit) { 273 + inst->work_bufs[i].size = wb_34[i].size; 274 + vpua = wb_34[i].vpua; 275 + wb_size = wb_34[i].size; 276 + } else { 277 + inst->work_bufs[i].size = wb[i].size; 278 + vpua = wb[i].vpua; 279 + wb_size = wb[i].size; 280 + } 281 + 349 282 if (i == VENC_H264_VPU_WORK_BUF_SKIP_FRAME) { 350 283 struct mtk_vcodec_fw *handler; 351 284 352 285 handler = inst->vpu_inst.ctx->dev->fw_handler; 353 286 inst->work_bufs[i].va = 354 - mtk_vcodec_fw_map_dm_addr(handler, wb[i].vpua); 287 + mtk_vcodec_fw_map_dm_addr(handler, vpua); 355 288 inst->work_bufs[i].dma_addr = 0; 356 289 } else { 357 290 ret = mtk_vcodec_mem_alloc(inst->ctx, ··· 382 297 383 298 handler = inst->vpu_inst.ctx->dev->fw_handler; 384 299 tmp_va = mtk_vcodec_fw_map_dm_addr(handler, 385 - wb[i].vpua); 386 - memcpy(inst->work_bufs[i].va, tmp_va, 387 - wb[i].size); 300 + vpua); 301 + memcpy(inst->work_bufs[i].va, tmp_va, wb_size); 388 302 } 389 303 } 390 - wb[i].iova = inst->work_bufs[i].dma_addr; 304 + if (is_34bit) 305 + wb_34[i].iova = inst->work_bufs[i].dma_addr; 306 + else 307 + wb[i].iova = inst->work_bufs[i].dma_addr; 391 308 392 309 mtk_vcodec_debug(inst, 393 310 "work_buf[%d] va=0x%p iova=%pad size=%zu", ··· 429 342 return irq_status; 430 343 } 431 344 432 - static int h264_frame_type(struct venc_h264_inst *inst) 345 + static int h264_frame_type(unsigned int frm_cnt, unsigned int gop_size, 346 + unsigned int intra_period) 433 347 { 434 - if ((inst->vsi->config.gop_size != 0 && 435 - (inst->frm_cnt % inst->vsi->config.gop_size) == 0) || 436 - (inst->frm_cnt == 0 && inst->vsi->config.gop_size == 0)) { 348 + if ((gop_size != 0 && (frm_cnt % gop_size) == 0) || 349 + (frm_cnt == 0 && gop_size == 0)) { 437 350 /* IDR frame */ 438 351 return VENC_H264_IDR_FRM; 439 - } else if ((inst->vsi->config.intra_period != 0 && 440 - (inst->frm_cnt % inst->vsi->config.intra_period) == 0) || 441 - (inst->frm_cnt == 0 && inst->vsi->config.intra_period == 0)) { 352 + } else if ((intra_period != 0 && (frm_cnt % intra_period) == 0) || 353 + (frm_cnt == 0 && intra_period == 0)) { 442 354 /* I frame */ 443 355 return VENC_H264_I_FRM; 444 356 } else { 445 357 return VENC_H264_P_FRM; /* Note: B frames are not supported */ 446 358 } 447 359 } 360 + 448 361 static int h264_encode_sps(struct venc_h264_inst *inst, 449 362 struct mtk_vcodec_mem *bs_buf, 450 363 unsigned int *bs_size) ··· 525 438 unsigned int *bs_size) 526 439 { 527 440 int ret = 0; 441 + unsigned int gop_size; 442 + unsigned int intra_period; 528 443 unsigned int irq_status; 529 444 struct venc_frame_info frame_info; 445 + struct mtk_vcodec_ctx *ctx = inst->ctx; 530 446 531 447 mtk_vcodec_debug_enter(inst); 532 448 mtk_vcodec_debug(inst, "frm_cnt = %d\n ", inst->frm_cnt); 449 + 450 + if (MTK_ENC_IOVA_IS_34BIT(ctx)) { 451 + gop_size = inst->vsi_34->config.gop_size; 452 + intra_period = inst->vsi_34->config.intra_period; 453 + } else { 454 + gop_size = inst->vsi->config.gop_size; 455 + intra_period = inst->vsi->config.intra_period; 456 + } 533 457 frame_info.frm_count = inst->frm_cnt; 534 458 frame_info.skip_frm_count = inst->skip_frm_cnt; 535 - frame_info.frm_type = h264_frame_type(inst); 459 + frame_info.frm_type = h264_frame_type(inst->frm_cnt, gop_size, 460 + intra_period); 536 461 mtk_vcodec_debug(inst, "frm_count = %d,skip_frm_count =%d,frm_type=%d.\n", 537 462 frame_info.frm_count, frame_info.skip_frm_count, 538 463 frame_info.frm_type); 539 - ret = vpu_enc_encode(&inst->vpu_inst, H264_BS_MODE_FRAME, frm_buf, bs_buf, &frame_info); 464 + 465 + ret = vpu_enc_encode(&inst->vpu_inst, H264_BS_MODE_FRAME, 466 + frm_buf, bs_buf, &frame_info); 540 467 if (ret) 541 468 return ret; 542 469 ··· 618 517 619 518 ret = vpu_enc_init(&inst->vpu_inst); 620 519 621 - inst->vsi = (struct venc_h264_vsi *)inst->vpu_inst.vsi; 520 + if (MTK_ENC_IOVA_IS_34BIT(ctx)) 521 + inst->vsi_34 = (struct venc_h264_vsi_34 *)inst->vpu_inst.vsi; 522 + else 523 + inst->vsi = (struct venc_h264_vsi *)inst->vpu_inst.vsi; 622 524 623 525 mtk_vcodec_debug_leave(inst); 624 526 ··· 728 624 return ret; 729 625 } 730 626 627 + static void h264_enc_set_vsi_configs(struct venc_h264_inst *inst, 628 + struct venc_enc_param *enc_prm) 629 + { 630 + inst->vsi->config.input_fourcc = enc_prm->input_yuv_fmt; 631 + inst->vsi->config.bitrate = enc_prm->bitrate; 632 + inst->vsi->config.pic_w = enc_prm->width; 633 + inst->vsi->config.pic_h = enc_prm->height; 634 + inst->vsi->config.buf_w = enc_prm->buf_width; 635 + inst->vsi->config.buf_h = enc_prm->buf_height; 636 + inst->vsi->config.gop_size = enc_prm->gop_size; 637 + inst->vsi->config.framerate = enc_prm->frm_rate; 638 + inst->vsi->config.intra_period = enc_prm->intra_period; 639 + inst->vsi->config.profile = 640 + h264_get_profile(inst, enc_prm->h264_profile); 641 + inst->vsi->config.level = 642 + h264_get_level(inst, enc_prm->h264_level); 643 + inst->vsi->config.wfd = 0; 644 + } 645 + 646 + static void h264_enc_set_vsi_34_configs(struct venc_h264_inst *inst, 647 + struct venc_enc_param *enc_prm) 648 + { 649 + inst->vsi_34->config.input_fourcc = enc_prm->input_yuv_fmt; 650 + inst->vsi_34->config.bitrate = enc_prm->bitrate; 651 + inst->vsi_34->config.pic_w = enc_prm->width; 652 + inst->vsi_34->config.pic_h = enc_prm->height; 653 + inst->vsi_34->config.buf_w = enc_prm->buf_width; 654 + inst->vsi_34->config.buf_h = enc_prm->buf_height; 655 + inst->vsi_34->config.gop_size = enc_prm->gop_size; 656 + inst->vsi_34->config.framerate = enc_prm->frm_rate; 657 + inst->vsi_34->config.intra_period = enc_prm->intra_period; 658 + inst->vsi_34->config.profile = 659 + h264_get_profile(inst, enc_prm->h264_profile); 660 + inst->vsi_34->config.level = 661 + h264_get_level(inst, enc_prm->h264_level); 662 + inst->vsi_34->config.wfd = 0; 663 + } 664 + 731 665 static int h264_enc_set_param(void *handle, 732 666 enum venc_set_param_type type, 733 667 struct venc_enc_param *enc_prm) 734 668 { 735 669 int ret = 0; 736 670 struct venc_h264_inst *inst = (struct venc_h264_inst *)handle; 671 + struct mtk_vcodec_ctx *ctx = inst->ctx; 672 + const bool is_34bit = MTK_ENC_IOVA_IS_34BIT(ctx); 737 673 738 674 mtk_vcodec_debug(inst, "->type=%d", type); 739 675 740 676 switch (type) { 741 677 case VENC_SET_PARAM_ENC: 742 - inst->vsi->config.input_fourcc = enc_prm->input_yuv_fmt; 743 - inst->vsi->config.bitrate = enc_prm->bitrate; 744 - inst->vsi->config.pic_w = enc_prm->width; 745 - inst->vsi->config.pic_h = enc_prm->height; 746 - inst->vsi->config.buf_w = enc_prm->buf_width; 747 - inst->vsi->config.buf_h = enc_prm->buf_height; 748 - inst->vsi->config.gop_size = enc_prm->gop_size; 749 - inst->vsi->config.framerate = enc_prm->frm_rate; 750 - inst->vsi->config.intra_period = enc_prm->intra_period; 751 - inst->vsi->config.profile = 752 - h264_get_profile(inst, enc_prm->h264_profile); 753 - inst->vsi->config.level = 754 - h264_get_level(inst, enc_prm->h264_level); 755 - inst->vsi->config.wfd = 0; 678 + if (is_34bit) 679 + h264_enc_set_vsi_34_configs(inst, enc_prm); 680 + else 681 + h264_enc_set_vsi_configs(inst, enc_prm); 756 682 ret = vpu_enc_set_param(&inst->vpu_inst, type, enc_prm); 757 683 if (ret) 758 684 break; ··· 790 656 h264_enc_free_work_buf(inst); 791 657 inst->work_buf_allocated = false; 792 658 } 793 - ret = h264_enc_alloc_work_buf(inst); 659 + ret = h264_enc_alloc_work_buf(inst, is_34bit); 794 660 if (ret) 795 661 break; 796 662 inst->work_buf_allocated = true;
+24
drivers/media/platform/mediatek/vcodec/venc_ipi_msg.h
··· 101 101 }; 102 102 103 103 /** 104 + * struct venc_ap_ipi_msg_enc_ext_34 - AP to SCP extended enc cmd structure 105 + * @msg_id: message id (AP_IPIMSG_XXX_ENC_ENCODE) 106 + * @vpu_inst_addr: VPU encoder instance addr 107 + * @bs_mode: bitstream mode for h264 108 + * @reserved: for struct padding 109 + * @input_addr: input frame buffer 34 bit address 110 + * @bs_addr: output bitstream buffer 34 bit address 111 + * @bs_size: bitstream buffer size 112 + * @data_item: number of items in the data array 113 + * @data: data array to store the set parameters 114 + */ 115 + struct venc_ap_ipi_msg_enc_ext_34 { 116 + u32 msg_id; 117 + u32 vpu_inst_addr; 118 + u32 bs_mode; 119 + u32 reserved; 120 + u64 input_addr[3]; 121 + u64 bs_addr; 122 + u32 bs_size; 123 + u32 data_item; 124 + u32 data[32]; 125 + }; 126 + 127 + /** 104 128 * struct venc_ap_ipi_msg_deinit - AP to VPU deinit cmd structure 105 129 * @msg_id: message id (AP_IPIMSG_XXX_ENC_DEINIT) 106 130 * @vpu_inst_addr: VPU encoder instance addr
+72 -4
drivers/media/platform/mediatek/vcodec/venc_vpu_if.c
··· 222 222 return 0; 223 223 } 224 224 225 - int vpu_enc_encode(struct venc_vpu_inst *vpu, unsigned int bs_mode, 226 - struct venc_frm_buf *frm_buf, 227 - struct mtk_vcodec_mem *bs_buf, 228 - struct venc_frame_info *frame_info) 225 + static int vpu_enc_encode_32bits(struct venc_vpu_inst *vpu, 226 + unsigned int bs_mode, 227 + struct venc_frm_buf *frm_buf, 228 + struct mtk_vcodec_mem *bs_buf, 229 + struct venc_frame_info *frame_info) 229 230 { 230 231 const bool is_ext = MTK_ENC_CTX_IS_EXT(vpu->ctx); 231 232 size_t msg_size = is_ext ? ··· 267 266 bs_mode); 268 267 return -EINVAL; 269 268 } 269 + 270 + return 0; 271 + } 272 + 273 + static int vpu_enc_encode_34bits(struct venc_vpu_inst *vpu, 274 + unsigned int bs_mode, 275 + struct venc_frm_buf *frm_buf, 276 + struct mtk_vcodec_mem *bs_buf, 277 + struct venc_frame_info *frame_info) 278 + { 279 + struct venc_ap_ipi_msg_enc_ext_34 out; 280 + size_t msg_size = sizeof(struct venc_ap_ipi_msg_enc_ext_34); 281 + 282 + mtk_vcodec_debug(vpu, "bs_mode %d ->", bs_mode); 283 + 284 + memset(&out, 0, sizeof(out)); 285 + out.msg_id = AP_IPIMSG_ENC_ENCODE; 286 + out.vpu_inst_addr = vpu->inst_addr; 287 + out.bs_mode = bs_mode; 288 + 289 + if (frm_buf) { 290 + if ((frm_buf->fb_addr[0].dma_addr % 16 == 0) && 291 + (frm_buf->fb_addr[1].dma_addr % 16 == 0) && 292 + (frm_buf->fb_addr[2].dma_addr % 16 == 0)) { 293 + out.input_addr[0] = frm_buf->fb_addr[0].dma_addr; 294 + out.input_addr[1] = frm_buf->fb_addr[1].dma_addr; 295 + out.input_addr[2] = frm_buf->fb_addr[2].dma_addr; 296 + } else { 297 + mtk_vcodec_err(vpu, "dma_addr not align to 16"); 298 + return -EINVAL; 299 + } 300 + } 301 + if (bs_buf) { 302 + out.bs_addr = bs_buf->dma_addr; 303 + out.bs_size = bs_buf->size; 304 + } 305 + if (frame_info) { 306 + out.data_item = 3; 307 + out.data[0] = frame_info->frm_count; 308 + out.data[1] = frame_info->skip_frm_count; 309 + out.data[2] = frame_info->frm_type; 310 + } 311 + if (vpu_enc_send_msg(vpu, &out, msg_size)) { 312 + mtk_vcodec_err(vpu, "AP_IPIMSG_ENC_ENCODE %d fail", 313 + bs_mode); 314 + return -EINVAL; 315 + } 316 + 317 + return 0; 318 + } 319 + 320 + int vpu_enc_encode(struct venc_vpu_inst *vpu, unsigned int bs_mode, 321 + struct venc_frm_buf *frm_buf, 322 + struct mtk_vcodec_mem *bs_buf, 323 + struct venc_frame_info *frame_info) 324 + { 325 + int ret; 326 + 327 + if (MTK_ENC_IOVA_IS_34BIT(vpu->ctx)) 328 + ret = vpu_enc_encode_34bits(vpu, bs_mode, 329 + frm_buf, bs_buf, frame_info); 330 + else 331 + ret = vpu_enc_encode_32bits(vpu, bs_mode, 332 + frm_buf, bs_buf, frame_info); 333 + 334 + if (ret) 335 + return ret; 270 336 271 337 mtk_vcodec_debug(vpu, "bs_mode %d state %d size %d key_frm %d <-", 272 338 bs_mode, vpu->state, vpu->bs_size, vpu->is_key_frm);