Skip to content

Commit 993eb19

Browse files
committed
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
2 parents ca8639f + 2c683e9 commit 993eb19

7 files changed

Lines changed: 95 additions & 70 deletions

File tree

drivers/gpu/drm/i915/display/intel_crtc.c

Lines changed: 46 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,8 @@ static struct intel_crtc *intel_crtc_alloc(void)
209209
crtc->base.state = &crtc_state->uapi;
210210
crtc->config = crtc_state;
211211

212+
INIT_LIST_HEAD(&crtc->pipe_head);
213+
212214
return crtc;
213215
}
214216

@@ -222,6 +224,8 @@ static void intel_crtc_destroy(struct drm_crtc *_crtc)
222224
{
223225
struct intel_crtc *crtc = to_intel_crtc(_crtc);
224226

227+
list_del(&crtc->pipe_head);
228+
225229
cpu_latency_qos_remove_request(&crtc->vblank_pm_qos);
226230

227231
drm_crtc_cleanup(&crtc->base);
@@ -308,6 +312,20 @@ static const struct drm_crtc_funcs i8xx_crtc_funcs = {
308312
.get_vblank_timestamp = intel_crtc_get_vblank_timestamp,
309313
};
310314

315+
static void add_crtc_to_pipe_list(struct intel_display *display, struct intel_crtc *crtc)
316+
{
317+
struct intel_crtc *iter;
318+
319+
list_for_each_entry(iter, &display->pipe_list, pipe_head) {
320+
if (crtc->pipe < iter->pipe) {
321+
list_add_tail(&crtc->pipe_head, &iter->pipe_head);
322+
return;
323+
}
324+
}
325+
326+
list_add_tail(&crtc->pipe_head, &display->pipe_list);
327+
}
328+
311329
static int __intel_crtc_init(struct intel_display *display, enum pipe pipe)
312330
{
313331
struct intel_plane *primary, *cursor;
@@ -393,11 +411,11 @@ static int __intel_crtc_init(struct intel_display *display, enum pipe pipe)
393411

394412
cpu_latency_qos_add_request(&crtc->vblank_pm_qos, PM_QOS_DEFAULT_VALUE);
395413

396-
drm_WARN_ON(display->drm, drm_crtc_index(&crtc->base) != crtc->pipe);
397-
398414
if (HAS_CASF(display) && crtc->num_scalers >= 2)
399415
drm_crtc_create_sharpness_strength_property(&crtc->base);
400416

417+
add_crtc_to_pipe_list(display, crtc);
418+
401419
return 0;
402420

403421
fail:
@@ -406,6 +424,31 @@ static int __intel_crtc_init(struct intel_display *display, enum pipe pipe)
406424
return ret;
407425
}
408426

427+
#define HAS_PIPE(display, pipe) (DISPLAY_RUNTIME_INFO(display)->pipe_mask & BIT(pipe))
428+
429+
/*
430+
* Expose the pipes in order A, C, B, D on discrete platforms to trick user
431+
* space into using pipes that are more likely to be available for both a) user
432+
* space if pipe B has been reserved for the joiner, and b) the joiner if pipe A
433+
* doesn't need the joiner.
434+
*
435+
* Swap pipes B and C only if both are available i.e. not fused off.
436+
*/
437+
static enum pipe reorder_pipe(struct intel_display *display, enum pipe pipe)
438+
{
439+
if (!display->platform.dgfx || !HAS_PIPE(display, PIPE_B) || !HAS_PIPE(display, PIPE_C))
440+
return pipe;
441+
442+
switch (pipe) {
443+
case PIPE_B:
444+
return PIPE_C;
445+
case PIPE_C:
446+
return PIPE_B;
447+
default:
448+
return pipe;
449+
}
450+
}
451+
409452
int intel_crtc_init(struct intel_display *display)
410453
{
411454
enum pipe pipe;
@@ -415,7 +458,7 @@ int intel_crtc_init(struct intel_display *display)
415458
INTEL_NUM_PIPES(display), str_plural(INTEL_NUM_PIPES(display)));
416459

417460
for_each_pipe(display, pipe) {
418-
ret = __intel_crtc_init(display, pipe);
461+
ret = __intel_crtc_init(display, reorder_pipe(display, pipe));
419462
if (ret)
420463
return ret;
421464
}

drivers/gpu/drm/i915/display/intel_display.c

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5939,17 +5939,6 @@ static int intel_atomic_check_joiner(struct intel_atomic_state *state,
59395939
return -EINVAL;
59405940
}
59415941

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-
59535942
drm_dbg_kms(display->drm,
59545943
"[CRTC:%d:%s] Used as secondary for joiner primary [CRTC:%d:%s]\n",
59555944
secondary_crtc->base.base.id, secondary_crtc->base.name,
@@ -6327,9 +6316,7 @@ static int intel_atomic_check_config(struct intel_atomic_state *state,
63276316

63286317
for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) {
63296318
if (!intel_crtc_needs_modeset(new_crtc_state)) {
6330-
if (intel_crtc_is_joiner_secondary(new_crtc_state))
6331-
copy_joiner_crtc_state_nomodeset(state, crtc);
6332-
else
6319+
if (!intel_crtc_is_joiner_secondary(new_crtc_state))
63336320
intel_crtc_copy_uapi_to_hw_state_nomodeset(state, crtc);
63346321
continue;
63356322
}
@@ -6460,8 +6447,11 @@ int intel_atomic_check(struct drm_device *dev,
64606447
goto fail;
64616448

64626449
for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) {
6463-
if (!intel_crtc_needs_modeset(new_crtc_state))
6450+
if (!intel_crtc_needs_modeset(new_crtc_state)) {
6451+
if (intel_crtc_is_joiner_secondary(new_crtc_state))
6452+
copy_joiner_crtc_state_nomodeset(state, crtc);
64646453
continue;
6454+
}
64656455

64666456
if (intel_crtc_is_joiner_secondary(new_crtc_state)) {
64676457
drm_WARN_ON(display->drm, new_crtc_state->uapi.enable);

drivers/gpu/drm/i915/display/intel_display.h

Lines changed: 38 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -212,22 +212,23 @@ enum phy_fia {
212212
base.head) \
213213
for_each_if((intel_plane)->pipe == (intel_crtc)->pipe)
214214

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)
219219

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)
224+
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))
225228

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))
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))
231232

