109,8 → 109,11 |
} |
|
static void intel_dp_link_down(struct intel_dp *intel_dp); |
static bool _edp_panel_vdd_on(struct intel_dp *intel_dp); |
static bool edp_panel_vdd_on(struct intel_dp *intel_dp); |
static void edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync); |
static void vlv_init_panel_power_sequencer(struct intel_dp *intel_dp); |
static void vlv_steal_power_sequencer(struct drm_device *dev, |
enum pipe pipe); |
|
int |
intel_dp_max_link_bw(struct intel_dp *intel_dp) |
222,8 → 225,7 |
return MODE_OK; |
} |
|
static uint32_t |
pack_aux(uint8_t *src, int src_bytes) |
uint32_t intel_dp_pack_aux(const uint8_t *src, int src_bytes) |
{ |
int i; |
uint32_t v = 0; |
235,8 → 237,7 |
return v; |
} |
|
static void |
unpack_aux(uint32_t src, uint8_t *dst, int dst_bytes) |
void intel_dp_unpack_aux(uint32_t src, uint8_t *dst, int dst_bytes) |
{ |
int i; |
if (dst_bytes > 4) |
281,41 → 282,277 |
|
static void |
intel_dp_init_panel_power_sequencer(struct drm_device *dev, |
struct intel_dp *intel_dp, |
struct edp_power_seq *out); |
struct intel_dp *intel_dp); |
static void |
intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev, |
struct intel_dp *intel_dp, |
struct edp_power_seq *out); |
struct intel_dp *intel_dp); |
|
static void pps_lock(struct intel_dp *intel_dp) |
{ |
struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); |
struct intel_encoder *encoder = &intel_dig_port->base; |
struct drm_device *dev = encoder->base.dev; |
struct drm_i915_private *dev_priv = dev->dev_private; |
enum intel_display_power_domain power_domain; |
|
/* |
* See vlv_power_sequencer_reset() why we need |
* a power domain reference here. |
*/ |
power_domain = intel_display_port_power_domain(encoder); |
intel_display_power_get(dev_priv, power_domain); |
|
mutex_lock(&dev_priv->pps_mutex); |
} |
|
static void pps_unlock(struct intel_dp *intel_dp) |
{ |
struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); |
struct intel_encoder *encoder = &intel_dig_port->base; |
struct drm_device *dev = encoder->base.dev; |
struct drm_i915_private *dev_priv = dev->dev_private; |
enum intel_display_power_domain power_domain; |
|
mutex_unlock(&dev_priv->pps_mutex); |
|
power_domain = intel_display_port_power_domain(encoder); |
intel_display_power_put(dev_priv, power_domain); |
} |
|
static void |
vlv_power_sequencer_kick(struct intel_dp *intel_dp) |
{ |
struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); |
struct drm_device *dev = intel_dig_port->base.base.dev; |
struct drm_i915_private *dev_priv = dev->dev_private; |
enum pipe pipe = intel_dp->pps_pipe; |
bool pll_enabled; |
uint32_t DP; |
|
if (WARN(I915_READ(intel_dp->output_reg) & DP_PORT_EN, |
"skipping pipe %c power seqeuncer kick due to port %c being active\n", |
pipe_name(pipe), port_name(intel_dig_port->port))) |
return; |
|
DRM_DEBUG_KMS("kicking pipe %c power sequencer for port %c\n", |
pipe_name(pipe), port_name(intel_dig_port->port)); |
|
/* Preserve the BIOS-computed detected bit. This is |
* supposed to be read-only. |
*/ |
DP = I915_READ(intel_dp->output_reg) & DP_DETECTED; |
DP |= DP_VOLTAGE_0_4 | DP_PRE_EMPHASIS_0; |
DP |= DP_PORT_WIDTH(1); |
DP |= DP_LINK_TRAIN_PAT_1; |
|
if (IS_CHERRYVIEW(dev)) |
DP |= DP_PIPE_SELECT_CHV(pipe); |
else if (pipe == PIPE_B) |
DP |= DP_PIPEB_SELECT; |
|
pll_enabled = I915_READ(DPLL(pipe)) & DPLL_VCO_ENABLE; |
|
/* |
* The DPLL for the pipe must be enabled for this to work. |
* So enable temporarily it if it's not already enabled. |
*/ |
if (!pll_enabled) |
vlv_force_pll_on(dev, pipe, IS_CHERRYVIEW(dev) ? |
&chv_dpll[0].dpll : &vlv_dpll[0].dpll); |
|
/* |
* Similar magic as in intel_dp_enable_port(). |
* We _must_ do this port enable + disable trick |
* to make this power seqeuencer lock onto the port. |
* Otherwise even VDD force bit won't work. |
*/ |
I915_WRITE(intel_dp->output_reg, DP); |
POSTING_READ(intel_dp->output_reg); |
|
I915_WRITE(intel_dp->output_reg, DP | DP_PORT_EN); |
POSTING_READ(intel_dp->output_reg); |
|
I915_WRITE(intel_dp->output_reg, DP & ~DP_PORT_EN); |
POSTING_READ(intel_dp->output_reg); |
|
if (!pll_enabled) |
vlv_force_pll_off(dev, pipe); |
} |
|
static enum pipe |
vlv_power_sequencer_pipe(struct intel_dp *intel_dp) |
{ |
struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); |
struct drm_crtc *crtc = intel_dig_port->base.base.crtc; |
struct drm_device *dev = intel_dig_port->base.base.dev; |
struct drm_i915_private *dev_priv = dev->dev_private; |
enum port port = intel_dig_port->port; |
struct intel_encoder *encoder; |
unsigned int pipes = (1 << PIPE_A) | (1 << PIPE_B); |
enum pipe pipe; |
|
/* modeset should have pipe */ |
if (crtc) |
return to_intel_crtc(crtc)->pipe; |
lockdep_assert_held(&dev_priv->pps_mutex); |
|
/* init time, try to find a pipe with this port selected */ |
/* We should never land here with regular DP ports */ |
WARN_ON(!is_edp(intel_dp)); |
|
if (intel_dp->pps_pipe != INVALID_PIPE) |
return intel_dp->pps_pipe; |
|
/* |
* We don't have power sequencer currently. |
* Pick one that's not used by other ports. |
*/ |
list_for_each_entry(encoder, &dev->mode_config.encoder_list, |
base.head) { |
struct intel_dp *tmp; |
|
if (encoder->type != INTEL_OUTPUT_EDP) |
continue; |
|
tmp = enc_to_intel_dp(&encoder->base); |
|
if (tmp->pps_pipe != INVALID_PIPE) |
pipes &= ~(1 << tmp->pps_pipe); |
} |
|
/* |
* Didn't find one. This should not happen since there |
* are two power sequencers and up to two eDP ports. |
*/ |
if (WARN_ON(pipes == 0)) |
pipe = PIPE_A; |
else |
pipe = ffs(pipes) - 1; |
|
vlv_steal_power_sequencer(dev, pipe); |
intel_dp->pps_pipe = pipe; |
|
DRM_DEBUG_KMS("picked pipe %c power sequencer for port %c\n", |
pipe_name(intel_dp->pps_pipe), |
port_name(intel_dig_port->port)); |
|
/* init power sequencer on this pipe and port */ |
intel_dp_init_panel_power_sequencer(dev, intel_dp); |
intel_dp_init_panel_power_sequencer_registers(dev, intel_dp); |
|
/* |
* Even vdd force doesn't work until we've made |
* the power sequencer lock in on the port. |
*/ |
vlv_power_sequencer_kick(intel_dp); |
|
return intel_dp->pps_pipe; |
} |
|
typedef bool (*vlv_pipe_check)(struct drm_i915_private *dev_priv, |
enum pipe pipe); |
|
static bool vlv_pipe_has_pp_on(struct drm_i915_private *dev_priv, |
enum pipe pipe) |
{ |
return I915_READ(VLV_PIPE_PP_STATUS(pipe)) & PP_ON; |
} |
|
static bool vlv_pipe_has_vdd_on(struct drm_i915_private *dev_priv, |
enum pipe pipe) |
{ |
return I915_READ(VLV_PIPE_PP_CONTROL(pipe)) & EDP_FORCE_VDD; |
} |
|
static bool vlv_pipe_any(struct drm_i915_private *dev_priv, |
enum pipe pipe) |
{ |
return true; |
} |
|
static enum pipe |
vlv_initial_pps_pipe(struct drm_i915_private *dev_priv, |
enum port port, |
vlv_pipe_check pipe_check) |
{ |
enum pipe pipe; |
|
for (pipe = PIPE_A; pipe <= PIPE_B; pipe++) { |
u32 port_sel = I915_READ(VLV_PIPE_PP_ON_DELAYS(pipe)) & |
PANEL_PORT_SELECT_MASK; |
if (port_sel == PANEL_PORT_SELECT_DPB_VLV && port == PORT_B) |
|
if (port_sel != PANEL_PORT_SELECT_VLV(port)) |
continue; |
|
if (!pipe_check(dev_priv, pipe)) |
continue; |
|
return pipe; |
if (port_sel == PANEL_PORT_SELECT_DPC_VLV && port == PORT_C) |
return pipe; |
} |
|
/* shrug */ |
return PIPE_A; |
return INVALID_PIPE; |
} |
|
static void |
vlv_initial_power_sequencer_setup(struct intel_dp *intel_dp) |
{ |
struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); |
struct drm_device *dev = intel_dig_port->base.base.dev; |
struct drm_i915_private *dev_priv = dev->dev_private; |
enum port port = intel_dig_port->port; |
|
lockdep_assert_held(&dev_priv->pps_mutex); |
|
/* try to find a pipe with this port selected */ |
/* first pick one where the panel is on */ |
intel_dp->pps_pipe = vlv_initial_pps_pipe(dev_priv, port, |
vlv_pipe_has_pp_on); |
/* didn't find one? pick one where vdd is on */ |
if (intel_dp->pps_pipe == INVALID_PIPE) |
intel_dp->pps_pipe = vlv_initial_pps_pipe(dev_priv, port, |
vlv_pipe_has_vdd_on); |
/* didn't find one? pick one with just the correct port */ |
if (intel_dp->pps_pipe == INVALID_PIPE) |
intel_dp->pps_pipe = vlv_initial_pps_pipe(dev_priv, port, |
vlv_pipe_any); |
|
/* didn't find one? just let vlv_power_sequencer_pipe() pick one when needed */ |
if (intel_dp->pps_pipe == INVALID_PIPE) { |
DRM_DEBUG_KMS("no initial power sequencer for port %c\n", |
port_name(port)); |
return; |
} |
|
DRM_DEBUG_KMS("initial power sequencer for port %c: pipe %c\n", |
port_name(port), pipe_name(intel_dp->pps_pipe)); |
|
intel_dp_init_panel_power_sequencer(dev, intel_dp); |
intel_dp_init_panel_power_sequencer_registers(dev, intel_dp); |
} |
|
void vlv_power_sequencer_reset(struct drm_i915_private *dev_priv) |
{ |
struct drm_device *dev = dev_priv->dev; |
struct intel_encoder *encoder; |
|
if (WARN_ON(!IS_VALLEYVIEW(dev))) |
return; |
|
/* |
* We can't grab pps_mutex here due to deadlock with power_domain |
* mutex when power_domain functions are called while holding pps_mutex. |
* That also means that in order to use pps_pipe the code needs to |
* hold both a power domain reference and pps_mutex, and the power domain |
* reference get/put must be done while _not_ holding pps_mutex. |
* pps_{lock,unlock}() do these steps in the correct order, so one |
* should use them always. |
*/ |
|
list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.head) { |
struct intel_dp *intel_dp; |
|
if (encoder->type != INTEL_OUTPUT_EDP) |
continue; |
|
intel_dp = enc_to_intel_dp(&encoder->base); |
intel_dp->pps_pipe = INVALID_PIPE; |
} |
} |
|
static u32 _pp_ctrl_reg(struct intel_dp *intel_dp) |
{ |
struct drm_device *dev = intel_dp_to_dev(intel_dp); |
336,12 → 573,55 |
return VLV_PIPE_PP_STATUS(vlv_power_sequencer_pipe(intel_dp)); |
} |
|
#if 0 |
/* Reboot notifier handler to shutdown panel power to guarantee T12 timing |
This function only applicable when panel PM state is not to be tracked */ |
static int edp_notify_handler(struct notifier_block *this, unsigned long code, |
void *unused) |
{ |
struct intel_dp *intel_dp = container_of(this, typeof(* intel_dp), |
edp_notifier); |
struct drm_device *dev = intel_dp_to_dev(intel_dp); |
struct drm_i915_private *dev_priv = dev->dev_private; |
u32 pp_div; |
u32 pp_ctrl_reg, pp_div_reg; |
|
if (!is_edp(intel_dp) || code != SYS_RESTART) |
return 0; |
|
pps_lock(intel_dp); |
|
if (IS_VALLEYVIEW(dev)) { |
enum pipe pipe = vlv_power_sequencer_pipe(intel_dp); |
|
pp_ctrl_reg = VLV_PIPE_PP_CONTROL(pipe); |
pp_div_reg = VLV_PIPE_PP_DIVISOR(pipe); |
pp_div = I915_READ(pp_div_reg); |
pp_div &= PP_REFERENCE_DIVIDER_MASK; |
|
/* 0x1F write to PP_DIV_REG sets max cycle delay */ |
I915_WRITE(pp_div_reg, pp_div | 0x1F); |
I915_WRITE(pp_ctrl_reg, PANEL_UNLOCK_REGS | PANEL_POWER_OFF); |
msleep(intel_dp->panel_power_cycle_delay); |
} |
|
pps_unlock(intel_dp); |
|
return 0; |
} |
#endif |
|
static bool edp_have_panel_power(struct intel_dp *intel_dp) |
{ |
struct drm_device *dev = intel_dp_to_dev(intel_dp); |
struct drm_i915_private *dev_priv = dev->dev_private; |
|
lockdep_assert_held(&dev_priv->pps_mutex); |
|
if (IS_VALLEYVIEW(dev) && |
intel_dp->pps_pipe == INVALID_PIPE) |
return false; |
|
return (I915_READ(_pp_stat_reg(intel_dp)) & PP_ON) != 0; |
} |
|
349,13 → 629,14 |
{ |
struct drm_device *dev = intel_dp_to_dev(intel_dp); |
struct drm_i915_private *dev_priv = dev->dev_private; |
struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); |
struct intel_encoder *intel_encoder = &intel_dig_port->base; |
enum intel_display_power_domain power_domain; |
|
power_domain = intel_display_port_power_domain(intel_encoder); |
return intel_display_power_enabled(dev_priv, power_domain) && |
(I915_READ(_pp_ctrl_reg(intel_dp)) & EDP_FORCE_VDD) != 0; |
lockdep_assert_held(&dev_priv->pps_mutex); |
|
if (IS_VALLEYVIEW(dev) && |
intel_dp->pps_pipe == INVALID_PIPE) |
return false; |
|
return I915_READ(_pp_ctrl_reg(intel_dp)) & EDP_FORCE_VDD; |
} |
|
static void |
456,6 → 737,16 |
return index ? 0 : 100; |
} |
|
static uint32_t skl_get_aux_clock_divider(struct intel_dp *intel_dp, int index) |
{ |
/* |
* SKL doesn't need us to program the AUX clock divider (Hardware will |
* derive the clock from CDCLK automatically). We still implement the |
* get_aux_clock_divider vfunc to plug-in into the existing code. |
*/ |
return index ? 0 : 1; |
} |
|
static uint32_t i9xx_get_aux_send_ctl(struct intel_dp *intel_dp, |
bool has_aux_irq, |
int send_bytes, |
486,9 → 777,24 |
(aux_clock_divider << DP_AUX_CH_CTL_BIT_CLOCK_2X_SHIFT); |
} |
|
static uint32_t skl_get_aux_send_ctl(struct intel_dp *intel_dp, |
bool has_aux_irq, |
int send_bytes, |
uint32_t unused) |
{ |
return DP_AUX_CH_CTL_SEND_BUSY | |
DP_AUX_CH_CTL_DONE | |
(has_aux_irq ? DP_AUX_CH_CTL_INTERRUPT : 0) | |
DP_AUX_CH_CTL_TIME_OUT_ERROR | |
DP_AUX_CH_CTL_TIME_OUT_1600us | |
DP_AUX_CH_CTL_RECEIVE_ERROR | |
(send_bytes << DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT) | |
DP_AUX_CH_CTL_SYNC_PULSE_SKL(32); |
} |
|
static int |
intel_dp_aux_ch(struct intel_dp *intel_dp, |
uint8_t *send, int send_bytes, |
const uint8_t *send, int send_bytes, |
uint8_t *recv, int recv_size) |
{ |
struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); |
503,8 → 809,16 |
bool has_aux_irq = HAS_AUX_IRQ(dev); |
bool vdd; |
|
vdd = _edp_panel_vdd_on(intel_dp); |
pps_lock(intel_dp); |
|
/* |
* We will be called with VDD already enabled for dpcd/edid/oui reads. |
* In such cases we want to leave VDD enabled and it's up to upper layers |
* to turn it off. But for eg. i2c-dev access we need to turn it on/off |
* ourselves. |
*/ |
vdd = edp_panel_vdd_on(intel_dp); |
|
/* 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. |
546,7 → 860,8 |
/* Load the send data into the aux channel data registers */ |
for (i = 0; i < send_bytes; i += 4) |
I915_WRITE(ch_data + i, |
pack_aux(send + i, send_bytes - i)); |
intel_dp_pack_aux(send + i, |
send_bytes - i)); |
|
/* Send the command and wait for it to complete */ |
I915_WRITE(ch_ctl, send_ctl); |
600,7 → 915,7 |
recv_bytes = recv_size; |
|
for (i = 0; i < recv_bytes; i += 4) |
unpack_aux(I915_READ(ch_data + i), |
intel_dp_unpack_aux(I915_READ(ch_data + i), |
recv + i, recv_bytes - i); |
|
ret = recv_bytes; |
611,6 → 926,8 |
if (vdd) |
edp_panel_vdd_off(intel_dp, false); |
|
pps_unlock(intel_dp); |
|
return ret; |
} |
|
709,7 → 1026,16 |
BUG(); |
} |
|
if (!HAS_DDI(dev)) |
/* |
* The AUX_CTL register is usually DP_CTL + 0x10. |
* |
* On Haswell and Broadwell though: |
* - Both port A DDI_BUF_CTL and DDI_AUX_CTL are on the CPU |
* - Port B/C/D AUX channels are on the PCH, DDI_BUF_CTL on the CPU |
* |
* Skylake moves AUX_CTL back next to DDI_BUF_CTL, on the CPU. |
*/ |
if (!IS_HASWELL(dev) && !IS_BROADWELL(dev)) |
intel_dp->aux_ch_ctl_reg = intel_dp->output_reg + 0x10; |
|
intel_dp->aux.name = name; |
716,6 → 1042,8 |
intel_dp->aux.dev = dev->dev; |
intel_dp->aux.transfer = intel_dp_aux_transfer; |
|
DRM_DEBUG_KMS("registering %s bus for %s\n", name, |
connector->base.kdev->kobj.name); |
|
ret = drm_dp_aux_register(&intel_dp->aux); |
if (ret < 0) { |
734,6 → 1062,33 |
} |
|
static void |
skl_edp_set_pll_config(struct intel_crtc_config *pipe_config, int link_bw) |
{ |
u32 ctrl1; |
|
pipe_config->ddi_pll_sel = SKL_DPLL0; |
pipe_config->dpll_hw_state.cfgcr1 = 0; |
pipe_config->dpll_hw_state.cfgcr2 = 0; |
|
ctrl1 = DPLL_CTRL1_OVERRIDE(SKL_DPLL0); |
switch (link_bw) { |
case DP_LINK_BW_1_62: |
ctrl1 |= DPLL_CRTL1_LINK_RATE(DPLL_CRTL1_LINK_RATE_810, |
SKL_DPLL0); |
break; |
case DP_LINK_BW_2_7: |
ctrl1 |= DPLL_CRTL1_LINK_RATE(DPLL_CRTL1_LINK_RATE_1350, |
SKL_DPLL0); |
break; |
case DP_LINK_BW_5_4: |
ctrl1 |= DPLL_CRTL1_LINK_RATE(DPLL_CRTL1_LINK_RATE_2700, |
SKL_DPLL0); |
break; |
} |
pipe_config->dpll_hw_state.ctrl1 = ctrl1; |
} |
|
static void |
hsw_dp_set_ddi_pll_sel(struct intel_crtc_config *pipe_config, int link_bw) |
{ |
switch (link_bw) { |
782,20 → 1137,6 |
} |
} |
|
static void |
intel_dp_set_m2_n2(struct intel_crtc *crtc, struct intel_link_m_n *m_n) |
{ |
struct drm_device *dev = crtc->base.dev; |
struct drm_i915_private *dev_priv = dev->dev_private; |
enum transcoder transcoder = crtc->config.cpu_transcoder; |
|
I915_WRITE(PIPE_DATA_M2(transcoder), |
TU_SIZE(m_n->tu) | m_n->gmch_m); |
I915_WRITE(PIPE_DATA_N2(transcoder), m_n->gmch_n); |
I915_WRITE(PIPE_LINK_M2(transcoder), m_n->link_m); |
I915_WRITE(PIPE_LINK_N2(transcoder), m_n->link_n); |
} |
|
bool |
intel_dp_compute_config(struct intel_encoder *encoder, |
struct intel_crtc_config *pipe_config) |
821,6 → 1162,7 |
pipe_config->has_pch_encoder = true; |
|
pipe_config->has_dp_encoder = true; |
pipe_config->has_drrs = false; |
pipe_config->has_audio = intel_dp->has_audio; |
|
if (is_edp(intel_dp) && intel_connector->panel.fixed_mode) { |
852,25 → 1194,17 |
bpp = dev_priv->vbt.edp_bpp; |
} |
|
if (IS_BROADWELL(dev)) { |
/* Yes, it's an ugly hack. */ |
/* |
* Use the maximum clock and number of lanes the eDP panel |
* advertizes being capable of. The panels are generally |
* designed to support only a single clock and lane |
* configuration, and typically these values correspond to the |
* native resolution of the panel. |
*/ |
min_lane_count = max_lane_count; |
DRM_DEBUG_KMS("forcing lane count to max (%u) on BDW\n", |
min_lane_count); |
} else if (dev_priv->vbt.edp_lanes) { |
min_lane_count = min(dev_priv->vbt.edp_lanes, |
max_lane_count); |
DRM_DEBUG_KMS("using min %u lanes per VBT\n", |
min_lane_count); |
min_clock = max_clock; |
} |
|
if (dev_priv->vbt.edp_rate) { |
min_clock = min(dev_priv->vbt.edp_rate >> 3, max_clock); |
DRM_DEBUG_KMS("using min %02x link bw per VBT\n", |
bws[min_clock]); |
} |
} |
|
for (; bpp >= 6*3; bpp -= 2*3) { |
mode_rate = intel_dp_link_required(adjusted_mode->crtc_clock, |
bpp); |
924,6 → 1258,7 |
|
if (intel_connector->panel.downclock_mode != NULL && |
intel_dp->drrs_state.type == SEAMLESS_DRRS_SUPPORT) { |
pipe_config->has_drrs = true; |
intel_link_compute_m_n(bpp, lane_count, |
intel_connector->panel.downclock_mode->clock, |
pipe_config->port_clock, |
930,7 → 1265,9 |
&pipe_config->dp_m2_n2); |
} |
|
if (HAS_DDI(dev)) |
if (IS_SKYLAKE(dev) && is_edp(intel_dp)) |
skl_edp_set_pll_config(pipe_config, intel_dp->link_bw); |
else if (IS_HASWELL(dev) || IS_BROADWELL(dev)) |
hsw_dp_set_ddi_pll_sel(pipe_config, intel_dp->link_bw); |
else |
intel_dp_set_clock(encoder, pipe_config, intel_dp->link_bw); |
1003,12 → 1340,8 |
intel_dp->DP |= DP_VOLTAGE_0_4 | DP_PRE_EMPHASIS_0; |
intel_dp->DP |= DP_PORT_WIDTH(intel_dp->lane_count); |
|
if (crtc->config.has_audio) { |
DRM_DEBUG_DRIVER("Enabling DP audio on pipe %c\n", |
pipe_name(crtc->pipe)); |
if (crtc->config.has_audio) |
intel_dp->DP |= DP_AUDIO_OUTPUT_ENABLE; |
intel_write_eld(&encoder->base, adjusted_mode); |
} |
|
/* Split out the IBX/CPU vs CPT settings */ |
|
1064,6 → 1397,8 |
struct drm_i915_private *dev_priv = dev->dev_private; |
u32 pp_stat_reg, pp_ctrl_reg; |
|
lockdep_assert_held(&dev_priv->pps_mutex); |
|
pp_stat_reg = _pp_stat_reg(intel_dp); |
pp_ctrl_reg = _pp_ctrl_reg(intel_dp); |
|
1127,6 → 1462,8 |
struct drm_i915_private *dev_priv = dev->dev_private; |
u32 control; |
|
lockdep_assert_held(&dev_priv->pps_mutex); |
|
control = I915_READ(_pp_ctrl_reg(intel_dp)); |
control &= ~PANEL_UNLOCK_MASK; |
control |= PANEL_UNLOCK_REGS; |
1133,7 → 1470,12 |
return control; |
} |
|
static bool _edp_panel_vdd_on(struct intel_dp *intel_dp) |
/* |
* Must be paired with edp_panel_vdd_off(). |
* Must hold pps_mutex around the whole on/off sequence. |
* Can be nested with intel_edp_panel_vdd_{on,off}() calls. |
*/ |
static bool edp_panel_vdd_on(struct intel_dp *intel_dp) |
{ |
struct drm_device *dev = intel_dp_to_dev(intel_dp); |
struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); |
1144,6 → 1486,8 |
u32 pp_stat_reg, pp_ctrl_reg; |
bool need_to_disable = !intel_dp->want_panel_vdd; |
|
lockdep_assert_held(&dev_priv->pps_mutex); |
|
if (!is_edp(intel_dp)) |
return false; |
|
1155,7 → 1499,8 |
power_domain = intel_display_port_power_domain(intel_encoder); |
intel_display_power_get(dev_priv, power_domain); |
|
DRM_DEBUG_KMS("Turning eDP VDD on\n"); |
DRM_DEBUG_KMS("Turning eDP port %c VDD on\n", |
port_name(intel_dig_port->port)); |
|
if (!edp_have_panel_power(intel_dp)) |
wait_panel_power_cycle(intel_dp); |
1174,7 → 1519,8 |
* If the panel wasn't on, delay before accessing aux channel |
*/ |
if (!edp_have_panel_power(intel_dp)) { |
DRM_DEBUG_KMS("eDP was not running\n"); |
DRM_DEBUG_KMS("eDP port %c panel power wasn't enabled\n", |
port_name(intel_dig_port->port)); |
msleep(intel_dp->panel_power_up_delay); |
} |
|
1181,32 → 1527,49 |
return need_to_disable; |
} |
|
/* |
* Must be paired with intel_edp_panel_vdd_off() or |
* intel_edp_panel_off(). |
* Nested calls to these functions are not allowed since |
* we drop the lock. Caller must use some higher level |
* locking to prevent nested calls from other threads. |
*/ |
void intel_edp_panel_vdd_on(struct intel_dp *intel_dp) |
{ |
if (is_edp(intel_dp)) { |
bool vdd = _edp_panel_vdd_on(intel_dp); |
bool vdd; |
|
WARN(!vdd, "eDP VDD already requested on\n"); |
if (!is_edp(intel_dp)) |
return; |
|
pps_lock(intel_dp); |
vdd = edp_panel_vdd_on(intel_dp); |
pps_unlock(intel_dp); |
|
WARN(!vdd, "eDP port %c VDD already requested on\n", |
port_name(dp_to_dig_port(intel_dp)->port)); |
} |
} |
|
static void edp_panel_vdd_off_sync(struct intel_dp *intel_dp) |
{ |
struct drm_device *dev = intel_dp_to_dev(intel_dp); |
struct drm_i915_private *dev_priv = dev->dev_private; |
u32 pp; |
u32 pp_stat_reg, pp_ctrl_reg; |
|
WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex)); |
|
if (!intel_dp->want_panel_vdd && edp_have_panel_vdd(intel_dp)) { |
struct intel_digital_port *intel_dig_port = |
dp_to_dig_port(intel_dp); |
struct intel_encoder *intel_encoder = &intel_dig_port->base; |
enum intel_display_power_domain power_domain; |
u32 pp; |
u32 pp_stat_reg, pp_ctrl_reg; |
|
DRM_DEBUG_KMS("Turning eDP VDD off\n"); |
lockdep_assert_held(&dev_priv->pps_mutex); |
|
WARN_ON(intel_dp->want_panel_vdd); |
|
if (!edp_have_panel_vdd(intel_dp)) |
return; |
|
DRM_DEBUG_KMS("Turning eDP port %c VDD off\n", |
port_name(intel_dig_port->port)); |
|
pp = ironlake_get_pp_control(intel_dp); |
pp &= ~EDP_FORCE_VDD; |
|
1226,17 → 1589,16 |
power_domain = intel_display_port_power_domain(intel_encoder); |
intel_display_power_put(dev_priv, power_domain); |
} |
} |
|
static void edp_panel_vdd_work(struct work_struct *__work) |
{ |
struct intel_dp *intel_dp = container_of(to_delayed_work(__work), |
struct intel_dp, panel_vdd_work); |
struct drm_device *dev = intel_dp_to_dev(intel_dp); |
|
drm_modeset_lock(&dev->mode_config.connection_mutex, NULL); |
pps_lock(intel_dp); |
if (!intel_dp->want_panel_vdd) |
edp_panel_vdd_off_sync(intel_dp); |
drm_modeset_unlock(&dev->mode_config.connection_mutex); |
pps_unlock(intel_dp); |
} |
|
static void edp_panel_vdd_schedule_off(struct intel_dp *intel_dp) |
1252,12 → 1614,23 |
schedule_delayed_work(&intel_dp->panel_vdd_work, delay); |
} |
|
/* |
* Must be paired with edp_panel_vdd_on(). |
* Must hold pps_mutex around the whole on/off sequence. |
* Can be nested with intel_edp_panel_vdd_{on,off}() calls. |
*/ |
static void edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync) |
{ |
struct drm_i915_private *dev_priv = |
intel_dp_to_dev(intel_dp)->dev_private; |
|
lockdep_assert_held(&dev_priv->pps_mutex); |
|
if (!is_edp(intel_dp)) |
return; |
|
WARN(!intel_dp->want_panel_vdd, "eDP VDD not forced on"); |
WARN(!intel_dp->want_panel_vdd, "eDP port %c VDD not forced on", |
port_name(dp_to_dig_port(intel_dp)->port)); |
|
intel_dp->want_panel_vdd = false; |
|
1267,7 → 1640,7 |
edp_panel_vdd_schedule_off(intel_dp); |
} |
|
void intel_edp_panel_on(struct intel_dp *intel_dp) |
static void edp_panel_on(struct intel_dp *intel_dp) |
{ |
struct drm_device *dev = intel_dp_to_dev(intel_dp); |
struct drm_i915_private *dev_priv = dev->dev_private; |
1274,15 → 1647,18 |
u32 pp; |
u32 pp_ctrl_reg; |
|
lockdep_assert_held(&dev_priv->pps_mutex); |
|
if (!is_edp(intel_dp)) |
return; |
|
DRM_DEBUG_KMS("Turn eDP power on\n"); |
DRM_DEBUG_KMS("Turn eDP port %c panel power on\n", |
port_name(dp_to_dig_port(intel_dp)->port)); |
|
if (edp_have_panel_power(intel_dp)) { |
DRM_DEBUG_KMS("eDP power already on\n"); |
if (WARN(edp_have_panel_power(intel_dp), |
"eDP port %c panel power already on\n", |
port_name(dp_to_dig_port(intel_dp)->port))) |
return; |
} |
|
wait_panel_power_cycle(intel_dp); |
|
1312,8 → 1688,19 |
} |
} |
|
void intel_edp_panel_off(struct intel_dp *intel_dp) |
void intel_edp_panel_on(struct intel_dp *intel_dp) |
{ |
if (!is_edp(intel_dp)) |
return; |
|
pps_lock(intel_dp); |
edp_panel_on(intel_dp); |
pps_unlock(intel_dp); |
} |
|
|
static void edp_panel_off(struct intel_dp *intel_dp) |
{ |
struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); |
struct intel_encoder *intel_encoder = &intel_dig_port->base; |
struct drm_device *dev = intel_dp_to_dev(intel_dp); |
1322,12 → 1709,16 |
u32 pp; |
u32 pp_ctrl_reg; |
|
lockdep_assert_held(&dev_priv->pps_mutex); |
|
if (!is_edp(intel_dp)) |
return; |
|
DRM_DEBUG_KMS("Turn eDP power off\n"); |
DRM_DEBUG_KMS("Turn eDP port %c panel power off\n", |
port_name(dp_to_dig_port(intel_dp)->port)); |
|
WARN(!intel_dp->want_panel_vdd, "Need VDD to turn off panel\n"); |
WARN(!intel_dp->want_panel_vdd, "Need eDP port %c VDD to turn off panel\n", |
port_name(dp_to_dig_port(intel_dp)->port)); |
|
pp = ironlake_get_pp_control(intel_dp); |
/* We need to switch off panel power _and_ force vdd, for otherwise some |
1350,8 → 1741,19 |
intel_display_power_put(dev_priv, power_domain); |
} |
|
void intel_edp_backlight_on(struct intel_dp *intel_dp) |
void intel_edp_panel_off(struct intel_dp *intel_dp) |
{ |
if (!is_edp(intel_dp)) |
return; |
|
pps_lock(intel_dp); |
edp_panel_off(intel_dp); |
pps_unlock(intel_dp); |
} |
|
/* Enable backlight in the panel power control. */ |
static void _intel_edp_backlight_on(struct intel_dp *intel_dp) |
{ |
struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); |
struct drm_device *dev = intel_dig_port->base.base.dev; |
struct drm_i915_private *dev_priv = dev->dev_private; |
1358,13 → 1760,6 |
u32 pp; |
u32 pp_ctrl_reg; |
|
if (!is_edp(intel_dp)) |
return; |
|
DRM_DEBUG_KMS("\n"); |
|
intel_panel_enable_backlight(intel_dp->attached_connector); |
|
/* |
* If we enable the backlight right away following a panel power |
* on, we may see slight flicker as the panel syncs with the eDP |
1372,6 → 1767,9 |
* allowing it to appear. |
*/ |
wait_backlight_on(intel_dp); |
|
pps_lock(intel_dp); |
|
pp = ironlake_get_pp_control(intel_dp); |
pp |= EDP_BLC_ENABLE; |
|
1379,10 → 1777,25 |
|
I915_WRITE(pp_ctrl_reg, pp); |
POSTING_READ(pp_ctrl_reg); |
|
pps_unlock(intel_dp); |
} |
|
void intel_edp_backlight_off(struct intel_dp *intel_dp) |
/* Enable backlight PWM and backlight PP control. */ |
void intel_edp_backlight_on(struct intel_dp *intel_dp) |
{ |
if (!is_edp(intel_dp)) |
return; |
|
DRM_DEBUG_KMS("\n"); |
|
intel_panel_enable_backlight(intel_dp->attached_connector); |
_intel_edp_backlight_on(intel_dp); |
} |
|
/* Disable backlight in the panel power control. */ |
static void _intel_edp_backlight_off(struct intel_dp *intel_dp) |
{ |
struct drm_device *dev = intel_dp_to_dev(intel_dp); |
struct drm_i915_private *dev_priv = dev->dev_private; |
u32 pp; |
1391,7 → 1804,8 |
if (!is_edp(intel_dp)) |
return; |
|
DRM_DEBUG_KMS("\n"); |
pps_lock(intel_dp); |
|
pp = ironlake_get_pp_control(intel_dp); |
pp &= ~EDP_BLC_ENABLE; |
|
1399,13 → 1813,51 |
|
I915_WRITE(pp_ctrl_reg, pp); |
POSTING_READ(pp_ctrl_reg); |
|
pps_unlock(intel_dp); |
|
intel_dp->last_backlight_off = jiffies; |
|
edp_wait_backlight_off(intel_dp); |
} |
|
/* Disable backlight PP control and backlight PWM. */ |
void intel_edp_backlight_off(struct intel_dp *intel_dp) |
{ |
if (!is_edp(intel_dp)) |
return; |
|
DRM_DEBUG_KMS("\n"); |
|
_intel_edp_backlight_off(intel_dp); |
intel_panel_disable_backlight(intel_dp->attached_connector); |
} |
|
/* |
* Hook for controlling the panel power control backlight through the bl_power |
* sysfs attribute. Take care to handle multiple calls. |
*/ |
static void intel_edp_backlight_power(struct intel_connector *connector, |
bool enable) |
{ |
struct intel_dp *intel_dp = intel_attached_dp(&connector->base); |
bool is_enabled; |
|
pps_lock(intel_dp); |
is_enabled = ironlake_get_pp_control(intel_dp) & EDP_BLC_ENABLE; |
pps_unlock(intel_dp); |
|
if (is_enabled == enable) |
return; |
|
DRM_DEBUG_KMS("panel power control backlight %s\n", |
enable ? "enable" : "disable"); |
|
if (enable) |
_intel_edp_backlight_on(intel_dp); |
else |
_intel_edp_backlight_off(intel_dp); |
} |
|
static void ironlake_edp_pll_on(struct intel_dp *intel_dp) |
{ |
struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); |
1469,8 → 1921,6 |
if (mode != DRM_MODE_DPMS_ON) { |
ret = drm_dp_dpcd_writeb(&intel_dp->aux, DP_SET_POWER, |
DP_SET_POWER_D3); |
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 |
1484,6 → 1934,10 |
msleep(1); |
} |
} |
|
if (ret != 1) |
DRM_DEBUG_KMS("failed to %s sink power state\n", |
mode == DRM_MODE_DPMS_ON ? "enable" : "disable"); |
} |
|
static bool intel_dp_get_hw_state(struct intel_encoder *encoder, |
1497,7 → 1951,7 |
u32 tmp; |
|
power_domain = intel_display_port_power_domain(encoder); |
if (!intel_display_power_enabled(dev_priv, power_domain)) |
if (!intel_display_power_is_enabled(dev_priv, power_domain)) |
return false; |
|
tmp = I915_READ(intel_dp->output_reg); |
1530,7 → 1984,7 |
return true; |
} |
|
for_each_pipe(i) { |
for_each_pipe(dev_priv, i) { |
trans_dp = I915_READ(TRANS_DP_CTL(i)); |
if ((trans_dp & TRANS_DP_PORT_SEL_MASK) == trans_sel) { |
*pipe = i; |
1629,370 → 2083,15 |
} |
} |
|
static bool is_edp_psr(struct intel_dp *intel_dp) |
{ |
return intel_dp->psr_dpcd[0] & DP_PSR_IS_SUPPORTED; |
} |
|
static bool intel_edp_is_psr_enabled(struct drm_device *dev) |
{ |
struct drm_i915_private *dev_priv = dev->dev_private; |
|
if (!HAS_PSR(dev)) |
return false; |
|
return I915_READ(EDP_PSR_CTL(dev)) & EDP_PSR_ENABLE; |
} |
|
static void intel_edp_psr_write_vsc(struct intel_dp *intel_dp, |
struct edp_vsc_psr *vsc_psr) |
{ |
struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); |
struct drm_device *dev = dig_port->base.base.dev; |
struct drm_i915_private *dev_priv = dev->dev_private; |
struct intel_crtc *crtc = to_intel_crtc(dig_port->base.base.crtc); |
u32 ctl_reg = HSW_TVIDEO_DIP_CTL(crtc->config.cpu_transcoder); |
u32 data_reg = HSW_TVIDEO_DIP_VSC_DATA(crtc->config.cpu_transcoder); |
uint32_t *data = (uint32_t *) vsc_psr; |
unsigned int i; |
|
/* As per BSPec (Pipe Video Data Island Packet), we need to disable |
the video DIP being updated before program video DIP data buffer |
registers for DIP being updated. */ |
I915_WRITE(ctl_reg, 0); |
POSTING_READ(ctl_reg); |
|
for (i = 0; i < VIDEO_DIP_VSC_DATA_SIZE; i += 4) { |
if (i < sizeof(struct edp_vsc_psr)) |
I915_WRITE(data_reg + i, *data++); |
else |
I915_WRITE(data_reg + i, 0); |
} |
|
I915_WRITE(ctl_reg, VIDEO_DIP_ENABLE_VSC_HSW); |
POSTING_READ(ctl_reg); |
} |
|
static void intel_edp_psr_setup(struct intel_dp *intel_dp) |
{ |
struct drm_device *dev = intel_dp_to_dev(intel_dp); |
struct drm_i915_private *dev_priv = dev->dev_private; |
struct edp_vsc_psr psr_vsc; |
|
/* Prepare VSC packet as per EDP 1.3 spec, Table 3.10 */ |
memset(&psr_vsc, 0, sizeof(psr_vsc)); |
psr_vsc.sdp_header.HB0 = 0; |
psr_vsc.sdp_header.HB1 = 0x7; |
psr_vsc.sdp_header.HB2 = 0x2; |
psr_vsc.sdp_header.HB3 = 0x8; |
intel_edp_psr_write_vsc(intel_dp, &psr_vsc); |
|
/* Avoid continuous PSR exit by masking memup and hpd */ |
I915_WRITE(EDP_PSR_DEBUG_CTL(dev), EDP_PSR_DEBUG_MASK_MEMUP | |
EDP_PSR_DEBUG_MASK_HPD | EDP_PSR_DEBUG_MASK_LPSP); |
} |
|
static void intel_edp_psr_enable_sink(struct intel_dp *intel_dp) |
{ |
struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); |
struct drm_device *dev = dig_port->base.base.dev; |
struct drm_i915_private *dev_priv = dev->dev_private; |
uint32_t aux_clock_divider; |
int precharge = 0x3; |
int msg_size = 5; /* Header(4) + Message(1) */ |
bool only_standby = false; |
|
aux_clock_divider = intel_dp->get_aux_clock_divider(intel_dp, 0); |
|
if (IS_BROADWELL(dev) && dig_port->port != PORT_A) |
only_standby = true; |
|
/* Enable PSR in sink */ |
if (intel_dp->psr_dpcd[1] & DP_PSR_NO_TRAIN_ON_EXIT || only_standby) |
drm_dp_dpcd_writeb(&intel_dp->aux, DP_PSR_EN_CFG, |
DP_PSR_ENABLE & ~DP_PSR_MAIN_LINK_ACTIVE); |
else |
drm_dp_dpcd_writeb(&intel_dp->aux, DP_PSR_EN_CFG, |
DP_PSR_ENABLE | DP_PSR_MAIN_LINK_ACTIVE); |
|
/* Setup AUX registers */ |
I915_WRITE(EDP_PSR_AUX_DATA1(dev), EDP_PSR_DPCD_COMMAND); |
I915_WRITE(EDP_PSR_AUX_DATA2(dev), EDP_PSR_DPCD_NORMAL_OPERATION); |
I915_WRITE(EDP_PSR_AUX_CTL(dev), |
DP_AUX_CH_CTL_TIME_OUT_400us | |
(msg_size << DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT) | |
(precharge << DP_AUX_CH_CTL_PRECHARGE_2US_SHIFT) | |
(aux_clock_divider << DP_AUX_CH_CTL_BIT_CLOCK_2X_SHIFT)); |
} |
|
static void intel_edp_psr_enable_source(struct intel_dp *intel_dp) |
{ |
struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); |
struct drm_device *dev = dig_port->base.base.dev; |
struct drm_i915_private *dev_priv = dev->dev_private; |
uint32_t max_sleep_time = 0x1f; |
uint32_t idle_frames = 1; |
uint32_t val = 0x0; |
const uint32_t link_entry_time = EDP_PSR_MIN_LINK_ENTRY_TIME_8_LINES; |
bool only_standby = false; |
|
if (IS_BROADWELL(dev) && dig_port->port != PORT_A) |
only_standby = true; |
|
if (intel_dp->psr_dpcd[1] & DP_PSR_NO_TRAIN_ON_EXIT || only_standby) { |
val |= EDP_PSR_LINK_STANDBY; |
val |= EDP_PSR_TP2_TP3_TIME_0us; |
val |= EDP_PSR_TP1_TIME_0us; |
val |= EDP_PSR_SKIP_AUX_EXIT; |
val |= IS_BROADWELL(dev) ? BDW_PSR_SINGLE_FRAME : 0; |
} else |
val |= EDP_PSR_LINK_DISABLE; |
|
I915_WRITE(EDP_PSR_CTL(dev), val | |
(IS_BROADWELL(dev) ? 0 : link_entry_time) | |
max_sleep_time << EDP_PSR_MAX_SLEEP_TIME_SHIFT | |
idle_frames << EDP_PSR_IDLE_FRAME_SHIFT | |
EDP_PSR_ENABLE); |
} |
|
static bool intel_edp_psr_match_conditions(struct intel_dp *intel_dp) |
{ |
struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); |
struct drm_device *dev = dig_port->base.base.dev; |
struct drm_i915_private *dev_priv = dev->dev_private; |
struct drm_crtc *crtc = dig_port->base.base.crtc; |
struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
|
lockdep_assert_held(&dev_priv->psr.lock); |
WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex)); |
WARN_ON(!drm_modeset_is_locked(&crtc->mutex)); |
|
dev_priv->psr.source_ok = false; |
|
if (IS_HASWELL(dev) && dig_port->port != PORT_A) { |
DRM_DEBUG_KMS("HSW ties PSR to DDI A (eDP)\n"); |
return false; |
} |
|
if (!i915.enable_psr) { |
DRM_DEBUG_KMS("PSR disable by flag\n"); |
return false; |
} |
|
/* Below limitations aren't valid for Broadwell */ |
if (IS_BROADWELL(dev)) |
goto out; |
|
if (I915_READ(HSW_STEREO_3D_CTL(intel_crtc->config.cpu_transcoder)) & |
S3D_ENABLE) { |
DRM_DEBUG_KMS("PSR condition failed: Stereo 3D is Enabled\n"); |
return false; |
} |
|
if (intel_crtc->config.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE) { |
DRM_DEBUG_KMS("PSR condition failed: Interlaced is Enabled\n"); |
return false; |
} |
|
out: |
dev_priv->psr.source_ok = true; |
return true; |
} |
|
static void intel_edp_psr_do_enable(struct intel_dp *intel_dp) |
{ |
struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); |
struct drm_device *dev = intel_dig_port->base.base.dev; |
struct drm_i915_private *dev_priv = dev->dev_private; |
|
WARN_ON(I915_READ(EDP_PSR_CTL(dev)) & EDP_PSR_ENABLE); |
WARN_ON(dev_priv->psr.active); |
lockdep_assert_held(&dev_priv->psr.lock); |
|
/* Enable PSR on the panel */ |
intel_edp_psr_enable_sink(intel_dp); |
|
/* Enable PSR on the host */ |
intel_edp_psr_enable_source(intel_dp); |
|
dev_priv->psr.active = true; |
} |
|
void intel_edp_psr_enable(struct intel_dp *intel_dp) |
{ |
struct drm_device *dev = intel_dp_to_dev(intel_dp); |
struct drm_i915_private *dev_priv = dev->dev_private; |
|
if (!HAS_PSR(dev)) { |
DRM_DEBUG_KMS("PSR not supported on this platform\n"); |
return; |
} |
|
if (!is_edp_psr(intel_dp)) { |
DRM_DEBUG_KMS("PSR not supported by this panel\n"); |
return; |
} |
|
mutex_lock(&dev_priv->psr.lock); |
if (dev_priv->psr.enabled) { |
DRM_DEBUG_KMS("PSR already in use\n"); |
mutex_unlock(&dev_priv->psr.lock); |
return; |
} |
|
dev_priv->psr.busy_frontbuffer_bits = 0; |
|
/* Setup PSR once */ |
intel_edp_psr_setup(intel_dp); |
|
if (intel_edp_psr_match_conditions(intel_dp)) |
dev_priv->psr.enabled = intel_dp; |
mutex_unlock(&dev_priv->psr.lock); |
} |
|
void intel_edp_psr_disable(struct intel_dp *intel_dp) |
{ |
struct drm_device *dev = intel_dp_to_dev(intel_dp); |
struct drm_i915_private *dev_priv = dev->dev_private; |
|
mutex_lock(&dev_priv->psr.lock); |
if (!dev_priv->psr.enabled) { |
mutex_unlock(&dev_priv->psr.lock); |
return; |
} |
|
if (dev_priv->psr.active) { |
I915_WRITE(EDP_PSR_CTL(dev), |
I915_READ(EDP_PSR_CTL(dev)) & ~EDP_PSR_ENABLE); |
|
/* Wait till PSR is idle */ |
if (_wait_for((I915_READ(EDP_PSR_STATUS_CTL(dev)) & |
EDP_PSR_STATUS_STATE_MASK) == 0, 2000, 10)) |
DRM_ERROR("Timed out waiting for PSR Idle State\n"); |
|
dev_priv->psr.active = false; |
} else { |
WARN_ON(I915_READ(EDP_PSR_CTL(dev)) & EDP_PSR_ENABLE); |
} |
|
dev_priv->psr.enabled = NULL; |
mutex_unlock(&dev_priv->psr.lock); |
|
cancel_delayed_work_sync(&dev_priv->psr.work); |
} |
|
static void intel_edp_psr_work(struct work_struct *work) |
{ |
struct drm_i915_private *dev_priv = |
container_of(work, typeof(*dev_priv), psr.work.work); |
struct intel_dp *intel_dp = dev_priv->psr.enabled; |
|
mutex_lock(&dev_priv->psr.lock); |
intel_dp = dev_priv->psr.enabled; |
|
if (!intel_dp) |
goto unlock; |
|
/* |
* The delayed work can race with an invalidate hence we need to |
* recheck. Since psr_flush first clears this and then reschedules we |
* won't ever miss a flush when bailing out here. |
*/ |
if (dev_priv->psr.busy_frontbuffer_bits) |
goto unlock; |
|
intel_edp_psr_do_enable(intel_dp); |
unlock: |
mutex_unlock(&dev_priv->psr.lock); |
} |
|
static void intel_edp_psr_do_exit(struct drm_device *dev) |
{ |
struct drm_i915_private *dev_priv = dev->dev_private; |
|
if (dev_priv->psr.active) { |
u32 val = I915_READ(EDP_PSR_CTL(dev)); |
|
WARN_ON(!(val & EDP_PSR_ENABLE)); |
|
I915_WRITE(EDP_PSR_CTL(dev), val & ~EDP_PSR_ENABLE); |
|
dev_priv->psr.active = false; |
} |
|
} |
|
void intel_edp_psr_invalidate(struct drm_device *dev, |
unsigned frontbuffer_bits) |
{ |
struct drm_i915_private *dev_priv = dev->dev_private; |
struct drm_crtc *crtc; |
enum pipe pipe; |
|
mutex_lock(&dev_priv->psr.lock); |
if (!dev_priv->psr.enabled) { |
mutex_unlock(&dev_priv->psr.lock); |
return; |
} |
|
crtc = dp_to_dig_port(dev_priv->psr.enabled)->base.base.crtc; |
pipe = to_intel_crtc(crtc)->pipe; |
|
intel_edp_psr_do_exit(dev); |
|
frontbuffer_bits &= INTEL_FRONTBUFFER_ALL_MASK(pipe); |
|
dev_priv->psr.busy_frontbuffer_bits |= frontbuffer_bits; |
mutex_unlock(&dev_priv->psr.lock); |
} |
|
void intel_edp_psr_flush(struct drm_device *dev, |
unsigned frontbuffer_bits) |
{ |
struct drm_i915_private *dev_priv = dev->dev_private; |
struct drm_crtc *crtc; |
enum pipe pipe; |
|
mutex_lock(&dev_priv->psr.lock); |
if (!dev_priv->psr.enabled) { |
mutex_unlock(&dev_priv->psr.lock); |
return; |
} |
|
crtc = dp_to_dig_port(dev_priv->psr.enabled)->base.base.crtc; |
pipe = to_intel_crtc(crtc)->pipe; |
dev_priv->psr.busy_frontbuffer_bits &= ~frontbuffer_bits; |
|
/* |
* On Haswell sprite plane updates don't result in a psr invalidating |
* signal in the hardware. Which means we need to manually fake this in |
* software for all flushes, not just when we've seen a preceding |
* invalidation through frontbuffer rendering. |
*/ |
if (IS_HASWELL(dev) && |
(frontbuffer_bits & INTEL_FRONTBUFFER_SPRITE(pipe))) |
intel_edp_psr_do_exit(dev); |
|
if (!dev_priv->psr.active && !dev_priv->psr.busy_frontbuffer_bits) |
schedule_delayed_work(&dev_priv->psr.work, |
msecs_to_jiffies(100)); |
mutex_unlock(&dev_priv->psr.lock); |
} |
|
void intel_edp_psr_init(struct drm_device *dev) |
{ |
struct drm_i915_private *dev_priv = dev->dev_private; |
|
INIT_DELAYED_WORK(&dev_priv->psr.work, intel_edp_psr_work); |
mutex_init(&dev_priv->psr.lock); |
} |
|
static void intel_disable_dp(struct intel_encoder *encoder) |
{ |
struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); |
enum port port = dp_to_dig_port(intel_dp)->port; |
struct drm_device *dev = encoder->base.dev; |
struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc); |
|
if (crtc->config.has_audio) |
intel_audio_codec_disable(encoder); |
|
/* 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. */ |
intel_edp_panel_vdd_on(intel_dp); |
2000,20 → 2099,18 |
intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_OFF); |
intel_edp_panel_off(intel_dp); |
|
/* cpu edp my only be disable _after_ the cpu pipe/plane is disabled. */ |
if (!(port == PORT_A || IS_VALLEYVIEW(dev))) |
/* disable the port before the pipe on g4x */ |
if (INTEL_INFO(dev)->gen < 5) |
intel_dp_link_down(intel_dp); |
} |
|
static void g4x_post_disable_dp(struct intel_encoder *encoder) |
static void ilk_post_disable_dp(struct intel_encoder *encoder) |
{ |
struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); |
enum port port = dp_to_dig_port(intel_dp)->port; |
|
if (port != PORT_A) |
return; |
|
intel_dp_link_down(intel_dp); |
if (port == PORT_A) |
ironlake_edp_pll_off(intel_dp); |
} |
|
2060,24 → 2157,151 |
mutex_unlock(&dev_priv->dpio_lock); |
} |
|
static void |
_intel_dp_set_link_train(struct intel_dp *intel_dp, |
uint32_t *DP, |
uint8_t dp_train_pat) |
{ |
struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); |
struct drm_device *dev = intel_dig_port->base.base.dev; |
struct drm_i915_private *dev_priv = dev->dev_private; |
enum port port = intel_dig_port->port; |
|
if (HAS_DDI(dev)) { |
uint32_t temp = I915_READ(DP_TP_CTL(port)); |
|
if (dp_train_pat & DP_LINK_SCRAMBLING_DISABLE) |
temp |= DP_TP_CTL_SCRAMBLE_DISABLE; |
else |
temp &= ~DP_TP_CTL_SCRAMBLE_DISABLE; |
|
temp &= ~DP_TP_CTL_LINK_TRAIN_MASK; |
switch (dp_train_pat & DP_TRAINING_PATTERN_MASK) { |
case DP_TRAINING_PATTERN_DISABLE: |
temp |= DP_TP_CTL_LINK_TRAIN_NORMAL; |
|
break; |
case DP_TRAINING_PATTERN_1: |
temp |= DP_TP_CTL_LINK_TRAIN_PAT1; |
break; |
case DP_TRAINING_PATTERN_2: |
temp |= DP_TP_CTL_LINK_TRAIN_PAT2; |
break; |
case DP_TRAINING_PATTERN_3: |
temp |= DP_TP_CTL_LINK_TRAIN_PAT3; |
break; |
} |
I915_WRITE(DP_TP_CTL(port), temp); |
|
} else if (HAS_PCH_CPT(dev) && (IS_GEN7(dev) || port != PORT_A)) { |
*DP &= ~DP_LINK_TRAIN_MASK_CPT; |
|
switch (dp_train_pat & DP_TRAINING_PATTERN_MASK) { |
case DP_TRAINING_PATTERN_DISABLE: |
*DP |= DP_LINK_TRAIN_OFF_CPT; |
break; |
case DP_TRAINING_PATTERN_1: |
*DP |= DP_LINK_TRAIN_PAT_1_CPT; |
break; |
case DP_TRAINING_PATTERN_2: |
*DP |= DP_LINK_TRAIN_PAT_2_CPT; |
break; |
case DP_TRAINING_PATTERN_3: |
DRM_ERROR("DP training pattern 3 not supported\n"); |
*DP |= DP_LINK_TRAIN_PAT_2_CPT; |
break; |
} |
|
} else { |
if (IS_CHERRYVIEW(dev)) |
*DP &= ~DP_LINK_TRAIN_MASK_CHV; |
else |
*DP &= ~DP_LINK_TRAIN_MASK; |
|
switch (dp_train_pat & DP_TRAINING_PATTERN_MASK) { |
case DP_TRAINING_PATTERN_DISABLE: |
*DP |= DP_LINK_TRAIN_OFF; |
break; |
case DP_TRAINING_PATTERN_1: |
*DP |= DP_LINK_TRAIN_PAT_1; |
break; |
case DP_TRAINING_PATTERN_2: |
*DP |= DP_LINK_TRAIN_PAT_2; |
break; |
case DP_TRAINING_PATTERN_3: |
if (IS_CHERRYVIEW(dev)) { |
*DP |= DP_LINK_TRAIN_PAT_3_CHV; |
} else { |
DRM_ERROR("DP training pattern 3 not supported\n"); |
*DP |= DP_LINK_TRAIN_PAT_2; |
} |
break; |
} |
} |
} |
|
static void intel_dp_enable_port(struct intel_dp *intel_dp) |
{ |
struct drm_device *dev = intel_dp_to_dev(intel_dp); |
struct drm_i915_private *dev_priv = dev->dev_private; |
|
/* enable with pattern 1 (as per spec) */ |
_intel_dp_set_link_train(intel_dp, &intel_dp->DP, |
DP_TRAINING_PATTERN_1); |
|
I915_WRITE(intel_dp->output_reg, intel_dp->DP); |
POSTING_READ(intel_dp->output_reg); |
|
/* |
* Magic for VLV/CHV. We _must_ first set up the register |
* without actually enabling the port, and then do another |
* write to enable the port. Otherwise link training will |
* fail when the power sequencer is freshly used for this port. |
*/ |
intel_dp->DP |= DP_PORT_EN; |
|
I915_WRITE(intel_dp->output_reg, intel_dp->DP); |
POSTING_READ(intel_dp->output_reg); |
} |
|
static void intel_enable_dp(struct intel_encoder *encoder) |
{ |
struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); |
struct drm_device *dev = encoder->base.dev; |
struct drm_i915_private *dev_priv = dev->dev_private; |
struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc); |
uint32_t dp_reg = I915_READ(intel_dp->output_reg); |
|
if (WARN_ON(dp_reg & DP_PORT_EN)) |
return; |
|
intel_edp_panel_vdd_on(intel_dp); |
pps_lock(intel_dp); |
|
if (IS_VALLEYVIEW(dev)) |
vlv_init_panel_power_sequencer(intel_dp); |
|
intel_dp_enable_port(intel_dp); |
|
edp_panel_vdd_on(intel_dp); |
edp_panel_on(intel_dp); |
edp_panel_vdd_off(intel_dp, true); |
|
pps_unlock(intel_dp); |
|
if (IS_VALLEYVIEW(dev)) |
vlv_wait_port_ready(dev_priv, dp_to_dig_port(intel_dp)); |
|
intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON); |
intel_dp_start_link_train(intel_dp); |
intel_edp_panel_on(intel_dp); |
edp_panel_vdd_off(intel_dp, true); |
intel_dp_complete_link_train(intel_dp); |
intel_dp_stop_link_train(intel_dp); |
|
if (crtc->config.has_audio) { |
DRM_DEBUG_DRIVER("Enabling DP audio on pipe %c\n", |
pipe_name(crtc->pipe)); |
intel_audio_codec_enable(encoder); |
} |
} |
|
static void g4x_enable_dp(struct intel_encoder *encoder) |
{ |
2108,6 → 2332,110 |
} |
} |
|
static void vlv_detach_power_sequencer(struct intel_dp *intel_dp) |
{ |
struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); |
struct drm_i915_private *dev_priv = intel_dig_port->base.base.dev->dev_private; |
enum pipe pipe = intel_dp->pps_pipe; |
int pp_on_reg = VLV_PIPE_PP_ON_DELAYS(pipe); |
|
edp_panel_vdd_off_sync(intel_dp); |
|
/* |
* VLV seems to get confused when multiple power seqeuencers |
* have the same port selected (even if only one has power/vdd |
* enabled). The failure manifests as vlv_wait_port_ready() failing |
* CHV on the other hand doesn't seem to mind having the same port |
* selected in multiple power seqeuencers, but let's clear the |
* port select always when logically disconnecting a power sequencer |
* from a port. |
*/ |
DRM_DEBUG_KMS("detaching pipe %c power sequencer from port %c\n", |
pipe_name(pipe), port_name(intel_dig_port->port)); |
I915_WRITE(pp_on_reg, 0); |
POSTING_READ(pp_on_reg); |
|
intel_dp->pps_pipe = INVALID_PIPE; |
} |
|
static void vlv_steal_power_sequencer(struct drm_device *dev, |
enum pipe pipe) |
{ |
struct drm_i915_private *dev_priv = dev->dev_private; |
struct intel_encoder *encoder; |
|
lockdep_assert_held(&dev_priv->pps_mutex); |
|
if (WARN_ON(pipe != PIPE_A && pipe != PIPE_B)) |
return; |
|
list_for_each_entry(encoder, &dev->mode_config.encoder_list, |
base.head) { |
struct intel_dp *intel_dp; |
enum port port; |
|
if (encoder->type != INTEL_OUTPUT_EDP) |
continue; |
|
intel_dp = enc_to_intel_dp(&encoder->base); |
port = dp_to_dig_port(intel_dp)->port; |
|
if (intel_dp->pps_pipe != pipe) |
continue; |
|
DRM_DEBUG_KMS("stealing pipe %c power sequencer from port %c\n", |
pipe_name(pipe), port_name(port)); |
|
WARN(encoder->connectors_active, |
"stealing pipe %c power sequencer from active eDP port %c\n", |
pipe_name(pipe), port_name(port)); |
|
/* make sure vdd is off before we steal it */ |
vlv_detach_power_sequencer(intel_dp); |
} |
} |
|
static void vlv_init_panel_power_sequencer(struct intel_dp *intel_dp) |
{ |
struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); |
struct intel_encoder *encoder = &intel_dig_port->base; |
struct drm_device *dev = encoder->base.dev; |
struct drm_i915_private *dev_priv = dev->dev_private; |
struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc); |
|
lockdep_assert_held(&dev_priv->pps_mutex); |
|
if (!is_edp(intel_dp)) |
return; |
|
if (intel_dp->pps_pipe == crtc->pipe) |
return; |
|
/* |
* If another power sequencer was being used on this |
* port previously make sure to turn off vdd there while |
* we still have control of it. |
*/ |
if (intel_dp->pps_pipe != INVALID_PIPE) |
vlv_detach_power_sequencer(intel_dp); |
|
/* |
* We may be stealing the power |
* sequencer from another port. |
*/ |
vlv_steal_power_sequencer(dev, crtc->pipe); |
|
/* now it's all ours */ |
intel_dp->pps_pipe = crtc->pipe; |
|
DRM_DEBUG_KMS("initializing pipe %c power sequencer for port %c\n", |
pipe_name(intel_dp->pps_pipe), port_name(intel_dig_port->port)); |
|
/* init power sequencer on this pipe and port */ |
intel_dp_init_panel_power_sequencer(dev, intel_dp); |
intel_dp_init_panel_power_sequencer_registers(dev, intel_dp); |
} |
|
static void vlv_pre_enable_dp(struct intel_encoder *encoder) |
{ |
struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); |
2117,7 → 2445,6 |
struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc); |
enum dpio_channel port = vlv_dport_to_channel(dport); |
int pipe = intel_crtc->pipe; |
struct edp_power_seq power_seq; |
u32 val; |
|
mutex_lock(&dev_priv->dpio_lock); |
2135,16 → 2462,7 |
|
mutex_unlock(&dev_priv->dpio_lock); |
|
if (is_edp(intel_dp)) { |
/* init power sequencer on this pipe and port */ |
intel_dp_init_panel_power_sequencer(dev, intel_dp, &power_seq); |
intel_dp_init_panel_power_sequencer_registers(dev, intel_dp, |
&power_seq); |
} |
|
intel_enable_dp(encoder); |
|
vlv_wait_port_ready(dev_priv, dport); |
} |
|
static void vlv_dp_pre_pll_enable(struct intel_encoder *encoder) |
2183,7 → 2501,6 |
struct intel_digital_port *dport = dp_to_dig_port(intel_dp); |
struct drm_device *dev = encoder->base.dev; |
struct drm_i915_private *dev_priv = dev->dev_private; |
struct edp_power_seq power_seq; |
struct intel_crtc *intel_crtc = |
to_intel_crtc(encoder->base.crtc); |
enum dpio_channel ch = vlv_dport_to_channel(dport); |
2193,6 → 2510,15 |
|
mutex_lock(&dev_priv->dpio_lock); |
|
/* allow hardware to manage TX FIFO reset source */ |
val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW11(ch)); |
val &= ~DPIO_LANEDESKEW_STRAP_OVRD; |
vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW11(ch), val); |
|
val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW11(ch)); |
val &= ~DPIO_LANEDESKEW_STRAP_OVRD; |
vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW11(ch), val); |
|
/* Deassert soft data lane reset*/ |
val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW1(ch)); |
val |= CHV_PCS_REQ_SOFTRESET_EN; |
2228,16 → 2554,7 |
|
mutex_unlock(&dev_priv->dpio_lock); |
|
if (is_edp(intel_dp)) { |
/* init power sequencer on this pipe and port */ |
intel_dp_init_panel_power_sequencer(dev, intel_dp, &power_seq); |
intel_dp_init_panel_power_sequencer_registers(dev, intel_dp, |
&power_seq); |
} |
|
intel_enable_dp(encoder); |
|
vlv_wait_port_ready(dev_priv, dport); |
} |
|
static void chv_dp_pre_pll_enable(struct intel_encoder *encoder) |
2251,6 → 2568,8 |
enum pipe pipe = intel_crtc->pipe; |
u32 val; |
|
intel_dp_prepare(encoder); |
|
mutex_lock(&dev_priv->dpio_lock); |
|
/* program left/right clock distribution */ |
2318,6 → 2637,13 |
ssize_t ret; |
int i; |
|
/* |
* Sometime we just get the same incorrect byte repeated |
* over the entire buffer. Doing just one throw away read |
* initially seems to "solve" it. |
*/ |
drm_dp_dpcd_read(aux, DP_DPCD_REV, buffer, 1); |
|
for (i = 0; i < 3; i++) { |
ret = drm_dp_dpcd_read(aux, offset, buffer, size); |
if (ret == size) |
2348,14 → 2674,16 |
struct drm_device *dev = intel_dp_to_dev(intel_dp); |
enum port port = dp_to_dig_port(intel_dp)->port; |
|
if (IS_VALLEYVIEW(dev)) |
return DP_TRAIN_VOLTAGE_SWING_1200; |
if (INTEL_INFO(dev)->gen >= 9) |
return DP_TRAIN_VOLTAGE_SWING_LEVEL_2; |
else if (IS_VALLEYVIEW(dev)) |
return DP_TRAIN_VOLTAGE_SWING_LEVEL_3; |
else if (IS_GEN7(dev) && port == PORT_A) |
return DP_TRAIN_VOLTAGE_SWING_800; |
return DP_TRAIN_VOLTAGE_SWING_LEVEL_2; |
else if (HAS_PCH_CPT(dev) && port != PORT_A) |
return DP_TRAIN_VOLTAGE_SWING_1200; |
return DP_TRAIN_VOLTAGE_SWING_LEVEL_3; |
else |
return DP_TRAIN_VOLTAGE_SWING_800; |
return DP_TRAIN_VOLTAGE_SWING_LEVEL_2; |
} |
|
static uint8_t |
2364,51 → 2692,62 |
struct drm_device *dev = intel_dp_to_dev(intel_dp); |
enum port port = dp_to_dig_port(intel_dp)->port; |
|
if (IS_HASWELL(dev) || IS_BROADWELL(dev)) { |
if (INTEL_INFO(dev)->gen >= 9) { |
switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) { |
case DP_TRAIN_VOLTAGE_SWING_400: |
return DP_TRAIN_PRE_EMPHASIS_9_5; |
case DP_TRAIN_VOLTAGE_SWING_600: |
return DP_TRAIN_PRE_EMPHASIS_6; |
case DP_TRAIN_VOLTAGE_SWING_800: |
return DP_TRAIN_PRE_EMPHASIS_3_5; |
case DP_TRAIN_VOLTAGE_SWING_1200: |
case DP_TRAIN_VOLTAGE_SWING_LEVEL_0: |
return DP_TRAIN_PRE_EMPH_LEVEL_3; |
case DP_TRAIN_VOLTAGE_SWING_LEVEL_1: |
return DP_TRAIN_PRE_EMPH_LEVEL_2; |
case DP_TRAIN_VOLTAGE_SWING_LEVEL_2: |
return DP_TRAIN_PRE_EMPH_LEVEL_1; |
default: |
return DP_TRAIN_PRE_EMPHASIS_0; |
return DP_TRAIN_PRE_EMPH_LEVEL_0; |
} |
} else if (IS_HASWELL(dev) || IS_BROADWELL(dev)) { |
switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) { |
case DP_TRAIN_VOLTAGE_SWING_LEVEL_0: |
return DP_TRAIN_PRE_EMPH_LEVEL_3; |
case DP_TRAIN_VOLTAGE_SWING_LEVEL_1: |
return DP_TRAIN_PRE_EMPH_LEVEL_2; |
case DP_TRAIN_VOLTAGE_SWING_LEVEL_2: |
return DP_TRAIN_PRE_EMPH_LEVEL_1; |
case DP_TRAIN_VOLTAGE_SWING_LEVEL_3: |
default: |
return DP_TRAIN_PRE_EMPH_LEVEL_0; |
} |
} else if (IS_VALLEYVIEW(dev)) { |
switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) { |
case DP_TRAIN_VOLTAGE_SWING_400: |
return DP_TRAIN_PRE_EMPHASIS_9_5; |
case DP_TRAIN_VOLTAGE_SWING_600: |
return DP_TRAIN_PRE_EMPHASIS_6; |
case DP_TRAIN_VOLTAGE_SWING_800: |
return DP_TRAIN_PRE_EMPHASIS_3_5; |
case DP_TRAIN_VOLTAGE_SWING_1200: |
case DP_TRAIN_VOLTAGE_SWING_LEVEL_0: |
return DP_TRAIN_PRE_EMPH_LEVEL_3; |
case DP_TRAIN_VOLTAGE_SWING_LEVEL_1: |
return DP_TRAIN_PRE_EMPH_LEVEL_2; |
case DP_TRAIN_VOLTAGE_SWING_LEVEL_2: |
return DP_TRAIN_PRE_EMPH_LEVEL_1; |
case DP_TRAIN_VOLTAGE_SWING_LEVEL_3: |
default: |
return DP_TRAIN_PRE_EMPHASIS_0; |
return DP_TRAIN_PRE_EMPH_LEVEL_0; |
} |
} else if (IS_GEN7(dev) && port == PORT_A) { |
switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) { |
case DP_TRAIN_VOLTAGE_SWING_400: |
return DP_TRAIN_PRE_EMPHASIS_6; |
case DP_TRAIN_VOLTAGE_SWING_600: |
case DP_TRAIN_VOLTAGE_SWING_800: |
return DP_TRAIN_PRE_EMPHASIS_3_5; |
case DP_TRAIN_VOLTAGE_SWING_LEVEL_0: |
return DP_TRAIN_PRE_EMPH_LEVEL_2; |
case DP_TRAIN_VOLTAGE_SWING_LEVEL_1: |
case DP_TRAIN_VOLTAGE_SWING_LEVEL_2: |
return DP_TRAIN_PRE_EMPH_LEVEL_1; |
default: |
return DP_TRAIN_PRE_EMPHASIS_0; |
return DP_TRAIN_PRE_EMPH_LEVEL_0; |
} |
} else { |
switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) { |
case DP_TRAIN_VOLTAGE_SWING_400: |
return DP_TRAIN_PRE_EMPHASIS_6; |
case DP_TRAIN_VOLTAGE_SWING_600: |
return DP_TRAIN_PRE_EMPHASIS_6; |
case DP_TRAIN_VOLTAGE_SWING_800: |
return DP_TRAIN_PRE_EMPHASIS_3_5; |
case DP_TRAIN_VOLTAGE_SWING_1200: |
case DP_TRAIN_VOLTAGE_SWING_LEVEL_0: |
return DP_TRAIN_PRE_EMPH_LEVEL_2; |
case DP_TRAIN_VOLTAGE_SWING_LEVEL_1: |
return DP_TRAIN_PRE_EMPH_LEVEL_2; |
case DP_TRAIN_VOLTAGE_SWING_LEVEL_2: |
return DP_TRAIN_PRE_EMPH_LEVEL_1; |
case DP_TRAIN_VOLTAGE_SWING_LEVEL_3: |
default: |
return DP_TRAIN_PRE_EMPHASIS_0; |
return DP_TRAIN_PRE_EMPH_LEVEL_0; |
} |
} |
} |
2427,22 → 2766,22 |
int pipe = intel_crtc->pipe; |
|
switch (train_set & DP_TRAIN_PRE_EMPHASIS_MASK) { |
case DP_TRAIN_PRE_EMPHASIS_0: |
case DP_TRAIN_PRE_EMPH_LEVEL_0: |
preemph_reg_value = 0x0004000; |
switch (train_set & DP_TRAIN_VOLTAGE_SWING_MASK) { |
case DP_TRAIN_VOLTAGE_SWING_400: |
case DP_TRAIN_VOLTAGE_SWING_LEVEL_0: |
demph_reg_value = 0x2B405555; |
uniqtranscale_reg_value = 0x552AB83A; |
break; |
case DP_TRAIN_VOLTAGE_SWING_600: |
case DP_TRAIN_VOLTAGE_SWING_LEVEL_1: |
demph_reg_value = 0x2B404040; |
uniqtranscale_reg_value = 0x5548B83A; |
break; |
case DP_TRAIN_VOLTAGE_SWING_800: |
case DP_TRAIN_VOLTAGE_SWING_LEVEL_2: |
demph_reg_value = 0x2B245555; |
uniqtranscale_reg_value = 0x5560B83A; |
break; |
case DP_TRAIN_VOLTAGE_SWING_1200: |
case DP_TRAIN_VOLTAGE_SWING_LEVEL_3: |
demph_reg_value = 0x2B405555; |
uniqtranscale_reg_value = 0x5598DA3A; |
break; |
2450,18 → 2789,18 |
return 0; |
} |
break; |
case DP_TRAIN_PRE_EMPHASIS_3_5: |
case DP_TRAIN_PRE_EMPH_LEVEL_1: |
preemph_reg_value = 0x0002000; |
switch (train_set & DP_TRAIN_VOLTAGE_SWING_MASK) { |
case DP_TRAIN_VOLTAGE_SWING_400: |
case DP_TRAIN_VOLTAGE_SWING_LEVEL_0: |
demph_reg_value = 0x2B404040; |
uniqtranscale_reg_value = 0x5552B83A; |
break; |
case DP_TRAIN_VOLTAGE_SWING_600: |
case DP_TRAIN_VOLTAGE_SWING_LEVEL_1: |
demph_reg_value = 0x2B404848; |
uniqtranscale_reg_value = 0x5580B83A; |
break; |
case DP_TRAIN_VOLTAGE_SWING_800: |
case DP_TRAIN_VOLTAGE_SWING_LEVEL_2: |
demph_reg_value = 0x2B404040; |
uniqtranscale_reg_value = 0x55ADDA3A; |
break; |
2469,14 → 2808,14 |
return 0; |
} |
break; |
case DP_TRAIN_PRE_EMPHASIS_6: |
case DP_TRAIN_PRE_EMPH_LEVEL_2: |
preemph_reg_value = 0x0000000; |
switch (train_set & DP_TRAIN_VOLTAGE_SWING_MASK) { |
case DP_TRAIN_VOLTAGE_SWING_400: |
case DP_TRAIN_VOLTAGE_SWING_LEVEL_0: |
demph_reg_value = 0x2B305555; |
uniqtranscale_reg_value = 0x5570B83A; |
break; |
case DP_TRAIN_VOLTAGE_SWING_600: |
case DP_TRAIN_VOLTAGE_SWING_LEVEL_1: |
demph_reg_value = 0x2B2B4040; |
uniqtranscale_reg_value = 0x55ADDA3A; |
break; |
2484,10 → 2823,10 |
return 0; |
} |
break; |
case DP_TRAIN_PRE_EMPHASIS_9_5: |
case DP_TRAIN_PRE_EMPH_LEVEL_3: |
preemph_reg_value = 0x0006000; |
switch (train_set & DP_TRAIN_VOLTAGE_SWING_MASK) { |
case DP_TRAIN_VOLTAGE_SWING_400: |
case DP_TRAIN_VOLTAGE_SWING_LEVEL_0: |
demph_reg_value = 0x1B405555; |
uniqtranscale_reg_value = 0x55ADDA3A; |
break; |
2526,21 → 2865,21 |
int i; |
|
switch (train_set & DP_TRAIN_PRE_EMPHASIS_MASK) { |
case DP_TRAIN_PRE_EMPHASIS_0: |
case DP_TRAIN_PRE_EMPH_LEVEL_0: |
switch (train_set & DP_TRAIN_VOLTAGE_SWING_MASK) { |
case DP_TRAIN_VOLTAGE_SWING_400: |
case DP_TRAIN_VOLTAGE_SWING_LEVEL_0: |
deemph_reg_value = 128; |
margin_reg_value = 52; |
break; |
case DP_TRAIN_VOLTAGE_SWING_600: |
case DP_TRAIN_VOLTAGE_SWING_LEVEL_1: |
deemph_reg_value = 128; |
margin_reg_value = 77; |
break; |
case DP_TRAIN_VOLTAGE_SWING_800: |
case DP_TRAIN_VOLTAGE_SWING_LEVEL_2: |
deemph_reg_value = 128; |
margin_reg_value = 102; |
break; |
case DP_TRAIN_VOLTAGE_SWING_1200: |
case DP_TRAIN_VOLTAGE_SWING_LEVEL_3: |
deemph_reg_value = 128; |
margin_reg_value = 154; |
/* FIXME extra to set for 1200 */ |
2549,17 → 2888,17 |
return 0; |
} |
break; |
case DP_TRAIN_PRE_EMPHASIS_3_5: |
case DP_TRAIN_PRE_EMPH_LEVEL_1: |
switch (train_set & DP_TRAIN_VOLTAGE_SWING_MASK) { |
case DP_TRAIN_VOLTAGE_SWING_400: |
case DP_TRAIN_VOLTAGE_SWING_LEVEL_0: |
deemph_reg_value = 85; |
margin_reg_value = 78; |
break; |
case DP_TRAIN_VOLTAGE_SWING_600: |
case DP_TRAIN_VOLTAGE_SWING_LEVEL_1: |
deemph_reg_value = 85; |
margin_reg_value = 116; |
break; |
case DP_TRAIN_VOLTAGE_SWING_800: |
case DP_TRAIN_VOLTAGE_SWING_LEVEL_2: |
deemph_reg_value = 85; |
margin_reg_value = 154; |
break; |
2567,13 → 2906,13 |
return 0; |
} |
break; |
case DP_TRAIN_PRE_EMPHASIS_6: |
case DP_TRAIN_PRE_EMPH_LEVEL_2: |
switch (train_set & DP_TRAIN_VOLTAGE_SWING_MASK) { |
case DP_TRAIN_VOLTAGE_SWING_400: |
case DP_TRAIN_VOLTAGE_SWING_LEVEL_0: |
deemph_reg_value = 64; |
margin_reg_value = 104; |
break; |
case DP_TRAIN_VOLTAGE_SWING_600: |
case DP_TRAIN_VOLTAGE_SWING_LEVEL_1: |
deemph_reg_value = 64; |
margin_reg_value = 154; |
break; |
2581,9 → 2920,9 |
return 0; |
} |
break; |
case DP_TRAIN_PRE_EMPHASIS_9_5: |
case DP_TRAIN_PRE_EMPH_LEVEL_3: |
switch (train_set & DP_TRAIN_VOLTAGE_SWING_MASK) { |
case DP_TRAIN_VOLTAGE_SWING_400: |
case DP_TRAIN_VOLTAGE_SWING_LEVEL_0: |
deemph_reg_value = 43; |
margin_reg_value = 154; |
break; |
2600,12 → 2939,26 |
/* Clear calc init */ |
val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW10(ch)); |
val &= ~(DPIO_PCS_SWING_CALC_TX0_TX2 | DPIO_PCS_SWING_CALC_TX1_TX3); |
val &= ~(DPIO_PCS_TX1DEEMP_MASK | DPIO_PCS_TX2DEEMP_MASK); |
val |= DPIO_PCS_TX1DEEMP_9P5 | DPIO_PCS_TX2DEEMP_9P5; |
vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW10(ch), val); |
|
val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW10(ch)); |
val &= ~(DPIO_PCS_SWING_CALC_TX0_TX2 | DPIO_PCS_SWING_CALC_TX1_TX3); |
val &= ~(DPIO_PCS_TX1DEEMP_MASK | DPIO_PCS_TX2DEEMP_MASK); |
val |= DPIO_PCS_TX1DEEMP_9P5 | DPIO_PCS_TX2DEEMP_9P5; |
vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW10(ch), val); |
|
val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW9(ch)); |
val &= ~(DPIO_PCS_TX1MARGIN_MASK | DPIO_PCS_TX2MARGIN_MASK); |
val |= DPIO_PCS_TX1MARGIN_000 | DPIO_PCS_TX2MARGIN_000; |
vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW9(ch), val); |
|
val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW9(ch)); |
val &= ~(DPIO_PCS_TX1MARGIN_MASK | DPIO_PCS_TX2MARGIN_MASK); |
val |= DPIO_PCS_TX1MARGIN_000 | DPIO_PCS_TX2MARGIN_000; |
vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW9(ch), val); |
|
/* Program swing deemph */ |
for (i = 0; i < 4; i++) { |
val = vlv_dpio_read(dev_priv, pipe, CHV_TX_DW4(ch, i)); |
2617,8 → 2970,8 |
/* Program swing margin */ |
for (i = 0; i < 4; i++) { |
val = vlv_dpio_read(dev_priv, pipe, CHV_TX_DW2(ch, i)); |
val &= ~DPIO_SWING_MARGIN_MASK; |
val |= margin_reg_value << DPIO_SWING_MARGIN_SHIFT; |
val &= ~DPIO_SWING_MARGIN000_MASK; |
val |= margin_reg_value << DPIO_SWING_MARGIN000_SHIFT; |
vlv_dpio_write(dev_priv, pipe, CHV_TX_DW2(ch, i), val); |
} |
|
2630,9 → 2983,9 |
} |
|
if (((train_set & DP_TRAIN_PRE_EMPHASIS_MASK) |
== DP_TRAIN_PRE_EMPHASIS_0) && |
== DP_TRAIN_PRE_EMPH_LEVEL_0) && |
((train_set & DP_TRAIN_VOLTAGE_SWING_MASK) |
== DP_TRAIN_VOLTAGE_SWING_1200)) { |
== DP_TRAIN_VOLTAGE_SWING_LEVEL_3)) { |
|
/* |
* The document said it needs to set bit 27 for ch0 and bit 26 |
2711,32 → 3064,32 |
uint32_t signal_levels = 0; |
|
switch (train_set & DP_TRAIN_VOLTAGE_SWING_MASK) { |
case DP_TRAIN_VOLTAGE_SWING_400: |
case DP_TRAIN_VOLTAGE_SWING_LEVEL_0: |
default: |
signal_levels |= DP_VOLTAGE_0_4; |
break; |
case DP_TRAIN_VOLTAGE_SWING_600: |
case DP_TRAIN_VOLTAGE_SWING_LEVEL_1: |
signal_levels |= DP_VOLTAGE_0_6; |
break; |
case DP_TRAIN_VOLTAGE_SWING_800: |
case DP_TRAIN_VOLTAGE_SWING_LEVEL_2: |
signal_levels |= DP_VOLTAGE_0_8; |
break; |
case DP_TRAIN_VOLTAGE_SWING_1200: |
case DP_TRAIN_VOLTAGE_SWING_LEVEL_3: |
signal_levels |= DP_VOLTAGE_1_2; |
break; |
} |
switch (train_set & DP_TRAIN_PRE_EMPHASIS_MASK) { |
case DP_TRAIN_PRE_EMPHASIS_0: |
case DP_TRAIN_PRE_EMPH_LEVEL_0: |
default: |
signal_levels |= DP_PRE_EMPHASIS_0; |
break; |
case DP_TRAIN_PRE_EMPHASIS_3_5: |
case DP_TRAIN_PRE_EMPH_LEVEL_1: |
signal_levels |= DP_PRE_EMPHASIS_3_5; |
break; |
case DP_TRAIN_PRE_EMPHASIS_6: |
case DP_TRAIN_PRE_EMPH_LEVEL_2: |
signal_levels |= DP_PRE_EMPHASIS_6; |
break; |
case DP_TRAIN_PRE_EMPHASIS_9_5: |
case DP_TRAIN_PRE_EMPH_LEVEL_3: |
signal_levels |= DP_PRE_EMPHASIS_9_5; |
break; |
} |
2750,19 → 3103,19 |
int signal_levels = train_set & (DP_TRAIN_VOLTAGE_SWING_MASK | |
DP_TRAIN_PRE_EMPHASIS_MASK); |
switch (signal_levels) { |
case DP_TRAIN_VOLTAGE_SWING_400 | DP_TRAIN_PRE_EMPHASIS_0: |
case DP_TRAIN_VOLTAGE_SWING_600 | DP_TRAIN_PRE_EMPHASIS_0: |
case DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_0: |
case DP_TRAIN_VOLTAGE_SWING_LEVEL_1 | DP_TRAIN_PRE_EMPH_LEVEL_0: |
return EDP_LINK_TRAIN_400_600MV_0DB_SNB_B; |
case DP_TRAIN_VOLTAGE_SWING_400 | DP_TRAIN_PRE_EMPHASIS_3_5: |
case DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_1: |
return EDP_LINK_TRAIN_400MV_3_5DB_SNB_B; |
case DP_TRAIN_VOLTAGE_SWING_400 | DP_TRAIN_PRE_EMPHASIS_6: |
case DP_TRAIN_VOLTAGE_SWING_600 | DP_TRAIN_PRE_EMPHASIS_6: |
case DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_2: |
case DP_TRAIN_VOLTAGE_SWING_LEVEL_1 | DP_TRAIN_PRE_EMPH_LEVEL_2: |
return EDP_LINK_TRAIN_400_600MV_6DB_SNB_B; |
case DP_TRAIN_VOLTAGE_SWING_600 | DP_TRAIN_PRE_EMPHASIS_3_5: |
case DP_TRAIN_VOLTAGE_SWING_800 | DP_TRAIN_PRE_EMPHASIS_3_5: |
case DP_TRAIN_VOLTAGE_SWING_LEVEL_1 | DP_TRAIN_PRE_EMPH_LEVEL_1: |
case DP_TRAIN_VOLTAGE_SWING_LEVEL_2 | DP_TRAIN_PRE_EMPH_LEVEL_1: |
return EDP_LINK_TRAIN_600_800MV_3_5DB_SNB_B; |
case DP_TRAIN_VOLTAGE_SWING_800 | DP_TRAIN_PRE_EMPHASIS_0: |
case DP_TRAIN_VOLTAGE_SWING_1200 | DP_TRAIN_PRE_EMPHASIS_0: |
case DP_TRAIN_VOLTAGE_SWING_LEVEL_2 | DP_TRAIN_PRE_EMPH_LEVEL_0: |
case DP_TRAIN_VOLTAGE_SWING_LEVEL_3 | DP_TRAIN_PRE_EMPH_LEVEL_0: |
return EDP_LINK_TRAIN_800_1200MV_0DB_SNB_B; |
default: |
DRM_DEBUG_KMS("Unsupported voltage swing/pre-emphasis level:" |
2778,21 → 3131,21 |
int signal_levels = train_set & (DP_TRAIN_VOLTAGE_SWING_MASK | |
DP_TRAIN_PRE_EMPHASIS_MASK); |
switch (signal_levels) { |
case DP_TRAIN_VOLTAGE_SWING_400 | DP_TRAIN_PRE_EMPHASIS_0: |
case DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_0: |
return EDP_LINK_TRAIN_400MV_0DB_IVB; |
case DP_TRAIN_VOLTAGE_SWING_400 | DP_TRAIN_PRE_EMPHASIS_3_5: |
case DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_1: |
return EDP_LINK_TRAIN_400MV_3_5DB_IVB; |
case DP_TRAIN_VOLTAGE_SWING_400 | DP_TRAIN_PRE_EMPHASIS_6: |
case DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_2: |
return EDP_LINK_TRAIN_400MV_6DB_IVB; |
|
case DP_TRAIN_VOLTAGE_SWING_600 | DP_TRAIN_PRE_EMPHASIS_0: |
case DP_TRAIN_VOLTAGE_SWING_LEVEL_1 | DP_TRAIN_PRE_EMPH_LEVEL_0: |
return EDP_LINK_TRAIN_600MV_0DB_IVB; |
case DP_TRAIN_VOLTAGE_SWING_600 | DP_TRAIN_PRE_EMPHASIS_3_5: |
case DP_TRAIN_VOLTAGE_SWING_LEVEL_1 | DP_TRAIN_PRE_EMPH_LEVEL_1: |
return EDP_LINK_TRAIN_600MV_3_5DB_IVB; |
|
case DP_TRAIN_VOLTAGE_SWING_800 | DP_TRAIN_PRE_EMPHASIS_0: |
case DP_TRAIN_VOLTAGE_SWING_LEVEL_2 | DP_TRAIN_PRE_EMPH_LEVEL_0: |
return EDP_LINK_TRAIN_800MV_0DB_IVB; |
case DP_TRAIN_VOLTAGE_SWING_800 | DP_TRAIN_PRE_EMPHASIS_3_5: |
case DP_TRAIN_VOLTAGE_SWING_LEVEL_2 | DP_TRAIN_PRE_EMPH_LEVEL_1: |
return EDP_LINK_TRAIN_800MV_3_5DB_IVB; |
|
default: |
2809,30 → 3162,30 |
int signal_levels = train_set & (DP_TRAIN_VOLTAGE_SWING_MASK | |
DP_TRAIN_PRE_EMPHASIS_MASK); |
switch (signal_levels) { |
case DP_TRAIN_VOLTAGE_SWING_400 | DP_TRAIN_PRE_EMPHASIS_0: |
return DDI_BUF_EMP_400MV_0DB_HSW; |
case DP_TRAIN_VOLTAGE_SWING_400 | DP_TRAIN_PRE_EMPHASIS_3_5: |
return DDI_BUF_EMP_400MV_3_5DB_HSW; |
case DP_TRAIN_VOLTAGE_SWING_400 | DP_TRAIN_PRE_EMPHASIS_6: |
return DDI_BUF_EMP_400MV_6DB_HSW; |
case DP_TRAIN_VOLTAGE_SWING_400 | DP_TRAIN_PRE_EMPHASIS_9_5: |
return DDI_BUF_EMP_400MV_9_5DB_HSW; |
case DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_0: |
return DDI_BUF_TRANS_SELECT(0); |
case DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_1: |
return DDI_BUF_TRANS_SELECT(1); |
case DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_2: |
return DDI_BUF_TRANS_SELECT(2); |
case DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_3: |
return DDI_BUF_TRANS_SELECT(3); |
|
case DP_TRAIN_VOLTAGE_SWING_600 | DP_TRAIN_PRE_EMPHASIS_0: |
return DDI_BUF_EMP_600MV_0DB_HSW; |
case DP_TRAIN_VOLTAGE_SWING_600 | DP_TRAIN_PRE_EMPHASIS_3_5: |
return DDI_BUF_EMP_600MV_3_5DB_HSW; |
case DP_TRAIN_VOLTAGE_SWING_600 | DP_TRAIN_PRE_EMPHASIS_6: |
return DDI_BUF_EMP_600MV_6DB_HSW; |
case DP_TRAIN_VOLTAGE_SWING_LEVEL_1 | DP_TRAIN_PRE_EMPH_LEVEL_0: |
return DDI_BUF_TRANS_SELECT(4); |
case DP_TRAIN_VOLTAGE_SWING_LEVEL_1 | DP_TRAIN_PRE_EMPH_LEVEL_1: |
return DDI_BUF_TRANS_SELECT(5); |
case DP_TRAIN_VOLTAGE_SWING_LEVEL_1 | DP_TRAIN_PRE_EMPH_LEVEL_2: |
return DDI_BUF_TRANS_SELECT(6); |
|
case DP_TRAIN_VOLTAGE_SWING_800 | DP_TRAIN_PRE_EMPHASIS_0: |
return DDI_BUF_EMP_800MV_0DB_HSW; |
case DP_TRAIN_VOLTAGE_SWING_800 | DP_TRAIN_PRE_EMPHASIS_3_5: |
return DDI_BUF_EMP_800MV_3_5DB_HSW; |
case DP_TRAIN_VOLTAGE_SWING_LEVEL_2 | DP_TRAIN_PRE_EMPH_LEVEL_0: |
return DDI_BUF_TRANS_SELECT(7); |
case DP_TRAIN_VOLTAGE_SWING_LEVEL_2 | DP_TRAIN_PRE_EMPH_LEVEL_1: |
return DDI_BUF_TRANS_SELECT(8); |
default: |
DRM_DEBUG_KMS("Unsupported voltage swing/pre-emphasis level:" |
"0x%x\n", signal_levels); |
return DDI_BUF_EMP_400MV_0DB_HSW; |
return DDI_BUF_TRANS_SELECT(0); |
} |
} |
|
2846,7 → 3199,7 |
uint32_t signal_levels, mask; |
uint8_t train_set = intel_dp->train_set[0]; |
|
if (IS_HASWELL(dev) || IS_BROADWELL(dev)) { |
if (IS_HASWELL(dev) || IS_BROADWELL(dev) || INTEL_INFO(dev)->gen >= 9) { |
signal_levels = intel_hsw_signal_levels(train_set); |
mask = DDI_BUF_EMP_MASK; |
} else if (IS_CHERRYVIEW(dev)) { |
2879,75 → 3232,11 |
struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); |
struct drm_device *dev = intel_dig_port->base.base.dev; |
struct drm_i915_private *dev_priv = dev->dev_private; |
enum port port = intel_dig_port->port; |
uint8_t buf[sizeof(intel_dp->train_set) + 1]; |
int ret, len; |
|
if (HAS_DDI(dev)) { |
uint32_t temp = I915_READ(DP_TP_CTL(port)); |
_intel_dp_set_link_train(intel_dp, DP, dp_train_pat); |
|
if (dp_train_pat & DP_LINK_SCRAMBLING_DISABLE) |
temp |= DP_TP_CTL_SCRAMBLE_DISABLE; |
else |
temp &= ~DP_TP_CTL_SCRAMBLE_DISABLE; |
|
temp &= ~DP_TP_CTL_LINK_TRAIN_MASK; |
switch (dp_train_pat & DP_TRAINING_PATTERN_MASK) { |
case DP_TRAINING_PATTERN_DISABLE: |
temp |= DP_TP_CTL_LINK_TRAIN_NORMAL; |
|
break; |
case DP_TRAINING_PATTERN_1: |
temp |= DP_TP_CTL_LINK_TRAIN_PAT1; |
break; |
case DP_TRAINING_PATTERN_2: |
temp |= DP_TP_CTL_LINK_TRAIN_PAT2; |
break; |
case DP_TRAINING_PATTERN_3: |
temp |= DP_TP_CTL_LINK_TRAIN_PAT3; |
break; |
} |
I915_WRITE(DP_TP_CTL(port), temp); |
|
} else if (HAS_PCH_CPT(dev) && (IS_GEN7(dev) || port != PORT_A)) { |
*DP &= ~DP_LINK_TRAIN_MASK_CPT; |
|
switch (dp_train_pat & DP_TRAINING_PATTERN_MASK) { |
case DP_TRAINING_PATTERN_DISABLE: |
*DP |= DP_LINK_TRAIN_OFF_CPT; |
break; |
case DP_TRAINING_PATTERN_1: |
*DP |= DP_LINK_TRAIN_PAT_1_CPT; |
break; |
case DP_TRAINING_PATTERN_2: |
*DP |= DP_LINK_TRAIN_PAT_2_CPT; |
break; |
case DP_TRAINING_PATTERN_3: |
DRM_ERROR("DP training pattern 3 not supported\n"); |
*DP |= DP_LINK_TRAIN_PAT_2_CPT; |
break; |
} |
|
} else { |
*DP &= ~DP_LINK_TRAIN_MASK; |
|
switch (dp_train_pat & DP_TRAINING_PATTERN_MASK) { |
case DP_TRAINING_PATTERN_DISABLE: |
*DP |= DP_LINK_TRAIN_OFF; |
break; |
case DP_TRAINING_PATTERN_1: |
*DP |= DP_LINK_TRAIN_PAT_1; |
break; |
case DP_TRAINING_PATTERN_2: |
*DP |= DP_LINK_TRAIN_PAT_2; |
break; |
case DP_TRAINING_PATTERN_3: |
DRM_ERROR("DP training pattern 3 not supported\n"); |
*DP |= DP_LINK_TRAIN_PAT_2; |
break; |
} |
} |
|
I915_WRITE(intel_dp->output_reg, *DP); |
POSTING_READ(intel_dp->output_reg); |
|
3174,7 → 3463,6 |
|
/* Try 5 times, then try clock recovery if that fails */ |
if (tries > 5) { |
intel_dp_link_down(intel_dp); |
intel_dp_start_link_train(intel_dp); |
intel_dp_set_link_train(intel_dp, &DP, |
training_pattern | |
3230,6 → 3518,9 |
DP &= ~DP_LINK_TRAIN_MASK_CPT; |
I915_WRITE(intel_dp->output_reg, DP | DP_LINK_TRAIN_PAT_IDLE_CPT); |
} else { |
if (IS_CHERRYVIEW(dev)) |
DP &= ~DP_LINK_TRAIN_MASK_CHV; |
else |
DP &= ~DP_LINK_TRAIN_MASK; |
I915_WRITE(intel_dp->output_reg, DP | DP_LINK_TRAIN_PAT_IDLE); |
} |
3276,15 → 3567,11 |
struct drm_device *dev = dig_port->base.base.dev; |
struct drm_i915_private *dev_priv = dev->dev_private; |
|
char dpcd_hex_dump[sizeof(intel_dp->dpcd) * 3]; |
|
if (intel_dp_dpcd_read_wake(&intel_dp->aux, 0x000, intel_dp->dpcd, |
sizeof(intel_dp->dpcd)) < 0) |
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); |
DRM_DEBUG_KMS("DPCD: %*ph\n", (int) sizeof(intel_dp->dpcd), intel_dp->dpcd); |
|
if (intel_dp->dpcd[DP_DPCD_REV] == 0) |
return false; /* DPCD not present */ |
3301,11 → 3588,12 |
} |
} |
|
/* Training Pattern 3 support */ |
/* Training Pattern 3 support, both source and sink */ |
if (intel_dp->dpcd[DP_DPCD_REV] >= 0x12 && |
intel_dp->dpcd[DP_MAX_LANE_COUNT] & DP_TPS3_SUPPORTED) { |
intel_dp->dpcd[DP_MAX_LANE_COUNT] & DP_TPS3_SUPPORTED && |
(IS_HASWELL(dev_priv) || INTEL_INFO(dev_priv)->gen >= 8)) { |
intel_dp->use_tps3 = true; |
DRM_DEBUG_KMS("Displayport TPS3 supported"); |
DRM_DEBUG_KMS("Displayport TPS3 supported\n"); |
} else |
intel_dp->use_tps3 = false; |
|
3332,8 → 3620,6 |
if (!(intel_dp->dpcd[DP_DOWN_STREAM_PORT_COUNT] & DP_OUI_SUPPORT)) |
return; |
|
intel_edp_panel_vdd_on(intel_dp); |
|
if (intel_dp_dpcd_read_wake(&intel_dp->aux, DP_SINK_OUI, buf, 3) == 3) |
DRM_DEBUG_KMS("Sink OUI: %02hx%02hx%02hx\n", |
buf[0], buf[1], buf[2]); |
3341,8 → 3627,6 |
if (intel_dp_dpcd_read_wake(&intel_dp->aux, DP_BRANCH_OUI, buf, 3) == 3) |
DRM_DEBUG_KMS("Branch OUI: %02hx%02hx%02hx\n", |
buf[0], buf[1], buf[2]); |
|
edp_panel_vdd_off(intel_dp, false); |
} |
|
static bool |
3356,7 → 3640,6 |
if (intel_dp->dpcd[DP_DPCD_REV] < 0x12) |
return false; |
|
_edp_panel_vdd_on(intel_dp); |
if (intel_dp_dpcd_read_wake(&intel_dp->aux, DP_MSTM_CAP, buf, 1)) { |
if (buf[0] & DP_MST_CAP) { |
DRM_DEBUG_KMS("Sink is MST capable\n"); |
3366,7 → 3649,6 |
intel_dp->is_mst = false; |
} |
} |
edp_panel_vdd_off(intel_dp, false); |
|
drm_dp_mst_topology_mgr_set_mst(&intel_dp->mst_mgr, intel_dp->is_mst); |
return intel_dp->is_mst; |
3378,26 → 3660,48 |
struct drm_device *dev = intel_dig_port->base.base.dev; |
struct intel_crtc *intel_crtc = |
to_intel_crtc(intel_dig_port->base.base.crtc); |
u8 buf[1]; |
u8 buf; |
int test_crc_count; |
int attempts = 6; |
|
if (drm_dp_dpcd_readb(&intel_dp->aux, DP_TEST_SINK_MISC, buf) < 0) |
return -EAGAIN; |
if (drm_dp_dpcd_readb(&intel_dp->aux, DP_TEST_SINK_MISC, &buf) < 0) |
return -EIO; |
|
if (!(buf[0] & DP_TEST_CRC_SUPPORTED)) |
if (!(buf & DP_TEST_CRC_SUPPORTED)) |
return -ENOTTY; |
|
if (drm_dp_dpcd_readb(&intel_dp->aux, DP_TEST_SINK, &buf) < 0) |
return -EIO; |
|
if (drm_dp_dpcd_writeb(&intel_dp->aux, DP_TEST_SINK, |
DP_TEST_SINK_START) < 0) |
return -EAGAIN; |
buf | DP_TEST_SINK_START) < 0) |
return -EIO; |
|
/* Wait 2 vblanks to be sure we will have the correct CRC value */ |
if (drm_dp_dpcd_readb(&intel_dp->aux, DP_TEST_SINK_MISC, &buf) < 0) |
return -EIO; |
test_crc_count = buf & DP_TEST_COUNT_MASK; |
|
do { |
if (drm_dp_dpcd_readb(&intel_dp->aux, |
DP_TEST_SINK_MISC, &buf) < 0) |
return -EIO; |
intel_wait_for_vblank(dev, intel_crtc->pipe); |
intel_wait_for_vblank(dev, intel_crtc->pipe); |
} while (--attempts && (buf & DP_TEST_COUNT_MASK) == test_crc_count); |
|
if (attempts == 0) { |
DRM_DEBUG_KMS("Panel is unable to calculate CRC after 6 vblanks\n"); |
return -ETIMEDOUT; |
} |
|
if (drm_dp_dpcd_read(&intel_dp->aux, DP_TEST_CRC_R_CR, crc, 6) < 0) |
return -EAGAIN; |
return -EIO; |
|
drm_dp_dpcd_writeb(&intel_dp->aux, DP_TEST_SINK, 0); |
if (drm_dp_dpcd_readb(&intel_dp->aux, DP_TEST_SINK, &buf) < 0) |
return -EIO; |
if (drm_dp_dpcd_writeb(&intel_dp->aux, DP_TEST_SINK, |
buf & ~DP_TEST_SINK_START) < 0) |
return -EIO; |
|
return 0; |
} |
|
3598,21 → 3902,25 |
} |
|
static enum drm_connector_status |
ironlake_dp_detect(struct intel_dp *intel_dp) |
edp_detect(struct intel_dp *intel_dp) |
{ |
struct drm_device *dev = intel_dp_to_dev(intel_dp); |
struct drm_i915_private *dev_priv = dev->dev_private; |
struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); |
enum drm_connector_status status; |
|
/* Can't disconnect eDP, but you can close the lid... */ |
if (is_edp(intel_dp)) { |
status = intel_panel_detect(dev); |
if (status == connector_status_unknown) |
status = connector_status_connected; |
|
return status; |
} |
|
static enum drm_connector_status |
ironlake_dp_detect(struct intel_dp *intel_dp) |
{ |
struct drm_device *dev = intel_dp_to_dev(intel_dp); |
struct drm_i915_private *dev_priv = dev->dev_private; |
struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); |
|
if (!ibx_digital_port_connected(dev_priv, intel_dig_port)) |
return connector_status_disconnected; |
|
3687,9 → 3995,9 |
} |
|
static struct edid * |
intel_dp_get_edid(struct drm_connector *connector, struct i2c_adapter *adapter) |
intel_dp_get_edid(struct intel_dp *intel_dp) |
{ |
struct intel_connector *intel_connector = to_intel_connector(connector); |
struct intel_connector *intel_connector = intel_dp->attached_connector; |
|
/* use cached edid if we have one */ |
if (intel_connector->edid) { |
3698,29 → 4006,57 |
return NULL; |
|
return drm_edid_duplicate(intel_connector->edid); |
} else |
return drm_get_edid(&intel_connector->base, |
&intel_dp->aux.ddc); |
} |
|
return drm_get_edid(connector, adapter); |
static void |
intel_dp_set_edid(struct intel_dp *intel_dp) |
{ |
struct intel_connector *intel_connector = intel_dp->attached_connector; |
struct edid *edid; |
|
edid = intel_dp_get_edid(intel_dp); |
intel_connector->detect_edid = edid; |
|
if (intel_dp->force_audio != HDMI_AUDIO_AUTO) |
intel_dp->has_audio = intel_dp->force_audio == HDMI_AUDIO_ON; |
else |
intel_dp->has_audio = drm_detect_monitor_audio(edid); |
} |
|
static int |
intel_dp_get_edid_modes(struct drm_connector *connector, struct i2c_adapter *adapter) |
static void |
intel_dp_unset_edid(struct intel_dp *intel_dp) |
{ |
struct intel_connector *intel_connector = to_intel_connector(connector); |
struct intel_connector *intel_connector = intel_dp->attached_connector; |
|
/* use cached edid if we have one */ |
if (intel_connector->edid) { |
/* invalid edid */ |
if (IS_ERR(intel_connector->edid)) |
return 0; |
kfree(intel_connector->detect_edid); |
intel_connector->detect_edid = NULL; |
|
return intel_connector_update_modes(connector, |
intel_connector->edid); |
intel_dp->has_audio = false; |
} |
|
return intel_ddc_get_modes(connector, adapter); |
static enum intel_display_power_domain |
intel_dp_power_get(struct intel_dp *dp) |
{ |
struct intel_encoder *encoder = &dp_to_dig_port(dp)->base; |
enum intel_display_power_domain power_domain; |
|
power_domain = intel_display_port_power_domain(encoder); |
intel_display_power_get(to_i915(encoder->base.dev), power_domain); |
|
return power_domain; |
} |
|
static void |
intel_dp_power_put(struct intel_dp *dp, |
enum intel_display_power_domain power_domain) |
{ |
struct intel_encoder *encoder = &dp_to_dig_port(dp)->base; |
intel_display_power_put(to_i915(encoder->base.dev), power_domain); |
} |
|
static enum drm_connector_status |
intel_dp_detect(struct drm_connector *connector, bool force) |
{ |
3728,33 → 4064,30 |
struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); |
struct intel_encoder *intel_encoder = &intel_dig_port->base; |
struct drm_device *dev = connector->dev; |
struct drm_i915_private *dev_priv = dev->dev_private; |
enum drm_connector_status status; |
enum intel_display_power_domain power_domain; |
struct edid *edid = NULL; |
bool ret; |
|
power_domain = intel_display_port_power_domain(intel_encoder); |
intel_display_power_get(dev_priv, power_domain); |
|
DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", |
connector->base.id, connector->name); |
intel_dp_unset_edid(intel_dp); |
|
if (intel_dp->is_mst) { |
/* MST devices are disconnected from a monitor POV */ |
if (intel_encoder->type != INTEL_OUTPUT_EDP) |
intel_encoder->type = INTEL_OUTPUT_DISPLAYPORT; |
status = connector_status_disconnected; |
goto out; |
return connector_status_disconnected; |
} |
|
intel_dp->has_audio = false; |
power_domain = intel_dp_power_get(intel_dp); |
|
if (HAS_PCH_SPLIT(dev)) |
/* Can't disconnect eDP, but you can close the lid... */ |
if (is_edp(intel_dp)) |
status = edp_detect(intel_dp); |
else if (HAS_PCH_SPLIT(dev)) |
status = ironlake_dp_detect(intel_dp); |
else |
status = g4x_dp_detect(intel_dp); |
|
if (status != connector_status_connected) |
goto out; |
|
3770,15 → 4103,7 |
goto out; |
} |
|
if (intel_dp->force_audio != HDMI_AUDIO_AUTO) { |
intel_dp->has_audio = (intel_dp->force_audio == HDMI_AUDIO_ON); |
} else { |
edid = intel_dp_get_edid(connector, &intel_dp->aux.ddc); |
if (edid) { |
intel_dp->has_audio = drm_detect_monitor_audio(edid); |
kfree(edid); |
} |
} |
intel_dp_set_edid(intel_dp); |
|
if (intel_encoder->type != INTEL_OUTPUT_EDP) |
intel_encoder->type = INTEL_OUTPUT_DISPLAYPORT; |
3785,36 → 4110,52 |
status = connector_status_connected; |
|
out: |
intel_display_power_put(dev_priv, power_domain); |
intel_dp_power_put(intel_dp, power_domain); |
return status; |
} |
|
static int intel_dp_get_modes(struct drm_connector *connector) |
static void |
intel_dp_force(struct drm_connector *connector) |
{ |
struct intel_dp *intel_dp = intel_attached_dp(connector); |
struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); |
struct intel_encoder *intel_encoder = &intel_dig_port->base; |
struct intel_connector *intel_connector = to_intel_connector(connector); |
struct drm_device *dev = connector->dev; |
struct drm_i915_private *dev_priv = dev->dev_private; |
struct intel_encoder *intel_encoder = &dp_to_dig_port(intel_dp)->base; |
enum intel_display_power_domain power_domain; |
int ret; |
|
/* We should parse the EDID data and find out if it has an audio sink |
*/ |
DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", |
connector->base.id, connector->name); |
intel_dp_unset_edid(intel_dp); |
|
power_domain = intel_display_port_power_domain(intel_encoder); |
intel_display_power_get(dev_priv, power_domain); |
if (connector->status != connector_status_connected) |
return; |
|
ret = intel_dp_get_edid_modes(connector, &intel_dp->aux.ddc); |
intel_display_power_put(dev_priv, power_domain); |
power_domain = intel_dp_power_get(intel_dp); |
|
intel_dp_set_edid(intel_dp); |
|
intel_dp_power_put(intel_dp, power_domain); |
|
if (intel_encoder->type != INTEL_OUTPUT_EDP) |
intel_encoder->type = INTEL_OUTPUT_DISPLAYPORT; |
} |
|
static int intel_dp_get_modes(struct drm_connector *connector) |
{ |
struct intel_connector *intel_connector = to_intel_connector(connector); |
struct edid *edid; |
|
edid = intel_connector->detect_edid; |
if (edid) { |
int ret = intel_connector_update_modes(connector, edid); |
if (ret) |
return ret; |
} |
|
/* if eDP has no EDID, fall back to fixed mode */ |
if (is_edp(intel_dp) && intel_connector->panel.fixed_mode) { |
if (is_edp(intel_attached_dp(connector)) && |
intel_connector->panel.fixed_mode) { |
struct drm_display_mode *mode; |
mode = drm_mode_duplicate(dev, |
|
mode = drm_mode_duplicate(connector->dev, |
intel_connector->panel.fixed_mode); |
if (mode) { |
drm_mode_probed_add(connector, mode); |
3821,6 → 4162,7 |
return 1; |
} |
} |
|
return 0; |
} |
|
3827,26 → 4169,13 |
static bool |
intel_dp_detect_audio(struct drm_connector *connector) |
{ |
struct intel_dp *intel_dp = intel_attached_dp(connector); |
struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); |
struct intel_encoder *intel_encoder = &intel_dig_port->base; |
struct drm_device *dev = connector->dev; |
struct drm_i915_private *dev_priv = dev->dev_private; |
enum intel_display_power_domain power_domain; |
bool has_audio = false; |
struct edid *edid; |
bool has_audio = false; |
|
power_domain = intel_display_port_power_domain(intel_encoder); |
intel_display_power_get(dev_priv, power_domain); |
|
edid = intel_dp_get_edid(connector, &intel_dp->aux.ddc); |
if (edid) { |
edid = to_intel_connector(connector)->detect_edid; |
if (edid) |
has_audio = drm_detect_monitor_audio(edid); |
kfree(edid); |
} |
|
intel_display_power_put(dev_priv, power_domain); |
|
return has_audio; |
} |
|
3943,6 → 4272,8 |
{ |
struct intel_connector *intel_connector = to_intel_connector(connector); |
|
kfree(intel_connector->detect_edid); |
|
if (!IS_ERR_OR_NULL(intel_connector->edid)) |
kfree(intel_connector->edid); |
|
3959,7 → 4290,6 |
{ |
struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder); |
struct intel_dp *intel_dp = &intel_dig_port->dp; |
struct drm_device *dev = intel_dp_to_dev(intel_dp); |
|
drm_dp_aux_unregister(&intel_dp->aux); |
intel_dp_mst_encoder_cleanup(intel_dig_port); |
3966,9 → 4296,14 |
drm_encoder_cleanup(encoder); |
if (is_edp(intel_dp)) { |
cancel_delayed_work_sync(&intel_dp->panel_vdd_work); |
drm_modeset_lock(&dev->mode_config.connection_mutex, NULL); |
/* |
* vdd might still be enabled do to the delayed vdd off. |
* Make sure vdd is actually turned off here. |
*/ |
pps_lock(intel_dp); |
edp_panel_vdd_off_sync(intel_dp); |
drm_modeset_unlock(&dev->mode_config.connection_mutex); |
pps_unlock(intel_dp); |
|
} |
kfree(intel_dig_port); |
} |
3980,17 → 4315,68 |
if (!is_edp(intel_dp)) |
return; |
|
/* |
* vdd might still be enabled do to the delayed vdd off. |
* Make sure vdd is actually turned off here. |
*/ |
cancel_delayed_work_sync(&intel_dp->panel_vdd_work); |
pps_lock(intel_dp); |
edp_panel_vdd_off_sync(intel_dp); |
pps_unlock(intel_dp); |
} |
|
static void intel_edp_panel_vdd_sanitize(struct intel_dp *intel_dp) |
{ |
struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); |
struct drm_device *dev = intel_dig_port->base.base.dev; |
struct drm_i915_private *dev_priv = dev->dev_private; |
enum intel_display_power_domain power_domain; |
|
lockdep_assert_held(&dev_priv->pps_mutex); |
|
if (!edp_have_panel_vdd(intel_dp)) |
return; |
|
/* |
* The VDD bit needs a power domain reference, so if the bit is |
* already enabled when we boot or resume, grab this reference and |
* schedule a vdd off, so we don't hold on to the reference |
* indefinitely. |
*/ |
DRM_DEBUG_KMS("VDD left on by BIOS, adjusting state tracking\n"); |
power_domain = intel_display_port_power_domain(&intel_dig_port->base); |
intel_display_power_get(dev_priv, power_domain); |
|
edp_panel_vdd_schedule_off(intel_dp); |
} |
|
static void intel_dp_encoder_reset(struct drm_encoder *encoder) |
{ |
intel_edp_panel_vdd_sanitize(to_intel_encoder(encoder)); |
struct intel_dp *intel_dp; |
|
if (to_intel_encoder(encoder)->type != INTEL_OUTPUT_EDP) |
return; |
|
intel_dp = enc_to_intel_dp(encoder); |
|
pps_lock(intel_dp); |
|
/* |
* Read out the current power sequencer assignment, |
* in case the BIOS did something with it. |
*/ |
if (IS_VALLEYVIEW(encoder->dev)) |
vlv_initial_power_sequencer_setup(intel_dp); |
|
intel_edp_panel_vdd_sanitize(intel_dp); |
|
pps_unlock(intel_dp); |
} |
|
static const struct drm_connector_funcs intel_dp_connector_funcs = { |
.dpms = intel_connector_dpms, |
.detect = intel_dp_detect, |
.force = intel_dp_force, |
.fill_modes = drm_helper_probe_single_connector_modes, |
.set_property = intel_dp_set_property, |
.destroy = intel_dp_connector_destroy, |
4026,7 → 4412,20 |
if (intel_dig_port->base.type != INTEL_OUTPUT_EDP) |
intel_dig_port->base.type = INTEL_OUTPUT_DISPLAYPORT; |
|
DRM_DEBUG_KMS("got hpd irq on port %d - %s\n", intel_dig_port->port, |
if (long_hpd && intel_dig_port->base.type == INTEL_OUTPUT_EDP) { |
/* |
* vdd off can generate a long pulse on eDP which |
* would require vdd on to handle it, and thus we |
* would end up in an endless cycle of |
* "vdd off -> long hpd -> vdd on -> detect -> vdd off -> ..." |
*/ |
DRM_DEBUG_KMS("ignoring long hpd on eDP port %c\n", |
port_name(intel_dig_port->port)); |
return false; |
} |
|
DRM_DEBUG_KMS("got hpd irq on port %c - %s\n", |
port_name(intel_dig_port->port), |
long_hpd ? "long" : "short"); |
|
power_domain = intel_display_port_power_domain(intel_encoder); |
4158,14 → 4557,20 |
|
static void |
intel_dp_init_panel_power_sequencer(struct drm_device *dev, |
struct intel_dp *intel_dp, |
struct edp_power_seq *out) |
struct intel_dp *intel_dp) |
{ |
struct drm_i915_private *dev_priv = dev->dev_private; |
struct edp_power_seq cur, vbt, spec, final; |
struct edp_power_seq cur, vbt, spec, |
*final = &intel_dp->pps_delays; |
u32 pp_on, pp_off, pp_div, pp; |
int pp_ctrl_reg, pp_on_reg, pp_off_reg, pp_div_reg; |
|
lockdep_assert_held(&dev_priv->pps_mutex); |
|
/* already initialized? */ |
if (final->t11_t12 != 0) |
return; |
|
if (HAS_PCH_SPLIT(dev)) { |
pp_ctrl_reg = PCH_PP_CONTROL; |
pp_on_reg = PCH_PP_ON_DELAYS; |
4227,7 → 4632,7 |
|
/* Use the max of the register settings and vbt. If both are |
* unset, fall back to the spec limits. */ |
#define assign_final(field) final.field = (max(cur.field, vbt.field) == 0 ? \ |
#define assign_final(field) final->field = (max(cur.field, vbt.field) == 0 ? \ |
spec.field : \ |
max(cur.field, vbt.field)) |
assign_final(t1_t3); |
4237,7 → 4642,7 |
assign_final(t11_t12); |
#undef assign_final |
|
#define get_delay(field) (DIV_ROUND_UP(final.field, 10)) |
#define get_delay(field) (DIV_ROUND_UP(final->field, 10)) |
intel_dp->panel_power_up_delay = get_delay(t1_t3); |
intel_dp->backlight_on_delay = get_delay(t8); |
intel_dp->backlight_off_delay = get_delay(t9); |
4251,21 → 4656,21 |
|
DRM_DEBUG_KMS("backlight on delay %d, off delay %d\n", |
intel_dp->backlight_on_delay, intel_dp->backlight_off_delay); |
|
if (out) |
*out = final; |
} |
|
static void |
intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev, |
struct intel_dp *intel_dp, |
struct edp_power_seq *seq) |
struct intel_dp *intel_dp) |
{ |
struct drm_i915_private *dev_priv = dev->dev_private; |
u32 pp_on, pp_off, pp_div, port_sel = 0; |
int div = HAS_PCH_SPLIT(dev) ? intel_pch_rawclk(dev) : intel_hrawclk(dev); |
int pp_on_reg, pp_off_reg, pp_div_reg; |
enum port port = dp_to_dig_port(intel_dp)->port; |
const struct edp_power_seq *seq = &intel_dp->pps_delays; |
|
lockdep_assert_held(&dev_priv->pps_mutex); |
|
if (HAS_PCH_SPLIT(dev)) { |
pp_on_reg = PCH_PP_ON_DELAYS; |
pp_off_reg = PCH_PP_OFF_DELAYS; |
4299,12 → 4704,9 |
/* Haswell doesn't have any port selection bits for the panel |
* power sequencer any more. */ |
if (IS_VALLEYVIEW(dev)) { |
if (dp_to_dig_port(intel_dp)->port == PORT_B) |
port_sel = PANEL_PORT_SELECT_DPB_VLV; |
else |
port_sel = PANEL_PORT_SELECT_DPC_VLV; |
port_sel = PANEL_PORT_SELECT_VLV(port); |
} else if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)) { |
if (dp_to_dig_port(intel_dp)->port == PORT_A) |
if (port == PORT_A) |
port_sel = PANEL_PORT_SELECT_DPA; |
else |
port_sel = PANEL_PORT_SELECT_DPD; |
4348,7 → 4750,7 |
* hard to tell without seeing the user of this function of this code. |
* Check locking and ordering once that lands. |
*/ |
if (INTEL_INFO(dev)->gen < 8 && intel_edp_is_psr_enabled(dev)) { |
if (INTEL_INFO(dev)->gen < 8 && intel_psr_is_enabled(dev)) { |
DRM_DEBUG_KMS("DRRS is disabled as PSR is enabled\n"); |
return; |
} |
4388,7 → 4790,7 |
val = I915_READ(reg); |
if (index > DRRS_HIGH_RR) { |
val |= PIPECONF_EDP_RR_MODE_SWITCH; |
intel_dp_set_m2_n2(intel_crtc, &config->dp_m2_n2); |
intel_dp_set_m_n(intel_crtc); |
} else { |
val &= ~PIPECONF_EDP_RR_MODE_SWITCH; |
} |
4428,7 → 4830,7 |
} |
|
if (dev_priv->vbt.drrs_type != SEAMLESS_DRRS_SUPPORT) { |
DRM_INFO("VBT doesn't support DRRS\n"); |
DRM_DEBUG_KMS("VBT doesn't support DRRS\n"); |
return NULL; |
} |
|
4436,7 → 4838,7 |
(dev, fixed_mode, connector); |
|
if (!downclock_mode) { |
DRM_INFO("DRRS not supported\n"); |
DRM_DEBUG_KMS("DRRS not supported\n"); |
return NULL; |
} |
|
4447,39 → 4849,12 |
intel_dp->drrs_state.type = dev_priv->vbt.drrs_type; |
|
intel_dp->drrs_state.refresh_rate_type = DRRS_HIGH_RR; |
DRM_INFO("seamless DRRS supported for eDP panel.\n"); |
DRM_DEBUG_KMS("seamless DRRS supported for eDP panel.\n"); |
return downclock_mode; |
} |
|
void intel_edp_panel_vdd_sanitize(struct intel_encoder *intel_encoder) |
{ |
struct drm_device *dev = intel_encoder->base.dev; |
struct drm_i915_private *dev_priv = dev->dev_private; |
struct intel_dp *intel_dp; |
enum intel_display_power_domain power_domain; |
|
if (intel_encoder->type != INTEL_OUTPUT_EDP) |
return; |
|
intel_dp = enc_to_intel_dp(&intel_encoder->base); |
if (!edp_have_panel_vdd(intel_dp)) |
return; |
/* |
* The VDD bit needs a power domain reference, so if the bit is |
* already enabled when we boot or resume, grab this reference and |
* schedule a vdd off, so we don't hold on to the reference |
* indefinitely. |
*/ |
DRM_DEBUG_KMS("VDD left on by BIOS, adjusting state tracking\n"); |
power_domain = intel_display_port_power_domain(intel_encoder); |
intel_display_power_get(dev_priv, power_domain); |
|
edp_panel_vdd_schedule_off(intel_dp); |
} |
|
static bool intel_edp_init_connector(struct intel_dp *intel_dp, |
struct intel_connector *intel_connector, |
struct edp_power_seq *power_seq) |
struct intel_connector *intel_connector) |
{ |
struct drm_connector *connector = &intel_connector->base; |
struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); |
4491,6 → 4866,7 |
bool has_dpcd; |
struct drm_display_mode *scan; |
struct edid *edid; |
enum pipe pipe = INVALID_PIPE; |
|
intel_dp->drrs_state.type = DRRS_NOT_SUPPORTED; |
|
4497,12 → 4873,12 |
if (!is_edp(intel_dp)) |
return true; |
|
intel_edp_panel_vdd_sanitize(intel_encoder); |
pps_lock(intel_dp); |
intel_edp_panel_vdd_sanitize(intel_dp); |
pps_unlock(intel_dp); |
|
/* Cache DPCD and EDID for edp. */ |
intel_edp_panel_vdd_on(intel_dp); |
has_dpcd = intel_dp_get_dpcd(intel_dp); |
edp_panel_vdd_off(intel_dp, false); |
|
if (has_dpcd) { |
if (intel_dp->dpcd[DP_DPCD_REV] >= 0x11) |
4516,7 → 4892,9 |
} |
|
/* We now know it's not a ghost, init power sequence regs. */ |
intel_dp_init_panel_power_sequencer_registers(dev, intel_dp, power_seq); |
pps_lock(intel_dp); |
intel_dp_init_panel_power_sequencer_registers(dev, intel_dp); |
pps_unlock(intel_dp); |
|
mutex_lock(&dev->mode_config.mutex); |
edid = drm_get_edid(connector, &intel_dp->aux.ddc); |
4554,8 → 4932,31 |
} |
mutex_unlock(&dev->mode_config.mutex); |
|
if (IS_VALLEYVIEW(dev)) { |
|
/* |
* Figure out the current pipe for the initial backlight setup. |
* If the current pipe isn't valid, try the PPS pipe, and if that |
* fails just assume pipe A. |
*/ |
if (IS_CHERRYVIEW(dev)) |
pipe = DP_PORT_TO_PIPE_CHV(intel_dp->DP); |
else |
pipe = PORT_TO_PIPE(intel_dp->DP); |
|
if (pipe != PIPE_A && pipe != PIPE_B) |
pipe = intel_dp->pps_pipe; |
|
if (pipe != PIPE_A && pipe != PIPE_B) |
pipe = PIPE_A; |
|
DRM_DEBUG_KMS("using pipe %c for initial backlight setup\n", |
pipe_name(pipe)); |
} |
|
intel_panel_init(&intel_connector->panel, fixed_mode, downclock_mode); |
intel_panel_setup_backlight(connector); |
intel_connector->panel.backlight_power = intel_edp_backlight_power; |
intel_panel_setup_backlight(connector, pipe); |
|
return true; |
} |
4570,11 → 4971,14 |
struct drm_device *dev = intel_encoder->base.dev; |
struct drm_i915_private *dev_priv = dev->dev_private; |
enum port port = intel_dig_port->port; |
struct edp_power_seq power_seq = { 0 }; |
int type; |
|
intel_dp->pps_pipe = INVALID_PIPE; |
|
/* intel_dp vfuncs */ |
if (IS_VALLEYVIEW(dev)) |
if (INTEL_INFO(dev)->gen >= 9) |
intel_dp->get_aux_clock_divider = skl_get_aux_clock_divider; |
else if (IS_VALLEYVIEW(dev)) |
intel_dp->get_aux_clock_divider = vlv_get_aux_clock_divider; |
else if (IS_HASWELL(dev) || IS_BROADWELL(dev)) |
intel_dp->get_aux_clock_divider = hsw_get_aux_clock_divider; |
4583,6 → 4987,9 |
else |
intel_dp->get_aux_clock_divider = i9xx_get_aux_clock_divider; |
|
if (INTEL_INFO(dev)->gen >= 9) |
intel_dp->get_aux_send_ctl = skl_get_aux_send_ctl; |
else |
intel_dp->get_aux_send_ctl = i9xx_get_aux_send_ctl; |
|
/* Preserve the current hw state. */ |
4602,6 → 5009,11 |
if (type == DRM_MODE_CONNECTOR_eDP) |
intel_encoder->type = INTEL_OUTPUT_EDP; |
|
/* eDP only on port B and/or C on vlv/chv */ |
if (WARN_ON(IS_VALLEYVIEW(dev) && is_edp(intel_dp) && |
port != PORT_B && port != PORT_C)) |
return false; |
|
DRM_DEBUG_KMS("Adding %s connector on port %c\n", |
type == DRM_MODE_CONNECTOR_eDP ? "eDP" : "DP", |
port_name(port)); |
4643,8 → 5055,13 |
} |
|
if (is_edp(intel_dp)) { |
pps_lock(intel_dp); |
intel_dp_init_panel_power_timestamps(intel_dp); |
intel_dp_init_panel_power_sequencer(dev, intel_dp, &power_seq); |
if (IS_VALLEYVIEW(dev)) |
vlv_initial_power_sequencer_setup(intel_dp); |
else |
intel_dp_init_panel_power_sequencer(dev, intel_dp); |
pps_unlock(intel_dp); |
} |
|
intel_dp_aux_init(intel_dp, intel_connector); |
4652,17 → 5069,22 |
/* init MST on ports that can support it */ |
if (IS_HASWELL(dev) || IS_BROADWELL(dev)) { |
if (port == PORT_B || port == PORT_C || port == PORT_D) { |
intel_dp_mst_encoder_init(intel_dig_port, intel_connector->base.base.id); |
intel_dp_mst_encoder_init(intel_dig_port, |
intel_connector->base.base.id); |
} |
} |
|
if (!intel_edp_init_connector(intel_dp, intel_connector, &power_seq)) { |
if (!intel_edp_init_connector(intel_dp, intel_connector)) { |
drm_dp_aux_unregister(&intel_dp->aux); |
if (is_edp(intel_dp)) { |
cancel_delayed_work_sync(&intel_dp->panel_vdd_work); |
drm_modeset_lock(&dev->mode_config.connection_mutex, NULL); |
/* |
* vdd might still be enabled do to the delayed vdd off. |
* Make sure vdd is actually turned off here. |
*/ |
pps_lock(intel_dp); |
edp_panel_vdd_off_sync(intel_dp); |
drm_modeset_unlock(&dev->mode_config.connection_mutex); |
pps_unlock(intel_dp); |
} |
drm_connector_unregister(connector); |
drm_connector_cleanup(connector); |
4726,7 → 5148,8 |
} else { |
intel_encoder->pre_enable = g4x_pre_enable_dp; |
intel_encoder->enable = g4x_enable_dp; |
intel_encoder->post_disable = g4x_post_disable_dp; |
if (INTEL_INFO(dev)->gen >= 5) |
intel_encoder->post_disable = ilk_post_disable_dp; |
} |
|
intel_dig_port->port = port; |