Commit 701078d5 authored by Dave Airlie's avatar Dave Airlie

Merge tag 'drm-intel-next-fixes-2015-08-28' of...

Merge tag 'drm-intel-next-fixes-2015-08-28' of git://anongit.freedesktop.org/drm-intel into drm-next

Some i915 fixes headed for v4.3. SKL DDI-E is a wip, but here's the
first in a series.

* tag 'drm-intel-next-fixes-2015-08-28' of git://anongit.freedesktop.org/drm-intel:
  drm/i915/skl: enable DDI-E hotplug
  drm/i915: Fix build warning on 32-bit
  drm/i915/skl: Update DDI buffer translation programming.
  drm/i915: Allow parsing of variable size child device entries from VBT
  drm/i915: fix link rates reported for SKL
  drm/i915: fix VBT parsing for SDVO child device mapping
parents d3e8ea50 26951caf
...@@ -214,6 +214,7 @@ enum hpd_pin { ...@@ -214,6 +214,7 @@ enum hpd_pin {
HPD_PORT_B, HPD_PORT_B,
HPD_PORT_C, HPD_PORT_C,
HPD_PORT_D, HPD_PORT_D,
HPD_PORT_E,
HPD_NUM_PINS HPD_NUM_PINS
}; };
......
...@@ -348,7 +348,7 @@ int i915_gem_init_stolen(struct drm_device *dev) ...@@ -348,7 +348,7 @@ int i915_gem_init_stolen(struct drm_device *dev)
* memory, so just consider the start. */ * memory, so just consider the start. */
reserved_total = stolen_top - reserved_base; reserved_total = stolen_top - reserved_base;
DRM_DEBUG_KMS("Memory reserved for graphics device: %luK, usable: %luK\n", DRM_DEBUG_KMS("Memory reserved for graphics device: %zuK, usable: %luK\n",
dev_priv->gtt.stolen_size >> 10, dev_priv->gtt.stolen_size >> 10,
(dev_priv->gtt.stolen_size - reserved_total) >> 10); (dev_priv->gtt.stolen_size - reserved_total) >> 10);
......
...@@ -61,6 +61,13 @@ static const u32 hpd_cpt[HPD_NUM_PINS] = { ...@@ -61,6 +61,13 @@ static const u32 hpd_cpt[HPD_NUM_PINS] = {
[HPD_PORT_D] = SDE_PORTD_HOTPLUG_CPT [HPD_PORT_D] = SDE_PORTD_HOTPLUG_CPT
}; };
static const u32 hpd_spt[HPD_NUM_PINS] = {
[HPD_PORT_B] = SDE_PORTB_HOTPLUG_CPT,
[HPD_PORT_C] = SDE_PORTC_HOTPLUG_CPT,
[HPD_PORT_D] = SDE_PORTD_HOTPLUG_CPT,
[HPD_PORT_E] = SDE_PORTE_HOTPLUG_SPT
};
static const u32 hpd_mask_i915[HPD_NUM_PINS] = { static const u32 hpd_mask_i915[HPD_NUM_PINS] = {
[HPD_CRT] = CRT_HOTPLUG_INT_EN, [HPD_CRT] = CRT_HOTPLUG_INT_EN,
[HPD_SDVO_B] = SDVOB_HOTPLUG_INT_EN, [HPD_SDVO_B] = SDVOB_HOTPLUG_INT_EN,
...@@ -1252,6 +1259,8 @@ static bool pch_port_hotplug_long_detect(enum port port, u32 val) ...@@ -1252,6 +1259,8 @@ static bool pch_port_hotplug_long_detect(enum port port, u32 val)
return val & PORTC_HOTPLUG_LONG_DETECT; return val & PORTC_HOTPLUG_LONG_DETECT;
case PORT_D: case PORT_D:
return val & PORTD_HOTPLUG_LONG_DETECT; return val & PORTD_HOTPLUG_LONG_DETECT;
case PORT_E:
return val & PORTE_HOTPLUG_LONG_DETECT;
default: default:
return false; return false;
} }
...@@ -1752,7 +1761,12 @@ static void cpt_irq_handler(struct drm_device *dev, u32 pch_iir) ...@@ -1752,7 +1761,12 @@ static void cpt_irq_handler(struct drm_device *dev, u32 pch_iir)
{ {
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
int pipe; int pipe;
u32 hotplug_trigger = pch_iir & SDE_HOTPLUG_MASK_CPT; u32 hotplug_trigger;
if (HAS_PCH_SPT(dev))
hotplug_trigger = pch_iir & SDE_HOTPLUG_MASK_SPT;
else
hotplug_trigger = pch_iir & SDE_HOTPLUG_MASK_CPT;
if (hotplug_trigger) { if (hotplug_trigger) {
u32 dig_hotplug_reg, pin_mask, long_mask; u32 dig_hotplug_reg, pin_mask, long_mask;
...@@ -1760,9 +1774,23 @@ static void cpt_irq_handler(struct drm_device *dev, u32 pch_iir) ...@@ -1760,9 +1774,23 @@ static void cpt_irq_handler(struct drm_device *dev, u32 pch_iir)
dig_hotplug_reg = I915_READ(PCH_PORT_HOTPLUG); dig_hotplug_reg = I915_READ(PCH_PORT_HOTPLUG);
I915_WRITE(PCH_PORT_HOTPLUG, dig_hotplug_reg); I915_WRITE(PCH_PORT_HOTPLUG, dig_hotplug_reg);
intel_get_hpd_pins(&pin_mask, &long_mask, hotplug_trigger, if (HAS_PCH_SPT(dev)) {
dig_hotplug_reg, hpd_cpt, intel_get_hpd_pins(&pin_mask, &long_mask,
pch_port_hotplug_long_detect); hotplug_trigger,
dig_hotplug_reg, hpd_spt,
pch_port_hotplug_long_detect);
/* detect PORTE HP event */
dig_hotplug_reg = I915_READ(PCH_PORT_HOTPLUG2);
if (pch_port_hotplug_long_detect(PORT_E,
dig_hotplug_reg))
long_mask |= 1 << HPD_PORT_E;
} else
intel_get_hpd_pins(&pin_mask, &long_mask,
hotplug_trigger,
dig_hotplug_reg, hpd_cpt,
pch_port_hotplug_long_detect);
intel_hpd_irq_handler(dev, pin_mask, long_mask); intel_hpd_irq_handler(dev, pin_mask, long_mask);
} }
...@@ -2984,6 +3012,11 @@ static void ibx_hpd_irq_setup(struct drm_device *dev) ...@@ -2984,6 +3012,11 @@ static void ibx_hpd_irq_setup(struct drm_device *dev)
for_each_intel_encoder(dev, intel_encoder) for_each_intel_encoder(dev, intel_encoder)
if (dev_priv->hotplug.stats[intel_encoder->hpd_pin].state == HPD_ENABLED) if (dev_priv->hotplug.stats[intel_encoder->hpd_pin].state == HPD_ENABLED)
enabled_irqs |= hpd_ibx[intel_encoder->hpd_pin]; enabled_irqs |= hpd_ibx[intel_encoder->hpd_pin];
} else if (HAS_PCH_SPT(dev)) {
hotplug_irqs = SDE_HOTPLUG_MASK_SPT;
for_each_intel_encoder(dev, intel_encoder)
if (dev_priv->hotplug.stats[intel_encoder->hpd_pin].state == HPD_ENABLED)
enabled_irqs |= hpd_spt[intel_encoder->hpd_pin];
} else { } else {
hotplug_irqs = SDE_HOTPLUG_MASK_CPT; hotplug_irqs = SDE_HOTPLUG_MASK_CPT;
for_each_intel_encoder(dev, intel_encoder) for_each_intel_encoder(dev, intel_encoder)
...@@ -3005,6 +3038,13 @@ static void ibx_hpd_irq_setup(struct drm_device *dev) ...@@ -3005,6 +3038,13 @@ static void ibx_hpd_irq_setup(struct drm_device *dev)
hotplug |= PORTC_HOTPLUG_ENABLE | PORTC_PULSE_DURATION_2ms; hotplug |= PORTC_HOTPLUG_ENABLE | PORTC_PULSE_DURATION_2ms;
hotplug |= PORTB_HOTPLUG_ENABLE | PORTB_PULSE_DURATION_2ms; hotplug |= PORTB_HOTPLUG_ENABLE | PORTB_PULSE_DURATION_2ms;
I915_WRITE(PCH_PORT_HOTPLUG, hotplug); I915_WRITE(PCH_PORT_HOTPLUG, hotplug);
/* enable SPT PORTE hot plug */
if (HAS_PCH_SPT(dev)) {
hotplug = I915_READ(PCH_PORT_HOTPLUG2);
hotplug |= PORTE_HOTPLUG_ENABLE;
I915_WRITE(PCH_PORT_HOTPLUG2, hotplug);
}
} }
static void bxt_hpd_irq_setup(struct drm_device *dev) static void bxt_hpd_irq_setup(struct drm_device *dev)
......
...@@ -5949,6 +5949,7 @@ enum skl_disp_power_wells { ...@@ -5949,6 +5949,7 @@ enum skl_disp_power_wells {
#define SDE_AUXC_CPT (1 << 26) #define SDE_AUXC_CPT (1 << 26)
#define SDE_AUXB_CPT (1 << 25) #define SDE_AUXB_CPT (1 << 25)
#define SDE_AUX_MASK_CPT (7 << 25) #define SDE_AUX_MASK_CPT (7 << 25)
#define SDE_PORTE_HOTPLUG_SPT (1 << 25)
#define SDE_PORTD_HOTPLUG_CPT (1 << 23) #define SDE_PORTD_HOTPLUG_CPT (1 << 23)
#define SDE_PORTC_HOTPLUG_CPT (1 << 22) #define SDE_PORTC_HOTPLUG_CPT (1 << 22)
#define SDE_PORTB_HOTPLUG_CPT (1 << 21) #define SDE_PORTB_HOTPLUG_CPT (1 << 21)
...@@ -5959,6 +5960,10 @@ enum skl_disp_power_wells { ...@@ -5959,6 +5960,10 @@ enum skl_disp_power_wells {
SDE_PORTD_HOTPLUG_CPT | \ SDE_PORTD_HOTPLUG_CPT | \
SDE_PORTC_HOTPLUG_CPT | \ SDE_PORTC_HOTPLUG_CPT | \
SDE_PORTB_HOTPLUG_CPT) SDE_PORTB_HOTPLUG_CPT)
#define SDE_HOTPLUG_MASK_SPT (SDE_PORTE_HOTPLUG_SPT | \
SDE_PORTD_HOTPLUG_CPT | \
SDE_PORTC_HOTPLUG_CPT | \
SDE_PORTB_HOTPLUG_CPT)
#define SDE_GMBUS_CPT (1 << 17) #define SDE_GMBUS_CPT (1 << 17)
#define SDE_ERROR_CPT (1 << 16) #define SDE_ERROR_CPT (1 << 16)
#define SDE_AUDIO_CP_REQ_C_CPT (1 << 10) #define SDE_AUDIO_CP_REQ_C_CPT (1 << 10)
...@@ -6030,6 +6035,13 @@ enum skl_disp_power_wells { ...@@ -6030,6 +6035,13 @@ enum skl_disp_power_wells {
#define PORTB_HOTPLUG_SHORT_DETECT (1 << 0) #define PORTB_HOTPLUG_SHORT_DETECT (1 << 0)
#define PORTB_HOTPLUG_LONG_DETECT (2 << 0) #define PORTB_HOTPLUG_LONG_DETECT (2 << 0)
#define PCH_PORT_HOTPLUG2 0xc403C /* SHOTPLUG_CTL2 */
#define PORTE_HOTPLUG_ENABLE (1 << 4)
#define PORTE_HOTPLUG_STATUS_MASK (0x3 << 0)
#define PORTE_HOTPLUG_NO_DETECT (0 << 0)
#define PORTE_HOTPLUG_SHORT_DETECT (1 << 0)
#define PORTE_HOTPLUG_LONG_DETECT (2 << 0)
#define PCH_GPIOA 0xc5010 #define PCH_GPIOA 0xc5010
#define PCH_GPIOB 0xc5014 #define PCH_GPIOB 0xc5014
#define PCH_GPIOC 0xc5018 #define PCH_GPIOC 0xc5018
......
...@@ -401,7 +401,7 @@ parse_sdvo_device_mapping(struct drm_i915_private *dev_priv, ...@@ -401,7 +401,7 @@ parse_sdvo_device_mapping(struct drm_i915_private *dev_priv,
{ {
struct sdvo_device_mapping *p_mapping; struct sdvo_device_mapping *p_mapping;
const struct bdb_general_definitions *p_defs; const struct bdb_general_definitions *p_defs;
const union child_device_config *p_child; const struct old_child_dev_config *child; /* legacy */
int i, child_device_num, count; int i, child_device_num, count;
u16 block_size; u16 block_size;
...@@ -410,14 +410,14 @@ parse_sdvo_device_mapping(struct drm_i915_private *dev_priv, ...@@ -410,14 +410,14 @@ parse_sdvo_device_mapping(struct drm_i915_private *dev_priv,
DRM_DEBUG_KMS("No general definition block is found, unable to construct sdvo mapping.\n"); DRM_DEBUG_KMS("No general definition block is found, unable to construct sdvo mapping.\n");
return; return;
} }
/* judge whether the size of child device meets the requirements.
* If the child device size obtained from general definition block /*
* is different with sizeof(struct child_device_config), skip the * Only parse SDVO mappings when the general definitions block child
* parsing of sdvo device info * device size matches that of the *legacy* child device config
* struct. Thus, SDVO mapping will be skipped for newer VBT.
*/ */
if (p_defs->child_dev_size != sizeof(*p_child)) { if (p_defs->child_dev_size != sizeof(*child)) {
/* different child dev size . Ignore it */ DRM_DEBUG_KMS("Unsupported child device size for SDVO mapping.\n");
DRM_DEBUG_KMS("different child size is found. Invalid.\n");
return; return;
} }
/* get the block size of general definitions */ /* get the block size of general definitions */
...@@ -427,37 +427,37 @@ parse_sdvo_device_mapping(struct drm_i915_private *dev_priv, ...@@ -427,37 +427,37 @@ parse_sdvo_device_mapping(struct drm_i915_private *dev_priv,
p_defs->child_dev_size; p_defs->child_dev_size;
count = 0; count = 0;
for (i = 0; i < child_device_num; i++) { for (i = 0; i < child_device_num; i++) {
p_child = child_device_ptr(p_defs, i); child = &child_device_ptr(p_defs, i)->old;
if (!p_child->old.device_type) { if (!child->device_type) {
/* skip the device block if device type is invalid */ /* skip the device block if device type is invalid */
continue; continue;
} }
if (p_child->old.slave_addr != SLAVE_ADDR1 && if (child->slave_addr != SLAVE_ADDR1 &&
p_child->old.slave_addr != SLAVE_ADDR2) { child->slave_addr != SLAVE_ADDR2) {
/* /*
* If the slave address is neither 0x70 nor 0x72, * If the slave address is neither 0x70 nor 0x72,
* it is not a SDVO device. Skip it. * it is not a SDVO device. Skip it.
*/ */
continue; continue;
} }
if (p_child->old.dvo_port != DEVICE_PORT_DVOB && if (child->dvo_port != DEVICE_PORT_DVOB &&
p_child->old.dvo_port != DEVICE_PORT_DVOC) { child->dvo_port != DEVICE_PORT_DVOC) {
/* skip the incorrect SDVO port */ /* skip the incorrect SDVO port */
DRM_DEBUG_KMS("Incorrect SDVO port. Skip it\n"); DRM_DEBUG_KMS("Incorrect SDVO port. Skip it\n");
continue; continue;
} }
DRM_DEBUG_KMS("the SDVO device with slave addr %2x is found on" DRM_DEBUG_KMS("the SDVO device with slave addr %2x is found on"
" %s port\n", " %s port\n",
p_child->old.slave_addr, child->slave_addr,
(p_child->old.dvo_port == DEVICE_PORT_DVOB) ? (child->dvo_port == DEVICE_PORT_DVOB) ?
"SDVOB" : "SDVOC"); "SDVOB" : "SDVOC");
p_mapping = &(dev_priv->sdvo_mappings[p_child->old.dvo_port - 1]); p_mapping = &(dev_priv->sdvo_mappings[child->dvo_port - 1]);
if (!p_mapping->initialized) { if (!p_mapping->initialized) {
p_mapping->dvo_port = p_child->old.dvo_port; p_mapping->dvo_port = child->dvo_port;
p_mapping->slave_addr = p_child->old.slave_addr; p_mapping->slave_addr = child->slave_addr;
p_mapping->dvo_wiring = p_child->old.dvo_wiring; p_mapping->dvo_wiring = child->dvo_wiring;
p_mapping->ddc_pin = p_child->old.ddc_pin; p_mapping->ddc_pin = child->ddc_pin;
p_mapping->i2c_pin = p_child->old.i2c_pin; p_mapping->i2c_pin = child->i2c_pin;
p_mapping->initialized = 1; p_mapping->initialized = 1;
DRM_DEBUG_KMS("SDVO device: dvo=%x, addr=%x, wiring=%d, ddc_pin=%d, i2c_pin=%d\n", DRM_DEBUG_KMS("SDVO device: dvo=%x, addr=%x, wiring=%d, ddc_pin=%d, i2c_pin=%d\n",
p_mapping->dvo_port, p_mapping->dvo_port,
...@@ -469,7 +469,7 @@ parse_sdvo_device_mapping(struct drm_i915_private *dev_priv, ...@@ -469,7 +469,7 @@ parse_sdvo_device_mapping(struct drm_i915_private *dev_priv,
DRM_DEBUG_KMS("Maybe one SDVO port is shared by " DRM_DEBUG_KMS("Maybe one SDVO port is shared by "
"two SDVO device.\n"); "two SDVO device.\n");
} }
if (p_child->old.slave2_addr) { if (child->slave2_addr) {
/* Maybe this is a SDVO device with multiple inputs */ /* Maybe this is a SDVO device with multiple inputs */
/* And the mapping info is not added */ /* And the mapping info is not added */
DRM_DEBUG_KMS("there exists the slave2_addr. Maybe this" DRM_DEBUG_KMS("there exists the slave2_addr. Maybe this"
...@@ -1051,17 +1051,39 @@ parse_device_mapping(struct drm_i915_private *dev_priv, ...@@ -1051,17 +1051,39 @@ parse_device_mapping(struct drm_i915_private *dev_priv,
const union child_device_config *p_child; const union child_device_config *p_child;
union child_device_config *child_dev_ptr; union child_device_config *child_dev_ptr;
int i, child_device_num, count; int i, child_device_num, count;
u16 block_size; u8 expected_size;
u16 block_size;
p_defs = find_section(bdb, BDB_GENERAL_DEFINITIONS); p_defs = find_section(bdb, BDB_GENERAL_DEFINITIONS);
if (!p_defs) { if (!p_defs) {
DRM_DEBUG_KMS("No general definition block is found, no devices defined.\n"); DRM_DEBUG_KMS("No general definition block is found, no devices defined.\n");
return; return;
} }
if (p_defs->child_dev_size < sizeof(*p_child)) { if (bdb->version < 195) {
DRM_ERROR("General definiton block child device size is too small.\n"); expected_size = sizeof(struct old_child_dev_config);
} else if (bdb->version == 195) {
expected_size = 37;
} else if (bdb->version <= 197) {
expected_size = 38;
} else {
expected_size = 38;
BUILD_BUG_ON(sizeof(*p_child) < 38);
DRM_DEBUG_DRIVER("Expected child device config size for VBT version %u not known; assuming %u\n",
bdb->version, expected_size);
}
/* The legacy sized child device config is the minimum we need. */
if (p_defs->child_dev_size < sizeof(struct old_child_dev_config)) {
DRM_ERROR("Child device config size %u is too small.\n",
p_defs->child_dev_size);
return; return;
} }
/* Flag an error for unexpected size, but continue anyway. */
if (p_defs->child_dev_size != expected_size)
DRM_ERROR("Unexpected child device config size %u (expected %u for VBT version %u)\n",
p_defs->child_dev_size, expected_size, bdb->version);
/* get the block size of general definitions */ /* get the block size of general definitions */
block_size = get_blocksize(p_defs); block_size = get_blocksize(p_defs);
/* get the number of child device */ /* get the number of child device */
...@@ -1106,7 +1128,14 @@ parse_device_mapping(struct drm_i915_private *dev_priv, ...@@ -1106,7 +1128,14 @@ parse_device_mapping(struct drm_i915_private *dev_priv,
child_dev_ptr = dev_priv->vbt.child_dev + count; child_dev_ptr = dev_priv->vbt.child_dev + count;
count++; count++;
memcpy(child_dev_ptr, p_child, sizeof(*p_child));
/*
* Copy as much as we know (sizeof) and is available
* (child_dev_size) of the child device. Accessing the data must
* depend on VBT version.
*/
memcpy(child_dev_ptr, p_child,
min_t(size_t, p_defs->child_dev_size, sizeof(*p_child)));
} }
return; return;
} }
......
...@@ -203,9 +203,11 @@ struct bdb_general_features { ...@@ -203,9 +203,11 @@ struct bdb_general_features {
#define DEVICE_PORT_DVOB 0x01 #define DEVICE_PORT_DVOB 0x01
#define DEVICE_PORT_DVOC 0x02 #define DEVICE_PORT_DVOC 0x02
/* We used to keep this struct but without any version control. We should avoid /*
* We used to keep this struct but without any version control. We should avoid
* using it in the future, but it should be safe to keep using it in the old * using it in the future, but it should be safe to keep using it in the old
* code. */ * code. Do not change; we rely on its size.
*/
struct old_child_dev_config { struct old_child_dev_config {
u16 handle; u16 handle;
u16 device_type; u16 device_type;
......
...@@ -128,7 +128,7 @@ static const struct ddi_buf_trans bdw_ddi_translations_hdmi[] = { ...@@ -128,7 +128,7 @@ static const struct ddi_buf_trans bdw_ddi_translations_hdmi[] = {
{ 0x80FFFFFF, 0x001B0002, 0x0 },/* 9: 1000 1000 0 */ { 0x80FFFFFF, 0x001B0002, 0x0 },/* 9: 1000 1000 0 */
}; };
/* Skylake H, S, and Skylake Y with 0.95V VccIO */ /* Skylake H and S */
static const struct ddi_buf_trans skl_ddi_translations_dp[] = { static const struct ddi_buf_trans skl_ddi_translations_dp[] = {
{ 0x00002016, 0x000000A0, 0x0 }, { 0x00002016, 0x000000A0, 0x0 },
{ 0x00005012, 0x0000009B, 0x0 }, { 0x00005012, 0x0000009B, 0x0 },
...@@ -143,23 +143,23 @@ static const struct ddi_buf_trans skl_ddi_translations_dp[] = { ...@@ -143,23 +143,23 @@ static const struct ddi_buf_trans skl_ddi_translations_dp[] = {
/* Skylake U */ /* Skylake U */
static const struct ddi_buf_trans skl_u_ddi_translations_dp[] = { static const struct ddi_buf_trans skl_u_ddi_translations_dp[] = {
{ 0x00002016, 0x000000A2, 0x0 }, { 0x0000201B, 0x000000A2, 0x0 },
{ 0x00005012, 0x00000088, 0x0 }, { 0x00005012, 0x00000088, 0x0 },
{ 0x00007011, 0x00000087, 0x0 }, { 0x00007011, 0x00000087, 0x0 },
{ 0x80009010, 0x000000C7, 0x1 }, /* Uses I_boost */ { 0x80009010, 0x000000C7, 0x1 }, /* Uses I_boost level 0x1 */
{ 0x00002016, 0x0000009D, 0x0 }, { 0x0000201B, 0x0000009D, 0x0 },
{ 0x00005012, 0x000000C7, 0x0 }, { 0x00005012, 0x000000C7, 0x0 },
{ 0x00007011, 0x000000C7, 0x0 }, { 0x00007011, 0x000000C7, 0x0 },
{ 0x00002016, 0x00000088, 0x0 }, { 0x00002016, 0x00000088, 0x0 },
{ 0x00005012, 0x000000C7, 0x0 }, { 0x00005012, 0x000000C7, 0x0 },
}; };
/* Skylake Y with 0.85V VccIO */ /* Skylake Y */
static const struct ddi_buf_trans skl_y_085v_ddi_translations_dp[] = { static const struct ddi_buf_trans skl_y_ddi_translations_dp[] = {
{ 0x00000018, 0x000000A2, 0x0 }, { 0x00000018, 0x000000A2, 0x0 },
{ 0x00005012, 0x00000088, 0x0 }, { 0x00005012, 0x00000088, 0x0 },
{ 0x00007011, 0x00000087, 0x0 }, { 0x00007011, 0x00000087, 0x0 },
{ 0x80009010, 0x000000C7, 0x1 }, /* Uses I_boost */ { 0x80009010, 0x000000C7, 0x3 }, /* Uses I_boost level 0x3 */
{ 0x00000018, 0x0000009D, 0x0 }, { 0x00000018, 0x0000009D, 0x0 },
{ 0x00005012, 0x000000C7, 0x0 }, { 0x00005012, 0x000000C7, 0x0 },
{ 0x00007011, 0x000000C7, 0x0 }, { 0x00007011, 0x000000C7, 0x0 },
...@@ -168,7 +168,7 @@ static const struct ddi_buf_trans skl_y_085v_ddi_translations_dp[] = { ...@@ -168,7 +168,7 @@ static const struct ddi_buf_trans skl_y_085v_ddi_translations_dp[] = {
}; };
/* /*
* Skylake H and S, and Skylake Y with 0.95V VccIO * Skylake H and S
* eDP 1.4 low vswing translation parameters * eDP 1.4 low vswing translation parameters
*/ */
static const struct ddi_buf_trans skl_ddi_translations_edp[] = { static const struct ddi_buf_trans skl_ddi_translations_edp[] = {
...@@ -202,10 +202,10 @@ static const struct ddi_buf_trans skl_u_ddi_translations_edp[] = { ...@@ -202,10 +202,10 @@ static const struct ddi_buf_trans skl_u_ddi_translations_edp[] = {
}; };
/* /*
* Skylake Y with 0.95V VccIO * Skylake Y
* eDP 1.4 low vswing translation parameters * eDP 1.4 low vswing translation parameters
*/ */
static const struct ddi_buf_trans skl_y_085v_ddi_translations_edp[] = { static const struct ddi_buf_trans skl_y_ddi_translations_edp[] = {
{ 0x00000018, 0x000000A8, 0x0 }, { 0x00000018, 0x000000A8, 0x0 },
{ 0x00004013, 0x000000AB, 0x0 }, { 0x00004013, 0x000000AB, 0x0 },
{ 0x00007011, 0x000000A4, 0x0 }, { 0x00007011, 0x000000A4, 0x0 },
...@@ -218,7 +218,7 @@ static const struct ddi_buf_trans skl_y_085v_ddi_translations_edp[] = { ...@@ -218,7 +218,7 @@ static const struct ddi_buf_trans skl_y_085v_ddi_translations_edp[] = {
{ 0x00000018, 0x0000008A, 0x0 }, { 0x00000018, 0x0000008A, 0x0 },
}; };
/* Skylake H, S and U, and Skylake Y with 0.95V VccIO */ /* Skylake U, H and S */
static const struct ddi_buf_trans skl_ddi_translations_hdmi[] = { static const struct ddi_buf_trans skl_ddi_translations_hdmi[] = {
{ 0x00000018, 0x000000AC, 0x0 }, { 0x00000018, 0x000000AC, 0x0 },
{ 0x00005012, 0x0000009D, 0x0 }, { 0x00005012, 0x0000009D, 0x0 },
...@@ -233,8 +233,8 @@ static const struct ddi_buf_trans skl_ddi_translations_hdmi[] = { ...@@ -233,8 +233,8 @@ static const struct ddi_buf_trans skl_ddi_translations_hdmi[] = {
{ 0x00000018, 0x000000C7, 0x0 }, { 0x00000018, 0x000000C7, 0x0 },
}; };
/* Skylake Y with 0.85V VccIO */ /* Skylake Y */
static const struct ddi_buf_trans skl_y_085v_ddi_translations_hdmi[] = { static const struct ddi_buf_trans skl_y_ddi_translations_hdmi[] = {
{ 0x00000018, 0x000000A1, 0x0 }, { 0x00000018, 0x000000A1, 0x0 },
{ 0x00005012, 0x000000DF, 0x0 }, { 0x00005012, 0x000000DF, 0x0 },
{ 0x00007011, 0x00000084, 0x0 }, { 0x00007011, 0x00000084, 0x0 },
...@@ -244,7 +244,7 @@ static const struct ddi_buf_trans skl_y_085v_ddi_translations_hdmi[] = { ...@@ -244,7 +244,7 @@ static const struct ddi_buf_trans skl_y_085v_ddi_translations_hdmi[] = {
{ 0x00006013, 0x000000C7, 0x0 }, { 0x00006013, 0x000000C7, 0x0 },
{ 0x00000018, 0x0000008A, 0x0 }, { 0x00000018, 0x0000008A, 0x0 },
{ 0x00003015, 0x000000C7, 0x0 }, /* Default */ { 0x00003015, 0x000000C7, 0x0 }, /* Default */
{ 0x80003015, 0x000000C7, 0x7 }, /* Uses I_boost */ { 0x80003015, 0x000000C7, 0x7 }, /* Uses I_boost level 0x7 */
{ 0x00000018, 0x000000C7, 0x0 }, { 0x00000018, 0x000000C7, 0x0 },
}; };
...@@ -335,19 +335,11 @@ intel_dig_port_supports_hdmi(const struct intel_digital_port *intel_dig_port) ...@@ -335,19 +335,11 @@ intel_dig_port_supports_hdmi(const struct intel_digital_port *intel_dig_port)
static const struct ddi_buf_trans *skl_get_buf_trans_dp(struct drm_device *dev, static const struct ddi_buf_trans *skl_get_buf_trans_dp(struct drm_device *dev,
int *n_entries) int *n_entries)
{ {
struct drm_i915_private *dev_priv = dev->dev_private;
const struct ddi_buf_trans *ddi_translations; const struct ddi_buf_trans *ddi_translations;
static int is_095v = -1;
if (is_095v == -1) {
u32 spr1 = I915_READ(UAIMI_SPR1);
is_095v = spr1 & SKL_VCCIO_MASK;
}
if (IS_SKL_ULX(dev) && !is_095v) { if (IS_SKL_ULX(dev)) {
ddi_translations = skl_y_085v_ddi_translations_dp; ddi_translations = skl_y_ddi_translations_dp;
*n_entries = ARRAY_SIZE(skl_y_085v_ddi_translations_dp); *n_entries = ARRAY_SIZE(skl_y_ddi_translations_dp);
} else if (IS_SKL_ULT(dev)) { } else if (IS_SKL_ULT(dev)) {
ddi_translations = skl_u_ddi_translations_dp; ddi_translations = skl_u_ddi_translations_dp;
*n_entries = ARRAY_SIZE(skl_u_ddi_translations_dp); *n_entries = ARRAY_SIZE(skl_u_ddi_translations_dp);
...@@ -364,23 +356,14 @@ static const struct ddi_buf_trans *skl_get_buf_trans_edp(struct drm_device *dev, ...@@ -364,23 +356,14 @@ static const struct ddi_buf_trans *skl_get_buf_trans_edp(struct drm_device *dev,
{ {
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
const struct ddi_buf_trans *ddi_translations; const struct ddi_buf_trans *ddi_translations;
static int is_095v = -1;
if (is_095v == -1) {
u32 spr1 = I915_READ(UAIMI_SPR1);
is_095v = spr1 & SKL_VCCIO_MASK; if (IS_SKL_ULX(dev)) {
}
if (IS_SKL_ULX(dev) && !is_095v) {
if (dev_priv->edp_low_vswing) { if (dev_priv->edp_low_vswing) {
ddi_translations = skl_y_085v_ddi_translations_edp; ddi_translations = skl_y_ddi_translations_edp;
*n_entries = *n_entries = ARRAY_SIZE(skl_y_ddi_translations_edp);
ARRAY_SIZE(skl_y_085v_ddi_translations_edp);
} else { } else {
ddi_translations = skl_y_085v_ddi_translations_dp; ddi_translations = skl_y_ddi_translations_dp;
*n_entries = *n_entries = ARRAY_SIZE(skl_y_ddi_translations_dp);
ARRAY_SIZE(skl_y_085v_ddi_translations_dp);
} }
} else if (IS_SKL_ULT(dev)) { } else if (IS_SKL_ULT(dev)) {
if (dev_priv->edp_low_vswing) { if (dev_priv->edp_low_vswing) {
...@@ -407,19 +390,11 @@ static const struct ddi_buf_trans * ...@@ -407,19 +390,11 @@ static const struct ddi_buf_trans *
skl_get_buf_trans_hdmi(struct drm_device *dev, skl_get_buf_trans_hdmi(struct drm_device *dev,
int *n_entries) int *n_entries)
{ {
struct drm_i915_private *dev_priv = dev->dev_private;
const struct ddi_buf_trans *ddi_translations; const struct ddi_buf_trans *ddi_translations;
static int is_095v = -1;
if (is_095v == -1) {
u32 spr1 = I915_READ(UAIMI_SPR1);
is_095v = spr1 & SKL_VCCIO_MASK;
}
if (IS_SKL_ULX(dev) && !is_095v) { if (IS_SKL_ULX(dev)) {
ddi_translations = skl_y_085v_ddi_translations_hdmi; ddi_translations = skl_y_ddi_translations_hdmi;
*n_entries = ARRAY_SIZE(skl_y_085v_ddi_translations_hdmi); *n_entries = ARRAY_SIZE(skl_y_ddi_translations_hdmi);
} else { } else {
ddi_translations = skl_ddi_translations_hdmi; ddi_translations = skl_ddi_translations_hdmi;
*n_entries = ARRAY_SIZE(skl_ddi_translations_hdmi); *n_entries = ARRAY_SIZE(skl_ddi_translations_hdmi);
......
...@@ -1098,6 +1098,9 @@ bool ibx_digital_port_connected(struct drm_i915_private *dev_priv, ...@@ -1098,6 +1098,9 @@ bool ibx_digital_port_connected(struct drm_i915_private *dev_priv,
case PORT_D: case PORT_D:
bit = SDE_PORTD_HOTPLUG_CPT; bit = SDE_PORTD_HOTPLUG_CPT;
break; break;
case PORT_E:
bit = SDE_PORTE_HOTPLUG_SPT;
break;
default: default:
return true; return true;
} }
......
...@@ -1223,21 +1223,24 @@ static bool intel_dp_source_supports_hbr2(struct drm_device *dev) ...@@ -1223,21 +1223,24 @@ static bool intel_dp_source_supports_hbr2(struct drm_device *dev)
static int static int
intel_dp_source_rates(struct drm_device *dev, const int **source_rates) intel_dp_source_rates(struct drm_device *dev, const int **source_rates)
{ {
int size;
if (IS_BROXTON(dev)) { if (IS_BROXTON(dev)) {
*source_rates = bxt_rates; *source_rates = bxt_rates;
return ARRAY_SIZE(bxt_rates); size = ARRAY_SIZE(bxt_rates);
} else if (IS_SKYLAKE(dev)) { } else if (IS_SKYLAKE(dev)) {
*source_rates = skl_rates; *source_rates = skl_rates;
return ARRAY_SIZE(skl_rates); size = ARRAY_SIZE(skl_rates);
} else {
*source_rates = default_rates;
size = ARRAY_SIZE(default_rates);
} }
*source_rates = default_rates;
/* This depends on the fact that 5.4 is last value in the array */ /* This depends on the fact that 5.4 is last value in the array */
if (intel_dp_source_supports_hbr2(dev)) if (!intel_dp_source_supports_hbr2(dev))
return (DP_LINK_BW_5_4 >> 3) + 1; size--;
else
return (DP_LINK_BW_2_7 >> 3) + 1; return size;
} }
static void static void
...@@ -5857,6 +5860,9 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port, ...@@ -5857,6 +5860,9 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
case PORT_D: case PORT_D:
intel_encoder->hpd_pin = HPD_PORT_D; intel_encoder->hpd_pin = HPD_PORT_D;
break; break;
case PORT_E:
intel_encoder->hpd_pin = HPD_PORT_E;
break;
default: default:
BUG(); BUG();
} }
......
...@@ -91,6 +91,9 @@ bool intel_hpd_pin_to_port(enum hpd_pin pin, enum port *port) ...@@ -91,6 +91,9 @@ bool intel_hpd_pin_to_port(enum hpd_pin pin, enum port *port)
case HPD_PORT_D: case HPD_PORT_D:
*port = PORT_D; *port = PORT_D;
return true; return true;
case HPD_PORT_E:
*port = PORT_E;
return true;
default: default:
return false; /* no hpd */ return false; /* no hpd */
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment