104,6 → 104,12 |
break; |
} |
|
/* |
* Enable gamma to match primary/cursor plane behaviour. |
* FIXME should be user controllable via propertiesa. |
*/ |
sprctl |= SP_GAMMA_ENABLE; |
|
if (obj->tiling_mode != I915_TILING_NONE) |
sprctl |= SP_TILED; |
|
135,7 → 141,7 |
|
I915_WRITE(SPSIZE(pipe, plane), (crtc_h << 16) | crtc_w); |
I915_WRITE(SPCNTR(pipe, plane), sprctl); |
I915_MODIFY_DISPBASE(SPSURF(pipe, plane), i915_gem_obj_ggtt_offset(obj) + |
I915_WRITE(SPSURF(pipe, plane), i915_gem_obj_ggtt_offset(obj) + |
sprsurf_offset); |
POSTING_READ(SPSURF(pipe, plane)); |
} |
152,7 → 158,7 |
I915_WRITE(SPCNTR(pipe, plane), I915_READ(SPCNTR(pipe, plane)) & |
~SP_ENABLE); |
/* Activate double buffered register update */ |
I915_MODIFY_DISPBASE(SPSURF(pipe, plane), 0); |
I915_WRITE(SPSURF(pipe, plane), 0); |
POSTING_READ(SPSURF(pipe, plane)); |
|
intel_update_sprite_watermarks(dplane, crtc, 0, 0, false, false); |
224,7 → 230,6 |
u32 sprctl, sprscale = 0; |
unsigned long sprsurf_offset, linear_offset; |
int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0); |
bool scaling_was_enabled = dev_priv->sprite_scaling_enabled; |
|
sprctl = I915_READ(SPRCTL(pipe)); |
|
257,10 → 262,16 |
BUG(); |
} |
|
/* |
* Enable gamma to match primary/cursor plane behaviour. |
* FIXME should be user controllable via propertiesa. |
*/ |
sprctl |= SPRITE_GAMMA_ENABLE; |
|
if (obj->tiling_mode != I915_TILING_NONE) |
sprctl |= SPRITE_TILED; |
|
if (IS_HASWELL(dev)) |
if (IS_HASWELL(dev) || IS_BROADWELL(dev)) |
sprctl &= ~SPRITE_TRICKLE_FEED_DISABLE; |
else |
sprctl |= SPRITE_TRICKLE_FEED_DISABLE; |
267,7 → 278,7 |
|
sprctl |= SPRITE_ENABLE; |
|
if (IS_HASWELL(dev)) |
if (IS_HASWELL(dev) || IS_BROADWELL(dev)) |
sprctl |= SPRITE_PIPE_CSC_ENABLE; |
|
intel_update_sprite_watermarks(plane, crtc, src_w, pixel_size, true, |
279,21 → 290,8 |
crtc_w--; |
crtc_h--; |
|
/* |
* IVB workaround: must disable low power watermarks for at least |
* one frame before enabling scaling. LP watermarks can be re-enabled |
* when scaling is disabled. |
*/ |
if (crtc_w != src_w || crtc_h != src_h) { |
dev_priv->sprite_scaling_enabled |= 1 << pipe; |
|
if (!scaling_was_enabled) { |
intel_update_watermarks(dev); |
intel_wait_for_vblank(dev, pipe); |
} |
if (crtc_w != src_w || crtc_h != src_h) |
sprscale = SPRITE_SCALE_ENABLE | (src_w << 16) | src_h; |
} else |
dev_priv->sprite_scaling_enabled &= ~(1 << pipe); |
|
I915_WRITE(SPRSTRIDE(pipe), fb->pitches[0]); |
I915_WRITE(SPRPOS(pipe), (crtc_y << 16) | crtc_x); |
306,7 → 304,7 |
|
/* HSW consolidates SPRTILEOFF and SPRLINOFF into a single SPROFFSET |
* register */ |
if (IS_HASWELL(dev)) |
if (IS_HASWELL(dev) || IS_BROADWELL(dev)) |
I915_WRITE(SPROFFSET(pipe), (y << 16) | x); |
else if (obj->tiling_mode != I915_TILING_NONE) |
I915_WRITE(SPRTILEOFF(pipe), (y << 16) | x); |
317,13 → 315,9 |
if (intel_plane->can_scale) |
I915_WRITE(SPRSCALE(pipe), sprscale); |
I915_WRITE(SPRCTL(pipe), sprctl); |
I915_MODIFY_DISPBASE(SPRSURF(pipe), |
I915_WRITE(SPRSURF(pipe), |
i915_gem_obj_ggtt_offset(obj) + sprsurf_offset); |
POSTING_READ(SPRSURF(pipe)); |
|
/* potentially re-enable LP watermarks */ |
if (scaling_was_enabled && !dev_priv->sprite_scaling_enabled) |
intel_update_watermarks(dev); |
} |
|
static void |
333,7 → 327,6 |
struct drm_i915_private *dev_priv = dev->dev_private; |
struct intel_plane *intel_plane = to_intel_plane(plane); |
int pipe = intel_plane->pipe; |
bool scaling_was_enabled = dev_priv->sprite_scaling_enabled; |
|
I915_WRITE(SPRCTL(pipe), I915_READ(SPRCTL(pipe)) & ~SPRITE_ENABLE); |
/* Can't leave the scaler enabled... */ |
340,16 → 333,16 |
if (intel_plane->can_scale) |
I915_WRITE(SPRSCALE(pipe), 0); |
/* Activate double buffered register update */ |
I915_MODIFY_DISPBASE(SPRSURF(pipe), 0); |
I915_WRITE(SPRSURF(pipe), 0); |
POSTING_READ(SPRSURF(pipe)); |
|
dev_priv->sprite_scaling_enabled &= ~(1 << pipe); |
/* |
* Avoid underruns when disabling the sprite. |
* FIXME remove once watermark updates are done properly. |
*/ |
intel_wait_for_vblank(dev, pipe); |
|
intel_update_sprite_watermarks(plane, crtc, 0, 0, false, false); |
|
/* potentially re-enable LP watermarks */ |
if (scaling_was_enabled && !dev_priv->sprite_scaling_enabled) |
intel_update_watermarks(dev); |
} |
|
static int |
453,6 → 446,12 |
BUG(); |
} |
|
/* |
* Enable gamma to match primary/cursor plane behaviour. |
* FIXME should be user controllable via propertiesa. |
*/ |
dvscntr |= DVS_GAMMA_ENABLE; |
|
if (obj->tiling_mode != I915_TILING_NONE) |
dvscntr |= DVS_TILED; |
|
470,7 → 469,7 |
crtc_h--; |
|
dvsscale = 0; |
if (IS_GEN5(dev) || crtc_w != src_w || crtc_h != src_h) |
if (crtc_w != src_w || crtc_h != src_h) |
dvsscale = DVS_SCALE_ENABLE | (src_w << 16) | src_h; |
|
I915_WRITE(DVSSTRIDE(pipe), fb->pitches[0]); |
490,7 → 489,7 |
I915_WRITE(DVSSIZE(pipe), (crtc_h << 16) | crtc_w); |
I915_WRITE(DVSSCALE(pipe), dvsscale); |
I915_WRITE(DVSCNTR(pipe), dvscntr); |
I915_MODIFY_DISPBASE(DVSSURF(pipe), |
I915_WRITE(DVSSURF(pipe), |
i915_gem_obj_ggtt_offset(obj) + dvssurf_offset); |
POSTING_READ(DVSSURF(pipe)); |
} |
507,9 → 506,15 |
/* Disable the scaler */ |
I915_WRITE(DVSSCALE(pipe), 0); |
/* Flush double buffered register updates */ |
I915_MODIFY_DISPBASE(DVSSURF(pipe), 0); |
I915_WRITE(DVSSURF(pipe), 0); |
POSTING_READ(DVSSURF(pipe)); |
|
/* |
* Avoid underruns when disabling the sprite. |
* FIXME remove once watermark updates are done properly. |
*/ |
intel_wait_for_vblank(dev, pipe); |
|
intel_update_sprite_watermarks(plane, crtc, 0, 0, false, false); |
} |
|
521,15 → 526,30 |
struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
int reg = DSPCNTR(intel_crtc->plane); |
|
if (!intel_crtc->primary_disabled) |
if (intel_crtc->primary_enabled) |
return; |
|
intel_crtc->primary_disabled = false; |
intel_update_fbc(dev); |
intel_crtc->primary_enabled = true; |
|
I915_WRITE(reg, I915_READ(reg) | DISPLAY_PLANE_ENABLE); |
intel_flush_primary_plane(dev_priv, intel_crtc->plane); |
|
/* |
* FIXME IPS should be fine as long as one plane is |
* enabled, but in practice it seems to have problems |
* when going from primary only to sprite only and vice |
* versa. |
*/ |
if (intel_crtc->config.ips_enabled) { |
intel_wait_for_vblank(dev, intel_crtc->pipe); |
hsw_enable_ips(intel_crtc); |
} |
|
mutex_lock(&dev->struct_mutex); |
intel_update_fbc(dev); |
mutex_unlock(&dev->struct_mutex); |
} |
|
static void |
intel_disable_primary(struct drm_crtc *crtc) |
{ |
538,13 → 558,26 |
struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
int reg = DSPCNTR(intel_crtc->plane); |
|
if (intel_crtc->primary_disabled) |
if (!intel_crtc->primary_enabled) |
return; |
|
intel_crtc->primary_enabled = false; |
|
mutex_lock(&dev->struct_mutex); |
if (dev_priv->fbc.plane == intel_crtc->plane) |
intel_disable_fbc(dev); |
mutex_unlock(&dev->struct_mutex); |
|
/* |
* FIXME IPS should be fine as long as one plane is |
* enabled, but in practice it seems to have problems |
* when going from primary only to sprite only and vice |
* versa. |
*/ |
hsw_disable_ips(intel_crtc); |
|
I915_WRITE(reg, I915_READ(reg) & ~DISPLAY_PLANE_ENABLE); |
|
intel_crtc->primary_disabled = true; |
intel_update_fbc(dev); |
intel_flush_primary_plane(dev_priv, intel_crtc->plane); |
} |
|
static int |
615,6 → 648,15 |
} |
} |
|
static bool colorkey_enabled(struct intel_plane *intel_plane) |
{ |
struct drm_intel_sprite_colorkey key; |
|
intel_plane->get_colorkey(&intel_plane->base, &key); |
|
return key.flags != I915_SET_COLORKEY_NONE; |
} |
|
static int |
intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, |
struct drm_framebuffer *fb, int crtc_x, int crtc_y, |
623,15 → 665,12 |
uint32_t src_w, uint32_t src_h) |
{ |
struct drm_device *dev = plane->dev; |
struct drm_i915_private *dev_priv = dev->dev_private; |
struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
struct intel_plane *intel_plane = to_intel_plane(plane); |
struct intel_framebuffer *intel_fb; |
struct drm_i915_gem_object *obj, *old_obj; |
int pipe = intel_plane->pipe; |
enum transcoder cpu_transcoder = intel_pipe_to_cpu_transcoder(dev_priv, |
pipe); |
int ret = 0; |
struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb); |
struct drm_i915_gem_object *obj = intel_fb->obj; |
struct drm_i915_gem_object *old_obj = intel_plane->obj; |
int ret; |
bool disable_primary = false; |
bool visible; |
int hscale, vscale; |
652,30 → 691,24 |
.y2 = crtc_y + crtc_h, |
}; |
const struct drm_rect clip = { |
.x2 = crtc->mode.hdisplay, |
.y2 = crtc->mode.vdisplay, |
.x2 = intel_crtc->active ? intel_crtc->config.pipe_src_w : 0, |
.y2 = intel_crtc->active ? intel_crtc->config.pipe_src_h : 0, |
}; |
const struct { |
int crtc_x, crtc_y; |
unsigned int crtc_w, crtc_h; |
uint32_t src_x, src_y, src_w, src_h; |
} orig = { |
.crtc_x = crtc_x, |
.crtc_y = crtc_y, |
.crtc_w = crtc_w, |
.crtc_h = crtc_h, |
.src_x = src_x, |
.src_y = src_y, |
.src_w = src_w, |
.src_h = src_h, |
}; |
|
intel_fb = to_intel_framebuffer(fb); |
obj = intel_fb->obj; |
|
old_obj = intel_plane->obj; |
|
intel_plane->crtc_x = crtc_x; |
intel_plane->crtc_y = crtc_y; |
intel_plane->crtc_w = crtc_w; |
intel_plane->crtc_h = crtc_h; |
intel_plane->src_x = src_x; |
intel_plane->src_y = src_y; |
intel_plane->src_w = src_w; |
intel_plane->src_h = src_h; |
|
/* Pipe must be running... */ |
if (!(I915_READ(PIPECONF(cpu_transcoder)) & PIPECONF_ENABLE)) { |
DRM_DEBUG_KMS("Pipe disabled\n"); |
return -EINVAL; |
} |
|
/* Don't modify another pipe's plane */ |
if (intel_plane->pipe != intel_crtc->pipe) { |
DRM_DEBUG_KMS("Wrong plane <-> crtc mapping\n"); |
809,8 → 842,8 |
* If the sprite is completely covering the primary plane, |
* we can disable the primary and save power. |
*/ |
disable_primary = drm_rect_equals(&dst, &clip); |
WARN_ON(disable_primary && !visible); |
disable_primary = drm_rect_equals(&dst, &clip) && !colorkey_enabled(intel_plane); |
WARN_ON(disable_primary && !visible && intel_crtc->active); |
|
mutex_lock(&dev->struct_mutex); |
|
820,11 → 853,23 |
* the sprite planes only require 128KiB alignment and 32 PTE padding. |
*/ |
ret = intel_pin_and_fence_fb_obj(dev, obj, NULL); |
|
mutex_unlock(&dev->struct_mutex); |
|
if (ret) |
goto out_unlock; |
return ret; |
|
intel_plane->crtc_x = orig.crtc_x; |
intel_plane->crtc_y = orig.crtc_y; |
intel_plane->crtc_w = orig.crtc_w; |
intel_plane->crtc_h = orig.crtc_h; |
intel_plane->src_x = orig.src_x; |
intel_plane->src_y = orig.src_y; |
intel_plane->src_w = orig.src_w; |
intel_plane->src_h = orig.src_h; |
intel_plane->obj = obj; |
|
if (intel_crtc->active) { |
/* |
* Be sure to re-enable the primary before the sprite is no longer |
* covering it fully. |
841,6 → 886,7 |
|
if (disable_primary) |
intel_disable_primary(crtc); |
} |
|
/* Unpin old obj after new one is active to avoid ugliness */ |
if (old_obj) { |
850,17 → 896,15 |
* wait for vblank to avoid ugliness, we only need to |
* do the pin & ref bookkeeping. |
*/ |
if (old_obj != obj) { |
mutex_unlock(&dev->struct_mutex); |
intel_wait_for_vblank(dev, to_intel_crtc(crtc)->pipe); |
if (old_obj != obj && intel_crtc->active) |
intel_wait_for_vblank(dev, intel_crtc->pipe); |
|
mutex_lock(&dev->struct_mutex); |
} |
intel_unpin_fb_obj(old_obj); |
mutex_unlock(&dev->struct_mutex); |
} |
|
out_unlock: |
mutex_unlock(&dev->struct_mutex); |
return ret; |
return 0; |
} |
|
static int |
868,7 → 912,7 |
{ |
struct drm_device *dev = plane->dev; |
struct intel_plane *intel_plane = to_intel_plane(plane); |
int ret = 0; |
struct intel_crtc *intel_crtc; |
|
if (!plane->fb) |
return 0; |
876,23 → 920,27 |
if (WARN_ON(!plane->crtc)) |
return -EINVAL; |
|
intel_crtc = to_intel_crtc(plane->crtc); |
|
if (intel_crtc->active) { |
intel_enable_primary(plane->crtc); |
intel_plane->disable_plane(plane, plane->crtc); |
} |
|
if (!intel_plane->obj) |
goto out; |
|
if (intel_plane->obj) { |
if (intel_crtc->active) |
intel_wait_for_vblank(dev, intel_plane->pipe); |
|
mutex_lock(&dev->struct_mutex); |
intel_unpin_fb_obj(intel_plane->obj); |
intel_plane->obj = NULL; |
mutex_unlock(&dev->struct_mutex); |
out: |
|
return ret; |
intel_plane->obj = NULL; |
} |
|
return 0; |
} |
|
static void intel_destroy_plane(struct drm_plane *plane) |
{ |
struct intel_plane *intel_plane = to_intel_plane(plane); |
921,7 → 969,7 |
|
obj = drm_mode_object_find(dev, set->plane_id, DRM_MODE_OBJECT_PLANE); |
if (!obj) { |
ret = -EINVAL; |
ret = -ENOENT; |
goto out_unlock; |
} |
|
950,7 → 998,7 |
|
obj = drm_mode_object_find(dev, get->plane_id, DRM_MODE_OBJECT_PLANE); |
if (!obj) { |
ret = -EINVAL; |
ret = -ENOENT; |
goto out_unlock; |
} |
|
1034,7 → 1082,7 |
if (INTEL_INFO(dev)->gen < 5) |
return -ENODEV; |
|
intel_plane = kzalloc(sizeof(struct intel_plane), GFP_KERNEL); |
intel_plane = kzalloc(sizeof(*intel_plane), GFP_KERNEL); |
if (!intel_plane) |
return -ENOMEM; |
|
1058,6 → 1106,7 |
break; |
|
case 7: |
case 8: |
if (IS_IVYBRIDGE(dev)) { |
intel_plane->can_scale = true; |
intel_plane->max_downscale = 2; |