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