| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0 |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Copyright (c) 2016 MediaTek Inc. |
|---|
| 3 | 4 | * Author: Daniel Hsiao <daniel.hsiao@mediatek.com> |
|---|
| 4 | 5 | * Kai-Sean Yang <kai-sean.yang@mediatek.com> |
|---|
| 5 | 6 | * Tiffany Lin <tiffany.lin@mediatek.com> |
|---|
| 6 | | - * |
|---|
| 7 | | - * This program is free software; you can redistribute it and/or |
|---|
| 8 | | - * modify it under the terms of the GNU General Public License |
|---|
| 9 | | - * version 2 as published by the Free Software Foundation. |
|---|
| 10 | | - * |
|---|
| 11 | | - * This program is distributed in the hope that it will be useful, |
|---|
| 12 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 13 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 14 | | - * GNU General Public License for more details. |
|---|
| 15 | 7 | */ |
|---|
| 16 | 8 | |
|---|
| 17 | 9 | #include <linux/fs.h> |
|---|
| .. | .. |
|---|
| 118 | 110 | * @buf_len_sz_c : size used to store cbcr plane ufo info (AP-R, VPU-W) |
|---|
| 119 | 111 | |
|---|
| 120 | 112 | * @profile : profile sparsed from vpu (AP-R, VPU-W) |
|---|
| 121 | | - * @show_frame : display this frame or not (AP-R, VPU-W) |
|---|
| 113 | + * @show_frame : [BIT(0)] display this frame or not (AP-R, VPU-W) |
|---|
| 114 | + * [BIT(1)] reset segment data or not (AP-R, VPU-W) |
|---|
| 115 | + * [BIT(2)] trig decoder hardware or not (AP-R, VPU-W) |
|---|
| 116 | + * [BIT(3)] ask VPU to set bits(0~4) accordingly (AP-W, VPU-R) |
|---|
| 117 | + * [BIT(4)] do not reset segment data before every frame (AP-R, VPU-W) |
|---|
| 122 | 118 | * @show_existing_frame : inform this frame is show existing frame |
|---|
| 123 | 119 | * (AP-R, VPU-W) |
|---|
| 124 | 120 | * @frm_to_show_idx : index to show frame (AP-R, VPU-W) |
|---|
| .. | .. |
|---|
| 230 | 226 | if (fb->base_y.va == addr) { |
|---|
| 231 | 227 | list_move_tail(&node->list, |
|---|
| 232 | 228 | &inst->available_fb_node_list); |
|---|
| 233 | | - break; |
|---|
| 229 | + return fb; |
|---|
| 234 | 230 | } |
|---|
| 235 | 231 | } |
|---|
| 236 | | - return fb; |
|---|
| 232 | + |
|---|
| 233 | + return NULL; |
|---|
| 237 | 234 | } |
|---|
| 238 | 235 | |
|---|
| 239 | 236 | static void vp9_add_to_fb_free_list(struct vdec_vp9_inst *inst, |
|---|
| .. | .. |
|---|
| 481 | 478 | */ |
|---|
| 482 | 479 | if ((frm_to_show->fb != NULL) && |
|---|
| 483 | 480 | (inst->cur_fb->base_y.size >= |
|---|
| 484 | | - frm_to_show->fb->base_y.size)) { |
|---|
| 481 | + frm_to_show->fb->base_y.size) && |
|---|
| 482 | + (inst->cur_fb->base_c.size >= |
|---|
| 483 | + frm_to_show->fb->base_c.size)) { |
|---|
| 485 | 484 | memcpy((void *)inst->cur_fb->base_y.va, |
|---|
| 486 | 485 | (void *)frm_to_show->fb->base_y.va, |
|---|
| 487 | | - vsi->buf_w * |
|---|
| 488 | | - vsi->buf_h); |
|---|
| 486 | + frm_to_show->fb->base_y.size); |
|---|
| 489 | 487 | memcpy((void *)inst->cur_fb->base_c.va, |
|---|
| 490 | 488 | (void *)frm_to_show->fb->base_c.va, |
|---|
| 491 | | - vsi->buf_w * |
|---|
| 492 | | - vsi->buf_h / 2); |
|---|
| 489 | + frm_to_show->fb->base_c.size); |
|---|
| 493 | 490 | } else { |
|---|
| 494 | 491 | /* After resolution change case, current CAPTURE buffer |
|---|
| 495 | 492 | * may have less buffer size than frm_to_show buffer |
|---|
| .. | .. |
|---|
| 502 | 499 | frm_to_show->fb->base_y.size); |
|---|
| 503 | 500 | } |
|---|
| 504 | 501 | if (!vp9_is_sf_ref_fb(inst, inst->cur_fb)) { |
|---|
| 505 | | - if (vsi->show_frame) |
|---|
| 502 | + if (vsi->show_frame & BIT(0)) |
|---|
| 506 | 503 | vp9_add_to_fb_disp_list(inst, inst->cur_fb); |
|---|
| 507 | 504 | } |
|---|
| 508 | 505 | } else { |
|---|
| 509 | 506 | if (!vp9_is_sf_ref_fb(inst, inst->cur_fb)) { |
|---|
| 510 | | - if (vsi->show_frame) |
|---|
| 507 | + if (vsi->show_frame & BIT(0)) |
|---|
| 511 | 508 | vp9_add_to_fb_disp_list(inst, frm_to_show->fb); |
|---|
| 512 | 509 | } |
|---|
| 513 | 510 | } |
|---|
| .. | .. |
|---|
| 702 | 699 | |
|---|
| 703 | 700 | static void get_pic_info(struct vdec_vp9_inst *inst, struct vdec_pic_info *pic) |
|---|
| 704 | 701 | { |
|---|
| 705 | | - pic->y_bs_sz = inst->vsi->buf_sz_y_bs; |
|---|
| 706 | | - pic->c_bs_sz = inst->vsi->buf_sz_c_bs; |
|---|
| 707 | | - pic->y_len_sz = inst->vsi->buf_len_sz_y; |
|---|
| 708 | | - pic->c_len_sz = inst->vsi->buf_len_sz_c; |
|---|
| 702 | + pic->fb_sz[0] = inst->vsi->buf_sz_y_bs + inst->vsi->buf_len_sz_y; |
|---|
| 703 | + pic->fb_sz[1] = inst->vsi->buf_sz_c_bs + inst->vsi->buf_len_sz_c; |
|---|
| 709 | 704 | |
|---|
| 710 | 705 | pic->pic_w = inst->vsi->pic_w; |
|---|
| 711 | 706 | pic->pic_h = inst->vsi->pic_h; |
|---|
| .. | .. |
|---|
| 714 | 709 | |
|---|
| 715 | 710 | mtk_vcodec_debug(inst, "pic(%d, %d), buf(%d, %d)", |
|---|
| 716 | 711 | pic->pic_w, pic->pic_h, pic->buf_w, pic->buf_h); |
|---|
| 717 | | - mtk_vcodec_debug(inst, "Y(%d, %d), C(%d, %d)", pic->y_bs_sz, |
|---|
| 718 | | - pic->y_len_sz, pic->c_bs_sz, pic->c_len_sz); |
|---|
| 712 | + mtk_vcodec_debug(inst, "fb size: Y(%d), C(%d)", |
|---|
| 713 | + pic->fb_sz[0], |
|---|
| 714 | + pic->fb_sz[1]); |
|---|
| 719 | 715 | } |
|---|
| 720 | 716 | |
|---|
| 721 | 717 | static void get_disp_fb(struct vdec_vp9_inst *inst, struct vdec_fb **out_fb) |
|---|
| .. | .. |
|---|
| 766 | 762 | return 0; |
|---|
| 767 | 763 | } |
|---|
| 768 | 764 | |
|---|
| 769 | | -static void vdec_vp9_deinit(unsigned long h_vdec) |
|---|
| 765 | +static void vdec_vp9_deinit(void *h_vdec) |
|---|
| 770 | 766 | { |
|---|
| 771 | 767 | struct vdec_vp9_inst *inst = (struct vdec_vp9_inst *)h_vdec; |
|---|
| 772 | 768 | struct mtk_vcodec_mem *mem; |
|---|
| .. | .. |
|---|
| 788 | 784 | vp9_free_inst(inst); |
|---|
| 789 | 785 | } |
|---|
| 790 | 786 | |
|---|
| 791 | | -static int vdec_vp9_init(struct mtk_vcodec_ctx *ctx, unsigned long *h_vdec) |
|---|
| 787 | +static int vdec_vp9_init(struct mtk_vcodec_ctx *ctx) |
|---|
| 792 | 788 | { |
|---|
| 793 | 789 | struct vdec_vp9_inst *inst; |
|---|
| 794 | 790 | |
|---|
| .. | .. |
|---|
| 800 | 796 | inst->ctx = ctx; |
|---|
| 801 | 797 | |
|---|
| 802 | 798 | inst->vpu.id = IPI_VDEC_VP9; |
|---|
| 803 | | - inst->vpu.dev = ctx->dev->vpu_plat_dev; |
|---|
| 804 | 799 | inst->vpu.ctx = ctx; |
|---|
| 805 | | - inst->vpu.handler = vpu_dec_ipi_handler; |
|---|
| 806 | 800 | |
|---|
| 807 | 801 | if (vpu_dec_init(&inst->vpu)) { |
|---|
| 808 | 802 | mtk_vcodec_err(inst, "vp9_dec_vpu_init failed"); |
|---|
| .. | .. |
|---|
| 810 | 804 | } |
|---|
| 811 | 805 | |
|---|
| 812 | 806 | inst->vsi = (struct vdec_vp9_vsi *)inst->vpu.vsi; |
|---|
| 807 | + |
|---|
| 808 | + inst->vsi->show_frame |= BIT(3); |
|---|
| 809 | + |
|---|
| 813 | 810 | init_all_fb_lists(inst); |
|---|
| 814 | 811 | |
|---|
| 815 | | - (*h_vdec) = (unsigned long)inst; |
|---|
| 812 | + ctx->drv_handle = inst; |
|---|
| 816 | 813 | return 0; |
|---|
| 817 | 814 | |
|---|
| 818 | 815 | err_deinit_inst: |
|---|
| .. | .. |
|---|
| 821 | 818 | return -EINVAL; |
|---|
| 822 | 819 | } |
|---|
| 823 | 820 | |
|---|
| 824 | | -static int vdec_vp9_decode(unsigned long h_vdec, struct mtk_vcodec_mem *bs, |
|---|
| 825 | | - struct vdec_fb *fb, bool *res_chg) |
|---|
| 821 | +static int vdec_vp9_decode(void *h_vdec, struct mtk_vcodec_mem *bs, |
|---|
| 822 | + struct vdec_fb *fb, bool *res_chg) |
|---|
| 826 | 823 | { |
|---|
| 827 | 824 | int ret = 0; |
|---|
| 828 | 825 | struct vdec_vp9_inst *inst = (struct vdec_vp9_inst *)h_vdec; |
|---|
| .. | .. |
|---|
| 880 | 877 | vsi->sf_frm_sz[idx]); |
|---|
| 881 | 878 | } |
|---|
| 882 | 879 | } |
|---|
| 883 | | - memset(inst->seg_id_buf.va, 0, inst->seg_id_buf.size); |
|---|
| 880 | + |
|---|
| 881 | + if (!(vsi->show_frame & BIT(4))) |
|---|
| 882 | + memset(inst->seg_id_buf.va, 0, inst->seg_id_buf.size); |
|---|
| 883 | + |
|---|
| 884 | 884 | ret = vpu_dec_start(&inst->vpu, data, 3); |
|---|
| 885 | 885 | if (ret) { |
|---|
| 886 | 886 | mtk_vcodec_err(inst, "vpu_dec_start failed"); |
|---|
| 887 | 887 | goto DECODE_ERROR; |
|---|
| 888 | + } |
|---|
| 889 | + |
|---|
| 890 | + if (vsi->show_frame & BIT(1)) { |
|---|
| 891 | + memset(inst->seg_id_buf.va, 0, inst->seg_id_buf.size); |
|---|
| 892 | + |
|---|
| 893 | + if (vsi->show_frame & BIT(2)) { |
|---|
| 894 | + ret = vpu_dec_start(&inst->vpu, NULL, 0); |
|---|
| 895 | + if (ret) { |
|---|
| 896 | + mtk_vcodec_err(inst, "vpu trig decoder failed"); |
|---|
| 897 | + goto DECODE_ERROR; |
|---|
| 898 | + } |
|---|
| 899 | + } |
|---|
| 888 | 900 | } |
|---|
| 889 | 901 | |
|---|
| 890 | 902 | ret = validate_vsi_array_indexes(inst, vsi); |
|---|
| .. | .. |
|---|
| 895 | 907 | |
|---|
| 896 | 908 | if (vsi->resolution_changed) { |
|---|
| 897 | 909 | if (!vp9_alloc_work_buf(inst)) { |
|---|
| 898 | | - ret = -EINVAL; |
|---|
| 910 | + ret = -EIO; |
|---|
| 899 | 911 | goto DECODE_ERROR; |
|---|
| 900 | 912 | } |
|---|
| 901 | 913 | } |
|---|
| .. | .. |
|---|
| 924 | 936 | |
|---|
| 925 | 937 | if (vsi->show_existing_frame && (vsi->frm_to_show_idx < |
|---|
| 926 | 938 | VP9_MAX_FRM_BUF_NUM)) { |
|---|
| 927 | | - mtk_vcodec_err(inst, |
|---|
| 939 | + mtk_vcodec_debug(inst, |
|---|
| 928 | 940 | "Skip Decode drv->new_fb_idx=%d, drv->frm_to_show_idx=%d", |
|---|
| 929 | 941 | vsi->new_fb_idx, vsi->frm_to_show_idx); |
|---|
| 930 | 942 | |
|---|
| 931 | 943 | vp9_ref_cnt_fb(inst, &vsi->new_fb_idx, |
|---|
| 932 | 944 | vsi->frm_to_show_idx); |
|---|
| 933 | | - ret = -EINVAL; |
|---|
| 934 | | - goto DECODE_ERROR; |
|---|
| 935 | 945 | } |
|---|
| 936 | 946 | |
|---|
| 937 | 947 | /* VPU assign the buffer pointer in its address space, |
|---|
| .. | .. |
|---|
| 951 | 961 | goto DECODE_ERROR; |
|---|
| 952 | 962 | } |
|---|
| 953 | 963 | |
|---|
| 954 | | - if (vp9_decode_end_proc(inst) != true) { |
|---|
| 964 | + if (!vp9_decode_end_proc(inst)) { |
|---|
| 955 | 965 | mtk_vcodec_err(inst, "vp9_decode_end_proc"); |
|---|
| 956 | 966 | ret = -EINVAL; |
|---|
| 957 | 967 | goto DECODE_ERROR; |
|---|
| .. | .. |
|---|
| 980 | 990 | cr->left, cr->top, cr->width, cr->height); |
|---|
| 981 | 991 | } |
|---|
| 982 | 992 | |
|---|
| 983 | | -static int vdec_vp9_get_param(unsigned long h_vdec, |
|---|
| 984 | | - enum vdec_get_param_type type, void *out) |
|---|
| 993 | +static int vdec_vp9_get_param(void *h_vdec, enum vdec_get_param_type type, |
|---|
| 994 | + void *out) |
|---|
| 985 | 995 | { |
|---|
| 986 | 996 | struct vdec_vp9_inst *inst = (struct vdec_vp9_inst *)h_vdec; |
|---|
| 987 | 997 | int ret = 0; |
|---|
| .. | .. |
|---|
| 1011 | 1021 | return ret; |
|---|
| 1012 | 1022 | } |
|---|
| 1013 | 1023 | |
|---|
| 1014 | | -static struct vdec_common_if vdec_vp9_if = { |
|---|
| 1024 | +const struct vdec_common_if vdec_vp9_if = { |
|---|
| 1015 | 1025 | .init = vdec_vp9_init, |
|---|
| 1016 | 1026 | .decode = vdec_vp9_decode, |
|---|
| 1017 | 1027 | .get_param = vdec_vp9_get_param, |
|---|
| 1018 | 1028 | .deinit = vdec_vp9_deinit, |
|---|
| 1019 | 1029 | }; |
|---|
| 1020 | | - |
|---|
| 1021 | | -struct vdec_common_if *get_vp9_dec_comm_if(void); |
|---|
| 1022 | | - |
|---|
| 1023 | | -struct vdec_common_if *get_vp9_dec_comm_if(void) |
|---|
| 1024 | | -{ |
|---|
| 1025 | | - return &vdec_vp9_if; |
|---|
| 1026 | | -} |
|---|