All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/2] drm: add plane support
@ 2011-11-08 21:18 Jesse Barnes
  2011-11-08 21:18 ` [PATCH 2/2] drm: add an fb creation ioctl that takes a pixel format Jesse Barnes
                   ` (2 more replies)
  0 siblings, 3 replies; 17+ messages in thread
From: Jesse Barnes @ 2011-11-08 21:18 UTC (permalink / raw)
  To: dri-devel

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.

Acked-by: Alan Cox <alan@lxorguk.ukuu.org.uk>
Reviewed-by: Rob Clark <rob.clark@linaro.org>
Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
---
 drivers/gpu/drm/drm_crtc.c |  257 +++++++++++++++++++++++++++++++++++++++++++-
 drivers/gpu/drm/drm_drv.c  |    3 +
 include/drm/drm.h          |    3 +
 include/drm/drm_crtc.h     |   75 +++++++++++++-
 include/drm/drm_mode.h     |   33 ++++++
 5 files changed, 368 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index fe738f0..804ef12 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,50 @@ void drm_encoder_cleanup(struct drm_encoder *encoder)
 }
 EXPORT_SYMBOL(drm_encoder_cleanup);
 
+int 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 -ENOMEM;
+	}
+
+	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);
+
+	return 0;
+}
+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 +920,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 +997,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 +1022,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 +1526,197 @@ 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 = -ENOENT;
+		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 = -ENOENT;
+		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 = -ENOENT;
+		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 = -ENOENT;
+		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_w, plane_req->src_h);
+	if (!ret) {
+		plane->crtc = crtc;
+		plane->fb = fb;
+	}
+
+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 +1939,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..e20867e 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,62 @@ 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
+ * @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 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 +647,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 +701,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 +721,13 @@ extern void drm_encoder_init(struct drm_device *dev,
 			     const struct drm_encoder_funcs *funcs,
 			     int encoder_type);
 
+extern int 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 +821,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] 17+ messages in thread

* [PATCH 2/2] drm: add an fb creation ioctl that takes a pixel format
  2011-11-08 21:18 [PATCH 1/2] drm: add plane support Jesse Barnes
@ 2011-11-08 21:18 ` Jesse Barnes
  2011-11-09 13:25   ` InKi Dae
                     ` (2 more replies)
  2011-11-08 21:26 ` [PATCH 1/2] drm: add plane support Chris Wilson
  2011-11-09 10:55 ` [PATCH 1/5] " Joonyoung Shim
  2 siblings, 3 replies; 17+ messages in thread
From: Jesse Barnes @ 2011-11-08 21:18 UTC (permalink / raw)
  To: dri-devel

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.  Implement the fb creation hooks in terms of the
new mode_fb_cmd2 using helpers where the old bpp/depth values are
needed.

Acked-by: Alan Cox <alan@lxorguk.ukuu.org.uk>
Reviewed-by: Rob Clark <rob.clark@linaro.org>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
---
 drivers/gpu/drm/drm_crtc.c                |  108 +++++++++++++++++++++++++++-
 drivers/gpu/drm/drm_crtc_helper.c         |   50 ++++++++++++-
 drivers/gpu/drm/drm_drv.c                 |    1 +
 drivers/gpu/drm/i915/intel_display.c      |   36 +++++-----
 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/nouveau/nouveau_fb.h      |    2 +-
 drivers/gpu/drm/nouveau/nouveau_fbcon.c   |   13 ++--
 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       |   22 ++++--
 drivers/gpu/drm/vmwgfx/vmwgfx_kms.h       |    1 +
 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                    |   28 +++++++-
 include/linux/videodev2.h                 |    1 +
 20 files changed, 256 insertions(+), 61 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 804ef12..39cccb4 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -1910,6 +1910,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
@@ -1930,7 +1966,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;
@@ -1951,9 +2054,6 @@ int drm_mode_addfb(struct drm_device *dev,
 
 	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");
diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c
index f236644..68011bb 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 = 32;
+		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..aae7b03 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;
@@ -7581,21 +7581,23 @@ 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->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/nouveau/nouveau_fb.h b/drivers/gpu/drm/nouveau/nouveau_fb.h
index 95c843e..f4dd301 100644
--- a/drivers/gpu/drm/nouveau/nouveau_fb.h
+++ b/drivers/gpu/drm/nouveau/nouveau_fb.h
@@ -45,5 +45,5 @@ nouveau_framebuffer(struct drm_framebuffer *fb)
 extern const struct drm_mode_config_funcs nouveau_mode_config_funcs;
 
 int nouveau_framebuffer_init(struct drm_device *dev, struct nouveau_framebuffer *nouveau_fb,
-			     struct drm_mode_fb_cmd *mode_cmd, struct nouveau_bo *nvbo);
+			     struct drm_mode_fb_cmd2 *mode_cmd, struct nouveau_bo *nvbo);
 #endif /* __NOUVEAU_FB_H__ */
diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c
index 14a8627..d663065 100644
--- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c
+++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c
@@ -281,7 +281,7 @@ nouveau_fbcon_create(struct nouveau_fbdev *nfbdev,
 	struct nouveau_framebuffer *nouveau_fb;
 	struct nouveau_channel *chan;
 	struct nouveau_bo *nvbo;
-	struct drm_mode_fb_cmd mode_cmd;
+	struct drm_mode_fb_cmd2 mode_cmd;
 	struct pci_dev *pdev = dev->pdev;
 	struct device *device = &pdev->dev;
 	int size, ret;
@@ -289,12 +289,13 @@ nouveau_fbcon_create(struct nouveau_fbdev *nfbdev,
 	mode_cmd.width = sizes->surface_width;
 	mode_cmd.height = sizes->surface_height;
 
-	mode_cmd.bpp = sizes->surface_bpp;
-	mode_cmd.pitch = mode_cmd.width * (mode_cmd.bpp >> 3);
-	mode_cmd.pitch = roundup(mode_cmd.pitch, 256);
-	mode_cmd.depth = sizes->surface_depth;
+	mode_cmd.pitches[0] = mode_cmd.width * (sizes->surface_bpp >> 3);
+	mode_cmd.pitches[0] = roundup(mode_cmd.pitches[0], 256);
 
-	size = mode_cmd.pitch * mode_cmd.height;
+	mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp,
+							  sizes->surface_depth);
+
+	size = mode_cmd.pitches[0] * mode_cmd.height;
 	size = roundup(size, PAGE_SIZE);
 
 	ret = nouveau_gem_new(dev, size, 0, NOUVEAU_GEM_DOMAIN_VRAM,
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..61a030c 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_cmd2)
 {
 	struct vmw_private *dev_priv = vmw_priv(dev);
 	struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
@@ -982,16 +982,24 @@ static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev,
 	struct vmw_surface *surface = NULL;
 	struct vmw_dma_buffer *bo = NULL;
 	struct ttm_base_object *user_obj;
+	struct drm_mode_fb_cmd mode_cmd;
 	u64 required_size;
 	int ret;
 
+	mode_cmd.width = mode_cmd2->width;
+	mode_cmd.height = mode_cmd2->height;
+	mode_cmd.pitch = mode_cmd2->pitches[0];
+	mode_cmd.handle = mode_cmd2->handle;
+	drm_helper_get_fb_bpp_depth(mode_cmd2->pixel_format, &mode_cmd.depth,
+				    &mode_cmd.bpp);
+
 	/**
 	 * This code should be conditioned on Screen Objects not being used.
 	 * If screen objects are used, we can allocate a GMR to hold the
 	 * requested framebuffer.
 	 */
 
-	required_size = mode_cmd->pitch * mode_cmd->height;
+	required_size = mode_cmd.pitch * mode_cmd.height;
 	if (unlikely(required_size > (u64) dev_priv->vram_size)) {
 		DRM_ERROR("VRAM size is too small for requested mode.\n");
 		return NULL;
@@ -1006,7 +1014,7 @@ static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev,
 	 * command stream using user-space handles.
 	 */
 
-	user_obj = ttm_base_object_lookup(tfile, mode_cmd->handle);
+	user_obj = ttm_base_object_lookup(tfile, mode_cmd.handle);
 	if (unlikely(user_obj == NULL)) {
 		DRM_ERROR("Could not locate requested kms frame buffer.\n");
 		return ERR_PTR(-ENOENT);
@@ -1017,7 +1025,7 @@ static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev,
 	 */
 
 	ret = vmw_user_surface_lookup_handle(dev_priv, tfile,
-					     mode_cmd->handle, &surface);
+					     mode_cmd.handle, &surface);
 	if (ret)
 		goto try_dmabuf;
 
@@ -1025,7 +1033,7 @@ static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev,
 		goto err_not_scanout;
 
 	ret = vmw_kms_new_framebuffer_surface(dev_priv, file_priv, surface,
-					      &vfb, mode_cmd);
+					      &vfb, &mode_cmd);
 
 	/* vmw_user_surface_lookup takes one ref so does new_fb */
 	vmw_surface_unreference(&surface);
@@ -1041,14 +1049,14 @@ static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev,
 try_dmabuf:
 	DRM_INFO("%s: trying buffer\n", __func__);
 
-	ret = vmw_user_dmabuf_lookup(tfile, mode_cmd->handle, &bo);
+	ret = vmw_user_dmabuf_lookup(tfile, mode_cmd.handle, &bo);
 	if (ret) {
 		DRM_ERROR("failed to find buffer: %i\n", ret);
 		return ERR_PTR(-ENOENT);
 	}
 
 	ret = vmw_kms_new_framebuffer_dmabuf(dev_priv, bo, &vfb,
-					     mode_cmd);
+					     &mode_cmd);
 
 	/* vmw_user_dmabuf_lookup takes one ref so does new_fb */
 	vmw_dmabuf_unreference(&bo);
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
index db0b901..e199adf 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
@@ -29,6 +29,7 @@
 #define VMWGFX_KMS_H_
 
 #include "drmP.h"
+#include "drm_crtc_helper.h"
 #include "vmwgfx_drv.h"
 
 #define VMWGFX_NUM_DISPLAY_UNITS 8
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 e20867e..84db125 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;
@@ -619,7 +621,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);
 };
 
@@ -837,6 +839,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..3cfa160 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
@@ -136,7 +138,6 @@ struct drm_mode_set_plane {
 };
 
 struct drm_mode_get_plane {
-	__u64 format_type_ptr;
 	__u32 plane_id;
 
 	__u32 crtc_id;
@@ -146,6 +147,7 @@ struct drm_mode_get_plane {
 	__u32 gamma_size;
 
 	__u32 count_format_types;
+	__u64 format_type_ptr;
 };
 
 struct drm_mode_get_plane_res {
@@ -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] 17+ messages in thread

* Re: [PATCH 1/2] drm: add plane support
  2011-11-08 21:18 [PATCH 1/2] drm: add plane support Jesse Barnes
  2011-11-08 21:18 ` [PATCH 2/2] drm: add an fb creation ioctl that takes a pixel format Jesse Barnes
@ 2011-11-08 21:26 ` Chris Wilson
  2011-11-09 10:55 ` [PATCH 1/5] " Joonyoung Shim
  2 siblings, 0 replies; 17+ messages in thread
From: Chris Wilson @ 2011-11-08 21:26 UTC (permalink / raw)
  To: Jesse Barnes, dri-devel

On Tue,  8 Nov 2011 13:18:33 -0800, 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.
> 
> Acked-by: Alan Cox <alan@lxorguk.ukuu.org.uk>
> Reviewed-by: Rob Clark <rob.clark@linaro.org>
> Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>

Thanks for ammending the errors, fwiw
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
-Chris

-- 
Chris Wilson, Intel Open Source Technology Centre

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

