All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Noralf Trønnes" <noralf@tronnes.org>
To: dri-devel@lists.freedesktop.org
Cc: daniel.vetter@ffwll.ch, intel-gfx@lists.freedesktop.org,
	"Noralf Trønnes" <noralf@tronnes.org>,
	laurent.pinchart@ideasonboard.com, mstaudt@suse.de,
	dh.herrmann@gmail.com
Subject: [RFC v4 18/25] drm/client: Make the display modes available to clients
Date: Thu, 12 Apr 2018 18:12:30 +0200	[thread overview]
Message-ID: <20180412161237.9314-7-noralf@tronnes.org> (raw)
In-Reply-To: <20180412161237.9314-1-noralf@tronnes.org>

Give clients easy access to the display modes.

Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
---
 drivers/gpu/drm/drm_client.c | 159 +++++++++++++++++++++++++++++++++----------
 include/drm/drm_client.h     |  25 +++++++
 2 files changed, 148 insertions(+), 36 deletions(-)

diff --git a/drivers/gpu/drm/drm_client.c b/drivers/gpu/drm/drm_client.c
index 764c556630b8..bce1630a0db2 100644
--- a/drivers/gpu/drm/drm_client.c
+++ b/drivers/gpu/drm/drm_client.c
@@ -8,6 +8,7 @@
  * Copyright (c) 2007 Dave Airlie <airlied@linux.ie>
  */
 
+#include <linux/list.h>
 #include <linux/slab.h>
 
 #include <drm/drm_atomic.h>
@@ -54,6 +55,7 @@ struct drm_client_display *drm_client_display_create(struct drm_device *dev)
 	}
 
 	display->dev = dev;
+	INIT_LIST_HEAD(&display->modes);
 	display->modeset_count = num_crtc;
 
 	drm_for_each_crtc(crtc, dev)
