dri-devel.lists.freedesktop.org archive mirror
 help / color / mirror / Atom feed
* [PATCHv3 0/6] drm/omap: hdmi: improve hdmi4 CEC, add CEC for hdmi5
@ 2021-04-28 13:25 Hans Verkuil
  2021-04-28 13:25 ` [PATCHv3 1/6] drm: drm_bridge: add connector_attach/detach bridge ops Hans Verkuil
                   ` (5 more replies)
  0 siblings, 6 replies; 10+ messages in thread
From: Hans Verkuil @ 2021-04-28 13:25 UTC (permalink / raw)
  To: linux-media; +Cc: Tony Lindgren, Tomi Valkeinen, Laurent Pinchart, dri-devel

This series improves the drm_bridge support for CEC by introducing two
new bridge ops in the first patch, and using those in the second patch.

This makes it possible to call cec_s_conn_info() and set
CEC_CAP_CONNECTOR_INFO for the CEC adapter, so userspace can associate
the CEC adapter with the corresponding DRM connector.

The third patch simplifies CEC physical address handling by using the
cec_s_phys_addr_from_edid helper function that didn't exist when this
code was originally written.

The fourth patch adds the cec clock to ti,omap5-dss.txt.

The fifth patch the missing cec clock to the dra7 and omap5 device tree,
and the last patch adds CEC support to the OMAP5 driver.

Tested with a Pandaboard and a Beagle X15 board.

Regards,

	Hans

Changes since v2:

- connector_attach can now return an error. If an error is
  returned then connector_detach is called in reverse order
  to clean up any previous connector_attach calls.

- connector_attach in hdmi4 and hdmi5 now return 0.

Changes since v1:

- as per suggestion from Laurent, changed cec_init/exit to
  connector_attach/_detach which are just called for all
  bridges. The DRM_BRIDGE_OP_CEC was dropped.

- added patch to add the cec clock to ti,omap5-dss.txt

- swapped the order of the last two patches

- incorporated Tomi's suggestions for the hdmi5 CEC support.

Hans Verkuil (6):
  drm: drm_bridge: add connector_attach/detach bridge ops
  drm/omapdrm/dss/hdmi4: switch to the connector bridge ops
  drm/omapdrm/dss/hdmi4: simplify CEC Phys Addr handling
  dt-bindings: display: ti: ti,omap5-dss.txt: add cec clock
  dra7.dtsi/omap5.dtsi: add cec clock
  drm/omapdrm/dss/hdmi5: add CEC support

 .../bindings/display/ti/ti,omap5-dss.txt      |   4 +-
 arch/arm/boot/dts/dra7.dtsi                   |   5 +-
 arch/arm/boot/dts/omap5.dtsi                  |   5 +-
 drivers/gpu/drm/drm_bridge_connector.c        |  25 ++-
 drivers/gpu/drm/omapdrm/Kconfig               |   8 +
 drivers/gpu/drm/omapdrm/Makefile              |   1 +
 drivers/gpu/drm/omapdrm/dss/hdmi.h            |   1 +
 drivers/gpu/drm/omapdrm/dss/hdmi4.c           |  41 ++--
 drivers/gpu/drm/omapdrm/dss/hdmi4_cec.c       |  13 +-
 drivers/gpu/drm/omapdrm/dss/hdmi4_cec.h       |  12 +-
 drivers/gpu/drm/omapdrm/dss/hdmi5.c           |  64 +++++-
 drivers/gpu/drm/omapdrm/dss/hdmi5_cec.c       | 209 ++++++++++++++++++
 drivers/gpu/drm/omapdrm/dss/hdmi5_cec.h       |  42 ++++
 drivers/gpu/drm/omapdrm/dss/hdmi5_core.c      |  35 ++-
 drivers/gpu/drm/omapdrm/dss/hdmi5_core.h      |  33 ++-
 include/drm/drm_bridge.h                      |  27 +++
 16 files changed, 470 insertions(+), 55 deletions(-)
 create mode 100644 drivers/gpu/drm/omapdrm/dss/hdmi5_cec.c
 create mode 100644 drivers/gpu/drm/omapdrm/dss/hdmi5_cec.h

-- 
2.30.2

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCHv3 1/6] drm: drm_bridge: add connector_attach/detach bridge ops
  2021-04-28 13:25 [PATCHv3 0/6] drm/omap: hdmi: improve hdmi4 CEC, add CEC for hdmi5 Hans Verkuil
@ 2021-04-28 13:25 ` Hans Verkuil
  2021-05-04  8:26   ` Tomi Valkeinen
  2021-04-28 13:25 ` [PATCHv3 2/6] drm/omapdrm/dss/hdmi4: switch to the connector " Hans Verkuil
                   ` (4 subsequent siblings)
  5 siblings, 1 reply; 10+ messages in thread
From: Hans Verkuil @ 2021-04-28 13:25 UTC (permalink / raw)
  To: linux-media
  Cc: Tony Lindgren, Tomi Valkeinen, Laurent Pinchart, dri-devel, Hans Verkuil

Add bridge connector_attach/detach ops. These ops are called when a
bridge is attached or detached to a drm_connector. These ops can be
used to register and unregister an HDMI CEC adapter for a bridge that
supports CEC.

Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
---
 drivers/gpu/drm/drm_bridge_connector.c | 25 +++++++++++++++++++++++-
 include/drm/drm_bridge.h               | 27 ++++++++++++++++++++++++++
 2 files changed, 51 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/drm_bridge_connector.c b/drivers/gpu/drm/drm_bridge_connector.c
