summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJesse Barnes <jbarnes@virtuousgeek.org>2012-01-03 08:05:39 -0800
committerKeith Packard <keithp@keithp.com>2012-01-03 09:31:12 -0800
commit8ea30864229e54b01ac0e9fe88c4b733a940ec4e (patch)
tree45d7912ad57216d9e18bef23698d0d099b51cbf2
parent175bd4204e069f8bd855ca3dcf70a78db4410936 (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>
-rw-r--r--drivers/gpu/drm/i915/i915_dma.c2
-rw-r--r--drivers/gpu/drm/i915/i915_reg.h3
-rw-r--r--drivers/gpu/drm/i915/intel_drv.h11
-rw-r--r--drivers/gpu/drm/i915/intel_sprite.c177
-rw-r--r--include/drm/i915_drm.h36
5 files changed, 229 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
2310int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls); 2312int 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);
414extern void intel_update_sprite_watermarks(struct drm_device *dev, int pipe, 419extern 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
423extern int intel_sprite_set_colorkey(struct drm_device *dev, void *data,
424 struct drm_file *file_priv);
425extern 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
157static int
158ivb_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
186static void
187ivb_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
156static void 211static void
157snb_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb, 212snb_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
281static int 336static int
337snb_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
365static void
366snb_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
390static int
282intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, 391intel_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
549int 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
578out_unlock:
579 mutex_unlock(&dev->mode_config.mutex);
580 return ret;
581}
582
583int 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
608out_unlock:
609 mutex_unlock(&dev->mode_config.mutex);
610 return ret;
611}
612
440static const struct drm_plane_funcs intel_plane_funcs = { 613static 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;
diff --git a/include/drm/i915_drm.h b/include/drm/i915_drm.h
index 28c0d114cb52..1b4da1a9ec0f 100644
--- a/include/drm/i915_drm.h
+++ b/include/drm/i915_drm.h
@@ -198,6 +198,8 @@ typedef struct _drm_i915_sarea {
198#define DRM_I915_OVERLAY_PUT_IMAGE 0x27 198#define DRM_I915_OVERLAY_PUT_IMAGE 0x27
199#define DRM_I915_OVERLAY_ATTRS 0x28 199#define DRM_I915_OVERLAY_ATTRS 0x28
200#define DRM_I915_GEM_EXECBUFFER2 0x29 200#define DRM_I915_GEM_EXECBUFFER2 0x29
201#define DRM_I915_GET_SPRITE_COLORKEY 0x2a
202#define DRM_I915_SET_SPRITE_COLORKEY 0x2b
201 203
202#define DRM_IOCTL_I915_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t) 204#define DRM_IOCTL_I915_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t)
203#define DRM_IOCTL_I915_FLUSH DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH) 205#define DRM_IOCTL_I915_FLUSH DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH)
@@ -239,6 +241,8 @@ typedef struct _drm_i915_sarea {
239#define DRM_IOCTL_I915_GEM_MADVISE DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_MADVISE, struct drm_i915_gem_madvise) 241#define DRM_IOCTL_I915_GEM_MADVISE DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_MADVISE, struct drm_i915_gem_madvise)
240#define DRM_IOCTL_I915_OVERLAY_PUT_IMAGE DRM_IOW(DRM_COMMAND_BASE + DRM_I915_OVERLAY_PUT_IMAGE, struct drm_intel_overlay_put_image) 242#define DRM_IOCTL_I915_OVERLAY_PUT_IMAGE DRM_IOW(DRM_COMMAND_BASE + DRM_I915_OVERLAY_PUT_IMAGE, struct drm_intel_overlay_put_image)
241#define DRM_IOCTL_I915_OVERLAY_ATTRS DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_OVERLAY_ATTRS, struct drm_intel_overlay_attrs) 243#define DRM_IOCTL_I915_OVERLAY_ATTRS DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_OVERLAY_ATTRS, struct drm_intel_overlay_attrs)
244#define DRM_IOCTL_I915_SET_SPRITE_COLORKEY DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_SET_SPRITE_COLORKEY, struct drm_intel_sprite_colorkey)
245#define DRM_IOCTL_I915_GET_SPRITE_COLORKEY DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_SET_SPRITE_COLORKEY, struct drm_intel_sprite_colorkey)
242 246
243/* Allow drivers to submit batchbuffers directly to hardware, relying 247/* Allow drivers to submit batchbuffers directly to hardware, relying
244 * on the security mechanisms provided by hardware. 248 * on the security mechanisms provided by hardware.
@@ -844,4 +848,36 @@ struct drm_intel_overlay_attrs {
844 __u32 gamma5; 848 __u32 gamma5;
845}; 849};
846 850
851/*
852 * Intel sprite handling
853 *
854 * Color keying works with a min/mask/max tuple. Both source and destination
855 * color keying is allowed.
856 *
857 * Source keying:
858 * Sprite pixels within the min & max values, masked against the color channels
859 * specified in the mask field, will be transparent. All other pixels will
860 * be displayed on top of the primary plane. For RGB surfaces, only the min
861 * and mask fields will be used; ranged compares are not allowed.
862 *
863 * Destination keying:
864 * Primary plane pixels that match the min value, masked against the color
865 * channels specified in the mask field, will be replaced by corresponding
866 * pixels from the sprite plane.
867 *
868 * Note that source & destination keying are exclusive; only one can be
869 * active on a given plane.
870 */
871
872#define I915_SET_COLORKEY_NONE (1<<0) /* disable color key matching */
873#define I915_SET_COLORKEY_DESTINATION (1<<1)
874#define I915_SET_COLORKEY_SOURCE (1<<2)
875struct drm_intel_sprite_colorkey {
876 __u32 plane_id;
877 __u32 min_value;
878 __u32 channel_mask;
879 __u32 max_value;
880 __u32 flags;
881};
882
847#endif /* _I915_DRM_H_ */ 883#endif /* _I915_DRM_H_ */