280,6 → 280,34 |
} |
} |
|
static void |
parse_lfp_backlight(struct drm_i915_private *dev_priv, struct bdb_header *bdb) |
{ |
const struct bdb_lfp_backlight_data *backlight_data; |
const struct bdb_lfp_backlight_data_entry *entry; |
|
backlight_data = find_section(bdb, BDB_LVDS_BACKLIGHT); |
if (!backlight_data) |
return; |
|
if (backlight_data->entry_size != sizeof(backlight_data->data[0])) { |
DRM_DEBUG_KMS("Unsupported backlight data entry size %u\n", |
backlight_data->entry_size); |
return; |
} |
|
entry = &backlight_data->data[panel_type]; |
|
dev_priv->vbt.backlight.pwm_freq_hz = entry->pwm_freq_hz; |
dev_priv->vbt.backlight.active_low_pwm = entry->active_low_pwm; |
DRM_DEBUG_KMS("VBT backlight PWM modulation frequency %u Hz, " |
"active %s, min brightness %u, level %u\n", |
dev_priv->vbt.backlight.pwm_freq_hz, |
dev_priv->vbt.backlight.active_low_pwm ? "low" : "high", |
entry->min_brightness, |
backlight_data->level[panel_type]); |
} |
|
/* Try to find sdvo panel data */ |
static void |
parse_sdvo_panel_data(struct drm_i915_private *dev_priv, |
326,12 → 354,12 |
{ |
switch (INTEL_INFO(dev)->gen) { |
case 2: |
return alternate ? 66 : 48; |
return alternate ? 66667 : 48000; |
case 3: |
case 4: |
return alternate ? 100 : 96; |
return alternate ? 100000 : 96000; |
default: |
return alternate ? 100 : 120; |
return alternate ? 100000 : 120000; |
} |
} |
|
388,7 → 416,7 |
{ |
struct sdvo_device_mapping *p_mapping; |
struct bdb_general_definitions *p_defs; |
struct child_device_config *p_child; |
union child_device_config *p_child; |
int i, child_device_num, count; |
u16 block_size; |
|
415,12 → 443,12 |
count = 0; |
for (i = 0; i < child_device_num; i++) { |
p_child = &(p_defs->devices[i]); |
if (!p_child->device_type) { |
if (!p_child->old.device_type) { |
/* skip the device block if device type is invalid */ |
continue; |
} |
if (p_child->slave_addr != SLAVE_ADDR1 && |
p_child->slave_addr != SLAVE_ADDR2) { |
if (p_child->old.slave_addr != SLAVE_ADDR1 && |
p_child->old.slave_addr != SLAVE_ADDR2) { |
/* |
* If the slave address is neither 0x70 nor 0x72, |
* it is not a SDVO device. Skip it. |
427,8 → 455,8 |
*/ |
continue; |
} |
if (p_child->dvo_port != DEVICE_PORT_DVOB && |
p_child->dvo_port != DEVICE_PORT_DVOC) { |
if (p_child->old.dvo_port != DEVICE_PORT_DVOB && |
p_child->old.dvo_port != DEVICE_PORT_DVOC) { |
/* skip the incorrect SDVO port */ |
DRM_DEBUG_KMS("Incorrect SDVO port. Skip it\n"); |
continue; |
435,16 → 463,16 |
} |
DRM_DEBUG_KMS("the SDVO device with slave addr %2x is found on" |
" %s port\n", |
p_child->slave_addr, |
(p_child->dvo_port == DEVICE_PORT_DVOB) ? |
p_child->old.slave_addr, |
(p_child->old.dvo_port == DEVICE_PORT_DVOB) ? |
"SDVOB" : "SDVOC"); |
p_mapping = &(dev_priv->sdvo_mappings[p_child->dvo_port - 1]); |
p_mapping = &(dev_priv->sdvo_mappings[p_child->old.dvo_port - 1]); |
if (!p_mapping->initialized) { |
p_mapping->dvo_port = p_child->dvo_port; |
p_mapping->slave_addr = p_child->slave_addr; |
p_mapping->dvo_wiring = p_child->dvo_wiring; |
p_mapping->ddc_pin = p_child->ddc_pin; |
p_mapping->i2c_pin = p_child->i2c_pin; |
p_mapping->dvo_port = p_child->old.dvo_port; |
p_mapping->slave_addr = p_child->old.slave_addr; |
p_mapping->dvo_wiring = p_child->old.dvo_wiring; |
p_mapping->ddc_pin = p_child->old.ddc_pin; |
p_mapping->i2c_pin = p_child->old.i2c_pin; |
p_mapping->initialized = 1; |
DRM_DEBUG_KMS("SDVO device: dvo=%x, addr=%x, wiring=%d, ddc_pin=%d, i2c_pin=%d\n", |
p_mapping->dvo_port, |
456,7 → 484,7 |
DRM_DEBUG_KMS("Maybe one SDVO port is shared by " |
"two SDVO device.\n"); |
} |
if (p_child->slave2_addr) { |
if (p_child->old.slave2_addr) { |
/* Maybe this is a SDVO device with multiple inputs */ |
/* And the mapping info is not added */ |
DRM_DEBUG_KMS("there exists the slave2_addr. Maybe this" |
476,7 → 504,6 |
parse_driver_features(struct drm_i915_private *dev_priv, |
struct bdb_header *bdb) |
{ |
struct drm_device *dev = dev_priv->dev; |
struct bdb_driver_features *driver; |
|
driver = find_section(bdb, BDB_DRIVER_FEATURES); |
483,8 → 510,7 |
if (!driver) |
return; |
|
if (SUPPORTS_EDP(dev) && |
driver->lvds_config == BDB_DRIVER_FEATURE_EDP) |
if (driver->lvds_config == BDB_DRIVER_FEATURE_EDP) |
dev_priv->vbt.edp_support = 1; |
|
if (driver->dual_frequency) |
500,7 → 526,7 |
|
edp = find_section(bdb, BDB_EDP); |
if (!edp) { |
if (SUPPORTS_EDP(dev_priv->dev) && dev_priv->vbt.edp_support) |
if (dev_priv->vbt.edp_support) |
DRM_DEBUG_KMS("No eDP BDB found but eDP panel supported.\n"); |
return; |
} |
568,11 → 594,149 |
} |
|
static void |
parse_mipi(struct drm_i915_private *dev_priv, struct bdb_header *bdb) |
{ |
struct bdb_mipi *mipi; |
|
mipi = find_section(bdb, BDB_MIPI); |
if (!mipi) { |
DRM_DEBUG_KMS("No MIPI BDB found"); |
return; |
} |
|
/* XXX: add more info */ |
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; |
bool is_dvi, is_hdmi, is_dp, is_edp, is_crt; |
uint8_t aux_channel; |
/* 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; |
|
aux_channel = child->raw[25]; |
|
is_dvi = child->common.device_type & DEVICE_TYPE_TMDS_DVI_SIGNALING; |
is_dp = child->common.device_type & DEVICE_TYPE_DISPLAYPORT_OUTPUT; |
is_crt = child->common.device_type & DEVICE_TYPE_ANALOG_OUTPUT; |
is_hdmi = is_dvi && (child->common.device_type & DEVICE_TYPE_NOT_HDMI_OUTPUT) == 0; |
is_edp = is_dp && (child->common.device_type & DEVICE_TYPE_INTERNAL_CONNECTOR); |
|
info->supports_dvi = is_dvi; |
info->supports_hdmi = is_hdmi; |
info->supports_dp = is_dp; |
|
DRM_DEBUG_KMS("Port %c VBT info: DP:%d HDMI:%d DVI:%d EDP:%d CRT:%d\n", |
port_name(port), is_dp, is_hdmi, is_dvi, is_edp, is_crt); |
|
if (is_edp && is_dvi) |
DRM_DEBUG_KMS("Internal DP port %c is TMDS compatible\n", |
port_name(port)); |
if (is_crt && port != PORT_E) |
DRM_DEBUG_KMS("Port %c is analog\n", port_name(port)); |
if (is_crt && (is_dvi || is_dp)) |
DRM_DEBUG_KMS("Analog port %c is also DP or TMDS compatible\n", |
port_name(port)); |
if (is_dvi && (port == PORT_A || port == PORT_E)) |
DRM_DEBUG_KMS("Port %c is TMDS compabile\n", port_name(port)); |
if (!is_dvi && !is_dp && !is_crt) |
DRM_DEBUG_KMS("Port %c is not DP/TMDS/CRT compatible\n", |
port_name(port)); |
if (is_edp && (port == PORT_B || port == PORT_C || port == PORT_E)) |
DRM_DEBUG_KMS("Port %c is internal DP\n", port_name(port)); |
|
if (is_dvi) { |
if (child->common.ddc_pin == 0x05 && port != PORT_B) |
DRM_DEBUG_KMS("Unexpected DDC pin for port B\n"); |
if (child->common.ddc_pin == 0x04 && port != PORT_C) |
DRM_DEBUG_KMS("Unexpected DDC pin for port C\n"); |
if (child->common.ddc_pin == 0x06 && port != PORT_D) |
DRM_DEBUG_KMS("Unexpected DDC pin for port D\n"); |
} |
|
if (is_dp) { |
if (aux_channel == 0x40 && port != PORT_A) |
DRM_DEBUG_KMS("Unexpected AUX channel for port A\n"); |
if (aux_channel == 0x10 && port != PORT_B) |
DRM_DEBUG_KMS("Unexpected AUX channel for port B\n"); |
if (aux_channel == 0x20 && port != PORT_C) |
DRM_DEBUG_KMS("Unexpected AUX channel for port C\n"); |
if (aux_channel == 0x30 && port != PORT_D) |
DRM_DEBUG_KMS("Unexpected AUX channel for port D\n"); |
} |
|
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) |
{ |
struct bdb_general_definitions *p_defs; |
struct child_device_config *p_child, *child_dev_ptr; |
union child_device_config *p_child, *child_dev_ptr; |
int i, child_device_num, count; |
u16 block_size; |
|
600,7 → 764,7 |
/* get the number of child device that is present */ |
for (i = 0; i < child_device_num; i++) { |
p_child = &(p_defs->devices[i]); |
if (!p_child->device_type) { |
if (!p_child->common.device_type) { |
/* skip the device block if device type is invalid */ |
continue; |
} |
620,7 → 784,7 |
count = 0; |
for (i = 0; i < child_device_num; i++) { |
p_child = &(p_defs->devices[i]); |
if (!p_child->device_type) { |
if (!p_child->common.device_type) { |
/* skip the device block if device type is invalid */ |
continue; |
} |
636,6 → 800,7 |
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; |
|
652,9 → 817,26 |
|
/* Default to using SSC */ |
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); |
/* |
* Core/SandyBridge/IvyBridge use alternative (120MHz) reference |
* clock for LVDS. |
*/ |
dev_priv->vbt.lvds_ssc_freq = intel_bios_ssc_frequency(dev, |
!HAS_PCH_SPLIT(dev)); |
DRM_DEBUG_KMS("Set default to SSC at %d kHz\n", dev_priv->vbt.lvds_ssc_freq); |
|
for (port = PORT_A; port < I915_MAX_PORTS; port++) { |
struct ddi_vbt_port_info *info = |
&dev_priv->vbt.ddi_port_info[port]; |
|
/* Recommended BSpec default: 800mV 0dB. */ |
info->hdmi_level_shift = 6; |
|
info->supports_dvi = (port != PORT_A && port != PORT_E); |
info->supports_hdmi = info->supports_dvi; |
info->supports_dp = (port != PORT_E); |
} |
} |
|
|
/** |
720,11 → 902,14 |
parse_general_features(dev_priv, bdb); |
parse_general_definitions(dev_priv, bdb); |
parse_lfp_panel_data(dev_priv, bdb); |
parse_lfp_backlight(dev_priv, bdb); |
parse_sdvo_panel_data(dev_priv, bdb); |
parse_sdvo_device_mapping(dev_priv, bdb); |
parse_device_mapping(dev_priv, bdb); |
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); |