2012-08-13 10:18:55

by Jani Nikula

[permalink] [raw]
Subject: [PATCH 0/2] GMBUS EDID read bit-banging fallback

Alex, Maciej, please test the following to see if it fixes the issue
[1], thanks.

BR,
Jani.


[1] https://bugzilla.kernel.org/show_bug.cgi?id=45881

Jani Nikula (2):
drm/i915: extract connector update from intel_ddc_get_modes() for
reuse
drm/i915: fall back to bit-banging if GMBUS fails in CRT EDID reads

drivers/gpu/drm/i915/intel_crt.c | 36 +++++++++++++++++++++++++++++++++---
drivers/gpu/drm/i915/intel_drv.h | 2 ++
drivers/gpu/drm/i915/intel_modes.c | 31 ++++++++++++++++++++++---------
3 files changed, 57 insertions(+), 12 deletions(-)

--
1.7.9.5


2012-08-13 10:19:00

by Jani Nikula

[permalink] [raw]
Subject: [PATCH 1/2] drm/i915: extract connector update from intel_ddc_get_modes() for reuse

Refactor the connector update part of intel_ddc_get_modes() into a separate
intel_connector_update_modes() function for reuse. No functional changes.

Signed-off-by: Jani Nikula <[email protected]>
---
drivers/gpu/drm/i915/intel_drv.h | 2 ++
drivers/gpu/drm/i915/intel_modes.c | 31 ++++++++++++++++++++++---------
2 files changed, 24 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 13f0467..8a224ca 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -357,6 +357,8 @@ struct intel_fbc_work {
int interval;
};

+int intel_connector_update_modes(struct drm_connector *connector,
+ struct edid *edid);
int intel_ddc_get_modes(struct drm_connector *c, struct i2c_adapter *adapter);

extern void intel_attach_force_audio_property(struct drm_connector *connector);
diff --git a/drivers/gpu/drm/i915/intel_modes.c b/drivers/gpu/drm/i915/intel_modes.c
index 45848b9..29b7259 100644
--- a/drivers/gpu/drm/i915/intel_modes.c
+++ b/drivers/gpu/drm/i915/intel_modes.c
@@ -33,6 +33,25 @@
#include "i915_drv.h"

