Basically ULPS handling during enable/disable has been moved to pre_enable and post_disable phases. PLL and panel power disable also has been moved to post_disable phase. The ULPS entry/exit sequneces as suggested by HW team is as follows - During enable time - set DEVICE_READY --> Clear DEVICE_READY --> set DEVICE_READY And during disable time to flush all FIFOs - set ENTER_SLEEP --> EXIT_SLEEP --> ENTER_SLEEP Also during disbale sequnece sub-encoder disable is moved to the end after port is disabled. v2: Based on comments from Ville - Detailed epxlaination in the commit messgae - Moved parameter changes out into another patch - Backlight enabling will be a new patch Signed-off-by: Yogesh Mohan Marimuthu <yogesh.mohan.marimuthu@xxxxxxxxx> Signed-off-by: Shobhit Kumar <shobhit.kumar@xxxxxxxxx> --- drivers/gpu/drm/i915/i915_drv.h | 11 ++++ drivers/gpu/drm/i915/intel_dsi.c | 111 ++++++++++++++++++++++++++------------ drivers/gpu/drm/i915/intel_dsi.h | 2 + 3 files changed, 91 insertions(+), 33 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index a2bbff9..55c16cb 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2433,6 +2433,17 @@ int vlv_freq_opcode(int ddr_freq, int val); #define POSTING_READ(reg) (void)I915_READ_NOTRACE(reg) #define POSTING_READ16(reg) (void)I915_READ16_NOTRACE(reg) +#define I915_WRITE_BITS(reg, val, mask) \ +do { \ + u32 tmp, data; \ + tmp = I915_READ((reg)); \ + tmp &= ~(mask); \ + data = (val) & (mask); \ + data = data | tmp; \ + I915_WRITE((reg), data); \ +} while(0) + + /* "Broadcast RGB" property */ #define INTEL_BROADCAST_RGB_AUTO 0 #define INTEL_BROADCAST_RGB_FULL 1 diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c index 8dc9a38..9e67f78 100644 --- a/drivers/gpu/drm/i915/intel_dsi.c +++ b/drivers/gpu/drm/i915/intel_dsi.c @@ -101,46 +101,59 @@ static void intel_dsi_pre_pll_enable(struct intel_encoder *encoder) vlv_enable_dsi_pll(encoder); } -static void intel_dsi_pre_enable(struct intel_encoder *encoder) -{ - DRM_DEBUG_KMS("\n"); -} - -static void intel_dsi_enable(struct intel_encoder *encoder) +void intel_dsi_device_ready(struct intel_encoder *encoder) { struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc); struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base); int pipe = intel_crtc->pipe; - u32 temp; DRM_DEBUG_KMS("\n"); if (intel_dsi->dev.dev_ops->panel_reset) intel_dsi->dev.dev_ops->panel_reset(&intel_dsi->dev); - temp = I915_READ(MIPI_DEVICE_READY(pipe)); - if ((temp & DEVICE_READY) == 0) { - temp &= ~ULPS_STATE_MASK; - I915_WRITE(MIPI_DEVICE_READY(pipe), temp | DEVICE_READY); - } else if (temp & ULPS_STATE_MASK) { - temp &= ~ULPS_STATE_MASK; - I915_WRITE(MIPI_DEVICE_READY(pipe), temp | ULPS_STATE_EXIT); - /* - * We need to ensure that there is a minimum of 1 ms time - * available before clearing the UPLS exit state. - */ - msleep(2); - I915_WRITE(MIPI_DEVICE_READY(pipe), temp); - } + I915_WRITE_BITS(MIPI_PORT_CTRL(pipe), LP_OUTPUT_HOLD, LP_OUTPUT_HOLD); + usleep_range(1000, 1500); + I915_WRITE_BITS(MIPI_DEVICE_READY(pipe), DEVICE_READY | + ULPS_STATE_EXIT, DEVICE_READY | ULPS_STATE_MASK); + usleep_range(2000, 2500); + I915_WRITE_BITS(MIPI_DEVICE_READY(pipe), DEVICE_READY, + DEVICE_READY | ULPS_STATE_MASK); + usleep_range(2000, 2500); + I915_WRITE_BITS(MIPI_DEVICE_READY(pipe), 0x00, + DEVICE_READY | ULPS_STATE_MASK); + usleep_range(2000, 2500); + I915_WRITE_BITS(MIPI_DEVICE_READY(pipe), DEVICE_READY, + DEVICE_READY | ULPS_STATE_MASK); + usleep_range(2000, 2500); if (intel_dsi->dev.dev_ops->send_otp_cmds) intel_dsi->dev.dev_ops->send_otp_cmds(&intel_dsi->dev); +} +static void intel_dsi_pre_enable(struct intel_encoder *encoder) +{ + DRM_DEBUG_KMS("\n"); + + /* put device in ready state */ + intel_dsi_device_ready(encoder); +} + +static void intel_dsi_enable(struct intel_encoder *encoder) +{ + struct drm_device *dev = encoder->base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc); + struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base); + int pipe = intel_crtc->pipe; + u32 temp; + + DRM_DEBUG_KMS("\n"); + if (is_cmd_mode(intel_dsi)) I915_WRITE(MIPI_MAX_RETURN_PKT_SIZE(pipe), 8 * 4); - - if (is_vid_mode(intel_dsi)) { + else { msleep(20); /* XXX */ dpi_send_cmd(intel_dsi, TURN_ON); msleep(100); @@ -157,7 +170,8 @@ static void intel_dsi_enable(struct intel_encoder *encoder) static void intel_dsi_disable(struct intel_encoder *encoder) { - struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; + struct drm_device *dev = encoder->base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc); struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base); int pipe = intel_crtc->pipe; @@ -165,8 +179,6 @@ static void intel_dsi_disable(struct intel_encoder *encoder) DRM_DEBUG_KMS("\n"); - intel_dsi->dev.dev_ops->disable(&intel_dsi->dev); - if (is_vid_mode(intel_dsi)) { dpi_send_cmd(intel_dsi, SHUTDOWN); msleep(10); @@ -179,19 +191,52 @@ static void intel_dsi_disable(struct intel_encoder *encoder) msleep(2); } - temp = I915_READ(MIPI_DEVICE_READY(pipe)); - if (temp & DEVICE_READY) { - temp &= ~DEVICE_READY; - temp &= ~ULPS_STATE_MASK; - I915_WRITE(MIPI_DEVICE_READY(pipe), temp); - } + /* if disable packets are sent before sending shutdown packet then in + * some next enable sequence send turn on packet error is observed */ + if (intel_dsi->dev.dev_ops->disable) + intel_dsi->dev.dev_ops->disable(&intel_dsi->dev); } -static void intel_dsi_post_disable(struct intel_encoder *encoder) +void intel_dsi_clear_device_ready(struct intel_encoder *encoder) { + struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; + struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc); + struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base); + int pipe = intel_crtc->pipe; + DRM_DEBUG_KMS("\n"); + I915_WRITE_BITS(MIPI_DEVICE_READY(pipe), ULPS_STATE_ENTER, + ULPS_STATE_MASK); + usleep_range(2000, 2500); + + I915_WRITE_BITS(MIPI_DEVICE_READY(pipe), ULPS_STATE_EXIT, + ULPS_STATE_MASK); + usleep_range(2000, 2500); + + I915_WRITE_BITS(MIPI_DEVICE_READY(pipe), ULPS_STATE_ENTER, + ULPS_STATE_MASK); + usleep_range(2000, 2500); + + I915_WRITE_BITS(MIPI_PORT_CTRL(pipe), 0, LP_OUTPUT_HOLD); + usleep_range(1000, 1500); + + if (wait_for(((I915_READ(MIPI_PORT_CTRL(pipe)) & 0x20000) + == 0x00000), 30)) + DRM_ERROR("DSI LP not going Low\n"); + + I915_WRITE_BITS(MIPI_DEVICE_READY(pipe), 0x00, DEVICE_READY); + usleep_range(2000, 2500); + vlv_disable_dsi_pll(encoder); + + if (intel_dsi->dev.dev_ops->disable_panel_power) + intel_dsi->dev.dev_ops->disable_panel_power(&intel_dsi->dev); +} +static void intel_dsi_post_disable(struct intel_encoder *encoder) +{ + DRM_DEBUG_KMS("\n"); + intel_dsi_clear_device_ready(encoder); } static bool intel_dsi_get_hw_state(struct intel_encoder *encoder, diff --git a/drivers/gpu/drm/i915/intel_dsi.h b/drivers/gpu/drm/i915/intel_dsi.h index 14509d6..387dfe1 100644 --- a/drivers/gpu/drm/i915/intel_dsi.h +++ b/drivers/gpu/drm/i915/intel_dsi.h @@ -41,6 +41,8 @@ struct intel_dsi_dev_ops { void (*panel_reset)(struct intel_dsi_device *dsi); + void (*disable_panel_power)(struct intel_dsi_device *dsi); + /* one time programmable commands if needed */ void (*send_otp_cmds)(struct intel_dsi_device *dsi); -- 1.7.9.5 _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/intel-gfx