Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / Atom feed
* [PATCH 0/7] Add HDMI audio support on RK3288 veyron board
@ 2019-06-03  4:32 Cheng-Yi Chiang
  2019-06-03  4:32 ` [PATCH 1/7] video: add HDMI state notifier support Cheng-Yi Chiang
                   ` (6 more replies)
  0 siblings, 7 replies; 30+ messages in thread
From: Cheng-Yi Chiang @ 2019-06-03  4:32 UTC (permalink / raw)
  To: linux-kernel
  Cc: alsa-devel, Heiko Stuebner, David Airlie, dri-devel,
	Liam Girdwood, Hans Verkuil, Andrzej Hajda, Laurent Pinchart,
	Cheng-Yi Chiang, Takashi Iwai, linux-rockchip, dgreid,
	linux-media, devicetree, tzungbi, Philipp Zabel,
	Bartlomiej Zolnierkiewicz, Russell King, Rob Herring,
	Jaroslav Kysela, linux-arm-kernel, Greg Kroah-Hartman, dianders,
	Mark Brown, Daniel Vetter

This patch series is to support HDMI audio on RK3288 veyron board.

To support jack reporting, there are two old patches:

video: add HDMI state notifier support

<https://lore.kernel.org/linux-media/20161213150813.37966-2-hverkuil@xs4all.nl/>

ASoC: hdmi-codec: use HDMI state notifier to add jack support

<https://patchwork.kernel.org/patch/9430355/>

They are modified to pass checkpatch checking based on latest ASoC tree

https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git

for-next branch.

With these two patches at hand, hdmi-notifier support is then added to dw-hdmi
driver so the plug/unplug event can be passed to codec driver.

The rest patches are about machine driver rockchip_max98090.
A HDMI DAI link is added for HDMI playback so there will be two devices on
this sound card. One for max98090 and one for HDMI.
The HDMI node is passed from DTS so machine driver can set the correct
hdmi-notifier on codec driver.

Cheng-Yi Chiang (5):
  drm/bridge/synopsys: dw-hdmi: Add HDMI notifier support
  ASoC: rockchip_max98090: Add dai_link for HDMI
  ASoC: rockchip: rockchip-max98090: Add node for HDMI
  ASoC: rockchip_max98090: Add HDMI jack support
  ARM: dts: rockchip: Specify HDMI node to sound card node

Hans Verkuil (1):
  video: add HDMI state notifier support

Philipp Zabel (1):
  ASoC: hdmi-codec: use HDMI state notifier to add jack support

 .../bindings/sound/rockchip-max98090.txt      |   2 +
 MAINTAINERS                                   |   6 +
 .../boot/dts/rk3288-veyron-analog-audio.dtsi  |   1 +
 drivers/gpu/drm/bridge/synopsys/Kconfig       |   1 +
 drivers/gpu/drm/bridge/synopsys/dw-hdmi.c     |  28 +++-
 drivers/video/Kconfig                         |   3 +
 drivers/video/Makefile                        |   1 +
 drivers/video/hdmi-notifier.c                 | 145 ++++++++++++++++++
 include/linux/hdmi-notifier.h                 | 112 ++++++++++++++
 include/sound/hdmi-codec.h                    |   7 +
 sound/soc/codecs/Kconfig                      |   1 +
 sound/soc/codecs/hdmi-codec.c                 | 104 ++++++++++++-
 sound/soc/rockchip/rockchip_max98090.c        | 123 ++++++++++++---
 13 files changed, 508 insertions(+), 26 deletions(-)
 create mode 100644 drivers/video/hdmi-notifier.c
 create mode 100644 include/linux/hdmi-notifier.h

-- 
2.22.0.rc1.257.g3120a18244-goog


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH 1/7] video: add HDMI state notifier support
  2019-06-03  4:32 [PATCH 0/7] Add HDMI audio support on RK3288 veyron board Cheng-Yi Chiang
@ 2019-06-03  4:32 ` Cheng-Yi Chiang
  2019-06-03  7:45   ` Hans Verkuil
  2019-06-03  4:32 ` [PATCH 2/7] ASoC: hdmi-codec: use HDMI state notifier to add jack support Cheng-Yi Chiang
                   ` (5 subsequent siblings)
  6 siblings, 1 reply; 30+ messages in thread
From: Cheng-Yi Chiang @ 2019-06-03  4:32 UTC (permalink / raw)
  To: linux-kernel
  Cc: alsa-devel, Heiko Stuebner, David Airlie, dri-devel,
	Liam Girdwood, Hans Verkuil, Andrzej Hajda, Laurent Pinchart,
	Cheng-Yi Chiang, Takashi Iwai, linux-rockchip, Hans Verkuil,
	dgreid, linux-media, devicetree, tzungbi, Philipp Zabel,
	Bartlomiej Zolnierkiewicz, Russell King, Rob Herring,
	Jaroslav Kysela, linux-arm-kernel, Greg Kroah-Hartman, dianders,
	Mark Brown, Daniel Vetter

From: Hans Verkuil <hans.verkuil@cisco.com>

Add support for HDMI hotplug and EDID notifiers, which is used to convey
information from HDMI drivers to their CEC and audio counterparts.

Based on an earlier version from Russell King:

https://patchwork.kernel.org/patch/9277043/

The hdmi_notifier is a reference counted object containing the HDMI state
of an HDMI device.

When a new notifier is registered the current state will be reported to
that notifier at registration time.

Based on Hans Verkuil's patch:

https://patchwork.kernel.org/patch/9472521/

Modified by Cheng-Yi Chiang:
 - Add a section in MAINTAINER.
 - Changes connected and has_eld to bitfield of unsigned int.
 - Other minor fixes to pass checkpatch.pl --strict checks.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Acked-by: Philipp Zabel <p.zabel@pengutronix.de>
Signed-off-by: Cheng-Yi Chiang <cychiang@chromium.org>
---
The original patch is at
https://lore.kernel.org/linux-arm-kernel/20161213150813.37966-2-hverkuil@xs4all.nl

 MAINTAINERS                   |   6 ++
 drivers/video/Kconfig         |   3 +
 drivers/video/Makefile        |   1 +
 drivers/video/hdmi-notifier.c | 145 ++++++++++++++++++++++++++++++++++
 include/linux/hdmi-notifier.h | 112 ++++++++++++++++++++++++++
 5 files changed, 267 insertions(+)
 create mode 100644 drivers/video/hdmi-notifier.c
 create mode 100644 include/linux/hdmi-notifier.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 5cfbea4ce575..ffb7376f9509 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -16676,6 +16676,12 @@ W:	https://linuxtv.org
 S:	Maintained
 F:	drivers/media/platform/vicodec/*
 
+VIDEO FRAMEWORK
+M:	Hans Verkuil <hverkuil@xs4all.nl>
+L:	linux-media@vger.kernel.org
+F:	drivers/video/hdmi-notifier.*
+S:	Maintained
+
 VIDEO MULTIPLEXER DRIVER
 M:	Philipp Zabel <p.zabel@pengutronix.de>
 L:	linux-media@vger.kernel.org
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 83d3d271ca15..000ba9bc0ae7 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -34,6 +34,9 @@ config VIDEOMODE_HELPERS
 config HDMI
 	bool
 
+config HDMI_NOTIFIERS
+	bool
+
 endif # HAS_IOMEM
 
 if VT
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index df7650adede9..eff4736102ca 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -1,6 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0
 obj-$(CONFIG_VGASTATE)            += vgastate.o
 obj-$(CONFIG_HDMI)                += hdmi.o
+obj-$(CONFIG_HDMI_NOTIFIERS)      += hdmi-notifier.o
 
 obj-$(CONFIG_VT)		  += console/
 obj-$(CONFIG_FB_STI)		  += console/
diff --git a/drivers/video/hdmi-notifier.c b/drivers/video/hdmi-notifier.c
new file mode 100644
index 000000000000..d1eedf661648
--- /dev/null
+++ b/drivers/video/hdmi-notifier.c
@@ -0,0 +1,145 @@
+// SPDX-License-Identifier: GPL-2.0
+/* hdmi-notifier.c - notify interested parties of (dis)connect and EDID
+ * events
+ *
+ * Copyright 2016 Russell King <rmk+kernel@arm.linux.org.uk>
+ * Copyright 2016 Cisco Systems, Inc. and/or its affiliates.
+ * All rights reserved.
+ */
+
+#include <linux/export.h>
+#include <linux/hdmi-notifier.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/list.h>
+
+static LIST_HEAD(hdmi_notifiers);
+static DEFINE_MUTEX(hdmi_notifiers_lock);
+
+struct hdmi_notifier *hdmi_notifier_get(struct device *dev)
+{
+	struct hdmi_notifier *n;
+
+	mutex_lock(&hdmi_notifiers_lock);
+	list_for_each_entry(n, &hdmi_notifiers, head) {
+		if (n->dev == dev) {
+			mutex_unlock(&hdmi_notifiers_lock);
+			kref_get(&n->kref);
+			return n;
+		}
+	}
+	n = kzalloc(sizeof(*n), GFP_KERNEL);
+	if (!n)
+		goto unlock;
+	n->dev = dev;
+	mutex_init(&n->lock);
+	BLOCKING_INIT_NOTIFIER_HEAD(&n->notifiers);
+	kref_init(&n->kref);
+	list_add_tail(&n->head, &hdmi_notifiers);
+unlock:
+	mutex_unlock(&hdmi_notifiers_lock);
+	return n;
+}
+EXPORT_SYMBOL_GPL(hdmi_notifier_get);
+
+static void hdmi_notifier_release(struct kref *kref)
+{
+	struct hdmi_notifier *n =
+		container_of(kref, struct hdmi_notifier, kref);
+
+	mutex_lock(&hdmi_notifiers_lock);
+	list_del(&n->head);
+	mutex_unlock(&hdmi_notifiers_lock);
+	kfree(n->edid);
+	kfree(n);
+}
+
+void hdmi_notifier_put(struct hdmi_notifier *n)
+{
+	kref_put(&n->kref, hdmi_notifier_release);
+}
+EXPORT_SYMBOL_GPL(hdmi_notifier_put);
+
+int hdmi_notifier_register(struct hdmi_notifier *n, struct notifier_block *nb)
+{
+	int ret = blocking_notifier_chain_register(&n->notifiers, nb);
+
+	if (ret)
+		return ret;
+	kref_get(&n->kref);
+	mutex_lock(&n->lock);
+	if (n->connected) {
+		blocking_notifier_call_chain(&n->notifiers, HDMI_CONNECTED, n);
+		if (n->edid_size)
+			blocking_notifier_call_chain(&n->notifiers,
+						     HDMI_NEW_EDID, n);
+		if (n->has_eld)
+			blocking_notifier_call_chain(&n->notifiers,
+						     HDMI_NEW_ELD, n);
+	}
+	mutex_unlock(&n->lock);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(hdmi_notifier_register);
+
+int hdmi_notifier_unregister(struct hdmi_notifier *n, struct notifier_block *nb)
+{
+	int ret = blocking_notifier_chain_unregister(&n->notifiers, nb);
+
+	if (ret == 0)
+		hdmi_notifier_put(n);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(hdmi_notifier_unregister);
+
+void hdmi_event_connect(struct hdmi_notifier *n)
+{
+	mutex_lock(&n->lock);
+	n->connected = true;
+	blocking_notifier_call_chain(&n->notifiers, HDMI_CONNECTED, n);
+	mutex_unlock(&n->lock);
+}
+EXPORT_SYMBOL_GPL(hdmi_event_connect);
+
+void hdmi_event_disconnect(struct hdmi_notifier *n)
+{
+	mutex_lock(&n->lock);
+	n->connected = false;
+	n->has_eld = false;
+	n->edid_size = 0;
+	blocking_notifier_call_chain(&n->notifiers, HDMI_DISCONNECTED, n);
+	mutex_unlock(&n->lock);
+}
+EXPORT_SYMBOL_GPL(hdmi_event_disconnect);
+
+int hdmi_event_new_edid(struct hdmi_notifier *n, const void *edid, size_t size)
+{
+	mutex_lock(&n->lock);
+	if (n->edid_allocated_size < size) {
+		void *p = kmalloc(size, GFP_KERNEL);
+
+		if (!p) {
+			mutex_unlock(&n->lock);
+			return -ENOMEM;
+		}
+		kfree(n->edid);
+		n->edid = p;
+		n->edid_allocated_size = size;
+	}
+	memcpy(n->edid, edid, size);
+	n->edid_size = size;
+	blocking_notifier_call_chain(&n->notifiers, HDMI_NEW_EDID, n);
+	mutex_unlock(&n->lock);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(hdmi_event_new_edid);
+
+void hdmi_event_new_eld(struct hdmi_notifier *n, const u8 eld[128])
+{
+	mutex_lock(&n->lock);
+	memcpy(n->eld, eld, sizeof(n->eld));
+	n->has_eld = true;
+	blocking_notifier_call_chain(&n->notifiers, HDMI_NEW_ELD, n);
+	mutex_unlock(&n->lock);
+}
+EXPORT_SYMBOL_GPL(hdmi_event_new_eld);
diff --git a/include/linux/hdmi-notifier.h b/include/linux/hdmi-notifier.h
new file mode 100644
index 000000000000..c8f35110e3e3
--- /dev/null
+++ b/include/linux/hdmi-notifier.h
@@ -0,0 +1,112 @@
+/* SPDX-License-Identifier: GPL-2.0
+ * hdmi-notifier.h - notify interested parties of (dis)connect and EDID
+ * events
+ *
+ * Copyright 2016 Russell King <rmk+kernel@arm.linux.org.uk>
+ * Copyright 2016 Cisco Systems, Inc. and/or its affiliates.
+ * All rights reserved.
+ */
+
+#ifndef LINUX_HDMI_NOTIFIER_H
+#define LINUX_HDMI_NOTIFIER_H
+
+#include <linux/types.h>
+#include <linux/notifier.h>
+#include <linux/kref.h>
+
+enum {
+	HDMI_CONNECTED,
+	HDMI_DISCONNECTED,
+	HDMI_NEW_EDID,
+	HDMI_NEW_ELD,
+};
+
+struct device;
+
+struct hdmi_notifier {
+	/* Lock to protect callback registration and notification. */
+	struct mutex lock;
+	struct list_head head;
+	struct kref kref;
+	struct blocking_notifier_head notifiers;
+	struct device *dev;
+
+	/* Current state */
+	unsigned int connected : 1;
+	unsigned int has_eld : 1;
+	unsigned char eld[128];
+	void *edid;
+	size_t edid_size;
+	size_t edid_allocated_size;
+};
+
+/**
+ * hdmi_notifier_get - find or create a new hdmi_notifier for the given device.
+ * @dev: device that sends the events.
+ *
+ * If a notifier for device @dev already exists, then increase the refcount
+ * and return that notifier.
+ *
+ * If it doesn't exist, then allocate a new notifier struct and return a
+ * pointer to that new struct.
+ *
+ * Return NULL if the memory could not be allocated.
+ */
+struct hdmi_notifier *hdmi_notifier_get(struct device *dev);
+
+/**
+ * hdmi_notifier_put - decrease refcount and delete when the refcount reaches 0.
+ * @n: notifier
+ */
+void hdmi_notifier_put(struct hdmi_notifier *n);
+
+/**
+ * hdmi_notifier_register - register the notifier with the notifier_block.
+ * @n: the HDMI notifier
+ * @nb: the notifier_block
+ */
+int hdmi_notifier_register(struct hdmi_notifier *n, struct notifier_block *nb);
+
+/**
+ * hdmi_notifier_unregister - unregister the notifier with the notifier_block.
+ * @n: the HDMI notifier
+ * @nb: the notifier_block
+ */
+int hdmi_notifier_unregister(struct hdmi_notifier *n,
+			     struct notifier_block *nb);
+
+/**
+ * hdmi_event_connect - send a connect event.
+ * @n: the HDMI notifier
+ *
+ * Send an HDMI_CONNECTED event to any registered parties.
+ */
+void hdmi_event_connect(struct hdmi_notifier *n);
+
+/**
+ * hdmi_event_disconnect - send a disconnect event.
+ * @n: the HDMI notifier
+ *
+ * Send an HDMI_DISCONNECTED event to any registered parties.
+ */
+void hdmi_event_disconnect(struct hdmi_notifier *n);
+
+/**
+ * hdmi_event_new_edid - send a new EDID event.
+ * @n: the HDMI notifier
+ *
+ * Send an HDMI_NEW_EDID event to any registered parties.
+ * This function will make a copy the EDID so it can return -ENOMEM if
+ * no memory could be allocated.
+ */
+int hdmi_event_new_edid(struct hdmi_notifier *n, const void *edid, size_t size);
+
+/**
+ * hdmi_event_new_eld - send a new ELD event.
+ * @n: the HDMI notifier
+ *
+ * Send an HDMI_NEW_ELD event to any registered parties.
+ */
+void hdmi_event_new_eld(struct hdmi_notifier *n, const u8 eld[128]);
+
+#endif
-- 
2.22.0.rc1.257.g3120a18244-goog


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH 2/7] ASoC: hdmi-codec: use HDMI state notifier to add jack support
  2019-06-03  4:32 [PATCH 0/7] Add HDMI audio support on RK3288 veyron board Cheng-Yi Chiang
  2019-06-03  4:32 ` [PATCH 1/7] video: add HDMI state notifier support Cheng-Yi Chiang
@ 2019-06-03  4:32 ` Cheng-Yi Chiang
  2019-06-03  8:03   ` [alsa-devel] " Amadeusz Sławiński
  2019-06-03  4:32 ` [PATCH 3/7] drm/bridge/synopsys: dw-hdmi: Add HDMI notifier support Cheng-Yi Chiang
                   ` (4 subsequent siblings)
  6 siblings, 1 reply; 30+ messages in thread
From: Cheng-Yi Chiang @ 2019-06-03  4:32 UTC (permalink / raw)
  To: linux-kernel
  Cc: alsa-devel, Heiko Stuebner, David Airlie, dri-devel,
	Liam Girdwood, Hans Verkuil, Andrzej Hajda, Laurent Pinchart,
	Cheng-Yi Chiang, Takashi Iwai, linux-rockchip, dgreid,
	linux-media, devicetree, tzungbi, Philipp Zabel,
	Bartlomiej Zolnierkiewicz, Russell King, Rob Herring,
	Jaroslav Kysela, linux-arm-kernel, Greg Kroah-Hartman, dianders,
	Mark Brown, Daniel Vetter

From: Philipp Zabel <p.zabel@pengutronix.de>

Use HDMI connection / disconnection notifications to update an ALSA
jack object. Also make a copy of the ELD block after every change.

This was posted by Philipp Zabel at

https://patchwork.kernel.org/patch/9430747/

Modified by Cheng-Yi Chiang:
- Fix the conflict of removed hdmi_codec_remove ops.
- Other minor fix for the conflict with latest hdmi-codec on ASoC
  for-next tree.

Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
Signed-off-by: Cheng-Yi Chiang <cychiang@chromium.org>
---
The original patch is at https://patchwork.kernel.org/patch/9430747/
I could not find the LKML link for the patch.

 include/sound/hdmi-codec.h    |   7 +++
 sound/soc/codecs/Kconfig      |   1 +
 sound/soc/codecs/hdmi-codec.c | 104 +++++++++++++++++++++++++++++++++-
 3 files changed, 110 insertions(+), 2 deletions(-)

diff --git a/include/sound/hdmi-codec.h b/include/sound/hdmi-codec.h
index 9483c55f871b..4fa39c93363f 100644
--- a/include/sound/hdmi-codec.h
+++ b/include/sound/hdmi-codec.h
@@ -107,6 +107,13 @@ struct hdmi_codec_pdata {
 	void *data;
 };
 
+struct snd_soc_component;
+struct snd_soc_jack;
+
+int hdmi_codec_set_jack_detect(struct snd_soc_component *component,
+			       struct snd_soc_jack *jack,
+			       struct device *dev);
+
 #define HDMI_CODEC_DRV_NAME "hdmi-audio-codec"
 
 #endif /* __HDMI_CODEC_H__ */
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 8f577258080b..f5f6dd04234c 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -639,6 +639,7 @@ config SND_SOC_HDMI_CODEC
 	select SND_PCM_ELD
 	select SND_PCM_IEC958
 	select HDMI
+	select HDMI_NOTIFIERS
 
 config SND_SOC_ES7134
        tristate "Everest Semi ES7134 CODEC"
diff --git a/sound/soc/codecs/hdmi-codec.c b/sound/soc/codecs/hdmi-codec.c
index 6a0cc8d7e141..fe796a7475a5 100644
--- a/sound/soc/codecs/hdmi-codec.c
+++ b/sound/soc/codecs/hdmi-codec.c
@@ -12,9 +12,12 @@
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU
  * General Public License for more details.
  */
+#include <linux/hdmi-notifier.h>
 #include <linux/module.h>
+#include <linux/notifier.h>
 #include <linux/string.h>
 #include <sound/core.h>
+#include <sound/jack.h>
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
 #include <sound/soc.h>
@@ -282,6 +285,13 @@ struct hdmi_codec_priv {
 	struct snd_pcm_chmap *chmap_info;
 	unsigned int chmap_idx;
 	struct mutex lock;
+	struct snd_soc_jack *jack;
+	/* Lock to protect setting and getting eld. */
+	struct mutex eld_lock;
+	struct device *dev;
+	struct hdmi_notifier *notifier;
+	struct notifier_block nb;
+	unsigned int jack_status;
 };
 
 static const struct snd_soc_dapm_widget hdmi_widgets[] = {
@@ -308,7 +318,9 @@ static int hdmi_eld_ctl_get(struct snd_kcontrol *kcontrol,
 	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
 	struct hdmi_codec_priv *hcp = snd_soc_component_get_drvdata(component);
 
+	mutex_lock(&hcp->eld_lock);
 	memcpy(ucontrol->value.bytes.data, hcp->eld, sizeof(hcp->eld));
+	mutex_unlock(&hcp->eld_lock);
 
 	return 0;
 }
@@ -393,7 +405,7 @@ static int hdmi_codec_startup(struct snd_pcm_substream *substream,
 			      struct snd_soc_dai *dai)
 {
 	struct hdmi_codec_priv *hcp = snd_soc_dai_get_drvdata(dai);
-	int ret = 0;
+	int ret;
 
 	ret = mutex_trylock(&hcp->lock);
 	if (!ret) {
@@ -408,9 +420,9 @@ static int hdmi_codec_startup(struct snd_pcm_substream *substream,
 	}
 
 	if (hcp->hcd.ops->get_eld) {
+		mutex_lock(&hcp->eld_lock);
 		ret = hcp->hcd.ops->get_eld(dai->dev->parent, hcp->hcd.data,
 					    hcp->eld, sizeof(hcp->eld));
-
 		if (!ret) {
 			ret = snd_pcm_hw_constraint_eld(substream->runtime,
 							hcp->eld);
@@ -419,6 +431,7 @@ static int hdmi_codec_startup(struct snd_pcm_substream *substream,
 		}
 		/* Select chmap supported */
 		hdmi_codec_eld_chmap(hcp);
+		mutex_unlock(&hcp->eld_lock);
 	}
 	return 0;
 
@@ -747,6 +760,77 @@ static const struct snd_soc_component_driver hdmi_driver = {
 	.non_legacy_dai_naming	= 1,
 };
 
+static void hdmi_codec_jack_report(struct hdmi_codec_priv *hcp,
+				   unsigned int jack_status)
+{
+	if (!hcp->jack)
+		return;
+
+	if (jack_status != hcp->jack_status) {
+		snd_soc_jack_report(hcp->jack, jack_status, SND_JACK_LINEOUT);
+		hcp->jack_status = jack_status;
+	}
+}
+
+static int hdmi_codec_notify(struct notifier_block *nb, unsigned long event,
+			     void *data)
+{
+	struct hdmi_codec_priv *hcp = container_of(nb, struct hdmi_codec_priv,
+						   nb);
+	struct hdmi_notifier *n = data;
+
+	if (!hcp->jack)
+		return NOTIFY_OK;
+
+	switch (event) {
+	case HDMI_NEW_ELD:
+		mutex_lock(&hcp->eld_lock);
+		memcpy(hcp->eld, n->eld, sizeof(hcp->eld));
+		mutex_unlock(&hcp->eld_lock);
+		/* fall through */
+	case HDMI_CONNECTED:
+		hdmi_codec_jack_report(hcp, SND_JACK_LINEOUT);
+		break;
+	case HDMI_DISCONNECTED:
+		hdmi_codec_jack_report(hcp, 0);
+		break;
+	}
+
+	return NOTIFY_OK;
+}
+
+/**
+ * hdmi_codec_set_jack_detect - register HDMI state notifier callback
+ * @component: the hdmi-codec instance
+ * @jack: ASoC jack to report (dis)connection events on
+ * @dev: hdmi_notifier device, usually HDMI_TX or CEC device
+ */
+int hdmi_codec_set_jack_detect(struct snd_soc_component *component,
+			       struct snd_soc_jack *jack,
+			       struct device *dev)
+{
+	struct hdmi_codec_priv *hcp = snd_soc_component_get_drvdata(component);
+	int ret;
+
+	hcp->notifier = hdmi_notifier_get(dev);
+	if (!hcp->notifier)
+		return -ENOMEM;
+
+	hcp->jack = jack;
+	hcp->nb.notifier_call = hdmi_codec_notify;
+	ret = hdmi_notifier_register(hcp->notifier, &hcp->nb);
+	if (ret)
+		goto err_notifier_put;
+
+	return 0;
+
+err_notifier_put:
+	hdmi_notifier_put(hcp->notifier);
+	hcp->notifier = NULL;
+	return ret;
+}
+EXPORT_SYMBOL_GPL(hdmi_codec_set_jack_detect);
+
 static int hdmi_codec_probe(struct platform_device *pdev)
 {
 	struct hdmi_codec_pdata *hcd = pdev->dev.platform_data;
@@ -774,6 +858,7 @@ static int hdmi_codec_probe(struct platform_device *pdev)
 
 	hcp->hcd = *hcd;
 	mutex_init(&hcp->lock);
+	mutex_init(&hcp->eld_lock);
 
 	daidrv = devm_kcalloc(dev, dai_count, sizeof(*daidrv), GFP_KERNEL);
 	if (!daidrv)
@@ -797,6 +882,20 @@ static int hdmi_codec_probe(struct platform_device *pdev)
 			__func__, ret);
 		return ret;
 	}
+
+	hcp->dev = dev;
+
+	return 0;
+}
+
+static int hdmi_codec_remove(struct platform_device *pdev)
+{
+	struct hdmi_codec_priv *hcp = platform_get_drvdata(pdev);
+
+	if (hcp->notifier) {
+		hdmi_notifier_unregister(hcp->notifier, &hcp->nb);
+		hdmi_notifier_put(hcp->notifier);
+	}
 	return 0;
 }
 
@@ -805,6 +904,7 @@ static struct platform_driver hdmi_codec_driver = {
 		.name = HDMI_CODEC_DRV_NAME,
 	},
 	.probe = hdmi_codec_probe,
+	.remove = hdmi_codec_remove,
 };
 
 module_platform_driver(hdmi_codec_driver);
-- 
2.22.0.rc1.257.g3120a18244-goog


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH 3/7] drm/bridge/synopsys: dw-hdmi: Add HDMI notifier support
  2019-06-03  4:32 [PATCH 0/7] Add HDMI audio support on RK3288 veyron board Cheng-Yi Chiang
  2019-06-03  4:32 ` [PATCH 1/7] video: add HDMI state notifier support Cheng-Yi Chiang
  2019-06-03  4:32 ` [PATCH 2/7] ASoC: hdmi-codec: use HDMI state notifier to add jack support Cheng-Yi Chiang
@ 2019-06-03  4:32 ` Cheng-Yi Chiang
  2019-06-03  4:32 ` [PATCH 4/7] ASoC: rockchip_max98090: Add dai_link for HDMI Cheng-Yi Chiang
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 30+ messages in thread
From: Cheng-Yi Chiang @ 2019-06-03  4:32 UTC (permalink / raw)
  To: linux-kernel
  Cc: alsa-devel, Heiko Stuebner, David Airlie, dri-devel,
	Liam Girdwood, Hans Verkuil, Andrzej Hajda, Laurent Pinchart,
	Cheng-Yi Chiang, Takashi Iwai, linux-rockchip, dgreid,
	linux-media, devicetree, tzungbi, Philipp Zabel,
	Bartlomiej Zolnierkiewicz, Russell King, Rob Herring,
	Jaroslav Kysela, linux-arm-kernel, Greg Kroah-Hartman, dianders,
	Mark Brown, Daniel Vetter

Use hdmi-notifier to notify codec driver that there is HDMI plug/unplug
event.

Signed-off-by: Cheng-Yi Chiang <cychiang@chromium.org>
---
 drivers/gpu/drm/bridge/synopsys/Kconfig   |  1 +
 drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 28 +++++++++++++++++++++--
 2 files changed, 27 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/bridge/synopsys/Kconfig b/drivers/gpu/drm/bridge/synopsys/Kconfig
index 3cc53b44186e..43192d9d7357 100644
--- a/drivers/gpu/drm/bridge/synopsys/Kconfig
+++ b/drivers/gpu/drm/bridge/synopsys/Kconfig
@@ -3,6 +3,7 @@ config DRM_DW_HDMI
 	select DRM_KMS_HELPER
 	select REGMAP_MMIO
 	select CEC_CORE if CEC_NOTIFIER
+	select HDMI_NOTIFIERS
 
 config DRM_DW_HDMI_AHB_AUDIO
 	tristate "Synopsys Designware AHB Audio interface"
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
index ab7968c8f6a2..53701921eb1f 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
@@ -17,6 +17,7 @@
 #include <linux/err.h>
 #include <linux/clk.h>
 #include <linux/hdmi.h>
+#include <linux/hdmi-notifier.h>
 #include <linux/mutex.h>
 #include <linux/of_device.h>
 #include <linux/regmap.h>
@@ -190,6 +191,7 @@ struct dw_hdmi {
 	void (*disable_audio)(struct dw_hdmi *hdmi);
 
 	struct cec_notifier *cec_notifier;
+	struct hdmi_notifier *hdmi_notifier;
 };
 
 #define HDMI_IH_PHY_STAT0_RX_SENSE \
@@ -2301,8 +2303,15 @@ static irqreturn_t dw_hdmi_irq(int irq, void *dev_id)
 	}
 
 	if (intr_stat & HDMI_IH_PHY_STAT0_HPD) {
-		dev_dbg(hdmi->dev, "EVENT=%s\n",
-			phy_int_pol & HDMI_PHY_HPD ? "plugin" : "plugout");
+		if (phy_int_pol & HDMI_PHY_HPD) {
+			dev_dbg(hdmi->dev, "EVENT=plugin\n");
+			if (hdmi->hdmi_notifier)
+				hdmi_event_connect(hdmi->hdmi_notifier);
+		} else {
+			dev_dbg(hdmi->dev, "EVENT=plugout\n");
+			if (hdmi->hdmi_notifier)
+				hdmi_event_disconnect(hdmi->hdmi_notifier);
+		}
 		if (hdmi->bridge.dev)
 			drm_helper_hpd_irq_event(hdmi->bridge.dev);
 	}
@@ -2606,6 +2615,12 @@ __dw_hdmi_probe(struct platform_device *pdev,
 		goto err_iahb;
 	}
 
+	hdmi->hdmi_notifier = hdmi_notifier_get(dev);
+	if (!hdmi->hdmi_notifier) {
+		ret = -ENOMEM;
+		goto err_iahb;
+	}
+
 	/*
 	 * To prevent overflows in HDMI_IH_FC_STAT2, set the clk regenerator
 	 * N and cts values before enabling phy
@@ -2696,6 +2711,9 @@ __dw_hdmi_probe(struct platform_device *pdev,
 	if (hdmi->cec_notifier)
 		cec_notifier_put(hdmi->cec_notifier);
 
+	if (hdmi->hdmi_notifier)
+		hdmi_notifier_put(hdmi->hdmi_notifier);
+
 	clk_disable_unprepare(hdmi->iahb_clk);
 	if (hdmi->cec_clk)
 		clk_disable_unprepare(hdmi->cec_clk);
@@ -2709,6 +2727,9 @@ __dw_hdmi_probe(struct platform_device *pdev,
 
 static void __dw_hdmi_remove(struct dw_hdmi *hdmi)
 {
+	if (hdmi->hdmi_notifier)
+		hdmi_event_disconnect(hdmi->hdmi_notifier);
+
 	if (hdmi->audio && !IS_ERR(hdmi->audio))
 		platform_device_unregister(hdmi->audio);
 	if (!IS_ERR(hdmi->cec))
@@ -2720,6 +2741,9 @@ static void __dw_hdmi_remove(struct dw_hdmi *hdmi)
 	if (hdmi->cec_notifier)
 		cec_notifier_put(hdmi->cec_notifier);
 
+	if (hdmi->hdmi_notifier)
+		hdmi_notifier_put(hdmi->hdmi_notifier);
+
 	clk_disable_unprepare(hdmi->iahb_clk);
 	clk_disable_unprepare(hdmi->isfr_clk);
 	if (hdmi->cec_clk)
-- 
2.22.0.rc1.257.g3120a18244-goog


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH 4/7] ASoC: rockchip_max98090: Add dai_link for HDMI
  2019-06-03  4:32 [PATCH 0/7] Add HDMI audio support on RK3288 veyron board Cheng-Yi Chiang
                   ` (2 preceding siblings ...)
  2019-06-03  4:32 ` [PATCH 3/7] drm/bridge/synopsys: dw-hdmi: Add HDMI notifier support Cheng-Yi Chiang
@ 2019-06-03  4:32 ` Cheng-Yi Chiang
  2019-06-03  4:32 ` [PATCH 5/7] ASoC: rockchip: rockchip-max98090: Add node " Cheng-Yi Chiang
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 30+ messages in thread
From: Cheng-Yi Chiang @ 2019-06-03  4:32 UTC (permalink / raw)
  To: linux-kernel
  Cc: alsa-devel, Heiko Stuebner, David Airlie, dri-devel,
	Liam Girdwood, Hans Verkuil, Andrzej Hajda, Laurent Pinchart,
	Cheng-Yi Chiang, Takashi Iwai, linux-rockchip, dgreid,
	linux-media, devicetree, tzungbi, Philipp Zabel,
	Bartlomiej Zolnierkiewicz, Russell King, Rob Herring,
	Jaroslav Kysela, linux-arm-kernel, Greg Kroah-Hartman, dianders,
	Mark Brown, Daniel Vetter

Use two dai_links. One for HDMI and one for max98090.
With this setup, audio can play to speaker and HDMI selectively.

Signed-off-by: Cheng-Yi Chiang <cychiang@chromium.org>
---
 sound/soc/rockchip/rockchip_max98090.c | 82 +++++++++++++++++++-------
 1 file changed, 60 insertions(+), 22 deletions(-)

diff --git a/sound/soc/rockchip/rockchip_max98090.c b/sound/soc/rockchip/rockchip_max98090.c
index 789d6f1e2b5f..2dd247670c7a 100644
--- a/sound/soc/rockchip/rockchip_max98090.c
+++ b/sound/soc/rockchip/rockchip_max98090.c
@@ -53,6 +53,7 @@ static const struct snd_soc_dapm_widget rk_dapm_widgets[] = {
 	SND_SOC_DAPM_MIC("Headset Mic", NULL),
 	SND_SOC_DAPM_MIC("Int Mic", NULL),
 	SND_SOC_DAPM_SPK("Speaker", NULL),
+	SND_SOC_DAPM_LINE("HDMI", NULL),
 };
 
 static const struct snd_soc_dapm_route rk_audio_map[] = {
@@ -64,6 +65,7 @@ static const struct snd_soc_dapm_route rk_audio_map[] = {
 	{"Headphone", NULL, "HPR"},
 	{"Speaker", NULL, "SPKL"},
 	{"Speaker", NULL, "SPKR"},
+	{"HDMI", NULL, "TX"},
 };
 
 static const struct snd_kcontrol_new rk_mc_controls[] = {
@@ -71,6 +73,7 @@ static const struct snd_kcontrol_new rk_mc_controls[] = {
 	SOC_DAPM_PIN_SWITCH("Headset Mic"),
 	SOC_DAPM_PIN_SWITCH("Int Mic"),
 	SOC_DAPM_PIN_SWITCH("Speaker"),
+	SOC_DAPM_PIN_SWITCH("HDMI"),
 };
 
 static int rk_aif1_hw_params(struct snd_pcm_substream *substream,
@@ -104,33 +107,48 @@ static int rk_aif1_hw_params(struct snd_pcm_substream *substream,
 
 	ret = snd_soc_dai_set_sysclk(cpu_dai, 0, mclk,
 				     SND_SOC_CLOCK_OUT);
-	if (ret < 0) {
-		dev_err(codec_dai->dev, "Can't set codec clock %d\n", ret);
+	if (ret && ret != -ENOTSUPP) {
+		dev_err(cpu_dai->dev, "Can't set cpu dai clock %d\n", ret);
 		return ret;
 	}
 
 	ret = snd_soc_dai_set_sysclk(codec_dai, 0, mclk,
 				     SND_SOC_CLOCK_IN);
-	if (ret < 0) {
-		dev_err(codec_dai->dev, "Can't set codec clock %d\n", ret);
+	if (ret && ret != -ENOTSUPP) {
+		dev_err(codec_dai->dev, "Can't set codec dai clock %d\n", ret);
 		return ret;
 	}
 
-	return ret;
+	return 0;
 }
 
 static const struct snd_soc_ops rk_aif1_ops = {
 	.hw_params = rk_aif1_hw_params,
 };
 
-static struct snd_soc_dai_link rk_dailink = {
-	.name = "max98090",
-	.stream_name = "Audio",
-	.codec_dai_name = "HiFi",
-	.ops = &rk_aif1_ops,
-	/* set max98090 as slave */
-	.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
-		SND_SOC_DAIFMT_CBS_CFS,
+enum {
+	DAILINK_MAX98090,
+	DAILINK_HDMI,
+};
+
+/* max98090 and HDMI codec dai_link */
+static struct snd_soc_dai_link rk_dailinks[] = {
+	[DAILINK_MAX98090] = {
+		.name = "max98090",
+		.stream_name = "Analog",
+		.ops = &rk_aif1_ops,
+		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+			SND_SOC_DAIFMT_CBS_CFS,
+	},
+	[DAILINK_HDMI] = {
+		.name = "HDMI",
+		.stream_name = "HDMI",
+		.codec_name = "hdmi-audio-codec.3.auto",
+		.codec_dai_name = "i2s-hifi",
+		.ops = &rk_aif1_ops,
+		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+			SND_SOC_DAIFMT_CBS_CFS,
+	}
 };
 
 static int rk_98090_headset_init(struct snd_soc_component *component);
@@ -143,8 +161,8 @@ static struct snd_soc_aux_dev rk_98090_headset_dev = {
 static struct snd_soc_card snd_soc_card_rk = {
 	.name = "ROCKCHIP-I2S",
 	.owner = THIS_MODULE,
-	.dai_link = &rk_dailink,
-	.num_links = 1,
+	.dai_link = rk_dailinks,
+	.num_links = ARRAY_SIZE(rk_dailinks),
 	.aux_dev = &rk_98090_headset_dev,
 	.num_aux_devs = 1,
 	.dapm_widgets = rk_dapm_widgets,
@@ -180,27 +198,47 @@ static int snd_rk_mc_probe(struct platform_device *pdev)
 	int ret = 0;
 	struct snd_soc_card *card = &snd_soc_card_rk;
 	struct device_node *np = pdev->dev.of_node;
+	struct device_node *np_cpu;
+	struct of_phandle_args args;
 
 	/* register the soc card */
 	card->dev = &pdev->dev;
 
-	rk_dailink.codec_of_node = of_parse_phandle(np,
-			"rockchip,audio-codec", 0);
-	if (!rk_dailink.codec_of_node) {
+	rk_dailinks[DAILINK_MAX98090].codec_of_node =
+			of_parse_phandle(np, "rockchip,audio-codec", 0);
+	if (!rk_dailinks[DAILINK_MAX98090].codec_of_node) {
 		dev_err(&pdev->dev,
 			"Property 'rockchip,audio-codec' missing or invalid\n");
 		return -EINVAL;
 	}
 
-	rk_dailink.cpu_of_node = of_parse_phandle(np,
-			"rockchip,i2s-controller", 0);
-	if (!rk_dailink.cpu_of_node) {
+	ret = of_parse_phandle_with_fixed_args(np, "rockchip,audio-codec",
+					       0, 0, &args);
+	if (ret) {
+		dev_err(&pdev->dev,
+			"Unable to parse property 'rockchip,audio-codec'\n");
+		return ret;
+	}
+
+	ret = snd_soc_get_dai_name(
+			&args, &rk_dailinks[DAILINK_MAX98090].codec_dai_name);
+	if (ret) {
+		dev_err(&pdev->dev, "Unable to get codec_dai_name\n");
+		return ret;
+	}
+
+	np_cpu = of_parse_phandle(np, "rockchip,i2s-controller", 0);
+
+	if (!np_cpu) {
 		dev_err(&pdev->dev,
 			"Property 'rockchip,i2s-controller' missing or invalid\n");
 		return -EINVAL;
 	}
 
-	rk_dailink.platform_of_node = rk_dailink.cpu_of_node;
+	rk_dailinks[DAILINK_MAX98090].cpu_of_node = np_cpu;
+	rk_dailinks[DAILINK_MAX98090].platform_of_node = np_cpu;
+	rk_dailinks[DAILINK_HDMI].cpu_of_node = np_cpu;
+	rk_dailinks[DAILINK_HDMI].platform_of_node = np_cpu;
 
 	rk_98090_headset_dev.codec_of_node = of_parse_phandle(np,
 			"rockchip,headset-codec", 0);
-- 
2.22.0.rc1.257.g3120a18244-goog


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH 5/7] ASoC: rockchip: rockchip-max98090: Add node for HDMI
  2019-06-03  4:32 [PATCH 0/7] Add HDMI audio support on RK3288 veyron board Cheng-Yi Chiang
                   ` (3 preceding siblings ...)
  2019-06-03  4:32 ` [PATCH 4/7] ASoC: rockchip_max98090: Add dai_link for HDMI Cheng-Yi Chiang
@ 2019-06-03  4:32 ` " Cheng-Yi Chiang
  2019-07-09 20:01   ` Rob Herring
  2019-06-03  4:32 ` [PATCH 6/7] ASoC: rockchip_max98090: Add HDMI jack support Cheng-Yi Chiang
  2019-06-03  4:32 ` [PATCH 7/7] ARM: dts: rockchip: Specify HDMI node to sound card node Cheng-Yi Chiang
  6 siblings, 1 reply; 30+ messages in thread
From: Cheng-Yi Chiang @ 2019-06-03  4:32 UTC (permalink / raw)
  To: linux-kernel
  Cc: alsa-devel, Heiko Stuebner, David Airlie, dri-devel,
	Liam Girdwood, Hans Verkuil, Andrzej Hajda, Laurent Pinchart,
	Cheng-Yi Chiang, Takashi Iwai, linux-rockchip, dgreid,
	linux-media, devicetree, tzungbi, Philipp Zabel,
	Bartlomiej Zolnierkiewicz, Russell King, Rob Herring,
	Jaroslav Kysela, linux-arm-kernel, Greg Kroah-Hartman, dianders,
	Mark Brown, Daniel Vetter

Let user specify HDMI node so machine driver can use it to let codec
driver register callback on correct hdmi-notifier.

Signed-off-by: Cheng-Yi Chiang <cychiang@chromium.org>
---
 Documentation/devicetree/bindings/sound/rockchip-max98090.txt | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/Documentation/devicetree/bindings/sound/rockchip-max98090.txt b/Documentation/devicetree/bindings/sound/rockchip-max98090.txt
index a805aa99ad75..dae57c14864e 100644
--- a/Documentation/devicetree/bindings/sound/rockchip-max98090.txt
+++ b/Documentation/devicetree/bindings/sound/rockchip-max98090.txt
@@ -7,6 +7,7 @@ Required properties:
   connected to the CODEC
 - rockchip,audio-codec: The phandle of the MAX98090 audio codec
 - rockchip,headset-codec: The phandle of Ext chip for jack detection
+- rockchip,hdmi: The phandle of HDMI node for HDMI jack detection
 
 Example:
 
@@ -16,4 +17,5 @@ sound {
 	rockchip,i2s-controller = <&i2s>;
 	rockchip,audio-codec = <&max98090>;
 	rockchip,headset-codec = <&headsetcodec>;
+	rockchip,hdmi= <&hdmi>;
 };
-- 
2.22.0.rc1.257.g3120a18244-goog


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH 6/7] ASoC: rockchip_max98090: Add HDMI jack support
  2019-06-03  4:32 [PATCH 0/7] Add HDMI audio support on RK3288 veyron board Cheng-Yi Chiang
                   ` (4 preceding siblings ...)
  2019-06-03  4:32 ` [PATCH 5/7] ASoC: rockchip: rockchip-max98090: Add node " Cheng-Yi Chiang
@ 2019-06-03  4:32 ` Cheng-Yi Chiang
  2019-06-03  4:32 ` [PATCH 7/7] ARM: dts: rockchip: Specify HDMI node to sound card node Cheng-Yi Chiang
  6 siblings, 0 replies; 30+ messages in thread
From: Cheng-Yi Chiang @ 2019-06-03  4:32 UTC (permalink / raw)
  To: linux-kernel
  Cc: alsa-devel, Heiko Stuebner, David Airlie, dri-devel,
	Liam Girdwood, Hans Verkuil, Andrzej Hajda, Laurent Pinchart,
	Cheng-Yi Chiang, Takashi Iwai, linux-rockchip, dgreid,
	linux-media, devicetree, tzungbi, Philipp Zabel,
	Bartlomiej Zolnierkiewicz, Russell King, Rob Herring,
	Jaroslav Kysela, linux-arm-kernel, Greg Kroah-Hartman, dianders,
	Mark Brown, Daniel Vetter

In machine driver, create a jack and let hdmi-codec report jack status.

Signed-off-by: Cheng-Yi Chiang <cychiang@chromium.org>
---
 sound/soc/rockchip/rockchip_max98090.c | 41 ++++++++++++++++++++++++++
 1 file changed, 41 insertions(+)

diff --git a/sound/soc/rockchip/rockchip_max98090.c b/sound/soc/rockchip/rockchip_max98090.c
index 2dd247670c7a..17c50d9fbac1 100644
--- a/sound/soc/rockchip/rockchip_max98090.c
+++ b/sound/soc/rockchip/rockchip_max98090.c
@@ -18,6 +18,7 @@
  */
 
 #include <linux/module.h>
+#include <linux/of_platform.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <linux/gpio.h>
@@ -27,6 +28,7 @@
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
 #include <sound/soc.h>
+#include <sound/hdmi-codec.h>
 
 #include "rockchip_i2s.h"
 #include "../codecs/ts3a227e.h"
@@ -131,6 +133,26 @@ enum {
 	DAILINK_HDMI,
 };
 
+static struct snd_soc_jack rk_hdmi_jack;
+
+static int rk_hdmi_init(struct snd_soc_pcm_runtime *runtime)
+{
+	struct snd_soc_card *card = runtime->card;
+	struct snd_soc_component *component = runtime->codec_dai->component;
+	struct device *hdmi_dev = snd_soc_card_get_drvdata(card);
+	int ret;
+
+	/* enable jack detection */
+	ret = snd_soc_card_jack_new(card, "HDMI Jack", SND_JACK_LINEOUT,
+				    &rk_hdmi_jack, NULL, 0);
+	if (ret) {
+		dev_err(card->dev, "Can't new HDMI Jack %d\n", ret);
+		return ret;
+	}
+
+	return hdmi_codec_set_jack_detect(component, &rk_hdmi_jack, hdmi_dev);
+}
+
 /* max98090 and HDMI codec dai_link */
 static struct snd_soc_dai_link rk_dailinks[] = {
 	[DAILINK_MAX98090] = {
@@ -148,6 +170,7 @@ static struct snd_soc_dai_link rk_dailinks[] = {
 		.ops = &rk_aif1_ops,
 		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
 			SND_SOC_DAIFMT_CBS_CFS,
+		.init = rk_hdmi_init,
 	}
 };
 
@@ -200,6 +223,8 @@ static int snd_rk_mc_probe(struct platform_device *pdev)
 	struct device_node *np = pdev->dev.of_node;
 	struct device_node *np_cpu;
 	struct of_phandle_args args;
+	struct device_node *np_hdmi;
+	struct platform_device *hdmi_pdev;
 
 	/* register the soc card */
 	card->dev = &pdev->dev;
@@ -248,6 +273,22 @@ static int snd_rk_mc_probe(struct platform_device *pdev)
 		return -EINVAL;
 	}
 
+	/* The hdmi device handles HDMI hotplug detection */
+	np_hdmi = of_parse_phandle(np, "rockchip,hdmi", 0);
+	if (!np_hdmi) {
+		dev_err(&pdev->dev, "Failed to find HDMI node\n");
+		return -EINVAL;
+	}
+
+	hdmi_pdev = of_find_device_by_node(np_hdmi);
+	if (!hdmi_pdev) {
+		dev_err(&pdev->dev, "Waiting for HDMI device %s\n",
+			np_hdmi->full_name);
+		return -EPROBE_DEFER;
+	}
+
+	snd_soc_card_set_drvdata(card, &hdmi_pdev->dev);
+
 	ret = snd_soc_of_parse_card_name(card, "rockchip,model");
 	if (ret) {
 		dev_err(&pdev->dev,
-- 
2.22.0.rc1.257.g3120a18244-goog


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH 7/7] ARM: dts: rockchip: Specify HDMI node to sound card node
  2019-06-03  4:32 [PATCH 0/7] Add HDMI audio support on RK3288 veyron board Cheng-Yi Chiang
                   ` (5 preceding siblings ...)
  2019-06-03  4:32 ` [PATCH 6/7] ASoC: rockchip_max98090: Add HDMI jack support Cheng-Yi Chiang
@ 2019-06-03  4:32 ` Cheng-Yi Chiang
  6 siblings, 0 replies; 30+ messages in thread
From: Cheng-Yi Chiang @ 2019-06-03  4:32 UTC (permalink / raw)
  To: linux-kernel
  Cc: alsa-devel, Heiko Stuebner, David Airlie, dri-devel,
	Liam Girdwood, Hans Verkuil, Andrzej Hajda, Laurent Pinchart,
	Cheng-Yi Chiang, Takashi Iwai, linux-rockchip, dgreid,
	linux-media, devicetree, tzungbi, Philipp Zabel,
	Bartlomiej Zolnierkiewicz, Russell King, Rob Herring,
	Jaroslav Kysela, linux-arm-kernel, Greg Kroah-Hartman, dianders,
	Mark Brown, Daniel Vetter

Sound card needs HDMI node in order to register jack callback on HDMI
notifier.

Signed-off-by: Cheng-Yi Chiang <cychiang@chromium.org>
---
 arch/arm/boot/dts/rk3288-veyron-analog-audio.dtsi | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/boot/dts/rk3288-veyron-analog-audio.dtsi b/arch/arm/boot/dts/rk3288-veyron-analog-audio.dtsi
index 445270aa136e..096ba4e96db2 100644
--- a/arch/arm/boot/dts/rk3288-veyron-analog-audio.dtsi
+++ b/arch/arm/boot/dts/rk3288-veyron-analog-audio.dtsi
@@ -14,6 +14,7 @@
 		rockchip,model = "VEYRON-I2S";
 		rockchip,i2s-controller = <&i2s>;
 		rockchip,audio-codec = <&max98090>;
+		rockchip,hdmi= <&hdmi>;
 		rockchip,hp-det-gpios = <&gpio6 RK_PA5 GPIO_ACTIVE_HIGH>;
 		rockchip,mic-det-gpios = <&gpio6 RK_PB3 GPIO_ACTIVE_LOW>;
 		rockchip,headset-codec = <&headsetcodec>;
-- 
2.22.0.rc1.257.g3120a18244-goog


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 1/7] video: add HDMI state notifier support
  2019-06-03  4:32 ` [PATCH 1/7] video: add HDMI state notifier support Cheng-Yi Chiang
@ 2019-06-03  7:45   ` Hans Verkuil
  2019-06-03  8:09     ` Daniel Vetter
  2019-06-04  1:48     ` Cheng-yi Chiang
  0 siblings, 2 replies; 30+ messages in thread
From: Hans Verkuil @ 2019-06-03  7:45 UTC (permalink / raw)
  To: Cheng-Yi Chiang, linux-kernel
  Cc: alsa-devel, Heiko Stuebner, Liam Girdwood, David Airlie,
	dri-devel, Takashi Iwai, Andrzej Hajda, Laurent Pinchart,
	linux-rockchip, dgreid, linux-media, devicetree, tzungbi,
	Philipp Zabel, Bartlomiej Zolnierkiewicz, Russell King,
	Rob Herring, Jaroslav Kysela, linux-arm-kernel,
	Greg Kroah-Hartman, dianders, Mark Brown, Daniel Vetter,
	Dariusz Marcinkiewicz

On 6/3/19 6:32 AM, Cheng-Yi Chiang wrote:
> From: Hans Verkuil <hans.verkuil@cisco.com>
> 
> Add support for HDMI hotplug and EDID notifiers, which is used to convey
> information from HDMI drivers to their CEC and audio counterparts.
> 
> Based on an earlier version from Russell King:
> 
> https://patchwork.kernel.org/patch/9277043/
> 
> The hdmi_notifier is a reference counted object containing the HDMI state
> of an HDMI device.
> 
> When a new notifier is registered the current state will be reported to
> that notifier at registration time.
> 
> Based on Hans Verkuil's patch:
> 
> https://patchwork.kernel.org/patch/9472521/

Erm, you are aware that this patch morphed into a CEC-specific notifier
found in drivers/media/cec/cec-notifier.c?

I don't think it makes sense to have two notifier implementations in the kernel.
The original intention was to have the notifier deal with both CEC and ASoC
notifications, but there was not enough interest for the ASoC bits at the time
and it was dropped.

I am planning changes to the cec-notifier API, I hope to work on that this
week. I'll CC you when I post those. Those might be a good starting point
to convert the cec-notifier to an hdmi-notifier as was originally intended.

I've added your colleague Dariusz Marcinkiewicz to the CC list since he's been
working on some nice cec-notifier improvements as well.

Regards,

	Hans

> 
> Modified by Cheng-Yi Chiang:
>  - Add a section in MAINTAINER.
>  - Changes connected and has_eld to bitfield of unsigned int.
>  - Other minor fixes to pass checkpatch.pl --strict checks.
> 
> Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
> Acked-by: Philipp Zabel <p.zabel@pengutronix.de>
> Signed-off-by: Cheng-Yi Chiang <cychiang@chromium.org>
> ---
> The original patch is at
> https://lore.kernel.org/linux-arm-kernel/20161213150813.37966-2-hverkuil@xs4all.nl
> 
>  MAINTAINERS                   |   6 ++
>  drivers/video/Kconfig         |   3 +
>  drivers/video/Makefile        |   1 +
>  drivers/video/hdmi-notifier.c | 145 ++++++++++++++++++++++++++++++++++
>  include/linux/hdmi-notifier.h | 112 ++++++++++++++++++++++++++
>  5 files changed, 267 insertions(+)
>  create mode 100644 drivers/video/hdmi-notifier.c
>  create mode 100644 include/linux/hdmi-notifier.h
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 5cfbea4ce575..ffb7376f9509 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -16676,6 +16676,12 @@ W:	https://linuxtv.org
>  S:	Maintained
>  F:	drivers/media/platform/vicodec/*
>  
> +VIDEO FRAMEWORK
> +M:	Hans Verkuil <hverkuil@xs4all.nl>
> +L:	linux-media@vger.kernel.org
> +F:	drivers/video/hdmi-notifier.*
> +S:	Maintained
> +
>  VIDEO MULTIPLEXER DRIVER
>  M:	Philipp Zabel <p.zabel@pengutronix.de>
>  L:	linux-media@vger.kernel.org
> diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
> index 83d3d271ca15..000ba9bc0ae7 100644
> --- a/drivers/video/Kconfig
> +++ b/drivers/video/Kconfig
> @@ -34,6 +34,9 @@ config VIDEOMODE_HELPERS
>  config HDMI
>  	bool
>  
> +config HDMI_NOTIFIERS
> +	bool
> +
>  endif # HAS_IOMEM
>  
>  if VT
> diff --git a/drivers/video/Makefile b/drivers/video/Makefile
> index df7650adede9..eff4736102ca 100644
> --- a/drivers/video/Makefile
> +++ b/drivers/video/Makefile
> @@ -1,6 +1,7 @@
>  # SPDX-License-Identifier: GPL-2.0
>  obj-$(CONFIG_VGASTATE)            += vgastate.o
>  obj-$(CONFIG_HDMI)                += hdmi.o
> +obj-$(CONFIG_HDMI_NOTIFIERS)      += hdmi-notifier.o
>  
>  obj-$(CONFIG_VT)		  += console/
>  obj-$(CONFIG_FB_STI)		  += console/
> diff --git a/drivers/video/hdmi-notifier.c b/drivers/video/hdmi-notifier.c
> new file mode 100644
> index 000000000000..d1eedf661648
> --- /dev/null
> +++ b/drivers/video/hdmi-notifier.c
> @@ -0,0 +1,145 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/* hdmi-notifier.c - notify interested parties of (dis)connect and EDID
> + * events
> + *
> + * Copyright 2016 Russell King <rmk+kernel@arm.linux.org.uk>
> + * Copyright 2016 Cisco Systems, Inc. and/or its affiliates.
> + * All rights reserved.
> + */
> +
> +#include <linux/export.h>
> +#include <linux/hdmi-notifier.h>
> +#include <linux/string.h>
> +#include <linux/slab.h>
> +#include <linux/list.h>
> +
> +static LIST_HEAD(hdmi_notifiers);
> +static DEFINE_MUTEX(hdmi_notifiers_lock);
> +
> +struct hdmi_notifier *hdmi_notifier_get(struct device *dev)
> +{
> +	struct hdmi_notifier *n;
> +
> +	mutex_lock(&hdmi_notifiers_lock);
> +	list_for_each_entry(n, &hdmi_notifiers, head) {
> +		if (n->dev == dev) {
> +			mutex_unlock(&hdmi_notifiers_lock);
> +			kref_get(&n->kref);
> +			return n;
> +		}
> +	}
> +	n = kzalloc(sizeof(*n), GFP_KERNEL);
> +	if (!n)
> +		goto unlock;
> +	n->dev = dev;
> +	mutex_init(&n->lock);
> +	BLOCKING_INIT_NOTIFIER_HEAD(&n->notifiers);
> +	kref_init(&n->kref);
> +	list_add_tail(&n->head, &hdmi_notifiers);
> +unlock:
> +	mutex_unlock(&hdmi_notifiers_lock);
> +	return n;
> +}
> +EXPORT_SYMBOL_GPL(hdmi_notifier_get);
> +
> +static void hdmi_notifier_release(struct kref *kref)
> +{
> +	struct hdmi_notifier *n =
> +		container_of(kref, struct hdmi_notifier, kref);
> +
> +	mutex_lock(&hdmi_notifiers_lock);
> +	list_del(&n->head);
> +	mutex_unlock(&hdmi_notifiers_lock);
> +	kfree(n->edid);
> +	kfree(n);
> +}
> +
> +void hdmi_notifier_put(struct hdmi_notifier *n)
> +{
> +	kref_put(&n->kref, hdmi_notifier_release);
> +}
> +EXPORT_SYMBOL_GPL(hdmi_notifier_put);
> +
> +int hdmi_notifier_register(struct hdmi_notifier *n, struct notifier_block *nb)
> +{
> +	int ret = blocking_notifier_chain_register(&n->notifiers, nb);
> +
> +	if (ret)
> +		return ret;
> +	kref_get(&n->kref);
> +	mutex_lock(&n->lock);
> +	if (n->connected) {
> +		blocking_notifier_call_chain(&n->notifiers, HDMI_CONNECTED, n);
> +		if (n->edid_size)
> +			blocking_notifier_call_chain(&n->notifiers,
> +						     HDMI_NEW_EDID, n);
> +		if (n->has_eld)
> +			blocking_notifier_call_chain(&n->notifiers,
> +						     HDMI_NEW_ELD, n);
> +	}
> +	mutex_unlock(&n->lock);
> +	return 0;
> +}
> +EXPORT_SYMBOL_GPL(hdmi_notifier_register);
> +
> +int hdmi_notifier_unregister(struct hdmi_notifier *n, struct notifier_block *nb)
> +{
> +	int ret = blocking_notifier_chain_unregister(&n->notifiers, nb);
> +
> +	if (ret == 0)
> +		hdmi_notifier_put(n);
> +	return ret;
> +}
> +EXPORT_SYMBOL_GPL(hdmi_notifier_unregister);
> +
> +void hdmi_event_connect(struct hdmi_notifier *n)
> +{
> +	mutex_lock(&n->lock);
> +	n->connected = true;
> +	blocking_notifier_call_chain(&n->notifiers, HDMI_CONNECTED, n);
> +	mutex_unlock(&n->lock);
> +}
> +EXPORT_SYMBOL_GPL(hdmi_event_connect);
> +
> +void hdmi_event_disconnect(struct hdmi_notifier *n)
> +{
> +	mutex_lock(&n->lock);
> +	n->connected = false;
> +	n->has_eld = false;
> +	n->edid_size = 0;
> +	blocking_notifier_call_chain(&n->notifiers, HDMI_DISCONNECTED, n);
> +	mutex_unlock(&n->lock);
> +}
> +EXPORT_SYMBOL_GPL(hdmi_event_disconnect);
> +
> +int hdmi_event_new_edid(struct hdmi_notifier *n, const void *edid, size_t size)
> +{
> +	mutex_lock(&n->lock);
> +	if (n->edid_allocated_size < size) {
> +		void *p = kmalloc(size, GFP_KERNEL);
> +
> +		if (!p) {
> +			mutex_unlock(&n->lock);
> +			return -ENOMEM;
> +		}
> +		kfree(n->edid);
> +		n->edid = p;
> +		n->edid_allocated_size = size;
> +	}
> +	memcpy(n->edid, edid, size);
> +	n->edid_size = size;
> +	blocking_notifier_call_chain(&n->notifiers, HDMI_NEW_EDID, n);
> +	mutex_unlock(&n->lock);
> +	return 0;
> +}
> +EXPORT_SYMBOL_GPL(hdmi_event_new_edid);
> +
> +void hdmi_event_new_eld(struct hdmi_notifier *n, const u8 eld[128])
> +{
> +	mutex_lock(&n->lock);
> +	memcpy(n->eld, eld, sizeof(n->eld));
> +	n->has_eld = true;
> +	blocking_notifier_call_chain(&n->notifiers, HDMI_NEW_ELD, n);
> +	mutex_unlock(&n->lock);
> +}
> +EXPORT_SYMBOL_GPL(hdmi_event_new_eld);
> diff --git a/include/linux/hdmi-notifier.h b/include/linux/hdmi-notifier.h
> new file mode 100644
> index 000000000000..c8f35110e3e3
> --- /dev/null
> +++ b/include/linux/hdmi-notifier.h
> @@ -0,0 +1,112 @@
> +/* SPDX-License-Identifier: GPL-2.0
> + * hdmi-notifier.h - notify interested parties of (dis)connect and EDID
> + * events
> + *
> + * Copyright 2016 Russell King <rmk+kernel@arm.linux.org.uk>
> + * Copyright 2016 Cisco Systems, Inc. and/or its affiliates.
> + * All rights reserved.
> + */
> +
> +#ifndef LINUX_HDMI_NOTIFIER_H
> +#define LINUX_HDMI_NOTIFIER_H
> +
> +#include <linux/types.h>
> +#include <linux/notifier.h>
> +#include <linux/kref.h>
> +
> +enum {
> +	HDMI_CONNECTED,
> +	HDMI_DISCONNECTED,
> +	HDMI_NEW_EDID,
> +	HDMI_NEW_ELD,
> +};
> +
> +struct device;
> +
> +struct hdmi_notifier {
> +	/* Lock to protect callback registration and notification. */
> +	struct mutex lock;
> +	struct list_head head;
> +	struct kref kref;
> +	struct blocking_notifier_head notifiers;
> +	struct device *dev;
> +
> +	/* Current state */
> +	unsigned int connected : 1;
> +	unsigned int has_eld : 1;
> +	unsigned char eld[128];
> +	void *edid;
> +	size_t edid_size;
> +	size_t edid_allocated_size;
> +};
> +
> +/**
> + * hdmi_notifier_get - find or create a new hdmi_notifier for the given device.
> + * @dev: device that sends the events.
> + *
> + * If a notifier for device @dev already exists, then increase the refcount
> + * and return that notifier.
> + *
> + * If it doesn't exist, then allocate a new notifier struct and return a
> + * pointer to that new struct.
> + *
> + * Return NULL if the memory could not be allocated.
> + */
> +struct hdmi_notifier *hdmi_notifier_get(struct device *dev);
> +
> +/**
> + * hdmi_notifier_put - decrease refcount and delete when the refcount reaches 0.
> + * @n: notifier
> + */
> +void hdmi_notifier_put(struct hdmi_notifier *n);
> +
> +/**
> + * hdmi_notifier_register - register the notifier with the notifier_block.
> + * @n: the HDMI notifier
> + * @nb: the notifier_block
> + */
> +int hdmi_notifier_register(struct hdmi_notifier *n, struct notifier_block *nb);
> +
> +/**
> + * hdmi_notifier_unregister - unregister the notifier with the notifier_block.
> + * @n: the HDMI notifier
> + * @nb: the notifier_block
> + */
> +int hdmi_notifier_unregister(struct hdmi_notifier *n,
> +			     struct notifier_block *nb);
> +
> +/**
> + * hdmi_event_connect - send a connect event.
> + * @n: the HDMI notifier
> + *
> + * Send an HDMI_CONNECTED event to any registered parties.
> + */
> +void hdmi_event_connect(struct hdmi_notifier *n);
> +
> +/**
> + * hdmi_event_disconnect - send a disconnect event.
> + * @n: the HDMI notifier
> + *
> + * Send an HDMI_DISCONNECTED event to any registered parties.
> + */
> +void hdmi_event_disconnect(struct hdmi_notifier *n);
> +
> +/**
> + * hdmi_event_new_edid - send a new EDID event.
> + * @n: the HDMI notifier
> + *
> + * Send an HDMI_NEW_EDID event to any registered parties.
> + * This function will make a copy the EDID so it can return -ENOMEM if
> + * no memory could be allocated.
> + */
> +int hdmi_event_new_edid(struct hdmi_notifier *n, const void *edid, size_t size);
> +
> +/**
> + * hdmi_event_new_eld - send a new ELD event.
> + * @n: the HDMI notifier
> + *
> + * Send an HDMI_NEW_ELD event to any registered parties.
> + */
> +void hdmi_event_new_eld(struct hdmi_notifier *n, const u8 eld[128]);
> +
> +#endif
> 


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [alsa-devel] [PATCH 2/7] ASoC: hdmi-codec: use HDMI state notifier to add jack support
  2019-06-03  4:32 ` [PATCH 2/7] ASoC: hdmi-codec: use HDMI state notifier to add jack support Cheng-Yi Chiang
@ 2019-06-03  8:03   ` " Amadeusz Sławiński
  2019-06-03  8:53     ` Cheng-yi Chiang
  0 siblings, 1 reply; 30+ messages in thread
From: Amadeusz Sławiński @ 2019-06-03  8:03 UTC (permalink / raw)
  To: Cheng-Yi Chiang
  Cc: alsa-devel, Heiko Stuebner, Liam Girdwood, David Airlie,
	dri-devel, Takashi Iwai, Hans Verkuil, Andrzej Hajda,
	Laurent Pinchart, linux-rockchip, dgreid, linux-media,
	devicetree, tzungbi, Daniel Vetter, Bartlomiej Zolnierkiewicz,
	Russell King, Rob Herring, linux-arm-kernel, Greg Kroah-Hartman,
	dianders, linux-kernel, Mark Brown, Philipp Zabel

On Mon,  3 Jun 2019 12:32:46 +0800
Cheng-Yi Chiang <cychiang@chromium.org> wrote:

> From: Philipp Zabel <p.zabel@pengutronix.de>
> 
> Use HDMI connection / disconnection notifications to update an ALSA
> jack object. Also make a copy of the ELD block after every change.
> 
> This was posted by Philipp Zabel at
> 
> https://patchwork.kernel.org/patch/9430747/
> 
> Modified by Cheng-Yi Chiang:
> - Fix the conflict of removed hdmi_codec_remove ops.
> - Other minor fix for the conflict with latest hdmi-codec on ASoC
>   for-next tree.
> 
> Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
> Signed-off-by: Cheng-Yi Chiang <cychiang@chromium.org>
> ---
> The original patch is at https://patchwork.kernel.org/patch/9430747/
> I could not find the LKML link for the patch.
> 
>  include/sound/hdmi-codec.h    |   7 +++
>  sound/soc/codecs/Kconfig      |   1 +
>  sound/soc/codecs/hdmi-codec.c | 104
> +++++++++++++++++++++++++++++++++- 3 files changed, 110
> insertions(+), 2 deletions(-)
> 
> diff --git a/include/sound/hdmi-codec.h b/include/sound/hdmi-codec.h
> index 9483c55f871b..4fa39c93363f 100644
> --- a/include/sound/hdmi-codec.h
> +++ b/include/sound/hdmi-codec.h
> @@ -107,6 +107,13 @@ struct hdmi_codec_pdata {
>  	void *data;
>  };
>  
> +struct snd_soc_component;
> +struct snd_soc_jack;
> +
> +int hdmi_codec_set_jack_detect(struct snd_soc_component *component,
> +			       struct snd_soc_jack *jack,
> +			       struct device *dev);
> +
>  #define HDMI_CODEC_DRV_NAME "hdmi-audio-codec"
>  
>  #endif /* __HDMI_CODEC_H__ */
> diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
> index 8f577258080b..f5f6dd04234c 100644
> --- a/sound/soc/codecs/Kconfig
> +++ b/sound/soc/codecs/Kconfig
> @@ -639,6 +639,7 @@ config SND_SOC_HDMI_CODEC
>  	select SND_PCM_ELD
>  	select SND_PCM_IEC958
>  	select HDMI
> +	select HDMI_NOTIFIERS
>  
>  config SND_SOC_ES7134
>         tristate "Everest Semi ES7134 CODEC"
> diff --git a/sound/soc/codecs/hdmi-codec.c
> b/sound/soc/codecs/hdmi-codec.c index 6a0cc8d7e141..fe796a7475a5
> 100644 --- a/sound/soc/codecs/hdmi-codec.c
> +++ b/sound/soc/codecs/hdmi-codec.c
> @@ -12,9 +12,12 @@
>   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See
> the GNU
>   * General Public License for more details.
>   */
> +#include <linux/hdmi-notifier.h>
>  #include <linux/module.h>
> +#include <linux/notifier.h>
>  #include <linux/string.h>
>  #include <sound/core.h>
> +#include <sound/jack.h>
>  #include <sound/pcm.h>
>  #include <sound/pcm_params.h>
>  #include <sound/soc.h>
> @@ -282,6 +285,13 @@ struct hdmi_codec_priv {
>  	struct snd_pcm_chmap *chmap_info;
>  	unsigned int chmap_idx;
>  	struct mutex lock;
> +	struct snd_soc_jack *jack;
> +	/* Lock to protect setting and getting eld. */
> +	struct mutex eld_lock;
> +	struct device *dev;
> +	struct hdmi_notifier *notifier;
> +	struct notifier_block nb;
> +	unsigned int jack_status;
>  };
>  
>  static const struct snd_soc_dapm_widget hdmi_widgets[] = {
> @@ -308,7 +318,9 @@ static int hdmi_eld_ctl_get(struct snd_kcontrol
> *kcontrol, struct snd_soc_component *component =
> snd_kcontrol_chip(kcontrol); struct hdmi_codec_priv *hcp =
> snd_soc_component_get_drvdata(component); 
> +	mutex_lock(&hcp->eld_lock);
>  	memcpy(ucontrol->value.bytes.data, hcp->eld,
> sizeof(hcp->eld));
> +	mutex_unlock(&hcp->eld_lock);
>  
>  	return 0;
>  }
> @@ -393,7 +405,7 @@ static int hdmi_codec_startup(struct
> snd_pcm_substream *substream, struct snd_soc_dai *dai)
>  {
>  	struct hdmi_codec_priv *hcp = snd_soc_dai_get_drvdata(dai);
> -	int ret = 0;
> +	int ret;
>  
>  	ret = mutex_trylock(&hcp->lock);
>  	if (!ret) {
> @@ -408,9 +420,9 @@ static int hdmi_codec_startup(struct
> snd_pcm_substream *substream, }
>  
>  	if (hcp->hcd.ops->get_eld) {
> +		mutex_lock(&hcp->eld_lock);
>  		ret = hcp->hcd.ops->get_eld(dai->dev->parent,
> hcp->hcd.data, hcp->eld, sizeof(hcp->eld));
> -
>  		if (!ret) {
>  			ret =
> snd_pcm_hw_constraint_eld(substream->runtime, hcp->eld);

Seems to me like you missed unlock here. There is return inside this
if().

> @@ -419,6 +431,7 @@ static int hdmi_codec_startup(struct
> snd_pcm_substream *substream, }
>  		/* Select chmap supported */
>  		hdmi_codec_eld_chmap(hcp);
> +		mutex_unlock(&hcp->eld_lock);
>  	}
>  	return 0;
>  
> @@ -747,6 +760,77 @@ static const struct snd_soc_component_driver
> hdmi_driver = { .non_legacy_dai_naming	= 1,
>  };
>  
> +static void hdmi_codec_jack_report(struct hdmi_codec_priv *hcp,
> +				   unsigned int jack_status)
> +{
> +	if (!hcp->jack)
> +		return;
> +
> +	if (jack_status != hcp->jack_status) {
> +		snd_soc_jack_report(hcp->jack, jack_status,
> SND_JACK_LINEOUT);
> +		hcp->jack_status = jack_status;
> +	}
> +}
> +
> +static int hdmi_codec_notify(struct notifier_block *nb, unsigned
> long event,
> +			     void *data)
> +{
> +	struct hdmi_codec_priv *hcp = container_of(nb, struct
> hdmi_codec_priv,
> +						   nb);
> +	struct hdmi_notifier *n = data;
> +
> +	if (!hcp->jack)
> +		return NOTIFY_OK;
> +
> +	switch (event) {
> +	case HDMI_NEW_ELD:
> +		mutex_lock(&hcp->eld_lock);
> +		memcpy(hcp->eld, n->eld, sizeof(hcp->eld));
> +		mutex_unlock(&hcp->eld_lock);
> +		/* fall through */
> +	case HDMI_CONNECTED:
> +		hdmi_codec_jack_report(hcp, SND_JACK_LINEOUT);
> +		break;
> +	case HDMI_DISCONNECTED:
> +		hdmi_codec_jack_report(hcp, 0);
> +		break;
> +	}
> +
> +	return NOTIFY_OK;
> +}
> +
> +/**
> + * hdmi_codec_set_jack_detect - register HDMI state notifier callback
> + * @component: the hdmi-codec instance
> + * @jack: ASoC jack to report (dis)connection events on
> + * @dev: hdmi_notifier device, usually HDMI_TX or CEC device
> + */
> +int hdmi_codec_set_jack_detect(struct snd_soc_component *component,
> +			       struct snd_soc_jack *jack,
> +			       struct device *dev)
> +{
> +	struct hdmi_codec_priv *hcp =
> snd_soc_component_get_drvdata(component);
> +	int ret;
> +
> +	hcp->notifier = hdmi_notifier_get(dev);
> +	if (!hcp->notifier)
> +		return -ENOMEM;
> +
> +	hcp->jack = jack;
> +	hcp->nb.notifier_call = hdmi_codec_notify;
> +	ret = hdmi_notifier_register(hcp->notifier, &hcp->nb);
> +	if (ret)
> +		goto err_notifier_put;
> +
> +	return 0;
> +
> +err_notifier_put:
> +	hdmi_notifier_put(hcp->notifier);
> +	hcp->notifier = NULL;
> +	return ret;
> +}
> +EXPORT_SYMBOL_GPL(hdmi_codec_set_jack_detect);
> +
>  static int hdmi_codec_probe(struct platform_device *pdev)
>  {
>  	struct hdmi_codec_pdata *hcd = pdev->dev.platform_data;
> @@ -774,6 +858,7 @@ static int hdmi_codec_probe(struct
> platform_device *pdev) 
>  	hcp->hcd = *hcd;
>  	mutex_init(&hcp->lock);
> +	mutex_init(&hcp->eld_lock);
>  
>  	daidrv = devm_kcalloc(dev, dai_count, sizeof(*daidrv),
> GFP_KERNEL); if (!daidrv)
> @@ -797,6 +882,20 @@ static int hdmi_codec_probe(struct
> platform_device *pdev) __func__, ret);
>  		return ret;
>  	}
> +
> +	hcp->dev = dev;
> +
> +	return 0;
> +}
> +
> +static int hdmi_codec_remove(struct platform_device *pdev)
> +{
> +	struct hdmi_codec_priv *hcp = platform_get_drvdata(pdev);
> +
> +	if (hcp->notifier) {
> +		hdmi_notifier_unregister(hcp->notifier, &hcp->nb);
> +		hdmi_notifier_put(hcp->notifier);
> +	}
>  	return 0;
>  }
>  
> @@ -805,6 +904,7 @@ static struct platform_driver hdmi_codec_driver =
> { .name = HDMI_CODEC_DRV_NAME,
>  	},
>  	.probe = hdmi_codec_probe,
> +	.remove = hdmi_codec_remove,
>  };
>  
>  module_platform_driver(hdmi_codec_driver);


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 1/7] video: add HDMI state notifier support
  2019-06-03  7:45   ` Hans Verkuil
@ 2019-06-03  8:09     ` Daniel Vetter
  2019-06-03  9:05       ` Hans Verkuil
  2019-06-04  2:32       ` Cheng-yi Chiang
  2019-06-04  1:48     ` Cheng-yi Chiang
  1 sibling, 2 replies; 30+ messages in thread
From: Daniel Vetter @ 2019-06-03  8:09 UTC (permalink / raw)
  To: Hans Verkuil
  Cc: alsa-devel, Heiko Stuebner, Liam Girdwood, David Airlie,
	dri-devel, Takashi Iwai, Andrzej Hajda, Laurent Pinchart,
	Cheng-Yi Chiang, linux-rockchip, dgreid, linux-media, devicetree,
	tzungbi, Philipp Zabel, Bartlomiej Zolnierkiewicz, Russell King,
	Rob Herring, Jaroslav Kysela, linux-arm-kernel,
	Greg Kroah-Hartman, dianders, linux-kernel, Mark Brown,
	Daniel Vetter, Dariusz Marcinkiewicz

On Mon, Jun 03, 2019 at 09:45:49AM +0200, Hans Verkuil wrote:
> On 6/3/19 6:32 AM, Cheng-Yi Chiang wrote:
> > From: Hans Verkuil <hans.verkuil@cisco.com>
> > 
> > Add support for HDMI hotplug and EDID notifiers, which is used to convey
> > information from HDMI drivers to their CEC and audio counterparts.
> > 
> > Based on an earlier version from Russell King:
> > 
> > https://patchwork.kernel.org/patch/9277043/
> > 
> > The hdmi_notifier is a reference counted object containing the HDMI state
> > of an HDMI device.
> > 
> > When a new notifier is registered the current state will be reported to
> > that notifier at registration time.
> > 
> > Based on Hans Verkuil's patch:
> > 
> > https://patchwork.kernel.org/patch/9472521/
> 
> Erm, you are aware that this patch morphed into a CEC-specific notifier
> found in drivers/media/cec/cec-notifier.c?
> 
> I don't think it makes sense to have two notifier implementations in the kernel.
> The original intention was to have the notifier deal with both CEC and ASoC
> notifications, but there was not enough interest for the ASoC bits at the time
> and it was dropped.
> 
> I am planning changes to the cec-notifier API, I hope to work on that this
> week. I'll CC you when I post those. Those might be a good starting point
> to convert the cec-notifier to an hdmi-notifier as was originally intended.
> 
> I've added your colleague Dariusz Marcinkiewicz to the CC list since he's been
> working on some nice cec-notifier improvements as well.

We also have some interfaces for drm/alsa interactions around hdmi
already in drm/drm_audio_component.h, but it's not used by anything
outside of i915. Imo we should extend that, not reinvent a new wheel.

Another note: notifiers considered evil, imo. Gets the job done for one
case, as soon as you have multiple devices and need to make sure you get
the update for the right one it all comes crashing down. Please create an
api which registers for updates from a specific device only, plus
something that has real callbacks (like the drm_audio_component.h thing we
started already).
-Daniel

> 
> Regards,
> 
> 	Hans
> 
> > 
> > Modified by Cheng-Yi Chiang:
> >  - Add a section in MAINTAINER.
> >  - Changes connected and has_eld to bitfield of unsigned int.
> >  - Other minor fixes to pass checkpatch.pl --strict checks.
> > 
> > Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
> > Acked-by: Philipp Zabel <p.zabel@pengutronix.de>
> > Signed-off-by: Cheng-Yi Chiang <cychiang@chromium.org>
> > ---
> > The original patch is at
> > https://lore.kernel.org/linux-arm-kernel/20161213150813.37966-2-hverkuil@xs4all.nl
> > 
> >  MAINTAINERS                   |   6 ++
> >  drivers/video/Kconfig         |   3 +
> >  drivers/video/Makefile        |   1 +
> >  drivers/video/hdmi-notifier.c | 145 ++++++++++++++++++++++++++++++++++
> >  include/linux/hdmi-notifier.h | 112 ++++++++++++++++++++++++++
> >  5 files changed, 267 insertions(+)
> >  create mode 100644 drivers/video/hdmi-notifier.c
> >  create mode 100644 include/linux/hdmi-notifier.h
> > 
> > diff --git a/MAINTAINERS b/MAINTAINERS
> > index 5cfbea4ce575..ffb7376f9509 100644
> > --- a/MAINTAINERS
> > +++ b/MAINTAINERS
> > @@ -16676,6 +16676,12 @@ W:	https://linuxtv.org
> >  S:	Maintained
> >  F:	drivers/media/platform/vicodec/*
> >  
> > +VIDEO FRAMEWORK
> > +M:	Hans Verkuil <hverkuil@xs4all.nl>
> > +L:	linux-media@vger.kernel.org
> > +F:	drivers/video/hdmi-notifier.*
> > +S:	Maintained
> > +
> >  VIDEO MULTIPLEXER DRIVER
> >  M:	Philipp Zabel <p.zabel@pengutronix.de>
> >  L:	linux-media@vger.kernel.org
> > diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
> > index 83d3d271ca15..000ba9bc0ae7 100644
> > --- a/drivers/video/Kconfig
> > +++ b/drivers/video/Kconfig
> > @@ -34,6 +34,9 @@ config VIDEOMODE_HELPERS
> >  config HDMI
> >  	bool
> >  
> > +config HDMI_NOTIFIERS
> > +	bool
> > +
> >  endif # HAS_IOMEM
> >  
> >  if VT
> > diff --git a/drivers/video/Makefile b/drivers/video/Makefile
> > index df7650adede9..eff4736102ca 100644
> > --- a/drivers/video/Makefile
> > +++ b/drivers/video/Makefile
> > @@ -1,6 +1,7 @@
> >  # SPDX-License-Identifier: GPL-2.0
> >  obj-$(CONFIG_VGASTATE)            += vgastate.o
> >  obj-$(CONFIG_HDMI)                += hdmi.o
> > +obj-$(CONFIG_HDMI_NOTIFIERS)      += hdmi-notifier.o
> >  
> >  obj-$(CONFIG_VT)		  += console/
> >  obj-$(CONFIG_FB_STI)		  += console/
> > diff --git a/drivers/video/hdmi-notifier.c b/drivers/video/hdmi-notifier.c
> > new file mode 100644
> > index 000000000000..d1eedf661648
> > --- /dev/null
> > +++ b/drivers/video/hdmi-notifier.c
> > @@ -0,0 +1,145 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/* hdmi-notifier.c - notify interested parties of (dis)connect and EDID
> > + * events
> > + *
> > + * Copyright 2016 Russell King <rmk+kernel@arm.linux.org.uk>
> > + * Copyright 2016 Cisco Systems, Inc. and/or its affiliates.
> > + * All rights reserved.
> > + */
> > +
> > +#include <linux/export.h>
> > +#include <linux/hdmi-notifier.h>
> > +#include <linux/string.h>
> > +#include <linux/slab.h>
> > +#include <linux/list.h>
> > +
> > +static LIST_HEAD(hdmi_notifiers);
> > +static DEFINE_MUTEX(hdmi_notifiers_lock);
> > +
> > +struct hdmi_notifier *hdmi_notifier_get(struct device *dev)
> > +{
> > +	struct hdmi_notifier *n;
> > +
> > +	mutex_lock(&hdmi_notifiers_lock);
> > +	list_for_each_entry(n, &hdmi_notifiers, head) {
> > +		if (n->dev == dev) {
> > +			mutex_unlock(&hdmi_notifiers_lock);
> > +			kref_get(&n->kref);
> > +			return n;
> > +		}
> > +	}
> > +	n = kzalloc(sizeof(*n), GFP_KERNEL);
> > +	if (!n)
> > +		goto unlock;
> > +	n->dev = dev;
> > +	mutex_init(&n->lock);
> > +	BLOCKING_INIT_NOTIFIER_HEAD(&n->notifiers);
> > +	kref_init(&n->kref);
> > +	list_add_tail(&n->head, &hdmi_notifiers);
> > +unlock:
> > +	mutex_unlock(&hdmi_notifiers_lock);
> > +	return n;
> > +}
> > +EXPORT_SYMBOL_GPL(hdmi_notifier_get);
> > +
> > +static void hdmi_notifier_release(struct kref *kref)
> > +{
> > +	struct hdmi_notifier *n =
> > +		container_of(kref, struct hdmi_notifier, kref);
> > +
> > +	mutex_lock(&hdmi_notifiers_lock);
> > +	list_del(&n->head);
> > +	mutex_unlock(&hdmi_notifiers_lock);
> > +	kfree(n->edid);
> > +	kfree(n);
> > +}
> > +
> > +void hdmi_notifier_put(struct hdmi_notifier *n)
> > +{
> > +	kref_put(&n->kref, hdmi_notifier_release);
> > +}
> > +EXPORT_SYMBOL_GPL(hdmi_notifier_put);
> > +
> > +int hdmi_notifier_register(struct hdmi_notifier *n, struct notifier_block *nb)
> > +{
> > +	int ret = blocking_notifier_chain_register(&n->notifiers, nb);
> > +
> > +	if (ret)
> > +		return ret;
> > +	kref_get(&n->kref);
> > +	mutex_lock(&n->lock);
> > +	if (n->connected) {
> > +		blocking_notifier_call_chain(&n->notifiers, HDMI_CONNECTED, n);
> > +		if (n->edid_size)
> > +			blocking_notifier_call_chain(&n->notifiers,
> > +						     HDMI_NEW_EDID, n);
> > +		if (n->has_eld)
> > +			blocking_notifier_call_chain(&n->notifiers,
> > +						     HDMI_NEW_ELD, n);
> > +	}
> > +	mutex_unlock(&n->lock);
> > +	return 0;
> > +}
> > +EXPORT_SYMBOL_GPL(hdmi_notifier_register);
> > +
> > +int hdmi_notifier_unregister(struct hdmi_notifier *n, struct notifier_block *nb)
> > +{
> > +	int ret = blocking_notifier_chain_unregister(&n->notifiers, nb);
> > +
> > +	if (ret == 0)
> > +		hdmi_notifier_put(n);
> > +	return ret;
> > +}
> > +EXPORT_SYMBOL_GPL(hdmi_notifier_unregister);
> > +
> > +void hdmi_event_connect(struct hdmi_notifier *n)
> > +{
> > +	mutex_lock(&n->lock);
> > +	n->connected = true;
> > +	blocking_notifier_call_chain(&n->notifiers, HDMI_CONNECTED, n);
> > +	mutex_unlock(&n->lock);
> > +}
> > +EXPORT_SYMBOL_GPL(hdmi_event_connect);
> > +
> > +void hdmi_event_disconnect(struct hdmi_notifier *n)
> > +{
> > +	mutex_lock(&n->lock);
> > +	n->connected = false;
> > +	n->has_eld = false;
> > +	n->edid_size = 0;
> > +	blocking_notifier_call_chain(&n->notifiers, HDMI_DISCONNECTED, n);
> > +	mutex_unlock(&n->lock);
> > +}
> > +EXPORT_SYMBOL_GPL(hdmi_event_disconnect);
> > +
> > +int hdmi_event_new_edid(struct hdmi_notifier *n, const void *edid, size_t size)
> > +{
> > +	mutex_lock(&n->lock);
> > +	if (n->edid_allocated_size < size) {
> > +		void *p = kmalloc(size, GFP_KERNEL);
> > +
> > +		if (!p) {
> > +			mutex_unlock(&n->lock);
> > +			return -ENOMEM;
> > +		}
> > +		kfree(n->edid);
> > +		n->edid = p;
> > +		n->edid_allocated_size = size;
> > +	}
> > +	memcpy(n->edid, edid, size);
> > +	n->edid_size = size;
> > +	blocking_notifier_call_chain(&n->notifiers, HDMI_NEW_EDID, n);
> > +	mutex_unlock(&n->lock);
> > +	return 0;
> > +}
> > +EXPORT_SYMBOL_GPL(hdmi_event_new_edid);
> > +
> > +void hdmi_event_new_eld(struct hdmi_notifier *n, const u8 eld[128])
> > +{
> > +	mutex_lock(&n->lock);
> > +	memcpy(n->eld, eld, sizeof(n->eld));
> > +	n->has_eld = true;
> > +	blocking_notifier_call_chain(&n->notifiers, HDMI_NEW_ELD, n);
> > +	mutex_unlock(&n->lock);
> > +}
> > +EXPORT_SYMBOL_GPL(hdmi_event_new_eld);
> > diff --git a/include/linux/hdmi-notifier.h b/include/linux/hdmi-notifier.h
> > new file mode 100644
> > index 000000000000..c8f35110e3e3
> > --- /dev/null
> > +++ b/include/linux/hdmi-notifier.h
> > @@ -0,0 +1,112 @@
> > +/* SPDX-License-Identifier: GPL-2.0
> > + * hdmi-notifier.h - notify interested parties of (dis)connect and EDID
> > + * events
> > + *
> > + * Copyright 2016 Russell King <rmk+kernel@arm.linux.org.uk>
> > + * Copyright 2016 Cisco Systems, Inc. and/or its affiliates.
> > + * All rights reserved.
> > + */
> > +
> > +#ifndef LINUX_HDMI_NOTIFIER_H
> > +#define LINUX_HDMI_NOTIFIER_H
> > +
> > +#include <linux/types.h>
> > +#include <linux/notifier.h>
> > +#include <linux/kref.h>
> > +
> > +enum {
> > +	HDMI_CONNECTED,
> > +	HDMI_DISCONNECTED,
> > +	HDMI_NEW_EDID,
> > +	HDMI_NEW_ELD,
> > +};
> > +
> > +struct device;
> > +
> > +struct hdmi_notifier {
> > +	/* Lock to protect callback registration and notification. */
> > +	struct mutex lock;
> > +	struct list_head head;
> > +	struct kref kref;
> > +	struct blocking_notifier_head notifiers;
> > +	struct device *dev;
> > +
> > +	/* Current state */
> > +	unsigned int connected : 1;
> > +	unsigned int has_eld : 1;
> > +	unsigned char eld[128];
> > +	void *edid;
> > +	size_t edid_size;
> > +	size_t edid_allocated_size;
> > +};
> > +
> > +/**
> > + * hdmi_notifier_get - find or create a new hdmi_notifier for the given device.
> > + * @dev: device that sends the events.
> > + *
> > + * If a notifier for device @dev already exists, then increase the refcount
> > + * and return that notifier.
> > + *
> > + * If it doesn't exist, then allocate a new notifier struct and return a
> > + * pointer to that new struct.
> > + *
> > + * Return NULL if the memory could not be allocated.
> > + */
> > +struct hdmi_notifier *hdmi_notifier_get(struct device *dev);
> > +
> > +/**
> > + * hdmi_notifier_put - decrease refcount and delete when the refcount reaches 0.
> > + * @n: notifier
> > + */
> > +void hdmi_notifier_put(struct hdmi_notifier *n);
> > +
> > +/**
> > + * hdmi_notifier_register - register the notifier with the notifier_block.
> > + * @n: the HDMI notifier
> > + * @nb: the notifier_block
> > + */
> > +int hdmi_notifier_register(struct hdmi_notifier *n, struct notifier_block *nb);
> > +
> > +/**
> > + * hdmi_notifier_unregister - unregister the notifier with the notifier_block.
> > + * @n: the HDMI notifier
> > + * @nb: the notifier_block
> > + */
> > +int hdmi_notifier_unregister(struct hdmi_notifier *n,
> > +			     struct notifier_block *nb);
> > +
> > +/**
> > + * hdmi_event_connect - send a connect event.
> > + * @n: the HDMI notifier
> > + *
> > + * Send an HDMI_CONNECTED event to any registered parties.
> > + */
> > +void hdmi_event_connect(struct hdmi_notifier *n);
> > +
> > +/**
> > + * hdmi_event_disconnect - send a disconnect event.
> > + * @n: the HDMI notifier
> > + *
> > + * Send an HDMI_DISCONNECTED event to any registered parties.
> > + */
> > +void hdmi_event_disconnect(struct hdmi_notifier *n);
> > +
> > +/**
> > + * hdmi_event_new_edid - send a new EDID event.
> > + * @n: the HDMI notifier
> > + *
> > + * Send an HDMI_NEW_EDID event to any registered parties.
> > + * This function will make a copy the EDID so it can return -ENOMEM if
> > + * no memory could be allocated.
> > + */
> > +int hdmi_event_new_edid(struct hdmi_notifier *n, const void *edid, size_t size);
> > +
> > +/**
> > + * hdmi_event_new_eld - send a new ELD event.
> > + * @n: the HDMI notifier
> > + *
> > + * Send an HDMI_NEW_ELD event to any registered parties.
> > + */
> > +void hdmi_event_new_eld(struct hdmi_notifier *n, const u8 eld[128]);
> > +
> > +#endif
> > 
> 

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [alsa-devel] [PATCH 2/7] ASoC: hdmi-codec: use HDMI state notifier to add jack support
  2019-06-03  8:03   ` [alsa-devel] " Amadeusz Sławiński
@ 2019-06-03  8:53     ` Cheng-yi Chiang
  0 siblings, 0 replies; 30+ messages in thread
From: Cheng-yi Chiang @ 2019-06-03  8:53 UTC (permalink / raw)
  To: Amadeusz Sławiński
  Cc: moderated list:SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEM...,
	Heiko Stuebner, Liam Girdwood, David Airlie, dri-devel,
	Takashi Iwai, Hans Verkuil, Andrzej Hajda, Laurent Pinchart,
	linux-rockchip, Dylan Reid, linux-media, devicetree, tzungbi,
	Daniel Vetter, Bartlomiej Zolnierkiewicz, Russell King,
	Rob Herring, linux-arm-kernel, Greg Kroah-Hartman, Doug Anderson,
	linux-kernel, Mark Brown, Philipp Zabel

On Mon, Jun 3, 2019 at 3:59 PM Amadeusz Sławiński
<amadeuszx.slawinski@linux.intel.com> wrote:
>
> On Mon,  3 Jun 2019 12:32:46 +0800
> Cheng-Yi Chiang <cychiang@chromium.org> wrote:
>
> > From: Philipp Zabel <p.zabel@pengutronix.de>
> >
> > Use HDMI connection / disconnection notifications to update an ALSA
> > jack object. Also make a copy of the ELD block after every change.
> >
> > This was posted by Philipp Zabel at
> >
> > https://patchwork.kernel.org/patch/9430747/
> >
> > Modified by Cheng-Yi Chiang:
> > - Fix the conflict of removed hdmi_codec_remove ops.
> > - Other minor fix for the conflict with latest hdmi-codec on ASoC
> >   for-next tree.
> >
> > Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
> > Signed-off-by: Cheng-Yi Chiang <cychiang@chromium.org>
> > ---
> > The original patch is at https://patchwork.kernel.org/patch/9430747/
> > I could not find the LKML link for the patch.
> >
> >  include/sound/hdmi-codec.h    |   7 +++
> >  sound/soc/codecs/Kconfig      |   1 +
> >  sound/soc/codecs/hdmi-codec.c | 104
> > +++++++++++++++++++++++++++++++++- 3 files changed, 110
> > insertions(+), 2 deletions(-)
> >
> > diff --git a/include/sound/hdmi-codec.h b/include/sound/hdmi-codec.h
> > index 9483c55f871b..4fa39c93363f 100644
> > --- a/include/sound/hdmi-codec.h
> > +++ b/include/sound/hdmi-codec.h
> > @@ -107,6 +107,13 @@ struct hdmi_codec_pdata {
> >       void *data;
> >  };
> >
> > +struct snd_soc_component;
> > +struct snd_soc_jack;
> > +
> > +int hdmi_codec_set_jack_detect(struct snd_soc_component *component,
> > +                            struct snd_soc_jack *jack,
> > +                            struct device *dev);
> > +
> >  #define HDMI_CODEC_DRV_NAME "hdmi-audio-codec"
> >
> >  #endif /* __HDMI_CODEC_H__ */
> > diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
> > index 8f577258080b..f5f6dd04234c 100644
> > --- a/sound/soc/codecs/Kconfig
> > +++ b/sound/soc/codecs/Kconfig
> > @@ -639,6 +639,7 @@ config SND_SOC_HDMI_CODEC
> >       select SND_PCM_ELD
> >       select SND_PCM_IEC958
> >       select HDMI
> > +     select HDMI_NOTIFIERS
> >
> >  config SND_SOC_ES7134
> >         tristate "Everest Semi ES7134 CODEC"
> > diff --git a/sound/soc/codecs/hdmi-codec.c
> > b/sound/soc/codecs/hdmi-codec.c index 6a0cc8d7e141..fe796a7475a5
> > 100644 --- a/sound/soc/codecs/hdmi-codec.c
> > +++ b/sound/soc/codecs/hdmi-codec.c
> > @@ -12,9 +12,12 @@
> >   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.       See
> > the GNU
> >   * General Public License for more details.
> >   */
> > +#include <linux/hdmi-notifier.h>
> >  #include <linux/module.h>
> > +#include <linux/notifier.h>
> >  #include <linux/string.h>
> >  #include <sound/core.h>
> > +#include <sound/jack.h>
> >  #include <sound/pcm.h>
> >  #include <sound/pcm_params.h>
> >  #include <sound/soc.h>
> > @@ -282,6 +285,13 @@ struct hdmi_codec_priv {
> >       struct snd_pcm_chmap *chmap_info;
> >       unsigned int chmap_idx;
> >       struct mutex lock;
> > +     struct snd_soc_jack *jack;
> > +     /* Lock to protect setting and getting eld. */
> > +     struct mutex eld_lock;
> > +     struct device *dev;
> > +     struct hdmi_notifier *notifier;
> > +     struct notifier_block nb;
> > +     unsigned int jack_status;
> >  };
> >
> >  static const struct snd_soc_dapm_widget hdmi_widgets[] = {
> > @@ -308,7 +318,9 @@ static int hdmi_eld_ctl_get(struct snd_kcontrol
> > *kcontrol, struct snd_soc_component *component =
> > snd_kcontrol_chip(kcontrol); struct hdmi_codec_priv *hcp =
> > snd_soc_component_get_drvdata(component);
> > +     mutex_lock(&hcp->eld_lock);
> >       memcpy(ucontrol->value.bytes.data, hcp->eld,
> > sizeof(hcp->eld));
> > +     mutex_unlock(&hcp->eld_lock);
> >
> >       return 0;
> >  }
> > @@ -393,7 +405,7 @@ static int hdmi_codec_startup(struct
> > snd_pcm_substream *substream, struct snd_soc_dai *dai)
> >  {
> >       struct hdmi_codec_priv *hcp = snd_soc_dai_get_drvdata(dai);
> > -     int ret = 0;
> > +     int ret;
> >
> >       ret = mutex_trylock(&hcp->lock);
> >       if (!ret) {
> > @@ -408,9 +420,9 @@ static int hdmi_codec_startup(struct
> > snd_pcm_substream *substream, }
> >
> >       if (hcp->hcd.ops->get_eld) {
> > +             mutex_lock(&hcp->eld_lock);
> >               ret = hcp->hcd.ops->get_eld(dai->dev->parent,
> > hcp->hcd.data, hcp->eld, sizeof(hcp->eld));
> > -
> >               if (!ret) {
> >                       ret =
> > snd_pcm_hw_constraint_eld(substream->runtime, hcp->eld);
>
> Seems to me like you missed unlock here. There is return inside this
> if().
>

Thanks for checking!
The latest patch on hdmi-codec.c on ASoC tree has a change to replace
that return to goto err.

https://patchwork.kernel.org/patch/10930875/

My patch is based on that so it should be okay.
Thanks!

> > @@ -419,6 +431,7 @@ static int hdmi_codec_startup(struct
> > snd_pcm_substream *substream, }
> >               /* Select chmap supported */
> >               hdmi_codec_eld_chmap(hcp);
> > +             mutex_unlock(&hcp->eld_lock);
> >       }
> >       return 0;
> >
> > @@ -747,6 +760,77 @@ static const struct snd_soc_component_driver
> > hdmi_driver = { .non_legacy_dai_naming        = 1,
> >  };
> >
> > +static void hdmi_codec_jack_report(struct hdmi_codec_priv *hcp,
> > +                                unsigned int jack_status)
> > +{
> > +     if (!hcp->jack)
> > +             return;
> > +
> > +     if (jack_status != hcp->jack_status) {
> > +             snd_soc_jack_report(hcp->jack, jack_status,
> > SND_JACK_LINEOUT);
> > +             hcp->jack_status = jack_status;
> > +     }
> > +}
> > +
> > +static int hdmi_codec_notify(struct notifier_block *nb, unsigned
> > long event,
> > +                          void *data)
> > +{
> > +     struct hdmi_codec_priv *hcp = container_of(nb, struct
> > hdmi_codec_priv,
> > +                                                nb);
> > +     struct hdmi_notifier *n = data;
> > +
> > +     if (!hcp->jack)
> > +             return NOTIFY_OK;
> > +
> > +     switch (event) {
> > +     case HDMI_NEW_ELD:
> > +             mutex_lock(&hcp->eld_lock);
> > +             memcpy(hcp->eld, n->eld, sizeof(hcp->eld));
> > +             mutex_unlock(&hcp->eld_lock);
> > +             /* fall through */
> > +     case HDMI_CONNECTED:
> > +             hdmi_codec_jack_report(hcp, SND_JACK_LINEOUT);
> > +             break;
> > +     case HDMI_DISCONNECTED:
> > +             hdmi_codec_jack_report(hcp, 0);
> > +             break;
> > +     }
> > +
> > +     return NOTIFY_OK;
> > +}
> > +
> > +/**
> > + * hdmi_codec_set_jack_detect - register HDMI state notifier callback
> > + * @component: the hdmi-codec instance
> > + * @jack: ASoC jack to report (dis)connection events on
> > + * @dev: hdmi_notifier device, usually HDMI_TX or CEC device
> > + */
> > +int hdmi_codec_set_jack_detect(struct snd_soc_component *component,
> > +                            struct snd_soc_jack *jack,
> > +                            struct device *dev)
> > +{
> > +     struct hdmi_codec_priv *hcp =
> > snd_soc_component_get_drvdata(component);
> > +     int ret;
> > +
> > +     hcp->notifier = hdmi_notifier_get(dev);
> > +     if (!hcp->notifier)
> > +             return -ENOMEM;
> > +
> > +     hcp->jack = jack;
> > +     hcp->nb.notifier_call = hdmi_codec_notify;
> > +     ret = hdmi_notifier_register(hcp->notifier, &hcp->nb);
> > +     if (ret)
> > +             goto err_notifier_put;
> > +
> > +     return 0;
> > +
> > +err_notifier_put:
> > +     hdmi_notifier_put(hcp->notifier);
> > +     hcp->notifier = NULL;
> > +     return ret;
> > +}
> > +EXPORT_SYMBOL_GPL(hdmi_codec_set_jack_detect);
> > +
> >  static int hdmi_codec_probe(struct platform_device *pdev)
> >  {
> >       struct hdmi_codec_pdata *hcd = pdev->dev.platform_data;
> > @@ -774,6 +858,7 @@ static int hdmi_codec_probe(struct
> > platform_device *pdev)
> >       hcp->hcd = *hcd;
> >       mutex_init(&hcp->lock);
> > +     mutex_init(&hcp->eld_lock);
> >
> >       daidrv = devm_kcalloc(dev, dai_count, sizeof(*daidrv),
> > GFP_KERNEL); if (!daidrv)
> > @@ -797,6 +882,20 @@ static int hdmi_codec_probe(struct
> > platform_device *pdev) __func__, ret);
> >               return ret;
> >       }
> > +
> > +     hcp->dev = dev;
> > +
> > +     return 0;
> > +}
> > +
> > +static int hdmi_codec_remove(struct platform_device *pdev)
> > +{
> > +     struct hdmi_codec_priv *hcp = platform_get_drvdata(pdev);
> > +
> > +     if (hcp->notifier) {
> > +             hdmi_notifier_unregister(hcp->notifier, &hcp->nb);
> > +             hdmi_notifier_put(hcp->notifier);
> > +     }
> >       return 0;
> >  }
> >
> > @@ -805,6 +904,7 @@ static struct platform_driver hdmi_codec_driver =
> > { .name = HDMI_CODEC_DRV_NAME,
> >       },
> >       .probe = hdmi_codec_probe,
> > +     .remove = hdmi_codec_remove,
> >  };
> >
> >  module_platform_driver(hdmi_codec_driver);
>

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 1/7] video: add HDMI state notifier support
  2019-06-03  8:09     ` Daniel Vetter
@ 2019-06-03  9:05       ` Hans Verkuil
  2019-06-04  7:19         ` Daniel Vetter
  2019-06-04  2:32       ` Cheng-yi Chiang
  1 sibling, 1 reply; 30+ messages in thread
From: Hans Verkuil @ 2019-06-03  9:05 UTC (permalink / raw)
  To: Cheng-Yi Chiang, linux-kernel, Bartlomiej Zolnierkiewicz,
	Greg Kroah-Hartman, Philipp Zabel, Mark Brown, Liam Girdwood,
	Takashi Iwai, Jaroslav Kysela, Russell King, Andrzej Hajda,
	Laurent Pinchart, David Airlie, Rob Herring, Heiko Stuebner,
	dianders, dgreid, tzungbi, linux-media, alsa-devel, dri-devel,
	linux-arm-kernel, linux-rockchip, devicetree,
	Dariusz Marcinkiewicz

On 6/3/19 10:09 AM, Daniel Vetter wrote:
> On Mon, Jun 03, 2019 at 09:45:49AM +0200, Hans Verkuil wrote:
>> On 6/3/19 6:32 AM, Cheng-Yi Chiang wrote:
>>> From: Hans Verkuil <hans.verkuil@cisco.com>
>>>
>>> Add support for HDMI hotplug and EDID notifiers, which is used to convey
>>> information from HDMI drivers to their CEC and audio counterparts.
>>>
>>> Based on an earlier version from Russell King:
>>>
>>> https://patchwork.kernel.org/patch/9277043/
>>>
>>> The hdmi_notifier is a reference counted object containing the HDMI state
>>> of an HDMI device.
>>>
>>> When a new notifier is registered the current state will be reported to
>>> that notifier at registration time.
>>>
>>> Based on Hans Verkuil's patch:
>>>
>>> https://patchwork.kernel.org/patch/9472521/
>>
>> Erm, you are aware that this patch morphed into a CEC-specific notifier
>> found in drivers/media/cec/cec-notifier.c?
>>
>> I don't think it makes sense to have two notifier implementations in the kernel.
>> The original intention was to have the notifier deal with both CEC and ASoC
>> notifications, but there was not enough interest for the ASoC bits at the time
>> and it was dropped.
>>
>> I am planning changes to the cec-notifier API, I hope to work on that this
>> week. I'll CC you when I post those. Those might be a good starting point
>> to convert the cec-notifier to an hdmi-notifier as was originally intended.
>>
>> I've added your colleague Dariusz Marcinkiewicz to the CC list since he's been
>> working on some nice cec-notifier improvements as well.
> 
> We also have some interfaces for drm/alsa interactions around hdmi
> already in drm/drm_audio_component.h, but it's not used by anything
> outside of i915. Imo we should extend that, not reinvent a new wheel.

If that can be used instead of this hdmi-notifier, then that's fine by me.

> Another note: notifiers considered evil, imo. Gets the job done for one
> case, as soon as you have multiple devices and need to make sure you get
> the update for the right one it all comes crashing down. Please create an
> api which registers for updates from a specific device only, plus
> something that has real callbacks (like the drm_audio_component.h thing we
> started already).

For CEC the notifier works very well. But CEC has some special requirements
that ASoC doesn't have:

- The cec-notifier can be used by both HDMI transmitters and receivers (so
has to work with two different subsystems).

- There may be multiple CEC devices connected to one HDMI transmitter: one
that is used when the system is in Standby, and a more capable CEC device
used when the system is powered up. This isn't supported yet, but it is likely
that we'll need this.

- HDMI and CEC devices are often completely independent and one or the other
(or both) can be unbound at any time. A real-world example is when an FPGA
containing the HDMI and/or CEC support is unloaded to save power when in standby.

- In some cases you want to register a CEC device via a notifier to an HDMI
connector based on userspace information. E.g. the popular USB Pulse-Eight CEC
device can be connected to any HDMI output by the user, there is no way to know
this in the kernel. An application that knows about the Pulse-Eight currently
has to parse the EDID and set the Physical Address of the Pulse-Eight accordingly.
I want to make it possible that the user can just tell the Pulse-Eight which HDMI
output is used and have it connect to that output using the notifier. I have a
proof-of-concept, but this needs Dariusz' series to make it work.

Regards,

	Hans

> -Daniel
> 
>>
>> Regards,
>>
>> 	Hans
>>
>>>
>>> Modified by Cheng-Yi Chiang:
>>>  - Add a section in MAINTAINER.
>>>  - Changes connected and has_eld to bitfield of unsigned int.
>>>  - Other minor fixes to pass checkpatch.pl --strict checks.
>>>
>>> Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
>>> Acked-by: Philipp Zabel <p.zabel@pengutronix.de>
>>> Signed-off-by: Cheng-Yi Chiang <cychiang@chromium.org>
>>> ---
>>> The original patch is at
>>> https://lore.kernel.org/linux-arm-kernel/20161213150813.37966-2-hverkuil@xs4all.nl
>>>
>>>  MAINTAINERS                   |   6 ++
>>>  drivers/video/Kconfig         |   3 +
>>>  drivers/video/Makefile        |   1 +
>>>  drivers/video/hdmi-notifier.c | 145 ++++++++++++++++++++++++++++++++++
>>>  include/linux/hdmi-notifier.h | 112 ++++++++++++++++++++++++++
>>>  5 files changed, 267 insertions(+)
>>>  create mode 100644 drivers/video/hdmi-notifier.c
>>>  create mode 100644 include/linux/hdmi-notifier.h
>>>
>>> diff --git a/MAINTAINERS b/MAINTAINERS
>>> index 5cfbea4ce575..ffb7376f9509 100644
>>> --- a/MAINTAINERS
>>> +++ b/MAINTAINERS
>>> @@ -16676,6 +16676,12 @@ W:	https://linuxtv.org
>>>  S:	Maintained
>>>  F:	drivers/media/platform/vicodec/*
>>>  
>>> +VIDEO FRAMEWORK
>>> +M:	Hans Verkuil <hverkuil@xs4all.nl>
>>> +L:	linux-media@vger.kernel.org
>>> +F:	drivers/video/hdmi-notifier.*
>>> +S:	Maintained
>>> +
>>>  VIDEO MULTIPLEXER DRIVER
>>>  M:	Philipp Zabel <p.zabel@pengutronix.de>
>>>  L:	linux-media@vger.kernel.org
>>> diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
>>> index 83d3d271ca15..000ba9bc0ae7 100644
>>> --- a/drivers/video/Kconfig
>>> +++ b/drivers/video/Kconfig
>>> @@ -34,6 +34,9 @@ config VIDEOMODE_HELPERS
>>>  config HDMI
>>>  	bool
>>>  
>>> +config HDMI_NOTIFIERS
>>> +	bool
>>> +
>>>  endif # HAS_IOMEM
>>>  
>>>  if VT
>>> diff --git a/drivers/video/Makefile b/drivers/video/Makefile
>>> index df7650adede9..eff4736102ca 100644
>>> --- a/drivers/video/Makefile
>>> +++ b/drivers/video/Makefile
>>> @@ -1,6 +1,7 @@
>>>  # SPDX-License-Identifier: GPL-2.0
>>>  obj-$(CONFIG_VGASTATE)            += vgastate.o
>>>  obj-$(CONFIG_HDMI)                += hdmi.o
>>> +obj-$(CONFIG_HDMI_NOTIFIERS)      += hdmi-notifier.o
>>>  
>>>  obj-$(CONFIG_VT)		  += console/
>>>  obj-$(CONFIG_FB_STI)		  += console/
>>> diff --git a/drivers/video/hdmi-notifier.c b/drivers/video/hdmi-notifier.c
>>> new file mode 100644
>>> index 000000000000..d1eedf661648
>>> --- /dev/null
>>> +++ b/drivers/video/hdmi-notifier.c
>>> @@ -0,0 +1,145 @@
>>> +// SPDX-License-Identifier: GPL-2.0
>>> +/* hdmi-notifier.c - notify interested parties of (dis)connect and EDID
>>> + * events
>>> + *
>>> + * Copyright 2016 Russell King <rmk+kernel@arm.linux.org.uk>
>>> + * Copyright 2016 Cisco Systems, Inc. and/or its affiliates.
>>> + * All rights reserved.
>>> + */
>>> +
>>> +#include <linux/export.h>
>>> +#include <linux/hdmi-notifier.h>
>>> +#include <linux/string.h>
>>> +#include <linux/slab.h>
>>> +#include <linux/list.h>
>>> +
>>> +static LIST_HEAD(hdmi_notifiers);
>>> +static DEFINE_MUTEX(hdmi_notifiers_lock);
>>> +
>>> +struct hdmi_notifier *hdmi_notifier_get(struct device *dev)
>>> +{
>>> +	struct hdmi_notifier *n;
>>> +
>>> +	mutex_lock(&hdmi_notifiers_lock);
>>> +	list_for_each_entry(n, &hdmi_notifiers, head) {
>>> +		if (n->dev == dev) {
>>> +			mutex_unlock(&hdmi_notifiers_lock);
>>> +			kref_get(&n->kref);
>>> +			return n;
>>> +		}
>>> +	}
>>> +	n = kzalloc(sizeof(*n), GFP_KERNEL);
>>> +	if (!n)
>>> +		goto unlock;
>>> +	n->dev = dev;
>>> +	mutex_init(&n->lock);
>>> +	BLOCKING_INIT_NOTIFIER_HEAD(&n->notifiers);
>>> +	kref_init(&n->kref);
>>> +	list_add_tail(&n->head, &hdmi_notifiers);
>>> +unlock:
>>> +	mutex_unlock(&hdmi_notifiers_lock);
>>> +	return n;
>>> +}
>>> +EXPORT_SYMBOL_GPL(hdmi_notifier_get);
>>> +
>>> +static void hdmi_notifier_release(struct kref *kref)
>>> +{
>>> +	struct hdmi_notifier *n =
>>> +		container_of(kref, struct hdmi_notifier, kref);
>>> +
>>> +	mutex_lock(&hdmi_notifiers_lock);
>>> +	list_del(&n->head);
>>> +	mutex_unlock(&hdmi_notifiers_lock);
>>> +	kfree(n->edid);
>>> +	kfree(n);
>>> +}
>>> +
>>> +void hdmi_notifier_put(struct hdmi_notifier *n)
>>> +{
>>> +	kref_put(&n->kref, hdmi_notifier_release);
>>> +}
>>> +EXPORT_SYMBOL_GPL(hdmi_notifier_put);
>>> +
>>> +int hdmi_notifier_register(struct hdmi_notifier *n, struct notifier_block *nb)
>>> +{
>>> +	int ret = blocking_notifier_chain_register(&n->notifiers, nb);
>>> +
>>> +	if (ret)
>>> +		return ret;
>>> +	kref_get(&n->kref);
>>> +	mutex_lock(&n->lock);
>>> +	if (n->connected) {
>>> +		blocking_notifier_call_chain(&n->notifiers, HDMI_CONNECTED, n);
>>> +		if (n->edid_size)
>>> +			blocking_notifier_call_chain(&n->notifiers,
>>> +						     HDMI_NEW_EDID, n);
>>> +		if (n->has_eld)
>>> +			blocking_notifier_call_chain(&n->notifiers,
>>> +						     HDMI_NEW_ELD, n);
>>> +	}
>>> +	mutex_unlock(&n->lock);
>>> +	return 0;
>>> +}
>>> +EXPORT_SYMBOL_GPL(hdmi_notifier_register);
>>> +
>>> +int hdmi_notifier_unregister(struct hdmi_notifier *n, struct notifier_block *nb)
>>> +{
>>> +	int ret = blocking_notifier_chain_unregister(&n->notifiers, nb);
>>> +
>>> +	if (ret == 0)
>>> +		hdmi_notifier_put(n);
>>> +	return ret;
>>> +}
>>> +EXPORT_SYMBOL_GPL(hdmi_notifier_unregister);
>>> +
>>> +void hdmi_event_connect(struct hdmi_notifier *n)
>>> +{
>>> +	mutex_lock(&n->lock);
>>> +	n->connected = true;
>>> +	blocking_notifier_call_chain(&n->notifiers, HDMI_CONNECTED, n);
>>> +	mutex_unlock(&n->lock);
>>> +}
>>> +EXPORT_SYMBOL_GPL(hdmi_event_connect);
>>> +
>>> +void hdmi_event_disconnect(struct hdmi_notifier *n)
>>> +{
>>> +	mutex_lock(&n->lock);
>>> +	n->connected = false;
>>> +	n->has_eld = false;
>>> +	n->edid_size = 0;
>>> +	blocking_notifier_call_chain(&n->notifiers, HDMI_DISCONNECTED, n);
>>> +	mutex_unlock(&n->lock);
>>> +}
>>> +EXPORT_SYMBOL_GPL(hdmi_event_disconnect);
>>> +
>>> +int hdmi_event_new_edid(struct hdmi_notifier *n, const void *edid, size_t size)
>>> +{
>>> +	mutex_lock(&n->lock);
>>> +	if (n->edid_allocated_size < size) {
>>> +		void *p = kmalloc(size, GFP_KERNEL);
>>> +
>>> +		if (!p) {
>>> +			mutex_unlock(&n->lock);
>>> +			return -ENOMEM;
>>> +		}
>>> +		kfree(n->edid);
>>> +		n->edid = p;
>>> +		n->edid_allocated_size = size;
>>> +	}
>>> +	memcpy(n->edid, edid, size);
>>> +	n->edid_size = size;
>>> +	blocking_notifier_call_chain(&n->notifiers, HDMI_NEW_EDID, n);
>>> +	mutex_unlock(&n->lock);
>>> +	return 0;
>>> +}
>>> +EXPORT_SYMBOL_GPL(hdmi_event_new_edid);
>>> +
>>> +void hdmi_event_new_eld(struct hdmi_notifier *n, const u8 eld[128])
>>> +{
>>> +	mutex_lock(&n->lock);
>>> +	memcpy(n->eld, eld, sizeof(n->eld));
>>> +	n->has_eld = true;
>>> +	blocking_notifier_call_chain(&n->notifiers, HDMI_NEW_ELD, n);
>>> +	mutex_unlock(&n->lock);
>>> +}
>>> +EXPORT_SYMBOL_GPL(hdmi_event_new_eld);
>>> diff --git a/include/linux/hdmi-notifier.h b/include/linux/hdmi-notifier.h
>>> new file mode 100644
>>> index 000000000000..c8f35110e3e3
>>> --- /dev/null
>>> +++ b/include/linux/hdmi-notifier.h
>>> @@ -0,0 +1,112 @@
>>> +/* SPDX-License-Identifier: GPL-2.0
>>> + * hdmi-notifier.h - notify interested parties of (dis)connect and EDID
>>> + * events
>>> + *
>>> + * Copyright 2016 Russell King <rmk+kernel@arm.linux.org.uk>
>>> + * Copyright 2016 Cisco Systems, Inc. and/or its affiliates.
>>> + * All rights reserved.
>>> + */
>>> +
>>> +#ifndef LINUX_HDMI_NOTIFIER_H
>>> +#define LINUX_HDMI_NOTIFIER_H
>>> +
>>> +#include <linux/types.h>
>>> +#include <linux/notifier.h>
>>> +#include <linux/kref.h>
>>> +
>>> +enum {
>>> +	HDMI_CONNECTED,
>>> +	HDMI_DISCONNECTED,
>>> +	HDMI_NEW_EDID,
>>> +	HDMI_NEW_ELD,
>>> +};
>>> +
>>> +struct device;
>>> +
>>> +struct hdmi_notifier {
>>> +	/* Lock to protect callback registration and notification. */
>>> +	struct mutex lock;
>>> +	struct list_head head;
>>> +	struct kref kref;
>>> +	struct blocking_notifier_head notifiers;
>>> +	struct device *dev;
>>> +
>>> +	/* Current state */
>>> +	unsigned int connected : 1;
>>> +	unsigned int has_eld : 1;
>>> +	unsigned char eld[128];
>>> +	void *edid;
>>> +	size_t edid_size;
>>> +	size_t edid_allocated_size;
>>> +};
>>> +
>>> +/**
>>> + * hdmi_notifier_get - find or create a new hdmi_notifier for the given device.
>>> + * @dev: device that sends the events.
>>> + *
>>> + * If a notifier for device @dev already exists, then increase the refcount
>>> + * and return that notifier.
>>> + *
>>> + * If it doesn't exist, then allocate a new notifier struct and return a
>>> + * pointer to that new struct.
>>> + *
>>> + * Return NULL if the memory could not be allocated.
>>> + */
>>> +struct hdmi_notifier *hdmi_notifier_get(struct device *dev);
>>> +
>>> +/**
>>> + * hdmi_notifier_put - decrease refcount and delete when the refcount reaches 0.
>>> + * @n: notifier
>>> + */
>>> +void hdmi_notifier_put(struct hdmi_notifier *n);
>>> +
>>> +/**
>>> + * hdmi_notifier_register - register the notifier with the notifier_block.
>>> + * @n: the HDMI notifier
>>> + * @nb: the notifier_block
>>> + */
>>> +int hdmi_notifier_register(struct hdmi_notifier *n, struct notifier_block *nb);
>>> +
>>> +/**
>>> + * hdmi_notifier_unregister - unregister the notifier with the notifier_block.
>>> + * @n: the HDMI notifier
>>> + * @nb: the notifier_block
>>> + */
>>> +int hdmi_notifier_unregister(struct hdmi_notifier *n,
>>> +			     struct notifier_block *nb);
>>> +
>>> +/**
>>> + * hdmi_event_connect - send a connect event.
>>> + * @n: the HDMI notifier
>>> + *
>>> + * Send an HDMI_CONNECTED event to any registered parties.
>>> + */
>>> +void hdmi_event_connect(struct hdmi_notifier *n);
>>> +
>>> +/**
>>> + * hdmi_event_disconnect - send a disconnect event.
>>> + * @n: the HDMI notifier
>>> + *
>>> + * Send an HDMI_DISCONNECTED event to any registered parties.
>>> + */
>>> +void hdmi_event_disconnect(struct hdmi_notifier *n);
>>> +
>>> +/**
>>> + * hdmi_event_new_edid - send a new EDID event.
>>> + * @n: the HDMI notifier
>>> + *
>>> + * Send an HDMI_NEW_EDID event to any registered parties.
>>> + * This function will make a copy the EDID so it can return -ENOMEM if
>>> + * no memory could be allocated.
>>> + */
>>> +int hdmi_event_new_edid(struct hdmi_notifier *n, const void *edid, size_t size);
>>> +
>>> +/**
>>> + * hdmi_event_new_eld - send a new ELD event.
>>> + * @n: the HDMI notifier
>>> + *
>>> + * Send an HDMI_NEW_ELD event to any registered parties.
>>> + */
>>> +void hdmi_event_new_eld(struct hdmi_notifier *n, const u8 eld[128]);
>>> +
>>> +#endif
>>>
>>
> 


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 1/7] video: add HDMI state notifier support
  2019-06-03  7:45   ` Hans Verkuil
  2019-06-03  8:09     ` Daniel Vetter
@ 2019-06-04  1:48     ` Cheng-yi Chiang
  1 sibling, 0 replies; 30+ messages in thread
From: Cheng-yi Chiang @ 2019-06-04  1:48 UTC (permalink / raw)
  To: Hans Verkuil
  Cc: moderated list:SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEM...,
	Heiko Stuebner, Liam Girdwood, David Airlie, dri-devel,
	Takashi Iwai, Andrzej Hajda, Laurent Pinchart, linux-rockchip,
	Dylan Reid, linux-media, devicetree, tzungbi, Philipp Zabel,
	Bartlomiej Zolnierkiewicz, Russell King, Rob Herring,
	Jaroslav Kysela, linux-arm-kernel, Greg Kroah-Hartman,
	Doug Anderson, linux-kernel, Mark Brown, Daniel Vetter,
	Dariusz Marcinkiewicz

On Mon, Jun 3, 2019 at 3:46 PM Hans Verkuil <hverkuil@xs4all.nl> wrote:
>
> On 6/3/19 6:32 AM, Cheng-Yi Chiang wrote:
> > From: Hans Verkuil <hans.verkuil@cisco.com>
> >
> > Add support for HDMI hotplug and EDID notifiers, which is used to convey
> > information from HDMI drivers to their CEC and audio counterparts.
> >
> > Based on an earlier version from Russell King:
> >
> > https://patchwork.kernel.org/patch/9277043/
> >
> > The hdmi_notifier is a reference counted object containing the HDMI state
> > of an HDMI device.
> >
> > When a new notifier is registered the current state will be reported to
> > that notifier at registration time.
> >
> > Based on Hans Verkuil's patch:
> >
> > https://patchwork.kernel.org/patch/9472521/
>
> Erm, you are aware that this patch morphed into a CEC-specific notifier
> found in drivers/media/cec/cec-notifier.c?
>
> I don't think it makes sense to have two notifier implementations in the kernel.
> The original intention was to have the notifier deal with both CEC and ASoC
> notifications, but there was not enough interest for the ASoC bits at the time
> and it was dropped.
>
> I am planning changes to the cec-notifier API, I hope to work on that this
> week. I'll CC you when I post those. Those might be a good starting point
> to convert the cec-notifier to an hdmi-notifier as was originally intended.
>
> I've added your colleague Dariusz Marcinkiewicz to the CC list since he's been
> working on some nice cec-notifier improvements as well.

Hi Hans, thank you for quick reply.
I am not aware of the history of cec-notifier and hdmi-notifier.
The reason I took this patch is because its different versions were
used extensively in rockchip tree and chromium tree for years.
And hdmi-notifier patch posted at
https://patchwork.kernel.org/patch/9472521/ did not get objection at
that time.
If you think jack reporting should be supported on cec-notifier
instead, I can look into it after you post the new changes on
cec-notifier.
Thanks!

>
> Regards,
>
>         Hans
>
> >
> > Modified by Cheng-Yi Chiang:
> >  - Add a section in MAINTAINER.
> >  - Changes connected and has_eld to bitfield of unsigned int.
> >  - Other minor fixes to pass checkpatch.pl --strict checks.
> >
> > Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
> > Acked-by: Philipp Zabel <p.zabel@pengutronix.de>
> > Signed-off-by: Cheng-Yi Chiang <cychiang@chromium.org>
> > ---
> > The original patch is at
> > https://lore.kernel.org/linux-arm-kernel/20161213150813.37966-2-hverkuil@xs4all.nl
> >
> >  MAINTAINERS                   |   6 ++
> >  drivers/video/Kconfig         |   3 +
> >  drivers/video/Makefile        |   1 +
> >  drivers/video/hdmi-notifier.c | 145 ++++++++++++++++++++++++++++++++++
> >  include/linux/hdmi-notifier.h | 112 ++++++++++++++++++++++++++
> >  5 files changed, 267 insertions(+)
> >  create mode 100644 drivers/video/hdmi-notifier.c
> >  create mode 100644 include/linux/hdmi-notifier.h
> >
> > diff --git a/MAINTAINERS b/MAINTAINERS
> > index 5cfbea4ce575..ffb7376f9509 100644
> > --- a/MAINTAINERS
> > +++ b/MAINTAINERS
> > @@ -16676,6 +16676,12 @@ W:   https://linuxtv.org
> >  S:   Maintained
> >  F:   drivers/media/platform/vicodec/*
> >
> > +VIDEO FRAMEWORK
> > +M:   Hans Verkuil <hverkuil@xs4all.nl>
> > +L:   linux-media@vger.kernel.org
> > +F:   drivers/video/hdmi-notifier.*
> > +S:   Maintained
> > +
> >  VIDEO MULTIPLEXER DRIVER
> >  M:   Philipp Zabel <p.zabel@pengutronix.de>
> >  L:   linux-media@vger.kernel.org
> > diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
> > index 83d3d271ca15..000ba9bc0ae7 100644
> > --- a/drivers/video/Kconfig
> > +++ b/drivers/video/Kconfig
> > @@ -34,6 +34,9 @@ config VIDEOMODE_HELPERS
> >  config HDMI
> >       bool
> >
> > +config HDMI_NOTIFIERS
> > +     bool
> > +
> >  endif # HAS_IOMEM
> >
> >  if VT
> > diff --git a/drivers/video/Makefile b/drivers/video/Makefile
> > index df7650adede9..eff4736102ca 100644
> > --- a/drivers/video/Makefile
> > +++ b/drivers/video/Makefile
> > @@ -1,6 +1,7 @@
> >  # SPDX-License-Identifier: GPL-2.0
> >  obj-$(CONFIG_VGASTATE)            += vgastate.o
> >  obj-$(CONFIG_HDMI)                += hdmi.o
> > +obj-$(CONFIG_HDMI_NOTIFIERS)      += hdmi-notifier.o
> >
> >  obj-$(CONFIG_VT)               += console/
> >  obj-$(CONFIG_FB_STI)           += console/
> > diff --git a/drivers/video/hdmi-notifier.c b/drivers/video/hdmi-notifier.c
> > new file mode 100644
> > index 000000000000..d1eedf661648
> > --- /dev/null
> > +++ b/drivers/video/hdmi-notifier.c
> > @@ -0,0 +1,145 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/* hdmi-notifier.c - notify interested parties of (dis)connect and EDID
> > + * events
> > + *
> > + * Copyright 2016 Russell King <rmk+kernel@arm.linux.org.uk>
> > + * Copyright 2016 Cisco Systems, Inc. and/or its affiliates.
> > + * All rights reserved.
> > + */
> > +
> > +#include <linux/export.h>
> > +#include <linux/hdmi-notifier.h>
> > +#include <linux/string.h>
> > +#include <linux/slab.h>
> > +#include <linux/list.h>
> > +
> > +static LIST_HEAD(hdmi_notifiers);
> > +static DEFINE_MUTEX(hdmi_notifiers_lock);
> > +
> > +struct hdmi_notifier *hdmi_notifier_get(struct device *dev)
> > +{
> > +     struct hdmi_notifier *n;
> > +
> > +     mutex_lock(&hdmi_notifiers_lock);
> > +     list_for_each_entry(n, &hdmi_notifiers, head) {
> > +             if (n->dev == dev) {
> > +                     mutex_unlock(&hdmi_notifiers_lock);
> > +                     kref_get(&n->kref);
> > +                     return n;
> > +             }
> > +     }
> > +     n = kzalloc(sizeof(*n), GFP_KERNEL);
> > +     if (!n)
> > +             goto unlock;
> > +     n->dev = dev;
> > +     mutex_init(&n->lock);
> > +     BLOCKING_INIT_NOTIFIER_HEAD(&n->notifiers);
> > +     kref_init(&n->kref);
> > +     list_add_tail(&n->head, &hdmi_notifiers);
> > +unlock:
> > +     mutex_unlock(&hdmi_notifiers_lock);
> > +     return n;
> > +}
> > +EXPORT_SYMBOL_GPL(hdmi_notifier_get);
> > +
> > +static void hdmi_notifier_release(struct kref *kref)
> > +{
> > +     struct hdmi_notifier *n =
> > +             container_of(kref, struct hdmi_notifier, kref);
> > +
> > +     mutex_lock(&hdmi_notifiers_lock);
> > +     list_del(&n->head);
> > +     mutex_unlock(&hdmi_notifiers_lock);
> > +     kfree(n->edid);
> > +     kfree(n);
> > +}
> > +
> > +void hdmi_notifier_put(struct hdmi_notifier *n)
> > +{
> > +     kref_put(&n->kref, hdmi_notifier_release);
> > +}
> > +EXPORT_SYMBOL_GPL(hdmi_notifier_put);
> > +
> > +int hdmi_notifier_register(struct hdmi_notifier *n, struct notifier_block *nb)
> > +{
> > +     int ret = blocking_notifier_chain_register(&n->notifiers, nb);
> > +
> > +     if (ret)
> > +             return ret;
> > +     kref_get(&n->kref);
> > +     mutex_lock(&n->lock);
> > +     if (n->connected) {
> > +             blocking_notifier_call_chain(&n->notifiers, HDMI_CONNECTED, n);
> > +             if (n->edid_size)
> > +                     blocking_notifier_call_chain(&n->notifiers,
> > +                                                  HDMI_NEW_EDID, n);
> > +             if (n->has_eld)
> > +                     blocking_notifier_call_chain(&n->notifiers,
> > +                                                  HDMI_NEW_ELD, n);
> > +     }
> > +     mutex_unlock(&n->lock);
> > +     return 0;
> > +}
> > +EXPORT_SYMBOL_GPL(hdmi_notifier_register);
> > +
> > +int hdmi_notifier_unregister(struct hdmi_notifier *n, struct notifier_block *nb)
> > +{
> > +     int ret = blocking_notifier_chain_unregister(&n->notifiers, nb);
> > +
> > +     if (ret == 0)
> > +             hdmi_notifier_put(n);
> > +     return ret;
> > +}
> > +EXPORT_SYMBOL_GPL(hdmi_notifier_unregister);
> > +
> > +void hdmi_event_connect(struct hdmi_notifier *n)
> > +{
> > +     mutex_lock(&n->lock);
> > +     n->connected = true;
> > +     blocking_notifier_call_chain(&n->notifiers, HDMI_CONNECTED, n);
> > +     mutex_unlock(&n->lock);
> > +}
> > +EXPORT_SYMBOL_GPL(hdmi_event_connect);
> > +
> > +void hdmi_event_disconnect(struct hdmi_notifier *n)
> > +{
> > +     mutex_lock(&n->lock);
> > +     n->connected = false;
> > +     n->has_eld = false;
> > +     n->edid_size = 0;
> > +     blocking_notifier_call_chain(&n->notifiers, HDMI_DISCONNECTED, n);
> > +     mutex_unlock(&n->lock);
> > +}
> > +EXPORT_SYMBOL_GPL(hdmi_event_disconnect);
> > +
> > +int hdmi_event_new_edid(struct hdmi_notifier *n, const void *edid, size_t size)
> > +{
> > +     mutex_lock(&n->lock);
> > +     if (n->edid_allocated_size < size) {
> > +             void *p = kmalloc(size, GFP_KERNEL);
> > +
> > +             if (!p) {
> > +                     mutex_unlock(&n->lock);
> > +                     return -ENOMEM;
> > +             }
> > +             kfree(n->edid);
> > +             n->edid = p;
> > +             n->edid_allocated_size = size;
> > +     }
> > +     memcpy(n->edid, edid, size);
> > +     n->edid_size = size;
> > +     blocking_notifier_call_chain(&n->notifiers, HDMI_NEW_EDID, n);
> > +     mutex_unlock(&n->lock);
> > +     return 0;
> > +}
> > +EXPORT_SYMBOL_GPL(hdmi_event_new_edid);
> > +
> > +void hdmi_event_new_eld(struct hdmi_notifier *n, const u8 eld[128])
> > +{
> > +     mutex_lock(&n->lock);
> > +     memcpy(n->eld, eld, sizeof(n->eld));
> > +     n->has_eld = true;
> > +     blocking_notifier_call_chain(&n->notifiers, HDMI_NEW_ELD, n);
> > +     mutex_unlock(&n->lock);
> > +}
> > +EXPORT_SYMBOL_GPL(hdmi_event_new_eld);
> > diff --git a/include/linux/hdmi-notifier.h b/include/linux/hdmi-notifier.h
> > new file mode 100644
> > index 000000000000..c8f35110e3e3
> > --- /dev/null
> > +++ b/include/linux/hdmi-notifier.h
> > @@ -0,0 +1,112 @@
> > +/* SPDX-License-Identifier: GPL-2.0
> > + * hdmi-notifier.h - notify interested parties of (dis)connect and EDID
> > + * events
> > + *
> > + * Copyright 2016 Russell King <rmk+kernel@arm.linux.org.uk>
> > + * Copyright 2016 Cisco Systems, Inc. and/or its affiliates.
> > + * All rights reserved.
> > + */
> > +
> > +#ifndef LINUX_HDMI_NOTIFIER_H
> > +#define LINUX_HDMI_NOTIFIER_H
> > +
> > +#include <linux/types.h>
> > +#include <linux/notifier.h>
> > +#include <linux/kref.h>
> > +
> > +enum {
> > +     HDMI_CONNECTED,
> > +     HDMI_DISCONNECTED,
> > +     HDMI_NEW_EDID,
> > +     HDMI_NEW_ELD,
> > +};
> > +
> > +struct device;
> > +
> > +struct hdmi_notifier {
> > +     /* Lock to protect callback registration and notification. */
> > +     struct mutex lock;
> > +     struct list_head head;
> > +     struct kref kref;
> > +     struct blocking_notifier_head notifiers;
> > +     struct device *dev;
> > +
> > +     /* Current state */
> > +     unsigned int connected : 1;
> > +     unsigned int has_eld : 1;
> > +     unsigned char eld[128];
> > +     void *edid;
> > +     size_t edid_size;
> > +     size_t edid_allocated_size;
> > +};
> > +
> > +/**
> > + * hdmi_notifier_get - find or create a new hdmi_notifier for the given device.
> > + * @dev: device that sends the events.
> > + *
> > + * If a notifier for device @dev already exists, then increase the refcount
> > + * and return that notifier.
> > + *
> > + * If it doesn't exist, then allocate a new notifier struct and return a
> > + * pointer to that new struct.
> > + *
> > + * Return NULL if the memory could not be allocated.
> > + */
> > +struct hdmi_notifier *hdmi_notifier_get(struct device *dev);
> > +
> > +/**
> > + * hdmi_notifier_put - decrease refcount and delete when the refcount reaches 0.
> > + * @n: notifier
> > + */
> > +void hdmi_notifier_put(struct hdmi_notifier *n);
> > +
> > +/**
> > + * hdmi_notifier_register - register the notifier with the notifier_block.
> > + * @n: the HDMI notifier
> > + * @nb: the notifier_block
> > + */
> > +int hdmi_notifier_register(struct hdmi_notifier *n, struct notifier_block *nb);
> > +
> > +/**
> > + * hdmi_notifier_unregister - unregister the notifier with the notifier_block.
> > + * @n: the HDMI notifier
> > + * @nb: the notifier_block
> > + */
> > +int hdmi_notifier_unregister(struct hdmi_notifier *n,
> > +                          struct notifier_block *nb);
> > +
> > +/**
> > + * hdmi_event_connect - send a connect event.
> > + * @n: the HDMI notifier
> > + *
> > + * Send an HDMI_CONNECTED event to any registered parties.
> > + */
> > +void hdmi_event_connect(struct hdmi_notifier *n);
> > +
> > +/**
> > + * hdmi_event_disconnect - send a disconnect event.
> > + * @n: the HDMI notifier
> > + *
> > + * Send an HDMI_DISCONNECTED event to any registered parties.
> > + */
> > +void hdmi_event_disconnect(struct hdmi_notifier *n);
> > +
> > +/**
> > + * hdmi_event_new_edid - send a new EDID event.
> > + * @n: the HDMI notifier
> > + *
> > + * Send an HDMI_NEW_EDID event to any registered parties.
> > + * This function will make a copy the EDID so it can return -ENOMEM if
> > + * no memory could be allocated.
> > + */
> > +int hdmi_event_new_edid(struct hdmi_notifier *n, const void *edid, size_t size);
> > +
> > +/**
> > + * hdmi_event_new_eld - send a new ELD event.
> > + * @n: the HDMI notifier
> > + *
> > + * Send an HDMI_NEW_ELD event to any registered parties.
> > + */
> > +void hdmi_event_new_eld(struct hdmi_notifier *n, const u8 eld[128]);
> > +
> > +#endif
> >
>

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 1/7] video: add HDMI state notifier support
  2019-06-03  8:09     ` Daniel Vetter
  2019-06-03  9:05       ` Hans Verkuil
@ 2019-06-04  2:32       ` Cheng-yi Chiang
  2019-06-04  7:24         ` Daniel Vetter
  1 sibling, 1 reply; 30+ messages in thread
From: Cheng-yi Chiang @ 2019-06-04  2:32 UTC (permalink / raw)
  To: Hans Verkuil, Cheng-Yi Chiang, linux-kernel,
	Bartlomiej Zolnierkiewicz, Greg Kroah-Hartman, Philipp Zabel,
	Mark Brown, Liam Girdwood, Takashi Iwai, Jaroslav Kysela,
	Russell King, Andrzej Hajda, Laurent Pinchart, David Airlie,
	Rob Herring, Heiko Stuebner, Doug Anderson, Dylan Reid, tzungbi,
	linux-media,
	moderated list:SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEM...,
	dri-devel, linux-arm-kernel, linux-rockchip, devicetree,
	Dariusz Marcinkiewicz
  Cc: Daniel Vetter

On Mon, Jun 3, 2019 at 4:09 PM Daniel Vetter <daniel@ffwll.ch> wrote:
>
> On Mon, Jun 03, 2019 at 09:45:49AM +0200, Hans Verkuil wrote:
> > On 6/3/19 6:32 AM, Cheng-Yi Chiang wrote:
> > > From: Hans Verkuil <hans.verkuil@cisco.com>
> > >
> > > Add support for HDMI hotplug and EDID notifiers, which is used to convey
> > > information from HDMI drivers to their CEC and audio counterparts.
> > >
> > > Based on an earlier version from Russell King:
> > >
> > > https://patchwork.kernel.org/patch/9277043/
> > >
> > > The hdmi_notifier is a reference counted object containing the HDMI state
> > > of an HDMI device.
> > >
> > > When a new notifier is registered the current state will be reported to
> > > that notifier at registration time.
> > >
> > > Based on Hans Verkuil's patch:
> > >
> > > https://patchwork.kernel.org/patch/9472521/
> >
> > Erm, you are aware that this patch morphed into a CEC-specific notifier
> > found in drivers/media/cec/cec-notifier.c?
> >
> > I don't think it makes sense to have two notifier implementations in the kernel.
> > The original intention was to have the notifier deal with both CEC and ASoC
> > notifications, but there was not enough interest for the ASoC bits at the time
> > and it was dropped.
> >
> > I am planning changes to the cec-notifier API, I hope to work on that this
> > week. I'll CC you when I post those. Those might be a good starting point
> > to convert the cec-notifier to an hdmi-notifier as was originally intended.
> >
> > I've added your colleague Dariusz Marcinkiewicz to the CC list since he's been
> > working on some nice cec-notifier improvements as well.
>
> We also have some interfaces for drm/alsa interactions around hdmi
> already in drm/drm_audio_component.h, but it's not used by anything
> outside of i915. Imo we should extend that, not reinvent a new wheel.
>
Hi Daniel,
Thank you for the pointer. Looking at the ops, it seems that it is
specific to HDA.
I am not familiar with drm and HDA. I am not sure how applicable it
would be to report jack status to ASoC.
There is a use case in sound/soc/codecs/hdac_hdmi.c though so it
should be possible.

> Another note: notifiers considered evil, imo. Gets the job done for one
> case, as soon as you have multiple devices and need to make sure you get
> the update for the right one it all comes crashing down. Please create an
> api which registers for updates from a specific device only, plus
> something that has real callbacks (like the drm_audio_component.h thing we
> started already).

To clarify a bit, this hdmi-notifier indeed supports updating from a
specific device only.
hdmi_notifier_get takes a device and return the notifier.

It seems that a major difference between drm_audio_components and
hdmi-notifier is that
drm_audio_components defines all supported ops in drm_audio_component_audio_ops.
On the other hand, hdmi-notifier passes different events using an enum
like HDMI_CONNECTED and let listener handle different events.
In this regard I agree with you that drm_audio_component is cleaner.
Anyway, I will look into it a bit more and see how it works.

Thanks again!

> -Daniel
>
> >
> > Regards,
> >
> >       Hans
> >
> > >
> > > Modified by Cheng-Yi Chiang:
> > >  - Add a section in MAINTAINER.
> > >  - Changes connected and has_eld to bitfield of unsigned int.
> > >  - Other minor fixes to pass checkpatch.pl --strict checks.
> > >
> > > Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
> > > Acked-by: Philipp Zabel <p.zabel@pengutronix.de>
> > > Signed-off-by: Cheng-Yi Chiang <cychiang@chromium.org>
> > > ---
> > > The original patch is at
> > > https://lore.kernel.org/linux-arm-kernel/20161213150813.37966-2-hverkuil@xs4all.nl
> > >
> > >  MAINTAINERS                   |   6 ++
> > >  drivers/video/Kconfig         |   3 +
> > >  drivers/video/Makefile        |   1 +
> > >  drivers/video/hdmi-notifier.c | 145 ++++++++++++++++++++++++++++++++++
> > >  include/linux/hdmi-notifier.h | 112 ++++++++++++++++++++++++++
> > >  5 files changed, 267 insertions(+)
> > >  create mode 100644 drivers/video/hdmi-notifier.c
> > >  create mode 100644 include/linux/hdmi-notifier.h
> > >
> > > diff --git a/MAINTAINERS b/MAINTAINERS
> > > index 5cfbea4ce575..ffb7376f9509 100644
> > > --- a/MAINTAINERS
> > > +++ b/MAINTAINERS
> > > @@ -16676,6 +16676,12 @@ W: https://linuxtv.org
> > >  S: Maintained
> > >  F: drivers/media/platform/vicodec/*
> > >
> > > +VIDEO FRAMEWORK
> > > +M: Hans Verkuil <hverkuil@xs4all.nl>
> > > +L: linux-media@vger.kernel.org
> > > +F: drivers/video/hdmi-notifier.*
> > > +S: Maintained
> > > +
> > >  VIDEO MULTIPLEXER DRIVER
> > >  M: Philipp Zabel <p.zabel@pengutronix.de>
> > >  L: linux-media@vger.kernel.org
> > > diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
> > > index 83d3d271ca15..000ba9bc0ae7 100644
> > > --- a/drivers/video/Kconfig
> > > +++ b/drivers/video/Kconfig
> > > @@ -34,6 +34,9 @@ config VIDEOMODE_HELPERS
> > >  config HDMI
> > >     bool
> > >
> > > +config HDMI_NOTIFIERS
> > > +   bool
> > > +
> > >  endif # HAS_IOMEM
> > >
> > >  if VT
> > > diff --git a/drivers/video/Makefile b/drivers/video/Makefile
> > > index df7650adede9..eff4736102ca 100644
> > > --- a/drivers/video/Makefile
> > > +++ b/drivers/video/Makefile
> > > @@ -1,6 +1,7 @@
> > >  # SPDX-License-Identifier: GPL-2.0
> > >  obj-$(CONFIG_VGASTATE)            += vgastate.o
> > >  obj-$(CONFIG_HDMI)                += hdmi.o
> > > +obj-$(CONFIG_HDMI_NOTIFIERS)      += hdmi-notifier.o
> > >
> > >  obj-$(CONFIG_VT)             += console/
> > >  obj-$(CONFIG_FB_STI)                 += console/
> > > diff --git a/drivers/video/hdmi-notifier.c b/drivers/video/hdmi-notifier.c
> > > new file mode 100644
> > > index 000000000000..d1eedf661648
> > > --- /dev/null
> > > +++ b/drivers/video/hdmi-notifier.c
> > > @@ -0,0 +1,145 @@
> > > +// SPDX-License-Identifier: GPL-2.0
> > > +/* hdmi-notifier.c - notify interested parties of (dis)connect and EDID
> > > + * events
> > > + *
> > > + * Copyright 2016 Russell King <rmk+kernel@arm.linux.org.uk>
> > > + * Copyright 2016 Cisco Systems, Inc. and/or its affiliates.
> > > + * All rights reserved.
> > > + */
> > > +
> > > +#include <linux/export.h>
> > > +#include <linux/hdmi-notifier.h>
> > > +#include <linux/string.h>
> > > +#include <linux/slab.h>
> > > +#include <linux/list.h>
> > > +
> > > +static LIST_HEAD(hdmi_notifiers);
> > > +static DEFINE_MUTEX(hdmi_notifiers_lock);
> > > +
> > > +struct hdmi_notifier *hdmi_notifier_get(struct device *dev)
> > > +{
> > > +   struct hdmi_notifier *n;
> > > +
> > > +   mutex_lock(&hdmi_notifiers_lock);
> > > +   list_for_each_entry(n, &hdmi_notifiers, head) {
> > > +           if (n->dev == dev) {
> > > +                   mutex_unlock(&hdmi_notifiers_lock);
> > > +                   kref_get(&n->kref);
> > > +                   return n;
> > > +           }
> > > +   }
> > > +   n = kzalloc(sizeof(*n), GFP_KERNEL);
> > > +   if (!n)
> > > +           goto unlock;
> > > +   n->dev = dev;
> > > +   mutex_init(&n->lock);
> > > +   BLOCKING_INIT_NOTIFIER_HEAD(&n->notifiers);
> > > +   kref_init(&n->kref);
> > > +   list_add_tail(&n->head, &hdmi_notifiers);
> > > +unlock:
> > > +   mutex_unlock(&hdmi_notifiers_lock);
> > > +   return n;
> > > +}
> > > +EXPORT_SYMBOL_GPL(hdmi_notifier_get);
> > > +
> > > +static void hdmi_notifier_release(struct kref *kref)
> > > +{
> > > +   struct hdmi_notifier *n =
> > > +           container_of(kref, struct hdmi_notifier, kref);
> > > +
> > > +   mutex_lock(&hdmi_notifiers_lock);
> > > +   list_del(&n->head);
> > > +   mutex_unlock(&hdmi_notifiers_lock);
> > > +   kfree(n->edid);
> > > +   kfree(n);
> > > +}
> > > +
> > > +void hdmi_notifier_put(struct hdmi_notifier *n)
> > > +{
> > > +   kref_put(&n->kref, hdmi_notifier_release);
> > > +}
> > > +EXPORT_SYMBOL_GPL(hdmi_notifier_put);
> > > +
> > > +int hdmi_notifier_register(struct hdmi_notifier *n, struct notifier_block *nb)
> > > +{
> > > +   int ret = blocking_notifier_chain_register(&n->notifiers, nb);
> > > +
> > > +   if (ret)
> > > +           return ret;
> > > +   kref_get(&n->kref);
> > > +   mutex_lock(&n->lock);
> > > +   if (n->connected) {
> > > +           blocking_notifier_call_chain(&n->notifiers, HDMI_CONNECTED, n);
> > > +           if (n->edid_size)
> > > +                   blocking_notifier_call_chain(&n->notifiers,
> > > +                                                HDMI_NEW_EDID, n);
> > > +           if (n->has_eld)
> > > +                   blocking_notifier_call_chain(&n->notifiers,
> > > +                                                HDMI_NEW_ELD, n);
> > > +   }
> > > +   mutex_unlock(&n->lock);
> > > +   return 0;
> > > +}
> > > +EXPORT_SYMBOL_GPL(hdmi_notifier_register);
> > > +
> > > +int hdmi_notifier_unregister(struct hdmi_notifier *n, struct notifier_block *nb)
> > > +{
> > > +   int ret = blocking_notifier_chain_unregister(&n->notifiers, nb);
> > > +
> > > +   if (ret == 0)
> > > +           hdmi_notifier_put(n);
> > > +   return ret;
> > > +}
> > > +EXPORT_SYMBOL_GPL(hdmi_notifier_unregister);
> > > +
> > > +void hdmi_event_connect(struct hdmi_notifier *n)
> > > +{
> > > +   mutex_lock(&n->lock);
> > > +   n->connected = true;
> > > +   blocking_notifier_call_chain(&n->notifiers, HDMI_CONNECTED, n);
> > > +   mutex_unlock(&n->lock);
> > > +}
> > > +EXPORT_SYMBOL_GPL(hdmi_event_connect);
> > > +
> > > +void hdmi_event_disconnect(struct hdmi_notifier *n)
> > > +{
> > > +   mutex_lock(&n->lock);
> > > +   n->connected = false;
> > > +   n->has_eld = false;
> > > +   n->edid_size = 0;
> > > +   blocking_notifier_call_chain(&n->notifiers, HDMI_DISCONNECTED, n);
> > > +   mutex_unlock(&n->lock);
> > > +}
> > > +EXPORT_SYMBOL_GPL(hdmi_event_disconnect);
> > > +
> > > +int hdmi_event_new_edid(struct hdmi_notifier *n, const void *edid, size_t size)
> > > +{
> > > +   mutex_lock(&n->lock);
> > > +   if (n->edid_allocated_size < size) {
> > > +           void *p = kmalloc(size, GFP_KERNEL);
> > > +
> > > +           if (!p) {
> > > +                   mutex_unlock(&n->lock);
> > > +                   return -ENOMEM;
> > > +           }
> > > +           kfree(n->edid);
> > > +           n->edid = p;
> > > +           n->edid_allocated_size = size;
> > > +   }
> > > +   memcpy(n->edid, edid, size);
> > > +   n->edid_size = size;
> > > +   blocking_notifier_call_chain(&n->notifiers, HDMI_NEW_EDID, n);
> > > +   mutex_unlock(&n->lock);
> > > +   return 0;
> > > +}
> > > +EXPORT_SYMBOL_GPL(hdmi_event_new_edid);
> > > +
> > > +void hdmi_event_new_eld(struct hdmi_notifier *n, const u8 eld[128])
> > > +{
> > > +   mutex_lock(&n->lock);
> > > +   memcpy(n->eld, eld, sizeof(n->eld));
> > > +   n->has_eld = true;
> > > +   blocking_notifier_call_chain(&n->notifiers, HDMI_NEW_ELD, n);
> > > +   mutex_unlock(&n->lock);
> > > +}
> > > +EXPORT_SYMBOL_GPL(hdmi_event_new_eld);
> > > diff --git a/include/linux/hdmi-notifier.h b/include/linux/hdmi-notifier.h
> > > new file mode 100644
> > > index 000000000000..c8f35110e3e3
> > > --- /dev/null
> > > +++ b/include/linux/hdmi-notifier.h
> > > @@ -0,0 +1,112 @@
> > > +/* SPDX-License-Identifier: GPL-2.0
> > > + * hdmi-notifier.h - notify interested parties of (dis)connect and EDID
> > > + * events
> > > + *
> > > + * Copyright 2016 Russell King <rmk+kernel@arm.linux.org.uk>
> > > + * Copyright 2016 Cisco Systems, Inc. and/or its affiliates.
> > > + * All rights reserved.
> > > + */
> > > +
> > > +#ifndef LINUX_HDMI_NOTIFIER_H
> > > +#define LINUX_HDMI_NOTIFIER_H
> > > +
> > > +#include <linux/types.h>
> > > +#include <linux/notifier.h>
> > > +#include <linux/kref.h>
> > > +
> > > +enum {
> > > +   HDMI_CONNECTED,
> > > +   HDMI_DISCONNECTED,
> > > +   HDMI_NEW_EDID,
> > > +   HDMI_NEW_ELD,
> > > +};
> > > +
> > > +struct device;
> > > +
> > > +struct hdmi_notifier {
> > > +   /* Lock to protect callback registration and notification. */
> > > +   struct mutex lock;
> > > +   struct list_head head;
> > > +   struct kref kref;
> > > +   struct blocking_notifier_head notifiers;
> > > +   struct device *dev;
> > > +
> > > +   /* Current state */
> > > +   unsigned int connected : 1;
> > > +   unsigned int has_eld : 1;
> > > +   unsigned char eld[128];
> > > +   void *edid;
> > > +   size_t edid_size;
> > > +   size_t edid_allocated_size;
> > > +};
> > > +
> > > +/**
> > > + * hdmi_notifier_get - find or create a new hdmi_notifier for the given device.
> > > + * @dev: device that sends the events.
> > > + *
> > > + * If a notifier for device @dev already exists, then increase the refcount
> > > + * and return that notifier.
> > > + *
> > > + * If it doesn't exist, then allocate a new notifier struct and return a
> > > + * pointer to that new struct.
> > > + *
> > > + * Return NULL if the memory could not be allocated.
> > > + */
> > > +struct hdmi_notifier *hdmi_notifier_get(struct device *dev);
> > > +
> > > +/**
> > > + * hdmi_notifier_put - decrease refcount and delete when the refcount reaches 0.
> > > + * @n: notifier
> > > + */
> > > +void hdmi_notifier_put(struct hdmi_notifier *n);
> > > +
> > > +/**
> > > + * hdmi_notifier_register - register the notifier with the notifier_block.
> > > + * @n: the HDMI notifier
> > > + * @nb: the notifier_block
> > > + */
> > > +int hdmi_notifier_register(struct hdmi_notifier *n, struct notifier_block *nb);
> > > +
> > > +/**
> > > + * hdmi_notifier_unregister - unregister the notifier with the notifier_block.
> > > + * @n: the HDMI notifier
> > > + * @nb: the notifier_block
> > > + */
> > > +int hdmi_notifier_unregister(struct hdmi_notifier *n,
> > > +                        struct notifier_block *nb);
> > > +
> > > +/**
> > > + * hdmi_event_connect - send a connect event.
> > > + * @n: the HDMI notifier
> > > + *
> > > + * Send an HDMI_CONNECTED event to any registered parties.
> > > + */
> > > +void hdmi_event_connect(struct hdmi_notifier *n);
> > > +
> > > +/**
> > > + * hdmi_event_disconnect - send a disconnect event.
> > > + * @n: the HDMI notifier
> > > + *
> > > + * Send an HDMI_DISCONNECTED event to any registered parties.
> > > + */
> > > +void hdmi_event_disconnect(struct hdmi_notifier *n);
> > > +
> > > +/**
> > > + * hdmi_event_new_edid - send a new EDID event.
> > > + * @n: the HDMI notifier
> > > + *
> > > + * Send an HDMI_NEW_EDID event to any registered parties.
> > > + * This function will make a copy the EDID so it can return -ENOMEM if
> > > + * no memory could be allocated.
> > > + */
> > > +int hdmi_event_new_edid(struct hdmi_notifier *n, const void *edid, size_t size);
> > > +
> > > +/**
> > > + * hdmi_event_new_eld - send a new ELD event.
> > > + * @n: the HDMI notifier
> > > + *
> > > + * Send an HDMI_NEW_ELD event to any registered parties.
> > > + */
> > > +void hdmi_event_new_eld(struct hdmi_notifier *n, const u8 eld[128]);
> > > +
> > > +#endif
> > >
> >
>
> --
> Daniel Vetter
> Software Engineer, Intel Corporation
> http://blog.ffwll.ch

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 1/7] video: add HDMI state notifier support
  2019-06-03  9:05       ` Hans Verkuil
@ 2019-06-04  7:19         ` Daniel Vetter
  0 siblings, 0 replies; 30+ messages in thread
From: Daniel Vetter @ 2019-06-04  7:19 UTC (permalink / raw)
  To: Hans Verkuil
  Cc: alsa-devel, Heiko Stuebner, Liam Girdwood, David Airlie,
	dri-devel, Takashi Iwai, Andrzej Hajda, Laurent Pinchart,
	Cheng-Yi Chiang, linux-rockchip, dgreid, linux-media, devicetree,
	tzungbi, Bartlomiej Zolnierkiewicz, Russell King, Rob Herring,
	Jaroslav Kysela, linux-arm-kernel, Greg Kroah-Hartman, dianders,
	linux-kernel, Mark Brown, Philipp Zabel, Dariusz Marcinkiewicz

On Mon, Jun 03, 2019 at 11:05:19AM +0200, Hans Verkuil wrote:
> On 6/3/19 10:09 AM, Daniel Vetter wrote:
> > On Mon, Jun 03, 2019 at 09:45:49AM +0200, Hans Verkuil wrote:
> >> On 6/3/19 6:32 AM, Cheng-Yi Chiang wrote:
> >>> From: Hans Verkuil <hans.verkuil@cisco.com>
> >>>
> >>> Add support for HDMI hotplug and EDID notifiers, which is used to convey
> >>> information from HDMI drivers to their CEC and audio counterparts.
> >>>
> >>> Based on an earlier version from Russell King:
> >>>
> >>> https://patchwork.kernel.org/patch/9277043/
> >>>
> >>> The hdmi_notifier is a reference counted object containing the HDMI state
> >>> of an HDMI device.
> >>>
> >>> When a new notifier is registered the current state will be reported to
> >>> that notifier at registration time.
> >>>
> >>> Based on Hans Verkuil's patch:
> >>>
> >>> https://patchwork.kernel.org/patch/9472521/
> >>
> >> Erm, you are aware that this patch morphed into a CEC-specific notifier
> >> found in drivers/media/cec/cec-notifier.c?
> >>
> >> I don't think it makes sense to have two notifier implementations in the kernel.
> >> The original intention was to have the notifier deal with both CEC and ASoC
> >> notifications, but there was not enough interest for the ASoC bits at the time
> >> and it was dropped.
> >>
> >> I am planning changes to the cec-notifier API, I hope to work on that this
> >> week. I'll CC you when I post those. Those might be a good starting point
> >> to convert the cec-notifier to an hdmi-notifier as was originally intended.
> >>
> >> I've added your colleague Dariusz Marcinkiewicz to the CC list since he's been
> >> working on some nice cec-notifier improvements as well.
> > 
> > We also have some interfaces for drm/alsa interactions around hdmi
> > already in drm/drm_audio_component.h, but it's not used by anything
> > outside of i915. Imo we should extend that, not reinvent a new wheel.
> 
> If that can be used instead of this hdmi-notifier, then that's fine by me.
> 
> > Another note: notifiers considered evil, imo. Gets the job done for one
> > case, as soon as you have multiple devices and need to make sure you get
> > the update for the right one it all comes crashing down. Please create an
> > api which registers for updates from a specific device only, plus
> > something that has real callbacks (like the drm_audio_component.h thing we
> > started already).
> 
> For CEC the notifier works very well. But CEC has some special requirements
> that ASoC doesn't have:
> 
> - The cec-notifier can be used by both HDMI transmitters and receivers (so
> has to work with two different subsystems).

From a (very quick) look the cec-notifier.c isn't a pure notifier, but
seems to have some things to get the right endpoint. Also minimal type
safety in callbacks, not just void * everywhere.

> - There may be multiple CEC devices connected to one HDMI transmitter: one
> that is used when the system is in Standby, and a more capable CEC device
> used when the system is powered up. This isn't supported yet, but it is likely
> that we'll need this.
> 
> - HDMI and CEC devices are often completely independent and one or the other
> (or both) can be unbound at any time. A real-world example is when an FPGA
> containing the HDMI and/or CEC support is unloaded to save power when in standby.
> 
> - In some cases you want to register a CEC device via a notifier to an HDMI
> connector based on userspace information. E.g. the popular USB Pulse-Eight CEC
> device can be connected to any HDMI output by the user, there is no way to know
> this in the kernel. An application that knows about the Pulse-Eight currently
> has to parse the EDID and set the Physical Address of the Pulse-Eight accordingly.
> I want to make it possible that the user can just tell the Pulse-Eight which HDMI
> output is used and have it connect to that output using the notifier. I have a
> proof-of-concept, but this needs Dariusz' series to make it work.

I'm not against having glue which can tie together largely unrelated
subsystems and drivers. The things that imo are bad design patterns with
standard modifiers:

- Locking gets in the way sooner or later. Can be fixed with an unlocked
  modifier and your own locking, but at that point just roll your own
  thing like cec-notifier.c.

- void * types everywhere, usually far from a good fit.

- shotgun approach of notifications, everyone gets everything all the
  time. Good notification should send a specific event (using a specific
  callback which has the right parameters as arguments), to a specific
  recipient.

This all doesn't matter for a poc with just one sender and one receiver,
but it becomes a huge pain once you have lots of drivers participating and
lots of devices/connections involved. Really bad example is the fbdev
notifier, which is abused for all kinds of horrible hacks by now, because
the interface doesn't have a solid api contract between sender and
receiver of notification events.

Hope that explains why I'm against standard modifiers, and why I think
cec-notifier.c looks good (without me understanding the details, just from
a quick look).

Cheers, Daniel

> 
> Regards,
> 
> 	Hans
> 
> > -Daniel
> > 
> >>
> >> Regards,
> >>
> >> 	Hans
> >>
> >>>
> >>> Modified by Cheng-Yi Chiang:
> >>>  - Add a section in MAINTAINER.
> >>>  - Changes connected and has_eld to bitfield of unsigned int.
> >>>  - Other minor fixes to pass checkpatch.pl --strict checks.
> >>>
> >>> Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
> >>> Acked-by: Philipp Zabel <p.zabel@pengutronix.de>
> >>> Signed-off-by: Cheng-Yi Chiang <cychiang@chromium.org>
> >>> ---
> >>> The original patch is at
> >>> https://lore.kernel.org/linux-arm-kernel/20161213150813.37966-2-hverkuil@xs4all.nl
> >>>
> >>>  MAINTAINERS                   |   6 ++
> >>>  drivers/video/Kconfig         |   3 +
> >>>  drivers/video/Makefile        |   1 +
> >>>  drivers/video/hdmi-notifier.c | 145 ++++++++++++++++++++++++++++++++++
> >>>  include/linux/hdmi-notifier.h | 112 ++++++++++++++++++++++++++
> >>>  5 files changed, 267 insertions(+)
> >>>  create mode 100644 drivers/video/hdmi-notifier.c
> >>>  create mode 100644 include/linux/hdmi-notifier.h
> >>>
> >>> diff --git a/MAINTAINERS b/MAINTAINERS
> >>> index 5cfbea4ce575..ffb7376f9509 100644
> >>> --- a/MAINTAINERS
> >>> +++ b/MAINTAINERS
> >>> @@ -16676,6 +16676,12 @@ W:	https://linuxtv.org
> >>>  S:	Maintained
> >>>  F:	drivers/media/platform/vicodec/*
> >>>  
> >>> +VIDEO FRAMEWORK
> >>> +M:	Hans Verkuil <hverkuil@xs4all.nl>
> >>> +L:	linux-media@vger.kernel.org
> >>> +F:	drivers/video/hdmi-notifier.*
> >>> +S:	Maintained
> >>> +
> >>>  VIDEO MULTIPLEXER DRIVER
> >>>  M:	Philipp Zabel <p.zabel@pengutronix.de>
> >>>  L:	linux-media@vger.kernel.org
> >>> diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
> >>> index 83d3d271ca15..000ba9bc0ae7 100644
> >>> --- a/drivers/video/Kconfig
> >>> +++ b/drivers/video/Kconfig
> >>> @@ -34,6 +34,9 @@ config VIDEOMODE_HELPERS
> >>>  config HDMI
> >>>  	bool
> >>>  
> >>> +config HDMI_NOTIFIERS
> >>> +	bool
> >>> +
> >>>  endif # HAS_IOMEM
> >>>  
> >>>  if VT
> >>> diff --git a/drivers/video/Makefile b/drivers/video/Makefile
> >>> index df7650adede9..eff4736102ca 100644
> >>> --- a/drivers/video/Makefile
> >>> +++ b/drivers/video/Makefile
> >>> @@ -1,6 +1,7 @@
> >>>  # SPDX-License-Identifier: GPL-2.0
> >>>  obj-$(CONFIG_VGASTATE)            += vgastate.o
> >>>  obj-$(CONFIG_HDMI)                += hdmi.o
> >>> +obj-$(CONFIG_HDMI_NOTIFIERS)      += hdmi-notifier.o
> >>>  
> >>>  obj-$(CONFIG_VT)		  += console/
> >>>  obj-$(CONFIG_FB_STI)		  += console/
> >>> diff --git a/drivers/video/hdmi-notifier.c b/drivers/video/hdmi-notifier.c
> >>> new file mode 100644
> >>> index 000000000000..d1eedf661648
> >>> --- /dev/null
> >>> +++ b/drivers/video/hdmi-notifier.c
> >>> @@ -0,0 +1,145 @@
> >>> +// SPDX-License-Identifier: GPL-2.0
> >>> +/* hdmi-notifier.c - notify interested parties of (dis)connect and EDID
> >>> + * events
> >>> + *
> >>> + * Copyright 2016 Russell King <rmk+kernel@arm.linux.org.uk>
> >>> + * Copyright 2016 Cisco Systems, Inc. and/or its affiliates.
> >>> + * All rights reserved.
> >>> + */
> >>> +
> >>> +#include <linux/export.h>
> >>> +#include <linux/hdmi-notifier.h>
> >>> +#include <linux/string.h>
> >>> +#include <linux/slab.h>
> >>> +#include <linux/list.h>
> >>> +
> >>> +static LIST_HEAD(hdmi_notifiers);
> >>> +static DEFINE_MUTEX(hdmi_notifiers_lock);
> >>> +
> >>> +struct hdmi_notifier *hdmi_notifier_get(struct device *dev)
> >>> +{
> >>> +	struct hdmi_notifier *n;
> >>> +
> >>> +	mutex_lock(&hdmi_notifiers_lock);
> >>> +	list_for_each_entry(n, &hdmi_notifiers, head) {
> >>> +		if (n->dev == dev) {
> >>> +			mutex_unlock(&hdmi_notifiers_lock);
> >>> +			kref_get(&n->kref);
> >>> +			return n;
> >>> +		}
> >>> +	}
> >>> +	n = kzalloc(sizeof(*n), GFP_KERNEL);
> >>> +	if (!n)
> >>> +		goto unlock;
> >>> +	n->dev = dev;
> >>> +	mutex_init(&n->lock);
> >>> +	BLOCKING_INIT_NOTIFIER_HEAD(&n->notifiers);
> >>> +	kref_init(&n->kref);
> >>> +	list_add_tail(&n->head, &hdmi_notifiers);
> >>> +unlock:
> >>> +	mutex_unlock(&hdmi_notifiers_lock);
> >>> +	return n;
> >>> +}
> >>> +EXPORT_SYMBOL_GPL(hdmi_notifier_get);
> >>> +
> >>> +static void hdmi_notifier_release(struct kref *kref)
> >>> +{
> >>> +	struct hdmi_notifier *n =
> >>> +		container_of(kref, struct hdmi_notifier, kref);
> >>> +
> >>> +	mutex_lock(&hdmi_notifiers_lock);
> >>> +	list_del(&n->head);
> >>> +	mutex_unlock(&hdmi_notifiers_lock);
> >>> +	kfree(n->edid);
> >>> +	kfree(n);
> >>> +}
> >>> +
> >>> +void hdmi_notifier_put(struct hdmi_notifier *n)
> >>> +{
> >>> +	kref_put(&n->kref, hdmi_notifier_release);
> >>> +}
> >>> +EXPORT_SYMBOL_GPL(hdmi_notifier_put);
> >>> +
> >>> +int hdmi_notifier_register(struct hdmi_notifier *n, struct notifier_block *nb)
> >>> +{
> >>> +	int ret = blocking_notifier_chain_register(&n->notifiers, nb);
> >>> +
> >>> +	if (ret)
> >>> +		return ret;
> >>> +	kref_get(&n->kref);
> >>> +	mutex_lock(&n->lock);
> >>> +	if (n->connected) {
> >>> +		blocking_notifier_call_chain(&n->notifiers, HDMI_CONNECTED, n);
> >>> +		if (n->edid_size)
> >>> +			blocking_notifier_call_chain(&n->notifiers,
> >>> +						     HDMI_NEW_EDID, n);
> >>> +		if (n->has_eld)
> >>> +			blocking_notifier_call_chain(&n->notifiers,
> >>> +						     HDMI_NEW_ELD, n);
> >>> +	}
> >>> +	mutex_unlock(&n->lock);
> >>> +	return 0;
> >>> +}
> >>> +EXPORT_SYMBOL_GPL(hdmi_notifier_register);
> >>> +
> >>> +int hdmi_notifier_unregister(struct hdmi_notifier *n, struct notifier_block *nb)
> >>> +{
> >>> +	int ret = blocking_notifier_chain_unregister(&n->notifiers, nb);
> >>> +
> >>> +	if (ret == 0)
> >>> +		hdmi_notifier_put(n);
> >>> +	return ret;
> >>> +}
> >>> +EXPORT_SYMBOL_GPL(hdmi_notifier_unregister);
> >>> +
> >>> +void hdmi_event_connect(struct hdmi_notifier *n)
> >>> +{
> >>> +	mutex_lock(&n->lock);
> >>> +	n->connected = true;
> >>> +	blocking_notifier_call_chain(&n->notifiers, HDMI_CONNECTED, n);
> >>> +	mutex_unlock(&n->lock);
> >>> +}
> >>> +EXPORT_SYMBOL_GPL(hdmi_event_connect);
> >>> +
> >>> +void hdmi_event_disconnect(struct hdmi_notifier *n)
> >>> +{
> >>> +	mutex_lock(&n->lock);
> >>> +	n->connected = false;
> >>> +	n->has_eld = false;
> >>> +	n->edid_size = 0;
> >>> +	blocking_notifier_call_chain(&n->notifiers, HDMI_DISCONNECTED, n);
> >>> +	mutex_unlock(&n->lock);
> >>> +}
> >>> +EXPORT_SYMBOL_GPL(hdmi_event_disconnect);
> >>> +
> >>> +int hdmi_event_new_edid(struct hdmi_notifier *n, const void *edid, size_t size)
> >>> +{
> >>> +	mutex_lock(&n->lock);
> >>> +	if (n->edid_allocated_size < size) {
> >>> +		void *p = kmalloc(size, GFP_KERNEL);
> >>> +
> >>> +		if (!p) {
> >>> +			mutex_unlock(&n->lock);
> >>> +			return -ENOMEM;
> >>> +		}
> >>> +		kfree(n->edid);
> >>> +		n->edid = p;
> >>> +		n->edid_allocated_size = size;
> >>> +	}
> >>> +	memcpy(n->edid, edid, size);
> >>> +	n->edid_size = size;
> >>> +	blocking_notifier_call_chain(&n->notifiers, HDMI_NEW_EDID, n);
> >>> +	mutex_unlock(&n->lock);
> >>> +	return 0;
> >>> +}
> >>> +EXPORT_SYMBOL_GPL(hdmi_event_new_edid);
> >>> +
> >>> +void hdmi_event_new_eld(struct hdmi_notifier *n, const u8 eld[128])
> >>> +{
> >>> +	mutex_lock(&n->lock);
> >>> +	memcpy(n->eld, eld, sizeof(n->eld));
> >>> +	n->has_eld = true;
> >>> +	blocking_notifier_call_chain(&n->notifiers, HDMI_NEW_ELD, n);
> >>> +	mutex_unlock(&n->lock);
> >>> +}
> >>> +EXPORT_SYMBOL_GPL(hdmi_event_new_eld);
> >>> diff --git a/include/linux/hdmi-notifier.h b/include/linux/hdmi-notifier.h
> >>> new file mode 100644
> >>> index 000000000000..c8f35110e3e3
> >>> --- /dev/null
> >>> +++ b/include/linux/hdmi-notifier.h
> >>> @@ -0,0 +1,112 @@
> >>> +/* SPDX-License-Identifier: GPL-2.0
> >>> + * hdmi-notifier.h - notify interested parties of (dis)connect and EDID
> >>> + * events
> >>> + *
> >>> + * Copyright 2016 Russell King <rmk+kernel@arm.linux.org.uk>
> >>> + * Copyright 2016 Cisco Systems, Inc. and/or its affiliates.
> >>> + * All rights reserved.
> >>> + */
> >>> +
> >>> +#ifndef LINUX_HDMI_NOTIFIER_H
> >>> +#define LINUX_HDMI_NOTIFIER_H
> >>> +
> >>> +#include <linux/types.h>
> >>> +#include <linux/notifier.h>
> >>> +#include <linux/kref.h>
> >>> +
> >>> +enum {
> >>> +	HDMI_CONNECTED,
> >>> +	HDMI_DISCONNECTED,
> >>> +	HDMI_NEW_EDID,
> >>> +	HDMI_NEW_ELD,
> >>> +};
> >>> +
> >>> +struct device;
> >>> +
> >>> +struct hdmi_notifier {
> >>> +	/* Lock to protect callback registration and notification. */
> >>> +	struct mutex lock;
> >>> +	struct list_head head;
> >>> +	struct kref kref;
> >>> +	struct blocking_notifier_head notifiers;
> >>> +	struct device *dev;
> >>> +
> >>> +	/* Current state */
> >>> +	unsigned int connected : 1;
> >>> +	unsigned int has_eld : 1;
> >>> +	unsigned char eld[128];
> >>> +	void *edid;
> >>> +	size_t edid_size;
> >>> +	size_t edid_allocated_size;
> >>> +};
> >>> +
> >>> +/**
> >>> + * hdmi_notifier_get - find or create a new hdmi_notifier for the given device.
> >>> + * @dev: device that sends the events.
> >>> + *
> >>> + * If a notifier for device @dev already exists, then increase the refcount
> >>> + * and return that notifier.
> >>> + *
> >>> + * If it doesn't exist, then allocate a new notifier struct and return a
> >>> + * pointer to that new struct.
> >>> + *
> >>> + * Return NULL if the memory could not be allocated.
> >>> + */
> >>> +struct hdmi_notifier *hdmi_notifier_get(struct device *dev);
> >>> +
> >>> +/**
> >>> + * hdmi_notifier_put - decrease refcount and delete when the refcount reaches 0.
> >>> + * @n: notifier
> >>> + */
> >>> +void hdmi_notifier_put(struct hdmi_notifier *n);
> >>> +
> >>> +/**
> >>> + * hdmi_notifier_register - register the notifier with the notifier_block.
> >>> + * @n: the HDMI notifier
> >>> + * @nb: the notifier_block
> >>> + */
> >>> +int hdmi_notifier_register(struct hdmi_notifier *n, struct notifier_block *nb);
> >>> +
> >>> +/**
> >>> + * hdmi_notifier_unregister - unregister the notifier with the notifier_block.
> >>> + * @n: the HDMI notifier
> >>> + * @nb: the notifier_block
> >>> + */
> >>> +int hdmi_notifier_unregister(struct hdmi_notifier *n,
> >>> +			     struct notifier_block *nb);
> >>> +
> >>> +/**
> >>> + * hdmi_event_connect - send a connect event.
> >>> + * @n: the HDMI notifier
> >>> + *
> >>> + * Send an HDMI_CONNECTED event to any registered parties.
> >>> + */
> >>> +void hdmi_event_connect(struct hdmi_notifier *n);
> >>> +
> >>> +/**
> >>> + * hdmi_event_disconnect - send a disconnect event.
> >>> + * @n: the HDMI notifier
> >>> + *
> >>> + * Send an HDMI_DISCONNECTED event to any registered parties.
> >>> + */
> >>> +void hdmi_event_disconnect(struct hdmi_notifier *n);
> >>> +
> >>> +/**
> >>> + * hdmi_event_new_edid - send a new EDID event.
> >>> + * @n: the HDMI notifier
> >>> + *
> >>> + * Send an HDMI_NEW_EDID event to any registered parties.
> >>> + * This function will make a copy the EDID so it can return -ENOMEM if
> >>> + * no memory could be allocated.
> >>> + */
> >>> +int hdmi_event_new_edid(struct hdmi_notifier *n, const void *edid, size_t size);
> >>> +
> >>> +/**
> >>> + * hdmi_event_new_eld - send a new ELD event.
> >>> + * @n: the HDMI notifier
> >>> + *
> >>> + * Send an HDMI_NEW_ELD event to any registered parties.
> >>> + */
> >>> +void hdmi_event_new_eld(struct hdmi_notifier *n, const u8 eld[128]);
> >>> +
> >>> +#endif
> >>>
> >>
> > 
> 
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 1/7] video: add HDMI state notifier support
  2019-06-04  2:32       ` Cheng-yi Chiang
@ 2019-06-04  7:24         ` Daniel Vetter
  2019-06-11 12:10           ` Cheng-yi Chiang
  0 siblings, 1 reply; 30+ messages in thread
From: Daniel Vetter @ 2019-06-04  7:24 UTC (permalink / raw)
  To: Cheng-yi Chiang
  Cc: moderated list:SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEM...,
	Heiko Stuebner, Liam Girdwood, David Airlie, dri-devel,
	Takashi Iwai, Hans Verkuil, Andrzej Hajda, Laurent Pinchart,
	linux-rockchip, Dylan Reid, linux-media, devicetree, tzungbi,
	Daniel Vetter, Bartlomiej Zolnierkiewicz, Russell King,
	Rob Herring, Jaroslav Kysela, linux-arm-kernel,
	Greg Kroah-Hartman, Doug Anderson, linux-kernel, Mark Brown,
	Philipp Zabel, Dariusz Marcinkiewicz

On Tue, Jun 04, 2019 at 10:32:50AM +0800, Cheng-yi Chiang wrote:
> On Mon, Jun 3, 2019 at 4:09 PM Daniel Vetter <daniel@ffwll.ch> wrote:
> >
> > On Mon, Jun 03, 2019 at 09:45:49AM +0200, Hans Verkuil wrote:
> > > On 6/3/19 6:32 AM, Cheng-Yi Chiang wrote:
> > > > From: Hans Verkuil <hans.verkuil@cisco.com>
> > > >
> > > > Add support for HDMI hotplug and EDID notifiers, which is used to convey
> > > > information from HDMI drivers to their CEC and audio counterparts.
> > > >
> > > > Based on an earlier version from Russell King:
> > > >
> > > > https://patchwork.kernel.org/patch/9277043/
> > > >
> > > > The hdmi_notifier is a reference counted object containing the HDMI state
> > > > of an HDMI device.
> > > >
> > > > When a new notifier is registered the current state will be reported to
> > > > that notifier at registration time.
> > > >
> > > > Based on Hans Verkuil's patch:
> > > >
> > > > https://patchwork.kernel.org/patch/9472521/
> > >
> > > Erm, you are aware that this patch morphed into a CEC-specific notifier
> > > found in drivers/media/cec/cec-notifier.c?
> > >
> > > I don't think it makes sense to have two notifier implementations in the kernel.
> > > The original intention was to have the notifier deal with both CEC and ASoC
> > > notifications, but there was not enough interest for the ASoC bits at the time
> > > and it was dropped.
> > >
> > > I am planning changes to the cec-notifier API, I hope to work on that this
> > > week. I'll CC you when I post those. Those might be a good starting point
> > > to convert the cec-notifier to an hdmi-notifier as was originally intended.
> > >
> > > I've added your colleague Dariusz Marcinkiewicz to the CC list since he's been
> > > working on some nice cec-notifier improvements as well.
> >
> > We also have some interfaces for drm/alsa interactions around hdmi
> > already in drm/drm_audio_component.h, but it's not used by anything
> > outside of i915. Imo we should extend that, not reinvent a new wheel.
> >
> Hi Daniel,
> Thank you for the pointer. Looking at the ops, it seems that it is
> specific to HDA.
> I am not familiar with drm and HDA. I am not sure how applicable it
> would be to report jack status to ASoC.
> There is a use case in sound/soc/codecs/hdac_hdmi.c though so it
> should be possible.

Currently hda is the only user, but the idea was to make it more generic.
Jack status in alsa is what drm calls connector status btw.

So if we can take that as a baseline and extend it (probably needs some
registration boilerplate and helpers to look up the right endpoint using
of/dt for soc systems, we use component.c in i915/hda for this), that
would be great I think.

> > Another note: notifiers considered evil, imo. Gets the job done for one
> > case, as soon as you have multiple devices and need to make sure you get
> > the update for the right one it all comes crashing down. Please create an
> > api which registers for updates from a specific device only, plus
> > something that has real callbacks (like the drm_audio_component.h thing we
> > started already).
> 
> To clarify a bit, this hdmi-notifier indeed supports updating from a
> specific device only.
> hdmi_notifier_get takes a device and return the notifier.

Hm I missed that, I thought it's global, so one of my usual notifier
concerns addressed.

> It seems that a major difference between drm_audio_components and
> hdmi-notifier is that
> drm_audio_components defines all supported ops in drm_audio_component_audio_ops.
> On the other hand, hdmi-notifier passes different events using an enum
> like HDMI_CONNECTED and let listener handle different events.
> In this regard I agree with you that drm_audio_component is cleaner.
> Anyway, I will look into it a bit more and see how it works.

Yeah I think if we could combine the approach, i.e. notifier side for
registration, some _ops structure for the actual notifications, then
there's a solid interface. I just really don't like the opaque void *
interface notifier provides, it encourages abuse way too much.

Ofc the registration side would then no longer be based on the notifier
datastructure, list_head (like cec-notifier.c) of registeres devices with
their _ops structure should be enough.
-Daniel

> 
> Thanks again!
> 
> > -Daniel
> >
> > >
> > > Regards,
> > >
> > >       Hans
> > >
> > > >
> > > > Modified by Cheng-Yi Chiang:
> > > >  - Add a section in MAINTAINER.
> > > >  - Changes connected and has_eld to bitfield of unsigned int.
> > > >  - Other minor fixes to pass checkpatch.pl --strict checks.
> > > >
> > > > Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
> > > > Acked-by: Philipp Zabel <p.zabel@pengutronix.de>
> > > > Signed-off-by: Cheng-Yi Chiang <cychiang@chromium.org>
> > > > ---
> > > > The original patch is at
> > > > https://lore.kernel.org/linux-arm-kernel/20161213150813.37966-2-hverkuil@xs4all.nl
> > > >
> > > >  MAINTAINERS                   |   6 ++
> > > >  drivers/video/Kconfig         |   3 +
> > > >  drivers/video/Makefile        |   1 +
> > > >  drivers/video/hdmi-notifier.c | 145 ++++++++++++++++++++++++++++++++++
> > > >  include/linux/hdmi-notifier.h | 112 ++++++++++++++++++++++++++
> > > >  5 files changed, 267 insertions(+)
> > > >  create mode 100644 drivers/video/hdmi-notifier.c
> > > >  create mode 100644 include/linux/hdmi-notifier.h
> > > >
> > > > diff --git a/MAINTAINERS b/MAINTAINERS
> > > > index 5cfbea4ce575..ffb7376f9509 100644
> > > > --- a/MAINTAINERS
> > > > +++ b/MAINTAINERS
> > > > @@ -16676,6 +16676,12 @@ W: https://linuxtv.org
> > > >  S: Maintained
> > > >  F: drivers/media/platform/vicodec/*
> > > >
> > > > +VIDEO FRAMEWORK
> > > > +M: Hans Verkuil <hverkuil@xs4all.nl>
> > > > +L: linux-media@vger.kernel.org
> > > > +F: drivers/video/hdmi-notifier.*
> > > > +S: Maintained
> > > > +
> > > >  VIDEO MULTIPLEXER DRIVER
> > > >  M: Philipp Zabel <p.zabel@pengutronix.de>
> > > >  L: linux-media@vger.kernel.org
> > > > diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
> > > > index 83d3d271ca15..000ba9bc0ae7 100644
> > > > --- a/drivers/video/Kconfig
> > > > +++ b/drivers/video/Kconfig
> > > > @@ -34,6 +34,9 @@ config VIDEOMODE_HELPERS
> > > >  config HDMI
> > > >     bool
> > > >
> > > > +config HDMI_NOTIFIERS
> > > > +   bool
> > > > +
> > > >  endif # HAS_IOMEM
> > > >
> > > >  if VT
> > > > diff --git a/drivers/video/Makefile b/drivers/video/Makefile
> > > > index df7650adede9..eff4736102ca 100644
> > > > --- a/drivers/video/Makefile
> > > > +++ b/drivers/video/Makefile
> > > > @@ -1,6 +1,7 @@
> > > >  # SPDX-License-Identifier: GPL-2.0
> > > >  obj-$(CONFIG_VGASTATE)            += vgastate.o
> > > >  obj-$(CONFIG_HDMI)                += hdmi.o
> > > > +obj-$(CONFIG_HDMI_NOTIFIERS)      += hdmi-notifier.o
> > > >
> > > >  obj-$(CONFIG_VT)             += console/
> > > >  obj-$(CONFIG_FB_STI)                 += console/
> > > > diff --git a/drivers/video/hdmi-notifier.c b/drivers/video/hdmi-notifier.c
> > > > new file mode 100644
> > > > index 000000000000..d1eedf661648
> > > > --- /dev/null
> > > > +++ b/drivers/video/hdmi-notifier.c
> > > > @@ -0,0 +1,145 @@
> > > > +// SPDX-License-Identifier: GPL-2.0
> > > > +/* hdmi-notifier.c - notify interested parties of (dis)connect and EDID
> > > > + * events
> > > > + *
> > > > + * Copyright 2016 Russell King <rmk+kernel@arm.linux.org.uk>
> > > > + * Copyright 2016 Cisco Systems, Inc. and/or its affiliates.
> > > > + * All rights reserved.
> > > > + */
> > > > +
> > > > +#include <linux/export.h>
> > > > +#include <linux/hdmi-notifier.h>
> > > > +#include <linux/string.h>
> > > > +#include <linux/slab.h>
> > > > +#include <linux/list.h>
> > > > +
> > > > +static LIST_HEAD(hdmi_notifiers);
> > > > +static DEFINE_MUTEX(hdmi_notifiers_lock);
> > > > +
> > > > +struct hdmi_notifier *hdmi_notifier_get(struct device *dev)
> > > > +{
> > > > +   struct hdmi_notifier *n;
> > > > +
> > > > +   mutex_lock(&hdmi_notifiers_lock);
> > > > +   list_for_each_entry(n, &hdmi_notifiers, head) {
> > > > +           if (n->dev == dev) {
> > > > +                   mutex_unlock(&hdmi_notifiers_lock);
> > > > +                   kref_get(&n->kref);
> > > > +                   return n;
> > > > +           }
> > > > +   }
> > > > +   n = kzalloc(sizeof(*n), GFP_KERNEL);
> > > > +   if (!n)
> > > > +           goto unlock;
> > > > +   n->dev = dev;
> > > > +   mutex_init(&n->lock);
> > > > +   BLOCKING_INIT_NOTIFIER_HEAD(&n->notifiers);
> > > > +   kref_init(&n->kref);
> > > > +   list_add_tail(&n->head, &hdmi_notifiers);
> > > > +unlock:
> > > > +   mutex_unlock(&hdmi_notifiers_lock);
> > > > +   return n;
> > > > +}
> > > > +EXPORT_SYMBOL_GPL(hdmi_notifier_get);
> > > > +
> > > > +static void hdmi_notifier_release(struct kref *kref)
> > > > +{
> > > > +   struct hdmi_notifier *n =
> > > > +           container_of(kref, struct hdmi_notifier, kref);
> > > > +
> > > > +   mutex_lock(&hdmi_notifiers_lock);
> > > > +   list_del(&n->head);
> > > > +   mutex_unlock(&hdmi_notifiers_lock);
> > > > +   kfree(n->edid);
> > > > +   kfree(n);
> > > > +}
> > > > +
> > > > +void hdmi_notifier_put(struct hdmi_notifier *n)
> > > > +{
> > > > +   kref_put(&n->kref, hdmi_notifier_release);
> > > > +}
> > > > +EXPORT_SYMBOL_GPL(hdmi_notifier_put);
> > > > +
> > > > +int hdmi_notifier_register(struct hdmi_notifier *n, struct notifier_block *nb)
> > > > +{
> > > > +   int ret = blocking_notifier_chain_register(&n->notifiers, nb);
> > > > +
> > > > +   if (ret)
> > > > +           return ret;
> > > > +   kref_get(&n->kref);
> > > > +   mutex_lock(&n->lock);
> > > > +   if (n->connected) {
> > > > +           blocking_notifier_call_chain(&n->notifiers, HDMI_CONNECTED, n);
> > > > +           if (n->edid_size)
> > > > +                   blocking_notifier_call_chain(&n->notifiers,
> > > > +                                                HDMI_NEW_EDID, n);
> > > > +           if (n->has_eld)
> > > > +                   blocking_notifier_call_chain(&n->notifiers,
> > > > +                                                HDMI_NEW_ELD, n);
> > > > +   }
> > > > +   mutex_unlock(&n->lock);
> > > > +   return 0;
> > > > +}
> > > > +EXPORT_SYMBOL_GPL(hdmi_notifier_register);
> > > > +
> > > > +int hdmi_notifier_unregister(struct hdmi_notifier *n, struct notifier_block *nb)
> > > > +{
> > > > +   int ret = blocking_notifier_chain_unregister(&n->notifiers, nb);
> > > > +
> > > > +   if (ret == 0)
> > > > +           hdmi_notifier_put(n);
> > > > +   return ret;
> > > > +}
> > > > +EXPORT_SYMBOL_GPL(hdmi_notifier_unregister);
> > > > +
> > > > +void hdmi_event_connect(struct hdmi_notifier *n)
> > > > +{
> > > > +   mutex_lock(&n->lock);
> > > > +   n->connected = true;
> > > > +   blocking_notifier_call_chain(&n->notifiers, HDMI_CONNECTED, n);
> > > > +   mutex_unlock(&n->lock);
> > > > +}
> > > > +EXPORT_SYMBOL_GPL(hdmi_event_connect);
> > > > +
> > > > +void hdmi_event_disconnect(struct hdmi_notifier *n)
> > > > +{
> > > > +   mutex_lock(&n->lock);
> > > > +   n->connected = false;
> > > > +   n->has_eld = false;
> > > > +   n->edid_size = 0;
> > > > +   blocking_notifier_call_chain(&n->notifiers, HDMI_DISCONNECTED, n);
> > > > +   mutex_unlock(&n->lock);
> > > > +}
> > > > +EXPORT_SYMBOL_GPL(hdmi_event_disconnect);
> > > > +
> > > > +int hdmi_event_new_edid(struct hdmi_notifier *n, const void *edid, size_t size)
> > > > +{
> > > > +   mutex_lock(&n->lock);
> > > > +   if (n->edid_allocated_size < size) {
> > > > +           void *p = kmalloc(size, GFP_KERNEL);
> > > > +
> > > > +           if (!p) {
> > > > +                   mutex_unlock(&n->lock);
> > > > +                   return -ENOMEM;
> > > > +           }
> > > > +           kfree(n->edid);
> > > > +           n->edid = p;
> > > > +           n->edid_allocated_size = size;
> > > > +   }
> > > > +   memcpy(n->edid, edid, size);
> > > > +   n->edid_size = size;
> > > > +   blocking_notifier_call_chain(&n->notifiers, HDMI_NEW_EDID, n);
> > > > +   mutex_unlock(&n->lock);
> > > > +   return 0;
> > > > +}
> > > > +EXPORT_SYMBOL_GPL(hdmi_event_new_edid);
> > > > +
> > > > +void hdmi_event_new_eld(struct hdmi_notifier *n, const u8 eld[128])
> > > > +{
> > > > +   mutex_lock(&n->lock);
> > > > +   memcpy(n->eld, eld, sizeof(n->eld));
> > > > +   n->has_eld = true;
> > > > +   blocking_notifier_call_chain(&n->notifiers, HDMI_NEW_ELD, n);
> > > > +   mutex_unlock(&n->lock);
> > > > +}
> > > > +EXPORT_SYMBOL_GPL(hdmi_event_new_eld);
> > > > diff --git a/include/linux/hdmi-notifier.h b/include/linux/hdmi-notifier.h
> > > > new file mode 100644
> > > > index 000000000000..c8f35110e3e3
> > > > --- /dev/null
> > > > +++ b/include/linux/hdmi-notifier.h
> > > > @@ -0,0 +1,112 @@
> > > > +/* SPDX-License-Identifier: GPL-2.0
> > > > + * hdmi-notifier.h - notify interested parties of (dis)connect and EDID
> > > > + * events
> > > > + *
> > > > + * Copyright 2016 Russell King <rmk+kernel@arm.linux.org.uk>
> > > > + * Copyright 2016 Cisco Systems, Inc. and/or its affiliates.
> > > > + * All rights reserved.
> > > > + */
> > > > +
> > > > +#ifndef LINUX_HDMI_NOTIFIER_H
> > > > +#define LINUX_HDMI_NOTIFIER_H
> > > > +
> > > > +#include <linux/types.h>
> > > > +#include <linux/notifier.h>
> > > > +#include <linux/kref.h>
> > > > +
> > > > +enum {
> > > > +   HDMI_CONNECTED,
> > > > +   HDMI_DISCONNECTED,
> > > > +   HDMI_NEW_EDID,
> > > > +   HDMI_NEW_ELD,
> > > > +};
> > > > +
> > > > +struct device;
> > > > +
> > > > +struct hdmi_notifier {
> > > > +   /* Lock to protect callback registration and notification. */
> > > > +   struct mutex lock;
> > > > +   struct list_head head;
> > > > +   struct kref kref;
> > > > +   struct blocking_notifier_head notifiers;
> > > > +   struct device *dev;
> > > > +
> > > > +   /* Current state */
> > > > +   unsigned int connected : 1;
> > > > +   unsigned int has_eld : 1;
> > > > +   unsigned char eld[128];
> > > > +   void *edid;
> > > > +   size_t edid_size;
> > > > +   size_t edid_allocated_size;
> > > > +};
> > > > +
> > > > +/**
> > > > + * hdmi_notifier_get - find or create a new hdmi_notifier for the given device.
> > > > + * @dev: device that sends the events.
> > > > + *
> > > > + * If a notifier for device @dev already exists, then increase the refcount
> > > > + * and return that notifier.
> > > > + *
> > > > + * If it doesn't exist, then allocate a new notifier struct and return a
> > > > + * pointer to that new struct.
> > > > + *
> > > > + * Return NULL if the memory could not be allocated.
> > > > + */
> > > > +struct hdmi_notifier *hdmi_notifier_get(struct device *dev);
> > > > +
> > > > +/**
> > > > + * hdmi_notifier_put - decrease refcount and delete when the refcount reaches 0.
> > > > + * @n: notifier
> > > > + */
> > > > +void hdmi_notifier_put(struct hdmi_notifier *n);
> > > > +
> > > > +/**
> > > > + * hdmi_notifier_register - register the notifier with the notifier_block.
> > > > + * @n: the HDMI notifier
> > > > + * @nb: the notifier_block
> > > > + */
> > > > +int hdmi_notifier_register(struct hdmi_notifier *n, struct notifier_block *nb);
> > > > +
> > > > +/**
> > > > + * hdmi_notifier_unregister - unregister the notifier with the notifier_block.
> > > > + * @n: the HDMI notifier
> > > > + * @nb: the notifier_block
> > > > + */
> > > > +int hdmi_notifier_unregister(struct hdmi_notifier *n,
> > > > +                        struct notifier_block *nb);
> > > > +
> > > > +/**
> > > > + * hdmi_event_connect - send a connect event.
> > > > + * @n: the HDMI notifier
> > > > + *
> > > > + * Send an HDMI_CONNECTED event to any registered parties.
> > > > + */
> > > > +void hdmi_event_connect(struct hdmi_notifier *n);
> > > > +
> > > > +/**
> > > > + * hdmi_event_disconnect - send a disconnect event.
> > > > + * @n: the HDMI notifier
> > > > + *
> > > > + * Send an HDMI_DISCONNECTED event to any registered parties.
> > > > + */
> > > > +void hdmi_event_disconnect(struct hdmi_notifier *n);
> > > > +
> > > > +/**
> > > > + * hdmi_event_new_edid - send a new EDID event.
> > > > + * @n: the HDMI notifier
> > > > + *
> > > > + * Send an HDMI_NEW_EDID event to any registered parties.
> > > > + * This function will make a copy the EDID so it can return -ENOMEM if
> > > > + * no memory could be allocated.
> > > > + */
> > > > +int hdmi_event_new_edid(struct hdmi_notifier *n, const void *edid, size_t size);
> > > > +
> > > > +/**
> > > > + * hdmi_event_new_eld - send a new ELD event.
> > > > + * @n: the HDMI notifier
> > > > + *
> > > > + * Send an HDMI_NEW_ELD event to any registered parties.
> > > > + */
> > > > +void hdmi_event_new_eld(struct hdmi_notifier *n, const u8 eld[128]);
> > > > +
> > > > +#endif
> > > >
> > >
> >
> > --
> > Daniel Vetter
> > Software Engineer, Intel Corporation
> > http://blog.ffwll.ch

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 1/7] video: add HDMI state notifier support
  2019-06-04  7:24         ` Daniel Vetter
@ 2019-06-11 12:10           ` Cheng-yi Chiang
  2019-06-11 12:34             ` Daniel Vetter
  2019-06-11 13:10             ` Hans Verkuil
  0 siblings, 2 replies; 30+ messages in thread
From: Cheng-yi Chiang @ 2019-06-11 12:10 UTC (permalink / raw)
  To: Cheng-yi Chiang, Hans Verkuil, linux-kernel,
	Bartlomiej Zolnierkiewicz, Greg Kroah-Hartman, Philipp Zabel,
	Mark Brown, Liam Girdwood, Takashi Iwai, Jaroslav Kysela,
	Russell King, Andrzej Hajda, Laurent Pinchart, David Airlie,
	Rob Herring, Heiko Stuebner, Doug Anderson, Dylan Reid, tzungbi,
	linux-media,
	moderated list:SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEM...,
	dri-devel, linux-arm-kernel, linux-rockchip, devicetree,
	Dariusz Marcinkiewicz
  Cc: Daniel Vetter

On Tue, Jun 4, 2019 at 3:24 PM Daniel Vetter <daniel@ffwll.ch> wrote:
>
> On Tue, Jun 04, 2019 at 10:32:50AM +0800, Cheng-yi Chiang wrote:
> > On Mon, Jun 3, 2019 at 4:09 PM Daniel Vetter <daniel@ffwll.ch> wrote:
> > >
> > > On Mon, Jun 03, 2019 at 09:45:49AM +0200, Hans Verkuil wrote:
> > > > On 6/3/19 6:32 AM, Cheng-Yi Chiang wrote:
> > > > > From: Hans Verkuil <hans.verkuil@cisco.com>
> > > > >
> > > > > Add support for HDMI hotplug and EDID notifiers, which is used to convey
> > > > > information from HDMI drivers to their CEC and audio counterparts.
> > > > >
> > > > > Based on an earlier version from Russell King:
> > > > >
> > > > > https://patchwork.kernel.org/patch/9277043/
> > > > >
> > > > > The hdmi_notifier is a reference counted object containing the HDMI state
> > > > > of an HDMI device.
> > > > >
> > > > > When a new notifier is registered the current state will be reported to
> > > > > that notifier at registration time.
> > > > >
> > > > > Based on Hans Verkuil's patch:
> > > > >
> > > > > https://patchwork.kernel.org/patch/9472521/
> > > >
> > > > Erm, you are aware that this patch morphed into a CEC-specific notifier
> > > > found in drivers/media/cec/cec-notifier.c?
> > > >
> > > > I don't think it makes sense to have two notifier implementations in the kernel.
> > > > The original intention was to have the notifier deal with both CEC and ASoC
> > > > notifications, but there was not enough interest for the ASoC bits at the time
> > > > and it was dropped.
> > > >
> > > > I am planning changes to the cec-notifier API, I hope to work on that this
> > > > week. I'll CC you when I post those. Those might be a good starting point
> > > > to convert the cec-notifier to an hdmi-notifier as was originally intended.
> > > >
> > > > I've added your colleague Dariusz Marcinkiewicz to the CC list since he's been
> > > > working on some nice cec-notifier improvements as well.
> > >
> > > We also have some interfaces for drm/alsa interactions around hdmi
> > > already in drm/drm_audio_component.h, but it's not used by anything
> > > outside of i915. Imo we should extend that, not reinvent a new wheel.
> > >
> > Hi Daniel,
> > Thank you for the pointer. Looking at the ops, it seems that it is
> > specific to HDA.
> > I am not familiar with drm and HDA. I am not sure how applicable it
> > would be to report jack status to ASoC.
> > There is a use case in sound/soc/codecs/hdac_hdmi.c though so it
> > should be possible.
>
> Currently hda is the only user, but the idea was to make it more generic.
> Jack status in alsa is what drm calls connector status btw.
>
> So if we can take that as a baseline and extend it (probably needs some
> registration boilerplate and helpers to look up the right endpoint using
> of/dt for soc systems, we use component.c in i915/hda for this), that
> would be great I think.
>
> > > Another note: notifiers considered evil, imo. Gets the job done for one
> > > case, as soon as you have multiple devices and need to make sure you get
> > > the update for the right one it all comes crashing down. Please create an
> > > api which registers for updates from a specific device only, plus
> > > something that has real callbacks (like the drm_audio_component.h thing we
> > > started already).
> >
> > To clarify a bit, this hdmi-notifier indeed supports updating from a
> > specific device only.
> > hdmi_notifier_get takes a device and return the notifier.
>
> Hm I missed that, I thought it's global, so one of my usual notifier
> concerns addressed.
>
> > It seems that a major difference between drm_audio_components and
> > hdmi-notifier is that
> > drm_audio_components defines all supported ops in drm_audio_component_audio_ops.
> > On the other hand, hdmi-notifier passes different events using an enum
> > like HDMI_CONNECTED and let listener handle different events.
> > In this regard I agree with you that drm_audio_component is cleaner.
> > Anyway, I will look into it a bit more and see how it works.
>
> Yeah I think if we could combine the approach, i.e. notifier side for
> registration, some _ops structure for the actual notifications, then
> there's a solid interface. I just really don't like the opaque void *
> interface notifier provides, it encourages abuse way too much.
>
> Ofc the registration side would then no longer be based on the notifier
> datastructure, list_head (like cec-notifier.c) of registeres devices with
> their _ops structure should be enough.
> -Daniel

Hi Daniel,
Yes, I agree the above statement that we should have a more solid interface.

Hi Hans,
I am not sure if I missed the patch.
Do you have a estimated timeline for new cec-notifier interface you
are working on?
It seems that your PoC patch needs Dariusz's patch to work.
I would like to seek your advice on whether I can proceed without your
patch and Dariusz's patch.

I looked through the patch from Dariusz

https://lkml.org/lkml/2019/5/21/389

, and saw that you were thinking whether we should use cec-notifier
for both HDMI and CEC.

https://lkml.org/lkml/2019/5/24/298

Could you please let me know your latest thought on whether we should
reuse cec-notifier?
I agree with you that I should not proceed with hdmi-notifier. Reasons include:
1. Method like cec_notifier_parse_hdmi_phandle can be reused. It is
error prone to memory leak if it is implemented by user, like the
patch in hdmi-codec.c in this series did not handle the ref count.
2. cec-notifier has a simpler implementation of register / unregister
because there is no call chain. I am not aware of the need for
hdmi-notifier to support a chain of callbacks. So I think that call
chain support can be removed.

If I go ahead and add a new interface to register ops to handle
connector status report from cec-notifer, based on current
cec-notifier, do you think that would work ?
I think it might work if I add another cec_notifier object inside
dw-hdmi.c, but only for HDMI jack reporting, not for CEC related
reporting.

And after some investigation, I realize that my requirement is even
simpler. I don't need hdmi_event_new_edid and hdmi_event_new_eld in my
use case.
I just need to report the connector status from synopsys/dw-hdmi.c to
codecs/hdmi-codec.c for codec driver to update the jack status.
Do you think I can proceed in this direction ? Or do you prefer I wait
for a while and work on it based on your new patch.

Thanks a lot!


>
> >
> > Thanks again!
> >
> > > -Daniel
> > >
> > > >
> > > > Regards,
> > > >
> > > >       Hans
> > > >
> > > > >
> > > > > Modified by Cheng-Yi Chiang:
> > > > >  - Add a section in MAINTAINER.
> > > > >  - Changes connected and has_eld to bitfield of unsigned int.
> > > > >  - Other minor fixes to pass checkpatch.pl --strict checks.
> > > > >
> > > > > Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
> > > > > Acked-by: Philipp Zabel <p.zabel@pengutronix.de>
> > > > > Signed-off-by: Cheng-Yi Chiang <cychiang@chromium.org>
> > > > > ---
> > > > > The original patch is at
> > > > > https://lore.kernel.org/linux-arm-kernel/20161213150813.37966-2-hverkuil@xs4all.nl
> > > > >
> > > > >  MAINTAINERS                   |   6 ++
> > > > >  drivers/video/Kconfig         |   3 +
> > > > >  drivers/video/Makefile        |   1 +
> > > > >  drivers/video/hdmi-notifier.c | 145 ++++++++++++++++++++++++++++++++++
> > > > >  include/linux/hdmi-notifier.h | 112 ++++++++++++++++++++++++++
> > > > >  5 files changed, 267 insertions(+)
> > > > >  create mode 100644 drivers/video/hdmi-notifier.c
> > > > >  create mode 100644 include/linux/hdmi-notifier.h
> > > > >
> > > > > diff --git a/MAINTAINERS b/MAINTAINERS
> > > > > index 5cfbea4ce575..ffb7376f9509 100644
> > > > > --- a/MAINTAINERS
> > > > > +++ b/MAINTAINERS
> > > > > @@ -16676,6 +16676,12 @@ W: https://linuxtv.org
> > > > >  S: Maintained
> > > > >  F: drivers/media/platform/vicodec/*
> > > > >
> > > > > +VIDEO FRAMEWORK
> > > > > +M: Hans Verkuil <hverkuil@xs4all.nl>
> > > > > +L: linux-media@vger.kernel.org
> > > > > +F: drivers/video/hdmi-notifier.*
> > > > > +S: Maintained
> > > > > +
> > > > >  VIDEO MULTIPLEXER DRIVER
> > > > >  M: Philipp Zabel <p.zabel@pengutronix.de>
> > > > >  L: linux-media@vger.kernel.org
> > > > > diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
> > > > > index 83d3d271ca15..000ba9bc0ae7 100644
> > > > > --- a/drivers/video/Kconfig
> > > > > +++ b/drivers/video/Kconfig
> > > > > @@ -34,6 +34,9 @@ config VIDEOMODE_HELPERS
> > > > >  config HDMI
> > > > >     bool
> > > > >
> > > > > +config HDMI_NOTIFIERS
> > > > > +   bool
> > > > > +
> > > > >  endif # HAS_IOMEM
> > > > >
> > > > >  if VT
> > > > > diff --git a/drivers/video/Makefile b/drivers/video/Makefile
> > > > > index df7650adede9..eff4736102ca 100644
> > > > > --- a/drivers/video/Makefile
> > > > > +++ b/drivers/video/Makefile
> > > > > @@ -1,6 +1,7 @@
> > > > >  # SPDX-License-Identifier: GPL-2.0
> > > > >  obj-$(CONFIG_VGASTATE)            += vgastate.o
> > > > >  obj-$(CONFIG_HDMI)                += hdmi.o
> > > > > +obj-$(CONFIG_HDMI_NOTIFIERS)      += hdmi-notifier.o
> > > > >
> > > > >  obj-$(CONFIG_VT)             += console/
> > > > >  obj-$(CONFIG_FB_STI)                 += console/
> > > > > diff --git a/drivers/video/hdmi-notifier.c b/drivers/video/hdmi-notifier.c
> > > > > new file mode 100644
> > > > > index 000000000000..d1eedf661648
> > > > > --- /dev/null
> > > > > +++ b/drivers/video/hdmi-notifier.c
> > > > > @@ -0,0 +1,145 @@
> > > > > +// SPDX-License-Identifier: GPL-2.0
> > > > > +/* hdmi-notifier.c - notify interested parties of (dis)connect and EDID
> > > > > + * events
> > > > > + *
> > > > > + * Copyright 2016 Russell King <rmk+kernel@arm.linux.org.uk>
> > > > > + * Copyright 2016 Cisco Systems, Inc. and/or its affiliates.
> > > > > + * All rights reserved.
> > > > > + */
> > > > > +
> > > > > +#include <linux/export.h>
> > > > > +#include <linux/hdmi-notifier.h>
> > > > > +#include <linux/string.h>
> > > > > +#include <linux/slab.h>
> > > > > +#include <linux/list.h>
> > > > > +
> > > > > +static LIST_HEAD(hdmi_notifiers);
> > > > > +static DEFINE_MUTEX(hdmi_notifiers_lock);
> > > > > +
> > > > > +struct hdmi_notifier *hdmi_notifier_get(struct device *dev)
> > > > > +{
> > > > > +   struct hdmi_notifier *n;
> > > > > +
> > > > > +   mutex_lock(&hdmi_notifiers_lock);
> > > > > +   list_for_each_entry(n, &hdmi_notifiers, head) {
> > > > > +           if (n->dev == dev) {
> > > > > +                   mutex_unlock(&hdmi_notifiers_lock);
> > > > > +                   kref_get(&n->kref);
> > > > > +                   return n;
> > > > > +           }
> > > > > +   }
> > > > > +   n = kzalloc(sizeof(*n), GFP_KERNEL);
> > > > > +   if (!n)
> > > > > +           goto unlock;
> > > > > +   n->dev = dev;
> > > > > +   mutex_init(&n->lock);
> > > > > +   BLOCKING_INIT_NOTIFIER_HEAD(&n->notifiers);
> > > > > +   kref_init(&n->kref);
> > > > > +   list_add_tail(&n->head, &hdmi_notifiers);
> > > > > +unlock:
> > > > > +   mutex_unlock(&hdmi_notifiers_lock);
> > > > > +   return n;
> > > > > +}
> > > > > +EXPORT_SYMBOL_GPL(hdmi_notifier_get);
> > > > > +
> > > > > +static void hdmi_notifier_release(struct kref *kref)
> > > > > +{
> > > > > +   struct hdmi_notifier *n =
> > > > > +           container_of(kref, struct hdmi_notifier, kref);
> > > > > +
> > > > > +   mutex_lock(&hdmi_notifiers_lock);
> > > > > +   list_del(&n->head);
> > > > > +   mutex_unlock(&hdmi_notifiers_lock);
> > > > > +   kfree(n->edid);
> > > > > +   kfree(n);
> > > > > +}
> > > > > +
> > > > > +void hdmi_notifier_put(struct hdmi_notifier *n)
> > > > > +{
> > > > > +   kref_put(&n->kref, hdmi_notifier_release);
> > > > > +}
> > > > > +EXPORT_SYMBOL_GPL(hdmi_notifier_put);
> > > > > +
> > > > > +int hdmi_notifier_register(struct hdmi_notifier *n, struct notifier_block *nb)
> > > > > +{
> > > > > +   int ret = blocking_notifier_chain_register(&n->notifiers, nb);
> > > > > +
> > > > > +   if (ret)
> > > > > +           return ret;
> > > > > +   kref_get(&n->kref);
> > > > > +   mutex_lock(&n->lock);
> > > > > +   if (n->connected) {
> > > > > +           blocking_notifier_call_chain(&n->notifiers, HDMI_CONNECTED, n);
> > > > > +           if (n->edid_size)
> > > > > +                   blocking_notifier_call_chain(&n->notifiers,
> > > > > +                                                HDMI_NEW_EDID, n);
> > > > > +           if (n->has_eld)
> > > > > +                   blocking_notifier_call_chain(&n->notifiers,
> > > > > +                                                HDMI_NEW_ELD, n);
> > > > > +   }
> > > > > +   mutex_unlock(&n->lock);
> > > > > +   return 0;
> > > > > +}
> > > > > +EXPORT_SYMBOL_GPL(hdmi_notifier_register);
> > > > > +
> > > > > +int hdmi_notifier_unregister(struct hdmi_notifier *n, struct notifier_block *nb)
> > > > > +{
> > > > > +   int ret = blocking_notifier_chain_unregister(&n->notifiers, nb);
> > > > > +
> > > > > +   if (ret == 0)
> > > > > +           hdmi_notifier_put(n);
> > > > > +   return ret;
> > > > > +}
> > > > > +EXPORT_SYMBOL_GPL(hdmi_notifier_unregister);
> > > > > +
> > > > > +void hdmi_event_connect(struct hdmi_notifier *n)
> > > > > +{
> > > > > +   mutex_lock(&n->lock);
> > > > > +   n->connected = true;
> > > > > +   blocking_notifier_call_chain(&n->notifiers, HDMI_CONNECTED, n);
> > > > > +   mutex_unlock(&n->lock);
> > > > > +}
> > > > > +EXPORT_SYMBOL_GPL(hdmi_event_connect);
> > > > > +
> > > > > +void hdmi_event_disconnect(struct hdmi_notifier *n)
> > > > > +{
> > > > > +   mutex_lock(&n->lock);
> > > > > +   n->connected = false;
> > > > > +   n->has_eld = false;
> > > > > +   n->edid_size = 0;
> > > > > +   blocking_notifier_call_chain(&n->notifiers, HDMI_DISCONNECTED, n);
> > > > > +   mutex_unlock(&n->lock);
> > > > > +}
> > > > > +EXPORT_SYMBOL_GPL(hdmi_event_disconnect);
> > > > > +
> > > > > +int hdmi_event_new_edid(struct hdmi_notifier *n, const void *edid, size_t size)
> > > > > +{
> > > > > +   mutex_lock(&n->lock);
> > > > > +   if (n->edid_allocated_size < size) {
> > > > > +           void *p = kmalloc(size, GFP_KERNEL);
> > > > > +
> > > > > +           if (!p) {
> > > > > +                   mutex_unlock(&n->lock);
> > > > > +                   return -ENOMEM;
> > > > > +           }
> > > > > +           kfree(n->edid);
> > > > > +           n->edid = p;
> > > > > +           n->edid_allocated_size = size;
> > > > > +   }
> > > > > +   memcpy(n->edid, edid, size);
> > > > > +   n->edid_size = size;
> > > > > +   blocking_notifier_call_chain(&n->notifiers, HDMI_NEW_EDID, n);
> > > > > +   mutex_unlock(&n->lock);
> > > > > +   return 0;
> > > > > +}
> > > > > +EXPORT_SYMBOL_GPL(hdmi_event_new_edid);
> > > > > +
> > > > > +void hdmi_event_new_eld(struct hdmi_notifier *n, const u8 eld[128])
> > > > > +{
> > > > > +   mutex_lock(&n->lock);
> > > > > +   memcpy(n->eld, eld, sizeof(n->eld));
> > > > > +   n->has_eld = true;
> > > > > +   blocking_notifier_call_chain(&n->notifiers, HDMI_NEW_ELD, n);
> > > > > +   mutex_unlock(&n->lock);
> > > > > +}
> > > > > +EXPORT_SYMBOL_GPL(hdmi_event_new_eld);
> > > > > diff --git a/include/linux/hdmi-notifier.h b/include/linux/hdmi-notifier.h
> > > > > new file mode 100644
> > > > > index 000000000000..c8f35110e3e3
> > > > > --- /dev/null
> > > > > +++ b/include/linux/hdmi-notifier.h
> > > > > @@ -0,0 +1,112 @@
> > > > > +/* SPDX-License-Identifier: GPL-2.0
> > > > > + * hdmi-notifier.h - notify interested parties of (dis)connect and EDID
> > > > > + * events
> > > > > + *
> > > > > + * Copyright 2016 Russell King <rmk+kernel@arm.linux.org.uk>
> > > > > + * Copyright 2016 Cisco Systems, Inc. and/or its affiliates.
> > > > > + * All rights reserved.
> > > > > + */
> > > > > +
> > > > > +#ifndef LINUX_HDMI_NOTIFIER_H
> > > > > +#define LINUX_HDMI_NOTIFIER_H
> > > > > +
> > > > > +#include <linux/types.h>
> > > > > +#include <linux/notifier.h>
> > > > > +#include <linux/kref.h>
> > > > > +
> > > > > +enum {
> > > > > +   HDMI_CONNECTED,
> > > > > +   HDMI_DISCONNECTED,
> > > > > +   HDMI_NEW_EDID,
> > > > > +   HDMI_NEW_ELD,
> > > > > +};
> > > > > +
> > > > > +struct device;
> > > > > +
> > > > > +struct hdmi_notifier {
> > > > > +   /* Lock to protect callback registration and notification. */
> > > > > +   struct mutex lock;
> > > > > +   struct list_head head;
> > > > > +   struct kref kref;
> > > > > +   struct blocking_notifier_head notifiers;
> > > > > +   struct device *dev;
> > > > > +
> > > > > +   /* Current state */
> > > > > +   unsigned int connected : 1;
> > > > > +   unsigned int has_eld : 1;
> > > > > +   unsigned char eld[128];
> > > > > +   void *edid;
> > > > > +   size_t edid_size;
> > > > > +   size_t edid_allocated_size;
> > > > > +};
> > > > > +
> > > > > +/**
> > > > > + * hdmi_notifier_get - find or create a new hdmi_notifier for the given device.
> > > > > + * @dev: device that sends the events.
> > > > > + *
> > > > > + * If a notifier for device @dev already exists, then increase the refcount
> > > > > + * and return that notifier.
> > > > > + *
> > > > > + * If it doesn't exist, then allocate a new notifier struct and return a
> > > > > + * pointer to that new struct.
> > > > > + *
> > > > > + * Return NULL if the memory could not be allocated.
> > > > > + */
> > > > > +struct hdmi_notifier *hdmi_notifier_get(struct device *dev);
> > > > > +
> > > > > +/**
> > > > > + * hdmi_notifier_put - decrease refcount and delete when the refcount reaches 0.
> > > > > + * @n: notifier
> > > > > + */
> > > > > +void hdmi_notifier_put(struct hdmi_notifier *n);
> > > > > +
> > > > > +/**
> > > > > + * hdmi_notifier_register - register the notifier with the notifier_block.
> > > > > + * @n: the HDMI notifier
> > > > > + * @nb: the notifier_block
> > > > > + */
> > > > > +int hdmi_notifier_register(struct hdmi_notifier *n, struct notifier_block *nb);
> > > > > +
> > > > > +/**
> > > > > + * hdmi_notifier_unregister - unregister the notifier with the notifier_block.
> > > > > + * @n: the HDMI notifier
> > > > > + * @nb: the notifier_block
> > > > > + */
> > > > > +int hdmi_notifier_unregister(struct hdmi_notifier *n,
> > > > > +                        struct notifier_block *nb);
> > > > > +
> > > > > +/**
> > > > > + * hdmi_event_connect - send a connect event.
> > > > > + * @n: the HDMI notifier
> > > > > + *
> > > > > + * Send an HDMI_CONNECTED event to any registered parties.
> > > > > + */
> > > > > +void hdmi_event_connect(struct hdmi_notifier *n);
> > > > > +
> > > > > +/**
> > > > > + * hdmi_event_disconnect - send a disconnect event.
> > > > > + * @n: the HDMI notifier
> > > > > + *
> > > > > + * Send an HDMI_DISCONNECTED event to any registered parties.
> > > > > + */
> > > > > +void hdmi_event_disconnect(struct hdmi_notifier *n);
> > > > > +
> > > > > +/**
> > > > > + * hdmi_event_new_edid - send a new EDID event.
> > > > > + * @n: the HDMI notifier
> > > > > + *
> > > > > + * Send an HDMI_NEW_EDID event to any registered parties.
> > > > > + * This function will make a copy the EDID so it can return -ENOMEM if
> > > > > + * no memory could be allocated.
> > > > > + */
> > > > > +int hdmi_event_new_edid(struct hdmi_notifier *n, const void *edid, size_t size);
> > > > > +
> > > > > +/**
> > > > > + * hdmi_event_new_eld - send a new ELD event.
> > > > > + * @n: the HDMI notifier
> > > > > + *
> > > > > + * Send an HDMI_NEW_ELD event to any registered parties.
> > > > > + */
> > > > > +void hdmi_event_new_eld(struct hdmi_notifier *n, const u8 eld[128]);
> > > > > +
> > > > > +#endif
> > > > >
> > > >
> > >
> > > --
> > > Daniel Vetter
> > > Software Engineer, Intel Corporation
> > > http://blog.ffwll.ch
>
> --
> Daniel Vetter
> Software Engineer, Intel Corporation
> http://blog.ffwll.ch

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 1/7] video: add HDMI state notifier support
  2019-06-11 12:10           ` Cheng-yi Chiang
@ 2019-06-11 12:34             ` Daniel Vetter
  2019-06-18 11:48               ` Cheng-yi Chiang
  2019-06-11 13:10             ` Hans Verkuil
  1 sibling, 1 reply; 30+ messages in thread
From: Daniel Vetter @ 2019-06-11 12:34 UTC (permalink / raw)
  To: Cheng-yi Chiang
  Cc: moderated list:SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEM...,
	Heiko Stuebner, Liam Girdwood, David Airlie, dri-devel,
	Takashi Iwai, Hans Verkuil, Andrzej Hajda, Laurent Pinchart,
	linux-rockchip, Dylan Reid, linux-media, devicetree, tzungbi,
	Daniel Vetter, Bartlomiej Zolnierkiewicz, Russell King,
	Rob Herring, Jaroslav Kysela, linux-arm-kernel,
	Greg Kroah-Hartman, Doug Anderson, linux-kernel, Mark Brown,
	Philipp Zabel, Dariusz Marcinkiewicz

On Tue, Jun 11, 2019 at 08:10:38PM +0800, Cheng-yi Chiang wrote:
> On Tue, Jun 4, 2019 at 3:24 PM Daniel Vetter <daniel@ffwll.ch> wrote:
> >
> > On Tue, Jun 04, 2019 at 10:32:50AM +0800, Cheng-yi Chiang wrote:
> > > On Mon, Jun 3, 2019 at 4:09 PM Daniel Vetter <daniel@ffwll.ch> wrote:
> > > >
> > > > On Mon, Jun 03, 2019 at 09:45:49AM +0200, Hans Verkuil wrote:
> > > > > On 6/3/19 6:32 AM, Cheng-Yi Chiang wrote:
> > > > > > From: Hans Verkuil <hans.verkuil@cisco.com>
> > > > > >
> > > > > > Add support for HDMI hotplug and EDID notifiers, which is used to convey
> > > > > > information from HDMI drivers to their CEC and audio counterparts.
> > > > > >
> > > > > > Based on an earlier version from Russell King:
> > > > > >
> > > > > > https://patchwork.kernel.org/patch/9277043/
> > > > > >
> > > > > > The hdmi_notifier is a reference counted object containing the HDMI state
> > > > > > of an HDMI device.
> > > > > >
> > > > > > When a new notifier is registered the current state will be reported to
> > > > > > that notifier at registration time.
> > > > > >
> > > > > > Based on Hans Verkuil's patch:
> > > > > >
> > > > > > https://patchwork.kernel.org/patch/9472521/
> > > > >
> > > > > Erm, you are aware that this patch morphed into a CEC-specific notifier
> > > > > found in drivers/media/cec/cec-notifier.c?
> > > > >
> > > > > I don't think it makes sense to have two notifier implementations in the kernel.
> > > > > The original intention was to have the notifier deal with both CEC and ASoC
> > > > > notifications, but there was not enough interest for the ASoC bits at the time
> > > > > and it was dropped.
> > > > >
> > > > > I am planning changes to the cec-notifier API, I hope to work on that this
> > > > > week. I'll CC you when I post those. Those might be a good starting point
> > > > > to convert the cec-notifier to an hdmi-notifier as was originally intended.
> > > > >
> > > > > I've added your colleague Dariusz Marcinkiewicz to the CC list since he's been
> > > > > working on some nice cec-notifier improvements as well.
> > > >
> > > > We also have some interfaces for drm/alsa interactions around hdmi
> > > > already in drm/drm_audio_component.h, but it's not used by anything
> > > > outside of i915. Imo we should extend that, not reinvent a new wheel.
> > > >
> > > Hi Daniel,
> > > Thank you for the pointer. Looking at the ops, it seems that it is
> > > specific to HDA.
> > > I am not familiar with drm and HDA. I am not sure how applicable it
> > > would be to report jack status to ASoC.
> > > There is a use case in sound/soc/codecs/hdac_hdmi.c though so it
> > > should be possible.
> >
> > Currently hda is the only user, but the idea was to make it more generic.
> > Jack status in alsa is what drm calls connector status btw.
> >
> > So if we can take that as a baseline and extend it (probably needs some
> > registration boilerplate and helpers to look up the right endpoint using
> > of/dt for soc systems, we use component.c in i915/hda for this), that
> > would be great I think.
> >
> > > > Another note: notifiers considered evil, imo. Gets the job done for one
> > > > case, as soon as you have multiple devices and need to make sure you get
> > > > the update for the right one it all comes crashing down. Please create an
> > > > api which registers for updates from a specific device only, plus
> > > > something that has real callbacks (like the drm_audio_component.h thing we
> > > > started already).
> > >
> > > To clarify a bit, this hdmi-notifier indeed supports updating from a
> > > specific device only.
> > > hdmi_notifier_get takes a device and return the notifier.
> >
> > Hm I missed that, I thought it's global, so one of my usual notifier
> > concerns addressed.
> >
> > > It seems that a major difference between drm_audio_components and
> > > hdmi-notifier is that
> > > drm_audio_components defines all supported ops in drm_audio_component_audio_ops.
> > > On the other hand, hdmi-notifier passes different events using an enum
> > > like HDMI_CONNECTED and let listener handle different events.
> > > In this regard I agree with you that drm_audio_component is cleaner.
> > > Anyway, I will look into it a bit more and see how it works.
> >
> > Yeah I think if we could combine the approach, i.e. notifier side for
> > registration, some _ops structure for the actual notifications, then
> > there's a solid interface. I just really don't like the opaque void *
> > interface notifier provides, it encourages abuse way too much.
> >
> > Ofc the registration side would then no longer be based on the notifier
> > datastructure, list_head (like cec-notifier.c) of registeres devices with
> > their _ops structure should be enough.
> > -Daniel
> 
> Hi Daniel,
> Yes, I agree the above statement that we should have a more solid interface.
> 
> Hi Hans,
> I am not sure if I missed the patch.
> Do you have a estimated timeline for new cec-notifier interface you
> are working on?
> It seems that your PoC patch needs Dariusz's patch to work.
> I would like to seek your advice on whether I can proceed without your
> patch and Dariusz's patch.
> 
> I looked through the patch from Dariusz
> 
> https://lkml.org/lkml/2019/5/21/389
> 
> , and saw that you were thinking whether we should use cec-notifier
> for both HDMI and CEC.
> 
> https://lkml.org/lkml/2019/5/24/298
> 
> Could you please let me know your latest thought on whether we should
> reuse cec-notifier?

Nah, see later in that thread, I think cec and audio seem to be different
use-cases.

But definitely a good idea to sync with Dariusz, I forgot to pull the two
threads together. Thanks for doing that.

> I agree with you that I should not proceed with hdmi-notifier. Reasons include:
> 1. Method like cec_notifier_parse_hdmi_phandle can be reused. It is
> error prone to memory leak if it is implemented by user, like the
> patch in hdmi-codec.c in this series did not handle the ref count.
> 2. cec-notifier has a simpler implementation of register / unregister
> because there is no call chain. I am not aware of the need for
> hdmi-notifier to support a chain of callbacks. So I think that call
> chain support can be removed.
> 
> If I go ahead and add a new interface to register ops to handle
> connector status report from cec-notifer, based on current
> cec-notifier, do you think that would work ?
> I think it might work if I add another cec_notifier object inside
> dw-hdmi.c, but only for HDMI jack reporting, not for CEC related
> reporting.
> 
> And after some investigation, I realize that my requirement is even
> simpler. I don't need hdmi_event_new_edid and hdmi_event_new_eld in my
> use case.

Yeah, connector status is how we started with the drm/alsa interface in
i915 too, but later on had to extend it. I think eventually we'll need it
all, that's why I suggested to use that as the interface between drm and
alsa side, but augmented with some register/unregister and bind logic.

> I just need to report the connector status from synopsys/dw-hdmi.c to
> codecs/hdmi-codec.c for codec driver to update the jack status.
> Do you think I can proceed in this direction ? Or do you prefer I wait
> for a while and work on it based on your new patch.

I think most important part here is that we sync across all the different
people pushing for better drm/alsa integration. What the solution looks
like in the end doesn't matter much imo, as long as we don't end up with 3
different things :-)

Cheers, Daniel

> 
> Thanks a lot!
> 
> 
> >
> > >
> > > Thanks again!
> > >
> > > > -Daniel
> > > >
> > > > >
> > > > > Regards,
> > > > >
> > > > >       Hans
> > > > >
> > > > > >
> > > > > > Modified by Cheng-Yi Chiang:
> > > > > >  - Add a section in MAINTAINER.
> > > > > >  - Changes connected and has_eld to bitfield of unsigned int.
> > > > > >  - Other minor fixes to pass checkpatch.pl --strict checks.
> > > > > >
> > > > > > Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
> > > > > > Acked-by: Philipp Zabel <p.zabel@pengutronix.de>
> > > > > > Signed-off-by: Cheng-Yi Chiang <cychiang@chromium.org>
> > > > > > ---
> > > > > > The original patch is at
> > > > > > https://lore.kernel.org/linux-arm-kernel/20161213150813.37966-2-hverkuil@xs4all.nl
> > > > > >
> > > > > >  MAINTAINERS                   |   6 ++
> > > > > >  drivers/video/Kconfig         |   3 +
> > > > > >  drivers/video/Makefile        |   1 +
> > > > > >  drivers/video/hdmi-notifier.c | 145 ++++++++++++++++++++++++++++++++++
> > > > > >  include/linux/hdmi-notifier.h | 112 ++++++++++++++++++++++++++
> > > > > >  5 files changed, 267 insertions(+)
> > > > > >  create mode 100644 drivers/video/hdmi-notifier.c
> > > > > >  create mode 100644 include/linux/hdmi-notifier.h
> > > > > >
> > > > > > diff --git a/MAINTAINERS b/MAINTAINERS
> > > > > > index 5cfbea4ce575..ffb7376f9509 100644
> > > > > > --- a/MAINTAINERS
> > > > > > +++ b/MAINTAINERS
> > > > > > @@ -16676,6 +16676,12 @@ W: https://linuxtv.org
> > > > > >  S: Maintained
> > > > > >  F: drivers/media/platform/vicodec/*
> > > > > >
> > > > > > +VIDEO FRAMEWORK
> > > > > > +M: Hans Verkuil <hverkuil@xs4all.nl>
> > > > > > +L: linux-media@vger.kernel.org
> > > > > > +F: drivers/video/hdmi-notifier.*
> > > > > > +S: Maintained
> > > > > > +
> > > > > >  VIDEO MULTIPLEXER DRIVER
> > > > > >  M: Philipp Zabel <p.zabel@pengutronix.de>
> > > > > >  L: linux-media@vger.kernel.org
> > > > > > diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
> > > > > > index 83d3d271ca15..000ba9bc0ae7 100644
> > > > > > --- a/drivers/video/Kconfig
> > > > > > +++ b/drivers/video/Kconfig
> > > > > > @@ -34,6 +34,9 @@ config VIDEOMODE_HELPERS
> > > > > >  config HDMI
> > > > > >     bool
> > > > > >
> > > > > > +config HDMI_NOTIFIERS
> > > > > > +   bool
> > > > > > +
> > > > > >  endif # HAS_IOMEM
> > > > > >
> > > > > >  if VT
> > > > > > diff --git a/drivers/video/Makefile b/drivers/video/Makefile
> > > > > > index df7650adede9..eff4736102ca 100644
> > > > > > --- a/drivers/video/Makefile
> > > > > > +++ b/drivers/video/Makefile
> > > > > > @@ -1,6 +1,7 @@
> > > > > >  # SPDX-License-Identifier: GPL-2.0
> > > > > >  obj-$(CONFIG_VGASTATE)            += vgastate.o
> > > > > >  obj-$(CONFIG_HDMI)                += hdmi.o
> > > > > > +obj-$(CONFIG_HDMI_NOTIFIERS)      += hdmi-notifier.o
> > > > > >
> > > > > >  obj-$(CONFIG_VT)             += console/
> > > > > >  obj-$(CONFIG_FB_STI)                 += console/
> > > > > > diff --git a/drivers/video/hdmi-notifier.c b/drivers/video/hdmi-notifier.c
> > > > > > new file mode 100644
> > > > > > index 000000000000..d1eedf661648
> > > > > > --- /dev/null
> > > > > > +++ b/drivers/video/hdmi-notifier.c
> > > > > > @@ -0,0 +1,145 @@
> > > > > > +// SPDX-License-Identifier: GPL-2.0
> > > > > > +/* hdmi-notifier.c - notify interested parties of (dis)connect and EDID
> > > > > > + * events
> > > > > > + *
> > > > > > + * Copyright 2016 Russell King <rmk+kernel@arm.linux.org.uk>
> > > > > > + * Copyright 2016 Cisco Systems, Inc. and/or its affiliates.
> > > > > > + * All rights reserved.
> > > > > > + */
> > > > > > +
> > > > > > +#include <linux/export.h>
> > > > > > +#include <linux/hdmi-notifier.h>
> > > > > > +#include <linux/string.h>
> > > > > > +#include <linux/slab.h>
> > > > > > +#include <linux/list.h>
> > > > > > +
> > > > > > +static LIST_HEAD(hdmi_notifiers);
> > > > > > +static DEFINE_MUTEX(hdmi_notifiers_lock);
> > > > > > +
> > > > > > +struct hdmi_notifier *hdmi_notifier_get(struct device *dev)
> > > > > > +{
> > > > > > +   struct hdmi_notifier *n;
> > > > > > +
> > > > > > +   mutex_lock(&hdmi_notifiers_lock);
> > > > > > +   list_for_each_entry(n, &hdmi_notifiers, head) {
> > > > > > +           if (n->dev == dev) {
> > > > > > +                   mutex_unlock(&hdmi_notifiers_lock);
> > > > > > +                   kref_get(&n->kref);
> > > > > > +                   return n;
> > > > > > +           }
> > > > > > +   }
> > > > > > +   n = kzalloc(sizeof(*n), GFP_KERNEL);
> > > > > > +   if (!n)
> > > > > > +           goto unlock;
> > > > > > +   n->dev = dev;
> > > > > > +   mutex_init(&n->lock);
> > > > > > +   BLOCKING_INIT_NOTIFIER_HEAD(&n->notifiers);
> > > > > > +   kref_init(&n->kref);
> > > > > > +   list_add_tail(&n->head, &hdmi_notifiers);
> > > > > > +unlock:
> > > > > > +   mutex_unlock(&hdmi_notifiers_lock);
> > > > > > +   return n;
> > > > > > +}
> > > > > > +EXPORT_SYMBOL_GPL(hdmi_notifier_get);
> > > > > > +
> > > > > > +static void hdmi_notifier_release(struct kref *kref)
> > > > > > +{
> > > > > > +   struct hdmi_notifier *n =
> > > > > > +           container_of(kref, struct hdmi_notifier, kref);
> > > > > > +
> > > > > > +   mutex_lock(&hdmi_notifiers_lock);
> > > > > > +   list_del(&n->head);
> > > > > > +   mutex_unlock(&hdmi_notifiers_lock);
> > > > > > +   kfree(n->edid);
> > > > > > +   kfree(n);
> > > > > > +}
> > > > > > +
> > > > > > +void hdmi_notifier_put(struct hdmi_notifier *n)
> > > > > > +{
> > > > > > +   kref_put(&n->kref, hdmi_notifier_release);
> > > > > > +}
> > > > > > +EXPORT_SYMBOL_GPL(hdmi_notifier_put);
> > > > > > +
> > > > > > +int hdmi_notifier_register(struct hdmi_notifier *n, struct notifier_block *nb)
> > > > > > +{
> > > > > > +   int ret = blocking_notifier_chain_register(&n->notifiers, nb);
> > > > > > +
> > > > > > +   if (ret)
> > > > > > +           return ret;
> > > > > > +   kref_get(&n->kref);
> > > > > > +   mutex_lock(&n->lock);
> > > > > > +   if (n->connected) {
> > > > > > +           blocking_notifier_call_chain(&n->notifiers, HDMI_CONNECTED, n);
> > > > > > +           if (n->edid_size)
> > > > > > +                   blocking_notifier_call_chain(&n->notifiers,
> > > > > > +                                                HDMI_NEW_EDID, n);
> > > > > > +           if (n->has_eld)
> > > > > > +                   blocking_notifier_call_chain(&n->notifiers,
> > > > > > +                                                HDMI_NEW_ELD, n);
> > > > > > +   }
> > > > > > +   mutex_unlock(&n->lock);
> > > > > > +   return 0;
> > > > > > +}
> > > > > > +EXPORT_SYMBOL_GPL(hdmi_notifier_register);
> > > > > > +
> > > > > > +int hdmi_notifier_unregister(struct hdmi_notifier *n, struct notifier_block *nb)
> > > > > > +{
> > > > > > +   int ret = blocking_notifier_chain_unregister(&n->notifiers, nb);
> > > > > > +
> > > > > > +   if (ret == 0)
> > > > > > +           hdmi_notifier_put(n);
> > > > > > +   return ret;
> > > > > > +}
> > > > > > +EXPORT_SYMBOL_GPL(hdmi_notifier_unregister);
> > > > > > +
> > > > > > +void hdmi_event_connect(struct hdmi_notifier *n)
> > > > > > +{
> > > > > > +   mutex_lock(&n->lock);
> > > > > > +   n->connected = true;
> > > > > > +   blocking_notifier_call_chain(&n->notifiers, HDMI_CONNECTED, n);
> > > > > > +   mutex_unlock(&n->lock);
> > > > > > +}
> > > > > > +EXPORT_SYMBOL_GPL(hdmi_event_connect);
> > > > > > +
> > > > > > +void hdmi_event_disconnect(struct hdmi_notifier *n)
> > > > > > +{
> > > > > > +   mutex_lock(&n->lock);
> > > > > > +   n->connected = false;
> > > > > > +   n->has_eld = false;
> > > > > > +   n->edid_size = 0;
> > > > > > +   blocking_notifier_call_chain(&n->notifiers, HDMI_DISCONNECTED, n);
> > > > > > +   mutex_unlock(&n->lock);
> > > > > > +}
> > > > > > +EXPORT_SYMBOL_GPL(hdmi_event_disconnect);
> > > > > > +
> > > > > > +int hdmi_event_new_edid(struct hdmi_notifier *n, const void *edid, size_t size)
> > > > > > +{
> > > > > > +   mutex_lock(&n->lock);
> > > > > > +   if (n->edid_allocated_size < size) {
> > > > > > +           void *p = kmalloc(size, GFP_KERNEL);
> > > > > > +
> > > > > > +           if (!p) {
> > > > > > +                   mutex_unlock(&n->lock);
> > > > > > +                   return -ENOMEM;
> > > > > > +           }
> > > > > > +           kfree(n->edid);
> > > > > > +           n->edid = p;
> > > > > > +           n->edid_allocated_size = size;
> > > > > > +   }
> > > > > > +   memcpy(n->edid, edid, size);
> > > > > > +   n->edid_size = size;
> > > > > > +   blocking_notifier_call_chain(&n->notifiers, HDMI_NEW_EDID, n);
> > > > > > +   mutex_unlock(&n->lock);
> > > > > > +   return 0;
> > > > > > +}
> > > > > > +EXPORT_SYMBOL_GPL(hdmi_event_new_edid);
> > > > > > +
> > > > > > +void hdmi_event_new_eld(struct hdmi_notifier *n, const u8 eld[128])
> > > > > > +{
> > > > > > +   mutex_lock(&n->lock);
> > > > > > +   memcpy(n->eld, eld, sizeof(n->eld));
> > > > > > +   n->has_eld = true;
> > > > > > +   blocking_notifier_call_chain(&n->notifiers, HDMI_NEW_ELD, n);
> > > > > > +   mutex_unlock(&n->lock);
> > > > > > +}
> > > > > > +EXPORT_SYMBOL_GPL(hdmi_event_new_eld);
> > > > > > diff --git a/include/linux/hdmi-notifier.h b/include/linux/hdmi-notifier.h
> > > > > > new file mode 100644
> > > > > > index 000000000000..c8f35110e3e3
> > > > > > --- /dev/null
> > > > > > +++ b/include/linux/hdmi-notifier.h
> > > > > > @@ -0,0 +1,112 @@
> > > > > > +/* SPDX-License-Identifier: GPL-2.0
> > > > > > + * hdmi-notifier.h - notify interested parties of (dis)connect and EDID
> > > > > > + * events
> > > > > > + *
> > > > > > + * Copyright 2016 Russell King <rmk+kernel@arm.linux.org.uk>
> > > > > > + * Copyright 2016 Cisco Systems, Inc. and/or its affiliates.
> > > > > > + * All rights reserved.
> > > > > > + */
> > > > > > +
> > > > > > +#ifndef LINUX_HDMI_NOTIFIER_H
> > > > > > +#define LINUX_HDMI_NOTIFIER_H
> > > > > > +
> > > > > > +#include <linux/types.h>
> > > > > > +#include <linux/notifier.h>
> > > > > > +#include <linux/kref.h>
> > > > > > +
> > > > > > +enum {
> > > > > > +   HDMI_CONNECTED,
> > > > > > +   HDMI_DISCONNECTED,
> > > > > > +   HDMI_NEW_EDID,
> > > > > > +   HDMI_NEW_ELD,
> > > > > > +};
> > > > > > +
> > > > > > +struct device;
> > > > > > +
> > > > > > +struct hdmi_notifier {
> > > > > > +   /* Lock to protect callback registration and notification. */
> > > > > > +   struct mutex lock;
> > > > > > +   struct list_head head;
> > > > > > +   struct kref kref;
> > > > > > +   struct blocking_notifier_head notifiers;
> > > > > > +   struct device *dev;
> > > > > > +
> > > > > > +   /* Current state */
> > > > > > +   unsigned int connected : 1;
> > > > > > +   unsigned int has_eld : 1;
> > > > > > +   unsigned char eld[128];
> > > > > > +   void *edid;
> > > > > > +   size_t edid_size;
> > > > > > +   size_t edid_allocated_size;
> > > > > > +};
> > > > > > +
> > > > > > +/**
> > > > > > + * hdmi_notifier_get - find or create a new hdmi_notifier for the given device.
> > > > > > + * @dev: device that sends the events.
> > > > > > + *
> > > > > > + * If a notifier for device @dev already exists, then increase the refcount
> > > > > > + * and return that notifier.
> > > > > > + *
> > > > > > + * If it doesn't exist, then allocate a new notifier struct and return a
> > > > > > + * pointer to that new struct.
> > > > > > + *
> > > > > > + * Return NULL if the memory could not be allocated.
> > > > > > + */
> > > > > > +struct hdmi_notifier *hdmi_notifier_get(struct device *dev);
> > > > > > +
> > > > > > +/**
> > > > > > + * hdmi_notifier_put - decrease refcount and delete when the refcount reaches 0.
> > > > > > + * @n: notifier
> > > > > > + */
> > > > > > +void hdmi_notifier_put(struct hdmi_notifier *n);
> > > > > > +
> > > > > > +/**
> > > > > > + * hdmi_notifier_register - register the notifier with the notifier_block.
> > > > > > + * @n: the HDMI notifier
> > > > > > + * @nb: the notifier_block
> > > > > > + */
> > > > > > +int hdmi_notifier_register(struct hdmi_notifier *n, struct notifier_block *nb);
> > > > > > +
> > > > > > +/**
> > > > > > + * hdmi_notifier_unregister - unregister the notifier with the notifier_block.
> > > > > > + * @n: the HDMI notifier
> > > > > > + * @nb: the notifier_block
> > > > > > + */
> > > > > > +int hdmi_notifier_unregister(struct hdmi_notifier *n,
> > > > > > +                        struct notifier_block *nb);
> > > > > > +
> > > > > > +/**
> > > > > > + * hdmi_event_connect - send a connect event.
> > > > > > + * @n: the HDMI notifier
> > > > > > + *
> > > > > > + * Send an HDMI_CONNECTED event to any registered parties.
> > > > > > + */
> > > > > > +void hdmi_event_connect(struct hdmi_notifier *n);
> > > > > > +
> > > > > > +/**
> > > > > > + * hdmi_event_disconnect - send a disconnect event.
> > > > > > + * @n: the HDMI notifier
> > > > > > + *
> > > > > > + * Send an HDMI_DISCONNECTED event to any registered parties.
> > > > > > + */
> > > > > > +void hdmi_event_disconnect(struct hdmi_notifier *n);
> > > > > > +
> > > > > > +/**
> > > > > > + * hdmi_event_new_edid - send a new EDID event.
> > > > > > + * @n: the HDMI notifier
> > > > > > + *
> > > > > > + * Send an HDMI_NEW_EDID event to any registered parties.
> > > > > > + * This function will make a copy the EDID so it can return -ENOMEM if
> > > > > > + * no memory could be allocated.
> > > > > > + */
> > > > > > +int hdmi_event_new_edid(struct hdmi_notifier *n, const void *edid, size_t size);
> > > > > > +
> > > > > > +/**
> > > > > > + * hdmi_event_new_eld - send a new ELD event.
> > > > > > + * @n: the HDMI notifier
> > > > > > + *
> > > > > > + * Send an HDMI_NEW_ELD event to any registered parties.
> > > > > > + */
> > > > > > +void hdmi_event_new_eld(struct hdmi_notifier *n, const u8 eld[128]);
> > > > > > +
> > > > > > +#endif
> > > > > >
> > > > >
> > > >
> > > > --
> > > > Daniel Vetter
> > > > Software Engineer, Intel Corporation
> > > > http://blog.ffwll.ch
> >
> > --
> > Daniel Vetter
> > Software Engineer, Intel Corporation
> > http://blog.ffwll.ch

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 1/7] video: add HDMI state notifier support
  2019-06-11 12:10           ` Cheng-yi Chiang
  2019-06-11 12:34             ` Daniel Vetter
@ 2019-06-11 13:10             ` Hans Verkuil
  2019-06-18 11:54               ` Cheng-yi Chiang
  1 sibling, 1 reply; 30+ messages in thread
From: Hans Verkuil @ 2019-06-11 13:10 UTC (permalink / raw)
  To: Cheng-yi Chiang, linux-kernel, Bartlomiej Zolnierkiewicz,
	Greg Kroah-Hartman, Philipp Zabel, Mark Brown, Liam Girdwood,
	Takashi Iwai, Jaroslav Kysela, Russell King, Andrzej Hajda,
	Laurent Pinchart, David Airlie, Rob Herring, Heiko Stuebner,
	Doug Anderson, Dylan Reid, tzungbi, linux-media,
	moderated list:SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEM...,
	dri-devel, linux-arm-kernel, linux-rockchip, devicetree,
	Dariusz Marcinkiewicz
  Cc: Daniel Vetter

On 6/11/19 2:10 PM, Cheng-yi Chiang wrote:
> On Tue, Jun 4, 2019 at 3:24 PM Daniel Vetter <daniel@ffwll.ch> wrote:
>>
>> On Tue, Jun 04, 2019 at 10:32:50AM +0800, Cheng-yi Chiang wrote:
>>> On Mon, Jun 3, 2019 at 4:09 PM Daniel Vetter <daniel@ffwll.ch> wrote:
>>>>
>>>> On Mon, Jun 03, 2019 at 09:45:49AM +0200, Hans Verkuil wrote:
>>>>> On 6/3/19 6:32 AM, Cheng-Yi Chiang wrote:
>>>>>> From: Hans Verkuil <hans.verkuil@cisco.com>
>>>>>>
>>>>>> Add support for HDMI hotplug and EDID notifiers, which is used to convey
>>>>>> information from HDMI drivers to their CEC and audio counterparts.
>>>>>>
>>>>>> Based on an earlier version from Russell King:
>>>>>>
>>>>>> https://patchwork.kernel.org/patch/9277043/
>>>>>>
>>>>>> The hdmi_notifier is a reference counted object containing the HDMI state
>>>>>> of an HDMI device.
>>>>>>
>>>>>> When a new notifier is registered the current state will be reported to
>>>>>> that notifier at registration time.
>>>>>>
>>>>>> Based on Hans Verkuil's patch:
>>>>>>
>>>>>> https://patchwork.kernel.org/patch/9472521/
>>>>>
>>>>> Erm, you are aware that this patch morphed into a CEC-specific notifier
>>>>> found in drivers/media/cec/cec-notifier.c?
>>>>>
>>>>> I don't think it makes sense to have two notifier implementations in the kernel.
>>>>> The original intention was to have the notifier deal with both CEC and ASoC
>>>>> notifications, but there was not enough interest for the ASoC bits at the time
>>>>> and it was dropped.
>>>>>
>>>>> I am planning changes to the cec-notifier API, I hope to work on that this
>>>>> week. I'll CC you when I post those. Those might be a good starting point
>>>>> to convert the cec-notifier to an hdmi-notifier as was originally intended.
>>>>>
>>>>> I've added your colleague Dariusz Marcinkiewicz to the CC list since he's been
>>>>> working on some nice cec-notifier improvements as well.
>>>>
>>>> We also have some interfaces for drm/alsa interactions around hdmi
>>>> already in drm/drm_audio_component.h, but it's not used by anything
>>>> outside of i915. Imo we should extend that, not reinvent a new wheel.
>>>>
>>> Hi Daniel,
>>> Thank you for the pointer. Looking at the ops, it seems that it is
>>> specific to HDA.
>>> I am not familiar with drm and HDA. I am not sure how applicable it
>>> would be to report jack status to ASoC.
>>> There is a use case in sound/soc/codecs/hdac_hdmi.c though so it
>>> should be possible.
>>
>> Currently hda is the only user, but the idea was to make it more generic.
>> Jack status in alsa is what drm calls connector status btw.
>>
>> So if we can take that as a baseline and extend it (probably needs some
>> registration boilerplate and helpers to look up the right endpoint using
>> of/dt for soc systems, we use component.c in i915/hda for this), that
>> would be great I think.
>>
>>>> Another note: notifiers considered evil, imo. Gets the job done for one
>>>> case, as soon as you have multiple devices and need to make sure you get
>>>> the update for the right one it all comes crashing down. Please create an
>>>> api which registers for updates from a specific device only, plus
>>>> something that has real callbacks (like the drm_audio_component.h thing we
>>>> started already).
>>>
>>> To clarify a bit, this hdmi-notifier indeed supports updating from a
>>> specific device only.
>>> hdmi_notifier_get takes a device and return the notifier.
>>
>> Hm I missed that, I thought it's global, so one of my usual notifier
>> concerns addressed.
>>
>>> It seems that a major difference between drm_audio_components and
>>> hdmi-notifier is that
>>> drm_audio_components defines all supported ops in drm_audio_component_audio_ops.
>>> On the other hand, hdmi-notifier passes different events using an enum
>>> like HDMI_CONNECTED and let listener handle different events.
>>> In this regard I agree with you that drm_audio_component is cleaner.
>>> Anyway, I will look into it a bit more and see how it works.
>>
>> Yeah I think if we could combine the approach, i.e. notifier side for
>> registration, some _ops structure for the actual notifications, then
>> there's a solid interface. I just really don't like the opaque void *
>> interface notifier provides, it encourages abuse way too much.
>>
>> Ofc the registration side would then no longer be based on the notifier
>> datastructure, list_head (like cec-notifier.c) of registeres devices with
>> their _ops structure should be enough.
>> -Daniel
> 
> Hi Daniel,
> Yes, I agree the above statement that we should have a more solid interface.
> 
> Hi Hans,
> I am not sure if I missed the patch.

You haven't :-)

> Do you have a estimated timeline for new cec-notifier interface you
> are working on?

I've started work on this, but I to find at least one more full day
to finish it.

Current status is here:

https://git.linuxtv.org/hverkuil/media_tree.git/log/?h=cec-conn

What needs to be changed is that cec-notifier API is split into functions
used by HDMI connectors to register/unregister themselves and functions
used by CEC adapters (and possibly ALSA devices, if you decide to reuse
this API) to do the same.

Right now the same functions (notifier_get/put) are used by both, but that
doesn't scale if we want to have multiple notifiers connected to the same
HDMI drm_connector.

Now, this is done, but the next step is on the CEC side where you need
proper (un)register callbacks that are called when the HDMI connector is
removed. That I still have to implement.

I'd like to finish this some time next week, but I can't promise anything.

> It seems that your PoC patch needs Dariusz's patch to work.
> I would like to seek your advice on whether I can proceed without your
> patch and Dariusz's patch.

If you want to reuse the cec-notifier framework for this as well, then you
need to wait. It is currently not possible to have more than one notifier
for an HDMI connector, and you'll need that.

> 
> I looked through the patch from Dariusz
> 
> https://lkml.org/lkml/2019/5/21/389
> 
> , and saw that you were thinking whether we should use cec-notifier
> for both HDMI and CEC.
> 
> https://lkml.org/lkml/2019/5/24/298
> 
> Could you please let me know your latest thought on whether we should
> reuse cec-notifier?

I don't know :-) I have no experience with ALSA, so I can't tell if generalizing
the CEC notifier is the right approach, or if another approach would be better.

The current design is not quite good enough for what you (or Dariusz, for that
matter) want. What I am working towards is this:

When a new HDMI connector appears, it calls cec_notifier_conn_register (and
_unregister when it is removed).

When a new CEC adapter appears, it calls cec_notifier_cec_adap_(un)register.
The plan is that eventually there may be more than on CEC adapter registered
to the same HDMI connector.

The cec notifier framework will detect when HDMI connectors or CEC adapters
appear/disappear and call the (un)register callbacks of the CEC adapter(s)
accordingly.

And what works for CEC adapters, should also work for ALSA devices.

Obviously, if this framework is extended to ALSA devices, then it needs to
be renamed.

> I agree with you that I should not proceed with hdmi-notifier. Reasons include:
> 1. Method like cec_notifier_parse_hdmi_phandle can be reused. It is
> error prone to memory leak if it is implemented by user, like the
> patch in hdmi-codec.c in this series did not handle the ref count.
> 2. cec-notifier has a simpler implementation of register / unregister
> because there is no call chain. I am not aware of the need for
> hdmi-notifier to support a chain of callbacks. So I think that call
> chain support can be removed.
> 
> If I go ahead and add a new interface to register ops to handle
> connector status report from cec-notifer, based on current
> cec-notifier, do you think that would work ?

No. The cec-notifier doesn't support multiple notifiers connected to
the same HDMI connector device. That's the main limitation that needs
to be lifted first.

> I think it might work if I add another cec_notifier object inside
> dw-hdmi.c, but only for HDMI jack reporting, not for CEC related
> reporting.

That won't work.

For testing you can reuse the current cec-notifier, but now for alsa.
Disable the CEC support so it won't be used for CEC, then hook it up
to the alsa device. That should be good enough to do a proof-of-concept.

> 
> And after some investigation, I realize that my requirement is even
> simpler. I don't need hdmi_event_new_edid and hdmi_event_new_eld in my
> use case.
> I just need to report the connector status from synopsys/dw-hdmi.c to
> codecs/hdmi-codec.c for codec driver to update the jack status.
> Do you think I can proceed in this direction ? Or do you prefer I wait
> for a while and work on it based on your new patch.

You can hack around as described above for testing the idea. If you
really want to use it, then you'll have to wait.

> 
> Thanks a lot!

No problem.

Regards,

	Hans

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 1/7] video: add HDMI state notifier support
  2019-06-11 12:34             ` Daniel Vetter
@ 2019-06-18 11:48               ` Cheng-yi Chiang
  2019-06-18 12:12                 ` Daniel Vetter
  0 siblings, 1 reply; 30+ messages in thread
From: Cheng-yi Chiang @ 2019-06-18 11:48 UTC (permalink / raw)
  To: Cheng-yi Chiang, Hans Verkuil, linux-kernel,
	Bartlomiej Zolnierkiewicz, Greg Kroah-Hartman, Philipp Zabel,
	Mark Brown, Liam Girdwood, Takashi Iwai, Jaroslav Kysela,
	Russell King, Andrzej Hajda, Laurent Pinchart, David Airlie,
	Rob Herring, Heiko Stuebner, Doug Anderson, Dylan Reid, tzungbi,
	linux-media,
	moderated list:SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEM...,
	dri-devel, linux-arm-kernel, linux-rockchip, devicetree,
	Dariusz Marcinkiewicz
  Cc: Daniel Vetter

On Tue, Jun 11, 2019 at 8:35 PM Daniel Vetter <daniel@ffwll.ch> wrote:
>
> On Tue, Jun 11, 2019 at 08:10:38PM +0800, Cheng-yi Chiang wrote:
> > On Tue, Jun 4, 2019 at 3:24 PM Daniel Vetter <daniel@ffwll.ch> wrote:
> > >
> > > On Tue, Jun 04, 2019 at 10:32:50AM +0800, Cheng-yi Chiang wrote:
> > > > On Mon, Jun 3, 2019 at 4:09 PM Daniel Vetter <daniel@ffwll.ch> wrote:
> > > > >
> > > > > On Mon, Jun 03, 2019 at 09:45:49AM +0200, Hans Verkuil wrote:
> > > > > > On 6/3/19 6:32 AM, Cheng-Yi Chiang wrote:
> > > > > > > From: Hans Verkuil <hans.verkuil@cisco.com>
> > > > > > >
> > > > > > > Add support for HDMI hotplug and EDID notifiers, which is used to convey
> > > > > > > information from HDMI drivers to their CEC and audio counterparts.
> > > > > > >
> > > > > > > Based on an earlier version from Russell King:
> > > > > > >
> > > > > > > https://patchwork.kernel.org/patch/9277043/
> > > > > > >
> > > > > > > The hdmi_notifier is a reference counted object containing the HDMI state
> > > > > > > of an HDMI device.
> > > > > > >
> > > > > > > When a new notifier is registered the current state will be reported to
> > > > > > > that notifier at registration time.
> > > > > > >
> > > > > > > Based on Hans Verkuil's patch:
> > > > > > >
> > > > > > > https://patchwork.kernel.org/patch/9472521/
> > > > > >
> > > > > > Erm, you are aware that this patch morphed into a CEC-specific notifier
> > > > > > found in drivers/media/cec/cec-notifier.c?
> > > > > >
> > > > > > I don't think it makes sense to have two notifier implementations in the kernel.
> > > > > > The original intention was to have the notifier deal with both CEC and ASoC
> > > > > > notifications, but there was not enough interest for the ASoC bits at the time
> > > > > > and it was dropped.
> > > > > >
> > > > > > I am planning changes to the cec-notifier API, I hope to work on that this
> > > > > > week. I'll CC you when I post those. Those might be a good starting point
> > > > > > to convert the cec-notifier to an hdmi-notifier as was originally intended.
> > > > > >
> > > > > > I've added your colleague Dariusz Marcinkiewicz to the CC list since he's been
> > > > > > working on some nice cec-notifier improvements as well.
> > > > >
> > > > > We also have some interfaces for drm/alsa interactions around hdmi
> > > > > already in drm/drm_audio_component.h, but it's not used by anything
> > > > > outside of i915. Imo we should extend that, not reinvent a new wheel.
> > > > >
> > > > Hi Daniel,
> > > > Thank you for the pointer. Looking at the ops, it seems that it is
> > > > specific to HDA.
> > > > I am not familiar with drm and HDA. I am not sure how applicable it
> > > > would be to report jack status to ASoC.
> > > > There is a use case in sound/soc/codecs/hdac_hdmi.c though so it
> > > > should be possible.
> > >
> > > Currently hda is the only user, but the idea was to make it more generic.
> > > Jack status in alsa is what drm calls connector status btw.
> > >
> > > So if we can take that as a baseline and extend it (probably needs some
> > > registration boilerplate and helpers to look up the right endpoint using
> > > of/dt for soc systems, we use component.c in i915/hda for this), that
> > > would be great I think.
> > >
> > > > > Another note: notifiers considered evil, imo. Gets the job done for one
> > > > > case, as soon as you have multiple devices and need to make sure you get
> > > > > the update for the right one it all comes crashing down. Please create an
> > > > > api which registers for updates from a specific device only, plus
> > > > > something that has real callbacks (like the drm_audio_component.h thing we
> > > > > started already).
> > > >
> > > > To clarify a bit, this hdmi-notifier indeed supports updating from a
> > > > specific device only.
> > > > hdmi_notifier_get takes a device and return the notifier.
> > >
> > > Hm I missed that, I thought it's global, so one of my usual notifier
> > > concerns addressed.
> > >
> > > > It seems that a major difference between drm_audio_components and
> > > > hdmi-notifier is that
> > > > drm_audio_components defines all supported ops in drm_audio_component_audio_ops.
> > > > On the other hand, hdmi-notifier passes different events using an enum
> > > > like HDMI_CONNECTED and let listener handle different events.
> > > > In this regard I agree with you that drm_audio_component is cleaner.
> > > > Anyway, I will look into it a bit more and see how it works.
> > >
> > > Yeah I think if we could combine the approach, i.e. notifier side for
> > > registration, some _ops structure for the actual notifications, then
> > > there's a solid interface. I just really don't like the opaque void *
> > > interface notifier provides, it encourages abuse way too much.
> > >
> > > Ofc the registration side would then no longer be based on the notifier
> > > datastructure, list_head (like cec-notifier.c) of registeres devices with
> > > their _ops structure should be enough.
> > > -Daniel
> >
> > Hi Daniel,
> > Yes, I agree the above statement that we should have a more solid interface.
> >
> > Hi Hans,
> > I am not sure if I missed the patch.
> > Do you have a estimated timeline for new cec-notifier interface you
> > are working on?
> > It seems that your PoC patch needs Dariusz's patch to work.
> > I would like to seek your advice on whether I can proceed without your
> > patch and Dariusz's patch.
> >
> > I looked through the patch from Dariusz
> >
> > https://lkml.org/lkml/2019/5/21/389
> >
> > , and saw that you were thinking whether we should use cec-notifier
> > for both HDMI and CEC.
> >
> > https://lkml.org/lkml/2019/5/24/298
> >
> > Could you please let me know your latest thought on whether we should
> > reuse cec-notifier?
>
> Nah, see later in that thread, I think cec and audio seem to be different
> use-cases.
>
Ack
> But definitely a good idea to sync with Dariusz, I forgot to pull the two
> threads together. Thanks for doing that.
>
> > I agree with you that I should not proceed with hdmi-notifier. Reasons include:
> > 1. Method like cec_notifier_parse_hdmi_phandle can be reused. It is
> > error prone to memory leak if it is implemented by user, like the
> > patch in hdmi-codec.c in this series did not handle the ref count.
> > 2. cec-notifier has a simpler implementation of register / unregister
> > because there is no call chain. I am not aware of the need for
> > hdmi-notifier to support a chain of callbacks. So I think that call
> > chain support can be removed.
> >
> > If I go ahead and add a new interface to register ops to handle
> > connector status report from cec-notifer, based on current
> > cec-notifier, do you think that would work ?
> > I think it might work if I add another cec_notifier object inside
> > dw-hdmi.c, but only for HDMI jack reporting, not for CEC related
> > reporting.
> >
> > And after some investigation, I realize that my requirement is even
> > simpler. I don't need hdmi_event_new_edid and hdmi_event_new_eld in my
> > use case.
>
> Yeah, connector status is how we started with the drm/alsa interface in
> i915 too, but later on had to extend it. I think eventually we'll need it
> all, that's why I suggested to use that as the interface between drm and
> alsa side, but augmented with some register/unregister and bind logic.
>
Hi Daniel,
Sorry for the late reply.
I spent some time investigating how drm_audio_component works.
The coupling of HDA in drm_audio_component framework makes the
register/unregister logic looks complicated to me as I don't use HDA
in my use case.
After some time, I found another patch series which also use component
framework to communicate between drm and mei world.

https://patchwork.kernel.org/patch/10824527/

And from that patch, I realized that I can follow the similar approach
to register a master component on ALSA side, a slave component on DRM
side, and use device and subcomponent to match them.
I should be able to do this without touching anything specific to HDA.
After that, DRM world should be able to use the ops in
drm_audio_component_audio_ops to notify ALSA world some event when
there is something happen in DRM world.
Currently the ops like pin_eld_notify, pin2port are too specific to HDA.
I think I can add an ops to drm_audio_component_audio_ops to convey
connector status.
I will work toward this approach these days.
If you have other thought please let me know.
Thanks!

> > I just need to report the connector status from synopsys/dw-hdmi.c to
> > codecs/hdmi-codec.c for codec driver to update the jack status.
> > Do you think I can proceed in this direction ? Or do you prefer I wait
> > for a while and work on it based on your new patch.
>
> I think most important part here is that we sync across all the different
> people pushing for better drm/alsa integration. What the solution looks
> like in the end doesn't matter much imo, as long as we don't end up with 3
> different things :-)

Totally agree.
Thanks again!

>
> Cheers, Daniel
>
> >
> > Thanks a lot!
> >
> >
> > >
> > > >
> > > > Thanks again!
> > > >
> > > > > -Daniel
> > > > >
> > > > > >
> > > > > > Regards,
> > > > > >
> > > > > >       Hans
> > > > > >
> > > > > > >
> > > > > > > Modified by Cheng-Yi Chiang:
> > > > > > >  - Add a section in MAINTAINER.
> > > > > > >  - Changes connected and has_eld to bitfield of unsigned int.
> > > > > > >  - Other minor fixes to pass checkpatch.pl --strict checks.
> > > > > > >
> > > > > > > Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
> > > > > > > Acked-by: Philipp Zabel <p.zabel@pengutronix.de>
> > > > > > > Signed-off-by: Cheng-Yi Chiang <cychiang@chromium.org>
> > > > > > > ---
> > > > > > > The original patch is at
> > > > > > > https://lore.kernel.org/linux-arm-kernel/20161213150813.37966-2-hverkuil@xs4all.nl
> > > > > > >
> > > > > > >  MAINTAINERS                   |   6 ++
> > > > > > >  drivers/video/Kconfig         |   3 +
> > > > > > >  drivers/video/Makefile        |   1 +
> > > > > > >  drivers/video/hdmi-notifier.c | 145 ++++++++++++++++++++++++++++++++++
> > > > > > >  include/linux/hdmi-notifier.h | 112 ++++++++++++++++++++++++++
> > > > > > >  5 files changed, 267 insertions(+)
> > > > > > >  create mode 100644 drivers/video/hdmi-notifier.c
> > > > > > >  create mode 100644 include/linux/hdmi-notifier.h
> > > > > > >
> > > > > > > diff --git a/MAINTAINERS b/MAINTAINERS
> > > > > > > index 5cfbea4ce575..ffb7376f9509 100644
> > > > > > > --- a/MAINTAINERS
> > > > > > > +++ b/MAINTAINERS
> > > > > > > @@ -16676,6 +16676,12 @@ W: https://linuxtv.org
> > > > > > >  S: Maintained
> > > > > > >  F: drivers/media/platform/vicodec/*
> > > > > > >
> > > > > > > +VIDEO FRAMEWORK
> > > > > > > +M: Hans Verkuil <hverkuil@xs4all.nl>
> > > > > > > +L: linux-media@vger.kernel.org
> > > > > > > +F: drivers/video/hdmi-notifier.*
> > > > > > > +S: Maintained
> > > > > > > +
> > > > > > >  VIDEO MULTIPLEXER DRIVER
> > > > > > >  M: Philipp Zabel <p.zabel@pengutronix.de>
> > > > > > >  L: linux-media@vger.kernel.org
> > > > > > > diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
> > > > > > > index 83d3d271ca15..000ba9bc0ae7 100644
> > > > > > > --- a/drivers/video/Kconfig
> > > > > > > +++ b/drivers/video/Kconfig
> > > > > > > @@ -34,6 +34,9 @@ config VIDEOMODE_HELPERS
> > > > > > >  config HDMI
> > > > > > >     bool
> > > > > > >
> > > > > > > +config HDMI_NOTIFIERS
> > > > > > > +   bool
> > > > > > > +
> > > > > > >  endif # HAS_IOMEM
> > > > > > >
> > > > > > >  if VT
> > > > > > > diff --git a/drivers/video/Makefile b/drivers/video/Makefile
> > > > > > > index df7650adede9..eff4736102ca 100644
> > > > > > > --- a/drivers/video/Makefile
> > > > > > > +++ b/drivers/video/Makefile
> > > > > > > @@ -1,6 +1,7 @@
> > > > > > >  # SPDX-License-Identifier: GPL-2.0
> > > > > > >  obj-$(CONFIG_VGASTATE)            += vgastate.o
> > > > > > >  obj-$(CONFIG_HDMI)                += hdmi.o
> > > > > > > +obj-$(CONFIG_HDMI_NOTIFIERS)      += hdmi-notifier.o
> > > > > > >
> > > > > > >  obj-$(CONFIG_VT)             += console/
> > > > > > >  obj-$(CONFIG_FB_STI)                 += console/
> > > > > > > diff --git a/drivers/video/hdmi-notifier.c b/drivers/video/hdmi-notifier.c
> > > > > > > new file mode 100644
> > > > > > > index 000000000000..d1eedf661648
> > > > > > > --- /dev/null
> > > > > > > +++ b/drivers/video/hdmi-notifier.c
> > > > > > > @@ -0,0 +1,145 @@
> > > > > > > +// SPDX-License-Identifier: GPL-2.0
> > > > > > > +/* hdmi-notifier.c - notify interested parties of (dis)connect and EDID
> > > > > > > + * events
> > > > > > > + *
> > > > > > > + * Copyright 2016 Russell King <rmk+kernel@arm.linux.org.uk>
> > > > > > > + * Copyright 2016 Cisco Systems, Inc. and/or its affiliates.
> > > > > > > + * All rights reserved.
> > > > > > > + */
> > > > > > > +
> > > > > > > +#include <linux/export.h>
> > > > > > > +#include <linux/hdmi-notifier.h>
> > > > > > > +#include <linux/string.h>
> > > > > > > +#include <linux/slab.h>
> > > > > > > +#include <linux/list.h>
> > > > > > > +
> > > > > > > +static LIST_HEAD(hdmi_notifiers);
> > > > > > > +static DEFINE_MUTEX(hdmi_notifiers_lock);
> > > > > > > +
> > > > > > > +struct hdmi_notifier *hdmi_notifier_get(struct device *dev)
> > > > > > > +{
> > > > > > > +   struct hdmi_notifier *n;
> > > > > > > +
> > > > > > > +   mutex_lock(&hdmi_notifiers_lock);
> > > > > > > +   list_for_each_entry(n, &hdmi_notifiers, head) {
> > > > > > > +           if (n->dev == dev) {
> > > > > > > +                   mutex_unlock(&hdmi_notifiers_lock);
> > > > > > > +                   kref_get(&n->kref);
> > > > > > > +                   return n;
> > > > > > > +           }
> > > > > > > +   }
> > > > > > > +   n = kzalloc(sizeof(*n), GFP_KERNEL);
> > > > > > > +   if (!n)
> > > > > > > +           goto unlock;
> > > > > > > +   n->dev = dev;
> > > > > > > +   mutex_init(&n->lock);
> > > > > > > +   BLOCKING_INIT_NOTIFIER_HEAD(&n->notifiers);
> > > > > > > +   kref_init(&n->kref);
> > > > > > > +   list_add_tail(&n->head, &hdmi_notifiers);
> > > > > > > +unlock:
> > > > > > > +   mutex_unlock(&hdmi_notifiers_lock);
> > > > > > > +   return n;
> > > > > > > +}
> > > > > > > +EXPORT_SYMBOL_GPL(hdmi_notifier_get);
> > > > > > > +
> > > > > > > +static void hdmi_notifier_release(struct kref *kref)
> > > > > > > +{
> > > > > > > +   struct hdmi_notifier *n =
> > > > > > > +           container_of(kref, struct hdmi_notifier, kref);
> > > > > > > +
> > > > > > > +   mutex_lock(&hdmi_notifiers_lock);
> > > > > > > +   list_del(&n->head);
> > > > > > > +   mutex_unlock(&hdmi_notifiers_lock);
> > > > > > > +   kfree(n->edid);
> > > > > > > +   kfree(n);
> > > > > > > +}
> > > > > > > +
> > > > > > > +void hdmi_notifier_put(struct hdmi_notifier *n)
> > > > > > > +{
> > > > > > > +   kref_put(&n->kref, hdmi_notifier_release);
> > > > > > > +}
> > > > > > > +EXPORT_SYMBOL_GPL(hdmi_notifier_put);
> > > > > > > +
> > > > > > > +int hdmi_notifier_register(struct hdmi_notifier *n, struct notifier_block *nb)
> > > > > > > +{
> > > > > > > +   int ret = blocking_notifier_chain_register(&n->notifiers, nb);
> > > > > > > +
> > > > > > > +   if (ret)
> > > > > > > +           return ret;
> > > > > > > +   kref_get(&n->kref);
> > > > > > > +   mutex_lock(&n->lock);
> > > > > > > +   if (n->connected) {
> > > > > > > +           blocking_notifier_call_chain(&n->notifiers, HDMI_CONNECTED, n);
> > > > > > > +           if (n->edid_size)
> > > > > > > +                   blocking_notifier_call_chain(&n->notifiers,
> > > > > > > +                                                HDMI_NEW_EDID, n);
> > > > > > > +           if (n->has_eld)
> > > > > > > +                   blocking_notifier_call_chain(&n->notifiers,
> > > > > > > +                                                HDMI_NEW_ELD, n);
> > > > > > > +   }
> > > > > > > +   mutex_unlock(&n->lock);
> > > > > > > +   return 0;
> > > > > > > +}
> > > > > > > +EXPORT_SYMBOL_GPL(hdmi_notifier_register);
> > > > > > > +
> > > > > > > +int hdmi_notifier_unregister(struct hdmi_notifier *n, struct notifier_block *nb)
> > > > > > > +{
> > > > > > > +   int ret = blocking_notifier_chain_unregister(&n->notifiers, nb);
> > > > > > > +
> > > > > > > +   if (ret == 0)
> > > > > > > +           hdmi_notifier_put(n);
> > > > > > > +   return ret;
> > > > > > > +}
> > > > > > > +EXPORT_SYMBOL_GPL(hdmi_notifier_unregister);
> > > > > > > +
> > > > > > > +void hdmi_event_connect(struct hdmi_notifier *n)
> > > > > > > +{
> > > > > > > +   mutex_lock(&n->lock);
> > > > > > > +   n->connected = true;
> > > > > > > +   blocking_notifier_call_chain(&n->notifiers, HDMI_CONNECTED, n);
> > > > > > > +   mutex_unlock(&n->lock);
> > > > > > > +}
> > > > > > > +EXPORT_SYMBOL_GPL(hdmi_event_connect);
> > > > > > > +
> > > > > > > +void hdmi_event_disconnect(struct hdmi_notifier *n)
> > > > > > > +{
> > > > > > > +   mutex_lock(&n->lock);
> > > > > > > +   n->connected = false;
> > > > > > > +   n->has_eld = false;
> > > > > > > +   n->edid_size = 0;
> > > > > > > +   blocking_notifier_call_chain(&n->notifiers, HDMI_DISCONNECTED, n);
> > > > > > > +   mutex_unlock(&n->lock);
> > > > > > > +}
> > > > > > > +EXPORT_SYMBOL_GPL(hdmi_event_disconnect);
> > > > > > > +
> > > > > > > +int hdmi_event_new_edid(struct hdmi_notifier *n, const void *edid, size_t size)
> > > > > > > +{
> > > > > > > +   mutex_lock(&n->lock);
> > > > > > > +   if (n->edid_allocated_size < size) {
> > > > > > > +           void *p = kmalloc(size, GFP_KERNEL);
> > > > > > > +
> > > > > > > +           if (!p) {
> > > > > > > +                   mutex_unlock(&n->lock);
> > > > > > > +                   return -ENOMEM;
> > > > > > > +           }
> > > > > > > +           kfree(n->edid);
> > > > > > > +           n->edid = p;
> > > > > > > +           n->edid_allocated_size = size;
> > > > > > > +   }
> > > > > > > +   memcpy(n->edid, edid, size);
> > > > > > > +   n->edid_size = size;
> > > > > > > +   blocking_notifier_call_chain(&n->notifiers, HDMI_NEW_EDID, n);
> > > > > > > +   mutex_unlock(&n->lock);
> > > > > > > +   return 0;
> > > > > > > +}
> > > > > > > +EXPORT_SYMBOL_GPL(hdmi_event_new_edid);
> > > > > > > +
> > > > > > > +void hdmi_event_new_eld(struct hdmi_notifier *n, const u8 eld[128])
> > > > > > > +{
> > > > > > > +   mutex_lock(&n->lock);
> > > > > > > +   memcpy(n->eld, eld, sizeof(n->eld));
> > > > > > > +   n->has_eld = true;
> > > > > > > +   blocking_notifier_call_chain(&n->notifiers, HDMI_NEW_ELD, n);
> > > > > > > +   mutex_unlock(&n->lock);
> > > > > > > +}
> > > > > > > +EXPORT_SYMBOL_GPL(hdmi_event_new_eld);
> > > > > > > diff --git a/include/linux/hdmi-notifier.h b/include/linux/hdmi-notifier.h
> > > > > > > new file mode 100644
> > > > > > > index 000000000000..c8f35110e3e3
> > > > > > > --- /dev/null
> > > > > > > +++ b/include/linux/hdmi-notifier.h
> > > > > > > @@ -0,0 +1,112 @@
> > > > > > > +/* SPDX-License-Identifier: GPL-2.0
> > > > > > > + * hdmi-notifier.h - notify interested parties of (dis)connect and EDID
> > > > > > > + * events
> > > > > > > + *
> > > > > > > + * Copyright 2016 Russell King <rmk+kernel@arm.linux.org.uk>
> > > > > > > + * Copyright 2016 Cisco Systems, Inc. and/or its affiliates.
> > > > > > > + * All rights reserved.
> > > > > > > + */
> > > > > > > +
> > > > > > > +#ifndef LINUX_HDMI_NOTIFIER_H
> > > > > > > +#define LINUX_HDMI_NOTIFIER_H
> > > > > > > +
> > > > > > > +#include <linux/types.h>
> > > > > > > +#include <linux/notifier.h>
> > > > > > > +#include <linux/kref.h>
> > > > > > > +
> > > > > > > +enum {
> > > > > > > +   HDMI_CONNECTED,
> > > > > > > +   HDMI_DISCONNECTED,
> > > > > > > +   HDMI_NEW_EDID,
> > > > > > > +   HDMI_NEW_ELD,
> > > > > > > +};
> > > > > > > +
> > > > > > > +struct device;
> > > > > > > +
> > > > > > > +struct hdmi_notifier {
> > > > > > > +   /* Lock to protect callback registration and notification. */
> > > > > > > +   struct mutex lock;
> > > > > > > +   struct list_head head;
> > > > > > > +   struct kref kref;
> > > > > > > +   struct blocking_notifier_head notifiers;
> > > > > > > +   struct device *dev;
> > > > > > > +
> > > > > > > +   /* Current state */
> > > > > > > +   unsigned int connected : 1;
> > > > > > > +   unsigned int has_eld : 1;
> > > > > > > +   unsigned char eld[128];
> > > > > > > +   void *edid;
> > > > > > > +   size_t edid_size;
> > > > > > > +   size_t edid_allocated_size;
> > > > > > > +};
> > > > > > > +
> > > > > > > +/**
> > > > > > > + * hdmi_notifier_get - find or create a new hdmi_notifier for the given device.
> > > > > > > + * @dev: device that sends the events.
> > > > > > > + *
> > > > > > > + * If a notifier for device @dev already exists, then increase the refcount
> > > > > > > + * and return that notifier.
> > > > > > > + *
> > > > > > > + * If it doesn't exist, then allocate a new notifier struct and return a
> > > > > > > + * pointer to that new struct.
> > > > > > > + *
> > > > > > > + * Return NULL if the memory could not be allocated.
> > > > > > > + */
> > > > > > > +struct hdmi_notifier *hdmi_notifier_get(struct device *dev);
> > > > > > > +
> > > > > > > +/**
> > > > > > > + * hdmi_notifier_put - decrease refcount and delete when the refcount reaches 0.
> > > > > > > + * @n: notifier
> > > > > > > + */
> > > > > > > +void hdmi_notifier_put(struct hdmi_notifier *n);
> > > > > > > +
> > > > > > > +/**
> > > > > > > + * hdmi_notifier_register - register the notifier with the notifier_block.
> > > > > > > + * @n: the HDMI notifier
> > > > > > > + * @nb: the notifier_block
> > > > > > > + */
> > > > > > > +int hdmi_notifier_register(struct hdmi_notifier *n, struct notifier_block *nb);
> > > > > > > +
> > > > > > > +/**
> > > > > > > + * hdmi_notifier_unregister - unregister the notifier with the notifier_block.
> > > > > > > + * @n: the HDMI notifier
> > > > > > > + * @nb: the notifier_block
> > > > > > > + */
> > > > > > > +int hdmi_notifier_unregister(struct hdmi_notifier *n,
> > > > > > > +                        struct notifier_block *nb);
> > > > > > > +
> > > > > > > +/**
> > > > > > > + * hdmi_event_connect - send a connect event.
> > > > > > > + * @n: the HDMI notifier
> > > > > > > + *
> > > > > > > + * Send an HDMI_CONNECTED event to any registered parties.
> > > > > > > + */
> > > > > > > +void hdmi_event_connect(struct hdmi_notifier *n);
> > > > > > > +
> > > > > > > +/**
> > > > > > > + * hdmi_event_disconnect - send a disconnect event.
> > > > > > > + * @n: the HDMI notifier
> > > > > > > + *
> > > > > > > + * Send an HDMI_DISCONNECTED event to any registered parties.
> > > > > > > + */
> > > > > > > +void hdmi_event_disconnect(struct hdmi_notifier *n);
> > > > > > > +
> > > > > > > +/**
> > > > > > > + * hdmi_event_new_edid - send a new EDID event.
> > > > > > > + * @n: the HDMI notifier
> > > > > > > + *
> > > > > > > + * Send an HDMI_NEW_EDID event to any registered parties.
> > > > > > > + * This function will make a copy the EDID so it can return -ENOMEM if
> > > > > > > + * no memory could be allocated.
> > > > > > > + */
> > > > > > > +int hdmi_event_new_edid(struct hdmi_notifier *n, const void *edid, size_t size);
> > > > > > > +
> > > > > > > +/**
> > > > > > > + * hdmi_event_new_eld - send a new ELD event.
> > > > > > > + * @n: the HDMI notifier
> > > > > > > + *
> > > > > > > + * Send an HDMI_NEW_ELD event to any registered parties.
> > > > > > > + */
> > > > > > > +void hdmi_event_new_eld(struct hdmi_notifier *n, const u8 eld[128]);
> > > > > > > +
> > > > > > > +#endif
> > > > > > >
> > > > > >
> > > > >
> > > > > --
> > > > > Daniel Vetter
> > > > > Software Engineer, Intel Corporation
> > > > > http://blog.ffwll.ch
> > >
> > > --
> > > Daniel Vetter
> > > Software Engineer, Intel Corporation
> > > http://blog.ffwll.ch
>
> --
> Daniel Vetter
> Software Engineer, Intel Corporation
> http://blog.ffwll.ch

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 1/7] video: add HDMI state notifier support
  2019-06-11 13:10             ` Hans Verkuil
@ 2019-06-18 11:54               ` Cheng-yi Chiang
  0 siblings, 0 replies; 30+ messages in thread
From: Cheng-yi Chiang @ 2019-06-18 11:54 UTC (permalink / raw)
  To: Hans Verkuil
  Cc: moderated list:SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEM...,
	Heiko Stuebner, Liam Girdwood, David Airlie, dri-devel,
	Takashi Iwai, Andrzej Hajda, Laurent Pinchart, linux-rockchip,
	Dylan Reid, linux-media, devicetree, tzungbi, Daniel Vetter,
	Bartlomiej Zolnierkiewicz, Russell King, Rob Herring,
	Jaroslav Kysela, linux-arm-kernel, Greg Kroah-Hartman,
	Doug Anderson, linux-kernel, Mark Brown, Philipp Zabel,
	Dariusz Marcinkiewicz

On Tue, Jun 11, 2019 at 9:11 PM Hans Verkuil <hverkuil@xs4all.nl> wrote:
>
> On 6/11/19 2:10 PM, Cheng-yi Chiang wrote:
> > On Tue, Jun 4, 2019 at 3:24 PM Daniel Vetter <daniel@ffwll.ch> wrote:
> >>
> >> On Tue, Jun 04, 2019 at 10:32:50AM +0800, Cheng-yi Chiang wrote:
> >>> On Mon, Jun 3, 2019 at 4:09 PM Daniel Vetter <daniel@ffwll.ch> wrote:
> >>>>
> >>>> On Mon, Jun 03, 2019 at 09:45:49AM +0200, Hans Verkuil wrote:
> >>>>> On 6/3/19 6:32 AM, Cheng-Yi Chiang wrote:
> >>>>>> From: Hans Verkuil <hans.verkuil@cisco.com>
> >>>>>>
> >>>>>> Add support for HDMI hotplug and EDID notifiers, which is used to convey
> >>>>>> information from HDMI drivers to their CEC and audio counterparts.
> >>>>>>
> >>>>>> Based on an earlier version from Russell King:
> >>>>>>
> >>>>>> https://patchwork.kernel.org/patch/9277043/
> >>>>>>
> >>>>>> The hdmi_notifier is a reference counted object containing the HDMI state
> >>>>>> of an HDMI device.
> >>>>>>
> >>>>>> When a new notifier is registered the current state will be reported to
> >>>>>> that notifier at registration time.
> >>>>>>
> >>>>>> Based on Hans Verkuil's patch:
> >>>>>>
> >>>>>> https://patchwork.kernel.org/patch/9472521/
> >>>>>
> >>>>> Erm, you are aware that this patch morphed into a CEC-specific notifier
> >>>>> found in drivers/media/cec/cec-notifier.c?
> >>>>>
> >>>>> I don't think it makes sense to have two notifier implementations in the kernel.
> >>>>> The original intention was to have the notifier deal with both CEC and ASoC
> >>>>> notifications, but there was not enough interest for the ASoC bits at the time
> >>>>> and it was dropped.
> >>>>>
> >>>>> I am planning changes to the cec-notifier API, I hope to work on that this
> >>>>> week. I'll CC you when I post those. Those might be a good starting point
> >>>>> to convert the cec-notifier to an hdmi-notifier as was originally intended.
> >>>>>
> >>>>> I've added your colleague Dariusz Marcinkiewicz to the CC list since he's been
> >>>>> working on some nice cec-notifier improvements as well.
> >>>>
> >>>> We also have some interfaces for drm/alsa interactions around hdmi
> >>>> already in drm/drm_audio_component.h, but it's not used by anything
> >>>> outside of i915. Imo we should extend that, not reinvent a new wheel.
> >>>>
> >>> Hi Daniel,
> >>> Thank you for the pointer. Looking at the ops, it seems that it is
> >>> specific to HDA.
> >>> I am not familiar with drm and HDA. I am not sure how applicable it
> >>> would be to report jack status to ASoC.
> >>> There is a use case in sound/soc/codecs/hdac_hdmi.c though so it
> >>> should be possible.
> >>
> >> Currently hda is the only user, but the idea was to make it more generic.
> >> Jack status in alsa is what drm calls connector status btw.
> >>
> >> So if we can take that as a baseline and extend it (probably needs some
> >> registration boilerplate and helpers to look up the right endpoint using
> >> of/dt for soc systems, we use component.c in i915/hda for this), that
> >> would be great I think.
> >>
> >>>> Another note: notifiers considered evil, imo. Gets the job done for one
> >>>> case, as soon as you have multiple devices and need to make sure you get
> >>>> the update for the right one it all comes crashing down. Please create an
> >>>> api which registers for updates from a specific device only, plus
> >>>> something that has real callbacks (like the drm_audio_component.h thing we
> >>>> started already).
> >>>
> >>> To clarify a bit, this hdmi-notifier indeed supports updating from a
> >>> specific device only.
> >>> hdmi_notifier_get takes a device and return the notifier.
> >>
> >> Hm I missed that, I thought it's global, so one of my usual notifier
> >> concerns addressed.
> >>
> >>> It seems that a major difference between drm_audio_components and
> >>> hdmi-notifier is that
> >>> drm_audio_components defines all supported ops in drm_audio_component_audio_ops.
> >>> On the other hand, hdmi-notifier passes different events using an enum
> >>> like HDMI_CONNECTED and let listener handle different events.
> >>> In this regard I agree with you that drm_audio_component is cleaner.
> >>> Anyway, I will look into it a bit more and see how it works.
> >>
> >> Yeah I think if we could combine the approach, i.e. notifier side for
> >> registration, some _ops structure for the actual notifications, then
> >> there's a solid interface. I just really don't like the opaque void *
> >> interface notifier provides, it encourages abuse way too much.
> >>
> >> Ofc the registration side would then no longer be based on the notifier
> >> datastructure, list_head (like cec-notifier.c) of registeres devices with
> >> their _ops structure should be enough.
> >> -Daniel
> >
> > Hi Daniel,
> > Yes, I agree the above statement that we should have a more solid interface.
> >
> > Hi Hans,
> > I am not sure if I missed the patch.
>
> You haven't :-)
>
> > Do you have a estimated timeline for new cec-notifier interface you
> > are working on?
>
> I've started work on this, but I to find at least one more full day
> to finish it.
>
> Current status is here:
>
> https://git.linuxtv.org/hverkuil/media_tree.git/log/?h=cec-conn
>
> What needs to be changed is that cec-notifier API is split into functions
> used by HDMI connectors to register/unregister themselves and functions
> used by CEC adapters (and possibly ALSA devices, if you decide to reuse
> this API) to do the same.
>
> Right now the same functions (notifier_get/put) are used by both, but that
> doesn't scale if we want to have multiple notifiers connected to the same
> HDMI drm_connector.
>
> Now, this is done, but the next step is on the CEC side where you need
> proper (un)register callbacks that are called when the HDMI connector is
> removed. That I still have to implement.
>
> I'd like to finish this some time next week, but I can't promise anything.
>
Hi Hans,
Sorry for the late reply. I have also spent some time digesting your
patch series.
I think your change makes sense for CEC.

> > It seems that your PoC patch needs Dariusz's patch to work.
> > I would like to seek your advice on whether I can proceed without your
> > patch and Dariusz's patch.
>
> If you want to reuse the cec-notifier framework for this as well, then you
> need to wait. It is currently not possible to have more than one notifier
> for an HDMI connector, and you'll need that.
>
> >
> > I looked through the patch from Dariusz
> >
> > https://lkml.org/lkml/2019/5/21/389
> >
> > , and saw that you were thinking whether we should use cec-notifier
> > for both HDMI and CEC.
> >
> > https://lkml.org/lkml/2019/5/24/298
> >
> > Could you please let me know your latest thought on whether we should
> > reuse cec-notifier?
>
> I don't know :-) I have no experience with ALSA, so I can't tell if generalizing
> the CEC notifier is the right approach, or if another approach would be better.
>
> The current design is not quite good enough for what you (or Dariusz, for that
> matter) want. What I am working towards is this:
>
> When a new HDMI connector appears, it calls cec_notifier_conn_register (and
> _unregister when it is removed).
>
> When a new CEC adapter appears, it calls cec_notifier_cec_adap_(un)register.
> The plan is that eventually there may be more than on CEC adapter registered
> to the same HDMI connector.
>
> The cec notifier framework will detect when HDMI connectors or CEC adapters
> appear/disappear and call the (un)register callbacks of the CEC adapter(s)
> accordingly.
>
> And what works for CEC adapters, should also work for ALSA devices.
>
> Obviously, if this framework is extended to ALSA devices, then it needs to
> be renamed.
>

Thank you for the explanation.
I can imagine how this path works.
But as I replied in the previous mail to Daniel, after some
investigation, I would like to try drm_audio_component approach and
see how that goes.
If that does not work out well, I will follow this approach.
Thanks again!

> > I agree with you that I should not proceed with hdmi-notifier. Reasons include:
> > 1. Method like cec_notifier_parse_hdmi_phandle can be reused. It is
> > error prone to memory leak if it is implemented by user, like the
> > patch in hdmi-codec.c in this series did not handle the ref count.
> > 2. cec-notifier has a simpler implementation of register / unregister
> > because there is no call chain. I am not aware of the need for
> > hdmi-notifier to support a chain of callbacks. So I think that call
> > chain support can be removed.
> >
> > If I go ahead and add a new interface to register ops to handle
> > connector status report from cec-notifer, based on current
> > cec-notifier, do you think that would work ?
>
> No. The cec-notifier doesn't support multiple notifiers connected to
> the same HDMI connector device. That's the main limitation that needs
> to be lifted first.
ACK
>
> > I think it might work if I add another cec_notifier object inside
> > dw-hdmi.c, but only for HDMI jack reporting, not for CEC related
> > reporting.
>
> That won't work.
>
> For testing you can reuse the current cec-notifier, but now for alsa.
> Disable the CEC support so it won't be used for CEC, then hook it up
> to the alsa device. That should be good enough to do a proof-of-concept.
>
ACK
> >
> > And after some investigation, I realize that my requirement is even
> > simpler. I don't need hdmi_event_new_edid and hdmi_event_new_eld in my
> > use case.
> > I just need to report the connector status from synopsys/dw-hdmi.c to
> > codecs/hdmi-codec.c for codec driver to update the jack status.
> > Do you think I can proceed in this direction ? Or do you prefer I wait
> > for a while and work on it based on your new patch.
>
> You can hack around as described above for testing the idea. If you
> really want to use it, then you'll have to wait.
>
> >
> > Thanks a lot!
>
> No problem.
>
> Regards,
>
>         Hans

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 1/7] video: add HDMI state notifier support
  2019-06-18 11:48               ` Cheng-yi Chiang
@ 2019-06-18 12:12                 ` Daniel Vetter
  2019-06-19 11:48                   ` Cheng-yi Chiang
  0 siblings, 1 reply; 30+ messages in thread
From: Daniel Vetter @ 2019-06-18 12:12 UTC (permalink / raw)
  To: Cheng-yi Chiang
  Cc: moderated list:SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEM...,
	Heiko Stuebner, Liam Girdwood, David Airlie, dri-devel,
	Takashi Iwai, Hans Verkuil, Andrzej Hajda, Laurent Pinchart,
	linux-rockchip, Dylan Reid, linux-media, devicetree, tzungbi,
	Daniel Vetter, Bartlomiej Zolnierkiewicz, Russell King,
	Rob Herring, Jaroslav Kysela, linux-arm-kernel,
	Greg Kroah-Hartman, Doug Anderson, linux-kernel, Mark Brown,
	Philipp Zabel, Dariusz Marcinkiewicz

On Tue, Jun 18, 2019 at 07:48:06PM +0800, Cheng-yi Chiang wrote:
> On Tue, Jun 11, 2019 at 8:35 PM Daniel Vetter <daniel@ffwll.ch> wrote:
> >
> > On Tue, Jun 11, 2019 at 08:10:38PM +0800, Cheng-yi Chiang wrote:
> > > On Tue, Jun 4, 2019 at 3:24 PM Daniel Vetter <daniel@ffwll.ch> wrote:
> > > >
> > > > On Tue, Jun 04, 2019 at 10:32:50AM +0800, Cheng-yi Chiang wrote:
> > > > > On Mon, Jun 3, 2019 at 4:09 PM Daniel Vetter <daniel@ffwll.ch> wrote:
> > > > > >
> > > > > > On Mon, Jun 03, 2019 at 09:45:49AM +0200, Hans Verkuil wrote:
> > > > > > > On 6/3/19 6:32 AM, Cheng-Yi Chiang wrote:
> > > > > > > > From: Hans Verkuil <hans.verkuil@cisco.com>
> > > > > > > >
> > > > > > > > Add support for HDMI hotplug and EDID notifiers, which is used to convey
> > > > > > > > information from HDMI drivers to their CEC and audio counterparts.
> > > > > > > >
> > > > > > > > Based on an earlier version from Russell King:
> > > > > > > >
> > > > > > > > https://patchwork.kernel.org/patch/9277043/
> > > > > > > >
> > > > > > > > The hdmi_notifier is a reference counted object containing the HDMI state
> > > > > > > > of an HDMI device.
> > > > > > > >
> > > > > > > > When a new notifier is registered the current state will be reported to
> > > > > > > > that notifier at registration time.
> > > > > > > >
> > > > > > > > Based on Hans Verkuil's patch:
> > > > > > > >
> > > > > > > > https://patchwork.kernel.org/patch/9472521/
> > > > > > >
> > > > > > > Erm, you are aware that this patch morphed into a CEC-specific notifier
> > > > > > > found in drivers/media/cec/cec-notifier.c?
> > > > > > >
> > > > > > > I don't think it makes sense to have two notifier implementations in the kernel.
> > > > > > > The original intention was to have the notifier deal with both CEC and ASoC
> > > > > > > notifications, but there was not enough interest for the ASoC bits at the time
> > > > > > > and it was dropped.
> > > > > > >
> > > > > > > I am planning changes to the cec-notifier API, I hope to work on that this
> > > > > > > week. I'll CC you when I post those. Those might be a good starting point
> > > > > > > to convert the cec-notifier to an hdmi-notifier as was originally intended.
> > > > > > >
> > > > > > > I've added your colleague Dariusz Marcinkiewicz to the CC list since he's been
> > > > > > > working on some nice cec-notifier improvements as well.
> > > > > >
> > > > > > We also have some interfaces for drm/alsa interactions around hdmi
> > > > > > already in drm/drm_audio_component.h, but it's not used by anything
> > > > > > outside of i915. Imo we should extend that, not reinvent a new wheel.
> > > > > >
> > > > > Hi Daniel,
> > > > > Thank you for the pointer. Looking at the ops, it seems that it is
> > > > > specific to HDA.
> > > > > I am not familiar with drm and HDA. I am not sure how applicable it
> > > > > would be to report jack status to ASoC.
> > > > > There is a use case in sound/soc/codecs/hdac_hdmi.c though so it
> > > > > should be possible.
> > > >
> > > > Currently hda is the only user, but the idea was to make it more generic.
> > > > Jack status in alsa is what drm calls connector status btw.
> > > >
> > > > So if we can take that as a baseline and extend it (probably needs some
> > > > registration boilerplate and helpers to look up the right endpoint using
> > > > of/dt for soc systems, we use component.c in i915/hda for this), that
> > > > would be great I think.
> > > >
> > > > > > Another note: notifiers considered evil, imo. Gets the job done for one
> > > > > > case, as soon as you have multiple devices and need to make sure you get
> > > > > > the update for the right one it all comes crashing down. Please create an
> > > > > > api which registers for updates from a specific device only, plus
> > > > > > something that has real callbacks (like the drm_audio_component.h thing we
> > > > > > started already).
> > > > >
> > > > > To clarify a bit, this hdmi-notifier indeed supports updating from a
> > > > > specific device only.
> > > > > hdmi_notifier_get takes a device and return the notifier.
> > > >
> > > > Hm I missed that, I thought it's global, so one of my usual notifier
> > > > concerns addressed.
> > > >
> > > > > It seems that a major difference between drm_audio_components and
> > > > > hdmi-notifier is that
> > > > > drm_audio_components defines all supported ops in drm_audio_component_audio_ops.
> > > > > On the other hand, hdmi-notifier passes different events using an enum
> > > > > like HDMI_CONNECTED and let listener handle different events.
> > > > > In this regard I agree with you that drm_audio_component is cleaner.
> > > > > Anyway, I will look into it a bit more and see how it works.
> > > >
> > > > Yeah I think if we could combine the approach, i.e. notifier side for
> > > > registration, some _ops structure for the actual notifications, then
> > > > there's a solid interface. I just really don't like the opaque void *
> > > > interface notifier provides, it encourages abuse way too much.
> > > >
> > > > Ofc the registration side would then no longer be based on the notifier
> > > > datastructure, list_head (like cec-notifier.c) of registeres devices with
> > > > their _ops structure should be enough.
> > > > -Daniel
> > >
> > > Hi Daniel,
> > > Yes, I agree the above statement that we should have a more solid interface.
> > >
> > > Hi Hans,
> > > I am not sure if I missed the patch.
> > > Do you have a estimated timeline for new cec-notifier interface you
> > > are working on?
> > > It seems that your PoC patch needs Dariusz's patch to work.
> > > I would like to seek your advice on whether I can proceed without your
> > > patch and Dariusz's patch.
> > >
> > > I looked through the patch from Dariusz
> > >
> > > https://lkml.org/lkml/2019/5/21/389
> > >
> > > , and saw that you were thinking whether we should use cec-notifier
> > > for both HDMI and CEC.
> > >
> > > https://lkml.org/lkml/2019/5/24/298
> > >
> > > Could you please let me know your latest thought on whether we should
> > > reuse cec-notifier?
> >
> > Nah, see later in that thread, I think cec and audio seem to be different
> > use-cases.
> >
> Ack
> > But definitely a good idea to sync with Dariusz, I forgot to pull the two
> > threads together. Thanks for doing that.
> >
> > > I agree with you that I should not proceed with hdmi-notifier. Reasons include:
> > > 1. Method like cec_notifier_parse_hdmi_phandle can be reused. It is
> > > error prone to memory leak if it is implemented by user, like the
> > > patch in hdmi-codec.c in this series did not handle the ref count.
> > > 2. cec-notifier has a simpler implementation of register / unregister
> > > because there is no call chain. I am not aware of the need for
> > > hdmi-notifier to support a chain of callbacks. So I think that call
> > > chain support can be removed.
> > >
> > > If I go ahead and add a new interface to register ops to handle
> > > connector status report from cec-notifer, based on current
> > > cec-notifier, do you think that would work ?
> > > I think it might work if I add another cec_notifier object inside
> > > dw-hdmi.c, but only for HDMI jack reporting, not for CEC related
> > > reporting.
> > >
> > > And after some investigation, I realize that my requirement is even
> > > simpler. I don't need hdmi_event_new_edid and hdmi_event_new_eld in my
> > > use case.
> >
> > Yeah, connector status is how we started with the drm/alsa interface in
> > i915 too, but later on had to extend it. I think eventually we'll need it
> > all, that's why I suggested to use that as the interface between drm and
> > alsa side, but augmented with some register/unregister and bind logic.
> >
> Hi Daniel,
> Sorry for the late reply.
> I spent some time investigating how drm_audio_component works.
> The coupling of HDA in drm_audio_component framework makes the
> register/unregister logic looks complicated to me as I don't use HDA
> in my use case.
> After some time, I found another patch series which also use component
> framework to communicate between drm and mei world.
> 
> https://patchwork.kernel.org/patch/10824527/
> 
> And from that patch, I realized that I can follow the similar approach
> to register a master component on ALSA side, a slave component on DRM
> side, and use device and subcomponent to match them.

Sorry for the confusion here. My suggestion is _not_ to use the component
framework. That's only meant for one-off special case solutions. For that
part I think you need to build a new register/unregister/bind/unbind
infrastructure, like we have for lots of other things in the kernel
already (clocks, gpio, drm_panel, drm_bridge as just a few examples).

My suggestion with the i915/hda interface is to build on the actual
interface for signalling connector status and exchanging eld and stuff
like that.

> I should be able to do this without touching anything specific to HDA.
> After that, DRM world should be able to use the ops in
> drm_audio_component_audio_ops to notify ALSA world some event when
> there is something happen in DRM world.
> Currently the ops like pin_eld_notify, pin2port are too specific to HDA.
> I think I can add an ops to drm_audio_component_audio_ops to convey
> connector status.

Hm why? The pin2port is maybe not the best one, since port is an intel
construct, and pin a hda construct. So we'd need to change those to talk
in terms of the higher-level concepts (alsa output pin and drm crtc
probably).

The other stuff should work a bit better. Either way my idea was to evolve
that interface (and put in the place the required type-casting for
i915/hda), since more users increases the odds that it actually is a good
design.

> I will work toward this approach these days.
> If you have other thought please let me know.
> Thanks!
> 
> > > I just need to report the connector status from synopsys/dw-hdmi.c to
> > > codecs/hdmi-codec.c for codec driver to update the jack status.
> > > Do you think I can proceed in this direction ? Or do you prefer I wait
> > > for a while and work on it based on your new patch.
> >
> > I think most important part here is that we sync across all the different
> > people pushing for better drm/alsa integration. What the solution looks
> > like in the end doesn't matter much imo, as long as we don't end up with 3
> > different things :-)
> 
> Totally agree.

Anyway just my thoughts, let's keep chatting.

Cheers, Daniel

> Thanks again!
> 
> >
> > Cheers, Daniel
> >
> > >
> > > Thanks a lot!
> > >
> > >
> > > >
> > > > >
> > > > > Thanks again!
> > > > >
> > > > > > -Daniel
> > > > > >
> > > > > > >
> > > > > > > Regards,
> > > > > > >
> > > > > > >       Hans
> > > > > > >
> > > > > > > >
> > > > > > > > Modified by Cheng-Yi Chiang:
> > > > > > > >  - Add a section in MAINTAINER.
> > > > > > > >  - Changes connected and has_eld to bitfield of unsigned int.
> > > > > > > >  - Other minor fixes to pass checkpatch.pl --strict checks.
> > > > > > > >
> > > > > > > > Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
> > > > > > > > Acked-by: Philipp Zabel <p.zabel@pengutronix.de>
> > > > > > > > Signed-off-by: Cheng-Yi Chiang <cychiang@chromium.org>
> > > > > > > > ---
> > > > > > > > The original patch is at
> > > > > > > > https://lore.kernel.org/linux-arm-kernel/20161213150813.37966-2-hverkuil@xs4all.nl
> > > > > > > >
> > > > > > > >  MAINTAINERS                   |   6 ++
> > > > > > > >  drivers/video/Kconfig         |   3 +
> > > > > > > >  drivers/video/Makefile        |   1 +
> > > > > > > >  drivers/video/hdmi-notifier.c | 145 ++++++++++++++++++++++++++++++++++
> > > > > > > >  include/linux/hdmi-notifier.h | 112 ++++++++++++++++++++++++++
> > > > > > > >  5 files changed, 267 insertions(+)
> > > > > > > >  create mode 100644 drivers/video/hdmi-notifier.c
> > > > > > > >  create mode 100644 include/linux/hdmi-notifier.h
> > > > > > > >
> > > > > > > > diff --git a/MAINTAINERS b/MAINTAINERS
> > > > > > > > index 5cfbea4ce575..ffb7376f9509 100644
> > > > > > > > --- a/MAINTAINERS
> > > > > > > > +++ b/MAINTAINERS
> > > > > > > > @@ -16676,6 +16676,12 @@ W: https://linuxtv.org
> > > > > > > >  S: Maintained
> > > > > > > >  F: drivers/media/platform/vicodec/*
> > > > > > > >
> > > > > > > > +VIDEO FRAMEWORK
> > > > > > > > +M: Hans Verkuil <hverkuil@xs4all.nl>
> > > > > > > > +L: linux-media@vger.kernel.org
> > > > > > > > +F: drivers/video/hdmi-notifier.*
> > > > > > > > +S: Maintained
> > > > > > > > +
> > > > > > > >  VIDEO MULTIPLEXER DRIVER
> > > > > > > >  M: Philipp Zabel <p.zabel@pengutronix.de>
> > > > > > > >  L: linux-media@vger.kernel.org
> > > > > > > > diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
> > > > > > > > index 83d3d271ca15..000ba9bc0ae7 100644
> > > > > > > > --- a/drivers/video/Kconfig
> > > > > > > > +++ b/drivers/video/Kconfig
> > > > > > > > @@ -34,6 +34,9 @@ config VIDEOMODE_HELPERS
> > > > > > > >  config HDMI
> > > > > > > >     bool
> > > > > > > >
> > > > > > > > +config HDMI_NOTIFIERS
> > > > > > > > +   bool
> > > > > > > > +
> > > > > > > >  endif # HAS_IOMEM
> > > > > > > >
> > > > > > > >  if VT
> > > > > > > > diff --git a/drivers/video/Makefile b/drivers/video/Makefile
> > > > > > > > index df7650adede9..eff4736102ca 100644
> > > > > > > > --- a/drivers/video/Makefile
> > > > > > > > +++ b/drivers/video/Makefile
> > > > > > > > @@ -1,6 +1,7 @@
> > > > > > > >  # SPDX-License-Identifier: GPL-2.0
> > > > > > > >  obj-$(CONFIG_VGASTATE)            += vgastate.o
> > > > > > > >  obj-$(CONFIG_HDMI)                += hdmi.o
> > > > > > > > +obj-$(CONFIG_HDMI_NOTIFIERS)      += hdmi-notifier.o
> > > > > > > >
> > > > > > > >  obj-$(CONFIG_VT)             += console/
> > > > > > > >  obj-$(CONFIG_FB_STI)                 += console/
> > > > > > > > diff --git a/drivers/video/hdmi-notifier.c b/drivers/video/hdmi-notifier.c
> > > > > > > > new file mode 100644
> > > > > > > > index 000000000000..d1eedf661648
> > > > > > > > --- /dev/null
> > > > > > > > +++ b/drivers/video/hdmi-notifier.c
> > > > > > > > @@ -0,0 +1,145 @@
> > > > > > > > +// SPDX-License-Identifier: GPL-2.0
> > > > > > > > +/* hdmi-notifier.c - notify interested parties of (dis)connect and EDID
> > > > > > > > + * events
> > > > > > > > + *
> > > > > > > > + * Copyright 2016 Russell King <rmk+kernel@arm.linux.org.uk>
> > > > > > > > + * Copyright 2016 Cisco Systems, Inc. and/or its affiliates.
> > > > > > > > + * All rights reserved.
> > > > > > > > + */
> > > > > > > > +
> > > > > > > > +#include <linux/export.h>
> > > > > > > > +#include <linux/hdmi-notifier.h>
> > > > > > > > +#include <linux/string.h>
> > > > > > > > +#include <linux/slab.h>
> > > > > > > > +#include <linux/list.h>
> > > > > > > > +
> > > > > > > > +static LIST_HEAD(hdmi_notifiers);
> > > > > > > > +static DEFINE_MUTEX(hdmi_notifiers_lock);
> > > > > > > > +
> > > > > > > > +struct hdmi_notifier *hdmi_notifier_get(struct device *dev)
> > > > > > > > +{
> > > > > > > > +   struct hdmi_notifier *n;
> > > > > > > > +
> > > > > > > > +   mutex_lock(&hdmi_notifiers_lock);
> > > > > > > > +   list_for_each_entry(n, &hdmi_notifiers, head) {
> > > > > > > > +           if (n->dev == dev) {
> > > > > > > > +                   mutex_unlock(&hdmi_notifiers_lock);
> > > > > > > > +                   kref_get(&n->kref);
> > > > > > > > +                   return n;
> > > > > > > > +           }
> > > > > > > > +   }
> > > > > > > > +   n = kzalloc(sizeof(*n), GFP_KERNEL);
> > > > > > > > +   if (!n)
> > > > > > > > +           goto unlock;
> > > > > > > > +   n->dev = dev;
> > > > > > > > +   mutex_init(&n->lock);
> > > > > > > > +   BLOCKING_INIT_NOTIFIER_HEAD(&n->notifiers);
> > > > > > > > +   kref_init(&n->kref);
> > > > > > > > +   list_add_tail(&n->head, &hdmi_notifiers);
> > > > > > > > +unlock:
> > > > > > > > +   mutex_unlock(&hdmi_notifiers_lock);
> > > > > > > > +   return n;
> > > > > > > > +}
> > > > > > > > +EXPORT_SYMBOL_GPL(hdmi_notifier_get);
> > > > > > > > +
> > > > > > > > +static void hdmi_notifier_release(struct kref *kref)
> > > > > > > > +{
> > > > > > > > +   struct hdmi_notifier *n =
> > > > > > > > +           container_of(kref, struct hdmi_notifier, kref);
> > > > > > > > +
> > > > > > > > +   mutex_lock(&hdmi_notifiers_lock);
> > > > > > > > +   list_del(&n->head);
> > > > > > > > +   mutex_unlock(&hdmi_notifiers_lock);
> > > > > > > > +   kfree(n->edid);
> > > > > > > > +   kfree(n);
> > > > > > > > +}
> > > > > > > > +
> > > > > > > > +void hdmi_notifier_put(struct hdmi_notifier *n)
> > > > > > > > +{
> > > > > > > > +   kref_put(&n->kref, hdmi_notifier_release);
> > > > > > > > +}
> > > > > > > > +EXPORT_SYMBOL_GPL(hdmi_notifier_put);
> > > > > > > > +
> > > > > > > > +int hdmi_notifier_register(struct hdmi_notifier *n, struct notifier_block *nb)
> > > > > > > > +{
> > > > > > > > +   int ret = blocking_notifier_chain_register(&n->notifiers, nb);
> > > > > > > > +
> > > > > > > > +   if (ret)
> > > > > > > > +           return ret;
> > > > > > > > +   kref_get(&n->kref);
> > > > > > > > +   mutex_lock(&n->lock);
> > > > > > > > +   if (n->connected) {
> > > > > > > > +           blocking_notifier_call_chain(&n->notifiers, HDMI_CONNECTED, n);
> > > > > > > > +           if (n->edid_size)
> > > > > > > > +                   blocking_notifier_call_chain(&n->notifiers,
> > > > > > > > +                                                HDMI_NEW_EDID, n);
> > > > > > > > +           if (n->has_eld)
> > > > > > > > +                   blocking_notifier_call_chain(&n->notifiers,
> > > > > > > > +                                                HDMI_NEW_ELD, n);
> > > > > > > > +   }
> > > > > > > > +   mutex_unlock(&n->lock);
> > > > > > > > +   return 0;
> > > > > > > > +}
> > > > > > > > +EXPORT_SYMBOL_GPL(hdmi_notifier_register);
> > > > > > > > +
> > > > > > > > +int hdmi_notifier_unregister(struct hdmi_notifier *n, struct notifier_block *nb)
> > > > > > > > +{
> > > > > > > > +   int ret = blocking_notifier_chain_unregister(&n->notifiers, nb);
> > > > > > > > +
> > > > > > > > +   if (ret == 0)
> > > > > > > > +           hdmi_notifier_put(n);
> > > > > > > > +   return ret;
> > > > > > > > +}
> > > > > > > > +EXPORT_SYMBOL_GPL(hdmi_notifier_unregister);
> > > > > > > > +
> > > > > > > > +void hdmi_event_connect(struct hdmi_notifier *n)
> > > > > > > > +{
> > > > > > > > +   mutex_lock(&n->lock);
> > > > > > > > +   n->connected = true;
> > > > > > > > +   blocking_notifier_call_chain(&n->notifiers, HDMI_CONNECTED, n);
> > > > > > > > +   mutex_unlock(&n->lock);
> > > > > > > > +}
> > > > > > > > +EXPORT_SYMBOL_GPL(hdmi_event_connect);
> > > > > > > > +
> > > > > > > > +void hdmi_event_disconnect(struct hdmi_notifier *n)
> > > > > > > > +{
> > > > > > > > +   mutex_lock(&n->lock);
> > > > > > > > +   n->connected = false;
> > > > > > > > +   n->has_eld = false;
> > > > > > > > +   n->edid_size = 0;
> > > > > > > > +   blocking_notifier_call_chain(&n->notifiers, HDMI_DISCONNECTED, n);
> > > > > > > > +   mutex_unlock(&n->lock);
> > > > > > > > +}
> > > > > > > > +EXPORT_SYMBOL_GPL(hdmi_event_disconnect);
> > > > > > > > +
> > > > > > > > +int hdmi_event_new_edid(struct hdmi_notifier *n, const void *edid, size_t size)
> > > > > > > > +{
> > > > > > > > +   mutex_lock(&n->lock);
> > > > > > > > +   if (n->edid_allocated_size < size) {
> > > > > > > > +           void *p = kmalloc(size, GFP_KERNEL);
> > > > > > > > +
> > > > > > > > +           if (!p) {
> > > > > > > > +                   mutex_unlock(&n->lock);
> > > > > > > > +                   return -ENOMEM;
> > > > > > > > +           }
> > > > > > > > +           kfree(n->edid);
> > > > > > > > +           n->edid = p;
> > > > > > > > +           n->edid_allocated_size = size;
> > > > > > > > +   }
> > > > > > > > +   memcpy(n->edid, edid, size);
> > > > > > > > +   n->edid_size = size;
> > > > > > > > +   blocking_notifier_call_chain(&n->notifiers, HDMI_NEW_EDID, n);
> > > > > > > > +   mutex_unlock(&n->lock);
> > > > > > > > +   return 0;
> > > > > > > > +}
> > > > > > > > +EXPORT_SYMBOL_GPL(hdmi_event_new_edid);
> > > > > > > > +
> > > > > > > > +void hdmi_event_new_eld(struct hdmi_notifier *n, const u8 eld[128])
> > > > > > > > +{
> > > > > > > > +   mutex_lock(&n->lock);
> > > > > > > > +   memcpy(n->eld, eld, sizeof(n->eld));
> > > > > > > > +   n->has_eld = true;
> > > > > > > > +   blocking_notifier_call_chain(&n->notifiers, HDMI_NEW_ELD, n);
> > > > > > > > +   mutex_unlock(&n->lock);
> > > > > > > > +}
> > > > > > > > +EXPORT_SYMBOL_GPL(hdmi_event_new_eld);
> > > > > > > > diff --git a/include/linux/hdmi-notifier.h b/include/linux/hdmi-notifier.h
> > > > > > > > new file mode 100644
> > > > > > > > index 000000000000..c8f35110e3e3
> > > > > > > > --- /dev/null
> > > > > > > > +++ b/include/linux/hdmi-notifier.h
> > > > > > > > @@ -0,0 +1,112 @@
> > > > > > > > +/* SPDX-License-Identifier: GPL-2.0
> > > > > > > > + * hdmi-notifier.h - notify interested parties of (dis)connect and EDID
> > > > > > > > + * events
> > > > > > > > + *
> > > > > > > > + * Copyright 2016 Russell King <rmk+kernel@arm.linux.org.uk>
> > > > > > > > + * Copyright 2016 Cisco Systems, Inc. and/or its affiliates.
> > > > > > > > + * All rights reserved.
> > > > > > > > + */
> > > > > > > > +
> > > > > > > > +#ifndef LINUX_HDMI_NOTIFIER_H
> > > > > > > > +#define LINUX_HDMI_NOTIFIER_H
> > > > > > > > +
> > > > > > > > +#include <linux/types.h>
> > > > > > > > +#include <linux/notifier.h>
> > > > > > > > +#include <linux/kref.h>
> > > > > > > > +
> > > > > > > > +enum {
> > > > > > > > +   HDMI_CONNECTED,
> > > > > > > > +   HDMI_DISCONNECTED,
> > > > > > > > +   HDMI_NEW_EDID,
> > > > > > > > +   HDMI_NEW_ELD,
> > > > > > > > +};
> > > > > > > > +
> > > > > > > > +struct device;
> > > > > > > > +
> > > > > > > > +struct hdmi_notifier {
> > > > > > > > +   /* Lock to protect callback registration and notification. */
> > > > > > > > +   struct mutex lock;
> > > > > > > > +   struct list_head head;
> > > > > > > > +   struct kref kref;
> > > > > > > > +   struct blocking_notifier_head notifiers;
> > > > > > > > +   struct device *dev;
> > > > > > > > +
> > > > > > > > +   /* Current state */
> > > > > > > > +   unsigned int connected : 1;
> > > > > > > > +   unsigned int has_eld : 1;
> > > > > > > > +   unsigned char eld[128];
> > > > > > > > +   void *edid;
> > > > > > > > +   size_t edid_size;
> > > > > > > > +   size_t edid_allocated_size;
> > > > > > > > +};
> > > > > > > > +
> > > > > > > > +/**
> > > > > > > > + * hdmi_notifier_get - find or create a new hdmi_notifier for the given device.
> > > > > > > > + * @dev: device that sends the events.
> > > > > > > > + *
> > > > > > > > + * If a notifier for device @dev already exists, then increase the refcount
> > > > > > > > + * and return that notifier.
> > > > > > > > + *
> > > > > > > > + * If it doesn't exist, then allocate a new notifier struct and return a
> > > > > > > > + * pointer to that new struct.
> > > > > > > > + *
> > > > > > > > + * Return NULL if the memory could not be allocated.
> > > > > > > > + */
> > > > > > > > +struct hdmi_notifier *hdmi_notifier_get(struct device *dev);
> > > > > > > > +
> > > > > > > > +/**
> > > > > > > > + * hdmi_notifier_put - decrease refcount and delete when the refcount reaches 0.
> > > > > > > > + * @n: notifier
> > > > > > > > + */
> > > > > > > > +void hdmi_notifier_put(struct hdmi_notifier *n);
> > > > > > > > +
> > > > > > > > +/**
> > > > > > > > + * hdmi_notifier_register - register the notifier with the notifier_block.
> > > > > > > > + * @n: the HDMI notifier
> > > > > > > > + * @nb: the notifier_block
> > > > > > > > + */
> > > > > > > > +int hdmi_notifier_register(struct hdmi_notifier *n, struct notifier_block *nb);
> > > > > > > > +
> > > > > > > > +/**
> > > > > > > > + * hdmi_notifier_unregister - unregister the notifier with the notifier_block.
> > > > > > > > + * @n: the HDMI notifier
> > > > > > > > + * @nb: the notifier_block
> > > > > > > > + */
> > > > > > > > +int hdmi_notifier_unregister(struct hdmi_notifier *n,
> > > > > > > > +                        struct notifier_block *nb);
> > > > > > > > +
> > > > > > > > +/**
> > > > > > > > + * hdmi_event_connect - send a connect event.
> > > > > > > > + * @n: the HDMI notifier
> > > > > > > > + *
> > > > > > > > + * Send an HDMI_CONNECTED event to any registered parties.
> > > > > > > > + */
> > > > > > > > +void hdmi_event_connect(struct hdmi_notifier *n);
> > > > > > > > +
> > > > > > > > +/**
> > > > > > > > + * hdmi_event_disconnect - send a disconnect event.
> > > > > > > > + * @n: the HDMI notifier
> > > > > > > > + *
> > > > > > > > + * Send an HDMI_DISCONNECTED event to any registered parties.
> > > > > > > > + */
> > > > > > > > +void hdmi_event_disconnect(struct hdmi_notifier *n);
> > > > > > > > +
> > > > > > > > +/**
> > > > > > > > + * hdmi_event_new_edid - send a new EDID event.
> > > > > > > > + * @n: the HDMI notifier
> > > > > > > > + *
> > > > > > > > + * Send an HDMI_NEW_EDID event to any registered parties.
> > > > > > > > + * This function will make a copy the EDID so it can return -ENOMEM if
> > > > > > > > + * no memory could be allocated.
> > > > > > > > + */
> > > > > > > > +int hdmi_event_new_edid(struct hdmi_notifier *n, const void *edid, size_t size);
> > > > > > > > +
> > > > > > > > +/**
> > > > > > > > + * hdmi_event_new_eld - send a new ELD event.
> > > > > > > > + * @n: the HDMI notifier
> > > > > > > > + *
> > > > > > > > + * Send an HDMI_NEW_ELD event to any registered parties.
> > > > > > > > + */
> > > > > > > > +void hdmi_event_new_eld(struct hdmi_notifier *n, const u8 eld[128]);
> > > > > > > > +
> > > > > > > > +#endif
> > > > > > > >
> > > > > > >
> > > > > >
> > > > > > --
> > > > > > Daniel Vetter
> > > > > > Software Engineer, Intel Corporation
> > > > > > http://blog.ffwll.ch
> > > >
> > > > --
> > > > Daniel Vetter
> > > > Software Engineer, Intel Corporation
> > > > http://blog.ffwll.ch
> >
> > --
> > Daniel Vetter
> > Software Engineer, Intel Corporation
> > http://blog.ffwll.ch

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 1/7] video: add HDMI state notifier support
  2019-06-18 12:12                 ` Daniel Vetter
@ 2019-06-19 11:48                   ` Cheng-yi Chiang
  2019-06-20  9:25                     ` Daniel Vetter
  0 siblings, 1 reply; 30+ messages in thread
From: Cheng-yi Chiang @ 2019-06-19 11:48 UTC (permalink / raw)
  To: Cheng-yi Chiang, Hans Verkuil, linux-kernel,
	Bartlomiej Zolnierkiewicz, Greg Kroah-Hartman, Philipp Zabel,
	Mark Brown, Liam Girdwood, Takashi Iwai, Jaroslav Kysela,
	Russell King, Andrzej Hajda, Laurent Pinchart, David Airlie,
	Rob Herring, Heiko Stuebner, Doug Anderson, Dylan Reid, tzungbi,
	linux-media,
	moderated list:SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEM...,
	dri-devel, linux-arm-kernel, linux-rockchip, devicetree,
	Dariusz Marcinkiewicz
  Cc: Daniel Vetter

On Tue, Jun 18, 2019 at 8:12 PM Daniel Vetter <daniel@ffwll.ch> wrote:
>
> On Tue, Jun 18, 2019 at 07:48:06PM +0800, Cheng-yi Chiang wrote:
> > On Tue, Jun 11, 2019 at 8:35 PM Daniel Vetter <daniel@ffwll.ch> wrote:
> > >
> > > On Tue, Jun 11, 2019 at 08:10:38PM +0800, Cheng-yi Chiang wrote:
> > > > On Tue, Jun 4, 2019 at 3:24 PM Daniel Vetter <daniel@ffwll.ch> wrote:
> > > > >
> > > > > On Tue, Jun 04, 2019 at 10:32:50AM +0800, Cheng-yi Chiang wrote:
> > > > > > On Mon, Jun 3, 2019 at 4:09 PM Daniel Vetter <daniel@ffwll.ch> wrote:
> > > > > > >
> > > > > > > On Mon, Jun 03, 2019 at 09:45:49AM +0200, Hans Verkuil wrote:
> > > > > > > > On 6/3/19 6:32 AM, Cheng-Yi Chiang wrote:
> > > > > > > > > From: Hans Verkuil <hans.verkuil@cisco.com>
> > > > > > > > >
> > > > > > > > > Add support for HDMI hotplug and EDID notifiers, which is used to convey
> > > > > > > > > information from HDMI drivers to their CEC and audio counterparts.
> > > > > > > > >
> > > > > > > > > Based on an earlier version from Russell King:
> > > > > > > > >
> > > > > > > > > https://patchwork.kernel.org/patch/9277043/
> > > > > > > > >
> > > > > > > > > The hdmi_notifier is a reference counted object containing the HDMI state
> > > > > > > > > of an HDMI device.
> > > > > > > > >
> > > > > > > > > When a new notifier is registered the current state will be reported to
> > > > > > > > > that notifier at registration time.
> > > > > > > > >
> > > > > > > > > Based on Hans Verkuil's patch:
> > > > > > > > >
> > > > > > > > > https://patchwork.kernel.org/patch/9472521/
> > > > > > > >
> > > > > > > > Erm, you are aware that this patch morphed into a CEC-specific notifier
> > > > > > > > found in drivers/media/cec/cec-notifier.c?
> > > > > > > >
> > > > > > > > I don't think it makes sense to have two notifier implementations in the kernel.
> > > > > > > > The original intention was to have the notifier deal with both CEC and ASoC
> > > > > > > > notifications, but there was not enough interest for the ASoC bits at the time
> > > > > > > > and it was dropped.
> > > > > > > >
> > > > > > > > I am planning changes to the cec-notifier API, I hope to work on that this
> > > > > > > > week. I'll CC you when I post those. Those might be a good starting point
> > > > > > > > to convert the cec-notifier to an hdmi-notifier as was originally intended.
> > > > > > > >
> > > > > > > > I've added your colleague Dariusz Marcinkiewicz to the CC list since he's been
> > > > > > > > working on some nice cec-notifier improvements as well.
> > > > > > >
> > > > > > > We also have some interfaces for drm/alsa interactions around hdmi
> > > > > > > already in drm/drm_audio_component.h, but it's not used by anything
> > > > > > > outside of i915. Imo we should extend that, not reinvent a new wheel.
> > > > > > >
> > > > > > Hi Daniel,
> > > > > > Thank you for the pointer. Looking at the ops, it seems that it is
> > > > > > specific to HDA.
> > > > > > I am not familiar with drm and HDA. I am not sure how applicable it
> > > > > > would be to report jack status to ASoC.
> > > > > > There is a use case in sound/soc/codecs/hdac_hdmi.c though so it
> > > > > > should be possible.
> > > > >
> > > > > Currently hda is the only user, but the idea was to make it more generic.
> > > > > Jack status in alsa is what drm calls connector status btw.
> > > > >
> > > > > So if we can take that as a baseline and extend it (probably needs some
> > > > > registration boilerplate and helpers to look up the right endpoint using
> > > > > of/dt for soc systems, we use component.c in i915/hda for this), that
> > > > > would be great I think.
> > > > >
> > > > > > > Another note: notifiers considered evil, imo. Gets the job done for one
> > > > > > > case, as soon as you have multiple devices and need to make sure you get
> > > > > > > the update for the right one it all comes crashing down. Please create an
> > > > > > > api which registers for updates from a specific device only, plus
> > > > > > > something that has real callbacks (like the drm_audio_component.h thing we
> > > > > > > started already).
> > > > > >
> > > > > > To clarify a bit, this hdmi-notifier indeed supports updating from a
> > > > > > specific device only.
> > > > > > hdmi_notifier_get takes a device and return the notifier.
> > > > >
> > > > > Hm I missed that, I thought it's global, so one of my usual notifier
> > > > > concerns addressed.
> > > > >
> > > > > > It seems that a major difference between drm_audio_components and
> > > > > > hdmi-notifier is that
> > > > > > drm_audio_components defines all supported ops in drm_audio_component_audio_ops.
> > > > > > On the other hand, hdmi-notifier passes different events using an enum
> > > > > > like HDMI_CONNECTED and let listener handle different events.
> > > > > > In this regard I agree with you that drm_audio_component is cleaner.
> > > > > > Anyway, I will look into it a bit more and see how it works.
> > > > >
> > > > > Yeah I think if we could combine the approach, i.e. notifier side for
> > > > > registration, some _ops structure for the actual notifications, then
> > > > > there's a solid interface. I just really don't like the opaque void *
> > > > > interface notifier provides, it encourages abuse way too much.
> > > > >
> > > > > Ofc the registration side would then no longer be based on the notifier
> > > > > datastructure, list_head (like cec-notifier.c) of registeres devices with
> > > > > their _ops structure should be enough.
> > > > > -Daniel
> > > >
> > > > Hi Daniel,
> > > > Yes, I agree the above statement that we should have a more solid interface.
> > > >
> > > > Hi Hans,
> > > > I am not sure if I missed the patch.
> > > > Do you have a estimated timeline for new cec-notifier interface you
> > > > are working on?
> > > > It seems that your PoC patch needs Dariusz's patch to work.
> > > > I would like to seek your advice on whether I can proceed without your
> > > > patch and Dariusz's patch.
> > > >
> > > > I looked through the patch from Dariusz
> > > >
> > > > https://lkml.org/lkml/2019/5/21/389
> > > >
> > > > , and saw that you were thinking whether we should use cec-notifier
> > > > for both HDMI and CEC.
> > > >
> > > > https://lkml.org/lkml/2019/5/24/298
> > > >
> > > > Could you please let me know your latest thought on whether we should
> > > > reuse cec-notifier?
> > >
> > > Nah, see later in that thread, I think cec and audio seem to be different
> > > use-cases.
> > >
> > Ack
> > > But definitely a good idea to sync with Dariusz, I forgot to pull the two
> > > threads together. Thanks for doing that.
> > >
> > > > I agree with you that I should not proceed with hdmi-notifier. Reasons include:
> > > > 1. Method like cec_notifier_parse_hdmi_phandle can be reused. It is
> > > > error prone to memory leak if it is implemented by user, like the
> > > > patch in hdmi-codec.c in this series did not handle the ref count.
> > > > 2. cec-notifier has a simpler implementation of register / unregister
> > > > because there is no call chain. I am not aware of the need for
> > > > hdmi-notifier to support a chain of callbacks. So I think that call
> > > > chain support can be removed.
> > > >
> > > > If I go ahead and add a new interface to register ops to handle
> > > > connector status report from cec-notifer, based on current
> > > > cec-notifier, do you think that would work ?
> > > > I think it might work if I add another cec_notifier object inside
> > > > dw-hdmi.c, but only for HDMI jack reporting, not for CEC related
> > > > reporting.
> > > >
> > > > And after some investigation, I realize that my requirement is even
> > > > simpler. I don't need hdmi_event_new_edid and hdmi_event_new_eld in my
> > > > use case.
> > >
> > > Yeah, connector status is how we started with the drm/alsa interface in
> > > i915 too, but later on had to extend it. I think eventually we'll need it
> > > all, that's why I suggested to use that as the interface between drm and
> > > alsa side, but augmented with some register/unregister and bind logic.
> > >
> > Hi Daniel,
> > Sorry for the late reply.
> > I spent some time investigating how drm_audio_component works.
> > The coupling of HDA in drm_audio_component framework makes the
> > register/unregister logic looks complicated to me as I don't use HDA
> > in my use case.
> > After some time, I found another patch series which also use component
> > framework to communicate between drm and mei world.
> >
> > https://patchwork.kernel.org/patch/10824527/
> >
> > And from that patch, I realized that I can follow the similar approach
> > to register a master component on ALSA side, a slave component on DRM
> > side, and use device and subcomponent to match them.
>
> Sorry for the confusion here. My suggestion is _not_ to use the component
> framework. That's only meant for one-off special case solutions. For that
> part I think you need to build a new register/unregister/bind/unbind
> infrastructure, like we have for lots of other things in the kernel
> already (clocks, gpio, drm_panel, drm_bridge as just a few examples).
>

Hi Daniel,
Thank you for the prompt reply and guidance.

I see. I was not aware that we should avoid using component framework.
Your example of drm_panel seems great.
I plan is to reuse drm_audio_components like this:
A LIST_HEAD holding the list of drm_audio_components instances, and add API
drm_audio_comp_init,
_add, _remove, _attach, _detach.
And for DRM side to look up the instance to use, we can use similar
approach like of_drm_find_panel, that is, using device tree node.

> My suggestion with the i915/hda interface is to build on the actual
> interface for signalling connector status and exchanging eld and stuff
> like that.
>

I agree with using this interface. But in my use case there is no much
data to be exchanged.
Only the connector status needs to be passed from DRM to ALSA world.
If in the future there is need for ALSA to make some call, that ops
can be added to drm_audio_component_ops.

> > I should be able to do this without touching anything specific to HDA.
> > After that, DRM world should be able to use the ops in
> > drm_audio_component_audio_ops to notify ALSA world some event when
> > there is something happen in DRM world.
> > Currently the ops like pin_eld_notify, pin2port are too specific to HDA.
> > I think I can add an ops to drm_audio_component_audio_ops to convey
> > connector status.
>
> Hm why? The pin2port is maybe not the best one, since port is an intel
> construct, and pin a hda construct. So we'd need to change those to talk
> in terms of the higher-level concepts (alsa output pin and drm crtc
> probably).
>

I took more look into how information of audio being present or not is
passed between DRM and ALSA world,
taking drivers/gpu/drm/i915/intel_audio.c and
sound/soc/codecs/hdac_hdmi.c as example.
I see the sequence is DRM side to call pin_eld_notify ops with port
and pipe to ALSA side.
Then, ALSA side calls get_eld ops with port and pipe to look up
whether the saved encoder has audio_connector.

However, my use case on RK3288 is different in that ALSA side does not
need to get ELD.
I think adding an ops like connector_status() for DRM side to call in
parallel to pin_eld_notify is reasonable.
Both DRM side and ALSA side can choose what is the desired ops to be
implemented as these ops can be optional.

> The other stuff should work a bit better. Either way my idea was to evolve
> that interface (and put in the place the required type-casting for
> i915/hda), since more users increases the odds that it actually is a good
> design.
>
Sorry I don't understand this part.
Could you please elaborate more about type-casting for i915/hda ?

TBH, If possible, I would like to minimize the change I'll need to
make to i915/hda because of my limited knowledge of i915/hda and my
limited bandwidth.

I would like to point out the scope of this problem to help the discussion.
I think this is a common need on boards using ALSA hdmi-codec driver.
Currently, there are many DRM drivers resorted to hdmi_codec_ops
approach to let ALSA world talks to DRM world.
That hdmi_codec_ops approach came around 2016 so it was before
drm_audio_component was introduced.
As for how jack status is reported for these boards, I am not sure,
maybe with local patches of hdmi-notifier.
So this is not a one-off change for RK3288 only. I believe other
boards will benefit from this jack reporting feature as well.

As for extending and improving the interface of drm_audio_component so
more users can adopt it,
I think the ops in hdmi_codec_ops are good candidates to be moved to
drm_audio_component to consolidate the interface between DRM and ALSA
better.
That said, I don't feel a strong need to change i915/hda if the
purpose is to let more users use drm_audio_component.

I can drew these changes in three stages:
1. Add the infrastructure to add/remove/attach/detach
drm_audio_component (like how drm_panel does), and add
connector_status ops.
2. Move ops in hdmi_codec_ops into drm_audio_components.
3. Desired change of i915/hda (I am not clear about this part)

I can help with 1 and 2 as Chromium tree have at least RK3288 and
MT8173 SoC using hdmi-codec driver so it is easier for me to try
patches.
And there may be more in the future.

Thanks again for the patience.
I am not familiar with DRM so it takes me more time to digest your
comment and reply.

> > I will work toward this approach these days.
> > If you have other thought please let me know.
> > Thanks!
> >
> > > > I just need to report the connector status from synopsys/dw-hdmi.c to
> > > > codecs/hdmi-codec.c for codec driver to update the jack status.
> > > > Do you think I can proceed in this direction ? Or do you prefer I wait
> > > > for a while and work on it based on your new patch.
> > >
> > > I think most important part here is that we sync across all the different
> > > people pushing for better drm/alsa integration. What the solution looks
> > > like in the end doesn't matter much imo, as long as we don't end up with 3
> > > different things :-)
> >
> > Totally agree.
>
> Anyway just my thoughts, let's keep chatting.
>
> Cheers, Daniel
>
> > Thanks again!
> >
> > >
> > > Cheers, Daniel
> > >
> > > >
> > > > Thanks a lot!
> > > >
> > > >
> > > > >
> > > > > >
> > > > > > Thanks again!
> > > > > >
> > > > > > > -Daniel
> > > > > > >
> > > > > > > >
> > > > > > > > Regards,
> > > > > > > >
> > > > > > > >       Hans
> > > > > > > >
> > > > > > > > >
> > > > > > > > > Modified by Cheng-Yi Chiang:
> > > > > > > > >  - Add a section in MAINTAINER.
> > > > > > > > >  - Changes connected and has_eld to bitfield of unsigned int.
> > > > > > > > >  - Other minor fixes to pass checkpatch.pl --strict checks.
> > > > > > > > >
> > > > > > > > > Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
> > > > > > > > > Acked-by: Philipp Zabel <p.zabel@pengutronix.de>
> > > > > > > > > Signed-off-by: Cheng-Yi Chiang <cychiang@chromium.org>
> > > > > > > > > ---
> > > > > > > > > The original patch is at
> > > > > > > > > https://lore.kernel.org/linux-arm-kernel/20161213150813.37966-2-hverkuil@xs4all.nl
> > > > > > > > >
> > > > > > > > >  MAINTAINERS                   |   6 ++
> > > > > > > > >  drivers/video/Kconfig         |   3 +
> > > > > > > > >  drivers/video/Makefile        |   1 +
> > > > > > > > >  drivers/video/hdmi-notifier.c | 145 ++++++++++++++++++++++++++++++++++
> > > > > > > > >  include/linux/hdmi-notifier.h | 112 ++++++++++++++++++++++++++
> > > > > > > > >  5 files changed, 267 insertions(+)
> > > > > > > > >  create mode 100644 drivers/video/hdmi-notifier.c
> > > > > > > > >  create mode 100644 include/linux/hdmi-notifier.h
> > > > > > > > >
> > > > > > > > > diff --git a/MAINTAINERS b/MAINTAINERS
> > > > > > > > > index 5cfbea4ce575..ffb7376f9509 100644
> > > > > > > > > --- a/MAINTAINERS
> > > > > > > > > +++ b/MAINTAINERS
> > > > > > > > > @@ -16676,6 +16676,12 @@ W: https://linuxtv.org
> > > > > > > > >  S: Maintained
> > > > > > > > >  F: drivers/media/platform/vicodec/*
> > > > > > > > >
> > > > > > > > > +VIDEO FRAMEWORK
> > > > > > > > > +M: Hans Verkuil <hverkuil@xs4all.nl>
> > > > > > > > > +L: linux-media@vger.kernel.org
> > > > > > > > > +F: drivers/video/hdmi-notifier.*
> > > > > > > > > +S: Maintained
> > > > > > > > > +
> > > > > > > > >  VIDEO MULTIPLEXER DRIVER
> > > > > > > > >  M: Philipp Zabel <p.zabel@pengutronix.de>
> > > > > > > > >  L: linux-media@vger.kernel.org
> > > > > > > > > diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
> > > > > > > > > index 83d3d271ca15..000ba9bc0ae7 100644
> > > > > > > > > --- a/drivers/video/Kconfig
> > > > > > > > > +++ b/drivers/video/Kconfig
> > > > > > > > > @@ -34,6 +34,9 @@ config VIDEOMODE_HELPERS
> > > > > > > > >  config HDMI
> > > > > > > > >     bool
> > > > > > > > >
> > > > > > > > > +config HDMI_NOTIFIERS
> > > > > > > > > +   bool
> > > > > > > > > +
> > > > > > > > >  endif # HAS_IOMEM
> > > > > > > > >
> > > > > > > > >  if VT
> > > > > > > > > diff --git a/drivers/video/Makefile b/drivers/video/Makefile
> > > > > > > > > index df7650adede9..eff4736102ca 100644
> > > > > > > > > --- a/drivers/video/Makefile
> > > > > > > > > +++ b/drivers/video/Makefile
> > > > > > > > > @@ -1,6 +1,7 @@
> > > > > > > > >  # SPDX-License-Identifier: GPL-2.0
> > > > > > > > >  obj-$(CONFIG_VGASTATE)            += vgastate.o
> > > > > > > > >  obj-$(CONFIG_HDMI)                += hdmi.o
> > > > > > > > > +obj-$(CONFIG_HDMI_NOTIFIERS)      += hdmi-notifier.o
> > > > > > > > >
> > > > > > > > >  obj-$(CONFIG_VT)             += console/
> > > > > > > > >  obj-$(CONFIG_FB_STI)                 += console/
> > > > > > > > > diff --git a/drivers/video/hdmi-notifier.c b/drivers/video/hdmi-notifier.c
> > > > > > > > > new file mode 100644
> > > > > > > > > index 000000000000..d1eedf661648
> > > > > > > > > --- /dev/null
> > > > > > > > > +++ b/drivers/video/hdmi-notifier.c
> > > > > > > > > @@ -0,0 +1,145 @@
> > > > > > > > > +// SPDX-License-Identifier: GPL-2.0
> > > > > > > > > +/* hdmi-notifier.c - notify interested parties of (dis)connect and EDID
> > > > > > > > > + * events
> > > > > > > > > + *
> > > > > > > > > + * Copyright 2016 Russell King <rmk+kernel@arm.linux.org.uk>
> > > > > > > > > + * Copyright 2016 Cisco Systems, Inc. and/or its affiliates.
> > > > > > > > > + * All rights reserved.
> > > > > > > > > + */
> > > > > > > > > +
> > > > > > > > > +#include <linux/export.h>
> > > > > > > > > +#include <linux/hdmi-notifier.h>
> > > > > > > > > +#include <linux/string.h>
> > > > > > > > > +#include <linux/slab.h>
> > > > > > > > > +#include <linux/list.h>
> > > > > > > > > +
> > > > > > > > > +static LIST_HEAD(hdmi_notifiers);
> > > > > > > > > +static DEFINE_MUTEX(hdmi_notifiers_lock);
> > > > > > > > > +
> > > > > > > > > +struct hdmi_notifier *hdmi_notifier_get(struct device *dev)
> > > > > > > > > +{
> > > > > > > > > +   struct hdmi_notifier *n;
> > > > > > > > > +
> > > > > > > > > +   mutex_lock(&hdmi_notifiers_lock);
> > > > > > > > > +   list_for_each_entry(n, &hdmi_notifiers, head) {
> > > > > > > > > +           if (n->dev == dev) {
> > > > > > > > > +                   mutex_unlock(&hdmi_notifiers_lock);
> > > > > > > > > +                   kref_get(&n->kref);
> > > > > > > > > +                   return n;
> > > > > > > > > +           }
> > > > > > > > > +   }
> > > > > > > > > +   n = kzalloc(sizeof(*n), GFP_KERNEL);
> > > > > > > > > +   if (!n)
> > > > > > > > > +           goto unlock;
> > > > > > > > > +   n->dev = dev;
> > > > > > > > > +   mutex_init(&n->lock);
> > > > > > > > > +   BLOCKING_INIT_NOTIFIER_HEAD(&n->notifiers);
> > > > > > > > > +   kref_init(&n->kref);
> > > > > > > > > +   list_add_tail(&n->head, &hdmi_notifiers);
> > > > > > > > > +unlock:
> > > > > > > > > +   mutex_unlock(&hdmi_notifiers_lock);
> > > > > > > > > +   return n;
> > > > > > > > > +}
> > > > > > > > > +EXPORT_SYMBOL_GPL(hdmi_notifier_get);
> > > > > > > > > +
> > > > > > > > > +static void hdmi_notifier_release(struct kref *kref)
> > > > > > > > > +{
> > > > > > > > > +   struct hdmi_notifier *n =
> > > > > > > > > +           container_of(kref, struct hdmi_notifier, kref);
> > > > > > > > > +
> > > > > > > > > +   mutex_lock(&hdmi_notifiers_lock);
> > > > > > > > > +   list_del(&n->head);
> > > > > > > > > +   mutex_unlock(&hdmi_notifiers_lock);
> > > > > > > > > +   kfree(n->edid);
> > > > > > > > > +   kfree(n);
> > > > > > > > > +}
> > > > > > > > > +
> > > > > > > > > +void hdmi_notifier_put(struct hdmi_notifier *n)
> > > > > > > > > +{
> > > > > > > > > +   kref_put(&n->kref, hdmi_notifier_release);
> > > > > > > > > +}
> > > > > > > > > +EXPORT_SYMBOL_GPL(hdmi_notifier_put);
> > > > > > > > > +
> > > > > > > > > +int hdmi_notifier_register(struct hdmi_notifier *n, struct notifier_block *nb)
> > > > > > > > > +{
> > > > > > > > > +   int ret = blocking_notifier_chain_register(&n->notifiers, nb);
> > > > > > > > > +
> > > > > > > > > +   if (ret)
> > > > > > > > > +           return ret;
> > > > > > > > > +   kref_get(&n->kref);
> > > > > > > > > +   mutex_lock(&n->lock);
> > > > > > > > > +   if (n->connected) {
> > > > > > > > > +           blocking_notifier_call_chain(&n->notifiers, HDMI_CONNECTED, n);
> > > > > > > > > +           if (n->edid_size)
> > > > > > > > > +                   blocking_notifier_call_chain(&n->notifiers,
> > > > > > > > > +                                                HDMI_NEW_EDID, n);
> > > > > > > > > +           if (n->has_eld)
> > > > > > > > > +                   blocking_notifier_call_chain(&n->notifiers,
> > > > > > > > > +                                                HDMI_NEW_ELD, n);
> > > > > > > > > +   }
> > > > > > > > > +   mutex_unlock(&n->lock);
> > > > > > > > > +   return 0;
> > > > > > > > > +}
> > > > > > > > > +EXPORT_SYMBOL_GPL(hdmi_notifier_register);
> > > > > > > > > +
> > > > > > > > > +int hdmi_notifier_unregister(struct hdmi_notifier *n, struct notifier_block *nb)
> > > > > > > > > +{
> > > > > > > > > +   int ret = blocking_notifier_chain_unregister(&n->notifiers, nb);
> > > > > > > > > +
> > > > > > > > > +   if (ret == 0)
> > > > > > > > > +           hdmi_notifier_put(n);
> > > > > > > > > +   return ret;
> > > > > > > > > +}
> > > > > > > > > +EXPORT_SYMBOL_GPL(hdmi_notifier_unregister);
> > > > > > > > > +
> > > > > > > > > +void hdmi_event_connect(struct hdmi_notifier *n)
> > > > > > > > > +{
> > > > > > > > > +   mutex_lock(&n->lock);
> > > > > > > > > +   n->connected = true;
> > > > > > > > > +   blocking_notifier_call_chain(&n->notifiers, HDMI_CONNECTED, n);
> > > > > > > > > +   mutex_unlock(&n->lock);
> > > > > > > > > +}
> > > > > > > > > +EXPORT_SYMBOL_GPL(hdmi_event_connect);
> > > > > > > > > +
> > > > > > > > > +void hdmi_event_disconnect(struct hdmi_notifier *n)
> > > > > > > > > +{
> > > > > > > > > +   mutex_lock(&n->lock);
> > > > > > > > > +   n->connected = false;
> > > > > > > > > +   n->has_eld = false;
> > > > > > > > > +   n->edid_size = 0;
> > > > > > > > > +   blocking_notifier_call_chain(&n->notifiers, HDMI_DISCONNECTED, n);
> > > > > > > > > +   mutex_unlock(&n->lock);
> > > > > > > > > +}
> > > > > > > > > +EXPORT_SYMBOL_GPL(hdmi_event_disconnect);
> > > > > > > > > +
> > > > > > > > > +int hdmi_event_new_edid(struct hdmi_notifier *n, const void *edid, size_t size)
> > > > > > > > > +{
> > > > > > > > > +   mutex_lock(&n->lock);
> > > > > > > > > +   if (n->edid_allocated_size < size) {
> > > > > > > > > +           void *p = kmalloc(size, GFP_KERNEL);
> > > > > > > > > +
> > > > > > > > > +           if (!p) {
> > > > > > > > > +                   mutex_unlock(&n->lock);
> > > > > > > > > +                   return -ENOMEM;
> > > > > > > > > +           }
> > > > > > > > > +           kfree(n->edid);
> > > > > > > > > +           n->edid = p;
> > > > > > > > > +           n->edid_allocated_size = size;
> > > > > > > > > +   }
> > > > > > > > > +   memcpy(n->edid, edid, size);
> > > > > > > > > +   n->edid_size = size;
> > > > > > > > > +   blocking_notifier_call_chain(&n->notifiers, HDMI_NEW_EDID, n);
> > > > > > > > > +   mutex_unlock(&n->lock);
> > > > > > > > > +   return 0;
> > > > > > > > > +}
> > > > > > > > > +EXPORT_SYMBOL_GPL(hdmi_event_new_edid);
> > > > > > > > > +
> > > > > > > > > +void hdmi_event_new_eld(struct hdmi_notifier *n, const u8 eld[128])
> > > > > > > > > +{
> > > > > > > > > +   mutex_lock(&n->lock);
> > > > > > > > > +   memcpy(n->eld, eld, sizeof(n->eld));
> > > > > > > > > +   n->has_eld = true;
> > > > > > > > > +   blocking_notifier_call_chain(&n->notifiers, HDMI_NEW_ELD, n);
> > > > > > > > > +   mutex_unlock(&n->lock);
> > > > > > > > > +}
> > > > > > > > > +EXPORT_SYMBOL_GPL(hdmi_event_new_eld);
> > > > > > > > > diff --git a/include/linux/hdmi-notifier.h b/include/linux/hdmi-notifier.h
> > > > > > > > > new file mode 100644
> > > > > > > > > index 000000000000..c8f35110e3e3
> > > > > > > > > --- /dev/null
> > > > > > > > > +++ b/include/linux/hdmi-notifier.h
> > > > > > > > > @@ -0,0 +1,112 @@
> > > > > > > > > +/* SPDX-License-Identifier: GPL-2.0
> > > > > > > > > + * hdmi-notifier.h - notify interested parties of (dis)connect and EDID
> > > > > > > > > + * events
> > > > > > > > > + *
> > > > > > > > > + * Copyright 2016 Russell King <rmk+kernel@arm.linux.org.uk>
> > > > > > > > > + * Copyright 2016 Cisco Systems, Inc. and/or its affiliates.
> > > > > > > > > + * All rights reserved.
> > > > > > > > > + */
> > > > > > > > > +
> > > > > > > > > +#ifndef LINUX_HDMI_NOTIFIER_H
> > > > > > > > > +#define LINUX_HDMI_NOTIFIER_H
> > > > > > > > > +
> > > > > > > > > +#include <linux/types.h>
> > > > > > > > > +#include <linux/notifier.h>
> > > > > > > > > +#include <linux/kref.h>
> > > > > > > > > +
> > > > > > > > > +enum {
> > > > > > > > > +   HDMI_CONNECTED,
> > > > > > > > > +   HDMI_DISCONNECTED,
> > > > > > > > > +   HDMI_NEW_EDID,
> > > > > > > > > +   HDMI_NEW_ELD,
> > > > > > > > > +};
> > > > > > > > > +
> > > > > > > > > +struct device;
> > > > > > > > > +
> > > > > > > > > +struct hdmi_notifier {
> > > > > > > > > +   /* Lock to protect callback registration and notification. */
> > > > > > > > > +   struct mutex lock;
> > > > > > > > > +   struct list_head head;
> > > > > > > > > +   struct kref kref;
> > > > > > > > > +   struct blocking_notifier_head notifiers;
> > > > > > > > > +   struct device *dev;
> > > > > > > > > +
> > > > > > > > > +   /* Current state */
> > > > > > > > > +   unsigned int connected : 1;
> > > > > > > > > +   unsigned int has_eld : 1;
> > > > > > > > > +   unsigned char eld[128];
> > > > > > > > > +   void *edid;
> > > > > > > > > +   size_t edid_size;
> > > > > > > > > +   size_t edid_allocated_size;
> > > > > > > > > +};
> > > > > > > > > +
> > > > > > > > > +/**
> > > > > > > > > + * hdmi_notifier_get - find or create a new hdmi_notifier for the given device.
> > > > > > > > > + * @dev: device that sends the events.
> > > > > > > > > + *
> > > > > > > > > + * If a notifier for device @dev already exists, then increase the refcount
> > > > > > > > > + * and return that notifier.
> > > > > > > > > + *
> > > > > > > > > + * If it doesn't exist, then allocate a new notifier struct and return a
> > > > > > > > > + * pointer to that new struct.
> > > > > > > > > + *
> > > > > > > > > + * Return NULL if the memory could not be allocated.
> > > > > > > > > + */
> > > > > > > > > +struct hdmi_notifier *hdmi_notifier_get(struct device *dev);
> > > > > > > > > +
> > > > > > > > > +/**
> > > > > > > > > + * hdmi_notifier_put - decrease refcount and delete when the refcount reaches 0.
> > > > > > > > > + * @n: notifier
> > > > > > > > > + */
> > > > > > > > > +void hdmi_notifier_put(struct hdmi_notifier *n);
> > > > > > > > > +
> > > > > > > > > +/**
> > > > > > > > > + * hdmi_notifier_register - register the notifier with the notifier_block.
> > > > > > > > > + * @n: the HDMI notifier
> > > > > > > > > + * @nb: the notifier_block
> > > > > > > > > + */
> > > > > > > > > +int hdmi_notifier_register(struct hdmi_notifier *n, struct notifier_block *nb);
> > > > > > > > > +
> > > > > > > > > +/**
> > > > > > > > > + * hdmi_notifier_unregister - unregister the notifier with the notifier_block.
> > > > > > > > > + * @n: the HDMI notifier
> > > > > > > > > + * @nb: the notifier_block
> > > > > > > > > + */
> > > > > > > > > +int hdmi_notifier_unregister(struct hdmi_notifier *n,
> > > > > > > > > +                        struct notifier_block *nb);
> > > > > > > > > +
> > > > > > > > > +/**
> > > > > > > > > + * hdmi_event_connect - send a connect event.
> > > > > > > > > + * @n: the HDMI notifier
> > > > > > > > > + *
> > > > > > > > > + * Send an HDMI_CONNECTED event to any registered parties.
> > > > > > > > > + */
> > > > > > > > > +void hdmi_event_connect(struct hdmi_notifier *n);
> > > > > > > > > +
> > > > > > > > > +/**
> > > > > > > > > + * hdmi_event_disconnect - send a disconnect event.
> > > > > > > > > + * @n: the HDMI notifier
> > > > > > > > > + *
> > > > > > > > > + * Send an HDMI_DISCONNECTED event to any registered parties.
> > > > > > > > > + */
> > > > > > > > > +void hdmi_event_disconnect(struct hdmi_notifier *n);
> > > > > > > > > +
> > > > > > > > > +/**
> > > > > > > > > + * hdmi_event_new_edid - send a new EDID event.
> > > > > > > > > + * @n: the HDMI notifier
> > > > > > > > > + *
> > > > > > > > > + * Send an HDMI_NEW_EDID event to any registered parties.
> > > > > > > > > + * This function will make a copy the EDID so it can return -ENOMEM if
> > > > > > > > > + * no memory could be allocated.
> > > > > > > > > + */
> > > > > > > > > +int hdmi_event_new_edid(struct hdmi_notifier *n, const void *edid, size_t size);
> > > > > > > > > +
> > > > > > > > > +/**
> > > > > > > > > + * hdmi_event_new_eld - send a new ELD event.
> > > > > > > > > + * @n: the HDMI notifier
> > > > > > > > > + *
> > > > > > > > > + * Send an HDMI_NEW_ELD event to any registered parties.
> > > > > > > > > + */
> > > > > > > > > +void hdmi_event_new_eld(struct hdmi_notifier *n, const u8 eld[128]);
> > > > > > > > > +
> > > > > > > > > +#endif
> > > > > > > > >
> > > > > > > >
> > > > > > >
> > > > > > > --
> > > > > > > Daniel Vetter
> > > > > > > Software Engineer, Intel Corporation
> > > > > > > http://blog.ffwll.ch
> > > > >
> > > > > --
> > > > > Daniel Vetter
> > > > > Software Engineer, Intel Corporation
> > > > > http://blog.ffwll.ch
> > >
> > > --
> > > Daniel Vetter
> > > Software Engineer, Intel Corporation
> > > http://blog.ffwll.ch
>
> --
> Daniel Vetter
> Software Engineer, Intel Corporation
> http://blog.ffwll.ch

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 1/7] video: add HDMI state notifier support
  2019-06-19 11:48                   ` Cheng-yi Chiang
@ 2019-06-20  9:25                     ` Daniel Vetter
  2019-06-20 13:23                       ` Cheng-yi Chiang
  0 siblings, 1 reply; 30+ messages in thread
From: Daniel Vetter @ 2019-06-20  9:25 UTC (permalink / raw)
  To: Cheng-yi Chiang
  Cc: moderated list:SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEM...,
	Heiko Stuebner, Liam Girdwood, David Airlie, dri-devel,
	Takashi Iwai, Hans Verkuil, Andrzej Hajda, Laurent Pinchart,
	linux-rockchip, Dylan Reid, linux-media, devicetree, tzungbi,
	Daniel Vetter, Bartlomiej Zolnierkiewicz, Russell King,
	Rob Herring, Jaroslav Kysela, linux-arm-kernel,
	Greg Kroah-Hartman, Doug Anderson, linux-kernel, Mark Brown,
	Philipp Zabel, Dariusz Marcinkiewicz

On Wed, Jun 19, 2019 at 07:48:11PM +0800, Cheng-yi Chiang wrote:
> On Tue, Jun 18, 2019 at 8:12 PM Daniel Vetter <daniel@ffwll.ch> wrote:
> >
> > On Tue, Jun 18, 2019 at 07:48:06PM +0800, Cheng-yi Chiang wrote:
> > > On Tue, Jun 11, 2019 at 8:35 PM Daniel Vetter <daniel@ffwll.ch> wrote:
> > > >
> > > > On Tue, Jun 11, 2019 at 08:10:38PM +0800, Cheng-yi Chiang wrote:
> > > > > On Tue, Jun 4, 2019 at 3:24 PM Daniel Vetter <daniel@ffwll.ch> wrote:
> > > > > >
> > > > > > On Tue, Jun 04, 2019 at 10:32:50AM +0800, Cheng-yi Chiang wrote:
> > > > > > > On Mon, Jun 3, 2019 at 4:09 PM Daniel Vetter <daniel@ffwll.ch> wrote:
> > > > > > > >
> > > > > > > > On Mon, Jun 03, 2019 at 09:45:49AM +0200, Hans Verkuil wrote:
> > > > > > > > > On 6/3/19 6:32 AM, Cheng-Yi Chiang wrote:
> > > > > > > > > > From: Hans Verkuil <hans.verkuil@cisco.com>
> > > > > > > > > >
> > > > > > > > > > Add support for HDMI hotplug and EDID notifiers, which is used to convey
> > > > > > > > > > information from HDMI drivers to their CEC and audio counterparts.
> > > > > > > > > >
> > > > > > > > > > Based on an earlier version from Russell King:
> > > > > > > > > >
> > > > > > > > > > https://patchwork.kernel.org/patch/9277043/
> > > > > > > > > >
> > > > > > > > > > The hdmi_notifier is a reference counted object containing the HDMI state
> > > > > > > > > > of an HDMI device.
> > > > > > > > > >
> > > > > > > > > > When a new notifier is registered the current state will be reported to
> > > > > > > > > > that notifier at registration time.
> > > > > > > > > >
> > > > > > > > > > Based on Hans Verkuil's patch:
> > > > > > > > > >
> > > > > > > > > > https://patchwork.kernel.org/patch/9472521/
> > > > > > > > >
> > > > > > > > > Erm, you are aware that this patch morphed into a CEC-specific notifier
> > > > > > > > > found in drivers/media/cec/cec-notifier.c?
> > > > > > > > >
> > > > > > > > > I don't think it makes sense to have two notifier implementations in the kernel.
> > > > > > > > > The original intention was to have the notifier deal with both CEC and ASoC
> > > > > > > > > notifications, but there was not enough interest for the ASoC bits at the time
> > > > > > > > > and it was dropped.
> > > > > > > > >
> > > > > > > > > I am planning changes to the cec-notifier API, I hope to work on that this
> > > > > > > > > week. I'll CC you when I post those. Those might be a good starting point
> > > > > > > > > to convert the cec-notifier to an hdmi-notifier as was originally intended.
> > > > > > > > >
> > > > > > > > > I've added your colleague Dariusz Marcinkiewicz to the CC list since he's been
> > > > > > > > > working on some nice cec-notifier improvements as well.
> > > > > > > >
> > > > > > > > We also have some interfaces for drm/alsa interactions around hdmi
> > > > > > > > already in drm/drm_audio_component.h, but it's not used by anything
> > > > > > > > outside of i915. Imo we should extend that, not reinvent a new wheel.
> > > > > > > >
> > > > > > > Hi Daniel,
> > > > > > > Thank you for the pointer. Looking at the ops, it seems that it is
> > > > > > > specific to HDA.
> > > > > > > I am not familiar with drm and HDA. I am not sure how applicable it
> > > > > > > would be to report jack status to ASoC.
> > > > > > > There is a use case in sound/soc/codecs/hdac_hdmi.c though so it
> > > > > > > should be possible.
> > > > > >
> > > > > > Currently hda is the only user, but the idea was to make it more generic.
> > > > > > Jack status in alsa is what drm calls connector status btw.
> > > > > >
> > > > > > So if we can take that as a baseline and extend it (probably needs some
> > > > > > registration boilerplate and helpers to look up the right endpoint using
> > > > > > of/dt for soc systems, we use component.c in i915/hda for this), that
> > > > > > would be great I think.
> > > > > >
> > > > > > > > Another note: notifiers considered evil, imo. Gets the job done for one
> > > > > > > > case, as soon as you have multiple devices and need to make sure you get
> > > > > > > > the update for the right one it all comes crashing down. Please create an
> > > > > > > > api which registers for updates from a specific device only, plus
> > > > > > > > something that has real callbacks (like the drm_audio_component.h thing we
> > > > > > > > started already).
> > > > > > >
> > > > > > > To clarify a bit, this hdmi-notifier indeed supports updating from a
> > > > > > > specific device only.
> > > > > > > hdmi_notifier_get takes a device and return the notifier.
> > > > > >
> > > > > > Hm I missed that, I thought it's global, so one of my usual notifier
> > > > > > concerns addressed.
> > > > > >
> > > > > > > It seems that a major difference between drm_audio_components and
> > > > > > > hdmi-notifier is that
> > > > > > > drm_audio_components defines all supported ops in drm_audio_component_audio_ops.
> > > > > > > On the other hand, hdmi-notifier passes different events using an enum
> > > > > > > like HDMI_CONNECTED and let listener handle different events.
> > > > > > > In this regard I agree with you that drm_audio_component is cleaner.
> > > > > > > Anyway, I will look into it a bit more and see how it works.
> > > > > >
> > > > > > Yeah I think if we could combine the approach, i.e. notifier side for
> > > > > > registration, some _ops structure for the actual notifications, then
> > > > > > there's a solid interface. I just really don't like the opaque void *
> > > > > > interface notifier provides, it encourages abuse way too much.
> > > > > >
> > > > > > Ofc the registration side would then no longer be based on the notifier
> > > > > > datastructure, list_head (like cec-notifier.c) of registeres devices with
> > > > > > their _ops structure should be enough.
> > > > > > -Daniel
> > > > >
> > > > > Hi Daniel,
> > > > > Yes, I agree the above statement that we should have a more solid interface.
> > > > >
> > > > > Hi Hans,
> > > > > I am not sure if I missed the patch.
> > > > > Do you have a estimated timeline for new cec-notifier interface you
> > > > > are working on?
> > > > > It seems that your PoC patch needs Dariusz's patch to work.
> > > > > I would like to seek your advice on whether I can proceed without your
> > > > > patch and Dariusz's patch.
> > > > >
> > > > > I looked through the patch from Dariusz
> > > > >
> > > > > https://lkml.org/lkml/2019/5/21/389
> > > > >
> > > > > , and saw that you were thinking whether we should use cec-notifier
> > > > > for both HDMI and CEC.
> > > > >
> > > > > https://lkml.org/lkml/2019/5/24/298
> > > > >
> > > > > Could you please let me know your latest thought on whether we should
> > > > > reuse cec-notifier?
> > > >
> > > > Nah, see later in that thread, I think cec and audio seem to be different
> > > > use-cases.
> > > >
> > > Ack
> > > > But definitely a good idea to sync with Dariusz, I forgot to pull the two
> > > > threads together. Thanks for doing that.
> > > >
> > > > > I agree with you that I should not proceed with hdmi-notifier. Reasons include:
> > > > > 1. Method like cec_notifier_parse_hdmi_phandle can be reused. It is
> > > > > error prone to memory leak if it is implemented by user, like the
> > > > > patch in hdmi-codec.c in this series did not handle the ref count.
> > > > > 2. cec-notifier has a simpler implementation of register / unregister
> > > > > because there is no call chain. I am not aware of the need for
> > > > > hdmi-notifier to support a chain of callbacks. So I think that call
> > > > > chain support can be removed.
> > > > >
> > > > > If I go ahead and add a new interface to register ops to handle
> > > > > connector status report from cec-notifer, based on current
> > > > > cec-notifier, do you think that would work ?
> > > > > I think it might work if I add another cec_notifier object inside
> > > > > dw-hdmi.c, but only for HDMI jack reporting, not for CEC related
> > > > > reporting.
> > > > >
> > > > > And after some investigation, I realize that my requirement is even
> > > > > simpler. I don't need hdmi_event_new_edid and hdmi_event_new_eld in my
> > > > > use case.
> > > >
> > > > Yeah, connector status is how we started with the drm/alsa interface in
> > > > i915 too, but later on had to extend it. I think eventually we'll need it
> > > > all, that's why I suggested to use that as the interface between drm and
> > > > alsa side, but augmented with some register/unregister and bind logic.
> > > >
> > > Hi Daniel,
> > > Sorry for the late reply.
> > > I spent some time investigating how drm_audio_component works.
> > > The coupling of HDA in drm_audio_component framework makes the
> > > register/unregister logic looks complicated to me as I don't use HDA
> > > in my use case.
> > > After some time, I found another patch series which also use component
> > > framework to communicate between drm and mei world.
> > >
> > > https://patchwork.kernel.org/patch/10824527/
> > >
> > > And from that patch, I realized that I can follow the similar approach
> > > to register a master component on ALSA side, a slave component on DRM
> > > side, and use device and subcomponent to match them.
> >
> > Sorry for the confusion here. My suggestion is _not_ to use the component
> > framework. That's only meant for one-off special case solutions. For that
> > part I think you need to build a new register/unregister/bind/unbind
> > infrastructure, like we have for lots of other things in the kernel
> > already (clocks, gpio, drm_panel, drm_bridge as just a few examples).
> >
> 
> Hi Daniel,
> Thank you for the prompt reply and guidance.
> 
> I see. I was not aware that we should avoid using component framework.
> Your example of drm_panel seems great.
> I plan is to reuse drm_audio_components like this:
> A LIST_HEAD holding the list of drm_audio_components instances, and add API
> drm_audio_comp_init,
> _add, _remove, _attach, _detach.
> And for DRM side to look up the instance to use, we can use similar
> approach like of_drm_find_panel, that is, using device tree node.

Sounds good. I guess somewhere in there you'll use of_node/DT information
to make sure you have the right audio component? Just to make sure we're
agreeing on the design completely.

> > My suggestion with the i915/hda interface is to build on the actual
> > interface for signalling connector status and exchanging eld and stuff
> > like that.
> >
> 
> I agree with using this interface. But in my use case there is no much
> data to be exchanged.
> Only the connector status needs to be passed from DRM to ALSA world.
> If in the future there is need for ALSA to make some call, that ops
> can be added to drm_audio_component_ops.

Yeah I think it's ok to not implement everyhing. Iirc we started with only
the connector status too, then extended that to sharing the eld.

There's also some i915/had hacks (clocks without using clock framework,
power domains without using power framework), where for DT platforms we
probably want to do this right.

Looking at the entire thing we might need to create new _ops structures,
or at least refactor them quite a bit. But we can improve things
iteratively imo.

> > > I should be able to do this without touching anything specific to HDA.
> > > After that, DRM world should be able to use the ops in
> > > drm_audio_component_audio_ops to notify ALSA world some event when
> > > there is something happen in DRM world.
> > > Currently the ops like pin_eld_notify, pin2port are too specific to HDA.
> > > I think I can add an ops to drm_audio_component_audio_ops to convey
> > > connector status.
> >
> > Hm why? The pin2port is maybe not the best one, since port is an intel
> > construct, and pin a hda construct. So we'd need to change those to talk
> > in terms of the higher-level concepts (alsa output pin and drm crtc
> > probably).
> >
> 
> I took more look into how information of audio being present or not is
> passed between DRM and ALSA world,
> taking drivers/gpu/drm/i915/intel_audio.c and
> sound/soc/codecs/hdac_hdmi.c as example.
> I see the sequence is DRM side to call pin_eld_notify ops with port
> and pipe to ALSA side.
> Then, ALSA side calls get_eld ops with port and pipe to look up
> whether the saved encoder has audio_connector.
> 
> However, my use case on RK3288 is different in that ALSA side does not
> need to get ELD.
> I think adding an ops like connector_status() for DRM side to call in
> parallel to pin_eld_notify is reasonable.
> Both DRM side and ALSA side can choose what is the desired ops to be
> implemented as these ops can be optional.

I think pin_eld_notify and get_eld are just mislabeled, they give you both
eld and status (the bool *enabled in get_eld). Maybe we should rename them
to get_status and pin_status_notify?

> > The other stuff should work a bit better. Either way my idea was to evolve
> > that interface (and put in the place the required type-casting for
> > i915/hda), since more users increases the odds that it actually is a good
> > design.
> >
> Sorry I don't understand this part.
> Could you please elaborate more about type-casting for i915/hda ?
> 
> TBH, If possible, I would like to minimize the change I'll need to
> make to i915/hda because of my limited knowledge of i915/hda and my
> limited bandwidth.
> 
> I would like to point out the scope of this problem to help the discussion.
> I think this is a common need on boards using ALSA hdmi-codec driver.
> Currently, there are many DRM drivers resorted to hdmi_codec_ops
> approach to let ALSA world talks to DRM world.
> That hdmi_codec_ops approach came around 2016 so it was before
> drm_audio_component was introduced.
> As for how jack status is reported for these boards, I am not sure,
> maybe with local patches of hdmi-notifier.
> So this is not a one-off change for RK3288 only. I believe other
> boards will benefit from this jack reporting feature as well.
> 
> As for extending and improving the interface of drm_audio_component so
> more users can adopt it,
> I think the ops in hdmi_codec_ops are good candidates to be moved to
> drm_audio_component to consolidate the interface between DRM and ALSA
> better.
> That said, I don't feel a strong need to change i915/hda if the
> purpose is to let more users use drm_audio_component.
> 
> I can drew these changes in three stages:
> 1. Add the infrastructure to add/remove/attach/detach
> drm_audio_component (like how drm_panel does), and add
> connector_status ops.
> 2. Move ops in hdmi_codec_ops into drm_audio_components.
> 3. Desired change of i915/hda (I am not clear about this part)
> 
> I can help with 1 and 2 as Chromium tree have at least RK3288 and
> MT8173 SoC using hdmi-codec driver so it is easier for me to try
> patches.
> And there may be more in the future.
> 
> Thanks again for the patience.
> I am not familiar with DRM so it takes me more time to digest your
> comment and reply.

Hm sorry, I totally forgot about this again, iirc I looked at this.

Yeah fully agreeing that hdmi_audio_code is probably a better starting
point. Problem is that becuase hdmi_codec is built on top of platform
device it's quite a bit harder to extend with callbacks and things like
that, without breaking the driver model.

I need to think about this more, but if all we need to look at is
hdmi_codec, then I think this becomes a lot easier. And we can ignore
drm_audio_component.h completely.
-Daniel


> 
> > > I will work toward this approach these days.
> > > If you have other thought please let me know.
> > > Thanks!
> > >
> > > > > I just need to report the connector status from synopsys/dw-hdmi.c to
> > > > > codecs/hdmi-codec.c for codec driver to update the jack status.
> > > > > Do you think I can proceed in this direction ? Or do you prefer I wait
> > > > > for a while and work on it based on your new patch.
> > > >
> > > > I think most important part here is that we sync across all the different
> > > > people pushing for better drm/alsa integration. What the solution looks
> > > > like in the end doesn't matter much imo, as long as we don't end up with 3
> > > > different things :-)
> > >
> > > Totally agree.
> >
> > Anyway just my thoughts, let's keep chatting.
> >
> > Cheers, Daniel
> >
> > > Thanks again!
> > >
> > > >
> > > > Cheers, Daniel
> > > >
> > > > >
> > > > > Thanks a lot!
> > > > >
> > > > >
> > > > > >
> > > > > > >
> > > > > > > Thanks again!
> > > > > > >
> > > > > > > > -Daniel
> > > > > > > >
> > > > > > > > >
> > > > > > > > > Regards,
> > > > > > > > >
> > > > > > > > >       Hans
> > > > > > > > >
> > > > > > > > > >
> > > > > > > > > > Modified by Cheng-Yi Chiang:
> > > > > > > > > >  - Add a section in MAINTAINER.
> > > > > > > > > >  - Changes connected and has_eld to bitfield of unsigned int.
> > > > > > > > > >  - Other minor fixes to pass checkpatch.pl --strict checks.
> > > > > > > > > >
> > > > > > > > > > Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
> > > > > > > > > > Acked-by: Philipp Zabel <p.zabel@pengutronix.de>
> > > > > > > > > > Signed-off-by: Cheng-Yi Chiang <cychiang@chromium.org>
> > > > > > > > > > ---
> > > > > > > > > > The original patch is at
> > > > > > > > > > https://lore.kernel.org/linux-arm-kernel/20161213150813.37966-2-hverkuil@xs4all.nl
> > > > > > > > > >
> > > > > > > > > >  MAINTAINERS                   |   6 ++
> > > > > > > > > >  drivers/video/Kconfig         |   3 +
> > > > > > > > > >  drivers/video/Makefile        |   1 +
> > > > > > > > > >  drivers/video/hdmi-notifier.c | 145 ++++++++++++++++++++++++++++++++++
> > > > > > > > > >  include/linux/hdmi-notifier.h | 112 ++++++++++++++++++++++++++
> > > > > > > > > >  5 files changed, 267 insertions(+)
> > > > > > > > > >  create mode 100644 drivers/video/hdmi-notifier.c
> > > > > > > > > >  create mode 100644 include/linux/hdmi-notifier.h
> > > > > > > > > >
> > > > > > > > > > diff --git a/MAINTAINERS b/MAINTAINERS
> > > > > > > > > > index 5cfbea4ce575..ffb7376f9509 100644
> > > > > > > > > > --- a/MAINTAINERS
> > > > > > > > > > +++ b/MAINTAINERS
> > > > > > > > > > @@ -16676,6 +16676,12 @@ W: https://linuxtv.org
> > > > > > > > > >  S: Maintained
> > > > > > > > > >  F: drivers/media/platform/vicodec/*
> > > > > > > > > >
> > > > > > > > > > +VIDEO FRAMEWORK
> > > > > > > > > > +M: Hans Verkuil <hverkuil@xs4all.nl>
> > > > > > > > > > +L: linux-media@vger.kernel.org
> > > > > > > > > > +F: drivers/video/hdmi-notifier.*
> > > > > > > > > > +S: Maintained
> > > > > > > > > > +
> > > > > > > > > >  VIDEO MULTIPLEXER DRIVER
> > > > > > > > > >  M: Philipp Zabel <p.zabel@pengutronix.de>
> > > > > > > > > >  L: linux-media@vger.kernel.org
> > > > > > > > > > diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
> > > > > > > > > > index 83d3d271ca15..000ba9bc0ae7 100644
> > > > > > > > > > --- a/drivers/video/Kconfig
> > > > > > > > > > +++ b/drivers/video/Kconfig
> > > > > > > > > > @@ -34,6 +34,9 @@ config VIDEOMODE_HELPERS
> > > > > > > > > >  config HDMI
> > > > > > > > > >     bool
> > > > > > > > > >
> > > > > > > > > > +config HDMI_NOTIFIERS
> > > > > > > > > > +   bool
> > > > > > > > > > +
> > > > > > > > > >  endif # HAS_IOMEM
> > > > > > > > > >
> > > > > > > > > >  if VT
> > > > > > > > > > diff --git a/drivers/video/Makefile b/drivers/video/Makefile
> > > > > > > > > > index df7650adede9..eff4736102ca 100644
> > > > > > > > > > --- a/drivers/video/Makefile
> > > > > > > > > > +++ b/drivers/video/Makefile
> > > > > > > > > > @@ -1,6 +1,7 @@
> > > > > > > > > >  # SPDX-License-Identifier: GPL-2.0
> > > > > > > > > >  obj-$(CONFIG_VGASTATE)            += vgastate.o
> > > > > > > > > >  obj-$(CONFIG_HDMI)                += hdmi.o
> > > > > > > > > > +obj-$(CONFIG_HDMI_NOTIFIERS)      += hdmi-notifier.o
> > > > > > > > > >
> > > > > > > > > >  obj-$(CONFIG_VT)             += console/
> > > > > > > > > >  obj-$(CONFIG_FB_STI)                 += console/
> > > > > > > > > > diff --git a/drivers/video/hdmi-notifier.c b/drivers/video/hdmi-notifier.c
> > > > > > > > > > new file mode 100644
> > > > > > > > > > index 000000000000..d1eedf661648
> > > > > > > > > > --- /dev/null
> > > > > > > > > > +++ b/drivers/video/hdmi-notifier.c
> > > > > > > > > > @@ -0,0 +1,145 @@
> > > > > > > > > > +// SPDX-License-Identifier: GPL-2.0
> > > > > > > > > > +/* hdmi-notifier.c - notify interested parties of (dis)connect and EDID
> > > > > > > > > > + * events
> > > > > > > > > > + *
> > > > > > > > > > + * Copyright 2016 Russell King <rmk+kernel@arm.linux.org.uk>
> > > > > > > > > > + * Copyright 2016 Cisco Systems, Inc. and/or its affiliates.
> > > > > > > > > > + * All rights reserved.
> > > > > > > > > > + */
> > > > > > > > > > +
> > > > > > > > > > +#include <linux/export.h>
> > > > > > > > > > +#include <linux/hdmi-notifier.h>
> > > > > > > > > > +#include <linux/string.h>
> > > > > > > > > > +#include <linux/slab.h>
> > > > > > > > > > +#include <linux/list.h>
> > > > > > > > > > +
> > > > > > > > > > +static LIST_HEAD(hdmi_notifiers);
> > > > > > > > > > +static DEFINE_MUTEX(hdmi_notifiers_lock);
> > > > > > > > > > +
> > > > > > > > > > +struct hdmi_notifier *hdmi_notifier_get(struct device *dev)
> > > > > > > > > > +{
> > > > > > > > > > +   struct hdmi_notifier *n;
> > > > > > > > > > +
> > > > > > > > > > +   mutex_lock(&hdmi_notifiers_lock);
> > > > > > > > > > +   list_for_each_entry(n, &hdmi_notifiers, head) {
> > > > > > > > > > +           if (n->dev == dev) {
> > > > > > > > > > +                   mutex_unlock(&hdmi_notifiers_lock);
> > > > > > > > > > +                   kref_get(&n->kref);
> > > > > > > > > > +                   return n;
> > > > > > > > > > +           }
> > > > > > > > > > +   }
> > > > > > > > > > +   n = kzalloc(sizeof(*n), GFP_KERNEL);
> > > > > > > > > > +   if (!n)
> > > > > > > > > > +           goto unlock;
> > > > > > > > > > +   n->dev = dev;
> > > > > > > > > > +   mutex_init(&n->lock);
> > > > > > > > > > +   BLOCKING_INIT_NOTIFIER_HEAD(&n->notifiers);
> > > > > > > > > > +   kref_init(&n->kref);
> > > > > > > > > > +   list_add_tail(&n->head, &hdmi_notifiers);
> > > > > > > > > > +unlock:
> > > > > > > > > > +   mutex_unlock(&hdmi_notifiers_lock);
> > > > > > > > > > +   return n;
> > > > > > > > > > +}
> > > > > > > > > > +EXPORT_SYMBOL_GPL(hdmi_notifier_get);
> > > > > > > > > > +
> > > > > > > > > > +static void hdmi_notifier_release(struct kref *kref)
> > > > > > > > > > +{
> > > > > > > > > > +   struct hdmi_notifier *n =
> > > > > > > > > > +           container_of(kref, struct hdmi_notifier, kref);
> > > > > > > > > > +
> > > > > > > > > > +   mutex_lock(&hdmi_notifiers_lock);
> > > > > > > > > > +   list_del(&n->head);
> > > > > > > > > > +   mutex_unlock(&hdmi_notifiers_lock);
> > > > > > > > > > +   kfree(n->edid);
> > > > > > > > > > +   kfree(n);
> > > > > > > > > > +}
> > > > > > > > > > +
> > > > > > > > > > +void hdmi_notifier_put(struct hdmi_notifier *n)
> > > > > > > > > > +{
> > > > > > > > > > +   kref_put(&n->kref, hdmi_notifier_release);
> > > > > > > > > > +}
> > > > > > > > > > +EXPORT_SYMBOL_GPL(hdmi_notifier_put);
> > > > > > > > > > +
> > > > > > > > > > +int hdmi_notifier_register(struct hdmi_notifier *n, struct notifier_block *nb)
> > > > > > > > > > +{
> > > > > > > > > > +   int ret = blocking_notifier_chain_register(&n->notifiers, nb);
> > > > > > > > > > +
> > > > > > > > > > +   if (ret)
> > > > > > > > > > +           return ret;
> > > > > > > > > > +   kref_get(&n->kref);
> > > > > > > > > > +   mutex_lock(&n->lock);
> > > > > > > > > > +   if (n->connected) {
> > > > > > > > > > +           blocking_notifier_call_chain(&n->notifiers, HDMI_CONNECTED, n);
> > > > > > > > > > +           if (n->edid_size)
> > > > > > > > > > +                   blocking_notifier_call_chain(&n->notifiers,
> > > > > > > > > > +                                                HDMI_NEW_EDID, n);
> > > > > > > > > > +           if (n->has_eld)
> > > > > > > > > > +                   blocking_notifier_call_chain(&n->notifiers,
> > > > > > > > > > +                                                HDMI_NEW_ELD, n);
> > > > > > > > > > +   }
> > > > > > > > > > +   mutex_unlock(&n->lock);
> > > > > > > > > > +   return 0;
> > > > > > > > > > +}
> > > > > > > > > > +EXPORT_SYMBOL_GPL(hdmi_notifier_register);
> > > > > > > > > > +
> > > > > > > > > > +int hdmi_notifier_unregister(struct hdmi_notifier *n, struct notifier_block *nb)
> > > > > > > > > > +{
> > > > > > > > > > +   int ret = blocking_notifier_chain_unregister(&n->notifiers, nb);
> > > > > > > > > > +
> > > > > > > > > > +   if (ret == 0)
> > > > > > > > > > +           hdmi_notifier_put(n);
> > > > > > > > > > +   return ret;
> > > > > > > > > > +}
> > > > > > > > > > +EXPORT_SYMBOL_GPL(hdmi_notifier_unregister);
> > > > > > > > > > +
> > > > > > > > > > +void hdmi_event_connect(struct hdmi_notifier *n)
> > > > > > > > > > +{
> > > > > > > > > > +   mutex_lock(&n->lock);
> > > > > > > > > > +   n->connected = true;
> > > > > > > > > > +   blocking_notifier_call_chain(&n->notifiers, HDMI_CONNECTED, n);
> > > > > > > > > > +   mutex_unlock(&n->lock);
> > > > > > > > > > +}
> > > > > > > > > > +EXPORT_SYMBOL_GPL(hdmi_event_connect);
> > > > > > > > > > +
> > > > > > > > > > +void hdmi_event_disconnect(struct hdmi_notifier *n)
> > > > > > > > > > +{
> > > > > > > > > > +   mutex_lock(&n->lock);
> > > > > > > > > > +   n->connected = false;
> > > > > > > > > > +   n->has_eld = false;
> > > > > > > > > > +   n->edid_size = 0;
> > > > > > > > > > +   blocking_notifier_call_chain(&n->notifiers, HDMI_DISCONNECTED, n);
> > > > > > > > > > +   mutex_unlock(&n->lock);
> > > > > > > > > > +}
> > > > > > > > > > +EXPORT_SYMBOL_GPL(hdmi_event_disconnect);
> > > > > > > > > > +
> > > > > > > > > > +int hdmi_event_new_edid(struct hdmi_notifier *n, const void *edid, size_t size)
> > > > > > > > > > +{
> > > > > > > > > > +   mutex_lock(&n->lock);
> > > > > > > > > > +   if (n->edid_allocated_size < size) {
> > > > > > > > > > +           void *p = kmalloc(size, GFP_KERNEL);
> > > > > > > > > > +
> > > > > > > > > > +           if (!p) {
> > > > > > > > > > +                   mutex_unlock(&n->lock);
> > > > > > > > > > +                   return -ENOMEM;
> > > > > > > > > > +           }
> > > > > > > > > > +           kfree(n->edid);
> > > > > > > > > > +           n->edid = p;
> > > > > > > > > > +           n->edid_allocated_size = size;
> > > > > > > > > > +   }
> > > > > > > > > > +   memcpy(n->edid, edid, size);
> > > > > > > > > > +   n->edid_size = size;
> > > > > > > > > > +   blocking_notifier_call_chain(&n->notifiers, HDMI_NEW_EDID, n);
> > > > > > > > > > +   mutex_unlock(&n->lock);
> > > > > > > > > > +   return 0;
> > > > > > > > > > +}
> > > > > > > > > > +EXPORT_SYMBOL_GPL(hdmi_event_new_edid);
> > > > > > > > > > +
> > > > > > > > > > +void hdmi_event_new_eld(struct hdmi_notifier *n, const u8 eld[128])
> > > > > > > > > > +{
> > > > > > > > > > +   mutex_lock(&n->lock);
> > > > > > > > > > +   memcpy(n->eld, eld, sizeof(n->eld));
> > > > > > > > > > +   n->has_eld = true;
> > > > > > > > > > +   blocking_notifier_call_chain(&n->notifiers, HDMI_NEW_ELD, n);
> > > > > > > > > > +   mutex_unlock(&n->lock);
> > > > > > > > > > +}
> > > > > > > > > > +EXPORT_SYMBOL_GPL(hdmi_event_new_eld);
> > > > > > > > > > diff --git a/include/linux/hdmi-notifier.h b/include/linux/hdmi-notifier.h
> > > > > > > > > > new file mode 100644
> > > > > > > > > > index 000000000000..c8f35110e3e3
> > > > > > > > > > --- /dev/null
> > > > > > > > > > +++ b/include/linux/hdmi-notifier.h
> > > > > > > > > > @@ -0,0 +1,112 @@
> > > > > > > > > > +/* SPDX-License-Identifier: GPL-2.0
> > > > > > > > > > + * hdmi-notifier.h - notify interested parties of (dis)connect and EDID
> > > > > > > > > > + * events
> > > > > > > > > > + *
> > > > > > > > > > + * Copyright 2016 Russell King <rmk+kernel@arm.linux.org.uk>
> > > > > > > > > > + * Copyright 2016 Cisco Systems, Inc. and/or its affiliates.
> > > > > > > > > > + * All rights reserved.
> > > > > > > > > > + */
> > > > > > > > > > +
> > > > > > > > > > +#ifndef LINUX_HDMI_NOTIFIER_H
> > > > > > > > > > +#define LINUX_HDMI_NOTIFIER_H
> > > > > > > > > > +
> > > > > > > > > > +#include <linux/types.h>
> > > > > > > > > > +#include <linux/notifier.h>
> > > > > > > > > > +#include <linux/kref.h>
> > > > > > > > > > +
> > > > > > > > > > +enum {
> > > > > > > > > > +   HDMI_CONNECTED,
> > > > > > > > > > +   HDMI_DISCONNECTED,
> > > > > > > > > > +   HDMI_NEW_EDID,
> > > > > > > > > > +   HDMI_NEW_ELD,
> > > > > > > > > > +};
> > > > > > > > > > +
> > > > > > > > > > +struct device;
> > > > > > > > > > +
> > > > > > > > > > +struct hdmi_notifier {
> > > > > > > > > > +   /* Lock to protect callback registration and notification. */
> > > > > > > > > > +   struct mutex lock;
> > > > > > > > > > +   struct list_head head;
> > > > > > > > > > +   struct kref kref;
> > > > > > > > > > +   struct blocking_notifier_head notifiers;
> > > > > > > > > > +   struct device *dev;
> > > > > > > > > > +
> > > > > > > > > > +   /* Current state */
> > > > > > > > > > +   unsigned int connected : 1;
> > > > > > > > > > +   unsigned int has_eld : 1;
> > > > > > > > > > +   unsigned char eld[128];
> > > > > > > > > > +   void *edid;
> > > > > > > > > > +   size_t edid_size;
> > > > > > > > > > +   size_t edid_allocated_size;
> > > > > > > > > > +};
> > > > > > > > > > +
> > > > > > > > > > +/**
> > > > > > > > > > + * hdmi_notifier_get - find or create a new hdmi_notifier for the given device.
> > > > > > > > > > + * @dev: device that sends the events.
> > > > > > > > > > + *
> > > > > > > > > > + * If a notifier for device @dev already exists, then increase the refcount
> > > > > > > > > > + * and return that notifier.
> > > > > > > > > > + *
> > > > > > > > > > + * If it doesn't exist, then allocate a new notifier struct and return a
> > > > > > > > > > + * pointer to that new struct.
> > > > > > > > > > + *
> > > > > > > > > > + * Return NULL if the memory could not be allocated.
> > > > > > > > > > + */
> > > > > > > > > > +struct hdmi_notifier *hdmi_notifier_get(struct device *dev);
> > > > > > > > > > +
> > > > > > > > > > +/**
> > > > > > > > > > + * hdmi_notifier_put - decrease refcount and delete when the refcount reaches 0.
> > > > > > > > > > + * @n: notifier
> > > > > > > > > > + */
> > > > > > > > > > +void hdmi_notifier_put(struct hdmi_notifier *n);
> > > > > > > > > > +
> > > > > > > > > > +/**
> > > > > > > > > > + * hdmi_notifier_register - register the notifier with the notifier_block.
> > > > > > > > > > + * @n: the HDMI notifier
> > > > > > > > > > + * @nb: the notifier_block
> > > > > > > > > > + */
> > > > > > > > > > +int hdmi_notifier_register(struct hdmi_notifier *n, struct notifier_block *nb);
> > > > > > > > > > +
> > > > > > > > > > +/**
> > > > > > > > > > + * hdmi_notifier_unregister - unregister the notifier with the notifier_block.
> > > > > > > > > > + * @n: the HDMI notifier
> > > > > > > > > > + * @nb: the notifier_block
> > > > > > > > > > + */
> > > > > > > > > > +int hdmi_notifier_unregister(struct hdmi_notifier *n,
> > > > > > > > > > +                        struct notifier_block *nb);
> > > > > > > > > > +
> > > > > > > > > > +/**
> > > > > > > > > > + * hdmi_event_connect - send a connect event.
> > > > > > > > > > + * @n: the HDMI notifier
> > > > > > > > > > + *
> > > > > > > > > > + * Send an HDMI_CONNECTED event to any registered parties.
> > > > > > > > > > + */
> > > > > > > > > > +void hdmi_event_connect(struct hdmi_notifier *n);
> > > > > > > > > > +
> > > > > > > > > > +/**
> > > > > > > > > > + * hdmi_event_disconnect - send a disconnect event.
> > > > > > > > > > + * @n: the HDMI notifier
> > > > > > > > > > + *
> > > > > > > > > > + * Send an HDMI_DISCONNECTED event to any registered parties.
> > > > > > > > > > + */
> > > > > > > > > > +void hdmi_event_disconnect(struct hdmi_notifier *n);
> > > > > > > > > > +
> > > > > > > > > > +/**
> > > > > > > > > > + * hdmi_event_new_edid - send a new EDID event.
> > > > > > > > > > + * @n: the HDMI notifier
> > > > > > > > > > + *
> > > > > > > > > > + * Send an HDMI_NEW_EDID event to any registered parties.
> > > > > > > > > > + * This function will make a copy the EDID so it can return -ENOMEM if
> > > > > > > > > > + * no memory could be allocated.
> > > > > > > > > > + */
> > > > > > > > > > +int hdmi_event_new_edid(struct hdmi_notifier *n, const void *edid, size_t size);
> > > > > > > > > > +
> > > > > > > > > > +/**
> > > > > > > > > > + * hdmi_event_new_eld - send a new ELD event.
> > > > > > > > > > + * @n: the HDMI notifier
> > > > > > > > > > + *
> > > > > > > > > > + * Send an HDMI_NEW_ELD event to any registered parties.
> > > > > > > > > > + */
> > > > > > > > > > +void hdmi_event_new_eld(struct hdmi_notifier *n, const u8 eld[128]);
> > > > > > > > > > +
> > > > > > > > > > +#endif
> > > > > > > > > >
> > > > > > > > >
> > > > > > > >
> > > > > > > > --
> > > > > > > > Daniel Vetter
> > > > > > > > Software Engineer, Intel Corporation
> > > > > > > > http://blog.ffwll.ch
> > > > > >
> > > > > > --
> > > > > > Daniel Vetter
> > > > > > Software Engineer, Intel Corporation
> > > > > > http://blog.ffwll.ch
> > > >
> > > > --
> > > > Daniel Vetter
> > > > Software Engineer, Intel Corporation
> > > > http://blog.ffwll.ch
> >
> > --
> > Daniel Vetter
> > Software Engineer, Intel Corporation
> > http://blog.ffwll.ch

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 1/7] video: add HDMI state notifier support
  2019-06-20  9:25                     ` Daniel Vetter
@ 2019-06-20 13:23                       ` Cheng-yi Chiang
  2019-06-20 21:12                         ` Daniel Vetter
  0 siblings, 1 reply; 30+ messages in thread
From: Cheng-yi Chiang @ 2019-06-20 13:23 UTC (permalink / raw)
  To: Cheng-yi Chiang, Hans Verkuil, linux-kernel,
	Bartlomiej Zolnierkiewicz, Greg Kroah-Hartman, Philipp Zabel,
	Mark Brown, Liam Girdwood, Takashi Iwai, Jaroslav Kysela,
	Russell King, Andrzej Hajda, Laurent Pinchart, David Airlie,
	Rob Herring, Heiko Stuebner, Doug Anderson, Dylan Reid, tzungbi,
	linux-media,
	moderated list:SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEM...,
	dri-devel, linux-arm-kernel, linux-rockchip, devicetree,
	Dariusz Marcinkiewicz
  Cc: Daniel Vetter

On Thu, Jun 20, 2019 at 5:25 PM Daniel Vetter <daniel@ffwll.ch> wrote:
>
> On Wed, Jun 19, 2019 at 07:48:11PM +0800, Cheng-yi Chiang wrote:
> > On Tue, Jun 18, 2019 at 8:12 PM Daniel Vetter <daniel@ffwll.ch> wrote:
> > >
> > > On Tue, Jun 18, 2019 at 07:48:06PM +0800, Cheng-yi Chiang wrote:
> > > > On Tue, Jun 11, 2019 at 8:35 PM Daniel Vetter <daniel@ffwll.ch> wrote:
> > > > >
> > > > > On Tue, Jun 11, 2019 at 08:10:38PM +0800, Cheng-yi Chiang wrote:
> > > > > > On Tue, Jun 4, 2019 at 3:24 PM Daniel Vetter <daniel@ffwll.ch> wrote:
> > > > > > >
> > > > > > > On Tue, Jun 04, 2019 at 10:32:50AM +0800, Cheng-yi Chiang wrote:
> > > > > > > > On Mon, Jun 3, 2019 at 4:09 PM Daniel Vetter <daniel@ffwll.ch> wrote:
> > > > > > > > >
> > > > > > > > > On Mon, Jun 03, 2019 at 09:45:49AM +0200, Hans Verkuil wrote:
> > > > > > > > > > On 6/3/19 6:32 AM, Cheng-Yi Chiang wrote:
> > > > > > > > > > > From: Hans Verkuil <hans.verkuil@cisco.com>
> > > > > > > > > > >
> > > > > > > > > > > Add support for HDMI hotplug and EDID notifiers, which is used to convey
> > > > > > > > > > > information from HDMI drivers to their CEC and audio counterparts.
> > > > > > > > > > >
> > > > > > > > > > > Based on an earlier version from Russell King:
> > > > > > > > > > >
> > > > > > > > > > > https://patchwork.kernel.org/patch/9277043/
> > > > > > > > > > >
> > > > > > > > > > > The hdmi_notifier is a reference counted object containing the HDMI state
> > > > > > > > > > > of an HDMI device.
> > > > > > > > > > >
> > > > > > > > > > > When a new notifier is registered the current state will be reported to
> > > > > > > > > > > that notifier at registration time.
> > > > > > > > > > >
> > > > > > > > > > > Based on Hans Verkuil's patch:
> > > > > > > > > > >
> > > > > > > > > > > https://patchwork.kernel.org/patch/9472521/
> > > > > > > > > >
> > > > > > > > > > Erm, you are aware that this patch morphed into a CEC-specific notifier
> > > > > > > > > > found in drivers/media/cec/cec-notifier.c?
> > > > > > > > > >
> > > > > > > > > > I don't think it makes sense to have two notifier implementations in the kernel.
> > > > > > > > > > The original intention was to have the notifier deal with both CEC and ASoC
> > > > > > > > > > notifications, but there was not enough interest for the ASoC bits at the time
> > > > > > > > > > and it was dropped.
> > > > > > > > > >
> > > > > > > > > > I am planning changes to the cec-notifier API, I hope to work on that this
> > > > > > > > > > week. I'll CC you when I post those. Those might be a good starting point
> > > > > > > > > > to convert the cec-notifier to an hdmi-notifier as was originally intended.
> > > > > > > > > >
> > > > > > > > > > I've added your colleague Dariusz Marcinkiewicz to the CC list since he's been
> > > > > > > > > > working on some nice cec-notifier improvements as well.
> > > > > > > > >
> > > > > > > > > We also have some interfaces for drm/alsa interactions around hdmi
> > > > > > > > > already in drm/drm_audio_component.h, but it's not used by anything
> > > > > > > > > outside of i915. Imo we should extend that, not reinvent a new wheel.
> > > > > > > > >
> > > > > > > > Hi Daniel,
> > > > > > > > Thank you for the pointer. Looking at the ops, it seems that it is
> > > > > > > > specific to HDA.
> > > > > > > > I am not familiar with drm and HDA. I am not sure how applicable it
> > > > > > > > would be to report jack status to ASoC.
> > > > > > > > There is a use case in sound/soc/codecs/hdac_hdmi.c though so it
> > > > > > > > should be possible.
> > > > > > >
> > > > > > > Currently hda is the only user, but the idea was to make it more generic.
> > > > > > > Jack status in alsa is what drm calls connector status btw.
> > > > > > >
> > > > > > > So if we can take that as a baseline and extend it (probably needs some
> > > > > > > registration boilerplate and helpers to look up the right endpoint using
> > > > > > > of/dt for soc systems, we use component.c in i915/hda for this), that
> > > > > > > would be great I think.
> > > > > > >
> > > > > > > > > Another note: notifiers considered evil, imo. Gets the job done for one
> > > > > > > > > case, as soon as you have multiple devices and need to make sure you get
> > > > > > > > > the update for the right one it all comes crashing down. Please create an
> > > > > > > > > api which registers for updates from a specific device only, plus
> > > > > > > > > something that has real callbacks (like the drm_audio_component.h thing we
> > > > > > > > > started already).
> > > > > > > >
> > > > > > > > To clarify a bit, this hdmi-notifier indeed supports updating from a
> > > > > > > > specific device only.
> > > > > > > > hdmi_notifier_get takes a device and return the notifier.
> > > > > > >
> > > > > > > Hm I missed that, I thought it's global, so one of my usual notifier
> > > > > > > concerns addressed.
> > > > > > >
> > > > > > > > It seems that a major difference between drm_audio_components and
> > > > > > > > hdmi-notifier is that
> > > > > > > > drm_audio_components defines all supported ops in drm_audio_component_audio_ops.
> > > > > > > > On the other hand, hdmi-notifier passes different events using an enum
> > > > > > > > like HDMI_CONNECTED and let listener handle different events.
> > > > > > > > In this regard I agree with you that drm_audio_component is cleaner.
> > > > > > > > Anyway, I will look into it a bit more and see how it works.
> > > > > > >
> > > > > > > Yeah I think if we could combine the approach, i.e. notifier side for
> > > > > > > registration, some _ops structure for the actual notifications, then
> > > > > > > there's a solid interface. I just really don't like the opaque void *
> > > > > > > interface notifier provides, it encourages abuse way too much.
> > > > > > >
> > > > > > > Ofc the registration side would then no longer be based on the notifier
> > > > > > > datastructure, list_head (like cec-notifier.c) of registeres devices with
> > > > > > > their _ops structure should be enough.
> > > > > > > -Daniel
> > > > > >
> > > > > > Hi Daniel,
> > > > > > Yes, I agree the above statement that we should have a more solid interface.
> > > > > >
> > > > > > Hi Hans,
> > > > > > I am not sure if I missed the patch.
> > > > > > Do you have a estimated timeline for new cec-notifier interface you
> > > > > > are working on?
> > > > > > It seems that your PoC patch needs Dariusz's patch to work.
> > > > > > I would like to seek your advice on whether I can proceed without your
> > > > > > patch and Dariusz's patch.
> > > > > >
> > > > > > I looked through the patch from Dariusz
> > > > > >
> > > > > > https://lkml.org/lkml/2019/5/21/389
> > > > > >
> > > > > > , and saw that you were thinking whether we should use cec-notifier
> > > > > > for both HDMI and CEC.
> > > > > >
> > > > > > https://lkml.org/lkml/2019/5/24/298
> > > > > >
> > > > > > Could you please let me know your latest thought on whether we should
> > > > > > reuse cec-notifier?
> > > > >
> > > > > Nah, see later in that thread, I think cec and audio seem to be different
> > > > > use-cases.
> > > > >
> > > > Ack
> > > > > But definitely a good idea to sync with Dariusz, I forgot to pull the two
> > > > > threads together. Thanks for doing that.
> > > > >
> > > > > > I agree with you that I should not proceed with hdmi-notifier. Reasons include:
> > > > > > 1. Method like cec_notifier_parse_hdmi_phandle can be reused. It is
> > > > > > error prone to memory leak if it is implemented by user, like the
> > > > > > patch in hdmi-codec.c in this series did not handle the ref count.
> > > > > > 2. cec-notifier has a simpler implementation of register / unregister
> > > > > > because there is no call chain. I am not aware of the need for
> > > > > > hdmi-notifier to support a chain of callbacks. So I think that call
> > > > > > chain support can be removed.
> > > > > >
> > > > > > If I go ahead and add a new interface to register ops to handle
> > > > > > connector status report from cec-notifer, based on current
> > > > > > cec-notifier, do you think that would work ?
> > > > > > I think it might work if I add another cec_notifier object inside
> > > > > > dw-hdmi.c, but only for HDMI jack reporting, not for CEC related
> > > > > > reporting.
> > > > > >
> > > > > > And after some investigation, I realize that my requirement is even
> > > > > > simpler. I don't need hdmi_event_new_edid and hdmi_event_new_eld in my
> > > > > > use case.
> > > > >
> > > > > Yeah, connector status is how we started with the drm/alsa interface in
> > > > > i915 too, but later on had to extend it. I think eventually we'll need it
> > > > > all, that's why I suggested to use that as the interface between drm and
> > > > > alsa side, but augmented with some register/unregister and bind logic.
> > > > >
> > > > Hi Daniel,
> > > > Sorry for the late reply.
> > > > I spent some time investigating how drm_audio_component works.
> > > > The coupling of HDA in drm_audio_component framework makes the
> > > > register/unregister logic looks complicated to me as I don't use HDA
> > > > in my use case.
> > > > After some time, I found another patch series which also use component
> > > > framework to communicate between drm and mei world.
> > > >
> > > > https://patchwork.kernel.org/patch/10824527/
> > > >
> > > > And from that patch, I realized that I can follow the similar approach
> > > > to register a master component on ALSA side, a slave component on DRM
> > > > side, and use device and subcomponent to match them.
> > >
> > > Sorry for the confusion here. My suggestion is _not_ to use the component
> > > framework. That's only meant for one-off special case solutions. For that
> > > part I think you need to build a new register/unregister/bind/unbind
> > > infrastructure, like we have for lots of other things in the kernel
> > > already (clocks, gpio, drm_panel, drm_bridge as just a few examples).
> > >
> >
> > Hi Daniel,
> > Thank you for the prompt reply and guidance.
> >
> > I see. I was not aware that we should avoid using component framework.
> > Your example of drm_panel seems great.
> > I plan is to reuse drm_audio_components like this:
> > A LIST_HEAD holding the list of drm_audio_components instances, and add API
> > drm_audio_comp_init,
> > _add, _remove, _attach, _detach.
> > And for DRM side to look up the instance to use, we can use similar
> > approach like of_drm_find_panel, that is, using device tree node.
>
> Sounds good. I guess somewhere in there you'll use of_node/DT information
> to make sure you have the right audio component? Just to make sure we're
> agreeing on the design completely.


ACK.
I need to check closer. I will use of_node/DT information,
but it might be the other way around as machine driver can get the
hdmi node and hence hdmi device,
and that device can be passed to codec driver to register a component
with the device.
So the register mechanism is more like original hdmi_notifier.
>
>
> > > My suggestion with the i915/hda interface is to build on the actual
> > > interface for signalling connector status and exchanging eld and stuff
> > > like that.
> > >
> >
> > I agree with using this interface. But in my use case there is no much
> > data to be exchanged.
> > Only the connector status needs to be passed from DRM to ALSA world.
> > If in the future there is need for ALSA to make some call, that ops
> > can be added to drm_audio_component_ops.
>
> Yeah I think it's ok to not implement everyhing. Iirc we started with only
> the connector status too, then extended that to sharing the eld.
>
> There's also some i915/had hacks (clocks without using clock framework,
> power domains without using power framework), where for DT platforms we
> probably want to do this right.
>
> Looking at the entire thing we might need to create new _ops structures,
> or at least refactor them quite a bit. But we can improve things
> iteratively imo.


ACK
>
>
> > > > I should be able to do this without touching anything specific to HDA.
> > > > After that, DRM world should be able to use the ops in
> > > > drm_audio_component_audio_ops to notify ALSA world some event when
> > > > there is something happen in DRM world.
> > > > Currently the ops like pin_eld_notify, pin2port are too specific to HDA.
> > > > I think I can add an ops to drm_audio_component_audio_ops to convey
> > > > connector status.
> > >
> > > Hm why? The pin2port is maybe not the best one, since port is an intel
> > > construct, and pin a hda construct. So we'd need to change those to talk
> > > in terms of the higher-level concepts (alsa output pin and drm crtc
> > > probably).
> > >
> >
> > I took more look into how information of audio being present or not is
> > passed between DRM and ALSA world,
> > taking drivers/gpu/drm/i915/intel_audio.c and
> > sound/soc/codecs/hdac_hdmi.c as example.
> > I see the sequence is DRM side to call pin_eld_notify ops with port
> > and pipe to ALSA side.
> > Then, ALSA side calls get_eld ops with port and pipe to look up
> > whether the saved encoder has audio_connector.
> >
> > However, my use case on RK3288 is different in that ALSA side does not
> > need to get ELD.
> > I think adding an ops like connector_status() for DRM side to call in
> > parallel to pin_eld_notify is reasonable.
> > Both DRM side and ALSA side can choose what is the desired ops to be
> > implemented as these ops can be optional.
>
> I think pin_eld_notify and get_eld are just mislabeled, they give you both
> eld and status (the bool *enabled in get_eld). Maybe we should rename them
> to get_status and pin_status_notify?


ACK

>
> > > The other stuff should work a bit better. Either way my idea was to evolve
> > > that interface (and put in the place the required type-casting for
> > > i915/hda), since more users increases the odds that it actually is a good
> > > design.
> > >
> > Sorry I don't understand this part.
> > Could you please elaborate more about type-casting for i915/hda ?
> >
> > TBH, If possible, I would like to minimize the change I'll need to
> > make to i915/hda because of my limited knowledge of i915/hda and my
> > limited bandwidth.
> >
> > I would like to point out the scope of this problem to help the discussion.
> > I think this is a common need on boards using ALSA hdmi-codec driver.
> > Currently, there are many DRM drivers resorted to hdmi_codec_ops
> > approach to let ALSA world talks to DRM world.
> > That hdmi_codec_ops approach came around 2016 so it was before
> > drm_audio_component was introduced.
> > As for how jack status is reported for these boards, I am not sure,
> > maybe with local patches of hdmi-notifier.
> > So this is not a one-off change for RK3288 only. I believe other
> > boards will benefit from this jack reporting feature as well.
> >
> > As for extending and improving the interface of drm_audio_component so
> > more users can adopt it,
> > I think the ops in hdmi_codec_ops are good candidates to be moved to
> > drm_audio_component to consolidate the interface between DRM and ALSA
> > better.
> > That said, I don't feel a strong need to change i915/hda if the
> > purpose is to let more users use drm_audio_component.
> >
> > I can drew these changes in three stages:
> > 1. Add the infrastructure to add/remove/attach/detach
> > drm_audio_component (like how drm_panel does), and add
> > connector_status ops.
> > 2. Move ops in hdmi_codec_ops into drm_audio_components.
> > 3. Desired change of i915/hda (I am not clear about this part)
> >
> > I can help with 1 and 2 as Chromium tree have at least RK3288 and
> > MT8173 SoC using hdmi-codec driver so it is easier for me to try
> > patches.
> > And there may be more in the future.
> >
> > Thanks again for the patience.
> > I am not familiar with DRM so it takes me more time to digest your
> > comment and reply.
>
> Hm sorry, I totally forgot about this again, iirc I looked at this.
>
> Yeah fully agreeing that hdmi_audio_code is probably a better starting
> point. Problem is that becuase hdmi_codec is built on top of platform
> device it's quite a bit harder to extend with callbacks and things like
> that, without breaking the driver model.
>
> I need to think about this more, but if all we need to look at is
> hdmi_codec, then I think this becomes a lot easier. And we can ignore
> drm_audio_component.h completely.


It is surprising that you think this way.
Maybe the original patch before hdmi-notifier was introduced is the
better way to solve this issue, if we only need to look at hdmi_codec.

The history of hdmi_codec driver is in this patch series:

https://lore.kernel.org/patchwork/patch/539656/

There was a callback mechanism implemented between dw-hdmi and hdmi
codec driver.
It was later consolidated by Doug in this patch for better jack status
reporting:

https://chromium-review.googlesource.com/c/chromiumos/third_party/kernel/+/303573/

I am not sure why the original patch series did not get fully accepted
in the upstream.
It was quite long time ago.

But if you think this might be the right way to do, then it is even
better for us because the patch series and Doug's patch had been quite
stable
on our RK3288 products for about four years with plenty of users, so
we have much higher confidence in them.
I can rebase and clean up them and post another patch for review.

Please let me know what approach you feel is better.
Thanks again!


>
> -Daniel
>
>
> >
> > > > I will work toward this approach these days.
> > > > If you have other thought please let me know.
> > > > Thanks!
> > > >
> > > > > > I just need to report the connector status from synopsys/dw-hdmi.c to
> > > > > > codecs/hdmi-codec.c for codec driver to update the jack status.
> > > > > > Do you think I can proceed in this direction ? Or do you prefer I wait
> > > > > > for a while and work on it based on your new patch.
> > > > >
> > > > > I think most important part here is that we sync across all the different
> > > > > people pushing for better drm/alsa integration. What the solution looks
> > > > > like in the end doesn't matter much imo, as long as we don't end up with 3
> > > > > different things :-)
> > > >
> > > > Totally agree.
> > >
> > > Anyway just my thoughts, let's keep chatting.
> > >
> > > Cheers, Daniel
> > >
> > > > Thanks again!
> > > >
> > > > >
> > > > > Cheers, Daniel
> > > > >
> > > > > >
> > > > > > Thanks a lot!
> > > > > >
> > > > > >
> > > > > > >
> > > > > > > >
> > > > > > > > Thanks again!
> > > > > > > >
> > > > > > > > > -Daniel
> > > > > > > > >
> > > > > > > > > >
> > > > > > > > > > Regards,
> > > > > > > > > >
> > > > > > > > > >       Hans
> > > > > > > > > >
> > > > > > > > > > >
> > > > > > > > > > > Modified by Cheng-Yi Chiang:
> > > > > > > > > > >  - Add a section in MAINTAINER.
> > > > > > > > > > >  - Changes connected and has_eld to bitfield of unsigned int.
> > > > > > > > > > >  - Other minor fixes to pass checkpatch.pl --strict checks.
> > > > > > > > > > >
> > > > > > > > > > > Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
> > > > > > > > > > > Acked-by: Philipp Zabel <p.zabel@pengutronix.de>
> > > > > > > > > > > Signed-off-by: Cheng-Yi Chiang <cychiang@chromium.org>
> > > > > > > > > > > ---
> > > > > > > > > > > The original patch is at
> > > > > > > > > > > https://lore.kernel.org/linux-arm-kernel/20161213150813.37966-2-hverkuil@xs4all.nl
> > > > > > > > > > >
> > > > > > > > > > >  MAINTAINERS                   |   6 ++
> > > > > > > > > > >  drivers/video/Kconfig         |   3 +
> > > > > > > > > > >  drivers/video/Makefile        |   1 +
> > > > > > > > > > >  drivers/video/hdmi-notifier.c | 145 ++++++++++++++++++++++++++++++++++
> > > > > > > > > > >  include/linux/hdmi-notifier.h | 112 ++++++++++++++++++++++++++
> > > > > > > > > > >  5 files changed, 267 insertions(+)
> > > > > > > > > > >  create mode 100644 drivers/video/hdmi-notifier.c
> > > > > > > > > > >  create mode 100644 include/linux/hdmi-notifier.h
> > > > > > > > > > >
> > > > > > > > > > > diff --git a/MAINTAINERS b/MAINTAINERS
> > > > > > > > > > > index 5cfbea4ce575..ffb7376f9509 100644
> > > > > > > > > > > --- a/MAINTAINERS
> > > > > > > > > > > +++ b/MAINTAINERS
> > > > > > > > > > > @@ -16676,6 +16676,12 @@ W: https://linuxtv.org
> > > > > > > > > > >  S: Maintained
> > > > > > > > > > >  F: drivers/media/platform/vicodec/*
> > > > > > > > > > >
> > > > > > > > > > > +VIDEO FRAMEWORK
> > > > > > > > > > > +M: Hans Verkuil <hverkuil@xs4all.nl>
> > > > > > > > > > > +L: linux-media@vger.kernel.org
> > > > > > > > > > > +F: drivers/video/hdmi-notifier.*
> > > > > > > > > > > +S: Maintained
> > > > > > > > > > > +
> > > > > > > > > > >  VIDEO MULTIPLEXER DRIVER
> > > > > > > > > > >  M: Philipp Zabel <p.zabel@pengutronix.de>
> > > > > > > > > > >  L: linux-media@vger.kernel.org
> > > > > > > > > > > diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
> > > > > > > > > > > index 83d3d271ca15..000ba9bc0ae7 100644
> > > > > > > > > > > --- a/drivers/video/Kconfig
> > > > > > > > > > > +++ b/drivers/video/Kconfig
> > > > > > > > > > > @@ -34,6 +34,9 @@ config VIDEOMODE_HELPERS
> > > > > > > > > > >  config HDMI
> > > > > > > > > > >     bool
> > > > > > > > > > >
> > > > > > > > > > > +config HDMI_NOTIFIERS
> > > > > > > > > > > +   bool
> > > > > > > > > > > +
> > > > > > > > > > >  endif # HAS_IOMEM
> > > > > > > > > > >
> > > > > > > > > > >  if VT
> > > > > > > > > > > diff --git a/drivers/video/Makefile b/drivers/video/Makefile
> > > > > > > > > > > index df7650adede9..eff4736102ca 100644
> > > > > > > > > > > --- a/drivers/video/Makefile
> > > > > > > > > > > +++ b/drivers/video/Makefile
> > > > > > > > > > > @@ -1,6 +1,7 @@
> > > > > > > > > > >  # SPDX-License-Identifier: GPL-2.0
> > > > > > > > > > >  obj-$(CONFIG_VGASTATE)            += vgastate.o
> > > > > > > > > > >  obj-$(CONFIG_HDMI)                += hdmi.o
> > > > > > > > > > > +obj-$(CONFIG_HDMI_NOTIFIERS)      += hdmi-notifier.o
> > > > > > > > > > >
> > > > > > > > > > >  obj-$(CONFIG_VT)             += console/
> > > > > > > > > > >  obj-$(CONFIG_FB_STI)                 += console/
> > > > > > > > > > > diff --git a/drivers/video/hdmi-notifier.c b/drivers/video/hdmi-notifier.c
> > > > > > > > > > > new file mode 100644
> > > > > > > > > > > index 000000000000..d1eedf661648
> > > > > > > > > > > --- /dev/null
> > > > > > > > > > > +++ b/drivers/video/hdmi-notifier.c
> > > > > > > > > > > @@ -0,0 +1,145 @@
> > > > > > > > > > > +// SPDX-License-Identifier: GPL-2.0
> > > > > > > > > > > +/* hdmi-notifier.c - notify interested parties of (dis)connect and EDID
> > > > > > > > > > > + * events
> > > > > > > > > > > + *
> > > > > > > > > > > + * Copyright 2016 Russell King <rmk+kernel@arm.linux.org.uk>
> > > > > > > > > > > + * Copyright 2016 Cisco Systems, Inc. and/or its affiliates.
> > > > > > > > > > > + * All rights reserved.
> > > > > > > > > > > + */
> > > > > > > > > > > +
> > > > > > > > > > > +#include <linux/export.h>
> > > > > > > > > > > +#include <linux/hdmi-notifier.h>
> > > > > > > > > > > +#include <linux/string.h>
> > > > > > > > > > > +#include <linux/slab.h>
> > > > > > > > > > > +#include <linux/list.h>
> > > > > > > > > > > +
> > > > > > > > > > > +static LIST_HEAD(hdmi_notifiers);
> > > > > > > > > > > +static DEFINE_MUTEX(hdmi_notifiers_lock);
> > > > > > > > > > > +
> > > > > > > > > > > +struct hdmi_notifier *hdmi_notifier_get(struct device *dev)
> > > > > > > > > > > +{
> > > > > > > > > > > +   struct hdmi_notifier *n;
> > > > > > > > > > > +
> > > > > > > > > > > +   mutex_lock(&hdmi_notifiers_lock);
> > > > > > > > > > > +   list_for_each_entry(n, &hdmi_notifiers, head) {
> > > > > > > > > > > +           if (n->dev == dev) {
> > > > > > > > > > > +                   mutex_unlock(&hdmi_notifiers_lock);
> > > > > > > > > > > +                   kref_get(&n->kref);
> > > > > > > > > > > +                   return n;
> > > > > > > > > > > +           }
> > > > > > > > > > > +   }
> > > > > > > > > > > +   n = kzalloc(sizeof(*n), GFP_KERNEL);
> > > > > > > > > > > +   if (!n)
> > > > > > > > > > > +           goto unlock;
> > > > > > > > > > > +   n->dev = dev;
> > > > > > > > > > > +   mutex_init(&n->lock);
> > > > > > > > > > > +   BLOCKING_INIT_NOTIFIER_HEAD(&n->notifiers);
> > > > > > > > > > > +   kref_init(&n->kref);
> > > > > > > > > > > +   list_add_tail(&n->head, &hdmi_notifiers);
> > > > > > > > > > > +unlock:
> > > > > > > > > > > +   mutex_unlock(&hdmi_notifiers_lock);
> > > > > > > > > > > +   return n;
> > > > > > > > > > > +}
> > > > > > > > > > > +EXPORT_SYMBOL_GPL(hdmi_notifier_get);
> > > > > > > > > > > +
> > > > > > > > > > > +static void hdmi_notifier_release(struct kref *kref)
> > > > > > > > > > > +{
> > > > > > > > > > > +   struct hdmi_notifier *n =
> > > > > > > > > > > +           container_of(kref, struct hdmi_notifier, kref);
> > > > > > > > > > > +
> > > > > > > > > > > +   mutex_lock(&hdmi_notifiers_lock);
> > > > > > > > > > > +   list_del(&n->head);
> > > > > > > > > > > +   mutex_unlock(&hdmi_notifiers_lock);
> > > > > > > > > > > +   kfree(n->edid);
> > > > > > > > > > > +   kfree(n);
> > > > > > > > > > > +}
> > > > > > > > > > > +
> > > > > > > > > > > +void hdmi_notifier_put(struct hdmi_notifier *n)
> > > > > > > > > > > +{
> > > > > > > > > > > +   kref_put(&n->kref, hdmi_notifier_release);
> > > > > > > > > > > +}
> > > > > > > > > > > +EXPORT_SYMBOL_GPL(hdmi_notifier_put);
> > > > > > > > > > > +
> > > > > > > > > > > +int hdmi_notifier_register(struct hdmi_notifier *n, struct notifier_block *nb)
> > > > > > > > > > > +{
> > > > > > > > > > > +   int ret = blocking_notifier_chain_register(&n->notifiers, nb);
> > > > > > > > > > > +
> > > > > > > > > > > +   if (ret)
> > > > > > > > > > > +           return ret;
> > > > > > > > > > > +   kref_get(&n->kref);
> > > > > > > > > > > +   mutex_lock(&n->lock);
> > > > > > > > > > > +   if (n->connected) {
> > > > > > > > > > > +           blocking_notifier_call_chain(&n->notifiers, HDMI_CONNECTED, n);
> > > > > > > > > > > +           if (n->edid_size)
> > > > > > > > > > > +                   blocking_notifier_call_chain(&n->notifiers,
> > > > > > > > > > > +                                                HDMI_NEW_EDID, n);
> > > > > > > > > > > +           if (n->has_eld)
> > > > > > > > > > > +                   blocking_notifier_call_chain(&n->notifiers,
> > > > > > > > > > > +                                                HDMI_NEW_ELD, n);
> > > > > > > > > > > +   }
> > > > > > > > > > > +   mutex_unlock(&n->lock);
> > > > > > > > > > > +   return 0;
> > > > > > > > > > > +}
> > > > > > > > > > > +EXPORT_SYMBOL_GPL(hdmi_notifier_register);
> > > > > > > > > > > +
> > > > > > > > > > > +int hdmi_notifier_unregister(struct hdmi_notifier *n, struct notifier_block *nb)
> > > > > > > > > > > +{
> > > > > > > > > > > +   int ret = blocking_notifier_chain_unregister(&n->notifiers, nb);
> > > > > > > > > > > +
> > > > > > > > > > > +   if (ret == 0)
> > > > > > > > > > > +           hdmi_notifier_put(n);
> > > > > > > > > > > +   return ret;
> > > > > > > > > > > +}
> > > > > > > > > > > +EXPORT_SYMBOL_GPL(hdmi_notifier_unregister);
> > > > > > > > > > > +
> > > > > > > > > > > +void hdmi_event_connect(struct hdmi_notifier *n)
> > > > > > > > > > > +{
> > > > > > > > > > > +   mutex_lock(&n->lock);
> > > > > > > > > > > +   n->connected = true;
> > > > > > > > > > > +   blocking_notifier_call_chain(&n->notifiers, HDMI_CONNECTED, n);
> > > > > > > > > > > +   mutex_unlock(&n->lock);
> > > > > > > > > > > +}
> > > > > > > > > > > +EXPORT_SYMBOL_GPL(hdmi_event_connect);
> > > > > > > > > > > +
> > > > > > > > > > > +void hdmi_event_disconnect(struct hdmi_notifier *n)
> > > > > > > > > > > +{
> > > > > > > > > > > +   mutex_lock(&n->lock);
> > > > > > > > > > > +   n->connected = false;
> > > > > > > > > > > +   n->has_eld = false;
> > > > > > > > > > > +   n->edid_size = 0;
> > > > > > > > > > > +   blocking_notifier_call_chain(&n->notifiers, HDMI_DISCONNECTED, n);
> > > > > > > > > > > +   mutex_unlock(&n->lock);
> > > > > > > > > > > +}
> > > > > > > > > > > +EXPORT_SYMBOL_GPL(hdmi_event_disconnect);
> > > > > > > > > > > +
> > > > > > > > > > > +int hdmi_event_new_edid(struct hdmi_notifier *n, const void *edid, size_t size)
> > > > > > > > > > > +{
> > > > > > > > > > > +   mutex_lock(&n->lock);
> > > > > > > > > > > +   if (n->edid_allocated_size < size) {
> > > > > > > > > > > +           void *p = kmalloc(size, GFP_KERNEL);
> > > > > > > > > > > +
> > > > > > > > > > > +           if (!p) {
> > > > > > > > > > > +                   mutex_unlock(&n->lock);
> > > > > > > > > > > +                   return -ENOMEM;
> > > > > > > > > > > +           }
> > > > > > > > > > > +           kfree(n->edid);
> > > > > > > > > > > +           n->edid = p;
> > > > > > > > > > > +           n->edid_allocated_size = size;
> > > > > > > > > > > +   }
> > > > > > > > > > > +   memcpy(n->edid, edid, size);
> > > > > > > > > > > +   n->edid_size = size;
> > > > > > > > > > > +   blocking_notifier_call_chain(&n->notifiers, HDMI_NEW_EDID, n);
> > > > > > > > > > > +   mutex_unlock(&n->lock);
> > > > > > > > > > > +   return 0;
> > > > > > > > > > > +}
> > > > > > > > > > > +EXPORT_SYMBOL_GPL(hdmi_event_new_edid);
> > > > > > > > > > > +
> > > > > > > > > > > +void hdmi_event_new_eld(struct hdmi_notifier *n, const u8 eld[128])
> > > > > > > > > > > +{
> > > > > > > > > > > +   mutex_lock(&n->lock);
> > > > > > > > > > > +   memcpy(n->eld, eld, sizeof(n->eld));
> > > > > > > > > > > +   n->has_eld = true;
> > > > > > > > > > > +   blocking_notifier_call_chain(&n->notifiers, HDMI_NEW_ELD, n);
> > > > > > > > > > > +   mutex_unlock(&n->lock);
> > > > > > > > > > > +}
> > > > > > > > > > > +EXPORT_SYMBOL_GPL(hdmi_event_new_eld);
> > > > > > > > > > > diff --git a/include/linux/hdmi-notifier.h b/include/linux/hdmi-notifier.h
> > > > > > > > > > > new file mode 100644
> > > > > > > > > > > index 000000000000..c8f35110e3e3
> > > > > > > > > > > --- /dev/null
> > > > > > > > > > > +++ b/include/linux/hdmi-notifier.h
> > > > > > > > > > > @@ -0,0 +1,112 @@
> > > > > > > > > > > +/* SPDX-License-Identifier: GPL-2.0
> > > > > > > > > > > + * hdmi-notifier.h - notify interested parties of (dis)connect and EDID
> > > > > > > > > > > + * events
> > > > > > > > > > > + *
> > > > > > > > > > > + * Copyright 2016 Russell King <rmk+kernel@arm.linux.org.uk>
> > > > > > > > > > > + * Copyright 2016 Cisco Systems, Inc. and/or its affiliates.
> > > > > > > > > > > + * All rights reserved.
> > > > > > > > > > > + */
> > > > > > > > > > > +
> > > > > > > > > > > +#ifndef LINUX_HDMI_NOTIFIER_H
> > > > > > > > > > > +#define LINUX_HDMI_NOTIFIER_H
> > > > > > > > > > > +
> > > > > > > > > > > +#include <linux/types.h>
> > > > > > > > > > > +#include <linux/notifier.h>
> > > > > > > > > > > +#include <linux/kref.h>
> > > > > > > > > > > +
> > > > > > > > > > > +enum {
> > > > > > > > > > > +   HDMI_CONNECTED,
> > > > > > > > > > > +   HDMI_DISCONNECTED,
> > > > > > > > > > > +   HDMI_NEW_EDID,
> > > > > > > > > > > +   HDMI_NEW_ELD,
> > > > > > > > > > > +};
> > > > > > > > > > > +
> > > > > > > > > > > +struct device;
> > > > > > > > > > > +
> > > > > > > > > > > +struct hdmi_notifier {
> > > > > > > > > > > +   /* Lock to protect callback registration and notification. */
> > > > > > > > > > > +   struct mutex lock;
> > > > > > > > > > > +   struct list_head head;
> > > > > > > > > > > +   struct kref kref;
> > > > > > > > > > > +   struct blocking_notifier_head notifiers;
> > > > > > > > > > > +   struct device *dev;
> > > > > > > > > > > +
> > > > > > > > > > > +   /* Current state */
> > > > > > > > > > > +   unsigned int connected : 1;
> > > > > > > > > > > +   unsigned int has_eld : 1;
> > > > > > > > > > > +   unsigned char eld[128];
> > > > > > > > > > > +   void *edid;
> > > > > > > > > > > +   size_t edid_size;
> > > > > > > > > > > +   size_t edid_allocated_size;
> > > > > > > > > > > +};
> > > > > > > > > > > +
> > > > > > > > > > > +/**
> > > > > > > > > > > + * hdmi_notifier_get - find or create a new hdmi_notifier for the given device.
> > > > > > > > > > > + * @dev: device that sends the events.
> > > > > > > > > > > + *
> > > > > > > > > > > + * If a notifier for device @dev already exists, then increase the refcount
> > > > > > > > > > > + * and return that notifier.
> > > > > > > > > > > + *
> > > > > > > > > > > + * If it doesn't exist, then allocate a new notifier struct and return a
> > > > > > > > > > > + * pointer to that new struct.
> > > > > > > > > > > + *
> > > > > > > > > > > + * Return NULL if the memory could not be allocated.
> > > > > > > > > > > + */
> > > > > > > > > > > +struct hdmi_notifier *hdmi_notifier_get(struct device *dev);
> > > > > > > > > > > +
> > > > > > > > > > > +/**
> > > > > > > > > > > + * hdmi_notifier_put - decrease refcount and delete when the refcount reaches 0.
> > > > > > > > > > > + * @n: notifier
> > > > > > > > > > > + */
> > > > > > > > > > > +void hdmi_notifier_put(struct hdmi_notifier *n);
> > > > > > > > > > > +
> > > > > > > > > > > +/**
> > > > > > > > > > > + * hdmi_notifier_register - register the notifier with the notifier_block.
> > > > > > > > > > > + * @n: the HDMI notifier
> > > > > > > > > > > + * @nb: the notifier_block
> > > > > > > > > > > + */
> > > > > > > > > > > +int hdmi_notifier_register(struct hdmi_notifier *n, struct notifier_block *nb);
> > > > > > > > > > > +
> > > > > > > > > > > +/**
> > > > > > > > > > > + * hdmi_notifier_unregister - unregister the notifier with the notifier_block.
> > > > > > > > > > > + * @n: the HDMI notifier
> > > > > > > > > > > + * @nb: the notifier_block
> > > > > > > > > > > + */
> > > > > > > > > > > +int hdmi_notifier_unregister(struct hdmi_notifier *n,
> > > > > > > > > > > +                        struct notifier_block *nb);
> > > > > > > > > > > +
> > > > > > > > > > > +/**
> > > > > > > > > > > + * hdmi_event_connect - send a connect event.
> > > > > > > > > > > + * @n: the HDMI notifier
> > > > > > > > > > > + *
> > > > > > > > > > > + * Send an HDMI_CONNECTED event to any registered parties.
> > > > > > > > > > > + */
> > > > > > > > > > > +void hdmi_event_connect(struct hdmi_notifier *n);
> > > > > > > > > > > +
> > > > > > > > > > > +/**
> > > > > > > > > > > + * hdmi_event_disconnect - send a disconnect event.
> > > > > > > > > > > + * @n: the HDMI notifier
> > > > > > > > > > > + *
> > > > > > > > > > > + * Send an HDMI_DISCONNECTED event to any registered parties.
> > > > > > > > > > > + */
> > > > > > > > > > > +void hdmi_event_disconnect(struct hdmi_notifier *n);
> > > > > > > > > > > +
> > > > > > > > > > > +/**
> > > > > > > > > > > + * hdmi_event_new_edid - send a new EDID event.
> > > > > > > > > > > + * @n: the HDMI notifier
> > > > > > > > > > > + *
> > > > > > > > > > > + * Send an HDMI_NEW_EDID event to any registered parties.
> > > > > > > > > > > + * This function will make a copy the EDID so it can return -ENOMEM if
> > > > > > > > > > > + * no memory could be allocated.
> > > > > > > > > > > + */
> > > > > > > > > > > +int hdmi_event_new_edid(struct hdmi_notifier *n, const void *edid, size_t size);
> > > > > > > > > > > +
> > > > > > > > > > > +/**
> > > > > > > > > > > + * hdmi_event_new_eld - send a new ELD event.
> > > > > > > > > > > + * @n: the HDMI notifier
> > > > > > > > > > > + *
> > > > > > > > > > > + * Send an HDMI_NEW_ELD event to any registered parties.
> > > > > > > > > > > + */
> > > > > > > > > > > +void hdmi_event_new_eld(struct hdmi_notifier *n, const u8 eld[128]);
> > > > > > > > > > > +
> > > > > > > > > > > +#endif
> > > > > > > > > > >
> > > > > > > > > >
> > > > > > > > >
> > > > > > > > > --
> > > > > > > > > Daniel Vetter
> > > > > > > > > Software Engineer, Intel Corporation
> > > > > > > > > http://blog.ffwll.ch
> > > > > > >
> > > > > > > --
> > > > > > > Daniel Vetter
> > > > > > > Software Engineer, Intel Corporation
> > > > > > > http://blog.ffwll.ch
> > > > >
> > > > > --
> > > > > Daniel Vetter
> > > > > Software Engineer, Intel Corporation
> > > > > http://blog.ffwll.ch
> > >
> > > --
> > > Daniel Vetter
> > > Software Engineer, Intel Corporation
> > > http://blog.ffwll.ch
>
> --
> Daniel Vetter
> Software Engineer, Intel Corporation
> http://blog.ffwll.ch

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 1/7] video: add HDMI state notifier support
  2019-06-20 13:23                       ` Cheng-yi Chiang
@ 2019-06-20 21:12                         ` Daniel Vetter
  2019-06-21  9:39                           ` Cheng-yi Chiang
  0 siblings, 1 reply; 30+ messages in thread
From: Daniel Vetter @ 2019-06-20 21:12 UTC (permalink / raw)
  To: Cheng-yi Chiang
  Cc: moderated list:SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEM...,
	Heiko Stuebner, Liam Girdwood, David Airlie, dri-devel,
	Takashi Iwai, Hans Verkuil, Andrzej Hajda, Laurent Pinchart,
	linux-rockchip, Dylan Reid, linux-media, devicetree, tzungbi,
	Daniel Vetter, Bartlomiej Zolnierkiewicz, Russell King,
	Rob Herring, Jaroslav Kysela, linux-arm-kernel,
	Greg Kroah-Hartman, Doug Anderson, linux-kernel, Mark Brown,
	Philipp Zabel, Dariusz Marcinkiewicz

Massively cutting this thread, since halfway through in my previous reply
I realized that maybe hdmi_codec is a much better starting point.

On Thu, Jun 20, 2019 at 09:23:23PM +0800, Cheng-yi Chiang wrote:
> On Thu, Jun 20, 2019 at 5:25 PM Daniel Vetter <daniel@ffwll.ch> wrote:
> > Yeah fully agreeing that hdmi_audio_code is probably a better starting
> > point. Problem is that becuase hdmi_codec is built on top of platform
> > device it's quite a bit harder to extend with callbacks and things like
> > that, without breaking the driver model.
> >
> > I need to think about this more, but if all we need to look at is
> > hdmi_codec, then I think this becomes a lot easier. And we can ignore
> > drm_audio_component.h completely.
> 
> 
> It is surprising that you think this way.
> Maybe the original patch before hdmi-notifier was introduced is the
> better way to solve this issue, if we only need to look at hdmi_codec.
> 
> The history of hdmi_codec driver is in this patch series:
> 
> https://lore.kernel.org/patchwork/patch/539656/

Hm, this doesn't seem to be the hdmi_codec driver I meant, but another,
new one. I was talking about SND_SOC_HDMI_CODEC.

> There was a callback mechanism implemented between dw-hdmi and hdmi
> codec driver.
> It was later consolidated by Doug in this patch for better jack status
> reporting:
> 
> https://chromium-review.googlesource.com/c/chromiumos/third_party/kernel/+/303573/

Hm that still seems entirely separate hdmi-codec specific to dw-hdmi only
...

> I am not sure why the original patch series did not get fully accepted
> in the upstream.
> It was quite long time ago.
> 
> But if you think this might be the right way to do, then it is even
> better for us because the patch series and Doug's patch had been quite
> stable
> on our RK3288 products for about four years with plenty of users, so
> we have much higher confidence in them.
> I can rebase and clean up them and post another patch for review.
> 
> Please let me know what approach you feel is better.
> Thanks again!

Not sure we're talking about the same. What I had in mind is to add jack
status to the hdmi-codec.c stuff, which is used by multiple soc drm
display drivers already. Looking at git grep output, there seems to be
already some support for dw-hdmi synopsys drm_bridge driver. I thought of
extending that. Does that not work for you?

Thanks, Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 1/7] video: add HDMI state notifier support
  2019-06-20 21:12                         ` Daniel Vetter
@ 2019-06-21  9:39                           ` Cheng-yi Chiang
  0 siblings, 0 replies; 30+ messages in thread
From: Cheng-yi Chiang @ 2019-06-21  9:39 UTC (permalink / raw)
  To: Cheng-yi Chiang, Hans Verkuil, linux-kernel,
	Bartlomiej Zolnierkiewicz, Greg Kroah-Hartman, Philipp Zabel,
	Mark Brown, Liam Girdwood, Takashi Iwai, Jaroslav Kysela,
	Russell King, Andrzej Hajda, Laurent Pinchart, David Airlie,
	Rob Herring, Heiko Stuebner, Doug Anderson, Dylan Reid, tzungbi,
	linux-media,
	moderated list:SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEM...,
	dri-devel, linux-arm-kernel, linux-rockchip, devicetree,
	Dariusz Marcinkiewicz
  Cc: Daniel Vetter

On Fri, Jun 21, 2019 at 5:12 AM Daniel Vetter <daniel@ffwll.ch> wrote:
>
> Massively cutting this thread, since halfway through in my previous reply
> I realized that maybe hdmi_codec is a much better starting point.
>
ACK
> On Thu, Jun 20, 2019 at 09:23:23PM +0800, Cheng-yi Chiang wrote:
> > On Thu, Jun 20, 2019 at 5:25 PM Daniel Vetter <daniel@ffwll.ch> wrote:
> > > Yeah fully agreeing that hdmi_audio_code is probably a better starting
> > > point. Problem is that becuase hdmi_codec is built on top of platform
> > > device it's quite a bit harder to extend with callbacks and things like
> > > that, without breaking the driver model.
> > >
> > > I need to think about this more, but if all we need to look at is
> > > hdmi_codec, then I think this becomes a lot easier. And we can ignore
> > > drm_audio_component.h completely.
> >
> >
> > It is surprising that you think this way.
> > Maybe the original patch before hdmi-notifier was introduced is the
> > better way to solve this issue, if we only need to look at hdmi_codec.
> >
> > The history of hdmi_codec driver is in this patch series:
> >
> > https://lore.kernel.org/patchwork/patch/539656/
>
> Hm, this doesn't seem to be the hdmi_codec driver I meant, but another,
> new one. I was talking about SND_SOC_HDMI_CODEC.
>
Yes you are right. They are different codec drivers.
Sorry for the confusion. What I meant was that my use case on RK3288
was using dw-hdmi-audio.c codec driver,
which was later replaced by a more general version hdmi-codec.c.

> > There was a callback mechanism implemented between dw-hdmi and hdmi
> > codec driver.
> > It was later consolidated by Doug in this patch for better jack status
> > reporting:
> >
> > https://chromium-review.googlesource.com/c/chromiumos/third_party/kernel/+/303573/
>
> Hm that still seems entirely separate hdmi-codec specific to dw-hdmi only
> ...
>
Again you are right. Sorry for the confusion. What I meant is that
this callback mechanism should work on hdmi-codec.c driver as well.

> > I am not sure why the original patch series did not get fully accepted
> > in the upstream.
> > It was quite long time ago.
> >
> > But if you think this might be the right way to do, then it is even
> > better for us because the patch series and Doug's patch had been quite
> > stable
> > on our RK3288 products for about four years with plenty of users, so
> > we have much higher confidence in them.
> > I can rebase and clean up them and post another patch for review.
> >
> > Please let me know what approach you feel is better.
> > Thanks again!
>
> Not sure we're talking about the same. What I had in mind is to add jack
> status to the hdmi-codec.c stuff, which is used by multiple soc drm
> display drivers already. Looking at git grep output, there seems to be
> already some support for dw-hdmi synopsys drm_bridge driver. I thought of
> extending that. Does that not work for you?
>
I think extending current interface will work.
There is a struct hdmi_codec_pdata to let ALSA codec driver access
some ops through platform data.
And after this patch

https://lore.kernel.org/patchwork/patch/692324/

ALSA codec driver can get access to the struct on DRM side.
Based on this I can add a new ops to register callback function for jack status.
It will be similar to Doug's chromium patch above.
I think that is quite a feasible way, and can benefit all boards using
hdmi-codec.c.

Thanks a lot!!

> Thanks, Daniel
> --
> Daniel Vetter
> Software Engineer, Intel Corporation
> http://blog.ffwll.ch

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 5/7] ASoC: rockchip: rockchip-max98090: Add node for HDMI
  2019-06-03  4:32 ` [PATCH 5/7] ASoC: rockchip: rockchip-max98090: Add node " Cheng-Yi Chiang
@ 2019-07-09 20:01   ` Rob Herring
  2019-07-10  4:11     ` Cheng-yi Chiang
  0 siblings, 1 reply; 30+ messages in thread
From: Rob Herring @ 2019-07-09 20:01 UTC (permalink / raw)
  To: Cheng-Yi Chiang
  Cc: alsa-devel, Heiko Stuebner, Liam Girdwood, David Airlie,
	dri-devel, Takashi Iwai, Hans Verkuil, Andrzej Hajda,
	Laurent Pinchart, linux-rockchip, dgreid, linux-media,
	devicetree, tzungbi, Philipp Zabel, Bartlomiej Zolnierkiewicz,
	Russell King, Mark Brown, Jaroslav Kysela, linux-arm-kernel,
	Greg Kroah-Hartman, dianders, linux-kernel, Daniel Vetter

On Mon, Jun 03, 2019 at 12:32:49PM +0800, Cheng-Yi Chiang wrote:
> Let user specify HDMI node so machine driver can use it to let codec
> driver register callback on correct hdmi-notifier.
> 
> Signed-off-by: Cheng-Yi Chiang <cychiang@chromium.org>
> ---
>  Documentation/devicetree/bindings/sound/rockchip-max98090.txt | 2 ++
>  1 file changed, 2 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/sound/rockchip-max98090.txt b/Documentation/devicetree/bindings/sound/rockchip-max98090.txt
> index a805aa99ad75..dae57c14864e 100644
> --- a/Documentation/devicetree/bindings/sound/rockchip-max98090.txt
> +++ b/Documentation/devicetree/bindings/sound/rockchip-max98090.txt
> @@ -7,6 +7,7 @@ Required properties:
>    connected to the CODEC
>  - rockchip,audio-codec: The phandle of the MAX98090 audio codec
>  - rockchip,headset-codec: The phandle of Ext chip for jack detection
> +- rockchip,hdmi: The phandle of HDMI node for HDMI jack detection
>  
>  Example:
>  
> @@ -16,4 +17,5 @@ sound {
>  	rockchip,i2s-controller = <&i2s>;
>  	rockchip,audio-codec = <&max98090>;
>  	rockchip,headset-codec = <&headsetcodec>;
> +	rockchip,hdmi= <&hdmi>;

space                ^

With that,

Acked-by: Rob Herring <robh@kernel.org>

>  };
> -- 
> 2.22.0.rc1.257.g3120a18244-goog
> 

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 5/7] ASoC: rockchip: rockchip-max98090: Add node for HDMI
  2019-07-09 20:01   ` Rob Herring
@ 2019-07-10  4:11     ` Cheng-yi Chiang
  0 siblings, 0 replies; 30+ messages in thread
From: Cheng-yi Chiang @ 2019-07-10  4:11 UTC (permalink / raw)
  To: Rob Herring
  Cc: moderated list:SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEM...,
	Heiko Stuebner, Liam Girdwood, David Airlie, dri-devel,
	Takashi Iwai, Hans Verkuil, Andrzej Hajda, Laurent Pinchart,
	linux-rockchip, Dylan Reid, linux-media, devicetree, tzungbi,
	Philipp Zabel, Bartlomiej Zolnierkiewicz, Russell King,
	Mark Brown, Jaroslav Kysela, linux-arm-kernel,
	Greg Kroah-Hartman, Doug Anderson, linux-kernel, Daniel Vetter

On Wed, Jul 10, 2019 at 4:01 AM Rob Herring <robh@kernel.org> wrote:
>
> On Mon, Jun 03, 2019 at 12:32:49PM +0800, Cheng-Yi Chiang wrote:
> > Let user specify HDMI node so machine driver can use it to let codec
> > driver register callback on correct hdmi-notifier.
> >
> > Signed-off-by: Cheng-Yi Chiang <cychiang@chromium.org>
> > ---
> >  Documentation/devicetree/bindings/sound/rockchip-max98090.txt | 2 ++
> >  1 file changed, 2 insertions(+)
> >
> > diff --git a/Documentation/devicetree/bindings/sound/rockchip-max98090.txt b/Documentation/devicetree/bindings/sound/rockchip-max98090.txt
> > index a805aa99ad75..dae57c14864e 100644
> > --- a/Documentation/devicetree/bindings/sound/rockchip-max98090.txt
> > +++ b/Documentation/devicetree/bindings/sound/rockchip-max98090.txt
> > @@ -7,6 +7,7 @@ Required properties:
> >    connected to the CODEC
> >  - rockchip,audio-codec: The phandle of the MAX98090 audio codec
> >  - rockchip,headset-codec: The phandle of Ext chip for jack detection
> > +- rockchip,hdmi: The phandle of HDMI node for HDMI jack detection
> >
> >  Example:
> >
> > @@ -16,4 +17,5 @@ sound {
> >       rockchip,i2s-controller = <&i2s>;
> >       rockchip,audio-codec = <&max98090>;
> >       rockchip,headset-codec = <&headsetcodec>;
> > +     rockchip,hdmi= <&hdmi>;
>
> space                ^
>
> With that,
>
> Acked-by: Rob Herring <robh@kernel.org>
>
Hi Rob,
Thank you for the review.
But I have changed the approach in v2 so there is no need for machine
driver to expose this property.
Thanks!
> >  };
> > --
> > 2.22.0.rc1.257.g3120a18244-goog
> >

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 30+ messages in thread

end of thread, back to index

Thread overview: 30+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-06-03  4:32 [PATCH 0/7] Add HDMI audio support on RK3288 veyron board Cheng-Yi Chiang
2019-06-03  4:32 ` [PATCH 1/7] video: add HDMI state notifier support Cheng-Yi Chiang
2019-06-03  7:45   ` Hans Verkuil
2019-06-03  8:09     ` Daniel Vetter
2019-06-03  9:05       ` Hans Verkuil
2019-06-04  7:19         ` Daniel Vetter
2019-06-04  2:32       ` Cheng-yi Chiang
2019-06-04  7:24         ` Daniel Vetter
2019-06-11 12:10           ` Cheng-yi Chiang
2019-06-11 12:34             ` Daniel Vetter
2019-06-18 11:48               ` Cheng-yi Chiang
2019-06-18 12:12                 ` Daniel Vetter
2019-06-19 11:48                   ` Cheng-yi Chiang
2019-06-20  9:25                     ` Daniel Vetter
2019-06-20 13:23                       ` Cheng-yi Chiang
2019-06-20 21:12                         ` Daniel Vetter
2019-06-21  9:39                           ` Cheng-yi Chiang
2019-06-11 13:10             ` Hans Verkuil
2019-06-18 11:54               ` Cheng-yi Chiang
2019-06-04  1:48     ` Cheng-yi Chiang
2019-06-03  4:32 ` [PATCH 2/7] ASoC: hdmi-codec: use HDMI state notifier to add jack support Cheng-Yi Chiang
2019-06-03  8:03   ` [alsa-devel] " Amadeusz Sławiński
2019-06-03  8:53     ` Cheng-yi Chiang
2019-06-03  4:32 ` [PATCH 3/7] drm/bridge/synopsys: dw-hdmi: Add HDMI notifier support Cheng-Yi Chiang
2019-06-03  4:32 ` [PATCH 4/7] ASoC: rockchip_max98090: Add dai_link for HDMI Cheng-Yi Chiang
2019-06-03  4:32 ` [PATCH 5/7] ASoC: rockchip: rockchip-max98090: Add node " Cheng-Yi Chiang
2019-07-09 20:01   ` Rob Herring
2019-07-10  4:11     ` Cheng-yi Chiang
2019-06-03  4:32 ` [PATCH 6/7] ASoC: rockchip_max98090: Add HDMI jack support Cheng-Yi Chiang
2019-06-03  4:32 ` [PATCH 7/7] ARM: dts: rockchip: Specify HDMI node to sound card node Cheng-Yi Chiang

Linux-ARM-Kernel Archive on lore.kernel.org

Archives are clonable:
	git clone --mirror https://lore.kernel.org/linux-arm-kernel/0 linux-arm-kernel/git/0.git
	git clone --mirror https://lore.kernel.org/linux-arm-kernel/1 linux-arm-kernel/git/1.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 linux-arm-kernel linux-arm-kernel/ https://lore.kernel.org/linux-arm-kernel \
		linux-arm-kernel@lists.infradead.org infradead-linux-arm-kernel@archiver.kernel.org
	public-inbox-index linux-arm-kernel

Example config snippet for mirrors

Newsgroup available over NNTP:
	nntp://nntp.lore.kernel.org/org.infradead.lists.linux-arm-kernel


AGPL code for this site: git clone https://public-inbox.org/ public-inbox