[RFC v4 07/25] drm: Begin an API for in-kernel clients

Noralf Trønnes noralf at tronnes.org
Sat Apr 14 11:53:00 UTC 2018


This the beginning of an API for in-kernel clients.
First out is a display representation that will be used by drm_fb_helper
in order to move out its mode setting code.

Signed-off-by: Noralf Trønnes <noralf at tronnes.org>
---
 drivers/gpu/drm/Makefile     |   2 +-
 drivers/gpu/drm/drm_client.c | 119 +++++++++++++++++++++++++++++++++++++++++++
 include/drm/drm_client.h     |  44 ++++++++++++++++
 3 files changed, 164 insertions(+), 1 deletion(-)
 create mode 100644 drivers/gpu/drm/drm_client.c
 create mode 100644 include/drm/drm_client.h

diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index 9d66657ea117..d25afa136d8f 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -18,7 +18,7 @@ drm-y       :=	drm_auth.o drm_bufs.o drm_cache.o \
 		drm_encoder.o drm_mode_object.o drm_property.o \
 		drm_plane.o drm_color_mgmt.o drm_print.o \
 		drm_dumb_buffers.o drm_mode_config.o drm_vblank.o \
-		drm_syncobj.o drm_lease.o
+		drm_syncobj.o drm_lease.o drm_client.o
 
 drm-$(CONFIG_DRM_LIB_RANDOM) += lib/drm_random.o
 drm-$(CONFIG_DRM_VM) += drm_vm.o
diff --git a/drivers/gpu/drm/drm_client.c b/drivers/gpu/drm/drm_client.c
new file mode 100644
index 000000000000..7c31a6efb2f4
--- /dev/null
+++ b/drivers/gpu/drm/drm_client.c
@@ -0,0 +1,119 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2018 Noralf Trønnes
+ *
+ * For parts copied from drm_fb_helper:
+ * Copyright (c) 2006-2009 Red Hat Inc.
+ * Copyright (c) 2006-2008 Intel Corporation
+ * Copyright (c) 2007 Dave Airlie <airlied at linux.ie>
+ */
+
+#include <linux/slab.h>
+
+#include <drm/drm_client.h>
+#include <drm/drm_connector.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_device.h>
+#include <drm/drm_modes.h>
+
+/**
+ * drm_client_display_create() - Create display structure
+ * @dev: DRM device
+ *
+ * This function creates a display structure for clients backed by an array of
+ * &drm_mode_set, one per CRTC.
+ *
+ * Returns:
+ * A &drm_client_display or an error pointer on allocation failure.
+ */
+struct drm_client_display *drm_client_display_create(struct drm_device *dev)
+{
+	unsigned int num_crtc = dev->mode_config.num_crtc;
+	struct drm_client_display *display;
+	struct drm_mode_set *modeset;
+	struct drm_crtc *crtc;
+	unsigned int i = 0;
+
+	display = kzalloc(sizeof(*display), GFP_KERNEL);
+	if (!display)
+		return ERR_PTR(-ENOMEM);
+
+	/* Add NULL terminating entry to enable index less iteration */
+	display->modesets = kcalloc(num_crtc + 1, sizeof(*display->modesets), GFP_KERNEL);
+	if (!display->modesets) {
+		kfree(display);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	display->dev = dev;
+	display->modeset_count = num_crtc;
+
+	drm_for_each_crtc(crtc, dev)
+		display->modesets[i++].crtc = crtc;
+
+	drm_client_display_for_each_modeset(modeset, display) {
+		/* One connector per crtc except for the cloned case */
+		modeset->connectors = kcalloc(2, sizeof(*modeset->connectors), GFP_KERNEL);
+		if (!modeset->connectors)
+			goto err_free;
+	}
+
+	return display;
+
+err_free:
+	drm_client_display_free(display);
+
+	return ERR_PTR(-ENOMEM);
+}
+EXPORT_SYMBOL(drm_client_display_create);
+
+/**
+ * drm_client_display_free() - Free display structure
+ * @display: Client display
+ *
+ * This function frees the structure allocated by drm_client_display_create().
+ * It also destroys display modes and puts connectors.
+ */
+void drm_client_display_free(struct drm_client_display *display)
+{
+	struct drm_mode_set *modeset;
+	unsigned int i;
+
+	if (!display)
+		return;
+
+	drm_client_display_for_each_modeset(modeset, display) {
+		if (modeset->mode)
+			drm_mode_destroy(display->dev, modeset->mode);
+
+		for (i = 0; i < modeset->num_connectors; i++)
+			drm_connector_put(modeset->connectors[i]);
+		kfree(modeset->connectors);
+	}
+	kfree(display->modesets);
+	kfree(display);
+}
+EXPORT_SYMBOL(drm_client_display_free);
+
+/**
+ * drm_client_display_find_modeset() - Find modeset matching a CRTC
+ * @display: Client display
+ * @crtc: CRTC
+ *
+ * This function looks up the @display modeset connected to @crtc.
+ *
+ * Returns:
+ * A &drm_mode_set or NULL.
+ */
+struct drm_mode_set *
+drm_client_display_find_modeset(struct drm_client_display *display, struct drm_crtc *crtc)
+{
+	struct drm_mode_set *modeset;
+
+	drm_client_display_for_each_modeset(modeset, display)
+		if (modeset->crtc == crtc)
+			return modeset;
+
+	return NULL;
+}
+EXPORT_SYMBOL(drm_client_display_find_modeset);
diff --git a/include/drm/drm_client.h b/include/drm/drm_client.h
new file mode 100644
index 000000000000..b6a057802769
--- /dev/null
+++ b/include/drm/drm_client.h
@@ -0,0 +1,44 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef _DRM_CLIENT_H_
+#define _DRM_CLIENT_H_
+
+struct drm_crtc;
+struct drm_device;
+struct drm_mode_set;
+
+/**
+ * struct drm_client_display - DRM client display
+ */
+struct drm_client_display {
+	/**
+	 * @dev:
+	 *
+	 * DRM device.
+	 */
+	struct drm_device *dev;
+
+	/**
+	 * @modesets:
+	 *
+	 * Per CRTC array of modeset configurations.
+	 */
+	struct drm_mode_set *modesets;
+
+	/**
+	 * @modeset_count:
+	 *
+	 * Number of modesets
+	 */
+	unsigned int modeset_count;
+};
+
+struct drm_client_display *drm_client_display_create(struct drm_device *dev);
+void drm_client_display_free(struct drm_client_display *display);
+struct drm_mode_set *
+drm_client_display_find_modeset(struct drm_client_display *display, struct drm_crtc *crtc);
+
+#define drm_client_display_for_each_modeset(modeset, display) \
+	for (modeset = display->modesets; modeset->crtc; modeset++)
+
+#endif
-- 
2.15.1



More information about the dri-devel mailing list