[PATCH 09/10] drm/i015: Share the EDID caching logic and mode query between LVDS and eDP

Chris Wilson
2011-04-22T09:19:28Z

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
---
drivers/gpu/drm/i915/intel_dp.c | 54 +++++++++++++++++------------------
drivers/gpu/drm/i915/intel_drv.h | 3 ++
drivers/gpu/drm/i915/intel_lvds.c | 33 ++++++---------------
drivers/gpu/drm/i915/intel_panel.c | 19 ++++++++++++
4 files changed, 58 insertions(+), 51 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 4c42f39..31b0774 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -1622,37 +1622,14 @@ intel_dp_detect(struct drm_connector *connector, bool force)
static int intel_dp_get_modes(struct drm_connector *connector)
{
struct intel_dp *intel_dp = intel_attached_dp(connector);
- struct drm_device *dev = intel_dp->base.base.dev;
- int ret;

/* We should parse the EDID data and find out if it has an audio sink
*/

- ret = intel_ddc_get_modes(connector, &intel_dp->adapter);
- if (ret) {
- if (is_edp(intel_dp) && !intel_dp->panel.fixed_mode) {
- struct drm_display_mode *newmode;
- list_for_each_entry(newmode, &connector->probed_modes,
- head) {
- if (newmode->type & DRM_MODE_TYPE_PREFERRED) {
- intel_dp->panel.fixed_mode =
- drm_mode_duplicate(dev, newmode);
- break;
- }
- }
- }
+ if (intel_dp->panel.connector)
+ return intel_panel_get_modes(&intel_dp->panel);

- return ret;
- }
-
- /* if eDP has no EDID, try to use fixed panel mode from VBT */
- if (intel_dp->panel.fixed_mode != NULL) {
- struct drm_display_mode *mode;
- mode = drm_mode_duplicate(dev, intel_dp->panel.fixed_mode);
- drm_mode_probed_add(connector, mode);
- return 1;
- }
- return 0;
+ return intel_ddc_get_modes(connector, &intel_dp->adapter);
}

static bool
@@ -1967,9 +1944,30 @@ intel_dp_init(struct drm_device *dev, int output_reg)

