All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] DRM planes
@ 2011-11-02 20:03 Jesse Barnes
  2011-11-02 20:03 ` [PATCH 1/5] drm: add plane support Jesse Barnes
                   ` (5 more replies)
  0 siblings, 6 replies; 32+ messages in thread
From: Jesse Barnes @ 2011-11-02 20:03 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx, rob.clark

In response to feedback, I've adjusted the new addfb2 ioctl to take per
component pitch and offset args.  Generally, the offset[0] field will be
0, but it's conceivable that some metadata could be stored at the start
of a given buffer, and an offset[0] allows the client to skip past that.
Similarly, pitch[0] will typically describe the whole buffer, but it's
possible to simply string together several planes into a single object
where individual pitch components matter.

Userland patches are available in the drm-overlays branches of my
personal libdrm and xf86-video-intel trees at freedesktop.org.  The
xf86-video-intel side works well enough to handle clipping (using a new
i915 specific ioctl for setting a destination color key) and play
videos, albeit without nice flipping.

Assuming no major objections, I think this is finally ready for
drm-next.

Thanks,
Jesse

^ permalink raw reply	[flat|nested] 32+ messages in thread

* [PATCH 1/5] drm: add plane support
  2011-11-02 20:03 [PATCH] DRM planes Jesse Barnes
@ 2011-11-02 20:03 ` Jesse Barnes
  2011-11-02 22:33   ` Jesse Barnes
  2011-11-04  2:22   ` Joonyoung Shim
  2011-11-02 20:03 ` [PATCH 2/5] drm: add an fb creation ioctl that takes a pixel format Jesse Barnes
                   ` (4 subsequent siblings)
  5 siblings, 2 replies; 32+ messages in thread
From: Jesse Barnes @ 2011-11-02 20:03 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx, rob.clark

Planes are a bit like half-CRTCs.  They have a location and fb, but
don't drive outputs directly.  Add support for handling them to the core
KMS code.

Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
---
 drivers/gpu/drm/drm_crtc.c |  236 +++++++++++++++++++++++++++++++++++++++++++-
 drivers/gpu/drm/drm_drv.c  |    3 +
 include/drm/drm.h          |    3 +
 include/drm/drm_crtc.h     |   76 ++++++++++++++-
 include/drm/drm_mode.h     |   33 ++++++
 5 files changed, 348 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index fe738f0..0e129b1 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -535,6 +535,48 @@ void drm_encoder_cleanup(struct drm_encoder *encoder)
 }
 EXPORT_SYMBOL(drm_encoder_cleanup);
 
+void drm_plane_init(struct drm_device *dev, struct drm_plane *plane,
+		    unsigned long possible_crtcs,
+		    const struct drm_plane_funcs *funcs,
+		    uint32_t *formats, uint32_t format_count)
+{
+	mutex_lock(&dev->mode_config.mutex);
+
+	plane->dev = dev;
+	drm_mode_object_get(dev, &plane->base, DRM_MODE_OBJECT_PLANE);
+	plane->funcs = funcs;
+	plane->format_types = kmalloc(sizeof(uint32_t) * format_count,
+				      GFP_KERNEL);
+	if (!plane->format_types) {
+		DRM_DEBUG_KMS("out of memory when allocating plane\n");
+		drm_mode_object_put(dev, &plane->base);
+		return;
+	}
+
+	memcpy(plane->format_types, formats, format_count);
+	plane->format_count = format_count;
+	plane->possible_crtcs = possible_crtcs;
+
+	list_add_tail(&plane->head, &dev->mode_config.plane_list);
+	dev->mode_config.num_plane++;
+
+	mutex_unlock(&dev->mode_config.mutex);
+}
+EXPORT_SYMBOL(drm_plane_init);
+
+void drm_plane_cleanup(struct drm_plane *plane)
+{
+	struct drm_device *dev = plane->dev;
+
+	mutex_lock(&dev->mode_config.mutex);
+	kfree(plane->format_types);
+	drm_mode_object_put(dev, &plane->base);
+	list_del(&plane->head);
+	dev->mode_config.num_plane--;
+	mutex_unlock(&dev->mode_config.mutex);
+}
+EXPORT_SYMBOL(drm_plane_cleanup);
+
 /**
  * drm_mode_create - create a new display mode
  * @dev: DRM device
@@ -866,6 +908,7 @@ void drm_mode_config_init(struct drm_device *dev)
 	INIT_LIST_HEAD(&dev->mode_config.encoder_list);
 	INIT_LIST_HEAD(&dev->mode_config.property_list);
 	INIT_LIST_HEAD(&dev->mode_config.property_blob_list);
+	INIT_LIST_HEAD(&dev->mode_config.plane_list);
 	idr_init(&dev->mode_config.crtc_idr);
 
 	mutex_lock(&dev->mode_config.mutex);
@@ -1466,6 +1509,193 @@ out:
 }
 
 /**
+ * drm_mode_getplane_res - get plane info
+ * @dev: DRM device
+ * @data: ioctl data
+ * @file_priv: DRM file info
+ *
+ * Return an plane count and set of IDs.
+ */
+int drm_mode_getplane_res(struct drm_device *dev, void *data,
+			    struct drm_file *file_priv)
+{
+	struct drm_mode_get_plane_res *plane_resp = data;
+	struct drm_mode_config *config;
+	struct drm_plane *plane;
+	uint32_t __user *plane_ptr;
+	int copied = 0, ret = 0;
+
+	if (!drm_core_check_feature(dev, DRIVER_MODESET))
+		return -EINVAL;
+
+	mutex_lock(&dev->mode_config.mutex);
+	config = &dev->mode_config;
+
+	/*
+	 * This ioctl is called twice, once to determine how much space is
+	 * needed, and the 2nd time to fill it.
+	 */
+	if (config->num_plane &&
+	    (plane_resp->count_planes >= config->num_plane)) {
+		plane_ptr = (uint32_t *)(unsigned long)plane_resp->plane_id_ptr;
+
+		list_for_each_entry(plane, &config->plane_list, head) {
+			if (put_user(plane->base.id, plane_ptr + copied)) {
+				ret = -EFAULT;
+				goto out;
+			}
+			copied++;
+		}
+	}
+	plane_resp->count_planes = config->num_plane;
+
+out:
+	mutex_unlock(&dev->mode_config.mutex);
+	return ret;
+}
+
+/**
+ * drm_mode_getplane - get plane info
+ * @dev: DRM device
+ * @data: ioctl data
+ * @file_priv: DRM file info
+ *
+ * Return plane info, including formats supported, gamma size, any
+ * current fb, etc.
+ */
+int drm_mode_getplane(struct drm_device *dev, void *data,
+			struct drm_file *file_priv)
+{
+	struct drm_mode_get_plane *plane_resp = data;
+	struct drm_mode_object *obj;
+	struct drm_plane *plane;
+	uint32_t __user *format_ptr;
+	int ret = 0;
+
+	if (!drm_core_check_feature(dev, DRIVER_MODESET))
+		return -EINVAL;
+
+	mutex_lock(&dev->mode_config.mutex);
+	obj = drm_mode_object_find(dev, plane_resp->plane_id,
+				   DRM_MODE_OBJECT_PLANE);
+	if (!obj) {
+		ret = -EINVAL;
+		goto out;
+	}
+	plane = obj_to_plane(obj);
+
+	if (plane->crtc)
+		plane_resp->crtc_id = plane->crtc->base.id;
+	else
+		plane_resp->crtc_id = 0;
+
+	if (plane->fb)
+		plane_resp->fb_id = plane->fb->base.id;
+	else
+		plane_resp->fb_id = 0;
+
+	plane_resp->plane_id = plane->base.id;
+	plane_resp->possible_crtcs = plane->possible_crtcs;
+	plane_resp->gamma_size = plane->gamma_size;
+
+	/*
+	 * This ioctl is called twice, once to determine how much space is
+	 * needed, and the 2nd time to fill it.
+	 */
+	if (plane->format_count &&
+	    (plane_resp->count_format_types >= plane->format_count)) {
+		format_ptr = (uint32_t *)(unsigned long)plane_resp->format_type_ptr;
+		if (copy_to_user(format_ptr,
+				 plane->format_types,
+				 sizeof(uint32_t) * plane->format_count)) {
+			ret = -EFAULT;
+			goto out;
+		}
+	}
+	plane_resp->count_format_types = plane->format_count;
+
+out:
+	mutex_unlock(&dev->mode_config.mutex);
+	return ret;
+}
+
+/**
+ * drm_mode_setplane - set up or tear down an plane
+ * @dev: DRM device
+ * @data: ioctl data*
+ * @file_prive: DRM file info
+ *
+ * Set plane info, including placement, fb, scaling, and other factors.
+ * Or pass a NULL fb to disable.
+ */
+int drm_mode_setplane(struct drm_device *dev, void *data,
+			struct drm_file *file_priv)
+{
+	struct drm_mode_set_plane *plane_req = data;
+	struct drm_mode_object *obj;
+	struct drm_plane *plane;
+	struct drm_crtc *crtc;
+	struct drm_framebuffer *fb;
+	int ret = 0;
+
+	if (!drm_core_check_feature(dev, DRIVER_MODESET))
+		return -EINVAL;
+
+	mutex_lock(&dev->mode_config.mutex);
+
+	/*
+	 * First, find the plane, crtc, and fb objects.  If not available,
+	 * we don't bother to call the driver.
+	 */
+	obj = drm_mode_object_find(dev, plane_req->plane_id,
+				   DRM_MODE_OBJECT_PLANE);
+	if (!obj) {
+		DRM_DEBUG_KMS("Unknown plane ID %d\n",
+			      plane_req->plane_id);
+		ret = -EINVAL;
+		goto out;
+	}
+	plane = obj_to_plane(obj);
+
+	/* No fb means shut it down */
+	if (!plane_req->fb_id) {
+		plane->funcs->disable_plane(plane);
+		goto out;
+	}
+
+	obj = drm_mode_object_find(dev, plane_req->crtc_id,
+				   DRM_MODE_OBJECT_CRTC);
+	if (!obj) {
+		DRM_DEBUG_KMS("Unknown crtc ID %d\n",
+			      plane_req->crtc_id);
+		ret = -EINVAL;
+		goto out;
+	}
+	crtc = obj_to_crtc(obj);
+
+	obj = drm_mode_object_find(dev, plane_req->fb_id,
+				   DRM_MODE_OBJECT_FB);
+	if (!obj) {
+		DRM_DEBUG_KMS("Unknown framebuffer ID %d\n",
+			      plane_req->fb_id);
+		ret = -EINVAL;
+		goto out;
+	}
+	fb = obj_to_fb(obj);
+
+	ret = plane->funcs->update_plane(plane, crtc, fb,
+					 plane_req->crtc_x, plane_req->crtc_y,
+					 plane_req->crtc_w, plane_req->crtc_h,
+					 plane_req->src_x, plane_req->src_y,
+					 plane_req->src_h, plane_req->src_w);
+
+out:
+	mutex_unlock(&dev->mode_config.mutex);
+
+	return ret;
+}
+
+/**
  * drm_mode_setcrtc - set CRTC configuration
  * @inode: inode from the ioctl
  * @filp: file * from the ioctl
@@ -1688,11 +1918,13 @@ int drm_mode_addfb(struct drm_device *dev,
 		return -EINVAL;
 
 	if ((config->min_width > r->width) || (r->width > config->max_width)) {
-		DRM_ERROR("mode new framebuffer width not within limits\n");
+		DRM_ERROR("bad framebuffer width %d, should be >= %d && <= %d\n",
+			  r->width, config->min_width, config->max_width);
 		return -EINVAL;
 	}
 	if ((config->min_height > r->height) || (r->height > config->max_height)) {
-		DRM_ERROR("mode new framebuffer height not within limits\n");
+		DRM_ERROR("bad framebuffer height %d, should be >= %d && <= %d\n",
+			  r->height, config->min_height, config->max_height);
 		return -EINVAL;
 	}
 
diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
index 93a112d..15da618 100644
--- a/drivers/gpu/drm/drm_drv.c
+++ b/drivers/gpu/drm/drm_drv.c
@@ -135,8 +135,11 @@ static struct drm_ioctl_desc drm_ioctls[] = {
 	DRM_IOCTL_DEF(DRM_IOCTL_GEM_OPEN, drm_gem_open_ioctl, DRM_AUTH|DRM_UNLOCKED),
 
 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETRESOURCES, drm_mode_getresources, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPLANERESOURCES, drm_mode_getplane_res, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCRTC, drm_mode_getcrtc, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETCRTC, drm_mode_setcrtc, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPLANE, drm_mode_getplane, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETPLANE, drm_mode_setplane, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_CURSOR, drm_mode_cursor_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETGAMMA, drm_mode_gamma_get_ioctl, DRM_MASTER|DRM_UNLOCKED),
 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETGAMMA, drm_mode_gamma_set_ioctl, DRM_MASTER|DRM_UNLOCKED),
diff --git a/include/drm/drm.h b/include/drm/drm.h
index 4be33b4..2897967 100644
--- a/include/drm/drm.h
+++ b/include/drm/drm.h
@@ -714,6 +714,9 @@ struct drm_get_cap {
 #define DRM_IOCTL_MODE_CREATE_DUMB DRM_IOWR(0xB2, struct drm_mode_create_dumb)
 #define DRM_IOCTL_MODE_MAP_DUMB    DRM_IOWR(0xB3, struct drm_mode_map_dumb)
 #define DRM_IOCTL_MODE_DESTROY_DUMB    DRM_IOWR(0xB4, struct drm_mode_destroy_dumb)
+#define DRM_IOCTL_MODE_GETPLANERESOURCES DRM_IOWR(0xB5, struct drm_mode_get_plane_res)
+#define DRM_IOCTL_MODE_GETPLANE	DRM_IOWR(0xB6, struct drm_mode_get_plane)
+#define DRM_IOCTL_MODE_SETPLANE	DRM_IOWR(0xB7, struct drm_mode_set_plane)
 
 /**
  * Device specific ioctls should only be in their respective headers
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 8020798..b4519f8 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -44,6 +44,7 @@ struct drm_framebuffer;
 #define DRM_MODE_OBJECT_PROPERTY 0xb0b0b0b0
 #define DRM_MODE_OBJECT_FB 0xfbfbfbfb
 #define DRM_MODE_OBJECT_BLOB 0xbbbbbbbb
+#define DRM_MODE_OBJECT_PLANE 0xeeeeeeee
 
 struct drm_mode_object {
 	uint32_t id;
@@ -278,6 +279,7 @@ struct drm_crtc;
 struct drm_connector;
 struct drm_encoder;
 struct drm_pending_vblank_event;
+struct drm_plane;
 
 /**
  * drm_crtc_funcs - control CRTCs for a given device
@@ -536,6 +538,63 @@ struct drm_connector {
 };
 
 /**
+ * drm_plane_funcs - driver plane control functions
+ * @update_plane: update the plane configuration
+ */
+struct drm_plane_funcs {
+	int (*update_plane)(struct drm_plane *plane,
+			    struct drm_crtc *crtc, struct drm_framebuffer *fb,
+			    int crtc_x, int crtc_y,
+			    unsigned int crtc_w, unsigned int crtc_h,
+			    uint32_t src_x, uint32_t src_y,
+			    uint32_t src_w, uint32_t src_h);
+	int (*disable_plane)(struct drm_plane *plane);
+};
+
+/**
+ * drm_plane - central DRM plane control structure
+ * @dev: DRM device this plane belongs to
+ * @kdev: kernel device
+ * @attr: kdev attributes
+ * @head: for list management
+ * @base: base mode object
+ * @possible_crtcs: pipes this plane can be bound to
+ * @format_types: array of formats supported by this plane
+ * @format_count: number of formats supported
+ * @crtc: currently bound CRTC
+ * @fb: currently bound fb
+ * @gamma_size: size of gamma table
+ * @gamma_store: gamma correction table
+ * @enabled: enabled flag
+ * @funcs: helper functions
+ * @helper_private: storage for drver layer
+ */
+struct drm_plane {
+	struct drm_device *dev;
+	struct device kdev;
+	struct device_attribute *attr;
+	struct list_head head;
+
+	struct drm_mode_object base;
+
+	uint32_t possible_crtcs;
+	uint32_t *format_types;
+	uint32_t format_count;
+
+	struct drm_crtc *crtc;
+	struct drm_framebuffer *fb;
+
+	/* CRTC gamma size for reporting to userspace */
+	uint32_t gamma_size;
+	uint16_t *gamma_store;
+
+	bool enabled;
+
+	const struct drm_plane_funcs *funcs;
+	void *helper_private;
+};
+
+/**
  * struct drm_mode_set
  *
  * Represents a single crtc the connectors that it drives with what mode
@@ -589,6 +648,8 @@ struct drm_mode_config {
 	struct list_head connector_list;
 	int num_encoder;
 	struct list_head encoder_list;
+	int num_plane;
+	struct list_head plane_list;
 
 	int num_crtc;
 	struct list_head crtc_list;
@@ -641,6 +702,7 @@ struct drm_mode_config {
 #define obj_to_fb(x) container_of(x, struct drm_framebuffer, base)
 #define obj_to_property(x) container_of(x, struct drm_property, base)
 #define obj_to_blob(x) container_of(x, struct drm_property_blob, base)
+#define obj_to_plane(x) container_of(x, struct drm_plane, base)
 
 
 extern void drm_crtc_init(struct drm_device *dev,
@@ -660,6 +722,13 @@ extern void drm_encoder_init(struct drm_device *dev,
 			     const struct drm_encoder_funcs *funcs,
 			     int encoder_type);
 
+extern void drm_plane_init(struct drm_device *dev,
+			   struct drm_plane *plane,
+			   unsigned long possible_crtcs,
+			   const struct drm_plane_funcs *funcs,
+			   uint32_t *formats, uint32_t format_count);
+extern void drm_plane_cleanup(struct drm_plane *plane);
+
 extern void drm_encoder_cleanup(struct drm_encoder *encoder);
 
 extern char *drm_get_connector_name(struct drm_connector *connector);
@@ -753,13 +822,18 @@ extern struct drm_mode_object *drm_mode_object_find(struct drm_device *dev,
 /* IOCTLs */
 extern int drm_mode_getresources(struct drm_device *dev,
 				 void *data, struct drm_file *file_priv);
-
+extern int drm_mode_getplane_res(struct drm_device *dev, void *data,
+				   struct drm_file *file_priv);
 extern int drm_mode_getcrtc(struct drm_device *dev,
 			    void *data, struct drm_file *file_priv);
 extern int drm_mode_getconnector(struct drm_device *dev,
 			      void *data, struct drm_file *file_priv);
 extern int drm_mode_setcrtc(struct drm_device *dev,
 			    void *data, struct drm_file *file_priv);
+extern int drm_mode_getplane(struct drm_device *dev,
+			       void *data, struct drm_file *file_priv);
+extern int drm_mode_setplane(struct drm_device *dev,
+			       void *data, struct drm_file *file_priv);
 extern int drm_mode_cursor_ioctl(struct drm_device *dev,
 				void *data, struct drm_file *file_priv);
 extern int drm_mode_addfb(struct drm_device *dev,
diff --git a/include/drm/drm_mode.h b/include/drm/drm_mode.h
index c4961ea..07711b0 100644
--- a/include/drm/drm_mode.h
+++ b/include/drm/drm_mode.h
@@ -120,6 +120,39 @@ struct drm_mode_crtc {
 	struct drm_mode_modeinfo mode;
 };
 
+/* Planes blend with or override other bits on the CRTC */
+struct drm_mode_set_plane {
+	__u32 plane_id;
+	__u32 crtc_id;
+	__u32 fb_id; /* fb object contains surface format type */
+
+	/* Signed dest location allows it to be partially off screen */
+	__s32 crtc_x, crtc_y;
+	__u32 crtc_w, crtc_h;
+
+	/* Source values are 16.16 fixed point */
+	__u32 src_x, src_y;
+	__u32 src_h, src_w;
+};
+
+struct drm_mode_get_plane {
+	__u64 format_type_ptr;
+	__u32 plane_id;
+
+	__u32 crtc_id;
+	__u32 fb_id;
+
+	__u32 possible_crtcs;
+	__u32 gamma_size;
+
+	__u32 count_format_types;
+};
+
+struct drm_mode_get_plane_res {
+	__u64 plane_id_ptr;
+	__u32 count_planes;
+};
+
 #define DRM_MODE_ENCODER_NONE	0
 #define DRM_MODE_ENCODER_DAC	1
 #define DRM_MODE_ENCODER_TMDS	2
-- 
1.7.4.1

^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [PATCH 2/5] drm: add an fb creation ioctl that takes a pixel format
  2011-11-02 20:03 [PATCH] DRM planes Jesse Barnes
  2011-11-02 20:03 ` [PATCH 1/5] drm: add plane support Jesse Barnes
