This patch makes dw-hdmi pass DRM connector info to a respective
CEC adapter. In order to be able to do that it delays creation of
the dw-hdmi-cec platform device until DRM connector is initialized.

Requires testing.

Signed-off-by: Dariusz Marcinkiewicz <dar...@google.com>
---
 drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.c |  5 +-
 drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.h |  2 +
 drivers/gpu/drm/bridge/synopsys/dw-hdmi.c     | 82 +++++++++++--------
 3 files changed, 52 insertions(+), 37 deletions(-)

diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.c 
b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.c
index 84fb7b6a0a5e0..cf879629e0726 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.c
@@ -232,6 +232,7 @@ static void dw_hdmi_cec_del(void *data)
 static int dw_hdmi_cec_probe(struct platform_device *pdev)
 {
        struct dw_hdmi_cec_data *data = dev_get_platdata(&pdev->dev);
+       struct cec_connector_info conn_info;
        struct dw_hdmi_cec *cec;
        int ret;
 
@@ -258,10 +259,12 @@ static int dw_hdmi_cec_probe(struct platform_device *pdev)
        dw_hdmi_write(cec, ~0, HDMI_IH_MUTE_CEC_STAT0);
        dw_hdmi_write(cec, 0, HDMI_CEC_POLARITY);
 
+       cec_fill_connector_info(&conn_info, data->connector);
+
        cec->adap = cec_allocate_adapter(&dw_hdmi_cec_ops, cec, "dw_hdmi",
                                         CEC_CAP_LOG_ADDRS | CEC_CAP_TRANSMIT |
                                         CEC_CAP_RC | CEC_CAP_PASSTHROUGH,
-                                        CEC_MAX_LOG_ADDRS, NULL);
+                                        CEC_MAX_LOG_ADDRS, &conn_info);
        if (IS_ERR(cec->adap))
                return PTR_ERR(cec->adap);
 
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.h 
b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.h
index cf4dc121a2c43..a2ac91ec845ed 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.h
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.h
@@ -1,6 +1,7 @@
 #ifndef DW_HDMI_CEC_H
 #define DW_HDMI_CEC_H
 