* Re: [PATCH 1/5] drm: add plane support
  2011-11-08 21:18 [PATCH 1/2] drm: add plane support Jesse Barnes
  2011-11-08 21:18 ` [PATCH 2/2] drm: add an fb creation ioctl that takes a pixel format Jesse Barnes
  2011-11-08 21:26 ` [PATCH 1/2] drm: add plane support Chris Wilson
@ 2011-11-09 10:55 ` Joonyoung Shim
  2 siblings, 0 replies; 17+ messages in thread
From: Joonyoung Shim @ 2011-11-09 10:55 UTC (permalink / raw)
  To: Jesse Barnes; +Cc: dri-devel


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

2011년 11월 9일 수요일에 Jesse Barnes<jbarnes@virtuousgeek.org>님이 작성:
> 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.
>
> Acked-by: Alan Cox <alan@lxorguk.ukuu.org.uk>
> Reviewed-by: Rob Clark <rob.clark@linaro.org>
> Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>

Reviewed-by: Joonyoung Shim <jy0922.shim@samsung.com>

Thanks.

> ---
>  drivers/gpu/drm/drm_crtc.c |  257
+++++++++++++++++++++++++++++++++++++++++++-
>  drivers/gpu/drm/drm_drv.c  |    3 +
>  include/drm/drm.h          |    3 +
>  include/drm/drm_crtc.h     |   75 +++++++++++++-
>  include/drm/drm_mode.h     |   33 ++++++
>  5 files changed, 368 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
> index fe738f0..804ef12 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,50 @@ void drm_encoder_cleanup(struct drm_encoder *encoder)
>  }
>  EXPORT_SYMBOL(drm_encoder_cleanup);
>
> +int 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 -ENOMEM;
> +       }
> +
> +       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);
> +
> +       return 0;
> +}
> +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 +920,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 +997,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 +1022,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 +1526,197 @@ 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 = -ENOENT;
> +               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 = -ENOENT;
> +               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 = -ENOENT;
> +               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 = -ENOENT;
> +               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_w,
plane_req->src_h);
> +       if (!ret) {
> +               plane->crtc = crtc;
> +               plane->fb = fb;
> +       }
> +
> +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 +1939,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;
> index 8020798..e20867e 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_+extern int drm_pl

-- 
- Joonyoung Shim

[-- Attachment #1.2: Type: text/html, Size: 21392 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] 17+ messages in thread

* Re: [PATCH 2/2] drm: add an fb creation ioctl that takes a pixel format
  2011-11-08 21:18 ` [PATCH 2/2] drm: add an fb creation ioctl that takes a pixel format Jesse Barnes
@ 2011-11-09 13:25   ` InKi Dae
  2011-11-09 14:08     ` Rob Clark
  2011-11-11 10:47   ` Dave Airlie
  2011-11-11 10:56   ` Dave Airlie
  2 siblings, 1 reply; 17+ messages in thread
From: InKi Dae @ 2011-11-09 13:25 UTC (permalink / raw)
  To: Jesse Barnes; +Cc: dri-devel

Hello, all.

I am trying to implement multi planer using your plane patch and I
think it's good but I am still warried about that drm_mode_fb_cmd2
structure has only one handle. I know this handle is sent to
framebuffer module to create new framebuffer. and the framebuffer
would cover entire a image. as you know, the image could be consisted
of one more planes. so I think now drm_mode_fb_cmd2 structure doesn't
support multi planer because it has only one handle. with update_plane
callback, a buffer of the framebuffer would be set to a hardware
overlay. how we could set two planes or three planes to the hardware
overlay? but there might be my missing point so please give me any
comments. in addition, have you been looked into gem flink and open
functions for memory sharing between processes? gem object basically
has one buffer so we can't modify it because of compatibility. so I
think it's right way that gem object manages only one buffer. for such
a reason, maybe drm_mode_fb_cmd2 structure should include one more
handles and plane count. each handle has a gem object to one plane and
plane count means how many planes are requested and when update_plane
callback is called by setplane(), we could set them of the specific
framebuffer to a hardware overlay.

another one, and also I have tried to implement the way sharing the
memory between v4l2 based drivers and drm based drivers through
application and this works fine. this feature had been introduced by
v4l2 framework as user ptr. my way also is similar to it. the
difference is that application could get new gem handle from specific
gem framework of kernel side if user application requests user ptr
import with the user space address(mmaped memory). the new gem handle
means a gem object to the memory mapped to the user space address.
this way makes different applications to be possible to share the
memory between v4l2 based driver and drm based driver. and also this
feature is considered for IOMMU so it would support non continuous
memory also. I will introduce this feature soon.

Thank you,
Inki Dae.