index 791379816837..0676677badfe 100644
--- a/drivers/gpu/drm/drm_bridge_connector.c
+++ b/drivers/gpu/drm/drm_bridge_connector.c
@@ -203,6 +203,11 @@ static void drm_bridge_connector_destroy(struct drm_connector *connector)
 {
 	struct drm_bridge_connector *bridge_connector =
 		to_drm_bridge_connector(connector);
+	struct drm_bridge *bridge;
+
+	drm_for_each_bridge_in_chain(bridge_connector->encoder, bridge)
+		if (bridge->funcs->connector_detach)
+			bridge->funcs->connector_detach(bridge, connector);
 
 	if (bridge_connector->bridge_hpd) {
 		struct drm_bridge *hpd = bridge_connector->bridge_hpd;
@@ -318,6 +323,7 @@ struct drm_connector *drm_bridge_connector_init(struct drm_device *drm,
 	struct i2c_adapter *ddc = NULL;
 	struct drm_bridge *bridge;
 	int connector_type;
+	int ret;
 
 	bridge_connector = kzalloc(sizeof(*bridge_connector), GFP_KERNEL);
 	if (!bridge_connector)
@@ -375,6 +381,23 @@ struct drm_connector *drm_bridge_connector_init(struct drm_device *drm,
 		connector->polled = DRM_CONNECTOR_POLL_CONNECT
 				  | DRM_CONNECTOR_POLL_DISCONNECT;
 
-	return connector;
+	ret = 0;
+	/* call connector_attach for all bridges */
+	drm_for_each_bridge_in_chain(encoder, bridge) {
+		if (!bridge->funcs->connector_attach)
+			continue;
+		ret = bridge->funcs->connector_attach(bridge, connector);
+		if (ret)
+			break;
+	}
+	if (!ret)
+		return connector;
+
+	/* on error, detach any previously successfully attached connectors */
+	list_for_each_entry_continue_reverse(bridge, &(encoder)->bridge_chain,
+					     chain_node)
+		if (bridge->funcs->connector_detach)
+			bridge->funcs->connector_detach(bridge, connector);
+	return ERR_PTR(ret);
 }
 EXPORT_SYMBOL_GPL(drm_bridge_connector_init);
diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h
index 2195daa289d2..333fbc3a03e9 100644
--- a/include/drm/drm_bridge.h
+++ b/include/drm/drm_bridge.h
@@ -629,6 +629,33 @@ struct drm_bridge_funcs {
 	 * the DRM_BRIDGE_OP_HPD flag in their &drm_bridge->ops.
 	 */
 	void (*hpd_disable)(struct drm_bridge *bridge);
+
+	/**
+	 * @connector_attach:
+	 *
+	 * This callback is invoked whenever our bridge is being attached to a
+	 * &drm_connector. This is where an HDMI CEC adapter can be registered.
+	 *
+	 * The @connector_attach callback is optional.
+	 *
+	 * RETURNS:
+	 *
+	 * Zero on success, error code on failure.
+	 */
+	int (*connector_attach)(struct drm_bridge *bridge,
+				struct drm_connector *conn);
+
+	/**
+	 * @connector_detach:
+	 *
+	 * This callback is invoked whenever our bridge is being detached from a
+	 * &drm_connector. This is where an HDMI CEC adapter can be
+	 * unregistered.
+	 *
+	 * The @connector_detach callback is optional.
+	 */
+	void (*connector_detach)(struct drm_bridge *bridge,
+				 struct drm_connector *conn);
 };
 
 /**
-- 
2.30.2

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCHv3 2/6] drm/omapdrm/dss/hdmi4: switch to the connector bridge ops
  2021-04-28 13:25 [PATCHv3 0/6] drm/omap: hdmi: improve hdmi4 CEC, add CEC for hdmi5 Hans Verkuil
  2021-04-28 13:25 ` [PATCHv3 1/6] drm: drm_bridge: add connector_attach/detach bridge ops Hans Verkuil
@ 2021-04-28 13:25 ` Hans Verkuil
  2021-04-28 13:25 ` [PATCHv3 3/6] drm/omapdrm/dss/hdmi4: simplify CEC Phys Addr handling Hans Verkuil
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 10+ messages in thread
From: Hans Verkuil @ 2021-04-28 13:25 UTC (permalink / raw)
  To: linux-media
  Cc: Tony Lindgren, Tomi Valkeinen, Laurent Pinchart, dri-devel, Hans Verkuil

Implement the new connector_attach/detach bridge ops. This makes it
possible to associate a CEC adapter with a drm connector, which helps
userspace determine which cec device node belongs to which drm connector.

Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
---
 drivers/gpu/drm/omapdrm/dss/hdmi4.c     | 28 ++++++++++++++++++-------
 drivers/gpu/drm/omapdrm/dss/hdmi4_cec.c |  9 +++++---
 drivers/gpu/drm/omapdrm/dss/hdmi4_cec.h |  7 ++++---
 3 files changed, 30 insertions(+), 14 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi4.c b/drivers/gpu/drm/omapdrm/dss/hdmi4.c
index 35b750cebaeb..e29d4d186265 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi4.c
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi4.c
@@ -482,6 +482,23 @@ static struct edid *hdmi4_bridge_get_edid(struct drm_bridge *bridge,
 	return edid;
 }
 
+static int hdmi4_bridge_connector_attach(struct drm_bridge *bridge,
+					 struct drm_connector *conn)
+{
+	struct omap_hdmi *hdmi = drm_bridge_to_hdmi(bridge);
+
+	hdmi4_cec_init(hdmi->pdev, &hdmi->core, &hdmi->wp, conn);
+	return 0;
+}
+
+static void hdmi4_bridge_connector_detach(struct drm_bridge *bridge,
+					  struct drm_connector *conn)
+{
+	struct omap_hdmi *hdmi = drm_bridge_to_hdmi(bridge);
+
+	hdmi4_cec_uninit(&hdmi->core);
+}
+
 static const struct drm_bridge_funcs hdmi4_bridge_funcs = {
 	.attach = hdmi4_bridge_attach,
 	.mode_set = hdmi4_bridge_mode_set,
@@ -492,6 +509,8 @@ static const struct drm_bridge_funcs hdmi4_bridge_funcs = {
 	.atomic_disable = hdmi4_bridge_disable,
 	.hpd_notify = hdmi4_bridge_hpd_notify,
 	.get_edid = hdmi4_bridge_get_edid,
+	.connector_attach = hdmi4_bridge_connector_attach,
+	.connector_detach = hdmi4_bridge_connector_detach,
 };
 
 static void hdmi4_bridge_init(struct omap_hdmi *hdmi)
@@ -647,14 +666,10 @@ static int hdmi4_bind(struct device *dev, struct device *master, void *data)
 	if (r)
 		goto err_runtime_put;
 
-	r = hdmi4_cec_init(hdmi->pdev, &hdmi->core, &hdmi->wp);
-	if (r)
-		goto err_pll_uninit;
-
 	r = hdmi_audio_register(hdmi);
 	if (r) {
 		DSSERR("Registering HDMI audio failed\n");
-		goto err_cec_uninit;
+		goto err_pll_uninit;
 	}
 
 	hdmi->debugfs = dss_debugfs_create_file(dss, "hdmi", hdmi_dump_regs,
@@ -664,8 +679,6 @@ static int hdmi4_bind(struct device *dev, struct device *master, void *data)
 
 	return 0;
 
-err_cec_uninit:
-	hdmi4_cec_uninit(&hdmi->core);
 err_pll_uninit:
 	hdmi_pll_uninit(&hdmi->pll);
 err_runtime_put:
@@ -682,7 +695,6 @@ static void hdmi4_unbind(struct device *dev, struct device *master, void *data)
 	if (hdmi->audio_pdev)
 		platform_device_unregister(hdmi->audio_pdev);
 
-	hdmi4_cec_uninit(&hdmi->core);
 	hdmi_pll_uninit(&hdmi->pll);
 }
 
diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi4_cec.c b/drivers/gpu/drm/omapdrm/dss/hdmi4_cec.c
index 43592c1cf081..80ec52c9c846 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi4_cec.c
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi4_cec.c
@@ -335,10 +335,10 @@ void hdmi4_cec_set_phys_addr(struct hdmi_core_data *core, u16 pa)
 }
 
 int hdmi4_cec_init(struct platform_device *pdev, struct hdmi_core_data *core,
-		  struct hdmi_wp_data *wp)
+		   struct hdmi_wp_data *wp, struct drm_connector *conn)
 {
-	const u32 caps = CEC_CAP_TRANSMIT | CEC_CAP_LOG_ADDRS |
-			 CEC_CAP_PASSTHROUGH | CEC_CAP_RC;
+	const u32 caps = CEC_CAP_DEFAULTS | CEC_CAP_CONNECTOR_INFO;
+	struct cec_connector_info conn_info;
 	int ret;
 
 	core->adap = cec_allocate_adapter(&hdmi_cec_adap_ops, core,
@@ -346,6 +346,8 @@ int hdmi4_cec_init(struct platform_device *pdev, struct hdmi_core_data *core,
 	ret = PTR_ERR_OR_ZERO(core->adap);
 	if (ret < 0)
 		return ret;
+	cec_fill_conn_info_from_drm(&conn_info, conn);
+	cec_s_conn_info(core->adap, &conn_info);
 	core->wp = wp;
 
 	/* Disable clock initially, hdmi_cec_adap_enable() manages it */
@@ -354,6 +356,7 @@ int hdmi4_cec_init(struct platform_device *pdev, struct hdmi_core_data *core,
 	ret = cec_register_adapter(core->adap, &pdev->dev);
 	if (ret < 0) {
 		cec_delete_adapter(core->adap);
+		core->adap = NULL;
 		return ret;
 	}
 	return 0;
diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi4_cec.h b/drivers/gpu/drm/omapdrm/dss/hdmi4_cec.h
index 0292337c97cc..b59a54c3040e 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi4_cec.h
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi4_cec.h
@@ -29,7 +29,7 @@ struct platform_device;
 void hdmi4_cec_set_phys_addr(struct hdmi_core_data *core, u16 pa);
 void hdmi4_cec_irq(struct hdmi_core_data *core);
 int hdmi4_cec_init(struct platform_device *pdev, struct hdmi_core_data *core,
-		  struct hdmi_wp_data *wp);
+		   struct hdmi_wp_data *wp, struct drm_connector *conn);
 void hdmi4_cec_uninit(struct hdmi_core_data *core);
 #else
 static inline void hdmi4_cec_set_phys_addr(struct hdmi_core_data *core, u16 pa)
@@ -41,8 +41,9 @@ static inline void hdmi4_cec_irq(struct hdmi_core_data *core)
 }
 
 static inline int hdmi4_cec_init(struct platform_device *pdev,
-				struct hdmi_core_data *core,
-				struct hdmi_wp_data *wp)
+				 struct hdmi_core_data *core,
+				 struct hdmi_wp_data *wp,
+				 struct drm_connector *conn)
 {
 	return 0;
 }
-- 
2.30.2

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCHv3 3/6] drm/omapdrm/dss/hdmi4: simplify CEC Phys Addr handling
  2021-04-28 13:25 [PATCHv3 0/6] drm/omap: hdmi: improve hdmi4 CEC, add CEC for hdmi5 Hans Verkuil
  2021-04-28 13:25 ` [PATCHv3 1/6] drm: drm_bridge: add connector_attach/detach bridge ops Hans Verkuil
  2021-04-28 13:25 ` [PATCHv3 2/6] drm/omapdrm/dss/hdmi4: switch to the connector " Hans Verkuil
@ 2021-04-28 13:25 ` Hans Verkuil
  2021-04-28 13:25 ` [PATCHv3 4/6] dt-bindings: display: ti: ti, omap5-dss.txt: add cec clock Hans Verkuil
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 10+ messages in thread
From: Hans Verkuil @ 2021-04-28 13:25 UTC (permalink / raw)
  To: linux-media
  Cc: Tony Lindgren, Tomi Valkeinen, Laurent Pinchart, dri-devel, Hans Verkuil

