76,12 → 76,12 |
0x00FFFFFF, 0x00000012, /* eDP parameters */ |
0x00EBAFFF, 0x00020011, |
0x00C71FFF, 0x0006000F, |
0x00AAAFFF, 0x000E000A, |
0x00FFFFFF, 0x00020011, |
0x00DB6FFF, 0x0005000F, |
0x00BEEFFF, 0x000A000C, |
0x00FFFFFF, 0x0005000F, |
0x00DB6FFF, 0x000A000C, |
0x00FFFFFF, 0x000A000C, |
0x00FFFFFF, 0x00140006 /* HDMI parameters 800mV 0dB*/ |
}; |
|
89,12 → 89,12 |
0x00FFFFFF, 0x0007000E, /* DP parameters */ |
0x00D75FFF, 0x000E000A, |
0x00BEFFFF, 0x00140006, |
0x80B2CFFF, 0x001B0002, |
0x00FFFFFF, 0x000E000A, |
0x00D75FFF, 0x00180004, |
0x80CB2FFF, 0x001B0002, |
0x00F7DFFF, 0x00180004, |
0x80D75FFF, 0x001B0002, |
0x80FFFFFF, 0x001B0002, |
0x00FFFFFF, 0x00140006 /* HDMI parameters 800mV 0dB*/ |
}; |
|
116,7 → 116,10 |
struct drm_encoder *encoder = &intel_encoder->base; |
int type = intel_encoder->type; |
|
if (type == INTEL_OUTPUT_DISPLAYPORT || type == INTEL_OUTPUT_EDP || |
if (type == INTEL_OUTPUT_DP_MST) { |
struct intel_digital_port *intel_dig_port = enc_to_mst(encoder)->primary; |
return intel_dig_port->port; |
} else if (type == INTEL_OUTPUT_DISPLAYPORT || type == INTEL_OUTPUT_EDP || |
type == INTEL_OUTPUT_HDMI || type == INTEL_OUTPUT_UNKNOWN) { |
struct intel_digital_port *intel_dig_port = |
enc_to_dig_port(encoder); |
277,7 → 280,8 |
I915_WRITE(_FDI_RXA_CTL, rx_ctl_val); |
|
/* Configure Port Clock Select */ |
I915_WRITE(PORT_CLK_SEL(PORT_E), intel_crtc->ddi_pll_sel); |
I915_WRITE(PORT_CLK_SEL(PORT_E), intel_crtc->config.ddi_pll_sel); |
WARN_ON(intel_crtc->config.ddi_pll_sel != PORT_CLK_SEL_SPLL); |
|
/* Start the training iterating through available voltages and emphasis, |
* testing each value twice. */ |
364,19 → 368,8 |
DRM_ERROR("FDI link training failed!\n"); |
} |
|
static void intel_ddi_mode_set(struct intel_encoder *encoder) |
void intel_ddi_init_dp_buf_reg(struct intel_encoder *encoder) |
{ |
struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc); |
int port = intel_ddi_get_encoder_port(encoder); |
int pipe = crtc->pipe; |
int type = encoder->type; |
struct drm_display_mode *adjusted_mode = &crtc->config.adjusted_mode; |
|
DRM_DEBUG_KMS("Preparing DDI mode on port %c, pipe %c\n", |
port_name(port), pipe_name(pipe)); |
|
crtc->eld_vld = false; |
if (type == INTEL_OUTPUT_DISPLAYPORT || type == INTEL_OUTPUT_EDP) { |
struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); |
struct intel_digital_port *intel_dig_port = |
enc_to_dig_port(&encoder->base); |
385,34 → 378,8 |
DDI_BUF_CTL_ENABLE | DDI_BUF_EMP_400MV_0DB_HSW; |
intel_dp->DP |= DDI_PORT_WIDTH(intel_dp->lane_count); |
|
if (intel_dp->has_audio) { |
DRM_DEBUG_DRIVER("DP audio on pipe %c on DDI\n", |
pipe_name(crtc->pipe)); |
|
/* write eld */ |
DRM_DEBUG_DRIVER("DP audio: write eld information\n"); |
intel_write_eld(&encoder->base, adjusted_mode); |
} |
} else if (type == INTEL_OUTPUT_HDMI) { |
struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base); |
|
if (intel_hdmi->has_audio) { |
/* Proper support for digital audio needs a new logic |
* and a new set of registers, so we leave it for future |
* patch bombing. |
*/ |
DRM_DEBUG_DRIVER("HDMI audio on pipe %c on DDI\n", |
pipe_name(crtc->pipe)); |
|
/* write eld */ |
DRM_DEBUG_DRIVER("HDMI audio: write eld information\n"); |
intel_write_eld(&encoder->base, adjusted_mode); |
} |
|
intel_hdmi->set_infoframes(&encoder->base, adjusted_mode); |
} |
} |
|
static struct intel_encoder * |
intel_ddi_get_crtc_encoder(struct drm_crtc *crtc) |
{ |
434,53 → 401,6 |
return ret; |
} |
|
void intel_ddi_put_crtc_pll(struct drm_crtc *crtc) |
{ |
struct drm_i915_private *dev_priv = crtc->dev->dev_private; |
struct intel_ddi_plls *plls = &dev_priv->ddi_plls; |
struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
uint32_t val; |
|
switch (intel_crtc->ddi_pll_sel) { |
case PORT_CLK_SEL_SPLL: |
plls->spll_refcount--; |
if (plls->spll_refcount == 0) { |
DRM_DEBUG_KMS("Disabling SPLL\n"); |
val = I915_READ(SPLL_CTL); |
WARN_ON(!(val & SPLL_PLL_ENABLE)); |
I915_WRITE(SPLL_CTL, val & ~SPLL_PLL_ENABLE); |
POSTING_READ(SPLL_CTL); |
} |
break; |
case PORT_CLK_SEL_WRPLL1: |
plls->wrpll1_refcount--; |
if (plls->wrpll1_refcount == 0) { |
DRM_DEBUG_KMS("Disabling WRPLL 1\n"); |
val = I915_READ(WRPLL_CTL1); |
WARN_ON(!(val & WRPLL_PLL_ENABLE)); |
I915_WRITE(WRPLL_CTL1, val & ~WRPLL_PLL_ENABLE); |
POSTING_READ(WRPLL_CTL1); |
} |
break; |
case PORT_CLK_SEL_WRPLL2: |
plls->wrpll2_refcount--; |
if (plls->wrpll2_refcount == 0) { |
DRM_DEBUG_KMS("Disabling WRPLL 2\n"); |
val = I915_READ(WRPLL_CTL2); |
WARN_ON(!(val & WRPLL_PLL_ENABLE)); |
I915_WRITE(WRPLL_CTL2, val & ~WRPLL_PLL_ENABLE); |
POSTING_READ(WRPLL_CTL2); |
} |
break; |
} |
|
WARN(plls->spll_refcount < 0, "Invalid SPLL refcount\n"); |
WARN(plls->wrpll1_refcount < 0, "Invalid WRPLL1 refcount\n"); |
WARN(plls->wrpll2_refcount < 0, "Invalid WRPLL2 refcount\n"); |
|
intel_crtc->ddi_pll_sel = PORT_CLK_SEL_NONE; |
} |
|
#define LC_FREQ 2700 |
#define LC_FREQ_2K (LC_FREQ * 2000) |
|
633,6 → 553,96 |
/* Otherwise a < c && b >= d, do nothing */ |
} |
|
static int intel_ddi_calc_wrpll_link(struct drm_i915_private *dev_priv, |
int reg) |
{ |
int refclk = LC_FREQ; |
int n, p, r; |
u32 wrpll; |
|
wrpll = I915_READ(reg); |
switch (wrpll & WRPLL_PLL_REF_MASK) { |
case WRPLL_PLL_SSC: |
case WRPLL_PLL_NON_SSC: |
/* |
* We could calculate spread here, but our checking |
* code only cares about 5% accuracy, and spread is a max of |
* 0.5% downspread. |
*/ |
refclk = 135; |
break; |
case WRPLL_PLL_LCPLL: |
refclk = LC_FREQ; |
break; |
default: |
WARN(1, "bad wrpll refclk\n"); |
return 0; |
} |
|
r = wrpll & WRPLL_DIVIDER_REF_MASK; |
p = (wrpll & WRPLL_DIVIDER_POST_MASK) >> WRPLL_DIVIDER_POST_SHIFT; |
n = (wrpll & WRPLL_DIVIDER_FB_MASK) >> WRPLL_DIVIDER_FB_SHIFT; |
|
/* Convert to KHz, p & r have a fixed point portion */ |
return (refclk * n * 100) / (p * r); |
} |
|
void intel_ddi_clock_get(struct intel_encoder *encoder, |
struct intel_crtc_config *pipe_config) |
{ |
struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; |
int link_clock = 0; |
u32 val, pll; |
|
val = pipe_config->ddi_pll_sel; |
switch (val & PORT_CLK_SEL_MASK) { |
case PORT_CLK_SEL_LCPLL_810: |
link_clock = 81000; |
break; |
case PORT_CLK_SEL_LCPLL_1350: |
link_clock = 135000; |
break; |
case PORT_CLK_SEL_LCPLL_2700: |
link_clock = 270000; |
break; |
case PORT_CLK_SEL_WRPLL1: |
link_clock = intel_ddi_calc_wrpll_link(dev_priv, WRPLL_CTL1); |
break; |
case PORT_CLK_SEL_WRPLL2: |
link_clock = intel_ddi_calc_wrpll_link(dev_priv, WRPLL_CTL2); |
break; |
case PORT_CLK_SEL_SPLL: |
pll = I915_READ(SPLL_CTL) & SPLL_PLL_FREQ_MASK; |
if (pll == SPLL_PLL_FREQ_810MHz) |
link_clock = 81000; |
else if (pll == SPLL_PLL_FREQ_1350MHz) |
link_clock = 135000; |
else if (pll == SPLL_PLL_FREQ_2700MHz) |
link_clock = 270000; |
else { |
WARN(1, "bad spll freq\n"); |
return; |
} |
break; |
default: |
WARN(1, "bad port clock sel\n"); |
return; |
} |
|
pipe_config->port_clock = link_clock * 2; |
|
if (pipe_config->has_pch_encoder) |
pipe_config->adjusted_mode.crtc_clock = |
intel_dotclock_calculate(pipe_config->port_clock, |
&pipe_config->fdi_m_n); |
else if (pipe_config->has_dp_encoder) |
pipe_config->adjusted_mode.crtc_clock = |
intel_dotclock_calculate(pipe_config->port_clock, |
&pipe_config->dp_m_n); |
else |
pipe_config->adjusted_mode.crtc_clock = pipe_config->port_clock; |
} |
|
static void |
intel_ddi_calculate_wrpll(int clock /* in Hz */, |
unsigned *r2_out, unsigned *n2_out, unsigned *p_out) |
708,173 → 718,37 |
{ |
struct drm_crtc *crtc = &intel_crtc->base; |
struct intel_encoder *intel_encoder = intel_ddi_get_crtc_encoder(crtc); |
struct drm_encoder *encoder = &intel_encoder->base; |
struct drm_i915_private *dev_priv = crtc->dev->dev_private; |
struct intel_ddi_plls *plls = &dev_priv->ddi_plls; |
int type = intel_encoder->type; |
enum pipe pipe = intel_crtc->pipe; |
int clock = intel_crtc->config.port_clock; |
|
intel_ddi_put_crtc_pll(crtc); |
intel_put_shared_dpll(intel_crtc); |
|
if (type == INTEL_OUTPUT_DISPLAYPORT || type == INTEL_OUTPUT_EDP) { |
struct intel_dp *intel_dp = enc_to_intel_dp(encoder); |
|
switch (intel_dp->link_bw) { |
case DP_LINK_BW_1_62: |
intel_crtc->ddi_pll_sel = PORT_CLK_SEL_LCPLL_810; |
break; |
case DP_LINK_BW_2_7: |
intel_crtc->ddi_pll_sel = PORT_CLK_SEL_LCPLL_1350; |
break; |
case DP_LINK_BW_5_4: |
intel_crtc->ddi_pll_sel = PORT_CLK_SEL_LCPLL_2700; |
break; |
default: |
DRM_ERROR("Link bandwidth %d unsupported\n", |
intel_dp->link_bw); |
return false; |
} |
|
} else if (type == INTEL_OUTPUT_HDMI) { |
uint32_t reg, val; |
if (type == INTEL_OUTPUT_HDMI) { |
struct intel_shared_dpll *pll; |
uint32_t val; |
unsigned p, n2, r2; |
|
intel_ddi_calculate_wrpll(clock * 1000, &r2, &n2, &p); |
|
val = WRPLL_PLL_ENABLE | WRPLL_PLL_SELECT_LCPLL_2700 | |
val = WRPLL_PLL_ENABLE | WRPLL_PLL_LCPLL | |
WRPLL_DIVIDER_REFERENCE(r2) | WRPLL_DIVIDER_FEEDBACK(n2) | |
WRPLL_DIVIDER_POST(p); |
|
if (val == I915_READ(WRPLL_CTL1)) { |
DRM_DEBUG_KMS("Reusing WRPLL 1 on pipe %c\n", |
pipe_name(pipe)); |
reg = WRPLL_CTL1; |
} else if (val == I915_READ(WRPLL_CTL2)) { |
DRM_DEBUG_KMS("Reusing WRPLL 2 on pipe %c\n", |
pipe_name(pipe)); |
reg = WRPLL_CTL2; |
} else if (plls->wrpll1_refcount == 0) { |
DRM_DEBUG_KMS("Using WRPLL 1 on pipe %c\n", |
pipe_name(pipe)); |
reg = WRPLL_CTL1; |
} else if (plls->wrpll2_refcount == 0) { |
DRM_DEBUG_KMS("Using WRPLL 2 on pipe %c\n", |
pipe_name(pipe)); |
reg = WRPLL_CTL2; |
} else { |
DRM_ERROR("No WRPLLs available!\n"); |
return false; |
} |
intel_crtc->config.dpll_hw_state.wrpll = val; |
|
DRM_DEBUG_KMS("WRPLL: %dKHz refresh rate with p=%d, n2=%d r2=%d\n", |
clock, p, n2, r2); |
|
if (reg == WRPLL_CTL1) { |
plls->wrpll1_refcount++; |
intel_crtc->ddi_pll_sel = PORT_CLK_SEL_WRPLL1; |
} else { |
plls->wrpll2_refcount++; |
intel_crtc->ddi_pll_sel = PORT_CLK_SEL_WRPLL2; |
} |
|
} else if (type == INTEL_OUTPUT_ANALOG) { |
if (plls->spll_refcount == 0) { |
DRM_DEBUG_KMS("Using SPLL on pipe %c\n", |
pipe_name(pipe)); |
plls->spll_refcount++; |
intel_crtc->ddi_pll_sel = PORT_CLK_SEL_SPLL; |
} else { |
DRM_ERROR("SPLL already in use\n"); |
pll = intel_get_shared_dpll(intel_crtc); |
if (pll == NULL) { |
DRM_DEBUG_DRIVER("failed to find PLL for pipe %c\n", |
pipe_name(intel_crtc->pipe)); |
return false; |
} |
|
} else { |
WARN(1, "Invalid DDI encoder type %d\n", type); |
return false; |
intel_crtc->config.ddi_pll_sel = PORT_CLK_SEL_WRPLL(pll->id); |
} |
|
return true; |
} |
|
/* |
* To be called after intel_ddi_pll_select(). That one selects the PLL to be |
* used, this one actually enables the PLL. |
*/ |
void intel_ddi_pll_enable(struct intel_crtc *crtc) |
{ |
struct drm_device *dev = crtc->base.dev; |
struct drm_i915_private *dev_priv = dev->dev_private; |
struct intel_ddi_plls *plls = &dev_priv->ddi_plls; |
int clock = crtc->config.port_clock; |
uint32_t reg, cur_val, new_val; |
int refcount; |
const char *pll_name; |
uint32_t enable_bit = (1 << 31); |
unsigned int p, n2, r2; |
|
BUILD_BUG_ON(enable_bit != SPLL_PLL_ENABLE); |
BUILD_BUG_ON(enable_bit != WRPLL_PLL_ENABLE); |
|
switch (crtc->ddi_pll_sel) { |
case PORT_CLK_SEL_LCPLL_2700: |
case PORT_CLK_SEL_LCPLL_1350: |
case PORT_CLK_SEL_LCPLL_810: |
/* |
* LCPLL should always be enabled at this point of the mode set |
* sequence, so nothing to do. |
*/ |
return; |
|
case PORT_CLK_SEL_SPLL: |
pll_name = "SPLL"; |
reg = SPLL_CTL; |
refcount = plls->spll_refcount; |
new_val = SPLL_PLL_ENABLE | SPLL_PLL_FREQ_1350MHz | |
SPLL_PLL_SSC; |
break; |
|
case PORT_CLK_SEL_WRPLL1: |
case PORT_CLK_SEL_WRPLL2: |
if (crtc->ddi_pll_sel == PORT_CLK_SEL_WRPLL1) { |
pll_name = "WRPLL1"; |
reg = WRPLL_CTL1; |
refcount = plls->wrpll1_refcount; |
} else { |
pll_name = "WRPLL2"; |
reg = WRPLL_CTL2; |
refcount = plls->wrpll2_refcount; |
} |
|
intel_ddi_calculate_wrpll(clock * 1000, &r2, &n2, &p); |
|
new_val = WRPLL_PLL_ENABLE | WRPLL_PLL_SELECT_LCPLL_2700 | |
WRPLL_DIVIDER_REFERENCE(r2) | |
WRPLL_DIVIDER_FEEDBACK(n2) | WRPLL_DIVIDER_POST(p); |
|
break; |
|
case PORT_CLK_SEL_NONE: |
WARN(1, "Bad selected pll: PORT_CLK_SEL_NONE\n"); |
return; |
default: |
WARN(1, "Bad selected pll: 0x%08x\n", crtc->ddi_pll_sel); |
return; |
} |
|
cur_val = I915_READ(reg); |
|
WARN(refcount < 1, "Bad %s refcount: %d\n", pll_name, refcount); |
if (refcount == 1) { |
WARN(cur_val & enable_bit, "%s already enabled\n", pll_name); |
I915_WRITE(reg, new_val); |
POSTING_READ(reg); |
udelay(20); |
} else { |
WARN((cur_val & enable_bit) == 0, "%s disabled\n", pll_name); |
} |
} |
|
void intel_ddi_set_pipe_settings(struct drm_crtc *crtc) |
{ |
struct drm_i915_private *dev_priv = crtc->dev->dev_private; |
884,8 → 758,7 |
int type = intel_encoder->type; |
uint32_t temp; |
|
if (type == INTEL_OUTPUT_DISPLAYPORT || type == INTEL_OUTPUT_EDP) { |
|
if (type == INTEL_OUTPUT_DISPLAYPORT || type == INTEL_OUTPUT_EDP || type == INTEL_OUTPUT_DP_MST) { |
temp = TRANS_MSA_SYNC_CLK; |
switch (intel_crtc->config.pipe_bpp) { |
case 18: |
907,6 → 780,21 |
} |
} |
|
void intel_ddi_set_vc_payload_alloc(struct drm_crtc *crtc, bool state) |
{ |
struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
struct drm_device *dev = crtc->dev; |
struct drm_i915_private *dev_priv = dev->dev_private; |
enum transcoder cpu_transcoder = intel_crtc->config.cpu_transcoder; |
uint32_t temp; |
temp = I915_READ(TRANS_DDI_FUNC_CTL(cpu_transcoder)); |
if (state == true) |
temp |= TRANS_DDI_DP_VC_PAYLOAD_ALLOC; |
else |
temp &= ~TRANS_DDI_DP_VC_PAYLOAD_ALLOC; |
I915_WRITE(TRANS_DDI_FUNC_CTL(cpu_transcoder), temp); |
} |
|
void intel_ddi_enable_transcoder_func(struct drm_crtc *crtc) |
{ |
struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
953,7 → 841,9 |
* eDP when not using the panel fitter, and when not |
* using motion blur mitigation (which we don't |
* support). */ |
if (IS_HASWELL(dev) && intel_crtc->config.pch_pfit.enabled) |
if (IS_HASWELL(dev) && |
(intel_crtc->config.pch_pfit.enabled || |
intel_crtc->config.pch_pfit.force_thru)) |
temp |= TRANS_DDI_EDP_INPUT_A_ONOFF; |
else |
temp |= TRANS_DDI_EDP_INPUT_A_ON; |
971,9 → 861,7 |
} |
|
if (type == INTEL_OUTPUT_HDMI) { |
struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); |
|
if (intel_hdmi->has_hdmi_sink) |
if (intel_crtc->config.has_hdmi_sink) |
temp |= TRANS_DDI_MODE_SELECT_HDMI; |
else |
temp |= TRANS_DDI_MODE_SELECT_DVI; |
986,9 → 874,21 |
type == INTEL_OUTPUT_EDP) { |
struct intel_dp *intel_dp = enc_to_intel_dp(encoder); |
|
if (intel_dp->is_mst) { |
temp |= TRANS_DDI_MODE_SELECT_DP_MST; |
} else |
temp |= TRANS_DDI_MODE_SELECT_DP_SST; |
|
temp |= DDI_PORT_WIDTH(intel_dp->lane_count); |
} else if (type == INTEL_OUTPUT_DP_MST) { |
struct intel_dp *intel_dp = &enc_to_mst(encoder)->primary->dp; |
|
if (intel_dp->is_mst) { |
temp |= TRANS_DDI_MODE_SELECT_DP_MST; |
} else |
temp |= TRANS_DDI_MODE_SELECT_DP_SST; |
|
temp |= DDI_PORT_WIDTH(intel_dp->lane_count); |
} else { |
WARN(1, "Invalid encoder type %d for pipe %c\n", |
intel_encoder->type, pipe_name(pipe)); |
1003,7 → 903,7 |
uint32_t reg = TRANS_DDI_FUNC_CTL(cpu_transcoder); |
uint32_t val = I915_READ(reg); |
|
val &= ~(TRANS_DDI_FUNC_ENABLE | TRANS_DDI_PORT_MASK); |
val &= ~(TRANS_DDI_FUNC_ENABLE | TRANS_DDI_PORT_MASK | TRANS_DDI_DP_VC_PAYLOAD_ALLOC); |
val |= TRANS_DDI_PORT_NONE; |
I915_WRITE(reg, val); |
} |
1017,8 → 917,13 |
enum port port = intel_ddi_get_encoder_port(intel_encoder); |
enum pipe pipe = 0; |
enum transcoder cpu_transcoder; |
enum intel_display_power_domain power_domain; |
uint32_t tmp; |
|
power_domain = intel_display_port_power_domain(intel_encoder); |
if (!intel_display_power_enabled(dev_priv, power_domain)) |
return false; |
|
if (!intel_encoder->get_hw_state(intel_encoder, &pipe)) |
return false; |
|
1037,8 → 942,11 |
case TRANS_DDI_MODE_SELECT_DP_SST: |
if (type == DRM_MODE_CONNECTOR_eDP) |
return true; |
return (type == DRM_MODE_CONNECTOR_DisplayPort); |
case TRANS_DDI_MODE_SELECT_DP_MST: |
return (type == DRM_MODE_CONNECTOR_DisplayPort); |
/* if the transcoder is in MST state then |
* connector isn't connected */ |
return false; |
|
case TRANS_DDI_MODE_SELECT_FDI: |
return (type == DRM_MODE_CONNECTOR_VGA); |
1054,9 → 962,14 |
struct drm_device *dev = encoder->base.dev; |
struct drm_i915_private *dev_priv = dev->dev_private; |
enum port port = intel_ddi_get_encoder_port(encoder); |
enum intel_display_power_domain power_domain; |
u32 tmp; |
int i; |
|
power_domain = intel_display_port_power_domain(encoder); |
if (!intel_display_power_enabled(dev_priv, power_domain)) |
return false; |
|
tmp = I915_READ(DDI_BUF_CTL(port)); |
|
if (!(tmp & DDI_BUF_CTL_ENABLE)) |
1085,6 → 998,9 |
|
if ((tmp & TRANS_DDI_PORT_MASK) |
== TRANS_DDI_SELECT_PORT(port)) { |
if ((tmp & TRANS_DDI_MODE_SELECT_MASK) == TRANS_DDI_MODE_SELECT_DP_MST) |
return false; |
|
*pipe = i; |
return true; |
} |
1096,76 → 1012,6 |
return false; |
} |
|
static uint32_t intel_ddi_get_crtc_pll(struct drm_i915_private *dev_priv, |
enum pipe pipe) |
{ |
uint32_t temp, ret; |
enum port port = I915_MAX_PORTS; |
enum transcoder cpu_transcoder = intel_pipe_to_cpu_transcoder(dev_priv, |
pipe); |
int i; |
|
if (cpu_transcoder == TRANSCODER_EDP) { |
port = PORT_A; |
} else { |
temp = I915_READ(TRANS_DDI_FUNC_CTL(cpu_transcoder)); |
temp &= TRANS_DDI_PORT_MASK; |
|
for (i = PORT_B; i <= PORT_E; i++) |
if (temp == TRANS_DDI_SELECT_PORT(i)) |
port = i; |
} |
|
if (port == I915_MAX_PORTS) { |
WARN(1, "Pipe %c enabled on an unknown port\n", |
pipe_name(pipe)); |
ret = PORT_CLK_SEL_NONE; |
} else { |
ret = I915_READ(PORT_CLK_SEL(port)); |
DRM_DEBUG_KMS("Pipe %c connected to port %c using clock " |
"0x%08x\n", pipe_name(pipe), port_name(port), |
ret); |
} |
|
return ret; |
} |
|
void intel_ddi_setup_hw_pll_state(struct drm_device *dev) |
{ |
struct drm_i915_private *dev_priv = dev->dev_private; |
enum pipe pipe; |
struct intel_crtc *intel_crtc; |
|
dev_priv->ddi_plls.spll_refcount = 0; |
dev_priv->ddi_plls.wrpll1_refcount = 0; |
dev_priv->ddi_plls.wrpll2_refcount = 0; |
|
for_each_pipe(pipe) { |
intel_crtc = |
to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]); |
|
if (!intel_crtc->active) { |
intel_crtc->ddi_pll_sel = PORT_CLK_SEL_NONE; |
continue; |
} |
|
intel_crtc->ddi_pll_sel = intel_ddi_get_crtc_pll(dev_priv, |
pipe); |
|
switch (intel_crtc->ddi_pll_sel) { |
case PORT_CLK_SEL_SPLL: |
dev_priv->ddi_plls.spll_refcount++; |
break; |
case PORT_CLK_SEL_WRPLL1: |
dev_priv->ddi_plls.wrpll1_refcount++; |
break; |
case PORT_CLK_SEL_WRPLL2: |
dev_priv->ddi_plls.wrpll2_refcount++; |
break; |
} |
} |
} |
|
void intel_ddi_enable_pipe_clock(struct intel_crtc *intel_crtc) |
{ |
struct drm_crtc *crtc = &intel_crtc->base; |
1192,28 → 1038,44 |
static void intel_ddi_pre_enable(struct intel_encoder *intel_encoder) |
{ |
struct drm_encoder *encoder = &intel_encoder->base; |
struct drm_crtc *crtc = encoder->crtc; |
struct drm_i915_private *dev_priv = encoder->dev->dev_private; |
struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
struct intel_crtc *crtc = to_intel_crtc(encoder->crtc); |
enum port port = intel_ddi_get_encoder_port(intel_encoder); |
int type = intel_encoder->type; |
|
if (crtc->config.has_audio) { |
DRM_DEBUG_DRIVER("Audio on pipe %c on DDI\n", |
pipe_name(crtc->pipe)); |
|
/* write eld */ |
DRM_DEBUG_DRIVER("DDI audio: write eld information\n"); |
intel_write_eld(encoder, &crtc->config.adjusted_mode); |
} |
|
if (type == INTEL_OUTPUT_EDP) { |
struct intel_dp *intel_dp = enc_to_intel_dp(encoder); |
ironlake_edp_panel_on(intel_dp); |
intel_edp_panel_on(intel_dp); |
} |
|
WARN_ON(intel_crtc->ddi_pll_sel == PORT_CLK_SEL_NONE); |
I915_WRITE(PORT_CLK_SEL(port), intel_crtc->ddi_pll_sel); |
WARN_ON(crtc->config.ddi_pll_sel == PORT_CLK_SEL_NONE); |
I915_WRITE(PORT_CLK_SEL(port), crtc->config.ddi_pll_sel); |
|
if (type == INTEL_OUTPUT_DISPLAYPORT || type == INTEL_OUTPUT_EDP) { |
struct intel_dp *intel_dp = enc_to_intel_dp(encoder); |
|
intel_ddi_init_dp_buf_reg(intel_encoder); |
|
intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON); |
intel_dp_start_link_train(intel_dp); |
intel_dp_complete_link_train(intel_dp); |
if (port != PORT_A) |
intel_dp_stop_link_train(intel_dp); |
} else if (type == INTEL_OUTPUT_HDMI) { |
struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); |
|
intel_hdmi->set_infoframes(encoder, |
crtc->config.has_hdmi_sink, |
&crtc->config.adjusted_mode); |
} |
} |
|
1244,7 → 1106,8 |
if (type == INTEL_OUTPUT_DISPLAYPORT || type == INTEL_OUTPUT_EDP) { |
struct intel_dp *intel_dp = enc_to_intel_dp(encoder); |
intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_OFF); |
ironlake_edp_panel_off(intel_dp); |
intel_edp_panel_vdd_on(intel_dp); |
intel_edp_panel_off(intel_dp); |
} |
|
I915_WRITE(PORT_CLK_SEL(port), PORT_CLK_SEL_NONE); |
1279,11 → 1142,12 |
if (port == PORT_A) |
intel_dp_stop_link_train(intel_dp); |
|
ironlake_edp_backlight_on(intel_dp); |
intel_edp_backlight_on(intel_dp); |
intel_edp_psr_enable(intel_dp); |
} |
|
if (intel_crtc->eld_vld && type != INTEL_OUTPUT_EDP) { |
if (intel_crtc->config.has_audio) { |
intel_display_power_get(dev_priv, POWER_DOMAIN_AUDIO); |
tmp = I915_READ(HSW_AUD_PIN_ELD_CP_VLD); |
tmp |= ((AUDIO_OUTPUT_ENABLE_A | AUDIO_ELD_VALID_A) << (pipe * 4)); |
I915_WRITE(HSW_AUD_PIN_ELD_CP_VLD, tmp); |
1301,11 → 1165,14 |
struct drm_i915_private *dev_priv = dev->dev_private; |
uint32_t tmp; |
|
if (intel_crtc->eld_vld && type != INTEL_OUTPUT_EDP) { |
/* We can't touch HSW_AUD_PIN_ELD_CP_VLD uncionditionally because this |
* register is part of the power well on Haswell. */ |
if (intel_crtc->config.has_audio) { |
tmp = I915_READ(HSW_AUD_PIN_ELD_CP_VLD); |
tmp &= ~((AUDIO_OUTPUT_ENABLE_A | AUDIO_ELD_VALID_A) << |
(pipe * 4)); |
I915_WRITE(HSW_AUD_PIN_ELD_CP_VLD, tmp); |
intel_display_power_put(dev_priv, POWER_DOMAIN_AUDIO); |
} |
|
if (type == INTEL_OUTPUT_EDP) { |
1312,7 → 1179,7 |
struct intel_dp *intel_dp = enc_to_intel_dp(encoder); |
|
intel_edp_psr_disable(intel_dp); |
ironlake_edp_backlight_off(intel_dp); |
intel_edp_backlight_off(intel_dp); |
} |
} |
|
1324,7 → 1191,7 |
|
if (lcpll & LCPLL_CD_SOURCE_FCLK) { |
return 800000; |
} else if (I915_READ(HSW_FUSE_STRAP) & HSW_CDCLK_LIMIT) { |
} else if (I915_READ(FUSE_STRAP) & HSW_CDCLK_LIMIT) { |
return 450000; |
} else if (freq == LCPLL_CLK_FREQ_450) { |
return 450000; |
1343,11 → 1210,61 |
} |
} |
|
static void hsw_ddi_pll_enable(struct drm_i915_private *dev_priv, |
struct intel_shared_dpll *pll) |
{ |
I915_WRITE(WRPLL_CTL(pll->id), pll->hw_state.wrpll); |
POSTING_READ(WRPLL_CTL(pll->id)); |
udelay(20); |
} |
|
static void hsw_ddi_pll_disable(struct drm_i915_private *dev_priv, |
struct intel_shared_dpll *pll) |
{ |
uint32_t val; |
|
val = I915_READ(WRPLL_CTL(pll->id)); |
I915_WRITE(WRPLL_CTL(pll->id), val & ~WRPLL_PLL_ENABLE); |
POSTING_READ(WRPLL_CTL(pll->id)); |
} |
|
static bool hsw_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv, |
struct intel_shared_dpll *pll, |
struct intel_dpll_hw_state *hw_state) |
{ |
uint32_t val; |
|
if (!intel_display_power_enabled(dev_priv, POWER_DOMAIN_PLLS)) |
return false; |
|
val = I915_READ(WRPLL_CTL(pll->id)); |
hw_state->wrpll = val; |
|
return val & WRPLL_PLL_ENABLE; |
} |
|
static const char * const hsw_ddi_pll_names[] = { |
"WRPLL 1", |
"WRPLL 2", |
}; |
|
void intel_ddi_pll_init(struct drm_device *dev) |
{ |
struct drm_i915_private *dev_priv = dev->dev_private; |
uint32_t val = I915_READ(LCPLL_CTL); |
int i; |
|
dev_priv->num_shared_dpll = 2; |
|
for (i = 0; i < dev_priv->num_shared_dpll; i++) { |
dev_priv->shared_dplls[i].id = i; |
dev_priv->shared_dplls[i].name = hsw_ddi_pll_names[i]; |
dev_priv->shared_dplls[i].disable = hsw_ddi_pll_disable; |
dev_priv->shared_dplls[i].enable = hsw_ddi_pll_enable; |
dev_priv->shared_dplls[i].get_hw_state = |
hsw_ddi_pll_get_hw_state; |
} |
|
/* The LCPLL register should be turned on by the BIOS. For now let's |
* just check its state and print errors in case something is wrong. |
* Don't even try to turn it on. |
1390,10 → 1307,15 |
intel_wait_ddi_buf_idle(dev_priv, port); |
} |
|
val = DP_TP_CTL_ENABLE | DP_TP_CTL_MODE_SST | |
val = DP_TP_CTL_ENABLE | |
DP_TP_CTL_LINK_TRAIN_PAT1 | DP_TP_CTL_SCRAMBLE_DISABLE; |
if (intel_dp->is_mst) |
val |= DP_TP_CTL_MODE_MST; |
else { |
val |= DP_TP_CTL_MODE_SST; |
if (drm_dp_enhanced_frame_cap(intel_dp->dpcd)) |
val |= DP_TP_CTL_ENHANCED_FRAME_ENABLE; |
} |
I915_WRITE(DP_TP_CTL(port), val); |
POSTING_READ(DP_TP_CTL(port)); |
|
1432,13 → 1354,18 |
|
static void intel_ddi_hot_plug(struct intel_encoder *intel_encoder) |
{ |
struct intel_dp *intel_dp = enc_to_intel_dp(&intel_encoder->base); |
int type = intel_encoder->type; |
struct intel_digital_port *intel_dig_port = enc_to_dig_port(&intel_encoder->base); |
int type = intel_dig_port->base.type; |
|
if (type == INTEL_OUTPUT_DISPLAYPORT || type == INTEL_OUTPUT_EDP) |
intel_dp_check_link_status(intel_dp); |
if (type != INTEL_OUTPUT_DISPLAYPORT && |
type != INTEL_OUTPUT_EDP && |
type != INTEL_OUTPUT_UNKNOWN) { |
return; |
} |
|
intel_dp_hot_plug(intel_encoder); |
} |
|
void intel_ddi_get_config(struct intel_encoder *encoder, |
struct intel_crtc_config *pipe_config) |
{ |
1478,6 → 1405,7 |
|
switch (temp & TRANS_DDI_MODE_SELECT_MASK) { |
case TRANS_DDI_MODE_SELECT_HDMI: |
pipe_config->has_hdmi_sink = true; |
case TRANS_DDI_MODE_SELECT_DVI: |
case TRANS_DDI_MODE_SELECT_FDI: |
break; |
1490,6 → 1418,12 |
break; |
} |
|
if (intel_display_power_enabled(dev_priv, POWER_DOMAIN_AUDIO)) { |
temp = I915_READ(HSW_AUD_PIN_ELD_CP_VLD); |
if (temp & (AUDIO_OUTPUT_ENABLE_A << (intel_crtc->pipe * 4))) |
pipe_config->has_audio = true; |
} |
|
if (encoder->type == INTEL_OUTPUT_EDP && dev_priv->vbt.edp_bpp && |
pipe_config->pipe_bpp > dev_priv->vbt.edp_bpp) { |
/* |
1509,6 → 1443,8 |
pipe_config->pipe_bpp, dev_priv->vbt.edp_bpp); |
dev_priv->vbt.edp_bpp = pipe_config->pipe_bpp; |
} |
|
intel_ddi_clock_get(encoder, pipe_config); |
} |
|
static void intel_ddi_destroy(struct drm_encoder *encoder) |
1579,8 → 1515,6 |
struct intel_digital_port *intel_dig_port; |
struct intel_encoder *intel_encoder; |
struct drm_encoder *encoder; |
struct intel_connector *hdmi_connector = NULL; |
struct intel_connector *dp_connector = NULL; |
bool init_hdmi, init_dp; |
|
init_hdmi = (dev_priv->vbt.ddi_port_info[port].supports_dvi || |
1587,7 → 1521,7 |
dev_priv->vbt.ddi_port_info[port].supports_hdmi); |
init_dp = dev_priv->vbt.ddi_port_info[port].supports_dp; |
if (!init_dp && !init_hdmi) { |
DRM_DEBUG_KMS("VBT says port %c is not DVI/HDMI/DP compatible\n", |
DRM_DEBUG_KMS("VBT says port %c is not DVI/HDMI/DP compatible, assuming it is\n", |
port_name(port)); |
init_hdmi = true; |
init_dp = true; |
1604,7 → 1538,6 |
DRM_MODE_ENCODER_TMDS); |
|
intel_encoder->compute_config = intel_ddi_compute_config; |
intel_encoder->mode_set = intel_ddi_mode_set; |
intel_encoder->enable = intel_enable_ddi; |
intel_encoder->pre_enable = intel_ddi_pre_enable; |
intel_encoder->disable = intel_disable_ddi; |
1619,19 → 1552,27 |
|
intel_encoder->type = INTEL_OUTPUT_UNKNOWN; |
intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2); |
intel_encoder->cloneable = false; |
intel_encoder->cloneable = 0; |
intel_encoder->hot_plug = intel_ddi_hot_plug; |
|
if (init_dp) |
dp_connector = intel_ddi_init_dp_connector(intel_dig_port); |
if (init_dp) { |
if (!intel_ddi_init_dp_connector(intel_dig_port)) |
goto err; |
|
intel_dig_port->hpd_pulse = intel_dp_hpd_pulse; |
dev_priv->hpd_irq_port[port] = intel_dig_port; |
} |
|
/* In theory we don't need the encoder->type check, but leave it just in |
* case we have some really bad VBTs... */ |
if (intel_encoder->type != INTEL_OUTPUT_EDP && init_hdmi) |
hdmi_connector = intel_ddi_init_hdmi_connector(intel_dig_port); |
if (intel_encoder->type != INTEL_OUTPUT_EDP && init_hdmi) { |
if (!intel_ddi_init_hdmi_connector(intel_dig_port)) |
goto err; |
} |
|
if (!dp_connector && !hdmi_connector) { |
return; |
|
err: |
drm_encoder_cleanup(encoder); |
kfree(intel_dig_port); |
} |
} |