From 9152cfd9e9c39e5fa182913efc477e146a6cda62 Mon Sep 17 00:00:00 2001 From: Naveen Kumar S Date: Mon, 6 Jul 2020 21:31:49 +0530 Subject: [PATCH] video: tegra: dc: add pm_runtime support Add genpd/pm_runtime support to handle power domains in Tegra Display driver. Also updated CEC and HDA_DC drivers to add pm_runtime calls. Added new APIs in CEC and SOR drivers to abstract calls to pm_runtime and tegra_powergate APIs based on specific Kernel version. Guarded powergate_id with CONFIG_TEGRA_POWERGATE since its not needed when pm_runtime APIs are used, and the powergate IDs are defined in tegra_powergate.h which is not used in K5.9. Removed pm_runtime autosuspend setting since display driver doesn't assign PM suspend/resume hooks at present. Suspend/resume calls are linked to platform device callbacks. Removed pm_runtime_enable() call in dc_common probe since there's logically no need of power-domains in dc_common and also there is no power-domains node in display_hub node in device-tree. Same with DSI. All the power-domains handled by each DC are listed in "power-domains" and "power-domain-names" properties under respective dc nodes in device tree. bug 200601926 Change-Id: I0fc9d21ff56185a69de6e0663b5932a93cf40e2b Signed-off-by: Naveen Kumar S Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvidia/+/2358953 Tested-by: mobile promotions Reviewed-by: automaticguardword Reviewed-by: Shu Zhong Reviewed-by: Ujwal Patel Reviewed-by: mobile promotions GVS: Gerrit_Virtual_Submit --- drivers/misc/tegra-cec/tegra_cec.c | 79 ++++++++++++++++++++---------- 1 file changed, 53 insertions(+), 26 deletions(-) diff --git a/drivers/misc/tegra-cec/tegra_cec.c b/drivers/misc/tegra-cec/tegra_cec.c index b2c8b1a6..9db5ffd8 100644 --- a/drivers/misc/tegra-cec/tegra_cec.c +++ b/drivers/misc/tegra-cec/tegra_cec.c @@ -39,7 +39,9 @@ #include #include +#if defined(CONFIG_TEGRA_POWERGATE) #include +#endif #include "tegra_cec.h" #include "../../../../nvidia/drivers/video/tegra/dc/dc.h" @@ -339,6 +341,36 @@ static int tegra_cec_dump_registers(struct tegra_cec *cec) } +static int tegra_cec_unpowergate(struct tegra_cec *cec) +{ + int ret = 0; + + if (!tegra_dc_is_nvdisplay()) + return 0; + +#if defined(CONFIG_TEGRA_POWERGATE) + ret = tegra_unpowergate_partition(cec->soc->powergate_id); +#else + ret = pm_runtime_get(cec->dev); +#endif + if (IS_ERR(ERR_PTR(ret))) + dev_err(cec->dev, "Failed to unpowergate DISP,err = %d\n", ret); + + return ret; +} + +static void tegra_cec_powergate(struct tegra_cec *cec) +{ + if (!tegra_dc_is_nvdisplay()) + return; + +#if defined(CONFIG_TEGRA_POWERGATE) + tegra_powergate_partition(cec->soc->powergate_id); +#else + pm_runtime_put(cec->dev); +#endif +} + static int tegra_cec_set_rx_snoop(struct tegra_cec *cec, u32 enable) { u32 state; @@ -660,19 +692,18 @@ static int tegra_cec_probe(struct platform_device *pdev) atomic_set(&cec->init_done, 0); mutex_init(&cec->tx_lock); mutex_init(&cec->recovery_lock); + cec->dev = &pdev->dev; -#if defined(CONFIG_TEGRA_POWERGATE) - if (tegra_dc_is_nvdisplay()) { - ret = tegra_unpowergate_partition(cec->soc->powergate_id); - if (ret) { - dev_err(&pdev->dev, "Fail to unpowergate DISP: %d.\n", - ret); - goto clk_error; - } - dev_info(&pdev->dev, "Unpowergate DISP: %d.\n", ret); - } +#if !defined(CONFIG_TEGRA_POWERGATE) + if (tegra_dc_is_nvdisplay()) + pm_runtime_enable(&pdev->dev); #endif + ret = tegra_cec_unpowergate(cec); + if (IS_ERR(ERR_PTR(ret))) + goto clk_error; + dev_info(&pdev->dev, "Unpowergated DISP\n"); + if (tegra_dc_is_nvdisplay()) { if (np) cec->clk = of_clk_get_by_name(np, "cec"); @@ -690,7 +721,6 @@ static int tegra_cec_probe(struct platform_device *pdev) dev_info(&pdev->dev, "Enable clock result: %d.\n", ret); /* set context info. */ - cec->dev = &pdev->dev; init_waitqueue_head(&cec->rx_waitq); init_waitqueue_head(&cec->tx_waitq); init_waitqueue_head(&cec->init_waitq); @@ -755,10 +785,7 @@ cec_error: cancel_work_sync(&cec->work); clk_disable(cec->clk); clk_put(cec->clk); -#if defined(CONFIG_TEGRA_POWERGATE) - if (tegra_dc_is_nvdisplay()) - tegra_powergate_partition(cec->soc->powergate_id); -#endif + tegra_cec_powergate(cec); clk_error: return ret; } @@ -769,11 +796,11 @@ static int tegra_cec_remove(struct platform_device *pdev) clk_disable(cec->clk); clk_put(cec->clk); -#if defined(CONFIG_TEGRA_POWERGATE) + tegra_cec_powergate(cec); +#if !defined(CONFIG_TEGRA_POWERGATE) if (tegra_dc_is_nvdisplay()) - tegra_powergate_partition(cec->soc->powergate_id); + pm_runtime_disable(&pdev->dev); #endif - misc_deregister(&cec->misc_dev); cancel_work_sync(&cec->work); @@ -797,10 +824,7 @@ static int tegra_cec_suspend(struct platform_device *pdev, pm_message_t state) atomic_set(&cec->init_cancel, 0); clk_disable(cec->clk); -#if defined(CONFIG_TEGRA_POWERGATE) - if (tegra_dc_is_nvdisplay()) - tegra_powergate_partition(cec->soc->powergate_id); -#endif + tegra_cec_powergate(cec); dev_notice(&pdev->dev, "suspended\n"); return 0; @@ -812,10 +836,7 @@ static int tegra_cec_resume(struct platform_device *pdev) dev_notice(&pdev->dev, "Resuming\n"); -#if defined(CONFIG_TEGRA_POWERGATE) - if (tegra_dc_is_nvdisplay()) - tegra_unpowergate_partition(cec->soc->powergate_id); -#endif + tegra_cec_unpowergate(cec); clk_enable(cec->clk); schedule_work(&cec->work); @@ -835,15 +856,21 @@ static int __init check_post_recovery(char *options) early_param("post_recovery", check_post_recovery); static struct tegra_cec_soc tegra210_soc_data = { +#if defined(CONFIG_TEGRA_POWERGATE) .powergate_id = TEGRA210_POWER_DOMAIN_DISA, +#endif }; static struct tegra_cec_soc tegra186_soc_data = { +#if defined(CONFIG_TEGRA_POWERGATE) .powergate_id = TEGRA186_POWER_DOMAIN_DISP, +#endif }; static struct tegra_cec_soc tegra194_soc_data = { +#if defined(CONFIG_TEGRA_POWERGATE) .powergate_id = TEGRA194_POWER_DOMAIN_DISP, +#endif }; static struct of_device_id tegra_cec_of_match[] = {