diff options
author | Jani Nikula <jani.nikula@intel.com> | 2018-12-04 05:19:26 -0500 |
---|---|---|
committer | Jani Nikula <jani.nikula@intel.com> | 2018-12-04 12:05:51 -0500 |
commit | 0716931a82b4d0e211d2ef66616ad7130107e455 (patch) | |
tree | 18edd3aa820771aab8091653f6d023395fef48b5 | |
parent | 5179749925933575a67f9d8f16d0cc204f98a29f (diff) |
drm/i915/icl: fix transcoder state readout
Commit 2ca711caeca2 ("drm/i915/icl: Consider DSI for getting transcoder
state") clobbers the previously read TRANS_DDI_FUNC_CTL_EDP register
contents with TRANS_DDI_FUNC_CTL_DSI0 contents. Fix the state readout,
and handle DSI 1 while at it.
Use a bitmask for iterating and logging transcoders, because the allowed
combinations are a bit funky.
Fixes: 2ca711caeca2 ("drm/i915/icl: Consider DSI for getting transcoder state")
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=108928
Cc: Ville Syrjala <ville.syrjala@linux.intel.com>
Cc: Madhav Chauhan <madhav.chauhan@intel.com>
Reviewed-by: Imre Deak <imre.deak@intel.com>
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20181204101926.17174-1-jani.nikula@intel.com
-rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 52 |
1 files changed, 31 insertions, 21 deletions
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index a2584f977ab1..07c861884c70 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
@@ -9476,13 +9476,18 @@ static bool hsw_get_transcoder_state(struct intel_crtc *crtc, | |||
9476 | struct drm_device *dev = crtc->base.dev; | 9476 | struct drm_device *dev = crtc->base.dev; |
9477 | struct drm_i915_private *dev_priv = to_i915(dev); | 9477 | struct drm_i915_private *dev_priv = to_i915(dev); |
9478 | enum intel_display_power_domain power_domain; | 9478 | enum intel_display_power_domain power_domain; |
9479 | unsigned long panel_transcoder_mask = BIT(TRANSCODER_EDP); | ||
9480 | unsigned long enabled_panel_transcoders = 0; | ||
9481 | enum transcoder panel_transcoder; | ||
9479 | u32 tmp; | 9482 | u32 tmp; |
9480 | bool is_dsi = false; | 9483 | |
9481 | bool is_edp = false; | 9484 | if (IS_ICELAKE(dev_priv)) |
9485 | panel_transcoder_mask |= | ||
9486 | BIT(TRANSCODER_DSI_0) | BIT(TRANSCODER_DSI_1); | ||
9482 | 9487 | ||
9483 | /* | 9488 | /* |
9484 | * The pipe->transcoder mapping is fixed with the exception of the eDP | 9489 | * The pipe->transcoder mapping is fixed with the exception of the eDP |
9485 | * transcoder handled below. | 9490 | * and DSI transcoders handled below. |
9486 | */ | 9491 | */ |
9487 | pipe_config->cpu_transcoder = (enum transcoder) crtc->pipe; | 9492 | pipe_config->cpu_transcoder = (enum transcoder) crtc->pipe; |
9488 | 9493 | ||
@@ -9490,23 +9495,26 @@ static bool hsw_get_transcoder_state(struct intel_crtc *crtc, | |||
9490 | * XXX: Do intel_display_power_get_if_enabled before reading this (for | 9495 | * XXX: Do intel_display_power_get_if_enabled before reading this (for |
9491 | * consistency and less surprising code; it's in always on power). | 9496 | * consistency and less surprising code; it's in always on power). |
9492 | */ | 9497 | */ |
9493 | tmp = I915_READ(TRANS_DDI_FUNC_CTL(TRANSCODER_EDP)); | 9498 | for_each_set_bit(panel_transcoder, &panel_transcoder_mask, 32) { |
9494 | if (tmp & TRANS_DDI_FUNC_ENABLE) | 9499 | enum pipe trans_pipe; |
9495 | is_edp = true; | ||
9496 | 9500 | ||
9497 | if (IS_ICELAKE(dev_priv)) { | 9501 | tmp = I915_READ(TRANS_DDI_FUNC_CTL(panel_transcoder)); |
9498 | tmp = I915_READ(TRANS_DDI_FUNC_CTL(TRANSCODER_DSI_0)); | 9502 | if (!(tmp & TRANS_DDI_FUNC_ENABLE)) |
9499 | if (tmp & TRANS_DDI_FUNC_ENABLE) | 9503 | continue; |
9500 | is_dsi = true; | ||
9501 | } | ||
9502 | 9504 | ||
9503 | WARN_ON(is_edp && is_dsi); | 9505 | /* |
9506 | * Log all enabled ones, only use the first one. | ||
9507 | * | ||
9508 | * FIXME: This won't work for two separate DSI displays. | ||
9509 | */ | ||
9510 | enabled_panel_transcoders |= BIT(panel_transcoder); | ||
9511 | if (enabled_panel_transcoders != BIT(panel_transcoder)) | ||
9512 | continue; | ||
9504 | 9513 | ||
9505 | if (is_edp || is_dsi) { | ||
9506 | enum pipe trans_pipe; | ||
9507 | switch (tmp & TRANS_DDI_EDP_INPUT_MASK) { | 9514 | switch (tmp & TRANS_DDI_EDP_INPUT_MASK) { |
9508 | default: | 9515 | default: |
9509 | WARN(1, "unknown pipe linked to edp transcoder\n"); | 9516 | WARN(1, "unknown pipe linked to transcoder %s\n", |
9517 | transcoder_name(panel_transcoder)); | ||
9510 | /* fall through */ | 9518 | /* fall through */ |
9511 | case TRANS_DDI_EDP_INPUT_A_ONOFF: | 9519 | case TRANS_DDI_EDP_INPUT_A_ONOFF: |
9512 | case TRANS_DDI_EDP_INPUT_A_ON: | 9520 | case TRANS_DDI_EDP_INPUT_A_ON: |
@@ -9520,14 +9528,16 @@ static bool hsw_get_transcoder_state(struct intel_crtc *crtc, | |||
9520 | break; | 9528 | break; |
9521 | } | 9529 | } |
9522 | 9530 | ||
9523 | if (trans_pipe == crtc->pipe) { | 9531 | if (trans_pipe == crtc->pipe) |
9524 | if (is_edp) | 9532 | pipe_config->cpu_transcoder = panel_transcoder; |
9525 | pipe_config->cpu_transcoder = TRANSCODER_EDP; | ||
9526 | else if (is_dsi) | ||
9527 | pipe_config->cpu_transcoder = TRANSCODER_DSI_0; | ||
9528 | } | ||
9529 | } | 9533 | } |
9530 | 9534 | ||
9535 | /* | ||
9536 | * Valid combos: none, eDP, DSI0, DSI1, DSI0+DSI1 | ||
9537 | */ | ||
9538 | WARN_ON((enabled_panel_transcoders & BIT(TRANSCODER_EDP)) && | ||
9539 | enabled_panel_transcoders != BIT(TRANSCODER_EDP)); | ||
9540 | |||
9531 | power_domain = POWER_DOMAIN_TRANSCODER(pipe_config->cpu_transcoder); | 9541 | power_domain = POWER_DOMAIN_TRANSCODER(pipe_config->cpu_transcoder); |
9532 | if (!intel_display_power_get_if_enabled(dev_priv, power_domain)) | 9542 | if (!intel_display_power_get_if_enabled(dev_priv, power_domain)) |
9533 | return false; | 9543 | return false; |