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