diff options
Diffstat (limited to 'drivers/gpu/drm/i915/intel_bios.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_bios.c | 290 |
1 files changed, 199 insertions, 91 deletions
diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index 96f75d7f6633..927442a11925 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c | |||
@@ -24,6 +24,7 @@ | |||
24 | * Eric Anholt <eric@anholt.net> | 24 | * Eric Anholt <eric@anholt.net> |
25 | * | 25 | * |
26 | */ | 26 | */ |
27 | #include <drm/drm_dp_helper.h> | ||
27 | #include "drmP.h" | 28 | #include "drmP.h" |
28 | #include "drm.h" | 29 | #include "drm.h" |
29 | #include "i915_drm.h" | 30 | #include "i915_drm.h" |
@@ -129,10 +130,6 @@ parse_lfp_panel_data(struct drm_i915_private *dev_priv, | |||
129 | int i, temp_downclock; | 130 | int i, temp_downclock; |
130 | struct drm_display_mode *temp_mode; | 131 | struct drm_display_mode *temp_mode; |
131 | 132 | ||
132 | /* Defaults if we can't find VBT info */ | ||
133 | dev_priv->lvds_dither = 0; | ||
134 | dev_priv->lvds_vbt = 0; | ||
135 | |||
136 | lvds_options = find_section(bdb, BDB_LVDS_OPTIONS); | 133 | lvds_options = find_section(bdb, BDB_LVDS_OPTIONS); |
137 | if (!lvds_options) | 134 | if (!lvds_options) |
138 | return; | 135 | return; |
@@ -140,6 +137,7 @@ parse_lfp_panel_data(struct drm_i915_private *dev_priv, | |||
140 | dev_priv->lvds_dither = lvds_options->pixel_dither; | 137 | dev_priv->lvds_dither = lvds_options->pixel_dither; |
141 | if (lvds_options->panel_type == 0xff) | 138 | if (lvds_options->panel_type == 0xff) |
142 | return; | 139 | return; |
140 | |||
143 | panel_type = lvds_options->panel_type; | 141 | panel_type = lvds_options->panel_type; |
144 | 142 | ||
145 | lvds_lfp_data = find_section(bdb, BDB_LVDS_LFP_DATA); | 143 | lvds_lfp_data = find_section(bdb, BDB_LVDS_LFP_DATA); |
@@ -169,6 +167,8 @@ parse_lfp_panel_data(struct drm_i915_private *dev_priv, | |||
169 | ((unsigned char *)entry + dvo_timing_offset); | 167 | ((unsigned char *)entry + dvo_timing_offset); |
170 | 168 | ||
171 | panel_fixed_mode = kzalloc(sizeof(*panel_fixed_mode), GFP_KERNEL); | 169 | panel_fixed_mode = kzalloc(sizeof(*panel_fixed_mode), GFP_KERNEL); |
170 | if (!panel_fixed_mode) | ||
171 | return; | ||
172 | 172 | ||
173 | fill_detail_timing_data(panel_fixed_mode, dvo_timing); | 173 | fill_detail_timing_data(panel_fixed_mode, dvo_timing); |
174 | 174 | ||
@@ -214,9 +214,9 @@ parse_lfp_panel_data(struct drm_i915_private *dev_priv, | |||
214 | i915_lvds_downclock) { | 214 | i915_lvds_downclock) { |
215 | dev_priv->lvds_downclock_avail = 1; | 215 | dev_priv->lvds_downclock_avail = 1; |
216 | dev_priv->lvds_downclock = temp_downclock; | 216 | dev_priv->lvds_downclock = temp_downclock; |
217 | DRM_DEBUG_KMS("LVDS downclock is found in VBT. ", | 217 | DRM_DEBUG_KMS("LVDS downclock is found in VBT. " |
218 | "Normal Clock %dKHz, downclock %dKHz\n", | 218 | "Normal Clock %dKHz, downclock %dKHz\n", |
219 | temp_downclock, panel_fixed_mode->clock); | 219 | temp_downclock, panel_fixed_mode->clock); |
220 | } | 220 | } |
221 | return; | 221 | return; |
222 | } | 222 | } |
@@ -226,31 +226,49 @@ static void | |||
226 | parse_sdvo_panel_data(struct drm_i915_private *dev_priv, | 226 | parse_sdvo_panel_data(struct drm_i915_private *dev_priv, |
227 | struct bdb_header *bdb) | 227 | struct bdb_header *bdb) |
228 | { | 228 | { |
229 | struct bdb_sdvo_lvds_options *sdvo_lvds_options; | ||
230 | struct lvds_dvo_timing *dvo_timing; | 229 | struct lvds_dvo_timing *dvo_timing; |
231 | struct drm_display_mode *panel_fixed_mode; | 230 | struct drm_display_mode *panel_fixed_mode; |
231 | int index; | ||
232 | 232 | ||
233 | dev_priv->sdvo_lvds_vbt_mode = NULL; | 233 | index = i915_vbt_sdvo_panel_type; |
234 | if (index == -1) { | ||
235 | struct bdb_sdvo_lvds_options *sdvo_lvds_options; | ||
234 | 236 | ||
235 | sdvo_lvds_options = find_section(bdb, BDB_SDVO_LVDS_OPTIONS); | 237 | sdvo_lvds_options = find_section(bdb, BDB_SDVO_LVDS_OPTIONS); |
236 | if (!sdvo_lvds_options) | 238 | if (!sdvo_lvds_options) |
237 | return; | 239 | return; |
240 | |||
241 | index = sdvo_lvds_options->panel_type; | ||
242 | } | ||
238 | 243 | ||
239 | dvo_timing = find_section(bdb, BDB_SDVO_PANEL_DTDS); | 244 | dvo_timing = find_section(bdb, BDB_SDVO_PANEL_DTDS); |
240 | if (!dvo_timing) | 245 | if (!dvo_timing) |
241 | return; | 246 | return; |
242 | 247 | ||
243 | panel_fixed_mode = kzalloc(sizeof(*panel_fixed_mode), GFP_KERNEL); | 248 | panel_fixed_mode = kzalloc(sizeof(*panel_fixed_mode), GFP_KERNEL); |
244 | |||
245 | if (!panel_fixed_mode) | 249 | if (!panel_fixed_mode) |
246 | return; | 250 | return; |
247 | 251 | ||
248 | fill_detail_timing_data(panel_fixed_mode, | 252 | fill_detail_timing_data(panel_fixed_mode, dvo_timing + index); |
249 | dvo_timing + sdvo_lvds_options->panel_type); | ||
250 | 253 | ||
251 | dev_priv->sdvo_lvds_vbt_mode = panel_fixed_mode; | 254 | dev_priv->sdvo_lvds_vbt_mode = panel_fixed_mode; |
252 | 255 | ||
253 | return; | 256 | DRM_DEBUG_KMS("Found SDVO panel mode in BIOS VBT tables:\n"); |
257 | drm_mode_debug_printmodeline(panel_fixed_mode); | ||
258 | } | ||
259 | |||
260 | static int intel_bios_ssc_frequency(struct drm_device *dev, | ||
261 | bool alternate) | ||
262 | { | ||
263 | switch (INTEL_INFO(dev)->gen) { | ||
264 | case 2: | ||
265 | return alternate ? 66 : 48; | ||
266 | case 3: | ||
267 | case 4: | ||
268 | return alternate ? 100 : 96; | ||
269 | default: | ||
270 | return alternate ? 100 : 120; | ||
271 | } | ||
254 | } | 272 | } |
255 | 273 | ||
256 | static void | 274 | static void |
@@ -260,27 +278,13 @@ parse_general_features(struct drm_i915_private *dev_priv, | |||
260 | struct drm_device *dev = dev_priv->dev; | 278 | struct drm_device *dev = dev_priv->dev; |
261 | struct bdb_general_features *general; | 279 | struct bdb_general_features *general; |
262 | 280 | ||
263 | /* Set sensible defaults in case we can't find the general block */ | ||
264 | dev_priv->int_tv_support = 1; | ||
265 | dev_priv->int_crt_support = 1; | ||
266 | |||
267 | general = find_section(bdb, BDB_GENERAL_FEATURES); | 281 | general = find_section(bdb, BDB_GENERAL_FEATURES); |
268 | if (general) { | 282 | if (general) { |
269 | dev_priv->int_tv_support = general->int_tv_support; | 283 | dev_priv->int_tv_support = general->int_tv_support; |
270 | dev_priv->int_crt_support = general->int_crt_support; | 284 | dev_priv->int_crt_support = general->int_crt_support; |
271 | dev_priv->lvds_use_ssc = general->enable_ssc; | 285 | dev_priv->lvds_use_ssc = general->enable_ssc; |
272 | 286 | dev_priv->lvds_ssc_freq = | |
273 | if (dev_priv->lvds_use_ssc) { | 287 | intel_bios_ssc_frequency(dev, general->ssc_freq); |
274 | if (IS_I85X(dev_priv->dev)) | ||
275 | dev_priv->lvds_ssc_freq = | ||
276 | general->ssc_freq ? 66 : 48; | ||
277 | else if (IS_IRONLAKE(dev_priv->dev) || IS_GEN6(dev)) | ||
278 | dev_priv->lvds_ssc_freq = | ||
279 | general->ssc_freq ? 100 : 120; | ||
280 | else | ||
281 | dev_priv->lvds_ssc_freq = | ||
282 | general->ssc_freq ? 100 : 96; | ||
283 | } | ||
284 | } | 288 | } |
285 | } | 289 | } |
286 | 290 | ||
@@ -289,14 +293,6 @@ parse_general_definitions(struct drm_i915_private *dev_priv, | |||
289 | struct bdb_header *bdb) | 293 | struct bdb_header *bdb) |
290 | { | 294 | { |
291 | struct bdb_general_definitions *general; | 295 | struct bdb_general_definitions *general; |
292 | const int crt_bus_map_table[] = { | ||
293 | GPIOB, | ||
294 | GPIOA, | ||
295 | GPIOC, | ||
296 | GPIOD, | ||
297 | GPIOE, | ||
298 | GPIOF, | ||
299 | }; | ||
300 | 296 | ||
301 | general = find_section(bdb, BDB_GENERAL_DEFINITIONS); | 297 | general = find_section(bdb, BDB_GENERAL_DEFINITIONS); |
302 | if (general) { | 298 | if (general) { |
@@ -304,10 +300,8 @@ parse_general_definitions(struct drm_i915_private *dev_priv, | |||
304 | if (block_size >= sizeof(*general)) { | 300 | if (block_size >= sizeof(*general)) { |
305 | int bus_pin = general->crt_ddc_gmbus_pin; | 301 | int bus_pin = general->crt_ddc_gmbus_pin; |
306 | DRM_DEBUG_KMS("crt_ddc_bus_pin: %d\n", bus_pin); | 302 | DRM_DEBUG_KMS("crt_ddc_bus_pin: %d\n", bus_pin); |
307 | if ((bus_pin >= 1) && (bus_pin <= 6)) { | 303 | if (bus_pin >= 1 && bus_pin <= 6) |
308 | dev_priv->crt_ddc_bus = | 304 | dev_priv->crt_ddc_pin = bus_pin; |
309 | crt_bus_map_table[bus_pin-1]; | ||
310 | } | ||
311 | } else { | 305 | } else { |
312 | DRM_DEBUG_KMS("BDB_GD too small (%d). Invalid.\n", | 306 | DRM_DEBUG_KMS("BDB_GD too small (%d). Invalid.\n", |
313 | block_size); | 307 | block_size); |
@@ -317,7 +311,7 @@ parse_general_definitions(struct drm_i915_private *dev_priv, | |||
317 | 311 | ||
318 | static void | 312 | static void |
319 | parse_sdvo_device_mapping(struct drm_i915_private *dev_priv, | 313 | parse_sdvo_device_mapping(struct drm_i915_private *dev_priv, |
320 | struct bdb_header *bdb) | 314 | struct bdb_header *bdb) |
321 | { | 315 | { |
322 | struct sdvo_device_mapping *p_mapping; | 316 | struct sdvo_device_mapping *p_mapping; |
323 | struct bdb_general_definitions *p_defs; | 317 | struct bdb_general_definitions *p_defs; |
@@ -327,7 +321,7 @@ parse_sdvo_device_mapping(struct drm_i915_private *dev_priv, | |||
327 | 321 | ||
328 | p_defs = find_section(bdb, BDB_GENERAL_DEFINITIONS); | 322 | p_defs = find_section(bdb, BDB_GENERAL_DEFINITIONS); |
329 | if (!p_defs) { | 323 | if (!p_defs) { |
330 | DRM_DEBUG_KMS("No general definition block is found\n"); | 324 | DRM_DEBUG_KMS("No general definition block is found, unable to construct sdvo mapping.\n"); |
331 | return; | 325 | return; |
332 | } | 326 | } |
333 | /* judge whether the size of child device meets the requirements. | 327 | /* judge whether the size of child device meets the requirements. |
@@ -377,7 +371,16 @@ parse_sdvo_device_mapping(struct drm_i915_private *dev_priv, | |||
377 | p_mapping->slave_addr = p_child->slave_addr; | 371 | p_mapping->slave_addr = p_child->slave_addr; |
378 | p_mapping->dvo_wiring = p_child->dvo_wiring; | 372 | p_mapping->dvo_wiring = p_child->dvo_wiring; |
379 | p_mapping->ddc_pin = p_child->ddc_pin; | 373 | p_mapping->ddc_pin = p_child->ddc_pin; |
374 | p_mapping->i2c_pin = p_child->i2c_pin; | ||
375 | p_mapping->i2c_speed = p_child->i2c_speed; | ||
380 | p_mapping->initialized = 1; | 376 | p_mapping->initialized = 1; |
377 | DRM_DEBUG_KMS("SDVO device: dvo=%x, addr=%x, wiring=%d, ddc_pin=%d, i2c_pin=%d, i2c_speed=%d\n", | ||
378 | p_mapping->dvo_port, | ||
379 | p_mapping->slave_addr, | ||
380 | p_mapping->dvo_wiring, | ||
381 | p_mapping->ddc_pin, | ||
382 | p_mapping->i2c_pin, | ||
383 | p_mapping->i2c_speed); | ||
381 | } else { | 384 | } else { |
382 | DRM_DEBUG_KMS("Maybe one SDVO port is shared by " | 385 | DRM_DEBUG_KMS("Maybe one SDVO port is shared by " |
383 | "two SDVO device.\n"); | 386 | "two SDVO device.\n"); |
@@ -409,14 +412,11 @@ parse_driver_features(struct drm_i915_private *dev_priv, | |||
409 | if (!driver) | 412 | if (!driver) |
410 | return; | 413 | return; |
411 | 414 | ||
412 | if (driver && SUPPORTS_EDP(dev) && | 415 | if (SUPPORTS_EDP(dev) && |
413 | driver->lvds_config == BDB_DRIVER_FEATURE_EDP) { | 416 | driver->lvds_config == BDB_DRIVER_FEATURE_EDP) |
414 | dev_priv->edp_support = 1; | 417 | dev_priv->edp.support = 1; |
415 | } else { | ||
416 | dev_priv->edp_support = 0; | ||
417 | } | ||
418 | 418 | ||
419 | if (driver && driver->dual_frequency) | 419 | if (driver->dual_frequency) |
420 | dev_priv->render_reclock_avail = true; | 420 | dev_priv->render_reclock_avail = true; |
421 | } | 421 | } |
422 | 422 | ||
@@ -424,27 +424,78 @@ static void | |||
424 | parse_edp(struct drm_i915_private *dev_priv, struct bdb_header *bdb) | 424 | parse_edp(struct drm_i915_private *dev_priv, struct bdb_header *bdb) |
425 | { | 425 | { |
426 | struct bdb_edp *edp; | 426 | struct bdb_edp *edp; |
427 | struct edp_power_seq *edp_pps; | ||
428 | struct edp_link_params *edp_link_params; | ||
427 | 429 | ||
428 | edp = find_section(bdb, BDB_EDP); | 430 | edp = find_section(bdb, BDB_EDP); |
429 | if (!edp) { | 431 | if (!edp) { |
430 | if (SUPPORTS_EDP(dev_priv->dev) && dev_priv->edp_support) { | 432 | if (SUPPORTS_EDP(dev_priv->dev) && dev_priv->edp.support) { |
431 | DRM_DEBUG_KMS("No eDP BDB found but eDP panel " | 433 | DRM_DEBUG_KMS("No eDP BDB found but eDP panel " |
432 | "supported, assume 18bpp panel color " | 434 | "supported, assume %dbpp panel color " |
433 | "depth.\n"); | 435 | "depth.\n", |
434 | dev_priv->edp_bpp = 18; | 436 | dev_priv->edp.bpp); |
435 | } | 437 | } |
436 | return; | 438 | return; |
437 | } | 439 | } |
438 | 440 | ||
439 | switch ((edp->color_depth >> (panel_type * 2)) & 3) { | 441 | switch ((edp->color_depth >> (panel_type * 2)) & 3) { |
440 | case EDP_18BPP: | 442 | case EDP_18BPP: |
441 | dev_priv->edp_bpp = 18; | 443 | dev_priv->edp.bpp = 18; |
442 | break; | 444 | break; |
443 | case EDP_24BPP: | 445 | case EDP_24BPP: |
444 | dev_priv->edp_bpp = 24; | 446 | dev_priv->edp.bpp = 24; |
445 | break; | 447 | break; |
446 | case EDP_30BPP: | 448 | case EDP_30BPP: |
447 | dev_priv->edp_bpp = 30; | 449 | dev_priv->edp.bpp = 30; |
450 | break; | ||
451 | } | ||
452 | |||
453 | /* Get the eDP sequencing and link info */ | ||
454 | edp_pps = &edp->power_seqs[panel_type]; | ||
455 | edp_link_params = &edp->link_params[panel_type]; | ||
456 | |||
457 | dev_priv->edp.pps = *edp_pps; | ||
458 | |||
459 | dev_priv->edp.rate = edp_link_params->rate ? DP_LINK_BW_2_7 : | ||
460 | DP_LINK_BW_1_62; | ||
461 | switch (edp_link_params->lanes) { | ||
462 | case 0: | ||
463 | dev_priv->edp.lanes = 1; | ||
464 | break; | ||
465 | case 1: | ||
466 | dev_priv->edp.lanes = 2; | ||
467 | break; | ||
468 | case 3: | ||
469 | default: | ||
470 | dev_priv->edp.lanes = 4; | ||
471 | break; | ||
472 | } | ||
473 | switch (edp_link_params->preemphasis) { | ||
474 | case 0: | ||
475 | dev_priv->edp.preemphasis = DP_TRAIN_PRE_EMPHASIS_0; | ||
476 | break; | ||
477 | case 1: | ||
478 | dev_priv->edp.preemphasis = DP_TRAIN_PRE_EMPHASIS_3_5; | ||
479 | break; | ||
480 | case 2: | ||
481 | dev_priv->edp.preemphasis = DP_TRAIN_PRE_EMPHASIS_6; | ||
482 | break; | ||
483 | case 3: | ||
484 | dev_priv->edp.preemphasis = DP_TRAIN_PRE_EMPHASIS_9_5; | ||
485 | break; | ||
486 | } | ||
487 | switch (edp_link_params->vswing) { | ||
488 | case 0: | ||
489 | dev_priv->edp.vswing = DP_TRAIN_VOLTAGE_SWING_400; | ||
490 | break; | ||
491 | case 1: | ||
492 | dev_priv->edp.vswing = DP_TRAIN_VOLTAGE_SWING_600; | ||
493 | break; | ||
494 | case 2: | ||
495 | dev_priv->edp.vswing = DP_TRAIN_VOLTAGE_SWING_800; | ||
496 | break; | ||
497 | case 3: | ||
498 | dev_priv->edp.vswing = DP_TRAIN_VOLTAGE_SWING_1200; | ||
448 | break; | 499 | break; |
449 | } | 500 | } |
450 | } | 501 | } |
@@ -460,7 +511,7 @@ parse_device_mapping(struct drm_i915_private *dev_priv, | |||
460 | 511 | ||
461 | p_defs = find_section(bdb, BDB_GENERAL_DEFINITIONS); | 512 | p_defs = find_section(bdb, BDB_GENERAL_DEFINITIONS); |
462 | if (!p_defs) { | 513 | if (!p_defs) { |
463 | DRM_DEBUG_KMS("No general definition block is found\n"); | 514 | DRM_DEBUG_KMS("No general definition block is found, no devices defined.\n"); |
464 | return; | 515 | return; |
465 | } | 516 | } |
466 | /* judge whether the size of child device meets the requirements. | 517 | /* judge whether the size of child device meets the requirements. |
@@ -513,50 +564,89 @@ parse_device_mapping(struct drm_i915_private *dev_priv, | |||
513 | } | 564 | } |
514 | return; | 565 | return; |
515 | } | 566 | } |
567 | |||
568 | static void | ||
569 | init_vbt_defaults(struct drm_i915_private *dev_priv) | ||
570 | { | ||
571 | struct drm_device *dev = dev_priv->dev; | ||
572 | |||
573 | dev_priv->crt_ddc_pin = GMBUS_PORT_VGADDC; | ||
574 | |||
575 | /* LFP panel data */ | ||
576 | dev_priv->lvds_dither = 1; | ||
577 | dev_priv->lvds_vbt = 0; | ||
578 | |||
579 | /* SDVO panel data */ | ||
580 | dev_priv->sdvo_lvds_vbt_mode = NULL; | ||
581 | |||
582 | /* general features */ | ||
583 | dev_priv->int_tv_support = 1; | ||
584 | dev_priv->int_crt_support = 1; | ||
585 | |||
586 | /* Default to using SSC */ | ||
587 | dev_priv->lvds_use_ssc = 1; | ||
588 | dev_priv->lvds_ssc_freq = intel_bios_ssc_frequency(dev, 1); | ||
589 | DRM_DEBUG("Set default to SSC at %dMHz\n", dev_priv->lvds_ssc_freq); | ||
590 | |||
591 | /* eDP data */ | ||
592 | dev_priv->edp.bpp = 18; | ||
593 | } | ||
594 | |||
516 | /** | 595 | /** |
517 | * intel_init_bios - initialize VBIOS settings & find VBT | 596 | * intel_parse_bios - find VBT and initialize settings from the BIOS |
518 | * @dev: DRM device | 597 | * @dev: DRM device |
519 | * | 598 | * |
520 | * Loads the Video BIOS and checks that the VBT exists. Sets scratch registers | 599 | * Loads the Video BIOS and checks that the VBT exists. Sets scratch registers |
521 | * to appropriate values. | 600 | * to appropriate values. |
522 | * | 601 | * |
523 | * VBT existence is a sanity check that is relied on by other i830_bios.c code. | ||
524 | * Note that it would be better to use a BIOS call to get the VBT, as BIOSes may | ||
525 | * feed an updated VBT back through that, compared to what we'll fetch using | ||
526 | * this method of groping around in the BIOS data. | ||
527 | * | ||
528 | * Returns 0 on success, nonzero on failure. | 602 | * Returns 0 on success, nonzero on failure. |
529 | */ | 603 | */ |
530 | bool | 604 | bool |
531 | intel_init_bios(struct drm_device *dev) | 605 | intel_parse_bios(struct drm_device *dev) |
532 | { | 606 | { |
533 | struct drm_i915_private *dev_priv = dev->dev_private; | 607 | struct drm_i915_private *dev_priv = dev->dev_private; |
534 | struct pci_dev *pdev = dev->pdev; | 608 | struct pci_dev *pdev = dev->pdev; |
535 | struct vbt_header *vbt = NULL; | 609 | struct bdb_header *bdb = NULL; |
536 | struct bdb_header *bdb; | 610 | u8 __iomem *bios = NULL; |
537 | u8 __iomem *bios; | 611 | |
538 | size_t size; | 612 | init_vbt_defaults(dev_priv); |
539 | int i; | 613 | |
540 | 614 | /* XXX Should this validation be moved to intel_opregion.c? */ | |
541 | bios = pci_map_rom(pdev, &size); | 615 | if (dev_priv->opregion.vbt) { |
542 | if (!bios) | 616 | struct vbt_header *vbt = dev_priv->opregion.vbt; |
543 | return -1; | 617 | if (memcmp(vbt->signature, "$VBT", 4) == 0) { |
544 | 618 | DRM_DEBUG_DRIVER("Using VBT from OpRegion: %20s\n", | |
545 | /* Scour memory looking for the VBT signature */ | 619 | vbt->signature); |
546 | for (i = 0; i + 4 < size; i++) { | 620 | bdb = (struct bdb_header *)((char *)vbt + vbt->bdb_offset); |
547 | if (!memcmp(bios + i, "$VBT", 4)) { | 621 | } else |
548 | vbt = (struct vbt_header *)(bios + i); | 622 | dev_priv->opregion.vbt = NULL; |
549 | break; | ||
550 | } | ||
551 | } | 623 | } |
552 | 624 | ||
553 | if (!vbt) { | 625 | if (bdb == NULL) { |
554 | DRM_ERROR("VBT signature missing\n"); | 626 | struct vbt_header *vbt = NULL; |
555 | pci_unmap_rom(pdev, bios); | 627 | size_t size; |
556 | return -1; | 628 | int i; |
557 | } | 629 | |
630 | bios = pci_map_rom(pdev, &size); | ||
631 | if (!bios) | ||
632 | return -1; | ||
633 | |||
634 | /* Scour memory looking for the VBT signature */ | ||
635 | for (i = 0; i + 4 < size; i++) { | ||
636 | if (!memcmp(bios + i, "$VBT", 4)) { | ||
637 | vbt = (struct vbt_header *)(bios + i); | ||
638 | break; | ||
639 | } | ||
640 | } | ||
558 | 641 | ||
559 | bdb = (struct bdb_header *)(bios + i + vbt->bdb_offset); | 642 | if (!vbt) { |
643 | DRM_ERROR("VBT signature missing\n"); | ||
644 | pci_unmap_rom(pdev, bios); | ||
645 | return -1; | ||
646 | } | ||
647 | |||
648 | bdb = (struct bdb_header *)(bios + i + vbt->bdb_offset); | ||
649 | } | ||
560 | 650 | ||
561 | /* Grab useful general definitions */ | 651 | /* Grab useful general definitions */ |
562 | parse_general_features(dev_priv, bdb); | 652 | parse_general_features(dev_priv, bdb); |
@@ -568,7 +658,25 @@ intel_init_bios(struct drm_device *dev) | |||
568 | parse_driver_features(dev_priv, bdb); | 658 | parse_driver_features(dev_priv, bdb); |
569 | parse_edp(dev_priv, bdb); | 659 | parse_edp(dev_priv, bdb); |
570 | 660 | ||
571 | pci_unmap_rom(pdev, bios); | 661 | if (bios) |
662 | pci_unmap_rom(pdev, bios); | ||
572 | 663 | ||
573 | return 0; | 664 | return 0; |
574 | } | 665 | } |
666 | |||
667 | /* Ensure that vital registers have been initialised, even if the BIOS | ||
668 | * is absent or just failing to do its job. | ||
669 | */ | ||
670 | void intel_setup_bios(struct drm_device *dev) | ||
671 | { | ||
672 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
673 | |||
674 | /* Set the Panel Power On/Off timings if uninitialized. */ | ||
675 | if ((I915_READ(PP_ON_DELAYS) == 0) && (I915_READ(PP_OFF_DELAYS) == 0)) { | ||
676 | /* Set T2 to 40ms and T5 to 200ms */ | ||
677 | I915_WRITE(PP_ON_DELAYS, 0x019007d0); | ||
678 | |||
679 | /* Set T3 to 35ms and Tx to 200ms */ | ||
680 | I915_WRITE(PP_OFF_DELAYS, 0x015e07d0); | ||
681 | } | ||
682 | } | ||