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