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 "vdpu382_com"
18
19 #include <string.h>
20 #include <stdlib.h>
21 #include "mpp_log.h"
22 #include "mpp_buffer.h"
23 #include "mpp_common.h"
24 #include "mpp_compat_impl.h"
25 #include "mpp_frame_impl.h"
26 #include "mpp_env.h"
27
28 #include "vdpu382_com.h"
29
30 static RK_U32 rcb_coeff[RCB_BUF_COUNT] = {
31 [RCB_INTRA_ROW] = 6, /* RCB_INTRA_ROW_COEF */
32 [RCB_TRANSD_ROW] = 1, /* RCB_TRANSD_ROW_COEF */
33 [RCB_TRANSD_COL] = 1, /* RCB_TRANSD_COL_COEF */
34 [RCB_STRMD_ROW] = 3, /* RCB_STRMD_ROW_COEF */
35 [RCB_INTER_ROW] = 6, /* RCB_INTER_ROW_COEF */
36 [RCB_INTER_COL] = 3, /* RCB_INTER_COL_COEF */
37 [RCB_DBLK_ROW] = 22, /* RCB_DBLK_ROW_COEF */
38 [RCB_SAO_ROW] = 6, /* RCB_SAO_ROW_COEF */
39 [RCB_FBC_ROW] = 11, /* RCB_FBC_ROW_COEF */
40 [RCB_FILT_COL] = 67, /* RCB_FILT_COL_COEF */
41 };
42
update_size_offset(Vdpu382RcbInfo * info,RK_U32 reg,RK_S32 offset,RK_S32 len,RK_S32 idx)43 static RK_S32 update_size_offset(Vdpu382RcbInfo *info, RK_U32 reg,
44 RK_S32 offset, RK_S32 len, RK_S32 idx)
45 {
46 RK_S32 buf_size = 0;
47
48 buf_size = MPP_ALIGN(len * rcb_coeff[idx], RCB_ALLINE_SIZE);
49 info[idx].reg = reg;
50 info[idx].offset = offset;
51 info[idx].size = buf_size;
52
53 return buf_size;
54 }
55
vdpu382_get_rcb_buf_size(Vdpu382RcbInfo * info,RK_S32 width,RK_S32 height)56 RK_S32 vdpu382_get_rcb_buf_size(Vdpu382RcbInfo *info, RK_S32 width, RK_S32 height)
57 {
58 RK_S32 offset = 0;
59
60 offset += update_size_offset(info, 139, offset, width, RCB_DBLK_ROW);
61 offset += update_size_offset(info, 133, offset, width, RCB_INTRA_ROW);
62 offset += update_size_offset(info, 134, offset, width, RCB_TRANSD_ROW);
63 offset += update_size_offset(info, 136, offset, width, RCB_STRMD_ROW);
64 offset += update_size_offset(info, 137, offset, width, RCB_INTER_ROW);
65 offset += update_size_offset(info, 140, offset, width, RCB_SAO_ROW);
66 offset += update_size_offset(info, 141, offset, width, RCB_FBC_ROW);
67 /* col rcb */
68 offset += update_size_offset(info, 135, offset, height, RCB_TRANSD_COL);
69 offset += update_size_offset(info, 138, offset, height, RCB_INTER_COL);
70 offset += update_size_offset(info, 142, offset, height, RCB_FILT_COL);
71
72 return offset;
73 }
74
vdpu382_setup_rcb(Vdpu382RegCommonAddr * reg,MppDev dev,MppBuffer buf,Vdpu382RcbInfo * info)75 void vdpu382_setup_rcb(Vdpu382RegCommonAddr *reg, MppDev dev, MppBuffer buf, Vdpu382RcbInfo *info)
76 {
77 RK_S32 fd = mpp_buffer_get_fd(buf);
78
79 reg->reg139_rcb_dblk_base = fd;
80 reg->reg133_rcb_intra_base = fd;
81 reg->reg134_rcb_transd_row_base = fd;
82 reg->reg136_rcb_streamd_row_base = fd;
83 reg->reg137_rcb_inter_row_base = fd;
84 reg->reg140_rcb_sao_base = fd;
85 reg->reg141_rcb_fbc_base = fd;
86 reg->reg135_rcb_transd_col_base = fd;
87 reg->reg138_rcb_inter_col_base = fd;
88 reg->reg142_rcb_filter_col_base = fd;
89
90 if (info[RCB_DBLK_ROW].offset)
91 mpp_dev_set_reg_offset(dev, 139, info[RCB_DBLK_ROW].offset);
92 if (info[RCB_INTRA_ROW].offset)
93 mpp_dev_set_reg_offset(dev, 133, info[RCB_INTRA_ROW].offset);
94 if (info[RCB_TRANSD_ROW].offset)
95 mpp_dev_set_reg_offset(dev, 134, info[RCB_TRANSD_ROW].offset);
96 if (info[RCB_STRMD_ROW].offset)
97 mpp_dev_set_reg_offset(dev, 136, info[RCB_STRMD_ROW].offset);
98 if (info[RCB_INTER_ROW].offset)
99 mpp_dev_set_reg_offset(dev, 137, info[RCB_INTER_ROW].offset);
100 if (info[RCB_SAO_ROW].offset)
101 mpp_dev_set_reg_offset(dev, 140, info[RCB_SAO_ROW].offset);
102 if (info[RCB_FBC_ROW].offset)
103 mpp_dev_set_reg_offset(dev, 141, info[RCB_FBC_ROW].offset);
104 if (info[RCB_TRANSD_COL].offset)
105 mpp_dev_set_reg_offset(dev, 135, info[RCB_TRANSD_COL].offset);
106 if (info[RCB_INTER_COL].offset)
107 mpp_dev_set_reg_offset(dev, 138, info[RCB_INTER_COL].offset);
108 if (info[RCB_FILT_COL].offset)
109 mpp_dev_set_reg_offset(dev, 142, info[RCB_FILT_COL].offset);
110 }
111
vdpu382_compare_rcb_size(const void * a,const void * b)112 RK_S32 vdpu382_compare_rcb_size(const void *a, const void *b)
113 {
114 RK_S32 val = 0;
115 Vdpu382RcbInfo *p0 = (Vdpu382RcbInfo *)a;
116 Vdpu382RcbInfo *p1 = (Vdpu382RcbInfo *)b;
117
118 val = (p0->size > p1->size) ? -1 : 1;
119
120 return val;
121 }
122
vdpu382_set_rcbinfo(MppDev dev,Vdpu382RcbInfo * rcb_info)123 RK_S32 vdpu382_set_rcbinfo(MppDev dev, Vdpu382RcbInfo *rcb_info)
124 {
125 MppDevRcbInfoCfg rcb_cfg;
126 RK_U32 i;
127 /*
128 * RCB_SET_BY_SIZE_SORT_MODE: by size sort
129 * RCB_SET_BY_PRIORITY_MODE: by priority
130 */
131 Vdpu382RcbSetMode_e set_rcb_mode = RCB_SET_BY_PRIORITY_MODE;
132 RK_U32 rcb_priority[RCB_BUF_COUNT] = {
133 RCB_DBLK_ROW,
134 RCB_INTRA_ROW,
135 RCB_SAO_ROW,
136 RCB_INTER_ROW,
137 RCB_FBC_ROW,
138 RCB_TRANSD_ROW,
139 RCB_STRMD_ROW,
140 RCB_INTER_COL,
141 RCB_FILT_COL,
142 RCB_TRANSD_COL,
143 };
144
145 switch (set_rcb_mode) {
146 case RCB_SET_BY_SIZE_SORT_MODE : {
147 Vdpu382RcbInfo info[RCB_BUF_COUNT];
148
149 memcpy(info, rcb_info, sizeof(info));
150 qsort(info, MPP_ARRAY_ELEMS(info),
151 sizeof(info[0]), vdpu382_compare_rcb_size);
152
153 for (i = 0; i < MPP_ARRAY_ELEMS(info); i++) {
154 rcb_cfg.reg_idx = info[i].reg;
155 rcb_cfg.size = info[i].size;
156 if (rcb_cfg.size > 0) {
157 mpp_dev_ioctl(dev, MPP_DEV_RCB_INFO, &rcb_cfg);
158 } else
159 break;
160 }
161 } break;
162 case RCB_SET_BY_PRIORITY_MODE : {
163 Vdpu382RcbInfo *info = rcb_info;
164 RK_U32 index = 0;
165
166 for (i = 0; i < MPP_ARRAY_ELEMS(rcb_priority); i ++) {
167 index = rcb_priority[i];
168
169 rcb_cfg.reg_idx = info[index].reg;
170 rcb_cfg.size = info[index].size;
171 if (rcb_cfg.size > 0) {
172 mpp_dev_ioctl(dev, MPP_DEV_RCB_INFO, &rcb_cfg);
173 }
174 }
175 } break;
176 default:
177 break;
178 }
179
180 return 0;
181 }
182
vdpu382_setup_statistic(Vdpu382RegCommon * com,Vdpu382RegStatistic * sta)183 void vdpu382_setup_statistic(Vdpu382RegCommon *com, Vdpu382RegStatistic *sta)
184 {
185 com->reg011.pix_range_detection_e = 1;
186
187 memset(sta, 0, sizeof(*sta));
188
189 sta->reg256.axi_perf_work_e = 1;
190 sta->reg256.axi_perf_clr_e = 1;
191 sta->reg256.axi_cnt_type = 1;
192
193 sta->reg257.addr_align_type = 1;
194
195 /* set hurry */
196 sta->reg270.axi_rd_hurry_level = 3;
197 sta->reg270.axi_wr_hurry_level = 1;
198 sta->reg270.axi_wr_qos = 1;
199 sta->reg270.axi_rd_qos = 3;
200 sta->reg270.bus2mc_buffer_qos_level = 255;
201 sta->reg271_wr_wait_cycle_qos = 0;
202 }
203
vdpu382_afbc_align_calc(MppBufSlots slots,MppFrame frame,RK_U32 expand)204 void vdpu382_afbc_align_calc(MppBufSlots slots, MppFrame frame, RK_U32 expand)
205 {
206 RK_U32 ver_stride = 0;
207 RK_U32 img_height = mpp_frame_get_height(frame);
208 RK_U32 img_width = mpp_frame_get_width(frame);
209 RK_U32 hdr_stride = (*compat_ext_fbc_hdr_256_odd) ?
210 (MPP_ALIGN(img_width, 256) | 256) :
211 (MPP_ALIGN(img_width, 64));
212
213 mpp_slots_set_prop(slots, SLOTS_HOR_ALIGN, mpp_align_64);
214 mpp_slots_set_prop(slots, SLOTS_VER_ALIGN, mpp_align_16);
215
216 mpp_frame_set_fbc_hdr_stride(frame, hdr_stride);
217
218 ver_stride = mpp_align_16(img_height);
219 if (*compat_ext_fbc_buf_size) {
220 ver_stride += expand;
221 }
222 mpp_frame_set_ver_stride(frame, ver_stride);
223 }
224
vdpu382_setup_down_scale(MppFrame frame,MppDev dev,Vdpu382RegCommon * com)225 void vdpu382_setup_down_scale(MppFrame frame, MppDev dev, Vdpu382RegCommon *com)
226 {
227 RK_U32 ver_stride = mpp_frame_get_ver_stride(frame);
228 RK_U32 hor_stride = mpp_frame_get_hor_stride(frame);
229 RK_U32 down_scale_ver = MPP_ALIGN(ver_stride >> 1, 16);
230 RK_U32 down_scale_hor = MPP_ALIGN(hor_stride >> 1, 16);
231 MppFrameFormat fmt = mpp_frame_get_fmt(frame);
232 MppMeta meta = mpp_frame_get_meta(frame);
233 RK_U32 down_scale_y_offset = 0;
234 RK_U32 down_scale_uv_offset = 0;
235
236 if (MPP_FRAME_FMT_IS_FBC(fmt))
237 down_scale_y_offset = mpp_frame_get_fbc_size(frame);
238 else
239 down_scale_y_offset = ver_stride * hor_stride * 3 / 2;
240
241 com->reg012.scale_down_en = 1;
242 com->reg029.scale_down_y_wratio = 2;
243 com->reg029.scale_down_y_hratio = 2;
244 com->reg029.scale_down_c_wratio = 2;
245 com->reg029.scale_down_c_hratio = 2;
246 com->reg030.y_scale_down_hor_stride = MPP_ALIGN(down_scale_hor, 16) >> 4;
247 com->reg031.uv_scale_down_hor_stride = MPP_ALIGN(down_scale_hor, 16) >> 4;
248
249 down_scale_y_offset = MPP_ALIGN(down_scale_y_offset, 16);
250 mpp_dev_set_reg_offset(dev, 198, down_scale_y_offset);
251 mpp_meta_set_s32(meta, KEY_DEC_TBN_Y_OFFSET, down_scale_y_offset);
252
253 down_scale_uv_offset = down_scale_y_offset + down_scale_hor * down_scale_ver;
254 mpp_dev_set_reg_offset(dev, 199, down_scale_uv_offset);
255 mpp_meta_set_s32(meta, KEY_DEC_TBN_UV_OFFSET, down_scale_uv_offset);
256 }
257
vdpu382_get_colmv_size(RK_U32 width,RK_U32 height,RK_U32 ctu_size,RK_U32 colmv_bytes,RK_U32 colmv_size,RK_U32 compress)258 RK_U32 vdpu382_get_colmv_size(RK_U32 width, RK_U32 height, RK_U32 ctu_size,
259 RK_U32 colmv_bytes, RK_U32 colmv_size, RK_U32 compress)
260 {
261 RK_U32 colmv_total_size;
262
263 if (compress) {
264 RK_U32 segment_w = (64 * colmv_size * colmv_size) / ctu_size;
265 RK_U32 segment_h = ctu_size;
266 RK_U32 seg_cnt_w = MPP_ALIGN(width, segment_w) / segment_w;
267 RK_U32 seg_cnt_h = MPP_ALIGN(height, segment_h) / segment_h;
268 RK_U32 seg_head_size = MPP_ALIGN(seg_cnt_w, 16) * seg_cnt_h;
269 RK_U32 seg_payload_size = seg_cnt_w * seg_cnt_h * 64 * colmv_bytes;
270
271 colmv_total_size = seg_head_size + seg_payload_size;
272 } else {
273 RK_U32 colmv_block_size_w = MPP_ALIGN(width, 64) / colmv_size;
274 RK_U32 colmv_block_size_h = MPP_ALIGN(height, 64) / colmv_size;
275
276 colmv_total_size = colmv_block_size_w * colmv_block_size_h * colmv_bytes;
277 }
278
279 return MPP_ALIGN(colmv_total_size, 128);
280 }
281