@@ -84,12 +86,16 @@ EXPORT_SYMBOL(drm_client_display_create);
  */
 void drm_client_display_free(struct drm_client_display *display)
 {
+	struct drm_display_mode *mode, *tmp;
 	struct drm_mode_set *modeset;
 	unsigned int i;
 
 	if (!display)
 		return;
 
+	list_for_each_entry_safe(mode, tmp, &display->modes, head)
+		drm_mode_destroy(display->dev, mode);
+
 	drm_client_display_for_each_modeset(modeset, display) {
 		if (modeset->mode)
 			drm_mode_destroy(display->dev, modeset->mode);
@@ -670,22 +676,70 @@ static int drm_pick_crtcs(struct drm_client_display *display,
 	return best_score;
 }
 
-/**
- * drm_client_find_display() - Find display
- * @dev: DRM device
- * @width: Maximum display mode width (optional)
- * @height: Maximum display mode height (optional)
- *
- * This function returns a display the client can use if available.
- *
- * Free resources by calling drm_client_display_free().
- *
- * Returns:
- * A &drm_client_display on success, NULL if no connectors are found
- * or error pointer on failure.
- */
-struct drm_client_display *
-drm_client_find_display(struct drm_device *dev, unsigned int width, unsigned int height)
+/* Give the client a static list of display modes */
+static int drm_client_display_copy_modes(struct drm_client_display *display)
+{
+	int hdisplay = 0, vdisplay = 0, vrefresh;
+	struct drm_device *dev = display->dev;
+	struct drm_display_mode *mode, *copy;
+	struct drm_connector *connector;
+	struct drm_mode_set *modeset;
+	unsigned int count = 0;
+
+	drm_client_display_for_each_modeset(modeset, display) {
+		if (!modeset->num_connectors || !modeset->mode)
+			continue;
+
+		connector = modeset->connectors[0];
+		mode = modeset->mode;
+		count++;
+
+		if (modeset->num_connectors == 2) {
+			/* Cloned output */
+			copy = drm_mode_duplicate(dev, modeset->mode);
+			if (!copy)
+				return -ENOMEM;
+			list_add_tail(&copy->head, &display->modes);
+			display->mode = copy;
+
+			return 0;
+		}
+
+		if (!modeset->y)
+			hdisplay += modeset->mode->hdisplay;
+		if (!modeset->x)
+			vdisplay += modeset->mode->vdisplay;
+		vrefresh = modeset->mode->vrefresh;
+	}
+
+	if (!count)
+		return 0;
+
+	if (count == 1) {
+		struct drm_display_mode *iter;
+
+		list_for_each_entry(iter, &connector->modes, head) {
+			copy = drm_mode_duplicate(dev, iter);
+			if (!copy)
+				return -ENOMEM;
+			list_add_tail(&copy->head, &display->modes);
+			if (!display->mode && drm_mode_equal(iter, mode))
+				display->mode = copy;
+		}
+	} else {
+		/* Combined tile mode. Only the default one for now */
+		copy = drm_cvt_mode(dev, hdisplay, vdisplay, vrefresh, false, false, false);
+		if (!copy)
+			return -ENOMEM;
+		list_add_tail(&copy->head, &display->modes);
+		display->mode = copy;
+	}
+
+	return 0;
+}
+
+static struct drm_client_display *
+drm_client_find_display_default(struct drm_device *dev, unsigned int width, unsigned int height)
 {
 	struct drm_client_display_offset *offsets;
 	struct drm_client_display *display;
@@ -695,25 +749,6 @@ drm_client_find_display(struct drm_device *dev, unsigned int width, unsigned int
 	int i, connector_count;
 	bool *enabled;
 
-	DRM_DEBUG_KMS("\n");
-
-	if (!width)
-		width = dev->mode_config.max_width;
-	if (!height)
-		height = dev->mode_config.max_height;
-
-	mutex_lock(&dev->mode_config.mutex);
-	if (!drm_client_probe_connector_modes(dev, width, height))
-		DRM_DEBUG_KMS("No connectors reported connected with modes\n");
-
-	if (dev->driver->initial_client_display) {
-		display = dev->driver->initial_client_display(dev, width, height);
-		if (display) {
-			mutex_unlock(&dev->mode_config.mutex);
-			return display;
-		}
-	}
-
 	connector_count = drm_connector_get_all(dev, &connectors);
 	if (connector_count < 1)
 		return NULL;
@@ -772,7 +807,6 @@ drm_client_find_display(struct drm_device *dev, unsigned int width, unsigned int
 		}
 	}
 out:
-	mutex_unlock(&dev->mode_config.mutex);
 	drm_connector_put_all(connectors, connector_count);
 	kfree(crtcs);
 	kfree(modes);
@@ -781,4 +815,57 @@ drm_client_find_display(struct drm_device *dev, unsigned int width, unsigned int
 
 	return display;
 }
+
+/**
+ * drm_client_find_display() - Find display
+ * @dev: DRM device
+ * @width: Maximum display mode width (optional)
+ * @height: Maximum display mode height (optional)
+ *
+ * This function returns a display the client can use if one is found.
+ *
+ * Free resources by calling drm_client_display_free().
+ *
+ * Returns:
+ * A &drm_client_display on success, NULL if no connectors are found
+ * or error pointer on failure.
+ */
+struct drm_client_display *
+drm_client_find_display(struct drm_device *dev, unsigned int width, unsigned int height)
+{
+	struct drm_client_display *display = NULL;
+	int ret;
+
+	DRM_DEBUG_KMS("\n");
+
+	if (!width)
+		width = dev->mode_config.max_width;
+	if (!height)
+		height = dev->mode_config.max_height;
+
+	mutex_lock(&dev->mode_config.mutex);
+
+	if (!drm_client_probe_connector_modes(dev, width, height))
+		DRM_DEBUG_KMS("No connectors reported connected with modes\n");
+
+	if (dev->driver->initial_client_display)
+		display = dev->driver->initial_client_display(dev, width, height);
+
+	if (!display)
+		display = drm_client_find_display_default(dev, width, height);
+
+	if (IS_ERR_OR_NULL(display))
+		goto out_unlock;
+
+	ret = drm_client_display_copy_modes(display);
+	if (ret) {
+		drm_client_display_free(display);
+		display = ERR_PTR(ret);
+	}
+
+out_unlock:
+	mutex_unlock(&dev->mode_config.mutex);
+
+	return display;
+}
 EXPORT_SYMBOL(drm_client_find_display);
diff --git a/include/drm/drm_client.h b/include/drm/drm_client.h
index 3befd879a0b0..524f793d6e7b 100644
--- a/include/drm/drm_client.h
+++ b/include/drm/drm_client.h
@@ -3,9 +3,12 @@
 #ifndef _DRM_CLIENT_H_
 #define _DRM_CLIENT_H_
 
+#include <linux/types.h>
+
 struct drm_connector;
 struct drm_crtc;
 struct drm_device;
+struct drm_display_mode;
 struct drm_mode_set;
 struct drm_plane;
 
@@ -33,6 +36,20 @@ struct drm_client_display {
 	 * Number of modesets
 	 */
 	unsigned int modeset_count;
+
+	/**
+	 * @modes:
+	 *
+	 * Display modes available on this display.
+	 */
+	struct list_head modes;
+
+	/**
+	 * @mode:
+	 *
+	 * The current display mode.
+	 */
+	struct drm_display_mode *mode;
 };
 
 struct drm_client_display *drm_client_display_create(struct drm_device *dev);
@@ -51,4 +68,12 @@ int drm_client_display_dpms(struct drm_client_display *display, int mode);
 struct drm_client_display *
 drm_client_find_display(struct drm_device *dev, unsigned int width, unsigned int height);
 
+/**
+ * drm_client_display_for_each_mode - Iterate over the available display modes
+ * @mode: A @drm_display_mode loop cursor
+ * @display: Client display
+ */
+#define drm_client_display_for_each_mode(mode, display) \
+	list_for_each_entry(mode, &display->modes, head)
+
 #endif
-- 
2.15.1

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

  parent reply	other threads:[~2018-04-12 16:12 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-04-12 16:12 [RFC v4 12/25] drm/i915: Add drm_driver->initial_client_display callback Noralf Trønnes
2018-04-12 16:12 ` [RFC v4 13/25] drm/fb-helper: Remove struct drm_fb_helper_crtc Noralf Trønnes
2018-04-12 16:12 ` [RFC v4 14/25] drm/fb-helper: Remove struct drm_fb_helper_connector Noralf Trønnes
2018-04-12 16:12 ` [RFC v4 15/25] drm/fb-helper: Move modeset config code to drm_client Noralf Trønnes
2018-04-12 16:12 ` [RFC v4 16/25] drm: Make ioctls available for in-kernel clients Noralf Trønnes
2018-04-12 16:12 ` [RFC v4 17/25] drm/client: Bail out if there's a DRM master Noralf Trønnes
2018-04-12 16:12 ` Noralf Trønnes [this message]
2018-04-12 16:12 ` [RFC v4 19/25] drm/client: Finish the in-kernel client API Noralf Trønnes
2018-04-12 16:12 ` [RFC v4 20/25] drm/prime: Don't pin module on export for in-kernel clients Noralf Trønnes
2018-04-12 16:12 ` [RFC v4 21/25] drm/fb-helper: Add drm_fb_helper_fb_open/release() Noralf Trønnes
2018-04-12 16:12 ` [RFC v4 22/25] drm/fb-helper: Add generic fbdev emulation Noralf Trønnes
2018-04-12 16:12 ` [RFC v4 23/25] drm: Add DRM device registered notifier Noralf Trønnes
2018-04-12 16:12 ` [RFC v4 24/25] drm/client: Hack: Add bootsplash Noralf Trønnes
2018-04-13 16:53 [RFC v4 00/25] drm: Add generic fbdev emulation Noralf Trønnes
2018-04-13 16:53 ` [RFC v4 18/25] drm/client: Make the display modes available to clients Noralf Trønnes
2018-04-14 11:52 [RFC v4 00/25] drm: Add generic fbdev emulation Noralf Trønnes
2018-04-14 11:53 ` [RFC v4 18/25] drm/client: Make the display modes available to clients Noralf Trønnes

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20180412161237.9314-7-noralf@tronnes.org \
    --to=noralf@tronnes.org \
    --cc=daniel.vetter@ffwll.ch \
    --cc=dh.herrmann@gmail.com \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=intel-gfx@lists.freedesktop.org \
    --cc=laurent.pinchart@ideasonboard.com \
    --cc=mstaudt@suse.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.