Blob Blame History Raw
From: Hans Verkuil <hans.verkuil@cisco.com>
Date: Mon, 11 Sep 2017 14:29:52 +0200
Subject: drm/tegra: hdmi: Add cec-notifier support
Git-commit: fb83be8873909ba7c089d1c5cb72873cc2cce7d1
Patch-mainline: v4.15-rc1
References: FATE#326289 FATE#326079 FATE#326049 FATE#322398 FATE#326166

In order to support CEC the HDMI driver has to inform the CEC driver
whenever the physical address changes. So when the EDID is read the
CEC driver has to be informed and whenever the hotplug detect goes
away.

This is done through the cec-notifier framework.

The link between the HDMI driver and the CEC driver is done through
the hdmi-phandle property in the tegra-cec node in the device tree.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Thierry Reding <treding@nvidia.com>
Acked-by: Petr Tesarik <ptesarik@suse.com>
---
 drivers/gpu/drm/tegra/Kconfig  |    1 +
 drivers/gpu/drm/tegra/drm.h    |    3 +++
 drivers/gpu/drm/tegra/hdmi.c   |    9 +++++++++
 drivers/gpu/drm/tegra/output.c |    6 ++++++
 4 files changed, 19 insertions(+)

--- a/drivers/gpu/drm/tegra/Kconfig
+++ b/drivers/gpu/drm/tegra/Kconfig
@@ -9,6 +9,7 @@ config DRM_TEGRA
 	select DRM_PANEL
 	select TEGRA_HOST1X
 	select IOMMU_IOVA if IOMMU_SUPPORT
+	select CEC_CORE if CEC_NOTIFIER
 	help
 	  Choose this option if you have an NVIDIA Tegra SoC.
 
--- a/drivers/gpu/drm/tegra/drm.h
+++ b/drivers/gpu/drm/tegra/drm.h
@@ -119,6 +119,8 @@ void *tegra_drm_alloc(struct tegra_drm *
 void tegra_drm_free(struct tegra_drm *tegra, size_t size, void *virt,
 		    dma_addr_t iova);
 
+struct cec_notifier;
+
 struct tegra_output {
 	struct device_node *of_node;
 	struct device *dev;
@@ -126,6 +128,7 @@ struct tegra_output {
 	struct drm_panel *panel;
 	struct i2c_adapter *ddc;
 	const struct edid *edid;
+	struct cec_notifier *notifier;
 	unsigned int hpd_irq;
 	int hpd_gpio;
 	enum of_gpio_flags hpd_gpio_flags;
--- a/drivers/gpu/drm/tegra/hdmi.c
+++ b/drivers/gpu/drm/tegra/hdmi.c
@@ -22,6 +22,8 @@
 
 #include <sound/hda_verbs.h>
 
+#include <media/cec-notifier.h>
+
 #include "hdmi.h"
 #include "drm.h"
 #include "dc.h"
@@ -1721,6 +1723,10 @@ static int tegra_hdmi_probe(struct platf
 		return PTR_ERR(hdmi->vdd);
 	}
 
+	hdmi->output.notifier = cec_notifier_get(&pdev->dev);
+	if (hdmi->output.notifier == NULL)
+		return -ENOMEM;
+
 	hdmi->output.dev = &pdev->dev;
 
 	err = tegra_output_probe(&hdmi->output);
@@ -1779,6 +1785,9 @@ static int tegra_hdmi_remove(struct plat
 
 	tegra_output_remove(&hdmi->output);
 
+	if (hdmi->output.notifier)
+		cec_notifier_put(hdmi->output.notifier);
+
 	return 0;
 }
 
--- a/drivers/gpu/drm/tegra/output.c
+++ b/drivers/gpu/drm/tegra/output.c
@@ -11,6 +11,8 @@
 #include <drm/drm_panel.h>
 #include "drm.h"
 
+#include <media/cec-notifier.h>
+
 int tegra_output_connector_get_modes(struct drm_connector *connector)
 {
 	struct tegra_output *output = connector_to_output(connector);
@@ -32,6 +34,7 @@ int tegra_output_connector_get_modes(str
 	else if (output->ddc)
 		edid = drm_get_edid(connector, output->ddc);
 
+	cec_notifier_set_phys_addr_from_edid(output->notifier, edid);
 	drm_mode_connector_update_edid_property(connector, edid);
 
 	if (edid) {
@@ -68,6 +71,9 @@ tegra_output_connector_detect(struct drm
 			status = connector_status_connected;
 	}
 
+	if (status != connector_status_connected)
+		cec_notifier_phys_addr_invalidate(output->notifier);
+
 	return status;
 }