Switch to using cec_s_phys_addr_from_edid() instead of a two-step process
of calling cec_get_edid_phys_addr() followed by cec_s_phys_addr().

Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
---
 drivers/gpu/drm/omapdrm/dss/hdmi4.c     | 13 ++-----------
 drivers/gpu/drm/omapdrm/dss/hdmi4_cec.c |  4 ++--
 drivers/gpu/drm/omapdrm/dss/hdmi4_cec.h |  5 +++--
 3 files changed, 7 insertions(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi4.c b/drivers/gpu/drm/omapdrm/dss/hdmi4.c
index e29d4d186265..40f791c668f4 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi4.c
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi4.c
@@ -432,7 +432,7 @@ static void hdmi4_bridge_hpd_notify(struct drm_bridge *bridge,
 	struct omap_hdmi *hdmi = drm_bridge_to_hdmi(bridge);
 
 	if (status == connector_status_disconnected)
-		hdmi4_cec_set_phys_addr(&hdmi->core, CEC_PHYS_ADDR_INVALID);
+		hdmi4_cec_set_phys_addr(&hdmi->core, NULL);
 }
 
 static struct edid *hdmi4_bridge_get_edid(struct drm_bridge *bridge,
@@ -440,7 +440,6 @@ static struct edid *hdmi4_bridge_get_edid(struct drm_bridge *bridge,
 {
 	struct omap_hdmi *hdmi = drm_bridge_to_hdmi(bridge);
 	struct edid *edid = NULL;
-	unsigned int cec_addr;
 	bool need_enable;
 	int r;
 
@@ -466,15 +465,7 @@ static struct edid *hdmi4_bridge_get_edid(struct drm_bridge *bridge,
 	hdmi_runtime_put(hdmi);
 	mutex_unlock(&hdmi->lock);
 
-	if (edid && edid->extensions) {
-		unsigned int len = (edid->extensions + 1) * EDID_LENGTH;
-
-		cec_addr = cec_get_edid_phys_addr((u8 *)edid, len, NULL);
-	} else {
-		cec_addr = CEC_PHYS_ADDR_INVALID;
-	}
-
-	hdmi4_cec_set_phys_addr(&hdmi->core, cec_addr);
+	hdmi4_cec_set_phys_addr(&hdmi->core, edid);
 
 	if (need_enable)
 		hdmi4_core_disable(&hdmi->core);
diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi4_cec.c b/drivers/gpu/drm/omapdrm/dss/hdmi4_cec.c
index 80ec52c9c846..cf406d86c845 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi4_cec.c
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi4_cec.c
@@ -329,9 +329,9 @@ static const struct cec_adap_ops hdmi_cec_adap_ops = {
 	.adap_transmit = hdmi_cec_adap_transmit,
 };
 
-void hdmi4_cec_set_phys_addr(struct hdmi_core_data *core, u16 pa)
+void hdmi4_cec_set_phys_addr(struct hdmi_core_data *core, struct edid *edid)
 {
-	cec_s_phys_addr(core->adap, pa, false);
+	cec_s_phys_addr_from_edid(core->adap, edid);
 }
 
 int hdmi4_cec_init(struct platform_device *pdev, struct hdmi_core_data *core,
diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi4_cec.h b/drivers/gpu/drm/omapdrm/dss/hdmi4_cec.h
index b59a54c3040e..16bf259643b7 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi4_cec.h
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi4_cec.h
@@ -26,13 +26,14 @@ struct platform_device;
 
 /* HDMI CEC funcs */
 #ifdef CONFIG_OMAP4_DSS_HDMI_CEC
-void hdmi4_cec_set_phys_addr(struct hdmi_core_data *core, u16 pa);
+void hdmi4_cec_set_phys_addr(struct hdmi_core_data *core, struct edid *edid);
 void hdmi4_cec_irq(struct hdmi_core_data *core);
 int hdmi4_cec_init(struct platform_device *pdev, struct hdmi_core_data *core,
 		   struct hdmi_wp_data *wp, struct drm_connector *conn);
 void hdmi4_cec_uninit(struct hdmi_core_data *core);
 #else
-static inline void hdmi4_cec_set_phys_addr(struct hdmi_core_data *core, u16 pa)
+static inline void hdmi4_cec_set_phys_addr(struct hdmi_core_data *core,
+					   struct edid *edid)
 {
 }
 
-- 
2.30.2

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCHv3 4/6] dt-bindings: display: ti: ti, omap5-dss.txt: add cec clock
  2021-04-28 13:25 [PATCHv3 0/6] drm/omap: hdmi: improve hdmi4 CEC, add CEC for hdmi5 Hans Verkuil
                   ` (2 preceding siblings ...)
  2021-04-28 13:25 ` [PATCHv3 3/6] drm/omapdrm/dss/hdmi4: simplify CEC Phys Addr handling Hans Verkuil
@ 2021-04-28 13:25 ` Hans Verkuil
  2021-04-28 13:25 ` [PATCHv3 5/6] dra7.dtsi/omap5.dtsi: " Hans Verkuil
  2021-04-28 13:25 ` [PATCHv3 6/6] drm/omapdrm/dss/hdmi5: add CEC support Hans Verkuil
  5 siblings, 0 replies; 10+ messages in thread
From: Hans Verkuil @ 2021-04-28 13:25 UTC (permalink / raw)
  To: linux-media
  Cc: Tony Lindgren, Tomi Valkeinen, dri-devel, Laurent Pinchart, Hans Verkuil

The cec clock is required as well in order to support HDMI CEC,
document this.

Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
Acked-by: Rob Herring <robh@kernel.org>
---
 Documentation/devicetree/bindings/display/ti/ti,omap5-dss.txt | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/display/ti/ti,omap5-dss.txt b/Documentation/devicetree/bindings/display/ti/ti,omap5-dss.txt
index 20861218649f..c321c67472f0 100644
--- a/Documentation/devicetree/bindings/display/ti/ti,omap5-dss.txt
+++ b/Documentation/devicetree/bindings/display/ti/ti,omap5-dss.txt
@@ -89,8 +89,8 @@ Required properties:
 - interrupts: the HDMI interrupt line
 - ti,hwmods: "dss_hdmi"
 - vdda-supply: vdda power supply
-- clocks: handles to fclk and pll clock
-- clock-names: "fck", "sys_clk"
+- clocks: handles to fclk, pll and cec clock
+- clock-names: "fck", "sys_clk", "cec"
 
 Optional nodes:
 - Video port for HDMI output
-- 
2.30.2

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCHv3 5/6] dra7.dtsi/omap5.dtsi: add cec clock
  2021-04-28 13:25 [PATCHv3 0/6] drm/omap: hdmi: improve hdmi4 CEC, add CEC for hdmi5 Hans Verkuil
                   ` (3 preceding siblings ...)
  2021-04-28 13:25 ` [PATCHv3 4/6] dt-bindings: display: ti: ti, omap5-dss.txt: add cec clock Hans Verkuil
@ 2021-04-28 13:25 ` Hans Verkuil
  2021-04-28 13:25 ` [PATCHv3 6/6] drm/omapdrm/dss/hdmi5: add CEC support Hans Verkuil
  5 siblings, 0 replies; 10+ messages in thread
From: Hans Verkuil @ 2021-04-28 13:25 UTC (permalink / raw)
  To: linux-media
  Cc: Tony Lindgren, Tomi Valkeinen, Laurent Pinchart, dri-devel, Hans Verkuil

Add cec clock to the dra7 and omap5 device trees.

Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
Acked-by: Tony Lindgren <tony@atomide.com>
Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
---
 arch/arm/boot/dts/dra7.dtsi  | 5 +++--
 arch/arm/boot/dts/omap5.dtsi | 5 +++--
 2 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/arch/arm/boot/dts/dra7.dtsi b/arch/arm/boot/dts/dra7.dtsi
index ce1194744f84..efe579ddb324 100644
--- a/arch/arm/boot/dts/dra7.dtsi
+++ b/arch/arm/boot/dts/dra7.dtsi
@@ -879,8 +879,9 @@ hdmi: encoder@0 {
 						interrupts = <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>;
 						status = "disabled";
 						clocks = <&dss_clkctrl DRA7_DSS_DSS_CORE_CLKCTRL 9>,
-							 <&dss_clkctrl DRA7_DSS_DSS_CORE_CLKCTRL 10>;
-						clock-names = "fck", "sys_clk";
+							 <&dss_clkctrl DRA7_DSS_DSS_CORE_CLKCTRL 10>,
+							 <&dss_clkctrl DRA7_DSS_DSS_CORE_CLKCTRL 11>;
+						clock-names = "fck", "sys_clk", "cec";
 						dmas = <&sdma_xbar 76>;
 						dma-names = "audio_tx";
 					};
diff --git a/arch/arm/boot/dts/omap5.dtsi b/arch/arm/boot/dts/omap5.dtsi
index e025b7c9a357..6726e1f1b07c 100644
--- a/arch/arm/boot/dts/omap5.dtsi
+++ b/arch/arm/boot/dts/omap5.dtsi
@@ -586,8 +586,9 @@ hdmi: encoder@0 {
 						interrupts = <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>;
 						status = "disabled";
 						clocks = <&dss_clkctrl OMAP5_DSS_CORE_CLKCTRL 9>,
-							 <&dss_clkctrl OMAP5_DSS_CORE_CLKCTRL 10>;
-						clock-names = "fck", "sys_clk";
+							 <&dss_clkctrl OMAP5_DSS_CORE_CLKCTRL 10>,
+							 <&dss_clkctrl OMAP5_DSS_CORE_CLKCTRL 11>;
+						clock-names = "fck", "sys_clk", "cec";
 						dmas = <&sdma 76>;
 						dma-names = "audio_tx";
 					};
-- 
2.30.2

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCHv3 6/6] drm/omapdrm/dss/hdmi5: add CEC support
  2021-04-28 13:25 [PATCHv3 0/6] drm/omap: hdmi: improve hdmi4 CEC, add CEC for hdmi5 Hans Verkuil
                   ` (4 preceding siblings ...)
  2021-04-28 13:25 ` [PATCHv3 5/6] dra7.dtsi/omap5.dtsi: " Hans Verkuil
@ 2021-04-28 13:25 ` Hans Verkuil
  5 siblings, 0 replies; 10+ messages in thread
From: Hans Verkuil @ 2021-04-28 13:25 UTC (permalink / raw)
  To: linux-media
  Cc: Tony Lindgren, Tomi Valkeinen, Laurent Pinchart, dri-devel, Hans Verkuil

Add HDMI CEC support for OMAP5.

Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
---
 drivers/gpu/drm/omapdrm/Kconfig          |   8 +
 drivers/gpu/drm/omapdrm/Makefile         |   1 +
 drivers/gpu/drm/omapdrm/dss/hdmi.h       |   1 +
 drivers/gpu/drm/omapdrm/dss/hdmi5.c      |  64 +++++--
 drivers/gpu/drm/omapdrm/dss/hdmi5_cec.c  | 209 +++++++++++++++++++++++
 drivers/gpu/drm/omapdrm/dss/hdmi5_cec.h  |  42 +++++
 drivers/gpu/drm/omapdrm/dss/hdmi5_core.c |  35 +++-
 drivers/gpu/drm/omapdrm/dss/hdmi5_core.h |  33 +++-
 8 files changed, 374 insertions(+), 19 deletions(-)
 create mode 100644 drivers/gpu/drm/omapdrm/dss/hdmi5_cec.c
 create mode 100644 drivers/gpu/drm/omapdrm/dss/hdmi5_cec.h

diff --git a/drivers/gpu/drm/omapdrm/Kconfig b/drivers/gpu/drm/omapdrm/Kconfig
index e7281da5bc6a..08866ac7d869 100644
--- a/drivers/gpu/drm/omapdrm/Kconfig
+++ b/drivers/gpu/drm/omapdrm/Kconfig
@@ -80,6 +80,14 @@ config OMAP5_DSS_HDMI
 	  Definition Multimedia Interface. See http://www.hdmi.org/ for HDMI
 	  specification.
 
+config OMAP5_DSS_HDMI_CEC
+	bool "Enable HDMI CEC support for OMAP5"
+	depends on OMAP5_DSS_HDMI
+	select CEC_CORE
+	default y
+	help
+	  When selected the HDMI transmitter will support the CEC feature.
+
 config OMAP2_DSS_SDI
 	bool "SDI support"
 	default n
diff --git a/drivers/gpu/drm/omapdrm/Makefile b/drivers/gpu/drm/omapdrm/Makefile
index 21e8277ff88f..0732bd2dae1e 100644
--- a/drivers/gpu/drm/omapdrm/Makefile
+++ b/drivers/gpu/drm/omapdrm/Makefile
@@ -29,6 +29,7 @@ omapdrm-$(CONFIG_OMAP2_DSS_HDMI_COMMON) += dss/hdmi_common.o dss/hdmi_wp.o \
 omapdrm-$(CONFIG_OMAP4_DSS_HDMI) += dss/hdmi4.o dss/hdmi4_core.o
 omapdrm-$(CONFIG_OMAP4_DSS_HDMI_CEC) += dss/hdmi4_cec.o
 omapdrm-$(CONFIG_OMAP5_DSS_HDMI) += dss/hdmi5.o dss/hdmi5_core.o
+omapdrm-$(CONFIG_OMAP5_DSS_HDMI_CEC) += dss/hdmi5_cec.o
 ccflags-$(CONFIG_OMAP2_DSS_DEBUG) += -DDEBUG
 
 obj-$(CONFIG_DRM_OMAP) += omapdrm.o
diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi.h b/drivers/gpu/drm/omapdrm/dss/hdmi.h
index c4a4e07f0b99..72d8ae441da6 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi.h
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi.h
@@ -261,6 +261,7 @@ struct hdmi_core_data {
 	struct hdmi_wp_data *wp;
 	unsigned int core_pwr_cnt;
 	struct cec_adapter *adap;
+	struct clk *cec_clk;
 };
 
 static inline void hdmi_write_reg(void __iomem *base_addr, const u32 idx,
diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi5.c b/drivers/gpu/drm/omapdrm/dss/hdmi5.c
index 65085d886da5..11941d7b1d81 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi5.c
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi5.c
@@ -29,12 +29,14 @@
 #include <linux/of.h>
 #include <linux/of_graph.h>
 #include <sound/omap-hdmi-audio.h>
+#include <media/cec.h>
 
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_state_helper.h>
 
 #include "omapdss.h"
 #include "hdmi5_core.h"
+#include "hdmi5_cec.h"
 #include "dss.h"
 
 static int hdmi_runtime_get(struct omap_hdmi *hdmi)
@@ -105,6 +107,9 @@ static irqreturn_t hdmi_irq_handler(int irq, void *data)
 		hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_LDOON);
 	}
 
+	if (irqstatus & HDMI_IRQ_CORE)
+		hdmi5_core_handle_irqs(&hdmi->core);
+
 	return IRQ_HANDLED;
 }
 
@@ -112,9 +117,12 @@ static int hdmi_power_on_core(struct omap_hdmi *hdmi)
 {
 	int r;
 
+	if (hdmi->core.core_pwr_cnt++)
+		return 0;
+
 	r = regulator_enable(hdmi->vdda_reg);
 	if (r)
-		return r;
+		goto err_reg_enable;
 
 	r = hdmi_runtime_get(hdmi);
 	if (r)
@@ -129,12 +137,17 @@ static int hdmi_power_on_core(struct omap_hdmi *hdmi)
 
 err_runtime_get:
 	regulator_disable(hdmi->vdda_reg);
+err_reg_enable:
+	hdmi->core.core_pwr_cnt--;
 
 	return r;
 }
 
 static void hdmi_power_off_core(struct omap_hdmi *hdmi)
 {
+	if (--hdmi->core.core_pwr_cnt)
+		return;
+
 	hdmi->core_enabled = false;
 
 	hdmi_runtime_put(hdmi);
@@ -168,9 +181,9 @@ static int hdmi_power_on_full(struct omap_hdmi *hdmi)
 		pc, &hdmi_cinfo);
 
 	/* disable and clear irqs */
-	hdmi_wp_clear_irqenable(&hdmi->wp, 0xffffffff);
+	hdmi_wp_clear_irqenable(&hdmi->wp, ~HDMI_IRQ_CORE);
 	hdmi_wp_set_irqstatus(&hdmi->wp,
-			hdmi_wp_get_irqstatus(&hdmi->wp));
+			hdmi_wp_get_irqstatus(&hdmi->wp) & ~HDMI_IRQ_CORE);
 
 	r = dss_pll_enable(&hdmi->pll.pll);
 	if (r) {
@@ -225,7 +238,7 @@ static int hdmi_power_on_full(struct omap_hdmi *hdmi)
 
 static void hdmi_power_off_full(struct omap_hdmi *hdmi)
 {
-	hdmi_wp_clear_irqenable(&hdmi->wp, 0xffffffff);
+	hdmi_wp_clear_irqenable(&hdmi->wp, ~HDMI_IRQ_CORE);
 
 	hdmi_wp_video_stop(&hdmi->wp);
 
@@ -273,11 +286,11 @@ static void hdmi_stop_audio_stream(struct omap_hdmi *hd)
 	REG_FLD_MOD(hd->wp.base, HDMI_WP_SYSCONFIG, hd->wp_idlemode, 3, 2);
 }
 
-static int hdmi_core_enable(struct omap_hdmi *hdmi)
+int hdmi5_core_enable(struct omap_hdmi *hdmi)
 {
 	int r = 0;
 
-	DSSDBG("ENTER omapdss_hdmi_core_enable\n");
+	DSSDBG("ENTER %s\n", __func__);
 
 	mutex_lock(&hdmi->lock);
 
@@ -295,9 +308,9 @@ static int hdmi_core_enable(struct omap_hdmi *hdmi)
 	return r;
 }
 
-static void hdmi_core_disable(struct omap_hdmi *hdmi)
+void hdmi5_core_disable(struct omap_hdmi *hdmi)
 {
-	DSSDBG("Enter omapdss_hdmi_core_disable\n");
+	DSSDBG("ENTER %s\n", __func__);
 
 	mutex_lock(&hdmi->lock);
 
@@ -424,6 +437,15 @@ static void hdmi5_bridge_disable(struct drm_bridge *bridge,
 	mutex_unlock(&hdmi->lock);
 }
 
+static void hdmi5_bridge_hpd_notify(struct drm_bridge *bridge,
+				    enum drm_connector_status status)
+{
+	struct omap_hdmi *hdmi = drm_bridge_to_hdmi(bridge);
+
+	if (status == connector_status_disconnected)
+		hdmi5_cec_set_phys_addr(&hdmi->core, NULL);
+}
+
 static struct edid *hdmi5_bridge_get_edid(struct drm_bridge *bridge,
 					  struct drm_connector *connector)
 {
@@ -436,7 +458,7 @@ static struct edid *hdmi5_bridge_get_edid(struct drm_bridge *bridge,
 	need_enable = hdmi->core_enabled == false;
 
 	if (need_enable) {
-		r = hdmi_core_enable(hdmi);
+		r = hdmi5_core_enable(hdmi);
 		if (r)
 			return NULL;
 	}
@@ -460,12 +482,31 @@ static struct edid *hdmi5_bridge_get_edid(struct drm_bridge *bridge,
 	hdmi_runtime_put(hdmi);
 	mutex_unlock(&hdmi->lock);
 
+	hdmi5_cec_set_phys_addr(&hdmi->core, edid);
+
 	if (need_enable)
-		hdmi_core_disable(hdmi);
+		hdmi5_core_disable(hdmi);
 
 	return (struct edid *)edid;
 }
 
+static int hdmi5_bridge_connector_attach(struct drm_bridge *bridge,
+					 struct drm_connector *conn)
+{
+	struct omap_hdmi *hdmi = drm_bridge_to_hdmi(bridge);
+
+	hdmi5_cec_init(hdmi->pdev, &hdmi->core, &hdmi->wp, conn);
+	return 0;
+}
+
+static void hdmi5_bridge_connector_detach(struct drm_bridge *bridge,
+					  struct drm_connector *conn)
+{
+	struct omap_hdmi *hdmi = drm_bridge_to_hdmi(bridge);
+
+	hdmi5_cec_uninit(&hdmi->core);
+}
+
 static const struct drm_bridge_funcs hdmi5_bridge_funcs = {
 	.attach = hdmi5_bridge_attach,
 	.mode_set = hdmi5_bridge_mode_set,
@@ -474,7 +515,10 @@ static const struct drm_bridge_funcs hdmi5_bridge_funcs = {
 	.atomic_reset = drm_atomic_helper_bridge_reset,
 	.atomic_enable = hdmi5_bridge_enable,
 	.atomic_disable = hdmi5_bridge_disable,
+	.hpd_notify = hdmi5_bridge_hpd_notify,
 	.get_edid = hdmi5_bridge_get_edid,
+	.connector_attach = hdmi5_bridge_connector_attach,
+	.connector_detach = hdmi5_bridge_connector_detach,
 };
 
 static void hdmi5_bridge_init(struct omap_hdmi *hdmi)
diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi5_cec.c b/drivers/gpu/drm/omapdrm/dss/hdmi5_cec.c
new file mode 100644
index 000000000000..9df6805a5cb4
--- /dev/null
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi5_cec.c
@@ -0,0 +1,209 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * HDMI CEC
+ *
+ * Copyright 2019 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
+ */
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/clk.h>
+
+#include "dss.h"
+#include "hdmi.h"
+#include "hdmi5_core.h"
+#include "hdmi5_cec.h"
+
+static int hdmi5_cec_log_addr(struct cec_adapter *adap, u8 logical_addr)
+{
+	struct hdmi_core_data *core = cec_get_drvdata(adap);
+	u8 v;
+
+	if (logical_addr == CEC_LOG_ADDR_INVALID) {
+		hdmi_write_reg(core->base, HDMI_CORE_CEC_ADDR_L, 0);
+		hdmi_write_reg(core->base, HDMI_CORE_CEC_ADDR_H, 0);
+
+		return 0;
+	}
+
+	if (logical_addr <= 7) {
+		v = hdmi_read_reg(core->base, HDMI_CORE_CEC_ADDR_L);
+		v |= 1 << logical_addr;
+		hdmi_write_reg(core->base, HDMI_CORE_CEC_ADDR_L, v);
+		v = hdmi_read_reg(core->base, HDMI_CORE_CEC_ADDR_H);
+		v |= 1 << 7;
+		hdmi_write_reg(core->base, HDMI_CORE_CEC_ADDR_H, v);
+	} else {
+		v = hdmi_read_reg(core->base, HDMI_CORE_CEC_ADDR_H);
+		v |= 1 << (logical_addr - 8);
+		v |= 1 << 7;
+		hdmi_write_reg(core->base, HDMI_CORE_CEC_ADDR_H, v);
+	}
+
+	return 0;
+}
+
+static int hdmi5_cec_transmit(struct cec_adapter *adap, u8 attempts,
+			      u32 signal_free_time, struct cec_msg *msg)
+{
+	struct hdmi_core_data *core = cec_get_drvdata(adap);
+	unsigned int i, ctrl;
+
+	switch (signal_free_time) {
+	case CEC_SIGNAL_FREE_TIME_RETRY:
+		ctrl = CEC_CTRL_RETRY;
+		break;
+	case CEC_SIGNAL_FREE_TIME_NEW_INITIATOR:
+	default:
+		ctrl = CEC_CTRL_NORMAL;
+		break;
+	case CEC_SIGNAL_FREE_TIME_NEXT_XFER:
+		ctrl = CEC_CTRL_IMMED;
+		break;
+	}
+
+	for (i = 0; i < msg->len; i++)
+		hdmi_write_reg(core->base,
+			       HDMI_CORE_CEC_TX_DATA0 + i * 4, msg->msg[i]);
+
+	hdmi_write_reg(core->base, HDMI_CORE_CEC_TX_CNT, msg->len);
+	hdmi_write_reg(core->base, HDMI_CORE_CEC_CTRL,
+		       ctrl | CEC_CTRL_START);
+
+	return 0;
+}
+
+void hdmi5_cec_irq(struct hdmi_core_data *core, unsigned int stat)
+{
+	struct cec_adapter *adap = core->adap;
+
+	if (stat & CEC_STAT_ERROR_INIT)
+		cec_transmit_attempt_done(adap, CEC_TX_STATUS_ERROR);
+	else if (stat & CEC_STAT_DONE)
+		cec_transmit_attempt_done(adap, CEC_TX_STATUS_OK);
+	else if (stat & CEC_STAT_NACK)
+		cec_transmit_attempt_done(adap, CEC_TX_STATUS_NACK);
+
+	if (stat & CEC_STAT_EOM) {
+		struct cec_msg msg = {};
+		unsigned int len, i;
+
+		len = hdmi_read_reg(core->base, HDMI_CORE_CEC_RX_CNT);
+		if (len > sizeof(msg.msg))
+			len = sizeof(msg.msg);
+
+		for (i = 0; i < len; i++)
+			msg.msg[i] =
+				hdmi_read_reg(core->base,
+					      HDMI_CORE_CEC_RX_DATA0 + i * 4);
+
+		hdmi_write_reg(core->base, HDMI_CORE_CEC_LOCK, 0);
+
+		msg.len = len;
+		cec_received_msg(adap, &msg);
+	}
+}
+
+static int hdmi5_cec_enable(struct cec_adapter *adap, bool enable)
+{
+	struct hdmi_core_data *core = cec_get_drvdata(adap);
+	struct omap_hdmi *hdmi = container_of(core, struct omap_hdmi, core);
+	unsigned int irqs;
+	int err;
+
+	if (!enable) {
+		hdmi_write_reg(core->base, HDMI_CORE_CEC_MASK, ~0);
+		hdmi_write_reg(core->base, HDMI_CORE_IH_MUTE_CEC_STAT0, ~0);
+		hdmi_wp_clear_irqenable(core->wp, HDMI_IRQ_CORE);
+		hdmi_wp_set_irqstatus(core->wp, HDMI_IRQ_CORE);
+		REG_FLD_MOD(core->base, HDMI_CORE_MC_CLKDIS, 0x01, 5, 5);
+		hdmi5_core_disable(hdmi);
+
+		return 0;
+	}
+
+	err = hdmi5_core_enable(hdmi);
+	if (err)
+		return err;
+
+	REG_FLD_MOD(core->base, HDMI_CORE_MC_CLKDIS, 0x00, 5, 5);
+	hdmi_write_reg(core->base, HDMI_CORE_IH_I2CM_STAT0, ~0);
+	hdmi_write_reg(core->base, HDMI_CORE_IH_MUTE_I2CM_STAT0, ~0);
+	hdmi_write_reg(core->base, HDMI_CORE_CEC_CTRL, 0);
+	hdmi_write_reg(core->base, HDMI_CORE_IH_CEC_STAT0, ~0);
+	hdmi_write_reg(core->base, HDMI_CORE_CEC_LOCK, 0);
+	hdmi_write_reg(core->base, HDMI_CORE_CEC_TX_CNT, 0);
+
+	hdmi5_cec_log_addr(adap, CEC_LOG_ADDR_INVALID);
+
+	/* Enable HDMI core interrupts */
+	hdmi_wp_set_irqenable(core->wp, HDMI_IRQ_CORE);
+
+	irqs = CEC_STAT_ERROR_INIT | CEC_STAT_NACK | CEC_STAT_EOM |
+	       CEC_STAT_DONE;
+	hdmi_write_reg(core->base, HDMI_CORE_CEC_MASK, ~irqs);
+	hdmi_write_reg(core->base, HDMI_CORE_IH_MUTE_CEC_STAT0, ~irqs);
+
+	return 0;
+}
+
+static const struct cec_adap_ops hdmi5_cec_ops = {
+	.adap_enable = hdmi5_cec_enable,
+	.adap_log_addr = hdmi5_cec_log_addr,
+	.adap_transmit = hdmi5_cec_transmit,
+};
+
+void hdmi5_cec_set_phys_addr(struct hdmi_core_data *core, struct edid *edid)
+{
+	cec_s_phys_addr_from_edid(core->adap, edid);
+}
+
+int hdmi5_cec_init(struct platform_device *pdev, struct hdmi_core_data *core,
+		   struct hdmi_wp_data *wp, struct drm_connector *conn)
+{
+	const u32 caps = CEC_CAP_DEFAULTS | CEC_CAP_CONNECTOR_INFO;
+	struct cec_connector_info conn_info;
+	int ret;
+
+	core->cec_clk = devm_clk_get(&pdev->dev, "cec");
+	if (IS_ERR(core->cec_clk))
+		return PTR_ERR(core->cec_clk);
+	ret = clk_prepare_enable(core->cec_clk);
+	if (ret)
+		return ret;
+
+	core->adap = cec_allocate_adapter(&hdmi5_cec_ops, core,
+					  "omap5", caps, CEC_MAX_LOG_ADDRS);
+	ret = PTR_ERR_OR_ZERO(core->adap);
+	if (ret < 0)
+		goto disable_clk;
+
+	cec_fill_conn_info_from_drm(&conn_info, conn);
+	cec_s_conn_info(core->adap, &conn_info);
+	core->wp = wp;
+
+	ret = cec_register_adapter(core->adap, &pdev->dev);
+	if (ret < 0)
+		goto delete_adap;
+
+	return 0;
+
+delete_adap:
+	cec_delete_adapter(core->adap);
+disable_clk:
+	clk_disable_unprepare(core->cec_clk);
+	core->adap = NULL;
+	return ret;
+}
+
+void hdmi5_cec_uninit(struct hdmi_core_data *core)
+{
+	if (IS_ERR_OR_NULL(core->adap))
+		return;
+
+	cec_unregister_adapter(core->adap);
+	clk_disable_unprepare(core->cec_clk);
+}
diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi5_cec.h b/drivers/gpu/drm/omapdrm/dss/hdmi5_cec.h
new file mode 100644
index 000000000000..d7732f9a675a
--- /dev/null
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi5_cec.h
@@ -0,0 +1,42 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * HDMI header definition for OMAP5 HDMI CEC IP
+ *
+ * Copyright 2019 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
+ */
+
+#ifndef _HDMI5_CEC_H_
+#define _HDMI5_CEC_H_
+
+/* HDMI CEC funcs */
+#ifdef CONFIG_OMAP5_DSS_HDMI_CEC
+void hdmi5_cec_set_phys_addr(struct hdmi_core_data *core,
+			     struct edid *edid);
+void hdmi5_cec_irq(struct hdmi_core_data *core, unsigned int stat);
+int hdmi5_cec_init(struct platform_device *pdev, struct hdmi_core_data *core,
+		   struct hdmi_wp_data *wp, struct drm_connector *conn);
+void hdmi5_cec_uninit(struct hdmi_core_data *core);
+#else
+static inline void hdmi5_cec_set_phys_addr(struct hdmi_core_data *core,
+					   struct edid *edid)
+{
+}
+
+static inline void hdmi5_cec_irq(struct hdmi_core_data *core, unsigned int stat)
+{
+}
+
+static inline int hdmi5_cec_init(struct platform_device *pdev,
+				 struct hdmi_core_data *core,
+				 struct hdmi_wp_data *wp,
+				 struct drm_connector *conn)
+{
+	return 0;
+}
+
+static inline void hdmi5_cec_uninit(struct hdmi_core_data *core)
+{
+}
+#endif
+
+#endif
diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi5_core.c b/drivers/gpu/drm/omapdrm/dss/hdmi5_core.c
index 6cc2ad7a420c..de57384ad159 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi5_core.c
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi5_core.c
@@ -22,6 +22,7 @@
 #include <sound/asoundef.h>
 
 #include "hdmi5_core.h"
+#include "hdmi5_cec.h"
 
 void hdmi5_core_ddc_init(struct hdmi_core_data *core)
 {
@@ -229,6 +230,19 @@ void hdmi5_core_dump(struct hdmi_core_data *core, struct seq_file *s)
 	DUMPCORE(HDMI_CORE_I2CM_FS_SCL_LCNT_1_ADDR);
 	DUMPCORE(HDMI_CORE_I2CM_FS_SCL_LCNT_0_ADDR);
 	DUMPCORE(HDMI_CORE_I2CM_SDA_HOLD_ADDR);
+
+	DUMPCORE(HDMI_CORE_IH_CEC_STAT0);
+	DUMPCORE(HDMI_CORE_IH_MUTE_CEC_STAT0);
+	DUMPCORE(HDMI_CORE_CEC_CTRL);
+	DUMPCORE(HDMI_CORE_CEC_MASK);
+	DUMPCORE(HDMI_CORE_CEC_ADDR_L);
+	DUMPCORE(HDMI_CORE_CEC_ADDR_H);
+	DUMPCORE(HDMI_CORE_CEC_TX_CNT);
+	DUMPCORE(HDMI_CORE_CEC_RX_CNT);
+	DUMPCORE(HDMI_CORE_CEC_TX_DATA0);
+	DUMPCORE(HDMI_CORE_CEC_RX_DATA0);
+	DUMPCORE(HDMI_CORE_CEC_LOCK);
+	DUMPCORE(HDMI_CORE_CEC_WKUPCTRL);
 }
 
 static void hdmi_core_init(struct hdmi_core_vid_config *video_cfg,
@@ -513,8 +527,6 @@ static void hdmi_core_mask_interrupts(struct hdmi_core_data *core)
 	REG_FLD_MOD(base, HDMI_CORE_AUD_INT, 0x3, 3, 2);
 	REG_FLD_MOD(base, HDMI_CORE_AUD_GP_MASK, 0x3, 1, 0);
 
-	REG_FLD_MOD(base, HDMI_CORE_CEC_MASK, 0x7f, 6, 0);
-
 	REG_FLD_MOD(base, HDMI_CORE_I2CM_CTLINT, 0x1, 6, 6);
 	REG_FLD_MOD(base, HDMI_CORE_I2CM_CTLINT, 0x1, 2, 2);
 	REG_FLD_MOD(base, HDMI_CORE_I2CM_INT, 0x1, 2, 2);
@@ -532,8 +544,6 @@ static void hdmi_core_mask_interrupts(struct hdmi_core_data *core)
 
 	REG_FLD_MOD(base, HDMI_CORE_IH_AS_STAT0, 0x7, 2, 0);
 
-	REG_FLD_MOD(base, HDMI_CORE_IH_CEC_STAT0, 0x7f, 6, 0);
-
 	REG_FLD_MOD(base, HDMI_CORE_IH_I2CM_STAT0, 0x3, 1, 0);
 
 	REG_FLD_MOD(base, HDMI_CORE_IH_PHY_STAT0, 0xff, 7, 0);
@@ -548,14 +558,24 @@ static void hdmi_core_enable_interrupts(struct hdmi_core_data *core)
 int hdmi5_core_handle_irqs(struct hdmi_core_data *core)
 {
 	void __iomem *base = core->base;
+	unsigned int stat = hdmi_read_reg(base, HDMI_CORE_IH_CEC_STAT0);
+
+	if (stat) {
+		hdmi_write_reg(base, HDMI_CORE_IH_CEC_STAT0, stat);
+		hdmi5_cec_irq(core, stat);
+	}
 
+	/*
+	 * Clear all possible IRQ_CORE interrupts except for
+	 * HDMI_CORE_IH_I2CM_STAT0 (that interrupt is muted and
+	 * is handled by polling elsewhere) and HDMI_CORE_IH_CEC_STAT0
+	 * which is handled by the CEC code above.
+	 */
 	REG_FLD_MOD(base, HDMI_CORE_IH_FC_STAT0, 0xff, 7, 0);
 	REG_FLD_MOD(base, HDMI_CORE_IH_FC_STAT1, 0xff, 7, 0);
 	REG_FLD_MOD(base, HDMI_CORE_IH_FC_STAT2, 0xff, 7, 0);
 	REG_FLD_MOD(base, HDMI_CORE_IH_AS_STAT0, 0xff, 7, 0);
 	REG_FLD_MOD(base, HDMI_CORE_IH_PHY_STAT0, 0xff, 7, 0);
-	REG_FLD_MOD(base, HDMI_CORE_IH_I2CM_STAT0, 0xff, 7, 0);
-	REG_FLD_MOD(base, HDMI_CORE_IH_CEC_STAT0, 0xff, 7, 0);
 	REG_FLD_MOD(base, HDMI_CORE_IH_VP_STAT0, 0xff, 7, 0);
 	REG_FLD_MOD(base, HDMI_CORE_IH_I2CMPHY_STAT0, 0xff, 7, 0);
 
@@ -879,5 +899,8 @@ int hdmi5_core_init(struct platform_device *pdev, struct hdmi_core_data *core)
 	if (IS_ERR(core->base))
 		return PTR_ERR(core->base);
 
+	REG_FLD_MOD(core->base, HDMI_CORE_CEC_MASK, 0x7f, 6, 0);
+	REG_FLD_MOD(core->base, HDMI_CORE_IH_CEC_STAT0, 0x7f, 6, 0);
+
 	return 0;
 }
diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi5_core.h b/drivers/gpu/drm/omapdrm/dss/hdmi5_core.h
index 070cbf5fb57d..6bcef70a87cc 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi5_core.h
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi5_core.h
@@ -30,8 +30,18 @@
 #define HDMI_CORE_IH_PHY_STAT0			0x00410
 #define HDMI_CORE_IH_I2CM_STAT0			0x00414
 #define HDMI_CORE_IH_CEC_STAT0			0x00418
+#define CEC_STAT_DONE				BIT(0)
+#define CEC_STAT_EOM				BIT(1)
+#define CEC_STAT_NACK				BIT(2)
+#define CEC_STAT_ARBLOST			BIT(3)
+#define CEC_STAT_ERROR_INIT			BIT(4)
+#define CEC_STAT_ERROR_FOLL			BIT(5)
+#define CEC_STAT_WAKEUP				BIT(6)
+
 #define HDMI_CORE_IH_VP_STAT0			0x0041C
 #define HDMI_CORE_IH_I2CMPHY_STAT0		0x00420
+#define HDMI_CORE_IH_MUTE_I2CM_STAT0		0x00614
+#define HDMI_CORE_IH_MUTE_CEC_STAT0		0x00618
 #define HDMI_CORE_IH_MUTE			0x007FC
 
 /* HDMI Video Sampler */
@@ -233,9 +243,6 @@
 /* HDMI HDCP */
 #define HDMI_CORE_HDCP_MASK			0x14020
 
-/* HDMI CEC */
-#define HDMI_CORE_CEC_MASK			0x17408
-
 /* HDMI I2C Master */
 #define HDMI_CORE_I2CM_SLAVE			0x157C8
 #define HDMI_CORE_I2CM_ADDRESS			0x157CC
@@ -258,6 +265,24 @@
 #define HDMI_CORE_I2CM_FS_SCL_LCNT_0_ADDR	0x15810
 #define HDMI_CORE_I2CM_SDA_HOLD_ADDR		0x15814
 
+/* HDMI CEC */
+#define HDMI_CORE_CEC_CTRL			0x153C8
+#define CEC_CTRL_START				BIT(0)
+#define CEC_CTRL_FRAME_TYP			(3 << 1)
+#define CEC_CTRL_RETRY				(0 << 1)
+#define CEC_CTRL_NORMAL				(1 << 1)
+#define CEC_CTRL_IMMED				(2 << 1)
+
+#define HDMI_CORE_CEC_MASK			0x153D0
+#define HDMI_CORE_CEC_ADDR_L			0x153DC
+#define HDMI_CORE_CEC_ADDR_H			0x153E0
+#define HDMI_CORE_CEC_TX_CNT			0x153E4
+#define HDMI_CORE_CEC_RX_CNT			0x153E8
+#define HDMI_CORE_CEC_TX_DATA0			0x15408
+#define HDMI_CORE_CEC_RX_DATA0			0x15448
+#define HDMI_CORE_CEC_LOCK			0x15488
+#define HDMI_CORE_CEC_WKUPCTRL			0x1548C
+
 enum hdmi_core_packet_mode {
 	HDMI_PACKETMODERESERVEDVALUE = 0,
 	HDMI_PACKETMODE24BITPERPIXEL = 4,
@@ -290,6 +315,8 @@ int hdmi5_core_handle_irqs(struct hdmi_core_data *core);
 void hdmi5_configure(struct hdmi_core_data *core, struct hdmi_wp_data *wp,
 			struct hdmi_config *cfg);
 int hdmi5_core_init(struct platform_device *pdev, struct hdmi_core_data *core);
+int hdmi5_core_enable(struct omap_hdmi *hdmi);
+void hdmi5_core_disable(struct omap_hdmi *hdmi);
 
 int hdmi5_audio_config(struct hdmi_core_data *core, struct hdmi_wp_data *wp,
 			struct omap_dss_audio *audio, u32 pclk);
-- 
2.30.2

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCHv3 1/6] drm: drm_bridge: add connector_attach/detach bridge ops
  2021-04-28 13:25 ` [PATCHv3 1/6] drm: drm_bridge: add connector_attach/detach bridge ops Hans Verkuil
@ 2021-05-04  8:26   ` Tomi Valkeinen
  2021-05-27  7:22     ` Hans Verkuil
  0 siblings, 1 reply; 10+ messages in thread
From: Tomi Valkeinen @ 2021-05-04  8:26 UTC (permalink / raw)
  To: Hans Verkuil, dri-devel, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann, David Airlie, Daniel Vetter
  Cc: Tony Lindgren, Laurent Pinchart, linux-media

On 28/04/2021 16:25, Hans Verkuil wrote:
> Add bridge connector_attach/detach ops. These ops are called when a
> bridge is attached or detached to a drm_connector. These ops can be
> used to register and unregister an HDMI CEC adapter for a bridge that
> supports CEC.
> 
> Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
> ---
>   drivers/gpu/drm/drm_bridge_connector.c | 25 +++++++++++++++++++++++-
>   include/drm/drm_bridge.h               | 27 ++++++++++++++++++++++++++
>   2 files changed, 51 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/drm_bridge_connector.c b/drivers/gpu/drm/drm_bridge_connector.c
> index 791379816837..0676677badfe 100644
> --- a/drivers/gpu/drm/drm_bridge_connector.c
> +++ b/drivers/gpu/drm/drm_bridge_connector.c
> @@ -203,6 +203,11 @@ static void drm_bridge_connector_destroy(struct drm_connector *connector)
>   {
>   	struct drm_bridge_connector *bridge_connector =
>   		to_drm_bridge_connector(connector);
> +	struct drm_bridge *bridge;
> +
> +	drm_for_each_bridge_in_chain(bridge_connector->encoder, bridge)
> +		if (bridge->funcs->connector_detach)
> +			bridge->funcs->connector_detach(bridge, connector);
>   
>   	if (bridge_connector->bridge_hpd) {
>   		struct drm_bridge *hpd = bridge_connector->bridge_hpd;
> @@ -318,6 +323,7 @@ struct drm_connector *drm_bridge_connector_init(struct drm_device *drm,
>   	struct i2c_adapter *ddc = NULL;
>   	struct drm_bridge *bridge;
>   	int connector_type;
> +	int ret;
>   
>   	bridge_connector = kzalloc(sizeof(*bridge_connector), GFP_KERNEL);
>   	if (!bridge_connector)
> @@ -375,6 +381,23 @@ struct drm_connector *drm_bridge_connector_init(struct drm_device *drm,
>   		connector->polled = DRM_CONNECTOR_POLL_CONNECT
>   				  | DRM_CONNECTOR_POLL_DISCONNECT;
>   
> -	return connector;
> +	ret = 0;
> +	/* call connector_attach for all bridges */
> +	drm_for_each_bridge_in_chain(encoder, bridge) {
> +		if (!bridge->funcs->connector_attach)
> +			continue;
> +		ret = bridge->funcs->connector_attach(bridge, connector);
> +		if (ret)
> +			break;
> +	}
> +	if (!ret)
> +		return connector;
> +
> +	/* on error, detach any previously successfully attached connectors */
> +	list_for_each_entry_continue_reverse(bridge, &(encoder)->bridge_chain,

No need for parenthesis in (encoder) here.

> +					     chain_node)
> +		if (bridge->funcs->connector_detach)
> +			bridge->funcs->connector_detach(bridge, connector);
> +	return ERR_PTR(ret);
>   }
>   EXPORT_SYMBOL_GPL(drm_bridge_connector_init);
> diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h
> index 2195daa289d2..333fbc3a03e9 100644
> --- a/include/drm/drm_bridge.h
> +++ b/include/drm/drm_bridge.h
> @@ -629,6 +629,33 @@ struct drm_bridge_funcs {
>   	 * the DRM_BRIDGE_OP_HPD flag in their &drm_bridge->ops.
>   	 */
>   	void (*hpd_disable)(struct drm_bridge *bridge);
> +
> +	/**
> +	 * @connector_attach:
> +	 *
> +	 * This callback is invoked whenever our bridge is being attached to a
> +	 * &drm_connector. This is where an HDMI CEC adapter can be registered.
> +	 *
> +	 * The @connector_attach callback is optional.
> +	 *
> +	 * RETURNS:
> +	 *
> +	 * Zero on success, error code on failure.
> +	 */
> +	int (*connector_attach)(struct drm_bridge *bridge,
> +				struct drm_connector *conn);
> +
> +	/**
> +	 * @connector_detach:
> +	 *
> +	 * This callback is invoked whenever our bridge is being detached from a
> +	 * &drm_connector. This is where an HDMI CEC adapter can be
> +	 * unregistered.
> +	 *
> +	 * The @connector_detach callback is optional.
> +	 */
> +	void (*connector_detach)(struct drm_bridge *bridge,
> +				 struct drm_connector *conn);
>   };
>   
>   /**
> 

Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>

I can take this series as it's mostly omapdrm, but we'll need a 
reviewed-by/acked-by from a maintainer for this patch.

  Tomi
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCHv3 1/6] drm: drm_bridge: add connector_attach/detach bridge ops
  2021-05-04  8:26   ` Tomi Valkeinen
@ 2021-05-27  7:22     ` Hans Verkuil
  2021-06-03 12:34       ` Laurent Pinchart
  0 siblings, 1 reply; 10+ messages in thread
From: Hans Verkuil @ 2021-05-27  7:22 UTC (permalink / raw)
  To: Tomi Valkeinen, dri-devel, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann, David Airlie, Daniel Vetter
  Cc: Tony Lindgren, Laurent Pinchart, linux-media

On 04/05/2021 10:26, Tomi Valkeinen wrote:
> On 28/04/2021 16:25, Hans Verkuil wrote:
>> Add bridge connector_attach/detach ops. These ops are called when a
>> bridge is attached or detached to a drm_connector. These ops can be
>> used to register and unregister an HDMI CEC adapter for a bridge that
>> supports CEC.
>>
>> Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
>> ---
>>   drivers/gpu/drm/drm_bridge_connector.c | 25 +++++++++++++++++++++++-
>>   include/drm/drm_bridge.h               | 27 ++++++++++++++++++++++++++
>>   2 files changed, 51 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/gpu/drm/drm_bridge_connector.c b/drivers/gpu/drm/drm_bridge_connector.c
>> index 791379816837..0676677badfe 100644
>> --- a/drivers/gpu/drm/drm_bridge_connector.c
>> +++ b/drivers/gpu/drm/drm_bridge_connector.c
>> @@ -203,6 +203,11 @@ static void drm_bridge_connector_destroy(struct drm_connector *connector)
>>   {
>>   	struct drm_bridge_connector *bridge_connector =
>>   		to_drm_bridge_connector(connector);
>> +	struct drm_bridge *bridge;
>> +
>> +	drm_for_each_bridge_in_chain(bridge_connector->encoder, bridge)
>> +		if (bridge->funcs->connector_detach)
>> +			bridge->funcs->connector_detach(bridge, connector);
>>   
>>   	if (bridge_connector->bridge_hpd) {
>>   		struct drm_bridge *hpd = bridge_connector->bridge_hpd;
>> @@ -318,6 +323,7 @@ struct drm_connector *drm_bridge_connector_init(struct drm_device *drm,
>>   	struct i2c_adapter *ddc = NULL;
>>   	struct drm_bridge *bridge;
>>   	int connector_type;
>> +	int ret;
>>   
>>   	bridge_connector = kzalloc(sizeof(*bridge_connector), GFP_KERNEL);
>>   	if (!bridge_connector)
>> @@ -375,6 +381,23 @@ struct drm_connector *drm_bridge_connector_init(struct drm_device *drm,
>>   		connector->polled = DRM_CONNECTOR_POLL_CONNECT
>>   				  | DRM_CONNECTOR_POLL_DISCONNECT;
>>   
>> -	return connector;
>> +	ret = 0;
>> +	/* call connector_attach for all bridges */
>> +	drm_for_each_bridge_in_chain(encoder, bridge) {
>> +		if (!bridge->funcs->connector_attach)
>> +			continue;
>> +		ret = bridge->funcs->connector_attach(bridge, connector);
>> +		if (ret)
>> +			break;
>> +	}
>> +	if (!ret)
>> +		return connector;
>> +
>> +	/* on error, detach any previously successfully attached connectors */
>> +	list_for_each_entry_continue_reverse(bridge, &(encoder)->bridge_chain,
> 
> No need for parenthesis in (encoder) here.
> 
>> +					     chain_node)
>> +		if (bridge->funcs->connector_detach)
>> +			bridge->funcs->connector_detach(bridge, connector);
>> +	return ERR_PTR(ret);
>>   }
>>   EXPORT_SYMBOL_GPL(drm_bridge_connector_init);
>> diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h
>> index 2195daa289d2..333fbc3a03e9 100644
>> --- a/include/drm/drm_bridge.h
>> +++ b/include/drm/drm_bridge.h
>> @@ -629,6 +629,33 @@ struct drm_bridge_funcs {
>>   	 * the DRM_BRIDGE_OP_HPD flag in their &drm_bridge->ops.
>>   	 */
>>   	void (*hpd_disable)(struct drm_bridge *bridge);
>> +
>> +	/**
>> +	 * @connector_attach:
>> +	 *
>> +	 * This callback is invoked whenever our bridge is being attached to a
>> +	 * &drm_connector. This is where an HDMI CEC adapter can be registered.
>> +	 *
>> +	 * The @connector_attach callback is optional.
>> +	 *
>> +	 * RETURNS:
>> +	 *
>> +	 * Zero on success, error code on failure.
>> +	 */
>> +	int (*connector_attach)(struct drm_bridge *bridge,
>> +				struct drm_connector *conn);
>> +
>> +	/**
>> +	 * @connector_detach:
>> +	 *
>> +	 * This callback is invoked whenever our bridge is being detached from a
>> +	 * &drm_connector. This is where an HDMI CEC adapter can be
>> +	 * unregistered.
>> +	 *
>> +	 * The @connector_detach callback is optional.
>> +	 */
>> +	void (*connector_detach)(struct drm_bridge *bridge,
>> +				 struct drm_connector *conn);
>>   };
>>   
>>   /**
>>
> 
> Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
> 
> I can take this series as it's mostly omapdrm, but we'll need a 
> reviewed-by/acked-by from a maintainer for this patch.

Laurent, aren't you the drm bridge maintainer?

If so, can you review/ack this patch so Tomi can merge it?

Regards,

	Hans

> 
>   Tomi
> 


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCHv3 1/6] drm: drm_bridge: add connector_attach/detach bridge ops
  2021-05-27  7:22     ` Hans Verkuil
@ 2021-06-03 12:34       ` Laurent Pinchart
  0 siblings, 0 replies; 10+ messages in thread
From: Laurent Pinchart @ 2021-06-03 12:34 UTC (permalink / raw)
  To: Hans Verkuil
  Cc: David Airlie, Tomi Valkeinen, Tony Lindgren, dri-devel,
	Thomas Zimmermann, linux-media

Hi Hans,

On Thu, May 27, 2021 at 09:22:12AM +0200, Hans Verkuil wrote:
> On 04/05/2021 10:26, Tomi Valkeinen wrote:
> > On 28/04/2021 16:25, Hans Verkuil wrote:
> >> Add bridge connector_attach/detach ops. These ops are called when a
> >> bridge is attached or detached to a drm_connector. These ops can be
> >> used to register and unregister an HDMI CEC adapter for a bridge that
> >> supports CEC.
> >>
> >> Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
> >> ---
> >>   drivers/gpu/drm/drm_bridge_connector.c | 25 +++++++++++++++++++++++-
> >>   include/drm/drm_bridge.h               | 27 ++++++++++++++++++++++++++
> >>   2 files changed, 51 insertions(+), 1 deletion(-)
> >>
> >> diff --git a/drivers/gpu/drm/drm_bridge_connector.c b/drivers/gpu/drm/drm_bridge_connector.c
> >> index 791379816837..0676677badfe 100644
> >> --- a/drivers/gpu/drm/drm_bridge_connector.c
> >> +++ b/drivers/gpu/drm/drm_bridge_connector.c
> >> @@ -203,6 +203,11 @@ static void drm_bridge_connector_destroy(struct drm_connector *connector)
> >>   {
> >>   	struct drm_bridge_connector *bridge_connector =
> >>   		to_drm_bridge_connector(connector);
> >> +	struct drm_bridge *bridge;
> >> +
> >> +	drm_for_each_bridge_in_chain(bridge_connector->encoder, bridge)
> >> +		if (bridge->funcs->connector_detach)
> >> +			bridge->funcs->connector_detach(bridge, connector);
> >>   
> >>   	if (bridge_connector->bridge_hpd) {
> >>   		struct drm_bridge *hpd = bridge_connector->bridge_hpd;
> >> @@ -318,6 +323,7 @@ struct drm_connector *drm_bridge_connector_init(struct drm_device *drm,
> >>   	struct i2c_adapter *ddc = NULL;
> >>   	struct drm_bridge *bridge;
> >>   	int connector_type;
> >> +	int ret;
> >>   
> >>   	bridge_connector = kzalloc(sizeof(*bridge_connector), GFP_KERNEL);
> >>   	if (!bridge_connector)
> >> @@ -375,6 +381,23 @@ struct drm_connector *drm_bridge_connector_init(struct drm_device *drm,
> >>   		connector->polled = DRM_CONNECTOR_POLL_CONNECT
> >>   				  | DRM_CONNECTOR_POLL_DISCONNECT;
> >>   
> >> -	return connector;
> >> +	ret = 0;
> >> +	/* call connector_attach for all bridges */
> >> +	drm_for_each_bridge_in_chain(encoder, bridge) {
> >> +		if (!bridge->funcs->connector_attach)
> >> +			continue;
> >> +		ret = bridge->funcs->connector_attach(bridge, connector);
> >> +		if (ret)
> >> +			break;
> >> +	}
> >> +	if (!ret)
> >> +		return connector;
> >> +
> >> +	/* on error, detach any previously successfully attached connectors */
> >> +	list_for_each_entry_continue_reverse(bridge, &(encoder)->bridge_chain,
> > 
> > No need for parenthesis in (encoder) here.
> > 
> >> +					     chain_node)
> >> +		if (bridge->funcs->connector_detach)
> >> +			bridge->funcs->connector_detach(bridge, connector);
> >> +	return ERR_PTR(ret);
> >>   }
> >>   EXPORT_SYMBOL_GPL(drm_bridge_connector_init);
> >> diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h
> >> index 2195daa289d2..333fbc3a03e9 100644
> >> --- a/include/drm/drm_bridge.h
> >> +++ b/include/drm/drm_bridge.h
> >> @@ -629,6 +629,33 @@ struct drm_bridge_funcs {
> >>   	 * the DRM_BRIDGE_OP_HPD flag in their &drm_bridge->ops.
> >>   	 */
> >>   	void (*hpd_disable)(struct drm_bridge *bridge);
> >> +
> >> +	/**
> >> +	 * @connector_attach:
> >> +	 *
> >> +	 * This callback is invoked whenever our bridge is being attached to a
> >> +	 * &drm_connector. This is where an HDMI CEC adapter can be registered.
> >> +	 *
> >> +	 * The @connector_attach callback is optional.
> >> +	 *
> >> +	 * RETURNS:
> >> +	 *
> >> +	 * Zero on success, error code on failure.
> >> +	 */
> >> +	int (*connector_attach)(struct drm_bridge *bridge,
> >> +				struct drm_connector *conn);
> >> +
> >> +	/**
> >> +	 * @connector_detach:
> >> +	 *
> >> +	 * This callback is invoked whenever our bridge is being detached from a
> >> +	 * &drm_connector. This is where an HDMI CEC adapter can be
> >> +	 * unregistered.
> >> +	 *
> >> +	 * The @connector_detach callback is optional.
> >> +	 */
> >> +	void (*connector_detach)(struct drm_bridge *bridge,
> >> +				 struct drm_connector *conn);
> >>   };
> >>   
> >>   /**
> >>
> > 
> > Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
> > 
> > I can take this series as it's mostly omapdrm, but we'll need a 
> > reviewed-by/acked-by from a maintainer for this patch.
> 
> Laurent, aren't you the drm bridge maintainer?

I'm merely a reviewer, but one without much free time these days :-(

> If so, can you review/ack this patch so Tomi can merge it?

Overall, I'm not fond of giving access to the connector to individual
bridges. It breaks the abstraction layers, and seems to be a bit of a
hack. On the other hand, a proper solution would likely involve lots of
work, so I'm not rejecting this, but I fear these operations will be
abused and we'll regret it later.

-- 
Regards,

Laurent Pinchart

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2021-06-03 12:35 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-04-28 13:25 [PATCHv3 0/6] drm/omap: hdmi: improve hdmi4 CEC, add CEC for hdmi5 Hans Verkuil
2021-04-28 13:25 ` [PATCHv3 1/6] drm: drm_bridge: add connector_attach/detach bridge ops Hans Verkuil
2021-05-04  8:26   ` Tomi Valkeinen
2021-05-27  7:22     ` Hans Verkuil
2021-06-03 12:34       ` Laurent Pinchart
2021-04-28 13:25 ` [PATCHv3 2/6] drm/omapdrm/dss/hdmi4: switch to the connector " Hans Verkuil
2021-04-28 13:25 ` [PATCHv3 3/6] drm/omapdrm/dss/hdmi4: simplify CEC Phys Addr handling Hans Verkuil
2021-04-28 13:25 ` [PATCHv3 4/6] dt-bindings: display: ti: ti, omap5-dss.txt: add cec clock Hans Verkuil
2021-04-28 13:25 ` [PATCHv3 5/6] dra7.dtsi/omap5.dtsi: " Hans Verkuil
2021-04-28 13:25 ` [PATCHv3 6/6] drm/omapdrm/dss/hdmi5: add CEC support Hans Verkuil

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).