[PATCH v5 2/3] drm/bridge: dw-hdmi: pass connector info to the CEC adapter
From: Dariusz Marcinkiewicz
Date: Thu May 16 2019 - 10:02:41 EST
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 <darekm@xxxxxxxxxx>
---
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