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