1 // SPDX-License-Identifier: MIT
2 /*
3 * Copyright © 2023 Intel Corporation
4 */
5
6 #include <linux/ctype.h>
7 #include <linux/debugfs.h>
8 #include <linux/int_log.h>
9 #include <linux/math.h>
10
11 #include <drm/drm_fixed.h>
12 #include <drm/drm_print.h>
13
14 #include "intel_atomic.h"
15 #include "intel_crtc.h"
16 #include "intel_display_core.h"
17 #include "intel_display_types.h"
18 #include "intel_dp.h"
19 #include "intel_dp_mst.h"
20 #include "intel_dp_tunnel.h"
21 #include "intel_fdi.h"
22 #include "intel_link_bw.h"
23 #include "intel_vdsc.h"
24
get_forced_link_bpp_x16(struct intel_atomic_state * state,const struct intel_crtc * crtc)25 static int get_forced_link_bpp_x16(struct intel_atomic_state *state,
26 const struct intel_crtc *crtc)
27 {
28 struct intel_digital_connector_state *conn_state;
29 struct intel_connector *connector;
30 int force_bpp_x16 = INT_MAX;
31 int i;
32
33 for_each_new_intel_connector_in_state(state, connector, conn_state, i) {
34 if (conn_state->base.crtc != &crtc->base)
35 continue;
36
37 if (!connector->link.force_bpp_x16)
38 continue;
39
40 force_bpp_x16 = min(force_bpp_x16, connector->link.force_bpp_x16);
41 }
42
43 return force_bpp_x16 < INT_MAX ? force_bpp_x16 : 0;
44 }
45
46 /**
47 * intel_link_bw_init_limits - initialize BW limits
48 * @state: Atomic state
49 * @limits: link BW limits
50 *
51 * Initialize @limits.
52 */
intel_link_bw_init_limits(struct intel_atomic_state * state,struct intel_link_bw_limits * limits)53 void intel_link_bw_init_limits(struct intel_atomic_state *state,
54 struct intel_link_bw_limits *limits)
55 {
56 struct intel_display *display = to_intel_display(state);
57 enum pipe pipe;
58
59 limits->link_dsc_pipes = 0;
60 limits->bpp_limit_reached_pipes = 0;
61 for_each_pipe(display, pipe) {
62 struct intel_crtc *crtc = intel_crtc_for_pipe(display, pipe);
63 const struct intel_crtc_state *crtc_state =
64 intel_atomic_get_new_crtc_state(state, crtc);
65 int forced_bpp_x16 = get_forced_link_bpp_x16(state, crtc);
66
67 if ((state->base.duplicated && crtc_state) ||
68 intel_dp_mst_stream_disconnected(state, crtc)) {
69 limits->max_bpp_x16[pipe] = crtc_state->max_link_bpp_x16;
70 if (intel_dsc_enabled_on_link(crtc_state))
71 limits->link_dsc_pipes |= BIT(pipe);
72 } else {
73 limits->max_bpp_x16[pipe] = INT_MAX;
74 }
75
76 if (forced_bpp_x16)
77 limits->max_bpp_x16[pipe] = min(limits->max_bpp_x16[pipe], forced_bpp_x16);
78 }
79 }
80
81 /**
82 * __intel_link_bw_reduce_bpp - reduce maximum link bpp for a selected pipe
83 * @state: atomic state
84 * @limits: link BW limits
85 * @pipe_mask: mask of pipes to select from
86 * @reason: explanation of why bpp reduction is needed
87 * @reduce_forced_bpp: allow reducing bpps below their forced link bpp
88 *
89 * Select the pipe from @pipe_mask with the biggest link bpp value and set the
90 * maximum of link bpp in @limits below this value. Modeset the selected pipe,
91 * so that its state will get recomputed.
92 *
93 * This function can be called to resolve a link's BW overallocation by reducing
94 * the link bpp of one pipe on the link and hence reducing the total link BW.
95 *
96 * Returns
97 * - 0 in case of success
98 * - %-ENOSPC if no pipe can further reduce its link bpp
99 * - Other negative error, if modesetting the selected pipe failed
100 */
__intel_link_bw_reduce_bpp(struct intel_atomic_state * state,struct intel_link_bw_limits * limits,u8 pipe_mask,const char * reason,bool reduce_forced_bpp)101 static int __intel_link_bw_reduce_bpp(struct intel_atomic_state *state,
102 struct intel_link_bw_limits *limits,
103 u8 pipe_mask,
104 const char *reason,
105 bool reduce_forced_bpp)
106 {
107 struct intel_display *display = to_intel_display(state);
108 enum pipe max_bpp_pipe = INVALID_PIPE;
109 struct intel_crtc *crtc;
110 int max_bpp_x16 = 0;
111
112 for_each_intel_crtc_in_pipe_mask(display, crtc, pipe_mask) {
113 struct intel_crtc_state *crtc_state;
114 int link_bpp_x16;
115
116 if (limits->bpp_limit_reached_pipes & BIT(crtc->pipe))
117 continue;
118
119 crtc_state = intel_atomic_get_crtc_state(&state->base,
120 crtc);
121 if (IS_ERR(crtc_state))
122 return PTR_ERR(crtc_state);
123
124 if (crtc_state->dsc.compression_enable)
125 link_bpp_x16 = crtc_state->dsc.compressed_bpp_x16;
126 else
127 /*
128 * TODO: for YUV420 the actual link bpp is only half
129 * of the pipe bpp value. The MST encoder's BW allocation
130 * is based on the pipe bpp value, set the actual link bpp
131 * limit here once the MST BW allocation is fixed.
132 */
133 link_bpp_x16 = fxp_q4_from_int(crtc_state->pipe_bpp);
134
135 if (!reduce_forced_bpp &&
136 link_bpp_x16 <= get_forced_link_bpp_x16(state, crtc))
137 continue;
138
139 if (link_bpp_x16 > max_bpp_x16) {
140 max_bpp_x16 = link_bpp_x16;
141 max_bpp_pipe = crtc->pipe;
142 }
143 }
144
145 if (max_bpp_pipe == INVALID_PIPE)
146 return -ENOSPC;
147
148 limits->max_bpp_x16[max_bpp_pipe] = max_bpp_x16 - 1;
149
150 return intel_modeset_pipes_in_mask_early(state, reason,
151 BIT(max_bpp_pipe));
152 }
153
intel_link_bw_reduce_bpp(struct intel_atomic_state * state,struct intel_link_bw_limits * limits,u8 pipe_mask,const char * reason)154 int intel_link_bw_reduce_bpp(struct intel_atomic_state *state,
155 struct intel_link_bw_limits *limits,
156 u8 pipe_mask,
157 const char *reason)
158 {
159 int ret;
160
161 /* Try to keep any forced link BPP. */
162 ret = __intel_link_bw_reduce_bpp(state, limits, pipe_mask, reason, false);
163 if (ret == -ENOSPC)
164 ret = __intel_link_bw_reduce_bpp(state, limits, pipe_mask, reason, true);
165
166 return ret;
167 }
168
169 /**
170 * intel_link_bw_compute_pipe_bpp - compute pipe bpp limited by max link bpp
171 * @crtc_state: the crtc state
172 *
173 * Compute the pipe bpp limited by the CRTC's maximum link bpp. Encoders can
174 * call this function during state computation in the simple case where the
175 * link bpp will always match the pipe bpp. This is the case for all non-DP
176 * encoders, while DP encoders will use a link bpp lower than pipe bpp in case
177 * of DSC compression.
178 *
179 * Returns %true in case of success, %false if pipe bpp would need to be
180 * reduced below its valid range.
181 */
intel_link_bw_compute_pipe_bpp(struct intel_crtc_state * crtc_state)182 bool intel_link_bw_compute_pipe_bpp(struct intel_crtc_state *crtc_state)
183 {
184 int pipe_bpp = min(crtc_state->pipe_bpp,
185 fxp_q4_to_int(crtc_state->max_link_bpp_x16));
186
187 pipe_bpp = rounddown(pipe_bpp, 2 * 3);
188
189 if (pipe_bpp < 6 * 3)
190 return false;
191
192 crtc_state->pipe_bpp = pipe_bpp;
193
194 return true;
195 }
196
197 /**
198 * intel_link_bw_set_bpp_limit_for_pipe - set link bpp limit for a pipe to its minimum
199 * @state: atomic state
200 * @old_limits: link BW limits
201 * @new_limits: link BW limits
202 * @pipe: pipe
203 *
204 * Set the link bpp limit for @pipe in @new_limits to its value in
205 * @old_limits and mark this limit as the minimum. This function must be
206 * called after a pipe's compute config function failed, @old_limits
207 * containing the bpp limit with which compute config previously passed.
208 *
209 * The function will fail if setting a minimum is not possible, either
210 * because the old and new limits match (and so would lead to a pipe compute
211 * config failure) or the limit is already at the minimum.
212 *
213 * Returns %true in case of success.
214 */
215 bool
intel_link_bw_set_bpp_limit_for_pipe(struct intel_atomic_state * state,const struct intel_link_bw_limits * old_limits,struct intel_link_bw_limits * new_limits,enum pipe pipe)216 intel_link_bw_set_bpp_limit_for_pipe(struct intel_atomic_state *state,
217 const struct intel_link_bw_limits *old_limits,
218 struct intel_link_bw_limits *new_limits,
219 enum pipe pipe)
220 {
221 struct intel_display *display = to_intel_display(state);
222
223 if (pipe == INVALID_PIPE)
224 return false;
225
226 if (new_limits->max_bpp_x16[pipe] ==
227 old_limits->max_bpp_x16[pipe])
228 return false;
229
230 if (drm_WARN_ON(display->drm,
231 new_limits->bpp_limit_reached_pipes & BIT(pipe)))
232 return false;
233
234 new_limits->max_bpp_x16[pipe] =
235 old_limits->max_bpp_x16[pipe];
236 new_limits->bpp_limit_reached_pipes |= BIT(pipe);
237
238 return true;
239 }
240
check_all_link_config(struct intel_atomic_state * state,struct intel_link_bw_limits * limits)241 static int check_all_link_config(struct intel_atomic_state *state,
242 struct intel_link_bw_limits *limits)
243 {
244 /* TODO: Check additional shared display link configurations like MST */
245 int ret;
246
247 ret = intel_dp_mst_atomic_check_link(state, limits);
248 if (ret)
249 return ret;
250
251 ret = intel_dp_tunnel_atomic_check_link(state, limits);
252 if (ret)
253 return ret;
254
255 ret = intel_fdi_atomic_check_link(state, limits);
256 if (ret)
257 return ret;
258
259 return 0;
260 }
261
262 static bool
assert_link_limit_change_valid(struct intel_display * display,const struct intel_link_bw_limits * old_limits,const struct intel_link_bw_limits * new_limits)263 assert_link_limit_change_valid(struct intel_display *display,
264 const struct intel_link_bw_limits *old_limits,
265 const struct intel_link_bw_limits *new_limits)
266 {
267 bool bpps_changed = false;
268 enum pipe pipe;
269
270 /* DSC can't be disabled after it was enabled. */
271 if (drm_WARN_ON(display->drm,
272 (old_limits->link_dsc_pipes & new_limits->link_dsc_pipes) !=
273 old_limits->link_dsc_pipes))
274 return false;
275
276 for_each_pipe(display, pipe) {
277 /* The bpp limit can only decrease. */
278 if (drm_WARN_ON(display->drm,
279 new_limits->max_bpp_x16[pipe] >
280 old_limits->max_bpp_x16[pipe]))
281 return false;
282
283 if (new_limits->max_bpp_x16[pipe] <
284 old_limits->max_bpp_x16[pipe])
285 bpps_changed = true;
286 }
287
288 /* At least one limit must change. */
289 if (drm_WARN_ON(display->drm,
290 !bpps_changed &&
291 new_limits->link_dsc_pipes ==
292 old_limits->link_dsc_pipes))
293 return false;
294
295 return true;
296 }
297
298 /**
299 * intel_link_bw_atomic_check - check display link states and set a fallback config if needed
300 * @state: atomic state
301 * @new_limits: link BW limits
302 *
303 * Check the configuration of all shared display links in @state and set new BW
304 * limits in @new_limits if there is a BW limitation.
305 *
306 * Returns:
307 * - 0 if the configuration is valid
308 * - %-EAGAIN, if the configuration is invalid and @new_limits got updated
309 * with fallback values with which the configuration of all CRTCs
310 * in @state must be recomputed
311 * - Other negative error, if the configuration is invalid without a
312 * fallback possibility, or the check failed for another reason
313 */
intel_link_bw_atomic_check(struct intel_atomic_state * state,struct intel_link_bw_limits * new_limits)314 int intel_link_bw_atomic_check(struct intel_atomic_state *state,
315 struct intel_link_bw_limits *new_limits)
316 {
317 struct intel_display *display = to_intel_display(state);
318 struct intel_link_bw_limits old_limits = *new_limits;
319 int ret;
320
321 ret = check_all_link_config(state, new_limits);
322 if (ret != -EAGAIN)
323 return ret;
324
325 if (!assert_link_limit_change_valid(display, &old_limits, new_limits))
326 return -EINVAL;
327
328 return -EAGAIN;
329 }
330
force_link_bpp_show(struct seq_file * m,void * data)331 static int force_link_bpp_show(struct seq_file *m, void *data)
332 {
333 struct intel_connector *connector = m->private;
334
335 seq_printf(m, FXP_Q4_FMT "\n", FXP_Q4_ARGS(connector->link.force_bpp_x16));
336
337 return 0;
338 }
339
str_to_fxp_q4_nonneg_int(const char * str,int * val_x16)340 static int str_to_fxp_q4_nonneg_int(const char *str, int *val_x16)
341 {
342 unsigned int val;
343 int err;
344
345 err = kstrtouint(str, 10, &val);
346 if (err)
347 return err;
348
349 if (val > INT_MAX >> 4)
350 return -ERANGE;
351
352 *val_x16 = fxp_q4_from_int(val);
353
354 return 0;
355 }
356
357 /* modifies str */
str_to_fxp_q4_nonneg(char * str,int * val_x16)358 static int str_to_fxp_q4_nonneg(char *str, int *val_x16)
359 {
360 const char *int_str;
361 char *frac_str;
362 int frac_digits;
363 int frac_val;
364 int err;
365
366 int_str = strim(str);
367 frac_str = strchr(int_str, '.');
368
369 if (frac_str)
370 *frac_str++ = '\0';
371
372 err = str_to_fxp_q4_nonneg_int(int_str, val_x16);
373 if (err)
374 return err;
375
376 if (!frac_str)
377 return 0;
378
379 /* prevent negative number/leading +- sign mark */
380 if (!isdigit(*frac_str))
381 return -EINVAL;
382
383 err = str_to_fxp_q4_nonneg_int(frac_str, &frac_val);
384 if (err)
385 return err;
386
387 frac_digits = strlen(frac_str);
388 if (frac_digits > intlog10(INT_MAX) >> 24 ||
389 frac_val > INT_MAX - int_pow(10, frac_digits) / 2)
390 return -ERANGE;
391
392 frac_val = DIV_ROUND_CLOSEST(frac_val, (int)int_pow(10, frac_digits));
393
394 if (*val_x16 > INT_MAX - frac_val)
395 return -ERANGE;
396
397 *val_x16 += frac_val;
398
399 return 0;
400 }
401
user_str_to_fxp_q4_nonneg(const char __user * ubuf,size_t len,int * val_x16)402 static int user_str_to_fxp_q4_nonneg(const char __user *ubuf, size_t len, int *val_x16)
403 {
404 char *kbuf;
405 int err;
406
407 kbuf = memdup_user_nul(ubuf, len);
408 if (IS_ERR(kbuf))
409 return PTR_ERR(kbuf);
410
411 err = str_to_fxp_q4_nonneg(kbuf, val_x16);
412
413 kfree(kbuf);
414
415 return err;
416 }
417
connector_supports_dsc(struct intel_connector * connector)418 static bool connector_supports_dsc(struct intel_connector *connector)
419 {
420 struct intel_display *display = to_intel_display(connector);
421
422 switch (connector->base.connector_type) {
423 case DRM_MODE_CONNECTOR_eDP:
424 return intel_dp_has_dsc(connector);
425 case DRM_MODE_CONNECTOR_DisplayPort:
426 if (connector->mst.dp)
427 return HAS_DSC_MST(display);
428
429 return HAS_DSC(display);
430 default:
431 return false;
432 }
433 }
434
435 static ssize_t
force_link_bpp_write(struct file * file,const char __user * ubuf,size_t len,loff_t * offp)436 force_link_bpp_write(struct file *file, const char __user *ubuf, size_t len, loff_t *offp)
437 {
438 struct seq_file *m = file->private_data;
439 struct intel_connector *connector = m->private;
440 struct intel_display *display = to_intel_display(connector);
441 int min_bpp;
442 int bpp_x16;
443 int err;
444
445 err = user_str_to_fxp_q4_nonneg(ubuf, len, &bpp_x16);
446 if (err)
447 return err;
448
449 /* TODO: Make the non-DSC min_bpp value connector specific. */
450 if (connector_supports_dsc(connector))
451 min_bpp = intel_dp_dsc_min_src_compressed_bpp();
452 else
453 min_bpp = intel_display_min_pipe_bpp();
454
455 if (bpp_x16 &&
456 (bpp_x16 < fxp_q4_from_int(min_bpp) ||
457 bpp_x16 > fxp_q4_from_int(intel_display_max_pipe_bpp(display))))
458 return -EINVAL;
459
460 err = drm_modeset_lock_single_interruptible(&display->drm->mode_config.connection_mutex);
461 if (err)
462 return err;
463
464 connector->link.force_bpp_x16 = bpp_x16;
465
466 drm_modeset_unlock(&display->drm->mode_config.connection_mutex);
467
468 *offp += len;
469
470 return len;
471 }
472 DEFINE_SHOW_STORE_ATTRIBUTE(force_link_bpp);
473
intel_link_bw_connector_debugfs_add(struct intel_connector * connector)474 void intel_link_bw_connector_debugfs_add(struct intel_connector *connector)
475 {
476 struct intel_display *display = to_intel_display(connector);
477 struct dentry *root = connector->base.debugfs_entry;
478
479 switch (connector->base.connector_type) {
480 case DRM_MODE_CONNECTOR_DisplayPort:
481 case DRM_MODE_CONNECTOR_eDP:
482 case DRM_MODE_CONNECTOR_HDMIA:
483 break;
484 case DRM_MODE_CONNECTOR_VGA:
485 case DRM_MODE_CONNECTOR_SVIDEO:
486 case DRM_MODE_CONNECTOR_LVDS:
487 case DRM_MODE_CONNECTOR_DVID:
488 if (HAS_FDI(display))
489 break;
490
491 return;
492 default:
493 return;
494 }
495
496 debugfs_create_file("intel_force_link_bpp", 0644, root,
497 connector, &force_link_bpp_fops);
498 }
499