ASoC: tegra: Invoke multi instance APIs

- Invoke the new multi instance ADSP OS and app
  APIs in the adsp and virt-alt adsp ASoC drivers.
- Currently, it is hardcoded to get the ADSP0 handle
  and invoke the respective APIs. Multi instance
  support is to be added later in these drivers.

Bug 4606840
Bug 4635899

Change-Id: I6c95693d738a2b77e953195698bfe2cab8f13dba
Signed-off-by: Aditya Bavanari <abavanari@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3145896
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: svcacv <svcacv@nvidia.com>
Reviewed-by: Viswanath L <viswanathl@nvidia.com>
Reviewed-by: Mohan kumar <mkumard@nvidia.com>
This commit is contained in:
Aditya Bavanari
2024-05-28 08:58:01 +00:00
committed by mobile promotions
parent 939e786e16
commit e7b93be004
2 changed files with 132 additions and 68 deletions

View File

@@ -1,7 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only // SPDX-License-Identifier: GPL-2.0-only
/* // SPDX-FileCopyrightText: Copyright (c) 2021-2024 NVIDIA CORPORATION. All rights reserved.
* Copyright (c) 2021-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved. //
*/
#include <nvidia/conftest.h> #include <nvidia/conftest.h>
@@ -194,6 +193,7 @@ struct tegra210_adsp {
int32_t apm_to_admaif_map[APM_IN_END - APM_IN_START + 1][2]; int32_t apm_to_admaif_map[APM_IN_END - APM_IN_START + 1][2];
bool is_fe_set[ADSP_FE_COUNT]; bool is_fe_set[ADSP_FE_COUNT];
struct sock *nl_sk; struct sock *nl_sk;
struct nvadsp_handle *hdl;
}; };
static const struct snd_pcm_hardware adsp_pcm_hardware = { static const struct snd_pcm_hardware adsp_pcm_hardware = {
@@ -357,15 +357,24 @@ static uint32_t tegra210_adsp_get_source(struct tegra210_adsp *adsp,
return source; return source;
} }
/* ADSP shared memory allocate/free functions */ /* ADSP shared memory allocate/free functions */
static int tegra210_adsp_preallocate_dma_buffer(struct device *dev, size_t size, static int tegra210_adsp_preallocate_dma_buffer(struct device *dev,
struct tegra210_adsp *adsp,
size_t size,
struct snd_dma_buffer *buf) struct snd_dma_buffer *buf)
{ {
dev_vdbg(dev, "%s : size %d.", __func__, (uint32_t)size); struct nvadsp_handle *h;
buf->area = nvadsp_alloc_coherent(size, &buf->addr, GFP_KERNEL); dev_vdbg(dev, "%s : size %d\n", __func__, (uint32_t)size);
if (!adsp)
return -ENODEV;
h = adsp->hdl;
buf->area = h->alloc_coherent(h, size, &buf->addr, GFP_KERNEL);
if (!buf->area) { if (!buf->area) {
dev_err(dev, "Failed to pre-allocated DMA buffer."); dev_err(dev, "Failed to pre-allocate DMA buffer");
return -ENOMEM; return -ENOMEM;
} }
@@ -377,39 +386,44 @@ static int tegra210_adsp_preallocate_dma_buffer(struct device *dev, size_t size,
return 0; return 0;
} }
static void tegra210_adsp_deallocate_dma_buffer(struct snd_dma_buffer *buf) static void tegra210_adsp_deallocate_dma_buffer(struct tegra210_adsp *adsp,
struct snd_dma_buffer *buf)
{ {
dev_vdbg(buf->dev.dev, "%s : size %d.", __func__, (uint32_t)buf->bytes); struct nvadsp_handle *h;
dev_vdbg(buf->dev.dev, "%s : size %d\n", __func__, (uint32_t)buf->bytes);
if (!buf->area) if (!buf->area)
return; return;
nvadsp_free_coherent(buf->bytes, buf->area, buf->addr); h = adsp->hdl;
h->free_coherent(h, buf->bytes, buf->area, buf->addr);
buf->area = NULL; buf->area = NULL;
buf->addr = 0; buf->addr = 0;
} }
/* ADSP OS boot and init API */ /* ADSP OS boot and init API */
static int tegra210_adsp_init(struct tegra210_adsp *adsp) static int tegra210_adsp_init(struct tegra210_adsp *adsp)
{ {
int i, ret = 0; int i, ret = 0;
struct nvadsp_handle *h = adsp->hdl;
mutex_lock(&adsp->mutex); mutex_lock(&adsp->mutex);
ret = nvadsp_os_load();
ret = h->os_load(h);
if (ret < 0) { if (ret < 0) {
dev_err(adsp->dev, "Failed to load OS."); dev_err(adsp->dev, "Failed to load OS.");
goto exit; goto exit;
} }
if (nvadsp_os_start()) { if (h->os_start(h)) {
dev_err(adsp->dev, "Failed to start OS"); dev_err(adsp->dev, "Failed to start OS");
goto exit; goto exit;
} }
/* Load ADSP audio apps */ /* Load ADSP audio apps */
for (i = 0; i < adsp_app_count; i++) { for (i = 0; i < adsp_app_count; i++) {
adsp_app_desc[i].handle = nvadsp_app_load( adsp_app_desc[i].handle = h->app_load(h,
adsp_app_desc[i].name, adsp_app_desc[i].name,
adsp_app_desc[i].fw_name); adsp_app_desc[i].fw_name);
if (!adsp_app_desc[i].handle) { if (!adsp_app_desc[i].handle) {
@@ -421,7 +435,7 @@ static int tegra210_adsp_init(struct tegra210_adsp *adsp)
/* TODO: set callback function for adsp to dump adma registers for debug */ /* TODO: set callback function for adsp to dump adma registers for debug */
/* Suspend OS for now. Resume will happen via runtime pm calls */ /* Suspend OS for now. Resume will happen via runtime pm calls */
ret = nvadsp_os_suspend(); ret = h->os_suspend(h);
if (ret < 0) { if (ret < 0) {
dev_err(adsp->dev, "Failed to suspend OS."); dev_err(adsp->dev, "Failed to suspend OS.");
goto exit; goto exit;
@@ -436,9 +450,11 @@ exit:
static void tegra210_adsp_deinit(struct tegra210_adsp *adsp) static void tegra210_adsp_deinit(struct tegra210_adsp *adsp)
{ {
struct nvadsp_handle *h = adsp->hdl;
mutex_lock(&adsp->mutex); mutex_lock(&adsp->mutex);
if (adsp->init_done) { if (adsp->init_done) {
nvadsp_os_stop(); h->os_stop(h);
adsp->init_done = 0; adsp->init_done = 0;
} }
mutex_unlock(&adsp->mutex); mutex_unlock(&adsp->mutex);
@@ -468,6 +484,7 @@ static int tegra210_adsp_send_msg(struct tegra210_adsp_app *app,
{ {
int ret = 0; int ret = 0;
unsigned long flag; unsigned long flag;
struct nvadsp_handle *h = app->adsp->hdl;
if (flags & TEGRA210_ADSP_MSG_FLAG_NEED_ACK) { if (flags & TEGRA210_ADSP_MSG_FLAG_NEED_ACK) {
if (flags & TEGRA210_ADSP_MSG_FLAG_HOLD) { if (flags & TEGRA210_ADSP_MSG_FLAG_HOLD) {
@@ -499,7 +516,7 @@ static int tegra210_adsp_send_msg(struct tegra210_adsp_app *app,
spin_unlock_irqrestore(&app->apm_msg_queue_lock, flag); spin_unlock_irqrestore(&app->apm_msg_queue_lock, flag);
if (ret < 0) { if (ret < 0) {
/* Wakeup APM to consume messages and give it some time */ /* Wakeup APM to consume messages and give it some time */
ret = nvadsp_mbox_send(&app->apm_mbox, apm_cmd_msg_ready, ret = h->mbox_send(h, &app->apm_mbox, apm_cmd_msg_ready,
NVADSP_MBOX_SMSG, false, 0); NVADSP_MBOX_SMSG, false, 0);
if (ret) { if (ret) {
pr_err("%s: Failed to send mailbox message id %d ret %d\n", pr_err("%s: Failed to send mailbox message id %d ret %d\n",
@@ -525,7 +542,7 @@ static int tegra210_adsp_send_msg(struct tegra210_adsp_app *app,
if (flags & TEGRA210_ADSP_MSG_FLAG_HOLD) if (flags & TEGRA210_ADSP_MSG_FLAG_HOLD)
return 0; return 0;
ret = nvadsp_mbox_send(&app->apm_mbox, apm_cmd_msg_ready, ret = h->mbox_send(h, &app->apm_mbox, apm_cmd_msg_ready,
NVADSP_MBOX_SMSG, false, 0); NVADSP_MBOX_SMSG, false, 0);
if (ret) { if (ret) {
pr_err("%s: Failed to send mailbox message id %d ret %d\n", pr_err("%s: Failed to send mailbox message id %d ret %d\n",
@@ -552,6 +569,7 @@ static int tegra210_adsp_send_raw_data_msg(struct tegra210_adsp_app *app,
int ret = 0; int ret = 0;
struct tegra210_adsp_app *apm = app; struct tegra210_adsp_app *apm = app;
unsigned long flag; unsigned long flag;
struct nvadsp_handle *h = app->adsp->hdl;
/* Find parent APM to wait for ACK*/ /* Find parent APM to wait for ACK*/
if (!IS_APM_IN(apm->reg)) { if (!IS_APM_IN(apm->reg)) {
@@ -576,7 +594,7 @@ static int tegra210_adsp_send_raw_data_msg(struct tegra210_adsp_app *app,
return ret; return ret;
} }
ret = nvadsp_mbox_send(&app->apm_mbox, apm_cmd_raw_data_ready, ret = h->mbox_send(h, &app->apm_mbox, apm_cmd_raw_data_ready,
NVADSP_MBOX_SMSG, true, 100); NVADSP_MBOX_SMSG, true, 100);
if (ret) { if (ret) {
pr_err("Failed to send mailbox message id %d ret %d\n", pr_err("Failed to send mailbox message id %d ret %d\n",
@@ -826,6 +844,7 @@ static int tegra210_adsp_app_init(struct tegra210_adsp *adsp,
struct tegra210_adsp_app *app) struct tegra210_adsp_app *app)
{ {
int ret = 0; int ret = 0;
struct nvadsp_handle *h = adsp->hdl;
/* If app is already open or it is APM output pin don't open app */ /* If app is already open or it is APM output pin don't open app */
if (app->info || IS_APM_OUT(app->reg)) if (app->info || IS_APM_OUT(app->reg))
@@ -834,7 +853,7 @@ static int tegra210_adsp_app_init(struct tegra210_adsp *adsp,
if (!app->desc->handle) if (!app->desc->handle)
return -ENODEV; return -ENODEV;
app->info = nvadsp_app_init(app->desc->handle, NULL); app->info = h->app_init(h, app->desc->handle, NULL);
if (IS_ERR_OR_NULL(app->info)) { if (IS_ERR_OR_NULL(app->info)) {
dev_err(adsp->dev, "Failed to init app %s(%s).", dev_err(adsp->dev, "Failed to init app %s(%s).",
app->desc->name, app->desc->fw_name); app->desc->name, app->desc->fw_name);
@@ -859,7 +878,7 @@ static int tegra210_adsp_app_init(struct tegra210_adsp *adsp,
app->apm = APM_SHARED_STATE(app->info->mem.shared); app->apm = APM_SHARED_STATE(app->info->mem.shared);
app->info->stack_size = apm_stack_size[app->reg - APM_IN_START]; app->info->stack_size = apm_stack_size[app->reg - APM_IN_START];
ret = nvadsp_mbox_open(&app->apm_mbox, ret = h->mbox_open(h, &app->apm_mbox,
&app->apm->mbox_id, &app->apm->mbox_id,
app->desc->name, tegra210_adsp_msg_handler, app); app->desc->name, tegra210_adsp_msg_handler, app);
if (ret < 0) { if (ret < 0) {
@@ -896,7 +915,7 @@ static int tegra210_adsp_app_init(struct tegra210_adsp *adsp,
init_completion(app->raw_msg_read_complete); init_completion(app->raw_msg_read_complete);
init_completion(app->raw_msg_write_complete); init_completion(app->raw_msg_write_complete);
ret = nvadsp_app_start(app->info); ret = h->app_start(h, app->info);
if (ret < 0) { if (ret < 0) {
dev_err(adsp->dev, "Failed to start adsp app"); dev_err(adsp->dev, "Failed to start adsp app");
goto err_mbox_close; goto err_mbox_close;
@@ -937,7 +956,7 @@ static int tegra210_adsp_app_init(struct tegra210_adsp *adsp,
return 0; return 0;
err_mbox_close: err_mbox_close:
nvadsp_mbox_close(&app->apm_mbox); h->mbox_close(h, &app->apm_mbox);
err_app_exit: err_app_exit:
app->info = NULL; app->info = NULL;
return 0; return 0;
@@ -1520,6 +1539,7 @@ static int tegra210_adsp_compr_free(struct snd_soc_component *component,
struct snd_compr_stream *cstream) struct snd_compr_stream *cstream)
{ {
struct tegra210_adsp_compr_rtd *prtd = cstream->runtime->private_data; struct tegra210_adsp_compr_rtd *prtd = cstream->runtime->private_data;
struct tegra210_adsp *adsp = dev_get_drvdata(component->dev);
unsigned long flags; unsigned long flags;
if (!prtd) if (!prtd)
@@ -1530,7 +1550,7 @@ static int tegra210_adsp_compr_free(struct snd_soc_component *component,
pm_runtime_put(prtd->dev); pm_runtime_put(prtd->dev);
tegra210_adsp_deallocate_dma_buffer(&prtd->buf); tegra210_adsp_deallocate_dma_buffer(adsp, &prtd->buf);
spin_lock_irqsave(&prtd->fe_apm->lock, flags); spin_lock_irqsave(&prtd->fe_apm->lock, flags);
@@ -1550,6 +1570,7 @@ static int tegra210_adsp_compr_set_params(struct snd_soc_component *component,
struct snd_compr_params *params) struct snd_compr_params *params)
{ {
struct tegra210_adsp_compr_rtd *prtd = cstream->runtime->private_data; struct tegra210_adsp_compr_rtd *prtd = cstream->runtime->private_data;
struct tegra210_adsp *adsp = dev_get_drvdata(component->dev);
int ret = 0; int ret = 0;
if (!prtd) if (!prtd)
@@ -1561,7 +1582,7 @@ static int tegra210_adsp_compr_set_params(struct snd_soc_component *component,
params->codec.ch_in, params->buffer.fragment_size, params->codec.ch_in, params->buffer.fragment_size,
params->buffer.fragments); params->buffer.fragments);
ret = tegra210_adsp_preallocate_dma_buffer(prtd->dev, ret = tegra210_adsp_preallocate_dma_buffer(prtd->dev, adsp,
params->buffer.fragment_size * params->buffer.fragments, params->buffer.fragment_size * params->buffer.fragments,
&prtd->buf); &prtd->buf);
if (ret < 0) if (ret < 0)
@@ -2393,13 +2414,14 @@ static int tegra210_adsp_pcm_construct(struct snd_soc_component *component,
#if ENABLE_ADSP #if ENABLE_ADSP
struct snd_card *card = rtd->card->snd_card; struct snd_card *card = rtd->card->snd_card;
struct snd_pcm *pcm = rtd->pcm; struct snd_pcm *pcm = rtd->pcm;
struct tegra210_adsp *adsp = dev_get_drvdata(component->dev);
int ret = 0; int ret = 0;
if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) { if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
struct snd_pcm_substream *substream = struct snd_pcm_substream *substream =
pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
ret = tegra210_adsp_preallocate_dma_buffer(card->dev, ret = tegra210_adsp_preallocate_dma_buffer(card->dev, adsp,
adsp_pcm_hardware.buffer_bytes_max, adsp_pcm_hardware.buffer_bytes_max,
&substream->dma_buffer); &substream->dma_buffer);
@@ -2411,7 +2433,7 @@ static int tegra210_adsp_pcm_construct(struct snd_soc_component *component,
struct snd_pcm_substream *substream = struct snd_pcm_substream *substream =
pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream; pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream;
ret = tegra210_adsp_preallocate_dma_buffer(card->dev, ret = tegra210_adsp_preallocate_dma_buffer(card->dev, adsp,
adsp_pcm_hardware.buffer_bytes_max, adsp_pcm_hardware.buffer_bytes_max,
&substream->dma_buffer); &substream->dma_buffer);
if (ret) if (ret)
@@ -2421,7 +2443,7 @@ static int tegra210_adsp_pcm_construct(struct snd_soc_component *component,
return 0; return 0;
err: err:
tegra210_adsp_deallocate_dma_buffer( tegra210_adsp_deallocate_dma_buffer(adsp,
&pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream->dma_buffer); &pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream->dma_buffer);
return ret; return ret;
#else #else
@@ -2432,16 +2454,18 @@ err:
static void tegra210_adsp_pcm_destruct(struct snd_soc_component *component, static void tegra210_adsp_pcm_destruct(struct snd_soc_component *component,
struct snd_pcm *pcm) struct snd_pcm *pcm)
{ {
struct tegra210_adsp *adsp = dev_get_drvdata(component->dev);
if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) { if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
int stream = SNDRV_PCM_STREAM_PLAYBACK; int stream = SNDRV_PCM_STREAM_PLAYBACK;
tegra210_adsp_deallocate_dma_buffer( tegra210_adsp_deallocate_dma_buffer(adsp,
&pcm->streams[stream].substream->dma_buffer); &pcm->streams[stream].substream->dma_buffer);
} }
if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) { if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
int stream = SNDRV_PCM_STREAM_CAPTURE; int stream = SNDRV_PCM_STREAM_CAPTURE;
tegra210_adsp_deallocate_dma_buffer( tegra210_adsp_deallocate_dma_buffer(adsp,
&pcm->streams[stream].substream->dma_buffer); &pcm->streams[stream].substream->dma_buffer);
} }
} }
@@ -2926,6 +2950,7 @@ static int tegra210_adsp_runtime_suspend(struct device *dev)
{ {
struct tegra210_adsp *adsp = dev_get_drvdata(dev); struct tegra210_adsp *adsp = dev_get_drvdata(dev);
int ret = 0, i; int ret = 0, i;
struct nvadsp_handle *h = adsp->hdl;
dev_dbg(adsp->dev, "%s\n", __func__); dev_dbg(adsp->dev, "%s\n", __func__);
@@ -2948,7 +2973,7 @@ static int tegra210_adsp_runtime_suspend(struct device *dev)
} }
} }
ret = nvadsp_os_suspend(); ret = h->os_suspend(h);
if (ret) if (ret)
dev_err(adsp->dev, "Failed to suspend ADSP OS"); dev_err(adsp->dev, "Failed to suspend ADSP OS");
@@ -2968,6 +2993,7 @@ static int tegra210_adsp_runtime_resume(struct device *dev)
{ {
struct tegra210_adsp *adsp = dev_get_drvdata(dev); struct tegra210_adsp *adsp = dev_get_drvdata(dev);
int ret = 0; int ret = 0;
struct nvadsp_handle *h = adsp->hdl;
dev_dbg(adsp->dev, "%s\n", __func__); dev_dbg(adsp->dev, "%s\n", __func__);
@@ -2975,7 +3001,6 @@ static int tegra210_adsp_runtime_resume(struct device *dev)
if (!adsp->init_done || adsp->adsp_started) if (!adsp->init_done || adsp->adsp_started)
goto exit; goto exit;
ret = clk_prepare_enable(adsp->ahub_clk); ret = clk_prepare_enable(adsp->ahub_clk);
if (ret < 0) { if (ret < 0) {
dev_err(dev, "ahub clk_enable failed: %d\n", ret); dev_err(dev, "ahub clk_enable failed: %d\n", ret);
@@ -2997,7 +3022,7 @@ static int tegra210_adsp_runtime_resume(struct device *dev)
} }
} }
ret = nvadsp_os_start(); ret = h->os_start(h);
if (ret) { if (ret) {
dev_err(adsp->dev, "Failed to start ADSP OS ret 0x%x", ret); dev_err(adsp->dev, "Failed to start ADSP OS ret 0x%x", ret);
adsp->adsp_started = 0; adsp->adsp_started = 0;
@@ -4952,7 +4977,7 @@ static int tegra210_adsp_component_probe(struct snd_soc_component *cmpnt)
struct tegra210_adsp *adsp = dev_get_drvdata(cmpnt->dev); struct tegra210_adsp *adsp = dev_get_drvdata(cmpnt->dev);
if (!adsp) if (!adsp)
return -ENODEV; return -EPROBE_DEFER;
snd_soc_component_set_drvdata(cmpnt, adsp); snd_soc_component_set_drvdata(cmpnt, adsp);
@@ -5071,7 +5096,13 @@ static int tegra210_adsp_audio_probe(struct platform_device *pdev)
adsp->is_shutdown = false; adsp->is_shutdown = false;
adsp->soc_data = (struct adsp_soc_data *)match->data; adsp->soc_data = (struct adsp_soc_data *)match->data;
/*
* Currently it is hardcoded to get the ADSP0 handle
* TODO: Multi instance ADSP support to be added
*/
adsp->hdl = nvadsp_get_handle("adsp");
if (!adsp->hdl)
return -EPROBE_DEFER;
adsp->ahub_clk = devm_clk_get(&pdev->dev, "ahub"); adsp->ahub_clk = devm_clk_get(&pdev->dev, "ahub");
if (IS_ERR(adsp->ahub_clk)) { if (IS_ERR(adsp->ahub_clk)) {
@@ -5103,7 +5134,6 @@ static int tegra210_adsp_audio_probe(struct platform_device *pdev)
pdev->dev.dma_mask = &tegra_dma_mask; pdev->dev.dma_mask = &tegra_dma_mask;
pdev->dev.coherent_dma_mask = tegra_dma_mask; pdev->dev.coherent_dma_mask = tegra_dma_mask;
pm_runtime_enable(&pdev->dev); pm_runtime_enable(&pdev->dev);
if (!pm_runtime_enabled(&pdev->dev)) if (!pm_runtime_enabled(&pdev->dev))
goto err_pm_disable; goto err_pm_disable;
@@ -5227,7 +5257,6 @@ static int tegra210_adsp_audio_probe(struct platform_device *pdev)
} }
} }
/* copy basic apps needed */ /* copy basic apps needed */
memcpy(&adsp_app_desc[adsp_app_count], memcpy(&adsp_app_desc[adsp_app_count],
&adsp_app_minimal[0], sizeof(adsp_app_minimal)); &adsp_app_minimal[0], sizeof(adsp_app_minimal));

View File

@@ -173,6 +173,7 @@ struct tegra210_adsp {
uint32_t rate; uint32_t rate;
} pcm_path[ADSP_FE_COUNT+1][2]; } pcm_path[ADSP_FE_COUNT+1][2];
struct sock *nl_sk; struct sock *nl_sk;
struct nvadsp_handle *hdl;
}; };
static const struct snd_pcm_hardware adsp_pcm_hardware = { static const struct snd_pcm_hardware adsp_pcm_hardware = {
@@ -336,13 +337,22 @@ static uint32_t tegra210_adsp_get_source(struct tegra210_adsp *adsp,
return source; return source;
} }
/* ADSP shared memory allocate/free functions */ /* ADSP shared memory allocate/free functions */
static int tegra210_adsp_preallocate_dma_buffer(struct device *dev, size_t size, static int tegra210_adsp_preallocate_dma_buffer(struct device *dev,
struct tegra210_adsp *adsp,
size_t size,
struct snd_dma_buffer *buf) struct snd_dma_buffer *buf)
{ {
dev_vdbg(dev, "%s : size %d.", __func__, (uint32_t)size); struct nvadsp_handle *h;
buf->area = nvadsp_alloc_coherent(size, &buf->addr, GFP_KERNEL); dev_vdbg(dev, "%s : size %d\n", __func__, (uint32_t)size);
if (!adsp)
return -ENODEV;
h = adsp->hdl;
buf->area = h->alloc_coherent(h, size, &buf->addr, GFP_KERNEL);
if (!buf->area) { if (!buf->area) {
dev_err(dev, "Failed to pre-allocated DMA buffer."); dev_err(dev, "Failed to pre-allocated DMA buffer.");
return -ENOMEM; return -ENOMEM;
@@ -356,14 +366,18 @@ static int tegra210_adsp_preallocate_dma_buffer(struct device *dev, size_t size,
return 0; return 0;
} }
static void tegra210_adsp_deallocate_dma_buffer(struct snd_dma_buffer *buf) static void tegra210_adsp_deallocate_dma_buffer(struct tegra210_adsp *adsp,
struct snd_dma_buffer *buf)
{ {
dev_vdbg(buf->dev.dev, "%s : size %d.", __func__, (uint32_t)buf->bytes); struct nvadsp_handle *h;
dev_vdbg(buf->dev.dev, "%s : size %d\n", __func__, (uint32_t)buf->bytes);
if (!buf->area) if (!buf->area)
return; return;
nvadsp_free_coherent(buf->bytes, buf->area, buf->addr); h = adsp->hdl;
h->free_coherent(h, buf->bytes, buf->area, buf->addr);
buf->area = NULL; buf->area = NULL;
buf->addr = 0; buf->addr = 0;
} }
@@ -372,19 +386,20 @@ static void tegra210_adsp_deallocate_dma_buffer(struct snd_dma_buffer *buf)
static int tegra210_adsp_init(struct tegra210_adsp *adsp) static int tegra210_adsp_init(struct tegra210_adsp *adsp)
{ {
int i, ret = 0; int i, ret = 0;
struct nvadsp_handle *h = adsp->hdl;
mutex_lock(&adsp->mutex); mutex_lock(&adsp->mutex);
if (adsp->init_done) if (adsp->init_done)
goto exit; goto exit;
ret = nvadsp_os_load(); ret = h->os_load(h);
if (ret < 0) { if (ret < 0) {
dev_err(adsp->dev, "Failed to load OS."); dev_err(adsp->dev, "Failed to load OS.");
goto exit; goto exit;
} }
ret = nvadsp_os_start(); ret = h->os_start(h);
if (ret) { if (ret) {
dev_err(adsp->dev, "Failed to start OS"); dev_err(adsp->dev, "Failed to start OS");
goto exit; goto exit;
@@ -392,7 +407,7 @@ static int tegra210_adsp_init(struct tegra210_adsp *adsp)
/* Load ADSP audio apps */ /* Load ADSP audio apps */
for (i = 0; i < adsp_app_count; i++) { for (i = 0; i < adsp_app_count; i++) {
adsp_app_desc[i].handle = nvadsp_app_load( adsp_app_desc[i].handle = h->app_load(h,
adsp_app_desc[i].name, adsp_app_desc[i].name,
adsp_app_desc[i].fw_name); adsp_app_desc[i].fw_name);
if (adsp_app_desc[i].handle) { if (adsp_app_desc[i].handle) {
@@ -406,7 +421,7 @@ static int tegra210_adsp_init(struct tegra210_adsp *adsp)
*/ */
/* Suspend OS for now. Resume will happen via runtime pm calls */ /* Suspend OS for now. Resume will happen via runtime pm calls */
ret = nvadsp_os_suspend(); ret = h->os_suspend(h);
if (ret < 0) { if (ret < 0) {
dev_err(adsp->dev, "Failed to suspend OS."); dev_err(adsp->dev, "Failed to suspend OS.");
goto exit; goto exit;
@@ -422,9 +437,11 @@ exit:
static void tegra210_adsp_deinit(struct tegra210_adsp *adsp) static void tegra210_adsp_deinit(struct tegra210_adsp *adsp)
{ {
struct nvadsp_handle *h = adsp->hdl;
mutex_lock(&adsp->mutex); mutex_lock(&adsp->mutex);
if (adsp->init_done) { if (adsp->init_done) {
nvadsp_os_stop(); h->os_stop(h);
adsp->init_done = 0; adsp->init_done = 0;
} }
reinit_completion(&adsp->init_complete); reinit_completion(&adsp->init_complete);
@@ -455,6 +472,7 @@ static int tegra210_adsp_send_msg(struct tegra210_adsp_app *app,
{ {
int ret = 0; int ret = 0;
unsigned long flag; unsigned long flag;
struct nvadsp_handle *h = app->adsp->hdl;
if (flags & TEGRA210_ADSP_MSG_FLAG_NEED_ACK) { if (flags & TEGRA210_ADSP_MSG_FLAG_NEED_ACK) {
if (flags & TEGRA210_ADSP_MSG_FLAG_HOLD) { if (flags & TEGRA210_ADSP_MSG_FLAG_HOLD) {
@@ -486,7 +504,7 @@ static int tegra210_adsp_send_msg(struct tegra210_adsp_app *app,
spin_unlock_irqrestore(&app->apm_msg_queue_lock, flag); spin_unlock_irqrestore(&app->apm_msg_queue_lock, flag);
if (ret < 0) { if (ret < 0) {
/* Wakeup APM to consume messages and give it some time */ /* Wakeup APM to consume messages and give it some time */
ret = nvadsp_mbox_send(&app->apm_mbox, apm_cmd_msg_ready, ret = h->mbox_send(h, &app->apm_mbox, apm_cmd_msg_ready,
NVADSP_MBOX_SMSG, false, 0); NVADSP_MBOX_SMSG, false, 0);
if (ret) { if (ret) {
pr_err("%s: Failed to send mailbox message id %d ret %d\n", pr_err("%s: Failed to send mailbox message id %d ret %d\n",
@@ -512,7 +530,7 @@ static int tegra210_adsp_send_msg(struct tegra210_adsp_app *app,
if (flags & TEGRA210_ADSP_MSG_FLAG_HOLD) if (flags & TEGRA210_ADSP_MSG_FLAG_HOLD)
return 0; return 0;
ret = nvadsp_mbox_send(&app->apm_mbox, apm_cmd_msg_ready, ret = h->mbox_send(h, &app->apm_mbox, apm_cmd_msg_ready,
NVADSP_MBOX_SMSG, false, 0); NVADSP_MBOX_SMSG, false, 0);
if (ret) { if (ret) {
pr_err("%s: Failed to send mailbox message id %d ret %d\n", pr_err("%s: Failed to send mailbox message id %d ret %d\n",
@@ -539,6 +557,7 @@ static int tegra210_adsp_send_raw_data_msg(struct tegra210_adsp_app *app,
int ret = 0; int ret = 0;
struct tegra210_adsp_app *apm = app; struct tegra210_adsp_app *apm = app;
unsigned long flag; unsigned long flag;
struct nvadsp_handle *h = app->adsp->hdl;
/* Find parent APM to wait for ACK*/ /* Find parent APM to wait for ACK*/
if (!IS_APM_IN(apm->reg)) { if (!IS_APM_IN(apm->reg)) {
@@ -563,7 +582,7 @@ static int tegra210_adsp_send_raw_data_msg(struct tegra210_adsp_app *app,
return ret; return ret;
} }
ret = nvadsp_mbox_send(&app->apm_mbox, apm_cmd_raw_data_ready, ret = h->mbox_send(h, &app->apm_mbox, apm_cmd_raw_data_ready,
NVADSP_MBOX_SMSG, true, 100); NVADSP_MBOX_SMSG, true, 100);
if (ret) { if (ret) {
pr_err("Failed to send mailbox message id %d ret %d\n", pr_err("Failed to send mailbox message id %d ret %d\n",
@@ -820,6 +839,7 @@ static int tegra210_adsp_app_init(struct tegra210_adsp *adsp,
struct tegra210_adsp_app *app) struct tegra210_adsp_app *app)
{ {
int ret = 0; int ret = 0;
struct nvadsp_handle *h = adsp->hdl;
/* If app is already open or it is APM output pin don't open app */ /* If app is already open or it is APM output pin don't open app */
if (app->info || IS_APM_OUT(app->reg)) if (app->info || IS_APM_OUT(app->reg))
@@ -828,7 +848,7 @@ static int tegra210_adsp_app_init(struct tegra210_adsp *adsp,
if (!app->desc->handle) if (!app->desc->handle)
return -ENODEV; return -ENODEV;
app->info = nvadsp_app_init(app->desc->handle, NULL); app->info = h->app_init(h, app->desc->handle, NULL);
if (IS_ERR_OR_NULL(app->info)) { if (IS_ERR_OR_NULL(app->info)) {
dev_err(adsp->dev, "Failed to init app %s(%s).", dev_err(adsp->dev, "Failed to init app %s(%s).",
app->desc->name, app->desc->fw_name); app->desc->name, app->desc->fw_name);
@@ -852,7 +872,7 @@ static int tegra210_adsp_app_init(struct tegra210_adsp *adsp,
app->apm = APM_SHARED_STATE(app->info->mem.shared); app->apm = APM_SHARED_STATE(app->info->mem.shared);
app->info->stack_size = apm_stack_size[app->reg - APM_IN_START]; app->info->stack_size = apm_stack_size[app->reg - APM_IN_START];
ret = nvadsp_mbox_open(&app->apm_mbox, ret = h->mbox_open(h, &app->apm_mbox,
&app->apm->mbox_id, &app->apm->mbox_id,
app->desc->name, tegra210_adsp_msg_handler, app); app->desc->name, tegra210_adsp_msg_handler, app);
if (ret < 0) { if (ret < 0) {
@@ -887,7 +907,7 @@ static int tegra210_adsp_app_init(struct tegra210_adsp *adsp,
init_completion(app->raw_msg_read_complete); init_completion(app->raw_msg_read_complete);
init_completion(app->raw_msg_write_complete); init_completion(app->raw_msg_write_complete);
ret = nvadsp_app_start(app->info); ret = h->app_start(h, app->info);
if (ret < 0) { if (ret < 0) {
dev_err(adsp->dev, "Failed to start adsp app"); dev_err(adsp->dev, "Failed to start adsp app");
goto err_mbox_close; goto err_mbox_close;
@@ -928,7 +948,7 @@ static int tegra210_adsp_app_init(struct tegra210_adsp *adsp,
return 0; return 0;
err_mbox_close: err_mbox_close:
nvadsp_mbox_close(&app->apm_mbox); h->mbox_close(h, &app->apm_mbox);
err_app_exit: err_app_exit:
app->info = NULL; app->info = NULL;
return 0; return 0;
@@ -1452,6 +1472,7 @@ static int tegra210_adsp_compr_free(struct snd_soc_component *component,
struct snd_compr_stream *cstream) struct snd_compr_stream *cstream)
{ {
struct tegra210_adsp_compr_rtd *prtd = cstream->runtime->private_data; struct tegra210_adsp_compr_rtd *prtd = cstream->runtime->private_data;
struct tegra210_adsp *adsp = dev_get_drvdata(component->dev);
unsigned long flags; unsigned long flags;
if (!prtd) if (!prtd)
@@ -1462,7 +1483,7 @@ static int tegra210_adsp_compr_free(struct snd_soc_component *component,
pm_runtime_put(prtd->dev); pm_runtime_put(prtd->dev);
tegra210_adsp_deallocate_dma_buffer(&prtd->buf); tegra210_adsp_deallocate_dma_buffer(adsp, &prtd->buf);
spin_lock_irqsave(&prtd->fe_apm->lock, flags); spin_lock_irqsave(&prtd->fe_apm->lock, flags);
@@ -1482,6 +1503,7 @@ static int tegra210_adsp_compr_set_params(struct snd_soc_component *component,
struct snd_compr_params *params) struct snd_compr_params *params)
{ {
struct tegra210_adsp_compr_rtd *prtd = cstream->runtime->private_data; struct tegra210_adsp_compr_rtd *prtd = cstream->runtime->private_data;
struct tegra210_adsp *adsp = dev_get_drvdata(component->dev);
int ret = 0; int ret = 0;
if (!prtd) if (!prtd)
@@ -1493,7 +1515,7 @@ static int tegra210_adsp_compr_set_params(struct snd_soc_component *component,
params->codec.ch_in, params->buffer.fragment_size, params->codec.ch_in, params->buffer.fragment_size,
params->buffer.fragments); params->buffer.fragments);
ret = tegra210_adsp_preallocate_dma_buffer(prtd->dev, ret = tegra210_adsp_preallocate_dma_buffer(prtd->dev, adsp,
params->buffer.fragment_size * params->buffer.fragments, params->buffer.fragment_size * params->buffer.fragments,
&prtd->buf); &prtd->buf);
if (ret < 0) if (ret < 0)
@@ -1994,13 +2016,14 @@ static int tegra210_adsp_pcm_construct(struct snd_soc_component *component,
#if ENABLE_ADSP #if ENABLE_ADSP
struct snd_card *card = rtd->card->snd_card; struct snd_card *card = rtd->card->snd_card;
struct snd_pcm *pcm = rtd->pcm; struct snd_pcm *pcm = rtd->pcm;
struct tegra210_adsp *adsp = dev_get_drvdata(component->dev);
int ret = 0; int ret = 0;
if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) { if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
struct snd_pcm_substream *substream = struct snd_pcm_substream *substream =
pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
ret = tegra210_adsp_preallocate_dma_buffer(card->dev, ret = tegra210_adsp_preallocate_dma_buffer(card->dev, adsp,
adsp_pcm_hardware.buffer_bytes_max, adsp_pcm_hardware.buffer_bytes_max,
&substream->dma_buffer); &substream->dma_buffer);
@@ -2012,7 +2035,7 @@ static int tegra210_adsp_pcm_construct(struct snd_soc_component *component,
struct snd_pcm_substream *substream = struct snd_pcm_substream *substream =
pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream; pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream;
ret = tegra210_adsp_preallocate_dma_buffer(card->dev, ret = tegra210_adsp_preallocate_dma_buffer(card->dev, adsp,
adsp_pcm_hardware.buffer_bytes_max, adsp_pcm_hardware.buffer_bytes_max,
&substream->dma_buffer); &substream->dma_buffer);
if (ret) if (ret)
@@ -2022,7 +2045,7 @@ static int tegra210_adsp_pcm_construct(struct snd_soc_component *component,
return 0; return 0;
err: err:
tegra210_adsp_deallocate_dma_buffer( tegra210_adsp_deallocate_dma_buffer(adsp,
&pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream->dma_buffer); &pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream->dma_buffer);
return ret; return ret;
#else #else
@@ -2033,16 +2056,18 @@ err:
static void tegra210_adsp_pcm_destruct(struct snd_soc_component *component, static void tegra210_adsp_pcm_destruct(struct snd_soc_component *component,
struct snd_pcm *pcm) struct snd_pcm *pcm)
{ {
struct tegra210_adsp *adsp = dev_get_drvdata(component->dev);
if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) { if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
int stream = SNDRV_PCM_STREAM_PLAYBACK; int stream = SNDRV_PCM_STREAM_PLAYBACK;
tegra210_adsp_deallocate_dma_buffer( tegra210_adsp_deallocate_dma_buffer(adsp,
&pcm->streams[stream].substream->dma_buffer); &pcm->streams[stream].substream->dma_buffer);
} }
if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) { if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
int stream = SNDRV_PCM_STREAM_CAPTURE; int stream = SNDRV_PCM_STREAM_CAPTURE;
tegra210_adsp_deallocate_dma_buffer( tegra210_adsp_deallocate_dma_buffer(adsp,
&pcm->streams[stream].substream->dma_buffer); &pcm->streams[stream].substream->dma_buffer);
} }
} }
@@ -2379,6 +2404,7 @@ static int tegra210_adsp_runtime_suspend(struct device *dev)
{ {
struct tegra210_adsp *adsp = dev_get_drvdata(dev); struct tegra210_adsp *adsp = dev_get_drvdata(dev);
int ret = 0, i; int ret = 0, i;
struct nvadsp_handle *h = adsp->hdl;
dev_dbg(adsp->dev, "%s\n", __func__); dev_dbg(adsp->dev, "%s\n", __func__);
@@ -2401,13 +2427,13 @@ static int tegra210_adsp_runtime_suspend(struct device *dev)
} }
} }
ret = nvadsp_os_suspend(); ret = h->os_suspend(h);
if (ret) if (ret)
dev_err(adsp->dev, "Failed to suspend ADSP OS"); dev_err(adsp->dev, "Failed to suspend ADSP OS");
adsp->adsp_started = 0; adsp->adsp_started = 0;
if (!tegra_platform_is_fpga()) { if (!tegra_platform_is_fpga() && !tegra_platform_is_vdk()) {
if (!adsp->soc_data->is_soc_t210) if (!adsp->soc_data->is_soc_t210)
clk_disable_unprepare(adsp->apb2ape_clk); clk_disable_unprepare(adsp->apb2ape_clk);
clk_disable_unprepare(adsp->ahub_clk); clk_disable_unprepare(adsp->ahub_clk);
@@ -2423,6 +2449,7 @@ static int tegra210_adsp_runtime_resume(struct device *dev)
{ {
struct tegra210_adsp *adsp = dev_get_drvdata(dev); struct tegra210_adsp *adsp = dev_get_drvdata(dev);
int ret = 0; int ret = 0;
struct nvadsp_handle *h = adsp->hdl;
dev_dbg(adsp->dev, "%s\n", __func__); dev_dbg(adsp->dev, "%s\n", __func__);
@@ -2430,7 +2457,7 @@ static int tegra210_adsp_runtime_resume(struct device *dev)
if (!adsp->init_done || adsp->adsp_started) if (!adsp->init_done || adsp->adsp_started)
goto exit; goto exit;
if (!tegra_platform_is_fpga()) { if (!tegra_platform_is_fpga() && !tegra_platform_is_vdk()) {
ret = clk_prepare_enable(adsp->ahub_clk); ret = clk_prepare_enable(adsp->ahub_clk);
if (ret < 0) { if (ret < 0) {
dev_err(dev, "ahub clk_enable failed: %d\n", ret); dev_err(dev, "ahub clk_enable failed: %d\n", ret);
@@ -2453,7 +2480,7 @@ static int tegra210_adsp_runtime_resume(struct device *dev)
} }
} }
ret = nvadsp_os_start(); ret = h->os_start(h);
if (ret) { if (ret) {
dev_err(adsp->dev, "Failed to start ADSP OS ret 0x%x", ret); dev_err(adsp->dev, "Failed to start ADSP OS ret 0x%x", ret);
adsp->adsp_started = 0; adsp->adsp_started = 0;
@@ -4380,7 +4407,7 @@ static int tegra210_adsp_component_probe(struct snd_soc_component *cmpnt)
struct tegra210_adsp *adsp = dev_get_drvdata(cmpnt->dev); struct tegra210_adsp *adsp = dev_get_drvdata(cmpnt->dev);
if (!adsp) if (!adsp)
return -ENODEV; return -EPROBE_DEFER;
snd_soc_component_set_drvdata(cmpnt, adsp); snd_soc_component_set_drvdata(cmpnt, adsp);
@@ -4508,7 +4535,15 @@ static int tegra210_adsp_audio_probe(struct platform_device *pdev)
adsp->dev = &pdev->dev; adsp->dev = &pdev->dev;
adsp->soc_data = (struct adsp_soc_data *)match->data; adsp->soc_data = (struct adsp_soc_data *)match->data;
if (!tegra_platform_is_fpga()) { /*
* Currently it is hardcoded to get the ADSP0 handle
* TODO: Multi instance ADSP support to be added
*/
adsp->hdl = nvadsp_get_handle("adsp");
if (!adsp->hdl)
return -EPROBE_DEFER;
if (!tegra_platform_is_fpga() && !tegra_platform_is_vdk()) {
adsp->ahub_clk = devm_clk_get(&pdev->dev, "ahub"); adsp->ahub_clk = devm_clk_get(&pdev->dev, "ahub");
if (IS_ERR(adsp->ahub_clk)) { if (IS_ERR(adsp->ahub_clk)) {
dev_err(&pdev->dev, "Error: Missing AHUB clock\n"); dev_err(&pdev->dev, "Error: Missing AHUB clock\n");