tegra_asoc_machine.c 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * tegra_asoc_machine.c - Universal ASoC machine driver for NVIDIA Tegra boards.
  4. */
  5. #include <linux/clk.h>
  6. #include <linux/export.h>
  7. #include <linux/gpio/consumer.h>
  8. #include <linux/module.h>
  9. #include <linux/of.h>
  10. #include <linux/platform_device.h>
  11. #include <linux/slab.h>
  12. #include <sound/core.h>
  13. #include <sound/jack.h>
  14. #include <sound/pcm.h>
  15. #include <sound/pcm_params.h>
  16. #include <sound/soc.h>
  17. #include "tegra_asoc_machine.h"
  18. /* Headphones Jack */
  19. static struct snd_soc_jack tegra_machine_hp_jack;
  20. static struct snd_soc_jack_pin tegra_machine_hp_jack_pins[] = {
  21. { .pin = "Headphone", .mask = SND_JACK_HEADPHONE },
  22. { .pin = "Headphones", .mask = SND_JACK_HEADPHONE },
  23. };
  24. static struct snd_soc_jack_gpio tegra_machine_hp_jack_gpio = {
  25. .name = "Headphones detection",
  26. .report = SND_JACK_HEADPHONE,
  27. .debounce_time = 150,
  28. };
  29. /* Headset Jack */
  30. static struct snd_soc_jack tegra_machine_headset_jack;
  31. static struct snd_soc_jack_pin tegra_machine_headset_jack_pins[] = {
  32. { .pin = "Headset Mic", .mask = SND_JACK_MICROPHONE },
  33. { .pin = "Headset Stereophone", .mask = SND_JACK_HEADPHONE },
  34. };
  35. static struct snd_soc_jack_gpio tegra_machine_headset_jack_gpio = {
  36. .name = "Headset detection",
  37. .report = SND_JACK_HEADSET,
  38. .debounce_time = 150,
  39. };
  40. /* Mic Jack */
  41. static int coupled_mic_hp_check(void *data)
  42. {
  43. struct tegra_machine *machine = (struct tegra_machine *)data;
  44. /* Detect mic insertion only if 3.5 jack is in */
  45. if (gpiod_get_value_cansleep(machine->gpiod_hp_det) &&
  46. gpiod_get_value_cansleep(machine->gpiod_mic_det))
  47. return SND_JACK_MICROPHONE;
  48. return 0;
  49. }
  50. static struct snd_soc_jack tegra_machine_mic_jack;
  51. static struct snd_soc_jack_pin tegra_machine_mic_jack_pins[] = {
  52. { .pin = "Mic Jack", .mask = SND_JACK_MICROPHONE },
  53. { .pin = "Headset Mic", .mask = SND_JACK_MICROPHONE },
  54. };
  55. static struct snd_soc_jack_gpio tegra_machine_mic_jack_gpio = {
  56. .name = "Mic detection",
  57. .report = SND_JACK_MICROPHONE,
  58. .debounce_time = 150,
  59. };
  60. static int tegra_machine_event(struct snd_soc_dapm_widget *w,
  61. struct snd_kcontrol *k, int event)
  62. {
  63. struct snd_soc_dapm_context *dapm = w->dapm;
  64. struct tegra_machine *machine = snd_soc_card_get_drvdata(dapm->card);
  65. if (!snd_soc_dapm_widget_name_cmp(w, "Int Spk") ||
  66. !snd_soc_dapm_widget_name_cmp(w, "Speakers"))
  67. gpiod_set_value_cansleep(machine->gpiod_spkr_en,
  68. SND_SOC_DAPM_EVENT_ON(event));
  69. if (!snd_soc_dapm_widget_name_cmp(w, "Mic Jack") ||
  70. !snd_soc_dapm_widget_name_cmp(w, "Headset Mic"))
  71. gpiod_set_value_cansleep(machine->gpiod_ext_mic_en,
  72. SND_SOC_DAPM_EVENT_ON(event));
  73. if (!snd_soc_dapm_widget_name_cmp(w, "Int Mic") ||
  74. !snd_soc_dapm_widget_name_cmp(w, "Internal Mic 2"))
  75. gpiod_set_value_cansleep(machine->gpiod_int_mic_en,
  76. SND_SOC_DAPM_EVENT_ON(event));
  77. if (!snd_soc_dapm_widget_name_cmp(w, "Headphone") ||
  78. !snd_soc_dapm_widget_name_cmp(w, "Headphone Jack"))
  79. gpiod_set_value_cansleep(machine->gpiod_hp_mute,
  80. !SND_SOC_DAPM_EVENT_ON(event));
  81. return 0;
  82. }
  83. static const struct snd_soc_dapm_widget tegra_machine_dapm_widgets[] = {
  84. SND_SOC_DAPM_HP("Headphone Jack", tegra_machine_event),
  85. SND_SOC_DAPM_HP("Headphone", tegra_machine_event),
  86. SND_SOC_DAPM_HP("Headset Stereophone", NULL),
  87. SND_SOC_DAPM_HP("Headphones", NULL),
  88. SND_SOC_DAPM_SPK("Speakers", tegra_machine_event),
  89. SND_SOC_DAPM_SPK("Int Spk", tegra_machine_event),
  90. SND_SOC_DAPM_SPK("Earpiece", NULL),
  91. SND_SOC_DAPM_MIC("Int Mic", tegra_machine_event),
  92. SND_SOC_DAPM_MIC("Mic Jack", tegra_machine_event),
  93. SND_SOC_DAPM_MIC("Internal Mic 1", NULL),
  94. SND_SOC_DAPM_MIC("Internal Mic 2", tegra_machine_event),
  95. SND_SOC_DAPM_MIC("Headset Mic", tegra_machine_event),
  96. SND_SOC_DAPM_MIC("Digital Mic", NULL),
  97. SND_SOC_DAPM_MIC("Mic", NULL),
  98. SND_SOC_DAPM_LINE("Line In Jack", NULL),
  99. SND_SOC_DAPM_LINE("Line In", NULL),
  100. SND_SOC_DAPM_LINE("LineIn", NULL),
  101. };
  102. static const struct snd_kcontrol_new tegra_machine_controls[] = {
  103. SOC_DAPM_PIN_SWITCH("Speakers"),
  104. SOC_DAPM_PIN_SWITCH("Int Spk"),
  105. SOC_DAPM_PIN_SWITCH("Earpiece"),
  106. SOC_DAPM_PIN_SWITCH("Int Mic"),
  107. SOC_DAPM_PIN_SWITCH("Headset Mic"),
  108. SOC_DAPM_PIN_SWITCH("Internal Mic 1"),
  109. SOC_DAPM_PIN_SWITCH("Internal Mic 2"),
  110. SOC_DAPM_PIN_SWITCH("Headphones"),
  111. SOC_DAPM_PIN_SWITCH("Mic Jack"),
  112. };
  113. int tegra_asoc_machine_init(struct snd_soc_pcm_runtime *rtd)
  114. {
  115. struct snd_soc_card *card = rtd->card;
  116. struct tegra_machine *machine = snd_soc_card_get_drvdata(card);
  117. const char *jack_name;
  118. int err;
  119. if (machine->gpiod_hp_det && machine->asoc->add_hp_jack) {
  120. if (machine->asoc->hp_jack_name)
  121. jack_name = machine->asoc->hp_jack_name;
  122. else
  123. jack_name = "Headphones Jack";
  124. err = snd_soc_card_jack_new_pins(card, jack_name,
  125. SND_JACK_HEADPHONE,
  126. &tegra_machine_hp_jack,
  127. tegra_machine_hp_jack_pins,
  128. ARRAY_SIZE(tegra_machine_hp_jack_pins));
  129. if (err) {
  130. dev_err(rtd->dev,
  131. "Headphones Jack creation failed: %d\n", err);
  132. return err;
  133. }
  134. tegra_machine_hp_jack_gpio.desc = machine->gpiod_hp_det;
  135. err = snd_soc_jack_add_gpios(&tegra_machine_hp_jack, 1,
  136. &tegra_machine_hp_jack_gpio);
  137. if (err)
  138. dev_err(rtd->dev, "HP GPIOs not added: %d\n", err);
  139. }
  140. if (machine->gpiod_hp_det && machine->asoc->add_headset_jack) {
  141. err = snd_soc_card_jack_new_pins(card, "Headset Jack",
  142. SND_JACK_HEADSET,
  143. &tegra_machine_headset_jack,
  144. tegra_machine_headset_jack_pins,
  145. ARRAY_SIZE(tegra_machine_headset_jack_pins));
  146. if (err) {
  147. dev_err(rtd->dev,
  148. "Headset Jack creation failed: %d\n", err);
  149. return err;
  150. }
  151. tegra_machine_headset_jack_gpio.desc = machine->gpiod_hp_det;
  152. err = snd_soc_jack_add_gpios(&tegra_machine_headset_jack, 1,
  153. &tegra_machine_headset_jack_gpio);
  154. if (err)
  155. dev_err(rtd->dev, "Headset GPIOs not added: %d\n", err);
  156. }
  157. if (machine->gpiod_mic_det && machine->asoc->add_mic_jack) {
  158. err = snd_soc_card_jack_new_pins(rtd->card, "Mic Jack",
  159. SND_JACK_MICROPHONE,
  160. &tegra_machine_mic_jack,
  161. tegra_machine_mic_jack_pins,
  162. ARRAY_SIZE(tegra_machine_mic_jack_pins));
  163. if (err) {
  164. dev_err(rtd->dev, "Mic Jack creation failed: %d\n", err);
  165. return err;
  166. }
  167. tegra_machine_mic_jack_gpio.data = machine;
  168. tegra_machine_mic_jack_gpio.desc = machine->gpiod_mic_det;
  169. if (of_property_read_bool(card->dev->of_node,
  170. "nvidia,coupled-mic-hp-det")) {
  171. tegra_machine_mic_jack_gpio.desc = machine->gpiod_hp_det;
  172. tegra_machine_mic_jack_gpio.jack_status_check = coupled_mic_hp_check;
  173. }
  174. err = snd_soc_jack_add_gpios(&tegra_machine_mic_jack, 1,
  175. &tegra_machine_mic_jack_gpio);
  176. if (err)
  177. dev_err(rtd->dev, "Mic GPIOs not added: %d\n", err);
  178. }
  179. return 0;
  180. }
  181. EXPORT_SYMBOL_GPL(tegra_asoc_machine_init);
  182. static unsigned int tegra_machine_mclk_rate_128(unsigned int srate)
  183. {
  184. return 128 * srate;
  185. }
  186. static unsigned int tegra_machine_mclk_rate_256(unsigned int srate)
  187. {
  188. return 256 * srate;
  189. }
  190. static unsigned int tegra_machine_mclk_rate_512(unsigned int srate)
  191. {
  192. return 512 * srate;
  193. }
  194. static unsigned int tegra_machine_mclk_rate_12mhz(unsigned int srate)
  195. {
  196. unsigned int mclk;
  197. switch (srate) {
  198. case 8000:
  199. case 16000:
  200. case 24000:
  201. case 32000:
  202. case 48000:
  203. case 64000:
  204. case 96000:
  205. mclk = 12288000;
  206. break;
  207. case 11025:
  208. case 22050:
  209. case 44100:
  210. case 88200:
  211. mclk = 11289600;
  212. break;
  213. default:
  214. mclk = 12000000;
  215. break;
  216. }
  217. return mclk;
  218. }
  219. static unsigned int tegra_machine_mclk_rate_6mhz(unsigned int srate)
  220. {
  221. unsigned int mclk;
  222. switch (srate) {
  223. case 8000:
  224. case 16000:
  225. case 64000:
  226. mclk = 8192000;
  227. break;
  228. case 11025:
  229. case 22050:
  230. case 88200:
  231. mclk = 11289600;
  232. break;
  233. case 96000:
  234. mclk = 12288000;
  235. break;
  236. default:
  237. mclk = 256 * srate;
  238. break;
  239. }
  240. return mclk;
  241. }
  242. static int tegra_machine_hw_params(struct snd_pcm_substream *substream,
  243. struct snd_pcm_hw_params *params)
  244. {
  245. struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
  246. struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0);
  247. struct snd_soc_card *card = rtd->card;
  248. struct tegra_machine *machine = snd_soc_card_get_drvdata(card);
  249. unsigned int srate = params_rate(params);
  250. unsigned int mclk = machine->asoc->mclk_rate(srate);
  251. unsigned int clk_id = machine->asoc->mclk_id;
  252. unsigned int new_baseclock;
  253. int err;
  254. switch (srate) {
  255. case 11025:
  256. case 22050:
  257. case 44100:
  258. case 88200:
  259. if (of_machine_is_compatible("nvidia,tegra20"))
  260. new_baseclock = 56448000;
  261. else if (of_machine_is_compatible("nvidia,tegra30"))
  262. new_baseclock = 564480000;
  263. else
  264. new_baseclock = 282240000;
  265. break;
  266. case 8000:
  267. case 16000:
  268. case 32000:
  269. case 48000:
  270. case 64000:
  271. case 96000:
  272. if (of_machine_is_compatible("nvidia,tegra20"))
  273. new_baseclock = 73728000;
  274. else if (of_machine_is_compatible("nvidia,tegra30"))
  275. new_baseclock = 552960000;
  276. else
  277. new_baseclock = 368640000;
  278. break;
  279. default:
  280. dev_err(card->dev, "Invalid sound rate: %u\n", srate);
  281. return -EINVAL;
  282. }
  283. if (new_baseclock != machine->set_baseclock ||
  284. mclk != machine->set_mclk) {
  285. machine->set_baseclock = 0;
  286. machine->set_mclk = 0;
  287. clk_disable_unprepare(machine->clk_cdev1);
  288. err = clk_set_rate(machine->clk_pll_a, new_baseclock);
  289. if (err) {
  290. dev_err(card->dev, "Can't set pll_a rate: %d\n", err);
  291. return err;
  292. }
  293. err = clk_set_rate(machine->clk_pll_a_out0, mclk);
  294. if (err) {
  295. dev_err(card->dev, "Can't set pll_a_out0 rate: %d\n", err);
  296. return err;
  297. }
  298. /* Don't set cdev1/extern1 rate; it's locked to pll_a_out0 */
  299. err = clk_prepare_enable(machine->clk_cdev1);
  300. if (err) {
  301. dev_err(card->dev, "Can't enable cdev1: %d\n", err);
  302. return err;
  303. }
  304. machine->set_baseclock = new_baseclock;
  305. machine->set_mclk = mclk;
  306. }
  307. err = snd_soc_dai_set_sysclk(codec_dai, clk_id, mclk, SND_SOC_CLOCK_IN);
  308. if (err < 0) {
  309. dev_err(card->dev, "codec_dai clock not set: %d\n", err);
  310. return err;
  311. }
  312. return 0;
  313. }
  314. static const struct snd_soc_ops tegra_machine_snd_ops = {
  315. .hw_params = tegra_machine_hw_params,
  316. };
  317. static void tegra_machine_node_release(void *of_node)
  318. {
  319. of_node_put(of_node);
  320. }
  321. static struct device_node *
  322. tegra_machine_parse_phandle(struct device *dev, const char *name)
  323. {
  324. struct device_node *np;
  325. int err;
  326. np = of_parse_phandle(dev->of_node, name, 0);
  327. if (!np) {
  328. dev_err(dev, "Property '%s' missing or invalid\n", name);
  329. return ERR_PTR(-EINVAL);
  330. }
  331. err = devm_add_action_or_reset(dev, tegra_machine_node_release, np);
  332. if (err)
  333. return ERR_PTR(err);
  334. return np;
  335. }
  336. static void tegra_machine_unregister_codec(void *pdev)
  337. {
  338. platform_device_unregister(pdev);
  339. }
  340. static int tegra_machine_register_codec(struct device *dev, const char *name)
  341. {
  342. struct platform_device *pdev;
  343. int err;
  344. if (!name)
  345. return 0;
  346. pdev = platform_device_register_simple(name, -1, NULL, 0);
  347. if (IS_ERR(pdev))
  348. return PTR_ERR(pdev);
  349. err = devm_add_action_or_reset(dev, tegra_machine_unregister_codec,
  350. pdev);
  351. if (err)
  352. return err;
  353. return 0;
  354. }
  355. int tegra_asoc_machine_probe(struct platform_device *pdev)
  356. {
  357. struct device_node *np_codec, *np_i2s, *np_ac97;
  358. const struct tegra_asoc_data *asoc;
  359. struct device *dev = &pdev->dev;
  360. struct tegra_machine *machine;
  361. struct snd_soc_card *card;
  362. struct gpio_desc *gpiod;
  363. int err;
  364. machine = devm_kzalloc(dev, sizeof(*machine), GFP_KERNEL);
  365. if (!machine)
  366. return -ENOMEM;
  367. asoc = of_device_get_match_data(dev);
  368. card = asoc->card;
  369. card->dev = dev;
  370. machine->asoc = asoc;
  371. machine->mic_jack = &tegra_machine_mic_jack;
  372. machine->hp_jack_gpio = &tegra_machine_hp_jack_gpio;
  373. snd_soc_card_set_drvdata(card, machine);
  374. gpiod = devm_gpiod_get_optional(dev, "nvidia,hp-mute", GPIOD_OUT_HIGH);
  375. machine->gpiod_hp_mute = gpiod;
  376. if (IS_ERR(gpiod))
  377. return PTR_ERR(gpiod);
  378. gpiod = devm_gpiod_get_optional(dev, "nvidia,hp-det", GPIOD_IN);
  379. machine->gpiod_hp_det = gpiod;
  380. if (IS_ERR(gpiod))
  381. return PTR_ERR(gpiod);
  382. gpiod = devm_gpiod_get_optional(dev, "nvidia,mic-det", GPIOD_IN);
  383. machine->gpiod_mic_det = gpiod;
  384. if (IS_ERR(gpiod))
  385. return PTR_ERR(gpiod);
  386. gpiod = devm_gpiod_get_optional(dev, "nvidia,spkr-en", GPIOD_OUT_LOW);
  387. machine->gpiod_spkr_en = gpiod;
  388. if (IS_ERR(gpiod))
  389. return PTR_ERR(gpiod);
  390. gpiod = devm_gpiod_get_optional(dev, "nvidia,int-mic-en", GPIOD_OUT_LOW);
  391. machine->gpiod_int_mic_en = gpiod;
  392. if (IS_ERR(gpiod))
  393. return PTR_ERR(gpiod);
  394. gpiod = devm_gpiod_get_optional(dev, "nvidia,ext-mic-en", GPIOD_OUT_LOW);
  395. machine->gpiod_ext_mic_en = gpiod;
  396. if (IS_ERR(gpiod))
  397. return PTR_ERR(gpiod);
  398. err = snd_soc_of_parse_card_name(card, "nvidia,model");
  399. if (err)
  400. return err;
  401. if (!card->dapm_routes) {
  402. err = snd_soc_of_parse_audio_routing(card, "nvidia,audio-routing");
  403. if (err)
  404. return err;
  405. }
  406. if (asoc->set_ac97) {
  407. err = tegra_machine_register_codec(dev, asoc->codec_dev_name);
  408. if (err)
  409. return err;
  410. np_ac97 = tegra_machine_parse_phandle(dev, "nvidia,ac97-controller");
  411. if (IS_ERR(np_ac97))
  412. return PTR_ERR(np_ac97);
  413. card->dai_link->cpus->of_node = np_ac97;
  414. card->dai_link->platforms->of_node = np_ac97;
  415. } else {
  416. np_codec = tegra_machine_parse_phandle(dev, "nvidia,audio-codec");
  417. if (IS_ERR(np_codec))
  418. return PTR_ERR(np_codec);
  419. np_i2s = tegra_machine_parse_phandle(dev, "nvidia,i2s-controller");
  420. if (IS_ERR(np_i2s))
  421. return PTR_ERR(np_i2s);
  422. card->dai_link->cpus->of_node = np_i2s;
  423. card->dai_link->codecs->of_node = np_codec;
  424. card->dai_link->platforms->of_node = np_i2s;
  425. }
  426. if (asoc->add_common_controls) {
  427. card->controls = tegra_machine_controls;
  428. card->num_controls = ARRAY_SIZE(tegra_machine_controls);
  429. }
  430. if (asoc->add_common_dapm_widgets) {
  431. card->dapm_widgets = tegra_machine_dapm_widgets;
  432. card->num_dapm_widgets = ARRAY_SIZE(tegra_machine_dapm_widgets);
  433. }
  434. if (asoc->add_common_snd_ops)
  435. card->dai_link->ops = &tegra_machine_snd_ops;
  436. if (!card->owner)
  437. card->owner = THIS_MODULE;
  438. if (!card->driver_name)
  439. card->driver_name = "tegra";
  440. machine->clk_pll_a = devm_clk_get(dev, "pll_a");
  441. if (IS_ERR(machine->clk_pll_a)) {
  442. dev_err(dev, "Can't retrieve clk pll_a\n");
  443. return PTR_ERR(machine->clk_pll_a);
  444. }
  445. machine->clk_pll_a_out0 = devm_clk_get(dev, "pll_a_out0");
  446. if (IS_ERR(machine->clk_pll_a_out0)) {
  447. dev_err(dev, "Can't retrieve clk pll_a_out0\n");
  448. return PTR_ERR(machine->clk_pll_a_out0);
  449. }
  450. machine->clk_cdev1 = devm_clk_get(dev, "mclk");
  451. if (IS_ERR(machine->clk_cdev1)) {
  452. dev_err(dev, "Can't retrieve clk cdev1\n");
  453. return PTR_ERR(machine->clk_cdev1);
  454. }
  455. /*
  456. * If clock parents are not set in DT, configure here to use clk_out_1
  457. * as mclk and extern1 as parent for Tegra30 and higher.
  458. */
  459. if (!of_property_present(dev->of_node, "assigned-clock-parents") &&
  460. !of_machine_is_compatible("nvidia,tegra20")) {
  461. struct clk *clk_out_1, *clk_extern1;
  462. dev_warn(dev, "Configuring clocks for a legacy device-tree\n");
  463. dev_warn(dev, "Please update DT to use assigned-clock-parents\n");
  464. clk_extern1 = devm_clk_get(dev, "extern1");
  465. if (IS_ERR(clk_extern1)) {
  466. dev_err(dev, "Can't retrieve clk extern1\n");
  467. return PTR_ERR(clk_extern1);
  468. }
  469. err = clk_set_parent(clk_extern1, machine->clk_pll_a_out0);
  470. if (err < 0) {
  471. dev_err(dev, "Set parent failed for clk extern1\n");
  472. return err;
  473. }
  474. clk_out_1 = devm_clk_get(dev, "pmc_clk_out_1");
  475. if (IS_ERR(clk_out_1)) {
  476. dev_err(dev, "Can't retrieve pmc_clk_out_1\n");
  477. return PTR_ERR(clk_out_1);
  478. }
  479. err = clk_set_parent(clk_out_1, clk_extern1);
  480. if (err < 0) {
  481. dev_err(dev, "Set parent failed for pmc_clk_out_1\n");
  482. return err;
  483. }
  484. machine->clk_cdev1 = clk_out_1;
  485. }
  486. if (asoc->set_ac97) {
  487. /*
  488. * AC97 rate is fixed at 24.576MHz and is used for both the
  489. * host controller and the external codec
  490. */
  491. err = clk_set_rate(machine->clk_pll_a, 73728000);
  492. if (err) {
  493. dev_err(dev, "Can't set pll_a rate: %d\n", err);
  494. return err;
  495. }
  496. err = clk_set_rate(machine->clk_pll_a_out0, 24576000);
  497. if (err) {
  498. dev_err(dev, "Can't set pll_a_out0 rate: %d\n", err);
  499. return err;
  500. }
  501. machine->set_baseclock = 73728000;
  502. machine->set_mclk = 24576000;
  503. }
  504. /*
  505. * FIXME: There is some unknown dependency between audio MCLK disable
  506. * and suspend-resume functionality on Tegra30, although audio MCLK is
  507. * only needed for audio.
  508. */
  509. err = clk_prepare_enable(machine->clk_cdev1);
  510. if (err) {
  511. dev_err(dev, "Can't enable cdev1: %d\n", err);
  512. return err;
  513. }
  514. err = devm_snd_soc_register_card(dev, card);
  515. if (err)
  516. return err;
  517. return 0;
  518. }
  519. EXPORT_SYMBOL_GPL(tegra_asoc_machine_probe);
  520. /* WM8753 machine */
  521. SND_SOC_DAILINK_DEFS(wm8753_hifi,
  522. DAILINK_COMP_ARRAY(COMP_EMPTY()),
  523. DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "wm8753-hifi")),
  524. DAILINK_COMP_ARRAY(COMP_EMPTY()));
  525. static struct snd_soc_dai_link tegra_wm8753_dai = {
  526. .name = "WM8753",
  527. .stream_name = "WM8753 PCM",
  528. .dai_fmt = SND_SOC_DAIFMT_I2S |
  529. SND_SOC_DAIFMT_NB_NF |
  530. SND_SOC_DAIFMT_CBS_CFS,
  531. SND_SOC_DAILINK_REG(wm8753_hifi),
  532. };
  533. static struct snd_soc_card snd_soc_tegra_wm8753 = {
  534. .components = "codec:wm8753",
  535. .dai_link = &tegra_wm8753_dai,
  536. .num_links = 1,
  537. .fully_routed = true,
  538. };
  539. static const struct tegra_asoc_data tegra_wm8753_data = {
  540. .mclk_rate = tegra_machine_mclk_rate_12mhz,
  541. .card = &snd_soc_tegra_wm8753,
  542. .add_common_dapm_widgets = true,
  543. .add_common_snd_ops = true,
  544. };
  545. /* WM9712 machine */
  546. static int tegra_wm9712_init(struct snd_soc_pcm_runtime *rtd)
  547. {
  548. return snd_soc_dapm_force_enable_pin(&rtd->card->dapm, "Mic Bias");
  549. }
  550. SND_SOC_DAILINK_DEFS(wm9712_hifi,
  551. DAILINK_COMP_ARRAY(COMP_EMPTY()),
  552. DAILINK_COMP_ARRAY(COMP_CODEC("wm9712-codec", "wm9712-hifi")),
  553. DAILINK_COMP_ARRAY(COMP_EMPTY()));
  554. static struct snd_soc_dai_link tegra_wm9712_dai = {
  555. .name = "AC97 HiFi",
  556. .stream_name = "AC97 HiFi",
  557. .init = tegra_wm9712_init,
  558. SND_SOC_DAILINK_REG(wm9712_hifi),
  559. };
  560. static struct snd_soc_card snd_soc_tegra_wm9712 = {
  561. .components = "codec:wm9712",
  562. .dai_link = &tegra_wm9712_dai,
  563. .num_links = 1,
  564. .fully_routed = true,
  565. };
  566. static const struct tegra_asoc_data tegra_wm9712_data = {
  567. .card = &snd_soc_tegra_wm9712,
  568. .add_common_dapm_widgets = true,
  569. .codec_dev_name = "wm9712-codec",
  570. .set_ac97 = true,
  571. };
  572. /* MAX98090 machine */
  573. SND_SOC_DAILINK_DEFS(max98090_hifi,
  574. DAILINK_COMP_ARRAY(COMP_EMPTY()),
  575. DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "HiFi")),
  576. DAILINK_COMP_ARRAY(COMP_EMPTY()));
  577. static struct snd_soc_dai_link tegra_max98090_dai = {
  578. .name = "max98090",
  579. .stream_name = "max98090 PCM",
  580. .init = tegra_asoc_machine_init,
  581. .dai_fmt = SND_SOC_DAIFMT_I2S |
  582. SND_SOC_DAIFMT_NB_NF |
  583. SND_SOC_DAIFMT_CBS_CFS,
  584. SND_SOC_DAILINK_REG(max98090_hifi),
  585. };
  586. static struct snd_soc_card snd_soc_tegra_max98090 = {
  587. .components = "codec:max98090",
  588. .dai_link = &tegra_max98090_dai,
  589. .num_links = 1,
  590. .fully_routed = true,
  591. };
  592. static const struct tegra_asoc_data tegra_max98090_data = {
  593. .mclk_rate = tegra_machine_mclk_rate_12mhz,
  594. .card = &snd_soc_tegra_max98090,
  595. .hp_jack_name = "Headphones",
  596. .add_common_dapm_widgets = true,
  597. .add_common_controls = true,
  598. .add_common_snd_ops = true,
  599. .add_mic_jack = true,
  600. .add_hp_jack = true,
  601. };
  602. /* MAX98088 machine */
  603. SND_SOC_DAILINK_DEFS(max98088_hifi,
  604. DAILINK_COMP_ARRAY(COMP_EMPTY()),
  605. DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "HiFi")),
  606. DAILINK_COMP_ARRAY(COMP_EMPTY()));
  607. static struct snd_soc_dai_link tegra_max98088_dai = {
  608. .name = "MAX98088",
  609. .stream_name = "MAX98088 PCM",
  610. .init = tegra_asoc_machine_init,
  611. .dai_fmt = SND_SOC_DAIFMT_I2S |
  612. SND_SOC_DAIFMT_NB_NF |
  613. SND_SOC_DAIFMT_CBS_CFS,
  614. SND_SOC_DAILINK_REG(max98088_hifi),
  615. };
  616. static struct snd_soc_card snd_soc_tegra_max98088 = {
  617. .components = "codec:max98088",
  618. .dai_link = &tegra_max98088_dai,
  619. .num_links = 1,
  620. .fully_routed = true,
  621. };
  622. static const struct tegra_asoc_data tegra_max98088_data = {
  623. .mclk_rate = tegra_machine_mclk_rate_12mhz,
  624. .card = &snd_soc_tegra_max98088,
  625. .add_common_dapm_widgets = true,
  626. .add_common_controls = true,
  627. .add_common_snd_ops = true,
  628. .add_mic_jack = true,
  629. .add_hp_jack = true,
  630. };
  631. /* SGTL5000 machine */
  632. SND_SOC_DAILINK_DEFS(sgtl5000_hifi,
  633. DAILINK_COMP_ARRAY(COMP_EMPTY()),
  634. DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "sgtl5000")),
  635. DAILINK_COMP_ARRAY(COMP_EMPTY()));
  636. static struct snd_soc_dai_link tegra_sgtl5000_dai = {
  637. .name = "sgtl5000",
  638. .stream_name = "HiFi",
  639. .dai_fmt = SND_SOC_DAIFMT_I2S |
  640. SND_SOC_DAIFMT_NB_NF |
  641. SND_SOC_DAIFMT_CBS_CFS,
  642. SND_SOC_DAILINK_REG(sgtl5000_hifi),
  643. };
  644. static struct snd_soc_card snd_soc_tegra_sgtl5000 = {
  645. .components = "codec:sgtl5000",
  646. .dai_link = &tegra_sgtl5000_dai,
  647. .num_links = 1,
  648. .fully_routed = true,
  649. };
  650. static const struct tegra_asoc_data tegra_sgtl5000_data = {
  651. .mclk_rate = tegra_machine_mclk_rate_12mhz,
  652. .card = &snd_soc_tegra_sgtl5000,
  653. .add_common_dapm_widgets = true,
  654. .add_common_snd_ops = true,
  655. };
  656. /* TLV320AIC23 machine */
  657. static const struct snd_soc_dapm_widget trimslice_dapm_widgets[] = {
  658. SND_SOC_DAPM_HP("Line Out", NULL),
  659. SND_SOC_DAPM_LINE("Line In", NULL),
  660. };
  661. static const struct snd_soc_dapm_route trimslice_audio_map[] = {
  662. {"Line Out", NULL, "LOUT"},
  663. {"Line Out", NULL, "ROUT"},
  664. {"LLINEIN", NULL, "Line In"},
  665. {"RLINEIN", NULL, "Line In"},
  666. };
  667. SND_SOC_DAILINK_DEFS(tlv320aic23_hifi,
  668. DAILINK_COMP_ARRAY(COMP_EMPTY()),
  669. DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "tlv320aic23-hifi")),
  670. DAILINK_COMP_ARRAY(COMP_EMPTY()));
  671. static struct snd_soc_dai_link tegra_tlv320aic23_dai = {
  672. .name = "TLV320AIC23",
  673. .stream_name = "AIC23",
  674. .dai_fmt = SND_SOC_DAIFMT_I2S |
  675. SND_SOC_DAIFMT_NB_NF |
  676. SND_SOC_DAIFMT_CBS_CFS,
  677. SND_SOC_DAILINK_REG(tlv320aic23_hifi),
  678. };
  679. static struct snd_soc_card snd_soc_tegra_trimslice = {
  680. .name = "tegra-trimslice",
  681. .components = "codec:tlv320aic23",
  682. .dai_link = &tegra_tlv320aic23_dai,
  683. .num_links = 1,
  684. .dapm_widgets = trimslice_dapm_widgets,
  685. .num_dapm_widgets = ARRAY_SIZE(trimslice_dapm_widgets),
  686. .dapm_routes = trimslice_audio_map,
  687. .num_dapm_routes = ARRAY_SIZE(trimslice_audio_map),
  688. .fully_routed = true,
  689. };
  690. static const struct tegra_asoc_data tegra_trimslice_data = {
  691. .mclk_rate = tegra_machine_mclk_rate_128,
  692. .card = &snd_soc_tegra_trimslice,
  693. .add_common_snd_ops = true,
  694. };
  695. /* RT5677 machine */
  696. static int tegra_rt5677_init(struct snd_soc_pcm_runtime *rtd)
  697. {
  698. struct snd_soc_card *card = rtd->card;
  699. int err;
  700. err = tegra_asoc_machine_init(rtd);
  701. if (err)
  702. return err;
  703. snd_soc_dapm_force_enable_pin(&card->dapm, "MICBIAS1");
  704. return 0;
  705. }
  706. SND_SOC_DAILINK_DEFS(rt5677_aif1,
  707. DAILINK_COMP_ARRAY(COMP_EMPTY()),
  708. DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "rt5677-aif1")),
  709. DAILINK_COMP_ARRAY(COMP_EMPTY()));
  710. static struct snd_soc_dai_link tegra_rt5677_dai = {
  711. .name = "RT5677",
  712. .stream_name = "RT5677 PCM",
  713. .init = tegra_rt5677_init,
  714. .dai_fmt = SND_SOC_DAIFMT_I2S |
  715. SND_SOC_DAIFMT_NB_NF |
  716. SND_SOC_DAIFMT_CBS_CFS,
  717. SND_SOC_DAILINK_REG(rt5677_aif1),
  718. };
  719. static struct snd_soc_card snd_soc_tegra_rt5677 = {
  720. .components = "codec:rt5677",
  721. .dai_link = &tegra_rt5677_dai,
  722. .num_links = 1,
  723. .fully_routed = true,
  724. };
  725. static const struct tegra_asoc_data tegra_rt5677_data = {
  726. .mclk_rate = tegra_machine_mclk_rate_256,
  727. .card = &snd_soc_tegra_rt5677,
  728. .add_common_dapm_widgets = true,
  729. .add_common_controls = true,
  730. .add_common_snd_ops = true,
  731. .add_mic_jack = true,
  732. .add_hp_jack = true,
  733. };
  734. /* RT5640 machine */
  735. SND_SOC_DAILINK_DEFS(rt5640_aif1,
  736. DAILINK_COMP_ARRAY(COMP_EMPTY()),
  737. DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "rt5640-aif1")),
  738. DAILINK_COMP_ARRAY(COMP_EMPTY()));
  739. static struct snd_soc_dai_link tegra_rt5640_dai = {
  740. .name = "RT5640",
  741. .stream_name = "RT5640 PCM",
  742. .init = tegra_asoc_machine_init,
  743. .dai_fmt = SND_SOC_DAIFMT_I2S |
  744. SND_SOC_DAIFMT_NB_NF |
  745. SND_SOC_DAIFMT_CBS_CFS,
  746. SND_SOC_DAILINK_REG(rt5640_aif1),
  747. };
  748. static struct snd_soc_card snd_soc_tegra_rt5640 = {
  749. .components = "codec:rt5640",
  750. .dai_link = &tegra_rt5640_dai,
  751. .num_links = 1,
  752. .fully_routed = true,
  753. };
  754. static const struct tegra_asoc_data tegra_rt5640_data = {
  755. .mclk_rate = tegra_machine_mclk_rate_256,
  756. .card = &snd_soc_tegra_rt5640,
  757. .add_common_dapm_widgets = true,
  758. .add_common_controls = true,
  759. .add_common_snd_ops = true,
  760. .add_hp_jack = true,
  761. };
  762. /* RT5632 machine */
  763. SND_SOC_DAILINK_DEFS(rt5632_hifi,
  764. DAILINK_COMP_ARRAY(COMP_EMPTY()),
  765. DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "alc5632-hifi")),
  766. DAILINK_COMP_ARRAY(COMP_EMPTY()));
  767. static struct snd_soc_dai_link tegra_rt5632_dai = {
  768. .name = "ALC5632",
  769. .stream_name = "ALC5632 PCM",
  770. .init = tegra_rt5677_init,
  771. .dai_fmt = SND_SOC_DAIFMT_I2S |
  772. SND_SOC_DAIFMT_NB_NF |
  773. SND_SOC_DAIFMT_CBS_CFS,
  774. SND_SOC_DAILINK_REG(rt5632_hifi),
  775. };
  776. static struct snd_soc_card snd_soc_tegra_rt5632 = {
  777. .components = "codec:rt5632",
  778. .dai_link = &tegra_rt5632_dai,
  779. .num_links = 1,
  780. .fully_routed = true,
  781. };
  782. static const struct tegra_asoc_data tegra_rt5632_data = {
  783. .mclk_rate = tegra_machine_mclk_rate_512,
  784. .card = &snd_soc_tegra_rt5632,
  785. .add_common_dapm_widgets = true,
  786. .add_common_controls = true,
  787. .add_common_snd_ops = true,
  788. .add_headset_jack = true,
  789. };
  790. /* RT5631 machine */
  791. SND_SOC_DAILINK_DEFS(rt5631_hifi,
  792. DAILINK_COMP_ARRAY(COMP_EMPTY()),
  793. DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "rt5631-hifi")),
  794. DAILINK_COMP_ARRAY(COMP_EMPTY()));
  795. static struct snd_soc_dai_link tegra_rt5631_dai = {
  796. .name = "RT5631",
  797. .stream_name = "RT5631 PCM",
  798. .init = tegra_asoc_machine_init,
  799. .dai_fmt = SND_SOC_DAIFMT_I2S |
  800. SND_SOC_DAIFMT_NB_NF |
  801. SND_SOC_DAIFMT_CBS_CFS,
  802. SND_SOC_DAILINK_REG(rt5631_hifi),
  803. };
  804. static struct snd_soc_card snd_soc_tegra_rt5631 = {
  805. .components = "codec:rt5631",
  806. .dai_link = &tegra_rt5631_dai,
  807. .num_links = 1,
  808. .fully_routed = true,
  809. };
  810. static const struct tegra_asoc_data tegra_rt5631_data = {
  811. .mclk_rate = tegra_machine_mclk_rate_6mhz,
  812. .card = &snd_soc_tegra_rt5631,
  813. .add_common_dapm_widgets = true,
  814. .add_common_controls = true,
  815. .add_common_snd_ops = true,
  816. .add_mic_jack = true,
  817. .add_hp_jack = true,
  818. };
  819. static const struct of_device_id tegra_machine_of_match[] = {
  820. { .compatible = "nvidia,tegra-audio-trimslice", .data = &tegra_trimslice_data },
  821. { .compatible = "nvidia,tegra-audio-max98090", .data = &tegra_max98090_data },
  822. { .compatible = "nvidia,tegra-audio-max98088", .data = &tegra_max98088_data },
  823. { .compatible = "nvidia,tegra-audio-max98089", .data = &tegra_max98088_data },
  824. { .compatible = "nvidia,tegra-audio-sgtl5000", .data = &tegra_sgtl5000_data },
  825. { .compatible = "nvidia,tegra-audio-wm9712", .data = &tegra_wm9712_data },
  826. { .compatible = "nvidia,tegra-audio-wm8753", .data = &tegra_wm8753_data },
  827. { .compatible = "nvidia,tegra-audio-rt5677", .data = &tegra_rt5677_data },
  828. { .compatible = "nvidia,tegra-audio-rt5640", .data = &tegra_rt5640_data },
  829. { .compatible = "nvidia,tegra-audio-alc5632", .data = &tegra_rt5632_data },
  830. { .compatible = "nvidia,tegra-audio-rt5631", .data = &tegra_rt5631_data },
  831. {},
  832. };
  833. MODULE_DEVICE_TABLE(of, tegra_machine_of_match);
  834. static struct platform_driver tegra_asoc_machine_driver = {
  835. .driver = {
  836. .name = "tegra-audio",
  837. .of_match_table = tegra_machine_of_match,
  838. .pm = &snd_soc_pm_ops,
  839. },
  840. .probe = tegra_asoc_machine_probe,
  841. };
  842. module_platform_driver(tegra_asoc_machine_driver);
  843. MODULE_AUTHOR("Anatol Pomozov <anatol@google.com>");
  844. MODULE_AUTHOR("Andrey Danin <danindrey@mail.ru>");
  845. MODULE_AUTHOR("Dmitry Osipenko <digetx@gmail.com>");
  846. MODULE_AUTHOR("Ion Agorria <ion@agorria.com>");
  847. MODULE_AUTHOR("Leon Romanovsky <leon@leon.nu>");
  848. MODULE_AUTHOR("Lucas Stach <dev@lynxeye.de>");
  849. MODULE_AUTHOR("Marc Dietrich <marvin24@gmx.de>");
  850. MODULE_AUTHOR("Marcel Ziswiler <marcel@ziswiler.com>");
  851. MODULE_AUTHOR("Mike Rapoport <mike@compulab.co.il>");
  852. MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>");
  853. MODULE_AUTHOR("Svyatoslav Ryhel <clamor95@gmail.com>");
  854. MODULE_DESCRIPTION("Tegra machine ASoC driver");
  855. MODULE_LICENSE("GPL");