|
@@ -416,13 +416,11 @@ static const intel_limit_t intel_limits_vlv_dp = {
|
|
|
|
|
|
u32 intel_dpio_read(struct drm_i915_private *dev_priv, int reg)
|
|
|
{
|
|
|
- unsigned long flags;
|
|
|
- u32 val = 0;
|
|
|
+ WARN_ON(!mutex_is_locked(&dev_priv->dpio_lock));
|
|
|
|
|
|
- spin_lock_irqsave(&dev_priv->dpio_lock, flags);
|
|
|
if (wait_for_atomic_us((I915_READ(DPIO_PKT) & DPIO_BUSY) == 0, 100)) {
|
|
|
DRM_ERROR("DPIO idle wait timed out\n");
|
|
|
- goto out_unlock;
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
I915_WRITE(DPIO_REG, reg);
|
|
@@ -430,24 +428,20 @@ u32 intel_dpio_read(struct drm_i915_private *dev_priv, int reg)
|
|
|
DPIO_BYTE);
|
|
|
if (wait_for_atomic_us((I915_READ(DPIO_PKT) & DPIO_BUSY) == 0, 100)) {
|
|
|
DRM_ERROR("DPIO read wait timed out\n");
|
|
|
- goto out_unlock;
|
|
|
+ return 0;
|
|
|
}
|
|
|
- val = I915_READ(DPIO_DATA);
|
|
|
|
|
|
-out_unlock:
|
|
|
- spin_unlock_irqrestore(&dev_priv->dpio_lock, flags);
|
|
|
- return val;
|
|
|
+ return I915_READ(DPIO_DATA);
|
|
|
}
|
|
|
|
|
|
static void intel_dpio_write(struct drm_i915_private *dev_priv, int reg,
|
|
|
u32 val)
|
|
|
{
|
|
|
- unsigned long flags;
|
|
|
+ WARN_ON(!mutex_is_locked(&dev_priv->dpio_lock));
|
|
|
|
|
|
- spin_lock_irqsave(&dev_priv->dpio_lock, flags);
|
|
|
if (wait_for_atomic_us((I915_READ(DPIO_PKT) & DPIO_BUSY) == 0, 100)) {
|
|
|
DRM_ERROR("DPIO idle wait timed out\n");
|
|
|
- goto out_unlock;
|
|
|
+ return;
|
|
|
}
|
|
|
|
|
|
I915_WRITE(DPIO_DATA, val);
|
|
@@ -456,9 +450,6 @@ static void intel_dpio_write(struct drm_i915_private *dev_priv, int reg,
|
|
|
DPIO_BYTE);
|
|
|
if (wait_for_atomic_us((I915_READ(DPIO_PKT) & DPIO_BUSY) == 0, 100))
|
|
|
DRM_ERROR("DPIO write wait timed out\n");
|
|
|
-
|
|
|
-out_unlock:
|
|
|
- spin_unlock_irqrestore(&dev_priv->dpio_lock, flags);
|
|
|
}
|
|
|
|
|
|
static void vlv_init_dpio(struct drm_device *dev)
|
|
@@ -472,61 +463,14 @@ static void vlv_init_dpio(struct drm_device *dev)
|
|
|
POSTING_READ(DPIO_CTL);
|
|
|
}
|
|
|
|
|
|
-static int intel_dual_link_lvds_callback(const struct dmi_system_id *id)
|
|
|
-{
|
|
|
- DRM_INFO("Forcing lvds to dual link mode on %s\n", id->ident);
|
|
|
- return 1;
|
|
|
-}
|
|
|
-
|
|
|
-static const struct dmi_system_id intel_dual_link_lvds[] = {
|
|
|
- {
|
|
|
- .callback = intel_dual_link_lvds_callback,
|
|
|
- .ident = "Apple MacBook Pro (Core i5/i7 Series)",
|
|
|
- .matches = {
|
|
|
- DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
|
|
|
- DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro8,2"),
|
|
|
- },
|
|
|
- },
|
|
|
- { } /* terminating entry */
|
|
|
-};
|
|
|
-
|
|
|
-static bool is_dual_link_lvds(struct drm_i915_private *dev_priv,
|
|
|
- unsigned int reg)
|
|
|
-{
|
|
|
- unsigned int val;
|
|
|
-
|
|
|
- /* use the module option value if specified */
|
|
|
- if (i915_lvds_channel_mode > 0)
|
|
|
- return i915_lvds_channel_mode == 2;
|
|
|
-
|
|
|
- if (dmi_check_system(intel_dual_link_lvds))
|
|
|
- return true;
|
|
|
-
|
|
|
- if (dev_priv->lvds_val)
|
|
|
- val = dev_priv->lvds_val;
|
|
|
- else {
|
|
|
- /* BIOS should set the proper LVDS register value at boot, but
|
|
|
- * in reality, it doesn't set the value when the lid is closed;
|
|
|
- * we need to check "the value to be set" in VBT when LVDS
|
|
|
- * register is uninitialized.
|
|
|
- */
|
|
|
- val = I915_READ(reg);
|
|
|
- if (!(val & ~(LVDS_PIPE_MASK | LVDS_DETECTED)))
|
|
|
- val = dev_priv->bios_lvds_val;
|
|
|
- dev_priv->lvds_val = val;
|
|
|
- }
|
|
|
- return (val & LVDS_CLKB_POWER_MASK) == LVDS_CLKB_POWER_UP;
|
|
|
-}
|
|
|
-
|
|
|
static const intel_limit_t *intel_ironlake_limit(struct drm_crtc *crtc,
|
|
|
int refclk)
|
|
|
{
|
|
|
struct drm_device *dev = crtc->dev;
|
|
|
- struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
const intel_limit_t *limit;
|
|
|
|
|
|
if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) {
|
|
|
- if (is_dual_link_lvds(dev_priv, PCH_LVDS)) {
|
|
|
+ if (intel_is_dual_link_lvds(dev)) {
|
|
|
/* LVDS dual channel */
|
|
|
if (refclk == 100000)
|
|
|
limit = &intel_limits_ironlake_dual_lvds_100m;
|
|
@@ -550,11 +494,10 @@ static const intel_limit_t *intel_ironlake_limit(struct drm_crtc *crtc,
|
|
|
static const intel_limit_t *intel_g4x_limit(struct drm_crtc *crtc)
|
|
|
{
|
|
|
struct drm_device *dev = crtc->dev;
|
|
|
- struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
const intel_limit_t *limit;
|
|
|
|
|
|
if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) {
|
|
|
- if (is_dual_link_lvds(dev_priv, LVDS))
|
|
|
+ if (intel_is_dual_link_lvds(dev))
|
|
|
/* LVDS with dual channel */
|
|
|
limit = &intel_limits_g4x_dual_channel_lvds;
|
|
|
else
|
|
@@ -686,19 +629,16 @@ intel_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
|
|
|
|
|
|
{
|
|
|
struct drm_device *dev = crtc->dev;
|
|
|
- struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
intel_clock_t clock;
|
|
|
int err = target;
|
|
|
|
|
|
- if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) &&
|
|
|
- (I915_READ(LVDS)) != 0) {
|
|
|
+ if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) {
|
|
|
/*
|
|
|
- * For LVDS, if the panel is on, just rely on its current
|
|
|
- * settings for dual-channel. We haven't figured out how to
|
|
|
- * reliably set up different single/dual channel state, if we
|
|
|
- * even can.
|
|
|
+ * For LVDS just rely on its current settings for dual-channel.
|
|
|
+ * We haven't figured out how to reliably set up different
|
|
|
+ * single/dual channel state, if we even can.
|
|
|
*/
|
|
|
- if (is_dual_link_lvds(dev_priv, LVDS))
|
|
|
+ if (intel_is_dual_link_lvds(dev))
|
|
|
clock.p2 = limit->p2.p2_fast;
|
|
|
else
|
|
|
clock.p2 = limit->p2.p2_slow;
|
|
@@ -751,7 +691,6 @@ intel_g4x_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
|
|
|
intel_clock_t *best_clock)
|
|
|
{
|
|
|
struct drm_device *dev = crtc->dev;
|
|
|
- struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
intel_clock_t clock;
|
|
|
int max_n;
|
|
|
bool found;
|
|
@@ -766,8 +705,7 @@ intel_g4x_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
|
|
|
lvds_reg = PCH_LVDS;
|
|
|
else
|
|
|
lvds_reg = LVDS;
|
|
|
- if ((I915_READ(lvds_reg) & LVDS_CLKB_POWER_MASK) ==
|
|
|
- LVDS_CLKB_POWER_UP)
|
|
|
+ if (intel_is_dual_link_lvds(dev))
|
|
|
clock.p2 = limit->p2.p2_fast;
|
|
|
else
|
|
|
clock.p2 = limit->p2.p2_slow;
|
|
@@ -1047,6 +985,51 @@ void intel_wait_for_pipe_off(struct drm_device *dev, int pipe)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+/*
|
|
|
+ * ibx_digital_port_connected - is the specified port connected?
|
|
|
+ * @dev_priv: i915 private structure
|
|
|
+ * @port: the port to test
|
|
|
+ *
|
|
|
+ * Returns true if @port is connected, false otherwise.
|
|
|
+ */
|
|
|
+bool ibx_digital_port_connected(struct drm_i915_private *dev_priv,
|
|
|
+ struct intel_digital_port *port)
|
|
|
+{
|
|
|
+ u32 bit;
|
|
|
+
|
|
|
+ if (HAS_PCH_IBX(dev_priv->dev)) {
|
|
|
+ switch(port->port) {
|
|
|
+ case PORT_B:
|
|
|
+ bit = SDE_PORTB_HOTPLUG;
|
|
|
+ break;
|
|
|
+ case PORT_C:
|
|
|
+ bit = SDE_PORTC_HOTPLUG;
|
|
|
+ break;
|
|
|
+ case PORT_D:
|
|
|
+ bit = SDE_PORTD_HOTPLUG;
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ switch(port->port) {
|
|
|
+ case PORT_B:
|
|
|
+ bit = SDE_PORTB_HOTPLUG_CPT;
|
|
|
+ break;
|
|
|
+ case PORT_C:
|
|
|
+ bit = SDE_PORTC_HOTPLUG_CPT;
|
|
|
+ break;
|
|
|
+ case PORT_D:
|
|
|
+ bit = SDE_PORTD_HOTPLUG_CPT;
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return I915_READ(SDEISR) & bit;
|
|
|
+}
|
|
|
+
|
|
|
static const char *state_string(bool enabled)
|
|
|
{
|
|
|
return enabled ? "on" : "off";
|
|
@@ -1125,8 +1108,8 @@ static void assert_fdi_tx(struct drm_i915_private *dev_priv,
|
|
|
enum transcoder cpu_transcoder = intel_pipe_to_cpu_transcoder(dev_priv,
|
|
|
pipe);
|
|
|
|
|
|
- if (IS_HASWELL(dev_priv->dev)) {
|
|
|
- /* On Haswell, DDI is used instead of FDI_TX_CTL */
|
|
|
+ if (HAS_DDI(dev_priv->dev)) {
|
|
|
+ /* DDI does not have a specific FDI_TX register */
|
|
|
reg = TRANS_DDI_FUNC_CTL(cpu_transcoder);
|
|
|
val = I915_READ(reg);
|
|
|
cur_state = !!(val & TRANS_DDI_FUNC_ENABLE);
|
|
@@ -1170,7 +1153,7 @@ static void assert_fdi_tx_pll_enabled(struct drm_i915_private *dev_priv,
|
|
|
return;
|
|
|
|
|
|
/* On Haswell, DDI ports are responsible for the FDI PLL setup */
|
|
|
- if (IS_HASWELL(dev_priv->dev))
|
|
|
+ if (HAS_DDI(dev_priv->dev))
|
|
|
return;
|
|
|
|
|
|
reg = FDI_TX_CTL(pipe);
|
|
@@ -1509,13 +1492,14 @@ static void
|
|
|
intel_sbi_write(struct drm_i915_private *dev_priv, u16 reg, u32 value,
|
|
|
enum intel_sbi_destination destination)
|
|
|
{
|
|
|
- unsigned long flags;
|
|
|
u32 tmp;
|
|
|
|
|
|
- spin_lock_irqsave(&dev_priv->dpio_lock, flags);
|
|
|
- if (wait_for((I915_READ(SBI_CTL_STAT) & SBI_BUSY) == 0, 100)) {
|
|
|
+ WARN_ON(!mutex_is_locked(&dev_priv->dpio_lock));
|
|
|
+
|
|
|
+ if (wait_for((I915_READ(SBI_CTL_STAT) & SBI_BUSY) == 0,
|
|
|
+ 100)) {
|
|
|
DRM_ERROR("timeout waiting for SBI to become ready\n");
|
|
|
- goto out_unlock;
|
|
|
+ return;
|
|
|
}
|
|
|
|
|
|
I915_WRITE(SBI_ADDR, (reg << 16));
|
|
@@ -1530,24 +1514,21 @@ intel_sbi_write(struct drm_i915_private *dev_priv, u16 reg, u32 value,
|
|
|
if (wait_for((I915_READ(SBI_CTL_STAT) & (SBI_BUSY | SBI_RESPONSE_FAIL)) == 0,
|
|
|
100)) {
|
|
|
DRM_ERROR("timeout waiting for SBI to complete write transaction\n");
|
|
|
- goto out_unlock;
|
|
|
+ return;
|
|
|
}
|
|
|
-
|
|
|
-out_unlock:
|
|
|
- spin_unlock_irqrestore(&dev_priv->dpio_lock, flags);
|
|
|
}
|
|
|
|
|
|
static u32
|
|
|
intel_sbi_read(struct drm_i915_private *dev_priv, u16 reg,
|
|
|
enum intel_sbi_destination destination)
|
|
|
{
|
|
|
- unsigned long flags;
|
|
|
u32 value = 0;
|
|
|
+ WARN_ON(!mutex_is_locked(&dev_priv->dpio_lock));
|
|
|
|
|
|
- spin_lock_irqsave(&dev_priv->dpio_lock, flags);
|
|
|
- if (wait_for((I915_READ(SBI_CTL_STAT) & SBI_BUSY) == 0, 100)) {
|
|
|
+ if (wait_for((I915_READ(SBI_CTL_STAT) & SBI_BUSY) == 0,
|
|
|
+ 100)) {
|
|
|
DRM_ERROR("timeout waiting for SBI to become ready\n");
|
|
|
- goto out_unlock;
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
I915_WRITE(SBI_ADDR, (reg << 16));
|
|
@@ -1561,14 +1542,10 @@ intel_sbi_read(struct drm_i915_private *dev_priv, u16 reg,
|
|
|
if (wait_for((I915_READ(SBI_CTL_STAT) & (SBI_BUSY | SBI_RESPONSE_FAIL)) == 0,
|
|
|
100)) {
|
|
|
DRM_ERROR("timeout waiting for SBI to complete read transaction\n");
|
|
|
- goto out_unlock;
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
- value = I915_READ(SBI_DATA);
|
|
|
-
|
|
|
-out_unlock:
|
|
|
- spin_unlock_irqrestore(&dev_priv->dpio_lock, flags);
|
|
|
- return value;
|
|
|
+ return I915_READ(SBI_DATA);
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -1700,8 +1677,8 @@ static void ironlake_enable_pch_transcoder(struct drm_i915_private *dev_priv,
|
|
|
* make the BPC in transcoder be consistent with
|
|
|
* that in pipeconf reg.
|
|
|
*/
|
|
|
- val &= ~PIPE_BPC_MASK;
|
|
|
- val |= pipeconf_val & PIPE_BPC_MASK;
|
|
|
+ val &= ~PIPECONF_BPC_MASK;
|
|
|
+ val |= pipeconf_val & PIPECONF_BPC_MASK;
|
|
|
}
|
|
|
|
|
|
val &= ~TRANS_INTERLACE_MASK;
|
|
@@ -1728,7 +1705,7 @@ static void lpt_enable_pch_transcoder(struct drm_i915_private *dev_priv,
|
|
|
BUG_ON(dev_priv->info->gen < 5);
|
|
|
|
|
|
/* FDI must be feeding us bits for PCH ports */
|
|
|
- assert_fdi_tx_enabled(dev_priv, cpu_transcoder);
|
|
|
+ assert_fdi_tx_enabled(dev_priv, (enum pipe) cpu_transcoder);
|
|
|
assert_fdi_rx_enabled(dev_priv, TRANSCODER_A);
|
|
|
|
|
|
/* Workaround: set timing override bit. */
|
|
@@ -1816,11 +1793,11 @@ static void intel_enable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe,
|
|
|
{
|
|
|
enum transcoder cpu_transcoder = intel_pipe_to_cpu_transcoder(dev_priv,
|
|
|
pipe);
|
|
|
- enum transcoder pch_transcoder;
|
|
|
+ enum pipe pch_transcoder;
|
|
|
int reg;
|
|
|
u32 val;
|
|
|
|
|
|
- if (IS_HASWELL(dev_priv->dev))
|
|
|
+ if (HAS_PCH_LPT(dev_priv->dev))
|
|
|
pch_transcoder = TRANSCODER_A;
|
|
|
else
|
|
|
pch_transcoder = pipe;
|
|
@@ -1836,7 +1813,8 @@ static void intel_enable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe,
|
|
|
if (pch_port) {
|
|
|
/* if driving the PCH, we need FDI enabled */
|
|
|
assert_fdi_rx_pll_enabled(dev_priv, pch_transcoder);
|
|
|
- assert_fdi_tx_pll_enabled(dev_priv, cpu_transcoder);
|
|
|
+ assert_fdi_tx_pll_enabled(dev_priv,
|
|
|
+ (enum pipe) cpu_transcoder);
|
|
|
}
|
|
|
/* FIXME: assert CPU port conditions for SNB+ */
|
|
|
}
|
|
@@ -2350,43 +2328,6 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-static void ironlake_set_pll_edp(struct drm_crtc *crtc, int clock)
|
|
|
-{
|
|
|
- struct drm_device *dev = crtc->dev;
|
|
|
- struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
- u32 dpa_ctl;
|
|
|
-
|
|
|
- DRM_DEBUG_KMS("eDP PLL enable for clock %d\n", clock);
|
|
|
- dpa_ctl = I915_READ(DP_A);
|
|
|
- dpa_ctl &= ~DP_PLL_FREQ_MASK;
|
|
|
-
|
|
|
- if (clock < 200000) {
|
|
|
- u32 temp;
|
|
|
- dpa_ctl |= DP_PLL_FREQ_160MHZ;
|
|
|
- /* workaround for 160Mhz:
|
|
|
- 1) program 0x4600c bits 15:0 = 0x8124
|
|
|
- 2) program 0x46010 bit 0 = 1
|
|
|
- 3) program 0x46034 bit 24 = 1
|
|
|
- 4) program 0x64000 bit 14 = 1
|
|
|
- */
|
|
|
- temp = I915_READ(0x4600c);
|
|
|
- temp &= 0xffff0000;
|
|
|
- I915_WRITE(0x4600c, temp | 0x8124);
|
|
|
-
|
|
|
- temp = I915_READ(0x46010);
|
|
|
- I915_WRITE(0x46010, temp | 1);
|
|
|
-
|
|
|
- temp = I915_READ(0x46034);
|
|
|
- I915_WRITE(0x46034, temp | (1 << 24));
|
|
|
- } else {
|
|
|
- dpa_ctl |= DP_PLL_FREQ_270MHZ;
|
|
|
- }
|
|
|
- I915_WRITE(DP_A, dpa_ctl);
|
|
|
-
|
|
|
- POSTING_READ(DP_A);
|
|
|
- udelay(500);
|
|
|
-}
|
|
|
-
|
|
|
static void intel_fdi_normal_train(struct drm_crtc *crtc)
|
|
|
{
|
|
|
struct drm_device *dev = crtc->dev;
|
|
@@ -2815,7 +2756,7 @@ static void ironlake_fdi_pll_enable(struct intel_crtc *intel_crtc)
|
|
|
temp = I915_READ(reg);
|
|
|
temp &= ~((0x7 << 19) | (0x7 << 16));
|
|
|
temp |= (intel_crtc->fdi_lanes - 1) << 19;
|
|
|
- temp |= (I915_READ(PIPECONF(pipe)) & PIPE_BPC_MASK) << 11;
|
|
|
+ temp |= (I915_READ(PIPECONF(pipe)) & PIPECONF_BPC_MASK) << 11;
|
|
|
I915_WRITE(reg, temp | FDI_RX_PLL_ENABLE);
|
|
|
|
|
|
POSTING_READ(reg);
|
|
@@ -2828,18 +2769,14 @@ static void ironlake_fdi_pll_enable(struct intel_crtc *intel_crtc)
|
|
|
POSTING_READ(reg);
|
|
|
udelay(200);
|
|
|
|
|
|
- /* On Haswell, the PLL configuration for ports and pipes is handled
|
|
|
- * separately, as part of DDI setup */
|
|
|
- if (!IS_HASWELL(dev)) {
|
|
|
- /* Enable CPU FDI TX PLL, always on for Ironlake */
|
|
|
- reg = FDI_TX_CTL(pipe);
|
|
|
- temp = I915_READ(reg);
|
|
|
- if ((temp & FDI_TX_PLL_ENABLE) == 0) {
|
|
|
- I915_WRITE(reg, temp | FDI_TX_PLL_ENABLE);
|
|
|
+ /* Enable CPU FDI TX PLL, always on for Ironlake */
|
|
|
+ reg = FDI_TX_CTL(pipe);
|
|
|
+ temp = I915_READ(reg);
|
|
|
+ if ((temp & FDI_TX_PLL_ENABLE) == 0) {
|
|
|
+ I915_WRITE(reg, temp | FDI_TX_PLL_ENABLE);
|
|
|
|
|
|
- POSTING_READ(reg);
|
|
|
- udelay(100);
|
|
|
- }
|
|
|
+ POSTING_READ(reg);
|
|
|
+ udelay(100);
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -2889,7 +2826,7 @@ static void ironlake_fdi_disable(struct drm_crtc *crtc)
|
|
|
reg = FDI_RX_CTL(pipe);
|
|
|
temp = I915_READ(reg);
|
|
|
temp &= ~(0x7 << 16);
|
|
|
- temp |= (I915_READ(PIPECONF(pipe)) & PIPE_BPC_MASK) << 11;
|
|
|
+ temp |= (I915_READ(PIPECONF(pipe)) & PIPECONF_BPC_MASK) << 11;
|
|
|
I915_WRITE(reg, temp & ~FDI_RX_ENABLE);
|
|
|
|
|
|
POSTING_READ(reg);
|
|
@@ -2918,7 +2855,7 @@ static void ironlake_fdi_disable(struct drm_crtc *crtc)
|
|
|
}
|
|
|
/* BPC in FDI rx is consistent with that in PIPECONF */
|
|
|
temp &= ~(0x07 << 16);
|
|
|
- temp |= (I915_READ(PIPECONF(pipe)) & PIPE_BPC_MASK) << 11;
|
|
|
+ temp |= (I915_READ(PIPECONF(pipe)) & PIPECONF_BPC_MASK) << 11;
|
|
|
I915_WRITE(reg, temp);
|
|
|
|
|
|
POSTING_READ(reg);
|
|
@@ -2992,6 +2929,8 @@ static void lpt_program_iclkip(struct drm_crtc *crtc)
|
|
|
u32 divsel, phaseinc, auxdiv, phasedir = 0;
|
|
|
u32 temp;
|
|
|
|
|
|
+ mutex_lock(&dev_priv->dpio_lock);
|
|
|
+
|
|
|
/* It is necessary to ungate the pixclk gate prior to programming
|
|
|
* the divisors, and gate it back when it is done.
|
|
|
*/
|
|
@@ -3066,6 +3005,8 @@ static void lpt_program_iclkip(struct drm_crtc *crtc)
|
|
|
udelay(24);
|
|
|
|
|
|
I915_WRITE(PIXCLK_GATE, PIXCLK_GATE_UNGATE);
|
|
|
+
|
|
|
+ mutex_unlock(&dev_priv->dpio_lock);
|
|
|
}
|
|
|
|
|
|
/*
|
|
@@ -3146,7 +3087,7 @@ static void ironlake_pch_enable(struct drm_crtc *crtc)
|
|
|
if (HAS_PCH_CPT(dev) &&
|
|
|
(intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT) ||
|
|
|
intel_pipe_has_type(crtc, INTEL_OUTPUT_EDP))) {
|
|
|
- u32 bpc = (I915_READ(PIPECONF(pipe)) & PIPE_BPC_MASK) >> 5;
|
|
|
+ u32 bpc = (I915_READ(PIPECONF(pipe)) & PIPECONF_BPC_MASK) >> 5;
|
|
|
reg = TRANS_DP_CTL(pipe);
|
|
|
temp = I915_READ(reg);
|
|
|
temp &= ~(TRANS_DP_PORT_SEL_MASK |
|
|
@@ -3623,7 +3564,7 @@ static void haswell_crtc_off(struct drm_crtc *crtc)
|
|
|
|
|
|
/* Stop saying we're using TRANSCODER_EDP because some other CRTC might
|
|
|
* start using it. */
|
|
|
- intel_crtc->cpu_transcoder = intel_crtc->pipe;
|
|
|
+ intel_crtc->cpu_transcoder = (enum transcoder) intel_crtc->pipe;
|
|
|
|
|
|
intel_ddi_put_crtc_pll(crtc);
|
|
|
}
|
|
@@ -4012,16 +3953,8 @@ static int i830_get_display_clock_speed(struct drm_device *dev)
|
|
|
return 133000;
|
|
|
}
|
|
|
|
|
|
-struct fdi_m_n {
|
|
|
- u32 tu;
|
|
|
- u32 gmch_m;
|
|
|
- u32 gmch_n;
|
|
|
- u32 link_m;
|
|
|
- u32 link_n;
|
|
|
-};
|
|
|
-
|
|
|
static void
|
|
|
-fdi_reduce_ratio(u32 *num, u32 *den)
|
|
|
+intel_reduce_ratio(uint32_t *num, uint32_t *den)
|
|
|
{
|
|
|
while (*num > 0xffffff || *den > 0xffffff) {
|
|
|
*num >>= 1;
|
|
@@ -4029,20 +3962,18 @@ fdi_reduce_ratio(u32 *num, u32 *den)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-static void
|
|
|
-ironlake_compute_m_n(int bits_per_pixel, int nlanes, int pixel_clock,
|
|
|
- int link_clock, struct fdi_m_n *m_n)
|
|
|
+void
|
|
|
+intel_link_compute_m_n(int bits_per_pixel, int nlanes,
|
|
|
+ int pixel_clock, int link_clock,
|
|
|
+ struct intel_link_m_n *m_n)
|
|
|
{
|
|
|
- m_n->tu = 64; /* default size */
|
|
|
-
|
|
|
- /* BUG_ON(pixel_clock > INT_MAX / 36); */
|
|
|
+ m_n->tu = 64;
|
|
|
m_n->gmch_m = bits_per_pixel * pixel_clock;
|
|
|
m_n->gmch_n = link_clock * nlanes * 8;
|
|
|
- fdi_reduce_ratio(&m_n->gmch_m, &m_n->gmch_n);
|
|
|
-
|
|
|
+ intel_reduce_ratio(&m_n->gmch_m, &m_n->gmch_n);
|
|
|
m_n->link_m = pixel_clock;
|
|
|
m_n->link_n = link_clock;
|
|
|
- fdi_reduce_ratio(&m_n->link_m, &m_n->link_n);
|
|
|
+ intel_reduce_ratio(&m_n->link_m, &m_n->link_n);
|
|
|
}
|
|
|
|
|
|
static inline bool intel_panel_use_ssc(struct drm_i915_private *dev_priv)
|
|
@@ -4289,51 +4220,6 @@ static void i9xx_update_pll_dividers(struct drm_crtc *crtc,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-static void intel_update_lvds(struct drm_crtc *crtc, intel_clock_t *clock,
|
|
|
- struct drm_display_mode *adjusted_mode)
|
|
|
-{
|
|
|
- struct drm_device *dev = crtc->dev;
|
|
|
- struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
- struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
|
- int pipe = intel_crtc->pipe;
|
|
|
- u32 temp;
|
|
|
-
|
|
|
- temp = I915_READ(LVDS);
|
|
|
- temp |= LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP;
|
|
|
- if (pipe == 1) {
|
|
|
- temp |= LVDS_PIPEB_SELECT;
|
|
|
- } else {
|
|
|
- temp &= ~LVDS_PIPEB_SELECT;
|
|
|
- }
|
|
|
- /* set the corresponsding LVDS_BORDER bit */
|
|
|
- temp |= dev_priv->lvds_border_bits;
|
|
|
- /* Set the B0-B3 data pairs corresponding to whether we're going to
|
|
|
- * set the DPLLs for dual-channel mode or not.
|
|
|
- */
|
|
|
- if (clock->p2 == 7)
|
|
|
- temp |= LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP;
|
|
|
- else
|
|
|
- temp &= ~(LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP);
|
|
|
-
|
|
|
- /* It would be nice to set 24 vs 18-bit mode (LVDS_A3_POWER_UP)
|
|
|
- * appropriately here, but we need to look more thoroughly into how
|
|
|
- * panels behave in the two modes.
|
|
|
- */
|
|
|
- /* set the dithering flag on LVDS as needed */
|
|
|
- if (INTEL_INFO(dev)->gen >= 4) {
|
|
|
- if (dev_priv->lvds_dither)
|
|
|
- temp |= LVDS_ENABLE_DITHER;
|
|
|
- else
|
|
|
- temp &= ~LVDS_ENABLE_DITHER;
|
|
|
- }
|
|
|
- temp &= ~(LVDS_HSYNC_POLARITY | LVDS_VSYNC_POLARITY);
|
|
|
- if (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC)
|
|
|
- temp |= LVDS_HSYNC_POLARITY;
|
|
|
- if (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC)
|
|
|
- temp |= LVDS_VSYNC_POLARITY;
|
|
|
- I915_WRITE(LVDS, temp);
|
|
|
-}
|
|
|
-
|
|
|
static void vlv_update_pll(struct drm_crtc *crtc,
|
|
|
struct drm_display_mode *mode,
|
|
|
struct drm_display_mode *adjusted_mode,
|
|
@@ -4349,6 +4235,8 @@ static void vlv_update_pll(struct drm_crtc *crtc,
|
|
|
bool is_sdvo;
|
|
|
u32 temp;
|
|
|
|
|
|
+ mutex_lock(&dev_priv->dpio_lock);
|
|
|
+
|
|
|
is_sdvo = intel_pipe_has_type(crtc, INTEL_OUTPUT_SDVO) ||
|
|
|
intel_pipe_has_type(crtc, INTEL_OUTPUT_HDMI);
|
|
|
|
|
@@ -4432,6 +4320,8 @@ static void vlv_update_pll(struct drm_crtc *crtc,
|
|
|
temp |= (1 << 21);
|
|
|
intel_dpio_write(dev_priv, DPIO_DATA_CHANNEL2, temp);
|
|
|
}
|
|
|
+
|
|
|
+ mutex_unlock(&dev_priv->dpio_lock);
|
|
|
}
|
|
|
|
|
|
static void i9xx_update_pll(struct drm_crtc *crtc,
|
|
@@ -4443,6 +4333,7 @@ static void i9xx_update_pll(struct drm_crtc *crtc,
|
|
|
struct drm_device *dev = crtc->dev;
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
|
+ struct intel_encoder *encoder;
|
|
|
int pipe = intel_crtc->pipe;
|
|
|
u32 dpll;
|
|
|
bool is_sdvo;
|
|
@@ -4511,12 +4402,9 @@ static void i9xx_update_pll(struct drm_crtc *crtc,
|
|
|
POSTING_READ(DPLL(pipe));
|
|
|
udelay(150);
|
|
|
|
|
|
- /* The LVDS pin pair needs to be on before the DPLLs are enabled.
|
|
|
- * This is an exception to the general rule that mode_set doesn't turn
|
|
|
- * things on.
|
|
|
- */
|
|
|
- if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS))
|
|
|
- intel_update_lvds(crtc, clock, adjusted_mode);
|
|
|
+ for_each_encoder_on_crtc(dev, crtc, encoder)
|
|
|
+ if (encoder->pre_pll_enable)
|
|
|
+ encoder->pre_pll_enable(encoder);
|
|
|
|
|
|
if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT))
|
|
|
intel_dp_set_m_n(crtc, mode, adjusted_mode);
|
|
@@ -4555,6 +4443,7 @@ static void i8xx_update_pll(struct drm_crtc *crtc,
|
|
|
struct drm_device *dev = crtc->dev;
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
|
+ struct intel_encoder *encoder;
|
|
|
int pipe = intel_crtc->pipe;
|
|
|
u32 dpll;
|
|
|
|
|
@@ -4588,12 +4477,9 @@ static void i8xx_update_pll(struct drm_crtc *crtc,
|
|
|
POSTING_READ(DPLL(pipe));
|
|
|
udelay(150);
|
|
|
|
|
|
- /* The LVDS pin pair needs to be on before the DPLLs are enabled.
|
|
|
- * This is an exception to the general rule that mode_set doesn't turn
|
|
|
- * things on.
|
|
|
- */
|
|
|
- if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS))
|
|
|
- intel_update_lvds(crtc, clock, adjusted_mode);
|
|
|
+ for_each_encoder_on_crtc(dev, crtc, encoder)
|
|
|
+ if (encoder->pre_pll_enable)
|
|
|
+ encoder->pre_pll_enable(encoder);
|
|
|
|
|
|
I915_WRITE(DPLL(pipe), dpll);
|
|
|
|
|
@@ -4783,10 +4669,10 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc,
|
|
|
}
|
|
|
|
|
|
/* default to 8bpc */
|
|
|
- pipeconf &= ~(PIPECONF_BPP_MASK | PIPECONF_DITHER_EN);
|
|
|
+ pipeconf &= ~(PIPECONF_BPC_MASK | PIPECONF_DITHER_EN);
|
|
|
if (is_dp) {
|
|
|
if (adjusted_mode->private_flags & INTEL_MODE_DP_FORCE_6BPC) {
|
|
|
- pipeconf |= PIPECONF_BPP_6 |
|
|
|
+ pipeconf |= PIPECONF_6BPC |
|
|
|
PIPECONF_DITHER_EN |
|
|
|
PIPECONF_DITHER_TYPE_SP;
|
|
|
}
|
|
@@ -4794,7 +4680,7 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc,
|
|
|
|
|
|
if (IS_VALLEYVIEW(dev) && intel_pipe_has_type(crtc, INTEL_OUTPUT_EDP)) {
|
|
|
if (adjusted_mode->private_flags & INTEL_MODE_DP_FORCE_6BPC) {
|
|
|
- pipeconf |= PIPECONF_BPP_6 |
|
|
|
+ pipeconf |= PIPECONF_6BPC |
|
|
|
PIPECONF_ENABLE |
|
|
|
I965_PIPECONF_ACTIVE;
|
|
|
}
|
|
@@ -5177,19 +5063,19 @@ static void ironlake_set_pipeconf(struct drm_crtc *crtc,
|
|
|
|
|
|
val = I915_READ(PIPECONF(pipe));
|
|
|
|
|
|
- val &= ~PIPE_BPC_MASK;
|
|
|
+ val &= ~PIPECONF_BPC_MASK;
|
|
|
switch (intel_crtc->bpp) {
|
|
|
case 18:
|
|
|
- val |= PIPE_6BPC;
|
|
|
+ val |= PIPECONF_6BPC;
|
|
|
break;
|
|
|
case 24:
|
|
|
- val |= PIPE_8BPC;
|
|
|
+ val |= PIPECONF_8BPC;
|
|
|
break;
|
|
|
case 30:
|
|
|
- val |= PIPE_10BPC;
|
|
|
+ val |= PIPECONF_10BPC;
|
|
|
break;
|
|
|
case 36:
|
|
|
- val |= PIPE_12BPC;
|
|
|
+ val |= PIPECONF_12BPC;
|
|
|
break;
|
|
|
default:
|
|
|
/* Case prevented by intel_choose_pipe_bpp_dither. */
|
|
@@ -5400,7 +5286,7 @@ static void ironlake_set_m_n(struct drm_crtc *crtc,
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
|
enum transcoder cpu_transcoder = intel_crtc->cpu_transcoder;
|
|
|
struct intel_encoder *intel_encoder, *edp_encoder = NULL;
|
|
|
- struct fdi_m_n m_n = {0};
|
|
|
+ struct intel_link_m_n m_n = {0};
|
|
|
int target_clock, pixel_multiplier, lane, link_bw;
|
|
|
bool is_dp = false, is_cpu_edp = false;
|
|
|
|
|
@@ -5452,8 +5338,7 @@ static void ironlake_set_m_n(struct drm_crtc *crtc,
|
|
|
|
|
|
if (pixel_multiplier > 1)
|
|
|
link_bw *= pixel_multiplier;
|
|
|
- ironlake_compute_m_n(intel_crtc->bpp, lane, target_clock, link_bw,
|
|
|
- &m_n);
|
|
|
+ intel_link_compute_m_n(intel_crtc->bpp, lane, target_clock, link_bw, &m_n);
|
|
|
|
|
|
I915_WRITE(PIPE_DATA_M1(cpu_transcoder), TU_SIZE(m_n.tu) | m_n.gmch_m);
|
|
|
I915_WRITE(PIPE_DATA_N1(cpu_transcoder), m_n.gmch_n);
|
|
@@ -5506,7 +5391,7 @@ static uint32_t ironlake_compute_dpll(struct intel_crtc *intel_crtc,
|
|
|
if (is_lvds) {
|
|
|
if ((intel_panel_use_ssc(dev_priv) &&
|
|
|
dev_priv->lvds_ssc_freq == 100) ||
|
|
|
- (I915_READ(PCH_LVDS) & LVDS_CLKB_POWER_MASK) == LVDS_CLKB_POWER_UP)
|
|
|
+ intel_is_dual_link_lvds(dev))
|
|
|
factor = 25;
|
|
|
} else if (is_sdvo && is_tv)
|
|
|
factor = 20;
|
|
@@ -5581,7 +5466,6 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
|
|
|
bool ok, has_reduced_clock = false;
|
|
|
bool is_lvds = false, is_dp = false, is_cpu_edp = false;
|
|
|
struct intel_encoder *encoder;
|
|
|
- u32 temp;
|
|
|
int ret;
|
|
|
bool dither, fdi_config_ok;
|
|
|
|
|
@@ -5645,54 +5529,12 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
|
|
|
} else
|
|
|
intel_put_pch_pll(intel_crtc);
|
|
|
|
|
|
- /* The LVDS pin pair needs to be on before the DPLLs are enabled.
|
|
|
- * This is an exception to the general rule that mode_set doesn't turn
|
|
|
- * things on.
|
|
|
- */
|
|
|
- if (is_lvds) {
|
|
|
- temp = I915_READ(PCH_LVDS);
|
|
|
- temp |= LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP;
|
|
|
- if (HAS_PCH_CPT(dev)) {
|
|
|
- temp &= ~PORT_TRANS_SEL_MASK;
|
|
|
- temp |= PORT_TRANS_SEL_CPT(pipe);
|
|
|
- } else {
|
|
|
- if (pipe == 1)
|
|
|
- temp |= LVDS_PIPEB_SELECT;
|
|
|
- else
|
|
|
- temp &= ~LVDS_PIPEB_SELECT;
|
|
|
- }
|
|
|
-
|
|
|
- /* set the corresponsding LVDS_BORDER bit */
|
|
|
- temp |= dev_priv->lvds_border_bits;
|
|
|
- /* Set the B0-B3 data pairs corresponding to whether we're going to
|
|
|
- * set the DPLLs for dual-channel mode or not.
|
|
|
- */
|
|
|
- if (clock.p2 == 7)
|
|
|
- temp |= LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP;
|
|
|
- else
|
|
|
- temp &= ~(LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP);
|
|
|
-
|
|
|
- /* It would be nice to set 24 vs 18-bit mode (LVDS_A3_POWER_UP)
|
|
|
- * appropriately here, but we need to look more thoroughly into how
|
|
|
- * panels behave in the two modes.
|
|
|
- */
|
|
|
- temp &= ~(LVDS_HSYNC_POLARITY | LVDS_VSYNC_POLARITY);
|
|
|
- if (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC)
|
|
|
- temp |= LVDS_HSYNC_POLARITY;
|
|
|
- if (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC)
|
|
|
- temp |= LVDS_VSYNC_POLARITY;
|
|
|
- I915_WRITE(PCH_LVDS, temp);
|
|
|
- }
|
|
|
-
|
|
|
- if (is_dp && !is_cpu_edp) {
|
|
|
+ if (is_dp && !is_cpu_edp)
|
|
|
intel_dp_set_m_n(crtc, mode, adjusted_mode);
|
|
|
- } else {
|
|
|
- /* For non-DP output, clear any trans DP clock recovery setting.*/
|
|
|
- I915_WRITE(TRANSDATA_M1(pipe), 0);
|
|
|
- I915_WRITE(TRANSDATA_N1(pipe), 0);
|
|
|
- I915_WRITE(TRANSDPLINK_M1(pipe), 0);
|
|
|
- I915_WRITE(TRANSDPLINK_N1(pipe), 0);
|
|
|
- }
|
|
|
+
|
|
|
+ for_each_encoder_on_crtc(dev, crtc, encoder)
|
|
|
+ if (encoder->pre_pll_enable)
|
|
|
+ encoder->pre_pll_enable(encoder);
|
|
|
|
|
|
if (intel_crtc->pch_pll) {
|
|
|
I915_WRITE(intel_crtc->pch_pll->pll_reg, dpll);
|
|
@@ -5727,9 +5569,6 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
|
|
|
|
|
|
fdi_config_ok = ironlake_check_fdi_lanes(intel_crtc);
|
|
|
|
|
|
- if (is_cpu_edp)
|
|
|
- ironlake_set_pll_edp(crtc, adjusted_mode->clock);
|
|
|
-
|
|
|
ironlake_set_pipeconf(crtc, adjusted_mode, dither);
|
|
|
|
|
|
intel_wait_for_vblank(dev, pipe);
|
|
@@ -5759,20 +5598,13 @@ static int haswell_crtc_mode_set(struct drm_crtc *crtc,
|
|
|
int pipe = intel_crtc->pipe;
|
|
|
int plane = intel_crtc->plane;
|
|
|
int num_connectors = 0;
|
|
|
- intel_clock_t clock, reduced_clock;
|
|
|
- u32 dpll = 0, fp = 0, fp2 = 0;
|
|
|
- bool ok, has_reduced_clock = false;
|
|
|
- bool is_lvds = false, is_dp = false, is_cpu_edp = false;
|
|
|
+ bool is_dp = false, is_cpu_edp = false;
|
|
|
struct intel_encoder *encoder;
|
|
|
- u32 temp;
|
|
|
int ret;
|
|
|
bool dither;
|
|
|
|
|
|
for_each_encoder_on_crtc(dev, crtc, encoder) {
|
|
|
switch (encoder->type) {
|
|
|
- case INTEL_OUTPUT_LVDS:
|
|
|
- is_lvds = true;
|
|
|
- break;
|
|
|
case INTEL_OUTPUT_DISPLAYPORT:
|
|
|
is_dp = true;
|
|
|
break;
|
|
@@ -5806,143 +5638,26 @@ static int haswell_crtc_mode_set(struct drm_crtc *crtc,
|
|
|
if (!intel_ddi_pll_mode_set(crtc, adjusted_mode->clock))
|
|
|
return -EINVAL;
|
|
|
|
|
|
- if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)) {
|
|
|
- ok = ironlake_compute_clocks(crtc, adjusted_mode, &clock,
|
|
|
- &has_reduced_clock,
|
|
|
- &reduced_clock);
|
|
|
- if (!ok) {
|
|
|
- DRM_ERROR("Couldn't find PLL settings for mode!\n");
|
|
|
- return -EINVAL;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
/* Ensure that the cursor is valid for the new mode before changing... */
|
|
|
intel_crtc_update_cursor(crtc, true);
|
|
|
|
|
|
/* determine panel color depth */
|
|
|
dither = intel_choose_pipe_bpp_dither(crtc, fb, &intel_crtc->bpp,
|
|
|
adjusted_mode);
|
|
|
- if (is_lvds && dev_priv->lvds_dither)
|
|
|
- dither = true;
|
|
|
|
|
|
DRM_DEBUG_KMS("Mode for pipe %d:\n", pipe);
|
|
|
drm_mode_debug_printmodeline(mode);
|
|
|
|
|
|
- if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)) {
|
|
|
- fp = clock.n << 16 | clock.m1 << 8 | clock.m2;
|
|
|
- if (has_reduced_clock)
|
|
|
- fp2 = reduced_clock.n << 16 | reduced_clock.m1 << 8 |
|
|
|
- reduced_clock.m2;
|
|
|
-
|
|
|
- dpll = ironlake_compute_dpll(intel_crtc, adjusted_mode, &clock,
|
|
|
- fp);
|
|
|
-
|
|
|
- /* CPU eDP is the only output that doesn't need a PCH PLL of its
|
|
|
- * own on pre-Haswell/LPT generation */
|
|
|
- if (!is_cpu_edp) {
|
|
|
- struct intel_pch_pll *pll;
|
|
|
-
|
|
|
- pll = intel_get_pch_pll(intel_crtc, dpll, fp);
|
|
|
- if (pll == NULL) {
|
|
|
- DRM_DEBUG_DRIVER("failed to find PLL for pipe %d\n",
|
|
|
- pipe);
|
|
|
- return -EINVAL;
|
|
|
- }
|
|
|
- } else
|
|
|
- intel_put_pch_pll(intel_crtc);
|
|
|
-
|
|
|
- /* The LVDS pin pair needs to be on before the DPLLs are
|
|
|
- * enabled. This is an exception to the general rule that
|
|
|
- * mode_set doesn't turn things on.
|
|
|
- */
|
|
|
- if (is_lvds) {
|
|
|
- temp = I915_READ(PCH_LVDS);
|
|
|
- temp |= LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP;
|
|
|
- if (HAS_PCH_CPT(dev)) {
|
|
|
- temp &= ~PORT_TRANS_SEL_MASK;
|
|
|
- temp |= PORT_TRANS_SEL_CPT(pipe);
|
|
|
- } else {
|
|
|
- if (pipe == 1)
|
|
|
- temp |= LVDS_PIPEB_SELECT;
|
|
|
- else
|
|
|
- temp &= ~LVDS_PIPEB_SELECT;
|
|
|
- }
|
|
|
-
|
|
|
- /* set the corresponsding LVDS_BORDER bit */
|
|
|
- temp |= dev_priv->lvds_border_bits;
|
|
|
- /* Set the B0-B3 data pairs corresponding to whether
|
|
|
- * we're going to set the DPLLs for dual-channel mode or
|
|
|
- * not.
|
|
|
- */
|
|
|
- if (clock.p2 == 7)
|
|
|
- temp |= LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP;
|
|
|
- else
|
|
|
- temp &= ~(LVDS_B0B3_POWER_UP |
|
|
|
- LVDS_CLKB_POWER_UP);
|
|
|
-
|
|
|
- /* It would be nice to set 24 vs 18-bit mode
|
|
|
- * (LVDS_A3_POWER_UP) appropriately here, but we need to
|
|
|
- * look more thoroughly into how panels behave in the
|
|
|
- * two modes.
|
|
|
- */
|
|
|
- temp &= ~(LVDS_HSYNC_POLARITY | LVDS_VSYNC_POLARITY);
|
|
|
- if (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC)
|
|
|
- temp |= LVDS_HSYNC_POLARITY;
|
|
|
- if (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC)
|
|
|
- temp |= LVDS_VSYNC_POLARITY;
|
|
|
- I915_WRITE(PCH_LVDS, temp);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if (is_dp && !is_cpu_edp) {
|
|
|
+ if (is_dp && !is_cpu_edp)
|
|
|
intel_dp_set_m_n(crtc, mode, adjusted_mode);
|
|
|
- } else {
|
|
|
- if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)) {
|
|
|
- /* For non-DP output, clear any trans DP clock recovery
|
|
|
- * setting.*/
|
|
|
- I915_WRITE(TRANSDATA_M1(pipe), 0);
|
|
|
- I915_WRITE(TRANSDATA_N1(pipe), 0);
|
|
|
- I915_WRITE(TRANSDPLINK_M1(pipe), 0);
|
|
|
- I915_WRITE(TRANSDPLINK_N1(pipe), 0);
|
|
|
- }
|
|
|
- }
|
|
|
|
|
|
intel_crtc->lowfreq_avail = false;
|
|
|
- if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)) {
|
|
|
- if (intel_crtc->pch_pll) {
|
|
|
- I915_WRITE(intel_crtc->pch_pll->pll_reg, dpll);
|
|
|
-
|
|
|
- /* Wait for the clocks to stabilize. */
|
|
|
- POSTING_READ(intel_crtc->pch_pll->pll_reg);
|
|
|
- udelay(150);
|
|
|
-
|
|
|
- /* The pixel multiplier can only be updated once the
|
|
|
- * DPLL is enabled and the clocks are stable.
|
|
|
- *
|
|
|
- * So write it again.
|
|
|
- */
|
|
|
- I915_WRITE(intel_crtc->pch_pll->pll_reg, dpll);
|
|
|
- }
|
|
|
-
|
|
|
- if (intel_crtc->pch_pll) {
|
|
|
- if (is_lvds && has_reduced_clock && i915_powersave) {
|
|
|
- I915_WRITE(intel_crtc->pch_pll->fp1_reg, fp2);
|
|
|
- intel_crtc->lowfreq_avail = true;
|
|
|
- } else {
|
|
|
- I915_WRITE(intel_crtc->pch_pll->fp1_reg, fp);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
|
|
|
intel_set_pipe_timings(intel_crtc, mode, adjusted_mode);
|
|
|
|
|
|
if (!is_dp || is_cpu_edp)
|
|
|
ironlake_set_m_n(crtc, mode, adjusted_mode);
|
|
|
|
|
|
- if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev))
|
|
|
- if (is_cpu_edp)
|
|
|
- ironlake_set_pll_edp(crtc, adjusted_mode->clock);
|
|
|
-
|
|
|
haswell_set_pipeconf(crtc, adjusted_mode, dither);
|
|
|
|
|
|
/* Set up the display plane register */
|
|
@@ -6759,7 +6474,7 @@ bool intel_get_load_detect_pipe(struct drm_connector *connector,
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
- if (!intel_set_mode(crtc, mode, 0, 0, fb)) {
|
|
|
+ if (intel_set_mode(crtc, mode, 0, 0, fb)) {
|
|
|
DRM_DEBUG_KMS("failed to set mode on load-detect pipe\n");
|
|
|
if (old->release_fb)
|
|
|
old->release_fb->funcs->destroy(old->release_fb);
|
|
@@ -7109,8 +6824,6 @@ static void do_intel_finish_page_flip(struct drm_device *dev,
|
|
|
|
|
|
obj = work->old_fb_obj;
|
|
|
|
|
|
- atomic_clear_mask(1 << intel_crtc->plane,
|
|
|
- &obj->pending_flip.counter);
|
|
|
wake_up(&dev_priv->pending_flip_queue);
|
|
|
|
|
|
queue_work(dev_priv->wq, &work->work);
|
|
@@ -7474,10 +7187,6 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
|
|
|
|
|
|
work->enable_stall_check = true;
|
|
|
|
|
|
- /* Block clients from rendering to the new back buffer until
|
|
|
- * the flip occurs and the object is no longer visible.
|
|
|
- */
|
|
|
- atomic_add(1 << intel_crtc->plane, &work->old_fb_obj->pending_flip);
|
|
|
atomic_inc(&intel_crtc->unpin_work_count);
|
|
|
|
|
|
ret = dev_priv->display.queue_flip(dev, crtc, fb, obj);
|
|
@@ -7494,7 +7203,6 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
|
|
|
|
|
|
cleanup_pending:
|
|
|
atomic_dec(&intel_crtc->unpin_work_count);
|
|
|
- atomic_sub(1 << intel_crtc->plane, &work->old_fb_obj->pending_flip);
|
|
|
drm_gem_object_unreference(&work->old_fb_obj->base);
|
|
|
drm_gem_object_unreference(&obj->base);
|
|
|
mutex_unlock(&dev->struct_mutex);
|
|
@@ -7904,16 +7612,21 @@ intel_modeset_check_state(struct drm_device *dev)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-bool intel_set_mode(struct drm_crtc *crtc,
|
|
|
- struct drm_display_mode *mode,
|
|
|
- int x, int y, struct drm_framebuffer *fb)
|
|
|
+int intel_set_mode(struct drm_crtc *crtc,
|
|
|
+ struct drm_display_mode *mode,
|
|
|
+ int x, int y, struct drm_framebuffer *fb)
|
|
|
{
|
|
|
struct drm_device *dev = crtc->dev;
|
|
|
drm_i915_private_t *dev_priv = dev->dev_private;
|
|
|
- struct drm_display_mode *adjusted_mode, saved_mode, saved_hwmode;
|
|
|
+ struct drm_display_mode *adjusted_mode, *saved_mode, *saved_hwmode;
|
|
|
struct intel_crtc *intel_crtc;
|
|
|
unsigned disable_pipes, prepare_pipes, modeset_pipes;
|
|
|
- bool ret = true;
|
|
|
+ int ret = 0;
|
|
|
+
|
|
|
+ saved_mode = kmalloc(2 * sizeof(*saved_mode), GFP_KERNEL);
|
|
|
+ if (!saved_mode)
|
|
|
+ return -ENOMEM;
|
|
|
+ saved_hwmode = saved_mode + 1;
|
|
|
|
|
|
intel_modeset_affected_pipes(crtc, &modeset_pipes,
|
|
|
&prepare_pipes, &disable_pipes);
|
|
@@ -7924,8 +7637,8 @@ bool intel_set_mode(struct drm_crtc *crtc,
|
|
|
for_each_intel_crtc_masked(dev, disable_pipes, intel_crtc)
|
|
|
intel_crtc_disable(&intel_crtc->base);
|
|
|
|
|
|
- saved_hwmode = crtc->hwmode;
|
|
|
- saved_mode = crtc->mode;
|
|
|
+ *saved_hwmode = crtc->hwmode;
|
|
|
+ *saved_mode = crtc->mode;
|
|
|
|
|
|
/* Hack: Because we don't (yet) support global modeset on multiple
|
|
|
* crtcs, we don't keep track of the new mode for more than one crtc.
|
|
@@ -7936,7 +7649,8 @@ bool intel_set_mode(struct drm_crtc *crtc,
|
|
|
if (modeset_pipes) {
|
|
|
adjusted_mode = intel_modeset_adjusted_mode(crtc, mode);
|
|
|
if (IS_ERR(adjusted_mode)) {
|
|
|
- return false;
|
|
|
+ ret = PTR_ERR(adjusted_mode);
|
|
|
+ goto out;
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -7962,11 +7676,11 @@ bool intel_set_mode(struct drm_crtc *crtc,
|
|
|
* on the DPLL.
|
|
|
*/
|
|
|
for_each_intel_crtc_masked(dev, modeset_pipes, intel_crtc) {
|
|
|
- ret = !intel_crtc_mode_set(&intel_crtc->base,
|
|
|
- mode, adjusted_mode,
|
|
|
- x, y, fb);
|
|
|
- if (!ret)
|
|
|
- goto done;
|
|
|
+ ret = intel_crtc_mode_set(&intel_crtc->base,
|
|
|
+ mode, adjusted_mode,
|
|
|
+ x, y, fb);
|
|
|
+ if (ret)
|
|
|
+ goto done;
|
|
|
}
|
|
|
|
|
|
/* Now enable the clocks, plane, pipe, and connectors that we set up. */
|
|
@@ -7987,16 +7701,23 @@ bool intel_set_mode(struct drm_crtc *crtc,
|
|
|
/* FIXME: add subpixel order */
|
|
|
done:
|
|
|
drm_mode_destroy(dev, adjusted_mode);
|
|
|
- if (!ret && crtc->enabled) {
|
|
|
- crtc->hwmode = saved_hwmode;
|
|
|
- crtc->mode = saved_mode;
|
|
|
+ if (ret && crtc->enabled) {
|
|
|
+ crtc->hwmode = *saved_hwmode;
|
|
|
+ crtc->mode = *saved_mode;
|
|
|
} else {
|
|
|
intel_modeset_check_state(dev);
|
|
|
}
|
|
|
|
|
|
+out:
|
|
|
+ kfree(saved_mode);
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
+void intel_crtc_restore_mode(struct drm_crtc *crtc)
|
|
|
+{
|
|
|
+ intel_set_mode(crtc, &crtc->mode, crtc->x, crtc->y, crtc->fb);
|
|
|
+}
|
|
|
+
|
|
|
#undef for_each_intel_crtc_masked
|
|
|
|
|
|
static void intel_set_config_free(struct intel_set_config *config)
|
|
@@ -8262,11 +7983,11 @@ static int intel_crtc_set_config(struct drm_mode_set *set)
|
|
|
drm_mode_debug_printmodeline(set->mode);
|
|
|
}
|
|
|
|
|
|
- if (!intel_set_mode(set->crtc, set->mode,
|
|
|
- set->x, set->y, set->fb)) {
|
|
|
- DRM_ERROR("failed to set mode on [CRTC:%d]\n",
|
|
|
- set->crtc->base.id);
|
|
|
- ret = -EINVAL;
|
|
|
+ ret = intel_set_mode(set->crtc, set->mode,
|
|
|
+ set->x, set->y, set->fb);
|
|
|
+ if (ret) {
|
|
|
+ DRM_ERROR("failed to set mode on [CRTC:%d], err = %d\n",
|
|
|
+ set->crtc->base.id, ret);
|
|
|
goto fail;
|
|
|
}
|
|
|
} else if (config->fb_changed) {
|
|
@@ -8283,8 +8004,8 @@ fail:
|
|
|
|
|
|
/* Try to restore the config */
|
|
|
if (config->mode_changed &&
|
|
|
- !intel_set_mode(save_set.crtc, save_set.mode,
|
|
|
- save_set.x, save_set.y, save_set.fb))
|
|
|
+ intel_set_mode(save_set.crtc, save_set.mode,
|
|
|
+ save_set.x, save_set.y, save_set.fb))
|
|
|
DRM_ERROR("failed to restore config after modeset failure\n");
|
|
|
|
|
|
out_config:
|
|
@@ -8303,7 +8024,7 @@ static const struct drm_crtc_funcs intel_crtc_funcs = {
|
|
|
|
|
|
static void intel_cpu_pll_init(struct drm_device *dev)
|
|
|
{
|
|
|
- if (IS_HASWELL(dev))
|
|
|
+ if (HAS_DDI(dev))
|
|
|
intel_ddi_pll_init(dev);
|
|
|
}
|
|
|
|
|
@@ -8439,11 +8160,10 @@ static void intel_setup_outputs(struct drm_device *dev)
|
|
|
I915_WRITE(PFIT_CONTROL, 0);
|
|
|
}
|
|
|
|
|
|
- if (!(IS_HASWELL(dev) &&
|
|
|
- (I915_READ(DDI_BUF_CTL(PORT_A)) & DDI_A_4_LANES)))
|
|
|
+ if (!(HAS_DDI(dev) && (I915_READ(DDI_BUF_CTL(PORT_A)) & DDI_A_4_LANES)))
|
|
|
intel_crt_init(dev);
|
|
|
|
|
|
- if (IS_HASWELL(dev)) {
|
|
|
+ if (HAS_DDI(dev)) {
|
|
|
int found;
|
|
|
|
|
|
/* Haswell uses DDI functions to detect digital outputs */
|
|
@@ -8686,7 +8406,7 @@ static void intel_init_display(struct drm_device *dev)
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
|
|
/* We always want a DPMS function */
|
|
|
- if (IS_HASWELL(dev)) {
|
|
|
+ if (HAS_DDI(dev)) {
|
|
|
dev_priv->display.crtc_mode_set = haswell_crtc_mode_set;
|
|
|
dev_priv->display.crtc_enable = haswell_crtc_enable;
|
|
|
dev_priv->display.crtc_disable = haswell_crtc_disable;
|
|
@@ -8748,8 +8468,7 @@ static void intel_init_display(struct drm_device *dev)
|
|
|
} else if (IS_HASWELL(dev)) {
|
|
|
dev_priv->display.fdi_link_train = hsw_fdi_link_train;
|
|
|
dev_priv->display.write_eld = haswell_write_eld;
|
|
|
- } else
|
|
|
- dev_priv->display.update_wm = NULL;
|
|
|
+ }
|
|
|
} else if (IS_G4X(dev)) {
|
|
|
dev_priv->display.write_eld = g4x_write_eld;
|
|
|
}
|
|
@@ -8982,6 +8701,9 @@ void intel_modeset_init(struct drm_device *dev)
|
|
|
/* Just disable it once at startup */
|
|
|
i915_disable_vga(dev);
|
|
|
intel_setup_outputs(dev);
|
|
|
+
|
|
|
+ /* Just in case the BIOS is doing something questionable. */
|
|
|
+ intel_disable_fbc(dev);
|
|
|
}
|
|
|
|
|
|
static void
|
|
@@ -9192,7 +8914,7 @@ void intel_modeset_setup_hw_state(struct drm_device *dev,
|
|
|
struct intel_encoder *encoder;
|
|
|
struct intel_connector *connector;
|
|
|
|
|
|
- if (IS_HASWELL(dev)) {
|
|
|
+ if (HAS_DDI(dev)) {
|
|
|
tmp = I915_READ(TRANS_DDI_FUNC_CTL(TRANSCODER_EDP));
|
|
|
|
|
|
if (tmp & TRANS_DDI_FUNC_ENABLE) {
|
|
@@ -9233,7 +8955,7 @@ void intel_modeset_setup_hw_state(struct drm_device *dev,
|
|
|
crtc->active ? "enabled" : "disabled");
|
|
|
}
|
|
|
|
|
|
- if (IS_HASWELL(dev))
|
|
|
+ if (HAS_DDI(dev))
|
|
|
intel_ddi_setup_hw_pll_state(dev);
|
|
|
|
|
|
list_for_each_entry(encoder, &dev->mode_config.encoder_list,
|
|
@@ -9284,9 +9006,7 @@ void intel_modeset_setup_hw_state(struct drm_device *dev,
|
|
|
|
|
|
if (force_restore) {
|
|
|
for_each_pipe(pipe) {
|
|
|
- crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]);
|
|
|
- intel_set_mode(&crtc->base, &crtc->base.mode,
|
|
|
- crtc->base.x, crtc->base.y, crtc->base.fb);
|
|
|
+ intel_crtc_restore_mode(dev_priv->pipe_to_crtc_mapping[pipe]);
|
|
|
}
|
|
|
|
|
|
i915_redisable_vga(dev);
|
|
@@ -9350,6 +9070,8 @@ void intel_modeset_cleanup(struct drm_device *dev)
|
|
|
flush_scheduled_work();
|
|
|
|
|
|
drm_mode_config_cleanup(dev);
|
|
|
+
|
|
|
+ intel_cleanup_overlay(dev);
|
|
|
}
|
|
|
|
|
|
/*
|