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