1 // SPDX-License-Identifier: GPL-2.0-only 2 // SPDX-FileCopyrightText: Copyright (c) 2020-2025 NVIDIA CORPORATION. All rights reserved. 3 // 4 // tegra_audio_graph_card.c - Audio Graph based Tegra Machine Driver 5 6 #include <linux/math64.h> 7 #include <linux/module.h> 8 #include <linux/of.h> 9 #include <linux/platform_device.h> 10 #include <sound/graph_card.h> 11 #include <sound/pcm_params.h> 12 #include <sound/soc-dai.h> 13 14 #define MAX_PLLA_OUT0_DIV 128 15 16 #define simple_to_tegra_priv(simple) \ 17 container_of(simple, struct tegra_audio_priv, simple) 18 19 enum srate_type { 20 /* 21 * Sample rates multiple of 8000 Hz and below are supported: 22 * ( 8000, 16000, 32000, 48000, 96000, 192000 Hz ) 23 */ 24 x8_RATE, 25 26 /* 27 * Sample rates multiple of 11025 Hz and below are supported: 28 * ( 11025, 22050, 44100, 88200, 176400 Hz ) 29 */ 30 x11_RATE, 31 32 NUM_RATE_TYPE, 33 }; 34 35 struct tegra_audio_priv { 36 struct simple_util_priv simple; 37 struct clk *clk_plla_out0; 38 struct clk *clk_plla; 39 }; 40 41 /* Tegra audio chip data */ 42 struct tegra_audio_cdata { 43 unsigned int plla_rates[NUM_RATE_TYPE]; 44 unsigned int plla_out0_rates[NUM_RATE_TYPE]; 45 }; 46 47 static bool need_clk_update(struct snd_soc_dai *dai) 48 { 49 if (snd_soc_dai_is_dummy(dai) || 50 !dai->driver->ops || 51 !dai->driver->name) 52 return false; 53 54 if (strstr(dai->driver->name, "I2S") || 55 strstr(dai->driver->name, "DMIC") || 56 strstr(dai->driver->name, "DSPK")) 57 return true; 58 59 return false; 60 } 61 62 /* Setup PLL clock as per the given sample rate */ 63 static int tegra_audio_graph_update_pll(struct snd_pcm_substream *substream, 64 struct snd_pcm_hw_params *params) 65 { 66 struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); 67 struct simple_util_priv *simple = snd_soc_card_get_drvdata(rtd->card); 68 struct tegra_audio_priv *priv = simple_to_tegra_priv(simple); 69 struct device *dev = rtd->card->dev; 70 const struct tegra_audio_cdata *data = of_device_get_match_data(dev); 71 unsigned int plla_rate, plla_out0_rate, bclk; 72 unsigned int srate = params_rate(params); 73 int err; 74 75 switch (srate) { 76 case 11025: 77 case 22050: 78 case 44100: 79 case 88200: 80 case 176400: 81 plla_out0_rate = data->plla_out0_rates[x11_RATE]; 82 plla_rate = data->plla_rates[x11_RATE]; 83 break; 84 case 8000: 85 case 16000: 86 case 32000: 87 case 48000: 88 case 96000: 89 case 192000: 90 plla_out0_rate = data->plla_out0_rates[x8_RATE]; 91 plla_rate = data->plla_rates[x8_RATE]; 92 break; 93 default: 94 dev_err(rtd->card->dev, "Unsupported sample rate %u\n", 95 srate); 96 return -EINVAL; 97 } 98 99 /* 100 * Below is the clock relation: 101 * 102 * PLLA 103 * | 104 * |--> PLLA_OUT0 105 * | 106 * |---> I2S modules 107 * | 108 * |---> DMIC modules 109 * | 110 * |---> DSPK modules 111 * 112 * 113 * Default PLLA_OUT0 rate might be too high when I/O is running 114 * at minimum PCM configurations. This may result in incorrect 115 * clock rates and glitchy audio. The maximum divider is 128 116 * and any thing higher than that won't work. Thus reduce PLLA_OUT0 117 * to work for lower configurations. 118 * 119 * This problem is seen for I2S only, as DMIC and DSPK minimum 120 * clock requirements are under allowed divider limits. 121 */ 122 bclk = srate * params_channels(params) * params_width(params); 123 if (div_u64(plla_out0_rate, bclk) > MAX_PLLA_OUT0_DIV) 124 plla_out0_rate >>= 1; 125 126 dev_dbg(rtd->card->dev, 127 "Update clock rates: PLLA(= %u Hz) and PLLA_OUT0(= %u Hz)\n", 128 plla_rate, plla_out0_rate); 129 130 /* Set PLLA rate */ 131 err = clk_set_rate(priv->clk_plla, plla_rate); 132 if (err) { 133 dev_err(rtd->card->dev, 134 "Can't set plla rate for %u, err: %d\n", 135 plla_rate, err); 136 return err; 137 } 138 139 /* Set PLLA_OUT0 rate */ 140 err = clk_set_rate(priv->clk_plla_out0, plla_out0_rate); 141 if (err) { 142 dev_err(rtd->card->dev, 143 "Can't set plla_out0 rate %u, err: %d\n", 144 plla_out0_rate, err); 145 return err; 146 } 147 148 return err; 149 } 150 151 static int tegra_audio_graph_hw_params(struct snd_pcm_substream *substream, 152 struct snd_pcm_hw_params *params) 153 { 154 struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); 155 struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); 156 int err; 157 158 if (need_clk_update(cpu_dai)) { 159 err = tegra_audio_graph_update_pll(substream, params); 160 if (err) 161 return err; 162 } 163 164 return simple_util_hw_params(substream, params); 165 } 166 167 static const struct snd_soc_ops tegra_audio_graph_ops = { 168 .startup = simple_util_startup, 169 .shutdown = simple_util_shutdown, 170 .hw_params = tegra_audio_graph_hw_params, 171 }; 172 173 static int tegra_audio_graph_card_probe(struct snd_soc_card *card) 174 { 175 struct simple_util_priv *simple = snd_soc_card_get_drvdata(card); 176 struct tegra_audio_priv *priv = simple_to_tegra_priv(simple); 177 178 priv->clk_plla = devm_clk_get(card->dev, "pll_a"); 179 if (IS_ERR(priv->clk_plla)) { 180 dev_err(card->dev, "Can't retrieve clk pll_a\n"); 181 return PTR_ERR(priv->clk_plla); 182 } 183 184 priv->clk_plla_out0 = devm_clk_get(card->dev, "plla_out0"); 185 if (IS_ERR(priv->clk_plla_out0)) { 186 dev_err(card->dev, "Can't retrieve clk plla_out0\n"); 187 return PTR_ERR(priv->clk_plla_out0); 188 } 189 190 return graph_util_card_probe(card); 191 } 192 193 static int tegra_audio_graph_probe(struct platform_device *pdev) 194 { 195 struct tegra_audio_priv *priv; 196 struct device *dev = &pdev->dev; 197 struct snd_soc_card *card; 198 199 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 200 if (!priv) 201 return -ENOMEM; 202 203 card = simple_priv_to_card(&priv->simple); 204 card->driver_name = "tegra-ape"; 205 206 card->probe = tegra_audio_graph_card_probe; 207 208 /* audio_graph_parse_of() depends on below */ 209 card->component_chaining = 1; 210 priv->simple.ops = &tegra_audio_graph_ops; 211 priv->simple.force_dpcm = 1; 212 213 return audio_graph_parse_of(&priv->simple, dev); 214 } 215 216 static const struct tegra_audio_cdata tegra210_data = { 217 /* PLLA */ 218 .plla_rates[x8_RATE] = 368640000, 219 .plla_rates[x11_RATE] = 338688000, 220 /* PLLA_OUT0 */ 221 .plla_out0_rates[x8_RATE] = 49152000, 222 .plla_out0_rates[x11_RATE] = 45158400, 223 }; 224 225 static const struct tegra_audio_cdata tegra186_data = { 226 /* PLLA */ 227 .plla_rates[x8_RATE] = 245760000, 228 .plla_rates[x11_RATE] = 270950400, 229 /* PLLA_OUT0 */ 230 .plla_out0_rates[x8_RATE] = 49152000, 231 .plla_out0_rates[x11_RATE] = 45158400, 232 }; 233 234 static const struct tegra_audio_cdata tegra264_data = { 235 /* PLLA1 */ 236 .plla_rates[x8_RATE] = 983040000, 237 .plla_rates[x11_RATE] = 993484800, 238 /* PLLA1_OUT1 */ 239 .plla_out0_rates[x8_RATE] = 49152000, 240 .plla_out0_rates[x11_RATE] = 45158400, 241 }; 242 243 static const struct of_device_id graph_of_tegra_match[] = { 244 { .compatible = "nvidia,tegra210-audio-graph-card", 245 .data = &tegra210_data }, 246 { .compatible = "nvidia,tegra186-audio-graph-card", 247 .data = &tegra186_data }, 248 { .compatible = "nvidia,tegra264-audio-graph-card", 249 .data = &tegra264_data }, 250 {}, 251 }; 252 MODULE_DEVICE_TABLE(of, graph_of_tegra_match); 253 254 static struct platform_driver tegra_audio_graph_card = { 255 .driver = { 256 .name = "tegra-audio-graph-card", 257 .pm = &snd_soc_pm_ops, 258 .of_match_table = graph_of_tegra_match, 259 }, 260 .probe = tegra_audio_graph_probe, 261 .remove = simple_util_remove, 262 }; 263 module_platform_driver(tegra_audio_graph_card); 264 265 MODULE_LICENSE("GPL v2"); 266 MODULE_DESCRIPTION("ASoC Tegra Audio Graph Sound Card"); 267 MODULE_AUTHOR("Sameer Pujar <spujar@nvidia.com>"); 268