History

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?)

Jesse Barnes committed 14 years ago

Commit 8ea30861 parent 175bd425 files · +229 −0Browse files

Unified · Split

5 files
  1. drivers/gpu/drm/i915/i915_dma.c +2 −0
  2. drivers/gpu/drm/i915/i915_reg.h +3 −0
  3. drivers/gpu/drm/i915/intel_drv.h +11 −0
  4. drivers/gpu/drm/i915/intel_sprite.c +177 −0
  5. include/drm/i915_drm.h +36 −0
drivers/gpu/drm/i915/i915_dma.c+2−0
@@ -2305,6 +2305,8 @@ struct drm_ioctl_desc i915_ioctls[] = { · 2304 unmodified lines
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);
drivers/gpu/drm/i915/i915_reg.h+3−0
@@ -2737,9 +2737,12 @@ · 2736 unmodified lines
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 0x702802747#define _SPRA_CTL 0x70280
2745#define SPRITE_ENABLE (1<<31)2748#define SPRITE_ENABLE (1<<31)
drivers/gpu/drm/i915/intel_drv.h+11−0
@@ -26,6 +26,7 @@ · 25 unmodified lines
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 { · 160 unmodified lines
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); · 216 unmodified lines
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__ */
drivers/gpu/drm/i915/intel_sprite.c+177−0
@@ -95,6 +95,7 @@ ivb_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb, · 94 unmodified lines
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) · 52 unmodified lines
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 void211static 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,
@@ -278,6 +333,60 @@ intel_disable_primary(struct drm_crtc *crtc) · 119 unmodified lines
278 I915_WRITE(reg, I915_READ(reg) & ~DISPLAY_PLANE_ENABLE);333 I915_WRITE(reg, I915_READ(reg) & ~DISPLAY_PLANE_ENABLE);
279}334}
280 335
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
281static int390static 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,
@@ -437,6 +546,70 @@ static void intel_destroy_plane(struct drm_plane *plane) · 153 unmodified lines
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) · 29 unmodified lines
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;
include/drm/i915_drm.h+36−0
@@ -198,6 +198,8 @@ typedef struct _drm_i915_sarea { · 197 unmodified lines
198#define DRM_I915_OVERLAY_PUT_IMAGE 0x27198#define DRM_I915_OVERLAY_PUT_IMAGE 0x27
199#define DRM_I915_OVERLAY_ATTRS 0x28199#define DRM_I915_OVERLAY_ATTRS 0x28
200#define DRM_I915_GEM_EXECBUFFER2 0x29200#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 { · 35 unmodified lines
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, relying247/* 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 { · 599 unmodified lines
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_ */