drm: dw-hdmi: use cec_notifier_conn_(un)register

Use the new cec_notifier_conn_(un)register() functions to
(un)register the notifier for the HDMI connector, and fill in
the cec_connector_info.

Changes since v6:
        - move cec_notifier_conn_unregister to a bridge detach
	  function,
	- add a mutex protecting a CEC notifier.
Changes since v4:
	- typo fix
Changes since v2:
	- removed unnecessary NULL check before a call to
	cec_notifier_conn_unregister,
	- use cec_notifier_phys_addr_invalidate to invalidate physical
	address.
Changes since v1:
	Add memory barrier to make sure that the notifier
	becomes visible to the irq thread once it is fully
	constructed.

Signed-off-by: Dariusz Marcinkiewicz <darekm@google.com>
Acked-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
Tested-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
Reviewed-by: Neil Armstrong <narmstrong@baylibre.com>
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20190814104520.6001-9-darekm@google.com
This commit is contained in:
Dariusz Marcinkiewicz 2019-08-14 12:45:06 +02:00 committed by Neil Armstrong
parent 96158346b5
commit 7070fe7386
1 changed files with 30 additions and 15 deletions

View File

@ -190,6 +190,7 @@ struct dw_hdmi {
void (*enable_audio)(struct dw_hdmi *hdmi); void (*enable_audio)(struct dw_hdmi *hdmi);
void (*disable_audio)(struct dw_hdmi *hdmi); void (*disable_audio)(struct dw_hdmi *hdmi);
struct mutex cec_notifier_mutex;
struct cec_notifier *cec_notifier; struct cec_notifier *cec_notifier;
}; };
@ -2230,6 +2231,8 @@ static int dw_hdmi_bridge_attach(struct drm_bridge *bridge)
struct dw_hdmi *hdmi = bridge->driver_private; struct dw_hdmi *hdmi = bridge->driver_private;
struct drm_encoder *encoder = bridge->encoder; struct drm_encoder *encoder = bridge->encoder;
struct drm_connector *connector = &hdmi->connector; struct drm_connector *connector = &hdmi->connector;
struct cec_connector_info conn_info;
struct cec_notifier *notifier;
connector->interlace_allowed = 1; connector->interlace_allowed = 1;
connector->polled = DRM_CONNECTOR_POLL_HPD; connector->polled = DRM_CONNECTOR_POLL_HPD;
@ -2243,9 +2246,29 @@ static int dw_hdmi_bridge_attach(struct drm_bridge *bridge)
drm_connector_attach_encoder(connector, encoder); drm_connector_attach_encoder(connector, encoder);
cec_fill_conn_info_from_drm(&conn_info, connector);
notifier = cec_notifier_conn_register(hdmi->dev, NULL, &conn_info);
if (!notifier)
return -ENOMEM;
mutex_lock(&hdmi->cec_notifier_mutex);
hdmi->cec_notifier = notifier;
mutex_unlock(&hdmi->cec_notifier_mutex);
return 0; return 0;
} }
static void dw_hdmi_bridge_detach(struct drm_bridge *bridge)
{
struct dw_hdmi *hdmi = bridge->driver_private;
mutex_lock(&hdmi->cec_notifier_mutex);
cec_notifier_conn_unregister(hdmi->cec_notifier);
hdmi->cec_notifier = NULL;
mutex_unlock(&hdmi->cec_notifier_mutex);
}
static enum drm_mode_status static enum drm_mode_status
dw_hdmi_bridge_mode_valid(struct drm_bridge *bridge, dw_hdmi_bridge_mode_valid(struct drm_bridge *bridge,
const struct drm_display_mode *mode) const struct drm_display_mode *mode)
@ -2302,6 +2325,7 @@ static void dw_hdmi_bridge_enable(struct drm_bridge *bridge)
static const struct drm_bridge_funcs dw_hdmi_bridge_funcs = { static const struct drm_bridge_funcs dw_hdmi_bridge_funcs = {
.attach = dw_hdmi_bridge_attach, .attach = dw_hdmi_bridge_attach,
.detach = dw_hdmi_bridge_detach,
.enable = dw_hdmi_bridge_enable, .enable = dw_hdmi_bridge_enable,
.disable = dw_hdmi_bridge_disable, .disable = dw_hdmi_bridge_disable,
.mode_set = dw_hdmi_bridge_mode_set, .mode_set = dw_hdmi_bridge_mode_set,
@ -2409,9 +2433,11 @@ static irqreturn_t dw_hdmi_irq(int irq, void *dev_id)
phy_stat & HDMI_PHY_HPD, phy_stat & HDMI_PHY_HPD,
phy_stat & HDMI_PHY_RX_SENSE); phy_stat & HDMI_PHY_RX_SENSE);
if ((phy_stat & (HDMI_PHY_RX_SENSE | HDMI_PHY_HPD)) == 0) if ((phy_stat & (HDMI_PHY_RX_SENSE | HDMI_PHY_HPD)) == 0) {
cec_notifier_set_phys_addr(hdmi->cec_notifier, mutex_lock(&hdmi->cec_notifier_mutex);
CEC_PHYS_ADDR_INVALID); cec_notifier_phys_addr_invalidate(hdmi->cec_notifier);
mutex_unlock(&hdmi->cec_notifier_mutex);
}
} }
if (intr_stat & HDMI_IH_PHY_STAT0_HPD) { if (intr_stat & HDMI_IH_PHY_STAT0_HPD) {
@ -2597,6 +2623,7 @@ __dw_hdmi_probe(struct platform_device *pdev,
mutex_init(&hdmi->mutex); mutex_init(&hdmi->mutex);
mutex_init(&hdmi->audio_mutex); mutex_init(&hdmi->audio_mutex);
mutex_init(&hdmi->cec_notifier_mutex);
spin_lock_init(&hdmi->audio_lock); spin_lock_init(&hdmi->audio_lock);
ddc_node = of_parse_phandle(np, "ddc-i2c-bus", 0); ddc_node = of_parse_phandle(np, "ddc-i2c-bus", 0);
@ -2729,12 +2756,6 @@ __dw_hdmi_probe(struct platform_device *pdev,
if (ret) if (ret)
goto err_iahb; goto err_iahb;
hdmi->cec_notifier = cec_notifier_get(dev);
if (!hdmi->cec_notifier) {
ret = -ENOMEM;
goto err_iahb;
}
/* /*
* To prevent overflows in HDMI_IH_FC_STAT2, set the clk regenerator * To prevent overflows in HDMI_IH_FC_STAT2, set the clk regenerator
* N and cts values before enabling phy * N and cts values before enabling phy
@ -2833,9 +2854,6 @@ __dw_hdmi_probe(struct platform_device *pdev,
hdmi->ddc = NULL; hdmi->ddc = NULL;
} }
if (hdmi->cec_notifier)
cec_notifier_put(hdmi->cec_notifier);
clk_disable_unprepare(hdmi->iahb_clk); clk_disable_unprepare(hdmi->iahb_clk);
if (hdmi->cec_clk) if (hdmi->cec_clk)
clk_disable_unprepare(hdmi->cec_clk); clk_disable_unprepare(hdmi->cec_clk);
@ -2857,9 +2875,6 @@ static void __dw_hdmi_remove(struct dw_hdmi *hdmi)
/* Disable all interrupts */ /* Disable all interrupts */
hdmi_writeb(hdmi, ~0, HDMI_IH_MUTE_PHY_STAT0); hdmi_writeb(hdmi, ~0, HDMI_IH_MUTE_PHY_STAT0);
if (hdmi->cec_notifier)
cec_notifier_put(hdmi->cec_notifier);
clk_disable_unprepare(hdmi->iahb_clk); clk_disable_unprepare(hdmi->iahb_clk);
clk_disable_unprepare(hdmi->isfr_clk); clk_disable_unprepare(hdmi->isfr_clk);
if (hdmi->cec_clk) if (hdmi->cec_clk)