Commit 5165fe0b authored by Dave Airlie's avatar Dave Airlie

Merge tag 'drm-intel-fixes-2021-03-25-1' of...

Merge tag 'drm-intel-fixes-2021-03-25-1' of git://anongit.freedesktop.org/drm/drm-intel into drm-fixes

- DisplayPort LTTPR fixes around link training and limiting it
  according to supported spec version. (Imre)
- Fix enabled_planes bitmask to really represent only logically
  enabled planes (Ville).
- Fix DSS CTL registers for ICL DSI transcoders (Jani)
- Fix the GT fence revocation runtime PM logic. (Imre)
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>

From: Rodrigo Vivi <rodrigo.vivi@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/YFxYdrjqeUtSu+3p@intel.com
parents 0f43ad78 8840e3bd
......@@ -317,12 +317,13 @@ int intel_plane_atomic_check_with_state(const struct intel_crtc_state *old_crtc_
if (!new_plane_state->hw.crtc && !old_plane_state->hw.crtc)
return 0;
new_crtc_state->enabled_planes |= BIT(plane->id);
ret = plane->check_plane(new_crtc_state, new_plane_state);
if (ret)
return ret;
if (fb)
new_crtc_state->enabled_planes |= BIT(plane->id);
/* FIXME pre-g4x don't work like this */
if (new_plane_state->uapi.visible)
new_crtc_state->active_planes |= BIT(plane->id);
......
......@@ -3619,9 +3619,7 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp)
{
int ret;
intel_dp_lttpr_init(intel_dp);
if (drm_dp_read_dpcd_caps(&intel_dp->aux, intel_dp->dpcd))
if (intel_dp_init_lttpr_and_dprx_caps(intel_dp) < 0)
return false;
/*
......
......@@ -133,6 +133,7 @@ static u32 g4x_get_aux_send_ctl(struct intel_dp *intel_dp,
else
precharge = 5;
/* Max timeout value on G4x-BDW: 1.6ms */
if (IS_BROADWELL(dev_priv))
timeout = DP_AUX_CH_CTL_TIME_OUT_600us;
else
......@@ -159,6 +160,12 @@ static u32 skl_get_aux_send_ctl(struct intel_dp *intel_dp,
enum phy phy = intel_port_to_phy(i915, dig_port->base.port);
u32 ret;
/*
* Max timeout values:
* SKL-GLK: 1.6ms
* CNL: 3.2ms
* ICL+: 4ms
*/
ret = DP_AUX_CH_CTL_SEND_BUSY |
DP_AUX_CH_CTL_DONE |
DP_AUX_CH_CTL_INTERRUPT |
......
......@@ -34,6 +34,11 @@ intel_dp_dump_link_status(const u8 link_status[DP_LINK_STATUS_SIZE])
link_status[3], link_status[4], link_status[5]);
}
static void intel_dp_reset_lttpr_common_caps(struct intel_dp *intel_dp)
{
memset(&intel_dp->lttpr_common_caps, 0, sizeof(intel_dp->lttpr_common_caps));
}
static void intel_dp_reset_lttpr_count(struct intel_dp *intel_dp)
{
intel_dp->lttpr_common_caps[DP_PHY_REPEATER_CNT -
......@@ -81,19 +86,36 @@ static void intel_dp_read_lttpr_phy_caps(struct intel_dp *intel_dp,
static bool intel_dp_read_lttpr_common_caps(struct intel_dp *intel_dp)
{
if (drm_dp_read_lttpr_common_caps(&intel_dp->aux,
intel_dp->lttpr_common_caps) < 0) {
memset(intel_dp->lttpr_common_caps, 0,
sizeof(intel_dp->lttpr_common_caps));
struct drm_i915_private *i915 = dp_to_i915(intel_dp);
if (intel_dp_is_edp(intel_dp))
return false;
}
/*
* Detecting LTTPRs must be avoided on platforms with an AUX timeout
* period < 3.2ms. (see DP Standard v2.0, 2.11.2, 3.6.6.1).
*/
if (INTEL_GEN(i915) < 10)
return false;
if (drm_dp_read_lttpr_common_caps(&intel_dp->aux,
intel_dp->lttpr_common_caps) < 0)
goto reset_caps;
drm_dbg_kms(&dp_to_i915(intel_dp)->drm,
"LTTPR common capabilities: %*ph\n",
(int)sizeof(intel_dp->lttpr_common_caps),
intel_dp->lttpr_common_caps);
/* The minimum value of LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV is 1.4 */
if (intel_dp->lttpr_common_caps[0] < 0x14)
goto reset_caps;
return true;
reset_caps:
intel_dp_reset_lttpr_common_caps(intel_dp);
return false;
}
static bool
......@@ -106,33 +128,49 @@ intel_dp_set_lttpr_transparent_mode(struct intel_dp *intel_dp, bool enable)
}
/**
* intel_dp_lttpr_init - detect LTTPRs and init the LTTPR link training mode
* intel_dp_init_lttpr_and_dprx_caps - detect LTTPR and DPRX caps, init the LTTPR link training mode
* @intel_dp: Intel DP struct
*
* Read the LTTPR common capabilities, switch to non-transparent link training
* mode if any is detected and read the PHY capabilities for all detected
* LTTPRs. In case of an LTTPR detection error or if the number of
* Read the LTTPR common and DPRX capabilities and switch to non-transparent
* link training mode if any is detected and read the PHY capabilities for all
* detected LTTPRs. In case of an LTTPR detection error or if the number of
* LTTPRs is more than is supported (8), fall back to the no-LTTPR,
* transparent mode link training mode.
*
* Returns:
* >0 if LTTPRs were detected and the non-transparent LT mode was set
* >0 if LTTPRs were detected and the non-transparent LT mode was set. The
* DPRX capabilities are read out.
* 0 if no LTTPRs or more than 8 LTTPRs were detected or in case of a
* detection failure and the transparent LT mode was set
* detection failure and the transparent LT mode was set. The DPRX
* capabilities are read out.
* <0 Reading out the DPRX capabilities failed.
*/
int intel_dp_lttpr_init(struct intel_dp *intel_dp)
int intel_dp_init_lttpr_and_dprx_caps(struct intel_dp *intel_dp)
{
int lttpr_count;
bool ret;
int i;
if (intel_dp_is_edp(intel_dp))
return 0;
ret = intel_dp_read_lttpr_common_caps(intel_dp);
/* The DPTX shall read the DPRX caps after LTTPR detection. */
if (drm_dp_read_dpcd_caps(&intel_dp->aux, intel_dp->dpcd)) {
intel_dp_reset_lttpr_common_caps(intel_dp);
return -EIO;
}
if (!ret)
return 0;
/*
* The 0xF0000-0xF02FF range is only valid if the DPCD revision is
* at least 1.4.
*/
if (intel_dp->dpcd[DP_DPCD_REV] < 0x14) {
intel_dp_reset_lttpr_common_caps(intel_dp);
return 0;
}
lttpr_count = drm_dp_lttpr_count(intel_dp->lttpr_common_caps);
/*
* Prevent setting LTTPR transparent mode explicitly if no LTTPRs are
......@@ -172,7 +210,7 @@ int intel_dp_lttpr_init(struct intel_dp *intel_dp)
return lttpr_count;
}
EXPORT_SYMBOL(intel_dp_lttpr_init);
EXPORT_SYMBOL(intel_dp_init_lttpr_and_dprx_caps);
static u8 dp_voltage_max(u8 preemph)
{
......@@ -807,7 +845,10 @@ void intel_dp_start_link_train(struct intel_dp *intel_dp,
* TODO: Reiniting LTTPRs here won't be needed once proper connector
* HW state readout is added.
*/
int lttpr_count = intel_dp_lttpr_init(intel_dp);
int lttpr_count = intel_dp_init_lttpr_and_dprx_caps(intel_dp);
if (lttpr_count < 0)
return;
if (!intel_dp_link_train_all_phys(intel_dp, crtc_state, lttpr_count))
intel_dp_schedule_fallback_link_training(intel_dp, crtc_state);
......
......@@ -11,7 +11,7 @@
struct intel_crtc_state;
struct intel_dp;
int intel_dp_lttpr_init(struct intel_dp *intel_dp);
int intel_dp_init_lttpr_and_dprx_caps(struct intel_dp *intel_dp);
void intel_dp_get_adjust_train(struct intel_dp *intel_dp,
const struct intel_crtc_state *crtc_state,
......
......@@ -1014,20 +1014,14 @@ static i915_reg_t dss_ctl1_reg(const struct intel_crtc_state *crtc_state)
{
enum pipe pipe = to_intel_crtc(crtc_state->uapi.crtc)->pipe;
if (crtc_state->cpu_transcoder == TRANSCODER_EDP)
return DSS_CTL1;
return ICL_PIPE_DSS_CTL1(pipe);
return is_pipe_dsc(crtc_state) ? ICL_PIPE_DSS_CTL1(pipe) : DSS_CTL1;
}
static i915_reg_t dss_ctl2_reg(const struct intel_crtc_state *crtc_state)
{
enum pipe pipe = to_intel_crtc(crtc_state->uapi.crtc)->pipe;
if (crtc_state->cpu_transcoder == TRANSCODER_EDP)
return DSS_CTL2;
return ICL_PIPE_DSS_CTL2(pipe);
return is_pipe_dsc(crtc_state) ? ICL_PIPE_DSS_CTL2(pipe) : DSS_CTL2;
}
void intel_dsc_enable(struct intel_encoder *encoder,
......
......@@ -316,7 +316,18 @@ void i915_vma_revoke_fence(struct i915_vma *vma)
WRITE_ONCE(fence->vma, NULL);
vma->fence = NULL;
with_intel_runtime_pm_if_in_use(fence_to_uncore(fence)->rpm, wakeref)
/*
* Skip the write to HW if and only if the device is currently
* suspended.
*
* If the driver does not currently hold a wakeref (if_in_use == 0),
* the device may currently be runtime suspended, or it may be woken
* up before the suspend takes place. If the device is not suspended
* (powered down) and we skip clearing the fence register, the HW is
* left in an undefined state where we may end up with multiple
* registers overlapping.
*/
with_intel_runtime_pm_if_active(fence_to_uncore(fence)->rpm, wakeref)
fence_write(fence);
}
......
......@@ -412,12 +412,20 @@ intel_wakeref_t intel_runtime_pm_get(struct intel_runtime_pm *rpm)
}
/**
* intel_runtime_pm_get_if_in_use - grab a runtime pm reference if device in use
* __intel_runtime_pm_get_if_active - grab a runtime pm reference if device is active
* @rpm: the intel_runtime_pm structure
* @ignore_usecount: get a ref even if dev->power.usage_count is 0
*
* This function grabs a device-level runtime pm reference if the device is
* already in use and ensures that it is powered up. It is illegal to try
* and access the HW should intel_runtime_pm_get_if_in_use() report failure.
* already active and ensures that it is powered up. It is illegal to try
* and access the HW should intel_runtime_pm_get_if_active() report failure.
*
* If @ignore_usecount=true, a reference will be acquired even if there is no
* user requiring the device to be powered up (dev->power.usage_count == 0).
* If the function returns false in this case then it's guaranteed that the
* device's runtime suspend hook has been called already or that it will be
* called (and hence it's also guaranteed that the device's runtime resume
* hook will be called eventually).
*
* Any runtime pm reference obtained by this function must have a symmetric
* call to intel_runtime_pm_put() to release the reference again.
......@@ -425,7 +433,8 @@ intel_wakeref_t intel_runtime_pm_get(struct intel_runtime_pm *rpm)
* Returns: the wakeref cookie to pass to intel_runtime_pm_put(), evaluates
* as True if the wakeref was acquired, or False otherwise.
*/
intel_wakeref_t intel_runtime_pm_get_if_in_use(struct intel_runtime_pm *rpm)
static intel_wakeref_t __intel_runtime_pm_get_if_active(struct intel_runtime_pm *rpm,
bool ignore_usecount)
{
if (IS_ENABLED(CONFIG_PM)) {
/*
......@@ -434,7 +443,7 @@ intel_wakeref_t intel_runtime_pm_get_if_in_use(struct intel_runtime_pm *rpm)
* function, since the power state is undefined. This applies
* atm to the late/early system suspend/resume handlers.
*/
if (pm_runtime_get_if_in_use(rpm->kdev) <= 0)
if (pm_runtime_get_if_active(rpm->kdev, ignore_usecount) <= 0)
return 0;
}
......@@ -443,6 +452,16 @@ intel_wakeref_t intel_runtime_pm_get_if_in_use(struct intel_runtime_pm *rpm)
return track_intel_runtime_pm_wakeref(rpm);
}
intel_wakeref_t intel_runtime_pm_get_if_in_use(struct intel_runtime_pm *rpm)
{
return __intel_runtime_pm_get_if_active(rpm, false);
}
intel_wakeref_t intel_runtime_pm_get_if_active(struct intel_runtime_pm *rpm)
{
return __intel_runtime_pm_get_if_active(rpm, true);
}
/**
* intel_runtime_pm_get_noresume - grab a runtime pm reference
* @rpm: the intel_runtime_pm structure
......
......@@ -177,6 +177,7 @@ void intel_runtime_pm_driver_release(struct intel_runtime_pm *rpm);
intel_wakeref_t intel_runtime_pm_get(struct intel_runtime_pm *rpm);
intel_wakeref_t intel_runtime_pm_get_if_in_use(struct intel_runtime_pm *rpm);
intel_wakeref_t intel_runtime_pm_get_if_active(struct intel_runtime_pm *rpm);
intel_wakeref_t intel_runtime_pm_get_noresume(struct intel_runtime_pm *rpm);
intel_wakeref_t intel_runtime_pm_get_raw(struct intel_runtime_pm *rpm);
......@@ -188,6 +189,10 @@ intel_wakeref_t intel_runtime_pm_get_raw(struct intel_runtime_pm *rpm);
for ((wf) = intel_runtime_pm_get_if_in_use(rpm); (wf); \
intel_runtime_pm_put((rpm), (wf)), (wf) = 0)
#define with_intel_runtime_pm_if_active(rpm, wf) \
for ((wf) = intel_runtime_pm_get_if_active(rpm); (wf); \
intel_runtime_pm_put((rpm), (wf)), (wf) = 0)
void intel_runtime_pm_put_unchecked(struct intel_runtime_pm *rpm);
#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_RUNTIME_PM)
void intel_runtime_pm_put(struct intel_runtime_pm *rpm, intel_wakeref_t wref);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment