forked from mirrors/linux
		
	drm/bridge: sn65dsi86: Register and attach our DSI device at probe
In order to avoid any probe ordering issue, the best practice is to move the secondary MIPI-DSI device registration and attachment to the MIPI-DSI host at probe time. Let's do this. Acked-by: Sam Ravnborg <sam@ravnborg.org> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://patchwork.freedesktop.org/patch/msgid/20211025151536.1048186-18-maxime@cerno.tech
This commit is contained in:
		
							parent
							
								
									77d2a71b94
								
							
						
					
					
						commit
						c3b75d4734
					
				
					 1 changed files with 51 additions and 48 deletions
				
			
		| 
						 | 
					@ -702,11 +702,9 @@ static struct ti_sn65dsi86 *bridge_to_ti_sn65dsi86(struct drm_bridge *bridge)
 | 
				
			||||||
	return container_of(bridge, struct ti_sn65dsi86, bridge);
 | 
						return container_of(bridge, struct ti_sn65dsi86, bridge);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int ti_sn_bridge_attach(struct drm_bridge *bridge,
 | 
					static int ti_sn_attach_host(struct ti_sn65dsi86 *pdata)
 | 
				
			||||||
			       enum drm_bridge_attach_flags flags)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int ret, val;
 | 
						int ret, val;
 | 
				
			||||||
	struct ti_sn65dsi86 *pdata = bridge_to_ti_sn65dsi86(bridge);
 | 
					 | 
				
			||||||
	struct mipi_dsi_host *host;
 | 
						struct mipi_dsi_host *host;
 | 
				
			||||||
	struct mipi_dsi_device *dsi;
 | 
						struct mipi_dsi_device *dsi;
 | 
				
			||||||
	struct device *dev = pdata->dev;
 | 
						struct device *dev = pdata->dev;
 | 
				
			||||||
