linux-media.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v7 1/3] media: cec: expose HDMI connector to CEC dev mapping
@ 2019-05-21 10:52 Dariusz Marcinkiewicz
  2019-05-21 10:52 ` [PATCH v7 2/3] drm/bridge: dw-hdmi: pass connector info to the CEC adapter Dariusz Marcinkiewicz
                   ` (2 more replies)
  0 siblings, 3 replies; 9+ messages in thread
From: Dariusz Marcinkiewicz @ 2019-05-21 10:52 UTC (permalink / raw)
  To: linux-media, hans.verkuil, hverkuil; +Cc: linux-kernel, Dariusz Marcinkiewicz

This patch proposes to expose explicit mapping between HDMI connectors
and /dev/cecX adapters to userland.

New structure with connector info (card number and connector id in case
of DRM connectors) is added to cec_adapter. That connector info is expected
to be provided when an adapter is created.

CEC notifier is extended so that it can be used to communicate the
connector's info to CEC adapters' creators.

New ioctl, exposing connector info to userland, is added to /dev/cec.

Changes since v6:
 - updated remaining cec_allocate_adapter calls
Changes since v5:
 - make the patch apply against the latest changes in the affected code
Changes since v4:
 - small tweaks + added documentation
Changes since v3:
 - cec_get_connter_conn takes connector_info as argument
Changes since v2:
 - cec_s_connector_info removed, the connector info is now passed to
   cec_allocate_adapter
 - updated commit message
Changes since v1:
 - removed the unnecessary event,
 - extended cec_connctor_info to allow for various types of connectors.

Signed-off-by: Dariusz Marcinkiewicz <darekm@google.com>
---
 Documentation/media/kapi/cec-core.rst         |   7 +-
 Documentation/media/uapi/cec/cec-funcs.rst    |   1 +
 .../uapi/cec/cec-ioc-adap-g-conn-info.rst     | 109 ++++++++++++++++++
 .../display/amdgpu_dm/amdgpu_dm_mst_types.c   |   2 +-
 drivers/gpu/drm/bridge/adv7511/adv7511_cec.c  |   3 +-
 drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.c |   2 +-
 drivers/gpu/drm/drm_dp_cec.c                  |  22 ++--
 drivers/gpu/drm/i2c/tda9950.c                 |   3 +-
 drivers/gpu/drm/i915/intel_dp.c               |   4 +-
 drivers/gpu/drm/i915/intel_hdmi.c             |   6 +-
 drivers/gpu/drm/nouveau/nouveau_connector.c   |   3 +-
 drivers/gpu/drm/omapdrm/dss/hdmi4_cec.c       |   2 +-
 drivers/gpu/drm/vc4/vc4_hdmi.c                |   8 +-
 drivers/media/cec/cec-adap.c                  |  13 +++
 drivers/media/cec/cec-api.c                   |  12 ++
 drivers/media/cec/cec-core.c                  |   8 +-
 drivers/media/cec/cec-notifier.c              |  20 +++-
 drivers/media/cec/cec-pin.c                   |   2 +-
 drivers/media/i2c/adv7511.c                   |   2 +-
 drivers/media/i2c/adv7604.c                   |   2 +-
 drivers/media/i2c/adv7842.c                   |   2 +-
 drivers/media/i2c/tc358743.c                  |   3 +-
 .../media/platform/cros-ec-cec/cros-ec-cec.c  |   7 +-
 drivers/media/platform/meson/ao-cec-g12a.c    |   3 +-
 drivers/media/platform/meson/ao-cec.c         |   6 +-
 drivers/media/platform/s5p-cec/s5p_cec.c      |   6 +-
 drivers/media/platform/seco-cec/seco-cec.c    |   8 +-
 drivers/media/platform/sti/cec/stih-cec.c     |   6 +-
 drivers/media/platform/stm32/stm32-cec.c      |   2 +-
 drivers/media/platform/tegra-cec/tegra_cec.c  |   5 +-
 drivers/media/platform/vivid/vivid-cec.c      |   2 +-
 drivers/media/usb/pulse8-cec/pulse8-cec.c     |   3 +-
 .../media/usb/rainshadow-cec/rainshadow-cec.c |   3 +-
 include/drm/drm_dp_helper.h                   |  14 +--
 include/media/cec-notifier.h                  |  34 ++++--
 include/media/cec.h                           |  16 ++-
 include/uapi/linux/cec.h                      |  24 ++++
 37 files changed, 316 insertions(+), 59 deletions(-)
 create mode 100644 Documentation/media/uapi/cec/cec-ioc-adap-g-conn-info.rst

diff --git a/Documentation/media/kapi/cec-core.rst b/Documentation/media/kapi/cec-core.rst
index 3ce26b7c2b2b6..3678a0a75104e 100644
--- a/Documentation/media/kapi/cec-core.rst
+++ b/Documentation/media/kapi/cec-core.rst
@@ -37,7 +37,8 @@ calling cec_allocate_adapter() and deleted by calling cec_delete_adapter():
 
 .. c:function::
    struct cec_adapter *cec_allocate_adapter(const struct cec_adap_ops *ops, void *priv,
-   const char *name, u32 caps, u8 available_las);
+                                            const char *name, u32 caps, u8 available_las,
+                                            const struct cec_connector_info *connector_info);
 
 .. c:function::
    void cec_delete_adapter(struct cec_adapter *adap);
@@ -65,6 +66,10 @@ available_las:
 	the number of simultaneous logical addresses that this
 	adapter can handle. Must be 1 <= available_las <= CEC_MAX_LOG_ADDRS.
 
+connector_info:
+        pointer to a struct describing connector this adapter is associated with,
+        can be NULL.
+
 To obtain the priv pointer use this helper function:
 
 .. c:function::
diff --git a/Documentation/media/uapi/cec/cec-funcs.rst b/Documentation/media/uapi/cec/cec-funcs.rst
index 620590b168c9e..dc6da9c639a85 100644
--- a/Documentation/media/uapi/cec/cec-funcs.rst
+++ b/Documentation/media/uapi/cec/cec-funcs.rst
@@ -24,6 +24,7 @@ Function Reference
     cec-ioc-adap-g-caps
     cec-ioc-adap-g-log-addrs
     cec-ioc-adap-g-phys-addr
+    cec-ioc-adap-g-conn-info
     cec-ioc-dqevent
     cec-ioc-g-mode
     cec-ioc-receive
diff --git a/Documentation/media/uapi/cec/cec-ioc-adap-g-conn-info.rst b/Documentation/media/uapi/cec/cec-ioc-adap-g-conn-info.rst
new file mode 100644
index 0000000000000..87f475d7dfed4
--- /dev/null
+++ b/Documentation/media/uapi/cec/cec-ioc-adap-g-conn-info.rst
@@ -0,0 +1,109 @@
+.. SPDX-License-Identifier: GPL-2.0
+..
+.. Copyright 2019 Google LLC
+..
+.. This documentation is free software; you can redistribute it and/or
+.. modify it under the terms of the GNU General Public License
+.. version 2 as published by the Free Software Foundation.
+..
+.. This documentation is distributed in the hope that it will be useful,
+.. but WITHOUT ANY WARRANTY; without even the implied warranty of
+.. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+.. GNU General Public License for more details.
+..
+.. _CEC_ADAP_G_CONNECTOR_INFO:
+
+*******************************
+ioctl CEC_ADAP_G_CONNECTOR_INFO
+*******************************
+
+Name
+====
+
+CEC_ADAP_G_CONNECTOR_INFO - Query HDMI connector information
+
+Synopsis
+========
+
+.. c:function:: int ioctl( int fd, CEC_ADAP_G_CONNECTOR_INFO, struct cec_connector_info *argp )
+    :name: CEC_ADAP_G_CONNECTOR_INFO
+
+Arguments
+=========
+
+``fd``
+    File descriptor returned by :c:func:`open() <cec-open>`.
+
+``argp``
+
+
+Description
+===========
+
+Using this ioctl an application can learn which HDMI connector this CEC
+device corresponds to. While calling this ioctl the application should
+provide pointer to a cec_connector_info struct which will be populated
+by the kernel with the info provided by the adapter's driver. Not all
+drivers supply this information.
+
+.. tabularcolumns:: |p{1.0cm}|p{4.4cm}|p{2.5cm}|p{9.6cm}|
+
+.. c:type:: cec_connector_info
+
+.. flat-table:: struct cec_connector_info
+    :header-rows:  0
+    :stub-columns: 0
+    :widths:       1 1 1 8
+
+    * - __u32
+      - ``type``
+      - The type of connector this adapter is associated with.
+    * - union
+      - ``(anonymous)``
+      -
+    * -
+      - ``struct cec_drm_connector_info``
+      - drm
+      - :ref:`cec-drm-connector-info`.
+
+
+.. tabularcolumns:: |p{4.4cm}|p{2.5cm}|p{10.6cm}|
+
+.. _connector-type:
+
+.. flat-table:: Connector types
+    :header-rows:  0
+    :stub-columns: 0
+    :widths:       3 1 8
+
+    * .. _`CEC-CONNECTOR-TYPE-NO-CONNECTOR`:
+
+      - ``CEC_CONNECTOR_TYPE_NO_CONNECTOR``
+      - 0
+      - No connector is associated with the adapter/the information is not provided by the driver.
+    * .. _`CEC-CONNECTOR-TYPE-DRM`:
+
+      - ``CEC_CONNECTOR_TYPE_DRM``
+      - 1
+      - Indicates that a DRM connector is associated with this adapter. Info about the
+        connector can be found in :ref:`cec-drm-connector-info`.
+
+.. tabularcolumns:: |p{4.4cm}|p{2.5cm}|p{10.6cm}|
+
+.. c:type:: cec_drm_connector_info
+
+.. _cec-drm-connector-info:
+
+.. flat-table:: struct cec_drm_connector_info
+    :header-rows:  0
+    :stub-columns: 0
+    :widths:       3 1 8
+
+    * .. _`CEC-DRM-CONNECTOR-TYPE-CARD-NO`:
+
+      - __u32
+      - ``card_no``
+      - DRM card number - the digit from a card's path, e.g. 0 in case of /dev/card0.
+    * .. _`CEC-DRM-CONNECTOR-TYPE-CONNECTOR_ID`:
+
+      - __u32
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
index 6e205ee36ac3b..7f2eb4eb1035b 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
@@ -394,7 +394,7 @@ void amdgpu_dm_initialize_dp_connector(struct amdgpu_display_manager *dm,
 
 	drm_dp_aux_register(&aconnector->dm_dp_aux.aux);
 	drm_dp_cec_register_connector(&aconnector->dm_dp_aux.aux,
-				      aconnector->base.name, dm->adev->dev);
+				      &aconnector->base);
 	aconnector->mst_mgr.cbs = &dm_mst_cbs;
 	drm_dp_mst_topology_mgr_init(
 		&aconnector->mst_mgr,
diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511_cec.c b/drivers/gpu/drm/bridge/adv7511/adv7511_cec.c
index a20a45c0b353f..6400ad9b85502 100644
--- a/drivers/gpu/drm/bridge/adv7511/adv7511_cec.c
+++ b/drivers/gpu/drm/bridge/adv7511/adv7511_cec.c
@@ -310,7 +310,8 @@ int adv7511_cec_init(struct device *dev, struct adv7511 *adv7511)
 		goto err_cec_parse_dt;
 
 	adv7511->cec_adap = cec_allocate_adapter(&adv7511_cec_adap_ops,
-		adv7511, dev_name(dev), CEC_CAP_DEFAULTS, ADV7511_MAX_ADDRS);
+		adv7511, dev_name(dev), CEC_CAP_DEFAULTS, ADV7511_MAX_ADDRS,
+		NULL);
 	if (IS_ERR(adv7511->cec_adap)) {
 		ret = PTR_ERR(adv7511->cec_adap);
 		goto err_cec_alloc;
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.c
index 6c323510f1288..84fb7b6a0a5e0 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.c
@@ -261,7 +261,7 @@ static int dw_hdmi_cec_probe(struct platform_device *pdev)
 	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);
