xref: /rockchip-linux_mpp/mpp/hal/vpu/h263d/hal_h263d_vdpu1.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_vdpu1.h"
29 #include "hal_h263d_vdpu1_reg.h"
30 #include "hal_h263d_base.h"
31 
vpu1_h263d_setup_regs_by_syntax(hal_h263_ctx * ctx,MppSyntax syntax)32 static void vpu1_h263d_setup_regs_by_syntax(hal_h263_ctx *ctx, MppSyntax syntax)
33 {
34     Vpu1H263dRegSet_t *regs = (Vpu1H263dRegSet_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->SwReg04.sw_pic_mb_width = (pp->vop_width  + 15) >> 4;
62     regs->SwReg04.sw_pic_mb_hight_p = (pp->vop_height + 15) >> 4;
63     regs->SwReg04.sw_mb_width_off = pp->vop_width & 0xf;
64     regs->SwReg04.sw_mb_height_off = pp->vop_height & 0xf;
65 
66     regs->SwReg03.sw_dec_mode = 2;
67     regs->SwReg03.sw_filtering_dis = 1;
68     regs->SwReg18.sw_h263_vc1_rc = 0;
69     regs->SwReg06.sw_init_qp = pp->vop_quant;
70     regs->SwReg05.sw_sync_markers_e = 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->SwReg12.sw_rlc_vlc_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, 12, consumed_bytes_align);
87         regs->SwReg12.sw_rlc_vlc_base = val;
88         regs->SwReg05.sw_strm_start_bit = start_bit_offset;
89         regs->SwReg06.sw_stream_len = left_bytes;
90     }
91 
92     regs->SwReg05.sw_vop_time_incr = pp->vop_time_increment_resolution;
93 
94     switch (pp->vop_coding_type) {
95     case H263_P_VOP : {
96         regs->SwReg03.sw_pic_inter_e = 1;
97 
98         if (ctx->fd_ref0 >= 0) {
99             regs->SwReg14.sw_refer0_base = (RK_U32)ctx->fd_ref0;
100             regs->SwReg15.sw_refer1_base = (RK_U32)ctx->fd_ref0;
101         } else {
102             regs->SwReg14.sw_refer0_base = (RK_U32)ctx->fd_curr;
103             regs->SwReg15.sw_refer1_base = (RK_U32)ctx->fd_curr;
104         }
105     } break;
106     case H263_I_VOP : {
107         regs->SwReg03.sw_pic_inter_e = 0;
108 
109         regs->SwReg14.sw_refer0_base = (RK_U32)ctx->fd_curr;
110         regs->SwReg15.sw_refer1_base = (RK_U32)ctx->fd_curr;
111     } break;
112     default : {
113         /* no nothing */
114     } break;
115     }
116 
117     regs->SwReg18.sw_fcode_fwd_hor = 1;
118     regs->SwReg18.sw_fcode_fwd_ver = 1;
119     regs->SwReg18.sw_prev_anc_type = (pp->prev_coding_type == H263_P_VOP);
120 }
121 
hal_vpu1_h263d_init(void * hal,MppHalCfg * cfg)122 MPP_RET hal_vpu1_h263d_init(void *hal, MppHalCfg *cfg)
123 {
124     MPP_RET ret = MPP_OK;
125     Vpu1H263dRegSet_t *regs = NULL;
126     hal_h263_ctx *ctx = (hal_h263_ctx *)hal;
127 
128     mpp_assert(hal);
129 
130     regs = mpp_calloc(Vpu1H263dRegSet_t, 1);
131     if (NULL == regs) {
132         mpp_err_f("failed to malloc register ret\n");
133         ret = MPP_ERR_MALLOC;
134         goto ERR_RET;
135     }
136 
137     ret = mpp_dev_init(&ctx->dev, VPU_CLIENT_VDPU1);
138     if (ret) {
139         mpp_err_f("mpp_dev_init failed. ret: %d\n", ret);
140         ret = MPP_ERR_UNKNOW;
141         goto ERR_RET;
142     }
143 
144     ctx->frm_slots  = cfg->frame_slots;
145     ctx->pkt_slots  = cfg->packet_slots;
146     ctx->dec_cb     = cfg->dec_cb;
147     ctx->regs       = (void*)regs;
148 
149     return ret;
150 ERR_RET:
151     if (regs) {
152         mpp_free(regs);
153         regs = NULL;
154     }
155 
156     return ret;
157 }
158 
hal_vpu1_h263d_deinit(void * hal)159 MPP_RET hal_vpu1_h263d_deinit(void *hal)
160 {
161     MPP_RET ret = MPP_OK;
162     hal_h263_ctx *ctx = (hal_h263_ctx *)hal;
163 
164     mpp_assert(hal);
165 
166     if (ctx->regs) {
167         mpp_free(ctx->regs);
168         ctx->regs = NULL;
169     }
170 
171     if (ctx->dev) {
172         mpp_dev_deinit(ctx->dev);
173         ctx->dev = NULL;
174     }
175 
176     return ret;
177 }
178 
hal_vpu1_h263d_gen_regs(void * hal,HalTaskInfo * syn)179 MPP_RET hal_vpu1_h263d_gen_regs(void *hal,  HalTaskInfo *syn)
180 {
181     MPP_RET ret = MPP_OK;
182     hal_h263_ctx *ctx = (hal_h263_ctx *)hal;
183     HalDecTask *task = &syn->dec;
184     MppBuffer buf_frm_curr = NULL;
185     MppBuffer buf_frm_ref0 = NULL;
186     MppBuffer buf_pkt = NULL;
187     Vpu1H263dRegSet_t *regs = (Vpu1H263dRegSet_t*)ctx->regs;
188 
189     mpp_assert(task->valid);
190     mpp_assert(task->input >= 0);
191     mpp_assert(task->output >= 0);
192 
193     memset(regs, 0, sizeof(Vpu1H263dRegSet_t));
194 
195     /*
196      * basic register configuration setup here
197      */
198     regs->SwReg02.sw_dec_out_endian = 1;
199     regs->SwReg02.sw_dec_in_endian = 1;
200     regs->SwReg02.sw_dec_inswap32_e = 1;
201     regs->SwReg02.sw_dec_outswap32_e = 1;
202     regs->SwReg02.sw_dec_strswap32_e = 1;
203     regs->SwReg02.sw_dec_strendian_e = 1;
204     regs->SwReg02.sw_dec_max_burst = 16;
205     regs->SwReg55.sw_apf_threshold = 1;
206     regs->SwReg02.sw_dec_timeout_e = 1;
207     regs->SwReg02.sw_dec_clk_gate_e = 1;
208     regs->SwReg01.sw_dec_en = 1;
209     regs->SwReg49.sw_pred_bc_tap_0_0 = -1;
210     regs->SwReg49.sw_pred_bc_tap_0_1 = 3;
211     regs->SwReg49.sw_pred_bc_tap_0_2 = -6;
212     regs->SwReg34.sw_pred_bc_tap_0_3 = 20;
213 
214     /* setup buffer for input / output / reference */
215     mpp_buf_slot_get_prop(ctx->pkt_slots, task->input, SLOT_BUFFER, &buf_pkt);
216     mpp_assert(buf_pkt);
217     vpu_h263d_get_buffer_by_index(ctx, task->output, &buf_frm_curr);
218     vpu_h263d_get_buffer_by_index(ctx, task->refer[0], &buf_frm_ref0);
219 
220     /* address registers setup first */
221     ctx->fd_curr = mpp_buffer_get_fd(buf_frm_curr);
222     ctx->fd_ref0 = (buf_frm_ref0) ? (mpp_buffer_get_fd(buf_frm_ref0)) : (-1);
223     regs->SwReg13.dec_out_st_adr = (RK_U32)ctx->fd_curr;
224     regs->SwReg12.sw_rlc_vlc_base = mpp_buffer_get_fd(buf_pkt);
225 
226     /* setup other registers, here will update packet address */
227     vpu1_h263d_setup_regs_by_syntax(ctx, task->syntax);
228 
229     return ret;
230 }
231 
hal_vpu1_h263d_start(void * hal,HalTaskInfo * task)232 MPP_RET hal_vpu1_h263d_start(void *hal, HalTaskInfo *task)
233 {
234     MPP_RET ret = MPP_OK;
235     hal_h263_ctx *ctx = (hal_h263_ctx *)hal;
236     RK_U32 *regs = (RK_U32 *)ctx->regs;
237 
238     if (h263d_hal_debug & H263D_HAL_DBG_REG_PUT) {
239         RK_U32 reg_count = (sizeof(Vpu1H263dRegSet_t) / sizeof(RK_U32));
240         RK_U32 i = 0;
241 
242         for (i = 0; i < reg_count; i++)
243             mpp_log("reg[%03d]: %08x\n", i, regs[i]);
244     }
245 
246     do {
247         MppDevRegWrCfg wr_cfg;
248         MppDevRegRdCfg rd_cfg;
249 
250         wr_cfg.reg = regs;
251         wr_cfg.size = sizeof(Vpu1H263dRegSet_t);
252         wr_cfg.offset = 0;
253 
254         ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_WR, &wr_cfg);
255         if (ret) {
256             mpp_err_f("set register write failed %d\n", ret);
257             break;
258         }
259 
260         rd_cfg.reg = regs;
261         rd_cfg.size = sizeof(Vpu1H263dRegSet_t);
262         rd_cfg.offset = 0;
263 
264         ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_RD, &rd_cfg);
265         if (ret) {
266             mpp_err_f("set register read failed %d\n", ret);
267             break;
268         }
269 
270         ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_CMD_SEND, NULL);
271         if (ret) {
272             mpp_err_f("send cmd failed %d\n", ret);
273             break;
274         }
275     } while (0);
276 
277     (void)task;
278     return ret;
279 }
280 
hal_vpu1_h263d_wait(void * hal,HalTaskInfo * task)281 MPP_RET hal_vpu1_h263d_wait(void *hal, HalTaskInfo *task)
282 {
283     MPP_RET ret = MPP_OK;
284     hal_h263_ctx *ctx = (hal_h263_ctx *)hal;
285 
286     ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_CMD_POLL, NULL);
287     if (ret)
288         mpp_err_f("poll cmd failed %d\n", ret);
289 
290     if (h263d_hal_debug & H263D_HAL_DBG_REG_GET) {
291         RK_U32 *regs = (RK_U32 *)ctx->regs;
292         RK_U32 reg_count = (sizeof(Vpu1H263dRegSet_t) / sizeof(RK_U32));
293         RK_U32 i = 0;
294 
295         for (i = 0; i < reg_count; i++)
296             mpp_log("reg[%03d]: %08x\n", i, regs[i]);
297     }
298 
299     (void)task;
300     return ret;
301 }
302