To save power when the sprite is full screen, we can disable the primary plane on the same pipe. Track the sprite status and enable/disable the primary opportunistically. v2: remove primary plane enable/disable hooks; they're identical
Unified · Split
| @@ -181,6 +181,7 @@ struct intel_plane { · 180 unmodified lines | ||
| 181 | 181 | struct drm_plane base; |
| 182 | 182 | enum pipe pipe; |
| 183 | 183 | struct drm_i915_gem_object *obj; |
| 184 | + bool primary_disabled; | |
| 184 | 185 | int max_downscale; |
| 185 | 186 | u32 lut_r[1024], lut_g[1024], lut_b[1024]; |
| 186 | 187 | void (*update_plane)(struct drm_plane *plane, |
| @@ -256,6 +256,28 @@ snb_disable_plane(struct drm_plane *plane) · 255 unmodified lines | ||
| 256 | 256 | POSTING_READ(DVSSURF(pipe)); |
| 257 | 257 | } |
| 258 | 258 | |
| 259 | +static void | |
| 260 | +intel_enable_primary(struct drm_crtc *crtc) | |
| 261 | +{ | |
| 262 | + struct drm_device *dev = crtc->dev; | |
| 263 | + struct drm_i915_private *dev_priv = dev->dev_private; | |
| 264 | + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | |
| 265 | + int reg = DSPCNTR(intel_crtc->plane); | |
| 266 | + | |
| 267 | + I915_WRITE(reg, I915_READ(reg) | DISPLAY_PLANE_ENABLE); | |
| 268 | +} | |
| 269 | + | |
| 270 | +static void | |
| 271 | +intel_disable_primary(struct drm_crtc *crtc) | |
| 272 | +{ | |
| 273 | + struct drm_device *dev = crtc->dev; | |
| 274 | + struct drm_i915_private *dev_priv = dev->dev_private; | |
| 275 | + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | |
| 276 | + int reg = DSPCNTR(intel_crtc->plane); | |
| 277 | + | |
| 278 | + I915_WRITE(reg, I915_READ(reg) & ~DISPLAY_PLANE_ENABLE); | |
| 279 | +} | |
| 280 | + | |
| 259 | 281 | static int |
| 260 | 282 | intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, |
| 261 | 283 | struct drm_framebuffer *fb, int crtc_x, int crtc_y, |
| @@ -342,9 +364,23 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, · 80 unmodified lines | ||
| 342 | 364 | |
| 343 | 365 | intel_plane->obj = obj; |
| 344 | 366 | |
| 367 | + /* | |
| 368 | + * Be sure to re-enable the primary before the sprite is no longer | |
| 369 | + * covering it fully. | |
| 370 | + */ | |
| 371 | + if (!disable_primary && intel_plane->primary_disabled) { | |
| 372 | + intel_enable_primary(crtc); | |
| 373 | + intel_plane->primary_disabled = false; | |
| 374 | + } | |
| 375 | + | |
| 345 | 376 | intel_plane->update_plane(plane, fb, obj, crtc_x, crtc_y, |
| 346 | 377 | crtc_w, crtc_h, x, y, src_w, src_h); |
| 347 | 378 | |
| 379 | + if (disable_primary) { | |
| 380 | + intel_disable_primary(crtc); | |
| 381 | + intel_plane->primary_disabled = true; | |
| 382 | + } | |
| 383 | + | |
| 348 | 384 | /* Unpin old obj after new one is active to avoid ugliness */ |
| 349 | 385 | if (old_obj) { |
| 350 | 386 | /* |
| @@ -374,6 +410,11 @@ intel_disable_plane(struct drm_plane *plane) · 23 unmodified lines | ||
| 374 | 410 | struct intel_plane *intel_plane = to_intel_plane(plane); |
| 375 | 411 | int ret = 0; |
| 376 | 412 | |
| 413 | + if (intel_plane->primary_disabled) { | |
| 414 | + intel_enable_primary(plane->crtc); | |
| 415 | + intel_plane->primary_disabled = false; | |
| 416 | + } | |
| 417 | + | |
| 377 | 418 | intel_plane->disable_plane(plane); |
| 378 | 419 | |
| 379 | 420 | if (!intel_plane->obj) |