aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h6
-rw-r--r--drivers/gpu/drm/i915/intel_bios.c77
-rw-r--r--drivers/gpu/drm/i915/intel_bios.h13
-rw-r--r--drivers/gpu/drm/i915/intel_ddi.c24
4 files changed, 118 insertions, 2 deletions
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 9868a66ef59c..2eca286b57ff 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1057,6 +1057,10 @@ enum modeset_restore {
1057 MODESET_SUSPENDED, 1057 MODESET_SUSPENDED,
1058}; 1058};
1059 1059
1060struct ddi_vbt_port_info {
1061 uint8_t hdmi_level_shift;
1062};
1063
1060struct intel_vbt_data { 1064struct intel_vbt_data {
1061 struct drm_display_mode *lfp_lvds_vbt_mode; /* if any */ 1065 struct drm_display_mode *lfp_lvds_vbt_mode; /* if any */
1062 struct drm_display_mode *sdvo_lvds_vbt_mode; /* if any */ 1066 struct drm_display_mode *sdvo_lvds_vbt_mode; /* if any */
@@ -1091,6 +1095,8 @@ struct intel_vbt_data {
1091 1095
1092 int child_dev_num; 1096 int child_dev_num;
1093 union child_device_config *child_dev; 1097 union child_device_config *child_dev;
1098
1099 struct ddi_vbt_port_info ddi_port_info[I915_MAX_PORTS];
1094}; 1100};
1095 1101
1096enum intel_ddb_partitioning { 1102enum intel_ddb_partitioning {
diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c
index 33003b97f1f0..2f434297246e 100644
--- a/drivers/gpu/drm/i915/intel_bios.c
+++ b/drivers/gpu/drm/i915/intel_bios.c
@@ -583,6 +583,76 @@ parse_mipi(struct drm_i915_private *dev_priv, struct bdb_header *bdb)
583 dev_priv->vbt.dsi.panel_id = mipi->panel_id; 583 dev_priv->vbt.dsi.panel_id = mipi->panel_id;
584} 584}
585 585
586static void parse_ddi_port(struct drm_i915_private *dev_priv, enum port port,
587 struct bdb_header *bdb)
588{
589 union child_device_config *it, *child = NULL;
590 struct ddi_vbt_port_info *info = &dev_priv->vbt.ddi_port_info[port];
591 uint8_t hdmi_level_shift;
592 int i, j;
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 if (bdb->version >= 158) {
626 /* The VBT HDMI level shift values match the table we have. */
627 hdmi_level_shift = child->raw[7] & 0xF;
628 if (hdmi_level_shift < 0xC) {
629 DRM_DEBUG_KMS("VBT HDMI level shift for port %c: %d\n",
630 port_name(port),
631 hdmi_level_shift);
632 info->hdmi_level_shift = hdmi_level_shift;
633 }
634 }
635}
636
637static void parse_ddi_ports(struct drm_i915_private *dev_priv,
638 struct bdb_header *bdb)
639{
640 struct drm_device *dev = dev_priv->dev;
641 enum port port;
642
643 if (!HAS_DDI(dev))
644 return;
645
646 if (!dev_priv->vbt.child_dev_num)
647 return;
648
649 if (bdb->version < 155)
650 return;
651
652 for (port = PORT_A; port < I915_MAX_PORTS; port++)
653 parse_ddi_port(dev_priv, port, bdb);
654}
655
586static void 656static void
587parse_device_mapping(struct drm_i915_private *dev_priv, 657parse_device_mapping(struct drm_i915_private *dev_priv,
588 struct bdb_header *bdb) 658 struct bdb_header *bdb)
@@ -652,6 +722,7 @@ static void
652init_vbt_defaults(struct drm_i915_private *dev_priv) 722init_vbt_defaults(struct drm_i915_private *dev_priv)
653{ 723{
654 struct drm_device *dev = dev_priv->dev; 724 struct drm_device *dev = dev_priv->dev;
725 enum port port;
655 726
656 dev_priv->vbt.crt_ddc_pin = GMBUS_PORT_VGADDC; 727 dev_priv->vbt.crt_ddc_pin = GMBUS_PORT_VGADDC;
657 728
@@ -670,6 +741,11 @@ init_vbt_defaults(struct drm_i915_private *dev_priv)
670 dev_priv->vbt.lvds_use_ssc = 1; 741 dev_priv->vbt.lvds_use_ssc = 1;
671 dev_priv->vbt.lvds_ssc_freq = intel_bios_ssc_frequency(dev, 1); 742 dev_priv->vbt.lvds_ssc_freq = intel_bios_ssc_frequency(dev, 1);
672 DRM_DEBUG_KMS("Set default to SSC at %dMHz\n", dev_priv->vbt.lvds_ssc_freq); 743 DRM_DEBUG_KMS("Set default to SSC at %dMHz\n", dev_priv->vbt.lvds_ssc_freq);
744
745 for (port = PORT_A; port < I915_MAX_PORTS; port++) {
746 /* Recommended BSpec default: 800mV 0dB. */
747 dev_priv->vbt.ddi_port_info[port].hdmi_level_shift = 6;
748 }
673} 749}
674 750
675static int __init intel_no_opregion_vbt_callback(const struct dmi_system_id *id) 751static int __init intel_no_opregion_vbt_callback(const struct dmi_system_id *id)
@@ -761,6 +837,7 @@ intel_parse_bios(struct drm_device *dev)
761 parse_driver_features(dev_priv, bdb); 837 parse_driver_features(dev_priv, bdb);
762 parse_edp(dev_priv, bdb); 838 parse_edp(dev_priv, bdb);
763 parse_mipi(dev_priv, bdb); 839 parse_mipi(dev_priv, bdb);
840 parse_ddi_ports(dev_priv, bdb);
764 841
765 if (bios) 842 if (bios)
766 pci_unmap_rom(pdev, bios); 843 pci_unmap_rom(pdev, bios);
diff --git a/drivers/gpu/drm/i915/intel_bios.h b/drivers/gpu/drm/i915/intel_bios.h
index 1da2bf208299..287cc5a21c2e 100644
--- a/drivers/gpu/drm/i915/intel_bios.h
+++ b/drivers/gpu/drm/i915/intel_bios.h
@@ -648,6 +648,19 @@ int intel_parse_bios(struct drm_device *dev);
648#define PORT_IDPC 8 648#define PORT_IDPC 8
649#define PORT_IDPD 9 649#define PORT_IDPD 9
650 650
651/* Possible values for the "DVO Port" field for versions >= 155: */
652#define DVO_PORT_HDMIA 0
653#define DVO_PORT_HDMIB 1
654#define DVO_PORT_HDMIC 2
655#define DVO_PORT_HDMID 3
656#define DVO_PORT_LVDS 4
657#define DVO_PORT_TV 5
658#define DVO_PORT_CRT 6
659#define DVO_PORT_DPB 7
660#define DVO_PORT_DPC 8
661#define DVO_PORT_DPD 9
662#define DVO_PORT_DPA 10
663
651/* MIPI DSI panel info */ 664/* MIPI DSI panel info */
652struct bdb_mipi { 665struct bdb_mipi {
653 u16 panel_id; 666 u16 panel_id;
diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index 351e21a0be07..963245a104e4 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -42,7 +42,6 @@ static const u32 hsw_ddi_translations_dp[] = {
42 0x80C30FFF, 0x000B0000, 42 0x80C30FFF, 0x000B0000,
43 0x00FFFFFF, 0x00040006, 43 0x00FFFFFF, 0x00040006,
44 0x80D75FFF, 0x000B0000, 44 0x80D75FFF, 0x000B0000,
45 0x00FFFFFF, 0x00040006 /* HDMI parameters */
46}; 45};
47 46
48static const u32 hsw_ddi_translations_fdi[] = { 47static const u32 hsw_ddi_translations_fdi[] = {
@@ -55,7 +54,22 @@ static const u32 hsw_ddi_translations_fdi[] = {
55 0x00C30FFF, 0x001E0000, 54 0x00C30FFF, 0x001E0000,
56 0x00FFFFFF, 0x00060006, 55 0x00FFFFFF, 0x00060006,
57 0x00D75FFF, 0x001E0000, 56 0x00D75FFF, 0x001E0000,
58 0x00FFFFFF, 0x00040006 /* HDMI parameters */ 57};
58
59static const u32 hsw_ddi_translations_hdmi[] = {
60 /* Idx NT mV diff T mV diff db */
61 0x00FFFFFF, 0x0006000E, /* 0: 400 400 0 */
62 0x00E79FFF, 0x000E000C, /* 1: 400 500 2 */
63 0x00D75FFF, 0x0005000A, /* 2: 400 600 3.5 */
64 0x00FFFFFF, 0x0005000A, /* 3: 600 600 0 */
65 0x00E79FFF, 0x001D0007, /* 4: 600 750 2 */
66 0x00D75FFF, 0x000C0004, /* 5: 600 900 3.5 */
67 0x00FFFFFF, 0x00040006, /* 6: 800 800 0 */
68 0x80E79FFF, 0x00030002, /* 7: 800 1000 2 */
69 0x00FFFFFF, 0x00140005, /* 8: 850 850 0 */
70 0x00FFFFFF, 0x000C0004, /* 9: 900 900 0 */
71 0x00FFFFFF, 0x001C0003, /* 10: 950 950 0 */
72 0x80FFFFFF, 0x00030002, /* 11: 1000 1000 0 */
59}; 73};
60 74
61enum port intel_ddi_get_encoder_port(struct intel_encoder *intel_encoder) 75enum port intel_ddi_get_encoder_port(struct intel_encoder *intel_encoder)
@@ -92,12 +106,18 @@ static void intel_prepare_ddi_buffers(struct drm_device *dev, enum port port)
92 const u32 *ddi_translations = (port == PORT_E) ? 106 const u32 *ddi_translations = (port == PORT_E) ?
93 hsw_ddi_translations_fdi : 107 hsw_ddi_translations_fdi :
94 hsw_ddi_translations_dp; 108 hsw_ddi_translations_dp;
109 int hdmi_level = dev_priv->vbt.ddi_port_info[port].hdmi_level_shift;
95 110
96 for (i = 0, reg = DDI_BUF_TRANS(port); 111 for (i = 0, reg = DDI_BUF_TRANS(port);
97 i < ARRAY_SIZE(hsw_ddi_translations_fdi); i++) { 112 i < ARRAY_SIZE(hsw_ddi_translations_fdi); i++) {
98 I915_WRITE(reg, ddi_translations[i]); 113 I915_WRITE(reg, ddi_translations[i]);
99 reg += 4; 114 reg += 4;
100 } 115 }
116 /* Entry 9 is for HDMI: */
117 for (i = 0; i < 2; i++) {
118 I915_WRITE(reg, hsw_ddi_translations_hdmi[hdmi_level * 2 + i]);
119 reg += 4;
120 }
101} 121}
102 122
103/* Program DDI buffers translations for DP. By default, program ports A-D in DP 123/* Program DDI buffers translations for DP. By default, program ports A-D in DP