mirror of
https://github.com/torvalds/linux.git
synced 2026-05-24 23:22:31 +02:00
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
This commit is contained in:
commit
993eb19140
|
|
@ -209,6 +209,8 @@ static struct intel_crtc *intel_crtc_alloc(void)
|
|||
crtc->base.state = &crtc_state->uapi;
|
||||
crtc->config = crtc_state;
|
||||
|
||||
INIT_LIST_HEAD(&crtc->pipe_head);
|
||||
|
||||
return crtc;
|
||||
}
|
||||
|
||||
|
|
@ -222,6 +224,8 @@ static void intel_crtc_destroy(struct drm_crtc *_crtc)
|
|||
{
|
||||
struct intel_crtc *crtc = to_intel_crtc(_crtc);
|
||||
|
||||
list_del(&crtc->pipe_head);
|
||||
|
||||
cpu_latency_qos_remove_request(&crtc->vblank_pm_qos);
|
||||
|
||||
drm_crtc_cleanup(&crtc->base);
|
||||
|
|
@ -308,6 +312,20 @@ static const struct drm_crtc_funcs i8xx_crtc_funcs = {
|
|||
.get_vblank_timestamp = intel_crtc_get_vblank_timestamp,
|
||||
};
|
||||
|
||||
static void add_crtc_to_pipe_list(struct intel_display *display, struct intel_crtc *crtc)
|
||||
{
|
||||
struct intel_crtc *iter;
|
||||
|
||||
list_for_each_entry(iter, &display->pipe_list, pipe_head) {
|
||||
if (crtc->pipe < iter->pipe) {
|
||||
list_add_tail(&crtc->pipe_head, &iter->pipe_head);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
list_add_tail(&crtc->pipe_head, &display->pipe_list);
|
||||
}
|
||||
|
||||
static int __intel_crtc_init(struct intel_display *display, enum pipe pipe)
|
||||
{
|
||||
struct intel_plane *primary, *cursor;
|
||||
|
|
@ -393,11 +411,11 @@ static int __intel_crtc_init(struct intel_display *display, enum pipe pipe)
|
|||
|
||||
cpu_latency_qos_add_request(&crtc->vblank_pm_qos, PM_QOS_DEFAULT_VALUE);
|
||||
|
||||
drm_WARN_ON(display->drm, drm_crtc_index(&crtc->base) != crtc->pipe);
|
||||
|
||||
if (HAS_CASF(display) && crtc->num_scalers >= 2)
|
||||
drm_crtc_create_sharpness_strength_property(&crtc->base);
|
||||
|
||||
add_crtc_to_pipe_list(display, crtc);
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
|
|
@ -406,6 +424,31 @@ static int __intel_crtc_init(struct intel_display *display, enum pipe pipe)
|
|||
return ret;
|
||||
}
|
||||
|
||||
#define HAS_PIPE(display, pipe) (DISPLAY_RUNTIME_INFO(display)->pipe_mask & BIT(pipe))
|
||||
|
||||
/*
|
||||
* Expose the pipes in order A, C, B, D on discrete platforms to trick user
|
||||
* space into using pipes that are more likely to be available for both a) user
|
||||
* space if pipe B has been reserved for the joiner, and b) the joiner if pipe A
|
||||
* doesn't need the joiner.
|
||||
*
|
||||
* Swap pipes B and C only if both are available i.e. not fused off.
|
||||
*/
|
||||
static enum pipe reorder_pipe(struct intel_display *display, enum pipe pipe)
|
||||
{
|
||||
if (!display->platform.dgfx || !HAS_PIPE(display, PIPE_B) || !HAS_PIPE(display, PIPE_C))
|
||||
return pipe;
|
||||
|
||||
switch (pipe) {
|
||||
case PIPE_B:
|
||||
return PIPE_C;
|
||||
case PIPE_C:
|
||||
return PIPE_B;
|
||||
default:
|
||||
return pipe;
|
||||
}
|
||||
}
|
||||
|
||||
int intel_crtc_init(struct intel_display *display)
|
||||
{
|
||||
enum pipe pipe;
|
||||
|
|
@ -415,7 +458,7 @@ int intel_crtc_init(struct intel_display *display)
|
|||
INTEL_NUM_PIPES(display), str_plural(INTEL_NUM_PIPES(display)));
|
||||
|
||||
for_each_pipe(display, pipe) {
|
||||
ret = __intel_crtc_init(display, pipe);
|
||||
ret = __intel_crtc_init(display, reorder_pipe(display, pipe));
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5939,17 +5939,6 @@ static int intel_atomic_check_joiner(struct intel_atomic_state *state,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* The state copy logic assumes the primary crtc gets processed
|
||||
* before the secondary crtc during the main compute_config loop.
|
||||
* This works because the crtcs are created in pipe order,
|
||||
* and the hardware requires primary pipe < secondary pipe as well.
|
||||
* Should that change we need to rethink the logic.
|
||||
*/
|
||||
if (WARN_ON(drm_crtc_index(&primary_crtc->base) >
|
||||
drm_crtc_index(&secondary_crtc->base)))
|
||||
return -EINVAL;
|
||||
|
||||
drm_dbg_kms(display->drm,
|
||||
"[CRTC:%d:%s] Used as secondary for joiner primary [CRTC:%d:%s]\n",
|
||||
secondary_crtc->base.base.id, secondary_crtc->base.name,
|
||||
|
|
@ -6327,9 +6316,7 @@ static int intel_atomic_check_config(struct intel_atomic_state *state,
|
|||
|
||||
for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) {
|
||||
if (!intel_crtc_needs_modeset(new_crtc_state)) {
|
||||
if (intel_crtc_is_joiner_secondary(new_crtc_state))
|
||||
copy_joiner_crtc_state_nomodeset(state, crtc);
|
||||
else
|
||||
if (!intel_crtc_is_joiner_secondary(new_crtc_state))
|
||||
intel_crtc_copy_uapi_to_hw_state_nomodeset(state, crtc);
|
||||
continue;
|
||||
}
|
||||
|
|
@ -6460,8 +6447,11 @@ int intel_atomic_check(struct drm_device *dev,
|
|||
goto fail;
|
||||
|
||||
for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) {
|
||||
if (!intel_crtc_needs_modeset(new_crtc_state))
|
||||
if (!intel_crtc_needs_modeset(new_crtc_state)) {
|
||||
if (intel_crtc_is_joiner_secondary(new_crtc_state))
|
||||
copy_joiner_crtc_state_nomodeset(state, crtc);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (intel_crtc_is_joiner_secondary(new_crtc_state)) {
|
||||
drm_WARN_ON(display->drm, new_crtc_state->uapi.enable);
|
||||
|
|
|
|||
|
|
@ -212,22 +212,23 @@ enum phy_fia {
|
|||
base.head) \
|
||||
for_each_if((intel_plane)->pipe == (intel_crtc)->pipe)
|
||||
|
||||
#define for_each_intel_crtc(dev, intel_crtc) \
|
||||
list_for_each_entry(intel_crtc, \
|
||||
&(dev)->mode_config.crtc_list, \
|
||||
base.head)
|
||||
#define for_each_intel_crtc(dev, crtc) \
|
||||
list_for_each_entry((crtc), \
|
||||
&to_intel_display(dev)->pipe_list, \
|
||||
pipe_head)
|
||||
|
||||
#define for_each_intel_crtc_in_pipe_mask(dev, intel_crtc, pipe_mask) \
|
||||
list_for_each_entry(intel_crtc, \
|
||||
&(dev)->mode_config.crtc_list, \
|
||||
base.head) \
|
||||
for_each_if((pipe_mask) & BIT(intel_crtc->pipe))
|
||||
#define for_each_intel_crtc_reverse(dev, crtc) \
|
||||
list_for_each_entry_reverse((crtc), \
|
||||
&to_intel_display(dev)->pipe_list, \
|
||||
pipe_head)
|
||||
|
||||
#define for_each_intel_crtc_in_pipe_mask_reverse(dev, intel_crtc, pipe_mask) \
|
||||
list_for_each_entry_reverse((intel_crtc), \
|
||||
&(dev)->mode_config.crtc_list, \
|
||||
base.head) \
|
||||
for_each_if((pipe_mask) & BIT((intel_crtc)->pipe))
|
||||
#define for_each_intel_crtc_in_pipe_mask(dev, crtc, pipe_mask) \
|
||||
for_each_intel_crtc((dev), (crtc)) \
|
||||
for_each_if((pipe_mask) & BIT((crtc)->pipe))
|
||||
|
||||
#define for_each_intel_crtc_in_pipe_mask_reverse(dev, crtc, pipe_mask) \
|
||||
for_each_intel_crtc_reverse((dev), (crtc)) \
|
||||
for_each_if((pipe_mask) & BIT((crtc)->pipe))
|
||||
|
||||
#define for_each_intel_encoder(dev, intel_encoder) \
|
||||
list_for_each_entry(intel_encoder, \
|
||||
|
|
@ -269,14 +270,6 @@ enum phy_fia {
|
|||
(__i)++) \
|
||||
for_each_if(plane)
|
||||
|
||||
#define for_each_old_intel_crtc_in_state(__state, crtc, old_crtc_state, __i) \
|
||||
for ((__i) = 0; \
|
||||
(__i) < (__state)->base.dev->mode_config.num_crtc && \
|
||||
((crtc) = to_intel_crtc((__state)->base.crtcs[__i].ptr), \
|
||||
(old_crtc_state) = to_intel_crtc_state((__state)->base.crtcs[__i].old_state), 1); \
|
||||
(__i)++) \
|
||||
for_each_if(crtc)
|
||||
|
||||
#define for_each_new_intel_plane_in_state(__state, plane, new_plane_state, __i) \
|
||||
for ((__i) = 0; \
|
||||
(__i) < (__state)->base.dev->mode_config.num_total_plane && \
|
||||
|
|
@ -285,22 +278,6 @@ enum phy_fia {
|
|||
(__i)++) \
|
||||
for_each_if(plane)
|
||||
|
||||
#define for_each_new_intel_crtc_in_state(__state, crtc, new_crtc_state, __i) \
|
||||
for ((__i) = 0; \
|
||||
(__i) < (__state)->base.dev->mode_config.num_crtc && \
|
||||
((crtc) = to_intel_crtc((__state)->base.crtcs[__i].ptr), \
|
||||
(new_crtc_state) = to_intel_crtc_state((__state)->base.crtcs[__i].new_state), 1); \
|
||||
(__i)++) \
|
||||
for_each_if(crtc)
|
||||
|
||||
#define for_each_new_intel_crtc_in_state_reverse(__state, crtc, new_crtc_state, __i) \
|
||||
for ((__i) = (__state)->base.dev->mode_config.num_crtc - 1; \
|
||||
(__i) >= 0 && \
|
||||
((crtc) = to_intel_crtc((__state)->base.crtcs[__i].ptr), \
|
||||
(new_crtc_state) = to_intel_crtc_state((__state)->base.crtcs[__i].new_state), 1); \
|
||||
(__i)--) \
|
||||
for_each_if(crtc)
|
||||
|
||||
#define for_each_oldnew_intel_plane_in_state(__state, plane, old_plane_state, new_plane_state, __i) \
|
||||
for ((__i) = 0; \
|
||||
(__i) < (__state)->base.dev->mode_config.num_total_plane && \
|
||||
|
|
@ -310,23 +287,32 @@ enum phy_fia {
|
|||
(__i)++) \
|
||||
for_each_if(plane)
|
||||
|
||||
#define for_each_old_intel_crtc_in_state(__state, crtc, old_crtc_state, __i) \
|
||||
for_each_intel_crtc((__state)->base.dev, (crtc)) \
|
||||
for_each_if(((__i) = drm_crtc_index(&(crtc)->base), (void)(__i), \
|
||||
(old_crtc_state) = intel_atomic_get_old_crtc_state((__state), (crtc))))
|
||||
|
||||
#define for_each_new_intel_crtc_in_state(__state, crtc, new_crtc_state, __i) \
|
||||
for_each_intel_crtc((__state)->base.dev, (crtc)) \
|
||||
for_each_if(((__i) = drm_crtc_index(&(crtc)->base), (void)(__i), \
|
||||
(new_crtc_state) = intel_atomic_get_new_crtc_state((__state), (crtc))))
|
||||
|
||||
#define for_each_new_intel_crtc_in_state_reverse(__state, crtc, new_crtc_state, __i) \
|
||||
for_each_intel_crtc_reverse((__state)->base.dev, (crtc)) \
|
||||
for_each_if(((__i) = drm_crtc_index(&(crtc)->base), (void)(__i), \
|
||||
(new_crtc_state) = intel_atomic_get_new_crtc_state((__state), (crtc))))
|
||||
|
||||
#define for_each_oldnew_intel_crtc_in_state(__state, crtc, old_crtc_state, new_crtc_state, __i) \
|
||||
for ((__i) = 0; \
|
||||
(__i) < (__state)->base.dev->mode_config.num_crtc && \
|
||||
((crtc) = to_intel_crtc((__state)->base.crtcs[__i].ptr), \
|
||||
(old_crtc_state) = to_intel_crtc_state((__state)->base.crtcs[__i].old_state), \
|
||||
(new_crtc_state) = to_intel_crtc_state((__state)->base.crtcs[__i].new_state), 1); \
|
||||
(__i)++) \
|
||||
for_each_if(crtc)
|
||||
for_each_intel_crtc((__state)->base.dev, (crtc)) \
|
||||
for_each_if(((__i) = drm_crtc_index(&(crtc)->base), (void)(__i), \
|
||||
(old_crtc_state) = intel_atomic_get_old_crtc_state((__state), (crtc)), \
|
||||
(new_crtc_state) = intel_atomic_get_new_crtc_state((__state), (crtc))))
|
||||
|
||||
#define for_each_oldnew_intel_crtc_in_state_reverse(__state, crtc, old_crtc_state, new_crtc_state, __i) \
|
||||
for ((__i) = (__state)->base.dev->mode_config.num_crtc - 1; \
|
||||
(__i) >= 0 && \
|
||||
((crtc) = to_intel_crtc((__state)->base.crtcs[__i].ptr), \
|
||||
(old_crtc_state) = to_intel_crtc_state((__state)->base.crtcs[__i].old_state), \
|
||||
(new_crtc_state) = to_intel_crtc_state((__state)->base.crtcs[__i].new_state), 1); \
|
||||
(__i)--) \
|
||||
for_each_if(crtc)
|
||||
for_each_intel_crtc_reverse((__state)->base.dev, (crtc)) \
|
||||
for_each_if(((__i) = drm_crtc_index(&(crtc)->base), (void)(__i), \
|
||||
(old_crtc_state) = intel_atomic_get_old_crtc_state((__state), (crtc)), \
|
||||
(new_crtc_state) = intel_atomic_get_new_crtc_state((__state), (crtc))))
|
||||
|
||||
#define intel_atomic_crtc_state_for_each_plane_state( \
|
||||
plane, plane_state, \
|
||||
|
|
|
|||
|
|
@ -294,6 +294,9 @@ struct intel_display {
|
|||
/* Parent, or core, driver functions exposed to display */
|
||||
const struct intel_display_parent_interface *parent;
|
||||
|
||||
/* list of all intel_crtcs sorted by pipe */
|
||||
struct list_head pipe_list;
|
||||
|
||||
/* Display functions */
|
||||
struct {
|
||||
/* Top level crtc-ish functions */
|
||||
|
|
|
|||
|
|
@ -117,6 +117,7 @@ static void intel_mode_config_init(struct intel_display *display)
|
|||
|
||||
drm_mode_config_init(display->drm);
|
||||
INIT_LIST_HEAD(&display->global.obj_list);
|
||||
INIT_LIST_HEAD(&display->pipe_list);
|
||||
|
||||
mode_config->min_width = 0;
|
||||
mode_config->min_height = 0;
|
||||
|
|
|
|||
|
|
@ -1484,6 +1484,7 @@ struct intel_flipq {
|
|||
|
||||
struct intel_crtc {
|
||||
struct drm_crtc base;
|
||||
struct list_head pipe_head;
|
||||
enum pipe pipe;
|
||||
/*
|
||||
* Whether the crtc and the connected output pipeline is active. Implies
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
#include "intel_audio.h"
|
||||
#include "intel_bw.h"
|
||||
#include "intel_display.h"
|
||||
#include "intel_display_core.h"
|
||||
#include "intel_display_device.h"
|
||||
#include "intel_display_driver.h"
|
||||
#include "intel_display_irq.h"
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user