Commit 1dd07e56 authored by Imre Deak's avatar Imre Deak Committed by Jani Nikula

drm/i915/icl: Sanitize DDI port clock gating for DSI ports

The requirement for the DDI port clock gating for a port in DSI mode is
the opposite wrt. the case when the port is in DDI mode: the clock
should be gated when the port is active and ungated when the port is
inactive. Note that we cannot simply keep the DDI clock gated when the
port will be only used in DSI mode: it must be gated/ungated at a
specific spot in the DSI enable/disable sequence.

Ensure the above for all ports of a DSI encoder, also adding a sanity
check that we haven't registered another encoder using the same port
(VBT should never allow this to happen).

Cc: Madhav Chauhan <madhav.chauhan@intel.com>
Cc: Vandita Kulkarni <vandita.kulkarni@intel.com>
Cc: Jani Nikula <jani.nikula@intel.com>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Cc: Clint Taylor <clinton.a.taylor@intel.com>
Reviewed-by: default avatarJani Nikula <jani.nikula@intel.com>
Signed-off-by: default avatarImre Deak <imre.deak@intel.com>
Signed-off-by: default avatarJani Nikula <jani.nikula@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/ceb14d5a68e8e23988d923d4290a4f981789e616.1543500285.git.jani.nikula@intel.com
parent 3b8c0d5b
......@@ -28,6 +28,7 @@
#include <drm/drm_scdc_helper.h>
#include "i915_drv.h"
#include "intel_drv.h"
#include "intel_dsi.h"
struct ddi_buf_trans {
u32 trans1; /* balance leg enable, de-emph level */
......@@ -2836,8 +2837,9 @@ void icl_sanitize_encoder_pll_mapping(struct intel_encoder *encoder)
{
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
u32 val;
enum port port = encoder->port;
bool clk_enabled;
enum port port;
u32 port_mask;
bool ddi_clk_needed;
/*
* In case of DP MST, we sanitize the primary encoder only, not the
......@@ -2846,9 +2848,6 @@ void icl_sanitize_encoder_pll_mapping(struct intel_encoder *encoder)
if (encoder->type == INTEL_OUTPUT_DP_MST)
return;
val = I915_READ(DPCLKA_CFGCR0_ICL);
clk_enabled = !(val & icl_dpclka_cfgcr0_clk_off(dev_priv, port));
if (!encoder->base.crtc && intel_encoder_is_dp(encoder)) {
u8 pipe_mask;
bool is_mst;
......@@ -2862,20 +2861,52 @@ void icl_sanitize_encoder_pll_mapping(struct intel_encoder *encoder)
return;
}
if (clk_enabled == !!encoder->base.crtc)
return;
port_mask = BIT(encoder->port);
ddi_clk_needed = encoder->base.crtc;
/*
* Punt on the case now where clock is disabled, but the encoder is
* enabled, something else is really broken then.
*/
if (WARN_ON(!clk_enabled))
return;
if (encoder->type == INTEL_OUTPUT_DSI) {
struct intel_encoder *other_encoder;
DRM_NOTE("Port %c is disabled but it has a mapped PLL, unmap it\n",
port_name(port));
val |= icl_dpclka_cfgcr0_clk_off(dev_priv, port);
I915_WRITE(DPCLKA_CFGCR0_ICL, val);
port_mask = intel_dsi_encoder_ports(encoder);
/*
* Sanity check that we haven't incorrectly registered another
* encoder using any of the ports of this DSI encoder.
*/
for_each_intel_encoder(&dev_priv->drm, other_encoder) {
if (other_encoder == encoder)
continue;
if (WARN_ON(port_mask & BIT(other_encoder->port)))
return;
}
/*
* DSI ports should have their DDI clock ungated when disabled
* and gated when enabled.
*/
ddi_clk_needed = !encoder->base.crtc;
}
val = I915_READ(DPCLKA_CFGCR0_ICL);
for_each_port_masked(port, port_mask) {
bool ddi_clk_ungated = !(val &
icl_dpclka_cfgcr0_clk_off(dev_priv,
port));
if (ddi_clk_needed == ddi_clk_ungated)
continue;
/*
* Punt on the case now where clock is gated, but it would
* be needed by the port. Something else is really broken then.
*/
if (WARN_ON(ddi_clk_needed))
continue;
DRM_NOTE("Port %c is disabled/in DSI mode with an ungated DDI clock, gate it\n",
port_name(port));
val |= icl_dpclka_cfgcr0_clk_off(dev_priv, port);
I915_WRITE(DPCLKA_CFGCR0_ICL, val);
}
}
static void intel_ddi_clk_select(struct intel_encoder *encoder,
......
......@@ -146,6 +146,11 @@ static inline bool is_cmd_mode(struct intel_dsi *intel_dsi)
return intel_dsi->operation_mode == INTEL_DSI_COMMAND_MODE;
}
static inline u16 intel_dsi_encoder_ports(struct intel_encoder *encoder)
{
return enc_to_intel_dsi(&encoder->base)->ports;
}
/* intel_dsi.c */
int intel_dsi_bitrate(const struct intel_dsi *intel_dsi);
int intel_dsi_tlpx_ns(const struct intel_dsi *intel_dsi);
......
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