diff options
| -rw-r--r-- | drivers/gpu/drm/i915/i915_drv.h | 3 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/intel_bios.c | 102 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/intel_bios.h | 17 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/intel_lvds.c | 4 |
4 files changed, 93 insertions, 33 deletions
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 9b149fe824c3..c431fa54bbb5 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h | |||
| @@ -180,7 +180,8 @@ typedef struct drm_i915_private { | |||
| 180 | int backlight_duty_cycle; /* restore backlight to this value */ | 180 | int backlight_duty_cycle; /* restore backlight to this value */ |
| 181 | bool panel_wants_dither; | 181 | bool panel_wants_dither; |
| 182 | struct drm_display_mode *panel_fixed_mode; | 182 | struct drm_display_mode *panel_fixed_mode; |
| 183 | struct drm_display_mode *vbt_mode; /* if any */ | 183 | struct drm_display_mode *lfp_lvds_vbt_mode; /* if any */ |
| 184 | struct drm_display_mode *sdvo_lvds_vbt_mode; /* if any */ | ||
| 184 | 185 | ||
| 185 | /* Feature bits from the VBIOS */ | 186 | /* Feature bits from the VBIOS */ |
| 186 | unsigned int int_tv_support:1; | 187 | 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 fc28e2bbd542..9d78cff33b24 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) | |||
| 57 | return NULL; | 57 | return NULL; |
| 58 | } | 58 | } |
| 59 | 59 | ||
| 60 | /* Try to find panel data */ | ||
| 61 | static void | 60 | static void |
| 62 | parse_panel_data(struct drm_i915_private *dev_priv, struct bdb_header *bdb) | 61 | fill_detail_timing_data(struct drm_display_mode *panel_fixed_mode, |
| 62 | struct lvds_dvo_timing *dvo_timing) | ||
| 63 | { | ||
| 64 | panel_fixed_mode->hdisplay = (dvo_timing->hactive_hi << 8) | | ||
| 65 | dvo_timing->hactive_lo; | ||
| 66 | panel_fixed_mode->hsync_start = panel_fixed_mode->hdisplay + | ||
| 67 | ((dvo_timing->hsync_off_hi << 8) | dvo_timing->hsync_off_lo); | ||
| 68 | panel_fixed_mode->hsync_end = panel_fixed_mode->hsync_start + | ||
| 69 | dvo_timing->hsync_pulse_width; | ||
| 70 | panel_fixed_mode->htotal = panel_fixed_mode->hdisplay + | ||
| 71 | ((dvo_timing->hblank_hi << 8) | dvo_timing->hblank_lo); | ||
| 72 | |||
| 73 | panel_fixed_mode->vdisplay = (dvo_timing->vactive_hi << 8) | | ||
| 74 | dvo_timing->vactive_lo; | ||
| 75 | panel_fixed_mode->vsync_start = panel_fixed_mode->vdisplay + | ||
| 76 | dvo_timing->vsync_off; | ||
| 77 | panel_fixed_mode->vsync_end = panel_fixed_mode->vsync_start + | ||
| 78 | dvo_timing->vsync_pulse_width; | ||
| 79 | panel_fixed_mode->vtotal = panel_fixed_mode->vdisplay + | ||
| 80 | ((dvo_timing->vblank_hi << 8) | dvo_timing->vblank_lo); | ||
| 81 | panel_fixed_mode->clock = dvo_timing->clock * 10; | ||
| 82 | panel_fixed_mode->type = DRM_MODE_TYPE_PREFERRED; | ||
| 83 | |||
| 84 | /* Some VBTs have bogus h/vtotal values */ | ||
| 85 | if (panel_fixed_mode->hsync_end > panel_fixed_mode->htotal) | ||
| 86 | panel_fixed_mode->htotal = panel_fixed_mode->hsync_end + 1; | ||
| 87 | if (panel_fixed_mode->vsync_end > panel_fixed_mode->vtotal) | ||
| 88 | panel_fixed_mode->vtotal = panel_fixed_mode->vsync_end + 1; | ||
| 89 | |||
| 90 | drm_mode_set_name(panel_fixed_mode); | ||
| 91 | } | ||
| 92 | |||
| 93 | /* Try to find integrated panel data */ | ||
| 94 | static void | ||
| 95 | parse_lfp_panel_data(struct drm_i915_private *dev_priv, | ||
| 96 | struct bdb_header *bdb) | ||
| 63 | { | 97 | { |
| 64 | struct bdb_lvds_options *lvds_options; | 98 | struct bdb_lvds_options *lvds_options; |
| 65 | struct bdb_lvds_lfp_data *lvds_lfp_data; | 99 | 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 | panel_fixed_mode = drm_calloc(1, sizeof(*panel_fixed_mode), | 125 | panel_fixed_mode = drm_calloc(1, sizeof(*panel_fixed_mode), |
| 92 | DRM_MEM_DRIVER); | 126 | DRM_MEM_DRIVER); |
| 93 | 127 | ||
| 94 | panel_fixed_mode->hdisplay = (dvo_timing->hactive_hi << 8) | | 128 | fill_detail_timing_data(panel_fixed_mode, dvo_timing); |
| 95 | dvo_timing->hactive_lo; | ||
| 96 | panel_fixed_mode->hsync_start = panel_fixed_mode->hdisplay + | ||
| 97 | ((dvo_timing->hsync_off_hi << 8) | dvo_timing->hsync_off_lo); | ||
| 98 | panel_fixed_mode->hsync_end = panel_fixed_mode->hsync_start + | ||
| 99 | dvo_timing->hsync_pulse_width; | ||
| 100 | panel_fixed_mode->htotal = panel_fixed_mode->hdisplay + | ||
| 101 | ((dvo_timing->hblank_hi << 8) | dvo_timing->hblank_lo); | ||
| 102 | 129 | ||
| 103 | panel_fixed_mode->vdisplay = (dvo_timing->vactive_hi << 8) | | 130 | dev_priv->lfp_lvds_vbt_mode = panel_fixed_mode; |
| 104 | dvo_timing->vactive_lo; | ||
| 105 | panel_fixed_mode->vsync_start = panel_fixed_mode->vdisplay + | ||
| 106 | dvo_timing->vsync_off; | ||
| 107 | panel_fixed_mode->vsync_end = panel_fixed_mode->vsync_start + | ||
| 108 | dvo_timing->vsync_pulse_width; | ||
| 109 | panel_fixed_mode->vtotal = panel_fixed_mode->vdisplay + | ||
| 110 | ((dvo_timing->vblank_hi << 8) | dvo_timing->vblank_lo); | ||
| 111 | panel_fixed_mode->clock = dvo_timing->clock * 10; | ||
| 112 | panel_fixed_mode->type = DRM_MODE_TYPE_PREFERRED; | ||
| 113 | 131 | ||
| 114 | /* Some VBTs have bogus h/vtotal values */ | 132 | DRM_DEBUG("Found panel mode in BIOS VBT tables:\n"); |
| 115 | if (panel_fixed_mode->hsync_end > panel_fixed_mode->htotal) | 133 | drm_mode_debug_printmodeline(panel_fixed_mode); |
| 116 | panel_fixed_mode->htotal = panel_fixed_mode->hsync_end + 1; | ||
| 117 | if (panel_fixed_mode->vsync_end > panel_fixed_mode->vtotal) | ||
| 118 | panel_fixed_mode->vtotal = panel_fixed_mode->vsync_end + 1; | ||
| 119 | 134 | ||
| 120 | drm_mode_set_name(panel_fixed_mode); | 135 | return; |
| 136 | } | ||
| 137 | |||
| 138 | /* Try to find sdvo panel data */ | ||
| 139 | static void | ||
| 140 | parse_sdvo_panel_data(struct drm_i915_private *dev_priv, | ||
| 141 | struct bdb_header *bdb) | ||
| 142 | { | ||
| 143 | struct bdb_sdvo_lvds_options *sdvo_lvds_options; | ||
| 144 | struct lvds_dvo_timing *dvo_timing; | ||
| 145 | struct drm_display_mode *panel_fixed_mode; | ||
| 121 | 146 | ||
| 122 | dev_priv->vbt_mode = panel_fixed_mode; | 147 | dev_priv->sdvo_lvds_vbt_mode = NULL; |
| 123 | 148 | ||
| 124 | DRM_DEBUG("Found panel mode in BIOS VBT tables:\n"); | 149 | sdvo_lvds_options = find_section(bdb, BDB_SDVO_LVDS_OPTIONS); |
| 125 | drm_mode_debug_printmodeline(panel_fixed_mode); | 150 | if (!sdvo_lvds_options) |
| 151 | return; | ||
| 152 | |||
| 153 | dvo_timing = find_section(bdb, BDB_SDVO_PANEL_DTDS); | ||
| 154 | if (!dvo_timing) | ||
| 155 | return; | ||
| 156 | |||
| 157 | panel_fixed_mode = drm_calloc(1, sizeof(*panel_fixed_mode), | ||
| 158 | DRM_MEM_DRIVER); | ||
| 159 | |||
| 160 | if (!panel_fixed_mode) | ||
| 161 | return; | ||
| 162 | |||
| 163 | fill_detail_timing_data(panel_fixed_mode, | ||
| 164 | dvo_timing + sdvo_lvds_options->panel_type); | ||
| 165 | |||
| 166 | dev_priv->sdvo_lvds_vbt_mode = panel_fixed_mode; | ||
| 126 | 167 | ||
| 127 | return; | 168 | return; |
| 128 | } | 169 | } |
| @@ -199,7 +240,8 @@ intel_init_bios(struct drm_device *dev) | |||
| 199 | 240 | ||
| 200 | /* Grab useful general definitions */ | 241 | /* Grab useful general definitions */ |
| 201 | parse_general_features(dev_priv, bdb); | 242 | parse_general_features(dev_priv, bdb); |
| 202 | parse_panel_data(dev_priv, bdb); | 243 | parse_lfp_panel_data(dev_priv, bdb); |
| 244 | parse_sdvo_panel_data(dev_priv, bdb); | ||
| 203 | 245 | ||
| 204 | pci_unmap_rom(pdev, bios); | 246 | pci_unmap_rom(pdev, bios); |
| 205 | 247 | ||
diff --git a/drivers/gpu/drm/i915/intel_bios.h b/drivers/gpu/drm/i915/intel_bios.h index de621aad85b5..8ca2cde15804 100644 --- a/drivers/gpu/drm/i915/intel_bios.h +++ b/drivers/gpu/drm/i915/intel_bios.h | |||
| @@ -279,6 +279,23 @@ struct vch_bdb_22 { | |||
| 279 | struct vch_panel_data panels[16]; | 279 | struct vch_panel_data panels[16]; |
| 280 | } __attribute__((packed)); | 280 | } __attribute__((packed)); |
| 281 | 281 | ||
| 282 | struct bdb_sdvo_lvds_options { | ||
| 283 | u8 panel_backlight; | ||
| 284 | u8 h40_set_panel_type; | ||
| 285 | u8 panel_type; | ||
| 286 | u8 ssc_clk_freq; | ||
| 287 | u16 als_low_trip; | ||
| 288 | u16 als_high_trip; | ||
| 289 | u8 sclalarcoeff_tab_row_num; | ||
| 290 | u8 sclalarcoeff_tab_row_size; | ||
| 291 | u8 coefficient[8]; | ||
| 292 | u8 panel_misc_bits_1; | ||
| 293 | u8 panel_misc_bits_2; | ||
| 294 | u8 panel_misc_bits_3; | ||
| 295 | u8 panel_misc_bits_4; | ||
| 296 | } __attribute__((packed)); | ||
| 297 | |||
| 298 | |||
| 282 | bool intel_init_bios(struct drm_device *dev); | 299 | bool intel_init_bios(struct drm_device *dev); |
| 283 | 300 | ||
| 284 | /* | 301 | /* |
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index 439a86514993..53731f0ffcb5 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c | |||
| @@ -511,10 +511,10 @@ void intel_lvds_init(struct drm_device *dev) | |||
| 511 | } | 511 | } |
| 512 | 512 | ||
| 513 | /* Failed to get EDID, what about VBT? */ | 513 | /* Failed to get EDID, what about VBT? */ |
| 514 | if (dev_priv->vbt_mode) { | 514 | if (dev_priv->lfp_lvds_vbt_mode) { |
| 515 | mutex_lock(&dev->mode_config.mutex); | 515 | mutex_lock(&dev->mode_config.mutex); |
| 516 | dev_priv->panel_fixed_mode = | 516 | dev_priv->panel_fixed_mode = |
| 517 | drm_mode_duplicate(dev, dev_priv->vbt_mode); | 517 | drm_mode_duplicate(dev, dev_priv->lfp_lvds_vbt_mode); |
| 518 | mutex_unlock(&dev->mode_config.mutex); | 518 | mutex_unlock(&dev->mode_config.mutex); |
| 519 | if (dev_priv->panel_fixed_mode) { | 519 | if (dev_priv->panel_fixed_mode) { |
| 520 | dev_priv->panel_fixed_mode->type |= | 520 | dev_priv->panel_fixed_mode->type |= |
