mxs-saif.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680
  1. /*
  2. * Copyright 2011 Freescale Semiconductor, Inc.
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation; either version 2 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License along
  15. * with this program; if not, write to the Free Software Foundation, Inc.,
  16. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  17. */
  18. #include <linux/module.h>
  19. #include <linux/init.h>
  20. #include <linux/platform_device.h>
  21. #include <linux/slab.h>
  22. #include <linux/dma-mapping.h>
  23. #include <linux/clk.h>
  24. #include <linux/delay.h>
  25. #include <sound/core.h>
  26. #include <sound/pcm.h>
  27. #include <sound/pcm_params.h>
  28. #include <sound/soc.h>
  29. #include <mach/dma.h>
  30. #include <asm/mach-types.h>
  31. #include <mach/hardware.h>
  32. #include <mach/mxs.h>
  33. #include "mxs-saif.h"
  34. static struct mxs_saif *mxs_saif[2];
  35. static int mxs_saif_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
  36. int clk_id, unsigned int freq, int dir)
  37. {
  38. struct mxs_saif *saif = snd_soc_dai_get_drvdata(cpu_dai);
  39. switch (clk_id) {
  40. case MXS_SAIF_MCLK:
  41. saif->mclk = freq;
  42. break;
  43. default:
  44. return -EINVAL;
  45. }
  46. return 0;
  47. }
  48. /*
  49. * Set SAIF clock and MCLK
  50. */
  51. static int mxs_saif_set_clk(struct mxs_saif *saif,
  52. unsigned int mclk,
  53. unsigned int rate)
  54. {
  55. u32 scr;
  56. int ret;
  57. scr = __raw_readl(saif->base + SAIF_CTRL);
  58. scr &= ~BM_SAIF_CTRL_BITCLK_MULT_RATE;
  59. scr &= ~BM_SAIF_CTRL_BITCLK_BASE_RATE;
  60. /*
  61. * Set SAIF clock
  62. *
  63. * The SAIF clock should be either 384*fs or 512*fs.
  64. * If MCLK is used, the SAIF clk ratio need to match mclk ratio.
  65. * For 32x mclk, set saif clk as 512*fs.
  66. * For 48x mclk, set saif clk as 384*fs.
  67. *
  68. * If MCLK is not used, we just set saif clk to 512*fs.
  69. */
  70. if (saif->mclk_in_use) {
  71. if (mclk % 32 == 0) {
  72. scr &= ~BM_SAIF_CTRL_BITCLK_BASE_RATE;
  73. ret = clk_set_rate(saif->clk, 512 * rate);
  74. } else if (mclk % 48 == 0) {
  75. scr |= BM_SAIF_CTRL_BITCLK_BASE_RATE;
  76. ret = clk_set_rate(saif->clk, 384 * rate);
  77. } else {
  78. /* SAIF MCLK should be either 32x or 48x */
  79. return -EINVAL;
  80. }
  81. } else {
  82. ret = clk_set_rate(saif->clk, 512 * rate);
  83. scr &= ~BM_SAIF_CTRL_BITCLK_BASE_RATE;
  84. }
  85. if (ret)
  86. return ret;
  87. if (!saif->mclk_in_use) {
  88. __raw_writel(scr, saif->base + SAIF_CTRL);
  89. return 0;
  90. }
  91. /*
  92. * Program the over-sample rate for MCLK output
  93. *
  94. * The available MCLK range is 32x, 48x... 512x. The rate
  95. * could be from 8kHz to 192kH.
  96. */
  97. switch (mclk / rate) {
  98. case 32:
  99. scr |= BF_SAIF_CTRL_BITCLK_MULT_RATE(4);
  100. break;
  101. case 64:
  102. scr |= BF_SAIF_CTRL_BITCLK_MULT_RATE(3);
  103. break;
  104. case 128:
  105. scr |= BF_SAIF_CTRL_BITCLK_MULT_RATE(2);
  106. break;
  107. case 256:
  108. scr |= BF_SAIF_CTRL_BITCLK_MULT_RATE(1);
  109. break;
  110. case 512:
  111. scr |= BF_SAIF_CTRL_BITCLK_MULT_RATE(0);
  112. break;
  113. case 48:
  114. scr |= BF_SAIF_CTRL_BITCLK_MULT_RATE(3);
  115. break;
  116. case 96:
  117. scr |= BF_SAIF_CTRL_BITCLK_MULT_RATE(2);
  118. break;
  119. case 192:
  120. scr |= BF_SAIF_CTRL_BITCLK_MULT_RATE(1);
  121. break;
  122. case 384:
  123. scr |= BF_SAIF_CTRL_BITCLK_MULT_RATE(0);
  124. break;
  125. default:
  126. return -EINVAL;
  127. }
  128. __raw_writel(scr, saif->base + SAIF_CTRL);
  129. return 0;
  130. }
  131. /*
  132. * Put and disable MCLK.
  133. */
  134. int mxs_saif_put_mclk(unsigned int saif_id)
  135. {
  136. struct mxs_saif *saif = mxs_saif[saif_id];
  137. u32 stat;
  138. if (!saif)
  139. return -EINVAL;
  140. stat = __raw_readl(saif->base + SAIF_STAT);
  141. if (stat & BM_SAIF_STAT_BUSY) {
  142. dev_err(saif->dev, "error: busy\n");
  143. return -EBUSY;
  144. }
  145. clk_disable(saif->clk);
  146. /* disable MCLK output */
  147. __raw_writel(BM_SAIF_CTRL_CLKGATE,
  148. saif->base + SAIF_CTRL + MXS_SET_ADDR);
  149. __raw_writel(BM_SAIF_CTRL_RUN,
  150. saif->base + SAIF_CTRL + MXS_CLR_ADDR);
  151. saif->mclk_in_use = 0;
  152. return 0;
  153. }
  154. /*
  155. * Get MCLK and set clock rate, then enable it
  156. *
  157. * This interface is used for codecs who are using MCLK provided
  158. * by saif.
  159. */
  160. int mxs_saif_get_mclk(unsigned int saif_id, unsigned int mclk,
  161. unsigned int rate)
  162. {
  163. struct mxs_saif *saif = mxs_saif[saif_id];
  164. u32 stat;
  165. int ret;
  166. if (!saif)
  167. return -EINVAL;
  168. /* Clear Reset */
  169. __raw_writel(BM_SAIF_CTRL_SFTRST,
  170. saif->base + SAIF_CTRL + MXS_CLR_ADDR);
  171. /* FIXME: need clear clk gate for register r/w */
  172. __raw_writel(BM_SAIF_CTRL_CLKGATE,
  173. saif->base + SAIF_CTRL + MXS_CLR_ADDR);
  174. stat = __raw_readl(saif->base + SAIF_STAT);
  175. if (stat & BM_SAIF_STAT_BUSY) {
  176. dev_err(saif->dev, "error: busy\n");
  177. return -EBUSY;
  178. }
  179. saif->mclk_in_use = 1;
  180. ret = mxs_saif_set_clk(saif, mclk, rate);
  181. if (ret)
  182. return ret;
  183. ret = clk_enable(saif->clk);
  184. if (ret)
  185. return ret;
  186. /* enable MCLK output */
  187. __raw_writel(BM_SAIF_CTRL_RUN,
  188. saif->base + SAIF_CTRL + MXS_SET_ADDR);
  189. return 0;
  190. }
  191. /*
  192. * SAIF DAI format configuration.
  193. * Should only be called when port is inactive.
  194. */
  195. static int mxs_saif_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)
  196. {
  197. u32 scr, stat;
  198. u32 scr0;
  199. struct mxs_saif *saif = snd_soc_dai_get_drvdata(cpu_dai);
  200. stat = __raw_readl(saif->base + SAIF_STAT);
  201. if (stat & BM_SAIF_STAT_BUSY) {
  202. dev_err(cpu_dai->dev, "error: busy\n");
  203. return -EBUSY;
  204. }
  205. scr0 = __raw_readl(saif->base + SAIF_CTRL);
  206. scr0 = scr0 & ~BM_SAIF_CTRL_BITCLK_EDGE & ~BM_SAIF_CTRL_LRCLK_POLARITY \
  207. & ~BM_SAIF_CTRL_JUSTIFY & ~BM_SAIF_CTRL_DELAY;
  208. scr = 0;
  209. /* DAI mode */
  210. switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
  211. case SND_SOC_DAIFMT_I2S:
  212. /* data frame low 1clk before data */
  213. scr |= BM_SAIF_CTRL_DELAY;
  214. scr &= ~BM_SAIF_CTRL_LRCLK_POLARITY;
  215. break;
  216. case SND_SOC_DAIFMT_LEFT_J:
  217. /* data frame high with data */
  218. scr &= ~BM_SAIF_CTRL_DELAY;
  219. scr &= ~BM_SAIF_CTRL_LRCLK_POLARITY;
  220. scr &= ~BM_SAIF_CTRL_JUSTIFY;
  221. break;
  222. default:
  223. return -EINVAL;
  224. }
  225. /* DAI clock inversion */
  226. switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
  227. case SND_SOC_DAIFMT_IB_IF:
  228. scr |= BM_SAIF_CTRL_BITCLK_EDGE;
  229. scr |= BM_SAIF_CTRL_LRCLK_POLARITY;
  230. break;
  231. case SND_SOC_DAIFMT_IB_NF:
  232. scr |= BM_SAIF_CTRL_BITCLK_EDGE;
  233. scr &= ~BM_SAIF_CTRL_LRCLK_POLARITY;
  234. break;
  235. case SND_SOC_DAIFMT_NB_IF:
  236. scr &= ~BM_SAIF_CTRL_BITCLK_EDGE;
  237. scr |= BM_SAIF_CTRL_LRCLK_POLARITY;
  238. break;
  239. case SND_SOC_DAIFMT_NB_NF:
  240. scr &= ~BM_SAIF_CTRL_BITCLK_EDGE;
  241. scr &= ~BM_SAIF_CTRL_LRCLK_POLARITY;
  242. break;
  243. }
  244. /*
  245. * Note: We simply just support master mode since SAIF TX can only
  246. * work as master.
  247. */
  248. switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
  249. case SND_SOC_DAIFMT_CBS_CFS:
  250. scr &= ~BM_SAIF_CTRL_SLAVE_MODE;
  251. __raw_writel(scr | scr0, saif->base + SAIF_CTRL);
  252. break;
  253. default:
  254. return -EINVAL;
  255. }
  256. return 0;
  257. }
  258. static int mxs_saif_startup(struct snd_pcm_substream *substream,
  259. struct snd_soc_dai *cpu_dai)
  260. {
  261. struct mxs_saif *saif = snd_soc_dai_get_drvdata(cpu_dai);
  262. snd_soc_dai_set_dma_data(cpu_dai, substream, &saif->dma_param);
  263. /* clear error status to 0 for each re-open */
  264. saif->fifo_underrun = 0;
  265. saif->fifo_overrun = 0;
  266. /* Clear Reset for normal operations */
  267. __raw_writel(BM_SAIF_CTRL_SFTRST,
  268. saif->base + SAIF_CTRL + MXS_CLR_ADDR);
  269. /* clear clock gate */
  270. __raw_writel(BM_SAIF_CTRL_CLKGATE,
  271. saif->base + SAIF_CTRL + MXS_CLR_ADDR);
  272. return 0;
  273. }
  274. /*
  275. * Should only be called when port is inactive.
  276. * although can be called multiple times by upper layers.
  277. */
  278. static int mxs_saif_hw_params(struct snd_pcm_substream *substream,
  279. struct snd_pcm_hw_params *params,
  280. struct snd_soc_dai *cpu_dai)
  281. {
  282. struct mxs_saif *saif = snd_soc_dai_get_drvdata(cpu_dai);
  283. u32 scr, stat;
  284. int ret;
  285. /* mclk should already be set */
  286. if (!saif->mclk && saif->mclk_in_use) {
  287. dev_err(cpu_dai->dev, "set mclk first\n");
  288. return -EINVAL;
  289. }
  290. stat = __raw_readl(saif->base + SAIF_STAT);
  291. if (stat & BM_SAIF_STAT_BUSY) {
  292. dev_err(cpu_dai->dev, "error: busy\n");
  293. return -EBUSY;
  294. }
  295. /*
  296. * Set saif clk based on sample rate.
  297. * If mclk is used, we also set mclk, if not, saif->mclk is
  298. * default 0, means not used.
  299. */
  300. ret = mxs_saif_set_clk(saif, saif->mclk, params_rate(params));
  301. if (ret) {
  302. dev_err(cpu_dai->dev, "unable to get proper clk\n");
  303. return ret;
  304. }
  305. scr = __raw_readl(saif->base + SAIF_CTRL);
  306. scr &= ~BM_SAIF_CTRL_WORD_LENGTH;
  307. scr &= ~BM_SAIF_CTRL_BITCLK_48XFS_ENABLE;
  308. switch (params_format(params)) {
  309. case SNDRV_PCM_FORMAT_S16_LE:
  310. scr |= BF_SAIF_CTRL_WORD_LENGTH(0);
  311. break;
  312. case SNDRV_PCM_FORMAT_S20_3LE:
  313. scr |= BF_SAIF_CTRL_WORD_LENGTH(4);
  314. scr |= BM_SAIF_CTRL_BITCLK_48XFS_ENABLE;
  315. break;
  316. case SNDRV_PCM_FORMAT_S24_LE:
  317. scr |= BF_SAIF_CTRL_WORD_LENGTH(8);
  318. scr |= BM_SAIF_CTRL_BITCLK_48XFS_ENABLE;
  319. break;
  320. default:
  321. return -EINVAL;
  322. }
  323. /* Tx/Rx config */
  324. if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
  325. /* enable TX mode */
  326. scr &= ~BM_SAIF_CTRL_READ_MODE;
  327. } else {
  328. /* enable RX mode */
  329. scr |= BM_SAIF_CTRL_READ_MODE;
  330. }
  331. __raw_writel(scr, saif->base + SAIF_CTRL);
  332. return 0;
  333. }
  334. static int mxs_saif_prepare(struct snd_pcm_substream *substream,
  335. struct snd_soc_dai *cpu_dai)
  336. {
  337. struct mxs_saif *saif = snd_soc_dai_get_drvdata(cpu_dai);
  338. /* enable FIFO error irqs */
  339. __raw_writel(BM_SAIF_CTRL_FIFO_ERROR_IRQ_EN,
  340. saif->base + SAIF_CTRL + MXS_SET_ADDR);
  341. return 0;
  342. }
  343. static int mxs_saif_trigger(struct snd_pcm_substream *substream, int cmd,
  344. struct snd_soc_dai *cpu_dai)
  345. {
  346. struct mxs_saif *saif = snd_soc_dai_get_drvdata(cpu_dai);
  347. switch (cmd) {
  348. case SNDRV_PCM_TRIGGER_START:
  349. case SNDRV_PCM_TRIGGER_RESUME:
  350. case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
  351. dev_dbg(cpu_dai->dev, "start\n");
  352. clk_enable(saif->clk);
  353. if (!saif->mclk_in_use)
  354. __raw_writel(BM_SAIF_CTRL_RUN,
  355. saif->base + SAIF_CTRL + MXS_SET_ADDR);
  356. if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
  357. /*
  358. * write a data to saif data register to trigger
  359. * the transfer
  360. */
  361. __raw_writel(0, saif->base + SAIF_DATA);
  362. } else {
  363. /*
  364. * read a data from saif data register to trigger
  365. * the receive
  366. */
  367. __raw_readl(saif->base + SAIF_DATA);
  368. }
  369. dev_dbg(cpu_dai->dev, "CTRL 0x%x STAT 0x%x\n",
  370. __raw_readl(saif->base + SAIF_CTRL),
  371. __raw_readl(saif->base + SAIF_STAT));
  372. break;
  373. case SNDRV_PCM_TRIGGER_SUSPEND:
  374. case SNDRV_PCM_TRIGGER_STOP:
  375. case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
  376. dev_dbg(cpu_dai->dev, "stop\n");
  377. clk_disable(saif->clk);
  378. if (!saif->mclk_in_use)
  379. __raw_writel(BM_SAIF_CTRL_RUN,
  380. saif->base + SAIF_CTRL + MXS_CLR_ADDR);
  381. break;
  382. default:
  383. return -EINVAL;
  384. }
  385. return 0;
  386. }
  387. #define MXS_SAIF_RATES SNDRV_PCM_RATE_8000_192000
  388. #define MXS_SAIF_FORMATS \
  389. (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
  390. SNDRV_PCM_FMTBIT_S24_LE)
  391. static struct snd_soc_dai_ops mxs_saif_dai_ops = {
  392. .startup = mxs_saif_startup,
  393. .trigger = mxs_saif_trigger,
  394. .prepare = mxs_saif_prepare,
  395. .hw_params = mxs_saif_hw_params,
  396. .set_sysclk = mxs_saif_set_dai_sysclk,
  397. .set_fmt = mxs_saif_set_dai_fmt,
  398. };
  399. static int mxs_saif_dai_probe(struct snd_soc_dai *dai)
  400. {
  401. struct mxs_saif *saif = dev_get_drvdata(dai->dev);
  402. snd_soc_dai_set_drvdata(dai, saif);
  403. return 0;
  404. }
  405. static struct snd_soc_dai_driver mxs_saif_dai = {
  406. .name = "mxs-saif",
  407. .probe = mxs_saif_dai_probe,
  408. .playback = {
  409. .channels_min = 2,
  410. .channels_max = 2,
  411. .rates = MXS_SAIF_RATES,
  412. .formats = MXS_SAIF_FORMATS,
  413. },
  414. .capture = {
  415. .channels_min = 2,
  416. .channels_max = 2,
  417. .rates = MXS_SAIF_RATES,
  418. .formats = MXS_SAIF_FORMATS,
  419. },
  420. .ops = &mxs_saif_dai_ops,
  421. };
  422. static irqreturn_t mxs_saif_irq(int irq, void *dev_id)
  423. {
  424. struct mxs_saif *saif = dev_id;
  425. unsigned int stat;
  426. stat = __raw_readl(saif->base + SAIF_STAT);
  427. if (!(stat & (BM_SAIF_STAT_FIFO_UNDERFLOW_IRQ |
  428. BM_SAIF_STAT_FIFO_OVERFLOW_IRQ)))
  429. return IRQ_NONE;
  430. if (stat & BM_SAIF_STAT_FIFO_UNDERFLOW_IRQ) {
  431. dev_dbg(saif->dev, "underrun!!! %d\n", ++saif->fifo_underrun);
  432. __raw_writel(BM_SAIF_STAT_FIFO_UNDERFLOW_IRQ,
  433. saif->base + SAIF_STAT + MXS_CLR_ADDR);
  434. }
  435. if (stat & BM_SAIF_STAT_FIFO_OVERFLOW_IRQ) {
  436. dev_dbg(saif->dev, "overrun!!! %d\n", ++saif->fifo_overrun);
  437. __raw_writel(BM_SAIF_STAT_FIFO_OVERFLOW_IRQ,
  438. saif->base + SAIF_STAT + MXS_CLR_ADDR);
  439. }
  440. dev_dbg(saif->dev, "SAIF_CTRL %x SAIF_STAT %x\n",
  441. __raw_readl(saif->base + SAIF_CTRL),
  442. __raw_readl(saif->base + SAIF_STAT));
  443. return IRQ_HANDLED;
  444. }
  445. static int mxs_saif_probe(struct platform_device *pdev)
  446. {
  447. struct resource *res;
  448. struct mxs_saif *saif;
  449. int ret = 0;
  450. if (pdev->id >= ARRAY_SIZE(mxs_saif))
  451. return -EINVAL;
  452. saif = kzalloc(sizeof(*saif), GFP_KERNEL);
  453. if (!saif)
  454. return -ENOMEM;
  455. mxs_saif[pdev->id] = saif;
  456. saif->clk = clk_get(&pdev->dev, NULL);
  457. if (IS_ERR(saif->clk)) {
  458. ret = PTR_ERR(saif->clk);
  459. dev_err(&pdev->dev, "Cannot get the clock: %d\n",
  460. ret);
  461. goto failed_clk;
  462. }
  463. res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  464. if (!res) {
  465. ret = -ENODEV;
  466. dev_err(&pdev->dev, "failed to get io resource: %d\n",
  467. ret);
  468. goto failed_get_resource;
  469. }
  470. if (!request_mem_region(res->start, resource_size(res), "mxs-saif")) {
  471. dev_err(&pdev->dev, "request_mem_region failed\n");
  472. ret = -EBUSY;
  473. goto failed_get_resource;
  474. }
  475. saif->base = ioremap(res->start, resource_size(res));
  476. if (!saif->base) {
  477. dev_err(&pdev->dev, "ioremap failed\n");
  478. ret = -ENODEV;
  479. goto failed_ioremap;
  480. }
  481. res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
  482. if (!res) {
  483. ret = -ENODEV;
  484. dev_err(&pdev->dev, "failed to get dma resource: %d\n",
  485. ret);
  486. goto failed_ioremap;
  487. }
  488. saif->dma_param.chan_num = res->start;
  489. saif->irq = platform_get_irq(pdev, 0);
  490. if (saif->irq < 0) {
  491. ret = saif->irq;
  492. dev_err(&pdev->dev, "failed to get irq resource: %d\n",
  493. ret);
  494. goto failed_get_irq1;
  495. }
  496. saif->dev = &pdev->dev;
  497. ret = request_irq(saif->irq, mxs_saif_irq, 0, "mxs-saif", saif);
  498. if (ret) {
  499. dev_err(&pdev->dev, "failed to request irq\n");
  500. goto failed_get_irq1;
  501. }
  502. saif->dma_param.chan_irq = platform_get_irq(pdev, 1);
  503. if (saif->dma_param.chan_irq < 0) {
  504. ret = saif->dma_param.chan_irq;
  505. dev_err(&pdev->dev, "failed to get dma irq resource: %d\n",
  506. ret);
  507. goto failed_get_irq2;
  508. }
  509. platform_set_drvdata(pdev, saif);
  510. ret = snd_soc_register_dai(&pdev->dev, &mxs_saif_dai);
  511. if (ret) {
  512. dev_err(&pdev->dev, "register DAI failed\n");
  513. goto failed_register;
  514. }
  515. saif->soc_platform_pdev = platform_device_alloc(
  516. "mxs-pcm-audio", pdev->id);
  517. if (!saif->soc_platform_pdev) {
  518. ret = -ENOMEM;
  519. goto failed_pdev_alloc;
  520. }
  521. platform_set_drvdata(saif->soc_platform_pdev, saif);
  522. ret = platform_device_add(saif->soc_platform_pdev);
  523. if (ret) {
  524. dev_err(&pdev->dev, "failed to add soc platform device\n");
  525. goto failed_pdev_add;
  526. }
  527. return 0;
  528. failed_pdev_add:
  529. platform_device_put(saif->soc_platform_pdev);
  530. failed_pdev_alloc:
  531. snd_soc_unregister_dai(&pdev->dev);
  532. failed_register:
  533. failed_get_irq2:
  534. free_irq(saif->irq, saif);
  535. failed_get_irq1:
  536. iounmap(saif->base);
  537. failed_ioremap:
  538. release_mem_region(res->start, resource_size(res));
  539. failed_get_resource:
  540. clk_put(saif->clk);
  541. failed_clk:
  542. kfree(saif);
  543. return ret;
  544. }
  545. static int __devexit mxs_saif_remove(struct platform_device *pdev)
  546. {
  547. struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  548. struct mxs_saif *saif = platform_get_drvdata(pdev);
  549. platform_device_unregister(saif->soc_platform_pdev);
  550. snd_soc_unregister_dai(&pdev->dev);
  551. iounmap(saif->base);
  552. release_mem_region(res->start, resource_size(res));
  553. free_irq(saif->irq, saif);
  554. clk_put(saif->clk);
  555. kfree(saif);
  556. return 0;
  557. }
  558. static struct platform_driver mxs_saif_driver = {
  559. .probe = mxs_saif_probe,
  560. .remove = __devexit_p(mxs_saif_remove),
  561. .driver = {
  562. .name = "mxs-saif",
  563. .owner = THIS_MODULE,
  564. },
  565. };
  566. static int __init mxs_saif_init(void)
  567. {
  568. return platform_driver_register(&mxs_saif_driver);
  569. }
  570. static void __exit mxs_saif_exit(void)
  571. {
  572. platform_driver_unregister(&mxs_saif_driver);
  573. }
  574. module_init(mxs_saif_init);
  575. module_exit(mxs_saif_exit);
  576. MODULE_AUTHOR("Freescale Semiconductor, Inc.");
  577. MODULE_DESCRIPTION("MXS ASoC SAIF driver");
  578. MODULE_LICENSE("GPL");