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
23052305 DRM_IOCTL_DEF_DRV(I915_GEM_MADVISE, i915_gem_madvise_ioctl, DRM_UNLOCKED),
23062306 DRM_IOCTL_DEF_DRV(I915_OVERLAY_PUT_IMAGE, intel_overlay_put_image, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
23072307 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),
23082310 };
23092311
23102312 int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls);
drivers/gpu/drm/i915/i915_reg.h+3−0
@@ -2737,9 +2737,12 @@ · 2736 unmodified lines
27372737 #define DVSSTRIDE(pipe) _PIPE(pipe, _DVSASTRIDE, _DVSBSTRIDE)
27382738 #define DVSPOS(pipe) _PIPE(pipe, _DVSAPOS, _DVSBPOS)
27392739 #define DVSSURF(pipe) _PIPE(pipe, _DVSASURF, _DVSBSURF)
2740+#define DVSKEYMAX(pipe) _PIPE(pipe, _DVSAKEYMAXVAL, _DVSBKEYMAXVAL)
27402741 #define DVSSIZE(pipe) _PIPE(pipe, _DVSASIZE, _DVSBSIZE)
27412742 #define DVSSCALE(pipe) _PIPE(pipe, _DVSASCALE, _DVSBSCALE)
27422743 #define DVSTILEOFF(pipe) _PIPE(pipe, _DVSATILEOFF, _DVSBTILEOFF)
2744+#define DVSKEYVAL(pipe) _PIPE(pipe, _DVSAKEYVAL, _DVSBKEYVAL)
2745+#define DVSKEYMSK(pipe) _PIPE(pipe, _DVSAKEYMSK, _DVSBKEYMSK)
27432746
27442747 #define _SPRA_CTL 0x70280
27452748 #define SPRITE_ENABLE (1<<31)
drivers/gpu/drm/i915/intel_drv.h+11−0
@@ -26,6 +26,7 @@ · 25 unmodified lines
2626 #define __INTEL_DRV_H__
2727
2828 #include <linux/i2c.h>
29+#include "i915_drm.h"
2930 #include "i915_drv.h"
3031 #include "drm_crtc.h"
3132 #include "drm_crtc_helper.h"
@@ -192,6 +193,10 @@ struct intel_plane { · 160 unmodified lines
192193 uint32_t x, uint32_t y,
193194 uint32_t src_w, uint32_t src_h);
194195 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);
195200 };
196201
197202 #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
414419 extern void intel_update_sprite_watermarks(struct drm_device *dev, int pipe,
415420 uint32_t sprite_width,
416421 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+
417428 #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
9595 /* must disable */
9696 sprctl |= SPRITE_TRICKLE_FEED_DISABLE;
9797 sprctl |= SPRITE_ENABLE;
98+ sprctl |= SPRITE_DEST_KEY;
9899
99100 /* Sizes are 0 based */
100101 src_w--;
@@ -153,6 +154,60 @@ ivb_disable_plane(struct drm_plane *plane) · 52 unmodified lines
153154 POSTING_READ(SPRSURF(pipe));
154155 }
155156
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+
156211 static void
157212 snb_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb,
158213 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
278333 I915_WRITE(reg, I915_READ(reg) & ~DISPLAY_PLANE_ENABLE);
279334 }
280335
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+
281390 static int
282391 intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
283392 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
437546 kfree(intel_plane);
438547 }
439548
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+
440613 static const struct drm_plane_funcs intel_plane_funcs = {
441614 .update_plane = intel_update_plane,
442615 .disable_plane = intel_disable_plane,
@@ -472,10 +645,14 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe) · 29 unmodified lines
472645 intel_plane->max_downscale = 16;
473646 intel_plane->update_plane = snb_update_plane;
474647 intel_plane->disable_plane = snb_disable_plane;
648+ intel_plane->update_colorkey = snb_update_colorkey;
649+ intel_plane->get_colorkey = snb_get_colorkey;
475650 } else if (IS_GEN7(dev)) {
476651 intel_plane->max_downscale = 2;
477652 intel_plane->update_plane = ivb_update_plane;
478653 intel_plane->disable_plane = ivb_disable_plane;
654+ intel_plane->update_colorkey = ivb_update_colorkey;
655+ intel_plane->get_colorkey = ivb_get_colorkey;
479656 }
480657
481658 intel_plane->pipe = pipe;
include/drm/i915_drm.h+36−0
@@ -198,6 +198,8 @@ typedef struct _drm_i915_sarea { · 197 unmodified lines
198198 #define DRM_I915_OVERLAY_PUT_IMAGE 0x27
199199 #define DRM_I915_OVERLAY_ATTRS 0x28
200200 #define DRM_I915_GEM_EXECBUFFER2 0x29
201+#define DRM_I915_GET_SPRITE_COLORKEY 0x2a
202+#define DRM_I915_SET_SPRITE_COLORKEY 0x2b
201203
202204 #define DRM_IOCTL_I915_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t)
203205 #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
239241 #define DRM_IOCTL_I915_GEM_MADVISE DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_MADVISE, struct drm_i915_gem_madvise)
240242 #define DRM_IOCTL_I915_OVERLAY_PUT_IMAGE DRM_IOW(DRM_COMMAND_BASE + DRM_I915_OVERLAY_PUT_IMAGE, struct drm_intel_overlay_put_image)
241243 #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)
242246
243247 /* Allow drivers to submit batchbuffers directly to hardware, relying
244248 * on the security mechanisms provided by hardware.
@@ -844,4 +848,36 @@ struct drm_intel_overlay_attrs { · 599 unmodified lines
844848 __u32 gamma5;
845849 };
846850
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)
875+struct 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+
847883 #endif /* _I915_DRM_H_ */