2011/11/9 Jesse Barnes <jbarnes@virtuousgeek.org>:
> 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.  Implement the fb creation hooks in terms of the
> new mode_fb_cmd2 using helpers where the old bpp/depth values are
> needed.
>
> Acked-by: Alan Cox <alan@lxorguk.ukuu.org.uk>
> Reviewed-by: Rob Clark <rob.clark@linaro.org>
> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
> ---
>  drivers/gpu/drm/drm_crtc.c                |  108 +++++++++++++++++++++++++++-
>  drivers/gpu/drm/drm_crtc_helper.c         |   50 ++++++++++++-
>  drivers/gpu/drm/drm_drv.c                 |    1 +
>  drivers/gpu/drm/i915/intel_display.c      |   36 +++++-----
>  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/nouveau/nouveau_fb.h      |    2 +-
>  drivers/gpu/drm/nouveau/nouveau_fbcon.c   |   13 ++--
>  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       |   22 ++++--
>  drivers/gpu/drm/vmwgfx/vmwgfx_kms.h       |    1 +
>  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                    |   28 +++++++-
>  include/linux/videodev2.h                 |    1 +
>  20 files changed, 256 insertions(+), 61 deletions(-)
>
> diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
> index 804ef12..39cccb4 100644
> --- a/drivers/gpu/drm/drm_crtc.c
> +++ b/drivers/gpu/drm/drm_crtc.c
> @@ -1910,6 +1910,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
> @@ -1930,7 +1966,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;
> @@ -1951,9 +2054,6 @@ int drm_mode_addfb(struct drm_device *dev,
>
>        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");
> diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c
> index f236644..68011bb 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 = 32;
> +               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..aae7b03 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;
> @@ -7581,21 +7581,23 @@ 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->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/nouveau/nouveau_fb.h b/drivers/gpu/drm/nouveau/nouveau_fb.h
> index 95c843e..f4dd301 100644
> --- a/drivers/gpu/drm/nouveau/nouveau_fb.h
> +++ b/drivers/gpu/drm/nouveau/nouveau_fb.h
> @@ -45,5 +45,5 @@ nouveau_framebuffer(struct drm_framebuffer *fb)
>  extern const struct drm_mode_config_funcs nouveau_mode_config_funcs;
>
>  int nouveau_framebuffer_init(struct drm_device *dev, struct nouveau_framebuffer *nouveau_fb,
> -                            struct drm_mode_fb_cmd *mode_cmd, struct nouveau_bo *nvbo);
> +                            struct drm_mode_fb_cmd2 *mode_cmd, struct nouveau_bo *nvbo);
>  #endif /* __NOUVEAU_FB_H__ */
> diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c
> index 14a8627..d663065 100644
> --- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c
> +++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c
> @@ -281,7 +281,7 @@ nouveau_fbcon_create(struct nouveau_fbdev *nfbdev,
>        struct nouveau_framebuffer *nouveau_fb;
>        struct nouveau_channel *chan;
>        struct nouveau_bo *nvbo;
> -       struct drm_mode_fb_cmd mode_cmd;
> +       struct drm_mode_fb_cmd2 mode_cmd;
>        struct pci_dev *pdev = dev->pdev;
>        struct device *device = &pdev->dev;
>        int size, ret;
> @@ -289,12 +289,13 @@ nouveau_fbcon_create(struct nouveau_fbdev *nfbdev,
>        mode_cmd.width = sizes->surface_width;
>        mode_cmd.height = sizes->surface_height;
>
> -       mode_cmd.bpp = sizes->surface_bpp;
> -       mode_cmd.pitch = mode_cmd.width * (mode_cmd.bpp >> 3);
> -       mode_cmd.pitch = roundup(mode_cmd.pitch, 256);
> -       mode_cmd.depth = sizes->surface_depth;
> +       mode_cmd.pitches[0] = mode_cmd.width * (sizes->surface_bpp >> 3);
> +       mode_cmd.pitches[0] = roundup(mode_cmd.pitches[0], 256);
>
> -       size = mode_cmd.pitch * mode_cmd.height;
> +       mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp,
> +                                                         sizes->surface_depth);
> +
> +       size = mode_cmd.pitches[0] * mode_cmd.height;
>        size = roundup(size, PAGE_SIZE);
>
>        ret = nouveau_gem_new(dev, size, 0, NOUVEAU_GEM_DOMAIN_VRAM,
> 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..61a030c 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_cmd2)
>  {
>        struct vmw_private *dev_priv = vmw_priv(dev);
>        struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
> @@ -982,16 +982,24 @@ static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev,
>        struct vmw_surface *surface = NULL;
>        struct vmw_dma_buffer *bo = NULL;
>        struct ttm_base_object *user_obj;
> +       struct drm_mode_fb_cmd mode_cmd;
>        u64 required_size;
>        int ret;
>
> +       mode_cmd.width = mode_cmd2->width;
> +       mode_cmd.height = mode_cmd2->height;
> +       mode_cmd.pitch = mode_cmd2->pitches[0];
> +       mode_cmd.handle = mode_cmd2->handle;
> +       drm_helper_get_fb_bpp_depth(mode_cmd2->pixel_format, &mode_cmd.depth,
> +                                   &mode_cmd.bpp);
> +
>        /**
>         * This code should be conditioned on Screen Objects not being used.
>         * If screen objects are used, we can allocate a GMR to hold the
>         * requested framebuffer.
>         */
>
> -       required_size = mode_cmd->pitch * mode_cmd->height;
> +       required_size = mode_cmd.pitch * mode_cmd.height;
>        if (unlikely(required_size > (u64) dev_priv->vram_size)) {
>                DRM_ERROR("VRAM size is too small for requested mode.\n");
>                return NULL;
> @@ -1006,7 +1014,7 @@ static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev,
>         * command stream using user-space handles.
>         */
>
> -       user_obj = ttm_base_object_lookup(tfile, mode_cmd->handle);
> +       user_obj = ttm_base_object_lookup(tfile, mode_cmd.handle);
>        if (unlikely(user_obj == NULL)) {
>                DRM_ERROR("Could not locate requested kms frame buffer.\n");
>                return ERR_PTR(-ENOENT);
> @@ -1017,7 +1025,7 @@ static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev,
>         */
>
>        ret = vmw_user_surface_lookup_handle(dev_priv, tfile,
> -                                            mode_cmd->handle, &surface);
> +                                            mode_cmd.handle, &surface);
>        if (ret)
>                goto try_dmabuf;
>
> @@ -1025,7 +1033,7 @@ static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev,
>                goto err_not_scanout;
>
>        ret = vmw_kms_new_framebuffer_surface(dev_priv, file_priv, surface,
> -                                             &vfb, mode_cmd);
> +                                             &vfb, &mode_cmd);
>
>        /* vmw_user_surface_lookup takes one ref so does new_fb */
>        vmw_surface_unreference(&surface);
> @@ -1041,14 +1049,14 @@ static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev,
>  try_dmabuf:
>        DRM_INFO("%s: trying buffer\n", __func__);
>
> -       ret = vmw_user_dmabuf_lookup(tfile, mode_cmd->handle, &bo);
> +       ret = vmw_user_dmabuf_lookup(tfile, mode_cmd.handle, &bo);
>        if (ret) {
>                DRM_ERROR("failed to find buffer: %i\n", ret);
>                return ERR_PTR(-ENOENT);
>        }
>
>        ret = vmw_kms_new_framebuffer_dmabuf(dev_priv, bo, &vfb,
> -                                            mode_cmd);
> +                                            &mode_cmd);
>
>        /* vmw_user_dmabuf_lookup takes one ref so does new_fb */
>        vmw_dmabuf_unreference(&bo);
> diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
> index db0b901..e199adf 100644
> --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
> +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
> @@ -29,6 +29,7 @@
>  #define VMWGFX_KMS_H_
>
>  #include "drmP.h"
> +#include "drm_crtc_helper.h"
>  #include "vmwgfx_drv.h"
>
>  #define VMWGFX_NUM_DISPLAY_UNITS 8
> 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 e20867e..84db125 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;
> @@ -619,7 +621,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);
>  };
>
> @@ -837,6 +839,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..3cfa160 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
> @@ -136,7 +138,6 @@ struct drm_mode_set_plane {
>  };
>
>  struct drm_mode_get_plane {
> -       __u64 format_type_ptr;
>        __u32 plane_id;
>
>        __u32 crtc_id;
> @@ -146,6 +147,7 @@ struct drm_mode_get_plane {
>        __u32 gamma_size;
>
>        __u32 count_format_types;
> +       __u64 format_type_ptr;
>  };
>
>  struct drm_mode_get_plane_res {
> @@ -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
>
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel
>

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

* Re: [PATCH 2/2] drm: add an fb creation ioctl that takes a pixel format
  2011-11-09 13:25   ` InKi Dae
@ 2011-11-09 14:08     ` Rob Clark
  2011-11-10 14:54       ` InKi Dae
  0 siblings, 1 reply; 17+ messages in thread
From: Rob Clark @ 2011-11-09 14:08 UTC (permalink / raw)
  To: InKi Dae; +Cc: dri-devel

On Wed, Nov 9, 2011 at 7:25 AM, InKi Dae <daeinki@gmail.com> wrote:
> Hello, all.
>
> I am trying to implement multi planer using your plane patch and I
> think it's good but I am still warried about that drm_mode_fb_cmd2
> structure has only one handle. I know this handle is sent to
> framebuffer module to create new framebuffer. and the framebuffer
> would cover entire a image. as you know, the image could be consisted
> of one more planes. so I think now drm_mode_fb_cmd2 structure doesn't
> support multi planer because it has only one handle. with update_plane
> callback, a buffer of the framebuffer would be set to a hardware
> overlay. how we could set two planes or three planes to the hardware
> overlay? but there might be my missing point so please give me any
> comments. in addition, have you been looked into gem flink and open
> functions for memory sharing between processes? gem object basically
> has one buffer so we can't modify it because of compatibility. so I
> think it's right way that gem object manages only one buffer. for such
> a reason, maybe drm_mode_fb_cmd2 structure should include one more
> handles and plane count. each handle has a gem object to one plane and
> plane count means how many planes are requested and when update_plane
> callback is called by setplane(), we could set them of the specific
> framebuffer to a hardware overlay.

The current plan is to add a 3rd ioctl, for adding multi-planar fb..
I guess it is a good thing that I'm not the only one who wants this
:-)

> another one, and also I have tried to implement the way sharing the
> memory between v4l2 based drivers and drm based drivers through
> application and this works fine. this feature had been introduced by
> v4l2 framework as user ptr. my way also is similar to it. the
> difference is that application could get new gem handle from specific
> gem framework of kernel side if user application requests user ptr
> import with the user space address(mmaped memory). the new gem handle
> means a gem object to the memory mapped to the user space address.
> this way makes different applications to be possible to share the
> memory between v4l2 based driver and drm based driver. and also this
> feature is considered for IOMMU so it would support non continuous
> memory also. I will introduce this feature soon.

btw, there was an RFC a little while back for "dmabuf" buffer sharing
mechanism..  the idea would be to export a (for example) GEM buffer to
a dmabuf handle which could be passed in to other devices, including
for example v4l2 (although without necessarily requiring a userspace
mapping)..

http://www.spinics.net/lists/dri-devel/msg15077.html

It sounds like you are looking for a similar thing..

BR,
-R

> Thank you,
> Inki Dae.
>
> 2011/11/9 Jesse Barnes <jbarnes@virtuousgeek.org>:
>> 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.  Implement the fb creation hooks in terms of the
>> new mode_fb_cmd2 using helpers where the old bpp/depth values are
>> needed.
>>
>> Acked-by: Alan Cox <alan@lxorguk.ukuu.org.uk>
>> Reviewed-by: Rob Clark <rob.clark@linaro.org>
>> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
>> ---
>>  drivers/gpu/drm/drm_crtc.c                |  108 +++++++++++++++++++++++++++-
>>  drivers/gpu/drm/drm_crtc_helper.c         |   50 ++++++++++++-
>>  drivers/gpu/drm/drm_drv.c                 |    1 +
>>  drivers/gpu/drm/i915/intel_display.c      |   36 +++++-----
>>  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/nouveau/nouveau_fb.h      |    2 +-
>>  drivers/gpu/drm/nouveau/nouveau_fbcon.c   |   13 ++--
>>  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       |   22 ++++--
>>  drivers/gpu/drm/vmwgfx/vmwgfx_kms.h       |    1 +
>>  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                    |   28 +++++++-
>>  include/linux/videodev2.h                 |    1 +
>>  20 files changed, 256 insertions(+), 61 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
>> index 804ef12..39cccb4 100644
>> --- a/drivers/gpu/drm/drm_crtc.c
>> +++ b/drivers/gpu/drm/drm_crtc.c
>> @@ -1910,6 +1910,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
>> @@ -1930,7 +1966,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;
>> @@ -1951,9 +2054,6 @@ int drm_mode_addfb(struct drm_device *dev,
>>
>>        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");
>> diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c
>> index f236644..68011bb 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 = 32;
>> +               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..aae7b03 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;
>> @@ -7581,21 +7581,23 @@ 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->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/nouveau/nouveau_fb.h b/drivers/gpu/drm/nouveau/nouveau_fb.h
>> index 95c843e..f4dd301 100644
>> --- a/drivers/gpu/drm/nouveau/nouveau_fb.h
>> +++ b/drivers/gpu/drm/nouveau/nouveau_fb.h
>> @@ -45,5 +45,5 @@ nouveau_framebuffer(struct drm_framebuffer *fb)
>>  extern const struct drm_mode_config_funcs nouveau_mode_config_funcs;
>>
>>  int nouveau_framebuffer_init(struct drm_device *dev, struct nouveau_framebuffer *nouveau_fb,
>> -                            struct drm_mode_fb_cmd *mode_cmd, struct nouveau_bo *nvbo);
>> +                            struct drm_mode_fb_cmd2 *mode_cmd, struct nouveau_bo *nvbo);
>>  #endif /* __NOUVEAU_FB_H__ */
>> diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c
>> index 14a8627..d663065 100644
>> --- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c
>> +++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c
>> @@ -281,7 +281,7 @@ nouveau_fbcon_create(struct nouveau_fbdev *nfbdev,
>>        struct nouveau_framebuffer *nouveau_fb;
>>        struct nouveau_channel *chan;
>>        struct nouveau_bo *nvbo;
>> -       struct drm_mode_fb_cmd mode_cmd;
>> +       struct drm_mode_fb_cmd2 mode_cmd;
>>        struct pci_dev *pdev = dev->pdev;
>>        struct device *device = &pdev->dev;
>>        int size, ret;
>> @@ -289,12 +289,13 @@ nouveau_fbcon_create(struct nouveau_fbdev *nfbdev,
>>        mode_cmd.width = sizes->surface_width;
>>        mode_cmd.height = sizes->surface_height;
>>
>> -       mode_cmd.bpp = sizes->surface_bpp;
>> -       mode_cmd.pitch = mode_cmd.width * (mode_cmd.bpp >> 3);
>> -       mode_cmd.pitch = roundup(mode_cmd.pitch, 256);
>> -       mode_cmd.depth = sizes->surface_depth;
>> +       mode_cmd.pitches[0] = mode_cmd.width * (sizes->surface_bpp >> 3);
>> +       mode_cmd.pitches[0] = roundup(mode_cmd.pitches[0], 256);
>>
>> -       size = mode_cmd.pitch * mode_cmd.height;
>> +       mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp,
>> +                                                         sizes->surface_depth);
>> +
>> +       size = mode_cmd.pitches[0] * mode_cmd.height;
>>        size = roundup(size, PAGE_SIZE);
>>
>>        ret = nouveau_gem_new(dev, size, 0, NOUVEAU_GEM_DOMAIN_VRAM,
>> 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..61a030c 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_cmd2)
>>  {
>>        struct vmw_private *dev_priv = vmw_priv(dev);
>>        struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
>> @@ -982,16 +982,24 @@ static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev,
>>        struct vmw_surface *surface = NULL;
>>        struct vmw_dma_buffer *bo = NULL;
>>        struct ttm_base_object *user_obj;
>> +       struct drm_mode_fb_cmd mode_cmd;
>>        u64 required_size;
>>        int ret;
>>
>> +       mode_cmd.width = mode_cmd2->width;
>> +       mode_cmd.height = mode_cmd2->height;
>> +       mode_cmd.pitch = mode_cmd2->pitches[0];
>> +       mode_cmd.handle = mode_cmd2->handle;
>> +       drm_helper_get_fb_bpp_depth(mode_cmd2->pixel_format, &mode_cmd.depth,
>> +                                   &mode_cmd.bpp);
>> +
>>        /**
>>         * This code should be conditioned on Screen Objects not being used.
>>         * If screen objects are used, we can allocate a GMR to hold the
>>         * requested framebuffer.
>>         */
>>
>> -       required_size = mode_cmd->pitch * mode_cmd->height;
>> +       required_size = mode_cmd.pitch * mode_cmd.height;
>>        if (unlikely(required_size > (u64) dev_priv->vram_size)) {
>>                DRM_ERROR("VRAM size is too small for requested mode.\n");
>>                return NULL;
>> @@ -1006,7 +1014,7 @@ static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev,
>>         * command stream using user-space handles.
>>         */
>>
>> -       user_obj = ttm_base_object_lookup(tfile, mode_cmd->handle);
>> +       user_obj = ttm_base_object_lookup(tfile, mode_cmd.handle);
>>        if (unlikely(user_obj == NULL)) {
>>                DRM_ERROR("Could not locate requested kms frame buffer.\n");
>>                return ERR_PTR(-ENOENT);
>> @@ -1017,7 +1025,7 @@ static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev,
>>         */
>>
>>        ret = vmw_user_surface_lookup_handle(dev_priv, tfile,
>> -                                            mode_cmd->handle, &surface);
>> +                                            mode_cmd.handle, &surface);
>>        if (ret)
>>                goto try_dmabuf;
>>
>> @@ -1025,7 +1033,7 @@ static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev,
>>                goto err_not_scanout;
>>
>>        ret = vmw_kms_new_framebuffer_surface(dev_priv, file_priv, surface,
>> -                                             &vfb, mode_cmd);
>> +                                             &vfb, &mode_cmd);
>>
>>        /* vmw_user_surface_lookup takes one ref so does new_fb */
>>        vmw_surface_unreference(&surface);
>> @@ -1041,14 +1049,14 @@ static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev,
>>  try_dmabuf:
>>        DRM_INFO("%s: trying buffer\n", __func__);
>>
>> -       ret = vmw_user_dmabuf_lookup(tfile, mode_cmd->handle, &bo);
>> +       ret = vmw_user_dmabuf_lookup(tfile, mode_cmd.handle, &bo);
>>        if (ret) {
>>                DRM_ERROR("failed to find buffer: %i\n", ret);
>>                return ERR_PTR(-ENOENT);
>>        }
>>
>>        ret = vmw_kms_new_framebuffer_dmabuf(dev_priv, bo, &vfb,
>> -                                            mode_cmd);
>> +                                            &mode_cmd);
>>
>>        /* vmw_user_dmabuf_lookup takes one ref so does new_fb */
>>        vmw_dmabuf_unreference(&bo);
>> diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
>> index db0b901..e199adf 100644
>> --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
>> +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
>> @@ -29,6 +29,7 @@
>>  #define VMWGFX_KMS_H_
>>
>>  #include "drmP.h"
>> +#include "drm_crtc_helper.h"
>>  #include "vmwgfx_drv.h"
>>
>>  #define VMWGFX_NUM_DISPLAY_UNITS 8
>> 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 e20867e..84db125 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;
>> @@ -619,7 +621,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);
>>  };
>>
>> @@ -837,6 +839,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..3cfa160 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
>> @@ -136,7 +138,6 @@ struct drm_mode_set_plane {
>>  };
>>
>>  struct drm_mode_get_plane {
>> -       __u64 format_type_ptr;
>>        __u32 plane_id;
>>
>>        __u32 crtc_id;
>> @@ -146,6 +147,7 @@ struct drm_mode_get_plane {
>>        __u32 gamma_size;
>>
>>        __u32 count_format_types;
>> +       __u64 format_type_ptr;
>>  };
>>
>>  struct drm_mode_get_plane_res {
>> @@ -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
>>
>> _______________________________________________
>> dri-devel mailing list
>> dri-devel@lists.freedesktop.org
>> http://lists.freedesktop.org/mailman/listinfo/dri-devel
>>
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel
>

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

* Re: [PATCH 2/2] drm: add an fb creation ioctl that takes a pixel format
  2011-11-09 14:08     ` Rob Clark
@ 2011-11-10 14:54       ` InKi Dae
  2011-11-10 16:30         ` Rob Clark
  0 siblings, 1 reply; 17+ messages in thread
From: InKi Dae @ 2011-11-10 14:54 UTC (permalink / raw)
  To: Rob Clark; +Cc: dri-devel

2011/11/9 Rob Clark <robdclark@gmail.com>:
> On Wed, Nov 9, 2011 at 7:25 AM, InKi Dae <daeinki@gmail.com> wrote:
>> Hello, all.
>>
>> I am trying to implement multi planer using your plane patch and I
>> think it's good but I am still warried about that drm_mode_fb_cmd2
>> structure has only one handle. I know this handle is sent to
>> framebuffer module to create new framebuffer. and the framebuffer
>> would cover entire a image. as you know, the image could be consisted
>> of one more planes. so I think now drm_mode_fb_cmd2 structure doesn't
>> support multi planer because it has only one handle. with update_plane
>> callback, a buffer of the framebuffer would be set to a hardware
>> overlay. how we could set two planes or three planes to the hardware
>> overlay? but there might be my missing point so please give me any
>> comments. in addition, have you been looked into gem flink and open
>> functions for memory sharing between processes? gem object basically
>> has one buffer so we can't modify it because of compatibility. so I
>> think it's right way that gem object manages only one buffer. for such
>> a reason, maybe drm_mode_fb_cmd2 structure should include one more
>> handles and plane count. each handle has a gem object to one plane and
>> plane count means how many planes are requested and when update_plane
>> callback is called by setplane(), we could set them of the specific
>> framebuffer to a hardware overlay.
>
> The current plan is to add a 3rd ioctl, for adding multi-planar fb..
> I guess it is a good thing that I'm not the only one who wants this
> :-)
>
>> another one, and also I have tried to implement the way sharing the
>> memory between v4l2 based drivers and drm based drivers through
>> application and this works fine. this feature had been introduced by
>> v4l2 framework as user ptr. my way also is similar to it. the
>> difference is that application could get new gem handle from specific
>> gem framework of kernel side if user application requests user ptr
>> import with the user space address(mmaped memory). the new gem handle
>> means a gem object to the memory mapped to the user space address.
>> this way makes different applications to be possible to share the
>> memory between v4l2 based driver and drm based driver. and also this
>> feature is considered for IOMMU so it would support non continuous
>> memory also. I will introduce this feature soon.
>
> btw, there was an RFC a little while back for "dmabuf" buffer sharing
> mechanism..  the idea would be to export a (for example) GEM buffer to
> a dmabuf handle which could be passed in to other devices, including
> for example v4l2 (although without necessarily requiring a userspace
> mapping)..
>
> http://www.spinics.net/lists/dri-devel/msg15077.html
>
> It sounds like you are looking for a similar thing..
>

Hi, Rob.

GEM framework already supports memory sharing way that a object name
created by gem flink is sent to another process and then the process
opens the object name. at that time, the gem framework of kernel side
creates new gem object. and I know that dmabuf is similar to the ION
introduced by Rebecca who is an engineer of Google at least for buffer
sharing way. but is it possible to share the memory region drawing on
only user virtual address mmaped with another process?. for instance,
as you know, v4l2 based driver has request buf feature that the driver
of kernel side allocates the memory regions as user-desired buffer
count and user gets user virtual address with mmap request after quary
buffer request. so we need to share this memory mmaped at here also.
for this, v4l2 based driver has userptr feature that user application
sets user virtual address to userptr structure and then the address is
translated to bus address(physical address without iommu or device
address with iommu) and sets it to hardware. I think it doesn't need
dmabuf if we would use it only for sharing the gem buffer with another
process because GEM framework already can do it. I will try to find
the way that we can use this feature commonly for generic gem
framework. this feature has already been implemented in our specific
gem framework and also tested.

thank you,
Inki dae.


> BR,
> -R
>
>> Thank you,
>> Inki Dae.
>>
>> 2011/11/9 Jesse Barnes <jbarnes@virtuousgeek.org>:
>>> 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.  Implement the fb creation hooks in terms of the
>>> new mode_fb_cmd2 using helpers where the old bpp/depth values are
>>> needed.
>>>
>>> Acked-by: Alan Cox <alan@lxorguk.ukuu.org.uk>
>>> Reviewed-by: Rob Clark <rob.clark@linaro.org>
>>> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
>>> ---
>>>  drivers/gpu/drm/drm_crtc.c                |  108 +++++++++++++++++++++++++++-
>>>  drivers/gpu/drm/drm_crtc_helper.c         |   50 ++++++++++++-
>>>  drivers/gpu/drm/drm_drv.c                 |    1 +
>>>  drivers/gpu/drm/i915/intel_display.c      |   36 +++++-----
>>>  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/nouveau/nouveau_fb.h      |    2 +-
>>>  drivers/gpu/drm/nouveau/nouveau_fbcon.c   |   13 ++--
>>>  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       |   22 ++++--
>>>  drivers/gpu/drm/vmwgfx/vmwgfx_kms.h       |    1 +
>>>  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                    |   28 +++++++-
>>>  include/linux/videodev2.h                 |    1 +
>>>  20 files changed, 256 insertions(+), 61 deletions(-)
>>>
>>> diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
>>> index 804ef12..39cccb4 100644
>>> --- a/drivers/gpu/drm/drm_crtc.c
>>> +++ b/drivers/gpu/drm/drm_crtc.c
>>> @@ -1910,6 +1910,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
>>> @@ -1930,7 +1966,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;
>>> @@ -1951,9 +2054,6 @@ int drm_mode_addfb(struct drm_device *dev,
>>>
>>>        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");
>>> diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c
>>> index f236644..68011bb 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 = 32;
>>> +               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..aae7b03 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;
>>> @@ -7581,21 +7581,23 @@ 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->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/nouveau/nouveau_fb.h b/drivers/gpu/drm/nouveau/nouveau_fb.h
>>> index 95c843e..f4dd301 100644
>>> --- a/drivers/gpu/drm/nouveau/nouveau_fb.h
>>> +++ b/drivers/gpu/drm/nouveau/nouveau_fb.h
>>> @@ -45,5 +45,5 @@ nouveau_framebuffer(struct drm_framebuffer *fb)
>>>  extern const struct drm_mode_config_funcs nouveau_mode_config_funcs;
>>>
>>>  int nouveau_framebuffer_init(struct drm_device *dev, struct nouveau_framebuffer *nouveau_fb,
>>> -                            struct drm_mode_fb_cmd *mode_cmd, struct nouveau_bo *nvbo);
>>> +                            struct drm_mode_fb_cmd2 *mode_cmd, struct nouveau_bo *nvbo);
>>>  #endif /* __NOUVEAU_FB_H__ */
>>> diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c
>>> index 14a8627..d663065 100644
>>> --- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c
>>> +++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c
>>> @@ -281,7 +281,7 @@ nouveau_fbcon_create(struct nouveau_fbdev *nfbdev,
>>>        struct nouveau_framebuffer *nouveau_fb;
>>>        struct nouveau_channel *chan;
>>>        struct nouveau_bo *nvbo;
>>> -       struct drm_mode_fb_cmd mode_cmd;
>>> +       struct drm_mode_fb_cmd2 mode_cmd;
>>>        struct pci_dev *pdev = dev->pdev;
>>>        struct device *device = &pdev->dev;
>>>        int size, ret;
>>> @@ -289,12 +289,13 @@ nouveau_fbcon_create(struct nouveau_fbdev *nfbdev,
>>>        mode_cmd.width = sizes->surface_width;
>>>        mode_cmd.height = sizes->surface_height;
>>>
>>> -       mode_cmd.bpp = sizes->surface_bpp;
>>> -       mode_cmd.pitch = mode_cmd.width * (mode_cmd.bpp >> 3);
>>> -       mode_cmd.pitch = roundup(mode_cmd.pitch, 256);
>>> -       mode_cmd.depth = sizes->surface_depth;
>>> +       mode_cmd.pitches[0] = mode_cmd.width * (sizes->surface_bpp >> 3);
>>> +       mode_cmd.pitches[0] = roundup(mode_cmd.pitches[0], 256);
>>>
>>> -       size = mode_cmd.pitch * mode_cmd.height;
>>> +       mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp,
>>> +                                                         sizes->surface_depth);
>>> +
>>> +       size = mode_cmd.pitches[0] * mode_cmd.height;
>>>        size = roundup(size, PAGE_SIZE);
>>>
>>>        ret = nouveau_gem_new(dev, size, 0, NOUVEAU_GEM_DOMAIN_VRAM,
>>> 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..61a030c 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_cmd2)
>>>  {
>>>        struct vmw_private *dev_priv = vmw_priv(dev);
>>>        struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
>>> @@ -982,16 +982,24 @@ static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev,
>>>        struct vmw_surface *surface = NULL;
>>>        struct vmw_dma_buffer *bo = NULL;
>>>        struct ttm_base_object *user_obj;
>>> +       struct drm_mode_fb_cmd mode_cmd;
>>>        u64 required_size;
>>>        int ret;
>>>
>>> +       mode_cmd.width = mode_cmd2->width;
>>> +       mode_cmd.height = mode_cmd2->height;
>>> +       mode_cmd.pitch = mode_cmd2->pitches[0];
>>> +       mode_cmd.handle = mode_cmd2->handle;
>>> +       drm_helper_get_fb_bpp_depth(mode_cmd2->pixel_format, &mode_cmd.depth,
>>> +                                   &mode_cmd.bpp);
>>> +
>>>        /**
>>>         * This code should be conditioned on Screen Objects not being used.
>>>         * If screen objects are used, we can allocate a GMR to hold the
>>>         * requested framebuffer.
>>>         */
>>>
>>> -       required_size = mode_cmd->pitch * mode_cmd->height;
>>> +       required_size = mode_cmd.pitch * mode_cmd.height;
>>>        if (unlikely(required_size > (u64) dev_priv->vram_size)) {
>>>                DRM_ERROR("VRAM size is too small for requested mode.\n");
>>>                return NULL;
>>> @@ -1006,7 +1014,7 @@ static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev,
>>>         * command stream using user-space handles.
>>>         */
>>>
>>> -       user_obj = ttm_base_object_lookup(tfile, mode_cmd->handle);
>>> +       user_obj = ttm_base_object_lookup(tfile, mode_cmd.handle);
>>>        if (unlikely(user_obj == NULL)) {
>>>                DRM_ERROR("Could not locate requested kms frame buffer.\n");
>>>                return ERR_PTR(-ENOENT);
>>> @@ -1017,7 +1025,7 @@ static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev,
>>>         */
>>>
>>>        ret = vmw_user_surface_lookup_handle(dev_priv, tfile,
>>> -                                            mode_cmd->handle, &surface);
>>> +                                            mode_cmd.handle, &surface);
>>>        if (ret)
>>>                goto try_dmabuf;
>>>
>>> @@ -1025,7 +1033,7 @@ static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev,
>>>                goto err_not_scanout;
>>>
>>>        ret = vmw_kms_new_framebuffer_surface(dev_priv, file_priv, surface,
>>> -                                             &vfb, mode_cmd);
>>> +                                             &vfb, &mode_cmd);
>>>
>>>        /* vmw_user_surface_lookup takes one ref so does new_fb */
>>>        vmw_surface_unreference(&surface);
>>> @@ -1041,14 +1049,14 @@ static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev,
>>>  try_dmabuf:
>>>        DRM_INFO("%s: trying buffer\n", __func__);
>>>
>>> -       ret = vmw_user_dmabuf_lookup(tfile, mode_cmd->handle, &bo);
>>> +       ret = vmw_user_dmabuf_lookup(tfile, mode_cmd.handle, &bo);
>>>        if (ret) {
>>>                DRM_ERROR("failed to find buffer: %i\n", ret);
>>>                return ERR_PTR(-ENOENT);
>>>        }
>>>
>>>        ret = vmw_kms_new_framebuffer_dmabuf(dev_priv, bo, &vfb,
>>> -                                            mode_cmd);
>>> +                                            &mode_cmd);
>>>
>>>        /* vmw_user_dmabuf_lookup takes one ref so does new_fb */
>>>        vmw_dmabuf_unreference(&bo);
>>> diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
>>> index db0b901..e199adf 100644
>>> --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
>>> +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
>>> @@ -29,6 +29,7 @@
>>>  #define VMWGFX_KMS_H_
>>>
>>>  #include "drmP.h"
>>> +#include "drm_crtc_helper.h"
>>>  #include "vmwgfx_drv.h"
>>>
>>>  #define VMWGFX_NUM_DISPLAY_UNITS 8
>>> 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 e20867e..84db125 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;
>>> @@ -619,7 +621,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);
>>>  };
>>>
>>> @@ -837,6 +839,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..3cfa160 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
>>> @@ -136,7 +138,6 @@ struct drm_mode_set_plane {
>>>  };
>>>
>>>  struct drm_mode_get_plane {
>>> -       __u64 format_type_ptr;
>>>        __u32 plane_id;
>>>
>>>        __u32 crtc_id;
>>> @@ -146,6 +147,7 @@ struct drm_mode_get_plane {
>>>        __u32 gamma_size;
>>>
>>>        __u32 count_format_types;
>>> +       __u64 format_type_ptr;
>>>  };
>>>
>>>  struct drm_mode_get_plane_res {
>>> @@ -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
>>>
>>> _______________________________________________
>>> dri-devel mailing list
>>> dri-devel@lists.freedesktop.org
>>> http://lists.freedesktop.org/mailman/listinfo/dri-devel
>>>
>> _______________________________________________
>> dri-devel mailing list
>> dri-devel@lists.freedesktop.org
>> http://lists.freedesktop.org/mailman/listinfo/dri-devel
>>
>

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

* Re: [PATCH 2/2] drm: add an fb creation ioctl that takes a pixel format
  2011-11-10 14:54       ` InKi Dae
@ 2011-11-10 16:30         ` Rob Clark
  2011-11-12  9:14           ` InKi Dae
  0 siblings, 1 reply; 17+ messages in thread
From: Rob Clark @ 2011-11-10 16:30 UTC (permalink / raw)
  To: InKi Dae; +Cc: dri-devel

On Thu, Nov 10, 2011 at 8:54 AM, InKi Dae <daeinki@gmail.com> wrote:
> 2011/11/9 Rob Clark <robdclark@gmail.com>:
>> On Wed, Nov 9, 2011 at 7:25 AM, InKi Dae <daeinki@gmail.com> wrote:
>>> Hello, all.
>>>
>>> I am trying to implement multi planer using your plane patch and I
>>> think it's good but I am still warried about that drm_mode_fb_cmd2
>>> structure has only one handle. I know this handle is sent to
>>> framebuffer module to create new framebuffer. and the framebuffer
>>> would cover entire a image. as you know, the image could be consisted
>>> of one more planes. so I think now drm_mode_fb_cmd2 structure doesn't
>>> support multi planer because it has only one handle. with update_plane
>>> callback, a buffer of the framebuffer would be set to a hardware
>>> overlay. how we could set two planes or three planes to the hardware
>>> overlay? but there might be my missing point so please give me any
>>> comments. in addition, have you been looked into gem flink and open
>>> functions for memory sharing between processes? gem object basically
>>> has one buffer so we can't modify it because of compatibility. so I
>>> think it's right way that gem object manages only one buffer. for such
>>> a reason, maybe drm_mode_fb_cmd2 structure should include one more
>>> handles and plane count. each handle has a gem object to one plane and
>>> plane count means how many planes are requested and when update_plane
>>> callback is called by setplane(), we could set them of the specific
>>> framebuffer to a hardware overlay.
>>
>> The current plan is to add a 3rd ioctl, for adding multi-planar fb..
>> I guess it is a good thing that I'm not the only one who wants this
>> :-)
>>
>>> another one, and also I have tried to implement the way sharing the
>>> memory between v4l2 based drivers and drm based drivers through
>>> application and this works fine. this feature had been introduced by
>>> v4l2 framework as user ptr. my way also is similar to it. the
>>> difference is that application could get new gem handle from specific
>>> gem framework of kernel side if user application requests user ptr
>>> import with the user space address(mmaped memory). the new gem handle
>>> means a gem object to the memory mapped to the user space address.
>>> this way makes different applications to be possible to share the
>>> memory between v4l2 based driver and drm based driver. and also this
>>> feature is considered for IOMMU so it would support non continuous
>>> memory also. I will introduce this feature soon.
>>
>> btw, there was an RFC a little while back for "dmabuf" buffer sharing
>> mechanism..  the idea would be to export a (for example) GEM buffer to
>> a dmabuf handle which could be passed in to other devices, including
>> for example v4l2 (although without necessarily requiring a userspace
>> mapping)..
>>
>> http://www.spinics.net/lists/dri-devel/msg15077.html
>>
>> It sounds like you are looking for a similar thing..
>>
>
> Hi, Rob.
>
> GEM framework already supports memory sharing way that a object name
> created by gem flink is sent to another process and then the process
> opens the object name. at that time, the gem framework of kernel side
> creates new gem object. and I know that dmabuf is similar to the ION
> introduced by Rebecca who is an engineer of Google at least for buffer
> sharing way. but is it possible to share the memory region drawing on
> only user virtual address mmaped with another process?. for instance,
> as you know, v4l2 based driver has request buf feature that the driver
> of kernel side allocates the memory regions as user-desired buffer
> count and user gets user virtual address with mmap request after quary
> buffer request. so we need to share this memory mmaped at here also.
> for this, v4l2 based driver has userptr feature that user application
> sets user virtual address to userptr structure and then the address is
> translated to bus address(physical address without iommu or device
> address with iommu) and sets it to hardware. I think it doesn't need
> dmabuf if we would use it only for sharing the gem buffer with another
> process because GEM framework already can do it. I will try to find
> the way that we can use this feature commonly for generic gem
> framework. this feature has already been implemented in our specific
> gem framework and also tested.

There are a few limitations with userptr:
1) will simply fail if importing driver has some special dma
requirements (contiguous memory, specific address range, etc)..
2) requires a userspace virtual mapping of buffer.. which might not
always be required for fully hw accelerated use cases

And in general I'm not a huge fan of dma'ing to arbitrary malloc'd
buffers (which userptr seems to encourage)..

So it's true, that somehow people have managed to ship linux based
products without dmabuf, using various hacks..  but part of the point
of dmabuf is to try to get to a cleaner more generic solution.

BR,
-R

> thank you,
> Inki dae.
>
>
>> BR,
>> -R
>>
>>> Thank you,
>>> Inki Dae.
>>>
>>> 2011/11/9 Jesse Barnes <jbarnes@virtuousgeek.org>:
>>>> 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.  Implement the fb creation hooks in terms of the
>>>> new mode_fb_cmd2 using helpers where the old bpp/depth values are
>>>> needed.
>>>>
>>>> Acked-by: Alan Cox <alan@lxorguk.ukuu.org.uk>
>>>> Reviewed-by: Rob Clark <rob.clark@linaro.org>
>>>> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
>>>> ---
>>>>  drivers/gpu/drm/drm_crtc.c                |  108 +++++++++++++++++++++++++++-
>>>>  drivers/gpu/drm/drm_crtc_helper.c         |   50 ++++++++++++-
>>>>  drivers/gpu/drm/drm_drv.c                 |    1 +
>>>>  drivers/gpu/drm/i915/intel_display.c      |   36 +++++-----
>>>>  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/nouveau/nouveau_fb.h      |    2 +-
>>>>  drivers/gpu/drm/nouveau/nouveau_fbcon.c   |   13 ++--
>>>>  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       |   22 ++++--
>>>>  drivers/gpu/drm/vmwgfx/vmwgfx_kms.h       |    1 +
>>>>  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                    |   28 +++++++-
>>>>  include/linux/videodev2.h                 |    1 +
>>>>  20 files changed, 256 insertions(+), 61 deletions(-)
>>>>
>>>> diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
>>>> index 804ef12..39cccb4 100644
>>>> --- a/drivers/gpu/drm/drm_crtc.c
>>>> +++ b/drivers/gpu/drm/drm_crtc.c
>>>> @@ -1910,6 +1910,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
>>>> @@ -1930,7 +1966,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;
>>>> @@ -1951,9 +2054,6 @@ int drm_mode_addfb(struct drm_device *dev,
>>>>
>>>>        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");
>>>> diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c
>>>> index f236644..68011bb 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 = 32;
>>>> +               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..aae7b03 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;
>>>> @@ -7581,21 +7581,23 @@ 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->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/nouveau/nouveau_fb.h b/drivers/gpu/drm/nouveau/nouveau_fb.h
>>>> index 95c843e..f4dd301 100644
>>>> --- a/drivers/gpu/drm/nouveau/nouveau_fb.h
>>>> +++ b/drivers/gpu/drm/nouveau/nouveau_fb.h
>>>> @@ -45,5 +45,5 @@ nouveau_framebuffer(struct drm_framebuffer *fb)
>>>>  extern const struct drm_mode_config_funcs nouveau_mode_config_funcs;
>>>>
>>>>  int nouveau_framebuffer_init(struct drm_device *dev, struct nouveau_framebuffer *nouveau_fb,
>>>> -                            struct drm_mode_fb_cmd *mode_cmd, struct nouveau_bo *nvbo);
>>>> +                            struct drm_mode_fb_cmd2 *mode_cmd, struct nouveau_bo *nvbo);
>>>>  #endif /* __NOUVEAU_FB_H__ */
>>>> diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c
>>>> index 14a8627..d663065 100644
>>>> --- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c
>>>> +++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c
>>>> @@ -281,7 +281,7 @@ nouveau_fbcon_create(struct nouveau_fbdev *nfbdev,
>>>>        struct nouveau_framebuffer *nouveau_fb;
>>>>        struct nouveau_channel *chan;
>>>>        struct nouveau_bo *nvbo;
>>>> -       struct drm_mode_fb_cmd mode_cmd;
>>>> +       struct drm_mode_fb_cmd2 mode_cmd;
>>>>        struct pci_dev *pdev = dev->pdev;
>>>>        struct device *device = &pdev->dev;
>>>>        int size, ret;
>>>> @@ -289,12 +289,13 @@ nouveau_fbcon_create(struct nouveau_fbdev *nfbdev,
>>>>        mode_cmd.width = sizes->surface_width;
>>>>        mode_cmd.height = sizes->surface_height;
>>>>
>>>> -       mode_cmd.bpp = sizes->surface_bpp;
>>>> -       mode_cmd.pitch = mode_cmd.width * (mode_cmd.bpp >> 3);
>>>> -       mode_cmd.pitch = roundup(mode_cmd.pitch, 256);
>>>> -       mode_cmd.depth = sizes->surface_depth;
>>>> +       mode_cmd.pitches[0] = mode_cmd.width * (sizes->surface_bpp >> 3);
>>>> +       mode_cmd.pitches[0] = roundup(mode_cmd.pitches[0], 256);
>>>>
>>>> -       size = mode_cmd.pitch * mode_cmd.height;
>>>> +       mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp,
>>>> +                                                         sizes->surface_depth);
>>>> +
>>>> +       size = mode_cmd.pitches[0] * mode_cmd.height;
>>>>        size = roundup(size, PAGE_SIZE);
>>>>
>>>>        ret = nouveau_gem_new(dev, size, 0, NOUVEAU_GEM_DOMAIN_VRAM,
>>>> 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..61a030c 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_cmd2)
>>>>  {
>>>>        struct vmw_private *dev_priv = vmw_priv(dev);
>>>>        struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
>>>> @@ -982,16 +982,24 @@ static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev,
>>>>        struct vmw_surface *surface = NULL;
>>>>        struct vmw_dma_buffer *bo = NULL;
>>>>        struct ttm_base_object *user_obj;
>>>> +       struct drm_mode_fb_cmd mode_cmd;
>>>>        u64 required_size;
>>>>        int ret;
>>>>
>>>> +       mode_cmd.width = mode_cmd2->width;
>>>> +       mode_cmd.height = mode_cmd2->height;
>>>> +       mode_cmd.pitch = mode_cmd2->pitches[0];
>>>> +       mode_cmd.handle = mode_cmd2->handle;
>>>> +       drm_helper_get_fb_bpp_depth(mode_cmd2->pixel_format, &mode_cmd.depth,
>>>> +                                   &mode_cmd.bpp);
>>>> +
>>>>        /**
>>>>         * This code should be conditioned on Screen Objects not being used.
>>>>         * If screen objects are used, we can allocate a GMR to hold the
>>>>         * requested framebuffer.
>>>>         */
>>>>
>>>> -       required_size = mode_cmd->pitch * mode_cmd->height;
>>>> +       required_size = mode_cmd.pitch * mode_cmd.height;
>>>>        if (unlikely(required_size > (u64) dev_priv->vram_size)) {
>>>>                DRM_ERROR("VRAM size is too small for requested mode.\n");
>>>>                return NULL;
>>>> @@ -1006,7 +1014,7 @@ static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev,
>>>>         * command stream using user-space handles.
>>>>         */
>>>>
>>>> -       user_obj = ttm_base_object_lookup(tfile, mode_cmd->handle);
>>>> +       user_obj = ttm_base_object_lookup(tfile, mode_cmd.handle);
>>>>        if (unlikely(user_obj == NULL)) {
>>>>                DRM_ERROR("Could not locate requested kms frame buffer.\n");
>>>>                return ERR_PTR(-ENOENT);
>>>> @@ -1017,7 +1025,7 @@ static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev,
>>>>         */
>>>>
>>>>        ret = vmw_user_surface_lookup_handle(dev_priv, tfile,
>>>> -                                            mode_cmd->handle, &surface);
>>>> +                                            mode_cmd.handle, &surface);
>>>>        if (ret)
>>>>                goto try_dmabuf;
>>>>
>>>> @@ -1025,7 +1033,7 @@ static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev,
>>>>                goto err_not_scanout;
>>>>
>>>>        ret = vmw_kms_new_framebuffer_surface(dev_priv, file_priv, surface,
>>>> -                                             &vfb, mode_cmd);
>>>> +                                             &vfb, &mode_cmd);
>>>>
>>>>        /* vmw_user_surface_lookup takes one ref so does new_fb */
>>>>        vmw_surface_unreference(&surface);
>>>> @@ -1041,14 +1049,14 @@ static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev,
>>>>  try_dmabuf:
>>>>        DRM_INFO("%s: trying buffer\n", __func__);
>>>>
>>>> -       ret = vmw_user_dmabuf_lookup(tfile, mode_cmd->handle, &bo);
>>>> +       ret = vmw_user_dmabuf_lookup(tfile, mode_cmd.handle, &bo);
>>>>        if (ret) {
>>>>                DRM_ERROR("failed to find buffer: %i\n", ret);
>>>>                return ERR_PTR(-ENOENT);
>>>>        }
>>>>
>>>>        ret = vmw_kms_new_framebuffer_dmabuf(dev_priv, bo, &vfb,
>>>> -                                            mode_cmd);
>>>> +                                            &mode_cmd);
>>>>
>>>>        /* vmw_user_dmabuf_lookup takes one ref so does new_fb */
>>>>        vmw_dmabuf_unreference(&bo);
>>>> diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
>>>> index db0b901..e199adf 100644
>>>> --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
>>>> +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
>>>> @@ -29,6 +29,7 @@
>>>>  #define VMWGFX_KMS_H_
>>>>
>>>>  #include "drmP.h"
>>>> +#include "drm_crtc_helper.h"
>>>>  #include "vmwgfx_drv.h"
>>>>
>>>>  #define VMWGFX_NUM_DISPLAY_UNITS 8
>>>> 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 e20867e..84db125 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;
>>>> @@ -619,7 +621,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);
>>>>  };
>>>>
>>>> @@ -837,6 +839,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..3cfa160 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
>>>> @@ -136,7 +138,6 @@ struct drm_mode_set_plane {
>>>>  };
>>>>
>>>>  struct drm_mode_get_plane {
>>>> -       __u64 format_type_ptr;
>>>>        __u32 plane_id;
>>>>
>>>>        __u32 crtc_id;
>>>> @@ -146,6 +147,7 @@ struct drm_mode_get_plane {
>>>>        __u32 gamma_size;
>>>>
>>>>        __u32 count_format_types;
>>>> +       __u64 format_type_ptr;
>>>>  };
>>>>
>>>>  struct drm_mode_get_plane_res {
>>>> @@ -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
>>>>
>>>> _______________________________________________
>>>> dri-devel mailing list
>>>> dri-devel@lists.freedesktop.org
>>>> http://lists.freedesktop.org/mailman/listinfo/dri-devel
>>>>
>>> _______________________________________________
>>> dri-devel mailing list
>>> dri-devel@lists.freedesktop.org
>>> http://lists.freedesktop.org/mailman/listinfo/dri-devel
>>>
>>
>

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

* Re: [PATCH 2/2] drm: add an fb creation ioctl that takes a pixel format
  2011-11-08 21:18 ` [PATCH 2/2] drm: add an fb creation ioctl that takes a pixel format Jesse Barnes
  2011-11-09 13:25   ` InKi Dae
@ 2011-11-11 10:47   ` Dave Airlie
  2011-11-11 10:50     ` Dave Airlie
  2011-11-11 10:56   ` Dave Airlie
  2 siblings, 1 reply; 17+ messages in thread
From: Dave Airlie @ 2011-11-11 10:47 UTC (permalink / raw)
  To: Jesse Barnes; +Cc: dri-devel

On Tue, Nov 8, 2011 at 9:18 PM, 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.  Implement the fb creation hooks in terms of the
> new mode_fb_cmd2 using helpers where the old bpp/depth values are
> needed.

I'm nearly sure I said this before, but please move the FOURCC defines
somewhere generic,
then use those, otherwise this is going to encourage crappy userspace
coding where
they drag in libv4l2 just to use a drm feature.

I know they are generic, but userspace writes will start to include
v4l headers to get at
the same defines you use in the kernel.

Dave.

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

* Re: [PATCH 2/2] drm: add an fb creation ioctl that takes a pixel format
  2011-11-11 10:47   ` Dave Airlie
@ 2011-11-11 10:50     ` Dave Airlie
  2011-11-11 15:35       ` Jesse Barnes
  0 siblings, 1 reply; 17+ messages in thread
From: Dave Airlie @ 2011-11-11 10:50 UTC (permalink / raw)
  To: Jesse Barnes; +Cc: dri-devel

On Fri, Nov 11, 2011 at 10:47 AM, Dave Airlie <airlied@gmail.com> wrote:
> On Tue, Nov 8, 2011 at 9:18 PM, 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.  Implement the fb creation hooks in terms of the
>> new mode_fb_cmd2 using helpers where the old bpp/depth values are
>> needed.
>
> I'm nearly sure I said this before, but please move the FOURCC defines
> somewhere generic,
> then use those, otherwise this is going to encourage crappy userspace
> coding where
> they drag in libv4l2 just to use a drm feature.
>
> I know they are generic, but userspace writes will start to include
> v4l headers to get at
> the same defines you use in the kernel.
>

Oh and I'll take it as a follow-up patch. as I'd rather merge the base
code now before it gets too late.

Dave.

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

* Re: [PATCH 2/2] drm: add an fb creation ioctl that takes a pixel format
  2011-11-08 21:18 ` [PATCH 2/2] drm: add an fb creation ioctl that takes a pixel format Jesse Barnes
  2011-11-09 13:25   ` InKi Dae
  2011-11-11 10:47   ` Dave Airlie
@ 2011-11-11 10:56   ` Dave Airlie
  2 siblings, 0 replies; 17+ messages in thread
From: Dave Airlie @ 2011-11-11 10:56 UTC (permalink / raw)
  To: Jesse Barnes; +Cc: dri-devel

Another comment below, I'd rather you respin them, with a version
number on them so I know which ones to pick up, really this is my 3rd
try at merging these and I keep finding sillyness.

>> index 07711b0..3cfa160 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>

You are essentially changing the drm abi to require videodev2.h here,
these files are reused in userspace, I really don't like this, the
commit message makes no mention of this either
> +
>  #define DRM_DISPLAY_INFO_LEN   32
>  #define DRM_CONNECTOR_NAME_LEN 32
>  #define DRM_DISPLAY_MODE_LEN   32
> @@ -136,7 +138,6 @@ struct drm_mode_set_plane {
>  };
>
>  struct drm_mode_get_plane {
> -       __u64 format_type_ptr;
>        __u32 plane_id;
>
>        __u32 crtc_id;
> @@ -146,6 +147,7 @@ struct drm_mode_get_plane {
>        __u32 gamma_size;
>
>        __u32 count_format_types;
> +       __u64 format_type_ptr;
>  };

And you changed ABI here from your first patch? why isn't this in the
first patch?

try again? (with versioned patches).

Dave.

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

* Re: [PATCH 2/2] drm: add an fb creation ioctl that takes a pixel format
  2011-11-11 10:50     ` Dave Airlie
@ 2011-11-11 15:35       ` Jesse Barnes
  0 siblings, 0 replies; 17+ messages in thread
From: Jesse Barnes @ 2011-11-11 15:35 UTC (permalink / raw)
  To: Dave Airlie; +Cc: dri-devel


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

On Fri, 11 Nov 2011 10:50:00 +0000
Dave Airlie <airlied@gmail.com> wrote:

> On Fri, Nov 11, 2011 at 10:47 AM, Dave Airlie <airlied@gmail.com> wrote:
> > On Tue, Nov 8, 2011 at 9:18 PM, 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.  Implement the fb creation hooks in terms of the
> >> new mode_fb_cmd2 using helpers where the old bpp/depth values are
> >> needed.
> >
> > I'm nearly sure I said this before, but please move the FOURCC defines
> > somewhere generic,
> > then use those, otherwise this is going to encourage crappy userspace
> > coding where
> > they drag in libv4l2 just to use a drm feature.
> >
> > I know they are generic, but userspace writes will start to include
> > v4l headers to get at
> > the same defines you use in the kernel.
> >
> 
> Oh and I'll take it as a follow-up patch. as I'd rather merge the base
> code now before it gets too late.

So just a separate header would be enough for you?
include/linux/fourcc or something?  Do you care if they continue to use
the v4l prefixes or not?  My preference would be to preserve that;
anything else is just churn for churn's sake.

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 --]

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

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

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

2011/11/11 Rob Clark <robdclark@gmail.com>:
> On Thu, Nov 10, 2011 at 8:54 AM, InKi Dae <daeinki@gmail.com> wrote:
>> 2011/11/9 Rob Clark <robdclark@gmail.com>:
>>> On Wed, Nov 9, 2011 at 7:25 AM, InKi Dae <daeinki@gmail.com> wrote:
>>>> Hello, all.
>>>>
>>>> I am trying to implement multi planer using your plane patch and I
>>>> think it's good but I am still warried about that drm_mode_fb_cmd2
>>>> structure has only one handle. I know this handle is sent to
>>>> framebuffer module to create new framebuffer. and the framebuffer
>>>> would cover entire a image. as you know, the image could be consisted
>>>> of one more planes. so I think now drm_mode_fb_cmd2 structure doesn't
>>>> support multi planer because it has only one handle. with update_plane
>>>> callback, a buffer of the framebuffer would be set to a hardware
>>>> overlay. how we could set two planes or three planes to the hardware
>>>> overlay? but there might be my missing point so please give me any
>>>> comments. in addition, have you been looked into gem flink and open
>>>> functions for memory sharing between processes? gem object basically
>>>> has one buffer so we can't modify it because of compatibility. so I
>>>> think it's right way that gem object manages only one buffer. for such
>>>> a reason, maybe drm_mode_fb_cmd2 structure should include one more
>>>> handles and plane count. each handle has a gem object to one plane and
>>>> plane count means how many planes are requested and when update_plane
>>>> callback is called by setplane(), we could set them of the specific
>>>> framebuffer to a hardware overlay.
>>>
>>> The current plan is to add a 3rd ioctl, for adding multi-planar fb..
>>> I guess it is a good thing that I'm not the only one who wants this
>>> :-)
>>>
>>>> another one, and also I have tried to implement the way sharing the
>>>> memory between v4l2 based drivers and drm based drivers through
>>>> application and this works fine. this feature had been introduced by
>>>> v4l2 framework as user ptr. my way also is similar to it. the
>>>> difference is that application could get new gem handle from specific
>>>> gem framework of kernel side if user application requests user ptr
>>>> import with the user space address(mmaped memory). the new gem handle
>>>> means a gem object to the memory mapped to the user space address.
>>>> this way makes different applications to be possible to share the
>>>> memory between v4l2 based driver and drm based driver. and also this
>>>> feature is considered for IOMMU so it would support non continuous
>>>> memory also. I will introduce this feature soon.
>>>
>>> btw, there was an RFC a little while back for "dmabuf" buffer sharing
>>> mechanism..  the idea would be to export a (for example) GEM buffer to
>>> a dmabuf handle which could be passed in to other devices, including
>>> for example v4l2 (although without necessarily requiring a userspace
>>> mapping)..
>>>
>>> http://www.spinics.net/lists/dri-devel/msg15077.html
>>>
>>> It sounds like you are looking for a similar thing..
>>>
>>
>> Hi, Rob.
>>
>> GEM framework already supports memory sharing way that a object name
>> created by gem flink is sent to another process and then the process
>> opens the object name. at that time, the gem framework of kernel side
>> creates new gem object. and I know that dmabuf is similar to the ION
>> introduced by Rebecca who is an engineer of Google at least for buffer
>> sharing way. but is it possible to share the memory region drawing on
>> only user virtual address mmaped with another process?. for instance,
>> as you know, v4l2 based driver has request buf feature that the driver
>> of kernel side allocates the memory regions as user-desired buffer
>> count and user gets user virtual address with mmap request after quary
>> buffer request. so we need to share this memory mmaped at here also.
>> for this, v4l2 based driver has userptr feature that user application
>> sets user virtual address to userptr structure and then the address is
>> translated to bus address(physical address without iommu or device
>> address with iommu) and sets it to hardware. I think it doesn't need
>> dmabuf if we would use it only for sharing the gem buffer with another
>> process because GEM framework already can do it. I will try to find
>> the way that we can use this feature commonly for generic gem
>> framework. this feature has already been implemented in our specific
>> gem framework and also tested.
>
> There are a few limitations with userptr:
> 1) will simply fail if importing driver has some special dma
> requirements (contiguous memory, specific address range, etc)..

Yes, right. so we used DMA-Mapping framework. for this, you can refer
to the link below
http://www.spinics.net/lists/linux-arch/msg15210.html

as you know, with dma-mapping framework, we could get bus address
through dma_map_sg() appropriately. for instance, without iommu we
could get physical address and with iommu we could get device address
through the funtion call.

> 2) requires a userspace virtual mapping of buffer.. which might not
> always be required for fully hw accelerated use cases
>
> And in general I'm not a huge fan of dma'ing to arbitrary malloc'd
> buffers (which userptr seems to encourage)..
>
> So it's true, that somehow people have managed to ship linux based
> products without dmabuf, using various hacks..  but part of the point
> of dmabuf is to try to get to a cleaner more generic solution.
>

for buffer object sharing between processes, as I mentioned before,
now drm gem framework can do that. so I think we don't need dmabuf. I
mean that the problem is user virtual address mmaped to the memory
region. as you know, linux platform would use 'framebuffer and v4l2
framework' or 'drm and v4l2 framework' for graphics and multimedia.
v4l2 based multimedia application might want to use V4L2_MEMORY_MMAP
type that this feature allocates the buffers as user-desired count
internally. so I think we should consider the memory sharing way for
user virtual address mmaped to any allocated memory region. if there
is my missing point, please feel free to give me your comments and
advices.

Thank you,
Inki dae.

> BR,
> -R
>
>> thank you,
>> Inki dae.
>>
>>
>>> BR,
>>> -R
>>>
>>>> Thank you,
>>>> Inki Dae.
>>>>
>>>> 2011/11/9 Jesse Barnes <jbarnes@virtuousgeek.org>:
>>>>> 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.  Implement the fb creation hooks in terms of the
>>>>> new mode_fb_cmd2 using helpers where the old bpp/depth values are
>>>>> needed.
>>>>>
>>>>> Acked-by: Alan Cox <alan@lxorguk.ukuu.org.uk>
>>>>> Reviewed-by: Rob Clark <rob.clark@linaro.org>
>>>>> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
>>>>> ---
>>>>>  drivers/gpu/drm/drm_crtc.c                |  108 +++++++++++++++++++++++++++-
>>>>>  drivers/gpu/drm/drm_crtc_helper.c         |   50 ++++++++++++-
>>>>>  drivers/gpu/drm/drm_drv.c                 |    1 +
>>>>>  drivers/gpu/drm/i915/intel_display.c      |   36 +++++-----
>>>>>  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/nouveau/nouveau_fb.h      |    2 +-
>>>>>  drivers/gpu/drm/nouveau/nouveau_fbcon.c   |   13 ++--
>>>>>  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       |   22 ++++--
>>>>>  drivers/gpu/drm/vmwgfx/vmwgfx_kms.h       |    1 +
>>>>>  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                    |   28 +++++++-
>>>>>  include/linux/videodev2.h                 |    1 +
>>>>>  20 files changed, 256 insertions(+), 61 deletions(-)
>>>>>
>>>>> diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
>>>>> index 804ef12..39cccb4 100644
>>>>> --- a/drivers/gpu/drm/drm_crtc.c
>>>>> +++ b/drivers/gpu/drm/drm_crtc.c
>>>>> @@ -1910,6 +1910,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
>>>>> @@ -1930,7 +1966,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;
>>>>> @@ -1951,9 +2054,6 @@ int drm_mode_addfb(struct drm_device *dev,
>>>>>
>>>>>        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");
>>>>> diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c
>>>>> index f236644..68011bb 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 = 32;
>>>>> +               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..aae7b03 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;
>>>>> @@ -7581,21 +7581,23 @@ 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->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/nouveau/nouveau_fb.h b/drivers/gpu/drm/nouveau/nouveau_fb.h
>>>>> index 95c843e..f4dd301 100644
>>>>> --- a/drivers/gpu/drm/nouveau/nouveau_fb.h
>>>>> +++ b/drivers/gpu/drm/nouveau/nouveau_fb.h
>>>>> @@ -45,5 +45,5 @@ nouveau_framebuffer(struct drm_framebuffer *fb)
>>>>>  extern const struct drm_mode_config_funcs nouveau_mode_config_funcs;
>>>>>
>>>>>  int nouveau_framebuffer_init(struct drm_device *dev, struct nouveau_framebuffer *nouveau_fb,
>>>>> -                            struct drm_mode_fb_cmd *mode_cmd, struct nouveau_bo *nvbo);
>>>>> +                            struct drm_mode_fb_cmd2 *mode_cmd, struct nouveau_bo *nvbo);
>>>>>  #endif /* __NOUVEAU_FB_H__ */
>>>>> diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c
>>>>> index 14a8627..d663065 100644
>>>>> --- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c
>>>>> +++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c
>>>>> @@ -281,7 +281,7 @@ nouveau_fbcon_create(struct nouveau_fbdev *nfbdev,
>>>>>        struct nouveau_framebuffer *nouveau_fb;
>>>>>        struct nouveau_channel *chan;
>>>>>        struct nouveau_bo *nvbo;
>>>>> -       struct drm_mode_fb_cmd mode_cmd;
>>>>> +       struct drm_mode_fb_cmd2 mode_cmd;
>>>>>        struct pci_dev *pdev = dev->pdev;
>>>>>        struct device *device = &pdev->dev;
>>>>>        int size, ret;
>>>>> @@ -289,12 +289,13 @@ nouveau_fbcon_create(struct nouveau_fbdev *nfbdev,
>>>>>        mode_cmd.width = sizes->surface_width;
>>>>>        mode_cmd.height = sizes->surface_height;
>>>>>
>>>>> -       mode_cmd.bpp = sizes->surface_bpp;
>>>>> -       mode_cmd.pitch = mode_cmd.width * (mode_cmd.bpp >> 3);
>>>>> -       mode_cmd.pitch = roundup(mode_cmd.pitch, 256);
>>>>> -       mode_cmd.depth = sizes->surface_depth;
>>>>> +       mode_cmd.pitches[0] = mode_cmd.width * (sizes->surface_bpp >> 3);
>>>>> +       mode_cmd.pitches[0] = roundup(mode_cmd.pitches[0], 256);
>>>>>
>>>>> -       size = mode_cmd.pitch * mode_cmd.height;
>>>>> +       mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp,
>>>>> +                                                         sizes->surface_depth);
>>>>> +
>>>>> +       size = mode_cmd.pitches[0] * mode_cmd.height;
>>>>>        size = roundup(size, PAGE_SIZE);
>>>>>
>>>>>        ret = nouveau_gem_new(dev, size, 0, NOUVEAU_GEM_DOMAIN_VRAM,
>>>>> 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..61a030c 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_cmd2)
>>>>>  {
>>>>>        struct vmw_private *dev_priv = vmw_priv(dev);
>>>>>        struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
>>>>> @@ -982,16 +982,24 @@ static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev,
>>>>>        struct vmw_surface *surface = NULL;
>>>>>        struct vmw_dma_buffer *bo = NULL;
>>>>>        struct ttm_base_object *user_obj;
>>>>> +       struct drm_mode_fb_cmd mode_cmd;
>>>>>        u64 required_size;
>>>>>        int ret;
>>>>>
>>>>> +       mode_cmd.width = mode_cmd2->width;
>>>>> +       mode_cmd.height = mode_cmd2->height;
>>>>> +       mode_cmd.pitch = mode_cmd2->pitches[0];
>>>>> +       mode_cmd.handle = mode_cmd2->handle;
>>>>> +       drm_helper_get_fb_bpp_depth(mode_cmd2->pixel_format, &mode_cmd.depth,
>>>>> +                                   &mode_cmd.bpp);
>>>>> +
>>>>>        /**
>>>>>         * This code should be conditioned on Screen Objects not being used.
>>>>>         * If screen objects are used, we can allocate a GMR to hold the
>>>>>         * requested framebuffer.
>>>>>         */
>>>>>
>>>>> -       required_size = mode_cmd->pitch * mode_cmd->height;
>>>>> +       required_size = mode_cmd.pitch * mode_cmd.height;
>>>>>        if (unlikely(required_size > (u64) dev_priv->vram_size)) {
>>>>>                DRM_ERROR("VRAM size is too small for requested mode.\n");
>>>>>                return NULL;
>>>>> @@ -1006,7 +1014,7 @@ static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev,
>>>>>         * command stream using user-space handles.
>>>>>         */
>>>>>
>>>>> -       user_obj = ttm_base_object_lookup(tfile, mode_cmd->handle);
>>>>> +       user_obj = ttm_base_object_lookup(tfile, mode_cmd.handle);
>>>>>        if (unlikely(user_obj == NULL)) {
>>>>>                DRM_ERROR("Could not locate requested kms frame buffer.\n");
>>>>>                return ERR_PTR(-ENOENT);
>>>>> @@ -1017,7 +1025,7 @@ static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev,
>>>>>         */
>>>>>
>>>>>        ret = vmw_user_surface_lookup_handle(dev_priv, tfile,
>>>>> -                                            mode_cmd->handle, &surface);
>>>>> +                                            mode_cmd.handle, &surface);
>>>>>        if (ret)
>>>>>                goto try_dmabuf;
>>>>>
>>>>> @@ -1025,7 +1033,7 @@ static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev,
>>>>>                goto err_not_scanout;
>>>>>
>>>>>        ret = vmw_kms_new_framebuffer_surface(dev_priv, file_priv, surface,
>>>>> -                                             &vfb, mode_cmd);
>>>>> +                                             &vfb, &mode_cmd);
>>>>>
>>>>>        /* vmw_user_surface_lookup takes one ref so does new_fb */
>>>>>        vmw_surface_unreference(&surface);
>>>>> @@ -1041,14 +1049,14 @@ static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev,
>>>>>  try_dmabuf:
>>>>>        DRM_INFO("%s: trying buffer\n", __func__);
>>>>>
>>>>> -       ret = vmw_user_dmabuf_lookup(tfile, mode_cmd->handle, &bo);
>>>>> +       ret = vmw_user_dmabuf_lookup(tfile, mode_cmd.handle, &bo);
>>>>>        if (ret) {
>>>>>                DRM_ERROR("failed to find buffer: %i\n", ret);
>>>>>                return ERR_PTR(-ENOENT);
>>>>>        }
>>>>>
>>>>>        ret = vmw_kms_new_framebuffer_dmabuf(dev_priv, bo, &vfb,
>>>>> -                                            mode_cmd);
>>>>> +                                            &mode_cmd);
>>>>>
>>>>>        /* vmw_user_dmabuf_lookup takes one ref so does new_fb */
>>>>>        vmw_dmabuf_unreference(&bo);
>>>>> diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
>>>>> index db0b901..e199adf 100644
>>>>> --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
>>>>> +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
>>>>> @@ -29,6 +29,7 @@
>>>>>  #define VMWGFX_KMS_H_
>>>>>
>>>>>  #include "drmP.h"
>>>>> +#include "drm_crtc_helper.h"
>>>>>  #include "vmwgfx_drv.h"
>>>>>
>>>>>  #define VMWGFX_NUM_DISPLAY_UNITS 8
>>>>> 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 e20867e..84db125 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;
>>>>> @@ -619,7 +621,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);
>>>>>  };
>>>>>
>>>>> @@ -837,6 +839,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..3cfa160 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
>>>>> @@ -136,7 +138,6 @@ struct drm_mode_set_plane {
>>>>>  };
>>>>>
>>>>>  struct drm_mode_get_plane {
>>>>> -       __u64 format_type_ptr;
>>>>>        __u32 plane_id;
>>>>>
>>>>>        __u32 crtc_id;
>>>>> @@ -146,6 +147,7 @@ struct drm_mode_get_plane {
>>>>>        __u32 gamma_size;
>>>>>
>>>>>        __u32 count_format_types;
>>>>> +       __u64 format_type_ptr;
>>>>>  };
>>>>>
>>>>>  struct drm_mode_get_plane_res {
>>>>> @@ -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
>>>>>
>>>>> _______________________________________________
>>>>> dri-devel mailing list
>>>>> dri-devel@lists.freedesktop.org
>>>>> http://lists.freedesktop.org/mailman/listinfo/dri-devel
>>>>>
>>>> _______________________________________________
>>>> dri-devel mailing list
>>>> dri-devel@lists.freedesktop.org
>>>> http://lists.freedesktop.org/mailman/listinfo/dri-devel
>>>>
>>>
>>
>

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

* Re: [PATCH 1/2] drm: add plane support
  2011-11-08 17:50 ` Chris Wilson
@ 2011-11-08 21:17   ` Jesse Barnes
  0 siblings, 0 replies; 17+ messages in thread
From: Jesse Barnes @ 2011-11-08 21:17 UTC (permalink / raw)
  To: Chris Wilson; +Cc: dri-devel


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

On Tue, 08 Nov 2011 17:50:51 +0000
Chris Wilson <chris@chris-wilson.co.uk> wrote:

> On Tue,  8 Nov 2011 09:38:52 -0800, Jesse Barnes <jbarnes@virtuousgeek.org> wrote:
> > +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;
> > +	}
> We had begun to use ENOENT for failure to find the specified object to
> give a little variation to our error codes. Still not very widespread,
> but I think a good practice to encourage :)

Ok both good comments; fixed in the latest update.

-- 
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] 17+ messages in thread

* Re: [PATCH 1/2] drm: add plane support
  2011-11-08 17:38 [PATCH 1/2] " Jesse Barnes
  2011-11-08 17:46 ` Chris Wilson
@ 2011-11-08 17:50 ` Chris Wilson
  2011-11-08 21:17   ` Jesse Barnes
  1 sibling, 1 reply; 17+ messages in thread
From: Chris Wilson @ 2011-11-08 17:50 UTC (permalink / raw)
  To: Jesse Barnes, dri-devel

On Tue,  8 Nov 2011 09:38:52 -0800, Jesse Barnes <jbarnes@virtuousgeek.org> wrote:
> +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;
> +	}
We had begun to use ENOENT for failure to find the specified object to
give a little variation to our error codes. Still not very widespread,
but I think a good practice to encourage :)
-Chris

-- 
Chris Wilson, Intel Open Source Technology Centre

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

* Re: [PATCH 1/2] drm: add plane support
  2011-11-08 17:38 [PATCH 1/2] " Jesse Barnes
@ 2011-11-08 17:46 ` Chris Wilson
  2011-11-08 17:50 ` Chris Wilson
  1 sibling, 0 replies; 17+ messages in thread
From: Chris Wilson @ 2011-11-08 17:46 UTC (permalink / raw)
  To: Jesse Barnes, dri-devel

On Tue,  8 Nov 2011 09:38:52 -0800, 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.
> 
> Acked-by: Alan Cox <alan@lxorguk.ukuu.org.uk>
> Reviewed-by: Rob Clark <rob.clark@linaro.org>
> Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> 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     |   75 +++++++++++++-
>  include/drm/drm_mode.h     |   33 ++++++
>  5 files changed, 362 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;
This can fail, report it back to the caller so that he can tear down his
allocations and propagate onwards. Kthxbye.
-Chris

-- 
Chris Wilson, Intel Open Source Technology Centre

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

* [PATCH 1/2] drm: add plane support
@ 2011-11-08 17:38 Jesse Barnes
  2011-11-08 17:46 ` Chris Wilson
  2011-11-08 17:50 ` Chris Wilson
  0 siblings, 2 replies; 17+ messages in thread
