[PATCH 6/8] drm: Allow DSI devices to be registered before the host registers.

Archit Taneja architt at codeaurora.org
Thu Jun 29 05:03:17 UTC 2017



On 06/28/2017 01:28 AM, Eric Anholt wrote:
> When a mipi_dsi_host is registered, the DT is walked to find any child
> nodes with compatible strings.  Those get registered as DSI devices,
> and most DSI panel drivers are mipi_dsi_drivers that attach to those nodes.
> 
> There is one special case currently, the adv7533 bridge, where the
> bridge probes on I2C, and during the bridge attach step it looks up
> the mipi_dsi_host and registers the mipi_dsi_device (for its own stub
> mipi_dsi_driver).
> 
> For the Raspberry Pi panel, though, we also need to attach on I2C (our
> control bus), but don't have a bridge driver.  The lack of a bridge's
> attach() step like adv7533 uses means that we aren't able to delay the
> mipi_dsi_device creation until the mipi_dsi_host is present.
> 
> To fix this, we extend mipi_dsi_device_register_full() to allow being
> called with a NULL host, which puts the device on a queue waiting for
> a host to appear.  When a new host is registered, we fill in the host
> value and finish the device creation process.

This is quite a nice idea. The only bothering thing is the info.of_node usage
varies between child nodes (mipi_dsi_devs) and non-child nodes (i2c control
bus).

For DSI children expressed in DT, the of_node in info holds the DT node
corresponding to the DSI child itself. For non-DT ones, this patch assumes
that info.of_node stores the DSI host DT node. I think it should be okay as
long as we mention the usage in a comment somewhere. The other option is to
have a new info.host_node field to keep a track of the host DT node.

Thanks,
Archit

> 
> Signed-off-by: Eric Anholt <eric at anholt.net>
> ---
>   drivers/gpu/drm/drm_mipi_dsi.c | 49 ++++++++++++++++++++++++++++++++----------
>   include/drm/drm_mipi_dsi.h     |  3 +++
>   2 files changed, 41 insertions(+), 11 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_mipi_dsi.c b/drivers/gpu/drm/drm_mipi_dsi.c
> index 1160a579e0dc..9cdd68a7dc0d 100644
> --- a/drivers/gpu/drm/drm_mipi_dsi.c
> +++ b/drivers/gpu/drm/drm_mipi_dsi.c
> @@ -45,6 +45,13 @@
>    * subset of the MIPI DCS command set.
>    */
>   
> +static DEFINE_MUTEX(host_lock);
> +static LIST_HEAD(host_list);
> +/* List of struct mipi_dsi_device which were registered while no host
> + * was available.
> + */
> +static LIST_HEAD(unattached_device_list);
> +
>   static int mipi_dsi_device_match(struct device *dev, struct device_driver *drv)
>   {
>   	struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev);
> @@ -138,10 +145,12 @@ static struct mipi_dsi_device *mipi_dsi_device_alloc(struct mipi_dsi_host *host)
>   
>   	dsi->host = host;
>   	dsi->dev.bus = &mipi_dsi_bus_type;
> -	dsi->dev.parent = host->dev;
>   	dsi->dev.type = &mipi_dsi_device_type;
>   
> -	device_initialize(&dsi->dev);
> +	if (dsi->host) {
> +		dsi->dev.parent = host->dev;
> +		device_initialize(&dsi->dev);
> +	}
>   
>   	return dsi;
>   }
> @@ -206,7 +215,7 @@ 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;
> +	struct device *dev = host ? host->dev : NULL;
>   	int ret;
>   
>   	if (!info) {
> @@ -230,11 +239,17 @@ mipi_dsi_device_register_full(struct mipi_dsi_host *host,
>   	dsi->channel = info->channel;
>   	strlcpy(dsi->name, info->type, sizeof(dsi->name));
>   
> -	ret = mipi_dsi_device_add(dsi);
> -	if (ret) {
> -		dev_err(dev, "failed to add DSI device %d\n", ret);
> -		kfree(dsi);
> -		return ERR_PTR(ret);
> +	if (!dsi->host) {
> +		mutex_lock(&host_lock);
> +		list_add(&dsi->list, &unattached_device_list);
> +		mutex_unlock(&host_lock);
> +	} else {
> +		ret = mipi_dsi_device_add(dsi);
> +		if (ret) {
> +			dev_err(dev, "failed to add DSI device %d\n", ret);
> +			kfree(dsi);
> +			return ERR_PTR(ret);
> +		}
>   	}
>   
>   	return dsi;
> @@ -251,9 +266,6 @@ 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
> @@ -285,6 +297,7 @@ EXPORT_SYMBOL(of_find_mipi_dsi_host_by_node);
>   int mipi_dsi_host_register(struct mipi_dsi_host *host)
>   {
>   	struct device_node *node;
> +	struct mipi_dsi_device *dsi, *temp;
>   
>   	for_each_available_child_of_node(host->dev->of_node, node) {
>   		/* skip nodes without reg property */
> @@ -295,6 +308,20 @@ int mipi_dsi_host_register(struct mipi_dsi_host *host)
>   
>   	mutex_lock(&host_lock);
>   	list_add_tail(&host->list, &host_list);
> +
> +	/* If any DSI devices were registered under our OF node, then
> +	 * connect our host to it and probe them now.
> +	 */
> +	list_for_each_entry_safe(dsi, temp, &unattached_device_list, list) {
> +		if (of_get_parent(dsi->dev.of_node) == host->dev->of_node) {
> +			dsi->host = host;
> +			dsi->dev.parent = host->dev;
> +			device_initialize(&dsi->dev);
> +
> +			mipi_dsi_device_add(dsi);
> +			list_del_init(&dsi->list);
> +		}
> +	}
>   	mutex_unlock(&host_lock);
>   
>   	return 0;
> diff --git a/include/drm/drm_mipi_dsi.h b/include/drm/drm_mipi_dsi.h
> index 4fef19064b0f..699ea4acd5b6 100644
> --- a/include/drm/drm_mipi_dsi.h
> +++ b/include/drm/drm_mipi_dsi.h
> @@ -178,6 +178,9 @@ struct mipi_dsi_device {
>   	unsigned int lanes;
>   	enum mipi_dsi_pixel_format format;
>   	unsigned long mode_flags;
> +
> +	/* Entry on the unattached_device_list */
> +	struct list_head list;
>   };
>   
>   #define MIPI_DSI_MODULE_PREFIX "mipi-dsi:"
> 

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project


More information about the dri-devel mailing list