All of lore.kernel.org
 help / color / mirror / Atom feed
From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
To: dri-devel@lists.freedesktop.org, linux-fbdev@vger.kernel.org,
	linux-media@vger.kernel.org
Cc: "Sebastien Guiriec" <s-guiriec@ti.com>,
	"Jesse Barnes" <jesse.barnes@intel.com>,
	"Benjamin Gaignard" <benjamin.gaignard@linaro.org>,
	"Tom Gall" <tom.gall@linaro.org>,
	"Kyungmin Park" <kyungmin.park@samsung.com>,
	"Tomi Valkeinen" <tomi.valkeinen@ti.com>,
	"Stephen Warren" <swarren@wwwdotorg.org>,
	"Mark Zhang" <markz@nvidia.com>,
	"Stéphane Marchesin" <stephane.marchesin@gmail.com>,
	"Alexandre Courbot" <acourbot@nvidia.com>,
	"Ragesh Radhakrishnan" <Ragesh.R@linaro.org>,
	"Thomas Petazzoni" <thomas.petazzoni@free-electrons.com>,
	"Sunil Joshi" <joshi@samsung.com>,
	"Maxime Ripard" <maxime.ripard@free-electrons.com>,
	"Vikas Sajjan" <vikas.sajjan@linaro.org>,
	"Marcus Lorentzon" <marcus.lorentzon@huawei.com>
Subject: [PATCH/RFC v3 04/19] video: display: Add display entity notifier
Date: Fri,  9 Aug 2013 19:14:55 +0200	[thread overview]
Message-ID: <1376068510-30363-5-git-send-email-laurent.pinchart+renesas@ideasonboard.com> (raw)
In-Reply-To: <1376068510-30363-1-git-send-email-laurent.pinchart+renesas@ideasonboard.com>

Display entities are initialized by they respective drivers
asynchronously with the master display driver. The notifier
infrastructure allows display drivers to create a list of entities they
need (based on platform data) and be notified when those entities are
added to or removed from the system.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/video/display/Makefile           |   3 +-
 drivers/video/display/display-notifier.c | 304 +++++++++++++++++++++++++++++++
 include/video/display.h                  |  66 +++++++
 3 files changed, 372 insertions(+), 1 deletion(-)
 create mode 100644 drivers/video/display/display-notifier.c

diff --git a/drivers/video/display/Makefile b/drivers/video/display/Makefile
index 3054adc..b907aad 100644
--- a/drivers/video/display/Makefile
+++ b/drivers/video/display/Makefile
@@ -1,2 +1,3 @@
-display-y					:= display-core.o
+display-y					:= display-core.o \
+						   display-notifier.o
 obj-$(CONFIG_DISPLAY_CORE)			+= display.o
diff --git a/drivers/video/display/display-notifier.c b/drivers/video/display/display-notifier.c
new file mode 100644
index 0000000..c9210ec
--- /dev/null
+++ b/drivers/video/display/display-notifier.c
@@ -0,0 +1,304 @@
+/*
+ * Display Notifier
+ *
+ * Copyright (C) 2013 Renesas Solutions Corp.
+ *
+ * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/device.h>
+#include <linux/export.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+
+#include <video/display.h>
+
+static LIST_HEAD(display_entity_list);
+static LIST_HEAD(display_entity_notifiers);
+static DEFINE_MUTEX(display_entity_mutex);
+
+/* -----------------------------------------------------------------------------
+ * Notifiers
+ */
+
+static bool match_platform(struct device *dev,
+			   struct display_entity_match *match)
+{
+	pr_debug("%s: matching device '%s' with name '%s'\n", __func__,
+		 dev_name(dev), match->match.platform.name);
+
+	return !strcmp(match->match.platform.name, dev_name(dev));
+}
+
+static struct display_entity_match *
+display_entity_notifier_match(struct display_entity_notifier *notifier,
+			      struct display_entity *entity)
+{
+	bool (*match_func)(struct device *, struct display_entity_match *);
+	struct display_entity_match *match;
+
+	pr_debug("%s: matching entity '%s' (ptr 0x%p dev '%s')\n", __func__,
+		 entity->name, entity, dev_name(entity->dev));
+
+	list_for_each_entry(match, &notifier->waiting, list) {
+		switch (match->type) {
+		default:
+		case DISPLAY_ENTITY_BUS_PLATFORM:
+			match_func = match_platform;
+			break;
+		}
+
+		if (match_func(entity->dev, match))
+			return match;
+	}
+
+	return NULL;
+}
+
+static void display_entity_notifier_cleanup(struct display_entity *entity)
+{
+	entity->match = NULL;
+	entity->notifier = NULL;
+}
+
+static int
+display_entity_notifier_notify(struct display_entity_notifier *notifier,
+			       struct display_entity *entity,
+			       struct display_entity_match *match)
+{
+	int ret;
+
+	pr_debug("%s: notifying device '%s' for entity '%s' (ptr 0x%p dev '%s')\n",
+		 __func__, dev_name(notifier->dev), entity->name, entity,
+		 dev_name(entity->dev));
+
+	/* Remove the match from waiting list. */
+	list_del(&match->list);
+	entity->match = match;
+	entity->notifier = notifier;
+
+	if (notifier->bound) {
+		ret = notifier->bound(notifier, entity, match);
+		if (ret < 0)
+			goto error_bound;
+	}
+
+	/* Move the entity from the global list to the notifier's done list. */
+	list_move(&entity->list, &notifier->done);
+
+	if (list_empty(&notifier->waiting) && notifier->complete) {
+		pr_debug("%s: notifying device '%s' of completion\n", __func__,
+			 dev_name(notifier->dev));
+		ret = notifier->complete(notifier);
+		if (ret < 0)
+			goto error_complete;
+	}
+
+	return 0;
+
+error_complete:
+	/* Move the entity back to the global list. */
+	list_move(&entity->list, &display_entity_list);
+	if (notifier->unbind)
+		notifier->unbind(notifier, entity, match);
+error_bound:
+	/* Put the match back to the waiting list. */
+	list_add_tail(&match->list, &notifier->waiting);
+	display_entity_notifier_cleanup(entity);
+
+	return ret;
+}
+
+/**
+ * display_entity_register_notifier - register a display entity notifier
+ * @notifier: display entity notifier structure we want to register
+ *
+ * Display entity notifiers are called to notify drivers of display
+ * entity-related events for matching display_entitys.
+ *
+ * Notifiers and display_entitys are matched through the device they correspond
+ * to. If the notifier dev field is equal to the display entity dev field the
+ * notifier will be called when an event is reported. Notifiers with a NULL dev
+ * field act as catch-all and will be called for all display_entitys.
+ *
+ * Supported events are
+ *
+ * - DISPLAY_ENTITY_NOTIFIER_CONNECT reports display entity connection and is
+ *   sent at display entity or notifier registration time
+ * - DISPLAY_ENTITY_NOTIFIER_DISCONNECT reports display entity disconnection and
+ *   is sent at display entity unregistration time
+ *
+ * Registering a notifier sends DISPLAY_ENTITY_NOTIFIER_CONNECT events for all
+ * previously registered display_entitys that match the notifiers.
+ *
+ * Return 0 on success.
+ */
+int display_entity_register_notifier(struct display_entity_notifier *notifier)
+{
+	struct display_entity_match *match;
+	struct display_entity *entity;
+	struct display_entity *next;
+	unsigned int i;
+	int ret = 0;
+
+	if (notifier->num_entities == 0)
+		return -EINVAL;
+
+	INIT_LIST_HEAD(&notifier->waiting);
+	INIT_LIST_HEAD(&notifier->done);
+
+	for (i = 0; i < notifier->num_entities; i++) {
+		match = &notifier->entities[i];
+
+		switch (match->type) {
+		case DISPLAY_ENTITY_BUS_PLATFORM:
+			break;
+		default:
+			dev_err(notifier->dev,
+				"%s: Invalid bus type %u on %p\n", __func__,
+				match->type, match);
+			return -EINVAL;
+		}
+
+		list_add_tail(&match->list, &notifier->waiting);
+	}
+
+	mutex_lock(&display_entity_mutex);
+
+	list_add_tail(&notifier->list, &display_entity_notifiers);
+
+	list_for_each_entry_safe(entity, next, &display_entity_list, list) {
+		match = display_entity_notifier_match(notifier, entity);
+		if (!match)
+			continue;
+
+		ret = display_entity_notifier_notify(notifier, entity, match);
+		if (ret)
+			break;
+	}
+
+	mutex_unlock(&display_entity_mutex);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(display_entity_register_notifier);
+
+/**
+ * display_entity_unregister_notifier - unregister a display entity notifier
+ * @notifier: display entity notifier to be unregistered
+ *
+ * Unregistration guarantees that the notifier will never be called upon return
+ * of this function.
+ */
+void display_entity_unregister_notifier(struct display_entity_notifier *notifier)
+{
+	struct display_entity *entity;
+	struct display_entity *next;
+
+	if (notifier->num_entities == 0)
+		return;
+
+	mutex_lock(&display_entity_mutex);
+
+	list_del(&notifier->list);
+
+	list_for_each_entry_safe(entity, next, &notifier->done, list) {
+		if (notifier->unbind)
+			notifier->unbind(notifier, entity, entity->match);
+
+		/* Move the entity back to the global list. */
+		display_entity_notifier_cleanup(entity);
+		list_move(&entity->list, &display_entity_list);
+	}
+	mutex_unlock(&display_entity_mutex);
+}
+EXPORT_SYMBOL_GPL(display_entity_unregister_notifier);
+
+/* -----------------------------------------------------------------------------
+ * Entity Registration
+ */
+
+/**
+ * display_entity_add - add a display entity to the list of available entities
+ * @entity: display entity to be added
+ *
+ * Add the display entity to the list of available entities and send the
+ * DISPLAY_ENTITY_NOTIFIER_CONNECT event to all matching registered notifiers.
+ *
+ * Return 0 on success.
+ */
+int display_entity_add(struct display_entity *entity)
+{
+	struct display_entity_notifier *notifier;
+	struct display_entity_match *match = NULL;
+
+	pr_debug("%s: adding entity '%s' (ptr 0x%p dev '%s')\n", __func__,
+		 entity->name, entity, dev_name(entity->dev));
+
+	mutex_lock(&display_entity_mutex);
+
+	/* Add the entity to the global unbound entities list. It will later be
+	 * moved to the notifier done list by display_entity_notifier_notify().
+	 */
+	list_add_tail(&entity->list, &display_entity_list);
+
+	list_for_each_entry(notifier, &display_entity_notifiers, list) {
+		match = display_entity_notifier_match(notifier, entity);
+		if (match)
+			break;
+	}
+
+	if (match) {
+		/* A match has been found, notify the notifier. */
+		display_entity_notifier_notify(notifier, entity, match);
+	}
+
+	mutex_unlock(&display_entity_mutex);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(display_entity_add);
+
+/**
+ * display_entity_remove - removea display entity
+ * @entity: display entity to be removed
+ *
+ * Remove the display entity from the list of available entities and send the
+ * DISPLAY_ENTITY_NOTIFIER_DISCONNECT event to all matching registered
+ * notifiers.
+ */
+void display_entity_remove(struct display_entity *entity)
+{
+	struct display_entity_notifier *notifier = entity->notifier;
+	struct display_entity_match *match = entity->match;
+
+	pr_debug("%s: removing entity '%s' (ptr 0x%p dev '%s')\n", __func__,
+		 entity->name, entity, dev_name(entity->dev));
+
+	if (!notifier) {
+		/* Remove the entity from the global list. */
+		list_del(&entity->list);
+		return;
+	}
+
+	mutex_lock(&display_entity_mutex);
+
+	if (notifier->unbind)
+		notifier->unbind(notifier, entity, match);
+
+	/* Remove the entity from the notifier's done list. */
+	display_entity_notifier_cleanup(entity);
+	list_del(&entity->list);
+
+	/* Move the match back to the waiting list. */
+	list_add_tail(&match->list, &notifier->waiting);
+
+	mutex_unlock(&display_entity_mutex);
+}
+EXPORT_SYMBOL_GPL(display_entity_remove);
diff --git a/include/video/display.h b/include/video/display.h
index fef05a68..2063694 100644
--- a/include/video/display.h
+++ b/include/video/display.h
@@ -23,6 +23,8 @@
  */
 
 struct display_entity;
+struct display_entity_match;
+struct display_entity_notify;
 struct videomode;
 
 /**
@@ -101,6 +103,9 @@ struct display_entity {
 	char name[32];
 	struct media_entity entity;
 
+	struct display_entity_match *match;
+	struct display_entity_notifier *notifier;
+
 	const struct display_entity_ops *ops;
 
 	void(*release)(struct display_entity *ent);
@@ -140,4 +145,65 @@ int display_entity_get_params(struct display_entity *entity, unsigned int port,
 int display_entity_set_stream(struct display_entity *entity, unsigned int port,
 			      enum display_entity_stream_state state);
 
+/* -----------------------------------------------------------------------------
+ * Notifier
+ */
+
+enum display_entity_bus_type {
+	DISPLAY_ENTITY_BUS_PLATFORM,
+};
+
+/**
+ * struct display_entity_match - Display entity description
+ * @type: display entity bus type
+ * @match.platform.name: platform device name
+ * @match.dt.node: DT node
+ * @list: link match objects waiting to be matched
+ */
+struct display_entity_match {
+	enum display_entity_bus_type type;
+	union {
+		struct {
+			const char *name;
+		} platform;
+	} match;
+
+	struct list_head list;
+};
+
+/**
+ * display_entity_notifier - display entity notifier
+ * @num_entities: number of display entities
+ * @entities: array of pointers to subdevice descriptors
+ * @waiting: list of struct v4l2_async_subdev, waiting for their drivers
+ * @done: list of struct v4l2_async_subdev_list, already probed
+ * @list: member in a global list of notifiers
+ * @bound: a display entity has been registered
+ * @complete: all display entities have been registered
+ * @unbind: a display entity is being unregistered
+ */
+struct display_entity_notifier {
+	struct device *dev;
+
+	unsigned int num_entities;
+	struct display_entity_match *entities;
+	struct list_head waiting;
+	struct list_head done;
+	struct list_head list;
+
+	int (*bound)(struct display_entity_notifier *notifier,
+		     struct display_entity *entity,
+		     struct display_entity_match *match);
+	int (*complete)(struct display_entity_notifier *notifier);
+	void (*unbind)(struct display_entity_notifier *notifier,
+		       struct display_entity *entity,
+		       struct display_entity_match *match);
+};
+
+int display_entity_register_notifier(struct display_entity_notifier *notifier);
+void display_entity_unregister_notifier(struct display_entity_notifier *notifier);
+
+int display_entity_add(struct display_entity *entity);
+void display_entity_remove(struct display_entity *entity);
+
 #endif /* __DISPLAY_H__ */
-- 
1.8.1.5

  parent reply	other threads:[~2013-08-09 17:14 UTC|newest]

Thread overview: 83+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-08-09 17:14 [PATCH/RFC v3 00/19] Common Display Framework Laurent Pinchart
2013-08-09 17:14 ` [PATCH/RFC v3 01/19] OMAPDSS: panels: Rename Kconfig options to OMAP2_DISPLAY_* Laurent Pinchart
2013-08-09 17:14 ` [PATCH/RFC v3 02/19] video: Add Common Display Framework core Laurent Pinchart
2013-09-02  8:42   ` Tomi Valkeinen
2013-09-03 11:29     ` Laurent Pinchart
2013-08-09 17:14 ` [PATCH/RFC v3 03/19] video: display: Add video and stream control operations Laurent Pinchart
2013-08-09 17:14 ` Laurent Pinchart [this message]
2013-08-09 17:14 ` [PATCH/RFC v3 05/19] video: display: Graph helpers Laurent Pinchart
2013-08-09 17:14 ` [PATCH/RFC v3 06/19] video: display: OF support Laurent Pinchart
2013-08-13 14:37   ` Philipp Zabel
2013-08-21  1:02     ` Laurent Pinchart
2013-08-21  9:10       ` Philipp Zabel
2013-08-22  0:51         ` Laurent Pinchart
2013-08-09 17:14 ` [PATCH/RFC v3 07/19] video: display: Add pixel coding definitions Laurent Pinchart
2013-08-09 17:14 ` [PATCH/RFC v3 08/19] video: display: Add MIPI DBI bus support Laurent Pinchart
2013-08-14  0:52   ` Rob Clark
2013-08-20 13:26     ` Laurent Pinchart
2013-08-26 11:10   ` Tomi Valkeinen
2013-09-06 14:09     ` Laurent Pinchart
2013-09-06 15:43       ` Tomi Valkeinen
2013-09-07  9:35         ` Tomi Valkeinen
2013-09-04 10:50   ` Vikas Sajjan
2013-09-06 14:37     ` Laurent Pinchart
2013-09-18 10:59       ` Vikas Sajjan
2013-09-04 12:52   ` Vikas Sajjan
2013-09-06 14:56     ` Laurent Pinchart
2013-08-09 17:15 ` [PATCH/RFC v3 09/19] video: panel: Add DPI panel support Laurent Pinchart
2013-08-09 17:15 ` [PATCH/RFC v3 10/19] video: panel: Add R61505 " Laurent Pinchart
2013-08-09 17:15 ` [PATCH/RFC v3 11/19] video: panel: Add R61517 " Laurent Pinchart
2013-08-09 17:15 ` [PATCH/RFC v3 12/19] video: display: Add VGA Digital to Analog Converter support Laurent Pinchart
2013-08-09 17:15 ` [PATCH/RFC v3 13/19] video: display: Add VGA connector support Laurent Pinchart
2013-08-09 17:15 ` [PATCH/RFC v3 14/19] ARM: shmobile: r8a7790: Add DU clocks for DT Laurent Pinchart
2013-08-09 17:15 ` [PATCH/RFC v3 15/19] ARM: shmobile: r8a7790: Add DU device node to device tree Laurent Pinchart
2013-08-09 17:15 ` [PATCH/RFC v3 16/19] ARM: shmobile: marzen: Port DU platform data to CDF Laurent Pinchart
2013-08-09 17:15 ` [PATCH/RFC v3 17/19] ARM: shmobile: lager: " Laurent Pinchart
2013-08-09 17:15 ` [PATCH/RFC v3 18/19] ARM: shmobile: lager-reference: Add display device nodes to device tree Laurent Pinchart
2013-08-09 17:15 ` [PATCH/RFC v3 19/19] drm/rcar-du: Port to the Common Display Framework Laurent Pinchart
2013-08-14  0:43 ` [PATCH/RFC v3 00/19] " Rob Clark
2013-08-20 15:24   ` Laurent Pinchart
2013-08-20 18:40     ` Rob Clark
2013-08-21  7:09       ` Sascha Hauer
2013-08-21 12:22         ` Rob Clark
2013-09-06 16:16           ` Laurent Pinchart
2013-09-09 12:12           ` Tomi Valkeinen
2013-09-09 14:17             ` Rob Clark
2013-09-09 14:58               ` Tomi Valkeinen
2013-09-09 15:10                 ` Rob Clark
2013-09-02 11:06 ` Tomi Valkeinen
2013-09-30 13:48 ` Tomi Valkeinen
2013-10-02 12:23   ` Andrzej Hajda
2013-10-02 12:23     ` Andrzej Hajda
2013-10-02 13:24     ` Tomi Valkeinen
2013-10-02 13:24       ` Tomi Valkeinen
2013-10-02 13:24       ` Tomi Valkeinen
2013-10-09 14:08       ` Andrzej Hajda
2013-10-09 14:08         ` Andrzej Hajda
2013-10-11  6:37         ` Tomi Valkeinen
2013-10-11  6:37           ` Tomi Valkeinen
2013-10-11  6:37           ` Tomi Valkeinen
2013-10-11 11:19           ` Andrzej Hajda
2013-10-11 11:19             ` Andrzej Hajda
2013-10-11 12:30             ` Tomi Valkeinen
2013-10-11 12:30               ` Tomi Valkeinen
2013-10-11 12:30               ` Tomi Valkeinen
2013-10-11 14:16               ` Andrzej Hajda
2013-10-11 14:16                 ` Andrzej Hajda
2013-10-11 14:45                 ` Tomi Valkeinen
2013-10-11 14:45                   ` Tomi Valkeinen
2013-10-11 14:45                   ` Tomi Valkeinen
2013-10-17  7:48                   ` Andrzej Hajda
2013-10-17  7:48                     ` Andrzej Hajda
2013-10-17  8:18                     ` Tomi Valkeinen
2013-10-17  8:18                       ` Tomi Valkeinen
2013-10-17  8:18                       ` Tomi Valkeinen
2013-10-17 12:26                       ` Andrzej Hajda
2013-10-17 12:26                         ` Andrzej Hajda
2013-10-17 12:55                         ` Tomi Valkeinen
2013-10-17 12:55                           ` Tomi Valkeinen
2013-10-17 12:55                           ` Tomi Valkeinen
2013-10-18 11:55                           ` Andrzej Hajda
2013-10-18 11:55                             ` Andrzej Hajda
2013-08-09 23:02 Laurent Pinchart
2013-08-09 23:03 ` [PATCH/RFC v3 04/19] video: display: Add display entity notifier Laurent Pinchart
2013-08-09 23:03   ` Laurent Pinchart

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=1376068510-30363-5-git-send-email-laurent.pinchart+renesas@ideasonboard.com \
    --to=laurent.pinchart+renesas@ideasonboard.com \
    --cc=Ragesh.R@linaro.org \
    --cc=acourbot@nvidia.com \
    --cc=benjamin.gaignard@linaro.org \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=jesse.barnes@intel.com \
    --cc=joshi@samsung.com \
    --cc=kyungmin.park@samsung.com \
    --cc=linux-fbdev@vger.kernel.org \
    --cc=linux-media@vger.kernel.org \
    --cc=marcus.lorentzon@huawei.com \
    --cc=markz@nvidia.com \
    --cc=maxime.ripard@free-electrons.com \
    --cc=s-guiriec@ti.com \
    --cc=stephane.marchesin@gmail.com \
    --cc=swarren@wwwdotorg.org \
    --cc=thomas.petazzoni@free-electrons.com \
    --cc=tom.gall@linaro.org \
    --cc=tomi.valkeinen@ti.com \
    --cc=vikas.sajjan@linaro.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 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.