From: Jesse Barnes @ 2011-11-08 17:38 UTC (permalink / raw)
  To: dri-devel

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.

Acked-by: Alan Cox <alan@lxorguk.ukuu.org.uk>
Reviewed-by: Rob Clark <rob.clark@linaro.org>
Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
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     |   75 +++++++++++++-
 include/drm/drm_mode.h     |   33 ++++++
 5 files changed, 362 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..d607367 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,62 @@ 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
+ * @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 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 +647,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 +701,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 +721,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 +821,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] 17+ messages in thread

end of thread, other threads:[~2011-11-12  9:14 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-11-08 21:18 [PATCH 1/2] drm: add plane support Jesse Barnes
2011-11-08 21:18 ` [PATCH 2/2] drm: add an fb creation ioctl that takes a pixel format Jesse Barnes
2011-11-09 13:25   ` InKi Dae
2011-11-09 14:08     ` Rob Clark
2011-11-10 14:54       ` InKi Dae
2011-11-10 16:30         ` Rob Clark
2011-11-12  9:14           ` InKi Dae
2011-11-11 10:47   ` Dave Airlie
2011-11-11 10:50     ` Dave Airlie
2011-11-11 15:35       ` Jesse Barnes
2011-11-11 10:56   ` Dave Airlie
2011-11-08 21:26 ` [PATCH 1/2] drm: add plane support Chris Wilson
2011-11-09 10:55 ` [PATCH 1/5] " Joonyoung Shim
  -- strict thread matches above, loose matches on Subject: below --
2011-11-08 17:38 [PATCH 1/2] " Jesse Barnes
2011-11-08 17:46 ` Chris Wilson
2011-11-08 17:50 ` Chris Wilson
2011-11-08 21:17   ` 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.