xref: /linux/drivers/gpu/drm/i915/display/intel_link_bw.c (revision 6812ce4e4379ffc99c52401ec28f0d7ffbc36206)
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