From ebc9446135671b89c2397f438af45d9cef0d1368 Mon Sep 17 00:00:00 2001 From: Rob Herring <robh@kernel.org> Date: Wed, 29 Mar 2017 13:55:46 -0500 Subject: drm: convert drivers to use drm_of_find_panel_or_bridge Similar to the previous commit, convert drivers open coding OF graph parsing to use drm_of_find_panel_or_bridge instead. This changes some error messages to debug messages (in the graph core). Graph connections are often "no connects" depending on the particular board, so we want to avoid spurious messages. Plus the kernel is not a DT validator. Signed-off-by: Rob Herring <robh@kernel.org> Reviewed-by: Archit Taneja <architt@codeaurora.org> Tested-by: Philipp Zabel <p.zabel@pengutronix.de> Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com> [seanpaul dropped rockchip changes since they're now obsolete] Signed-off-by: Sean Paul <seanpaul@chromium.org> --- drivers/gpu/drm/rockchip/analogix_dp-rockchip.c | 26 ++++--------------------- 1 file changed, 4 insertions(+), 22 deletions(-) (limited to 'drivers/gpu/drm/rockchip') diff --git a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c index 91ebe5c2c7a0..01b3f354ca0e 100644 --- a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c +++ b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c @@ -428,31 +428,13 @@ static const struct component_ops rockchip_dp_component_ops = { static int rockchip_dp_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; - struct device_node *panel_node, *port, *endpoint; struct drm_panel *panel = NULL; struct rockchip_dp_device *dp; + int ret; - port = of_graph_get_port_by_id(dev->of_node, 1); - if (port) { - endpoint = of_get_child_by_name(port, "endpoint"); - of_node_put(port); - if (!endpoint) { - dev_err(dev, "no output endpoint found\n"); - return -EINVAL; - } - - panel_node = of_graph_get_remote_port_parent(endpoint); - of_node_put(endpoint); - if (!panel_node) { - dev_err(dev, "no output node found\n"); - return -EINVAL; - } - - panel = of_drm_find_panel(panel_node); - of_node_put(panel_node); - if (!panel) - return -EPROBE_DEFER; - } + ret = drm_of_find_panel_or_bridge(dev->of_node, 1, 0, &panel, NULL); + if (ret) + return ret; dp = devm_kzalloc(dev, sizeof(*dp), GFP_KERNEL); if (!dp) -- cgit v1.2.3 From 54bd16780e2b7bcbe7096baab94e2454686f0941 Mon Sep 17 00:00:00 2001 From: Jeffy Chen <jeffy.chen@rock-chips.com> Date: Thu, 6 Apr 2017 20:31:18 +0800 Subject: drm/rockchip: cdn-dp: Don't try to release firmware when not loaded Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com> Signed-off-by: Sean Paul <seanpaul@chromium.org> Link: http://patchwork.freedesktop.org/patch/msgid/1491481885-13775-6-git-send-email-jeffy.chen@rock-chips.com --- drivers/gpu/drm/rockchip/cdn-dp-core.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/rockchip') diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.c b/drivers/gpu/drm/rockchip/cdn-dp-core.c index 4e55d63c3ef3..ee4195d6592c 100644 --- a/drivers/gpu/drm/rockchip/cdn-dp-core.c +++ b/drivers/gpu/drm/rockchip/cdn-dp-core.c @@ -1053,6 +1053,7 @@ static int cdn_dp_bind(struct device *dev, struct device *master, void *data) dp->connected = false; dp->active = false; dp->active_port = -1; + dp->fw_loaded = false; INIT_WORK(&dp->event_work, cdn_dp_pd_event_work); @@ -1133,7 +1134,8 @@ static void cdn_dp_unbind(struct device *dev, struct device *master, void *data) connector->funcs->destroy(connector); pm_runtime_disable(dev); - release_firmware(dp->fw); + if (dp->fw_loaded) + release_firmware(dp->fw); kfree(dp->edid); dp->edid = NULL; } -- cgit v1.2.3 From 88582f5646927348d31424fa8bdb0f2d97a046c0 Mon Sep 17 00:00:00 2001 From: Jeffy Chen <jeffy.chen@rock-chips.com> Date: Thu, 6 Apr 2017 20:31:19 +0800 Subject: drm/rockchip: cdn-dp: Don't unregister audio dev when unbinding After snd_soc_unregister_codec, the dai link would remain bound to the invalid codec. That would cause crashes after unbind dp driver. Let's unregister audio codec when removing dp driver to prevent that. Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com> Signed-off-by: Sean Paul <seanpaul@chromium.org> Link: http://patchwork.freedesktop.org/patch/msgid/1491481885-13775-7-git-send-email-jeffy.chen@rock-chips.com --- drivers/gpu/drm/rockchip/cdn-dp-core.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/gpu/drm/rockchip') diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.c b/drivers/gpu/drm/rockchip/cdn-dp-core.c index ee4195d6592c..a2169dd3d26b 100644 --- a/drivers/gpu/drm/rockchip/cdn-dp-core.c +++ b/drivers/gpu/drm/rockchip/cdn-dp-core.c @@ -1092,8 +1092,6 @@ static int cdn_dp_bind(struct device *dev, struct device *master, void *data) goto err_free_connector; } - cdn_dp_audio_codec_init(dp, dev); - for (i = 0; i < dp->ports; i++) { port = dp->port[i]; @@ -1128,7 +1126,6 @@ static void cdn_dp_unbind(struct device *dev, struct device *master, void *data) struct drm_connector *connector = &dp->connector; cancel_work_sync(&dp->event_work); - platform_device_unregister(dp->audio_pdev); cdn_dp_encoder_disable(encoder); encoder->funcs->destroy(encoder); connector->funcs->destroy(connector); @@ -1221,6 +1218,8 @@ static int cdn_dp_probe(struct platform_device *pdev) mutex_init(&dp->lock); dev_set_drvdata(dev, dp); + cdn_dp_audio_codec_init(dp, dev); + return component_add(dev, &cdn_dp_component_ops); } @@ -1228,6 +1227,7 @@ static int cdn_dp_remove(struct platform_device *pdev) { struct cdn_dp_device *dp = platform_get_drvdata(pdev); + platform_device_unregister(dp->audio_pdev); cdn_dp_suspend(dp->dev); component_del(&pdev->dev, &cdn_dp_component_ops); -- cgit v1.2.3 From 5e570373c015b60a68828b1cd9d475cb33d3be4b Mon Sep 17 00:00:00 2001 From: Jeffy Chen <jeffy.chen@rock-chips.com> Date: Thu, 6 Apr 2017 20:31:20 +0800 Subject: drm/rockchip: vop: Enable pm domain before vop_initial We're trying to access vop registers here, so need to make sure the pm domain is on. Normally it should be enabled by the bootloader, but there's no guarantee of it. And if we wanna do unbind/bind, it would also cause the device to hang. And this patch also does these: 1/ move vop_initial to the end of vop_bind for eaiser error handling. 2/ correct the err_put_pm_runtime of vop_enable. Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com> Signed-off-by: Sean Paul <seanpaul@chromium.org> Link: http://patchwork.freedesktop.org/patch/msgid/1491481885-13775-8-git-send-email-jeffy.chen@rock-chips.com --- drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) (limited to 'drivers/gpu/drm/rockchip') diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c index 2151e1cee4b4..b65b296ca48b 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c @@ -506,7 +506,7 @@ static int vop_enable(struct drm_crtc *crtc) ret = pm_runtime_get_sync(vop->dev); if (ret < 0) { dev_err(vop->dev, "failed to get pm runtime: %d\n", ret); - goto err_put_pm_runtime; + return ret; } ret = clk_enable(vop->hclk); @@ -1405,10 +1405,16 @@ static int vop_initial(struct vop *vop) return PTR_ERR(vop->dclk); } + ret = pm_runtime_get_sync(vop->dev); + if (ret < 0) { + dev_err(vop->dev, "failed to get pm runtime: %d\n", ret); + return ret; + } + ret = clk_prepare(vop->dclk); if (ret < 0) { dev_err(vop->dev, "failed to prepare dclk\n"); - return ret; + goto err_put_pm_runtime; } /* Enable both the hclk and aclk to setup the vop */ @@ -1468,6 +1474,8 @@ static int vop_initial(struct vop *vop) vop->is_enabled = false; + pm_runtime_put_sync(vop->dev); + return 0; err_disable_aclk: @@ -1476,6 +1484,8 @@ err_disable_hclk: clk_disable_unprepare(vop->hclk); err_unprepare_dclk: clk_unprepare(vop->dclk); +err_put_pm_runtime: + pm_runtime_put_sync(vop->dev); return ret; } @@ -1576,12 +1586,6 @@ static int vop_bind(struct device *dev, struct device *master, void *data) if (!vop->regsbak) return -ENOMEM; - ret = vop_initial(vop); - if (ret < 0) { - dev_err(&pdev->dev, "cannot initial vop dev - err %d\n", ret); - return ret; - } - irq = platform_get_irq(pdev, 0); if (irq < 0) { dev_err(dev, "cannot find irq for vop\n"); @@ -1608,8 +1612,17 @@ static int vop_bind(struct device *dev, struct device *master, void *data) pm_runtime_enable(&pdev->dev); + ret = vop_initial(vop); + if (ret < 0) { + dev_err(&pdev->dev, "cannot initial vop dev - err %d\n", ret); + goto err_disable_pm_runtime; + } + return 0; +err_disable_pm_runtime: + pm_runtime_disable(&pdev->dev); + vop_destroy_crtc(vop); err_enable_irq: enable_irq(vop->irq); /* To balance out the disable_irq above */ return ret; -- cgit v1.2.3 From ec6e7767c925d8c490517315cba75216d9e8620e Mon Sep 17 00:00:00 2001 From: Jeffy Chen <jeffy.chen@rock-chips.com> Date: Thu, 6 Apr 2017 20:31:21 +0800 Subject: drm/rockchip: vop: Unprepare clocks when unbinding The clocks are prepared when binding vop. Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com> Signed-off-by: Sean Paul <seanpaul@chromium.org> Link: http://patchwork.freedesktop.org/patch/msgid/1491481885-13775-9-git-send-email-jeffy.chen@rock-chips.com --- drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/gpu/drm/rockchip') diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c index b65b296ca48b..3f7a82d1e095 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c @@ -1634,6 +1634,10 @@ static void vop_unbind(struct device *dev, struct device *master, void *data) pm_runtime_disable(dev); vop_destroy_crtc(vop); + + clk_unprepare(vop->aclk); + clk_unprepare(vop->hclk); + clk_unprepare(vop->dclk); } const struct component_ops vop_component_ops = { -- cgit v1.2.3 From b7ac7b5b6bb46ed0afbcf94b0834d60e557da779 Mon Sep 17 00:00:00 2001 From: Jeffy Chen <jeffy.chen@rock-chips.com> Date: Thu, 6 Apr 2017 20:31:22 +0800 Subject: drm/rockchip: analogix_dp: Disable clock when unbinding The clock is enabled when binding cdn dp. Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com> Signed-off-by: Sean Paul <seanpaul@chromium.org> Link: http://patchwork.freedesktop.org/patch/msgid/1491481885-13775-10-git-send-email-jeffy.chen@rock-chips.com --- drivers/gpu/drm/rockchip/analogix_dp-rockchip.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/rockchip') diff --git a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c index 01b3f354ca0e..d8fa7a9c9240 100644 --- a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c +++ b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c @@ -417,7 +417,8 @@ static void rockchip_dp_unbind(struct device *dev, struct device *master, rockchip_drm_psr_unregister(&dp->encoder); - return analogix_dp_unbind(dev, master, data); + analogix_dp_unbind(dev, master, data); + clk_disable_unprepare(dp->pclk); } static const struct component_ops rockchip_dp_component_ops = { -- cgit v1.2.3 From ccea91998c8f140bc3e324bbb3c3fb7148e72d31 Mon Sep 17 00:00:00 2001 From: Jeffy Chen <jeffy.chen@rock-chips.com> Date: Thu, 6 Apr 2017 20:31:23 +0800 Subject: drm/rockchip: Reorder drm bind/unbind sequence Current drm bind/unbind sequence would cause some memory issues. For example we should not cleanup iommu before cleanup mode config. Reorder bind/unbind sequence, follow exynos drm. Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com> [seanpaul fixed spelling typo in commit subject] Signed-off-by: Sean Paul <seanpaul@chromium.org> Link: http://patchwork.freedesktop.org/patch/msgid/1491481885-13775-11-git-send-email-jeffy.chen@rock-chips.com --- drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 49 +++++++++++++++-------------- 1 file changed, 26 insertions(+), 23 deletions(-) (limited to 'drivers/gpu/drm/rockchip') diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c index cd7d02e1f758..f24968f1bb25 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c @@ -136,21 +136,24 @@ static int rockchip_drm_bind(struct device *dev) INIT_LIST_HEAD(&private->psr_list); spin_lock_init(&private->psr_list_lock); + ret = rockchip_drm_init_iommu(drm_dev); + if (ret) + goto err_free; + drm_mode_config_init(drm_dev); rockchip_drm_mode_config_init(drm_dev); - ret = rockchip_drm_init_iommu(drm_dev); - if (ret) - goto err_config_cleanup; - /* Try to bind all sub drivers. */ ret = component_bind_all(dev, drm_dev); if (ret) - goto err_iommu_cleanup; + goto err_mode_config_cleanup; - /* init kms poll for handling hpd */ - drm_kms_helper_poll_init(drm_dev); + ret = drm_vblank_init(drm_dev, drm_dev->mode_config.num_crtc); + if (ret) + goto err_unbind_all; + + drm_mode_config_reset(drm_dev); /* * enable drm irq mode. @@ -158,15 +161,12 @@ static int rockchip_drm_bind(struct device *dev) */ drm_dev->irq_enabled = true; - ret = drm_vblank_init(drm_dev, ROCKCHIP_MAX_CRTC); - if (ret) - goto err_kms_helper_poll_fini; - - drm_mode_config_reset(drm_dev); + /* init kms poll for handling hpd */ + drm_kms_helper_poll_init(drm_dev); ret = rockchip_drm_fbdev_init(drm_dev); if (ret) - goto err_vblank_cleanup; + goto err_kms_helper_poll_fini; ret = drm_dev_register(drm_dev, 0); if (ret) @@ -175,17 +175,17 @@ static int rockchip_drm_bind(struct device *dev) return 0; err_fbdev_fini: rockchip_drm_fbdev_fini(drm_dev); -err_vblank_cleanup: - drm_vblank_cleanup(drm_dev); err_kms_helper_poll_fini: drm_kms_helper_poll_fini(drm_dev); + drm_vblank_cleanup(drm_dev); +err_unbind_all: component_unbind_all(dev, drm_dev); -err_iommu_cleanup: - rockchip_iommu_cleanup(drm_dev); -err_config_cleanup: +err_mode_config_cleanup: drm_mode_config_cleanup(drm_dev); - drm_dev->dev_private = NULL; + rockchip_iommu_cleanup(drm_dev); err_free: + drm_dev->dev_private = NULL; + dev_set_drvdata(dev, NULL); drm_dev_unref(drm_dev); return ret; } @@ -194,16 +194,19 @@ static void rockchip_drm_unbind(struct device *dev) { struct drm_device *drm_dev = dev_get_drvdata(dev); + drm_dev_unregister(drm_dev); + rockchip_drm_fbdev_fini(drm_dev); - drm_vblank_cleanup(drm_dev); drm_kms_helper_poll_fini(drm_dev); + + drm_vblank_cleanup(drm_dev); component_unbind_all(dev, drm_dev); - rockchip_iommu_cleanup(drm_dev); drm_mode_config_cleanup(drm_dev); + rockchip_iommu_cleanup(drm_dev); + drm_dev->dev_private = NULL; - drm_dev_unregister(drm_dev); - drm_dev_unref(drm_dev); dev_set_drvdata(dev, NULL); + drm_dev_unref(drm_dev); } static void rockchip_drm_lastclose(struct drm_device *dev) -- cgit v1.2.3 From c1bb81888746b6fff8c3b0abfecc751ab73b3a08 Mon Sep 17 00:00:00 2001 From: Jeffy Chen <jeffy.chen@rock-chips.com> Date: Thu, 6 Apr 2017 20:31:24 +0800 Subject: drm/rockchip: Shutdown all crtcs when unbinding drm Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com> Signed-off-by: Sean Paul <seanpaul@chromium.org> Link: http://patchwork.freedesktop.org/patch/msgid/1491481885-13775-12-git-send-email-jeffy.chen@rock-chips.com --- drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/gpu/drm/rockchip') diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c index f24968f1bb25..c6b1b7f3a2a3 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c @@ -199,6 +199,7 @@ static void rockchip_drm_unbind(struct device *dev) rockchip_drm_fbdev_fini(drm_dev); drm_kms_helper_poll_fini(drm_dev); + drm_atomic_helper_shutdown(drm_dev); drm_vblank_cleanup(drm_dev); component_unbind_all(dev, drm_dev); drm_mode_config_cleanup(drm_dev); -- cgit v1.2.3