Commit 0095e6dc authored by Paulo Zanoni's avatar Paulo Zanoni Committed by Daniel Vetter

drm/i915: init the DP panel power seq variables earlier

Our driver has two different ways of waiting for panel power
sequencing delays. One of these ways is through
ironlake_wait_panel_status, which implicitly uses the values written
to our registers. The other way is through the functions that call
intel_wait_until_after, and on this case we do direct msleep() calls
on the intel_dp->xxx_delay variables.

Function intel_dp_init_panel_power_sequencer is responsible for
initializing the _delay variables and deciding which values we need to
write to the registers, but it does not write these values to the
registers. Only at intel_dp_init_panel_power_sequencer_registers we
actually do this write.

Then problem is that when we call intel_dp_i2c_init, we will get some
I2C calls, which will trigger a VDD enable, which will make use of the
panel power sequencing registers and the _delay variables, so we need
to have both ready by this time. Today, when this happens, the _delay
variables are zero (because they were not computed) and the panel
power sequence registers contain whatever values were written by the
BIOS (which are usually correct).

What this patch does is to make sure that function
intel_dp_init_panel_power_sequencer is called earlier, so by the time
we call intel_dp_i2c_init, the _delay variables will already be
initialized. The actual registers won't contain their final values,
but at least they will contain the values set by the BIOS.

The good side is that we were reading the values, but were not using
them for anything (because we were just skipping the msleep(0) calls),
so this "fix" shouldn't fix any real existing bugs. I was only able to
identify the problem because I added some debug code to check how much
time time we were saving with my previous patch.

Regression introduced by:
    commit ed92f0b2
    Author: Paulo Zanoni <paulo.r.zanoni@intel.com>
    Date:   Wed Jun 12 17:27:24 2013 -0300
        drm/i915: extract intel_edp_init_connector

v2: - Rewrite commit message.
Reviewed-by: default avatarJesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: default avatarPaulo Zanoni <paulo.r.zanoni@intel.com>
Signed-off-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
parent 7f1bdbcb
...@@ -3545,14 +3545,14 @@ intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev, ...@@ -3545,14 +3545,14 @@ intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev,
} }
static bool intel_edp_init_connector(struct intel_dp *intel_dp, static bool intel_edp_init_connector(struct intel_dp *intel_dp,
struct intel_connector *intel_connector) struct intel_connector *intel_connector,
struct edp_power_seq *power_seq)
{ {
struct drm_connector *connector = &intel_connector->base; struct drm_connector *connector = &intel_connector->base;
struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
struct drm_device *dev = intel_dig_port->base.base.dev; struct drm_device *dev = intel_dig_port->base.base.dev;
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_display_mode *fixed_mode = NULL; struct drm_display_mode *fixed_mode = NULL;
struct edp_power_seq power_seq = { 0 };
bool has_dpcd; bool has_dpcd;
struct drm_display_mode *scan; struct drm_display_mode *scan;
struct edid *edid; struct edid *edid;
...@@ -3560,8 +3560,6 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp, ...@@ -3560,8 +3560,6 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
if (!is_edp(intel_dp)) if (!is_edp(intel_dp))
return true; return true;
intel_dp_init_panel_power_sequencer(dev, intel_dp, &power_seq);
/* Cache DPCD and EDID for edp. */ /* Cache DPCD and EDID for edp. */
ironlake_edp_panel_vdd_on(intel_dp); ironlake_edp_panel_vdd_on(intel_dp);
has_dpcd = intel_dp_get_dpcd(intel_dp); has_dpcd = intel_dp_get_dpcd(intel_dp);
...@@ -3579,8 +3577,7 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp, ...@@ -3579,8 +3577,7 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
} }
/* We now know it's not a ghost, init power sequence regs. */ /* We now know it's not a ghost, init power sequence regs. */
intel_dp_init_panel_power_sequencer_registers(dev, intel_dp, intel_dp_init_panel_power_sequencer_registers(dev, intel_dp, power_seq);
&power_seq);
edid = drm_get_edid(connector, &intel_dp->adapter); edid = drm_get_edid(connector, &intel_dp->adapter);
if (edid) { if (edid) {
...@@ -3629,6 +3626,7 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port, ...@@ -3629,6 +3626,7 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
struct drm_device *dev = intel_encoder->base.dev; struct drm_device *dev = intel_encoder->base.dev;
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
enum port port = intel_dig_port->port; enum port port = intel_dig_port->port;
struct edp_power_seq power_seq = { 0 };
const char *name = NULL; const char *name = NULL;
int type, error; int type, error;
...@@ -3712,13 +3710,16 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port, ...@@ -3712,13 +3710,16 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
BUG(); BUG();
} }
if (is_edp(intel_dp))
intel_dp_init_panel_power_sequencer(dev, intel_dp, &power_seq);
error = intel_dp_i2c_init(intel_dp, intel_connector, name); error = intel_dp_i2c_init(intel_dp, intel_connector, name);
WARN(error, "intel_dp_i2c_init failed with error %d for port %c\n", WARN(error, "intel_dp_i2c_init failed with error %d for port %c\n",
error, port_name(port)); error, port_name(port));
intel_dp->psr_setup_done = false; intel_dp->psr_setup_done = false;
if (!intel_edp_init_connector(intel_dp, intel_connector)) { if (!intel_edp_init_connector(intel_dp, intel_connector, &power_seq)) {
i2c_del_adapter(&intel_dp->adapter); i2c_del_adapter(&intel_dp->adapter);
if (is_edp(intel_dp)) { if (is_edp(intel_dp)) {
cancel_delayed_work_sync(&intel_dp->panel_vdd_work); cancel_delayed_work_sync(&intel_dp->panel_vdd_work);
......
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