1 // SPDX-License-Identifier: GPL-2.0 2 // 3 // Copyright (C) 2017 Samsung Electronics Co., Ltd. 4 5 #include <linux/clk.h> 6 #include <linux/clk-provider.h> 7 #include <linux/of.h> 8 #include <linux/of_device.h> 9 #include <linux/module.h> 10 #include <sound/soc.h> 11 #include <sound/pcm_params.h> 12 #include "i2s.h" 13 #include "i2s-regs.h" 14 15 struct odroid_priv { 16 struct snd_soc_card card; 17 struct clk *clk_i2s_bus; 18 struct clk *sclk_i2s; 19 20 /* Spinlock protecting fields below */ 21 spinlock_t lock; 22 unsigned int be_sample_rate; 23 bool be_active; 24 }; 25 26 static int odroid_card_fe_startup(struct snd_pcm_substream *substream) 27 { 28 struct snd_pcm_runtime *runtime = substream->runtime; 29 30 snd_pcm_hw_constraint_single(runtime, SNDRV_PCM_HW_PARAM_CHANNELS, 2); 31 32 return 0; 33 } 34 35 static int odroid_card_fe_hw_params(struct snd_pcm_substream *substream, 36 struct snd_pcm_hw_params *params) 37 { 38 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 39 struct odroid_priv *priv = snd_soc_card_get_drvdata(rtd->card); 40 unsigned long flags; 41 int ret = 0; 42 43 spin_lock_irqsave(&priv->lock, flags); 44 if (priv->be_active && priv->be_sample_rate != params_rate(params)) 45 ret = -EINVAL; 46 spin_unlock_irqrestore(&priv->lock, flags); 47 48 return ret; 49 } 50 51 static const struct snd_soc_ops odroid_card_fe_ops = { 52 .startup = odroid_card_fe_startup, 53 .hw_params = odroid_card_fe_hw_params, 54 }; 55 56 static int odroid_card_be_hw_params(struct snd_pcm_substream *substream, 57 struct snd_pcm_hw_params *params) 58 { 59 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 60 struct odroid_priv *priv = snd_soc_card_get_drvdata(rtd->card); 61 unsigned int pll_freq, rclk_freq, rfs; 62 unsigned long flags; 63 int ret; 64 65 switch (params_rate(params)) { 66 case 64000: 67 pll_freq = 196608001U; 68 rfs = 384; 69 break; 70 case 44100: 71 case 88200: 72 pll_freq = 180633609U; 73 rfs = 512; 74 break; 75 case 32000: 76 case 48000: 77 case 96000: 78 pll_freq = 196608001U; 79 rfs = 512; 80 break; 81 default: 82 return -EINVAL; 83 } 84 85 ret = clk_set_rate(priv->clk_i2s_bus, pll_freq / 2 + 1); 86 if (ret < 0) 87 return ret; 88 89 /* 90 * We add 2 to the rclk_freq value in order to avoid too low clock 91 * frequency values due to the EPLL output frequency not being exact 92 * multiple of the audio sampling rate. 93 */ 94 rclk_freq = params_rate(params) * rfs + 2; 95 96 ret = clk_set_rate(priv->sclk_i2s, rclk_freq); 97 if (ret < 0) 98 return ret; 99 100 if (rtd->dai_link->num_codecs > 1) { 101 struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 1); 102 103 ret = snd_soc_dai_set_sysclk(codec_dai, 0, rclk_freq, 104 SND_SOC_CLOCK_IN); 105 if (ret < 0) 106 return ret; 107 } 108 109 spin_lock_irqsave(&priv->lock, flags); 110 priv->be_sample_rate = params_rate(params); 111 spin_unlock_irqrestore(&priv->lock, flags); 112 113 return 0; 114 } 115 116 static int odroid_card_be_trigger(struct snd_pcm_substream *substream, int cmd) 117 { 118 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 119 struct odroid_priv *priv = snd_soc_card_get_drvdata(rtd->card); 120 unsigned long flags; 121 122 spin_lock_irqsave(&priv->lock, flags); 123 124 switch (cmd) { 125 case SNDRV_PCM_TRIGGER_START: 126 case SNDRV_PCM_TRIGGER_RESUME: 127 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 128 priv->be_active = true; 129 break; 130 131 case SNDRV_PCM_TRIGGER_STOP: 132 case SNDRV_PCM_TRIGGER_SUSPEND: 133 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 134 priv->be_active = false; 135 break; 136 } 137 138 spin_unlock_irqrestore(&priv->lock, flags); 139 140 return 0; 141 } 142 143 static const struct snd_soc_ops odroid_card_be_ops = { 144 .hw_params = odroid_card_be_hw_params, 145 .trigger = odroid_card_be_trigger, 146 }; 147 148 /* DAPM routes for backward compatibility with old DTS */ 149 static const struct snd_soc_dapm_route odroid_dapm_routes[] = { 150 { "I2S Playback", NULL, "Mixer DAI TX" }, 151 { "HiFi Playback", NULL, "Mixer DAI TX" }, 152 }; 153 154 SND_SOC_DAILINK_DEFS(primary, 155 DAILINK_COMP_ARRAY(COMP_EMPTY()), 156 DAILINK_COMP_ARRAY(COMP_DUMMY()), 157 DAILINK_COMP_ARRAY(COMP_PLATFORM("3830000.i2s"))); 158 159 SND_SOC_DAILINK_DEFS(mixer, 160 DAILINK_COMP_ARRAY(COMP_DUMMY()), 161 DAILINK_COMP_ARRAY(COMP_EMPTY()), 162 DAILINK_COMP_ARRAY(COMP_DUMMY())); 163 164 SND_SOC_DAILINK_DEFS(secondary, 165 DAILINK_COMP_ARRAY(COMP_EMPTY()), 166 DAILINK_COMP_ARRAY(COMP_DUMMY()), 167 DAILINK_COMP_ARRAY(COMP_PLATFORM("3830000.i2s-sec"))); 168 169 static struct snd_soc_dai_link odroid_card_dais[] = { 170 { 171 /* Primary FE <-> BE link */ 172 .ops = &odroid_card_fe_ops, 173 .name = "Primary", 174 .stream_name = "Primary", 175 .dynamic = 1, 176 .dpcm_playback = 1, 177 SND_SOC_DAILINK_REG(primary), 178 }, { 179 /* BE <-> CODECs link */ 180 .name = "I2S Mixer", 181 .ops = &odroid_card_be_ops, 182 .no_pcm = 1, 183 .dpcm_playback = 1, 184 .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | 185 SND_SOC_DAIFMT_CBS_CFS, 186 SND_SOC_DAILINK_REG(mixer), 187 }, { 188 /* Secondary FE <-> BE link */ 189 .playback_only = 1, 190 .ops = &odroid_card_fe_ops, 191 .name = "Secondary", 192 .stream_name = "Secondary", 193 .dynamic = 1, 194 .dpcm_playback = 1, 195 SND_SOC_DAILINK_REG(secondary), 196 } 197 }; 198 199 static int odroid_audio_probe(struct platform_device *pdev) 200 { 201 struct device *dev = &pdev->dev; 202 struct device_node *cpu_dai = NULL; 203 struct device_node *cpu, *codec; 204 struct odroid_priv *priv; 205 struct snd_soc_card *card; 206 struct snd_soc_dai_link *link, *codec_link; 207 int num_pcms, ret, i; 208 209 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 210 if (!priv) 211 return -ENOMEM; 212 213 card = &priv->card; 214 card->dev = dev; 215 216 card->owner = THIS_MODULE; 217 card->fully_routed = true; 218 219 spin_lock_init(&priv->lock); 220 snd_soc_card_set_drvdata(card, priv); 221 222 ret = snd_soc_of_parse_card_name(card, "model"); 223 if (ret < 0) 224 return ret; 225 226 if (of_property_present(dev->of_node, "samsung,audio-widgets")) { 227 ret = snd_soc_of_parse_audio_simple_widgets(card, 228 "samsung,audio-widgets"); 229 if (ret < 0) 230 return ret; 231 } 232 233 ret = 0; 234 if (of_property_present(dev->of_node, "audio-routing")) 235 ret = snd_soc_of_parse_audio_routing(card, "audio-routing"); 236 else if (of_property_present(dev->of_node, "samsung,audio-routing")) 237 ret = snd_soc_of_parse_audio_routing(card, "samsung,audio-routing"); 238 if (ret < 0) 239 return ret; 240 241 card->dai_link = odroid_card_dais; 242 card->num_links = ARRAY_SIZE(odroid_card_dais); 243 244 cpu = of_get_child_by_name(dev->of_node, "cpu"); 245 codec = of_get_child_by_name(dev->of_node, "codec"); 246 link = card->dai_link; 247 codec_link = &card->dai_link[1]; 248 249 /* 250 * For backwards compatibility create the secondary CPU DAI link only 251 * if there are 2 CPU DAI entries in the cpu sound-dai property in DT. 252 * Also add required DAPM routes not available in old DTS. 253 */ 254 num_pcms = of_count_phandle_with_args(cpu, "sound-dai", 255 "#sound-dai-cells"); 256 if (num_pcms == 1) { 257 card->dapm_routes = odroid_dapm_routes; 258 card->num_dapm_routes = ARRAY_SIZE(odroid_dapm_routes); 259 card->num_links--; 260 } 261 262 for (i = 0; i < num_pcms; i++, link += 2) { 263 ret = snd_soc_of_get_dai_name(cpu, &link->cpus->dai_name, i); 264 if (ret < 0) 265 break; 266 } 267 if (ret == 0) { 268 cpu_dai = of_parse_phandle(cpu, "sound-dai", 0); 269 if (!cpu_dai) 270 ret = -EINVAL; 271 } 272 273 of_node_put(cpu); 274 if (ret < 0) 275 goto err_put_node; 276 277 ret = snd_soc_of_get_dai_link_codecs(dev, codec, codec_link); 278 if (ret < 0) 279 goto err_put_cpu_dai; 280 281 /* Set capture capability only for boards with the MAX98090 CODEC */ 282 if (codec_link->num_codecs > 1) { 283 card->dai_link[0].dpcm_capture = 1; 284 card->dai_link[1].dpcm_capture = 1; 285 } 286 287 priv->sclk_i2s = of_clk_get_by_name(cpu_dai, "i2s_opclk1"); 288 if (IS_ERR(priv->sclk_i2s)) { 289 ret = PTR_ERR(priv->sclk_i2s); 290 goto err_put_cpu_dai; 291 } 292 293 priv->clk_i2s_bus = of_clk_get_by_name(cpu_dai, "iis"); 294 if (IS_ERR(priv->clk_i2s_bus)) { 295 ret = PTR_ERR(priv->clk_i2s_bus); 296 goto err_put_sclk; 297 } 298 299 ret = devm_snd_soc_register_card(dev, card); 300 if (ret < 0) { 301 dev_err_probe(dev, ret, "snd_soc_register_card() failed\n"); 302 goto err_put_clk_i2s; 303 } 304 305 of_node_put(cpu_dai); 306 of_node_put(codec); 307 return 0; 308 309 err_put_clk_i2s: 310 clk_put(priv->clk_i2s_bus); 311 err_put_sclk: 312 clk_put(priv->sclk_i2s); 313 err_put_cpu_dai: 314 of_node_put(cpu_dai); 315 snd_soc_of_put_dai_link_codecs(codec_link); 316 err_put_node: 317 of_node_put(codec); 318 return ret; 319 } 320 321 static void odroid_audio_remove(struct platform_device *pdev) 322 { 323 struct odroid_priv *priv = platform_get_drvdata(pdev); 324 325 snd_soc_of_put_dai_link_codecs(&priv->card.dai_link[1]); 326 clk_put(priv->sclk_i2s); 327 clk_put(priv->clk_i2s_bus); 328 } 329 330 static const struct of_device_id odroid_audio_of_match[] = { 331 { .compatible = "hardkernel,odroid-xu3-audio" }, 332 { .compatible = "hardkernel,odroid-xu4-audio" }, 333 { .compatible = "samsung,odroid-xu3-audio" }, 334 { .compatible = "samsung,odroid-xu4-audio" }, 335 { }, 336 }; 337 MODULE_DEVICE_TABLE(of, odroid_audio_of_match); 338 339 static struct platform_driver odroid_audio_driver = { 340 .driver = { 341 .name = "odroid-audio", 342 .of_match_table = odroid_audio_of_match, 343 .pm = &snd_soc_pm_ops, 344 }, 345 .probe = odroid_audio_probe, 346 .remove_new = odroid_audio_remove, 347 }; 348 module_platform_driver(odroid_audio_driver); 349 350 MODULE_AUTHOR("Sylwester Nawrocki <s.nawrocki@samsung.com>"); 351 MODULE_DESCRIPTION("Odroid XU3/XU4 audio support"); 352 MODULE_LICENSE("GPL v2"); 353