sdm845.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright (c) 2018, The Linux Foundation. All rights reserved.
  4. */
  5. #include <linux/module.h>
  6. #include <linux/platform_device.h>
  7. #include <linux/of_device.h>
  8. #include <sound/core.h>
  9. #include <sound/pcm.h>
  10. #include <sound/pcm_params.h>
  11. #include <sound/jack.h>
  12. #include <sound/soc.h>
  13. #include <linux/soundwire/sdw.h>
  14. #include <uapi/linux/input-event-codes.h>
  15. #include "common.h"
  16. #include "qdsp6/q6afe.h"
  17. #include "../codecs/rt5663.h"
  18. #define DRIVER_NAME "sdm845"
  19. #define DEFAULT_SAMPLE_RATE_48K 48000
  20. #define DEFAULT_MCLK_RATE 24576000
  21. #define TDM_BCLK_RATE 6144000
  22. #define MI2S_BCLK_RATE 1536000
  23. #define LEFT_SPK_TDM_TX_MASK 0x30
  24. #define RIGHT_SPK_TDM_TX_MASK 0xC0
  25. #define SPK_TDM_RX_MASK 0x03
  26. #define NUM_TDM_SLOTS 8
  27. #define SLIM_MAX_TX_PORTS 16
  28. #define SLIM_MAX_RX_PORTS 13
  29. #define WCD934X_DEFAULT_MCLK_RATE 9600000
  30. struct sdm845_snd_data {
  31. struct snd_soc_jack jack;
  32. bool jack_setup;
  33. bool slim_port_setup;
  34. bool stream_prepared[AFE_PORT_MAX];
  35. struct snd_soc_card *card;
  36. uint32_t pri_mi2s_clk_count;
  37. uint32_t sec_mi2s_clk_count;
  38. uint32_t quat_tdm_clk_count;
  39. struct sdw_stream_runtime *sruntime[AFE_PORT_MAX];
  40. };
  41. static unsigned int tdm_slot_offset[8] = {0, 4, 8, 12, 16, 20, 24, 28};
  42. static int sdm845_slim_snd_hw_params(struct snd_pcm_substream *substream,
  43. struct snd_pcm_hw_params *params)
  44. {
  45. struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
  46. struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
  47. struct snd_soc_dai *codec_dai;
  48. struct sdm845_snd_data *pdata = snd_soc_card_get_drvdata(rtd->card);
  49. u32 rx_ch[SLIM_MAX_RX_PORTS], tx_ch[SLIM_MAX_TX_PORTS];
  50. struct sdw_stream_runtime *sruntime;
  51. u32 rx_ch_cnt = 0, tx_ch_cnt = 0;
  52. int ret = 0, i;
  53. for_each_rtd_codec_dais(rtd, i, codec_dai) {
  54. sruntime = snd_soc_dai_get_stream(codec_dai,
  55. substream->stream);
  56. if (sruntime != ERR_PTR(-ENOTSUPP))
  57. pdata->sruntime[cpu_dai->id] = sruntime;
  58. ret = snd_soc_dai_get_channel_map(codec_dai,
  59. &tx_ch_cnt, tx_ch, &rx_ch_cnt, rx_ch);
  60. if (ret != 0 && ret != -ENOTSUPP) {
  61. pr_err("failed to get codec chan map, err:%d\n", ret);
  62. return ret;
  63. } else if (ret == -ENOTSUPP) {
  64. /* Ignore unsupported */
  65. continue;
  66. }
  67. if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
  68. ret = snd_soc_dai_set_channel_map(cpu_dai, 0, NULL,
  69. rx_ch_cnt, rx_ch);
  70. else
  71. ret = snd_soc_dai_set_channel_map(cpu_dai, tx_ch_cnt,
  72. tx_ch, 0, NULL);
  73. }
  74. return 0;
  75. }
  76. static int sdm845_tdm_snd_hw_params(struct snd_pcm_substream *substream,
  77. struct snd_pcm_hw_params *params)
  78. {
  79. struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
  80. struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
  81. struct snd_soc_dai *codec_dai;
  82. int ret = 0, j;
  83. int channels, slot_width;
  84. switch (params_format(params)) {
  85. case SNDRV_PCM_FORMAT_S16_LE:
  86. slot_width = 16;
  87. break;
  88. default:
  89. dev_err(rtd->dev, "%s: invalid param format 0x%x\n",
  90. __func__, params_format(params));
  91. return -EINVAL;
  92. }
  93. channels = params_channels(params);
  94. if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
  95. ret = snd_soc_dai_set_tdm_slot(cpu_dai, 0, 0x3,
  96. 8, slot_width);
  97. if (ret < 0) {
  98. dev_err(rtd->dev, "%s: failed to set tdm slot, err:%d\n",
  99. __func__, ret);
  100. goto end;
  101. }
  102. ret = snd_soc_dai_set_channel_map(cpu_dai, 0, NULL,
  103. channels, tdm_slot_offset);
  104. if (ret < 0) {
  105. dev_err(rtd->dev, "%s: failed to set channel map, err:%d\n",
  106. __func__, ret);
  107. goto end;
  108. }
  109. } else {
  110. ret = snd_soc_dai_set_tdm_slot(cpu_dai, 0xf, 0,
  111. 8, slot_width);
  112. if (ret < 0) {
  113. dev_err(rtd->dev, "%s: failed to set tdm slot, err:%d\n",
  114. __func__, ret);
  115. goto end;
  116. }
  117. ret = snd_soc_dai_set_channel_map(cpu_dai, channels,
  118. tdm_slot_offset, 0, NULL);
  119. if (ret < 0) {
  120. dev_err(rtd->dev, "%s: failed to set channel map, err:%d\n",
  121. __func__, ret);
  122. goto end;
  123. }
  124. }
  125. for_each_rtd_codec_dais(rtd, j, codec_dai) {
  126. if (!strcmp(codec_dai->component->name_prefix, "Left")) {
  127. ret = snd_soc_dai_set_tdm_slot(
  128. codec_dai, LEFT_SPK_TDM_TX_MASK,
  129. SPK_TDM_RX_MASK, NUM_TDM_SLOTS,
  130. slot_width);
  131. if (ret < 0) {
  132. dev_err(rtd->dev,
  133. "DEV0 TDM slot err:%d\n", ret);
  134. return ret;
  135. }
  136. }
  137. if (!strcmp(codec_dai->component->name_prefix, "Right")) {
  138. ret = snd_soc_dai_set_tdm_slot(
  139. codec_dai, RIGHT_SPK_TDM_TX_MASK,
  140. SPK_TDM_RX_MASK, NUM_TDM_SLOTS,
  141. slot_width);
  142. if (ret < 0) {
  143. dev_err(rtd->dev,
  144. "DEV1 TDM slot err:%d\n", ret);
  145. return ret;
  146. }
  147. }
  148. }
  149. end:
  150. return ret;
  151. }
  152. static int sdm845_snd_hw_params(struct snd_pcm_substream *substream,
  153. struct snd_pcm_hw_params *params)
  154. {
  155. struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
  156. struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
  157. struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
  158. int ret = 0;
  159. switch (cpu_dai->id) {
  160. case PRIMARY_MI2S_RX:
  161. case PRIMARY_MI2S_TX:
  162. /*
  163. * Use ASRC for internal clocks, as PLL rate isn't multiple
  164. * of BCLK.
  165. */
  166. rt5663_sel_asrc_clk_src(
  167. codec_dai->component,
  168. RT5663_DA_STEREO_FILTER | RT5663_AD_STEREO_FILTER,
  169. RT5663_CLK_SEL_I2S1_ASRC);
  170. ret = snd_soc_dai_set_sysclk(
  171. codec_dai, RT5663_SCLK_S_MCLK, DEFAULT_MCLK_RATE,
  172. SND_SOC_CLOCK_IN);
  173. if (ret < 0)
  174. dev_err(rtd->dev,
  175. "snd_soc_dai_set_sysclk err = %d\n", ret);
  176. break;
  177. case QUATERNARY_TDM_RX_0:
  178. case QUATERNARY_TDM_TX_0:
  179. ret = sdm845_tdm_snd_hw_params(substream, params);
  180. break;
  181. case SLIMBUS_0_RX...SLIMBUS_6_TX:
  182. ret = sdm845_slim_snd_hw_params(substream, params);
  183. break;
  184. case QUATERNARY_MI2S_RX:
  185. break;
  186. default:
  187. pr_err("%s: invalid dai id 0x%x\n", __func__, cpu_dai->id);
  188. break;
  189. }
  190. return ret;
  191. }
  192. static void sdm845_jack_free(struct snd_jack *jack)
  193. {
  194. struct snd_soc_component *component = jack->private_data;
  195. snd_soc_component_set_jack(component, NULL, NULL);
  196. }
  197. static int sdm845_dai_init(struct snd_soc_pcm_runtime *rtd)
  198. {
  199. struct snd_soc_component *component;
  200. struct snd_soc_card *card = rtd->card;
  201. struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
  202. struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
  203. struct sdm845_snd_data *pdata = snd_soc_card_get_drvdata(card);
  204. struct snd_soc_dai_link *link = rtd->dai_link;
  205. struct snd_jack *jack;
  206. /*
  207. * Codec SLIMBUS configuration
  208. * RX1, RX2, RX3, RX4, RX5, RX6, RX7, RX8, RX9, RX10, RX11, RX12, RX13
  209. * TX1, TX2, TX3, TX4, TX5, TX6, TX7, TX8, TX9, TX10, TX11, TX12, TX13
  210. * TX14, TX15, TX16
  211. */
  212. unsigned int rx_ch[SLIM_MAX_RX_PORTS] = {144, 145, 146, 147, 148, 149,
  213. 150, 151, 152, 153, 154, 155, 156};
  214. unsigned int tx_ch[SLIM_MAX_TX_PORTS] = {128, 129, 130, 131, 132, 133,
  215. 134, 135, 136, 137, 138, 139,
  216. 140, 141, 142, 143};
  217. int rval, i;
  218. if (!pdata->jack_setup) {
  219. rval = snd_soc_card_jack_new(card, "Headset Jack",
  220. SND_JACK_HEADSET |
  221. SND_JACK_HEADPHONE |
  222. SND_JACK_BTN_0 | SND_JACK_BTN_1 |
  223. SND_JACK_BTN_2 | SND_JACK_BTN_3,
  224. &pdata->jack);
  225. if (rval < 0) {
  226. dev_err(card->dev, "Unable to add Headphone Jack\n");
  227. return rval;
  228. }
  229. jack = pdata->jack.jack;
  230. snd_jack_set_key(jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
  231. snd_jack_set_key(jack, SND_JACK_BTN_1, KEY_VOICECOMMAND);
  232. snd_jack_set_key(jack, SND_JACK_BTN_2, KEY_VOLUMEUP);
  233. snd_jack_set_key(jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN);
  234. pdata->jack_setup = true;
  235. }
  236. switch (cpu_dai->id) {
  237. case PRIMARY_MI2S_RX:
  238. jack = pdata->jack.jack;
  239. component = codec_dai->component;
  240. jack->private_data = component;
  241. jack->private_free = sdm845_jack_free;
  242. rval = snd_soc_component_set_jack(component,
  243. &pdata->jack, NULL);
  244. if (rval != 0 && rval != -ENOTSUPP) {
  245. dev_warn(card->dev, "Failed to set jack: %d\n", rval);
  246. return rval;
  247. }
  248. break;
  249. case SLIMBUS_0_RX...SLIMBUS_6_TX:
  250. /* setting up wcd multiple times for slim port is redundant */
  251. if (pdata->slim_port_setup || !link->no_pcm)
  252. return 0;
  253. for_each_rtd_codec_dais(rtd, i, codec_dai) {
  254. rval = snd_soc_dai_set_channel_map(codec_dai,
  255. ARRAY_SIZE(tx_ch),
  256. tx_ch,
  257. ARRAY_SIZE(rx_ch),
  258. rx_ch);
  259. if (rval != 0 && rval != -ENOTSUPP)
  260. return rval;
  261. snd_soc_dai_set_sysclk(codec_dai, 0,
  262. WCD934X_DEFAULT_MCLK_RATE,
  263. SNDRV_PCM_STREAM_PLAYBACK);
  264. rval = snd_soc_component_set_jack(codec_dai->component,
  265. &pdata->jack, NULL);
  266. if (rval != 0 && rval != -ENOTSUPP) {
  267. dev_warn(card->dev, "Failed to set jack: %d\n", rval);
  268. return rval;
  269. }
  270. }
  271. pdata->slim_port_setup = true;
  272. break;
  273. default:
  274. break;
  275. }
  276. return 0;
  277. }
  278. static int sdm845_snd_startup(struct snd_pcm_substream *substream)
  279. {
  280. unsigned int fmt = SND_SOC_DAIFMT_BP_FP;
  281. unsigned int codec_dai_fmt = SND_SOC_DAIFMT_BC_FC;
  282. struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
  283. struct snd_soc_card *card = rtd->card;
  284. struct sdm845_snd_data *data = snd_soc_card_get_drvdata(card);
  285. struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
  286. struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
  287. int j;
  288. int ret;
  289. switch (cpu_dai->id) {
  290. case PRIMARY_MI2S_RX:
  291. case PRIMARY_MI2S_TX:
  292. codec_dai_fmt |= SND_SOC_DAIFMT_NB_NF;
  293. if (++(data->pri_mi2s_clk_count) == 1) {
  294. snd_soc_dai_set_sysclk(cpu_dai,
  295. Q6AFE_LPASS_CLK_ID_MCLK_1,
  296. DEFAULT_MCLK_RATE, SNDRV_PCM_STREAM_PLAYBACK);
  297. snd_soc_dai_set_sysclk(cpu_dai,
  298. Q6AFE_LPASS_CLK_ID_PRI_MI2S_IBIT,
  299. MI2S_BCLK_RATE, SNDRV_PCM_STREAM_PLAYBACK);
  300. }
  301. snd_soc_dai_set_fmt(cpu_dai, fmt);
  302. snd_soc_dai_set_fmt(codec_dai, codec_dai_fmt);
  303. break;
  304. case SECONDARY_MI2S_TX:
  305. codec_dai_fmt |= SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_I2S;
  306. if (++(data->sec_mi2s_clk_count) == 1) {
  307. snd_soc_dai_set_sysclk(cpu_dai,
  308. Q6AFE_LPASS_CLK_ID_SEC_MI2S_IBIT,
  309. MI2S_BCLK_RATE, SNDRV_PCM_STREAM_CAPTURE);
  310. }
  311. snd_soc_dai_set_fmt(cpu_dai, fmt);
  312. snd_soc_dai_set_fmt(codec_dai, codec_dai_fmt);
  313. break;
  314. case QUATERNARY_MI2S_RX:
  315. snd_soc_dai_set_sysclk(cpu_dai,
  316. Q6AFE_LPASS_CLK_ID_QUAD_MI2S_IBIT,
  317. MI2S_BCLK_RATE, SNDRV_PCM_STREAM_PLAYBACK);
  318. snd_soc_dai_set_fmt(cpu_dai, fmt);
  319. break;
  320. case QUATERNARY_TDM_RX_0:
  321. case QUATERNARY_TDM_TX_0:
  322. if (++(data->quat_tdm_clk_count) == 1) {
  323. snd_soc_dai_set_sysclk(cpu_dai,
  324. Q6AFE_LPASS_CLK_ID_QUAD_TDM_IBIT,
  325. TDM_BCLK_RATE, SNDRV_PCM_STREAM_PLAYBACK);
  326. }
  327. codec_dai_fmt |= SND_SOC_DAIFMT_IB_NF | SND_SOC_DAIFMT_DSP_B;
  328. for_each_rtd_codec_dais(rtd, j, codec_dai) {
  329. if (!strcmp(codec_dai->component->name_prefix,
  330. "Left")) {
  331. ret = snd_soc_dai_set_fmt(
  332. codec_dai, codec_dai_fmt);
  333. if (ret < 0) {
  334. dev_err(rtd->dev,
  335. "Left TDM fmt err:%d\n", ret);
  336. return ret;
  337. }
  338. }
  339. if (!strcmp(codec_dai->component->name_prefix,
  340. "Right")) {
  341. ret = snd_soc_dai_set_fmt(
  342. codec_dai, codec_dai_fmt);
  343. if (ret < 0) {
  344. dev_err(rtd->dev,
  345. "Right TDM slot err:%d\n", ret);
  346. return ret;
  347. }
  348. }
  349. }
  350. break;
  351. case SLIMBUS_0_RX...SLIMBUS_6_TX:
  352. break;
  353. default:
  354. pr_err("%s: invalid dai id 0x%x\n", __func__, cpu_dai->id);
  355. break;
  356. }
  357. return 0;
  358. }
  359. static void sdm845_snd_shutdown(struct snd_pcm_substream *substream)
  360. {
  361. struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
  362. struct snd_soc_card *card = rtd->card;
  363. struct sdm845_snd_data *data = snd_soc_card_get_drvdata(card);
  364. struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
  365. switch (cpu_dai->id) {
  366. case PRIMARY_MI2S_RX:
  367. case PRIMARY_MI2S_TX:
  368. if (--(data->pri_mi2s_clk_count) == 0) {
  369. snd_soc_dai_set_sysclk(cpu_dai,
  370. Q6AFE_LPASS_CLK_ID_MCLK_1,
  371. 0, SNDRV_PCM_STREAM_PLAYBACK);
  372. snd_soc_dai_set_sysclk(cpu_dai,
  373. Q6AFE_LPASS_CLK_ID_PRI_MI2S_IBIT,
  374. 0, SNDRV_PCM_STREAM_PLAYBACK);
  375. }
  376. break;
  377. case SECONDARY_MI2S_TX:
  378. if (--(data->sec_mi2s_clk_count) == 0) {
  379. snd_soc_dai_set_sysclk(cpu_dai,
  380. Q6AFE_LPASS_CLK_ID_SEC_MI2S_IBIT,
  381. 0, SNDRV_PCM_STREAM_CAPTURE);
  382. }
  383. break;
  384. case QUATERNARY_TDM_RX_0:
  385. case QUATERNARY_TDM_TX_0:
  386. if (--(data->quat_tdm_clk_count) == 0) {
  387. snd_soc_dai_set_sysclk(cpu_dai,
  388. Q6AFE_LPASS_CLK_ID_QUAD_TDM_IBIT,
  389. 0, SNDRV_PCM_STREAM_PLAYBACK);
  390. }
  391. break;
  392. case SLIMBUS_0_RX...SLIMBUS_6_TX:
  393. case QUATERNARY_MI2S_RX:
  394. break;
  395. default:
  396. pr_err("%s: invalid dai id 0x%x\n", __func__, cpu_dai->id);
  397. break;
  398. }
  399. }
  400. static int sdm845_snd_prepare(struct snd_pcm_substream *substream)
  401. {
  402. struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
  403. struct sdm845_snd_data *data = snd_soc_card_get_drvdata(rtd->card);
  404. struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
  405. struct sdw_stream_runtime *sruntime = data->sruntime[cpu_dai->id];
  406. int ret;
  407. if (!sruntime)
  408. return 0;
  409. if (data->stream_prepared[cpu_dai->id]) {
  410. sdw_disable_stream(sruntime);
  411. sdw_deprepare_stream(sruntime);
  412. data->stream_prepared[cpu_dai->id] = false;
  413. }
  414. ret = sdw_prepare_stream(sruntime);
  415. if (ret)
  416. return ret;
  417. /**
  418. * NOTE: there is a strict hw requirement about the ordering of port
  419. * enables and actual WSA881x PA enable. PA enable should only happen
  420. * after soundwire ports are enabled if not DC on the line is
  421. * accumulated resulting in Click/Pop Noise
  422. * PA enable/mute are handled as part of codec DAPM and digital mute.
  423. */
  424. ret = sdw_enable_stream(sruntime);
  425. if (ret) {
  426. sdw_deprepare_stream(sruntime);
  427. return ret;
  428. }
  429. data->stream_prepared[cpu_dai->id] = true;
  430. return ret;
  431. }
  432. static int sdm845_snd_hw_free(struct snd_pcm_substream *substream)
  433. {
  434. struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
  435. struct sdm845_snd_data *data = snd_soc_card_get_drvdata(rtd->card);
  436. struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
  437. struct sdw_stream_runtime *sruntime = data->sruntime[cpu_dai->id];
  438. if (sruntime && data->stream_prepared[cpu_dai->id]) {
  439. sdw_disable_stream(sruntime);
  440. sdw_deprepare_stream(sruntime);
  441. data->stream_prepared[cpu_dai->id] = false;
  442. }
  443. return 0;
  444. }
  445. static const struct snd_soc_ops sdm845_be_ops = {
  446. .hw_params = sdm845_snd_hw_params,
  447. .hw_free = sdm845_snd_hw_free,
  448. .prepare = sdm845_snd_prepare,
  449. .startup = sdm845_snd_startup,
  450. .shutdown = sdm845_snd_shutdown,
  451. };
  452. static int sdm845_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
  453. struct snd_pcm_hw_params *params)
  454. {
  455. struct snd_interval *rate = hw_param_interval(params,
  456. SNDRV_PCM_HW_PARAM_RATE);
  457. struct snd_interval *channels = hw_param_interval(params,
  458. SNDRV_PCM_HW_PARAM_CHANNELS);
  459. struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
  460. rate->min = rate->max = DEFAULT_SAMPLE_RATE_48K;
  461. channels->min = channels->max = 2;
  462. snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S16_LE);
  463. return 0;
  464. }
  465. static const struct snd_soc_dapm_widget sdm845_snd_widgets[] = {
  466. SND_SOC_DAPM_HP("Headphone Jack", NULL),
  467. SND_SOC_DAPM_MIC("Headset Mic", NULL),
  468. SND_SOC_DAPM_SPK("Left Spk", NULL),
  469. SND_SOC_DAPM_SPK("Right Spk", NULL),
  470. SND_SOC_DAPM_MIC("Int Mic", NULL),
  471. };
  472. static void sdm845_add_ops(struct snd_soc_card *card)
  473. {
  474. struct snd_soc_dai_link *link;
  475. int i;
  476. for_each_card_prelinks(card, i, link) {
  477. if (link->no_pcm == 1) {
  478. link->ops = &sdm845_be_ops;
  479. link->be_hw_params_fixup = sdm845_be_hw_params_fixup;
  480. }
  481. link->init = sdm845_dai_init;
  482. }
  483. }
  484. static int sdm845_snd_platform_probe(struct platform_device *pdev)
  485. {
  486. struct snd_soc_card *card;
  487. struct sdm845_snd_data *data;
  488. struct device *dev = &pdev->dev;
  489. int ret;
  490. card = devm_kzalloc(dev, sizeof(*card), GFP_KERNEL);
  491. if (!card)
  492. return -ENOMEM;
  493. /* Allocate the private data */
  494. data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
  495. if (!data)
  496. return -ENOMEM;
  497. card->driver_name = DRIVER_NAME;
  498. card->dapm_widgets = sdm845_snd_widgets;
  499. card->num_dapm_widgets = ARRAY_SIZE(sdm845_snd_widgets);
  500. card->dev = dev;
  501. card->owner = THIS_MODULE;
  502. dev_set_drvdata(dev, card);
  503. ret = qcom_snd_parse_of(card);
  504. if (ret)
  505. return ret;
  506. data->card = card;
  507. snd_soc_card_set_drvdata(card, data);
  508. sdm845_add_ops(card);
  509. return devm_snd_soc_register_card(dev, card);
  510. }
  511. static const struct of_device_id sdm845_snd_device_id[] = {
  512. { .compatible = "qcom,sdm845-sndcard" },
  513. { .compatible = "qcom,db845c-sndcard" },
  514. { .compatible = "lenovo,yoga-c630-sndcard" },
  515. {},
  516. };
  517. MODULE_DEVICE_TABLE(of, sdm845_snd_device_id);
  518. static struct platform_driver sdm845_snd_driver = {
  519. .probe = sdm845_snd_platform_probe,
  520. .driver = {
  521. .name = "msm-snd-sdm845",
  522. .of_match_table = sdm845_snd_device_id,
  523. },
  524. };
  525. module_platform_driver(sdm845_snd_driver);
  526. MODULE_DESCRIPTION("sdm845 ASoC Machine Driver");
  527. MODULE_LICENSE("GPL v2");