dri-devel.lists.freedesktop.org archive mirror
 help / color / mirror / Atom feed
From: "Noralf Trønnes" <noralf@tronnes.org>
To: dri-devel@lists.freedesktop.org
Cc: intel-gfx@lists.freedesktop.org, "Noralf Trønnes" <noralf@tronnes.org>
Subject: [RFC v4 18/25] drm/client: Make the display modes available to clients
Date: Sat, 14 Apr 2018 13:53:11 +0200	[thread overview]
Message-ID: <20180414115318.14500-19-noralf@tronnes.org> (raw)
In-Reply-To: <20180414115318.14500-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-14 11:53 UTC|newest]

Thread overview: 46+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-04-14 11:52 [RFC v4 00/25] drm: Add generic fbdev emulation Noralf Trønnes
2018-04-14 11:52 ` [RFC v4 01/25] drm: provide management functions for drm_file Noralf Trønnes
2018-04-14 11:52 ` [RFC v4 02/25] drm/file: Don't set master on in-kernel clients Noralf Trønnes
2018-04-14 11:52 ` [RFC v4 03/25] drm/fb-helper: No need to cache rotation and sw_rotations Noralf Trønnes
2018-04-14 11:52 ` [RFC v4 04/25] drm/fb-helper: Remove drm_fb_helper_debug_enter/leave() Noralf Trønnes
2018-04-14 11:52 ` [RFC v4 05/25] drm/fb-helper: dpms_legacy(): Only set on connectors in use Noralf Trønnes
2018-04-14 11:52 ` [RFC v4 06/25] drm/atomic: Move __drm_atomic_helper_disable_plane/set_config() Noralf Trønnes
2018-04-16  8:30   ` Daniel Vetter
2018-04-14 11:53 ` [RFC v4 07/25] drm: Begin an API for in-kernel clients Noralf Trønnes
2018-04-14 11:53 ` [RFC v4 08/25] drm/fb-helper: Use struct drm_client_display Noralf Trønnes
2018-04-14 11:53 ` [RFC v4 09/25] drm/fb-helper: Move modeset commit code to drm_client Noralf Trønnes
2018-04-14 11:53 ` [RFC v4 10/25] drm/connector: Add drm_connector_has_preferred_mode/pick_cmdline_mode() Noralf Trønnes
2018-04-14 11:53 ` [RFC v4 11/25] drm/connector: Add connector array functions Noralf Trønnes
2018-04-16  8:33   ` Daniel Vetter
2018-04-14 11:53 ` [RFC v4 12/25] drm/i915: Add drm_driver->initial_client_display callback Noralf Trønnes
2018-04-16  8:38   ` Daniel Vetter
2019-03-01 11:46     ` [Intel-gfx] " Noralf Trønnes
2019-03-01 11:51       ` Daniel Vetter
2018-04-14 11:53 ` [RFC v4 13/25] drm/fb-helper: Remove struct drm_fb_helper_crtc Noralf Trønnes
2018-04-14 11:53 ` [RFC v4 14/25] drm/fb-helper: Remove struct drm_fb_helper_connector Noralf Trønnes
2018-04-14 11:53 ` [RFC v4 15/25] drm/fb-helper: Move modeset config code to drm_client Noralf Trønnes
2018-04-14 11:53 ` [RFC v4 16/25] drm: Make ioctls available for in-kernel clients Noralf Trønnes
2018-04-16  9:04   ` Daniel Vetter
2018-04-14 11:53 ` [RFC v4 17/25] drm/client: Bail out if there's a DRM master Noralf Trønnes
2018-04-16  8:45   ` Daniel Vetter
2018-04-14 11:53 ` Noralf Trønnes [this message]
2018-04-14 11:53 ` [RFC v4 19/25] drm/client: Finish the in-kernel client API Noralf Trønnes
2018-04-16  8:27   ` [Intel-gfx] " Daniel Vetter
2018-04-16 15:58     ` Noralf Trønnes
2018-04-17  8:08       ` Daniel Vetter
2018-04-14 11:53 ` [RFC v4 20/25] drm/prime: Don't pin module on export for in-kernel clients Noralf Trønnes
2018-04-14 11:53 ` [RFC v4 21/25] drm/fb-helper: Add drm_fb_helper_fb_open/release() Noralf Trønnes
2018-04-16  8:46   ` Daniel Vetter
2018-04-16 16:10     ` Noralf Trønnes
2018-04-17  8:14       ` [Intel-gfx] " Daniel Vetter
2018-04-14 11:53 ` [RFC v4 22/25] drm/fb-helper: Add generic fbdev emulation Noralf Trønnes
2018-04-16  8:52   ` Daniel Vetter
2018-04-14 11:53 ` [RFC v4 23/25] drm: Add DRM device registered notifier Noralf Trønnes
2018-04-17 10:16   ` Daniel Vetter
2018-04-14 11:53 ` [RFC v4 24/25] drm/client: Hack: Add bootsplash Noralf Trønnes
2018-04-14 11:53 ` [RFC v4 25/25] drm/client: Hack: Add DRM VT console client Noralf Trønnes
2018-04-16  8:21 ` [RFC v4 00/25] drm: Add generic fbdev emulation Daniel Vetter
2018-04-16 18:49   ` Noralf Trønnes
2018-04-17  8:10     ` [Intel-gfx] " Daniel Vetter
  -- strict thread matches above, loose matches on Subject: below --
2018-04-13 16:53 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-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 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=20180414115318.14500-19-noralf@tronnes.org \
    --to=noralf@tronnes.org \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=intel-gfx@lists.freedesktop.org \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).