Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'topic/pipe-reorder-2026-04-15' of https://gitlab.freedesktop.org/drm/i915/kernel into drm-next

drm/i915/display: change pipe allocation order for discrete platforms

This is a topic pull request for changing the pipe allocation order for
discrete platforms from the usual A,B,C,D to A,C,B,D. The goal is to
help pipe joiner configurations that reserve the adjacent pipe as the
secondary pipe without the user space knowing. More details in the
relevant commit message. The CRTC iteration is also changed to remain in
pipe order.

Signed-off-by: Dave Airlie <airlied@redhat.com>
From: Jani Nikula <jani.nikula@intel.com>
Link: https://patch.msgid.link/d69501d53c233386d70ed10290af24aafebf434f@intel.com

+95 -70
+46 -3
drivers/gpu/drm/i915/display/intel_crtc.c
··· 209 209 crtc->base.state = &crtc_state->uapi; 210 210 crtc->config = crtc_state; 211 211 212 + INIT_LIST_HEAD(&crtc->pipe_head); 213 + 212 214 return crtc; 213 215 } 214 216 ··· 223 221 static void intel_crtc_destroy(struct drm_crtc *_crtc) 224 222 { 225 223 struct intel_crtc *crtc = to_intel_crtc(_crtc); 224 + 225 + list_del(&crtc->pipe_head); 226 226 227 227 cpu_latency_qos_remove_request(&crtc->vblank_pm_qos); 228 228 ··· 312 308 .get_vblank_timestamp = intel_crtc_get_vblank_timestamp, 313 309 }; 314 310 311 + static void add_crtc_to_pipe_list(struct intel_display *display, struct intel_crtc *crtc) 312 + { 313 + struct intel_crtc *iter; 314 + 315 + list_for_each_entry(iter, &display->pipe_list, pipe_head) { 316 + if (crtc->pipe < iter->pipe) { 317 + list_add_tail(&crtc->pipe_head, &iter->pipe_head); 318 + return; 319 + } 320 + } 321 + 322 + list_add_tail(&crtc->pipe_head, &display->pipe_list); 323 + } 324 + 315 325 static int __intel_crtc_init(struct intel_display *display, enum pipe pipe) 316 326 { 317 327 struct intel_plane *primary, *cursor; ··· 411 393 412 394 cpu_latency_qos_add_request(&crtc->vblank_pm_qos, PM_QOS_DEFAULT_VALUE); 413 395 414 - drm_WARN_ON(display->drm, drm_crtc_index(&crtc->base) != crtc->pipe); 415 - 416 396 if (HAS_CASF(display) && crtc->num_scalers >= 2) 417 397 drm_crtc_create_sharpness_strength_property(&crtc->base); 398 + 399 + add_crtc_to_pipe_list(display, crtc); 418 400 419 401 return 0; 420 402 ··· 422 404 intel_crtc_free(crtc); 423 405 424 406 return ret; 407 + } 408 + 409 + #define HAS_PIPE(display, pipe) (DISPLAY_RUNTIME_INFO(display)->pipe_mask & BIT(pipe)) 410 + 411 + /* 412 + * Expose the pipes in order A, C, B, D on discrete platforms to trick user 413 + * space into using pipes that are more likely to be available for both a) user 414 + * space if pipe B has been reserved for the joiner, and b) the joiner if pipe A 415 + * doesn't need the joiner. 416 + * 417 + * Swap pipes B and C only if both are available i.e. not fused off. 418 + */ 419 + static enum pipe reorder_pipe(struct intel_display *display, enum pipe pipe) 420 + { 421 + if (!display->platform.dgfx || !HAS_PIPE(display, PIPE_B) || !HAS_PIPE(display, PIPE_C)) 422 + return pipe; 423 + 424 + switch (pipe) { 425 + case PIPE_B: 426 + return PIPE_C; 427 + case PIPE_C: 428 + return PIPE_B; 429 + default: 430 + return pipe; 431 + } 425 432 } 426 433 427 434 int intel_crtc_init(struct intel_display *display) ··· 458 415 INTEL_NUM_PIPES(display), str_plural(INTEL_NUM_PIPES(display))); 459 416 460 417 for_each_pipe(display, pipe) { 461 - ret = __intel_crtc_init(display, pipe); 418 + ret = __intel_crtc_init(display, reorder_pipe(display, pipe)); 462 419 if (ret) 463 420 return ret; 464 421 }
+5 -15
drivers/gpu/drm/i915/display/intel_display.c
··· 5939 5939 return -EINVAL; 5940 5940 } 5941 5941 5942 - /* 5943 - * The state copy logic assumes the primary crtc gets processed 5944 - * before the secondary crtc during the main compute_config loop. 5945 - * This works because the crtcs are created in pipe order, 5946 - * and the hardware requires primary pipe < secondary pipe as well. 5947 - * Should that change we need to rethink the logic. 5948 - */ 5949 - if (WARN_ON(drm_crtc_index(&primary_crtc->base) > 5950 - drm_crtc_index(&secondary_crtc->base))) 5951 - return -EINVAL; 5952 - 5953 5942 drm_dbg_kms(display->drm, 5954 5943 "[CRTC:%d:%s] Used as secondary for joiner primary [CRTC:%d:%s]\n", 5955 5944 secondary_crtc->base.base.id, secondary_crtc->base.name, ··· 6316 6327 6317 6328 for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) { 6318 6329 if (!intel_crtc_needs_modeset(new_crtc_state)) { 6319 - if (intel_crtc_is_joiner_secondary(new_crtc_state)) 6320 - copy_joiner_crtc_state_nomodeset(state, crtc); 6321 - else 6330 + if (!intel_crtc_is_joiner_secondary(new_crtc_state)) 6322 6331 intel_crtc_copy_uapi_to_hw_state_nomodeset(state, crtc); 6323 6332 continue; 6324 6333 } ··· 6447 6460 goto fail; 6448 6461 6449 6462 for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) { 6450 - if (!intel_crtc_needs_modeset(new_crtc_state)) 6463 + if (!intel_crtc_needs_modeset(new_crtc_state)) { 6464 + if (intel_crtc_is_joiner_secondary(new_crtc_state)) 6465 + copy_joiner_crtc_state_nomodeset(state, crtc); 6451 6466 continue; 6467 + } 6452 6468 6453 6469 if (intel_crtc_is_joiner_secondary(new_crtc_state)) { 6454 6470 drm_WARN_ON(display->drm, new_crtc_state->uapi.enable);
+38 -52
drivers/gpu/drm/i915/display/intel_display.h
··· 212 212 base.head) \ 213 213 for_each_if((intel_plane)->pipe == (intel_crtc)->pipe) 214 214 215 - #define for_each_intel_crtc(dev, intel_crtc) \ 216 - list_for_each_entry(intel_crtc, \ 217 - &(dev)->mode_config.crtc_list, \ 218 - base.head) 215 + #define for_each_intel_crtc(dev, crtc) \ 216 + list_for_each_entry((crtc), \ 217 + &to_intel_display(dev)->pipe_list, \ 218 + pipe_head) 219 219 220 - #define for_each_intel_crtc_in_pipe_mask(dev, intel_crtc, pipe_mask) \ 221 - list_for_each_entry(intel_crtc, \ 222 - &(dev)->mode_config.crtc_list, \ 223 - base.head) \ 224 - for_each_if((pipe_mask) & BIT(intel_crtc->pipe)) 220 + #define for_each_intel_crtc_reverse(dev, crtc) \ 221 + list_for_each_entry_reverse((crtc), \ 222 + &to_intel_display(dev)->pipe_list, \ 223 + pipe_head) 225 224 226 - #define for_each_intel_crtc_in_pipe_mask_reverse(dev, intel_crtc, pipe_mask) \ 227 - list_for_each_entry_reverse((intel_crtc), \ 228 - &(dev)->mode_config.crtc_list, \ 229 - base.head) \ 230 - for_each_if((pipe_mask) & BIT((intel_crtc)->pipe)) 225 + #define for_each_intel_crtc_in_pipe_mask(dev, crtc, pipe_mask) \ 226 + for_each_intel_crtc((dev), (crtc)) \ 227 + for_each_if((pipe_mask) & BIT((crtc)->pipe)) 228 + 229 + #define for_each_intel_crtc_in_pipe_mask_reverse(dev, crtc, pipe_mask) \ 230 + for_each_intel_crtc_reverse((dev), (crtc)) \ 231 + for_each_if((pipe_mask) & BIT((crtc)->pipe)) 231 232 232 233 #define for_each_intel_encoder(dev, intel_encoder) \ 233 234 list_for_each_entry(intel_encoder, \ ··· 270 269 (__i)++) \ 271 270 for_each_if(plane) 272 271 273 - #define for_each_old_intel_crtc_in_state(__state, crtc, old_crtc_state, __i) \ 274 - for ((__i) = 0; \ 275 - (__i) < (__state)->base.dev->mode_config.num_crtc && \ 276 - ((crtc) = to_intel_crtc((__state)->base.crtcs[__i].ptr), \ 277 - (old_crtc_state) = to_intel_crtc_state((__state)->base.crtcs[__i].old_state), 1); \ 278 - (__i)++) \ 279 - for_each_if(crtc) 280 - 281 272 #define for_each_new_intel_plane_in_state(__state, plane, new_plane_state, __i) \ 282 273 for ((__i) = 0; \ 283 274 (__i) < (__state)->base.dev->mode_config.num_total_plane && \ ··· 277 284 (new_plane_state) = to_intel_plane_state((__state)->base.planes[__i].new_state), 1); \ 278 285 (__i)++) \ 279 286 for_each_if(plane) 280 - 281 - #define for_each_new_intel_crtc_in_state(__state, crtc, new_crtc_state, __i) \ 282 - for ((__i) = 0; \ 283 - (__i) < (__state)->base.dev->mode_config.num_crtc && \ 284 - ((crtc) = to_intel_crtc((__state)->base.crtcs[__i].ptr), \ 285 - (new_crtc_state) = to_intel_crtc_state((__state)->base.crtcs[__i].new_state), 1); \ 286 - (__i)++) \ 287 - for_each_if(crtc) 288 - 289 - #define for_each_new_intel_crtc_in_state_reverse(__state, crtc, new_crtc_state, __i) \ 290 - for ((__i) = (__state)->base.dev->mode_config.num_crtc - 1; \ 291 - (__i) >= 0 && \ 292 - ((crtc) = to_intel_crtc((__state)->base.crtcs[__i].ptr), \ 293 - (new_crtc_state) = to_intel_crtc_state((__state)->base.crtcs[__i].new_state), 1); \ 294 - (__i)--) \ 295 - for_each_if(crtc) 296 287 297 288 #define for_each_oldnew_intel_plane_in_state(__state, plane, old_plane_state, new_plane_state, __i) \ 298 289 for ((__i) = 0; \ ··· 287 310 (__i)++) \ 288 311 for_each_if(plane) 289 312 313 + #define for_each_old_intel_crtc_in_state(__state, crtc, old_crtc_state, __i) \ 314 + for_each_intel_crtc((__state)->base.dev, (crtc)) \ 315 + for_each_if(((__i) = drm_crtc_index(&(crtc)->base), (void)(__i), \ 316 + (old_crtc_state) = intel_atomic_get_old_crtc_state((__state), (crtc)))) 317 + 318 + #define for_each_new_intel_crtc_in_state(__state, crtc, new_crtc_state, __i) \ 319 + for_each_intel_crtc((__state)->base.dev, (crtc)) \ 320 + for_each_if(((__i) = drm_crtc_index(&(crtc)->base), (void)(__i), \ 321 + (new_crtc_state) = intel_atomic_get_new_crtc_state((__state), (crtc)))) 322 + 323 + #define for_each_new_intel_crtc_in_state_reverse(__state, crtc, new_crtc_state, __i) \ 324 + for_each_intel_crtc_reverse((__state)->base.dev, (crtc)) \ 325 + for_each_if(((__i) = drm_crtc_index(&(crtc)->base), (void)(__i), \ 326 + (new_crtc_state) = intel_atomic_get_new_crtc_state((__state), (crtc)))) 327 + 290 328 #define for_each_oldnew_intel_crtc_in_state(__state, crtc, old_crtc_state, new_crtc_state, __i) \ 291 - for ((__i) = 0; \ 292 - (__i) < (__state)->base.dev->mode_config.num_crtc && \ 293 - ((crtc) = to_intel_crtc((__state)->base.crtcs[__i].ptr), \ 294 - (old_crtc_state) = to_intel_crtc_state((__state)->base.crtcs[__i].old_state), \ 295 - (new_crtc_state) = to_intel_crtc_state((__state)->base.crtcs[__i].new_state), 1); \ 296 - (__i)++) \ 297 - for_each_if(crtc) 329 + for_each_intel_crtc((__state)->base.dev, (crtc)) \ 330 + for_each_if(((__i) = drm_crtc_index(&(crtc)->base), (void)(__i), \ 331 + (old_crtc_state) = intel_atomic_get_old_crtc_state((__state), (crtc)), \ 332 + (new_crtc_state) = intel_atomic_get_new_crtc_state((__state), (crtc)))) 298 333 299 334 #define for_each_oldnew_intel_crtc_in_state_reverse(__state, crtc, old_crtc_state, new_crtc_state, __i) \ 300 - for ((__i) = (__state)->base.dev->mode_config.num_crtc - 1; \ 301 - (__i) >= 0 && \ 302 - ((crtc) = to_intel_crtc((__state)->base.crtcs[__i].ptr), \ 303 - (old_crtc_state) = to_intel_crtc_state((__state)->base.crtcs[__i].old_state), \ 304 - (new_crtc_state) = to_intel_crtc_state((__state)->base.crtcs[__i].new_state), 1); \ 305 - (__i)--) \ 306 - for_each_if(crtc) 335 + for_each_intel_crtc_reverse((__state)->base.dev, (crtc)) \ 336 + for_each_if(((__i) = drm_crtc_index(&(crtc)->base), (void)(__i), \ 337 + (old_crtc_state) = intel_atomic_get_old_crtc_state((__state), (crtc)), \ 338 + (new_crtc_state) = intel_atomic_get_new_crtc_state((__state), (crtc)))) 307 339 308 340 #define intel_atomic_crtc_state_for_each_plane_state( \ 309 341 plane, plane_state, \
+3
drivers/gpu/drm/i915/display/intel_display_core.h
··· 294 294 /* Parent, or core, driver functions exposed to display */ 295 295 const struct intel_display_parent_interface *parent; 296 296 297 + /* list of all intel_crtcs sorted by pipe */ 298 + struct list_head pipe_list; 299 + 297 300 /* Display functions */ 298 301 struct { 299 302 /* Top level crtc-ish functions */
+1
drivers/gpu/drm/i915/display/intel_display_driver.c
··· 117 117 118 118 drm_mode_config_init(display->drm); 119 119 INIT_LIST_HEAD(&display->global.obj_list); 120 + INIT_LIST_HEAD(&display->pipe_list); 120 121 121 122 mode_config->min_width = 0; 122 123 mode_config->min_height = 0;
+1
drivers/gpu/drm/i915/display/intel_display_types.h
··· 1484 1484 1485 1485 struct intel_crtc { 1486 1486 struct drm_crtc base; 1487 + struct list_head pipe_head; 1487 1488 enum pipe pipe; 1488 1489 /* 1489 1490 * Whether the crtc and the connected output pipeline is active. Implies
+1
drivers/gpu/drm/xe/display/xe_display.c
··· 21 21 #include "intel_audio.h" 22 22 #include "intel_bw.h" 23 23 #include "intel_display.h" 24 + #include "intel_display_core.h" 24 25 #include "intel_display_device.h" 25 26 #include "intel_display_driver.h" 26 27 #include "intel_display_irq.h"