1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (C) 2020 Texas Instruments Incorporated - http://www.ti.com 4 * Author: Peter Ujfalusi <peter.ujfalusi@ti.com> 5 */ 6 7 #include <linux/clk.h> 8 #include <linux/module.h> 9 #include <linux/of.h> 10 #include <linux/platform_device.h> 11 12 #include <sound/core.h> 13 #include <sound/pcm.h> 14 #include <sound/pcm_params.h> 15 #include <sound/soc.h> 16 17 #include "davinci-mcasp.h" 18 19 /* 20 * Maximum number of configuration entries for prefixes: 21 * CPB: 2 (mcasp10 + codec) 22 * IVI: 3 (mcasp0 + 2x codec) 23 */ 24 #define J721E_CODEC_CONF_COUNT 5 25 26 enum j721e_audio_domain_id { 27 J721E_AUDIO_DOMAIN_CPB = 0, 28 J721E_AUDIO_DOMAIN_IVI, 29 J721E_AUDIO_DOMAIN_LAST, 30 }; 31 32 #define J721E_CLK_PARENT_48000 0 33 #define J721E_CLK_PARENT_44100 1 34 35 #define J721E_MAX_CLK_HSDIV 128 36 #define PCM1368A_MAX_SYSCLK 36864000 37 38 #define J721E_DAI_FMT (SND_SOC_DAIFMT_RIGHT_J | \ 39 SND_SOC_DAIFMT_NB_NF | \ 40 SND_SOC_DAIFMT_CBC_CFC) 41 42 enum j721e_board_type { 43 J721E_BOARD_CPB = 1, 44 J721E_BOARD_CPB_IVI, 45 }; 46 47 struct j721e_audio_match_data { 48 enum j721e_board_type board_type; 49 int num_links; 50 unsigned int pll_rates[2]; 51 }; 52 53 static unsigned int ratios_for_pcm3168a[] = { 54 256, 55 512, 56 768, 57 }; 58 59 struct j721e_audio_clocks { 60 struct clk *target; 61 struct clk *parent[2]; 62 }; 63 64 struct j721e_audio_domain { 65 struct j721e_audio_clocks codec; 66 struct j721e_audio_clocks mcasp; 67 int parent_clk_id; 68 69 int active; 70 unsigned int active_link; 71 unsigned int rate; 72 }; 73 74 struct j721e_priv { 75 struct device *dev; 76 struct snd_soc_card card; 77 struct snd_soc_dai_link *dai_links; 78 struct snd_soc_codec_conf codec_conf[J721E_CODEC_CONF_COUNT]; 79 struct snd_interval rate_range; 80 const struct j721e_audio_match_data *match_data; 81 u32 pll_rates[2]; 82 unsigned int hsdiv_rates[2]; 83 84 struct j721e_audio_domain audio_domains[J721E_AUDIO_DOMAIN_LAST]; 85 86 struct mutex mutex; 87 }; 88 89 static const struct snd_soc_dapm_widget j721e_cpb_dapm_widgets[] = { 90 SND_SOC_DAPM_HP("CPB Stereo HP 1", NULL), 91 SND_SOC_DAPM_HP("CPB Stereo HP 2", NULL), 92 SND_SOC_DAPM_HP("CPB Stereo HP 3", NULL), 93 SND_SOC_DAPM_LINE("CPB Line Out", NULL), 94 SND_SOC_DAPM_MIC("CPB Stereo Mic 1", NULL), 95 SND_SOC_DAPM_MIC("CPB Stereo Mic 2", NULL), 96 SND_SOC_DAPM_LINE("CPB Line In", NULL), 97 }; 98 99 static const struct snd_soc_dapm_route j721e_cpb_dapm_routes[] = { 100 {"CPB Stereo HP 1", NULL, "codec-1 AOUT1L"}, 101 {"CPB Stereo HP 1", NULL, "codec-1 AOUT1R"}, 102 {"CPB Stereo HP 2", NULL, "codec-1 AOUT2L"}, 103 {"CPB Stereo HP 2", NULL, "codec-1 AOUT2R"}, 104 {"CPB Stereo HP 3", NULL, "codec-1 AOUT3L"}, 105 {"CPB Stereo HP 3", NULL, "codec-1 AOUT3R"}, 106 {"CPB Line Out", NULL, "codec-1 AOUT4L"}, 107 {"CPB Line Out", NULL, "codec-1 AOUT4R"}, 108 109 {"codec-1 AIN1L", NULL, "CPB Stereo Mic 1"}, 110 {"codec-1 AIN1R", NULL, "CPB Stereo Mic 1"}, 111 {"codec-1 AIN2L", NULL, "CPB Stereo Mic 2"}, 112 {"codec-1 AIN2R", NULL, "CPB Stereo Mic 2"}, 113 {"codec-1 AIN3L", NULL, "CPB Line In"}, 114 {"codec-1 AIN3R", NULL, "CPB Line In"}, 115 }; 116 117 static const struct snd_soc_dapm_widget j721e_ivi_codec_a_dapm_widgets[] = { 118 SND_SOC_DAPM_LINE("IVI A Line Out 1", NULL), 119 SND_SOC_DAPM_LINE("IVI A Line Out 2", NULL), 120 SND_SOC_DAPM_LINE("IVI A Line Out 3", NULL), 121 SND_SOC_DAPM_LINE("IVI A Line Out 4", NULL), 122 SND_SOC_DAPM_MIC("IVI A Stereo Mic 1", NULL), 123 SND_SOC_DAPM_MIC("IVI A Stereo Mic 2", NULL), 124 SND_SOC_DAPM_LINE("IVI A Line In", NULL), 125 }; 126 127 static const struct snd_soc_dapm_route j721e_codec_a_dapm_routes[] = { 128 {"IVI A Line Out 1", NULL, "codec-a AOUT1L"}, 129 {"IVI A Line Out 1", NULL, "codec-a AOUT1R"}, 130 {"IVI A Line Out 2", NULL, "codec-a AOUT2L"}, 131 {"IVI A Line Out 2", NULL, "codec-a AOUT2R"}, 132 {"IVI A Line Out 3", NULL, "codec-a AOUT3L"}, 133 {"IVI A Line Out 3", NULL, "codec-a AOUT3R"}, 134 {"IVI A Line Out 4", NULL, "codec-a AOUT4L"}, 135 {"IVI A Line Out 4", NULL, "codec-a AOUT4R"}, 136 137 {"codec-a AIN1L", NULL, "IVI A Stereo Mic 1"}, 138 {"codec-a AIN1R", NULL, "IVI A Stereo Mic 1"}, 139 {"codec-a AIN2L", NULL, "IVI A Stereo Mic 2"}, 140 {"codec-a AIN2R", NULL, "IVI A Stereo Mic 2"}, 141 {"codec-a AIN3L", NULL, "IVI A Line In"}, 142 {"codec-a AIN3R", NULL, "IVI A Line In"}, 143 }; 144 145 static const struct snd_soc_dapm_widget j721e_ivi_codec_b_dapm_widgets[] = { 146 SND_SOC_DAPM_LINE("IVI B Line Out 1", NULL), 147 SND_SOC_DAPM_LINE("IVI B Line Out 2", NULL), 148 SND_SOC_DAPM_LINE("IVI B Line Out 3", NULL), 149 SND_SOC_DAPM_LINE("IVI B Line Out 4", NULL), 150 SND_SOC_DAPM_MIC("IVI B Stereo Mic 1", NULL), 151 SND_SOC_DAPM_MIC("IVI B Stereo Mic 2", NULL), 152 SND_SOC_DAPM_LINE("IVI B Line In", NULL), 153 }; 154 155 static const struct snd_soc_dapm_route j721e_codec_b_dapm_routes[] = { 156 {"IVI B Line Out 1", NULL, "codec-b AOUT1L"}, 157 {"IVI B Line Out 1", NULL, "codec-b AOUT1R"}, 158 {"IVI B Line Out 2", NULL, "codec-b AOUT2L"}, 159 {"IVI B Line Out 2", NULL, "codec-b AOUT2R"}, 160 {"IVI B Line Out 3", NULL, "codec-b AOUT3L"}, 161 {"IVI B Line Out 3", NULL, "codec-b AOUT3R"}, 162 {"IVI B Line Out 4", NULL, "codec-b AOUT4L"}, 163 {"IVI B Line Out 4", NULL, "codec-b AOUT4R"}, 164 165 {"codec-b AIN1L", NULL, "IVI B Stereo Mic 1"}, 166 {"codec-b AIN1R", NULL, "IVI B Stereo Mic 1"}, 167 {"codec-b AIN2L", NULL, "IVI B Stereo Mic 2"}, 168 {"codec-b AIN2R", NULL, "IVI B Stereo Mic 2"}, 169 {"codec-b AIN3L", NULL, "IVI B Line In"}, 170 {"codec-b AIN3R", NULL, "IVI B Line In"}, 171 }; 172 173 static int j721e_configure_refclk(struct j721e_priv *priv, 174 unsigned int audio_domain, unsigned int rate) 175 { 176 struct j721e_audio_domain *domain = &priv->audio_domains[audio_domain]; 177 unsigned int scki; 178 int ret = -EINVAL; 179 int i, clk_id; 180 181 if (!(rate % 8000) && priv->pll_rates[J721E_CLK_PARENT_48000]) 182 clk_id = J721E_CLK_PARENT_48000; 183 else if (!(rate % 11025) && priv->pll_rates[J721E_CLK_PARENT_44100]) 184 clk_id = J721E_CLK_PARENT_44100; 185 else if (!(rate % 11025) && priv->pll_rates[J721E_CLK_PARENT_48000]) 186 clk_id = J721E_CLK_PARENT_48000; 187 else 188 return ret; 189 190 for (i = 0; i < ARRAY_SIZE(ratios_for_pcm3168a); i++) { 191 scki = ratios_for_pcm3168a[i] * rate; 192 193 if (priv->pll_rates[clk_id] / scki <= J721E_MAX_CLK_HSDIV) { 194 ret = 0; 195 break; 196 } 197 } 198 199 if (ret) { 200 dev_err(priv->dev, "No valid clock configuration for %u Hz\n", 201 rate); 202 return ret; 203 } 204 205 if (domain->parent_clk_id == -1 || priv->hsdiv_rates[domain->parent_clk_id] != scki) { 206 dev_dbg(priv->dev, 207 "domain%u configuration for %u Hz: %s, %dxFS (SCKI: %u Hz)\n", 208 audio_domain, rate, 209 clk_id == J721E_CLK_PARENT_48000 ? "PLL4" : "PLL15", 210 ratios_for_pcm3168a[i], scki); 211 212 if (domain->parent_clk_id != clk_id) { 213 ret = clk_set_parent(domain->codec.target, 214 domain->codec.parent[clk_id]); 215 if (ret) 216 return ret; 217 218 ret = clk_set_parent(domain->mcasp.target, 219 domain->mcasp.parent[clk_id]); 220 if (ret) 221 return ret; 222 223 domain->parent_clk_id = clk_id; 224 } 225 226 ret = clk_set_rate(domain->codec.target, scki); 227 if (ret) { 228 dev_err(priv->dev, "codec set rate failed for %u Hz\n", 229 scki); 230 return ret; 231 } 232 233 ret = clk_set_rate(domain->mcasp.target, scki); 234 if (!ret) { 235 priv->hsdiv_rates[domain->parent_clk_id] = scki; 236 } else { 237 dev_err(priv->dev, "mcasp set rate failed for %u Hz\n", 238 scki); 239 return ret; 240 } 241 } 242 243 return ret; 244 } 245 246 static int j721e_rule_rate(struct snd_pcm_hw_params *params, 247 struct snd_pcm_hw_rule *rule) 248 { 249 struct snd_interval *t = rule->private; 250 251 return snd_interval_refine(hw_param_interval(params, rule->var), t); 252 } 253 254 static int j721e_audio_startup(struct snd_pcm_substream *substream) 255 { 256 struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); 257 struct j721e_priv *priv = snd_soc_card_get_drvdata(rtd->card); 258 unsigned int domain_id = rtd->dai_link->id; 259 struct j721e_audio_domain *domain = &priv->audio_domains[domain_id]; 260 struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); 261 struct snd_soc_dai *codec_dai; 262 unsigned int active_rate; 263 int ret = 0; 264 int i; 265 266 mutex_lock(&priv->mutex); 267 268 domain->active++; 269 270 for (i = 0; i < J721E_AUDIO_DOMAIN_LAST; i++) { 271 active_rate = priv->audio_domains[i].rate; 272 if (active_rate) 273 break; 274 } 275 276 if (active_rate) 277 ret = snd_pcm_hw_constraint_single(substream->runtime, 278 SNDRV_PCM_HW_PARAM_RATE, 279 active_rate); 280 else 281 ret = snd_pcm_hw_rule_add(substream->runtime, 0, 282 SNDRV_PCM_HW_PARAM_RATE, 283 j721e_rule_rate, &priv->rate_range, 284 SNDRV_PCM_HW_PARAM_RATE, -1); 285 286 287 if (ret) 288 goto out; 289 290 /* Reset TDM slots to 32 */ 291 ret = snd_soc_dai_set_tdm_slot(cpu_dai, 0x3, 0x3, 2, 32); 292 if (ret && ret != -ENOTSUPP) 293 goto out; 294 295 for_each_rtd_codec_dais(rtd, i, codec_dai) { 296 ret = snd_soc_dai_set_tdm_slot(codec_dai, 0x3, 0x3, 2, 32); 297 if (ret && ret != -ENOTSUPP) 298 goto out; 299 } 300 301 if (ret == -ENOTSUPP) 302 ret = 0; 303 out: 304 if (ret) 305 domain->active--; 306 mutex_unlock(&priv->mutex); 307 308 return ret; 309 } 310 311 static int j721e_audio_hw_params(struct snd_pcm_substream *substream, 312 struct snd_pcm_hw_params *params) 313 { 314 struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); 315 struct snd_soc_card *card = rtd->card; 316 struct j721e_priv *priv = snd_soc_card_get_drvdata(card); 317 unsigned int domain_id = rtd->dai_link->id; 318 struct j721e_audio_domain *domain = &priv->audio_domains[domain_id]; 319 struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); 320 struct snd_soc_dai *codec_dai; 321 unsigned int sysclk_rate; 322 int slot_width = 32; 323 int ret; 324 int i; 325 326 mutex_lock(&priv->mutex); 327 328 if (domain->rate && domain->rate != params_rate(params)) { 329 ret = -EINVAL; 330 goto out; 331 } 332 333 if (params_width(params) == 16) 334 slot_width = 16; 335 336 ret = snd_soc_dai_set_tdm_slot(cpu_dai, 0x3, 0x3, 2, slot_width); 337 if (ret && ret != -ENOTSUPP) 338 goto out; 339 340 for_each_rtd_codec_dais(rtd, i, codec_dai) { 341 ret = snd_soc_dai_set_tdm_slot(codec_dai, 0x3, 0x3, 2, 342 slot_width); 343 if (ret && ret != -ENOTSUPP) 344 goto out; 345 } 346 347 ret = j721e_configure_refclk(priv, domain_id, params_rate(params)); 348 if (ret) 349 goto out; 350 351 sysclk_rate = priv->hsdiv_rates[domain->parent_clk_id]; 352 for_each_rtd_codec_dais(rtd, i, codec_dai) { 353 ret = snd_soc_dai_set_sysclk(codec_dai, 0, sysclk_rate, 354 SND_SOC_CLOCK_IN); 355 if (ret && ret != -ENOTSUPP) { 356 dev_err(priv->dev, 357 "codec set_sysclk failed for %u Hz\n", 358 sysclk_rate); 359 goto out; 360 } 361 } 362 363 ret = snd_soc_dai_set_sysclk(cpu_dai, MCASP_CLK_HCLK_AUXCLK, 364 sysclk_rate, SND_SOC_CLOCK_IN); 365 366 if (ret && ret != -ENOTSUPP) { 367 dev_err(priv->dev, "mcasp set_sysclk failed for %u Hz\n", 368 sysclk_rate); 369 } else { 370 domain->rate = params_rate(params); 371 ret = 0; 372 } 373 374 out: 375 mutex_unlock(&priv->mutex); 376 return ret; 377 } 378 379 static void j721e_audio_shutdown(struct snd_pcm_substream *substream) 380 { 381 struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); 382 struct j721e_priv *priv = snd_soc_card_get_drvdata(rtd->card); 383 unsigned int domain_id = rtd->dai_link->id; 384 struct j721e_audio_domain *domain = &priv->audio_domains[domain_id]; 385 386 mutex_lock(&priv->mutex); 387 388 domain->active--; 389 if (!domain->active) { 390 domain->rate = 0; 391 domain->active_link = 0; 392 } 393 394 mutex_unlock(&priv->mutex); 395 } 396 397 static const struct snd_soc_ops j721e_audio_ops = { 398 .startup = j721e_audio_startup, 399 .hw_params = j721e_audio_hw_params, 400 .shutdown = j721e_audio_shutdown, 401 }; 402 403 static int j721e_audio_init(struct snd_soc_pcm_runtime *rtd) 404 { 405 struct j721e_priv *priv = snd_soc_card_get_drvdata(rtd->card); 406 unsigned int domain_id = rtd->dai_link->id; 407 struct j721e_audio_domain *domain = &priv->audio_domains[domain_id]; 408 struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); 409 struct snd_soc_dai *codec_dai; 410 unsigned int sysclk_rate; 411 int i, ret; 412 413 /* Set up initial clock configuration */ 414 ret = j721e_configure_refclk(priv, domain_id, 48000); 415 if (ret) 416 return ret; 417 418 sysclk_rate = priv->hsdiv_rates[domain->parent_clk_id]; 419 for_each_rtd_codec_dais(rtd, i, codec_dai) { 420 ret = snd_soc_dai_set_sysclk(codec_dai, 0, sysclk_rate, 421 SND_SOC_CLOCK_IN); 422 if (ret && ret != -ENOTSUPP) 423 return ret; 424 } 425 426 ret = snd_soc_dai_set_sysclk(cpu_dai, MCASP_CLK_HCLK_AUXCLK, 427 sysclk_rate, SND_SOC_CLOCK_IN); 428 if (ret && ret != -ENOTSUPP) 429 return ret; 430 431 /* Set initial tdm slots */ 432 ret = snd_soc_dai_set_tdm_slot(cpu_dai, 0x3, 0x3, 2, 32); 433 if (ret && ret != -ENOTSUPP) 434 return ret; 435 436 for_each_rtd_codec_dais(rtd, i, codec_dai) { 437 ret = snd_soc_dai_set_tdm_slot(codec_dai, 0x3, 0x3, 2, 32); 438 if (ret && ret != -ENOTSUPP) 439 return ret; 440 } 441 442 return 0; 443 } 444 445 static int j721e_audio_init_ivi(struct snd_soc_pcm_runtime *rtd) 446 { 447 struct snd_soc_dapm_context *dapm = &rtd->card->dapm; 448 449 snd_soc_dapm_new_controls(dapm, j721e_ivi_codec_a_dapm_widgets, 450 ARRAY_SIZE(j721e_ivi_codec_a_dapm_widgets)); 451 snd_soc_dapm_add_routes(dapm, j721e_codec_a_dapm_routes, 452 ARRAY_SIZE(j721e_codec_a_dapm_routes)); 453 snd_soc_dapm_new_controls(dapm, j721e_ivi_codec_b_dapm_widgets, 454 ARRAY_SIZE(j721e_ivi_codec_b_dapm_widgets)); 455 snd_soc_dapm_add_routes(dapm, j721e_codec_b_dapm_routes, 456 ARRAY_SIZE(j721e_codec_b_dapm_routes)); 457 458 return j721e_audio_init(rtd); 459 } 460 461 static int j721e_get_clocks(struct device *dev, 462 struct j721e_audio_clocks *clocks, char *prefix) 463 { 464 struct clk *parent; 465 char *clk_name; 466 int ret; 467 468 clocks->target = devm_clk_get(dev, prefix); 469 if (IS_ERR(clocks->target)) 470 return dev_err_probe(dev, PTR_ERR(clocks->target), 471 "failed to acquire %s\n", prefix); 472 473 clk_name = kasprintf(GFP_KERNEL, "%s-48000", prefix); 474 if (clk_name) { 475 parent = devm_clk_get(dev, clk_name); 476 kfree(clk_name); 477 if (IS_ERR(parent)) { 478 ret = PTR_ERR(parent); 479 if (ret == -EPROBE_DEFER) 480 return ret; 481 482 dev_dbg(dev, "no 48KHz parent for %s: %d\n", prefix, ret); 483 parent = NULL; 484 } 485 clocks->parent[J721E_CLK_PARENT_48000] = parent; 486 } else { 487 return -ENOMEM; 488 } 489 490 clk_name = kasprintf(GFP_KERNEL, "%s-44100", prefix); 491 if (clk_name) { 492 parent = devm_clk_get(dev, clk_name); 493 kfree(clk_name); 494 if (IS_ERR(parent)) { 495 ret = PTR_ERR(parent); 496 if (ret == -EPROBE_DEFER) 497 return ret; 498 499 dev_dbg(dev, "no 44.1KHz parent for %s: %d\n", prefix, ret); 500 parent = NULL; 501 } 502 clocks->parent[J721E_CLK_PARENT_44100] = parent; 503 } else { 504 return -ENOMEM; 505 } 506 507 if (!clocks->parent[J721E_CLK_PARENT_44100] && 508 !clocks->parent[J721E_CLK_PARENT_48000]) { 509 dev_err(dev, "At least one parent clock is needed for %s\n", 510 prefix); 511 return -EINVAL; 512 } 513 514 return 0; 515 } 516 517 static const struct j721e_audio_match_data j721e_cpb_data = { 518 .board_type = J721E_BOARD_CPB, 519 .num_links = 2, /* CPB pcm3168a */ 520 .pll_rates = { 521 [J721E_CLK_PARENT_44100] = 1083801600, /* PLL15 */ 522 [J721E_CLK_PARENT_48000] = 1179648000, /* PLL4 */ 523 }, 524 }; 525 526 static const struct j721e_audio_match_data j721e_cpb_ivi_data = { 527 .board_type = J721E_BOARD_CPB_IVI, 528 .num_links = 4, /* CPB pcm3168a + 2x pcm3168a on IVI */ 529 .pll_rates = { 530 [J721E_CLK_PARENT_44100] = 1083801600, /* PLL15 */ 531 [J721E_CLK_PARENT_48000] = 1179648000, /* PLL4 */ 532 }, 533 }; 534 535 static const struct j721e_audio_match_data j7200_cpb_data = { 536 .board_type = J721E_BOARD_CPB, 537 .num_links = 2, /* CPB pcm3168a */ 538 .pll_rates = { 539 [J721E_CLK_PARENT_48000] = 2359296000u, /* PLL4 */ 540 }, 541 }; 542 543 static const struct of_device_id j721e_audio_of_match[] = { 544 { 545 .compatible = "ti,j721e-cpb-audio", 546 .data = &j721e_cpb_data, 547 }, { 548 .compatible = "ti,j721e-cpb-ivi-audio", 549 .data = &j721e_cpb_ivi_data, 550 }, { 551 .compatible = "ti,j7200-cpb-audio", 552 .data = &j7200_cpb_data, 553 }, 554 { }, 555 }; 556 MODULE_DEVICE_TABLE(of, j721e_audio_of_match); 557 558 static int j721e_calculate_rate_range(struct j721e_priv *priv) 559 { 560 const struct j721e_audio_match_data *match_data = priv->match_data; 561 struct j721e_audio_clocks *domain_clocks; 562 unsigned int min_rate, max_rate, pll_rate; 563 struct clk *pll; 564 565 domain_clocks = &priv->audio_domains[J721E_AUDIO_DOMAIN_CPB].mcasp; 566 567 pll = clk_get_parent(domain_clocks->parent[J721E_CLK_PARENT_44100]); 568 if (IS_ERR_OR_NULL(pll)) { 569 priv->pll_rates[J721E_CLK_PARENT_44100] = 570 match_data->pll_rates[J721E_CLK_PARENT_44100]; 571 } else { 572 priv->pll_rates[J721E_CLK_PARENT_44100] = clk_get_rate(pll); 573 clk_put(pll); 574 } 575 576 pll = clk_get_parent(domain_clocks->parent[J721E_CLK_PARENT_48000]); 577 if (IS_ERR_OR_NULL(pll)) { 578 priv->pll_rates[J721E_CLK_PARENT_48000] = 579 match_data->pll_rates[J721E_CLK_PARENT_48000]; 580 } else { 581 priv->pll_rates[J721E_CLK_PARENT_48000] = clk_get_rate(pll); 582 clk_put(pll); 583 } 584 585 if (!priv->pll_rates[J721E_CLK_PARENT_44100] && 586 !priv->pll_rates[J721E_CLK_PARENT_48000]) { 587 dev_err(priv->dev, "At least one PLL is needed\n"); 588 return -EINVAL; 589 } 590 591 if (priv->pll_rates[J721E_CLK_PARENT_44100]) 592 pll_rate = priv->pll_rates[J721E_CLK_PARENT_44100]; 593 else 594 pll_rate = priv->pll_rates[J721E_CLK_PARENT_48000]; 595 596 min_rate = pll_rate / J721E_MAX_CLK_HSDIV; 597 min_rate /= ratios_for_pcm3168a[ARRAY_SIZE(ratios_for_pcm3168a) - 1]; 598 599 if (priv->pll_rates[J721E_CLK_PARENT_48000]) 600 pll_rate = priv->pll_rates[J721E_CLK_PARENT_48000]; 601 else 602 pll_rate = priv->pll_rates[J721E_CLK_PARENT_44100]; 603 604 if (pll_rate > PCM1368A_MAX_SYSCLK) 605 pll_rate = PCM1368A_MAX_SYSCLK; 606 607 max_rate = pll_rate / ratios_for_pcm3168a[0]; 608 609 snd_interval_any(&priv->rate_range); 610 priv->rate_range.min = min_rate; 611 priv->rate_range.max = max_rate; 612 613 return 0; 614 } 615 616 static int j721e_soc_probe_cpb(struct j721e_priv *priv, int *link_idx, 617 int *conf_idx) 618 { 619 struct device_node *node = priv->dev->of_node; 620 struct snd_soc_dai_link_component *compnent; 621 struct device_node *dai_node, *codec_node; 622 struct j721e_audio_domain *domain; 623 int comp_count, comp_idx; 624 int ret; 625 626 dai_node = of_parse_phandle(node, "ti,cpb-mcasp", 0); 627 if (!dai_node) { 628 dev_err(priv->dev, "CPB McASP node is not provided\n"); 629 return -EINVAL; 630 } 631 632 codec_node = of_parse_phandle(node, "ti,cpb-codec", 0); 633 if (!codec_node) { 634 dev_err(priv->dev, "CPB codec node is not provided\n"); 635 ret = -EINVAL; 636 goto put_dai_node; 637 } 638 639 domain = &priv->audio_domains[J721E_AUDIO_DOMAIN_CPB]; 640 ret = j721e_get_clocks(priv->dev, &domain->codec, "cpb-codec-scki"); 641 if (ret) 642 goto put_codec_node; 643 644 ret = j721e_get_clocks(priv->dev, &domain->mcasp, "cpb-mcasp-auxclk"); 645 if (ret) 646 goto put_codec_node; 647 648 /* 649 * Common Processor Board, two links 650 * Link 1: McASP10 -> pcm3168a_1 DAC 651 * Link 2: McASP10 <- pcm3168a_1 ADC 652 */ 653 comp_count = 6; 654 compnent = devm_kcalloc(priv->dev, comp_count, sizeof(*compnent), 655 GFP_KERNEL); 656 if (!compnent) { 657 ret = -ENOMEM; 658 goto put_codec_node; 659 } 660 661 comp_idx = 0; 662 priv->dai_links[*link_idx].cpus = &compnent[comp_idx++]; 663 priv->dai_links[*link_idx].num_cpus = 1; 664 priv->dai_links[*link_idx].codecs = &compnent[comp_idx++]; 665 priv->dai_links[*link_idx].num_codecs = 1; 666 priv->dai_links[*link_idx].platforms = &compnent[comp_idx++]; 667 priv->dai_links[*link_idx].num_platforms = 1; 668 669 priv->dai_links[*link_idx].name = "CPB PCM3168A Playback"; 670 priv->dai_links[*link_idx].stream_name = "CPB PCM3168A Analog"; 671 priv->dai_links[*link_idx].cpus->of_node = dai_node; 672 priv->dai_links[*link_idx].platforms->of_node = dai_node; 673 priv->dai_links[*link_idx].codecs->of_node = codec_node; 674 priv->dai_links[*link_idx].codecs->dai_name = "pcm3168a-dac"; 675 priv->dai_links[*link_idx].playback_only = 1; 676 priv->dai_links[*link_idx].id = J721E_AUDIO_DOMAIN_CPB; 677 priv->dai_links[*link_idx].dai_fmt = J721E_DAI_FMT; 678 priv->dai_links[*link_idx].init = j721e_audio_init; 679 priv->dai_links[*link_idx].ops = &j721e_audio_ops; 680 (*link_idx)++; 681 682 priv->dai_links[*link_idx].cpus = &compnent[comp_idx++]; 683 priv->dai_links[*link_idx].num_cpus = 1; 684 priv->dai_links[*link_idx].codecs = &compnent[comp_idx++]; 685 priv->dai_links[*link_idx].num_codecs = 1; 686 priv->dai_links[*link_idx].platforms = &compnent[comp_idx++]; 687 priv->dai_links[*link_idx].num_platforms = 1; 688 689 priv->dai_links[*link_idx].name = "CPB PCM3168A Capture"; 690 priv->dai_links[*link_idx].stream_name = "CPB PCM3168A Analog"; 691 priv->dai_links[*link_idx].cpus->of_node = dai_node; 692 priv->dai_links[*link_idx].platforms->of_node = dai_node; 693 priv->dai_links[*link_idx].codecs->of_node = codec_node; 694 priv->dai_links[*link_idx].codecs->dai_name = "pcm3168a-adc"; 695 priv->dai_links[*link_idx].capture_only = 1; 696 priv->dai_links[*link_idx].id = J721E_AUDIO_DOMAIN_CPB; 697 priv->dai_links[*link_idx].dai_fmt = J721E_DAI_FMT; 698 priv->dai_links[*link_idx].init = j721e_audio_init; 699 priv->dai_links[*link_idx].ops = &j721e_audio_ops; 700 (*link_idx)++; 701 702 priv->codec_conf[*conf_idx].dlc.of_node = codec_node; 703 priv->codec_conf[*conf_idx].name_prefix = "codec-1"; 704 (*conf_idx)++; 705 priv->codec_conf[*conf_idx].dlc.of_node = dai_node; 706 priv->codec_conf[*conf_idx].name_prefix = "McASP10"; 707 (*conf_idx)++; 708 709 return 0; 710 711 put_codec_node: 712 of_node_put(codec_node); 713 put_dai_node: 714 of_node_put(dai_node); 715 return ret; 716 } 717 718 static int j721e_soc_probe_ivi(struct j721e_priv *priv, int *link_idx, 719 int *conf_idx) 720 { 721 struct device_node *node = priv->dev->of_node; 722 struct snd_soc_dai_link_component *compnent; 723 struct device_node *dai_node, *codeca_node, *codecb_node; 724 struct j721e_audio_domain *domain; 725 int comp_count, comp_idx; 726 int ret; 727 728 if (priv->match_data->board_type != J721E_BOARD_CPB_IVI) 729 return 0; 730 731 dai_node = of_parse_phandle(node, "ti,ivi-mcasp", 0); 732 if (!dai_node) { 733 dev_err(priv->dev, "IVI McASP node is not provided\n"); 734 return -EINVAL; 735 } 736 737 codeca_node = of_parse_phandle(node, "ti,ivi-codec-a", 0); 738 if (!codeca_node) { 739 dev_err(priv->dev, "IVI codec-a node is not provided\n"); 740 ret = -EINVAL; 741 goto put_dai_node; 742 } 743 744 codecb_node = of_parse_phandle(node, "ti,ivi-codec-b", 0); 745 if (!codecb_node) { 746 dev_warn(priv->dev, "IVI codec-b node is not provided\n"); 747 ret = 0; 748 goto put_codeca_node; 749 } 750 751 domain = &priv->audio_domains[J721E_AUDIO_DOMAIN_IVI]; 752 ret = j721e_get_clocks(priv->dev, &domain->codec, "ivi-codec-scki"); 753 if (ret) 754 goto put_codecb_node; 755 756 ret = j721e_get_clocks(priv->dev, &domain->mcasp, "ivi-mcasp-auxclk"); 757 if (ret) 758 goto put_codecb_node; 759 760 /* 761 * IVI extension, two links 762 * Link 1: McASP0 -> pcm3168a_a DAC 763 * \> pcm3168a_b DAC 764 * Link 2: McASP0 <- pcm3168a_a ADC 765 * \ pcm3168a_b ADC 766 */ 767 comp_count = 8; 768 compnent = devm_kcalloc(priv->dev, comp_count, sizeof(*compnent), 769 GFP_KERNEL); 770 if (!compnent) { 771 ret = -ENOMEM; 772 goto put_codecb_node; 773 } 774 775 comp_idx = 0; 776 priv->dai_links[*link_idx].cpus = &compnent[comp_idx++]; 777 priv->dai_links[*link_idx].num_cpus = 1; 778 priv->dai_links[*link_idx].platforms = &compnent[comp_idx++]; 779 priv->dai_links[*link_idx].num_platforms = 1; 780 priv->dai_links[*link_idx].codecs = &compnent[comp_idx]; 781 priv->dai_links[*link_idx].num_codecs = 2; 782 comp_idx += 2; 783 784 priv->dai_links[*link_idx].name = "IVI 2xPCM3168A Playback"; 785 priv->dai_links[*link_idx].stream_name = "IVI 2xPCM3168A Analog"; 786 priv->dai_links[*link_idx].cpus->of_node = dai_node; 787 priv->dai_links[*link_idx].platforms->of_node = dai_node; 788 priv->dai_links[*link_idx].codecs[0].of_node = codeca_node; 789 priv->dai_links[*link_idx].codecs[0].dai_name = "pcm3168a-dac"; 790 priv->dai_links[*link_idx].codecs[1].of_node = codecb_node; 791 priv->dai_links[*link_idx].codecs[1].dai_name = "pcm3168a-dac"; 792 priv->dai_links[*link_idx].playback_only = 1; 793 priv->dai_links[*link_idx].id = J721E_AUDIO_DOMAIN_IVI; 794 priv->dai_links[*link_idx].dai_fmt = J721E_DAI_FMT; 795 priv->dai_links[*link_idx].init = j721e_audio_init_ivi; 796 priv->dai_links[*link_idx].ops = &j721e_audio_ops; 797 (*link_idx)++; 798 799 priv->dai_links[*link_idx].cpus = &compnent[comp_idx++]; 800 priv->dai_links[*link_idx].num_cpus = 1; 801 priv->dai_links[*link_idx].platforms = &compnent[comp_idx++]; 802 priv->dai_links[*link_idx].num_platforms = 1; 803 priv->dai_links[*link_idx].codecs = &compnent[comp_idx]; 804 priv->dai_links[*link_idx].num_codecs = 2; 805 806 priv->dai_links[*link_idx].name = "IVI 2xPCM3168A Capture"; 807 priv->dai_links[*link_idx].stream_name = "IVI 2xPCM3168A Analog"; 808 priv->dai_links[*link_idx].cpus->of_node = dai_node; 809 priv->dai_links[*link_idx].platforms->of_node = dai_node; 810 priv->dai_links[*link_idx].codecs[0].of_node = codeca_node; 811 priv->dai_links[*link_idx].codecs[0].dai_name = "pcm3168a-adc"; 812 priv->dai_links[*link_idx].codecs[1].of_node = codecb_node; 813 priv->dai_links[*link_idx].codecs[1].dai_name = "pcm3168a-adc"; 814 priv->dai_links[*link_idx].capture_only = 1; 815 priv->dai_links[*link_idx].id = J721E_AUDIO_DOMAIN_IVI; 816 priv->dai_links[*link_idx].dai_fmt = J721E_DAI_FMT; 817 priv->dai_links[*link_idx].init = j721e_audio_init; 818 priv->dai_links[*link_idx].ops = &j721e_audio_ops; 819 (*link_idx)++; 820 821 priv->codec_conf[*conf_idx].dlc.of_node = codeca_node; 822 priv->codec_conf[*conf_idx].name_prefix = "codec-a"; 823 (*conf_idx)++; 824 825 priv->codec_conf[*conf_idx].dlc.of_node = codecb_node; 826 priv->codec_conf[*conf_idx].name_prefix = "codec-b"; 827 (*conf_idx)++; 828 829 priv->codec_conf[*conf_idx].dlc.of_node = dai_node; 830 priv->codec_conf[*conf_idx].name_prefix = "McASP0"; 831 (*conf_idx)++; 832 833 return 0; 834 835 836 put_codecb_node: 837 of_node_put(codecb_node); 838 put_codeca_node: 839 of_node_put(codeca_node); 840 put_dai_node: 841 of_node_put(dai_node); 842 return ret; 843 } 844 845 static int j721e_soc_probe(struct platform_device *pdev) 846 { 847 struct device_node *node = pdev->dev.of_node; 848 struct snd_soc_card *card; 849 const struct of_device_id *match; 850 struct j721e_priv *priv; 851 int link_cnt, conf_cnt, ret, i; 852 853 if (!node) { 854 dev_err(&pdev->dev, "of node is missing.\n"); 855 return -ENODEV; 856 } 857 858 match = of_match_node(j721e_audio_of_match, node); 859 if (!match) { 860 dev_err(&pdev->dev, "No compatible match found\n"); 861 return -ENODEV; 862 } 863 864 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); 865 if (!priv) 866 return -ENOMEM; 867 868 priv->match_data = match->data; 869 870 priv->dai_links = devm_kcalloc(&pdev->dev, priv->match_data->num_links, 871 sizeof(*priv->dai_links), GFP_KERNEL); 872 if (!priv->dai_links) 873 return -ENOMEM; 874 875 for (i = 0; i < J721E_AUDIO_DOMAIN_LAST; i++) 876 priv->audio_domains[i].parent_clk_id = -1; 877 878 priv->dev = &pdev->dev; 879 card = &priv->card; 880 card->dev = &pdev->dev; 881 card->owner = THIS_MODULE; 882 card->dapm_widgets = j721e_cpb_dapm_widgets; 883 card->num_dapm_widgets = ARRAY_SIZE(j721e_cpb_dapm_widgets); 884 card->dapm_routes = j721e_cpb_dapm_routes; 885 card->num_dapm_routes = ARRAY_SIZE(j721e_cpb_dapm_routes); 886 card->fully_routed = 1; 887 888 if (snd_soc_of_parse_card_name(card, "model")) { 889 dev_err(&pdev->dev, "Card name is not provided\n"); 890 return -ENODEV; 891 } 892 893 link_cnt = 0; 894 conf_cnt = 0; 895 ret = j721e_soc_probe_cpb(priv, &link_cnt, &conf_cnt); 896 if (ret) 897 return ret; 898 899 ret = j721e_soc_probe_ivi(priv, &link_cnt, &conf_cnt); 900 if (ret) 901 return ret; 902 903 card->dai_link = priv->dai_links; 904 card->num_links = link_cnt; 905 906 card->codec_conf = priv->codec_conf; 907 card->num_configs = conf_cnt; 908 909 ret = j721e_calculate_rate_range(priv); 910 if (ret) 911 return ret; 912 913 snd_soc_card_set_drvdata(card, priv); 914 915 mutex_init(&priv->mutex); 916 ret = devm_snd_soc_register_card(&pdev->dev, card); 917 if (ret) 918 dev_err_probe(&pdev->dev, ret, 919 "devm_snd_soc_register_card() failed: %d\n", 920 ret); 921 922 return ret; 923 } 924 925 static struct platform_driver j721e_soc_driver = { 926 .driver = { 927 .name = "j721e-audio", 928 .pm = &snd_soc_pm_ops, 929 .of_match_table = j721e_audio_of_match, 930 }, 931 .probe = j721e_soc_probe, 932 }; 933 934 module_platform_driver(j721e_soc_driver); 935 936 MODULE_AUTHOR("Peter Ujfalusi <peter.ujfalusi@ti.com>"); 937 MODULE_DESCRIPTION("ASoC machine driver for j721e Common Processor Board"); 938 MODULE_LICENSE("GPL v2"); 939