1 /*
2 * Copyright 2022 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_jpege_v540c"
18
19 #include <linux/string.h>
20
21 #include <string.h>
22 #include <math.h>
23 #include <limits.h>
24
25 #include "mpp_env.h"
26 #include "mpp_mem.h"
27 #include "mpp_soc.h"
28 #include "mpp_common.h"
29 #include "mpp_frame_impl.h"
30
31 #include "hal_jpege_debug.h"
32 #include "jpege_syntax.h"
33 #include "hal_bufs.h"
34 #include "rkv_enc_def.h"
35 #include "vepu5xx_common.h"
36 #include "vepu540c_common.h"
37 #include "hal_jpege_vepu540c.h"
38 #include "hal_jpege_vepu540c_reg.h"
39 #include "hal_jpege_hdr.h"
40
41 typedef struct jpegeV540cHalContext_t {
42 MppEncHalApi api;
43 MppDev dev;
44 void *regs;
45 void *reg_out;
46
47 void *dump_files;
48
49 RK_S32 frame_type;
50 RK_S32 last_frame_type;
51
52 /* @frame_cnt starts from ZERO */
53 RK_U32 frame_cnt;
54 void *roi_data;
55 MppEncCfgSet *cfg;
56
57 RK_U32 enc_mode;
58 RK_U32 frame_size;
59 RK_S32 max_buf_cnt;
60 RK_S32 hdr_status;
61 void *input_fmt;
62 RK_U8 *src_buf;
63 RK_U8 *dst_buf;
64 RK_S32 buf_size;
65 RK_U32 frame_num;
66 RK_S32 fbc_header_len;
67 RK_U32 title_num;
68
69 JpegeBits bits;
70 JpegeSyntax syntax;
71 HalJpegeRc hal_rc;
72 } jpegeV540cHalContext;
73
hal_jpege_v540c_init(void * hal,MppEncHalCfg * cfg)74 MPP_RET hal_jpege_v540c_init(void *hal, MppEncHalCfg *cfg)
75 {
76 MPP_RET ret = MPP_OK;
77 jpegeV540cHalContext *ctx = (jpegeV540cHalContext *)hal;
78
79 mpp_env_get_u32("hal_jpege_debug", &hal_jpege_debug, 0);
80
81 hal_jpege_enter();
82
83 ctx->reg_out = mpp_calloc(JpegV540cStatus, 1);
84 ctx->regs = mpp_calloc(JpegV540cRegSet, 1);
85 ctx->input_fmt = mpp_calloc(VepuFmtCfg, 1);
86 ctx->cfg = cfg->cfg;
87
88 ctx->frame_cnt = 0;
89 ctx->enc_mode = 1;
90 cfg->type = VPU_CLIENT_RKVENC;
91 ret = mpp_dev_init(&cfg->dev, cfg->type);
92 if (ret) {
93 mpp_err_f("mpp_dev_init failed. ret: %d\n", ret);
94 return ret;
95 }
96
97 ctx->dev = cfg->dev;
98 jpege_bits_init(&ctx->bits);
99 mpp_assert(ctx->bits);
100 hal_jpege_rc_init(&ctx->hal_rc);
101
102 hal_jpege_leave();
103 return ret;
104 }
105
hal_jpege_v540c_deinit(void * hal)106 MPP_RET hal_jpege_v540c_deinit(void *hal)
107 {
108 jpegeV540cHalContext *ctx = (jpegeV540cHalContext *)hal;
109
110 hal_jpege_enter();
111 jpege_bits_deinit(ctx->bits);
112 MPP_FREE(ctx->regs);
113
114 MPP_FREE(ctx->reg_out);
115
116 MPP_FREE(ctx->input_fmt);
117
118 if (ctx->dev) {
119 mpp_dev_deinit(ctx->dev);
120 ctx->dev = NULL;
121 }
122 hal_jpege_leave();
123 return MPP_OK;
124 }
125
hal_jpege_vepu540c_prepare(void * hal)126 static MPP_RET hal_jpege_vepu540c_prepare(void *hal)
127 {
128 jpegeV540cHalContext *ctx = (jpegeV540cHalContext *)hal;
129
130 hal_jpege_dbg_func("enter %p\n", hal);
131 VepuFmtCfg *fmt = (VepuFmtCfg *)ctx->input_fmt;
132 vepu5xx_set_fmt(fmt, ctx->cfg->prep.format);
133
134 hal_jpege_dbg_func("leave %p\n", hal);
135
136 return MPP_OK;
137 }
138
hal_jpege_v540c_gen_regs(void * hal,HalEncTask * task)139 MPP_RET hal_jpege_v540c_gen_regs(void *hal, HalEncTask *task)
140 {
141 jpegeV540cHalContext *ctx = (jpegeV540cHalContext *)hal;
142 JpegV540cRegSet *regs = ctx->regs;
143 jpeg_vepu540c_control_cfg *reg_ctl = ®s->reg_ctl;
144 jpeg_vepu540c_base *reg_base = ®s->reg_base;
145 JpegeBits bits = ctx->bits;
146 size_t length = mpp_packet_get_length(task->packet);
147 RK_U8 *buf = mpp_buffer_get_ptr(task->output);
148 size_t size = mpp_buffer_get_size(task->output);
149 JpegeSyntax *syntax = &ctx->syntax;
150 Vepu540cJpegCfg cfg;
151 RK_S32 bitpos;
152
153 hal_jpege_enter();
154 cfg.enc_task = task;
155 cfg.jpeg_reg_base = ®_base->jpegReg;
156 cfg.dev = ctx->dev;
157 cfg.input_fmt = ctx->input_fmt;
158
159 memset(regs, 0, sizeof(JpegV540cRegSet));
160
161 if (syntax->q_mode == JPEG_QFACTOR) {
162 syntax->q_factor = 100 - task->rc_task->info.quality_target;
163 hal_jpege_rc_update(&ctx->hal_rc, syntax);
164 }
165
166 /* write header to output buffer */
167 jpege_bits_setup(bits, buf, (RK_U32)size);
168 /* seek length bytes data */
169 jpege_seek_bits(bits, length << 3);
170 /* NOTE: write header will update qtable */
171 write_jpeg_header(bits, syntax, &ctx->hal_rc);
172
173 bitpos = jpege_bits_get_bitpos(bits);
174 task->length = (bitpos + 7) >> 3;
175 mpp_buffer_sync_partial_end(task->output, 0, task->length);
176 mpp_packet_set_length(task->packet, task->length);
177 reg_ctl->reg0004_enc_strt.lkt_num = 0;
178 reg_ctl->reg0004_enc_strt.vepu_cmd = ctx->enc_mode;
179 reg_ctl->reg0005_enc_clr.safe_clr = 0x0;
180 reg_ctl->reg0005_enc_clr.force_clr = 0x0;
181
182 reg_ctl->reg0008_int_en.enc_done_en = 1;
183 reg_ctl->reg0008_int_en.lkt_node_done_en = 1;
184 reg_ctl->reg0008_int_en.sclr_done_en = 1;
185 reg_ctl->reg0008_int_en.slc_done_en = 1;
186 reg_ctl->reg0008_int_en.bsf_oflw_en = 1;
187 reg_ctl->reg0008_int_en.brsp_otsd_en = 1;
188 reg_ctl->reg0008_int_en.wbus_err_en = 1;
189 reg_ctl->reg0008_int_en.rbus_err_en = 1;
190 reg_ctl->reg0008_int_en.wdg_en = 1;
191 reg_ctl->reg0008_int_en.lkt_err_int_en = 0;
192
193 reg_ctl->reg0012_dtrns_map.jpeg_bus_edin = 0x7;
194 reg_ctl->reg0012_dtrns_map.src_bus_edin = 0x0;
195 reg_ctl->reg0012_dtrns_map.meiw_bus_edin = 0x0;
196 reg_ctl->reg0012_dtrns_map.bsw_bus_edin = 0x0;
197 reg_ctl->reg0012_dtrns_map.lktr_bus_edin = 0x0;
198 reg_ctl->reg0012_dtrns_map.roir_bus_edin = 0x0;
199 reg_ctl->reg0012_dtrns_map.lktw_bus_edin = 0x0;
200 reg_ctl->reg0012_dtrns_map.rec_nfbc_bus_edin = 0x0;
201 reg_base->reg0192_enc_pic.enc_stnd = 2; // disable h264 or hevc
202
203 reg_ctl->reg0013_dtrns_cfg.axi_brsp_cke = 0x0;
204 reg_ctl->reg0014_enc_wdg.vs_load_thd = 0x1fffff;
205 reg_ctl->reg0014_enc_wdg.rfp_load_thd = 0;
206
207 vepu540c_set_jpeg_reg(&cfg);
208 {
209 RK_U16 *tbl = ®s->jpeg_table.qua_tab0[0];
210 RK_U32 i, j;
211
212 for ( i = 0; i < 8; i++) {
213 for ( j = 0; j < 8; j++) {
214 tbl[i * 8 + j] = 0x8000 / ctx->hal_rc.qtables[0][j * 8 + i];
215 }
216 }
217 tbl += 64;
218 for ( i = 0; i < 8; i++) {
219 for ( j = 0; j < 8; j++) {
220 tbl[i * 8 + j] = 0x8000 / ctx->hal_rc.qtables[1][j * 8 + i];
221 }
222 }
223 tbl += 64;
224 for ( i = 0; i < 8; i++) {
225 for ( j = 0; j < 8; j++) {
226 tbl[i * 8 + j] = 0x8000 / ctx->hal_rc.qtables[1][j * 8 + i];
227 }
228 }
229 }
230 ctx->frame_num++;
231
232 hal_jpege_leave();
233 return MPP_OK;
234 }
235
hal_jpege_v540c_start(void * hal,HalEncTask * enc_task)236 MPP_RET hal_jpege_v540c_start(void *hal, HalEncTask *enc_task)
237 {
238 MPP_RET ret = MPP_OK;
239 jpegeV540cHalContext *ctx = (jpegeV540cHalContext *)hal;
240 JpegV540cRegSet *hw_regs = ctx->regs;
241 JpegV540cStatus *reg_out = ctx->reg_out;
242 MppDevRegWrCfg cfg;
243 MppDevRegRdCfg cfg1;
244 hal_jpege_enter();
245
246 if (enc_task->flags.err) {
247 mpp_err_f("enc_task->flags.err %08x, return e arly",
248 enc_task->flags.err);
249 return MPP_NOK;
250 }
251
252 cfg.reg = (RK_U32*)&hw_regs->reg_ctl;
253 cfg.size = sizeof(jpeg_vepu540c_control_cfg);
254 cfg.offset = VEPU540C_CTL_OFFSET;
255
256 ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_WR, &cfg);
257 if (ret) {
258 mpp_err_f("set register write failed %d\n", ret);
259 return ret;
260 }
261
262 cfg.reg = &hw_regs->jpeg_table;
263 cfg.size = sizeof(vepu540c_jpeg_tab);
264 cfg.offset = VEPU540C_JPEGTAB_OFFSET;
265
266 ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_WR, &cfg);
267 if (ret) {
268 mpp_err_f("set register write failed %d\n", ret);
269 return ret;
270 }
271
272 cfg.reg = &hw_regs->reg_base;
273 cfg.size = sizeof(jpeg_vepu540c_base);
274 cfg.offset = VEPU540C_BASE_OFFSET;
275
276 ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_WR, &cfg);
277 if (ret) {
278 mpp_err_f("set register write failed %d\n", ret);
279 return ret;
280 }
281
282 cfg1.reg = ®_out->hw_status;
283 cfg1.size = sizeof(RK_U32);
284 cfg1.offset = VEPU540C_REG_BASE_HW_STATUS;
285
286 ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_RD, &cfg1);
287 if (ret) {
288 mpp_err_f("set register read failed %d\n", ret);
289 return ret;
290 }
291
292 cfg1.reg = ®_out->st;
293 cfg1.size = sizeof(JpegV540cStatus) - 4;
294 cfg1.offset = VEPU540C_STATUS_OFFSET;
295
296 ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_RD, &cfg1);
297 if (ret) {
298 mpp_err_f("set register read failed %d\n", ret);
299 return ret;
300 }
301
302 ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_CMD_SEND, NULL);
303 if (ret) {
304 mpp_err_f("send cmd failed %d\n", ret);
305 }
306 hal_jpege_leave();
307 return ret;
308 }
309
310 //#define DUMP_DATA
hal_jpege_vepu540c_status_check(void * hal)311 static MPP_RET hal_jpege_vepu540c_status_check(void *hal)
312 {
313 jpegeV540cHalContext *ctx = (jpegeV540cHalContext *)hal;
314 JpegV540cStatus *elem = (JpegV540cStatus *)ctx->reg_out;
315
316 vepu540c_hw_status hw_status = elem->hw_status;
317
318 hal_jpege_dbg_detail("hw_status: 0x%08x", hw_status.val);
319 if (hw_status.int_sta.enc_done_sta)
320 hal_jpege_dbg_detail("RKV_ENC_INT_ENC_DONE");
321
322 if (hw_status.int_sta.wdg_sta)
323 mpp_err_f("RKV_ENC_INT_WDG_TIMEOUT");
324
325 if (hw_status.int_sta.jslc_done_sta)
326 hal_jpege_dbg_detail("RKV_ENC_INT_JSL_DONE");
327
328 if (hw_status.int_sta.jbsf_oflw_sta)
329 mpp_err_f("RKV_ENC_INT_JBSF_OFLOW");
330
331
332 return MPP_OK;
333 }
334
335
336
hal_jpege_v540c_wait(void * hal,HalEncTask * task)337 MPP_RET hal_jpege_v540c_wait(void *hal, HalEncTask *task)
338 {
339 MPP_RET ret = MPP_OK;
340 jpegeV540cHalContext *ctx = (jpegeV540cHalContext *)hal;
341 HalEncTask *enc_task = task;
342 JpegV540cStatus *elem = (JpegV540cStatus *)ctx->reg_out;
343 hal_jpege_enter();
344
345 if (enc_task->flags.err) {
346 mpp_err_f("enc_task->flags.err %08x, return early",
347 enc_task->flags.err);
348 return MPP_NOK;
349 }
350
351 ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_CMD_POLL, NULL);
352 if (ret) {
353 mpp_err_f("poll cmd failed %d\n", ret);
354 ret = MPP_ERR_VPUHW;
355 } else {
356 hal_jpege_vepu540c_status_check(hal);
357 task->hw_length += elem->st.jpeg_head_bits_l32;
358 }
359
360 hal_jpege_leave();
361 return ret;
362 }
363
hal_jpege_v540c_get_task(void * hal,HalEncTask * task)364 MPP_RET hal_jpege_v540c_get_task(void *hal, HalEncTask *task)
365 {
366 jpegeV540cHalContext *ctx = (jpegeV540cHalContext *)hal;
367 MppFrame frame = task->frame;
368 EncFrmStatus *frm_status = &task->rc_task->frm;
369 JpegeSyntax *syntax = (JpegeSyntax *)task->syntax.data;
370
371 hal_jpege_enter();
372
373 memcpy(&ctx->syntax, syntax, sizeof(ctx->syntax));
374
375 ctx->last_frame_type = ctx->frame_type;
376
377 if (!frm_status->reencode && mpp_frame_has_meta(task->frame)) {
378 MppMeta meta = mpp_frame_get_meta(frame);
379
380 mpp_meta_get_ptr(meta, KEY_ROI_DATA, (void **)&ctx->roi_data);
381 }
382
383 if (ctx->cfg->jpeg.update) {
384 hal_jpege_rc_update(&ctx->hal_rc, syntax);
385 ctx->cfg->jpeg.update = 0;
386 }
387 task->rc_task->frm.is_intra = 1;
388
389 hal_jpege_leave();
390 return MPP_OK;
391 }
392
hal_jpege_v540c_ret_task(void * hal,HalEncTask * task)393 MPP_RET hal_jpege_v540c_ret_task(void *hal, HalEncTask *task)
394 {
395 (void)hal;
396 EncRcTaskInfo *rc_info = &task->rc_task->info;
397 hal_jpege_enter();
398
399 task->length += task->hw_length;
400
401 // setup bit length for rate control
402 rc_info->bit_real = task->hw_length * 8;
403 rc_info->quality_real = rc_info->quality_target;
404
405 hal_jpege_leave();
406 return MPP_OK;
407 }
408
409 const MppEncHalApi hal_jpege_vepu540c = {
410 "hal_jpege_v540c",
411 MPP_VIDEO_CodingMJPEG,
412 sizeof(jpegeV540cHalContext),
413 0,
414 hal_jpege_v540c_init,
415 hal_jpege_v540c_deinit,
416 hal_jpege_vepu540c_prepare,
417 hal_jpege_v540c_get_task,
418 hal_jpege_v540c_gen_regs,
419 hal_jpege_v540c_start,
420 hal_jpege_v540c_wait,
421 NULL,
422 NULL,
423 hal_jpege_v540c_ret_task,
424 };
425