mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-18 00:24:58 +08:00
drm/i915: Per-DDI I_boost override
An OEM may request increased I_boost beyond the recommended values by specifying an I_boost value to be applied to all swing entries for a port. These override values are specified in VBT. v2: rebase and remove unused iboost_bit variable Issue: VIZ-5676 Signed-off-by: Antti Koskipaa <antti.koskipaa@linux.intel.com> Reviewed-by: David Weinehall <david.weinehall@linux.intel.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
This commit is contained in:
parent
622147fdad
commit
75067ddecf
@ -1429,6 +1429,9 @@ struct ddi_vbt_port_info {
|
||||
uint8_t supports_dp:1;
|
||||
|
||||
uint8_t alternate_aux_channel;
|
||||
|
||||
uint8_t dp_boost_level;
|
||||
uint8_t hdmi_boost_level;
|
||||
};
|
||||
|
||||
enum psr_lines_to_wait {
|
||||
|
@ -886,6 +886,17 @@ err:
|
||||
memset(dev_priv->vbt.dsi.sequence, 0, sizeof(dev_priv->vbt.dsi.sequence));
|
||||
}
|
||||
|
||||
static u8 translate_iboost(u8 val)
|
||||
{
|
||||
static const u8 mapping[] = { 1, 3, 7 }; /* See VBT spec */
|
||||
|
||||
if (val >= ARRAY_SIZE(mapping)) {
|
||||
DRM_DEBUG_KMS("Unsupported I_boost value found in VBT (%d), display may not work properly\n", val);
|
||||
return 0;
|
||||
}
|
||||
return mapping[val];
|
||||
}
|
||||
|
||||
static void parse_ddi_port(struct drm_i915_private *dev_priv, enum port port,
|
||||
const struct bdb_header *bdb)
|
||||
{
|
||||
@ -1001,6 +1012,16 @@ static void parse_ddi_port(struct drm_i915_private *dev_priv, enum port port,
|
||||
hdmi_level_shift);
|
||||
info->hdmi_level_shift = hdmi_level_shift;
|
||||
}
|
||||
|
||||
/* Parse the I_boost config for SKL and above */
|
||||
if (bdb->version >= 196 && (child->common.flags_1 & IBOOST_ENABLE)) {
|
||||
info->dp_boost_level = translate_iboost(child->common.iboost_level & 0xF);
|
||||
DRM_DEBUG_KMS("VBT (e)DP boost level for port %c: %d\n",
|
||||
port_name(port), info->dp_boost_level);
|
||||
info->hdmi_boost_level = translate_iboost(child->common.iboost_level >> 4);
|
||||
DRM_DEBUG_KMS("VBT HDMI boost level for port %c: %d\n",
|
||||
port_name(port), info->hdmi_boost_level);
|
||||
}
|
||||
}
|
||||
|
||||
static void parse_ddi_ports(struct drm_i915_private *dev_priv,
|
||||
|
@ -231,6 +231,10 @@ struct old_child_dev_config {
|
||||
/* This one contains field offsets that are known to be common for all BDB
|
||||
* versions. Notice that the meaning of the contents contents may still change,
|
||||
* but at least the offsets are consistent. */
|
||||
|
||||
/* Definitions for flags_1 */
|
||||
#define IBOOST_ENABLE (1<<3)
|
||||
|
||||
struct common_child_dev_config {
|
||||
u16 handle;
|
||||
u16 device_type;
|
||||
@ -239,8 +243,13 @@ struct common_child_dev_config {
|
||||
u8 not_common2[2];
|
||||
u8 ddc_pin;
|
||||
u16 edid_ptr;
|
||||
u8 obsolete;
|
||||
u8 flags_1;
|
||||
u8 not_common3[13];
|
||||
u8 iboost_level;
|
||||
} __packed;
|
||||
|
||||
|
||||
/* This field changes depending on the BDB version, so the most reliable way to
|
||||
* read it is by checking the BDB version and reading the raw pointer. */
|
||||
union child_device_config {
|
||||
|
@ -440,6 +440,7 @@ static void intel_prepare_ddi_buffers(struct drm_device *dev, enum port port,
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
u32 reg;
|
||||
u32 iboost_bit = 0;
|
||||
int i, n_hdmi_entries, n_dp_entries, n_edp_entries, hdmi_default_entry,
|
||||
size;
|
||||
int hdmi_level = dev_priv->vbt.ddi_port_info[port].hdmi_level_shift;
|
||||
@ -466,6 +467,10 @@ static void intel_prepare_ddi_buffers(struct drm_device *dev, enum port port,
|
||||
ddi_translations_hdmi =
|
||||
skl_get_buf_trans_hdmi(dev, &n_hdmi_entries);
|
||||
hdmi_default_entry = 8;
|
||||
/* If we're boosting the current, set bit 31 of trans1 */
|
||||
if (dev_priv->vbt.ddi_port_info[port].hdmi_boost_level ||
|
||||
dev_priv->vbt.ddi_port_info[port].dp_boost_level)
|
||||
iboost_bit = 1<<31;
|
||||
} else if (IS_BROADWELL(dev)) {
|
||||
ddi_translations_fdi = bdw_ddi_translations_fdi;
|
||||
ddi_translations_dp = bdw_ddi_translations_dp;
|
||||
@ -526,7 +531,7 @@ static void intel_prepare_ddi_buffers(struct drm_device *dev, enum port port,
|
||||
}
|
||||
|
||||
for (i = 0, reg = DDI_BUF_TRANS(port); i < size; i++) {
|
||||
I915_WRITE(reg, ddi_translations[i].trans1);
|
||||
I915_WRITE(reg, ddi_translations[i].trans1 | iboost_bit);
|
||||
reg += 4;
|
||||
I915_WRITE(reg, ddi_translations[i].trans2);
|
||||
reg += 4;
|
||||
@ -541,7 +546,7 @@ static void intel_prepare_ddi_buffers(struct drm_device *dev, enum port port,
|
||||
hdmi_level = hdmi_default_entry;
|
||||
|
||||
/* Entry 9 is for HDMI: */
|
||||
I915_WRITE(reg, ddi_translations_hdmi[hdmi_level].trans1);
|
||||
I915_WRITE(reg, ddi_translations_hdmi[hdmi_level].trans1 | iboost_bit);
|
||||
reg += 4;
|
||||
I915_WRITE(reg, ddi_translations_hdmi[hdmi_level].trans2);
|
||||
reg += 4;
|
||||
@ -2078,18 +2083,35 @@ static void skl_ddi_set_iboost(struct drm_device *dev, u32 level,
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
const struct ddi_buf_trans *ddi_translations;
|
||||
uint8_t iboost;
|
||||
uint8_t dp_iboost, hdmi_iboost;
|
||||
int n_entries;
|
||||
u32 reg;
|
||||
|
||||
/* VBT may override standard boost values */
|
||||
dp_iboost = dev_priv->vbt.ddi_port_info[port].dp_boost_level;
|
||||
hdmi_iboost = dev_priv->vbt.ddi_port_info[port].hdmi_boost_level;
|
||||
|
||||
if (type == INTEL_OUTPUT_DISPLAYPORT) {
|
||||
ddi_translations = skl_get_buf_trans_dp(dev, &n_entries);
|
||||
iboost = ddi_translations[port].i_boost;
|
||||
if (dp_iboost) {
|
||||
iboost = dp_iboost;
|
||||
} else {
|
||||
ddi_translations = skl_get_buf_trans_dp(dev, &n_entries);
|
||||
iboost = ddi_translations[port].i_boost;
|
||||
}
|
||||
} else if (type == INTEL_OUTPUT_EDP) {
|
||||
ddi_translations = skl_get_buf_trans_edp(dev, &n_entries);
|
||||
iboost = ddi_translations[port].i_boost;
|
||||
if (dp_iboost) {
|
||||
iboost = dp_iboost;
|
||||
} else {
|
||||
ddi_translations = skl_get_buf_trans_edp(dev, &n_entries);
|
||||
iboost = ddi_translations[port].i_boost;
|
||||
}
|
||||
} else if (type == INTEL_OUTPUT_HDMI) {
|
||||
ddi_translations = skl_get_buf_trans_hdmi(dev, &n_entries);
|
||||
iboost = ddi_translations[port].i_boost;
|
||||
if (hdmi_iboost) {
|
||||
iboost = hdmi_iboost;
|
||||
} else {
|
||||
ddi_translations = skl_get_buf_trans_hdmi(dev, &n_entries);
|
||||
iboost = ddi_translations[port].i_boost;
|
||||
}
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user