From 30706b0ceffdeceab337669fd68d6597798ca53e Mon Sep 17 00:00:00 2001 From: Mohan Kumar Date: Fri, 4 Sep 2020 14:32:18 +0530 Subject: [PATCH] ASoC: tegra: Add Interconnect support for ADMA Add Interconnect API support for ADMA Memory bandwidth requirement handling. From Kernel 4.14 and beyond - On T23X and newer platforms, the interconnects driver will be initialized and calls to BWMGR will be stubbed out. - On T194 and earlier platforms, BWMGR driver will be initialized and calls to interconnect framework will be stubbed out. Jira TAS-1059 Change-Id: I7a26f61517937ac3103222a43f08ee7c4e4ad484 Signed-off-by: Mohan Kumar Reviewed-on: https://git-master.nvidia.com/r/c/linux-5.9/+/2408552 Tested-by: mobile promotions Reviewed-by: mobile promotions --- sound/soc/tegra/tegra210_admaif.c | 14 ++-- sound/soc/tegra/tegra210_admaif.h | 1 - sound/soc/tegra/tegra_isomgr_bw.c | 113 +++++++++++++++++++++--------- sound/soc/tegra/tegra_isomgr_bw.h | 13 +--- 4 files changed, 85 insertions(+), 56 deletions(-) diff --git a/sound/soc/tegra/tegra210_admaif.c b/sound/soc/tegra/tegra210_admaif.c index 7fbb3793..ee8c6669 100644 --- a/sound/soc/tegra/tegra210_admaif.c +++ b/sound/soc/tegra/tegra210_admaif.c @@ -268,8 +268,7 @@ static int tegra_admaif_prepare(struct snd_pcm_substream *substream, { struct tegra_admaif *admaif = snd_soc_dai_get_drvdata(dai); - if (admaif->soc_data->is_isomgr_client) - tegra_isomgr_adma_setbw(substream, true); + tegra_isomgr_adma_setbw(substream, true); return 0; } @@ -279,8 +278,7 @@ static void tegra_admaif_shutdown(struct snd_pcm_substream *substream, { struct tegra_admaif *admaif = snd_soc_dai_get_drvdata(dai); - if (admaif->soc_data->is_isomgr_client) - tegra_isomgr_adma_setbw(substream, false); + tegra_isomgr_adma_setbw(substream, false); } static int tegra_admaif_hw_params(struct snd_pcm_substream *substream, @@ -994,7 +992,6 @@ static const struct tegra_admaif_soc_data soc_data_tegra210 = { .global_base = TEGRA210_ADMAIF_GLOBAL_BASE, .tx_base = TEGRA210_ADMAIF_TX_BASE, .rx_base = TEGRA210_ADMAIF_RX_BASE, - .is_isomgr_client = false, }; static const struct tegra_admaif_soc_data soc_data_tegra186 = { @@ -1005,7 +1002,6 @@ static const struct tegra_admaif_soc_data soc_data_tegra186 = { .global_base = TEGRA186_ADMAIF_GLOBAL_BASE, .tx_base = TEGRA186_ADMAIF_TX_BASE, .rx_base = TEGRA186_ADMAIF_RX_BASE, - .is_isomgr_client = true, }; static const struct of_device_id tegra_admaif_of_match[] = { @@ -1089,8 +1085,7 @@ static int tegra_admaif_probe(struct platform_device *pdev) regcache_cache_only(admaif->regmap, true); - if (admaif->soc_data->is_isomgr_client) - tegra_isomgr_adma_register(); + tegra_isomgr_adma_register(&pdev->dev); regmap_update_bits(admaif->regmap, admaif->soc_data->global_base + TEGRA_ADMAIF_GLOBAL_ENABLE, 1, 1); @@ -1147,8 +1142,7 @@ static int tegra_admaif_remove(struct platform_device *pdev) { struct tegra_admaif *admaif = dev_get_drvdata(&pdev->dev); - if (admaif->soc_data->is_isomgr_client) - tegra_isomgr_adma_unregister(); + tegra_isomgr_adma_unregister(&pdev->dev); pm_runtime_disable(&pdev->dev); diff --git a/sound/soc/tegra/tegra210_admaif.h b/sound/soc/tegra/tegra210_admaif.h index ef3f31bc..44b2df64 100644 --- a/sound/soc/tegra/tegra210_admaif.h +++ b/sound/soc/tegra/tegra210_admaif.h @@ -148,7 +148,6 @@ struct tegra_admaif_soc_data { unsigned int tx_base; unsigned int rx_base; unsigned int num_ch; - bool is_isomgr_client; }; struct tegra_admaif { diff --git a/sound/soc/tegra/tegra_isomgr_bw.c b/sound/soc/tegra/tegra_isomgr_bw.c index bec53fb6..deb63445 100644 --- a/sound/soc/tegra/tegra_isomgr_bw.c +++ b/sound/soc/tegra/tegra_isomgr_bw.c @@ -15,20 +15,20 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ + #include #include #include #include #include #include "tegra_isomgr_bw.h" - -#if defined(CONFIG_TEGRA_ISOMGR) && defined(CONFIG_NV_TEGRA_MC) +#include +#include +#include #define MAX_BW 393216 /*Maximum KiloByte*/ #define MAX_DEV_NUM 256 -static long tegra_adma_calc_min_bandwidth(void); - static struct adma_isomgr { int current_bandwidth; bool device_number[MAX_DEV_NUM]; @@ -36,8 +36,11 @@ static struct adma_isomgr { struct mutex mutex; /* iso manager handle */ tegra_isomgr_handle isomgr_handle; + /* icc_path handle handle */ + struct icc_path *icc_path_handle; } *adma; +#if IS_ENABLED(CONFIG_TEGRA_ISOMGR) && IS_ENABLED(CONFIG_NV_TEGRA_MC) static long tegra_adma_calc_min_bandwidth(void) { int max_srate = 192; /*Khz*/ @@ -51,6 +54,15 @@ static long tegra_adma_calc_min_bandwidth(void) return min_bw; } +void tegra_isomgr_adma_renegotiate(void *p, u32 avail_bw) +{ + /* For Audio usecase there is no possibility of renegotiation + * as it may lead to glitches. So currently dummy renegotiate call + * is added to support bandwidth request more than registered bw which + * got initialized during register call + */ +} + static int adma_isomgr_request(uint adma_bw, uint lt) { int ret; @@ -78,12 +90,12 @@ static int adma_isomgr_request(uint adma_bw, uint lt) return 0; } +#endif void tegra_isomgr_adma_setbw(struct snd_pcm_substream *substream, bool is_running) { int bandwidth, sample_bytes; - int ret; struct snd_pcm_runtime *runtime = substream->runtime; struct snd_pcm *pcm = substream->pcm; @@ -132,28 +144,31 @@ void tegra_isomgr_adma_setbw(struct snd_pcm_substream *substream, adma->current_bandwidth = MAX_BW; } - ret = adma_isomgr_request(adma->current_bandwidth, 1000); - if (!ret) { - /* Call LA/PTSA driver which will configure the Memory - controller to support APEDMA's new BW requirement in MBps*/ - ret = tegra_set_latency_allowance(TEGRA_LA_APEDMAW, - ((adma->current_bandwidth + 999)/1000)); - if (ret) - pr_err("%s: LA/PTSA setting Failed\n", __func__); + if (adma->icc_path_handle) + icc_set_bw(adma->icc_path_handle, adma->current_bandwidth, + adma->current_bandwidth); + +#if IS_ENABLED(CONFIG_TEGRA_ISOMGR) && IS_ENABLED(CONFIG_NV_TEGRA_MC) + if (adma->isomgr_handle) { + int ret; + + ret = adma_isomgr_request(adma->current_bandwidth, 1000); + if (!ret) { + /* Call LA/PTSA driver which will configure the + * Memory controller to support APEDMA's new BW + * requirement in MBps + */ + ret = tegra_set_latency_allowance(TEGRA_LA_APEDMAW, + ((adma->current_bandwidth + 999)/1000)); + if (ret) + pr_err("%s: LA/PTSA config Failed\n", __func__); + } } +#endif } EXPORT_SYMBOL(tegra_isomgr_adma_setbw); -void tegra_isomgr_adma_renegotiate(void *p, u32 avail_bw) -{ - /* For Audio usecase there is no possibility of renegotiation - as it may lead to glitches. So currently dummy renegotiate call - is added to support bandwidth request more than registered bw which - got initialized during register call */ -} -EXPORT_SYMBOL(tegra_isomgr_adma_renegotiate); - -void tegra_isomgr_adma_register(void) +void tegra_isomgr_adma_register(struct device *dev) { adma = kzalloc(sizeof(struct adma_isomgr), GFP_KERNEL); if (!adma) { @@ -162,42 +177,72 @@ void tegra_isomgr_adma_register(void) } adma->current_bandwidth = 0; + adma->isomgr_handle = NULL; + adma->icc_path_handle = NULL; memset(&adma->device_number, 0, sizeof(bool) * MAX_DEV_NUM); memset(&adma->bw_per_device, 0, sizeof(int) * MAX_DEV_NUM); mutex_init(&adma->mutex); - /* Register the required BW for adma usecases.*/ - adma->isomgr_handle = tegra_isomgr_register(TEGRA_ISO_CLIENT_APE_ADMA, + switch (tegra_get_chip_id()) { + case TEGRA210: + /* No Support added for T210 */ + tegra_isomgr_adma_unregister(dev); + break; + case TEGRA186: + case TEGRA194: +#if IS_ENABLED(CONFIG_TEGRA_ISOMGR) && IS_ENABLED(CONFIG_NV_TEGRA_MC) + /* Register the required BW for adma usecases.*/ + adma->isomgr_handle = tegra_isomgr_register( + TEGRA_ISO_CLIENT_APE_ADMA, tegra_adma_calc_min_bandwidth(), tegra_isomgr_adma_renegotiate, adma); - if (IS_ERR(adma->isomgr_handle)) { - pr_err("%s: Failed to register adma isomgr client. err=%ld\n", + if (IS_ERR(adma->isomgr_handle)) { + pr_err( + "%s: Failed to register adma isomgr client. err=%ld\n", __func__, PTR_ERR(adma->isomgr_handle)); - adma->isomgr_handle = NULL; - mutex_destroy(&adma->mutex); - kfree(adma); - adma = NULL; + adma->isomgr_handle = NULL; + tegra_isomgr_adma_unregister(dev); + } +#endif + break; + default: + adma->icc_path_handle = icc_get(dev, TEGRA_ICC_APEDMA, + TEGRA_ICC_PRIMARY); + if (IS_ERR(adma->icc_path_handle)) { + pr_err("%s: Failed to register Interconnect. err=%ld\n", + __func__, PTR_ERR(adma->icc_path_handle)); + adma->icc_path_handle = NULL; + tegra_isomgr_adma_unregister(dev); + } } } EXPORT_SYMBOL(tegra_isomgr_adma_register); -void tegra_isomgr_adma_unregister(void) + +void tegra_isomgr_adma_unregister(struct device *dev) { if (!adma) return; mutex_destroy(&adma->mutex); + if (adma->icc_path_handle) { + icc_put(adma->icc_path_handle); + adma->icc_path_handle = NULL; + } + +#if IS_ENABLED(CONFIG_TEGRA_ISOMGR) && IS_ENABLED(CONFIG_NV_TEGRA_MC) if (adma->isomgr_handle) { tegra_isomgr_unregister(adma->isomgr_handle); adma->isomgr_handle = NULL; } +#endif kfree(adma); adma = NULL; } EXPORT_SYMBOL(tegra_isomgr_adma_unregister); -#endif - +MODULE_AUTHOR("Mohan Kumar "); +MODULE_DESCRIPTION("Tegra ADMA Bandwidth Request driver"); MODULE_LICENSE("GPL"); diff --git a/sound/soc/tegra/tegra_isomgr_bw.h b/sound/soc/tegra/tegra_isomgr_bw.h index 3e39898b..bbbadd87 100644 --- a/sound/soc/tegra/tegra_isomgr_bw.h +++ b/sound/soc/tegra/tegra_isomgr_bw.h @@ -18,18 +18,9 @@ #ifndef __TEGRA_ISOMGR_BW_H__ #define __TEGRA_ISOMGR_BW_H__ - -#if defined(CONFIG_TEGRA_ISOMGR) && defined(CONFIG_NV_TEGRA_MC) -void tegra_isomgr_adma_register(void); -void tegra_isomgr_adma_unregister(void); +void tegra_isomgr_adma_register(struct device *dev); +void tegra_isomgr_adma_unregister(struct device *dev); void tegra_isomgr_adma_setbw(struct snd_pcm_substream *substream, bool is_running); void tegra_isomgr_adma_renegotiate(void *p, u32 avail_bw); -#else -static inline void tegra_isomgr_adma_register(void) { return; } -static inline void tegra_isomgr_adma_unregister(void) { return; } -static inline void tegra_isomgr_adma_setbw(struct snd_pcm_substream *substream, - bool is_running) { return; } -#endif - #endif