mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-24 01:41:39 +00:00
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>
This commit is contained in:
parent
175bd4204e
commit
8ea3086422
5 changed files with 229 additions and 0 deletions
|
@ -2305,6 +2305,8 @@ struct drm_ioctl_desc i915_ioctls[] = {
|
|||
DRM_IOCTL_DEF_DRV(I915_GEM_MADVISE, i915_gem_madvise_ioctl, DRM_UNLOCKED),
|
||||
DRM_IOCTL_DEF_DRV(I915_OVERLAY_PUT_IMAGE, intel_overlay_put_image, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
|
||||
DRM_IOCTL_DEF_DRV(I915_OVERLAY_ATTRS, intel_overlay_attrs, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
|
||||
DRM_IOCTL_DEF_DRV(I915_SET_SPRITE_COLORKEY, intel_sprite_set_colorkey, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
|
||||
DRM_IOCTL_DEF_DRV(I915_GET_SPRITE_COLORKEY, intel_sprite_get_colorkey, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
|
||||
};
|
||||
|
||||
int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls);
|
||||
|
|
|
@ -2737,9 +2737,12 @@
|
|||
#define DVSSTRIDE(pipe) _PIPE(pipe, _DVSASTRIDE, _DVSBSTRIDE)
|
||||
#define DVSPOS(pipe) _PIPE(pipe, _DVSAPOS, _DVSBPOS)
|
||||
#define DVSSURF(pipe) _PIPE(pipe, _DVSASURF, _DVSBSURF)
|
||||
#define DVSKEYMAX(pipe) _PIPE(pipe, _DVSAKEYMAXVAL, _DVSBKEYMAXVAL)
|
||||
#define DVSSIZE(pipe) _PIPE(pipe, _DVSASIZE, _DVSBSIZE)
|
||||
#define DVSSCALE(pipe) _PIPE(pipe, _DVSASCALE, _DVSBSCALE)
|
||||
#define DVSTILEOFF(pipe) _PIPE(pipe, _DVSATILEOFF, _DVSBTILEOFF)
|
||||
#define DVSKEYVAL(pipe) _PIPE(pipe, _DVSAKEYVAL, _DVSBKEYVAL)
|
||||
#define DVSKEYMSK(pipe) _PIPE(pipe, _DVSAKEYMSK, _DVSBKEYMSK)
|
||||
|
||||
#define _SPRA_CTL 0x70280
|
||||
#define SPRITE_ENABLE (1<<31)
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#define __INTEL_DRV_H__
|
||||
|
||||
#include <linux/i2c.h>
|
||||
#include "i915_drm.h"
|
||||
#include "i915_drv.h"
|
||||
#include "drm_crtc.h"
|
||||
#include "drm_crtc_helper.h"
|
||||
|
@ -192,6 +193,10 @@ struct intel_plane {
|
|||
uint32_t x, uint32_t y,
|
||||
uint32_t src_w, uint32_t src_h);
|
||||
void (*disable_plane)(struct drm_plane *plane);
|
||||
int (*update_colorkey)(struct drm_plane *plane,
|
||||
struct drm_intel_sprite_colorkey *key);
|
||||
void (*get_colorkey)(struct drm_plane *plane,
|
||||
struct drm_intel_sprite_colorkey *key);
|
||||
};
|
||||
|
||||
#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);
|
|||
extern void intel_update_sprite_watermarks(struct drm_device *dev, int pipe,
|
||||
uint32_t sprite_width,
|
||||
int pixel_size);
|
||||
|
||||
extern int intel_sprite_set_colorkey(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv);
|
||||
extern int intel_sprite_get_colorkey(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv);
|
||||
|
||||
#endif /* __INTEL_DRV_H__ */
|
||||
|
|
|
@ -95,6 +95,7 @@ ivb_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb,
|
|||
/* must disable */
|
||||
sprctl |= SPRITE_TRICKLE_FEED_DISABLE;
|
||||
sprctl |= SPRITE_ENABLE;
|
||||
sprctl |= SPRITE_DEST_KEY;
|
||||
|
||||
/* Sizes are 0 based */
|
||||
src_w--;
|
||||
|
@ -153,6 +154,60 @@ ivb_disable_plane(struct drm_plane *plane)
|
|||
POSTING_READ(SPRSURF(pipe));
|
||||
}
|
||||
|
||||
static int
|
||||
ivb_update_colorkey(struct drm_plane *plane,
|
||||
struct drm_intel_sprite_colorkey *key)
|
||||
{
|
||||
struct drm_device *dev = plane->dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct intel_plane *intel_plane;
|
||||
u32 sprctl;
|
||||
int ret = 0;
|
||||
|
||||
intel_plane = to_intel_plane(plane);
|
||||
|
||||
I915_WRITE(SPRKEYVAL(intel_plane->pipe), key->min_value);
|
||||
I915_WRITE(SPRKEYMAX(intel_plane->pipe), key->max_value);
|
||||
I915_WRITE(SPRKEYMSK(intel_plane->pipe), key->channel_mask);
|
||||
|
||||
sprctl = I915_READ(SPRCTL(intel_plane->pipe));
|
||||
sprctl &= ~(SPRITE_SOURCE_KEY | SPRITE_DEST_KEY);
|
||||
if (key->flags & I915_SET_COLORKEY_DESTINATION)
|
||||
sprctl |= SPRITE_DEST_KEY;
|
||||
else if (key->flags & I915_SET_COLORKEY_SOURCE)
|
||||
sprctl |= SPRITE_SOURCE_KEY;
|
||||
I915_WRITE(SPRCTL(intel_plane->pipe), sprctl);
|
||||
|
||||
POSTING_READ(SPRKEYMSK(intel_plane->pipe));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
ivb_get_colorkey(struct drm_plane *plane, struct drm_intel_sprite_colorkey *key)
|
||||
{
|
||||
struct drm_device *dev = plane->dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct intel_plane *intel_plane;
|
||||
u32 sprctl;
|
||||
|
||||
intel_plane = to_intel_plane(plane);
|
||||
|
||||
key->min_value = I915_READ(SPRKEYVAL(intel_plane->pipe));
|
||||
key->max_value = I915_READ(SPRKEYMAX(intel_plane->pipe));
|
||||
key->channel_mask = I915_READ(SPRKEYMSK(intel_plane->pipe));
|
||||
key->flags = 0;
|
||||
|
||||
sprctl = I915_READ(SPRCTL(intel_plane->pipe));
|
||||
|
||||
if (sprctl & SPRITE_DEST_KEY)
|
||||
key->flags = I915_SET_COLORKEY_DESTINATION;
|
||||
else if (sprctl & SPRITE_SOURCE_KEY)
|
||||
key->flags = I915_SET_COLORKEY_SOURCE;
|
||||
else
|
||||
key->flags = I915_SET_COLORKEY_NONE;
|
||||
}
|
||||
|
||||
static void
|
||||
snb_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb,
|
||||
struct drm_i915_gem_object *obj, int crtc_x, int crtc_y,
|
||||
|
@ -278,6 +333,60 @@ intel_disable_primary(struct drm_crtc *crtc)
|
|||
I915_WRITE(reg, I915_READ(reg) & ~DISPLAY_PLANE_ENABLE);
|
||||
}
|
||||
|
||||
static int
|
||||
snb_update_colorkey(struct drm_plane *plane,
|
||||
struct drm_intel_sprite_colorkey *key)
|
||||
{
|
||||
struct drm_device *dev = plane->dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct intel_plane *intel_plane;
|
||||
u32 dvscntr;
|
||||
int ret = 0;
|
||||
|
||||
intel_plane = to_intel_plane(plane);
|
||||
|
||||
I915_WRITE(DVSKEYVAL(intel_plane->pipe), key->min_value);
|
||||
I915_WRITE(DVSKEYMAX(intel_plane->pipe), key->max_value);
|
||||
I915_WRITE(DVSKEYMSK(intel_plane->pipe), key->channel_mask);
|
||||
|
||||
dvscntr = I915_READ(DVSCNTR(intel_plane->pipe));
|
||||
dvscntr &= ~(DVS_SOURCE_KEY | DVS_DEST_KEY);
|
||||
if (key->flags & I915_SET_COLORKEY_DESTINATION)
|
||||
dvscntr |= DVS_DEST_KEY;
|
||||
else if (key->flags & I915_SET_COLORKEY_SOURCE)
|
||||
dvscntr |= DVS_SOURCE_KEY;
|
||||
I915_WRITE(DVSCNTR(intel_plane->pipe), dvscntr);
|
||||
|
||||
POSTING_READ(DVSKEYMSK(intel_plane->pipe));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
snb_get_colorkey(struct drm_plane *plane, struct drm_intel_sprite_colorkey *key)
|
||||
{
|
||||
struct drm_device *dev = plane->dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct intel_plane *intel_plane;
|
||||
u32 dvscntr;
|
||||
|
||||
intel_plane = to_intel_plane(plane);
|
||||
|
||||
key->min_value = I915_READ(DVSKEYVAL(intel_plane->pipe));
|
||||
key->max_value = I915_READ(DVSKEYMAX(intel_plane->pipe));
|
||||
key->channel_mask = I915_READ(DVSKEYMSK(intel_plane->pipe));
|
||||
key->flags = 0;
|
||||
|
||||
dvscntr = I915_READ(DVSCNTR(intel_plane->pipe));
|
||||
|
||||
if (dvscntr & DVS_DEST_KEY)
|
||||
key->flags = I915_SET_COLORKEY_DESTINATION;
|
||||
else if (dvscntr & DVS_SOURCE_KEY)
|
||||
key->flags = I915_SET_COLORKEY_SOURCE;
|
||||
else
|
||||
key->flags = I915_SET_COLORKEY_NONE;
|
||||
}
|
||||
|
||||
static int
|
||||
intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
|
||||
struct drm_framebuffer *fb, int crtc_x, int crtc_y,
|
||||
|
@ -437,6 +546,70 @@ static void intel_destroy_plane(struct drm_plane *plane)
|
|||
kfree(intel_plane);
|
||||
}
|
||||
|
||||
int intel_sprite_set_colorkey(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
struct drm_intel_sprite_colorkey *set = data;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct drm_mode_object *obj;
|
||||
struct drm_plane *plane;
|
||||
struct intel_plane *intel_plane;
|
||||
int ret = 0;
|
||||
|
||||
if (!dev_priv)
|
||||
return -EINVAL;
|
||||
|
||||
/* Make sure we don't try to enable both src & dest simultaneously */
|
||||
if ((set->flags & (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE)) == (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE))
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&dev->mode_config.mutex);
|
||||
|
||||
obj = drm_mode_object_find(dev, set->plane_id, DRM_MODE_OBJECT_PLANE);
|
||||
if (!obj) {
|
||||
ret = -EINVAL;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
plane = obj_to_plane(obj);
|
||||
intel_plane = to_intel_plane(plane);
|
||||
ret = intel_plane->update_colorkey(plane, set);
|
||||
|
||||
out_unlock:
|
||||
mutex_unlock(&dev->mode_config.mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int intel_sprite_get_colorkey(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
struct drm_intel_sprite_colorkey *get = data;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct drm_mode_object *obj;
|
||||
struct drm_plane *plane;
|
||||
struct intel_plane *intel_plane;
|
||||
int ret = 0;
|
||||
|
||||
if (!dev_priv)
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&dev->mode_config.mutex);
|
||||
|
||||
obj = drm_mode_object_find(dev, get->plane_id, DRM_MODE_OBJECT_PLANE);
|
||||
if (!obj) {
|
||||
ret = -EINVAL;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
plane = obj_to_plane(obj);
|
||||
intel_plane = to_intel_plane(plane);
|
||||
intel_plane->get_colorkey(plane, get);
|
||||
|
||||
out_unlock:
|
||||
mutex_unlock(&dev->mode_config.mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct drm_plane_funcs intel_plane_funcs = {
|
||||
.update_plane = intel_update_plane,
|
||||
.disable_plane = intel_disable_plane,
|
||||
|
@ -472,10 +645,14 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe)
|
|||
intel_plane->max_downscale = 16;
|
||||
intel_plane->update_plane = snb_update_plane;
|
||||
intel_plane->disable_plane = snb_disable_plane;
|
||||
intel_plane->update_colorkey = snb_update_colorkey;
|
||||
intel_plane->get_colorkey = snb_get_colorkey;
|
||||
} else if (IS_GEN7(dev)) {
|
||||
intel_plane->max_downscale = 2;
|
||||
intel_plane->update_plane = ivb_update_plane;
|
||||
intel_plane->disable_plane = ivb_disable_plane;
|
||||
intel_plane->update_colorkey = ivb_update_colorkey;
|
||||
intel_plane->get_colorkey = ivb_get_colorkey;
|
||||
}
|
||||
|
||||
intel_plane->pipe = pipe;
|
||||
|
|
|
@ -198,6 +198,8 @@ typedef struct _drm_i915_sarea {
|
|||
#define DRM_I915_OVERLAY_PUT_IMAGE 0x27
|
||||
#define DRM_I915_OVERLAY_ATTRS 0x28
|
||||
#define DRM_I915_GEM_EXECBUFFER2 0x29
|
||||
#define DRM_I915_GET_SPRITE_COLORKEY 0x2a
|
||||
#define DRM_I915_SET_SPRITE_COLORKEY 0x2b
|
||||
|
||||
#define DRM_IOCTL_I915_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t)
|
||||
#define DRM_IOCTL_I915_FLUSH DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH)
|
||||
|
@ -239,6 +241,8 @@ typedef struct _drm_i915_sarea {
|
|||
#define DRM_IOCTL_I915_GEM_MADVISE DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_MADVISE, struct drm_i915_gem_madvise)
|
||||
#define DRM_IOCTL_I915_OVERLAY_PUT_IMAGE DRM_IOW(DRM_COMMAND_BASE + DRM_I915_OVERLAY_PUT_IMAGE, struct drm_intel_overlay_put_image)
|
||||
#define DRM_IOCTL_I915_OVERLAY_ATTRS DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_OVERLAY_ATTRS, struct drm_intel_overlay_attrs)
|
||||
#define DRM_IOCTL_I915_SET_SPRITE_COLORKEY DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_SET_SPRITE_COLORKEY, struct drm_intel_sprite_colorkey)
|
||||
#define DRM_IOCTL_I915_GET_SPRITE_COLORKEY DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_SET_SPRITE_COLORKEY, struct drm_intel_sprite_colorkey)
|
||||
|
||||
/* Allow drivers to submit batchbuffers directly to hardware, relying
|
||||
* on the security mechanisms provided by hardware.
|
||||
|
@ -844,4 +848,36 @@ struct drm_intel_overlay_attrs {
|
|||
__u32 gamma5;
|
||||
};
|
||||
|
||||
/*
|
||||
* Intel sprite handling
|
||||
*
|
||||
* Color keying works with a min/mask/max tuple. Both source and destination
|
||||
* color keying is allowed.
|
||||
*
|
||||
* Source keying:
|
||||
* Sprite pixels within the min & max values, masked against the color channels
|
||||
* specified in the mask field, will be transparent. All other pixels will
|
||||
* be displayed on top of the primary plane. For RGB surfaces, only the min
|
||||
* and mask fields will be used; ranged compares are not allowed.
|
||||
*
|
||||
* Destination keying:
|
||||
* Primary plane pixels that match the min value, masked against the color
|
||||
* channels specified in the mask field, will be replaced by corresponding
|
||||
* pixels from the sprite plane.
|
||||
*
|
||||
* Note that source & destination keying are exclusive; only one can be
|
||||
* active on a given plane.
|
||||
*/
|
||||
|
||||
#define I915_SET_COLORKEY_NONE (1<<0) /* disable color key matching */
|
||||
#define I915_SET_COLORKEY_DESTINATION (1<<1)
|
||||
#define I915_SET_COLORKEY_SOURCE (1<<2)
|
||||
struct drm_intel_sprite_colorkey {
|
||||
__u32 plane_id;
|
||||
__u32 min_value;
|
||||
__u32 channel_mask;
|
||||
__u32 max_value;
|
||||
__u32 flags;
|
||||
};
|
||||
|
||||
#endif /* _I915_DRM_H_ */
|
||||
|
|
Loading…
Reference in a new issue