/*
*/
/*
* Copyright (c) 2008, 2013, Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*
* Authors:
* Keith Packard <keithp@keithp.com>
*
*/
#include "drmP.h"
#include "drm.h"
#include "drm_crtc.h"
#include "drm_crtc_helper.h"
#include "drm_sun_i2c.h" /* OSOL_i915 */
#include "intel_drv.h"
#include "i915_drm.h"
#include "i915_drv.h"
#include "drm_dp_helper.h"
#include "drm_edid.h"
/**
* is_edp - is the given port attached to an eDP panel (either CPU or PCH)
* @intel_dp: DP struct
*
* If a CPU or PCH DP output is attached to an eDP panel, this function
* will return true, and false otherwise.
*/
{
}
{
}
{
}
static int
{
switch (max_link_bw) {
case DP_LINK_BW_1_62:
case DP_LINK_BW_2_7:
break;
case DP_LINK_BW_5_4: /* 1.2 capable displays may advertise higher bw */
break;
default:
DRM_ERROR("invalid max DP link bw val %x, using 1.62Gbps\n",
break;
}
return max_link_bw;
}
/*
* The units on the numbers in the next two are... bizarre. Examples will
* make it clearer; this one parallels an example in the eDP spec.
*
* intel_dp_max_data_rate for one lane of 2.7GHz evaluates as:
*
* 270000 * 1 * 8 / 10 == 216000
*
* The actual data capacity of that configuration is 2.16Gbit/s, so the
* units are decakilobits. ->clock in a drm_display_mode is in kilohertz -
* or equivalently, kilopixels per second - so for 1680x1050R it'd be
* 119000. At 18bpp that's 2142000 kilobits per second.
*
* Thus the strange-looking division by 10 in intel_dp_link_required, to
* get the result in decakilobits instead of kilobits.
*/
static int
{
}
static int
{
}
static int
struct drm_display_mode *mode)
{
return MODE_PANEL;
return MODE_PANEL;
}
return MODE_CLOCK_HIGH;
return MODE_CLOCK_LOW;
return MODE_H_ILLEGAL;
return MODE_OK;
}
static uint32_t
{
int i;
uint32_t v = 0;
if (src_bytes > 4)
src_bytes = 4;
for (i = 0; i < src_bytes; i++)
return v;
}
static void
{
int i;
if (dst_bytes > 4)
dst_bytes = 4;
for (i = 0; i < dst_bytes; i++)
}
/* hrawclock is 1/4 the FSB frequency */
static int
{
/* There is no CLKCFG reg in Valleyview. VLV hrawclk is 200 MHz */
if (IS_VALLEYVIEW(dev))
return 200;
switch (clkcfg & CLKCFG_FSB_MASK) {
case CLKCFG_FSB_400:
return 100;
case CLKCFG_FSB_533:
return 133;
case CLKCFG_FSB_667:
return 166;
case CLKCFG_FSB_800:
return 200;
case CLKCFG_FSB_1067:
return 266;
case CLKCFG_FSB_1333:
return 333;
/* these two are just a guess; one of them might be right */
case CLKCFG_FSB_1600:
case CLKCFG_FSB_1600_ALT:
return 400;
default:
return 133;
}
}
{
}
{
}
static void
{
return;
DRM_ERROR("eDP powered off while attempting aux channel communication.");
DRM_DEBUG_KMS("Status 0x%08x Control 0x%08x\n",
}
}
static uint32_t
{
bool done;
if (has_aux_irq) {
} else {
}
if (!done)
DRM_ERROR("dp aux hw did not signal timeout (has irq: %i)!\n",
#undef C
return status;
}
static int
{
/* dp aux is extremely sensitive to irq latency, hence request the
* lowest possible wakeup latency and so prevent the cpu from going into
* deep sleep states.
*/
/* The clock divider is based off the hrawclk,
* and would like to run at 2MHz. So, take the
* hrawclk value and divide by 2 and use that
*
* Note that PCH attached eDP panels should use a 125MHz input
* clock divider.
*/
if (IS_VALLEYVIEW(dev)) {
aux_clock_divider = 100;
else
/* Workaround for non-ULT HSW */
aux_clock_divider = 74;
} else if (HAS_PCH_SPLIT(dev)) {
} else {
}
precharge = 3;
else
precharge = 5;
/* Try to wait for any previous AUX channel activity */
if ((status & DP_AUX_CH_CTL_SEND_BUSY) == 0)
break;
msleep(1);
}
if (try == 3) {
DRM_ERROR("dp_aux_ch not started status 0x%08x\n",
goto out;
}
/* Must try at least 3 times according to DP spec */
/* Load the send data into the aux channel data registers */
for (i = 0; i < send_bytes; i += 4)
I915_WRITE(ch_data + i,
/* Send the command and wait for it to complete */
(has_aux_irq ? DP_AUX_CH_CTL_INTERRUPT : 0) |
/* workaround: edp and dp doesn't work with intel_dp_aux_wait_done */
// status = intel_dp_aux_wait_done(intel_dp, has_aux_irq);
for (;;) {
if ((status & DP_AUX_CH_CTL_SEND_BUSY) == 0)
break;
udelay(100);
}
/* Clear done status and any errors */
status |
if (status & (DP_AUX_CH_CTL_TIME_OUT_ERROR |
continue;
if (status & DP_AUX_CH_CTL_DONE)
break;
}
if ((status & DP_AUX_CH_CTL_DONE) == 0) {
goto out;
}
/* Check for timeout or receive error.
* Timeouts occur when the sink is not connected
*/
if (status & DP_AUX_CH_CTL_RECEIVE_ERROR) {
goto out;
}
/* Timeouts occur when the device isn't connected, so they're
* "normal" -- don't fill the kernel log with these */
if (status & DP_AUX_CH_CTL_TIME_OUT_ERROR) {
goto out;
}
/* Unload any bytes sent back from the other side */
if (recv_bytes > recv_size)
for (i = 0; i < recv_bytes; i += 4)
recv + i, recv_bytes - i);
ret = recv_bytes;
out:
return ret;
}
/* Write data to the aux channel in native mode */
static int
{
int ret;
int msg_bytes;
if (send_bytes > 16)
return -1;
for (;;) {
if (ret < 0)
return ret;
break;
udelay(100);
else
return -EIO;
}
return send_bytes;
}
/* Write a single byte to the aux channel in native mode */
static int
{
}
/* read bytes from a native aux channel */
static int
{
int msg_bytes;
int reply_bytes;
int ret;
msg_bytes = 4;
for (;;) {
reply, reply_bytes);
if (ret == 0)
return -EPROTO;
if (ret < 0)
return ret;
return ret - 1;
}
udelay(100);
else
return -EIO;
}
}
static int
{
struct intel_dp,
adapter);
unsigned retry;
int msg_bytes;
int reply_bytes;
int ret;
/* Set up the command byte */
if (mode & MODE_I2C_READ)
else
if (!(mode & MODE_I2C_STOP))
switch (mode) {
case MODE_I2C_WRITE:
msg[3] = 0;
msg_bytes = 5;
reply_bytes = 1;
break;
case MODE_I2C_READ:
msg[3] = 0;
msg_bytes = 4;
reply_bytes = 2;
break;
default:
msg_bytes = 3;
reply_bytes = 1;
break;
}
reply, reply_bytes);
if (ret < 0) {
return ret;
}
switch (reply[0] & AUX_NATIVE_REPLY_MASK) {
case AUX_NATIVE_REPLY_ACK:
/* I2C-over-AUX Reply field is only valid
* when paired with AUX ACK.
*/
break;
case AUX_NATIVE_REPLY_NACK:
DRM_DEBUG_KMS("aux_ch native nack\n");
return -EIO;
case AUX_NATIVE_REPLY_DEFER:
udelay(100);
continue;
default:
DRM_ERROR("aux_ch invalid native reply 0x%02x\n",
reply[0]);
return -EIO;
}
switch (reply[0] & AUX_I2C_REPLY_MASK) {
case AUX_I2C_REPLY_ACK:
if (mode == MODE_I2C_READ) {
}
return reply_bytes - 1;
case AUX_I2C_REPLY_NACK:
DRM_DEBUG_KMS("aux_i2c nack\n");
return -EIO;
case AUX_I2C_REPLY_DEFER:
DRM_DEBUG_KMS("aux_i2c defer\n");
udelay(100);
break;
default:
return -EIO;
}
}
DRM_ERROR("too many retries, giving up\n");
return -EIO;
}
static int
{
int ret;
/* OSOL_i915: dp_priv->adapter.owner = THIS_MODULE; */
/* OSOL_i915: dp_priv->adapter.class = I2C_CLASS_DDC; */
/* OSOL_i915: dp_priv->adapter.dev.parent = &intel_encoder->base.kdev; */
ironlake_edp_panel_vdd_off(intel_dp, false);
return ret;
}
static void
{
if (link_bw == DP_LINK_BW_1_62) {
} else {
}
pipe_config->clock_set = true;
// } else if (IS_HASWELL(dev)) {
/* Haswell has special-purpose DP DDI clocks. */
} else if (HAS_PCH_SPLIT(dev)) {
if (link_bw == DP_LINK_BW_1_62) {
} else {
}
pipe_config->clock_set = true;
// } else if (IS_VALLEYVIEW(dev)) {
/* FIXME: Need to figure out optimized DP clocks for vlv. */
}
}
bool
struct intel_crtc_config *pipe_config)
{
pipe_config->has_pch_encoder = true;
pipe_config->has_dp_encoder = true;
if (!HAS_PCH_SPLIT(dev))
else
}
return false;
DRM_DEBUG_KMS("DP link computation with max lane count %i "
"max bw %02x pixel clock %iKHz\n",
/* Walk through all bpp values. Luckily they're all nicely spaced with 2
* bpc in between. */
if (mode_rate <= link_avail) {
goto found;
}
}
}
}
return false;
if (intel_dp->color_range_auto) {
/*
* See:
* CEA-861-E - 5.1 Default Encoding Parameters
* VESA DisplayPort Ver.1.2a - 5.1.1.1 Video Colorimetry
*/
else
intel_dp->color_range = 0;
}
if (intel_dp->color_range)
pipe_config->limited_color_range = true;
DRM_DEBUG_KMS("DP link bw %02x lane count %d clock %d bpp %d\n",
DRM_DEBUG_KMS("DP link bw required %i available %i\n",
&pipe_config->dp_m_n);
return true;
}
{
/*
* Check for DPCD version > 1.1 and enhanced framing support
*/
}
}
{
dpa_ctl &= ~DP_PLL_FREQ_MASK;
/* For a long time we've carried around a ILK-DevA w/a for the
* 160MHz clock. If we're really unlucky, it's still required.
*/
DRM_DEBUG_KMS("160MHz cpu eDP clock, might need ilk devA w/a\n");
} else {
}
udelay(500);
}
static void
/* LINTED */
struct drm_display_mode *adjusted_mode)
{
/*
* There are four kinds of DP registers:
*
* IBX PCH
* SNB CPU
* IVB CPU
* CPT PCH
*
* IBX PCH and CPU are the same for almost everything,
* except that the CPU DP PLL is configured in this
* register
*
* CPT PCH is quite different, having many bits moved
* to the TRANS_DP_CTL register instead. That
* configuration happens (oddly) in ironlake_pch_enable
*/
/* Preserve the BIOS-computed detected bit. This is
* supposed to be read-only.
*/
/* Handle DP bits in common between all three register formats */
DRM_DEBUG_DRIVER("Enabling DP audio on pipe %c\n",
}
} else {
}
}
#define IDLE_CYCLE_MASK (PP_ON | 0 | PP_SEQUENCE_MASK | PP_CYCLE_DELAY_ACTIVE | PP_SEQUENCE_STATE_MASK)
{
DRM_DEBUG_KMS("mask %08x value %08x status %08x control %08x\n",
DRM_ERROR("Panel status timeout: status %08x control %08x\n",
}
}
{
DRM_DEBUG_KMS("Wait for panel power on\n");
}
{
DRM_DEBUG_KMS("Wait for panel power off time\n");
}
{
DRM_DEBUG_KMS("Wait for panel power cycle\n");
}
/* Read the current pp_control value, unlocking the register if it
* is locked
*/
{
control &= ~PANEL_UNLOCK_MASK;
return control;
}
{
return;
DRM_DEBUG_KMS("Turn eDP VDD on\n");
if(intel_dp->want_panel_vdd)
DRM_ERROR("eDP VDD already requested on");
intel_dp->want_panel_vdd = true;
if (ironlake_edp_have_panel_vdd(intel_dp)) {
DRM_DEBUG_KMS("eDP VDD already on\n");
return;
}
pp |= EDP_FORCE_VDD;
DRM_DEBUG_KMS("PP_STATUS: 0x%08x PP_CONTROL: 0x%08x\n",
/*
* If the panel wasn't on, delay before accessing aux channel
*/
if (!ironlake_edp_have_panel_power(intel_dp)) {
DRM_DEBUG_KMS("eDP was not running\n");
}
}
{
/* fix me: crash on mode switch */
// WARN_ON(!mutex_is_locked(&dev->mode_config.mutex));
pp &= ~EDP_FORCE_VDD;
/* Make sure sequencer is idle before allowing subsequent activity */
DRM_DEBUG_KMS("PP_STATUS: 0x%08x PP_CONTROL: 0x%08x\n",
}
}
{
}
{
return;
if(!intel_dp->want_panel_vdd)
DRM_ERROR("eDP VDD not forced on");
intel_dp->want_panel_vdd = false;
if (sync) {
} else {
/*
* Queue the timer to fire a long
* time from now (relative to the power down delay)
* to keep the panel power up across a sequence of operations
*/
}
}
{
return;
DRM_DEBUG_KMS("Turn eDP power on\n");
DRM_DEBUG_KMS("eDP power already on\n");
return;
}
/* ILK workaround: disable reset around power sequence */
pp &= ~PANEL_POWER_RESET;
}
pp |= POWER_TARGET_ON;
pp |= PANEL_POWER_RESET;
}
}
{
return;
DRM_DEBUG_KMS("Turn eDP power off\n");
if(!intel_dp->want_panel_vdd)
DRM_ERROR("Need VDD to turn off panel");
intel_dp->want_panel_vdd = false;
}
{
return;
DRM_DEBUG_KMS("\n");
/*
* If we enable the backlight right away following a panel power
* on, we may see slight flicker as the panel syncs with the eDP
* link. So delay a bit to make sure the image is solid before
* allowing it to appear.
*/
pp |= EDP_BLC_ENABLE;
}
{
return;
DRM_DEBUG_KMS("\n");
pp &= ~EDP_BLC_ENABLE;
}
{
DRM_DEBUG_KMS("\n");
if (dpa_ctl & DP_PLL_ENABLE)
DRM_ERROR("dp pll on, should be off\n");
if (dpa_ctl & DP_PORT_EN)
DRM_ERROR("dp port still on, should be off\n");
/* We don't adjust intel_dp->DP while tearing down the link, to
* facilitate link retraining (e.g. after hotplug). Hence clear all
* enable bits here to ensure that we don't enable too much. */
udelay(200);
}
{
if ((dpa_ctl & DP_PLL_ENABLE) == 0)
DRM_ERROR("dp pll off, should be on\n");
if (dpa_ctl & DP_PORT_EN)
DRM_ERROR("dp port still on, should be off\n");
/* We can't rely on the value tracked for the DP register in
* intel_dp->DP because link_down must not change that (otherwise link
* re-training will fail. */
dpa_ctl &= ~DP_PLL_ENABLE;
udelay(200);
}
/* If the sink supports it, try to set the power state appropriately */
{
int ret, i;
/* Should have a valid DPCD by this point */
return;
if (mode != DRM_MODE_DPMS_ON) {
if (ret != 1)
DRM_DEBUG_DRIVER("failed to write sink power state\n");
} else {
/*
* When turning on, we need to retry for 1ms to give the sink
* time to wake up.
*/
for (i = 0; i < 3; i++) {
if (ret == 1)
break;
msleep(1);
}
}
}
{
if (!(tmp & DP_PORT_EN))
return false;
} else {
int i;
switch (intel_dp->output_reg) {
case PCH_DP_B:
break;
case PCH_DP_C:
break;
case PCH_DP_D:
break;
default:
return true;
}
for_each_pipe(i) {
*pipe = i;
return true;
}
}
DRM_DEBUG_KMS("No pipe for dp port 0x%x found\n",
}
return true;
}
struct intel_crtc_config *pipe_config)
{
if (tmp & DP_SYNC_HS_HIGH)
else
if (tmp & DP_SYNC_VS_HIGH)
else
} else {
if (tmp & TRANS_DP_HSYNC_ACTIVE_HIGH)
else
if (tmp & TRANS_DP_VSYNC_ACTIVE_HIGH)
else
}
}
{
/* Make sure the panel is off before trying to change the mode. But also
* ensure that we have vdd while we switch off the panel. */
}
{
if (!IS_VALLEYVIEW(dev))
}
}
{
if (dp_reg & DP_PORT_EN) {
DRM_ERROR("DP already enabled");
return;
}
ironlake_edp_panel_vdd_off(intel_dp, true);
if (IS_VALLEYVIEW(dev)) {
}
}
{
if (IS_VALLEYVIEW(dev)) {
val = 0;
if (pipe)
else
val |= 0x001000c4;
0x00760018);
0x00400888);
}
}
{
if (!IS_VALLEYVIEW(dev))
return;
/* Program Tx lane resets to default */
(1<<DPIO_PCS_CLK_DATAWIDTH_SHIFT) |
/* Fix up inter-pair skew failure */
}
/*
* Native read with retry for link status and receiver capability reads for
* cases where the sink may still be asleep.
*/
static bool
{
int ret, i;
/*
* Sinks are *supposed* to come up within 1ms from an off state,
* but we're also supposed to retry 3 times per the spec.
*/
for (i = 0; i < 3; i++) {
if (ret == recv_bytes)
return true;
msleep(1);
}
return false;
}
/*
* Fetch AUX CH registers 0x202 - 0x207 which contain
* link status information
*/
static bool
{
}
#if 0
static char *voltage_names[] = {
"0.4V", "0.6V", "0.8V", "1.2V"
};
static char *pre_emph_names[] = {
"0dB", "3.5dB", "6dB", "9.5dB"
};
static char *link_train_names[] = {
"pattern 1", "pattern 2", "idle", "off"
};
#endif
/*
* These are source-specific values; current Intel hardware supports
* a maximum voltage of 800mV and a maximum pre-emphasis of 6dB
*/
static uint8_t
{
if (IS_VALLEYVIEW(dev))
return DP_TRAIN_VOLTAGE_SWING_1200;
return DP_TRAIN_VOLTAGE_SWING_800;
return DP_TRAIN_VOLTAGE_SWING_1200;
else
return DP_TRAIN_VOLTAGE_SWING_800;
}
static uint8_t
{
switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) {
return DP_TRAIN_PRE_EMPHASIS_9_5;
return DP_TRAIN_PRE_EMPHASIS_6;
return DP_TRAIN_PRE_EMPHASIS_3_5;
default:
return DP_TRAIN_PRE_EMPHASIS_0;
}
} else if (IS_VALLEYVIEW(dev)) {
switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) {
return DP_TRAIN_PRE_EMPHASIS_9_5;
return DP_TRAIN_PRE_EMPHASIS_6;
return DP_TRAIN_PRE_EMPHASIS_3_5;
default:
return DP_TRAIN_PRE_EMPHASIS_0;
}
switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) {
return DP_TRAIN_PRE_EMPHASIS_6;
return DP_TRAIN_PRE_EMPHASIS_3_5;
default:
return DP_TRAIN_PRE_EMPHASIS_0;
}
} else {
switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) {
return DP_TRAIN_PRE_EMPHASIS_6;
return DP_TRAIN_PRE_EMPHASIS_6;
return DP_TRAIN_PRE_EMPHASIS_3_5;
default:
return DP_TRAIN_PRE_EMPHASIS_0;
}
}
}
{
switch (train_set & DP_TRAIN_PRE_EMPHASIS_MASK) {
case DP_TRAIN_PRE_EMPHASIS_0:
preemph_reg_value = 0x0004000;
switch (train_set & DP_TRAIN_VOLTAGE_SWING_MASK) {
demph_reg_value = 0x2B405555;
uniqtranscale_reg_value = 0x552AB83A;
break;
demph_reg_value = 0x2B404040;
uniqtranscale_reg_value = 0x5548B83A;
break;
demph_reg_value = 0x2B245555;
uniqtranscale_reg_value = 0x5560B83A;
break;
demph_reg_value = 0x2B405555;
uniqtranscale_reg_value = 0x5598DA3A;
break;
default:
return 0;
}
break;
preemph_reg_value = 0x0002000;
switch (train_set & DP_TRAIN_VOLTAGE_SWING_MASK) {
demph_reg_value = 0x2B404040;
uniqtranscale_reg_value = 0x5552B83A;
break;
demph_reg_value = 0x2B404848;
uniqtranscale_reg_value = 0x5580B83A;
break;
demph_reg_value = 0x2B404040;
uniqtranscale_reg_value = 0x55ADDA3A;
break;
default:
return 0;
}
break;
case DP_TRAIN_PRE_EMPHASIS_6:
preemph_reg_value = 0x0000000;
switch (train_set & DP_TRAIN_VOLTAGE_SWING_MASK) {
demph_reg_value = 0x2B305555;
uniqtranscale_reg_value = 0x5570B83A;
break;
demph_reg_value = 0x2B2B4040;
uniqtranscale_reg_value = 0x55ADDA3A;
break;
default:
return 0;
}
break;
preemph_reg_value = 0x0006000;
switch (train_set & DP_TRAIN_VOLTAGE_SWING_MASK) {
demph_reg_value = 0x1B405555;
uniqtranscale_reg_value = 0x55ADDA3A;
break;
default:
return 0;
}
break;
default:
return 0;
}
return 0;
}
static void
{
uint8_t v = 0;
uint8_t p = 0;
int lane;
if (this_v > v)
v = this_v;
if (this_p > p)
p = this_p;
}
if (v >= voltage_max)
if (p >= preemph_max)
}
static uint32_t
{
switch (train_set & DP_TRAIN_VOLTAGE_SWING_MASK) {
default:
break;
break;
break;
break;
}
switch (train_set & DP_TRAIN_PRE_EMPHASIS_MASK) {
case DP_TRAIN_PRE_EMPHASIS_0:
default:
break;
break;
case DP_TRAIN_PRE_EMPHASIS_6:
break;
break;
}
return signal_levels;
}
/* Gen6's DP voltage swing and pre-emphasis control */
static uint32_t
{
switch (signal_levels) {
return EDP_LINK_TRAIN_400MV_3_5DB_SNB_B;
default:
DRM_DEBUG_KMS("Unsupported voltage swing/pre-emphasis level:"
"0x%x\n", signal_levels);
}
}
/* Gen7's DP voltage swing and pre-emphasis control */
static uint32_t
{
switch (signal_levels) {
return EDP_LINK_TRAIN_400MV_0DB_IVB;
return EDP_LINK_TRAIN_400MV_3_5DB_IVB;
return EDP_LINK_TRAIN_400MV_6DB_IVB;
return EDP_LINK_TRAIN_600MV_0DB_IVB;
return EDP_LINK_TRAIN_600MV_3_5DB_IVB;
return EDP_LINK_TRAIN_800MV_0DB_IVB;
return EDP_LINK_TRAIN_800MV_3_5DB_IVB;
default:
DRM_DEBUG_KMS("Unsupported voltage swing/pre-emphasis level:"
"0x%x\n", signal_levels);
return EDP_LINK_TRAIN_500MV_0DB_IVB;
}
}
/* Gen7.5's (HSW) DP voltage swing and pre-emphasis control */
static uint32_t
{
switch (signal_levels) {
return DDI_BUF_EMP_400MV_0DB_HSW;
return DDI_BUF_EMP_400MV_3_5DB_HSW;
return DDI_BUF_EMP_400MV_6DB_HSW;
return DDI_BUF_EMP_400MV_9_5DB_HSW;
return DDI_BUF_EMP_600MV_0DB_HSW;
return DDI_BUF_EMP_600MV_3_5DB_HSW;
return DDI_BUF_EMP_600MV_6DB_HSW;
return DDI_BUF_EMP_800MV_0DB_HSW;
return DDI_BUF_EMP_800MV_3_5DB_HSW;
default:
DRM_DEBUG_KMS("Unsupported voltage swing/pre-emphasis level:"
"0x%x\n", signal_levels);
return DDI_BUF_EMP_400MV_0DB_HSW;
}
}
/* Properly updates "DP" with the correct signal levels. */
static void
{
} else if (IS_VALLEYVIEW(dev)) {
mask = 0;
} else {
}
}
static bool
{
int ret;
else
switch (dp_train_pat & DP_TRAINING_PATTERN_MASK) {
break;
case DP_TRAINING_PATTERN_1:
break;
case DP_TRAINING_PATTERN_2:
break;
case DP_TRAINING_PATTERN_3:
break;
}
switch (dp_train_pat & DP_TRAINING_PATTERN_MASK) {
break;
case DP_TRAINING_PATTERN_1:
break;
case DP_TRAINING_PATTERN_2:
break;
case DP_TRAINING_PATTERN_3:
DRM_ERROR("DP training pattern 3 not supported\n");
break;
}
} else {
switch (dp_train_pat & DP_TRAINING_PATTERN_MASK) {
break;
case DP_TRAINING_PATTERN_1:
break;
case DP_TRAINING_PATTERN_2:
break;
case DP_TRAINING_PATTERN_3:
DRM_ERROR("DP training pattern 3 not supported\n");
break;
}
}
if ((dp_train_pat & DP_TRAINING_PATTERN_MASK) !=
return false;
}
return true;
}
{
return;
/*
* On PORT_A we can have only eDP in SST mode. There the only reason
* we need to set idle transmission mode is to work around a HW issue
* where we enable the pipe while not in idle link-training mode.
* In this case there is requirement to wait for a minimum number of
* idle patterns to be sent.
*/
return;
1))
DRM_ERROR("Timed out waiting for DP idle patterns\n");
}
/* Enable corresponding port and start training pattern 1 */
void
{
int i;
/* LINTED */
bool clock_recovery = false;
/* Write the link configuration data */
DP |= DP_PORT_EN;
voltage = 0xff;
voltage_tries = 0;
loop_tries = 0;
clock_recovery = false;
for (;;) {
/* Use intel_dp->train_set[0] to set the voltage and pre emphasis values */
/* Set training pattern 1 */
break;
DRM_ERROR("failed to get link status\n");
break;
}
DRM_DEBUG_KMS("clock recovery OK\n");
clock_recovery = true;
break;
}
/* Check to see if we've tried the max voltage */
for (i = 0; i < intel_dp->lane_count; i++)
break;
if (i == intel_dp->lane_count) {
++loop_tries;
if (loop_tries == 5) {
DRM_DEBUG_KMS("too many full retries, give up\n");
break;
}
voltage_tries = 0;
continue;
}
/* Check to see if we've tried the same voltage 5 times */
if (voltage_tries == 5) {
DRM_DEBUG_KMS("too many voltage retries, give up\n");
break;
}
} else
voltage_tries = 0;
/* Compute new train_set as requested by target */
}
}
void
{
bool channel_eq = false;
/* channel equalization */
tries = 0;
cr_tries = 0;
channel_eq = false;
for (;;) {
if (cr_tries > 5) {
DRM_ERROR("failed to train DP, aborting\n");
break;
}
/* channel eq pattern */
break;
break;
/* Make sure clock is still ok */
cr_tries++;
continue;
}
channel_eq = true;
break;
}
/* Try 5 times, then try clock recovery if that fails */
if (tries > 5) {
tries = 0;
cr_tries++;
continue;
}
/* Compute new train_set as requested by target */
++tries;
}
if (channel_eq)
DRM_DEBUG_KMS("Channel EQ done. DP Training successful\n");
}
{
}
static void
{
/*
* DDI code has a strict mode set sequence and we should try to respect
* it, otherwise we might hang the machine in many different ways. So we
* really should be disabling the port only on a complete crtc_disable
* sequence. This function is just called under two conditions on DDI
* code:
* - Link train failed while doing crtc_enable, and on this case we
* really should respect the mode set sequence and wait for a
* crtc_disable.
* - Someone turned the monitor off and intel_dp_check_link_status
* called us. We don't need to disable the whole port on this case, so
* when someone turns the monitor on again,
* intel_ddi_prepare_link_retrain will take care of redoing the link
* train.
*/
return;
return;
DRM_DEBUG_KMS("\n");
DP &= ~DP_LINK_TRAIN_MASK_CPT;
} else {
DP &= ~DP_LINK_TRAIN_MASK;
}
/* We don't really know why we're doing this */
if (HAS_PCH_IBX(dev) &&
/* Hardware workaround: leaving our transcoder select
* set to transcoder B while it's off will prevent the
* corresponding HDMI output on transcoder A.
*
* Combine this with another hardware workaround:
* transcoder select bit can only be cleared while the
* port is enabled.
*/
DP &= ~DP_PIPEB_SELECT;
/* Changes to enable or select take place the vblank
* after being written.
*/
/* We should never try to disable a port without a crtc
* attached. For paranoia keep the code around for a
* bit. */
msleep(50);
} else
}
DP &= ~DP_AUDIO_OUTPUT_ENABLE;
}
static bool
{
// char dpcd_hex_dump[sizeof(intel_dp->dpcd) * 3];
return false; /* aux transfer failed */
/*
hex_dump_to_buffer(intel_dp->dpcd, sizeof(intel_dp->dpcd),
32, 1, dpcd_hex_dump, sizeof(dpcd_hex_dump), false);
DRM_DEBUG_KMS("DPCD: %s\n", dpcd_hex_dump);
*/
return false; /* DPCD not present */
return true; /* native DP sink */
return true; /* no per-port downstream info */
DP_MAX_DOWNSTREAM_PORTS) == 0)
return false; /* downstream port status fetch failed */
return true;
}
static void
{
return;
DRM_DEBUG_KMS("Sink OUI: %02hx%02hx%02hx\n",
DRM_DEBUG_KMS("Branch OUI: %02hx%02hx%02hx\n",
ironlake_edp_panel_vdd_off(intel_dp, false);
}
static bool
{
int ret;
sink_irq_vector, 1);
if (!ret)
return false;
return true;
}
static void
{
/* NAK by default */
}
/*
* According to DP spec
* 5.1.2:
* 1. Read DPCD
* 2. Configure link according to Receiver Capabilities
* 3. Use Link Training from 2.5.3.3 and 3.5.1.3
* 4. Check link status on receipt of hot-plug interrupt
*/
void
{
if (!intel_encoder->connectors_active)
return;
return;
/* Try to read receiver status if the link appears to be up */
return;
}
/* Now read the DPCD to see if it's actually running */
if (!intel_dp_get_dpcd(intel_dp)) {
return;
}
/* Try to read the source of the interrupt */
/* Clear interrupt source */
(void) intel_dp_aux_native_write_1(intel_dp,
DRM_DEBUG_DRIVER("CP or sink specific irq unhandled\n");
}
DRM_DEBUG_KMS("%s: channel EQ not ok, retraining\n",
}
}
/* XXX this is probably wrong for multiple downstream ports */
static enum drm_connector_status
{
bool hpd;
if (!intel_dp_get_dpcd(intel_dp))
return connector_status_disconnected;
/* if there's no downstream port, we're done */
return connector_status_connected;
/* If we're HPD-aware, SINK_COUNT changes dynamically */
if (hpd) {
®, 1))
return connector_status_unknown;
}
/* If no HPD, poke DDC gently */
return connector_status_connected;
/* Well we tried, say unknown for unreliable port types */
return connector_status_unknown;
/* Anything else is out of spec, warn and ignore */
DRM_DEBUG_KMS("Broken DP branch device, ignoring\n");
return connector_status_disconnected;
}
static enum drm_connector_status
{
/* Can't disconnect eDP */
if (status == connector_status_unknown)
return status;
}
return connector_status_disconnected;
return intel_dp_detect_dpcd(intel_dp);
}
static enum drm_connector_status
{
/* Can't disconnect eDP, but you can close the lid... */
if (status == connector_status_unknown)
return status;
}
switch (intel_dig_port->port) {
case PORT_B:
break;
case PORT_C:
break;
case PORT_D:
break;
default:
return connector_status_unknown;
}
return connector_status_disconnected;
return intel_dp_detect_dpcd(intel_dp);
}
static struct edid *
{
/* use cached edid if we have one */
if (intel_connector->edid) {
int size;
/* invalid edid */
return NULL;
if (!edid)
return NULL;
return edid;
}
}
static int
{
/* use cached edid if we have one */
if (intel_connector->edid) {
/* invalid edid */
return 0;
}
}
static enum drm_connector_status
{
if (HAS_PCH_SPLIT(dev))
else
if (status != connector_status_connected)
return status;
} else {
if (edid) {
}
}
return connector_status_connected;
}
{
int ret;
/* We should parse the EDID data and find out if it has an audio sink
*/
if (ret)
return ret;
/* if eDP has no EDID, fall back to fixed mode */
if (mode) {
return 1;
}
}
return 0;
}
static bool
{
bool has_audio = false;
if (edid) {
}
return has_audio;
}
static int
struct drm_property *property,
{
int ret;
if (ret)
return ret;
int i = (int)val;
bool has_audio;
if (i == intel_dp->force_audio)
return 0;
intel_dp->force_audio = i;
if (i == HDMI_AUDIO_AUTO)
else
has_audio = (i == HDMI_AUDIO_ON);
return 0;
goto done;
}
switch (val) {
case INTEL_BROADCAST_RGB_AUTO:
intel_dp->color_range_auto = true;
break;
case INTEL_BROADCAST_RGB_FULL:
intel_dp->color_range_auto = false;
intel_dp->color_range = 0;
break;
intel_dp->color_range_auto = false;
break;
default:
return -EINVAL;
}
return 0;
goto done;
}
if (val == DRM_MODE_SCALE_NONE) {
DRM_DEBUG_KMS("no scaling not supported\n");
return -EINVAL;
}
/* the eDP scaling property is not changed */
return 0;
}
goto done;
}
return -EINVAL;
done:
return 0;
}
static void
{
/* Can't call is_edp() since the encoder may have been destroyed
* already. */
}
{
// i2c_del_adapter(&intel_dp->adapter);
}
}
}
};
};
};
};
static void
{
}
/* Return which DP Port should be selected for Transcoder DP control */
int
{
return intel_dp->output_reg;
}
return -1;
}
/* check the VBT to see whether the eDP is on DP-D port */
{
int i;
return false;
return true;
}
return false;
}
static void
{
intel_dp->color_range_auto = true;
}
}
static void
struct edp_power_seq *out)
{
if (HAS_PCH_SPLIT(dev)) {
} else {
}
/* Workaround: Need to write PP_CONTROL with the unlock key as
* the very first thing. */
/* Pull timing values out of registers */
PANEL_POWER_CYCLE_DELAY_SHIFT) * 1000;
DRM_DEBUG_KMS("cur t1_t3 %d t8 %d t9 %d t10 %d t11_t12 %d\n",
/* Upper limits from eDP 1.3 spec. Note that we use the clunky units of
* our hw here, which are all in 100usec. */
/* This one is special and actually in units of 100ms, but zero
* based in the hw (so we need to add 100 ms). But the sw vbt
* table multiplies it with 1000 to make it in units of 100usec,
* too. */
DRM_DEBUG_KMS("vbt t1_t3 %d t8 %d t9 %d t10 %d t11_t12 %d\n",
/* Use the max of the register settings and vbt. If both are
* unset, fall back to the spec limits. */
DRM_DEBUG_KMS("panel power up delay %d, power down delay %d, power cycle delay %d\n",
DRM_DEBUG_KMS("backlight on delay %d, off delay %d\n",
if (out)
}
static void
struct edp_power_seq *seq)
{
if (HAS_PCH_SPLIT(dev)) {
} else {
}
/* And finally store the new values in the power sequencer. */
/* Compute the divisor for the pp clock, simply match the Bspec
* formula. */
/* Haswell doesn't have any port selection bits for the panel
* power sequencer any more. */
if (IS_VALLEYVIEW(dev)) {
else
}
DRM_DEBUG_KMS("panel power sequencer register settings: PP_ON %#x, PP_OFF %#x, PP_DIV %#x\n",
}
struct intel_connector *intel_connector)
{
bool has_dpcd;
return true;
/* Cache DPCD and EDID for edp. */
ironlake_edp_panel_vdd_off(intel_dp, false);
if (has_dpcd) {
} else {
/* if this fails, presume the device is a ghost */
DRM_INFO("failed to retrieve link info, disabling eDP\n");
return false;
}
/* We now know it's not a ghost, init power sequence regs. */
&power_seq);
if (edid) {
edid);
} else {
}
} else {
}
/* prefer fixed mode from EDID if available */
break;
}
}
/* fallback to VBT if available for eDP */
if (fixed_mode)
}
ironlake_edp_panel_vdd_off(intel_dp, false);
return true;
}
bool
struct intel_connector *intel_connector)
{
/* Preserve the current hw state. */
/*
* FIXME : We need to initialize built-in panels before external panels.
* For X0, DP_C is fixed as eDP. Revisit this as part of VLV eDP cleanup
*/
switch (port) {
case PORT_A:
break;
case PORT_C:
if (IS_VALLEYVIEW(dev))
break;
case PORT_D:
break;
default: /* silence GCC warning */
break;
}
/*
* For eDP we always set the encoder type to INTEL_OUTPUT_EDP, but
* for DP the encoder type can be set by the caller to
* INTEL_OUTPUT_UNKNOWN for DDI, so don't rewrite it.
*/
if (type == DRM_MODE_CONNECTOR_eDP)
DRM_DEBUG_KMS("Adding %s connector on port %c\n",
connector->interlace_allowed = true;
connector->doublescan_allowed = 0;
else
switch (intel_dig_port->port) {
case PORT_A:
break;
case PORT_B:
break;
case PORT_C:
break;
case PORT_D:
break;
default:
BUG();
}
}
/* Set up the DDC bus. */
switch (port) {
case PORT_A:
name = "DPDDC-A";
break;
case PORT_B:
name = "DPDDC-B";
break;
case PORT_C:
name = "DPDDC-C";
break;
case PORT_D:
name = "DPDDC-D";
break;
default:
BUG();
}
if(error)
DRM_ERROR("intel_dp_i2c_init failed with error %d for port %c\n",
//i2c_del_adapter(&intel_dp->adapter);
}
}
return false;
}
/* For G4X desktop chip, PEG_BAND_GAP_DATA 3:0 must first be written
* 0xd. Failure to do so will result in spurious interrupts being
* generated on the port when a cable is not attached.
*/
}
return true;
}
void
{
if (!intel_dig_port)
return;
if (!intel_connector) {
return;
}
if (IS_VALLEYVIEW(dev))
intel_encoder->cloneable = false;
}
}