Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/bridge: analogix_dp: Split bind() into probe() and real bind()

Analogix_dp driver acquires all its resources in the ->bind() callback,
what is a bit against the component driver based approach, where the
driver initialization is split into a probe(), where all resources are
gathered, and a bind(), where all objects are created and a compound
driver is initialized.

Extract all the resource related operations to analogix_dp_probe() and
analogix_dp_remove(), then call them before/after registration of the
device components from the main Exynos DP and Rockchip DP drivers. Also
move the plat_data initialization to the probe() to make it available for
the analogix_dp_probe() function.

This fixes the multiple calls to the bind() of the DRM compound driver
when the DP PHY driver is not yet loaded/probed:

[drm] Exynos DRM: using 14400000.fimd device for DMA mapping operations
exynos-drm exynos-drm: bound 14400000.fimd (ops fimd_component_ops [exynosdrm])
exynos-drm exynos-drm: bound 14450000.mixer (ops mixer_component_ops [exynosdrm])
exynos-dp 145b0000.dp-controller: no DP phy configured
exynos-drm exynos-drm: failed to bind 145b0000.dp-controller (ops exynos_dp_ops [exynosdrm]): -517
exynos-drm exynos-drm: master bind failed: -517
...
[drm] Exynos DRM: using 14400000.fimd device for DMA mapping operations
exynos-drm exynos-drm: bound 14400000.fimd (ops hdmi_enable [exynosdrm])
exynos-drm exynos-drm: bound 14450000.mixer (ops hdmi_enable [exynosdrm])
exynos-drm exynos-drm: bound 145b0000.dp-controller (ops hdmi_enable [exynosdrm])
exynos-drm exynos-drm: bound 14530000.hdmi (ops hdmi_enable [exynosdrm])
[drm] Supports vblank timestamp caching Rev 2 (21.10.2013).
Console: switching to colour frame buffer device 170x48
exynos-drm exynos-drm: fb0: exynosdrmfb frame buffer device
[drm] Initialized exynos 1.1.0 20180330 for exynos-drm on minor 1
...

Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
Acked-by: Andy Yan <andy.yan@rock-chips.com>
Reviewed-by: Andrzej Hajda <a.hajda@samsung.com>
Signed-off-by: Andrzej Hajda <a.hajda@samsung.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20200310103427.26048-1-m.szyprowski@samsung.com
(cherry picked from commit 83a196773b8bc6702f49df1eddc848180e350340)
Signed-off-by: Maxime Ripard <maxime@cerno.tech>

authored by

Marek Szyprowski and committed by
Maxime Ripard
152cce00 b2ecb89c

