From e3b31a037dcdef9cd3a101d40ca505e40221cbb6 Mon Sep 17 00:00:00 2001 From: Damon Ding Date: Fri, 26 Jul 2024 17:00:05 +0800 Subject: [PATCH] drm/rockchip: tve: add .loader_protect() support for tve If logo display enabled, the rockchip_tve_encoder_loader_protect() helps to set the tve enable/disable status and call pm_runtime_get_sync()/pm_runtime_put(), which allows for the continuation of the display state from the U-Boot stage. In addition, fix the check of tve mode setting in .mode_set() to avoid display flashing, which caused by the off/on switch of dac. Change-Id: I6f1fcaf05cb6e362ce375e447c566fb5356c5380 Signed-off-by: Damon Ding --- drivers/gpu/drm/rockchip/rockchip_drm_tve.c | 84 ++++++++++++++++++++- 1 file changed, 81 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_tve.c b/drivers/gpu/drm/rockchip/rockchip_drm_tve.c index 05880ef46f9d..9184509fc2ba 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_tve.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_tve.c @@ -486,15 +486,17 @@ static void rockchip_tve_encoder_mode_set(struct drm_encoder *encoder, struct drm_display_mode *adjusted_mode) { struct rockchip_tve *tve = encoder_to_tve(encoder); + u32 tv_format; dev_dbg(tve->dev, "encoder mode set:%s\n", adjusted_mode->name); if (adjusted_mode->vdisplay == 576) - tve->tv_format = TVOUT_CVBS_PAL; + tv_format = TVOUT_CVBS_PAL; else - tve->tv_format = TVOUT_CVBS_NTSC; + tv_format = TVOUT_CVBS_NTSC; - if (tve->enable) { + if (tve->enable && tve->tv_format != tv_format) { + tve->tv_format = tv_format; dac_enable(tve, false); msleep(200); @@ -541,6 +543,81 @@ rockchip_tve_encoder_atomic_check(struct drm_encoder *encoder, return 0; } +static int rockchip_tve_encoder_loader_protect(struct drm_encoder *encoder, bool on) +{ + struct rockchip_tve *tve = encoder_to_tve(encoder); + int ret; + + if (on) { + ret = pm_runtime_get_sync(tve->dev); + if (ret < 0) { + dev_err(tve->dev, "failed to get pm runtime: %d\n", ret); + return ret; + } + + ret = clk_prepare_enable(tve->aclk); + if (ret) { + dev_err(tve->dev, "Cannot enable tve aclk: %d\n", ret); + goto err_pm_put; + } + + ret = clk_prepare_enable(tve->hclk); + if (ret) { + dev_err(tve->dev, "Cannot enable tve hclk: %d\n", ret); + goto err_disable_aclk; + } + + ret = clk_prepare_enable(tve->pclk_vdac); + if (ret) { + dev_err(tve->dev, "Cannot enable vdac pclk: %d\n", ret); + goto err_disable_hclk; + } + + ret = clk_prepare_enable(tve->dclk); + if (ret) { + dev_err(tve->dev, "Cannot enable tve dclk: %d\n", ret); + goto err_disable_pclk; + } + + ret = clk_prepare_enable(tve->dclk_4x); + if (ret) { + dev_err(tve->dev, "Cannot enable tve dclk_4x: %d\n", ret); + goto err_disable_dclk; + } + + tve->enable = 1; + } else { + ret = pm_runtime_put(tve->dev); + if (ret < 0) { + dev_err(tve->dev, "failed to put pm runtime: %d\n", ret); + return ret; + } + + clk_disable_unprepare(tve->dclk_4x); + clk_disable_unprepare(tve->dclk); + clk_disable_unprepare(tve->pclk_vdac); + clk_disable_unprepare(tve->hclk); + clk_disable_unprepare(tve->aclk); + + tve->enable = 0; + } + + return 0; + +err_disable_dclk: + clk_disable_unprepare(tve->dclk); +err_disable_pclk: + clk_disable_unprepare(tve->pclk_vdac); +err_disable_hclk: + clk_disable_unprepare(tve->hclk); +err_disable_aclk: + clk_disable_unprepare(tve->aclk); +err_pm_put: + pm_runtime_put_sync(tve->dev); + + return ret; +} + static const struct drm_connector_helper_funcs rockchip_tve_connector_helper_funcs = { .mode_valid = rockchip_tve_mode_valid, @@ -1006,6 +1083,7 @@ static int rockchip_tve_bind(struct device *dev, struct device *master, } tve->sub_dev.connector = &tve->connector; tve->sub_dev.of_node = tve->dev->of_node; + tve->sub_dev.loader_protect = rockchip_tve_encoder_loader_protect; rockchip_drm_register_sub_dev(&tve->sub_dev); pm_runtime_enable(dev);