1 /*
2 * Copyright 2020 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 #define MODULE_TAG "hal_jpegd_rkv"
17
18 #include <stdio.h>
19 #include <string.h>
20 #include <stdint.h>
21
22 #include "mpp_env.h"
23 #include "mpp_mem.h"
24 #include "mpp_debug.h"
25 #include "mpp_frame.h"
26 #include "mpp_common.h"
27 #include "mpp_buffer_impl.h"
28
29 #include "jpegd_syntax.h"
30 #include "hal_jpegd_common.h"
31 #include "hal_jpegd_rkv.h"
32 #include "hal_jpegd_rkv_reg.h"
33 #include "mpp_dec_cb_param.h"
34
35 // Support 8-bit precision only
36 #define NB_COMPONENTS (3)
37 #define RKD_QUANTIZATION_TBL_SIZE (8*8*2*NB_COMPONENTS)
38 #define RKD_HUFFMAN_MINCODE_TBL_SIZE (16*3*2*NB_COMPONENTS)
39 #define RKD_HUFFMAN_VALUE_TBL_SIZE (16*12*NB_COMPONENTS)
40 #define RKD_HUFFMAN_MINCODE_TBL_OFFSET (RKD_QUANTIZATION_TBL_SIZE)
41 #define RKD_HUFFMAN_VALUE_TBL_OFFSET (RKD_HUFFMAN_MINCODE_TBL_OFFSET + MPP_ALIGN(RKD_HUFFMAN_MINCODE_TBL_SIZE, 64))
42 #define RKD_TABLE_SIZE (RKD_HUFFMAN_VALUE_TBL_OFFSET + RKD_HUFFMAN_VALUE_TBL_SIZE)
43
jpegd_write_rkv_qtbl(JpegdHalCtx * ctx,JpegdSyntax * syntax)44 MPP_RET jpegd_write_rkv_qtbl(JpegdHalCtx *ctx, JpegdSyntax *syntax)
45 {
46 jpegd_dbg_func("enter\n");
47 MPP_RET ret = MPP_OK;
48 JpegdSyntax *s = syntax;
49 RK_U16 *base = (RK_U16 *)mpp_buffer_get_ptr(ctx->pTableBase);
50 RK_U16 table_tmp[QUANTIZE_TABLE_LENGTH] = {0};
51 RK_U32 i, j , idx;
52
53 for (j = 0; j < s->nb_components; j++) {
54 idx = s->quant_index[j];
55
56 //turn zig-zag order to raster-scan order
57 for (i = 0; i < QUANTIZE_TABLE_LENGTH; i++) {
58 table_tmp[zzOrder[i]] = s->quant_matrixes[idx][i];
59 }
60
61 memcpy(base + j * QUANTIZE_TABLE_LENGTH, table_tmp, sizeof(RK_U16) * QUANTIZE_TABLE_LENGTH);
62 }
63
64 if (jpegd_debug & JPEGD_DBG_HAL_TBL) {
65 RK_U8 *data = (RK_U8 *)mpp_buffer_get_ptr(ctx->pTableBase);
66
67 mpp_log("--------------Quant tbl----------------------\n");
68 for (i = 0; i < RKD_QUANTIZATION_TBL_SIZE; i += 8) {
69 mpp_log("%02x%02x%02x%02x%02x%02x%02x%02x\n",
70 data[i + 7], data[i + 6], data[i + 5], data[i + 4],
71 data[i + 3], data[i + 2], data[i + 1], data[i + 0]);
72 }
73 }
74
75 jpegd_dbg_func("exit\n");
76 return ret;
77
78 }
79
jpegd_write_rkv_htbl(JpegdHalCtx * ctx,JpegdSyntax * jpegd_syntax)80 MPP_RET jpegd_write_rkv_htbl(JpegdHalCtx *ctx, JpegdSyntax *jpegd_syntax)
81 {
82 jpegd_dbg_func("enter\n");
83 MPP_RET ret = MPP_OK;
84
85 JpegdSyntax *s = jpegd_syntax;
86 void * htbl_ptr[6] = {NULL};
87 RK_U32 i, j, k = 0;
88 RK_U8 *p_htbl_value = (RK_U8 *)mpp_buffer_get_ptr(ctx->pTableBase) + RKD_HUFFMAN_VALUE_TBL_OFFSET;
89 RK_U16 *p_htbl_mincode = (RK_U16 *)mpp_buffer_get_ptr(ctx->pTableBase) + RKD_HUFFMAN_MINCODE_TBL_OFFSET / 2;
90 RK_U16 min_code_ac[16] = {0};
91 RK_U16 min_code_dc[16] = {0};
92 RK_U16 acc_addr_ac[16] = {0};
93 RK_U16 acc_addr_dc[16] = {0};
94 RK_U8 htbl_value[192] = {0};
95 RK_U16 code = 0;
96 RK_S32 addr = 0;
97 RK_U32 len = 0;
98 AcTable *ac_ptr;
99 DcTable *dc_ptr;
100
101 htbl_ptr[0] = &s->dc_table[s->dc_index[0]];
102 htbl_ptr[1] = &s->ac_table[s->ac_index[0]];
103
104 htbl_ptr[2] = &s->dc_table[s->dc_index[1]];
105 htbl_ptr[3] = &s->ac_table[s->ac_index[1]];
106
107 htbl_ptr[4] = htbl_ptr[2];
108 htbl_ptr[5] = htbl_ptr[3];
109
110 for (k = 0; k < s->nb_components; k++) {
111 dc_ptr = (DcTable *)htbl_ptr[k * 2];
112 ac_ptr = (AcTable *)htbl_ptr[k * 2 + 1];
113
114 len = dc_ptr->bits[0];
115 code = addr = 0;
116 min_code_dc[0] = 0;
117 acc_addr_dc[0] = 0;
118
119 for (j = 0; j < 16; j++) {
120 len = dc_ptr->bits[j];
121
122 if (len == 0 && j > 0) {
123 if (code > (min_code_dc[j - 1] << 1))
124 min_code_dc[j] = code;
125 else
126 min_code_dc[j] = min_code_dc[j - 1] << 1;
127 } else {
128 min_code_dc[j] = code;
129 }
130
131 code += len;
132 addr += len;
133 acc_addr_dc[j] = addr;
134 code <<= 1;
135
136 }
137
138 if (dc_ptr->bits[15])
139 min_code_dc[0] = min_code_dc[15] + dc_ptr->bits[15] - 1;
140 else
141 min_code_dc[0] = min_code_dc[15];
142
143 len = ac_ptr->bits[0];
144 code = addr = 0;
145 min_code_ac[0] = 0;
146 acc_addr_ac[0] = 0;
147 for (j = 0; j < 16; j++) {
148 len = ac_ptr->bits[j];
149
150 if (len == 0 && j > 0) {
151 if (code > (min_code_ac[j - 1] << 1))
152 min_code_ac[j] = code;
153 else
154 min_code_ac[j] = min_code_ac[j - 1] << 1;
155 } else {
156 min_code_ac[j] = code;
157 }
158
159 code += len;
160 addr += len;
161 acc_addr_ac[j] = addr;
162 code <<= 1;
163 }
164
165 if (ac_ptr->bits[15])
166 min_code_ac[0] = min_code_ac[15] + ac_ptr->bits[15] - 1;
167 else
168 min_code_ac[0] = min_code_ac[15];
169
170 for (i = 0; i < 16; i++) {
171 *p_htbl_mincode++ = min_code_dc[i];
172 }
173
174 for (i = 0; i < 8; i++) {
175 *p_htbl_mincode++ = acc_addr_dc[2 * i] | acc_addr_dc[2 * i + 1] << 8;
176 }
177
178 for (i = 0; i < 16; i++) {
179 *p_htbl_mincode++ = min_code_ac[i];
180 }
181
182 for (i = 0; i < 8; i++) {
183 *p_htbl_mincode++ = acc_addr_ac[2 * i] | acc_addr_ac[2 * i + 1] << 8;
184 }
185
186 for (i = 0; i < MAX_DC_HUFFMAN_TABLE_LENGTH; i++) {
187 htbl_value[i] = dc_ptr->vals[i];
188 }
189
190 for (i = 0; i < MAX_AC_HUFFMAN_TABLE_LENGTH; i++) {
191 htbl_value[i + 16] = ac_ptr->vals[i];
192 }
193
194 for (i = 0; i < 12 * 16; i++) {
195 *p_htbl_value++ = htbl_value[i];
196 }
197 }
198
199 if (jpegd_debug & JPEGD_DBG_HAL_TBL) {
200 RK_U8 *data = (RK_U8 *)mpp_buffer_get_ptr(ctx->pTableBase) + RKD_HUFFMAN_VALUE_TBL_OFFSET;
201
202 mpp_log("--------------huffman value tbl----------------------\n");
203 for (i = 0; i < RKD_HUFFMAN_VALUE_TBL_SIZE; i += 8) {
204 mpp_log("%02x%02x%02x%02x%02x%02x%02x%02x\n",
205 data[i + 7], data[i + 6], data[i + 5], data[i + 4],
206 data[i + 3], data[i + 2], data[i + 1], data[i + 0]);
207 }
208
209 data = NULL;
210 data = (RK_U8 *)mpp_buffer_get_ptr(ctx->pTableBase) + RKD_HUFFMAN_MINCODE_TBL_OFFSET;
211
212 mpp_log("--------------huffman mincode tbl----------------------\n");
213 for (i = 0; i < RKD_HUFFMAN_MINCODE_TBL_SIZE; i += 8) {
214 mpp_log("%02x%02x%02x%02x%02x%02x%02x%02x\n",
215 data[i + 7], data[i + 6], data[i + 5], data[i + 4],
216 data[i + 3], data[i + 2], data[i + 1], data[i + 0]);
217 }
218 }
219
220 jpegd_dbg_func("exit\n");
221 return ret;
222 }
223
hal_jpegd_rkv_init(void * hal,MppHalCfg * cfg)224 MPP_RET hal_jpegd_rkv_init(void *hal, MppHalCfg *cfg)
225 {
226 jpegd_dbg_func("enter\n");
227 MPP_RET ret = MPP_OK;
228 JpegdHalCtx *ctx = (JpegdHalCtx *)hal;
229 if (NULL == ctx) {
230 ctx = (JpegdHalCtx *)mpp_calloc(JpegdHalCtx, 1);
231 if (NULL == ctx) {
232 mpp_err_f("NULL pointer");
233 return MPP_ERR_NULL_PTR;
234 }
235 }
236
237 ctx->dec_cb = cfg->dec_cb;
238 ctx->packet_slots = cfg->packet_slots;
239 ctx->frame_slots = cfg->frame_slots;
240
241 /* allocate regs buffer */
242 if (ctx->regs == NULL) {
243 ctx->regs = mpp_calloc_size(void, sizeof(JpegRegSet));
244 if (ctx->regs == NULL) {
245 mpp_err("hal jpegd reg alloc failed\n");
246
247 jpegd_dbg_func("exit\n");
248 return MPP_ERR_NOMEM;
249 }
250 }
251
252 if (ctx->group == NULL) {
253 ret = mpp_buffer_group_get_internal(&ctx->group, MPP_BUFFER_TYPE_ION);
254 if (ret) {
255 mpp_err_f("mpp_buffer_group_get failed ret %d\n", ret);
256 return ret;
257 }
258 }
259
260 ret = mpp_buffer_get(ctx->group, &ctx->pTableBase, RKD_TABLE_SIZE);
261 if (ret) {
262 mpp_err_f("Get table buffer failed, ret %d\n", ret);
263 }
264
265 mpp_buffer_attach_dev(ctx->pTableBase, ctx->dev);
266
267 jpegd_dbg_func("exit\n");
268 return ret;
269 }
270
setup_output_fmt(JpegdHalCtx * ctx,JpegdSyntax * syntax,RK_S32 out_idx)271 static MPP_RET setup_output_fmt(JpegdHalCtx *ctx, JpegdSyntax *syntax, RK_S32 out_idx)
272 {
273
274 jpegd_dbg_func("enter\n");
275 MPP_RET ret = MPP_OK;
276 JpegdSyntax *s = syntax;
277 JpegRegSet *regs = (JpegRegSet *)ctx->regs;
278 RK_U32 stride = syntax->hor_stride;
279 MppFrame frm = NULL;
280
281 mpp_buf_slot_get_prop(ctx->frame_slots, out_idx, SLOT_FRAME_PTR, &frm);
282
283 if (ctx->scale) {
284 if (ctx->scale == 2)
285 regs->reg2_sys.scaledown_mode = SCALEDOWN_HALF;
286 if (ctx->scale == 4)
287 regs->reg2_sys.scaledown_mode = SCALEDOWN_QUARTER;
288 if (ctx->scale == 8)
289 regs->reg2_sys.scaledown_mode = SCALEDOWN_ONE_EIGHTS;
290 } else {
291 regs->reg2_sys.scaledown_mode = SCALEDOWN_DISABLE;
292 }
293
294 mpp_frame_set_hor_stride_pixel(frm, stride);
295
296 if (ctx->set_output_fmt_flag && (ctx->output_fmt != s->output_fmt)) { // PP enable
297 if (MPP_FRAME_FMT_IS_YUV(ctx->output_fmt) && s->output_fmt != MPP_FMT_YUV400) {
298 if (ctx->output_fmt == MPP_FMT_YUV420SP)
299 regs->reg2_sys.yuv_out_format = YUV_OUT_FMT_2_NV12;
300 else if (ctx->output_fmt == MPP_FMT_YUV422_YUYV)
301 /* Only support yuv422 and yuv444.
302 * Other format transformation won't report hardware irq error,
303 * and won't get a correct YUV image.
304 */
305 regs->reg2_sys.yuv_out_format = YUV_OUT_FMT_2_YUYV;
306 else if (ctx->output_fmt == MPP_FMT_YUV422_YVYU) {
307 regs->reg2_sys.out_cbcr_swap = 1;
308 regs->reg2_sys.yuv_out_format = YUV_OUT_FMT_2_YUYV;
309 } else if (ctx->output_fmt == MPP_FMT_YUV420SP_VU) {
310 regs->reg2_sys.yuv_out_format = YUV_OUT_FMT_2_NV12;
311 regs->reg2_sys.out_cbcr_swap = 1;
312 }
313 } else if (MPP_FRAME_FMT_IS_RGB(ctx->output_fmt)) {
314 if (ctx->output_fmt == MPP_FMT_RGB888) {
315 regs->reg2_sys.yuv_out_format = YUV_OUT_FMT_2_RGB888;
316 mpp_frame_set_hor_stride(frm, stride * 3);
317 } else if (ctx->output_fmt == (MPP_FMT_BGR565 | MPP_FRAME_FMT_LE_MASK) ||
318 ctx->output_fmt == MPP_FMT_RGB565) { // bgr565le or rgb565be
319 regs->reg2_sys.yuv_out_format = YUV_OUT_FMT_2_RGB565;
320 mpp_frame_set_hor_stride(frm, stride * 2);
321 } else {
322 mpp_err_f("unsupported output format %d\n", ctx->output_fmt);
323 ret = MPP_NOK;
324 }
325 MppFrameColorRange color_range = MPP_FRAME_RANGE_UNSPECIFIED;
326 color_range = mpp_frame_get_color_range(frm);
327 if (color_range != MPP_FRAME_RANGE_MPEG)
328 regs->reg2_sys.yuv2rgb_range = YUV_TO_RGB_FULL_RANGE;
329 else
330 regs->reg2_sys.yuv2rgb_range = YUV_TO_RGB_LIMIT_RANGE;
331 }
332 } else { //keep original format
333 regs->reg2_sys.yuv_out_format = YUV_OUT_FMT_NO_TRANS;
334 ctx->output_fmt = s->output_fmt;
335 }
336
337 if (MPP_FRAME_FMT_IS_TILE(ctx->output_fmt))
338 regs->reg2_sys.dec_out_sequence = OUTPUT_TILE;
339 else
340 regs->reg2_sys.dec_out_sequence = OUTPUT_RASTER;
341
342 jpegd_dbg_hal("convert format %d to format %d\n", s->output_fmt, ctx->output_fmt);
343
344 if ((s->yuv_mode == YUV_MODE_420 && regs->reg2_sys.yuv_out_format == YUV_OUT_FMT_NO_TRANS) ||
345 (regs->reg2_sys.yuv_out_format == YUV_OUT_FMT_2_NV12))
346 regs->reg2_sys.fill_down_e = 1;
347 else
348 regs->reg2_sys.fill_down_e = s->fill_bottom;
349 regs->reg2_sys.fill_right_e = s->fill_right;
350
351 mpp_frame_set_fmt(frm, ctx->output_fmt);
352
353 jpegd_dbg_func("exit\n");
354 return ret;
355 }
356
jpegd_gen_regs(JpegdHalCtx * ctx,JpegdSyntax * syntax)357 static MPP_RET jpegd_gen_regs(JpegdHalCtx *ctx, JpegdSyntax *syntax)
358 {
359 jpegd_dbg_func("enter\n");
360 MPP_RET ret = MPP_OK;
361 JpegdSyntax *s = syntax;
362 JpegRegSet *regs = (JpegRegSet *)ctx->regs;
363
364 regs->reg1_int.dec_e = 1;
365 regs->reg1_int.dec_timeout_e = 1;
366 regs->reg1_int.buf_empty_e = 1;
367
368 regs->reg3_pic_size.pic_width_m1 = s->width - 1;
369 regs->reg3_pic_size.pic_height_m1 = s->height - 1;
370
371 if (s->sample_precision != DCT_SAMPLE_PRECISION_8 || s->qtbl_entry > TBL_ENTRY_3)
372 return MPP_NOK;
373
374 regs->reg4_pic_fmt.pixel_depth = BIT_DEPTH_8;
375 if (s->nb_components == 1) {
376 regs->reg4_pic_fmt.htables_sel = TBL_ENTRY_1;
377 }
378
379 if (s->nb_components > 1) {
380 regs->reg4_pic_fmt.qtables_sel = (s->qtbl_entry > 1) ? TBL_ENTRY_3 : TBL_ENTRY_2;
381 regs->reg4_pic_fmt.htables_sel = (s->htbl_entry > 0x0f) ? TBL_ENTRY_3 : TBL_ENTRY_2;
382 } else {
383 regs->reg4_pic_fmt.qtables_sel = TBL_ENTRY_1;
384 regs->reg4_pic_fmt.htables_sel = TBL_ENTRY_1;
385 }
386
387 if (s->restart_interval) {
388 regs->reg4_pic_fmt.dri_e = RST_ENABLE;
389 regs->reg4_pic_fmt.dri_mcu_num_m1 = s->restart_interval - 1;
390 }
391
392 switch (s->yuv_mode) {
393 case JPEGDEC_YUV400:
394 case JPEGDEC_YUV420:
395 case JPEGDEC_YUV422:
396 regs->reg4_pic_fmt.jpeg_mode = s->yuv_mode;
397 break;
398 case JPEGDEC_YUV411:
399 regs->reg4_pic_fmt.jpeg_mode = YUV_MODE_411;
400 break;
401 case JPEGDEC_YUV440:
402 regs->reg4_pic_fmt.jpeg_mode = YUV_MODE_440;
403 break;
404 case JPEGDEC_YUV444:
405 regs->reg4_pic_fmt.jpeg_mode = YUV_MODE_444;
406 break;
407 default:
408 mpp_err_f("unsupported yuv mode %d\n", s->yuv_mode);
409 break;
410 }
411
412 RK_U32 out_width = MPP_ALIGN(s->width, 16);
413 RK_U32 out_height = s->height;
414 out_width = out_width >> regs->reg2_sys.scaledown_mode;
415 out_width = MPP_ALIGN(out_width, 16);
416 out_height = regs->reg2_sys.fill_down_e ? MPP_ALIGN(out_height, 16) : MPP_ALIGN(out_height, 8);
417 out_height = out_height >> regs->reg2_sys.scaledown_mode;
418 jpegd_dbg_hal("output scale %d, width %d, height %d\n", regs->reg2_sys.scaledown_mode, out_width, out_height);
419
420 RK_U32 y_hor_stride = out_width >> 4;
421 RK_U32 y_virstride = 0;
422 RK_U32 uv_hor_virstride = 0;
423
424 switch (regs->reg2_sys.yuv_out_format) {
425 case YUV_OUT_FMT_2_RGB888:
426 y_hor_stride *= 3;
427 break;
428 case YUV_OUT_FMT_2_RGB565:
429 case YUV_OUT_FMT_2_YUYV:
430 y_hor_stride *= 2;
431 break;
432 case YUV_OUT_FMT_NO_TRANS:
433 switch (regs->reg4_pic_fmt.jpeg_mode) {
434 case YUV_MODE_440:
435 case YUV_MODE_444:
436 uv_hor_virstride = y_hor_stride * 2;
437 break;
438 case YUV_MODE_411:
439 uv_hor_virstride = y_hor_stride >> 1;
440 break;
441 case YUV_MODE_400:
442 uv_hor_virstride = 0;
443 break;
444 default:
445 uv_hor_virstride = y_hor_stride;
446 break;
447 }
448 break;
449 case YUV_OUT_FMT_2_NV12:
450 uv_hor_virstride = y_hor_stride;
451 break;
452 }
453
454 y_virstride = y_hor_stride * out_height;
455 if (regs->reg2_sys.dec_out_sequence == OUTPUT_TILE) {
456 // The new JPEG decoder supports tile 4x4 output by default.
457 if (mpp_get_soc_type() >= ROCKCHIP_SOC_RK3576) {
458 switch (regs->reg2_sys.yuv_out_format) {
459 case YUV_OUT_FMT_2_YUYV:
460 y_hor_stride = y_hor_stride * 4 * 2;
461 break;
462 case YUV_OUT_FMT_NO_TRANS:
463 switch (regs->reg4_pic_fmt.jpeg_mode) {
464 case YUV_MODE_422:
465 case YUV_MODE_440:
466 y_hor_stride = y_hor_stride * 4 * 2;
467 break;
468 case YUV_MODE_444:
469 y_hor_stride = y_hor_stride * 4 * 3;
470 break;
471 case YUV_MODE_411:
472 case YUV_MODE_420:
473 y_hor_stride = y_hor_stride * 4 * 3 / 2;
474 break;
475 case YUV_MODE_400:
476 y_hor_stride = y_hor_stride * 4;
477 break;
478 default:
479 return MPP_NOK;
480 break;
481 }
482 break;
483 case YUV_OUT_FMT_2_NV12:
484 y_hor_stride = y_hor_stride * 4 * 3 / 2;
485 break;
486 }
487
488 uv_hor_virstride = 0;
489 } else {
490 y_hor_stride <<= 3;
491 uv_hor_virstride <<= 3;
492 }
493 }
494
495 regs->reg5_hor_virstride.y_hor_virstride = y_hor_stride & 0xffff;
496 regs->reg5_hor_virstride.uv_hor_virstride = uv_hor_virstride & 0xffff;
497 regs->reg6_y_virstride.y_virstride = y_virstride;
498
499 regs->reg7_tbl_len.y_hor_virstride_h = (y_hor_stride >> 16) & 1;
500
501 if (s->qtable_cnt)
502 regs->reg7_tbl_len.qtbl_len = regs->reg4_pic_fmt.qtables_sel * 8 - 1;
503 else
504 regs->reg7_tbl_len.qtbl_len = 0;
505
506 // 8 bit precision 12, 12 bit precision 16;
507 regs->reg7_tbl_len.htbl_value_len = regs->reg4_pic_fmt.htables_sel * (regs->reg4_pic_fmt.pixel_depth ? 16 : 12) - 1;
508
509 switch (regs->reg4_pic_fmt.htables_sel) {
510 case TBL_ENTRY_0 :
511 regs->reg7_tbl_len.htbl_mincode_len = 0;
512 regs->reg7_tbl_len.htbl_value_len = 0;
513 break;
514 case TBL_ENTRY_2 :
515 regs->reg7_tbl_len.htbl_mincode_len = (s->nb_components - 1) * 6 - 1;
516 break;
517 case TBL_ENTRY_1 :
518 case TBL_ENTRY_3 :
519 regs->reg7_tbl_len.htbl_mincode_len = s->nb_components * 6 - 1;
520 break;
521 default :
522 mpp_err_f("unsupported htable_sel %d\n", regs->reg4_pic_fmt.htables_sel);
523 break;
524 }
525
526 RK_U32 strm_offset = 0;
527 RK_U32 hw_strm_offset = 0;
528 RK_U8 start_byte = 0;
529 RK_U32 table_fd = mpp_buffer_get_fd(ctx->pTableBase);
530
531 if (table_fd <= 0) {
532 mpp_err_f("get table_fd failed\n");
533 return MPP_NOK;
534 }
535
536 strm_offset = s->strm_offset;
537 hw_strm_offset = strm_offset - strm_offset % 16;
538 start_byte = strm_offset % 16;
539
540 regs->reg8_strm_len.stream_len = (MPP_ALIGN((s->pkt_len - hw_strm_offset), 16) - 1) >> 4;
541 regs->reg8_strm_len.strm_start_byte = start_byte;
542
543 regs->reg9_qtbl_base = table_fd;
544 regs->reg10_htbl_mincode_base = table_fd;
545 regs->reg11_htbl_value_base = table_fd;
546 regs->reg13_dec_out_base = ctx->frame_fd;
547 regs->reg12_strm_base = ctx->pkt_fd;
548
549 mpp_dev_set_reg_offset(ctx->dev, 12, hw_strm_offset);
550 mpp_dev_set_reg_offset(ctx->dev, 10, RKD_HUFFMAN_MINCODE_TBL_OFFSET);
551 mpp_dev_set_reg_offset(ctx->dev, 11, RKD_HUFFMAN_VALUE_TBL_OFFSET);
552
553 regs->reg14_strm_error.error_prc_mode = 1;
554 regs->reg14_strm_error.strm_ffff_err_mode = 2;
555 regs->reg14_strm_error.strm_other_mark_mode = 2;
556 regs->reg14_strm_error.strm_dri_seq_err_mode = 0;
557
558 regs->reg16_clk_gate.val = 0xff;
559
560 regs->reg30_perf_latency_ctrl0.axi_per_work_e = 1;
561 regs->reg30_perf_latency_ctrl0.axi_per_clr_e = 1;
562 regs->reg30_perf_latency_ctrl0.axi_cnt_type = 1;
563 regs->reg30_perf_latency_ctrl0.rd_latency_id = 0xa;
564
565 jpegd_write_rkv_htbl(ctx, s);
566
567 jpegd_write_rkv_qtbl(ctx, s);
568
569 jpegd_dbg_func("exit\n");
570 return ret;
571 }
572
hal_jpegd_rkv_deinit(void * hal)573 MPP_RET hal_jpegd_rkv_deinit(void *hal)
574 {
575 MPP_RET ret = MPP_OK;
576 JpegdHalCtx *ctx = (JpegdHalCtx *)hal;
577
578 jpegd_dbg_func("enter\n");
579
580 if (ctx->dev) {
581 mpp_dev_deinit(ctx->dev);
582 ctx->dev = NULL;
583 }
584
585 if (ctx->pTableBase) {
586 ret = mpp_buffer_put(ctx->pTableBase);
587 if (ret) {
588 mpp_err_f("put buffer failed\n");
589 return ret;
590 }
591 }
592
593 if (ctx->group) {
594 ret = mpp_buffer_group_put(ctx->group);
595 if (ret) {
596 mpp_err_f("group free buffer failed\n");
597 return ret;
598 }
599 }
600
601 if (ctx->regs) {
602 mpp_free(ctx->regs);
603 ctx->regs = NULL;
604 }
605
606 ctx->output_fmt = MPP_FMT_YUV420SP;
607 ctx->set_output_fmt_flag = 0;
608 ctx->hal_debug_enable = 0;
609 ctx->frame_count = 0;
610 ctx->output_yuv_count = 0;
611
612 jpegd_dbg_func("exit\n");
613 return ret;
614 }
615
hal_jpegd_rkv_gen_regs(void * hal,HalTaskInfo * syn)616 MPP_RET hal_jpegd_rkv_gen_regs(void *hal, HalTaskInfo *syn)
617 {
618 jpegd_dbg_func("enter\n");
619 MPP_RET ret = MPP_OK;
620 JpegdHalCtx *ctx = (JpegdHalCtx *)hal;
621 JpegdSyntax *s = (JpegdSyntax *)syn->dec.syntax.data;
622
623 MppBuffer strm_buf = NULL;
624 MppBuffer output_buf = NULL;
625
626 if (syn->dec.flags.parse_err)
627 goto __RETURN;
628
629 mpp_buf_slot_get_prop(ctx->packet_slots, syn->dec.input, SLOT_BUFFER, & strm_buf);
630 mpp_buf_slot_get_prop(ctx->frame_slots, syn->dec.output, SLOT_BUFFER, &output_buf);
631
632 ctx->pkt_fd = mpp_buffer_get_fd(strm_buf);
633 if (ctx->pkt_fd <= 0) {
634 mpp_err_f("get pkt_fd failed\n");
635 goto __RETURN;
636 }
637
638 ctx->frame_fd = mpp_buffer_get_fd(output_buf);
639 if (ctx->frame_fd <= 0) {
640 mpp_err_f("get frame_fd failed\n");
641 goto __RETURN;
642 }
643
644 memset(ctx->regs, 0, sizeof(JpegRegSet));
645
646 setup_output_fmt(ctx, s, syn->dec.output);
647
648 ret = jpegd_gen_regs(ctx, s);
649 mpp_buffer_sync_end(strm_buf);
650 mpp_buffer_sync_end(ctx->pTableBase);
651
652 if (ret != MPP_OK) {
653 mpp_err_f("generate registers failed\n");
654 goto __RETURN;
655 }
656
657 syn->dec.valid = 1;
658 jpegd_dbg_func("exit\n");
659 return ret;
660
661 __RETURN:
662 syn->dec.flags.parse_err = 1;
663 jpegd_dbg_func("exit\n");
664 return ret;
665 }
666
hal_jpegd_rkv_start(void * hal,HalTaskInfo * task)667 MPP_RET hal_jpegd_rkv_start(void *hal, HalTaskInfo *task)
668 {
669 MPP_RET ret = MPP_OK;
670 JpegdHalCtx * ctx = (JpegdHalCtx *)hal;
671 RK_U32 *regs = (RK_U32 *)ctx->regs;
672
673 jpegd_dbg_func("enter\n");
674 if (task->dec.flags.parse_err)
675 goto __RETURN;
676
677 MppDevRegWrCfg wr_cfg;
678 MppDevRegRdCfg rd_cfg;
679 RK_U32 reg_size = JPEGD_REG_NUM * sizeof(RK_U32);
680 RK_U8 i = 0;
681
682 wr_cfg.reg = regs;
683 wr_cfg.size = reg_size;
684 wr_cfg.offset = 0;
685
686 if (jpegd_debug & JPEGD_DBG_HAL_INFO) {
687 for (i = 0; i < JPEGD_REG_NUM; i++) {
688 mpp_log_f("send reg[%d]=0x%08x\n", i, regs[i]);
689 }
690 }
691
692 ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_WR, &wr_cfg);
693
694 if (ret) {
695 mpp_err_f("set register write failed %d\n", ret);
696 goto __RETURN;
697 }
698
699 rd_cfg.reg = regs;
700 rd_cfg.size = reg_size;
701 rd_cfg.offset = 0;
702
703 ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_RD, &rd_cfg);
704
705 if (ret) {
706 mpp_err_f("set register read failed %d\n", ret);
707 goto __RETURN;
708 }
709
710 ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_CMD_SEND, NULL);
711
712 if (ret) {
713 mpp_err_f("send cmd failed %d\n", ret);
714 goto __RETURN;
715 }
716
717 jpegd_dbg_func("exit\n");
718 return ret;
719
720 __RETURN:
721 task->dec.flags.parse_err = 1;
722 jpegd_dbg_func("exit\n");
723 return ret;
724 }
725
hal_jpegd_rkv_wait(void * hal,HalTaskInfo * task)726 MPP_RET hal_jpegd_rkv_wait(void *hal, HalTaskInfo *task)
727 {
728 MPP_RET ret = MPP_OK;
729 JpegdHalCtx *ctx = (JpegdHalCtx *)hal;
730 JpegRegSet *reg_out = ctx->regs;
731 RK_U32 errinfo = 0;
732 RK_U8 i = 0;
733
734 jpegd_dbg_func("enter\n");
735 if (task->dec.flags.parse_err)
736 goto __SKIP_HARD;
737
738 ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_CMD_POLL, NULL);
739
740 if (ret) {
741 task->dec.flags.parse_err = 1;
742 mpp_err_f("poll cmd failed %d\n", ret);
743 }
744
745 __SKIP_HARD:
746 if (ctx->dec_cb) {
747 DecCbHalDone param;
748
749 param.task = (void *)&task->dec;
750 param.regs = (RK_U32 *)reg_out;
751 if (!reg_out->reg1_int.dec_irq || !reg_out->reg1_int.dec_rdy_sta
752 || reg_out->reg1_int.dec_bus_sta || reg_out->reg1_int.dec_error_sta
753 || reg_out->reg1_int.dec_timeout_sta
754 || reg_out->reg1_int.dec_buf_empty_sta) {
755 mpp_err("decode result: failed, irq 0x%08x\n", ((RK_U32 *)reg_out)[1]);
756 errinfo = 1;
757 }
758 param.hard_err = errinfo;
759 mpp_callback(ctx->dec_cb, ¶m);
760 }
761 if (jpegd_debug & JPEGD_DBG_HAL_INFO) {
762 for (i = 0; i < JPEGD_REG_NUM; i++) {
763 mpp_log_f("read regs[%d]=0x%08x\n", i, ((RK_U32*)reg_out)[i]);
764 }
765 }
766
767 jpegd_dbg_hal("decode one frame in cycles: %d\n", reg_out->reg39_perf_working_cnt);
768 if (jpegd_debug & JPEGD_DBG_IO) {
769 FILE *jpg_file;
770 char name[32];
771 MppBuffer outputBuf = NULL;
772 void *base = NULL;
773 mpp_buf_slot_get_prop(ctx->frame_slots, task->dec.output, SLOT_BUFFER, &outputBuf);
774 base = mpp_buffer_get_ptr(outputBuf);
775
776 snprintf(name, sizeof(name) - 1, "/data/tmp/output%02d.yuv", ctx->output_yuv_count);
777 jpg_file = fopen(name, "wb+");
778 if (jpg_file) {
779 JpegdSyntax *s = (JpegdSyntax *) task->dec.syntax.data;
780 RK_U32 width = s->hor_stride;
781 RK_U32 height = s->ver_stride;
782
783 fwrite(base, width * height * 3, 1, jpg_file);
784 jpegd_dbg_io("frame_%02d output YUV(%d*%d) saving to %s\n", ctx->output_yuv_count,
785 width, height, name);
786 fclose(jpg_file);
787 ctx->output_yuv_count++;
788 }
789 }
790
791 memset(®_out->reg1_int, 0, sizeof(RK_U32));
792
793 jpegd_dbg_func("exit\n");
794 return ret;
795 }
796
hal_jpegd_rkv_control(void * hal,MpiCmd cmd_type,void * param)797 MPP_RET hal_jpegd_rkv_control(void *hal, MpiCmd cmd_type, void *param)
798 {
799 jpegd_dbg_func("enter\n");
800 MPP_RET ret = MPP_OK;
801 JpegdHalCtx *JpegHalCtx = (JpegdHalCtx *)hal;
802
803 if (NULL == JpegHalCtx) {
804 mpp_err_f("NULL pointer");
805 return MPP_ERR_NULL_PTR;
806 }
807
808 switch (cmd_type) {
809 case MPP_DEC_SET_OUTPUT_FORMAT: {
810 MppFrameFormat output_fmt = *((MppFrameFormat *)param);
811 RockchipSocType soc_type = mpp_get_soc_type();
812 MppFrameFormat frm_fmt = output_fmt & MPP_FRAME_FMT_MASK;
813
814 if (MPP_FRAME_FMT_IS_FBC(output_fmt)) {
815 ret = MPP_ERR_VALUE;
816 }
817
818 if (MPP_FRAME_FMT_IS_TILE(output_fmt)) {
819 if (soc_type < ROCKCHIP_SOC_RK3576 || MPP_FRAME_FMT_IS_RGB(output_fmt)) {
820 ret = MPP_ERR_VALUE;
821 }
822 }
823
824 if (MPP_FRAME_FMT_IS_RGB(output_fmt)) {
825 // The new JPEG decoder defaults to no RGB support.
826 if (soc_type >= ROCKCHIP_SOC_RK3576) {
827 ret = MPP_ERR_VALUE;
828 } else if (soc_type >= ROCKCHIP_SOC_RK3588) {
829 // only rgb565be and rgb888 supported
830 if (output_fmt != MPP_FMT_RGB555 && output_fmt != MPP_FMT_RGB888 ) {
831 ret = MPP_ERR_VALUE;
832 }
833 } else {
834 // only bgr565le and rgb 888 supported
835 if (frm_fmt != (MPP_FMT_BGR565 | MPP_FRAME_FMT_LE_MASK)
836 && output_fmt != MPP_FMT_RGB888) {
837 ret = MPP_ERR_VALUE;
838 }
839 }
840 }
841
842 if (ret) {
843 mpp_err_f("invalid output format 0x%x\n", output_fmt);
844 } else {
845 JpegHalCtx->output_fmt = output_fmt;
846 JpegHalCtx->set_output_fmt_flag = 1;
847 jpegd_dbg_hal("output_format: 0x%x\n", JpegHalCtx->output_fmt);
848 }
849 } break;
850 //TODO support scale and tile output
851 default :
852 break;
853 }
854
855 jpegd_dbg_func("exit ret %d\n", ret);
856 return ret;
857 }
858