mirror of
git://nv-tegra.nvidia.com/linux-nv-oot.git
synced 2025-12-22 17:25:35 +03:00
ASoC: tegra: update ADSP audio driver for 5.4
This patch registers ADSP device as a component with ASoC core. Necessary changes are made to work with 5.4 kernel and driver need not register a separate platform and codec device. Along with this following cleanup is done: - Move driver to 'tegra' directory. - Wherever possible, fix ACV issues in the driver. Not all of them can be fixed at the moment. Bug 200593718 Change-Id: Ic60c7f59095bbe9f84d25077e4d4469544ca7783 Signed-off-by: Sameer Pujar <spujar@nvidia.com> Reviewed-on: https://git-master.nvidia.com/r/c/linux-5.4/+/2342897 (cherry picked from commit d927c5daa951a58924e25d32b8002eb682e43aa0) Reviewed-on: https://git-master.nvidia.com/r/c/linux-5.9/+/2353303 Reviewed-by: automaticguardword <automaticguardword@nvidia.com> Reviewed-by: Bitan Biswas <bbiswas@nvidia.com> Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com> Tested-by: mobile promotions <svcmobile_promotions@nvidia.com> GVS: Gerrit_Virtual_Submit
This commit is contained in:
@@ -1,22 +1,9 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
/*
|
/*
|
||||||
* tegra210_adsp_alt.c - Tegra ADSP audio driver
|
* tegra210_adsp.c - Tegra ADSP audio driver
|
||||||
*
|
*
|
||||||
* Author: Sumit Bhattacharya <sumitb@nvidia.com>
|
* Author: Sumit Bhattacharya <sumitb@nvidia.com>
|
||||||
* Copyright (c) 2014-2019, NVIDIA CORPORATION. All rights reserved.
|
* Copyright (c) 2014-2020 NVIDIA CORPORATION. All rights reserved.
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License
|
|
||||||
* version 2 as published by the Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but
|
|
||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
|
||||||
* 02110-1301 USA
|
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -32,13 +19,11 @@
|
|||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
#include <linux/dma-mapping.h>
|
#include <linux/dma-mapping.h>
|
||||||
#include <linux/pm_runtime.h>
|
#include <linux/pm_runtime.h>
|
||||||
#include <linux/tegra_pm_domains.h>
|
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
#include <linux/firmware.h>
|
#include <linux/firmware.h>
|
||||||
#include <linux/kthread.h>
|
#include <linux/kthread.h>
|
||||||
#include <linux/tegra_nvadsp.h>
|
#include <linux/tegra_nvadsp.h>
|
||||||
#include <linux/irqchip/tegra-agic.h>
|
|
||||||
#include <linux/of_device.h>
|
#include <linux/of_device.h>
|
||||||
|
|
||||||
#include <net/sock.h>
|
#include <net/sock.h>
|
||||||
@@ -49,18 +34,18 @@
|
|||||||
#include <sound/core.h>
|
#include <sound/core.h>
|
||||||
#include <sound/pcm_params.h>
|
#include <sound/pcm_params.h>
|
||||||
#include <sound/soc.h>
|
#include <sound/soc.h>
|
||||||
#include <soc/tegra/chip-id.h>
|
#include <soc/tegra/fuse.h>
|
||||||
#include <sound/compress_driver.h>
|
#include <sound/compress_driver.h>
|
||||||
#include <sound/dmaengine_pcm.h>
|
#include <sound/dmaengine_pcm.h>
|
||||||
#include <sound/tegra_nvfx.h>
|
#include <sound/tegra_nvfx.h>
|
||||||
#include <sound/tegra_nvfx_apm.h>
|
#include <sound/tegra_nvfx_apm.h>
|
||||||
#include <sound/tegra_nvfx_plugin.h>
|
#include <sound/tegra_nvfx_plugin.h>
|
||||||
#include "tegra_isomgr_bw_alt.h"
|
#include "tegra_isomgr_bw.h"
|
||||||
|
|
||||||
#include "tegra_asoc_utils_alt.h"
|
#include "tegra_asoc_utils.h"
|
||||||
#include "tegra210_adsp_alt.h"
|
#include "tegra210_adsp.h"
|
||||||
|
|
||||||
#define DRV_NAME_ADSP "tegra210-adsp"
|
#define DRV_NAME "tegra210-adsp"
|
||||||
|
|
||||||
/* Flag to enable/disable loading of ADSP firmware */
|
/* Flag to enable/disable loading of ADSP firmware */
|
||||||
#define ENABLE_ADSP 1
|
#define ENABLE_ADSP 1
|
||||||
@@ -127,7 +112,11 @@ struct tegra210_adsp_app {
|
|||||||
uint32_t reg;
|
uint32_t reg;
|
||||||
uint32_t adma_chan; /* Valid for only ADMA app */
|
uint32_t adma_chan; /* Valid for only ADMA app */
|
||||||
uint32_t fe:1; /* Whether the app is used as a FE APM */
|
uint32_t fe:1; /* Whether the app is used as a FE APM */
|
||||||
uint32_t fe_playback_triggered:1; /* if app is playback FE, indicates whether in triggered state or inactive */
|
/*
|
||||||
|
* if app is playback FE, indicates whether in triggered state
|
||||||
|
* or inactive
|
||||||
|
*/
|
||||||
|
uint32_t fe_playback_triggered:1;
|
||||||
uint32_t connect:1; /* if app is connected to a source */
|
uint32_t connect:1; /* if app is connected to a source */
|
||||||
uint32_t priority; /* Valid for only APM app */
|
uint32_t priority; /* Valid for only APM app */
|
||||||
uint32_t min_adsp_clock; /* Min ADSP clock required in MHz */
|
uint32_t min_adsp_clock; /* Min ADSP clock required in MHz */
|
||||||
@@ -136,7 +125,7 @@ struct tegra210_adsp_app {
|
|||||||
struct tegra210_adsp_app_read_data read_data;
|
struct tegra210_adsp_app_read_data read_data;
|
||||||
spinlock_t lock;
|
spinlock_t lock;
|
||||||
void *private_data;
|
void *private_data;
|
||||||
int (*msg_handler)(struct tegra210_adsp_app *, apm_msg_t *);
|
int (*msg_handler)(struct tegra210_adsp_app *app, apm_msg_t *msg);
|
||||||
struct work_struct *override_freq_work;
|
struct work_struct *override_freq_work;
|
||||||
spinlock_t apm_msg_queue_lock;
|
spinlock_t apm_msg_queue_lock;
|
||||||
};
|
};
|
||||||
@@ -482,6 +471,7 @@ static int tegra210_adsp_send_msg(struct tegra210_adsp_app *app,
|
|||||||
|
|
||||||
if (!IS_APM_IN(app->reg)) {
|
if (!IS_APM_IN(app->reg)) {
|
||||||
uint32_t source;
|
uint32_t source;
|
||||||
|
|
||||||
while (IS_ADSP_APP(app->reg) && !IS_APM_IN(app->reg)) {
|
while (IS_ADSP_APP(app->reg) && !IS_APM_IN(app->reg)) {
|
||||||
source = tegra210_adsp_get_source(app->adsp, app->reg);
|
source = tegra210_adsp_get_source(app->adsp, app->reg);
|
||||||
app = &app->adsp->apps[source];
|
app = &app->adsp->apps[source];
|
||||||
@@ -555,6 +545,7 @@ static int tegra210_adsp_send_raw_data_msg(struct tegra210_adsp_app *app,
|
|||||||
/* 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)) {
|
||||||
uint32_t source;
|
uint32_t source;
|
||||||
|
|
||||||
while (IS_ADSP_APP(apm->reg) && !IS_APM_IN(apm->reg)) {
|
while (IS_ADSP_APP(apm->reg) && !IS_APM_IN(apm->reg)) {
|
||||||
source = tegra210_adsp_get_source(apm->adsp, apm->reg);
|
source = tegra210_adsp_get_source(apm->adsp, apm->reg);
|
||||||
apm = &apm->adsp->apps[source];
|
apm = &apm->adsp->apps[source];
|
||||||
@@ -793,7 +784,8 @@ static int tegra210_adsp_send_data_request_msg(struct tegra210_adsp_app *app,
|
|||||||
apm_msg.msgq_msg.size = MSGQ_MSG_WSIZE(apm_fx_read_request_params_t);
|
apm_msg.msgq_msg.size = MSGQ_MSG_WSIZE(apm_fx_read_request_params_t);
|
||||||
apm_msg.msg.call_params.size = sizeof(apm_fx_read_request_params_t);
|
apm_msg.msg.call_params.size = sizeof(apm_fx_read_request_params_t);
|
||||||
apm_msg.msg.call_params.method = nvfx_apm_method_read_data;
|
apm_msg.msg.call_params.method = nvfx_apm_method_read_data;
|
||||||
apm_msg.msg.fx_read_request_params.plugin.pvoid = app->plugin->plugin.pvoid;
|
apm_msg.msg.fx_read_request_params.plugin.pvoid =
|
||||||
|
app->plugin->plugin.pvoid;
|
||||||
apm_msg.msg.fx_read_request_params.req_size = size;
|
apm_msg.msg.fx_read_request_params.req_size = size;
|
||||||
|
|
||||||
return tegra210_adsp_send_msg(app, &apm_msg, flags);
|
return tegra210_adsp_send_msg(app, &apm_msg, flags);
|
||||||
@@ -835,9 +827,9 @@ static int tegra210_adsp_app_init(struct tegra210_adsp *adsp,
|
|||||||
if (app->info || IS_APM_OUT(app->reg))
|
if (app->info || IS_APM_OUT(app->reg))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (!app->desc->handle) {
|
if (!app->desc->handle)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
|
||||||
app->info = nvadsp_app_init(app->desc->handle, NULL);
|
app->info = nvadsp_app_init(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).",
|
||||||
@@ -873,10 +865,8 @@ static int tegra210_adsp_app_init(struct tegra210_adsp *adsp,
|
|||||||
|
|
||||||
app->msg_complete = devm_kzalloc(adsp->dev,
|
app->msg_complete = devm_kzalloc(adsp->dev,
|
||||||
sizeof(struct completion), GFP_KERNEL);
|
sizeof(struct completion), GFP_KERNEL);
|
||||||
if (!app->msg_complete) {
|
if (!app->msg_complete)
|
||||||
dev_err(adsp->dev, "Failed to allocate completion struct.");
|
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
|
||||||
|
|
||||||
app->raw_msg_read_complete = devm_kzalloc(adsp->dev,
|
app->raw_msg_read_complete = devm_kzalloc(adsp->dev,
|
||||||
sizeof(struct completion), GFP_KERNEL);
|
sizeof(struct completion), GFP_KERNEL);
|
||||||
@@ -904,8 +894,8 @@ static int tegra210_adsp_app_init(struct tegra210_adsp *adsp,
|
|||||||
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;
|
||||||
}
|
}
|
||||||
dev_info(adsp->dev, "apm start app %d msg_q 0x%p\n"
|
dev_info(adsp->dev, "apm start app %d msg_q 0x%p\n",
|
||||||
,app->apm->mbox_id, &app->apm->msgq_recv.msgq);
|
app->apm->mbox_id, &app->apm->msgq_recv.msgq);
|
||||||
/* Copy APM IN app data to APM OUT app */
|
/* Copy APM IN app data to APM OUT app */
|
||||||
apm_out->info = app->info;
|
apm_out->info = app->info;
|
||||||
apm_out->plugin = app->plugin;
|
apm_out->plugin = app->plugin;
|
||||||
@@ -955,7 +945,6 @@ static void tegra210_adsp_app_deinit(struct tegra210_adsp *adsp,
|
|||||||
* everytime. Add app deinit functionality properly if needed in
|
* everytime. Add app deinit functionality properly if needed in
|
||||||
* future.
|
* future.
|
||||||
*/
|
*/
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* API to connect two APMs */
|
/* API to connect two APMs */
|
||||||
@@ -966,8 +955,7 @@ static int tegra210_adsp_connect_apm(struct tegra210_adsp *adsp,
|
|||||||
struct tegra210_adsp_app *src = &adsp->apps[source];
|
struct tegra210_adsp_app *src = &adsp->apps[source];
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
/* If both APMs are in connected state no need to
|
// If both APMs are in connected state no need to send connect message
|
||||||
send connect message */
|
|
||||||
if (app->connect && src->connect)
|
if (app->connect && src->connect)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@@ -983,8 +971,10 @@ static int tegra210_adsp_connect_apm(struct tegra210_adsp *adsp,
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Recursive function to connect plugins under a APM
|
/*
|
||||||
Returns BE/FE on the pcm path */
|
* Recursive function to connect plugins under a APM.
|
||||||
|
* Returns BE/FE on the pcm path
|
||||||
|
*/
|
||||||
static int tegra210_adsp_connect_plugin(struct tegra210_adsp *adsp,
|
static int tegra210_adsp_connect_plugin(struct tegra210_adsp *adsp,
|
||||||
struct tegra210_adsp_app *app,
|
struct tegra210_adsp_app *app,
|
||||||
uint32_t *apm_in_src)
|
uint32_t *apm_in_src)
|
||||||
@@ -1015,8 +1005,7 @@ static int tegra210_adsp_connect_plugin(struct tegra210_adsp *adsp,
|
|||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
} else {
|
} else {
|
||||||
/* return if APM_IN is not
|
/* return if APM_IN is not connected to valid inputs */
|
||||||
connected to valid inputs */
|
|
||||||
if (!IS_ADSP_FE(source) &&
|
if (!IS_ADSP_FE(source) &&
|
||||||
!IS_ADSP_ADMAIF(source))
|
!IS_ADSP_ADMAIF(source))
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
@@ -1027,8 +1016,10 @@ static int tegra210_adsp_connect_plugin(struct tegra210_adsp *adsp,
|
|||||||
app->apm = src->apm;
|
app->apm = src->apm;
|
||||||
app->apm_mbox = src->apm_mbox;
|
app->apm_mbox = src->apm_mbox;
|
||||||
|
|
||||||
/* If App is already connected and source connections have not changed
|
/*
|
||||||
no need to again send connect message */
|
* If App is already connected and source connections have not changed,
|
||||||
|
* no need to again send connect message
|
||||||
|
*/
|
||||||
if (!ret && app->connect)
|
if (!ret && app->connect)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@@ -1049,7 +1040,8 @@ static int tegra210_adsp_connect_plugin(struct tegra210_adsp *adsp,
|
|||||||
|
|
||||||
/* Manages FE/BE plugins and deletes if fe_apm is specified */
|
/* Manages FE/BE plugins and deletes if fe_apm is specified */
|
||||||
static void tegra210_adsp_manage_plugin(struct tegra210_adsp *adsp,
|
static void tegra210_adsp_manage_plugin(struct tegra210_adsp *adsp,
|
||||||
uint32_t end_reg, uint32_t apm_out, struct tegra210_adsp_app *fe_apm)
|
uint32_t end_reg, uint32_t apm_out,
|
||||||
|
struct tegra210_adsp_app *fe_apm)
|
||||||
{
|
{
|
||||||
uint32_t j, fe_reg, be_reg;
|
uint32_t j, fe_reg, be_reg;
|
||||||
|
|
||||||
@@ -1113,7 +1105,8 @@ static int tegra210_adsp_update_connection(struct tegra210_adsp *adsp)
|
|||||||
uint32_t end_reg;
|
uint32_t end_reg;
|
||||||
|
|
||||||
for (i = APM_OUT_START; i <= APM_OUT_END; i++) {
|
for (i = APM_OUT_START; i <= APM_OUT_END; i++) {
|
||||||
ret = tegra210_adsp_connect_plugin(adsp, &adsp->apps[i], &end_reg);
|
ret = tegra210_adsp_connect_plugin(adsp, &adsp->apps[i],
|
||||||
|
&end_reg);
|
||||||
if (ret >= 0) {
|
if (ret >= 0) {
|
||||||
/* Record FE/BE pair for every successful connection */
|
/* Record FE/BE pair for every successful connection */
|
||||||
tegra210_adsp_manage_plugin(adsp, end_reg, i, NULL);
|
tegra210_adsp_manage_plugin(adsp, end_reg, i, NULL);
|
||||||
@@ -1180,8 +1173,6 @@ static void tegra210_adsp_nl_recv_msg(struct sk_buff *skb)
|
|||||||
|
|
||||||
nlh = (struct nlmsghdr *)skb->data;
|
nlh = (struct nlmsghdr *)skb->data;
|
||||||
pr_info("Established client: %d\n", nlh->nlmsg_pid);
|
pr_info("Established client: %d\n", nlh->nlmsg_pid);
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tegra210_adsp_nl_send_msg(struct tegra210_adsp *adsp,
|
static void tegra210_adsp_nl_send_msg(struct tegra210_adsp *adsp,
|
||||||
@@ -1204,8 +1195,11 @@ static void tegra210_adsp_nl_send_msg(struct tegra210_adsp *adsp,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
nlh = nlmsg_put(skb, 0, 0, NLMSG_DONE, sizeof(struct adsp_event_nlmsg), 0);
|
nlh = nlmsg_put(skb, 0, 0, NLMSG_DONE, sizeof(struct adsp_event_nlmsg),
|
||||||
NETLINK_CB(skb).dst_group = NETLINK_ADSP_EVENT_GROUP; /* to mcast group 1<<0 */
|
0);
|
||||||
|
|
||||||
|
/* to mcast group 1<<0 */
|
||||||
|
NETLINK_CB(skb).dst_group = NETLINK_ADSP_EVENT_GROUP;
|
||||||
|
|
||||||
msg = (struct adsp_event_nlmsg *)nlmsg_data(nlh);
|
msg = (struct adsp_event_nlmsg *)nlmsg_data(nlh);
|
||||||
msg->err = apm_err_msg->err;
|
msg->err = apm_err_msg->err;
|
||||||
@@ -1215,8 +1209,6 @@ static void tegra210_adsp_nl_send_msg(struct tegra210_adsp *adsp,
|
|||||||
res = nlmsg_multicast(adsp->nl_sk, skb, 0, NETLINK_ADSP_EVENT_GROUP, 0);
|
res = nlmsg_multicast(adsp->nl_sk, skb, 0, NETLINK_ADSP_EVENT_GROUP, 0);
|
||||||
if (res < 0)
|
if (res < 0)
|
||||||
pr_err("Error while sending back to user: %d\n", res);
|
pr_err("Error while sending back to user: %d\n", res);
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ADSP mailbox message handler */
|
/* ADSP mailbox message handler */
|
||||||
@@ -1326,7 +1318,8 @@ static int tegra210_adsp_pcm_msg_handler(struct tegra210_adsp_app *app,
|
|||||||
if ((IS_MMAP_ACCESS(runtime->access))) {
|
if ((IS_MMAP_ACCESS(runtime->access))) {
|
||||||
if (prtd->prev_appl_ptr !=
|
if (prtd->prev_appl_ptr !=
|
||||||
runtime->control->appl_ptr) {
|
runtime->control->appl_ptr) {
|
||||||
prtd->prev_appl_ptr = runtime->control->appl_ptr;
|
prtd->prev_appl_ptr =
|
||||||
|
runtime->control->appl_ptr;
|
||||||
tegra210_adsp_pcm_ack(prtd->substream);
|
tegra210_adsp_pcm_ack(prtd->substream);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1354,9 +1347,8 @@ static int tegra210_adsp_compr_msg_handler(struct tegra210_adsp_app *app,
|
|||||||
{
|
{
|
||||||
struct tegra210_adsp_compr_rtd *prtd = app->private_data;
|
struct tegra210_adsp_compr_rtd *prtd = app->private_data;
|
||||||
|
|
||||||
if (!prtd) {
|
if (!prtd)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
|
|
||||||
switch (apm_msg->msg.call_params.method) {
|
switch (apm_msg->msg.call_params.method) {
|
||||||
case nvfx_apm_method_set_position:
|
case nvfx_apm_method_set_position:
|
||||||
@@ -1388,8 +1380,8 @@ static int tegra210_adsp_compr_msg_handler(struct tegra210_adsp_app *app,
|
|||||||
static int tegra210_adsp_compr_open(struct snd_compr_stream *cstream)
|
static int tegra210_adsp_compr_open(struct snd_compr_stream *cstream)
|
||||||
{
|
{
|
||||||
struct snd_soc_pcm_runtime *rtd = cstream->device->private_data;
|
struct snd_soc_pcm_runtime *rtd = cstream->device->private_data;
|
||||||
struct tegra210_adsp *adsp =
|
struct snd_soc_component *cmpnt = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
|
||||||
snd_soc_platform_get_drvdata(rtd->platform);
|
struct tegra210_adsp *adsp = snd_soc_component_get_drvdata(cmpnt);
|
||||||
struct tegra210_adsp_compr_rtd *prtd;
|
struct tegra210_adsp_compr_rtd *prtd;
|
||||||
uint32_t fe_reg = rtd->codec_dai->id + 1;
|
uint32_t fe_reg = rtd->codec_dai->id + 1;
|
||||||
int ret;
|
int ret;
|
||||||
@@ -1402,16 +1394,15 @@ static int tegra210_adsp_compr_open(struct snd_compr_stream *cstream)
|
|||||||
|
|
||||||
if (!adsp->pcm_path[fe_reg][cstream->direction].fe_reg ||
|
if (!adsp->pcm_path[fe_reg][cstream->direction].fe_reg ||
|
||||||
!adsp->pcm_path[fe_reg][cstream->direction].be_reg) {
|
!adsp->pcm_path[fe_reg][cstream->direction].be_reg) {
|
||||||
dev_err(adsp->dev, "Broken Path%d - FE not linked to BE", fe_reg);
|
dev_err(adsp->dev, "Broken Path%d - FE not linked to BE",
|
||||||
|
fe_reg);
|
||||||
return -EPIPE;
|
return -EPIPE;
|
||||||
}
|
}
|
||||||
|
|
||||||
prtd = devm_kzalloc(adsp->dev, sizeof(struct tegra210_adsp_compr_rtd),
|
prtd = devm_kzalloc(adsp->dev, sizeof(struct tegra210_adsp_compr_rtd),
|
||||||
GFP_KERNEL);
|
GFP_KERNEL);
|
||||||
if (!prtd) {
|
if (!prtd)
|
||||||
dev_err(adsp->dev, "Failed to allocate adsp rtd.");
|
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
|
||||||
|
|
||||||
/* Find out the APM connected with ADSP-FE DAI */
|
/* Find out the APM connected with ADSP-FE DAI */
|
||||||
for (i = APM_IN_START; i <= APM_IN_END; i++) {
|
for (i = APM_IN_START; i <= APM_IN_END; i++) {
|
||||||
@@ -1700,7 +1691,6 @@ static int tegra210_adsp_compr_codec_caps(struct snd_compr_stream *cstream,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static struct snd_compr_ops tegra210_adsp_compr_ops = {
|
static struct snd_compr_ops tegra210_adsp_compr_ops = {
|
||||||
|
|
||||||
.open = tegra210_adsp_compr_open,
|
.open = tegra210_adsp_compr_open,
|
||||||
.free = tegra210_adsp_compr_free,
|
.free = tegra210_adsp_compr_free,
|
||||||
.set_params = tegra210_adsp_compr_set_params,
|
.set_params = tegra210_adsp_compr_set_params,
|
||||||
@@ -1716,8 +1706,8 @@ static struct snd_compr_ops tegra210_adsp_compr_ops = {
|
|||||||
static int tegra210_adsp_pcm_open(struct snd_pcm_substream *substream)
|
static int tegra210_adsp_pcm_open(struct snd_pcm_substream *substream)
|
||||||
{
|
{
|
||||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||||
struct tegra210_adsp *adsp =
|
struct snd_soc_component *cmpnt = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
|
||||||
snd_soc_platform_get_drvdata(rtd->platform);
|
struct tegra210_adsp *adsp = snd_soc_component_get_drvdata(cmpnt);
|
||||||
struct tegra210_adsp_pcm_rtd *prtd;
|
struct tegra210_adsp_pcm_rtd *prtd;
|
||||||
uint32_t fe_reg = rtd->codec_dai->id + 1;
|
uint32_t fe_reg = rtd->codec_dai->id + 1;
|
||||||
uint32_t source;
|
uint32_t source;
|
||||||
@@ -1727,16 +1717,15 @@ static int tegra210_adsp_pcm_open(struct snd_pcm_substream *substream)
|
|||||||
|
|
||||||
if (!adsp->pcm_path[fe_reg][substream->stream].fe_reg ||
|
if (!adsp->pcm_path[fe_reg][substream->stream].fe_reg ||
|
||||||
!adsp->pcm_path[fe_reg][substream->stream].be_reg) {
|
!adsp->pcm_path[fe_reg][substream->stream].be_reg) {
|
||||||
dev_err(adsp->dev, "Broken Path%d - FE not linked to BE", fe_reg);
|
dev_err(adsp->dev, "Broken Path%d - FE not linked to BE",
|
||||||
|
fe_reg);
|
||||||
return -EPIPE;
|
return -EPIPE;
|
||||||
}
|
}
|
||||||
|
|
||||||
prtd = devm_kzalloc(adsp->dev, sizeof(struct tegra210_adsp_pcm_rtd),
|
prtd = devm_kzalloc(adsp->dev, sizeof(struct tegra210_adsp_pcm_rtd),
|
||||||
GFP_KERNEL);
|
GFP_KERNEL);
|
||||||
if (!prtd) {
|
if (!prtd)
|
||||||
dev_err(adsp->dev, "Failed to allocate adsp rtd.");
|
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
|
||||||
|
|
||||||
/* Find out the APM connected with ADSP-FE DAI */
|
/* Find out the APM connected with ADSP-FE DAI */
|
||||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||||
@@ -2066,7 +2055,6 @@ static int tegra210_adsp_fe_hw_params(struct snd_pcm_substream *substream,
|
|||||||
struct snd_pcm_hw_params *params,
|
struct snd_pcm_hw_params *params,
|
||||||
struct snd_soc_dai *dai)
|
struct snd_soc_dai *dai)
|
||||||
{
|
{
|
||||||
|
|
||||||
struct tegra210_adsp *adsp = snd_soc_dai_get_drvdata(dai);
|
struct tegra210_adsp *adsp = snd_soc_dai_get_drvdata(dai);
|
||||||
uint32_t fe_reg = dai->id + 1;
|
uint32_t fe_reg = dai->id + 1;
|
||||||
|
|
||||||
@@ -2090,10 +2078,10 @@ static int tegra210_adsp_fe_hw_params(struct snd_pcm_substream *substream,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int tegra210_adsp_null_sink_hw_params(struct snd_soc_dapm_widget *w,
|
static int tegra210_adsp_null_sink_hw_params(struct snd_soc_dapm_widget *w,
|
||||||
struct snd_kcontrol *kcontrol, int event) {
|
struct snd_kcontrol *kcontrol, int event)
|
||||||
|
{
|
||||||
struct snd_soc_platform *platform = snd_soc_dapm_to_platform(w->dapm);
|
struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
|
||||||
struct tegra210_adsp *adsp = snd_soc_platform_get_drvdata(platform);
|
struct tegra210_adsp *adsp = snd_soc_component_get_drvdata(cmpnt);
|
||||||
struct tegra210_adsp_app *app;
|
struct tegra210_adsp_app *app;
|
||||||
nvfx_adma_init_params_t adma_params;
|
nvfx_adma_init_params_t adma_params;
|
||||||
struct tegra210_adsp_pcm_rtd *prtd = NULL;
|
struct tegra210_adsp_pcm_rtd *prtd = NULL;
|
||||||
@@ -2384,8 +2372,10 @@ static int tegra210_adsp_runtime_suspend(struct device *dev)
|
|||||||
/* Check for msgq empty before suspend */
|
/* Check for msgq empty before suspend */
|
||||||
for (i = 0; i < TEGRA210_ADSP_VIRT_REG_MAX; i++) {
|
for (i = 0; i < TEGRA210_ADSP_VIRT_REG_MAX; i++) {
|
||||||
struct tegra210_adsp_app *app = &adsp->apps[i];
|
struct tegra210_adsp_app *app = &adsp->apps[i];
|
||||||
|
|
||||||
if (app->plugin && IS_APM_IN(app->reg)) {
|
if (app->plugin && IS_APM_IN(app->reg)) {
|
||||||
msgq_t *msgq = &app->apm->msgq_recv.msgq;
|
msgq_t *msgq = &app->apm->msgq_recv.msgq;
|
||||||
|
|
||||||
if (msgq->read_index == msgq->write_index)
|
if (msgq->read_index == msgq->write_index)
|
||||||
continue;
|
continue;
|
||||||
pr_err("%s: app %d, msgq not empty rd %d wr %d\n",
|
pr_err("%s: app %d, msgq not empty rd %d wr %d\n",
|
||||||
@@ -2400,7 +2390,7 @@ static int tegra210_adsp_runtime_suspend(struct device *dev)
|
|||||||
|
|
||||||
adsp->adsp_started = 0;
|
adsp->adsp_started = 0;
|
||||||
|
|
||||||
if (!(tegra_platform_is_unit_fpga() || tegra_platform_is_fpga())) {
|
if (!tegra_platform_is_fpga()) {
|
||||||
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,7 +2413,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_unit_fpga() || tegra_platform_is_fpga())) {
|
if (!tegra_platform_is_fpga()) {
|
||||||
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);
|
||||||
@@ -2461,31 +2451,27 @@ exit:
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* ADSP platform driver read/write call-back */
|
/* ADSP platform driver read/write call-back */
|
||||||
static int tegra210_adsp_read(struct snd_soc_component *component,
|
static unsigned int tegra210_adsp_read(struct snd_soc_component *component,
|
||||||
unsigned int reg, unsigned int *val)
|
unsigned int reg)
|
||||||
{
|
{
|
||||||
struct snd_soc_platform *platform =
|
struct tegra210_adsp *adsp = snd_soc_component_get_drvdata(component);
|
||||||
snd_soc_component_to_platform(component);
|
|
||||||
struct tegra210_adsp *adsp = snd_soc_platform_get_drvdata(platform);
|
|
||||||
|
|
||||||
dev_vdbg(adsp->dev, "%s [0x%x] -> 0x%x\n", __func__, reg,
|
dev_vdbg(adsp->dev, "%s [0x%x] -> 0x%x\n", __func__, reg,
|
||||||
tegra210_adsp_reg_read(adsp, reg));
|
tegra210_adsp_reg_read(adsp, reg));
|
||||||
|
|
||||||
*val = tegra210_adsp_reg_read(adsp, reg);
|
return tegra210_adsp_reg_read(adsp, reg);
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int tegra210_adsp_write(struct snd_soc_component *component,
|
static int tegra210_adsp_write(struct snd_soc_component *component,
|
||||||
unsigned int reg,
|
unsigned int reg,
|
||||||
unsigned int val)
|
unsigned int val)
|
||||||
{
|
{
|
||||||
struct snd_soc_platform *platform =
|
struct tegra210_adsp *adsp = snd_soc_component_get_drvdata(component);
|
||||||
snd_soc_component_to_platform(component);
|
|
||||||
struct tegra210_adsp *adsp = snd_soc_platform_get_drvdata(platform);
|
|
||||||
|
|
||||||
dev_vdbg(adsp->dev, "%s [0x%x] -> 0x%x\n", __func__, reg, val);
|
dev_vdbg(adsp->dev, "%s [0x%x] -> 0x%x\n", __func__, reg, val);
|
||||||
|
|
||||||
tegra210_adsp_reg_write(adsp, reg, val);
|
tegra210_adsp_reg_write(adsp, reg, val);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2495,10 +2481,10 @@ static int tegra210_adsp_mux_get(struct snd_kcontrol *kcontrol,
|
|||||||
{
|
{
|
||||||
struct snd_soc_dapm_context *dapm =
|
struct snd_soc_dapm_context *dapm =
|
||||||
snd_soc_dapm_kcontrol_dapm(kcontrol);
|
snd_soc_dapm_kcontrol_dapm(kcontrol);
|
||||||
struct snd_soc_platform *platform = snd_soc_dapm_to_platform(dapm);
|
struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(dapm);
|
||||||
struct soc_enum *e =
|
struct soc_enum *e =
|
||||||
(struct soc_enum *)kcontrol->private_value;
|
(struct soc_enum *)kcontrol->private_value;
|
||||||
struct tegra210_adsp *adsp = snd_soc_platform_get_drvdata(platform);
|
struct tegra210_adsp *adsp = snd_soc_component_get_drvdata(cmpnt);
|
||||||
uint32_t val = tegra210_adsp_reg_read(adsp, e->reg);
|
uint32_t val = tegra210_adsp_reg_read(adsp, e->reg);
|
||||||
|
|
||||||
ucontrol->value.integer.value[0] =
|
ucontrol->value.integer.value[0] =
|
||||||
@@ -2511,10 +2497,10 @@ static int tegra210_adsp_mux_put(struct snd_kcontrol *kcontrol,
|
|||||||
{
|
{
|
||||||
struct snd_soc_dapm_context *dapm =
|
struct snd_soc_dapm_context *dapm =
|
||||||
snd_soc_dapm_kcontrol_dapm(kcontrol);
|
snd_soc_dapm_kcontrol_dapm(kcontrol);
|
||||||
struct snd_soc_platform *platform = snd_soc_dapm_to_platform(dapm);
|
struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(dapm);
|
||||||
uint32_t val = ucontrol->value.enumerated.item[0];
|
uint32_t val = ucontrol->value.enumerated.item[0];
|
||||||
struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
|
struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
|
||||||
struct tegra210_adsp *adsp = snd_soc_platform_get_drvdata(platform);
|
struct tegra210_adsp *adsp = snd_soc_component_get_drvdata(cmpnt);
|
||||||
struct tegra210_adsp_app *app;
|
struct tegra210_adsp_app *app;
|
||||||
uint32_t cur_val = 0;
|
uint32_t cur_val = 0;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
@@ -2615,10 +2601,11 @@ static int tegra210_adsp_init_put(struct snd_kcontrol *kcontrol,
|
|||||||
* handled by fe_widget_event() in SND_SOC_DAPM_POST_PMD event handling
|
* handled by fe_widget_event() in SND_SOC_DAPM_POST_PMD event handling
|
||||||
*/
|
*/
|
||||||
static int tegra210_adsp_fe_widget_event(struct snd_soc_dapm_widget *w,
|
static int tegra210_adsp_fe_widget_event(struct snd_soc_dapm_widget *w,
|
||||||
struct snd_kcontrol *kcontrol, int event)
|
struct snd_kcontrol *kcontrol,
|
||||||
|
int event)
|
||||||
{
|
{
|
||||||
struct snd_soc_platform *platform = snd_soc_dapm_to_platform(w->dapm);
|
struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
|
||||||
struct tegra210_adsp *adsp = snd_soc_platform_get_drvdata(platform);
|
struct tegra210_adsp *adsp = snd_soc_component_get_drvdata(cmpnt);
|
||||||
struct tegra210_adsp_app *apm;
|
struct tegra210_adsp_app *apm;
|
||||||
struct device *dev = adsp->dev;
|
struct device *dev = adsp->dev;
|
||||||
struct device_node *node = dev->of_node;
|
struct device_node *node = dev->of_node;
|
||||||
@@ -2669,10 +2656,11 @@ static int tegra210_adsp_fe_widget_event(struct snd_soc_dapm_widget *w,
|
|||||||
(i + 1) - APM_IN_START, w->reg);
|
(i + 1) - APM_IN_START, w->reg);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* For trigger playback, pcm_trigger calls will handle ivc and adsp messages
|
* For trigger playback, pcm_trigger calls will handle ivc and
|
||||||
|
* adsp messages.
|
||||||
*
|
*
|
||||||
* When ADSP FE is in triggered state, path disconnect and connect is done,
|
* When ADSP FE is in triggered state, path disconnect and
|
||||||
* widget event will send IVC and ADSP messages
|
* connect is done, widget event will send IVC and ADSP messages
|
||||||
*/
|
*/
|
||||||
if (!apm->fe_playback_triggered) {
|
if (!apm->fe_playback_triggered) {
|
||||||
ret = 0;
|
ret = 0;
|
||||||
@@ -2730,8 +2718,8 @@ err_put:
|
|||||||
static int tegra210_adsp_widget_event(struct snd_soc_dapm_widget *w,
|
static int tegra210_adsp_widget_event(struct snd_soc_dapm_widget *w,
|
||||||
struct snd_kcontrol *kcontrol, int event)
|
struct snd_kcontrol *kcontrol, int event)
|
||||||
{
|
{
|
||||||
struct snd_soc_platform *platform = snd_soc_dapm_to_platform(w->dapm);
|
struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
|
||||||
struct tegra210_adsp *adsp = snd_soc_platform_get_drvdata(platform);
|
struct tegra210_adsp *adsp = snd_soc_component_get_drvdata(cmpnt);
|
||||||
struct tegra210_adsp_app *app;
|
struct tegra210_adsp_app *app;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
@@ -2745,8 +2733,10 @@ static int tegra210_adsp_widget_event(struct snd_soc_dapm_widget *w,
|
|||||||
|
|
||||||
if (SND_SOC_DAPM_EVENT_ON(event)) {
|
if (SND_SOC_DAPM_EVENT_ON(event)) {
|
||||||
if (IS_APM_IN(w->reg)) {
|
if (IS_APM_IN(w->reg)) {
|
||||||
/* Request higher ADSP clock when starting stream.
|
/*
|
||||||
* Actmon takes care of adjusting frequency later. */
|
* Request higher ADSP clock when starting stream.
|
||||||
|
* Actmon takes care of adjusting frequency later.
|
||||||
|
*/
|
||||||
ret = pm_runtime_get_sync(adsp->dev);
|
ret = pm_runtime_get_sync(adsp->dev);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
dev_err(adsp->dev, "%s pm_runtime_get_sync error 0x%x\n",
|
dev_err(adsp->dev, "%s pm_runtime_get_sync error 0x%x\n",
|
||||||
@@ -2756,8 +2746,8 @@ static int tegra210_adsp_widget_event(struct snd_soc_dapm_widget *w,
|
|||||||
if (app->min_adsp_clock)
|
if (app->min_adsp_clock)
|
||||||
adsp_update_dfs_min_rate(app->min_adsp_clock * 1000);
|
adsp_update_dfs_min_rate(app->min_adsp_clock * 1000);
|
||||||
|
|
||||||
ret = tegra210_adsp_send_state_msg(app, nvfx_state_active,
|
ret = tegra210_adsp_send_state_msg(app,
|
||||||
TEGRA210_ADSP_MSG_FLAG_SEND);
|
nvfx_state_active, TEGRA210_ADSP_MSG_FLAG_SEND);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
dev_err(adsp->dev, "Failed to set state active.");
|
dev_err(adsp->dev, "Failed to set state active.");
|
||||||
|
|
||||||
@@ -2772,7 +2762,8 @@ static int tegra210_adsp_widget_event(struct snd_soc_dapm_widget *w,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = tegra210_adsp_send_state_msg(app, nvfx_state_inactive,
|
ret = tegra210_adsp_send_state_msg(app,
|
||||||
|
nvfx_state_inactive,
|
||||||
TEGRA210_ADSP_MSG_FLAG_SEND);
|
TEGRA210_ADSP_MSG_FLAG_SEND);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
dev_err(adsp->dev, "Failed to set state inactive.");
|
dev_err(adsp->dev, "Failed to set state inactive.");
|
||||||
@@ -2928,7 +2919,7 @@ static struct snd_soc_dai_ops tegra210_adsp_eavb_dai_ops = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static struct snd_soc_dai_driver tegra210_adsp_codec_dai[] = {
|
static struct snd_soc_dai_driver tegra210_adsp_cmpnt_dai[] = {
|
||||||
ADSP_FE_CODEC_DAI(1),
|
ADSP_FE_CODEC_DAI(1),
|
||||||
ADSP_FE_CODEC_DAI(2),
|
ADSP_FE_CODEC_DAI(2),
|
||||||
ADSP_FE_CODEC_DAI(3),
|
ADSP_FE_CODEC_DAI(3),
|
||||||
@@ -2985,8 +2976,10 @@ static struct snd_soc_dai_driver tegra210_adsp_codec_dai[] = {
|
|||||||
ADSP_EAVB_DAI(),
|
ADSP_EAVB_DAI(),
|
||||||
};
|
};
|
||||||
|
|
||||||
/* This array is linked with tegra210_adsp_virt_regs enum defines. Any thing
|
/*
|
||||||
changed in enum define should be also reflected here and vice-versa */
|
* This array is linked with tegra210_adsp_virt_regs enum defines. Any thing
|
||||||
|
* changed in enum define should be also reflected here and vice-versa
|
||||||
|
*/
|
||||||
static const char *tegra210_adsp_mux_texts[] = {
|
static const char *tegra210_adsp_mux_texts[] = {
|
||||||
"None",
|
"None",
|
||||||
"ADSP-FE1",
|
"ADSP-FE1",
|
||||||
@@ -3269,7 +3262,8 @@ static ADSP_MUX_ENUM_CTRL_DECL(plugin20, TEGRA210_ADSP_PLUGIN20);
|
|||||||
|
|
||||||
#define ADSP_FE_WIDGETS(sname, ename, reg) \
|
#define ADSP_FE_WIDGETS(sname, ename, reg) \
|
||||||
SND_SOC_DAPM_AIF_IN_E(sname " RX", NULL, 0, reg, \
|
SND_SOC_DAPM_AIF_IN_E(sname " RX", NULL, 0, reg, \
|
||||||
TEGRA210_ADSP_WIDGET_EN_SHIFT, 0, tegra210_adsp_fe_widget_event, \
|
TEGRA210_ADSP_WIDGET_EN_SHIFT, 0, \
|
||||||
|
tegra210_adsp_fe_widget_event, \
|
||||||
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), \
|
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), \
|
||||||
SND_SOC_DAPM_AIF_OUT_E(sname " TX", NULL, 0, reg, \
|
SND_SOC_DAPM_AIF_OUT_E(sname " TX", NULL, 0, reg, \
|
||||||
TEGRA210_ADSP_WIDGET_EN_SHIFT, 0, NULL, \
|
TEGRA210_ADSP_WIDGET_EN_SHIFT, 0, NULL, \
|
||||||
@@ -3278,7 +3272,8 @@ static ADSP_MUX_ENUM_CTRL_DECL(plugin20, TEGRA210_ADSP_PLUGIN20);
|
|||||||
|
|
||||||
#define ADSP_WIDGETS(sname, ename, reg) \
|
#define ADSP_WIDGETS(sname, ename, reg) \
|
||||||
SND_SOC_DAPM_AIF_OUT_E(sname " TX", NULL, 0, reg, \
|
SND_SOC_DAPM_AIF_OUT_E(sname " TX", NULL, 0, reg, \
|
||||||
TEGRA210_ADSP_WIDGET_EN_SHIFT, 0, tegra210_adsp_widget_event, \
|
TEGRA210_ADSP_WIDGET_EN_SHIFT, 0, \
|
||||||
|
tegra210_adsp_widget_event, \
|
||||||
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), \
|
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), \
|
||||||
SND_SOC_DAPM_MUX(sname " MUX", SND_SOC_NOPM, 0, 0, &ename##_ctrl)
|
SND_SOC_DAPM_MUX(sname " MUX", SND_SOC_NOPM, 0, 0, &ename##_ctrl)
|
||||||
|
|
||||||
@@ -4012,14 +4007,16 @@ static int tegra210_adsp_tlv_callback(struct snd_kcontrol *kcontrol,
|
|||||||
apm_raw_data_msg_t *apm_msg;
|
apm_raw_data_msg_t *apm_msg;
|
||||||
nvfx_call_params_t *call_params;
|
nvfx_call_params_t *call_params;
|
||||||
|
|
||||||
apm_msg = devm_kzalloc(adsp->dev, sizeof(apm_raw_data_msg_t), GFP_KERNEL);
|
apm_msg = devm_kzalloc(adsp->dev, sizeof(apm_raw_data_msg_t),
|
||||||
|
GFP_KERNEL);
|
||||||
if (!apm_msg) {
|
if (!apm_msg) {
|
||||||
dev_err(adsp->dev, "Failed to allocate memory for message\n");
|
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
apm_msg->msgq_msg.size = MSGQ_MSG_WSIZE(apm_fx_raw_data_params_t);
|
apm_msg->msgq_msg.size =
|
||||||
apm_msg->msg.call_params.size = sizeof(apm_fx_raw_data_params_t);
|
MSGQ_MSG_WSIZE(apm_fx_raw_data_params_t);
|
||||||
|
apm_msg->msg.call_params.size =
|
||||||
|
sizeof(apm_fx_raw_data_params_t);
|
||||||
apm_msg->msg.call_params.method = nvfx_apm_method_write_data;
|
apm_msg->msg.call_params.method = nvfx_apm_method_write_data;
|
||||||
apm_msg->msg.fx_raw_data_params.plugin.pvoid =
|
apm_msg->msg.fx_raw_data_params.plugin.pvoid =
|
||||||
app->plugin->plugin.pvoid;
|
app->plugin->plugin.pvoid;
|
||||||
@@ -4106,15 +4103,15 @@ static int tegra210_adsp_apm_get(struct snd_kcontrol *kcontrol,
|
|||||||
struct tegra210_adsp *adsp = snd_soc_component_get_drvdata(cmpnt);
|
struct tegra210_adsp *adsp = snd_soc_component_get_drvdata(cmpnt);
|
||||||
struct tegra210_adsp_app *app = &adsp->apps[mc->reg];
|
struct tegra210_adsp_app *app = &adsp->apps[mc->reg];
|
||||||
|
|
||||||
if (strstr(kcontrol->id.name, "Priority")) {
|
if (strstr(kcontrol->id.name, "Priority"))
|
||||||
ucontrol->value.integer.value[0] = app->priority;
|
ucontrol->value.integer.value[0] = app->priority;
|
||||||
} else if (strstr(kcontrol->id.name, "Min ADSP Clock")) {
|
else if (strstr(kcontrol->id.name, "Min ADSP Clock"))
|
||||||
ucontrol->value.integer.value[0] = app->min_adsp_clock;
|
ucontrol->value.integer.value[0] = app->min_adsp_clock;
|
||||||
} else if (strstr(kcontrol->id.name, "Input Mode")) {
|
else if (strstr(kcontrol->id.name, "Input Mode"))
|
||||||
ucontrol->value.integer.value[0] = app->input_mode;
|
ucontrol->value.integer.value[0] = app->input_mode;
|
||||||
} else if (strstr(kcontrol->id.name, "Secure Mode")) {
|
else if (strstr(kcontrol->id.name, "Secure Mode"))
|
||||||
ucontrol->value.integer.value[0] = app->secure_mode;
|
ucontrol->value.integer.value[0] = app->secure_mode;
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4221,9 +4218,11 @@ static int tegra210_adsp_apm_put(struct snd_kcontrol *kcontrol,
|
|||||||
SOC_SINGLE_EXT("APM15 " xname, TEGRA210_ADSP_APM_IN15, 0, xmax, 0,\
|
SOC_SINGLE_EXT("APM15 " xname, TEGRA210_ADSP_APM_IN15, 0, xmax, 0,\
|
||||||
tegra210_adsp_apm_get, tegra210_adsp_apm_put)
|
tegra210_adsp_apm_get, tegra210_adsp_apm_put)
|
||||||
|
|
||||||
/* Any new addition of control should be added after PLUGIN controls otherwise
|
/*
|
||||||
|
* Any new addition of control should be added after PLUGIN controls otherwise
|
||||||
* the index of PLUGIN needs to be changed with define PLUGIN_SET_PARAMS_IDX and
|
* the index of PLUGIN needs to be changed with define PLUGIN_SET_PARAMS_IDX and
|
||||||
* PLUGIN_SEND_BYTES_IDX */
|
* PLUGIN_SEND_BYTES_IDX
|
||||||
|
*/
|
||||||
static struct snd_kcontrol_new tegra210_adsp_controls[] = {
|
static struct snd_kcontrol_new tegra210_adsp_controls[] = {
|
||||||
SOC_SINGLE_BOOL_EXT("ADSP init", 0,
|
SOC_SINGLE_BOOL_EXT("ADSP init", 0,
|
||||||
tegra210_adsp_init_get, tegra210_adsp_init_put),
|
tegra210_adsp_init_get, tegra210_adsp_init_put),
|
||||||
@@ -4374,43 +4373,33 @@ static struct snd_kcontrol_new tegra210_adsp_controls[] = {
|
|||||||
APM_CONTROL("Secure Mode", 1),
|
APM_CONTROL("Secure Mode", 1),
|
||||||
};
|
};
|
||||||
|
|
||||||
static int tegra210_adsp_component_probe(struct snd_soc_component *component)
|
static int tegra210_adsp_component_probe(struct snd_soc_component *cmpnt)
|
||||||
{
|
{
|
||||||
component->read = tegra210_adsp_read;
|
struct tegra210_adsp *adsp = dev_get_drvdata(cmpnt->dev);
|
||||||
component->write = tegra210_adsp_write;
|
|
||||||
|
if (!adsp)
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
|
snd_soc_component_set_drvdata(cmpnt, adsp);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct snd_soc_codec_driver tegra210_adsp_codec = {
|
static struct snd_soc_component_driver tegra210_adsp_cmpnt = {
|
||||||
.idle_bias_off = 1,
|
.name = DRV_NAME,
|
||||||
.component_driver = {
|
|
||||||
.name = "tegra210-adsp",
|
|
||||||
.probe = tegra210_adsp_component_probe,
|
|
||||||
.dapm_widgets = tegra210_adsp_widgets,
|
.dapm_widgets = tegra210_adsp_widgets,
|
||||||
.num_dapm_widgets = ARRAY_SIZE(tegra210_adsp_widgets),
|
.num_dapm_widgets = ARRAY_SIZE(tegra210_adsp_widgets),
|
||||||
.dapm_routes = tegra210_adsp_routes,
|
.dapm_routes = tegra210_adsp_routes,
|
||||||
.num_dapm_routes = ARRAY_SIZE(tegra210_adsp_routes),
|
.num_dapm_routes = ARRAY_SIZE(tegra210_adsp_routes),
|
||||||
.controls = tegra210_adsp_controls,
|
.controls = tegra210_adsp_controls,
|
||||||
.num_controls = ARRAY_SIZE(tegra210_adsp_controls),
|
.num_controls = ARRAY_SIZE(tegra210_adsp_controls),
|
||||||
},
|
.probe = tegra210_adsp_component_probe,
|
||||||
};
|
|
||||||
|
|
||||||
static int tegra210_adsp_pcm_probe(struct snd_soc_platform *platform)
|
|
||||||
{
|
|
||||||
struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(&platform->component);
|
|
||||||
dapm->idle_bias_off = 1;
|
|
||||||
platform->component.read = tegra210_adsp_read;
|
|
||||||
platform->component.write = tegra210_adsp_write;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct snd_soc_platform_driver tegra210_adsp_platform = {
|
|
||||||
.ops = &tegra210_adsp_pcm_ops,
|
|
||||||
.compr_ops = &tegra210_adsp_compr_ops,
|
|
||||||
.pcm_new = tegra210_adsp_pcm_new,
|
.pcm_new = tegra210_adsp_pcm_new,
|
||||||
.pcm_free = tegra210_adsp_pcm_free,
|
.pcm_free = tegra210_adsp_pcm_free,
|
||||||
.probe = tegra210_adsp_pcm_probe,
|
.ops = &tegra210_adsp_pcm_ops,
|
||||||
|
.compr_ops = &tegra210_adsp_compr_ops,
|
||||||
|
.read = tegra210_adsp_read,
|
||||||
|
.write = tegra210_adsp_write,
|
||||||
};
|
};
|
||||||
|
|
||||||
static u64 tegra_dma_mask = DMA_BIT_MASK(32);
|
static u64 tegra_dma_mask = DMA_BIT_MASK(32);
|
||||||
@@ -4426,8 +4415,10 @@ static struct adsp_soc_data adsp_soc_data_t186 = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static const struct of_device_id tegra210_adsp_audio_of_match[] = {
|
static const struct of_device_id tegra210_adsp_audio_of_match[] = {
|
||||||
{ .compatible = "nvidia,tegra210-adsp-audio", .data = &adsp_soc_data_t210},
|
{ .compatible = "nvidia,tegra210-adsp-audio",
|
||||||
{ .compatible = "nvidia,tegra186-adsp-audio", .data = &adsp_soc_data_t186},
|
.data = &adsp_soc_data_t210 },
|
||||||
|
{ .compatible = "nvidia,tegra186-adsp-audio",
|
||||||
|
.data = &adsp_soc_data_t186 },
|
||||||
{},
|
{},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -4464,7 +4455,7 @@ static void adsp_control_name_override(struct device *dev, int wt_idx, int i,
|
|||||||
tegra210_adsp_mux_texts[mux_idx] = name;
|
tegra210_adsp_mux_texts[mux_idx] = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int tegra210_adsp_audio_platform_probe(struct platform_device *pdev)
|
static int tegra210_adsp_audio_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct device_node *np = pdev->dev.of_node, *subnp;
|
struct device_node *np = pdev->dev.of_node, *subnp;
|
||||||
const struct of_device_id *match;
|
const struct of_device_id *match;
|
||||||
@@ -4480,30 +4471,28 @@ static int tegra210_adsp_audio_platform_probe(struct platform_device *pdev)
|
|||||||
.input = tegra210_adsp_nl_recv_msg,
|
.input = tegra210_adsp_nl_recv_msg,
|
||||||
};
|
};
|
||||||
|
|
||||||
pr_info("tegra210_adsp_audio_platform_probe: platform probe started\n");
|
pr_info("%s: platform probe started\n", __func__);
|
||||||
|
|
||||||
if (dev_set_name(&pdev->dev, "%s", DRV_NAME_ADSP) < 0) {
|
if (dev_set_name(&pdev->dev, "%s", DRV_NAME) < 0) {
|
||||||
dev_err(&pdev->dev, "error in setting adsp device name\n");
|
dev_err(&pdev->dev, "error in setting adsp device name\n");
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
match = of_match_device(tegra210_adsp_audio_of_match, &pdev->dev);
|
match = of_match_device(tegra210_adsp_audio_of_match, &pdev->dev);
|
||||||
if (!match) {
|
if (!match)
|
||||||
dev_err(&pdev->dev, "Error: No device match found\n");
|
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
|
||||||
|
|
||||||
adsp = devm_kzalloc(&pdev->dev, sizeof(*adsp), GFP_KERNEL);
|
adsp = devm_kzalloc(&pdev->dev, sizeof(*adsp), GFP_KERNEL);
|
||||||
if (!adsp) {
|
if (!adsp) {
|
||||||
dev_err(&pdev->dev, "Can't allocate tegra210_adsp_ctx\n");
|
dev_err(&pdev->dev, "Can't allocate tegra210_adsp_ctx\n");
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
dev_set_drvdata(&pdev->dev, adsp);
|
dev_set_drvdata(&pdev->dev, adsp);
|
||||||
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()) {
|
||||||
if (!(tegra_platform_is_unit_fpga() || tegra_platform_is_fpga())) {
|
|
||||||
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");
|
||||||
@@ -4535,8 +4524,6 @@ static int tegra210_adsp_audio_platform_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;
|
||||||
|
|
||||||
tegra_pd_add_device(&pdev->dev);
|
|
||||||
|
|
||||||
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;
|
||||||
@@ -4667,7 +4654,7 @@ static int tegra210_adsp_audio_platform_probe(struct platform_device *pdev)
|
|||||||
/* enable/disable compr-ops from DT */
|
/* enable/disable compr-ops from DT */
|
||||||
of_property_read_u32(pdev->dev.of_node, "compr-ops", &compr_ops);
|
of_property_read_u32(pdev->dev.of_node, "compr-ops", &compr_ops);
|
||||||
if (!compr_ops)
|
if (!compr_ops)
|
||||||
tegra210_adsp_platform.compr_ops = NULL;
|
tegra210_adsp_cmpnt.compr_ops = NULL;
|
||||||
|
|
||||||
if (of_property_read_u32_index(pdev->dev.of_node, "nvidia,adma_ch_page",
|
if (of_property_read_u32_index(pdev->dev.of_node, "nvidia,adma_ch_page",
|
||||||
0, &adma_ch_page)) {
|
0, &adma_ch_page)) {
|
||||||
@@ -4701,18 +4688,12 @@ static int tegra210_adsp_audio_platform_probe(struct platform_device *pdev)
|
|||||||
adsp->adma_ch_cnt);
|
adsp->adma_ch_cnt);
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = snd_soc_register_platform(&pdev->dev, &tegra210_adsp_platform);
|
ret = snd_soc_register_component(&pdev->dev, &tegra210_adsp_cmpnt,
|
||||||
if (ret) {
|
tegra210_adsp_cmpnt_dai,
|
||||||
dev_err(&pdev->dev, "Could not register platform: %d\n", ret);
|
ARRAY_SIZE(tegra210_adsp_cmpnt_dai));
|
||||||
goto err_pm_disable;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = snd_soc_register_codec(&pdev->dev, &tegra210_adsp_codec,
|
|
||||||
tegra210_adsp_codec_dai,
|
|
||||||
ARRAY_SIZE(tegra210_adsp_codec_dai));
|
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
dev_err(&pdev->dev, "Could not register CODEC: %d\n", ret);
|
dev_err(&pdev->dev, "Could not register CODEC: %d\n", ret);
|
||||||
goto err_unregister_platform;
|
goto err_pm_disable;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < (APM_IN_END - APM_IN_START + 1); i++) {
|
for (i = 0; i < (APM_IN_END - APM_IN_START + 1); i++) {
|
||||||
@@ -4723,7 +4704,8 @@ static int tegra210_adsp_audio_platform_probe(struct platform_device *pdev)
|
|||||||
&apm_stack_size[i]);
|
&apm_stack_size[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
adsp->nl_sk = netlink_kernel_create(&init_net, NETLINK_ADSP_EVENT, &cfg);
|
adsp->nl_sk = netlink_kernel_create(&init_net, NETLINK_ADSP_EVENT,
|
||||||
|
&cfg);
|
||||||
if (!adsp->nl_sk) {
|
if (!adsp->nl_sk) {
|
||||||
dev_err(&pdev->dev, "Error creating socket\n");
|
dev_err(&pdev->dev, "Error creating socket\n");
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
@@ -4744,24 +4726,20 @@ static int tegra210_adsp_audio_platform_probe(struct platform_device *pdev)
|
|||||||
err_release_netlink:
|
err_release_netlink:
|
||||||
netlink_kernel_release(adsp->nl_sk);
|
netlink_kernel_release(adsp->nl_sk);
|
||||||
err_unregister_codec:
|
err_unregister_codec:
|
||||||
snd_soc_unregister_codec(&pdev->dev);
|
snd_soc_unregister_component(&pdev->dev);
|
||||||
err_unregister_platform:
|
|
||||||
snd_soc_unregister_platform(&pdev->dev);
|
|
||||||
err_pm_disable:
|
err_pm_disable:
|
||||||
pm_runtime_disable(&pdev->dev);
|
pm_runtime_disable(&pdev->dev);
|
||||||
err:
|
err:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int tegra210_adsp_audio_platform_remove(struct platform_device *pdev)
|
static int tegra210_adsp_audio_remove(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct tegra210_adsp *adsp = dev_get_drvdata(&pdev->dev);
|
struct tegra210_adsp *adsp = dev_get_drvdata(&pdev->dev);
|
||||||
|
|
||||||
netlink_kernel_release(adsp->nl_sk);
|
netlink_kernel_release(adsp->nl_sk);
|
||||||
snd_soc_unregister_codec(&pdev->dev);
|
snd_soc_unregister_component(&pdev->dev);
|
||||||
pm_runtime_disable(&pdev->dev);
|
pm_runtime_disable(&pdev->dev);
|
||||||
tegra_pd_remove_device(&pdev->dev);
|
|
||||||
snd_soc_unregister_platform(&pdev->dev);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4775,20 +4753,20 @@ static const struct dev_pm_ops tegra210_adsp_pm_ops = {
|
|||||||
|
|
||||||
static struct platform_driver tegra210_adsp_audio_driver = {
|
static struct platform_driver tegra210_adsp_audio_driver = {
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = DRV_NAME_ADSP,
|
.name = DRV_NAME,
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
.of_match_table = tegra210_adsp_audio_of_match,
|
.of_match_table = tegra210_adsp_audio_of_match,
|
||||||
.pm = &tegra210_adsp_pm_ops,
|
.pm = &tegra210_adsp_pm_ops,
|
||||||
.suppress_bind_attrs = true,
|
.suppress_bind_attrs = true,
|
||||||
},
|
},
|
||||||
.probe = tegra210_adsp_audio_platform_probe,
|
.probe = tegra210_adsp_audio_probe,
|
||||||
.remove = tegra210_adsp_audio_platform_remove,
|
.remove = tegra210_adsp_audio_remove,
|
||||||
};
|
};
|
||||||
module_platform_driver(tegra210_adsp_audio_driver);
|
module_platform_driver(tegra210_adsp_audio_driver);
|
||||||
|
|
||||||
MODULE_AUTHOR("Sumit Bhattacharya <sumitb@nvidia.com>");
|
MODULE_AUTHOR("Sumit Bhattacharya <sumitb@nvidia.com>");
|
||||||
MODULE_DESCRIPTION("Tegra210 ADSP Audio driver");
|
MODULE_DESCRIPTION("Tegra210 ADSP Audio driver");
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
MODULE_ALIAS("platform:" DRV_NAME_ADSP);
|
MODULE_ALIAS("platform:" DRV_NAME);
|
||||||
MODULE_DEVICE_TABLE(of, tegra210_adsp_audio_of_match);
|
MODULE_DEVICE_TABLE(of, tegra210_adsp_audio_of_match);
|
||||||
|
|
||||||
@@ -1,26 +1,18 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/*
|
/*
|
||||||
* tegra210_adsp_alt.h - Tegra210 ADSP header
|
* tegra210_adsp.h - Tegra210 ADSP header
|
||||||
*
|
*
|
||||||
* Copyright (c) 2014-2019 NVIDIA CORPORATION. All rights reserved.
|
* Copyright (c) 2014-2020 NVIDIA CORPORATION. All rights reserved.
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms and conditions of the GNU General Public License,
|
|
||||||
* version 2, as published by the Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
||||||
* more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __TEGRA210_ADSP_ALT_H__
|
#ifndef __TEGRA210_ADSP_H__
|
||||||
#define __TEGRA210_ADSP_ALT_H__
|
#define __TEGRA210_ADSP_H__
|
||||||
|
|
||||||
/* This enum is linked with tegra210_adsp_mux_texts array. Any thing
|
/*
|
||||||
changed in enum define should be also reflected in text array */
|
* This enum is linked with tegra210_adsp_mux_texts array. Any thing
|
||||||
|
* changed in enum define should be also reflected in text array
|
||||||
|
*/
|
||||||
enum tegra210_adsp_virt_regs {
|
enum tegra210_adsp_virt_regs {
|
||||||
TEGRA210_ADSP_NONE,
|
TEGRA210_ADSP_NONE,
|
||||||
|
|
||||||
Reference in New Issue
Block a user