diff options
| author | Jesse Barnes <jbarnes@virtuousgeek.org> | 2012-01-03 11:05:39 -0500 |
|---|---|---|
| committer | Keith Packard <keithp@keithp.com> | 2012-01-03 12:31:12 -0500 |
| commit | 8ea30864229e54b01ac0e9fe88c4b733a940ec4e (patch) | |
| tree | 45d7912ad57216d9e18bef23698d0d099b51cbf2 /drivers/gpu | |
| parent | 175bd4204e069f8bd855ca3dcf70a78db4410936 (diff) | |
drm/i915: add color key support v4
Add new ioctls for getting and setting the current destination color
key. This allows for simple overlay display control by matching a color
key value in the primary plane before blending the overlay on top.
v2: remove unnecessary mutex acquire/release around reg accesses
v3: add support for full color key management
v4: fix copy & paste bug in snb_get_colorkey
don't bother checking min/max values against docs as the docs are likely
wrong (how could we handle 10bpc surface formats?)
Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Diffstat (limited to 'drivers/gpu')
| -rw-r--r-- | drivers/gpu/drm/i915/i915_dma.c | 2 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/i915_reg.h | 3 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/intel_drv.h | 11 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/intel_sprite.c | 177 |
4 files changed, 193 insertions, 0 deletions
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index a9ae374861e7..77dace6a01f6 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c | |||
| @@ -2305,6 +2305,8 @@ struct drm_ioctl_desc i915_ioctls[] = { | |||
| 2305 | DRM_IOCTL_DEF_DRV(I915_GEM_MADVISE, i915_gem_madvise_ioctl, DRM_UNLOCKED), | 2305 | DRM_IOCTL_DEF_DRV(I915_GEM_MADVISE, i915_gem_madvise_ioctl, DRM_UNLOCKED), |
| 2306 | DRM_IOCTL_DEF_DRV(I915_OVERLAY_PUT_IMAGE, intel_overlay_put_image, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), | 2306 | DRM_IOCTL_DEF_DRV(I915_OVERLAY_PUT_IMAGE, intel_overlay_put_image, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), |
| 2307 | DRM_IOCTL_DEF_DRV(I915_OVERLAY_ATTRS, intel_overlay_attrs, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), | 2307 | DRM_IOCTL_DEF_DRV(I915_OVERLAY_ATTRS, intel_overlay_attrs, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), |
| 2308 | DRM_IOCTL_DEF_DRV(I915_SET_SPRITE_COLORKEY, intel_sprite_set_colorkey, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), | ||
| 2309 | DRM_IOCTL_DEF_DRV(I915_GET_SPRITE_COLORKEY, intel_sprite_get_colorkey, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), | ||
| 2308 | }; | 2310 | }; |
| 2309 | 2311 | ||
| 2310 | int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls); | 2312 | int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls); |
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index d791043c8ec1..eb44432d79bf 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h | |||
| @@ -2737,9 +2737,12 @@ | |||
| 2737 | #define DVSSTRIDE(pipe) _PIPE(pipe, _DVSASTRIDE, _DVSBSTRIDE) | 2737 | #define DVSSTRIDE(pipe) _PIPE(pipe, _DVSASTRIDE, _DVSBSTRIDE) |
| 2738 | #define DVSPOS(pipe) _PIPE(pipe, _DVSAPOS, _DVSBPOS) | 2738 | #define DVSPOS(pipe) _PIPE(pipe, _DVSAPOS, _DVSBPOS) |
| 2739 | #define DVSSURF(pipe) _PIPE(pipe, _DVSASURF, _DVSBSURF) | 2739 | #define DVSSURF(pipe) _PIPE(pipe, _DVSASURF, _DVSBSURF) |
| 2740 | #define DVSKEYMAX(pipe) _PIPE(pipe, _DVSAKEYMAXVAL, _DVSBKEYMAXVAL) | ||
| 2740 | #define DVSSIZE(pipe) _PIPE(pipe, _DVSASIZE, _DVSBSIZE) | 2741 | #define DVSSIZE(pipe) _PIPE(pipe, _DVSASIZE, _DVSBSIZE) |
| 2741 | #define DVSSCALE(pipe) _PIPE(pipe, _DVSASCALE, _DVSBSCALE) | 2742 | #define DVSSCALE(pipe) _PIPE(pipe, _DVSASCALE, _DVSBSCALE) |
| 2742 | #define DVSTILEOFF(pipe) _PIPE(pipe, _DVSATILEOFF, _DVSBTILEOFF) | 2743 | #define DVSTILEOFF(pipe) _PIPE(pipe, _DVSATILEOFF, _DVSBTILEOFF) |
| 2744 | #define DVSKEYVAL(pipe) _PIPE(pipe, _DVSAKEYVAL, _DVSBKEYVAL) | ||
| 2745 | #define DVSKEYMSK(pipe) _PIPE(pipe, _DVSAKEYMSK, _DVSBKEYMSK) | ||
| 2743 | 2746 | ||
| 2744 | #define _SPRA_CTL 0x70280 | 2747 | #define _SPRA_CTL 0x70280 |
| 2745 | #define SPRITE_ENABLE (1<<31) | 2748 | #define SPRITE_ENABLE (1<<31) |
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index ed65121989bf..5ac8a164a1ee 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h | |||
| @@ -26,6 +26,7 @@ | |||
| 26 | #define __INTEL_DRV_H__ | 26 | #define __INTEL_DRV_H__ |
| 27 | 27 | ||
| 28 | #include <linux/i2c.h> | 28 | #include <linux/i2c.h> |
| 29 | #include "i915_drm.h" | ||
| 29 | #include "i915_drv.h" | 30 | #include "i915_drv.h" |
| 30 | #include "drm_crtc.h" | 31 | #include "drm_crtc.h" |
| 31 | #include "drm_crtc_helper.h" | 32 | #include "drm_crtc_helper.h" |
| @@ -192,6 +193,10 @@ struct intel_plane { | |||
| 192 | uint32_t x, uint32_t y, | 193 | uint32_t x, uint32_t y, |
| 193 | uint32_t src_w, uint32_t src_h); | 194 | uint32_t src_w, uint32_t src_h); |
| 194 | void (*disable_plane)(struct drm_plane *plane); | 195 | void (*disable_plane)(struct drm_plane *plane); |
| 196 | int (*update_colorkey)(struct drm_plane *plane, | ||
| 197 | struct drm_intel_sprite_colorkey *key); | ||
| 198 | void (*get_colorkey)(struct drm_plane *plane, | ||
| 199 | struct drm_intel_sprite_colorkey *key); | ||
| 195 | }; | 200 | }; |
| 196 | 201 | ||
| 197 | #define to_intel_crtc(x) container_of(x, struct intel_crtc, base) | 202 | #define to_intel_crtc(x) container_of(x, struct intel_crtc, base) |
| @@ -414,4 +419,10 @@ extern void sandybridge_update_wm(struct drm_device *dev); | |||
| 414 | extern void intel_update_sprite_watermarks(struct drm_device *dev, int pipe, | 419 | extern void intel_update_sprite_watermarks(struct drm_device *dev, int pipe, |
| 415 | uint32_t sprite_width, | 420 | uint32_t sprite_width, |
| 416 | int pixel_size); | 421 | int pixel_size); |
| 422 | |||
| 423 | extern int intel_sprite_set_colorkey(struct drm_device *dev, void *data, | ||
| 424 | struct drm_file *file_priv); | ||
| 425 | extern int intel_sprite_get_colorkey(struct drm_device *dev, void *data, | ||
| 426 | struct drm_file *file_priv); | ||
| 427 | |||
| 417 | #endif /* __INTEL_DRV_H__ */ | 428 | #endif /* __INTEL_DRV_H__ */ |
diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index 6994e06f8975..b26e7c46a752 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c | |||
| @@ -95,6 +95,7 @@ ivb_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb, | |||
| 95 | /* must disable */ | 95 | /* must disable */ |
| 96 | sprctl |= SPRITE_TRICKLE_FEED_DISABLE; | 96 | sprctl |= SPRITE_TRICKLE_FEED_DISABLE; |
| 97 | sprctl |= SPRITE_ENABLE; | 97 | sprctl |= SPRITE_ENABLE; |
| 98 | sprctl |= SPRITE_DEST_KEY; | ||
| 98 | 99 | ||
| 99 | /* Sizes are 0 based */ | 100 | /* Sizes are 0 based */ |
| 100 | src_w--; | 101 | src_w--; |
| @@ -153,6 +154,60 @@ ivb_disable_plane(struct drm_plane *plane) | |||
| 153 | POSTING_READ(SPRSURF(pipe)); | 154 | POSTING_READ(SPRSURF(pipe)); |
| 154 | } | 155 | } |
| 155 | 156 | ||
| 157 | static int | ||
| 158 | ivb_update_colorkey(struct drm_plane *plane, | ||
| 159 | struct drm_intel_sprite_colorkey *key) | ||
| 160 | { | ||
| 161 | struct drm_device *dev = plane->dev; | ||
| 162 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 163 | struct intel_plane *intel_plane; | ||
| 164 | u32 sprctl; | ||
| 165 | int ret = 0; | ||
| 166 | |||
| 167 | intel_plane = to_intel_plane(plane); | ||
| 168 | |||
| 169 | I915_WRITE(SPRKEYVAL(intel_plane->pipe), key->min_value); | ||
| 170 | I915_WRITE(SPRKEYMAX(intel_plane->pipe), key->max_value); | ||
| 171 | I915_WRITE(SPRKEYMSK(intel_plane->pipe), key->channel_mask); | ||
| 172 | |||
| 173 | sprctl = I915_READ(SPRCTL(intel_plane->pipe)); | ||
| 174 | sprctl &= ~(SPRITE_SOURCE_KEY | SPRITE_DEST_KEY); | ||
| 175 | if (key->flags & I915_SET_COLORKEY_DESTINATION) | ||
| 176 | sprctl |= SPRITE_DEST_KEY; | ||
| 177 | else if (key->flags & I915_SET_COLORKEY_SOURCE) | ||
| 178 | sprctl |= SPRITE_SOURCE_KEY; | ||
| 179 | I915_WRITE(SPRCTL(intel_plane->pipe), sprctl); | ||
| 180 | |||
| 181 | POSTING_READ(SPRKEYMSK(intel_plane->pipe)); | ||
| 182 | |||
| 183 | return ret; | ||
| 184 | } | ||
| 185 | |||
| 186 | static void | ||
| 187 | ivb_get_colorkey(struct drm_plane *plane, struct drm_intel_sprite_colorkey *key) | ||
| 188 | { | ||
| 189 | struct drm_device *dev = plane->dev; | ||
| 190 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 191 | struct intel_plane *intel_plane; | ||
| 192 | u32 sprctl; | ||
| 193 | |||
| 194 | intel_plane = to_intel_plane(plane); | ||
| 195 | |||
| 196 | key->min_value = I915_READ(SPRKEYVAL(intel_plane->pipe)); | ||
| 197 | key->max_value = I915_READ(SPRKEYMAX(intel_plane->pipe)); | ||
| 198 | key->channel_mask = I915_READ(SPRKEYMSK(intel_plane->pipe)); | ||
| 199 | key->flags = 0; | ||
| 200 | |||
| 201 | sprctl = I915_READ(SPRCTL(intel_plane->pipe)); | ||
| 202 | |||
| 203 | if (sprctl & SPRITE_DEST_KEY) | ||
| 204 | key->flags = I915_SET_COLORKEY_DESTINATION; | ||
| 205 | else if (sprctl & SPRITE_SOURCE_KEY) | ||
| 206 | key->flags = I915_SET_COLORKEY_SOURCE; | ||
| 207 | else | ||
| 208 | key->flags = I915_SET_COLORKEY_NONE; | ||
| 209 | } | ||
| 210 | |||
| 156 | static void | 211 | static void |
| 157 | snb_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb, | 212 | snb_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb, |
| 158 | struct drm_i915_gem_object *obj, int crtc_x, int crtc_y, | 213 | struct drm_i915_gem_object *obj, int crtc_x, int crtc_y, |
| @@ -279,6 +334,60 @@ intel_disable_primary(struct drm_crtc *crtc) | |||
| 279 | } | 334 | } |
| 280 | 335 | ||
| 281 | static int | 336 | static int |
| 337 | snb_update_colorkey(struct drm_plane *plane, | ||
| 338 | struct drm_intel_sprite_colorkey *key) | ||
| 339 | { | ||
| 340 | struct drm_device *dev = plane->dev; | ||
| 341 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 342 | struct intel_plane *intel_plane; | ||
| 343 | u32 dvscntr; | ||
| 344 | int ret = 0; | ||
| 345 | |||
| 346 | intel_plane = to_intel_plane(plane); | ||
| 347 | |||
| 348 | I915_WRITE(DVSKEYVAL(intel_plane->pipe), key->min_value); | ||
| 349 | I915_WRITE(DVSKEYMAX(intel_plane->pipe), key->max_value); | ||
| 350 | I915_WRITE(DVSKEYMSK(intel_plane->pipe), key->channel_mask); | ||
| 351 | |||
| 352 | dvscntr = I915_READ(DVSCNTR(intel_plane->pipe)); | ||
| 353 | dvscntr &= ~(DVS_SOURCE_KEY | DVS_DEST_KEY); | ||
| 354 | if (key->flags & I915_SET_COLORKEY_DESTINATION) | ||
| 355 | dvscntr |= DVS_DEST_KEY; | ||
| 356 | else if (key->flags & I915_SET_COLORKEY_SOURCE) | ||
| 357 | dvscntr |= DVS_SOURCE_KEY; | ||
| 358 | I915_WRITE(DVSCNTR(intel_plane->pipe), dvscntr); | ||
| 359 | |||
| 360 | POSTING_READ(DVSKEYMSK(intel_plane->pipe)); | ||
| 361 | |||
| 362 | return ret; | ||
| 363 | } | ||
| 364 | |||
| 365 | static void | ||
| 366 | snb_get_colorkey(struct drm_plane *plane, struct drm_intel_sprite_colorkey *key) | ||
| 367 | { | ||
| 368 | struct drm_device *dev = plane->dev; | ||
| 369 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 370 | struct intel_plane *intel_plane; | ||
| 371 | u32 dvscntr; | ||
| 372 | |||
| 373 | intel_plane = to_intel_plane(plane); | ||
| 374 | |||
| 375 | key->min_value = I915_READ(DVSKEYVAL(intel_plane->pipe)); | ||
| 376 | key->max_value = I915_READ(DVSKEYMAX(intel_plane->pipe)); | ||
| 377 | key->channel_mask = I915_READ(DVSKEYMSK(intel_plane->pipe)); | ||
| 378 | key->flags = 0; | ||
| 379 | |||
| 380 | dvscntr = I915_READ(DVSCNTR(intel_plane->pipe)); | ||
| 381 | |||
| 382 | if (dvscntr & DVS_DEST_KEY) | ||
| 383 | key->flags = I915_SET_COLORKEY_DESTINATION; | ||
| 384 | else if (dvscntr & DVS_SOURCE_KEY) | ||
| 385 | key->flags = I915_SET_COLORKEY_SOURCE; | ||
| 386 | else | ||
| 387 | key->flags = I915_SET_COLORKEY_NONE; | ||
| 388 | } | ||
| 389 | |||
| 390 | static int | ||
| 282 | intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, | 391 | intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, |
| 283 | struct drm_framebuffer *fb, int crtc_x, int crtc_y, | 392 | struct drm_framebuffer *fb, int crtc_x, int crtc_y, |
| 284 | unsigned int crtc_w, unsigned int crtc_h, | 393 | unsigned int crtc_w, unsigned int crtc_h, |
| @@ -437,6 +546,70 @@ static void intel_destroy_plane(struct drm_plane *plane) | |||
| 437 | kfree(intel_plane); | 546 | kfree(intel_plane); |
| 438 | } | 547 | } |
| 439 | 548 | ||
| 549 | int intel_sprite_set_colorkey(struct drm_device *dev, void *data, | ||
| 550 | struct drm_file *file_priv) | ||
| 551 | { | ||
| 552 | struct drm_intel_sprite_colorkey *set = data; | ||
| 553 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 554 | struct drm_mode_object *obj; | ||
| 555 | struct drm_plane *plane; | ||
| 556 | struct intel_plane *intel_plane; | ||
| 557 | int ret = 0; | ||
| 558 | |||
| 559 | if (!dev_priv) | ||
| 560 | return -EINVAL; | ||
| 561 | |||
| 562 | /* Make sure we don't try to enable both src & dest simultaneously */ | ||
| 563 | if ((set->flags & (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE)) == (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE)) | ||
| 564 | return -EINVAL; | ||
| 565 | |||
| 566 | mutex_lock(&dev->mode_config.mutex); | ||
| 567 | |||
| 568 | obj = drm_mode_object_find(dev, set->plane_id, DRM_MODE_OBJECT_PLANE); | ||
| 569 | if (!obj) { | ||
| 570 | ret = -EINVAL; | ||
| 571 | goto out_unlock; | ||
| 572 | } | ||
| 573 | |||
| 574 | plane = obj_to_plane(obj); | ||
| 575 | intel_plane = to_intel_plane(plane); | ||
| 576 | ret = intel_plane->update_colorkey(plane, set); | ||
| 577 | |||
| 578 | out_unlock: | ||
| 579 | mutex_unlock(&dev->mode_config.mutex); | ||
| 580 | return ret; | ||
| 581 | } | ||
| 582 | |||
| 583 | int intel_sprite_get_colorkey(struct drm_device *dev, void *data, | ||
| 584 | struct drm_file *file_priv) | ||
| 585 | { | ||
| 586 | struct drm_intel_sprite_colorkey *get = data; | ||
| 587 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 588 | struct drm_mode_object *obj; | ||
| 589 | struct drm_plane *plane; | ||
| 590 | struct intel_plane *intel_plane; | ||
| 591 | int ret = 0; | ||
| 592 | |||
| 593 | if (!dev_priv) | ||
| 594 | return -EINVAL; | ||
| 595 | |||
| 596 | mutex_lock(&dev->mode_config.mutex); | ||
| 597 | |||
| 598 | obj = drm_mode_object_find(dev, get->plane_id, DRM_MODE_OBJECT_PLANE); | ||
| 599 | if (!obj) { | ||
| 600 | ret = -EINVAL; | ||
| 601 | goto out_unlock; | ||
| 602 | } | ||
| 603 | |||
| 604 | plane = obj_to_plane(obj); | ||
| 605 | intel_plane = to_intel_plane(plane); | ||
| 606 | intel_plane->get_colorkey(plane, get); | ||
| 607 | |||
| 608 | out_unlock: | ||
| 609 | mutex_unlock(&dev->mode_config.mutex); | ||
| 610 | return ret; | ||
| 611 | } | ||
| 612 | |||
| 440 | static const struct drm_plane_funcs intel_plane_funcs = { | 613 | static const struct drm_plane_funcs intel_plane_funcs = { |
| 441 | .update_plane = intel_update_plane, | 614 | .update_plane = intel_update_plane, |
| 442 | .disable_plane = intel_disable_plane, | 615 | .disable_plane = intel_disable_plane, |
| @@ -472,10 +645,14 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe) | |||
| 472 | intel_plane->max_downscale = 16; | 645 | intel_plane->max_downscale = 16; |
| 473 | intel_plane->update_plane = snb_update_plane; | 646 | intel_plane->update_plane = snb_update_plane; |
| 474 | intel_plane->disable_plane = snb_disable_plane; | 647 | intel_plane->disable_plane = snb_disable_plane; |
| 648 | intel_plane->update_colorkey = snb_update_colorkey; | ||
| 649 | intel_plane->get_colorkey = snb_get_colorkey; | ||
| 475 | } else if (IS_GEN7(dev)) { | 650 | } else if (IS_GEN7(dev)) { |
| 476 | intel_plane->max_downscale = 2; | 651 | intel_plane->max_downscale = 2; |
| 477 | intel_plane->update_plane = ivb_update_plane; | 652 | intel_plane->update_plane = ivb_update_plane; |
| 478 | intel_plane->disable_plane = ivb_disable_plane; | 653 | intel_plane->disable_plane = ivb_disable_plane; |
| 654 | intel_plane->update_colorkey = ivb_update_colorkey; | ||
| 655 | intel_plane->get_colorkey = ivb_get_colorkey; | ||
| 479 | } | 656 | } |
| 480 | 657 | ||
| 481 | intel_plane->pipe = pipe; | 658 | intel_plane->pipe = pipe; |