+					 CEC_MAX_LOG_ADDRS, NULL);
 	if (IS_ERR(cec->adap))
 		return PTR_ERR(cec->adap);
 
diff --git a/drivers/gpu/drm/drm_dp_cec.c b/drivers/gpu/drm/drm_dp_cec.c
index b15cee85b702b..c739acad45475 100644
--- a/drivers/gpu/drm/drm_dp_cec.c
+++ b/drivers/gpu/drm/drm_dp_cec.c
@@ -8,7 +8,9 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/slab.h>
+#include <drm/drm_connector.h>
 #include <drm/drm_dp_helper.h>
+#include <drm/drmP.h>
 #include <media/cec.h>
 
 /*
@@ -295,7 +297,9 @@ static void drm_dp_cec_unregister_work(struct work_struct *work)
  */
 void drm_dp_cec_set_edid(struct drm_dp_aux *aux, const struct edid *edid)
 {
+	struct drm_connector *connector = aux->cec.connector;
 	u32 cec_caps = CEC_CAP_DEFAULTS | CEC_CAP_NEEDS_HPD;
+	struct cec_connector_info conn_info;
 	unsigned int num_las = 1;
 	u8 cap;
 
@@ -342,15 +346,17 @@ void drm_dp_cec_set_edid(struct drm_dp_aux *aux, const struct edid *edid)
 		cec_unregister_adapter(aux->cec.adap);
 	}
 
+	cec_fill_connector_info(&conn_info, connector);
+
 	/* Create a new adapter */
 	aux->cec.adap = cec_allocate_adapter(&drm_dp_cec_adap_ops,
-					     aux, aux->cec.name, cec_caps,
-					     num_las);
+					     aux, connector->name, cec_caps,
+					     num_las, &conn_info);
 	if (IS_ERR(aux->cec.adap)) {
 		aux->cec.adap = NULL;
 		goto unlock;
 	}
