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 | struct drm_plane base; | 181 | struct drm_plane base; |
| 182 | enum pipe pipe; | 182 | enum pipe pipe; |
| 183 | struct drm_i915_gem_object *obj; | 183 | struct drm_i915_gem_object *obj; |
| 184 | bool primary_disabled; | ||
| 184 | int max_downscale; | 185 | int max_downscale; |
| 185 | u32 lut_r[1024], lut_g[1024], lut_b[1024]; | 186 | u32 lut_r[1024], lut_g[1024], lut_b[1024]; |
| 186 | void (*update_plane)(struct drm_plane *plane, | 187 | void (*update_plane)(struct drm_plane *plane, |
| @@ -256,6 +256,28 @@ snb_disable_plane(struct drm_plane *plane) · 255 unmodified lines | |||
| 256 | POSTING_READ(DVSSURF(pipe)); | 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 | static int | 281 | static int |
| 260 | intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, | 282 | intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, |
| 261 | struct drm_framebuffer *fb, int crtc_x, int crtc_y, | 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 | intel_plane->obj = obj; | 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 | intel_plane->update_plane(plane, fb, obj, crtc_x, crtc_y, | 376 | intel_plane->update_plane(plane, fb, obj, crtc_x, crtc_y, |
| 346 | crtc_w, crtc_h, x, y, src_w, src_h); | 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 | /* Unpin old obj after new one is active to avoid ugliness */ | 384 | /* Unpin old obj after new one is active to avoid ugliness */ |
| 349 | if (old_obj) { | 385 | if (old_obj) { |
| 350 | /* | 386 | /* |
| @@ -374,6 +410,11 @@ intel_disable_plane(struct drm_plane *plane) · 23 unmodified lines | |||
| 374 | struct intel_plane *intel_plane = to_intel_plane(plane); | 410 | struct intel_plane *intel_plane = to_intel_plane(plane); |
| 375 | int ret = 0; | 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 | intel_plane->disable_plane(plane); | 418 | intel_plane->disable_plane(plane); |
| 378 | 419 | ||
| 379 | if (!intel_plane->obj) | 420 | if (!intel_plane->obj) |