232233
#define for_each_intel_encoder(dev, intel_encoder) \
233234
list_for_each_entry(intel_encoder, \
@@ -269,14 +270,6 @@ enum phy_fia {
269270
(__i)++) \
270271
for_each_if(plane)
271272

272-
#define for_each_old_intel_crtc_in_state(__state, crtc, old_crtc_state, __i) \
273-
for ((__i) = 0; \
274-
(__i) < (__state)->base.dev->mode_config.num_crtc && \
275-
((crtc) = to_intel_crtc((__state)->base.crtcs[__i].ptr), \
276-
(old_crtc_state) = to_intel_crtc_state((__state)->base.crtcs[__i].old_state), 1); \
277-
(__i)++) \
278-
for_each_if(crtc)
279-
280273
#define for_each_new_intel_plane_in_state(__state, plane, new_plane_state, __i) \
281274
for ((__i) = 0; \
282275
(__i) < (__state)->base.dev->mode_config.num_total_plane && \
@@ -285,22 +278,6 @@ enum phy_fia {
285278
(__i)++) \
286279
for_each_if(plane)
287280

288-
#define for_each_new_intel_crtc_in_state(__state, crtc, new_crtc_state, __i) \
289-
for ((__i) = 0; \
290-
(__i) < (__state)->base.dev->mode_config.num_crtc && \
291-
((crtc) = to_intel_crtc((__state)->base.crtcs[__i].ptr), \
292-
(new_crtc_state) = to_intel_crtc_state((__state)->base.crtcs[__i].new_state), 1); \
293-
(__i)++) \
294-
for_each_if(crtc)
295-
296-
#define for_each_new_intel_crtc_in_state_reverse(__state, crtc, new_crtc_state, __i) \
297-
for ((__i) = (__state)->base.dev->mode_config.num_crtc - 1; \
298-
(__i) >= 0 && \
299-
((crtc) = to_intel_crtc((__state)->base.crtcs[__i].ptr), \
300-
(new_crtc_state) = to_intel_crtc_state((__state)->base.crtcs[__i].new_state), 1); \
301-
(__i)--) \
302-
for_each_if(crtc)
303-
304281
#define for_each_oldnew_intel_plane_in_state(__state, plane, old_plane_state, new_plane_state, __i) \
305282
for ((__i) = 0; \
306283
(__i) < (__state)->base.dev->mode_config.num_total_plane && \
@@ -310,23 +287,32 @@ enum phy_fia {
310287
(__i)++) \
311288
for_each_if(plane)
312289

290+
#define for_each_old_intel_crtc_in_state(__state, crtc, old_crtc_state, __i) \
291+
for_each_intel_crtc((__state)->base.dev, (crtc)) \
292+
for_each_if(((__i) = drm_crtc_index(&(crtc)->base), (void)(__i), \
293+
(old_crtc_state) = intel_atomic_get_old_crtc_state((__state), (crtc))))
294+
295+
#define for_each_new_intel_crtc_in_state(__state, crtc, new_crtc_state, __i) \
296+
for_each_intel_crtc((__state)->base.dev, (crtc)) \
297+
for_each_if(((__i) = drm_crtc_index(&(crtc)->base), (void)(__i), \
298+
(new_crtc_state) = intel_atomic_get_new_crtc_state((__state), (crtc))))
299+
300+
#define for_each_new_intel_crtc_in_state_reverse(__state, crtc, new_crtc_state, __i) \
301+
for_each_intel_crtc_reverse((__state)->base.dev, (crtc)) \
302+
for_each_if(((__i) = drm_crtc_index(&(crtc)->base), (void)(__i), \
303+
(new_crtc_state) = intel_atomic_get_new_crtc_state((__state), (crtc))))
304+
313305
#define for_each_oldnew_intel_crtc_in_state(__state, crtc, old_crtc_state, new_crtc_state, __i) \
314-
for ((__i) = 0; \
315-
(__i) < (__state)->base.dev->mode_config.num_crtc && \
316-
((crtc) = to_intel_crtc((__state)->base.crtcs[__i].ptr), \
317-
(old_crtc_state) = to_intel_crtc_state((__state)->base.crtcs[__i].old_state), \
318-
(new_crtc_state) = to_intel_crtc_state((__state)->base.crtcs[__i].new_state), 1); \
319-
(__i)++) \
320-
for_each_if(crtc)
306+
for_each_intel_crtc((__state)->base.dev, (crtc)) \
307+
for_each_if(((__i) = drm_crtc_index(&(crtc)->base), (void)(__i), \
308+
(old_crtc_state) = intel_atomic_get_old_crtc_state((__state), (crtc)), \
309+
(new_crtc_state) = intel_atomic_get_new_crtc_state((__state), (crtc))))
321310

322311
#define for_each_oldnew_intel_crtc_in_state_reverse(__state, crtc, old_crtc_state, new_crtc_state, __i) \
323-
for ((__i) = (__state)->base.dev->mode_config.num_crtc - 1; \
324-
(__i) >= 0 && \
325-
((crtc) = to_intel_crtc((__state)->base.crtcs[__i].ptr), \
326-
(old_crtc_state) = to_intel_crtc_state((__state)->base.crtcs[__i].old_state), \
327-
(new_crtc_state) = to_intel_crtc_state((__state)->base.crtcs[__i].new_state), 1); \
328-
(__i)--) \
329-
for_each_if(crtc)
312+
for_each_intel_crtc_reverse((__state)->base.dev, (crtc)) \
313+
for_each_if(((__i) = drm_crtc_index(&(crtc)->base), (void)(__i), \
314+
(old_crtc_state) = intel_atomic_get_old_crtc_state((__state), (crtc)), \
315+
(new_crtc_state) = intel_atomic_get_new_crtc_state((__state), (crtc))))
330316

331317
#define intel_atomic_crtc_state_for_each_plane_state( \
332318
plane, plane_state, \

drivers/gpu/drm/i915/display/intel_display_core.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,9 @@ struct intel_display {
294294
/* Parent, or core, driver functions exposed to display */
295295
const struct intel_display_parent_interface *parent;
296296

297+
/* list of all intel_crtcs sorted by pipe */
298+
struct list_head pipe_list;
299+
297300
/* Display functions */
298301
struct {
299302
/* Top level crtc-ish functions */

drivers/gpu/drm/i915/display/intel_display_driver.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ static void intel_mode_config_init(struct intel_display *display)
117117

118118
drm_mode_config_init(display->drm);
119119
INIT_LIST_HEAD(&display->global.obj_list);
120+
INIT_LIST_HEAD(&display->pipe_list);
120121

121122
mode_config->min_width = 0;
122123
mode_config->min_height = 0;

drivers/gpu/drm/i915/display/intel_display_types.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1484,6 +1484,7 @@ struct intel_flipq {
14841484

14851485
struct intel_crtc {
14861486
struct drm_crtc base;
1487+
struct list_head pipe_head;
14871488
enum pipe pipe;
14881489
/*
14891490
* Whether the crtc and the connected output pipeline is active. Implies

drivers/gpu/drm/xe/display/xe_display.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "intel_audio.h"
2222
#include "intel_bw.h"
2323
#include "intel_display.h"
24+
#include "intel_display_core.h"
2425
#include "intel_display_device.h"
2526
#include "intel_display_driver.h"
2627
#include "intel_display_irq.h"

0 commit comments

Comments
 (0)