961 lines · c
1// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)2/*3 * Wave5 series multi-standard codec IP - helper functions4 *5 * Copyright (C) 2021-2023 CHIPS&MEDIA INC6 */7 8#include <linux/bug.h>9#include "wave5-vpuapi.h"10#include "wave5-regdefine.h"11#include "wave5.h"12 13#define DECODE_ALL_TEMPORAL_LAYERS 014#define DECODE_ALL_SPATIAL_LAYERS 015 16static int wave5_initialize_vpu(struct device *dev, u8 *code, size_t size)17{18 int ret;19 struct vpu_device *vpu_dev = dev_get_drvdata(dev);20 21 ret = mutex_lock_interruptible(&vpu_dev->hw_lock);22 if (ret)23 return ret;24 25 if (wave5_vpu_is_init(vpu_dev)) {26 wave5_vpu_re_init(dev, (void *)code, size);27 ret = -EBUSY;28 goto err_out;29 }30 31 ret = wave5_vpu_reset(dev, SW_RESET_ON_BOOT);32 if (ret)33 goto err_out;34 35 ret = wave5_vpu_init(dev, (void *)code, size);36 37err_out:38 mutex_unlock(&vpu_dev->hw_lock);39 return ret;40}41 42int wave5_vpu_init_with_bitcode(struct device *dev, u8 *bitcode, size_t size)43{44 if (!bitcode || size == 0)45 return -EINVAL;46 47 return wave5_initialize_vpu(dev, bitcode, size);48}49 50int wave5_vpu_flush_instance(struct vpu_instance *inst)51{52 int ret = 0;53 int retry = 0;54 55 ret = mutex_lock_interruptible(&inst->dev->hw_lock);56 if (ret)57 return ret;58 do {59 /*60 * Repeat the FLUSH command until the firmware reports that the61 * VPU isn't running anymore62 */63 ret = wave5_vpu_hw_flush_instance(inst);64 if (ret < 0 && ret != -EBUSY) {65 dev_warn(inst->dev->dev, "Flush of %s instance with id: %d fail: %d\n",66 inst->type == VPU_INST_TYPE_DEC ? "DECODER" : "ENCODER", inst->id,67 ret);68 mutex_unlock(&inst->dev->hw_lock);69 return ret;70 }71 if (ret == -EBUSY && retry++ >= MAX_FIRMWARE_CALL_RETRY) {72 dev_warn(inst->dev->dev, "Flush of %s instance with id: %d timed out!\n",73 inst->type == VPU_INST_TYPE_DEC ? "DECODER" : "ENCODER", inst->id);74 mutex_unlock(&inst->dev->hw_lock);75 return -ETIMEDOUT;76 }77 } while (ret != 0);78 mutex_unlock(&inst->dev->hw_lock);79 80 return ret;81}82 83int wave5_vpu_get_version_info(struct device *dev, u32 *revision, unsigned int *product_id)84{85 int ret;86 struct vpu_device *vpu_dev = dev_get_drvdata(dev);87 88 ret = mutex_lock_interruptible(&vpu_dev->hw_lock);89 if (ret)90 return ret;91 92 if (!wave5_vpu_is_init(vpu_dev)) {93 ret = -EINVAL;94 goto err_out;95 }96 97 if (product_id)98 *product_id = vpu_dev->product;99 ret = wave5_vpu_get_version(vpu_dev, revision);100 101err_out:102 mutex_unlock(&vpu_dev->hw_lock);103 return ret;104}105 106static int wave5_check_dec_open_param(struct vpu_instance *inst, struct dec_open_param *param)107{108 if (inst->id >= MAX_NUM_INSTANCE) {109 dev_err(inst->dev->dev, "Too many simultaneous instances: %d (max: %u)\n",110 inst->id, MAX_NUM_INSTANCE);111 return -EOPNOTSUPP;112 }113 114 if (param->bitstream_buffer % 8) {115 dev_err(inst->dev->dev,116 "Bitstream buffer must be aligned to a multiple of 8\n");117 return -EINVAL;118 }119 120 if (param->bitstream_buffer_size % 1024 ||121 param->bitstream_buffer_size < MIN_BITSTREAM_BUFFER_SIZE) {122 dev_err(inst->dev->dev,123 "Bitstream buffer size must be aligned to a multiple of 1024 and have a minimum size of %d\n",124 MIN_BITSTREAM_BUFFER_SIZE);125 return -EINVAL;126 }127 128 return 0;129}130 131int wave5_vpu_dec_open(struct vpu_instance *inst, struct dec_open_param *open_param)132{133 struct dec_info *p_dec_info;134 int ret;135 struct vpu_device *vpu_dev = inst->dev;136 dma_addr_t buffer_addr;137 size_t buffer_size;138 139 ret = wave5_check_dec_open_param(inst, open_param);140 if (ret)141 return ret;142 143 ret = mutex_lock_interruptible(&vpu_dev->hw_lock);144 if (ret)145 return ret;146 147 if (!wave5_vpu_is_init(vpu_dev)) {148 mutex_unlock(&vpu_dev->hw_lock);149 return -ENODEV;150 }151 152 p_dec_info = &inst->codec_info->dec_info;153 memcpy(&p_dec_info->open_param, open_param, sizeof(struct dec_open_param));154 155 buffer_addr = open_param->bitstream_buffer;156 buffer_size = open_param->bitstream_buffer_size;157 p_dec_info->stream_wr_ptr = buffer_addr;158 p_dec_info->stream_rd_ptr = buffer_addr;159 p_dec_info->stream_buf_start_addr = buffer_addr;160 p_dec_info->stream_buf_size = buffer_size;161 p_dec_info->stream_buf_end_addr = buffer_addr + buffer_size;162 p_dec_info->reorder_enable = TRUE;163 p_dec_info->temp_id_select_mode = TEMPORAL_ID_MODE_ABSOLUTE;164 p_dec_info->target_temp_id = DECODE_ALL_TEMPORAL_LAYERS;165 p_dec_info->target_spatial_id = DECODE_ALL_SPATIAL_LAYERS;166 167 ret = wave5_vpu_build_up_dec_param(inst, open_param);168 mutex_unlock(&vpu_dev->hw_lock);169 170 return ret;171}172 173static int reset_auxiliary_buffers(struct vpu_instance *inst, unsigned int index)174{175 struct dec_info *p_dec_info = &inst->codec_info->dec_info;176 177 if (index >= MAX_REG_FRAME)178 return 1;179 180 if (p_dec_info->vb_mv[index].size == 0 && p_dec_info->vb_fbc_y_tbl[index].size == 0 &&181 p_dec_info->vb_fbc_c_tbl[index].size == 0)182 return 1;183 184 wave5_vdi_free_dma_memory(inst->dev, &p_dec_info->vb_mv[index]);185 wave5_vdi_free_dma_memory(inst->dev, &p_dec_info->vb_fbc_y_tbl[index]);186 wave5_vdi_free_dma_memory(inst->dev, &p_dec_info->vb_fbc_c_tbl[index]);187 188 return 0;189}190 191int wave5_vpu_dec_close(struct vpu_instance *inst, u32 *fail_res)192{193 struct dec_info *p_dec_info = &inst->codec_info->dec_info;194 int ret;195 int retry = 0;196 struct vpu_device *vpu_dev = inst->dev;197 int i;198 199 *fail_res = 0;200 if (!inst->codec_info)201 return -EINVAL;202 203 ret = mutex_lock_interruptible(&vpu_dev->hw_lock);204 if (ret)205 return ret;206 207 do {208 ret = wave5_vpu_dec_finish_seq(inst, fail_res);209 if (ret < 0 && *fail_res != WAVE5_SYSERR_VPU_STILL_RUNNING) {210 dev_warn(inst->dev->dev, "dec_finish_seq timed out\n");211 goto unlock_and_return;212 }213 214 if (*fail_res == WAVE5_SYSERR_VPU_STILL_RUNNING &&215 retry++ >= MAX_FIRMWARE_CALL_RETRY) {216 ret = -ETIMEDOUT;217 goto unlock_and_return;218 }219 } while (ret != 0);220 221 dev_dbg(inst->dev->dev, "%s: dec_finish_seq complete\n", __func__);222 223 wave5_vdi_free_dma_memory(vpu_dev, &p_dec_info->vb_work);224 225 for (i = 0 ; i < MAX_REG_FRAME; i++) {226 ret = reset_auxiliary_buffers(inst, i);227 if (ret) {228 ret = 0;229 break;230 }231 }232 233 wave5_vdi_free_dma_memory(vpu_dev, &p_dec_info->vb_task);234 235unlock_and_return:236 mutex_unlock(&vpu_dev->hw_lock);237 238 return ret;239}240 241int wave5_vpu_dec_issue_seq_init(struct vpu_instance *inst)242{243 int ret;244 struct vpu_device *vpu_dev = inst->dev;245 246 ret = mutex_lock_interruptible(&vpu_dev->hw_lock);247 if (ret)248 return ret;249 250 ret = wave5_vpu_dec_init_seq(inst);251 252 mutex_unlock(&vpu_dev->hw_lock);253 254 return ret;255}256 257int wave5_vpu_dec_complete_seq_init(struct vpu_instance *inst, struct dec_initial_info *info)258{259 struct dec_info *p_dec_info = &inst->codec_info->dec_info;260 int ret;261 struct vpu_device *vpu_dev = inst->dev;262 263 ret = mutex_lock_interruptible(&vpu_dev->hw_lock);264 if (ret)265 return ret;266 267 ret = wave5_vpu_dec_get_seq_info(inst, info);268 if (!ret)269 p_dec_info->initial_info_obtained = true;270 271 info->rd_ptr = wave5_dec_get_rd_ptr(inst);272 info->wr_ptr = p_dec_info->stream_wr_ptr;273 274 p_dec_info->initial_info = *info;275 276 mutex_unlock(&vpu_dev->hw_lock);277 278 return ret;279}280 281int wave5_vpu_dec_register_frame_buffer_ex(struct vpu_instance *inst, int num_of_decoding_fbs,282 int num_of_display_fbs, int stride, int height)283{284 struct dec_info *p_dec_info;285 int ret;286 struct vpu_device *vpu_dev = inst->dev;287 struct frame_buffer *fb;288 289 if (num_of_decoding_fbs >= WAVE5_MAX_FBS || num_of_display_fbs >= WAVE5_MAX_FBS)290 return -EINVAL;291 292 p_dec_info = &inst->codec_info->dec_info;293 p_dec_info->num_of_decoding_fbs = num_of_decoding_fbs;294 p_dec_info->num_of_display_fbs = num_of_display_fbs;295 p_dec_info->stride = stride;296 297 if (!p_dec_info->initial_info_obtained)298 return -EINVAL;299 300 if (stride < p_dec_info->initial_info.pic_width || (stride % 8 != 0) ||301 height < p_dec_info->initial_info.pic_height)302 return -EINVAL;303 304 ret = mutex_lock_interruptible(&vpu_dev->hw_lock);305 if (ret)306 return ret;307 308 fb = inst->frame_buf;309 ret = wave5_vpu_dec_register_framebuffer(inst, &fb[p_dec_info->num_of_decoding_fbs],310 LINEAR_FRAME_MAP, p_dec_info->num_of_display_fbs);311 if (ret)312 goto err_out;313 314 ret = wave5_vpu_dec_register_framebuffer(inst, &fb[0], COMPRESSED_FRAME_MAP,315 p_dec_info->num_of_decoding_fbs);316 317err_out:318 mutex_unlock(&vpu_dev->hw_lock);319 320 return ret;321}322 323int wave5_vpu_dec_get_bitstream_buffer(struct vpu_instance *inst, dma_addr_t *prd_ptr,324 dma_addr_t *pwr_ptr, size_t *size)325{326 struct dec_info *p_dec_info;327 dma_addr_t rd_ptr;328 dma_addr_t wr_ptr;329 int room;330 struct vpu_device *vpu_dev = inst->dev;331 int ret;332 333 p_dec_info = &inst->codec_info->dec_info;334 335 ret = mutex_lock_interruptible(&vpu_dev->hw_lock);336 if (ret)337 return ret;338 rd_ptr = wave5_dec_get_rd_ptr(inst);339 mutex_unlock(&vpu_dev->hw_lock);340 341 wr_ptr = p_dec_info->stream_wr_ptr;342 343 if (wr_ptr < rd_ptr)344 room = rd_ptr - wr_ptr;345 else346 room = (p_dec_info->stream_buf_end_addr - wr_ptr) +347 (rd_ptr - p_dec_info->stream_buf_start_addr);348 room--;349 350 if (prd_ptr)351 *prd_ptr = rd_ptr;352 if (pwr_ptr)353 *pwr_ptr = wr_ptr;354 if (size)355 *size = room;356 357 return 0;358}359 360int wave5_vpu_dec_update_bitstream_buffer(struct vpu_instance *inst, size_t size)361{362 struct dec_info *p_dec_info;363 dma_addr_t wr_ptr;364 dma_addr_t rd_ptr;365 int ret;366 struct vpu_device *vpu_dev = inst->dev;367 368 if (!inst->codec_info)369 return -EINVAL;370 371 p_dec_info = &inst->codec_info->dec_info;372 wr_ptr = p_dec_info->stream_wr_ptr;373 rd_ptr = p_dec_info->stream_rd_ptr;374 375 if (size > 0) {376 if (wr_ptr < rd_ptr && rd_ptr <= wr_ptr + size)377 return -EINVAL;378 379 wr_ptr += size;380 381 if (wr_ptr > p_dec_info->stream_buf_end_addr) {382 u32 room = wr_ptr - p_dec_info->stream_buf_end_addr;383 384 wr_ptr = p_dec_info->stream_buf_start_addr;385 wr_ptr += room;386 } else if (wr_ptr == p_dec_info->stream_buf_end_addr) {387 wr_ptr = p_dec_info->stream_buf_start_addr;388 }389 390 p_dec_info->stream_wr_ptr = wr_ptr;391 p_dec_info->stream_rd_ptr = rd_ptr;392 }393 394 ret = mutex_lock_interruptible(&vpu_dev->hw_lock);395 if (ret)396 return ret;397 ret = wave5_vpu_dec_set_bitstream_flag(inst, (size == 0));398 mutex_unlock(&vpu_dev->hw_lock);399 400 return ret;401}402 403int wave5_vpu_dec_start_one_frame(struct vpu_instance *inst, u32 *res_fail)404{405 struct dec_info *p_dec_info = &inst->codec_info->dec_info;406 int ret;407 struct vpu_device *vpu_dev = inst->dev;408 409 if (p_dec_info->stride == 0) /* this means frame buffers have not been registered. */410 return -EINVAL;411 412 ret = mutex_lock_interruptible(&vpu_dev->hw_lock);413 if (ret)414 return ret;415 416 ret = wave5_vpu_decode(inst, res_fail);417 418 mutex_unlock(&vpu_dev->hw_lock);419 420 return ret;421}422 423int wave5_vpu_dec_set_rd_ptr(struct vpu_instance *inst, dma_addr_t addr, int update_wr_ptr)424{425 struct dec_info *p_dec_info = &inst->codec_info->dec_info;426 int ret;427 struct vpu_device *vpu_dev = inst->dev;428 429 ret = mutex_lock_interruptible(&vpu_dev->hw_lock);430 if (ret)431 return ret;432 433 ret = wave5_dec_set_rd_ptr(inst, addr);434 435 p_dec_info->stream_rd_ptr = addr;436 if (update_wr_ptr)437 p_dec_info->stream_wr_ptr = addr;438 439 mutex_unlock(&vpu_dev->hw_lock);440 441 return ret;442}443 444dma_addr_t wave5_vpu_dec_get_rd_ptr(struct vpu_instance *inst)445{446 int ret;447 dma_addr_t rd_ptr;448 449 ret = mutex_lock_interruptible(&inst->dev->hw_lock);450 if (ret)451 return ret;452 453 rd_ptr = wave5_dec_get_rd_ptr(inst);454 455 mutex_unlock(&inst->dev->hw_lock);456 457 return rd_ptr;458}459 460int wave5_vpu_dec_get_output_info(struct vpu_instance *inst, struct dec_output_info *info)461{462 struct dec_info *p_dec_info;463 int ret;464 struct vpu_rect rect_info;465 u32 val;466 u32 decoded_index;467 u32 disp_idx;468 u32 max_dec_index;469 struct vpu_device *vpu_dev = inst->dev;470 struct dec_output_info *disp_info;471 472 if (!info)473 return -EINVAL;474 475 p_dec_info = &inst->codec_info->dec_info;476 477 ret = mutex_lock_interruptible(&vpu_dev->hw_lock);478 if (ret)479 return ret;480 481 memset(info, 0, sizeof(*info));482 483 ret = wave5_vpu_dec_get_result(inst, info);484 if (ret) {485 info->rd_ptr = p_dec_info->stream_rd_ptr;486 info->wr_ptr = p_dec_info->stream_wr_ptr;487 goto err_out;488 }489 490 decoded_index = info->index_frame_decoded;491 492 /* calculate display frame region */493 val = 0;494 rect_info.left = 0;495 rect_info.right = 0;496 rect_info.top = 0;497 rect_info.bottom = 0;498 499 if (decoded_index < WAVE5_MAX_FBS) {500 if (inst->std == W_HEVC_DEC || inst->std == W_AVC_DEC)501 rect_info = p_dec_info->initial_info.pic_crop_rect;502 503 if (inst->std == W_HEVC_DEC)504 p_dec_info->dec_out_info[decoded_index].decoded_poc = info->decoded_poc;505 506 p_dec_info->dec_out_info[decoded_index].rc_decoded = rect_info;507 }508 info->rc_decoded = rect_info;509 510 disp_idx = info->index_frame_display;511 if (info->index_frame_display >= 0 && info->index_frame_display < WAVE5_MAX_FBS) {512 disp_info = &p_dec_info->dec_out_info[disp_idx];513 if (info->index_frame_display != info->index_frame_decoded) {514 /*515 * when index_frame_decoded < 0, and index_frame_display >= 0516 * info->dec_pic_width and info->dec_pic_height are still valid517 * but those of p_dec_info->dec_out_info[disp_idx] are invalid in VP9518 */519 info->disp_pic_width = disp_info->dec_pic_width;520 info->disp_pic_height = disp_info->dec_pic_height;521 } else {522 info->disp_pic_width = info->dec_pic_width;523 info->disp_pic_height = info->dec_pic_height;524 }525 526 info->rc_display = disp_info->rc_decoded;527 528 } else {529 info->rc_display.left = 0;530 info->rc_display.right = 0;531 info->rc_display.top = 0;532 info->rc_display.bottom = 0;533 info->disp_pic_width = 0;534 info->disp_pic_height = 0;535 }536 537 p_dec_info->stream_rd_ptr = wave5_dec_get_rd_ptr(inst);538 p_dec_info->frame_display_flag = vpu_read_reg(vpu_dev, W5_RET_DEC_DISP_IDC);539 540 val = p_dec_info->num_of_decoding_fbs; //fb_offset541 542 max_dec_index = (p_dec_info->num_of_decoding_fbs > p_dec_info->num_of_display_fbs) ?543 p_dec_info->num_of_decoding_fbs : p_dec_info->num_of_display_fbs;544 545 if (info->index_frame_display >= 0 &&546 info->index_frame_display < (int)max_dec_index)547 info->disp_frame = inst->frame_buf[val + info->index_frame_display];548 549 info->rd_ptr = p_dec_info->stream_rd_ptr;550 info->wr_ptr = p_dec_info->stream_wr_ptr;551 info->frame_display_flag = p_dec_info->frame_display_flag;552 553 info->sequence_no = p_dec_info->initial_info.sequence_no;554 if (decoded_index < WAVE5_MAX_FBS)555 p_dec_info->dec_out_info[decoded_index] = *info;556 557 if (disp_idx < WAVE5_MAX_FBS)558 info->disp_frame.sequence_no = info->sequence_no;559 560 if (info->sequence_changed) {561 memcpy((void *)&p_dec_info->initial_info, (void *)&p_dec_info->new_seq_info,562 sizeof(struct dec_initial_info));563 p_dec_info->initial_info.sequence_no++;564 }565 566err_out:567 mutex_unlock(&vpu_dev->hw_lock);568 569 return ret;570}571 572int wave5_vpu_dec_clr_disp_flag(struct vpu_instance *inst, int index)573{574 struct dec_info *p_dec_info = &inst->codec_info->dec_info;575 int ret;576 struct vpu_device *vpu_dev = inst->dev;577 578 if (index >= p_dec_info->num_of_display_fbs)579 return -EINVAL;580 581 ret = mutex_lock_interruptible(&vpu_dev->hw_lock);582 if (ret)583 return ret;584 ret = wave5_dec_clr_disp_flag(inst, index);585 mutex_unlock(&vpu_dev->hw_lock);586 587 return ret;588}589 590int wave5_vpu_dec_set_disp_flag(struct vpu_instance *inst, int index)591{592 struct dec_info *p_dec_info = &inst->codec_info->dec_info;593 int ret = 0;594 struct vpu_device *vpu_dev = inst->dev;595 596 if (index >= p_dec_info->num_of_display_fbs)597 return -EINVAL;598 599 ret = mutex_lock_interruptible(&vpu_dev->hw_lock);600 if (ret)601 return ret;602 ret = wave5_dec_set_disp_flag(inst, index);603 mutex_unlock(&vpu_dev->hw_lock);604 605 return ret;606}607 608int wave5_vpu_dec_reset_framebuffer(struct vpu_instance *inst, unsigned int index)609{610 if (index >= MAX_REG_FRAME)611 return -EINVAL;612 613 if (inst->frame_vbuf[index].size == 0)614 return -EINVAL;615 616 wave5_vdi_free_dma_memory(inst->dev, &inst->frame_vbuf[index]);617 618 return 0;619}620 621int wave5_vpu_dec_give_command(struct vpu_instance *inst, enum codec_command cmd, void *parameter)622{623 struct dec_info *p_dec_info = &inst->codec_info->dec_info;624 int ret = 0;625 626 switch (cmd) {627 case DEC_GET_QUEUE_STATUS: {628 struct queue_status_info *queue_info = parameter;629 630 queue_info->instance_queue_count = p_dec_info->instance_queue_count;631 queue_info->report_queue_count = p_dec_info->report_queue_count;632 break;633 }634 case DEC_RESET_FRAMEBUF_INFO: {635 int i;636 637 for (i = 0; i < MAX_REG_FRAME; i++) {638 ret = wave5_vpu_dec_reset_framebuffer(inst, i);639 if (ret)640 break;641 }642 643 for (i = 0; i < MAX_REG_FRAME; i++) {644 ret = reset_auxiliary_buffers(inst, i);645 if (ret)646 break;647 }648 649 wave5_vdi_free_dma_memory(inst->dev, &p_dec_info->vb_task);650 break;651 }652 case DEC_GET_SEQ_INFO: {653 struct dec_initial_info *seq_info = parameter;654 655 *seq_info = p_dec_info->initial_info;656 break;657 }658 659 default:660 return -EINVAL;661 }662 663 return ret;664}665 666int wave5_vpu_enc_open(struct vpu_instance *inst, struct enc_open_param *open_param)667{668 struct enc_info *p_enc_info;669 int ret;670 struct vpu_device *vpu_dev = inst->dev;671 672 ret = wave5_vpu_enc_check_open_param(inst, open_param);673 if (ret)674 return ret;675 676 ret = mutex_lock_interruptible(&vpu_dev->hw_lock);677 if (ret)678 return ret;679 680 if (!wave5_vpu_is_init(vpu_dev)) {681 mutex_unlock(&vpu_dev->hw_lock);682 return -ENODEV;683 }684 685 p_enc_info = &inst->codec_info->enc_info;686 p_enc_info->open_param = *open_param;687 688 ret = wave5_vpu_build_up_enc_param(vpu_dev->dev, inst, open_param);689 mutex_unlock(&vpu_dev->hw_lock);690 691 return ret;692}693 694int wave5_vpu_enc_close(struct vpu_instance *inst, u32 *fail_res)695{696 struct enc_info *p_enc_info = &inst->codec_info->enc_info;697 int ret;698 int retry = 0;699 struct vpu_device *vpu_dev = inst->dev;700 701 *fail_res = 0;702 if (!inst->codec_info)703 return -EINVAL;704 705 ret = mutex_lock_interruptible(&vpu_dev->hw_lock);706 if (ret)707 return ret;708 709 do {710 ret = wave5_vpu_enc_finish_seq(inst, fail_res);711 if (ret < 0 && *fail_res != WAVE5_SYSERR_VPU_STILL_RUNNING) {712 dev_warn(inst->dev->dev, "enc_finish_seq timed out\n");713 mutex_unlock(&vpu_dev->hw_lock);714 return ret;715 }716 717 if (*fail_res == WAVE5_SYSERR_VPU_STILL_RUNNING &&718 retry++ >= MAX_FIRMWARE_CALL_RETRY) {719 mutex_unlock(&vpu_dev->hw_lock);720 return -ETIMEDOUT;721 }722 } while (ret != 0);723 724 dev_dbg(inst->dev->dev, "%s: enc_finish_seq complete\n", __func__);725 726 wave5_vdi_free_dma_memory(vpu_dev, &p_enc_info->vb_work);727 728 if (inst->std == W_HEVC_ENC || inst->std == W_AVC_ENC) {729 wave5_vdi_free_dma_memory(vpu_dev, &p_enc_info->vb_sub_sam_buf);730 wave5_vdi_free_dma_memory(vpu_dev, &p_enc_info->vb_mv);731 wave5_vdi_free_dma_memory(vpu_dev, &p_enc_info->vb_fbc_y_tbl);732 wave5_vdi_free_dma_memory(vpu_dev, &p_enc_info->vb_fbc_c_tbl);733 }734 735 wave5_vdi_free_dma_memory(vpu_dev, &p_enc_info->vb_task);736 737 mutex_unlock(&vpu_dev->hw_lock);738 739 return 0;740}741 742int wave5_vpu_enc_register_frame_buffer(struct vpu_instance *inst, unsigned int num,743 unsigned int stride, int height,744 enum tiled_map_type map_type)745{746 struct enc_info *p_enc_info = &inst->codec_info->enc_info;747 int ret;748 struct vpu_device *vpu_dev = inst->dev;749 unsigned int size_luma, size_chroma;750 int i;751 752 if (p_enc_info->stride)753 return -EINVAL;754 755 if (!p_enc_info->initial_info_obtained)756 return -EINVAL;757 758 if (num < p_enc_info->initial_info.min_frame_buffer_count)759 return -EINVAL;760 761 if (stride == 0 || stride % 8 != 0)762 return -EINVAL;763 764 if (height <= 0)765 return -EINVAL;766 767 ret = mutex_lock_interruptible(&vpu_dev->hw_lock);768 if (ret)769 return ret;770 771 p_enc_info->num_frame_buffers = num;772 p_enc_info->stride = stride;773 774 size_luma = stride * height;775 size_chroma = ALIGN(stride / 2, 16) * height;776 777 for (i = 0; i < num; i++) {778 if (!inst->frame_buf[i].update_fb_info)779 continue;780 781 inst->frame_buf[i].update_fb_info = false;782 inst->frame_buf[i].stride = stride;783 inst->frame_buf[i].height = height;784 inst->frame_buf[i].map_type = COMPRESSED_FRAME_MAP;785 inst->frame_buf[i].buf_y_size = size_luma;786 inst->frame_buf[i].buf_cb = inst->frame_buf[i].buf_y + size_luma;787 inst->frame_buf[i].buf_cb_size = size_chroma;788 inst->frame_buf[i].buf_cr_size = 0;789 }790 791 ret = wave5_vpu_enc_register_framebuffer(inst->dev->dev, inst, &inst->frame_buf[0],792 COMPRESSED_FRAME_MAP,793 p_enc_info->num_frame_buffers);794 795 mutex_unlock(&vpu_dev->hw_lock);796 797 return ret;798}799 800static int wave5_check_enc_param(struct vpu_instance *inst, struct enc_param *param)801{802 struct enc_info *p_enc_info = &inst->codec_info->enc_info;803 804 if (!param)805 return -EINVAL;806 807 if (!param->source_frame)808 return -EINVAL;809 810 if (p_enc_info->open_param.bit_rate == 0 && inst->std == W_HEVC_ENC) {811 if (param->pic_stream_buffer_addr % 16 || param->pic_stream_buffer_size == 0)812 return -EINVAL;813 }814 if (param->pic_stream_buffer_addr % 8 || param->pic_stream_buffer_size == 0)815 return -EINVAL;816 817 return 0;818}819 820int wave5_vpu_enc_start_one_frame(struct vpu_instance *inst, struct enc_param *param, u32 *fail_res)821{822 struct enc_info *p_enc_info = &inst->codec_info->enc_info;823 int ret;824 struct vpu_device *vpu_dev = inst->dev;825 826 *fail_res = 0;827 828 if (p_enc_info->stride == 0) /* this means frame buffers have not been registered. */829 return -EINVAL;830 831 ret = wave5_check_enc_param(inst, param);832 if (ret)833 return ret;834 835 ret = mutex_lock_interruptible(&vpu_dev->hw_lock);836 if (ret)837 return ret;838 839 p_enc_info->pts_map[param->src_idx] = param->pts;840 841 ret = wave5_vpu_encode(inst, param, fail_res);842 843 mutex_unlock(&vpu_dev->hw_lock);844 845 return ret;846}847 848int wave5_vpu_enc_get_output_info(struct vpu_instance *inst, struct enc_output_info *info)849{850 struct enc_info *p_enc_info = &inst->codec_info->enc_info;851 int ret;852 struct vpu_device *vpu_dev = inst->dev;853 854 ret = mutex_lock_interruptible(&vpu_dev->hw_lock);855 if (ret)856 return ret;857 858 ret = wave5_vpu_enc_get_result(inst, info);859 if (ret) {860 info->pts = 0;861 goto unlock;862 }863 864 if (info->recon_frame_index >= 0)865 info->pts = p_enc_info->pts_map[info->enc_src_idx];866 867unlock:868 mutex_unlock(&vpu_dev->hw_lock);869 870 return ret;871}872 873int wave5_vpu_enc_give_command(struct vpu_instance *inst, enum codec_command cmd, void *parameter)874{875 struct enc_info *p_enc_info = &inst->codec_info->enc_info;876 877 switch (cmd) {878 case ENABLE_ROTATION:879 p_enc_info->rotation_enable = true;880 break;881 case ENABLE_MIRRORING:882 p_enc_info->mirror_enable = true;883 break;884 case SET_MIRROR_DIRECTION: {885 enum mirror_direction mir_dir;886 887 mir_dir = *(enum mirror_direction *)parameter;888 if (mir_dir != MIRDIR_NONE && mir_dir != MIRDIR_HOR &&889 mir_dir != MIRDIR_VER && mir_dir != MIRDIR_HOR_VER)890 return -EINVAL;891 p_enc_info->mirror_direction = mir_dir;892 break;893 }894 case SET_ROTATION_ANGLE: {895 int angle;896 897 angle = *(int *)parameter;898 if (angle && angle != 90 && angle != 180 && angle != 270)899 return -EINVAL;900 if (p_enc_info->initial_info_obtained && (angle == 90 || angle == 270))901 return -EINVAL;902 p_enc_info->rotation_angle = angle;903 break;904 }905 case ENC_GET_QUEUE_STATUS: {906 struct queue_status_info *queue_info = parameter;907 908 queue_info->instance_queue_count = p_enc_info->instance_queue_count;909 queue_info->report_queue_count = p_enc_info->report_queue_count;910 break;911 }912 default:913 return -EINVAL;914 }915 return 0;916}917 918int wave5_vpu_enc_issue_seq_init(struct vpu_instance *inst)919{920 int ret;921 struct vpu_device *vpu_dev = inst->dev;922 923 ret = mutex_lock_interruptible(&vpu_dev->hw_lock);924 if (ret)925 return ret;926 927 ret = wave5_vpu_enc_init_seq(inst);928 929 mutex_unlock(&vpu_dev->hw_lock);930 931 return ret;932}933 934int wave5_vpu_enc_complete_seq_init(struct vpu_instance *inst, struct enc_initial_info *info)935{936 struct enc_info *p_enc_info = &inst->codec_info->enc_info;937 int ret;938 struct vpu_device *vpu_dev = inst->dev;939 940 if (!info)941 return -EINVAL;942 943 ret = mutex_lock_interruptible(&vpu_dev->hw_lock);944 if (ret)945 return ret;946 947 ret = wave5_vpu_enc_get_seq_info(inst, info);948 if (ret) {949 p_enc_info->initial_info_obtained = false;950 mutex_unlock(&vpu_dev->hw_lock);951 return ret;952 }953 954 p_enc_info->initial_info_obtained = true;955 p_enc_info->initial_info = *info;956 957 mutex_unlock(&vpu_dev->hw_lock);958 959 return 0;960}961