[Intel-gfx] [PATCH 1/2] drm/i915: Fetch mode lines from VBT, then reserve them
Ma Ling
ling.ma at intel.com
Fri May 8 12:38:16 CEST 2009
Intends to fetch mode lines in VBT
Signed-off-by: Ma Ling <ling.ma at intel.com>
---
drivers/gpu/drm/i915/i915_drv.h | 1 +
drivers/gpu/drm/i915/intel_bios.c | 113 +++++++++++++++++++++++++++----------
2 files changed, 84 insertions(+), 30 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 2506592..ef156e3 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -181,6 +181,7 @@ typedef struct drm_i915_private {
bool panel_wants_dither;
struct drm_display_mode *panel_fixed_mode;
struct drm_display_mode *vbt_mode; /* if any */
+ struct drm_display_mode *sdvo_lvds_vbt_mode; /* if any */
/* Feature bits from the VBIOS */
unsigned int int_tv_support:1;
diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c
index fc28e2b..2be2627 100644
--- a/drivers/gpu/drm/i915/intel_bios.c
+++ b/drivers/gpu/drm/i915/intel_bios.c
@@ -57,9 +57,43 @@ find_section(struct bdb_header *bdb, int section_id)
return NULL;
}
-/* Try to find panel data */
static void
-parse_panel_data(struct drm_i915_private *dev_priv, struct bdb_header *bdb)
+fill_detail_timing_data(struct drm_display_mode *panel_fixed_mode,
+ struct lvds_dvo_timing *dvo_timing)
+{
+ panel_fixed_mode->hdisplay = (dvo_timing->hactive_hi << 8) |
+ dvo_timing->hactive_lo;
+ panel_fixed_mode->hsync_start = panel_fixed_mode->hdisplay +
+ ((dvo_timing->hsync_off_hi << 8) | dvo_timing->hsync_off_lo);
+ panel_fixed_mode->hsync_end = panel_fixed_mode->hsync_start +
+ dvo_timing->hsync_pulse_width;
+ panel_fixed_mode->htotal = panel_fixed_mode->hdisplay +
+ ((dvo_timing->hblank_hi << 8) | dvo_timing->hblank_lo);
+
+ panel_fixed_mode->vdisplay = (dvo_timing->vactive_hi << 8) |
+ dvo_timing->vactive_lo;
+ panel_fixed_mode->vsync_start = panel_fixed_mode->vdisplay +
+ dvo_timing->vsync_off;
+ panel_fixed_mode->vsync_end = panel_fixed_mode->vsync_start +
+ dvo_timing->vsync_pulse_width;
+ panel_fixed_mode->vtotal = panel_fixed_mode->vdisplay +
+ ((dvo_timing->vblank_hi << 8) | dvo_timing->vblank_lo);
+ panel_fixed_mode->clock = dvo_timing->clock * 10;
+ panel_fixed_mode->type = DRM_MODE_TYPE_PREFERRED;
+
+ /* Some VBTs have bogus h/vtotal values */
+ if (panel_fixed_mode->hsync_end > panel_fixed_mode->htotal)
+ panel_fixed_mode->htotal = panel_fixed_mode->hsync_end + 1;
+ if (panel_fixed_mode->vsync_end > panel_fixed_mode->vtotal)
+ panel_fixed_mode->vtotal = panel_fixed_mode->vsync_end + 1;
+
+ drm_mode_set_name(panel_fixed_mode);
+}
+
+/* Try to find integrated panel data */
+static void
+parse_integrated_panel_data(struct drm_i915_private *dev_priv,
+ struct bdb_header *bdb)
{
struct bdb_lvds_options *lvds_options;
struct bdb_lvds_lfp_data *lvds_lfp_data;
@@ -91,33 +125,7 @@ parse_panel_data(struct drm_i915_private *dev_priv, struct bdb_header *bdb)
panel_fixed_mode = drm_calloc(1, sizeof(*panel_fixed_mode),
DRM_MEM_DRIVER);
- panel_fixed_mode->hdisplay = (dvo_timing->hactive_hi << 8) |
- dvo_timing->hactive_lo;
- panel_fixed_mode->hsync_start = panel_fixed_mode->hdisplay +
- ((dvo_timing->hsync_off_hi << 8) | dvo_timing->hsync_off_lo);
- panel_fixed_mode->hsync_end = panel_fixed_mode->hsync_start +
- dvo_timing->hsync_pulse_width;
- panel_fixed_mode->htotal = panel_fixed_mode->hdisplay +
- ((dvo_timing->hblank_hi << 8) | dvo_timing->hblank_lo);
-
- panel_fixed_mode->vdisplay = (dvo_timing->vactive_hi << 8) |
- dvo_timing->vactive_lo;
- panel_fixed_mode->vsync_start = panel_fixed_mode->vdisplay +
- dvo_timing->vsync_off;
- panel_fixed_mode->vsync_end = panel_fixed_mode->vsync_start +
- dvo_timing->vsync_pulse_width;
- panel_fixed_mode->vtotal = panel_fixed_mode->vdisplay +
- ((dvo_timing->vblank_hi << 8) | dvo_timing->vblank_lo);
- panel_fixed_mode->clock = dvo_timing->clock * 10;
- panel_fixed_mode->type = DRM_MODE_TYPE_PREFERRED;
-
- /* Some VBTs have bogus h/vtotal values */
- if (panel_fixed_mode->hsync_end > panel_fixed_mode->htotal)
- panel_fixed_mode->htotal = panel_fixed_mode->hsync_end + 1;
- if (panel_fixed_mode->vsync_end > panel_fixed_mode->vtotal)
- panel_fixed_mode->vtotal = panel_fixed_mode->vsync_end + 1;
-
- drm_mode_set_name(panel_fixed_mode);
+ fill_detail_timing_data(panel_fixed_mode, dvo_timing);
dev_priv->vbt_mode = panel_fixed_mode;
@@ -127,6 +135,50 @@ parse_panel_data(struct drm_i915_private *dev_priv, struct bdb_header *bdb)
return;
}
+/* Try to find sdvo panel data */
+static void
+parse_sdvo_panel_data(struct drm_i915_private *dev_priv,
+ struct bdb_header *bdb)
+{
+ struct lvds_dvo_timing *dvo_timing, *dvo_timing_end;
+ struct drm_display_mode *panel_fixed_mode;
+ char *parse;
+ uint16_t dvo_size, dvo_num;
+
+ dev_priv->sdvo_lvds_vbt_mode = NULL;
+
+ dvo_timing = find_section(bdb, BDB_SDVO_PANEL_DTDS);
+ if (dvo_timing == NULL)
+ return;
+
+ parse = ((char *)dvo_timing) - 2;
+
+ dvo_size = parse[0] | (parse[1] << 8);
+ dvo_num = dvo_size / sizeof(struct lvds_dvo_timing);
+ if (dvo_size == 0 || dvo_num == 0)
+ return;
+
+ dvo_timing_end = dvo_timing + dvo_num;
+
+ for (; dvo_timing < dvo_timing_end; dvo_timing = dvo_timing + 1) {
+ panel_fixed_mode = drm_calloc(1, sizeof(*panel_fixed_mode),
+ DRM_MEM_DRIVER);
+ if (panel_fixed_mode == NULL)
+ break;
+
+ fill_detail_timing_data(panel_fixed_mode, dvo_timing);
+
+ if (dev_priv->sdvo_lvds_vbt_mode == NULL) {
+ dev_priv->sdvo_lvds_vbt_mode = panel_fixed_mode;
+ INIT_LIST_HEAD(&dev_priv->sdvo_lvds_vbt_mode->head);
+ } else
+ list_add(&panel_fixed_mode->head,
+ &dev_priv->sdvo_lvds_vbt_mode->head);
+ }
+
+ return;
+}
+
static void
parse_general_features(struct drm_i915_private *dev_priv,
struct bdb_header *bdb)
@@ -199,7 +251,8 @@ intel_init_bios(struct drm_device *dev)
/* Grab useful general definitions */
parse_general_features(dev_priv, bdb);
- parse_panel_data(dev_priv, bdb);
+ parse_integrated_panel_data(dev_priv, bdb);
+ parse_sdvo_panel_data(dev_priv, bdb);
pci_unmap_rom(pdev, bios);
--
1.5.4.4
More information about the Intel-gfx
mailing list