diff options
Diffstat (limited to 'drivers/gpu/drm/i915/intel_bios.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_bios.c | 234 |
1 files changed, 163 insertions, 71 deletions
diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index 96f75d7f6633..b0b1200ed650 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 | ||
@@ -230,8 +230,6 @@ parse_sdvo_panel_data(struct drm_i915_private *dev_priv, | |||
230 | struct lvds_dvo_timing *dvo_timing; | 230 | struct lvds_dvo_timing *dvo_timing; |
231 | struct drm_display_mode *panel_fixed_mode; | 231 | struct drm_display_mode *panel_fixed_mode; |
232 | 232 | ||
233 | dev_priv->sdvo_lvds_vbt_mode = NULL; | ||
234 | |||
235 | sdvo_lvds_options = find_section(bdb, BDB_SDVO_LVDS_OPTIONS); | 233 | sdvo_lvds_options = find_section(bdb, BDB_SDVO_LVDS_OPTIONS); |
236 | if (!sdvo_lvds_options) | 234 | if (!sdvo_lvds_options) |
237 | return; | 235 | return; |
@@ -260,10 +258,6 @@ parse_general_features(struct drm_i915_private *dev_priv, | |||
260 | struct drm_device *dev = dev_priv->dev; | 258 | struct drm_device *dev = dev_priv->dev; |
261 | struct bdb_general_features *general; | 259 | struct bdb_general_features *general; |
262 | 260 | ||
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); | 261 | general = find_section(bdb, BDB_GENERAL_FEATURES); |
268 | if (general) { | 262 | if (general) { |
269 | dev_priv->int_tv_support = general->int_tv_support; | 263 | dev_priv->int_tv_support = general->int_tv_support; |
@@ -271,10 +265,10 @@ parse_general_features(struct drm_i915_private *dev_priv, | |||
271 | dev_priv->lvds_use_ssc = general->enable_ssc; | 265 | dev_priv->lvds_use_ssc = general->enable_ssc; |
272 | 266 | ||
273 | if (dev_priv->lvds_use_ssc) { | 267 | if (dev_priv->lvds_use_ssc) { |
274 | if (IS_I85X(dev_priv->dev)) | 268 | if (IS_I85X(dev)) |
275 | dev_priv->lvds_ssc_freq = | 269 | dev_priv->lvds_ssc_freq = |
276 | general->ssc_freq ? 66 : 48; | 270 | general->ssc_freq ? 66 : 48; |
277 | else if (IS_IRONLAKE(dev_priv->dev) || IS_GEN6(dev)) | 271 | else if (IS_GEN5(dev) || IS_GEN6(dev)) |
278 | dev_priv->lvds_ssc_freq = | 272 | dev_priv->lvds_ssc_freq = |
279 | general->ssc_freq ? 100 : 120; | 273 | general->ssc_freq ? 100 : 120; |
280 | else | 274 | else |
@@ -289,14 +283,6 @@ parse_general_definitions(struct drm_i915_private *dev_priv, | |||
289 | struct bdb_header *bdb) | 283 | struct bdb_header *bdb) |
290 | { | 284 | { |
291 | struct bdb_general_definitions *general; | 285 | 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 | 286 | ||
301 | general = find_section(bdb, BDB_GENERAL_DEFINITIONS); | 287 | general = find_section(bdb, BDB_GENERAL_DEFINITIONS); |
302 | if (general) { | 288 | if (general) { |
@@ -304,10 +290,8 @@ parse_general_definitions(struct drm_i915_private *dev_priv, | |||
304 | if (block_size >= sizeof(*general)) { | 290 | if (block_size >= sizeof(*general)) { |
305 | int bus_pin = general->crt_ddc_gmbus_pin; | 291 | int bus_pin = general->crt_ddc_gmbus_pin; |
306 | DRM_DEBUG_KMS("crt_ddc_bus_pin: %d\n", bus_pin); | 292 | DRM_DEBUG_KMS("crt_ddc_bus_pin: %d\n", bus_pin); |
307 | if ((bus_pin >= 1) && (bus_pin <= 6)) { | 293 | if (bus_pin >= 1 && bus_pin <= 6) |
308 | dev_priv->crt_ddc_bus = | 294 | dev_priv->crt_ddc_pin = bus_pin; |
309 | crt_bus_map_table[bus_pin-1]; | ||
310 | } | ||
311 | } else { | 295 | } else { |
312 | DRM_DEBUG_KMS("BDB_GD too small (%d). Invalid.\n", | 296 | DRM_DEBUG_KMS("BDB_GD too small (%d). Invalid.\n", |
313 | block_size); | 297 | block_size); |
@@ -317,7 +301,7 @@ parse_general_definitions(struct drm_i915_private *dev_priv, | |||
317 | 301 | ||
318 | static void | 302 | static void |
319 | parse_sdvo_device_mapping(struct drm_i915_private *dev_priv, | 303 | parse_sdvo_device_mapping(struct drm_i915_private *dev_priv, |
320 | struct bdb_header *bdb) | 304 | struct bdb_header *bdb) |
321 | { | 305 | { |
322 | struct sdvo_device_mapping *p_mapping; | 306 | struct sdvo_device_mapping *p_mapping; |
323 | struct bdb_general_definitions *p_defs; | 307 | struct bdb_general_definitions *p_defs; |
@@ -327,7 +311,7 @@ parse_sdvo_device_mapping(struct drm_i915_private *dev_priv, | |||
327 | 311 | ||
328 | p_defs = find_section(bdb, BDB_GENERAL_DEFINITIONS); | 312 | p_defs = find_section(bdb, BDB_GENERAL_DEFINITIONS); |
329 | if (!p_defs) { | 313 | if (!p_defs) { |
330 | DRM_DEBUG_KMS("No general definition block is found\n"); | 314 | DRM_DEBUG_KMS("No general definition block is found, unable to construct sdvo mapping.\n"); |
331 | return; | 315 | return; |
332 | } | 316 | } |
333 | /* judge whether the size of child device meets the requirements. | 317 | /* judge whether the size of child device meets the requirements. |
@@ -377,7 +361,16 @@ parse_sdvo_device_mapping(struct drm_i915_private *dev_priv, | |||
377 | p_mapping->slave_addr = p_child->slave_addr; | 361 | p_mapping->slave_addr = p_child->slave_addr; |
378 | p_mapping->dvo_wiring = p_child->dvo_wiring; | 362 | p_mapping->dvo_wiring = p_child->dvo_wiring; |
379 | p_mapping->ddc_pin = p_child->ddc_pin; | 363 | p_mapping->ddc_pin = p_child->ddc_pin; |
364 | p_mapping->i2c_pin = p_child->i2c_pin; | ||
365 | p_mapping->i2c_speed = p_child->i2c_speed; | ||
380 | p_mapping->initialized = 1; | 366 | p_mapping->initialized = 1; |
367 | DRM_DEBUG_KMS("SDVO device: dvo=%x, addr=%x, wiring=%d, ddc_pin=%d, i2c_pin=%d, i2c_speed=%d\n", | ||
368 | p_mapping->dvo_port, | ||
369 | p_mapping->slave_addr, | ||
370 | p_mapping->dvo_wiring, | ||
371 | p_mapping->ddc_pin, | ||
372 | p_mapping->i2c_pin, | ||
373 | p_mapping->i2c_speed); | ||
381 | } else { | 374 | } else { |
382 | DRM_DEBUG_KMS("Maybe one SDVO port is shared by " | 375 | DRM_DEBUG_KMS("Maybe one SDVO port is shared by " |
383 | "two SDVO device.\n"); | 376 | "two SDVO device.\n"); |
@@ -409,14 +402,11 @@ parse_driver_features(struct drm_i915_private *dev_priv, | |||
409 | if (!driver) | 402 | if (!driver) |
410 | return; | 403 | return; |
411 | 404 | ||
412 | if (driver && SUPPORTS_EDP(dev) && | 405 | if (SUPPORTS_EDP(dev) && |
413 | driver->lvds_config == BDB_DRIVER_FEATURE_EDP) { | 406 | driver->lvds_config == BDB_DRIVER_FEATURE_EDP) |
414 | dev_priv->edp_support = 1; | 407 | dev_priv->edp.support = 1; |
415 | } else { | ||
416 | dev_priv->edp_support = 0; | ||
417 | } | ||
418 | 408 | ||
419 | if (driver && driver->dual_frequency) | 409 | if (driver->dual_frequency) |
420 | dev_priv->render_reclock_avail = true; | 410 | dev_priv->render_reclock_avail = true; |
421 | } | 411 | } |
422 | 412 | ||
@@ -424,27 +414,78 @@ static void | |||
424 | parse_edp(struct drm_i915_private *dev_priv, struct bdb_header *bdb) | 414 | parse_edp(struct drm_i915_private *dev_priv, struct bdb_header *bdb) |
425 | { | 415 | { |
426 | struct bdb_edp *edp; | 416 | struct bdb_edp *edp; |
417 | struct edp_power_seq *edp_pps; | ||
418 | struct edp_link_params *edp_link_params; | ||
427 | 419 | ||
428 | edp = find_section(bdb, BDB_EDP); | 420 | edp = find_section(bdb, BDB_EDP); |
429 | if (!edp) { | 421 | if (!edp) { |
430 | if (SUPPORTS_EDP(dev_priv->dev) && dev_priv->edp_support) { | 422 | if (SUPPORTS_EDP(dev_priv->dev) && dev_priv->edp.support) { |
431 | DRM_DEBUG_KMS("No eDP BDB found but eDP panel " | 423 | DRM_DEBUG_KMS("No eDP BDB found but eDP panel " |
432 | "supported, assume 18bpp panel color " | 424 | "supported, assume %dbpp panel color " |
433 | "depth.\n"); | 425 | "depth.\n", |
434 | dev_priv->edp_bpp = 18; | 426 | dev_priv->edp.bpp); |
435 | } | 427 | } |
436 | return; | 428 | return; |
437 | } | 429 | } |
438 | 430 | ||
439 | switch ((edp->color_depth >> (panel_type * 2)) & 3) { | 431 | switch ((edp->color_depth >> (panel_type * 2)) & 3) { |
440 | case EDP_18BPP: | 432 | case EDP_18BPP: |
441 | dev_priv->edp_bpp = 18; | 433 | dev_priv->edp.bpp = 18; |
442 | break; | 434 | break; |
443 | case EDP_24BPP: | 435 | case EDP_24BPP: |
444 | dev_priv->edp_bpp = 24; | 436 | dev_priv->edp.bpp = 24; |
445 | break; | 437 | break; |
446 | case EDP_30BPP: | 438 | case EDP_30BPP: |
447 | dev_priv->edp_bpp = 30; | 439 | dev_priv->edp.bpp = 30; |
440 | break; | ||
441 | } | ||
442 | |||
443 | /* Get the eDP sequencing and link info */ | ||
444 | edp_pps = &edp->power_seqs[panel_type]; | ||
445 | edp_link_params = &edp->link_params[panel_type]; | ||
446 | |||
447 | dev_priv->edp.pps = *edp_pps; | ||
448 | |||
449 | dev_priv->edp.rate = edp_link_params->rate ? DP_LINK_BW_2_7 : | ||
450 | DP_LINK_BW_1_62; | ||
451 | switch (edp_link_params->lanes) { | ||
452 | case 0: | ||
453 | dev_priv->edp.lanes = 1; | ||
454 | break; | ||
455 | case 1: | ||
456 | dev_priv->edp.lanes = 2; | ||
457 | break; | ||
458 | case 3: | ||
459 | default: | ||
460 | dev_priv->edp.lanes = 4; | ||
461 | break; | ||
462 | } | ||
463 | switch (edp_link_params->preemphasis) { | ||
464 | case 0: | ||
465 | dev_priv->edp.preemphasis = DP_TRAIN_PRE_EMPHASIS_0; | ||
466 | break; | ||
467 | case 1: | ||
468 | dev_priv->edp.preemphasis = DP_TRAIN_PRE_EMPHASIS_3_5; | ||
469 | break; | ||
470 | case 2: | ||
471 | dev_priv->edp.preemphasis = DP_TRAIN_PRE_EMPHASIS_6; | ||
472 | break; | ||
473 | case 3: | ||
474 | dev_priv->edp.preemphasis = DP_TRAIN_PRE_EMPHASIS_9_5; | ||
475 | break; | ||
476 | } | ||
477 | switch (edp_link_params->vswing) { | ||
478 | case 0: | ||
479 | dev_priv->edp.vswing = DP_TRAIN_VOLTAGE_SWING_400; | ||
480 | break; | ||
481 | case 1: | ||
482 | dev_priv->edp.vswing = DP_TRAIN_VOLTAGE_SWING_600; | ||
483 | break; | ||
484 | case 2: | ||
485 | dev_priv->edp.vswing = DP_TRAIN_VOLTAGE_SWING_800; | ||
486 | break; | ||
487 | case 3: | ||
488 | dev_priv->edp.vswing = DP_TRAIN_VOLTAGE_SWING_1200; | ||
448 | break; | 489 | break; |
449 | } | 490 | } |
450 | } | 491 | } |
@@ -460,7 +501,7 @@ parse_device_mapping(struct drm_i915_private *dev_priv, | |||
460 | 501 | ||
461 | p_defs = find_section(bdb, BDB_GENERAL_DEFINITIONS); | 502 | p_defs = find_section(bdb, BDB_GENERAL_DEFINITIONS); |
462 | if (!p_defs) { | 503 | if (!p_defs) { |
463 | DRM_DEBUG_KMS("No general definition block is found\n"); | 504 | DRM_DEBUG_KMS("No general definition block is found, no devices defined.\n"); |
464 | return; | 505 | return; |
465 | } | 506 | } |
466 | /* judge whether the size of child device meets the requirements. | 507 | /* judge whether the size of child device meets the requirements. |
@@ -513,50 +554,83 @@ parse_device_mapping(struct drm_i915_private *dev_priv, | |||
513 | } | 554 | } |
514 | return; | 555 | return; |
515 | } | 556 | } |
557 | |||
558 | static void | ||
559 | init_vbt_defaults(struct drm_i915_private *dev_priv) | ||
560 | { | ||
561 | dev_priv->crt_ddc_pin = GMBUS_PORT_VGADDC; | ||
562 | |||
563 | /* LFP panel data */ | ||
564 | dev_priv->lvds_dither = 1; | ||
565 | dev_priv->lvds_vbt = 0; | ||
566 | |||
567 | /* SDVO panel data */ | ||
568 | dev_priv->sdvo_lvds_vbt_mode = NULL; | ||
569 | |||
570 | /* general features */ | ||
571 | dev_priv->int_tv_support = 1; | ||
572 | dev_priv->int_crt_support = 1; | ||
573 | dev_priv->lvds_use_ssc = 0; | ||
574 | |||
575 | /* eDP data */ | ||
576 | dev_priv->edp.bpp = 18; | ||
577 | } | ||
578 | |||
516 | /** | 579 | /** |
517 | * intel_init_bios - initialize VBIOS settings & find VBT | 580 | * intel_parse_bios - find VBT and initialize settings from the BIOS |
518 | * @dev: DRM device | 581 | * @dev: DRM device |
519 | * | 582 | * |
520 | * Loads the Video BIOS and checks that the VBT exists. Sets scratch registers | 583 | * Loads the Video BIOS and checks that the VBT exists. Sets scratch registers |
521 | * to appropriate values. | 584 | * to appropriate values. |
522 | * | 585 | * |
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. | 586 | * Returns 0 on success, nonzero on failure. |
529 | */ | 587 | */ |
530 | bool | 588 | bool |
531 | intel_init_bios(struct drm_device *dev) | 589 | intel_parse_bios(struct drm_device *dev) |
532 | { | 590 | { |
533 | struct drm_i915_private *dev_priv = dev->dev_private; | 591 | struct drm_i915_private *dev_priv = dev->dev_private; |
534 | struct pci_dev *pdev = dev->pdev; | 592 | struct pci_dev *pdev = dev->pdev; |
535 | struct vbt_header *vbt = NULL; | 593 | struct bdb_header *bdb = NULL; |
536 | struct bdb_header *bdb; | 594 | u8 __iomem *bios = NULL; |
537 | u8 __iomem *bios; | 595 | |
538 | size_t size; | 596 | init_vbt_defaults(dev_priv); |
539 | int i; | 597 | |
540 | 598 | /* XXX Should this validation be moved to intel_opregion.c? */ | |
541 | bios = pci_map_rom(pdev, &size); | 599 | if (dev_priv->opregion.vbt) { |
542 | if (!bios) | 600 | struct vbt_header *vbt = dev_priv->opregion.vbt; |
543 | return -1; | 601 | if (memcmp(vbt->signature, "$VBT", 4) == 0) { |
544 | 602 | DRM_DEBUG_DRIVER("Using VBT from OpRegion: %20s\n", | |
545 | /* Scour memory looking for the VBT signature */ | 603 | vbt->signature); |
546 | for (i = 0; i + 4 < size; i++) { | 604 | bdb = (struct bdb_header *)((char *)vbt + vbt->bdb_offset); |
547 | if (!memcmp(bios + i, "$VBT", 4)) { | 605 | } else |
548 | vbt = (struct vbt_header *)(bios + i); | 606 | dev_priv->opregion.vbt = NULL; |
549 | break; | ||
550 | } | ||
551 | } | 607 | } |
552 | 608 | ||
553 | if (!vbt) { | 609 | if (bdb == NULL) { |
554 | DRM_ERROR("VBT signature missing\n"); | 610 | struct vbt_header *vbt = NULL; |
555 | pci_unmap_rom(pdev, bios); | 611 | size_t size; |
556 | return -1; | 612 | int i; |
557 | } | ||
558 | 613 | ||
559 | bdb = (struct bdb_header *)(bios + i + vbt->bdb_offset); | 614 | bios = pci_map_rom(pdev, &size); |
615 | if (!bios) | ||
616 | return -1; | ||
617 | |||
618 | /* Scour memory looking for the VBT signature */ | ||
619 | for (i = 0; i + 4 < size; i++) { | ||
620 | if (!memcmp(bios + i, "$VBT", 4)) { | ||
621 | vbt = (struct vbt_header *)(bios + i); | ||
622 | break; | ||
623 | } | ||
624 | } | ||
625 | |||
626 | if (!vbt) { | ||
627 | DRM_ERROR("VBT signature missing\n"); | ||
628 | pci_unmap_rom(pdev, bios); | ||
629 | return -1; | ||
630 | } | ||
631 | |||
632 | bdb = (struct bdb_header *)(bios + i + vbt->bdb_offset); | ||
633 | } | ||
560 | 634 | ||
561 | /* Grab useful general definitions */ | 635 | /* Grab useful general definitions */ |
562 | parse_general_features(dev_priv, bdb); | 636 | parse_general_features(dev_priv, bdb); |
@@ -568,7 +642,25 @@ intel_init_bios(struct drm_device *dev) | |||
568 | parse_driver_features(dev_priv, bdb); | 642 | parse_driver_features(dev_priv, bdb); |
569 | parse_edp(dev_priv, bdb); | 643 | parse_edp(dev_priv, bdb); |
570 | 644 | ||
571 | pci_unmap_rom(pdev, bios); | 645 | if (bios) |
646 | pci_unmap_rom(pdev, bios); | ||
572 | 647 | ||
573 | return 0; | 648 | return 0; |
574 | } | 649 | } |
650 | |||
651 | /* Ensure that vital registers have been initialised, even if the BIOS | ||
652 | * is absent or just failing to do its job. | ||
653 | */ | ||
654 | void intel_setup_bios(struct drm_device *dev) | ||
655 | { | ||
656 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
657 | |||
658 | /* Set the Panel Power On/Off timings if uninitialized. */ | ||
659 | if ((I915_READ(PP_ON_DELAYS) == 0) && (I915_READ(PP_OFF_DELAYS) == 0)) { | ||
660 | /* Set T2 to 40ms and T5 to 200ms */ | ||
661 | I915_WRITE(PP_ON_DELAYS, 0x019007d0); | ||
662 | |||
663 | /* Set T3 to 35ms and Tx to 200ms */ | ||
664 | I915_WRITE(PP_OFF_DELAYS, 0x015e07d0); | ||
665 | } | ||
666 | } | ||