Commit 88631706 authored by Ma Ling's avatar Ma Ling Committed by Eric Anholt

drm/i915: Fetch SDVO LVDS mode lines from VBT, then reserve them

Signed-off-by: default avatarMa Ling <ling.ma@intel.com>
Signed-off-by: default avatarEric Anholt <eric@anholt.net>
parent 14b60391
...@@ -180,7 +180,8 @@ typedef struct drm_i915_private { ...@@ -180,7 +180,8 @@ typedef struct drm_i915_private {
int backlight_duty_cycle; /* restore backlight to this value */ int backlight_duty_cycle; /* restore backlight to this value */
bool panel_wants_dither; bool panel_wants_dither;
struct drm_display_mode *panel_fixed_mode; struct drm_display_mode *panel_fixed_mode;
struct drm_display_mode *vbt_mode; /* if any */ struct drm_display_mode *lfp_lvds_vbt_mode; /* if any */
struct drm_display_mode *sdvo_lvds_vbt_mode; /* if any */
/* Feature bits from the VBIOS */ /* Feature bits from the VBIOS */
unsigned int int_tv_support:1; unsigned int int_tv_support:1;
......
...@@ -57,9 +57,43 @@ find_section(struct bdb_header *bdb, int section_id) ...@@ -57,9 +57,43 @@ find_section(struct bdb_header *bdb, int section_id)
return NULL; return NULL;
} }
/* Try to find panel data */
static void 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_lfp_panel_data(struct drm_i915_private *dev_priv,
struct bdb_header *bdb)
{ {
struct bdb_lvds_options *lvds_options; struct bdb_lvds_options *lvds_options;
struct bdb_lvds_lfp_data *lvds_lfp_data; struct bdb_lvds_lfp_data *lvds_lfp_data;
...@@ -91,38 +125,45 @@ parse_panel_data(struct drm_i915_private *dev_priv, struct bdb_header *bdb) ...@@ -91,38 +125,45 @@ parse_panel_data(struct drm_i915_private *dev_priv, struct bdb_header *bdb)
panel_fixed_mode = drm_calloc(1, sizeof(*panel_fixed_mode), panel_fixed_mode = drm_calloc(1, sizeof(*panel_fixed_mode),
DRM_MEM_DRIVER); DRM_MEM_DRIVER);
panel_fixed_mode->hdisplay = (dvo_timing->hactive_hi << 8) | fill_detail_timing_data(panel_fixed_mode, dvo_timing);
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) | dev_priv->lfp_lvds_vbt_mode = panel_fixed_mode;
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 */ DRM_DEBUG("Found panel mode in BIOS VBT tables:\n");
if (panel_fixed_mode->hsync_end > panel_fixed_mode->htotal) drm_mode_debug_printmodeline(panel_fixed_mode);
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); return;
}
/* Try to find sdvo panel data */
static void
parse_sdvo_panel_data(struct drm_i915_private *dev_priv,
struct bdb_header *bdb)
{
struct bdb_sdvo_lvds_options *sdvo_lvds_options;
struct lvds_dvo_timing *dvo_timing;
struct drm_display_mode *panel_fixed_mode;
dev_priv->vbt_mode = panel_fixed_mode; dev_priv->sdvo_lvds_vbt_mode = NULL;
DRM_DEBUG("Found panel mode in BIOS VBT tables:\n"); sdvo_lvds_options = find_section(bdb, BDB_SDVO_LVDS_OPTIONS);
drm_mode_debug_printmodeline(panel_fixed_mode); if (!sdvo_lvds_options)
return;
dvo_timing = find_section(bdb, BDB_SDVO_PANEL_DTDS);
if (!dvo_timing)
return;
panel_fixed_mode = drm_calloc(1, sizeof(*panel_fixed_mode),
DRM_MEM_DRIVER);
if (!panel_fixed_mode)
return;
fill_detail_timing_data(panel_fixed_mode,
dvo_timing + sdvo_lvds_options->panel_type);
dev_priv->sdvo_lvds_vbt_mode = panel_fixed_mode;
return; return;
} }
...@@ -199,7 +240,8 @@ intel_init_bios(struct drm_device *dev) ...@@ -199,7 +240,8 @@ intel_init_bios(struct drm_device *dev)
/* Grab useful general definitions */ /* Grab useful general definitions */
parse_general_features(dev_priv, bdb); parse_general_features(dev_priv, bdb);
parse_panel_data(dev_priv, bdb); parse_lfp_panel_data(dev_priv, bdb);
parse_sdvo_panel_data(dev_priv, bdb);
pci_unmap_rom(pdev, bios); pci_unmap_rom(pdev, bios);
......
...@@ -279,6 +279,23 @@ struct vch_bdb_22 { ...@@ -279,6 +279,23 @@ struct vch_bdb_22 {
struct vch_panel_data panels[16]; struct vch_panel_data panels[16];
} __attribute__((packed)); } __attribute__((packed));
struct bdb_sdvo_lvds_options {
u8 panel_backlight;
u8 h40_set_panel_type;
u8 panel_type;
u8 ssc_clk_freq;
u16 als_low_trip;
u16 als_high_trip;
u8 sclalarcoeff_tab_row_num;
u8 sclalarcoeff_tab_row_size;
u8 coefficient[8];
u8 panel_misc_bits_1;
u8 panel_misc_bits_2;
u8 panel_misc_bits_3;
u8 panel_misc_bits_4;
} __attribute__((packed));
bool intel_init_bios(struct drm_device *dev); bool intel_init_bios(struct drm_device *dev);
/* /*
......
...@@ -511,10 +511,10 @@ void intel_lvds_init(struct drm_device *dev) ...@@ -511,10 +511,10 @@ void intel_lvds_init(struct drm_device *dev)
} }
/* Failed to get EDID, what about VBT? */ /* Failed to get EDID, what about VBT? */
if (dev_priv->vbt_mode) { if (dev_priv->lfp_lvds_vbt_mode) {
mutex_lock(&dev->mode_config.mutex); mutex_lock(&dev->mode_config.mutex);
dev_priv->panel_fixed_mode = dev_priv->panel_fixed_mode =
drm_mode_duplicate(dev, dev_priv->vbt_mode); drm_mode_duplicate(dev, dev_priv->lfp_lvds_vbt_mode);
mutex_unlock(&dev->mode_config.mutex); mutex_unlock(&dev->mode_config.mutex);
if (dev_priv->panel_fixed_mode) { if (dev_priv->panel_fixed_mode) {
dev_priv->panel_fixed_mode->type |= dev_priv->panel_fixed_mode->type |=
......
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