Xe related:

- Fix Xe oops in suspend/shutdown when display was disabled (Jani)
 
 Display in general:
  - More general refactor towards display separation (Jani)
  - Preparation for fix Adaptive-Sync SDP for PR with Link ON + Auxless-ALPM (Ankit)
  - PSR related fixes and improvements (Jouni)
  - Use polling when irqs are unavailable (Michal)
  - Split bandwidth params into platform- and display-IP-specific structs (Gustavo)
  - Revert "drm/i915/backlight: Remove try_vesa_interface" (Suraj)
  - Casf & scaler refactoring (Michal)
  - Add support for pipe background color (Maarten)
  - General clean-ups (Maarten)
  - Sanitize DP link capability change handling (Imre)
  - Multiple BW QGV fixes (Ville)
 -----BEGIN PGP SIGNATURE-----
 
 iQEzBAABCgAdFiEEbSBwaO7dZQkcLOKj+mJfZA7rE8oFAmoYRLYACgkQ+mJfZA7r
 E8rtVQgArEfJhvSxvoALAQjfeM/mjWHj0AThfCxROed2Z1TO5WN+BB9hXzwGwEqA
 EE6TnKhDEQZy22a/t/iNhDDUy1UTYifMbfFAsdVz7NYfXKZpkRdJ4/mZk6MVEcrd
 jEbrIw8ZQ7SPTvhVdKn6zWvLzPskrJqzfIS4JFYJn61MepfD+QhOayoUxEU9gTjZ
 +SNSHu0lQSpwYwz+0AV65CkDwSbFZDqMLtDd8MxI0b4X8kjX1D9MH+QNu2wYnk7i
 9hqcErJ/jH/hMCNHwCIdPh6sfli8qpN7GbAdDcgkA+/E0hsJBkdJe2cSDGxUA/Ws
 76P8PjtZ3sGbq7vPL/Db6t0lY1yVJQ==
 =cTLp
 -----END PGP SIGNATURE-----

Merge tag 'drm-intel-next-2026-05-28' of https://gitlab.freedesktop.org/drm/i915/kernel into drm-next

Xe related:
 - Fix Xe oops in suspend/shutdown when display was disabled (Jani)

Display in general:
 - More general refactor towards display separation (Jani)
 - Preparation for fix Adaptive-Sync SDP for PR with Link ON + Auxless-ALPM (Ankit)
 - PSR related fixes and improvements (Jouni)
 - Use polling when irqs are unavailable (Michal)
 - Split bandwidth params into platform- and display-IP-specific structs (Gustavo)
 - Revert "drm/i915/backlight: Remove try_vesa_interface" (Suraj)
 - Casf & scaler refactoring (Michal)
 - Add support for pipe background color (Maarten)
 - General clean-ups (Maarten)
 - Sanitize DP link capability change handling (Imre)
 - Multiple BW QGV fixes (Ville)

Signed-off-by: Dave Airlie <airlied@redhat.com>

From: Rodrigo Vivi <rodrigo.vivi@intel.com>
Link: https://patch.msgid.link/ahhFE5Co5PdZQKG8@intel.com
This commit is contained in:
Dave Airlie 2026-06-03 09:09:11 +10:00
commit edbea3eff5
59 changed files with 1228 additions and 863 deletions

View File

