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 | |
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')
-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 a9ae374861e..77dace6a01f 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 d791043c8ec..eb44432d79b 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 ed65121989b..5ac8a164a1e 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 6994e06f897..b26e7c46a75 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; |