diff options
author | Jesse Barnes <jbarnes@virtuousgeek.org> | 2010-09-10 13:31:34 -0400 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2010-09-10 17:23:45 -0400 |
commit | 0b8765c6e7fb6e0aaa9b9081454fb0f202852523 (patch) | |
tree | e668955f8bf8ab79bda4b589c559742a902193e2 /drivers/gpu/drm/i915/intel_display.c | |
parent | 6be4a6078e41a8ec511dad35d1377bc5338f97be (diff) |
drm/i915: split i9xx CRTC enable/disable code
So we can use it for CRTC prepare/commit.
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Diffstat (limited to 'drivers/gpu/drm/i915/intel_display.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 185 |
1 files changed, 103 insertions, 82 deletions
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 56ca589a83f5..fecb98c2d8ad 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
@@ -2262,7 +2262,7 @@ static void intel_crtc_dpms_overlay(struct intel_crtc *intel_crtc, bool enable) | |||
2262 | */ | 2262 | */ |
2263 | } | 2263 | } |
2264 | 2264 | ||
2265 | static void i9xx_crtc_dpms(struct drm_crtc *crtc, int mode) | 2265 | static void i9xx_crtc_enable(struct drm_crtc *crtc) |
2266 | { | 2266 | { |
2267 | struct drm_device *dev = crtc->dev; | 2267 | struct drm_device *dev = crtc->dev; |
2268 | struct drm_i915_private *dev_priv = dev->dev_private; | 2268 | struct drm_i915_private *dev_priv = dev->dev_private; |
@@ -2275,97 +2275,118 @@ static void i9xx_crtc_dpms(struct drm_crtc *crtc, int mode) | |||
2275 | int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF; | 2275 | int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF; |
2276 | u32 temp; | 2276 | u32 temp; |
2277 | 2277 | ||
2278 | /* XXX: When our outputs are all unaware of DPMS modes other than off | 2278 | /* Enable the DPLL */ |
2279 | * and on, we should map those modes to DRM_MODE_DPMS_OFF in the CRTC. | 2279 | temp = I915_READ(dpll_reg); |
2280 | */ | 2280 | if ((temp & DPLL_VCO_ENABLE) == 0) { |
2281 | switch (mode) { | 2281 | I915_WRITE(dpll_reg, temp); |
2282 | case DRM_MODE_DPMS_ON: | 2282 | I915_READ(dpll_reg); |
2283 | case DRM_MODE_DPMS_STANDBY: | 2283 | /* Wait for the clocks to stabilize. */ |
2284 | case DRM_MODE_DPMS_SUSPEND: | 2284 | udelay(150); |
2285 | /* Enable the DPLL */ | 2285 | I915_WRITE(dpll_reg, temp | DPLL_VCO_ENABLE); |
2286 | temp = I915_READ(dpll_reg); | 2286 | I915_READ(dpll_reg); |
2287 | if ((temp & DPLL_VCO_ENABLE) == 0) { | 2287 | /* Wait for the clocks to stabilize. */ |
2288 | I915_WRITE(dpll_reg, temp); | 2288 | udelay(150); |
2289 | I915_READ(dpll_reg); | 2289 | I915_WRITE(dpll_reg, temp | DPLL_VCO_ENABLE); |
2290 | /* Wait for the clocks to stabilize. */ | 2290 | I915_READ(dpll_reg); |
2291 | udelay(150); | 2291 | /* Wait for the clocks to stabilize. */ |
2292 | I915_WRITE(dpll_reg, temp | DPLL_VCO_ENABLE); | 2292 | udelay(150); |
2293 | I915_READ(dpll_reg); | 2293 | } |
2294 | /* Wait for the clocks to stabilize. */ | ||
2295 | udelay(150); | ||
2296 | I915_WRITE(dpll_reg, temp | DPLL_VCO_ENABLE); | ||
2297 | I915_READ(dpll_reg); | ||
2298 | /* Wait for the clocks to stabilize. */ | ||
2299 | udelay(150); | ||
2300 | } | ||
2301 | 2294 | ||
2302 | /* Enable the pipe */ | 2295 | /* Enable the pipe */ |
2303 | temp = I915_READ(pipeconf_reg); | 2296 | temp = I915_READ(pipeconf_reg); |
2304 | if ((temp & PIPEACONF_ENABLE) == 0) | 2297 | if ((temp & PIPEACONF_ENABLE) == 0) |
2305 | I915_WRITE(pipeconf_reg, temp | PIPEACONF_ENABLE); | 2298 | I915_WRITE(pipeconf_reg, temp | PIPEACONF_ENABLE); |
2306 | |||
2307 | /* Enable the plane */ | ||
2308 | temp = I915_READ(dspcntr_reg); | ||
2309 | if ((temp & DISPLAY_PLANE_ENABLE) == 0) { | ||
2310 | I915_WRITE(dspcntr_reg, temp | DISPLAY_PLANE_ENABLE); | ||
2311 | /* Flush the plane changes */ | ||
2312 | I915_WRITE(dspbase_reg, I915_READ(dspbase_reg)); | ||
2313 | } | ||
2314 | 2299 | ||
2315 | intel_crtc_load_lut(crtc); | 2300 | /* Enable the plane */ |
2301 | temp = I915_READ(dspcntr_reg); | ||
2302 | if ((temp & DISPLAY_PLANE_ENABLE) == 0) { | ||
2303 | I915_WRITE(dspcntr_reg, temp | DISPLAY_PLANE_ENABLE); | ||
2304 | /* Flush the plane changes */ | ||
2305 | I915_WRITE(dspbase_reg, I915_READ(dspbase_reg)); | ||
2306 | } | ||
2316 | 2307 | ||
2317 | if ((IS_I965G(dev) || plane == 0)) | 2308 | intel_crtc_load_lut(crtc); |
2318 | intel_update_fbc(crtc, &crtc->mode); | ||
2319 | 2309 | ||
2320 | /* Give the overlay scaler a chance to enable if it's on this pipe */ | 2310 | if ((IS_I965G(dev) || plane == 0)) |
2321 | intel_crtc_dpms_overlay(intel_crtc, true); | 2311 | intel_update_fbc(crtc, &crtc->mode); |
2322 | break; | ||
2323 | case DRM_MODE_DPMS_OFF: | ||
2324 | /* Give the overlay scaler a chance to disable if it's on this pipe */ | ||
2325 | intel_crtc_dpms_overlay(intel_crtc, false); | ||
2326 | drm_vblank_off(dev, pipe); | ||
2327 | |||
2328 | if (dev_priv->cfb_plane == plane && | ||
2329 | dev_priv->display.disable_fbc) | ||
2330 | dev_priv->display.disable_fbc(dev); | ||
2331 | |||
2332 | /* Disable display plane */ | ||
2333 | temp = I915_READ(dspcntr_reg); | ||
2334 | if ((temp & DISPLAY_PLANE_ENABLE) != 0) { | ||
2335 | I915_WRITE(dspcntr_reg, temp & ~DISPLAY_PLANE_ENABLE); | ||
2336 | /* Flush the plane changes */ | ||
2337 | I915_WRITE(dspbase_reg, I915_READ(dspbase_reg)); | ||
2338 | I915_READ(dspbase_reg); | ||
2339 | } | ||
2340 | 2312 | ||
2341 | if (!IS_I9XX(dev)) { | 2313 | /* Give the overlay scaler a chance to enable if it's on this pipe */ |
2342 | /* Wait for vblank for the disable to take effect */ | 2314 | intel_crtc_dpms_overlay(intel_crtc, true); |
2343 | intel_wait_for_vblank_off(dev, pipe); | 2315 | } |
2344 | } | ||
2345 | 2316 | ||
2346 | /* Don't disable pipe A or pipe A PLLs if needed */ | 2317 | static void i9xx_crtc_disable(struct drm_crtc *crtc) |
2347 | if (pipeconf_reg == PIPEACONF && | 2318 | { |
2348 | (dev_priv->quirks & QUIRK_PIPEA_FORCE)) | 2319 | struct drm_device *dev = crtc->dev; |
2349 | goto skip_pipe_off; | 2320 | struct drm_i915_private *dev_priv = dev->dev_private; |
2321 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | ||
2322 | int pipe = intel_crtc->pipe; | ||
2323 | int plane = intel_crtc->plane; | ||
2324 | int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B; | ||
2325 | int dspcntr_reg = (plane == 0) ? DSPACNTR : DSPBCNTR; | ||
2326 | int dspbase_reg = (plane == 0) ? DSPAADDR : DSPBADDR; | ||
2327 | int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF; | ||
2328 | u32 temp; | ||
2350 | 2329 | ||
2351 | /* Next, disable display pipes */ | 2330 | /* Give the overlay scaler a chance to disable if it's on this pipe */ |
2352 | temp = I915_READ(pipeconf_reg); | 2331 | intel_crtc_dpms_overlay(intel_crtc, false); |
2353 | if ((temp & PIPEACONF_ENABLE) != 0) { | 2332 | drm_vblank_off(dev, pipe); |
2354 | I915_WRITE(pipeconf_reg, temp & ~PIPEACONF_ENABLE); | 2333 | |
2355 | I915_READ(pipeconf_reg); | 2334 | if (dev_priv->cfb_plane == plane && |
2356 | } | 2335 | dev_priv->display.disable_fbc) |
2336 | dev_priv->display.disable_fbc(dev); | ||
2357 | 2337 | ||
2358 | /* Wait for vblank for the disable to take effect. */ | 2338 | /* Disable display plane */ |
2339 | temp = I915_READ(dspcntr_reg); | ||
2340 | if ((temp & DISPLAY_PLANE_ENABLE) != 0) { | ||
2341 | I915_WRITE(dspcntr_reg, temp & ~DISPLAY_PLANE_ENABLE); | ||
2342 | /* Flush the plane changes */ | ||
2343 | I915_WRITE(dspbase_reg, I915_READ(dspbase_reg)); | ||
2344 | I915_READ(dspbase_reg); | ||
2345 | } | ||
2346 | |||
2347 | if (!IS_I9XX(dev)) { | ||
2348 | /* Wait for vblank for the disable to take effect */ | ||
2359 | intel_wait_for_vblank_off(dev, pipe); | 2349 | intel_wait_for_vblank_off(dev, pipe); |
2350 | } | ||
2360 | 2351 | ||
2361 | temp = I915_READ(dpll_reg); | 2352 | /* Don't disable pipe A or pipe A PLLs if needed */ |
2362 | if ((temp & DPLL_VCO_ENABLE) != 0) { | 2353 | if (pipeconf_reg == PIPEACONF && |
2363 | I915_WRITE(dpll_reg, temp & ~DPLL_VCO_ENABLE); | 2354 | (dev_priv->quirks & QUIRK_PIPEA_FORCE)) |
2364 | I915_READ(dpll_reg); | 2355 | goto skip_pipe_off; |
2365 | } | 2356 | |
2366 | skip_pipe_off: | 2357 | /* Next, disable display pipes */ |
2367 | /* Wait for the clocks to turn off. */ | 2358 | temp = I915_READ(pipeconf_reg); |
2368 | udelay(150); | 2359 | if ((temp & PIPEACONF_ENABLE) != 0) { |
2360 | I915_WRITE(pipeconf_reg, temp & ~PIPEACONF_ENABLE); | ||
2361 | I915_READ(pipeconf_reg); | ||
2362 | } | ||
2363 | |||
2364 | /* Wait for vblank for the disable to take effect. */ | ||
2365 | intel_wait_for_vblank_off(dev, pipe); | ||
2366 | |||
2367 | temp = I915_READ(dpll_reg); | ||
2368 | if ((temp & DPLL_VCO_ENABLE) != 0) { | ||
2369 | I915_WRITE(dpll_reg, temp & ~DPLL_VCO_ENABLE); | ||
2370 | I915_READ(dpll_reg); | ||
2371 | } | ||
2372 | skip_pipe_off: | ||
2373 | /* Wait for the clocks to turn off. */ | ||
2374 | udelay(150); | ||
2375 | } | ||
2376 | |||
2377 | static void i9xx_crtc_dpms(struct drm_crtc *crtc, int mode) | ||
2378 | { | ||
2379 | /* XXX: When our outputs are all unaware of DPMS modes other than off | ||
2380 | * and on, we should map those modes to DRM_MODE_DPMS_OFF in the CRTC. | ||
2381 | */ | ||
2382 | switch (mode) { | ||
2383 | case DRM_MODE_DPMS_ON: | ||
2384 | case DRM_MODE_DPMS_STANDBY: | ||
2385 | case DRM_MODE_DPMS_SUSPEND: | ||
2386 | i9xx_crtc_enable(crtc); | ||
2387 | break; | ||
2388 | case DRM_MODE_DPMS_OFF: | ||
2389 | i9xx_crtc_disable(crtc); | ||
2369 | break; | 2390 | break; |
2370 | } | 2391 | } |
2371 | } | 2392 | } |