mirror of https://gitee.com/openkylin/linux.git
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:
parent
96158346b5
commit
7070fe7386
|
@ -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)
|
||||||
|
|
Loading…
Reference in New Issue