xref: /rockchip-linux_mpp/mpp/hal/vpu/h263d/hal_h263d_vdpu2.c (revision 437bfbeb9567cca9cd9080e3f6954aa9d6a94f18)
1 /*
2  * Copyright 2016 Rockchip Electronics Co. LTD
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #define MODULE_TAG "hal_vpu_h263d"
18 
19 #include <stdio.h>
20 #include <string.h>
21 
22 #include "mpp_err.h"
23 #include "mpp_mem.h"
24 #include "mpp_debug.h"
25 
26 #include "h263d_syntax.h"
27 #include "hal_h263d_api.h"
28 #include "hal_h263d_vdpu2.h"
29 #include "hal_h263d_vdpu2_reg.h"
30 #include "hal_h263d_base.h"
31 
vpu2_h263d_setup_regs_by_syntax(hal_h263_ctx * ctx,MppSyntax syntax)32 static void vpu2_h263d_setup_regs_by_syntax(hal_h263_ctx *ctx, MppSyntax syntax)
33 {
34     Vpu2H263dRegSet_t *regs = (Vpu2H263dRegSet_t*)ctx->regs;
35     DXVA2_DecodeBufferDesc **data = syntax.data;
36     DXVA_PicParams_H263 *pp = NULL;
37     RK_U32 stream_length = 0;
38     RK_U32 stream_used = 0;
39     RK_U32 i;
40 
41     for (i = 0; i < syntax.number; i++) {
42         DXVA2_DecodeBufferDesc *desc = data[i];
43         switch (desc->CompressedBufferType) {
44         case DXVA2_PictureParametersBufferType : {
45             pp = (DXVA_PicParams_H263 *)desc->pvPVPState;
46         } break;
47         case DXVA2_BitStreamDateBufferType : {
48             stream_length = desc->DataSize;
49             stream_used = desc->DataOffset;
50         } break;
51         default : {
52             mpp_err_f("found invalid buffer descriptor type %d\n", desc->CompressedBufferType);
53         } break;
54         }
55     }
56 
57     mpp_assert(pp);
58     mpp_assert(stream_length);
59     mpp_assert(stream_used);
60 
61     regs->reg120.sw_pic_mb_width = (pp->vop_width  + 15) >> 4;
62     regs->reg120.sw_pic_mb_hight_p = (pp->vop_height + 15) >> 4;
63     regs->reg120.sw_mb_width_off = pp->vop_width & 0xf;
64     regs->reg120.sw_mb_height_off = pp->vop_height & 0xf;
65 
66     regs->reg53_dec_mode = 2;
67     regs->reg50_dec_ctrl.sw_filtering_dis = 1;
68     regs->reg136.sw_rounding = 0;
69     regs->reg51_stream_info.sw_init_qp = pp->vop_quant;
70     regs->reg122.sw_sync_markers_en = 1;
71 
72     {
73         /*
74          * update stream base address here according to consumed bit length
75          * 1. hardware start address has to be 64 bit align
76          * 2. hardware need to know which is the start bit in
77          * 2. pass (10bit fd + (offset << 10)) register value to kernel
78          */
79         RK_U32 val = regs->reg64_input_stream_base;
80         RK_U32 consumed_bytes = stream_used >> 3;
81         RK_U32 consumed_bytes_align = consumed_bytes & (~0x7);
82         RK_U32 start_bit_offset = stream_used & 0x3F;
83         RK_U32 left_bytes = stream_length - consumed_bytes_align;
84 
85         if (consumed_bytes_align) {
86             mpp_dev_set_reg_offset(ctx->dev, 64, consumed_bytes_align);
87         }
88         regs->reg64_input_stream_base = val;
89         regs->reg122.sw_stream_start_word = start_bit_offset;
90         regs->reg51_stream_info.sw_stream_len = left_bytes;
91     }
92 
93     regs->reg122.sw_vop_time_incr = pp->vop_time_increment_resolution;
94 
95     switch (pp->vop_coding_type) {
96     case H263_P_VOP : {
97         regs->reg57_enable_ctrl.sw_pic_inter_e = 1;
98 
99         if (ctx->fd_ref0 >= 0) {
100             regs->reg131_ref0_base = (RK_U32)ctx->fd_ref0;
101             regs->reg148_ref1_base = (RK_U32)ctx->fd_ref0;
102         } else {
103             regs->reg131_ref0_base = (RK_U32)ctx->fd_curr;
104             regs->reg148_ref1_base = (RK_U32)ctx->fd_curr;
105         }
106     } break;
107     case H263_I_VOP : {
108         regs->reg57_enable_ctrl.sw_pic_inter_e = 0;
109 
110         regs->reg131_ref0_base = (RK_U32)ctx->fd_curr;
111         regs->reg148_ref1_base = (RK_U32)ctx->fd_curr;
112     } break;
113     default : {
114         /* no nothing */
115     } break;
116     }
117 
118     regs->reg136.sw_hrz_bit_of_fwd_mv = 1;
119     regs->reg136.sw_vrz_bit_of_fwd_mv = 1;
120     regs->reg136.sw_prev_pic_type = (pp->prev_coding_type == H263_P_VOP);
121 }
122 
hal_vpu2_h263d_init(void * hal,MppHalCfg * cfg)123 MPP_RET hal_vpu2_h263d_init(void *hal, MppHalCfg *cfg)
124 {
125     MPP_RET ret = MPP_OK;
126     Vpu2H263dRegSet_t *regs = NULL;
127     hal_h263_ctx *ctx = (hal_h263_ctx *)hal;
128 
129     mpp_assert(hal);
130 
131     regs = mpp_calloc(Vpu2H263dRegSet_t, 1);
132     if (NULL == regs) {
133         mpp_err_f("failed to malloc register ret\n");
134         ret = MPP_ERR_MALLOC;
135         goto ERR_RET;
136     }
137 
138     ret = mpp_dev_init(&ctx->dev, VPU_CLIENT_VDPU2);
139     if (ret) {
140         mpp_err_f("mpp_dev_init failed. ret: %d\n", ret);
141         ret = MPP_ERR_UNKNOW;
142         goto ERR_RET;
143     }
144 
145     ctx->frm_slots  = cfg->frame_slots;
146     ctx->pkt_slots  = cfg->packet_slots;
147     ctx->dec_cb     = cfg->dec_cb;
148     ctx->regs       = (void*)regs;
149 
150     return ret;
151 ERR_RET:
152     if (regs) {
153         mpp_free(regs);
154         regs = NULL;
155     }
156 
157     return ret;
158 }
159 
hal_vpu2_h263d_deinit(void * hal)160 MPP_RET hal_vpu2_h263d_deinit(void *hal)
161 {
162     MPP_RET ret = MPP_OK;
163     hal_h263_ctx *ctx = (hal_h263_ctx *)hal;
164 
165     mpp_assert(hal);
166 
167     if (ctx->regs) {
168         mpp_free(ctx->regs);
169         ctx->regs = NULL;
170     }
171 
172     if (ctx->dev) {
173         mpp_dev_deinit(ctx->dev);
174         ctx->dev = NULL;
175     }
176 
177     return ret;
178 }
179 
hal_vpu2_h263d_gen_regs(void * hal,HalTaskInfo * syn)180 MPP_RET hal_vpu2_h263d_gen_regs(void *hal,  HalTaskInfo *syn)
181 {
182     MPP_RET ret = MPP_OK;
183     hal_h263_ctx *ctx = (hal_h263_ctx *)hal;
184     HalDecTask *task = &syn->dec;
185     MppBuffer buf_frm_curr = NULL;
186     MppBuffer buf_frm_ref0 = NULL;
187     MppBuffer buf_pkt = NULL;
188     Vpu2H263dRegSet_t *regs = (Vpu2H263dRegSet_t*)ctx->regs;
189 
190     mpp_assert(task->valid);
191     mpp_assert(task->input >= 0);
192     mpp_assert(task->output >= 0);
193 
194     memset(regs, 0, sizeof(Vpu2H263dRegSet_t));
195 
196     /*
197      * basic register configuration setup here
198      */
199     regs->reg54_endian.sw_dec_out_endian = 1;
200     regs->reg54_endian.sw_dec_in_endian = 1;
201     regs->reg54_endian.sw_dec_inswap32_e = 1;
202     regs->reg54_endian.sw_dec_outswap32_e = 1;
203     regs->reg54_endian.sw_dec_strswap32_e = 1;
204     regs->reg54_endian.sw_dec_strendian_e = 1;
205     regs->reg56_axi_ctrl.sw_dec_max_burst = 16;
206     regs->reg52_error_concealment.sw_apf_threshold = 1;
207     regs->reg57_enable_ctrl.sw_dec_timeout_e = 1;
208     regs->reg57_enable_ctrl.sw_dec_clk_gate_e = 1;
209     regs->reg57_enable_ctrl.sw_dec_e = 1;
210     regs->reg59.sw_pred_bc_tap_0_0 = -1;
211     regs->reg59.sw_pred_bc_tap_0_1 = 3;
212     regs->reg59.sw_pred_bc_tap_0_2 = -6;
213     regs->reg153.sw_pred_bc_tap_0_3 = 20;
214 
215     /* setup buffer for input / output / reference */
216     mpp_buf_slot_get_prop(ctx->pkt_slots, task->input, SLOT_BUFFER, &buf_pkt);
217     mpp_assert(buf_pkt);
218     vpu_h263d_get_buffer_by_index(ctx, task->output, &buf_frm_curr);
219     vpu_h263d_get_buffer_by_index(ctx, task->refer[0], &buf_frm_ref0);
220 
221     /* address registers setup first */
222     ctx->fd_curr = mpp_buffer_get_fd(buf_frm_curr);
223     ctx->fd_ref0 = (buf_frm_ref0) ? (mpp_buffer_get_fd(buf_frm_ref0)) : (-1);
224     regs->reg63_cur_pic_base = (RK_U32)ctx->fd_curr;
225     regs->reg64_input_stream_base = mpp_buffer_get_fd(buf_pkt);
226 
227     /* setup other registers, here will update packet address */
228     vpu2_h263d_setup_regs_by_syntax(ctx, task->syntax);
229 
230     return ret;
231 }
232 
hal_vpu2_h263d_start(void * hal,HalTaskInfo * task)233 MPP_RET hal_vpu2_h263d_start(void *hal, HalTaskInfo *task)
234 {
235     MPP_RET ret = MPP_OK;
236     hal_h263_ctx *ctx = (hal_h263_ctx *)hal;
237     RK_U32 *regs = (RK_U32 *)ctx->regs;
238 
239     if (h263d_hal_debug & H263D_HAL_DBG_REG_PUT) {
240         RK_U32 reg_count = (sizeof(Vpu2H263dRegSet_t) / sizeof(RK_U32));
241         RK_U32 i = 0;
242 
243         for (i = 0; i < reg_count; i++)
244             mpp_log("reg[%03d]: %08x\n", i, regs[i]);
245     }
246 
247     do {
248         MppDevRegWrCfg wr_cfg;
249         MppDevRegRdCfg rd_cfg;
250 
251         wr_cfg.reg = regs;
252         wr_cfg.size = sizeof(Vpu2H263dRegSet_t);
253         wr_cfg.offset = 0;
254 
255         ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_WR, &wr_cfg);
256         if (ret) {
257             mpp_err_f("set register write failed %d\n", ret);
258             break;
259         }
260 
261         rd_cfg.reg = regs;
262         rd_cfg.size = sizeof(Vpu2H263dRegSet_t);
263         rd_cfg.offset = 0;
264 
265         ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_RD, &rd_cfg);
266         if (ret) {
267             mpp_err_f("set register read failed %d\n", ret);
268             break;
269         }
270 
271         ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_CMD_SEND, NULL);
272         if (ret) {
273             mpp_err_f("send cmd failed %d\n", ret);
274             break;
275         }
276     } while (0);
277 
278     (void)task;
279     return ret;
280 }
281 
hal_vpu2_h263d_wait(void * hal,HalTaskInfo * task)282 MPP_RET hal_vpu2_h263d_wait(void *hal, HalTaskInfo *task)
283 {
284     MPP_RET ret = MPP_OK;
285     hal_h263_ctx *ctx = (hal_h263_ctx *)hal;
286 
287     ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_CMD_POLL, NULL);
288     if (ret)
289         mpp_err_f("poll cmd failed %d\n", ret);
290 
291     if (h263d_hal_debug & H263D_HAL_DBG_REG_GET) {
292         RK_U32 *regs = (RK_U32 *)ctx->regs;
293         RK_U32 reg_count = (sizeof(Vpu2H263dRegSet_t) / sizeof(RK_U32));
294         RK_U32 i = 0;
295 
296         for (i = 0; i < reg_count; i++)
297             mpp_log("reg[%03d]: %08x\n", i, regs[i]);
298     }
299 
300     (void)task;
301     return ret;
302 }
303