From ea7af586a74533a9e9ce6cb8a8e5c61e80338906 Mon Sep 17 00:00:00 2001 From: Sameer Pujar Date: Thu, 4 Apr 2024 19:04:51 +0000 Subject: [PATCH] ASoC: tegra: cleanup legacy code Upstream sound card machine driver is used now and legacy machine driver is not required anymore. Hence following cleanups are made: - Remove legacy machine driver 'tegra_machine_driver.c'. - With legacy driver removal many of the APIs in tegra_asoc_machine.c are not required. So remove all such APIs and update the header file as well. - The ASoC utils 'tegra_asoc_utils.c' is not needed after removal of legacy machine driver. Remove the corresponding header as well. - BW manager support needs to be pushed in upstream and it is needed for ADMAIF and ADSP ASoC drivers. The downstream BW manager code can't be used by the ADMAIF driver. So remove downstream BW manager code and put FIXME item in ADSP driver. Bug 4596865 Change-Id: Iac154b00759571a5593c3d75bbacbae5a68385e2 Signed-off-by: Sameer Pujar Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3110862 Reviewed-by: Mohan kumar Reviewed-by: Dara Ramesh GVS: buildbot_gerritrpt --- sound/soc/tegra/Makefile | 6 +- sound/soc/tegra/tegra210_adsp.c | 13 +- sound/soc/tegra/tegra_asoc_machine.c | 646 ------------------------- sound/soc/tegra/tegra_asoc_machine.h | 41 +- sound/soc/tegra/tegra_asoc_utils.c | 451 ----------------- sound/soc/tegra/tegra_asoc_utils.h | 53 -- sound/soc/tegra/tegra_codecs.c | 287 ----------- sound/soc/tegra/tegra_codecs.h | 21 - sound/soc/tegra/tegra_machine_driver.c | 489 ------------------- 9 files changed, 7 insertions(+), 2000 deletions(-) delete mode 100644 sound/soc/tegra/tegra_asoc_utils.c delete mode 100644 sound/soc/tegra/tegra_asoc_utils.h delete mode 100644 sound/soc/tegra/tegra_codecs.c delete mode 100644 sound/soc/tegra/tegra_codecs.h delete mode 100644 sound/soc/tegra/tegra_machine_driver.c diff --git a/sound/soc/tegra/Makefile b/sound/soc/tegra/Makefile index d187f7b8..4f75f887 100644 --- a/sound/soc/tegra/Makefile +++ b/sound/soc/tegra/Makefile @@ -1,13 +1,12 @@ # SPDX-License-Identifier: GPL-2.0-only # SPDX-FileCopyrightText: Copyright (c) 2023-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved. -snd-soc-tegra-utils-objs := tegra_asoc_utils.o tegra_asoc_machine.o \ - tegra_isomgr_bw.o tegra_codecs.o +snd-soc-tegra-utils-objs := tegra_asoc_machine.o \ + tegra_isomgr_bw.o snd-soc-tegra210-afc-objs := tegra210_afc.o snd-soc-tegra210-iqc-objs := tegra210_iqc.o snd-soc-tegra186-arad-objs := tegra186_arad.o snd-soc-tegra210-adsp-objs := tegra210_adsp.o -snd-soc-tegra-machine-driver-objs := tegra_machine_driver.o snd-soc-tegra-controls-objs := tegra_mixer_control.o obj-m += snd-soc-tegra-utils.o @@ -15,5 +14,4 @@ obj-m += snd-soc-tegra210-afc.o obj-m += snd-soc-tegra210-iqc.o obj-m += snd-soc-tegra186-arad.o obj-m += snd-soc-tegra210-adsp.o -obj-m += snd-soc-tegra-machine-driver.o obj-m += snd-soc-tegra-controls.o diff --git a/sound/soc/tegra/tegra210_adsp.c b/sound/soc/tegra/tegra210_adsp.c index 25c9d780..01f880d7 100644 --- a/sound/soc/tegra/tegra210_adsp.c +++ b/sound/soc/tegra/tegra210_adsp.c @@ -1,11 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only -/* - * tegra210_adsp.c - Tegra ADSP audio driver - * - * Author: Sumit Bhattacharya - * Copyright (c) 2014-2024 NVIDIA CORPORATION. All rights reserved. - * - */ +// SPDX-FileCopyrightText: Copyright (c) 2014-2024 NVIDIA CORPORATION. All rights reserved. +// +// tegra210_adsp.c - Tegra ADSP audio driver #include #include @@ -42,7 +38,6 @@ #include #include "tegra_isomgr_bw.h" -#include "tegra_asoc_utils.h" #include "tegra210_adsp.h" #define DRV_NAME "tegra210-adsp" @@ -4803,4 +4798,4 @@ MODULE_AUTHOR("Sumit Bhattacharya "); MODULE_DESCRIPTION("Tegra210 ADSP Audio driver"); MODULE_LICENSE("GPL"); MODULE_ALIAS("platform:" DRV_NAME); -MODULE_DEVICE_TABLE(of, tegra210_adsp_audio_of_match); \ No newline at end of file +MODULE_DEVICE_TABLE(of, tegra210_adsp_audio_of_match); diff --git a/sound/soc/tegra/tegra_asoc_machine.c b/sound/soc/tegra/tegra_asoc_machine.c index a59f9758..fae7dbc5 100644 --- a/sound/soc/tegra/tegra_asoc_machine.c +++ b/sound/soc/tegra/tegra_asoc_machine.c @@ -13,634 +13,6 @@ #include #include "tegra_asoc_machine.h" -#define PREFIX "nvidia-audio-card," -#define CELL "#sound-dai-cells" -#define DAI "sound-dai" - -/* DT also uses similar values to specify link type */ -enum dai_link_type { - PCM_LINK, - COMPR_LINK, - C2C_LINK, -}; - -struct snd_soc_pcm_stream link_params = { - .formats = SNDRV_PCM_FMTBIT_S8 | - SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_LE | - SNDRV_PCM_FMTBIT_S32_LE, - .rate_min = 8000, - .rate_max = 192000, - .channels_min = 1, - .channels_max = 16, -}; - -/* find if DAI link or its cpu/codec DAI nodes are disabled */ -static bool of_dai_link_is_available(struct device_node *link_node) -{ - struct device_node *child, *dai_node; - - if (!of_device_is_available(link_node)) - return false; - - for_each_child_of_node(link_node, child) { - /* check for "cpu" and "codec" nodes only */ - if (of_node_cmp(child->name, "cpu") && - of_node_cmp(child->name, "codec")) - continue; - - /* - * Skip a codec subnode if DAI property is missing. For a - * link with multiple codecs, at least one codec needs to - * have DAI property (which is ensured while counting the - * number of links that DT exposes). Other codec subnodes - * can be empty and populated in override file. - */ - if (!of_property_read_bool(child, DAI) && - !of_node_cmp(child->name, "codec")) - continue; - - dai_node = of_parse_phandle(child, DAI, 0); - if (!dai_node) { - of_node_put(child); - return false; - } - - if (!of_device_is_available(dai_node)) { - of_node_put(dai_node); - of_node_put(child); - return false; - } - - of_node_put(dai_node); - } - - return true; -} - -/* find number of child nodes with given name and containing DAI property */ -static int of_get_child_count_with_name(struct device_node *node, - const char *name) -{ - struct device_node *child; - int num = 0; - - for_each_child_of_node(node, child) - if (!of_node_cmp(child->name, name) && - of_property_read_bool(child, DAI)) - num++; - - return num; -} - -static int get_num_dai_links(struct platform_device *pdev, - unsigned int *num_links) -{ - struct device_node *top = pdev->dev.of_node; - struct device_node *link_node; - unsigned int link_count = 0; - - link_node = of_get_child_by_name(top, PREFIX "dai-link"); - if (!link_node) { - dev_err(&pdev->dev, "no dai links found\n"); - return -ENOENT; - } - - do { - if (!of_dai_link_is_available(link_node)) { - link_node = of_get_next_child(top, link_node); - continue; - } - - link_count++; - link_node = of_get_next_child(top, link_node); - } while (link_node); - - *num_links = link_count; - - return 0; -} - -static int allocate_link_dais(struct platform_device *pdev, - struct snd_soc_dai_link *dai_links) -{ - struct device_node *top = pdev->dev.of_node; - struct device_node *link_node; - unsigned int link_count = 0, num_codecs; - - link_node = of_get_child_by_name(top, PREFIX "dai-link"); - if (!link_node) { - dev_err(&pdev->dev, "no dai links found\n"); - return -ENOENT; - } - - do { - if (!of_dai_link_is_available(link_node)) { - link_node = of_get_next_child(top, link_node); - continue; - } - - dai_links[link_count].cpus = devm_kzalloc(&pdev->dev, - sizeof(*dai_links[link_count].cpus), - GFP_KERNEL); - if (!dai_links[link_count].cpus) - return -ENOMEM; - - num_codecs = of_get_child_count_with_name(link_node, - "codec"); - if (!num_codecs) { - of_node_put(link_node); - dev_err(&pdev->dev, - "no codec subnode or sound-dai property\n"); - return -EINVAL; - } - - dai_links[link_count].codecs = - devm_kzalloc(&pdev->dev, - sizeof(*dai_links[link_count].codecs) * num_codecs, - GFP_KERNEL); - if (!dai_links[link_count].codecs) - return -ENOMEM; - - dai_links[link_count].platforms = devm_kzalloc(&pdev->dev, - sizeof(*dai_links[link_count].platforms), - GFP_KERNEL); - if (!dai_links[link_count].platforms) - return -ENOMEM; - - dai_links[link_count].num_cpus = 1; - dai_links[link_count].num_codecs = num_codecs; - dai_links[link_count].num_platforms = 1; - - link_count++; - - link_node = of_get_next_child(top, link_node); - } while (link_node); - - return 0; -} - -static int get_num_codec_confs(struct platform_device *pdev, int *num_confs) -{ - struct device_node *top = pdev->dev.of_node; - struct device_node *link_node, *codec; - unsigned int conf_count = 0, num_codecs; - - link_node = of_get_child_by_name(top, PREFIX "dai-link"); - if (!link_node) { - dev_err(&pdev->dev, "no dai links found\n"); - return -EINVAL; - } - - do { - if (!of_dai_link_is_available(link_node)) { - link_node = of_get_next_child(top, link_node); - continue; - } - - num_codecs = of_get_child_count_with_name(link_node, - "codec"); - if (!num_codecs) { - of_node_put(link_node); - dev_err(&pdev->dev, "missing codec subnode\n"); - return -EINVAL; - } - - for_each_child_of_node(link_node, codec) { - if (of_node_cmp(codec->name, "codec")) - continue; - - if (of_property_read_bool(codec, "prefix")) - conf_count++; - } - - link_node = of_get_next_child(top, link_node); - } while (link_node); - - *num_confs = conf_count; - - return 0; -} - -static void parse_mclk_fs(struct snd_soc_card *card) -{ - struct tegra_machine *machine = snd_soc_card_get_drvdata(card); - struct platform_device *pdev = to_platform_device(card->dev); - - if (of_property_read_u32(pdev->dev.of_node, PREFIX "mclk-fs", - &machine->audio_clock.mclk_fs)) - dev_dbg(&pdev->dev, "'%smclk-fs' property is missing\n", - PREFIX); -} - -static int parse_dai(struct device_node *node, - struct snd_soc_dai_link_component *dlc) -{ - struct of_phandle_args args; - int ret; - - ret = of_parse_phandle_with_args(node, DAI, CELL, 0, &args); - if (ret) - return ret; - -#if defined(NV_SND_SOC_OF_GET_DAI_NAME_HAS_INDEX_ARG) - ret = snd_soc_of_get_dai_name(node, &dlc->dai_name, 0); -#else - ret = snd_soc_of_get_dai_name(node, &dlc->dai_name); -#endif - if (ret < 0) - return ret; - - dlc->of_node = args.np; - - return 0; -} - -static int parse_dt_codec_confs(struct snd_soc_card *card) -{ - struct platform_device *pdev = to_platform_device(card->dev); - struct tegra_machine *machine = snd_soc_card_get_drvdata(card); - struct device_node *top = pdev->dev.of_node; - struct device_node *link_node; - struct snd_soc_codec_conf *codec_confs; - unsigned int num_confs, i = 0; - int err; - - err = get_num_codec_confs(pdev, &machine->asoc->num_confs); - if (err < 0) - return err; - - num_confs = machine->asoc->num_confs; - if (!num_confs) - return 0; - - machine->asoc->codec_confs = devm_kcalloc(&pdev->dev, - num_confs, - sizeof(*codec_confs), - GFP_KERNEL); - if (!machine->asoc->codec_confs) - return -ENOMEM; - codec_confs = machine->asoc->codec_confs; - - link_node = of_get_child_by_name(top, PREFIX "dai-link"); - if (!link_node) { - dev_err(&pdev->dev, "DAI links not found in DT\n"); - return -ENOENT; - } - - do { - struct of_phandle_args args; - struct device_node *codec; - - if (!of_dai_link_is_available(link_node)) { - link_node = of_get_next_child(top, link_node); - continue; - } - - for_each_child_of_node(link_node, codec) { - if (of_node_cmp(codec->name, "codec")) - continue; - - if (!of_property_read_bool(codec, "prefix")) - continue; - - err = of_parse_phandle_with_args(codec, DAI, CELL, 0, - &args); - if (err < 0) { - of_node_put(codec); - of_node_put(link_node); - return err; - } - - codec_confs[i].dlc.of_node = args.np; - codec_confs[i].dlc.name = NULL; - - of_property_read_string(codec, "prefix", - &codec_confs[i].name_prefix); - - i++; - } - - link_node = of_get_next_child(top, link_node); - } while (link_node); - - card->num_configs = num_confs; - card->codec_conf = codec_confs; - - return 0; -} - -static int parse_dai_link_params(struct platform_device *pdev, - struct device_node *link_node, - struct snd_soc_dai_link *dai_link) -{ - struct snd_soc_pcm_stream *params; - char *str; - - params = devm_kzalloc(&pdev->dev, sizeof(*params), GFP_KERNEL); - if (!params) - return -ENOMEM; - - /* Copy default settings */ - memcpy(params, &link_params, sizeof(*params)); - - if (!of_property_read_u32(link_node, "srate", - ¶ms->rate_min)) { - if (params->rate_min < link_params.rate_min || - params->rate_min > link_params.rate_max) { - dev_err(&pdev->dev, - "Unsupported rate %d for DAI link (%pOF)\n", - params->rate_min, link_node); - - return -EOPNOTSUPP; - } - - params->rate_max = params->rate_min; - } - - if (!of_property_read_u32(link_node, "num-channel", - ¶ms->channels_min)) { - if (params->channels_min < link_params.channels_min || - params->channels_min > link_params.channels_max) { - dev_err(&pdev->dev, - "Unsupported channel %d for DAI link (%pOF)\n", - params->channels_min, link_node); - - return -EOPNOTSUPP; - } - - params->channels_max = params->channels_min; - } - - if (!of_property_read_string(link_node, "bit-format", - (const char **)&str)) { - if (!strcmp("s8", str)) { - params->formats = SNDRV_PCM_FMTBIT_S8; - } else if (!strcmp("s16_le", str)) { - params->formats = SNDRV_PCM_FMTBIT_S16_LE; - } else if (!strcmp("s24_le", str)) { - params->formats = SNDRV_PCM_FMTBIT_S24_LE; - } else if (!strcmp("s32_le", str)) { - params->formats = SNDRV_PCM_FMTBIT_S32_LE; - } else { - dev_err(&pdev->dev, - "Unsupported format %s for DAI link (%pOF)\n", - str, link_node); - - return -EOPNOTSUPP; - } - - if (!(params->formats & link_params.formats)) { - dev_err(&pdev->dev, - "Unsupported format %s for DAI link (%pOF)\n", - str, link_node); - - return -EOPNOTSUPP; - } - } - -#if defined(NV_SND_SOC_DAI_LINK_STRUCT_HAS_C2C_PARAMS_ARG) /* Linux v6.4 */ - dai_link->c2c_params = params; -#else - dai_link->params = params; -#endif - - return 0; -} - -static int parse_dt_dai_links(struct snd_soc_card *card, - struct snd_soc_ops *pcm_ops, - struct snd_soc_compr_ops *compr_ops) -{ - struct platform_device *pdev = to_platform_device(card->dev); - struct tegra_machine *machine = snd_soc_card_get_drvdata(card); - struct device_node *top = pdev->dev.of_node; - struct device_node *link_node; - struct snd_soc_dai_link *dai_links; - unsigned int num_links, link_count = 0; - int ret; - - ret = get_num_dai_links(pdev, &machine->asoc->num_links); - if (ret < 0) - return ret; - - num_links = machine->asoc->num_links; - if (!num_links) - return -EINVAL; - - dai_links = devm_kcalloc(&pdev->dev, num_links, sizeof(*dai_links), - GFP_KERNEL); - if (!dai_links) - return -ENOMEM; - - ret = allocate_link_dais(pdev, dai_links); - if (ret < 0) - return ret; - - machine->asoc->dai_links = dai_links; - - link_node = of_get_child_by_name(top, PREFIX "dai-link"); - if (!link_node) { - dev_err(&pdev->dev, "DAI links not found in DT\n"); - return -ENOENT; - } - - do { - struct device_node *codec = NULL, *cpu = NULL; - struct snd_soc_dai_link *dai_link; - int link_type = 0, codec_count = 0; - char *link_addr; - - if (!of_dai_link_is_available(link_node)) { - link_node = of_get_next_child(top, link_node); - continue; - } - - dev_dbg(&pdev->dev, "parsing (%pOF)\n", link_node); - - dai_link = &dai_links[link_count]; - cpu = of_get_child_by_name(link_node, "cpu"); - if (!cpu) { - dev_err(&pdev->dev, "cpu subnode is missing"); - ret = -ENOENT; - goto cleanup; - } - - /* parse CPU DAI */ - ret = parse_dai(cpu, dai_link->cpus); - if (ret < 0) - goto cleanup; - - for_each_child_of_node(link_node, codec) { - /* loop over codecs only */ - if (of_node_cmp(codec->name, "codec")) - continue; - - if (!of_property_read_bool(codec, DAI)) { - dev_dbg(&pdev->dev, - "sound-dai prop missing for (%pOF)\n", - codec); - codec_count++; - continue; - } - - /* parse CODEC DAI */ - ret = parse_dai(codec, &dai_link->codecs[codec_count]); - if (ret < 0) - goto cleanup; - - codec_count++; - } - - /* set DAI link name */ - if (of_property_read_string(link_node, - "link-name", - &dai_link->name)) { -#if defined(NV_ASOC_SIMPLE_RENAMED_SIMPLE) /* Linux 6.7 */ - ret = simple_util_set_dailink_name( - &pdev->dev, dai_link, "%s-%d", - "tegra-dlink", link_count); -#else - ret = asoc_simple_set_dailink_name( - &pdev->dev, dai_link, "%s-%d", - "tegra-dlink", link_count); -#endif - if (ret < 0) - goto cleanup; - } - -#if defined(NV_ASOC_SIMPLE_RENAMED_SIMPLE) /* Linux 6.7 */ - simple_util_parse_daifmt(&pdev->dev, link_node, codec, - NULL, &dai_link->dai_fmt); - - simple_util_canonicalize_platform(dai_link->platforms, - dai_link->cpus); -#else - asoc_simple_parse_daifmt(&pdev->dev, link_node, codec, - NULL, &dai_link->dai_fmt); - - asoc_simple_canonicalize_platform(dai_link->platforms, - dai_link->cpus); -#endif - - of_property_read_u32(link_node, "link-type", - &link_type); - switch (link_type) { - case PCM_LINK: - dai_link->ops = pcm_ops; - break; - case COMPR_LINK: - dai_link->compr_ops = compr_ops; - break; - case C2C_LINK: - /* Parse DT provided link params */ - ret = parse_dai_link_params(pdev, link_node, - dai_link); - if (ret < 0) - goto cleanup; - - break; - default: - dev_err(&pdev->dev, "DAI link type invalid\n"); - ret = -EINVAL; - goto cleanup; - } - - /* - * Assign DAI link ID based on DT link address. - * This is done to use consistent PCM/Compress device - * IDs irrespective of parsing order of DT DAI links. - */ - link_addr = strrchr(link_node->full_name, '@'); - if (!link_addr) { - dev_err(&pdev->dev, - "Invalid link node (%pOF)\n", - link_node); - ret = -EINVAL; - goto cleanup; - } - - ret = kstrtos32(++link_addr, 10, &dai_link->id); - if (ret < 0) { - dev_err(&pdev->dev, - "Failed to get link node (%pOF) ID\n", - link_node); - goto cleanup; - } - - link_count++; - -cleanup: - of_node_put(cpu); - if (ret < 0) { - of_node_put(codec); - of_node_put(link_node); - return ret; - } - - link_node = of_get_next_child(top, link_node); - } while (link_node); - - card->num_links = num_links; - card->dai_link = dai_links; - - return 0; -} - -int parse_card_info(struct snd_soc_card *card, struct snd_soc_ops *pcm_ops, - struct snd_soc_compr_ops *compr_ops) -{ - struct tegra_machine *machine = snd_soc_card_get_drvdata(card); - struct device_node *node = card->dev->of_node; - int ret; - -#if defined(NV_ASOC_SIMPLE_RENAMED_SIMPLE) /* Linux 6.7 */ - ret = simple_util_parse_card_name(card, PREFIX); -#else - ret = asoc_simple_parse_card_name(card, PREFIX); -#endif - if (ret < 0) - return ret; - - /* parse machine DAPM widgets */ - if (of_property_read_bool(node, PREFIX "widgets")) { - ret = snd_soc_of_parse_audio_simple_widgets(card, - PREFIX "widgets"); - if (ret < 0) - return ret; - } - - /*str - * Below property of routing map is required only when there - * are DAPM input/output widgets available for external codec, - * which require them to be connected to machine source/sink - * DAPM widgets. - */ - if (of_property_read_bool(node, PREFIX "routing")) { - ret = snd_soc_of_parse_audio_routing(card, PREFIX "routing"); - if (ret < 0) - return ret; - } - - parse_mclk_fs(card); - - if (of_property_read_bool(node, "fixed-pll")) { - machine->audio_clock.fixed_pll = true; - dev_info(card->dev, "PLL configuration is fixed from DT\n"); - } - - ret = parse_dt_dai_links(card, pcm_ops, compr_ops); - if (ret < 0) - return ret; - - ret = parse_dt_codec_confs(card); - if (ret < 0) - return ret; - - return 0; -} -EXPORT_SYMBOL_GPL(parse_card_info); - struct tegra_machine_control_data { struct snd_soc_pcm_runtime *rtd; unsigned int frame_mode; @@ -983,23 +355,5 @@ int tegra_machine_add_codec_jack_control(struct snd_soc_card *card, } EXPORT_SYMBOL_GPL(tegra_machine_add_codec_jack_control); -void release_asoc_phandles(struct tegra_machine *machine) -{ - unsigned int i; - - if (machine->asoc->dai_links) { - for (i = 0; i < machine->asoc->num_links; i++) { - of_node_put(machine->asoc->dai_links[i].cpus->of_node); - of_node_put(machine->asoc->dai_links[i].codecs->of_node); - } - } - if (machine->asoc->codec_confs) { - for (i = 0; i < machine->asoc->num_confs; i++) - of_node_put(machine->asoc->codec_confs[i].dlc.of_node); - } -} -EXPORT_SYMBOL_GPL(release_asoc_phandles); -MODULE_LICENSE("GPL"); - MODULE_DESCRIPTION("Tegra ASoC Machine Utility Code"); MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/tegra/tegra_asoc_machine.h b/sound/soc/tegra/tegra_asoc_machine.h index a07ac3d5..370aaf3b 100644 --- a/sound/soc/tegra/tegra_asoc_machine.h +++ b/sound/soc/tegra/tegra_asoc_machine.h @@ -1,55 +1,16 @@ /* SPDX-License-Identifier: GPL-2.0-only */ +/* SPDX-FileCopyrightText: Copyright (c) 2014-2024 NVIDIA CORPORATION. All rights reserved. */ /* * tegra_asoc_machine.h * - * Copyright (c) 2014-2020 NVIDIA CORPORATION. All rights reserved. - * */ #ifndef __TEGRA_ASOC_MACHINE_H__ #define __TEGRA_ASOC_MACHINE_H__ -#include "tegra_asoc_utils.h" - -/* - * struct tegra_asoc - ASoC topology of dai links and codec confs - * @codec_confs: Configuration of codecs from xbar and devicetree - * @dai_links: All DAI links from xbar and device tree - * @num_links: Total number of DAI links for given card - * @num_confs: Total number of codec confs for given card - * @tx_slot: TDM slot for Tx path - * @rx_slot: TDM slot for Rx path - */ -struct tegra_asoc { - struct snd_soc_codec_conf *codec_confs; - struct snd_soc_dai_link *dai_links; - unsigned int num_links; - unsigned int num_confs; - unsigned int *tx_slot; - unsigned int *rx_slot; -}; - -/* machine structure which holds sound card */ -struct tegra_machine { - struct tegra_asoc_utils_data audio_clock; - struct tegra_asoc *asoc; - unsigned int num_codec_links; - int rate_via_kcontrol; - int fmt_via_kcontrol; -}; - int tegra_machine_add_i2s_codec_controls(struct snd_soc_card *card); int tegra_machine_add_codec_jack_control(struct snd_soc_card *card, struct snd_soc_pcm_runtime *rtd, struct snd_soc_jack *jack); -void release_asoc_phandles(struct tegra_machine *machine); - -/* - * new helper functions for parsing all DAI links from DT. - * Representation of XBAR and codec links would be similar. - */ -int parse_card_info(struct snd_soc_card *card, struct snd_soc_ops *pcm_ops, - struct snd_soc_compr_ops *compr_ops); - #endif diff --git a/sound/soc/tegra/tegra_asoc_utils.c b/sound/soc/tegra/tegra_asoc_utils.c deleted file mode 100644 index ad5bea28..00000000 --- a/sound/soc/tegra/tegra_asoc_utils.c +++ /dev/null @@ -1,451 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * tegra_asoc_utils.c - Harmony machine ASoC driver - * - * Author: Stephen Warren - * Copyright (c) 2010-2023 NVIDIA CORPORATION. All rights reserved. - */ - -#include -#include -#include -#include -#include -#include - -#include "tegra_asoc_utils.h" - -#define MAX(X, Y) ((X > Y) ? (X) : (Y)) -/* - * this will be used for platforms from Tegra210 onwards. - * odd rates: sample rates multiple of 11.025kHz - * even_rates: sample rates multiple of 8kHz - */ -enum rate_type { - ODD_RATE, - EVEN_RATE, - NUM_RATE_TYPE, -}; -unsigned int tegra210_pll_base_rate[NUM_RATE_TYPE] = {338688000, 368640000}; -unsigned int tegra186_pll_stereo_base_rate[NUM_RATE_TYPE] = {270950400, 294912000}; -unsigned int tegra239_pll_base_rate[NUM_RATE_TYPE] = {1264435200, 1277952000}; -unsigned int default_pll_out_stereo_rate[NUM_RATE_TYPE] = {45158400, 49152000}; - -int tegra_asoc_utils_set_rate(struct tegra_asoc_utils_data *data, int srate, - int mclk) -{ - int new_baseclock; - bool clk_change; - int err; - - switch (srate) { - case 11025: - case 22050: - case 44100: - case 88200: - if (data->soc == TEGRA_ASOC_UTILS_SOC_TEGRA20) - new_baseclock = 56448000; - else if (data->soc == TEGRA_ASOC_UTILS_SOC_TEGRA30) - new_baseclock = 564480000; - else - new_baseclock = 282240000; - break; - case 8000: - case 16000: - case 24000: - case 32000: - case 48000: - case 64000: - case 96000: - if (data->soc == TEGRA_ASOC_UTILS_SOC_TEGRA20) - new_baseclock = 73728000; - else if (data->soc == TEGRA_ASOC_UTILS_SOC_TEGRA30) - new_baseclock = 552960000; - else - new_baseclock = 368640000; - break; - default: - return -EINVAL; - } - - clk_change = ((new_baseclock != data->set_baseclock) || - (mclk != data->set_mclk)); - if (!clk_change) - return 0; - - data->set_baseclock = 0; - data->set_mclk = 0; - - clk_disable_unprepare(data->clk_cdev1); - clk_disable_unprepare(data->clk_pll_a_out0); - clk_disable_unprepare(data->clk_pll_a); - - err = clk_set_rate(data->clk_pll_a, new_baseclock); - if (err) { - dev_err(data->dev, "Can't set base pll rate: %d\n", err); - return err; - } - - err = clk_set_rate(data->clk_pll_a_out0, mclk); - if (err) { - dev_err(data->dev, "Can't set pll_out rate: %d\n", err); - return err; - } - - /* Don't set cdev1/extern1 rate; it's locked to pll_out */ - - err = clk_prepare_enable(data->clk_pll_a); - if (err) { - dev_err(data->dev, "Can't enable pll: %d\n", err); - return err; - } - - err = clk_prepare_enable(data->clk_pll_a_out0); - if (err) { - dev_err(data->dev, "Can't enable pll_out: %d\n", err); - return err; - } - - err = clk_prepare_enable(data->clk_cdev1); - if (err) { - dev_err(data->dev, "Can't enable clk_cdev1: %d\n", err); - return err; - } - - data->set_baseclock = new_baseclock; - data->set_mclk = mclk; - - return 0; -} -EXPORT_SYMBOL_GPL(tegra_asoc_utils_set_rate); - -int tegra_asoc_utils_set_ac97_rate(struct tegra_asoc_utils_data *data) -{ - const int pll_rate = 73728000; - const int ac97_rate = 24576000; - int err; - - clk_disable_unprepare(data->clk_cdev1); - clk_disable_unprepare(data->clk_pll_a_out0); - clk_disable_unprepare(data->clk_pll_a); - - /* - * AC97 rate is fixed at 24.576MHz and is used for both the host - * controller and the external codec - */ - err = clk_set_rate(data->clk_pll_a, pll_rate); - if (err) { - dev_err(data->dev, "Can't set pll_a rate: %d\n", err); - return err; - } - - err = clk_set_rate(data->clk_pll_a_out0, ac97_rate); - if (err) { - dev_err(data->dev, "Can't set pll_a_out0 rate: %d\n", err); - return err; - } - - /* Don't set cdev1/extern1 rate; it's locked to pll_a_out0 */ - - err = clk_prepare_enable(data->clk_pll_a); - if (err) { - dev_err(data->dev, "Can't enable pll_a: %d\n", err); - return err; - } - - err = clk_prepare_enable(data->clk_pll_a_out0); - if (err) { - dev_err(data->dev, "Can't enable pll_a_out0: %d\n", err); - return err; - } - - err = clk_prepare_enable(data->clk_cdev1); - if (err) { - dev_err(data->dev, "Can't enable cdev1: %d\n", err); - return err; - } - - data->set_baseclock = pll_rate; - data->set_mclk = ac97_rate; - - return 0; -} -EXPORT_SYMBOL_GPL(tegra_asoc_utils_set_ac97_rate); - -static int modify_parent_clk_base_rates(unsigned int *new_pll_base, - unsigned int *pll_out, - unsigned int req_bclk, - struct tegra_asoc_utils_data *data) -{ - unsigned int bclk_div, pll_div; - bool pll_out_halved = false; - - if (req_bclk == 0) - return 0; - - if (req_bclk > *pll_out) - return -EOPNOTSUPP; - - if ((*pll_out / req_bclk) > 128) { - /* reduce pll_out rate to support lower sampling rates */ - *pll_out >>= 1; - pll_out_halved = true; - } - - /* Modify base rates on chips >= T186 if fractional dividier is seen */ - if (data->soc >= TEGRA_ASOC_UTILS_SOC_TEGRA186 && - (*pll_out % req_bclk)) { - - /* Below logic is added to reduce dynamic range - * of PLLA (~37MHz). Min and max plla for chips >= t186 - * are 258.048 MHz and 294.912 MHz respectively. PLLA dynamic - * range is kept minimal to avoid clk ramp up/down issues - * and avoid halving plla if already halved - */ - if (!pll_out_halved && req_bclk <= (*pll_out >> 1)) - *pll_out >>= 1; - - *new_pll_base = MAX(data->pll_base_rate[EVEN_RATE], - data->pll_base_rate[ODD_RATE]); - - /* Modifying base rates for i2s parent and grand parent - * clocks so that i2s rate can be derived with integer division - * as fractional divider is not supported in HW - */ - - bclk_div = *pll_out / req_bclk; - *pll_out = req_bclk * bclk_div; - pll_div = *new_pll_base / *pll_out; - *new_pll_base = pll_div * (*pll_out); - /* TODO: Make sure that the dynamic range is not violated - * by having chip specific lower and upper limits of PLLA - */ - } - return 0; -} - -int tegra_asoc_utils_set_tegra210_rate(struct tegra_asoc_utils_data *data, - unsigned int sample_rate, - unsigned int channels, - unsigned int sample_size) -{ - unsigned int new_pll_base, pll_out, aud_mclk = 0, req_bclk; - int err; - - if (data->fixed_pll) - goto update_mclk_rate; - - switch (sample_rate) { - case 11025: - case 22050: - case 44100: - case 88200: - case 176400: - new_pll_base = data->pll_base_rate[ODD_RATE]; - pll_out = default_pll_out_stereo_rate[ODD_RATE]; - break; - case 8000: - case 16000: - case 24000: - case 32000: - case 48000: - case 64000: - case 96000: - case 192000: - new_pll_base = data->pll_base_rate[EVEN_RATE]; - pll_out = default_pll_out_stereo_rate[EVEN_RATE]; - break; - default: - return -EINVAL; - } - - req_bclk = sample_rate * channels * sample_size; - - err = modify_parent_clk_base_rates(&new_pll_base, - &pll_out, req_bclk, data); - if (err) { - dev_err(data->dev, "Clk rate %d not supported\n", - req_bclk); - return err; - } - - if (data->set_baseclock != new_pll_base) { - err = clk_set_rate(data->clk_pll_a, new_pll_base); - if (err) { - dev_err(data->dev, "Can't set clk_pll_a rate: %d\n", - err); - return err; - } - data->set_baseclock = new_pll_base; - } - - if (data->set_pll_out != pll_out) { - err = clk_set_rate(data->clk_pll_a_out0, pll_out); - if (err) { - dev_err(data->dev, "Can't set clk_pll_a_out0 rate: %d\n", - err); - return err; - } - data->set_pll_out = pll_out; - } - -update_mclk_rate: - if (data->mclk_fs) - aud_mclk = sample_rate * data->mclk_fs; - - if (data->set_mclk != aud_mclk) { - err = clk_set_rate(data->clk_cdev1, aud_mclk); - if (err) { - dev_err(data->dev, "Can't set clk_cdev1 rate: %d\n", - err); - return err; - } - data->set_mclk = aud_mclk; - } - - return 0; -} -EXPORT_SYMBOL_GPL(tegra_asoc_utils_set_tegra210_rate); - -int tegra_asoc_utils_clk_enable(struct tegra_asoc_utils_data *data) -{ - int err; - - err = clk_prepare_enable(data->clk_cdev1); - if (err) { - dev_err(data->dev, "Can't enable clock cdev1\n"); - return err; - } - - return 0; -} -EXPORT_SYMBOL_GPL(tegra_asoc_utils_clk_enable); - -void tegra_asoc_utils_clk_disable(struct tegra_asoc_utils_data *data) -{ - clk_disable_unprepare(data->clk_cdev1); -} -EXPORT_SYMBOL_GPL(tegra_asoc_utils_clk_disable); - -int tegra_asoc_utils_init(struct tegra_asoc_utils_data *data, - struct device *dev) -{ - struct clk *clk_out_1, *clk_extern1; - int ret; - - data->dev = dev; - - if (of_machine_is_compatible("nvidia,tegra20")) - data->soc = TEGRA_ASOC_UTILS_SOC_TEGRA20; - else if (of_machine_is_compatible("nvidia,tegra30")) - data->soc = TEGRA_ASOC_UTILS_SOC_TEGRA30; - else if (of_machine_is_compatible("nvidia,tegra114")) - data->soc = TEGRA_ASOC_UTILS_SOC_TEGRA114; - else if (of_machine_is_compatible("nvidia,tegra124")) - data->soc = TEGRA_ASOC_UTILS_SOC_TEGRA124; - else if (of_machine_is_compatible("nvidia,tegra210")) - data->soc = TEGRA_ASOC_UTILS_SOC_TEGRA210; - else if (of_machine_is_compatible("nvidia,tegra186")) - data->soc = TEGRA_ASOC_UTILS_SOC_TEGRA186; - else if (of_machine_is_compatible("nvidia,tegra194")) - data->soc = TEGRA_ASOC_UTILS_SOC_TEGRA194; - else if (of_machine_is_compatible("nvidia,tegra234")) - data->soc = TEGRA_ASOC_UTILS_SOC_TEGRA234; - else if (of_machine_is_compatible("nvidia,tegra239")) - data->soc = TEGRA_ASOC_UTILS_SOC_TEGRA239; - else { - dev_err(data->dev, "SoC unknown to Tegra ASoC utils\n"); - return -EINVAL; - } - - data->clk_pll_a = devm_clk_get(dev, "pll_a"); - if (IS_ERR(data->clk_pll_a)) { - dev_err(data->dev, "Can't retrieve clk pll_a\n"); - return PTR_ERR(data->clk_pll_a); - } - - data->clk_pll_a_out0 = devm_clk_get(dev, "plla_out0"); - if (IS_ERR(data->clk_pll_a_out0)) { - dev_err(data->dev, "Can't retrieve clk plla_out0\n"); - return PTR_ERR(data->clk_pll_a_out0); - } - - /* FIXME: data->clk_cdev1 = devm_clk_get_optional(dev, "mclk"); */ - data->clk_cdev1 = devm_clk_get_optional(dev, "extern1"); - if (IS_ERR(data->clk_cdev1)) { - dev_err(data->dev, "Can't retrieve clk cdev1\n"); - return PTR_ERR(data->clk_cdev1); - } - - if (data->soc < TEGRA_ASOC_UTILS_SOC_TEGRA210) { - ret = tegra_asoc_utils_set_rate(data, 44100, 256 * 44100); - if (ret) - return ret; - } - - if (data->soc < TEGRA_ASOC_UTILS_SOC_TEGRA186) - data->pll_base_rate = tegra210_pll_base_rate; - else if (data->soc < TEGRA_ASOC_UTILS_SOC_TEGRA239) - data->pll_base_rate = tegra186_pll_stereo_base_rate; - else - data->pll_base_rate = tegra239_pll_base_rate; - - /* - * If clock parents are not set in DT, configure here to use clk_out_1 - * as mclk and extern1 as parent for Tegra30 and higher. - */ - if (!of_find_property(dev->of_node, "assigned-clock-parents", NULL) && - data->soc > TEGRA_ASOC_UTILS_SOC_TEGRA20) { - dev_warn(data->dev, - "Configuring clocks for a legacy device-tree\n"); - dev_warn(data->dev, - "Please update DT to use assigned-clock-parents\n"); - clk_extern1 = devm_clk_get_optional(dev, "extern1"); - if (IS_ERR(clk_extern1)) { - dev_err(data->dev, "Can't retrieve clk extern1\n"); - return PTR_ERR(clk_extern1); - } - - ret = clk_set_parent(clk_extern1, data->clk_pll_a_out0); - if (ret < 0) { - dev_err(data->dev, - "Set parent failed for clk extern1\n"); - return ret; - } - - clk_out_1 = devm_clk_get(dev, "pmc_clk_out_1"); - if (IS_ERR(clk_out_1)) { - dev_err(data->dev, "Can't retrieve pmc_clk_out_1\n"); - return PTR_ERR(clk_out_1); - } - - ret = clk_set_parent(clk_out_1, clk_extern1); - if (ret < 0) { - dev_err(data->dev, - "Set parent failed for pmc_clk_out_1\n"); - return ret; - } - - data->clk_cdev1 = clk_out_1; - } - - /* - * FIXME: There is some unknown dependency between audio mclk disable - * and suspend-resume functionality on Tegra30, although audio mclk is - * only needed for audio. - */ - if (data->soc == TEGRA_ASOC_UTILS_SOC_TEGRA30) { - ret = clk_prepare_enable(data->clk_cdev1); - if (ret) { - dev_err(data->dev, "Can't enable cdev1: %d\n", ret); - return ret; - } - } - - return 0; -} -EXPORT_SYMBOL_GPL(tegra_asoc_utils_init); - -MODULE_AUTHOR("Stephen Warren "); -MODULE_DESCRIPTION("Tegra ASoC utility code"); -MODULE_LICENSE("GPL"); diff --git a/sound/soc/tegra/tegra_asoc_utils.h b/sound/soc/tegra/tegra_asoc_utils.h deleted file mode 100644 index bed2fdaa..00000000 --- a/sound/soc/tegra/tegra_asoc_utils.h +++ /dev/null @@ -1,53 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * tegra_asoc_utils.h - Definitions for Tegra DAS driver - * - * Author: Stephen Warren - * Copyright (c) 2010,2012-2022, NVIDIA CORPORATION. All rights reserved. - */ - -#ifndef __TEGRA_ASOC_UTILS_H__ -#define __TEGRA_ASOC_UTILS_H__ - -struct clk; -struct device; - -enum tegra_asoc_utils_soc { - TEGRA_ASOC_UTILS_SOC_TEGRA20, - TEGRA_ASOC_UTILS_SOC_TEGRA30, - TEGRA_ASOC_UTILS_SOC_TEGRA114, - TEGRA_ASOC_UTILS_SOC_TEGRA124, - TEGRA_ASOC_UTILS_SOC_TEGRA210, - TEGRA_ASOC_UTILS_SOC_TEGRA186, - TEGRA_ASOC_UTILS_SOC_TEGRA194, - TEGRA_ASOC_UTILS_SOC_TEGRA234, - TEGRA_ASOC_UTILS_SOC_TEGRA239, -}; - -struct tegra_asoc_utils_data { - struct device *dev; - enum tegra_asoc_utils_soc soc; - struct clk *clk_pll_a; - struct clk *clk_pll_a_out0; - struct clk *clk_cdev1; - int set_baseclock; - int set_mclk; - unsigned int set_pll_out; - unsigned int *pll_base_rate; - unsigned int mclk_fs; - bool fixed_pll; -}; - -int tegra_asoc_utils_set_rate(struct tegra_asoc_utils_data *data, int srate, - int mclk); -int tegra_asoc_utils_set_ac97_rate(struct tegra_asoc_utils_data *data); -int tegra_asoc_utils_set_tegra210_rate(struct tegra_asoc_utils_data *data, - unsigned int sample_rate, - unsigned int channels, - unsigned int sample_size); -int tegra_asoc_utils_clk_enable(struct tegra_asoc_utils_data *data); -void tegra_asoc_utils_clk_disable(struct tegra_asoc_utils_data *data); -int tegra_asoc_utils_init(struct tegra_asoc_utils_data *data, - struct device *dev); - -#endif diff --git a/sound/soc/tegra/tegra_codecs.c b/sound/soc/tegra/tegra_codecs.c deleted file mode 100644 index e16ec7d8..00000000 --- a/sound/soc/tegra/tegra_codecs.c +++ /dev/null @@ -1,287 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -// -// tegra_codecs.c - External audio codec setup -// -// Copyright (c) 2021-2023, NVIDIA CORPORATION. All rights reserved. - -#include - -#include -#include -#include -#include -#include - -#include "tegra_asoc_machine.h" -#include "tegra_codecs.h" - -#include -#include -#include - -static int tegra_audio_dai_init(struct snd_soc_pcm_runtime *rtd) -{ - /* Used for audio graph based sound cards only */ -#if defined(NV_ASOC_SIMPLE_RENAMED_SIMPLE) /* Linux 6.7 */ - if (rtd->card->component_chaining) - return simple_util_dai_init(rtd); -#else - if (rtd->card->component_chaining) - return asoc_simple_dai_init(rtd); -#endif - - return 0; -} - -static int tegra_machine_rt56xx_init(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_soc_component *cmpnt; - struct snd_soc_card *card = rtd->card; - struct snd_soc_jack *jack; - int err; - - cmpnt = rtd->dais[rtd->dai_link->num_cpus]->component; - if (!cmpnt->driver->set_jack) - goto dai_init; - - jack = devm_kzalloc(card->dev, sizeof(struct snd_soc_jack), GFP_KERNEL); - if (!jack) - return -ENOMEM; - -#if defined(NV_SND_SOC_CARD_JACK_NEW_HAS_NO_SND_SOC_JACK_PINS) /* Linux v5.19 */ - err = snd_soc_card_jack_new(card, "Headset Jack", SND_JACK_HEADSET, - jack); -#else - err = snd_soc_card_jack_new(card, "Headset Jack", SND_JACK_HEADSET, - jack, NULL, 0); -#endif - if (err) { - dev_err(card->dev, "Headset Jack creation failed %d\n", err); - return err; - } - - err = tegra_machine_add_codec_jack_control(card, rtd, jack); - if (err) { - dev_err(card->dev, "Failed to add jack control: %d\n", err); - return err; - } - - err = cmpnt->driver->set_jack(cmpnt, jack, NULL); - if (err) { - dev_err(cmpnt->dev, "Failed to set jack: %d\n", err); - return err; - } - - /* single button supporting play/pause */ - snd_jack_set_key(jack->jack, SND_JACK_BTN_0, KEY_MEDIA); - - /* multiple buttons supporting play/pause and volume up/down */ - snd_jack_set_key(jack->jack, SND_JACK_BTN_1, KEY_MEDIA); - snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEUP); - snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN); - - snd_soc_dapm_sync(&card->dapm); - - -dai_init: - return tegra_audio_dai_init(rtd); -} - -static int tegra_machine_fepi_init(struct snd_soc_pcm_runtime *rtd) -{ - struct device *dev = rtd->card->dev; - int err; - - err = snd_soc_dai_set_sysclk(rtd->dais[rtd->dai_link->num_cpus], - SGTL5000_SYSCLK, 12288000, - SND_SOC_CLOCK_IN); - if (err) { - dev_err(dev, "failed to set sgtl5000 sysclk!\n"); - return err; - } - - return tegra_audio_dai_init(rtd); -} - -static int tegra_machine_respeaker_init(struct snd_soc_pcm_runtime *rtd) -{ - struct device *dev = rtd->card->dev; - int err; - - /* ac108 codec driver hardcodes the freq as 24000000 - * and source as PLL irrespective of args passed through - * this callback - */ - err = snd_soc_dai_set_sysclk(rtd->dais[rtd->dai_link->num_cpus], - 0, 24000000, SND_SOC_CLOCK_IN); - if (err) { - dev_err(dev, "failed to set ac108 sysclk!\n"); - return err; - } - - return tegra_audio_dai_init(rtd); -} - -static struct snd_soc_pcm_runtime *get_pcm_runtime(struct snd_soc_card *card, - const char *link_name) -{ - struct snd_soc_pcm_runtime *rtd; - - for_each_card_rtds(card, rtd) { - if (!strcmp(rtd->dai_link->name, link_name)) - return rtd; - } - - return NULL; -} - -static int set_pll_sysclk(struct device *dev, struct snd_soc_pcm_runtime *rtd, - int pll_src, int clk_id, unsigned int srate, - unsigned int channels) -{ - struct snd_soc_pcm_stream *dai_params; - unsigned int bclk_rate; - int err; - -#if defined(NV_SND_SOC_DAI_LINK_STRUCT_HAS_C2C_PARAMS_ARG) /* Linux v6.4 */ - dai_params = (struct snd_soc_pcm_stream *)rtd->dai_link->c2c_params; -#else - dai_params = (struct snd_soc_pcm_stream *)rtd->dai_link->params; -#endif - - switch (dai_params->formats) { - case SNDRV_PCM_FMTBIT_S8: - bclk_rate = srate * channels * 8; - break; - case SNDRV_PCM_FMTBIT_S16_LE: - bclk_rate = srate * channels * 16; - break; - case SNDRV_PCM_FMTBIT_S24_LE: - bclk_rate = srate * channels * 24; - break; - case SNDRV_PCM_FMTBIT_S32_LE: - bclk_rate = srate * channels * 32; - break; - default: - dev_err(dev, "invalid format %llu\n", - dai_params->formats); - return -EINVAL; - } - - err = snd_soc_dai_set_pll(rtd->dais[rtd->dai_link->num_cpus], 0, - pll_src, bclk_rate, srate * 256); - if (err < 0) { - dev_err(dev, "failed to set codec pll\n"); - return err; - } - - err = snd_soc_dai_set_sysclk(rtd->dais[rtd->dai_link->num_cpus], clk_id, - srate * 256, SND_SOC_CLOCK_IN); - if (err < 0) { - dev_err(dev, "dais[%d] clock not set\n", - rtd->dai_link->num_cpus); - return err; - } - - return 0; -} - -int tegra_codecs_runtime_setup(struct snd_soc_card *card, - unsigned int srate, - unsigned int channels, - unsigned int aud_mclk) -{ - struct snd_soc_pcm_runtime *rtd; - int i, err; - - rtd = get_pcm_runtime(card, "rt565x-playback"); - if (rtd) { - err = snd_soc_dai_set_sysclk(rtd->dais[rtd->dai_link->num_cpus], - RT5659_SCLK_S_MCLK, - aud_mclk, SND_SOC_CLOCK_IN); - if (err < 0) { - dev_err(card->dev, "dais[%d] clock not set\n", - rtd->dai_link->num_cpus); - return err; - } - } - - rtd = get_pcm_runtime(card, "rt5640-playback"); - if (rtd) { - err = snd_soc_dai_set_sysclk(rtd->dais[rtd->dai_link->num_cpus], - RT5640_SCLK_S_MCLK, - aud_mclk, SND_SOC_CLOCK_IN); - if (err < 0) { - dev_err(card->dev, "dais[%d] clock not set\n", - rtd->dai_link->num_cpus); - return err; - } - } - - rtd = get_pcm_runtime(card, "rt565x-codec-sysclk-bclk1"); - if (rtd) { - err = set_pll_sysclk(card->dev, rtd, RT5659_PLL1_S_BCLK1, - RT5659_SCLK_S_PLL1, srate, channels); - if (err < 0) { - dev_err(card->dev, "failed to set pll clk\n"); - return err; - } - } - - rtd = get_pcm_runtime(card, "rt5640-codec-sysclk-bclk1"); - if (rtd) { - err = set_pll_sysclk(card->dev, rtd, RT5640_PLL1_S_BCLK1, - RT5640_SCLK_S_PLL1, srate, channels); - if (err < 0) { - dev_err(card->dev, "failed to set pll clk\n"); - return err; - } - } - - rtd = get_pcm_runtime(card, "dspk-playback-dual-tas2552"); - if (rtd) { - for (i = 0; i < rtd->dai_link->num_codecs; i++) { - if (!strcmp(rtd->dais[rtd->dai_link->num_cpus + i]->name, - "tas2552-amplifier")) { - err = snd_soc_dai_set_sysclk( - rtd->dais[rtd->dai_link->num_cpus + i], - TAS2552_PDM_CLK_IVCLKIN, aud_mclk, - SND_SOC_CLOCK_IN); - if (err < 0) { - dev_err(card->dev, - "dais[%d] clock not set\n", - rtd->dai_link->num_cpus + i); - return err; - } - } - } - } - - return 0; -} -EXPORT_SYMBOL_GPL(tegra_codecs_runtime_setup); - -int tegra_codecs_init(struct snd_soc_card *card) -{ - struct snd_soc_dai_link *dai_links = card->dai_link; - int i; - - if (!dai_links || !card->num_links) - return -EINVAL; - - for (i = 0; i < card->num_links; i++) { - if (strstr(dai_links[i].name, "rt565x-playback") || - strstr(dai_links[i].name, "rt5640-playback") || - strstr(dai_links[i].name, "rt565x-codec-sysclk-bclk1") || - strstr(dai_links[i].name, "rt5640-codec-sysclk-bclk1")) - dai_links[i].init = tegra_machine_rt56xx_init; - else if (strstr(dai_links[i].name, "fe-pi-audio-z-v2")) - dai_links[i].init = tegra_machine_fepi_init; - else if (strstr(dai_links[i].name, "respeaker-4-mic-array")) - dai_links[i].init = tegra_machine_respeaker_init; - } - - return 0; -} -EXPORT_SYMBOL_GPL(tegra_codecs_init); - diff --git a/sound/soc/tegra/tegra_codecs.h b/sound/soc/tegra/tegra_codecs.h deleted file mode 100644 index 02594725..00000000 --- a/sound/soc/tegra/tegra_codecs.h +++ /dev/null @@ -1,21 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * tegra_codec.h - * - * Copyright (c) 2021 NVIDIA CORPORATION. All rights reserved. - * - */ - -#ifndef __TEGRA_CODECS_H__ -#define __TEGRA_CODECS_H__ - -#include - -int tegra_codecs_init(struct snd_soc_card *card); - -int tegra_codecs_runtime_setup(struct snd_soc_card *card, - unsigned int srate, - unsigned int channels, - unsigned int aud_mclk); - -#endif diff --git a/sound/soc/tegra/tegra_machine_driver.c b/sound/soc/tegra/tegra_machine_driver.c deleted file mode 100644 index 640acd68..00000000 --- a/sound/soc/tegra/tegra_machine_driver.c +++ /dev/null @@ -1,489 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -// SPDX-FileCopyrightText: Copyright (c) 2017-2024 NVIDIA CORPORATION. All rights reserved. -// -// tegra_machine_driver.c - Tegra ASoC Machine driver - -#include - -#include -#include -#include -#include -#include -#include -#include -#include "tegra_asoc_machine.h" -#include "tegra_codecs.h" - -#define DRV_NAME "tegra-asoc:" - -static const char * const tegra_machine_srate_text[] = { - "None", - "8kHz", - "16kHz", - "44kHz", - "48kHz", - "11kHz", - "22kHz", - "24kHz", - "32kHz", - "88kHz", - "96kHz", - "176kHz", - "192kHz", -}; - -static const char * const tegra_machine_format_text[] = { - "None", - "16", - "32", -}; - -static const struct soc_enum tegra_machine_codec_rate = - SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(tegra_machine_srate_text), - tegra_machine_srate_text); - -static const struct soc_enum tegra_machine_codec_format = - SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(tegra_machine_format_text), - tegra_machine_format_text); - -static const int tegra_machine_srate_values[] = { - 0, - 8000, - 16000, - 44100, - 48000, - 11025, - 22050, - 24000, - 32000, - 88200, - 96000, - 176400, - 192000, -}; - -static int tegra_machine_codec_get_rate(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_card *card = snd_kcontrol_chip(kcontrol); - struct tegra_machine *machine = snd_soc_card_get_drvdata(card); - - ucontrol->value.integer.value[0] = machine->rate_via_kcontrol; - - return 0; -} - -static int tegra_machine_codec_put_rate(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_card *card = snd_kcontrol_chip(kcontrol); - struct tegra_machine *machine = snd_soc_card_get_drvdata(card); - - /* set the rate control flag */ - machine->rate_via_kcontrol = ucontrol->value.integer.value[0]; - - return 0; -} - -static int tegra_machine_codec_get_format(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_card *card = snd_kcontrol_chip(kcontrol); - struct tegra_machine *machine = snd_soc_card_get_drvdata(card); - - ucontrol->value.integer.value[0] = machine->fmt_via_kcontrol; - - return 0; -} - -static int tegra_machine_codec_put_format(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_card *card = snd_kcontrol_chip(kcontrol); - struct tegra_machine *machine = snd_soc_card_get_drvdata(card); - - /* set the format control flag */ - machine->fmt_via_kcontrol = ucontrol->value.integer.value[0]; - - return 0; -} - -static int tegra_machine_dai_init(struct snd_soc_pcm_runtime *runtime, - unsigned int rate, unsigned int channels, - u64 formats, - struct snd_pcm_hw_params *pcm_params) -{ - unsigned int mask = (1 << channels) - 1; - struct snd_soc_card *card = runtime->card; - struct tegra_machine *machine = snd_soc_card_get_drvdata(card); - struct snd_soc_pcm_stream *dai_params; - unsigned int aud_mclk, srate; - u64 format_k, fmt; - int err, sample_size; - struct snd_soc_pcm_runtime *rtd; - - srate = (machine->rate_via_kcontrol) ? - tegra_machine_srate_values[machine->rate_via_kcontrol] : - rate; - format_k = (machine->fmt_via_kcontrol == 2) ? - (1ULL << SNDRV_PCM_FORMAT_S32_LE) : (1 << formats); - switch (formats) { - case SNDRV_PCM_FORMAT_S8: - sample_size = 8; - break; - case SNDRV_PCM_FORMAT_S16_LE: - sample_size = 16; - break; - case SNDRV_PCM_FORMAT_S24_LE: - /* - * I2S bit clock is derived from PLLA_OUT0 and size of - * 24 bits results in fractional value and the clock - * is not accurate with this. To have integer clock - * division below is used. It means there are additional - * bit clocks (8 cycles) which are ignored. Codec picks - * up data for other channel when LRCK signal toggles. - */ - case SNDRV_PCM_FORMAT_S32_LE: - sample_size = 32; - break; - default: - pr_err("Wrong format!\n"); - return -EINVAL; - } - - err = tegra_asoc_utils_set_tegra210_rate(&machine->audio_clock, srate, - channels, sample_size); - if (err < 0) { - dev_err(card->dev, "Can't configure clocks\n"); - return err; - } - - aud_mclk = machine->audio_clock.set_mclk; - - pr_debug("pll_a_out0 = %u Hz, aud_mclk = %u Hz, sample rate = %u Hz\n", - machine->audio_clock.set_pll_out, aud_mclk, srate); - - list_for_each_entry(rtd, &card->rtd_list, list) { - /* fixup PCM params */ - if (pcm_params && rtd->dai_link->be_hw_params_fixup) { - struct snd_pcm_hw_params new_params = *pcm_params; - - err = rtd->dai_link->be_hw_params_fixup(rtd, &new_params); - if (err) { - dev_err(rtd->card->dev, "fixup failed for link %s\n", - rtd->dai_link->name); - return err; - } - - srate = params_rate(&new_params); - channels = params_channels(&new_params); - format_k = 1 << params_format(&new_params); - } - -#if defined(NV_SND_SOC_DAI_LINK_STRUCT_HAS_C2C_PARAMS_ARG) /* Linux v6.4 */ - if (!rtd->dai_link->c2c_params) - continue; - dai_params = (struct snd_soc_pcm_stream *)rtd->dai_link->c2c_params; -#else - if (!rtd->dai_link->params) - continue; - dai_params = (struct snd_soc_pcm_stream *)rtd->dai_link->params; -#endif - dai_params->rate_min = srate; - dai_params->channels_min = channels; - dai_params->formats = format_k; - - fmt = rtd->dai_link->dai_fmt & SND_SOC_DAIFMT_FORMAT_MASK; - /* set TDM slot mask */ - if (fmt == SND_SOC_DAIFMT_DSP_A || - fmt == SND_SOC_DAIFMT_DSP_B) { - err = snd_soc_dai_set_tdm_slot( - rtd->dais[0], mask, - mask, 0, 0); - if (err < 0) { - dev_err(card->dev, - "%s cpu DAI slot mask not set\n", - rtd->dais[0]->name); - return err; - } - } - } - - return tegra_codecs_runtime_setup(card, srate, channels, aud_mclk); -} - -static int tegra_machine_pcm_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_card *card = rtd->card; - int err; - - err = tegra_machine_dai_init(rtd, params_rate(params), - params_channels(params), - params_format(params), - params); - if (err < 0) { - dev_err(card->dev, "Failed dai init\n"); - return err; - } - - return 0; -} - -static int tegra_machine_pcm_startup(struct snd_pcm_substream *substream) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct tegra_machine *machine = snd_soc_card_get_drvdata(rtd->card); - - tegra_asoc_utils_clk_enable(&machine->audio_clock); - - return 0; -} - -static void tegra_machine_pcm_shutdown(struct snd_pcm_substream *substream) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct tegra_machine *machine = snd_soc_card_get_drvdata(rtd->card); - - tegra_asoc_utils_clk_disable(&machine->audio_clock); -} - -static int tegra_machine_compr_startup(struct snd_compr_stream *cstream) -{ - struct snd_soc_pcm_runtime *rtd = cstream->private_data; - struct snd_soc_card *card = rtd->card; - struct tegra_machine *machine = snd_soc_card_get_drvdata(card); - - tegra_asoc_utils_clk_enable(&machine->audio_clock); - - return 0; -} - -static void tegra_machine_compr_shutdown(struct snd_compr_stream *cstream) -{ - struct snd_soc_pcm_runtime *rtd = cstream->private_data; - struct snd_soc_card *card = rtd->card; - struct tegra_machine *machine = snd_soc_card_get_drvdata(card); - - tegra_asoc_utils_clk_disable(&machine->audio_clock); -} - -static int tegra_machine_compr_set_params(struct snd_compr_stream *cstream) -{ - struct snd_soc_pcm_runtime *rtd = cstream->private_data; - struct snd_soc_card *card = rtd->card; - struct snd_codec codec_params; - int err; - - if (cstream->ops && cstream->ops->get_params) { - err = cstream->ops->get_params(cstream, &codec_params); - if (err < 0) { - dev_err(card->dev, "Failed to get compr params\n"); - return err; - } - } else { - dev_err(card->dev, "compr ops not set\n"); - return -EINVAL; - } - - err = tegra_machine_dai_init(rtd, codec_params.sample_rate, - codec_params.ch_out, - SNDRV_PCM_FORMAT_S16_LE, - NULL); - if (err < 0) { - dev_err(card->dev, "Failed dai init\n"); - return err; - } - - return 0; -} - -static struct snd_soc_ops tegra_machine_pcm_ops = { - .hw_params = tegra_machine_pcm_hw_params, - .startup = tegra_machine_pcm_startup, - .shutdown = tegra_machine_pcm_shutdown, -}; - -static struct snd_soc_compr_ops tegra_machine_compr_ops = { - .set_params = tegra_machine_compr_set_params, - .startup = tegra_machine_compr_startup, - .shutdown = tegra_machine_compr_shutdown, -}; - -static int add_dai_links(struct snd_soc_card *card) -{ - int ret; - - ret = parse_card_info(card, &tegra_machine_pcm_ops, - &tegra_machine_compr_ops); - if (ret < 0) - return ret; - - ret = tegra_codecs_init(card); - if (ret < 0) - return ret; - - return 0; -} - -static const struct snd_kcontrol_new tegra_machine_controls[] = { - SOC_ENUM_EXT("codec-x rate", tegra_machine_codec_rate, - tegra_machine_codec_get_rate, tegra_machine_codec_put_rate), - SOC_ENUM_EXT("codec-x format", tegra_machine_codec_format, - tegra_machine_codec_get_format, tegra_machine_codec_put_format), -}; - -static struct snd_soc_card snd_soc_tegra_card = { - .owner = THIS_MODULE, - .controls = tegra_machine_controls, - .num_controls = ARRAY_SIZE(tegra_machine_controls), - .fully_routed = true, - .driver_name = "tegra-ape", -}; - -static struct snd_soc_dai_driver tegra_dummy_dai = { - .name = "tegra-snd-dummy-dai", - .playback = { - .stream_name = "Dummy Playback", - .channels_min = 1, - .channels_max = 32, - .rates = SNDRV_PCM_RATE_8000_192000, - .formats = SNDRV_PCM_FMTBIT_S8 | - SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S32_LE, - }, - .capture = { - .stream_name = "Dummy Capture", - .channels_min = 1, - .channels_max = 32, - .rates = SNDRV_PCM_RATE_8000_192000, - .formats = SNDRV_PCM_FMTBIT_S8 | - SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S32_LE, - }, -}; - -static const struct snd_soc_dapm_widget tegra_dummy_widgets[] = { - SND_SOC_DAPM_MIC("Dummy MIC", NULL), - SND_SOC_DAPM_SPK("Dummy SPK", NULL), -}; - -static const struct snd_soc_dapm_route tegra_dummy_routes[] = { - {"Dummy SPK", NULL, "Dummy Playback"}, - {"Dummy Capture", NULL, "Dummy MIC"}, -}; - -static const struct snd_soc_component_driver tegra_dummy_component = { - .dapm_widgets = tegra_dummy_widgets, - .num_dapm_widgets = ARRAY_SIZE(tegra_dummy_widgets), - .dapm_routes = tegra_dummy_routes, - .num_dapm_routes = ARRAY_SIZE(tegra_dummy_routes), - .endianness = 1, -}; - -/* structure to match device tree node */ -static const struct of_device_id tegra_machine_of_match[] = { - { .compatible = "nvidia,tegra186-ape" }, - { .compatible = "nvidia,tegra210-ape" }, - {}, -}; - -static int tegra_machine_driver_probe(struct platform_device *pdev) -{ - struct snd_soc_card *card = &snd_soc_tegra_card; - struct tegra_machine *machine; - int ret = 0; - - machine = devm_kzalloc(&pdev->dev, sizeof(*machine), GFP_KERNEL); - if (!machine) - return -ENOMEM; - - machine->asoc = devm_kzalloc(&pdev->dev, sizeof(*machine->asoc), - GFP_KERNEL); - if (!machine->asoc) - return -ENOMEM; - - card->dev = &pdev->dev; - platform_set_drvdata(pdev, card); - snd_soc_card_set_drvdata(card, machine); - - card->dapm.idle_bias_off = true; - - memset(&machine->audio_clock, 0, sizeof(machine->audio_clock)); - ret = tegra_asoc_utils_init(&machine->audio_clock, &pdev->dev); - if (ret < 0) - return ret; - - ret = devm_snd_soc_register_component(&pdev->dev, &tegra_dummy_component, - &tegra_dummy_dai, 1); - if (ret < 0) { - dev_err(&pdev->dev, "Tegra dummy component registration fails\n"); - return ret; - } - - ret = add_dai_links(card); - if (ret < 0) - goto cleanup_asoc; - - ret = snd_soc_register_card(card); - if (ret) { - dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", - ret); - goto cleanup_asoc; - } - - tegra_machine_add_i2s_codec_controls(card); - - of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev); - - dev_info(&pdev->dev, "Registered legacy APE sound card\n"); - - return 0; -cleanup_asoc: - release_asoc_phandles(machine); - return ret; -} - -static int tegra_machine_driver_remove(struct platform_device *pdev) -{ - struct snd_soc_card *card = platform_get_drvdata(pdev); - - snd_soc_unregister_card(card); - - return 0; -} - -#if CONFIG_PM -static void tegra_asoc_machine_resume(struct device *dev) -{ - WARN_ON(snd_soc_resume(dev)); -} -#else -#define tegra_asoc_machine_resume NULL -#endif - -static const struct dev_pm_ops tegra_asoc_machine_pm_ops = { - .prepare = snd_soc_suspend, - .complete = tegra_asoc_machine_resume, - .poweroff = snd_soc_poweroff, -}; - -static struct platform_driver tegra_asoc_machine_driver = { - .driver = { - .name = DRV_NAME, - .owner = THIS_MODULE, - .pm = &tegra_asoc_machine_pm_ops, - .of_match_table = tegra_machine_of_match, - }, - .probe = tegra_machine_driver_probe, - .remove = tegra_machine_driver_remove, -}; -module_platform_driver(tegra_asoc_machine_driver); - -MODULE_AUTHOR("Mohan Kumar , Sameer Pujar "); -MODULE_DESCRIPTION("Tegra ASoC machine driver"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:" DRV_NAME); -MODULE_DEVICE_TABLE(of, tegra_machine_of_match);