@ 2011-11-02 20:03 ` Jesse Barnes
  2011-11-03 18:22   ` Jesse Barnes
                     ` (2 more replies)
  2011-11-02 20:03 ` [PATCH 3/5] drm/i915: rename existing overlay support to "legacy" Jesse Barnes
                   ` (3 subsequent siblings)
  5 siblings, 3 replies; 32+ messages in thread
From: Jesse Barnes @ 2011-11-02 20:03 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx, rob.clark

To properly support the various plane formats supported by different
hardware, the kernel must know the pixel format of a framebuffer object.
So add a new ioctl taking a format argument corresponding to a fourcc
name from videodev2.h.

Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
---
 drivers/gpu/drm/drm_crtc.c                |  105 ++++++++++++++++++++++++++++-
 drivers/gpu/drm/drm_crtc_helper.c         |   50 +++++++++++++-
 drivers/gpu/drm/drm_drv.c                 |    1 +
 drivers/gpu/drm/i915/intel_display.c      |   34 +++++-----
 drivers/gpu/drm/i915/intel_drv.h          |    2 +-
 drivers/gpu/drm/i915/intel_fb.c           |   11 ++--
 drivers/gpu/drm/nouveau/nouveau_display.c |    4 +-
 drivers/gpu/drm/radeon/radeon_display.c   |    4 +-
 drivers/gpu/drm/radeon/radeon_fb.c        |   18 +++--
 drivers/gpu/drm/radeon/radeon_mode.h      |    2 +-
 drivers/gpu/drm/vmwgfx/vmwgfx_kms.c       |    2 +-
 drivers/staging/gma500/framebuffer.c      |    2 +-
 include/drm/drm.h                         |    1 +
 include/drm/drm_crtc.h                    |    7 ++-
 include/drm/drm_crtc_helper.h             |    4 +-
 include/drm/drm_mode.h                    |   26 +++++++
 include/linux/videodev2.h                 |    1 +
 17 files changed, 231 insertions(+), 43 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 0e129b1..ff47554 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -1889,6 +1889,42 @@ out:
 	return ret;
 }
 
+/* Original addfb only supported RGB formats, so figure out which one */
+uint32_t drm_mode_legacy_fb_format(uint32_t bpp, uint32_t depth)
+{
+	uint32_t fmt;
+
+	switch (bpp) {
+	case 8:
+		fmt = V4L2_PIX_FMT_RGB332;
+		break;
+	case 16:
+		if (depth == 15)
+			fmt = V4L2_PIX_FMT_RGB555;
+		else
+			fmt = V4L2_PIX_FMT_RGB565;
+		break;
+	case 24:
+		fmt = V4L2_PIX_FMT_RGB24;
+		break;
+	case 32:
+		if (depth == 24)
+			fmt = V4L2_PIX_FMT_RGB24;
+		else if (depth == 30)
+			fmt = V4L2_PIX_FMT_INTC_RGB30;
+		else
+			fmt = V4L2_PIX_FMT_RGB32;
+		break;
+	default:
+		DRM_ERROR("bad bpp, assuming RGB24 pixel format\n");
+		fmt = V4L2_PIX_FMT_RGB24;
+		break;
+	}
+
+	return fmt;
+}
+EXPORT_SYMBOL(drm_mode_legacy_fb_format);
+
 /**
  * drm_mode_addfb - add an FB to the graphics configuration
  * @inode: inode from the ioctl
@@ -1909,7 +1945,74 @@ out:
 int drm_mode_addfb(struct drm_device *dev,
 		   void *data, struct drm_file *file_priv)
 {
-	struct drm_mode_fb_cmd *r = data;
+	struct drm_mode_fb_cmd *or = data;
+	struct drm_mode_fb_cmd2 r;
+	struct drm_mode_config *config = &dev->mode_config;
+	struct drm_framebuffer *fb;
+	int ret = 0;
+
+	/* Use new struct with format internally */
+	r.fb_id = or->fb_id;
+	r.width = or->width;
+	r.height = or->height;
+	r.pitches[0] = or->pitch;
+	r.pixel_format = drm_mode_legacy_fb_format(or->bpp, or->depth);
+	r.handle = or->handle;
+
+	if (!drm_core_check_feature(dev, DRIVER_MODESET))
+		return -EINVAL;
+
+	if ((config->min_width > r.width) || (r.width > config->max_width)) {
+		DRM_ERROR("mode new framebuffer width not within limits\n");
+		return -EINVAL;
+	}
+	if ((config->min_height > r.height) || (r.height > config->max_height)) {
+		DRM_ERROR("mode new framebuffer height not within limits\n");
+		return -EINVAL;
+	}
+
+	mutex_lock(&dev->mode_config.mutex);
+
+	/* TODO check buffer is sufficiently large */
+	/* TODO setup destructor callback */
+
+	fb = dev->mode_config.funcs->fb_create(dev, file_priv, &r);
+	if (IS_ERR(fb)) {
+		DRM_ERROR("could not create framebuffer\n");
+		ret = PTR_ERR(fb);
+		goto out;
+	}
+
+	or->fb_id = fb->base.id;
+	list_add(&fb->filp_head, &file_priv->fbs);
+	DRM_DEBUG_KMS("[FB:%d]\n", fb->base.id);
+
+out:
+	mutex_unlock(&dev->mode_config.mutex);
+	return ret;
+}
+
+/**
+ * drm_mode_addfb2 - add an FB to the graphics configuration
+ * @inode: inode from the ioctl
+ * @filp: file * from the ioctl
+ * @cmd: cmd from ioctl
+ * @arg: arg from ioctl
+ *
+ * LOCKING:
+ * Takes mode config lock.
+ *
+ * Add a new FB to the specified CRTC, given a user request with format.
+ *
+ * Called by the user via ioctl.
+ *
+ * RETURNS:
+ * Zero on success, errno on failure.
+ */
+int drm_mode_addfb2(struct drm_device *dev,
+		    void *data, struct drm_file *file_priv)
+{
+	struct drm_mode_fb_cmd2 *r = data;
 	struct drm_mode_config *config = &dev->mode_config;
 	struct drm_framebuffer *fb;
 	int ret = 0;
diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c
index f88a9b2..0573f12 100644
--- a/drivers/gpu/drm/drm_crtc_helper.c
+++ b/drivers/gpu/drm/drm_crtc_helper.c
@@ -805,14 +805,56 @@ void drm_helper_connector_dpms(struct drm_connector *connector, int mode)
 }
 EXPORT_SYMBOL(drm_helper_connector_dpms);
 
+/*
+ * Just need to support RGB formats here for compat with code that doesn't
+ * use pixel formats directly yet.
+ */
+void drm_helper_get_fb_bpp_depth(uint32_t format, unsigned int *depth,
+				 int *bpp)
+{
+	switch (format) {
+	case V4L2_PIX_FMT_RGB332:
+		*depth = 8;
+		*bpp = 8;
+		break;
+	case V4L2_PIX_FMT_RGB555:
+		*depth = 15;
+		*bpp = 16;
+		break;
+	case V4L2_PIX_FMT_RGB565:
+		*depth = 16;
+		*bpp = 16;
+		break;
+	case V4L2_PIX_FMT_RGB24:
+		*depth = 24;
+		*bpp = 24;
+		break;
+	case V4L2_PIX_FMT_INTC_RGB30:
+		*depth = 30;
+		*bpp = 32;
+		break;
+	case V4L2_PIX_FMT_RGB32:
+		*depth = 32;
+		*bpp = 32;
+		break;
+	default:
+		DRM_DEBUG_KMS("unsupported pixel format\n");
+		*depth = 0;
+		*bpp = 0;
+		break;
+	}
+}
+EXPORT_SYMBOL(drm_helper_get_fb_bpp_depth);
+
 int drm_helper_mode_fill_fb_struct(struct drm_framebuffer *fb,
-				   struct drm_mode_fb_cmd *mode_cmd)
+				   struct drm_mode_fb_cmd2 *mode_cmd)
 {
 	fb->width = mode_cmd->width;
 	fb->height = mode_cmd->height;
-	fb->pitch = mode_cmd->pitch;
-	fb->bits_per_pixel = mode_cmd->bpp;
-	fb->depth = mode_cmd->depth;
+	fb->pitch = mode_cmd->pitches[0];
+	drm_helper_get_fb_bpp_depth(mode_cmd->pixel_format, &fb->depth,
+				    &fb->bits_per_pixel);
+	fb->pixel_format = mode_cmd->pixel_format;
 
 	return 0;
 }
diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
index 15da618..f24b9b6 100644
--- a/drivers/gpu/drm/drm_drv.c
+++ b/drivers/gpu/drm/drm_drv.c
@@ -152,6 +152,7 @@ static struct drm_ioctl_desc drm_ioctls[] = {
 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPROPBLOB, drm_mode_getblob_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETFB, drm_mode_getfb, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB, drm_mode_addfb, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB2, drm_mode_addfb2, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_RMFB, drm_mode_rmfb, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_PAGE_FLIP, drm_mode_page_flip_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_DIRTYFB, drm_mode_dirtyfb_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 981b1f1..0727fc8 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -6279,7 +6279,7 @@ static struct drm_display_mode load_detect_mode = {
 
 static struct drm_framebuffer *
 intel_framebuffer_create(struct drm_device *dev,
-			 struct drm_mode_fb_cmd *mode_cmd,
+			 struct drm_mode_fb_cmd2 *mode_cmd,
 			 struct drm_i915_gem_object *obj)
 {
 	struct intel_framebuffer *intel_fb;
@@ -6321,7 +6321,7 @@ intel_framebuffer_create_for_mode(struct drm_device *dev,
 				  int depth, int bpp)
 {
 	struct drm_i915_gem_object *obj;
-	struct drm_mode_fb_cmd mode_cmd;
+	struct drm_mode_fb_cmd2 mode_cmd;
 
 	obj = i915_gem_alloc_object(dev,
 				    intel_framebuffer_size_for_mode(mode, bpp));
@@ -6330,9 +6330,9 @@ intel_framebuffer_create_for_mode(struct drm_device *dev,
 
 	mode_cmd.width = mode->hdisplay;
 	mode_cmd.height = mode->vdisplay;
-	mode_cmd.depth = depth;
-	mode_cmd.bpp = bpp;
-	mode_cmd.pitch = intel_framebuffer_pitch_for_width(mode_cmd.width, bpp);
+	mode_cmd.pitches[0] = intel_framebuffer_pitch_for_width(mode_cmd.width,
+								bpp);
+	mode_cmd.pixel_format = 0;
 
 	return intel_framebuffer_create(dev, &mode_cmd, obj);
 }
@@ -7573,7 +7573,7 @@ static const struct drm_framebuffer_funcs intel_fb_funcs = {
 
 int intel_framebuffer_init(struct drm_device *dev,
 			   struct intel_framebuffer *intel_fb,
-			   struct drm_mode_fb_cmd *mode_cmd,
+			   struct drm_mode_fb_cmd2 *mode_cmd,
 			   struct drm_i915_gem_object *obj)
 {
 	int ret;
@@ -7584,18 +7584,20 @@ int intel_framebuffer_init(struct drm_device *dev,
 	if (mode_cmd->pitch & 63)
 		return -EINVAL;
 
-	switch (mode_cmd->bpp) {
-	case 8:
-	case 16:
-		/* Only pre-ILK can handle 5:5:5 */
-		if (mode_cmd->depth == 15 && !HAS_PCH_SPLIT(dev))
-			return -EINVAL;
+	switch (mode_cmd->pixel_format) {
+	case V4L2_PIX_FMT_RGB332:
+	case V4L2_PIX_FMT_RGB565:
+	case V4L2_PIX_FMT_RGB24:
+	case V4L2_PIX_FMT_INTC_RGB30:
+		/* RGB formats are common across chipsets */
 		break;
-
-	case 24:
-	case 32:
+	case V4L2_PIX_FMT_YUYV:
+	case V4L2_PIX_FMT_UYVY:
+	case V4L2_PIX_FMT_YVYU:
+	case V4L2_PIX_FMT_VYUY:
 		break;
 	default:
+		DRM_ERROR("unsupported pixel format\n");
 		return -EINVAL;
 	}
 
@@ -7613,7 +7615,7 @@ int intel_framebuffer_init(struct drm_device *dev,
 static struct drm_framebuffer *
 intel_user_framebuffer_create(struct drm_device *dev,
 			      struct drm_file *filp,
-			      struct drm_mode_fb_cmd *mode_cmd)
+			      struct drm_mode_fb_cmd2 *mode_cmd)
 {
 	struct drm_i915_gem_object *obj;
 
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index bd9a604..23c5622 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -359,7 +359,7 @@ extern int intel_pin_and_fence_fb_obj(struct drm_device *dev,
 
 extern int intel_framebuffer_init(struct drm_device *dev,
 				  struct intel_framebuffer *ifb,
-				  struct drm_mode_fb_cmd *mode_cmd,
+				  struct drm_mode_fb_cmd2 *mode_cmd,
 				  struct drm_i915_gem_object *obj);
 extern int intel_fbdev_init(struct drm_device *dev);
 extern void intel_fbdev_fini(struct drm_device *dev);
diff --git a/drivers/gpu/drm/i915/intel_fb.c b/drivers/gpu/drm/i915/intel_fb.c
index ec49bae..dc1db4f 100644
--- a/drivers/gpu/drm/i915/intel_fb.c
+++ b/drivers/gpu/drm/i915/intel_fb.c
@@ -65,7 +65,7 @@ static int intelfb_create(struct intel_fbdev *ifbdev,
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct fb_info *info;
 	struct drm_framebuffer *fb;
-	struct drm_mode_fb_cmd mode_cmd;
+	struct drm_mode_fb_cmd2 mode_cmd;
 	struct drm_i915_gem_object *obj;
 	struct device *device = &dev->pdev->dev;
 	int size, ret;
@@ -77,11 +77,12 @@ static int intelfb_create(struct intel_fbdev *ifbdev,
 	mode_cmd.width = sizes->surface_width;
 	mode_cmd.height = sizes->surface_height;
 
-	mode_cmd.bpp = sizes->surface_bpp;
-	mode_cmd.pitch = ALIGN(mode_cmd.width * ((mode_cmd.bpp + 7) / 8), 64);
-	mode_cmd.depth = sizes->surface_depth;
+	mode_cmd.pitches[0] = ALIGN(mode_cmd.width * ((sizes->surface_bpp + 7) /
+						      8), 64);
+	mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp,
+							  sizes->surface_depth);
 
-	size = mode_cmd.pitch * mode_cmd.height;
+	size = mode_cmd.pitches[0] * mode_cmd.height;
 	size = ALIGN(size, PAGE_SIZE);
 	obj = i915_gem_alloc_object(dev, size);
 	if (!obj) {
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c
index ddbabef..7a428a9 100644
--- a/drivers/gpu/drm/nouveau/nouveau_display.c
+++ b/drivers/gpu/drm/nouveau/nouveau_display.c
@@ -64,7 +64,7 @@ static const struct drm_framebuffer_funcs nouveau_framebuffer_funcs = {
 int
 nouveau_framebuffer_init(struct drm_device *dev,
 			 struct nouveau_framebuffer *nv_fb,
-			 struct drm_mode_fb_cmd *mode_cmd,
+			 struct drm_mode_fb_cmd2 *mode_cmd,
 			 struct nouveau_bo *nvbo)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
@@ -124,7 +124,7 @@ nouveau_framebuffer_init(struct drm_device *dev,
 static struct drm_framebuffer *
 nouveau_user_framebuffer_create(struct drm_device *dev,
 				struct drm_file *file_priv,
-				struct drm_mode_fb_cmd *mode_cmd)
+				struct drm_mode_fb_cmd2 *mode_cmd)
 {
 	struct nouveau_framebuffer *nouveau_fb;
 	struct drm_gem_object *gem;
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c
index 6cc17fb..ae803f8 100644
--- a/drivers/gpu/drm/radeon/radeon_display.c
+++ b/drivers/gpu/drm/radeon/radeon_display.c
@@ -1113,7 +1113,7 @@ static const struct drm_framebuffer_funcs radeon_fb_funcs = {
 void
 radeon_framebuffer_init(struct drm_device *dev,
 			struct radeon_framebuffer *rfb,
-			struct drm_mode_fb_cmd *mode_cmd,
+			struct drm_mode_fb_cmd2 *mode_cmd,
 			struct drm_gem_object *obj)
 {
 	rfb->obj = obj;
@@ -1124,7 +1124,7 @@ radeon_framebuffer_init(struct drm_device *dev,
 static struct drm_framebuffer *
 radeon_user_framebuffer_create(struct drm_device *dev,
 			       struct drm_file *file_priv,
-			       struct drm_mode_fb_cmd *mode_cmd)
+			       struct drm_mode_fb_cmd2 *mode_cmd)
 {
 	struct drm_gem_object *obj;
 	struct radeon_framebuffer *radeon_fb;
diff --git a/drivers/gpu/drm/radeon/radeon_fb.c b/drivers/gpu/drm/radeon/radeon_fb.c
index 0b7b486..ea110ad 100644
--- a/drivers/gpu/drm/radeon/radeon_fb.c
+++ b/drivers/gpu/drm/radeon/radeon_fb.c
@@ -103,7 +103,7 @@ static void radeonfb_destroy_pinned_object(struct drm_gem_object *gobj)
 }
 
 static int radeonfb_create_pinned_object(struct radeon_fbdev *rfbdev,
-					 struct drm_mode_fb_cmd *mode_cmd,
+					 struct drm_mode_fb_cmd2 *mode_cmd,
 					 struct drm_gem_object **gobj_p)
 {
 	struct radeon_device *rdev = rfbdev->rdev;
@@ -114,13 +114,17 @@ static int radeonfb_create_pinned_object(struct radeon_fbdev *rfbdev,
 	int ret;
 	int aligned_size, size;
 	int height = mode_cmd->height;
+	u32 bpp, depth;
+
+	drm_helper_get_fb_bpp_depth(mode_cmd->pixel_format, &depth, &bpp);
 
 	/* need to align pitch with crtc limits */
-	mode_cmd->pitch = radeon_align_pitch(rdev, mode_cmd->width, mode_cmd->bpp, fb_tiled) * ((mode_cmd->bpp + 1) / 8);
+	mode_cmd->pitches[0] = radeon_align_pitch(rdev, mode_cmd->width, bpp,
+						  fb_tiled) * ((bpp + 1) / 8);
 
 	if (rdev->family >= CHIP_R600)
 		height = ALIGN(mode_cmd->height, 8);
-	size = mode_cmd->pitch * height;
+	size = mode_cmd->pitches[0] * height;
 	aligned_size = ALIGN(size, PAGE_SIZE);
 	ret = radeon_gem_object_create(rdev, aligned_size, 0,
 				       RADEON_GEM_DOMAIN_VRAM,
@@ -151,7 +155,7 @@ static int radeonfb_create_pinned_object(struct radeon_fbdev *rfbdev,
 	if (tiling_flags) {
 		ret = radeon_bo_set_tiling_flags(rbo,
 						 tiling_flags | RADEON_TILING_SURFACE,
-						 mode_cmd->pitch);
+						 mode_cmd->pitches[0]);
 		if (ret)
 			dev_err(rdev->dev, "FB failed to set tiling flags\n");
 	}
@@ -187,7 +191,7 @@ static int radeonfb_create(struct radeon_fbdev *rfbdev,
 	struct radeon_device *rdev = rfbdev->rdev;
 	struct fb_info *info;
 	struct drm_framebuffer *fb = NULL;
-	struct drm_mode_fb_cmd mode_cmd;
+	struct drm_mode_fb_cmd2 mode_cmd;
 	struct drm_gem_object *gobj = NULL;
 	struct radeon_bo *rbo = NULL;
 	struct device *device = &rdev->pdev->dev;
@@ -201,8 +205,8 @@ static int radeonfb_create(struct radeon_fbdev *rfbdev,
 	if ((sizes->surface_bpp == 24) && ASIC_IS_AVIVO(rdev))
 		sizes->surface_bpp = 32;
 
-	mode_cmd.bpp = sizes->surface_bpp;
-	mode_cmd.depth = sizes->surface_depth;
+	mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp,
+							  sizes->surface_depth);
 
 	ret = radeonfb_create_pinned_object(rfbdev, &mode_cmd, &gobj);
 	rbo = gem_to_radeon_bo(gobj);
diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h
index 68820f5..227f595 100644
--- a/drivers/gpu/drm/radeon/radeon_mode.h
+++ b/drivers/gpu/drm/radeon/radeon_mode.h
@@ -644,7 +644,7 @@ extern void radeon_crtc_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green
 				     u16 *blue, int regno);
 void radeon_framebuffer_init(struct drm_device *dev,
 			     struct radeon_framebuffer *rfb,
-			     struct drm_mode_fb_cmd *mode_cmd,
+			     struct drm_mode_fb_cmd2 *mode_cmd,
 			     struct drm_gem_object *obj);
 
 int radeonfb_remove(struct drm_device *dev, struct drm_framebuffer *fb);
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
index 1a4c84c..2a1b802 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
@@ -839,7 +839,7 @@ out_err1:
 
 static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev,
 						 struct drm_file *file_priv,
-						 struct drm_mode_fb_cmd *mode_cmd)
+						 struct drm_mode_fb_cmd2 *mode_cmd)
 {
 	struct vmw_private *dev_priv = vmw_priv(dev);
 	struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
diff --git a/drivers/staging/gma500/framebuffer.c b/drivers/staging/gma500/framebuffer.c
index ebfde13..85f47d5 100644
--- a/drivers/staging/gma500/framebuffer.c
+++ b/drivers/staging/gma500/framebuffer.c
@@ -487,7 +487,7 @@ out_err1:
  */
 static struct drm_framebuffer *psb_user_framebuffer_create
 			(struct drm_device *dev, struct drm_file *filp,
-			 struct drm_mode_fb_cmd *cmd)
+			 struct drm_mode_fb_cmd2 *cmd)
 {
 	struct gtt_range *r;
 	struct drm_gem_object *obj;
diff --git a/include/drm/drm.h b/include/drm/drm.h
index 2897967..49d94ed 100644
--- a/include/drm/drm.h
+++ b/include/drm/drm.h
@@ -717,6 +717,7 @@ struct drm_get_cap {
 #define DRM_IOCTL_MODE_GETPLANERESOURCES DRM_IOWR(0xB5, struct drm_mode_get_plane_res)
 #define DRM_IOCTL_MODE_GETPLANE	DRM_IOWR(0xB6, struct drm_mode_get_plane)
 #define DRM_IOCTL_MODE_SETPLANE	DRM_IOWR(0xB7, struct drm_mode_set_plane)
+#define DRM_IOCTL_MODE_ADDFB2		DRM_IOWR(0xB8, struct drm_mode_fb_cmd2)
 
 /**
  * Device specific ioctls should only be in their respective headers
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index b4519f8..f65ec08 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -29,6 +29,7 @@
 #include <linux/spinlock.h>
 #include <linux/types.h>
 #include <linux/idr.h>
+#include <linux/videodev2.h> /* for plane formats */
 
 #include <linux/fb.h>
 
@@ -246,6 +247,7 @@ struct drm_framebuffer {
 	unsigned int depth;
 	int bits_per_pixel;
 	int flags;
+	uint32_t pixel_format; /* fourcc format */
 	struct list_head filp_head;
 	/* if you are using the helper */
 	void *helper_private;
@@ -620,7 +622,7 @@ struct drm_mode_set {
  * struct drm_mode_config_funcs - configure CRTCs for a given screen layout
  */
 struct drm_mode_config_funcs {
-	struct drm_framebuffer *(*fb_create)(struct drm_device *dev, struct drm_file *file_priv, struct drm_mode_fb_cmd *mode_cmd);
+	struct drm_framebuffer *(*fb_create)(struct drm_device *dev, struct drm_file *file_priv, struct drm_mode_fb_cmd2 *mode_cmd);
 	void (*output_poll_changed)(struct drm_device *dev);
 };
 
@@ -838,6 +840,9 @@ extern int drm_mode_cursor_ioctl(struct drm_device *dev,
 				void *data, struct drm_file *file_priv);
 extern int drm_mode_addfb(struct drm_device *dev,
 			  void *data, struct drm_file *file_priv);
+extern int drm_mode_addfb2(struct drm_device *dev,
+			   void *data, struct drm_file *file_priv);
+extern uint32_t drm_mode_legacy_fb_format(uint32_t bpp, uint32_t depth);
 extern int drm_mode_rmfb(struct drm_device *dev,
 			 void *data, struct drm_file *file_priv);
 extern int drm_mode_getfb(struct drm_device *dev,
diff --git a/include/drm/drm_crtc_helper.h b/include/drm/drm_crtc_helper.h
index 73b0712..b4abb33 100644
--- a/include/drm/drm_crtc_helper.h
+++ b/include/drm/drm_crtc_helper.h
@@ -116,8 +116,10 @@ extern bool drm_helper_encoder_in_use(struct drm_encoder *encoder);
 
 extern void drm_helper_connector_dpms(struct drm_connector *connector, int mode);
 
+extern void drm_helper_get_fb_bpp_depth(uint32_t format, unsigned int *depth,
+					int *bpp);
 extern int drm_helper_mode_fill_fb_struct(struct drm_framebuffer *fb,
-					  struct drm_mode_fb_cmd *mode_cmd);
+					  struct drm_mode_fb_cmd2 *mode_cmd);
 
 static inline void drm_crtc_helper_add(struct drm_crtc *crtc,
 				       const struct drm_crtc_helper_funcs *funcs)
diff --git a/include/drm/drm_mode.h b/include/drm/drm_mode.h
index 07711b0..69f8ece 100644
--- a/include/drm/drm_mode.h
+++ b/include/drm/drm_mode.h
@@ -27,6 +27,8 @@
 #ifndef _DRM_MODE_H
 #define _DRM_MODE_H
 
+#include <linux/videodev2.h>
+
 #define DRM_DISPLAY_INFO_LEN	32
 #define DRM_CONNECTOR_NAME_LEN	32
 #define DRM_DISPLAY_MODE_LEN	32
@@ -262,6 +264,30 @@ struct drm_mode_fb_cmd {
 	__u32 handle;
 };
 
+struct drm_mode_fb_cmd2 {
+	__u32 fb_id;
+	__u32 width, height;
+	__u32 pixel_format; /* fourcc code from videodev2.h */
+
+	/*
+	 * In case of planar formats, this ioctl allows one
+	 * buffer object with offets and pitches per plane.
+	 * The pitch and offset order is dictated by the fourcc,
+	 * e.g. NV12 (http://fourcc.org/yuv.php#NV12) is described as:
+	 *
+	 *   YUV 4:2:0 image with a plane of 8 bit Y samples
+	 *   followed by an interleaved U/V plane containing
+	 *   8 bit 2x2 subsampled colour difference samples.
+	 *
+	 * So it would consist of Y as offset[0] and UV as
+	 * offeset[1].  Note that offset[0] will generally
+	 * be 0.
+	 */
+	__u32 handle;
+	__u32 pitches[4]; /* pitch for each plane */
+	__u32 offsets[4]; /* offset of each plane */
+};
+
 #define DRM_MODE_FB_DIRTY_ANNOTATE_COPY 0x01
 #define DRM_MODE_FB_DIRTY_ANNOTATE_FILL 0x02
 #define DRM_MODE_FB_DIRTY_FLAGS         0x03
diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
index fca24cc..6da4ab4 100644
--- a/include/linux/videodev2.h
+++ b/include/linux/videodev2.h
@@ -412,6 +412,7 @@ struct v4l2_pix_format {
 #define V4L2_PIX_FMT_KONICA420  v4l2_fourcc('K', 'O', 'N', 'I') /* YUV420 planar in blocks of 256 pixels */
 #define V4L2_PIX_FMT_JPGL	v4l2_fourcc('J', 'P', 'G', 'L') /* JPEG-Lite */
 #define V4L2_PIX_FMT_SE401      v4l2_fourcc('S', '4', '0', '1') /* se401 janggu compressed rgb */
+#define V4L2_PIX_FMT_INTC_RGB30	v4l2_fourcc('R', 'G', 'B', '0') /* RGB x:10:10:10 */
 
 /*
  *	F O R M A T   E N U M E R A T I O N
-- 
1.7.4.1

^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [PATCH 3/5] drm/i915: rename existing overlay support to "legacy"
  2011-11-02 20:03 [PATCH] DRM planes Jesse Barnes
  2011-11-02 20:03 ` [PATCH 1/5] drm: add plane support Jesse Barnes
  2011-11-02 20:03 ` [PATCH 2/5] drm: add an fb creation ioctl that takes a pixel format Jesse Barnes
@ 2011-11-02 20:03 ` Jesse Barnes
  2011-11-03 18:22   ` Jesse Barnes
  2011-11-02 20:03 ` [PATCH 4/5] drm/i915: add SNB and IVB video sprite support Jesse Barnes
                   ` (2 subsequent siblings)
  5 siblings, 1 reply; 32+ messages in thread
From: Jesse Barnes @ 2011-11-02 20:03 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx, rob.clark

The old overlay block has all sorts of quirks and is very different than
ILK+ video sprites.  So rename it to legacy to make that clear and clash
less with core overlay support.

Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
---
 drivers/gpu/drm/i915/i915_debugfs.c  |    2 +-
 drivers/gpu/drm/i915/i915_drv.h      |   12 ++--
 drivers/gpu/drm/i915/i915_irq.c      |    2 +-
 drivers/gpu/drm/i915/intel_display.c |    2 +-
 drivers/gpu/drm/i915/intel_drv.h     |    4 +-
 drivers/gpu/drm/i915/intel_overlay.c |  126 +++++++++++++++++-----------------
 6 files changed, 74 insertions(+), 74 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index 8e95d66..b6d0bbc 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -825,7 +825,7 @@ static int i915_error_state(struct seq_file *m, void *unused)
 	}
 
 	if (error->overlay)
-		intel_overlay_print_error_state(m, error->overlay);
+		intel_legacy_overlay_print_error_state(m, error->overlay);
 
 	if (error->display)
 		intel_display_print_error_state(m, dev, error->display);
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 06a37f4..b96c174 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -118,8 +118,8 @@ struct intel_opregion {
 };
 #define OPREGION_SIZE            (8*1024)
 
-struct intel_overlay;
-struct intel_overlay_error_state;
+struct intel_legacy_overlay;
+struct intel_legacy_overlay_error_state;
 
 struct drm_i915_master_private {
 	drm_local_map_t *sarea;
@@ -191,7 +191,7 @@ struct drm_i915_error_state {
 		u32 cache_level:2;
 	} *active_bo, *pinned_bo;
 	u32 active_bo_count, pinned_bo_count;
-	struct intel_overlay_error_state *overlay;
+	struct intel_legacy_overlay_error_state *overlay;
 	struct intel_display_error_state *display;
 };
 
@@ -343,7 +343,7 @@ typedef struct drm_i915_private {
 	struct intel_opregion opregion;
 
 	/* overlay */
-	struct intel_overlay *overlay;
+	struct intel_legacy_overlay *overlay;
 
 	/* LVDS info */
 	int backlight_level;  /* restore backlight to this value */
@@ -1309,8 +1309,8 @@ extern int intel_trans_dp_port_sel(struct drm_crtc *crtc);
 
 /* overlay */
 #ifdef CONFIG_DEBUG_FS
-extern struct intel_overlay_error_state *intel_overlay_capture_error_state(struct drm_device *dev);
-extern void intel_overlay_print_error_state(struct seq_file *m, struct intel_overlay_error_state *error);
+extern struct intel_legacy_overlay_error_state *intel_legacy_overlay_capture_error_state(struct drm_device *dev);
+extern void intel_legacy_overlay_print_error_state(struct seq_file *m, struct intel_legacy_overlay_error_state *error);
 
 extern struct intel_display_error_state *intel_display_capture_error_state(struct drm_device *dev);
 extern void intel_display_print_error_state(struct seq_file *m,
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 9ee2729..36f2837 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -998,7 +998,7 @@ static void i915_capture_error_state(struct drm_device *dev)
 
 	do_gettimeofday(&error->time);
 
-	error->overlay = intel_overlay_capture_error_state(dev);
+	error->overlay = intel_legacy_overlay_capture_error_state(dev);
 	error->display = intel_display_capture_error_state(dev);
 
 	spin_lock_irqsave(&dev_priv->error_lock, flags);
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 0727fc8..660168a 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3180,7 +3180,7 @@ static void intel_crtc_dpms_overlay(struct intel_crtc *intel_crtc, bool enable)
 
 		mutex_lock(&dev->struct_mutex);
 		dev_priv->mm.interruptible = false;
-		(void) intel_overlay_switch_off(intel_crtc->overlay);
+		(void) intel_legacy_overlay_switch_off(intel_crtc->overlay);
 		dev_priv->mm.interruptible = true;
 		mutex_unlock(&dev->struct_mutex);
 	}
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 23c5622..467fb4a 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -161,7 +161,7 @@ struct intel_crtc {
 	bool busy; /* is scanout buffer being updated frequently? */
 	struct timer_list idle_timer;
 	bool lowfreq_avail;
-	struct intel_overlay *overlay;
+	struct intel_legacy_overlay *overlay;
 	struct intel_unpin_work *unpin_work;
 	int fdi_lanes;
 
@@ -370,7 +370,7 @@ extern void intel_finish_page_flip_plane(struct drm_device *dev, int plane);
 
 extern void intel_setup_overlay(struct drm_device *dev);
 extern void intel_cleanup_overlay(struct drm_device *dev);
-extern int intel_overlay_switch_off(struct intel_overlay *overlay);
+extern int intel_legacy_overlay_switch_off(struct intel_legacy_overlay *overlay);
 extern int intel_overlay_put_image(struct drm_device *dev, void *data,
 				   struct drm_file *file_priv);
 extern int intel_overlay_attrs(struct drm_device *dev, void *data,
diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c
index cdf17d4..6327da4 100644
--- a/drivers/gpu/drm/i915/intel_overlay.c
+++ b/drivers/gpu/drm/i915/intel_overlay.c
@@ -170,7 +170,7 @@ struct overlay_registers {
 	u16 RESERVEDG[0x100 / 2 - N_HORIZ_UV_TAPS * N_PHASES];
 };
 
-struct intel_overlay {
+struct intel_legacy_overlay {
 	struct drm_device *dev;
 	struct intel_crtc *crtc;
 	struct drm_i915_gem_object *vid_bo;
@@ -186,11 +186,11 @@ struct intel_overlay {
 	struct drm_i915_gem_object *reg_bo;
 	/* flip handling */
 	uint32_t last_flip_req;
-	void (*flip_tail)(struct intel_overlay *);
+	void (*flip_tail)(struct intel_legacy_overlay *);
 };
 
 static struct overlay_registers *
-intel_overlay_map_regs(struct intel_overlay *overlay)
+intel_legacy_overlay_map_regs(struct intel_legacy_overlay *overlay)
 {
 	drm_i915_private_t *dev_priv = overlay->dev->dev_private;
 	struct overlay_registers *regs;
@@ -204,16 +204,16 @@ intel_overlay_map_regs(struct intel_overlay *overlay)
 	return regs;
 }
 
-static void intel_overlay_unmap_regs(struct intel_overlay *overlay,
+static void intel_legacy_overlay_unmap_regs(struct intel_legacy_overlay *overlay,
 				     struct overlay_registers *regs)
 {
 	if (!OVERLAY_NEEDS_PHYSICAL(overlay->dev))
 		io_mapping_unmap(regs);
 }
 
-static int intel_overlay_do_wait_request(struct intel_overlay *overlay,
+static int intel_legacy_overlay_do_wait_request(struct intel_legacy_overlay *overlay,
 					 struct drm_i915_gem_request *request,
-					 void (*tail)(struct intel_overlay *))
+					 void (*tail)(struct intel_legacy_overlay *))
 {
 	struct drm_device *dev = overlay->dev;
 	drm_i915_private_t *dev_priv = dev->dev_private;
@@ -284,7 +284,7 @@ i830_deactivate_pipe_a(struct drm_device *dev)
 }
 
 /* overlay needs to be disable in OCMD reg */
-static int intel_overlay_on(struct intel_overlay *overlay)
+static int intel_legacy_overlay_on(struct intel_legacy_overlay *overlay)
 {
 	struct drm_device *dev = overlay->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -319,7 +319,7 @@ static int intel_overlay_on(struct intel_overlay *overlay)
 	OUT_RING(MI_NOOP);
 	ADVANCE_LP_RING();
 
-	ret = intel_overlay_do_wait_request(overlay, request, NULL);
+	ret = intel_legacy_overlay_do_wait_request(overlay, request, NULL);
 out:
 	if (pipe_a_quirk)
 		i830_deactivate_pipe_a(dev);
@@ -328,7 +328,7 @@ out:
 }
 
 /* overlay needs to be enabled in OCMD reg */
-static int intel_overlay_continue(struct intel_overlay *overlay,
+static int intel_legacy_overlay_continue(struct intel_legacy_overlay *overlay,
 				  bool load_polyphase_filter)
 {
 	struct drm_device *dev = overlay->dev;
@@ -371,7 +371,7 @@ static int intel_overlay_continue(struct intel_overlay *overlay,
 	return 0;
 }
 
-static void intel_overlay_release_old_vid_tail(struct intel_overlay *overlay)
+static void intel_legacy_overlay_release_old_vid_tail(struct intel_legacy_overlay *overlay)
 {
 	struct drm_i915_gem_object *obj = overlay->old_vid_bo;
 
@@ -381,7 +381,7 @@ static void intel_overlay_release_old_vid_tail(struct intel_overlay *overlay)
 	overlay->old_vid_bo = NULL;
 }
 
-static void intel_overlay_off_tail(struct intel_overlay *overlay)
+static void intel_legacy_overlay_off_tail(struct intel_legacy_overlay *overlay)
 {
 	struct drm_i915_gem_object *obj = overlay->vid_bo;
 
@@ -398,7 +398,7 @@ static void intel_overlay_off_tail(struct intel_overlay *overlay)
 }
 
 /* overlay needs to be disabled in OCMD reg */
-static int intel_overlay_off(struct intel_overlay *overlay)
+static int intel_legacy_overlay_off(struct intel_legacy_overlay *overlay)
 {
 	struct drm_device *dev = overlay->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -433,13 +433,13 @@ static int intel_overlay_off(struct intel_overlay *overlay)
 	OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
 	ADVANCE_LP_RING();
 
-	return intel_overlay_do_wait_request(overlay, request,
-					     intel_overlay_off_tail);
+	return intel_legacy_overlay_do_wait_request(overlay, request,
+					     intel_legacy_overlay_off_tail);
 }
 
 /* recover from an interruption due to a signal
  * We have to be careful not to repeat work forever an make forward progess. */
-static int intel_overlay_recover_from_interrupt(struct intel_overlay *overlay)
+static int intel_legacy_overlay_recover_from_interrupt(struct intel_legacy_overlay *overlay)
 {
 	struct drm_device *dev = overlay->dev;
 	drm_i915_private_t *dev_priv = dev->dev_private;
@@ -461,9 +461,9 @@ static int intel_overlay_recover_from_interrupt(struct intel_overlay *overlay)
 
 /* Wait for pending overlay flip and release old frame.
  * Needs to be called before the overlay register are changed
- * via intel_overlay_(un)map_regs
+ * via intel_legacy_overlay_(un)map_regs
  */
-static int intel_overlay_release_old_vid(struct intel_overlay *overlay)
+static int intel_legacy_overlay_release_old_vid(struct intel_legacy_overlay *overlay)
 {
 	struct drm_device *dev = overlay->dev;
 	drm_i915_private_t *dev_priv = dev->dev_private;
@@ -493,13 +493,13 @@ static int intel_overlay_release_old_vid(struct intel_overlay *overlay)
 		OUT_RING(MI_NOOP);
 		ADVANCE_LP_RING();
 
-		ret = intel_overlay_do_wait_request(overlay, request,
-						    intel_overlay_release_old_vid_tail);
+		ret = intel_legacy_overlay_do_wait_request(overlay, request,
+						    intel_legacy_overlay_release_old_vid_tail);
 		if (ret)
 			return ret;
 	}
 
-	intel_overlay_release_old_vid_tail(overlay);
+	intel_legacy_overlay_release_old_vid_tail(overlay);
 	return 0;
 }
 
@@ -625,7 +625,7 @@ static void update_polyphase_filter(struct overlay_registers *regs)
 	memcpy(regs->UV_HCOEFS, uv_static_hcoeffs, sizeof(uv_static_hcoeffs));
 }
 
-static bool update_scaling_factors(struct intel_overlay *overlay,
+static bool update_scaling_factors(struct intel_legacy_overlay *overlay,
 				   struct overlay_registers *regs,
 				   struct put_image_params *params)
 {
@@ -682,7 +682,7 @@ static bool update_scaling_factors(struct intel_overlay *overlay,
 	return scale_changed;
 }
 
-static void update_colorkey(struct intel_overlay *overlay,
+static void update_colorkey(struct intel_legacy_overlay *overlay,
 			    struct overlay_registers *regs)
 {
 	u32 key = overlay->color_key;
@@ -756,7 +756,7 @@ static u32 overlay_cmd_reg(struct put_image_params *params)
 	return cmd;
 }
 
-static int intel_overlay_do_put_image(struct intel_overlay *overlay,
+static int intel_legacy_overlay_do_put_image(struct intel_legacy_overlay *overlay,
 				      struct drm_i915_gem_object *new_bo,
 				      struct put_image_params *params)
 {
@@ -769,7 +769,7 @@ static int intel_overlay_do_put_image(struct intel_overlay *overlay,
 	BUG_ON(!mutex_is_locked(&dev->mode_config.mutex));
 	BUG_ON(!overlay);
 
-	ret = intel_overlay_release_old_vid(overlay);
+	ret = intel_legacy_overlay_release_old_vid(overlay);
 	if (ret != 0)
 		return ret;
 
@@ -782,7 +782,7 @@ static int intel_overlay_do_put_image(struct intel_overlay *overlay,
 		goto out_unpin;
 
 	if (!overlay->active) {
-		regs = intel_overlay_map_regs(overlay);
+		regs = intel_legacy_overlay_map_regs(overlay);
 		if (!regs) {
 			ret = -ENOMEM;
 			goto out_unpin;
@@ -792,14 +792,14 @@ static int intel_overlay_do_put_image(struct intel_overlay *overlay,
 			regs->OCONFIG |= OCONF_CSC_MODE_BT709;
 		regs->OCONFIG |= overlay->crtc->pipe == 0 ?
 			OCONF_PIPE_A : OCONF_PIPE_B;
-		intel_overlay_unmap_regs(overlay, regs);
+		intel_legacy_overlay_unmap_regs(overlay, regs);
 
-		ret = intel_overlay_on(overlay);
+		ret = intel_legacy_overlay_on(overlay);
 		if (ret != 0)
 			goto out_unpin;
 	}
 
-	regs = intel_overlay_map_regs(overlay);
+	regs = intel_legacy_overlay_map_regs(overlay);
 	if (!regs) {
 		ret = -ENOMEM;
 		goto out_unpin;
@@ -842,9 +842,9 @@ static int intel_overlay_do_put_image(struct intel_overlay *overlay,
 
 	regs->OCMD = overlay_cmd_reg(params);
 
-	intel_overlay_unmap_regs(overlay, regs);
+	intel_legacy_overlay_unmap_regs(overlay, regs);
 
-	ret = intel_overlay_continue(overlay, scale_changed);
+	ret = intel_legacy_overlay_continue(overlay, scale_changed);
 	if (ret)
 		goto out_unpin;
 
@@ -858,7 +858,7 @@ out_unpin:
 	return ret;
 }
 
-int intel_overlay_switch_off(struct intel_overlay *overlay)
+int intel_legacy_overlay_switch_off(struct intel_legacy_overlay *overlay)
 {
 	struct overlay_registers *regs;
 	struct drm_device *dev = overlay->dev;
@@ -867,30 +867,30 @@ int intel_overlay_switch_off(struct intel_overlay *overlay)
 	BUG_ON(!mutex_is_locked(&dev->struct_mutex));
 	BUG_ON(!mutex_is_locked(&dev->mode_config.mutex));
 
-	ret = intel_overlay_recover_from_interrupt(overlay);
+	ret = intel_legacy_overlay_recover_from_interrupt(overlay);
 	if (ret != 0)
 		return ret;
 
 	if (!overlay->active)
 		return 0;
 
-	ret = intel_overlay_release_old_vid(overlay);
+	ret = intel_legacy_overlay_release_old_vid(overlay);
 	if (ret != 0)
 		return ret;
 
-	regs = intel_overlay_map_regs(overlay);
+	regs = intel_legacy_overlay_map_regs(overlay);
 	regs->OCMD = 0;
-	intel_overlay_unmap_regs(overlay, regs);
+	intel_legacy_overlay_unmap_regs(overlay, regs);
 
-	ret = intel_overlay_off(overlay);
+	ret = intel_legacy_overlay_off(overlay);
 	if (ret != 0)
 		return ret;
 
-	intel_overlay_off_tail(overlay);
+	intel_legacy_overlay_off_tail(overlay);
 	return 0;
 }
 
-static int check_overlay_possible_on_crtc(struct intel_overlay *overlay,
+static int check_overlay_possible_on_crtc(struct intel_legacy_overlay *overlay,
 					  struct intel_crtc *crtc)
 {
 	drm_i915_private_t *dev_priv = overlay->dev->dev_private;
@@ -906,7 +906,7 @@ static int check_overlay_possible_on_crtc(struct intel_overlay *overlay,
 	return 0;
 }
 
-static void update_pfit_vscale_ratio(struct intel_overlay *overlay)
+static void update_pfit_vscale_ratio(struct intel_legacy_overlay *overlay)
 {
 	struct drm_device *dev = overlay->dev;
 	drm_i915_private_t *dev_priv = dev->dev_private;
@@ -930,7 +930,7 @@ static void update_pfit_vscale_ratio(struct intel_overlay *overlay)
 	overlay->pfit_vscale_ratio = ratio;
 }
 
-static int check_overlay_dst(struct intel_overlay *overlay,
+static int check_overlay_dst(struct intel_legacy_overlay *overlay,
 			     struct drm_intel_overlay_put_image *rec)
 {
 	struct drm_display_mode *mode = &overlay->crtc->base.mode;
@@ -1102,7 +1102,7 @@ int intel_overlay_put_image(struct drm_device *dev, void *data,
 {
 	struct drm_intel_overlay_put_image *put_image_rec = data;
 	drm_i915_private_t *dev_priv = dev->dev_private;
-	struct intel_overlay *overlay;
+	struct intel_legacy_overlay *overlay;
 	struct drm_mode_object *drmmode_obj;
 	struct intel_crtc *crtc;
 	struct drm_i915_gem_object *new_bo;
@@ -1124,7 +1124,7 @@ int intel_overlay_put_image(struct drm_device *dev, void *data,
 		mutex_lock(&dev->mode_config.mutex);
 		mutex_lock(&dev->struct_mutex);
 
-		ret = intel_overlay_switch_off(overlay);
+		ret = intel_legacy_overlay_switch_off(overlay);
 
 		mutex_unlock(&dev->struct_mutex);
 		mutex_unlock(&dev->mode_config.mutex);
@@ -1160,13 +1160,13 @@ int intel_overlay_put_image(struct drm_device *dev, void *data,
 		goto out_unlock;
 	}
 
-	ret = intel_overlay_recover_from_interrupt(overlay);
+	ret = intel_legacy_overlay_recover_from_interrupt(overlay);
 	if (ret != 0)
 		goto out_unlock;
 
 	if (overlay->crtc != crtc) {
 		struct drm_display_mode *mode = &crtc->base.mode;
-		ret = intel_overlay_switch_off(overlay);
+		ret = intel_legacy_overlay_switch_off(overlay);
 		if (ret != 0)
 			goto out_unlock;
 
@@ -1228,7 +1228,7 @@ int intel_overlay_put_image(struct drm_device *dev, void *data,
 	if (ret != 0)
 		goto out_unlock;
 
-	ret = intel_overlay_do_put_image(overlay, new_bo, params);
+	ret = intel_legacy_overlay_do_put_image(overlay, new_bo, params);
 	if (ret != 0)
 		goto out_unlock;
 
@@ -1249,7 +1249,7 @@ out_free:
 	return ret;
 }
 
-static void update_reg_attrs(struct intel_overlay *overlay,
+static void update_reg_attrs(struct intel_legacy_overlay *overlay,
 			     struct overlay_registers *regs)
 {
 	regs->OCLRC0 = (overlay->contrast << 18) | (overlay->brightness & 0xff);
@@ -1305,7 +1305,7 @@ int intel_overlay_attrs(struct drm_device *dev, void *data,
 {
 	struct drm_intel_overlay_attrs *attrs = data;
 	drm_i915_private_t *dev_priv = dev->dev_private;
-	struct intel_overlay *overlay;
+	struct intel_legacy_overlay *overlay;
 	struct overlay_registers *regs;
 	int ret;
 
@@ -1351,7 +1351,7 @@ int intel_overlay_attrs(struct drm_device *dev, void *data,
 		overlay->contrast   = attrs->contrast;
 		overlay->saturation = attrs->saturation;
 
-		regs = intel_overlay_map_regs(overlay);
+		regs = intel_legacy_overlay_map_regs(overlay);
 		if (!regs) {
 			ret = -ENOMEM;
 			goto out_unlock;
@@ -1359,7 +1359,7 @@ int intel_overlay_attrs(struct drm_device *dev, void *data,
 
 		update_reg_attrs(overlay, regs);
 
-		intel_overlay_unmap_regs(overlay, regs);
+		intel_legacy_overlay_unmap_regs(overlay, regs);
 
 		if (attrs->flags & I915_OVERLAY_UPDATE_GAMMA) {
 			if (IS_GEN2(dev))
@@ -1394,7 +1394,7 @@ out_unlock:
 void intel_setup_overlay(struct drm_device *dev)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
-	struct intel_overlay *overlay;
+	struct intel_legacy_overlay *overlay;
 	struct drm_i915_gem_object *reg_bo;
 	struct overlay_registers *regs;
 	int ret;
@@ -1402,7 +1402,7 @@ void intel_setup_overlay(struct drm_device *dev)
 	if (!HAS_OVERLAY(dev))
 		return;
 
-	overlay = kzalloc(sizeof(struct intel_overlay), GFP_KERNEL);
+	overlay = kzalloc(sizeof(struct intel_legacy_overlay), GFP_KERNEL);
 	if (!overlay)
 		return;
 
@@ -1447,7 +1447,7 @@ void intel_setup_overlay(struct drm_device *dev)
 	overlay->contrast = 75;
 	overlay->saturation = 146;
 
-	regs = intel_overlay_map_regs(overlay);
+	regs = intel_legacy_overlay_map_regs(overlay);
 	if (!regs)
 		goto out_unpin_bo;
 
@@ -1455,7 +1455,7 @@ void intel_setup_overlay(struct drm_device *dev)
 	update_polyphase_filter(regs);
 	update_reg_attrs(overlay, regs);
 
-	intel_overlay_unmap_regs(overlay, regs);
+	intel_legacy_overlay_unmap_regs(overlay, regs);
 
 	dev_priv->overlay = overlay;
 	mutex_unlock(&dev->struct_mutex);
@@ -1492,7 +1492,7 @@ void intel_cleanup_overlay(struct drm_device *dev)
 #ifdef CONFIG_DEBUG_FS
 #include <linux/seq_file.h>
 
-struct intel_overlay_error_state {
+struct intel_legacy_overlay_error_state {
 	struct overlay_registers regs;
 	unsigned long base;
 	u32 dovsta;
@@ -1500,7 +1500,7 @@ struct intel_overlay_error_state {
 };
 
 static struct overlay_registers *
-intel_overlay_map_regs_atomic(struct intel_overlay *overlay)
+intel_legacy_overlay_map_regs_atomic(struct intel_legacy_overlay *overlay)
 {
 	drm_i915_private_t *dev_priv = overlay->dev->dev_private;
 	struct overlay_registers *regs;
@@ -1514,7 +1514,7 @@ intel_overlay_map_regs_atomic(struct intel_overlay *overlay)
 	return regs;
 }
 
-static void intel_overlay_unmap_regs_atomic(struct intel_overlay *overlay,
+static void intel_legacy_overlay_unmap_regs_atomic(struct intel_legacy_overlay *overlay,
 					    struct overlay_registers *regs)
 {
 	if (!OVERLAY_NEEDS_PHYSICAL(overlay->dev))
@@ -1522,12 +1522,12 @@ static void intel_overlay_unmap_regs_atomic(struct intel_overlay *overlay,
 }
 
 
-struct intel_overlay_error_state *
-intel_overlay_capture_error_state(struct drm_device *dev)
+struct intel_legacy_overlay_error_state *
+intel_legacy_overlay_capture_error_state(struct drm_device *dev)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
-	struct intel_overlay *overlay = dev_priv->overlay;
-	struct intel_overlay_error_state *error;
+	struct intel_legacy_overlay *overlay = dev_priv->overlay;
+	struct intel_legacy_overlay_error_state *error;
 	struct overlay_registers __iomem *regs;
 
 	if (!overlay || !overlay->active)
@@ -1544,12 +1544,12 @@ intel_overlay_capture_error_state(struct drm_device *dev)
 	else
 		error->base = (long) overlay->reg_bo->gtt_offset;
 
-	regs = intel_overlay_map_regs_atomic(overlay);
+	regs = intel_legacy_overlay_map_regs_atomic(overlay);
 	if (!regs)
 		goto err;
 
 	memcpy_fromio(&error->regs, regs, sizeof(struct overlay_registers));
-	intel_overlay_unmap_regs_atomic(overlay, regs);
+	intel_legacy_overlay_unmap_regs_atomic(overlay, regs);
 
 	return error;
 
@@ -1559,7 +1559,7 @@ err:
 }
 
 void
-intel_overlay_print_error_state(struct seq_file *m, struct intel_overlay_error_state *error)
+intel_legacy_overlay_print_error_state(struct seq_file *m, struct intel_legacy_overlay_error_state *error)
 {
 	seq_printf(m, "Overlay, status: 0x%08x, interrupt: 0x%08x\n",
 		   error->dovsta, error->isr);
-- 
1.7.4.1

^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [PATCH 4/5] drm/i915: add SNB and IVB video sprite support
  2011-11-02 20:03 [PATCH] DRM planes Jesse Barnes
                   ` (2 preceding siblings ...)
  2011-11-02 20:03 ` [PATCH 3/5] drm/i915: rename existing overlay support to "legacy" Jesse Barnes
@ 2011-11-02 20:03 ` Jesse Barnes
  2011-11-03 18:22   ` Jesse Barnes
  2011-11-04  2:29   ` [Intel-gfx] " Lan, Hai
  2011-11-02 20:03 ` [PATCH 5/5] drm/i915: add destination color key support Jesse Barnes
  2011-11-03 14:11 ` [PATCH] DRM planes Daniel Vetter
  5 siblings, 2 replies; 32+ messages in thread
From: Jesse Barnes @ 2011-11-02 20:03 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx, rob.clark

The video sprites support various video surface formats natively and can
handle scaling as well.  So add support for them using the new DRM core
overlay support functions.

Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
---
 drivers/gpu/drm/i915/Makefile         |    1 +
 drivers/gpu/drm/i915/i915_reg.h       |  123 +++++++++
 drivers/gpu/drm/i915/intel_display.c  |   29 ++-
 drivers/gpu/drm/i915/intel_drv.h      |   23 ++
 drivers/gpu/drm/i915/intel_fb.c       |    6 +
 drivers/gpu/drm/i915/intel_overlay2.c |  438 +++++++++++++++++++++++++++++++++
 6 files changed, 610 insertions(+), 10 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/intel_overlay2.c

diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index 0ae6a7c..6193471 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -28,6 +28,7 @@ i915-y := i915_drv.o i915_dma.o i915_irq.o i915_mem.o \
 	  intel_dvo.o \
 	  intel_ringbuffer.o \
 	  intel_overlay.o \
+	  intel_overlay2.o \
 	  intel_opregion.o \
 	  dvo_ch7xxx.o \
 	  dvo_ch7017.o \
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 5a09416..b2270fa 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -2450,6 +2450,8 @@
 #define WM3_LP_ILK		0x45110
 #define  WM3_LP_EN		(1<<31)
 #define WM1S_LP_ILK		0x45120
+#define WM2S_LP_IVB		0x45124
+#define WM3S_LP_IVB		0x45128
 #define  WM1S_LP_EN		(1<<31)
 
 /* Memory latency timer register */
@@ -2666,6 +2668,127 @@
 #define _DSPBSURF		0x7119C
 #define _DSPBTILEOFF		0x711A4
 
+/* Sprite A control */
+#define _DVSACNTR		0x72180
+#define   DVS_ENABLE		(1<<31)
+#define   DVS_GAMMA_ENABLE	(1<<30)
+#define   DVS_PIXFORMAT_MASK	(3<<25)
+#define   DVS_FORMAT_YUV422	(0<<25)
+#define   DVS_FORMAT_RGBX101010	(1<<25)
+#define   DVS_FORMAT_RGBX888	(2<<25)
+#define   DVS_FORMAT_RGBX161616	(3<<25)
+#define   DVS_SOURCE_KEY	(1<<22)
+#define   DVS_RGB_ORDER_RGBX	(1<<20)
+#define   DVS_YUV_BYTE_ORDER_MASK (3<<16)
+#define   DVS_YUV_ORDER_YUYV	(0<<16)
+#define   DVS_YUV_ORDER_UYVY	(1<<16)
+#define   DVS_YUV_ORDER_YVYU	(2<<16)
+#define   DVS_YUV_ORDER_VYUY	(3<<16)
+#define   DVS_DEST_KEY		(1<<2)
+#define   DVS_TRICKLE_FEED_DISABLE (1<<14)
+#define   DVS_TILED		(1<<10)
+#define _DVSASTRIDE		0x72188
+#define _DVSAPOS		0x7218c
+#define _DVSASIZE		0x72190
+#define _DVSAKEYVAL		0x72194
+#define _DVSAKEYMSK		0x72198
+#define _DVSASURF		0x7219c
+#define _DVSAKEYMAXVAL		0x721a0
+#define _DVSATILEOFF		0x721a4
+#define _DVSASURFLIVE		0x721ac
+#define _DVSASCALE		0x72204
+#define   DVS_SCALE_ENABLE	(1<<31)
+#define   DVS_FILTER_MASK	(3<<29)
+#define   DVS_FILTER_MEDIUM	(0<<29)
+#define   DVS_FILTER_ENHANCING	(1<<29)
+#define   DVS_FILTER_SOFTENING	(2<<29)
+#define _DVSAGAMC		0x72300
+
+#define _DVSBCNTR		0x73180
+#define _DVSBSTRIDE		0x73188
+#define _DVSBPOS		0x7318c
+#define _DVSBSIZE		0x73190
+#define _DVSBKEYVAL		0x73194
+#define _DVSBKEYMSK		0x73198
+#define _DVSBSURF		0x7319c
+#define _DVSBKEYMAXVAL		0x731a0
+#define _DVSBTILEOFF		0x731a4
+#define _DVSBSURFLIVE		0x731ac
+#define _DVSBSCALE		0x73204
+#define _DVSBGAMC		0x73300
+
+#define DVSCNTR(pipe) _PIPE(pipe, _DVSACNTR, _DVSBCNTR)
+#define DVSSTRIDE(pipe) _PIPE(pipe, _DVSASTRIDE, _DVSBSTRIDE)
+#define DVSPOS(pipe) _PIPE(pipe, _DVSAPOS, _DVSBPOS)
+#define DVSSURF(pipe) _PIPE(pipe, _DVSASURF, _DVSBSURF)
+#define DVSSIZE(pipe) _PIPE(pipe, _DVSASIZE, _DVSBSIZE)
+#define DVSSCALE(pipe) _PIPE(pipe, _DVSASCALE, _DVSBSCALE)
+#define DVSTILEOFF(pipe) _PIPE(pipe, _DVSATILEOFF, _DVSBTILEOFF)
+
+#define _SPRA_CTL		0x70280
+#define   SPRITE_ENABLE			(1<<31)
+#define   SPRITE_GAMMA_ENABLE		(1<<30)
+#define   SPRITE_PIXFORMAT_MASK		(7<<25)
+#define   SPRITE_FORMAT_YUV422		(0<<25)
+#define   SPRITE_FORMAT_RGBX101010	(1<<25)
+#define   SPRITE_FORMAT_RGBX888		(2<<25)
+#define   SPRITE_FORMAT_RGBX161616	(3<<25)
+#define   SPRITE_FORMAT_YUV444		(4<<25)
+#define   SPRITE_FORMAT_XBGR101010	(5<<25)
+#define   SPRITE_CSC_ENABLE		(1<<24)
+#define   SPRITE_SOURCE_KEY		(1<<22)
+#define   SPRITE_RGB_ORDER_RGBX		(1<<20) /* only for 888 and 161616 */
+#define   SPRITE_YUV_TO_RGB_CSC_DISABLE	(1<<19)
+#define   SPRITE_YUV_CSC_FORMAT_BT709	(1<<18) /* 0 is BT601 */
+#define   SPRITE_YUV_BYTE_ORDER_MASK	(3<<16)
+#define   SPRITE_YUV_ORDER_YUYV		(0<<16)
+#define   SPRITE_YUV_ORDER_UYVY		(1<<16)
+#define   SPRITE_YUV_ORDER_YVYU		(2<<16)
+#define   SPRITE_YUV_ORDER_VYUY		(3<<16)
+#define   SPRITE_TRICKLE_FEED_DISABLE	(1<<14)
+#define   SPRITE_INT_GAMMA_ENABLE	(1<<13)
+#define   SPRITE_TILED			(1<<10)
+#define   SPRITE_DEST_KEY		(1<<2)
+#define _SPRA_STRIDE		0x70288
+#define _SPRA_POS		0x7028c
+#define _SPRA_SIZE		0x70290
+#define _SPRA_KEYVAL		0x70294
+#define _SPRA_KEYMSK		0x70298
+#define _SPRA_SURF		0x7029c
+#define _SPRA_KEYMAX		0x702a0
+#define _SPRA_TILEOFF		0x702a4
+#define _SPRA_SCALE		0x70304
+#define   SPRITE_SCALE_ENABLE	(1<<31)
+#define   SPRITE_FILTER_MASK	(3<<29)
+#define   SPRITE_FILTER_MEDIUM	(0<<29)
+#define   SPRITE_FILTER_ENHANCING	(1<<29)
+#define   SPRITE_FILTER_SOFTENING	(2<<29)
+#define _SPRA_GAMC		0x70400
+
+#define _SPRB_CTL		0x71280
+#define _SPRB_STRIDE		0x71288
+#define _SPRB_POS		0x7128c
+#define _SPRB_SIZE		0x71290
+#define _SPRB_KEYVAL		0x71294
+#define _SPRB_KEYMSK		0x71298
+#define _SPRB_SURF		0x7129c
+#define _SPRB_KEYMAX		0x712a0
+#define _SPRB_TILEOFF		0x712a4
+#define _SPRB_SCALE		0x71304
+#define _SPRB_GAMC		0x71400
+
+#define SPRCTL(pipe) _PIPE(pipe, _SPRA_CTL, _SPRB_CTL)
+#define SPRSTRIDE(pipe) _PIPE(pipe, _SPRA_STRIDE, _SPRB_STRIDE)
+#define SPRPOS(pipe) _PIPE(pipe, _SPRA_POS, _SPRB_POS)
+#define SPRSIZE(pipe) _PIPE(pipe, _SPRA_SIZE, _SPRB_SIZE)
+#define SPRKEYVAL(pipe) _PIPE(pipe, _SPRA_KEYVAL, _SPRB_KEYVAL)
+#define SPRKEYMSK(pipe) _PIPE(pipe, _SPRA_KEYMSK, _SPRB_KEYMSK)
+#define SPRSURF(pipe) _PIPE(pipe, _SPRA_SURF, _SPRB_SURF)
+#define SPRKEYMAX(pipe) _PIPE(pipe, _SPRA_KEYMAX, _SPRB_KEYMAX)
+#define SPRTILEOFF(pipe) _PIPE(pipe, _SPRA_TILEOFF, _SPRB_TILEOFF)
+#define SPRSCALE(pipe) _PIPE(pipe, _SPRA_SCALE, _SPRB_SCALE)
+#define SPRGAMC(pipe) _PIPE(pipe, _SPRA_GAMC, _SPRB_GAMC)
+
 /* VBIOS regs */
 #define VGACNTRL		0x71400
 # define VGA_DISP_DISABLE			(1 << 31)
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 660168a..e0ce53e 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -915,8 +915,8 @@ static void assert_panel_unlocked(struct drm_i915_private *dev_priv,
 	     pipe_name(pipe));
 }
 
-static void assert_pipe(struct drm_i915_private *dev_priv,
-			enum pipe pipe, bool state)
+void assert_pipe(struct drm_i915_private *dev_priv,
+		 enum pipe pipe, bool state)
 {
 	int reg;
 	u32 val;
@@ -929,8 +929,6 @@ static void assert_pipe(struct drm_i915_private *dev_priv,
 	     "pipe %c assertion failure (expected %s, current %s)\n",
 	     pipe_name(pipe), state_string(state), state_string(cur_state));
 }
-#define assert_pipe_enabled(d, p) assert_pipe(d, p, true)
-#define assert_pipe_disabled(d, p) assert_pipe(d, p, false)
 
 static void assert_plane_enabled(struct drm_i915_private *dev_priv,
 				 enum plane plane)
@@ -4439,7 +4437,8 @@ static void ironlake_update_wm(struct drm_device *dev)
 			    ILK_LP0_CURSOR_LATENCY,
 			    &plane_wm, &cursor_wm)) {
 		I915_WRITE(WM0_PIPEA_ILK,
-			   (plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm);
+			   (plane_wm << WM0_PIPE_PLANE_SHIFT) |
+			   (plane_wm << WM0_PIPE_SPRITE_SHIFT) | cursor_wm);
 		DRM_DEBUG_KMS("FIFO watermarks For pipe A -"
 			      " plane %d, " "cursor: %d\n",
 			      plane_wm, cursor_wm);
@@ -4453,7 +4452,8 @@ static void ironlake_update_wm(struct drm_device *dev)
 			    ILK_LP0_CURSOR_LATENCY,
 			    &plane_wm, &cursor_wm)) {
 		I915_WRITE(WM0_PIPEB_ILK,
-			   (plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm);
+			   (plane_wm << WM0_PIPE_PLANE_SHIFT) |
+			   (plane_wm << WM0_PIPE_SPRITE_SHIFT) | cursor_wm);
 		DRM_DEBUG_KMS("FIFO watermarks For pipe B -"
 			      " plane %d, cursor: %d\n",
 			      plane_wm, cursor_wm);
@@ -4521,7 +4521,8 @@ static void sandybridge_update_wm(struct drm_device *dev)
 			    &sandybridge_cursor_wm_info, latency,
 			    &plane_wm, &cursor_wm)) {
 		I915_WRITE(WM0_PIPEA_ILK,
-			   (plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm);
+			   (plane_wm << WM0_PIPE_PLANE_SHIFT) |
+			   (plane_wm << WM0_PIPE_SPRITE_SHIFT) | cursor_wm);
 		DRM_DEBUG_KMS("FIFO watermarks For pipe A -"
 			      " plane %d, " "cursor: %d\n",
 			      plane_wm, cursor_wm);
@@ -4533,7 +4534,8 @@ static void sandybridge_update_wm(struct drm_device *dev)
 			    &sandybridge_cursor_wm_info, latency,
 			    &plane_wm, &cursor_wm)) {
 		I915_WRITE(WM0_PIPEB_ILK,
-			   (plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm);
+			   (plane_wm << WM0_PIPE_PLANE_SHIFT) |
+			   (plane_wm << WM0_PIPE_SPRITE_SHIFT) | cursor_wm);
 		DRM_DEBUG_KMS("FIFO watermarks For pipe B -"
 			      " plane %d, cursor: %d\n",
 			      plane_wm, cursor_wm);
@@ -4547,7 +4549,8 @@ static void sandybridge_update_wm(struct drm_device *dev)
 			    &sandybridge_cursor_wm_info, latency,
 			    &plane_wm, &cursor_wm)) {
 		I915_WRITE(WM0_PIPEC_IVB,
-			   (plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm);
+			   (plane_wm << WM0_PIPE_PLANE_SHIFT) |
+			   (plane_wm << WM0_PIPE_SPRITE_SHIFT) | cursor_wm);
 		DRM_DEBUG_KMS("FIFO watermarks For pipe C -"
 			      " plane %d, cursor: %d\n",
 			      plane_wm, cursor_wm);
@@ -8693,7 +8696,7 @@ static void i915_disable_vga(struct drm_device *dev)
 void intel_modeset_init(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	int i;
+	int i, ret;
 
 	drm_mode_config_init(dev);
 
@@ -8723,6 +8726,12 @@ void intel_modeset_init(struct drm_device *dev)
 
 	for (i = 0; i < dev_priv->num_pipe; i++) {
 		intel_crtc_init(dev, i);
+		if (HAS_PCH_SPLIT(dev)) {
+			ret = intel_plane_init(dev, i);
+			if (ret)
+				DRM_ERROR("plane %d init failed: %d\n",
+					  i, ret);
+		}
 	}
 
 	/* Just disable it once at startup */
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 467fb4a..39b3ae7 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -176,10 +176,27 @@ struct intel_crtc {
 	bool use_pll_a;
 };
 
+struct intel_plane {
+	struct drm_plane base;
+	enum pipe pipe;
+	struct drm_i915_gem_object *obj;
+	bool primary_disabled;
+	int max_downscale;
+	u32 lut_r[1024], lut_g[1024], lut_b[1024];
+	void (*update_plane)(struct drm_plane *plane,
+			     struct drm_framebuffer *fb, unsigned long start,
+			     int crtc_x, int crtc_y,
+			     unsigned int crtc_w, unsigned int crtc_h,
+			     uint32_t x, uint32_t y,
+			     uint32_t src_w, uint32_t src_h);
+	void (*disable_plane)(struct drm_plane *plane);
+};
+
 #define to_intel_crtc(x) container_of(x, struct intel_crtc, base)
 #define to_intel_connector(x) container_of(x, struct intel_connector, base)
 #define to_intel_encoder(x) container_of(x, struct intel_encoder, base)
 #define to_intel_framebuffer(x) container_of(x, struct intel_framebuffer, base)
+#define to_intel_plane(x) container_of(x, struct intel_plane, base)
 
 #define DIP_HEADER_SIZE	5
 
@@ -289,6 +306,7 @@ intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode,
 extern bool intel_dpd_is_edp(struct drm_device *dev);
 extern void intel_edp_link_config(struct intel_encoder *, int *, int *);
 extern bool intel_encoder_is_pch_edp(struct drm_encoder *encoder);
+extern int intel_plane_init(struct drm_device *dev, enum pipe pipe);
 
 /* intel_panel.c */
 extern void intel_fixed_panel_mode(struct drm_display_mode *fixed_mode,
@@ -379,6 +397,11 @@ extern int intel_overlay_attrs(struct drm_device *dev, void *data,
 extern void intel_fb_output_poll_changed(struct drm_device *dev);
 extern void intel_fb_restore_mode(struct drm_device *dev);
 
+extern void assert_pipe(struct drm_i915_private *dev_priv, enum pipe pipe,
+			bool state);
+#define assert_pipe_enabled(d, p) assert_pipe(d, p, true)
+#define assert_pipe_disabled(d, p) assert_pipe(d, p, false)
+
 extern void intel_init_clock_gating(struct drm_device *dev);
 extern void intel_write_eld(struct drm_encoder *encoder,
 			    struct drm_display_mode *mode);
diff --git a/drivers/gpu/drm/i915/intel_fb.c b/drivers/gpu/drm/i915/intel_fb.c
index dc1db4f..068b086 100644
--- a/drivers/gpu/drm/i915/intel_fb.c
+++ b/drivers/gpu/drm/i915/intel_fb.c
@@ -270,8 +270,14 @@ void intel_fb_restore_mode(struct drm_device *dev)
 {
 	int ret;
 	drm_i915_private_t *dev_priv = dev->dev_private;
+	struct drm_mode_config *config = &dev->mode_config;
+	struct drm_plane *plane;
 
 	ret = drm_fb_helper_restore_fbdev_mode(&dev_priv->fbdev->helper);
 	if (ret)
 		DRM_DEBUG("failed to restore crtc mode\n");
+
+	/* Be sure to shut off any planes that may be active */
+	list_for_each_entry(plane, &config->plane_list, head)
+		plane->funcs->disable_plane(plane);
 }
diff --git a/drivers/gpu/drm/i915/intel_overlay2.c b/drivers/gpu/drm/i915/intel_overlay2.c
new file mode 100644
index 0000000..5d376d9
--- /dev/null
+++ b/drivers/gpu/drm/i915/intel_overlay2.c
@@ -0,0 +1,438 @@
+/*
+ * Copyright © 2011 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ *   Jesse Barnes <jbarnes@virtuousgeek.org>
+ *
+ * New plane/sprite handling.
+ *
+ * The older chips had a separate interface for programming plane related
+ * registers; newer ones are much simpler and we can use the new DRM plane
+ * support.
+ */
+#include "drmP.h"
+#include "drm_crtc.h"
+#include "intel_drv.h"
+#include "i915_drm.h"
+#include "i915_drv.h"
+
+/*
+ * Note on refcounting:
+ * When the user creates an fb for the GEM object to be used for the plane,
+ * a ref is taken on the object.  However, if the application exits before
+ * disabling the plane, the DRM close handling will free all the fbs and
+ * unless we take a ref on the object, it will be destroyed before the
+ * plane disable hook is called, causing obvious trouble with our efforts
+ * to look up and unpin the object.  So we take a ref after we move the
+ * object to the display plane so it won't be destroyed until our disable
+ * hook is called and we drop our private reference.
+ */
+
+static void
+ivb_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb,
+		 unsigned long start, int crtc_x, int crtc_y,
+		 unsigned int crtc_w, unsigned int crtc_h,
+		 uint32_t x, uint32_t y,
+		 uint32_t src_w, uint32_t src_h)
+{
+	struct drm_device *dev = plane->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_plane *intel_plane = to_intel_plane(plane);
+	int pipe = intel_plane->pipe;
+	u32 sprctl, sprscale = 0;
+	u32 reg = SPRCTL(pipe);
+
+	sprctl = I915_READ(reg);
+
+	/* Mask out pixel format bits in case we change it */
+	sprctl &= ~(SPRITE_DEST_KEY | SPRITE_SOURCE_KEY);
+	sprctl &= ~SPRITE_PIXFORMAT_MASK;
+	sprctl &= ~SPRITE_RGB_ORDER_RGBX;
+	sprctl &= ~SPRITE_YUV_BYTE_ORDER_MASK;
+
+	switch (fb->pixel_format) {
+	case V4L2_PIX_FMT_BGR32:
+		sprctl |= SPRITE_FORMAT_RGBX888;
+		break;
+	case V4L2_PIX_FMT_RGB32:
+		sprctl |= SPRITE_FORMAT_RGBX888 | SPRITE_RGB_ORDER_RGBX;
+		break;
+	case V4L2_PIX_FMT_YUYV:
+		sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YUYV;
+		break;
+	case V4L2_PIX_FMT_YVYU:
+		sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YVYU;
+		break;
+	case V4L2_PIX_FMT_UYVY:
+		sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_UYVY;
+		break;
+	case V4L2_PIX_FMT_VYUY:
+		sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_VYUY;
+		break;
+	default:
+		DRM_DEBUG_DRIVER("bad pixel format, assuming RGBX888\n");
+		sprctl |= DVS_FORMAT_RGBX888;
+		break;
+	}
+
+	sprctl |= SPRITE_TILED;
+
+	/* must disable */
+	sprctl |= SPRITE_TRICKLE_FEED_DISABLE;
+	sprctl |= SPRITE_ENABLE;
+
+	/* Sizes are 0 based */
+	src_w--;
+	src_h--;
+	crtc_w--;
+	crtc_h--;
+
+	if (crtc_w != src_w || crtc_h != src_h)
+		sprscale = SPRITE_SCALE_ENABLE | (src_h << 16) | src_w;
+
+	I915_WRITE(SPRSTRIDE(pipe), fb->pitch);
+	I915_WRITE(SPRPOS(pipe), (crtc_y << 16) | crtc_x);
+	I915_WRITE(SPRTILEOFF(pipe), (y << 16) | x);
+	I915_WRITE(SPRSIZE(pipe), (crtc_h << 16) | crtc_w);
+	I915_WRITE(SPRSCALE(pipe), sprscale);
+	I915_WRITE(reg, sprctl);
+	I915_WRITE(SPRSURF(pipe), start);
+	POSTING_READ(SPRSURF(pipe));
+
+	/* Adjust watermarks as needed */
+	I915_WRITE(WM1S_LP_ILK, 0x100);
+	I915_WRITE(WM2S_LP_IVB, 0x100);
+	I915_WRITE(WM3S_LP_IVB, 0x100);
+}
+
+static void
+ivb_disable_plane(struct drm_plane *plane)
+{
+	struct drm_device *dev = plane->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_plane *intel_plane = to_intel_plane(plane);
+	int pipe = intel_plane->pipe;
+
+	I915_WRITE(SPRCTL(pipe), I915_READ(SPRCTL(pipe)) & ~SPRITE_ENABLE);
+	I915_WRITE(SPRSCALE(pipe), 0);
+	I915_WRITE(SPRSURF(pipe), 0);
+	POSTING_READ(SPRSURF(pipe));
+	intel_wait_for_vblank(dev, pipe);
+}
+
+static void
+snb_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb,
+		 unsigned long start, int crtc_x, int crtc_y,
+		 unsigned int crtc_w, unsigned int crtc_h,
+		 uint32_t x, uint32_t y,
+		 uint32_t src_w, uint32_t src_h)
+{
+	struct drm_device *dev = plane->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_plane *intel_plane = to_intel_plane(plane);
+	int pipe = intel_plane->pipe;
+	u32 dvscntr, dvsscale = 0;
+	u32 reg = DVSCNTR(pipe);
+
+	dvscntr = I915_READ(reg);
+
+	/* Mask out pixel format bits in case we change it */
+	dvscntr &= ~(DVS_DEST_KEY | DVS_SOURCE_KEY);
+	dvscntr &= ~DVS_PIXFORMAT_MASK;
+	dvscntr &= ~DVS_RGB_ORDER_RGBX;
+	dvscntr &= ~DVS_YUV_BYTE_ORDER_MASK;
+
+	switch (fb->pixel_format) {
+	case V4L2_PIX_FMT_BGR32:
+		dvscntr |= DVS_FORMAT_RGBX888;
+		break;
+	case V4L2_PIX_FMT_RGB32:
+		dvscntr |= DVS_FORMAT_RGBX888 | DVS_RGB_ORDER_RGBX;
+		break;
+	case V4L2_PIX_FMT_YUYV:
+		dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YUYV;
+		break;
+	case V4L2_PIX_FMT_YVYU:
+		dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YVYU;
+		break;
+	case V4L2_PIX_FMT_UYVY:
+		dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_UYVY;
+		break;
+	case V4L2_PIX_FMT_VYUY:
+		dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_VYUY;
+		break;
+	default:
+		DRM_DEBUG_DRIVER("bad pixel format, assuming RGBX888\n");
+		dvscntr |= DVS_FORMAT_RGBX888;
+		break;
+	}
+
+	dvscntr |= DVS_TILED;
+
+	/* must disable */
+	dvscntr |= DVS_TRICKLE_FEED_DISABLE;
+	dvscntr |= DVS_ENABLE;
+
+	/* Sizes are 0 based */
+	src_w--;
+	src_h--;
+	crtc_w--;
+	crtc_h--;
+
+	if (crtc_w != src_w || crtc_h != src_h)
+		dvsscale = DVS_SCALE_ENABLE | (src_h << 16) | src_w;
+
+	I915_WRITE(DVSSTRIDE(pipe), fb->pitch);
+	I915_WRITE(DVSPOS(pipe), (crtc_y << 16) | crtc_x);
+	I915_WRITE(DVSTILEOFF(pipe), (y << 16) | x);
+	I915_WRITE(DVSSIZE(pipe), (crtc_h << 16) | crtc_w);
+	I915_WRITE(DVSSCALE(pipe), dvsscale);
+	I915_WRITE(reg, dvscntr);
+	I915_WRITE(DVSSURF(pipe), start);
+	POSTING_READ(DVSSURF(pipe));
+}
+
+static void
+snb_disable_plane(struct drm_plane *plane)
+{
+	struct drm_device *dev = plane->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_plane *intel_plane = to_intel_plane(plane);
+	int pipe = intel_plane->pipe;
+
+	I915_WRITE(DVSCNTR(pipe), I915_READ(DVSCNTR(pipe)) & ~DVS_ENABLE);
+	I915_WRITE(DVSSCALE(pipe), 0);
+	I915_WRITE(DVSSURF(pipe), 0);
+	POSTING_READ(DVSSURF(pipe));
+	intel_wait_for_vblank(dev, pipe);
+}
+
+static int
+intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
+		   struct drm_framebuffer *fb, int crtc_x, int crtc_y,
+		   unsigned int crtc_w, unsigned int crtc_h,
+		   uint32_t src_x, uint32_t src_y,
+		   uint32_t src_w, uint32_t src_h)
+{
+	struct drm_device *dev = plane->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	struct intel_plane *intel_plane = to_intel_plane(plane);
+	struct intel_framebuffer *intel_fb;
+	struct drm_i915_gem_object *obj, *old_obj;
+	int pipe = intel_plane->pipe;
+	unsigned long start;
+	int ret = 0;
+	int x = src_x >> 16, y = src_y >> 16;
+	int primary_w = crtc->mode.hdisplay, primary_h = crtc->mode.vdisplay;
+	bool disable_primary = false;
+
+	intel_fb = to_intel_framebuffer(fb);
+	obj = intel_fb->obj;
+
+	old_obj = intel_plane->obj;
+
+	/* Pipe must be running... */
+	if (!(I915_READ(PIPECONF(pipe)) & PIPECONF_ENABLE))
+		return -EINVAL;
+
+	if (crtc_x >= primary_w || crtc_y >= primary_h)
+		return -EINVAL;
+
+	/* Don't modify another pipe's plane */
+	if (intel_plane->pipe != intel_crtc->pipe)
+		return -EINVAL;
+
+	/*
+	 * Clamp the width & height into the visible area.  Note we don't
+	 * try to scale the source if part of the visible region is offscreen.
+	 * The caller must handle that by adjusting source offset and size.
+	 */
+	if (crtc_x < 0) {
+		crtc_w += crtc_x;
+		crtc_x = 0;
+	}
+	if (crtc_x + crtc_w > primary_w)
+		crtc_w = primary_w - crtc_x;
+
+	if (crtc_y < 0) {
+		crtc_h += crtc_y;
+		crtc_y = 0;
+	}
+	if (crtc_y + crtc_h > primary_h)
+		crtc_h = primary_h - crtc_y;
+
+	/*
+	 * We can take a larger source and scale it down, but
+	 * only so much...  16x is the max on SNB.
+	 */
+	if (((src_w * src_h) / (crtc_w * crtc_h)) > intel_plane->max_downscale)
+		return -EINVAL;
+
+	/*
+	 * If the overlay is completely covering the primary plane,
+	 * we can disable the primary and save power.
+	 */
+	if ((crtc_x == 0) && (crtc_y == 0) &&
+	    (crtc_w == primary_w) && (crtc_h == primary_h))
+		disable_primary = true;
+
+	mutex_lock(&dev->struct_mutex);
+
+	if (obj->tiling_mode != I915_TILING_X) {
+		DRM_ERROR("plane surfaces must be X tiled\n");
+		ret = -EINVAL;
+		goto out_unlock;
+	}
+
+	ret = intel_pin_and_fence_fb_obj(dev, obj, NULL);
+	if (ret) {
+		DRM_ERROR("failed to pin object\n");
+		goto out_unlock;
+	}
+
+	drm_gem_object_reference(&obj->base);
+
+	intel_plane->obj = obj;
+
+	start = obj->gtt_offset;
+
+	/*
+	 * Be sure to re-enable the primary before the overlay is no longer
+	 * covering it fully.
+	 */
+	if (!disable_primary && intel_plane->primary_disabled) {
+		//dev_priv->display.enable_primary(dev, crtc);
+		intel_plane->primary_disabled = false;
+	}
+
+	intel_plane->update_plane(plane, fb, start, crtc_x, crtc_y,
+				  crtc_w, crtc_h, x, y, src_w, src_h);
+
+	if (disable_primary) {
+		//dev_priv->display.disable_primary(dev, crtc);
+		intel_plane->primary_disabled = true;
+	}
+
+	/* Unpin old obj after new one is active to avoid ugliness */
+	if (old_obj) {
+		/*
+		 * It's fairly common to simply update the position of
+		 * an existing object.  In that case, we don't need to
+		 * wait for vblank to avoid ugliness, we only need to
+		 * do the pin & ref bookkeeping.
+		 */
+		if (old_obj != obj)
+			intel_wait_for_vblank(dev, to_intel_crtc(crtc)->pipe);
+		i915_gem_object_unpin(old_obj);
+		drm_gem_object_unreference(&old_obj->base);
+	}
+
+out_unlock:
+	mutex_unlock(&dev->struct_mutex);
+
+	return ret;
+}
+
+static int
+intel_disable_plane(struct drm_plane *plane)
+{
+	struct drm_device *dev = plane->dev;
+	struct intel_plane *intel_plane = to_intel_plane(plane);
+	int ret = 0;
+
+	mutex_lock(&dev->struct_mutex);
+
+	if (intel_plane->primary_disabled) {
+		//dev_priv->display.enable_primary(dev, crtc);
+		intel_plane->primary_disabled = false;
+	}
+
+	intel_plane->disable_plane(plane);
+
+	if (!intel_plane->obj)
+		goto out_unlock;
+
+	ret = i915_gem_object_finish_gpu(intel_plane->obj);
+	if (ret)
+		goto out_unlock;
+
+	i915_gem_object_unpin(intel_plane->obj);
+
+	drm_gem_object_unreference(&intel_plane->obj->base);
+
+out_unlock:
+	intel_plane->obj = NULL;
+
+	mutex_unlock(&dev->struct_mutex);
+
+	return ret;
+}
+
+static struct drm_plane_funcs intel_plane_funcs;
+
+static uint32_t snb_plane_formats[] = {
+	V4L2_PIX_FMT_BGR32,
+	V4L2_PIX_FMT_RGB32,
+	V4L2_PIX_FMT_YUYV,
+	V4L2_PIX_FMT_YVYU,
+	V4L2_PIX_FMT_UYVY,
+	V4L2_PIX_FMT_VYUY,
+};
+
+int
+intel_plane_init(struct drm_device *dev, enum pipe pipe)
+{
+	struct intel_plane *intel_plane;
+	unsigned long possible_crtcs;
+
+	if (!(IS_GEN6(dev) || IS_GEN7(dev))) {
+		DRM_ERROR("new plane code only for SNB+\n");
+		return -ENODEV;
+	}
+
+	intel_plane = kzalloc(sizeof(struct intel_plane), GFP_KERNEL);
+	if (!intel_plane)
+		return -ENOMEM;
+
+	intel_plane_funcs.update_plane = intel_update_plane;
+	intel_plane_funcs.disable_plane = intel_disable_plane;
+
+	if (IS_GEN6(dev)) {
+		intel_plane->max_downscale = 16;
+		intel_plane->update_plane = snb_update_plane;
+		intel_plane->disable_plane = snb_disable_plane;
+	} 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->pipe = pipe;
+	possible_crtcs = (1 << pipe);
+	drm_plane_init(dev, &intel_plane->base, possible_crtcs,
+		       &intel_plane_funcs, snb_plane_formats,
+		       ARRAY_SIZE(snb_plane_formats));
+
+	return 0;
+}
+
-- 
1.7.4.1

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [PATCH 5/5] drm/i915: add destination color key support
  2011-11-02 20:03 [PATCH] DRM planes Jesse Barnes
                   ` (3 preceding siblings ...)
  2011-11-02 20:03 ` [PATCH 4/5] drm/i915: add SNB and IVB video sprite support Jesse Barnes
@ 2011-11-02 20:03 ` Jesse Barnes
  2011-11-03 18:23   ` Jesse Barnes
  2011-11-03 14:11 ` [PATCH] DRM planes Daniel Vetter
  5 siblings, 1 reply; 32+ messages in thread
From: Jesse Barnes @ 2011-11-02 20:03 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx, rob.clark

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.

Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
---
 drivers/gpu/drm/i915/i915_dma.c       |    2 +
 drivers/gpu/drm/i915/intel_drv.h      |    6 +++
 drivers/gpu/drm/i915/intel_overlay2.c |   72 +++++++++++++++++++++++++++++++++
 include/drm/i915_drm.h                |   16 +++++++
 4 files changed, 96 insertions(+), 0 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index 2eac955..2d163e8 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -2294,6 +2294,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_DESTKEY, intel_overlay_set_destkey, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+	DRM_IOCTL_DEF_DRV(I915_GET_SPRITE_DESTKEY, intel_overlay_get_destkey, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
 };
 
 int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls);
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 39b3ae7..016ef54 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -407,4 +407,10 @@ extern void intel_write_eld(struct drm_encoder *encoder,
 			    struct drm_display_mode *mode);
 extern void intel_cpt_verify_modeset(struct drm_device *dev, int pipe);
 
+extern int intel_overlay_set_destkey(struct drm_device *dev, void *data,
+				     struct drm_file *file_priv);
+extern int intel_overlay_get_destkey(struct drm_device *dev, void *data,
+				     struct drm_file *file_priv);
+
+
 #endif /* __INTEL_DRV_H__ */
diff --git a/drivers/gpu/drm/i915/intel_overlay2.c b/drivers/gpu/drm/i915/intel_overlay2.c
index 5d376d9..dd6ede5 100644
--- a/drivers/gpu/drm/i915/intel_overlay2.c
+++ b/drivers/gpu/drm/i915/intel_overlay2.c
@@ -99,6 +99,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--;
@@ -388,6 +389,77 @@ out_unlock:
 	return ret;
 }
 
+int intel_overlay_set_destkey(struct drm_device *dev, void *data,
+			      struct drm_file *file_priv)
+{
+	struct drm_intel_set_sprite_destkey *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;
+
+	if (set->value > 0xffffff)
+		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);
+
+	mutex_lock(&dev->struct_mutex);
+	I915_WRITE(SPRKEYVAL(intel_plane->pipe), set->value);
+	I915_WRITE(SPRKEYMSK(intel_plane->pipe), 0xffffff);
+	POSTING_READ(SPRKEYMSK(intel_plane->pipe));
+	mutex_unlock(&dev->struct_mutex);
+
+out_unlock:
+	mutex_unlock(&dev->mode_config.mutex);
+	return ret;
+}
+
+int intel_overlay_get_destkey(struct drm_device *dev, void *data,
+			      struct drm_file *file_priv)
+{
+	struct drm_intel_get_sprite_destkey *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);
+
+	mutex_lock(&dev->struct_mutex);
+	get->value = I915_READ(SPRKEYVAL(intel_plane->pipe));
+	mutex_unlock(&dev->struct_mutex);
+
+out_unlock:
+	mutex_unlock(&dev->mode_config.mutex);
+	return ret;
+}
+
 static struct drm_plane_funcs intel_plane_funcs;
 
 static uint32_t snb_plane_formats[] = {
diff --git a/include/drm/i915_drm.h b/include/drm/i915_drm.h
index 28c0d11..f9a390b 100644
--- a/include/drm/i915_drm.h
+++ b/include/drm/i915_drm.h
@@ -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_DESTKEY	0x2a
+#define DRM_I915_SET_SPRITE_DESTKEY	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_DESTKEY DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_SET_SPRITE_DESTKEY, struct drm_intel_set_sprite_destkey)
+#define DRM_IOCTL_I915_GET_SPRITE_DESTKEY DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_SET_SPRITE_DESTKEY, struct drm_intel_get_sprite_destkey)
 
 /* Allow drivers to submit batchbuffers directly to hardware, relying
  * on the security mechanisms provided by hardware.
@@ -844,4 +848,16 @@ struct drm_intel_overlay_attrs {
 	__u32 gamma5;
 };
 
+/* Set the destination color key on a given sprite */
+struct drm_intel_set_sprite_destkey {
+	__u32 plane_id;
+	__u32 value;
+};
+
+/* Get the current destination color key on a given sprite */
+struct drm_intel_get_sprite_destkey {
+	__u32 plane_id;
+	__u64 value;
+};
+
 #endif				/* _I915_DRM_H_ */
-- 
1.7.4.1

^ permalink raw reply related	[flat|nested] 32+ messages in thread

* Re: [PATCH 1/5] drm: add plane support
  2011-11-02 20:03 ` [PATCH 1/5] drm: add plane support Jesse Barnes
@ 2011-11-02 22:33   ` Jesse Barnes
  2011-11-03 18:21     ` Jesse Barnes
  2011-11-04  2:22   ` Joonyoung Shim
  1 sibling, 1 reply; 32+ messages in thread
From: Jesse Barnes @ 2011-11-02 22:33 UTC (permalink / raw)
  To: Jesse Barnes; +Cc: intel-gfx, dri-devel, rob.clark


[-- Attachment #1.1: Type: text/plain, Size: 533 bytes --]

On Wed,  2 Nov 2011 13:03:19 -0700
Jesse Barnes <jbarnes@virtuousgeek.org> wrote:

> Planes are a bit like half-CRTCs.  They have a location and fb, but
> don't drive outputs directly.  Add support for handling them to the core
> KMS code.

Accidentally left out the ->destroy hook in this one.  The drm-overlays
branch at git://people.freedesktop.org/~jbarnes/linux has a fixed
version, along with a couple of fixes for issues Chris and Dan pointed
out.

Thanks,
-- 
Jesse Barnes, Intel Open Source Technology Center

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

[-- Attachment #2: Type: text/plain, Size: 159 bytes --]

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH] DRM planes
  2011-11-02 20:03 [PATCH] DRM planes Jesse Barnes
                   ` (4 preceding siblings ...)
  2011-11-02 20:03 ` [PATCH 5/5] drm/i915: add destination color key support Jesse Barnes
@ 2011-11-03 14:11 ` Daniel Vetter
  2011-11-03 15:12   ` Jesse Barnes
  2011-11-03 17:47   ` Alan Cox
  5 siblings, 2 replies; 32+ messages in thread
From: Daniel Vetter @ 2011-11-03 14:11 UTC (permalink / raw)
  To: Jesse Barnes; +Cc: intel-gfx, dri-devel, rob.clark

On Wed, Nov 02, 2011 at 01:03:18PM -0700, Jesse Barnes wrote:
> In response to feedback, I've adjusted the new addfb2 ioctl to take per
> component pitch and offset args.  Generally, the offset[0] field will be
> 0, but it's conceivable that some metadata could be stored at the start
> of a given buffer, and an offset[0] allows the client to skip past that.
> Similarly, pitch[0] will typically describe the whole buffer, but it's
> possible to simply string together several planes into a single object
> where individual pitch components matter.
> 
> Userland patches are available in the drm-overlays branches of my
> personal libdrm and xf86-video-intel trees at freedesktop.org.  The
> xf86-video-intel side works well enough to handle clipping (using a new
> i915 specific ioctl for setting a destination color key) and play
> videos, albeit without nice flipping.
> 
> Assuming no major objections, I think this is finally ready for
> drm-next.

Well, the fool I am I've attempted to write a nice little drm plane
wrapper for the legacy intel overlay code. Code is totally untested, but I
like what it looks like - the drm plane interfaces are a quite natural fit
to the existing code. There's one thing though which is imo a bloody mess
(and I've given up writing the code for it), namely planar yuv handling
with fourcc pixelformats. The current implementation for snb+ doesn't
stumble over that rock because it only supports packed yuv.

So here goes the rant: The legacy overlay (and my ioctl) accept a set off
offset for Y, U and V planes (i.e. it could even accept different bos, but
the current ioctl designed for Xv doesn't). The hw has the restriction
that the strides for the U and V planes need to be identical, but that's
it. Pixelformat is just an enumeration of YUV422,420,411,410 to specify
the subsampling ratio of the U/V planes.

Now fourcc specifies all these offset implicitly in the pixelformat (at
least that's what I've figured out, I might be wrong though):
- Some formats have the YUV planes in a special, fixed arrangement, no
  additional offset needs to be passed in and strides are implicit from
  the width.
- Some have a separate offset somewhere for UV planes, but the UV planes
  are again in a fixed layout (either interleaved or one after another).
- Some fourcc have all three planes independant, i.e. you need an offset
  for the U and the V plane. No clue what that implies for the stride.

In short decoding these fourcc values with all their implicit assumptions
about offset, strides and whatnotelse will be one giant switch mess. Not
my idea of a nice kernel interface. Also practically guaranteed to result
in slightly different behaviour in each driver.

So here's the new radical proposal (and yep, I expect heat for this):
- Ditch fourcc. Afaics this wheel is square and no amount of sharpening
  the corners will make it round.
- Ditch addfb support for planar yuv formats, at least for the moment.
  Until we have more than one kms driver for this I don't think we can
  come up with any sane interface.

In conclusion: Ditch the addfb2ioctl and just add a few more kms pixel
formats for the new packed yuv layouts that the snb+ sprite code needs.

Cheers, Daniel
-- 
Daniel Vetter
Mail: daniel@ffwll.ch
Mobile: +41 (0)79 365 57 48

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH] DRM planes
  2011-11-03 14:11 ` [PATCH] DRM planes Daniel Vetter
@ 2011-11-03 15:12   ` Jesse Barnes
  2011-11-03 17:29     ` Daniel Vetter
  2011-11-03 17:47   ` Alan Cox
  1 sibling, 1 reply; 32+ messages in thread
From: Jesse Barnes @ 2011-11-03 15:12 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: intel-gfx, dri-devel, rob.clark


[-- Attachment #1.1: Type: text/plain, Size: 4165 bytes --]

On Thu, 3 Nov 2011 15:11:55 +0100
Daniel Vetter <daniel@ffwll.ch> wrote:

> On Wed, Nov 02, 2011 at 01:03:18PM -0700, Jesse Barnes wrote:
> > In response to feedback, I've adjusted the new addfb2 ioctl to take per
> > component pitch and offset args.  Generally, the offset[0] field will be
> > 0, but it's conceivable that some metadata could be stored at the start
> > of a given buffer, and an offset[0] allows the client to skip past that.
> > Similarly, pitch[0] will typically describe the whole buffer, but it's
> > possible to simply string together several planes into a single object
> > where individual pitch components matter.
> > 
> > Userland patches are available in the drm-overlays branches of my
> > personal libdrm and xf86-video-intel trees at freedesktop.org.  The
> > xf86-video-intel side works well enough to handle clipping (using a new
> > i915 specific ioctl for setting a destination color key) and play
> > videos, albeit without nice flipping.
> > 
> > Assuming no major objections, I think this is finally ready for
> > drm-next.
> 
> Well, the fool I am I've attempted to write a nice little drm plane
> wrapper for the legacy intel overlay code. Code is totally untested, but I
> like what it looks like - the drm plane interfaces are a quite natural fit
> to the existing code. There's one thing though which is imo a bloody mess
> (and I've given up writing the code for it), namely planar yuv handling
> with fourcc pixelformats. The current implementation for snb+ doesn't
> stumble over that rock because it only supports packed yuv.
> 
> So here goes the rant: The legacy overlay (and my ioctl) accept a set off
> offset for Y, U and V planes (i.e. it could even accept different bos, but
> the current ioctl designed for Xv doesn't). The hw has the restriction
> that the strides for the U and V planes need to be identical, but that's
> it. Pixelformat is just an enumeration of YUV422,420,411,410 to specify
> the subsampling ratio of the U/V planes.
> 
> Now fourcc specifies all these offset implicitly in the pixelformat (at
> least that's what I've figured out, I might be wrong though):
> - Some formats have the YUV planes in a special, fixed arrangement, no
>   additional offset needs to be passed in and strides are implicit from
>   the width.
> - Some have a separate offset somewhere for UV planes, but the UV planes
>   are again in a fixed layout (either interleaved or one after another).
> - Some fourcc have all three planes independant, i.e. you need an offset
>   for the U and the V plane. No clue what that implies for the stride.
> 
> In short decoding these fourcc values with all their implicit assumptions
> about offset, strides and whatnotelse will be one giant switch mess. Not
> my idea of a nice kernel interface. Also practically guaranteed to result
> in slightly different behaviour in each driver.

There may be some v4l code we can share here, or at least refactor, for
use by drivers that want to handle planar formats like the old
overlay.  Did you look for any?

> 
> So here's the new radical proposal (and yep, I expect heat for this):
> - Ditch fourcc. Afaics this wheel is square and no amount of sharpening
>   the corners will make it round.
> - Ditch addfb support for planar yuv formats, at least for the moment.
>   Until we have more than one kms driver for this I don't think we can
>   come up with any sane interface.
> 
> In conclusion: Ditch the addfb2ioctl and just add a few more kms pixel
> formats for the new packed yuv layouts that the snb+ sprite code needs.

We'll still need the new ioctl though.  We don't have enough info today
(just bpp and depth) in the existing addfb ioctl to figure out what the
actual plane layout is.

We can move away from fourcc, but it still seems like we'd end up
duplicating it at least a little, as our full set of supported formats
would be the superset of what each driver supports.

I'm not wedded to fourcc, but I guess we'll have to see what the TI and
Samsung guys say to make a decision.

-- 
Jesse Barnes, Intel Open Source Technology Center

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

[-- Attachment #2: Type: text/plain, Size: 159 bytes --]

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH] DRM planes
  2011-11-03 15:12   ` Jesse Barnes
@ 2011-11-03 17:29     ` Daniel Vetter
  2011-11-03 17:36       ` Jesse Barnes
  0 siblings, 1 reply; 32+ messages in thread
From: Daniel Vetter @ 2011-11-03 17:29 UTC (permalink / raw)
  To: Jesse Barnes; +Cc: intel-gfx, dri-devel, rob.clark

Hi all,

I've discussed this a bit on irc and consensus seems to be "some ugliness
due to interface impendance mistmatches in the kernel? who cares ...". I
agree that there's not a fundamental problem with fourcc and planar yuv
that can't be fixed with a bunch of boilerplate code with the assorted set
of inconsistencies between drivers. So if this is the general consensus
I'll just look the other way, shut down my shields an recall my battle
ship out of LEO ... ;-)

Cheers, Daniel
-- 
Daniel Vetter
Mail: daniel@ffwll.ch
Mobile: +41 (0)79 365 57 48

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH] DRM planes
  2011-11-03 17:29     ` Daniel Vetter
@ 2011-11-03 17:36       ` Jesse Barnes
  2011-11-03 18:55         ` Rob Clark
  0 siblings, 1 reply; 32+ messages in thread
From: Jesse Barnes @ 2011-11-03 17:36 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Inki Dae, intel-gfx, Joonyoung Shim, dri-devel, rob.clark


[-- Attachment #1.1: Type: text/plain, Size: 736 bytes --]

On Thu, 3 Nov 2011 18:29:14 +0100
Daniel Vetter <daniel@ffwll.ch> wrote:

> Hi all,
> 
> I've discussed this a bit on irc and consensus seems to be "some ugliness
> due to interface impendance mistmatches in the kernel? who cares ...". I
> agree that there's not a fundamental problem with fourcc and planar yuv
> that can't be fixed with a bunch of boilerplate code with the assorted set
> of inconsistencies between drivers. So if this is the general consensus
> I'll just look the other way, shut down my shields an recall my battle
> ship out of LEO ... ;-)

Rob, Joonyoung, Inkie, any comment on using fourcc vs rolling our own
surface definitions?

Thanks,
-- 
Jesse Barnes, Intel Open Source Technology Center

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

[-- Attachment #2: Type: text/plain, Size: 159 bytes --]

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH] DRM planes
  2011-11-03 14:11 ` [PATCH] DRM planes Daniel Vetter
  2011-11-03 15:12   ` Jesse Barnes
@ 2011-11-03 17:47   ` Alan Cox
  2011-11-03 18:58     ` Daniel Vetter
  1 sibling, 1 reply; 32+ messages in thread
From: Alan Cox @ 2011-11-03 17:47 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: intel-gfx, dri-devel, rob.clark

> In short decoding these fourcc values with all their implicit assumptions
> about offset, strides and whatnotelse will be one giant switch mess. Not
> my idea of a nice kernel interface. Also practically guaranteed to result
> in slightly different behaviour in each driver.

So you'd rather make each applicationa author get it wrong individually
and uniquely. That is a bigger mess by far.

> In conclusion: Ditch the addfb2ioctl and just add a few more kms pixel
> formats for the new packed yuv layouts that the snb+ sprite code needs.

If you need a decoder for some hardware then fine, write one - share it
with the v4l one and put it in a library drivers can call.

However - user space is already working in fourcc, v4l has working fourcc
and dumping the mess on the user isn't going to be a win.

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH 1/5] drm: add plane support
  2011-11-02 22:33   ` Jesse Barnes
@ 2011-11-03 18:21     ` Jesse Barnes
  2011-11-03 22:48       ` Jesse Barnes
  0 siblings, 1 reply; 32+ messages in thread
From: Jesse Barnes @ 2011-11-03 18:21 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx, rob.clark


[-- Attachment #1.1: Type: text/plain, Size: 17616 bytes --]

On Wed, 2 Nov 2011 15:33:04 -0700
Jesse Barnes <jbarnes@virtuousgeek.org> wrote:

> On Wed,  2 Nov 2011 13:03:19 -0700
> Jesse Barnes <jbarnes@virtuousgeek.org> wrote:
> 
> > Planes are a bit like half-CRTCs.  They have a location and fb, but
> > don't drive outputs directly.  Add support for handling them to the core
> > KMS code.
> 
> Accidentally left out the ->destroy hook in this one.  The drm-overlays
> branch at git://people.freedesktop.org/~jbarnes/linux has a fixed
> version, along with a couple of fixes for issues Chris and Dan pointed
> out.

Below is the updated patch with ->destroy in case this series passes
muster and Dave is ready to apply.

-- 
Jesse Barnes, Intel Open Source Technology Center

From cb292ebfc5efbcc71b1b55ada45a98e43347b4cf Mon Sep 17 00:00:00 2001
From: Jesse Barnes <jbarnes@virtuousgeek.org>
Date: Thu, 21 Apr 2011 16:58:37 -0700
Subject: [PATCH 1/4] drm: add plane support

Planes are a bit like half-CRTCs.  They have a location and fb, but
don't drive outputs directly.  Add support for handling them to the core
KMS code.

Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
---
 drivers/gpu/drm/drm_crtc.c |  241 +++++++++++++++++++++++++++++++++++++++++++-
 drivers/gpu/drm/drm_drv.c  |    3 +
 include/drm/drm.h          |    3 +
 include/drm/drm_crtc.h     |   79 ++++++++++++++-
 include/drm/drm_mode.h     |   33 ++++++
 5 files changed, 356 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index fe738f0..cea209a 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -535,6 +535,48 @@ void drm_encoder_cleanup(struct drm_encoder *encoder)
 }
 EXPORT_SYMBOL(drm_encoder_cleanup);
 
+void drm_plane_init(struct drm_device *dev, struct drm_plane *plane,
+		    unsigned long possible_crtcs,
+		    const struct drm_plane_funcs *funcs,
+		    uint32_t *formats, uint32_t format_count)
+{
+	mutex_lock(&dev->mode_config.mutex);
+
+	plane->dev = dev;
+	drm_mode_object_get(dev, &plane->base, DRM_MODE_OBJECT_PLANE);
+	plane->funcs = funcs;
+	plane->format_types = kmalloc(sizeof(uint32_t) * format_count,
+				      GFP_KERNEL);
+	if (!plane->format_types) {
+		DRM_DEBUG_KMS("out of memory when allocating plane\n");
+		drm_mode_object_put(dev, &plane->base);
+		return;
+	}
+
+	memcpy(plane->format_types, formats, format_count);
+	plane->format_count = format_count;
+	plane->possible_crtcs = possible_crtcs;
+
+	list_add_tail(&plane->head, &dev->mode_config.plane_list);
+	dev->mode_config.num_plane++;
+
+	mutex_unlock(&dev->mode_config.mutex);
+}
+EXPORT_SYMBOL(drm_plane_init);
+
+void drm_plane_cleanup(struct drm_plane *plane)
+{
+	struct drm_device *dev = plane->dev;
+
+	mutex_lock(&dev->mode_config.mutex);
+	kfree(plane->format_types);
+	drm_mode_object_put(dev, &plane->base);
+	list_del(&plane->head);
+	dev->mode_config.num_plane--;
+	mutex_unlock(&dev->mode_config.mutex);
+}
+EXPORT_SYMBOL(drm_plane_cleanup);
+
 /**
  * drm_mode_create - create a new display mode
  * @dev: DRM device
@@ -866,6 +908,7 @@ void drm_mode_config_init(struct drm_device *dev)
 	INIT_LIST_HEAD(&dev->mode_config.encoder_list);
 	INIT_LIST_HEAD(&dev->mode_config.property_list);
 	INIT_LIST_HEAD(&dev->mode_config.property_blob_list);
+	INIT_LIST_HEAD(&dev->mode_config.plane_list);
 	idr_init(&dev->mode_config.crtc_idr);
 
 	mutex_lock(&dev->mode_config.mutex);
@@ -942,6 +985,7 @@ void drm_mode_config_cleanup(struct drm_device *dev)
 	struct drm_encoder *encoder, *enct;
 	struct drm_framebuffer *fb, *fbt;
 	struct drm_property *property, *pt;
+	struct drm_plane *plane, *plt;
 
 	list_for_each_entry_safe(encoder, enct, &dev->mode_config.encoder_list,
 				 head) {
@@ -966,6 +1010,10 @@ void drm_mode_config_cleanup(struct drm_device *dev)
 		crtc->funcs->destroy(crtc);
 	}
 
+	list_for_each_entry_safe(plane, plt, &dev->mode_config.plane_list,
+				 head) {
+		plane->funcs->destroy(plane);
+	}
 }
 EXPORT_SYMBOL(drm_mode_config_cleanup);
 
@@ -1466,6 +1514,193 @@ out:
 }
 
 /**
+ * drm_mode_getplane_res - get plane info
+ * @dev: DRM device
+ * @data: ioctl data
+ * @file_priv: DRM file info
+ *
+ * Return an plane count and set of IDs.
+ */
+int drm_mode_getplane_res(struct drm_device *dev, void *data,
+			    struct drm_file *file_priv)
+{
+	struct drm_mode_get_plane_res *plane_resp = data;
+	struct drm_mode_config *config;
+	struct drm_plane *plane;
+	uint32_t __user *plane_ptr;
+	int copied = 0, ret = 0;
+
+	if (!drm_core_check_feature(dev, DRIVER_MODESET))
+		return -EINVAL;
+
+	mutex_lock(&dev->mode_config.mutex);
+	config = &dev->mode_config;
+
+	/*
+	 * This ioctl is called twice, once to determine how much space is
+	 * needed, and the 2nd time to fill it.
+	 */
+	if (config->num_plane &&
+	    (plane_resp->count_planes >= config->num_plane)) {
+		plane_ptr = (uint32_t *)(unsigned long)plane_resp->plane_id_ptr;
+
+		list_for_each_entry(plane, &config->plane_list, head) {
+			if (put_user(plane->base.id, plane_ptr + copied)) {
+				ret = -EFAULT;
+				goto out;
+			}
+			copied++;
+		}
+	}
+	plane_resp->count_planes = config->num_plane;
+
+out:
+	mutex_unlock(&dev->mode_config.mutex);
+	return ret;
+}
+
+/**
+ * drm_mode_getplane - get plane info
+ * @dev: DRM device
+ * @data: ioctl data
+ * @file_priv: DRM file info
+ *
+ * Return plane info, including formats supported, gamma size, any
+ * current fb, etc.
+ */
+int drm_mode_getplane(struct drm_device *dev, void *data,
+			struct drm_file *file_priv)
+{
+	struct drm_mode_get_plane *plane_resp = data;
+	struct drm_mode_object *obj;
+	struct drm_plane *plane;
+	uint32_t __user *format_ptr;
+	int ret = 0;
+
+	if (!drm_core_check_feature(dev, DRIVER_MODESET))
+		return -EINVAL;
+
+	mutex_lock(&dev->mode_config.mutex);
+	obj = drm_mode_object_find(dev, plane_resp->plane_id,
+				   DRM_MODE_OBJECT_PLANE);
+	if (!obj) {
+		ret = -EINVAL;
+		goto out;
+	}
+	plane = obj_to_plane(obj);
+
+	if (plane->crtc)
+		plane_resp->crtc_id = plane->crtc->base.id;
+	else
+		plane_resp->crtc_id = 0;
+
+	if (plane->fb)
+		plane_resp->fb_id = plane->fb->base.id;
+	else
+		plane_resp->fb_id = 0;
+
+	plane_resp->plane_id = plane->base.id;
+	plane_resp->possible_crtcs = plane->possible_crtcs;
+	plane_resp->gamma_size = plane->gamma_size;
+
+	/*
+	 * This ioctl is called twice, once to determine how much space is
+	 * needed, and the 2nd time to fill it.
+	 */
+	if (plane->format_count &&
+	    (plane_resp->count_format_types >= plane->format_count)) {
+		format_ptr = (uint32_t *)(unsigned long)plane_resp->format_type_ptr;
+		if (copy_to_user(format_ptr,
+				 plane->format_types,
+				 sizeof(uint32_t) * plane->format_count)) {
+			ret = -EFAULT;
+			goto out;
+		}
+	}
+	plane_resp->count_format_types = plane->format_count;
+
+out:
+	mutex_unlock(&dev->mode_config.mutex);
+	return ret;
+}
+
+/**
+ * drm_mode_setplane - set up or tear down an plane
+ * @dev: DRM device
+ * @data: ioctl data*
+ * @file_prive: DRM file info
+ *
+ * Set plane info, including placement, fb, scaling, and other factors.
+ * Or pass a NULL fb to disable.
+ */
+int drm_mode_setplane(struct drm_device *dev, void *data,
+			struct drm_file *file_priv)
+{
+	struct drm_mode_set_plane *plane_req = data;
+	struct drm_mode_object *obj;
+	struct drm_plane *plane;
+	struct drm_crtc *crtc;
+	struct drm_framebuffer *fb;
+	int ret = 0;
+
+	if (!drm_core_check_feature(dev, DRIVER_MODESET))
+		return -EINVAL;
+
+	mutex_lock(&dev->mode_config.mutex);
+
+	/*
+	 * First, find the plane, crtc, and fb objects.  If not available,
+	 * we don't bother to call the driver.
+	 */
+	obj = drm_mode_object_find(dev, plane_req->plane_id,
+				   DRM_MODE_OBJECT_PLANE);
+	if (!obj) {
+		DRM_DEBUG_KMS("Unknown plane ID %d\n",
+			      plane_req->plane_id);
+		ret = -EINVAL;
+		goto out;
+	}
+	plane = obj_to_plane(obj);
+
+	/* No fb means shut it down */
+	if (!plane_req->fb_id) {
+		plane->funcs->disable_plane(plane);
+		goto out;
+	}
+
+	obj = drm_mode_object_find(dev, plane_req->crtc_id,
+				   DRM_MODE_OBJECT_CRTC);
+	if (!obj) {
+		DRM_DEBUG_KMS("Unknown crtc ID %d\n",
+			      plane_req->crtc_id);
+		ret = -EINVAL;
+		goto out;
+	}
+	crtc = obj_to_crtc(obj);
+
+	obj = drm_mode_object_find(dev, plane_req->fb_id,
+				   DRM_MODE_OBJECT_FB);
+	if (!obj) {
+		DRM_DEBUG_KMS("Unknown framebuffer ID %d\n",
+			      plane_req->fb_id);
+		ret = -EINVAL;
+		goto out;
+	}
+	fb = obj_to_fb(obj);
+
+	ret = plane->funcs->update_plane(plane, crtc, fb,
+					 plane_req->crtc_x, plane_req->crtc_y,
+					 plane_req->crtc_w, plane_req->crtc_h,
+					 plane_req->src_x, plane_req->src_y,
+					 plane_req->src_h, plane_req->src_w);
+
+out:
+	mutex_unlock(&dev->mode_config.mutex);
+
+	return ret;
+}
+
+/**
  * drm_mode_setcrtc - set CRTC configuration
  * @inode: inode from the ioctl
  * @filp: file * from the ioctl
@@ -1688,11 +1923,13 @@ int drm_mode_addfb(struct drm_device *dev,
 		return -EINVAL;
 
 	if ((config->min_width > r->width) || (r->width > config->max_width)) {
-		DRM_ERROR("mode new framebuffer width not within limits\n");
+		DRM_ERROR("bad framebuffer width %d, should be >= %d && <= %d\n",
+			  r->width, config->min_width, config->max_width);
 		return -EINVAL;
 	}
 	if ((config->min_height > r->height) || (r->height > config->max_height)) {
-		DRM_ERROR("mode new framebuffer height not within limits\n");
+		DRM_ERROR("bad framebuffer height %d, should be >= %d && <= %d\n",
+			  r->height, config->min_height, config->max_height);
 		return -EINVAL;
 	}
 
diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
index 7a87e08..d782bd1 100644
--- a/drivers/gpu/drm/drm_drv.c
+++ b/drivers/gpu/drm/drm_drv.c
@@ -135,8 +135,11 @@ static struct drm_ioctl_desc drm_ioctls[] = {
 	DRM_IOCTL_DEF(DRM_IOCTL_GEM_OPEN, drm_gem_open_ioctl, DRM_AUTH|DRM_UNLOCKED),
 
 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETRESOURCES, drm_mode_getresources, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPLANERESOURCES, drm_mode_getplane_res, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCRTC, drm_mode_getcrtc, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETCRTC, drm_mode_setcrtc, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPLANE, drm_mode_getplane, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETPLANE, drm_mode_setplane, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_CURSOR, drm_mode_cursor_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETGAMMA, drm_mode_gamma_get_ioctl, DRM_MASTER|DRM_UNLOCKED),
 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETGAMMA, drm_mode_gamma_set_ioctl, DRM_MASTER|DRM_UNLOCKED),
diff --git a/include/drm/drm.h b/include/drm/drm.h
index 4be33b4..2897967 100644
--- a/include/drm/drm.h
+++ b/include/drm/drm.h
@@ -714,6 +714,9 @@ struct drm_get_cap {
 #define DRM_IOCTL_MODE_CREATE_DUMB DRM_IOWR(0xB2, struct drm_mode_create_dumb)
 #define DRM_IOCTL_MODE_MAP_DUMB    DRM_IOWR(0xB3, struct drm_mode_map_dumb)
 #define DRM_IOCTL_MODE_DESTROY_DUMB    DRM_IOWR(0xB4, struct drm_mode_destroy_dumb)
+#define DRM_IOCTL_MODE_GETPLANERESOURCES DRM_IOWR(0xB5, struct drm_mode_get_plane_res)
+#define DRM_IOCTL_MODE_GETPLANE	DRM_IOWR(0xB6, struct drm_mode_get_plane)
+#define DRM_IOCTL_MODE_SETPLANE	DRM_IOWR(0xB7, struct drm_mode_set_plane)
 
 /**
  * Device specific ioctls should only be in their respective headers
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 8020798..8331dc6 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -44,6 +44,7 @@ struct drm_framebuffer;
 #define DRM_MODE_OBJECT_PROPERTY 0xb0b0b0b0
 #define DRM_MODE_OBJECT_FB 0xfbfbfbfb
 #define DRM_MODE_OBJECT_BLOB 0xbbbbbbbb
+#define DRM_MODE_OBJECT_PLANE 0xeeeeeeee
 
 struct drm_mode_object {
 	uint32_t id;
@@ -278,6 +279,7 @@ struct drm_crtc;
 struct drm_connector;
 struct drm_encoder;
 struct drm_pending_vblank_event;
+struct drm_plane;
 
 /**
  * drm_crtc_funcs - control CRTCs for a given device
@@ -536,6 +538,66 @@ struct drm_connector {
 };
 
 /**
+ * drm_plane_funcs - driver plane control functions
+ * @update_plane: update the plane configuration
+ * @disable_plane: shut down the plane
+ * @destroy: clean up plane resources
+ */
+struct drm_plane_funcs {
+	int (*update_plane)(struct drm_plane *plane,
+			    struct drm_crtc *crtc, struct drm_framebuffer *fb,
+			    int crtc_x, int crtc_y,
+			    unsigned int crtc_w, unsigned int crtc_h,
+			    uint32_t src_x, uint32_t src_y,
+			    uint32_t src_w, uint32_t src_h);
+	int (*disable_plane)(struct drm_plane *plane);
+	void (*destroy)(struct drm_plane *plane);
+};
+
+/**
+ * drm_plane - central DRM plane control structure
+ * @dev: DRM device this plane belongs to
+ * @kdev: kernel device
+ * @attr: kdev attributes
+ * @head: for list management
+ * @base: base mode object
+ * @possible_crtcs: pipes this plane can be bound to
+ * @format_types: array of formats supported by this plane
+ * @format_count: number of formats supported
+ * @crtc: currently bound CRTC
+ * @fb: currently bound fb
+ * @gamma_size: size of gamma table
+ * @gamma_store: gamma correction table
+ * @enabled: enabled flag
+ * @funcs: helper functions
+ * @helper_private: storage for drver layer
+ */
+struct drm_plane {
+	struct drm_device *dev;
+	struct device kdev;
+	struct device_attribute *attr;
+	struct list_head head;
+
+	struct drm_mode_object base;
+
+	uint32_t possible_crtcs;
+	uint32_t *format_types;
+	uint32_t format_count;
+
+	struct drm_crtc *crtc;
+	struct drm_framebuffer *fb;
+
+	/* CRTC gamma size for reporting to userspace */
+	uint32_t gamma_size;
+	uint16_t *gamma_store;
+
+	bool enabled;
+
+	const struct drm_plane_funcs *funcs;
+	void *helper_private;
+};
+
+/**
  * struct drm_mode_set
  *
  * Represents a single crtc the connectors that it drives with what mode
@@ -589,6 +651,8 @@ struct drm_mode_config {
 	struct list_head connector_list;
 	int num_encoder;
 	struct list_head encoder_list;
+	int num_plane;
+	struct list_head plane_list;
 
 	int num_crtc;
 	struct list_head crtc_list;
@@ -641,6 +705,7 @@ struct drm_mode_config {
 #define obj_to_fb(x) container_of(x, struct drm_framebuffer, base)
 #define obj_to_property(x) container_of(x, struct drm_property, base)
 #define obj_to_blob(x) container_of(x, struct drm_property_blob, base)
+#define obj_to_plane(x) container_of(x, struct drm_plane, base)
 
 
 extern void drm_crtc_init(struct drm_device *dev,
@@ -660,6 +725,13 @@ extern void drm_encoder_init(struct drm_device *dev,
 			     const struct drm_encoder_funcs *funcs,
 			     int encoder_type);
 
+extern void drm_plane_init(struct drm_device *dev,
+			   struct drm_plane *plane,
+			   unsigned long possible_crtcs,
+			   const struct drm_plane_funcs *funcs,
+			   uint32_t *formats, uint32_t format_count);
+extern void drm_plane_cleanup(struct drm_plane *plane);
+
 extern void drm_encoder_cleanup(struct drm_encoder *encoder);
 
 extern char *drm_get_connector_name(struct drm_connector *connector);
@@ -753,13 +825,18 @@ extern struct drm_mode_object *drm_mode_object_find(struct drm_device *dev,
 /* IOCTLs */
 extern int drm_mode_getresources(struct drm_device *dev,
 				 void *data, struct drm_file *file_priv);
-
+extern int drm_mode_getplane_res(struct drm_device *dev, void *data,
+				   struct drm_file *file_priv);
 extern int drm_mode_getcrtc(struct drm_device *dev,
 			    void *data, struct drm_file *file_priv);
 extern int drm_mode_getconnector(struct drm_device *dev,
 			      void *data, struct drm_file *file_priv);
 extern int drm_mode_setcrtc(struct drm_device *dev,
 			    void *data, struct drm_file *file_priv);
+extern int drm_mode_getplane(struct drm_device *dev,
+			       void *data, struct drm_file *file_priv);
+extern int drm_mode_setplane(struct drm_device *dev,
+			       void *data, struct drm_file *file_priv);
 extern int drm_mode_cursor_ioctl(struct drm_device *dev,
 				void *data, struct drm_file *file_priv);
 extern int drm_mode_addfb(struct drm_device *dev,
diff --git a/include/drm/drm_mode.h b/include/drm/drm_mode.h
index c4961ea..07711b0 100644
--- a/include/drm/drm_mode.h
+++ b/include/drm/drm_mode.h
@@ -120,6 +120,39 @@ struct drm_mode_crtc {
 	struct drm_mode_modeinfo mode;
 };
 
+/* Planes blend with or override other bits on the CRTC */
+struct drm_mode_set_plane {
+	__u32 plane_id;
+	__u32 crtc_id;
+	__u32 fb_id; /* fb object contains surface format type */
+
+	/* Signed dest location allows it to be partially off screen */
+	__s32 crtc_x, crtc_y;
+	__u32 crtc_w, crtc_h;
+
+	/* Source values are 16.16 fixed point */
+	__u32 src_x, src_y;
+	__u32 src_h, src_w;
+};
+
+struct drm_mode_get_plane {
+	__u64 format_type_ptr;
+	__u32 plane_id;
+
+	__u32 crtc_id;
+	__u32 fb_id;
+
+	__u32 possible_crtcs;
+	__u32 gamma_size;
+
+	__u32 count_format_types;
+};
+
+struct drm_mode_get_plane_res {
+	__u64 plane_id_ptr;
+	__u32 count_planes;
+};
+
 #define DRM_MODE_ENCODER_NONE	0
 #define DRM_MODE_ENCODER_DAC	1
 #define DRM_MODE_ENCODER_TMDS	2
-- 
1.7.4.1


[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

[-- Attachment #2: Type: text/plain, Size: 159 bytes --]

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 32+ messages in thread

* Re: [PATCH 2/5] drm: add an fb creation ioctl that takes a pixel format
  2011-11-02 20:03 ` [PATCH 2/5] drm: add an fb creation ioctl that takes a pixel format Jesse Barnes
@ 2011-11-03 18:22   ` Jesse Barnes
  2011-11-04  7:34   ` Joonyoung Shim
       [not found]   ` <CAAQKjZPhqYdMAUkbCbc68muPLN7azuVr0yod7hFC=i+MigwNhw@mail.gmail.com>
  2 siblings, 0 replies; 32+ messages in thread
From: Jesse Barnes @ 2011-11-03 18:22 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx, rob.clark


[-- Attachment #1.1: Type: text/plain, Size: 23527 bytes --]

On Wed,  2 Nov 2011 13:03:20 -0700
Jesse Barnes <jbarnes@virtuousgeek.org> wrote:

> To properly support the various plane formats supported by different
> hardware, the kernel must know the pixel format of a framebuffer object.
> So add a new ioctl taking a format argument corresponding to a fourcc
> name from videodev2.h.

Updated version.

-- 
Jesse Barnes, Intel Open Source Technology Center

From 38038767854cead6d65eaa80be79267a5fbbd097 Mon Sep 17 00:00:00 2001
From: Jesse Barnes <jbarnes@virtuousgeek.org>
Date: Tue, 7 Jun 2011 12:32:43 -0700
Subject: [PATCH 2/4] drm: add an fb creation ioctl that takes a pixel format

To properly support the various plane formats supported by different
hardware, the kernel must know the pixel format of a framebuffer object.
So add a new ioctl taking a format argument corresponding to a fourcc
name from videodev2.h.

Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
---
 drivers/gpu/drm/drm_crtc.c                |  105 ++++++++++++++++++++++++++++-
 drivers/gpu/drm/drm_crtc_helper.c         |   50 +++++++++++++-
 drivers/gpu/drm/drm_drv.c                 |    1 +
 drivers/gpu/drm/i915/intel_display.c      |   34 +++++-----
 drivers/gpu/drm/i915/intel_drv.h          |    2 +-
 drivers/gpu/drm/i915/intel_fb.c           |   11 ++--
 drivers/gpu/drm/nouveau/nouveau_display.c |    4 +-
 drivers/gpu/drm/radeon/radeon_display.c   |    4 +-
 drivers/gpu/drm/radeon/radeon_fb.c        |   18 +++--
 drivers/gpu/drm/radeon/radeon_mode.h      |    2 +-
 drivers/gpu/drm/vmwgfx/vmwgfx_kms.c       |    2 +-
 drivers/staging/gma500/framebuffer.c      |    2 +-
 include/drm/drm.h                         |    1 +
 include/drm/drm_crtc.h                    |    7 ++-
 include/drm/drm_crtc_helper.h             |    4 +-
 include/drm/drm_mode.h                    |   26 +++++++
 include/linux/videodev2.h                 |    1 +
 17 files changed, 231 insertions(+), 43 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index cea209a..869e177 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -1894,6 +1894,42 @@ out:
 	return ret;
 }
 
+/* Original addfb only supported RGB formats, so figure out which one */
+uint32_t drm_mode_legacy_fb_format(uint32_t bpp, uint32_t depth)
+{
+	uint32_t fmt;
+
+	switch (bpp) {
+	case 8:
+		fmt = V4L2_PIX_FMT_RGB332;
+		break;
+	case 16:
+		if (depth == 15)
+			fmt = V4L2_PIX_FMT_RGB555;
+		else
+			fmt = V4L2_PIX_FMT_RGB565;
+		break;
+	case 24:
+		fmt = V4L2_PIX_FMT_RGB24;
+		break;
+	case 32:
+		if (depth == 24)
+			fmt = V4L2_PIX_FMT_RGB24;
+		else if (depth == 30)
+			fmt = V4L2_PIX_FMT_INTC_RGB30;
+		else
+			fmt = V4L2_PIX_FMT_RGB32;
+		break;
+	default:
+		DRM_ERROR("bad bpp, assuming RGB24 pixel format\n");
+		fmt = V4L2_PIX_FMT_RGB24;
+		break;
+	}
+
+	return fmt;
+}
+EXPORT_SYMBOL(drm_mode_legacy_fb_format);
+
 /**
  * drm_mode_addfb - add an FB to the graphics configuration
  * @inode: inode from the ioctl
@@ -1914,7 +1950,74 @@ out:
 int drm_mode_addfb(struct drm_device *dev,
 		   void *data, struct drm_file *file_priv)
 {
-	struct drm_mode_fb_cmd *r = data;
+	struct drm_mode_fb_cmd *or = data;
+	struct drm_mode_fb_cmd2 r;
+	struct drm_mode_config *config = &dev->mode_config;
+	struct drm_framebuffer *fb;
+	int ret = 0;
+
+	/* Use new struct with format internally */
+	r.fb_id = or->fb_id;
+	r.width = or->width;
+	r.height = or->height;
+	r.pitches[0] = or->pitch;
+	r.pixel_format = drm_mode_legacy_fb_format(or->bpp, or->depth);
+	r.handle = or->handle;
+
+	if (!drm_core_check_feature(dev, DRIVER_MODESET))
+		return -EINVAL;
+
+	if ((config->min_width > r.width) || (r.width > config->max_width)) {
+		DRM_ERROR("mode new framebuffer width not within limits\n");
+		return -EINVAL;
+	}
+	if ((config->min_height > r.height) || (r.height > config->max_height)) {
+		DRM_ERROR("mode new framebuffer height not within limits\n");
+		return -EINVAL;
+	}
+
+	mutex_lock(&dev->mode_config.mutex);
+
+	/* TODO check buffer is sufficiently large */
+	/* TODO setup destructor callback */
+
+	fb = dev->mode_config.funcs->fb_create(dev, file_priv, &r);
+	if (IS_ERR(fb)) {
+		DRM_ERROR("could not create framebuffer\n");
+		ret = PTR_ERR(fb);
+		goto out;
+	}
+
+	or->fb_id = fb->base.id;
+	list_add(&fb->filp_head, &file_priv->fbs);
+	DRM_DEBUG_KMS("[FB:%d]\n", fb->base.id);
+
+out:
+	mutex_unlock(&dev->mode_config.mutex);
+	return ret;
+}
+
+/**
+ * drm_mode_addfb2 - add an FB to the graphics configuration
+ * @inode: inode from the ioctl
+ * @filp: file * from the ioctl
+ * @cmd: cmd from ioctl
+ * @arg: arg from ioctl
+ *
+ * LOCKING:
+ * Takes mode config lock.
+ *
+ * Add a new FB to the specified CRTC, given a user request with format.
+ *
+ * Called by the user via ioctl.
+ *
+ * RETURNS:
+ * Zero on success, errno on failure.
+ */
+int drm_mode_addfb2(struct drm_device *dev,
+		    void *data, struct drm_file *file_priv)
+{
+	struct drm_mode_fb_cmd2 *r = data;
 	struct drm_mode_config *config = &dev->mode_config;
 	struct drm_framebuffer *fb;
 	int ret = 0;
diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c
index f236644..8a05575 100644
--- a/drivers/gpu/drm/drm_crtc_helper.c
+++ b/drivers/gpu/drm/drm_crtc_helper.c
@@ -807,14 +807,56 @@ void drm_helper_connector_dpms(struct drm_connector *connector, int mode)
 }
 EXPORT_SYMBOL(drm_helper_connector_dpms);
 
+/*
+ * Just need to support RGB formats here for compat with code that doesn't
+ * use pixel formats directly yet.
+ */
+void drm_helper_get_fb_bpp_depth(uint32_t format, unsigned int *depth,
+				 int *bpp)
+{
+	switch (format) {
+	case V4L2_PIX_FMT_RGB332:
+		*depth = 8;
+		*bpp = 8;
+		break;
+	case V4L2_PIX_FMT_RGB555:
+		*depth = 15;
+		*bpp = 16;
+		break;
+	case V4L2_PIX_FMT_RGB565:
+		*depth = 16;
+		*bpp = 16;
+		break;
+	case V4L2_PIX_FMT_RGB24:
+		*depth = 24;
+		*bpp = 24;
+		break;
+	case V4L2_PIX_FMT_INTC_RGB30:
+		*depth = 30;
+		*bpp = 32;
+		break;
+	case V4L2_PIX_FMT_RGB32:
+		*depth = 32;
+		*bpp = 32;
+		break;
+	default:
+		DRM_DEBUG_KMS("unsupported pixel format\n");
+		*depth = 0;
+		*bpp = 0;
+		break;
+	}
+}
+EXPORT_SYMBOL(drm_helper_get_fb_bpp_depth);
+
 int drm_helper_mode_fill_fb_struct(struct drm_framebuffer *fb,
-				   struct drm_mode_fb_cmd *mode_cmd)
+				   struct drm_mode_fb_cmd2 *mode_cmd)
 {
 	fb->width = mode_cmd->width;
 	fb->height = mode_cmd->height;
-	fb->pitch = mode_cmd->pitch;
-	fb->bits_per_pixel = mode_cmd->bpp;
-	fb->depth = mode_cmd->depth;
+	fb->pitch = mode_cmd->pitches[0];
+	drm_helper_get_fb_bpp_depth(mode_cmd->pixel_format, &fb->depth,
+				    &fb->bits_per_pixel);
+	fb->pixel_format = mode_cmd->pixel_format;
 
 	return 0;
 }
diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
index d782bd1..6d87a59 100644
--- a/drivers/gpu/drm/drm_drv.c
+++ b/drivers/gpu/drm/drm_drv.c
@@ -152,6 +152,7 @@ static struct drm_ioctl_desc drm_ioctls[] = {
 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPROPBLOB, drm_mode_getblob_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETFB, drm_mode_getfb, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB, drm_mode_addfb, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB2, drm_mode_addfb2, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_RMFB, drm_mode_rmfb, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_PAGE_FLIP, drm_mode_page_flip_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_DIRTYFB, drm_mode_dirtyfb_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 9fa342e..b2061b0 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -6279,7 +6279,7 @@ static struct drm_display_mode load_detect_mode = {
 
 static struct drm_framebuffer *
 intel_framebuffer_create(struct drm_device *dev,
-			 struct drm_mode_fb_cmd *mode_cmd,
+			 struct drm_mode_fb_cmd2 *mode_cmd,
 			 struct drm_i915_gem_object *obj)
 {
 	struct intel_framebuffer *intel_fb;
@@ -6321,7 +6321,7 @@ intel_framebuffer_create_for_mode(struct drm_device *dev,
 				  int depth, int bpp)
 {
 	struct drm_i915_gem_object *obj;
-	struct drm_mode_fb_cmd mode_cmd;
+	struct drm_mode_fb_cmd2 mode_cmd;
 
 	obj = i915_gem_alloc_object(dev,
 				    intel_framebuffer_size_for_mode(mode, bpp));
@@ -6330,9 +6330,9 @@ intel_framebuffer_create_for_mode(struct drm_device *dev,
 
 	mode_cmd.width = mode->hdisplay;
 	mode_cmd.height = mode->vdisplay;
-	mode_cmd.depth = depth;
-	mode_cmd.bpp = bpp;
-	mode_cmd.pitch = intel_framebuffer_pitch_for_width(mode_cmd.width, bpp);
+	mode_cmd.pitches[0] = intel_framebuffer_pitch_for_width(mode_cmd.width,
+								bpp);
+	mode_cmd.pixel_format = 0;
 
 	return intel_framebuffer_create(dev, &mode_cmd, obj);
 }
@@ -7573,7 +7573,7 @@ static const struct drm_framebuffer_funcs intel_fb_funcs = {
 
 int intel_framebuffer_init(struct drm_device *dev,
 			   struct intel_framebuffer *intel_fb,
-			   struct drm_mode_fb_cmd *mode_cmd,
+			   struct drm_mode_fb_cmd2 *mode_cmd,
 			   struct drm_i915_gem_object *obj)
 {
 	int ret;
@@ -7584,18 +7584,20 @@ int intel_framebuffer_init(struct drm_device *dev,
 	if (mode_cmd->pitch & 63)
 		return -EINVAL;
 
-	switch (mode_cmd->bpp) {
-	case 8:
-	case 16:
-		/* Only pre-ILK can handle 5:5:5 */
-		if (mode_cmd->depth == 15 && !HAS_PCH_SPLIT(dev))
-			return -EINVAL;
+	switch (mode_cmd->pixel_format) {
+	case V4L2_PIX_FMT_RGB332:
+	case V4L2_PIX_FMT_RGB565:
+	case V4L2_PIX_FMT_RGB24:
+	case V4L2_PIX_FMT_INTC_RGB30:
+		/* RGB formats are common across chipsets */
 		break;
-
-	case 24:
-	case 32:
+	case V4L2_PIX_FMT_YUYV:
+	case V4L2_PIX_FMT_UYVY:
+	case V4L2_PIX_FMT_YVYU:
+	case V4L2_PIX_FMT_VYUY:
 		break;
 	default:
+		DRM_ERROR("unsupported pixel format\n");
 		return -EINVAL;
 	}
 
@@ -7613,7 +7615,7 @@ int intel_framebuffer_init(struct drm_device *dev,
 static struct drm_framebuffer *
 intel_user_framebuffer_create(struct drm_device *dev,
 			      struct drm_file *filp,
-			      struct drm_mode_fb_cmd *mode_cmd)
+			      struct drm_mode_fb_cmd2 *mode_cmd)
 {
 	struct drm_i915_gem_object *obj;
 
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index bd9a604..23c5622 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -359,7 +359,7 @@ extern int intel_pin_and_fence_fb_obj(struct drm_device *dev,
 
 extern int intel_framebuffer_init(struct drm_device *dev,
 				  struct intel_framebuffer *ifb,
-				  struct drm_mode_fb_cmd *mode_cmd,
+				  struct drm_mode_fb_cmd2 *mode_cmd,
 				  struct drm_i915_gem_object *obj);
 extern int intel_fbdev_init(struct drm_device *dev);
 extern void intel_fbdev_fini(struct drm_device *dev);
diff --git a/drivers/gpu/drm/i915/intel_fb.c b/drivers/gpu/drm/i915/intel_fb.c
index ec49bae..dc1db4f 100644
--- a/drivers/gpu/drm/i915/intel_fb.c
+++ b/drivers/gpu/drm/i915/intel_fb.c
@@ -65,7 +65,7 @@ static int intelfb_create(struct intel_fbdev *ifbdev,
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct fb_info *info;
 	struct drm_framebuffer *fb;
-	struct drm_mode_fb_cmd mode_cmd;
+	struct drm_mode_fb_cmd2 mode_cmd;
 	struct drm_i915_gem_object *obj;
 	struct device *device = &dev->pdev->dev;
 	int size, ret;
@@ -77,11 +77,12 @@ static int intelfb_create(struct intel_fbdev *ifbdev,
 	mode_cmd.width = sizes->surface_width;
 	mode_cmd.height = sizes->surface_height;
 
-	mode_cmd.bpp = sizes->surface_bpp;
-	mode_cmd.pitch = ALIGN(mode_cmd.width * ((mode_cmd.bpp + 7) / 8), 64);
-	mode_cmd.depth = sizes->surface_depth;
+	mode_cmd.pitches[0] = ALIGN(mode_cmd.width * ((sizes->surface_bpp + 7) /
+						      8), 64);
+	mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp,
+							  sizes->surface_depth);
 
-	size = mode_cmd.pitch * mode_cmd.height;
+	size = mode_cmd.pitches[0] * mode_cmd.height;
 	size = ALIGN(size, PAGE_SIZE);
 	obj = i915_gem_alloc_object(dev, size);
 	if (!obj) {
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c
index ddbabef..7a428a9 100644
--- a/drivers/gpu/drm/nouveau/nouveau_display.c
+++ b/drivers/gpu/drm/nouveau/nouveau_display.c
@@ -64,7 +64,7 @@ static const struct drm_framebuffer_funcs nouveau_framebuffer_funcs = {
 int
 nouveau_framebuffer_init(struct drm_device *dev,
 			 struct nouveau_framebuffer *nv_fb,
-			 struct drm_mode_fb_cmd *mode_cmd,
+			 struct drm_mode_fb_cmd2 *mode_cmd,
 			 struct nouveau_bo *nvbo)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
@@ -124,7 +124,7 @@ nouveau_framebuffer_init(struct drm_device *dev,
 static struct drm_framebuffer *
 nouveau_user_framebuffer_create(struct drm_device *dev,
 				struct drm_file *file_priv,
-				struct drm_mode_fb_cmd *mode_cmd)
+				struct drm_mode_fb_cmd2 *mode_cmd)
 {
 	struct nouveau_framebuffer *nouveau_fb;
 	struct drm_gem_object *gem;
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c
index 6adb3e5..6fde9c3 100644
--- a/drivers/gpu/drm/radeon/radeon_display.c
+++ b/drivers/gpu/drm/radeon/radeon_display.c
@@ -1113,7 +1113,7 @@ static const struct drm_framebuffer_funcs radeon_fb_funcs = {
 void
 radeon_framebuffer_init(struct drm_device *dev,
 			struct radeon_framebuffer *rfb,
-			struct drm_mode_fb_cmd *mode_cmd,
+			struct drm_mode_fb_cmd2 *mode_cmd,
 			struct drm_gem_object *obj)
 {
 	rfb->obj = obj;
@@ -1124,7 +1124,7 @@ radeon_framebuffer_init(struct drm_device *dev,
 static struct drm_framebuffer *
 radeon_user_framebuffer_create(struct drm_device *dev,
 			       struct drm_file *file_priv,
-			       struct drm_mode_fb_cmd *mode_cmd)
+			       struct drm_mode_fb_cmd2 *mode_cmd)
 {
 	struct drm_gem_object *obj;
 	struct radeon_framebuffer *radeon_fb;
diff --git a/drivers/gpu/drm/radeon/radeon_fb.c b/drivers/gpu/drm/radeon/radeon_fb.c
index 0b7b486..ea110ad 100644
--- a/drivers/gpu/drm/radeon/radeon_fb.c
+++ b/drivers/gpu/drm/radeon/radeon_fb.c
@@ -103,7 +103,7 @@ static void radeonfb_destroy_pinned_object(struct drm_gem_object *gobj)
 }
 
 static int radeonfb_create_pinned_object(struct radeon_fbdev *rfbdev,
-					 struct drm_mode_fb_cmd *mode_cmd,
+					 struct drm_mode_fb_cmd2 *mode_cmd,
 					 struct drm_gem_object **gobj_p)
 {
 	struct radeon_device *rdev = rfbdev->rdev;
@@ -114,13 +114,17 @@ static int radeonfb_create_pinned_object(struct radeon_fbdev *rfbdev,
 	int ret;
 	int aligned_size, size;
 	int height = mode_cmd->height;
+	u32 bpp, depth;
+
+	drm_helper_get_fb_bpp_depth(mode_cmd->pixel_format, &depth, &bpp);
 
 	/* need to align pitch with crtc limits */
-	mode_cmd->pitch = radeon_align_pitch(rdev, mode_cmd->width, mode_cmd->bpp, fb_tiled) * ((mode_cmd->bpp + 1) / 8);
+	mode_cmd->pitches[0] = radeon_align_pitch(rdev, mode_cmd->width, bpp,
+						  fb_tiled) * ((bpp + 1) / 8);
 
 	if (rdev->family >= CHIP_R600)
 		height = ALIGN(mode_cmd->height, 8);
-	size = mode_cmd->pitch * height;
+	size = mode_cmd->pitches[0] * height;
 	aligned_size = ALIGN(size, PAGE_SIZE);
 	ret = radeon_gem_object_create(rdev, aligned_size, 0,
 				       RADEON_GEM_DOMAIN_VRAM,
@@ -151,7 +155,7 @@ static int radeonfb_create_pinned_object(struct radeon_fbdev *rfbdev,
 	if (tiling_flags) {
 		ret = radeon_bo_set_tiling_flags(rbo,
 						 tiling_flags | RADEON_TILING_SURFACE,
-						 mode_cmd->pitch);
+						 mode_cmd->pitches[0]);
 		if (ret)
 			dev_err(rdev->dev, "FB failed to set tiling flags\n");
 	}
@@ -187,7 +191,7 @@ static int radeonfb_create(struct radeon_fbdev *rfbdev,
 	struct radeon_device *rdev = rfbdev->rdev;
 	struct fb_info *info;
 	struct drm_framebuffer *fb = NULL;
-	struct drm_mode_fb_cmd mode_cmd;
+	struct drm_mode_fb_cmd2 mode_cmd;
 	struct drm_gem_object *gobj = NULL;
 	struct radeon_bo *rbo = NULL;
 	struct device *device = &rdev->pdev->dev;
@@ -201,8 +205,8 @@ static int radeonfb_create(struct radeon_fbdev *rfbdev,
 	if ((sizes->surface_bpp == 24) && ASIC_IS_AVIVO(rdev))
 		sizes->surface_bpp = 32;
 
-	mode_cmd.bpp = sizes->surface_bpp;
-	mode_cmd.depth = sizes->surface_depth;
+	mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp,
+							  sizes->surface_depth);
 
 	ret = radeonfb_create_pinned_object(rfbdev, &mode_cmd, &gobj);
 	rbo = gem_to_radeon_bo(gobj);
diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h
index ed0178f..dd429a1 100644
--- a/drivers/gpu/drm/radeon/radeon_mode.h
+++ b/drivers/gpu/drm/radeon/radeon_mode.h
@@ -645,7 +645,7 @@ extern void radeon_crtc_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green
 				     u16 *blue, int regno);
 void radeon_framebuffer_init(struct drm_device *dev,
 			     struct radeon_framebuffer *rfb,
-			     struct drm_mode_fb_cmd *mode_cmd,
+			     struct drm_mode_fb_cmd2 *mode_cmd,
 			     struct drm_gem_object *obj);
 
 int radeonfb_remove(struct drm_device *dev, struct drm_framebuffer *fb);
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
index 8b14dfd..6719170 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
@@ -974,7 +974,7 @@ out_err1:
 
 static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev,
 						 struct drm_file *file_priv,
-						 struct drm_mode_fb_cmd *mode_cmd)
+						 struct drm_mode_fb_cmd2 *mode_cmd)
 {
 	struct vmw_private *dev_priv = vmw_priv(dev);
 	struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
diff --git a/drivers/staging/gma500/framebuffer.c b/drivers/staging/gma500/framebuffer.c
index 3f39a37..1e77229 100644
--- a/drivers/staging/gma500/framebuffer.c
+++ b/drivers/staging/gma500/framebuffer.c
@@ -546,7 +546,7 @@ out_err1:
  */
 static struct drm_framebuffer *psb_user_framebuffer_create
 			(struct drm_device *dev, struct drm_file *filp,
-			 struct drm_mode_fb_cmd *cmd)
+			 struct drm_mode_fb_cmd2 *cmd)
 {
 	struct gtt_range *r;
 	struct drm_gem_object *obj;
diff --git a/include/drm/drm.h b/include/drm/drm.h
index 2897967..49d94ed 100644
--- a/include/drm/drm.h
+++ b/include/drm/drm.h
@@ -717,6 +717,7 @@ struct drm_get_cap {
 #define DRM_IOCTL_MODE_GETPLANERESOURCES DRM_IOWR(0xB5, struct drm_mode_get_plane_res)
 #define DRM_IOCTL_MODE_GETPLANE	DRM_IOWR(0xB6, struct drm_mode_get_plane)
 #define DRM_IOCTL_MODE_SETPLANE	DRM_IOWR(0xB7, struct drm_mode_set_plane)
+#define DRM_IOCTL_MODE_ADDFB2		DRM_IOWR(0xB8, struct drm_mode_fb_cmd2)
 
 /**
  * Device specific ioctls should only be in their respective headers
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 8331dc6..1d09af1 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -29,6 +29,7 @@
 #include <linux/spinlock.h>
 #include <linux/types.h>
 #include <linux/idr.h>
+#include <linux/videodev2.h> /* for plane formats */
 
 #include <linux/fb.h>
 
@@ -246,6 +247,7 @@ struct drm_framebuffer {
 	unsigned int depth;
 	int bits_per_pixel;
 	int flags;
+	uint32_t pixel_format; /* fourcc format */
 	struct list_head filp_head;
 	/* if you are using the helper */
 	void *helper_private;
@@ -623,7 +625,7 @@ struct drm_mode_set {
  * struct drm_mode_config_funcs - configure CRTCs for a given screen layout
  */
 struct drm_mode_config_funcs {
-	struct drm_framebuffer *(*fb_create)(struct drm_device *dev, struct drm_file *file_priv, struct drm_mode_fb_cmd *mode_cmd);
+	struct drm_framebuffer *(*fb_create)(struct drm_device *dev, struct drm_file *file_priv, struct drm_mode_fb_cmd2 *mode_cmd);
 	void (*output_poll_changed)(struct drm_device *dev);
 };
 
@@ -841,6 +843,9 @@ extern int drm_mode_cursor_ioctl(struct drm_device *dev,
 				void *data, struct drm_file *file_priv);
 extern int drm_mode_addfb(struct drm_device *dev,
 			  void *data, struct drm_file *file_priv);
+extern int drm_mode_addfb2(struct drm_device *dev,
+			   void *data, struct drm_file *file_priv);
+extern uint32_t drm_mode_legacy_fb_format(uint32_t bpp, uint32_t depth);
 extern int drm_mode_rmfb(struct drm_device *dev,
 			 void *data, struct drm_file *file_priv);
 extern int drm_mode_getfb(struct drm_device *dev,
diff --git a/include/drm/drm_crtc_helper.h b/include/drm/drm_crtc_helper.h
index 73b0712..b4abb33 100644
--- a/include/drm/drm_crtc_helper.h
+++ b/include/drm/drm_crtc_helper.h
@@ -116,8 +116,10 @@ extern bool drm_helper_encoder_in_use(struct drm_encoder *encoder);
 
 extern void drm_helper_connector_dpms(struct drm_connector *connector, int mode);
 
+extern void drm_helper_get_fb_bpp_depth(uint32_t format, unsigned int *depth,
+					int *bpp);
 extern int drm_helper_mode_fill_fb_struct(struct drm_framebuffer *fb,
-					  struct drm_mode_fb_cmd *mode_cmd);
+					  struct drm_mode_fb_cmd2 *mode_cmd);
 
 static inline void drm_crtc_helper_add(struct drm_crtc *crtc,
 				       const struct drm_crtc_helper_funcs *funcs)
diff --git a/include/drm/drm_mode.h b/include/drm/drm_mode.h
index 07711b0..69f8ece 100644
--- a/include/drm/drm_mode.h
+++ b/include/drm/drm_mode.h
@@ -27,6 +27,8 @@
 #ifndef _DRM_MODE_H
 #define _DRM_MODE_H
 
+#include <linux/videodev2.h>
+
 #define DRM_DISPLAY_INFO_LEN	32
 #define DRM_CONNECTOR_NAME_LEN	32
 #define DRM_DISPLAY_MODE_LEN	32
@@ -262,6 +264,30 @@ struct drm_mode_fb_cmd {
 	__u32 handle;
 };
 
+struct drm_mode_fb_cmd2 {
+	__u32 fb_id;
+	__u32 width, height;
+	__u32 pixel_format; /* fourcc code from videodev2.h */
+
+	/*
+	 * In case of planar formats, this ioctl allows one
+	 * buffer object with offets and pitches per plane.
+	 * The pitch and offset order is dictated by the fourcc,
+	 * e.g. NV12 (http://fourcc.org/yuv.php#NV12) is described as:
+	 *
+	 *   YUV 4:2:0 image with a plane of 8 bit Y samples
+	 *   followed by an interleaved U/V plane containing
+	 *   8 bit 2x2 subsampled colour difference samples.
+	 *
+	 * So it would consist of Y as offset[0] and UV as
+	 * offeset[1].  Note that offset[0] will generally
+	 * be 0.
+	 */
+	__u32 handle;
+	__u32 pitches[4]; /* pitch for each plane */
+	__u32 offsets[4]; /* offset of each plane */
+};
+
 #define DRM_MODE_FB_DIRTY_ANNOTATE_COPY 0x01
 #define DRM_MODE_FB_DIRTY_ANNOTATE_FILL 0x02
 #define DRM_MODE_FB_DIRTY_FLAGS         0x03
diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
index fca24cc..6da4ab4 100644
--- a/include/linux/videodev2.h
+++ b/include/linux/videodev2.h
@@ -412,6 +412,7 @@ struct v4l2_pix_format {
 #define V4L2_PIX_FMT_KONICA420  v4l2_fourcc('K', 'O', 'N', 'I') /* YUV420 planar in blocks of 256 pixels */
 #define V4L2_PIX_FMT_JPGL	v4l2_fourcc('J', 'P', 'G', 'L') /* JPEG-Lite */
 #define V4L2_PIX_FMT_SE401      v4l2_fourcc('S', '4', '0', '1') /* se401 janggu compressed rgb */
+#define V4L2_PIX_FMT_INTC_RGB30	v4l2_fourcc('R', 'G', 'B', '0') /* RGB x:10:10:10 */
 
 /*
  *	F O R M A T   E N U M E R A T I O N
-- 
1.7.4.1


[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

[-- Attachment #2: Type: text/plain, Size: 159 bytes --]

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 32+ messages in thread

* Re: [PATCH 3/5] drm/i915: rename existing overlay support to "legacy"
  2011-11-02 20:03 ` [PATCH 3/5] drm/i915: rename existing overlay support to "legacy" Jesse Barnes
@ 2011-11-03 18:22   ` Jesse Barnes
  0 siblings, 0 replies; 32+ messages in thread
From: Jesse Barnes @ 2011-11-03 18:22 UTC (permalink / raw)
  Cc: intel-gfx, dri-devel, rob.clark


[-- Attachment #1.1: Type: text/plain, Size: 413 bytes --]

On Wed,  2 Nov 2011 13:03:21 -0700
Jesse Barnes <jbarnes@virtuousgeek.org> wrote:

> The old overlay block has all sorts of quirks and is very different than
> ILK+ video sprites.  So rename it to legacy to make that clear and clash
> less with core overlay support.

This one has been dropped.  I'm calling things _sprite in the intel
code now.

-- 
Jesse Barnes, Intel Open Source Technology Center

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

[-- Attachment #2: Type: text/plain, Size: 159 bytes --]

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH 4/5] drm/i915: add SNB and IVB video sprite support
  2011-11-02 20:03 ` [PATCH 4/5] drm/i915: add SNB and IVB video sprite support Jesse Barnes
@ 2011-11-03 18:22   ` Jesse Barnes
  2011-11-04  2:29   ` [Intel-gfx] " Lan, Hai
  1 sibling, 0 replies; 32+ messages in thread
From: Jesse Barnes @ 2011-11-03 18:22 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx, rob.clark


[-- Attachment #1.1: Type: text/plain, Size: 27884 bytes --]

On Wed,  2 Nov 2011 13:03:22 -0700
Jesse Barnes <jbarnes@virtuousgeek.org> wrote:

> The video sprites support various video surface formats natively and can
> handle scaling as well.  So add support for them using the new DRM core
> overlay support functions.
> 
> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
> ---

Updated with ->destroy and _sprite naming.

-- 
Jesse Barnes, Intel Open Source Technology Center

From 1a87b73677f35b7a31acdbc7ecf2b910f042c5ec Mon Sep 17 00:00:00 2001
From: Jesse Barnes <jbarnes@virtuousgeek.org>
Date: Fri, 22 Apr 2011 14:55:33 -0700
Subject: [PATCH 3/4] drm/i915: add SNB and IVB video sprite support

The video sprites support various video surface formats natively and can
handle scaling as well.  So add support for them using the new DRM core
sprite support functions.

Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
---
 drivers/gpu/drm/i915/Makefile        |    1 +
 drivers/gpu/drm/i915/i915_reg.h      |  123 ++++++++++
 drivers/gpu/drm/i915/intel_display.c |   31 ++-
 drivers/gpu/drm/i915/intel_drv.h     |   23 ++
 drivers/gpu/drm/i915/intel_fb.c      |    6 +
 drivers/gpu/drm/i915/intel_sprite.c  |  447 ++++++++++++++++++++++++++++++++++
 6 files changed, 620 insertions(+), 11 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/intel_sprite.c

diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index 0ae6a7c..808b255 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -28,6 +28,7 @@ i915-y := i915_drv.o i915_dma.o i915_irq.o i915_mem.o \
 	  intel_dvo.o \
 	  intel_ringbuffer.o \
 	  intel_overlay.o \
+	  intel_sprite.o \
 	  intel_opregion.o \
 	  dvo_ch7xxx.o \
 	  dvo_ch7017.o \
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 5a09416..b2270fa 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -2450,6 +2450,8 @@
 #define WM3_LP_ILK		0x45110
 #define  WM3_LP_EN		(1<<31)
 #define WM1S_LP_ILK		0x45120
+#define WM2S_LP_IVB		0x45124
+#define WM3S_LP_IVB		0x45128
 #define  WM1S_LP_EN		(1<<31)
 
 /* Memory latency timer register */
@@ -2666,6 +2668,127 @@
 #define _DSPBSURF		0x7119C
 #define _DSPBTILEOFF		0x711A4
 
+/* Sprite A control */
+#define _DVSACNTR		0x72180
+#define   DVS_ENABLE		(1<<31)
+#define   DVS_GAMMA_ENABLE	(1<<30)
+#define   DVS_PIXFORMAT_MASK	(3<<25)
+#define   DVS_FORMAT_YUV422	(0<<25)
+#define   DVS_FORMAT_RGBX101010	(1<<25)
+#define   DVS_FORMAT_RGBX888	(2<<25)
+#define   DVS_FORMAT_RGBX161616	(3<<25)
+#define   DVS_SOURCE_KEY	(1<<22)
+#define   DVS_RGB_ORDER_RGBX	(1<<20)
+#define   DVS_YUV_BYTE_ORDER_MASK (3<<16)
+#define   DVS_YUV_ORDER_YUYV	(0<<16)
+#define   DVS_YUV_ORDER_UYVY	(1<<16)
+#define   DVS_YUV_ORDER_YVYU	(2<<16)
+#define   DVS_YUV_ORDER_VYUY	(3<<16)
+#define   DVS_DEST_KEY		(1<<2)
+#define   DVS_TRICKLE_FEED_DISABLE (1<<14)
+#define   DVS_TILED		(1<<10)
+#define _DVSASTRIDE		0x72188
+#define _DVSAPOS		0x7218c
+#define _DVSASIZE		0x72190
+#define _DVSAKEYVAL		0x72194
+#define _DVSAKEYMSK		0x72198
+#define _DVSASURF		0x7219c
+#define _DVSAKEYMAXVAL		0x721a0
+#define _DVSATILEOFF		0x721a4
+#define _DVSASURFLIVE		0x721ac
+#define _DVSASCALE		0x72204
+#define   DVS_SCALE_ENABLE	(1<<31)
+#define   DVS_FILTER_MASK	(3<<29)
+#define   DVS_FILTER_MEDIUM	(0<<29)
+#define   DVS_FILTER_ENHANCING	(1<<29)
+#define   DVS_FILTER_SOFTENING	(2<<29)
+#define _DVSAGAMC		0x72300
+
+#define _DVSBCNTR		0x73180
+#define _DVSBSTRIDE		0x73188
+#define _DVSBPOS		0x7318c
+#define _DVSBSIZE		0x73190
+#define _DVSBKEYVAL		0x73194
+#define _DVSBKEYMSK		0x73198
+#define _DVSBSURF		0x7319c
+#define _DVSBKEYMAXVAL		0x731a0
+#define _DVSBTILEOFF		0x731a4
+#define _DVSBSURFLIVE		0x731ac
+#define _DVSBSCALE		0x73204
+#define _DVSBGAMC		0x73300
+
+#define DVSCNTR(pipe) _PIPE(pipe, _DVSACNTR, _DVSBCNTR)
+#define DVSSTRIDE(pipe) _PIPE(pipe, _DVSASTRIDE, _DVSBSTRIDE)
+#define DVSPOS(pipe) _PIPE(pipe, _DVSAPOS, _DVSBPOS)
+#define DVSSURF(pipe) _PIPE(pipe, _DVSASURF, _DVSBSURF)
+#define DVSSIZE(pipe) _PIPE(pipe, _DVSASIZE, _DVSBSIZE)
+#define DVSSCALE(pipe) _PIPE(pipe, _DVSASCALE, _DVSBSCALE)
+#define DVSTILEOFF(pipe) _PIPE(pipe, _DVSATILEOFF, _DVSBTILEOFF)
+
+#define _SPRA_CTL		0x70280
+#define   SPRITE_ENABLE			(1<<31)
+#define   SPRITE_GAMMA_ENABLE		(1<<30)
+#define   SPRITE_PIXFORMAT_MASK		(7<<25)
+#define   SPRITE_FORMAT_YUV422		(0<<25)
+#define   SPRITE_FORMAT_RGBX101010	(1<<25)
+#define   SPRITE_FORMAT_RGBX888		(2<<25)
+#define   SPRITE_FORMAT_RGBX161616	(3<<25)
+#define   SPRITE_FORMAT_YUV444		(4<<25)
+#define   SPRITE_FORMAT_XBGR101010	(5<<25)
+#define   SPRITE_CSC_ENABLE		(1<<24)
+#define   SPRITE_SOURCE_KEY		(1<<22)
+#define   SPRITE_RGB_ORDER_RGBX		(1<<20) /* only for 888 and 161616 */
+#define   SPRITE_YUV_TO_RGB_CSC_DISABLE	(1<<19)
+#define   SPRITE_YUV_CSC_FORMAT_BT709	(1<<18) /* 0 is BT601 */
+#define   SPRITE_YUV_BYTE_ORDER_MASK	(3<<16)
+#define   SPRITE_YUV_ORDER_YUYV		(0<<16)
+#define   SPRITE_YUV_ORDER_UYVY		(1<<16)
+#define   SPRITE_YUV_ORDER_YVYU		(2<<16)
+#define   SPRITE_YUV_ORDER_VYUY		(3<<16)
+#define   SPRITE_TRICKLE_FEED_DISABLE	(1<<14)
+#define   SPRITE_INT_GAMMA_ENABLE	(1<<13)
+#define   SPRITE_TILED			(1<<10)
+#define   SPRITE_DEST_KEY		(1<<2)
+#define _SPRA_STRIDE		0x70288
+#define _SPRA_POS		0x7028c
+#define _SPRA_SIZE		0x70290
+#define _SPRA_KEYVAL		0x70294
+#define _SPRA_KEYMSK		0x70298
+#define _SPRA_SURF		0x7029c
+#define _SPRA_KEYMAX		0x702a0
+#define _SPRA_TILEOFF		0x702a4
+#define _SPRA_SCALE		0x70304
+#define   SPRITE_SCALE_ENABLE	(1<<31)
+#define   SPRITE_FILTER_MASK	(3<<29)
+#define   SPRITE_FILTER_MEDIUM	(0<<29)
+#define   SPRITE_FILTER_ENHANCING	(1<<29)
+#define   SPRITE_FILTER_SOFTENING	(2<<29)
+#define _SPRA_GAMC		0x70400
+
+#define _SPRB_CTL		0x71280
+#define _SPRB_STRIDE		0x71288
+#define _SPRB_POS		0x7128c
+#define _SPRB_SIZE		0x71290
+#define _SPRB_KEYVAL		0x71294
+#define _SPRB_KEYMSK		0x71298
+#define _SPRB_SURF		0x7129c
+#define _SPRB_KEYMAX		0x712a0
+#define _SPRB_TILEOFF		0x712a4
+#define _SPRB_SCALE		0x71304
+#define _SPRB_GAMC		0x71400
+
+#define SPRCTL(pipe) _PIPE(pipe, _SPRA_CTL, _SPRB_CTL)
+#define SPRSTRIDE(pipe) _PIPE(pipe, _SPRA_STRIDE, _SPRB_STRIDE)
+#define SPRPOS(pipe) _PIPE(pipe, _SPRA_POS, _SPRB_POS)
+#define SPRSIZE(pipe) _PIPE(pipe, _SPRA_SIZE, _SPRB_SIZE)
+#define SPRKEYVAL(pipe) _PIPE(pipe, _SPRA_KEYVAL, _SPRB_KEYVAL)
+#define SPRKEYMSK(pipe) _PIPE(pipe, _SPRA_KEYMSK, _SPRB_KEYMSK)
+#define SPRSURF(pipe) _PIPE(pipe, _SPRA_SURF, _SPRB_SURF)
+#define SPRKEYMAX(pipe) _PIPE(pipe, _SPRA_KEYMAX, _SPRB_KEYMAX)
+#define SPRTILEOFF(pipe) _PIPE(pipe, _SPRA_TILEOFF, _SPRB_TILEOFF)
+#define SPRSCALE(pipe) _PIPE(pipe, _SPRA_SCALE, _SPRB_SCALE)
+#define SPRGAMC(pipe) _PIPE(pipe, _SPRA_GAMC, _SPRB_GAMC)
+
 /* VBIOS regs */
 #define VGACNTRL		0x71400
 # define VGA_DISP_DISABLE			(1 << 31)
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index b2061b0..09228dd 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -915,8 +915,8 @@ static void assert_panel_unlocked(struct drm_i915_private *dev_priv,
 	     pipe_name(pipe));
 }
 
-static void assert_pipe(struct drm_i915_private *dev_priv,
-			enum pipe pipe, bool state)
+void assert_pipe(struct drm_i915_private *dev_priv,
+		 enum pipe pipe, bool state)
 {
 	int reg;
 	u32 val;
@@ -929,8 +929,6 @@ static void assert_pipe(struct drm_i915_private *dev_priv,
 	     "pipe %c assertion failure (expected %s, current %s)\n",
 	     pipe_name(pipe), state_string(state), state_string(cur_state));
 }
-#define assert_pipe_enabled(d, p) assert_pipe(d, p, true)
-#define assert_pipe_disabled(d, p) assert_pipe(d, p, false)
 
 static void assert_plane_enabled(struct drm_i915_private *dev_priv,
 				 enum plane plane)
@@ -4439,7 +4437,8 @@ static void ironlake_update_wm(struct drm_device *dev)
 			    ILK_LP0_CURSOR_LATENCY,
 			    &plane_wm, &cursor_wm)) {
 		I915_WRITE(WM0_PIPEA_ILK,
-			   (plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm);
+			   (plane_wm << WM0_PIPE_PLANE_SHIFT) |
+			   (plane_wm << WM0_PIPE_SPRITE_SHIFT) | cursor_wm);
 		DRM_DEBUG_KMS("FIFO watermarks For pipe A -"
 			      " plane %d, " "cursor: %d\n",
 			      plane_wm, cursor_wm);
@@ -4453,7 +4452,8 @@ static void ironlake_update_wm(struct drm_device *dev)
 			    ILK_LP0_CURSOR_LATENCY,
 			    &plane_wm, &cursor_wm)) {
 		I915_WRITE(WM0_PIPEB_ILK,
-			   (plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm);
+			   (plane_wm << WM0_PIPE_PLANE_SHIFT) |
+			   (plane_wm << WM0_PIPE_SPRITE_SHIFT) | cursor_wm);
 		DRM_DEBUG_KMS("FIFO watermarks For pipe B -"
 			      " plane %d, cursor: %d\n",
 			      plane_wm, cursor_wm);
@@ -4521,7 +4521,8 @@ static void sandybridge_update_wm(struct drm_device *dev)
 			    &sandybridge_cursor_wm_info, latency,
 			    &plane_wm, &cursor_wm)) {
 		I915_WRITE(WM0_PIPEA_ILK,
-			   (plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm);
+			   (plane_wm << WM0_PIPE_PLANE_SHIFT) |
+			   (plane_wm << WM0_PIPE_SPRITE_SHIFT) | cursor_wm);
 		DRM_DEBUG_KMS("FIFO watermarks For pipe A -"
 			      " plane %d, " "cursor: %d\n",
 			      plane_wm, cursor_wm);
@@ -4533,7 +4534,8 @@ static void sandybridge_update_wm(struct drm_device *dev)
 			    &sandybridge_cursor_wm_info, latency,
 			    &plane_wm, &cursor_wm)) {
 		I915_WRITE(WM0_PIPEB_ILK,
-			   (plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm);
+			   (plane_wm << WM0_PIPE_PLANE_SHIFT) |
+			   (plane_wm << WM0_PIPE_SPRITE_SHIFT) | cursor_wm);
 		DRM_DEBUG_KMS("FIFO watermarks For pipe B -"
 			      " plane %d, cursor: %d\n",
 			      plane_wm, cursor_wm);
@@ -4547,7 +4549,8 @@ static void sandybridge_update_wm(struct drm_device *dev)
 			    &sandybridge_cursor_wm_info, latency,
 			    &plane_wm, &cursor_wm)) {
 		I915_WRITE(WM0_PIPEC_IVB,
-			   (plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm);
+			   (plane_wm << WM0_PIPE_PLANE_SHIFT) |
+			   (plane_wm << WM0_PIPE_SPRITE_SHIFT) | cursor_wm);
 		DRM_DEBUG_KMS("FIFO watermarks For pipe C -"
 			      " plane %d, cursor: %d\n",
 			      plane_wm, cursor_wm);
@@ -7581,7 +7584,7 @@ int intel_framebuffer_init(struct drm_device *dev,
 	if (obj->tiling_mode == I915_TILING_Y)
 		return -EINVAL;
 
-	if (mode_cmd->pitch & 63)
+	if (mode_cmd->pitches[0] & 63)
 		return -EINVAL;
 
 	switch (mode_cmd->pixel_format) {
@@ -8693,7 +8696,7 @@ static void i915_disable_vga(struct drm_device *dev)
 void intel_modeset_init(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	int i;
+	int i, ret;
 
 	drm_mode_config_init(dev);
 
@@ -8723,6 +8726,12 @@ void intel_modeset_init(struct drm_device *dev)
 
 	for (i = 0; i < dev_priv->num_pipe; i++) {
 		intel_crtc_init(dev, i);
+		if (HAS_PCH_SPLIT(dev)) {
+			ret = intel_plane_init(dev, i);
+			if (ret)
+				DRM_ERROR("plane %d init failed: %d\n",
+					  i, ret);
+		}
 	}
 
 	/* Just disable it once at startup */
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 23c5622..785bae7 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -176,10 +176,27 @@ struct intel_crtc {
 	bool use_pll_a;
 };
 
+struct intel_plane {
+	struct drm_plane base;
+	enum pipe pipe;
+	struct drm_i915_gem_object *obj;
+	bool primary_disabled;
+	int max_downscale;
+	u32 lut_r[1024], lut_g[1024], lut_b[1024];
+	void (*update_plane)(struct drm_plane *plane,
+			     struct drm_framebuffer *fb, unsigned long start,
+			     int crtc_x, int crtc_y,
+			     unsigned int crtc_w, unsigned int crtc_h,
+			     uint32_t x, uint32_t y,
+			     uint32_t src_w, uint32_t src_h);
+	void (*disable_plane)(struct drm_plane *plane);
+};
+
 #define to_intel_crtc(x) container_of(x, struct intel_crtc, base)
 #define to_intel_connector(x) container_of(x, struct intel_connector, base)
 #define to_intel_encoder(x) container_of(x, struct intel_encoder, base)
 #define to_intel_framebuffer(x) container_of(x, struct intel_framebuffer, base)
+#define to_intel_plane(x) container_of(x, struct intel_plane, base)
 
 #define DIP_HEADER_SIZE	5
 
@@ -289,6 +306,7 @@ intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode,
 extern bool intel_dpd_is_edp(struct drm_device *dev);
 extern void intel_edp_link_config(struct intel_encoder *, int *, int *);
 extern bool intel_encoder_is_pch_edp(struct drm_encoder *encoder);
+extern int intel_plane_init(struct drm_device *dev, enum pipe pipe);
 
 /* intel_panel.c */
 extern void intel_fixed_panel_mode(struct drm_display_mode *fixed_mode,
@@ -379,6 +397,11 @@ extern int intel_overlay_attrs(struct drm_device *dev, void *data,
 extern void intel_fb_output_poll_changed(struct drm_device *dev);
 extern void intel_fb_restore_mode(struct drm_device *dev);
 
+extern void assert_pipe(struct drm_i915_private *dev_priv, enum pipe pipe,
+			bool state);
+#define assert_pipe_enabled(d, p) assert_pipe(d, p, true)
+#define assert_pipe_disabled(d, p) assert_pipe(d, p, false)
+
 extern void intel_init_clock_gating(struct drm_device *dev);
 extern void intel_write_eld(struct drm_encoder *encoder,
 			    struct drm_display_mode *mode);
diff --git a/drivers/gpu/drm/i915/intel_fb.c b/drivers/gpu/drm/i915/intel_fb.c
index dc1db4f..068b086 100644
--- a/drivers/gpu/drm/i915/intel_fb.c
+++ b/drivers/gpu/drm/i915/intel_fb.c
@@ -270,8 +270,14 @@ void intel_fb_restore_mode(struct drm_device *dev)
 {
 	int ret;
 	drm_i915_private_t *dev_priv = dev->dev_private;
+	struct drm_mode_config *config = &dev->mode_config;
+	struct drm_plane *plane;
 
 	ret = drm_fb_helper_restore_fbdev_mode(&dev_priv->fbdev->helper);
 	if (ret)
 		DRM_DEBUG("failed to restore crtc mode\n");
+
+	/* Be sure to shut off any planes that may be active */
+	list_for_each_entry(plane, &config->plane_list, head)
+		plane->funcs->disable_plane(plane);
 }
diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
new file mode 100644
index 0000000..ca0da52
--- /dev/null
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -0,0 +1,447 @@
+/*
+ * Copyright © 2011 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ *   Jesse Barnes <jbarnes@virtuousgeek.org>
+ *
+ * New plane/sprite handling.
+ *
+ * The older chips had a separate interface for programming plane related
+ * registers; newer ones are much simpler and we can use the new DRM plane
+ * support.
+ */
+#include "drmP.h"
+#include "drm_crtc.h"
+#include "intel_drv.h"
+#include "i915_drm.h"
+#include "i915_drv.h"
+
+/*
+ * Note on refcounting:
+ * When the user creates an fb for the GEM object to be used for the plane,
+ * a ref is taken on the object.  However, if the application exits before
+ * disabling the plane, the DRM close handling will free all the fbs and
+ * unless we take a ref on the object, it will be destroyed before the
+ * plane disable hook is called, causing obvious trouble with our efforts
+ * to look up and unpin the object.  So we take a ref after we move the
+ * object to the display plane so it won't be destroyed until our disable
+ * hook is called and we drop our private reference.
+ */
+
+static void
+ivb_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb,
+		 unsigned long start, int crtc_x, int crtc_y,
+		 unsigned int crtc_w, unsigned int crtc_h,
+		 uint32_t x, uint32_t y,
+		 uint32_t src_w, uint32_t src_h)
+{
+	struct drm_device *dev = plane->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_plane *intel_plane = to_intel_plane(plane);
+	int pipe = intel_plane->pipe;
+	u32 sprctl, sprscale = 0;
+	u32 reg = SPRCTL(pipe);
+
+	sprctl = I915_READ(reg);
+
+	/* Mask out pixel format bits in case we change it */
+	sprctl &= ~(SPRITE_DEST_KEY | SPRITE_SOURCE_KEY);
+	sprctl &= ~SPRITE_PIXFORMAT_MASK;
+	sprctl &= ~SPRITE_RGB_ORDER_RGBX;
+	sprctl &= ~SPRITE_YUV_BYTE_ORDER_MASK;
+
+	switch (fb->pixel_format) {
+	case V4L2_PIX_FMT_BGR32:
+		sprctl |= SPRITE_FORMAT_RGBX888;
+		break;
+	case V4L2_PIX_FMT_RGB32:
+		sprctl |= SPRITE_FORMAT_RGBX888 | SPRITE_RGB_ORDER_RGBX;
+		break;
+	case V4L2_PIX_FMT_YUYV:
+		sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YUYV;
+		break;
+	case V4L2_PIX_FMT_YVYU:
+		sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YVYU;
+		break;
+	case V4L2_PIX_FMT_UYVY:
+		sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_UYVY;
+		break;
+	case V4L2_PIX_FMT_VYUY:
+		sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_VYUY;
+		break;
+	default:
+		DRM_DEBUG_DRIVER("bad pixel format, assuming RGBX888\n");
+		sprctl |= DVS_FORMAT_RGBX888;
+		break;
+	}
+
+	sprctl |= SPRITE_TILED;
+
+	/* must disable */
+	sprctl |= SPRITE_TRICKLE_FEED_DISABLE;
+	sprctl |= SPRITE_ENABLE;
+
+	/* Sizes are 0 based */
+	src_w--;
+	src_h--;
+	crtc_w--;
+	crtc_h--;
+
+	/* Adjust watermarks as needed */
+	I915_WRITE(WM1S_LP_ILK, 0x100);
+	I915_WRITE(WM2S_LP_IVB, 0x100);
+	I915_WRITE(WM3S_LP_IVB, 0x100);
+
+	if (crtc_w != src_w || crtc_h != src_h)
+		sprscale = SPRITE_SCALE_ENABLE | (src_h << 16) | src_w;
+
+	I915_WRITE(SPRSTRIDE(pipe), fb->pitch);
+	I915_WRITE(SPRPOS(pipe), (crtc_y << 16) | crtc_x);
+	I915_WRITE(SPRTILEOFF(pipe), (y << 16) | x);
+	I915_WRITE(SPRSIZE(pipe), (crtc_h << 16) | crtc_w);
+	I915_WRITE(SPRSCALE(pipe), sprscale);
+	I915_WRITE(reg, sprctl);
+	I915_WRITE(SPRSURF(pipe), start);
+	POSTING_READ(SPRSURF(pipe));
+}
+
+static void
+ivb_disable_plane(struct drm_plane *plane)
+{
+	struct drm_device *dev = plane->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_plane *intel_plane = to_intel_plane(plane);
+	int pipe = intel_plane->pipe;
+
+	I915_WRITE(SPRCTL(pipe), I915_READ(SPRCTL(pipe)) & ~SPRITE_ENABLE);
+	I915_WRITE(SPRSCALE(pipe), 0);
+	I915_WRITE(SPRSURF(pipe), 0);
+	POSTING_READ(SPRSURF(pipe));
+	intel_wait_for_vblank(dev, pipe);
+}
+
+static void
+snb_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb,
+		 unsigned long start, int crtc_x, int crtc_y,
+		 unsigned int crtc_w, unsigned int crtc_h,
+		 uint32_t x, uint32_t y,
+		 uint32_t src_w, uint32_t src_h)
+{
+	struct drm_device *dev = plane->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_plane *intel_plane = to_intel_plane(plane);
+	int pipe = intel_plane->pipe;
+	u32 dvscntr, dvsscale = 0;
+	u32 reg = DVSCNTR(pipe);
+
+	dvscntr = I915_READ(reg);
+
+	/* Mask out pixel format bits in case we change it */
+	dvscntr &= ~(DVS_DEST_KEY | DVS_SOURCE_KEY);
+	dvscntr &= ~DVS_PIXFORMAT_MASK;
+	dvscntr &= ~DVS_RGB_ORDER_RGBX;
+	dvscntr &= ~DVS_YUV_BYTE_ORDER_MASK;
+
+	switch (fb->pixel_format) {
+	case V4L2_PIX_FMT_BGR32:
+		dvscntr |= DVS_FORMAT_RGBX888;
+		break;
+	case V4L2_PIX_FMT_RGB32:
+		dvscntr |= DVS_FORMAT_RGBX888 | DVS_RGB_ORDER_RGBX;
+		break;
+	case V4L2_PIX_FMT_YUYV:
+		dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YUYV;
+		break;
+	case V4L2_PIX_FMT_YVYU:
+		dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YVYU;
+		break;
+	case V4L2_PIX_FMT_UYVY:
+		dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_UYVY;
+		break;
+	case V4L2_PIX_FMT_VYUY:
+		dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_VYUY;
+		break;
+	default:
+		DRM_DEBUG_DRIVER("bad pixel format, assuming RGBX888\n");
+		dvscntr |= DVS_FORMAT_RGBX888;
+		break;
+	}
+
+	dvscntr |= DVS_TILED;
+
+	/* must disable */
+	dvscntr |= DVS_TRICKLE_FEED_DISABLE;
+	dvscntr |= DVS_ENABLE;
+
+	/* Sizes are 0 based */
+	src_w--;
+	src_h--;
+	crtc_w--;
+	crtc_h--;
+
+	if (crtc_w != src_w || crtc_h != src_h)
+		dvsscale = DVS_SCALE_ENABLE | (src_h << 16) | src_w;
+
+	I915_WRITE(DVSSTRIDE(pipe), fb->pitch);
+	I915_WRITE(DVSPOS(pipe), (crtc_y << 16) | crtc_x);
+	I915_WRITE(DVSTILEOFF(pipe), (y << 16) | x);
+	I915_WRITE(DVSSIZE(pipe), (crtc_h << 16) | crtc_w);
+	I915_WRITE(DVSSCALE(pipe), dvsscale);
+	I915_WRITE(reg, dvscntr);
+	I915_WRITE(DVSSURF(pipe), start);
+	POSTING_READ(DVSSURF(pipe));
+}
+
+static void
+snb_disable_plane(struct drm_plane *plane)
+{
+	struct drm_device *dev = plane->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_plane *intel_plane = to_intel_plane(plane);
+	int pipe = intel_plane->pipe;
+
+	I915_WRITE(DVSCNTR(pipe), I915_READ(DVSCNTR(pipe)) & ~DVS_ENABLE);
+	I915_WRITE(DVSSCALE(pipe), 0);
+	I915_WRITE(DVSSURF(pipe), 0);
+	POSTING_READ(DVSSURF(pipe));
+	intel_wait_for_vblank(dev, pipe);
+}
+
+static int
+intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
+		   struct drm_framebuffer *fb, int crtc_x, int crtc_y,
+		   unsigned int crtc_w, unsigned int crtc_h,
+		   uint32_t src_x, uint32_t src_y,
+		   uint32_t src_w, uint32_t src_h)
+{
+	struct drm_device *dev = plane->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	struct intel_plane *intel_plane = to_intel_plane(plane);
+	struct intel_framebuffer *intel_fb;
+	struct drm_i915_gem_object *obj, *old_obj;
+	int pipe = intel_plane->pipe;
+	unsigned long start;
+	int ret = 0;
+	int x = src_x >> 16, y = src_y >> 16;
+	int primary_w = crtc->mode.hdisplay, primary_h = crtc->mode.vdisplay;
+	bool disable_primary = false;
+
+	intel_fb = to_intel_framebuffer(fb);
+	obj = intel_fb->obj;
+
+	old_obj = intel_plane->obj;
+
+	/* Pipe must be running... */
+	if (!(I915_READ(PIPECONF(pipe)) & PIPECONF_ENABLE))
+		return -EINVAL;
+
+	if (crtc_x >= primary_w || crtc_y >= primary_h)
+		return -EINVAL;
+
+	/* Don't modify another pipe's plane */
+	if (intel_plane->pipe != intel_crtc->pipe)
+		return -EINVAL;
+
+	/*
+	 * Clamp the width & height into the visible area.  Note we don't
+	 * try to scale the source if part of the visible region is offscreen.
+	 * The caller must handle that by adjusting source offset and size.
+	 */
+	if (crtc_x < 0) {
+		crtc_w += crtc_x;
+		crtc_x = 0;
+	}
+	if (crtc_x + crtc_w > primary_w)
+		crtc_w = primary_w - crtc_x;
+
+	if (crtc_y < 0) {
+		crtc_h += crtc_y;
+		crtc_y = 0;
+	}
+	if (crtc_y + crtc_h > primary_h)
+		crtc_h = primary_h - crtc_y;
+
+	/*
+	 * We can take a larger source and scale it down, but
+	 * only so much...  16x is the max on SNB.
+	 */
+	if (((src_w * src_h) / (crtc_w * crtc_h)) > intel_plane->max_downscale)
+		return -EINVAL;
+
+	/*
+	 * If the sprite is completely covering the primary plane,
+	 * we can disable the primary and save power.
+	 */
+	if ((crtc_x == 0) && (crtc_y == 0) &&
+	    (crtc_w == primary_w) && (crtc_h == primary_h))
+		disable_primary = true;
+
+	mutex_lock(&dev->struct_mutex);
+
+	if (obj->tiling_mode != I915_TILING_X) {
+		DRM_ERROR("plane surfaces must be X tiled\n");
+		ret = -EINVAL;
+		goto out_unlock;
+	}
+
+	ret = intel_pin_and_fence_fb_obj(dev, obj, NULL);
+	if (ret) {
+		DRM_ERROR("failed to pin object\n");
+		goto out_unlock;
+	}
+
+	drm_gem_object_reference(&obj->base);
+
+	intel_plane->obj = obj;
+
+	start = obj->gtt_offset;
+
+	/*
+	 * Be sure to re-enable the primary before the sprite is no longer
+	 * covering it fully.
+	 */
+	if (!disable_primary && intel_plane->primary_disabled) {
+		//dev_priv->display.enable_primary(dev, crtc);
+		intel_plane->primary_disabled = false;
+	}
+
+	intel_plane->update_plane(plane, fb, start, crtc_x, crtc_y,
+				  crtc_w, crtc_h, x, y, src_w, src_h);
+
+	if (disable_primary) {
+		//dev_priv->display.disable_primary(dev, crtc);
+		intel_plane->primary_disabled = true;
+	}
+
+	/* Unpin old obj after new one is active to avoid ugliness */
+	if (old_obj) {
+		/*
+		 * It's fairly common to simply update the position of
+		 * an existing object.  In that case, we don't need to
+		 * wait for vblank to avoid ugliness, we only need to
+		 * do the pin & ref bookkeeping.
+		 */
+		if (old_obj != obj)
+			intel_wait_for_vblank(dev, to_intel_crtc(crtc)->pipe);
+		i915_gem_object_unpin(old_obj);
+		drm_gem_object_unreference(&old_obj->base);
+	}
+
+out_unlock:
+	mutex_unlock(&dev->struct_mutex);
+
+	return ret;
+}
+
+static int
+intel_disable_plane(struct drm_plane *plane)
+{
+	struct drm_device *dev = plane->dev;
+	struct intel_plane *intel_plane = to_intel_plane(plane);
+	int ret = 0;
+
+	mutex_lock(&dev->struct_mutex);
+
+	if (intel_plane->primary_disabled) {
+		//dev_priv->display.enable_primary(dev, crtc);
+		intel_plane->primary_disabled = false;
+	}
+
+	intel_plane->disable_plane(plane);
+
+	if (!intel_plane->obj)
+		goto out_unlock;
+
+	ret = i915_gem_object_finish_gpu(intel_plane->obj);
+	if (ret)
+		goto out_unlock;
+
+	i915_gem_object_unpin(intel_plane->obj);
+
+	drm_gem_object_unreference(&intel_plane->obj->base);
+
+out_unlock:
+	intel_plane->obj = NULL;
+
+	mutex_unlock(&dev->struct_mutex);
+
+	return ret;
+}
+
+static void intel_destroy_plane(struct drm_plane *plane)
+{
+	struct intel_plane *intel_plane = to_intel_plane(plane);
+	intel_disable_plane(plane);
+	drm_plane_cleanup(plane);
+	kfree(intel_plane);
+}
+
+static const struct drm_plane_funcs intel_plane_funcs = {
+	.update_plane = intel_update_plane,
+	.disable_plane = intel_disable_plane,
+	.destroy = intel_destroy_plane,
+};
+
+static uint32_t snb_plane_formats[] = {
+	V4L2_PIX_FMT_BGR32,
+	V4L2_PIX_FMT_RGB32,
+	V4L2_PIX_FMT_YUYV,
+	V4L2_PIX_FMT_YVYU,
+	V4L2_PIX_FMT_UYVY,
+	V4L2_PIX_FMT_VYUY,
+};
+
+int
+intel_plane_init(struct drm_device *dev, enum pipe pipe)
+{
+	struct intel_plane *intel_plane;
+	unsigned long possible_crtcs;
+
+	if (!(IS_GEN6(dev) || IS_GEN7(dev))) {
+		DRM_ERROR("new plane code only for SNB+\n");
+		return -ENODEV;
+	}
+
+	intel_plane = kzalloc(sizeof(struct intel_plane), GFP_KERNEL);
+	if (!intel_plane)
+		return -ENOMEM;
+
+	if (IS_GEN6(dev)) {
+		intel_plane->max_downscale = 16;
+		intel_plane->update_plane = snb_update_plane;
+		intel_plane->disable_plane = snb_disable_plane;
+	} 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->pipe = pipe;
+	possible_crtcs = (1 << pipe);
+	drm_plane_init(dev, &intel_plane->base, possible_crtcs,
+		       &intel_plane_funcs, snb_plane_formats,
+		       ARRAY_SIZE(snb_plane_formats));
+
+	return 0;
+}
+
-- 
1.7.4.1


[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

[-- Attachment #2: Type: text/plain, Size: 159 bytes --]

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 32+ messages in thread

* Re: [PATCH 5/5] drm/i915: add destination color key support
  2011-11-02 20:03 ` [PATCH 5/5] drm/i915: add destination color key support Jesse Barnes
@ 2011-11-03 18:23   ` Jesse Barnes
  0 siblings, 0 replies; 32+ messages in thread
From: Jesse Barnes @ 2011-11-03 18:23 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx, rob.clark


[-- Attachment #1.1: Type: text/plain, Size: 7135 bytes --]

On Wed,  2 Nov 2011 13:03:23 -0700
Jesse Barnes <jbarnes@virtuousgeek.org> wrote:

> 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.
> 
> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
> ---

Updated with changed context due to other changes.

-- 
Jesse Barnes, Intel Open Source Technology Center

From 00904140838effe4511213c89e887adee5937bd7 Mon Sep 17 00:00:00 2001
From: Jesse Barnes <jbarnes@virtuousgeek.org>
Date: Tue, 1 Nov 2011 15:13:28 -0700
Subject: [PATCH 4/4] drm/i915: add destination color key support

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.

Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
---
 drivers/gpu/drm/i915/i915_dma.c     |    2 +
 drivers/gpu/drm/i915/intel_drv.h    |    6 +++
 drivers/gpu/drm/i915/intel_sprite.c |   72 +++++++++++++++++++++++++++++++++++
 include/drm/i915_drm.h              |   16 ++++++++
 4 files changed, 96 insertions(+), 0 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index 2eac955..0385a27 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -2294,6 +2294,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_DESTKEY, intel_sprite_set_destkey, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+	DRM_IOCTL_DEF_DRV(I915_GET_SPRITE_DESTKEY, intel_sprite_get_destkey, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
 };
 
 int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls);
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 785bae7..2f376dc 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -407,4 +407,10 @@ extern void intel_write_eld(struct drm_encoder *encoder,
 			    struct drm_display_mode *mode);
 extern void intel_cpt_verify_modeset(struct drm_device *dev, int pipe);
 
+extern int intel_sprite_set_destkey(struct drm_device *dev, void *data,
+				     struct drm_file *file_priv);
+extern int intel_sprite_get_destkey(struct drm_device *dev, void *data,
+				     struct drm_file *file_priv);
+
+
 #endif /* __INTEL_DRV_H__ */
diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
index ca0da52..0891bda 100644
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -99,6 +99,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--;
@@ -396,6 +397,77 @@ static void intel_destroy_plane(struct drm_plane *plane)
 	kfree(intel_plane);
 }
 
+int intel_sprite_set_destkey(struct drm_device *dev, void *data,
+			      struct drm_file *file_priv)
+{
+	struct drm_intel_set_sprite_destkey *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;
+
+	if (set->value > 0xffffff)
+		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);
+
+	mutex_lock(&dev->struct_mutex);
+	I915_WRITE(SPRKEYVAL(intel_plane->pipe), set->value);
+	I915_WRITE(SPRKEYMSK(intel_plane->pipe), 0xffffff);
+	POSTING_READ(SPRKEYMSK(intel_plane->pipe));
+	mutex_unlock(&dev->struct_mutex);
+
+out_unlock:
+	mutex_unlock(&dev->mode_config.mutex);
+	return ret;
+}
+
+int intel_sprite_get_destkey(struct drm_device *dev, void *data,
+			      struct drm_file *file_priv)
+{
+	struct drm_intel_get_sprite_destkey *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);
+
+	mutex_lock(&dev->struct_mutex);
+	get->value = I915_READ(SPRKEYVAL(intel_plane->pipe));
+	mutex_unlock(&dev->struct_mutex);
+
+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,
diff --git a/include/drm/i915_drm.h b/include/drm/i915_drm.h
index 28c0d11..f9a390b 100644
--- a/include/drm/i915_drm.h
+++ b/include/drm/i915_drm.h
@@ -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_DESTKEY	0x2a
+#define DRM_I915_SET_SPRITE_DESTKEY	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_DESTKEY DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_SET_SPRITE_DESTKEY, struct drm_intel_set_sprite_destkey)
+#define DRM_IOCTL_I915_GET_SPRITE_DESTKEY DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_SET_SPRITE_DESTKEY, struct drm_intel_get_sprite_destkey)
 
 /* Allow drivers to submit batchbuffers directly to hardware, relying
  * on the security mechanisms provided by hardware.
@@ -844,4 +848,16 @@ struct drm_intel_overlay_attrs {
 	__u32 gamma5;
 };
 
+/* Set the destination color key on a given sprite */
+struct drm_intel_set_sprite_destkey {
+	__u32 plane_id;
+	__u32 value;
+};
+
+/* Get the current destination color key on a given sprite */
+struct drm_intel_get_sprite_destkey {
+	__u32 plane_id;
+	__u64 value;
+};
+
 #endif				/* _I915_DRM_H_ */
-- 
1.7.4.1


[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

[-- Attachment #2: Type: text/plain, Size: 159 bytes --]

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 32+ messages in thread

* Re: [PATCH] DRM planes
  2011-11-03 17:36       ` Jesse Barnes
@ 2011-11-03 18:55         ` Rob Clark
  2011-11-03 19:14           ` Jesse Barnes
  0 siblings, 1 reply; 32+ messages in thread
From: Rob Clark @ 2011-11-03 18:55 UTC (permalink / raw)
  To: Jesse Barnes; +Cc: Marcus Lorentzon, intel-gfx, dri-devel

On Thu, Nov 3, 2011 at 12:36 PM, Jesse Barnes <jbarnes@virtuousgeek.org> wrote:
> On Thu, 3 Nov 2011 18:29:14 +0100
> Daniel Vetter <daniel@ffwll.ch> wrote:
>
>> Hi all,
>>
>> I've discussed this a bit on irc and consensus seems to be "some ugliness
>> due to interface impendance mistmatches in the kernel? who cares ...". I
>> agree that there's not a fundamental problem with fourcc and planar yuv
>> that can't be fixed with a bunch of boilerplate code with the assorted set
>> of inconsistencies between drivers. So if this is the general consensus
>> I'll just look the other way, shut down my shields an recall my battle
>> ship out of LEO ... ;-)
>
> Rob, Joonyoung, Inkie, any comment on using fourcc vs rolling our own
> surface definitions?

I tend to think that, even if fourcc's aren't perfect, that it is
better than the alternatives..

I *think* the main issue is really about single vs multiple buffer
objects?  Although I've mostly not been having too much time to follow
email this week.

BR,
-R


> Thanks,
> --
> Jesse Barnes, Intel Open Source Technology Center
>

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH] DRM planes
  2011-11-03 17:47   ` Alan Cox
@ 2011-11-03 18:58     ` Daniel Vetter
  2011-11-03 22:20       ` Alan Cox
  0 siblings, 1 reply; 32+ messages in thread
From: Daniel Vetter @ 2011-11-03 18:58 UTC (permalink / raw)
  To: Alan Cox; +Cc: dri-devel, intel-gfx, rob.clark

On Thu, Nov 03, 2011 at 05:47:43PM +0000, Alan Cox wrote:
> > In short decoding these fourcc values with all their implicit assumptions
> > about offset, strides and whatnotelse will be one giant switch mess. Not
> > my idea of a nice kernel interface. Also practically guaranteed to result
> > in slightly different behaviour in each driver.
> 
> So you'd rather make each applicationa author get it wrong individually
> and uniquely. That is a bigger mess by far.

We're talking about gpus, there's no way an application will talk to them
than through some nice cozy abstraction layer like OpenGl, X, ... Even
Wayland has gbm to do the low-level kms scanout allocation.

> > In conclusion: Ditch the addfb2ioctl and just add a few more kms pixel
> > formats for the new packed yuv layouts that the snb+ sprite code needs.
> 
> If you need a decoder for some hardware then fine, write one - share it
> with the v4l one and put it in a library drivers can call.
> 
> However - user space is already working in fourcc, v4l has working fourcc
> and dumping the mess on the user isn't going to be a win.

The mess will be dumped onto userspace anyway, but it won't be dumped onto
the user - that one should use Xv or some fancy EGLImage extension.
-Daniel
-- 
Daniel Vetter
Mail: daniel@ffwll.ch
Mobile: +41 (0)79 365 57 48

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH] DRM planes
  2011-11-03 18:55         ` Rob Clark
@ 2011-11-03 19:14           ` Jesse Barnes
  0 siblings, 0 replies; 32+ messages in thread
From: Jesse Barnes @ 2011-11-03 19:14 UTC (permalink / raw)
  To: Rob Clark; +Cc: Marcus Lorentzon, intel-gfx, dri-devel


[-- Attachment #1.1: Type: text/plain, Size: 1539 bytes --]

On Thu, 3 Nov 2011 13:55:50 -0500
Rob Clark <rob.clark@linaro.org> wrote:

> On Thu, Nov 3, 2011 at 12:36 PM, Jesse Barnes <jbarnes@virtuousgeek.org> wrote:
> > On Thu, 3 Nov 2011 18:29:14 +0100
> > Daniel Vetter <daniel@ffwll.ch> wrote:
> >
> >> Hi all,
> >>
> >> I've discussed this a bit on irc and consensus seems to be "some ugliness
> >> due to interface impendance mistmatches in the kernel? who cares ...". I
> >> agree that there's not a fundamental problem with fourcc and planar yuv
> >> that can't be fixed with a bunch of boilerplate code with the assorted set
> >> of inconsistencies between drivers. So if this is the general consensus
> >> I'll just look the other way, shut down my shields an recall my battle
> >> ship out of LEO ... ;-)
> >
> > Rob, Joonyoung, Inkie, any comment on using fourcc vs rolling our own
> > surface definitions?
> 
> I tend to think that, even if fourcc's aren't perfect, that it is
> better than the alternatives..
> 
> I *think* the main issue is really about single vs multiple buffer
> objects?  Although I've mostly not been having too much time to follow
> email this week.

I've punted on multi-buffer object fbs anyway.  I think those would be
better suited to an addfb_multi ioctl.  Muxing it into addfb2 seemed
unnatural, but I'm not opposed to someone adding one.  I just think
userspace will have to use one or the other depending on whether all
the data is packed into a single bo or not.

-- 
Jesse Barnes, Intel Open Source Technology Center

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

[-- Attachment #2: Type: text/plain, Size: 159 bytes --]

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH] DRM planes
  2011-11-03 18:58     ` Daniel Vetter
@ 2011-11-03 22:20       ` Alan Cox
  2011-11-03 22:24         ` Jesse Barnes
  0 siblings, 1 reply; 32+ messages in thread
From: Alan Cox @ 2011-11-03 22:20 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: intel-gfx, dri-devel, rob.clark

> We're talking about gpus, there's no way an application will talk to them
> than through some nice cozy abstraction layer like OpenGl, X, ... Even
> Wayland has gbm to do the low-level kms scanout allocation.

You are talking about scanouts. Nothing more. Nothing in KMS/DRM even
requires GPU accelerations.

> > However - user space is already working in fourcc, v4l has working fourcc
> > and dumping the mess on the user isn't going to be a win.
> 
> The mess will be dumped onto userspace anyway, but it won't be dumped onto
> the user - that one should use Xv or some fancy EGLImage extension.

Or quite likely in many embedded circumstances be working directly with
buffers and FourCC. Just like happens now with V4L. FourCC has its ugly
corners but its trivial to turn it into a table if you have a driver that
requires this. Old hat, old problem. Solved in AmigaOS in the 1980s.

Alan

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH] DRM planes
  2011-11-03 22:20       ` Alan Cox
@ 2011-11-03 22:24         ` Jesse Barnes
  0 siblings, 0 replies; 32+ messages in thread
From: Jesse Barnes @ 2011-11-03 22:24 UTC (permalink / raw)
  To: Alan Cox; +Cc: intel-gfx, dri-devel, rob.clark


[-- Attachment #1.1: Type: text/plain, Size: 1317 bytes --]

On Thu, 3 Nov 2011 22:20:00 +0000
Alan Cox <alan@lxorguk.ukuu.org.uk> wrote:

> > We're talking about gpus, there's no way an application will talk to them
> > than through some nice cozy abstraction layer like OpenGl, X, ... Even
> > Wayland has gbm to do the low-level kms scanout allocation.
> 
> You are talking about scanouts. Nothing more. Nothing in KMS/DRM even
> requires GPU accelerations.
> 
> > > However - user space is already working in fourcc, v4l has working fourcc
> > > and dumping the mess on the user isn't going to be a win.
> > 
> > The mess will be dumped onto userspace anyway, but it won't be dumped onto
> > the user - that one should use Xv or some fancy EGLImage extension.
> 
> Or quite likely in many embedded circumstances be working directly with
> buffers and FourCC. Just like happens now with V4L. FourCC has its ugly
> corners but its trivial to turn it into a table if you have a driver that
> requires this. Old hat, old problem. Solved in AmigaOS in the 1980s.

Ok now does anyone want to provide reviewed-bys on this stuff so Dave
will feel warm & fuzzy before applying the patches?

Daniel, have you been beaten down enough to acquiesce to that?  Alan,
does this look usable for your stuff?

-- 
Jesse Barnes, Intel Open Source Technology Center

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

[-- Attachment #2: Type: text/plain, Size: 159 bytes --]

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH 1/5] drm: add plane support
  2011-11-03 18:21     ` Jesse Barnes
@ 2011-11-03 22:48       ` Jesse Barnes
  2011-11-03 22:56         ` Daniel Vetter
  0 siblings, 1 reply; 32+ messages in thread
From: Jesse Barnes @ 2011-11-03 22:48 UTC (permalink / raw)
  To: Jesse Barnes; +Cc: intel-gfx, dri-devel, rob.clark


[-- Attachment #1.1: Type: text/plain, Size: 18508 bytes --]

On Thu, 3 Nov 2011 11:21:18 -0700
Jesse Barnes <jbarnes@virtuousgeek.org> wrote:

> On Wed, 2 Nov 2011 15:33:04 -0700
> Jesse Barnes <jbarnes@virtuousgeek.org> wrote:
> 
> > On Wed,  2 Nov 2011 13:03:19 -0700
> > Jesse Barnes <jbarnes@virtuousgeek.org> wrote:
> > 
> > > Planes are a bit like half-CRTCs.  They have a location and fb, but
> > > don't drive outputs directly.  Add support for handling them to the core
> > > KMS code.
> > 
> > Accidentally left out the ->destroy hook in this one.  The drm-overlays
> > branch at git://people.freedesktop.org/~jbarnes/linux has a fixed
> > version, along with a couple of fixes for issues Chris and Dan pointed
> > out.
> 
> Below is the updated patch with ->destroy in case this series passes
> muster and Dave is ready to apply.

...and now fixed to include a disable call if an active fb is destroyed
while being used in a plane.

-- 
Jesse Barnes, Intel Open Source Technology Center

From 94b16917fdd846d54bc8a23765201e32ceda43bf Mon Sep 17 00:00:00 2001
From: Jesse Barnes <jbarnes@virtuousgeek.org>
Date: Thu, 21 Apr 2011 16:58:37 -0700
Subject: [PATCH 1/5] drm: add plane support

Planes are a bit like half-CRTCs.  They have a location and fb, but
don't drive outputs directly.  Add support for handling them to the core
KMS code.

Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
---
 drivers/gpu/drm/drm_crtc.c |  251 +++++++++++++++++++++++++++++++++++++++++++-
 drivers/gpu/drm/drm_drv.c  |    3 +
 include/drm/drm.h          |    3 +
 include/drm/drm_crtc.h     |   79 ++++++++++++++-
 include/drm/drm_mode.h     |   33 ++++++
 5 files changed, 366 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index fe738f0..fac8043 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -321,6 +321,7 @@ void drm_framebuffer_cleanup(struct drm_framebuffer *fb)
 {
 	struct drm_device *dev = fb->dev;
 	struct drm_crtc *crtc;
+	struct drm_plane *plane;
 	struct drm_mode_set set;
 	int ret;
 
@@ -337,6 +338,15 @@ void drm_framebuffer_cleanup(struct drm_framebuffer *fb)
 		}
 	}
 
+	list_for_each_entry(plane, &dev->mode_config.plane_list, head) {
+		if (plane->fb == fb) {
+			/* should turn off the crtc */
+			ret = plane->funcs->disable_plane(plane);
+			if (ret)
+				DRM_ERROR("failed to disable plane with busy fb\n");
+		}
+	}
+
 	drm_mode_object_put(dev, &fb->base);
 	list_del(&fb->head);
 	dev->mode_config.num_fb--;
@@ -535,6 +545,48 @@ void drm_encoder_cleanup(struct drm_encoder *encoder)
 }
 EXPORT_SYMBOL(drm_encoder_cleanup);
 
+void drm_plane_init(struct drm_device *dev, struct drm_plane *plane,
+		    unsigned long possible_crtcs,
+		    const struct drm_plane_funcs *funcs,
+		    uint32_t *formats, uint32_t format_count)
+{
+	mutex_lock(&dev->mode_config.mutex);
+
+	plane->dev = dev;
+	drm_mode_object_get(dev, &plane->base, DRM_MODE_OBJECT_PLANE);
+	plane->funcs = funcs;
+	plane->format_types = kmalloc(sizeof(uint32_t) * format_count,
+				      GFP_KERNEL);
+	if (!plane->format_types) {
+		DRM_DEBUG_KMS("out of memory when allocating plane\n");
+		drm_mode_object_put(dev, &plane->base);
+		return;
+	}
+
+	memcpy(plane->format_types, formats, format_count);
+	plane->format_count = format_count;
+	plane->possible_crtcs = possible_crtcs;
+
+	list_add_tail(&plane->head, &dev->mode_config.plane_list);
+	dev->mode_config.num_plane++;
+
+	mutex_unlock(&dev->mode_config.mutex);
+}
+EXPORT_SYMBOL(drm_plane_init);
+
+void drm_plane_cleanup(struct drm_plane *plane)
+{
+	struct drm_device *dev = plane->dev;
+
+	mutex_lock(&dev->mode_config.mutex);
+	kfree(plane->format_types);
+	drm_mode_object_put(dev, &plane->base);
+	list_del(&plane->head);
+	dev->mode_config.num_plane--;
+	mutex_unlock(&dev->mode_config.mutex);
+}
+EXPORT_SYMBOL(drm_plane_cleanup);
+
 /**
  * drm_mode_create - create a new display mode
  * @dev: DRM device
@@ -866,6 +918,7 @@ void drm_mode_config_init(struct drm_device *dev)
 	INIT_LIST_HEAD(&dev->mode_config.encoder_list);
 	INIT_LIST_HEAD(&dev->mode_config.property_list);
 	INIT_LIST_HEAD(&dev->mode_config.property_blob_list);
+	INIT_LIST_HEAD(&dev->mode_config.plane_list);
 	idr_init(&dev->mode_config.crtc_idr);
 
 	mutex_lock(&dev->mode_config.mutex);
@@ -942,6 +995,7 @@ void drm_mode_config_cleanup(struct drm_device *dev)
 	struct drm_encoder *encoder, *enct;
 	struct drm_framebuffer *fb, *fbt;
 	struct drm_property *property, *pt;
+	struct drm_plane *plane, *plt;
 
 	list_for_each_entry_safe(encoder, enct, &dev->mode_config.encoder_list,
 				 head) {
@@ -966,6 +1020,10 @@ void drm_mode_config_cleanup(struct drm_device *dev)
 		crtc->funcs->destroy(crtc);
 	}
 
+	list_for_each_entry_safe(plane, plt, &dev->mode_config.plane_list,
+				 head) {
+		plane->funcs->destroy(plane);
+	}
 }
 EXPORT_SYMBOL(drm_mode_config_cleanup);
 
@@ -1466,6 +1524,193 @@ out:
 }
 
 /**
+ * drm_mode_getplane_res - get plane info
+ * @dev: DRM device
+ * @data: ioctl data
+ * @file_priv: DRM file info
+ *
+ * Return an plane count and set of IDs.
+ */
+int drm_mode_getplane_res(struct drm_device *dev, void *data,
+			    struct drm_file *file_priv)
+{
+	struct drm_mode_get_plane_res *plane_resp = data;
+	struct drm_mode_config *config;
+	struct drm_plane *plane;
+	uint32_t __user *plane_ptr;
+	int copied = 0, ret = 0;
+
+	if (!drm_core_check_feature(dev, DRIVER_MODESET))
+		return -EINVAL;
+
+	mutex_lock(&dev->mode_config.mutex);
+	config = &dev->mode_config;
+
+	/*
+	 * This ioctl is called twice, once to determine how much space is
+	 * needed, and the 2nd time to fill it.
+	 */
+	if (config->num_plane &&
+	    (plane_resp->count_planes >= config->num_plane)) {
+		plane_ptr = (uint32_t *)(unsigned long)plane_resp->plane_id_ptr;
+
+		list_for_each_entry(plane, &config->plane_list, head) {
+			if (put_user(plane->base.id, plane_ptr + copied)) {
+				ret = -EFAULT;
+				goto out;
+			}
+			copied++;
+		}
+	}
+	plane_resp->count_planes = config->num_plane;
+
+out:
+	mutex_unlock(&dev->mode_config.mutex);
+	return ret;
+}
+
+/**
+ * drm_mode_getplane - get plane info
+ * @dev: DRM device
+ * @data: ioctl data
+ * @file_priv: DRM file info
+ *
+ * Return plane info, including formats supported, gamma size, any
+ * current fb, etc.
+ */
+int drm_mode_getplane(struct drm_device *dev, void *data,
+			struct drm_file *file_priv)
+{
+	struct drm_mode_get_plane *plane_resp = data;
+	struct drm_mode_object *obj;
+	struct drm_plane *plane;
+	uint32_t __user *format_ptr;
+	int ret = 0;
+
+	if (!drm_core_check_feature(dev, DRIVER_MODESET))
+		return -EINVAL;
+
+	mutex_lock(&dev->mode_config.mutex);
+	obj = drm_mode_object_find(dev, plane_resp->plane_id,
+				   DRM_MODE_OBJECT_PLANE);
+	if (!obj) {
+		ret = -EINVAL;
+		goto out;
+	}
+	plane = obj_to_plane(obj);
+
+	if (plane->crtc)
+		plane_resp->crtc_id = plane->crtc->base.id;
+	else
+		plane_resp->crtc_id = 0;
+
+	if (plane->fb)
+		plane_resp->fb_id = plane->fb->base.id;
+	else
+		plane_resp->fb_id = 0;
+
+	plane_resp->plane_id = plane->base.id;
+	plane_resp->possible_crtcs = plane->possible_crtcs;
+	plane_resp->gamma_size = plane->gamma_size;
+
+	/*
+	 * This ioctl is called twice, once to determine how much space is
+	 * needed, and the 2nd time to fill it.
+	 */
+	if (plane->format_count &&
+	    (plane_resp->count_format_types >= plane->format_count)) {
+		format_ptr = (uint32_t *)(unsigned long)plane_resp->format_type_ptr;
+		if (copy_to_user(format_ptr,
+				 plane->format_types,
+				 sizeof(uint32_t) * plane->format_count)) {
+			ret = -EFAULT;
+			goto out;
+		}
+	}
+	plane_resp->count_format_types = plane->format_count;
+
+out:
+	mutex_unlock(&dev->mode_config.mutex);
+	return ret;
+}
+
+/**
+ * drm_mode_setplane - set up or tear down an plane
+ * @dev: DRM device
+ * @data: ioctl data*
+ * @file_prive: DRM file info
+ *
+ * Set plane info, including placement, fb, scaling, and other factors.
+ * Or pass a NULL fb to disable.
+ */
+int drm_mode_setplane(struct drm_device *dev, void *data,
+			struct drm_file *file_priv)
+{
+	struct drm_mode_set_plane *plane_req = data;
+	struct drm_mode_object *obj;
+	struct drm_plane *plane;
+	struct drm_crtc *crtc;
+	struct drm_framebuffer *fb;
+	int ret = 0;
+
+	if (!drm_core_check_feature(dev, DRIVER_MODESET))
+		return -EINVAL;
+
+	mutex_lock(&dev->mode_config.mutex);
+
+	/*
+	 * First, find the plane, crtc, and fb objects.  If not available,
+	 * we don't bother to call the driver.
+	 */
+	obj = drm_mode_object_find(dev, plane_req->plane_id,
+				   DRM_MODE_OBJECT_PLANE);
+	if (!obj) {
+		DRM_DEBUG_KMS("Unknown plane ID %d\n",
+			      plane_req->plane_id);
+		ret = -EINVAL;
+		goto out;
+	}
+	plane = obj_to_plane(obj);
+
+	/* No fb means shut it down */
+	if (!plane_req->fb_id) {
+		plane->funcs->disable_plane(plane);
+		goto out;
+	}
+
+	obj = drm_mode_object_find(dev, plane_req->crtc_id,
+				   DRM_MODE_OBJECT_CRTC);
+	if (!obj) {
+		DRM_DEBUG_KMS("Unknown crtc ID %d\n",
+			      plane_req->crtc_id);
+		ret = -EINVAL;
+		goto out;
+	}
+	crtc = obj_to_crtc(obj);
+
+	obj = drm_mode_object_find(dev, plane_req->fb_id,
+				   DRM_MODE_OBJECT_FB);
+	if (!obj) {
+		DRM_DEBUG_KMS("Unknown framebuffer ID %d\n",
+			      plane_req->fb_id);
+		ret = -EINVAL;
+		goto out;
+	}
+	fb = obj_to_fb(obj);
+
+	ret = plane->funcs->update_plane(plane, crtc, fb,
+					 plane_req->crtc_x, plane_req->crtc_y,
+					 plane_req->crtc_w, plane_req->crtc_h,
+					 plane_req->src_x, plane_req->src_y,
+					 plane_req->src_h, plane_req->src_w);
+
+out:
+	mutex_unlock(&dev->mode_config.mutex);
+
+	return ret;
+}
+
+/**
  * drm_mode_setcrtc - set CRTC configuration
  * @inode: inode from the ioctl
  * @filp: file * from the ioctl
@@ -1688,11 +1933,13 @@ int drm_mode_addfb(struct drm_device *dev,
 		return -EINVAL;
 
 	if ((config->min_width > r->width) || (r->width > config->max_width)) {
-		DRM_ERROR("mode new framebuffer width not within limits\n");
+		DRM_ERROR("bad framebuffer width %d, should be >= %d && <= %d\n",
+			  r->width, config->min_width, config->max_width);
 		return -EINVAL;
 	}
 	if ((config->min_height > r->height) || (r->height > config->max_height)) {
-		DRM_ERROR("mode new framebuffer height not within limits\n");
+		DRM_ERROR("bad framebuffer height %d, should be >= %d && <= %d\n",
+			  r->height, config->min_height, config->max_height);
 		return -EINVAL;
 	}
 
diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
index 7a87e08..d782bd1 100644
--- a/drivers/gpu/drm/drm_drv.c
+++ b/drivers/gpu/drm/drm_drv.c
@@ -135,8 +135,11 @@ static struct drm_ioctl_desc drm_ioctls[] = {
 	DRM_IOCTL_DEF(DRM_IOCTL_GEM_OPEN, drm_gem_open_ioctl, DRM_AUTH|DRM_UNLOCKED),
 
 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETRESOURCES, drm_mode_getresources, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPLANERESOURCES, drm_mode_getplane_res, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCRTC, drm_mode_getcrtc, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETCRTC, drm_mode_setcrtc, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPLANE, drm_mode_getplane, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETPLANE, drm_mode_setplane, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_CURSOR, drm_mode_cursor_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETGAMMA, drm_mode_gamma_get_ioctl, DRM_MASTER|DRM_UNLOCKED),
 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETGAMMA, drm_mode_gamma_set_ioctl, DRM_MASTER|DRM_UNLOCKED),
diff --git a/include/drm/drm.h b/include/drm/drm.h
index 4be33b4..2897967 100644
--- a/include/drm/drm.h
+++ b/include/drm/drm.h
@@ -714,6 +714,9 @@ struct drm_get_cap {
 #define DRM_IOCTL_MODE_CREATE_DUMB DRM_IOWR(0xB2, struct drm_mode_create_dumb)
 #define DRM_IOCTL_MODE_MAP_DUMB    DRM_IOWR(0xB3, struct drm_mode_map_dumb)
 #define DRM_IOCTL_MODE_DESTROY_DUMB    DRM_IOWR(0xB4, struct drm_mode_destroy_dumb)
+#define DRM_IOCTL_MODE_GETPLANERESOURCES DRM_IOWR(0xB5, struct drm_mode_get_plane_res)
+#define DRM_IOCTL_MODE_GETPLANE	DRM_IOWR(0xB6, struct drm_mode_get_plane)
+#define DRM_IOCTL_MODE_SETPLANE	DRM_IOWR(0xB7, struct drm_mode_set_plane)
 
 /**
  * Device specific ioctls should only be in their respective headers
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 8020798..8331dc6 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -44,6 +44,7 @@ struct drm_framebuffer;
 #define DRM_MODE_OBJECT_PROPERTY 0xb0b0b0b0
 #define DRM_MODE_OBJECT_FB 0xfbfbfbfb
 #define DRM_MODE_OBJECT_BLOB 0xbbbbbbbb
+#define DRM_MODE_OBJECT_PLANE 0xeeeeeeee
 
 struct drm_mode_object {
 	uint32_t id;
@@ -278,6 +279,7 @@ struct drm_crtc;
 struct drm_connector;
 struct drm_encoder;
 struct drm_pending_vblank_event;
+struct drm_plane;
 
 /**
  * drm_crtc_funcs - control CRTCs for a given device
@@ -536,6 +538,66 @@ struct drm_connector {
 };
 
 /**
+ * drm_plane_funcs - driver plane control functions
+ * @update_plane: update the plane configuration
+ * @disable_plane: shut down the plane
+ * @destroy: clean up plane resources
+ */
+struct drm_plane_funcs {
+	int (*update_plane)(struct drm_plane *plane,
+			    struct drm_crtc *crtc, struct drm_framebuffer *fb,
+			    int crtc_x, int crtc_y,
+			    unsigned int crtc_w, unsigned int crtc_h,
+			    uint32_t src_x, uint32_t src_y,
+			    uint32_t src_w, uint32_t src_h);
+	int (*disable_plane)(struct drm_plane *plane);
+	void (*destroy)(struct drm_plane *plane);
+};
+
+/**
+ * drm_plane - central DRM plane control structure
+ * @dev: DRM device this plane belongs to
+ * @kdev: kernel device
+ * @attr: kdev attributes
+ * @head: for list management
+ * @base: base mode object
+ * @possible_crtcs: pipes this plane can be bound to
+ * @format_types: array of formats supported by this plane
+ * @format_count: number of formats supported
+ * @crtc: currently bound CRTC
+ * @fb: currently bound fb
+ * @gamma_size: size of gamma table
+ * @gamma_store: gamma correction table
+ * @enabled: enabled flag
+ * @funcs: helper functions
+ * @helper_private: storage for drver layer
+ */
+struct drm_plane {
+	struct drm_device *dev;
+	struct device kdev;
+	struct device_attribute *attr;
+	struct list_head head;
+
+	struct drm_mode_object base;
+
+	uint32_t possible_crtcs;
+	uint32_t *format_types;
+	uint32_t format_count;
+
+	struct drm_crtc *crtc;
+	struct drm_framebuffer *fb;
+
+	/* CRTC gamma size for reporting to userspace */
+	uint32_t gamma_size;
+	uint16_t *gamma_store;
+
+	bool enabled;
+
+	const struct drm_plane_funcs *funcs;
+	void *helper_private;
+};
+
+/**
  * struct drm_mode_set
  *
  * Represents a single crtc the connectors that it drives with what mode
@@ -589,6 +651,8 @@ struct drm_mode_config {
 	struct list_head connector_list;
 	int num_encoder;
 	struct list_head encoder_list;
+	int num_plane;
+	struct list_head plane_list;
 
 	int num_crtc;
 	struct list_head crtc_list;
@@ -641,6 +705,7 @@ struct drm_mode_config {
 #define obj_to_fb(x) container_of(x, struct drm_framebuffer, base)
 #define obj_to_property(x) container_of(x, struct drm_property, base)
 #define obj_to_blob(x) container_of(x, struct drm_property_blob, base)
+#define obj_to_plane(x) container_of(x, struct drm_plane, base)
 
 
 extern void drm_crtc_init(struct drm_device *dev,
@@ -660,6 +725,13 @@ extern void drm_encoder_init(struct drm_device *dev,
 			     const struct drm_encoder_funcs *funcs,
 			     int encoder_type);
 
+extern void drm_plane_init(struct drm_device *dev,
+			   struct drm_plane *plane,
+			   unsigned long possible_crtcs,
+			   const struct drm_plane_funcs *funcs,
+			   uint32_t *formats, uint32_t format_count);
+extern void drm_plane_cleanup(struct drm_plane *plane);
+
 extern void drm_encoder_cleanup(struct drm_encoder *encoder);
 
 extern char *drm_get_connector_name(struct drm_connector *connector);
@@ -753,13 +825,18 @@ extern struct drm_mode_object *drm_mode_object_find(struct drm_device *dev,
 /* IOCTLs */
 extern int drm_mode_getresources(struct drm_device *dev,
 				 void *data, struct drm_file *file_priv);
-
+extern int drm_mode_getplane_res(struct drm_device *dev, void *data,
+				   struct drm_file *file_priv);
 extern int drm_mode_getcrtc(struct drm_device *dev,
 			    void *data, struct drm_file *file_priv);
 extern int drm_mode_getconnector(struct drm_device *dev,
 			      void *data, struct drm_file *file_priv);
 extern int drm_mode_setcrtc(struct drm_device *dev,
 			    void *data, struct drm_file *file_priv);
+extern int drm_mode_getplane(struct drm_device *dev,
+			       void *data, struct drm_file *file_priv);
+extern int drm_mode_setplane(struct drm_device *dev,
+			       void *data, struct drm_file *file_priv);
 extern int drm_mode_cursor_ioctl(struct drm_device *dev,
 				void *data, struct drm_file *file_priv);
 extern int drm_mode_addfb(struct drm_device *dev,
diff --git a/include/drm/drm_mode.h b/include/drm/drm_mode.h
index c4961ea..07711b0 100644
--- a/include/drm/drm_mode.h
+++ b/include/drm/drm_mode.h
@@ -120,6 +120,39 @@ struct drm_mode_crtc {
 	struct drm_mode_modeinfo mode;
 };
 
+/* Planes blend with or override other bits on the CRTC */
+struct drm_mode_set_plane {
+	__u32 plane_id;
+	__u32 crtc_id;
+	__u32 fb_id; /* fb object contains surface format type */
+
+	/* Signed dest location allows it to be partially off screen */
+	__s32 crtc_x, crtc_y;
+	__u32 crtc_w, crtc_h;
+
+	/* Source values are 16.16 fixed point */
+	__u32 src_x, src_y;
+	__u32 src_h, src_w;
+};
+
+struct drm_mode_get_plane {
+	__u64 format_type_ptr;
+	__u32 plane_id;
+
+	__u32 crtc_id;
+	__u32 fb_id;
+
+	__u32 possible_crtcs;
+	__u32 gamma_size;
+
+	__u32 count_format_types;
+};
+
+struct drm_mode_get_plane_res {
+	__u64 plane_id_ptr;
+	__u32 count_planes;
+};
+
 #define DRM_MODE_ENCODER_NONE	0
 #define DRM_MODE_ENCODER_DAC	1
 #define DRM_MODE_ENCODER_TMDS	2
-- 
1.7.4.1


[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

[-- Attachment #2: Type: text/plain, Size: 159 bytes --]

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 32+ messages in thread

* Re: [PATCH 1/5] drm: add plane support
  2011-11-03 22:48       ` Jesse Barnes
@ 2011-11-03 22:56         ` Daniel Vetter
  0 siblings, 0 replies; 32+ messages in thread
From: Daniel Vetter @ 2011-11-03 22:56 UTC (permalink / raw)
  To: Jesse Barnes; +Cc: intel-gfx, dri-devel, rob.clark

On Thu, Nov 03, 2011 at 03:48:52PM -0700, Jesse Barnes wrote:
> On Thu, 3 Nov 2011 11:21:18 -0700
> Jesse Barnes <jbarnes@virtuousgeek.org> wrote:
> 
> > On Wed, 2 Nov 2011 15:33:04 -0700
> > Jesse Barnes <jbarnes@virtuousgeek.org> wrote:
> > 
> > > On Wed,  2 Nov 2011 13:03:19 -0700
> > > Jesse Barnes <jbarnes@virtuousgeek.org> wrote:
> > > 
> > > > Planes are a bit like half-CRTCs.  They have a location and fb, but
> > > > don't drive outputs directly.  Add support for handling them to the core
> > > > KMS code.
> > > 
> > > Accidentally left out the ->destroy hook in this one.  The drm-overlays
> > > branch at git://people.freedesktop.org/~jbarnes/linux has a fixed
> > > version, along with a couple of fixes for issues Chris and Dan pointed
> > > out.
> > 
> > Below is the updated patch with ->destroy in case this series passes
> > muster and Dave is ready to apply.
> 
> ...and now fixed to include a disable call if an active fb is destroyed
> while being used in a plane.
> 
> -- 
> Jesse Barnes, Intel Open Source Technology Center
> 
> From 94b16917fdd846d54bc8a23765201e32ceda43bf Mon Sep 17 00:00:00 2001
> From: Jesse Barnes <jbarnes@virtuousgeek.org>
> Date: Thu, 21 Apr 2011 16:58:37 -0700
> Subject: [PATCH 1/5] drm: add plane support
> 
> Planes are a bit like half-CRTCs.  They have a location and fb, but
> don't drive outputs directly.  Add support for handling them to the core
> KMS code.
> 
> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>

Ok, with the drm_framebuffer_cleanup fixed up, this looks code. I've also
played around a bit with the legacy i8xx overlay, and the existing code
would nicely fit into ->update_plane and ->disable_plane.

Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
-- 
Daniel Vetter
Mail: daniel@ffwll.ch
Mobile: +41 (0)79 365 57 48

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH 1/5] drm: add plane support
  2011-11-02 20:03 ` [PATCH 1/5] drm: add plane support Jesse Barnes
  2011-11-02 22:33   ` Jesse Barnes
@ 2011-11-04  2:22   ` Joonyoung Shim
  2011-11-04 14:10     ` Jesse Barnes
  1 sibling, 1 reply; 32+ messages in thread
From: Joonyoung Shim @ 2011-11-04  2:22 UTC (permalink / raw)
  To: Jesse Barnes; +Cc: intel-gfx, dri-devel, rob.clark

11/03/2011 05:03 AM, Jesse Barnes 쓴 글:
> Planes are a bit like half-CRTCs.  They have a location and fb, but
> don't drive outputs directly.  Add support for handling them to the core
> KMS code.
>
> Signed-off-by: Jesse Barnes<jbarnes@virtuousgeek.org>
> ---
>   drivers/gpu/drm/drm_crtc.c |  236 +++++++++++++++++++++++++++++++++++++++++++-
>   drivers/gpu/drm/drm_drv.c  |    3 +
>   include/drm/drm.h          |    3 +
>   include/drm/drm_crtc.h     |   76 ++++++++++++++-
>   include/drm/drm_mode.h     |   33 ++++++
>   5 files changed, 348 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
> index fe738f0..0e129b1 100644
> --- a/drivers/gpu/drm/drm_crtc.c
> +++ b/drivers/gpu/drm/drm_crtc.c
> @@ -535,6 +535,48 @@ void drm_encoder_cleanup(struct drm_encoder *encoder)
>   }
>   EXPORT_SYMBOL(drm_encoder_cleanup);
>
> +void drm_plane_init(struct drm_device *dev, struct drm_plane *plane,
> +		    unsigned long possible_crtcs,
> +		    const struct drm_plane_funcs *funcs,
> +		    uint32_t *formats, uint32_t format_count)
> +{
> +	mutex_lock(&dev->mode_config.mutex);
> +
> +	plane->dev = dev;
> +	drm_mode_object_get(dev,&plane->base, DRM_MODE_OBJECT_PLANE);
> +	plane->funcs = funcs;
> +	plane->format_types = kmalloc(sizeof(uint32_t) * format_count,
> +				      GFP_KERNEL);
> +	if (!plane->format_types) {
> +		DRM_DEBUG_KMS("out of memory when allocating plane\n");
> +		drm_mode_object_put(dev,&plane->base);
> +		return;
> +	}
> +
> +	memcpy(plane->format_types, formats, format_count);
> +	plane->format_count = format_count;
> +	plane->possible_crtcs = possible_crtcs;
> +
> +	list_add_tail(&plane->head,&dev->mode_config.plane_list);
> +	dev->mode_config.num_plane++;
> +
> +	mutex_unlock(&dev->mode_config.mutex);
> +}
> +EXPORT_SYMBOL(drm_plane_init);
> +
> +void drm_plane_cleanup(struct drm_plane *plane)
> +{
> +	struct drm_device *dev = plane->dev;
> +
> +	mutex_lock(&dev->mode_config.mutex);
> +	kfree(plane->format_types);
> +	drm_mode_object_put(dev,&plane->base);
> +	list_del(&plane->head);
> +	dev->mode_config.num_plane--;
> +	mutex_unlock(&dev->mode_config.mutex);
> +}
> +EXPORT_SYMBOL(drm_plane_cleanup);
> +
>   /**
>    * drm_mode_create - create a new display mode
>    * @dev: DRM device
> @@ -866,6 +908,7 @@ void drm_mode_config_init(struct drm_device *dev)
>   	INIT_LIST_HEAD(&dev->mode_config.encoder_list);
>   	INIT_LIST_HEAD(&dev->mode_config.property_list);
>   	INIT_LIST_HEAD(&dev->mode_config.property_blob_list);
> +	INIT_LIST_HEAD(&dev->mode_config.plane_list);
>   	idr_init(&dev->mode_config.crtc_idr);
>
>   	mutex_lock(&dev->mode_config.mutex);
> @@ -1466,6 +1509,193 @@ out:
>   }
>
>   /**
> + * drm_mode_getplane_res - get plane info
> + * @dev: DRM device
> + * @data: ioctl data
> + * @file_priv: DRM file info
> + *
> + * Return an plane count and set of IDs.
> + */
> +int drm_mode_getplane_res(struct drm_device *dev, void *data,
> +			    struct drm_file *file_priv)
> +{
> +	struct drm_mode_get_plane_res *plane_resp = data;
> +	struct drm_mode_config *config;
> +	struct drm_plane *plane;
> +	uint32_t __user *plane_ptr;
> +	int copied = 0, ret = 0;
> +
> +	if (!drm_core_check_feature(dev, DRIVER_MODESET))
> +		return -EINVAL;
> +
> +	mutex_lock(&dev->mode_config.mutex);
> +	config =&dev->mode_config;
> +
> +	/*
> +	 * This ioctl is called twice, once to determine how much space is
> +	 * needed, and the 2nd time to fill it.
> +	 */
> +	if (config->num_plane&&
> +	    (plane_resp->count_planes>= config->num_plane)) {
> +		plane_ptr = (uint32_t *)(unsigned long)plane_resp->plane_id_ptr;
> +
> +		list_for_each_entry(plane,&config->plane_list, head) {
> +			if (put_user(plane->base.id, plane_ptr + copied)) {
> +				ret = -EFAULT;
> +				goto out;
> +			}
> +			copied++;
> +		}
> +	}
> +	plane_resp->count_planes = config->num_plane;
> +
> +out:
> +	mutex_unlock(&dev->mode_config.mutex);
> +	return ret;
> +}
> +
> +/**
> + * drm_mode_getplane - get plane info
> + * @dev: DRM device
> + * @data: ioctl data
> + * @file_priv: DRM file info
> + *
> + * Return plane info, including formats supported, gamma size, any
> + * current fb, etc.
> + */
> +int drm_mode_getplane(struct drm_device *dev, void *data,
> +			struct drm_file *file_priv)
> +{
> +	struct drm_mode_get_plane *plane_resp = data;
> +	struct drm_mode_object *obj;
> +	struct drm_plane *plane;
> +	uint32_t __user *format_ptr;
> +	int ret = 0;
> +
> +	if (!drm_core_check_feature(dev, DRIVER_MODESET))
> +		return -EINVAL;
> +
> +	mutex_lock(&dev->mode_config.mutex);
> +	obj = drm_mode_object_find(dev, plane_resp->plane_id,
> +				   DRM_MODE_OBJECT_PLANE);
> +	if (!obj) {
> +		ret = -EINVAL;
> +		goto out;
> +	}
> +	plane = obj_to_plane(obj);
> +
> +	if (plane->crtc)
> +		plane_resp->crtc_id = plane->crtc->base.id;
> +	else
> +		plane_resp->crtc_id = 0;
> +
> +	if (plane->fb)
> +		plane_resp->fb_id = plane->fb->base.id;
> +	else
> +		plane_resp->fb_id = 0;
> +
> +	plane_resp->plane_id = plane->base.id;
> +	plane_resp->possible_crtcs = plane->possible_crtcs;
> +	plane_resp->gamma_size = plane->gamma_size;
> +
> +	/*
> +	 * This ioctl is called twice, once to determine how much space is
> +	 * needed, and the 2nd time to fill it.
> +	 */
> +	if (plane->format_count&&
> +	    (plane_resp->count_format_types>= plane->format_count)) {
> +		format_ptr = (uint32_t *)(unsigned long)plane_resp->format_type_ptr;
> +		if (copy_to_user(format_ptr,
> +				 plane->format_types,
> +				 sizeof(uint32_t) * plane->format_count)) {
> +			ret = -EFAULT;
> +			goto out;
> +		}
> +	}
> +	plane_resp->count_format_types = plane->format_count;
> +
> +out:
> +	mutex_unlock(&dev->mode_config.mutex);
> +	return ret;
> +}
> +
> +/**
> + * drm_mode_setplane - set up or tear down an plane
> + * @dev: DRM device
> + * @data: ioctl data*
> + * @file_prive: DRM file info
> + *
> + * Set plane info, including placement, fb, scaling, and other factors.
> + * Or pass a NULL fb to disable.
> + */
> +int drm_mode_setplane(struct drm_device *dev, void *data,
> +			struct drm_file *file_priv)
> +{
> +	struct drm_mode_set_plane *plane_req = data;
> +	struct drm_mode_object *obj;
> +	struct drm_plane *plane;
> +	struct drm_crtc *crtc;
> +	struct drm_framebuffer *fb;
> +	int ret = 0;
> +
> +	if (!drm_core_check_feature(dev, DRIVER_MODESET))
> +		return -EINVAL;
> +
> +	mutex_lock(&dev->mode_config.mutex);
> +
> +	/*
> +	 * First, find the plane, crtc, and fb objects.  If not available,
> +	 * we don't bother to call the driver.
> +	 */
> +	obj = drm_mode_object_find(dev, plane_req->plane_id,
> +				   DRM_MODE_OBJECT_PLANE);
> +	if (!obj) {
> +		DRM_DEBUG_KMS("Unknown plane ID %d\n",
> +			      plane_req->plane_id);
> +		ret = -EINVAL;
> +		goto out;
> +	}
> +	plane = obj_to_plane(obj);
> +
> +	/* No fb means shut it down */
> +	if (!plane_req->fb_id) {
> +		plane->funcs->disable_plane(plane);
> +		goto out;
> +	}
> +
> +	obj = drm_mode_object_find(dev, plane_req->crtc_id,
> +				   DRM_MODE_OBJECT_CRTC);
> +	if (!obj) {
> +		DRM_DEBUG_KMS("Unknown crtc ID %d\n",
> +			      plane_req->crtc_id);
> +		ret = -EINVAL;
> +		goto out;
> +	}
> +	crtc = obj_to_crtc(obj);
> +
> +	obj = drm_mode_object_find(dev, plane_req->fb_id,
> +				   DRM_MODE_OBJECT_FB);
> +	if (!obj) {
> +		DRM_DEBUG_KMS("Unknown framebuffer ID %d\n",
> +			      plane_req->fb_id);
> +		ret = -EINVAL;
> +		goto out;
> +	}
> +	fb = obj_to_fb(obj);
> +
> +	ret = plane->funcs->update_plane(plane, crtc, fb,
> +					 plane_req->crtc_x, plane_req->crtc_y,
> +					 plane_req->crtc_w, plane_req->crtc_h,
> +					 plane_req->src_x, plane_req->src_y,
> +					 plane_req->src_h, plane_req->src_w);
> +
> +out:
> +	mutex_unlock(&dev->mode_config.mutex);
> +
> +	return ret;
> +}
> +
> +/**
>    * drm_mode_setcrtc - set CRTC configuration
>    * @inode: inode from the ioctl
>    * @filp: file * from the ioctl
> @@ -1688,11 +1918,13 @@ int drm_mode_addfb(struct drm_device *dev,
>   		return -EINVAL;
>
>   	if ((config->min_width>  r->width) || (r->width>  config->max_width)) {
> -		DRM_ERROR("mode new framebuffer width not within limits\n");
> +		DRM_ERROR("bad framebuffer width %d, should be>= %d&&  <= %d\n",
> +			  r->width, config->min_width, config->max_width);
>   		return -EINVAL;
>   	}
>   	if ((config->min_height>  r->height) || (r->height>  config->max_height)) {
> -		DRM_ERROR("mode new framebuffer height not within limits\n");
> +		DRM_ERROR("bad framebuffer height %d, should be>= %d&&  <= %d\n",
> +			  r->height, config->min_height, config->max_height);
>   		return -EINVAL;
>   	}
>
> diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
> index 93a112d..15da618 100644
> --- a/drivers/gpu/drm/drm_drv.c
> +++ b/drivers/gpu/drm/drm_drv.c
> @@ -135,8 +135,11 @@ static struct drm_ioctl_desc drm_ioctls[] = {
>   	DRM_IOCTL_DEF(DRM_IOCTL_GEM_OPEN, drm_gem_open_ioctl, DRM_AUTH|DRM_UNLOCKED),
>
>   	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETRESOURCES, drm_mode_getresources, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> +	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPLANERESOURCES, drm_mode_getplane_res, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
>   	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCRTC, drm_mode_getcrtc, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
>   	DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETCRTC, drm_mode_setcrtc, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> +	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPLANE, drm_mode_getplane, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> +	DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETPLANE, drm_mode_setplane, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
>   	DRM_IOCTL_DEF(DRM_IOCTL_MODE_CURSOR, drm_mode_cursor_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
>   	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETGAMMA, drm_mode_gamma_get_ioctl, DRM_MASTER|DRM_UNLOCKED),
>   	DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETGAMMA, drm_mode_gamma_set_ioctl, DRM_MASTER|DRM_UNLOCKED),
> diff --git a/include/drm/drm.h b/include/drm/drm.h
> index 4be33b4..2897967 100644
> --- a/include/drm/drm.h
> +++ b/include/drm/drm.h
> @@ -714,6 +714,9 @@ struct drm_get_cap {
>   #define DRM_IOCTL_MODE_CREATE_DUMB DRM_IOWR(0xB2, struct drm_mode_create_dumb)
>   #define DRM_IOCTL_MODE_MAP_DUMB    DRM_IOWR(0xB3, struct drm_mode_map_dumb)
>   #define DRM_IOCTL_MODE_DESTROY_DUMB    DRM_IOWR(0xB4, struct drm_mode_destroy_dumb)
> +#define DRM_IOCTL_MODE_GETPLANERESOURCES DRM_IOWR(0xB5, struct drm_mode_get_plane_res)
> +#define DRM_IOCTL_MODE_GETPLANE	DRM_IOWR(0xB6, struct drm_mode_get_plane)
> +#define DRM_IOCTL_MODE_SETPLANE	DRM_IOWR(0xB7, struct drm_mode_set_plane)
>
>   /**
>    * Device specific ioctls should only be in their respective headers
> diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
> index 8020798..b4519f8 100644
> --- a/include/drm/drm_crtc.h
> +++ b/include/drm/drm_crtc.h
> @@ -44,6 +44,7 @@ struct drm_framebuffer;
>   #define DRM_MODE_OBJECT_PROPERTY 0xb0b0b0b0
>   #define DRM_MODE_OBJECT_FB 0xfbfbfbfb
>   #define DRM_MODE_OBJECT_BLOB 0xbbbbbbbb
> +#define DRM_MODE_OBJECT_PLANE 0xeeeeeeee
>
>   struct drm_mode_object {
>   	uint32_t id;
> @@ -278,6 +279,7 @@ struct drm_crtc;
>   struct drm_connector;
>   struct drm_encoder;
>   struct drm_pending_vblank_event;
> +struct drm_plane;
>
>   /**
>    * drm_crtc_funcs - control CRTCs for a given device
> @@ -536,6 +538,63 @@ struct drm_connector {
>   };
>
>   /**
> + * drm_plane_funcs - driver plane control functions
> + * @update_plane: update the plane configuration
> + */
> +struct drm_plane_funcs {
> +	int (*update_plane)(struct drm_plane *plane,
> +			    struct drm_crtc *crtc, struct drm_framebuffer *fb,
> +			    int crtc_x, int crtc_y,
> +			    unsigned int crtc_w, unsigned int crtc_h,
> +			    uint32_t src_x, uint32_t src_y,
> +			    uint32_t src_w, uint32_t src_h);
> +	int (*disable_plane)(struct drm_plane *plane);
> +};
> +
> +/**
> + * drm_plane - central DRM plane control structure
> + * @dev: DRM device this plane belongs to
> + * @kdev: kernel device
> + * @attr: kdev attributes
> + * @head: for list management
> + * @base: base mode object
> + * @possible_crtcs: pipes this plane can be bound to
> + * @format_types: array of formats supported by this plane
> + * @format_count: number of formats supported
> + * @crtc: currently bound CRTC
> + * @fb: currently bound fb
> + * @gamma_size: size of gamma table
> + * @gamma_store: gamma correction table
> + * @enabled: enabled flag
> + * @funcs: helper functions
> + * @helper_private: storage for drver layer
> + */
> +struct drm_plane {
> +	struct drm_device *dev;
> +	struct device kdev;
> +	struct device_attribute *attr;
> +	struct list_head head;
> +
> +	struct drm_mode_object base;
> +
> +	uint32_t possible_crtcs;
> +	uint32_t *format_types;
> +	uint32_t format_count;
> +
> +	struct drm_crtc *crtc;
> +	struct drm_framebuffer *fb;

Where are crtc and fb of struct drm_plane assigned?
First, i did it in device specific update_plane, but can do in
drm_mode_setplane?

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 32+ messages in thread

* RE: [Intel-gfx] [PATCH 4/5] drm/i915: add SNB and IVB video sprite support
  2011-11-02 20:03 ` [PATCH 4/5] drm/i915: add SNB and IVB video sprite support Jesse Barnes
  2011-11-03 18:22   ` Jesse Barnes
@ 2011-11-04  2:29   ` Lan, Hai
  1 sibling, 0 replies; 32+ messages in thread
From: Lan, Hai @ 2011-11-04  2:29 UTC (permalink / raw)
  To: Jesse Barnes, dri-devel; +Cc: intel-gfx, rob.clark

Hi Jesse,
It sees that there might be an overflow when crtc_w or crtc_h =0. 
Following is my patch.
Thanks and best regards.

Hai Lan


>From 778327daa3451f3c5f41c5db8bdccdcbf484267b Mon Sep 17 00:00:00 2001
From: Hai Lan <hai.lan@intel.com>
Date: Fri, 4 Nov 2011 18:08:11 +0800
Subject: [PATCH] drm/i915:fix the overflow for overlay when crtc_w or crtc_h =0

When the crtc_w = 0 or crtc_h = 0, it should not be divided.
Besides, when (crtc_x+<crtc_w)<0 or (crtc_y+crtc_h)<0, it should be handled.

Signed-off-by: Hai Lan <hai.lan@intel.com>
---
 drivers/gpu/drm/i915/intel_sprite.c |   14 +++++++++++---
 1 files changed, 11 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
index 0891bda..d62e8ca 100644
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -268,17 +268,23 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
 	 * try to scale the source if part of the visible region is offscreen.
 	 * The caller must handle that by adjusting source offset and size.
 	 */
-	if (crtc_x < 0) {
+	if ((crtc_x < 0) && ((crtc_x + crtc_w)>0)) {
 		crtc_w += crtc_x;
 		crtc_x = 0;
 	}
+	if ((crtc_x + crtc_w)<0) {
+		return -EINVAL;
+	}
 	if (crtc_x + crtc_w > primary_w)
 		crtc_w = primary_w - crtc_x;
 
-	if (crtc_y < 0) {
+	if ((crtc_y < 0) && ((crtc_y+crtc_h)>0)) {
 		crtc_h += crtc_y;
 		crtc_y = 0;
 	}
+	if ((crtc_y+crtc_h)<0) {
+		return -EINVAL;
+	}
 	if (crtc_y + crtc_h > primary_h)
 		crtc_h = primary_h - crtc_y;
 
@@ -286,7 +292,9 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
 	 * We can take a larger source and scale it down, but
 	 * only so much...  16x is the max on SNB.
 	 */
-	if (((src_w * src_h) / (crtc_w * crtc_h)) > intel_plane->max_downscale)
+	if (crtc_w == 0 || crtc_h == 0)
+		return -EINVAL;
+	else if (((src_w * src_h) / (crtc_w * crtc_h)) > intel_plane->max_downscale)
 		return -EINVAL;
 
 	/*
-- 
1.7.4.1

^ permalink raw reply related	[flat|nested] 32+ messages in thread

* Re: [PATCH 2/5] drm: add an fb creation ioctl that takes a pixel format
  2011-11-02 20:03 ` [PATCH 2/5] drm: add an fb creation ioctl that takes a pixel format Jesse Barnes
  2011-11-03 18:22   ` Jesse Barnes
@ 2011-11-04  7:34   ` Joonyoung Shim
  2011-11-04 14:13     ` Jesse Barnes
       [not found]   ` <CAAQKjZPhqYdMAUkbCbc68muPLN7azuVr0yod7hFC=i+MigwNhw@mail.gmail.com>
  2 siblings, 1 reply; 32+ messages in thread
From: Joonyoung Shim @ 2011-11-04  7:34 UTC (permalink / raw)
  To: Jesse Barnes; +Cc: intel-gfx, dri-devel, rob.clark

11/03/2011 05:03 AM, Jesse Barnes 쓴 글:
> To properly support the various plane formats supported by different
> hardware, the kernel must know the pixel format of a framebuffer object.
> So add a new ioctl taking a format argument corresponding to a fourcc
> name from videodev2.h.
>
> Signed-off-by: Jesse Barnes<jbarnes@virtuousgeek.org>
> ---
>   drivers/gpu/drm/drm_crtc.c                |  105 ++++++++++++++++++++++++++++-
>   drivers/gpu/drm/drm_crtc_helper.c         |   50 +++++++++++++-
>   drivers/gpu/drm/drm_drv.c                 |    1 +
>   drivers/gpu/drm/i915/intel_display.c      |   34 +++++-----
>   drivers/gpu/drm/i915/intel_drv.h          |    2 +-
>   drivers/gpu/drm/i915/intel_fb.c           |   11 ++--
>   drivers/gpu/drm/nouveau/nouveau_display.c |    4 +-
>   drivers/gpu/drm/radeon/radeon_display.c   |    4 +-
>   drivers/gpu/drm/radeon/radeon_fb.c        |   18 +++--
>   drivers/gpu/drm/radeon/radeon_mode.h      |    2 +-
>   drivers/gpu/drm/vmwgfx/vmwgfx_kms.c       |    2 +-
>   drivers/staging/gma500/framebuffer.c      |    2 +-
>   include/drm/drm.h                         |    1 +
>   include/drm/drm_crtc.h                    |    7 ++-
>   include/drm/drm_crtc_helper.h             |    4 +-
>   include/drm/drm_mode.h                    |   26 +++++++
>   include/linux/videodev2.h                 |    1 +
>   17 files changed, 231 insertions(+), 43 deletions(-)
>
> diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
> index 0e129b1..ff47554 100644
> --- a/drivers/gpu/drm/drm_crtc.c
> +++ b/drivers/gpu/drm/drm_crtc.c
> @@ -1889,6 +1889,42 @@ out:
>   	return ret;
>   }
>
> +/* Original addfb only supported RGB formats, so figure out which one */
> +uint32_t drm_mode_legacy_fb_format(uint32_t bpp, uint32_t depth)
> +{
> +	uint32_t fmt;
> +
> +	switch (bpp) {
> +	case 8:
> +		fmt = V4L2_PIX_FMT_RGB332;
> +		break;
> +	case 16:
> +		if (depth == 15)
> +			fmt = V4L2_PIX_FMT_RGB555;
> +		else
> +			fmt = V4L2_PIX_FMT_RGB565;
> +		break;
> +	case 24:
> +		fmt = V4L2_PIX_FMT_RGB24;
> +		break;
> +	case 32:
> +		if (depth == 24)
> +			fmt = V4L2_PIX_FMT_RGB24;
> +		else if (depth == 30)
> +			fmt = V4L2_PIX_FMT_INTC_RGB30;
> +		else
> +			fmt = V4L2_PIX_FMT_RGB32;
> +		break;
> +	default:
> +		DRM_ERROR("bad bpp, assuming RGB24 pixel format\n");
> +		fmt = V4L2_PIX_FMT_RGB24;
> +		break;
> +	}
> +
> +	return fmt;
> +}
> +EXPORT_SYMBOL(drm_mode_legacy_fb_format);
> +
>   /**
>    * drm_mode_addfb - add an FB to the graphics configuration
>    * @inode: inode from the ioctl
> @@ -1909,7 +1945,74 @@ out:
>   int drm_mode_addfb(struct drm_device *dev,
>   		   void *data, struct drm_file *file_priv)
>   {
> -	struct drm_mode_fb_cmd *r = data;
> +	struct drm_mode_fb_cmd *or = data;
> +	struct drm_mode_fb_cmd2 r;
> +	struct drm_mode_config *config =&dev->mode_config;
> +	struct drm_framebuffer *fb;
> +	int ret = 0;
> +
> +	/* Use new struct with format internally */
> +	r.fb_id = or->fb_id;
> +	r.width = or->width;
> +	r.height = or->height;
> +	r.pitches[0] = or->pitch;
> +	r.pixel_format = drm_mode_legacy_fb_format(or->bpp, or->depth);
> +	r.handle = or->handle;
> +
> +	if (!drm_core_check_feature(dev, DRIVER_MODESET))
> +		return -EINVAL;
> +
> +	if ((config->min_width>  r.width) || (r.width>  config->max_width)) {
> +		DRM_ERROR("mode new framebuffer width not within limits\n");
> +		return -EINVAL;
> +	}
> +	if ((config->min_height>  r.height) || (r.height>  config->max_height)) {
> +		DRM_ERROR("mode new framebuffer height not within limits\n");
> +		return -EINVAL;
> +	}
> +
> +	mutex_lock(&dev->mode_config.mutex);
> +
> +	/* TODO check buffer is sufficiently large */
> +	/* TODO setup destructor callback */
> +
> +	fb = dev->mode_config.funcs->fb_create(dev, file_priv,&r);
> +	if (IS_ERR(fb)) {
> +		DRM_ERROR("could not create framebuffer\n");
> +		ret = PTR_ERR(fb);
> +		goto out;
> +	}
> +
> +	or->fb_id = fb->base.id;
> +	list_add(&fb->filp_head,&file_priv->fbs);
> +	DRM_DEBUG_KMS("[FB:%d]\n", fb->base.id);
> +
> +out:
> +	mutex_unlock(&dev->mode_config.mutex);
> +	return ret;
> +}
> +
> +/**
> + * drm_mode_addfb2 - add an FB to the graphics configuration
> + * @inode: inode from the ioctl
> + * @filp: file * from the ioctl
> + * @cmd: cmd from ioctl
> + * @arg: arg from ioctl
> + *
> + * LOCKING:
> + * Takes mode config lock.
> + *
> + * Add a new FB to the specified CRTC, given a user request with format.
> + *
> + * Called by the user via ioctl.
> + *
> + * RETURNS:
> + * Zero on success, errno on failure.
> + */
> +int drm_mode_addfb2(struct drm_device *dev,
> +		    void *data, struct drm_file *file_priv)
> +{
> +	struct drm_mode_fb_cmd2 *r = data;
>   	struct drm_mode_config *config =&dev->mode_config;
>   	struct drm_framebuffer *fb;
>   	int ret = 0;
> diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c
> index f88a9b2..0573f12 100644
> --- a/drivers/gpu/drm/drm_crtc_helper.c
> +++ b/drivers/gpu/drm/drm_crtc_helper.c
> @@ -805,14 +805,56 @@ void drm_helper_connector_dpms(struct drm_connector *connector, int mode)
>   }
>   EXPORT_SYMBOL(drm_helper_connector_dpms);
>
> +/*
> + * Just need to support RGB formats here for compat with code that doesn't
> + * use pixel formats directly yet.
> + */
> +void drm_helper_get_fb_bpp_depth(uint32_t format, unsigned int *depth,
> +				 int *bpp)
> +{
> +	switch (format) {
> +	case V4L2_PIX_FMT_RGB332:
> +		*depth = 8;
> +		*bpp = 8;
> +		break;
> +	case V4L2_PIX_FMT_RGB555:
> +		*depth = 15;
> +		*bpp = 16;
> +		break;
> +	case V4L2_PIX_FMT_RGB565:
> +		*depth = 16;
> +		*bpp = 16;
> +		break;
> +	case V4L2_PIX_FMT_RGB24:
> +		*depth = 24;
> +		*bpp = 24;
> +		break;

In the depth = 24 and bpp = 32 case also the pixed_format is
V4L2_PIX_FMT_RGB24, but above function cannot detect it.


> +	case V4L2_PIX_FMT_INTC_RGB30:
> +		*depth = 30;
> +		*bpp = 32;
> +		break;
> +	case V4L2_PIX_FMT_RGB32:
> +		*depth = 32;
> +		*bpp = 32;
> +		break;
> +	default:
> +		DRM_DEBUG_KMS("unsupported pixel format\n");
> +		*depth = 0;
> +		*bpp = 0;
> +		break;
> +	}
> +}
> +EXPORT_SYMBOL(drm_helper_get_fb_bpp_depth);
> +
>   int drm_helper_mode_fill_fb_struct(struct drm_framebuffer *fb,
> -				   struct drm_mode_fb_cmd *mode_cmd)
> +				   struct drm_mode_fb_cmd2 *mode_cmd)
>   {
>   	fb->width = mode_cmd->width;
>   	fb->height = mode_cmd->height;
> -	fb->pitch = mode_cmd->pitch;
> -	fb->bits_per_pixel = mode_cmd->bpp;
> -	fb->depth = mode_cmd->depth;
> +	fb->pitch = mode_cmd->pitches[0];
> +	drm_helper_get_fb_bpp_depth(mode_cmd->pixel_format,&fb->depth,
> +				&fb->bits_per_pixel);
> +	fb->pixel_format = mode_cmd->pixel_format;
>
>   	return 0;
>   }
> diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
> index 15da618..f24b9b6 100644
> --- a/drivers/gpu/drm/drm_drv.c
> +++ b/drivers/gpu/drm/drm_drv.c
> @@ -152,6 +152,7 @@ static struct drm_ioctl_desc drm_ioctls[] = {
>   	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPROPBLOB, drm_mode_getblob_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
>   	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETFB, drm_mode_getfb, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
>   	DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB, drm_mode_addfb, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> +	DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB2, drm_mode_addfb2, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
>   	DRM_IOCTL_DEF(DRM_IOCTL_MODE_RMFB, drm_mode_rmfb, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
>   	DRM_IOCTL_DEF(DRM_IOCTL_MODE_PAGE_FLIP, drm_mode_page_flip_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
>   	DRM_IOCTL_DEF(DRM_IOCTL_MODE_DIRTYFB, drm_mode_dirtyfb_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 981b1f1..0727fc8 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -6279,7 +6279,7 @@ static struct drm_display_mode load_detect_mode = {
>
>   static struct drm_framebuffer *
>   intel_framebuffer_create(struct drm_device *dev,
> -			 struct drm_mode_fb_cmd *mode_cmd,
> +			 struct drm_mode_fb_cmd2 *mode_cmd,
>   			 struct drm_i915_gem_object *obj)
>   {
>   	struct intel_framebuffer *intel_fb;
> @@ -6321,7 +6321,7 @@ intel_framebuffer_create_for_mode(struct drm_device *dev,
>   				  int depth, int bpp)
>   {
>   	struct drm_i915_gem_object *obj;
> -	struct drm_mode_fb_cmd mode_cmd;
> +	struct drm_mode_fb_cmd2 mode_cmd;
>
>   	obj = i915_gem_alloc_object(dev,
>   				    intel_framebuffer_size_for_mode(mode, bpp));
> @@ -6330,9 +6330,9 @@ intel_framebuffer_create_for_mode(struct drm_device *dev,
>
>   	mode_cmd.width = mode->hdisplay;
>   	mode_cmd.height = mode->vdisplay;
> -	mode_cmd.depth = depth;
> -	mode_cmd.bpp = bpp;
> -	mode_cmd.pitch = intel_framebuffer_pitch_for_width(mode_cmd.width, bpp);
> +	mode_cmd.pitches[0] = intel_framebuffer_pitch_for_width(mode_cmd.width,
> +								bpp);
> +	mode_cmd.pixel_format = 0;
>
>   	return intel_framebuffer_create(dev,&mode_cmd, obj);
>   }
> @@ -7573,7 +7573,7 @@ static const struct drm_framebuffer_funcs intel_fb_funcs = {
>
>   int intel_framebuffer_init(struct drm_device *dev,
>   			   struct intel_framebuffer *intel_fb,
> -			   struct drm_mode_fb_cmd *mode_cmd,
> +			   struct drm_mode_fb_cmd2 *mode_cmd,
>   			   struct drm_i915_gem_object *obj)
>   {
>   	int ret;
> @@ -7584,18 +7584,20 @@ int intel_framebuffer_init(struct drm_device *dev,
>   	if (mode_cmd->pitch&  63)
>   		return -EINVAL;
>
> -	switch (mode_cmd->bpp) {
> -	case 8:
> -	case 16:
> -		/* Only pre-ILK can handle 5:5:5 */
> -		if (mode_cmd->depth == 15&&  !HAS_PCH_SPLIT(dev))
> -			return -EINVAL;
> +	switch (mode_cmd->pixel_format) {
> +	case V4L2_PIX_FMT_RGB332:
> +	case V4L2_PIX_FMT_RGB565:
> +	case V4L2_PIX_FMT_RGB24:
> +	case V4L2_PIX_FMT_INTC_RGB30:
> +		/* RGB formats are common across chipsets */
>   		break;
> -
> -	case 24:
> -	case 32:
> +	case V4L2_PIX_FMT_YUYV:
> +	case V4L2_PIX_FMT_UYVY:
> +	case V4L2_PIX_FMT_YVYU:
> +	case V4L2_PIX_FMT_VYUY:
>   		break;
>   	default:
> +		DRM_ERROR("unsupported pixel format\n");
>   		return -EINVAL;
>   	}
>
> @@ -7613,7 +7615,7 @@ int intel_framebuffer_init(struct drm_device *dev,
>   static struct drm_framebuffer *
>   intel_user_framebuffer_create(struct drm_device *dev,
>   			      struct drm_file *filp,
> -			      struct drm_mode_fb_cmd *mode_cmd)
> +			      struct drm_mode_fb_cmd2 *mode_cmd)
>   {
>   	struct drm_i915_gem_object *obj;
>
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index bd9a604..23c5622 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -359,7 +359,7 @@ extern int intel_pin_and_fence_fb_obj(struct drm_device *dev,
>
>   extern int intel_framebuffer_init(struct drm_device *dev,
>   				  struct intel_framebuffer *ifb,
> -				  struct drm_mode_fb_cmd *mode_cmd,
> +				  struct drm_mode_fb_cmd2 *mode_cmd,
>   				  struct drm_i915_gem_object *obj);
>   extern int intel_fbdev_init(struct drm_device *dev);
>   extern void intel_fbdev_fini(struct drm_device *dev);
> diff --git a/drivers/gpu/drm/i915/intel_fb.c b/drivers/gpu/drm/i915/intel_fb.c
> index ec49bae..dc1db4f 100644
> --- a/drivers/gpu/drm/i915/intel_fb.c
> +++ b/drivers/gpu/drm/i915/intel_fb.c
> @@ -65,7 +65,7 @@ static int intelfb_create(struct intel_fbdev *ifbdev,
>   	struct drm_i915_private *dev_priv = dev->dev_private;
>   	struct fb_info *info;
>   	struct drm_framebuffer *fb;
> -	struct drm_mode_fb_cmd mode_cmd;
> +	struct drm_mode_fb_cmd2 mode_cmd;
>   	struct drm_i915_gem_object *obj;
>   	struct device *device =&dev->pdev->dev;
>   	int size, ret;
> @@ -77,11 +77,12 @@ static int intelfb_create(struct intel_fbdev *ifbdev,
>   	mode_cmd.width = sizes->surface_width;
>   	mode_cmd.height = sizes->surface_height;
>
> -	mode_cmd.bpp = sizes->surface_bpp;
> -	mode_cmd.pitch = ALIGN(mode_cmd.width * ((mode_cmd.bpp + 7) / 8), 64);
> -	mode_cmd.depth = sizes->surface_depth;
> +	mode_cmd.pitches[0] = ALIGN(mode_cmd.width * ((sizes->surface_bpp + 7) /
> +						      8), 64);
> +	mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp,
> +							  sizes->surface_depth);
>
> -	size = mode_cmd.pitch * mode_cmd.height;
> +	size = mode_cmd.pitches[0] * mode_cmd.height;
>   	size = ALIGN(size, PAGE_SIZE);
>   	obj = i915_gem_alloc_object(dev, size);
>   	if (!obj) {
> diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c
> index ddbabef..7a428a9 100644
> --- a/drivers/gpu/drm/nouveau/nouveau_display.c
> +++ b/drivers/gpu/drm/nouveau/nouveau_display.c
> @@ -64,7 +64,7 @@ static const struct drm_framebuffer_funcs nouveau_framebuffer_funcs = {
>   int
>   nouveau_framebuffer_init(struct drm_device *dev,
>   			 struct nouveau_framebuffer *nv_fb,
> -			 struct drm_mode_fb_cmd *mode_cmd,
> +			 struct drm_mode_fb_cmd2 *mode_cmd,
>   			 struct nouveau_bo *nvbo)
>   {
>   	struct drm_nouveau_private *dev_priv = dev->dev_private;
> @@ -124,7 +124,7 @@ nouveau_framebuffer_init(struct drm_device *dev,
>   static struct drm_framebuffer *
>   nouveau_user_framebuffer_create(struct drm_device *dev,
>   				struct drm_file *file_priv,
> -				struct drm_mode_fb_cmd *mode_cmd)
> +				struct drm_mode_fb_cmd2 *mode_cmd)
>   {
>   	struct nouveau_framebuffer *nouveau_fb;
>   	struct drm_gem_object *gem;
> diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c
> index 6cc17fb..ae803f8 100644
> --- a/drivers/gpu/drm/radeon/radeon_display.c
> +++ b/drivers/gpu/drm/radeon/radeon_display.c
> @@ -1113,7 +1113,7 @@ static const struct drm_framebuffer_funcs radeon_fb_funcs = {
>   void
>   radeon_framebuffer_init(struct drm_device *dev,
>   			struct radeon_framebuffer *rfb,
> -			struct drm_mode_fb_cmd *mode_cmd,
> +			struct drm_mode_fb_cmd2 *mode_cmd,
>   			struct drm_gem_object *obj)
>   {
>   	rfb->obj = obj;
> @@ -1124,7 +1124,7 @@ radeon_framebuffer_init(struct drm_device *dev,
>   static struct drm_framebuffer *
>   radeon_user_framebuffer_create(struct drm_device *dev,
>   			       struct drm_file *file_priv,
> -			       struct drm_mode_fb_cmd *mode_cmd)
> +			       struct drm_mode_fb_cmd2 *mode_cmd)
>   {
>   	struct drm_gem_object *obj;
>   	struct radeon_framebuffer *radeon_fb;
> diff --git a/drivers/gpu/drm/radeon/radeon_fb.c b/drivers/gpu/drm/radeon/radeon_fb.c
> index 0b7b486..ea110ad 100644
> --- a/drivers/gpu/drm/radeon/radeon_fb.c
> +++ b/drivers/gpu/drm/radeon/radeon_fb.c
> @@ -103,7 +103,7 @@ static void radeonfb_destroy_pinned_object(struct drm_gem_object *gobj)
>   }
>
>   static int radeonfb_create_pinned_object(struct radeon_fbdev *rfbdev,
> -					 struct drm_mode_fb_cmd *mode_cmd,
> +					 struct drm_mode_fb_cmd2 *mode_cmd,
>   					 struct drm_gem_object **gobj_p)
>   {
>   	struct radeon_device *rdev = rfbdev->rdev;
> @@ -114,13 +114,17 @@ static int radeonfb_create_pinned_object(struct radeon_fbdev *rfbdev,
>   	int ret;
>   	int aligned_size, size;
>   	int height = mode_cmd->height;
> +	u32 bpp, depth;
> +
> +	drm_helper_get_fb_bpp_depth(mode_cmd->pixel_format,&depth,&bpp);
>
>   	/* need to align pitch with crtc limits */
> -	mode_cmd->pitch = radeon_align_pitch(rdev, mode_cmd->width, mode_cmd->bpp, fb_tiled) * ((mode_cmd->bpp + 1) / 8);
> +	mode_cmd->pitches[0] = radeon_align_pitch(rdev, mode_cmd->width, bpp,
> +						  fb_tiled) * ((bpp + 1) / 8);
>
>   	if (rdev->family>= CHIP_R600)
>   		height = ALIGN(mode_cmd->height, 8);
> -	size = mode_cmd->pitch * height;
> +	size = mode_cmd->pitches[0] * height;
>   	aligned_size = ALIGN(size, PAGE_SIZE);
>   	ret = radeon_gem_object_create(rdev, aligned_size, 0,
>   				       RADEON_GEM_DOMAIN_VRAM,
> @@ -151,7 +155,7 @@ static int radeonfb_create_pinned_object(struct radeon_fbdev *rfbdev,
>   	if (tiling_flags) {
>   		ret = radeon_bo_set_tiling_flags(rbo,
>   						 tiling_flags | RADEON_TILING_SURFACE,
> -						 mode_cmd->pitch);
> +						 mode_cmd->pitches[0]);
>   		if (ret)
>   			dev_err(rdev->dev, "FB failed to set tiling flags\n");
>   	}
> @@ -187,7 +191,7 @@ static int radeonfb_create(struct radeon_fbdev *rfbdev,
>   	struct radeon_device *rdev = rfbdev->rdev;
>   	struct fb_info *info;
>   	struct drm_framebuffer *fb = NULL;
> -	struct drm_mode_fb_cmd mode_cmd;
> +	struct drm_mode_fb_cmd2 mode_cmd;
>   	struct drm_gem_object *gobj = NULL;
>   	struct radeon_bo *rbo = NULL;
>   	struct device *device =&rdev->pdev->dev;
> @@ -201,8 +205,8 @@ static int radeonfb_create(struct radeon_fbdev *rfbdev,
>   	if ((sizes->surface_bpp == 24)&&  ASIC_IS_AVIVO(rdev))
>   		sizes->surface_bpp = 32;
>
> -	mode_cmd.bpp = sizes->surface_bpp;
> -	mode_cmd.depth = sizes->surface_depth;
> +	mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp,
> +							  sizes->surface_depth);
>
>   	ret = radeonfb_create_pinned_object(rfbdev,&mode_cmd,&gobj);
>   	rbo = gem_to_radeon_bo(gobj);
> diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h
> index 68820f5..227f595 100644
> --- a/drivers/gpu/drm/radeon/radeon_mode.h
> +++ b/drivers/gpu/drm/radeon/radeon_mode.h
> @@ -644,7 +644,7 @@ extern void radeon_crtc_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green
>   				     u16 *blue, int regno);
>   void radeon_framebuffer_init(struct drm_device *dev,
>   			     struct radeon_framebuffer *rfb,
> -			     struct drm_mode_fb_cmd *mode_cmd,
> +			     struct drm_mode_fb_cmd2 *mode_cmd,
>   			     struct drm_gem_object *obj);
>
>   int radeonfb_remove(struct drm_device *dev, struct drm_framebuffer *fb);
> diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
> index 1a4c84c..2a1b802 100644
> --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
> +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
> @@ -839,7 +839,7 @@ out_err1:
>
>   static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev,
>   						 struct drm_file *file_priv,
> -						 struct drm_mode_fb_cmd *mode_cmd)
> +						 struct drm_mode_fb_cmd2 *mode_cmd)
>   {
>   	struct vmw_private *dev_priv = vmw_priv(dev);
>   	struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
> diff --git a/drivers/staging/gma500/framebuffer.c b/drivers/staging/gma500/framebuffer.c
> index ebfde13..85f47d5 100644
> --- a/drivers/staging/gma500/framebuffer.c
> +++ b/drivers/staging/gma500/framebuffer.c
> @@ -487,7 +487,7 @@ out_err1:
>    */
>   static struct drm_framebuffer *psb_user_framebuffer_create
>   			(struct drm_device *dev, struct drm_file *filp,
> -			 struct drm_mode_fb_cmd *cmd)
> +			 struct drm_mode_fb_cmd2 *cmd)
>   {
>   	struct gtt_range *r;
>   	struct drm_gem_object *obj;
> diff --git a/include/drm/drm.h b/include/drm/drm.h
> index 2897967..49d94ed 100644
> --- a/include/drm/drm.h
> +++ b/include/drm/drm.h
> @@ -717,6 +717,7 @@ struct drm_get_cap {
>   #define DRM_IOCTL_MODE_GETPLANERESOURCES DRM_IOWR(0xB5, struct drm_mode_get_plane_res)
>   #define DRM_IOCTL_MODE_GETPLANE	DRM_IOWR(0xB6, struct drm_mode_get_plane)
>   #define DRM_IOCTL_MODE_SETPLANE	DRM_IOWR(0xB7, struct drm_mode_set_plane)
> +#define DRM_IOCTL_MODE_ADDFB2		DRM_IOWR(0xB8, struct drm_mode_fb_cmd2)
>
>   /**
>    * Device specific ioctls should only be in their respective headers
> diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
> index b4519f8..f65ec08 100644
> --- a/include/drm/drm_crtc.h
> +++ b/include/drm/drm_crtc.h
> @@ -29,6 +29,7 @@
>   #include<linux/spinlock.h>
>   #include<linux/types.h>
>   #include<linux/idr.h>
> +#include<linux/videodev2.h>  /* for plane formats */
>
>   #include<linux/fb.h>
>
> @@ -246,6 +247,7 @@ struct drm_framebuffer {
>   	unsigned int depth;
>   	int bits_per_pixel;
>   	int flags;
> +	uint32_t pixel_format; /* fourcc format */
>   	struct list_head filp_head;
>   	/* if you are using the helper */
>   	void *helper_private;
> @@ -620,7 +622,7 @@ struct drm_mode_set {
>    * struct drm_mode_config_funcs - configure CRTCs for a given screen layout
>    */
>   struct drm_mode_config_funcs {
> -	struct drm_framebuffer *(*fb_create)(struct drm_device *dev, struct drm_file *file_priv, struct drm_mode_fb_cmd *mode_cmd);
> +	struct drm_framebuffer *(*fb_create)(struct drm_device *dev, struct drm_file *file_priv, struct drm_mode_fb_cmd2 *mode_cmd);
>   	void (*output_poll_changed)(struct drm_device *dev);
>   };
>
> @@ -838,6 +840,9 @@ extern int drm_mode_cursor_ioctl(struct drm_device *dev,
>   				void *data, struct drm_file *file_priv);
>   extern int drm_mode_addfb(struct drm_device *dev,
>   			  void *data, struct drm_file *file_priv);
> +extern int drm_mode_addfb2(struct drm_device *dev,
> +			   void *data, struct drm_file *file_priv);
> +extern uint32_t drm_mode_legacy_fb_format(uint32_t bpp, uint32_t depth);
>   extern int drm_mode_rmfb(struct drm_device *dev,
>   			 void *data, struct drm_file *file_priv);
>   extern int drm_mode_getfb(struct drm_device *dev,
> diff --git a/include/drm/drm_crtc_helper.h b/include/drm/drm_crtc_helper.h
> index 73b0712..b4abb33 100644
> --- a/include/drm/drm_crtc_helper.h
> +++ b/include/drm/drm_crtc_helper.h
> @@ -116,8 +116,10 @@ extern bool drm_helper_encoder_in_use(struct drm_encoder *encoder);
>
>   extern void drm_helper_connector_dpms(struct drm_connector *connector, int mode);
>
> +extern void drm_helper_get_fb_bpp_depth(uint32_t format, unsigned int *depth,
> +					int *bpp);
>   extern int drm_helper_mode_fill_fb_struct(struct drm_framebuffer *fb,
> -					  struct drm_mode_fb_cmd *mode_cmd);
> +					  struct drm_mode_fb_cmd2 *mode_cmd);
>
>   static inline void drm_crtc_helper_add(struct drm_crtc *crtc,
>   				       const struct drm_crtc_helper_funcs *funcs)
> diff --git a/include/drm/drm_mode.h b/include/drm/drm_mode.h
> index 07711b0..69f8ece 100644
> --- a/include/drm/drm_mode.h
> +++ b/include/drm/drm_mode.h
> @@ -27,6 +27,8 @@
>   #ifndef _DRM_MODE_H
>   #define _DRM_MODE_H
>
> +#include<linux/videodev2.h>
> +
>   #define DRM_DISPLAY_INFO_LEN	32
>   #define DRM_CONNECTOR_NAME_LEN	32
>   #define DRM_DISPLAY_MODE_LEN	32
> @@ -262,6 +264,30 @@ struct drm_mode_fb_cmd {
>   	__u32 handle;
>   };
>
> +struct drm_mode_fb_cmd2 {
> +	__u32 fb_id;
> +	__u32 width, height;
> +	__u32 pixel_format; /* fourcc code from videodev2.h */
> +
> +	/*
> +	 * In case of planar formats, this ioctl allows one
> +	 * buffer object with offets and pitches per plane.
> +	 * The pitch and offset order is dictated by the fourcc,
> +	 * e.g. NV12 (http://fourcc.org/yuv.php#NV12) is described as:
> +	 *
> +	 *   YUV 4:2:0 image with a plane of 8 bit Y samples
> +	 *   followed by an interleaved U/V plane containing
> +	 *   8 bit 2x2 subsampled colour difference samples.
> +	 *
> +	 * So it would consist of Y as offset[0] and UV as
> +	 * offeset[1].  Note that offset[0] will generally
> +	 * be 0.
> +	 */
> +	__u32 handle;
> +	__u32 pitches[4]; /* pitch for each plane */
> +	__u32 offsets[4]; /* offset of each plane */
> +};
> +
>   #define DRM_MODE_FB_DIRTY_ANNOTATE_COPY 0x01
>   #define DRM_MODE_FB_DIRTY_ANNOTATE_FILL 0x02
>   #define DRM_MODE_FB_DIRTY_FLAGS         0x03
> diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
> index fca24cc..6da4ab4 100644
> --- a/include/linux/videodev2.h
> +++ b/include/linux/videodev2.h
> @@ -412,6 +412,7 @@ struct v4l2_pix_format {
>   #define V4L2_PIX_FMT_KONICA420  v4l2_fourcc('K', 'O', 'N', 'I') /* YUV420 planar in blocks of 256 pixels */
>   #define V4L2_PIX_FMT_JPGL	v4l2_fourcc('J', 'P', 'G', 'L') /* JPEG-Lite */
>   #define V4L2_PIX_FMT_SE401      v4l2_fourcc('S', '4', '0', '1') /* se401 janggu compressed rgb */
> +#define V4L2_PIX_FMT_INTC_RGB30	v4l2_fourcc('R', 'G', 'B', '0') /* RGB x:10:10:10 */
>
>   /*
>    *	F O R M A T   E N U M E R A T I O N

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH 1/5] drm: add plane support
  2011-11-04  2:22   ` Joonyoung Shim
@ 2011-11-04 14:10     ` Jesse Barnes
  0 siblings, 0 replies; 32+ messages in thread
From: Jesse Barnes @ 2011-11-04 14:10 UTC (permalink / raw)
  To: Joonyoung Shim; +Cc: intel-gfx, dri-devel, rob.clark


[-- Attachment #1.1: Type: text/plain, Size: 741 bytes --]

On Fri, 04 Nov 2011 11:22:10 +0900
Joonyoung Shim <jy0922.shim@samsung.com> wrote:
> > +struct drm_plane {
> > +	struct drm_device *dev;
> > +	struct device kdev;
> > +	struct device_attribute *attr;
> > +	struct list_head head;
> > +
> > +	struct drm_mode_object base;
> > +
> > +	uint32_t possible_crtcs;
> > +	uint32_t *format_types;
> > +	uint32_t format_count;
> > +
> > +	struct drm_crtc *crtc;
> > +	struct drm_framebuffer *fb;
> 
> Where are crtc and fb of struct drm_plane assigned?
> First, i did it in device specific update_plane, but can do in
> drm_mode_setplane?

Yeah it should probably be done in setplane if there's no error.  Fixed.

Thanks,
-- 
Jesse Barnes, Intel Open Source Technology Center

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

[-- Attachment #2: Type: text/plain, Size: 159 bytes --]

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH 2/5] drm: add an fb creation ioctl that takes a pixel format
  2011-11-04  7:34   ` Joonyoung Shim
@ 2011-11-04 14:13     ` Jesse Barnes
  0 siblings, 0 replies; 32+ messages in thread
From: Jesse Barnes @ 2011-11-04 14:13 UTC (permalink / raw)
  To: Joonyoung Shim; +Cc: intel-gfx, dri-devel, rob.clark


[-- Attachment #1.1: Type: text/plain, Size: 607 bytes --]

On Fri, 04 Nov 2011 16:34:22 +0900
Joonyoung Shim <jy0922.shim@samsung.com> wrote:

> > +	case V4L2_PIX_FMT_RGB24:
> > +		*depth = 24;
> > +		*bpp = 24;
> > +		break;  
> 
> In the depth = 24 and bpp = 32 case also the pixed_format is
> V4L2_PIX_FMT_RGB24, but above function cannot detect it.

Oh that's a mistake on my part.  RGB24 is generally bpp=32.  I'll fix
that.

This is just a compatibility function, so it only needs to handle cases
used by current code.  I expect future code to use the fourcc values
directly.

Thanks,
-- 
Jesse Barnes, Intel Open Source Technology Center

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

[-- Attachment #2: Type: text/plain, Size: 159 bytes --]

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH 2/5] drm: add an fb creation ioctl that takes a pixel format
       [not found]   ` <CAAQKjZPhqYdMAUkbCbc68muPLN7azuVr0yod7hFC=i+MigwNhw@mail.gmail.com>
@ 2011-11-07 16:12     ` Jesse Barnes
  2011-11-07 17:02       ` Rob Clark
  0 siblings, 1 reply; 32+ messages in thread
From: Jesse Barnes @ 2011-11-07 16:12 UTC (permalink / raw)
  To: InKi Dae, dri-devel


[-- Attachment #1.1: Type: text/plain, Size: 1854 bytes --]

On Mon, 7 Nov 2011 23:55:02 +0900
InKi Dae <daeinki@gmail.com> wrote:
> > +struct drm_mode_fb_cmd2 {
> > +       __u32 fb_id;
> > +       __u32 width, height;
> > +       __u32 pixel_format; /* fourcc code from videodev2.h */
> > +
> > +       /*
> > +        * In case of planar formats, this ioctl allows one
> > +        * buffer object with offets and pitches per plane.
> > +        * The pitch and offset order is dictated by the fourcc,
> > +        * e.g. NV12 (http://fourcc.org/yuv.php#NV12) is described as:
> > +        *
> > +        *   YUV 4:2:0 image with a plane of 8 bit Y samples
> > +        *   followed by an interleaved U/V plane containing
> > +        *   8 bit 2x2 subsampled colour difference samples.
> > +        *
> > +        * So it would consist of Y as offset[0] and UV as
> > +        * offeset[1].  Note that offset[0] will generally
> > +        * be 0.
> > +        */
> > +       __u32 handle;
> > +       __u32 pitches[4]; /* pitch for each plane */
> > +       __u32 offsets[4]; /* offset of each plane */
> > +};
> 
> I think that it doesn't pitches[] and offsets[] because we can
> calulate pitch and offset per plane in kernel side through pixel
> format information from user. (PS. pixel format has unique value) I
> think it's good to remove them if unnecessary. there could be my
> missing point. so  Rob, could you please tell me about why do you need
> them.?

Daniel seemed to think that some of the formats might have ambiguous
pitches or offsets, so being able to specify one for each possible
component seems like a good idea.

Also, for planar formats packed into a single buffer object handle
(through driver specific multiplexing or non-zero offsets), individual
pitches and offsets may be required.

-- 
Jesse Barnes, Intel Open Source Technology Center

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

[-- Attachment #2: Type: text/plain, Size: 159 bytes --]

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH 2/5] drm: add an fb creation ioctl that takes a pixel format
  2011-11-07 16:12     ` Jesse Barnes
@ 2011-11-07 17:02       ` Rob Clark
  0 siblings, 0 replies; 32+ messages in thread
From: Rob Clark @ 2011-11-07 17:02 UTC (permalink / raw)
  To: Jesse Barnes; +Cc: dri-devel

On Mon, Nov 7, 2011 at 10:12 AM, Jesse Barnes <jbarnes@virtuousgeek.org> wrote:
> On Mon, 7 Nov 2011 23:55:02 +0900
> InKi Dae <daeinki@gmail.com> wrote:
>> > +struct drm_mode_fb_cmd2 {
>> > +       __u32 fb_id;
>> > +       __u32 width, height;
>> > +       __u32 pixel_format; /* fourcc code from videodev2.h */
>> > +
>> > +       /*
>> > +        * In case of planar formats, this ioctl allows one
>> > +        * buffer object with offets and pitches per plane.
>> > +        * The pitch and offset order is dictated by the fourcc,
>> > +        * e.g. NV12 (http://fourcc.org/yuv.php#NV12) is described as:
>> > +        *
>> > +        *   YUV 4:2:0 image with a plane of 8 bit Y samples
>> > +        *   followed by an interleaved U/V plane containing
>> > +        *   8 bit 2x2 subsampled colour difference samples.
>> > +        *
>> > +        * So it would consist of Y as offset[0] and UV as
>> > +        * offeset[1].  Note that offset[0] will generally
>> > +        * be 0.
>> > +        */
>> > +       __u32 handle;
>> > +       __u32 pitches[4]; /* pitch for each plane */
>> > +       __u32 offsets[4]; /* offset of each plane */
>> > +};
>>
>> I think that it doesn't pitches[] and offsets[] because we can
>> calulate pitch and offset per plane in kernel side through pixel
>> format information from user. (PS. pixel format has unique value) I
>> think it's good to remove them if unnecessary. there could be my
>> missing point. so  Rob, could you please tell me about why do you need
>> them.?

yes, mainly for planar formats packed in a single buffer object..  But
then planar formats in multiple buffer objects, you'd also need
potentially a pitch for each bo, so I guess that is sort of the same
thing.

In practice, maybe it only matters for 3-plane formats like I420...
2-plane formats like NV12 with U/V interleaved end up having the same
width in the chroma plane as luma, and so (at least in all the cases I
have seen) they have the same pitch.  Still, I420 is a common format,
so makes sense to leave enough information in the interface for this
to work.

BR,
-R

> Daniel seemed to think that some of the formats might have ambiguous
> pitches or offsets, so being able to specify one for each possible
> component seems like a good idea.
>
> Also, for planar formats packed into a single buffer object handle
> (through driver specific multiplexing or non-zero offsets), individual
> pitches and offsets may be required.
>
> --
> Jesse Barnes, Intel Open Source Technology Center
>
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel
>
>

^ permalink raw reply	[flat|nested] 32+ messages in thread

* [PATCH] DRM planes
@ 2011-11-07 18:02 Jesse Barnes
  0 siblings, 0 replies; 32+ messages in thread
From: Jesse Barnes @ 2011-11-07 18:02 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx, rob.clark

Ok this one includes all the minor feedback from last week, and should
satisfy Daniel and Jakob enough to get their Reviewed-bys.

You can ignore the final patch in the series; it's a WIP power saving
feature, but the other ones are working well here.

Thanks,
Jesse

^ permalink raw reply	[flat|nested] 32+ messages in thread

end of thread, other threads:[~2011-11-07 18:02 UTC | newest]

Thread overview: 32+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-11-02 20:03 [PATCH] DRM planes Jesse Barnes
2011-11-02 20:03 ` [PATCH 1/5] drm: add plane support Jesse Barnes
2011-11-02 22:33   ` Jesse Barnes
2011-11-03 18:21     ` Jesse Barnes
2011-11-03 22:48       ` Jesse Barnes
2011-11-03 22:56         ` Daniel Vetter
2011-11-04  2:22   ` Joonyoung Shim
2011-11-04 14:10     ` Jesse Barnes
2011-11-02 20:03 ` [PATCH 2/5] drm: add an fb creation ioctl that takes a pixel format Jesse Barnes
2011-11-03 18:22   ` Jesse Barnes
2011-11-04  7:34   ` Joonyoung Shim
2011-11-04 14:13     ` Jesse Barnes
     [not found]   ` <CAAQKjZPhqYdMAUkbCbc68muPLN7azuVr0yod7hFC=i+MigwNhw@mail.gmail.com>
2011-11-07 16:12     ` Jesse Barnes
2011-11-07 17:02       ` Rob Clark
2011-11-02 20:03 ` [PATCH 3/5] drm/i915: rename existing overlay support to "legacy" Jesse Barnes
2011-11-03 18:22   ` Jesse Barnes
2011-11-02 20:03 ` [PATCH 4/5] drm/i915: add SNB and IVB video sprite support Jesse Barnes
2011-11-03 18:22   ` Jesse Barnes
2011-11-04  2:29   ` [Intel-gfx] " Lan, Hai
2011-11-02 20:03 ` [PATCH 5/5] drm/i915: add destination color key support Jesse Barnes
2011-11-03 18:23   ` Jesse Barnes
2011-11-03 14:11 ` [PATCH] DRM planes Daniel Vetter
2011-11-03 15:12   ` Jesse Barnes
2011-11-03 17:29     ` Daniel Vetter
2011-11-03 17:36       ` Jesse Barnes
2011-11-03 18:55         ` Rob Clark
2011-11-03 19:14           ` Jesse Barnes
2011-11-03 17:47   ` Alan Cox
2011-11-03 18:58     ` Daniel Vetter
2011-11-03 22:20       ` Alan Cox
2011-11-03 22:24         ` Jesse Barnes
2011-11-07 18:02 Jesse Barnes

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.