diff options
Diffstat (limited to 'drivers/gpu/drm/i915/intel_bios.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_bios.c | 195 |
1 files changed, 173 insertions, 22 deletions
diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index 53f2bed8bc5f..6dd622d733b9 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c | |||
@@ -389,7 +389,7 @@ parse_sdvo_device_mapping(struct drm_i915_private *dev_priv, | |||
389 | { | 389 | { |
390 | struct sdvo_device_mapping *p_mapping; | 390 | struct sdvo_device_mapping *p_mapping; |
391 | struct bdb_general_definitions *p_defs; | 391 | struct bdb_general_definitions *p_defs; |
392 | struct child_device_config *p_child; | 392 | union child_device_config *p_child; |
393 | int i, child_device_num, count; | 393 | int i, child_device_num, count; |
394 | u16 block_size; | 394 | u16 block_size; |
395 | 395 | ||
@@ -416,36 +416,36 @@ parse_sdvo_device_mapping(struct drm_i915_private *dev_priv, | |||
416 | count = 0; | 416 | count = 0; |
417 | for (i = 0; i < child_device_num; i++) { | 417 | for (i = 0; i < child_device_num; i++) { |
418 | p_child = &(p_defs->devices[i]); | 418 | p_child = &(p_defs->devices[i]); |
419 | if (!p_child->device_type) { | 419 | if (!p_child->old.device_type) { |
420 | /* skip the device block if device type is invalid */ | 420 | /* skip the device block if device type is invalid */ |
421 | continue; | 421 | continue; |
422 | } | 422 | } |
423 | if (p_child->slave_addr != SLAVE_ADDR1 && | 423 | if (p_child->old.slave_addr != SLAVE_ADDR1 && |
424 | p_child->slave_addr != SLAVE_ADDR2) { | 424 | p_child->old.slave_addr != SLAVE_ADDR2) { |
425 | /* | 425 | /* |
426 | * If the slave address is neither 0x70 nor 0x72, | 426 | * If the slave address is neither 0x70 nor 0x72, |
427 | * it is not a SDVO device. Skip it. | 427 | * it is not a SDVO device. Skip it. |
428 | */ | 428 | */ |
429 | continue; | 429 | continue; |
430 | } | 430 | } |
431 | if (p_child->dvo_port != DEVICE_PORT_DVOB && | 431 | if (p_child->old.dvo_port != DEVICE_PORT_DVOB && |
432 | p_child->dvo_port != DEVICE_PORT_DVOC) { | 432 | p_child->old.dvo_port != DEVICE_PORT_DVOC) { |
433 | /* skip the incorrect SDVO port */ | 433 | /* skip the incorrect SDVO port */ |
434 | DRM_DEBUG_KMS("Incorrect SDVO port. Skip it\n"); | 434 | DRM_DEBUG_KMS("Incorrect SDVO port. Skip it\n"); |
435 | continue; | 435 | continue; |
436 | } | 436 | } |
437 | DRM_DEBUG_KMS("the SDVO device with slave addr %2x is found on" | 437 | DRM_DEBUG_KMS("the SDVO device with slave addr %2x is found on" |
438 | " %s port\n", | 438 | " %s port\n", |
439 | p_child->slave_addr, | 439 | p_child->old.slave_addr, |
440 | (p_child->dvo_port == DEVICE_PORT_DVOB) ? | 440 | (p_child->old.dvo_port == DEVICE_PORT_DVOB) ? |
441 | "SDVOB" : "SDVOC"); | 441 | "SDVOB" : "SDVOC"); |
442 | p_mapping = &(dev_priv->sdvo_mappings[p_child->dvo_port - 1]); | 442 | p_mapping = &(dev_priv->sdvo_mappings[p_child->old.dvo_port - 1]); |
443 | if (!p_mapping->initialized) { | 443 | if (!p_mapping->initialized) { |
444 | p_mapping->dvo_port = p_child->dvo_port; | 444 | p_mapping->dvo_port = p_child->old.dvo_port; |
445 | p_mapping->slave_addr = p_child->slave_addr; | 445 | p_mapping->slave_addr = p_child->old.slave_addr; |
446 | p_mapping->dvo_wiring = p_child->dvo_wiring; | 446 | p_mapping->dvo_wiring = p_child->old.dvo_wiring; |
447 | p_mapping->ddc_pin = p_child->ddc_pin; | 447 | p_mapping->ddc_pin = p_child->old.ddc_pin; |
448 | p_mapping->i2c_pin = p_child->i2c_pin; | 448 | p_mapping->i2c_pin = p_child->old.i2c_pin; |
449 | p_mapping->initialized = 1; | 449 | p_mapping->initialized = 1; |
450 | DRM_DEBUG_KMS("SDVO device: dvo=%x, addr=%x, wiring=%d, ddc_pin=%d, i2c_pin=%d\n", | 450 | DRM_DEBUG_KMS("SDVO device: dvo=%x, addr=%x, wiring=%d, ddc_pin=%d, i2c_pin=%d\n", |
451 | p_mapping->dvo_port, | 451 | p_mapping->dvo_port, |
@@ -457,7 +457,7 @@ parse_sdvo_device_mapping(struct drm_i915_private *dev_priv, | |||
457 | DRM_DEBUG_KMS("Maybe one SDVO port is shared by " | 457 | DRM_DEBUG_KMS("Maybe one SDVO port is shared by " |
458 | "two SDVO device.\n"); | 458 | "two SDVO device.\n"); |
459 | } | 459 | } |
460 | if (p_child->slave2_addr) { | 460 | if (p_child->old.slave2_addr) { |
461 | /* Maybe this is a SDVO device with multiple inputs */ | 461 | /* Maybe this is a SDVO device with multiple inputs */ |
462 | /* And the mapping info is not added */ | 462 | /* And the mapping info is not added */ |
463 | DRM_DEBUG_KMS("there exists the slave2_addr. Maybe this" | 463 | DRM_DEBUG_KMS("there exists the slave2_addr. Maybe this" |
@@ -477,15 +477,13 @@ static void | |||
477 | parse_driver_features(struct drm_i915_private *dev_priv, | 477 | parse_driver_features(struct drm_i915_private *dev_priv, |
478 | struct bdb_header *bdb) | 478 | struct bdb_header *bdb) |
479 | { | 479 | { |
480 | struct drm_device *dev = dev_priv->dev; | ||
481 | struct bdb_driver_features *driver; | 480 | struct bdb_driver_features *driver; |
482 | 481 | ||
483 | driver = find_section(bdb, BDB_DRIVER_FEATURES); | 482 | driver = find_section(bdb, BDB_DRIVER_FEATURES); |
484 | if (!driver) | 483 | if (!driver) |
485 | return; | 484 | return; |
486 | 485 | ||
487 | if (SUPPORTS_EDP(dev) && | 486 | if (driver->lvds_config == BDB_DRIVER_FEATURE_EDP) |
488 | driver->lvds_config == BDB_DRIVER_FEATURE_EDP) | ||
489 | dev_priv->vbt.edp_support = 1; | 487 | dev_priv->vbt.edp_support = 1; |
490 | 488 | ||
491 | if (driver->dual_frequency) | 489 | if (driver->dual_frequency) |
@@ -501,7 +499,7 @@ parse_edp(struct drm_i915_private *dev_priv, struct bdb_header *bdb) | |||
501 | 499 | ||
502 | edp = find_section(bdb, BDB_EDP); | 500 | edp = find_section(bdb, BDB_EDP); |
503 | if (!edp) { | 501 | if (!edp) { |
504 | if (SUPPORTS_EDP(dev_priv->dev) && dev_priv->vbt.edp_support) | 502 | if (dev_priv->vbt.edp_support) |
505 | DRM_DEBUG_KMS("No eDP BDB found but eDP panel supported.\n"); | 503 | DRM_DEBUG_KMS("No eDP BDB found but eDP panel supported.\n"); |
506 | return; | 504 | return; |
507 | } | 505 | } |
@@ -569,11 +567,149 @@ parse_edp(struct drm_i915_private *dev_priv, struct bdb_header *bdb) | |||
569 | } | 567 | } |
570 | 568 | ||
571 | static void | 569 | static void |
570 | parse_mipi(struct drm_i915_private *dev_priv, struct bdb_header *bdb) | ||
571 | { | ||
572 | struct bdb_mipi *mipi; | ||
573 | |||
574 | mipi = find_section(bdb, BDB_MIPI); | ||
575 | if (!mipi) { | ||
576 | DRM_DEBUG_KMS("No MIPI BDB found"); | ||
577 | return; | ||
578 | } | ||
579 | |||
580 | /* XXX: add more info */ | ||
581 | dev_priv->vbt.dsi.panel_id = mipi->panel_id; | ||
582 | } | ||
583 | |||
584 | static void parse_ddi_port(struct drm_i915_private *dev_priv, enum port port, | ||
585 | struct bdb_header *bdb) | ||
586 | { | ||
587 | union child_device_config *it, *child = NULL; | ||
588 | struct ddi_vbt_port_info *info = &dev_priv->vbt.ddi_port_info[port]; | ||
589 | uint8_t hdmi_level_shift; | ||
590 | int i, j; | ||
591 | bool is_dvi, is_hdmi, is_dp, is_edp, is_crt; | ||
592 | uint8_t aux_channel; | ||
593 | /* Each DDI port can have more than one value on the "DVO Port" field, | ||
594 | * so look for all the possible values for each port and abort if more | ||
595 | * than one is found. */ | ||
596 | int dvo_ports[][2] = { | ||
597 | {DVO_PORT_HDMIA, DVO_PORT_DPA}, | ||
598 | {DVO_PORT_HDMIB, DVO_PORT_DPB}, | ||
599 | {DVO_PORT_HDMIC, DVO_PORT_DPC}, | ||
600 | {DVO_PORT_HDMID, DVO_PORT_DPD}, | ||
601 | {DVO_PORT_CRT, -1 /* Port E can only be DVO_PORT_CRT */ }, | ||
602 | }; | ||
603 | |||
604 | /* Find the child device to use, abort if more than one found. */ | ||
605 | for (i = 0; i < dev_priv->vbt.child_dev_num; i++) { | ||
606 | it = dev_priv->vbt.child_dev + i; | ||
607 | |||
608 | for (j = 0; j < 2; j++) { | ||
609 | if (dvo_ports[port][j] == -1) | ||
610 | break; | ||
611 | |||
612 | if (it->common.dvo_port == dvo_ports[port][j]) { | ||
613 | if (child) { | ||
614 | DRM_DEBUG_KMS("More than one child device for port %c in VBT.\n", | ||
615 | port_name(port)); | ||
616 | return; | ||
617 | } | ||
618 | child = it; | ||
619 | } | ||
620 | } | ||
621 | } | ||
622 | if (!child) | ||
623 | return; | ||
624 | |||
625 | aux_channel = child->raw[25]; | ||
626 | |||
627 | is_dvi = child->common.device_type & DEVICE_TYPE_TMDS_DVI_SIGNALING; | ||
628 | is_dp = child->common.device_type & DEVICE_TYPE_DISPLAYPORT_OUTPUT; | ||
629 | is_crt = child->common.device_type & DEVICE_TYPE_ANALOG_OUTPUT; | ||
630 | is_hdmi = is_dvi && (child->common.device_type & DEVICE_TYPE_NOT_HDMI_OUTPUT) == 0; | ||
631 | is_edp = is_dp && (child->common.device_type & DEVICE_TYPE_INTERNAL_CONNECTOR); | ||
632 | |||
633 | info->supports_dvi = is_dvi; | ||
634 | info->supports_hdmi = is_hdmi; | ||
635 | info->supports_dp = is_dp; | ||
636 | |||
637 | DRM_DEBUG_KMS("Port %c VBT info: DP:%d HDMI:%d DVI:%d EDP:%d CRT:%d\n", | ||
638 | port_name(port), is_dp, is_hdmi, is_dvi, is_edp, is_crt); | ||
639 | |||
640 | if (is_edp && is_dvi) | ||
641 | DRM_DEBUG_KMS("Internal DP port %c is TMDS compatible\n", | ||
642 | port_name(port)); | ||
643 | if (is_crt && port != PORT_E) | ||
644 | DRM_DEBUG_KMS("Port %c is analog\n", port_name(port)); | ||
645 | if (is_crt && (is_dvi || is_dp)) | ||
646 | DRM_DEBUG_KMS("Analog port %c is also DP or TMDS compatible\n", | ||
647 | port_name(port)); | ||
648 | if (is_dvi && (port == PORT_A || port == PORT_E)) | ||
649 | DRM_DEBUG_KMS("Port %c is TMDS compabile\n", port_name(port)); | ||
650 | if (!is_dvi && !is_dp && !is_crt) | ||
651 | DRM_DEBUG_KMS("Port %c is not DP/TMDS/CRT compatible\n", | ||
652 | port_name(port)); | ||
653 | if (is_edp && (port == PORT_B || port == PORT_C || port == PORT_E)) | ||
654 | DRM_DEBUG_KMS("Port %c is internal DP\n", port_name(port)); | ||
655 | |||
656 | if (is_dvi) { | ||
657 | if (child->common.ddc_pin == 0x05 && port != PORT_B) | ||
658 | DRM_DEBUG_KMS("Unexpected DDC pin for port B\n"); | ||
659 | if (child->common.ddc_pin == 0x04 && port != PORT_C) | ||
660 | DRM_DEBUG_KMS("Unexpected DDC pin for port C\n"); | ||
661 | if (child->common.ddc_pin == 0x06 && port != PORT_D) | ||
662 | DRM_DEBUG_KMS("Unexpected DDC pin for port D\n"); | ||
663 | } | ||
664 | |||
665 | if (is_dp) { | ||
666 | if (aux_channel == 0x40 && port != PORT_A) | ||
667 | DRM_DEBUG_KMS("Unexpected AUX channel for port A\n"); | ||
668 | if (aux_channel == 0x10 && port != PORT_B) | ||
669 | DRM_DEBUG_KMS("Unexpected AUX channel for port B\n"); | ||
670 | if (aux_channel == 0x20 && port != PORT_C) | ||
671 | DRM_DEBUG_KMS("Unexpected AUX channel for port C\n"); | ||
672 | if (aux_channel == 0x30 && port != PORT_D) | ||
673 | DRM_DEBUG_KMS("Unexpected AUX channel for port D\n"); | ||
674 | } | ||
675 | |||
676 | if (bdb->version >= 158) { | ||
677 | /* The VBT HDMI level shift values match the table we have. */ | ||
678 | hdmi_level_shift = child->raw[7] & 0xF; | ||
679 | if (hdmi_level_shift < 0xC) { | ||
680 | DRM_DEBUG_KMS("VBT HDMI level shift for port %c: %d\n", | ||
681 | port_name(port), | ||
682 | hdmi_level_shift); | ||
683 | info->hdmi_level_shift = hdmi_level_shift; | ||
684 | } | ||
685 | } | ||
686 | } | ||
687 | |||
688 | static void parse_ddi_ports(struct drm_i915_private *dev_priv, | ||
689 | struct bdb_header *bdb) | ||
690 | { | ||
691 | struct drm_device *dev = dev_priv->dev; | ||
692 | enum port port; | ||
693 | |||
694 | if (!HAS_DDI(dev)) | ||
695 | return; | ||
696 | |||
697 | if (!dev_priv->vbt.child_dev_num) | ||
698 | return; | ||
699 | |||
700 | if (bdb->version < 155) | ||
701 | return; | ||
702 | |||
703 | for (port = PORT_A; port < I915_MAX_PORTS; port++) | ||
704 | parse_ddi_port(dev_priv, port, bdb); | ||
705 | } | ||
706 | |||
707 | static void | ||
572 | parse_device_mapping(struct drm_i915_private *dev_priv, | 708 | parse_device_mapping(struct drm_i915_private *dev_priv, |
573 | struct bdb_header *bdb) | 709 | struct bdb_header *bdb) |
574 | { | 710 | { |
575 | struct bdb_general_definitions *p_defs; | 711 | struct bdb_general_definitions *p_defs; |
576 | struct child_device_config *p_child, *child_dev_ptr; | 712 | union child_device_config *p_child, *child_dev_ptr; |
577 | int i, child_device_num, count; | 713 | int i, child_device_num, count; |
578 | u16 block_size; | 714 | u16 block_size; |
579 | 715 | ||
@@ -601,7 +737,7 @@ parse_device_mapping(struct drm_i915_private *dev_priv, | |||
601 | /* get the number of child device that is present */ | 737 | /* get the number of child device that is present */ |
602 | for (i = 0; i < child_device_num; i++) { | 738 | for (i = 0; i < child_device_num; i++) { |
603 | p_child = &(p_defs->devices[i]); | 739 | p_child = &(p_defs->devices[i]); |
604 | if (!p_child->device_type) { | 740 | if (!p_child->common.device_type) { |
605 | /* skip the device block if device type is invalid */ | 741 | /* skip the device block if device type is invalid */ |
606 | continue; | 742 | continue; |
607 | } | 743 | } |
@@ -621,7 +757,7 @@ parse_device_mapping(struct drm_i915_private *dev_priv, | |||
621 | count = 0; | 757 | count = 0; |
622 | for (i = 0; i < child_device_num; i++) { | 758 | for (i = 0; i < child_device_num; i++) { |
623 | p_child = &(p_defs->devices[i]); | 759 | p_child = &(p_defs->devices[i]); |
624 | if (!p_child->device_type) { | 760 | if (!p_child->common.device_type) { |
625 | /* skip the device block if device type is invalid */ | 761 | /* skip the device block if device type is invalid */ |
626 | continue; | 762 | continue; |
627 | } | 763 | } |
@@ -637,6 +773,7 @@ static void | |||
637 | init_vbt_defaults(struct drm_i915_private *dev_priv) | 773 | init_vbt_defaults(struct drm_i915_private *dev_priv) |
638 | { | 774 | { |
639 | struct drm_device *dev = dev_priv->dev; | 775 | struct drm_device *dev = dev_priv->dev; |
776 | enum port port; | ||
640 | 777 | ||
641 | dev_priv->vbt.crt_ddc_pin = GMBUS_PORT_VGADDC; | 778 | dev_priv->vbt.crt_ddc_pin = GMBUS_PORT_VGADDC; |
642 | 779 | ||
@@ -655,6 +792,18 @@ init_vbt_defaults(struct drm_i915_private *dev_priv) | |||
655 | dev_priv->vbt.lvds_use_ssc = 1; | 792 | dev_priv->vbt.lvds_use_ssc = 1; |
656 | dev_priv->vbt.lvds_ssc_freq = intel_bios_ssc_frequency(dev, 1); | 793 | dev_priv->vbt.lvds_ssc_freq = intel_bios_ssc_frequency(dev, 1); |
657 | DRM_DEBUG_KMS("Set default to SSC at %dMHz\n", dev_priv->vbt.lvds_ssc_freq); | 794 | DRM_DEBUG_KMS("Set default to SSC at %dMHz\n", dev_priv->vbt.lvds_ssc_freq); |
795 | |||
796 | for (port = PORT_A; port < I915_MAX_PORTS; port++) { | ||
797 | struct ddi_vbt_port_info *info = | ||
798 | &dev_priv->vbt.ddi_port_info[port]; | ||
799 | |||
800 | /* Recommended BSpec default: 800mV 0dB. */ | ||
801 | info->hdmi_level_shift = 6; | ||
802 | |||
803 | info->supports_dvi = (port != PORT_A && port != PORT_E); | ||
804 | info->supports_hdmi = info->supports_dvi; | ||
805 | info->supports_dp = (port != PORT_E); | ||
806 | } | ||
658 | } | 807 | } |
659 | 808 | ||
660 | static int __init intel_no_opregion_vbt_callback(const struct dmi_system_id *id) | 809 | static int __init intel_no_opregion_vbt_callback(const struct dmi_system_id *id) |
@@ -745,6 +894,8 @@ intel_parse_bios(struct drm_device *dev) | |||
745 | parse_device_mapping(dev_priv, bdb); | 894 | parse_device_mapping(dev_priv, bdb); |
746 | parse_driver_features(dev_priv, bdb); | 895 | parse_driver_features(dev_priv, bdb); |
747 | parse_edp(dev_priv, bdb); | 896 | parse_edp(dev_priv, bdb); |
897 | parse_mipi(dev_priv, bdb); | ||
898 | parse_ddi_ports(dev_priv, bdb); | ||
748 | 899 | ||
749 | if (bios) | 900 | if (bios) |
750 | pci_unmap_rom(pdev, bios); | 901 | pci_unmap_rom(pdev, bios); |