if (is_edp(intel_dp)) {
struct drm_display_mode *fixed_mode = NULL;
+ struct drm_display_mode *scan;
+ struct edid *edid;
+
+ edid = drm_get_edid(connector, &intel_dp->adapter);
+ if (edid) {
+ if (drm_add_edid_modes(connector, edid)) {
+ drm_mode_connector_update_edid_property(connector,
+ edid);
+ } else {
+ kfree(edid);
+ edid = NULL;
+ }
+ }
+
+ /* Downclock? */
+ list_for_each_entry(scan, &connector->probed_modes, head) {
+ if (scan->type & DRM_MODE_TYPE_PREFERRED) {
+ fixed_mode = drm_mode_duplicate(dev, scan);
+ break;
+ }
+ }

/* initialize panel mode from VBT if available for eDP */
- if (dev_priv->lfp_lvds_vbt_mode) {
+ if (fixed_mode == NULL && dev_priv->lfp_lvds_vbt_mode) {
fixed_mode =
drm_mode_duplicate(dev,
dev_priv->lfp_lvds_vbt_mode);
@@ -1979,7 +1977,7 @@ intel_dp_init(struct drm_device *dev, int output_reg)

intel_panel_init(&intel_dp->panel,
intel_connector,
- fixed_mode);
+ edid, fixed_mode);
}

intel_dp_add_properties(intel_dp, connector);
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 09bfc6b0..b4e9e54 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -259,13 +259,16 @@ extern bool intel_encoder_is_pch_edp(struct drm_encoder *encoder);
/* intel_panel.c */
struct intel_panel {
struct intel_connector *connector;
+ struct edid *edid;
struct drm_display_mode *fixed_mode;
struct notifier_block lid_notifier;
};
extern int intel_panel_init(struct intel_panel *panel,
struct intel_connector *connector,
+ struct edid *edid,
struct drm_display_mode *fixed_mode);
extern void intel_panel_fini(struct intel_panel *panel);
+extern int intel_panel_get_modes(struct intel_panel *panel);

extern void intel_fixed_panel_mode(struct drm_display_mode *fixed_mode,
struct drm_display_mode *adjusted_mode);
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
index 68f03ea..98e75d1 100644
--- a/drivers/gpu/drm/i915/intel_lvds.c
+++ b/drivers/gpu/drm/i915/intel_lvds.c
@@ -43,8 +43,6 @@ struct intel_lvds_connector {
struct intel_connector base;
struct intel_panel panel;

- struct edid *edid;
-
int fitting_mode;
};

@@ -492,18 +490,7 @@ intel_lvds_connector_detect(struct drm_connector *connector, bool force)
static int intel_lvds_connector_get_modes(struct drm_connector *connector)
{
struct intel_lvds_connector *lvds_connector = to_lvds_connector(connector);
- struct drm_device *dev = connector->dev;
- struct drm_display_mode *mode;
-
- if (lvds_connector->edid)
- return drm_add_edid_modes(connector, lvds_connector->edid);
-
- mode = drm_mode_duplicate(dev, lvds_connector->panel.fixed_mode);
- if (mode == NULL)
- return 0;
-
- drm_mode_probed_add(connector, mode);
- return 1;
+ return intel_panel_get_modes(&lvds_connector->panel);
}

/**
@@ -787,6 +774,7 @@ bool intel_lvds_init(struct drm_device *dev)
struct drm_display_mode *scan; /* *modes, *bios_mode; */
struct drm_display_mode *fixed_mode = NULL;
struct drm_crtc *crtc;
+ struct edid *edid;
u32 lvds;
int pipe;
u8 pin;
@@ -884,18 +872,17 @@ bool intel_lvds_init(struct drm_device *dev)
* Attempt to get the fixed panel mode from DDC. Assume that the
* preferred mode is the right one.
*/
- lvds_connector->edid = drm_get_edid(connector,
- &dev_priv->gmbus[pin].adapter);
- if (lvds_connector->edid) {
- if (drm_add_edid_modes(connector, lvds_connector->edid)) {
+ edid = drm_get_edid(connector, &dev_priv->gmbus[pin].adapter);
+ if (edid) {
+ if (drm_add_edid_modes(connector, edid)) {
drm_mode_connector_update_edid_property(connector,
- lvds_connector->edid);
+ edid);
} else {
- kfree(lvds_connector->edid);
- lvds_connector->edid = NULL;
+ kfree(edid);
+ edid = NULL;
}
}
- if (!lvds_connector->edid) {
+ if (!edid) {
/* Didn't get an EDID, so
* Set wide sync ranges so we get all modes
* handed to valid_mode for checking
@@ -991,7 +978,7 @@ out:

intel_panel_init(&lvds_connector->panel,
&lvds_connector->base,
- fixed_mode);
+ edid, fixed_mode);
drm_sysfs_connector_add(connector);
return true;

diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c
index b7329be..b49aad7 100644
--- a/drivers/gpu/drm/i915/intel_panel.c
+++ b/drivers/gpu/drm/i915/intel_panel.c
@@ -185,9 +185,11 @@ static int intel_panel_lid_notify(struct notifier_block *nb, unsigned long val,

int intel_panel_init(struct intel_panel *panel,
struct intel_connector *connector,
+ struct edid *edid,
struct drm_display_mode *fixed_mode)
{
panel->connector = connector;
+ panel->edid = edid;
panel->fixed_mode = fixed_mode;

panel->lid_notifier.notifier_call = intel_panel_lid_notify;
@@ -209,6 +211,23 @@ void intel_panel_fini(struct intel_panel *panel)
panel->fixed_mode);
}

+int intel_panel_get_modes(struct intel_panel *panel)
+{
+ struct drm_connector *connector = &panel->connector->base;
+ struct drm_device *dev = connector->dev;
+ struct drm_display_mode *mode;
+
+ if (panel->edid)
+ return drm_add_edid_modes(connector, panel->edid);
+
+ mode = drm_mode_duplicate(dev, panel->fixed_mode);
+ if (mode == NULL)
+ return 0;
+
+ drm_mode_probed_add(connector, mode);
+ return 1;
+}
+
/* Panel backlight controls */

static int is_backlight_combination_mode(struct drm_device *dev)
--
1.7.4.1