+struct drm_connector;
 struct dw_hdmi;
 
 struct dw_hdmi_cec_ops {
@@ -13,6 +14,7 @@ struct dw_hdmi_cec_ops {
 struct dw_hdmi_cec_data {
        struct dw_hdmi *hdmi;
        const struct dw_hdmi_cec_ops *ops;
+       const struct drm_connector *connector;
        int irq;
 };
 
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c 
b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
index db761329a1e3e..6aaf0a7db9818 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
@@ -138,6 +138,8 @@ struct dw_hdmi {
        struct drm_connector connector;
        struct drm_bridge bridge;
 
+       int irq;
+
        unsigned int version;
 
        struct platform_device *audio;
@@ -189,6 +191,7 @@ struct dw_hdmi {
        void (*enable_audio)(struct dw_hdmi *hdmi);
        void (*disable_audio)(struct dw_hdmi *hdmi);
 
+       bool cec_configured;
        struct cec_notifier *cec_notifier;
 };
 
@@ -2105,6 +2108,29 @@ static const struct drm_connector_helper_funcs 
dw_hdmi_connector_helper_funcs =
        .get_modes = dw_hdmi_connector_get_modes,
 };
 
+static void dw_hdmi_cec_enable(struct dw_hdmi *hdmi)
+{
+       mutex_lock(&hdmi->mutex);
+       hdmi->mc_clkdis &= ~HDMI_MC_CLKDIS_CECCLK_DISABLE;
+       hdmi_writeb(hdmi, hdmi->mc_clkdis, HDMI_MC_CLKDIS);
+       mutex_unlock(&hdmi->mutex);
+}
+
+static void dw_hdmi_cec_disable(struct dw_hdmi *hdmi)
+{
+       mutex_lock(&hdmi->mutex);
+       hdmi->mc_clkdis |= HDMI_MC_CLKDIS_CECCLK_DISABLE;
+       hdmi_writeb(hdmi, hdmi->mc_clkdis, HDMI_MC_CLKDIS);
+       mutex_unlock(&hdmi->mutex);
+}
+
+static const struct dw_hdmi_cec_ops dw_hdmi_cec_ops = {
+       .write = hdmi_writeb,
+       .read = hdmi_readb,
+       .enable = dw_hdmi_cec_enable,
+       .disable = dw_hdmi_cec_disable,
+};
+
 static int dw_hdmi_bridge_attach(struct drm_bridge *bridge)
 {
        struct dw_hdmi *hdmi = bridge->driver_private;
@@ -2121,6 +2147,23 @@ static int dw_hdmi_bridge_attach(struct drm_bridge 
*bridge)
 
        drm_connector_attach_encoder(connector, encoder);
 
+       if (hdmi->cec_configured) {
+               struct platform_device_info pdevinfo;
+               struct dw_hdmi_cec_data cec;
+
+               cec.hdmi = hdmi;
+               cec.ops = &dw_hdmi_cec_ops;
+               cec.irq = hdmi->irq;
+               cec.connector = connector;
+
+               pdevinfo.name = "dw-hdmi-cec";
+               pdevinfo.data = &cec;
+               pdevinfo.size_data = sizeof(cec);
+               pdevinfo.dma_mask = 0;
+
+               hdmi->cec = platform_device_register_full(&pdevinfo);
+       }
+
        return 0;
 }
 
@@ -2390,29 +2433,6 @@ static int dw_hdmi_detect_phy(struct dw_hdmi *hdmi)
        return -ENODEV;
 }
 
-static void dw_hdmi_cec_enable(struct dw_hdmi *hdmi)
-{
-       mutex_lock(&hdmi->mutex);
-       hdmi->mc_clkdis &= ~HDMI_MC_CLKDIS_CECCLK_DISABLE;
-       hdmi_writeb(hdmi, hdmi->mc_clkdis, HDMI_MC_CLKDIS);
-       mutex_unlock(&hdmi->mutex);
-}
-
-static void dw_hdmi_cec_disable(struct dw_hdmi *hdmi)
-{
-       mutex_lock(&hdmi->mutex);
-       hdmi->mc_clkdis |= HDMI_MC_CLKDIS_CECCLK_DISABLE;
-       hdmi_writeb(hdmi, hdmi->mc_clkdis, HDMI_MC_CLKDIS);
-       mutex_unlock(&hdmi->mutex);
-}
-
-static const struct dw_hdmi_cec_ops dw_hdmi_cec_ops = {
-       .write = hdmi_writeb,
-       .read = hdmi_readb,
-       .enable = dw_hdmi_cec_enable,
-       .disable = dw_hdmi_cec_disable,
-};
-
 static const struct regmap_config hdmi_regmap_8bit_config = {
        .reg_bits       = 32,
        .val_bits       = 8,
@@ -2435,7 +2455,6 @@ __dw_hdmi_probe(struct platform_device *pdev,
        struct device_node *np = dev->of_node;
        struct platform_device_info pdevinfo;
        struct device_node *ddc_node;
-       struct dw_hdmi_cec_data cec;
        struct dw_hdmi *hdmi;
        struct resource *iores = NULL;
        int irq;
@@ -2585,6 +2604,7 @@ __dw_hdmi_probe(struct platform_device *pdev,
                ret = irq;
                goto err_iahb;
        }
+       hdmi->irq = irq;
 
        ret = devm_request_threaded_irq(dev, irq, dw_hdmi_hardirq,
                                        dw_hdmi_irq, IRQF_SHARED,
@@ -2660,18 +2680,8 @@ __dw_hdmi_probe(struct platform_device *pdev,
                hdmi->audio = platform_device_register_full(&pdevinfo);
        }
 
-       if (config0 & HDMI_CONFIG0_CEC) {
-               cec.hdmi = hdmi;
-               cec.ops = &dw_hdmi_cec_ops;
-               cec.irq = irq;
-
-               pdevinfo.name = "dw-hdmi-cec";
-               pdevinfo.data = &cec;
-               pdevinfo.size_data = sizeof(cec);
-               pdevinfo.dma_mask = 0;
-
-               hdmi->cec = platform_device_register_full(&pdevinfo);
-       }
+       if (config0 & HDMI_CONFIG0_CEC)
+               hdmi->cec_configured = true;
 
        /* Reset HDMI DDC I2C master controller and mute I2CM interrupts */
        if (hdmi->i2c)
-- 
2.18.1

Reply via email to