From c10e408a00bb74c39f4f9b817f2b948851513377 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mathias=20Fr=C3=B6hlich?= Date: Thu, 1 Mar 2012 06:44:35 +0100 Subject: i915: Add option to bypass vbt table. This change enables the use of displays where the vbt table just contains inappropriate values, but either the vesa defaults or the video=... modes do something sensible with the attached display. The problem happens with an embedded board that contains vbt bios tables that do not match the attached display. Using this change and the appropriate kernel boot command line they are able to use an otherwise completely unusable secondary display on that embedded board. Reviewed-by: Paul Menzel Signed-off-by: Mathias Froehlich Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_bios.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers/gpu/drm/i915/intel_bios.c') diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index 8168d8f..0ae76d6 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c @@ -255,6 +255,11 @@ parse_sdvo_panel_data(struct drm_i915_private *dev_priv, int index; index = i915_vbt_sdvo_panel_type; + if (index == -2) { + DRM_DEBUG_KMS("Ignore SDVO panel mode from BIOS VBT tables.\n"); + return; + } + if (index == -1) { struct bdb_sdvo_lvds_options *sdvo_lvds_options; -- cgit v1.1 From b03543857fd75876b96e10d4320b775e95041bb7 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 20 Mar 2012 13:07:05 +0100 Subject: drm/i915: Check VBIOS value for determining LVDS dual channel mode, too Currently i915 driver checks [PCH_]LVDS register bits to decide whether to set up the dual-link or the single-link mode. This relies implicitly on that BIOS initializes the register properly at boot. However, BIOS doesn't initialize it always. When the machine is booted with the closed lid, BIOS skips the LVDS reg initialization. This ends up in blank output on a machine with a dual-link LVDS when you open the lid after the boot. This patch adds a workaround for that problem by checking the initial LVDS register value in VBT. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=37742 Tested-By: Paulo Zanoni Reviewed-by: Rodrigo Vivi Reviewed-by: Adam Jackson Signed-off-by: Takashi Iwai Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_bios.c | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) (limited to 'drivers/gpu/drm/i915/intel_bios.c') diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index 0ae76d6..e4317da 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c @@ -173,6 +173,28 @@ get_lvds_dvo_timing(const struct bdb_lvds_lfp_data *lvds_lfp_data, return (struct lvds_dvo_timing *)(entry + dvo_timing_offset); } +/* get lvds_fp_timing entry + * this function may return NULL if the corresponding entry is invalid + */ +static const struct lvds_fp_timing * +get_lvds_fp_timing(const struct bdb_header *bdb, + const struct bdb_lvds_lfp_data *data, + const struct bdb_lvds_lfp_data_ptrs *ptrs, + int index) +{ + size_t data_ofs = (const u8 *)data - (const u8 *)bdb; + u16 data_size = ((const u16 *)data)[-1]; /* stored in header */ + size_t ofs; + + if (index >= ARRAY_SIZE(ptrs->ptr)) + return NULL; + ofs = ptrs->ptr[index].fp_timing_offset; + if (ofs < data_ofs || + ofs + sizeof(struct lvds_fp_timing) > data_ofs + data_size) + return NULL; + return (const struct lvds_fp_timing *)((const u8 *)bdb + ofs); +} + /* Try to find integrated panel data */ static void parse_lfp_panel_data(struct drm_i915_private *dev_priv, @@ -182,6 +204,7 @@ parse_lfp_panel_data(struct drm_i915_private *dev_priv, const struct bdb_lvds_lfp_data *lvds_lfp_data; const struct bdb_lvds_lfp_data_ptrs *lvds_lfp_data_ptrs; const struct lvds_dvo_timing *panel_dvo_timing; + const struct lvds_fp_timing *fp_timing; struct drm_display_mode *panel_fixed_mode; int i, downclock; @@ -243,6 +266,19 @@ parse_lfp_panel_data(struct drm_i915_private *dev_priv, "Normal Clock %dKHz, downclock %dKHz\n", panel_fixed_mode->clock, 10*downclock); } + + fp_timing = get_lvds_fp_timing(bdb, lvds_lfp_data, + lvds_lfp_data_ptrs, + lvds_options->panel_type); + if (fp_timing) { + /* check the resolution, just to be sure */ + if (fp_timing->x_res == panel_fixed_mode->hdisplay && + fp_timing->y_res == panel_fixed_mode->vdisplay) { + dev_priv->bios_lvds_val = fp_timing->lvds_reg_val; + DRM_DEBUG_KMS("VBT initial LVDS value %x\n", + dev_priv->bios_lvds_val); + } + } } /* Try to find sdvo panel data */ -- cgit v1.1 From 3bd7d90938f1fe77de5991dc4b727843c4980b2a Mon Sep 17 00:00:00 2001 From: Daniel Kurtz Date: Wed, 28 Mar 2012 02:36:14 +0800 Subject: drm/i915/intel_i2c: refactor using intel_gmbus_get_adapter Instead of letting other modules directly access the ->gmbus array, introduce intel_gmbus_get_adapter() for looking up an i2c_adapter for a given gmbus port identifier. This will enable later refactoring of the gmbus port list. Note: Before requesting an adapter for a given gmbus port number, the driver must first check its validity using i2c_intel_gmbus_is_port_valid(). If this check fails, a call to intel_gmbus_get_adapter() will WARN_ON and return NULL. This is relevant for parts of the driver that read a port from VBIOS, which might be improperly initialized and contain an invalid port. In these cases, the driver must fall back to using a safer default port. Signed-off-by: Daniel Kurtz Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_bios.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_bios.c') diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index e4317da..871aa27 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c @@ -372,11 +372,11 @@ parse_general_definitions(struct drm_i915_private *dev_priv, if (block_size >= sizeof(*general)) { int bus_pin = general->crt_ddc_gmbus_pin; DRM_DEBUG_KMS("crt_ddc_bus_pin: %d\n", bus_pin); - if (bus_pin >= 1 && bus_pin <= 6) + if (intel_gmbus_is_port_valid(bus_pin)) dev_priv->crt_ddc_pin = bus_pin; } else { DRM_DEBUG_KMS("BDB_GD too small (%d). Invalid.\n", - block_size); + block_size); } } } -- cgit v1.1