bxt_rt298.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634
  1. /*
  2. * Intel Broxton-P I2S Machine Driver
  3. *
  4. * Copyright (C) 2014-2016, Intel Corporation. All rights reserved.
  5. *
  6. * Modified from:
  7. * Intel Skylake I2S Machine driver
  8. *
  9. * This program is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU General Public License version
  11. * 2 as published by the Free Software Foundation.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. */
  18. #include <linux/module.h>
  19. #include <linux/platform_device.h>
  20. #include <sound/core.h>
  21. #include <sound/pcm.h>
  22. #include <sound/soc.h>
  23. #include <sound/jack.h>
  24. #include <sound/pcm_params.h>
  25. #include "../../codecs/hdac_hdmi.h"
  26. #include "../../codecs/rt298.h"
  27. /* Headset jack detection DAPM pins */
  28. static struct snd_soc_jack broxton_headset;
  29. static struct snd_soc_jack broxton_hdmi[3];
  30. struct bxt_hdmi_pcm {
  31. struct list_head head;
  32. struct snd_soc_dai *codec_dai;
  33. int device;
  34. };
  35. struct bxt_rt286_private {
  36. struct list_head hdmi_pcm_list;
  37. };
  38. enum {
  39. BXT_DPCM_AUDIO_PB = 0,
  40. BXT_DPCM_AUDIO_CP,
  41. BXT_DPCM_AUDIO_REF_CP,
  42. BXT_DPCM_AUDIO_DMIC_CP,
  43. BXT_DPCM_AUDIO_HDMI1_PB,
  44. BXT_DPCM_AUDIO_HDMI2_PB,
  45. BXT_DPCM_AUDIO_HDMI3_PB,
  46. };
  47. static struct snd_soc_jack_pin broxton_headset_pins[] = {
  48. {
  49. .pin = "Mic Jack",
  50. .mask = SND_JACK_MICROPHONE,
  51. },
  52. {
  53. .pin = "Headphone Jack",
  54. .mask = SND_JACK_HEADPHONE,
  55. },
  56. };
  57. static const struct snd_kcontrol_new broxton_controls[] = {
  58. SOC_DAPM_PIN_SWITCH("Speaker"),
  59. SOC_DAPM_PIN_SWITCH("Headphone Jack"),
  60. SOC_DAPM_PIN_SWITCH("Mic Jack"),
  61. };
  62. static const struct snd_soc_dapm_widget broxton_widgets[] = {
  63. SND_SOC_DAPM_HP("Headphone Jack", NULL),
  64. SND_SOC_DAPM_SPK("Speaker", NULL),
  65. SND_SOC_DAPM_MIC("Mic Jack", NULL),
  66. SND_SOC_DAPM_MIC("DMIC2", NULL),
  67. SND_SOC_DAPM_MIC("SoC DMIC", NULL),
  68. SND_SOC_DAPM_SPK("HDMI1", NULL),
  69. SND_SOC_DAPM_SPK("HDMI2", NULL),
  70. SND_SOC_DAPM_SPK("HDMI3", NULL),
  71. };
  72. static const struct snd_soc_dapm_route broxton_rt298_map[] = {
  73. /* speaker */
  74. {"Speaker", NULL, "SPOR"},
  75. {"Speaker", NULL, "SPOL"},
  76. /* HP jack connectors - unknown if we have jack detect */
  77. {"Headphone Jack", NULL, "HPO Pin"},
  78. /* other jacks */
  79. {"MIC1", NULL, "Mic Jack"},
  80. /* digital mics */
  81. {"DMIC1 Pin", NULL, "DMIC2"},
  82. {"DMic", NULL, "SoC DMIC"},
  83. {"HDMI1", NULL, "hif5-0 Output"},
  84. {"HDMI2", NULL, "hif6-0 Output"},
  85. {"HDMI2", NULL, "hif7-0 Output"},
  86. /* CODEC BE connections */
  87. { "AIF1 Playback", NULL, "ssp5 Tx"},
  88. { "ssp5 Tx", NULL, "codec0_out"},
  89. { "ssp5 Tx", NULL, "codec1_out"},
  90. { "codec0_in", NULL, "ssp5 Rx" },
  91. { "ssp5 Rx", NULL, "AIF1 Capture" },
  92. { "dmic01_hifi", NULL, "DMIC01 Rx" },
  93. { "DMIC01 Rx", NULL, "Capture" },
  94. { "hifi3", NULL, "iDisp3 Tx"},
  95. { "iDisp3 Tx", NULL, "iDisp3_out"},
  96. { "hifi2", NULL, "iDisp2 Tx"},
  97. { "iDisp2 Tx", NULL, "iDisp2_out"},
  98. { "hifi1", NULL, "iDisp1 Tx"},
  99. { "iDisp1 Tx", NULL, "iDisp1_out"},
  100. };
  101. static const struct snd_soc_dapm_route geminilake_rt298_map[] = {
  102. /* speaker */
  103. {"Speaker", NULL, "SPOR"},
  104. {"Speaker", NULL, "SPOL"},
  105. /* HP jack connectors - unknown if we have jack detect */
  106. {"Headphone Jack", NULL, "HPO Pin"},
  107. /* other jacks */
  108. {"MIC1", NULL, "Mic Jack"},
  109. /* digital mics */
  110. {"DMIC1 Pin", NULL, "DMIC2"},
  111. {"DMic", NULL, "SoC DMIC"},
  112. {"HDMI1", NULL, "hif5-0 Output"},
  113. {"HDMI2", NULL, "hif6-0 Output"},
  114. {"HDMI2", NULL, "hif7-0 Output"},
  115. /* CODEC BE connections */
  116. { "AIF1 Playback", NULL, "ssp2 Tx"},
  117. { "ssp2 Tx", NULL, "codec0_out"},
  118. { "ssp2 Tx", NULL, "codec1_out"},
  119. { "codec0_in", NULL, "ssp2 Rx" },
  120. { "ssp2 Rx", NULL, "AIF1 Capture" },
  121. { "dmic01_hifi", NULL, "DMIC01 Rx" },
  122. { "DMIC01 Rx", NULL, "Capture" },
  123. { "dmic_voice", NULL, "DMIC16k Rx" },
  124. { "DMIC16k Rx", NULL, "Capture" },
  125. { "hifi3", NULL, "iDisp3 Tx"},
  126. { "iDisp3 Tx", NULL, "iDisp3_out"},
  127. { "hifi2", NULL, "iDisp2 Tx"},
  128. { "iDisp2 Tx", NULL, "iDisp2_out"},
  129. { "hifi1", NULL, "iDisp1 Tx"},
  130. { "iDisp1 Tx", NULL, "iDisp1_out"},
  131. };
  132. static int broxton_rt298_fe_init(struct snd_soc_pcm_runtime *rtd)
  133. {
  134. struct snd_soc_dapm_context *dapm;
  135. struct snd_soc_component *component = rtd->cpu_dai->component;
  136. dapm = snd_soc_component_get_dapm(component);
  137. snd_soc_dapm_ignore_suspend(dapm, "Reference Capture");
  138. return 0;
  139. }
  140. static int broxton_rt298_codec_init(struct snd_soc_pcm_runtime *rtd)
  141. {
  142. struct snd_soc_component *component = rtd->codec_dai->component;
  143. int ret = 0;
  144. ret = snd_soc_card_jack_new(rtd->card, "Headset",
  145. SND_JACK_HEADSET | SND_JACK_BTN_0,
  146. &broxton_headset,
  147. broxton_headset_pins, ARRAY_SIZE(broxton_headset_pins));
  148. if (ret)
  149. return ret;
  150. rt298_mic_detect(component, &broxton_headset);
  151. snd_soc_dapm_ignore_suspend(&rtd->card->dapm, "SoC DMIC");
  152. return 0;
  153. }
  154. static int broxton_hdmi_init(struct snd_soc_pcm_runtime *rtd)
  155. {
  156. struct bxt_rt286_private *ctx = snd_soc_card_get_drvdata(rtd->card);
  157. struct snd_soc_dai *dai = rtd->codec_dai;
  158. struct bxt_hdmi_pcm *pcm;
  159. pcm = devm_kzalloc(rtd->card->dev, sizeof(*pcm), GFP_KERNEL);
  160. if (!pcm)
  161. return -ENOMEM;
  162. pcm->device = BXT_DPCM_AUDIO_HDMI1_PB + dai->id;
  163. pcm->codec_dai = dai;
  164. list_add_tail(&pcm->head, &ctx->hdmi_pcm_list);
  165. return 0;
  166. }
  167. static int broxton_ssp5_fixup(struct snd_soc_pcm_runtime *rtd,
  168. struct snd_pcm_hw_params *params)
  169. {
  170. struct snd_interval *rate = hw_param_interval(params,
  171. SNDRV_PCM_HW_PARAM_RATE);
  172. struct snd_interval *channels = hw_param_interval(params,
  173. SNDRV_PCM_HW_PARAM_CHANNELS);
  174. struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
  175. /* The ADSP will covert the FE rate to 48k, stereo */
  176. rate->min = rate->max = 48000;
  177. channels->min = channels->max = 2;
  178. /* set SSP5 to 24 bit */
  179. snd_mask_none(fmt);
  180. snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S24_LE);
  181. return 0;
  182. }
  183. static int broxton_rt298_hw_params(struct snd_pcm_substream *substream,
  184. struct snd_pcm_hw_params *params)
  185. {
  186. struct snd_soc_pcm_runtime *rtd = substream->private_data;
  187. struct snd_soc_dai *codec_dai = rtd->codec_dai;
  188. int ret;
  189. ret = snd_soc_dai_set_sysclk(codec_dai, RT298_SCLK_S_PLL,
  190. 19200000, SND_SOC_CLOCK_IN);
  191. if (ret < 0) {
  192. dev_err(rtd->dev, "can't set codec sysclk configuration\n");
  193. return ret;
  194. }
  195. return ret;
  196. }
  197. static const struct snd_soc_ops broxton_rt298_ops = {
  198. .hw_params = broxton_rt298_hw_params,
  199. };
  200. static const unsigned int rates[] = {
  201. 48000,
  202. };
  203. static const struct snd_pcm_hw_constraint_list constraints_rates = {
  204. .count = ARRAY_SIZE(rates),
  205. .list = rates,
  206. .mask = 0,
  207. };
  208. static int broxton_dmic_fixup(struct snd_soc_pcm_runtime *rtd,
  209. struct snd_pcm_hw_params *params)
  210. {
  211. struct snd_interval *channels = hw_param_interval(params,
  212. SNDRV_PCM_HW_PARAM_CHANNELS);
  213. channels->min = channels->max = 4;
  214. return 0;
  215. }
  216. static const unsigned int channels_dmic[] = {
  217. 1, 2, 3, 4,
  218. };
  219. static const struct snd_pcm_hw_constraint_list constraints_dmic_channels = {
  220. .count = ARRAY_SIZE(channels_dmic),
  221. .list = channels_dmic,
  222. .mask = 0,
  223. };
  224. static int broxton_dmic_startup(struct snd_pcm_substream *substream)
  225. {
  226. struct snd_pcm_runtime *runtime = substream->runtime;
  227. runtime->hw.channels_max = 4;
  228. snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
  229. &constraints_dmic_channels);
  230. return snd_pcm_hw_constraint_list(substream->runtime, 0,
  231. SNDRV_PCM_HW_PARAM_RATE, &constraints_rates);
  232. }
  233. static const struct snd_soc_ops broxton_dmic_ops = {
  234. .startup = broxton_dmic_startup,
  235. };
  236. static const unsigned int channels[] = {
  237. 2,
  238. };
  239. static const struct snd_pcm_hw_constraint_list constraints_channels = {
  240. .count = ARRAY_SIZE(channels),
  241. .list = channels,
  242. .mask = 0,
  243. };
  244. static int bxt_fe_startup(struct snd_pcm_substream *substream)
  245. {
  246. struct snd_pcm_runtime *runtime = substream->runtime;
  247. /*
  248. * on this platform for PCM device we support:
  249. * 48Khz
  250. * stereo
  251. * 16-bit audio
  252. */
  253. runtime->hw.channels_max = 2;
  254. snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
  255. &constraints_channels);
  256. runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE;
  257. snd_pcm_hw_constraint_msbits(runtime, 0, 16, 16);
  258. snd_pcm_hw_constraint_list(runtime, 0,
  259. SNDRV_PCM_HW_PARAM_RATE, &constraints_rates);
  260. return 0;
  261. }
  262. static const struct snd_soc_ops broxton_rt286_fe_ops = {
  263. .startup = bxt_fe_startup,
  264. };
  265. /* broxton digital audio interface glue - connects codec <--> CPU */
  266. static struct snd_soc_dai_link broxton_rt298_dais[] = {
  267. /* Front End DAI links */
  268. [BXT_DPCM_AUDIO_PB] =
  269. {
  270. .name = "Bxt Audio Port",
  271. .stream_name = "Audio",
  272. .cpu_dai_name = "System Pin",
  273. .platform_name = "0000:00:0e.0",
  274. .nonatomic = 1,
  275. .dynamic = 1,
  276. .codec_name = "snd-soc-dummy",
  277. .codec_dai_name = "snd-soc-dummy-dai",
  278. .init = broxton_rt298_fe_init,
  279. .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
  280. .dpcm_playback = 1,
  281. .ops = &broxton_rt286_fe_ops,
  282. },
  283. [BXT_DPCM_AUDIO_CP] =
  284. {
  285. .name = "Bxt Audio Capture Port",
  286. .stream_name = "Audio Record",
  287. .cpu_dai_name = "System Pin",
  288. .platform_name = "0000:00:0e.0",
  289. .nonatomic = 1,
  290. .dynamic = 1,
  291. .codec_name = "snd-soc-dummy",
  292. .codec_dai_name = "snd-soc-dummy-dai",
  293. .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
  294. .dpcm_capture = 1,
  295. .ops = &broxton_rt286_fe_ops,
  296. },
  297. [BXT_DPCM_AUDIO_REF_CP] =
  298. {
  299. .name = "Bxt Audio Reference cap",
  300. .stream_name = "refcap",
  301. .cpu_dai_name = "Reference Pin",
  302. .codec_name = "snd-soc-dummy",
  303. .codec_dai_name = "snd-soc-dummy-dai",
  304. .platform_name = "0000:00:0e.0",
  305. .init = NULL,
  306. .dpcm_capture = 1,
  307. .nonatomic = 1,
  308. .dynamic = 1,
  309. },
  310. [BXT_DPCM_AUDIO_DMIC_CP] =
  311. {
  312. .name = "Bxt Audio DMIC cap",
  313. .stream_name = "dmiccap",
  314. .cpu_dai_name = "DMIC Pin",
  315. .codec_name = "snd-soc-dummy",
  316. .codec_dai_name = "snd-soc-dummy-dai",
  317. .platform_name = "0000:00:0e.0",
  318. .init = NULL,
  319. .dpcm_capture = 1,
  320. .nonatomic = 1,
  321. .dynamic = 1,
  322. .ops = &broxton_dmic_ops,
  323. },
  324. [BXT_DPCM_AUDIO_HDMI1_PB] =
  325. {
  326. .name = "Bxt HDMI Port1",
  327. .stream_name = "Hdmi1",
  328. .cpu_dai_name = "HDMI1 Pin",
  329. .codec_name = "snd-soc-dummy",
  330. .codec_dai_name = "snd-soc-dummy-dai",
  331. .platform_name = "0000:00:0e.0",
  332. .dpcm_playback = 1,
  333. .init = NULL,
  334. .nonatomic = 1,
  335. .dynamic = 1,
  336. },
  337. [BXT_DPCM_AUDIO_HDMI2_PB] =
  338. {
  339. .name = "Bxt HDMI Port2",
  340. .stream_name = "Hdmi2",
  341. .cpu_dai_name = "HDMI2 Pin",
  342. .codec_name = "snd-soc-dummy",
  343. .codec_dai_name = "snd-soc-dummy-dai",
  344. .platform_name = "0000:00:0e.0",
  345. .dpcm_playback = 1,
  346. .init = NULL,
  347. .nonatomic = 1,
  348. .dynamic = 1,
  349. },
  350. [BXT_DPCM_AUDIO_HDMI3_PB] =
  351. {
  352. .name = "Bxt HDMI Port3",
  353. .stream_name = "Hdmi3",
  354. .cpu_dai_name = "HDMI3 Pin",
  355. .codec_name = "snd-soc-dummy",
  356. .codec_dai_name = "snd-soc-dummy-dai",
  357. .platform_name = "0000:00:0e.0",
  358. .dpcm_playback = 1,
  359. .init = NULL,
  360. .nonatomic = 1,
  361. .dynamic = 1,
  362. },
  363. /* Back End DAI links */
  364. {
  365. /* SSP5 - Codec */
  366. .name = "SSP5-Codec",
  367. .id = 0,
  368. .cpu_dai_name = "SSP5 Pin",
  369. .platform_name = "0000:00:0e.0",
  370. .no_pcm = 1,
  371. .codec_name = "i2c-INT343A:00",
  372. .codec_dai_name = "rt298-aif1",
  373. .init = broxton_rt298_codec_init,
  374. .dai_fmt = SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_NB_NF |
  375. SND_SOC_DAIFMT_CBS_CFS,
  376. .ignore_pmdown_time = 1,
  377. .be_hw_params_fixup = broxton_ssp5_fixup,
  378. .ops = &broxton_rt298_ops,
  379. .dpcm_playback = 1,
  380. .dpcm_capture = 1,
  381. },
  382. {
  383. .name = "dmic01",
  384. .id = 1,
  385. .cpu_dai_name = "DMIC01 Pin",
  386. .codec_name = "dmic-codec",
  387. .codec_dai_name = "dmic-hifi",
  388. .platform_name = "0000:00:0e.0",
  389. .be_hw_params_fixup = broxton_dmic_fixup,
  390. .ignore_suspend = 1,
  391. .dpcm_capture = 1,
  392. .no_pcm = 1,
  393. },
  394. {
  395. .name = "dmic16k",
  396. .id = 2,
  397. .cpu_dai_name = "DMIC16k Pin",
  398. .codec_name = "dmic-codec",
  399. .codec_dai_name = "dmic-hifi",
  400. .platform_name = "0000:00:0e.0",
  401. .be_hw_params_fixup = broxton_dmic_fixup,
  402. .ignore_suspend = 1,
  403. .dpcm_capture = 1,
  404. .no_pcm = 1,
  405. },
  406. {
  407. .name = "iDisp1",
  408. .id = 3,
  409. .cpu_dai_name = "iDisp1 Pin",
  410. .codec_name = "ehdaudio0D2",
  411. .codec_dai_name = "intel-hdmi-hifi1",
  412. .platform_name = "0000:00:0e.0",
  413. .init = broxton_hdmi_init,
  414. .dpcm_playback = 1,
  415. .no_pcm = 1,
  416. },
  417. {
  418. .name = "iDisp2",
  419. .id = 4,
  420. .cpu_dai_name = "iDisp2 Pin",
  421. .codec_name = "ehdaudio0D2",
  422. .codec_dai_name = "intel-hdmi-hifi2",
  423. .platform_name = "0000:00:0e.0",
  424. .init = broxton_hdmi_init,
  425. .dpcm_playback = 1,
  426. .no_pcm = 1,
  427. },
  428. {
  429. .name = "iDisp3",
  430. .id = 5,
  431. .cpu_dai_name = "iDisp3 Pin",
  432. .codec_name = "ehdaudio0D2",
  433. .codec_dai_name = "intel-hdmi-hifi3",
  434. .platform_name = "0000:00:0e.0",
  435. .init = broxton_hdmi_init,
  436. .dpcm_playback = 1,
  437. .no_pcm = 1,
  438. },
  439. };
  440. #define NAME_SIZE 32
  441. static int bxt_card_late_probe(struct snd_soc_card *card)
  442. {
  443. struct bxt_rt286_private *ctx = snd_soc_card_get_drvdata(card);
  444. struct bxt_hdmi_pcm *pcm;
  445. struct snd_soc_component *component = NULL;
  446. int err, i = 0;
  447. char jack_name[NAME_SIZE];
  448. list_for_each_entry(pcm, &ctx->hdmi_pcm_list, head) {
  449. component = pcm->codec_dai->component;
  450. snprintf(jack_name, sizeof(jack_name),
  451. "HDMI/DP, pcm=%d Jack", pcm->device);
  452. err = snd_soc_card_jack_new(card, jack_name,
  453. SND_JACK_AVOUT, &broxton_hdmi[i],
  454. NULL, 0);
  455. if (err)
  456. return err;
  457. err = hdac_hdmi_jack_init(pcm->codec_dai, pcm->device,
  458. &broxton_hdmi[i]);
  459. if (err < 0)
  460. return err;
  461. i++;
  462. }
  463. if (!component)
  464. return -EINVAL;
  465. return hdac_hdmi_jack_port_init(component, &card->dapm);
  466. }
  467. /* broxton audio machine driver for SPT + RT298S */
  468. static struct snd_soc_card broxton_rt298 = {
  469. .name = "broxton-rt298",
  470. .owner = THIS_MODULE,
  471. .dai_link = broxton_rt298_dais,
  472. .num_links = ARRAY_SIZE(broxton_rt298_dais),
  473. .controls = broxton_controls,
  474. .num_controls = ARRAY_SIZE(broxton_controls),
  475. .dapm_widgets = broxton_widgets,
  476. .num_dapm_widgets = ARRAY_SIZE(broxton_widgets),
  477. .dapm_routes = broxton_rt298_map,
  478. .num_dapm_routes = ARRAY_SIZE(broxton_rt298_map),
  479. .fully_routed = true,
  480. .late_probe = bxt_card_late_probe,
  481. };
  482. static struct snd_soc_card geminilake_rt298 = {
  483. .name = "geminilake-rt298",
  484. .owner = THIS_MODULE,
  485. .dai_link = broxton_rt298_dais,
  486. .num_links = ARRAY_SIZE(broxton_rt298_dais),
  487. .controls = broxton_controls,
  488. .num_controls = ARRAY_SIZE(broxton_controls),
  489. .dapm_widgets = broxton_widgets,
  490. .num_dapm_widgets = ARRAY_SIZE(broxton_widgets),
  491. .dapm_routes = geminilake_rt298_map,
  492. .num_dapm_routes = ARRAY_SIZE(geminilake_rt298_map),
  493. .fully_routed = true,
  494. .late_probe = bxt_card_late_probe,
  495. };
  496. static int broxton_audio_probe(struct platform_device *pdev)
  497. {
  498. struct bxt_rt286_private *ctx;
  499. struct snd_soc_card *card =
  500. (struct snd_soc_card *)pdev->id_entry->driver_data;
  501. int i;
  502. for (i = 0; i < ARRAY_SIZE(broxton_rt298_dais); i++) {
  503. if (!strncmp(card->dai_link[i].codec_name, "i2c-INT343A:00",
  504. I2C_NAME_SIZE)) {
  505. if (!strncmp(card->name, "broxton-rt298",
  506. PLATFORM_NAME_SIZE)) {
  507. card->dai_link[i].name = "SSP5-Codec";
  508. card->dai_link[i].cpu_dai_name = "SSP5 Pin";
  509. } else if (!strncmp(card->name, "geminilake-rt298",
  510. PLATFORM_NAME_SIZE)) {
  511. card->dai_link[i].name = "SSP2-Codec";
  512. card->dai_link[i].cpu_dai_name = "SSP2 Pin";
  513. }
  514. }
  515. }
  516. ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
  517. if (!ctx)
  518. return -ENOMEM;
  519. INIT_LIST_HEAD(&ctx->hdmi_pcm_list);
  520. card->dev = &pdev->dev;
  521. snd_soc_card_set_drvdata(card, ctx);
  522. return devm_snd_soc_register_card(&pdev->dev, card);
  523. }
  524. static const struct platform_device_id bxt_board_ids[] = {
  525. { .name = "bxt_alc298s_i2s", .driver_data =
  526. (unsigned long)&broxton_rt298 },
  527. { .name = "glk_alc298s_i2s", .driver_data =
  528. (unsigned long)&geminilake_rt298 },
  529. {}
  530. };
  531. static struct platform_driver broxton_audio = {
  532. .probe = broxton_audio_probe,
  533. .driver = {
  534. .name = "bxt_alc298s_i2s",
  535. .pm = &snd_soc_pm_ops,
  536. },
  537. .id_table = bxt_board_ids,
  538. };
  539. module_platform_driver(broxton_audio)
  540. /* Module information */
  541. MODULE_AUTHOR("Ramesh Babu <Ramesh.Babu@intel.com>");
  542. MODULE_AUTHOR("Senthilnathan Veppur <senthilnathanx.veppur@intel.com>");
  543. MODULE_DESCRIPTION("Intel SST Audio for Broxton");
  544. MODULE_LICENSE("GPL v2");
  545. MODULE_ALIAS("platform:bxt_alc298s_i2s");
  546. MODULE_ALIAS("platform:glk_alc298s_i2s");