Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7070fe73 authored by Dariusz Marcinkiewicz's avatar Dariusz Marcinkiewicz Committed by Neil Armstrong
Browse files

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: default avatarDariusz Marcinkiewicz <darekm@google.com>
Acked-by: default avatarHans Verkuil <hverkuil-cisco@xs4all.nl>
Tested-by: default avatarHans Verkuil <hverkuil-cisco@xs4all.nl>
Reviewed-by: default avatarNeil Armstrong <narmstrong@baylibre.com>
Signed-off-by: default avatarNeil Armstrong <narmstrong@baylibre.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20190814104520.6001-9-darekm@google.com
parent 96158346
Loading
Loading
Loading
Loading
+30 −15
Original line number Diff line number Diff line
@@ -190,6 +190,7 @@ struct dw_hdmi {
	void (*enable_audio)(struct dw_hdmi *hdmi);
	void (*disable_audio)(struct dw_hdmi *hdmi);

	struct mutex cec_notifier_mutex;
	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 drm_encoder *encoder = bridge->encoder;
	struct drm_connector *connector = &hdmi->connector;
	struct cec_connector_info conn_info;
	struct cec_notifier *notifier;

	connector->interlace_allowed = 1;
	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);

	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;
}

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
dw_hdmi_bridge_mode_valid(struct drm_bridge *bridge,
			  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 = {
	.attach = dw_hdmi_bridge_attach,
	.detach = dw_hdmi_bridge_detach,
	.enable = dw_hdmi_bridge_enable,
	.disable = dw_hdmi_bridge_disable,
	.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_RX_SENSE);

		if ((phy_stat & (HDMI_PHY_RX_SENSE | HDMI_PHY_HPD)) == 0)
			cec_notifier_set_phys_addr(hdmi->cec_notifier,
						   CEC_PHYS_ADDR_INVALID);
		if ((phy_stat & (HDMI_PHY_RX_SENSE | HDMI_PHY_HPD)) == 0) {
			mutex_lock(&hdmi->cec_notifier_mutex);
			cec_notifier_phys_addr_invalidate(hdmi->cec_notifier);
			mutex_unlock(&hdmi->cec_notifier_mutex);
		}
	}

	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->audio_mutex);
	mutex_init(&hdmi->cec_notifier_mutex);
	spin_lock_init(&hdmi->audio_lock);

	ddc_node = of_parse_phandle(np, "ddc-i2c-bus", 0);
@@ -2729,12 +2756,6 @@ __dw_hdmi_probe(struct platform_device *pdev,
	if (ret)
		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
	 * N and cts values before enabling phy
@@ -2833,9 +2854,6 @@ __dw_hdmi_probe(struct platform_device *pdev,
		hdmi->ddc = NULL;
	}

	if (hdmi->cec_notifier)
		cec_notifier_put(hdmi->cec_notifier);

	clk_disable_unprepare(hdmi->iahb_clk);
	if (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 */
	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->isfr_clk);
	if (hdmi->cec_clk)