dev_priv->vbt.dsi.panel_id = mipi->panel_id;
}
+static void parse_ddi_port(struct drm_i915_private *dev_priv, enum port port,
+ struct bdb_header *bdb)
+{
+ union child_device_config *it, *child = NULL;
+ struct ddi_vbt_port_info *info = &dev_priv->vbt.ddi_port_info[port];
+ uint8_t hdmi_level_shift;
+ int i, j;
+ /* Each DDI port can have more than one value on the "DVO Port" field,
+ * so look for all the possible values for each port and abort if more
+ * than one is found. */
+ int dvo_ports[][2] = {
+ {DVO_PORT_HDMIA, DVO_PORT_DPA},
+ {DVO_PORT_HDMIB, DVO_PORT_DPB},
+ {DVO_PORT_HDMIC, DVO_PORT_DPC},
+ {DVO_PORT_HDMID, DVO_PORT_DPD},
+ {DVO_PORT_CRT, -1 /* Port E can only be DVO_PORT_CRT */ },
+ };
+
+ /* Find the child device to use, abort if more than one found. */
+ for (i = 0; i < dev_priv->vbt.child_dev_num; i++) {
+ it = dev_priv->vbt.child_dev + i;
+
+ for (j = 0; j < 2; j++) {
+ if (dvo_ports[port][j] == -1)
+ break;
+
+ if (it->common.dvo_port == dvo_ports[port][j]) {
+ if (child) {
+ DRM_DEBUG_KMS("More than one child device for port %c in VBT.\n",
+ port_name(port));
+ return;
+ }
+ child = it;
+ }
+ }
+ }
+ if (!child)
+ return;
+
+ if (bdb->version >= 158) {
+ /* The VBT HDMI level shift values match the table we have. */
+ hdmi_level_shift = child->raw[7] & 0xF;
+ if (hdmi_level_shift < 0xC) {
+ DRM_DEBUG_KMS("VBT HDMI level shift for port %c: %d\n",
+ port_name(port),
+ hdmi_level_shift);
+ info->hdmi_level_shift = hdmi_level_shift;
+ }
+ }
+}
+
+static void parse_ddi_ports(struct drm_i915_private *dev_priv,
+ struct bdb_header *bdb)
+{
+ struct drm_device *dev = dev_priv->dev;
+ enum port port;
+
+ if (!HAS_DDI(dev))
+ return;
+
+ if (!dev_priv->vbt.child_dev_num)
+ return;
+
+ if (bdb->version < 155)
+ return;
+
+ for (port = PORT_A; port < I915_MAX_PORTS; port++)
+ parse_ddi_port(dev_priv, port, bdb);
+}
+
static void
parse_device_mapping(struct drm_i915_private *dev_priv,
struct bdb_header *bdb)
init_vbt_defaults(struct drm_i915_private *dev_priv)
{
struct drm_device *dev = dev_priv->dev;
+ enum port port;
dev_priv->vbt.crt_ddc_pin = GMBUS_PORT_VGADDC;
dev_priv->vbt.lvds_use_ssc = 1;
dev_priv->vbt.lvds_ssc_freq = intel_bios_ssc_frequency(dev, 1);
DRM_DEBUG_KMS("Set default to SSC at %dMHz\n", dev_priv->vbt.lvds_ssc_freq);
+
+ for (port = PORT_A; port < I915_MAX_PORTS; port++) {
+ /* Recommended BSpec default: 800mV 0dB. */
+ dev_priv->vbt.ddi_port_info[port].hdmi_level_shift = 6;
+ }
}
static int __init intel_no_opregion_vbt_callback(const struct dmi_system_id *id)
parse_driver_features(dev_priv, bdb);
parse_edp(dev_priv, bdb);
parse_mipi(dev_priv, bdb);
+ parse_ddi_ports(dev_priv, bdb);
if (bios)
pci_unmap_rom(pdev, bios);
0x80C30FFF, 0x000B0000,
0x00FFFFFF, 0x00040006,
0x80D75FFF, 0x000B0000,
- 0x00FFFFFF, 0x00040006 /* HDMI parameters */
};
static const u32 hsw_ddi_translations_fdi[] = {
0x00C30FFF, 0x001E0000,
0x00FFFFFF, 0x00060006,
0x00D75FFF, 0x001E0000,
- 0x00FFFFFF, 0x00040006 /* HDMI parameters */
+};
+
+static const u32 hsw_ddi_translations_hdmi[] = {
+ /* Idx NT mV diff T mV diff db */
+ 0x00FFFFFF, 0x0006000E, /* 0: 400 400 0 */
+ 0x00E79FFF, 0x000E000C, /* 1: 400 500 2 */
+ 0x00D75FFF, 0x0005000A, /* 2: 400 600 3.5 */
+ 0x00FFFFFF, 0x0005000A, /* 3: 600 600 0 */
+ 0x00E79FFF, 0x001D0007, /* 4: 600 750 2 */
+ 0x00D75FFF, 0x000C0004, /* 5: 600 900 3.5 */
+ 0x00FFFFFF, 0x00040006, /* 6: 800 800 0 */
+ 0x80E79FFF, 0x00030002, /* 7: 800 1000 2 */
+ 0x00FFFFFF, 0x00140005, /* 8: 850 850 0 */
+ 0x00FFFFFF, 0x000C0004, /* 9: 900 900 0 */
+ 0x00FFFFFF, 0x001C0003, /* 10: 950 950 0 */
+ 0x80FFFFFF, 0x00030002, /* 11: 1000 1000 0 */
};
enum port intel_ddi_get_encoder_port(struct intel_encoder *intel_encoder)
const u32 *ddi_translations = (port == PORT_E) ?
hsw_ddi_translations_fdi :
hsw_ddi_translations_dp;
+ int hdmi_level = dev_priv->vbt.ddi_port_info[port].hdmi_level_shift;
for (i = 0, reg = DDI_BUF_TRANS(port);
i < ARRAY_SIZE(hsw_ddi_translations_fdi); i++) {
I915_WRITE(reg, ddi_translations[i]);
reg += 4;
}
+ /* Entry 9 is for HDMI: */
+ for (i = 0; i < 2; i++) {
+ I915_WRITE(reg, hsw_ddi_translations_hdmi[hdmi_level * 2 + i]);
+ reg += 4;
+ }
}
/* Program DDI buffers translations for DP. By default, program ports A-D in DP