@ -640,7 +640,7 @@ static struct intel_crtc *single_enabled_crtc(struct intel_display *display)
{
struct intel_crtc *crtc, *enabled = NULL;
for_each_intel_crtc(display->drm, crtc) {
for_each_intel_crtc(display, crtc) {
if (intel_crtc_active(crtc)) {
if (enabled)
return NULL;
@ -1393,7 +1393,7 @@ static void g4x_merge_wm(struct intel_display *display,
wm->hpll_en = true;
wm->fbc_en = true;
for_each_intel_crtc(display->drm, crtc) {
for_each_intel_crtc(display, crtc) {
const struct g4x_wm_state *wm_state = &crtc->wm.active.g4x;
if (!crtc->active)
@ -1415,7 +1415,7 @@ static void g4x_merge_wm(struct intel_display *display,
wm->fbc_en = false;
}
for_each_intel_crtc(display->drm, crtc) {
for_each_intel_crtc(display, crtc) {
const struct g4x_wm_state *wm_state = &crtc->wm.active.g4x;
enum pipe pipe = crtc->pipe;
@ -2034,7 +2034,7 @@ static void vlv_merge_wm(struct intel_display *display,
wm->level = display->wm.num_levels - 1;
wm->cxsr = true;
for_each_intel_crtc(display->drm, crtc) {
for_each_intel_crtc(display, crtc) {
const struct vlv_wm_state *wm_state = &crtc->wm.active.vlv;
if (!crtc->active)
@ -2053,7 +2053,7 @@ static void vlv_merge_wm(struct intel_display *display,
if (num_active_pipes > 1)
wm->level = VLV_WM_LEVEL_PM2;
for_each_intel_crtc(display->drm, crtc) {
for_each_intel_crtc(display, crtc) {
const struct vlv_wm_state *wm_state = &crtc->wm.active.vlv;
enum pipe pipe = crtc->pipe;
@ -3078,7 +3078,7 @@ static void ilk_merge_wm_level(struct intel_display *display,
ret_wm->enable = true;
for_each_intel_crtc(display->drm, crtc) {
for_each_intel_crtc(display, crtc) {
const struct intel_pipe_wm *active = &crtc->wm.active.ilk;
const struct intel_wm_level *wm = &active->wm[level];
@ -3218,7 +3218,7 @@ static void ilk_compute_wm_results(struct intel_display *display,
}
/* LP0 register values */
for_each_intel_crtc(display->drm, crtc) {
for_each_intel_crtc(display, crtc) {
enum pipe pipe = crtc->pipe;
const struct intel_pipe_wm *pipe_wm = &crtc->wm.active.ilk;
const struct intel_wm_level *r = &pipe_wm->wm[0];
@ -3416,7 +3416,7 @@ static void ilk_compute_wm_config(struct intel_display *display,
struct intel_crtc *crtc;
/* Compute the currently _active_ config */
for_each_intel_crtc(display->drm, crtc) {
for_each_intel_crtc(display, crtc) {
const struct intel_pipe_wm *wm = &crtc->wm.active.ilk;
if (!wm->pipe_enabled)
@ -3533,10 +3533,11 @@ static void ilk_pipe_wm_get_hw_state(struct intel_crtc *crtc)
static int ilk_sanitize_watermarks_add_affected(struct drm_atomic_commit *state)
{
struct intel_display *display = to_intel_display(state->dev);
struct drm_plane *plane;
struct intel_crtc *crtc;
for_each_intel_crtc(state->dev, crtc) {
for_each_intel_crtc(display, crtc) {
struct intel_crtc_state *crtc_state;
crtc_state = intel_atomic_get_crtc_state(state, crtc);
@ -3581,7 +3582,6 @@ void ilk_wm_sanitize(struct intel_display *display)
struct intel_crtc_state *crtc_state;
struct drm_modeset_acquire_ctx ctx;
int ret;
int i;
/* Only supported on platforms that use atomic watermark design */
if (!display->wm.funcs->optimize_watermarks)
@ -3619,7 +3619,7 @@ void ilk_wm_sanitize(struct intel_display *display)
goto fail;
/* Write calculated watermark values back */
for_each_new_intel_crtc_in_state(intel_state, crtc, crtc_state, i) {
for_each_new_intel_crtc_in_state(intel_state, crtc, crtc_state) {
crtc_state->wm.need_postvbl_update = true;
intel_optimize_watermarks(intel_state, crtc);
@ -3769,7 +3769,7 @@ static void g4x_wm_get_hw_state(struct intel_display *display)
wm->cxsr = intel_de_read(display, FW_BLC_SELF) & FW_BLC_SELF_EN;
for_each_intel_crtc(display->drm, crtc) {
for_each_intel_crtc(display, crtc) {
struct intel_crtc_state *crtc_state =
to_intel_crtc_state(crtc->base.state);
struct g4x_wm_state *active = &crtc->wm.active.g4x;
@ -3884,7 +3884,7 @@ static void g4x_wm_sanitize(struct intel_display *display)
}
}
for_each_intel_crtc(display->drm, crtc) {
for_each_intel_crtc(display, crtc) {
struct intel_crtc_state *crtc_state =
to_intel_crtc_state(crtc->base.state);
int ret;
@ -3951,7 +3951,7 @@ static void vlv_wm_get_hw_state(struct intel_display *display)
vlv_punit_put(display);
}
for_each_intel_crtc(display->drm, crtc) {
for_each_intel_crtc(display, crtc) {
struct intel_crtc_state *crtc_state =
to_intel_crtc_state(crtc->base.state);
struct vlv_wm_state *active = &crtc->wm.active.vlv;
@ -4033,7 +4033,7 @@ static void vlv_wm_sanitize(struct intel_display *display)
}
}
for_each_intel_crtc(display->drm, crtc) {
for_each_intel_crtc(display, crtc) {
struct intel_crtc_state *crtc_state =
to_intel_crtc_state(crtc->base.state);
int ret;
@ -4074,7 +4074,7 @@ static void ilk_wm_get_hw_state(struct intel_display *display)
ilk_init_lp_watermarks(display);
for_each_intel_crtc(display->drm, crtc)
for_each_intel_crtc(display, crtc)
ilk_pipe_wm_get_hw_state(crtc);
hw->wm_lp[0] = intel_de_read(display, WM1_LP_ILK);

View File

@ -11,6 +11,7 @@
#include "intel_crtc.h"
#include "intel_de.h"
#include "intel_display_types.h"
#include "intel_display_utils.h"
#include "intel_dp.h"
#include "intel_dp_aux.h"
#include "intel_psr.h"
@ -359,6 +360,23 @@ void intel_alpm_lobf_compute_config(struct intel_dp *intel_dp,
crtc_state->has_lobf = true;
}
static u32 get_pr_alpm_as_sdp_transmission_time(const struct intel_crtc_state *crtc_state)
{
u8 as_sdp_setup_time = intel_dp_as_sdp_transmission_time();
switch (as_sdp_setup_time) {
case DP_PR_AS_SDP_SETUP_TIME_T1:
return PR_ALPM_CTL_ADAPTIVE_SYNC_SDP_POSITION_T1;
case DP_PR_AS_SDP_SETUP_TIME_DYNAMIC:
return PR_ALPM_CTL_ADAPTIVE_SYNC_SDP_POSITION_T1_OR_T2;
case DP_PR_AS_SDP_SETUP_TIME_T2:
return PR_ALPM_CTL_ADAPTIVE_SYNC_SDP_POSITION_T2;
default:
MISSING_CASE(as_sdp_setup_time);
return PR_ALPM_CTL_ADAPTIVE_SYNC_SDP_POSITION_T1;
}
}
static void lnl_alpm_configure(struct intel_dp *intel_dp,
const struct intel_crtc_state *crtc_state)
{
@ -382,7 +400,7 @@ static void lnl_alpm_configure(struct intel_dp *intel_dp,
ALPM_CTL_AUX_LESS_WAKE_TIME(crtc_state->alpm_state.aux_less_wake_lines);
if (intel_dp->as_sdp_supported) {
u32 pr_alpm_ctl = PR_ALPM_CTL_ADAPTIVE_SYNC_SDP_POSITION_T1;
u32 pr_alpm_ctl = get_pr_alpm_as_sdp_transmission_time(crtc_state);
if (crtc_state->link_off_after_as_sdp_when_pr_active)
pr_alpm_ctl |= PR_ALPM_CTL_ALLOW_LINK_OFF_BETWEEN_AS_SDP_AND_SU;

View File

@ -200,9 +200,8 @@ bool intel_any_crtc_needs_modeset(struct intel_atomic_state *state)
{
struct intel_crtc *crtc;
struct intel_crtc_state *crtc_state;
int i;
for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i) {
for_each_new_intel_crtc_in_state(state, crtc, crtc_state) {
if (intel_crtc_needs_modeset(crtc_state))
return true;
}

View File

@ -67,25 +67,31 @@ struct intel_qgv_info {
u8 deinterleave;
};
static int dclk_freq_mhz(int ratio)
{
/* multiple of 16.666 MHz (100/6) */
return DIV_ROUND_CLOSEST(ratio * 100, 6);
}
static int dg1_mchbar_read_qgv_point_info(struct intel_display *display,
struct intel_qgv_point *sp,
int point)
{
u32 dclk_ratio, dclk_reference;
u32 dclk_ratio;
u32 val;
val = intel_mchbar_read(display, SA_PERF_STATUS_0_0_0_MCHBAR_PC);
dclk_ratio = REG_FIELD_GET(DG1_QCLK_RATIO_MASK, val);
if (val & DG1_QCLK_REFERENCE)
dclk_reference = 6; /* 6 * 16.666 MHz = 100 MHz */
dclk_ratio *= 6; /* 6 * 16.666 MHz = 100 MHz */
else
dclk_reference = 8; /* 8 * 16.666 MHz = 133 MHz */
sp->dclk = DIV_ROUND_UP((16667 * dclk_ratio * dclk_reference) + 500, 1000);
dclk_ratio *= 8; /* 8 * 16.666 MHz = 133 MHz */
val = intel_mchbar_read(display, SKL_MC_BIOS_DATA_0_0_0_MCHBAR_PCU);
if (val & DG1_GEAR_TYPE)
sp->dclk *= 2;
dclk_ratio *= 2;
sp->dclk = dclk_freq_mhz(dclk_ratio);
if (sp->dclk == 0)
return -EINVAL;
@ -107,7 +113,6 @@ static int icl_pcode_read_qgv_point_info(struct intel_display *display,
int point)
{
u32 val = 0, val2 = 0;
u16 dclk;
int ret;
ret = intel_parent_pcode_read(display, ICL_PCODE_MEM_SUBSYSYSTEM_INFO |
@ -116,9 +121,7 @@ static int icl_pcode_read_qgv_point_info(struct intel_display *display,
if (ret)
return ret;
dclk = val & 0xffff;
sp->dclk = DIV_ROUND_UP((16667 * dclk) + (DISPLAY_VER(display) >= 12 ? 500 : 0),
1000);
sp->dclk = dclk_freq_mhz(val & 0xffff);
sp->t_rp = (val & 0xff0000) >> 16;
sp->t_rcd = (val & 0xff000000) >> 24;
@ -208,12 +211,11 @@ static int mtl_read_qgv_point_info(struct intel_display *display,
struct intel_qgv_point *sp, int point)
{
u32 val, val2;
u16 dclk;
val = intel_de_read(display, MTL_MEM_SS_INFO_QGV_POINT_LOW(point));
val2 = intel_de_read(display, MTL_MEM_SS_INFO_QGV_POINT_HIGH(point));
dclk = REG_FIELD_GET(MTL_DCLK_MASK, val);
sp->dclk = DIV_ROUND_CLOSEST(16667 * dclk, 1000);
sp->dclk = dclk_freq_mhz(REG_FIELD_GET(MTL_DCLK_MASK, val));
sp->t_rp = REG_FIELD_GET(MTL_TRP_MASK, val);
sp->t_rcd = REG_FIELD_GET(MTL_TRCD_MASK, val);
@ -238,10 +240,15 @@ intel_read_qgv_point_info(struct intel_display *display,
return icl_pcode_read_qgv_point_info(display, sp, point);
}
static bool is_y_tile(struct intel_display *display)
{
/* assume Y tile may be used if supported */
return !HAS_4TILE(display);
}
static int icl_get_qgv_points(struct intel_display *display,
const struct dram_info *dram_info,
struct intel_qgv_info *qi,
bool is_y_tile)
struct intel_qgv_info *qi)
{
int i, ret;
@ -280,16 +287,16 @@ static int icl_get_qgv_points(struct intel_display *display,
} else if (DISPLAY_VER(display) >= 12) {
switch (dram_info->type) {
case INTEL_DRAM_DDR4:
qi->t_bl = is_y_tile ? 8 : 4;
qi->t_bl = is_y_tile(display) ? 8 : 4;
qi->max_numchannels = 2;
qi->channel_width = 64;
qi->deinterleave = is_y_tile ? 1 : 2;
qi->deinterleave = is_y_tile(display) ? 1 : 2;
break;
case INTEL_DRAM_DDR5:
qi->t_bl = is_y_tile ? 16 : 8;
qi->t_bl = is_y_tile(display) ? 16 : 8;
qi->max_numchannels = 4;
qi->channel_width = 32;
qi->deinterleave = is_y_tile ? 1 : 2;
qi->deinterleave = is_y_tile(display) ? 1 : 2;
break;
case INTEL_DRAM_LPDDR4:
if (display->platform.rocketlake) {
@ -304,7 +311,7 @@ static int icl_get_qgv_points(struct intel_display *display,
qi->t_bl = 16;
qi->max_numchannels = 8;
qi->channel_width = 16;
qi->deinterleave = is_y_tile ? 2 : 4;
qi->deinterleave = is_y_tile(display) ? 2 : 4;
break;
default:
qi->t_bl = 16;
@ -372,85 +379,144 @@ static int icl_sagv_max_dclk(const struct intel_qgv_info *qi)
return dclk;
}
struct intel_sa_info {
u16 displayrtids;
u8 deburst, deprogbwlimit, derating;
/*
* Bandwidth parameters that are tied to the SoC (as opposed to struct
* intel_display_bw_params).
*/
struct intel_soc_bw_params {
u8 deprogbwlimit;
u8 derating;
};
static const struct intel_sa_info icl_sa_info = {
.deburst = 8,
.deprogbwlimit = 25, /* GB/s */
.displayrtids = 128,
static const struct intel_soc_bw_params icl_bw_params = {
.deprogbwlimit = 25,
.derating = 10,
};
static const struct intel_sa_info tgl_sa_info = {
.deburst = 16,
.deprogbwlimit = 34, /* GB/s */
.displayrtids = 256,
static const struct intel_soc_bw_params tgl_bw_params = {
.deprogbwlimit = 34,
.derating = 10,
};
static const struct intel_sa_info rkl_sa_info = {
.deburst = 8,
.deprogbwlimit = 20, /* GB/s */
.displayrtids = 128,
static const struct intel_soc_bw_params rkl_bw_params = {
.deprogbwlimit = 20,
.derating = 10,
};
static const struct intel_sa_info adls_sa_info = {
.deburst = 16,
.deprogbwlimit = 38, /* GB/s */
.displayrtids = 256,
static const struct intel_soc_bw_params adl_s_bw_params = {
.deprogbwlimit = 38,
.derating = 10,
};
static const struct intel_sa_info adlp_sa_info = {
.deburst = 16,
.deprogbwlimit = 38, /* GB/s */
.displayrtids = 256,
static const struct intel_soc_bw_params adl_p_bw_params = {
.deprogbwlimit = 38,
.derating = 20,
};
static const struct intel_sa_info mtl_sa_info = {
.deburst = 32,
.deprogbwlimit = 38, /* GB/s */
.displayrtids = 256,
.derating = 10,
};
static const struct intel_sa_info xe2_hpd_sa_info = {
static const struct intel_soc_bw_params bmg_bw_params = {
.deprogbwlimit = 53,
.derating = 30,
.deprogbwlimit = 53,
/* Other values not used by simplified algorithm */
};
static const struct intel_sa_info xe2_hpd_ecc_sa_info = {
static const struct intel_soc_bw_params bmg_ecc_bw_params = {
.deprogbwlimit = 53,
.derating = 45,
.deprogbwlimit = 53,
/* Other values not used by simplified algorithm */
};
static const struct intel_sa_info xe3lpd_sa_info = {
.deburst = 32,
.deprogbwlimit = 65, /* GB/s */
.displayrtids = 256,
static const struct intel_soc_bw_params ptl_bw_params = {
.deprogbwlimit = 65,
.derating = 10,
};
static const struct intel_sa_info xe3lpd_3002_sa_info = {
.deburst = 32,
.deprogbwlimit = 22, /* GB/s */
.displayrtids = 256,
static const struct intel_soc_bw_params wcl_bw_params = {
.deprogbwlimit = 22,
.derating = 10,
};
static const struct intel_soc_bw_params *get_soc_bw_params(struct intel_display *display,
const struct dram_info *dram_info)
{
if (display->platform.icelake ||
display->platform.jasperlake ||
display->platform.elkhartlake)
return &icl_bw_params;
else if (display->platform.tigerlake ||
display->platform.dg1)
return &tgl_bw_params;
else if (display->platform.rocketlake)
return &rkl_bw_params;
else if (display->platform.alderlake_s ||
display->platform.meteorlake ||
display->platform.lunarlake)
return &adl_s_bw_params;
else if (display->platform.alderlake_p)
return &adl_p_bw_params;
else if (display->platform.battlemage &&
dram_info->type == INTEL_DRAM_GDDR_ECC)
return &bmg_ecc_bw_params;
else if (display->platform.battlemage)
return &bmg_bw_params;
else if (display->platform.pantherlake_wildcatlake)
return &wcl_bw_params;
else if (display->platform.pantherlake ||
display->platform.novalake)
return &ptl_bw_params;
return NULL;
}
/*
* Bandwidth parameters that are tied to the display IP (as opposed to struct
* intel_soc_bw_params).
*/
struct intel_display_bw_params {
u16 displayrtids;
u8 deburst;
};
static const struct intel_display_bw_params gen11_bw_params = {
.deburst = 8,
.displayrtids = 128,
};
static const struct intel_display_bw_params gen12_bw_params = {
.deburst = 16,
.displayrtids = 256,
};
static const struct intel_display_bw_params xelpdp_bw_params = {
.deburst = 32,
.displayrtids = 256,
};
static const struct intel_display_bw_params *get_display_bw_params(struct intel_display *display)
{
if (DISPLAY_VER(display) >= 14) {
return &xelpdp_bw_params;
} else if (DISPLAY_VER(display) >= 12) {
/*
* RKL's SoC was based on ICL and the display, even though being
* gen12, had changes to the memory interface to match gen11's,
* consequently inheriting gen11's display-specific bandwidth
* parameters.
*/
if (display->platform.rocketlake)
return &gen11_bw_params;
else
return &gen12_bw_params;
} else if (DISPLAY_VER(display) == 11) {
return &gen11_bw_params;
}
return NULL;
}
static int icl_get_bw_info(struct intel_display *display,
const struct dram_info *dram_info,
const struct intel_sa_info *sa)
const struct intel_soc_bw_params *soc_bw_params,
const struct intel_display_bw_params *display_bw_params)
{
struct intel_qgv_info qi = {};
bool is_y_tile = true; /* assume y tile may be used */
int num_channels = max_t(u8, 1, dram_info->num_channels);
int ipqdepth, ipqdepthpch = 16;
int dclk_max;
@ -458,7 +524,7 @@ static int icl_get_bw_info(struct intel_display *display,
int num_groups = ARRAY_SIZE(display->bw.max);
int i, ret;
ret = icl_get_qgv_points(display, dram_info, &qi, is_y_tile);
ret = icl_get_qgv_points(display, dram_info, &qi);
if (ret) {
drm_dbg_kms(display->drm,
"Failed to get memory subsystem information, ignoring bandwidth limits");
@ -466,16 +532,16 @@ static int icl_get_bw_info(struct intel_display *display,
}
dclk_max = icl_sagv_max_dclk(&qi);
maxdebw = min(sa->deprogbwlimit * 1000, dclk_max * 16 * 6 / 10);
ipqdepth = min(ipqdepthpch, sa->displayrtids / num_channels);
qi.deinterleave = DIV_ROUND_UP(num_channels, is_y_tile ? 4 : 2);
maxdebw = min(soc_bw_params->deprogbwlimit * 1000, dclk_max * 16 * 6 / 10);
ipqdepth = min(ipqdepthpch, display_bw_params->displayrtids / num_channels);
qi.deinterleave = DIV_ROUND_UP(num_channels, is_y_tile(display) ? 4 : 2);
for (i = 0; i < num_groups; i++) {
struct intel_bw_info *bi = &display->bw.max[i];
int clpchgroup;
int j;
clpchgroup = (sa->deburst * qi.deinterleave / num_channels) << i;
clpchgroup = (display_bw_params->deburst * qi.deinterleave / num_channels) << i;
bi->num_planes = (ipqdepth - clpchgroup) / clpchgroup + 1;
bi->num_qgv_points = qi.num_points;
@ -493,10 +559,10 @@ static int icl_get_bw_info(struct intel_display *display,
*/
ct = max_t(int, sp->t_rc, sp->t_rp + sp->t_rcd +
(clpchgroup - 1) * qi.t_bl + sp->t_rdpre);
bw = DIV_ROUND_UP(sp->dclk * clpchgroup * 32 * num_channels, ct);
bw = sp->dclk * clpchgroup * 32 * num_channels / ct;
bi->deratedbw[j] = min(maxdebw,
bw * (100 - sa->derating) / 100);
bw * (100 - soc_bw_params->derating) / 100);
drm_dbg_kms(display->drm,
"BW%d / QGV %d: num_planes=%d deratedbw=%u\n",
@ -516,21 +582,25 @@ static int icl_get_bw_info(struct intel_display *display,
return 0;
}
static int tgl_peakbw(int num_channels, int channel_width, int dclk)
{
return num_channels * (channel_width / 8) * dclk;
}
static int tgl_get_bw_info(struct intel_display *display,
const struct dram_info *dram_info,
const struct intel_sa_info *sa)
const struct intel_soc_bw_params *soc_bw_params,
const struct intel_display_bw_params *display_bw_params)
{
struct intel_qgv_info qi = {};
bool is_y_tile = true; /* assume y tile may be used */
int num_channels = max_t(u8, 1, dram_info->num_channels);
int ipqdepth, ipqdepthpch = 16;
int dclk_max;
int maxdebw, peakbw;
int clperchgroup;
int num_groups = ARRAY_SIZE(display->bw.max);
int i, ret;
ret = icl_get_qgv_points(display, dram_info, &qi, is_y_tile);
ret = icl_get_qgv_points(display, dram_info, &qi);
if (ret) {
drm_dbg_kms(display->drm,
"Failed to get memory subsystem information, ignoring bandwidth limits");
@ -541,27 +611,23 @@ static int tgl_get_bw_info(struct intel_display *display,
(dram_info->type == INTEL_DRAM_LPDDR4 || dram_info->type == INTEL_DRAM_LPDDR5))
num_channels *= 2;
qi.deinterleave = qi.deinterleave ? : DIV_ROUND_UP(num_channels, is_y_tile ? 4 : 2);
if (num_channels < qi.max_numchannels && DISPLAY_VER(display) >= 12)
qi.deinterleave = max(DIV_ROUND_UP(qi.deinterleave, 2), 1);
qi.deinterleave = max(qi.deinterleave / 2, 1);
if (DISPLAY_VER(display) >= 12 && num_channels > qi.max_numchannels)
drm_warn(display->drm, "Number of channels exceeds max number of channels.");
if (qi.max_numchannels != 0)
num_channels = min_t(u8, num_channels, qi.max_numchannels);
dclk_max = icl_sagv_max_dclk(&qi);
peakbw = tgl_peakbw(num_channels, qi.channel_width, icl_sagv_max_dclk(&qi));
maxdebw = min(soc_bw_params->deprogbwlimit * 1000, peakbw * DEPROGBWPCLIMIT / 100);
peakbw = num_channels * DIV_ROUND_UP(qi.channel_width, 8) * dclk_max;
maxdebw = min(sa->deprogbwlimit * 1000, peakbw * DEPROGBWPCLIMIT / 100);
ipqdepth = min(ipqdepthpch, sa->displayrtids / num_channels);
ipqdepth = min(ipqdepthpch, display_bw_params->displayrtids / num_channels);
/*
* clperchgroup = 4kpagespermempage * clperchperblock,
* clperchperblock = 8 / num_channels * interleave
*/
clperchgroup = 4 * DIV_ROUND_UP(8, num_channels) * qi.deinterleave;
clperchgroup = 4 * (8 / num_channels) * qi.deinterleave;
for (i = 0; i < num_groups; i++) {
struct intel_bw_info *bi = &display->bw.max[i];
@ -569,14 +635,13 @@ static int tgl_get_bw_info(struct intel_display *display,
int clpchgroup;
int j;
clpchgroup = (sa->deburst * qi.deinterleave / num_channels) << i;
clpchgroup = (display_bw_params->deburst * qi.deinterleave / num_channels) << i;
if (i < num_groups - 1) {
bi_next = &display->bw.max[i + 1];
if (clpchgroup < clperchgroup)
bi_next->num_planes = (ipqdepth - clpchgroup) /
clpchgroup + 1;
bi_next->num_planes = (ipqdepth - clpchgroup) / clpchgroup;
else
bi_next->num_planes = 0;
}
@ -596,13 +661,11 @@ static int tgl_get_bw_info(struct intel_display *display,
*/
ct = max_t(int, sp->t_rc, sp->t_rp + sp->t_rcd +
(clpchgroup - 1) * qi.t_bl + sp->t_rdpre);
bw = DIV_ROUND_UP(sp->dclk * clpchgroup * 32 * num_channels, ct);
bw = sp->dclk * clpchgroup * 32 * num_channels / ct;
bi->deratedbw[j] = min(maxdebw,
bw * (100 - sa->derating) / 100);
bi->peakbw[j] = DIV_ROUND_CLOSEST(sp->dclk *
num_channels *
qi.channel_width, 8);
bw * (100 - soc_bw_params->derating) / 100);
bi->peakbw[j] = tgl_peakbw(num_channels, qi.channel_width, sp->dclk);
drm_dbg_kms(display->drm,
"BW%d / QGV %d: num_planes=%d deratedbw=%u peakbw: %u\n",
@ -661,29 +724,29 @@ static void dg2_get_bw_info(struct intel_display *display)
static int xe2_hpd_get_bw_info(struct intel_display *display,
const struct dram_info *dram_info,
const struct intel_sa_info *sa)
const struct intel_soc_bw_params *soc_bw_params)
{
struct intel_qgv_info qi = {};
int num_channels = dram_info->num_channels;
int peakbw, maxdebw;
int ret, i;
ret = icl_get_qgv_points(display, dram_info, &qi, true);
ret = icl_get_qgv_points(display, dram_info, &qi);
if (ret) {
drm_dbg_kms(display->drm,
"Failed to get memory subsystem information, ignoring bandwidth limits");
return ret;
}
peakbw = num_channels * qi.channel_width / 8 * icl_sagv_max_dclk(&qi);
maxdebw = min(sa->deprogbwlimit * 1000, peakbw * DEPROGBWPCLIMIT / 10);
peakbw = tgl_peakbw(num_channels, qi.channel_width, icl_sagv_max_dclk(&qi));
maxdebw = min(soc_bw_params->deprogbwlimit * 1000, peakbw * DEPROGBWPCLIMIT / 100);
for (i = 0; i < qi.num_points; i++) {
const struct intel_qgv_point *point = &qi.points[i];
int bw = num_channels * (qi.channel_width / 8) * point->dclk;
const struct intel_qgv_point *sp = &qi.points[i];
int bw = tgl_peakbw(num_channels, qi.channel_width, sp->dclk);
display->bw.max[0].deratedbw[i] =
min(maxdebw, (100 - sa->derating) * bw / 100);
min(maxdebw, (100 - soc_bw_params->derating) * bw / 100);
display->bw.max[0].peakbw[i] = bw;
drm_dbg_kms(display->drm, "QGV %d: deratedbw=%u peakbw: %u\n",
@ -741,11 +804,6 @@ static unsigned int tgl_max_bw_index(struct intel_display *display,
{
int i;
/*
* Let's return max bw for 0 planes
*/
num_planes = max(1, num_planes);
for (i = ARRAY_SIZE(display->bw.max) - 1; i >= 0; i--) {
const struct intel_bw_info *bi =
&display->bw.max[i];
@ -791,11 +849,17 @@ static unsigned int icl_qgv_bw(struct intel_display *display,
void intel_bw_init_hw(struct intel_display *display)
{
const struct dram_info *dram_info = intel_dram_info(display);
const struct dram_info *dram_info;
const struct intel_soc_bw_params *soc_bw_params;
const struct intel_display_bw_params *display_bw_params;
if (!HAS_DISPLAY(display))
return;
dram_info = intel_dram_info(display);
soc_bw_params = get_soc_bw_params(display, dram_info);
display_bw_params = get_display_bw_params(display);
/*
* Starting with Xe3p_LPD, the hardware tells us whether memory has ECC
* enabled that would impact display bandwidth. However, so far there
@ -805,30 +869,14 @@ void intel_bw_init_hw(struct intel_display *display)
if (DISPLAY_VER(display) >= 35)
drm_WARN_ON(display->drm, dram_info->ecc_impacting_de_bw);
if (DISPLAY_VER(display) >= 30) {
if (DISPLAY_VERx100(display) == 3002)
tgl_get_bw_info(display, dram_info, &xe3lpd_3002_sa_info);
else
tgl_get_bw_info(display, dram_info, &xe3lpd_sa_info);
} else if (DISPLAY_VERx100(display) >= 1401 && display->platform.dgfx) {
if (dram_info->type == INTEL_DRAM_GDDR_ECC)
xe2_hpd_get_bw_info(display, dram_info, &xe2_hpd_ecc_sa_info);
else
xe2_hpd_get_bw_info(display, dram_info, &xe2_hpd_sa_info);
} else if (DISPLAY_VER(display) >= 14) {
tgl_get_bw_info(display, dram_info, &mtl_sa_info);
if (DISPLAY_VERx100(display) >= 1401 && display->platform.dgfx) {
xe2_hpd_get_bw_info(display, dram_info, soc_bw_params);
} else if (display->platform.dg2) {
dg2_get_bw_info(display);
} else if (display->platform.alderlake_p) {
tgl_get_bw_info(display, dram_info, &adlp_sa_info);
} else if (display->platform.alderlake_s) {
tgl_get_bw_info(display, dram_info, &adls_sa_info);
} else if (display->platform.rocketlake) {
tgl_get_bw_info(display, dram_info, &rkl_sa_info);
} else if (DISPLAY_VER(display) == 12) {
tgl_get_bw_info(display, dram_info, &tgl_sa_info);
} else if (DISPLAY_VER(display) >= 12) {
tgl_get_bw_info(display, dram_info, soc_bw_params, display_bw_params);
} else if (DISPLAY_VER(display) == 11) {
icl_get_bw_info(display, dram_info, &icl_sa_info);
icl_get_bw_info(display, dram_info, soc_bw_params, display_bw_params);
}
}
@ -1103,7 +1151,7 @@ static int mtl_find_qgv_points(struct intel_display *display,
}
/* MTL PM DEMAND expects QGV BW parameter in multiples of 100 mbps */
new_bw_state->qgv_point_peakbw = DIV_ROUND_CLOSEST(qgv_peak_bw, 100);
new_bw_state->qgv_point_peakbw = qgv_peak_bw / 100;
return 0;
}
@ -1219,10 +1267,8 @@ static int intel_bw_check_data_rate(struct intel_atomic_state *state, bool *chan
struct intel_display *display = to_intel_display(state);
const struct intel_crtc_state *new_crtc_state, *old_crtc_state;
struct intel_crtc *crtc;
int i;
for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state,
new_crtc_state, i) {
for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state) {
unsigned int old_data_rate =
intel_crtc_bw_data_rate(old_crtc_state);
unsigned int new_data_rate =
@ -1268,10 +1314,9 @@ static int intel_bw_check_sagv_mask(struct intel_atomic_state *state)
const struct intel_bw_state *old_bw_state = NULL;
struct intel_bw_state *new_bw_state = NULL;
struct intel_crtc *crtc;
int ret, i;
int ret;
for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state,
new_crtc_state, i) {
for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state) {
if (intel_crtc_can_enable_sagv(old_crtc_state) ==
intel_crtc_can_enable_sagv(new_crtc_state))
continue;
@ -1378,7 +1423,7 @@ void intel_bw_update_hw_state(struct intel_display *display)
bw_state->pipe_sagv_reject = 0;
for_each_intel_crtc(display->drm, crtc) {
for_each_intel_crtc(display, crtc) {
const struct intel_crtc_state *crtc_state =
to_intel_crtc_state(crtc->base.state);
enum pipe pipe = crtc->pipe;

View File

@ -88,7 +88,7 @@ static void intel_casf_compute_win_size(struct intel_crtc_state *crtc_state)
crtc_state->pch_pfit.casf.win_size = SHARPNESS_FILTER_SIZE_7X7;
}
static void intel_casf_scaler_compute_coef(struct intel_crtc_state *crtc_state);
static void intel_casf_scaler_compute_coeff(struct intel_crtc_state *crtc_state);
int intel_casf_compute_config(struct intel_crtc_state *crtc_state)
{
@ -118,7 +118,7 @@ int intel_casf_compute_config(struct intel_crtc_state *crtc_state)
intel_casf_compute_win_size(crtc_state);
intel_casf_scaler_compute_coef(crtc_state);
intel_casf_scaler_compute_coeff(crtc_state);
return 0;
}
@ -148,12 +148,12 @@ static int casf_coeff_tap(int i)
return i % SCALER_FILTER_NUM_TAPS;
}
static u32 casf_coeff(const struct intel_crtc_state *crtc_state, int t)
static u32 casf_coeff(const struct intel_crtc_state *crtc_state, int tap)
{
struct scaler_filter_coeff value;
u32 coeff;
value = crtc_state->pch_pfit.casf.coeff[t];
value = crtc_state->pch_pfit.casf.coeff[tap];
value.sign = 0;
coeff = value.sign << 15 | value.exp << 12 | value.mantissa << 3;
@ -162,7 +162,7 @@ static u32 casf_coeff(const struct intel_crtc_state *crtc_state, int t)
/*
* 17 phase of 7 taps requires 119 coefficients in 60 dwords per set.
* To enable casf: program scaler coefficients with the coeffients
* To enable casf: program scaler coefficients with the coefficients
* that are calculated and stored in pch_pfit.casf.coeff as per
* SCALER_COEFFICIENT_FORMAT
*/
@ -183,20 +183,20 @@ static void intel_casf_write_coeff(const struct intel_crtc_state *crtc_state)
for (i = 0; i < 17 * SCALER_FILTER_NUM_TAPS; i += 2) {
u32 tmp;
int t;
int tap;
t = casf_coeff_tap(i);
tmp = casf_coeff(crtc_state, t);
tap = casf_coeff_tap(i);
tmp = casf_coeff(crtc_state, tap);
t = casf_coeff_tap(i + 1);
tmp |= casf_coeff(crtc_state, t) << 16;
tap = casf_coeff_tap(i + 1);
tmp |= casf_coeff(crtc_state, tap) << 16;
intel_de_write_fw(display, GLK_PS_COEF_DATA_SET(crtc->pipe, id, 0),
tmp);
}
}
static void convert_sharpness_coef_binary(struct scaler_filter_coeff *coeff,
static void convert_sharpness_coeff_binary(struct scaler_filter_coeff *coeff,
u16 coefficient)
{
if (coefficient < 25) {
@ -214,11 +214,11 @@ static void convert_sharpness_coef_binary(struct scaler_filter_coeff *coeff,
}
}
static void intel_casf_scaler_compute_coef(struct intel_crtc_state *crtc_state)
static void intel_casf_scaler_compute_coeff(struct intel_crtc_state *crtc_state)
{
const u16 *filtercoeff;
u16 filter_coeff[SCALER_FILTER_NUM_TAPS];
u16 sumcoeff = 0;
u16 sum_coeff = 0;
int i;
if (crtc_state->pch_pfit.casf.win_size == 0)
@ -229,11 +229,11 @@ static void intel_casf_scaler_compute_coef(struct intel_crtc_state *crtc_state)
filtercoeff = filtercoeff_3;
for (i = 0; i < SCALER_FILTER_NUM_TAPS; i++)
sumcoeff += *(filtercoeff + i);
sum_coeff += *(filtercoeff + i);
for (i = 0; i < SCALER_FILTER_NUM_TAPS; i++) {
filter_coeff[i] = (*(filtercoeff + i) * 100 / sumcoeff);
convert_sharpness_coef_binary(&crtc_state->pch_pfit.casf.coeff[i],
filter_coeff[i] = (*(filtercoeff + i) * 100 / sum_coeff);
convert_sharpness_coeff_binary(&crtc_state->pch_pfit.casf.coeff[i],
filter_coeff[i]);
}
}

View File

@ -3124,10 +3124,9 @@ static int bxt_compute_min_voltage_level(struct intel_atomic_state *state)
struct intel_crtc *crtc;
struct intel_crtc_state *crtc_state;
u8 min_voltage_level;
int i;
enum pipe pipe;
for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i) {
for_each_new_intel_crtc_in_state(state, crtc, crtc_state) {
int ret;
if (crtc_state->hw.enable)
@ -3219,13 +3218,13 @@ static int skl_dpll0_vco(struct intel_atomic_state *state)
intel_atomic_get_new_cdclk_state(state);
struct intel_crtc *crtc;
struct intel_crtc_state *crtc_state;
int vco, i;
int vco;
vco = cdclk_state->logical.vco;
if (!vco)
vco = display->cdclk.skl_preferred_vco_freq;
for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i) {
for_each_new_intel_crtc_in_state(state, crtc, crtc_state) {
if (!crtc_state->hw.enable)
continue;
@ -3424,10 +3423,9 @@ static int intel_crtcs_calc_min_cdclk(struct intel_atomic_state *state,
const struct intel_crtc_state *old_crtc_state;
const struct intel_crtc_state *new_crtc_state;
struct intel_crtc *crtc;
int i, ret;
int ret;
for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state,
new_crtc_state, i) {
for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state) {
ret = intel_cdclk_update_crtc_min_cdclk(state, crtc,
old_crtc_state->min_cdclk,
new_crtc_state->min_cdclk,
@ -3647,7 +3645,7 @@ void intel_cdclk_update_hw_state(struct intel_display *display)
cdclk_state->enabled_pipes = 0;
cdclk_state->active_pipes = 0;
for_each_intel_crtc(display->drm, crtc) {
for_each_intel_crtc(display, crtc) {
const struct intel_crtc_state *crtc_state =
to_intel_crtc_state(crtc->base.state);
enum pipe pipe = crtc->pipe;

View File

@ -1102,19 +1102,37 @@ static void skl_get_config(struct intel_crtc_state *crtc_state)
{
struct intel_display *display = to_intel_display(crtc_state);
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
u32 color;
crtc_state->gamma_mode = hsw_read_gamma_mode(crtc);
crtc_state->csc_mode = ilk_read_csc_mode(crtc);
color = intel_de_read(display, SKL_BOTTOM_COLOR(crtc->pipe));
if (DISPLAY_VER(display) < 35) {
u32 tmp = intel_de_read(display, SKL_BOTTOM_COLOR(crtc->pipe));
if (tmp & SKL_BOTTOM_COLOR_GAMMA_ENABLE)
if (color & SKL_BOTTOM_COLOR_GAMMA_ENABLE)
crtc_state->gamma_enable = true;
if (tmp & SKL_BOTTOM_COLOR_CSC_ENABLE)
if (color & SKL_BOTTOM_COLOR_CSC_ENABLE)
crtc_state->csc_enable = true;
}
crtc_state->hw.background_color = color & GENMASK(29, 0);
}
u32 intel_color_background_color_drm_to_hw(u64 drm_background_color)
{
return (DRM_ARGB64_GETR_BPC(drm_background_color, 10) << 20) |
(DRM_ARGB64_GETG_BPC(drm_background_color, 10) << 10) |
(DRM_ARGB64_GETB_BPC(drm_background_color, 10));
}
u64 intel_color_background_color_hw_to_drm(u32 hw_background_color)
{
u16 r = (hw_background_color >> 20) & 0x3ff;
u16 g = (hw_background_color >> 10) & 0x3ff;
u16 b = hw_background_color & 0x3ff;
return DRM_ARGB64_PREP_BPC(0x3ff, r, g, b, 10);
}
static void skl_color_commit_arm(struct intel_dsb *dsb,
@ -1123,16 +1141,11 @@ static void skl_color_commit_arm(struct intel_dsb *dsb,
struct intel_display *display = to_intel_display(crtc_state);
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
enum pipe pipe = crtc->pipe;
u32 val = 0;
u32 val = crtc_state->hw.background_color;
if (crtc_state->has_psr)
ilk_load_csc_matrix(dsb, crtc_state);
/*
* We don't (yet) allow userspace to control the pipe background color,
* so force it to black, but apply pipe gamma and CSC appropriately
* so that its handling will match how we program our planes.
*/
if (crtc_state->gamma_enable)
val |= SKL_BOTTOM_COLOR_GAMMA_ENABLE;
if (crtc_state->csc_enable)
@ -1151,11 +1164,7 @@ static void icl_color_commit_arm(struct intel_dsb *dsb,
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
enum pipe pipe = crtc->pipe;
/*
* We don't (yet) allow userspace to control the pipe background color,
* so force it to black.
*/
intel_de_write_dsb(display, dsb, SKL_BOTTOM_COLOR(pipe), 0);
intel_de_write_dsb(display, dsb, SKL_BOTTOM_COLOR(pipe), crtc_state->hw.background_color);
intel_de_write_dsb(display, dsb, GAMMA_MODE(crtc->pipe), crtc_state->gamma_mode);
@ -2107,9 +2116,15 @@ int intel_color_check(struct intel_atomic_state *state,
* May need to update pipe gamma enable bits
* when C8 planes are getting enabled/disabled.
*/
if (!old_crtc_state->c8_planes != !new_crtc_state->c8_planes)
if (!old_crtc_state->c8_planes != !new_crtc_state->c8_planes ||
old_crtc_state->hw.background_color != new_crtc_state->hw.background_color)
new_crtc_state->uapi.color_mgmt_changed = true;
if (DRM_ARGB64_GETA(new_crtc_state->uapi.background_color) != 0xffff) {
drm_dbg_kms(display->drm, "New background not completely opaque\n");
return -EINVAL;
}
if (!intel_crtc_needs_color_update(new_crtc_state))
return 0;
@ -3976,7 +3991,7 @@ xelpd_program_plane_pre_csc_lut(struct intel_dsb *dsb,
intel_de_write_dsb(display, dsb,
PLANE_PRE_CSC_GAMC_DATA_ENH(pipe, plane, 0),
(1 << 24));
} while (i++ > 130);
} while (i++ < 130);
} else {
for (i = 0; i < lut_size; i++) {
u32 v = (i * ((1 << 24) - 1)) / (lut_size - 1);

View File

@ -47,4 +47,7 @@ void intel_color_plane_program_pipeline(struct intel_dsb *dsb,
void intel_color_plane_commit_arm(struct intel_dsb *dsb,
const struct intel_plane_state *plane_state);
bool intel_color_crtc_has_3dlut(struct intel_display *display, enum pipe pipe);
u32 intel_color_background_color_drm_to_hw(u64 drm_background_color);
u64 intel_color_background_color_hw_to_drm(u32 hw_background_color);
#endif /* __INTEL_COLOR_H__ */

View File

@ -7,6 +7,7 @@
#include <linux/slab.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_blend.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_plane.h>
#include <drm/drm_print.h>
@ -55,7 +56,7 @@ struct intel_crtc *intel_crtc_for_pipe(struct intel_display *display,
{
struct intel_crtc *crtc;
for_each_intel_crtc(display->drm, crtc) {
for_each_intel_crtc(display, crtc) {
if (crtc->pipe == pipe)
return crtc;
}
@ -405,6 +406,9 @@ static int __intel_crtc_init(struct intel_display *display, enum pipe pipe)
BIT(DRM_SCALING_FILTER_DEFAULT) |
BIT(DRM_SCALING_FILTER_NEAREST_NEIGHBOR));
if (DISPLAY_VER(display) >= 9)
drm_crtc_attach_background_color_property(&crtc->base);
intel_color_crtc_init(crtc);
intel_drrs_crtc_init(crtc);
intel_crtc_crc_init(crtc);
@ -534,9 +538,8 @@ void intel_wait_for_vblank_workers(struct intel_atomic_state *state)
{
struct intel_crtc_state *crtc_state;
struct intel_crtc *crtc;
int i;
for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i) {
for_each_new_intel_crtc_in_state(state, crtc, crtc_state) {
if (!intel_crtc_needs_vblank_work(crtc_state))
continue;
@ -828,10 +831,8 @@ bool intel_any_crtc_enable_changed(struct intel_atomic_state *state)
{
const struct intel_crtc_state *old_crtc_state, *new_crtc_state;
struct intel_crtc *crtc;
int i;
for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state,
new_crtc_state, i) {
for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state) {
if (intel_crtc_enable_changed(old_crtc_state, new_crtc_state))
return true;
}
@ -849,10 +850,8 @@ bool intel_any_crtc_active_changed(struct intel_atomic_state *state)
{
const struct intel_crtc_state *old_crtc_state, *new_crtc_state;
struct intel_crtc *crtc;
int i;
for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state,
new_crtc_state, i) {
for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state) {
if (intel_crtc_active_changed(old_crtc_state, new_crtc_state))
return true;
}

View File

@ -184,13 +184,12 @@ int intel_dbuf_bw_calc_min_cdclk(struct intel_atomic_state *state,
const struct intel_crtc_state *old_crtc_state;
const struct intel_crtc_state *new_crtc_state;
struct intel_crtc *crtc;
int ret, i;
int ret;
if (DISPLAY_VER(display) < 9)
return 0;
for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state,
new_crtc_state, i) {
for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state) {
struct intel_dbuf_bw old_dbuf_bw, new_dbuf_bw;
skl_crtc_calc_dbuf_bw(&old_dbuf_bw, old_crtc_state);
@ -236,7 +235,7 @@ void intel_dbuf_bw_update_hw_state(struct intel_display *display)
if (DISPLAY_VER(display) < 9)
return;
for_each_intel_crtc(display->drm, crtc) {
for_each_intel_crtc(display, crtc) {
const struct intel_crtc_state *crtc_state =
to_intel_crtc_state(crtc->base.state);

View File

@ -3230,9 +3230,8 @@ static void intel_ddi_post_disable_hdmi_or_sst(struct intel_atomic_state *state,
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
struct intel_crtc *pipe_crtc;
bool is_hdmi = intel_crtc_has_type(old_crtc_state, INTEL_OUTPUT_HDMI);
int i;
for_each_pipe_crtc_modeset_disable(display, pipe_crtc, old_crtc_state, i) {
for_each_pipe_crtc_modeset_disable(display, pipe_crtc, old_crtc_state) {
const struct intel_crtc_state *old_pipe_crtc_state =
intel_atomic_get_old_crtc_state(state, pipe_crtc);
@ -3259,7 +3258,7 @@ static void intel_ddi_post_disable_hdmi_or_sst(struct intel_atomic_state *state,
intel_ddi_disable_transcoder_func(old_crtc_state);
for_each_pipe_crtc_modeset_disable(display, pipe_crtc, old_crtc_state, i) {
for_each_pipe_crtc_modeset_disable(display, pipe_crtc, old_crtc_state) {
const struct intel_crtc_state *old_pipe_crtc_state =
intel_atomic_get_old_crtc_state(state, pipe_crtc);
@ -3516,7 +3515,6 @@ static void intel_ddi_enable(struct intel_atomic_state *state,
struct intel_crtc *pipe_crtc;
enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
bool is_hdmi = intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI);
int i;
/* 128b/132b SST */
if (!is_hdmi && intel_dp_is_uhbr(crtc_state)) {
@ -3550,7 +3548,7 @@ static void intel_ddi_enable(struct intel_atomic_state *state,
intel_ddi_wait_for_fec_status(encoder, crtc_state, true);
for_each_pipe_crtc_modeset_enable(display, pipe_crtc, crtc_state, i) {
for_each_pipe_crtc_modeset_enable(display, pipe_crtc, crtc_state) {
const struct intel_crtc_state *pipe_crtc_state =
intel_atomic_get_new_crtc_state(state, pipe_crtc);
@ -3672,7 +3670,7 @@ void intel_ddi_update_active_dpll(struct intel_atomic_state *state,
if (!intel_encoder_is_tc(encoder) || !display->dpll.mgr)
return;
for_each_intel_crtc_in_pipe_mask(display->drm, pipe_crtc,
for_each_intel_crtc_in_pipe_mask(display, pipe_crtc,
intel_crtc_joined_pipe_mask(crtc_state))
intel_dpll_update_active(state, pipe_crtc, encoder);
}

View File

@ -714,22 +714,22 @@ static void icl_set_pipe_chicken(const struct intel_crtc_state *crtc_state)
bool intel_has_pending_fb_unpin(struct intel_display *display)
{
struct drm_crtc *crtc;
struct intel_crtc *crtc;
bool cleanup_done;
drm_for_each_crtc(crtc, display->drm) {
for_each_intel_crtc(display, crtc) {
struct drm_crtc_commit *commit;
spin_lock(&crtc->commit_lock);
commit = list_first_entry_or_null(&crtc->commit_list,
spin_lock(&crtc->base.commit_lock);
commit = list_first_entry_or_null(&crtc->base.commit_list,
struct drm_crtc_commit, commit_entry);
cleanup_done = commit ?
try_wait_for_completion(&commit->cleanup_done) : true;
spin_unlock(&crtc->commit_lock);
spin_unlock(&crtc->base.commit_lock);
if (cleanup_done)
continue;
intel_crtc_wait_for_next_vblank(to_intel_crtc(crtc));
intel_crtc_wait_for_next_vblank(crtc);
return true;
}
@ -737,6 +737,28 @@ bool intel_has_pending_fb_unpin(struct intel_display *display)
return false;
}
/* FIXME: remove this and just flush the cleanup wq where appropriate */
void intel_display_flush_cleanup_work(struct intel_display *display)
{
struct intel_crtc *crtc;
for_each_intel_crtc(display, crtc) {
struct drm_crtc_commit *commit;
spin_lock(&crtc->base.commit_lock);
commit = list_first_entry_or_null(&crtc->base.commit_list,
struct drm_crtc_commit, commit_entry);
if (commit)
drm_crtc_commit_get(commit);
spin_unlock(&crtc->base.commit_lock);
if (commit) {
wait_for_completion(&commit->cleanup_done);
drm_crtc_commit_put(commit);
}
}
}
/*
* Finds the encoder associated with the given CRTC. This can only be
* used when we know that the CRTC isn't feeding multiple encoders!
@ -1295,14 +1317,13 @@ static void intel_encoders_update_prepare(struct intel_atomic_state *state)
struct intel_display *display = to_intel_display(state);
struct intel_crtc_state *new_crtc_state, *old_crtc_state;
struct intel_crtc *crtc;
int i;
/*
* Make sure the DPLL state is up-to-date for fastset TypeC ports after non-blocking commits.
* TODO: Update the DPLL state for all cases in the encoder->update_prepare() hook.
*/
if (display->dpll.mgr) {
for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {
for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state) {
if (intel_crtc_needs_modeset(new_crtc_state))
continue;
@ -1633,11 +1654,10 @@ static void hsw_crtc_enable(struct intel_atomic_state *state,
intel_atomic_get_new_crtc_state(state, crtc);
enum transcoder cpu_transcoder = new_crtc_state->cpu_transcoder;
struct intel_crtc *pipe_crtc;
int i;
if (drm_WARN_ON(display->drm, crtc->active))
return;
for_each_pipe_crtc_modeset_enable(display, pipe_crtc, new_crtc_state, i) {
for_each_pipe_crtc_modeset_enable(display, pipe_crtc, new_crtc_state) {
const struct intel_crtc_state *new_pipe_crtc_state =
intel_atomic_get_new_crtc_state(state, pipe_crtc);
@ -1651,7 +1671,7 @@ static void hsw_crtc_enable(struct intel_atomic_state *state,
intel_encoders_pre_enable(state, crtc);
for_each_pipe_crtc_modeset_enable(display, pipe_crtc, new_crtc_state, i) {
for_each_pipe_crtc_modeset_enable(display, pipe_crtc, new_crtc_state) {
const struct intel_crtc_state *pipe_crtc_state =
intel_atomic_get_new_crtc_state(state, pipe_crtc);
@ -1669,7 +1689,7 @@ static void hsw_crtc_enable(struct intel_atomic_state *state,
if (!transcoder_is_dsi(cpu_transcoder))
hsw_configure_cpu_transcoder(new_crtc_state);
for_each_pipe_crtc_modeset_enable(display, pipe_crtc, new_crtc_state, i) {
for_each_pipe_crtc_modeset_enable(display, pipe_crtc, new_crtc_state) {
const struct intel_crtc_state *pipe_crtc_state =
intel_atomic_get_new_crtc_state(state, pipe_crtc);
@ -1699,7 +1719,7 @@ static void hsw_crtc_enable(struct intel_atomic_state *state,
intel_encoders_enable(state, crtc);
for_each_pipe_crtc_modeset_enable(display, pipe_crtc, new_crtc_state, i) {
for_each_pipe_crtc_modeset_enable(display, pipe_crtc, new_crtc_state) {
const struct intel_crtc_state *pipe_crtc_state =
intel_atomic_get_new_crtc_state(state, pipe_crtc);
enum pipe hsw_workaround_pipe;
@ -1767,7 +1787,6 @@ static void hsw_crtc_disable(struct intel_atomic_state *state,
const struct intel_crtc_state *old_crtc_state =
intel_atomic_get_old_crtc_state(state, crtc);
struct intel_crtc *pipe_crtc;
int i;
/*
* FIXME collapse everything to one hook.
@ -1780,7 +1799,7 @@ static void hsw_crtc_disable(struct intel_atomic_state *state,
intel_encoders_post_pll_disable(state, crtc);
for_each_pipe_crtc_modeset_disable(display, pipe_crtc, old_crtc_state, i) {
for_each_pipe_crtc_modeset_disable(display, pipe_crtc, old_crtc_state) {
const struct intel_crtc_state *old_pipe_crtc_state =
intel_atomic_get_old_crtc_state(state, pipe_crtc);
@ -3505,7 +3524,7 @@ static void enabled_uncompressed_joiner_pipes(struct intel_display *display,
if (!HAS_UNCOMPRESSED_JOINER(display))
return;
for_each_intel_crtc_in_pipe_mask(display->drm, crtc,
for_each_intel_crtc_in_pipe_mask(display, crtc,
joiner_pipes(display)) {
enum intel_display_power_domain power_domain;
enum pipe pipe = crtc->pipe;
@ -3533,7 +3552,7 @@ static void enabled_bigjoiner_pipes(struct intel_display *display,
if (!HAS_BIGJOINER(display))
return;
for_each_intel_crtc_in_pipe_mask(display->drm, crtc,
for_each_intel_crtc_in_pipe_mask(display, crtc,
joiner_pipes(display)) {
enum intel_display_power_domain power_domain;
enum pipe pipe = crtc->pipe;
@ -3602,7 +3621,7 @@ static void enabled_ultrajoiner_pipes(struct intel_display *display,
if (!HAS_ULTRAJOINER(display))
return;
for_each_intel_crtc_in_pipe_mask(display->drm, crtc,
for_each_intel_crtc_in_pipe_mask(display, crtc,
joiner_pipes(display)) {
enum intel_display_power_domain power_domain;
enum pipe pipe = crtc->pipe;
@ -4505,6 +4524,8 @@ intel_crtc_copy_uapi_to_hw_state_nomodeset(struct intel_atomic_state *state,
crtc_state->uapi.gamma_lut);
drm_property_replace_blob(&crtc_state->hw.ctm,
crtc_state->uapi.ctm);
crtc_state->hw.background_color =
intel_color_background_color_drm_to_hw(crtc_state->uapi.background_color);
}
static void
@ -4544,6 +4565,7 @@ copy_joiner_crtc_state_nomodeset(struct intel_atomic_state *state,
primary_crtc_state->hw.gamma_lut);
drm_property_replace_blob(&secondary_crtc_state->hw.ctm,
primary_crtc_state->hw.ctm);
secondary_crtc_state->hw.background_color = primary_crtc_state->hw.background_color;
secondary_crtc_state->uapi.color_mgmt_changed = primary_crtc_state->uapi.color_mgmt_changed;
}
@ -4881,11 +4903,16 @@ static bool
intel_compare_dp_as_sdp(const struct drm_dp_as_sdp *a,
const struct drm_dp_as_sdp *b)
{
return a->vtotal == b->vtotal &&
return a->sdp_type == b->sdp_type &&
a->revision == b->revision &&
a->length == b->length &&
a->vtotal == b->vtotal &&
a->target_rr == b->target_rr &&
a->duration_incr_ms == b->duration_incr_ms &&
a->duration_decr_ms == b->duration_decr_ms &&
a->mode == b->mode;
a->target_rr_divider == b->target_rr_divider &&
a->mode == b->mode &&
a->coasting_vtotal == b->coasting_vtotal;
}
static bool
@ -5356,6 +5383,8 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config,
else
PIPE_CONF_CHECK_X(csc_mode);
PIPE_CONF_CHECK_BOOL(gamma_enable);
PIPE_CONF_CHECK_X(hw.background_color);
PIPE_CONF_CHECK_BOOL(csc_enable);
PIPE_CONF_CHECK_BOOL(wgc_enable);
@ -5556,7 +5585,7 @@ int intel_modeset_pipes_in_mask_early(struct intel_atomic_state *state,
struct intel_display *display = to_intel_display(state);
struct intel_crtc *crtc;
for_each_intel_crtc_in_pipe_mask(display->drm, crtc, mask) {
for_each_intel_crtc_in_pipe_mask(display, crtc, mask) {
struct intel_crtc_state *crtc_state;
int ret;
@ -5603,7 +5632,7 @@ int intel_modeset_all_pipes_late(struct intel_atomic_state *state,
struct intel_display *display = to_intel_display(state);
struct intel_crtc *crtc;
for_each_intel_crtc(display->drm, crtc) {
for_each_intel_crtc(display, crtc) {
struct intel_crtc_state *crtc_state;
int ret;
@ -5644,7 +5673,7 @@ int intel_modeset_commit_pipes(struct intel_display *display,
state->acquire_ctx = ctx;
to_intel_atomic_state(state)->internal = true;
for_each_intel_crtc_in_pipe_mask(display->drm, crtc, pipe_mask) {
for_each_intel_crtc_in_pipe_mask(display, crtc, pipe_mask) {
struct intel_crtc_state *crtc_state =
intel_atomic_get_crtc_state(state, crtc);
@ -5671,15 +5700,15 @@ int intel_modeset_commit_pipes(struct intel_display *display,
*/
static int hsw_mode_set_planes_workaround(struct intel_atomic_state *state)
{
struct intel_display *display = to_intel_display(state);
struct intel_crtc_state *crtc_state;
struct intel_crtc *crtc;
struct intel_crtc_state *first_crtc_state = NULL;
struct intel_crtc_state *other_crtc_state = NULL;
enum pipe first_pipe = INVALID_PIPE, enabled_pipe = INVALID_PIPE;
int i;
/* look at all crtc's that are going to be enabled in during modeset */
for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i) {
for_each_new_intel_crtc_in_state(state, crtc, crtc_state) {
if (!crtc_state->hw.active ||
!intel_crtc_needs_modeset(crtc_state))
continue;
@ -5698,7 +5727,7 @@ static int hsw_mode_set_planes_workaround(struct intel_atomic_state *state)
return 0;
/* w/a possibly needed, check how many crtc's are already enabled. */
for_each_intel_crtc(state->base.dev, crtc) {
for_each_intel_crtc(display, crtc) {
crtc_state = intel_atomic_get_crtc_state(&state->base, crtc);
if (IS_ERR(crtc_state))
return PTR_ERR(crtc_state);
@ -5729,9 +5758,8 @@ u8 intel_calc_enabled_pipes(struct intel_atomic_state *state,
{
const struct intel_crtc_state *crtc_state;
struct intel_crtc *crtc;
int i;
for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i) {
for_each_new_intel_crtc_in_state(state, crtc, crtc_state) {
if (crtc_state->hw.enable)
enabled_pipes |= BIT(crtc->pipe);
else
@ -5746,9 +5774,8 @@ u8 intel_calc_active_pipes(struct intel_atomic_state *state,
{
const struct intel_crtc_state *crtc_state;
struct intel_crtc *crtc;
int i;
for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i) {
for_each_new_intel_crtc_in_state(state, crtc, crtc_state) {
if (crtc_state->hw.active)
active_pipes |= BIT(crtc->pipe);
else
@ -5819,9 +5846,8 @@ static int intel_atomic_check_crtcs(struct intel_atomic_state *state)
struct intel_display *display = to_intel_display(state);
struct intel_crtc_state __maybe_unused *crtc_state;
struct intel_crtc *crtc;
int i;
for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i) {
for_each_new_intel_crtc_in_state(state, crtc, crtc_state) {
int ret;
ret = intel_crtc_atomic_check(state, crtc);
@ -5841,9 +5867,8 @@ static bool intel_cpu_transcoders_need_modeset(struct intel_atomic_state *state,
{
const struct intel_crtc_state *new_crtc_state;
struct intel_crtc *crtc;
int i;
for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) {
for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state) {
if (new_crtc_state->hw.enable &&
transcoders & BIT(new_crtc_state->cpu_transcoder) &&
intel_crtc_needs_modeset(new_crtc_state))
@ -5858,9 +5883,8 @@ static bool intel_pipes_need_modeset(struct intel_atomic_state *state,
{
const struct intel_crtc_state *new_crtc_state;
struct intel_crtc *crtc;
int i;
for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) {
for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state) {
if (new_crtc_state->hw.enable &&
pipes & BIT(crtc->pipe) &&
intel_crtc_needs_modeset(new_crtc_state))
@ -5895,7 +5919,7 @@ static int intel_atomic_check_joiner(struct intel_atomic_state *state,
return -EINVAL;
}
for_each_intel_crtc_in_pipe_mask(display->drm, secondary_crtc,
for_each_intel_crtc_in_pipe_mask(display, secondary_crtc,
intel_crtc_joiner_secondary_pipes(primary_crtc_state)) {
struct intel_crtc_state *secondary_crtc_state;
int ret;
@ -5938,7 +5962,7 @@ static void kill_joiner_secondaries(struct intel_atomic_state *state,
intel_atomic_get_new_crtc_state(state, primary_crtc);
struct intel_crtc *secondary_crtc;
for_each_intel_crtc_in_pipe_mask(display->drm, secondary_crtc,
for_each_intel_crtc_in_pipe_mask(display, secondary_crtc,
intel_crtc_joiner_secondary_pipes(primary_crtc_state)) {
struct intel_crtc_state *secondary_crtc_state =
intel_atomic_get_new_crtc_state(state, secondary_crtc);
@ -6231,19 +6255,19 @@ static int intel_joiner_add_affected_crtcs(struct intel_atomic_state *state)
}
/* Now pull in all joined crtcs */
for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i) {
for_each_new_intel_crtc_in_state(state, crtc, crtc_state) {
affected_pipes |= crtc_state->joiner_pipes;
if (intel_crtc_needs_modeset(crtc_state))
modeset_pipes |= crtc_state->joiner_pipes;
}
for_each_intel_crtc_in_pipe_mask(display->drm, crtc, affected_pipes) {
for_each_intel_crtc_in_pipe_mask(display, crtc, affected_pipes) {
crtc_state = intel_atomic_get_crtc_state(&state->base, crtc);
if (IS_ERR(crtc_state))
return PTR_ERR(crtc_state);
}
for_each_intel_crtc_in_pipe_mask(display->drm, crtc, modeset_pipes) {
for_each_intel_crtc_in_pipe_mask(display, crtc, modeset_pipes) {
int ret;
crtc_state = intel_atomic_get_new_crtc_state(state, crtc);
@ -6259,7 +6283,7 @@ static int intel_joiner_add_affected_crtcs(struct intel_atomic_state *state)
return ret;
}
for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i) {
for_each_new_intel_crtc_in_state(state, crtc, crtc_state) {
/* Kill old joiner link, we may re-establish afterwards */
if (intel_crtc_needs_modeset(crtc_state) &&
intel_crtc_is_joiner_primary(crtc_state))
@ -6277,7 +6301,6 @@ static int intel_atomic_check_config(struct intel_atomic_state *state,
struct intel_crtc_state *new_crtc_state;
struct intel_crtc *crtc;
int ret;
int i;
*failed_pipe = INVALID_PIPE;
@ -6289,7 +6312,7 @@ static int intel_atomic_check_config(struct intel_atomic_state *state,
if (ret)
return ret;
for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) {
for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state) {
if (!intel_crtc_needs_modeset(new_crtc_state)) {
if (!intel_crtc_is_joiner_secondary(new_crtc_state))
intel_crtc_copy_uapi_to_hw_state_nomodeset(state, crtc);
@ -6311,7 +6334,7 @@ static int intel_atomic_check_config(struct intel_atomic_state *state,
goto fail;
}
for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) {
for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state) {
if (!intel_crtc_needs_modeset(new_crtc_state))
continue;
@ -6383,13 +6406,12 @@ int intel_atomic_check(struct drm_device *dev,
struct intel_atomic_state *state = to_intel_atomic_state(_state);
struct intel_crtc_state *old_crtc_state, *new_crtc_state;
struct intel_crtc *crtc;
int ret, i;
int ret;
if (!intel_display_driver_check_access(display))
return -ENODEV;
for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state,
new_crtc_state, i) {
for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state) {
/*
* crtc's state no longer considered to be inherited
* after the first userspace/client initiated commit.
@ -6415,7 +6437,7 @@ int intel_atomic_check(struct drm_device *dev,
if (ret)
goto fail;
for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) {
for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state) {
ret = intel_async_flip_check_uapi(state, crtc);
if (ret)
return ret;
@ -6425,7 +6447,7 @@ int intel_atomic_check(struct drm_device *dev,
if (ret)
goto fail;
for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) {
for_each_new_intel_crtc_in_state(state, crtc, 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);
@ -6442,8 +6464,7 @@ int intel_atomic_check(struct drm_device *dev,
goto fail;
}
for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state,
new_crtc_state, i) {
for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state) {
if (!intel_crtc_needs_modeset(new_crtc_state))
continue;
@ -6463,7 +6484,7 @@ int intel_atomic_check(struct drm_device *dev,
* needs a full modeset, all other synced crtcs should be
* forced a full modeset.
*/
for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) {
for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state) {
if (!new_crtc_state->hw.enable || intel_crtc_needs_modeset(new_crtc_state))
continue;
@ -6493,8 +6514,7 @@ int intel_atomic_check(struct drm_device *dev,
}
}
for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state,
new_crtc_state, i) {
for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state) {
if (!intel_crtc_needs_modeset(new_crtc_state))
continue;
@ -6511,7 +6531,7 @@ int intel_atomic_check(struct drm_device *dev,
if (ret)
goto fail;
for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i)
for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state)
new_crtc_state->min_cdclk = intel_crtc_min_cdclk(new_crtc_state);
ret = intel_compute_global_watermarks(state);
@ -6544,8 +6564,7 @@ int intel_atomic_check(struct drm_device *dev,
if (ret)
goto fail;
for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state,
new_crtc_state, i) {
for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state) {
intel_color_assert_luts(new_crtc_state);
ret = intel_async_flip_check_hw(state, crtc);
@ -6576,8 +6595,7 @@ int intel_atomic_check(struct drm_device *dev,
* FIXME would probably be nice to know which crtc specifically
* caused the failure, in cases where we can pinpoint it.
*/
for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state,
new_crtc_state, i)
for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state)
intel_crtc_state_dump(new_crtc_state, state, "failed");
return ret;
@ -6728,7 +6746,7 @@ static void intel_enable_crtc(struct intel_atomic_state *state,
if (!intel_crtc_needs_modeset(new_crtc_state))
return;
for_each_intel_crtc_in_pipe_mask_reverse(display->drm, pipe_crtc,
for_each_intel_crtc_in_pipe_mask_reverse(display, pipe_crtc,
intel_crtc_joined_pipe_mask(new_crtc_state)) {
const struct intel_crtc_state *pipe_crtc_state =
intel_atomic_get_new_crtc_state(state, pipe_crtc);
@ -6866,7 +6884,7 @@ static void intel_old_crtc_state_disables(struct intel_atomic_state *state,
* We need to disable pipe CRC before disabling the pipe,
* or we race against vblank off.
*/
for_each_intel_crtc_in_pipe_mask(display->drm, pipe_crtc,
for_each_intel_crtc_in_pipe_mask(display, pipe_crtc,
intel_crtc_joined_pipe_mask(old_crtc_state))
intel_crtc_disable_pipe_crc(pipe_crtc);
@ -6874,7 +6892,7 @@ static void intel_old_crtc_state_disables(struct intel_atomic_state *state,
display->modeset.funcs->crtc_disable(state, crtc);
for_each_intel_crtc_in_pipe_mask(display->drm, pipe_crtc,
for_each_intel_crtc_in_pipe_mask(display, pipe_crtc,
intel_crtc_joined_pipe_mask(old_crtc_state)) {
const struct intel_crtc_state *new_pipe_crtc_state =
intel_atomic_get_new_crtc_state(state, pipe_crtc);
@ -6893,10 +6911,8 @@ static void intel_commit_modeset_disables(struct intel_atomic_state *state)
const struct intel_crtc_state *new_crtc_state, *old_crtc_state;
struct intel_crtc *crtc;
u8 disable_pipes = 0;
int i;
for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state,
new_crtc_state, i) {
for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state) {
if (!intel_crtc_needs_modeset(new_crtc_state))
continue;
@ -6912,7 +6928,7 @@ static void intel_commit_modeset_disables(struct intel_atomic_state *state)
disable_pipes |= BIT(crtc->pipe);
}
for_each_old_intel_crtc_in_state(state, crtc, old_crtc_state, i) {
for_each_old_intel_crtc_in_state(state, crtc, old_crtc_state) {
if ((disable_pipes & BIT(crtc->pipe)) == 0)
continue;
@ -6922,7 +6938,7 @@ static void intel_commit_modeset_disables(struct intel_atomic_state *state)
}
/* Only disable port sync and MST slaves */
for_each_old_intel_crtc_in_state(state, crtc, old_crtc_state, i) {
for_each_old_intel_crtc_in_state(state, crtc, old_crtc_state) {
if ((disable_pipes & BIT(crtc->pipe)) == 0)
continue;
@ -6944,7 +6960,7 @@ static void intel_commit_modeset_disables(struct intel_atomic_state *state)
}
/* Disable everything else left on */
for_each_old_intel_crtc_in_state(state, crtc, old_crtc_state, i) {
for_each_old_intel_crtc_in_state(state, crtc, old_crtc_state) {
if ((disable_pipes & BIT(crtc->pipe)) == 0)
continue;
@ -6963,9 +6979,8 @@ static void intel_commit_modeset_enables(struct intel_atomic_state *state)
{
struct intel_crtc_state *new_crtc_state;
struct intel_crtc *crtc;
int i;
for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) {
for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state) {
if (!new_crtc_state->hw.active)
continue;
@ -6973,7 +6988,7 @@ static void intel_commit_modeset_enables(struct intel_atomic_state *state)
intel_pre_update_crtc(state, crtc);
}
for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) {
for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state) {
if (!new_crtc_state->hw.active)
continue;
@ -6988,9 +7003,8 @@ static void skl_commit_modeset_enables(struct intel_atomic_state *state)
struct intel_crtc_state *old_crtc_state, *new_crtc_state;
struct skl_ddb_entry entries[I915_MAX_PIPES] = {};
u8 update_pipes = 0, modeset_pipes = 0;
int i;
for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {
for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state) {
enum pipe pipe = crtc->pipe;
if (!new_crtc_state->hw.active)
@ -7014,7 +7028,7 @@ static void skl_commit_modeset_enables(struct intel_atomic_state *state)
* So first lets enable all pipes that do not need a fullmodeset as
* those don't have any external dependency.
*/
for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) {
for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state) {
enum pipe pipe = crtc->pipe;
if ((update_pipes & BIT(pipe)) == 0)
@ -7030,8 +7044,7 @@ static void skl_commit_modeset_enables(struct intel_atomic_state *state)
* Commit in reverse order to make joiner primary
* send the uapi events after secondaries are done.
*/
for_each_oldnew_intel_crtc_in_state_reverse(state, crtc, old_crtc_state,
new_crtc_state, i) {
for_each_oldnew_intel_crtc_in_state_reverse(state, crtc, old_crtc_state, new_crtc_state) {
enum pipe pipe = crtc->pipe;
if ((update_pipes & BIT(pipe)) == 0)
@ -7067,7 +7080,7 @@ static void skl_commit_modeset_enables(struct intel_atomic_state *state)
* Enable all pipes that needs a modeset and do not depends on other
* pipes
*/
for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) {
for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state) {
enum pipe pipe = crtc->pipe;
if ((modeset_pipes & BIT(pipe)) == 0)
@ -7089,7 +7102,7 @@ static void skl_commit_modeset_enables(struct intel_atomic_state *state)
* Then we enable all remaining pipes that depend on other
* pipes: MST slaves and port sync masters
*/
for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) {
for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state) {
enum pipe pipe = crtc->pipe;
if ((modeset_pipes & BIT(pipe)) == 0)
@ -7106,7 +7119,7 @@ static void skl_commit_modeset_enables(struct intel_atomic_state *state)
/*
* Finally we do the plane updates/etc. for all pipes that got enabled.
*/
for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) {
for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state) {
enum pipe pipe = crtc->pipe;
if ((update_pipes & BIT(pipe)) == 0)
@ -7119,7 +7132,7 @@ static void skl_commit_modeset_enables(struct intel_atomic_state *state)
* Commit in reverse order to make joiner primary
* send the uapi events after secondaries are done.
*/
for_each_new_intel_crtc_in_state_reverse(state, crtc, new_crtc_state, i) {
for_each_new_intel_crtc_in_state_reverse(state, crtc, new_crtc_state) {
enum pipe pipe = crtc->pipe;
if ((update_pipes & BIT(pipe)) == 0)
@ -7184,9 +7197,8 @@ static void intel_atomic_cleanup_work(struct work_struct *work)
struct intel_display *display = to_intel_display(state);
struct intel_crtc_state *old_crtc_state;
struct intel_crtc *crtc;
int i;
for_each_old_intel_crtc_in_state(state, crtc, old_crtc_state, i)
for_each_old_intel_crtc_in_state(state, crtc, old_crtc_state)
intel_atomic_dsb_cleanup(old_crtc_state);
drm_atomic_helper_cleanup_planes(display->drm, &state->base);
@ -7416,9 +7428,8 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state)
struct intel_crtc *crtc;
struct intel_power_domain_mask put_domains[I915_MAX_PIPES] = {};
struct ref_tracker *wakeref = NULL;
int i;
for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i)
for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state)
intel_atomic_dsb_prepare(state, crtc);
intel_atomic_commit_fence_wait(state);
@ -7427,10 +7438,10 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state)
intel_atomic_prepare_plane_clear_colors(state);
for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i)
for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state)
intel_fbc_prepare_dirty_rect(state, crtc);
for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i)
for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state)
intel_atomic_dsb_finish(state, crtc);
drm_atomic_helper_wait_for_dependencies(&state->base);
@ -7466,8 +7477,7 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state)
*/
wakeref = intel_display_power_get(display, POWER_DOMAIN_DC_OFF);
for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state,
new_crtc_state, i) {
for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state) {
if (intel_crtc_needs_modeset(new_crtc_state) ||
intel_crtc_needs_fastset(new_crtc_state))
intel_modeset_get_crtc_power_domains(new_crtc_state, &put_domains[crtc->pipe]);
@ -7478,7 +7488,7 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state)
intel_dp_tunnel_atomic_alloc_bw(state);
/* FIXME: Eventually get rid of our crtc->config pointer */
for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i)
for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state)
crtc->config = new_crtc_state;
/*
@ -7500,7 +7510,7 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state)
intel_sagv_pre_plane_update(state);
/* Complete the events for pipes that have now been disabled */
for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) {
for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state) {
bool modeset = intel_crtc_needs_modeset(new_crtc_state);
/* Complete events for now disable pipes here. */
@ -7518,7 +7528,7 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state)
intel_dbuf_pre_plane_update(state);
for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) {
for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state) {
if (new_crtc_state->do_async_flip)
intel_crtc_enable_flip_done(state, crtc);
}
@ -7542,7 +7552,7 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state)
*/
drm_atomic_helper_wait_for_flip_done(display->drm, &state->base);
for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) {
for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state) {
if (new_crtc_state->do_async_flip)
intel_crtc_disable_flip_done(state, crtc);
@ -7562,8 +7572,7 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state)
*
* TODO: Move this (and other cleanup) to an async worker eventually.
*/
for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state,
new_crtc_state, i) {
for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state) {
/*
* Gen2 reports pipe underruns whenever all planes are disabled.
* So re-enable underrun reporting after some planes get enabled.
@ -7580,7 +7589,7 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state)
intel_dbuf_post_plane_update(state);
for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {
for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state) {
intel_post_plane_update(state, crtc);
intel_modeset_put_crtc_power_domains(crtc, &put_domains[crtc->pipe]);
@ -7724,9 +7733,8 @@ int intel_atomic_commit(struct drm_device *dev, struct drm_atomic_commit *_state
if (DISPLAY_VER(display) < 9 && state->base.legacy_cursor_update) {
struct intel_crtc_state *new_crtc_state;
struct intel_crtc *crtc;
int i;
for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i)
for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state)
if (new_crtc_state->wm.need_postvbl_update ||
new_crtc_state->update_wm_post)
state->base.legacy_cursor_update = false;
@ -7786,7 +7794,7 @@ static u32 intel_encoder_possible_crtcs(struct intel_encoder *encoder)
struct intel_crtc *crtc;
u32 possible_crtcs = 0;
for_each_intel_crtc_in_pipe_mask(display->drm, crtc, encoder->pipe_mask)
for_each_intel_crtc_in_pipe_mask(display, crtc, encoder->pipe_mask)
possible_crtcs |= drm_crtc_mask(&crtc->base);
return possible_crtcs;
@ -8279,7 +8287,7 @@ int intel_initial_commit(struct intel_display *display)
to_intel_atomic_state(state)->internal = true;
retry:
for_each_intel_crtc(display->drm, crtc) {
for_each_intel_crtc(display, crtc) {
struct intel_crtc_state *crtc_state =
intel_atomic_get_crtc_state(state, crtc);

View File

@ -212,22 +212,22 @@ enum phy_fia {
base.head) \
for_each_if((intel_plane)->pipe == (intel_crtc)->pipe)
#define for_each_intel_crtc(dev, crtc) \
#define for_each_intel_crtc(display, crtc) \
list_for_each_entry((crtc), \
&to_intel_display(dev)->pipe_list, \
&(display)->pipe_list, \
pipe_head)
#define for_each_intel_crtc_reverse(dev, crtc) \
#define for_each_intel_crtc_reverse(display, crtc) \
list_for_each_entry_reverse((crtc), \
&to_intel_display(dev)->pipe_list, \
&(display)->pipe_list, \
pipe_head)
#define for_each_intel_crtc_in_pipe_mask(dev, crtc, pipe_mask) \
for_each_intel_crtc((dev), (crtc)) \
#define for_each_intel_crtc_in_pipe_mask(display, crtc, pipe_mask) \
for_each_intel_crtc((display), (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)) \
#define for_each_intel_crtc_in_pipe_mask_reverse(display, crtc, pipe_mask) \
for_each_intel_crtc_reverse((display), (crtc)) \
for_each_if((pipe_mask) & BIT((crtc)->pipe))
#define for_each_intel_encoder(dev, intel_encoder) \
@ -287,31 +287,26 @@ 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_old_intel_crtc_in_state(__state, crtc, old_crtc_state) \
for_each_intel_crtc(to_intel_display(__state), (crtc)) \
for_each_if((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), \
#define for_each_new_intel_crtc_in_state(__state, crtc, new_crtc_state) \
for_each_intel_crtc(to_intel_display(__state), (crtc)) \
for_each_if((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) \
for_each_intel_crtc_reverse(to_intel_display(__state), (crtc)) \
for_each_if((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) \
for_each_intel_crtc(to_intel_display(__state), (crtc)) \
for_each_if(((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_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_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_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)), \
#define for_each_oldnew_intel_crtc_in_state_reverse(__state, crtc, old_crtc_state, new_crtc_state) \
for_each_intel_crtc_reverse(to_intel_display(__state), (crtc)) \
for_each_if(((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( \
@ -330,29 +325,29 @@ enum phy_fia {
((connector) = to_intel_connector((__state)->base.connectors[__i].ptr), \
(new_connector_state) = to_intel_digital_connector_state((__state)->base.connectors[__i].new_state), 1))
#define for_each_crtc_in_masks(display, crtc, first_pipes, second_pipes, i) \
for ((i) = 0; \
#define __for_each_crtc_in_masks(display, crtc, first_pipes, second_pipes, i) \
for (int (i) = 0; \
(i) < (I915_MAX_PIPES * 2) && ((crtc) = intel_crtc_for_pipe(display, (i) % I915_MAX_PIPES), 1); \
(i)++) \
for_each_if((crtc) && ((first_pipes) | ((second_pipes) << I915_MAX_PIPES)) & BIT(i))
#define for_each_crtc_in_masks_reverse(display, crtc, first_pipes, second_pipes, i) \
for ((i) = (I915_MAX_PIPES * 2 - 1); \
#define __for_each_crtc_in_masks_reverse(display, crtc, first_pipes, second_pipes, i) \
for (int (i) = (I915_MAX_PIPES * 2 - 1); \
(i) >= 0 && ((crtc) = intel_crtc_for_pipe(display, (i) % I915_MAX_PIPES), 1); \
(i)--) \
for_each_if((crtc) && ((first_pipes) | ((second_pipes) << I915_MAX_PIPES)) & BIT(i))
#define for_each_pipe_crtc_modeset_disable(display, crtc, crtc_state, i) \
for_each_crtc_in_masks(display, crtc, \
_intel_modeset_primary_pipes(crtc_state), \
_intel_modeset_secondary_pipes(crtc_state), \
i)
#define for_each_pipe_crtc_modeset_disable(display, crtc, crtc_state) \
__for_each_crtc_in_masks(display, crtc, \
_intel_modeset_primary_pipes(crtc_state), \
_intel_modeset_secondary_pipes(crtc_state), \
__UNIQUE_ID(i))
#define for_each_pipe_crtc_modeset_enable(display, crtc, crtc_state, i) \
for_each_crtc_in_masks_reverse(display, crtc, \
_intel_modeset_primary_pipes(crtc_state), \
_intel_modeset_secondary_pipes(crtc_state), \
i)
#define for_each_pipe_crtc_modeset_enable(display, crtc, crtc_state) \
__for_each_crtc_in_masks_reverse(display, crtc, \
_intel_modeset_primary_pipes(crtc_state), \
_intel_modeset_secondary_pipes(crtc_state), \
__UNIQUE_ID(i))
int intel_atomic_check(struct drm_device *dev, struct drm_atomic_commit *state);
u8 intel_calc_enabled_pipes(struct intel_atomic_state *state,
@ -402,6 +397,7 @@ void intel_disable_transcoder(const struct intel_crtc_state *old_crtc_state);
void i830_enable_pipe(struct intel_display *display, enum pipe pipe);
void i830_disable_pipe(struct intel_display *display, enum pipe pipe);
bool intel_has_pending_fb_unpin(struct intel_display *display);
void intel_display_flush_cleanup_work(struct intel_display *display);
void intel_encoder_destroy(struct drm_encoder *encoder);
struct drm_display_mode *
intel_encoder_current_mode(struct intel_encoder *encoder);

View File

@ -475,6 +475,9 @@ struct intel_display {
} ips;
struct {
/* internal display irq functions */
const struct intel_display_irq_funcs *funcs;
/* protects the irq masks */
spinlock_t lock;
@ -491,6 +494,7 @@ struct intel_display {
u8 vblank_enabled;
int vblank_enable_count;
bool vblank_status_last_notified;
struct work_struct vblank_notify_work;

View File

@ -572,6 +572,12 @@ static void intel_crtc_info(struct seq_file *m, struct intel_crtc *crtc)
intel_scaler_info(m, crtc);
if (DISPLAY_VER(display) >= 9) {
u32 background = crtc_state->hw.background_color;
seq_printf(m, "\tbackground color (10bpc XRGB2101010): %08x\n", background);
}
if (crtc_state->joiner_pipes)
seq_printf(m, "\tLinked to 0x%x pipes as a %s\n",
crtc_state->joiner_pipes,
@ -606,7 +612,7 @@ static int i915_display_info(struct seq_file *m, void *unused)
seq_printf(m, "CRTC info\n");
seq_printf(m, "---------\n");
for_each_intel_crtc(display->drm, crtc)
for_each_intel_crtc(display, crtc)
intel_crtc_info(m, crtc);
seq_printf(m, "\n");
@ -664,7 +670,7 @@ static int i915_ddb_info(struct seq_file *m, void *unused)
seq_printf(m, "%-15s%8s%8s%8s\n", "", "Start", "End", "Size");
for_each_intel_crtc(display->drm, crtc) {
for_each_intel_crtc(display, crtc) {
struct intel_crtc_state *crtc_state =
to_intel_crtc_state(crtc->base.state);
enum pipe pipe = crtc->pipe;
@ -771,7 +777,7 @@ i915_fifo_underrun_reset_write(struct file *filp,
if (!reset)
return cnt;
for_each_intel_crtc(display->drm, crtc) {
for_each_intel_crtc(display, crtc) {
struct drm_crtc_commit *commit;
struct intel_crtc_state *crtc_state;

View File

@ -162,7 +162,6 @@ struct intel_display_platforms {
#define HAS_DDI(__display) (DISPLAY_INFO(__display)->has_ddi)
#define HAS_DISPLAY(__display) (DISPLAY_RUNTIME_INFO(__display)->pipe_mask != 0)
#define HAS_DMC(__display) (DISPLAY_RUNTIME_INFO(__display)->has_dmc)
#define HAS_DMC_WAKELOCK(__display) (DISPLAY_VER(__display) >= 20)
#define HAS_DOUBLE_BUFFERED_M_N(__display) (IS_DISPLAY_VER((__display), 9, 14) || (__display)->platform.broadwell)
#define HAS_DOUBLE_BUFFERED_LUT(__display) (DISPLAY_VER(__display) >= 30)
#define HAS_DOUBLE_WIDE(__display) (DISPLAY_VER(__display) < 4)

View File

@ -212,13 +212,13 @@ int intel_display_driver_probe_noirq(struct intel_display *display)
intel_psr_dc5_dc6_wa_init(display);
/* FIXME: completely on the wrong abstraction layer */
ret = intel_power_domains_init(display);
ret = intel_display_power_init(display);
if (ret < 0)
goto cleanup_bios;
intel_pmdemand_init_early(display);
intel_power_domains_init_hw(display, false);
intel_display_power_init_hw(display);
if (!HAS_DISPLAY(display))
return 0;
@ -300,7 +300,7 @@ int intel_display_driver_probe_noirq(struct intel_display *display)
destroy_workqueue(display->hotplug.dp_wq);
cleanup_pw_domain_dmc:
intel_dmc_fini(display);
intel_power_domains_driver_remove(display);
intel_display_power_driver_remove(display);
cleanup_bios:
intel_bios_driver_remove(display);
@ -641,7 +641,7 @@ void intel_display_driver_remove_nogem(struct intel_display *display)
{
intel_dmc_fini(display);
intel_power_domains_driver_remove(display);
intel_display_power_driver_remove(display);
intel_bios_driver_remove(display);
}

View File

@ -23,6 +23,7 @@
#include "intel_fifo_underrun.h"
#include "intel_gmbus.h"
#include "intel_hotplug_irq.h"
#include "intel_lpe_audio.h"
#include "intel_parent.h"
#include "intel_pipe_crc_regs.h"
#include "intel_plane.h"
@ -529,8 +530,8 @@ static void i9xx_pipestat_irq_reset(struct intel_display *display)
}
}
void i9xx_pipestat_irq_ack(struct intel_display *display,
u32 iir, u32 pipe_stats[I915_MAX_PIPES])
static void i9xx_pipestat_irq_ack(struct intel_display *display,
u32 iir, u32 pipe_stats[I915_MAX_PIPES])
{
enum pipe pipe;
@ -596,8 +597,8 @@ void i9xx_pipestat_irq_ack(struct intel_display *display,
spin_unlock(&display->irq.lock);
}
void i915_pipestat_irq_handler(struct intel_display *display,
u32 iir, u32 pipe_stats[I915_MAX_PIPES])
static void i915_pipestat_irq_handler(struct intel_display *display,
u32 iir, const u32 pipe_stats[I915_MAX_PIPES])
{
bool blc_event = false;
enum pipe pipe;
@ -620,8 +621,8 @@ void i915_pipestat_irq_handler(struct intel_display *display,
intel_opregion_asle_intr(display);
}
void i965_pipestat_irq_handler(struct intel_display *display,
u32 iir, u32 pipe_stats[I915_MAX_PIPES])
static void i965_pipestat_irq_handler(struct intel_display *display,
u32 iir, const u32 pipe_stats[I915_MAX_PIPES])
{
bool blc_event = false;
enum pipe pipe;
@ -647,8 +648,8 @@ void i965_pipestat_irq_handler(struct intel_display *display,
intel_gmbus_irq_handler(display);
}
void valleyview_pipestat_irq_handler(struct intel_display *display,
u32 pipe_stats[I915_MAX_PIPES])
static void valleyview_pipestat_irq_handler(struct intel_display *display,
const u32 pipe_stats[I915_MAX_PIPES])
{
enum pipe pipe;
@ -1020,7 +1021,8 @@ void ilk_display_irq_master_enable(struct intel_display *display, u32 de_ier, u3
intel_de_write_fw(display, SDEIER, sde_ier);
}
bool ilk_display_irq_handler(struct intel_display *display)
static bool ilk_display_irq_handler(struct intel_display *display,
const struct intel_display_irq_state *state)
{
u32 de_iir;
bool handled = false;
@ -1404,7 +1406,7 @@ static void gen8_read_and_ack_pch_irqs(struct intel_display *display, u32 *pch_i
intel_de_write(display, PICAINTERRUPT_IER, pica_ier);
}
void gen8_de_irq_handler(struct intel_display *display, u32 master_ctl)
static void gen8_de_irq_handler(struct intel_display *display, u32 master_ctl)
{
u32 iir;
enum pipe pipe;
@ -1565,6 +1567,14 @@ void gen8_de_irq_handler(struct intel_display *display, u32 master_ctl)
}
}
static bool gen8_display_irq_handler(struct intel_display *display,
const struct intel_display_irq_state *state)
{
gen8_de_irq_handler(display, state->master_ctl);
return true;
}
u32 gen11_gu_misc_irq_ack(struct intel_display *display, const u32 master_ctl)
{
u32 iir;
@ -1589,7 +1599,8 @@ void gen11_gu_misc_irq_handler(struct intel_display *display, const u32 iir)
intel_opregion_asle_intr(display);
}
void gen11_display_irq_handler(struct intel_display *display)
static bool gen11_display_irq_handler(struct intel_display *display,
const struct intel_display_irq_state *state)
{
u32 disp_ctl;
@ -1605,6 +1616,8 @@ void gen11_display_irq_handler(struct intel_display *display)
intel_de_write(display, GEN11_DISPLAY_INT_CTL, GEN11_DISPLAY_IRQ_ENABLE);
intel_display_rpm_assert_unblock(display);
return true;
}
static void i915gm_irq_cstate_wa_enable(struct intel_display *display)
@ -1773,8 +1786,12 @@ static void intel_display_vblank_notify_work(struct work_struct *work)
struct intel_display *display =
container_of(work, typeof(*display), irq.vblank_notify_work);
int vblank_enable_count = READ_ONCE(display->irq.vblank_enable_count);
bool vblank_status = !!vblank_enable_count;
intel_psr_notify_vblank_enable_disable(display, vblank_enable_count);
if (display->irq.vblank_status_last_notified != vblank_status) {
intel_psr_notify_vblank_enable_disable(display, vblank_status);
display->irq.vblank_status_last_notified = vblank_status;
}
}
int bdw_enable_vblank(struct drm_crtc *_crtc)
@ -1787,10 +1804,10 @@ int bdw_enable_vblank(struct drm_crtc *_crtc)
if (gen11_dsi_configure_te(crtc, true))
return 0;
spin_lock_irqsave(&display->irq.lock, irqflags);
if (crtc->vblank_psr_notify && display->irq.vblank_enable_count++ == 0)
schedule_work(&display->irq.vblank_notify_work);
spin_lock_irqsave(&display->irq.lock, irqflags);
bdw_enable_pipe_irq(display, pipe, GEN8_PIPE_VBLANK);
spin_unlock_irqrestore(&display->irq.lock, irqflags);
@ -1898,8 +1915,8 @@ static void vlv_page_table_error_irq_handler(struct intel_display *display, u32
}
}
void vlv_display_error_irq_ack(struct intel_display *display,
u32 *eir, u32 *dpinvgtt)
static void vlv_display_error_irq_ack(struct intel_display *display,
u32 *eir, u32 *dpinvgtt)
{
u32 emr;
@ -1920,8 +1937,8 @@ void vlv_display_error_irq_ack(struct intel_display *display,
intel_de_write(display, VLV_EMR, emr);
}
void vlv_display_error_irq_handler(struct intel_display *display,
u32 eir, u32 dpinvgtt)
static void vlv_display_error_irq_handler(struct intel_display *display,
u32 eir, u32 dpinvgtt)
{
drm_dbg(display->drm, "Master Error, EIR 0x%08x\n", eir);
@ -1947,7 +1964,7 @@ static void _vlv_display_irq_reset(struct intel_display *display)
display->irq.vlv_imr_mask = ~0u;
}
void vlv_display_irq_reset(struct intel_display *display)
static void vlv_display_irq_reset(struct intel_display *display)
{
spin_lock_irq(&display->irq.lock);
if (display->irq.vlv_display_irqs_enabled)
@ -1955,7 +1972,7 @@ void vlv_display_irq_reset(struct intel_display *display)
spin_unlock_irq(&display->irq.lock);
}
void i9xx_display_irq_reset(struct intel_display *display)
static void i9xx_display_irq_reset(struct intel_display *display)
{
if (HAS_HOTPLUG(display)) {
i915_hotplug_interrupt_update(display, 0xffffffff, 0);
@ -1981,7 +1998,7 @@ u32 i9xx_display_irq_enable_mask(struct intel_display *display)
return enable_mask;
}
void i915_display_irq_postinstall(struct intel_display *display)
static void i915_display_irq_postinstall(struct intel_display *display)
{
/*
* Interrupt setup is already guaranteed to be single-threaded, this is
@ -1995,7 +2012,7 @@ void i915_display_irq_postinstall(struct intel_display *display)
i915_enable_asle_pipestat(display);
}
void i965_display_irq_postinstall(struct intel_display *display)
static void i965_display_irq_postinstall(struct intel_display *display)
{
/*
* Interrupt setup is already guaranteed to be single-threaded, this is
@ -2010,6 +2027,38 @@ void i965_display_irq_postinstall(struct intel_display *display)
i915_enable_asle_pipestat(display);
}
static void i9xx_display_irq_ack(struct intel_display *display,
struct intel_display_irq_state *state)
{
if (state->iir & I915_DISPLAY_PORT_INTERRUPT)
state->hotplug_status = i9xx_hpd_irq_ack(display);
/* Call regardless, as some status bits might not be signalled in IIR */
i9xx_pipestat_irq_ack(display, state->iir, state->pipe_stats);
}
static bool i965_display_irq_handler(struct intel_display *display,
const struct intel_display_irq_state *state)
{
if (state->hotplug_status)
i9xx_hpd_irq_handler(display, state->hotplug_status);
i965_pipestat_irq_handler(display, state->iir, state->pipe_stats);
return true;
}
static bool i915_display_irq_handler(struct intel_display *display,
const struct intel_display_irq_state *state)
{
if (state->hotplug_status)
i9xx_hpd_irq_handler(display, state->hotplug_status);
i915_pipestat_irq_handler(display, state->iir, state->pipe_stats);
return true;
}
static u32 vlv_error_mask(void)
{
/* TODO enable other errors too? */
@ -2057,7 +2106,7 @@ static void _vlv_display_irq_postinstall(struct intel_display *display)
irq_init(display, VLV_IRQ_REGS, display->irq.vlv_imr_mask, enable_mask);
}
void vlv_display_irq_postinstall(struct intel_display *display)
static void vlv_display_irq_postinstall(struct intel_display *display)
{
spin_lock_irq(&display->irq.lock);
if (display->irq.vlv_display_irqs_enabled)
@ -2065,6 +2114,46 @@ void vlv_display_irq_postinstall(struct intel_display *display)
spin_unlock_irq(&display->irq.lock);
}
static u32 vlv_lpe_irq_mask(struct intel_display *display)
{
if (display->platform.cherryview)
return I915_LPE_PIPE_A_INTERRUPT | I915_LPE_PIPE_B_INTERRUPT |
I915_LPE_PIPE_C_INTERRUPT;
else
return I915_LPE_PIPE_A_INTERRUPT | I915_LPE_PIPE_B_INTERRUPT;
}
static void vlv_display_irq_ack(struct intel_display *display,
struct intel_display_irq_state *state)
{
if (state->iir & I915_DISPLAY_PORT_INTERRUPT)
state->hotplug_status = i9xx_hpd_irq_ack(display);
if (state->iir & I915_MASTER_ERROR_INTERRUPT)
vlv_display_error_irq_ack(display, &state->eir, &state->dpinvgtt);
/* Call regardless, as some status bits might not be signalled in IIR */
i9xx_pipestat_irq_ack(display, state->iir, state->pipe_stats);
/* The handler acks the irq, so need to call the handler here */
if (state->iir & vlv_lpe_irq_mask(display))
intel_lpe_audio_irq_handler(display);
}
static bool vlv_display_irq_handler(struct intel_display *display,
const struct intel_display_irq_state *state)
{
if (state->hotplug_status)
i9xx_hpd_irq_handler(display, state->hotplug_status);
if (state->iir & I915_MASTER_ERROR_INTERRUPT)
vlv_display_error_irq_handler(display, state->eir, state->dpinvgtt);
valleyview_pipestat_irq_handler(display, state->pipe_stats);
return true;
}
static void ibx_display_irq_reset(struct intel_display *display)
{
if (HAS_PCH_NOP(display))
@ -2076,7 +2165,7 @@ static void ibx_display_irq_reset(struct intel_display *display)
intel_de_write(display, SERR_INT, 0xffffffff);
}
void ilk_display_irq_reset(struct intel_display *display)
static void ilk_display_irq_reset(struct intel_display *display)
{
irq_reset(display, DE_IRQ_REGS);
display->irq.ilk_de_imr_mask = ~0u;
@ -2092,13 +2181,10 @@ void ilk_display_irq_reset(struct intel_display *display)
ibx_display_irq_reset(display);
}
void gen8_display_irq_reset(struct intel_display *display)
static void gen8_display_irq_reset(struct intel_display *display)
{
enum pipe pipe;
if (!HAS_DISPLAY(display))
return;
intel_de_write(display, EDP_PSR_IMR, 0xffffffff);
intel_de_write(display, EDP_PSR_IIR, 0xffffffff);
@ -2114,15 +2200,12 @@ void gen8_display_irq_reset(struct intel_display *display)
ibx_display_irq_reset(display);
}
void gen11_display_irq_reset(struct intel_display *display)
static void gen11_display_irq_reset(struct intel_display *display)
{
enum pipe pipe;
u32 trans_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B) |
BIT(TRANSCODER_C) | BIT(TRANSCODER_D);
if (!HAS_DISPLAY(display))
return;
intel_de_write(display, GEN11_DISPLAY_INT_CTL, 0);
if (DISPLAY_VER(display) >= 12) {
@ -2268,7 +2351,7 @@ void valleyview_disable_display_irqs(struct intel_display *display)
spin_unlock_irq(&display->irq.lock);
}
void ilk_de_irq_postinstall(struct intel_display *display)
static void ilk_de_irq_postinstall(struct intel_display *display)
{
u32 display_mask, extra_mask;
@ -2312,7 +2395,7 @@ void ilk_de_irq_postinstall(struct intel_display *display)
static void mtp_irq_postinstall(struct intel_display *display);
static void icp_irq_postinstall(struct intel_display *display);
void gen8_de_irq_postinstall(struct intel_display *display)
static void gen8_de_irq_postinstall(struct intel_display *display)
{
u32 de_pipe_masked = gen8_de_pipe_fault_mask(display) |
GEN8_PIPE_CDCLK_CRC_DONE;
@ -2439,29 +2522,93 @@ static void icp_irq_postinstall(struct intel_display *display)
irq_init(display, SDE_IRQ_REGS, ~mask, 0xffffffff);
}
void gen11_de_irq_postinstall(struct intel_display *display)
static void gen11_de_irq_postinstall(struct intel_display *display)
{
if (!HAS_DISPLAY(display))
return;
gen8_de_irq_postinstall(display);
intel_de_write(display, GEN11_DISPLAY_INT_CTL, GEN11_DISPLAY_IRQ_ENABLE);
}
void dg1_de_irq_postinstall(struct intel_display *display)
{
if (!HAS_DISPLAY(display))
return;
gen8_de_irq_postinstall(display);
intel_de_write(display, GEN11_DISPLAY_INT_CTL, GEN11_DISPLAY_IRQ_ENABLE);
}
struct intel_display_irq_funcs {
void (*reset)(struct intel_display *display);
void (*postinstall)(struct intel_display *display);
void (*ack)(struct intel_display *display, struct intel_display_irq_state *state);
bool (*handler)(struct intel_display *display, const struct intel_display_irq_state *state);
};
static const struct intel_display_irq_funcs gen11_display_irq_funcs = {
.reset = gen11_display_irq_reset,
.postinstall = gen11_de_irq_postinstall,
.handler = gen11_display_irq_handler,
};
static const struct intel_display_irq_funcs gen8_display_irq_funcs = {
.reset = gen8_display_irq_reset,
.postinstall = gen8_de_irq_postinstall,
.handler = gen8_display_irq_handler,
};
static const struct intel_display_irq_funcs vlv_display_irq_funcs = {
.reset = vlv_display_irq_reset,
.postinstall = vlv_display_irq_postinstall,
.ack = vlv_display_irq_ack,
.handler = vlv_display_irq_handler,
};
static const struct intel_display_irq_funcs ilk_display_irq_funcs = {
.reset = ilk_display_irq_reset,
.postinstall = ilk_de_irq_postinstall,
.handler = ilk_display_irq_handler,
};
static const struct intel_display_irq_funcs i965_display_irq_funcs = {
.reset = i9xx_display_irq_reset,
.postinstall = i965_display_irq_postinstall,
.ack = i9xx_display_irq_ack,
.handler = i965_display_irq_handler,
};
static const struct intel_display_irq_funcs i915_display_irq_funcs = {
.reset = i9xx_display_irq_reset,
.postinstall = i915_display_irq_postinstall,
.ack = i9xx_display_irq_ack,
.handler = i915_display_irq_handler,
};
void intel_display_irq_reset(struct intel_display *display)
{
if (!HAS_DISPLAY(display))
return;
display->irq.funcs->reset(display);
}
void intel_display_irq_postinstall(struct intel_display *display)
{
if (!HAS_DISPLAY(display))
return;
display->irq.funcs->postinstall(display);
}
void intel_display_irq_ack(struct intel_display *display,
struct intel_display_irq_state *state)
{
if (!HAS_DISPLAY(display) || !display->irq.funcs->ack)
return;
display->irq.funcs->ack(display, state);
}
bool intel_display_irq_handler(struct intel_display *display,
const struct intel_display_irq_state *state)
{
if (!HAS_DISPLAY(display) || !display->irq.funcs->handler)
return true;
return display->irq.funcs->handler(display, state);
}
void intel_display_irq_init(struct intel_display *display)
{
spin_lock_init(&display->irq.lock);
@ -2472,6 +2619,19 @@ void intel_display_irq_init(struct intel_display *display)
INIT_WORK(&display->irq.vblank_notify_work,
intel_display_vblank_notify_work);
if (DISPLAY_VER(display) >= 11)
display->irq.funcs = &gen11_display_irq_funcs;
else if (display->platform.cherryview || display->platform.valleyview)
display->irq.funcs = &vlv_display_irq_funcs;
else if (DISPLAY_VER(display) >= 8)
display->irq.funcs = &gen8_display_irq_funcs;
else if (DISPLAY_VER(display) >= 5)
display->irq.funcs = &ilk_display_irq_funcs;
else if (DISPLAY_VER(display) == 4)
display->irq.funcs = &i965_display_irq_funcs;
else
display->irq.funcs = &i915_display_irq_funcs;
}
struct intel_display_irq_snapshot {

View File

@ -51,41 +51,30 @@ void bdw_disable_vblank(struct drm_crtc *crtc);
void ilk_display_irq_master_disable(struct intel_display *display, u32 *de_ier, u32 *sde_ier);
void ilk_display_irq_master_enable(struct intel_display *display, u32 de_ier, u32 sde_ier);
bool ilk_display_irq_handler(struct intel_display *display);
void gen8_de_irq_handler(struct intel_display *display, u32 master_ctl);
void gen11_display_irq_handler(struct intel_display *display);
u32 gen11_gu_misc_irq_ack(struct intel_display *display, const u32 master_ctl);
void gen11_gu_misc_irq_handler(struct intel_display *display, const u32 iir);
void i9xx_display_irq_reset(struct intel_display *display);
void ilk_display_irq_reset(struct intel_display *display);
void vlv_display_irq_reset(struct intel_display *display);
void gen8_display_irq_reset(struct intel_display *display);
void gen11_display_irq_reset(struct intel_display *display);
struct intel_display_irq_state {
u32 master_ctl;
u32 iir;
u32 eir;
u32 hotplug_status;
u32 dpinvgtt;
u32 pipe_stats[I915_MAX_PIPES];
};
void intel_display_irq_reset(struct intel_display *display);
void intel_display_irq_postinstall(struct intel_display *display);
void intel_display_irq_ack(struct intel_display *display, struct intel_display_irq_state *state);
bool intel_display_irq_handler(struct intel_display *display, const struct intel_display_irq_state *state);
u32 i9xx_display_irq_enable_mask(struct intel_display *display);
void i915_display_irq_postinstall(struct intel_display *display);
void i965_display_irq_postinstall(struct intel_display *display);
void vlv_display_irq_postinstall(struct intel_display *display);
void ilk_de_irq_postinstall(struct intel_display *display);
void gen8_de_irq_postinstall(struct intel_display *display);
void gen11_de_irq_postinstall(struct intel_display *display);
void dg1_de_irq_postinstall(struct intel_display *display);
u32 i915_pipestat_enable_mask(struct intel_display *display, enum pipe pipe);
void i915_enable_pipestat(struct intel_display *display, enum pipe pipe, u32 status_mask);
void i915_disable_pipestat(struct intel_display *display, enum pipe pipe, u32 status_mask);
void i9xx_pipestat_irq_ack(struct intel_display *display, u32 iir, u32 pipe_stats[I915_MAX_PIPES]);
void i915_pipestat_irq_handler(struct intel_display *display, u32 iir, u32 pipe_stats[I915_MAX_PIPES]);
void i965_pipestat_irq_handler(struct intel_display *display, u32 iir, u32 pipe_stats[I915_MAX_PIPES]);
void valleyview_pipestat_irq_handler(struct intel_display *display, u32 pipe_stats[I915_MAX_PIPES]);
void vlv_display_error_irq_ack(struct intel_display *display, u32 *eir, u32 *dpinvgtt);
void vlv_display_error_irq_handler(struct intel_display *display, u32 eir, u32 dpinvgtt);
void intel_display_irq_init(struct intel_display *display);
void i915gm_irq_cstate_wa(struct intel_display *display, bool enable);

View File

@ -1018,13 +1018,13 @@ static u32 get_allowed_dc_mask(struct intel_display *display, int enable_dc)
}
/**
* intel_power_domains_init - initializes the power domain structures
* intel_display_power_init - initializes the power domain structures
* @display: display device instance
*
* Initializes the power domain structures for @display depending upon the
* supported platform.
*/
int intel_power_domains_init(struct intel_display *display)
int intel_display_power_init(struct intel_display *display)
{
struct i915_power_domains *power_domains = &display->power.domains;
@ -1045,12 +1045,12 @@ int intel_power_domains_init(struct intel_display *display)
}
/**
* intel_power_domains_cleanup - clean up power domains resources
* intel_display_power_cleanup - clean up power domains resources
* @display: display device instance
*
* Release any resources acquired by intel_power_domains_init()
* Release any resources acquired by intel_display_power_init()
*/
void intel_power_domains_cleanup(struct intel_display *display)
void intel_display_power_cleanup(struct intel_display *display)
{
intel_display_power_map_cleanup(&display->power.domains);
}
@ -1203,7 +1203,7 @@ static void assert_can_disable_lcpll(struct intel_display *display)
{
struct intel_crtc *crtc;
for_each_intel_crtc(display->drm, crtc)
for_each_intel_crtc(display, crtc)
INTEL_DISPLAY_STATE_WARN(display, crtc->active,
"CRTC for pipe %c enabled\n",
pipe_name(crtc->pipe));
@ -1917,23 +1917,7 @@ static void assert_isp_power_gated(struct intel_display *display)
static void intel_power_domains_verify_state(struct intel_display *display);
/**
* intel_power_domains_init_hw - initialize hardware power domain state
* @display: display device instance
* @resume: Called from resume code paths or not
*
* This function initializes the hardware power domain state and enables all
* power wells belonging to the INIT power domain. Power wells in other
* domains (and not in the INIT domain) are referenced or disabled by
* intel_modeset_readout_hw_state(). After that the reference count of each
* power well must match its HW enabled state, see
* intel_power_domains_verify_state().
*
* It will return with power domains disabled (to be enabled later by
* intel_power_domains_enable()) and must be paired with
* intel_power_domains_driver_remove().
*/
void intel_power_domains_init_hw(struct intel_display *display, bool resume)
static void __intel_display_power_init_hw(struct intel_display *display, bool resume)
{
struct i915_power_domains *power_domains = &display->power.domains;
@ -1967,7 +1951,7 @@ void intel_power_domains_init_hw(struct intel_display *display, bool resume)
* Keep all power wells enabled for any dependent HW access during
* initialization and to make sure we keep BIOS enabled display HW
* resources powered until display HW readout is complete. We drop
* this reference in intel_power_domains_enable().
* this reference in intel_display_power_enable().
*/
drm_WARN_ON(display->drm, power_domains->init_wakeref);
power_domains->init_wakeref =
@ -1985,17 +1969,37 @@ void intel_power_domains_init_hw(struct intel_display *display, bool resume)
}
/**
* intel_power_domains_driver_remove - deinitialize hw power domain state
* intel_display_power_init_hw - initialize hardware power domain state
* @display: display device instance
*
* This function initializes the hardware power domain state and enables all
* power wells belonging to the INIT power domain. Power wells in other
* domains (and not in the INIT domain) are referenced or disabled by
* intel_modeset_readout_hw_state(). After that the reference count of each
* power well must match its HW enabled state, see
* intel_power_domains_verify_state().
*
* It will return with power domains disabled (to be enabled later by
* intel_display_power_enable()) and must be paired with
* intel_display_power_driver_remove().
*/
void intel_display_power_init_hw(struct intel_display *display)
{
__intel_display_power_init_hw(display, false);
}
/**
* intel_display_power_driver_remove - deinitialize hw power domain state
* @display: display device instance
*
* De-initializes the display power domain HW state. It also ensures that the
* device stays powered up so that the driver can be reloaded.
*
* It must be called with power domains already disabled (after a call to
* intel_power_domains_disable()) and must be paired with
* intel_power_domains_init_hw().
* intel_display_power_disable()) and must be paired with
* intel_display_power_init_hw().
*/
void intel_power_domains_driver_remove(struct intel_display *display)
void intel_display_power_driver_remove(struct intel_display *display)
{
struct ref_tracker *wakeref __maybe_unused =
fetch_and_zero(&display->power.domains.init_wakeref);
@ -2014,7 +2018,7 @@ void intel_power_domains_driver_remove(struct intel_display *display)
}
/**
* intel_power_domains_sanitize_state - sanitize power domains state
* intel_display_power_sanitize_state - sanitize power domains state
* @display: display device instance
*
* Sanitize the power domains state during driver loading and system resume.
@ -2023,7 +2027,7 @@ void intel_power_domains_driver_remove(struct intel_display *display)
* on it by the time this function is called, after the state of all the
* pipe, encoder, etc. HW resources have been sanitized).
*/
void intel_power_domains_sanitize_state(struct intel_display *display)
void intel_display_power_sanitize_state(struct intel_display *display)
{
struct i915_power_domains *power_domains = &display->power.domains;
struct i915_power_well *power_well;
@ -2045,18 +2049,18 @@ void intel_power_domains_sanitize_state(struct intel_display *display)
}
/**
* intel_power_domains_enable - enable toggling of display power wells
* intel_display_power_enable - enable toggling of display power wells
* @display: display device instance
*
* Enable the ondemand enabling/disabling of the display power wells. Note that
* power wells not belonging to POWER_DOMAIN_INIT are allowed to be toggled
* only at specific points of the display modeset sequence, thus they are not
* affected by the intel_power_domains_enable()/disable() calls. The purpose
* affected by the intel_display_power_enable()/disable() calls. The purpose
* of these function is to keep the rest of power wells enabled until the end
* of display HW readout (which will acquire the power references reflecting
* the current HW state).
*/
void intel_power_domains_enable(struct intel_display *display)
void intel_display_power_enable(struct intel_display *display)
{
struct ref_tracker *wakeref __maybe_unused =
fetch_and_zero(&display->power.domains.init_wakeref);
@ -2066,13 +2070,13 @@ void intel_power_domains_enable(struct intel_display *display)
}
/**
* intel_power_domains_disable - disable toggling of display power wells
* intel_display_power_disable - disable toggling of display power wells
* @display: display device instance
*
* Disable the ondemand enabling/disabling of the display power wells. See
* intel_power_domains_enable() for which power wells this call controls.
* intel_display_power_enable() for which power wells this call controls.
*/
void intel_power_domains_disable(struct intel_display *display)
void intel_display_power_disable(struct intel_display *display)
{
struct i915_power_domains *power_domains = &display->power.domains;
@ -2092,9 +2096,9 @@ void intel_power_domains_disable(struct intel_display *display)
* system suspend.
*
* It must be called with power domains already disabled (after a call to
* intel_power_domains_disable()) and paired with intel_power_domains_resume().
* intel_display_power_disable()) and paired with intel_power_domains_resume().
*/
void intel_power_domains_suspend(struct intel_display *display, bool s2idle)
static void intel_power_domains_suspend(struct intel_display *display, bool s2idle)
{
struct i915_power_domains *power_domains = &display->power.domains;
struct ref_tracker *wakeref __maybe_unused =
@ -2144,15 +2148,15 @@ void intel_power_domains_suspend(struct intel_display *display, bool s2idle)
* This function resume the hardware power domain state during system resume.
*
* It will return with power domain support disabled (to be enabled later by
* intel_power_domains_enable()) and must be paired with
* intel_display_power_enable()) and must be paired with
* intel_power_domains_suspend().
*/
void intel_power_domains_resume(struct intel_display *display)
static void intel_power_domains_resume(struct intel_display *display)
{
struct i915_power_domains *power_domains = &display->power.domains;
if (power_domains->display_core_suspended) {
intel_power_domains_init_hw(display, true);
__intel_display_power_init_hw(display, true);
power_domains->display_core_suspended = false;
} else {
drm_WARN_ON(display->drm, power_domains->init_wakeref);
@ -2285,7 +2289,7 @@ void intel_display_power_resume_early(struct intel_display *display)
intel_power_domains_resume(display);
}
void intel_display_power_suspend(struct intel_display *display)
void intel_display_power_runtime_suspend(struct intel_display *display)
{
if (DISPLAY_VER(display) >= 11) {
icl_display_core_uninit(display);
@ -2298,7 +2302,7 @@ void intel_display_power_suspend(struct intel_display *display)
}
}
void intel_display_power_resume(struct intel_display *display)
void intel_display_power_runtime_resume(struct intel_display *display)
{
struct i915_power_domains *power_domains = &display->power.domains;

View File

@ -169,24 +169,23 @@ struct intel_display_power_domain_set {
for ((__domain) = 0; (__domain) < POWER_DOMAIN_NUM; (__domain)++) \
for_each_if(test_bit((__domain), (__mask)->bits))
int intel_power_domains_init(struct intel_display *display);
void intel_power_domains_cleanup(struct intel_display *display);
void intel_power_domains_init_hw(struct intel_display *display, bool resume);
void intel_power_domains_driver_remove(struct intel_display *display);
void intel_power_domains_enable(struct intel_display *display);
void intel_power_domains_disable(struct intel_display *display);
void intel_power_domains_suspend(struct intel_display *display, bool s2idle);
void intel_power_domains_resume(struct intel_display *display);
void intel_power_domains_sanitize_state(struct intel_display *display);
int intel_display_power_init(struct intel_display *display);
void intel_display_power_cleanup(struct intel_display *display);
void intel_display_power_init_hw(struct intel_display *display);
void intel_display_power_driver_remove(struct intel_display *display);
void intel_display_power_enable(struct intel_display *display);
void intel_display_power_disable(struct intel_display *display);
void intel_display_power_sanitize_state(struct intel_display *display);
void intel_display_power_suspend_late(struct intel_display *display, bool s2idle);
void intel_display_power_resume_early(struct intel_display *display);
void intel_display_power_suspend(struct intel_display *display);
void intel_display_power_resume(struct intel_display *display);
void intel_display_power_set_target_dc_state(struct intel_display *display,
u32 state);
u32 intel_display_power_get_current_dc_state(struct intel_display *display);
void intel_display_power_runtime_suspend(struct intel_display *display);
void intel_display_power_runtime_resume(struct intel_display *display);
bool intel_display_power_is_enabled(struct intel_display *display,
enum intel_display_power_domain domain);
struct ref_tracker *intel_display_power_get(struct intel_display *display,

View File

@ -84,7 +84,7 @@ TRACE_EVENT(intel_pipe_enable,
sizeof(__entry->frame[0]) * I915_MAX_PIPES);
memset(__entry->scanline, 0,
sizeof(__entry->scanline[0]) * I915_MAX_PIPES);
for_each_intel_crtc(display->drm, it__) {
for_each_intel_crtc(display, it__) {
__entry->frame[it__->pipe] = intel_crtc_get_vblank_counter(it__);
__entry->scanline[it__->pipe] = intel_get_crtc_scanline(it__);
}
@ -114,7 +114,7 @@ TRACE_EVENT(intel_pipe_disable,
sizeof(__entry->frame[0]) * I915_MAX_PIPES);
memset(__entry->scanline, 0,
sizeof(__entry->scanline[0]) * I915_MAX_PIPES);
for_each_intel_crtc(display->drm, it__) {
for_each_intel_crtc(display, it__) {
__entry->frame[it__->pipe] = intel_crtc_get_vblank_counter(it__);
__entry->scanline[it__->pipe] = intel_get_crtc_scanline(it__);
}
@ -244,7 +244,7 @@ TRACE_EVENT(intel_memory_cxsr,
sizeof(__entry->frame[0]) * I915_MAX_PIPES);
memset(__entry->scanline, 0,
sizeof(__entry->scanline[0]) * I915_MAX_PIPES);
for_each_intel_crtc(display->drm, crtc) {
for_each_intel_crtc(display, crtc) {
__entry->frame[crtc->pipe] = intel_crtc_get_vblank_counter(crtc);
__entry->scanline[crtc->pipe] = intel_get_crtc_scanline(crtc);
}

View File

@ -1035,6 +1035,7 @@ struct intel_crtc_state {
/* logical state of LUTs */
struct drm_property_blob *degamma_lut, *gamma_lut, *ctm;
struct drm_display_mode mode, pipe_mode, adjusted_mode;
u32 background_color;
enum drm_scaling_filter scaling_filter;
u8 sharpness_strength;
} hw;
@ -1790,6 +1791,8 @@ struct intel_psr {
u8 active_non_psr_pipes;
const char *no_psr_reason;
struct ref_tracker *vblank_wakeref;
};
struct intel_dp {
@ -1820,6 +1823,7 @@ struct intel_dp {
/* intersection of source and sink rates */
int num_common_rates;
int common_rates[DP_MAX_SUPPORTED_RATES];
int max_common_lane_count;
struct {
/* TODO: move the rest of link specific fields to here */
bool active;
@ -1872,6 +1876,7 @@ struct intel_dp {
/* connector directly attached - won't be use for modeset in mst world */
struct intel_connector *attached_connector;
bool as_sdp_supported;
bool as_sdp_v2_supported;
struct drm_dp_tunnel *tunnel;
bool tunnel_suspended:1;

View File

@ -136,6 +136,8 @@ bool __intel_display_wa(struct intel_display *display, enum intel_display_wa wa,
return DISPLAY_VER(display) == 20 &&
IS_DISPLAY_VERx100_STEP(display, 3000,
STEP_A0, STEP_B0);
case INTEL_DISPLAY_WA_16029024088:
return DISPLAY_VER(display) >= 35;
case INTEL_DISPLAY_WA_18034343758:
return DISPLAY_VER(display) == 20 ||
(display->platform.pantherlake &&

View File

@ -52,6 +52,7 @@ enum intel_display_wa {
INTEL_DISPLAY_WA_16023588340,
INTEL_DISPLAY_WA_16025573575,
INTEL_DISPLAY_WA_16025596647,
INTEL_DISPLAY_WA_16029024088,
INTEL_DISPLAY_WA_18034343758,
INTEL_DISPLAY_WA_22010178259,
INTEL_DISPLAY_WA_22010947358,

View File

@ -39,6 +39,13 @@
* current implementation, we only need one wakelock, so only
* DMC_WAKELOCK1_CTL is used. The other definitions are here for
* potential future use.
*
* This is available starting with Xe2_LPD (display version 20) as an
* experimental feature and on Xe3_LPD (display version 30) as the
* first display release with official support. That means that we
* only enable the feature by default on the latter and using it on
* the former requires explicitly using the enable_dmc_wl module
* parameter.
*/
/*
@ -286,7 +293,7 @@ static void intel_dmc_wl_sanitize_param(struct intel_display *display)
{
const char *desc;
if (!HAS_DMC_WAKELOCK(display)) {
if (DISPLAY_VER(display) < 20) {
display->params.enable_dmc_wl = ENABLE_DMC_WL_DISABLED;
} else if (display->params.enable_dmc_wl < 0) {
if (DISPLAY_VER(display) >= 30)

View File

@ -362,19 +362,30 @@ int intel_dp_max_source_lane_count(struct intel_digital_port *dig_port)
return max_lanes;
}
/* Theoretical max between source and sink */
int intel_dp_max_common_lane_count(struct intel_dp *intel_dp)
/*
* Theoretical max between source and sink.
* Return %true if the max common lane count changed.
*/
static bool intel_dp_set_max_common_lane_count(struct intel_dp *intel_dp)
{
struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
int source_max = intel_dp_max_source_lane_count(dig_port);
int sink_max = intel_dp->max_sink_lane_count;
int lane_max = intel_tc_port_max_lane_count(dig_port);
int lttpr_max = drm_dp_lttpr_max_lane_count(intel_dp->lttpr_common_caps);
int old_max_common_lane_count = intel_dp->max_common_lane_count;
if (lttpr_max)
sink_max = min(sink_max, lttpr_max);
return min3(source_max, sink_max, lane_max);
intel_dp->max_common_lane_count = min3(source_max, sink_max, lane_max);
return intel_dp->max_common_lane_count != old_max_common_lane_count;
}
int intel_dp_max_common_lane_count(struct intel_dp *intel_dp)
{
return intel_dp->max_common_lane_count;
}
static int forced_lane_count(struct intel_dp *intel_dp)
@ -787,13 +798,22 @@ int intel_dp_link_config_index(struct intel_dp *intel_dp, int link_rate, int lan
return -1;
}
static void intel_dp_set_common_rates(struct intel_dp *intel_dp)
/* Return %true if the common rates changed. */
static bool intel_dp_set_common_rates(struct intel_dp *intel_dp)
{
struct intel_display *display = to_intel_display(intel_dp);
int num_old_common_rates = intel_dp->num_common_rates;
int old_common_rates[DP_MAX_SUPPORTED_RATES];
drm_WARN_ON(display->drm,
!intel_dp->num_source_rates || !intel_dp->num_sink_rates);
/* TODO: Add a struct containing both rates and number of rates. */
static_assert(__same_type(old_common_rates[0], intel_dp->common_rates[0]) &&
sizeof(old_common_rates) == sizeof(intel_dp->common_rates));
memcpy(old_common_rates, intel_dp->common_rates,
num_old_common_rates * sizeof(old_common_rates[0]));
intel_dp->num_common_rates = intersect_rates(intel_dp->source_rates,
intel_dp->num_source_rates,
intel_dp->sink_rates,
@ -806,7 +826,25 @@ static void intel_dp_set_common_rates(struct intel_dp *intel_dp)
intel_dp->num_common_rates = 1;
}
return num_old_common_rates != intel_dp->num_common_rates ||
memcmp(old_common_rates, intel_dp->common_rates,
num_old_common_rates * sizeof(old_common_rates[0]));
}
/* Return %true if any common link param changed. */
static bool intel_dp_set_common_link_params(struct intel_dp *intel_dp)
{
bool params_changed = false;
if (intel_dp_set_common_rates(intel_dp))
params_changed = true;
if (intel_dp_set_max_common_lane_count(intel_dp))
params_changed = true;
intel_dp_link_config_init(intel_dp);
return params_changed;
}
bool intel_dp_link_params_valid(struct intel_dp *intel_dp, int link_rate,
@ -3172,16 +3210,20 @@ static void intel_dp_compute_vsc_colorimetry(const struct intel_crtc_state *crtc
static bool intel_dp_needs_as_sdp(struct intel_dp *intel_dp,
struct intel_crtc_state *crtc_state)
{
if (!intel_dp->as_sdp_supported)
if (!intel_dp->as_sdp_v2_supported)
return false;
/*
* #TODO Implement AS SDP for DP branch device.
* #TODO: Add AS SDP v1 support for PCONs (DP branch devices).
*/
if (drm_dp_is_branch(intel_dp->dpcd))
return false;
return crtc_state->vrr.enable;
if (intel_psr_needs_alpm_aux_less(intel_dp, crtc_state) &&
!intel_psr_pr_async_video_timing_supported(intel_dp))
return true;
return intel_vrr_possible(crtc_state);
}
static void intel_dp_compute_as_sdp(struct intel_dp *intel_dp,
@ -3204,16 +3246,34 @@ static void intel_dp_compute_as_sdp(struct intel_dp *intel_dp,
as_sdp->sdp_type = DP_SDP_ADAPTIVE_SYNC;
as_sdp->length = 0x9;
as_sdp->duration_incr_ms = 0;
as_sdp->revision = 0x2;
as_sdp->vtotal = intel_vrr_vmin_vtotal(crtc_state);
if (crtc_state->cmrr.enable) {
as_sdp->mode = DP_AS_SDP_FAVT_TRR_REACHED;
as_sdp->target_rr = drm_mode_vrefresh(adjusted_mode);
as_sdp->target_rr_divider = true;
} else {
} else if (crtc_state->vrr.enable) {
as_sdp->mode = DP_AS_SDP_AVT_DYNAMIC_VTOTAL;
as_sdp->target_rr = 0;
} else {
as_sdp->mode = DP_AS_SDP_AVT_FIXED_VTOTAL;
}
/*
* For Panel Replay with Async Video Timing support, the source can
* disable sending the AS SDP during PR Active state. In that case,
* the sink needs the coasting vtotal value to maintain the refresh
* rate. The HW only samples this on PR_ALPM_CTL[AS SDP Transmission
* in Active Disable], which we never program, so providing the value
* unconditionally when the sink advertises the capability is safe.
*
* #TODO:
* If we ever advertise support for coasting at other refresh targets,
* this logic could be revisited. For now, use the minimum refresh rate
* as the only safe coasting value.
*/
if (intel_psr_pr_async_video_timing_supported(intel_dp))
as_sdp->coasting_vtotal = crtc_state->vrr.vmax;
}
static void intel_dp_compute_vsc_sdp(struct intel_dp *intel_dp,
@ -3688,8 +3748,8 @@ intel_dp_compute_config(struct intel_encoder *encoder,
pipe_config->dp_m_n.data_m *= pipe_config->splitter.link_count;
intel_vrr_compute_config(pipe_config, conn_state);
intel_dp_compute_as_sdp(intel_dp, pipe_config);
intel_psr_compute_config(intel_dp, pipe_config, conn_state);
intel_dp_compute_as_sdp(intel_dp, pipe_config);
intel_alpm_lobf_compute_config(intel_dp, pipe_config, conn_state);
intel_dp_drrs_compute_config(connector, pipe_config, link_bpp_x16);
intel_dp_compute_vsc_sdp(intel_dp, pipe_config, conn_state);
@ -4874,9 +4934,21 @@ intel_dp_has_sink_count(struct intel_dp *intel_dp)
void intel_dp_update_sink_caps(struct intel_dp *intel_dp)
{
struct intel_display *display = to_intel_display(intel_dp);
intel_dp_set_sink_rates(intel_dp);
intel_dp_set_max_sink_lane_count(intel_dp);
intel_dp_set_common_rates(intel_dp);
/*
* Handle unexpected sink cap changes, or a race between setting
* the deferred link params flag in the HPD IRQ handler and
* clearing the flag during connector detect.
*/
if (intel_dp_set_common_link_params(intel_dp) &&
!intel_dp->reset_link_params) {
drm_dbg_kms(display->drm,
"DPRX capabilities changed before long HPD or RX_CAP_CHANGED signal\n");
intel_dp->reset_link_params = true;
}
}
static bool
@ -5180,7 +5252,7 @@ static ssize_t intel_dp_as_sdp_pack(const struct drm_dp_as_sdp *as_sdp,
/* Prepare AS (Adaptive Sync) SDP Header */
sdp->sdp_header.HB0 = 0;
sdp->sdp_header.HB1 = as_sdp->sdp_type;
sdp->sdp_header.HB2 = 0x02;
sdp->sdp_header.HB2 = as_sdp->revision;
sdp->sdp_header.HB3 = as_sdp->length;
/* Fill AS (Adaptive Sync) SDP Payload */
@ -5193,6 +5265,9 @@ static ssize_t intel_dp_as_sdp_pack(const struct drm_dp_as_sdp *as_sdp,
if (as_sdp->target_rr_divider)
sdp->db[4] |= 0x20;
sdp->db[7] = as_sdp->coasting_vtotal & 0xFF;
sdp->db[8] = (as_sdp->coasting_vtotal >> 8) & 0xFF;
return length;
}
@ -5367,17 +5442,17 @@ int intel_dp_as_sdp_unpack(struct drm_dp_as_sdp *as_sdp,
if (sdp->sdp_header.HB1 != DP_SDP_ADAPTIVE_SYNC)
return -EINVAL;
if (sdp->sdp_header.HB2 != 0x02)
return -EINVAL;
if ((sdp->sdp_header.HB3 & 0x3F) != 9)
return -EINVAL;
as_sdp->sdp_type = sdp->sdp_header.HB1;
as_sdp->length = sdp->sdp_header.HB3 & DP_AS_SDP_LENGTH_MASK;
as_sdp->revision = sdp->sdp_header.HB2;
as_sdp->mode = sdp->db[0] & DP_AS_SDP_OPERATION_MODE_MASK;
as_sdp->vtotal = (sdp->db[2] << 8) | sdp->db[1];
as_sdp->target_rr = ((sdp->db[4] & 0x3) << 8) | sdp->db[3];
as_sdp->target_rr_divider = sdp->db[4] & 0x20 ? true : false;
as_sdp->coasting_vtotal = (sdp->db[8] << 8) | sdp->db[7];
return 0;
}
@ -6000,8 +6075,10 @@ static bool intel_dp_handle_link_service_irq(struct intel_dp *intel_dp, u8 irq_m
drm_WARN_ON(display->drm, irq_mask & ~(INTEL_DP_LINK_SERVICE_IRQ_MASK_SST |
INTEL_DP_LINK_SERVICE_IRQ_MASK_MST));
if (irq_mask & RX_CAP_CHANGED)
if (irq_mask & RX_CAP_CHANGED) {
intel_dp->reset_link_params = true;
reprobe_needed = true;
}
if (irq_mask & LINK_STATUS_CHANGED)
intel_dp_check_link_state(intel_dp);
@ -6365,6 +6442,46 @@ intel_dp_unset_edid(struct intel_dp *intel_dp)
false);
}
static bool
intel_dp_sink_supports_as_sdp_v2(struct intel_dp *intel_dp)
{
u8 rx_features;
/*
* The DP spec does not explicitly provide the AS SDP v2 capability.
* So based on the DP v2.1 SCR, we infer it from the following bits:
*
* DP_AS_SDP_FAVT_PAYLOAD_FIELDS_PARSING_SUPPORTED indicates support for
* FAVT, which is explicitly defined to use AS SDP v2.
*
* DP_ASYNC_VIDEO_TIMING_NOT_SUPPORTED_IN_PR indicates that the sink
* does not support asynchronous video timing while in PR Active,
* requiring the source to keep transmitting Adaptive-Sync SDPs. The
* spec mandates that such sinks shall support AS SDP v2.
*
* #TODO: Check the Adaptive-Sync DisplayID 2.1 block once DisplayID
* parsing is available. This may help detect AS SDP v2 support for
* native DP 2.1 sinks that do not expose FAVT or PR-based capability
* bits.
*
* In the presence of PCONs, check PCON support from DPCD and sink
* support from Display ID.
*/
if (drm_dp_dpcd_read_byte(&intel_dp->aux,
DP_DPRX_FEATURE_ENUMERATION_LIST_CONT_1,
&rx_features) == 1) {
if (rx_features & DP_AS_SDP_FAVT_PAYLOAD_FIELDS_PARSING_SUPPORTED)
return true;
}
if (intel_dp->psr.sink_panel_replay_support &&
!intel_psr_pr_async_video_timing_supported(intel_dp))
return true;
return false;
}
static void
intel_dp_detect_sdp_caps(struct intel_dp *intel_dp)
{
@ -6372,6 +6489,15 @@ intel_dp_detect_sdp_caps(struct intel_dp *intel_dp)
intel_dp->as_sdp_supported = HAS_AS_SDP(display) &&
drm_dp_as_sdp_supported(&intel_dp->aux, intel_dp->dpcd);
if (!intel_dp->as_sdp_supported)
return;
/* eDP Adaptive-Sync SDP always uses AS SDP v2 */
if (intel_dp_is_edp(intel_dp))
intel_dp->as_sdp_v2_supported = true;
else
intel_dp->as_sdp_v2_supported = intel_dp_sink_supports_as_sdp_v2(intel_dp);
}
static bool intel_dp_needs_dpcd_probe(struct intel_dp *intel_dp, bool force_on_external)
@ -6751,7 +6877,7 @@ static int intel_modeset_affected_transcoders(struct intel_atomic_state *state,
if (transcoders == 0)
return 0;
for_each_intel_crtc(display->drm, crtc) {
for_each_intel_crtc(display, crtc) {
struct intel_crtc_state *crtc_state;
int ret;
@ -7316,7 +7442,7 @@ intel_dp_init_connector(struct intel_digital_port *dig_port,
}
intel_dp_set_source_rates(intel_dp);
intel_dp_set_common_rates(intel_dp);
intel_dp_set_common_link_params(intel_dp);
intel_dp_reset_link_params(intel_dp);
/* init MST on ports that can support it */
@ -7465,7 +7591,6 @@ int intel_dp_get_lines_for_sdp(const struct intel_crtc_state *crtc_state, u32 ty
int intel_dp_sdp_min_guardband(const struct intel_crtc_state *crtc_state,
bool assume_all_enabled)
{
struct intel_display *display = to_intel_display(crtc_state);
int sdp_guardband = 0;
if (assume_all_enabled ||
@ -7480,8 +7605,8 @@ int intel_dp_sdp_min_guardband(const struct intel_crtc_state *crtc_state,
sdp_guardband = max(sdp_guardband,
intel_dp_get_lines_for_sdp(crtc_state, DP_SDP_PPS));
if ((assume_all_enabled && HAS_AS_SDP(display)) ||
crtc_state->infoframes.enable & intel_hdmi_infoframe_enable(DP_SDP_ADAPTIVE_SYNC))
if (crtc_state->infoframes.enable &
intel_hdmi_infoframe_enable(DP_SDP_ADAPTIVE_SYNC))
sdp_guardband = max(sdp_guardband,
intel_dp_get_lines_for_sdp(crtc_state, DP_SDP_ADAPTIVE_SYNC));
@ -7506,3 +7631,14 @@ bool intel_dp_joiner_candidate_valid(struct intel_connector *connector,
return true;
}
u8 intel_dp_as_sdp_transmission_time(void)
{
/*
* DP allows AS SDP position to move during PR active in some cases, but
* software-controlled refresh rate changes with DC6v / ALPM require the
* AS SDP to remain at T1. Use T1 unconditionally for now.
*/
return DP_PR_AS_SDP_SETUP_TIME_T1;
}

View File

@ -241,4 +241,6 @@ bool intel_dp_joiner_candidate_valid(struct intel_connector *connector,
for ((__num_joined_pipes) = 1; (__num_joined_pipes) <= (I915_MAX_PIPES); (__num_joined_pipes)++) \
for_each_if(intel_dp_joiner_candidate_valid(__connector, (__mode)->hdisplay, __num_joined_pipes))
u8 intel_dp_as_sdp_transmission_time(void);
#endif /* __INTEL_DP_H__ */

View File

@ -12,6 +12,7 @@
#include "intel_dp.h"
#include "intel_dp_aux.h"
#include "intel_dp_aux_regs.h"
#include "intel_parent.h"
#include "intel_pps.h"
#include "intel_quirks.h"
#include "intel_tc.h"
@ -60,18 +61,29 @@ intel_dp_aux_wait_done(struct intel_dp *intel_dp)
struct intel_display *display = to_intel_display(intel_dp);
intel_reg_t ch_ctl = intel_dp->aux_ch_ctl_reg(intel_dp);
const unsigned int timeout_ms = 10;
bool done = true;
u32 status;
bool done;
int ret;
if (intel_parent_irq_enabled(display)) {
#define C (((status = intel_de_read_notrace(display, ch_ctl)) & DP_AUX_CH_CTL_SEND_BUSY) == 0)
done = wait_event_timeout(display->gmbus.wait_queue, C,
msecs_to_jiffies_timeout(timeout_ms));
done = wait_event_timeout(display->gmbus.wait_queue, C,
msecs_to_jiffies_timeout(timeout_ms));
#undef C
} else {
ret = intel_de_wait_ms(display, ch_ctl,
DP_AUX_CH_CTL_SEND_BUSY, 0,
timeout_ms, &status);
if (ret == -ETIMEDOUT)
done = false;
}
if (!done)
drm_err(display->drm,
"%s: did not complete or timeout within %ums (status 0x%08x)\n",
intel_dp->aux.name, timeout_ms, status);
#undef C
return status;
}

View File

@ -691,10 +691,9 @@ int intel_dp_aux_init_backlight_funcs(struct intel_connector *connector)
struct intel_dp *intel_dp = intel_attached_dp(connector);
struct drm_device *dev = connector->base.dev;
struct intel_panel *panel = &connector->panel;
bool try_intel_interface = false;
bool try_intel_interface = false, try_vesa_interface = false;
/*
* Check the VBT and user's module parameters to figure out which
/* Check the VBT and user's module parameters to figure out which
* interfaces to probe
*/
switch (display->params.enable_dpcd_backlight) {
@ -703,6 +702,7 @@ int intel_dp_aux_init_backlight_funcs(struct intel_connector *connector)
case INTEL_DP_AUX_BACKLIGHT_AUTO:
switch (panel->vbt.backlight.type) {
case INTEL_BACKLIGHT_VESA_EDP_AUX_INTERFACE:
try_vesa_interface = true;
break;
case INTEL_BACKLIGHT_DISPLAY_DDI:
try_intel_interface = true;
@ -715,12 +715,20 @@ int intel_dp_aux_init_backlight_funcs(struct intel_connector *connector)
if (panel->vbt.backlight.type != INTEL_BACKLIGHT_VESA_EDP_AUX_INTERFACE)
try_intel_interface = true;
try_vesa_interface = true;
break;
case INTEL_DP_AUX_BACKLIGHT_FORCE_VESA:
try_vesa_interface = true;
break;
case INTEL_DP_AUX_BACKLIGHT_FORCE_INTEL:
try_intel_interface = true;
break;
}
/* For eDP 1.5 and above we are supposed to use VESA interface for brightness control */
if (intel_dp->edp_dpcd[0] >= DP_EDP_15)
try_vesa_interface = true;
/*
* Since Intel has their own backlight control interface, the majority of machines out there
* using DPCD backlight controls with Intel GPUs will be using this interface as opposed to
@ -733,9 +741,6 @@ int intel_dp_aux_init_backlight_funcs(struct intel_connector *connector)
* panel with Intel's OUI - which is also required for us to be able to detect Intel's
* backlight interface at all. This means that the only sensible way for us to detect both
* interfaces is to probe for Intel's first, and VESA's second.
*
* Also there is a chance some VBTs may advertise false Intel backlight support even if the
* TCON DPCD says otherwise. This means we keep VESA interface as fallback in that case.
*/
if (try_intel_interface && intel_dp->edp_dpcd[0] <= DP_EDP_14b &&
intel_dp_aux_supports_hdr_backlight(connector)) {
@ -745,7 +750,7 @@ int intel_dp_aux_init_backlight_funcs(struct intel_connector *connector)
return 0;
}
if (intel_dp_aux_supports_vesa_backlight(connector)) {
if (try_vesa_interface && intel_dp_aux_supports_vesa_backlight(connector)) {
drm_dbg_kms(dev, "[CONNECTOR:%d:%s] Using VESA eDP backlight controls\n",
connector->base.base.id, connector->base.name);
panel->backlight.funcs = &intel_dp_vesa_bl_funcs;

View File

@ -34,8 +34,10 @@
#include "intel_dp.h"
#include "intel_dp_link_training.h"
#include "intel_encoder.h"
#include "intel_hdmi.h"
#include "intel_hotplug.h"
#include "intel_panel.h"
#include "intel_psr.h"
#define LT_MSG_PREFIX "[CONNECTOR:%d:%s][ENCODER:%d:%s][%s] "
#define LT_MSG_ARGS(_intel_dp, _dp_phy) (_intel_dp)->attached_connector->base.base.id, \
@ -710,16 +712,28 @@ static bool intel_dp_link_max_vswing_reached(struct intel_dp *intel_dp,
return true;
}
void intel_dp_link_training_set_mode(struct intel_dp *intel_dp, int link_rate, bool is_vrr)
void intel_dp_link_training_set_mode(struct intel_dp *intel_dp, int link_rate,
bool is_vrr,
bool pr_with_as_sdp_enable)
{
u8 link_config[2];
link_config[0] = is_vrr ? DP_MSA_TIMING_PAR_IGNORE_EN : 0;
link_config[0] |= pr_with_as_sdp_enable ? DP_FIXED_VTOTAL_AS_SDP_EN_IN_PR_ACTIVE : 0;
link_config[1] = drm_dp_is_uhbr_rate(link_rate) ?
DP_SET_ANSI_128B132B : DP_SET_ANSI_8B10B;
drm_dp_dpcd_write(&intel_dp->aux, DP_DOWNSPREAD_CTRL, link_config, 2);
}
static bool
intel_dp_pr_with_as_sdp_enabled(struct intel_dp *intel_dp,
const struct intel_crtc_state *crtc_state)
{
return intel_psr_needs_alpm_aux_less(intel_dp, crtc_state) &&
(crtc_state->infoframes.enable &
intel_hdmi_infoframe_enable(DP_SDP_ADAPTIVE_SYNC));
}
static void intel_dp_update_downspread_ctrl(struct intel_dp *intel_dp,
const struct intel_crtc_state *crtc_state)
{
@ -737,7 +751,9 @@ static void intel_dp_update_downspread_ctrl(struct intel_dp *intel_dp,
* especially on the first real commit when clearing the inherited flag.
*/
intel_dp_link_training_set_mode(intel_dp,
crtc_state->port_clock, crtc_state->vrr.in_range);
crtc_state->port_clock,
crtc_state->vrr.in_range,
intel_dp_pr_with_as_sdp_enabled(intel_dp, crtc_state));
}
void intel_dp_link_training_set_bw(struct intel_dp *intel_dp,

View File

@ -18,7 +18,8 @@ int intel_dp_init_lttpr_and_dprx_caps(struct intel_dp *intel_dp);
bool intel_dp_lttpr_transparent_mode_enabled(struct intel_dp *intel_dp);
void intel_dp_link_training_set_mode(struct intel_dp *intel_dp,
int link_rate, bool is_vrr);
int link_rate, bool is_vrr,
bool pr_with_as_sdp_enable);
void intel_dp_link_training_set_bw(struct intel_dp *intel_dp,
int link_bw, int rate_select, int lane_count,
bool enhanced_framing, bool post_lt_adj_req);

View File

@ -837,7 +837,7 @@ static int intel_dp_mst_check_dsc_change(struct intel_atomic_state *state,
mst_pipe_mask = get_pipes_downstream_of_mst_port(state, mst_mgr, NULL);
for_each_intel_crtc_in_pipe_mask(display->drm, crtc, mst_pipe_mask) {
for_each_intel_crtc_in_pipe_mask(display, crtc, mst_pipe_mask) {
struct intel_crtc_state *crtc_state =
intel_atomic_get_new_crtc_state(state, crtc);
@ -1065,14 +1065,13 @@ static void mst_stream_post_disable(struct intel_atomic_state *state,
drm_atomic_get_mst_payload_state(new_mst_state, connector->mst.port);
struct intel_crtc *pipe_crtc;
bool last_mst_stream;
int i;
last_mst_stream = intel_dp_mst_dec_active_streams(intel_dp);
drm_WARN_ON(display->drm, DISPLAY_VER(display) >= 12 && last_mst_stream &&
!intel_dp_mst_is_master_trans(old_crtc_state));
for_each_pipe_crtc_modeset_disable(display, pipe_crtc, old_crtc_state, i) {
for_each_pipe_crtc_modeset_disable(display, pipe_crtc, old_crtc_state) {
const struct intel_crtc_state *old_pipe_crtc_state =
intel_atomic_get_old_crtc_state(state, pipe_crtc);
@ -1099,7 +1098,7 @@ static void mst_stream_post_disable(struct intel_atomic_state *state,
intel_ddi_disable_transcoder_func(old_crtc_state);
for_each_pipe_crtc_modeset_disable(display, pipe_crtc, old_crtc_state, i) {
for_each_pipe_crtc_modeset_disable(display, pipe_crtc, old_crtc_state) {
const struct intel_crtc_state *old_pipe_crtc_state =
intel_atomic_get_old_crtc_state(state, pipe_crtc);
@ -1310,7 +1309,7 @@ static void mst_stream_enable(struct intel_atomic_state *state,
enum transcoder trans = pipe_config->cpu_transcoder;
bool first_mst_stream = intel_dp_mst_active_streams(intel_dp) == 1;
struct intel_crtc *pipe_crtc;
int ret, i;
int ret;
drm_WARN_ON(display->drm, pipe_config->has_pch_encoder);
@ -1355,7 +1354,7 @@ static void mst_stream_enable(struct intel_atomic_state *state,
intel_enable_transcoder(pipe_config);
for_each_pipe_crtc_modeset_enable(display, pipe_crtc, pipe_config, i) {
for_each_pipe_crtc_modeset_enable(display, pipe_crtc, pipe_config) {
const struct intel_crtc_state *pipe_crtc_state =
intel_atomic_get_new_crtc_state(state, pipe_crtc);
@ -2145,7 +2144,7 @@ void intel_dp_mst_prepare_probe(struct intel_dp *intel_dp)
intel_dp_compute_rate(intel_dp, link_rate, &link_bw, &rate_select);
intel_dp_link_training_set_mode(intel_dp, link_rate, false);
intel_dp_link_training_set_mode(intel_dp, link_rate, false, false);
intel_dp_link_training_set_bw(intel_dp, link_bw, rate_select, lane_count,
drm_dp_enhanced_frame_cap(intel_dp->dpcd), false);

View File

@ -471,7 +471,7 @@ static int intel_dp_do_phy_test(struct intel_encoder *encoder,
drm_dbg_kms(display->drm, "[ENCODER:%d:%s] PHY test\n",
encoder->base.base.id, encoder->base.name);
for_each_intel_crtc_in_pipe_mask(display->drm, crtc, pipe_mask) {
for_each_intel_crtc_in_pipe_mask(display, crtc, pipe_mask) {
const struct intel_crtc_state *crtc_state =
to_intel_crtc_state(crtc->base.state);

View File

@ -146,7 +146,7 @@ static int allocate_initial_tunnel_bw_for_pipes(struct intel_dp *intel_dp, u8 pi
int tunnel_bw = 0;
int err;
for_each_intel_crtc_in_pipe_mask(display->drm, crtc, pipe_mask) {
for_each_intel_crtc_in_pipe_mask(display, crtc, pipe_mask) {
const struct intel_crtc_state *crtc_state =
to_intel_crtc_state(crtc->base.state);
int stream_bw = intel_dp_config_required_rate(crtc_state);
@ -740,9 +740,8 @@ static void atomic_decrease_bw(struct intel_atomic_state *state)
struct intel_crtc *crtc;
const struct intel_crtc_state *old_crtc_state;
const struct intel_crtc_state *new_crtc_state;
int i;
for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {
for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state) {
const struct drm_dp_tunnel_state *new_tunnel_state;
struct drm_dp_tunnel *tunnel;
int old_bw;
@ -795,9 +794,8 @@ static void atomic_increase_bw(struct intel_atomic_state *state)
{
struct intel_crtc *crtc;
const struct intel_crtc_state *crtc_state;
int i;
for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i) {
for_each_new_intel_crtc_in_state(state, crtc, crtc_state) {
struct drm_dp_tunnel_state *tunnel_state;
struct drm_dp_tunnel *tunnel = crtc_state->dp_tunnel_ref.tunnel;
int bw;

View File

@ -4965,7 +4965,7 @@ static void readout_dpll_hw_state(struct intel_display *display,
pll->wakeref = intel_display_power_get(display, pll->info->power_domain);
pll->state.pipe_mask = 0;
for_each_intel_crtc(display->drm, crtc) {
for_each_intel_crtc(display, crtc) {
struct intel_crtc_state *crtc_state =
to_intel_crtc_state(crtc->base.state);

View File

@ -137,7 +137,7 @@ static unsigned int intel_drrs_frontbuffer_bits(const struct intel_crtc_state *c
frontbuffer_bits = INTEL_FRONTBUFFER_ALL_MASK(crtc->pipe);
for_each_intel_crtc_in_pipe_mask(display->drm, crtc,
for_each_intel_crtc_in_pipe_mask(display, crtc,
crtc_state->joiner_pipes)
frontbuffer_bits |= INTEL_FRONTBUFFER_ALL_MASK(crtc->pipe);
@ -227,7 +227,7 @@ static void intel_drrs_frontbuffer_update(struct intel_display *display,
{
struct intel_crtc *crtc;
for_each_intel_crtc(display->drm, crtc) {
for_each_intel_crtc(display, crtc) {
unsigned int frontbuffer_bits;
mutex_lock(&crtc->drrs.mutex);

View File

@ -380,7 +380,7 @@ static bool intel_fbdev_init_bios(struct intel_display *display,
unsigned int max_size = 0;
/* Find the largest fb */
for_each_intel_crtc(display->drm, crtc) {
for_each_intel_crtc(display, crtc) {
struct intel_crtc_state *crtc_state =
to_intel_crtc_state(crtc->base.state);
struct intel_plane *plane =
@ -419,7 +419,7 @@ static bool intel_fbdev_init_bios(struct intel_display *display,
}
/* Now make sure all the pipes will fit into it */
for_each_intel_crtc(display->drm, crtc) {
for_each_intel_crtc(display, crtc) {
struct intel_crtc_state *crtc_state =
to_intel_crtc_state(crtc->base.state);
struct intel_plane *plane =
@ -489,7 +489,7 @@ static bool intel_fbdev_init_bios(struct intel_display *display,
drm_framebuffer_get(&ifbdev->fb->base);
/* Final pass to check if any active pipes don't have fbs */
for_each_intel_crtc(display->drm, crtc) {
for_each_intel_crtc(display, crtc) {
struct intel_crtc_state *crtc_state =
to_intel_crtc_state(crtc->base.state);
struct intel_plane *plane =

View File

@ -368,9 +368,8 @@ int intel_fdi_atomic_check_link(struct intel_atomic_state *state,
{
struct intel_crtc *crtc;
struct intel_crtc_state *crtc_state;
int i;
for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i) {
for_each_new_intel_crtc_in_state(state, crtc, crtc_state) {
int ret;
if (!crtc_state->has_pch_encoder ||

View File

@ -527,7 +527,7 @@ void intel_check_cpu_fifo_underruns(struct intel_display *display)
spin_lock_irq(&display->irq.lock);
for_each_intel_crtc(display->drm, crtc) {
for_each_intel_crtc(display, crtc) {
if (crtc->cpu_fifo_underrun_disabled)
continue;
@ -554,7 +554,7 @@ void intel_check_pch_fifo_underruns(struct intel_display *display)
spin_lock_irq(&display->irq.lock);
for_each_intel_crtc(display->drm, crtc) {
for_each_intel_crtc(display, crtc) {
if (crtc->pch_fifo_underrun_disabled)
continue;

View File

@ -132,7 +132,7 @@ void intel_flipq_init(struct intel_display *display)
intel_dmc_wait_fw_load(display);
for_each_intel_crtc(display->drm, crtc)
for_each_intel_crtc(display, crtc)
intel_flipq_crtc_init(crtc);
}

View File

@ -140,7 +140,7 @@ static void assert_global_state_write_locked(struct intel_display *display)
{
struct intel_crtc *crtc;
for_each_intel_crtc(display->drm, crtc)
for_each_intel_crtc(display, crtc)
drm_modeset_lock_assert_held(&crtc->base.mutex);
}
@ -163,7 +163,7 @@ static void assert_global_state_read_locked(struct intel_atomic_state *state)
struct drm_modeset_acquire_ctx *ctx = state->base.acquire_ctx;
struct intel_crtc *crtc;
for_each_intel_crtc(display->drm, crtc) {
for_each_intel_crtc(display, crtc) {
if (modeset_lock_is_held(ctx, &crtc->base.mutex))
return;
}
@ -301,7 +301,7 @@ int intel_atomic_lock_global_state(struct intel_global_state *obj_state)
struct intel_display *display = to_intel_display(state);
struct intel_crtc *crtc;
for_each_intel_crtc(display->drm, crtc) {
for_each_intel_crtc(display, crtc) {
int ret;
ret = drm_modeset_lock(&crtc->base.mutex,
@ -334,7 +334,7 @@ intel_atomic_global_state_is_serialized(struct intel_atomic_state *state)
struct intel_display *display = to_intel_display(state);
struct intel_crtc *crtc;
for_each_intel_crtc(display->drm, crtc)
for_each_intel_crtc(display, crtc)
if (!intel_atomic_get_new_crtc_state(state, crtc))
return false;
return true;

View File

@ -50,7 +50,7 @@ intel_reuse_initial_plane_obj(struct intel_crtc *this,
struct intel_display *display = to_intel_display(this);
struct intel_crtc *crtc;
for_each_intel_crtc(display->drm, crtc) {
for_each_intel_crtc(display, crtc) {
struct intel_plane *plane =
to_intel_plane(crtc->base.primary);
const struct intel_plane_state *plane_state =
@ -208,7 +208,7 @@ void intel_initial_plane_config(struct intel_display *display)
struct intel_initial_plane_configs all_plane_configs = {};
struct intel_crtc *crtc;
for_each_intel_crtc(display->drm, crtc) {
for_each_intel_crtc(display, crtc) {
const struct intel_crtc_state *crtc_state =
to_intel_crtc_state(crtc->base.state);
struct intel_initial_plane_config *plane_config =

View File

@ -108,7 +108,7 @@ static int __intel_link_bw_reduce_bpp(struct intel_atomic_state *state,
struct intel_crtc *crtc;
int max_bpp_x16 = 0;
for_each_intel_crtc_in_pipe_mask(display->drm, crtc, pipe_mask) {
for_each_intel_crtc_in_pipe_mask(display, crtc, pipe_mask) {
struct intel_crtc_state *crtc_state;
int link_bpp_x16;

View File

@ -89,7 +89,7 @@ intel_load_detect_get_pipe(struct drm_connector *connector,
}
/* Find an unused one (if possible) */
for_each_intel_crtc(display->drm, possible_crtc) {
for_each_intel_crtc(display, possible_crtc) {
if (!(encoder->base.possible_crtcs &
drm_crtc_mask(&possible_crtc->base)))
continue;

View File

@ -71,7 +71,7 @@ static void intel_crtc_disable_noatomic_begin(struct intel_crtc *crtc,
to_intel_atomic_state(state)->internal = true;
/* Everything's already locked, -EDEADLK can't happen. */
for_each_intel_crtc_in_pipe_mask(display->drm, temp_crtc,
for_each_intel_crtc_in_pipe_mask(display, temp_crtc,
BIT(pipe) |
intel_crtc_joiner_secondary_pipes(crtc_state)) {
struct intel_crtc_state *temp_crtc_state =
@ -192,7 +192,7 @@ static u8 get_transcoder_pipes(struct intel_display *display,
struct intel_crtc *temp_crtc;
u8 pipes = 0;
for_each_intel_crtc(display->drm, temp_crtc) {
for_each_intel_crtc(display, temp_crtc) {
struct intel_crtc_state *temp_crtc_state =
to_intel_crtc_state(temp_crtc->base.state);
@ -248,7 +248,7 @@ static u8 get_joiner_secondary_pipes(struct intel_display *display, u8 primary_p
struct intel_crtc *primary_crtc;
u8 pipes = 0;
for_each_intel_crtc_in_pipe_mask(display->drm, primary_crtc, primary_pipes_mask) {
for_each_intel_crtc_in_pipe_mask(display, primary_crtc, primary_pipes_mask) {
struct intel_crtc_state *primary_crtc_state =
to_intel_crtc_state(primary_crtc->base.state);
@ -278,16 +278,16 @@ static void intel_crtc_disable_noatomic(struct intel_crtc *crtc,
portsync_master_mask & joiner_secondaries_mask ||
portsync_slaves_mask & joiner_secondaries_mask);
for_each_intel_crtc_in_pipe_mask(display->drm, temp_crtc, joiner_secondaries_mask)
for_each_intel_crtc_in_pipe_mask(display, temp_crtc, joiner_secondaries_mask)
intel_crtc_disable_noatomic_begin(temp_crtc, ctx);
for_each_intel_crtc_in_pipe_mask(display->drm, temp_crtc, portsync_slaves_mask)
for_each_intel_crtc_in_pipe_mask(display, temp_crtc, portsync_slaves_mask)
intel_crtc_disable_noatomic_begin(temp_crtc, ctx);
for_each_intel_crtc_in_pipe_mask(display->drm, temp_crtc, portsync_master_mask)
for_each_intel_crtc_in_pipe_mask(display, temp_crtc, portsync_master_mask)
intel_crtc_disable_noatomic_begin(temp_crtc, ctx);
for_each_intel_crtc_in_pipe_mask(display->drm, temp_crtc,
for_each_intel_crtc_in_pipe_mask(display, temp_crtc,
joiner_secondaries_mask |
portsync_slaves_mask |
portsync_master_mask)
@ -334,6 +334,8 @@ static void intel_crtc_copy_hw_to_uapi_state(struct intel_crtc_state *crtc_state
crtc_state->uapi.adjusted_mode = crtc_state->hw.adjusted_mode;
crtc_state->uapi.scaling_filter = crtc_state->hw.scaling_filter;
crtc_state->uapi.sharpness_strength = crtc_state->hw.sharpness_strength;
crtc_state->uapi.background_color =
intel_color_background_color_hw_to_drm(crtc_state->hw.background_color);
if (DISPLAY_INFO(display)->color.degamma_lut_size) {
/* assume 1:1 mapping */
@ -376,7 +378,7 @@ intel_sanitize_plane_mapping(struct intel_display *display)
if (DISPLAY_VER(display) >= 4)
return;
for_each_intel_crtc(display->drm, crtc) {
for_each_intel_crtc(display, crtc) {
struct intel_plane *plane =
to_intel_plane(crtc->base.primary);
struct intel_crtc *plane_crtc;
@ -532,7 +534,7 @@ static void intel_sanitize_all_crtcs(struct intel_display *display,
for (;;) {
u32 old_mask = crtcs_forced_off;
for_each_intel_crtc(display->drm, crtc) {
for_each_intel_crtc(display, crtc) {
u32 crtc_mask = drm_crtc_mask(&crtc->base);
if (crtcs_forced_off & crtc_mask)
@ -545,7 +547,7 @@ static void intel_sanitize_all_crtcs(struct intel_display *display,
break;
}
for_each_intel_crtc(display->drm, crtc) {
for_each_intel_crtc(display, crtc) {
struct intel_crtc_state *crtc_state =
to_intel_crtc_state(crtc->base.state);
@ -681,7 +683,7 @@ static void readout_plane_state(struct intel_display *display)
str_enabled_disabled(visible), pipe_name(pipe));
}
for_each_intel_crtc(display->drm, crtc) {
for_each_intel_crtc(display, crtc) {
struct intel_crtc_state *crtc_state =
to_intel_crtc_state(crtc->base.state);
@ -699,7 +701,7 @@ static void intel_modeset_readout_hw_state(struct intel_display *display)
struct intel_connector *connector;
struct drm_connector_list_iter conn_iter;
for_each_intel_crtc(display->drm, crtc) {
for_each_intel_crtc(display, crtc) {
struct intel_crtc_state *crtc_state =
to_intel_crtc_state(crtc->base.state);
@ -741,7 +743,7 @@ static void intel_modeset_readout_hw_state(struct intel_display *display)
/* encoder should read be linked to joiner primary */
WARN_ON(intel_crtc_is_joiner_secondary(crtc_state));
for_each_intel_crtc_in_pipe_mask(display->drm, secondary_crtc,
for_each_intel_crtc_in_pipe_mask(display, secondary_crtc,
intel_crtc_joiner_secondary_pipes(crtc_state)) {
struct intel_crtc_state *secondary_crtc_state;
@ -814,7 +816,7 @@ static void intel_modeset_readout_hw_state(struct intel_display *display)
}
drm_connector_list_iter_end(&conn_iter);
for_each_intel_crtc(display->drm, crtc) {
for_each_intel_crtc(display, crtc) {
struct intel_crtc_state *crtc_state =
to_intel_crtc_state(crtc->base.state);
struct intel_plane *plane;
@ -961,7 +963,7 @@ void intel_modeset_setup_hw_state(struct intel_display *display,
* intel_sanitize_plane_mapping() may need to do vblank
* waits, so we need vblank interrupts restored beforehand.
*/
for_each_intel_crtc(display->drm, crtc) {
for_each_intel_crtc(display, crtc) {
struct intel_crtc_state *crtc_state =
to_intel_crtc_state(crtc->base.state);
@ -997,7 +999,7 @@ void intel_modeset_setup_hw_state(struct intel_display *display,
intel_wm_get_hw_state(display);
intel_wm_sanitize(display);
for_each_intel_crtc(display->drm, crtc) {
for_each_intel_crtc(display, crtc) {
struct intel_crtc_state *crtc_state =
to_intel_crtc_state(crtc->base.state);
struct intel_power_domain_mask put_domains;
@ -1009,5 +1011,5 @@ void intel_modeset_setup_hw_state(struct intel_display *display,
intel_display_power_put(display, POWER_DOMAIN_INIT, wakeref);
intel_power_domains_sanitize_state(display);
intel_display_power_sanitize_state(display);
}

View File

@ -1794,6 +1794,7 @@ static u8 intel_joiner_affected_planes(struct intel_atomic_state *state,
static int intel_joiner_add_affected_planes(struct intel_atomic_state *state,
u8 joined_pipes)
{
struct intel_display *display = to_intel_display(state);
u8 prev_affected_planes, affected_planes = 0;
/*
@ -1811,7 +1812,7 @@ static int intel_joiner_add_affected_planes(struct intel_atomic_state *state,
do {
struct intel_crtc *crtc;
for_each_intel_crtc_in_pipe_mask(state->base.dev, crtc, joined_pipes) {
for_each_intel_crtc_in_pipe_mask(display, crtc, joined_pipes) {
int ret;
ret = intel_crtc_add_planes_to_state(state, crtc, affected_planes);
@ -1830,9 +1831,8 @@ static int intel_add_affected_planes(struct intel_atomic_state *state)
{
const struct intel_crtc_state *crtc_state;
struct intel_crtc *crtc;
int i;
for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i) {
for_each_new_intel_crtc_in_state(state, crtc, crtc_state) {
int ret;
ret = intel_joiner_add_affected_planes(state, intel_crtc_joined_pipe_mask(crtc_state));
@ -1866,8 +1866,7 @@ int intel_plane_atomic_check(struct intel_atomic_state *state)
}
}
for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state,
new_crtc_state, i) {
for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state) {
u8 old_active_planes, new_active_planes;
ret = icl_check_nv12_planes(state, crtc);

View File

@ -190,7 +190,7 @@ intel_pmdemand_update_max_ddiclk(struct intel_display *display,
struct intel_crtc *crtc;
int i;
for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i)
for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state)
intel_pmdemand_update_port_clock(display, pmdemand_state,
crtc->pipe,
new_crtc_state->port_clock);
@ -299,7 +299,6 @@ static bool intel_pmdemand_needs_update(struct intel_atomic_state *state)
{
const struct intel_crtc_state *new_crtc_state, *old_crtc_state;
struct intel_crtc *crtc;
int i;
if (intel_bw_pmdemand_needs_update(state))
return true;
@ -310,8 +309,7 @@ static bool intel_pmdemand_needs_update(struct intel_atomic_state *state)
if (intel_cdclk_pmdemand_needs_update(state))
return true;
for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state,
new_crtc_state, i)
for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state)
if (new_crtc_state->port_clock != old_crtc_state->port_clock)
return true;

View File

@ -793,27 +793,30 @@ static bool psr2_su_region_et_valid(struct intel_connector *connector, bool pane
static void _panel_replay_enable_sink(struct intel_dp *intel_dp,
const struct intel_crtc_state *crtc_state)
{
u8 val = DP_PANEL_REPLAY_ENABLE |
DP_PANEL_REPLAY_VSC_SDP_CRC_EN |
DP_PANEL_REPLAY_UNRECOVERABLE_ERROR_EN |
DP_PANEL_REPLAY_RFB_STORAGE_ERROR_EN |
DP_PANEL_REPLAY_ACTIVE_FRAME_CRC_ERROR_EN;
u8 panel_replay_config2 = DP_PANEL_REPLAY_CRC_VERIFICATION;
u8 panel_replay_config[2];
u8 panel_replay_config_3;
panel_replay_config[0] = DP_PANEL_REPLAY_ENABLE |
DP_PANEL_REPLAY_VSC_SDP_CRC_EN |
DP_PANEL_REPLAY_UNRECOVERABLE_ERROR_EN |
DP_PANEL_REPLAY_RFB_STORAGE_ERROR_EN |
DP_PANEL_REPLAY_ACTIVE_FRAME_CRC_ERROR_EN;
panel_replay_config[1] = DP_PANEL_REPLAY_CRC_VERIFICATION;
if (crtc_state->has_sel_update)
val |= DP_PANEL_REPLAY_SU_ENABLE;
panel_replay_config[0] |= DP_PANEL_REPLAY_SU_ENABLE;
if (crtc_state->enable_psr2_su_region_et)
val |= DP_PANEL_REPLAY_ENABLE_SU_REGION_ET;
panel_replay_config[0] |= DP_PANEL_REPLAY_ENABLE_SU_REGION_ET;
if (crtc_state->req_psr2_sdp_prior_scanline)
panel_replay_config2 |=
panel_replay_config[1] |=
DP_PANEL_REPLAY_SU_REGION_SCANLINE_CAPTURE;
drm_dp_dpcd_writeb(&intel_dp->aux, PANEL_REPLAY_CONFIG, val);
drm_dp_dpcd_write(&intel_dp->aux, PANEL_REPLAY_CONFIG,
panel_replay_config, sizeof(panel_replay_config));
drm_dp_dpcd_writeb(&intel_dp->aux, PANEL_REPLAY_CONFIG2,
panel_replay_config2);
panel_replay_config_3 = intel_dp_as_sdp_transmission_time();
drm_dp_dpcd_writeb(&intel_dp->aux, PANEL_REPLAY_CONFIG3, panel_replay_config_3);
}
static void _psr_enable_sink(struct intel_dp *intel_dp,
@ -1508,15 +1511,21 @@ int _intel_psr_min_set_context_latency(const struct intel_crtc_state *crtc_state
* SRD_STATUS is used by PSR1 and Panel Replay DP on LunarLake.
*/
if (DISPLAY_VER(display) >= 30 && (needs_panel_replay ||
needs_sel_update))
if (needs_sel_update)
return 0;
else if (DISPLAY_VER(display) < 30 && (needs_sel_update ||
intel_crtc_has_type(crtc_state,
INTEL_OUTPUT_EDP)))
if (DISPLAY_VER(display) < 30 &&
intel_crtc_has_type(crtc_state, INTEL_OUTPUT_EDP))
return 0;
else
return 1;
if (DISPLAY_VER(display) >= 30 &&
needs_panel_replay)
return 0;
if (intel_vrr_always_use_vrr_tg(display))
return 0;
return 1;
}
static bool _wake_lines_fit_into_vblank(const struct intel_crtc_state *crtc_state,
@ -1902,7 +1911,7 @@ void intel_psr_set_non_psr_pipes(struct intel_dp *intel_dp,
return;
/* We ignore possible secondary PSR/Panel Replay capable eDP */
for_each_intel_crtc(display->drm, crtc)
for_each_intel_crtc(display, crtc)
active_pipes |= crtc->active ? BIT(crtc->pipe) : 0;
active_pipes = intel_calc_active_pipes(state, active_pipes);
@ -2913,6 +2922,11 @@ intel_psr_apply_su_area_workarounds(struct intel_crtc_state *crtc_state)
crtc_state->splitter.enable)
crtc_state->psr2_su_area.y1 = 0;
if (intel_display_wa(display, INTEL_DISPLAY_WA_16029024088) &&
crtc_state->req_psr2_sdp_prior_scanline &&
!crtc_state->enable_psr2_su_region_et)
crtc_state->psr2_su_area.y1 = 0;
/* Wa 14019834836 */
if (DISPLAY_VER(display) == 30)
intel_psr_apply_pr_link_on_su_wa(crtc_state);
@ -4180,27 +4194,22 @@ void intel_psr_notify_vblank_enable_disable(struct intel_display *display,
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
mutex_lock(&intel_dp->psr.lock);
if (intel_dp->psr.panel_replay_enabled) {
mutex_unlock(&intel_dp->psr.lock);
break;
if (CAN_PANEL_REPLAY(intel_dp)) {
if (enable)
intel_dp->psr.vblank_wakeref =
intel_display_power_get(display,
POWER_DOMAIN_DC_OFF);
else
intel_display_power_put(display, POWER_DOMAIN_DC_OFF,
intel_dp->psr.vblank_wakeref);
}
if (intel_dp->psr.enabled && intel_dp->psr.pkg_c_latency_used)
if (intel_dp->psr.enabled && !intel_dp->psr.panel_replay_enabled &&
intel_dp->psr.pkg_c_latency_used)
intel_psr_apply_underrun_on_idle_wa_locked(intel_dp);
mutex_unlock(&intel_dp->psr.lock);
return;
}
/*
* NOTE: intel_display_power_set_target_dc_state is used
* only by PSR * code for DC3CO handling. DC3CO target
* state is currently disabled in * PSR code. If DC3CO
* is taken into use we need take that into account here
* as well.
*/
intel_display_power_set_target_dc_state(display, enable ? DC_STATE_DISABLE :
DC_STATE_EN_UPTO_DC6);
}
static void
@ -4689,3 +4698,14 @@ bool intel_psr_use_trans_push(const struct intel_crtc_state *crtc_state)
return HAS_PSR_TRANS_PUSH_FRAME_CHANGE(display) && crtc_state->has_psr;
}
bool intel_psr_pr_async_video_timing_supported(struct intel_dp *intel_dp)
{
struct intel_connector *connector = intel_dp->attached_connector;
u8 *dpcd = connector->dp.panel_replay_caps.dpcd;
u8 pr_support = dpcd[INTEL_PR_DPCD_INDEX(DP_PANEL_REPLAY_CAP_SUPPORT)];
u8 pr_cap = dpcd[INTEL_PR_DPCD_INDEX(DP_PANEL_REPLAY_CAP_CAPABILITY)];
return (pr_support & DP_PANEL_REPLAY_SUPPORT) &&
!(pr_cap & DP_PANEL_REPLAY_ASYNC_VIDEO_TIMING_NOT_SUPPORTED_IN_PR);
}

View File

@ -86,5 +86,6 @@ void intel_psr_compute_config_late(struct intel_dp *intel_dp,
struct intel_crtc_state *crtc_state);
int intel_psr_min_guardband(struct intel_crtc_state *crtc_state);
bool intel_psr_use_trans_push(const struct intel_crtc_state *crtc_state);
bool intel_psr_pr_async_video_timing_supported(struct intel_dp *intel_dp);
#endif /* __INTEL_PSR_H__ */

View File

@ -1779,7 +1779,7 @@ static int reset_link_commit(struct intel_tc_port *tc,
if (!pipe_mask)
return 0;
for_each_intel_crtc_in_pipe_mask(display->drm, crtc, pipe_mask) {
for_each_intel_crtc_in_pipe_mask(display, crtc, pipe_mask) {
struct intel_crtc_state *crtc_state;
crtc_state = intel_atomic_get_crtc_state(&state->base, crtc);

View File

@ -94,12 +94,10 @@ bool intel_vrr_possible(const struct intel_crtc_state *crtc_state)
void
intel_vrr_check_modeset(struct intel_atomic_state *state)
{
int i;
struct intel_crtc_state *old_crtc_state, *new_crtc_state;
struct intel_crtc *crtc;
for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state,
new_crtc_state, i) {
for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state) {
if (new_crtc_state->uapi.vrr_enabled !=
old_crtc_state->uapi.vrr_enabled)
new_crtc_state->uapi.mode_changed = true;

View File

@ -661,9 +661,9 @@ static int glk_coef_tap(int i)
return i % 7;
}
static u16 glk_nearest_filter_coef(int t)
static u16 glk_nearest_filter_coef(int tap)
{
return t == 3 ? 0x0800 : 0x3000;
return tap == 3 ? 0x0800 : 0x3000;
}
/*
@ -715,13 +715,13 @@ static void glk_program_nearest_filter_coefs(struct intel_display *display,
for (i = 0; i < 17 * 7; i += 2) {
u32 tmp;
int t;
int tap;
t = glk_coef_tap(i);
tmp = glk_nearest_filter_coef(t);
tap = glk_coef_tap(i);
tmp = glk_nearest_filter_coef(tap);
t = glk_coef_tap(i + 1);
tmp |= glk_nearest_filter_coef(t) << 16;
tap = glk_coef_tap(i + 1);
tmp |= glk_nearest_filter_coef(tap) << 16;
intel_de_write_dsb(display, dsb,
GLK_PS_COEF_DATA_SET(pipe, id, set), tmp);
@ -836,6 +836,22 @@ void skl_pfit_enable(const struct intel_crtc_state *crtc_state)
PS_WIN_XSIZE(width) | PS_WIN_YSIZE(height));
}
static int skl_pipe_scaler_get_hw_state(struct intel_crtc_state *crtc_state)
{
struct intel_display *display = to_intel_display(crtc_state);
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
for (int scaler_id = 0; scaler_id < crtc->num_scalers; scaler_id++) {
u32 ctl;
ctl = intel_de_read(display, SKL_PS_CTRL(crtc->pipe, scaler_id));
if ((ctl & (PS_SCALER_EN | PS_BINDING_MASK)) == (PS_SCALER_EN | PS_BINDING_PIPE))
return scaler_id;
}
return -1;
}
void
skl_program_plane_scaler(struct intel_dsb *dsb,
struct intel_plane *plane,
@ -950,42 +966,32 @@ void skl_scaler_get_config(struct intel_crtc_state *crtc_state)
struct intel_display *display = to_intel_display(crtc_state);
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
struct intel_crtc_scaler_state *scaler_state = &crtc_state->scaler_state;
int id = -1;
int i;
int scaler_id;
u32 pos, size;
/* find scaler attached to this pipe */
for (i = 0; i < crtc->num_scalers; i++) {
u32 ctl, pos, size;
scaler_id = skl_pipe_scaler_get_hw_state(crtc_state);
if (scaler_id < 0)
return;
ctl = intel_de_read(display, SKL_PS_CTRL(crtc->pipe, i));
if ((ctl & (PS_SCALER_EN | PS_BINDING_MASK)) != (PS_SCALER_EN | PS_BINDING_PIPE))
continue;
if (scaler_has_casf(display, scaler_id))
intel_casf_sharpness_get_config(crtc_state);
id = i;
crtc_state->pch_pfit.enabled = true;
if (scaler_has_casf(display, i))
intel_casf_sharpness_get_config(crtc_state);
pos = intel_de_read(display, SKL_PS_WIN_POS(crtc->pipe, scaler_id));
size = intel_de_read(display, SKL_PS_WIN_SZ(crtc->pipe, scaler_id));
crtc_state->pch_pfit.enabled = true;
drm_rect_init(&crtc_state->pch_pfit.dst,
REG_FIELD_GET(PS_WIN_XPOS_MASK, pos),
REG_FIELD_GET(PS_WIN_YPOS_MASK, pos),
REG_FIELD_GET(PS_WIN_XSIZE_MASK, size),
REG_FIELD_GET(PS_WIN_YSIZE_MASK, size));
pos = intel_de_read(display, SKL_PS_WIN_POS(crtc->pipe, i));
size = intel_de_read(display, SKL_PS_WIN_SZ(crtc->pipe, i));
scaler_state->scalers[scaler_id].in_use = true;
drm_rect_init(&crtc_state->pch_pfit.dst,
REG_FIELD_GET(PS_WIN_XPOS_MASK, pos),
REG_FIELD_GET(PS_WIN_YPOS_MASK, pos),
REG_FIELD_GET(PS_WIN_XSIZE_MASK, size),
REG_FIELD_GET(PS_WIN_YSIZE_MASK, size));
scaler_state->scalers[i].in_use = true;
break;
}
scaler_state->scaler_id = id;
if (id >= 0)
scaler_state->scaler_users |= (1 << SKL_CRTC_INDEX);
else
scaler_state->scaler_users &= ~(1 << SKL_CRTC_INDEX);
scaler_state->scaler_id = scaler_id;
scaler_state->scaler_users |= (1 << SKL_CRTC_INDEX);
}
void adl_scaler_ecc_mask(const struct intel_crtc_state *crtc_state)

View File

@ -1532,7 +1532,7 @@ static void icl_plane_update_sel_fetch_noarm(struct intel_dsb *dsb,
if (!color_plane)
y = plane_state->view.color_plane[color_plane].y + clip->y1;
else
y = plane_state->view.color_plane[color_plane].y + clip->y1 / 2;
y = plane_state->view.color_plane[color_plane].y + DIV_ROUND_UP(clip->y1, 2);
val = y << 16 | x;

View File

@ -2495,9 +2495,9 @@ skl_compute_ddb(struct intel_atomic_state *state)
struct intel_dbuf_state *new_dbuf_state = NULL;
struct intel_crtc_state *new_crtc_state;
struct intel_crtc *crtc;
int ret, i;
int ret;
for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) {
for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state) {
new_dbuf_state = intel_atomic_get_dbuf_state(state);
if (IS_ERR(new_dbuf_state))
return PTR_ERR(new_dbuf_state);
@ -2529,7 +2529,7 @@ skl_compute_ddb(struct intel_atomic_state *state)
}
}
for_each_intel_crtc(display->drm, crtc) {
for_each_intel_crtc(display, crtc) {
enum pipe pipe = crtc->pipe;
new_dbuf_state->slices[pipe] =
@ -2561,7 +2561,7 @@ skl_compute_ddb(struct intel_atomic_state *state)
str_yes_no(new_dbuf_state->joined_mbus));
}
for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) {
for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state) {
enum pipe pipe = crtc->pipe;
new_dbuf_state->weight[pipe] = intel_crtc_ddb_weight(new_crtc_state);
@ -2574,13 +2574,13 @@ skl_compute_ddb(struct intel_atomic_state *state)
return ret;
}
for_each_intel_crtc(display->drm, crtc) {
for_each_intel_crtc(display, crtc) {
ret = skl_crtc_allocate_ddb(state, crtc);
if (ret)
return ret;
}
for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) {
for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state) {
ret = skl_crtc_allocate_plane_ddb(state, crtc);
if (ret)
return ret;
@ -2687,13 +2687,11 @@ skl_print_wm_changes(struct intel_atomic_state *state)
const struct intel_crtc_state *new_crtc_state;
struct intel_plane *plane;
struct intel_crtc *crtc;
int i;
if (!drm_debug_enabled(DRM_UT_KMS))
return;
for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state,
new_crtc_state, i) {
for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state) {
const struct skl_pipe_wm *old_pipe_wm, *new_pipe_wm;
old_pipe_wm = &old_crtc_state->wm.skl.optimal;
@ -2833,19 +2831,19 @@ static int pkgc_max_linetime(struct intel_atomic_state *state)
struct intel_display *display = to_intel_display(state);
const struct intel_crtc_state *crtc_state;
struct intel_crtc *crtc;
int i, max_linetime;
int max_linetime;
/*
* Apparenty the hardware uses WM_LINETIME internally for
* this stuff, compute everything based on that.
*/
for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i) {
for_each_new_intel_crtc_in_state(state, crtc, crtc_state) {
display->pkgc.disable[crtc->pipe] = crtc_state->vrr.enable;
display->pkgc.linetime[crtc->pipe] = DIV_ROUND_UP(crtc_state->linetime, 8);
}
max_linetime = 0;
for_each_intel_crtc(display->drm, crtc) {
for_each_intel_crtc(display, crtc) {
if (display->pkgc.disable[crtc->pipe])
return 0;
@ -2909,9 +2907,9 @@ skl_compute_wm(struct intel_atomic_state *state)
struct intel_display *display = to_intel_display(state);
struct intel_crtc *crtc;
struct intel_crtc_state __maybe_unused *new_crtc_state;
int ret, i;
int ret;
for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) {
for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state) {
ret = skl_build_pipe_wm(state, crtc);
if (ret)
return ret;
@ -2926,7 +2924,7 @@ skl_compute_wm(struct intel_atomic_state *state)
* based on how much ddb is available. Now we can actually
* check if the final watermarks changed.
*/
for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) {
for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state) {
struct skl_pipe_wm *pipe_wm = &new_crtc_state->wm.skl.optimal;
/*
@ -3033,7 +3031,7 @@ static void skl_wm_get_hw_state(struct intel_display *display)
dbuf_state->mdclk_cdclk_ratio = intel_mdclk_cdclk_ratio(display, &display->cdclk.hw);
dbuf_state->active_pipes = 0;
for_each_intel_crtc(display->drm, crtc) {
for_each_intel_crtc(display, crtc) {
struct intel_crtc_state *crtc_state =
to_intel_crtc_state(crtc->base.state);
enum pipe pipe = crtc->pipe;
@ -3446,7 +3444,7 @@ static void pipe_mbus_dbox_ctl_update(struct intel_display *display,
{
struct intel_crtc *crtc;
for_each_intel_crtc_in_pipe_mask(display->drm, crtc, dbuf_state->active_pipes)
for_each_intel_crtc_in_pipe_mask(display, crtc, dbuf_state->active_pipes)
intel_de_write(display, PIPE_MBUS_DBOX_CTL(crtc->pipe),
pipe_mbus_dbox_ctl(crtc, dbuf_state));
}
@ -3758,14 +3756,14 @@ static bool skl_dbuf_is_misconfigured(struct intel_display *display)
struct skl_ddb_entry entries[I915_MAX_PIPES] = {};
struct intel_crtc *crtc;
for_each_intel_crtc(display->drm, crtc) {
for_each_intel_crtc(display, crtc) {
const struct intel_crtc_state *crtc_state =
to_intel_crtc_state(crtc->base.state);
entries[crtc->pipe] = crtc_state->wm.skl.ddb;
}
for_each_intel_crtc(display->drm, crtc) {
for_each_intel_crtc(display, crtc) {
const struct intel_crtc_state *crtc_state =
to_intel_crtc_state(crtc->base.state);
u8 slices;
@ -3803,7 +3801,7 @@ static void skl_dbuf_sanitize(struct intel_display *display)
drm_dbg_kms(display->drm, "BIOS has misprogrammed the DBUF, disabling all planes\n");
for_each_intel_crtc(display->drm, crtc) {
for_each_intel_crtc(display, crtc) {
struct intel_plane *plane = to_intel_plane(crtc->base.primary);
const struct intel_plane_state *plane_state =
to_intel_plane_state(plane->base.state);

View File

@ -297,7 +297,7 @@ static void i915_driver_late_release(struct drm_i915_private *dev_priv)
struct intel_display *display = dev_priv->display;
intel_irq_fini(dev_priv);
intel_power_domains_cleanup(display);
intel_display_power_cleanup(display);
i915_gem_cleanup_early(dev_priv);
intel_gt_driver_late_release_all(dev_priv);
intel_region_ttm_device_fini(dev_priv);
@ -660,7 +660,7 @@ static int i915_driver_register(struct drm_i915_private *dev_priv)
intel_display_driver_register(display);
intel_power_domains_enable(display);
intel_display_power_enable(display);
intel_runtime_pm_enable(&dev_priv->runtime_pm);
if (i915_switcheroo_register(dev_priv))
@ -682,7 +682,7 @@ static void i915_driver_unregister(struct drm_i915_private *dev_priv)
i915_switcheroo_unregister(dev_priv);
intel_runtime_pm_disable(&dev_priv->runtime_pm);
intel_power_domains_disable(display);
intel_display_power_disable(display);
intel_display_driver_unregister(display);
@ -971,6 +971,7 @@ void i915_driver_remove(struct drm_i915_private *i915)
intel_display_driver_remove(display);
intel_irq_uninstall(i915);
intel_hpd_cancel_work(display);
intel_display_driver_remove_noirq(display);
@ -1042,7 +1043,7 @@ void i915_driver_shutdown(struct drm_i915_private *i915)
disable_rpm_wakeref_asserts(&i915->runtime_pm);
intel_runtime_pm_disable(&i915->runtime_pm);
intel_power_domains_disable(display);
intel_display_power_disable(display);
drm_client_dev_suspend(&i915->drm);
if (intel_display_device_present(display)) {
@ -1078,7 +1079,7 @@ void i915_driver_shutdown(struct drm_i915_private *i915)
* - unify the driver remove and system/runtime suspend sequences with
* the above unified shutdown/poweroff sequence.
*/
intel_power_domains_driver_remove(display);
intel_display_power_driver_remove(display);
enable_rpm_wakeref_asserts(&i915->runtime_pm);
intel_runtime_pm_driver_last_release(&i915->runtime_pm);
@ -1125,7 +1126,7 @@ static int i915_drm_suspend(struct drm_device *dev)
/* We do a lot of poking in a lot of registers, make sure they work
* properly. */
intel_power_domains_disable(display);
intel_display_power_disable(display);
drm_client_dev_suspend(dev);
if (intel_display_device_present(display)) {
drm_kms_helper_poll_disable(dev);
@ -1325,7 +1326,7 @@ static int i915_drm_resume(struct drm_device *dev)
drm_client_dev_resume(dev);
intel_power_domains_enable(display);
intel_display_power_enable(display);
intel_gvt_resume(dev_priv);
@ -1557,7 +1558,7 @@ static int i915_pm_restore(struct device *kdev)
return i915_pm_resume(kdev);
}
static int intel_runtime_suspend(struct device *kdev)
static int i915_pm_runtime_suspend(struct device *kdev)
{
struct drm_i915_private *dev_priv = kdev_to_i915(kdev);
struct intel_display *display = dev_priv->display;
@ -1590,7 +1591,7 @@ static int intel_runtime_suspend(struct device *kdev)
for_each_gt(gt, dev_priv, i)
intel_uncore_suspend(gt->uncore);
intel_display_power_suspend(display);
intel_display_power_runtime_suspend(display);
ret = vlv_suspend_complete(dev_priv);
if (ret) {
@ -1631,7 +1632,7 @@ static int intel_runtime_suspend(struct device *kdev)
if (IS_BROADWELL(dev_priv)) {
/*
* On Broadwell, if we use PCI_D1 the PCH DDI ports will stop
* being detected, and the call we do at intel_runtime_resume()
* being detected, and the call we do at i915_pm_runtime_resume()
* won't be able to restore them. Since PCI_D3hot matches the
* actual specification and appears to be working, use it.
*/
@ -1656,7 +1657,7 @@ static int intel_runtime_suspend(struct device *kdev)
return 0;
}
static int intel_runtime_resume(struct device *kdev)
static int i915_pm_runtime_resume(struct device *kdev)
{
struct drm_i915_private *dev_priv = kdev_to_i915(kdev);
struct intel_display *display = dev_priv->display;
@ -1684,7 +1685,7 @@ static int intel_runtime_resume(struct device *kdev)
drm_dbg(&dev_priv->drm,
"Unclaimed access during suspend, bios?\n");
intel_display_power_resume(display);
intel_display_power_runtime_resume(display);
ret = vlv_resume_prepare(dev_priv, true);
@ -1764,8 +1765,8 @@ const struct dev_pm_ops i915_pm_ops = {
.restore = i915_pm_restore,
/* S0ix (via runtime suspend) event handlers */
.runtime_suspend = intel_runtime_suspend,
.runtime_resume = intel_runtime_resume,
.runtime_suspend = i915_pm_runtime_suspend,
.runtime_resume = i915_pm_runtime_resume,
};
static const struct file_operations i915_driver_fops = {
@ -1869,9 +1870,6 @@ static const struct drm_ioctl_desc i915_ioctls[] = {
#define DRIVER_PATCHLEVEL 0
static const struct drm_driver i915_drm_driver = {
/* Don't use MTRRs here; the Xserver or userspace app should
* deal with them for Intel hardware.
*/
.driver_features =
DRIVER_GEM |
DRIVER_RENDER | DRIVER_MODESET | DRIVER_ATOMIC | DRIVER_SYNCOBJ |

View File

@ -37,9 +37,6 @@
#include <drm/intel/intel_gmd_interrupt_regs.h>
#include "display/intel_display_irq.h"
#include "display/intel_hotplug.h"
#include "display/intel_hotplug_irq.h"
#include "display/intel_lpe_audio.h"
#include "gt/intel_breadcrumbs.h"
#include "gt/intel_gt.h"
@ -236,17 +233,15 @@ static irqreturn_t valleyview_irq_handler(int irq, void *arg)
disable_rpm_wakeref_asserts(&dev_priv->runtime_pm);
do {
u32 iir, gt_iir, pm_iir;
u32 eir = 0, dpinvgtt = 0;
u32 pipe_stats[I915_MAX_PIPES] = {};
u32 hotplug_status = 0;
struct intel_display_irq_state state = {};
u32 gt_iir, pm_iir;
u32 ier = 0;
gt_iir = intel_uncore_read(&dev_priv->uncore, GTIIR);
pm_iir = intel_uncore_read(&dev_priv->uncore, GEN6_PMIIR);
iir = intel_uncore_read(&dev_priv->uncore, VLV_IIR);
state.iir = intel_uncore_read(&dev_priv->uncore, VLV_IIR);
if (gt_iir == 0 && pm_iir == 0 && iir == 0)
if (gt_iir == 0 && pm_iir == 0 && state.iir == 0)
break;
ret = IRQ_HANDLED;
@ -272,26 +267,14 @@ static irqreturn_t valleyview_irq_handler(int irq, void *arg)
if (pm_iir)
intel_uncore_write(&dev_priv->uncore, GEN6_PMIIR, pm_iir);
if (iir & I915_DISPLAY_PORT_INTERRUPT)
hotplug_status = i9xx_hpd_irq_ack(display);
if (iir & I915_MASTER_ERROR_INTERRUPT)
vlv_display_error_irq_ack(display, &eir, &dpinvgtt);
/* Call regardless, as some status bits might not be
* signalled in IIR */
i9xx_pipestat_irq_ack(display, iir, pipe_stats);
if (iir & (I915_LPE_PIPE_A_INTERRUPT |
I915_LPE_PIPE_B_INTERRUPT))
intel_lpe_audio_irq_handler(display);
intel_display_irq_ack(display, &state);
/*
* VLV_IIR is single buffered, and reflects the level
* from PIPESTAT/PORT_HOTPLUG_STAT, hence clear it last.
*/
if (iir)
intel_uncore_write(&dev_priv->uncore, VLV_IIR, iir);
if (state.iir)
intel_uncore_write(&dev_priv->uncore, VLV_IIR, state.iir);
intel_uncore_write(&dev_priv->uncore, VLV_IER, ier);
intel_uncore_write(&dev_priv->uncore, VLV_MASTER_IER, MASTER_INTERRUPT_ENABLE);
@ -301,13 +284,7 @@ static irqreturn_t valleyview_irq_handler(int irq, void *arg)
if (pm_iir)
gen6_rps_irq_handler(&to_gt(dev_priv)->rps, pm_iir);
if (hotplug_status)
i9xx_hpd_irq_handler(display, hotplug_status);
if (iir & I915_MASTER_ERROR_INTERRUPT)
vlv_display_error_irq_handler(display, eir, dpinvgtt);
valleyview_pipestat_irq_handler(display, pipe_stats);
intel_display_irq_handler(display, &state);
} while (0);
pmu_irq_stats(dev_priv, ret);
@ -330,16 +307,14 @@ static irqreturn_t cherryview_irq_handler(int irq, void *arg)
disable_rpm_wakeref_asserts(&dev_priv->runtime_pm);
do {
u32 master_ctl, iir;
u32 eir = 0, dpinvgtt = 0;
u32 pipe_stats[I915_MAX_PIPES] = {};
u32 hotplug_status = 0;
struct intel_display_irq_state state = {};
u32 master_ctl;
u32 ier = 0;
master_ctl = intel_uncore_read(&dev_priv->uncore, GEN8_MASTER_IRQ) & ~GEN8_MASTER_IRQ_CONTROL;
iir = intel_uncore_read(&dev_priv->uncore, VLV_IIR);
state.iir = intel_uncore_read(&dev_priv->uncore, VLV_IIR);
if (master_ctl == 0 && iir == 0)
if (master_ctl == 0 && state.iir == 0)
break;
ret = IRQ_HANDLED;
@ -362,38 +337,19 @@ static irqreturn_t cherryview_irq_handler(int irq, void *arg)
gen8_gt_irq_handler(to_gt(dev_priv), master_ctl);
if (iir & I915_DISPLAY_PORT_INTERRUPT)
hotplug_status = i9xx_hpd_irq_ack(display);
if (iir & I915_MASTER_ERROR_INTERRUPT)
vlv_display_error_irq_ack(display, &eir, &dpinvgtt);
/* Call regardless, as some status bits might not be
* signalled in IIR */
i9xx_pipestat_irq_ack(display, iir, pipe_stats);
if (iir & (I915_LPE_PIPE_A_INTERRUPT |
I915_LPE_PIPE_B_INTERRUPT |
I915_LPE_PIPE_C_INTERRUPT))
intel_lpe_audio_irq_handler(display);
intel_display_irq_ack(display, &state);
/*
* VLV_IIR is single buffered, and reflects the level
* from PIPESTAT/PORT_HOTPLUG_STAT, hence clear it last.
*/
if (iir)
intel_uncore_write(&dev_priv->uncore, VLV_IIR, iir);
if (state.iir)
intel_uncore_write(&dev_priv->uncore, VLV_IIR, state.iir);
intel_uncore_write(&dev_priv->uncore, VLV_IER, ier);
intel_uncore_write(&dev_priv->uncore, GEN8_MASTER_IRQ, GEN8_MASTER_IRQ_CONTROL);
if (hotplug_status)
i9xx_hpd_irq_handler(display, hotplug_status);
if (iir & I915_MASTER_ERROR_INTERRUPT)
vlv_display_error_irq_handler(display, eir, dpinvgtt);
valleyview_pipestat_irq_handler(display, pipe_stats);
intel_display_irq_handler(display, &state);
} while (0);
pmu_irq_stats(dev_priv, ret);
@ -440,7 +396,7 @@ static irqreturn_t ilk_irq_handler(int irq, void *arg)
ret = IRQ_HANDLED;
}
if (ilk_display_irq_handler(display))
if (intel_display_irq_handler(display, NULL))
ret = IRQ_HANDLED;
if (GRAPHICS_VER(i915) >= 6) {
@ -502,8 +458,11 @@ static irqreturn_t gen8_irq_handler(int irq, void *arg)
/* IRQs are synced during runtime_suspend, we don't require a wakeref */
if (master_ctl & ~GEN8_GT_IRQS) {
const struct intel_display_irq_state state = {
.master_ctl = master_ctl,
};
disable_rpm_wakeref_asserts(&dev_priv->runtime_pm);
gen8_de_irq_handler(display, master_ctl);
intel_display_irq_handler(display, &state);
enable_rpm_wakeref_asserts(&dev_priv->runtime_pm);
}
@ -555,7 +514,7 @@ static irqreturn_t gen11_irq_handler(int irq, void *arg)
/* IRQs are synced during runtime_suspend, we don't require a wakeref */
if (master_ctl & GEN11_DISPLAY_IRQ)
gen11_display_irq_handler(display);
intel_display_irq_handler(display, NULL);
gu_misc_iir = gen11_gu_misc_irq_ack(display, master_ctl);
@ -622,7 +581,7 @@ static irqreturn_t dg1_irq_handler(int irq, void *arg)
gen11_gt_irq_handler(gt, master_ctl);
if (master_ctl & GEN11_DISPLAY_IRQ)
gen11_display_irq_handler(display);
intel_display_irq_handler(display, NULL);
gu_misc_iir = gen11_gu_misc_irq_ack(display, master_ctl);
@ -640,7 +599,7 @@ static void ilk_irq_reset(struct drm_i915_private *dev_priv)
struct intel_display *display = dev_priv->display;
/* The master interrupt enable is in DEIER, reset display irq first */
ilk_display_irq_reset(display);
intel_display_irq_reset(display);
gen5_gt_irq_reset(to_gt(dev_priv));
}
@ -653,7 +612,7 @@ static void valleyview_irq_reset(struct drm_i915_private *dev_priv)
gen5_gt_irq_reset(to_gt(dev_priv));
vlv_display_irq_reset(display);
intel_display_irq_reset(display);
}
static void gen8_irq_reset(struct drm_i915_private *dev_priv)
@ -664,7 +623,7 @@ static void gen8_irq_reset(struct drm_i915_private *dev_priv)
gen8_master_intr_disable(intel_uncore_regs(uncore));
gen8_gt_irq_reset(to_gt(dev_priv));
gen8_display_irq_reset(display);
intel_display_irq_reset(display);
gen2_irq_reset(uncore, GEN8_PCU_IRQ_REGS);
}
@ -677,7 +636,7 @@ static void gen11_irq_reset(struct drm_i915_private *dev_priv)
gen11_master_intr_disable(intel_uncore_regs(&dev_priv->uncore));
gen11_gt_irq_reset(gt);
gen11_display_irq_reset(display);
intel_display_irq_reset(display);
gen2_irq_reset(uncore, GEN11_GU_MISC_IRQ_REGS);
gen2_irq_reset(uncore, GEN8_PCU_IRQ_REGS);
@ -695,7 +654,7 @@ static void dg1_irq_reset(struct drm_i915_private *dev_priv)
for_each_gt(gt, dev_priv, i)
gen11_gt_irq_reset(gt);
gen11_display_irq_reset(display);
intel_display_irq_reset(display);
gen2_irq_reset(uncore, GEN11_GU_MISC_IRQ_REGS);
gen2_irq_reset(uncore, GEN8_PCU_IRQ_REGS);
@ -715,7 +674,7 @@ static void cherryview_irq_reset(struct drm_i915_private *dev_priv)
gen2_irq_reset(uncore, GEN8_PCU_IRQ_REGS);
vlv_display_irq_reset(display);
intel_display_irq_reset(display);
}
static void ilk_irq_postinstall(struct drm_i915_private *dev_priv)
@ -724,7 +683,7 @@ static void ilk_irq_postinstall(struct drm_i915_private *dev_priv)
gen5_gt_irq_postinstall(to_gt(dev_priv));
ilk_de_irq_postinstall(display);
intel_display_irq_postinstall(display);
}
static void valleyview_irq_postinstall(struct drm_i915_private *dev_priv)
@ -733,7 +692,7 @@ static void valleyview_irq_postinstall(struct drm_i915_private *dev_priv)
gen5_gt_irq_postinstall(to_gt(dev_priv));
vlv_display_irq_postinstall(display);
intel_display_irq_postinstall(display);
intel_uncore_write(&dev_priv->uncore, VLV_MASTER_IER, MASTER_INTERRUPT_ENABLE);
intel_uncore_posting_read(&dev_priv->uncore, VLV_MASTER_IER);
@ -744,7 +703,7 @@ static void gen8_irq_postinstall(struct drm_i915_private *dev_priv)
struct intel_display *display = dev_priv->display;
gen8_gt_irq_postinstall(to_gt(dev_priv));
gen8_de_irq_postinstall(display);
intel_display_irq_postinstall(display);
gen8_master_intr_enable(intel_uncore_regs(&dev_priv->uncore));
}
@ -757,7 +716,7 @@ static void gen11_irq_postinstall(struct drm_i915_private *dev_priv)
u32 gu_misc_masked = GEN11_GU_MISC_GSE;
gen11_gt_irq_postinstall(gt);
gen11_de_irq_postinstall(display);
intel_display_irq_postinstall(display);
gen2_irq_init(uncore, GEN11_GU_MISC_IRQ_REGS, ~gu_misc_masked, gu_misc_masked);
@ -778,7 +737,7 @@ static void dg1_irq_postinstall(struct drm_i915_private *dev_priv)
gen2_irq_init(uncore, GEN11_GU_MISC_IRQ_REGS, ~gu_misc_masked, gu_misc_masked);
dg1_de_irq_postinstall(display);
intel_display_irq_postinstall(display);
dg1_master_intr_enable(intel_uncore_regs(uncore));
intel_uncore_posting_read(uncore, DG1_MSTR_TILE_INTR);
@ -790,7 +749,7 @@ static void cherryview_irq_postinstall(struct drm_i915_private *dev_priv)
gen8_gt_irq_postinstall(to_gt(dev_priv));
vlv_display_irq_postinstall(display);
intel_display_irq_postinstall(display);
intel_uncore_write(&dev_priv->uncore, GEN8_MASTER_IRQ, GEN8_MASTER_IRQ_CONTROL);
intel_uncore_posting_read(&dev_priv->uncore, GEN8_MASTER_IRQ);
@ -864,7 +823,7 @@ static void i915_irq_reset(struct drm_i915_private *dev_priv)
struct intel_display *display = dev_priv->display;
struct intel_uncore *uncore = &dev_priv->uncore;
i9xx_display_irq_reset(display);
intel_display_irq_reset(display);
gen2_error_reset(uncore, GEN2_ERROR_REGS);
gen2_irq_reset(uncore, GEN2_IRQ_REGS);
@ -888,7 +847,7 @@ static void i915_irq_postinstall(struct drm_i915_private *dev_priv)
gen2_irq_init(uncore, GEN2_IRQ_REGS, dev_priv->gen2_imr_mask, enable_mask);
i915_display_irq_postinstall(display);
intel_display_irq_postinstall(display);
}
static irqreturn_t i915_irq_handler(int irq, void *arg)
@ -904,39 +863,29 @@ static irqreturn_t i915_irq_handler(int irq, void *arg)
disable_rpm_wakeref_asserts(&dev_priv->runtime_pm);
do {
u32 pipe_stats[I915_MAX_PIPES] = {};
struct intel_display_irq_state state = {};
u32 eir = 0, eir_stuck = 0;
u32 hotplug_status = 0;
u32 iir;
iir = intel_uncore_read(&dev_priv->uncore, GEN2_IIR);
if (iir == 0)
state.iir = intel_uncore_read(&dev_priv->uncore, GEN2_IIR);
if (state.iir == 0)
break;
ret = IRQ_HANDLED;
if (iir & I915_DISPLAY_PORT_INTERRUPT)
hotplug_status = i9xx_hpd_irq_ack(display);
intel_display_irq_ack(display, &state);
/* Call regardless, as some status bits might not be
* signalled in IIR */
i9xx_pipestat_irq_ack(display, iir, pipe_stats);
if (iir & I915_MASTER_ERROR_INTERRUPT)
if (state.iir & I915_MASTER_ERROR_INTERRUPT)
i9xx_error_irq_ack(dev_priv, &eir, &eir_stuck);
intel_uncore_write(&dev_priv->uncore, GEN2_IIR, iir);
intel_uncore_write(&dev_priv->uncore, GEN2_IIR, state.iir);
if (iir & I915_USER_INTERRUPT)
intel_engine_cs_irq(to_gt(dev_priv)->engine[RCS0], iir);
if (state.iir & I915_USER_INTERRUPT)
intel_engine_cs_irq(to_gt(dev_priv)->engine[RCS0], state.iir);
if (iir & I915_MASTER_ERROR_INTERRUPT)
if (state.iir & I915_MASTER_ERROR_INTERRUPT)
i9xx_error_irq_handler(dev_priv, eir, eir_stuck);
if (hotplug_status)
i9xx_hpd_irq_handler(display, hotplug_status);
i915_pipestat_irq_handler(display, iir, pipe_stats);
intel_display_irq_handler(display, &state);
} while (0);
pmu_irq_stats(dev_priv, ret);
@ -951,7 +900,7 @@ static void i965_irq_reset(struct drm_i915_private *dev_priv)
struct intel_display *display = dev_priv->display;
struct intel_uncore *uncore = &dev_priv->uncore;
i9xx_display_irq_reset(display);
intel_display_irq_reset(display);
gen2_error_reset(uncore, GEN2_ERROR_REGS);
gen2_irq_reset(uncore, GEN2_IRQ_REGS);
@ -997,7 +946,7 @@ static void i965_irq_postinstall(struct drm_i915_private *dev_priv)
gen2_irq_init(uncore, GEN2_IRQ_REGS, dev_priv->gen2_imr_mask, enable_mask);
i965_display_irq_postinstall(display);
intel_display_irq_postinstall(display);
}
static irqreturn_t i965_irq_handler(int irq, void *arg)
@ -1013,44 +962,34 @@ static irqreturn_t i965_irq_handler(int irq, void *arg)
disable_rpm_wakeref_asserts(&dev_priv->runtime_pm);
do {
u32 pipe_stats[I915_MAX_PIPES] = {};
struct intel_display_irq_state state = {};
u32 eir = 0, eir_stuck = 0;
u32 hotplug_status = 0;
u32 iir;
iir = intel_uncore_read(&dev_priv->uncore, GEN2_IIR);
if (iir == 0)
state.iir = intel_uncore_read(&dev_priv->uncore, GEN2_IIR);
if (state.iir == 0)
break;
ret = IRQ_HANDLED;
if (iir & I915_DISPLAY_PORT_INTERRUPT)
hotplug_status = i9xx_hpd_irq_ack(display);
intel_display_irq_ack(display, &state);
/* Call regardless, as some status bits might not be
* signalled in IIR */
i9xx_pipestat_irq_ack(display, iir, pipe_stats);
if (iir & I915_MASTER_ERROR_INTERRUPT)
if (state.iir & I915_MASTER_ERROR_INTERRUPT)
i9xx_error_irq_ack(dev_priv, &eir, &eir_stuck);
intel_uncore_write(&dev_priv->uncore, GEN2_IIR, iir);
intel_uncore_write(&dev_priv->uncore, GEN2_IIR, state.iir);
if (iir & I915_USER_INTERRUPT)
if (state.iir & I915_USER_INTERRUPT)
intel_engine_cs_irq(to_gt(dev_priv)->engine[RCS0],
iir);
state.iir);
if (iir & I915_BSD_USER_INTERRUPT)
if (state.iir & I915_BSD_USER_INTERRUPT)
intel_engine_cs_irq(to_gt(dev_priv)->engine[VCS0],
iir >> 25);
state.iir >> 25);
if (iir & I915_MASTER_ERROR_INTERRUPT)
if (state.iir & I915_MASTER_ERROR_INTERRUPT)
i9xx_error_irq_handler(dev_priv, eir, eir_stuck);
if (hotplug_status)
i9xx_hpd_irq_handler(display, hotplug_status);
i965_pipestat_irq_handler(display, iir, pipe_stats);
intel_display_irq_handler(display, &state);
} while (0);
pmu_irq_stats(dev_priv, IRQ_HANDLED);
@ -1200,7 +1139,6 @@ int intel_irq_install(struct drm_i915_private *dev_priv)
*/
void intel_irq_uninstall(struct drm_i915_private *dev_priv)
{
struct intel_display *display = dev_priv->display;
int irq = to_pci_dev(dev_priv->drm.dev)->irq;
if (drm_WARN_ON(&dev_priv->drm, !dev_priv->irqs_enabled))
@ -1210,7 +1148,6 @@ void intel_irq_uninstall(struct drm_i915_private *dev_priv)
free_irq(irq, dev_priv);
intel_hpd_cancel_work(display);
dev_priv->irqs_enabled = false;
}

View File

@ -442,7 +442,7 @@ void intel_runtime_pm_put(struct intel_runtime_pm *rpm, intel_wakeref_t wref)
*
* Note that this function does currently not enable runtime pm for the
* subordinate display power domains. That is done by
* intel_power_domains_enable().
* intel_display_power_enable().
*/
void intel_runtime_pm_enable(struct intel_runtime_pm *rpm)
{

View File

@ -88,7 +88,7 @@ static void xe_display_fini_early(void *arg)
intel_display_driver_remove_nogem(display);
intel_display_driver_remove_noirq(display);
intel_opregion_cleanup(display);
intel_power_domains_cleanup(display);
intel_display_power_cleanup(display);
}
int xe_display_init_early(struct xe_device *xe)
@ -104,6 +104,15 @@ int xe_display_init_early(struct xe_device *xe)
intel_display_driver_early_probe(display);
intel_display_device_info_runtime_init(display);
/* Display may have been disabled at runtime init */
if (!intel_display_device_present(display)) {
xe->info.probe_display = false;
unset_display_features(xe);
return 0;
}
/* Early display init.. */
intel_opregion_setup(display);
@ -117,8 +126,6 @@ int xe_display_init_early(struct xe_device *xe)
intel_bw_init_hw(display);
intel_display_device_info_runtime_init(display);
err = intel_display_driver_probe_noirq(display);
if (err)
goto err_opregion;
@ -130,7 +137,7 @@ int xe_display_init_early(struct xe_device *xe)
return devm_add_action_or_reset(xe->drm.dev, xe_display_fini_early, xe);
err_noirq:
intel_display_driver_remove_noirq(display);
intel_power_domains_cleanup(display);
intel_display_power_cleanup(display);
err_opregion:
intel_opregion_cleanup(display);
return err;
@ -170,7 +177,7 @@ void xe_display_register(struct xe_device *xe)
return;
intel_display_driver_register(display);
intel_power_domains_enable(display);
intel_display_power_enable(display);
}
void xe_display_unregister(struct xe_device *xe)
@ -180,7 +187,7 @@ void xe_display_unregister(struct xe_device *xe)
if (!xe->info.probe_display)
return;
intel_power_domains_disable(display);
intel_display_power_disable(display);
intel_display_driver_unregister(display);
}
@ -194,7 +201,7 @@ void xe_display_irq_handler(struct xe_device *xe, u32 master_ctl)
return;
if (master_ctl & DISPLAY_IRQ)
gen11_display_irq_handler(display);
intel_display_irq_handler(display, NULL);
}
void xe_display_irq_enable(struct xe_device *xe, u32 gu_misc_iir)
@ -215,7 +222,7 @@ void xe_display_irq_reset(struct xe_device *xe)
if (!xe->info.probe_display)
return;
gen11_display_irq_reset(display);
intel_display_irq_reset(display);
}
void xe_display_irq_postinstall(struct xe_device *xe)
@ -225,7 +232,7 @@ void xe_display_irq_postinstall(struct xe_device *xe)
if (!xe->info.probe_display)
return;
gen11_de_irq_postinstall(display);
intel_display_irq_postinstall(display);
}
static bool suspend_to_idle(void)
@ -237,27 +244,6 @@ static bool suspend_to_idle(void)
return false;
}
static void xe_display_flush_cleanup_work(struct xe_device *xe)
{
struct intel_crtc *crtc;
for_each_intel_crtc(&xe->drm, crtc) {
struct drm_crtc_commit *commit;
spin_lock(&crtc->base.commit_lock);
commit = list_first_entry_or_null(&crtc->base.commit_list,
struct drm_crtc_commit, commit_entry);
if (commit)
drm_crtc_commit_get(commit);
spin_unlock(&crtc->base.commit_lock);
if (commit) {
wait_for_completion(&commit->cleanup_done);
drm_crtc_commit_put(commit);
}
}
}
static void xe_display_enable_d3cold(struct xe_device *xe)
{
struct intel_display *display = xe->display;
@ -269,9 +255,9 @@ static void xe_display_enable_d3cold(struct xe_device *xe)
* We do a lot of poking in a lot of registers, make sure they work
* properly.
*/
intel_power_domains_disable(display);
intel_display_power_disable(display);
xe_display_flush_cleanup_work(xe);
intel_display_flush_cleanup_work(display);
intel_opregion_suspend(display, PCI_D3cold);
@ -302,7 +288,7 @@ static void xe_display_disable_d3cold(struct xe_device *xe)
intel_opregion_resume(display);
intel_power_domains_enable(display);
intel_display_power_enable(display);
}
void xe_display_pm_suspend(struct xe_device *xe)
@ -317,7 +303,7 @@ void xe_display_pm_suspend(struct xe_device *xe)
* We do a lot of poking in a lot of registers, make sure they work
* properly.
*/
intel_power_domains_disable(display);
intel_display_power_disable(display);
drm_client_dev_suspend(&xe->drm);
if (intel_display_device_present(display)) {
@ -326,7 +312,7 @@ void xe_display_pm_suspend(struct xe_device *xe)
intel_display_driver_suspend(display);
}
xe_display_flush_cleanup_work(xe);
intel_display_flush_cleanup_work(display);
intel_encoder_block_all_hpds(display);
@ -349,7 +335,7 @@ void xe_display_pm_shutdown(struct xe_device *xe)
if (!xe->info.probe_display)
return;
intel_power_domains_disable(display);
intel_display_power_disable(display);
drm_client_dev_suspend(&xe->drm);
if (intel_display_device_present(display)) {
@ -358,7 +344,7 @@ void xe_display_pm_shutdown(struct xe_device *xe)
intel_display_driver_suspend(display);
}
xe_display_flush_cleanup_work(xe);
intel_display_flush_cleanup_work(display);
intel_dp_mst_suspend(display);
intel_encoder_block_all_hpds(display);
intel_hpd_cancel_work(display);
@ -430,7 +416,7 @@ void xe_display_pm_shutdown_late(struct xe_device *xe)
* for now leaving all display power wells in the INIT power domain
* enabled.
*/
intel_power_domains_driver_remove(display);
intel_display_power_driver_remove(display);
}
void xe_display_pm_resume_early(struct xe_device *xe)
@ -477,7 +463,7 @@ void xe_display_pm_resume(struct xe_device *xe)
drm_client_dev_resume(&xe->drm);
intel_power_domains_enable(display);
intel_display_power_enable(display);
}
void xe_display_pm_runtime_resume(struct xe_device *xe)