1 /* SPDX-License-Identifier: Apache-2.0 OR MIT */
2 /*
3 * Copyright (c) 2024 Rockchip Electronics Co., Ltd.
4 */
5
6 #define MODULE_TAG "vdpu384a_com"
7
8 #include <string.h>
9
10 #include "mpp_log.h"
11 #include "mpp_buffer.h"
12 #include "mpp_common.h"
13 #include "mpp_compat_impl.h"
14 #include "mpp_frame_impl.h"
15 #include "mpp_debug.h"
16
17 #include "vdpu384a_com.h"
18
19 static RK_U32 rcb_coeff[RCB_BUF_COUNT] = {
20 [RCB_STRMD_ROW] = 3,
21 [RCB_STRMD_TILE_ROW] = 3,
22 [RCB_INTER_ROW] = 6,
23 [RCB_INTER_TILE_ROW] = 6,
24 [RCB_INTRA_ROW] = 5,
25 [RCB_INTRA_TILE_ROW] = 5,
26 [RCB_FILTERD_ROW] = 90,
27 [RCB_FILTERD_PROTECT_ROW] = 90,
28 [RCB_FILTERD_TILE_ROW] = 90,
29 [RCB_FILTERD_TILE_COL] = 260,
30 [RCB_FILTERD_AV1_UP_TILE_COL] = 0,
31 };
32
update_size_offset(Vdpu384aRcbInfo * info,RK_U32 reg_idx,RK_S32 offset,RK_S32 len,RK_S32 idx)33 static RK_S32 update_size_offset(Vdpu384aRcbInfo *info, RK_U32 reg_idx,
34 RK_S32 offset, RK_S32 len, RK_S32 idx)
35 {
36 RK_S32 buf_size = 0;
37
38 buf_size = MPP_ALIGN(len * rcb_coeff[idx], RCB_ALLINE_SIZE);
39 info[idx].reg_idx = reg_idx;
40 info[idx].offset = offset;
41 info[idx].size = buf_size;
42
43 return buf_size;
44 }
45
vdpu384a_get_rcb_buf_size(Vdpu384aRcbInfo * info,RK_S32 width,RK_S32 height)46 RK_S32 vdpu384a_get_rcb_buf_size(Vdpu384aRcbInfo *info, RK_S32 width, RK_S32 height)
47 {
48 RK_S32 offset = 0;
49
50 offset += update_size_offset(info, 140, offset, width, RCB_STRMD_ROW);
51 offset += update_size_offset(info, 142, offset, width, RCB_STRMD_TILE_ROW);
52 offset += update_size_offset(info, 144, offset, width, RCB_INTER_ROW);
53 offset += update_size_offset(info, 146, offset, width, RCB_INTER_TILE_ROW);
54 offset += update_size_offset(info, 148, offset, width, RCB_INTRA_ROW);
55 offset += update_size_offset(info, 150, offset, width, RCB_INTRA_TILE_ROW);
56 offset += update_size_offset(info, 152, offset, width, RCB_FILTERD_ROW);
57 offset += update_size_offset(info, 154, offset, width, RCB_FILTERD_PROTECT_ROW);
58 offset += update_size_offset(info, 156, offset, width, RCB_FILTERD_TILE_ROW);
59 offset += update_size_offset(info, 158, offset, height, RCB_FILTERD_TILE_COL);
60 offset += update_size_offset(info, 160, offset, height, RCB_FILTERD_AV1_UP_TILE_COL);
61
62 return offset;
63 }
64
vdpu384a_check_rcb_buf_size(Vdpu384aRcbInfo * info,RK_S32 width,RK_S32 height)65 RK_RET vdpu384a_check_rcb_buf_size(Vdpu384aRcbInfo *info, RK_S32 width, RK_S32 height)
66 {
67 RK_U32 i;
68
69 for (i = 0; i < RCB_FILTERD_TILE_COL; i++)
70 mpp_assert(info[i].size < (RK_S32)MPP_ALIGN(width * rcb_coeff[i], RCB_ALLINE_SIZE));
71
72 for (i = RCB_FILTERD_TILE_COL; i < RCB_BUF_COUNT; i++)
73 mpp_assert(info[i].size < (RK_S32)MPP_ALIGN(height * rcb_coeff[i], RCB_ALLINE_SIZE));
74
75 return MPP_OK;
76 }
77
vdpu384a_setup_rcb(Vdpu384aRegCommonAddr * reg,MppDev dev,MppBuffer buf,Vdpu384aRcbInfo * info)78 void vdpu384a_setup_rcb(Vdpu384aRegCommonAddr *reg, MppDev dev,
79 MppBuffer buf, Vdpu384aRcbInfo *info)
80 {
81 RK_U32 i;
82
83 reg->reg140_rcb_strmd_row_offset = mpp_buffer_get_fd(buf);
84 reg->reg142_rcb_strmd_tile_row_offset = mpp_buffer_get_fd(buf);
85 reg->reg144_rcb_inter_row_offset = mpp_buffer_get_fd(buf);
86 reg->reg146_rcb_inter_tile_row_offset = mpp_buffer_get_fd(buf);
87 reg->reg148_rcb_intra_row_offset = mpp_buffer_get_fd(buf);
88 reg->reg150_rcb_intra_tile_row_offset = mpp_buffer_get_fd(buf);
89 reg->reg152_rcb_filterd_row_offset = mpp_buffer_get_fd(buf);
90 reg->reg156_rcb_filterd_tile_row_offset = mpp_buffer_get_fd(buf);
91 reg->reg158_rcb_filterd_tile_col_offset = mpp_buffer_get_fd(buf);
92 reg->reg160_rcb_filterd_av1_upscale_tile_col_offset = mpp_buffer_get_fd(buf);
93
94 reg->reg141_rcb_strmd_row_len = info[RCB_STRMD_ROW].size ;
95 reg->reg143_rcb_strmd_tile_row_len = info[RCB_STRMD_TILE_ROW].size ;
96 reg->reg145_rcb_inter_row_len = info[RCB_INTER_ROW].size ;
97 reg->reg147_rcb_inter_tile_row_len = info[RCB_INTER_TILE_ROW].size ;
98 reg->reg149_rcb_intra_row_len = info[RCB_INTRA_ROW].size ;
99 reg->reg151_rcb_intra_tile_row_len = info[RCB_INTRA_TILE_ROW].size ;
100 reg->reg153_rcb_filterd_row_len = info[RCB_FILTERD_ROW].size ;
101 reg->reg157_rcb_filterd_tile_row_len = info[RCB_FILTERD_TILE_ROW].size ;
102 reg->reg159_rcb_filterd_tile_col_len = info[RCB_FILTERD_TILE_COL].size ;
103 reg->reg161_rcb_filterd_av1_upscale_tile_col_len = info[RCB_FILTERD_AV1_UP_TILE_COL].size;
104
105 for (i = 0; i < RCB_BUF_COUNT; i++) {
106 if (info[i].offset)
107 mpp_dev_set_reg_offset(dev, info[i].reg_idx, info[i].offset);
108 }
109 }
110
vdpu384a_compare_rcb_size(const void * a,const void * b)111 RK_S32 vdpu384a_compare_rcb_size(const void *a, const void *b)
112 {
113 RK_S32 val = 0;
114 Vdpu384aRcbInfo *p0 = (Vdpu384aRcbInfo *)a;
115 Vdpu384aRcbInfo *p1 = (Vdpu384aRcbInfo *)b;
116
117 val = (p0->size > p1->size) ? -1 : 1;
118
119 return val;
120 }
121
vdpu384a_setup_statistic(Vdpu384aCtrlReg * ctrl_regs)122 void vdpu384a_setup_statistic(Vdpu384aCtrlReg *ctrl_regs)
123 {
124 ctrl_regs->reg28.axi_perf_work_e = 1;
125 ctrl_regs->reg28.axi_cnt_type = 1;
126 ctrl_regs->reg28.rd_latency_id = 11;
127
128 ctrl_regs->reg29.addr_align_type = 1;
129 ctrl_regs->reg29.ar_cnt_id_type = 0;
130 ctrl_regs->reg29.aw_cnt_id_type = 1;
131 ctrl_regs->reg29.ar_count_id = 17;
132 ctrl_regs->reg29.aw_count_id = 0;
133 ctrl_regs->reg29.rd_band_width_mode = 0;
134
135 /* set hurry */
136 ctrl_regs->reg30.axi_wr_qos = 0;
137 ctrl_regs->reg30.axi_rd_qos = 0;
138 }
139
vdpu384a_afbc_align_calc(MppBufSlots slots,MppFrame frame,RK_U32 expand)140 void vdpu384a_afbc_align_calc(MppBufSlots slots, MppFrame frame, RK_U32 expand)
141 {
142 RK_U32 ver_stride = 0;
143 RK_U32 img_height = mpp_frame_get_height(frame);
144 RK_U32 img_width = mpp_frame_get_width(frame);
145 RK_U32 hdr_stride = (*compat_ext_fbc_hdr_256_odd) ?
146 (MPP_ALIGN(img_width, 256) | 256) :
147 (MPP_ALIGN(img_width, 64));
148
149 mpp_slots_set_prop(slots, SLOTS_HOR_ALIGN, mpp_align_64);
150 mpp_slots_set_prop(slots, SLOTS_VER_ALIGN, mpp_align_16);
151
152 mpp_frame_set_fbc_hdr_stride(frame, hdr_stride);
153
154 ver_stride = mpp_align_16(img_height);
155 if (*compat_ext_fbc_buf_size) {
156 ver_stride += expand;
157 }
158 mpp_frame_set_ver_stride(frame, ver_stride);
159 }
160
vdpu384a_set_rcbinfo(MppDev dev,Vdpu384aRcbInfo * rcb_info)161 RK_S32 vdpu384a_set_rcbinfo(MppDev dev, Vdpu384aRcbInfo *rcb_info)
162 {
163 MppDevRcbInfoCfg rcb_cfg;
164 RK_U32 i;
165
166 Vdpu384aRcbSetMode_e set_rcb_mode = RCB_SET_BY_PRIORITY_MODE;
167
168 RK_U32 rcb_priority[RCB_BUF_COUNT] = {
169 RCB_FILTERD_ROW,
170 RCB_INTER_ROW,
171 RCB_INTRA_ROW,
172 RCB_STRMD_ROW,
173 RCB_INTER_TILE_ROW,
174 RCB_INTRA_TILE_ROW,
175 RCB_STRMD_TILE_ROW,
176 RCB_FILTERD_TILE_ROW,
177 RCB_FILTERD_TILE_COL,
178 RCB_FILTERD_AV1_UP_TILE_COL,
179 RCB_FILTERD_PROTECT_ROW,
180 };
181 /*
182 * RCB_SET_BY_SIZE_SORT_MODE: by size sort
183 * RCB_SET_BY_PRIORITY_MODE: by priority
184 */
185
186 switch (set_rcb_mode) {
187 case RCB_SET_BY_SIZE_SORT_MODE : {
188 Vdpu384aRcbInfo info[RCB_BUF_COUNT];
189
190 memcpy(info, rcb_info, sizeof(info));
191 qsort(info, MPP_ARRAY_ELEMS(info),
192 sizeof(info[0]), vdpu384a_compare_rcb_size);
193
194 for (i = 0; i < MPP_ARRAY_ELEMS(info); i++) {
195 rcb_cfg.reg_idx = info[i].reg_idx;
196 rcb_cfg.size = info[i].size;
197 if (rcb_cfg.size > 0) {
198 mpp_dev_ioctl(dev, MPP_DEV_RCB_INFO, &rcb_cfg);
199 } else
200 break;
201 }
202 } break;
203 case RCB_SET_BY_PRIORITY_MODE : {
204 Vdpu384aRcbInfo *info = rcb_info;
205 RK_U32 index = 0;
206
207 for (i = 0; i < MPP_ARRAY_ELEMS(rcb_priority); i ++) {
208 index = rcb_priority[i];
209
210 rcb_cfg.reg_idx = info[index].reg_idx;
211 rcb_cfg.size = info[index].size;
212 if (rcb_cfg.size > 0) {
213 mpp_dev_ioctl(dev, MPP_DEV_RCB_INFO, &rcb_cfg);
214 }
215 }
216 } break;
217 default:
218 break;
219 }
220
221 return 0;
222 }
223
vdpu384a_update_thumbnail_frame_info(MppFrame frame)224 void vdpu384a_update_thumbnail_frame_info(MppFrame frame)
225 {
226 RK_U32 down_scale_height = mpp_frame_get_height(frame) >> 1;
227 RK_U32 down_scale_width = mpp_frame_get_width(frame) >> 1;
228 RK_U32 down_scale_ver = MPP_ALIGN(down_scale_height, 16);
229 RK_U32 down_scale_hor = MPP_ALIGN(down_scale_width, 16);
230 RK_U32 down_scale_buf_size = 0;
231
232 if (!MPP_FRAME_FMT_IS_FBC(mpp_frame_get_fmt(frame))) {
233 down_scale_hor = mpp_align_128_odd_plus_64(down_scale_hor);
234 down_scale_ver = mpp_frame_get_ver_stride(frame) >> 1;
235 }
236
237 down_scale_buf_size = down_scale_hor * down_scale_ver * 3 / 2;
238 /*
239 * no matter what format, scale down image will output as 8bit raster format;
240 */
241 mpp_frame_set_fmt(frame, MPP_FMT_YUV420SP);
242 mpp_frame_set_width(frame, down_scale_width);
243 mpp_frame_set_height(frame, down_scale_height);
244 mpp_frame_set_hor_stride(frame, down_scale_hor);
245 mpp_frame_set_ver_stride(frame, down_scale_ver);
246 mpp_frame_set_buf_size(frame, down_scale_buf_size);
247 }
248
vdpu384a_setup_down_scale(MppFrame frame,MppDev dev,Vdpu384aCtrlReg * com,void * comParas)249 void vdpu384a_setup_down_scale(MppFrame frame, MppDev dev, Vdpu384aCtrlReg *com, void* comParas)
250 {
251 RK_U32 down_scale_height = mpp_frame_get_height(frame) >> 1;
252 RK_U32 down_scale_width = mpp_frame_get_width(frame) >> 1;
253 RK_U32 down_scale_ver = MPP_ALIGN(down_scale_height, 16);
254 RK_U32 down_scale_hor = MPP_ALIGN(down_scale_width, 16);
255
256 Vdpu384aRegCommParas* paras = (Vdpu384aRegCommParas*)comParas;
257 MppFrameFormat fmt = mpp_frame_get_fmt(frame);
258 MppMeta meta = mpp_frame_get_meta(frame);
259 RK_U32 down_scale_y_offset = 0;
260 RK_U32 down_scale_uv_offset = 0;
261 RK_U32 down_scale_y_virstride = down_scale_ver * down_scale_hor;
262 RK_U32 downscale_buf_size;
263
264 if (!MPP_FRAME_FMT_IS_FBC(mpp_frame_get_fmt(frame))) {
265 down_scale_hor = mpp_align_128_odd_plus_64(down_scale_hor);
266 down_scale_ver = mpp_frame_get_ver_stride(frame) >> 1;
267 down_scale_y_virstride = down_scale_ver * down_scale_hor;
268 }
269 /*
270 * no matter what format, scale down image will output as 8bit raster format;
271 * down_scale image buffer size was already added to the buf_size of mpp_frame,
272 * which was calculated in mpp_buf_slot.cpp: (size = original_size + scaledown_size)
273 */
274 switch ((fmt & MPP_FRAME_FMT_MASK)) {
275 case MPP_FMT_YUV400 : {
276 downscale_buf_size = down_scale_y_virstride;
277 } break;
278 case MPP_FMT_YUV420SP_10BIT :
279 case MPP_FMT_YUV420SP : {
280 downscale_buf_size = down_scale_y_virstride * 3 / 2;
281 } break;
282 case MPP_FMT_YUV422SP_10BIT :
283 case MPP_FMT_YUV422SP : {
284 downscale_buf_size = down_scale_y_virstride * 2;
285 } break;
286 case MPP_FMT_YUV444SP : {
287 downscale_buf_size = down_scale_y_virstride * 3;
288 } break;
289 default : {
290 downscale_buf_size = down_scale_y_virstride * 3 / 2;
291 } break;
292 }
293 downscale_buf_size = MPP_ALIGN(downscale_buf_size, 16);
294
295 down_scale_y_offset = MPP_ALIGN((mpp_frame_get_buf_size(frame) - downscale_buf_size), 16);
296 down_scale_uv_offset = down_scale_y_offset + down_scale_y_virstride;
297
298 com->reg9.scale_down_en = 1;
299 com->reg9.av1_fgs_en = 0;
300 paras->reg71_scl_ref_hor_virstride = down_scale_hor >> 4;
301 paras->reg72_scl_ref_raster_uv_hor_virstride = down_scale_hor >> 4;
302 if ((fmt & MPP_FRAME_FMT_MASK) == MPP_FMT_YUV444SP)
303 paras->reg72_scl_ref_raster_uv_hor_virstride = down_scale_hor >> 3;
304 paras->reg73_scl_ref_virstride = down_scale_y_virstride >> 4;
305 if (mpp_frame_get_thumbnail_en(frame) == MPP_FRAME_THUMBNAIL_MIXED) {
306 mpp_dev_set_reg_offset(dev, 133, down_scale_y_offset);
307 mpp_meta_set_s32(meta, KEY_DEC_TBN_Y_OFFSET, down_scale_y_offset);
308 mpp_meta_set_s32(meta, KEY_DEC_TBN_UV_OFFSET, down_scale_uv_offset);
309 }
310 }
311
312 #ifdef DUMP_VDPU384A_DATAS
313 RK_U32 dump_cur_frame = 0;
314 char dump_cur_dir[128];
315 char dump_cur_fname_path[512];
316
flip_string(char * str)317 MPP_RET flip_string(char *str)
318 {
319 RK_U32 len = strlen(str);
320 RK_U32 i, j;
321
322 for (i = 0, j = len - 1; i <= j; i++, j--) {
323 // swapping characters
324 char c = str[i];
325 str[i] = str[j];
326 str[j] = c;
327 }
328
329 return MPP_OK;
330 }
331
dump_data_to_file(char * fname_path,void * data,RK_U32 data_bit_size,RK_U32 line_bits,RK_U32 big_end)332 MPP_RET dump_data_to_file(char *fname_path, void *data, RK_U32 data_bit_size,
333 RK_U32 line_bits, RK_U32 big_end)
334 {
335 RK_U8 *buf_p = (RK_U8 *)data;
336 RK_U8 cur_data;
337 RK_U32 i;
338 RK_U32 loop_cnt;
339 FILE *dump_fp = NULL;
340 char line_tmp[256];
341 RK_U32 str_idx = 0;
342
343 dump_fp = fopen(fname_path, "w+");
344 if (!dump_fp) {
345 mpp_err_f("open file: %s error!\n", fname_path);
346 return MPP_NOK;
347 }
348
349 if ((data_bit_size % 4 != 0) || (line_bits % 8 != 0)) {
350 mpp_err_f("line bits not align to 4!\n");
351 return MPP_NOK;
352 }
353
354 loop_cnt = data_bit_size / 8;
355 for (i = 0; i < loop_cnt; i++) {
356 cur_data = buf_p[i];
357
358 sprintf(&line_tmp[str_idx++], "%0x", cur_data & 0xf);
359 if ((i * 8 + 4) % line_bits == 0) {
360 line_tmp[str_idx++] = '\0';
361 str_idx = 0;
362 if (!big_end)
363 flip_string(line_tmp);
364 fprintf(dump_fp, "%s\n", line_tmp);
365 }
366 sprintf(&line_tmp[str_idx++], "%0x", (cur_data >> 4) & 0xf);
367 if ((i * 8 + 8) % line_bits == 0) {
368 line_tmp[str_idx++] = '\0';
369 str_idx = 0;
370 if (!big_end)
371 flip_string(line_tmp);
372 fprintf(dump_fp, "%s\n", line_tmp);
373 }
374 }
375
376 // last line
377 if (data_bit_size % 4) {
378 cur_data = buf_p[i];
379 sprintf(&line_tmp[str_idx++], "%0x", cur_data & 0xf);
380 if ((i * 8 + 8) % line_bits == 0) {
381 line_tmp[str_idx++] = '\0';
382 str_idx = 0;
383 if (!big_end)
384 flip_string(line_tmp);
385 fprintf(dump_fp, "%s\n", line_tmp);
386 }
387 }
388 if (data_bit_size % line_bits) {
389 loop_cnt = (line_bits - (data_bit_size % line_bits)) / 4;
390 for (i = 0; i < loop_cnt; i++)
391 sprintf(&line_tmp[str_idx++], "%0x", 0);
392 line_tmp[str_idx++] = '\0';
393 str_idx = 0;
394 if (!big_end)
395 flip_string(line_tmp);
396 fprintf(dump_fp, "%s\n", line_tmp);
397 }
398
399 fclose(dump_fp);
400
401 return MPP_OK;
402 }
403 #endif
404