drm/tegra: hdmi: Add cec-notifier support
authorHans Verkuil <hans.verkuil@cisco.com>
Mon, 11 Sep 2017 12:29:52 +0000 (14:29 +0200)
committerThierry Reding <treding@nvidia.com>
Fri, 20 Oct 2017 12:19:54 +0000 (14:19 +0200)
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>
drivers/gpu/drm/tegra/Kconfig
drivers/gpu/drm/tegra/drm.h
drivers/gpu/drm/tegra/hdmi.c
drivers/gpu/drm/tegra/output.c

index dc58ab140151f24bcde9baed20602428f6b37d83..cf54847a8bd1756411562447bb5665096bce356a 100644 (file)
@@ -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.
 
index 9bb6e8ebe40c16692e68af0dff92b5ab7a508bf8..ddae331ad8b6b9369c5f5f9ddfb30b6d295ec06a 100644 (file)
@@ -119,6 +119,8 @@ void *tegra_drm_alloc(struct tegra_drm *tegra, size_t size, dma_addr_t *iova);
 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;
index a4e9c769fc7a18273e873523d3f9f6c45b8d69e4..6434b3d3d1ba4da8bf2b1838df90a89267838098 100644 (file)
@@ -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 platform_device *pdev)
                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 platform_device *pdev)
 
        tegra_output_remove(&hdmi->output);
 
+       if (hdmi->output.notifier)
+               cec_notifier_put(hdmi->output.notifier);
+
        return 0;
 }
 
index 595d1ec3e02e8ff6e42c0574b0d1d1218bd8210f..1cfbacea811396c9db03927561e619d43da72b72 100644 (file)
@@ -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(struct drm_connector *connector)
        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_connector *connector, bool force)
                        status = connector_status_connected;
        }
 
+       if (status != connector_status_connected)
+               cec_notifier_phys_addr_invalidate(output->notifier);
+
        return status;
 }