+61 -42
+22 -11
drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
··· 1652 1652 } 1653 1653 1654 1654 struct analogix_dp_device * 1655 - analogix_dp_bind(struct device *dev, struct drm_device *drm_dev, 1656 - struct analogix_dp_plat_data *plat_data) 1655 + analogix_dp_probe(struct device *dev, struct analogix_dp_plat_data *plat_data) 1657 1656 { 1658 1657 struct platform_device *pdev = to_platform_device(dev); 1659 1658 struct analogix_dp_device *dp; ··· 1755 1756 irq_flags, "analogix-dp", dp); 1756 1757 if (ret) { 1757 1758 dev_err(&pdev->dev, "failed to request irq\n"); 1758 - goto err_disable_pm_runtime; 1759 + return ERR_PTR(ret); 1759 1760 } 1760 1761 disable_irq(dp->irq); 1762 + 1763 + return dp; 1764 + } 1765 + EXPORT_SYMBOL_GPL(analogix_dp_probe); 1766 + 1767 + int analogix_dp_bind(struct analogix_dp_device *dp, struct drm_device *drm_dev) 1768 + { 1769 + int ret; 1761 1770 1762 1771 dp->drm_dev = drm_dev; 1763 1772 dp->encoder = dp->plat_data->encoder; 1764 1773 1765 1774 dp->aux.name = "DP-AUX"; 1766 1775 dp->aux.transfer = analogix_dpaux_transfer; 1767 - dp->aux.dev = &pdev->dev; 1776 + dp->aux.dev = dp->dev; 1768 1777 1769 1778 ret = drm_dp_aux_register(&dp->aux); 1770 1779 if (ret) 1771 - return ERR_PTR(ret); 1780 + return ret; 1772 1781 1773 - pm_runtime_enable(dev); 1782 + pm_runtime_enable(dp->dev); 1774 1783 1775 1784 ret = analogix_dp_create_bridge(drm_dev, dp); 1776 1785 if (ret) { ··· 1786 1779 goto err_disable_pm_runtime; 1787 1780 } 1788 1781 1789 - return dp; 1782 + return 0; 1790 1783 1791 1784 err_disable_pm_runtime: 1785 + pm_runtime_disable(dp->dev); 1792 1786 1793 - pm_runtime_disable(dev); 1794 - 1795 - return ERR_PTR(ret); 1787 + return ret; 1796 1788 } 1797 1789 EXPORT_SYMBOL_GPL(analogix_dp_bind); 1798 1790 ··· 1808 1802 1809 1803 drm_dp_aux_unregister(&dp->aux); 1810 1804 pm_runtime_disable(dp->dev); 1811 - clk_disable_unprepare(dp->clock); 1812 1805 } 1813 1806 EXPORT_SYMBOL_GPL(analogix_dp_unbind); 1807 + 1808 + void analogix_dp_remove(struct analogix_dp_device *dp) 1809 + { 1810 + clk_disable_unprepare(dp->clock); 1811 + } 1812 + EXPORT_SYMBOL_GPL(analogix_dp_remove); 1814 1813 1815 1814 #ifdef CONFIG_PM 1816 1815 int analogix_dp_suspend(struct analogix_dp_device *dp)
+17 -12
drivers/gpu/drm/exynos/exynos_dp.c
··· 159 159 struct drm_device *drm_dev = data; 160 160 int ret; 161 161 162 - dp->dev = dev; 163 162 dp->drm_dev = drm_dev; 164 - 165 - dp->plat_data.dev_type = EXYNOS_DP; 166 - dp->plat_data.power_on_start = exynos_dp_poweron; 167 - dp->plat_data.power_off = exynos_dp_poweroff; 168 - dp->plat_data.attach = exynos_dp_bridge_attach; 169 - dp->plat_data.get_modes = exynos_dp_get_modes; 170 163 171 164 if (!dp->plat_data.panel && !dp->ptn_bridge) { 172 165 ret = exynos_dp_dt_parse_panel(dp); ··· 178 185 179 186 dp->plat_data.encoder = encoder; 180 187 181 - dp->adp = analogix_dp_bind(dev, dp->drm_dev, &dp->plat_data); 182 - if (IS_ERR(dp->adp)) { 188 + ret = analogix_dp_bind(dp->adp, dp->drm_dev); 189 + if (ret) 183 190 dp->encoder.funcs->destroy(&dp->encoder); 184 - return PTR_ERR(dp->adp); 185 - } 186 191 187 - return 0; 192 + return ret; 188 193 } 189 194 190 195 static void exynos_dp_unbind(struct device *dev, struct device *master, ··· 213 222 if (!dp) 214 223 return -ENOMEM; 215 224 225 + dp->dev = dev; 216 226 /* 217 227 * We just use the drvdata until driver run into component 218 228 * add function, and then we would set drvdata to null, so ··· 239 247 240 248 /* The remote port can be either a panel or a bridge */ 241 249 dp->plat_data.panel = panel; 250 + dp->plat_data.dev_type = EXYNOS_DP; 251 + dp->plat_data.power_on_start = exynos_dp_poweron; 252 + dp->plat_data.power_off = exynos_dp_poweroff; 253 + dp->plat_data.attach = exynos_dp_bridge_attach; 254 + dp->plat_data.get_modes = exynos_dp_get_modes; 242 255 dp->plat_data.skip_connector = !!bridge; 256 + 243 257 dp->ptn_bridge = bridge; 244 258 245 259 out: 260 + dp->adp = analogix_dp_probe(dev, &dp->plat_data); 261 + if (IS_ERR(dp->adp)) 262 + return PTR_ERR(dp->adp); 263 + 246 264 return component_add(&pdev->dev, &exynos_dp_ops); 247 265 } 248 266 249 267 static int exynos_dp_remove(struct platform_device *pdev) 250 268 { 269 + struct exynos_dp_device *dp = platform_get_drvdata(pdev); 270 + 251 271 component_del(&pdev->dev, &exynos_dp_ops); 272 + analogix_dp_remove(dp->adp); 252 273 253 274 return 0; 254 275 }
+19 -17
drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
··· 325 325 void *data) 326 326 { 327 327 struct rockchip_dp_device *dp = dev_get_drvdata(dev); 328 - const struct rockchip_dp_chip_data *dp_data; 329 328 struct drm_device *drm_dev = data; 330 329 int ret; 331 330 332 - dp_data = of_device_get_match_data(dev); 333 - if (!dp_data) 334 - return -ENODEV; 335 - 336 - dp->data = dp_data; 337 331 dp->drm_dev = drm_dev; 338 332 339 333 ret = rockchip_dp_drm_create_encoder(dp); ··· 338 344 339 345 dp->plat_data.encoder = &dp->encoder; 340 346 341 - dp->plat_data.dev_type = dp->data->chip_type; 342 - dp->plat_data.power_on_start = rockchip_dp_poweron_start; 343 - dp->plat_data.power_off = rockchip_dp_powerdown; 344 - dp->plat_data.get_modes = rockchip_dp_get_modes; 345 - 346 - dp->adp = analogix_dp_bind(dev, dp->drm_dev, &dp->plat_data); 347 - if (IS_ERR(dp->adp)) { 348 - ret = PTR_ERR(dp->adp); 347 + ret = analogix_dp_bind(dp->adp, drm_dev); 348 + if (ret) 349 349 goto err_cleanup_encoder; 350 - } 351 350 352 351 return 0; 353 352 err_cleanup_encoder: ··· 355 368 356 369 analogix_dp_unbind(dp->adp); 357 370 dp->encoder.funcs->destroy(&dp->encoder); 358 - 359 - dp->adp = ERR_PTR(-ENODEV); 360 371 } 361 372 362 373 static const struct component_ops rockchip_dp_component_ops = { ··· 365 380 static int rockchip_dp_probe(struct platform_device *pdev) 366 381 { 367 382 struct device *dev = &pdev->dev; 383 + const struct rockchip_dp_chip_data *dp_data; 368 384 struct drm_panel *panel = NULL; 369 385 struct rockchip_dp_device *dp; 370 386 int ret; 387 + 388 + dp_data = of_device_get_match_data(dev); 389 + if (!dp_data) 390 + return -ENODEV; 371 391 372 392 ret = drm_of_find_panel_or_bridge(dev->of_node, 1, 0, &panel, NULL); 373 393 if (ret < 0) ··· 384 394 385 395 dp->dev = dev; 386 396 dp->adp = ERR_PTR(-ENODEV); 397 + dp->data = dp_data; 387 398 dp->plat_data.panel = panel; 399 + dp->plat_data.dev_type = dp->data->chip_type; 400 + dp->plat_data.power_on_start = rockchip_dp_poweron_start; 401 + dp->plat_data.power_off = rockchip_dp_powerdown; 402 + dp->plat_data.get_modes = rockchip_dp_get_modes; 388 403 389 404 ret = rockchip_dp_of_probe(dp); 390 405 if (ret < 0) ··· 397 402 398 403 platform_set_drvdata(pdev, dp); 399 404 405 + dp->adp = analogix_dp_probe(dev, &dp->plat_data); 406 + if (IS_ERR(dp->adp)) 407 + return PTR_ERR(dp->adp); 408 + 400 409 return component_add(dev, &rockchip_dp_component_ops); 401 410 } 402 411 403 412 static int rockchip_dp_remove(struct platform_device *pdev) 404 413 { 414 + struct rockchip_dp_device *dp = platform_get_drvdata(pdev); 415 + 405 416 component_del(&pdev->dev, &rockchip_dp_component_ops); 417 + analogix_dp_remove(dp->adp); 406 418 407 419 return 0; 408 420 }
+3 -2
include/drm/bridge/analogix_dp.h
··· 42 42 int analogix_dp_suspend(struct analogix_dp_device *dp); 43 43 44 44 struct analogix_dp_device * 45 - analogix_dp_bind(struct device *dev, struct drm_device *drm_dev, 46 - struct analogix_dp_plat_data *plat_data); 45 + analogix_dp_probe(struct device *dev, struct analogix_dp_plat_data *plat_data); 46 + int analogix_dp_bind(struct analogix_dp_device *dp, struct drm_device *drm_dev); 47 47 void analogix_dp_unbind(struct analogix_dp_device *dp); 48 + void analogix_dp_remove(struct analogix_dp_device *dp); 48 49 49 50 int analogix_dp_start_crc(struct drm_connector *connector); 50 51 int analogix_dp_stop_crc(struct drm_connector *connector);