Skip to contentSkip to conversation

drm/dsi: DSI for devices with different control bus

RFC Superseded Archit Taneja 8 participants 84 messages Jun 30, 2015 – Mar 2, 2016

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

cover drm/dsi: DSI for devices with different control bus

We are currently restricted when it comes to supporting DSI on devices that have a non-DSI control bus. For example, DSI encoder chips are available in the market that are configured via i2c. Configuring their registers via DSI bus is either optional or not available at all.

These devices still need to pass DSI parameters (data lanes, mode flags etc) to the DSI host they are connected to. We don't have a way to do that at the moment.

The method presented in these patches is to provide an API to create a 'dummy' mipi_dsi_device. This device is populated with the desired DSI params, which are passed on to the host via mipi_dsi_attach().

This method will require the device driver to get a phandle to the DSI host since there is no parent-child relation between the two.

Is there a better way to do this? Please let me know!

Archit Taneja (2):
drm/dsi: Create dummy DSI devices
drm/dsi: Get DSI host by DT device node

 drivers/gpu/drm/drm_mipi_dsi.c | 108 ++++++++++++++++++++++++++++++++++++++++-
 include/drm/drm_mipi_dsi.h     |   4 ++
 2 files changed, 110 insertions(+), 2 deletions(-)
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation
#1 lore raw

RFC 1/2 drm/dsi: Create dummy DSI devices

We can have devices where the data bus is MIPI DSI, but the control bus is something else (i2c, spi etc). A typical example is i2c controlled encoder bridge chips.

Such devices too require passing DSI specific parameters (number of data lanes, DSI mode flags, color format etc) to their DSI host. For a device that isn't 'mipi_dsi_device', there is no way of passing such parameters.

Provide the option of creating a dummy DSI device. The main purpose of this would be to attach to a DSI host by calling mipi_dsi_attach, and pass DSI params.

Create mipi_dsi_new_dummy for creating a dummy dsi device. The driver calling this needs to be aware of the mipi_dsi_host it wants to attach to, and also the DSI virtual channel the DSI device intends to use.

---
 drivers/gpu/drm/drm_mipi_dsi.c | 78 ++++++++++++++++++++++++++++++++++++++++--
 include/drm/drm_mipi_dsi.h     |  2 ++
 2 files changed, 78 insertions(+), 2 deletions(-)
drivers/gpu/drm/drm_mipi_dsi.c +76 -2
index 2d5ca8ee..9bfe215 100644
@@ -47,7 +47,14 @@
 
 static int mipi_dsi_device_match(struct device *dev, struct device_driver *drv)
 {
-	return of_driver_match_device(dev, drv);
+	if (of_driver_match_device(dev, drv))
+		return 1;
+
+	if (!strcmp(drv->name, "mipi_dsi_dummy") &&
+			strstr(dev_name(dev), "dummy_dev"))
+		return 1;
+
+	return 0;
 }
 
 static const struct dev_pm_ops mipi_dsi_device_pm_ops = {
@@ -171,6 +178,67 @@ of_mipi_dsi_device_add(struct mipi_dsi_host *host, struct device_node *node)
 	return dsi;
 }
 
+static int dummy_probe(struct mipi_dsi_device *dsi)
+{
+	return 0;
+}
+
+static int dummy_remove(struct mipi_dsi_device *dsi)
+{
+	return 0;
+}
+
+static void dummy_shutdown(struct mipi_dsi_device *dsi)
+{
+}
+
+static struct mipi_dsi_driver dummy_dsi_driver = {
+	.probe = dummy_probe,
+	.remove = dummy_remove,
+	.shutdown = dummy_shutdown,
+	.driver.name = "mipi_dsi_dummy",
+};
+
+static int mipi_dsi_device_add_dummy(struct mipi_dsi_device *dsi)
+{
+	struct mipi_dsi_host *host = dsi->host;
+
+	dev_set_name(&dsi->dev, "%s.dummy_dev.%d", dev_name(host->dev),
+			dsi->channel);
+
+	return device_add(&dsi->dev);
+}
+
+struct mipi_dsi_device *mipi_dsi_new_dummy(struct mipi_dsi_host *host, u32 reg)
+{
+	struct mipi_dsi_device *dsi;
+	struct device *dev = host->dev;
+	int ret;
+
+	if (reg > 3) {
+		dev_err(dev, "invalid reg property %u\n", reg);
+		return ERR_PTR(-EINVAL);
+	}
+
+	dsi = mipi_dsi_device_alloc(host);
+	if (IS_ERR(dsi)) {
+		dev_err(dev, "failed to allocate dummy DSI device %ld\n",
+			PTR_ERR(dsi));
+		return dsi;
+	}
+
+	dsi->channel = reg;
+
+	ret = mipi_dsi_device_add_dummy(dsi);
+	if (ret) {
+		dev_err(dev, "failed to add dummy DSI device %d\n", ret);
+		kfree(dsi);
+		return ERR_PTR(ret);
+	}
+
+	return dsi;
+}
+
 int mipi_dsi_host_register(struct mipi_dsi_host *host)
 {
 	struct device_node *node;
@@ -924,7 +992,13 @@ EXPORT_SYMBOL(mipi_dsi_driver_unregister);
 
 static int __init mipi_dsi_bus_init(void)
 {
-	return bus_register(&mipi_dsi_bus_type);
+	int ret;
+
+	ret = bus_register(&mipi_dsi_bus_type);
+	if (ret < 0)
+		return ret;
+
+	return mipi_dsi_driver_register(&dummy_dsi_driver);
 }
 postcore_initcall(mipi_dsi_bus_init);
 
include/drm/drm_mipi_dsi.h +2 -0
index f1d8d0d..d06ba99 100644
@@ -174,6 +174,8 @@ ssize_t mipi_dsi_generic_write(struct mipi_dsi_device *dsi, const void *payload,
 ssize_t mipi_dsi_generic_read(struct mipi_dsi_device *dsi, const void *params,
 			      size_t num_params, void *data, size_t size);
 
+struct mipi_dsi_device *mipi_dsi_new_dummy(struct mipi_dsi_host *host, u32 reg);
+
 /**
  * enum mipi_dsi_dcs_tear_mode - Tearing Effect Output Line mode
  * @MIPI_DSI_DCS_TEAR_MODE_VBLANK: the TE output line consists of V-Blanking
Signature · 7 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel
#2 lore raw

Re: [RFC 1/2] drm/dsi: Create dummy DSI devices

Quoted 27 lines · Archit Taneja

We can have devices where the data bus is MIPI DSI, but the control bus is something else (i2c, spi etc). A typical example is i2c controlled encoder bridge chips.

Such devices too require passing DSI specific parameters (number of data lanes, DSI mode flags, color format etc) to their DSI host. For a device that isn't 'mipi_dsi_device', there is no way of passing such parameters.

Provide the option of creating a dummy DSI device. The main purpose of this would be to attach to a DSI host by calling mipi_dsi_attach, and pass DSI params.

Create mipi_dsi_new_dummy for creating a dummy dsi device. The driver calling this needs to be aware of the mipi_dsi_host it wants to attach to, and also the DSI virtual channel the DSI device intends to use.

---
 drivers/gpu/drm/drm_mipi_dsi.c | 78 ++++++++++++++++++++++++++++++++++++++++--
 include/drm/drm_mipi_dsi.h     |  2 ++
 2 files changed, 78 insertions(+), 2 deletions(-)
drivers/gpu/drm/drm_mipi_dsi.c +0 -0
index 2d5ca8ee..9bfe215 100644

drivers/gpu/drm/drm_mipi_dsi.c line 55

Quoted 10 lines
drivers/gpu/drm/drm_mipi_dsi.c +6 -1
@@ -47,7 +47,14 @@
 
 static int mipi_dsi_device_match(struct device *dev, struct device_driver *drv)
 {
-	return of_driver_match_device(dev, drv);
+	if (of_driver_match_device(dev, drv))
+		return 1;
+
+	if (!strcmp(drv->name, "mipi_dsi_dummy") &&
+			strstr(dev_name(dev), "dummy_dev"))
+		return 1;

Is this kind of fuzzy matching used in other dummy devs? It looks little bit scary. You
can at least replace

strstr(dev_name(dev), "dummy_dev"))

with

strstr(dev_name(dev), ".dummy_dev."))

Anyway, currently it should not break anything, am I right?

Quoted 12 lines
drivers/gpu/drm/drm_mipi_dsi.c +5 -0
+
+	return 0;
 }
 
 static const struct dev_pm_ops mipi_dsi_device_pm_ops = {
@@ -171,6 +178,67 @@ of_mipi_dsi_device_add(struct mipi_dsi_host *host, struct device_node *node)
 	return dsi;
 }
 
+static int dummy_probe(struct mipi_dsi_device *dsi)
+{
+	return 0;

drivers/gpu/drm/drm_mipi_dsi.c of_mipi_dsi_device_add(struct mipi_dsi_host *host, struct device_node *node) · line 193

Quoted 10 lines
drivers/gpu/drm/drm_mipi_dsi.c +10 -0
+}
+
+static int dummy_remove(struct mipi_dsi_device *dsi)
+{
+	return 0;
+}
+
+static void dummy_shutdown(struct mipi_dsi_device *dsi)
+{
+}

I suppose these callbacks are optional, so you can omit them.

Quoted 71 lines
drivers/gpu/drm/drm_mipi_dsi.c +55 -1
+
+static struct mipi_dsi_driver dummy_dsi_driver = {
+	.probe = dummy_probe,
+	.remove = dummy_remove,
+	.shutdown = dummy_shutdown,
+	.driver.name = "mipi_dsi_dummy",
+};
+
+static int mipi_dsi_device_add_dummy(struct mipi_dsi_device *dsi)
+{
+	struct mipi_dsi_host *host = dsi->host;
+
+	dev_set_name(&dsi->dev, "%s.dummy_dev.%d", dev_name(host->dev),
+			dsi->channel);
+
+	return device_add(&dsi->dev);
+}
+
+struct mipi_dsi_device *mipi_dsi_new_dummy(struct mipi_dsi_host *host, u32 reg)
+{
+	struct mipi_dsi_device *dsi;
+	struct device *dev = host->dev;
+	int ret;
+
+	if (reg > 3) {
+		dev_err(dev, "invalid reg property %u\n", reg);
+		return ERR_PTR(-EINVAL);
+	}
+
+	dsi = mipi_dsi_device_alloc(host);
+	if (IS_ERR(dsi)) {
+		dev_err(dev, "failed to allocate dummy DSI device %ld\n",
+			PTR_ERR(dsi));
+		return dsi;
+	}
+
+	dsi->channel = reg;
+
+	ret = mipi_dsi_device_add_dummy(dsi);
+	if (ret) {
+		dev_err(dev, "failed to add dummy DSI device %d\n", ret);
+		kfree(dsi);
+		return ERR_PTR(ret);
+	}
+
+	return dsi;
+}
+
 int mipi_dsi_host_register(struct mipi_dsi_host *host)
 {
 	struct device_node *node;
@@ -924,7 +992,13 @@ EXPORT_SYMBOL(mipi_dsi_driver_unregister);
 
 static int __init mipi_dsi_bus_init(void)
 {
-	return bus_register(&mipi_dsi_bus_type);
+	int ret;
+
+	ret = bus_register(&mipi_dsi_bus_type);
+	if (ret < 0)
+		return ret;
+
+	return mipi_dsi_driver_register(&dummy_dsi_driver);
 }
 postcore_initcall(mipi_dsi_bus_init);
 
include/drm/drm_mipi_dsi.h +0 -0
index f1d8d0d..d06ba99 100644

include/drm/drm_mipi_dsi.h ssize_t mipi_dsi_generic_write(struct mipi_dsi_device *dsi, const void *payload, · line 181

Quoted 8 lines
include/drm/drm_mipi_dsi.h +2 -0
@@ -174,6 +174,8 @@ ssize_t mipi_dsi_generic_write(struct mipi_dsi_device *dsi, const void *payload,
 ssize_t mipi_dsi_generic_read(struct mipi_dsi_device *dsi, const void *params,
 			      size_t num_params, void *data, size_t size);
 
+struct mipi_dsi_device *mipi_dsi_new_dummy(struct mipi_dsi_host *host, u32 reg);
+
 /**
  * enum mipi_dsi_dcs_tear_mode - Tearing Effect Output Line mode
  * @MIPI_DSI_DCS_TEAR_MODE_VBLANK: the TE output line consists of V-Blanking

_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel

#3 lore raw

Re: [RFC 1/2] drm/dsi: Create dummy DSI devices

Hi,

Quoted 43 lines · Andrzej Hajda
Quoted 27 lines · Archit Taneja

We can have devices where the data bus is MIPI DSI, but the control bus is something else (i2c, spi etc). A typical example is i2c controlled encoder bridge chips.

Such devices too require passing DSI specific parameters (number of data lanes, DSI mode flags, color format etc) to their DSI host. For a device that isn't 'mipi_dsi_device', there is no way of passing such parameters.

Provide the option of creating a dummy DSI device. The main purpose of this would be to attach to a DSI host by calling mipi_dsi_attach, and pass DSI params.

Create mipi_dsi_new_dummy for creating a dummy dsi device. The driver calling this needs to be aware of the mipi_dsi_host it wants to attach to, and also the DSI virtual channel the DSI device intends to use.

---
  drivers/gpu/drm/drm_mipi_dsi.c | 78 ++++++++++++++++++++++++++++++++++++++++--
  include/drm/drm_mipi_dsi.h     |  2 ++
  2 files changed, 78 insertions(+), 2 deletions(-)
drivers/gpu/drm/drm_mipi_dsi.c +0 -0
index 2d5ca8ee..9bfe215 100644

drivers/gpu/drm/drm_mipi_dsi.c line 55

Quoted 10 lines
drivers/gpu/drm/drm_mipi_dsi.c +6 -1
@@ -47,7 +47,14 @@
 
  static int mipi_dsi_device_match(struct device *dev, struct device_driver *drv)
  {
-	return of_driver_match_device(dev, drv);
+	if (of_driver_match_device(dev, drv))
+		return 1;
+
+	if (!strcmp(drv->name, "mipi_dsi_dummy") &&
+			strstr(dev_name(dev), "dummy_dev"))
+		return 1;

Is this kind of fuzzy matching used in other dummy devs? It looks little bit scary. You
can at least replace

Quoted 7 lines

strstr(dev_name(dev), "dummy_dev"))

with

strstr(dev_name(dev), ".dummy_dev."))

Anyway, currently it should not break anything, am I right?

I took i2c's dummy dev creation as reference. The i2c_driver struct has an id_table param, that allows the match function (i2c_device_match) to not have a special case to check for a dummy device.

We could a 'id_table' entry in mipi_dsi_driver, and a 'name' entry in mipi_dsi_device. But that would be a bit of an overkill just to support dummy devices.

I could make the check more thorough by adding a func which does something similar to 'i2c_verify_client', but I think we would still need the above string.

I will change "dummy_dev" to ".dummy_dev.". I grepped the kernel for devices named "dummy_dev", but didn't find anything as such, so it shouldn't really break anything.

Quoted 10 lines
Quoted 10 lines
drivers/gpu/drm/drm_mipi_dsi.c +2 -0
+
+	return 0;
  }
 
  static const struct dev_pm_ops mipi_dsi_device_pm_ops = {
@@ -171,6 +178,67 @@ of_mipi_dsi_device_add(struct mipi_dsi_host *host, struct device_node *node)
  	return dsi;
  }
 
Quoted 15 lines

drivers/gpu/drm/drm_mipi_dsi.c of_mipi_dsi_device_add(struct mipi_dsi_host *host, struct device_node *node) · line 193

Quoted 13 lines
drivers/gpu/drm/drm_mipi_dsi.c +13 -0
+static int dummy_probe(struct mipi_dsi_device *dsi)
+{
+	return 0;
+}
+
+static int dummy_remove(struct mipi_dsi_device *dsi)
+{
+	return 0;
+}
+
+static void dummy_shutdown(struct mipi_dsi_device *dsi)
+{
+}

I suppose these callbacks are optional, so you can omit them.

Right. I will remove these.

Thanks for the review.

Archit

Signature · 2 lines
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
#4 lore raw

RFC 2/2 drm/dsi: Get DSI host by DT device node

In reply to Archit Taneja

mipi_dsi_devices are inherently aware of their host because they share a parent-child hierarchy in the device tree.

Non-dsi drivers that create a dummy dsi device don't have this data. In order to get this information, they require to a phandle to the dsi host in the device tree.

Maintain a list of all the hosts DSI that are currently registered.

This list will be used to find the mipi_dsi_host corresponding to the device_node passed in of_find_mipi_dsi_host_by_node.

---
 drivers/gpu/drm/drm_mipi_dsi.c | 30 ++++++++++++++++++++++++++++++
 include/drm/drm_mipi_dsi.h     |  2 ++
 2 files changed, 32 insertions(+)
drivers/gpu/drm/drm_mipi_dsi.c +30 -0
index 9bfe215..81ddb73 100644
@@ -239,6 +239,28 @@ struct mipi_dsi_device *mipi_dsi_new_dummy(struct mipi_dsi_host *host, u32 reg)
 	return dsi;
 }
 
+static DEFINE_MUTEX(host_lock);
+static LIST_HEAD(host_list);
+
+struct mipi_dsi_host *of_find_mipi_dsi_host_by_node(struct device_node *node)
+{
+	struct mipi_dsi_host *host;
+
+	mutex_lock(&host_lock);
+
+	list_for_each_entry(host, &host_list, list) {
+		if (host->dev->of_node == node) {
+			mutex_unlock(&host_lock);
+			return host;
+		}
+	}
+
+	mutex_unlock(&host_lock);
+
+	return NULL;
+}
+EXPORT_SYMBOL(of_find_mipi_dsi_host_by_node);
+
 int mipi_dsi_host_register(struct mipi_dsi_host *host)
 {
 	struct device_node *node;
@@ -250,6 +272,10 @@ int mipi_dsi_host_register(struct mipi_dsi_host *host)
 		of_mipi_dsi_device_add(host, node);
 	}
 
+	mutex_lock(&host_lock);
+	list_add_tail(&host->list, &host_list);
+	mutex_unlock(&host_lock);
+
 	return 0;
 }
 EXPORT_SYMBOL(mipi_dsi_host_register);
@@ -266,6 +292,10 @@ static int mipi_dsi_remove_device_fn(struct device *dev, void *priv)
 void mipi_dsi_host_unregister(struct mipi_dsi_host *host)
 {
 	device_for_each_child(host->dev, NULL, mipi_dsi_remove_device_fn);
+
+	mutex_lock(&host_lock);
+	list_del_init(&host->list);
+	mutex_unlock(&host_lock);
 }
 EXPORT_SYMBOL(mipi_dsi_host_unregister);
 
include/drm/drm_mipi_dsi.h +2 -0
index d06ba99..1684a0e 100644
@@ -100,10 +100,12 @@ struct mipi_dsi_host_ops {
 struct mipi_dsi_host {
 	struct device *dev;
 	const struct mipi_dsi_host_ops *ops;
+	struct list_head list;
 };
 
 int mipi_dsi_host_register(struct mipi_dsi_host *host);
 void mipi_dsi_host_unregister(struct mipi_dsi_host *host);
+struct mipi_dsi_host *of_find_mipi_dsi_host_by_node(struct device_node *node);
 
 /* DSI mode flags */
 
Signature · 7 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel
Reviewed-by on v1 2/2
#5 lore raw

Re: [RFC 2/2] drm/dsi: Get DSI host by DT device node

Quoted 11 lines · Archit Taneja

mipi_dsi_devices are inherently aware of their host because they share a parent-child hierarchy in the device tree.

Non-dsi drivers that create a dummy dsi device don't have this data. In order to get this information, they require to a phandle to the dsi host in the device tree.

Maintain a list of all the hosts DSI that are currently registered.

This list will be used to find the mipi_dsi_host corresponding to the device_node passed in of_find_mipi_dsi_host_by_node.

The lock protects only the list, there is no guarantee that mipi_dsi_host returned by of_find_mipi_dsi_host_by_node is still valid, or will be valid long enough.

But this issue affects many kernel frameworks so I am not sure if it should block this
particular patch.

Regards
Andrzej

Quoted 69 lines
---
 drivers/gpu/drm/drm_mipi_dsi.c | 30 ++++++++++++++++++++++++++++++
 include/drm/drm_mipi_dsi.h     |  2 ++
 2 files changed, 32 insertions(+)
drivers/gpu/drm/drm_mipi_dsi.c +30 -0
index 9bfe215..81ddb73 100644
@@ -239,6 +239,28 @@ struct mipi_dsi_device *mipi_dsi_new_dummy(struct mipi_dsi_host *host, u32 reg)
 	return dsi;
 }
 
+static DEFINE_MUTEX(host_lock);
+static LIST_HEAD(host_list);
+
+struct mipi_dsi_host *of_find_mipi_dsi_host_by_node(struct device_node *node)
+{
+	struct mipi_dsi_host *host;
+
+	mutex_lock(&host_lock);
+
+	list_for_each_entry(host, &host_list, list) {
+		if (host->dev->of_node == node) {
+			mutex_unlock(&host_lock);
+			return host;
+		}
+	}
+
+	mutex_unlock(&host_lock);
+
+	return NULL;
+}
+EXPORT_SYMBOL(of_find_mipi_dsi_host_by_node);
+
 int mipi_dsi_host_register(struct mipi_dsi_host *host)
 {
 	struct device_node *node;
@@ -250,6 +272,10 @@ int mipi_dsi_host_register(struct mipi_dsi_host *host)
 		of_mipi_dsi_device_add(host, node);
 	}
 
+	mutex_lock(&host_lock);
+	list_add_tail(&host->list, &host_list);
+	mutex_unlock(&host_lock);
+
 	return 0;
 }
 EXPORT_SYMBOL(mipi_dsi_host_register);
@@ -266,6 +292,10 @@ static int mipi_dsi_remove_device_fn(struct device *dev, void *priv)
 void mipi_dsi_host_unregister(struct mipi_dsi_host *host)
 {
 	device_for_each_child(host->dev, NULL, mipi_dsi_remove_device_fn);
+
+	mutex_lock(&host_lock);
+	list_del_init(&host->list);
+	mutex_unlock(&host_lock);
 }
 EXPORT_SYMBOL(mipi_dsi_host_unregister);
 
include/drm/drm_mipi_dsi.h +0 -0
index d06ba99..1684a0e 100644
@@ -100,10 +100,12 @@ struct mipi_dsi_host_ops {
 struct mipi_dsi_host {
 	struct device *dev;

include/drm/drm_mipi_dsi.h struct mipi_dsi_host_ops { · line 111

Quoted 10 lines
include/drm/drm_mipi_dsi.h +2 -0
 	const struct mipi_dsi_host_ops *ops;
+	struct list_head list;
 };
 
 int mipi_dsi_host_register(struct mipi_dsi_host *host);
 void mipi_dsi_host_unregister(struct mipi_dsi_host *host);
+struct mipi_dsi_host *of_find_mipi_dsi_host_by_node(struct device_node *node);
 
 /* DSI mode flags */
 

_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel

#6 lore raw
In reply to Archit Taneja

Hi,

Quoted 9 lines · Archit Taneja

We are currently restricted when it comes to supporting DSI on devices that have a non-DSI control bus. For example, DSI encoder chips are available in the market that are configured via i2c. Configuring their registers via DSI bus is either optional or not available at all.

These devices still need to pass DSI parameters (data lanes, mode flags etc) to the DSI host they are connected to. We don't have a way to do that at the moment.

Quoted 8 lines

The method presented in these patches is to provide an API to create a 'dummy' mipi_dsi_device. This device is populated with the desired DSI params, which are passed on to the host via mipi_dsi_attach().

This method will require the device driver to get a phandle to the DSI host since there is no parent-child relation between the two.

Is there a better way to do this? Please let me know!

Any comments on this?

Archit

Quoted 9 lines

Archit Taneja (2):
drm/dsi: Create dummy DSI devices
drm/dsi: Get DSI host by DT device node

  drivers/gpu/drm/drm_mipi_dsi.c | 108 ++++++++++++++++++++++++++++++++++++++++-
  include/drm/drm_mipi_dsi.h     |   4 ++
  2 files changed, 110 insertions(+), 2 deletions(-)
Signature · 2 lines
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
#7 lore raw
Quoted 16 lines · Archit Taneja

Hi,

Quoted 13 lines · Archit Taneja

We are currently restricted when it comes to supporting DSI on devices that have a non-DSI control bus. For example, DSI encoder chips are available in the market that are configured via i2c. Configuring their registers via DSI bus is either optional or not available at all.

These devices still need to pass DSI parameters (data lanes, mode flags etc) to the DSI host they are connected to. We don't have a way to do that at the moment.

The method presented in these patches is to provide an API to create a 'dummy' mipi_dsi_device. This device is populated with the desired DSI params, which are passed on to the host via mipi_dsi_attach().

Quoted 6 lines
Quoted 4 lines

This method will require the device driver to get a phandle to the DSI host since there is no parent-child relation between the two.

Is there a better way to do this? Please let me know!

Any comments on this?

Perhaps a better way would be to invert this relationship. According to your proposal we'd have to have DT like this:

	i2c@... {
		...

		dsi-device@... {
			...
			dsi-bus = <&dsi>;
			...
		};

		...
	};

	dsi@... {
		...
	};

Inversing the relationship would become something like this:

	i2c@... {
		...
	};

	dsi@... {
		...

		peripheral@... {
			...
			i2c-bus = <&i2c>;
			...
		};

		...
	};

Both of those aren't fundamentally different, and they both have the disavantage of lacking ways to transport configuration data that the other bus needs to instantiate the dummy device (such as the reg property for example, denoting the I2C slave address or the DSI VC).

So how about we create two devices in the device tree and fuse them at the driver level:

	i2c@... {
		...

		i2cdsi: dsi-device@... {
			...
		};

		...
	};

	dsi@... {
		...

		peripheral@... {
			...
			control = <&i2cdsi>;
			...
		};

		...
	};

This way we'll get both an I2C device and a DSI device that we can fully describe using the standard device tree bindings. At driver time we can get the I2C device from the phandle in the control property of the DSI device and use it to execute I2C transactions.

Thierry

#8 lore raw

Hi Thierry, Archit,

Am Mittwoch, den 19.08.2015, 15:13 +0200 schrieb Thierry Reding:

Quoted 91 lines · Archit Taneja
Quoted 16 lines

Hi,

Quoted 13 lines · Archit Taneja

We are currently restricted when it comes to supporting DSI on devices that have a non-DSI control bus. For example, DSI encoder chips are available in the market that are configured via i2c. Configuring their registers via DSI bus is either optional or not available at all.

These devices still need to pass DSI parameters (data lanes, mode flags etc) to the DSI host they are connected to. We don't have a way to do that at the moment.

The method presented in these patches is to provide an API to create a 'dummy' mipi_dsi_device. This device is populated with the desired DSI params, which are passed on to the host via mipi_dsi_attach().

Quoted 6 lines
Quoted 4 lines

This method will require the device driver to get a phandle to the DSI host since there is no parent-child relation between the two.

Is there a better way to do this? Please let me know!

Any comments on this?

Perhaps a better way would be to invert this relationship. According to your proposal we'd have to have DT like this:

	i2c@... {
		...

		dsi-device@... {
			...
			dsi-bus = <&dsi>;
			...
		};

		...
	};

	dsi@... {
		...
	};

Inversing the relationship would become something like this:

	i2c@... {
		...
	};

	dsi@... {
		...

		peripheral@... {
			...
			i2c-bus = <&i2c>;
			...
		};

		...
	};

Both of those aren't fundamentally different, and they both have the disavantage of lacking ways to transport configuration data that the other bus needs to instantiate the dummy device (such as the reg property for example, denoting the I2C slave address or the DSI VC).

So how about we create two devices in the device tree and fuse them at the driver level:

	i2c@... {
		...

		i2cdsi: dsi-device@... {
			...
		};

		...
	};

	dsi@... {
		...

		peripheral@... {
			...
			control = <&i2cdsi>;
			...
		};

		...
	};
Quoted 5 lines

This way we'll get both an I2C device and a DSI device that we can fully describe using the standard device tree bindings. At driver time we can get the I2C device from the phandle in the control property of the DSI device and use it to execute I2C transactions.

I don't really like to see that you are inventing yet-another-way to handle devices connected to multiple buses.

Devicetree is structured along the control buses, even if the devices are connected to multiple buses, in the DT they are always children of the bus that is used to control their registers from the CPUs perspective. So a DSI encoder that is controlled through i2c is clearly a child of the i2c master controller and only of that one.

If you need to model connections between devices that are not reflected through the control bus hierarchy you should really consider using the standardized of-graph bindings. (Documentation/devicetree/bindings/graph.txt)

Multiple device drivers in both the media and DRM universe have shown that they are a working way to represent those data bus connections between devices.
I know this might make things a bit more complicated for Tegra DRM, where you have a nice parent<->child relationship between the components even on the control path so far, but we should really move into the direction of more drivers using the standardized bindings for this stuff, instead of doing another round of NIH.

Regards,
Lucas

Signature · 2 lines
Pengutronix e.K.             | Lucas Stach                 |
Industrial Linux Solutions   | http://www.pengutronix.de/  |
#9 lore raw
Quoted 99 lines · Lucas Stach

Hi Thierry, Archit,

Am Mittwoch, den 19.08.2015, 15:13 +0200 schrieb Thierry Reding:

Quoted 91 lines · Archit Taneja
Quoted 16 lines

Hi,

Quoted 13 lines · Archit Taneja

We are currently restricted when it comes to supporting DSI on devices that have a non-DSI control bus. For example, DSI encoder chips are available in the market that are configured via i2c. Configuring their registers via DSI bus is either optional or not available at all.

These devices still need to pass DSI parameters (data lanes, mode flags etc) to the DSI host they are connected to. We don't have a way to do that at the moment.

The method presented in these patches is to provide an API to create a 'dummy' mipi_dsi_device. This device is populated with the desired DSI params, which are passed on to the host via mipi_dsi_attach().

Quoted 6 lines
Quoted 4 lines

This method will require the device driver to get a phandle to the DSI host since there is no parent-child relation between the two.

Is there a better way to do this? Please let me know!

Any comments on this?

Perhaps a better way would be to invert this relationship. According to your proposal we'd have to have DT like this:

	i2c@... {
		...

		dsi-device@... {
			...
			dsi-bus = <&dsi>;
			...
		};

		...
	};

	dsi@... {
		...
	};

Inversing the relationship would become something like this:

	i2c@... {
		...
	};

	dsi@... {
		...

		peripheral@... {
			...
			i2c-bus = <&i2c>;
			...
		};

		...
	};

Both of those aren't fundamentally different, and they both have the disavantage of lacking ways to transport configuration data that the other bus needs to instantiate the dummy device (such as the reg property for example, denoting the I2C slave address or the DSI VC).

So how about we create two devices in the device tree and fuse them at the driver level:

	i2c@... {
		...

		i2cdsi: dsi-device@... {
			...
		};

		...
	};

	dsi@... {
		...

		peripheral@... {
			...
			control = <&i2cdsi>;
			...
		};

		...
	};
Quoted 5 lines

This way we'll get both an I2C device and a DSI device that we can fully describe using the standard device tree bindings. At driver time we can get the I2C device from the phandle in the control property of the DSI device and use it to execute I2C transactions.

Quoted 8 lines

I don't really like to see that you are inventing yet-another-way to handle devices connected to multiple buses.

Devicetree is structured along the control buses, even if the devices are connected to multiple buses, in the DT they are always children of the bus that is used to control their registers from the CPUs perspective. So a DSI encoder that is controlled through i2c is clearly a child of the i2c master controller and only of that one.

I think that's a flawed interpretation of what's going on here. The device in fact has two interfaces: one is I2C, the other is DSI. In my opinion that's reason enough to represent it as two logical devices.

Quoted 4 lines

If you need to model connections between devices that are not reflected through the control bus hierarchy you should really consider using the standardized of-graph bindings. (Documentation/devicetree/bindings/graph.txt)

The problem is that the original proposal would instantiate a dummy device, so it wouldn't be represented in DT at all. So unless you do add two logical devices to DT (one for each bus interface), you don't have anything to glue together with an OF graph.

Quoted 8 lines

Multiple device drivers in both the media and DRM universe have shown that they are a working way to represent those data bus connections between devices.
I know this might make things a bit more complicated for Tegra DRM, where you have a nice parent<->child relationship between the components even on the control path so far, but we should really move into the direction of more drivers using the standardized bindings for this stuff, instead of doing another round of NIH.

Why are you bringing up Tegra DRM? I don't see how it's relevant in any way to this discussion.

Thierry

_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel

#10 lore raw

Am Mittwoch, den 19.08.2015, 16:34 +0200 schrieb Thierry Reding:

Quoted 3 lines · Lucas Stach
Quoted 2 lines

Hi Thierry, Archit,

[...]

Quoted 81 lines
Quoted 72 lines
Quoted 67 lines

Perhaps a better way would be to invert this relationship. According to your proposal we'd have to have DT like this:

	i2c@... {
		...

		dsi-device@... {
			...
			dsi-bus = <&dsi>;
			...
		};

		...
	};

	dsi@... {
		...
	};

Inversing the relationship would become something like this:

	i2c@... {
		...
	};

	dsi@... {
		...

		peripheral@... {
			...
			i2c-bus = <&i2c>;
			...
		};

		...
	};

Both of those aren't fundamentally different, and they both have the disavantage of lacking ways to transport configuration data that the other bus needs to instantiate the dummy device (such as the reg property for example, denoting the I2C slave address or the DSI VC).

So how about we create two devices in the device tree and fuse them at the driver level:

	i2c@... {
		...

		i2cdsi: dsi-device@... {
			...
		};

		...
	};

	dsi@... {
		...

		peripheral@... {
			...
			control = <&i2cdsi>;
			...
		};

		...
	};
Quoted 5 lines

This way we'll get both an I2C device and a DSI device that we can fully describe using the standard device tree bindings. At driver time we can get the I2C device from the phandle in the control property of the DSI device and use it to execute I2C transactions.

Quoted 8 lines

I don't really like to see that you are inventing yet-another-way to handle devices connected to multiple buses.

Devicetree is structured along the control buses, even if the devices are connected to multiple buses, in the DT they are always children of the bus that is used to control their registers from the CPUs perspective. So a DSI encoder that is controlled through i2c is clearly a child of the i2c master controller and only of that one.

Quoted 4 lines

I think that's a flawed interpretation of what's going on here. The device in fact has two interfaces: one is I2C, the other is DSI. In my opinion that's reason enough to represent it as two logical devices.

Does it really have 2 control interfaces that are used at the same time? Or is the DSI connection a passive data bus if the register control happens through i2c?

Quoted 10 lines
Quoted 4 lines

If you need to model connections between devices that are not reflected through the control bus hierarchy you should really consider using the standardized of-graph bindings. (Documentation/devicetree/bindings/graph.txt)

The problem is that the original proposal would instantiate a dummy device, so it wouldn't be represented in DT at all. So unless you do add two logical devices to DT (one for each bus interface), you don't have anything to glue together with an OF graph.

I see that the having dummy device is the least desirable solution. But if there is only one control bus to the device I think it should be one device sitting beneath the control bus.

You can then use of-graph to model the data path between the DSI encoder and device.

Quoted 9 lines
Quoted 8 lines

Multiple device drivers in both the media and DRM universe have shown that they are a working way to represent those data bus connections between devices.
I know this might make things a bit more complicated for Tegra DRM, where you have a nice parent<->child relationship between the components even on the control path so far, but we should really move into the direction of more drivers using the standardized bindings for this stuff, instead of doing another round of NIH.

Quoted 3 lines

Why are you bringing up Tegra DRM? I don't see how it's relevant in any way to this discussion.

Just disregard this comment then. Lets concentrate on the points above.

Regards,
Lucas

Signature · 7 lines
Pengutronix e.K.             | Lucas Stach                 |
Industrial Linux Solutions   | http://www.pengutronix.de/  |

_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel
#11 lore raw
Quoted 86 lines · Lucas Stach

Am Mittwoch, den 19.08.2015, 16:34 +0200 schrieb Thierry Reding:

Quoted 3 lines · Lucas Stach
Quoted 2 lines

Hi Thierry, Archit,

[...]

Quoted 81 lines
Quoted 80 lines
Quoted 67 lines

Perhaps a better way would be to invert this relationship. According to your proposal we'd have to have DT like this:

	i2c@... {
		...

		dsi-device@... {
			...
			dsi-bus = <&dsi>;
			...
		};

		...
	};

	dsi@... {
		...
	};

Inversing the relationship would become something like this:

	i2c@... {
		...
	};

	dsi@... {
		...

		peripheral@... {
			...
			i2c-bus = <&i2c>;
			...
		};

		...
	};

Both of those aren't fundamentally different, and they both have the disavantage of lacking ways to transport configuration data that the other bus needs to instantiate the dummy device (such as the reg property for example, denoting the I2C slave address or the DSI VC).

So how about we create two devices in the device tree and fuse them at the driver level:

	i2c@... {
		...

		i2cdsi: dsi-device@... {
			...
		};

		...
	};

	dsi@... {
		...

		peripheral@... {
			...
			control = <&i2cdsi>;
			...
		};

		...
	};
Quoted 5 lines

This way we'll get both an I2C device and a DSI device that we can fully describe using the standard device tree bindings. At driver time we can get the I2C device from the phandle in the control property of the DSI device and use it to execute I2C transactions.

I don't really like to see that you are inventing yet-another-way to handle devices connected to multiple buses.

Devicetree is structured along the control buses, even if the devices are connected to multiple buses, in the DT they are always children of the bus that is used to control their registers from the CPUs perspective. So a DSI encoder that is controlled through i2c is clearly a child of the i2c master controller and only of that one.

Quoted 7 lines
Quoted 4 lines

I think that's a flawed interpretation of what's going on here. The device in fact has two interfaces: one is I2C, the other is DSI. In my opinion that's reason enough to represent it as two logical devices.

Does it really have 2 control interfaces that are used at the same time? Or is the DSI connection a passive data bus if the register control happens through i2c?

The interfaces may not be used at the same time, and the DSI interface may even be crippled, but the device is still addressable from the DSI host controller, if for nothing else than for routing the video stream.

Quoted 10 lines
Quoted 10 lines
Quoted 4 lines

If you need to model connections between devices that are not reflected through the control bus hierarchy you should really consider using the standardized of-graph bindings. (Documentation/devicetree/bindings/graph.txt)

The problem is that the original proposal would instantiate a dummy device, so it wouldn't be represented in DT at all. So unless you do add two logical devices to DT (one for each bus interface), you don't have anything to glue together with an OF graph.

Quoted 6 lines

I see that the having dummy device is the least desirable solution. But if there is only one control bus to the device I think it should be one device sitting beneath the control bus.

You can then use of-graph to model the data path between the DSI encoder and device.

But you will be needing a device below the DSI host controller to represent that endpoint of the connection. The DSI host controller itself is in no way connected to the I2C adapter. You would have to add some sort of quirk to the DSI controller binding to allow it to hook up with a control endpoint. And then you'll need more quirks to describe what kind of DSI device this is.

On the other hand if you properly instantiate the DSI device you can easily write a driver for it, and the driver will set up the correct properties as implied by the compatible string. Once you have that you can easily hook it up to the I2C control interface in whatever way you like, be that an OF graph or just a simple unidirectional link by phandle.

Thierry

#12 lore raw
Quoted 6 lines · Thierry Reding
Quoted 5 lines · Lucas Stach

Am Mittwoch, den 19.08.2015, 16:34 +0200 schrieb Thierry Reding:

Quoted 4 lines

I think that's a flawed interpretation of what's going on here. The device in fact has two interfaces: one is I2C, the other is DSI. In my opinion that's reason enough to represent it as two logical devices.

Quoted 7 lines
Quoted 3 lines

Does it really have 2 control interfaces that are used at the same time? Or is the DSI connection a passive data bus if the register control happens through i2c?

The interfaces may not be used at the same time, and the DSI interface may even be crippled, but the device is still addressable from the DSI host controller, if for nothing else than for routing the video stream.

As a drive-by comment, the Toshiba TC358764XBG/65XBG chip can be configured via both DSI and I2C. The I2C interface requires DSI clock on the DSI interface to operate. You may not use the interfaces simultaneously, but provided you protect against races in register access, both interfaces can be operational at the same time.

Sorry I couldn't find a public spec of the chip to share.

HTH,
Jani.

Signature · 1 line
Jani Nikula, Intel Open Source Technology Center
#13 lore raw
In reply to Thierry Reding

Hi Thierry, Lucas,

Quoted 113 lines · Thierry Reding
Quoted 86 lines · Lucas Stach

Am Mittwoch, den 19.08.2015, 16:34 +0200 schrieb Thierry Reding:

Quoted 3 lines · Lucas Stach
Quoted 2 lines

Hi Thierry, Archit,

[...]

Quoted 81 lines
Quoted 80 lines
Quoted 67 lines

Perhaps a better way would be to invert this relationship. According to your proposal we'd have to have DT like this:

	i2c@... {
		...

		dsi-device@... {
			...
			dsi-bus = <&dsi>;
			...
		};

		...
	};

	dsi@... {
		...
	};

Inversing the relationship would become something like this:

	i2c@... {
		...
	};

	dsi@... {
		...

		peripheral@... {
			...
			i2c-bus = <&i2c>;
			...
		};

		...
	};

Both of those aren't fundamentally different, and they both have the disavantage of lacking ways to transport configuration data that the other bus needs to instantiate the dummy device (such as the reg property for example, denoting the I2C slave address or the DSI VC).

So how about we create two devices in the device tree and fuse them at the driver level:

	i2c@... {
		...

		i2cdsi: dsi-device@... {
			...
		};

		...
	};

	dsi@... {
		...

		peripheral@... {
			...
			control = <&i2cdsi>;
			...
		};

		...
	};
Quoted 5 lines

This way we'll get both an I2C device and a DSI device that we can fully describe using the standard device tree bindings. At driver time we can get the I2C device from the phandle in the control property of the DSI device and use it to execute I2C transactions.

I don't really like to see that you are inventing yet-another-way to handle devices connected to multiple buses.

Devicetree is structured along the control buses, even if the devices are connected to multiple buses, in the DT they are always children of the bus that is used to control their registers from the CPUs perspective. So a DSI encoder that is controlled through i2c is clearly a child of the i2c master controller and only of that one.

Quoted 7 lines
Quoted 4 lines

I think that's a flawed interpretation of what's going on here. The device in fact has two interfaces: one is I2C, the other is DSI. In my opinion that's reason enough to represent it as two logical devices.

Does it really have 2 control interfaces that are used at the same time? Or is the DSI connection a passive data bus if the register control happens through i2c?

The interfaces may not be used at the same time, and the DSI interface may even be crippled, but the device is still addressable from the DSI host controller, if for nothing else than for routing the video stream.

Quoted 14 lines
Quoted 10 lines
Quoted 4 lines

If you need to model connections between devices that are not reflected through the control bus hierarchy you should really consider using the standardized of-graph bindings. (Documentation/devicetree/bindings/graph.txt)

The problem is that the original proposal would instantiate a dummy device, so it wouldn't be represented in DT at all. So unless you do add two logical devices to DT (one for each bus interface), you don't have anything to glue together with an OF graph.

I see that the having dummy device is the least desirable solution. But if there is only one control bus to the device I think it should be one device sitting beneath the control bus.

Quoted 7 lines
Quoted 2 lines

You can then use of-graph to model the data path between the DSI encoder and device.

But you will be needing a device below the DSI host controller to represent that endpoint of the connection. The DSI host controller itself is in no way connected to the I2C adapter. You would have to add some sort of quirk to the DSI controller binding to allow it to

Thanks for the review.

I implemented this to support ADV7533 DSI to HDMI encoder chip, which has a DSI video bus and an i2c control bus.

There weren't any quirks as such in the device tree when I tried to implement this. The DT seems to manage fine without a node corresponding to a mipi_dsi_device:

i2c_adap@.. {
	adv7533@.. {

		port {
			adv_in: endpoint {
				remote-endpoint = <&dsi_out>;
			};
		};
	};
};
dsi_host@.. {
	...
	...

	port {
		dsi_out: endpoint {
			remote-endpoint = <&adv_in>;
		}
	};
};

It's the i2c driver's job to parse the graph and retrieve the phandle to the dsi host. Using this, it can proceed with registering itself to this host using the new dsi funcs. This patch does the same for the adv7533 i2c driver:

http://www.spinics.net/lists/dri-devel/msg86840.html

Quoted 2 lines

hook up with a control endpoint. And then you'll need more quirks to describe what kind of DSI device this is.

Could you explain what you meant by this? I.e. describing the kind of DSI device?

The dsi device created isn't really a dummy device as such. It's dummy in the sense that there isn't a real dsi driver associated with it. The dsi device is still used to attach to a mipi dsi host, the way normal dsi devices do.

Quoted 8 lines

On the other hand if you properly instantiate the DSI device you can easily write a driver for it, and the driver will set up the correct properties as implied by the compatible string. Once you have that you can easily hook it up to the I2C control interface in whatever way you like, be that an OF graph or just a simple unidirectional link by phandle.

With the fused approach you suggested, we would have 2 drivers: one i2c and the other dsi. The i2c client driver would be more or less minimal, preparing an i2c_client device for the dsi driver to use. Is my understanding correct?

We can do without dummy dsi devices with this method. But, representing a device with 2 DT nodes seems a bit off. We'd also need to compatible strings for the same device, one for the i2c part, and the other for the dsi part.

From an adv75xx driver perspective, it should also support the ADV7511 chip, which is a RGB/DPI to HDMI encoder. For adv7511, we don't need a DSI DT node. It would be a bit inconsistent to have the bindings require both DSI and I2C nodes for one chip, and only I2C node for the other, with both chips being supported by the same driver.

Thanks,
Archit

Signature · 2 lines
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
#14 lore raw
Quoted 161 lines · Archit Taneja

Hi Thierry, Lucas,

Quoted 113 lines · Thierry Reding
Quoted 86 lines · Lucas Stach

Am Mittwoch, den 19.08.2015, 16:34 +0200 schrieb Thierry Reding:

Quoted 3 lines · Lucas Stach
Quoted 2 lines

Hi Thierry, Archit,

[...]

Quoted 81 lines
Quoted 80 lines
Quoted 67 lines

Perhaps a better way would be to invert this relationship. According to your proposal we'd have to have DT like this:

	i2c@... {
		...

		dsi-device@... {
			...
			dsi-bus = <&dsi>;
			...
		};

		...
	};

	dsi@... {
		...
	};

Inversing the relationship would become something like this:

	i2c@... {
		...
	};

	dsi@... {
		...

		peripheral@... {
			...
			i2c-bus = <&i2c>;
			...
		};

		...
	};

Both of those aren't fundamentally different, and they both have the disavantage of lacking ways to transport configuration data that the other bus needs to instantiate the dummy device (such as the reg property for example, denoting the I2C slave address or the DSI VC).

So how about we create two devices in the device tree and fuse them at the driver level:

	i2c@... {
		...

		i2cdsi: dsi-device@... {
			...
		};

		...
	};

	dsi@... {
		...

		peripheral@... {
			...
			control = <&i2cdsi>;
			...
		};

		...
	};
Quoted 5 lines

This way we'll get both an I2C device and a DSI device that we can fully describe using the standard device tree bindings. At driver time we can get the I2C device from the phandle in the control property of the DSI device and use it to execute I2C transactions.

I don't really like to see that you are inventing yet-another-way to handle devices connected to multiple buses.

Devicetree is structured along the control buses, even if the devices are connected to multiple buses, in the DT they are always children of the bus that is used to control their registers from the CPUs perspective. So a DSI encoder that is controlled through i2c is clearly a child of the i2c master controller and only of that one.

Quoted 7 lines
Quoted 4 lines

I think that's a flawed interpretation of what's going on here. The device in fact has two interfaces: one is I2C, the other is DSI. In my opinion that's reason enough to represent it as two logical devices.

Does it really have 2 control interfaces that are used at the same time? Or is the DSI connection a passive data bus if the register control happens through i2c?

The interfaces may not be used at the same time, and the DSI interface may even be crippled, but the device is still addressable from the DSI host controller, if for nothing else than for routing the video stream.

Quoted 14 lines
Quoted 10 lines
Quoted 4 lines

If you need to model connections between devices that are not reflected through the control bus hierarchy you should really consider using the standardized of-graph bindings. (Documentation/devicetree/bindings/graph.txt)

The problem is that the original proposal would instantiate a dummy device, so it wouldn't be represented in DT at all. So unless you do add two logical devices to DT (one for each bus interface), you don't have anything to glue together with an OF graph.

I see that the having dummy device is the least desirable solution. But if there is only one control bus to the device I think it should be one device sitting beneath the control bus.

Quoted 7 lines
Quoted 2 lines

You can then use of-graph to model the data path between the DSI encoder and device.

But you will be needing a device below the DSI host controller to represent that endpoint of the connection. The DSI host controller itself is in no way connected to the I2C adapter. You would have to add some sort of quirk to the DSI controller binding to allow it to

Thanks for the review.

I implemented this to support ADV7533 DSI to HDMI encoder chip, which has a DSI video bus and an i2c control bus.

There weren't any quirks as such in the device tree when I tried to implement this. The DT seems to manage fine without a node corresponding to a mipi_dsi_device:

i2c_adap@.. {
	adv7533@.. {

		port {
			adv_in: endpoint {
				remote-endpoint = <&dsi_out>;
			};
		};
	};
};
dsi_host@.. {
	...
	...

	port {
		dsi_out: endpoint {
			remote-endpoint = <&adv_in>;
		}
	};
};

It's the i2c driver's job to parse the graph and retrieve the phandle to the dsi host. Using this, it can proceed with registering itself to this host using the new dsi funcs. This patch does the same for the adv7533 i2c driver:

Quoted 7 lines

http://www.spinics.net/lists/dri-devel/msg86840.html

Quoted 2 lines

hook up with a control endpoint. And then you'll need more quirks to describe what kind of DSI device this is.

Could you explain what you meant by this? I.e. describing the kind of DSI device?

Describing the number of lanes, specifying the virtual channel, mode flags, etc. You could probably set the number of lanes and mode flags via the I2C driver, but especially the virtual channel cannot be set because it isn't known to the I2C DT branch of the device.

Quoted 4 lines

The dsi device created isn't really a dummy device as such. It's dummy in the sense that there isn't a real dsi driver associated with it. The dsi device is still used to attach to a mipi dsi host, the way normal dsi devices do.

I understand, but I don't see why it has to be instantiated by the I2C driver, that's what I find backwards. There is already a standard way for instantiating DSI devices, why not use it?

Quoted 8 lines
Quoted 7 lines

On the other hand if you properly instantiate the DSI device you can easily write a driver for it, and the driver will set up the correct properties as implied by the compatible string. Once you have that you can easily hook it up to the I2C control interface in whatever way you like, be that an OF graph or just a simple unidirectional link by phandle.

Quoted 4 lines

With the fused approach you suggested, we would have 2 drivers: one i2c and the other dsi. The i2c client driver would be more or less minimal, preparing an i2c_client device for the dsi driver to use. Is my understanding correct?

Correct. That's kind of similar to the way an HDMI encoder driver would use an I2C adapter to query EDID. The i2c_client device would be a means for the DSI driver to access the control interface.

Quoted 4 lines

We can do without dummy dsi devices with this method. But, representing a device with 2 DT nodes seems a bit off. We'd also need to compatible strings for the same device, one for the i2c part, and the other for the dsi part.

I agree that this somewhat stretches the capabilities of device tree. Another alternative I guess would be to not have a compatible string for the I2C device at all (that's technically not valid, I guess) because we really don't need an I2C driver for the device. What we really need is a DSI driver with a means to talk over some I2C bus with some other part of its device.

Quoted 5 lines

From an adv75xx driver perspective, it should also support the ADV7511 chip, which is a RGB/DPI to HDMI encoder. For adv7511, we don't need a DSI DT node. It would be a bit inconsistent to have the bindings require both DSI and I2C nodes for one chip, and only I2C node for the other, with both chips being supported by the same driver.

Why would that be inconsistent? That sounds like the most accurate representation of the hardware to me.

Thierry

_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel

#15 lore raw
Quoted 167 lines · Thierry Reding
Quoted 166 lines · Archit Taneja

Hi Thierry, Lucas,

Quoted 113 lines · Thierry Reding
Quoted 86 lines · Lucas Stach

Am Mittwoch, den 19.08.2015, 16:34 +0200 schrieb Thierry Reding:

Quoted 3 lines · Lucas Stach
Quoted 2 lines

Hi Thierry, Archit,

[...]

Quoted 81 lines
Quoted 80 lines
Quoted 67 lines

Perhaps a better way would be to invert this relationship. According to your proposal we'd have to have DT like this:

	i2c@... {
		...

		dsi-device@... {
			...
			dsi-bus = <&dsi>;
			...
		};

		...
	};

	dsi@... {
		...
	};

Inversing the relationship would become something like this:

	i2c@... {
		...
	};

	dsi@... {
		...

		peripheral@... {
			...
			i2c-bus = <&i2c>;
			...
		};

		...
	};

Both of those aren't fundamentally different, and they both have the disavantage of lacking ways to transport configuration data that the other bus needs to instantiate the dummy device (such as the reg property for example, denoting the I2C slave address or the DSI VC).

So how about we create two devices in the device tree and fuse them at the driver level:

	i2c@... {
		...

		i2cdsi: dsi-device@... {
			...
		};

		...
	};

	dsi@... {
		...

		peripheral@... {
			...
			control = <&i2cdsi>;
			...
		};

		...
	};
Quoted 5 lines

This way we'll get both an I2C device and a DSI device that we can fully describe using the standard device tree bindings. At driver time we can get the I2C device from the phandle in the control property of the DSI device and use it to execute I2C transactions.

I don't really like to see that you are inventing yet-another-way to handle devices connected to multiple buses.

Devicetree is structured along the control buses, even if the devices are connected to multiple buses, in the DT they are always children of the bus that is used to control their registers from the CPUs perspective. So a DSI encoder that is controlled through i2c is clearly a child of the i2c master controller and only of that one.

Quoted 7 lines
Quoted 4 lines

I think that's a flawed interpretation of what's going on here. The device in fact has two interfaces: one is I2C, the other is DSI. In my opinion that's reason enough to represent it as two logical devices.

Does it really have 2 control interfaces that are used at the same time? Or is the DSI connection a passive data bus if the register control happens through i2c?

The interfaces may not be used at the same time, and the DSI interface may even be crippled, but the device is still addressable from the DSI host controller, if for nothing else than for routing the video stream.

Quoted 14 lines
Quoted 10 lines
Quoted 4 lines

If you need to model connections between devices that are not reflected through the control bus hierarchy you should really consider using the standardized of-graph bindings. (Documentation/devicetree/bindings/graph.txt)

The problem is that the original proposal would instantiate a dummy device, so it wouldn't be represented in DT at all. So unless you do add two logical devices to DT (one for each bus interface), you don't have anything to glue together with an OF graph.

I see that the having dummy device is the least desirable solution. But if there is only one control bus to the device I think it should be one device sitting beneath the control bus.

Quoted 7 lines
Quoted 2 lines

You can then use of-graph to model the data path between the DSI encoder and device.

But you will be needing a device below the DSI host controller to represent that endpoint of the connection. The DSI host controller itself is in no way connected to the I2C adapter. You would have to add some sort of quirk to the DSI controller binding to allow it to

Thanks for the review.

I implemented this to support ADV7533 DSI to HDMI encoder chip, which has a DSI video bus and an i2c control bus.

There weren't any quirks as such in the device tree when I tried to implement this. The DT seems to manage fine without a node corresponding to a mipi_dsi_device:

i2c_adap@.. {
	adv7533@.. {

		port {
			adv_in: endpoint {
				remote-endpoint = <&dsi_out>;
			};
		};
	};
};
dsi_host@.. {
	...
	...

	port {
		dsi_out: endpoint {
			remote-endpoint = <&adv_in>;
		}
	};
};

It's the i2c driver's job to parse the graph and retrieve the phandle to the dsi host. Using this, it can proceed with registering itself to this host using the new dsi funcs. This patch does the same for the adv7533 i2c driver:

http://www.spinics.net/lists/dri-devel/msg86840.html

Quoted 2 lines

hook up with a control endpoint. And then you'll need more quirks to describe what kind of DSI device this is.

Quoted 7 lines
Quoted 2 lines

Could you explain what you meant by this? I.e. describing the kind of DSI device?

Describing the number of lanes, specifying the virtual channel, mode flags, etc. You could probably set the number of lanes and mode flags via the I2C driver, but especially the virtual channel cannot be set because it isn't known to the I2C DT branch of the device.

I agree with the VC part. It could be a DT entry within the i2c client node, but that does make it seem like a quirk. The 'reg' way under the DSI host is definitely better to populate the virtual channel.

Quoted 9 lines
Quoted 5 lines

The dsi device created isn't really a dummy device as such. It's dummy in the sense that there isn't a real dsi driver associated with it. The dsi device is still used to attach to a mipi dsi host, the way normal dsi devices do.

I understand, but I don't see why it has to be instantiated by the I2C driver, that's what I find backwards. There is already a standard way for instantiating DSI devices, why not use it?

I assumed we could either represent the device using an i2c driver, or dsi, but not both. Hence, I came up with this approach.

Quoted 9 lines
Quoted 9 lines
Quoted 8 lines

On the other hand if you properly instantiate the DSI device you can easily write a driver for it, and the driver will set up the correct properties as implied by the compatible string. Once you have that you can easily hook it up to the I2C control interface in whatever way you like, be that an OF graph or just a simple unidirectional link by phandle.

Quoted 8 lines
Quoted 4 lines

With the fused approach you suggested, we would have 2 drivers: one i2c and the other dsi. The i2c client driver would be more or less minimal, preparing an i2c_client device for the dsi driver to use. Is my understanding correct?

Correct. That's kind of similar to the way an HDMI encoder driver would use an I2C adapter to query EDID. The i2c_client device would be a means for the DSI driver to access the control interface.

Okay.

Although, I'm not sure about the HDMI encoder example. An HDMI encoder would read off edid directly from the adapter(with an address specified), it wouldn't need to create an i2c client device. Therefore, an HDMI encoder wouldn't need to have a separate node for i2c in DT.

Quoted 6 lines
Quoted 5 lines

We can do without dummy dsi devices with this method. But, representing a device with 2 DT nodes seems a bit off. We'd also need to compatible strings for the same device, one for the i2c part, and the other for the dsi part.

Quoted 6 lines

I agree that this somewhat stretches the capabilities of device tree. Another alternative I guess would be to not have a compatible string for the I2C device at all (that's technically not valid, I guess) because we really don't need an I2C driver for the device. What we really need is a DSI driver with a means to talk over some I2C bus with some other part of its device.

I think what the driver should 'really' be is a bit subjective, and can vary based on what the buses are used for in the device. For the Toshiba chip that Jani mentioned, it tends more towards a DSI driver. Whereas, for an ADV75xx chip, it's closer to an I2C driver since only I2C can be used to configure the chip registers.

Although, I agree with the point you made about the DSI bus here:

"and the DSI interface may even be crippled, but the device is still addressable from the DSI host controller, if for nothing else than for routing the video stream."

The fact that the data on the DSI bus contains routing information (i.e, virtual channel number) always gives it some 'control' aspect.

Quoted 9 lines
Quoted 6 lines

From an adv75xx driver perspective, it should also support the ADV7511
chip, which is a RGB/DPI to HDMI encoder. For adv7511, we don't need a DSI DT node. It would be a bit inconsistent to have the bindings require both DSI and I2C nodes for one chip, and only I2C node for the other, with both chips being supported by the same driver.

Why would that be inconsistent? That sounds like the most accurate representation of the hardware to me.

Inconsistent wasn't the right term. I should have used 'uncommon' :) It's common for two chips of the same family to have a different set optional properties in DT, but it's not common for two chips of the same family to be represented by a different number of devices in DT.

I don't have an issue with the fused approach you suggested, as long as people are okay with the DT parts. Especially the part of needing 2 compatible strings in the DT.

Thanks,
Archit

Signature · 6 lines
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel
#16 lore raw

Thierry,

Quoted 284 lines · Archit Taneja
Quoted 187 lines · Thierry Reding
Quoted 186 lines · Archit Taneja

Hi Thierry, Lucas,

Quoted 132 lines · Thierry Reding
Quoted 102 lines · Lucas Stach

Am Mittwoch, den 19.08.2015, 16:34 +0200 schrieb Thierry Reding:

Quoted 3 lines · Lucas Stach
Quoted 2 lines

Hi Thierry, Archit,

[...]

Quoted 92 lines
Quoted 83 lines
Quoted 72 lines

Perhaps a better way would be to invert this relationship. According to
your proposal we'd have to have DT like this:

    i2c@... {
        ...

        dsi-device@... {
            ...
            dsi-bus = <&dsi>;
            ...
        };

        ...
    };

    dsi@... {
        ...
    };

Inversing the relationship would become something like this:

    i2c@... {
        ...
    };

    dsi@... {
        ...

        peripheral@... {
            ...
            i2c-bus = <&i2c>;
            ...
        };

        ...
    };

Both of those aren't fundamentally different, and they both have the
disavantage of lacking ways to transport configuration data that the
other bus needs to instantiate the dummy device (such as the reg property for example, denoting the I2C slave address or the DSI VC).

So how about we create two devices in the device tree and fuse them at
the driver level:

    i2c@... {
        ...

        i2cdsi: dsi-device@... {
            ...
        };

        ...
    };

    dsi@... {
        ...

        peripheral@... {
            ...
            control = <&i2cdsi>;
            ...
        };

        ...
    };
Quoted 8 lines

This way we'll get both an I2C device and a DSI device that we can fully
describe using the standard device tree bindings. At driver time we can
get the I2C device from the phandle in the control property of the DSI
device and use it to execute I2C transactions.

I don't really like to see that you are inventing yet-another-way to handle devices connected to multiple buses.

Quoted 8 lines

Devicetree is structured along the control buses, even if the devices
are connected to multiple buses, in the DT they are always children of
the bus that is used to control their registers from the CPUs perspective. So a DSI encoder that is controlled through i2c is clearly
a child of the i2c master controller and only of that one.

Quoted 5 lines

I think that's a flawed interpretation of what's going on here. The device in fact has two interfaces: one is I2C, the other is DSI. In my
opinion that's reason enough to represent it as two logical devices.

Quoted 4 lines

Does it really have 2 control interfaces that are used at the same time?
Or is the DSI connection a passive data bus if the register control happens through i2c?

The interfaces may not be used at the same time, and the DSI interface may even be crippled, but the device is still addressable from the DSI host controller, if for nothing else than for routing the video stream.

Quoted 20 lines
Quoted 7 lines
Quoted 6 lines

If you need to model connections between devices that are not reflected
through the control bus hierarchy you should really consider using the
standardized of-graph bindings. (Documentation/devicetree/bindings/graph.txt)

Quoted 7 lines

The problem is that the original proposal would instantiate a dummy device, so it wouldn't be represented in DT at all. So unless you do add
two logical devices to DT (one for each bus interface), you don't have
anything to glue together with an OF graph.

I see that the having dummy device is the least desirable solution. But
if there is only one control bus to the device I think it should be one
device sitting beneath the control bus.

Quoted 8 lines
Quoted 3 lines

You can then use of-graph to model the data path between the DSI encoder
and device.

But you will be needing a device below the DSI host controller to represent that endpoint of the connection. The DSI host controller itself is in no way connected to the I2C adapter. You would have to add some sort of quirk to the DSI controller binding to allow it to

Thanks for the review.

I implemented this to support ADV7533 DSI to HDMI encoder chip, which has a DSI video bus and an i2c control bus.

There weren't any quirks as such in the device tree when I tried to implement this. The DT seems to manage fine without a node corresponding to a mipi_dsi_device:

i2c_adap@.. {
    adv7533@.. {

        port {
            adv_in: endpoint {
                remote-endpoint = <&dsi_out>;
            };
        };
    };
};
dsi_host@.. {
    ...
    ...

    port {
        dsi_out: endpoint {
            remote-endpoint = <&adv_in>;
        }
    };
};

It's the i2c driver's job to parse the graph and retrieve the phandle to the dsi host. Using this, it can proceed with registering itself to this host using the new dsi funcs. This patch does the same for the adv7533 i2c driver:

http://www.spinics.net/lists/dri-devel/msg86840.html

Quoted 2 lines

hook up with a control endpoint. And then you'll need more quirks to describe what kind of DSI device this is.

Quoted 7 lines
Quoted 2 lines

Could you explain what you meant by this? I.e. describing the kind of DSI device?

Describing the number of lanes, specifying the virtual channel, mode flags, etc. You could probably set the number of lanes and mode flags via the I2C driver, but especially the virtual channel cannot be set because it isn't known to the I2C DT branch of the device.

I agree with the VC part. It could be a DT entry within the i2c client node, but that does make it seem like a quirk. The 'reg' way under the DSI host is definitely better to populate the virtual channel.

Quoted 9 lines
Quoted 5 lines

The dsi device created isn't really a dummy device as such. It's dummy in the sense that there isn't a real dsi driver associated with it. The dsi device is still used to attach to a mipi dsi host, the way normal dsi devices do.

I understand, but I don't see why it has to be instantiated by the I2C driver, that's what I find backwards. There is already a standard way for instantiating DSI devices, why not use it?

I assumed we could either represent the device using an i2c driver, or dsi, but not both. Hence, I came up with this approach.

Quoted 9 lines
Quoted 9 lines
Quoted 8 lines

On the other hand if you properly instantiate the DSI device you can easily write a driver for it, and the driver will set up the correct properties as implied by the compatible string. Once you have that you can easily hook it up to the I2C control interface in whatever way you like, be that an OF graph or just a simple unidirectional link by phandle.

Quoted 8 lines
Quoted 4 lines

With the fused approach you suggested, we would have 2 drivers: one i2c and the other dsi. The i2c client driver would be more or less minimal, preparing an i2c_client device for the dsi driver to use. Is my understanding correct?

Correct. That's kind of similar to the way an HDMI encoder driver would use an I2C adapter to query EDID. The i2c_client device would be a means for the DSI driver to access the control interface.

Okay.

Although, I'm not sure about the HDMI encoder example. An HDMI encoder would read off edid directly from the adapter(with an address specified), it wouldn't need to create an i2c client device. Therefore, an HDMI encoder wouldn't need to have a separate node for i2c in DT.

Quoted 6 lines
Quoted 5 lines

We can do without dummy dsi devices with this method. But, representing a device with 2 DT nodes seems a bit off. We'd also need to compatible strings for the same device, one for the i2c part, and the other for the dsi part.

Quoted 6 lines

I agree that this somewhat stretches the capabilities of device tree. Another alternative I guess would be to not have a compatible string for the I2C device at all (that's technically not valid, I guess) because we really don't need an I2C driver for the device. What we really need is a DSI driver with a means to talk over some I2C bus with some other part of its device.

I think what the driver should 'really' be is a bit subjective, and can vary based on what the buses are used for in the device. For the Toshiba chip that Jani mentioned, it tends more towards a DSI driver. Whereas, for an ADV75xx chip, it's closer to an I2C driver since only I2C can be used to configure the chip registers.

Although, I agree with the point you made about the DSI bus here:

"and the DSI interface may even be crippled, but the device is still addressable from the DSI host controller, if for nothing else than for routing the video stream."

The fact that the data on the DSI bus contains routing information (i.e, virtual channel number) always gives it some 'control' aspect.

Quoted 9 lines
Quoted 6 lines

From an adv75xx driver perspective, it should also support the ADV7511
chip, which is a RGB/DPI to HDMI encoder. For adv7511, we don't need a DSI DT node. It would be a bit inconsistent to have the bindings require both DSI and I2C nodes for one chip, and only I2C node for the other, with both chips being supported by the same driver.

Why would that be inconsistent? That sounds like the most accurate representation of the hardware to me.

Inconsistent wasn't the right term. I should have used 'uncommon' :) It's common for two chips of the same family to have a different set optional properties in DT, but it's not common for two chips of the same family to be represented by a different number of devices in DT.

Quoted 3 lines

I don't have an issue with the fused approach you suggested, as long as people are okay with the DT parts. Especially the part of needing 2 compatible strings in the DT.

I implemented the ADV7533 driver with the approach you suggested above (2 drivers for 2 different components of the chip). I posted it out just a while back (with you in loop).

The DT node with this apporach would look like this:

https://github.com/boddob/linux/blob/c24cbf63a6998d00095c10122ce5e37b764c7dba/arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi#L162

The main irritant with the '2 driver' approach is that we need to share the per-device driver data with them. For ADV7533, I've made the i2c driver allocate driver data (struct adv7511).

The dsi driver gets the driver data in the following way:

- The i2c driver sets the driver data as its client data using i2c_set_clientdata()
- Parse the i2c-control phandle to get the corresponding i2c client.
- Extract the adv7511 struct by getting i2c_get_clientdata()

This way of getting the same driver data is a bit strange, but it works. For this, we do need to ensure that the dsi driver defers as long as the i2c driver isn't probed.

I've now implemented both approaches for the driver. The first using a dummy dsi device, and this one using 2 drivers (with both being represented in DT). The advantage of the latter is that we don't need to create any dummy device stuff, the disadvantage is that DT is a bit uncommon.

Can we now come to a conclusion on what approach is better?

Thanks,
Archit

Signature · 6 lines
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel
#17 lore raw
Quoted 314 lines · Archit Taneja

Thierry,

Quoted 284 lines · Archit Taneja
Quoted 187 lines · Thierry Reding
Quoted 186 lines · Archit Taneja

Hi Thierry, Lucas,

Quoted 132 lines · Thierry Reding
Quoted 102 lines · Lucas Stach

Am Mittwoch, den 19.08.2015, 16:34 +0200 schrieb Thierry Reding:

Quoted 3 lines · Lucas Stach
Quoted 2 lines

Hi Thierry, Archit,

[...]

Quoted 92 lines
Quoted 83 lines
Quoted 72 lines

Perhaps a better way would be to invert this relationship. According to
your proposal we'd have to have DT like this:

    i2c@... {
        ...

        dsi-device@... {
            ...
            dsi-bus = <&dsi>;
            ...
        };

        ...
    };

    dsi@... {
        ...
    };

Inversing the relationship would become something like this:

    i2c@... {
        ...
    };

    dsi@... {
        ...

        peripheral@... {
            ...
            i2c-bus = <&i2c>;
            ...
        };

        ...
    };

Both of those aren't fundamentally different, and they both have the
disavantage of lacking ways to transport configuration data that the
other bus needs to instantiate the dummy device (such as the reg property for example, denoting the I2C slave address or the DSI VC).

So how about we create two devices in the device tree and fuse them at
the driver level:

    i2c@... {
        ...

        i2cdsi: dsi-device@... {
            ...
        };

        ...
    };

    dsi@... {
        ...

        peripheral@... {
            ...
            control = <&i2cdsi>;
            ...
        };

        ...
    };
Quoted 8 lines

This way we'll get both an I2C device and a DSI device that we can fully
describe using the standard device tree bindings. At driver time we can
get the I2C device from the phandle in the control property of the DSI
device and use it to execute I2C transactions.

I don't really like to see that you are inventing yet-another-way to handle devices connected to multiple buses.

Quoted 8 lines

Devicetree is structured along the control buses, even if the devices
are connected to multiple buses, in the DT they are always children of
the bus that is used to control their registers from the CPUs perspective. So a DSI encoder that is controlled through i2c is clearly
a child of the i2c master controller and only of that one.

Quoted 5 lines

I think that's a flawed interpretation of what's going on here. The device in fact has two interfaces: one is I2C, the other is DSI. In my
opinion that's reason enough to represent it as two logical devices.

Quoted 4 lines

Does it really have 2 control interfaces that are used at the same time?
Or is the DSI connection a passive data bus if the register control happens through i2c?

The interfaces may not be used at the same time, and the DSI interface may even be crippled, but the device is still addressable from the DSI host controller, if for nothing else than for routing the video stream.

Quoted 20 lines
Quoted 7 lines
Quoted 6 lines

If you need to model connections between devices that are not reflected
through the control bus hierarchy you should really consider using the
standardized of-graph bindings. (Documentation/devicetree/bindings/graph.txt)

Quoted 7 lines

The problem is that the original proposal would instantiate a dummy device, so it wouldn't be represented in DT at all. So unless you do add
two logical devices to DT (one for each bus interface), you don't have
anything to glue together with an OF graph.

I see that the having dummy device is the least desirable solution. But
if there is only one control bus to the device I think it should be one
device sitting beneath the control bus.

Quoted 8 lines
Quoted 3 lines

You can then use of-graph to model the data path between the DSI encoder
and device.

But you will be needing a device below the DSI host controller to represent that endpoint of the connection. The DSI host controller itself is in no way connected to the I2C adapter. You would have to add some sort of quirk to the DSI controller binding to allow it to

Thanks for the review.

I implemented this to support ADV7533 DSI to HDMI encoder chip, which has a DSI video bus and an i2c control bus.

There weren't any quirks as such in the device tree when I tried to implement this. The DT seems to manage fine without a node corresponding to a mipi_dsi_device:

i2c_adap@.. {
    adv7533@.. {

        port {
            adv_in: endpoint {
                remote-endpoint = <&dsi_out>;
            };
        };
    };
};
dsi_host@.. {
    ...
    ...

    port {
        dsi_out: endpoint {
            remote-endpoint = <&adv_in>;
        }
    };
};

It's the i2c driver's job to parse the graph and retrieve the phandle to the dsi host. Using this, it can proceed with registering itself to this host using the new dsi funcs. This patch does the same for the adv7533 i2c driver:

http://www.spinics.net/lists/dri-devel/msg86840.html

Quoted 2 lines

hook up with a control endpoint. And then you'll need more quirks to describe what kind of DSI device this is.

Quoted 7 lines
Quoted 2 lines

Could you explain what you meant by this? I.e. describing the kind of DSI device?

Describing the number of lanes, specifying the virtual channel, mode flags, etc. You could probably set the number of lanes and mode flags via the I2C driver, but especially the virtual channel cannot be set because it isn't known to the I2C DT branch of the device.

I agree with the VC part. It could be a DT entry within the i2c client node, but that does make it seem like a quirk. The 'reg' way under the DSI host is definitely better to populate the virtual channel.

Quoted 9 lines
Quoted 5 lines

The dsi device created isn't really a dummy device as such. It's dummy in the sense that there isn't a real dsi driver associated with it. The dsi device is still used to attach to a mipi dsi host, the way normal dsi devices do.

I understand, but I don't see why it has to be instantiated by the I2C driver, that's what I find backwards. There is already a standard way for instantiating DSI devices, why not use it?

I assumed we could either represent the device using an i2c driver, or dsi, but not both. Hence, I came up with this approach.

Quoted 9 lines
Quoted 9 lines
Quoted 8 lines

On the other hand if you properly instantiate the DSI device you can easily write a driver for it, and the driver will set up the correct properties as implied by the compatible string. Once you have that you can easily hook it up to the I2C control interface in whatever way you like, be that an OF graph or just a simple unidirectional link by phandle.

Quoted 8 lines
Quoted 4 lines

With the fused approach you suggested, we would have 2 drivers: one i2c and the other dsi. The i2c client driver would be more or less minimal, preparing an i2c_client device for the dsi driver to use. Is my understanding correct?

Correct. That's kind of similar to the way an HDMI encoder driver would use an I2C adapter to query EDID. The i2c_client device would be a means for the DSI driver to access the control interface.

Okay.

Although, I'm not sure about the HDMI encoder example. An HDMI encoder would read off edid directly from the adapter(with an address specified), it wouldn't need to create an i2c client device. Therefore, an HDMI encoder wouldn't need to have a separate node for i2c in DT.

Quoted 6 lines
Quoted 5 lines

We can do without dummy dsi devices with this method. But, representing a device with 2 DT nodes seems a bit off. We'd also need to compatible strings for the same device, one for the i2c part, and the other for the dsi part.

Quoted 6 lines

I agree that this somewhat stretches the capabilities of device tree. Another alternative I guess would be to not have a compatible string for the I2C device at all (that's technically not valid, I guess) because we really don't need an I2C driver for the device. What we really need is a DSI driver with a means to talk over some I2C bus with some other part of its device.

I think what the driver should 'really' be is a bit subjective, and can vary based on what the buses are used for in the device. For the Toshiba chip that Jani mentioned, it tends more towards a DSI driver. Whereas, for an ADV75xx chip, it's closer to an I2C driver since only I2C can be used to configure the chip registers.

Although, I agree with the point you made about the DSI bus here:

"and the DSI interface may even be crippled, but the device is still addressable from the DSI host controller, if for nothing else than for routing the video stream."

The fact that the data on the DSI bus contains routing information (i.e, virtual channel number) always gives it some 'control' aspect.

Quoted 9 lines
Quoted 6 lines

From an adv75xx driver perspective, it should also support the ADV7511
chip, which is a RGB/DPI to HDMI encoder. For adv7511, we don't need a DSI DT node. It would be a bit inconsistent to have the bindings require both DSI and I2C nodes for one chip, and only I2C node for the other, with both chips being supported by the same driver.

Why would that be inconsistent? That sounds like the most accurate representation of the hardware to me.

Inconsistent wasn't the right term. I should have used 'uncommon' :) It's common for two chips of the same family to have a different set optional properties in DT, but it's not common for two chips of the same family to be represented by a different number of devices in DT.

Quoted 3 lines

I don't have an issue with the fused approach you suggested, as long as people are okay with the DT parts. Especially the part of needing 2 compatible strings in the DT.

I implemented the ADV7533 driver with the approach you suggested above (2 drivers for 2 different components of the chip). I posted it out just a while back (with you in loop).

The DT node with this apporach would look like this:

https://github.com/boddob/linux/blob/c24cbf63a6998d00095c10122ce5e37b764c7dba/arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi#L162

The main irritant with the '2 driver' approach is that we need to share the per-device driver data with them. For ADV7533, I've made the i2c driver allocate driver data (struct adv7511).

The dsi driver gets the driver data in the following way:

- The i2c driver sets the driver data as its client data using i2c_set_clientdata()
- Parse the i2c-control phandle to get the corresponding i2c client.
- Extract the adv7511 struct by getting i2c_get_clientdata()

This way of getting the same driver data is a bit strange, but it works. For this, we do need to ensure that the dsi driver defers as long as the i2c driver isn't probed.

Quoted 7 lines

I've now implemented both approaches for the driver. The first using a dummy dsi device, and this one using 2 drivers (with both being represented in DT). The advantage of the latter is that we don't need to create any dummy device stuff, the disadvantage is that DT is a bit uncommon.

Can we now come to a conclusion on what approach is better?

DSI by design is data bus which can be used additionally as a control bus, but in this particular case it is purely data bus. So of-graph bindings seem to be better choice. As already Lucas Stach said DT hierarchy should describe control buses and of-graph bindings should describe data bus. Argument that hw has two interfaces does not seem to be valid here - it has only one control interface. The other one is only for data, representing every data interface using DT hierarchy would lead to inflation of pseudo devices.

On the other side I do not see dummy device approach ideal solution, I guess lightweight framework providing DSI hosts detached from Linux device model could work better here.
The only problem here is that it should coexist somehow with dsi bus used to control devices. Anyway implementing it shouldn't be hard, question is if it would be eventually accepted :) I guess we can live for now with dummy devs.

Summarizing I would prefer version with dummy devices, as it seems more compatible with DT design.

Regards
Andrzej

Quoted 4 lines

Thanks,
Archit

#18 lore raw
Quoted 338 lines · Andrzej Hajda
Quoted 314 lines · Archit Taneja

Thierry,

Quoted 284 lines · Archit Taneja
Quoted 187 lines · Thierry Reding
Quoted 186 lines · Archit Taneja

Hi Thierry, Lucas,

Quoted 132 lines · Thierry Reding
Quoted 102 lines · Lucas Stach

Am Mittwoch, den 19.08.2015, 16:34 +0200 schrieb Thierry Reding:

Quoted 3 lines · Lucas Stach
Quoted 2 lines

Hi Thierry, Archit,

[...]

Quoted 92 lines
Quoted 83 lines
Quoted 72 lines

Perhaps a better way would be to invert this relationship. According to
your proposal we'd have to have DT like this:

     i2c@... {
         ...

         dsi-device@... {
             ...
             dsi-bus = <&dsi>;
             ...
         };

         ...
     };

     dsi@... {
         ...
     };

Inversing the relationship would become something like this:

     i2c@... {
         ...
     };

     dsi@... {
         ...

         peripheral@... {
             ...
             i2c-bus = <&i2c>;
             ...
         };

         ...
     };

Both of those aren't fundamentally different, and they both have the
disavantage of lacking ways to transport configuration data that the
other bus needs to instantiate the dummy device (such as the reg property for example, denoting the I2C slave address or the DSI VC).

So how about we create two devices in the device tree and fuse them at
the driver level:

     i2c@... {
         ...

         i2cdsi: dsi-device@... {
             ...
         };

         ...
     };

     dsi@... {
         ...

         peripheral@... {
             ...
             control = <&i2cdsi>;
             ...
         };

         ...
     };
Quoted 8 lines

This way we'll get both an I2C device and a DSI device that we can fully
describe using the standard device tree bindings. At driver time we can
get the I2C device from the phandle in the control property of the DSI
device and use it to execute I2C transactions.

I don't really like to see that you are inventing yet-another-way to handle devices connected to multiple buses.

Quoted 8 lines

Devicetree is structured along the control buses, even if the devices
are connected to multiple buses, in the DT they are always children of
the bus that is used to control their registers from the CPUs perspective. So a DSI encoder that is controlled through i2c is clearly
a child of the i2c master controller and only of that one.

Quoted 5 lines

I think that's a flawed interpretation of what's going on here. The device in fact has two interfaces: one is I2C, the other is DSI. In my
opinion that's reason enough to represent it as two logical devices.

Quoted 4 lines

Does it really have 2 control interfaces that are used at the same time?
Or is the DSI connection a passive data bus if the register control happens through i2c?

The interfaces may not be used at the same time, and the DSI interface may even be crippled, but the device is still addressable from the DSI host controller, if for nothing else than for routing the video stream.

Quoted 20 lines
Quoted 7 lines
Quoted 6 lines

If you need to model connections between devices that are not reflected
through the control bus hierarchy you should really consider using the
standardized of-graph bindings. (Documentation/devicetree/bindings/graph.txt)

Quoted 7 lines

The problem is that the original proposal would instantiate a dummy device, so it wouldn't be represented in DT at all. So unless you do add
two logical devices to DT (one for each bus interface), you don't have
anything to glue together with an OF graph.

I see that the having dummy device is the least desirable solution. But
if there is only one control bus to the device I think it should be one
device sitting beneath the control bus.

Quoted 8 lines
Quoted 3 lines

You can then use of-graph to model the data path between the DSI encoder
and device.

But you will be needing a device below the DSI host controller to represent that endpoint of the connection. The DSI host controller itself is in no way connected to the I2C adapter. You would have to add some sort of quirk to the DSI controller binding to allow it to

Thanks for the review.

I implemented this to support ADV7533 DSI to HDMI encoder chip, which has a DSI video bus and an i2c control bus.

There weren't any quirks as such in the device tree when I tried to implement this. The DT seems to manage fine without a node corresponding to a mipi_dsi_device:

i2c_adap@.. {
     adv7533@.. {

         port {
             adv_in: endpoint {
                 remote-endpoint = <&dsi_out>;
             };
         };
     };
};
dsi_host@.. {
     ...
     ...

     port {
         dsi_out: endpoint {
             remote-endpoint = <&adv_in>;
         }
     };
};

It's the i2c driver's job to parse the graph and retrieve the phandle to the dsi host. Using this, it can proceed with registering itself to this host using the new dsi funcs. This patch does the same for the adv7533 i2c driver:

http://www.spinics.net/lists/dri-devel/msg86840.html

Quoted 2 lines

hook up with a control endpoint. And then you'll need more quirks to describe what kind of DSI device this is.

Quoted 7 lines
Quoted 2 lines

Could you explain what you meant by this? I.e. describing the kind of DSI device?

Describing the number of lanes, specifying the virtual channel, mode flags, etc. You could probably set the number of lanes and mode flags via the I2C driver, but especially the virtual channel cannot be set because it isn't known to the I2C DT branch of the device.

I agree with the VC part. It could be a DT entry within the i2c client node, but that does make it seem like a quirk. The 'reg' way under the DSI host is definitely better to populate the virtual channel.

Quoted 9 lines
Quoted 5 lines

The dsi device created isn't really a dummy device as such. It's dummy in the sense that there isn't a real dsi driver associated with it. The dsi device is still used to attach to a mipi dsi host, the way normal dsi devices do.

I understand, but I don't see why it has to be instantiated by the I2C driver, that's what I find backwards. There is already a standard way for instantiating DSI devices, why not use it?

I assumed we could either represent the device using an i2c driver, or dsi, but not both. Hence, I came up with this approach.

Quoted 9 lines
Quoted 9 lines
Quoted 8 lines

On the other hand if you properly instantiate the DSI device you can easily write a driver for it, and the driver will set up the correct properties as implied by the compatible string. Once you have that you can easily hook it up to the I2C control interface in whatever way you like, be that an OF graph or just a simple unidirectional link by phandle.

Quoted 8 lines
Quoted 4 lines

With the fused approach you suggested, we would have 2 drivers: one i2c and the other dsi. The i2c client driver would be more or less minimal, preparing an i2c_client device for the dsi driver to use. Is my understanding correct?

Correct. That's kind of similar to the way an HDMI encoder driver would use an I2C adapter to query EDID. The i2c_client device would be a means for the DSI driver to access the control interface.

Okay.

Although, I'm not sure about the HDMI encoder example. An HDMI encoder would read off edid directly from the adapter(with an address specified), it wouldn't need to create an i2c client device. Therefore, an HDMI encoder wouldn't need to have a separate node for i2c in DT.

Quoted 6 lines
Quoted 5 lines

We can do without dummy dsi devices with this method. But, representing a device with 2 DT nodes seems a bit off. We'd also need to compatible strings for the same device, one for the i2c part, and the other for the dsi part.

Quoted 6 lines

I agree that this somewhat stretches the capabilities of device tree. Another alternative I guess would be to not have a compatible string for the I2C device at all (that's technically not valid, I guess) because we really don't need an I2C driver for the device. What we really need is a DSI driver with a means to talk over some I2C bus with some other part of its device.

I think what the driver should 'really' be is a bit subjective, and can vary based on what the buses are used for in the device. For the Toshiba chip that Jani mentioned, it tends more towards a DSI driver. Whereas, for an ADV75xx chip, it's closer to an I2C driver since only I2C can be used to configure the chip registers.

Although, I agree with the point you made about the DSI bus here:

"and the DSI interface may even be crippled, but the device is still addressable from the DSI host controller, if for nothing else than for routing the video stream."

The fact that the data on the DSI bus contains routing information (i.e, virtual channel number) always gives it some 'control' aspect.

Quoted 9 lines
Quoted 6 lines

From an adv75xx driver perspective, it should also support the ADV7511
chip, which is a RGB/DPI to HDMI encoder. For adv7511, we don't need a DSI DT node. It would be a bit inconsistent to have the bindings require both DSI and I2C nodes for one chip, and only I2C node for the other, with both chips being supported by the same driver.

Why would that be inconsistent? That sounds like the most accurate representation of the hardware to me.

Inconsistent wasn't the right term. I should have used 'uncommon' :) It's common for two chips of the same family to have a different set optional properties in DT, but it's not common for two chips of the same family to be represented by a different number of devices in DT.

Quoted 3 lines

I don't have an issue with the fused approach you suggested, as long as people are okay with the DT parts. Especially the part of needing 2 compatible strings in the DT.

I implemented the ADV7533 driver with the approach you suggested above (2 drivers for 2 different components of the chip). I posted it out just a while back (with you in loop).

The DT node with this apporach would look like this:

https://github.com/boddob/linux/blob/c24cbf63a6998d00095c10122ce5e37b764c7dba/arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi#L162

The main irritant with the '2 driver' approach is that we need to share the per-device driver data with them. For ADV7533, I've made the i2c driver allocate driver data (struct adv7511).

The dsi driver gets the driver data in the following way:

- The i2c driver sets the driver data as its client data using i2c_set_clientdata()
- Parse the i2c-control phandle to get the corresponding i2c client.
- Extract the adv7511 struct by getting i2c_get_clientdata()

This way of getting the same driver data is a bit strange, but it works. For this, we do need to ensure that the dsi driver defers as long as the i2c driver isn't probed.

Quoted 7 lines

I've now implemented both approaches for the driver. The first using a dummy dsi device, and this one using 2 drivers (with both being represented in DT). The advantage of the latter is that we don't need to create any dummy device stuff, the disadvantage is that DT is a bit uncommon.

Can we now come to a conclusion on what approach is better?

DSI by design is data bus which can be used additionally as a control bus, but in this particular case it is purely data bus. So of-graph bindings seem to be better choice. As already Lucas Stach said DT hierarchy should describe control buses and of-graph bindings should describe data bus. Argument that hw has two interfaces does not seem to be valid here - it has only one control interface. The other one is only for data, representing every data interface using DT hierarchy would lead to inflation of pseudo devices.

On the other side I do not see dummy device approach ideal solution, I guess lightweight framework providing DSI hosts detached from Linux device model could work better here.
The only problem here is that it should coexist somehow with dsi bus used to control devices. Anyway implementing it shouldn't be hard, question is if it would be eventually accepted :) I guess we can live for now with dummy devs.

Quoted 2 lines

Summarizing I would prefer version with dummy devices, as it seems more compatible with DT design.

Thanks for the feedback. I'll spin a newer version of the dummy dsi dev patches after waiting for some more comments.

Archit

Quoted 5 lines

--
To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html

Signature · 6 lines
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel
#19 lore raw
Quoted 341 lines · Archit Taneja
Quoted 338 lines · Andrzej Hajda
Quoted 314 lines · Archit Taneja

Thierry,

Quoted 284 lines · Archit Taneja
Quoted 187 lines · Thierry Reding
Quoted 186 lines · Archit Taneja

Hi Thierry, Lucas,

Quoted 132 lines · Thierry Reding
Quoted 102 lines · Lucas Stach

Am Mittwoch, den 19.08.2015, 16:34 +0200 schrieb Thierry Reding:

Quoted 3 lines · Lucas Stach
Quoted 2 lines

Hi Thierry, Archit,

[...]

Quoted 92 lines
Quoted 83 lines
Quoted 72 lines

Perhaps a better way would be to invert this relationship. According to
your proposal we'd have to have DT like this:

    i2c@... {
        ...

        dsi-device@... {
            ...
            dsi-bus = <&dsi>;
            ...
        };

        ...
    };

    dsi@... {
        ...
    };

Inversing the relationship would become something like this:

    i2c@... {
        ...
    };

    dsi@... {
        ...

        peripheral@... {
            ...
            i2c-bus = <&i2c>;
            ...
        };

        ...
    };

Both of those aren't fundamentally different, and they both have the
disavantage of lacking ways to transport configuration data that the
other bus needs to instantiate the dummy device (such as the reg property for example, denoting the I2C slave address or the DSI VC).

So how about we create two devices in the device tree and fuse them at
the driver level:

    i2c@... {
        ...

        i2cdsi: dsi-device@... {
            ...
        };

        ...
    };

    dsi@... {
        ...

        peripheral@... {
            ...
            control = <&i2cdsi>;
            ...
        };

        ...
    };
Quoted 8 lines

This way we'll get both an I2C device and a DSI device that we can fully
describe using the standard device tree bindings. At driver time we can
get the I2C device from the phandle in the control property of the DSI
device and use it to execute I2C transactions.

I don't really like to see that you are inventing yet-another-way to handle devices connected to multiple buses.

Quoted 8 lines

Devicetree is structured along the control buses, even if the devices
are connected to multiple buses, in the DT they are always children of
the bus that is used to control their registers from the CPUs perspective. So a DSI encoder that is controlled through i2c is clearly
a child of the i2c master controller and only of that one.

Quoted 5 lines

I think that's a flawed interpretation of what's going on here. The device in fact has two interfaces: one is I2C, the other is DSI. In my
opinion that's reason enough to represent it as two logical devices.

Quoted 4 lines

Does it really have 2 control interfaces that are used at the same time?
Or is the DSI connection a passive data bus if the register control happens through i2c?

The interfaces may not be used at the same time, and the DSI interface may even be crippled, but the device is still addressable from the DSI host controller, if for nothing else than for routing the video stream.

Quoted 20 lines
Quoted 7 lines
Quoted 6 lines

If you need to model connections between devices that are not reflected
through the control bus hierarchy you should really consider using the
standardized of-graph bindings. (Documentation/devicetree/bindings/graph.txt)

Quoted 7 lines

The problem is that the original proposal would instantiate a dummy device, so it wouldn't be represented in DT at all. So unless you do add
two logical devices to DT (one for each bus interface), you don't have
anything to glue together with an OF graph.

I see that the having dummy device is the least desirable solution. But
if there is only one control bus to the device I think it should be one
device sitting beneath the control bus.

Quoted 8 lines
Quoted 3 lines

You can then use of-graph to model the data path between the DSI encoder
and device.

But you will be needing a device below the DSI host controller to represent that endpoint of the connection. The DSI host controller itself is in no way connected to the I2C adapter. You would have to add some sort of quirk to the DSI controller binding to allow it to

Thanks for the review.

I implemented this to support ADV7533 DSI to HDMI encoder chip, which has a DSI video bus and an i2c control bus.

There weren't any quirks as such in the device tree when I tried to implement this. The DT seems to manage fine without a node corresponding to a mipi_dsi_device:

i2c_adap@.. {
    adv7533@.. {

        port {
            adv_in: endpoint {
                remote-endpoint = <&dsi_out>;
            };
        };
    };
};
dsi_host@.. {
    ...
    ...

    port {
        dsi_out: endpoint {
            remote-endpoint = <&adv_in>;
        }
    };
};

It's the i2c driver's job to parse the graph and retrieve the phandle to the dsi host. Using this, it can proceed with registering itself to this host using the new dsi funcs. This patch does the same for the adv7533 i2c driver:

http://www.spinics.net/lists/dri-devel/msg86840.html

Quoted 2 lines

hook up with a control endpoint. And then you'll need more quirks to describe what kind of DSI device this is.

Quoted 7 lines
Quoted 2 lines

Could you explain what you meant by this? I.e. describing the kind of DSI device?

Describing the number of lanes, specifying the virtual channel, mode flags, etc. You could probably set the number of lanes and mode flags via the I2C driver, but especially the virtual channel cannot be set because it isn't known to the I2C DT branch of the device.

I agree with the VC part. It could be a DT entry within the i2c client node, but that does make it seem like a quirk. The 'reg' way under the DSI host is definitely better to populate the virtual channel.

Quoted 9 lines
Quoted 5 lines

The dsi device created isn't really a dummy device as such. It's dummy in the sense that there isn't a real dsi driver associated with it. The dsi device is still used to attach to a mipi dsi host, the way normal dsi devices do.

I understand, but I don't see why it has to be instantiated by the I2C driver, that's what I find backwards. There is already a standard way for instantiating DSI devices, why not use it?

I assumed we could either represent the device using an i2c driver, or dsi, but not both. Hence, I came up with this approach.

Quoted 9 lines
Quoted 9 lines
Quoted 8 lines

On the other hand if you properly instantiate the DSI device you can easily write a driver for it, and the driver will set up the correct properties as implied by the compatible string. Once you have that you can easily hook it up to the I2C control interface in whatever way you like, be that an OF graph or just a simple unidirectional link by phandle.

Quoted 8 lines
Quoted 4 lines

With the fused approach you suggested, we would have 2 drivers: one i2c and the other dsi. The i2c client driver would be more or less minimal, preparing an i2c_client device for the dsi driver to use. Is my understanding correct?

Correct. That's kind of similar to the way an HDMI encoder driver would use an I2C adapter to query EDID. The i2c_client device would be a means for the DSI driver to access the control interface.

Okay.

Although, I'm not sure about the HDMI encoder example. An HDMI encoder would read off edid directly from the adapter(with an address specified), it wouldn't need to create an i2c client device. Therefore, an HDMI encoder wouldn't need to have a separate node for i2c in DT.

Quoted 6 lines
Quoted 5 lines

We can do without dummy dsi devices with this method. But, representing a device with 2 DT nodes seems a bit off. We'd also need to compatible strings for the same device, one for the i2c part, and the other for the dsi part.

Quoted 6 lines

I agree that this somewhat stretches the capabilities of device tree. Another alternative I guess would be to not have a compatible string for the I2C device at all (that's technically not valid, I guess) because we really don't need an I2C driver for the device. What we really need is a DSI driver with a means to talk over some I2C bus with some other part of its device.

I think what the driver should 'really' be is a bit subjective, and can vary based on what the buses are used for in the device. For the Toshiba chip that Jani mentioned, it tends more towards a DSI driver. Whereas, for an ADV75xx chip, it's closer to an I2C driver since only I2C can be used to configure the chip registers.

Although, I agree with the point you made about the DSI bus here:

"and the DSI interface may even be crippled, but the device is still addressable from the DSI host controller, if for nothing else than for routing the video stream."

The fact that the data on the DSI bus contains routing information (i.e, virtual channel number) always gives it some 'control' aspect.

Quoted 9 lines
Quoted 6 lines

From an adv75xx driver perspective, it should also support the ADV7511
chip, which is a RGB/DPI to HDMI encoder. For adv7511, we don't need a DSI DT node. It would be a bit inconsistent to have the bindings require both DSI and I2C nodes for one chip, and only I2C node for the other, with both chips being supported by the same driver.

Why would that be inconsistent? That sounds like the most accurate representation of the hardware to me.

Inconsistent wasn't the right term. I should have used 'uncommon' :) It's common for two chips of the same family to have a different set optional properties in DT, but it's not common for two chips of the same family to be represented by a different number of devices in DT.

Quoted 3 lines

I don't have an issue with the fused approach you suggested, as long as people are okay with the DT parts. Especially the part of needing 2 compatible strings in the DT.

I implemented the ADV7533 driver with the approach you suggested above (2 drivers for 2 different components of the chip). I posted it out just a while back (with you in loop).

The DT node with this apporach would look like this:

https://github.com/boddob/linux/blob/c24cbf63a6998d00095c10122ce5e37b764c7dba/arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi#L162

The main irritant with the '2 driver' approach is that we need to share the per-device driver data with them. For ADV7533, I've made the i2c driver allocate driver data (struct adv7511).

The dsi driver gets the driver data in the following way:

- The i2c driver sets the driver data as its client data using i2c_set_clientdata()
- Parse the i2c-control phandle to get the corresponding i2c client.
- Extract the adv7511 struct by getting i2c_get_clientdata()

This way of getting the same driver data is a bit strange, but it works. For this, we do need to ensure that the dsi driver defers as long as the i2c driver isn't probed.

Quoted 7 lines

I've now implemented both approaches for the driver. The first using a dummy dsi device, and this one using 2 drivers (with both being represented in DT). The advantage of the latter is that we don't need to create any dummy device stuff, the disadvantage is that DT is a bit uncommon.

Can we now come to a conclusion on what approach is better?

DSI by design is data bus which can be used additionally as a control bus, but in this particular case it is purely data bus. So of-graph bindings seem to be better choice. As already Lucas Stach said DT hierarchy should describe control buses and of-graph bindings should describe data bus. Argument that hw has two interfaces does not seem to be valid here - it has only one control interface. The other one is only for data, representing every data interface using DT hierarchy would lead to inflation of pseudo devices.

On the other side I do not see dummy device approach ideal solution, I guess lightweight framework providing DSI hosts detached from Linux device model could work better here.
The only problem here is that it should coexist somehow with dsi bus used to control devices. Anyway implementing it shouldn't be hard, question is if it would be eventually accepted :) I guess we can live for now with dummy devs.

Quoted 5 lines
Quoted 2 lines

Summarizing I would prefer version with dummy devices, as it seems more compatible with DT design.

Thanks for the feedback. I'll spin a newer version of the dummy dsi dev patches after waiting for some more comments.

Let's wait for someone from the device tree maintainers to comment instead of going around in circles.

Thierry

_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel

#20 lore raw

Hi Rob, Mark,

We've been trying to figure out the right way to represent a class of display encoder devices in DT.

These devices have registers that are generally configured via i2c. Once the device is configured, it takes in video data from the mipi dsi bus.

Until now, all the devices we've supported devices that can be are configured by the dsi bus itself, and hence, we've been able to represent them in DT as children under the dsi host.

For the above class of devices (using both i2c and dsi), we aren't able to conclude upon what's the better approach among the two:

1. Represent the device via 2 different nodes in DT. One would be a child under an i2c adapter, the other a child of a dsi host. We would have two device drivers, one i2c client, and the other a mipi dsi device.

2. Represent the device as an i2c client in DT. Provide an api to create "dummy" dsi devices. The i2c client driver would use this api to register a dsi device, and link itself with the dsi host.

What do you think would be the way to go here? I guess you might have faced something similar in other subsystems.

I've given a relatively brief description of the problem. There were some more nitty gritties discussed in this thread before.

Thierry, Andrzej, Lucas,

Please feel free to add your comments if I have missed out on something.

Thanks,
Archit

Quoted 353 lines · Thierry Reding
Quoted 341 lines · Archit Taneja
Quoted 338 lines · Andrzej Hajda
Quoted 314 lines · Archit Taneja

Thierry,

Quoted 284 lines · Archit Taneja
Quoted 187 lines · Thierry Reding
Quoted 186 lines · Archit Taneja

Hi Thierry, Lucas,

Quoted 132 lines · Thierry Reding
Quoted 102 lines · Lucas Stach

Am Mittwoch, den 19.08.2015, 16:34 +0200 schrieb Thierry Reding:

Quoted 3 lines · Lucas Stach
Quoted 2 lines

Hi Thierry, Archit,

[...]

Quoted 92 lines
Quoted 83 lines
Quoted 72 lines

Perhaps a better way would be to invert this relationship. According to
your proposal we'd have to have DT like this:

     i2c@... {
         ...

         dsi-device@... {
             ...
             dsi-bus = <&dsi>;
             ...
         };

         ...
     };

     dsi@... {
         ...
     };

Inversing the relationship would become something like this:

     i2c@... {
         ...
     };

     dsi@... {
         ...

         peripheral@... {
             ...
             i2c-bus = <&i2c>;
             ...
         };

         ...
     };

Both of those aren't fundamentally different, and they both have the
disavantage of lacking ways to transport configuration data that the
other bus needs to instantiate the dummy device (such as the reg property for example, denoting the I2C slave address or the DSI VC).

So how about we create two devices in the device tree and fuse them at
the driver level:

     i2c@... {
         ...

         i2cdsi: dsi-device@... {
             ...
         };

         ...
     };

     dsi@... {
         ...

         peripheral@... {
             ...
             control = <&i2cdsi>;
             ...
         };

         ...
     };
Quoted 8 lines

This way we'll get both an I2C device and a DSI device that we can fully
describe using the standard device tree bindings. At driver time we can
get the I2C device from the phandle in the control property of the DSI
device and use it to execute I2C transactions.

I don't really like to see that you are inventing yet-another-way to handle devices connected to multiple buses.

Quoted 8 lines

Devicetree is structured along the control buses, even if the devices
are connected to multiple buses, in the DT they are always children of
the bus that is used to control their registers from the CPUs perspective. So a DSI encoder that is controlled through i2c is clearly
a child of the i2c master controller and only of that one.

Quoted 5 lines

I think that's a flawed interpretation of what's going on here. The device in fact has two interfaces: one is I2C, the other is DSI. In my
opinion that's reason enough to represent it as two logical devices.

Quoted 4 lines

Does it really have 2 control interfaces that are used at the same time?
Or is the DSI connection a passive data bus if the register control happens through i2c?

The interfaces may not be used at the same time, and the DSI interface may even be crippled, but the device is still addressable from the DSI host controller, if for nothing else than for routing the video stream.

Quoted 20 lines
Quoted 7 lines
Quoted 6 lines

If you need to model connections between devices that are not reflected
through the control bus hierarchy you should really consider using the
standardized of-graph bindings. (Documentation/devicetree/bindings/graph.txt)

Quoted 7 lines

The problem is that the original proposal would instantiate a dummy device, so it wouldn't be represented in DT at all. So unless you do add
two logical devices to DT (one for each bus interface), you don't have
anything to glue together with an OF graph.

I see that the having dummy device is the least desirable solution. But
if there is only one control bus to the device I think it should be one
device sitting beneath the control bus.

Quoted 8 lines
Quoted 3 lines

You can then use of-graph to model the data path between the DSI encoder
and device.

But you will be needing a device below the DSI host controller to represent that endpoint of the connection. The DSI host controller itself is in no way connected to the I2C adapter. You would have to add some sort of quirk to the DSI controller binding to allow it to

Thanks for the review.

I implemented this to support ADV7533 DSI to HDMI encoder chip, which has a DSI video bus and an i2c control bus.

There weren't any quirks as such in the device tree when I tried to implement this. The DT seems to manage fine without a node corresponding to a mipi_dsi_device:

i2c_adap@.. {
     adv7533@.. {

         port {
             adv_in: endpoint {
                 remote-endpoint = <&dsi_out>;
             };
         };
     };
};
dsi_host@.. {
     ...
     ...

     port {
         dsi_out: endpoint {
             remote-endpoint = <&adv_in>;
         }
     };
};

It's the i2c driver's job to parse the graph and retrieve the phandle to the dsi host. Using this, it can proceed with registering itself to this host using the new dsi funcs. This patch does the same for the adv7533 i2c driver:

http://www.spinics.net/lists/dri-devel/msg86840.html

Quoted 2 lines

hook up with a control endpoint. And then you'll need more quirks to describe what kind of DSI device this is.

Quoted 7 lines
Quoted 2 lines

Could you explain what you meant by this? I.e. describing the kind of DSI device?

Describing the number of lanes, specifying the virtual channel, mode flags, etc. You could probably set the number of lanes and mode flags via the I2C driver, but especially the virtual channel cannot be set because it isn't known to the I2C DT branch of the device.

I agree with the VC part. It could be a DT entry within the i2c client node, but that does make it seem like a quirk. The 'reg' way under the DSI host is definitely better to populate the virtual channel.

Quoted 9 lines
Quoted 5 lines

The dsi device created isn't really a dummy device as such. It's dummy in the sense that there isn't a real dsi driver associated with it. The dsi device is still used to attach to a mipi dsi host, the way normal dsi devices do.

I understand, but I don't see why it has to be instantiated by the I2C driver, that's what I find backwards. There is already a standard way for instantiating DSI devices, why not use it?

I assumed we could either represent the device using an i2c driver, or dsi, but not both. Hence, I came up with this approach.

Quoted 9 lines
Quoted 9 lines
Quoted 8 lines

On the other hand if you properly instantiate the DSI device you can easily write a driver for it, and the driver will set up the correct properties as implied by the compatible string. Once you have that you can easily hook it up to the I2C control interface in whatever way you like, be that an OF graph or just a simple unidirectional link by phandle.

Quoted 8 lines
Quoted 4 lines

With the fused approach you suggested, we would have 2 drivers: one i2c and the other dsi. The i2c client driver would be more or less minimal, preparing an i2c_client device for the dsi driver to use. Is my understanding correct?

Correct. That's kind of similar to the way an HDMI encoder driver would use an I2C adapter to query EDID. The i2c_client device would be a means for the DSI driver to access the control interface.

Okay.

Although, I'm not sure about the HDMI encoder example. An HDMI encoder would read off edid directly from the adapter(with an address specified), it wouldn't need to create an i2c client device. Therefore, an HDMI encoder wouldn't need to have a separate node for i2c in DT.

Quoted 6 lines
Quoted 5 lines

We can do without dummy dsi devices with this method. But, representing a device with 2 DT nodes seems a bit off. We'd also need to compatible strings for the same device, one for the i2c part, and the other for the dsi part.

Quoted 6 lines

I agree that this somewhat stretches the capabilities of device tree. Another alternative I guess would be to not have a compatible string for the I2C device at all (that's technically not valid, I guess) because we really don't need an I2C driver for the device. What we really need is a DSI driver with a means to talk over some I2C bus with some other part of its device.

I think what the driver should 'really' be is a bit subjective, and can vary based on what the buses are used for in the device. For the Toshiba chip that Jani mentioned, it tends more towards a DSI driver. Whereas, for an ADV75xx chip, it's closer to an I2C driver since only I2C can be used to configure the chip registers.

Although, I agree with the point you made about the DSI bus here:

"and the DSI interface may even be crippled, but the device is still addressable from the DSI host controller, if for nothing else than for routing the video stream."

The fact that the data on the DSI bus contains routing information (i.e, virtual channel number) always gives it some 'control' aspect.

Quoted 9 lines
Quoted 6 lines

From an adv75xx driver perspective, it should also support the ADV7511
chip, which is a RGB/DPI to HDMI encoder. For adv7511, we don't need a DSI DT node. It would be a bit inconsistent to have the bindings require both DSI and I2C nodes for one chip, and only I2C node for the other, with both chips being supported by the same driver.

Why would that be inconsistent? That sounds like the most accurate representation of the hardware to me.

Inconsistent wasn't the right term. I should have used 'uncommon' :) It's common for two chips of the same family to have a different set optional properties in DT, but it's not common for two chips of the same family to be represented by a different number of devices in DT.

Quoted 3 lines

I don't have an issue with the fused approach you suggested, as long as people are okay with the DT parts. Especially the part of needing 2 compatible strings in the DT.

I implemented the ADV7533 driver with the approach you suggested above (2 drivers for 2 different components of the chip). I posted it out just a while back (with you in loop).

The DT node with this apporach would look like this:

https://github.com/boddob/linux/blob/c24cbf63a6998d00095c10122ce5e37b764c7dba/arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi#L162

The main irritant with the '2 driver' approach is that we need to share the per-device driver data with them. For ADV7533, I've made the i2c driver allocate driver data (struct adv7511).

The dsi driver gets the driver data in the following way:

- The i2c driver sets the driver data as its client data using i2c_set_clientdata()
- Parse the i2c-control phandle to get the corresponding i2c client.
- Extract the adv7511 struct by getting i2c_get_clientdata()

This way of getting the same driver data is a bit strange, but it works. For this, we do need to ensure that the dsi driver defers as long as the i2c driver isn't probed.

Quoted 7 lines

I've now implemented both approaches for the driver. The first using a dummy dsi device, and this one using 2 drivers (with both being represented in DT). The advantage of the latter is that we don't need to create any dummy device stuff, the disadvantage is that DT is a bit uncommon.

Can we now come to a conclusion on what approach is better?

DSI by design is data bus which can be used additionally as a control bus, but in this particular case it is purely data bus. So of-graph bindings seem to be better choice. As already Lucas Stach said DT hierarchy should describe control buses and of-graph bindings should describe data bus. Argument that hw has two interfaces does not seem to be valid here - it has only one control interface. The other one is only for data, representing every data interface using DT hierarchy would lead to inflation of pseudo devices.

On the other side I do not see dummy device approach ideal solution, I guess lightweight framework providing DSI hosts detached from Linux device model could work better here.
The only problem here is that it should coexist somehow with dsi bus used to control devices. Anyway implementing it shouldn't be hard, question is if it would be eventually accepted :) I guess we can live for now with dummy devs.

Quoted 5 lines
Quoted 2 lines

Summarizing I would prefer version with dummy devices, as it seems more compatible with DT design.

Thanks for the feedback. I'll spin a newer version of the dummy dsi dev patches after waiting for some more comments.

Let's wait for someone from the device tree maintainers to comment instead of going around in circles.

Thierry

Signature · 6 lines
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel
#21 lore raw
Quoted 4 lines · Archit Taneja

Hi Rob, Mark,

We've been trying to figure out the right way to represent a class of display encoder devices in DT.

I've been meaning to reply on this.

Quoted 16 lines

These devices have registers that are generally configured via i2c. Once the device is configured, it takes in video data from the mipi dsi bus.

Until now, all the devices we've supported devices that can be are configured by the dsi bus itself, and hence, we've been able to represent them in DT as children under the dsi host.

For the above class of devices (using both i2c and dsi), we aren't able to conclude upon what's the better approach among the two:

1. Represent the device via 2 different nodes in DT. One would be a child under an i2c adapter, the other a child of a dsi host. We would have two device drivers, one i2c client, and the other a mipi dsi device.

Quoted 7 lines

2. Represent the device as an i2c client in DT. Provide an api to create "dummy" dsi devices. The i2c client driver would use this api to register a dsi device, and link itself with the dsi host.

What do you think would be the way to go here? I guess you might have faced something similar in other subsystems.

The closest thing I can think of are WiFi/BT combo chips that use SDIO+UART. In that case, 2 nodes makes sense as these chips are essentially 2 independent functions in a single chip and both interfaces are control interfaces (as well as data). This case is a bit different with both interfaces being tied to the same function.

So in this case, I think option 2 is the right way for the reasons already outlined in this thread. I think there needs to be more consistency in how the of-graph connections are defined with the core doing more of the graph traversing. So having an i2c device plus of-graph seems more consistent with other non-DSI cases.

The main open issue seemed to be setting the VC. At least for the ADV7533, it can be whatever you want it to be. The host and device just need to agree. I see no need for that to be in DT at least in this case. But then I'm not sure what are typical constraints for VC assignment. I'd guess that constraints are on the device side and hosts can support whatever the device wants. If so, then it can purely be up to the driver to set.

Implementation-wise, I don't think that I'd call this a dummy device. There are multiple ways for devices to get created in the driver model. DT is just one way. You are just creating the device in a different way outside of DT which is fine.

Rob

Quoted 432 lines

I've given a relatively brief description of the problem. There were some more nitty gritties discussed in this thread before.

Thierry, Andrzej, Lucas,

Please feel free to add your comments if I have missed out on something.

Thanks,
Archit

Quoted 419 lines · Thierry Reding
Quoted 407 lines · Archit Taneja
Quoted 404 lines · Andrzej Hajda
Quoted 369 lines · Archit Taneja

Thierry,

Quoted 337 lines · Archit Taneja
Quoted 208 lines · Thierry Reding
Quoted 207 lines · Archit Taneja

Hi Thierry, Lucas,

Quoted 154 lines · Thierry Reding
Quoted 110 lines · Lucas Stach

Am Mittwoch, den 19.08.2015, 16:34 +0200 schrieb Thierry Reding:

Quoted 3 lines · Lucas Stach
Quoted 2 lines

Hi Thierry, Archit,

[...]

Quoted 98 lines
Quoted 89 lines
Quoted 85 lines

Perhaps a better way would be to invert this relationship.
According to
your proposal we'd have to have DT like this:

i2c@... {
...

dsi-device@... {
...
dsi-bus = <&dsi>;
...
};

...
};

dsi@... {
...
};

Inversing the relationship would become something like this:

i2c@... {
...
};

dsi@... {
...

peripheral@... {
...
i2c-bus = <&i2c>;
...
};

...
};

Both of those aren't fundamentally different, and they both
have
the
disavantage of lacking ways to transport configuration data
that
the
other bus needs to instantiate the dummy device (such as
the reg
property for example, denoting the I2C slave address or the
DSI
VC).

So how about we create two devices in the device tree and fuse
them at
the driver level:

i2c@... {
...

i2cdsi: dsi-device@... {
...
};

...
};

dsi@... {
...

peripheral@... {
...
control = <&i2cdsi>;
...
};

...
};

This way we'll get both an I2C device and a DSI device that we
can fully
describe using the standard device tree bindings. At driver
time
we can
get the I2C device from the phandle in the control property of
the DSI
device and use it to execute I2C transactions.

I don't really like to see that you are inventing
yet-another-way to
handle devices connected to multiple buses.

Quoted 8 lines

Devicetree is structured along the control buses, even if the devices
are connected to multiple buses, in the DT they are always children of
the bus that is used to control their registers from the CPUs perspective. So a DSI encoder that is controlled through i2c is clearly
a child of the i2c master controller and only of that one.

Quoted 7 lines

I think that's a flawed interpretation of what's going on here. The
device in fact has two interfaces: one is I2C, the other is DSI. In my
opinion that's reason enough to represent it as two logical devices.

Quoted 6 lines

Does it really have 2 control interfaces that are used at the same
time?
Or is the DSI connection a passive data bus if the register control
happens through i2c?

The interfaces may not be used at the same time, and the DSI interface
may even be crippled, but the device is still addressable from the DSI
host controller, if for nothing else than for routing the video stream.

Quoted 25 lines
Quoted 7 lines
Quoted 6 lines

If you need to model connections between devices that are not reflected
through the control bus hierarchy you should really consider using the
standardized of-graph bindings. (Documentation/devicetree/bindings/graph.txt)

Quoted 10 lines

The problem is that the original proposal would instantiate a dummy
device, so it wouldn't be represented in DT at all. So unless you
do add
two logical devices to DT (one for each bus interface), you don't
have
anything to glue together with an OF graph.

I see that the having dummy device is the least desirable solution.
But
if there is only one control bus to the device I think it should be
one
device sitting beneath the control bus.

Quoted 3 lines

You can then use of-graph to model the data path between the DSI encoder
and device.

Quoted 6 lines

But you will be needing a device below the DSI host controller to represent that endpoint of the connection. The DSI host controller itself is in no way connected to the I2C adapter. You would have to
add some sort of quirk to the DSI controller binding to allow it to

Thanks for the review.

I implemented this to support ADV7533 DSI to HDMI encoder chip, which
has a DSI video bus and an i2c control bus.

There weren't any quirks as such in the device tree when I tried to implement this. The DT seems to manage fine without a node corresponding to a mipi_dsi_device:

i2c_adap@.. {
     adv7533@.. {

         port {
             adv_in: endpoint {
                 remote-endpoint = <&dsi_out>;
             };
         };
     };
};
dsi_host@.. {
     ...
     ...

     port {
         dsi_out: endpoint {
             remote-endpoint = <&adv_in>;
         }
     };
};

It's the i2c driver's job to parse the graph and retrieve the phandle to the dsi host. Using this, it can proceed with registering itself to this host using the new dsi funcs. This patch does the same for the adv7533 i2c driver:

http://www.spinics.net/lists/dri-devel/msg86840.html

Quoted 2 lines

hook up with a control endpoint. And then you'll need more quirks to describe what kind of DSI device this is.

Quoted 8 lines
Quoted 2 lines

Could you explain what you meant by this? I.e. describing the kind of DSI device?

Describing the number of lanes, specifying the virtual channel, mode flags, etc. You could probably set the number of lanes and mode flags
via the I2C driver, but especially the virtual channel cannot be set because it isn't known to the I2C DT branch of the device.

I agree with the VC part. It could be a DT entry within the i2c client
node, but that does make it seem like a quirk. The 'reg' way under the
DSI host is definitely better to populate the virtual channel.

Quoted 11 lines
Quoted 5 lines

The dsi device created isn't really a dummy device as such. It's dummy in the sense that there isn't a real dsi driver associated with it. The dsi device is still used to attach to a mipi dsi host, the way normal dsi devices do.

I understand, but I don't see why it has to be instantiated by the I2C
driver, that's what I find backwards. There is already a standard way
for instantiating DSI devices, why not use it?

I assumed we could either represent the device using an i2c driver, or
dsi, but not both. Hence, I came up with this approach.

Quoted 20 lines
Quoted 13 lines
Quoted 12 lines

On the other hand if you properly instantiate the DSI device you can
easily write a driver for it, and the driver will set up the correct
properties as implied by the compatible string. Once you have that you
can easily hook it up to the I2C control interface in whatever way you
like, be that an OF graph or just a simple unidirectional link by phandle.

Quoted 6 lines

With the fused approach you suggested, we would have 2 drivers:
one i2c
and the other dsi. The i2c client driver would be more or less minimal,
preparing an i2c_client device for the dsi driver to use. Is my understanding correct?

Quoted 5 lines

Correct. That's kind of similar to the way an HDMI encoder driver would
use an I2C adapter to query EDID. The i2c_client device would be a means
for the DSI driver to access the control interface.

Okay.

Although, I'm not sure about the HDMI encoder example. An HDMI encoder would read off edid directly from the adapter(with an address specified), it wouldn't need to create an i2c client device. Therefore,
an HDMI encoder wouldn't need to have a separate node for i2c in DT.

Quoted 9 lines
Quoted 8 lines

We can do without dummy dsi devices with this method. But, representing
a device with 2 DT nodes seems a bit off. We'd also need to compatible
strings for the same device, one for the i2c part, and the other for
the dsi part.

Quoted 11 lines

I agree that this somewhat stretches the capabilities of device tree.
Another alternative I guess would be to not have a compatible string for
the I2C device at all (that's technically not valid, I guess) because we
really don't need an I2C driver for the device. What we really need is a
DSI driver with a means to talk over some I2C bus with some other part
of its device.

I think what the driver should 'really' be is a bit subjective, and can
vary based on what the buses are used for in the device. For the Toshiba
chip that Jani mentioned, it tends more towards a DSI driver. Whereas,
for an ADV75xx chip, it's closer to an I2C driver since only I2C can be
used to configure the chip registers.

Although, I agree with the point you made about the DSI bus here:

"and the DSI interface may even be crippled, but the device is still addressable from the DSI host controller, if for nothing else than for
routing the video stream."

The fact that the data on the DSI bus contains routing information (i.e,
virtual channel number) always gives it some 'control' aspect.

Quoted 10 lines
Quoted 9 lines

From an adv75xx driver perspective, it should also support the
ADV7511
chip, which is a RGB/DPI to HDMI encoder. For adv7511, we don't need a
DSI DT node. It would be a bit inconsistent to have the bindings require both DSI and I2C nodes for one chip, and only I2C node for the
other, with both chips being supported by the same driver.

Quoted 2 lines

Why would that be inconsistent? That sounds like the most accurate representation of the hardware to me.

Inconsistent wasn't the right term. I should have used 'uncommon' :) It's common for two chips of the same family to have a different set optional properties in DT, but it's not common for two chips of the same family to be represented by a different number of devices in DT.

Quoted 4 lines

I don't have an issue with the fused approach you suggested, as long as people are okay with the DT parts. Especially the part of needing 2
compatible strings in the DT.

I implemented the ADV7533 driver with the approach you suggested above (2 drivers for 2 different components of the chip). I posted it out just a while back (with you in loop).

The DT node with this apporach would look like this:

https://github.com/boddob/linux/blob/c24cbf63a6998d00095c10122ce5e37b764c7dba/arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi#L162

The main irritant with the '2 driver' approach is that we need to share the per-device driver data with them. For ADV7533, I've made the i2c driver allocate driver data (struct adv7511).

The dsi driver gets the driver data in the following way:

- The i2c driver sets the driver data as its client data using i2c_set_clientdata()
- Parse the i2c-control phandle to get the corresponding i2c client.
- Extract the adv7511 struct by getting i2c_get_clientdata()

This way of getting the same driver data is a bit strange, but it works. For this, we do need to ensure that the dsi driver defers as long as the i2c driver isn't probed.

Quoted 7 lines

I've now implemented both approaches for the driver. The first using a dummy dsi device, and this one using 2 drivers (with both being represented in DT). The advantage of the latter is that we don't need to create any dummy device stuff, the disadvantage is that DT is a bit uncommon.

Can we now come to a conclusion on what approach is better?

DSI by design is data bus which can be used additionally as a control bus, but
in this particular case it is purely data bus. So of-graph bindings seem to be
better choice. As already Lucas Stach said DT hierarchy should describe control
buses and of-graph bindings should describe data bus. Argument that hw has two
interfaces does not seem to be valid here - it has only one control interface.
The other one is only for data, representing every data interface using DT
hierarchy would lead to inflation of pseudo devices.

On the other side I do not see dummy device approach ideal solution, I guess
lightweight framework providing DSI hosts detached from Linux device model could
work better here.
The only problem here is that it should coexist somehow with dsi bus used to
control devices. Anyway implementing it shouldn't be hard, question is if it
would be eventually accepted :) I guess we can live for now with dummy devs.

Quoted 5 lines
Quoted 2 lines

Summarizing I would prefer version with dummy devices, as it seems more compatible with DT design.

Thanks for the feedback. I'll spin a newer version of the dummy dsi dev patches after waiting for some more comments.

Let's wait for someone from the device tree maintainers to comment instead of going around in circles.

Thierry

#22 lore raw
Quoted 44 lines · Rob Herring
Quoted 4 lines · Archit Taneja

Hi Rob, Mark,

We've been trying to figure out the right way to represent a class of display encoder devices in DT.

I've been meaning to reply on this.

Quoted 16 lines

These devices have registers that are generally configured via i2c. Once the device is configured, it takes in video data from the mipi dsi bus.

Until now, all the devices we've supported devices that can be are configured by the dsi bus itself, and hence, we've been able to represent them in DT as children under the dsi host.

For the above class of devices (using both i2c and dsi), we aren't able to conclude upon what's the better approach among the two:

1. Represent the device via 2 different nodes in DT. One would be a child under an i2c adapter, the other a child of a dsi host. We would have two device drivers, one i2c client, and the other a mipi dsi device.

Quoted 7 lines

2. Represent the device as an i2c client in DT. Provide an api to create "dummy" dsi devices. The i2c client driver would use this api to register a dsi device, and link itself with the dsi host.

What do you think would be the way to go here? I guess you might have faced something similar in other subsystems.

The closest thing I can think of are WiFi/BT combo chips that use SDIO+UART. In that case, 2 nodes makes sense as these chips are essentially 2 independent functions in a single chip and both interfaces are control interfaces (as well as data). This case is a bit different with both interfaces being tied to the same function.

So in this case, I think option 2 is the right way for the reasons already outlined in this thread. I think there needs to be more consistency in how the of-graph connections are defined with the core doing more of the graph traversing. So having an i2c device plus of-graph seems more consistent with other non-DSI cases.

Quoted 7 lines

The main open issue seemed to be setting the VC. At least for the ADV7533, it can be whatever you want it to be. The host and device just need to agree. I see no need for that to be in DT at least in this case. But then I'm not sure what are typical constraints for VC assignment. I'd guess that constraints are on the device side and hosts can support whatever the device wants. If so, then it can purely be up to the driver to set.

2 DSI devices connected to the same host shouldn't have the same VC. When representing the DSI nodes via DT, we use the 'reg' property to assign the VC.

Although, in practice, we don't generally have multiple devices on the same bus. The trend is to have multiple DSI hosts on the platform to support more devices.

If we have checks that ensures the DT way and the new manual way of creation of DSI devices doesn't result in having conflicting VCs for devices, we should be okay.

Quoted 6 lines

Implementation-wise, I don't think that I'd call this a dummy device. There are multiple ways for devices to get created in the driver model. DT is just one way. You are just creating the device in a different way outside of DT which is fine.

Thanks for the feedback.

Archit

Signature · 2 lines
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
#23 lore raw
In reply to Thierry Reding

Hi Rob, Mark,

We've been trying to figure out the right way to represent a class of display encoder devices in DT.

These devices have registers that are generally configured via i2c. Once the device is configured, it takes in video data from the mipi dsi bus.

Until now, all the devices we've supported devices that can be are configured by the dsi bus itself, and hence, we've been able to represent them in DT as children under the dsi host.

For the above class of devices (using both i2c and dsi), we aren't able to conclude upon what's the better approach among the two:

1. Represent the device via 2 different nodes in DT. One would be a child under an i2c adapter, the other a child of a dsi host. We would have two device drivers, one i2c client, and the other a mipi dsi device.

2. Represent the device as an i2c client in DT. Provide an api to create "dummy" dsi devices. The i2c client driver would use this api to register a dsi device, and link itself with the dsi host.

What do you think would be the way to go here? I guess you might have faced something similar in other subsystems.

I've given a relatively brief description of the problem. There were some more nitty gritties discussed in this thread before.

Thierry, Andrzej, Lucas,

Please feel free to add your comments if I have missed out on something.

Thanks,
Archit

Quoted 353 lines · Thierry Reding
Quoted 341 lines · Archit Taneja
Quoted 338 lines · Andrzej Hajda
Quoted 314 lines · Archit Taneja

Thierry,

Quoted 284 lines · Archit Taneja
Quoted 187 lines · Thierry Reding
Quoted 186 lines · Archit Taneja

Hi Thierry, Lucas,

Quoted 132 lines · Thierry Reding
Quoted 102 lines · Lucas Stach

Am Mittwoch, den 19.08.2015, 16:34 +0200 schrieb Thierry Reding:

Quoted 3 lines · Lucas Stach
Quoted 2 lines

Hi Thierry, Archit,

[...]

Quoted 92 lines
Quoted 83 lines
Quoted 72 lines

Perhaps a better way would be to invert this relationship. According to
your proposal we'd have to have DT like this:

     i2c@... {
         ...

         dsi-device@... {
             ...
             dsi-bus = <&dsi>;
             ...
         };

         ...
     };

     dsi@... {
         ...
     };

Inversing the relationship would become something like this:

     i2c@... {
         ...
     };

     dsi@... {
         ...

         peripheral@... {
             ...
             i2c-bus = <&i2c>;
             ...
         };

         ...
     };

Both of those aren't fundamentally different, and they both have the
disavantage of lacking ways to transport configuration data that the
other bus needs to instantiate the dummy device (such as the reg property for example, denoting the I2C slave address or the DSI VC).

So how about we create two devices in the device tree and fuse them at
the driver level:

     i2c@... {
         ...

         i2cdsi: dsi-device@... {
             ...
         };

         ...
     };

     dsi@... {
         ...

         peripheral@... {
             ...
             control = <&i2cdsi>;
             ...
         };

         ...
     };
Quoted 8 lines

This way we'll get both an I2C device and a DSI device that we can fully
describe using the standard device tree bindings. At driver time we can
get the I2C device from the phandle in the control property of the DSI
device and use it to execute I2C transactions.

I don't really like to see that you are inventing yet-another-way to handle devices connected to multiple buses.

Quoted 8 lines

Devicetree is structured along the control buses, even if the devices
are connected to multiple buses, in the DT they are always children of
the bus that is used to control their registers from the CPUs perspective. So a DSI encoder that is controlled through i2c is clearly
a child of the i2c master controller and only of that one.

Quoted 5 lines

I think that's a flawed interpretation of what's going on here. The device in fact has two interfaces: one is I2C, the other is DSI. In my
opinion that's reason enough to represent it as two logical devices.

Quoted 4 lines

Does it really have 2 control interfaces that are used at the same time?
Or is the DSI connection a passive data bus if the register control happens through i2c?

The interfaces may not be used at the same time, and the DSI interface may even be crippled, but the device is still addressable from the DSI host controller, if for nothing else than for routing the video stream.

Quoted 20 lines
Quoted 7 lines
Quoted 6 lines

If you need to model connections between devices that are not reflected
through the control bus hierarchy you should really consider using the
standardized of-graph bindings. (Documentation/devicetree/bindings/graph.txt)

Quoted 7 lines

The problem is that the original proposal would instantiate a dummy device, so it wouldn't be represented in DT at all. So unless you do add
two logical devices to DT (one for each bus interface), you don't have
anything to glue together with an OF graph.

I see that the having dummy device is the least desirable solution. But
if there is only one control bus to the device I think it should be one
device sitting beneath the control bus.

Quoted 8 lines
Quoted 3 lines

You can then use of-graph to model the data path between the DSI encoder
and device.

But you will be needing a device below the DSI host controller to represent that endpoint of the connection. The DSI host controller itself is in no way connected to the I2C adapter. You would have to add some sort of quirk to the DSI controller binding to allow it to

Thanks for the review.

I implemented this to support ADV7533 DSI to HDMI encoder chip, which has a DSI video bus and an i2c control bus.

There weren't any quirks as such in the device tree when I tried to implement this. The DT seems to manage fine without a node corresponding to a mipi_dsi_device:

i2c_adap@.. {
     adv7533@.. {

         port {
             adv_in: endpoint {
                 remote-endpoint = <&dsi_out>;
             };
         };
     };
};
dsi_host@.. {
     ...
     ...

     port {
         dsi_out: endpoint {
             remote-endpoint = <&adv_in>;
         }
     };
};

It's the i2c driver's job to parse the graph and retrieve the phandle to the dsi host. Using this, it can proceed with registering itself to this host using the new dsi funcs. This patch does the same for the adv7533 i2c driver:

http://www.spinics.net/lists/dri-devel/msg86840.html

Quoted 2 lines

hook up with a control endpoint. And then you'll need more quirks to describe what kind of DSI device this is.

Quoted 7 lines
Quoted 2 lines

Could you explain what you meant by this? I.e. describing the kind of DSI device?

Describing the number of lanes, specifying the virtual channel, mode flags, etc. You could probably set the number of lanes and mode flags via the I2C driver, but especially the virtual channel cannot be set because it isn't known to the I2C DT branch of the device.

I agree with the VC part. It could be a DT entry within the i2c client node, but that does make it seem like a quirk. The 'reg' way under the DSI host is definitely better to populate the virtual channel.

Quoted 9 lines
Quoted 5 lines

The dsi device created isn't really a dummy device as such. It's dummy in the sense that there isn't a real dsi driver associated with it. The dsi device is still used to attach to a mipi dsi host, the way normal dsi devices do.

I understand, but I don't see why it has to be instantiated by the I2C driver, that's what I find backwards. There is already a standard way for instantiating DSI devices, why not use it?

I assumed we could either represent the device using an i2c driver, or dsi, but not both. Hence, I came up with this approach.

Quoted 9 lines
Quoted 9 lines
Quoted 8 lines

On the other hand if you properly instantiate the DSI device you can easily write a driver for it, and the driver will set up the correct properties as implied by the compatible string. Once you have that you can easily hook it up to the I2C control interface in whatever way you like, be that an OF graph or just a simple unidirectional link by phandle.

Quoted 8 lines
Quoted 4 lines

With the fused approach you suggested, we would have 2 drivers: one i2c and the other dsi. The i2c client driver would be more or less minimal, preparing an i2c_client device for the dsi driver to use. Is my understanding correct?

Correct. That's kind of similar to the way an HDMI encoder driver would use an I2C adapter to query EDID. The i2c_client device would be a means for the DSI driver to access the control interface.

Okay.

Although, I'm not sure about the HDMI encoder example. An HDMI encoder would read off edid directly from the adapter(with an address specified), it wouldn't need to create an i2c client device. Therefore, an HDMI encoder wouldn't need to have a separate node for i2c in DT.

Quoted 6 lines
Quoted 5 lines

We can do without dummy dsi devices with this method. But, representing a device with 2 DT nodes seems a bit off. We'd also need to compatible strings for the same device, one for the i2c part, and the other for the dsi part.

Quoted 6 lines

I agree that this somewhat stretches the capabilities of device tree. Another alternative I guess would be to not have a compatible string for the I2C device at all (that's technically not valid, I guess) because we really don't need an I2C driver for the device. What we really need is a DSI driver with a means to talk over some I2C bus with some other part of its device.

I think what the driver should 'really' be is a bit subjective, and can vary based on what the buses are used for in the device. For the Toshiba chip that Jani mentioned, it tends more towards a DSI driver. Whereas, for an ADV75xx chip, it's closer to an I2C driver since only I2C can be used to configure the chip registers.

Although, I agree with the point you made about the DSI bus here:

"and the DSI interface may even be crippled, but the device is still addressable from the DSI host controller, if for nothing else than for routing the video stream."

The fact that the data on the DSI bus contains routing information (i.e, virtual channel number) always gives it some 'control' aspect.

Quoted 9 lines
Quoted 6 lines

From an adv75xx driver perspective, it should also support the ADV7511
chip, which is a RGB/DPI to HDMI encoder. For adv7511, we don't need a DSI DT node. It would be a bit inconsistent to have the bindings require both DSI and I2C nodes for one chip, and only I2C node for the other, with both chips being supported by the same driver.

Why would that be inconsistent? That sounds like the most accurate representation of the hardware to me.

Inconsistent wasn't the right term. I should have used 'uncommon' :) It's common for two chips of the same family to have a different set optional properties in DT, but it's not common for two chips of the same family to be represented by a different number of devices in DT.

Quoted 3 lines

I don't have an issue with the fused approach you suggested, as long as people are okay with the DT parts. Especially the part of needing 2 compatible strings in the DT.

I implemented the ADV7533 driver with the approach you suggested above (2 drivers for 2 different components of the chip). I posted it out just a while back (with you in loop).

The DT node with this apporach would look like this:

https://github.com/boddob/linux/blob/c24cbf63a6998d00095c10122ce5e37b764c7dba/arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi#L162

The main irritant with the '2 driver' approach is that we need to share the per-device driver data with them. For ADV7533, I've made the i2c driver allocate driver data (struct adv7511).

The dsi driver gets the driver data in the following way:

- The i2c driver sets the driver data as its client data using i2c_set_clientdata()
- Parse the i2c-control phandle to get the corresponding i2c client.
- Extract the adv7511 struct by getting i2c_get_clientdata()

This way of getting the same driver data is a bit strange, but it works. For this, we do need to ensure that the dsi driver defers as long as the i2c driver isn't probed.

Quoted 7 lines

I've now implemented both approaches for the driver. The first using a dummy dsi device, and this one using 2 drivers (with both being represented in DT). The advantage of the latter is that we don't need to create any dummy device stuff, the disadvantage is that DT is a bit uncommon.

Can we now come to a conclusion on what approach is better?

DSI by design is data bus which can be used additionally as a control bus, but in this particular case it is purely data bus. So of-graph bindings seem to be better choice. As already Lucas Stach said DT hierarchy should describe control buses and of-graph bindings should describe data bus. Argument that hw has two interfaces does not seem to be valid here - it has only one control interface. The other one is only for data, representing every data interface using DT hierarchy would lead to inflation of pseudo devices.

On the other side I do not see dummy device approach ideal solution, I guess lightweight framework providing DSI hosts detached from Linux device model could work better here.
The only problem here is that it should coexist somehow with dsi bus used to control devices. Anyway implementing it shouldn't be hard, question is if it would be eventually accepted :) I guess we can live for now with dummy devs.

Quoted 5 lines
Quoted 2 lines

Summarizing I would prefer version with dummy devices, as it seems more compatible with DT design.

Thanks for the feedback. I'll spin a newer version of the dummy dsi dev patches after waiting for some more comments.

Let's wait for someone from the device tree maintainers to comment instead of going around in circles.

Thierry

Signature · 6 lines
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel
#24 lore raw

v2 cover drm/dsi: DSI for devices with different control bus

In reply to Archit Taneja

We are currently restricted when it comes to supporting DSI on devices that have a non-DSI control bus. For example, DSI encoder chips are available in the market that are configured via i2c. Configuring their registers via DSI bus is either optional or not available at all.

These devices still need to pass DSI parameters (data lanes, mode flags etc) to the DSI host they are connected to. We don't have a way to do that at the moment.

After some discussions on the previous RFC[1], we decided to support this by providing additional API in drm_mipi_dsi which lets us create new DSI devices without the need of them to have a DT node.

There are a couple of concerns I have about this patchset which I couldn't figure out a solution to (they are addressed in the individual patches too):

- Matching of non-DT devices: buses like i2c/spi populate id_table in their drivers to perform a match for the non-DT case. Is this something that we should do too?

- Race between host_unregister and device_unregister: The new API provides peripheral drivers to unregister the DSI devices they created by using mipi_dsi_device_unregister. If the dsi host unregisters first, the peripheral driver might have an unregistered device pointer without being aware of it.

Some comments on these would help.

[1]: https://lkml.org/lkml/2015/6/30/42

Archit Taneja (5):
drm/dsi: Refactor device creation
drm/dsi: Try to match non-DT dsi devices
drm/dsi: Check for used channels
drm/dsi: Add routine to unregister dsi device
drm/dsi: Get DSI host by DT device node

 drivers/gpu/drm/drm_mipi_dsi.c | 135 ++++++++++++++++++++++++++++++++---------
 include/drm/drm_mipi_dsi.h     |  27 +++++++++
 2 files changed, 132 insertions(+), 30 deletions(-)
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation
#25 lore raw

RFC v2 1/5 drm/dsi: Refactor device creation

Simplify the mipi dsi device creation process. device_initialize and device_add don't need to be called separately when creating mipi_dsi_device's. Use device_register instead to simplify things.

Create a helper function mipi_dsi_device_new which takes in struct mipi_dsi_device_info and mipi_dsi_host. It clubs the functions mipi_dsi_device_alloc and mipi_dsi_device_add into one.

mipi_dsi_device_info acts as a template to populate the dsi device information. This is populated by of_mipi_dsi_device_add and passed to mipi_dsi_device_new.

Later on, we'll provide mipi_dsi_device_new as a standalone way to create a dsi device not available via DT.

The new device creation process tries to closely follow what's been done in i2c_new_device in i2c-core.

---
 drivers/gpu/drm/drm_mipi_dsi.c | 61 +++++++++++++++++-------------------------
 include/drm/drm_mipi_dsi.h     | 15 +++++++++++
 2 files changed, 40 insertions(+), 36 deletions(-)
drivers/gpu/drm/drm_mipi_dsi.c +25 -36
index 2d5ca8ee..245ecfe 100644
@@ -102,9 +102,18 @@ static const struct device_type mipi_dsi_device_type = {
 	.release = mipi_dsi_dev_release,
 };
 
-static struct mipi_dsi_device *mipi_dsi_device_alloc(struct mipi_dsi_host *host)
+struct mipi_dsi_device *mipi_dsi_device_new(struct mipi_dsi_host *host,
+					    struct mipi_dsi_device_info *info)
 {
 	struct mipi_dsi_device *dsi;
+	struct device *dev = host->dev;
+	int r;
+
+	if (info->reg > 3) {
+		dev_err(dev, "device node has invalid reg property: %u\n",
+			info->reg);
+		return ERR_PTR(-EINVAL);
+	}
 
 	dsi = kzalloc(sizeof(*dsi), GFP_KERNEL);
 	if (!dsi)
@@ -114,26 +123,27 @@ static struct mipi_dsi_device *mipi_dsi_device_alloc(struct mipi_dsi_host *host)
 	dsi->dev.bus = &mipi_dsi_bus_type;
 	dsi->dev.parent = host->dev;
 	dsi->dev.type = &mipi_dsi_device_type;
+	dsi->dev.of_node = info->node;
+	dsi->channel = info->reg;
 
-	device_initialize(&dsi->dev);
-
-	return dsi;
-}
-
-static int mipi_dsi_device_add(struct mipi_dsi_device *dsi)
-{
-	struct mipi_dsi_host *host = dsi->host;
+	dev_set_name(&dsi->dev, "%s.%d", dev_name(host->dev), info->reg);
 
-	dev_set_name(&dsi->dev, "%s.%d", dev_name(host->dev),  dsi->channel);
+	r = device_register(&dsi->dev);
+	if (r) {
+		dev_err(dev, "failed to register device: %d\n", r);
+		kfree(dsi);
+		return ERR_PTR(r);
+	}
 
-	return device_add(&dsi->dev);
+	return dsi;
 }
+EXPORT_SYMBOL(mipi_dsi_device_new);
 
 static struct mipi_dsi_device *
 of_mipi_dsi_device_add(struct mipi_dsi_host *host, struct device_node *node)
 {
-	struct mipi_dsi_device *dsi;
 	struct device *dev = host->dev;
+	struct mipi_dsi_device_info info = { };
 	int ret;
 	u32 reg;
 
@@ -144,31 +154,10 @@ of_mipi_dsi_device_add(struct mipi_dsi_host *host, struct device_node *node)
 		return ERR_PTR(-EINVAL);
 	}
 
-	if (reg > 3) {
-		dev_err(dev, "device node %s has invalid reg property: %u\n",
-			node->full_name, reg);
-		return ERR_PTR(-EINVAL);
-	}
-
-	dsi = mipi_dsi_device_alloc(host);
-	if (IS_ERR(dsi)) {
-		dev_err(dev, "failed to allocate DSI device %s: %ld\n",
-			node->full_name, PTR_ERR(dsi));
-		return dsi;
-	}
-
-	dsi->dev.of_node = of_node_get(node);
-	dsi->channel = reg;
+	info.reg = reg;
+	info.node = of_node_get(node);
 
-	ret = mipi_dsi_device_add(dsi);
-	if (ret) {
-		dev_err(dev, "failed to add DSI device %s: %d\n",
-			node->full_name, ret);
-		kfree(dsi);
-		return ERR_PTR(ret);
-	}
-
-	return dsi;
+	return mipi_dsi_device_new(host, &info);
 }
 
 int mipi_dsi_host_register(struct mipi_dsi_host *host)
include/drm/drm_mipi_dsi.h +15 -0
index f1d8d0d..90f4f3c 100644
@@ -140,6 +140,19 @@ enum mipi_dsi_pixel_format {
 };
 
 /**
+ * struct mipi_dsi_device_info - template for creating a mipi_dsi_device
+ * @reg: DSI virtual channel assigned to peripheral
+ * @node: pointer to OF device node
+ *
+ * This is populated and passed to mipi_dsi_device_new to create a new
+ * DSI device
+ */
+struct mipi_dsi_device_info {
+	u32 reg;
+	struct device_node *node;
+};
+
+/**
  * struct mipi_dsi_device - DSI peripheral device
  * @host: DSI host for this peripheral
  * @dev: driver model device node for this peripheral
@@ -174,6 +187,8 @@ ssize_t mipi_dsi_generic_write(struct mipi_dsi_device *dsi, const void *payload,
 ssize_t mipi_dsi_generic_read(struct mipi_dsi_device *dsi, const void *params,
 			      size_t num_params, void *data, size_t size);
 
+struct mipi_dsi_device *mipi_dsi_device_new(struct mipi_dsi_host *host,
+					    struct mipi_dsi_device_info *info);
 /**
  * enum mipi_dsi_dcs_tear_mode - Tearing Effect Output Line mode
  * @MIPI_DSI_DCS_TEAR_MODE_VBLANK: the TE output line consists of V-Blanking
Signature · 7 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel
Reviewed-by on v2 1/5
#26 lore raw

Re: [RFC v2 1/5] drm/dsi: Refactor device creation

Quoted 12 lines · Archit Taneja

Simplify the mipi dsi device creation process. device_initialize and device_add don't need to be called separately when creating mipi_dsi_device's. Use device_register instead to simplify things.

Create a helper function mipi_dsi_device_new which takes in struct mipi_dsi_device_info and mipi_dsi_host. It clubs the functions mipi_dsi_device_alloc and mipi_dsi_device_add into one.

mipi_dsi_device_info acts as a template to populate the dsi device information. This is populated by of_mipi_dsi_device_add and passed to mipi_dsi_device_new.

Quoted 7 lines

Later on, we'll provide mipi_dsi_device_new as a standalone way to create a dsi device not available via DT.

The new device creation process tries to closely follow what's been done in i2c_new_device in i2c-core.

Regards
Andrzej

Quoted 129 lines
---
 drivers/gpu/drm/drm_mipi_dsi.c | 61 +++++++++++++++++-------------------------
 include/drm/drm_mipi_dsi.h     | 15 +++++++++++
 2 files changed, 40 insertions(+), 36 deletions(-)
drivers/gpu/drm/drm_mipi_dsi.c +10 -1
index 2d5ca8ee..245ecfe 100644
@@ -102,9 +102,18 @@ static const struct device_type mipi_dsi_device_type = {
 	.release = mipi_dsi_dev_release,
 };
 
-static struct mipi_dsi_device *mipi_dsi_device_alloc(struct mipi_dsi_host *host)
+struct mipi_dsi_device *mipi_dsi_device_new(struct mipi_dsi_host *host,
+					    struct mipi_dsi_device_info *info)
 {
 	struct mipi_dsi_device *dsi;
+	struct device *dev = host->dev;
+	int r;
 
+
+	if (info->reg > 3) {
+		dev_err(dev, "device node has invalid reg property: %u\n",
+			info->reg);
+		return ERR_PTR(-EINVAL);
+	}
 
 	dsi = kzalloc(sizeof(*dsi), GFP_KERNEL);
drivers/gpu/drm/drm_mipi_dsi.c +15 -35
 	if (!dsi)
@@ -114,26 +123,27 @@ static struct mipi_dsi_device *mipi_dsi_device_alloc(struct mipi_dsi_host *host)
 	dsi->dev.bus = &mipi_dsi_bus_type;
 	dsi->dev.parent = host->dev;
 	dsi->dev.type = &mipi_dsi_device_type;
+	dsi->dev.of_node = info->node;
+	dsi->channel = info->reg;
 
-	device_initialize(&dsi->dev);
-
-	return dsi;
-}
-
-static int mipi_dsi_device_add(struct mipi_dsi_device *dsi)
-{
-	struct mipi_dsi_host *host = dsi->host;
+	dev_set_name(&dsi->dev, "%s.%d", dev_name(host->dev), info->reg);
 
-	dev_set_name(&dsi->dev, "%s.%d", dev_name(host->dev),  dsi->channel);
+	r = device_register(&dsi->dev);
+	if (r) {
+		dev_err(dev, "failed to register device: %d\n", r);
+		kfree(dsi);
+		return ERR_PTR(r);
+	}
 
-	return device_add(&dsi->dev);
+	return dsi;
 }
+EXPORT_SYMBOL(mipi_dsi_device_new);
 
 static struct mipi_dsi_device *
 of_mipi_dsi_device_add(struct mipi_dsi_host *host, struct device_node *node)
 {
-	struct mipi_dsi_device *dsi;
 	struct device *dev = host->dev;
+	struct mipi_dsi_device_info info = { };
 	int ret;
 	u32 reg;
 
@@ -144,31 +154,10 @@ of_mipi_dsi_device_add(struct mipi_dsi_host *host, struct device_node *node)
 		return ERR_PTR(-EINVAL);
 	}
 
-	if (reg > 3) {
-		dev_err(dev, "device node %s has invalid reg property: %u\n",
-			node->full_name, reg);
-		return ERR_PTR(-EINVAL);
-	}
-
-	dsi = mipi_dsi_device_alloc(host);
-	if (IS_ERR(dsi)) {
-		dev_err(dev, "failed to allocate DSI device %s: %ld\n",
-			node->full_name, PTR_ERR(dsi));
-		return dsi;
-	}
-
-	dsi->dev.of_node = of_node_get(node);
-	dsi->channel = reg;
+	info.reg = reg;
+	info.node = of_node_get(node);
 
-	ret = mipi_dsi_device_add(dsi);
-	if (ret) {
-		dev_err(dev, "failed to add DSI device %s: %d\n",
-			node->full_name, ret);
-		kfree(dsi);
-		return ERR_PTR(ret);
-	}
-
-	return dsi;
+	return mipi_dsi_device_new(host, &info);
 }
 
 int mipi_dsi_host_register(struct mipi_dsi_host *host)
include/drm/drm_mipi_dsi.h +13 -0
index f1d8d0d..90f4f3c 100644
@@ -140,6 +140,19 @@ enum mipi_dsi_pixel_format {
 };
 
 /**
+ * struct mipi_dsi_device_info - template for creating a mipi_dsi_device
+ * @reg: DSI virtual channel assigned to peripheral
+ * @node: pointer to OF device node
+ *
+ * This is populated and passed to mipi_dsi_device_new to create a new
+ * DSI device
+ */
+struct mipi_dsi_device_info {
+	u32 reg;
+	struct device_node *node;
+};
+
+/**
  * struct mipi_dsi_device - DSI peripheral device
  * @host: DSI host for this peripheral
  * @dev: driver model device node for this peripheral

include/drm/drm_mipi_dsi.h ssize_t mipi_dsi_generic_write(struct mipi_dsi_device *dsi, const void *payload, · line 194

Quoted 8 lines
include/drm/drm_mipi_dsi.h +2 -0
@@ -174,6 +187,8 @@ ssize_t mipi_dsi_generic_write(struct mipi_dsi_device *dsi, const void *payload,
 ssize_t mipi_dsi_generic_read(struct mipi_dsi_device *dsi, const void *params,
 			      size_t num_params, void *data, size_t size);
 
+struct mipi_dsi_device *mipi_dsi_device_new(struct mipi_dsi_host *host,
+					    struct mipi_dsi_device_info *info);
 /**
  * enum mipi_dsi_dcs_tear_mode - Tearing Effect Output Line mode
  * @MIPI_DSI_DCS_TEAR_MODE_VBLANK: the TE output line consists of V-Blanking

_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel

#27 lore raw

RFC v2 2/5 drm/dsi: Try to match non-DT dsi devices

In reply to Archit Taneja

Add a device name field in mipi_dsi_device. This name is different from the actual dev name (which is of the format "hostname.reg"). When the device is created via DT, this name is set to the modalias string. In the non-DT case, the driver creating the DSI device provides the name by populating a filed in mipi_dsi_device_info.

Matching for DT case would be as it was before. For the non-DT case, we compare the device and driver names. Matching by comparing driver and device names isn't the best thing to do. I'd appreciate some suggestions here.

Other buses (like i2c/spi) perform a non-DT match by comparing the device name and entries in the driver's id_table. The id_table structs for different buses are defined in "include/linux/mod_devicetable.h", I didn't want to touch that for now.

---
 drivers/gpu/drm/drm_mipi_dsi.c | 29 ++++++++++++++++++++++++++++-
 include/drm/drm_mipi_dsi.h     |  8 ++++++++
 2 files changed, 36 insertions(+), 1 deletion(-)
drivers/gpu/drm/drm_mipi_dsi.c +28 -1
index 245ecfe..46ee515 100644
@@ -45,9 +45,30 @@
  * subset of the MIPI DCS command set.
  */
 
+static const struct device_type mipi_dsi_device_type;
+
 static int mipi_dsi_device_match(struct device *dev, struct device_driver *drv)
 {
-	return of_driver_match_device(dev, drv);
+	struct mipi_dsi_device *dsi;
+
+	if (dev->type == &mipi_dsi_device_type)
+		dsi = to_mipi_dsi_device(dev);
+	else
+		return 0;
+
+	/* Attempt OF style match */
+	if (of_driver_match_device(dev, drv))
+		return 1;
+
+	/*
+	 * Try to compare dsi device and driver names. If this matching approach
+	 * isn't strong, we'd probably want the dsi drivers to populate the
+	 * id_table field and use that instead
+	 */
+	if (!strcmp(dsi->name, drv->name))
+		return 1;
+
+	return 0;
 }
 
 static const struct dev_pm_ops mipi_dsi_device_pm_ops = {
@@ -125,6 +146,7 @@ struct mipi_dsi_device *mipi_dsi_device_new(struct mipi_dsi_host *host,
 	dsi->dev.type = &mipi_dsi_device_type;
 	dsi->dev.of_node = info->node;
 	dsi->channel = info->reg;
+	strlcpy(dsi->name, info->name, sizeof(dsi->name));
 
 	dev_set_name(&dsi->dev, "%s.%d", dev_name(host->dev), info->reg);
 
@@ -147,6 +169,11 @@ of_mipi_dsi_device_add(struct mipi_dsi_host *host, struct device_node *node)
 	int ret;
 	u32 reg;
 
+	if (of_modalias_node(node, info.name, sizeof(info.name)) < 0) {
+		dev_err(dev, "modalias failure on %s\n", node->full_name);
+		return ERR_PTR(-EINVAL);
+	}
+
 	ret = of_property_read_u32(node, "reg", &reg);
 	if (ret) {
 		dev_err(dev, "device node %s has no valid reg property: %d\n",
include/drm/drm_mipi_dsi.h +8 -0
index 90f4f3c..93dec7b 100644
@@ -139,8 +139,11 @@ enum mipi_dsi_pixel_format {
 	MIPI_DSI_FMT_RGB565,
 };
 
+#define DSI_DEV_NAME_SIZE		20
+
 /**
  * struct mipi_dsi_device_info - template for creating a mipi_dsi_device
+ * @name: name of the dsi peripheral
  * @reg: DSI virtual channel assigned to peripheral
  * @node: pointer to OF device node
  *
@@ -148,14 +151,17 @@ enum mipi_dsi_pixel_format {
  * DSI device
  */
 struct mipi_dsi_device_info {
+	char name[DSI_DEV_NAME_SIZE];
 	u32 reg;
 	struct device_node *node;
 };
 
+
 /**
  * struct mipi_dsi_device - DSI peripheral device
  * @host: DSI host for this peripheral
  * @dev: driver model device node for this peripheral
+ * @name: name of the dsi peripheral
  * @channel: virtual channel assigned to the peripheral
  * @format: pixel format for video mode
  * @lanes: number of active data lanes
@@ -165,6 +171,8 @@ struct mipi_dsi_device {
 	struct mipi_dsi_host *host;
 	struct device dev;
 
+	char name[DSI_DEV_NAME_SIZE];
+
 	unsigned int channel;
 	unsigned int lanes;
 	enum mipi_dsi_pixel_format format;
Signature · 7 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel
Reviewed-by on v2 2/5
#28 lore raw

Re: [RFC v2 2/5] drm/dsi: Try to match non-DT dsi devices

Quoted 11 lines · Archit Taneja

Add a device name field in mipi_dsi_device. This name is different from the actual dev name (which is of the format "hostname.reg"). When the device is created via DT, this name is set to the modalias string. In the non-DT case, the driver creating the DSI device provides the name by populating a filed in mipi_dsi_device_info.

Matching for DT case would be as it was before. For the non-DT case, we compare the device and driver names. Matching by comparing driver and device names isn't the best thing to do. I'd appreciate some suggestions here.

Quoted 6 lines

Other buses (like i2c/spi) perform a non-DT match by comparing the device name and entries in the driver's id_table. The id_table structs for different buses are defined in "include/linux/mod_devicetable.h", I didn't want to touch that for now.

Beside small comments below.

Quoted 78 lines
---
 drivers/gpu/drm/drm_mipi_dsi.c | 29 ++++++++++++++++++++++++++++-
 include/drm/drm_mipi_dsi.h     |  8 ++++++++
 2 files changed, 36 insertions(+), 1 deletion(-)
drivers/gpu/drm/drm_mipi_dsi.c +28 -1
index 245ecfe..46ee515 100644
@@ -45,9 +45,30 @@
  * subset of the MIPI DCS command set.
  */
 
+static const struct device_type mipi_dsi_device_type;
+
 static int mipi_dsi_device_match(struct device *dev, struct device_driver *drv)
 {
-	return of_driver_match_device(dev, drv);
+	struct mipi_dsi_device *dsi;
+
+	if (dev->type == &mipi_dsi_device_type)
+		dsi = to_mipi_dsi_device(dev);
+	else
+		return 0;
+
+	/* Attempt OF style match */
+	if (of_driver_match_device(dev, drv))
+		return 1;
+
+	/*
+	 * Try to compare dsi device and driver names. If this matching approach
+	 * isn't strong, we'd probably want the dsi drivers to populate the
+	 * id_table field and use that instead
+	 */
+	if (!strcmp(dsi->name, drv->name))
+		return 1;
+
+	return 0;
 }
 
 static const struct dev_pm_ops mipi_dsi_device_pm_ops = {
@@ -125,6 +146,7 @@ struct mipi_dsi_device *mipi_dsi_device_new(struct mipi_dsi_host *host,
 	dsi->dev.type = &mipi_dsi_device_type;
 	dsi->dev.of_node = info->node;
 	dsi->channel = info->reg;
+	strlcpy(dsi->name, info->name, sizeof(dsi->name));
 
 	dev_set_name(&dsi->dev, "%s.%d", dev_name(host->dev), info->reg);
 
@@ -147,6 +169,11 @@ of_mipi_dsi_device_add(struct mipi_dsi_host *host, struct device_node *node)
 	int ret;
 	u32 reg;
 
+	if (of_modalias_node(node, info.name, sizeof(info.name)) < 0) {
+		dev_err(dev, "modalias failure on %s\n", node->full_name);
+		return ERR_PTR(-EINVAL);
+	}
+
 	ret = of_property_read_u32(node, "reg", &reg);
 	if (ret) {
 		dev_err(dev, "device node %s has no valid reg property: %d\n",
include/drm/drm_mipi_dsi.h +3 -0
index 90f4f3c..93dec7b 100644
@@ -139,8 +139,11 @@ enum mipi_dsi_pixel_format {
 	MIPI_DSI_FMT_RGB565,
 };
 
+#define DSI_DEV_NAME_SIZE		20
+
 /**
  * struct mipi_dsi_device_info - template for creating a mipi_dsi_device
+ * @name: name of the dsi peripheral
  * @reg: DSI virtual channel assigned to peripheral
  * @node: pointer to OF device node
  *

include/drm/drm_mipi_dsi.h enum mipi_dsi_pixel_format { · line 154

Quoted 4 lines
include/drm/drm_mipi_dsi.h +1 -0
@@ -148,14 +151,17 @@ enum mipi_dsi_pixel_format {
  * DSI device
  */
 struct mipi_dsi_device_info {
+	char name[DSI_DEV_NAME_SIZE];

I wonder if it shouldn't be called type as in case of i2c, but no strong feelings.

include/drm/drm_mipi_dsi.h enum mipi_dsi_pixel_format { · line 159

Quoted 5 lines
include/drm/drm_mipi_dsi.h +1 -0
 	u32 reg;
 	struct device_node *node;
 };
 
+

Empty line.

Quoted 9 lines
include/drm/drm_mipi_dsi.h +1 -0
 /**
  * struct mipi_dsi_device - DSI peripheral device
  * @host: DSI host for this peripheral
  * @dev: driver model device node for this peripheral
+ * @name: name of the dsi peripheral
  * @channel: virtual channel assigned to the peripheral
  * @format: pixel format for video mode
  * @lanes: number of active data lanes

include/drm/drm_mipi_dsi.h struct mipi_dsi_device { · line 175

Quoted 5 lines
include/drm/drm_mipi_dsi.h +2 -0
@@ -165,6 +171,8 @@ struct mipi_dsi_device {
 	struct mipi_dsi_host *host;
 	struct device dev;
 
+	char name[DSI_DEV_NAME_SIZE];
+

This empty line can be also removed.

Regards
Andrzej

include/drm/drm_mipi_dsi.h struct mipi_dsi_device { · line 178

Quoted 3 lines
include/drm/drm_mipi_dsi.h +0 -0
 	unsigned int channel;
 	unsigned int lanes;
 	enum mipi_dsi_pixel_format format;

_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel

#29 lore raw

Re: [RFC v2 2/5] drm/dsi: Try to match non-DT dsi devices

Quoted 91 lines · Andrzej Hajda
Quoted 11 lines · Archit Taneja

Add a device name field in mipi_dsi_device. This name is different from the actual dev name (which is of the format "hostname.reg"). When the device is created via DT, this name is set to the modalias string. In the non-DT case, the driver creating the DSI device provides the name by populating a filed in mipi_dsi_device_info.

Matching for DT case would be as it was before. For the non-DT case, we compare the device and driver names. Matching by comparing driver and device names isn't the best thing to do. I'd appreciate some suggestions here.

Quoted 6 lines

Other buses (like i2c/spi) perform a non-DT match by comparing the device name and entries in the driver's id_table. The id_table structs for different buses are defined in "include/linux/mod_devicetable.h", I didn't want to touch that for now.

Beside small comments below.

Quoted 69 lines
---
  drivers/gpu/drm/drm_mipi_dsi.c | 29 ++++++++++++++++++++++++++++-
  include/drm/drm_mipi_dsi.h     |  8 ++++++++
  2 files changed, 36 insertions(+), 1 deletion(-)
drivers/gpu/drm/drm_mipi_dsi.c +28 -1
index 245ecfe..46ee515 100644
@@ -45,9 +45,30 @@
   * subset of the MIPI DCS command set.
   */
 
+static const struct device_type mipi_dsi_device_type;
+
  static int mipi_dsi_device_match(struct device *dev, struct device_driver *drv)
  {
-	return of_driver_match_device(dev, drv);
+	struct mipi_dsi_device *dsi;
+
+	if (dev->type == &mipi_dsi_device_type)
+		dsi = to_mipi_dsi_device(dev);
+	else
+		return 0;
+
+	/* Attempt OF style match */
+	if (of_driver_match_device(dev, drv))
+		return 1;
+
+	/*
+	 * Try to compare dsi device and driver names. If this matching approach
+	 * isn't strong, we'd probably want the dsi drivers to populate the
+	 * id_table field and use that instead
+	 */
+	if (!strcmp(dsi->name, drv->name))
+		return 1;
+
+	return 0;
  }
 
  static const struct dev_pm_ops mipi_dsi_device_pm_ops = {
@@ -125,6 +146,7 @@ struct mipi_dsi_device *mipi_dsi_device_new(struct mipi_dsi_host *host,
  	dsi->dev.type = &mipi_dsi_device_type;
  	dsi->dev.of_node = info->node;
  	dsi->channel = info->reg;
+	strlcpy(dsi->name, info->name, sizeof(dsi->name));
 
  	dev_set_name(&dsi->dev, "%s.%d", dev_name(host->dev), info->reg);
 
@@ -147,6 +169,11 @@ of_mipi_dsi_device_add(struct mipi_dsi_host *host, struct device_node *node)
  	int ret;
  	u32 reg;
 
+	if (of_modalias_node(node, info.name, sizeof(info.name)) < 0) {
+		dev_err(dev, "modalias failure on %s\n", node->full_name);
+		return ERR_PTR(-EINVAL);
+	}
+
  	ret = of_property_read_u32(node, "reg", &reg);
  	if (ret) {
  		dev_err(dev, "device node %s has no valid reg property: %d\n",
include/drm/drm_mipi_dsi.h +0 -0
index 90f4f3c..93dec7b 100644
@@ -139,8 +139,11 @@ enum mipi_dsi_pixel_format {
  	MIPI_DSI_FMT_RGB565,
  };
 
Quoted 15 lines

include/drm/drm_mipi_dsi.h enum mipi_dsi_pixel_format { · line 154

Quoted 13 lines
include/drm/drm_mipi_dsi.h +4 -0
+#define DSI_DEV_NAME_SIZE		20
+
  /**
   * struct mipi_dsi_device_info - template for creating a mipi_dsi_device
+ * @name: name of the dsi peripheral
   * @reg: DSI virtual channel assigned to peripheral
   * @node: pointer to OF device node
   *
@@ -148,14 +151,17 @@ enum mipi_dsi_pixel_format {
   * DSI device
   */
  struct mipi_dsi_device_info {
+	char name[DSI_DEV_NAME_SIZE];

I wonder if it shouldn't be called type as in case of i2c, but no strong feelings.

We could change it to 'type'. It'll be easier for someone to understand what the dsi core is doing by keeping the same nomenclature as in i2c-core.

Quoted 19 lines

include/drm/drm_mipi_dsi.h enum mipi_dsi_pixel_format { · line 159

Quoted 5 lines
include/drm/drm_mipi_dsi.h +1 -0
  	u32 reg;
  	struct device_node *node;
  };
 
+

Empty line.

Quoted 12 lines
include/drm/drm_mipi_dsi.h +1 -0
  /**
   * struct mipi_dsi_device - DSI peripheral device
   * @host: DSI host for this peripheral
   * @dev: driver model device node for this peripheral
+ * @name: name of the dsi peripheral
   * @channel: virtual channel assigned to the peripheral
   * @format: pixel format for video mode
   * @lanes: number of active data lanes
@@ -165,6 +171,8 @@ struct mipi_dsi_device {
  	struct mipi_dsi_host *host;
  	struct device dev;
 
Quoted 4 lines

include/drm/drm_mipi_dsi.h struct mipi_dsi_device { · line 175

Quoted 2 lines
include/drm/drm_mipi_dsi.h +2 -0
+	char name[DSI_DEV_NAME_SIZE];
+

This empty line can be also removed.

Will remove these.

Thanks,
Archit

Quoted 12 lines

Regards
Andrzej

include/drm/drm_mipi_dsi.h struct mipi_dsi_device { · line 178

Quoted 3 lines
include/drm/drm_mipi_dsi.h +0 -0
  	unsigned int channel;
  	unsigned int lanes;
  	enum mipi_dsi_pixel_format format;

--
To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html

Signature · 5 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel
#30 lore raw

RFC v2 3/5 drm/dsi: Check for used channels

In reply to Archit Taneja

We don't check whether a previously registered mipi_dsi_device under the same host shares the same virtual channel.

Before registering, check if any of the registered devices doesn't already have the same virtual channel.

This wasn't crucial when all the devices under a host were populated via DT. Now that we also support creating devices manually, we could end up in a situation where a driver tries to create a device with a virtual channel already taken by a device populated in DT.

---
 drivers/gpu/drm/drm_mipi_dsi.c | 26 ++++++++++++++++++++++++--
 1 file changed, 24 insertions(+), 2 deletions(-)
drivers/gpu/drm/drm_mipi_dsi.c +24 -2
index 46ee515..db6130a 100644
@@ -123,6 +123,22 @@ static const struct device_type mipi_dsi_device_type = {
 	.release = mipi_dsi_dev_release,
 };
 
+static int __dsi_check_chan_busy(struct device *dev, void *data)
+{
+	struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev);
+	u32 reg = *(u32 *) data;
+
+	if (dsi && dsi->channel == reg)
+		return -EBUSY;
+
+	return 0;
+}
+
+static int mipi_dsi_check_chan_busy(struct mipi_dsi_host *host, u32 reg)
+{
+	return device_for_each_child(host->dev, &reg, __dsi_check_chan_busy);
+}
+
 struct mipi_dsi_device *mipi_dsi_device_new(struct mipi_dsi_host *host,
 					    struct mipi_dsi_device_info *info)
 {
@@ -150,14 +166,20 @@ struct mipi_dsi_device *mipi_dsi_device_new(struct mipi_dsi_host *host,
 
 	dev_set_name(&dsi->dev, "%s.%d", dev_name(host->dev), info->reg);
 
+	r = mipi_dsi_check_chan_busy(host, info->reg);
+	if (r)
+		goto err;
+
 	r = device_register(&dsi->dev);
 	if (r) {
 		dev_err(dev, "failed to register device: %d\n", r);
-		kfree(dsi);
-		return ERR_PTR(r);
+		goto err;
 	}
 
 	return dsi;
+err:
+	kfree(dsi);
+	return ERR_PTR(r);
 }
 EXPORT_SYMBOL(mipi_dsi_device_new);
 
Signature · 7 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel
Reviewed-by on v2 3/5
#31 lore raw

Re: [RFC v2 3/5] drm/dsi: Check for used channels

Quoted 6 lines · Archit Taneja

We don't check whether a previously registered mipi_dsi_device under the same host shares the same virtual channel.

Before registering, check if any of the registered devices doesn't already have the same virtual channel.

Quoted 6 lines

This wasn't crucial when all the devices under a host were populated via DT. Now that we also support creating devices manually, we could end up in a situation where a driver tries to create a device with a virtual channel already taken by a device populated in DT.

Beside few non-blcking nitpicks.

Quoted 9 lines
---
 drivers/gpu/drm/drm_mipi_dsi.c | 26 ++++++++++++++++++++++++--
 1 file changed, 24 insertions(+), 2 deletions(-)
drivers/gpu/drm/drm_mipi_dsi.c +0 -0
index 46ee515..db6130a 100644

drivers/gpu/drm/drm_mipi_dsi.c static const struct device_type mipi_dsi_device_type = { · line 131

Quoted 9 lines
drivers/gpu/drm/drm_mipi_dsi.c +6 -0
@@ -123,6 +123,22 @@ static const struct device_type mipi_dsi_device_type = {
 	.release = mipi_dsi_dev_release,
 };
 
+static int __dsi_check_chan_busy(struct device *dev, void *data)
+{
+	struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev);
+	u32 reg = *(u32 *) data;
+
+	if (dsi && dsi->channel == reg)

Maybe simpler would be:

    u32 *reg = data;
 
    if (dsi && dsi->channel == *reg)
Quoted 14 lines
drivers/gpu/drm/drm_mipi_dsi.c +10 -0
+		return -EBUSY;
+
+	return 0;
+}
+
+static int mipi_dsi_check_chan_busy(struct mipi_dsi_host *host, u32 reg)
+{
+	return device_for_each_child(host->dev, &reg, __dsi_check_chan_busy);
+}
+
 struct mipi_dsi_device *mipi_dsi_device_new(struct mipi_dsi_host *host,
 					    struct mipi_dsi_device_info *info)
 {

drivers/gpu/drm/drm_mipi_dsi.c struct mipi_dsi_device *mipi_dsi_device_new(struct mipi_dsi_host *host, · line 169

Quoted 4 lines
drivers/gpu/drm/drm_mipi_dsi.c +1 -0
@@ -150,14 +166,20 @@ struct mipi_dsi_device *mipi_dsi_device_new(struct mipi_dsi_host *host,
 
 	dev_set_name(&dsi->dev, "%s.%d", dev_name(host->dev), info->reg);
 
+	r = mipi_dsi_check_chan_busy(host, info->reg);

I know this r variable was introduced in the 1st patch, but if you will send next iteration
consider replacing it with ret, looks more readable and follows file convention :)

Regards
Andrzej

Quoted 18 lines
drivers/gpu/drm/drm_mipi_dsi.c +7 -2
+	if (r)
+		goto err;
+
 	r = device_register(&dsi->dev);
 	if (r) {
 		dev_err(dev, "failed to register device: %d\n", r);
-		kfree(dsi);
-		return ERR_PTR(r);
+		goto err;
 	}
 
 	return dsi;
+err:
+	kfree(dsi);
+	return ERR_PTR(r);
 }
 EXPORT_SYMBOL(mipi_dsi_device_new);
 
#32 lore raw

Re: [RFC v2 3/5] drm/dsi: Check for used channels

Quoted 37 lines · Andrzej Hajda
Quoted 6 lines · Archit Taneja

We don't check whether a previously registered mipi_dsi_device under the same host shares the same virtual channel.

Before registering, check if any of the registered devices doesn't already have the same virtual channel.

Quoted 6 lines

This wasn't crucial when all the devices under a host were populated via DT. Now that we also support creating devices manually, we could end up in a situation where a driver tries to create a device with a virtual channel already taken by a device populated in DT.

Beside few non-blcking nitpicks.

Quoted 9 lines
---
  drivers/gpu/drm/drm_mipi_dsi.c | 26 ++++++++++++++++++++++++--
  1 file changed, 24 insertions(+), 2 deletions(-)
drivers/gpu/drm/drm_mipi_dsi.c +0 -0
index 46ee515..db6130a 100644

drivers/gpu/drm/drm_mipi_dsi.c static const struct device_type mipi_dsi_device_type = { · line 131

Quoted 9 lines
drivers/gpu/drm/drm_mipi_dsi.c +6 -0
@@ -123,6 +123,22 @@ static const struct device_type mipi_dsi_device_type = {
  	.release = mipi_dsi_dev_release,
  };
 
+static int __dsi_check_chan_busy(struct device *dev, void *data)
+{
+	struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev);
+	u32 reg = *(u32 *) data;
+
+	if (dsi && dsi->channel == reg)

Maybe simpler would be:

Quoted 4 lines
     u32 *reg = data;

     if (dsi && dsi->channel == *reg)

This is better. I'll change it to this.

Quoted 17 lines
Quoted 17 lines
drivers/gpu/drm/drm_mipi_dsi.c +10 -0
+		return -EBUSY;
+
+	return 0;
+}
+
+static int mipi_dsi_check_chan_busy(struct mipi_dsi_host *host, u32 reg)
+{
+	return device_for_each_child(host->dev, &reg, __dsi_check_chan_busy);
+}
+
  struct mipi_dsi_device *mipi_dsi_device_new(struct mipi_dsi_host *host,
  					    struct mipi_dsi_device_info *info)
  {
@@ -150,14 +166,20 @@ struct mipi_dsi_device *mipi_dsi_device_new(struct mipi_dsi_host *host,
 
Quoted 7 lines

drivers/gpu/drm/drm_mipi_dsi.c struct mipi_dsi_device *mipi_dsi_device_new(struct mipi_dsi_host *host, · line 169

Quoted 3 lines
drivers/gpu/drm/drm_mipi_dsi.c +1 -0
  	dev_set_name(&dsi->dev, "%s.%d", dev_name(host->dev), info->reg);
 
+	r = mipi_dsi_check_chan_busy(host, info->reg);

I know this r variable was introduced in the 1st patch, but if you will send next iteration
consider replacing it with ret, looks more readable and follows file convention :)

I'll probably end up sending another iteration (or more). I'll change the name.

Thanks,
Archit

Quoted 29 lines

Regards
Andrzej

Quoted 8 lines
drivers/gpu/drm/drm_mipi_dsi.c +3 -2
+	if (r)
+		goto err;
+
  	r = device_register(&dsi->dev);
  	if (r) {
  		dev_err(dev, "failed to register device: %d\n", r);
-		kfree(dsi);
-		return ERR_PTR(r);

drivers/gpu/drm/drm_mipi_dsi.c struct mipi_dsi_device *mipi_dsi_device_new(struct mipi_dsi_host *host, · line 185

Quoted 10 lines
drivers/gpu/drm/drm_mipi_dsi.c +4 -0
+		goto err;
  	}
 
  	return dsi;
+err:
+	kfree(dsi);
+	return ERR_PTR(r);
  }
  EXPORT_SYMBOL(mipi_dsi_device_new);
 

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/

Signature · 5 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel
#33 lore raw

RFC v2 4/5 drm/dsi: Add routine to unregister dsi device

In reply to Archit Taneja

A driver calling mipi_dsi_device_new might want to unregister the device once it's done. It might also require it in an error handling path in case something didn't go right.

When the dsi host driver calls mipi_dsi_host_unregister, the devices created by both DT and and without DT will be removed. This does leave the possibility of the host removing the dsi device without the peripheral driver being aware of it. I don't know a good way to solve this. Some suggestions here would be of help too.

---
 drivers/gpu/drm/drm_mipi_dsi.c | 7 +++++++
 include/drm/drm_mipi_dsi.h     | 2 ++
 2 files changed, 9 insertions(+)
drivers/gpu/drm/drm_mipi_dsi.c +7 -0
index db6130a..cbb7373 100644
@@ -183,6 +183,13 @@ err:
 }
 EXPORT_SYMBOL(mipi_dsi_device_new);
 
+void mipi_dsi_device_unregister(struct mipi_dsi_device *dsi)
+{
+	if (dsi)
+		device_unregister(&dsi->dev);
+}
+EXPORT_SYMBOL(mipi_dsi_device_unregister);
+
 static struct mipi_dsi_device *
 of_mipi_dsi_device_add(struct mipi_dsi_host *host, struct device_node *node)
 {
include/drm/drm_mipi_dsi.h +2 -0
index 93dec7b..68f49f4 100644
@@ -197,6 +197,8 @@ ssize_t mipi_dsi_generic_read(struct mipi_dsi_device *dsi, const void *params,
 
 struct mipi_dsi_device *mipi_dsi_device_new(struct mipi_dsi_host *host,
 					    struct mipi_dsi_device_info *info);
+void mipi_dsi_device_unregister(struct mipi_dsi_device *dsi);
+
 /**
  * enum mipi_dsi_dcs_tear_mode - Tearing Effect Output Line mode
  * @MIPI_DSI_DCS_TEAR_MODE_VBLANK: the TE output line consists of V-Blanking
Signature · 7 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel
#34 lore raw

Re: [RFC v2 4/5] drm/dsi: Add routine to unregister dsi device

Quoted 9 lines · Archit Taneja

A driver calling mipi_dsi_device_new might want to unregister the device once it's done. It might also require it in an error handling path in case something didn't go right.

When the dsi host driver calls mipi_dsi_host_unregister, the devices created by both DT and and without DT will be removed. This does leave the possibility of the host removing the dsi device without the peripheral driver being aware of it. I don't know a good way to solve this. Some suggestions here would be of help too.

The 2nd paragraph is not relevant here. It is another issue. Some comments about it:
I am not sure, but I guess device should not be removed if it is refcounted properly, it will be just detached from the driver, bus and system (whatever it means:) ).
It does not mean it will be usable and probably some races can occur anyway. I guess i2c and other buses have the same problem, am I right?

Quoted 12 lines
---
 drivers/gpu/drm/drm_mipi_dsi.c | 7 +++++++
 include/drm/drm_mipi_dsi.h     | 2 ++
 2 files changed, 9 insertions(+)
drivers/gpu/drm/drm_mipi_dsi.c +0 -0
index db6130a..cbb7373 100644

drivers/gpu/drm/drm_mipi_dsi.c err: · line 192

Quoted 10 lines
drivers/gpu/drm/drm_mipi_dsi.c +7 -0
@@ -183,6 +183,13 @@ err:
 }
 EXPORT_SYMBOL(mipi_dsi_device_new);
 
+void mipi_dsi_device_unregister(struct mipi_dsi_device *dsi)
+{
+	if (dsi)
+		device_unregister(&dsi->dev);
+}
+EXPORT_SYMBOL(mipi_dsi_device_unregister);
+

I guess NULL check can be removed and the whole function can be inlined.

Regards
Andrzej

Quoted 8 lines
drivers/gpu/drm/drm_mipi_dsi.c +0 -0
 static struct mipi_dsi_device *
 of_mipi_dsi_device_add(struct mipi_dsi_host *host, struct device_node *node)
 {
include/drm/drm_mipi_dsi.h +0 -0
index 93dec7b..68f49f4 100644

include/drm/drm_mipi_dsi.h ssize_t mipi_dsi_generic_read(struct mipi_dsi_device *dsi, const void *params, · line 204

Quoted 8 lines
include/drm/drm_mipi_dsi.h +2 -0
@@ -197,6 +197,8 @@ ssize_t mipi_dsi_generic_read(struct mipi_dsi_device *dsi, const void *params,
 
 struct mipi_dsi_device *mipi_dsi_device_new(struct mipi_dsi_host *host,
 					    struct mipi_dsi_device_info *info);
+void mipi_dsi_device_unregister(struct mipi_dsi_device *dsi);
+
 /**
  * enum mipi_dsi_dcs_tear_mode - Tearing Effect Output Line mode
  * @MIPI_DSI_DCS_TEAR_MODE_VBLANK: the TE output line consists of V-Blanking

_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel

#35 lore raw

Re: [RFC v2 4/5] drm/dsi: Add routine to unregister dsi device

Quoted 5 lines · Andrzej Hajda
Quoted 4 lines · Archit Taneja

A driver calling mipi_dsi_device_new might want to unregister the device once it's done. It might also require it in an error handling path in case something didn't go right.

Quoted 7 lines
Quoted 5 lines

When the dsi host driver calls mipi_dsi_host_unregister, the devices created by both DT and and without DT will be removed. This does leave the possibility of the host removing the dsi device without the peripheral driver being aware of it. I don't know a good way to solve this. Some suggestions here would be of help too.

The 2nd paragraph is not relevant here. It is another issue. Some comments about it:

Yes, it's probably not the best to put it in the commit message of this patch.

Quoted 5 lines

I am not sure, but I guess device should not be removed if it is refcounted properly, it will be just detached from the driver, bus and system (whatever it means:) ).
It does not mean it will be usable and probably some races can occur anyway. I guess i2c and other buses have the same problem, am I right?

I was concerned about one particular sequence:

1) DSI host driver calls mipi_dsi_host_unregister: All dsi devices would be unregistered.

2) dsi device driver calls mipi_dsi_device_unregister: This will try to unregister our dsi device

The problem here is that the device will cease to exist after step (1) itself, because the refcount of our device will never be 2.

mipi_dsi_host_register() will only register devices represented in DT, not the one the drivers register manually.

In other words, the dsi pointer in our driver will point to nothing valid after mipi_dsi_host_unregister is called.

As you said, I guess this exists in other buses too, and it's the drivers job to not use them.

Quoted 16 lines
Quoted 16 lines
---
  drivers/gpu/drm/drm_mipi_dsi.c | 7 +++++++
  include/drm/drm_mipi_dsi.h     | 2 ++
  2 files changed, 9 insertions(+)
drivers/gpu/drm/drm_mipi_dsi.c +0 -0
index db6130a..cbb7373 100644
@@ -183,6 +183,13 @@ err:
  }
  EXPORT_SYMBOL(mipi_dsi_device_new);
 
Quoted 8 lines

drivers/gpu/drm/drm_mipi_dsi.c err: · line 192

Quoted 7 lines
drivers/gpu/drm/drm_mipi_dsi.c +7 -0
+void mipi_dsi_device_unregister(struct mipi_dsi_device *dsi)
+{
+	if (dsi)
+		device_unregister(&dsi->dev);
+}
+EXPORT_SYMBOL(mipi_dsi_device_unregister);
+

I guess NULL check can be removed and the whole function can be inlined.

Yeah, this check won't help anyway.

I think I'll mention that drivers should use this only in error handling paths, and not in the driver's remove() op.

I'll also change this to inlined.

Archit

Quoted 25 lines

Regards
Andrzej

Quoted 8 lines
drivers/gpu/drm/drm_mipi_dsi.c +0 -0
  static struct mipi_dsi_device *
  of_mipi_dsi_device_add(struct mipi_dsi_host *host, struct device_node *node)
  {
include/drm/drm_mipi_dsi.h +0 -0
index 93dec7b..68f49f4 100644

include/drm/drm_mipi_dsi.h ssize_t mipi_dsi_generic_read(struct mipi_dsi_device *dsi, const void *params, · line 204

Quoted 8 lines
include/drm/drm_mipi_dsi.h +2 -0
@@ -197,6 +197,8 @@ ssize_t mipi_dsi_generic_read(struct mipi_dsi_device *dsi, const void *params,
 
  struct mipi_dsi_device *mipi_dsi_device_new(struct mipi_dsi_host *host,
  					    struct mipi_dsi_device_info *info);
+void mipi_dsi_device_unregister(struct mipi_dsi_device *dsi);
+
  /**
   * enum mipi_dsi_dcs_tear_mode - Tearing Effect Output Line mode
   * @MIPI_DSI_DCS_TEAR_MODE_VBLANK: the TE output line consists of V-Blanking

--
To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html

Signature · 1 line
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
#36 lore raw

Re: [RFC v2 4/5] drm/dsi: Add routine to unregister dsi device

Quoted 33 lines · Archit Taneja
Quoted 5 lines · Andrzej Hajda
Quoted 4 lines · Archit Taneja

A driver calling mipi_dsi_device_new might want to unregister the device once it's done. It might also require it in an error handling path in case something didn't go right.

Quoted 7 lines
Quoted 5 lines

When the dsi host driver calls mipi_dsi_host_unregister, the devices created by both DT and and without DT will be removed. This does leave the possibility of the host removing the dsi device without the peripheral driver being aware of it. I don't know a good way to solve this. Some suggestions here would be of help too.

The 2nd paragraph is not relevant here. It is another issue. Some comments about it:

Yes, it's probably not the best to put it in the commit message of this patch.

Quoted 5 lines

I am not sure, but I guess device should not be removed if it is refcounted properly, it will be just detached from the driver, bus and system (whatever it means:) ).
It does not mean it will be usable and probably some races can occur anyway. I guess i2c and other buses have the same problem, am I right?

I was concerned about one particular sequence:

1) DSI host driver calls mipi_dsi_host_unregister: All dsi devices would be unregistered.

2) dsi device driver calls mipi_dsi_device_unregister: This will try to unregister our dsi device

The problem here is that the device will cease to exist after step (1) itself, because the refcount of our device will never be 2.

Quoted 8 lines

mipi_dsi_host_register() will only register devices represented in DT, not the one the drivers register manually.

In other words, the dsi pointer in our driver will point to nothing valid after mipi_dsi_host_unregister is called.

As you said, I guess this exists in other buses too, and it's the drivers job to not use them.

I think the whole problem is due to fact we try to use devices
as interfaces to some bus hosts (DSI in our case), these devices are owned by bus host and we cannot control their lifetime from other code. The best solution IMO would be to create separate lightweight framework as I suggested in previous discussion[1]. It should be cleaner solution without any 'dummy' proxy devices.
But even in this case we would need some callbacks to notify that the provider is about to be removed.

2nd 'solution' is to leave it as is and pretend everything is OK, as in case of other frameworks :)

Maybe it would be possible 3rd solution - we could use probe and remove callbacks from dsi driver to notify clients about adding/removal of dsi device to/from bus. So during dummy dsi dev creation we would provide some callbacks which would be called
by dummy dsi driver probe/remove to notifiy client it can start/stop using dsi device.
This crazy construction probably can work but looks insane :)

[1]: http://www.spinics.net/lists/linux-arm-msm/msg16945.html

Regards
Andrzej

Quoted 55 lines
Quoted 15 lines
Quoted 15 lines
---
  drivers/gpu/drm/drm_mipi_dsi.c | 7 +++++++
  include/drm/drm_mipi_dsi.h     | 2 ++
  2 files changed, 9 insertions(+)
drivers/gpu/drm/drm_mipi_dsi.c +0 -0
index db6130a..cbb7373 100644
@@ -183,6 +183,13 @@ err:
  }
  EXPORT_SYMBOL(mipi_dsi_device_new);
 
Quoted 8 lines

drivers/gpu/drm/drm_mipi_dsi.c err: · line 192

Quoted 7 lines
drivers/gpu/drm/drm_mipi_dsi.c +7 -0
+void mipi_dsi_device_unregister(struct mipi_dsi_device *dsi)
+{
+	if (dsi)
+		device_unregister(&dsi->dev);
+}
+EXPORT_SYMBOL(mipi_dsi_device_unregister);
+

I guess NULL check can be removed and the whole function can be inlined.

Yeah, this check won't help anyway.

I think I'll mention that drivers should use this only in error handling paths, and not in the driver's remove() op.

I'll also change this to inlined.

Archit

Quoted 23 lines

Regards
Andrzej

Quoted 8 lines
drivers/gpu/drm/drm_mipi_dsi.c +0 -0
  static struct mipi_dsi_device *
  of_mipi_dsi_device_add(struct mipi_dsi_host *host, struct device_node *node)
  {
include/drm/drm_mipi_dsi.h +0 -0
index 93dec7b..68f49f4 100644

include/drm/drm_mipi_dsi.h ssize_t mipi_dsi_generic_read(struct mipi_dsi_device *dsi, const void *params, · line 204

Quoted 8 lines
include/drm/drm_mipi_dsi.h +2 -0
@@ -197,6 +197,8 @@ ssize_t mipi_dsi_generic_read(struct mipi_dsi_device *dsi, const void *params,
 
  struct mipi_dsi_device *mipi_dsi_device_new(struct mipi_dsi_host *host,
  					    struct mipi_dsi_device_info *info);
+void mipi_dsi_device_unregister(struct mipi_dsi_device *dsi);
+
  /**
   * enum mipi_dsi_dcs_tear_mode - Tearing Effect Output Line mode
   * @MIPI_DSI_DCS_TEAR_MODE_VBLANK: the TE output line consists of V-Blanking

--
To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html

#37 lore raw

Re: [RFC v2 4/5] drm/dsi: Add routine to unregister dsi device

Quoted 63 lines · Andrzej Hajda
Quoted 33 lines · Archit Taneja
Quoted 5 lines · Andrzej Hajda
Quoted 4 lines · Archit Taneja

A driver calling mipi_dsi_device_new might want to unregister the device once it's done. It might also require it in an error handling path in case something didn't go right.

Quoted 7 lines
Quoted 5 lines

When the dsi host driver calls mipi_dsi_host_unregister, the devices created by both DT and and without DT will be removed. This does leave the possibility of the host removing the dsi device without the peripheral driver being aware of it. I don't know a good way to solve this. Some suggestions here would be of help too.

The 2nd paragraph is not relevant here. It is another issue. Some comments about it:

Yes, it's probably not the best to put it in the commit message of this patch.

Quoted 5 lines

I am not sure, but I guess device should not be removed if it is refcounted properly, it will be just detached from the driver, bus and system (whatever it means:) ).
It does not mean it will be usable and probably some races can occur anyway. I guess i2c and other buses have the same problem, am I right?

I was concerned about one particular sequence:

1) DSI host driver calls mipi_dsi_host_unregister: All dsi devices would be unregistered.

2) dsi device driver calls mipi_dsi_device_unregister: This will try to unregister our dsi device

The problem here is that the device will cease to exist after step (1) itself, because the refcount of our device will never be 2.

Quoted 8 lines

mipi_dsi_host_register() will only register devices represented in DT, not the one the drivers register manually.

In other words, the dsi pointer in our driver will point to nothing valid after mipi_dsi_host_unregister is called.

As you said, I guess this exists in other buses too, and it's the drivers job to not use them.

I think the whole problem is due to fact we try to use devices
as interfaces to some bus hosts (DSI in our case), these devices are owned by bus host and we cannot control their lifetime from other code. The best solution IMO would be to create separate lightweight framework as I suggested in previous discussion[1]. It should be cleaner solution without any 'dummy' proxy devices.
But even in this case we would need some callbacks to notify that the provider is about to be removed.

2nd 'solution' is to leave it as is and pretend everything is OK, as in case of other frameworks :)

Maybe it would be possible 3rd solution - we could use probe and remove callbacks from dsi driver to notify clients about adding/removal of dsi device to/from bus. So during dummy dsi dev creation we would provide some callbacks which would be called
by dummy dsi driver probe/remove to notifiy client it can start/stop using dsi device.
This crazy construction probably can work but looks insane :)

Quoted 1 line

[1]: http://www.spinics.net/lists/linux-arm-msm/msg16945.html

I'm okay with the 2nd solution :). We can add callbacks or a notification mechanism if anyone needs it in the future.

Thanks,
Archit

Quoted 65 lines

Regards
Andrzej

Quoted 23 lines
Quoted 15 lines
Quoted 15 lines
---
   drivers/gpu/drm/drm_mipi_dsi.c | 7 +++++++
   include/drm/drm_mipi_dsi.h     | 2 ++
   2 files changed, 9 insertions(+)
drivers/gpu/drm/drm_mipi_dsi.c +0 -0
index db6130a..cbb7373 100644
@@ -183,6 +183,13 @@ err:
   }
   EXPORT_SYMBOL(mipi_dsi_device_new);
 
Quoted 8 lines

drivers/gpu/drm/drm_mipi_dsi.c err: · line 192

Quoted 7 lines
drivers/gpu/drm/drm_mipi_dsi.c +7 -0
+void mipi_dsi_device_unregister(struct mipi_dsi_device *dsi)
+{
+	if (dsi)
+		device_unregister(&dsi->dev);
+}
+EXPORT_SYMBOL(mipi_dsi_device_unregister);
+

I guess NULL check can be removed and the whole function can be inlined.

Quoted 32 lines

Yeah, this check won't help anyway.

I think I'll mention that drivers should use this only in error handling paths, and not in the driver's remove() op.

I'll also change this to inlined.

Archit

Quoted 23 lines

Regards
Andrzej

Quoted 8 lines
drivers/gpu/drm/drm_mipi_dsi.c +0 -0
   static struct mipi_dsi_device *
   of_mipi_dsi_device_add(struct mipi_dsi_host *host, struct device_node *node)
   {
include/drm/drm_mipi_dsi.h +0 -0
index 93dec7b..68f49f4 100644

include/drm/drm_mipi_dsi.h ssize_t mipi_dsi_generic_read(struct mipi_dsi_device *dsi, const void *params, · line 204

Quoted 8 lines
include/drm/drm_mipi_dsi.h +2 -0
@@ -197,6 +197,8 @@ ssize_t mipi_dsi_generic_read(struct mipi_dsi_device *dsi, const void *params,
 
   struct mipi_dsi_device *mipi_dsi_device_new(struct mipi_dsi_host *host,
   					    struct mipi_dsi_device_info *info);
+void mipi_dsi_device_unregister(struct mipi_dsi_device *dsi);
+
   /**
    * enum mipi_dsi_dcs_tear_mode - Tearing Effect Output Line mode
    * @MIPI_DSI_DCS_TEAR_MODE_VBLANK: the TE output line consists of V-Blanking

--
To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html

--
To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html

Signature · 1 line
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
#38 lore raw

RFC v2 5/5 drm/dsi: Get DSI host by DT device node

In reply to Archit Taneja

mipi_dsi_devices are inherently aware of their host because they share a parent-child hierarchy in the device tree.

Non-dsi drivers that create a dummy dsi device don't have this data. In order to get this information, they require to a phandle to the dsi host in the device tree.

Maintain a list of all the hosts DSI that are currently registered.

This list will be used to find the mipi_dsi_host corresponding to the device_node passed in of_find_mipi_dsi_host_by_node.

---
 drivers/gpu/drm/drm_mipi_dsi.c | 30 ++++++++++++++++++++++++++++++
 include/drm/drm_mipi_dsi.h     |  2 ++
 2 files changed, 32 insertions(+)
drivers/gpu/drm/drm_mipi_dsi.c +30 -0
index cbb7373..c51d73e 100644
@@ -216,6 +216,28 @@ of_mipi_dsi_device_add(struct mipi_dsi_host *host, struct device_node *node)
 	return mipi_dsi_device_new(host, &info);
 }
 
+static DEFINE_MUTEX(host_lock);
+static LIST_HEAD(host_list);
+
+struct mipi_dsi_host *of_find_mipi_dsi_host_by_node(struct device_node *node)
+{
+	struct mipi_dsi_host *host;
+
+	mutex_lock(&host_lock);
+
+	list_for_each_entry(host, &host_list, list) {
+		if (host->dev->of_node == node) {
+			mutex_unlock(&host_lock);
+			return host;
+		}
+	}
+
+	mutex_unlock(&host_lock);
+
+	return NULL;
+}
+EXPORT_SYMBOL(of_find_mipi_dsi_host_by_node);
+
 int mipi_dsi_host_register(struct mipi_dsi_host *host)
 {
 	struct device_node *node;
@@ -227,6 +249,10 @@ int mipi_dsi_host_register(struct mipi_dsi_host *host)
 		of_mipi_dsi_device_add(host, node);
 	}
 
+	mutex_lock(&host_lock);
+	list_add_tail(&host->list, &host_list);
+	mutex_unlock(&host_lock);
+
 	return 0;
 }
 EXPORT_SYMBOL(mipi_dsi_host_register);
@@ -243,6 +269,10 @@ static int mipi_dsi_remove_device_fn(struct device *dev, void *priv)
 void mipi_dsi_host_unregister(struct mipi_dsi_host *host)
 {
 	device_for_each_child(host->dev, NULL, mipi_dsi_remove_device_fn);
+
+	mutex_lock(&host_lock);
+	list_del_init(&host->list);
+	mutex_unlock(&host_lock);
 }
 EXPORT_SYMBOL(mipi_dsi_host_unregister);
 
include/drm/drm_mipi_dsi.h +2 -0
index 68f49f4..15d3068 100644
@@ -100,10 +100,12 @@ struct mipi_dsi_host_ops {
 struct mipi_dsi_host {
 	struct device *dev;
 	const struct mipi_dsi_host_ops *ops;
+	struct list_head list;
 };
 
 int mipi_dsi_host_register(struct mipi_dsi_host *host);
 void mipi_dsi_host_unregister(struct mipi_dsi_host *host);
+struct mipi_dsi_host *of_find_mipi_dsi_host_by_node(struct device_node *node);
 
 /* DSI mode flags */
 
Signature · 7 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel
#39 lore raw

Re: [RFC v2 5/5] drm/dsi: Get DSI host by DT device node

reproduce: make htmldocs

Hi Archit,

[auto build test WARNING on v4.3-rc4 -- if it's inappropriate base, please ignore]

reproduce: make htmldocs

All warnings (new ones prefixed by >>):

drivers/gpu/drm/i915/i915_irq.c:491: warning: No description found for parameter 'dev' drivers/gpu/drm/i915/i915_irq.c:2217: warning: No description found for parameter 'dev' drivers/gpu/drm/i915/i915_irq.c:2397: warning: No description found for parameter 'wedged' drivers/gpu/drm/i915/i915_irq.c:2397: warning: No description found for parameter 'fmt' include/drm/drm_crtc.h:310: warning: No description found for parameter 'mode_blob' include/drm/drm_crtc.h:748: warning: No description found for parameter 'tile_blob_ptr' include/drm/drm_crtc.h:787: warning: No description found for parameter 'rotation' include/drm/drm_crtc.h:883: warning: No description found for parameter 'mutex' include/drm/drm_crtc.h:883: warning: No description found for parameter 'helper_private' include/drm/drm_crtc.h:931: warning: Excess struct/union/enum/typedef member 'base' description in 'drm_bridge' include/drm/drm_crtc.h:1169: warning: No description found for parameter 'tile_idr' include/drm/drm_crtc.h:1169: warning: No description found for parameter 'delayed_event' include/drm/drm_crtc.h:1169: warning: No description found for parameter 'edid_property' include/drm/drm_crtc.h:1169: warning: No description found for parameter 'dpms_property' include/drm/drm_crtc.h:1169: warning: No description found for parameter 'path_property' include/drm/drm_crtc.h:1169: warning: No description found for parameter 'tile_property' include/drm/drm_crtc.h:1169: warning: No description found for parameter 'plane_type_property' include/drm/drm_crtc.h:1169: warning: No description found for parameter 'rotation_property' include/drm/drm_crtc.h:1169: warning: No description found for parameter 'prop_src_x' include/drm/drm_crtc.h:1169: warning: No description found for parameter 'prop_src_y' include/drm/drm_crtc.h:1169: warning: No description found for parameter 'prop_src_w' include/drm/drm_crtc.h:1169: warning: No description found for parameter 'prop_src_h' include/drm/drm_crtc.h:1169: warning: No description found for parameter 'prop_crtc_x' include/drm/drm_crtc.h:1169: warning: No description found for parameter 'prop_crtc_y' include/drm/drm_crtc.h:1169: warning: No description found for parameter 'prop_crtc_w' include/drm/drm_crtc.h:1169: warning: No description found for parameter 'prop_crtc_h' include/drm/drm_crtc.h:1169: warning: No description found for parameter 'prop_fb_id' include/drm/drm_crtc.h:1169: warning: No description found for parameter 'prop_crtc_id' include/drm/drm_crtc.h:1169: warning: No description found for parameter 'prop_active' include/drm/drm_crtc.h:1169: warning: No description found for parameter 'prop_mode_id' include/drm/drm_crtc.h:1169: warning: No description found for parameter 'dvi_i_subconnector_property' include/drm/drm_crtc.h:1169: warning: No description found for parameter 'dvi_i_select_subconnector_property' include/drm/drm_crtc.h:1169: warning: No description found for parameter 'tv_subconnector_property' include/drm/drm_crtc.h:1169: warning: No description found for parameter 'tv_select_subconnector_property' include/drm/drm_crtc.h:1169: warning: No description found for parameter 'tv_mode_property' include/drm/drm_crtc.h:1169: warning: No description found for parameter 'tv_left_margin_property' include/drm/drm_crtc.h:1169: warning: No description found for parameter 'tv_right_margin_property' include/drm/drm_crtc.h:1169: warning: No description found for parameter 'tv_top_margin_property' include/drm/drm_crtc.h:1169: warning: No description found for parameter 'tv_bottom_margin_property' include/drm/drm_crtc.h:1169: warning: No description found for parameter 'tv_brightness_property' include/drm/drm_crtc.h:1169: warning: No description found for parameter 'tv_contrast_property' include/drm/drm_crtc.h:1169: warning: No description found for parameter 'tv_flicker_reduction_property' include/drm/drm_crtc.h:1169: warning: No description found for parameter 'tv_overscan_property' include/drm/drm_crtc.h:1169: warning: No description found for parameter 'tv_saturation_property' include/drm/drm_crtc.h:1169: warning: No description found for parameter 'tv_hue_property' include/drm/drm_crtc.h:1169: warning: No description found for parameter 'scaling_mode_property' include/drm/drm_crtc.h:1169: warning: No description found for parameter 'aspect_ratio_property' include/drm/drm_crtc.h:1169: warning: No description found for parameter 'dirty_info_property' include/drm/drm_crtc.h:1169: warning: No description found for parameter 'suggested_x_property' include/drm/drm_crtc.h:1169: warning: No description found for parameter 'suggested_y_property' include/drm/drm_crtc.h:1169: warning: No description found for parameter 'allow_fb_modifiers'
Warning(include/drm/drm_modeset_lock.h:47): Incorrect use of kernel-doc format: * Contended lock: if a lock is contended you should only call
Warning(include/drm/drm_modeset_lock.h:54): Incorrect use of kernel-doc format: * list of held locks (drm_modeset_lock)
Warning(include/drm/drm_modeset_lock.h:59): Incorrect use of kernel-doc format: * Trylock mode, use only for panic handlers!
Warning(include/drm/drm_modeset_lock.h:74): Incorrect use of kernel-doc format: * modeset lock
Warning(include/drm/drm_modeset_lock.h:79): Incorrect use of kernel-doc format: * Resources that are locked as part of an atomic update are added
include/drm/drm_dp_helper.h:706: warning: No description found for parameter 'i2c_nack_count' include/drm/drm_dp_helper.h:706: warning: No description found for parameter 'i2c_defer_count' drivers/gpu/drm/drm_dp_mst_topology.c:2226: warning: No description found for parameter 'connector' include/drm/drm_dp_mst_helper.h:97: warning: No description found for parameter 'cached_edid' include/drm/drm_dp_mst_helper.h:471: warning: No description found for parameter 'max_dpcd_transaction_bytes' include/drm/drm_dp_mst_helper.h:471: warning: No description found for parameter 'sink_count' include/drm/drm_dp_mst_helper.h:471: warning: No description found for parameter 'total_slots' include/drm/drm_dp_mst_helper.h:471: warning: No description found for parameter 'avail_slots' include/drm/drm_dp_mst_helper.h:471: warning: No description found for parameter 'total_pbn' include/drm/drm_dp_mst_helper.h:471: warning: No description found for parameter 'qlock' include/drm/drm_dp_mst_helper.h:471: warning: No description found for parameter 'tx_msg_downq' include/drm/drm_dp_mst_helper.h:471: warning: No description found for parameter 'tx_msg_upq' include/drm/drm_dp_mst_helper.h:471: warning: No description found for parameter 'tx_down_in_progress' include/drm/drm_dp_mst_helper.h:471: warning: No description found for parameter 'tx_up_in_progress' include/drm/drm_dp_mst_helper.h:471: warning: No description found for parameter 'payload_lock' include/drm/drm_dp_mst_helper.h:471: warning: No description found for parameter 'proposed_vcpis' include/drm/drm_dp_mst_helper.h:471: warning: No description found for parameter 'payloads' include/drm/drm_dp_mst_helper.h:471: warning: No description found for parameter 'payload_mask' include/drm/drm_dp_mst_helper.h:471: warning: No description found for parameter 'vcpi_mask' include/drm/drm_dp_mst_helper.h:471: warning: No description found for parameter 'tx_waitq' include/drm/drm_dp_mst_helper.h:471: warning: No description found for parameter 'work' include/drm/drm_dp_mst_helper.h:471: warning: No description found for parameter 'tx_work' include/drm/drm_dp_mst_helper.h:471: warning: No description found for parameter 'destroy_connector_list' include/drm/drm_dp_mst_helper.h:471: warning: No description found for parameter 'destroy_connector_lock' include/drm/drm_dp_mst_helper.h:471: warning: No description found for parameter 'destroy_connector_work' drivers/gpu/drm/drm_dp_mst_topology.c:2226: warning: No description found for parameter 'connector'

>> include/drm/drm_mipi_dsi.h:104: warning: No description found for parameter 'list'

include/drm/drmP.h:164: warning: No description found for parameter 'fmt'
include/drm/drmP.h:180: warning: No description found for parameter 'fmt'
include/drm/drmP.h:198: warning: No description found for parameter 'fmt'
include/drm/drmP.h:238: warning: No description found for parameter 'dev'
include/drm/drmP.h:238: warning: No description found for parameter 'data'
include/drm/drmP.h:238: warning: No description found for parameter 'file_priv'
include/drm/drmP.h:271: warning: No description found for parameter 'ioctl'
include/drm/drmP.h:271: warning: No description found for parameter '_func'
include/drm/drmP.h:271: warning: No description found for parameter '_flags'
include/drm/drmP.h:344: warning: cannot understand function prototype: 'struct drm_lock_data ' include/drm/drmP.h:397: warning: cannot understand function prototype: 'struct drm_driver ' include/drm/drmP.h:646: warning: cannot understand function prototype: 'struct drm_info_list ' include/drm/drmP.h:656: warning: cannot understand function prototype: 'struct drm_info_node ' include/drm/drmP.h:666: warning: cannot understand function prototype: 'struct drm_minor ' include/drm/drmP.h:712: warning: cannot understand function prototype: 'struct drm_device ' drivers/gpu/drm/i915/i915_irq.c:491: warning: No description found for parameter 'dev' drivers/gpu/drm/i915/i915_irq.c:2217: warning: No description found for parameter 'dev' drivers/gpu/drm/i915/i915_irq.c:2397: warning: No description found for parameter 'wedged' drivers/gpu/drm/i915/i915_irq.c:2397: warning: No description found for parameter 'fmt' drivers/gpu/drm/i915/i915_irq.c:491: warning: No description found for parameter 'dev' drivers/gpu/drm/i915/i915_irq.c:2217: warning: No description found for parameter 'dev' drivers/gpu/drm/i915/i915_irq.c:2397: warning: No description found for parameter 'wedged' drivers/gpu/drm/i915/i915_irq.c:2397: warning: No description found for parameter 'fmt' drivers/gpu/drm/i915/i915_irq.c:491: warning: No description found for parameter 'dev' drivers/gpu/drm/i915/i915_irq.c:2217: warning: No description found for parameter 'dev' drivers/gpu/drm/i915/i915_irq.c:2397: warning: No description found for parameter 'wedged' drivers/gpu/drm/i915/i915_irq.c:2397: warning: No description found for parameter 'fmt' drivers/gpu/drm/i915/i915_irq.c:491: warning: No description found for parameter 'dev' drivers/gpu/drm/i915/i915_irq.c:2217: warning: No description found for parameter 'dev' drivers/gpu/drm/i915/i915_irq.c:2397: warning: No description found for parameter 'wedged' drivers/gpu/drm/i915/i915_irq.c:2397: warning: No description found for parameter 'fmt' drivers/gpu/drm/i915/i915_gem.c:421: warning: No description found for parameter 'dev' drivers/gpu/drm/i915/i915_gem.c:421: warning: No description found for parameter 'data' drivers/gpu/drm/i915/i915_gem.c:421: warning: No description found for parameter 'file' drivers/gpu/drm/i915/i915_gem.c:686: warning: No description found for parameter 'dev' drivers/gpu/drm/i915/i915_gem.c:686: warning: No description found for parameter 'data' drivers/gpu/drm/i915/i915_gem.c:686: warning: No description found for parameter 'file' drivers/gpu/drm/i915/i915_gem.c:767: warning: No description found for parameter 'dev' drivers/gpu/drm/i915/i915_gem.c:767: warning: No description found for parameter 'obj' drivers/gpu/drm/i915/i915_gem.c:767: warning: No description found for parameter 'args' drivers/gpu/drm/i915/i915_gem.c:767: warning: No description found for parameter 'file' drivers/gpu/drm/i915/i915_gem.c:1027: warning: No description found for parameter 'dev' drivers/gpu/drm/i915/i915_gem.c:1027: warning: No description found for parameter 'data' drivers/gpu/drm/i915/i915_gem.c:1027: warning: No description found for parameter 'file' drivers/gpu/drm/i915/i915_gem.c:1192: warning: No description found for parameter 'rps' drivers/gpu/drm/i915/i915_gem.c:1398: warning: No description found for parameter 'req' drivers/gpu/drm/i915/i915_gem.c:1433: warning: No description found for parameter 'obj' drivers/gpu/drm/i915/i915_gem.c:1433: warning: No description found for parameter 'readonly' drivers/gpu/drm/i915/i915_gem.c:1556: warning: No description found for parameter 'dev' drivers/gpu/drm/i915/i915_gem.c:1556: warning: No description found for parameter 'data' drivers/gpu/drm/i915/i915_gem.c:1556: warning: No description found for parameter 'file' drivers/gpu/drm/i915/i915_gem.c:1619: warning: No description found for parameter 'dev' drivers/gpu/drm/i915/i915_gem.c:1619: warning: No description found for parameter 'data' drivers/gpu/drm/i915/i915_gem.c:1619: warning: No description found for parameter 'file' drivers/gpu/drm/i915/i915_gem.c:1664: warning: No description found for parameter 'dev' drivers/gpu/drm/i915/i915_gem.c:1664: warning: No description found for parameter 'data' drivers/gpu/drm/i915/i915_gem.c:1664: warning: No description found for parameter 'file' drivers/gpu/drm/i915/i915_gem.c:1729: warning: No description found for parameter 'vma' drivers/gpu/drm/i915/i915_gem.c:1729: warning: No description found for parameter 'vmf' drivers/gpu/drm/i915/i915_gem.c:1952: warning: No description found for parameter 'dev' drivers/gpu/drm/i915/i915_gem.c:1952: warning: No description found for parameter 'size' drivers/gpu/drm/i915/i915_gem.c:1952: warning: No description found for parameter 'tiling_mode' drivers/gpu/drm/i915/i915_gem.c:1952: warning: No description found for parameter 'fenced' drivers/gpu/drm/i915/i915_gem.c:1952: warning: Excess function parameter 'obj' description in 'i915_gem_get_gtt_alignment' drivers/gpu/drm/i915/i915_gem.c:2815: warning: No description found for parameter 'ring' drivers/gpu/drm/i915/i915_gem.c:2944: warning: No description found for parameter 'obj' drivers/gpu/drm/i915/i915_gem.c:2994: warning: No description found for parameter 'dev' drivers/gpu/drm/i915/i915_gem.c:2994: warning: No description found for parameter 'data' drivers/gpu/drm/i915/i915_gem.c:2994: warning: No description found for parameter 'file' drivers/gpu/drm/i915/i915_gem.c:2994: warning: Excess function parameter 'DRM_IOCTL_ARGS' description in 'i915_gem_wait_ioctl' drivers/gpu/drm/i915/i915_gem.c:3355: warning: No description found for parameter 'obj' drivers/gpu/drm/i915/i915_gem.c:3355: warning: No description found for parameter 'vm' drivers/gpu/drm/i915/i915_gem.c:3355: warning: No description found for parameter 'ggtt_view' drivers/gpu/drm/i915/i915_gem.c:3355: warning: No description found for parameter 'alignment' drivers/gpu/drm/i915/i915_gem.c:3355: warning: No description found for parameter 'flags' drivers/gpu/drm/i915/i915_gem.c:3576: warning: No description found for parameter 'obj' drivers/gpu/drm/i915/i915_gem.c:3576: warning: No description found for parameter 'write' drivers/gpu/drm/i915/i915_gem.c:3858: warning: No description found for parameter 'obj' drivers/gpu/drm/i915/i915_gem.c:3858: warning: No description found for parameter 'write' drivers/gpu/drm/i915/i915_gem.c:4962: warning: No description found for parameter 'old' drivers/gpu/drm/i915/i915_gem.c:4962: warning: No description found for parameter 'new' drivers/gpu/drm/i915/i915_gem.c:4962: warning: No description found for parameter 'frontbuffer_bits' drivers/gpu/drm/i915/intel_lrc.c:782: warning: No description found for parameter 'req' drivers/gpu/drm/i915/intel_lrc.c:782: warning: Excess function parameter 'request' description in 'intel_logical_ring_begin' drivers/gpu/drm/i915/intel_lrc.c:782: warning: Excess function parameter 'ctx' description in 'intel_logical_ring_begin' drivers/gpu/drm/i915/intel_lrc.c:837: warning: No description found for parameter 'params' drivers/gpu/drm/i915/intel_lrc.c:837: warning: Excess function parameter 'dev' description in 'intel_execlists_submission' drivers/gpu/drm/i915/intel_lrc.c:837: warning: Excess function parameter 'file' description in 'intel_execlists_submission' drivers/gpu/drm/i915/intel_lrc.c:837: warning: Excess function parameter 'ring' description in 'intel_execlists_submission' drivers/gpu/drm/i915/intel_lrc.c:837: warning: Excess function parameter 'ctx' description in 'intel_execlists_submission' drivers/gpu/drm/i915/intel_lrc.c:837: warning: Excess function parameter 'batch_obj' description in 'intel_execlists_submission' drivers/gpu/drm/i915/intel_lrc.c:837: warning: Excess function parameter 'exec_start' description in 'intel_execlists_submission' drivers/gpu/drm/i915/intel_lrc.c:837: warning: Excess function parameter 'dispatch_flags' description in 'intel_execlists_submission' drivers/gpu/drm/i915/intel_lrc.c:782: warning: No description found for parameter 'req' drivers/gpu/drm/i915/intel_lrc.c:782: warning: Excess function parameter 'request' description in 'intel_logical_ring_begin' drivers/gpu/drm/i915/intel_lrc.c:782: warning: Excess function parameter 'ctx' description in 'intel_logical_ring_begin' drivers/gpu/drm/i915/intel_lrc.c:837: warning: No description found for parameter 'params' drivers/gpu/drm/i915/intel_lrc.c:837: warning: Excess function parameter 'dev' description in 'intel_execlists_submission' drivers/gpu/drm/i915/intel_lrc.c:837: warning: Excess function parameter 'file' description in 'intel_execlists_submission' drivers/gpu/drm/i915/intel_lrc.c:837: warning: Excess function parameter 'ring' description in 'intel_execlists_submission'

vim +/list +104 include/drm/drm_mipi_dsi.h

068a0023 Andrzej Hajda  2013-12-04   88  		      struct mipi_dsi_device *dsi);
068a0023 Andrzej Hajda  2013-12-04   89  	int (*detach)(struct mipi_dsi_host *host,
068a0023 Andrzej Hajda  2013-12-04   90  		      struct mipi_dsi_device *dsi);
068a0023 Andrzej Hajda  2013-12-04   91  	ssize_t (*transfer)(struct mipi_dsi_host *host,
ed6ff40e Thierry Reding 2014-08-05   92  			    const struct mipi_dsi_msg *msg);
068a0023 Andrzej Hajda  2013-12-04   93  };
068a0023 Andrzej Hajda  2013-12-04   94  
068a0023 Andrzej Hajda  2013-12-04   95  /**
068a0023 Andrzej Hajda  2013-12-04   96   * struct mipi_dsi_host - DSI host device
068a0023 Andrzej Hajda  2013-12-04   97   * @dev: driver model device node for this DSI host
068a0023 Andrzej Hajda  2013-12-04   98   * @ops: DSI host operations
068a0023 Andrzej Hajda  2013-12-04   99   */
068a0023 Andrzej Hajda  2013-12-04  100  struct mipi_dsi_host {
068a0023 Andrzej Hajda  2013-12-04  101  	struct device *dev;
068a0023 Andrzej Hajda  2013-12-04  102  	const struct mipi_dsi_host_ops *ops;
b3e0f8f8 Archit Taneja  2015-10-06  103  	struct list_head list;
068a0023 Andrzej Hajda  2013-12-04 @104  };
068a0023 Andrzej Hajda  2013-12-04  105  
068a0023 Andrzej Hajda  2013-12-04  106  int mipi_dsi_host_register(struct mipi_dsi_host *host);
068a0023 Andrzej Hajda  2013-12-04  107  void mipi_dsi_host_unregister(struct mipi_dsi_host *host);
b3e0f8f8 Archit Taneja  2015-10-06  108  struct mipi_dsi_host *of_find_mipi_dsi_host_by_node(struct device_node *node);
068a0023 Andrzej Hajda  2013-12-04  109  
068a0023 Andrzej Hajda  2013-12-04  110  /* DSI mode flags */
068a0023 Andrzej Hajda  2013-12-04  111  
068a0023 Andrzej Hajda  2013-12-04  112  /* video mode */

:::::: The code at line 104 was first introduced by commit
:::::: 068a00233969833f1ba925e7627797489efd6041 drm: Add MIPI DSI bus support

:::::: TO: Andrzej Hajda <[email protected]>
:::::: CC: Thierry Reding <[email protected]>

---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation

Reviewed-by on v2 5/5
#40 lore raw

Re: [RFC v2 5/5] drm/dsi: Get DSI host by DT device node

In reply to Archit Taneja
Quoted 7 lines · Archit Taneja

mipi_dsi_devices are inherently aware of their host because they share a parent-child hierarchy in the device tree.

Non-dsi drivers that create a dummy dsi device don't have this data. In order to get this information, they require to a phandle to the dsi host in the device tree.

Quoted 6 lines

Maintain a list of all the hosts DSI that are currently registered.

This list will be used to find the mipi_dsi_host corresponding to the device_node passed in of_find_mipi_dsi_host_by_node.

Looks OK, beside lack of documentation, after fixing it you can add

Regards
Andrzej

Quoted 67 lines
---
 drivers/gpu/drm/drm_mipi_dsi.c | 30 ++++++++++++++++++++++++++++++
 include/drm/drm_mipi_dsi.h     |  2 ++
 2 files changed, 32 insertions(+)
drivers/gpu/drm/drm_mipi_dsi.c +30 -0
index cbb7373..c51d73e 100644
@@ -216,6 +216,28 @@ of_mipi_dsi_device_add(struct mipi_dsi_host *host, struct device_node *node)
 	return mipi_dsi_device_new(host, &info);
 }
 
+static DEFINE_MUTEX(host_lock);
+static LIST_HEAD(host_list);
+
+struct mipi_dsi_host *of_find_mipi_dsi_host_by_node(struct device_node *node)
+{
+	struct mipi_dsi_host *host;
+
+	mutex_lock(&host_lock);
+
+	list_for_each_entry(host, &host_list, list) {
+		if (host->dev->of_node == node) {
+			mutex_unlock(&host_lock);
+			return host;
+		}
+	}
+
+	mutex_unlock(&host_lock);
+
+	return NULL;
+}
+EXPORT_SYMBOL(of_find_mipi_dsi_host_by_node);
+
 int mipi_dsi_host_register(struct mipi_dsi_host *host)
 {
 	struct device_node *node;
@@ -227,6 +249,10 @@ int mipi_dsi_host_register(struct mipi_dsi_host *host)
 		of_mipi_dsi_device_add(host, node);
 	}
 
+	mutex_lock(&host_lock);
+	list_add_tail(&host->list, &host_list);
+	mutex_unlock(&host_lock);
+
 	return 0;
 }
 EXPORT_SYMBOL(mipi_dsi_host_register);
@@ -243,6 +269,10 @@ static int mipi_dsi_remove_device_fn(struct device *dev, void *priv)
 void mipi_dsi_host_unregister(struct mipi_dsi_host *host)
 {
 	device_for_each_child(host->dev, NULL, mipi_dsi_remove_device_fn);
+
+	mutex_lock(&host_lock);
+	list_del_init(&host->list);
+	mutex_unlock(&host_lock);
 }
 EXPORT_SYMBOL(mipi_dsi_host_unregister);
 
include/drm/drm_mipi_dsi.h +0 -0
index 68f49f4..15d3068 100644
@@ -100,10 +100,12 @@ struct mipi_dsi_host_ops {
 struct mipi_dsi_host {
 	struct device *dev;

include/drm/drm_mipi_dsi.h struct mipi_dsi_host_ops { · line 111

Quoted 10 lines
include/drm/drm_mipi_dsi.h +2 -0
 	const struct mipi_dsi_host_ops *ops;
+	struct list_head list;
 };
 
 int mipi_dsi_host_register(struct mipi_dsi_host *host);
 void mipi_dsi_host_unregister(struct mipi_dsi_host *host);
+struct mipi_dsi_host *of_find_mipi_dsi_host_by_node(struct device_node *node);
 
 /* DSI mode flags */
 

_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel

#41 lore raw

Re: [RFC v2 5/5] drm/dsi: Get DSI host by DT device node

Quoted 10 lines · Andrzej Hajda
Quoted 9 lines · Archit Taneja

mipi_dsi_devices are inherently aware of their host because they share a parent-child hierarchy in the device tree.

Non-dsi drivers that create a dummy dsi device don't have this data. In order to get this information, they require to a phandle to the dsi host in the device tree.

Maintain a list of all the hosts DSI that are currently registered.

Quoted 7 lines
Quoted 4 lines

This list will be used to find the mipi_dsi_host corresponding to the device_node passed in of_find_mipi_dsi_host_by_node.

Looks OK, beside lack of documentation, after fixing it you can add

I will add missing documentation before posting v3.

Thanks again for the review.

Archit

Quoted 82 lines

Regards
Andrzej

Quoted 77 lines
---
  drivers/gpu/drm/drm_mipi_dsi.c | 30 ++++++++++++++++++++++++++++++
  include/drm/drm_mipi_dsi.h     |  2 ++
  2 files changed, 32 insertions(+)
drivers/gpu/drm/drm_mipi_dsi.c +30 -0
index cbb7373..c51d73e 100644
@@ -216,6 +216,28 @@ of_mipi_dsi_device_add(struct mipi_dsi_host *host, struct device_node *node)
  	return mipi_dsi_device_new(host, &info);
  }
 
+static DEFINE_MUTEX(host_lock);
+static LIST_HEAD(host_list);
+
+struct mipi_dsi_host *of_find_mipi_dsi_host_by_node(struct device_node *node)
+{
+	struct mipi_dsi_host *host;
+
+	mutex_lock(&host_lock);
+
+	list_for_each_entry(host, &host_list, list) {
+		if (host->dev->of_node == node) {
+			mutex_unlock(&host_lock);
+			return host;
+		}
+	}
+
+	mutex_unlock(&host_lock);
+
+	return NULL;
+}
+EXPORT_SYMBOL(of_find_mipi_dsi_host_by_node);
+
  int mipi_dsi_host_register(struct mipi_dsi_host *host)
  {
  	struct device_node *node;
@@ -227,6 +249,10 @@ int mipi_dsi_host_register(struct mipi_dsi_host *host)
  		of_mipi_dsi_device_add(host, node);
  	}
 
+	mutex_lock(&host_lock);
+	list_add_tail(&host->list, &host_list);
+	mutex_unlock(&host_lock);
+
  	return 0;
  }
  EXPORT_SYMBOL(mipi_dsi_host_register);
@@ -243,6 +269,10 @@ static int mipi_dsi_remove_device_fn(struct device *dev, void *priv)
  void mipi_dsi_host_unregister(struct mipi_dsi_host *host)
  {
  	device_for_each_child(host->dev, NULL, mipi_dsi_remove_device_fn);
+
+	mutex_lock(&host_lock);
+	list_del_init(&host->list);
+	mutex_unlock(&host_lock);
  }
  EXPORT_SYMBOL(mipi_dsi_host_unregister);
 
include/drm/drm_mipi_dsi.h +2 -0
index 68f49f4..15d3068 100644
@@ -100,10 +100,12 @@ struct mipi_dsi_host_ops {
  struct mipi_dsi_host {
  	struct device *dev;
  	const struct mipi_dsi_host_ops *ops;
+	struct list_head list;
  };
 
  int mipi_dsi_host_register(struct mipi_dsi_host *host);
  void mipi_dsi_host_unregister(struct mipi_dsi_host *host);
+struct mipi_dsi_host *of_find_mipi_dsi_host_by_node(struct device_node *node);
 
  /* DSI mode flags */
 
Signature · 5 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel
#42 lore raw

v3 cover drm/dsi: DSI for devices with different control bus

In reply to Archit Taneja

We are currently restricted when it comes to supporting DSI on devices that have a non-DSI control bus. For example, DSI encoder chips are available in the market that are configured via i2c. Configuring their registers via DSI bus is either optional or not available at all.

These devices still need to pass DSI parameters (data lanes, mode flags etc) to the DSI host they are connected to. We don't have a way to do that at the moment.

After some discussions on the previous RFC[1], we decided to support this by providing additional API in drm_mipi_dsi which lets us create new DSI devices without the need of them to have a DT node.

[1]: https://lkml.org/lkml/2015/6/30/42

Changes from v2 to v3:

- Incorporated misc comments by Andrzej. Changed from RFC to a PATCH set.
- Fixed htmldocs warnings.

Archit Taneja (5):
drm/dsi: Refactor device creation
drm/dsi: Try to match non-DT dsi devices
drm/dsi: Check for used channels
drm/dsi: Add routine to unregister dsi device
drm/dsi: Get DSI host by DT device node

 drivers/gpu/drm/drm_mipi_dsi.c | 136 +++++++++++++++++++++++++++++++----------
 include/drm/drm_mipi_dsi.h     |  29 +++++++++
 2 files changed, 133 insertions(+), 32 deletions(-)
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation
#43 lore raw

PATCH v3 1/5 drm/dsi: Refactor device creation

Simplify the mipi dsi device creation process. device_initialize and device_add don't need to be called separately when creating mipi_dsi_device's. Use device_register instead to simplify things.

Create a helper function mipi_dsi_device_new which takes in struct mipi_dsi_device_info and mipi_dsi_host. It clubs the functions mipi_dsi_device_alloc and mipi_dsi_device_add into one.

mipi_dsi_device_info acts as a template to populate the dsi device information. This is populated by of_mipi_dsi_device_add and passed to mipi_dsi_device_new.

Later on, we'll provide mipi_dsi_device_new as a standalone way to create a dsi device not available via DT.

The new device creation process tries to closely follow what's been done in i2c_new_device in i2c-core.

---
 drivers/gpu/drm/drm_mipi_dsi.c | 61 +++++++++++++++++-------------------------
 include/drm/drm_mipi_dsi.h     | 15 +++++++++++
 2 files changed, 40 insertions(+), 36 deletions(-)
drivers/gpu/drm/drm_mipi_dsi.c +25 -36
index 2d5ca8ee..82bcdcd 100644
@@ -102,9 +102,18 @@ static const struct device_type mipi_dsi_device_type = {
 	.release = mipi_dsi_dev_release,
 };
 
-static struct mipi_dsi_device *mipi_dsi_device_alloc(struct mipi_dsi_host *host)
+struct mipi_dsi_device *mipi_dsi_device_new(struct mipi_dsi_host *host,
+					    struct mipi_dsi_device_info *info)
 {
 	struct mipi_dsi_device *dsi;
+	struct device *dev = host->dev;
+	int ret;
+
+	if (info->reg > 3) {
+		dev_err(dev, "device node has invalid reg property: %u\n",
+			info->reg);
+		return ERR_PTR(-EINVAL);
+	}
 
 	dsi = kzalloc(sizeof(*dsi), GFP_KERNEL);
 	if (!dsi)
@@ -114,26 +123,27 @@ static struct mipi_dsi_device *mipi_dsi_device_alloc(struct mipi_dsi_host *host)
 	dsi->dev.bus = &mipi_dsi_bus_type;
 	dsi->dev.parent = host->dev;
 	dsi->dev.type = &mipi_dsi_device_type;
+	dsi->dev.of_node = info->node;
+	dsi->channel = info->reg;
 
-	device_initialize(&dsi->dev);
-
-	return dsi;
-}
-
-static int mipi_dsi_device_add(struct mipi_dsi_device *dsi)
-{
-	struct mipi_dsi_host *host = dsi->host;
+	dev_set_name(&dsi->dev, "%s.%d", dev_name(host->dev), info->reg);
 
-	dev_set_name(&dsi->dev, "%s.%d", dev_name(host->dev),  dsi->channel);
+	ret = device_register(&dsi->dev);
+	if (ret) {
+		dev_err(dev, "failed to register device: %d\n", ret);
+		kfree(dsi);
+		return ERR_PTR(ret);
+	}
 
-	return device_add(&dsi->dev);
+	return dsi;
 }
+EXPORT_SYMBOL(mipi_dsi_device_new);
 
 static struct mipi_dsi_device *
 of_mipi_dsi_device_add(struct mipi_dsi_host *host, struct device_node *node)
 {
-	struct mipi_dsi_device *dsi;
 	struct device *dev = host->dev;
+	struct mipi_dsi_device_info info = { };
 	int ret;
 	u32 reg;
 
@@ -144,31 +154,10 @@ of_mipi_dsi_device_add(struct mipi_dsi_host *host, struct device_node *node)
 		return ERR_PTR(-EINVAL);
 	}
 
-	if (reg > 3) {
-		dev_err(dev, "device node %s has invalid reg property: %u\n",
-			node->full_name, reg);
-		return ERR_PTR(-EINVAL);
-	}
-
-	dsi = mipi_dsi_device_alloc(host);
-	if (IS_ERR(dsi)) {
-		dev_err(dev, "failed to allocate DSI device %s: %ld\n",
-			node->full_name, PTR_ERR(dsi));
-		return dsi;
-	}
-
-	dsi->dev.of_node = of_node_get(node);
-	dsi->channel = reg;
+	info.reg = reg;
+	info.node = of_node_get(node);
 
-	ret = mipi_dsi_device_add(dsi);
-	if (ret) {
-		dev_err(dev, "failed to add DSI device %s: %d\n",
-			node->full_name, ret);
-		kfree(dsi);
-		return ERR_PTR(ret);
-	}
-
-	return dsi;
+	return mipi_dsi_device_new(host, &info);
 }
 
 int mipi_dsi_host_register(struct mipi_dsi_host *host)
include/drm/drm_mipi_dsi.h +15 -0
index f1d8d0d..90f4f3c 100644
@@ -140,6 +140,19 @@ enum mipi_dsi_pixel_format {
 };
 
 /**
+ * struct mipi_dsi_device_info - template for creating a mipi_dsi_device
+ * @reg: DSI virtual channel assigned to peripheral
+ * @node: pointer to OF device node
+ *
+ * This is populated and passed to mipi_dsi_device_new to create a new
+ * DSI device
+ */
+struct mipi_dsi_device_info {
+	u32 reg;
+	struct device_node *node;
+};
+
+/**
  * struct mipi_dsi_device - DSI peripheral device
  * @host: DSI host for this peripheral
  * @dev: driver model device node for this peripheral
@@ -174,6 +187,8 @@ ssize_t mipi_dsi_generic_write(struct mipi_dsi_device *dsi, const void *payload,
 ssize_t mipi_dsi_generic_read(struct mipi_dsi_device *dsi, const void *params,
 			      size_t num_params, void *data, size_t size);
 
+struct mipi_dsi_device *mipi_dsi_device_new(struct mipi_dsi_host *host,
+					    struct mipi_dsi_device_info *info);
 /**
  * enum mipi_dsi_dcs_tear_mode - Tearing Effect Output Line mode
  * @MIPI_DSI_DCS_TEAR_MODE_VBLANK: the TE output line consists of V-Blanking
Signature · 7 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel
#44 lore raw

PATCH v3 2/5 drm/dsi: Try to match non-DT dsi devices

In reply to Archit Taneja

Add a device name field in mipi_dsi_device. This name is different from the actual dev name (which is of the format "hostname.reg"). When the device is created via DT, this name is set to the modalias string. In the non-DT case, the driver creating the DSI device provides the name by populating a filed in mipi_dsi_device_info.

Matching for DT case would be as it was before. For the non-DT case, we compare the device and driver names. Other buses (like i2c/spi) perform a non-DT match by comparing the device name and entries in the driver's id_table. Such a mechanism isn't used for the dsi bus.

---
 drivers/gpu/drm/drm_mipi_dsi.c | 25 ++++++++++++++++++++++++-
 include/drm/drm_mipi_dsi.h     |  6 ++++++
 2 files changed, 30 insertions(+), 1 deletion(-)
drivers/gpu/drm/drm_mipi_dsi.c +24 -1
index 82bcdcd..143cce4 100644
@@ -45,9 +45,26 @@
  * subset of the MIPI DCS command set.
  */
 
+static const struct device_type mipi_dsi_device_type;
+
 static int mipi_dsi_device_match(struct device *dev, struct device_driver *drv)
 {
-	return of_driver_match_device(dev, drv);
+	struct mipi_dsi_device *dsi;
+
+	if (dev->type == &mipi_dsi_device_type)
+		dsi = to_mipi_dsi_device(dev);
+	else
+		return 0;
+
+	/* attempt OF style match */
+	if (of_driver_match_device(dev, drv))
+		return 1;
+
+	/* compare dsi device and driver names */
+	if (!strcmp(dsi->name, drv->name))
+		return 1;
+
+	return 0;
 }
 
 static const struct dev_pm_ops mipi_dsi_device_pm_ops = {
@@ -125,6 +142,7 @@ struct mipi_dsi_device *mipi_dsi_device_new(struct mipi_dsi_host *host,
 	dsi->dev.type = &mipi_dsi_device_type;
 	dsi->dev.of_node = info->node;
 	dsi->channel = info->reg;
+	strlcpy(dsi->name, info->type, sizeof(dsi->name));
 
 	dev_set_name(&dsi->dev, "%s.%d", dev_name(host->dev), info->reg);
 
@@ -147,6 +165,11 @@ of_mipi_dsi_device_add(struct mipi_dsi_host *host, struct device_node *node)
 	int ret;
 	u32 reg;
 
+	if (of_modalias_node(node, info.type, sizeof(info.type)) < 0) {
+		dev_err(dev, "modalias failure on %s\n", node->full_name);
+		return ERR_PTR(-EINVAL);
+	}
+
 	ret = of_property_read_u32(node, "reg", &reg);
 	if (ret) {
 		dev_err(dev, "device node %s has no valid reg property: %d\n",
include/drm/drm_mipi_dsi.h +6 -0
index 90f4f3c..cb084af 100644
@@ -139,8 +139,11 @@ enum mipi_dsi_pixel_format {
 	MIPI_DSI_FMT_RGB565,
 };
 
+#define DSI_DEV_NAME_SIZE		20
+
 /**
  * struct mipi_dsi_device_info - template for creating a mipi_dsi_device
+ * @type: dsi peripheral chip type
  * @reg: DSI virtual channel assigned to peripheral
  * @node: pointer to OF device node
  *
@@ -148,6 +151,7 @@ enum mipi_dsi_pixel_format {
  * DSI device
  */
 struct mipi_dsi_device_info {
+	char type[DSI_DEV_NAME_SIZE];
 	u32 reg;
 	struct device_node *node;
 };
@@ -156,6 +160,7 @@ struct mipi_dsi_device_info {
  * struct mipi_dsi_device - DSI peripheral device
  * @host: DSI host for this peripheral
  * @dev: driver model device node for this peripheral
+ * @name: dsi peripheral chip type
  * @channel: virtual channel assigned to the peripheral
  * @format: pixel format for video mode
  * @lanes: number of active data lanes
@@ -165,6 +170,7 @@ struct mipi_dsi_device {
 	struct mipi_dsi_host *host;
 	struct device dev;
 
+	char name[DSI_DEV_NAME_SIZE];
 	unsigned int channel;
 	unsigned int lanes;
 	enum mipi_dsi_pixel_format format;
Signature · 7 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel
#45 lore raw

Re: [PATCH v3 2/5] drm/dsi: Try to match non-DT dsi devices

reproduce:

Hi Archit,

[auto build test ERROR on: v4.4-rc3]
[also build test ERROR on: next-20151127]

url:    https://github.com/0day-ci/linux/commits/Archit-Taneja/drm-dsi-DSI-for-devices-with-different-control-bus/20151130-200725
config: x86_64-allyesdebian (attached as .config)
reproduce:
        # save the attached .config to linux build tree
        make ARCH=x86_64 

All errors (new ones prefixed by >>):

drivers/gpu/drm/drm_mipi_dsi.c: In function 'of_mipi_dsi_device_add':

>> drivers/gpu/drm/drm_mipi_dsi.c:168:6: error: implicit declaration of function 'of_modalias_node' [-Werror=implicit-function-declaration]
     if (of_modalias_node(node, info.type, sizeof(info.type)) < 0) {
         ^

cc1: some warnings being treated as errors

vim +/of_modalias_node +168 drivers/gpu/drm/drm_mipi_dsi.c

162 {
163 struct device *dev = host->dev;
164 struct mipi_dsi_device_info info = { };
165 int ret;
166 u32 reg;
167

 > 168		if (of_modalias_node(node, info.type, sizeof(info.type)) < 0) {

169 dev_err(dev, "modalias failure on %s\n", node->full_name);
170 return ERR_PTR(-EINVAL);
171 }

---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation

#46 lore raw

Re: [PATCH v3 2/5] drm/dsi: Try to match non-DT dsi devices

Hi,

Quoted 11 lines · kbuild test robot

Hi Archit,

[auto build test ERROR on: v4.4-rc3]
[also build test ERROR on: next-20151127]

url:    https://github.com/0day-ci/linux/commits/Archit-Taneja/drm-dsi-DSI-for-devices-with-different-control-bus/20151130-200725
config: x86_64-allyesdebian (attached as .config)
reproduce:
         # save the attached .config to linux build tree
         make ARCH=x86_64
Quoted 5 lines

All errors (new ones prefixed by >>):

drivers/gpu/drm/drm_mipi_dsi.c: In function 'of_mipi_dsi_device_add':

Quoted 1 line
Quoted 1 line

drivers/gpu/drm/drm_mipi_dsi.c:168:6: error: implicit declaration of function 'of_modalias_node' [-Werror=implicit-function-declaration]

      if (of_modalias_node(node, info.type, sizeof(info.type)) < 0) {

Any suggestions on how to fix this? Is it ok to make DRM_MIPI_DSI depend on CONFIG_OF? Or is it better to wrap these funcs around IF_ENABLED(CONFIG_OF)?

Archit

Quoted 20 lines

^
cc1: some warnings being treated as errors

vim +/of_modalias_node +168 drivers/gpu/drm/drm_mipi_dsi.c

    162	{
    163		struct device *dev = host->dev;
    164		struct mipi_dsi_device_info info = { };
    165		int ret;
    166		u32 reg;
    167	
Quoted 1 line

168 if (of_modalias_node(node, info.type, sizeof(info.type)) < 0) {

    169			dev_err(dev, "modalias failure on %s\n", node->full_name);
    170			return ERR_PTR(-EINVAL);
    171		}

---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation

Signature · 1 line
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
#47 lore raw

Re: [PATCH v3 2/5] drm/dsi: Try to match non-DT dsi devices

Quoted 14 lines · Archit Taneja

Hi,

Quoted 11 lines · kbuild test robot

Hi Archit,

[auto build test ERROR on: v4.4-rc3]
[also build test ERROR on: next-20151127]

url:    https://github.com/0day-ci/linux/commits/Archit-Taneja/drm-dsi-DSI-for-devices-with-different-control-bus/20151130-200725
config: x86_64-allyesdebian (attached as .config)
reproduce:
         # save the attached .config to linux build tree
         make ARCH=x86_64
Quoted 8 lines
Quoted 5 lines

All errors (new ones prefixed by >>):

drivers/gpu/drm/drm_mipi_dsi.c: In function 'of_mipi_dsi_device_add':

Quoted 1 line
Quoted 1 line

drivers/gpu/drm/drm_mipi_dsi.c:168:6: error: implicit declaration of function 'of_modalias_node' [-Werror=implicit-function-declaration]

      if (of_modalias_node(node, info.type, sizeof(info.type)) < 0) {

Any suggestions on how to fix this? Is it ok to make DRM_MIPI_DSI depend on CONFIG_OF?

Please don't.

BR,
Jani.

Signature · 1 line
Jani Nikula, Intel Open Source Technology Center
#48 lore raw

Re: [PATCH v3 2/5] drm/dsi: Try to match non-DT dsi devices

Quoted 17 lines · Jani Nikula
Quoted 16 lines · Archit Taneja

Hi,

Quoted 13 lines · kbuild test robot

Hi Archit,

[auto build test ERROR on: v4.4-rc3]
[also build test ERROR on: next-20151127]

url:    https://github.com/0day-ci/linux/commits/Archit-Taneja/drm-dsi-DSI-for-devices-with-different-control-bus/20151130-200725
config: x86_64-allyesdebian (attached as .config)
reproduce:
          # save the attached .config to linux build tree
          make ARCH=x86_64

All errors (new ones prefixed by >>):

Quoted 8 lines
Quoted 6 lines
Quoted 3 lines

drivers/gpu/drm/drm_mipi_dsi.c: In function 'of_mipi_dsi_device_add':

Quoted 1 line
Quoted 1 line

drivers/gpu/drm/drm_mipi_dsi.c:168:6: error: implicit declaration of function 'of_modalias_node' [-Werror=implicit-function-declaration]

       if (of_modalias_node(node, info.type, sizeof(info.type)) < 0) {

Any suggestions on how to fix this? Is it ok to make DRM_MIPI_DSI depend on CONFIG_OF?

Please don't.

Just curious, how did x86 use DSI if the only way to create DSI devices until now was via DT?

Archit

Quoted 4 lines

BR,
Jani.

Signature · 5 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel
#49 lore raw

Re: [PATCH v3 2/5] drm/dsi: Try to match non-DT dsi devices

Quoted 22 lines · Archit Taneja
Quoted 21 lines · Jani Nikula
Quoted 20 lines · Archit Taneja

Hi,

Quoted 16 lines · kbuild test robot

Hi Archit,

[auto build test ERROR on: v4.4-rc3]
[also build test ERROR on: next-20151127]

url:    https://github.com/0day-ci/linux/commits/Archit-Taneja/drm-dsi-DSI-for-devices-with-different-control-bus/20151130-200725
config: x86_64-allyesdebian (attached as .config)
reproduce:
          # save the attached .config to linux build tree
          make ARCH=x86_64

All errors (new ones prefixed by >>):

drivers/gpu/drm/drm_mipi_dsi.c: In function 'of_mipi_dsi_device_add':

Quoted 1 line
Quoted 1 line

drivers/gpu/drm/drm_mipi_dsi.c:168:6: error: implicit declaration of function 'of_modalias_node' [-Werror=implicit-function-declaration]

       if (of_modalias_node(node, info.type, sizeof(info.type)) < 0) {
Quoted 7 lines
Quoted 4 lines
Quoted 2 lines

Any suggestions on how to fix this? Is it ok to make DRM_MIPI_DSI depend on CONFIG_OF?

Please don't.

Just curious, how did x86 use DSI if the only way to create DSI devices until now was via DT?

Oh, you want the gory details... we use the DSI code as a library for abstraction and helpers, without actually creating or registering the devices.

BR,
Jani.

Quoted 7 lines

Archit

Quoted 4 lines

BR,
Jani.

Signature · 5 lines
Jani Nikula, Intel Open Source Technology Center
_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel
#50 lore raw

Re: [PATCH v3 2/5] drm/dsi: Try to match non-DT dsi devices

Quoted 26 lines · Jani Nikula
Quoted 25 lines · Archit Taneja
Quoted 24 lines · Jani Nikula
Quoted 22 lines · Archit Taneja

Hi,

Quoted 11 lines · kbuild test robot

Hi Archit,

[auto build test ERROR on: v4.4-rc3]
[also build test ERROR on: next-20151127]

url:    https://github.com/0day-ci/linux/commits/Archit-Taneja/drm-dsi-DSI-for-devices-with-different-control-bus/20151130-200725
config: x86_64-allyesdebian (attached as .config)
reproduce:
           # save the attached .config to linux build tree
           make ARCH=x86_64
Quoted 5 lines

All errors (new ones prefixed by >>):

drivers/gpu/drm/drm_mipi_dsi.c: In function 'of_mipi_dsi_device_add':

Quoted 1 line
Quoted 1 line

drivers/gpu/drm/drm_mipi_dsi.c:168:6: error: implicit declaration of function 'of_modalias_node' [-Werror=implicit-function-declaration]

        if (of_modalias_node(node, info.type, sizeof(info.type)) < 0) {

Any suggestions on how to fix this? Is it ok to make DRM_MIPI_DSI depend on CONFIG_OF?

Quoted 8 lines
Quoted 4 lines
Quoted 1 line

Please don't.

Just curious, how did x86 use DSI if the only way to create DSI devices until now was via DT?

Oh, you want the gory details... we use the DSI code as a library for abstraction and helpers, without actually creating or registering the devices.

Okay, got it. I'll go with the IS_ENABLED(CONFIG_OF) approach.

Humble request: Next time if I share something that doesn't make sense, please reply with something more than a "Please don't". That just sounds condescending and doesn't really help me with my cause either.

Thanks,
Archit

Quoted 13 lines

BR,
Jani.

Quoted 7 lines

Archit

Quoted 4 lines

BR,
Jani.

Signature · 1 line
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
#51 lore raw

Re: [PATCH v3 2/5] drm/dsi: Try to match non-DT dsi devices

Quoted 9 lines · Archit Taneja
Quoted 8 lines · Jani Nikula
Quoted 7 lines · Archit Taneja
Quoted 5 lines · Jani Nikula
Quoted 2 lines · Archit Taneja

Any suggestions on how to fix this? Is it ok to make DRM_MIPI_DSI depend on CONFIG_OF?

Please don't.

Quoted 8 lines
Quoted 6 lines
Quoted 2 lines

Just curious, how did x86 use DSI if the only way to create DSI devices until now was via DT?

Oh, you want the gory details... we use the DSI code as a library for abstraction and helpers, without actually creating or registering the devices.

Okay, got it. I'll go with the IS_ENABLED(CONFIG_OF) approach.

Thanks, appreciated, so i915 doesn't need to depend on OF.

Quoted 3 lines

Humble request: Next time if I share something that doesn't make sense, please reply with something more than a "Please don't". That just sounds condescending and doesn't really help me with my cause either.

That's a fair request, no need to be humble about it. Apologies.

BR,
Jani.

Signature · 1 line
Jani Nikula, Intel Open Source Technology Center
#52 lore raw

Re: [PATCH v3 2/5] drm/dsi: Try to match non-DT dsi devices

In reply to Jani Nikula
Quoted 17 lines · Jani Nikula
Quoted 16 lines · Archit Taneja

Hi,

Quoted 13 lines · kbuild test robot

Hi Archit,

[auto build test ERROR on: v4.4-rc3]
[also build test ERROR on: next-20151127]

url:    https://github.com/0day-ci/linux/commits/Archit-Taneja/drm-dsi-DSI-for-devices-with-different-control-bus/20151130-200725
config: x86_64-allyesdebian (attached as .config)
reproduce:
         # save the attached .config to linux build tree
         make ARCH=x86_64

All errors (new ones prefixed by >>):

Quoted 8 lines
Quoted 6 lines
Quoted 3 lines

drivers/gpu/drm/drm_mipi_dsi.c: In function 'of_mipi_dsi_device_add':

Quoted 1 line
Quoted 1 line

drivers/gpu/drm/drm_mipi_dsi.c:168:6: error: implicit declaration of function 'of_modalias_node' [-Werror=implicit-function-declaration]

      if (of_modalias_node(node, info.type, sizeof(info.type)) < 0) {

Any suggestions on how to fix this? Is it ok to make DRM_MIPI_DSI depend on CONFIG_OF?

Please don't.

I assume you are not using of_mipi_dsi_device_add()? We could just put this one fxn inside #ifdef CONFIG_OF / #endif, I think..

BR,
-R

Quoted 9 lines

BR,
Jani.

--
Jani Nikula, Intel Open Source Technology Center
_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel

#53 lore raw

PATCH v3 3/5 drm/dsi: Check for used channels

In reply to Archit Taneja

We don't check whether a previously registered mipi_dsi_device under the same host shares the same virtual channel.

Before registering, check if any of the registered devices doesn't already have the same virtual channel.

This wasn't crucial when all the devices under a host were populated via DT. Now that we also support creating devices manually, we could end up in a situation where a driver tries to create a device with a virtual channel already taken by a device populated in DT.

---
 drivers/gpu/drm/drm_mipi_dsi.c | 26 ++++++++++++++++++++++++--
 1 file changed, 24 insertions(+), 2 deletions(-)
drivers/gpu/drm/drm_mipi_dsi.c +24 -2
index 143cce4..f73e434 100644
@@ -119,6 +119,22 @@ static const struct device_type mipi_dsi_device_type = {
 	.release = mipi_dsi_dev_release,
 };
 
+static int __dsi_check_chan_busy(struct device *dev, void *data)
+{
+	struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev);
+	u32 *reg = data;
+
+	if (dsi && dsi->channel == *reg)
+		return -EBUSY;
+
+	return 0;
+}
+
+static int mipi_dsi_check_chan_busy(struct mipi_dsi_host *host, u32 reg)
+{
+	return device_for_each_child(host->dev, &reg, __dsi_check_chan_busy);
+}
+
 struct mipi_dsi_device *mipi_dsi_device_new(struct mipi_dsi_host *host,
 					    struct mipi_dsi_device_info *info)
 {
@@ -146,14 +162,20 @@ struct mipi_dsi_device *mipi_dsi_device_new(struct mipi_dsi_host *host,
 
 	dev_set_name(&dsi->dev, "%s.%d", dev_name(host->dev), info->reg);
 
+	ret = mipi_dsi_check_chan_busy(host, info->reg);
+	if (ret)
+		goto err;
+
 	ret = device_register(&dsi->dev);
 	if (ret) {
 		dev_err(dev, "failed to register device: %d\n", ret);
-		kfree(dsi);
-		return ERR_PTR(ret);
+		goto err;
 	}
 
 	return dsi;
+err:
+	kfree(dsi);
+	return ERR_PTR(ret);
 }
 EXPORT_SYMBOL(mipi_dsi_device_new);
 
Signature · 7 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel
#54 lore raw

PATCH v3 4/5 drm/dsi: Add routine to unregister dsi device

In reply to Archit Taneja

A driver calling mipi_dsi_device_new might want to unregister the device once it's done. It might also require it in an error handling path in case something didn't go right.

---
 include/drm/drm_mipi_dsi.h | 5 +++++
 1 file changed, 5 insertions(+)
include/drm/drm_mipi_dsi.h +5 -0
index cb084af..410d8b5 100644
@@ -195,6 +195,11 @@ ssize_t mipi_dsi_generic_read(struct mipi_dsi_device *dsi, const void *params,
 
 struct mipi_dsi_device *mipi_dsi_device_new(struct mipi_dsi_host *host,
 					    struct mipi_dsi_device_info *info);
+static inline void mipi_dsi_device_unregister(struct mipi_dsi_device *dsi)
+{
+	device_unregister(&dsi->dev);
+}
+
 /**
  * enum mipi_dsi_dcs_tear_mode - Tearing Effect Output Line mode
  * @MIPI_DSI_DCS_TEAR_MODE_VBLANK: the TE output line consists of V-Blanking
Signature · 7 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel
Reviewed-by on v3 4/5
#55 lore raw

Re: [PATCH v3 4/5] drm/dsi: Add routine to unregister dsi device

Quoted 5 lines · Archit Taneja

A driver calling mipi_dsi_device_new might want to unregister the device once it's done. It might also require it in an error handling path in case something didn't go right.

Regards
Andrzej

_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel

#56 lore raw

PATCH v3 5/5 drm/dsi: Get DSI host by DT device node

In reply to Archit Taneja

mipi_dsi_devices are inherently aware of their host because they share a parent-child hierarchy in the device tree.

non-dsi drivers that create dsi device don't have this data. In order to get this information, they require to a phandle to the dsi host in the device tree.

Maintain a list of all the hosts DSI that are currently registered.

This list will be used to find the mipi_dsi_host corresponding to the device_node passed in of_find_mipi_dsi_host_by_node.

---
 drivers/gpu/drm/drm_mipi_dsi.c | 38 ++++++++++++++++++++++++++++++++++++++
 include/drm/drm_mipi_dsi.h     |  3 +++
 2 files changed, 41 insertions(+)
drivers/gpu/drm/drm_mipi_dsi.c +38 -0
index f73e434..e9c17e25 100644
@@ -205,6 +205,36 @@ of_mipi_dsi_device_add(struct mipi_dsi_host *host, struct device_node *node)
 	return mipi_dsi_device_new(host, &info);
 }
 
+static DEFINE_MUTEX(host_lock);
+static LIST_HEAD(host_list);
+
+/**
+ * of_find_mipi_dsi_host_by_node() - find the MIPI DSI host matching a
+ *    device tree node
+ * @node: device tree node
+ *
+ * Return: A pointer to the MIPI DSI host corresponding to @np or NULL if no
+ *    such device exists (or has not been registered yet).
+ */
+struct mipi_dsi_host *of_find_mipi_dsi_host_by_node(struct device_node *node)
+{
+	struct mipi_dsi_host *host;
+
+	mutex_lock(&host_lock);
+
+	list_for_each_entry(host, &host_list, list) {
+		if (host->dev->of_node == node) {
+			mutex_unlock(&host_lock);
+			return host;
+		}
+	}
+
+	mutex_unlock(&host_lock);
+
+	return NULL;
+}
+EXPORT_SYMBOL(of_find_mipi_dsi_host_by_node);
+
 int mipi_dsi_host_register(struct mipi_dsi_host *host)
 {
 	struct device_node *node;
@@ -216,6 +246,10 @@ int mipi_dsi_host_register(struct mipi_dsi_host *host)
 		of_mipi_dsi_device_add(host, node);
 	}
 
+	mutex_lock(&host_lock);
+	list_add_tail(&host->list, &host_list);
+	mutex_unlock(&host_lock);
+
 	return 0;
 }
 EXPORT_SYMBOL(mipi_dsi_host_register);
@@ -232,6 +266,10 @@ static int mipi_dsi_remove_device_fn(struct device *dev, void *priv)
 void mipi_dsi_host_unregister(struct mipi_dsi_host *host)
 {
 	device_for_each_child(host->dev, NULL, mipi_dsi_remove_device_fn);
+
+	mutex_lock(&host_lock);
+	list_del_init(&host->list);
+	mutex_unlock(&host_lock);
 }
 EXPORT_SYMBOL(mipi_dsi_host_unregister);
 
include/drm/drm_mipi_dsi.h +3 -0
index 410d8b5..e5c1df9 100644
@@ -96,14 +96,17 @@ struct mipi_dsi_host_ops {
  * struct mipi_dsi_host - DSI host device
  * @dev: driver model device node for this DSI host
  * @ops: DSI host operations
+ * @list: list management
  */
 struct mipi_dsi_host {
 	struct device *dev;
 	const struct mipi_dsi_host_ops *ops;
+	struct list_head list;
 };
 
 int mipi_dsi_host_register(struct mipi_dsi_host *host);
 void mipi_dsi_host_unregister(struct mipi_dsi_host *host);
+struct mipi_dsi_host *of_find_mipi_dsi_host_by_node(struct device_node *node);
 
 /* DSI mode flags */
 
Signature · 7 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel
#57 lore raw

v4 cover drm/dsi: DSI for devices with different control bus

In reply to Archit Taneja

We are currently restricted when it comes to supporting DSI on devices that have a non-DSI control bus. For example, DSI encoder chips are available in the market that are configured via i2c. Configuring their registers via DSI bus is either optional or not available at all.

These devices still need to pass DSI parameters (data lanes, mode flags etc) to the DSI host they are connected to. We don't have a way to do that at the moment.

After some discussions on the previous RFC[1], we decided to support this by providing additional API in drm_mipi_dsi which lets us create new DSI devices without the need of them to have a DT node.

[1]: https://lkml.org/lkml/2015/6/30/42

Changes in v4:
- Added a new patch that fixes build issues when CONFIG_OF is not set.

Changes in v3:

- Incorporated misc comments by Andrzej. Changed from RFC to a PATCH set.
- Fixed htmldocs warnings.

Archit Taneja (6):
drm/dsi: check for CONFIG_OF when defining of_mipi_dsi_device_add drm/dsi: Refactor device creation
drm/dsi: Try to match non-DT dsi devices
drm/dsi: Check for used channels
drm/dsi: Add routine to unregister dsi device
drm/dsi: Get DSI host by DT device node

 drivers/gpu/drm/drm_mipi_dsi.c | 144 ++++++++++++++++++++++++++++++++---------
 include/drm/drm_mipi_dsi.h     |  29 +++++++++
 2 files changed, 141 insertions(+), 32 deletions(-)
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation
#58 lore raw

PATCH v4 1/6 drm/dsi: check for CONFIG_OF when defining of_mipi_dsi_device_add

of_mipi_dsi_device_add is used only when CONFIG_OF is enabled. It currently works if OF support is disabled, but this will change when we add more functionality to it.

Define the original func if CONFIG_OF is enabled. Define a dummy func otherwise.

---
 drivers/gpu/drm/drm_mipi_dsi.c | 8 ++++++++
 1 file changed, 8 insertions(+)
drivers/gpu/drm/drm_mipi_dsi.c +8 -0
index 2d5ca8ee..bced235 100644
@@ -129,6 +129,7 @@ static int mipi_dsi_device_add(struct mipi_dsi_device *dsi)
 	return device_add(&dsi->dev);
 }
 
+#if IS_ENABLED(CONFIG_OF)
 static struct mipi_dsi_device *
 of_mipi_dsi_device_add(struct mipi_dsi_host *host, struct device_node *node)
 {
@@ -170,6 +171,13 @@ of_mipi_dsi_device_add(struct mipi_dsi_host *host, struct device_node *node)
 
 	return dsi;
 }
+#else
+static struct mipi_dsi_device *
+of_mipi_dsi_device_add(struct mipi_dsi_host *host, struct device_node *node)
+{
+	return NULL;
+}
+#endif
 
 int mipi_dsi_host_register(struct mipi_dsi_host *host)
 {
Signature · 7 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel
#59 lore raw

Re: [PATCH v4 1/6] drm/dsi: check for CONFIG_OF when defining of_mipi_dsi_device_add

Quoted 25 lines · Archit Taneja

of_mipi_dsi_device_add is used only when CONFIG_OF is enabled. It currently works if OF support is disabled, but this will change when we add more functionality to it.

Define the original func if CONFIG_OF is enabled. Define a dummy func otherwise.

---
 drivers/gpu/drm/drm_mipi_dsi.c | 8 ++++++++
 1 file changed, 8 insertions(+)
drivers/gpu/drm/drm_mipi_dsi.c +1 -0
index 2d5ca8ee..bced235 100644
@@ -129,6 +129,7 @@ static int mipi_dsi_device_add(struct mipi_dsi_device *dsi)
 	return device_add(&dsi->dev);
 }
 
+#if IS_ENABLED(CONFIG_OF)
 static struct mipi_dsi_device *
 of_mipi_dsi_device_add(struct mipi_dsi_host *host, struct device_node *node)
 {

drivers/gpu/drm/drm_mipi_dsi.c of_mipi_dsi_device_add(struct mipi_dsi_host *host, struct device_node *node) · line 180

Quoted 10 lines
drivers/gpu/drm/drm_mipi_dsi.c +7 -0
@@ -170,6 +171,13 @@ of_mipi_dsi_device_add(struct mipi_dsi_host *host, struct device_node *node)
 
 	return dsi;
 }
+#else
+static struct mipi_dsi_device *
+of_mipi_dsi_device_add(struct mipi_dsi_host *host, struct device_node *node)
+{
+	return NULL;
+}
+#endif

The OF implementation of this function never returns NULL, so perhaps this should return an ERR_PTR()-encoded error code instead? This isn't really important because we never check the return value in the one call-site that we have, which I guess could be an argument for removing the return value altogether...

Thierry

#60 lore raw

Re: [PATCH v4 1/6] drm/dsi: check for CONFIG_OF when defining of_mipi_dsi_device_add

Quoted 27 lines · Thierry Reding
Quoted 26 lines · Archit Taneja

of_mipi_dsi_device_add is used only when CONFIG_OF is enabled. It currently works if OF support is disabled, but this will change when we add more functionality to it.

Define the original func if CONFIG_OF is enabled. Define a dummy func otherwise.

---
  drivers/gpu/drm/drm_mipi_dsi.c | 8 ++++++++
  1 file changed, 8 insertions(+)
drivers/gpu/drm/drm_mipi_dsi.c +1 -0
index 2d5ca8ee..bced235 100644
@@ -129,6 +129,7 @@ static int mipi_dsi_device_add(struct mipi_dsi_device *dsi)
  	return device_add(&dsi->dev);
  }
 
+#if IS_ENABLED(CONFIG_OF)
  static struct mipi_dsi_device *
  of_mipi_dsi_device_add(struct mipi_dsi_host *host, struct device_node *node)
  {
@@ -170,6 +171,13 @@ of_mipi_dsi_device_add(struct mipi_dsi_host *host, struct device_node *node)
 
Quoted 15 lines

drivers/gpu/drm/drm_mipi_dsi.c of_mipi_dsi_device_add(struct mipi_dsi_host *host, struct device_node *node) · line 180

Quoted 9 lines
drivers/gpu/drm/drm_mipi_dsi.c +7 -0
  	return dsi;
  }
+#else
+static struct mipi_dsi_device *
+of_mipi_dsi_device_add(struct mipi_dsi_host *host, struct device_node *node)
+{
+	return NULL;
+}
+#endif

The OF implementation of this function never returns NULL, so perhaps this should return an ERR_PTR()-encoded error code instead? This isn't really important because we never check the return value in the one call-site that we have, which I guess could be an argument for removing the return value altogether...

You're right. I'll replace this with ERR_PTR(-ENODEV). Maybe we could keep the return value in case we use it in the future.

Thanks,
Archit

Quoted 3 lines

Thierry

Signature · 6 lines
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel
#61 lore raw

PATCH v4 2/6 drm/dsi: Refactor device creation

In reply to Archit Taneja

Simplify the mipi dsi device creation process. device_initialize and device_add don't need to be called separately when creating mipi_dsi_device's. Use device_register instead to simplify things.

Create a helper function mipi_dsi_device_new which takes in struct mipi_dsi_device_info and mipi_dsi_host. It clubs the functions mipi_dsi_device_alloc and mipi_dsi_device_add into one.

mipi_dsi_device_info acts as a template to populate the dsi device information. This is populated by of_mipi_dsi_device_add and passed to mipi_dsi_device_new.

Later on, we'll provide mipi_dsi_device_new as a standalone way to create a dsi device not available via DT.

The new device creation process tries to closely follow what's been done in i2c_new_device in i2c-core.

---
 drivers/gpu/drm/drm_mipi_dsi.c | 61 +++++++++++++++++-------------------------
 include/drm/drm_mipi_dsi.h     | 15 +++++++++++
 2 files changed, 40 insertions(+), 36 deletions(-)
drivers/gpu/drm/drm_mipi_dsi.c +25 -36
index bced235..9434585 100644
@@ -102,9 +102,18 @@ static const struct device_type mipi_dsi_device_type = {
 	.release = mipi_dsi_dev_release,
 };
 
-static struct mipi_dsi_device *mipi_dsi_device_alloc(struct mipi_dsi_host *host)
+struct mipi_dsi_device *mipi_dsi_device_new(struct mipi_dsi_host *host,
+					    struct mipi_dsi_device_info *info)
 {
 	struct mipi_dsi_device *dsi;
+	struct device *dev = host->dev;
+	int ret;
+
+	if (info->reg > 3) {
+		dev_err(dev, "device node has invalid reg property: %u\n",
+			info->reg);
+		return ERR_PTR(-EINVAL);
+	}
 
 	dsi = kzalloc(sizeof(*dsi), GFP_KERNEL);
 	if (!dsi)
@@ -114,27 +123,28 @@ static struct mipi_dsi_device *mipi_dsi_device_alloc(struct mipi_dsi_host *host)
 	dsi->dev.bus = &mipi_dsi_bus_type;
 	dsi->dev.parent = host->dev;
 	dsi->dev.type = &mipi_dsi_device_type;
+	dsi->dev.of_node = info->node;
+	dsi->channel = info->reg;
 
-	device_initialize(&dsi->dev);
-
-	return dsi;
-}
-
-static int mipi_dsi_device_add(struct mipi_dsi_device *dsi)
-{
-	struct mipi_dsi_host *host = dsi->host;
+	dev_set_name(&dsi->dev, "%s.%d", dev_name(host->dev), info->reg);
 
-	dev_set_name(&dsi->dev, "%s.%d", dev_name(host->dev),  dsi->channel);
+	ret = device_register(&dsi->dev);
+	if (ret) {
+		dev_err(dev, "failed to register device: %d\n", ret);
+		kfree(dsi);
+		return ERR_PTR(ret);
+	}
 
-	return device_add(&dsi->dev);
+	return dsi;
 }
+EXPORT_SYMBOL(mipi_dsi_device_new);
 
 #if IS_ENABLED(CONFIG_OF)
 static struct mipi_dsi_device *
 of_mipi_dsi_device_add(struct mipi_dsi_host *host, struct device_node *node)
 {
-	struct mipi_dsi_device *dsi;
 	struct device *dev = host->dev;
+	struct mipi_dsi_device_info info = { };
 	int ret;
 	u32 reg;
 
@@ -145,31 +155,10 @@ of_mipi_dsi_device_add(struct mipi_dsi_host *host, struct device_node *node)
 		return ERR_PTR(-EINVAL);
 	}
 
-	if (reg > 3) {
-		dev_err(dev, "device node %s has invalid reg property: %u\n",
-			node->full_name, reg);
-		return ERR_PTR(-EINVAL);
-	}
-
-	dsi = mipi_dsi_device_alloc(host);
-	if (IS_ERR(dsi)) {
-		dev_err(dev, "failed to allocate DSI device %s: %ld\n",
-			node->full_name, PTR_ERR(dsi));
-		return dsi;
-	}
-
-	dsi->dev.of_node = of_node_get(node);
-	dsi->channel = reg;
+	info.reg = reg;
+	info.node = of_node_get(node);
 
-	ret = mipi_dsi_device_add(dsi);
-	if (ret) {
-		dev_err(dev, "failed to add DSI device %s: %d\n",
-			node->full_name, ret);
-		kfree(dsi);
-		return ERR_PTR(ret);
-	}
-
-	return dsi;
+	return mipi_dsi_device_new(host, &info);
 }
 #else
 static struct mipi_dsi_device *
include/drm/drm_mipi_dsi.h +15 -0
index f1d8d0d..90f4f3c 100644
@@ -140,6 +140,19 @@ enum mipi_dsi_pixel_format {
 };
 
 /**
+ * struct mipi_dsi_device_info - template for creating a mipi_dsi_device
+ * @reg: DSI virtual channel assigned to peripheral
+ * @node: pointer to OF device node
+ *
+ * This is populated and passed to mipi_dsi_device_new to create a new
+ * DSI device
+ */
+struct mipi_dsi_device_info {
+	u32 reg;
+	struct device_node *node;
+};
+
+/**
  * struct mipi_dsi_device - DSI peripheral device
  * @host: DSI host for this peripheral
  * @dev: driver model device node for this peripheral
@@ -174,6 +187,8 @@ ssize_t mipi_dsi_generic_write(struct mipi_dsi_device *dsi, const void *payload,
 ssize_t mipi_dsi_generic_read(struct mipi_dsi_device *dsi, const void *params,
 			      size_t num_params, void *data, size_t size);
 
+struct mipi_dsi_device *mipi_dsi_device_new(struct mipi_dsi_host *host,
+					    struct mipi_dsi_device_info *info);
 /**
  * enum mipi_dsi_dcs_tear_mode - Tearing Effect Output Line mode
  * @MIPI_DSI_DCS_TEAR_MODE_VBLANK: the TE output line consists of V-Blanking
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation
#62 lore raw

Re: [PATCH v4 2/6] drm/dsi: Refactor device creation

Quoted 1 line · Archit Taneja

Simplify the mipi dsi device creation process. device_initialize and

"MIPI" and "DSI", please.

Quoted 17 lines

device_add don't need to be called separately when creating mipi_dsi_device's. Use device_register instead to simplify things.

Create a helper function mipi_dsi_device_new which takes in struct mipi_dsi_device_info and mipi_dsi_host. It clubs the functions mipi_dsi_device_alloc and mipi_dsi_device_add into one.

mipi_dsi_device_info acts as a template to populate the dsi device information. This is populated by of_mipi_dsi_device_add and passed to mipi_dsi_device_new.

Later on, we'll provide mipi_dsi_device_new as a standalone way to create a dsi device not available via DT.

The new device creation process tries to closely follow what's been done in i2c_new_device in i2c-core.

Quoted 6 lines
---
 drivers/gpu/drm/drm_mipi_dsi.c | 61 +++++++++++++++++-------------------------
 include/drm/drm_mipi_dsi.h     | 15 +++++++++++
 2 files changed, 40 insertions(+), 36 deletions(-)

To be honest, I'm not sure I like this. If you want to have a simpler helper, why not implement it using the lower-level helpers. Really the only thing you're doing here is add a high-level helper that takes an info struct, whereas previously the same would be done by storing the info directly in the structure between allocation and addition of the device.

Initially the implementation was following that of platform devices, I see no reason to deviate from that. What you want here can easily be done by something like:

	struct mipi_dsi_device *
	mipi_dsi_device_register_full(struct mipi_dsi_host *host,
				      const struct mipi_dsi_device_info *info)
	{
		struct mipi_dsi_device *dsi;

		dsi = mipi_dsi_device_alloc(host);
		if (IS_ERR(dsi))
			return dsi;

		dsi->dev.of_node = info->node;
		dsi->channel = info->channel;

		err = mipi_dsi_device_add(dsi);
		if (err < 0) {
			...
		}

		return dsi;
	}

Thierry

_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel

#63 lore raw

Re: [PATCH v4 2/6] drm/dsi: Refactor device creation

Quoted 4 lines · Thierry Reding
Quoted 1 line · Archit Taneja

Simplify the mipi dsi device creation process. device_initialize and

"MIPI" and "DSI", please.

Sure, I'll replace with these and in the other patches.

Quoted 32 lines
Quoted 18 lines

device_add don't need to be called separately when creating mipi_dsi_device's. Use device_register instead to simplify things.

Create a helper function mipi_dsi_device_new which takes in struct mipi_dsi_device_info and mipi_dsi_host. It clubs the functions mipi_dsi_device_alloc and mipi_dsi_device_add into one.

mipi_dsi_device_info acts as a template to populate the dsi device information. This is populated by of_mipi_dsi_device_add and passed to mipi_dsi_device_new.

Later on, we'll provide mipi_dsi_device_new as a standalone way to create a dsi device not available via DT.

The new device creation process tries to closely follow what's been done in i2c_new_device in i2c-core.

Quoted 6 lines
---
  drivers/gpu/drm/drm_mipi_dsi.c | 61 +++++++++++++++++-------------------------
  include/drm/drm_mipi_dsi.h     | 15 +++++++++++
  2 files changed, 40 insertions(+), 36 deletions(-)

To be honest, I'm not sure I like this. If you want to have a simpler helper, why not implement it using the lower-level helpers. Really the only thing you're doing here is add a high-level helper that takes an info struct, whereas previously the same would be done by storing the info directly in the structure between allocation and addition of the device.

Quoted 2 lines

Initially the implementation was following that of platform devices, I see no reason to deviate from that. What you want here can easily be

I don't see why we need to call device_initialize and device_add
separately for DSI devices. From my (limited) understanding, we should
call these separately if we want to take a reference (using get_device()), or set up some private data before the bus's notifier kicks in.

Since the main purpose of the series is not to simplify the device creation code, I can drop this.

Quoted 23 lines

done by something like:

	struct mipi_dsi_device *
	mipi_dsi_device_register_full(struct mipi_dsi_host *host,
				      const struct mipi_dsi_device_info *info)
	{
		struct mipi_dsi_device *dsi;

		dsi = mipi_dsi_device_alloc(host);
		if (IS_ERR(dsi))
			return dsi;

		dsi->dev.of_node = info->node;
		dsi->channel = info->channel;

		err = mipi_dsi_device_add(dsi);
		if (err < 0) {
			...
		}

		return dsi;
	}
Quoted 2 lines

Thierry

This does look less intrusive. I'll consider switching to this.

Thanks,
Archit

Signature · 6 lines
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel
#64 lore raw

PATCH v4 3/6 drm/dsi: Try to match non-DT dsi devices

In reply to Archit Taneja

Add a device name field in mipi_dsi_device. This name is different from the actual dev name (which is of the format "hostname.reg"). When the device is created via DT, this name is set to the modalias string. In the non-DT case, the driver creating the DSI device provides the name by populating a filed in mipi_dsi_device_info.

Matching for DT case would be as it was before. For the non-DT case, we compare the device and driver names. Other buses (like i2c/spi) perform a non-DT match by comparing the device name and entries in the driver's id_table. Such a mechanism isn't used for the dsi bus.

---
 drivers/gpu/drm/drm_mipi_dsi.c | 25 ++++++++++++++++++++++++-
 include/drm/drm_mipi_dsi.h     |  6 ++++++
 2 files changed, 30 insertions(+), 1 deletion(-)
drivers/gpu/drm/drm_mipi_dsi.c +24 -1
index 9434585..5a46802 100644
@@ -45,9 +45,26 @@
  * subset of the MIPI DCS command set.
  */
 
+static const struct device_type mipi_dsi_device_type;
+
 static int mipi_dsi_device_match(struct device *dev, struct device_driver *drv)
 {
-	return of_driver_match_device(dev, drv);
+	struct mipi_dsi_device *dsi;
+
+	if (dev->type == &mipi_dsi_device_type)
+		dsi = to_mipi_dsi_device(dev);
+	else
+		return 0;
+
+	/* attempt OF style match */
+	if (of_driver_match_device(dev, drv))
+		return 1;
+
+	/* compare dsi device and driver names */
+	if (!strcmp(dsi->name, drv->name))
+		return 1;
+
+	return 0;
 }
 
 static const struct dev_pm_ops mipi_dsi_device_pm_ops = {
@@ -125,6 +142,7 @@ struct mipi_dsi_device *mipi_dsi_device_new(struct mipi_dsi_host *host,
 	dsi->dev.type = &mipi_dsi_device_type;
 	dsi->dev.of_node = info->node;
 	dsi->channel = info->reg;
+	strlcpy(dsi->name, info->type, sizeof(dsi->name));
 
 	dev_set_name(&dsi->dev, "%s.%d", dev_name(host->dev), info->reg);
 
@@ -148,6 +166,11 @@ of_mipi_dsi_device_add(struct mipi_dsi_host *host, struct device_node *node)
 	int ret;
 	u32 reg;
 
+	if (of_modalias_node(node, info.type, sizeof(info.type)) < 0) {
+		dev_err(dev, "modalias failure on %s\n", node->full_name);
+		return ERR_PTR(-EINVAL);
+	}
+
 	ret = of_property_read_u32(node, "reg", &reg);
 	if (ret) {
 		dev_err(dev, "device node %s has no valid reg property: %d\n",
include/drm/drm_mipi_dsi.h +6 -0
index 90f4f3c..cb084af 100644
@@ -139,8 +139,11 @@ enum mipi_dsi_pixel_format {
 	MIPI_DSI_FMT_RGB565,
 };
 
+#define DSI_DEV_NAME_SIZE		20
+
 /**
  * struct mipi_dsi_device_info - template for creating a mipi_dsi_device
+ * @type: dsi peripheral chip type
  * @reg: DSI virtual channel assigned to peripheral
  * @node: pointer to OF device node
  *
@@ -148,6 +151,7 @@ enum mipi_dsi_pixel_format {
  * DSI device
  */
 struct mipi_dsi_device_info {
+	char type[DSI_DEV_NAME_SIZE];
 	u32 reg;
 	struct device_node *node;
 };
@@ -156,6 +160,7 @@ struct mipi_dsi_device_info {
  * struct mipi_dsi_device - DSI peripheral device
  * @host: DSI host for this peripheral
  * @dev: driver model device node for this peripheral
+ * @name: dsi peripheral chip type
  * @channel: virtual channel assigned to the peripheral
  * @format: pixel format for video mode
  * @lanes: number of active data lanes
@@ -165,6 +170,7 @@ struct mipi_dsi_device {
 	struct mipi_dsi_host *host;
 	struct device dev;
 
+	char name[DSI_DEV_NAME_SIZE];
 	unsigned int channel;
 	unsigned int lanes;
 	enum mipi_dsi_pixel_format format;
Signature · 7 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel
#65 lore raw

Re: [PATCH v4 3/6] drm/dsi: Try to match non-DT dsi devices

Quoted 3 lines · Archit Taneja

Add a device name field in mipi_dsi_device. This name is different from the actual dev name (which is of the format "hostname.reg"). When the device is created via DT, this name is set to the modalias string.

Why? What's the use of setting this to the modalias string?

Quoted 5 lines

In the non-DT case, the driver creating the DSI device provides the name by populating a filed in mipi_dsi_device_info.

Matching for DT case would be as it was before. For the non-DT case, we compare the device and driver names. Other buses (like i2c/spi)

"I2C" and "SPI", please.

Quoted 2 lines

perform a non-DT match by comparing the device name and entries in the driver's id_table. Such a mechanism isn't used for the dsi bus.

"DSI", please.

Quoted 17 lines
---
 drivers/gpu/drm/drm_mipi_dsi.c | 25 ++++++++++++++++++++++++-
 include/drm/drm_mipi_dsi.h     |  6 ++++++
 2 files changed, 30 insertions(+), 1 deletion(-)
drivers/gpu/drm/drm_mipi_dsi.c +1 -0
index 9434585..5a46802 100644
@@ -45,9 +45,26 @@
  * subset of the MIPI DCS command set.
  */
 
+static const struct device_type mipi_dsi_device_type;

drivers/gpu/drm/drm_mipi_dsi.c line 57

Quoted 10 lines
drivers/gpu/drm/drm_mipi_dsi.c +7 -1
+
 static int mipi_dsi_device_match(struct device *dev, struct device_driver *drv)
 {
-	return of_driver_match_device(dev, drv);
+	struct mipi_dsi_device *dsi;
+
+	if (dev->type == &mipi_dsi_device_type)
+		dsi = to_mipi_dsi_device(dev);
+	else
+		return 0;

I think this check is redundant. I'm not aware of any case where the bus ->match() callback is called on a device that isn't on said bus.

drivers/gpu/drm/drm_mipi_dsi.c line 63

Quoted 5 lines
drivers/gpu/drm/drm_mipi_dsi.c +5 -0
+	/* attempt OF style match */
+	if (of_driver_match_device(dev, drv))
+		return 1;
+
+	/* compare dsi device and driver names */

"DSI", please.

drivers/gpu/drm/drm_mipi_dsi.c struct mipi_dsi_device *mipi_dsi_device_new(struct mipi_dsi_host *host, · line 145

Quoted 12 lines
drivers/gpu/drm/drm_mipi_dsi.c +5 -0
+	if (!strcmp(dsi->name, drv->name))
+		return 1;
+
+	return 0;
 }
 
 static const struct dev_pm_ops mipi_dsi_device_pm_ops = {
@@ -125,6 +142,7 @@ struct mipi_dsi_device *mipi_dsi_device_new(struct mipi_dsi_host *host,
 	dsi->dev.type = &mipi_dsi_device_type;
 	dsi->dev.of_node = info->node;
 	dsi->channel = info->reg;
+	strlcpy(dsi->name, info->type, sizeof(dsi->name));

Don't you need to check info->type != NULL before doing this?

Quoted 32 lines
drivers/gpu/drm/drm_mipi_dsi.c +5 -0
 	dev_set_name(&dsi->dev, "%s.%d", dev_name(host->dev), info->reg);
 
@@ -148,6 +166,11 @@ of_mipi_dsi_device_add(struct mipi_dsi_host *host, struct device_node *node)
 	int ret;
 	u32 reg;
 
+	if (of_modalias_node(node, info.type, sizeof(info.type)) < 0) {
+		dev_err(dev, "modalias failure on %s\n", node->full_name);
+		return ERR_PTR(-EINVAL);
+	}
+
 	ret = of_property_read_u32(node, "reg", &reg);
 	if (ret) {
 		dev_err(dev, "device node %s has no valid reg property: %d\n",
include/drm/drm_mipi_dsi.h +3 -0
index 90f4f3c..cb084af 100644
@@ -139,8 +139,11 @@ enum mipi_dsi_pixel_format {
 	MIPI_DSI_FMT_RGB565,
 };
 
+#define DSI_DEV_NAME_SIZE		20
+
 /**
  * struct mipi_dsi_device_info - template for creating a mipi_dsi_device
+ * @type: dsi peripheral chip type
  * @reg: DSI virtual channel assigned to peripheral
  * @node: pointer to OF device node
  *

include/drm/drm_mipi_dsi.h enum mipi_dsi_pixel_format { · line 154

Quoted 4 lines
include/drm/drm_mipi_dsi.h +1 -0
@@ -148,6 +151,7 @@ enum mipi_dsi_pixel_format {
  * DSI device
  */
 struct mipi_dsi_device_info {
+	char type[DSI_DEV_NAME_SIZE];

Why limit ourselves to 20 characters? And why even so complicated? Isn't the type always static when someone specifies this? Couldn't we simply use a const char *name here instead?

Thierry

_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel

#66 lore raw

Re: [PATCH v4 3/6] drm/dsi: Try to match non-DT dsi devices

Quoted 6 lines · Thierry Reding
Quoted 3 lines · Archit Taneja

Add a device name field in mipi_dsi_device. This name is different from the actual dev name (which is of the format "hostname.reg"). When the device is created via DT, this name is set to the modalias string.

Why? What's the use of setting this to the modalias string?

There is no use to set it in the DT case. It's just set for the sake of consistency between the non-DT and DT devices. For now, dsi->name is just used for device/driver matching for non-DT devices. There's no harm in setting it to a valid name for DT devices.

Quoted 30 lines
Quoted 6 lines

In the non-DT case, the driver creating the DSI device provides the name by populating a filed in mipi_dsi_device_info.

Matching for DT case would be as it was before. For the non-DT case, we compare the device and driver names. Other buses (like i2c/spi)

"I2C" and "SPI", please.

Quoted 2 lines

perform a non-DT match by comparing the device name and entries in the driver's id_table. Such a mechanism isn't used for the dsi bus.

"DSI", please.

Quoted 16 lines
---
  drivers/gpu/drm/drm_mipi_dsi.c | 25 ++++++++++++++++++++++++-
  include/drm/drm_mipi_dsi.h     |  6 ++++++
  2 files changed, 30 insertions(+), 1 deletion(-)
drivers/gpu/drm/drm_mipi_dsi.c +0 -0
index 9434585..5a46802 100644
@@ -45,9 +45,26 @@
   * subset of the MIPI DCS command set.
   */
 
Quoted 14 lines

drivers/gpu/drm/drm_mipi_dsi.c line 57

Quoted 11 lines
drivers/gpu/drm/drm_mipi_dsi.c +8 -1
+static const struct device_type mipi_dsi_device_type;
+
  static int mipi_dsi_device_match(struct device *dev, struct device_driver *drv)
  {
-	return of_driver_match_device(dev, drv);
+	struct mipi_dsi_device *dsi;
+
+	if (dev->type == &mipi_dsi_device_type)
+		dsi = to_mipi_dsi_device(dev);
+	else
+		return 0;

I think this check is redundant. I'm not aware of any case where the bus ->match() callback is called on a device that isn't on said bus.

You're right. I'll drop this.

Quoted 15 lines

drivers/gpu/drm/drm_mipi_dsi.c line 63

Quoted 6 lines
drivers/gpu/drm/drm_mipi_dsi.c +5 -0
+	/* attempt OF style match */
+	if (of_driver_match_device(dev, drv))
+		return 1;
+
+	/* compare dsi device and driver names */

"DSI", please.

Quoted 6 lines
drivers/gpu/drm/drm_mipi_dsi.c +4 -0
+	if (!strcmp(dsi->name, drv->name))
+		return 1;
+
+	return 0;
  }
 
Quoted 8 lines

drivers/gpu/drm/drm_mipi_dsi.c struct mipi_dsi_device *mipi_dsi_device_new(struct mipi_dsi_host *host, · line 145

Quoted 6 lines
drivers/gpu/drm/drm_mipi_dsi.c +1 -0
  static const struct dev_pm_ops mipi_dsi_device_pm_ops = {
@@ -125,6 +142,7 @@ struct mipi_dsi_device *mipi_dsi_device_new(struct mipi_dsi_host *host,
  	dsi->dev.type = &mipi_dsi_device_type;
  	dsi->dev.of_node = info->node;
  	dsi->channel = info->reg;
+	strlcpy(dsi->name, info->type, sizeof(dsi->name));

Don't you need to check info->type != NULL before doing this?

It's not needed with the way struct mipi_dsi_device_info is currently defined.

Quoted 33 lines
Quoted 33 lines
drivers/gpu/drm/drm_mipi_dsi.c +5 -0
  	dev_set_name(&dsi->dev, "%s.%d", dev_name(host->dev), info->reg);
 
@@ -148,6 +166,11 @@ of_mipi_dsi_device_add(struct mipi_dsi_host *host, struct device_node *node)
  	int ret;
  	u32 reg;
 
+	if (of_modalias_node(node, info.type, sizeof(info.type)) < 0) {
+		dev_err(dev, "modalias failure on %s\n", node->full_name);
+		return ERR_PTR(-EINVAL);
+	}
+
  	ret = of_property_read_u32(node, "reg", &reg);
  	if (ret) {
  		dev_err(dev, "device node %s has no valid reg property: %d\n",
include/drm/drm_mipi_dsi.h +3 -0
index 90f4f3c..cb084af 100644
@@ -139,8 +139,11 @@ enum mipi_dsi_pixel_format {
  	MIPI_DSI_FMT_RGB565,
  };
 
+#define DSI_DEV_NAME_SIZE		20
+
  /**
   * struct mipi_dsi_device_info - template for creating a mipi_dsi_device
+ * @type: dsi peripheral chip type
   * @reg: DSI virtual channel assigned to peripheral
   * @node: pointer to OF device node
   *
@@ -148,6 +151,7 @@ enum mipi_dsi_pixel_format {
Quoted 8 lines

include/drm/drm_mipi_dsi.h enum mipi_dsi_pixel_format { · line 154

Quoted 4 lines
include/drm/drm_mipi_dsi.h +1 -0
   * DSI device
   */
  struct mipi_dsi_device_info {
+	char type[DSI_DEV_NAME_SIZE];

Why limit ourselves to 20 characters? And why even so complicated? Isn't the type always static when someone specifies this? Couldn't we simply use a const char *name here instead?

In the case where the device is registered via DT, we would need space allocated for 'type' to copy the modalias string into it. Having const char *type would make it a bit complicated for the DT path.

The mipi_dsi_device_info struct was based on
the i2c_board_info/spi_board_info structs, and they have type/modalias members declared as array of chars. I kind of followed suit without putting to much thought on member type.

Archit

Quoted 3 lines

Thierry

Signature · 6 lines
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel
#67 lore raw

PATCH v4 4/6 drm/dsi: Check for used channels

In reply to Archit Taneja

We don't check whether a previously registered mipi_dsi_device under the same host shares the same virtual channel.

Before registering, check if any of the registered devices doesn't already have the same virtual channel.

This wasn't crucial when all the devices under a host were populated via DT. Now that we also support creating devices manually, we could end up in a situation where a driver tries to create a device with a virtual channel already taken by a device populated in DT.

---
 drivers/gpu/drm/drm_mipi_dsi.c | 26 ++++++++++++++++++++++++--
 1 file changed, 24 insertions(+), 2 deletions(-)
drivers/gpu/drm/drm_mipi_dsi.c +24 -2
index 5a46802..7a81171 100644
@@ -119,6 +119,22 @@ static const struct device_type mipi_dsi_device_type = {
 	.release = mipi_dsi_dev_release,
 };
 
+static int __dsi_check_chan_busy(struct device *dev, void *data)
+{
+	struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev);
+	u32 *reg = data;
+
+	if (dsi && dsi->channel == *reg)
+		return -EBUSY;
+
+	return 0;
+}
+
+static int mipi_dsi_check_chan_busy(struct mipi_dsi_host *host, u32 reg)
+{
+	return device_for_each_child(host->dev, &reg, __dsi_check_chan_busy);
+}
+
 struct mipi_dsi_device *mipi_dsi_device_new(struct mipi_dsi_host *host,
 					    struct mipi_dsi_device_info *info)
 {
@@ -146,14 +162,20 @@ struct mipi_dsi_device *mipi_dsi_device_new(struct mipi_dsi_host *host,
 
 	dev_set_name(&dsi->dev, "%s.%d", dev_name(host->dev), info->reg);
 
+	ret = mipi_dsi_check_chan_busy(host, info->reg);
+	if (ret)
+		goto err;
+
 	ret = device_register(&dsi->dev);
 	if (ret) {
 		dev_err(dev, "failed to register device: %d\n", ret);
-		kfree(dsi);
-		return ERR_PTR(ret);
+		goto err;
 	}
 
 	return dsi;
+err:
+	kfree(dsi);
+	return ERR_PTR(ret);
 }
 EXPORT_SYMBOL(mipi_dsi_device_new);
 
Signature · 7 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel
#68 lore raw

Re: [PATCH v4 4/6] drm/dsi: Check for used channels

Quoted 11 lines · Archit Taneja

We don't check whether a previously registered mipi_dsi_device under the same host shares the same virtual channel.

Before registering, check if any of the registered devices doesn't already have the same virtual channel.

This wasn't crucial when all the devices under a host were populated via DT. Now that we also support creating devices manually, we could end up in a situation where a driver tries to create a device with a virtual channel already taken by a device populated in DT.

Quoted 5 lines
---
 drivers/gpu/drm/drm_mipi_dsi.c | 26 ++++++++++++++++++++++++--
 1 file changed, 24 insertions(+), 2 deletions(-)

I don't think this is necessary. The device name will be composed of the host's name, a '.' and the virtual channel ID, and the device core will refuse to create two devices with the same name.

Thierry

#69 lore raw

Re: [PATCH v4 4/6] drm/dsi: Check for used channels

Quoted 18 lines · Thierry Reding
Quoted 11 lines · Archit Taneja

We don't check whether a previously registered mipi_dsi_device under the same host shares the same virtual channel.

Before registering, check if any of the registered devices doesn't already have the same virtual channel.

This wasn't crucial when all the devices under a host were populated via DT. Now that we also support creating devices manually, we could end up in a situation where a driver tries to create a device with a virtual channel already taken by a device populated in DT.

Quoted 5 lines
---
  drivers/gpu/drm/drm_mipi_dsi.c | 26 ++++++++++++++++++++++++--
  1 file changed, 24 insertions(+), 2 deletions(-)
Quoted 3 lines

I don't think this is necessary. The device name will be composed of the host's name, a '.' and the virtual channel ID, and the device core will refuse to create two devices with the same name.

That's a good point. I'll drop this patch.

Archit

Quoted 3 lines

Thierry

Signature · 5 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel
#70 lore raw

PATCH v4 5/6 drm/dsi: Add routine to unregister dsi device

In reply to Archit Taneja

A driver calling mipi_dsi_device_new might want to unregister the device once it's done. It might also require it in an error handling path in case something didn't go right.

---
 include/drm/drm_mipi_dsi.h | 5 +++++
 1 file changed, 5 insertions(+)
include/drm/drm_mipi_dsi.h +5 -0
index cb084af..410d8b5 100644
@@ -195,6 +195,11 @@ ssize_t mipi_dsi_generic_read(struct mipi_dsi_device *dsi, const void *params,
 
 struct mipi_dsi_device *mipi_dsi_device_new(struct mipi_dsi_host *host,
 					    struct mipi_dsi_device_info *info);
+static inline void mipi_dsi_device_unregister(struct mipi_dsi_device *dsi)
+{
+	device_unregister(&dsi->dev);
+}
+
 /**
  * enum mipi_dsi_dcs_tear_mode - Tearing Effect Output Line mode
  * @MIPI_DSI_DCS_TEAR_MODE_VBLANK: the TE output line consists of V-Blanking
Signature · 7 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel
#71 lore raw

Re: [PATCH v4 5/6] drm/dsi: Add routine to unregister dsi device

Quoted 15 lines · Archit Taneja

A driver calling mipi_dsi_device_new might want to unregister the device once it's done. It might also require it in an error handling path in case something didn't go right.

---
 include/drm/drm_mipi_dsi.h | 5 +++++
 1 file changed, 5 insertions(+)
include/drm/drm_mipi_dsi.h +0 -0
index cb084af..410d8b5 100644

include/drm/drm_mipi_dsi.h ssize_t mipi_dsi_generic_read(struct mipi_dsi_device *dsi, const void *params, · line 201

Quoted 7 lines
include/drm/drm_mipi_dsi.h +4 -0
@@ -195,6 +195,11 @@ ssize_t mipi_dsi_generic_read(struct mipi_dsi_device *dsi, const void *params,
 
 struct mipi_dsi_device *mipi_dsi_device_new(struct mipi_dsi_host *host,
 					    struct mipi_dsi_device_info *info);
+static inline void mipi_dsi_device_unregister(struct mipi_dsi_device *dsi)
+{
+	device_unregister(&dsi->dev);
+}

This is the same, essentially, as mipi_dsi_remove_device_fn(). I think this should move into drm_mipi_dsi.c and mipi_dsi_remove_device_fn() should call this new function so that both OF and !OF share the same code for this.

Thierry

#72 lore raw

Re: [PATCH v4 5/6] drm/dsi: Add routine to unregister dsi device

Quoted 17 lines · Thierry Reding
Quoted 16 lines · Archit Taneja

A driver calling mipi_dsi_device_new might want to unregister the device once it's done. It might also require it in an error handling path in case something didn't go right.

---
  include/drm/drm_mipi_dsi.h | 5 +++++
  1 file changed, 5 insertions(+)
include/drm/drm_mipi_dsi.h +0 -0
index cb084af..410d8b5 100644
@@ -195,6 +195,11 @@ ssize_t mipi_dsi_generic_read(struct mipi_dsi_device *dsi, const void *params,
 
Quoted 11 lines

include/drm/drm_mipi_dsi.h ssize_t mipi_dsi_generic_read(struct mipi_dsi_device *dsi, const void *params, · line 201

Quoted 6 lines
include/drm/drm_mipi_dsi.h +4 -0
  struct mipi_dsi_device *mipi_dsi_device_new(struct mipi_dsi_host *host,
  					    struct mipi_dsi_device_info *info);
+static inline void mipi_dsi_device_unregister(struct mipi_dsi_device *dsi)
+{
+	device_unregister(&dsi->dev);
+}

This is the same, essentially, as mipi_dsi_remove_device_fn(). I think this should move into drm_mipi_dsi.c and mipi_dsi_remove_device_fn() should call this new function so that both OF and !OF share the same code for this.

I can do this.

Thanks,
Archit

Signature · 1 line
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
#73 lore raw

PATCH v4 6/6 drm/dsi: Get DSI host by DT device node

In reply to Archit Taneja

mipi_dsi_devices are inherently aware of their host because they share a parent-child hierarchy in the device tree.

non-dsi drivers that create dsi device don't have this data. In order to get this information, they require to a phandle to the dsi host in the device tree.

Maintain a list of all the hosts DSI that are currently registered.

This list will be used to find the mipi_dsi_host corresponding to the device_node passed in of_find_mipi_dsi_host_by_node.

---
 drivers/gpu/drm/drm_mipi_dsi.c | 38 ++++++++++++++++++++++++++++++++++++++
 include/drm/drm_mipi_dsi.h     |  3 +++
 2 files changed, 41 insertions(+)
drivers/gpu/drm/drm_mipi_dsi.c +38 -0
index 7a81171..e40a665 100644
@@ -213,6 +213,36 @@ of_mipi_dsi_device_add(struct mipi_dsi_host *host, struct device_node *node)
 }
 #endif
 
+static DEFINE_MUTEX(host_lock);
+static LIST_HEAD(host_list);
+
+/**
+ * of_find_mipi_dsi_host_by_node() - find the MIPI DSI host matching a
+ *    device tree node
+ * @node: device tree node
+ *
+ * Return: A pointer to the MIPI DSI host corresponding to @np or NULL if no
+ *    such device exists (or has not been registered yet).
+ */
+struct mipi_dsi_host *of_find_mipi_dsi_host_by_node(struct device_node *node)
+{
+	struct mipi_dsi_host *host;
+
+	mutex_lock(&host_lock);
+
+	list_for_each_entry(host, &host_list, list) {
+		if (host->dev->of_node == node) {
+			mutex_unlock(&host_lock);
+			return host;
+		}
+	}
+
+	mutex_unlock(&host_lock);
+
+	return NULL;
+}
+EXPORT_SYMBOL(of_find_mipi_dsi_host_by_node);
+
 int mipi_dsi_host_register(struct mipi_dsi_host *host)
 {
 	struct device_node *node;
@@ -224,6 +254,10 @@ int mipi_dsi_host_register(struct mipi_dsi_host *host)
 		of_mipi_dsi_device_add(host, node);
 	}
 
+	mutex_lock(&host_lock);
+	list_add_tail(&host->list, &host_list);
+	mutex_unlock(&host_lock);
+
 	return 0;
 }
 EXPORT_SYMBOL(mipi_dsi_host_register);
@@ -240,6 +274,10 @@ static int mipi_dsi_remove_device_fn(struct device *dev, void *priv)
 void mipi_dsi_host_unregister(struct mipi_dsi_host *host)
 {
 	device_for_each_child(host->dev, NULL, mipi_dsi_remove_device_fn);
+
+	mutex_lock(&host_lock);
+	list_del_init(&host->list);
+	mutex_unlock(&host_lock);
 }
 EXPORT_SYMBOL(mipi_dsi_host_unregister);
 
include/drm/drm_mipi_dsi.h +3 -0
index 410d8b5..e5c1df9 100644
@@ -96,14 +96,17 @@ struct mipi_dsi_host_ops {
  * struct mipi_dsi_host - DSI host device
  * @dev: driver model device node for this DSI host
  * @ops: DSI host operations
+ * @list: list management
  */
 struct mipi_dsi_host {
 	struct device *dev;
 	const struct mipi_dsi_host_ops *ops;
+	struct list_head list;
 };
 
 int mipi_dsi_host_register(struct mipi_dsi_host *host);
 void mipi_dsi_host_unregister(struct mipi_dsi_host *host);
+struct mipi_dsi_host *of_find_mipi_dsi_host_by_node(struct device_node *node);
 
 /* DSI mode flags */
 
Signature · 7 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel
#74 lore raw

Re: [PATCH v4 6/6] drm/dsi: Get DSI host by DT device node

Quoted 12 lines · Archit Taneja

mipi_dsi_devices are inherently aware of their host because they share a parent-child hierarchy in the device tree.

non-dsi drivers that create dsi device don't have this data. In order to get this information, they require to a phandle to the dsi host in the device tree.

Maintain a list of all the hosts DSI that are currently registered.

This list will be used to find the mipi_dsi_host corresponding to the device_node passed in of_find_mipi_dsi_host_by_node.

Quoted 6 lines
---
 drivers/gpu/drm/drm_mipi_dsi.c | 38 ++++++++++++++++++++++++++++++++++++++
 include/drm/drm_mipi_dsi.h     |  3 +++
 2 files changed, 41 insertions(+)

Please be more consistent with the spelling. Abbreviations should be all capitals. Also s/mipi_dsi_devices/MIPI DSI devices/, and so on.

Otherwise I guess this makes sense.

Thierry

#75 lore raw

Re: [PATCH v4 6/6] drm/dsi: Get DSI host by DT device node

Quoted 20 lines · Thierry Reding
Quoted 12 lines · Archit Taneja

mipi_dsi_devices are inherently aware of their host because they share a parent-child hierarchy in the device tree.

non-dsi drivers that create dsi device don't have this data. In order to get this information, they require to a phandle to the dsi host in the device tree.

Maintain a list of all the hosts DSI that are currently registered.

This list will be used to find the mipi_dsi_host corresponding to the device_node passed in of_find_mipi_dsi_host_by_node.

Quoted 6 lines
---
  drivers/gpu/drm/drm_mipi_dsi.c | 38 ++++++++++++++++++++++++++++++++++++++
  include/drm/drm_mipi_dsi.h     |  3 +++
  2 files changed, 41 insertions(+)
Quoted 2 lines

Please be more consistent with the spelling. Abbreviations should be all capitals. Also s/mipi_dsi_devices/MIPI DSI devices/, and so on.

I'll ensure the abbreviations are consistent in the next revision.

Quoted 2 lines

Otherwise I guess this makes sense.

Thanks for the review.

Thanks,
Archit

Signature · 5 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel
#76 lore raw
In reply to Archit Taneja

Hi Thierry,

Can you pick up these DSI patches, or would it make more sense for these to go via someone else?

Thanks,
Archit

Quoted 35 lines · Archit Taneja

We are currently restricted when it comes to supporting DSI on devices that have a non-DSI control bus. For example, DSI encoder chips are available in the market that are configured via i2c. Configuring their registers via DSI bus is either optional or not available at all.

These devices still need to pass DSI parameters (data lanes, mode flags etc) to the DSI host they are connected to. We don't have a way to do that at the moment.

After some discussions on the previous RFC[1], we decided to support this by providing additional API in drm_mipi_dsi which lets us create new DSI devices without the need of them to have a DT node.

[1]: https://lkml.org/lkml/2015/6/30/42

Changes in v4:
- Added a new patch that fixes build issues when CONFIG_OF is not set.

Changes in v3:

- Incorporated misc comments by Andrzej. Changed from RFC to a PATCH set.
- Fixed htmldocs warnings.

Archit Taneja (6):
drm/dsi: check for CONFIG_OF when defining of_mipi_dsi_device_add drm/dsi: Refactor device creation
drm/dsi: Try to match non-DT dsi devices
drm/dsi: Check for used channels
drm/dsi: Add routine to unregister dsi device
drm/dsi: Get DSI host by DT device node

  drivers/gpu/drm/drm_mipi_dsi.c | 144 ++++++++++++++++++++++++++++++++---------
  include/drm/drm_mipi_dsi.h     |  29 +++++++++
  2 files changed, 141 insertions(+), 32 deletions(-)
Signature · 1 line
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
#77 lore raw

v5 cover drm/dsi: DSI for devices with different control bus

In reply to Archit Taneja

We are currently restricted when it comes to supporting DSI on devices that have a non-DSI control bus. For example, DSI encoder chips are available in the market that are configured via i2c. Configuring their registers via DSI bus is either optional or not available at all.

These devices still need to pass DSI parameters (data lanes, mode flags etc) to the DSI host they are connected to. We don't have a way to do that at the moment.

After some discussions on the previous RFC[1], we decided to support this by providing additional API in drm_mipi_dsi.c which lets us create new DSI devices without the need of them to have a DT node.

[1]: https://lkml.org/lkml/2015/6/30/42

Changes in v5:
- Simplify refactoring as suggested by Thierry.
- Use abbreviations correctly.
- Drop "drm/dsi: Check for used channels"
- Return the correct encoded error code for of_mipi_dsi_device_add when CONFIG_OF is disabled.
- Use mipi_dsi_device_unregister to implement mipi_dsi_remove_device_fn() too.

Changes in v4:
- Added a new patch that fixes build issues when CONFIG_OF is not set.

Changes in v3:

- Incorporated misc comments by Andrzej. Changed from RFC to a PATCH set.
- Fixed htmldocs warnings.

Archit Taneja (5):
drm/dsi: check for CONFIG_OF when defining of_mipi_dsi_device_add drm/dsi: Use mipi_dsi_device_register_full for DSI device creation drm/dsi: Try to match non-DT DSI devices
drm/dsi: Add routine to unregister a DSI device drm/dsi: Get DSI host by DT device node

 drivers/gpu/drm/drm_mipi_dsi.c | 127 +++++++++++++++++++++++++++++++++++++----
 include/drm/drm_mipi_dsi.h     |  26 +++++++++
 2 files changed, 141 insertions(+), 12 deletions(-)
Signature · 7 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel
#78 lore raw

PATCH v5 1/5 drm/dsi: check for CONFIG_OF when defining of_mipi_dsi_device_add

of_mipi_dsi_device_add is used only when CONFIG_OF is enabled. It currently works if OF support is disabled, but this will change when we add more functionality to it.

Define the original func if CONFIG_OF is enabled. Define a dummy func otherwise.

---
 drivers/gpu/drm/drm_mipi_dsi.c | 8 ++++++++
 1 file changed, 8 insertions(+)
drivers/gpu/drm/drm_mipi_dsi.c +8 -0
index 6e6a9c5..4f2a704 100644
@@ -129,6 +129,7 @@ static int mipi_dsi_device_add(struct mipi_dsi_device *dsi)
 	return device_add(&dsi->dev);
 }
 
+#if IS_ENABLED(CONFIG_OF)
 static struct mipi_dsi_device *
 of_mipi_dsi_device_add(struct mipi_dsi_host *host, struct device_node *node)
 {
@@ -170,6 +171,13 @@ of_mipi_dsi_device_add(struct mipi_dsi_host *host, struct device_node *node)
 
 	return dsi;
 }
+#else
+static struct mipi_dsi_device *
+of_mipi_dsi_device_add(struct mipi_dsi_host *host, struct device_node *node)
+{
+	return ERR_PTR(-ENODEV);
+}
+#endif
 
 int mipi_dsi_host_register(struct mipi_dsi_host *host)
 {
Signature · 7 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel
#79 lore raw

PATCH v5 2/5 drm/dsi: Use mipi_dsi_device_register_full for DSI device creation

In reply to Archit Taneja

Use mipi_dsi_device_register_full for device creation. This takes in mipi_dsi_device_info as a template to populate the DSI device information.

The reason to introduce this is to have a way to create DSI devices not available via DT. Drivers that want to create a DSI device can populate mipi_dsi_device_info and call this function. For DSI devices available via DT, of_mipi_dsi_device_add is used as before, but this now calls mipi_dsi_device_register_full internally.

---
 drivers/gpu/drm/drm_mipi_dsi.c | 64 +++++++++++++++++++++++++++++++-----------
 include/drm/drm_mipi_dsi.h     | 16 +++++++++++
 2 files changed, 63 insertions(+), 17 deletions(-)
drivers/gpu/drm/drm_mipi_dsi.c +47 -17
index 4f2a704..5d7243d 100644
@@ -133,8 +133,8 @@ static int mipi_dsi_device_add(struct mipi_dsi_device *dsi)
 static struct mipi_dsi_device *
 of_mipi_dsi_device_add(struct mipi_dsi_host *host, struct device_node *node)
 {
-	struct mipi_dsi_device *dsi;
 	struct device *dev = host->dev;
+	struct mipi_dsi_device_info info = { };
 	int ret;
 	u32 reg;
 
@@ -145,39 +145,69 @@ of_mipi_dsi_device_add(struct mipi_dsi_host *host, struct device_node *node)
 		return ERR_PTR(-EINVAL);
 	}
 
-	if (reg > 3) {
-		dev_err(dev, "device node %s has invalid reg property: %u\n",
-			node->full_name, reg);
+	info.channel = reg;
+	info.node = of_node_get(node);
+
+	return mipi_dsi_device_register_full(host, &info);
+}
+#else
+static struct mipi_dsi_device *
+of_mipi_dsi_device_add(struct mipi_dsi_host *host, struct device_node *node)
+{
+	return ERR_PTR(-ENODEV);
+}
+#endif
+
+/**
+ * mipi_dsi_device_register_full - create a MIPI DSI device
+ * @host: DSI host to which this device is connected
+ * @info: pointer to template containing DSI device information
+ *
+ * Create a MIPI DSI device by using the device information provided by
+ * mipi_dsi_device_info template
+ *
+ * Returns:
+ * A pointer to the newly created MIPI DSI device, or, a pointer encoded
+ * with an error
+ */
+struct mipi_dsi_device *
+mipi_dsi_device_register_full(struct mipi_dsi_host *host,
+			      const struct mipi_dsi_device_info *info)
+{
+	struct mipi_dsi_device *dsi;
+	struct device *dev = host->dev;
+	int ret;
+
+	if (!info) {
+		dev_err(dev, "invalid mipi_dsi_device_info pointer\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	if (info->channel > 3) {
+		dev_err(dev, "invalid virtual channel: %u\n", info->channel);
 		return ERR_PTR(-EINVAL);
 	}
 
 	dsi = mipi_dsi_device_alloc(host);
 	if (IS_ERR(dsi)) {
-		dev_err(dev, "failed to allocate DSI device %s: %ld\n",
-			node->full_name, PTR_ERR(dsi));
+		dev_err(dev, "failed to allocate DSI device %ld\n",
+			PTR_ERR(dsi));
 		return dsi;
 	}
 
-	dsi->dev.of_node = of_node_get(node);
-	dsi->channel = reg;
+	dsi->dev.of_node = info->node;
+	dsi->channel = info->channel;
 
 	ret = mipi_dsi_device_add(dsi);
 	if (ret) {
-		dev_err(dev, "failed to add DSI device %s: %d\n",
-			node->full_name, ret);
+		dev_err(dev, "failed to add DSI device %d\n", ret);
 		kfree(dsi);
 		return ERR_PTR(ret);
 	}
 
 	return dsi;
 }
-#else
-static struct mipi_dsi_device *
-of_mipi_dsi_device_add(struct mipi_dsi_host *host, struct device_node *node)
-{
-	return ERR_PTR(-ENODEV);
-}
-#endif
+EXPORT_SYMBOL(mipi_dsi_device_register_full);
 
 int mipi_dsi_host_register(struct mipi_dsi_host *host)
 {
include/drm/drm_mipi_dsi.h +16 -0
index 1b3b1f8..ce5eae43 100644
@@ -139,6 +139,19 @@ enum mipi_dsi_pixel_format {
 	MIPI_DSI_FMT_RGB565,
 };
 
+ /**
+ * struct mipi_dsi_device_info - template for creating a mipi_dsi_device
+ * @channel: DSI virtual channel assigned to peripheral
+ * @node: pointer to OF device node
+ *
+ * This is populated and passed to mipi_dsi_device_new to create a new
+ * DSI device
+ */
+struct mipi_dsi_device_info {
+	u32 channel;
+	struct device_node *node;
+};
+
 /**
  * struct mipi_dsi_device - DSI peripheral device
  * @host: DSI host for this peripheral
@@ -188,6 +201,9 @@ static inline int mipi_dsi_pixel_format_to_bpp(enum mipi_dsi_pixel_format fmt)
 	return -EINVAL;
 }
 
+struct mipi_dsi_device *
+mipi_dsi_device_register_full(struct mipi_dsi_host *host,
+			      const struct mipi_dsi_device_info *info);
 struct mipi_dsi_device *of_find_mipi_dsi_device_by_node(struct device_node *np);
 int mipi_dsi_attach(struct mipi_dsi_device *dsi);
 int mipi_dsi_detach(struct mipi_dsi_device *dsi);
Signature · 7 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel
#80 lore raw

PATCH v5 3/5 drm/dsi: Try to match non-DT DSI devices

In reply to Archit Taneja

Add a device name field in mipi_dsi_device. This name is different from the actual dev name (which is of the format "hostname.reg"). When the device is created via DT, this name is set to the modalias string. In the non-DT case, the driver creating the DSI device provides the name by populating a filed in mipi_dsi_device_info.

Matching for DT case would be as it was before. For the non-DT case, we compare the device and driver names. Other buses (like I2C/SPI) perform a non-DT match by comparing the device name and entries in the driver's id_table. Such a mechanism isn't used for the DSI bus.

---
 drivers/gpu/drm/drm_mipi_dsi.c | 18 +++++++++++++++++-
 include/drm/drm_mipi_dsi.h     | 10 ++++++++--
 2 files changed, 25 insertions(+), 3 deletions(-)
drivers/gpu/drm/drm_mipi_dsi.c +17 -1
index 5d7243d..42a7aac 100644
@@ -47,7 +47,17 @@
 
 static int mipi_dsi_device_match(struct device *dev, struct device_driver *drv)
 {
-	return of_driver_match_device(dev, drv);
+	struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev);
+
+	/* attempt OF style match */
+	if (of_driver_match_device(dev, drv))
+		return 1;
+
+	/* compare DSI device and driver names */
+	if (!strcmp(dsi->name, drv->name))
+		return 1;
+
+	return 0;
 }
 
 static const struct dev_pm_ops mipi_dsi_device_pm_ops = {
@@ -138,6 +148,11 @@ of_mipi_dsi_device_add(struct mipi_dsi_host *host, struct device_node *node)
 	int ret;
 	u32 reg;
 
+	if (of_modalias_node(node, info.type, sizeof(info.type)) < 0) {
+		dev_err(dev, "modalias failure on %s\n", node->full_name);
+		return ERR_PTR(-EINVAL);
+	}
+
 	ret = of_property_read_u32(node, "reg", &reg);
 	if (ret) {
 		dev_err(dev, "device node %s has no valid reg property: %d\n",
@@ -197,6 +212,7 @@ mipi_dsi_device_register_full(struct mipi_dsi_host *host,
 
 	dsi->dev.of_node = info->node;
 	dsi->channel = info->channel;
+	strlcpy(dsi->name, info->type, sizeof(dsi->name));
 
 	ret = mipi_dsi_device_add(dsi);
 	if (ret) {
include/drm/drm_mipi_dsi.h +8 -2
index ce5eae43..a914116 100644
@@ -139,15 +139,19 @@ enum mipi_dsi_pixel_format {
 	MIPI_DSI_FMT_RGB565,
 };
 
- /**
+#define DSI_DEV_NAME_SIZE		20
+
+/**
  * struct mipi_dsi_device_info - template for creating a mipi_dsi_device
+ * @type: DSI peripheral chip type
  * @channel: DSI virtual channel assigned to peripheral
- * @node: pointer to OF device node
+ * @node: pointer to OF device node or NULL
  *
  * This is populated and passed to mipi_dsi_device_new to create a new
  * DSI device
  */
 struct mipi_dsi_device_info {
+	char type[DSI_DEV_NAME_SIZE];
 	u32 channel;
 	struct device_node *node;
 };
@@ -156,6 +160,7 @@ struct mipi_dsi_device_info {
  * struct mipi_dsi_device - DSI peripheral device
  * @host: DSI host for this peripheral
  * @dev: driver model device node for this peripheral
+ * @name: DSI peripheral chip type
  * @channel: virtual channel assigned to the peripheral
  * @format: pixel format for video mode
  * @lanes: number of active data lanes
@@ -165,6 +170,7 @@ struct mipi_dsi_device {
 	struct mipi_dsi_host *host;
 	struct device dev;
 
+	char name[DSI_DEV_NAME_SIZE];
 	unsigned int channel;
 	unsigned int lanes;
 	enum mipi_dsi_pixel_format format;
Signature · 7 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel
#81 lore raw

PATCH v5 4/5 drm/dsi: Add routine to unregister a DSI device

In reply to Archit Taneja

A driver calling mipi_dsi_device_register_full might want to unregister the device once it's done. It might also require it in an error handling path in case something didn't go right.

Create mipi_dsi_device_unregister for this purpse, use it within mipi_dsi_remove_device_fn as it does the same thing.

---
 drivers/gpu/drm/drm_mipi_dsi.c | 12 +++++++++++-
 include/drm/drm_mipi_dsi.h     |  1 +
 2 files changed, 12 insertions(+), 1 deletion(-)
drivers/gpu/drm/drm_mipi_dsi.c +11 -1
index 42a7aac..f2f5a6d 100644
@@ -225,6 +225,16 @@ mipi_dsi_device_register_full(struct mipi_dsi_host *host,
 }
 EXPORT_SYMBOL(mipi_dsi_device_register_full);
 
+/**
+ * mipi_dsi_device_unregister - unregister MIPI DSI device
+ * @dsi: DSI peripheral device
+ */
+void mipi_dsi_device_unregister(struct mipi_dsi_device *dsi)
+{
+	device_unregister(&dsi->dev);
+}
+EXPORT_SYMBOL(mipi_dsi_device_unregister);
+
 int mipi_dsi_host_register(struct mipi_dsi_host *host)
 {
 	struct device_node *node;
@@ -244,7 +254,7 @@ static int mipi_dsi_remove_device_fn(struct device *dev, void *priv)
 {
 	struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev);
 
-	device_unregister(&dsi->dev);
+	mipi_dsi_device_unregister(dsi);
 
 	return 0;
 }
include/drm/drm_mipi_dsi.h +1 -0
index a914116..06e0a93 100644
@@ -210,6 +210,7 @@ static inline int mipi_dsi_pixel_format_to_bpp(enum mipi_dsi_pixel_format fmt)
 struct mipi_dsi_device *
 mipi_dsi_device_register_full(struct mipi_dsi_host *host,
 			      const struct mipi_dsi_device_info *info);
+void mipi_dsi_device_unregister(struct mipi_dsi_device *dsi);
 struct mipi_dsi_device *of_find_mipi_dsi_device_by_node(struct device_node *np);
 int mipi_dsi_attach(struct mipi_dsi_device *dsi);
 int mipi_dsi_detach(struct mipi_dsi_device *dsi);
Signature · 7 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel
#82 lore raw

PATCH v5 5/5 drm/dsi: Get DSI host by DT device node

In reply to Archit Taneja

MIPI DSI devices are inherently aware of their host because they share a parent-child hierarchy in the device tree.

Non-DSI drivers that create DSI device don't have this data. In order to get this information, they require to a phandle to the DSI host in the device tree.

Maintain a list of all the hosts DSI that are currently registered. This list will be used to find the mipi_dsi_host corresponding to the device_node passed in of_find_mipi_dsi_host_by_node.

---
 drivers/gpu/drm/drm_mipi_dsi.c | 39 +++++++++++++++++++++++++++++++++++++++
 include/drm/drm_mipi_dsi.h     |  3 +++
 2 files changed, 42 insertions(+)
drivers/gpu/drm/drm_mipi_dsi.c +39 -0
index f2f5a6d..f5d8083 100644
@@ -235,6 +235,37 @@ void mipi_dsi_device_unregister(struct mipi_dsi_device *dsi)
 }
 EXPORT_SYMBOL(mipi_dsi_device_unregister);
 
+static DEFINE_MUTEX(host_lock);
+static LIST_HEAD(host_list);
+
+/**
+ * of_find_mipi_dsi_host_by_node() - find the MIPI DSI host matching a
+ *				     device tree node
+ * @node: device tree node
+ *
+ * Returns:
+ * A pointer to the MIPI DSI host corresponding to @node or NULL if no
+ * such device exists (or has not been registered yet).
+ */
+struct mipi_dsi_host *of_find_mipi_dsi_host_by_node(struct device_node *node)
+{
+	struct mipi_dsi_host *host;
+
+	mutex_lock(&host_lock);
+
+	list_for_each_entry(host, &host_list, list) {
+		if (host->dev->of_node == node) {
+			mutex_unlock(&host_lock);
+			return host;
+		}
+	}
+
+	mutex_unlock(&host_lock);
+
+	return NULL;
+}
+EXPORT_SYMBOL(of_find_mipi_dsi_host_by_node);
+
 int mipi_dsi_host_register(struct mipi_dsi_host *host)
 {
 	struct device_node *node;
@@ -246,6 +277,10 @@ int mipi_dsi_host_register(struct mipi_dsi_host *host)
 		of_mipi_dsi_device_add(host, node);
 	}
 
+	mutex_lock(&host_lock);
+	list_add_tail(&host->list, &host_list);
+	mutex_unlock(&host_lock);
+
 	return 0;
 }
 EXPORT_SYMBOL(mipi_dsi_host_register);
@@ -262,6 +297,10 @@ static int mipi_dsi_remove_device_fn(struct device *dev, void *priv)
 void mipi_dsi_host_unregister(struct mipi_dsi_host *host)
 {
 	device_for_each_child(host->dev, NULL, mipi_dsi_remove_device_fn);
+
+	mutex_lock(&host_lock);
+	list_del_init(&host->list);
+	mutex_unlock(&host_lock);
 }
 EXPORT_SYMBOL(mipi_dsi_host_unregister);
 
include/drm/drm_mipi_dsi.h +3 -0
index 06e0a93..7a9840f 100644
@@ -96,14 +96,17 @@ struct mipi_dsi_host_ops {
  * struct mipi_dsi_host - DSI host device
  * @dev: driver model device node for this DSI host
  * @ops: DSI host operations
+ * @list: list management
  */
 struct mipi_dsi_host {
 	struct device *dev;
 	const struct mipi_dsi_host_ops *ops;
+	struct list_head list;
 };
 
 int mipi_dsi_host_register(struct mipi_dsi_host *host);
 void mipi_dsi_host_unregister(struct mipi_dsi_host *host);
+struct mipi_dsi_host *of_find_mipi_dsi_host_by_node(struct device_node *node);
 
 /* DSI mode flags */
 
Signature · 7 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel
#83 lore raw
In reply to Archit Taneja
Quoted 40 lines · Archit Taneja

We are currently restricted when it comes to supporting DSI on devices that have a non-DSI control bus. For example, DSI encoder chips are available in the market that are configured via i2c. Configuring their registers via DSI bus is either optional or not available at all.

These devices still need to pass DSI parameters (data lanes, mode flags etc) to the DSI host they are connected to. We don't have a way to do that at the moment.

After some discussions on the previous RFC[1], we decided to support this by providing additional API in drm_mipi_dsi.c which lets us create new DSI devices without the need of them to have a DT node.

[1]: https://lkml.org/lkml/2015/6/30/42

Changes in v5:
- Simplify refactoring as suggested by Thierry.
- Use abbreviations correctly.
- Drop "drm/dsi: Check for used channels"
- Return the correct encoded error code for of_mipi_dsi_device_add when CONFIG_OF is disabled.
- Use mipi_dsi_device_unregister to implement mipi_dsi_remove_device_fn() too.

Changes in v4:
- Added a new patch that fixes build issues when CONFIG_OF is not set.

Changes in v3:

- Incorporated misc comments by Andrzej. Changed from RFC to a PATCH set.
- Fixed htmldocs warnings.

Archit Taneja (5):
drm/dsi: check for CONFIG_OF when defining of_mipi_dsi_device_add drm/dsi: Use mipi_dsi_device_register_full for DSI device creation drm/dsi: Try to match non-DT DSI devices
drm/dsi: Add routine to unregister a DSI device drm/dsi: Get DSI host by DT device node

Quoted 3 lines
 drivers/gpu/drm/drm_mipi_dsi.c | 127 +++++++++++++++++++++++++++++++++++++----
 include/drm/drm_mipi_dsi.h     |  26 +++++++++
 2 files changed, 141 insertions(+), 12 deletions(-)

I've applied this with minor fixups and cleanups to the commit messages.

Thanks,
Thierry

_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel