From: Madhav Chauhan <madhav.chauhan@xxxxxxxxx> As per BSPEC, driver needs to ensure that all of commands/data has been dispatched to panel before the transcoder is enabled. This patch implement those steps i.e. sending NOP DCS command, wait for header/payload credit to be released etc. Signed-off-by: Madhav Chauhan <madhav.chauhan@xxxxxxxxx> Signed-off-by: Jani Nikula <jani.nikula@xxxxxxxxx> --- drivers/gpu/drm/i915/icl_dsi.c | 53 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 48 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/icl_dsi.c b/drivers/gpu/drm/i915/icl_dsi.c index 5fe024dfbdb0..90188ba8a4dc 100644 --- a/drivers/gpu/drm/i915/icl_dsi.c +++ b/drivers/gpu/drm/i915/icl_dsi.c @@ -28,9 +28,8 @@ #include <drm/drm_mipi_dsi.h> #include "intel_dsi.h" -static void __attribute__((unused)) wait_for_dsi_hdr_credit_release( - struct intel_dsi *intel_dsi, - enum transcoder dsi_trans) +static void wait_for_dsi_hdr_credit_release(struct intel_dsi *intel_dsi, + enum transcoder dsi_trans) { struct drm_i915_private *dev_priv = to_i915(intel_dsi->base.base.dev); @@ -40,8 +39,7 @@ static void __attribute__((unused)) wait_for_dsi_hdr_credit_release( DRM_ERROR("DSI header credits not released\n"); } -static void __attribute__((unused)) wait_for_dsi_payload_credit_release( - struct intel_dsi *intel_dsi, +static void wait_for_dsi_payload_credit_release(struct intel_dsi *intel_dsi, enum transcoder dsi_trans) { struct drm_i915_private *dev_priv = to_i915(intel_dsi->base.base.dev); @@ -60,6 +58,48 @@ static enum transcoder dsi_port_to_transcoder(enum port port) return TRANSCODER_DSI_1; } +static void wait_for_cmds_dispatched_to_panel(struct intel_encoder *encoder) +{ + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base); + struct mipi_dsi_device *dsi; + enum port port; + enum transcoder dsi_trans; + int ret; + + /* wait for header/payload credits to be released */ + for_each_dsi_port(port, intel_dsi->ports) { + dsi_trans = dsi_port_to_transcoder(port); + wait_for_dsi_hdr_credit_release(intel_dsi, dsi_trans); + wait_for_dsi_payload_credit_release(intel_dsi, dsi_trans); + } + + /* send nop DCS command */ + for_each_dsi_port(port, intel_dsi->ports) { + dsi = intel_dsi->dsi_hosts[port]->device; + dsi->mode_flags |= MIPI_DSI_MODE_LPM; + dsi->channel = 0; + ret = mipi_dsi_dcs_nop(dsi); + if (ret < 0) + DRM_ERROR("error sending DCS NOP command\n"); + } + + /* wait for header credits to be released */ + for_each_dsi_port(port, intel_dsi->ports) { + dsi_trans = dsi_port_to_transcoder(port); + wait_for_dsi_hdr_credit_release(intel_dsi, dsi_trans); + } + + /* wait for LP TX in progress bit to be cleared */ + for_each_dsi_port(port, intel_dsi->ports) { + dsi_trans = dsi_port_to_transcoder(port); + if (wait_for_us(!(I915_READ(DSI_LP_MSG(dsi_trans)) & + LPTX_IN_PROGRESS), + 20)) + DRM_ERROR("LPTX bit not cleared\n"); + } +} + static void dsi_program_swing_and_deemphasis(struct intel_encoder *encoder) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); @@ -690,6 +730,9 @@ static void gen11_dsi_powerup_panel(struct intel_encoder *encoder) intel_dsi_vbt_exec_sequence(intel_dsi, MIPI_SEQ_DEASSERT_RESET); intel_dsi_vbt_exec_sequence(intel_dsi, MIPI_SEQ_INIT_OTP); intel_dsi_vbt_exec_sequence(intel_dsi, MIPI_SEQ_DISPLAY_ON); + + /* ensure all panel commands dispatched before enabling transcoder */ + wait_for_cmds_dispatched_to_panel(encoder); } static void __attribute__((unused)) -- 2.11.0 _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/intel-gfx