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);