mirror of
git://nv-tegra.nvidia.com/linux-nv-oot.git
synced 2025-12-22 09:11:26 +03:00
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 <mkumard@nvidia.com> Reviewed-on: https://git-master.nvidia.com/r/c/linux-5.9/+/2408552 Tested-by: mobile promotions <svcmobile_promotions@nvidia.com> Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
This commit is contained in:
committed by
Sameer Pujar
parent
79d734adb3
commit
30706b0cef
@@ -268,7 +268,6 @@ 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);
|
||||
|
||||
return 0;
|
||||
@@ -279,7 +278,6 @@ 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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -15,20 +15,20 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <sound/pcm_params.h>
|
||||
#include <sound/soc.h>
|
||||
#include <linux/platform/tegra/isomgr.h>
|
||||
#include <linux/platform/tegra/latency_allowance.h>
|
||||
#include "tegra_isomgr_bw.h"
|
||||
|
||||
#if defined(CONFIG_TEGRA_ISOMGR) && defined(CONFIG_NV_TEGRA_MC)
|
||||
#include <soc/tegra/fuse.h>
|
||||
#include <linux/interconnect.h>
|
||||
#include <dt-bindings/interconnect/tegra_icc_id.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
|
||||
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*/
|
||||
/* 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__);
|
||||
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);
|
||||
|
||||
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,
|
||||
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",
|
||||
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;
|
||||
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 <mkumard@nvidia.com>");
|
||||
MODULE_DESCRIPTION("Tegra ADMA Bandwidth Request driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user