44,13 → 44,23 |
#define MAX_ERRNO 4095 |
phys_addr_t get_bus_addr(void); |
|
bool intel_pipe_has_type(struct drm_crtc *crtc, int type); |
static inline void outb(u8 v, u16 port) |
{ |
asm volatile("outb %0,%1" : : "a" (v), "dN" (port)); |
} |
static inline u8 inb(u16 port) |
{ |
u8 v; |
asm volatile("inb %1,%0" : "=a" (v) : "dN" (port)); |
return v; |
} |
|
static void intel_increase_pllclock(struct drm_crtc *crtc); |
static void intel_crtc_update_cursor(struct drm_crtc *crtc, bool on); |
|
static void i9xx_crtc_clock_get(struct intel_crtc *crtc, |
struct intel_crtc_config *pipe_config); |
static void ironlake_crtc_clock_get(struct intel_crtc *crtc, |
static void ironlake_pch_clock_get(struct intel_crtc *crtc, |
struct intel_crtc_config *pipe_config); |
|
static int intel_set_mode(struct drm_crtc *crtc, struct drm_display_mode *mode, |
72,9 → 82,6 |
intel_p2_t p2; |
}; |
|
/* FDI */ |
#define IRONLAKE_FDI_FREQ 2700000 /* in kHz for mode->clock */ |
|
int |
intel_pch_rawclk(struct drm_device *dev) |
{ |
97,8 → 104,8 |
|
static const intel_limit_t intel_limits_i8xx_dac = { |
.dot = { .min = 25000, .max = 350000 }, |
.vco = { .min = 930000, .max = 1400000 }, |
.n = { .min = 3, .max = 16 }, |
.vco = { .min = 908000, .max = 1512000 }, |
.n = { .min = 2, .max = 16 }, |
.m = { .min = 96, .max = 140 }, |
.m1 = { .min = 18, .max = 26 }, |
.m2 = { .min = 6, .max = 16 }, |
110,8 → 117,8 |
|
static const intel_limit_t intel_limits_i8xx_dvo = { |
.dot = { .min = 25000, .max = 350000 }, |
.vco = { .min = 930000, .max = 1400000 }, |
.n = { .min = 3, .max = 16 }, |
.vco = { .min = 908000, .max = 1512000 }, |
.n = { .min = 2, .max = 16 }, |
.m = { .min = 96, .max = 140 }, |
.m1 = { .min = 18, .max = 26 }, |
.m2 = { .min = 6, .max = 16 }, |
123,8 → 130,8 |
|
static const intel_limit_t intel_limits_i8xx_lvds = { |
.dot = { .min = 25000, .max = 350000 }, |
.vco = { .min = 930000, .max = 1400000 }, |
.n = { .min = 3, .max = 16 }, |
.vco = { .min = 908000, .max = 1512000 }, |
.n = { .min = 2, .max = 16 }, |
.m = { .min = 96, .max = 140 }, |
.m1 = { .min = 18, .max = 26 }, |
.m2 = { .min = 6, .max = 16 }, |
316,45 → 323,47 |
.p2_slow = 7, .p2_fast = 7 }, |
}; |
|
static const intel_limit_t intel_limits_vlv_dac = { |
.dot = { .min = 25000, .max = 270000 }, |
static const intel_limit_t intel_limits_vlv = { |
/* |
* These are the data rate limits (measured in fast clocks) |
* since those are the strictest limits we have. The fast |
* clock and actual rate limits are more relaxed, so checking |
* them would make no difference. |
*/ |
.dot = { .min = 25000 * 5, .max = 270000 * 5 }, |
.vco = { .min = 4000000, .max = 6000000 }, |
.n = { .min = 1, .max = 7 }, |
.m = { .min = 22, .max = 450 }, /* guess */ |
.m1 = { .min = 2, .max = 3 }, |
.m2 = { .min = 11, .max = 156 }, |
.p = { .min = 10, .max = 30 }, |
.p1 = { .min = 1, .max = 3 }, |
.p2 = { .dot_limit = 270000, |
.p2_slow = 2, .p2_fast = 20 }, |
}; |
|
static const intel_limit_t intel_limits_vlv_hdmi = { |
.dot = { .min = 25000, .max = 270000 }, |
.vco = { .min = 4000000, .max = 6000000 }, |
.n = { .min = 1, .max = 7 }, |
.m = { .min = 60, .max = 300 }, /* guess */ |
.m1 = { .min = 2, .max = 3 }, |
.m2 = { .min = 11, .max = 156 }, |
.p = { .min = 10, .max = 30 }, |
.p1 = { .min = 2, .max = 3 }, |
.p2 = { .dot_limit = 270000, |
.p2_slow = 2, .p2_fast = 20 }, |
.p2 = { .p2_slow = 2, .p2_fast = 20 }, /* slow=min, fast=max */ |
}; |
|
static const intel_limit_t intel_limits_vlv_dp = { |
.dot = { .min = 25000, .max = 270000 }, |
.vco = { .min = 4000000, .max = 6000000 }, |
.n = { .min = 1, .max = 7 }, |
.m = { .min = 22, .max = 450 }, |
.m1 = { .min = 2, .max = 3 }, |
.m2 = { .min = 11, .max = 156 }, |
.p = { .min = 10, .max = 30 }, |
.p1 = { .min = 1, .max = 3 }, |
.p2 = { .dot_limit = 270000, |
.p2_slow = 2, .p2_fast = 20 }, |
}; |
static void vlv_clock(int refclk, intel_clock_t *clock) |
{ |
clock->m = clock->m1 * clock->m2; |
clock->p = clock->p1 * clock->p2; |
if (WARN_ON(clock->n == 0 || clock->p == 0)) |
return; |
clock->vco = DIV_ROUND_CLOSEST(refclk * clock->m, clock->n); |
clock->dot = DIV_ROUND_CLOSEST(clock->vco, clock->p); |
} |
|
/** |
* Returns whether any output on the specified pipe is of the specified type |
*/ |
static bool intel_pipe_has_type(struct drm_crtc *crtc, int type) |
{ |
struct drm_device *dev = crtc->dev; |
struct intel_encoder *encoder; |
|
for_each_encoder_on_crtc(dev, crtc, encoder) |
if (encoder->type == type) |
return true; |
|
return false; |
} |
|
static const intel_limit_t *intel_ironlake_limit(struct drm_crtc *crtc, |
int refclk) |
{ |
415,12 → 424,7 |
else |
limit = &intel_limits_pineview_sdvo; |
} else if (IS_VALLEYVIEW(dev)) { |
if (intel_pipe_has_type(crtc, INTEL_OUTPUT_ANALOG)) |
limit = &intel_limits_vlv_dac; |
else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_HDMI)) |
limit = &intel_limits_vlv_hdmi; |
else |
limit = &intel_limits_vlv_dp; |
limit = &intel_limits_vlv; |
} else if (!IS_GEN2(dev)) { |
if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) |
limit = &intel_limits_i9xx_lvds; |
442,8 → 446,10 |
{ |
clock->m = clock->m2 + 2; |
clock->p = clock->p1 * clock->p2; |
clock->vco = refclk * clock->m / clock->n; |
clock->dot = clock->vco / clock->p; |
if (WARN_ON(clock->n == 0 || clock->p == 0)) |
return; |
clock->vco = DIV_ROUND_CLOSEST(refclk * clock->m, clock->n); |
clock->dot = DIV_ROUND_CLOSEST(clock->vco, clock->p); |
} |
|
static uint32_t i9xx_dpll_compute_m(struct dpll *dpll) |
455,25 → 461,12 |
{ |
clock->m = i9xx_dpll_compute_m(clock); |
clock->p = clock->p1 * clock->p2; |
clock->vco = refclk * clock->m / (clock->n + 2); |
clock->dot = clock->vco / clock->p; |
if (WARN_ON(clock->n + 2 == 0 || clock->p == 0)) |
return; |
clock->vco = DIV_ROUND_CLOSEST(refclk * clock->m, clock->n + 2); |
clock->dot = DIV_ROUND_CLOSEST(clock->vco, clock->p); |
} |
|
/** |
* Returns whether any output on the specified pipe is of the specified type |
*/ |
bool intel_pipe_has_type(struct drm_crtc *crtc, int type) |
{ |
struct drm_device *dev = crtc->dev; |
struct intel_encoder *encoder; |
|
for_each_encoder_on_crtc(dev, crtc, encoder) |
if (encoder->type == type) |
return true; |
|
return false; |
} |
|
#define INTELPllInvalid(s) do { /* DRM_DEBUG(s); */ return false; } while (0) |
/** |
* Returns whether the given set of divisors are valid for a given refclk with |
484,20 → 477,26 |
const intel_limit_t *limit, |
const intel_clock_t *clock) |
{ |
if (clock->n < limit->n.min || limit->n.max < clock->n) |
INTELPllInvalid("n out of range\n"); |
if (clock->p1 < limit->p1.min || limit->p1.max < clock->p1) |
INTELPllInvalid("p1 out of range\n"); |
if (clock->p < limit->p.min || limit->p.max < clock->p) |
INTELPllInvalid("p out of range\n"); |
if (clock->m2 < limit->m2.min || limit->m2.max < clock->m2) |
INTELPllInvalid("m2 out of range\n"); |
if (clock->m1 < limit->m1.min || limit->m1.max < clock->m1) |
INTELPllInvalid("m1 out of range\n"); |
if (clock->m1 <= clock->m2 && !IS_PINEVIEW(dev)) |
|
if (!IS_PINEVIEW(dev) && !IS_VALLEYVIEW(dev)) |
if (clock->m1 <= clock->m2) |
INTELPllInvalid("m1 <= m2\n"); |
|
if (!IS_VALLEYVIEW(dev)) { |
if (clock->p < limit->p.min || limit->p.max < clock->p) |
INTELPllInvalid("p out of range\n"); |
if (clock->m < limit->m.min || limit->m.max < clock->m) |
INTELPllInvalid("m out of range\n"); |
if (clock->n < limit->n.min || limit->n.max < clock->n) |
INTELPllInvalid("n out of range\n"); |
} |
|
if (clock->vco < limit->vco.min || limit->vco.max < clock->vco) |
INTELPllInvalid("vco out of range\n"); |
/* XXX: We may need to be checking "Dot clock" depending on the multiplier, |
691,67 → 690,73 |
int target, int refclk, intel_clock_t *match_clock, |
intel_clock_t *best_clock) |
{ |
u32 p1, p2, m1, m2, vco, bestn, bestm1, bestm2, bestp1, bestp2; |
u32 m, n, fastclk; |
u32 updrate, minupdate, p; |
unsigned long bestppm, ppm, absppm; |
int dotclk, flag; |
struct drm_device *dev = crtc->dev; |
intel_clock_t clock; |
unsigned int bestppm = 1000000; |
/* min update 19.2 MHz */ |
int max_n = min(limit->n.max, refclk / 19200); |
bool found = false; |
|
flag = 0; |
dotclk = target * 1000; |
bestppm = 1000000; |
ppm = absppm = 0; |
fastclk = dotclk / (2*100); |
updrate = 0; |
minupdate = 19200; |
n = p = p1 = p2 = m = m1 = m2 = vco = bestn = 0; |
bestm1 = bestm2 = bestp1 = bestp2 = 0; |
target *= 5; /* fast clock */ |
|
memset(best_clock, 0, sizeof(*best_clock)); |
|
/* based on hardware requirement, prefer smaller n to precision */ |
for (n = limit->n.min; n <= ((refclk) / minupdate); n++) { |
updrate = refclk / n; |
for (p1 = limit->p1.max; p1 > limit->p1.min; p1--) { |
for (p2 = limit->p2.p2_fast+1; p2 > 0; p2--) { |
if (p2 > 10) |
p2 = p2 - 1; |
p = p1 * p2; |
for (clock.n = limit->n.min; clock.n <= max_n; clock.n++) { |
for (clock.p1 = limit->p1.max; clock.p1 >= limit->p1.min; clock.p1--) { |
for (clock.p2 = limit->p2.p2_fast; clock.p2 >= limit->p2.p2_slow; |
clock.p2 -= clock.p2 > 10 ? 2 : 1) { |
clock.p = clock.p1 * clock.p2; |
/* based on hardware requirement, prefer bigger m1,m2 values */ |
for (m1 = limit->m1.min; m1 <= limit->m1.max; m1++) { |
m2 = (((2*(fastclk * p * n / m1 )) + |
refclk) / (2*refclk)); |
m = m1 * m2; |
vco = updrate * m; |
if (vco >= limit->vco.min && vco < limit->vco.max) { |
ppm = 1000000 * ((vco / p) - fastclk) / fastclk; |
absppm = (ppm > 0) ? ppm : (-ppm); |
if (absppm < 100 && ((p1 * p2) > (bestp1 * bestp2))) { |
for (clock.m1 = limit->m1.min; clock.m1 <= limit->m1.max; clock.m1++) { |
unsigned int ppm, diff; |
|
clock.m2 = DIV_ROUND_CLOSEST(target * clock.p * clock.n, |
refclk * clock.m1); |
|
vlv_clock(refclk, &clock); |
|
if (!intel_PLL_is_valid(dev, limit, |
&clock)) |
continue; |
|
diff = abs(clock.dot - target); |
ppm = div_u64(1000000ULL * diff, target); |
|
if (ppm < 100 && clock.p > best_clock->p) { |
bestppm = 0; |
flag = 1; |
*best_clock = clock; |
found = true; |
} |
if (absppm < bestppm - 10) { |
bestppm = absppm; |
flag = 1; |
|
if (bestppm >= 10 && ppm < bestppm - 10) { |
bestppm = ppm; |
*best_clock = clock; |
found = true; |
} |
if (flag) { |
bestn = n; |
bestm1 = m1; |
bestm2 = m2; |
bestp1 = p1; |
bestp2 = p2; |
flag = 0; |
} |
} |
} |
} |
|
return found; |
} |
} |
best_clock->n = bestn; |
best_clock->m1 = bestm1; |
best_clock->m2 = bestm2; |
best_clock->p1 = bestp1; |
best_clock->p2 = bestp2; |
|
return true; |
bool intel_crtc_active(struct drm_crtc *crtc) |
{ |
struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
|
/* Be paranoid as we can arrive here with only partial |
* state retrieved from the hardware during setup. |
* |
* We can ditch the adjusted_mode.crtc_clock check as soon |
* as Haswell has gained clock readout/fastboot support. |
* |
* We can ditch the crtc->fb check as soon as we can |
* properly reconstruct framebuffers. |
*/ |
return intel_crtc->active && crtc->fb && |
intel_crtc->config.adjusted_mode.crtc_clock; |
} |
|
enum transcoder intel_pipe_to_cpu_transcoder(struct drm_i915_private *dev_priv, |
763,10 → 768,10 |
return intel_crtc->config.cpu_transcoder; |
} |
|
static void ironlake_wait_for_vblank(struct drm_device *dev, int pipe) |
static void g4x_wait_for_vblank(struct drm_device *dev, int pipe) |
{ |
struct drm_i915_private *dev_priv = dev->dev_private; |
u32 frame, frame_reg = PIPEFRAME(pipe); |
u32 frame, frame_reg = PIPE_FRMCOUNT_GM45(pipe); |
|
frame = I915_READ(frame_reg); |
|
787,8 → 792,8 |
struct drm_i915_private *dev_priv = dev->dev_private; |
int pipestat_reg = PIPESTAT(pipe); |
|
if (INTEL_INFO(dev)->gen >= 5) { |
ironlake_wait_for_vblank(dev, pipe); |
if (IS_G4X(dev) || INTEL_INFO(dev)->gen >= 5) { |
g4x_wait_for_vblank(dev, pipe); |
return; |
} |
|
815,6 → 820,25 |
DRM_DEBUG_KMS("vblank wait timed out\n"); |
} |
|
static bool pipe_dsl_stopped(struct drm_device *dev, enum pipe pipe) |
{ |
struct drm_i915_private *dev_priv = dev->dev_private; |
u32 reg = PIPEDSL(pipe); |
u32 line1, line2; |
u32 line_mask; |
|
if (IS_GEN2(dev)) |
line_mask = DSL_LINEMASK_GEN2; |
else |
line_mask = DSL_LINEMASK_GEN3; |
|
line1 = I915_READ(reg) & line_mask; |
mdelay(5); |
line2 = I915_READ(reg) & line_mask; |
|
return line1 == line2; |
} |
|
/* |
* intel_wait_for_pipe_off - wait for pipe to turn off |
* @dev: drm device |
846,22 → 870,8 |
100)) |
WARN(1, "pipe_off wait timed out\n"); |
} else { |
u32 last_line, line_mask; |
int reg = PIPEDSL(pipe); |
unsigned long timeout = GetTimerTicks() + msecs_to_jiffies(100); |
|
if (IS_GEN2(dev)) |
line_mask = DSL_LINEMASK_GEN2; |
else |
line_mask = DSL_LINEMASK_GEN3; |
|
/* Wait for the display line to settle */ |
do { |
last_line = I915_READ(reg) & line_mask; |
mdelay(5); |
} while (((I915_READ(reg) & line_mask) != last_line) && |
time_after(timeout, GetTimerTicks())); |
if (time_after(GetTimerTicks(), timeout)) |
if (wait_for(pipe_dsl_stopped(dev, pipe), 100)) |
WARN(1, "pipe_off wait timed out\n"); |
} |
} |
932,6 → 942,24 |
state_string(state), state_string(cur_state)); |
} |
|
/* XXX: the dsi pll is shared between MIPI DSI ports */ |
static void assert_dsi_pll(struct drm_i915_private *dev_priv, bool state) |
{ |
u32 val; |
bool cur_state; |
|
mutex_lock(&dev_priv->dpio_lock); |
val = vlv_cck_read(dev_priv, CCK_REG_DSI_PLL_CONTROL); |
mutex_unlock(&dev_priv->dpio_lock); |
|
cur_state = val & DSI_PLL_VCO_EN; |
WARN(cur_state != state, |
"DSI PLL state assertion failure (expected %s, current %s)\n", |
state_string(state), state_string(cur_state)); |
} |
#define assert_dsi_pll_enabled(d) assert_dsi_pll(d, true) |
#define assert_dsi_pll_disabled(d) assert_dsi_pll(d, false) |
|
struct intel_shared_dpll * |
intel_crtc_to_shared_dpll(struct intel_crtc *crtc) |
{ |
1072,6 → 1100,26 |
pipe_name(pipe)); |
} |
|
static void assert_cursor(struct drm_i915_private *dev_priv, |
enum pipe pipe, bool state) |
{ |
struct drm_device *dev = dev_priv->dev; |
bool cur_state; |
|
if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev)) |
cur_state = I915_READ(CURCNTR_IVB(pipe)) & CURSOR_MODE; |
else if (IS_845G(dev) || IS_I865G(dev)) |
cur_state = I915_READ(_CURACNTR) & CURSOR_ENABLE; |
else |
cur_state = I915_READ(CURCNTR(pipe)) & CURSOR_MODE; |
|
WARN(cur_state != state, |
"cursor on pipe %c assertion failure (expected %s, current %s)\n", |
pipe_name(pipe), state_string(state), state_string(cur_state)); |
} |
#define assert_cursor_enabled(d, p) assert_cursor(d, p, true) |
#define assert_cursor_disabled(d, p) assert_cursor(d, p, false) |
|
void assert_pipe(struct drm_i915_private *dev_priv, |
enum pipe pipe, bool state) |
{ |
1177,15 → 1225,12 |
} |
} |
|
static void assert_pch_refclk_enabled(struct drm_i915_private *dev_priv) |
static void ibx_assert_pch_refclk_enabled(struct drm_i915_private *dev_priv) |
{ |
u32 val; |
bool enabled; |
|
if (HAS_PCH_LPT(dev_priv->dev)) { |
DRM_DEBUG_DRIVER("LPT does not has PCH refclk, skipping check\n"); |
return; |
} |
WARN_ON(!(HAS_PCH_IBX(dev_priv->dev) || HAS_PCH_CPT(dev_priv->dev))); |
|
val = I915_READ(PCH_DREF_CONTROL); |
enabled = !!(val & (DREF_SSC_SOURCE_MASK | DREF_NONSPREAD_SOURCE_MASK | |
1326,6 → 1371,44 |
assert_pch_hdmi_disabled(dev_priv, pipe, PCH_HDMID); |
} |
|
static void intel_init_dpio(struct drm_device *dev) |
{ |
struct drm_i915_private *dev_priv = dev->dev_private; |
|
if (!IS_VALLEYVIEW(dev)) |
return; |
|
DPIO_PHY_IOSF_PORT(DPIO_PHY0) = IOSF_PORT_DPIO; |
} |
|
static void intel_reset_dpio(struct drm_device *dev) |
{ |
struct drm_i915_private *dev_priv = dev->dev_private; |
|
if (!IS_VALLEYVIEW(dev)) |
return; |
|
/* |
* Enable the CRI clock source so we can get at the display and the |
* reference clock for VGA hotplug / manual detection. |
*/ |
I915_WRITE(DPLL(PIPE_B), I915_READ(DPLL(PIPE_B)) | |
DPLL_REFA_CLK_ENABLE_VLV | |
DPLL_INTEGRATED_CRI_CLK_VLV); |
|
/* |
* From VLV2A0_DP_eDP_DPIO_driver_vbios_notes_10.docx - |
* 6. De-assert cmn_reset/side_reset. Same as VLV X0. |
* a. GUnit 0x2110 bit[0] set to 1 (def 0) |
* b. The other bits such as sfr settings / modesel may all be set |
* to 0. |
* |
* This should only be done on init and resume from S3 with both |
* PLLs disabled, or we risk losing DPIO and PLL synchronization. |
*/ |
I915_WRITE(DPIO_CTL, I915_READ(DPIO_CTL) | DPIO_CMNRST); |
} |
|
static void vlv_enable_pll(struct intel_crtc *crtc) |
{ |
struct drm_device *dev = crtc->base.dev; |
1439,25 → 1522,35 |
/* Make sure the pipe isn't still relying on us */ |
assert_pipe_disabled(dev_priv, pipe); |
|
/* Leave integrated clock source enabled */ |
/* |
* Leave integrated clock source and reference clock enabled for pipe B. |
* The latter is needed for VGA hotplug / manual detection. |
*/ |
if (pipe == PIPE_B) |
val = DPLL_INTEGRATED_CRI_CLK_VLV; |
val = DPLL_INTEGRATED_CRI_CLK_VLV | DPLL_REFA_CLK_ENABLE_VLV; |
I915_WRITE(DPLL(pipe), val); |
POSTING_READ(DPLL(pipe)); |
} |
|
void vlv_wait_port_ready(struct drm_i915_private *dev_priv, int port) |
void vlv_wait_port_ready(struct drm_i915_private *dev_priv, |
struct intel_digital_port *dport) |
{ |
u32 port_mask; |
|
if (!port) |
switch (dport->port) { |
case PORT_B: |
port_mask = DPLL_PORTB_READY_MASK; |
else |
break; |
case PORT_C: |
port_mask = DPLL_PORTC_READY_MASK; |
break; |
default: |
BUG(); |
} |
|
if (wait_for((I915_READ(DPLL(0)) & port_mask) == 0, 1000)) |
WARN(1, "timed out waiting for port %c ready: 0x%08x\n", |
'B' + port, I915_READ(DPLL(0))); |
port_name(dport->port), I915_READ(DPLL(0))); |
} |
|
/** |
1678,7 → 1771,7 |
* returning. |
*/ |
static void intel_enable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe, |
bool pch_port) |
bool pch_port, bool dsi) |
{ |
enum transcoder cpu_transcoder = intel_pipe_to_cpu_transcoder(dev_priv, |
pipe); |
1687,6 → 1780,7 |
u32 val; |
|
assert_planes_disabled(dev_priv, pipe); |
assert_cursor_disabled(dev_priv, pipe); |
assert_sprites_disabled(dev_priv, pipe); |
|
if (HAS_PCH_LPT(dev_priv->dev)) |
1700,6 → 1794,9 |
* need the check. |
*/ |
if (!HAS_PCH_SPLIT(dev_priv->dev)) |
if (dsi) |
assert_dsi_pll_enabled(dev_priv); |
else |
assert_pll_enabled(dev_priv, pipe); |
else { |
if (pch_port) { |
1745,6 → 1842,7 |
* or we might hang the display. |
*/ |
assert_planes_disabled(dev_priv, pipe); |
assert_cursor_disabled(dev_priv, pipe); |
assert_sprites_disabled(dev_priv, pipe); |
|
/* Don't disable pipe A or pipe A PLLs if needed */ |
1764,17 → 1862,17 |
* Plane regs are double buffered, going from enabled->disabled needs a |
* trigger in order to latch. The display address reg provides this. |
*/ |
void intel_flush_display_plane(struct drm_i915_private *dev_priv, |
void intel_flush_primary_plane(struct drm_i915_private *dev_priv, |
enum plane plane) |
{ |
if (dev_priv->info->gen >= 4) |
I915_WRITE(DSPSURF(plane), I915_READ(DSPSURF(plane))); |
else |
I915_WRITE(DSPADDR(plane), I915_READ(DSPADDR(plane))); |
u32 reg = dev_priv->info->gen >= 4 ? DSPSURF(plane) : DSPADDR(plane); |
|
I915_WRITE(reg, I915_READ(reg)); |
POSTING_READ(reg); |
} |
|
/** |
* intel_enable_plane - enable a display plane on a given pipe |
* intel_enable_primary_plane - enable the primary plane on a given pipe |
* @dev_priv: i915 private structure |
* @plane: plane to enable |
* @pipe: pipe being fed |
1781,9 → 1879,11 |
* |
* Enable @plane on @pipe, making sure that @pipe is running first. |
*/ |
static void intel_enable_plane(struct drm_i915_private *dev_priv, |
static void intel_enable_primary_plane(struct drm_i915_private *dev_priv, |
enum plane plane, enum pipe pipe) |
{ |
struct intel_crtc *intel_crtc = |
to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]); |
int reg; |
u32 val; |
|
1790,6 → 1890,10 |
/* If the pipe isn't enabled, we can't pump pixels and may hang */ |
assert_pipe_enabled(dev_priv, pipe); |
|
WARN(intel_crtc->primary_enabled, "Primary plane already enabled\n"); |
|
intel_crtc->primary_enabled = true; |
|
reg = DSPCNTR(plane); |
val = I915_READ(reg); |
if (val & DISPLAY_PLANE_ENABLE) |
1796,12 → 1900,12 |
return; |
|
I915_WRITE(reg, val | DISPLAY_PLANE_ENABLE); |
intel_flush_display_plane(dev_priv, plane); |
intel_flush_primary_plane(dev_priv, plane); |
intel_wait_for_vblank(dev_priv->dev, pipe); |
} |
|
/** |
* intel_disable_plane - disable a display plane |
* intel_disable_primary_plane - disable the primary plane |
* @dev_priv: i915 private structure |
* @plane: plane to disable |
* @pipe: pipe consuming the data |
1808,12 → 1912,18 |
* |
* Disable @plane; should be an independent operation. |
*/ |
static void intel_disable_plane(struct drm_i915_private *dev_priv, |
static void intel_disable_primary_plane(struct drm_i915_private *dev_priv, |
enum plane plane, enum pipe pipe) |
{ |
struct intel_crtc *intel_crtc = |
to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]); |
int reg; |
u32 val; |
|
WARN(!intel_crtc->primary_enabled, "Primary plane already disabled\n"); |
|
intel_crtc->primary_enabled = false; |
|
reg = DSPCNTR(plane); |
val = I915_READ(reg); |
if ((val & DISPLAY_PLANE_ENABLE) == 0) |
1820,7 → 1930,7 |
return; |
|
I915_WRITE(reg, val & ~DISPLAY_PLANE_ENABLE); |
intel_flush_display_plane(dev_priv, plane); |
intel_flush_primary_plane(dev_priv, plane); |
intel_wait_for_vblank(dev_priv->dev, pipe); |
} |
|
1856,10 → 1966,7 |
alignment = 0; |
break; |
case I915_TILING_Y: |
/* Despite that we check this in framebuffer_init userspace can |
* screw us over and change the tiling after the fact. Only |
* pinned buffers can't change their tiling. */ |
DRM_DEBUG_DRIVER("Y tiled not allowed for scan out buffers\n"); |
WARN(1, "Y tiled bo slipped through, driver bug!\n"); |
return -EINVAL; |
default: |
BUG(); |
2021,7 → 2128,7 |
fb->pitches[0]); |
I915_WRITE(DSPSTRIDE(plane), fb->pitches[0]); |
if (INTEL_INFO(dev)->gen >= 4) { |
I915_MODIFY_DISPBASE(DSPSURF(plane), |
I915_WRITE(DSPSURF(plane), |
i915_gem_obj_ggtt_offset(obj) + intel_crtc->dspaddr_offset); |
I915_WRITE(DSPTILEOFF(plane), (y << 16) | x); |
I915_WRITE(DSPLINOFF(plane), linear_offset); |
2094,7 → 2201,7 |
else |
dspcntr &= ~DISPPLANE_TILED; |
|
if (IS_HASWELL(dev)) |
if (IS_HASWELL(dev) || IS_BROADWELL(dev)) |
dspcntr &= ~DISPPLANE_TRICKLE_FEED_DISABLE; |
else |
dspcntr |= DISPPLANE_TRICKLE_FEED_DISABLE; |
2112,9 → 2219,9 |
i915_gem_obj_ggtt_offset(obj), linear_offset, x, y, |
fb->pitches[0]); |
I915_WRITE(DSPSTRIDE(plane), fb->pitches[0]); |
I915_MODIFY_DISPBASE(DSPSURF(plane), |
I915_WRITE(DSPSURF(plane), |
i915_gem_obj_ggtt_offset(obj) + intel_crtc->dspaddr_offset); |
if (IS_HASWELL(dev)) { |
if (IS_HASWELL(dev) || IS_BROADWELL(dev)) { |
I915_WRITE(DSPOFFSET(plane), (y << 16) | x); |
} else { |
I915_WRITE(DSPTILEOFF(plane), (y << 16) | x); |
2172,7 → 2279,12 |
struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
|
mutex_lock(&crtc->mutex); |
if (intel_crtc->active) |
/* |
* FIXME: Once we have proper support for primary planes (and |
* disabling them without disabling the entire crtc) allow again |
* a NULL crtc->fb. |
*/ |
if (intel_crtc->active && crtc->fb) |
dev_priv->display.update_plane(crtc, crtc->fb, |
crtc->x, crtc->y); |
mutex_unlock(&crtc->mutex); |
2263,11 → 2375,26 |
return ret; |
} |
|
/* Update pipe size and adjust fitter if needed */ |
/* |
* Update pipe size and adjust fitter if needed: the reason for this is |
* that in compute_mode_changes we check the native mode (not the pfit |
* mode) to see if we can flip rather than do a full mode set. In the |
* fastboot case, we'll flip, but if we don't update the pipesrc and |
* pfit state, we'll end up with a big fb scanned out into the wrong |
* sized surface. |
* |
* To fix this properly, we need to hoist the checks up into |
* compute_mode_changes (or above), check the actual pfit state and |
* whether the platform allows pfit disable with pipe active, and only |
* then update the pipesrc and pfit state, even on the flip path. |
*/ |
if (i915_fastboot) { |
const struct drm_display_mode *adjusted_mode = |
&intel_crtc->config.adjusted_mode; |
|
I915_WRITE(PIPESRC(intel_crtc->pipe), |
((crtc->mode.hdisplay - 1) << 16) | |
(crtc->mode.vdisplay - 1)); |
((adjusted_mode->crtc_hdisplay - 1) << 16) | |
(adjusted_mode->crtc_vdisplay - 1)); |
if (!intel_crtc->config.pch_pfit.enabled && |
(intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) || |
intel_pipe_has_type(crtc, INTEL_OUTPUT_EDP))) { |
2275,6 → 2402,8 |
I915_WRITE(PF_WIN_POS(intel_crtc->pipe), 0); |
I915_WRITE(PF_WIN_SZ(intel_crtc->pipe), 0); |
} |
intel_crtc->config.pipe_src_w = adjusted_mode->crtc_hdisplay; |
intel_crtc->config.pipe_src_h = adjusted_mode->crtc_vdisplay; |
} |
|
ret = dev_priv->display.update_plane(crtc, fb, x, y); |
2892,6 → 3021,7 |
{ |
struct drm_device *dev = crtc->dev; |
struct drm_i915_private *dev_priv = dev->dev_private; |
int clock = to_intel_crtc(crtc)->config.adjusted_mode.crtc_clock; |
u32 divsel, phaseinc, auxdiv, phasedir = 0; |
u32 temp; |
|
2909,14 → 3039,14 |
SBI_ICLK); |
|
/* 20MHz is a corner case which is out of range for the 7-bit divisor */ |
if (crtc->mode.clock == 20000) { |
if (clock == 20000) { |
auxdiv = 1; |
divsel = 0x41; |
phaseinc = 0x20; |
} else { |
/* The iCLK virtual clock root frequency is in MHz, |
* but the crtc->mode.clock in in KHz. To get the divisors, |
* it is necessary to divide one by another, so we |
* but the adjusted_mode->crtc_clock in in KHz. To get the |
* divisors, it is necessary to divide one by another, so we |
* convert the virtual clock precision to KHz here for higher |
* precision. |
*/ |
2924,7 → 3054,7 |
u32 iclk_pi_range = 64; |
u32 desired_divisor, msb_divisor_value, pi_value; |
|
desired_divisor = (iclk_virtual_root_freq / crtc->mode.clock); |
desired_divisor = (iclk_virtual_root_freq / clock); |
msb_divisor_value = desired_divisor / iclk_pi_range; |
pi_value = desired_divisor % iclk_pi_range; |
|
2940,7 → 3070,7 |
~SBI_SSCDIVINTPHASE_INCVAL_MASK); |
|
DRM_DEBUG_KMS("iCLKIP clock: found settings for %dKHz refresh rate: auxdiv=%x, divsel=%x, phasedir=%x, phaseinc=%x\n", |
crtc->mode.clock, |
clock, |
auxdiv, |
divsel, |
phasedir, |
3305,6 → 3435,108 |
intel_plane_disable(&intel_plane->base); |
} |
|
void hsw_enable_ips(struct intel_crtc *crtc) |
{ |
struct drm_i915_private *dev_priv = crtc->base.dev->dev_private; |
|
if (!crtc->config.ips_enabled) |
return; |
|
/* We can only enable IPS after we enable a plane and wait for a vblank. |
* We guarantee that the plane is enabled by calling intel_enable_ips |
* only after intel_enable_plane. And intel_enable_plane already waits |
* for a vblank, so all we need to do here is to enable the IPS bit. */ |
assert_plane_enabled(dev_priv, crtc->plane); |
if (IS_BROADWELL(crtc->base.dev)) { |
mutex_lock(&dev_priv->rps.hw_lock); |
WARN_ON(sandybridge_pcode_write(dev_priv, DISPLAY_IPS_CONTROL, 0xc0000000)); |
mutex_unlock(&dev_priv->rps.hw_lock); |
/* Quoting Art Runyan: "its not safe to expect any particular |
* value in IPS_CTL bit 31 after enabling IPS through the |
* mailbox." Moreover, the mailbox may return a bogus state, |
* so we need to just enable it and continue on. |
*/ |
} else { |
I915_WRITE(IPS_CTL, IPS_ENABLE); |
/* The bit only becomes 1 in the next vblank, so this wait here |
* is essentially intel_wait_for_vblank. If we don't have this |
* and don't wait for vblanks until the end of crtc_enable, then |
* the HW state readout code will complain that the expected |
* IPS_CTL value is not the one we read. */ |
if (wait_for(I915_READ_NOTRACE(IPS_CTL) & IPS_ENABLE, 50)) |
DRM_ERROR("Timed out waiting for IPS enable\n"); |
} |
} |
|
void hsw_disable_ips(struct intel_crtc *crtc) |
{ |
struct drm_device *dev = crtc->base.dev; |
struct drm_i915_private *dev_priv = dev->dev_private; |
|
if (!crtc->config.ips_enabled) |
return; |
|
assert_plane_enabled(dev_priv, crtc->plane); |
if (IS_BROADWELL(crtc->base.dev)) { |
mutex_lock(&dev_priv->rps.hw_lock); |
WARN_ON(sandybridge_pcode_write(dev_priv, DISPLAY_IPS_CONTROL, 0)); |
mutex_unlock(&dev_priv->rps.hw_lock); |
} else { |
I915_WRITE(IPS_CTL, 0); |
POSTING_READ(IPS_CTL); |
} |
|
/* We need to wait for a vblank before we can disable the plane. */ |
intel_wait_for_vblank(dev, crtc->pipe); |
} |
|
/** Loads the palette/gamma unit for the CRTC with the prepared values */ |
static void intel_crtc_load_lut(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); |
enum pipe pipe = intel_crtc->pipe; |
int palreg = PALETTE(pipe); |
int i; |
bool reenable_ips = false; |
|
/* The clocks have to be on to load the palette. */ |
if (!crtc->enabled || !intel_crtc->active) |
return; |
|
if (!HAS_PCH_SPLIT(dev_priv->dev)) { |
if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DSI)) |
assert_dsi_pll_enabled(dev_priv); |
else |
assert_pll_enabled(dev_priv, pipe); |
} |
|
/* use legacy palette for Ironlake */ |
if (HAS_PCH_SPLIT(dev)) |
palreg = LGC_PALETTE(pipe); |
|
/* Workaround : Do not read or write the pipe palette/gamma data while |
* GAMMA_MODE is configured for split gamma and IPS_CTL has IPS enabled. |
*/ |
if (IS_HASWELL(dev) && intel_crtc->config.ips_enabled && |
((I915_READ(GAMMA_MODE(pipe)) & GAMMA_MODE_MODE_MASK) == |
GAMMA_MODE_MODE_SPLIT)) { |
hsw_disable_ips(intel_crtc); |
reenable_ips = true; |
} |
|
for (i = 0; i < 256; i++) { |
I915_WRITE(palreg + 4 * i, |
(intel_crtc->lut_r[i] << 16) | |
(intel_crtc->lut_g[i] << 8) | |
intel_crtc->lut_b[i]); |
} |
|
if (reenable_ips) |
hsw_enable_ips(intel_crtc); |
} |
|
static void ironlake_crtc_enable(struct drm_crtc *crtc) |
{ |
struct drm_device *dev = crtc->dev; |
3324,8 → 3556,6 |
intel_set_cpu_fifo_underrun_reporting(dev, pipe, true); |
intel_set_pch_fifo_underrun_reporting(dev, pipe, true); |
|
intel_update_watermarks(dev); |
|
for_each_encoder_on_crtc(dev, crtc, encoder) |
if (encoder->pre_enable) |
encoder->pre_enable(encoder); |
3348,9 → 3578,10 |
*/ |
intel_crtc_load_lut(crtc); |
|
intel_update_watermarks(crtc); |
intel_enable_pipe(dev_priv, pipe, |
intel_crtc->config.has_pch_encoder); |
intel_enable_plane(dev_priv, plane, pipe); |
intel_crtc->config.has_pch_encoder, false); |
intel_enable_primary_plane(dev_priv, plane, pipe); |
intel_enable_planes(crtc); |
intel_crtc_update_cursor(crtc, true); |
|
3384,34 → 3615,74 |
return HAS_IPS(crtc->base.dev) && crtc->pipe == PIPE_A; |
} |
|
static void hsw_enable_ips(struct intel_crtc *crtc) |
static void haswell_crtc_enable_planes(struct drm_crtc *crtc) |
{ |
struct drm_i915_private *dev_priv = crtc->base.dev->dev_private; |
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; |
int plane = intel_crtc->plane; |
|
if (!crtc->config.ips_enabled) |
return; |
intel_enable_primary_plane(dev_priv, plane, pipe); |
intel_enable_planes(crtc); |
intel_crtc_update_cursor(crtc, true); |
|
/* We can only enable IPS after we enable a plane and wait for a vblank. |
* We guarantee that the plane is enabled by calling intel_enable_ips |
* only after intel_enable_plane. And intel_enable_plane already waits |
* for a vblank, so all we need to do here is to enable the IPS bit. */ |
assert_plane_enabled(dev_priv, crtc->plane); |
I915_WRITE(IPS_CTL, IPS_ENABLE); |
hsw_enable_ips(intel_crtc); |
|
mutex_lock(&dev->struct_mutex); |
intel_update_fbc(dev); |
mutex_unlock(&dev->struct_mutex); |
} |
|
static void hsw_disable_ips(struct intel_crtc *crtc) |
static void haswell_crtc_disable_planes(struct drm_crtc *crtc) |
{ |
struct drm_device *dev = crtc->base.dev; |
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; |
int plane = intel_crtc->plane; |
|
if (!crtc->config.ips_enabled) |
// intel_crtc_wait_for_pending_flips(crtc); |
// drm_vblank_off(dev, pipe); |
|
/* FBC must be disabled before disabling the plane on HSW. */ |
if (dev_priv->fbc.plane == plane) |
intel_disable_fbc(dev); |
|
hsw_disable_ips(intel_crtc); |
|
intel_crtc_update_cursor(crtc, false); |
intel_disable_planes(crtc); |
intel_disable_primary_plane(dev_priv, plane, pipe); |
} |
|
/* |
* This implements the workaround described in the "notes" section of the mode |
* set sequence documentation. When going from no pipes or single pipe to |
* multiple pipes, and planes are enabled after the pipe, we need to wait at |
* least 2 vblanks on the first pipe before enabling planes on the second pipe. |
*/ |
static void haswell_mode_set_planes_workaround(struct intel_crtc *crtc) |
{ |
struct drm_device *dev = crtc->base.dev; |
struct intel_crtc *crtc_it, *other_active_crtc = NULL; |
|
/* We want to get the other_active_crtc only if there's only 1 other |
* active crtc. */ |
list_for_each_entry(crtc_it, &dev->mode_config.crtc_list, base.head) { |
if (!crtc_it->active || crtc_it == crtc) |
continue; |
|
if (other_active_crtc) |
return; |
|
assert_plane_enabled(dev_priv, crtc->plane); |
I915_WRITE(IPS_CTL, 0); |
other_active_crtc = crtc_it; |
} |
if (!other_active_crtc) |
return; |
|
/* We need to wait for a vblank before we can disable the plane. */ |
intel_wait_for_vblank(dev, crtc->pipe); |
intel_wait_for_vblank(dev, other_active_crtc->pipe); |
intel_wait_for_vblank(dev, other_active_crtc->pipe); |
} |
|
static void haswell_crtc_enable(struct drm_crtc *crtc) |
3421,7 → 3692,6 |
struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
struct intel_encoder *encoder; |
int pipe = intel_crtc->pipe; |
int plane = intel_crtc->plane; |
|
WARN_ON(!crtc->enabled); |
|
3434,8 → 3704,6 |
if (intel_crtc->config.has_pch_encoder) |
intel_set_pch_fifo_underrun_reporting(dev, TRANSCODER_A, true); |
|
intel_update_watermarks(dev); |
|
if (intel_crtc->config.has_pch_encoder) |
dev_priv->display.fdi_link_train(crtc); |
|
3456,24 → 3724,23 |
intel_ddi_set_pipe_settings(crtc); |
intel_ddi_enable_transcoder_func(crtc); |
|
intel_update_watermarks(crtc); |
intel_enable_pipe(dev_priv, pipe, |
intel_crtc->config.has_pch_encoder); |
intel_enable_plane(dev_priv, plane, pipe); |
intel_enable_planes(crtc); |
intel_crtc_update_cursor(crtc, true); |
intel_crtc->config.has_pch_encoder, false); |
|
hsw_enable_ips(intel_crtc); |
|
if (intel_crtc->config.has_pch_encoder) |
lpt_pch_enable(crtc); |
|
mutex_lock(&dev->struct_mutex); |
intel_update_fbc(dev); |
mutex_unlock(&dev->struct_mutex); |
|
for_each_encoder_on_crtc(dev, crtc, encoder) |
for_each_encoder_on_crtc(dev, crtc, encoder) { |
encoder->enable(encoder); |
intel_opregion_notify_encoder(encoder, true); |
} |
|
/* If we change the relative order between pipe/planes enabling, we need |
* to change the workaround. */ |
haswell_mode_set_planes_workaround(intel_crtc); |
haswell_crtc_enable_planes(crtc); |
|
/* |
* There seems to be a race in PCH platform hw (at least on some |
* outputs) where an enabled pipe still completes any pageflip right |
3525,7 → 3792,7 |
|
intel_crtc_update_cursor(crtc, false); |
intel_disable_planes(crtc); |
intel_disable_plane(dev_priv, plane, pipe); |
intel_disable_primary_plane(dev_priv, plane, pipe); |
|
if (intel_crtc->config.has_pch_encoder) |
intel_set_pch_fifo_underrun_reporting(dev, pipe, false); |
3566,7 → 3833,7 |
} |
|
intel_crtc->active = false; |
intel_update_watermarks(dev); |
intel_update_watermarks(crtc); |
|
mutex_lock(&dev->struct_mutex); |
intel_update_fbc(dev); |
3580,26 → 3847,18 |
struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
struct intel_encoder *encoder; |
int pipe = intel_crtc->pipe; |
int plane = intel_crtc->plane; |
enum transcoder cpu_transcoder = intel_crtc->config.cpu_transcoder; |
|
if (!intel_crtc->active) |
return; |
|
for_each_encoder_on_crtc(dev, crtc, encoder) |
haswell_crtc_disable_planes(crtc); |
|
for_each_encoder_on_crtc(dev, crtc, encoder) { |
intel_opregion_notify_encoder(encoder, false); |
encoder->disable(encoder); |
} |
|
|
/* FBC must be disabled before disabling the plane on HSW. */ |
if (dev_priv->fbc.plane == plane) |
intel_disable_fbc(dev); |
|
hsw_disable_ips(intel_crtc); |
|
intel_crtc_update_cursor(crtc, false); |
intel_disable_planes(crtc); |
intel_disable_plane(dev_priv, plane, pipe); |
|
if (intel_crtc->config.has_pch_encoder) |
intel_set_pch_fifo_underrun_reporting(dev, TRANSCODER_A, false); |
intel_disable_pipe(dev_priv, pipe); |
3621,7 → 3880,7 |
} |
|
intel_crtc->active = false; |
intel_update_watermarks(dev); |
intel_update_watermarks(crtc); |
|
mutex_lock(&dev->struct_mutex); |
intel_update_fbc(dev); |
3705,6 → 3964,174 |
I915_WRITE(BCLRPAT(crtc->pipe), 0); |
} |
|
int valleyview_get_vco(struct drm_i915_private *dev_priv) |
{ |
int hpll_freq, vco_freq[] = { 800, 1600, 2000, 2400 }; |
|
/* Obtain SKU information */ |
mutex_lock(&dev_priv->dpio_lock); |
hpll_freq = vlv_cck_read(dev_priv, CCK_FUSE_REG) & |
CCK_FUSE_HPLL_FREQ_MASK; |
mutex_unlock(&dev_priv->dpio_lock); |
|
return vco_freq[hpll_freq]; |
} |
|
/* Adjust CDclk dividers to allow high res or save power if possible */ |
static void valleyview_set_cdclk(struct drm_device *dev, int cdclk) |
{ |
struct drm_i915_private *dev_priv = dev->dev_private; |
u32 val, cmd; |
|
if (cdclk >= 320) /* jump to highest voltage for 400MHz too */ |
cmd = 2; |
else if (cdclk == 266) |
cmd = 1; |
else |
cmd = 0; |
|
mutex_lock(&dev_priv->rps.hw_lock); |
val = vlv_punit_read(dev_priv, PUNIT_REG_DSPFREQ); |
val &= ~DSPFREQGUAR_MASK; |
val |= (cmd << DSPFREQGUAR_SHIFT); |
vlv_punit_write(dev_priv, PUNIT_REG_DSPFREQ, val); |
if (wait_for((vlv_punit_read(dev_priv, PUNIT_REG_DSPFREQ) & |
DSPFREQSTAT_MASK) == (cmd << DSPFREQSTAT_SHIFT), |
50)) { |
DRM_ERROR("timed out waiting for CDclk change\n"); |
} |
mutex_unlock(&dev_priv->rps.hw_lock); |
|
if (cdclk == 400) { |
u32 divider, vco; |
|
vco = valleyview_get_vco(dev_priv); |
divider = ((vco << 1) / cdclk) - 1; |
|
mutex_lock(&dev_priv->dpio_lock); |
/* adjust cdclk divider */ |
val = vlv_cck_read(dev_priv, CCK_DISPLAY_CLOCK_CONTROL); |
val &= ~0xf; |
val |= divider; |
vlv_cck_write(dev_priv, CCK_DISPLAY_CLOCK_CONTROL, val); |
mutex_unlock(&dev_priv->dpio_lock); |
} |
|
mutex_lock(&dev_priv->dpio_lock); |
/* adjust self-refresh exit latency value */ |
val = vlv_bunit_read(dev_priv, BUNIT_REG_BISOC); |
val &= ~0x7f; |
|
/* |
* For high bandwidth configs, we set a higher latency in the bunit |
* so that the core display fetch happens in time to avoid underruns. |
*/ |
if (cdclk == 400) |
val |= 4500 / 250; /* 4.5 usec */ |
else |
val |= 3000 / 250; /* 3.0 usec */ |
vlv_bunit_write(dev_priv, BUNIT_REG_BISOC, val); |
mutex_unlock(&dev_priv->dpio_lock); |
|
/* Since we changed the CDclk, we need to update the GMBUSFREQ too */ |
intel_i2c_reset(dev); |
} |
|
static int valleyview_cur_cdclk(struct drm_i915_private *dev_priv) |
{ |
int cur_cdclk, vco; |
int divider; |
|
vco = valleyview_get_vco(dev_priv); |
|
mutex_lock(&dev_priv->dpio_lock); |
divider = vlv_cck_read(dev_priv, CCK_DISPLAY_CLOCK_CONTROL); |
mutex_unlock(&dev_priv->dpio_lock); |
|
divider &= 0xf; |
|
cur_cdclk = (vco << 1) / (divider + 1); |
|
return cur_cdclk; |
} |
|
static int valleyview_calc_cdclk(struct drm_i915_private *dev_priv, |
int max_pixclk) |
{ |
int cur_cdclk; |
|
cur_cdclk = valleyview_cur_cdclk(dev_priv); |
|
/* |
* Really only a few cases to deal with, as only 4 CDclks are supported: |
* 200MHz |
* 267MHz |
* 320MHz |
* 400MHz |
* So we check to see whether we're above 90% of the lower bin and |
* adjust if needed. |
*/ |
if (max_pixclk > 288000) { |
return 400; |
} else if (max_pixclk > 240000) { |
return 320; |
} else |
return 266; |
/* Looks like the 200MHz CDclk freq doesn't work on some configs */ |
} |
|
static int intel_mode_max_pixclk(struct drm_i915_private *dev_priv, |
unsigned modeset_pipes, |
struct intel_crtc_config *pipe_config) |
{ |
struct drm_device *dev = dev_priv->dev; |
struct intel_crtc *intel_crtc; |
int max_pixclk = 0; |
|
list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list, |
base.head) { |
if (modeset_pipes & (1 << intel_crtc->pipe)) |
max_pixclk = max(max_pixclk, |
pipe_config->adjusted_mode.crtc_clock); |
else if (intel_crtc->base.enabled) |
max_pixclk = max(max_pixclk, |
intel_crtc->config.adjusted_mode.crtc_clock); |
} |
|
return max_pixclk; |
} |
|
static void valleyview_modeset_global_pipes(struct drm_device *dev, |
unsigned *prepare_pipes, |
unsigned modeset_pipes, |
struct intel_crtc_config *pipe_config) |
{ |
struct drm_i915_private *dev_priv = dev->dev_private; |
struct intel_crtc *intel_crtc; |
int max_pixclk = intel_mode_max_pixclk(dev_priv, modeset_pipes, |
pipe_config); |
int cur_cdclk = valleyview_cur_cdclk(dev_priv); |
|
if (valleyview_calc_cdclk(dev_priv, max_pixclk) == cur_cdclk) |
return; |
|
list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list, |
base.head) |
if (intel_crtc->base.enabled) |
*prepare_pipes |= (1 << intel_crtc->pipe); |
} |
|
static void valleyview_modeset_global_resources(struct drm_device *dev) |
{ |
struct drm_i915_private *dev_priv = dev->dev_private; |
int max_pixclk = intel_mode_max_pixclk(dev_priv, 0, NULL); |
int cur_cdclk = valleyview_cur_cdclk(dev_priv); |
int req_cdclk = valleyview_calc_cdclk(dev_priv, max_pixclk); |
|
if (req_cdclk != cur_cdclk) |
valleyview_set_cdclk(dev, req_cdclk); |
} |
|
static void valleyview_crtc_enable(struct drm_crtc *crtc) |
{ |
struct drm_device *dev = crtc->dev; |
3713,6 → 4140,7 |
struct intel_encoder *encoder; |
int pipe = intel_crtc->pipe; |
int plane = intel_crtc->plane; |
bool is_dsi; |
|
WARN_ON(!crtc->enabled); |
|
3720,12 → 4148,14 |
return; |
|
intel_crtc->active = true; |
intel_update_watermarks(dev); |
|
for_each_encoder_on_crtc(dev, crtc, encoder) |
if (encoder->pre_pll_enable) |
encoder->pre_pll_enable(encoder); |
|
is_dsi = intel_pipe_has_type(crtc, INTEL_OUTPUT_DSI); |
|
if (!is_dsi) |
vlv_enable_pll(intel_crtc); |
|
for_each_encoder_on_crtc(dev, crtc, encoder) |
3736,8 → 4166,9 |
|
intel_crtc_load_lut(crtc); |
|
intel_enable_pipe(dev_priv, pipe, false); |
intel_enable_plane(dev_priv, plane, pipe); |
intel_update_watermarks(crtc); |
intel_enable_pipe(dev_priv, pipe, false, is_dsi); |
intel_enable_primary_plane(dev_priv, plane, pipe); |
intel_enable_planes(crtc); |
intel_crtc_update_cursor(crtc, true); |
|
3762,7 → 4193,6 |
return; |
|
intel_crtc->active = true; |
intel_update_watermarks(dev); |
|
for_each_encoder_on_crtc(dev, crtc, encoder) |
if (encoder->pre_enable) |
3774,8 → 4204,9 |
|
intel_crtc_load_lut(crtc); |
|
intel_enable_pipe(dev_priv, pipe, false); |
intel_enable_plane(dev_priv, plane, pipe); |
intel_update_watermarks(crtc); |
intel_enable_pipe(dev_priv, pipe, false, false); |
intel_enable_primary_plane(dev_priv, plane, pipe); |
intel_enable_planes(crtc); |
/* The fixup needs to happen before cursor is enabled */ |
if (IS_G4X(dev)) |
3831,7 → 4262,7 |
intel_crtc_dpms_overlay(intel_crtc, false); |
intel_crtc_update_cursor(crtc, false); |
intel_disable_planes(crtc); |
intel_disable_plane(dev_priv, plane, pipe); |
intel_disable_primary_plane(dev_priv, plane, pipe); |
|
intel_disable_pipe(dev_priv, pipe); |
|
3841,14 → 4272,15 |
if (encoder->post_disable) |
encoder->post_disable(encoder); |
|
if (IS_VALLEYVIEW(dev)) |
if (IS_VALLEYVIEW(dev) && !intel_pipe_has_type(crtc, INTEL_OUTPUT_DSI)) |
vlv_disable_pll(dev_priv, pipe); |
else |
else if (!IS_VALLEYVIEW(dev)) |
i9xx_disable_pll(dev_priv, pipe); |
|
intel_crtc->active = false; |
intel_update_watermarks(crtc); |
|
intel_update_fbc(dev); |
intel_update_watermarks(dev); |
} |
|
static void i9xx_crtc_off(struct drm_crtc *crtc) |
3926,6 → 4358,7 |
dev_priv->display.off(crtc); |
|
assert_plane_disabled(dev->dev_private, to_intel_crtc(crtc)->plane); |
assert_cursor_disabled(dev_priv, to_intel_crtc(crtc)->pipe); |
assert_pipe_disabled(dev->dev_private, to_intel_crtc(crtc)->pipe); |
|
if (crtc->fb) { |
4053,7 → 4486,7 |
return false; |
} |
|
if (IS_HASWELL(dev)) { |
if (IS_HASWELL(dev) || IS_BROADWELL(dev)) { |
if (pipe_config->fdi_lanes > 2) { |
DRM_DEBUG_KMS("only 2 lanes on haswell, required: %i lanes\n", |
pipe_config->fdi_lanes); |
4115,8 → 4548,7 |
*/ |
link_bw = intel_fdi_link_freq(dev) * MHz(100)/KHz(1)/10; |
|
fdi_dotclock = adjusted_mode->clock; |
fdi_dotclock /= pipe_config->pixel_multiplier; |
fdi_dotclock = adjusted_mode->crtc_clock; |
|
lane = ironlake_get_lanes_required(fdi_dotclock, link_bw, |
pipe_config->pipe_bpp); |
4158,13 → 4590,39 |
struct drm_device *dev = crtc->base.dev; |
struct drm_display_mode *adjusted_mode = &pipe_config->adjusted_mode; |
|
if (HAS_PCH_SPLIT(dev)) { |
/* FDI link clock is fixed at 2.7G */ |
if (pipe_config->requested_mode.clock * 3 |
> IRONLAKE_FDI_FREQ * 4) |
/* FIXME should check pixel clock limits on all platforms */ |
if (INTEL_INFO(dev)->gen < 4) { |
struct drm_i915_private *dev_priv = dev->dev_private; |
int clock_limit = |
dev_priv->display.get_display_clock_speed(dev); |
|
/* |
* Enable pixel doubling when the dot clock |
* is > 90% of the (display) core speed. |
* |
* GDG double wide on either pipe, |
* otherwise pipe A only. |
*/ |
if ((crtc->pipe == PIPE_A || IS_I915G(dev)) && |
adjusted_mode->crtc_clock > clock_limit * 9 / 10) { |
clock_limit *= 2; |
pipe_config->double_wide = true; |
} |
|
if (adjusted_mode->crtc_clock > clock_limit * 9 / 10) |
return -EINVAL; |
} |
|
/* |
* Pipe horizontal size must be even in: |
* - DVO ganged mode |
* - LVDS dual channel mode |
* - Double wide pipe |
*/ |
if ((intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_LVDS) && |
intel_is_dual_link_lvds(dev)) || pipe_config->double_wide) |
pipe_config->pipe_src_w &= ~1; |
|
/* Cantiga+ cannot handle modes with a hsync front porch of 0. |
* WaPruneModeWithIncorrectHsyncOffset:ctg,elk,ilk,snb,ivb,vlv,hsw. |
*/ |
4328,28 → 4786,6 |
&& !(dev_priv->quirks & QUIRK_LVDS_SSC_DISABLE); |
} |
|
static int vlv_get_refclk(struct drm_crtc *crtc) |
{ |
struct drm_device *dev = crtc->dev; |
struct drm_i915_private *dev_priv = dev->dev_private; |
int refclk = 27000; /* for DP & HDMI */ |
|
return 100000; /* only one validated so far */ |
|
if (intel_pipe_has_type(crtc, INTEL_OUTPUT_ANALOG)) { |
refclk = 96000; |
} else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) { |
if (intel_panel_use_ssc(dev_priv)) |
refclk = 100000; |
else |
refclk = 96000; |
} else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_EDP)) { |
refclk = 100000; |
} |
|
return refclk; |
} |
|
static int i9xx_get_refclk(struct drm_crtc *crtc, int num_connectors) |
{ |
struct drm_device *dev = crtc->dev; |
4357,12 → 4793,11 |
int refclk; |
|
if (IS_VALLEYVIEW(dev)) { |
refclk = vlv_get_refclk(crtc); |
refclk = 100000; |
} else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) && |
intel_panel_use_ssc(dev_priv) && num_connectors < 2) { |
refclk = dev_priv->vbt.lvds_ssc_freq * 1000; |
DRM_DEBUG_KMS("using SSC reference clock of %d MHz\n", |
refclk / 1000); |
refclk = dev_priv->vbt.lvds_ssc_freq; |
DRM_DEBUG_KMS("using SSC reference clock of %d kHz\n", refclk); |
} else if (!IS_GEN2(dev)) { |
refclk = 96000; |
} else { |
4415,7 → 4850,8 |
} |
} |
|
static void vlv_pllb_recal_opamp(struct drm_i915_private *dev_priv) |
static void vlv_pllb_recal_opamp(struct drm_i915_private *dev_priv, enum pipe |
pipe) |
{ |
u32 reg_val; |
|
4423,24 → 4859,24 |
* PLLB opamp always calibrates to max value of 0x3f, force enable it |
* and set it to a reasonable value instead. |
*/ |
reg_val = vlv_dpio_read(dev_priv, DPIO_IREF(1)); |
reg_val = vlv_dpio_read(dev_priv, pipe, VLV_PLL_DW9(1)); |
reg_val &= 0xffffff00; |
reg_val |= 0x00000030; |
vlv_dpio_write(dev_priv, DPIO_IREF(1), reg_val); |
vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW9(1), reg_val); |
|
reg_val = vlv_dpio_read(dev_priv, DPIO_CALIBRATION); |
reg_val = vlv_dpio_read(dev_priv, pipe, VLV_REF_DW13); |
reg_val &= 0x8cffffff; |
reg_val = 0x8c000000; |
vlv_dpio_write(dev_priv, DPIO_CALIBRATION, reg_val); |
vlv_dpio_write(dev_priv, pipe, VLV_REF_DW13, reg_val); |
|
reg_val = vlv_dpio_read(dev_priv, DPIO_IREF(1)); |
reg_val = vlv_dpio_read(dev_priv, pipe, VLV_PLL_DW9(1)); |
reg_val &= 0xffffff00; |
vlv_dpio_write(dev_priv, DPIO_IREF(1), reg_val); |
vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW9(1), reg_val); |
|
reg_val = vlv_dpio_read(dev_priv, DPIO_CALIBRATION); |
reg_val = vlv_dpio_read(dev_priv, pipe, VLV_REF_DW13); |
reg_val &= 0x00ffffff; |
reg_val |= 0xb0000000; |
vlv_dpio_write(dev_priv, DPIO_CALIBRATION, reg_val); |
vlv_dpio_write(dev_priv, pipe, VLV_REF_DW13, reg_val); |
} |
|
static void intel_pch_transcoder_set_m_n(struct intel_crtc *crtc, |
4506,18 → 4942,18 |
|
/* PLL B needs special handling */ |
if (pipe) |
vlv_pllb_recal_opamp(dev_priv); |
vlv_pllb_recal_opamp(dev_priv, pipe); |
|
/* Set up Tx target for periodic Rcomp update */ |
vlv_dpio_write(dev_priv, DPIO_IREF_BCAST, 0x0100000f); |
vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW9_BCAST, 0x0100000f); |
|
/* Disable target IRef on PLL */ |
reg_val = vlv_dpio_read(dev_priv, DPIO_IREF_CTL(pipe)); |
reg_val = vlv_dpio_read(dev_priv, pipe, VLV_PLL_DW8(pipe)); |
reg_val &= 0x00ffffff; |
vlv_dpio_write(dev_priv, DPIO_IREF_CTL(pipe), reg_val); |
vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW8(pipe), reg_val); |
|
/* Disable fast lock */ |
vlv_dpio_write(dev_priv, DPIO_FASTCLK_DISABLE, 0x610); |
vlv_dpio_write(dev_priv, pipe, VLV_CMN_DW0, 0x610); |
|
/* Set idtafcrecal before PLL is enabled */ |
mdiv = ((bestm1 << DPIO_M1DIV_SHIFT) | (bestm2 & DPIO_M2DIV_MASK)); |
4531,19 → 4967,19 |
* Note: don't use the DAC post divider as it seems unstable. |
*/ |
mdiv |= (DPIO_POST_DIV_HDMIDP << DPIO_POST_DIV_SHIFT); |
vlv_dpio_write(dev_priv, DPIO_DIV(pipe), mdiv); |
vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW3(pipe), mdiv); |
|
mdiv |= DPIO_ENABLE_CALIBRATION; |
vlv_dpio_write(dev_priv, DPIO_DIV(pipe), mdiv); |
vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW3(pipe), mdiv); |
|
/* Set HBR and RBR LPF coefficients */ |
if (crtc->config.port_clock == 162000 || |
intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_ANALOG) || |
intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_HDMI)) |
vlv_dpio_write(dev_priv, DPIO_LPF_COEFF(pipe), |
vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW10(pipe), |
0x009f0003); |
else |
vlv_dpio_write(dev_priv, DPIO_LPF_COEFF(pipe), |
vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW10(pipe), |
0x00d0000f); |
|
if (intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_EDP) || |
4550,31 → 4986,35 |
intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_DISPLAYPORT)) { |
/* Use SSC source */ |
if (!pipe) |
vlv_dpio_write(dev_priv, DPIO_REFSFR(pipe), |
vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW5(pipe), |
0x0df40000); |
else |
vlv_dpio_write(dev_priv, DPIO_REFSFR(pipe), |
vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW5(pipe), |
0x0df70000); |
} else { /* HDMI or VGA */ |
/* Use bend source */ |
if (!pipe) |
vlv_dpio_write(dev_priv, DPIO_REFSFR(pipe), |
vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW5(pipe), |
0x0df70000); |
else |
vlv_dpio_write(dev_priv, DPIO_REFSFR(pipe), |
vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW5(pipe), |
0x0df40000); |
} |
|
coreclk = vlv_dpio_read(dev_priv, DPIO_CORE_CLK(pipe)); |
coreclk = vlv_dpio_read(dev_priv, pipe, VLV_PLL_DW7(pipe)); |
coreclk = (coreclk & 0x0000ff00) | 0x01c00000; |
if (intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_DISPLAYPORT) || |
intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_EDP)) |
coreclk |= 0x01000000; |
vlv_dpio_write(dev_priv, DPIO_CORE_CLK(pipe), coreclk); |
vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW7(pipe), coreclk); |
|
vlv_dpio_write(dev_priv, DPIO_PLL_CML(pipe), 0x87871000); |
vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW11(pipe), 0x87871000); |
|
/* Enable DPIO clock input */ |
/* |
* Enable DPIO clock input. We should never disable the reference |
* clock for pipe B, since VGA hotplug / manual detection depends |
* on it. |
*/ |
dpll = DPLL_EXT_BUFFER_ENABLE_VLV | DPLL_REFA_CLK_ENABLE_VLV | |
DPLL_VGA_MODE_DIS | DPLL_INTEGRATED_CLOCK_VLV; |
/* We should never disable this, set it here for state tracking */ |
4717,7 → 5157,6 |
enum transcoder cpu_transcoder = intel_crtc->config.cpu_transcoder; |
struct drm_display_mode *adjusted_mode = |
&intel_crtc->config.adjusted_mode; |
struct drm_display_mode *mode = &intel_crtc->config.requested_mode; |
uint32_t vsyncshift, crtc_vtotal, crtc_vblank_end; |
|
/* We need to be careful not to changed the adjusted mode, for otherwise |
4770,7 → 5209,8 |
* always be the user's requested size. |
*/ |
I915_WRITE(PIPESRC(pipe), |
((mode->hdisplay - 1) << 16) | (mode->vdisplay - 1)); |
((intel_crtc->config.pipe_src_w - 1) << 16) | |
(intel_crtc->config.pipe_src_h - 1)); |
} |
|
static void intel_get_pipe_timings(struct intel_crtc *crtc, |
4808,8 → 5248,11 |
} |
|
tmp = I915_READ(PIPESRC(crtc->pipe)); |
pipe_config->requested_mode.vdisplay = (tmp & 0xffff) + 1; |
pipe_config->requested_mode.hdisplay = ((tmp >> 16) & 0xffff) + 1; |
pipe_config->pipe_src_h = (tmp & 0xffff) + 1; |
pipe_config->pipe_src_w = ((tmp >> 16) & 0xffff) + 1; |
|
pipe_config->requested_mode.vdisplay = pipe_config->pipe_src_h; |
pipe_config->requested_mode.hdisplay = pipe_config->pipe_src_w; |
} |
|
static void intel_crtc_mode_from_pipe_config(struct intel_crtc *intel_crtc, |
4829,7 → 5272,7 |
|
crtc->mode.flags = pipe_config->adjusted_mode.flags; |
|
crtc->mode.clock = pipe_config->adjusted_mode.clock; |
crtc->mode.clock = pipe_config->adjusted_mode.crtc_clock; |
crtc->mode.flags |= pipe_config->adjusted_mode.flags; |
} |
|
4845,17 → 5288,8 |
I915_READ(PIPECONF(intel_crtc->pipe)) & PIPECONF_ENABLE) |
pipeconf |= PIPECONF_ENABLE; |
|
if (intel_crtc->pipe == 0 && INTEL_INFO(dev)->gen < 4) { |
/* Enable pixel doubling when the dot clock is > 90% of the (display) |
* core speed. |
* |
* XXX: No double-wide on 915GM pipe B. Is that the only reason for the |
* pipe == 0 check? |
*/ |
if (intel_crtc->config.requested_mode.clock > |
dev_priv->display.get_display_clock_speed(dev) * 9 / 10) |
if (intel_crtc->config.double_wide) |
pipeconf |= PIPECONF_DOUBLE_WIDE; |
} |
|
/* only g4x and later have fancy bpc/dither controls */ |
if (IS_G4X(dev) || IS_VALLEYVIEW(dev)) { |
4909,7 → 5343,6 |
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 drm_display_mode *mode = &intel_crtc->config.requested_mode; |
int pipe = intel_crtc->pipe; |
int plane = intel_crtc->plane; |
int refclk, num_connectors = 0; |
4916,7 → 5349,7 |
intel_clock_t clock, reduced_clock; |
u32 dspcntr; |
bool ok, has_reduced_clock = false; |
bool is_lvds = false; |
bool is_lvds = false, is_dsi = false; |
struct intel_encoder *encoder; |
const intel_limit_t *limit; |
int ret; |
4926,23 → 5359,31 |
case INTEL_OUTPUT_LVDS: |
is_lvds = true; |
break; |
case INTEL_OUTPUT_DSI: |
is_dsi = true; |
break; |
} |
|
num_connectors++; |
} |
|
if (is_dsi) |
goto skip_dpll; |
|
if (!intel_crtc->config.clock_set) { |
refclk = i9xx_get_refclk(crtc, num_connectors); |
|
/* |
* Returns a set of divisors for the desired target clock with the given |
* refclk, or FALSE. The returned values represent the clock equation: |
* reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2. |
* Returns a set of divisors for the desired target clock with |
* the given refclk, or FALSE. The returned values represent |
* the clock equation: reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + |
* 2) / p1 / p2. |
*/ |
limit = intel_limit(crtc, refclk); |
ok = dev_priv->display.find_dpll(limit, crtc, |
intel_crtc->config.port_clock, |
refclk, NULL, &clock); |
if (!ok && !intel_crtc->config.clock_set) { |
if (!ok) { |
DRM_ERROR("Couldn't find PLL settings for mode!\n"); |
return -EINVAL; |
} |
4949,10 → 5390,10 |
|
if (is_lvds && dev_priv->lvds_downclock_avail) { |
/* |
* Ensure we match the reduced clock's P to the target clock. |
* If the clocks don't match, we can't switch the display clock |
* by using the FP0/FP1. In such case we will disable the LVDS |
* downclock feature. |
* Ensure we match the reduced clock's P to the target |
* clock. If the clocks don't match, we can't switch |
* the display clock by using the FP0/FP1. In such case |
* we will disable the LVDS downclock feature. |
*/ |
has_reduced_clock = |
dev_priv->display.find_dpll(limit, crtc, |
4961,7 → 5402,6 |
&reduced_clock); |
} |
/* Compat-code for transition, will disappear. */ |
if (!intel_crtc->config.clock_set) { |
intel_crtc->config.dpll.n = clock.n; |
intel_crtc->config.dpll.m1 = clock.m1; |
intel_crtc->config.dpll.m2 = clock.m2; |
4969,17 → 5409,19 |
intel_crtc->config.dpll.p2 = clock.p2; |
} |
|
if (IS_GEN2(dev)) |
if (IS_GEN2(dev)) { |
i8xx_update_pll(intel_crtc, |
has_reduced_clock ? &reduced_clock : NULL, |
num_connectors); |
else if (IS_VALLEYVIEW(dev)) |
} else if (IS_VALLEYVIEW(dev)) { |
vlv_update_pll(intel_crtc); |
else |
} else { |
i9xx_update_pll(intel_crtc, |
has_reduced_clock ? &reduced_clock : NULL, |
num_connectors); |
} |
|
skip_dpll: |
/* Set up the display plane register */ |
dspcntr = DISPPLANE_GAMMA_ENABLE; |
|
4996,8 → 5438,8 |
* which should always be the user's requested size. |
*/ |
I915_WRITE(DSPSIZE(plane), |
((mode->vdisplay - 1) << 16) | |
(mode->hdisplay - 1)); |
((intel_crtc->config.pipe_src_h - 1) << 16) | |
(intel_crtc->config.pipe_src_w - 1)); |
I915_WRITE(DSPPOS(plane), 0); |
|
i9xx_set_pipeconf(intel_crtc); |
5007,8 → 5449,6 |
|
ret = intel_pipe_set_base(crtc, x, y, fb); |
|
intel_update_watermarks(dev); |
|
return ret; |
} |
|
5019,6 → 5459,9 |
struct drm_i915_private *dev_priv = dev->dev_private; |
uint32_t tmp; |
|
if (INTEL_INFO(dev)->gen <= 3 && (IS_I830(dev) || !IS_MOBILE(dev))) |
return; |
|
tmp = I915_READ(PFIT_CONTROL); |
if (!(tmp & PFIT_ENABLE)) |
return; |
5050,7 → 5493,7 |
int refclk = 100000; |
|
mutex_lock(&dev_priv->dpio_lock); |
mdiv = vlv_dpio_read(dev_priv, DPIO_DIV(pipe)); |
mdiv = vlv_dpio_read(dev_priv, pipe, VLV_PLL_DW3(pipe)); |
mutex_unlock(&dev_priv->dpio_lock); |
|
clock.m1 = (mdiv >> DPIO_M1DIV_SHIFT) & 7; |
5059,10 → 5502,10 |
clock.p1 = (mdiv >> DPIO_P1_SHIFT) & 7; |
clock.p2 = (mdiv >> DPIO_P2_SHIFT) & 0x1f; |
|
clock.vco = refclk * clock.m1 * clock.m2 / clock.n; |
clock.dot = 2 * clock.vco / (clock.p1 * clock.p2); |
vlv_clock(refclk, &clock); |
|
pipe_config->adjusted_mode.clock = clock.dot / 10; |
/* clock.dot is the fast clock */ |
pipe_config->port_clock = clock.dot / 5; |
} |
|
static bool i9xx_get_pipe_config(struct intel_crtc *crtc, |
5095,6 → 5538,9 |
} |
} |
|
if (INTEL_INFO(dev)->gen < 4) |
pipe_config->double_wide = tmp & PIPECONF_DOUBLE_WIDE; |
|
intel_get_pipe_timings(crtc, pipe_config); |
|
i9xx_get_pfit_config(crtc, pipe_config); |
5127,6 → 5573,11 |
DPLL_PORTB_READY_MASK); |
} |
|
if (IS_VALLEYVIEW(dev)) |
vlv_crtc_clock_get(crtc, pipe_config); |
else |
i9xx_crtc_clock_get(crtc, pipe_config); |
|
return true; |
} |
|
5499,9 → 5950,9 |
} |
|
if (is_lvds && intel_panel_use_ssc(dev_priv) && num_connectors < 2) { |
DRM_DEBUG_KMS("using SSC reference clock of %d MHz\n", |
DRM_DEBUG_KMS("using SSC reference clock of %d kHz\n", |
dev_priv->vbt.lvds_ssc_freq); |
return dev_priv->vbt.lvds_ssc_freq * 1000; |
return dev_priv->vbt.lvds_ssc_freq; |
} |
|
return 120000; |
5615,14 → 6066,16 |
|
static void haswell_set_pipeconf(struct drm_crtc *crtc) |
{ |
struct drm_i915_private *dev_priv = crtc->dev->dev_private; |
struct drm_device *dev = crtc->dev; |
struct drm_i915_private *dev_priv = dev->dev_private; |
struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
enum pipe pipe = intel_crtc->pipe; |
enum transcoder cpu_transcoder = intel_crtc->config.cpu_transcoder; |
uint32_t val; |
|
val = 0; |
|
if (intel_crtc->config.dither) |
if (IS_HASWELL(dev) && intel_crtc->config.dither) |
val |= (PIPECONF_DITHER_EN | PIPECONF_DITHER_TYPE_SP); |
|
if (intel_crtc->config.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE) |
5635,8 → 6088,35 |
|
I915_WRITE(GAMMA_MODE(intel_crtc->pipe), GAMMA_MODE_MODE_8BIT); |
POSTING_READ(GAMMA_MODE(intel_crtc->pipe)); |
|
if (IS_BROADWELL(dev)) { |
val = 0; |
|
switch (intel_crtc->config.pipe_bpp) { |
case 18: |
val |= PIPEMISC_DITHER_6_BPC; |
break; |
case 24: |
val |= PIPEMISC_DITHER_8_BPC; |
break; |
case 30: |
val |= PIPEMISC_DITHER_10_BPC; |
break; |
case 36: |
val |= PIPEMISC_DITHER_12_BPC; |
break; |
default: |
/* Case prevented by pipe_config_set_bpp. */ |
BUG(); |
} |
|
if (intel_crtc->config.dither) |
val |= PIPEMISC_DITHER_ENABLE | PIPEMISC_DITHER_TYPE_SP; |
|
I915_WRITE(PIPEMISC(pipe), val); |
} |
} |
|
static bool ironlake_compute_clocks(struct drm_crtc *crtc, |
intel_clock_t *clock, |
bool *has_reduced_clock, |
5734,7 → 6214,7 |
factor = 21; |
if (is_lvds) { |
if ((intel_panel_use_ssc(dev_priv) && |
dev_priv->vbt.lvds_ssc_freq == 100) || |
dev_priv->vbt.lvds_ssc_freq == 100000) || |
(HAS_PCH_IBX(dev) && intel_is_dual_link_lvds(dev))) |
factor = 25; |
} else if (intel_crtc->config.sdvo_tv_clock) |
5869,11 → 6349,6 |
else |
intel_crtc->lowfreq_avail = false; |
|
if (intel_crtc->config.has_pch_encoder) { |
pll = intel_crtc_to_shared_dpll(intel_crtc); |
|
} |
|
intel_set_pipe_timings(intel_crtc); |
|
if (intel_crtc->config.has_pch_encoder) { |
5889,27 → 6364,69 |
|
ret = intel_pipe_set_base(crtc, x, y, fb); |
|
intel_update_watermarks(dev); |
|
return ret; |
} |
|
static void ironlake_get_fdi_m_n_config(struct intel_crtc *crtc, |
struct intel_crtc_config *pipe_config) |
static void intel_pch_transcoder_get_m_n(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 = pipe_config->cpu_transcoder; |
enum pipe pipe = crtc->pipe; |
|
pipe_config->fdi_m_n.link_m = I915_READ(PIPE_LINK_M1(transcoder)); |
pipe_config->fdi_m_n.link_n = I915_READ(PIPE_LINK_N1(transcoder)); |
pipe_config->fdi_m_n.gmch_m = I915_READ(PIPE_DATA_M1(transcoder)) |
m_n->link_m = I915_READ(PCH_TRANS_LINK_M1(pipe)); |
m_n->link_n = I915_READ(PCH_TRANS_LINK_N1(pipe)); |
m_n->gmch_m = I915_READ(PCH_TRANS_DATA_M1(pipe)) |
& ~TU_SIZE_MASK; |
pipe_config->fdi_m_n.gmch_n = I915_READ(PIPE_DATA_N1(transcoder)); |
pipe_config->fdi_m_n.tu = ((I915_READ(PIPE_DATA_M1(transcoder)) |
m_n->gmch_n = I915_READ(PCH_TRANS_DATA_N1(pipe)); |
m_n->tu = ((I915_READ(PCH_TRANS_DATA_M1(pipe)) |
& TU_SIZE_MASK) >> TU_SIZE_SHIFT) + 1; |
} |
|
static void intel_cpu_transcoder_get_m_n(struct intel_crtc *crtc, |
enum transcoder transcoder, |
struct intel_link_m_n *m_n) |
{ |
struct drm_device *dev = crtc->base.dev; |
struct drm_i915_private *dev_priv = dev->dev_private; |
enum pipe pipe = crtc->pipe; |
|
if (INTEL_INFO(dev)->gen >= 5) { |
m_n->link_m = I915_READ(PIPE_LINK_M1(transcoder)); |
m_n->link_n = I915_READ(PIPE_LINK_N1(transcoder)); |
m_n->gmch_m = I915_READ(PIPE_DATA_M1(transcoder)) |
& ~TU_SIZE_MASK; |
m_n->gmch_n = I915_READ(PIPE_DATA_N1(transcoder)); |
m_n->tu = ((I915_READ(PIPE_DATA_M1(transcoder)) |
& TU_SIZE_MASK) >> TU_SIZE_SHIFT) + 1; |
} else { |
m_n->link_m = I915_READ(PIPE_LINK_M_G4X(pipe)); |
m_n->link_n = I915_READ(PIPE_LINK_N_G4X(pipe)); |
m_n->gmch_m = I915_READ(PIPE_DATA_M_G4X(pipe)) |
& ~TU_SIZE_MASK; |
m_n->gmch_n = I915_READ(PIPE_DATA_N_G4X(pipe)); |
m_n->tu = ((I915_READ(PIPE_DATA_M_G4X(pipe)) |
& TU_SIZE_MASK) >> TU_SIZE_SHIFT) + 1; |
} |
} |
|
void intel_dp_get_m_n(struct intel_crtc *crtc, |
struct intel_crtc_config *pipe_config) |
{ |
if (crtc->config.has_pch_encoder) |
intel_pch_transcoder_get_m_n(crtc, &pipe_config->dp_m_n); |
else |
intel_cpu_transcoder_get_m_n(crtc, pipe_config->cpu_transcoder, |
&pipe_config->dp_m_n); |
} |
|
static void ironlake_get_fdi_m_n_config(struct intel_crtc *crtc, |
struct intel_crtc_config *pipe_config) |
{ |
intel_cpu_transcoder_get_m_n(crtc, pipe_config->cpu_transcoder, |
&pipe_config->fdi_m_n); |
} |
|
static void ironlake_get_pfit_config(struct intel_crtc *crtc, |
struct intel_crtc_config *pipe_config) |
{ |
5996,6 → 6513,8 |
pipe_config->pixel_multiplier = |
((tmp & PLL_REF_SDVO_HDMI_MULTIPLIER_MASK) |
>> PLL_REF_SDVO_HDMI_MULTIPLIER_SHIFT) + 1; |
|
ironlake_pch_clock_get(crtc, pipe_config); |
} else { |
pipe_config->pixel_multiplier = 1; |
} |
6036,7 → 6555,7 |
|
spin_lock_irqsave(&dev_priv->irq_lock, irqflags); |
val = I915_READ(DEIMR); |
WARN((val & ~DE_PCH_EVENT_IVB) != val, |
WARN((val | DE_PCH_EVENT_IVB) != 0xffffffff, |
"Unexpected DEIMR bits enabled: 0x%x\n", val); |
val = I915_READ(SDEIMR); |
WARN((val | SDE_HOTPLUG_MASK_CPT) != 0xffffffff, |
6052,7 → 6571,7 |
* register. Callers should take care of disabling all the display engine |
* functions, doing the mode unset, fixing interrupts, etc. |
*/ |
void hsw_disable_lcpll(struct drm_i915_private *dev_priv, |
static void hsw_disable_lcpll(struct drm_i915_private *dev_priv, |
bool switch_to_fclk, bool allow_power_down) |
{ |
uint32_t val; |
6081,9 → 6600,12 |
|
val = I915_READ(D_COMP); |
val |= D_COMP_COMP_DISABLE; |
I915_WRITE(D_COMP, val); |
mutex_lock(&dev_priv->rps.hw_lock); |
if (sandybridge_pcode_write(dev_priv, GEN6_PCODE_WRITE_D_COMP, val)) |
DRM_ERROR("Failed to disable D_COMP\n"); |
mutex_unlock(&dev_priv->rps.hw_lock); |
POSTING_READ(D_COMP); |
udelay(100); |
delay(1); |
|
if (wait_for((I915_READ(D_COMP) & D_COMP_RCOMP_IN_PROGRESS) == 0, 1)) |
DRM_ERROR("D_COMP RCOMP still in progress\n"); |
6100,7 → 6622,7 |
* Fully restores LCPLL, disallowing power down and switching back to LCPLL |
* source. |
*/ |
void hsw_restore_lcpll(struct drm_i915_private *dev_priv) |
static void hsw_restore_lcpll(struct drm_i915_private *dev_priv) |
{ |
uint32_t val; |
|
6112,7 → 6634,7 |
|
/* Make sure we're not on PC8 state before disabling PC8, otherwise |
* we'll hang the machine! */ |
gen6_gt_force_wake_get(dev_priv); |
gen6_gt_force_wake_get(dev_priv, FORCEWAKE_ALL); |
|
if (val & LCPLL_POWER_DOWN_ALLOW) { |
val &= ~LCPLL_POWER_DOWN_ALLOW; |
6123,7 → 6645,10 |
val = I915_READ(D_COMP); |
val |= D_COMP_COMP_FORCE; |
val &= ~D_COMP_COMP_DISABLE; |
I915_WRITE(D_COMP, val); |
mutex_lock(&dev_priv->rps.hw_lock); |
if (sandybridge_pcode_write(dev_priv, GEN6_PCODE_WRITE_D_COMP, val)) |
DRM_ERROR("Failed to enable D_COMP\n"); |
mutex_unlock(&dev_priv->rps.hw_lock); |
POSTING_READ(D_COMP); |
|
val = I915_READ(LCPLL_CTL); |
6143,7 → 6668,7 |
DRM_ERROR("Switching back to LCPLL failed\n"); |
} |
|
gen6_gt_force_wake_put(dev_priv); |
gen6_gt_force_wake_put(dev_priv, FORCEWAKE_ALL); |
} |
|
void hsw_enable_pc8_work(struct work_struct *__work) |
6154,6 → 6679,8 |
struct drm_device *dev = dev_priv->dev; |
uint32_t val; |
|
WARN_ON(!HAS_PC8(dev)); |
|
if (dev_priv->pc8.enabled) |
return; |
|
6170,6 → 6697,8 |
lpt_disable_clkout_dp(dev); |
hsw_pc8_disable_interrupts(dev); |
hsw_disable_lcpll(dev_priv, true, true); |
|
intel_runtime_pm_put(dev_priv); |
} |
|
static void __hsw_enable_package_c8(struct drm_i915_private *dev_priv) |
6199,6 → 6728,8 |
if (dev_priv->pc8.disable_count != 1) |
return; |
|
WARN_ON(!HAS_PC8(dev)); |
|
cancel_delayed_work_sync(&dev_priv->pc8.enable_work); |
if (!dev_priv->pc8.enabled) |
return; |
6205,6 → 6736,8 |
|
DRM_DEBUG_KMS("Disabling package C8+\n"); |
|
intel_runtime_pm_get(dev_priv); |
|
hsw_restore_lcpll(dev_priv); |
hsw_pc8_restore_interrupts(dev); |
lpt_init_pch_refclk(dev); |
6225,6 → 6758,9 |
|
void hsw_enable_package_c8(struct drm_i915_private *dev_priv) |
{ |
if (!HAS_PC8(dev_priv->dev)) |
return; |
|
mutex_lock(&dev_priv->pc8.lock); |
__hsw_enable_package_c8(dev_priv); |
mutex_unlock(&dev_priv->pc8.lock); |
6232,6 → 6768,9 |
|
void hsw_disable_package_c8(struct drm_i915_private *dev_priv) |
{ |
if (!HAS_PC8(dev_priv->dev)) |
return; |
|
mutex_lock(&dev_priv->pc8.lock); |
__hsw_disable_package_c8(dev_priv); |
mutex_unlock(&dev_priv->pc8.lock); |
6269,6 → 6808,9 |
struct drm_i915_private *dev_priv = dev->dev_private; |
bool allow; |
|
if (!HAS_PC8(dev_priv->dev)) |
return; |
|
if (!i915_enable_pc8) |
return; |
|
6292,36 → 6834,103 |
|
static void hsw_package_c8_gpu_idle(struct drm_i915_private *dev_priv) |
{ |
if (!HAS_PC8(dev_priv->dev)) |
return; |
|
mutex_lock(&dev_priv->pc8.lock); |
if (!dev_priv->pc8.gpu_idle) { |
dev_priv->pc8.gpu_idle = true; |
hsw_enable_package_c8(dev_priv); |
__hsw_enable_package_c8(dev_priv); |
} |
mutex_unlock(&dev_priv->pc8.lock); |
} |
|
static void hsw_package_c8_gpu_busy(struct drm_i915_private *dev_priv) |
{ |
if (!HAS_PC8(dev_priv->dev)) |
return; |
|
mutex_lock(&dev_priv->pc8.lock); |
if (dev_priv->pc8.gpu_idle) { |
dev_priv->pc8.gpu_idle = false; |
hsw_disable_package_c8(dev_priv); |
__hsw_disable_package_c8(dev_priv); |
} |
mutex_unlock(&dev_priv->pc8.lock); |
} |
|
static void haswell_modeset_global_resources(struct drm_device *dev) |
#define for_each_power_domain(domain, mask) \ |
for ((domain) = 0; (domain) < POWER_DOMAIN_NUM; (domain)++) \ |
if ((1 << (domain)) & (mask)) |
|
static unsigned long get_pipe_power_domains(struct drm_device *dev, |
enum pipe pipe, bool pfit_enabled) |
{ |
bool enable = false; |
unsigned long mask; |
enum transcoder transcoder; |
|
transcoder = intel_pipe_to_cpu_transcoder(dev->dev_private, pipe); |
|
mask = BIT(POWER_DOMAIN_PIPE(pipe)); |
mask |= BIT(POWER_DOMAIN_TRANSCODER(transcoder)); |
if (pfit_enabled) |
mask |= BIT(POWER_DOMAIN_PIPE_PANEL_FITTER(pipe)); |
|
return mask; |
} |
|
void intel_display_set_init_power(struct drm_device *dev, bool enable) |
{ |
struct drm_i915_private *dev_priv = dev->dev_private; |
|
if (dev_priv->power_domains.init_power_on == enable) |
return; |
|
if (enable) |
intel_display_power_get(dev, POWER_DOMAIN_INIT); |
else |
intel_display_power_put(dev, POWER_DOMAIN_INIT); |
|
dev_priv->power_domains.init_power_on = enable; |
} |
|
static void modeset_update_power_wells(struct drm_device *dev) |
{ |
unsigned long pipe_domains[I915_MAX_PIPES] = { 0, }; |
struct intel_crtc *crtc; |
|
/* |
* First get all needed power domains, then put all unneeded, to avoid |
* any unnecessary toggling of the power wells. |
*/ |
list_for_each_entry(crtc, &dev->mode_config.crtc_list, base.head) { |
enum intel_display_power_domain domain; |
|
if (!crtc->base.enabled) |
continue; |
|
if (crtc->pipe != PIPE_A || crtc->config.pch_pfit.enabled || |
crtc->config.cpu_transcoder != TRANSCODER_EDP) |
enable = true; |
pipe_domains[crtc->pipe] = get_pipe_power_domains(dev, |
crtc->pipe, |
crtc->config.pch_pfit.enabled); |
|
for_each_power_domain(domain, pipe_domains[crtc->pipe]) |
intel_display_power_get(dev, domain); |
} |
|
intel_set_power_well(dev, enable); |
list_for_each_entry(crtc, &dev->mode_config.crtc_list, base.head) { |
enum intel_display_power_domain domain; |
|
for_each_power_domain(domain, crtc->enabled_power_domains) |
intel_display_power_put(dev, domain); |
|
crtc->enabled_power_domains = pipe_domains[crtc->pipe]; |
} |
|
intel_display_set_init_power(dev, false); |
} |
|
static void haswell_modeset_global_resources(struct drm_device *dev) |
{ |
modeset_update_power_wells(dev); |
hsw_update_package_c8(dev); |
} |
|
6335,8 → 6944,9 |
int plane = intel_crtc->plane; |
int ret; |
|
if (!intel_ddi_pll_mode_set(crtc)) |
if (!intel_ddi_pll_select(intel_crtc)) |
return -EINVAL; |
intel_ddi_pll_enable(intel_crtc); |
|
if (intel_crtc->config.has_dp_encoder) |
intel_dp_set_m_n(intel_crtc); |
6360,8 → 6970,6 |
|
ret = intel_pipe_set_base(crtc, x, y, fb); |
|
intel_update_watermarks(dev); |
|
return ret; |
} |
|
6429,6 → 7037,7 |
if (intel_display_power_enabled(dev, pfit_domain)) |
ironlake_get_pfit_config(crtc, pipe_config); |
|
if (IS_HASWELL(dev)) |
pipe_config->ips_enabled = hsw_crtc_supports_ips(crtc) && |
(I915_READ(IPS_CTL) & IPS_ENABLE); |
|
6469,6 → 7078,44 |
return 0; |
} |
|
static struct { |
int clock; |
u32 config; |
} hdmi_audio_clock[] = { |
{ DIV_ROUND_UP(25200 * 1000, 1001), AUD_CONFIG_PIXEL_CLOCK_HDMI_25175 }, |
{ 25200, AUD_CONFIG_PIXEL_CLOCK_HDMI_25200 }, /* default per bspec */ |
{ 27000, AUD_CONFIG_PIXEL_CLOCK_HDMI_27000 }, |
{ 27000 * 1001 / 1000, AUD_CONFIG_PIXEL_CLOCK_HDMI_27027 }, |
{ 54000, AUD_CONFIG_PIXEL_CLOCK_HDMI_54000 }, |
{ 54000 * 1001 / 1000, AUD_CONFIG_PIXEL_CLOCK_HDMI_54054 }, |
{ DIV_ROUND_UP(74250 * 1000, 1001), AUD_CONFIG_PIXEL_CLOCK_HDMI_74176 }, |
{ 74250, AUD_CONFIG_PIXEL_CLOCK_HDMI_74250 }, |
{ DIV_ROUND_UP(148500 * 1000, 1001), AUD_CONFIG_PIXEL_CLOCK_HDMI_148352 }, |
{ 148500, AUD_CONFIG_PIXEL_CLOCK_HDMI_148500 }, |
}; |
|
/* get AUD_CONFIG_PIXEL_CLOCK_HDMI_* value for mode */ |
static u32 audio_config_hdmi_pixel_clock(struct drm_display_mode *mode) |
{ |
int i; |
|
for (i = 0; i < ARRAY_SIZE(hdmi_audio_clock); i++) { |
if (mode->clock == hdmi_audio_clock[i].clock) |
break; |
} |
|
if (i == ARRAY_SIZE(hdmi_audio_clock)) { |
DRM_DEBUG_KMS("HDMI audio pixel clock setting for %d not found, falling back to defaults\n", mode->clock); |
i = 1; |
} |
|
DRM_DEBUG_KMS("Configuring HDMI audio for pixel clock %d (0x%08x)\n", |
hdmi_audio_clock[i].clock, |
hdmi_audio_clock[i].config); |
|
return hdmi_audio_clock[i].config; |
} |
|
static bool intel_eld_uptodate(struct drm_connector *connector, |
int reg_eldv, uint32_t bits_eldv, |
int reg_elda, uint32_t bits_elda, |
6499,7 → 7146,8 |
} |
|
static void g4x_write_eld(struct drm_connector *connector, |
struct drm_crtc *crtc) |
struct drm_crtc *crtc, |
struct drm_display_mode *mode) |
{ |
struct drm_i915_private *dev_priv = connector->dev->dev_private; |
uint8_t *eld = connector->eld; |
6539,7 → 7187,8 |
} |
|
static void haswell_write_eld(struct drm_connector *connector, |
struct drm_crtc *crtc) |
struct drm_crtc *crtc, |
struct drm_display_mode *mode) |
{ |
struct drm_i915_private *dev_priv = connector->dev->dev_private; |
uint8_t *eld = connector->eld; |
6592,8 → 7241,9 |
DRM_DEBUG_DRIVER("ELD: DisplayPort detected\n"); |
eld[5] |= (1 << 2); /* Conn_Type, 0x1 = DisplayPort */ |
I915_WRITE(aud_config, AUD_CONFIG_N_VALUE_INDEX); /* 0x1 = DP */ |
} else |
I915_WRITE(aud_config, 0); |
} else { |
I915_WRITE(aud_config, audio_config_hdmi_pixel_clock(mode)); |
} |
|
if (intel_eld_uptodate(connector, |
aud_cntrl_st2, eldv, |
6626,7 → 7276,8 |
} |
|
static void ironlake_write_eld(struct drm_connector *connector, |
struct drm_crtc *crtc) |
struct drm_crtc *crtc, |
struct drm_display_mode *mode) |
{ |
struct drm_i915_private *dev_priv = connector->dev->dev_private; |
uint8_t *eld = connector->eld; |
6644,6 → 7295,11 |
aud_config = IBX_AUD_CFG(pipe); |
aud_cntl_st = IBX_AUD_CNTL_ST(pipe); |
aud_cntrl_st2 = IBX_AUD_CNTL_ST2; |
} else if (IS_VALLEYVIEW(connector->dev)) { |
hdmiw_hdmiedid = VLV_HDMIW_HDMIEDID(pipe); |
aud_config = VLV_AUD_CFG(pipe); |
aud_cntl_st = VLV_AUD_CNTL_ST(pipe); |
aud_cntrl_st2 = VLV_AUD_CNTL_ST2; |
} else { |
hdmiw_hdmiedid = CPT_HDMIW_HDMIEDID(pipe); |
aud_config = CPT_AUD_CFG(pipe); |
6653,8 → 7309,19 |
|
DRM_DEBUG_DRIVER("ELD on pipe %c\n", pipe_name(pipe)); |
|
if (IS_VALLEYVIEW(connector->dev)) { |
struct intel_encoder *intel_encoder; |
struct intel_digital_port *intel_dig_port; |
|
intel_encoder = intel_attached_encoder(connector); |
intel_dig_port = enc_to_dig_port(&intel_encoder->base); |
i = intel_dig_port->port; |
} else { |
i = I915_READ(aud_cntl_st); |
i = (i >> 29) & DIP_PORT_SEL_MASK; /* DIP_Port_Select, 0x1 = PortB */ |
i = (i >> 29) & DIP_PORT_SEL_MASK; |
/* DIP_Port_Select, 0x1 = PortB */ |
} |
|
if (!i) { |
DRM_DEBUG_DRIVER("Audio directed to unknown port\n"); |
/* operate blindly on all ports */ |
6670,8 → 7337,9 |
DRM_DEBUG_DRIVER("ELD: DisplayPort detected\n"); |
eld[5] |= (1 << 2); /* Conn_Type, 0x1 = DisplayPort */ |
I915_WRITE(aud_config, AUD_CONFIG_N_VALUE_INDEX); /* 0x1 = DP */ |
} else |
I915_WRITE(aud_config, 0); |
} else { |
I915_WRITE(aud_config, audio_config_hdmi_pixel_clock(mode)); |
} |
|
if (intel_eld_uptodate(connector, |
aud_cntrl_st2, eldv, |
6721,53 → 7389,9 |
connector->eld[6] = drm_av_sync_delay(connector, mode) / 2; |
|
if (dev_priv->display.write_eld) |
dev_priv->display.write_eld(connector, crtc); |
dev_priv->display.write_eld(connector, crtc, mode); |
} |
|
/** Loads the palette/gamma unit for the CRTC with the prepared values */ |
void intel_crtc_load_lut(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); |
enum pipe pipe = intel_crtc->pipe; |
int palreg = PALETTE(pipe); |
int i; |
bool reenable_ips = false; |
|
/* The clocks have to be on to load the palette. */ |
if (!crtc->enabled || !intel_crtc->active) |
return; |
|
if (!HAS_PCH_SPLIT(dev_priv->dev)) |
assert_pll_enabled(dev_priv, pipe); |
|
/* use legacy palette for Ironlake */ |
if (HAS_PCH_SPLIT(dev)) |
palreg = LGC_PALETTE(pipe); |
|
/* Workaround : Do not read or write the pipe palette/gamma data while |
* GAMMA_MODE is configured for split gamma and IPS_CTL has IPS enabled. |
*/ |
if (intel_crtc->config.ips_enabled && |
((I915_READ(GAMMA_MODE(pipe)) & GAMMA_MODE_MODE_MASK) == |
GAMMA_MODE_MODE_SPLIT)) { |
hsw_disable_ips(intel_crtc); |
reenable_ips = true; |
} |
|
for (i = 0; i < 256; i++) { |
I915_WRITE(palreg + 4 * i, |
(intel_crtc->lut_r[i] << 16) | |
(intel_crtc->lut_g[i] << 8) | |
intel_crtc->lut_b[i]); |
} |
|
if (reenable_ips) |
hsw_enable_ips(intel_crtc); |
} |
|
#if 0 |
static void i845_update_cursor(struct drm_crtc *crtc, u32 base) |
{ |
struct drm_device *dev = crtc->dev; |
6797,7 → 7421,6 |
|
intel_crtc->cursor_visible = visible; |
} |
#endif |
|
static void i9xx_update_cursor(struct drm_crtc *crtc, u32 base) |
{ |
6844,7 → 7467,7 |
cntl &= ~(CURSOR_MODE | MCURSOR_GAMMA_ENABLE); |
cntl |= CURSOR_MODE_DISABLE; |
} |
if (IS_HASWELL(dev)) { |
if (IS_HASWELL(dev) || IS_BROADWELL(dev)) { |
cntl |= CURSOR_PIPE_CSC_ENABLE; |
cntl &= ~CURSOR_TRICKLE_FEED_DISABLE; |
} |
6868,23 → 7491,20 |
int pipe = intel_crtc->pipe; |
int x = intel_crtc->cursor_x; |
int y = intel_crtc->cursor_y; |
u32 base, pos; |
u32 base = 0, pos = 0; |
bool visible; |
|
pos = 0; |
if (on) |
base = intel_crtc->cursor_addr; |
|
if (on && crtc->enabled && crtc->fb) { |
base = intel_crtc->cursor_addr; |
if (x > (int) crtc->fb->width) |
if (x >= intel_crtc->config.pipe_src_w) |
base = 0; |
|
if (y > (int) crtc->fb->height) |
if (y >= intel_crtc->config.pipe_src_h) |
base = 0; |
} else |
base = 0; |
|
if (x < 0) { |
if (x + intel_crtc->cursor_width < 0) |
if (x + intel_crtc->cursor_width <= 0) |
base = 0; |
|
pos |= CURSOR_POS_SIGN << CURSOR_X_SHIFT; |
6893,7 → 7513,7 |
pos |= x << CURSOR_X_SHIFT; |
|
if (y < 0) { |
if (y + intel_crtc->cursor_height < 0) |
if (y + intel_crtc->cursor_height <= 0) |
base = 0; |
|
pos |= CURSOR_POS_SIGN << CURSOR_Y_SHIFT; |
6905,7 → 7525,7 |
if (!visible && !intel_crtc->cursor_visible) |
return; |
|
if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev)) { |
if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev) || IS_BROADWELL(dev)) { |
I915_WRITE(CURPOS_IVB(pipe), pos); |
ivb_update_cursor(crtc, base); |
} else { |
7035,8 → 7655,8 |
{ |
struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
|
intel_crtc->cursor_x = x; |
intel_crtc->cursor_y = y; |
intel_crtc->cursor_x = clamp_t(int, x, SHRT_MIN, SHRT_MAX); |
intel_crtc->cursor_y = clamp_t(int, y, SHRT_MIN, SHRT_MAX); |
|
if (intel_crtc->active) |
intel_crtc_update_cursor(crtc, intel_crtc->cursor_bo != NULL); |
7044,27 → 7664,6 |
return 0; |
} |
|
/** Sets the color ramps on behalf of RandR */ |
void intel_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green, |
u16 blue, int regno) |
{ |
struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
|
intel_crtc->lut_r[regno] = red >> 8; |
intel_crtc->lut_g[regno] = green >> 8; |
intel_crtc->lut_b[regno] = blue >> 8; |
} |
|
void intel_crtc_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green, |
u16 *blue, int regno) |
{ |
struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
|
*red = intel_crtc->lut_r[regno] << 8; |
*green = intel_crtc->lut_g[regno] << 8; |
*blue = intel_crtc->lut_b[regno] << 8; |
} |
|
static void intel_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green, |
u16 *blue, uint32_t start, uint32_t size) |
{ |
7086,7 → 7685,7 |
704, 832, 0, 480, 489, 491, 520, 0, DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC), |
}; |
|
static struct drm_framebuffer * |
struct drm_framebuffer * |
intel_framebuffer_create(struct drm_device *dev, |
struct drm_mode_fb_cmd2 *mode_cmd, |
struct drm_i915_gem_object *obj) |
7100,16 → 7699,23 |
return ERR_PTR(-ENOMEM); |
} |
|
ret = i915_mutex_lock_interruptible(dev); |
if (ret) |
goto err; |
|
ret = intel_framebuffer_init(dev, intel_fb, mode_cmd, obj); |
if (ret) { |
mutex_unlock(&dev->struct_mutex); |
if (ret) |
goto err; |
|
return &intel_fb->base; |
err: |
drm_gem_object_unreference_unlocked(&obj->base); |
kfree(intel_fb); |
|
return ERR_PTR(ret); |
} |
|
return &intel_fb->base; |
} |
|
static u32 |
intel_framebuffer_pitch_for_width(int width, int bpp) |
{ |
7139,6 → 7745,7 |
mode_fits_in_fbdev(struct drm_device *dev, |
struct drm_display_mode *mode) |
{ |
#ifdef CONFIG_DRM_I915_FBDEV |
struct drm_i915_private *dev_priv = dev->dev_private; |
struct drm_i915_gem_object *obj; |
struct drm_framebuffer *fb; |
7159,6 → 7766,9 |
return NULL; |
|
return fb; |
#else |
return NULL; |
#endif |
} |
|
bool intel_get_load_detect_pipe(struct drm_connector *connector, |
7302,6 → 7912,22 |
mutex_unlock(&crtc->mutex); |
} |
|
static int i9xx_pll_refclk(struct drm_device *dev, |
const struct intel_crtc_config *pipe_config) |
{ |
struct drm_i915_private *dev_priv = dev->dev_private; |
u32 dpll = pipe_config->dpll_hw_state.dpll; |
|
if ((dpll & PLL_REF_INPUT_MASK) == PLLB_REF_INPUT_SPREADSPECTRUMIN) |
return dev_priv->vbt.lvds_ssc_freq; |
else if (HAS_PCH_SPLIT(dev)) |
return 120000; |
else if (!IS_GEN2(dev)) |
return 96000; |
else |
return 48000; |
} |
|
/* Returns the clock of the currently programmed mode of the given pipe. */ |
static void i9xx_crtc_clock_get(struct intel_crtc *crtc, |
struct intel_crtc_config *pipe_config) |
7309,14 → 7935,15 |
struct drm_device *dev = crtc->base.dev; |
struct drm_i915_private *dev_priv = dev->dev_private; |
int pipe = pipe_config->cpu_transcoder; |
u32 dpll = I915_READ(DPLL(pipe)); |
u32 dpll = pipe_config->dpll_hw_state.dpll; |
u32 fp; |
intel_clock_t clock; |
int refclk = i9xx_pll_refclk(dev, pipe_config); |
|
if ((dpll & DISPLAY_RATE_SELECT_FPA1) == 0) |
fp = I915_READ(FP0(pipe)); |
fp = pipe_config->dpll_hw_state.fp0; |
else |
fp = I915_READ(FP1(pipe)); |
fp = pipe_config->dpll_hw_state.fp1; |
|
clock.m1 = (fp & FP_M1_DIV_MASK) >> FP_M1_DIV_SHIFT; |
if (IS_PINEVIEW(dev)) { |
7347,28 → 7974,25 |
default: |
DRM_DEBUG_KMS("Unknown DPLL mode %08x in programmed " |
"mode\n", (int)(dpll & DPLL_MODE_MASK)); |
pipe_config->adjusted_mode.clock = 0; |
return; |
} |
|
if (IS_PINEVIEW(dev)) |
pineview_clock(96000, &clock); |
pineview_clock(refclk, &clock); |
else |
i9xx_clock(96000, &clock); |
i9xx_clock(refclk, &clock); |
} else { |
bool is_lvds = (pipe == 1) && (I915_READ(LVDS) & LVDS_PORT_EN); |
u32 lvds = IS_I830(dev) ? 0 : I915_READ(LVDS); |
bool is_lvds = (pipe == 1) && (lvds & LVDS_PORT_EN); |
|
if (is_lvds) { |
clock.p1 = ffs((dpll & DPLL_FPA01_P1_POST_DIV_MASK_I830_LVDS) >> |
DPLL_FPA01_P1_POST_DIV_SHIFT); |
|
if (lvds & LVDS_CLKB_POWER_UP) |
clock.p2 = 7; |
else |
clock.p2 = 14; |
|
if ((dpll & PLL_REF_INPUT_MASK) == |
PLLB_REF_INPUT_SPREADSPECTRUMIN) { |
/* XXX: might not be 66MHz */ |
i9xx_clock(66000, &clock); |
} else |
i9xx_clock(48000, &clock); |
} else { |
if (dpll & PLL_P1_DIVIDE_BY_TWO) |
clock.p1 = 2; |
7380,59 → 8004,55 |
clock.p2 = 4; |
else |
clock.p2 = 2; |
} |
|
i9xx_clock(48000, &clock); |
i9xx_clock(refclk, &clock); |
} |
} |
|
pipe_config->adjusted_mode.clock = clock.dot; |
/* |
* This value includes pixel_multiplier. We will use |
* port_clock to compute adjusted_mode.crtc_clock in the |
* encoder's get_config() function. |
*/ |
pipe_config->port_clock = clock.dot; |
} |
|
static void ironlake_crtc_clock_get(struct intel_crtc *crtc, |
struct intel_crtc_config *pipe_config) |
int intel_dotclock_calculate(int link_freq, |
const 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 cpu_transcoder = pipe_config->cpu_transcoder; |
int link_freq, repeat; |
u64 clock; |
u32 link_m, link_n; |
|
repeat = pipe_config->pixel_multiplier; |
|
/* |
* The calculation for the data clock is: |
* pixel_clock = ((m/n)*(link_clock * nr_lanes * repeat))/bpp |
* pixel_clock = ((m/n)*(link_clock * nr_lanes))/bpp |
* But we want to avoid losing precison if possible, so: |
* pixel_clock = ((m * link_clock * nr_lanes * repeat)/(n*bpp)) |
* pixel_clock = ((m * link_clock * nr_lanes)/(n*bpp)) |
* |
* and the link clock is simpler: |
* link_clock = (m * link_clock * repeat) / n |
* link_clock = (m * link_clock) / n |
*/ |
|
/* |
* We need to get the FDI or DP link clock here to derive |
* the M/N dividers. |
* |
* For FDI, we read it from the BIOS or use a fixed 2.7GHz. |
* For DP, it's either 1.62GHz or 2.7GHz. |
* We do our calculations in 10*MHz since we don't need much precison. |
*/ |
if (pipe_config->has_pch_encoder) |
link_freq = intel_fdi_link_freq(dev) * 10000; |
else |
link_freq = pipe_config->port_clock; |
if (!m_n->link_n) |
return 0; |
|
link_m = I915_READ(PIPE_LINK_M1(cpu_transcoder)); |
link_n = I915_READ(PIPE_LINK_N1(cpu_transcoder)); |
return div_u64((u64)m_n->link_m * link_freq, m_n->link_n); |
} |
|
if (!link_m || !link_n) |
return; |
static void ironlake_pch_clock_get(struct intel_crtc *crtc, |
struct intel_crtc_config *pipe_config) |
{ |
struct drm_device *dev = crtc->base.dev; |
|
clock = ((u64)link_m * (u64)link_freq * (u64)repeat); |
do_div(clock, link_n); |
/* read out port_clock from the DPLL */ |
i9xx_crtc_clock_get(crtc, pipe_config); |
|
pipe_config->adjusted_mode.clock = clock; |
/* |
* This value does not include pixel_multiplier. |
* We will check that port_clock and adjusted_mode.crtc_clock |
* agree once we know their relationship in the encoder's |
* get_config() function. |
*/ |
pipe_config->adjusted_mode.crtc_clock = |
intel_dotclock_calculate(intel_fdi_link_freq(dev) * 10000, |
&pipe_config->fdi_m_n); |
} |
|
/** Returns the currently programmed mode of the given pipe. */ |
7448,6 → 8068,7 |
int hsync = I915_READ(HSYNC(cpu_transcoder)); |
int vtot = I915_READ(VTOTAL(cpu_transcoder)); |
int vsync = I915_READ(VSYNC(cpu_transcoder)); |
enum pipe pipe = intel_crtc->pipe; |
|
mode = kzalloc(sizeof(*mode), GFP_KERNEL); |
if (!mode) |
7460,11 → 8081,14 |
* Note, if LVDS ever uses a non-1 pixel multiplier, we'll need |
* to use a real value here instead. |
*/ |
pipe_config.cpu_transcoder = (enum transcoder) intel_crtc->pipe; |
pipe_config.cpu_transcoder = (enum transcoder) pipe; |
pipe_config.pixel_multiplier = 1; |
pipe_config.dpll_hw_state.dpll = I915_READ(DPLL(pipe)); |
pipe_config.dpll_hw_state.fp0 = I915_READ(FP0(pipe)); |
pipe_config.dpll_hw_state.fp1 = I915_READ(FP1(pipe)); |
i9xx_crtc_clock_get(intel_crtc, &pipe_config); |
|
mode->clock = pipe_config.adjusted_mode.clock; |
mode->clock = pipe_config.port_clock / pipe_config.pixel_multiplier; |
mode->hdisplay = (htot & 0xffff) + 1; |
mode->htotal = ((htot & 0xffff0000) >> 16) + 1; |
mode->hsync_start = (hsync & 0xffff) + 1; |
7570,6 → 8194,9 |
|
intel_decrease_pllclock(crtc); |
} |
|
if (dev_priv->info->gen >= 6) |
gen6_rps_idle(dev->dev_private); |
} |
|
void intel_mark_fb_busy(struct drm_i915_gem_object *obj, |
7757,7 → 8384,7 |
intel_ring_emit(ring, 0); /* aux display base address, unused */ |
|
intel_mark_page_flip_active(intel_crtc); |
intel_ring_advance(ring); |
__intel_ring_advance(ring); |
return 0; |
|
err_unpin: |
7799,7 → 8426,7 |
intel_ring_emit(ring, MI_NOOP); |
|
intel_mark_page_flip_active(intel_crtc); |
intel_ring_advance(ring); |
__intel_ring_advance(ring); |
return 0; |
|
err_unpin: |
7848,7 → 8475,7 |
intel_ring_emit(ring, pf | pipesrc); |
|
intel_mark_page_flip_active(intel_crtc); |
intel_ring_advance(ring); |
__intel_ring_advance(ring); |
return 0; |
|
err_unpin: |
7893,7 → 8520,7 |
intel_ring_emit(ring, pf | pipesrc); |
|
intel_mark_page_flip_active(intel_crtc); |
intel_ring_advance(ring); |
__intel_ring_advance(ring); |
return 0; |
|
err_unpin: |
7961,7 → 8588,8 |
intel_ring_emit(ring, ~(DERRMR_PIPEA_PRI_FLIP_DONE | |
DERRMR_PIPEB_PRI_FLIP_DONE | |
DERRMR_PIPEC_PRI_FLIP_DONE)); |
intel_ring_emit(ring, MI_STORE_REGISTER_MEM(1)); |
intel_ring_emit(ring, MI_STORE_REGISTER_MEM(1) | |
MI_SRM_LRM_GLOBAL_GTT); |
intel_ring_emit(ring, DERRMR); |
intel_ring_emit(ring, ring->scratch.gtt_offset + 256); |
} |
7972,7 → 8600,7 |
intel_ring_emit(ring, (MI_NOOP)); |
|
intel_mark_page_flip_active(intel_crtc); |
intel_ring_advance(ring); |
__intel_ring_advance(ring); |
return 0; |
|
err_unpin: |
8017,7 → 8645,7 |
fb->pitches[0] != crtc->fb->pitches[0])) |
return -EINVAL; |
|
work = kzalloc(sizeof *work, GFP_KERNEL); |
work = kzalloc(sizeof(*work), GFP_KERNEL); |
if (work == NULL) |
return -ENOMEM; |
|
8100,28 → 8728,6 |
.load_lut = intel_crtc_load_lut, |
}; |
|
static bool intel_encoder_crtc_ok(struct drm_encoder *encoder, |
struct drm_crtc *crtc) |
{ |
struct drm_device *dev; |
struct drm_crtc *tmp; |
int crtc_mask = 1; |
|
WARN(!crtc, "checking null crtc?\n"); |
|
dev = crtc->dev; |
|
list_for_each_entry(tmp, &dev->mode_config.crtc_list, head) { |
if (tmp == crtc) |
break; |
crtc_mask <<= 1; |
} |
|
if (encoder->possible_crtcs & crtc_mask) |
return true; |
return false; |
} |
|
/** |
* intel_modeset_update_staged_output_state |
* |
8253,6 → 8859,17 |
return bpp; |
} |
|
static void intel_dump_crtc_timings(const struct drm_display_mode *mode) |
{ |
DRM_DEBUG_KMS("crtc timings: %d %d %d %d %d %d %d %d %d, " |
"type: 0x%x flags: 0x%x\n", |
mode->crtc_clock, |
mode->crtc_hdisplay, mode->crtc_hsync_start, |
mode->crtc_hsync_end, mode->crtc_htotal, |
mode->crtc_vdisplay, mode->crtc_vsync_start, |
mode->crtc_vsync_end, mode->crtc_vtotal, mode->type, mode->flags); |
} |
|
static void intel_dump_pipe_config(struct intel_crtc *crtc, |
struct intel_crtc_config *pipe_config, |
const char *context) |
8269,10 → 8886,19 |
pipe_config->fdi_m_n.gmch_m, pipe_config->fdi_m_n.gmch_n, |
pipe_config->fdi_m_n.link_m, pipe_config->fdi_m_n.link_n, |
pipe_config->fdi_m_n.tu); |
DRM_DEBUG_KMS("dp: %i, gmch_m: %u, gmch_n: %u, link_m: %u, link_n: %u, tu: %u\n", |
pipe_config->has_dp_encoder, |
pipe_config->dp_m_n.gmch_m, pipe_config->dp_m_n.gmch_n, |
pipe_config->dp_m_n.link_m, pipe_config->dp_m_n.link_n, |
pipe_config->dp_m_n.tu); |
DRM_DEBUG_KMS("requested mode:\n"); |
drm_mode_debug_printmodeline(&pipe_config->requested_mode); |
DRM_DEBUG_KMS("adjusted mode:\n"); |
drm_mode_debug_printmodeline(&pipe_config->adjusted_mode); |
intel_dump_crtc_timings(&pipe_config->adjusted_mode); |
DRM_DEBUG_KMS("port clock: %d\n", pipe_config->port_clock); |
DRM_DEBUG_KMS("pipe src size: %dx%d\n", |
pipe_config->pipe_src_w, pipe_config->pipe_src_h); |
DRM_DEBUG_KMS("gmch pfit: control: 0x%08x, ratios: 0x%08x, lvds border: 0x%08x\n", |
pipe_config->gmch_pfit.control, |
pipe_config->gmch_pfit.pgm_ratios, |
8282,6 → 8908,7 |
pipe_config->pch_pfit.size, |
pipe_config->pch_pfit.enabled ? "enabled" : "disabled"); |
DRM_DEBUG_KMS("ips: %i\n", pipe_config->ips_enabled); |
DRM_DEBUG_KMS("double wide: %i\n", pipe_config->double_wide); |
} |
|
static bool check_encoder_cloning(struct drm_crtc *crtc) |
8325,6 → 8952,7 |
|
drm_mode_copy(&pipe_config->adjusted_mode, mode); |
drm_mode_copy(&pipe_config->requested_mode, mode); |
|
pipe_config->cpu_transcoder = |
(enum transcoder) to_intel_crtc(crtc)->pipe; |
pipe_config->shared_dpll = DPLL_ID_PRIVATE; |
8351,6 → 8979,18 |
if (plane_bpp < 0) |
goto fail; |
|
/* |
* Determine the real pipe dimensions. Note that stereo modes can |
* increase the actual pipe size due to the frame doubling and |
* insertion of additional space for blanks between the frame. This |
* is stored in the crtc timings. We use the requested mode to do this |
* computation to clearly distinguish it from the adjusted mode, which |
* can be changed by the connectors in the below retry loop. |
*/ |
drm_mode_set_crtcinfo(&pipe_config->requested_mode, CRTC_STEREO_DOUBLE); |
pipe_config->pipe_src_w = pipe_config->requested_mode.crtc_hdisplay; |
pipe_config->pipe_src_h = pipe_config->requested_mode.crtc_vdisplay; |
|
encoder_retry: |
/* Ensure the port clock defaults are reset when retrying. */ |
pipe_config->port_clock = 0; |
8357,7 → 8997,7 |
pipe_config->pixel_multiplier = 1; |
|
/* Fill in default crtc timings, allow encoders to overwrite them. */ |
drm_mode_set_crtcinfo(&pipe_config->adjusted_mode, 0); |
drm_mode_set_crtcinfo(&pipe_config->adjusted_mode, CRTC_STEREO_DOUBLE); |
|
/* Pass our mode to the connectors and the CRTC to give them a chance to |
* adjust it according to limitations or connector properties, and also |
8378,7 → 9018,8 |
/* Set default port clock if not overwritten by the encoder. Needs to be |
* done afterwards in case the encoder adjusts the mode. */ |
if (!pipe_config->port_clock) |
pipe_config->port_clock = pipe_config->adjusted_mode.clock; |
pipe_config->port_clock = pipe_config->adjusted_mode.crtc_clock |
* pipe_config->pixel_multiplier; |
|
ret = intel_crtc_compute_config(to_intel_crtc(crtc), pipe_config); |
if (ret < 0) { |
8565,14 → 9206,10 |
|
} |
|
static bool intel_fuzzy_clock_check(struct intel_crtc_config *cur, |
struct intel_crtc_config *new) |
static bool intel_fuzzy_clock_check(int clock1, int clock2) |
{ |
int clock1, clock2, diff; |
int diff; |
|
clock1 = cur->adjusted_mode.clock; |
clock2 = new->adjusted_mode.clock; |
|
if (clock1 == clock2) |
return true; |
|
8625,6 → 9262,15 |
return false; \ |
} |
|
#define PIPE_CONF_CHECK_CLOCK_FUZZY(name) \ |
if (!intel_fuzzy_clock_check(current_config->name, pipe_config->name)) { \ |
DRM_ERROR("mismatch in " #name " " \ |
"(expected %i, found %i)\n", \ |
current_config->name, \ |
pipe_config->name); \ |
return false; \ |
} |
|
#define PIPE_CONF_QUIRK(quirk) \ |
((current_config->quirks | pipe_config->quirks) & (quirk)) |
|
8638,6 → 9284,13 |
PIPE_CONF_CHECK_I(fdi_m_n.link_n); |
PIPE_CONF_CHECK_I(fdi_m_n.tu); |
|
PIPE_CONF_CHECK_I(has_dp_encoder); |
PIPE_CONF_CHECK_I(dp_m_n.gmch_m); |
PIPE_CONF_CHECK_I(dp_m_n.gmch_n); |
PIPE_CONF_CHECK_I(dp_m_n.link_m); |
PIPE_CONF_CHECK_I(dp_m_n.link_n); |
PIPE_CONF_CHECK_I(dp_m_n.tu); |
|
PIPE_CONF_CHECK_I(adjusted_mode.crtc_hdisplay); |
PIPE_CONF_CHECK_I(adjusted_mode.crtc_htotal); |
PIPE_CONF_CHECK_I(adjusted_mode.crtc_hblank_start); |
8668,8 → 9321,8 |
DRM_MODE_FLAG_NVSYNC); |
} |
|
PIPE_CONF_CHECK_I(requested_mode.hdisplay); |
PIPE_CONF_CHECK_I(requested_mode.vdisplay); |
PIPE_CONF_CHECK_I(pipe_src_w); |
PIPE_CONF_CHECK_I(pipe_src_h); |
|
PIPE_CONF_CHECK_I(gmch_pfit.control); |
/* pfit ratios are autocomputed by the hw on gen4+ */ |
8682,8 → 9335,12 |
PIPE_CONF_CHECK_I(pch_pfit.size); |
} |
|
/* BDW+ don't expose a synchronous way to read the state */ |
if (IS_HASWELL(dev)) |
PIPE_CONF_CHECK_I(ips_enabled); |
|
PIPE_CONF_CHECK_I(double_wide); |
|
PIPE_CONF_CHECK_I(shared_dpll); |
PIPE_CONF_CHECK_X(dpll_hw_state.dpll); |
PIPE_CONF_CHECK_X(dpll_hw_state.dpll_md); |
8693,20 → 9350,17 |
if (IS_G4X(dev) || INTEL_INFO(dev)->gen >= 5) |
PIPE_CONF_CHECK_I(pipe_bpp); |
|
if (!HAS_DDI(dev)) { |
PIPE_CONF_CHECK_CLOCK_FUZZY(adjusted_mode.crtc_clock); |
PIPE_CONF_CHECK_CLOCK_FUZZY(port_clock); |
} |
|
#undef PIPE_CONF_CHECK_X |
#undef PIPE_CONF_CHECK_I |
#undef PIPE_CONF_CHECK_FLAGS |
#undef PIPE_CONF_CHECK_CLOCK_FUZZY |
#undef PIPE_CONF_QUIRK |
|
if (!IS_HASWELL(dev)) { |
if (!intel_fuzzy_clock_check(current_config, pipe_config)) { |
DRM_ERROR("mismatch in clock (expected %d, found %d)\n", |
current_config->adjusted_mode.clock, |
pipe_config->adjusted_mode.clock); |
return false; |
} |
} |
|
return true; |
} |
|
8833,14 → 9487,10 |
enum pipe pipe; |
if (encoder->base.crtc != &crtc->base) |
continue; |
if (encoder->get_config && |
encoder->get_hw_state(encoder, &pipe)) |
if (encoder->get_hw_state(encoder, &pipe)) |
encoder->get_config(encoder, &pipe_config); |
} |
|
if (dev_priv->display.get_clock) |
dev_priv->display.get_clock(crtc, &pipe_config); |
|
WARN(crtc->active != active, |
"crtc active state doesn't match with hw state " |
"(expected %i, found %i)\n", crtc->active, active); |
8915,6 → 9565,18 |
check_shared_dpll_state(dev); |
} |
|
void ironlake_check_encoder_dotclock(const struct intel_crtc_config *pipe_config, |
int dotclock) |
{ |
/* |
* FDI already provided one idea for the dotclock. |
* Yell if the encoder disagrees. |
*/ |
WARN(!intel_fuzzy_clock_check(pipe_config->adjusted_mode.crtc_clock, dotclock), |
"FDI dotclock and encoder dotclock mismatch, fdi: %i, encoder: %i\n", |
pipe_config->adjusted_mode.crtc_clock, dotclock); |
} |
|
static int __intel_set_mode(struct drm_crtc *crtc, |
struct drm_display_mode *mode, |
int x, int y, struct drm_framebuffer *fb) |
8921,21 → 9583,19 |
{ |
struct drm_device *dev = crtc->dev; |
drm_i915_private_t *dev_priv = dev->dev_private; |
struct drm_display_mode *saved_mode, *saved_hwmode; |
struct drm_display_mode *saved_mode; |
struct intel_crtc_config *pipe_config = NULL; |
struct intel_crtc *intel_crtc; |
unsigned disable_pipes, prepare_pipes, modeset_pipes; |
int ret = 0; |
|
saved_mode = kmalloc(2 * sizeof(*saved_mode), GFP_KERNEL); |
saved_mode = kmalloc(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); |
|
*saved_hwmode = crtc->hwmode; |
*saved_mode = crtc->mode; |
|
/* Hack: Because we don't (yet) support global modeset on multiple |
8955,6 → 9615,21 |
"[modeset]"); |
} |
|
/* |
* See if the config requires any additional preparation, e.g. |
* to adjust global state with pipes off. We need to do this |
* here so we can get the modeset_pipe updated config for the new |
* mode set on this crtc. For other crtcs we need to use the |
* adjusted_mode bits in the crtc directly. |
*/ |
if (IS_VALLEYVIEW(dev)) { |
valleyview_modeset_global_pipes(dev, &prepare_pipes, |
modeset_pipes, pipe_config); |
|
/* may have added more to prepare_pipes than we should */ |
prepare_pipes &= ~disable_pipes; |
} |
|
for_each_intel_crtc_masked(dev, disable_pipes, intel_crtc) |
intel_crtc_disable(&intel_crtc->base); |
|
8971,6 → 9646,14 |
/* mode_set/enable/disable functions rely on a correct pipe |
* config. */ |
to_intel_crtc(crtc)->config = *pipe_config; |
|
/* |
* Calculate and store various constants which |
* are later needed by vblank and swap-completion |
* timestamping. They are derived from true hwmode. |
*/ |
drm_calc_timestamping_constants(crtc, |
&pipe_config->adjusted_mode); |
} |
|
/* Only after disabling all output pipelines that will be changed can we |
8994,23 → 9677,10 |
for_each_intel_crtc_masked(dev, prepare_pipes, intel_crtc) |
dev_priv->display.crtc_enable(&intel_crtc->base); |
|
if (modeset_pipes) { |
/* Store real post-adjustment hardware mode. */ |
crtc->hwmode = pipe_config->adjusted_mode; |
|
/* Calculate and store various constants which |
* are later needed by vblank and swap-completion |
* timestamping. They are derived from true hwmode. |
*/ |
drm_calc_timestamping_constants(crtc); |
} |
|
/* FIXME: add subpixel order */ |
done: |
if (ret && crtc->enabled) { |
crtc->hwmode = *saved_hwmode; |
if (ret && crtc->enabled) |
crtc->mode = *saved_mode; |
} |
|
out: |
kfree(pipe_config); |
9232,7 → 9902,7 |
} |
|
/* Make sure the new CRTC will work with the encoder */ |
if (!intel_encoder_crtc_ok(&connector->new_encoder->base, |
if (!drm_encoder_crtc_ok(&connector->new_encoder->base, |
new_crtc)) { |
return -EINVAL; |
} |
9247,17 → 9917,21 |
/* Check for any encoders that needs to be disabled. */ |
list_for_each_entry(encoder, &dev->mode_config.encoder_list, |
base.head) { |
int num_connectors = 0; |
list_for_each_entry(connector, |
&dev->mode_config.connector_list, |
base.head) { |
if (connector->new_encoder == encoder) { |
WARN_ON(!connector->new_encoder->new_crtc); |
|
goto next_encoder; |
num_connectors++; |
} |
} |
|
if (num_connectors == 0) |
encoder->new_crtc = NULL; |
next_encoder: |
else if (num_connectors > 1) |
return -EINVAL; |
|
/* Only now check for crtc changes so we don't miss encoders |
* that will be disabled. */ |
if (&encoder->new_crtc->base != encoder->base.crtc) { |
9328,6 → 10002,16 |
|
ret = intel_pipe_set_base(set->crtc, |
set->x, set->y, set->fb); |
/* |
* In the fastboot case this may be our only check of the |
* state after boot. It would be better to only do it on |
* the first update, but we don't have a nice way of doing that |
* (and really, set_config isn't used much for high freq page |
* flipping, so increasing its cost here shouldn't be a big |
* deal). |
*/ |
if (i915_fastboot && ret == 0) |
intel_modeset_check_state(set->crtc->dev); |
} |
|
if (ret) { |
9388,7 → 10072,7 |
struct intel_shared_dpll *pll) |
{ |
/* PCH refclock must be enabled first */ |
assert_pch_refclk_enabled(dev_priv); |
ibx_assert_pch_refclk_enabled(dev_priv); |
|
I915_WRITE(PCH_DPLL(pll->id), pll->hw_state.dpll); |
|
9456,8 → 10140,6 |
dev_priv->num_shared_dpll = 0; |
|
BUG_ON(dev_priv->num_shared_dpll > I915_NUM_PLLS); |
DRM_DEBUG_KMS("%i shared PLLs initialized\n", |
dev_priv->num_shared_dpll); |
} |
|
static void intel_crtc_init(struct drm_device *dev, int pipe) |
9466,7 → 10148,7 |
struct intel_crtc *intel_crtc; |
int i; |
|
intel_crtc = kzalloc(sizeof(struct intel_crtc) + (INTELFB_CONN_LIMIT * sizeof(struct drm_connector *)), GFP_KERNEL); |
intel_crtc = kzalloc(sizeof(*intel_crtc), GFP_KERNEL); |
if (intel_crtc == NULL) |
return; |
|
9479,10 → 10161,13 |
intel_crtc->lut_b[i] = i; |
} |
|
/* Swap pipes & planes for FBC on pre-965 */ |
/* |
* On gen2/3 only plane A can do fbc, but the panel fitter and lvds port |
* is hooked to plane B. Hence we want plane A feeding pipe B. |
*/ |
intel_crtc->pipe = pipe; |
intel_crtc->plane = pipe; |
if (IS_MOBILE(dev) && IS_GEN3(dev)) { |
if (HAS_FBC(dev) && INTEL_INFO(dev)->gen < 4) { |
DRM_DEBUG_KMS("swapping pipes & planes for FBC\n"); |
intel_crtc->plane = !pipe; |
} |
9495,6 → 10180,18 |
drm_crtc_helper_add(&intel_crtc->base, &intel_helper_funcs); |
} |
|
enum pipe intel_get_pipe_from_connector(struct intel_connector *connector) |
{ |
struct drm_encoder *encoder = connector->base.encoder; |
|
WARN_ON(!mutex_is_locked(&connector->base.dev->mode_config.mutex)); |
|
if (!encoder) |
return INVALID_PIPE; |
|
return to_intel_crtc(encoder->crtc)->pipe; |
} |
|
int intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data, |
struct drm_file *file) |
{ |
9510,7 → 10207,7 |
|
if (!drmmode_obj) { |
DRM_ERROR("no such CRTC id\n"); |
return -EINVAL; |
return -ENOENT; |
} |
|
crtc = to_intel_crtc(obj_to_crtc(drmmode_obj)); |
9559,6 → 10256,28 |
return true; |
} |
|
const char *intel_output_name(int output) |
{ |
static const char *names[] = { |
[INTEL_OUTPUT_UNUSED] = "Unused", |
[INTEL_OUTPUT_ANALOG] = "Analog", |
[INTEL_OUTPUT_DVO] = "DVO", |
[INTEL_OUTPUT_SDVO] = "SDVO", |
[INTEL_OUTPUT_LVDS] = "LVDS", |
[INTEL_OUTPUT_TVOUT] = "TV", |
[INTEL_OUTPUT_HDMI] = "HDMI", |
[INTEL_OUTPUT_DISPLAYPORT] = "DisplayPort", |
[INTEL_OUTPUT_EDP] = "eDP", |
[INTEL_OUTPUT_DSI] = "DSI", |
[INTEL_OUTPUT_UNKNOWN] = "Unknown", |
}; |
|
if (output < 0 || output >= ARRAY_SIZE(names) || !names[output]) |
return "Invalid"; |
|
return names[output]; |
} |
|
static void intel_setup_outputs(struct drm_device *dev) |
{ |
struct drm_i915_private *dev_priv = dev->dev_private; |
9591,7 → 10310,7 |
intel_ddi_init(dev, PORT_D); |
} else if (HAS_PCH_SPLIT(dev)) { |
int found; |
dpd_is_edp = intel_dpd_is_edp(dev); |
dpd_is_edp = intel_dp_is_edp(dev, PORT_D); |
|
if (has_edp_a(dev)) |
intel_dp_init(dev, DP_A, PORT_A); |
9617,21 → 10336,21 |
if (I915_READ(PCH_DP_D) & DP_DETECTED) |
intel_dp_init(dev, PCH_DP_D, PORT_D); |
} else if (IS_VALLEYVIEW(dev)) { |
/* Check for built-in panel first. Shares lanes with HDMI on SDVOC */ |
if (I915_READ(VLV_DISPLAY_BASE + GEN4_HDMIB) & SDVO_DETECTED) { |
intel_hdmi_init(dev, VLV_DISPLAY_BASE + GEN4_HDMIB, |
PORT_B); |
if (I915_READ(VLV_DISPLAY_BASE + DP_B) & DP_DETECTED) |
intel_dp_init(dev, VLV_DISPLAY_BASE + DP_B, PORT_B); |
} |
|
if (I915_READ(VLV_DISPLAY_BASE + GEN4_HDMIC) & SDVO_DETECTED) { |
intel_hdmi_init(dev, VLV_DISPLAY_BASE + GEN4_HDMIC, |
PORT_C); |
if (I915_READ(VLV_DISPLAY_BASE + DP_C) & DP_DETECTED) |
intel_dp_init(dev, VLV_DISPLAY_BASE + DP_C, |
PORT_C); |
intel_dp_init(dev, VLV_DISPLAY_BASE + DP_C, PORT_C); |
} |
|
if (I915_READ(VLV_DISPLAY_BASE + GEN4_HDMIB) & SDVO_DETECTED) { |
intel_hdmi_init(dev, VLV_DISPLAY_BASE + GEN4_HDMIB, |
PORT_B); |
if (I915_READ(VLV_DISPLAY_BASE + DP_B) & DP_DETECTED) |
intel_dp_init(dev, VLV_DISPLAY_BASE + DP_B, PORT_B); |
} |
intel_dsi_init(dev); |
} else if (SUPPORTS_DIGITAL_OUTPUTS(dev)) { |
bool found = false; |
|
9696,9 → 10415,12 |
struct drm_mode_fb_cmd2 *mode_cmd, |
struct drm_i915_gem_object *obj) |
{ |
int aligned_height, tile_height; |
int pitch_limit; |
int ret; |
|
WARN_ON(!mutex_is_locked(&dev->struct_mutex)); |
|
if (obj->tiling_mode == I915_TILING_Y) { |
DRM_DEBUG("hardware does not support tiling Y\n"); |
return -EINVAL; |
9787,8 → 10509,16 |
if (mode_cmd->offsets[0] != 0) |
return -EINVAL; |
|
tile_height = IS_GEN2(dev) ? 16 : 8; |
aligned_height = ALIGN(mode_cmd->height, |
obj->tiling_mode ? tile_height : 1); |
/* FIXME drm helper for size checks (especially planar formats)? */ |
if (obj->base.size < aligned_height * mode_cmd->pitches[0]) |
return -EINVAL; |
|
drm_helper_mode_fill_fb_struct(&intel_fb->base, mode_cmd); |
intel_fb->obj = obj; |
intel_fb->obj->framebuffer_references++; |
|
ret = drm_framebuffer_init(dev, &intel_fb->base, &intel_fb_funcs); |
if (ret) { |
9799,10 → 10529,15 |
return 0; |
} |
|
#ifndef CONFIG_DRM_I915_FBDEV |
static inline void intel_fbdev_output_poll_changed(struct drm_device *dev) |
{ |
} |
#endif |
|
static const struct drm_mode_config_funcs intel_mode_funcs = { |
.fb_create = NULL /*intel_user_framebuffer_create*/, |
.output_poll_changed = intel_fb_output_poll_changed, |
.fb_create = NULL, |
.output_poll_changed = intel_fbdev_output_poll_changed, |
}; |
|
/* Set up chip specific display functions */ |
9828,7 → 10563,6 |
dev_priv->display.update_plane = ironlake_update_plane; |
} else if (HAS_PCH_SPLIT(dev)) { |
dev_priv->display.get_pipe_config = ironlake_get_pipe_config; |
dev_priv->display.get_clock = ironlake_crtc_clock_get; |
dev_priv->display.crtc_mode_set = ironlake_crtc_mode_set; |
dev_priv->display.crtc_enable = ironlake_crtc_enable; |
dev_priv->display.crtc_disable = ironlake_crtc_disable; |
9836,7 → 10570,6 |
dev_priv->display.update_plane = ironlake_update_plane; |
} else if (IS_VALLEYVIEW(dev)) { |
dev_priv->display.get_pipe_config = i9xx_get_pipe_config; |
dev_priv->display.get_clock = vlv_crtc_clock_get; |
dev_priv->display.crtc_mode_set = i9xx_crtc_mode_set; |
dev_priv->display.crtc_enable = valleyview_crtc_enable; |
dev_priv->display.crtc_disable = i9xx_crtc_disable; |
9844,7 → 10577,6 |
dev_priv->display.update_plane = i9xx_update_plane; |
} else { |
dev_priv->display.get_pipe_config = i9xx_get_pipe_config; |
dev_priv->display.get_clock = i9xx_crtc_clock_get; |
dev_priv->display.crtc_mode_set = i9xx_crtc_mode_set; |
dev_priv->display.crtc_enable = i9xx_crtc_enable; |
dev_priv->display.crtc_disable = i9xx_crtc_disable; |
9894,7 → 10626,7 |
dev_priv->display.write_eld = ironlake_write_eld; |
dev_priv->display.modeset_global_resources = |
ivb_modeset_global_resources; |
} else if (IS_HASWELL(dev)) { |
} else if (IS_HASWELL(dev) || IS_GEN8(dev)) { |
dev_priv->display.fdi_link_train = hsw_fdi_link_train; |
dev_priv->display.write_eld = haswell_write_eld; |
dev_priv->display.modeset_global_resources = |
9902,6 → 10634,10 |
} |
} else if (IS_G4X(dev)) { |
dev_priv->display.write_eld = g4x_write_eld; |
} else if (IS_VALLEYVIEW(dev)) { |
dev_priv->display.modeset_global_resources = |
valleyview_modeset_global_resources; |
dev_priv->display.write_eld = ironlake_write_eld; |
} |
|
/* Default just returns -ENODEV to indicate unsupported */ |
9910,6 → 10646,7 |
|
|
|
intel_panel_init_backlight_funcs(dev); |
} |
|
/* |
9946,17 → 10683,6 |
DRM_INFO("applying inverted panel brightness quirk\n"); |
} |
|
/* |
* Some machines (Dell XPS13) suffer broken backlight controls if |
* BLM_PCH_PWM_ENABLE is set. |
*/ |
static void quirk_no_pcm_pwm_enable(struct drm_device *dev) |
{ |
struct drm_i915_private *dev_priv = dev->dev_private; |
dev_priv->quirks |= QUIRK_NO_PCH_PWM_ENABLE; |
DRM_INFO("applying no-PCH_PWM_ENABLE quirk\n"); |
} |
|
struct intel_quirk { |
int device; |
int subsystem_vendor; |
10002,8 → 10728,7 |
/* ThinkPad T60 needs pipe A force quirk (bug #16494) */ |
{ 0x2782, 0x17aa, 0x201a, quirk_pipea_force }, |
|
/* 830/845 need to leave pipe A & dpll A up */ |
{ 0x2562, PCI_ANY_ID, PCI_ANY_ID, quirk_pipea_force }, |
/* 830 needs to leave pipe A & dpll A up */ |
{ 0x3577, PCI_ANY_ID, PCI_ANY_ID, quirk_pipea_force }, |
|
/* Lenovo U160 cannot use SSC on LVDS */ |
10026,11 → 10751,6 |
|
/* Acer Aspire 4736Z */ |
{ 0x2a42, 0x1025, 0x0260, quirk_invert_brightness }, |
|
/* Dell XPS13 HD Sandy Bridge */ |
{ 0x0116, 0x1028, 0x052e, quirk_no_pcm_pwm_enable }, |
/* Dell XPS13 HD and XPS13 FHD Ivy Bridge */ |
{ 0x0166, 0x1028, 0x058b, quirk_no_pcm_pwm_enable }, |
}; |
|
static void intel_init_quirks(struct drm_device *dev) |
10058,9 → 10778,9 |
u32 vga_reg = i915_vgacntrl_reg(dev); |
|
// vga_get_uninterruptible(dev->pdev, VGA_RSRC_LEGACY_IO); |
out8(SR01, VGA_SR_INDEX); |
sr1 = in8(VGA_SR_DATA); |
out8(sr1 | 1<<5, VGA_SR_DATA); |
outb(SR01, VGA_SR_INDEX); |
sr1 = inb(VGA_SR_DATA); |
outb(sr1 | 1<<5, VGA_SR_DATA); |
// vga_put(dev->pdev, VGA_RSRC_LEGACY_IO); |
udelay(300); |
|
10070,18 → 10790,11 |
|
void intel_modeset_init_hw(struct drm_device *dev) |
{ |
struct drm_i915_private *dev_priv = dev->dev_private; |
|
intel_init_power_well(dev); |
|
intel_prepare_ddi(dev); |
|
intel_init_clock_gating(dev); |
|
/* Enable the CRI clock source so we can get at the display */ |
if (IS_VALLEYVIEW(dev)) |
I915_WRITE(DPLL(PIPE_B), I915_READ(DPLL(PIPE_B)) | |
DPLL_INTEGRATED_CRI_CLK_VLV); |
intel_reset_dpio(dev); |
|
mutex_lock(&dev->struct_mutex); |
intel_enable_gt_powersave(dev); |
10143,6 → 10856,9 |
} |
} |
|
intel_init_dpio(dev); |
intel_reset_dpio(dev); |
|
intel_cpu_pll_init(dev); |
intel_shared_dpll_init(dev); |
|
10346,11 → 11062,11 |
* level, just check if the power well is enabled instead of trying to |
* follow the "don't touch the power well if we don't need it" policy |
* the rest of the driver uses. */ |
if (HAS_POWER_WELL(dev) && |
if ((IS_HASWELL(dev) || IS_BROADWELL(dev)) && |
(I915_READ(HSW_PWR_WELL_DRIVER) & HSW_PWR_WELL_STATE_ENABLED) == 0) |
return; |
|
if (I915_READ(vga_reg) != VGA_DISP_DISABLE) { |
if (!(I915_READ(vga_reg) & VGA_DISP_DISABLE)) { |
DRM_DEBUG_KMS("Something enabled VGA plane, disabling it\n"); |
i915_disable_vga(dev); |
} |
10373,6 → 11089,7 |
&crtc->config); |
|
crtc->base.enabled = crtc->active; |
crtc->primary_enabled = crtc->active; |
|
DRM_DEBUG_KMS("[CRTC:%d] hw state readout: %s\n", |
crtc->base.base.id, |
10406,7 → 11123,6 |
if (encoder->get_hw_state(encoder, &pipe)) { |
crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]); |
encoder->base.crtc = &crtc->base; |
if (encoder->get_config) |
encoder->get_config(encoder, &crtc->config); |
} else { |
encoder->base.crtc = NULL; |
10413,22 → 11129,13 |
} |
|
encoder->connectors_active = false; |
DRM_DEBUG_KMS("[ENCODER:%d:%s] hw state readout: %s, pipe=%i\n", |
DRM_DEBUG_KMS("[ENCODER:%d:%s] hw state readout: %s, pipe %c\n", |
encoder->base.base.id, |
drm_get_encoder_name(&encoder->base), |
encoder->base.crtc ? "enabled" : "disabled", |
pipe); |
pipe_name(pipe)); |
} |
|
list_for_each_entry(crtc, &dev->mode_config.crtc_list, |
base.head) { |
if (!crtc->active) |
continue; |
if (dev_priv->display.get_clock) |
dev_priv->display.get_clock(crtc, |
&crtc->config); |
} |
|
list_for_each_entry(connector, &dev->mode_config.connector_list, |
base.head) { |
if (connector->get_hw_state(connector)) { |
10453,7 → 11160,6 |
{ |
struct drm_i915_private *dev_priv = dev->dev_private; |
enum pipe pipe; |
struct drm_plane *plane; |
struct intel_crtc *crtc; |
struct intel_encoder *encoder; |
int i; |
10500,7 → 11206,12 |
pll->on = false; |
} |
|
if (HAS_PCH_SPLIT(dev)) |
ilk_wm_get_hw_state(dev); |
|
if (force_restore) { |
i915_redisable_vga(dev); |
|
/* |
* We need to use raw interfaces for restoring state to avoid |
* checking (bogus) intermediate states. |
10512,17 → 11223,11 |
__intel_set_mode(crtc, &crtc->mode, crtc->x, crtc->y, |
crtc->fb); |
} |
list_for_each_entry(plane, &dev->mode_config.plane_list, head) |
intel_plane_restore(plane); |
|
i915_redisable_vga(dev); |
} else { |
intel_modeset_update_staged_output_state(dev); |
} |
|
intel_modeset_check_state(dev); |
|
drm_mode_config_reset(dev); |
} |
|
void intel_modeset_gem_init(struct drm_device *dev) |
10532,6 → 11237,7 |
// intel_setup_overlay(dev); |
|
mutex_lock(&dev->mode_config.mutex); |
drm_mode_config_reset(dev); |
intel_modeset_setup_hw_state(dev, false); |
mutex_unlock(&dev->mode_config.mutex); |
} |
10541,6 → 11247,7 |
#if 0 |
struct drm_i915_private *dev_priv = dev->dev_private; |
struct drm_crtc *crtc; |
struct drm_connector *connector; |
|
/* |
* Interrupts and polling as the first thing to avoid creating havoc. |
10553,11 → 11260,11 |
* Due to the hpd irq storm handling the hotplug work can re-arm the |
* poll handlers. Hence disable polling after hpd handling is shut down. |
*/ |
// drm_kms_helper_poll_fini(dev); |
drm_kms_helper_poll_fini(dev); |
|
mutex_lock(&dev->struct_mutex); |
|
// intel_unregister_dsm_handler(); |
intel_unregister_dsm_handler(); |
|
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { |
/* Skip inactive CRTCs */ |
10578,8 → 11285,11 |
/* flush any delayed tasks or pending work */ |
flush_scheduled_work(); |
|
/* destroy backlight, if any, before the connectors */ |
intel_panel_destroy_backlight(dev); |
/* destroy the backlight and sysfs files before encoders/connectors */ |
list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
intel_panel_destroy_backlight(connector); |
drm_sysfs_connector_remove(connector); |
} |
|
drm_mode_config_cleanup(dev); |
#endif |
10620,7 → 11330,6 |
} |
|
#ifdef CONFIG_DEBUG_FS |
#include <linux/seq_file.h> |
|
struct intel_display_error_state { |
|
10636,6 → 11345,7 |
} cursor[I915_MAX_PIPES]; |
|
struct intel_pipe_error_state { |
bool power_domain_on; |
u32 source; |
} pipe[I915_MAX_PIPES]; |
|
10650,6 → 11360,7 |
} plane[I915_MAX_PIPES]; |
|
struct intel_transcoder_error_state { |
bool power_domain_on; |
enum transcoder cpu_transcoder; |
|
u32 conf; |
10679,14 → 11390,19 |
if (INTEL_INFO(dev)->num_pipes == 0) |
return NULL; |
|
error = kmalloc(sizeof(*error), GFP_ATOMIC); |
error = kzalloc(sizeof(*error), GFP_ATOMIC); |
if (error == NULL) |
return NULL; |
|
if (HAS_POWER_WELL(dev)) |
if (IS_HASWELL(dev) || IS_BROADWELL(dev)) |
error->power_well_driver = I915_READ(HSW_PWR_WELL_DRIVER); |
|
for_each_pipe(i) { |
error->pipe[i].power_domain_on = |
intel_display_power_enabled_sw(dev, POWER_DOMAIN_PIPE(i)); |
if (!error->pipe[i].power_domain_on) |
continue; |
|
if (INTEL_INFO(dev)->gen <= 6 || IS_VALLEYVIEW(dev)) { |
error->cursor[i].control = I915_READ(CURCNTR(i)); |
error->cursor[i].position = I915_READ(CURPOS(i)); |
10720,6 → 11436,12 |
for (i = 0; i < error->num_transcoders; i++) { |
enum transcoder cpu_transcoder = transcoders[i]; |
|
error->transcoder[i].power_domain_on = |
intel_display_power_enabled_sw(dev, |
POWER_DOMAIN_TRANSCODER(cpu_transcoder)); |
if (!error->transcoder[i].power_domain_on) |
continue; |
|
error->transcoder[i].cpu_transcoder = cpu_transcoder; |
|
error->transcoder[i].conf = I915_READ(PIPECONF(cpu_transcoder)); |
10731,12 → 11453,6 |
error->transcoder[i].vsync = I915_READ(VSYNC(cpu_transcoder)); |
} |
|
/* In the code above we read the registers without checking if the power |
* well was on, so here we have to clear the FPGA_DBG_RM_NOCLAIM bit to |
* prevent the next I915_WRITE from detecting it and printing an error |
* message. */ |
intel_uncore_clear_errors(dev); |
|
return error; |
} |
|
10753,11 → 11469,13 |
return; |
|
err_printf(m, "Num Pipes: %d\n", INTEL_INFO(dev)->num_pipes); |
if (HAS_POWER_WELL(dev)) |
if (IS_HASWELL(dev) || IS_BROADWELL(dev)) |
err_printf(m, "PWR_WELL_CTL2: %08x\n", |
error->power_well_driver); |
for_each_pipe(i) { |
err_printf(m, "Pipe [%d]:\n", i); |
err_printf(m, " Power: %s\n", |
error->pipe[i].power_domain_on ? "on" : "off"); |
err_printf(m, " SRC: %08x\n", error->pipe[i].source); |
|
err_printf(m, "Plane [%d]:\n", i); |
10783,6 → 11501,8 |
for (i = 0; i < error->num_transcoders; i++) { |
err_printf(m, " CPU transcoder: %c\n", |
transcoder_name(error->transcoder[i].cpu_transcoder)); |
err_printf(m, " Power: %s\n", |
error->transcoder[i].power_domain_on ? "on" : "off"); |
err_printf(m, " CONF: %08x\n", error->transcoder[i].conf); |
err_printf(m, " HTOTAL: %08x\n", error->transcoder[i].htotal); |
err_printf(m, " HBLANK: %08x\n", error->transcoder[i].hblank); |