/**
+ * intel_connector_update_modes - update connector from edid
+ * @connector: DRM connector device to use
+ * @edid: previously read EDID information
+ */
+int intel_connector_update_modes(struct drm_connector *connector,
+ struct edid *edid)
+{
+ int ret;
+
+ drm_mode_connector_update_edid_property(connector, edid);
+ ret = drm_add_edid_modes(connector, edid);
+ drm_edid_to_eld(connector, edid);
+ connector->display_info.raw_edid = NULL;
+ kfree(edid);
+
+ return ret;
+}
+
+/**
* intel_ddc_get_modes - get modelist from monitor
* @connector: DRM connector device to use
* @adapter: i2c adapter
@@ -43,18 +62,12 @@ int intel_ddc_get_modes(struct drm_connector *connector,
struct i2c_adapter *adapter)
{
struct edid *edid;
- int ret = 0;

edid = drm_get_edid(connector, adapter);
- if (edid) {
- drm_mode_connector_update_edid_property(connector, edid);
- ret = drm_add_edid_modes(connector, edid);
- drm_edid_to_eld(connector, edid);
- connector->display_info.raw_edid = NULL;
- kfree(edid);
- }
+ if (!edid)
+ return 0;

- return ret;
+ return intel_connector_update_modes(connector, edid);
}

static const struct drm_prop_enum_list force_audio_names[] = {
--
1.7.9.5

2012-08-13 10:19:04

by Jani Nikula

[permalink] [raw]
Subject: [PATCH 2/2] drm/i915: fall back to bit-banging if GMBUS fails in CRT EDID reads

GMBUS was enabled over bit-banging as the default in commits:

commit c3dfefa0a6d235bd465309e12f4c56ea16e71111
Author: Daniel Vetter <[email protected]>
Date: Tue Feb 14 22:37:25 2012 +0100

drm/i915: reenable gmbus on gen3+ again

and

commit 0fb3f969c8683505fb7323c06bf8a999a5a45a15
Author: Daniel Vetter <[email protected]>
Date: Fri Mar 2 19:38:30 2012 +0100

drm/i915: enable gmbus on gen2

Unfortunately, GMBUS seems to fail on some CRT displays. Add a bit-banging
fallback to CRT EDID reads.

LKML-Reference: <[email protected]>
Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=45881
Signed-off-by: Jani Nikula <[email protected]>
---
drivers/gpu/drm/i915/intel_crt.c | 36 +++++++++++++++++++++++++++++++++---
1 file changed, 33 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c
index bc5e2c9..80bf311 100644
--- a/drivers/gpu/drm/i915/intel_crt.c
+++ b/drivers/gpu/drm/i915/intel_crt.c
@@ -328,6 +328,36 @@ static bool intel_crt_detect_hotplug(struct drm_connector *connector)
return ret;
}

+static struct edid *intel_crt_get_edid(struct drm_connector *connector,
+ struct i2c_adapter *i2c)
+{
+ struct edid *edid;
+
+ edid = drm_get_edid(connector, i2c);
+
+ if (!edid && !intel_gmbus_is_forced_bit(i2c)) {
+ DRM_DEBUG_KMS("CRT GMBUS EDID read failed, retry using GPIO bit-banging\n");
+ intel_gmbus_force_bit(i2c, true);
+ edid = drm_get_edid(connector, i2c);
+ intel_gmbus_force_bit(i2c, false);
+ }
+
+ return edid;
+}
+
+/* local version of intel_ddc_get_modes() to use intel_crt_get_edid() */
+static int intel_crt_ddc_get_modes(struct drm_connector *connector,
+ struct i2c_adapter *adapter)
+{
+ struct edid *edid;
+
+ edid = intel_crt_get_edid(connector, adapter);
+ if (!edid)
+ return 0;
+
+ return intel_connector_update_modes(connector, edid);
+}
+
static bool intel_crt_detect_ddc(struct drm_connector *connector)
{
struct intel_crt *crt = intel_attached_crt(connector);
@@ -338,7 +368,7 @@ static bool intel_crt_detect_ddc(struct drm_connector *connector)
BUG_ON(crt->base.type != INTEL_OUTPUT_ANALOG);

i2c = intel_gmbus_get_adapter(dev_priv, dev_priv->crt_ddc_pin);
- edid = drm_get_edid(connector, i2c);
+ edid = intel_crt_get_edid(connector, i2c);

if (edid) {
bool is_digital = edid->input & DRM_EDID_INPUT_DIGITAL;
@@ -546,13 +576,13 @@ static int intel_crt_get_modes(struct drm_connector *connector)
struct i2c_adapter *i2c;

i2c = intel_gmbus_get_adapter(dev_priv, dev_priv->crt_ddc_pin);
- ret = intel_ddc_get_modes(connector, i2c);
+ ret = intel_crt_ddc_get_modes(connector, i2c);
if (ret || !IS_G4X(dev))
return ret;

/* Try to probe digital port for output in DVI-I -> VGA mode. */
i2c = intel_gmbus_get_adapter(dev_priv, GMBUS_PORT_DPB);
- return intel_ddc_get_modes(connector, i2c);
+ return intel_crt_ddc_get_modes(connector, i2c);
}

static int intel_crt_set_property(struct drm_connector *connector,
--
1.7.9.5

2012-08-16 14:34:45

by Daniel Vetter

[permalink] [raw]
Subject: Re: [PATCH 2/2] drm/i915: fall back to bit-banging if GMBUS fails in CRT EDID reads

On Mon, Aug 13, 2012 at 01:22:35PM +0300, Jani Nikula wrote:
> GMBUS was enabled over bit-banging as the default in commits:
>
> commit c3dfefa0a6d235bd465309e12f4c56ea16e71111
> Author: Daniel Vetter <[email protected]>
> Date: Tue Feb 14 22:37:25 2012 +0100
>
> drm/i915: reenable gmbus on gen3+ again
>
> and
>
> commit 0fb3f969c8683505fb7323c06bf8a999a5a45a15
> Author: Daniel Vetter <[email protected]>
> Date: Fri Mar 2 19:38:30 2012 +0100
>
> drm/i915: enable gmbus on gen2
>
> Unfortunately, GMBUS seems to fail on some CRT displays. Add a bit-banging
> fallback to CRT EDID reads.
>
> LKML-Reference: <[email protected]>
> Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=45881
> Signed-off-by: Jani Nikula <[email protected]>
Patches applied to -fixes with the tested-by result from the bug report.
I've also put a cc: stable on both of them, since the regression is
already in 3.4.

Thanks, Daniel
--
Daniel Vetter
Mail: [email protected]
Mobile: +41 (0)79 365 57 48