| 
						 | 
					@ -715,6 +713,47 @@ static int ti_sn_bridge_attach(struct drm_bridge *bridge,
 | 
				
			||||||
						   .node = NULL,
 | 
											   .node = NULL,
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						host = of_find_mipi_dsi_host_by_node(pdata->host_node);
 | 
				
			||||||
 | 
						if (!host) {
 | 
				
			||||||
 | 
							DRM_ERROR("failed to find dsi host\n");
 | 
				
			||||||
 | 
							return -ENODEV;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						dsi = devm_mipi_dsi_device_register_full(dev, host, &info);
 | 
				
			||||||
 | 
						if (IS_ERR(dsi)) {
 | 
				
			||||||
 | 
							DRM_ERROR("failed to create dsi device\n");
 | 
				
			||||||
 | 
							return PTR_ERR(dsi);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* TODO: setting to 4 MIPI lanes always for now */
 | 
				
			||||||
 | 
						dsi->lanes = 4;
 | 
				
			||||||
 | 
						dsi->format = MIPI_DSI_FMT_RGB888;
 | 
				
			||||||
 | 
						dsi->mode_flags = MIPI_DSI_MODE_VIDEO;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* check if continuous dsi clock is required or not */
 | 
				
			||||||
 | 
						pm_runtime_get_sync(dev);
 | 
				
			||||||
 | 
						regmap_read(pdata->regmap, SN_DPPLL_SRC_REG, &val);
 | 
				
			||||||
 | 
						pm_runtime_put_autosuspend(dev);
 | 
				
			||||||
 | 
						if (!(val & DPPLL_CLK_SRC_DSICLK))
 | 
				
			||||||
 | 
							dsi->mode_flags |= MIPI_DSI_CLOCK_NON_CONTINUOUS;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pdata->dsi = dsi;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ret = devm_mipi_dsi_attach(dev, dsi);
 | 
				
			||||||
 | 
						if (ret < 0) {
 | 
				
			||||||
 | 
							DRM_ERROR("failed to attach dsi to host\n");
 | 
				
			||||||
 | 
							return ret;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int ti_sn_bridge_attach(struct drm_bridge *bridge,
 | 
				
			||||||
 | 
								       enum drm_bridge_attach_flags flags)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct ti_sn65dsi86 *pdata = bridge_to_ti_sn65dsi86(bridge);
 | 
				
			||||||
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) {
 | 
						if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) {
 | 
				
			||||||
		DRM_ERROR("Fix bridge driver to make connector optional!");
 | 
							DRM_ERROR("Fix bridge driver to make connector optional!");
 | 
				
			||||||
		return -EINVAL;
 | 
							return -EINVAL;
 | 
				
			||||||
| 
						 | 
					@ -731,50 +770,6 @@ static int ti_sn_bridge_attach(struct drm_bridge *bridge,
 | 
				
			||||||
	if (ret < 0)
 | 
						if (ret < 0)
 | 
				
			||||||
		goto err_conn_init;
 | 
							goto err_conn_init;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
					 | 
				
			||||||
	 * TODO: ideally finding host resource and dsi dev registration needs
 | 
					 | 
				
			||||||
	 * to be done in bridge probe. But some existing DSI host drivers will
 | 
					 | 
				
			||||||
	 * wait for any of the drm_bridge/drm_panel to get added to the global
 | 
					 | 
				
			||||||
	 * bridge/panel list, before completing their probe. So if we do the
 | 
					 | 
				
			||||||
	 * dsi dev registration part in bridge probe, before populating in
 | 
					 | 
				
			||||||
	 * the global bridge list, then it will cause deadlock as dsi host probe
 | 
					 | 
				
			||||||
	 * will never complete, neither our bridge probe. So keeping it here
 | 
					 | 
				
			||||||
	 * will satisfy most of the existing host drivers. Once the host driver
 | 
					 | 
				
			||||||
	 * is fixed we can move the below code to bridge probe safely.
 | 
					 | 
				
			||||||
	 */
 | 
					 | 
				
			||||||
	host = of_find_mipi_dsi_host_by_node(pdata->host_node);
 | 
					 | 
				
			||||||
	if (!host) {
 | 
					 | 
				
			||||||
		DRM_ERROR("failed to find dsi host\n");
 | 
					 | 
				
			||||||
		ret = -ENODEV;
 | 
					 | 
				
			||||||
		goto err_dsi_host;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	dsi = devm_mipi_dsi_device_register_full(dev, host, &info);
 | 
					 | 
				
			||||||
	if (IS_ERR(dsi)) {
 | 
					 | 
				
			||||||
		DRM_ERROR("failed to create dsi device\n");
 | 
					 | 
				
			||||||
		ret = PTR_ERR(dsi);
 | 
					 | 
				
			||||||
		goto err_dsi_host;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* TODO: setting to 4 MIPI lanes always for now */
 | 
					 | 
				
			||||||
	dsi->lanes = 4;
 | 
					 | 
				
			||||||
	dsi->format = MIPI_DSI_FMT_RGB888;
 | 
					 | 
				
			||||||
	dsi->mode_flags = MIPI_DSI_MODE_VIDEO;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* check if continuous dsi clock is required or not */
 | 
					 | 
				
			||||||
	pm_runtime_get_sync(dev);
 | 
					 | 
				
			||||||
	regmap_read(pdata->regmap, SN_DPPLL_SRC_REG, &val);
 | 
					 | 
				
			||||||
	pm_runtime_put_autosuspend(dev);
 | 
					 | 
				
			||||||
	if (!(val & DPPLL_CLK_SRC_DSICLK))
 | 
					 | 
				
			||||||
		dsi->mode_flags |= MIPI_DSI_CLOCK_NON_CONTINUOUS;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ret = devm_mipi_dsi_attach(dev, dsi);
 | 
					 | 
				
			||||||
	if (ret < 0) {
 | 
					 | 
				
			||||||
		DRM_ERROR("failed to attach dsi to host\n");
 | 
					 | 
				
			||||||
		goto err_dsi_host;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	pdata->dsi = dsi;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* We never want the next bridge to *also* create a connector: */
 | 
						/* We never want the next bridge to *also* create a connector: */
 | 
				
			||||||
	flags |= DRM_BRIDGE_ATTACH_NO_CONNECTOR;
 | 
						flags |= DRM_BRIDGE_ATTACH_NO_CONNECTOR;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1271,7 +1266,15 @@ static int ti_sn_bridge_probe(struct auxiliary_device *adev,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	drm_bridge_add(&pdata->bridge);
 | 
						drm_bridge_add(&pdata->bridge);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ret = ti_sn_attach_host(pdata);
 | 
				
			||||||
 | 
						if (ret)
 | 
				
			||||||
 | 
							goto err_remove_bridge;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					err_remove_bridge:
 | 
				
			||||||
 | 
						drm_bridge_remove(&pdata->bridge);
 | 
				
			||||||
 | 
						return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void ti_sn_bridge_remove(struct auxiliary_device *adev)
 | 
					static void ti_sn_bridge_remove(struct auxiliary_device *adev)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue