[RFC] drm: Introduce max width and height properties for planes

Archit Taneja architt at codeaurora.org
Wed May 25 06:33:39 UTC 2016


High resoultion modes (4K/5K) are supported by encoder/crtc hardware, but
the backing hardware planes to scanout these buffers generally don't
support such large widths. Two (or more) hardware planes are used in
conjunction to scan out the entire width.

One way to support this is to virtualize the drm_plane objects that we
expose to userspace, and let the kms driver internally figure out whether
it needs to club multiple hardware pipes to run a particular mode.

The other option is to represent a drm_plane as it is in hardware, and
leave it to userspace use to manage multiple drm_planes for scanning
out these modes.

The advantage of the latter option is that the kms driver doesn't get
too complicated. It doesn't need to do the decision making on how to
distibute the hardware resources among the drm_planes. It also allows
userspace to continue doing some of the heavy lifting (figure out
the most power efficient combination of pipes, estimate bandwidth
consumption etc) which would have to be moved to the kernel if we
virtualized planes.

In order to achieve the latter, a drm_plane should expose an immutable
property to userspace describing the maximum width and height it can
support. Userspace can then prepare the drm_planes accordingly and
commit the state. This patch introduces these properties.

The main disadvantage is that legacy userspace (i.e. calling SetCrtc
on a high resolution framebuffer) wouldn't work. This, on the other
hand, wouldn't be a problem if we virtualized the planes and manipulated
the hardware pipes in the kenrel. One way around this is to fail large
resolution modes when using legacy setcrtc, or introduce some minimal
helpers in the kernel that automatically use multiple drm_planes when
we try to set such a mode. A solution to this issue isn't a part of the
RFC yet.

We're looking for feedback here and wondering whether this is the right
way to go or not.

Signed-off-by: Archit Taneja <architt at codeaurora.org>
---
 drivers/gpu/drm/drm_atomic.c |  9 +++++++++
 drivers/gpu/drm/drm_crtc.c   | 38 ++++++++++++++++++++++++++++++++++++++
 include/drm/drm_crtc.h       |  6 ++++++
 3 files changed, 53 insertions(+)

diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
index 8ee1db8..fded22a 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -839,6 +839,15 @@ static int drm_atomic_plane_check(struct drm_plane *plane,
 		return -ERANGE;
 	}
 
+	if (plane->max_width && (state->src_w >> 16) > plane->max_width ||
+	    plane->max_height && (state->src_h >> 16) > plane->max_height) {
+		DRM_DEBUG_ATOMIC("Invalid source width/height "
+				 "%u.%06ux%u.%06u\n",
+				 state->src_w >> 16, ((state->src_w & 0xffff) * 15625) >> 10,
+				 state->src_h >> 16, ((state->src_h & 0xffff) * 15625) >> 10);
+		return -ERANGE;
+	}
+
 	fb_width = state->fb->width << 16;
 	fb_height = state->fb->height << 16;
 
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index e08f962..f2d3b92 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -1267,6 +1267,9 @@ int drm_universal_plane_init(struct drm_device *dev, struct drm_plane *plane,
 	plane->possible_crtcs = possible_crtcs;
 	plane->type = type;
 
+	plane->max_width = 0;
+	plane->max_height = 0;
+
 	list_add_tail(&plane->head, &config->plane_list);
 	config->num_total_plane++;
 	if (plane->type == DRM_PLANE_TYPE_OVERLAY)
@@ -4957,6 +4960,41 @@ int drm_mode_plane_set_obj_prop(struct drm_plane *plane,
 }
 EXPORT_SYMBOL(drm_mode_plane_set_obj_prop);
 
+int drm_plane_create_max_width_prop(struct drm_plane *plane, uint32_t max_width)
+{
+	struct drm_property *prop;
+
+	prop = drm_property_create_range(plane->dev, DRM_MODE_PROP_IMMUTABLE,
+					 "MAX_W", max_width, max_width);
+	if (!prop)
+		return -ENOMEM;
+
+	drm_object_attach_property(&plane->base, prop, max_width);
+
+	plane->max_width = max_width;
+
+	return 0;
+}
+EXPORT_SYMBOL(drm_plane_create_max_width_prop);
+
+int drm_plane_create_max_height_prop(struct drm_plane *plane,
+				     uint32_t max_height)
+{
+	struct drm_property *prop;
+
+	prop = drm_property_create_range(plane->dev, DRM_MODE_PROP_IMMUTABLE,
+					 "MAX_H", max_height, max_height);
+	if (!prop)
+		return -ENOMEM;
+
+	drm_object_attach_property(&plane->base, prop, max_height);
+
+	plane->max_height = max_height;
+
+	return 0;
+}
+EXPORT_SYMBOL(drm_plane_create_max_height_prop);
+
 /**
  * drm_mode_obj_get_properties_ioctl - get the current value of a object's property
  * @dev: DRM device
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index e0170bf..6104527 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -1531,6 +1531,8 @@ struct drm_plane {
 	uint32_t *format_types;
 	unsigned int format_count;
 	bool format_default;
+	uint32_t max_width;
+	uint32_t max_height;
 
 	struct drm_crtc *crtc;
 	struct drm_framebuffer *fb;
@@ -2550,6 +2552,10 @@ extern struct drm_property *drm_mode_create_rotation_property(struct drm_device
 							      unsigned int supported_rotations);
 extern unsigned int drm_rotation_simplify(unsigned int rotation,
 					  unsigned int supported_rotations);
+extern int drm_plane_create_max_width_prop(struct drm_plane *plane,
+					   uint32_t max_width);
+extern int drm_plane_create_max_height_prop(struct drm_plane *plane,
+					    uint32_t max_height);
 
 /* Helpers */
 
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation



More information about the dri-devel mailing list