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