File: | dev/pci/drm/amd/display/dc/dsc/dc_dsc.c |
Warning: | line 368, column 6 Branch condition evaluates to a garbage value |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* | |||
2 | * Copyright 2019 Advanced Micro Devices, Inc. | |||
3 | * | |||
4 | * Permission is hereby granted, free of charge, to any person obtaining a | |||
5 | * copy of this software and associated documentation files (the "Software"), | |||
6 | * to deal in the Software without restriction, including without limitation | |||
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | |||
8 | * and/or sell copies of the Software, and to permit persons to whom the | |||
9 | * Software is furnished to do so, subject to the following conditions: | |||
10 | * | |||
11 | * The above copyright notice and this permission notice shall be included in | |||
12 | * all copies or substantial portions of the Software. | |||
13 | * | |||
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |||
17 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | |||
18 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | |||
19 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | |||
20 | * OTHER DEALINGS IN THE SOFTWARE. | |||
21 | * | |||
22 | * Author: AMD | |||
23 | */ | |||
24 | ||||
25 | #include <drm/drm_dsc.h> | |||
26 | #include "dc_hw_types.h" | |||
27 | #include "dsc.h" | |||
28 | #include <drm/drm_dp_helper.h> | |||
29 | #include "dc.h" | |||
30 | #include "rc_calc.h" | |||
31 | ||||
32 | /* This module's internal functions */ | |||
33 | ||||
34 | /* default DSC policy target bitrate limit is 16bpp */ | |||
35 | static uint32_t dsc_policy_max_target_bpp_limit = 16; | |||
36 | ||||
37 | /* default DSC policy enables DSC only when needed */ | |||
38 | static bool_Bool dsc_policy_enable_dsc_when_not_needed; | |||
39 | ||||
40 | static uint32_t dc_dsc_bandwidth_in_kbps_from_timing( | |||
41 | const struct dc_crtc_timing *timing) | |||
42 | { | |||
43 | uint32_t bits_per_channel = 0; | |||
44 | uint32_t kbps; | |||
45 | ||||
46 | if (timing->flags.DSC) { | |||
47 | kbps = (timing->pix_clk_100hz * timing->dsc_cfg.bits_per_pixel); | |||
48 | kbps = kbps / 160 + ((kbps % 160) ? 1 : 0); | |||
49 | return kbps; | |||
50 | } | |||
51 | ||||
52 | switch (timing->display_color_depth) { | |||
53 | case COLOR_DEPTH_666: | |||
54 | bits_per_channel = 6; | |||
55 | break; | |||
56 | case COLOR_DEPTH_888: | |||
57 | bits_per_channel = 8; | |||
58 | break; | |||
59 | case COLOR_DEPTH_101010: | |||
60 | bits_per_channel = 10; | |||
61 | break; | |||
62 | case COLOR_DEPTH_121212: | |||
63 | bits_per_channel = 12; | |||
64 | break; | |||
65 | case COLOR_DEPTH_141414: | |||
66 | bits_per_channel = 14; | |||
67 | break; | |||
68 | case COLOR_DEPTH_161616: | |||
69 | bits_per_channel = 16; | |||
70 | break; | |||
71 | default: | |||
72 | break; | |||
73 | } | |||
74 | ||||
75 | ASSERT(bits_per_channel != 0)do { if (({ static int __warned; int __ret = !!(!(bits_per_channel != 0)); if (__ret && !__warned) { printf("WARNING %s failed at %s:%d\n" , "!(bits_per_channel != 0)", "/usr/src/sys/dev/pci/drm/amd/display/dc/dsc/dc_dsc.c" , 75); __warned = 1; } __builtin_expect(!!(__ret), 0); })) do {} while (0); } while (0); | |||
76 | ||||
77 | kbps = timing->pix_clk_100hz / 10; | |||
78 | kbps *= bits_per_channel; | |||
79 | ||||
80 | if (timing->flags.Y_ONLY != 1) { | |||
81 | /*Only YOnly make reduce bandwidth by 1/3 compares to RGB*/ | |||
82 | kbps *= 3; | |||
83 | if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR420) | |||
84 | kbps /= 2; | |||
85 | else if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR422) | |||
86 | kbps = kbps * 2 / 3; | |||
87 | } | |||
88 | ||||
89 | return kbps; | |||
90 | ||||
91 | } | |||
92 | ||||
93 | static bool_Bool dsc_buff_block_size_from_dpcd(int dpcd_buff_block_size, int *buff_block_size) | |||
94 | { | |||
95 | ||||
96 | switch (dpcd_buff_block_size) { | |||
97 | case DP_DSC_RC_BUF_BLK_SIZE_10x0: | |||
98 | *buff_block_size = 1024; | |||
99 | break; | |||
100 | case DP_DSC_RC_BUF_BLK_SIZE_40x1: | |||
101 | *buff_block_size = 4 * 1024; | |||
102 | break; | |||
103 | case DP_DSC_RC_BUF_BLK_SIZE_160x2: | |||
104 | *buff_block_size = 16 * 1024; | |||
105 | break; | |||
106 | case DP_DSC_RC_BUF_BLK_SIZE_640x3: | |||
107 | *buff_block_size = 64 * 1024; | |||
108 | break; | |||
109 | default: { | |||
110 | dm_error("%s: DPCD DSC buffer size not recognized.\n", __func__)__drm_err("%s: DPCD DSC buffer size not recognized.\n", __func__ ); | |||
111 | return false0; | |||
112 | } | |||
113 | } | |||
114 | ||||
115 | return true1; | |||
116 | } | |||
117 | ||||
118 | ||||
119 | static bool_Bool dsc_line_buff_depth_from_dpcd(int dpcd_line_buff_bit_depth, int *line_buff_bit_depth) | |||
120 | { | |||
121 | if (0 <= dpcd_line_buff_bit_depth && dpcd_line_buff_bit_depth <= 7) | |||
122 | *line_buff_bit_depth = dpcd_line_buff_bit_depth + 9; | |||
123 | else if (dpcd_line_buff_bit_depth == 8) | |||
124 | *line_buff_bit_depth = 8; | |||
125 | else { | |||
126 | dm_error("%s: DPCD DSC buffer depth not recognized.\n", __func__)__drm_err("%s: DPCD DSC buffer depth not recognized.\n", __func__ ); | |||
127 | return false0; | |||
128 | } | |||
129 | ||||
130 | return true1; | |||
131 | } | |||
132 | ||||
133 | ||||
134 | static bool_Bool dsc_throughput_from_dpcd(int dpcd_throughput, int *throughput) | |||
135 | { | |||
136 | switch (dpcd_throughput) { | |||
137 | case DP_DSC_THROUGHPUT_MODE_0_UNSUPPORTED0: | |||
138 | *throughput = 0; | |||
139 | break; | |||
140 | case DP_DSC_THROUGHPUT_MODE_0_170(15 << 0): | |||
141 | *throughput = 170; | |||
142 | break; | |||
143 | case DP_DSC_THROUGHPUT_MODE_0_340(1 << 0): | |||
144 | *throughput = 340; | |||
145 | break; | |||
146 | case DP_DSC_THROUGHPUT_MODE_0_400(2 << 0): | |||
147 | *throughput = 400; | |||
148 | break; | |||
149 | case DP_DSC_THROUGHPUT_MODE_0_450(3 << 0): | |||
150 | *throughput = 450; | |||
151 | break; | |||
152 | case DP_DSC_THROUGHPUT_MODE_0_500(4 << 0): | |||
153 | *throughput = 500; | |||
154 | break; | |||
155 | case DP_DSC_THROUGHPUT_MODE_0_550(5 << 0): | |||
156 | *throughput = 550; | |||
157 | break; | |||
158 | case DP_DSC_THROUGHPUT_MODE_0_600(6 << 0): | |||
159 | *throughput = 600; | |||
160 | break; | |||
161 | case DP_DSC_THROUGHPUT_MODE_0_650(7 << 0): | |||
162 | *throughput = 650; | |||
163 | break; | |||
164 | case DP_DSC_THROUGHPUT_MODE_0_700(8 << 0): | |||
165 | *throughput = 700; | |||
166 | break; | |||
167 | case DP_DSC_THROUGHPUT_MODE_0_750(9 << 0): | |||
168 | *throughput = 750; | |||
169 | break; | |||
170 | case DP_DSC_THROUGHPUT_MODE_0_800(10 << 0): | |||
171 | *throughput = 800; | |||
172 | break; | |||
173 | case DP_DSC_THROUGHPUT_MODE_0_850(11 << 0): | |||
174 | *throughput = 850; | |||
175 | break; | |||
176 | case DP_DSC_THROUGHPUT_MODE_0_900(12 << 0): | |||
177 | *throughput = 900; | |||
178 | break; | |||
179 | case DP_DSC_THROUGHPUT_MODE_0_950(13 << 0): | |||
180 | *throughput = 950; | |||
181 | break; | |||
182 | case DP_DSC_THROUGHPUT_MODE_0_1000(14 << 0): | |||
183 | *throughput = 1000; | |||
184 | break; | |||
185 | default: { | |||
186 | dm_error("%s: DPCD DSC throughput mode not recognized.\n", __func__)__drm_err("%s: DPCD DSC throughput mode not recognized.\n", __func__ ); | |||
187 | return false0; | |||
188 | } | |||
189 | } | |||
190 | ||||
191 | return true1; | |||
192 | } | |||
193 | ||||
194 | ||||
195 | static bool_Bool dsc_bpp_increment_div_from_dpcd(uint8_t bpp_increment_dpcd, uint32_t *bpp_increment_div) | |||
196 | { | |||
197 | // Mask bpp increment dpcd field to avoid reading other fields | |||
198 | bpp_increment_dpcd &= 0x7; | |||
199 | ||||
200 | switch (bpp_increment_dpcd) { | |||
201 | case 0: | |||
202 | *bpp_increment_div = 16; | |||
203 | break; | |||
204 | case 1: | |||
205 | *bpp_increment_div = 8; | |||
206 | break; | |||
207 | case 2: | |||
208 | *bpp_increment_div = 4; | |||
209 | break; | |||
210 | case 3: | |||
211 | *bpp_increment_div = 2; | |||
212 | break; | |||
213 | case 4: | |||
214 | *bpp_increment_div = 1; | |||
215 | break; | |||
216 | default: { | |||
217 | dm_error("%s: DPCD DSC bits-per-pixel increment not recognized.\n", __func__)__drm_err("%s: DPCD DSC bits-per-pixel increment not recognized.\n" , __func__); | |||
218 | return false0; | |||
219 | } | |||
220 | } | |||
221 | ||||
222 | return true1; | |||
223 | } | |||
224 | ||||
225 | static void get_dsc_enc_caps( | |||
226 | const struct display_stream_compressor *dsc, | |||
227 | struct dsc_enc_caps *dsc_enc_caps, | |||
228 | int pixel_clock_100Hz) | |||
229 | { | |||
230 | // This is a static HW query, so we can use any DSC | |||
231 | ||||
232 | memset(dsc_enc_caps, 0, sizeof(struct dsc_enc_caps))__builtin_memset((dsc_enc_caps), (0), (sizeof(struct dsc_enc_caps ))); | |||
233 | if (dsc) { | |||
234 | if (!dsc->ctx->dc->debug.disable_dsc) | |||
235 | dsc->funcs->dsc_get_enc_caps(dsc_enc_caps, pixel_clock_100Hz); | |||
236 | if (dsc->ctx->dc->debug.native422_support) | |||
237 | dsc_enc_caps->color_formats.bits.YCBCR_NATIVE_422 = 1; | |||
238 | } | |||
239 | } | |||
240 | ||||
241 | /* Returns 'false' if no intersection was found for at least one capablity. | |||
242 | * It also implicitly validates some sink caps against invalid value of zero. | |||
243 | */ | |||
244 | static bool_Bool intersect_dsc_caps( | |||
245 | const struct dsc_dec_dpcd_caps *dsc_sink_caps, | |||
246 | const struct dsc_enc_caps *dsc_enc_caps, | |||
247 | enum dc_pixel_encoding pixel_encoding, | |||
248 | struct dsc_enc_caps *dsc_common_caps) | |||
249 | { | |||
250 | int32_t max_slices; | |||
251 | int32_t total_sink_throughput; | |||
252 | ||||
253 | memset(dsc_common_caps, 0, sizeof(struct dsc_enc_caps))__builtin_memset((dsc_common_caps), (0), (sizeof(struct dsc_enc_caps ))); | |||
254 | ||||
255 | dsc_common_caps->dsc_version = min(dsc_sink_caps->dsc_version, dsc_enc_caps->dsc_version)(((dsc_sink_caps->dsc_version)<(dsc_enc_caps->dsc_version ))?(dsc_sink_caps->dsc_version):(dsc_enc_caps->dsc_version )); | |||
256 | if (!dsc_common_caps->dsc_version) | |||
257 | return false0; | |||
258 | ||||
259 | dsc_common_caps->slice_caps.bits.NUM_SLICES_1 = dsc_sink_caps->slice_caps1.bits.NUM_SLICES_1 && dsc_enc_caps->slice_caps.bits.NUM_SLICES_1; | |||
260 | dsc_common_caps->slice_caps.bits.NUM_SLICES_2 = dsc_sink_caps->slice_caps1.bits.NUM_SLICES_2 && dsc_enc_caps->slice_caps.bits.NUM_SLICES_2; | |||
261 | dsc_common_caps->slice_caps.bits.NUM_SLICES_4 = dsc_sink_caps->slice_caps1.bits.NUM_SLICES_4 && dsc_enc_caps->slice_caps.bits.NUM_SLICES_4; | |||
262 | dsc_common_caps->slice_caps.bits.NUM_SLICES_8 = dsc_sink_caps->slice_caps1.bits.NUM_SLICES_8 && dsc_enc_caps->slice_caps.bits.NUM_SLICES_8; | |||
263 | if (!dsc_common_caps->slice_caps.raw) | |||
264 | return false0; | |||
265 | ||||
266 | dsc_common_caps->lb_bit_depth = min(dsc_sink_caps->lb_bit_depth, dsc_enc_caps->lb_bit_depth)(((dsc_sink_caps->lb_bit_depth)<(dsc_enc_caps->lb_bit_depth ))?(dsc_sink_caps->lb_bit_depth):(dsc_enc_caps->lb_bit_depth )); | |||
267 | if (!dsc_common_caps->lb_bit_depth) | |||
268 | return false0; | |||
269 | ||||
270 | dsc_common_caps->is_block_pred_supported = dsc_sink_caps->is_block_pred_supported && dsc_enc_caps->is_block_pred_supported; | |||
271 | ||||
272 | dsc_common_caps->color_formats.raw = dsc_sink_caps->color_formats.raw & dsc_enc_caps->color_formats.raw; | |||
273 | if (!dsc_common_caps->color_formats.raw) | |||
274 | return false0; | |||
275 | ||||
276 | dsc_common_caps->color_depth.raw = dsc_sink_caps->color_depth.raw & dsc_enc_caps->color_depth.raw; | |||
277 | if (!dsc_common_caps->color_depth.raw) | |||
278 | return false0; | |||
279 | ||||
280 | max_slices = 0; | |||
281 | if (dsc_common_caps->slice_caps.bits.NUM_SLICES_1) | |||
282 | max_slices = 1; | |||
283 | ||||
284 | if (dsc_common_caps->slice_caps.bits.NUM_SLICES_2) | |||
285 | max_slices = 2; | |||
286 | ||||
287 | if (dsc_common_caps->slice_caps.bits.NUM_SLICES_4) | |||
288 | max_slices = 4; | |||
289 | ||||
290 | total_sink_throughput = max_slices * dsc_sink_caps->throughput_mode_0_mps; | |||
291 | if (pixel_encoding == PIXEL_ENCODING_YCBCR422 || pixel_encoding == PIXEL_ENCODING_YCBCR420) | |||
292 | total_sink_throughput = max_slices * dsc_sink_caps->throughput_mode_1_mps; | |||
293 | ||||
294 | dsc_common_caps->max_total_throughput_mps = min(total_sink_throughput, dsc_enc_caps->max_total_throughput_mps)(((total_sink_throughput)<(dsc_enc_caps->max_total_throughput_mps ))?(total_sink_throughput):(dsc_enc_caps->max_total_throughput_mps )); | |||
295 | ||||
296 | dsc_common_caps->max_slice_width = min(dsc_sink_caps->max_slice_width, dsc_enc_caps->max_slice_width)(((dsc_sink_caps->max_slice_width)<(dsc_enc_caps->max_slice_width ))?(dsc_sink_caps->max_slice_width):(dsc_enc_caps->max_slice_width )); | |||
297 | if (!dsc_common_caps->max_slice_width) | |||
298 | return false0; | |||
299 | ||||
300 | dsc_common_caps->bpp_increment_div = min(dsc_sink_caps->bpp_increment_div, dsc_enc_caps->bpp_increment_div)(((dsc_sink_caps->bpp_increment_div)<(dsc_enc_caps-> bpp_increment_div))?(dsc_sink_caps->bpp_increment_div):(dsc_enc_caps ->bpp_increment_div)); | |||
301 | ||||
302 | // TODO DSC: Remove this workaround for N422 and 420 once it's fixed, or move it to get_dsc_encoder_caps() | |||
303 | if (pixel_encoding == PIXEL_ENCODING_YCBCR422 || pixel_encoding == PIXEL_ENCODING_YCBCR420) | |||
304 | dsc_common_caps->bpp_increment_div = min(dsc_common_caps->bpp_increment_div, (uint32_t)8)(((dsc_common_caps->bpp_increment_div)<((uint32_t)8))?( dsc_common_caps->bpp_increment_div):((uint32_t)8)); | |||
305 | ||||
306 | return true1; | |||
307 | } | |||
308 | ||||
309 | static inline uint32_t dsc_div_by_10_round_up(uint32_t value) | |||
310 | { | |||
311 | return (value + 9) / 10; | |||
312 | } | |||
313 | ||||
314 | /* Get DSC bandwidth range based on [min_bpp, max_bpp] target bitrate range, and timing's pixel clock | |||
315 | * and uncompressed bandwidth. | |||
316 | */ | |||
317 | static void get_dsc_bandwidth_range( | |||
318 | const uint32_t min_bpp, | |||
319 | const uint32_t max_bpp, | |||
320 | const struct dsc_enc_caps *dsc_caps, | |||
321 | const struct dc_crtc_timing *timing, | |||
322 | struct dc_dsc_bw_range *range) | |||
323 | { | |||
324 | /* native stream bandwidth */ | |||
325 | range->stream_kbps = dc_dsc_bandwidth_in_kbps_from_timing(timing); | |||
326 | ||||
327 | /* max dsc target bpp */ | |||
328 | range->max_kbps = dsc_div_by_10_round_up(max_bpp * timing->pix_clk_100hz); | |||
329 | range->max_target_bpp_x16 = max_bpp * 16; | |||
330 | if (range->max_kbps > range->stream_kbps) { | |||
331 | /* max dsc target bpp is capped to native bandwidth */ | |||
332 | range->max_kbps = range->stream_kbps; | |||
333 | range->max_target_bpp_x16 = calc_dsc_bpp_x16(range->stream_kbps, timing->pix_clk_100hz, dsc_caps->bpp_increment_div); | |||
334 | } | |||
335 | ||||
336 | /* min dsc target bpp */ | |||
337 | range->min_kbps = dsc_div_by_10_round_up(min_bpp * timing->pix_clk_100hz); | |||
338 | range->min_target_bpp_x16 = min_bpp * 16; | |||
339 | if (range->min_kbps > range->max_kbps) { | |||
340 | /* min dsc target bpp is capped to max dsc bandwidth*/ | |||
341 | range->min_kbps = range->max_kbps; | |||
342 | range->min_target_bpp_x16 = range->max_target_bpp_x16; | |||
343 | } | |||
344 | } | |||
345 | ||||
346 | ||||
347 | /* Decides if DSC should be used and calculates target bpp if it should, applying DSC policy. | |||
348 | * | |||
349 | * Returns: | |||
350 | * - 'true' if DSC was required by policy and was successfully applied | |||
351 | * - 'false' if DSC was not necessary (e.g. if uncompressed stream fits 'target_bandwidth_kbps'), | |||
352 | * or if it couldn't be applied based on DSC policy. | |||
353 | */ | |||
354 | static bool_Bool decide_dsc_target_bpp_x16( | |||
355 | const struct dc_dsc_policy *policy, | |||
356 | const struct dsc_enc_caps *dsc_common_caps, | |||
357 | const int target_bandwidth_kbps, | |||
358 | const struct dc_crtc_timing *timing, | |||
359 | int *target_bpp_x16) | |||
360 | { | |||
361 | bool_Bool should_use_dsc = false0; | |||
362 | struct dc_dsc_bw_range range; | |||
363 | ||||
364 | memset(&range, 0, sizeof(range))__builtin_memset((&range), (0), (sizeof(range))); | |||
365 | ||||
366 | get_dsc_bandwidth_range(policy->min_target_bpp, policy->max_target_bpp, | |||
367 | dsc_common_caps, timing, &range); | |||
368 | if (!policy->enable_dsc_when_not_needed && target_bandwidth_kbps >= range.stream_kbps) { | |||
| ||||
369 | /* enough bandwidth without dsc */ | |||
370 | *target_bpp_x16 = 0; | |||
371 | should_use_dsc = false0; | |||
372 | } else if (target_bandwidth_kbps >= range.max_kbps) { | |||
373 | /* use max target bpp allowed */ | |||
374 | *target_bpp_x16 = range.max_target_bpp_x16; | |||
375 | should_use_dsc = true1; | |||
376 | } else if (target_bandwidth_kbps >= range.min_kbps) { | |||
377 | /* use target bpp that can take entire target bandwidth */ | |||
378 | *target_bpp_x16 = calc_dsc_bpp_x16(target_bandwidth_kbps, timing->pix_clk_100hz, dsc_common_caps->bpp_increment_div); | |||
379 | should_use_dsc = true1; | |||
380 | } else { | |||
381 | /* not enough bandwidth to fulfill minimum requirement */ | |||
382 | *target_bpp_x16 = 0; | |||
383 | should_use_dsc = false0; | |||
384 | } | |||
385 | ||||
386 | return should_use_dsc; | |||
387 | } | |||
388 | ||||
389 | #define MIN_AVAILABLE_SLICES_SIZE4 4 | |||
390 | ||||
391 | static int get_available_dsc_slices(union dsc_enc_slice_caps slice_caps, int *available_slices) | |||
392 | { | |||
393 | int idx = 0; | |||
394 | ||||
395 | memset(available_slices, -1, MIN_AVAILABLE_SLICES_SIZE)__builtin_memset((available_slices), (-1), (4)); | |||
396 | ||||
397 | if (slice_caps.bits.NUM_SLICES_1) | |||
398 | available_slices[idx++] = 1; | |||
399 | ||||
400 | if (slice_caps.bits.NUM_SLICES_2) | |||
401 | available_slices[idx++] = 2; | |||
402 | ||||
403 | if (slice_caps.bits.NUM_SLICES_4) | |||
404 | available_slices[idx++] = 4; | |||
405 | ||||
406 | if (slice_caps.bits.NUM_SLICES_8) | |||
407 | available_slices[idx++] = 8; | |||
408 | ||||
409 | return idx; | |||
410 | } | |||
411 | ||||
412 | ||||
413 | static int get_max_dsc_slices(union dsc_enc_slice_caps slice_caps) | |||
414 | { | |||
415 | int max_slices = 0; | |||
416 | int available_slices[MIN_AVAILABLE_SLICES_SIZE4]; | |||
417 | int end_idx = get_available_dsc_slices(slice_caps, &available_slices[0]); | |||
418 | ||||
419 | if (end_idx > 0) | |||
420 | max_slices = available_slices[end_idx - 1]; | |||
421 | ||||
422 | return max_slices; | |||
423 | } | |||
424 | ||||
425 | ||||
426 | // Increment sice number in available sice numbers stops if possible, or just increment if not | |||
427 | static int inc_num_slices(union dsc_enc_slice_caps slice_caps, int num_slices) | |||
428 | { | |||
429 | // Get next bigger num slices available in common caps | |||
430 | int available_slices[MIN_AVAILABLE_SLICES_SIZE4]; | |||
431 | int end_idx; | |||
432 | int i; | |||
433 | int new_num_slices = num_slices; | |||
434 | ||||
435 | end_idx = get_available_dsc_slices(slice_caps, &available_slices[0]); | |||
436 | if (end_idx == 0) { | |||
437 | // No available slices found | |||
438 | new_num_slices++; | |||
439 | return new_num_slices; | |||
440 | } | |||
441 | ||||
442 | // Numbers of slices found - get the next bigger number | |||
443 | for (i = 0; i < end_idx; i++) { | |||
444 | if (new_num_slices < available_slices[i]) { | |||
445 | new_num_slices = available_slices[i]; | |||
446 | break; | |||
447 | } | |||
448 | } | |||
449 | ||||
450 | if (new_num_slices == num_slices) // No biger number of slices found | |||
451 | new_num_slices++; | |||
452 | ||||
453 | return new_num_slices; | |||
454 | } | |||
455 | ||||
456 | ||||
457 | // Decrement sice number in available sice numbers stops if possible, or just decrement if not. Stop at zero. | |||
458 | static int dec_num_slices(union dsc_enc_slice_caps slice_caps, int num_slices) | |||
459 | { | |||
460 | // Get next bigger num slices available in common caps | |||
461 | int available_slices[MIN_AVAILABLE_SLICES_SIZE4]; | |||
462 | int end_idx; | |||
463 | int i; | |||
464 | int new_num_slices = num_slices; | |||
465 | ||||
466 | end_idx = get_available_dsc_slices(slice_caps, &available_slices[0]); | |||
467 | if (end_idx == 0 && new_num_slices > 0) { | |||
468 | // No numbers of slices found | |||
469 | new_num_slices++; | |||
470 | return new_num_slices; | |||
471 | } | |||
472 | ||||
473 | // Numbers of slices found - get the next smaller number | |||
474 | for (i = end_idx - 1; i >= 0; i--) { | |||
475 | if (new_num_slices > available_slices[i]) { | |||
476 | new_num_slices = available_slices[i]; | |||
477 | break; | |||
478 | } | |||
479 | } | |||
480 | ||||
481 | if (new_num_slices == num_slices) { | |||
482 | // No smaller number of slices found | |||
483 | new_num_slices--; | |||
484 | if (new_num_slices < 0) | |||
485 | new_num_slices = 0; | |||
486 | } | |||
487 | ||||
488 | return new_num_slices; | |||
489 | } | |||
490 | ||||
491 | ||||
492 | // Choose next bigger number of slices if the requested number of slices is not available | |||
493 | static int fit_num_slices_up(union dsc_enc_slice_caps slice_caps, int num_slices) | |||
494 | { | |||
495 | // Get next bigger num slices available in common caps | |||
496 | int available_slices[MIN_AVAILABLE_SLICES_SIZE4]; | |||
497 | int end_idx; | |||
498 | int i; | |||
499 | int new_num_slices = num_slices; | |||
500 | ||||
501 | end_idx = get_available_dsc_slices(slice_caps, &available_slices[0]); | |||
502 | if (end_idx == 0) { | |||
503 | // No available slices found | |||
504 | new_num_slices++; | |||
505 | return new_num_slices; | |||
506 | } | |||
507 | ||||
508 | // Numbers of slices found - get the equal or next bigger number | |||
509 | for (i = 0; i < end_idx; i++) { | |||
510 | if (new_num_slices <= available_slices[i]) { | |||
511 | new_num_slices = available_slices[i]; | |||
512 | break; | |||
513 | } | |||
514 | } | |||
515 | ||||
516 | return new_num_slices; | |||
517 | } | |||
518 | ||||
519 | ||||
520 | /* Attempts to set DSC configuration for the stream, applying DSC policy. | |||
521 | * Returns 'true' if successful or 'false' if not. | |||
522 | * | |||
523 | * Parameters: | |||
524 | * | |||
525 | * dsc_sink_caps - DSC sink decoder capabilities (from DPCD) | |||
526 | * | |||
527 | * dsc_enc_caps - DSC encoder capabilities | |||
528 | * | |||
529 | * target_bandwidth_kbps - Target bandwidth to fit the stream into. | |||
530 | * If 0, do not calculate target bpp. | |||
531 | * | |||
532 | * timing - The stream timing to fit into 'target_bandwidth_kbps' or apply | |||
533 | * maximum compression to, if 'target_badwidth == 0' | |||
534 | * | |||
535 | * dsc_cfg - DSC configuration to use if it was possible to come up with | |||
536 | * one for the given inputs. | |||
537 | * The target bitrate after DSC can be calculated by multiplying | |||
538 | * dsc_cfg.bits_per_pixel (in U6.4 format) by pixel rate, e.g. | |||
539 | * | |||
540 | * dsc_stream_bitrate_kbps = (int)ceil(timing->pix_clk_khz * dsc_cfg.bits_per_pixel / 16.0); | |||
541 | */ | |||
542 | static bool_Bool setup_dsc_config( | |||
543 | const struct dsc_dec_dpcd_caps *dsc_sink_caps, | |||
544 | const struct dsc_enc_caps *dsc_enc_caps, | |||
545 | int target_bandwidth_kbps, | |||
546 | const struct dc_crtc_timing *timing, | |||
547 | int min_slice_height_override, | |||
548 | struct dc_dsc_config *dsc_cfg) | |||
549 | { | |||
550 | struct dsc_enc_caps dsc_common_caps; | |||
551 | int max_slices_h; | |||
552 | int min_slices_h; | |||
553 | int num_slices_h; | |||
554 | int pic_width; | |||
555 | int slice_width; | |||
556 | int target_bpp; | |||
557 | int sink_per_slice_throughput_mps; | |||
558 | int branch_max_throughput_mps = 0; | |||
559 | bool_Bool is_dsc_possible = false0; | |||
560 | int pic_height; | |||
561 | int slice_height; | |||
562 | struct dc_dsc_policy policy; | |||
563 | ||||
564 | memset(dsc_cfg, 0, sizeof(struct dc_dsc_config))__builtin_memset((dsc_cfg), (0), (sizeof(struct dc_dsc_config ))); | |||
565 | ||||
566 | dc_dsc_get_policy_for_timing(timing, &policy); | |||
| ||||
567 | pic_width = timing->h_addressable + timing->h_border_left + timing->h_border_right; | |||
568 | pic_height = timing->v_addressable + timing->v_border_top + timing->v_border_bottom; | |||
569 | ||||
570 | if (!dsc_sink_caps->is_dsc_supported) | |||
571 | goto done; | |||
572 | ||||
573 | if (dsc_sink_caps->branch_max_line_width && dsc_sink_caps->branch_max_line_width < pic_width) | |||
574 | goto done; | |||
575 | ||||
576 | // Intersect decoder with encoder DSC caps and validate DSC settings | |||
577 | is_dsc_possible = intersect_dsc_caps(dsc_sink_caps, dsc_enc_caps, timing->pixel_encoding, &dsc_common_caps); | |||
578 | if (!is_dsc_possible
| |||
579 | goto done; | |||
580 | ||||
581 | if (target_bandwidth_kbps > 0) { | |||
582 | is_dsc_possible = decide_dsc_target_bpp_x16( | |||
583 | &policy, | |||
584 | &dsc_common_caps, | |||
585 | target_bandwidth_kbps, | |||
586 | timing, | |||
587 | &target_bpp); | |||
588 | dsc_cfg->bits_per_pixel = target_bpp; | |||
589 | } | |||
590 | if (!is_dsc_possible) | |||
591 | goto done; | |||
592 | ||||
593 | sink_per_slice_throughput_mps = 0; | |||
594 | ||||
595 | // Validate available DSC settings against the mode timing | |||
596 | ||||
597 | // Validate color format (and pick up the throughput values) | |||
598 | dsc_cfg->ycbcr422_simple = false0; | |||
599 | switch (timing->pixel_encoding) { | |||
600 | case PIXEL_ENCODING_RGB: | |||
601 | is_dsc_possible = (bool_Bool)dsc_common_caps.color_formats.bits.RGB; | |||
602 | sink_per_slice_throughput_mps = dsc_sink_caps->throughput_mode_0_mps; | |||
603 | branch_max_throughput_mps = dsc_sink_caps->branch_overall_throughput_0_mps; | |||
604 | break; | |||
605 | case PIXEL_ENCODING_YCBCR444: | |||
606 | is_dsc_possible = (bool_Bool)dsc_common_caps.color_formats.bits.YCBCR_444; | |||
607 | sink_per_slice_throughput_mps = dsc_sink_caps->throughput_mode_0_mps; | |||
608 | branch_max_throughput_mps = dsc_sink_caps->branch_overall_throughput_0_mps; | |||
609 | break; | |||
610 | case PIXEL_ENCODING_YCBCR422: | |||
611 | is_dsc_possible = (bool_Bool)dsc_common_caps.color_formats.bits.YCBCR_NATIVE_422; | |||
612 | sink_per_slice_throughput_mps = dsc_sink_caps->throughput_mode_1_mps; | |||
613 | branch_max_throughput_mps = dsc_sink_caps->branch_overall_throughput_1_mps; | |||
614 | if (!is_dsc_possible) { | |||
615 | is_dsc_possible = (bool_Bool)dsc_common_caps.color_formats.bits.YCBCR_SIMPLE_422; | |||
616 | dsc_cfg->ycbcr422_simple = is_dsc_possible; | |||
617 | sink_per_slice_throughput_mps = dsc_sink_caps->throughput_mode_0_mps; | |||
618 | } | |||
619 | break; | |||
620 | case PIXEL_ENCODING_YCBCR420: | |||
621 | is_dsc_possible = (bool_Bool)dsc_common_caps.color_formats.bits.YCBCR_NATIVE_420; | |||
622 | sink_per_slice_throughput_mps = dsc_sink_caps->throughput_mode_1_mps; | |||
623 | branch_max_throughput_mps = dsc_sink_caps->branch_overall_throughput_1_mps; | |||
624 | break; | |||
625 | default: | |||
626 | is_dsc_possible = false0; | |||
627 | } | |||
628 | ||||
629 | // Validate branch's maximum throughput | |||
630 | if (branch_max_throughput_mps && dsc_div_by_10_round_up(timing->pix_clk_100hz) > branch_max_throughput_mps * 1000) | |||
631 | is_dsc_possible = false0; | |||
632 | ||||
633 | if (!is_dsc_possible) | |||
634 | goto done; | |||
635 | ||||
636 | // Color depth | |||
637 | switch (timing->display_color_depth) { | |||
638 | case COLOR_DEPTH_888: | |||
639 | is_dsc_possible = (bool_Bool)dsc_common_caps.color_depth.bits.COLOR_DEPTH_8_BPC; | |||
640 | break; | |||
641 | case COLOR_DEPTH_101010: | |||
642 | is_dsc_possible = (bool_Bool)dsc_common_caps.color_depth.bits.COLOR_DEPTH_10_BPC; | |||
643 | break; | |||
644 | case COLOR_DEPTH_121212: | |||
645 | is_dsc_possible = (bool_Bool)dsc_common_caps.color_depth.bits.COLOR_DEPTH_12_BPC; | |||
646 | break; | |||
647 | default: | |||
648 | is_dsc_possible = false0; | |||
649 | } | |||
650 | ||||
651 | if (!is_dsc_possible) | |||
652 | goto done; | |||
653 | ||||
654 | // Slice width (i.e. number of slices per line) | |||
655 | max_slices_h = get_max_dsc_slices(dsc_common_caps.slice_caps); | |||
656 | ||||
657 | while (max_slices_h > 0) { | |||
658 | if (pic_width % max_slices_h == 0) | |||
659 | break; | |||
660 | ||||
661 | max_slices_h = dec_num_slices(dsc_common_caps.slice_caps, max_slices_h); | |||
662 | } | |||
663 | ||||
664 | is_dsc_possible = (dsc_common_caps.max_slice_width > 0); | |||
665 | if (!is_dsc_possible) | |||
666 | goto done; | |||
667 | ||||
668 | min_slices_h = pic_width / dsc_common_caps.max_slice_width; | |||
669 | if (pic_width % dsc_common_caps.max_slice_width) | |||
670 | min_slices_h++; | |||
671 | ||||
672 | min_slices_h = fit_num_slices_up(dsc_common_caps.slice_caps, min_slices_h); | |||
673 | ||||
674 | while (min_slices_h <= max_slices_h) { | |||
675 | int pix_clk_per_slice_khz = dsc_div_by_10_round_up(timing->pix_clk_100hz) / min_slices_h; | |||
676 | if (pix_clk_per_slice_khz <= sink_per_slice_throughput_mps * 1000) | |||
677 | break; | |||
678 | ||||
679 | min_slices_h = inc_num_slices(dsc_common_caps.slice_caps, min_slices_h); | |||
680 | } | |||
681 | ||||
682 | if (pic_width % min_slices_h != 0) | |||
683 | min_slices_h = 0; // DSC TODO: Maybe try increasing the number of slices first? | |||
684 | ||||
685 | is_dsc_possible = (min_slices_h <= max_slices_h); | |||
686 | if (!is_dsc_possible) | |||
687 | goto done; | |||
688 | ||||
689 | if (policy.use_min_slices_h) { | |||
690 | if (min_slices_h > 0) | |||
691 | num_slices_h = min_slices_h; | |||
692 | else if (max_slices_h > 0) { // Fall back to max slices if min slices is not working out | |||
693 | if (policy.max_slices_h) | |||
694 | num_slices_h = min(policy.max_slices_h, max_slices_h)(((policy.max_slices_h)<(max_slices_h))?(policy.max_slices_h ):(max_slices_h)); | |||
695 | else | |||
696 | num_slices_h = max_slices_h; | |||
697 | } else | |||
698 | is_dsc_possible = false0; | |||
699 | } else { | |||
700 | if (max_slices_h > 0) { | |||
701 | if (policy.max_slices_h) | |||
702 | num_slices_h = min(policy.max_slices_h, max_slices_h)(((policy.max_slices_h)<(max_slices_h))?(policy.max_slices_h ):(max_slices_h)); | |||
703 | else | |||
704 | num_slices_h = max_slices_h; | |||
705 | } else if (min_slices_h > 0) // Fall back to min slices if max slices is not possible | |||
706 | num_slices_h = min_slices_h; | |||
707 | else | |||
708 | is_dsc_possible = false0; | |||
709 | } | |||
710 | ||||
711 | if (!is_dsc_possible) | |||
712 | goto done; | |||
713 | ||||
714 | dsc_cfg->num_slices_h = num_slices_h; | |||
715 | slice_width = pic_width / num_slices_h; | |||
716 | ||||
717 | is_dsc_possible = slice_width <= dsc_common_caps.max_slice_width; | |||
718 | if (!is_dsc_possible) | |||
719 | goto done; | |||
720 | ||||
721 | // Slice height (i.e. number of slices per column): start with policy and pick the first one that height is divisible by. | |||
722 | // For 4:2:0 make sure the slice height is divisible by 2 as well. | |||
723 | if (min_slice_height_override == 0) | |||
724 | slice_height = min(policy.min_slice_height, pic_height)(((policy.min_slice_height)<(pic_height))?(policy.min_slice_height ):(pic_height)); | |||
725 | else | |||
726 | slice_height = min(min_slice_height_override, pic_height)(((min_slice_height_override)<(pic_height))?(min_slice_height_override ):(pic_height)); | |||
727 | ||||
728 | while (slice_height < pic_height && (pic_height % slice_height != 0 || | |||
729 | (timing->pixel_encoding == PIXEL_ENCODING_YCBCR420 && slice_height % 2 != 0))) | |||
730 | slice_height++; | |||
731 | ||||
732 | if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR420) // For the case when pic_height < dsc_policy.min_sice_height | |||
733 | is_dsc_possible = (slice_height % 2 == 0); | |||
734 | ||||
735 | if (!is_dsc_possible) | |||
736 | goto done; | |||
737 | ||||
738 | dsc_cfg->num_slices_v = pic_height/slice_height; | |||
739 | ||||
740 | // Final decission: can we do DSC or not? | |||
741 | if (is_dsc_possible) { | |||
742 | // Fill out the rest of DSC settings | |||
743 | dsc_cfg->block_pred_enable = dsc_common_caps.is_block_pred_supported; | |||
744 | dsc_cfg->linebuf_depth = dsc_common_caps.lb_bit_depth; | |||
745 | dsc_cfg->version_minor = (dsc_common_caps.dsc_version & 0xf0) >> 4; | |||
746 | } | |||
747 | ||||
748 | done: | |||
749 | if (!is_dsc_possible) | |||
750 | memset(dsc_cfg, 0, sizeof(struct dc_dsc_config))__builtin_memset((dsc_cfg), (0), (sizeof(struct dc_dsc_config ))); | |||
751 | ||||
752 | return is_dsc_possible; | |||
753 | } | |||
754 | ||||
755 | bool_Bool dc_dsc_parse_dsc_dpcd(const struct dc *dc, const uint8_t *dpcd_dsc_basic_data, const uint8_t *dpcd_dsc_branch_decoder_caps, struct dsc_dec_dpcd_caps *dsc_sink_caps) | |||
756 | { | |||
757 | if (!dpcd_dsc_basic_data) | |||
758 | return false0; | |||
759 | ||||
760 | dsc_sink_caps->is_dsc_supported = (dpcd_dsc_basic_data[DP_DSC_SUPPORT0x060 - DP_DSC_SUPPORT0x060] & DP_DSC_DECOMPRESSION_IS_SUPPORTED(1 << 0)) != 0; | |||
761 | if (!dsc_sink_caps->is_dsc_supported) | |||
762 | return false0; | |||
763 | ||||
764 | dsc_sink_caps->dsc_version = dpcd_dsc_basic_data[DP_DSC_REV0x061 - DP_DSC_SUPPORT0x060]; | |||
765 | ||||
766 | { | |||
767 | int buff_block_size; | |||
768 | int buff_size; | |||
769 | ||||
770 | if (!dsc_buff_block_size_from_dpcd(dpcd_dsc_basic_data[DP_DSC_RC_BUF_BLK_SIZE0x062 - DP_DSC_SUPPORT0x060], &buff_block_size)) | |||
771 | return false0; | |||
772 | ||||
773 | buff_size = dpcd_dsc_basic_data[DP_DSC_RC_BUF_SIZE0x063 - DP_DSC_SUPPORT0x060] + 1; | |||
774 | dsc_sink_caps->rc_buffer_size = buff_size * buff_block_size; | |||
775 | } | |||
776 | ||||
777 | dsc_sink_caps->slice_caps1.raw = dpcd_dsc_basic_data[DP_DSC_SLICE_CAP_10x064 - DP_DSC_SUPPORT0x060]; | |||
778 | if (!dsc_line_buff_depth_from_dpcd(dpcd_dsc_basic_data[DP_DSC_LINE_BUF_BIT_DEPTH0x065 - DP_DSC_SUPPORT0x060], &dsc_sink_caps->lb_bit_depth)) | |||
779 | return false0; | |||
780 | ||||
781 | dsc_sink_caps->is_block_pred_supported = | |||
782 | (dpcd_dsc_basic_data[DP_DSC_BLK_PREDICTION_SUPPORT0x066 - DP_DSC_SUPPORT0x060] & DP_DSC_BLK_PREDICTION_IS_SUPPORTED(1 << 0)) != 0; | |||
783 | ||||
784 | dsc_sink_caps->edp_max_bits_per_pixel = | |||
785 | dpcd_dsc_basic_data[DP_DSC_MAX_BITS_PER_PIXEL_LOW0x067 - DP_DSC_SUPPORT0x060] | | |||
786 | dpcd_dsc_basic_data[DP_DSC_MAX_BITS_PER_PIXEL_HI0x068 - DP_DSC_SUPPORT0x060] << 8; | |||
787 | ||||
788 | dsc_sink_caps->color_formats.raw = dpcd_dsc_basic_data[DP_DSC_DEC_COLOR_FORMAT_CAP0x069 - DP_DSC_SUPPORT0x060]; | |||
789 | dsc_sink_caps->color_depth.raw = dpcd_dsc_basic_data[DP_DSC_DEC_COLOR_DEPTH_CAP0x06A - DP_DSC_SUPPORT0x060]; | |||
790 | ||||
791 | { | |||
792 | int dpcd_throughput = dpcd_dsc_basic_data[DP_DSC_PEAK_THROUGHPUT0x06B - DP_DSC_SUPPORT0x060]; | |||
793 | ||||
794 | if (!dsc_throughput_from_dpcd(dpcd_throughput & DP_DSC_THROUGHPUT_MODE_0_MASK(0xf << 0), &dsc_sink_caps->throughput_mode_0_mps)) | |||
795 | return false0; | |||
796 | ||||
797 | dpcd_throughput = (dpcd_throughput & DP_DSC_THROUGHPUT_MODE_1_MASK(0xf << 4)) >> DP_DSC_THROUGHPUT_MODE_1_SHIFT4; | |||
798 | if (!dsc_throughput_from_dpcd(dpcd_throughput, &dsc_sink_caps->throughput_mode_1_mps)) | |||
799 | return false0; | |||
800 | } | |||
801 | ||||
802 | dsc_sink_caps->max_slice_width = dpcd_dsc_basic_data[DP_DSC_MAX_SLICE_WIDTH0x06C - DP_DSC_SUPPORT0x060] * 320; | |||
803 | dsc_sink_caps->slice_caps2.raw = dpcd_dsc_basic_data[DP_DSC_SLICE_CAP_20x06D - DP_DSC_SUPPORT0x060]; | |||
804 | ||||
805 | if (!dsc_bpp_increment_div_from_dpcd(dpcd_dsc_basic_data[DP_DSC_BITS_PER_PIXEL_INC0x06F - DP_DSC_SUPPORT0x060], &dsc_sink_caps->bpp_increment_div)) | |||
806 | return false0; | |||
807 | ||||
808 | if (dc->debug.dsc_bpp_increment_div) { | |||
809 | /* dsc_bpp_increment_div should onl be 1, 2, 4, 8 or 16, but rather than rejecting invalid values, | |||
810 | * we'll accept all and get it into range. This also makes the above check against 0 redundant, | |||
811 | * but that one stresses out the override will be only used if it's not 0. | |||
812 | */ | |||
813 | if (dc->debug.dsc_bpp_increment_div >= 1) | |||
814 | dsc_sink_caps->bpp_increment_div = 1; | |||
815 | if (dc->debug.dsc_bpp_increment_div >= 2) | |||
816 | dsc_sink_caps->bpp_increment_div = 2; | |||
817 | if (dc->debug.dsc_bpp_increment_div >= 4) | |||
818 | dsc_sink_caps->bpp_increment_div = 4; | |||
819 | if (dc->debug.dsc_bpp_increment_div >= 8) | |||
820 | dsc_sink_caps->bpp_increment_div = 8; | |||
821 | if (dc->debug.dsc_bpp_increment_div >= 16) | |||
822 | dsc_sink_caps->bpp_increment_div = 16; | |||
823 | } | |||
824 | ||||
825 | /* Extended caps */ | |||
826 | if (dpcd_dsc_branch_decoder_caps == NULL((void *)0)) { // branch decoder DPCD DSC data can be null for non branch device | |||
827 | dsc_sink_caps->branch_overall_throughput_0_mps = 0; | |||
828 | dsc_sink_caps->branch_overall_throughput_1_mps = 0; | |||
829 | dsc_sink_caps->branch_max_line_width = 0; | |||
830 | return true1; | |||
831 | } | |||
832 | ||||
833 | dsc_sink_caps->branch_overall_throughput_0_mps = dpcd_dsc_branch_decoder_caps[DP_DSC_BRANCH_OVERALL_THROUGHPUT_00x0a0 - DP_DSC_BRANCH_OVERALL_THROUGHPUT_00x0a0]; | |||
834 | if (dsc_sink_caps->branch_overall_throughput_0_mps == 0) | |||
835 | dsc_sink_caps->branch_overall_throughput_0_mps = 0; | |||
836 | else if (dsc_sink_caps->branch_overall_throughput_0_mps == 1) | |||
837 | dsc_sink_caps->branch_overall_throughput_0_mps = 680; | |||
838 | else { | |||
839 | dsc_sink_caps->branch_overall_throughput_0_mps *= 50; | |||
840 | dsc_sink_caps->branch_overall_throughput_0_mps += 600; | |||
841 | } | |||
842 | ||||
843 | dsc_sink_caps->branch_overall_throughput_1_mps = dpcd_dsc_branch_decoder_caps[DP_DSC_BRANCH_OVERALL_THROUGHPUT_10x0a1 - DP_DSC_BRANCH_OVERALL_THROUGHPUT_00x0a0]; | |||
844 | if (dsc_sink_caps->branch_overall_throughput_1_mps == 0) | |||
845 | dsc_sink_caps->branch_overall_throughput_1_mps = 0; | |||
846 | else if (dsc_sink_caps->branch_overall_throughput_1_mps == 1) | |||
847 | dsc_sink_caps->branch_overall_throughput_1_mps = 680; | |||
848 | else { | |||
849 | dsc_sink_caps->branch_overall_throughput_1_mps *= 50; | |||
850 | dsc_sink_caps->branch_overall_throughput_1_mps += 600; | |||
851 | } | |||
852 | ||||
853 | dsc_sink_caps->branch_max_line_width = dpcd_dsc_branch_decoder_caps[DP_DSC_BRANCH_MAX_LINE_WIDTH0x0a2 - DP_DSC_BRANCH_OVERALL_THROUGHPUT_00x0a0] * 320; | |||
854 | ASSERT(dsc_sink_caps->branch_max_line_width == 0 || dsc_sink_caps->branch_max_line_width >= 5120)do { if (({ static int __warned; int __ret = !!(!(dsc_sink_caps ->branch_max_line_width == 0 || dsc_sink_caps->branch_max_line_width >= 5120)); if (__ret && !__warned) { printf("WARNING %s failed at %s:%d\n" , "!(dsc_sink_caps->branch_max_line_width == 0 || dsc_sink_caps->branch_max_line_width >= 5120)" , "/usr/src/sys/dev/pci/drm/amd/display/dc/dsc/dc_dsc.c", 854 ); __warned = 1; } __builtin_expect(!!(__ret), 0); })) do {} while (0); } while (0); | |||
855 | ||||
856 | return true1; | |||
857 | } | |||
858 | ||||
859 | ||||
860 | /* If DSC is possbile, get DSC bandwidth range based on [min_bpp, max_bpp] target bitrate range and | |||
861 | * timing's pixel clock and uncompressed bandwidth. | |||
862 | * If DSC is not possible, leave '*range' untouched. | |||
863 | */ | |||
864 | bool_Bool dc_dsc_compute_bandwidth_range( | |||
865 | const struct display_stream_compressor *dsc, | |||
866 | const uint32_t dsc_min_slice_height_override, | |||
867 | const uint32_t min_bpp, | |||
868 | const uint32_t max_bpp, | |||
869 | const struct dsc_dec_dpcd_caps *dsc_sink_caps, | |||
870 | const struct dc_crtc_timing *timing, | |||
871 | struct dc_dsc_bw_range *range) | |||
872 | { | |||
873 | bool_Bool is_dsc_possible = false0; | |||
874 | struct dsc_enc_caps dsc_enc_caps; | |||
875 | struct dsc_enc_caps dsc_common_caps; | |||
876 | struct dc_dsc_config config; | |||
877 | ||||
878 | get_dsc_enc_caps(dsc, &dsc_enc_caps, timing->pix_clk_100hz); | |||
879 | ||||
880 | is_dsc_possible = intersect_dsc_caps(dsc_sink_caps, &dsc_enc_caps, | |||
881 | timing->pixel_encoding, &dsc_common_caps); | |||
882 | ||||
883 | if (is_dsc_possible) | |||
884 | is_dsc_possible = setup_dsc_config(dsc_sink_caps, &dsc_enc_caps, 0, timing, | |||
885 | dsc_min_slice_height_override, &config); | |||
886 | ||||
887 | if (is_dsc_possible) | |||
888 | get_dsc_bandwidth_range(min_bpp, max_bpp, &dsc_common_caps, timing, range); | |||
889 | ||||
890 | return is_dsc_possible; | |||
891 | } | |||
892 | ||||
893 | bool_Bool dc_dsc_compute_config( | |||
894 | const struct display_stream_compressor *dsc, | |||
895 | const struct dsc_dec_dpcd_caps *dsc_sink_caps, | |||
896 | const uint32_t dsc_min_slice_height_override, | |||
897 | uint32_t target_bandwidth_kbps, | |||
898 | const struct dc_crtc_timing *timing, | |||
899 | struct dc_dsc_config *dsc_cfg) | |||
900 | { | |||
901 | bool_Bool is_dsc_possible = false0; | |||
902 | struct dsc_enc_caps dsc_enc_caps; | |||
903 | ||||
904 | get_dsc_enc_caps(dsc, &dsc_enc_caps, timing->pix_clk_100hz); | |||
905 | is_dsc_possible = setup_dsc_config(dsc_sink_caps, | |||
906 | &dsc_enc_caps, | |||
907 | target_bandwidth_kbps, | |||
908 | timing, dsc_min_slice_height_override, dsc_cfg); | |||
909 | return is_dsc_possible; | |||
910 | } | |||
911 | ||||
912 | void dc_dsc_get_policy_for_timing(const struct dc_crtc_timing *timing, struct dc_dsc_policy *policy) | |||
913 | { | |||
914 | uint32_t bpc = 0; | |||
915 | ||||
916 | policy->min_target_bpp = 0; | |||
917 | policy->max_target_bpp = 0; | |||
918 | ||||
919 | /* DSC Policy: Use minimum number of slices that fits the pixel clock */ | |||
920 | policy->use_min_slices_h = true1; | |||
921 | ||||
922 | /* DSC Policy: Use max available slices | |||
923 | * (in our case 4 for or 8, depending on the mode) | |||
924 | */ | |||
925 | policy->max_slices_h = 0; | |||
926 | ||||
927 | /* DSC Policy: Use slice height recommended | |||
928 | * by VESA DSC Spreadsheet user guide | |||
929 | */ | |||
930 | policy->min_slice_height = 108; | |||
931 | ||||
932 | /* DSC Policy: follow DP specs with an internal upper limit to 16 bpp | |||
933 | * for better interoperability | |||
934 | */ | |||
935 | switch (timing->display_color_depth) { | |||
936 | case COLOR_DEPTH_888: | |||
937 | bpc = 8; | |||
938 | break; | |||
939 | case COLOR_DEPTH_101010: | |||
940 | bpc = 10; | |||
941 | break; | |||
942 | case COLOR_DEPTH_121212: | |||
943 | bpc = 12; | |||
944 | break; | |||
945 | default: | |||
946 | return; | |||
947 | } | |||
948 | switch (timing->pixel_encoding) { | |||
949 | case PIXEL_ENCODING_RGB: | |||
950 | case PIXEL_ENCODING_YCBCR444: | |||
951 | case PIXEL_ENCODING_YCBCR422: /* assume no YCbCr422 native support */ | |||
952 | /* DP specs limits to 8 */ | |||
953 | policy->min_target_bpp = 8; | |||
954 | /* DP specs limits to 3 x bpc */ | |||
955 | policy->max_target_bpp = 3 * bpc; | |||
956 | break; | |||
957 | case PIXEL_ENCODING_YCBCR420: | |||
958 | /* DP specs limits to 6 */ | |||
959 | policy->min_target_bpp = 6; | |||
960 | /* DP specs limits to 1.5 x bpc assume bpc is an even number */ | |||
961 | policy->max_target_bpp = bpc * 3 / 2; | |||
962 | break; | |||
963 | default: | |||
964 | return; | |||
965 | } | |||
966 | /* internal upper limit, default 16 bpp */ | |||
967 | if (policy->max_target_bpp > dsc_policy_max_target_bpp_limit) | |||
968 | policy->max_target_bpp = dsc_policy_max_target_bpp_limit; | |||
969 | ||||
970 | /* enable DSC when not needed, default false */ | |||
971 | if (dsc_policy_enable_dsc_when_not_needed) | |||
972 | policy->enable_dsc_when_not_needed = dsc_policy_enable_dsc_when_not_needed; | |||
973 | else | |||
974 | policy->enable_dsc_when_not_needed = false0; | |||
975 | } | |||
976 | ||||
977 | void dc_dsc_policy_set_max_target_bpp_limit(uint32_t limit) | |||
978 | { | |||
979 | dsc_policy_max_target_bpp_limit = limit; | |||
980 | } | |||
981 | ||||
982 | void dc_dsc_policy_set_enable_dsc_when_not_needed(bool_Bool enable) | |||
983 | { | |||
984 | dsc_policy_enable_dsc_when_not_needed = enable; | |||
985 | } |