Guest User

fsl_esai.c

a guest
Dec 18th, 2014
286
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 33.37 KB | None | 0 0
  1. /*
  2. * Freescale ESAI ALSA SoC Digital Audio Interface (DAI) driver
  3. *
  4. * Copyright (C) 2014 Freescale Semiconductor, Inc.
  5. *
  6. * This file is licensed under the terms of the GNU General Public License
  7. * version 2. This program is licensed "as is" without any warranty of any
  8. * kind, whether express or implied.
  9. */
  10.  
  11. #include <linux/clk.h>
  12. #include <linux/dmaengine.h>
  13. #include <linux/module.h>
  14. #include <linux/of_irq.h>
  15. #include <linux/of_platform.h>
  16. #include <sound/dmaengine_pcm.h>
  17. #include <sound/pcm_params.h>
  18.  
  19. #include "fsl_esai.h"
  20. #include "imx-pcm.h"
  21.  
  22. #define FSL_ESAI_RATES SNDRV_PCM_RATE_8000_192000
  23. #define FSL_ESAI_FORMATS (SNDRV_PCM_FMTBIT_S8 | \
  24. SNDRV_PCM_FMTBIT_S16_LE | \
  25. SNDRV_PCM_FMTBIT_S20_3LE | \
  26. SNDRV_PCM_FMTBIT_S24_LE)
  27.  
  28. #define ESAI_DUMP() \
  29. do {u32 val;pr_info("dump @ %s\n", __func__); \
  30. regmap_read(esai_priv->regmap, REG_ESAI_ECR, &val);pr_info("ESAI_ECR 0x%08x\n", val); \
  31. regmap_read(esai_priv->regmap, REG_ESAI_ESR, &val);pr_info("ESAI_ESR 0x%08x\n", val); \
  32. regmap_read(esai_priv->regmap, REG_ESAI_TFCR, &val);pr_info("ESAI_TFCR 0x%08x\n", val); \
  33. regmap_read(esai_priv->regmap, REG_ESAI_TFSR, &val);pr_info("ESAI_TFSR 0x%08x\n", val); \
  34. regmap_read(esai_priv->regmap, REG_ESAI_RFCR, &val);pr_info("ESAI_RFCR 0x%08x\n", val); \
  35. regmap_read(esai_priv->regmap, REG_ESAI_RFSR, &val);pr_info("ESAI_RFSR 0x%08x\n", val); \
  36. regmap_read(esai_priv->regmap, REG_ESAI_TSR, &val);pr_info("ESAI_TSR 0x%08x\n", val); \
  37. regmap_read(esai_priv->regmap, REG_ESAI_SAISR, &val);pr_info("ESAI_SAISR 0x%08x\n", val); \
  38. regmap_read(esai_priv->regmap, REG_ESAI_SAICR, &val);pr_info("ESAI_SAICR 0x%08x\n", val); \
  39. regmap_read(esai_priv->regmap, REG_ESAI_TCR, &val);pr_info("ESAI_TCR 0x%08x\n", val); \
  40. regmap_read(esai_priv->regmap, REG_ESAI_TCCR, &val);pr_info("ESAI_TCCR 0x%08x\n", val); \
  41. regmap_read(esai_priv->regmap, REG_ESAI_RCR, &val);pr_info("ESAI_RCR 0x%08x\n", val); \
  42. regmap_read(esai_priv->regmap, REG_ESAI_RCCR, &val);pr_info("ESAI_RCCR 0x%08x\n", val); \
  43. regmap_read(esai_priv->regmap, REG_ESAI_TSMA, &val);pr_info("ESAI_TSMA 0x%08x\n", val); \
  44. regmap_read(esai_priv->regmap, REG_ESAI_TSMB, &val);pr_info("ESAI_TSMB 0x%08x\n", val); \
  45. regmap_read(esai_priv->regmap, REG_ESAI_RSMA, &val);pr_info("ESAI_RSMA 0x%08x\n", val); \
  46. regmap_read(esai_priv->regmap, REG_ESAI_RSMB, &val);pr_info("ESAI_RSMB 0x%08x\n", val); \
  47. regmap_read(esai_priv->regmap, REG_ESAI_PRRC, &val);pr_info("ESAI_PRRC 0x%08x\n", val); \
  48. regmap_read(esai_priv->regmap, REG_ESAI_PCRC, &val);pr_info("ESAI_PCRC 0x%08x\n", val); \
  49. } while (0);
  50.  
  51.  
  52.  
  53. /**
  54. * fsl_esai: ESAI private data
  55. *
  56. * @dma_params_rx: DMA parameters for receive channel
  57. * @dma_params_tx: DMA parameters for transmit channel
  58. * @pdev: platform device pointer
  59. * @regmap: regmap handler
  60. * @coreclk: clock source to access register
  61. * @extalclk: esai clock source to derive HCK, SCK and FS
  62. * @fsysclk: system clock source to derive HCK, SCK and FS
  63. * @fifo_depth: depth of tx/rx FIFO
  64. * @slot_width: width of each DAI slot
  65. * @hck_rate: clock rate of desired HCKx clock
  66. * @sck_div: if using PSR/PM dividers for SCKx clock
  67. * @slave_mode: if fully using DAI slave mode
  68. * @synchronous: if using tx/rx synchronous mode
  69. * @name: driver name
  70. */
  71. struct fsl_esai {
  72. struct snd_dmaengine_dai_dma_data dma_params_rx;
  73. struct snd_dmaengine_dai_dma_data dma_params_tx;
  74. struct imx_dma_data filter_data_tx;
  75. struct imx_dma_data filter_data_rx;
  76. struct snd_pcm_substream *substream[2];
  77. struct platform_device *pdev;
  78. struct regmap *regmap;
  79. struct clk *coreclk;
  80. struct clk *extalclk;
  81. struct clk *fsysclk;
  82. struct clk *dmaclk;
  83. u32 fifo_depth;
  84. u32 slot_width;
  85. u32 slots;
  86. u32 hck_rate[2];
  87. bool sck_div[2];
  88. bool slave_mode;
  89. bool synchronous;
  90. char name[32];
  91. };
  92.  
  93. static irqreturn_t esai_isr(int irq, void *devid)
  94. {
  95. struct fsl_esai *esai_priv = (struct fsl_esai *)devid;
  96. struct platform_device *pdev = esai_priv->pdev;
  97. u32 esr;
  98.  
  99. regmap_read(esai_priv->regmap, REG_ESAI_ESR, &esr);
  100.  
  101. if (esr & ESAI_ESR_TINIT_MASK)
  102. dev_dbg(&pdev->dev, "isr: Transmition Initialized\n");
  103.  
  104. if (esr & ESAI_ESR_RFF_MASK)
  105. dev_warn(&pdev->dev, "isr: Receiving overrun\n");
  106.  
  107. if (esr & ESAI_ESR_TFE_MASK)
  108. dev_warn(&pdev->dev, "isr: Transmition underrun\n");
  109.  
  110. if (esr & ESAI_ESR_TLS_MASK)
  111. dev_dbg(&pdev->dev, "isr: Just transmitted the last slot\n");
  112.  
  113. if (esr & ESAI_ESR_TDE_MASK)
  114. dev_dbg(&pdev->dev, "isr: Transmition data exception\n");
  115.  
  116. if (esr & ESAI_ESR_TED_MASK)
  117. dev_dbg(&pdev->dev, "isr: Transmitting even slots\n");
  118.  
  119. if (esr & ESAI_ESR_TD_MASK)
  120. dev_dbg(&pdev->dev, "isr: Transmitting data\n");
  121.  
  122. if (esr & ESAI_ESR_RLS_MASK)
  123. dev_dbg(&pdev->dev, "isr: Just received the last slot\n");
  124.  
  125. if (esr & ESAI_ESR_RDE_MASK)
  126. dev_dbg(&pdev->dev, "isr: Receiving data exception\n");
  127.  
  128. if (esr & ESAI_ESR_RED_MASK)
  129. dev_dbg(&pdev->dev, "isr: Receiving even slots\n");
  130.  
  131. if (esr & ESAI_ESR_RD_MASK)
  132. dev_dbg(&pdev->dev, "isr: Receiving data\n");
  133.  
  134. return IRQ_HANDLED;
  135. }
  136.  
  137. /**
  138. * This function is used to calculate the divisors of psr, pm, fp and it is
  139. * supposed to be called in set_dai_sysclk() and set_bclk().
  140. *
  141. * @ratio: desired overall ratio for the paticipating dividers
  142. * @usefp: for HCK setting, there is no need to set fp divider
  143. * @fp: bypass other dividers by setting fp directly if fp != 0
  144. * @tx: current setting is for playback or capture
  145. */
  146. static int fsl_esai_divisor_cal(struct snd_soc_dai *dai, bool tx, u32 ratio,
  147. bool usefp, u32 fp)
  148. {
  149. //usefp=false, fp=0;
  150. //ratio doit etre compris entre 2 et 4096
  151. //ratio compris entre 2 et 256 car TPSR=1
  152. struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai);
  153. u32 psr, pm = 999, maxfp, prod, sub, savesub, i, j;
  154.  
  155. maxfp = usefp ? 16 : 1;
  156. //maxfp = 1
  157. if (usefp && fp)
  158. goto out_fp;
  159. //ratio > 4096 || ratio < 2
  160. if (ratio > 2 * 8 * 256 * maxfp || ratio < 2) {
  161. dev_err(dai->dev, "the ratio is out of range (2 ~ %d)\n",
  162. 2 * 8 * 256 * maxfp);
  163. return -EINVAL;
  164. } else if (ratio % 2) {
  165. dev_err(dai->dev, "the ratio must be even if using upper divider\n");
  166. return -EINVAL;
  167. }
  168.  
  169. printk(KERN_ERR"ratio:%d\n",ratio);
  170. ratio /= 2;
  171.  
  172. psr = ratio <= 256 * maxfp ? ESAI_xCCR_xPSR_BYPASS : ESAI_xCCR_xPSR_DIV8;
  173.  
  174.  
  175.  
  176. /* Set the max fluctuation -- 0.1% of the max devisor */
  177. savesub = (psr ? 1 : 8) * 256 * maxfp / 1000;
  178.  
  179. /* Find the best value for PM */
  180. for (i = 1; i <= 256; i++) {
  181. for (j = 1; j <= maxfp; j++) {
  182. /* PSR (1 or 8) * PM (1 ~ 256) * FP (1 ~ 16) */
  183. prod = (psr ? 1 : 8) * i * j;
  184.  
  185. if (prod == ratio)
  186. sub = 0;
  187. else if (prod / ratio == 1)
  188. sub = prod - ratio;
  189. else if (ratio / prod == 1)
  190. sub = ratio - prod;
  191. else
  192. continue;
  193.  
  194. /* Calculate the fraction */
  195. sub = sub * 1000 / ratio;
  196. if (sub < savesub) {
  197. savesub = sub;
  198. pm = i;
  199. fp = j;
  200. }
  201.  
  202. /* We are lucky */
  203. if (savesub == 0)
  204. goto out;
  205. }
  206. }
  207.  
  208. if (pm == 999) {
  209. dev_err(dai->dev, "failed to calculate proper divisors\n");
  210. return -EINVAL;
  211. }
  212.  
  213. out:
  214. printk(KERN_ERR"pm:%d\n",pm);
  215. regmap_update_bits(esai_priv->regmap, REG_ESAI_xCCR(tx),
  216. ESAI_xCCR_xPSR_MASK | ESAI_xCCR_xPM_MASK,
  217. psr | ESAI_xCCR_xPM(pm));
  218. //il faut pm=0 et psr = 0x80
  219. out_fp:
  220. printk(KERN_ERR"maxfp:%d ; fp:%d\n",maxfp,fp);;
  221. /* Bypass fp if not being required */
  222. if (maxfp <= 1)
  223. return 0;
  224.  
  225. regmap_update_bits(esai_priv->regmap, REG_ESAI_xCCR(tx),
  226. ESAI_xCCR_xFP_MASK, ESAI_xCCR_xFP(fp));
  227. //il faut fp=1
  228. return 0;
  229. }
  230.  
  231. /**
  232. * This function mainly configures the clock frequency of MCLK (HCKT/HCKR)
  233. *
  234. * @Parameters:
  235. * clk_id: The clock source of HCKT/HCKR
  236. * (Input from outside; output from inside, FSYS or EXTAL)
  237. * freq: The required clock rate of HCKT/HCKR
  238. * dir: The clock direction of HCKT/HCKR
  239. *
  240. * Note: If the direction is input, we do not care about clk_id.
  241. */
  242. static int fsl_esai_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id,
  243. unsigned int freq, int dir)
  244. {
  245. struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai);
  246. struct clk *clksrc = esai_priv->extalclk;
  247. bool tx = clk_id <= ESAI_HCKT_EXTAL;
  248. bool in = dir == SND_SOC_CLOCK_IN;
  249. u32 ret, ratio, ecr = 0;
  250. unsigned long clk_rate;
  251.  
  252. /* sck_div can be only bypassed if ETO/ERO=0 and SNC_SOC_CLOCK_OUT */
  253. esai_priv->sck_div[tx] = true;
  254.  
  255. /* Set the direction of HCKT/HCKR pins */
  256. regmap_update_bits(esai_priv->regmap, REG_ESAI_xCCR(tx),
  257. ESAI_xCCR_xHCKD, in ? 0 : ESAI_xCCR_xHCKD);
  258.  
  259. if (in)
  260. goto out;
  261.  
  262. switch (clk_id) {
  263. case ESAI_HCKT_FSYS:
  264. case ESAI_HCKR_FSYS:
  265. clksrc = esai_priv->fsysclk;
  266. break;
  267. case ESAI_HCKT_EXTAL:
  268. ecr |= ESAI_ECR_ETI;
  269. case ESAI_HCKR_EXTAL:
  270. ecr |= ESAI_ECR_ERI;
  271. break;
  272. default:
  273. return -EINVAL;
  274. }
  275.  
  276. if (IS_ERR(clksrc)) {
  277. dev_err(dai->dev, "no assigned %s clock\n",
  278. clk_id % 2 ? "extal" : "fsys");
  279. return PTR_ERR(clksrc);
  280. }
  281. clk_rate = clk_get_rate(clksrc);
  282.  
  283. ratio = clk_rate / freq;
  284. printk(KERN_ERR"FYI clk_rate:%ld ; freq:%d; ratio:%d\n",clk_rate,freq,ratio);
  285. //FYI clk_rate:33868800 ; freq:24576000
  286. if (ratio * freq > clk_rate){
  287. ret = ratio * freq - clk_rate;
  288. printk(KERN_ERR"first condition ret:%d\n",ret);
  289. }
  290. else if (ratio * freq < clk_rate){
  291. ret = clk_rate - ratio * freq;
  292. printk(KERN_ERR"second condition ret:%d\n",ret);
  293. }
  294. else
  295. ret = 0;
  296.  
  297. /* Block if clock source can not be divided into the required rate */
  298. if (ret != 0 && clk_rate / ret < 1000) {
  299. dev_err(dai->dev, "failed to derive required HCK%c rate\n",
  300. tx ? 'T' : 'R');
  301. #if 0
  302. regmap_update_bits(esai_priv->regmap, REG_ESAI_xCCR(tx),
  303. 0xFFFFFFFF, 0x00947f00);
  304. regmap_update_bits(esai_priv->regmap, REG_ESAI_ECR,
  305. 0xFFFFFFFF, 0x000f0001);
  306. printk(KERN_ERR"Setting :0x%0X\n",0x00947f00);
  307. #endif
  308. return -EINVAL;
  309. }
  310.  
  311. if (ratio == 1) {
  312. /* Bypass all the dividers if not being needed */
  313. ecr |= tx ? ESAI_ECR_ETO : ESAI_ECR_ERO;
  314. goto out;
  315. }
  316.  
  317. ret = fsl_esai_divisor_cal(dai, tx, ratio, false, 0);
  318. if (ret)
  319. return ret;
  320.  
  321. esai_priv->sck_div[tx] = false;
  322.  
  323. out:
  324. esai_priv->hck_rate[tx] = freq;
  325.  
  326. regmap_update_bits(esai_priv->regmap, REG_ESAI_ECR,
  327. tx ? ESAI_ECR_ETI | ESAI_ECR_ETO :
  328. ESAI_ECR_ERI | ESAI_ECR_ERO, ecr);
  329.  
  330. return 0;
  331. }
  332.  
  333. /**
  334. * This function configures the related dividers according to the bclk rate
  335. */
  336. static int fsl_esai_set_bclk(struct snd_soc_dai *dai, bool tx, u32 freq)
  337. {
  338. struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai);
  339. u32 hck_rate = esai_priv->hck_rate[tx];
  340. u32 sub, ratio = hck_rate / freq;
  341.  
  342. /* Don't apply for fully slave mode*/
  343. if (esai_priv->slave_mode)
  344. return 0;
  345.  
  346. if (ratio * freq > hck_rate)
  347. sub = ratio * freq - hck_rate;
  348. else if (ratio * freq < hck_rate)
  349. sub = hck_rate - ratio * freq;
  350. else
  351. sub = 0;
  352.  
  353. /* Block if clock source can not be divided into the required rate */
  354. if (sub != 0 && hck_rate / sub < 1000) {
  355. dev_err(dai->dev, "failed to derive required SCK%c rate\n",
  356. tx ? 'T' : 'R');
  357. return -EINVAL;
  358. }
  359.  
  360. if (esai_priv->sck_div[tx] && (ratio > 16 || ratio == 0)) {
  361. dev_err(dai->dev, "the ratio is out of range (1 ~ 16)\n");
  362. return -EINVAL;
  363. }
  364.  
  365. return fsl_esai_divisor_cal(dai, tx, ratio, true,
  366. esai_priv->sck_div[tx] ? 0 : ratio);
  367. }
  368.  
  369. static int fsl_esai_set_dai_tdm_slot(struct snd_soc_dai *dai, u32 tx_mask,
  370. u32 rx_mask, int slots, int slot_width)
  371. {
  372. struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai);
  373.  
  374. regmap_update_bits(esai_priv->regmap, REG_ESAI_TCCR,
  375. ESAI_xCCR_xDC_MASK, ESAI_xCCR_xDC(slots));
  376.  
  377. regmap_update_bits(esai_priv->regmap, REG_ESAI_TSMA,
  378. ESAI_xSMA_xS_MASK, ESAI_xSMA_xS(tx_mask));
  379. regmap_update_bits(esai_priv->regmap, REG_ESAI_TSMB,
  380. ESAI_xSMB_xS_MASK, ESAI_xSMB_xS(tx_mask));
  381. regmap_update_bits(esai_priv->regmap, REG_ESAI_RCCR,
  382. ESAI_xCCR_xDC_MASK, ESAI_xCCR_xDC(slots));
  383.  
  384. regmap_update_bits(esai_priv->regmap, REG_ESAI_RSMA,
  385. ESAI_xSMA_xS_MASK, ESAI_xSMA_xS(rx_mask));
  386. regmap_update_bits(esai_priv->regmap, REG_ESAI_RSMB,
  387. ESAI_xSMB_xS_MASK, ESAI_xSMB_xS(rx_mask));
  388.  
  389. esai_priv->slot_width = slot_width;
  390. esai_priv->slots = slots;
  391. ESAI_DUMP();
  392. return 0;
  393. }
  394.  
  395. static int fsl_esai_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
  396. {
  397. struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai);
  398. u32 xcr = 0, xccr = 0, mask;
  399.  
  400. printk(KERN_ERR"%s(%d)\n",__func__,__LINE__);
  401. /* DAI mode */
  402. switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
  403. case SND_SOC_DAIFMT_I2S:
  404. /* Data on rising edge of bclk, frame low, 1clk before data */
  405. xcr |= ESAI_xCR_xFSR;
  406. xccr |= ESAI_xCCR_xFSP | ESAI_xCCR_xCKP | ESAI_xCCR_xHCKP;
  407. break;
  408. case SND_SOC_DAIFMT_LEFT_J:
  409. /* Data on rising edge of bclk, frame high */
  410. xccr |= ESAI_xCCR_xCKP | ESAI_xCCR_xHCKP;
  411. break;
  412. case SND_SOC_DAIFMT_RIGHT_J:
  413. /* Data on rising edge of bclk, frame high, right aligned */
  414. xccr |= ESAI_xCCR_xCKP | ESAI_xCCR_xHCKP | ESAI_xCR_xWA;
  415. break;
  416. case SND_SOC_DAIFMT_DSP_A:
  417. /* Data on rising edge of bclk, frame high, 1clk before data */
  418. xcr |= ESAI_xCR_xFSL | ESAI_xCR_xFSR;
  419. xccr |= ESAI_xCCR_xCKP | ESAI_xCCR_xHCKP;
  420. break;
  421. case SND_SOC_DAIFMT_DSP_B:
  422. /* Data on rising edge of bclk, frame high */
  423. xcr |= ESAI_xCR_xFSL;
  424. xccr |= ESAI_xCCR_xCKP | ESAI_xCCR_xHCKP;
  425. break;
  426. default:
  427. return -EINVAL;
  428. }
  429. printk(KERN_ERR"%s(%d)\n",__func__,__LINE__);
  430. /* DAI clock inversion */
  431. switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
  432. case SND_SOC_DAIFMT_NB_NF:
  433. /* Nothing to do for both normal cases */
  434. break;
  435. case SND_SOC_DAIFMT_IB_NF:
  436. /* Invert bit clock */
  437. xccr ^= ESAI_xCCR_xCKP | ESAI_xCCR_xHCKP;
  438. break;
  439. case SND_SOC_DAIFMT_NB_IF:
  440. /* Invert frame clock */
  441. xccr ^= ESAI_xCCR_xFSP;
  442. break;
  443. case SND_SOC_DAIFMT_IB_IF:
  444. /* Invert both clocks */
  445. xccr ^= ESAI_xCCR_xCKP | ESAI_xCCR_xHCKP | ESAI_xCCR_xFSP;
  446. break;
  447. default:
  448. return -EINVAL;
  449. }
  450. printk(KERN_ERR"%s(%d)\n",__func__,__LINE__);
  451. esai_priv->slave_mode = false;
  452.  
  453. /* DAI clock master masks */
  454. switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
  455. case SND_SOC_DAIFMT_CBM_CFM:
  456. esai_priv->slave_mode = true;
  457. break;
  458. case SND_SOC_DAIFMT_CBS_CFM:
  459. xccr |= ESAI_xCCR_xCKD;
  460. break;
  461. case SND_SOC_DAIFMT_CBM_CFS:
  462. xccr |= ESAI_xCCR_xFSD;
  463. break;
  464. case SND_SOC_DAIFMT_CBS_CFS:
  465. xccr |= ESAI_xCCR_xFSD | ESAI_xCCR_xCKD;
  466. break;
  467. default:
  468. return -EINVAL;
  469. }
  470.  
  471. mask = ESAI_xCR_xFSL | ESAI_xCR_xFSR;
  472.  
  473. #define MAKE_TCR_INTERRUPTIBLE
  474. #ifdef MAKE_TCR_INTERRUPTIBLE
  475. //make it interruptible
  476. printk(KERN_ERR"%s(%d)\n",__func__,__LINE__);
  477. mask |= ESAI_xCR_xEIE_MASK | ESAI_xCR_xIE_MASK;
  478. xcr |= ESAI_xCR_xEIE | ESAI_xCR_xIE;
  479. //make it interruptible
  480. #endif /* MAKE_TCR_INTERRUPTIBLE */
  481. #ifdef MAKE_TRANSMIT_LAST_SLOT_INT
  482. mask |= ESAI_xCR_xLIE_MASK;
  483. xcr |= ESAI_xCR_xLIE;
  484. #endif /* MAKE_TRANSMIT_LAST_SLOT_INT */
  485. #ifdef MAKE_TRANSMIT_EVEN_SLOT_INT
  486. mask |= ESAI_xCR_xEDIE_MASK;
  487. xcr |= ESAI_xCR_xEDIE;
  488. #endif /* MAKE_TRANSMIT_EVEN_SLOT_INT */
  489. #define FRAME_SYNCHRO_1_BIT
  490. #ifdef FRAME_SYNCHRO_1_BIT
  491. mask |= ESAI_xCR_xFSL_MASK;
  492. xcr |= ESAI_xCR_xFSL;
  493. #endif /* FRAME_SYNCHRO_1_BIT */
  494.  
  495. printk(KERN_ERR"xcr:0x%0X\n",xcr);
  496. regmap_update_bits(esai_priv->regmap, REG_ESAI_TCR, mask, xcr);
  497. regmap_update_bits(esai_priv->regmap, REG_ESAI_RCR, mask, xcr);
  498.  
  499. mask = ESAI_xCCR_xCKP | ESAI_xCCR_xHCKP | ESAI_xCCR_xFSP |
  500. ESAI_xCCR_xFSD | ESAI_xCCR_xCKD | ESAI_xCR_xWA;
  501. regmap_update_bits(esai_priv->regmap, REG_ESAI_TCCR, mask, xccr);
  502. regmap_update_bits(esai_priv->regmap, REG_ESAI_RCCR, mask, xccr);
  503. ESAI_DUMP();
  504. return 0;
  505. }
  506.  
  507. static int fsl_esai_startup(struct snd_pcm_substream *substream,
  508. struct snd_soc_dai *dai)
  509. {
  510. struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai);
  511.  
  512. /*
  513. * Some platforms might use the same bit to gate all three or two of
  514. * clocks, so keep all clocks open/close at the same time for safety
  515. */
  516. clk_prepare_enable(esai_priv->dmaclk);
  517. clk_prepare_enable(esai_priv->coreclk);
  518. if (!IS_ERR(esai_priv->extalclk))
  519. clk_prepare_enable(esai_priv->extalclk);
  520. if (!IS_ERR(esai_priv->fsysclk))
  521. clk_prepare_enable(esai_priv->fsysclk);
  522.  
  523. if (!dai->active) {
  524. /* Set synchronous mode */
  525. regmap_update_bits(esai_priv->regmap, REG_ESAI_SAICR,
  526. ESAI_SAICR_SYNC, esai_priv->synchronous ?
  527. ESAI_SAICR_SYNC : 0);
  528.  
  529. /* Set a default slot number -- 2 */
  530. regmap_update_bits(esai_priv->regmap, REG_ESAI_TCCR,
  531. ESAI_xCCR_xDC_MASK, ESAI_xCCR_xDC(2));
  532. regmap_update_bits(esai_priv->regmap, REG_ESAI_RCCR,
  533. ESAI_xCCR_xDC_MASK, ESAI_xCCR_xDC(2));
  534. }
  535.  
  536. esai_priv->substream[substream->stream] = substream;
  537.  
  538. return 0;
  539. }
  540.  
  541. static int fsl_esai_hw_params(struct snd_pcm_substream *substream,
  542. struct snd_pcm_hw_params *params,
  543. struct snd_soc_dai *dai)
  544. {
  545. struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai);
  546. bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
  547. u32 width = snd_pcm_format_width(params_format(params));
  548. u32 channels = params_channels(params);
  549. u32 pin = DIV_ROUND_UP(channels, esai_priv->slots);
  550. u32 bclk, mask, val, ret;
  551.  
  552. bclk = params_rate(params) * esai_priv->slot_width * esai_priv->slots;
  553.  
  554. ret = fsl_esai_set_bclk(dai, tx, bclk);
  555. if (ret)
  556. return ret;
  557.  
  558. /* Use Normal mode to support monaural audio */
  559. regmap_update_bits(esai_priv->regmap, REG_ESAI_xCR(tx),
  560. ESAI_xCR_xMOD_MASK, ESAI_xCR_xMOD_NETWORK);//TODO : check if network mode with one channel
  561. printk(KERN_ERR"using network mode\n");
  562. regmap_update_bits(esai_priv->regmap, REG_ESAI_xFCR(tx),
  563. ESAI_xFCR_xFR_MASK, ESAI_xFCR_xFR);
  564.  
  565. mask = ESAI_xFCR_xFR_MASK | ESAI_xFCR_xWA_MASK | ESAI_xFCR_xFWM_MASK |
  566. (tx ? ESAI_xFCR_TE_MASK | ESAI_xFCR_TIEN : ESAI_xFCR_RE_MASK);
  567. val = ESAI_xFCR_xWA(width) | ESAI_xFCR_xFWM(esai_priv->fifo_depth) |
  568. (tx ? ESAI_xFCR_TE(pin) | ESAI_xFCR_TIEN : ESAI_xFCR_RE(pin));
  569.  
  570. regmap_update_bits(esai_priv->regmap, REG_ESAI_xFCR(tx), mask, val);
  571.  
  572. mask = ESAI_xCR_xSWS_MASK | (tx ? ESAI_xCR_PADC : 0);
  573. val = ESAI_xCR_xSWS(esai_priv->slot_width, width) | (tx ? ESAI_xCR_PADC : 0);
  574.  
  575. regmap_update_bits(esai_priv->regmap, REG_ESAI_xCR(tx), mask, val);
  576.  
  577. /* Reset Port C */
  578. regmap_update_bits(esai_priv->regmap, REG_ESAI_PRRC,
  579. ESAI_PRRC_PDC_MASK, ESAI_PRRC_PDC(ESAI_GPIO));
  580. regmap_update_bits(esai_priv->regmap, REG_ESAI_PCRC,
  581. ESAI_PCRC_PC_MASK, ESAI_PCRC_PC(ESAI_GPIO));
  582.  
  583. printk(KERN_ERR"slot_width:%d\n",esai_priv->slot_width);
  584. printk(KERN_ERR"snd_pcm_format_width:%d\n",width);
  585. printk(KERN_ERR"params_channels:%d\n",channels);
  586. printk(KERN_ERR"pins used:%d\n",pin);
  587. printk(KERN_ERR"bclk:%d\n",bclk);
  588. printk(KERN_ERR"network:%d\n",1);
  589. printk(KERN_ERR"rate:%d\n",params_rate(params));
  590.  
  591. ESAI_DUMP();
  592.  
  593. return 0;
  594. }
  595.  
  596. static void fsl_esai_shutdown(struct snd_pcm_substream *substream,
  597. struct snd_soc_dai *dai)
  598. {
  599. struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai);
  600.  
  601. if (!dai->active) {
  602. /* Reset Port C */
  603. regmap_update_bits(esai_priv->regmap, REG_ESAI_PRRC,
  604. ESAI_PRRC_PDC_MASK, 0);
  605. regmap_update_bits(esai_priv->regmap, REG_ESAI_PCRC,
  606. ESAI_PCRC_PC_MASK, 0);
  607. }
  608.  
  609. esai_priv->substream[substream->stream] = NULL;
  610.  
  611. if (!IS_ERR(esai_priv->fsysclk))
  612. clk_disable_unprepare(esai_priv->fsysclk);
  613. if (!IS_ERR(esai_priv->extalclk))
  614. clk_disable_unprepare(esai_priv->extalclk);
  615. clk_disable_unprepare(esai_priv->coreclk);
  616. clk_disable_unprepare(esai_priv->dmaclk);
  617. }
  618.  
  619. static int fsl_esai_trigger(struct snd_pcm_substream *substream, int cmd,
  620. struct snd_soc_dai *dai)
  621. {
  622. struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai);
  623. bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
  624. u8 i, channels = substream->runtime->channels;
  625. u32 pin = DIV_ROUND_UP(channels, esai_priv->slots);
  626.  
  627. switch (cmd) {
  628. case SNDRV_PCM_TRIGGER_START:
  629. case SNDRV_PCM_TRIGGER_RESUME:
  630. case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
  631. regmap_update_bits(esai_priv->regmap, REG_ESAI_xFCR(tx),
  632. ESAI_xFCR_xFEN_MASK, ESAI_xFCR_xFEN);
  633.  
  634. /* Write initial words required by ESAI as normal procedure */
  635. for (i = 0; tx && i < channels; i++)
  636. regmap_write(esai_priv->regmap, REG_ESAI_ETDR, 0x0);
  637.  
  638. regmap_update_bits(esai_priv->regmap, REG_ESAI_xCR(tx),
  639. tx ? ESAI_xCR_TE_MASK : ESAI_xCR_RE_MASK,
  640. tx ? ESAI_xCR_TE(pin) : ESAI_xCR_RE(pin));
  641. break;
  642. case SNDRV_PCM_TRIGGER_SUSPEND:
  643. case SNDRV_PCM_TRIGGER_STOP:
  644. case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
  645. regmap_update_bits(esai_priv->regmap, REG_ESAI_xCR(tx),
  646. tx ? ESAI_xCR_TE_MASK : ESAI_xCR_RE_MASK, 0);
  647.  
  648. /* Disable and reset FIFO */
  649. regmap_update_bits(esai_priv->regmap, REG_ESAI_xFCR(tx),
  650. ESAI_xFCR_xFR | ESAI_xFCR_xFEN, ESAI_xFCR_xFR);
  651. regmap_update_bits(esai_priv->regmap, REG_ESAI_xFCR(tx),
  652. ESAI_xFCR_xFR, 0);
  653. break;
  654. default:
  655. return -EINVAL;
  656. }
  657.  
  658. return 0;
  659. }
  660.  
  661. static struct snd_soc_dai_ops fsl_esai_dai_ops = {
  662. .startup = fsl_esai_startup,
  663. .shutdown = fsl_esai_shutdown,
  664. .trigger = fsl_esai_trigger,
  665. .hw_params = fsl_esai_hw_params,
  666. .set_sysclk = fsl_esai_set_dai_sysclk,
  667. .set_fmt = fsl_esai_set_dai_fmt,
  668. .set_tdm_slot = fsl_esai_set_dai_tdm_slot,
  669. };
  670.  
  671. static int fsl_esai_dai_probe(struct snd_soc_dai *dai)
  672. {
  673. struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai);
  674.  
  675. snd_soc_dai_init_dma_data(dai, &esai_priv->dma_params_tx,
  676. &esai_priv->dma_params_rx);
  677.  
  678. return 0;
  679. }
  680.  
  681. static struct snd_soc_dai_driver fsl_esai_dai = {
  682. .probe = fsl_esai_dai_probe,
  683. .playback = {
  684. .stream_name = "esai-Playback",
  685. .channels_min = 1,
  686. .channels_max = 64,//12,
  687. .rates = FSL_ESAI_RATES,
  688. .formats = FSL_ESAI_FORMATS,
  689. },
  690. .capture = {
  691. .stream_name = "esai-Capture",
  692. .channels_min = 1,
  693. .channels_max = 64,//8,
  694. .rates = FSL_ESAI_RATES,
  695. .formats = FSL_ESAI_FORMATS,
  696. },
  697. .ops = &fsl_esai_dai_ops,
  698. };
  699.  
  700. static const struct snd_soc_component_driver fsl_esai_component = {
  701. .name = "fsl-esai",
  702. };
  703.  
  704. static bool fsl_esai_readable_reg(struct device *dev, unsigned int reg)
  705. {
  706. switch (reg) {
  707. case REG_ESAI_ERDR:
  708. case REG_ESAI_ECR:
  709. case REG_ESAI_ESR:
  710. case REG_ESAI_TFCR:
  711. case REG_ESAI_TFSR:
  712. case REG_ESAI_RFCR:
  713. case REG_ESAI_RFSR:
  714. case REG_ESAI_RX0:
  715. case REG_ESAI_RX1:
  716. case REG_ESAI_RX2:
  717. case REG_ESAI_RX3:
  718. case REG_ESAI_SAISR:
  719. case REG_ESAI_SAICR:
  720. case REG_ESAI_TCR:
  721. case REG_ESAI_TCCR:
  722. case REG_ESAI_RCR:
  723. case REG_ESAI_RCCR:
  724. case REG_ESAI_TSMA:
  725. case REG_ESAI_TSMB:
  726. case REG_ESAI_RSMA:
  727. case REG_ESAI_RSMB:
  728. case REG_ESAI_PRRC:
  729. case REG_ESAI_PCRC:
  730. return true;
  731. default:
  732. return false;
  733. }
  734. }
  735.  
  736. static bool fsl_esai_volatile_reg(struct device *dev, unsigned int reg)
  737. {
  738. switch (reg) {
  739. case REG_ESAI_ETDR:
  740. case REG_ESAI_ERDR:
  741. case REG_ESAI_ESR:
  742. case REG_ESAI_TFSR:
  743. case REG_ESAI_RFSR:
  744. case REG_ESAI_TX0:
  745. case REG_ESAI_TX1:
  746. case REG_ESAI_TX2:
  747. case REG_ESAI_TX3:
  748. case REG_ESAI_TX4:
  749. case REG_ESAI_TX5:
  750. case REG_ESAI_RX0:
  751. case REG_ESAI_RX1:
  752. case REG_ESAI_RX2:
  753. case REG_ESAI_RX3:
  754. case REG_ESAI_SAISR:
  755. return true;
  756. default:
  757. return false;
  758. }
  759.  
  760. }
  761.  
  762. static bool fsl_esai_writeable_reg(struct device *dev, unsigned int reg)
  763. {
  764. switch (reg) {
  765. case REG_ESAI_ETDR:
  766. case REG_ESAI_ECR:
  767. case REG_ESAI_TFCR:
  768. case REG_ESAI_RFCR:
  769. case REG_ESAI_TX0:
  770. case REG_ESAI_TX1:
  771. case REG_ESAI_TX2:
  772. case REG_ESAI_TX3:
  773. case REG_ESAI_TX4:
  774. case REG_ESAI_TX5:
  775. case REG_ESAI_TSR:
  776. case REG_ESAI_SAICR:
  777. case REG_ESAI_TCR:
  778. case REG_ESAI_TCCR:
  779. case REG_ESAI_RCR:
  780. case REG_ESAI_RCCR:
  781. case REG_ESAI_TSMA:
  782. case REG_ESAI_TSMB:
  783. case REG_ESAI_RSMA:
  784. case REG_ESAI_RSMB:
  785. case REG_ESAI_PRRC:
  786. case REG_ESAI_PCRC:
  787. return true;
  788. default:
  789. return false;
  790. }
  791. }
  792.  
  793. static const struct regmap_config fsl_esai_regmap_config = {
  794. .reg_bits = 32,
  795. .reg_stride = 4,
  796. .val_bits = 32,
  797.  
  798. .max_register = REG_ESAI_PCRC,
  799. .readable_reg = fsl_esai_readable_reg,
  800. .volatile_reg = fsl_esai_volatile_reg,
  801. .writeable_reg = fsl_esai_writeable_reg,
  802. .cache_type = REGCACHE_RBTREE,
  803. };
  804.  
  805. static bool fsl_esai_check_xrun(struct snd_pcm_substream *substream)
  806. {
  807. struct snd_soc_pcm_runtime *rtd = substream->private_data;
  808. struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
  809. struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(cpu_dai);
  810. u32 saisr;
  811.  
  812. regmap_read(esai_priv->regmap, REG_ESAI_SAISR, &saisr);
  813. printk(KERN_ERR"xrun checking :0x0%X\n",saisr);
  814. return saisr & (ESAI_SAISR_TUE | ESAI_SAISR_ROE) ;
  815. }
  816.  
  817. static int stop_lock_stream(struct snd_pcm_substream *substream)
  818. {
  819. if (substream) {
  820. snd_pcm_stream_lock_irq(substream);
  821. if (substream->runtime->status->state == SNDRV_PCM_STATE_RUNNING)
  822. substream->ops->trigger(substream, SNDRV_PCM_TRIGGER_STOP);
  823. }
  824. return 0;
  825. }
  826.  
  827. static int start_unlock_stream(struct snd_pcm_substream *substream)
  828. {
  829. if (substream) {
  830. if (substream->runtime->status->state == SNDRV_PCM_STATE_RUNNING)
  831. substream->ops->trigger(substream, SNDRV_PCM_TRIGGER_START);
  832. snd_pcm_stream_unlock_irq(substream);
  833. }
  834. return 0;
  835. }
  836.  
  837. /*
  838. *Here is ESAI underrun reset step:
  839. *1. Read "TUE" and got TUE=1
  840. *2. stop DMA.
  841. *3. stop ESAI TX section.
  842. *4. Set the transmitter section individual reset "TPR=1"
  843. *5. Reset the ESAI Transmit FIFO (set ESAI_TFCR[1]=1).
  844. *6. Config the control registers ESAI_TCCR and ESAI_TCR.config the Transmit FIFO register.
  845. *7. clear "TPR"
  846. *8. read "TUE"
  847. *9. Prefill ESAI TX FIFO.
  848. *10.Start DMA.
  849. *11 Enable the ESAI
  850. */
  851. static void fsl_esai_reset(struct snd_pcm_substream *substream, bool stop)
  852. {
  853. struct snd_soc_pcm_runtime *rtd = substream->private_data;
  854. struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
  855. struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(cpu_dai);
  856. u32 saisr;
  857.  
  858. printk(KERN_ERR"!!!!!!!! %s(%d) FSL RESET !!!\n",__func__,__LINE__);
  859. if (stop) {
  860. stop_lock_stream(esai_priv->substream[0]);
  861. stop_lock_stream(esai_priv->substream[1]);
  862. }
  863.  
  864.  
  865. regmap_update_bits(esai_priv->regmap, REG_ESAI_ECR,
  866. ESAI_ECR_ESAIEN_MASK | ESAI_ECR_ERST_MASK,
  867. ESAI_ECR_ESAIEN | ESAI_ECR_ERST);
  868. regmap_update_bits(esai_priv->regmap, REG_ESAI_ECR,
  869. ESAI_ECR_ESAIEN_MASK | ESAI_ECR_ERST_MASK,
  870. ESAI_ECR_ESAIEN);
  871.  
  872. regmap_update_bits(esai_priv->regmap, REG_ESAI_TCR, ESAI_xCR_xPR_MASK, ESAI_xCR_xPR);
  873. regmap_update_bits(esai_priv->regmap, REG_ESAI_RCR, ESAI_xCR_xPR_MASK, ESAI_xCR_xPR);
  874.  
  875. regmap_update_bits(esai_priv->regmap, REG_ESAI_PRRC, ESAI_PRRC_PDC_MASK, 0);
  876. regmap_update_bits(esai_priv->regmap, REG_ESAI_PCRC, ESAI_PCRC_PC_MASK, 0);
  877.  
  878. /*
  879. * Add fifo reset here, because the regcache_sync will write one more data to ETDR.
  880. * Which will cause channel shift.
  881. */
  882. regmap_update_bits(esai_priv->regmap, REG_ESAI_TFCR, ESAI_xFCR_xFR_MASK, ESAI_xFCR_xFR);
  883. regmap_update_bits(esai_priv->regmap, REG_ESAI_RFCR, ESAI_xFCR_xFR_MASK, ESAI_xFCR_xFR);
  884.  
  885. regcache_mark_dirty(esai_priv->regmap);
  886. regcache_sync(esai_priv->regmap);
  887.  
  888. regmap_update_bits(esai_priv->regmap, REG_ESAI_TFCR, ESAI_xFCR_xFR_MASK, 0);
  889. regmap_update_bits(esai_priv->regmap, REG_ESAI_RFCR, ESAI_xFCR_xFR_MASK, 0);
  890.  
  891. regmap_update_bits(esai_priv->regmap, REG_ESAI_TCR, ESAI_xCR_xPR_MASK, 0);
  892. regmap_update_bits(esai_priv->regmap, REG_ESAI_RCR, ESAI_xCR_xPR_MASK, 0);
  893.  
  894. regmap_update_bits(esai_priv->regmap, REG_ESAI_PRRC,
  895. ESAI_PRRC_PDC_MASK, ESAI_PRRC_PDC(ESAI_GPIO));
  896. regmap_update_bits(esai_priv->regmap, REG_ESAI_PCRC,
  897. ESAI_PCRC_PC_MASK, ESAI_PCRC_PC(ESAI_GPIO));
  898.  
  899. regmap_read(esai_priv->regmap, REG_ESAI_SAISR, &saisr);
  900.  
  901. if (stop) {
  902. start_unlock_stream(esai_priv->substream[1]);
  903. start_unlock_stream(esai_priv->substream[0]);
  904. }
  905. }
  906.  
  907. static int fsl_esai_probe(struct platform_device *pdev)
  908. {
  909. struct device_node *np = pdev->dev.of_node;
  910. struct fsl_esai *esai_priv;
  911. struct resource *res;
  912. const uint32_t *iprop;
  913. void __iomem *regs;
  914. int irq, ret;
  915. u32 dma_events[2];
  916.  
  917. esai_priv = devm_kzalloc(&pdev->dev, sizeof(*esai_priv), GFP_KERNEL);
  918. if (!esai_priv)
  919. return -ENOMEM;
  920.  
  921. esai_priv->pdev = pdev;
  922. strcpy(esai_priv->name, np->name);
  923.  
  924. /* Get the addresses and IRQ */
  925. res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  926. regs = devm_ioremap_resource(&pdev->dev, res);
  927. if (IS_ERR(regs))
  928. return PTR_ERR(regs);
  929.  
  930. esai_priv->regmap = devm_regmap_init_mmio_clk(&pdev->dev,
  931. "core", regs, &fsl_esai_regmap_config);
  932. if (IS_ERR(esai_priv->regmap)) {
  933. dev_err(&pdev->dev, "failed to init regmap: %ld\n",
  934. PTR_ERR(esai_priv->regmap));
  935. return PTR_ERR(esai_priv->regmap);
  936. }
  937.  
  938. esai_priv->coreclk = devm_clk_get(&pdev->dev, "core");
  939. if (IS_ERR(esai_priv->coreclk)) {
  940. dev_err(&pdev->dev, "failed to get core clock: %ld\n",
  941. PTR_ERR(esai_priv->coreclk));
  942. return PTR_ERR(esai_priv->coreclk);
  943. }
  944.  
  945. esai_priv->extalclk = devm_clk_get(&pdev->dev, "extal");
  946. if (IS_ERR(esai_priv->extalclk))
  947. dev_warn(&pdev->dev, "failed to get extal clock: %ld\n",
  948. PTR_ERR(esai_priv->extalclk));
  949.  
  950. esai_priv->fsysclk = devm_clk_get(&pdev->dev, "fsys");
  951. if (IS_ERR(esai_priv->fsysclk))
  952. dev_warn(&pdev->dev, "failed to get fsys clock: %ld\n",
  953. PTR_ERR(esai_priv->fsysclk));
  954.  
  955. esai_priv->dmaclk = devm_clk_get(&pdev->dev, "dma");
  956. if (IS_ERR(esai_priv->dmaclk)) {
  957. dev_err(&pdev->dev, "Cannot get dma clock: %ld\n",
  958. PTR_ERR(esai_priv->dmaclk));
  959. return PTR_ERR(esai_priv->dmaclk);
  960. }
  961.  
  962. irq = platform_get_irq(pdev, 0);
  963. if (irq < 0) {
  964. dev_err(&pdev->dev, "no irq for node %s\n", np->full_name);
  965. return irq;
  966. }
  967.  
  968. ret = devm_request_irq(&pdev->dev, irq, esai_isr, 0,
  969. esai_priv->name, esai_priv);
  970. if (ret) {
  971. dev_err(&pdev->dev, "failed to claim irq %u\n", irq);
  972. return ret;
  973. }
  974.  
  975. /* Set a default slot size */
  976. esai_priv->slot_width = 32;
  977.  
  978. /* Set a default master/slave state */
  979. esai_priv->slave_mode = true;
  980.  
  981. /* Determine the FIFO depth */
  982. iprop = of_get_property(np, "fsl,fifo-depth", NULL);
  983. if (iprop)
  984. esai_priv->fifo_depth = be32_to_cpup(iprop);
  985. else
  986. esai_priv->fifo_depth = 64;
  987.  
  988. esai_priv->dma_params_tx.maxburst = 16;
  989. esai_priv->dma_params_rx.maxburst = 16;
  990. esai_priv->dma_params_tx.addr = res->start + REG_ESAI_ETDR;
  991. esai_priv->dma_params_rx.addr = res->start + REG_ESAI_ERDR;
  992.  
  993. esai_priv->dma_params_tx.filter_data = &esai_priv->filter_data_tx;
  994. esai_priv->dma_params_rx.filter_data = &esai_priv->filter_data_rx;
  995.  
  996. ret = of_property_read_u32_array(pdev->dev.of_node,
  997. "fsl,esai-dma-events", dma_events, 2);
  998. if (ret) {
  999. dev_err(&pdev->dev, "could not get dma events\n");
  1000. return ret;
  1001. }
  1002.  
  1003. esai_priv->filter_data_tx.dma_request0 = dma_events[0];
  1004. esai_priv->filter_data_rx.dma_request0 = dma_events[1];
  1005. esai_priv->filter_data_tx.peripheral_type = IMX_DMATYPE_ESAI;
  1006. esai_priv->filter_data_rx.peripheral_type = IMX_DMATYPE_ESAI;
  1007.  
  1008. esai_priv->dma_params_tx.check_xrun = fsl_esai_check_xrun;
  1009. esai_priv->dma_params_rx.check_xrun = fsl_esai_check_xrun;
  1010. esai_priv->dma_params_tx.device_reset = fsl_esai_reset;
  1011. esai_priv->dma_params_rx.device_reset = fsl_esai_reset;
  1012.  
  1013. esai_priv->synchronous =
  1014. of_property_read_bool(np, "fsl,esai-synchronous");
  1015.  
  1016. /* Implement full symmetry for synchronous mode */
  1017. if (esai_priv->synchronous) {
  1018. printk(KERN_ERR"Using ESAI in Synchronous mode\n");
  1019. fsl_esai_dai.symmetric_rates = 1;
  1020. fsl_esai_dai.symmetric_channels = 1;
  1021. fsl_esai_dai.symmetric_samplebits = 1;
  1022. }
  1023.  
  1024. dev_set_drvdata(&pdev->dev, esai_priv);
  1025.  
  1026. /* Reset ESAI unit */
  1027. ret = regmap_write(esai_priv->regmap, REG_ESAI_ECR, ESAI_ECR_ERST);
  1028. if (ret) {
  1029. dev_err(&pdev->dev, "failed to reset ESAI: %d\n", ret);
  1030. return ret;
  1031. }
  1032.  
  1033. /*
  1034. * We need to enable ESAI so as to access some of its registers.
  1035. * Otherwise, we would fail to dump regmap from user space.
  1036. */
  1037. ret = regmap_write(esai_priv->regmap, REG_ESAI_ECR, ESAI_ECR_ESAIEN);
  1038. if (ret) {
  1039. dev_err(&pdev->dev, "failed to enable ESAI: %d\n", ret);
  1040. return ret;
  1041. }
  1042.  
  1043. ret = devm_snd_soc_register_component(&pdev->dev, &fsl_esai_component,
  1044. &fsl_esai_dai, 1);
  1045. if (ret) {
  1046. dev_err(&pdev->dev, "failed to register DAI: %d\n", ret);
  1047. return ret;
  1048. }
  1049.  
  1050. ret = imx_pcm_dma_init(pdev, SND_DMAENGINE_PCM_FLAG_NO_RESIDUE |
  1051. SND_DMAENGINE_PCM_FLAG_NO_DT |
  1052. SND_DMAENGINE_PCM_FLAG_COMPAT,
  1053. IMX_ESAI_DMABUF_SIZE);
  1054. if (ret)
  1055. dev_err(&pdev->dev, "failed to init imx pcm dma: %d\n", ret);
  1056.  
  1057. return ret;
  1058. }
  1059.  
  1060. static const struct of_device_id fsl_esai_dt_ids[] = {
  1061. { .compatible = "fsl,imx35-esai", },
  1062. {}
  1063. };
  1064. MODULE_DEVICE_TABLE(of, fsl_esai_dt_ids);
  1065.  
  1066. #if CONFIG_PM_SLEEP
  1067. static int fsl_esai_suspend(struct device *dev)
  1068. {
  1069. struct fsl_esai *esai = dev_get_drvdata(dev);
  1070.  
  1071. regcache_cache_only(esai->regmap, true);
  1072. regcache_mark_dirty(esai->regmap);
  1073.  
  1074. return 0;
  1075. }
  1076.  
  1077. static int fsl_esai_resume(struct device *dev)
  1078. {
  1079. struct fsl_esai *esai = dev_get_drvdata(dev);
  1080. int ret;
  1081.  
  1082. regcache_cache_only(esai->regmap, false);
  1083.  
  1084. /* FIFO reset for safety */
  1085. regmap_update_bits(esai->regmap, REG_ESAI_TFCR,
  1086. ESAI_xFCR_xFR, ESAI_xFCR_xFR);
  1087. regmap_update_bits(esai->regmap, REG_ESAI_RFCR,
  1088. ESAI_xFCR_xFR, ESAI_xFCR_xFR);
  1089.  
  1090. ret = regcache_sync(esai->regmap);
  1091. if (ret)
  1092. return ret;
  1093.  
  1094. /* FIFO reset done */
  1095. regmap_update_bits(esai->regmap, REG_ESAI_TFCR, ESAI_xFCR_xFR, 0);
  1096. regmap_update_bits(esai->regmap, REG_ESAI_RFCR, ESAI_xFCR_xFR, 0);
  1097.  
  1098. return 0;
  1099. }
  1100. #endif /* CONFIG_PM_SLEEP */
  1101.  
  1102. static const struct dev_pm_ops fsl_esai_pm_ops = {
  1103. SET_SYSTEM_SLEEP_PM_OPS(fsl_esai_suspend, fsl_esai_resume)
  1104. };
  1105.  
  1106. static struct platform_driver fsl_esai_driver = {
  1107. .probe = fsl_esai_probe,
  1108. .driver = {
  1109. .name = "fsl-esai-dai",
  1110. .owner = THIS_MODULE,
  1111. .pm = &fsl_esai_pm_ops,
  1112. .of_match_table = fsl_esai_dt_ids,
  1113. },
  1114. };
  1115.  
  1116. module_platform_driver(fsl_esai_driver);
  1117.  
  1118. MODULE_AUTHOR("Freescale Semiconductor, Inc.");
  1119. MODULE_DESCRIPTION("Freescale ESAI CPU DAI driver");
  1120. MODULE_LICENSE("GPL v2");
  1121. MODULE_ALIAS("platform:fsl-esai-dai");
Add Comment
Please, Sign In to add comment