-	if (cec_register_adapter(aux->cec.adap, aux->cec.parent)) {
+	if (cec_register_adapter(aux->cec.adap, connector->dev->dev)) {
 		cec_delete_adapter(aux->cec.adap);
 		aux->cec.adap = NULL;
 	} else {
@@ -406,22 +412,20 @@ EXPORT_SYMBOL(drm_dp_cec_unset_edid);
 /**
  * drm_dp_cec_register_connector() - register a new connector
  * @aux: DisplayPort AUX channel
- * @name: name of the CEC device
- * @parent: parent device
+ * @connector: drm connector
  *
  * A new connector was registered with associated CEC adapter name and
  * CEC adapter parent device. After registering the name and parent
  * drm_dp_cec_set_edid() is called to check if the connector supports
  * CEC and to register a CEC adapter if that is the case.
  */
-void drm_dp_cec_register_connector(struct drm_dp_aux *aux, const char *name,
-				   struct device *parent)
+void drm_dp_cec_register_connector(struct drm_dp_aux *aux,
+				   struct drm_connector *connector)
 {
 	WARN_ON(aux->cec.adap);
 	if (WARN_ON(!aux->transfer))
 		return;
-	aux->cec.name = name;
-	aux->cec.parent = parent;
+	aux->cec.connector = connector;
 	INIT_DELAYED_WORK(&aux->cec.unregister_work,
 			  drm_dp_cec_unregister_work);
 }
diff --git a/drivers/gpu/drm/i2c/tda9950.c b/drivers/gpu/drm/i2c/tda9950.c
index 250b5e02a314a..b944dd9df85e1 100644
--- a/drivers/gpu/drm/i2c/tda9950.c
+++ b/drivers/gpu/drm/i2c/tda9950.c
@@ -424,7 +424,8 @@ static int tda9950_probe(struct i2c_client *client,
 
 	priv->adap = cec_allocate_adapter(&tda9950_cec_ops, priv, "tda9950",
 					  CEC_CAP_DEFAULTS,
-					  CEC_MAX_LOG_ADDRS);
+					  CEC_MAX_LOG_ADDRS,
+					  NULL);
 	if (IS_ERR(priv->adap))
 		return PTR_ERR(priv->adap);
 
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 560274d1c50b2..1dfd16848e033 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -5518,7 +5518,6 @@ static int
 intel_dp_connector_register(struct drm_connector *connector)
 {
 	struct intel_dp *intel_dp = intel_attached_dp(connector);
-	struct drm_device *dev = connector->dev;
 	int ret;
 
 	ret = intel_connector_register(connector);
@@ -5533,8 +5532,7 @@ intel_dp_connector_register(struct drm_connector *connector)
 	intel_dp->aux.dev = connector->kdev;
 	ret = drm_dp_aux_register(&intel_dp->aux);
 	if (!ret)
-		drm_dp_cec_register_connector(&intel_dp->aux,
-					      connector->name, dev->dev);
+		drm_dp_cec_register_connector(&intel_dp->aux, connector);
 	return ret;
 }
 
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
index 34be2cfd0ec8d..84b30ff91ebd5 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -2968,6 +2968,7 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port,
 	struct drm_device *dev = intel_encoder->base.dev;
 	struct drm_i915_private *dev_priv = to_i915(dev);
 	enum port port = intel_encoder->port;
+	struct cec_connector_info conn_info;
 
 	DRM_DEBUG_KMS("Adding HDMI connector on port %c\n",
 		      port_name(port));
@@ -3020,8 +3021,11 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port,
 		I915_WRITE(PEG_BAND_GAP_DATA, (temp & ~0xf) | 0xd);
 	}
 
+	cec_fill_connector_info(&conn_info, connector);
+
 	intel_hdmi->cec_notifier = cec_notifier_get_conn(dev->dev,
-							 port_identifier(port));
+							 port_identifier(port),
+							 &conn_info);
 	if (!intel_hdmi->cec_notifier)
 		DRM_DEBUG_KMS("CEC notifier get failed\n");
 }
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c
index 4116ee62adafe..4438824ca88b0 100644
--- a/drivers/gpu/drm/nouveau/nouveau_connector.c
+++ b/drivers/gpu/drm/nouveau/nouveau_connector.c
@@ -1413,8 +1413,7 @@ nouveau_connector_create(struct drm_device *dev,
 	switch (type) {
 	case DRM_MODE_CONNECTOR_DisplayPort:
 	case DRM_MODE_CONNECTOR_eDP:
-		drm_dp_cec_register_connector(&nv_connector->aux,
-					      connector->name, dev->dev);
+		drm_dp_cec_register_connector(&nv_connector->aux, connector);
 		break;
 	}
 
diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi4_cec.c b/drivers/gpu/drm/omapdrm/dss/hdmi4_cec.c
index ebf9c96d43eee..9d3839f8cc9ca 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi4_cec.c
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi4_cec.c
@@ -342,7 +342,7 @@ int hdmi4_cec_init(struct platform_device *pdev, struct hdmi_core_data *core,
 	int ret;
 
 	core->adap = cec_allocate_adapter(&hdmi_cec_adap_ops, core,
-		"omap4", caps, CEC_MAX_LOG_ADDRS);
+		"omap4", caps, CEC_MAX_LOG_ADDRS, NULL);
 	ret = PTR_ERR_OR_ZERO(core->adap);
 	if (ret < 0)
 		return ret;
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index 99fc8569e0f52..0e081ee5b9bf9 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -1279,6 +1279,9 @@ static const struct cec_adap_ops vc4_hdmi_cec_adap_ops = {
 
 static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 {
+#ifdef CONFIG_DRM_VC4_HDMI_CEC
+	struct cec_connector_info conn_info;
+#endif
 	struct platform_device *pdev = to_platform_device(dev);
 	struct drm_device *drm = dev_get_drvdata(master);
 	struct vc4_dev *vc4 = drm->dev_private;
@@ -1395,12 +1398,15 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 		goto err_destroy_encoder;
 	}
 #ifdef CONFIG_DRM_VC4_HDMI_CEC
+	cec_fill_connector_info(&conn_info, hdmi->connector);
+
 	hdmi->cec_adap = cec_allocate_adapter(&vc4_hdmi_cec_adap_ops,
 					      vc4, "vc4",
 					      CEC_CAP_TRANSMIT |
 					      CEC_CAP_LOG_ADDRS |
 					      CEC_CAP_PASSTHROUGH |
-					      CEC_CAP_RC, 1);
+					      CEC_CAP_RC, 1,
+					      &conn_info);
 	ret = PTR_ERR_OR_ZERO(hdmi->cec_adap);
 	if (ret < 0)
 		goto err_destroy_conn;
diff --git a/drivers/media/cec/cec-adap.c b/drivers/media/cec/cec-adap.c
index f1261cc2b6fa5..1d2c78bbf3687 100644
--- a/drivers/media/cec/cec-adap.c
+++ b/drivers/media/cec/cec-adap.c
@@ -16,7 +16,10 @@
 #include <linux/string.h>
 #include <linux/types.h>
 
+#include <drm/drm_connector.h>
+#include <drm/drm_device.h>
 #include <drm/drm_edid.h>
+#include <drm/drm_file.h>
 
 #include "cec-priv.h"
 
@@ -75,6 +78,16 @@ u16 cec_get_edid_phys_addr(const u8 *edid, unsigned int size,
 }
 EXPORT_SYMBOL_GPL(cec_get_edid_phys_addr);
 
+void cec_fill_connector_info(struct cec_connector_info *conn_info,
+			     const struct drm_connector *connector)
+{
+	memset(conn_info, 0, sizeof(*conn_info));
+	conn_info->type = CEC_CONNECTOR_TYPE_DRM;
+	conn_info->drm.card_no = connector->dev->primary->index;
+	conn_info->drm.connector_id = connector->base.id;
+}
+EXPORT_SYMBOL_GPL(cec_fill_connector_info);
+
 /*
  * Queue a new event for this filehandle. If ts == 0, then set it
  * to the current time.
diff --git a/drivers/media/cec/cec-api.c b/drivers/media/cec/cec-api.c
index 156a0d76ab2a1..2ed312ad34a39 100644
--- a/drivers/media/cec/cec-api.c
+++ b/drivers/media/cec/cec-api.c
@@ -187,6 +187,15 @@ static long cec_adap_s_log_addrs(struct cec_adapter *adap, struct cec_fh *fh,
 	return 0;
 }
 
+static long cec_adap_g_connector_info(struct cec_adapter *adap,
+				      struct cec_log_addrs __user *parg)
+{
+	if (copy_to_user(parg, &adap->connector_info,
+			 sizeof(adap->connector_info)))
+		return -EFAULT;
+	return 0;
+}
+
 static long cec_transmit(struct cec_adapter *adap, struct cec_fh *fh,
 			 bool block, struct cec_msg __user *parg)
 {
@@ -514,6 +523,9 @@ static long cec_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 	case CEC_ADAP_S_LOG_ADDRS:
 		return cec_adap_s_log_addrs(adap, fh, block, parg);
 
+	case CEC_ADAP_G_CONNECTOR_INFO:
+		return cec_adap_g_connector_info(adap, parg);
+
 	case CEC_TRANSMIT:
 		return cec_transmit(adap, fh, block, parg);
 
diff --git a/drivers/media/cec/cec-core.c b/drivers/media/cec/cec-core.c
index f5d1578e256a7..7cba00981e841 100644
--- a/drivers/media/cec/cec-core.c
+++ b/drivers/media/cec/cec-core.c
@@ -250,8 +250,9 @@ static const struct file_operations cec_error_inj_fops = {
 #endif
 
 struct cec_adapter *cec_allocate_adapter(const struct cec_adap_ops *ops,
-					 void *priv, const char *name, u32 caps,
-					 u8 available_las)
+			void *priv, const char *name, u32 caps,
+			u8 available_las,
+			const struct cec_connector_info *connector_info)
 {
 	struct cec_adapter *adap;
 	int res;
@@ -288,6 +289,9 @@ struct cec_adapter *cec_allocate_adapter(const struct cec_adap_ops *ops,
 	INIT_LIST_HEAD(&adap->wait_queue);
 	init_waitqueue_head(&adap->kthread_waitq);
 
+	if (connector_info)
+		adap->connector_info = *connector_info;
+
 	/* adap->devnode initialization */
 	INIT_LIST_HEAD(&adap->devnode.fhs);
 	mutex_init(&adap->devnode.lock);
diff --git a/drivers/media/cec/cec-notifier.c b/drivers/media/cec/cec-notifier.c
index 9598c7778871a..36820d0d71677 100644
--- a/drivers/media/cec/cec-notifier.c
+++ b/drivers/media/cec/cec-notifier.c
@@ -27,12 +27,16 @@ struct cec_notifier {
 	void (*callback)(struct cec_adapter *adap, u16 pa);
 
 	u16 phys_addr;
+	struct cec_connector_info connector_info;
 };
 
 static LIST_HEAD(cec_notifiers);
 static DEFINE_MUTEX(cec_notifiers_lock);
 
-struct cec_notifier *cec_notifier_get_conn(struct device *dev, const char *conn)
+struct cec_notifier *
+cec_notifier_get_conn(struct device *dev,
+		      const char *conn,
+		      const struct cec_connector_info *connector_info)
 {
 	struct cec_notifier *n;
 
@@ -52,6 +56,10 @@ struct cec_notifier *cec_notifier_get_conn(struct device *dev, const char *conn)
 	if (conn)
 		n->conn = kstrdup(conn, GFP_KERNEL);
 	n->phys_addr = CEC_PHYS_ADDR_INVALID;
+
+	if (connector_info)
+		n->connector_info = *connector_info;
+
 	mutex_init(&n->lock);
 	kref_init(&n->kref);
 	list_add_tail(&n->head, &cec_notifiers);
@@ -107,9 +115,17 @@ void cec_notifier_set_phys_addr_from_edid(struct cec_notifier *n,
 }
 EXPORT_SYMBOL_GPL(cec_notifier_set_phys_addr_from_edid);
 
+const struct cec_connector_info *cec_notifier_get_conn_info(
+	struct cec_notifier *n)
+{
+	return &n->connector_info;
+}
+EXPORT_SYMBOL_GPL(cec_notifier_get_conn_info);
+
 void cec_notifier_register(struct cec_notifier *n,
 			   struct cec_adapter *adap,
-			   void (*callback)(struct cec_adapter *adap, u16 pa))
+			   void (*callback)(struct cec_adapter *adap,
+					    u16 pa))
 {
 	kref_get(&n->kref);
 	mutex_lock(&n->lock);
diff --git a/drivers/media/cec/cec-pin.c b/drivers/media/cec/cec-pin.c
index 8f987bc0dd883..1a04a9be737a9 100644
--- a/drivers/media/cec/cec-pin.c
+++ b/drivers/media/cec/cec-pin.c
@@ -1320,7 +1320,7 @@ struct cec_adapter *cec_pin_allocate_adapter(const struct cec_pin_ops *pin_ops,
 
 	adap = cec_allocate_adapter(&cec_pin_adap_ops, priv, name,
 			    caps | CEC_CAP_MONITOR_ALL | CEC_CAP_MONITOR_PIN,
-			    CEC_MAX_LOG_ADDRS);
+			    CEC_MAX_LOG_ADDRS, NULL);
 
 	if (IS_ERR(adap)) {
 		kfree(pin);
diff --git a/drivers/media/i2c/adv7511.c b/drivers/media/i2c/adv7511.c
index cec5ebb1c9e60..a785a120e5356 100644
--- a/drivers/media/i2c/adv7511.c
+++ b/drivers/media/i2c/adv7511.c
@@ -1917,7 +1917,7 @@ static int adv7511_probe(struct i2c_client *client, const struct i2c_device_id *
 #if IS_ENABLED(CONFIG_VIDEO_ADV7511_CEC)
 	state->cec_adap = cec_allocate_adapter(&adv7511_cec_adap_ops,
 		state, dev_name(&client->dev), CEC_CAP_DEFAULTS,
-		ADV7511_MAX_ADDRS);
+		ADV7511_MAX_ADDRS, NULL);
 	err = PTR_ERR_OR_ZERO(state->cec_adap);
 	if (err) {
 		destroy_workqueue(state->work_queue);
diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c
index 28a84bf9f8a94..0a3649f593a7d 100644
--- a/drivers/media/i2c/adv7604.c
+++ b/drivers/media/i2c/adv7604.c
@@ -3564,7 +3564,7 @@ static int adv76xx_probe(struct i2c_client *client,
 #if IS_ENABLED(CONFIG_VIDEO_ADV7604_CEC)
 	state->cec_adap = cec_allocate_adapter(&adv76xx_cec_adap_ops,
 		state, dev_name(&client->dev),
-		CEC_CAP_DEFAULTS, ADV76XX_MAX_ADDRS);
+		CEC_CAP_DEFAULTS, ADV76XX_MAX_ADDRS, NULL);
 	err = PTR_ERR_OR_ZERO(state->cec_adap);
 	if (err)
 		goto err_entity;
diff --git a/drivers/media/i2c/adv7842.c b/drivers/media/i2c/adv7842.c
index 11ab2df02dc70..ff78a31316bbf 100644
--- a/drivers/media/i2c/adv7842.c
+++ b/drivers/media/i2c/adv7842.c
@@ -3565,7 +3565,7 @@ static int adv7842_probe(struct i2c_client *client,
 #if IS_ENABLED(CONFIG_VIDEO_ADV7842_CEC)
 	state->cec_adap = cec_allocate_adapter(&adv7842_cec_adap_ops,
 		state, dev_name(&client->dev),
-		CEC_CAP_DEFAULTS, ADV7842_MAX_ADDRS);
+		CEC_CAP_DEFAULTS, ADV7842_MAX_ADDRS, NULL);
 	err = PTR_ERR_OR_ZERO(state->cec_adap);
 	if (err)
 		goto err_entity;
diff --git a/drivers/media/i2c/tc358743.c b/drivers/media/i2c/tc358743.c
index bc2e35e5ce615..14a686c80a9e6 100644
--- a/drivers/media/i2c/tc358743.c
+++ b/drivers/media/i2c/tc358743.c
@@ -2117,7 +2117,8 @@ static int tc358743_probe(struct i2c_client *client,
 #ifdef CONFIG_VIDEO_TC358743_CEC
 	state->cec_adap = cec_allocate_adapter(&tc358743_cec_adap_ops,
 		state, dev_name(&client->dev),
-		CEC_CAP_DEFAULTS | CEC_CAP_MONITOR_ALL, CEC_MAX_LOG_ADDRS);
+		CEC_CAP_DEFAULTS | CEC_CAP_MONITOR_ALL, CEC_MAX_LOG_ADDRS,
+		NULL);
 	if (IS_ERR(state->cec_adap)) {
 		err = PTR_ERR(state->cec_adap);
 		goto err_hdl;
diff --git a/drivers/media/platform/cros-ec-cec/cros-ec-cec.c b/drivers/media/platform/cros-ec-cec/cros-ec-cec.c
index 068df9888dbf0..f7e7a9e5f8f74 100644
--- a/drivers/media/platform/cros-ec-cec/cros-ec-cec.c
+++ b/drivers/media/platform/cros-ec-cec/cros-ec-cec.c
@@ -235,7 +235,7 @@ static int cros_ec_cec_get_notifier(struct device *dev,
 			if (!d)
 				return -EPROBE_DEFER;
 
-			*notify = cec_notifier_get_conn(d, m->conn);
+			*notify = cec_notifier_get_conn(d, m->conn, NULL);
 			put_device(d);
 			return 0;
 		}
@@ -261,6 +261,7 @@ static int cros_ec_cec_probe(struct platform_device *pdev)
 {
 	struct cros_ec_dev *ec_dev = dev_get_drvdata(pdev->dev.parent);
 	struct cros_ec_device *cros_ec = ec_dev->ec_dev;
+	const struct cec_connector_info *conn_info;
 	struct cros_ec_cec *cros_ec_cec;
 	int ret;
 
@@ -282,8 +283,10 @@ static int cros_ec_cec_probe(struct platform_device *pdev)
 		return ret;
 	}
 
+	conn_info = cec_notifier_get_conn_info(cros_ec_cec->notify);
+
 	cros_ec_cec->adap = cec_allocate_adapter(&cros_ec_cec_ops, cros_ec_cec,
-						 DRV_NAME, CEC_CAP_DEFAULTS, 1);
+				DRV_NAME, CEC_CAP_DEFAULTS, 1, conn_info);
 	if (IS_ERR(cros_ec_cec->adap))
 		return PTR_ERR(cros_ec_cec->adap);
 
diff --git a/drivers/media/platform/meson/ao-cec-g12a.c b/drivers/media/platform/meson/ao-cec-g12a.c
index 3620a1e310f52..e4c45d7d0abd2 100644
--- a/drivers/media/platform/meson/ao-cec-g12a.c
+++ b/drivers/media/platform/meson/ao-cec-g12a.c
@@ -657,7 +657,8 @@ static int meson_ao_cec_g12a_probe(struct platform_device *pdev)
 	ao_cec->adap = cec_allocate_adapter(&meson_ao_cec_g12a_ops, ao_cec,
 					    "meson_g12a_ao_cec",
 					    CEC_CAP_DEFAULTS,
-					    CEC_MAX_LOG_ADDRS);
+					    CEC_MAX_LOG_ADDRS,
+					    NULL);
 	if (IS_ERR(ao_cec->adap)) {
 		ret = PTR_ERR(ao_cec->adap);
 		goto out_probe_notify;
diff --git a/drivers/media/platform/meson/ao-cec.c b/drivers/media/platform/meson/ao-cec.c
index facf9b029e797..c219925a7c5c7 100644
--- a/drivers/media/platform/meson/ao-cec.c
+++ b/drivers/media/platform/meson/ao-cec.c
@@ -600,6 +600,7 @@ static const struct cec_adap_ops meson_ao_cec_ops = {
 
 static int meson_ao_cec_probe(struct platform_device *pdev)
 {
+	const struct cec_connector_info *conn_info;
 	struct meson_ao_cec_device *ao_cec;
 	struct device *hdmi_dev;
 	struct resource *res;
@@ -620,13 +621,16 @@ static int meson_ao_cec_probe(struct platform_device *pdev)
 	if (!ao_cec->notify)
 		return -ENOMEM;
 
+	conn_info = cec_notifier_get_conn_info(ao_cec->notify);
+
 	ao_cec->adap = cec_allocate_adapter(&meson_ao_cec_ops, ao_cec,
 					    "meson_ao_cec",
 					    CEC_CAP_LOG_ADDRS |
 					    CEC_CAP_TRANSMIT |
 					    CEC_CAP_RC |
 					    CEC_CAP_PASSTHROUGH,
-					    1); /* Use 1 for now */
+					    1, /* Use 1 for now */
+					    conn_info);
 	if (IS_ERR(ao_cec->adap)) {
 		ret = PTR_ERR(ao_cec->adap);
 		goto out_probe_notify;
diff --git a/drivers/media/platform/s5p-cec/s5p_cec.c b/drivers/media/platform/s5p-cec/s5p_cec.c
index 7f62f5ef00863..6236f9f7111f0 100644
--- a/drivers/media/platform/s5p-cec/s5p_cec.c
+++ b/drivers/media/platform/s5p-cec/s5p_cec.c
@@ -177,6 +177,7 @@ static const struct cec_adap_ops s5p_cec_adap_ops = {
 
 static int s5p_cec_probe(struct platform_device *pdev)
 {
+	const struct cec_connector_info *conn_info;
 	struct device *dev = &pdev->dev;
 	struct device *hdmi_dev;
 	struct resource *res;
@@ -222,8 +223,11 @@ static int s5p_cec_probe(struct platform_device *pdev)
 	if (cec->notifier == NULL)
 		return -ENOMEM;
 
+	conn_info = cec_notifier_get_conn_info(cec->notifier);
+
 	cec->adap = cec_allocate_adapter(&s5p_cec_adap_ops, cec, CEC_NAME,
-		CEC_CAP_DEFAULTS | (needs_hpd ? CEC_CAP_NEEDS_HPD : 0), 1);
+		CEC_CAP_DEFAULTS | (needs_hpd ? CEC_CAP_NEEDS_HPD : 0), 1,
+		conn_info);
 	ret = PTR_ERR_OR_ZERO(cec->adap);
 	if (ret)
 		return ret;
diff --git a/drivers/media/platform/seco-cec/seco-cec.c b/drivers/media/platform/seco-cec/seco-cec.c
index e5080d6f5b2d3..f74b9f059d21a 100644
--- a/drivers/media/platform/seco-cec/seco-cec.c
+++ b/drivers/media/platform/seco-cec/seco-cec.c
@@ -535,7 +535,7 @@ static int secocec_cec_get_notifier(struct cec_notifier **notify)
 			if (!d)
 				return -EPROBE_DEFER;
 
-			*notify = cec_notifier_get_conn(d, m->conn);
+			*notify = cec_notifier_get_conn(d, m->conn, NULL);
 			put_device(d);
 
 			return 0;
@@ -571,6 +571,7 @@ static int secocec_acpi_probe(struct secocec_data *sdev)
 
 static int secocec_probe(struct platform_device *pdev)
 {
+	const struct cec_connector_info *conn_info;
 	struct secocec_data *secocec;
 	struct device *dev = &pdev->dev;
 	int ret;
@@ -636,12 +637,15 @@ static int secocec_probe(struct platform_device *pdev)
 		goto err;
 	}
 
+	conn_info = cec_notifier_get_conn_info(secocec->notifier);
+
 	/* Allocate CEC adapter */
 	secocec->cec_adap = cec_allocate_adapter(&secocec_cec_adap_ops,
 						 secocec,
 						 dev_name(dev),
 						 CEC_CAP_DEFAULTS,
-						 SECOCEC_MAX_ADDRS);
+						 SECOCEC_MAX_ADDRS,
+						 conn_info);
 
 	if (IS_ERR(secocec->cec_adap)) {
 		ret = PTR_ERR(secocec->cec_adap);
diff --git a/drivers/media/platform/sti/cec/stih-cec.c b/drivers/media/platform/sti/cec/stih-cec.c
index fc37efe1d5542..0b8fbc99a7ea9 100644
--- a/drivers/media/platform/sti/cec/stih-cec.c
+++ b/drivers/media/platform/sti/cec/stih-cec.c
@@ -298,6 +298,7 @@ static const struct cec_adap_ops sti_cec_adap_ops = {
 
 static int stih_cec_probe(struct platform_device *pdev)
 {
+	const struct cec_connector_info *conn_info;
 	struct device *dev = &pdev->dev;
 	struct resource *res;
 	struct stih_cec *cec;
@@ -340,8 +341,11 @@ static int stih_cec_probe(struct platform_device *pdev)
 		return PTR_ERR(cec->clk);
 	}
 
+	conn_info = cec_notifier_get_conn_info(cec->notifier);
+
 	cec->adap = cec_allocate_adapter(&sti_cec_adap_ops, cec,
-			CEC_NAME, CEC_CAP_DEFAULTS, CEC_MAX_LOG_ADDRS);
+			CEC_NAME, CEC_CAP_DEFAULTS, CEC_MAX_LOG_ADDRS,
+			conn_info);
 	ret = PTR_ERR_OR_ZERO(cec->adap);
 	if (ret)
 		return ret;
diff --git a/drivers/media/platform/stm32/stm32-cec.c b/drivers/media/platform/stm32/stm32-cec.c
index 8a86b2cc22fab..632bda0504983 100644
--- a/drivers/media/platform/stm32/stm32-cec.c
+++ b/drivers/media/platform/stm32/stm32-cec.c
@@ -315,7 +315,7 @@ static int stm32_cec_probe(struct platform_device *pdev)
 	 * available for example when a drm driver can provide edid
 	 */
 	cec->adap = cec_allocate_adapter(&stm32_cec_adap_ops, cec,
-			CEC_NAME, caps,	CEC_MAX_LOG_ADDRS);
+			CEC_NAME, caps,	CEC_MAX_LOG_ADDRS, NULL);
 	ret = PTR_ERR_OR_ZERO(cec->adap);
 	if (ret)
 		return ret;
diff --git a/drivers/media/platform/tegra-cec/tegra_cec.c b/drivers/media/platform/tegra-cec/tegra_cec.c
index 447bdfbe5afe1..20b9fe9868ec7 100644
--- a/drivers/media/platform/tegra-cec/tegra_cec.c
+++ b/drivers/media/platform/tegra-cec/tegra_cec.c
@@ -327,6 +327,7 @@ static const struct cec_adap_ops tegra_cec_ops = {
 
 static int tegra_cec_probe(struct platform_device *pdev)
 {
+	const struct cec_connector_info *conn_info;
 	struct device *hdmi_dev;
 	struct tegra_cec *cec;
 	struct resource *res;
@@ -400,9 +401,11 @@ static int tegra_cec_probe(struct platform_device *pdev)
 		goto clk_error;
 	}
 
+	conn_info = cec_notifier_get_conn_info(cec->notifier);
+
 	cec->adap = cec_allocate_adapter(&tegra_cec_ops, cec, TEGRA_CEC_NAME,
 			CEC_CAP_DEFAULTS | CEC_CAP_MONITOR_ALL,
-			CEC_MAX_LOG_ADDRS);
+			CEC_MAX_LOG_ADDRS, conn_info);
 	if (IS_ERR(cec->adap)) {
 		ret = -ENOMEM;
 		dev_err(&pdev->dev, "Couldn't create cec adapter\n");
diff --git a/drivers/media/platform/vivid/vivid-cec.c b/drivers/media/platform/vivid/vivid-cec.c
index 4d822dbed9726..ef15c9c58c2a6 100644
--- a/drivers/media/platform/vivid/vivid-cec.c
+++ b/drivers/media/platform/vivid/vivid-cec.c
@@ -283,5 +283,5 @@ struct cec_adapter *vivid_cec_alloc_adap(struct vivid_dev *dev,
 		 is_source ? dev->vid_out_dev.name : dev->vid_cap_dev.name,
 		 idx);
 	return cec_allocate_adapter(&vivid_cec_adap_ops, dev,
-		name, caps, 1);
+		name, caps, 1, NULL);
 }
diff --git a/drivers/media/usb/pulse8-cec/pulse8-cec.c b/drivers/media/usb/pulse8-cec/pulse8-cec.c
index ea9ee74fa3365..22adcce739fdd 100644
--- a/drivers/media/usb/pulse8-cec/pulse8-cec.c
+++ b/drivers/media/usb/pulse8-cec/pulse8-cec.c
@@ -656,7 +656,8 @@ static int pulse8_connect(struct serio *serio, struct serio_driver *drv)
 
 	pulse8->serio = serio;
 	pulse8->adap = cec_allocate_adapter(&pulse8_cec_adap_ops, pulse8,
-					    dev_name(&serio->dev), caps, 1);
+					    dev_name(&serio->dev), caps, 1,
+					    NULL);
 	err = PTR_ERR_OR_ZERO(pulse8->adap);
 	if (err < 0)
 		goto free_device;
diff --git a/drivers/media/usb/rainshadow-cec/rainshadow-cec.c b/drivers/media/usb/rainshadow-cec/rainshadow-cec.c
index d9964da05976b..8681e4d6b3d59 100644
--- a/drivers/media/usb/rainshadow-cec/rainshadow-cec.c
+++ b/drivers/media/usb/rainshadow-cec/rainshadow-cec.c
@@ -323,7 +323,8 @@ static int rain_connect(struct serio *serio, struct serio_driver *drv)
 
 	rain->serio = serio;
 	rain->adap = cec_allocate_adapter(&rain_cec_adap_ops, rain,
-					  dev_name(&serio->dev), caps, 1);
+					  dev_name(&serio->dev), caps, 1,
+					  NULL);
 	err = PTR_ERR_OR_ZERO(rain->adap);
 	if (err < 0)
 		goto free_device;
diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h
index 97ce790a5b5aa..eeb42abc343c6 100644
--- a/include/drm/drm_dp_helper.h
+++ b/include/drm/drm_dp_helper.h
@@ -1208,6 +1208,7 @@ struct drm_dp_aux_msg {
 
 struct cec_adapter;
 struct edid;
+struct drm_connector;
 
 /**
  * struct drm_dp_aux_cec - DisplayPort CEC-Tunneling-over-AUX
@@ -1220,8 +1221,7 @@ struct edid;
 struct drm_dp_aux_cec {
 	struct mutex lock;
 	struct cec_adapter *adap;
-	const char *name;
-	struct device *parent;
+	struct drm_connector *connector;
 	struct delayed_work unregister_work;
 };
 
@@ -1418,8 +1418,8 @@ drm_dp_has_quirk(const struct drm_dp_desc *desc, enum drm_dp_quirk quirk)
 
 #ifdef CONFIG_DRM_DP_CEC
 void drm_dp_cec_irq(struct drm_dp_aux *aux);
-void drm_dp_cec_register_connector(struct drm_dp_aux *aux, const char *name,
-				   struct device *parent);
+void drm_dp_cec_register_connector(struct drm_dp_aux *aux,
+				   struct drm_connector *connector);
 void drm_dp_cec_unregister_connector(struct drm_dp_aux *aux);
 void drm_dp_cec_set_edid(struct drm_dp_aux *aux, const struct edid *edid);
 void drm_dp_cec_unset_edid(struct drm_dp_aux *aux);
@@ -1428,9 +1428,9 @@ static inline void drm_dp_cec_irq(struct drm_dp_aux *aux)
 {
 }
 
-static inline void drm_dp_cec_register_connector(struct drm_dp_aux *aux,
-						 const char *name,
-						 struct device *parent)
+static inline void
+drm_dp_cec_register_connector(struct drm_dp_aux *aux,
+			      struct drm_connector *connector)
 {
 }
 
diff --git a/include/media/cec-notifier.h b/include/media/cec-notifier.h
index 57b3a9f6ea1d5..7e39c10672a2d 100644
--- a/include/media/cec-notifier.h
+++ b/include/media/cec-notifier.h
@@ -24,6 +24,8 @@ struct cec_notifier;
  * device and connector tuple.
  * @dev: device that sends the events.
  * @conn: the connector name from which the event occurs
+ * @connector_info: relevant only if the call is used to create a notifier,
+ *   the connector's info to associate with new notifier.
  *
  * If a notifier for device @dev already exists, then increase the refcount
  * and return that notifier.
@@ -33,8 +35,10 @@ struct cec_notifier;
  *
  * Return NULL if the memory could not be allocated.
  */
-struct cec_notifier *cec_notifier_get_conn(struct device *dev,
-					   const char *conn);
+struct cec_notifier *cec_notifier_get_conn(
+			struct device *dev,
+			const char *conn,
+			const struct cec_connector_info *connector_info);
 
 /**
  * cec_notifier_put - decrease refcount and delete when the refcount reaches 0.
@@ -79,6 +83,14 @@ void cec_notifier_register(struct cec_notifier *n,
  */
 void cec_notifier_unregister(struct cec_notifier *n);
 
+/**
+ * cec_notifier_get_conn_info - get connector info associated with a
+ * notifier.
+ * @n: the CEC notifier
+ */
+const struct cec_connector_info *
+cec_notifier_get_conn_info(struct cec_notifier *n);
+
 /**
  * cec_register_cec_notifier - register the notifier with the cec adapter.
  * @adap: the CEC adapter
@@ -99,8 +111,10 @@ void cec_register_cec_notifier(struct cec_adapter *adap,
 struct device *cec_notifier_parse_hdmi_phandle(struct device *dev);
 
 #else
-static inline struct cec_notifier *cec_notifier_get_conn(struct device *dev,
-							 const char *conn)
+static inline struct cec_notifier *
+cec_notifier_get_conn(struct device *dev,
+		      const char *conn,
+		      const struct cec_connector_info *connector_info)
 {
 	/* A non-NULL pointer is expected on success */
 	return (struct cec_notifier *)0xdeadfeed;
@@ -119,9 +133,15 @@ static inline void cec_notifier_set_phys_addr_from_edid(struct cec_notifier *n,
 {
 }
 
+static inline const struct cec_connector_info*
+cec_notifier_get_conn_info(struct cec_notifier *n)
+{
+	return NULL;
+}
+
 static inline void cec_notifier_register(struct cec_notifier *n,
-			 struct cec_adapter *adap,
-			 void (*callback)(struct cec_adapter *adap, u16 pa))
+			struct cec_adapter *adap,
+			void (*callback)(struct cec_adapter *adap, u16 pa))
 {
 }
 
@@ -155,7 +175,7 @@ static inline struct device *cec_notifier_parse_hdmi_phandle(struct device *dev)
  */
 static inline struct cec_notifier *cec_notifier_get(struct device *dev)
 {
-	return cec_notifier_get_conn(dev, NULL);
+	return cec_notifier_get_conn(dev, NULL, NULL);
 }
 
 /**
diff --git a/include/media/cec.h b/include/media/cec.h
index 707411ef8ba28..6e0f9b70d36f5 100644
--- a/include/media/cec.h
+++ b/include/media/cec.h
@@ -200,6 +200,8 @@ struct cec_adapter {
 	u32 sequence;
 
 	char input_phys[32];
+
+	struct cec_connector_info connector_info;
 };
 
 static inline void *cec_get_drvdata(const struct cec_adapter *adap)
@@ -233,10 +235,12 @@ static inline bool cec_is_registered(const struct cec_adapter *adap)
 	((pa) >> 12), ((pa) >> 8) & 0xf, ((pa) >> 4) & 0xf, (pa) & 0xf
 
 struct edid;
+struct drm_connector;
 
 #if IS_REACHABLE(CONFIG_CEC_CORE)
 struct cec_adapter *cec_allocate_adapter(const struct cec_adap_ops *ops,
-		void *priv, const char *name, u32 caps, u8 available_las);
+		void *priv, const char *name, u32 caps, u8 available_las,
+		const struct cec_connector_info *connector_info);
 int cec_register_adapter(struct cec_adapter *adap, struct device *parent);
 void cec_unregister_adapter(struct cec_adapter *adap);
 void cec_delete_adapter(struct cec_adapter *adap);
@@ -331,6 +335,9 @@ void cec_queue_pin_5v_event(struct cec_adapter *adap, bool is_high, ktime_t ts);
 u16 cec_get_edid_phys_addr(const u8 *edid, unsigned int size,
 			   unsigned int *offset);
 
+void cec_fill_connector_info(struct cec_connector_info *connector_info,
+			     const struct drm_connector *connector);
+
 #else
 
 static inline int cec_register_adapter(struct cec_adapter *adap,
@@ -365,6 +372,13 @@ static inline u16 cec_get_edid_phys_addr(const u8 *edid, unsigned int size,
 	return CEC_PHYS_ADDR_INVALID;
 }
 
+static inline void
+cec_fill_connector_info(const struct drm_connector *connector,
+			struct cec_connector_info *conn_info)
+{
+	memset(conn_info, 0, sizeof(*conn_info));
+}
+
 #endif
 
 /**
diff --git a/include/uapi/linux/cec.h b/include/uapi/linux/cec.h
index 3094af68b6e76..14097023ce171 100644
--- a/include/uapi/linux/cec.h
+++ b/include/uapi/linux/cec.h
@@ -411,6 +411,27 @@ struct cec_event_lost_msgs {
 	__u32 lost_msgs;
 };
 
+/**
+ * struct cec_event_connector - tells if and which connector is associated
+ * with the CEC adapter.
+ * @card_no: drm card number
+ * @connector_id: drm connector ID
+ */
+struct cec_drm_connector_info {
+	__u32 card_no;
+	__u32 connector_id;
+};
+
+#define CEC_CONNECTOR_TYPE_NO_CONNECTOR	0
+#define CEC_CONNECTOR_TYPE_DRM		1
+struct cec_connector_info {
+	__u32 type;
+	union {
+		struct cec_drm_connector_info drm;
+		__u32 raw[16];
+	};
+};
+
 /**
  * struct cec_event - CEC event structure
  * @ts: the timestamp of when the event was sent.
@@ -475,6 +496,9 @@ struct cec_event {
 #define CEC_G_MODE		_IOR('a',  8, __u32)
 #define CEC_S_MODE		_IOW('a',  9, __u32)
 
+/* Gets the connector info */
+#define CEC_ADAP_G_CONNECTOR_INFO _IOR('a',  10, struct cec_connector_info)
+
 /*
  * The remainder of this header defines all CEC messages and operands.
  * The format matters since it the cec-ctl utility parses it to generate
-- 
2.18.1


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

* [PATCH v7 2/3] drm/bridge: dw-hdmi: pass connector info to the CEC adapter
  2019-05-21 10:52 [PATCH v7 1/3] media: cec: expose HDMI connector to CEC dev mapping Dariusz Marcinkiewicz
@ 2019-05-21 10:52 ` Dariusz Marcinkiewicz
  2019-05-21 10:52 ` [PATCH v7 3/3] drm/i2c: tda9950: pass HDMI connector info to " Dariusz Marcinkiewicz
  2019-05-24  9:21 ` [PATCH v7 1/3] media: cec: expose HDMI connector to CEC dev mapping Hans Verkuil
  2 siblings, 0 replies; 9+ messages in thread
From: Dariusz Marcinkiewicz @ 2019-05-21 10:52 UTC (permalink / raw)
  To: linux-media, hans.verkuil, hverkuil; +Cc: linux-kernel, Dariusz Marcinkiewicz

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.

Changes since version v5:
- connector info is passed trough notifier, fixed CEC platform
  device initialization

Signed-off-by: Dariusz Marcinkiewicz <darekm@google.com>
---
 drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.c |  13 ++-
 drivers/gpu/drm/bridge/synopsys/dw-hdmi.c     | 103 ++++++++++--------
 2 files changed, 66 insertions(+), 50 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..64cc278f5a754 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);
+	const struct cec_connector_info *conn_info;
 	struct dw_hdmi_cec *cec;
 	int ret;
 
@@ -258,10 +259,16 @@ 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->notify = cec_notifier_get(pdev->dev.parent);
+	if (!cec->notify)
+		return -ENOMEM;
+
+	conn_info = cec_notifier_get_conn_info(cec->notify);
+
 	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);
 
@@ -281,10 +288,6 @@ static int dw_hdmi_cec_probe(struct platform_device *pdev)
 	if (ret < 0)
 		return ret;
 
-	cec->notify = cec_notifier_get(pdev->dev.parent);
-	if (!cec->notify)
-		return -ENOMEM;
-
 	ret = cec_register_adapter(cec->adap, pdev->dev.parent);
 	if (ret < 0) {
 		cec_notifier_put(cec->notify);
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
index ab7968c8f6a29..ed2f3e7e9c1cf 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;
 };
 
@@ -2113,11 +2116,35 @@ 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;
 	struct drm_encoder *encoder = bridge->encoder;
 	struct drm_connector *connector = &hdmi->connector;
+	struct cec_connector_info conn_info;
 
 	connector->interlace_allowed = 1;
 	connector->polled = DRM_CONNECTOR_POLL_HPD;
@@ -2129,6 +2156,34 @@ static int dw_hdmi_bridge_attach(struct drm_bridge *bridge)
 
 	drm_connector_attach_encoder(connector, encoder);
 
+	cec_fill_connector_info(&conn_info, connector);
+
+	hdmi->cec_notifier = cec_notifier_get_conn(hdmi->dev, NULL,
+						   &conn_info);
+	if (!hdmi->cec_notifier)
+		return -ENOMEM;
+
+	if (hdmi->cec_configured) {
+		struct platform_device_info pdevinfo;
+		struct dw_hdmi_cec_data cec;
+
+		memset(&pdevinfo, 0, sizeof(pdevinfo));
+		pdevinfo.parent = hdmi->dev;
+		pdevinfo.id = PLATFORM_DEVID_AUTO;
+
+		cec.hdmi = hdmi;
+		cec.ops = &dw_hdmi_cec_ops;
+		cec.irq = hdmi->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);
+
+	}
+
 	return 0;
 }
 
@@ -2398,29 +2453,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,
@@ -2443,7 +2475,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;
@@ -2593,6 +2624,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,
@@ -2600,12 +2632,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
@@ -2668,18 +2694,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)
@@ -2693,9 +2709,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);
-- 
2.18.1


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

* [PATCH v7 3/3] drm/i2c: tda9950: pass HDMI connector info to CEC adapter
  2019-05-21 10:52 [PATCH v7 1/3] media: cec: expose HDMI connector to CEC dev mapping Dariusz Marcinkiewicz
  2019-05-21 10:52 ` [PATCH v7 2/3] drm/bridge: dw-hdmi: pass connector info to the CEC adapter Dariusz Marcinkiewicz
@ 2019-05-21 10:52 ` Dariusz Marcinkiewicz
  2019-05-24  9:21 ` [PATCH v7 1/3] media: cec: expose HDMI connector to CEC dev mapping Hans Verkuil
  2 siblings, 0 replies; 9+ messages in thread
From: Dariusz Marcinkiewicz @ 2019-05-21 10:52 UTC (permalink / raw)
  To: linux-media, hans.verkuil, hverkuil; +Cc: linux-kernel, Dariusz Marcinkiewicz

With that change tda998x provides a connector info to the CEC
adapter. In order to be able to that it delays creation of
respective CEC device until the DRM connector is initialized.

Requires testing.

Signed-off-by: Dariusz Marcinkiewicz <darekm@google.com>
---
 drivers/gpu/drm/i2c/tda9950.c     | 13 +++++---
 drivers/gpu/drm/i2c/tda998x_drv.c | 55 ++++++++++++++++---------------
 2 files changed, 36 insertions(+), 32 deletions(-)

diff --git a/drivers/gpu/drm/i2c/tda9950.c b/drivers/gpu/drm/i2c/tda9950.c
index b944dd9df85e1..61ec50a2ca275 100644
--- a/drivers/gpu/drm/i2c/tda9950.c
+++ b/drivers/gpu/drm/i2c/tda9950.c
@@ -382,6 +382,7 @@ static int tda9950_probe(struct i2c_client *client,
 			 const struct i2c_device_id *id)
 {
 	struct tda9950_glue *glue = client->dev.platform_data;
+	const struct cec_connector_info *conn_info;
 	struct device *dev = &client->dev;
 	struct tda9950_priv *priv;
 	unsigned long irqflags;
@@ -422,10 +423,16 @@ static int tda9950_probe(struct i2c_client *client,
 	if (glue && glue->parent)
 		priv->hdmi = glue->parent;
 
+	priv->notify = cec_notifier_get(priv->hdmi);
+	if (!priv->notify)
+		return -ENOMEM;
+
+	conn_info = cec_notifier_get_conn_info(priv->notify);
+
 	priv->adap = cec_allocate_adapter(&tda9950_cec_ops, priv, "tda9950",
 					  CEC_CAP_DEFAULTS,
 					  CEC_MAX_LOG_ADDRS,
-					  NULL);
+					  conn_info);
 	if (IS_ERR(priv->adap))
 		return PTR_ERR(priv->adap);
 
@@ -461,10 +468,6 @@ static int tda9950_probe(struct i2c_client *client,
 	if (ret < 0)
 		return ret;
 
-	priv->notify = cec_notifier_get(priv->hdmi);
-	if (!priv->notify)
-		return -ENOMEM;
-
 	ret = cec_register_adapter(priv->adap, priv->hdmi);
 	if (ret < 0) {
 		cec_notifier_put(priv->notify);
diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c
index 7f34601bb5155..b1d76e6561e30 100644
--- a/drivers/gpu/drm/i2c/tda998x_drv.c
+++ b/drivers/gpu/drm/i2c/tda998x_drv.c
@@ -1253,6 +1253,8 @@ static int tda998x_connector_init(struct tda998x_priv *priv,
 				  struct drm_device *drm)
 {
 	struct drm_connector *connector = &priv->connector;
+	struct cec_connector_info conn_info;
+	struct i2c_board_info cec_info;
 	int ret;
 
 	connector->interlace_allowed = 1;
@@ -1269,6 +1271,32 @@ static int tda998x_connector_init(struct tda998x_priv *priv,
 	if (ret)
 		return ret;
 
+	/*
+	 * Some TDA998x are actually two I2C devices merged onto one piece
+	 * of silicon: TDA9989 and TDA19989 combine the HDMI transmitter
+	 * with a slightly modified TDA9950 CEC device.  The CEC device
+	 * is at the TDA9950 address, with the address pins strapped across
+	 * to the TDA998x address pins.  Hence, it always has the same
+	 * offset.
+	 */
+	memset(&cec_info, 0, sizeof(cec_info));
+	strlcpy(cec_info.type, "tda9950", sizeof(cec_info.type));
+	cec_info.addr = priv->cec_addr;
+	cec_info.platform_data = &priv->cec_glue;
+	cec_info.irq = priv->hdmi->irq;
+
+	priv->cec = i2c_new_device(priv->hdmi->adapter, &cec_info);
+	if (!priv->cec)
+		return -ENODEV;
+
+	cec_fill_connector_info(&conn_info, connector);
+
+	priv->cec_notify = cec_notifier_get_conn(priv->cec_glue.parent,
+						 NULL, &conn_info);
+	if (!priv->cec_notify)
+		return -ENOMEM;
+
+
 	drm_connector_attach_encoder(&priv->connector,
 				     priv->bridge.encoder);
 
@@ -1658,7 +1686,6 @@ static int tda998x_create(struct device *dev)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct device_node *np = client->dev.of_node;
-	struct i2c_board_info cec_info;
 	struct tda998x_priv *priv;
 	u32 video;
 	int rev_lo, rev_hi, ret;
@@ -1776,12 +1803,6 @@ static int tda998x_create(struct device *dev)
 		cec_write(priv, REG_CEC_RXSHPDINTENA, CEC_RXSHPDLEV_HPD);
 	}
 
-	priv->cec_notify = cec_notifier_get(dev);
-	if (!priv->cec_notify) {
-		ret = -ENOMEM;
-		goto fail;
-	}
-
 	priv->cec_glue.parent = dev;
 	priv->cec_glue.data = priv;
 	priv->cec_glue.init = tda998x_cec_hook_init;
@@ -1789,26 +1810,6 @@ static int tda998x_create(struct device *dev)
 	priv->cec_glue.open = tda998x_cec_hook_open;
 	priv->cec_glue.release = tda998x_cec_hook_release;
 
-	/*
-	 * Some TDA998x are actually two I2C devices merged onto one piece
-	 * of silicon: TDA9989 and TDA19989 combine the HDMI transmitter
-	 * with a slightly modified TDA9950 CEC device.  The CEC device
-	 * is at the TDA9950 address, with the address pins strapped across
-	 * to the TDA998x address pins.  Hence, it always has the same
-	 * offset.
-	 */
-	memset(&cec_info, 0, sizeof(cec_info));
-	strlcpy(cec_info.type, "tda9950", sizeof(cec_info.type));
-	cec_info.addr = priv->cec_addr;
-	cec_info.platform_data = &priv->cec_glue;
-	cec_info.irq = client->irq;
-
-	priv->cec = i2c_new_device(client->adapter, &cec_info);
-	if (!priv->cec) {
-		ret = -ENODEV;
-		goto fail;
-	}
-
 	/* enable EDID read irq: */
 	reg_set(priv, REG_INT_FLAGS_2, INT_FLAGS_2_EDID_BLK_RD);
 
-- 
2.18.1


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

* Re: [PATCH v7 1/3] media: cec: expose HDMI connector to CEC dev mapping
  2019-05-21 10:52 [PATCH v7 1/3] media: cec: expose HDMI connector to CEC dev mapping Dariusz Marcinkiewicz
  2019-05-21 10:52 ` [PATCH v7 2/3] drm/bridge: dw-hdmi: pass connector info to the CEC adapter Dariusz Marcinkiewicz
  2019-05-21 10:52 ` [PATCH v7 3/3] drm/i2c: tda9950: pass HDMI connector info to " Dariusz Marcinkiewicz
@ 2019-05-24  9:21 ` Hans Verkuil
  2019-05-28  7:53   ` Dariusz Marcinkiewicz
  2019-06-19 11:05   ` Dariusz Marcinkiewicz
  2 siblings, 2 replies; 9+ messages in thread
From: Hans Verkuil @ 2019-05-24  9:21 UTC (permalink / raw)
  To: Dariusz Marcinkiewicz, linux-media, hans.verkuil; +Cc: linux-kernel

Hi Dariusz,

I did some more testing with the Khadas VIM2 and found another problem,
something that will, unfortunately, require some redesign.

See my comments below...

On 5/21/19 12:52 PM, Dariusz Marcinkiewicz wrote:
> This patch proposes to expose explicit mapping between HDMI connectors
> and /dev/cecX adapters to userland.
> 
> New structure with connector info (card number and connector id in case
> of DRM connectors) is added to cec_adapter. That connector info is expected
> to be provided when an adapter is created.
> 
> CEC notifier is extended so that it can be used to communicate the
> connector's info to CEC adapters' creators.
> 
> New ioctl, exposing connector info to userland, is added to /dev/cec.
> 
> Changes since v6:
>  - updated remaining cec_allocate_adapter calls
> Changes since v5:
>  - make the patch apply against the latest changes in the affected code
> Changes since v4:
>  - small tweaks + added documentation
> Changes since v3:
>  - cec_get_connter_conn takes connector_info as argument
> Changes since v2:
>  - cec_s_connector_info removed, the connector info is now passed to
>    cec_allocate_adapter
>  - updated commit message
> Changes since v1:
>  - removed the unnecessary event,
>  - extended cec_connctor_info to allow for various types of connectors.
> 
> Signed-off-by: Dariusz Marcinkiewicz <darekm@google.com>
> ---

<snip>

> diff --git a/drivers/media/cec/cec-notifier.c b/drivers/media/cec/cec-notifier.c
> index 9598c7778871a..36820d0d71677 100644
> --- a/drivers/media/cec/cec-notifier.c
> +++ b/drivers/media/cec/cec-notifier.c
> @@ -27,12 +27,16 @@ struct cec_notifier {
>  	void (*callback)(struct cec_adapter *adap, u16 pa);
>  
>  	u16 phys_addr;
> +	struct cec_connector_info connector_info;
>  };
>  
>  static LIST_HEAD(cec_notifiers);
>  static DEFINE_MUTEX(cec_notifiers_lock);
>  
> -struct cec_notifier *cec_notifier_get_conn(struct device *dev, const char *conn)
> +struct cec_notifier *
> +cec_notifier_get_conn(struct device *dev,
> +		      const char *conn,
> +		      const struct cec_connector_info *connector_info)
>  {
>  	struct cec_notifier *n;
>  
> @@ -52,6 +56,10 @@ struct cec_notifier *cec_notifier_get_conn(struct device *dev, const char *conn)
>  	if (conn)
>  		n->conn = kstrdup(conn, GFP_KERNEL);
>  	n->phys_addr = CEC_PHYS_ADDR_INVALID;
> +
> +	if (connector_info)
> +		n->connector_info = *connector_info;
> +

The core problem is that you do not know in which order the CEC and the HDMI
drivers are loaded. In the case of my configuration the CEC driver ao-cec.c
loads before the dw-hdmi driver. So cec_notifier_get_conn() is called when the
cec_notifier was already created by the CEC driver. And if you look at the
control flow in this function you'll see that the connector info is never
copied in that case.

But that's just one problem...

>  	mutex_init(&n->lock);
>  	kref_init(&n->kref);
>  	list_add_tail(&n->head, &cec_notifiers);
> @@ -107,9 +115,17 @@ void cec_notifier_set_phys_addr_from_edid(struct cec_notifier *n,
>  }
>  EXPORT_SYMBOL_GPL(cec_notifier_set_phys_addr_from_edid);
>  
> +const struct cec_connector_info *cec_notifier_get_conn_info(
> +	struct cec_notifier *n)
> +{
> +	return &n->connector_info;
> +}
> +EXPORT_SYMBOL_GPL(cec_notifier_get_conn_info);
> +
>  void cec_notifier_register(struct cec_notifier *n,
>  			   struct cec_adapter *adap,
> -			   void (*callback)(struct cec_adapter *adap, u16 pa))
> +			   void (*callback)(struct cec_adapter *adap,
> +					    u16 pa))
>  {
>  	kref_get(&n->kref);
>  	mutex_lock(&n->lock);

<snip>

> diff --git a/drivers/media/platform/meson/ao-cec.c b/drivers/media/platform/meson/ao-cec.c
> index facf9b029e797..c219925a7c5c7 100644
> --- a/drivers/media/platform/meson/ao-cec.c
> +++ b/drivers/media/platform/meson/ao-cec.c
> @@ -600,6 +600,7 @@ static const struct cec_adap_ops meson_ao_cec_ops = {
>  
>  static int meson_ao_cec_probe(struct platform_device *pdev)
>  {
> +	const struct cec_connector_info *conn_info;
>  	struct meson_ao_cec_device *ao_cec;
>  	struct device *hdmi_dev;
>  	struct resource *res;
> @@ -620,13 +621,16 @@ static int meson_ao_cec_probe(struct platform_device *pdev)
>  	if (!ao_cec->notify)
>  		return -ENOMEM;
>  
> +	conn_info = cec_notifier_get_conn_info(ao_cec->notify);
> +
>  	ao_cec->adap = cec_allocate_adapter(&meson_ao_cec_ops, ao_cec,
>  					    "meson_ao_cec",
>  					    CEC_CAP_LOG_ADDRS |
>  					    CEC_CAP_TRANSMIT |
>  					    CEC_CAP_RC |
>  					    CEC_CAP_PASSTHROUGH,
> -					    1); /* Use 1 for now */
> +					    1, /* Use 1 for now */
> +					    conn_info);

The other problem is in the CEC driver: it creates the CEC device as
soon as the HDMI device is found (cec_notifier_parse_hdmi_phandle).

But that doesn't mean that the HDMI device also had registered itself
as a CEC notifier.

Until now that never mattered: as long as the HDMI device was found
the CEC adapter would function fine, it would just have no physical
address until so notified by the HDMI device once it registered its
CEC notifier.

But if we want to have valid connector info during the lifetime of
the CEC adapter, then this no longer works.

I'm not entirely sure how to handle this.

Another issue here is that when the HDMI driver removes the notifier,
then it should also zero the connector info. Remember that both the
HDMI and the CEC drivers can be loaded and unloaded independently from
one another.

I have the feeling that the cec-notifier framework is trying too hard
to be generic (i.e. without knowledge of whether a notifier is created
by an HDMI device or a CEC device). Instead I think we need functions
specifically for use with a HDMI device and functions specifically for
use with a CEC device.

I'll have to think about this a bit more early next week.

Regards,

	Hans

>  	if (IS_ERR(ao_cec->adap)) {
>  		ret = PTR_ERR(ao_cec->adap);
>  		goto out_probe_notify;

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

* Re: [PATCH v7 1/3] media: cec: expose HDMI connector to CEC dev mapping
  2019-05-24  9:21 ` [PATCH v7 1/3] media: cec: expose HDMI connector to CEC dev mapping Hans Verkuil
@ 2019-05-28  7:53   ` Dariusz Marcinkiewicz
  2019-05-28  8:05     ` Hans Verkuil
  2019-06-19 11:05   ` Dariusz Marcinkiewicz
  1 sibling, 1 reply; 9+ messages in thread
From: Dariusz Marcinkiewicz @ 2019-05-28  7:53 UTC (permalink / raw)
  To: Hans Verkuil; +Cc: linux-media, hans.verkuil, linux-kernel

On Fri, May 24, 2019 at 11:21 AM Hans Verkuil <hverkuil@xs4all.nl> wrote:
>
> Hi Dariusz,
>
> I did some more testing with the Khadas VIM2 and found another problem,
> something that will, unfortunately, require some redesign.
>
...
>
> The other problem is in the CEC driver: it creates the CEC device as
> soon as the HDMI device is found (cec_notifier_parse_hdmi_phandle).
>
> But that doesn't mean that the HDMI device also had registered itself
> as a CEC notifier.
>
> Until now that never mattered: as long as the HDMI device was found
> the CEC adapter would function fine, it would just have no physical
> address until so notified by the HDMI device once it registered its
> CEC notifier.
>
> But if we want to have valid connector info during the lifetime of
> the CEC adapter, then this no longer works.
>
> I'm not entirely sure how to handle this.
>
> Another issue here is that when the HDMI driver removes the notifier,
> then it should also zero the connector info. Remember that both the
> HDMI and the CEC drivers can be loaded and unloaded independently from
> one another.
>
Given all of the above, what do you think about coming back to the v1
of the patch, where a connector info could be set on an adapter at any
time and an event was used to notify userland when that happened? That
approach seems to cover all the scenarios mentioned above.

Thank you for testing the patches!

Best regards.

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

* Re: [PATCH v7 1/3] media: cec: expose HDMI connector to CEC dev mapping
  2019-05-28  7:53   ` Dariusz Marcinkiewicz
@ 2019-05-28  8:05     ` Hans Verkuil
  2019-05-29 14:47       ` Hans Verkuil
  0 siblings, 1 reply; 9+ messages in thread
From: Hans Verkuil @ 2019-05-28  8:05 UTC (permalink / raw)
  To: Dariusz Marcinkiewicz; +Cc: linux-media, linux-kernel

On 5/28/19 9:53 AM, Dariusz Marcinkiewicz wrote:
> On Fri, May 24, 2019 at 11:21 AM Hans Verkuil <hverkuil@xs4all.nl> wrote:
>>
>> Hi Dariusz,
>>
>> I did some more testing with the Khadas VIM2 and found another problem,
>> something that will, unfortunately, require some redesign.
>>
> ...
>>
>> The other problem is in the CEC driver: it creates the CEC device as
>> soon as the HDMI device is found (cec_notifier_parse_hdmi_phandle).
>>
>> But that doesn't mean that the HDMI device also had registered itself
>> as a CEC notifier.
>>
>> Until now that never mattered: as long as the HDMI device was found
>> the CEC adapter would function fine, it would just have no physical
>> address until so notified by the HDMI device once it registered its
>> CEC notifier.
>>
>> But if we want to have valid connector info during the lifetime of
>> the CEC adapter, then this no longer works.
>>
>> I'm not entirely sure how to handle this.
>>
>> Another issue here is that when the HDMI driver removes the notifier,
>> then it should also zero the connector info. Remember that both the
>> HDMI and the CEC drivers can be loaded and unloaded independently from
>> one another.
>>
> Given all of the above, what do you think about coming back to the v1
> of the patch, where a connector info could be set on an adapter at any
> time and an event was used to notify userland when that happened? That
> approach seems to cover all the scenarios mentioned above.

That's just hiding the real problems :-)

I hope to spend some time on CEC tomorrow and I'll get back to you then.

Regards,

	Hans

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

* Re: [PATCH v7 1/3] media: cec: expose HDMI connector to CEC dev mapping
  2019-05-28  8:05     ` Hans Verkuil
@ 2019-05-29 14:47       ` Hans Verkuil
  0 siblings, 0 replies; 9+ messages in thread
From: Hans Verkuil @ 2019-05-29 14:47 UTC (permalink / raw)
  To: Dariusz Marcinkiewicz; +Cc: linux-media, linux-kernel

On 5/28/19 10:05 AM, Hans Verkuil wrote:
> On 5/28/19 9:53 AM, Dariusz Marcinkiewicz wrote:
>> On Fri, May 24, 2019 at 11:21 AM Hans Verkuil <hverkuil@xs4all.nl> wrote:
>>>
>>> Hi Dariusz,
>>>
>>> I did some more testing with the Khadas VIM2 and found another problem,
>>> something that will, unfortunately, require some redesign.
>>>
>> ...
>>>
>>> The other problem is in the CEC driver: it creates the CEC device as
>>> soon as the HDMI device is found (cec_notifier_parse_hdmi_phandle).
>>>
>>> But that doesn't mean that the HDMI device also had registered itself
>>> as a CEC notifier.
>>>
>>> Until now that never mattered: as long as the HDMI device was found
>>> the CEC adapter would function fine, it would just have no physical
>>> address until so notified by the HDMI device once it registered its
>>> CEC notifier.
>>>
>>> But if we want to have valid connector info during the lifetime of
>>> the CEC adapter, then this no longer works.
>>>
>>> I'm not entirely sure how to handle this.
>>>
>>> Another issue here is that when the HDMI driver removes the notifier,
>>> then it should also zero the connector info. Remember that both the
>>> HDMI and the CEC drivers can be loaded and unloaded independently from
>>> one another.
>>>
>> Given all of the above, what do you think about coming back to the v1
>> of the patch, where a connector info could be set on an adapter at any
>> time and an event was used to notify userland when that happened? That
>> approach seems to cover all the scenarios mentioned above.
> 
> That's just hiding the real problems :-)
> 
> I hope to spend some time on CEC tomorrow and I'll get back to you then.

Unfortunately I had too many other things going on to spend time on this.

Hopefully next week.

Regards,

	Hans


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

* Re: [PATCH v7 1/3] media: cec: expose HDMI connector to CEC dev mapping
  2019-05-24  9:21 ` [PATCH v7 1/3] media: cec: expose HDMI connector to CEC dev mapping Hans Verkuil
  2019-05-28  7:53   ` Dariusz Marcinkiewicz
@ 2019-06-19 11:05   ` Dariusz Marcinkiewicz
  2019-06-19 11:26     ` Hans Verkuil
  1 sibling, 1 reply; 9+ messages in thread
From: Dariusz Marcinkiewicz @ 2019-06-19 11:05 UTC (permalink / raw)
  To: Hans Verkuil; +Cc: linux-media, hans.verkuil, linux-kernel

Hi Hans.

I would like to come back to this thread.

On Fri, May 24, 2019 at 11:21 AM Hans Verkuil <hverkuil@xs4all.nl> wrote:
>
> Hi Dariusz,
>
> I did some more testing with the Khadas VIM2 and found another problem,
> something that will, unfortunately, require some redesign.
>
> See my comments below...
>
...
>
> Another issue here is that when the HDMI driver removes the notifier,
> then it should also zero the connector info. Remember that both the
> HDMI and the CEC drivers can be loaded and unloaded independently from
> one another.
>

I took a peek at the changes in
https://git.linuxtv.org/hverkuil/media_tree.git/log/?h=cec-conn. Do I
understand it correctly, that the above problem is addressed there by
unregistering an adapter in cec_notifier_conn_unregister (which will
result in /dev/cecX node going away)? I wonder to what degree this
solves the problem of HDMI and CEC drivers being loaded and unloaded
independently. It seems that in cases where HDMI driver is unloaded
and then loaded again, counterintuitively, the /dev/cecX might not
come back again, is this right, or am I missing something? Also, is it
guaranteed that adapter drivers won't try to access an adapter once it
gets removed by cec_notifier_conn_unregister?

Thank you.

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

* Re: [PATCH v7 1/3] media: cec: expose HDMI connector to CEC dev mapping
  2019-06-19 11:05   ` Dariusz Marcinkiewicz
@ 2019-06-19 11:26     ` Hans Verkuil
  0 siblings, 0 replies; 9+ messages in thread
From: Hans Verkuil @ 2019-06-19 11:26 UTC (permalink / raw)
  To: Dariusz Marcinkiewicz; +Cc: linux-media, linux-kernel

On 6/19/19 1:05 PM, Dariusz Marcinkiewicz wrote:
> Hi Hans.
> 
> I would like to come back to this thread.
> 
> On Fri, May 24, 2019 at 11:21 AM Hans Verkuil <hverkuil@xs4all.nl> wrote:
>>
>> Hi Dariusz,
>>
>> I did some more testing with the Khadas VIM2 and found another problem,
>> something that will, unfortunately, require some redesign.
>>
>> See my comments below...
>>
> ...
>>
>> Another issue here is that when the HDMI driver removes the notifier,
>> then it should also zero the connector info. Remember that both the
>> HDMI and the CEC drivers can be loaded and unloaded independently from
>> one another.
>>
> 
> I took a peek at the changes in
> https://git.linuxtv.org/hverkuil/media_tree.git/log/?h=cec-conn. Do I
> understand it correctly, that the above problem is addressed there by
> unregistering an adapter in cec_notifier_conn_unregister (which will
> result in /dev/cecX node going away)? I wonder to what degree this
> solves the problem of HDMI and CEC drivers being loaded and unloaded
> independently. It seems that in cases where HDMI driver is unloaded
> and then loaded again, counterintuitively, the /dev/cecX might not
> come back again, is this right, or am I missing something? Also, is it
> guaranteed that adapter drivers won't try to access an adapter once it
> gets removed by cec_notifier_conn_unregister?

It's old code, I'm going to do it differently (closer to your version,
actually).

I just pushed my latest code, I'm much happier with it.

I'll try to post a patch series this week.

Regards,

	Hans

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

end of thread, other threads:[~2019-06-19 11:27 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-05-21 10:52 [PATCH v7 1/3] media: cec: expose HDMI connector to CEC dev mapping Dariusz Marcinkiewicz
2019-05-21 10:52 ` [PATCH v7 2/3] drm/bridge: dw-hdmi: pass connector info to the CEC adapter Dariusz Marcinkiewicz
2019-05-21 10:52 ` [PATCH v7 3/3] drm/i2c: tda9950: pass HDMI connector info to " Dariusz Marcinkiewicz
2019-05-24  9:21 ` [PATCH v7 1/3] media: cec: expose HDMI connector to CEC dev mapping Hans Verkuil
2019-05-28  7:53   ` Dariusz Marcinkiewicz
2019-05-28  8:05     ` Hans Verkuil
2019-05-29 14:47       ` Hans Verkuil
2019-06-19 11:05   ` Dariusz Marcinkiewicz
2019-06-19 11:26     ` 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).