Advertisement
Guest User

imx-wm8731.c

a guest
Oct 17th, 2014
293
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 17.31 KB | None | 0 0
  1. /*
  2. * Copyright (C) 2014 Freescale Semiconductor, Inc.
  3. *
  4. * Based on imx-sgtl5000.c
  5. * Copyright (C) 2012 Freescale Semiconductor, Inc.
  6. * Copyright (C) 2012 Linaro Ltd.
  7. *
  8. * The code contained herein is licensed under the GNU General Public
  9. * License. You may obtain a copy of the GNU General Public License
  10. * Version 2 or later at the following locations:
  11. *
  12. * http://www.opensource.org/licenses/gpl-license.html
  13. * http://www.gnu.org/copyleft/gpl.html
  14. */
  15.  
  16. #include <linux/module.h>
  17. #include <linux/of_platform.h>
  18. #include <linux/i2c.h>
  19. #include <linux/of_gpio.h>
  20. #include <linux/slab.h>
  21. #include <linux/gpio.h>
  22. #include <linux/clk.h>
  23. #include <sound/soc.h>
  24. #include <sound/jack.h>
  25. #include <sound/pcm_params.h>
  26. #include <sound/soc-dapm.h>
  27. #include <linux/pinctrl/consumer.h>
  28.  
  29. #include "../codecs/wm8731.h"
  30. #include "imx-audmux.h"
  31. #include "imx-ssi.h"
  32.  
  33. #define DAI_NAME_SIZE 32
  34. #define WM8731_MCLK_FREQ (24000000 / 2)
  35.  
  36. struct imx_wm8731_data {
  37. struct snd_soc_dai_link dai;
  38. struct snd_soc_card card;
  39. char codec_dai_name[DAI_NAME_SIZE];
  40. char platform_name[DAI_NAME_SIZE];
  41. struct i2c_client *codec_dev;
  42. /* audio_clocking_data */
  43. struct clk *pll;
  44. struct clk *clock_root;
  45. long sysclk;
  46. long current_rate;
  47. /* apis */
  48. int (*clock_enable)(int enable,struct imx_wm8731_data *data);
  49. };
  50.  
  51. static int imx_wm8731_init(struct snd_soc_pcm_runtime *rtd);
  52. static int imx_hifi_hw_params_slv_mode(struct snd_pcm_substream *substream,
  53. struct snd_pcm_hw_params *params);
  54. static void imx_hifi_shutdown(struct snd_pcm_substream *substream);
  55.  
  56. struct imx_priv {
  57. struct platform_device *pdev;
  58. struct imx_wm8731_data *data;
  59. };
  60.  
  61. static struct imx_priv card_priv;
  62.  
  63. static struct snd_soc_ops imx_hifi_ops = {
  64. .shutdown = imx_hifi_shutdown,
  65. };
  66.  
  67. /* imx card dapm widgets */
  68. static const struct snd_soc_dapm_widget imx_dapm_widgets[] = {
  69. SND_SOC_DAPM_HP("Headphone Jack", NULL),
  70. SND_SOC_DAPM_SPK("Ext Spk", NULL),
  71. SND_SOC_DAPM_LINE("Line Jack", NULL),
  72. SND_SOC_DAPM_MIC("Mic Jack", NULL),
  73. };
  74.  
  75. /* imx machine connections to the codec pins */
  76. static const struct snd_soc_dapm_route audio_map[] = {
  77. { "Headphone Jack", NULL, "LHPOUT" },
  78. { "Headphone Jack", NULL, "RHPOUT" },
  79.  
  80. { "Ext Spk", NULL, "LOUT" },
  81. { "Ext Spk", NULL, "ROUT" },
  82.  
  83. { "LLINEIN", NULL, "Line Jack" },
  84. { "RLINEIN", NULL, "Line Jack" },
  85.  
  86. { "MICIN", NULL, "Mic Bias" },
  87. { "Mic Bias", NULL, "Mic Jack"},
  88. };
  89.  
  90. static int wm8731_slv_mode_init(struct imx_wm8731_data *data)
  91. {
  92. struct clk *new_parent;
  93. struct clk *ssi_clk;
  94. struct i2c_client *codec_dev = data->codec_dev;
  95.  
  96. new_parent = devm_clk_get(&codec_dev->dev, "pll4");
  97. if (IS_ERR(new_parent)) {
  98. pr_err("Could not get \"pll4\" clock \n");
  99. return PTR_ERR(new_parent);
  100. }
  101.  
  102. ssi_clk = devm_clk_get(&codec_dev->dev, "imx-ssi.1");
  103. if (IS_ERR(ssi_clk)) {
  104. pr_err("Could not get \"imx-ssi.1\" clock \n");
  105. return PTR_ERR(ssi_clk);
  106. }
  107.  
  108. clk_set_parent(ssi_clk, new_parent);
  109.  
  110. data->pll = new_parent;
  111. data->clock_root = ssi_clk;
  112. data->current_rate = 0;
  113.  
  114. data->sysclk = 0;
  115.  
  116. return 0;
  117. }
  118.  
  119. static int wm8731_slv_mode_clock_enable(int enable, struct imx_wm8731_data *data)
  120. {
  121. long pll_rate;
  122. long rate_req;
  123. long rate_avail;
  124.  
  125. if (!enable)
  126. return 0;
  127.  
  128. if (data->sysclk == data->current_rate)
  129. return 0;
  130.  
  131. switch (data->sysclk) {
  132. case 11289600:
  133. pll_rate = 632217600;
  134. break;
  135.  
  136. case 12288000:
  137. pll_rate = 688128000;
  138. break;
  139.  
  140. default:
  141. return -EINVAL;
  142. }
  143.  
  144. rate_req = pll_rate;
  145. rate_avail = clk_round_rate(data->pll, rate_req);
  146. clk_set_rate(data->pll, rate_avail);
  147.  
  148. rate_req = data->sysclk;
  149. rate_avail = clk_round_rate(data->clock_root,
  150. rate_req);
  151. clk_set_rate(data->clock_root, rate_avail);
  152.  
  153. pr_info("%s: \"imx-ssi.1\" rate = %ld (= %ld)\n",
  154. __func__, rate_avail, rate_req);
  155.  
  156. data->current_rate = data->sysclk;
  157.  
  158. return 0;
  159. }
  160.  
  161. static int imx_hifi_startup_slv_mode(struct snd_pcm_substream *substream)
  162. {
  163. /*
  164. * As SSI's sys clock rate depends on sampling rate,
  165. * the clock enabling code is moved to imx_hifi_hw_params().
  166. */
  167. return 0;
  168. }
  169.  
  170. static int wm8731_mst_mode_init(struct imx_wm8731_data *data)
  171. {
  172. long rate;
  173. struct clk *new_parent;
  174. struct clk *ssi_clk;
  175. struct i2c_client *codec_dev = data->codec_dev;
  176.  
  177. new_parent = devm_clk_get(&codec_dev->dev, "cko2");
  178. if (IS_ERR(new_parent)) {
  179. pr_err("Could not get \"cko2\" clock \n");
  180. return PTR_ERR(new_parent);
  181. }
  182.  
  183. ssi_clk = devm_clk_get(&codec_dev->dev, "cko");
  184. if (IS_ERR(ssi_clk)) {
  185. pr_err("Could not get \"cko\" clock \n");
  186. return PTR_ERR(ssi_clk);
  187. }
  188.  
  189. rate = clk_round_rate(new_parent, WM8731_MCLK_FREQ);
  190. clk_set_rate(new_parent, rate);
  191.  
  192. clk_set_parent(ssi_clk, new_parent);
  193.  
  194. rate = clk_round_rate(ssi_clk, WM8731_MCLK_FREQ);
  195. clk_set_rate(ssi_clk, rate);
  196.  
  197. pr_info("%s: \"CLKO\" rate = %ld (= %d)\n",
  198. __func__, rate, WM8731_MCLK_FREQ);
  199.  
  200. data->pll = new_parent;
  201. data->clock_root = ssi_clk;
  202. data->sysclk = rate;
  203.  
  204. return 0;
  205. }
  206.  
  207. static int wm8731_mst_mode_clock_enable(int enable, struct imx_wm8731_data *data)
  208. {
  209. struct clk *clko = data->clock_root;
  210.  
  211. if (enable)
  212. clk_enable(clko);
  213. else
  214. clk_disable(clko);
  215.  
  216. return 0;
  217. }
  218.  
  219. static int imx_hifi_startup_mst_mode(struct snd_pcm_substream *substream)
  220. {
  221. struct snd_soc_pcm_runtime *rtd = substream->private_data;
  222. struct snd_soc_dai *codec_dai = rtd->codec_dai;
  223. struct snd_soc_card *card = codec_dai->card;
  224. struct imx_wm8731_data *data = snd_soc_card_get_drvdata(card);
  225.  
  226. if (!codec_dai->active)
  227. data->clock_enable(1,data);
  228.  
  229. return 0;
  230. }
  231.  
  232.  
  233. static int imx_hifi_hw_params_slv_mode(struct snd_pcm_substream *substream,
  234. struct snd_pcm_hw_params *params)
  235. {
  236. struct snd_soc_pcm_runtime *rtd = substream->private_data;
  237. struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
  238. struct snd_soc_dai *codec_dai = rtd->codec_dai;
  239. struct snd_soc_card *card = codec_dai->card;
  240. struct imx_wm8731_data *data = snd_soc_card_get_drvdata(card);
  241.  
  242. u32 dai_format;
  243. snd_pcm_format_t sample_format;
  244. unsigned int channels;
  245. unsigned int tx_mask, rx_mask;
  246. unsigned int sampling_rate;
  247. unsigned int div_2, div_psr, div_pm;
  248. int ret;
  249.  
  250. sampling_rate = params_rate(params);
  251. sample_format = params_format(params);
  252.  
  253. channels = params_channels(params);
  254. printk("%s:%s sampling rate = %u channels = %u \n", __FUNCTION__,
  255. (substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? "Playback" : "Capture"),
  256. sampling_rate, channels);
  257.  
  258. /* set CPU DAI configuration */
  259. switch (sampling_rate) {
  260. case 8000:
  261. case 32000:
  262. case 48000:
  263. case 96000:
  264. data->sysclk = 12288000;
  265. break;
  266.  
  267. case 44100:
  268. case 88200:
  269. data->sysclk = 11289600;
  270. break;
  271.  
  272. default:
  273. return -EINVAL;
  274. }
  275.  
  276. wm8731_slv_mode_clock_enable(1,data);
  277.  
  278. dai_format = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_IF |
  279. SND_SOC_DAIFMT_CBS_CFS;
  280.  
  281. ret = snd_soc_dai_set_fmt(cpu_dai, dai_format);
  282. if (ret < 0)
  283. return ret;
  284.  
  285. /* set i.MX active slot mask */
  286. /* S[TR]CCR:DC */
  287. tx_mask = ~((1 << channels) - 1);
  288. rx_mask = tx_mask;
  289. snd_soc_dai_set_tdm_slot(cpu_dai, tx_mask, rx_mask, 2, 32);
  290.  
  291. /*
  292. * SSI sysclk divider:
  293. * div_2: /1 or /2
  294. * div_psr: /1 or /8
  295. * div_pm: /1 .. /256
  296. */
  297. div_2 = 0;
  298. div_psr = 0;
  299. switch (sampling_rate) {
  300. case 8000:
  301. // 1x1x12
  302. div_pm = 11;
  303. break;
  304. case 32000:
  305. // 1x1x3
  306. div_pm = 2;
  307. break;
  308. case 48000:
  309. // 1x1x2
  310. div_pm = 1;
  311. break;
  312. case 96000:
  313. // 1x1x1
  314. div_pm = 0;
  315. break;
  316. case 44100:
  317. // 1x1x2
  318. div_pm = 1;
  319. break;
  320. case 88200:
  321. // 1x1x1
  322. div_pm = 0;
  323. break;
  324. default:
  325. return -EINVAL;
  326. }
  327.  
  328. /* sync mode: a single clock controls both playback and capture */
  329. snd_soc_dai_set_clkdiv(cpu_dai, IMX_SSI_TX_DIV_2, (div_2 ? SSI_STCCR_DIV2 : 0));
  330. snd_soc_dai_set_clkdiv(cpu_dai, IMX_SSI_TX_DIV_PSR, (div_psr ? SSI_STCCR_PSR : 0));
  331. snd_soc_dai_set_clkdiv(cpu_dai, IMX_SSI_TX_DIV_PM, div_pm);
  332.  
  333. /* set codec DAI configuration */
  334. dai_format = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
  335. SND_SOC_DAIFMT_CBS_CFS;
  336.  
  337. ret = snd_soc_dai_set_fmt(codec_dai, dai_format);
  338. if (ret < 0)
  339. return ret;
  340.  
  341. ret = snd_soc_dai_set_sysclk(codec_dai,
  342. WM8731_SYSCLK_MCLK,
  343. data->sysclk,
  344. SND_SOC_CLOCK_IN);
  345.  
  346. if (ret < 0) {
  347. pr_err("Failed to set codec master clock to %u: %d \n",
  348. data->sysclk, ret);
  349. return ret;
  350. }
  351.  
  352. return 0;
  353. }
  354.  
  355. static int imx_hifi_hw_params_mst_mode(struct snd_pcm_substream *substream,
  356. struct snd_pcm_hw_params *params)
  357. {
  358. struct snd_soc_pcm_runtime *rtd = substream->private_data;
  359. struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
  360. struct snd_soc_dai *codec_dai = rtd->codec_dai;
  361. struct snd_soc_card *card = codec_dai->card;
  362. struct imx_wm8731_data *data = snd_soc_card_get_drvdata(card);
  363. u32 dai_format;
  364. unsigned int channels;
  365. unsigned int tx_mask, rx_mask;
  366. unsigned int sampling_rate;
  367. int ret;
  368.  
  369.  
  370. sampling_rate = params_rate(params);
  371. channels = params_channels(params);
  372. pr_debug("%s:%s sampling rate = %u channels = %u \n", __FUNCTION__,
  373. (substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? "Playback" : "Capture"),
  374. sampling_rate, channels);
  375.  
  376. /* set cpu DAI configuration */
  377. dai_format = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_IF |
  378. SND_SOC_DAIFMT_CBM_CFM;
  379.  
  380. ret = snd_soc_dai_set_fmt(cpu_dai, dai_format);
  381. if (ret < 0)
  382. return ret;
  383.  
  384. /* set i.MX active slot mask */
  385. /* S[TR]CCR:DC */
  386. tx_mask = ~((1 << channels) - 1);
  387. rx_mask = tx_mask;
  388. snd_soc_dai_set_tdm_slot(cpu_dai, tx_mask, rx_mask, 2, 32);
  389.  
  390. /* set codec DAI configuration */
  391. dai_format = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
  392. SND_SOC_DAIFMT_CBM_CFM;
  393.  
  394. ret = snd_soc_dai_set_fmt(codec_dai, dai_format);
  395. if (ret < 0)
  396. return ret;
  397.  
  398. ret = snd_soc_dai_set_sysclk(codec_dai,
  399. WM8731_SYSCLK_MCLK,
  400. data->sysclk,
  401. SND_SOC_CLOCK_IN);
  402.  
  403. if (ret < 0) {
  404. pr_err("Failed to set codec master clock to %u: %d \n",
  405. data->sysclk, ret);
  406. return ret;
  407. }
  408.  
  409. return 0;
  410. }
  411.  
  412. static void imx_hifi_shutdown(struct snd_pcm_substream *substream)
  413. {
  414. struct snd_soc_pcm_runtime *rtd = substream->private_data;
  415. struct snd_soc_dai *codec_dai = rtd->codec_dai;
  416. struct snd_soc_card *card = codec_dai->card;
  417. struct imx_wm8731_data *data = snd_soc_card_get_drvdata(card);
  418.  
  419. if (!codec_dai->active)
  420. data->clock_enable(0,data);
  421.  
  422. return;
  423. }
  424.  
  425. static int imx_wm8731_init(struct snd_soc_pcm_runtime *rtd)
  426. {
  427. int ret = 0;
  428. struct snd_soc_codec *codec = rtd->codec;
  429.  
  430. /* Add imx specific widgets */
  431. ret = snd_soc_dapm_new_controls(&codec->dapm, imx_dapm_widgets,
  432. ARRAY_SIZE(imx_dapm_widgets));
  433. if (ret)
  434. goto out_retcode;
  435.  
  436. /* Set up imx specific audio path audio_map */
  437. ret = snd_soc_dapm_add_routes(&codec->dapm, audio_map, ARRAY_SIZE(audio_map));
  438. if (ret)
  439. goto out_retcode;
  440.  
  441. ret = snd_soc_dapm_enable_pin(&codec->dapm, "Headphone Jack");
  442. if (ret)
  443. goto out_retcode;
  444.  
  445. ret = snd_soc_dapm_nc_pin(&codec->dapm, "Ext Spk");
  446. if (ret)
  447. goto out_retcode;
  448.  
  449. out_retcode:
  450.  
  451. if (ret)
  452. pr_err("%s: failed with error code: %d \n", __FUNCTION__, ret);
  453. else
  454. pr_info("%s: success \n", __FUNCTION__);
  455.  
  456. return ret;
  457. }
  458.  
  459. /**
  460. * Configure AUDMUX interconnection between
  461. * _slave (CPU side) and _master (codec size)
  462. *
  463. * When SSI operates in master mode, 5-wire interconnect with
  464. * audio codec is required:
  465. * TXC - BCLK
  466. * TXD - DAC data
  467. * RXD - ADC data
  468. * TXFS - {DAC|ADC}LRC, i.e. word clock
  469. * RXC - MCLK, i.e. oversampling clock
  470. * Audmux is operated in asynchronous mode to enable 6-wire
  471. * interface (as opposed to 4-wire interface in sync mode).
  472. */
  473. static int imx_audmux_config_slv_mode(int _slave, int _master)
  474. {
  475. unsigned int ptcr, pdcr;
  476. int slave = _slave - 1;
  477. int master = _master - 1;
  478.  
  479. ptcr = IMX_AUDMUX_V2_PTCR_SYN |
  480. IMX_AUDMUX_V2_PTCR_TFSDIR |
  481. IMX_AUDMUX_V2_PTCR_TFSEL(slave) |
  482. IMX_AUDMUX_V2_PTCR_RCLKDIR |
  483. IMX_AUDMUX_V2_PTCR_RCSEL(slave | 0x8) |
  484. IMX_AUDMUX_V2_PTCR_TCLKDIR |
  485. IMX_AUDMUX_V2_PTCR_TCSEL(slave);
  486.  
  487. pdcr = IMX_AUDMUX_V2_PDCR_RXDSEL(slave);
  488. imx_audmux_v2_configure_port(master, ptcr, pdcr);
  489. ptcr = ptcr & ~IMX_AUDMUX_V2_PTCR_SYN;
  490. imx_audmux_v2_configure_port(master, ptcr, pdcr);
  491.  
  492. ptcr = IMX_AUDMUX_V2_PTCR_SYN |
  493. IMX_AUDMUX_V2_PTCR_RCLKDIR |
  494. IMX_AUDMUX_V2_PTCR_RCSEL(master | 0x8) |
  495. IMX_AUDMUX_V2_PTCR_TCLKDIR |
  496. IMX_AUDMUX_V2_PTCR_TCSEL(master);
  497.  
  498. pdcr = IMX_AUDMUX_V2_PDCR_RXDSEL(master);
  499. imx_audmux_v2_configure_port(slave, ptcr, pdcr);
  500. ptcr = ptcr & ~IMX_AUDMUX_V2_PTCR_SYN;
  501. imx_audmux_v2_configure_port(slave, ptcr, pdcr);
  502.  
  503. return 0;
  504. }
  505.  
  506. static int imx_audmux_config_mst_mode(int _slave, int _master)
  507. {
  508. unsigned int ptcr, pdcr;
  509. int slave = _slave - 1;
  510. int master = _master - 1;
  511.  
  512. ptcr = IMX_AUDMUX_V2_PTCR_SYN;
  513. ptcr |= IMX_AUDMUX_V2_PTCR_TFSDIR |
  514. IMX_AUDMUX_V2_PTCR_TFSEL(master) |
  515. IMX_AUDMUX_V2_PTCR_TCLKDIR |
  516. IMX_AUDMUX_V2_PTCR_TCSEL(master);
  517. pdcr = IMX_AUDMUX_V2_PDCR_RXDSEL(master);
  518. imx_audmux_v2_configure_port(slave, ptcr, pdcr);
  519.  
  520. ptcr = IMX_AUDMUX_V2_PTCR_SYN;
  521. pdcr = IMX_AUDMUX_V2_PDCR_RXDSEL(slave);
  522. imx_audmux_v2_configure_port(master, ptcr, pdcr);
  523.  
  524. return 0;
  525. }
  526.  
  527. static int imx_wm8731_probe(struct platform_device *pdev)
  528. {
  529. struct device_node *ssi_np, *codec_np;
  530. struct platform_device *ssi_pdev;
  531. struct imx_priv *priv = &card_priv;
  532. struct i2c_client *codec_dev;
  533. struct imx_wm8731_data *data;
  534. unsigned int src_port, ext_port;
  535. unsigned int ssi_mode;
  536. const char *ssi_mode_str;
  537.  
  538. int ret;
  539.  
  540. priv->pdev = pdev;
  541.  
  542. ssi_np = of_parse_phandle(pdev->dev.of_node, "ssi-controller", 0);
  543. codec_np = of_parse_phandle(pdev->dev.of_node, "audio-codec", 0);
  544. if (!ssi_np || !codec_np) {
  545. dev_err(&pdev->dev, "phandle missing or invalid\n");
  546. ret = -EINVAL;
  547. goto fail;
  548. }
  549.  
  550. ssi_pdev = of_find_device_by_node(ssi_np);
  551. if (!ssi_pdev) {
  552. dev_err(&pdev->dev, "failed to find SSI platform device\n");
  553. ret = -EINVAL;
  554. goto fail;
  555. }
  556.  
  557. codec_dev = of_find_i2c_device_by_node(codec_np);
  558. if (!codec_dev || !codec_dev->dev.driver) {
  559. dev_err(&pdev->dev, "failed to find codec platform device\n");
  560. ret = -EINVAL;
  561. goto fail;
  562. }
  563.  
  564. data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
  565. if (!data) {
  566. ret = -ENOMEM;
  567. goto fail;
  568. }
  569.  
  570. card_priv.data = data;
  571.  
  572. data->codec_dev = codec_dev;
  573.  
  574. data->dai.name = "HiFi";
  575. data->dai.stream_name = "HiFi";
  576. data->dai.codec_dai_name = "wm8731-hifi";
  577. data->dai.codec_of_node = codec_np;
  578. data->dai.cpu_dai_name = dev_name(&ssi_pdev->dev);
  579. data->dai.platform_of_node = ssi_np;
  580. data->dai.ops = &imx_hifi_ops;
  581. data->dai.init = &imx_wm8731_init;
  582.  
  583. ret = of_property_read_u32(pdev->dev.of_node, "src-port", &src_port);
  584. if (ret) {
  585. dev_err(&pdev->dev, "failed to get \"src-port\" value\n");
  586. ret = -EINVAL;
  587. goto fail;
  588. }
  589.  
  590. ret = of_property_read_u32(pdev->dev.of_node, "ext-port", &ext_port);
  591. if (ret) {
  592. dev_err(&pdev->dev, "failed to get \"ext-port\" value\n");
  593. ret = -EINVAL;
  594. goto fail;
  595. }
  596.  
  597. ret = of_property_read_string(ssi_np, "fsl,mode", &ssi_mode_str);
  598. if (ret) {
  599. dev_err(&pdev->dev, "failed to get \"fsl,mode\" value\n");
  600. ret = -EINVAL;
  601. goto fail;
  602. }
  603.  
  604. ssi_mode = strcmp(ssi_mode_str, "i2s-master");
  605.  
  606. if (ssi_mode) {
  607. /* Master Mode */
  608. imx_audmux_config_mst_mode(src_port, ext_port);
  609. wm8731_mst_mode_init(data);
  610. data->clock_enable = wm8731_mst_mode_clock_enable;
  611. imx_hifi_ops.hw_params = imx_hifi_hw_params_mst_mode;
  612. imx_hifi_ops.startup = imx_hifi_startup_mst_mode;
  613. } else {
  614. /* Slave Mode */
  615. imx_audmux_config_slv_mode(src_port, ext_port);
  616. wm8731_slv_mode_init(data);
  617. data->clock_enable = wm8731_slv_mode_clock_enable;
  618. imx_hifi_ops.hw_params = imx_hifi_hw_params_slv_mode;
  619. imx_hifi_ops.startup = imx_hifi_startup_slv_mode;
  620. }
  621.  
  622. data->card.dev = &pdev->dev;
  623. ret = snd_soc_of_parse_card_name(&data->card, "model");
  624. if (ret)
  625. goto fail;
  626.  
  627. ret = snd_soc_of_parse_audio_routing(&data->card, "audio-routing");
  628. if (ret)
  629. goto fail;
  630.  
  631. data->card.num_links = 1;
  632. data->card.dai_link = &data->dai;
  633.  
  634. data->card.dapm_widgets = imx_dapm_widgets;
  635. data->card.num_dapm_widgets = ARRAY_SIZE(imx_dapm_widgets);
  636.  
  637. platform_set_drvdata(pdev, &data->card);
  638. snd_soc_card_set_drvdata(&data->card, data);
  639.  
  640. ret = snd_soc_register_card(&data->card);
  641. if (ret) {
  642. dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret);
  643. goto fail;
  644. }
  645.  
  646. return 0;
  647.  
  648. fail:
  649.  
  650. if (ssi_np)
  651. of_node_put(ssi_np);
  652.  
  653. if (codec_np)
  654. of_node_put(codec_np);
  655.  
  656. return ret;
  657. }
  658.  
  659. static int imx_wm8731_remove(struct platform_device *pdev)
  660. {
  661. struct snd_soc_card *card = platform_get_drvdata(pdev);
  662. snd_soc_unregister_card(card);
  663.  
  664. return 0;
  665. }
  666.  
  667. static const struct of_device_id imx_wm8731_dt_ids[] = {
  668. { .compatible = "fsl,imx-audio-wm8731", },
  669. { /* sentinel */ }
  670. };
  671. MODULE_DEVICE_TABLE(of, imx_wm8731_dt_ids);
  672.  
  673. static struct platform_driver imx_wm8731_driver = {
  674. .driver = {
  675. .name = "imx-wm8731",
  676. .owner = THIS_MODULE,
  677. .of_match_table = imx_wm8731_dt_ids,
  678. },
  679. .probe = imx_wm8731_probe,
  680. .remove = imx_wm8731_remove,
  681. };
  682. module_platform_driver(imx_wm8731_driver);
  683.  
  684. MODULE_AUTHOR("Freescale Semiconductor, Inc.");
  685. MODULE_DESCRIPTION("Freescale i.MX WM8731 ASoC machine driver");
  686. MODULE_LICENSE("GPL v2");
  687. MODULE_ALIAS("platform:imx-wm8731");
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement