fsl_esai.c 27 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013
  1. // SPDX-License-Identifier: GPL-2.0
  2. //
  3. // Freescale ESAI ALSA SoC Digital Audio Interface (DAI) driver
  4. //
  5. // Copyright (C) 2014 Freescale Semiconductor, Inc.
  6. #include <linux/clk.h>
  7. #include <linux/dmaengine.h>
  8. #include <linux/module.h>
  9. #include <linux/of_irq.h>
  10. #include <linux/of_platform.h>
  11. #include <sound/dmaengine_pcm.h>
  12. #include <sound/pcm_params.h>
  13. #include "fsl_esai.h"
  14. #include "imx-pcm.h"
  15. #define FSL_ESAI_FORMATS (SNDRV_PCM_FMTBIT_S8 | \
  16. SNDRV_PCM_FMTBIT_S16_LE | \
  17. SNDRV_PCM_FMTBIT_S20_3LE | \
  18. SNDRV_PCM_FMTBIT_S24_LE)
  19. /**
  20. * fsl_esai: ESAI private data
  21. *
  22. * @dma_params_rx: DMA parameters for receive channel
  23. * @dma_params_tx: DMA parameters for transmit channel
  24. * @pdev: platform device pointer
  25. * @regmap: regmap handler
  26. * @coreclk: clock source to access register
  27. * @extalclk: esai clock source to derive HCK, SCK and FS
  28. * @fsysclk: system clock source to derive HCK, SCK and FS
  29. * @spbaclk: SPBA clock (optional, depending on SoC design)
  30. * @fifo_depth: depth of tx/rx FIFO
  31. * @slot_width: width of each DAI slot
  32. * @slots: number of slots
  33. * @hck_rate: clock rate of desired HCKx clock
  34. * @sck_rate: clock rate of desired SCKx clock
  35. * @hck_dir: the direction of HCKx pads
  36. * @sck_div: if using PSR/PM dividers for SCKx clock
  37. * @slave_mode: if fully using DAI slave mode
  38. * @synchronous: if using tx/rx synchronous mode
  39. * @name: driver name
  40. */
  41. struct fsl_esai {
  42. struct snd_dmaengine_dai_dma_data dma_params_rx;
  43. struct snd_dmaengine_dai_dma_data dma_params_tx;
  44. struct platform_device *pdev;
  45. struct regmap *regmap;
  46. struct clk *coreclk;
  47. struct clk *extalclk;
  48. struct clk *fsysclk;
  49. struct clk *spbaclk;
  50. u32 fifo_depth;
  51. u32 slot_width;
  52. u32 slots;
  53. u32 tx_mask;
  54. u32 rx_mask;
  55. u32 hck_rate[2];
  56. u32 sck_rate[2];
  57. bool hck_dir[2];
  58. bool sck_div[2];
  59. bool slave_mode;
  60. bool synchronous;
  61. char name[32];
  62. };
  63. static irqreturn_t esai_isr(int irq, void *devid)
  64. {
  65. struct fsl_esai *esai_priv = (struct fsl_esai *)devid;
  66. struct platform_device *pdev = esai_priv->pdev;
  67. u32 esr;
  68. regmap_read(esai_priv->regmap, REG_ESAI_ESR, &esr);
  69. if (esr & ESAI_ESR_TINIT_MASK)
  70. dev_dbg(&pdev->dev, "isr: Transmission Initialized\n");
  71. if (esr & ESAI_ESR_RFF_MASK)
  72. dev_warn(&pdev->dev, "isr: Receiving overrun\n");
  73. if (esr & ESAI_ESR_TFE_MASK)
  74. dev_warn(&pdev->dev, "isr: Transmission underrun\n");
  75. if (esr & ESAI_ESR_TLS_MASK)
  76. dev_dbg(&pdev->dev, "isr: Just transmitted the last slot\n");
  77. if (esr & ESAI_ESR_TDE_MASK)
  78. dev_dbg(&pdev->dev, "isr: Transmission data exception\n");
  79. if (esr & ESAI_ESR_TED_MASK)
  80. dev_dbg(&pdev->dev, "isr: Transmitting even slots\n");
  81. if (esr & ESAI_ESR_TD_MASK)
  82. dev_dbg(&pdev->dev, "isr: Transmitting data\n");
  83. if (esr & ESAI_ESR_RLS_MASK)
  84. dev_dbg(&pdev->dev, "isr: Just received the last slot\n");
  85. if (esr & ESAI_ESR_RDE_MASK)
  86. dev_dbg(&pdev->dev, "isr: Receiving data exception\n");
  87. if (esr & ESAI_ESR_RED_MASK)
  88. dev_dbg(&pdev->dev, "isr: Receiving even slots\n");
  89. if (esr & ESAI_ESR_RD_MASK)
  90. dev_dbg(&pdev->dev, "isr: Receiving data\n");
  91. return IRQ_HANDLED;
  92. }
  93. /**
  94. * This function is used to calculate the divisors of psr, pm, fp and it is
  95. * supposed to be called in set_dai_sysclk() and set_bclk().
  96. *
  97. * @ratio: desired overall ratio for the paticipating dividers
  98. * @usefp: for HCK setting, there is no need to set fp divider
  99. * @fp: bypass other dividers by setting fp directly if fp != 0
  100. * @tx: current setting is for playback or capture
  101. */
  102. static int fsl_esai_divisor_cal(struct snd_soc_dai *dai, bool tx, u32 ratio,
  103. bool usefp, u32 fp)
  104. {
  105. struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai);
  106. u32 psr, pm = 999, maxfp, prod, sub, savesub, i, j;
  107. maxfp = usefp ? 16 : 1;
  108. if (usefp && fp)
  109. goto out_fp;
  110. if (ratio > 2 * 8 * 256 * maxfp || ratio < 2) {
  111. dev_err(dai->dev, "the ratio is out of range (2 ~ %d)\n",
  112. 2 * 8 * 256 * maxfp);
  113. return -EINVAL;
  114. } else if (ratio % 2) {
  115. dev_err(dai->dev, "the raio must be even if using upper divider\n");
  116. return -EINVAL;
  117. }
  118. ratio /= 2;
  119. psr = ratio <= 256 * maxfp ? ESAI_xCCR_xPSR_BYPASS : ESAI_xCCR_xPSR_DIV8;
  120. /* Do not loop-search if PM (1 ~ 256) alone can serve the ratio */
  121. if (ratio <= 256) {
  122. pm = ratio;
  123. fp = 1;
  124. goto out;
  125. }
  126. /* Set the max fluctuation -- 0.1% of the max devisor */
  127. savesub = (psr ? 1 : 8) * 256 * maxfp / 1000;
  128. /* Find the best value for PM */
  129. for (i = 1; i <= 256; i++) {
  130. for (j = 1; j <= maxfp; j++) {
  131. /* PSR (1 or 8) * PM (1 ~ 256) * FP (1 ~ 16) */
  132. prod = (psr ? 1 : 8) * i * j;
  133. if (prod == ratio)
  134. sub = 0;
  135. else if (prod / ratio == 1)
  136. sub = prod - ratio;
  137. else if (ratio / prod == 1)
  138. sub = ratio - prod;
  139. else
  140. continue;
  141. /* Calculate the fraction */
  142. sub = sub * 1000 / ratio;
  143. if (sub < savesub) {
  144. savesub = sub;
  145. pm = i;
  146. fp = j;
  147. }
  148. /* We are lucky */
  149. if (savesub == 0)
  150. goto out;
  151. }
  152. }
  153. if (pm == 999) {
  154. dev_err(dai->dev, "failed to calculate proper divisors\n");
  155. return -EINVAL;
  156. }
  157. out:
  158. regmap_update_bits(esai_priv->regmap, REG_ESAI_xCCR(tx),
  159. ESAI_xCCR_xPSR_MASK | ESAI_xCCR_xPM_MASK,
  160. psr | ESAI_xCCR_xPM(pm));
  161. out_fp:
  162. /* Bypass fp if not being required */
  163. if (maxfp <= 1)
  164. return 0;
  165. regmap_update_bits(esai_priv->regmap, REG_ESAI_xCCR(tx),
  166. ESAI_xCCR_xFP_MASK, ESAI_xCCR_xFP(fp));
  167. return 0;
  168. }
  169. /**
  170. * This function mainly configures the clock frequency of MCLK (HCKT/HCKR)
  171. *
  172. * @Parameters:
  173. * clk_id: The clock source of HCKT/HCKR
  174. * (Input from outside; output from inside, FSYS or EXTAL)
  175. * freq: The required clock rate of HCKT/HCKR
  176. * dir: The clock direction of HCKT/HCKR
  177. *
  178. * Note: If the direction is input, we do not care about clk_id.
  179. */
  180. static int fsl_esai_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id,
  181. unsigned int freq, int dir)
  182. {
  183. struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai);
  184. struct clk *clksrc = esai_priv->extalclk;
  185. bool tx = clk_id <= ESAI_HCKT_EXTAL;
  186. bool in = dir == SND_SOC_CLOCK_IN;
  187. u32 ratio, ecr = 0;
  188. unsigned long clk_rate;
  189. int ret;
  190. if (freq == 0) {
  191. dev_err(dai->dev, "%sput freq of HCK%c should not be 0Hz\n",
  192. in ? "in" : "out", tx ? 'T' : 'R');
  193. return -EINVAL;
  194. }
  195. /* Bypass divider settings if the requirement doesn't change */
  196. if (freq == esai_priv->hck_rate[tx] && dir == esai_priv->hck_dir[tx])
  197. return 0;
  198. /* sck_div can be only bypassed if ETO/ERO=0 and SNC_SOC_CLOCK_OUT */
  199. esai_priv->sck_div[tx] = true;
  200. /* Set the direction of HCKT/HCKR pins */
  201. regmap_update_bits(esai_priv->regmap, REG_ESAI_xCCR(tx),
  202. ESAI_xCCR_xHCKD, in ? 0 : ESAI_xCCR_xHCKD);
  203. if (in)
  204. goto out;
  205. switch (clk_id) {
  206. case ESAI_HCKT_FSYS:
  207. case ESAI_HCKR_FSYS:
  208. clksrc = esai_priv->fsysclk;
  209. break;
  210. case ESAI_HCKT_EXTAL:
  211. ecr |= ESAI_ECR_ETI;
  212. break;
  213. case ESAI_HCKR_EXTAL:
  214. ecr |= ESAI_ECR_ERI;
  215. break;
  216. default:
  217. return -EINVAL;
  218. }
  219. if (IS_ERR(clksrc)) {
  220. dev_err(dai->dev, "no assigned %s clock\n",
  221. clk_id % 2 ? "extal" : "fsys");
  222. return PTR_ERR(clksrc);
  223. }
  224. clk_rate = clk_get_rate(clksrc);
  225. ratio = clk_rate / freq;
  226. if (ratio * freq > clk_rate)
  227. ret = ratio * freq - clk_rate;
  228. else if (ratio * freq < clk_rate)
  229. ret = clk_rate - ratio * freq;
  230. else
  231. ret = 0;
  232. /* Block if clock source can not be divided into the required rate */
  233. if (ret != 0 && clk_rate / ret < 1000) {
  234. dev_err(dai->dev, "failed to derive required HCK%c rate\n",
  235. tx ? 'T' : 'R');
  236. return -EINVAL;
  237. }
  238. /* Only EXTAL source can be output directly without using PSR and PM */
  239. if (ratio == 1 && clksrc == esai_priv->extalclk) {
  240. /* Bypass all the dividers if not being needed */
  241. ecr |= tx ? ESAI_ECR_ETO : ESAI_ECR_ERO;
  242. goto out;
  243. } else if (ratio < 2) {
  244. /* The ratio should be no less than 2 if using other sources */
  245. dev_err(dai->dev, "failed to derive required HCK%c rate\n",
  246. tx ? 'T' : 'R');
  247. return -EINVAL;
  248. }
  249. ret = fsl_esai_divisor_cal(dai, tx, ratio, false, 0);
  250. if (ret)
  251. return ret;
  252. esai_priv->sck_div[tx] = false;
  253. out:
  254. esai_priv->hck_dir[tx] = dir;
  255. esai_priv->hck_rate[tx] = freq;
  256. regmap_update_bits(esai_priv->regmap, REG_ESAI_ECR,
  257. tx ? ESAI_ECR_ETI | ESAI_ECR_ETO :
  258. ESAI_ECR_ERI | ESAI_ECR_ERO, ecr);
  259. return 0;
  260. }
  261. /**
  262. * This function configures the related dividers according to the bclk rate
  263. */
  264. static int fsl_esai_set_bclk(struct snd_soc_dai *dai, bool tx, u32 freq)
  265. {
  266. struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai);
  267. u32 hck_rate = esai_priv->hck_rate[tx];
  268. u32 sub, ratio = hck_rate / freq;
  269. int ret;
  270. /* Don't apply for fully slave mode or unchanged bclk */
  271. if (esai_priv->slave_mode || esai_priv->sck_rate[tx] == freq)
  272. return 0;
  273. if (ratio * freq > hck_rate)
  274. sub = ratio * freq - hck_rate;
  275. else if (ratio * freq < hck_rate)
  276. sub = hck_rate - ratio * freq;
  277. else
  278. sub = 0;
  279. /* Block if clock source can not be divided into the required rate */
  280. if (sub != 0 && hck_rate / sub < 1000) {
  281. dev_err(dai->dev, "failed to derive required SCK%c rate\n",
  282. tx ? 'T' : 'R');
  283. return -EINVAL;
  284. }
  285. /* The ratio should be contented by FP alone if bypassing PM and PSR */
  286. if (!esai_priv->sck_div[tx] && (ratio > 16 || ratio == 0)) {
  287. dev_err(dai->dev, "the ratio is out of range (1 ~ 16)\n");
  288. return -EINVAL;
  289. }
  290. ret = fsl_esai_divisor_cal(dai, tx, ratio, true,
  291. esai_priv->sck_div[tx] ? 0 : ratio);
  292. if (ret)
  293. return ret;
  294. /* Save current bclk rate */
  295. esai_priv->sck_rate[tx] = freq;
  296. return 0;
  297. }
  298. static int fsl_esai_set_dai_tdm_slot(struct snd_soc_dai *dai, u32 tx_mask,
  299. u32 rx_mask, int slots, int slot_width)
  300. {
  301. struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai);
  302. regmap_update_bits(esai_priv->regmap, REG_ESAI_TCCR,
  303. ESAI_xCCR_xDC_MASK, ESAI_xCCR_xDC(slots));
  304. regmap_update_bits(esai_priv->regmap, REG_ESAI_RCCR,
  305. ESAI_xCCR_xDC_MASK, ESAI_xCCR_xDC(slots));
  306. esai_priv->slot_width = slot_width;
  307. esai_priv->slots = slots;
  308. esai_priv->tx_mask = tx_mask;
  309. esai_priv->rx_mask = rx_mask;
  310. return 0;
  311. }
  312. static int fsl_esai_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
  313. {
  314. struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai);
  315. u32 xcr = 0, xccr = 0, mask;
  316. /* DAI mode */
  317. switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
  318. case SND_SOC_DAIFMT_I2S:
  319. /* Data on rising edge of bclk, frame low, 1clk before data */
  320. xcr |= ESAI_xCR_xFSR;
  321. xccr |= ESAI_xCCR_xFSP | ESAI_xCCR_xCKP | ESAI_xCCR_xHCKP;
  322. break;
  323. case SND_SOC_DAIFMT_LEFT_J:
  324. /* Data on rising edge of bclk, frame high */
  325. xccr |= ESAI_xCCR_xCKP | ESAI_xCCR_xHCKP;
  326. break;
  327. case SND_SOC_DAIFMT_RIGHT_J:
  328. /* Data on rising edge of bclk, frame high, right aligned */
  329. xccr |= ESAI_xCCR_xCKP | ESAI_xCCR_xHCKP;
  330. xcr |= ESAI_xCR_xWA;
  331. break;
  332. case SND_SOC_DAIFMT_DSP_A:
  333. /* Data on rising edge of bclk, frame high, 1clk before data */
  334. xcr |= ESAI_xCR_xFSL | ESAI_xCR_xFSR;
  335. xccr |= ESAI_xCCR_xCKP | ESAI_xCCR_xHCKP;
  336. break;
  337. case SND_SOC_DAIFMT_DSP_B:
  338. /* Data on rising edge of bclk, frame high */
  339. xcr |= ESAI_xCR_xFSL;
  340. xccr |= ESAI_xCCR_xCKP | ESAI_xCCR_xHCKP;
  341. break;
  342. default:
  343. return -EINVAL;
  344. }
  345. /* DAI clock inversion */
  346. switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
  347. case SND_SOC_DAIFMT_NB_NF:
  348. /* Nothing to do for both normal cases */
  349. break;
  350. case SND_SOC_DAIFMT_IB_NF:
  351. /* Invert bit clock */
  352. xccr ^= ESAI_xCCR_xCKP | ESAI_xCCR_xHCKP;
  353. break;
  354. case SND_SOC_DAIFMT_NB_IF:
  355. /* Invert frame clock */
  356. xccr ^= ESAI_xCCR_xFSP;
  357. break;
  358. case SND_SOC_DAIFMT_IB_IF:
  359. /* Invert both clocks */
  360. xccr ^= ESAI_xCCR_xCKP | ESAI_xCCR_xHCKP | ESAI_xCCR_xFSP;
  361. break;
  362. default:
  363. return -EINVAL;
  364. }
  365. esai_priv->slave_mode = false;
  366. /* DAI clock master masks */
  367. switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
  368. case SND_SOC_DAIFMT_CBM_CFM:
  369. esai_priv->slave_mode = true;
  370. break;
  371. case SND_SOC_DAIFMT_CBS_CFM:
  372. xccr |= ESAI_xCCR_xCKD;
  373. break;
  374. case SND_SOC_DAIFMT_CBM_CFS:
  375. xccr |= ESAI_xCCR_xFSD;
  376. break;
  377. case SND_SOC_DAIFMT_CBS_CFS:
  378. xccr |= ESAI_xCCR_xFSD | ESAI_xCCR_xCKD;
  379. break;
  380. default:
  381. return -EINVAL;
  382. }
  383. mask = ESAI_xCR_xFSL | ESAI_xCR_xFSR | ESAI_xCR_xWA;
  384. regmap_update_bits(esai_priv->regmap, REG_ESAI_TCR, mask, xcr);
  385. regmap_update_bits(esai_priv->regmap, REG_ESAI_RCR, mask, xcr);
  386. mask = ESAI_xCCR_xCKP | ESAI_xCCR_xHCKP | ESAI_xCCR_xFSP |
  387. ESAI_xCCR_xFSD | ESAI_xCCR_xCKD;
  388. regmap_update_bits(esai_priv->regmap, REG_ESAI_TCCR, mask, xccr);
  389. regmap_update_bits(esai_priv->regmap, REG_ESAI_RCCR, mask, xccr);
  390. return 0;
  391. }
  392. static int fsl_esai_startup(struct snd_pcm_substream *substream,
  393. struct snd_soc_dai *dai)
  394. {
  395. struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai);
  396. int ret;
  397. /*
  398. * Some platforms might use the same bit to gate all three or two of
  399. * clocks, so keep all clocks open/close at the same time for safety
  400. */
  401. ret = clk_prepare_enable(esai_priv->coreclk);
  402. if (ret)
  403. return ret;
  404. if (!IS_ERR(esai_priv->spbaclk)) {
  405. ret = clk_prepare_enable(esai_priv->spbaclk);
  406. if (ret)
  407. goto err_spbaclk;
  408. }
  409. if (!IS_ERR(esai_priv->extalclk)) {
  410. ret = clk_prepare_enable(esai_priv->extalclk);
  411. if (ret)
  412. goto err_extalck;
  413. }
  414. if (!IS_ERR(esai_priv->fsysclk)) {
  415. ret = clk_prepare_enable(esai_priv->fsysclk);
  416. if (ret)
  417. goto err_fsysclk;
  418. }
  419. if (!dai->active) {
  420. /* Set synchronous mode */
  421. regmap_update_bits(esai_priv->regmap, REG_ESAI_SAICR,
  422. ESAI_SAICR_SYNC, esai_priv->synchronous ?
  423. ESAI_SAICR_SYNC : 0);
  424. /* Set slots count */
  425. regmap_update_bits(esai_priv->regmap, REG_ESAI_TCCR,
  426. ESAI_xCCR_xDC_MASK,
  427. ESAI_xCCR_xDC(esai_priv->slots));
  428. regmap_update_bits(esai_priv->regmap, REG_ESAI_RCCR,
  429. ESAI_xCCR_xDC_MASK,
  430. ESAI_xCCR_xDC(esai_priv->slots));
  431. }
  432. return 0;
  433. err_fsysclk:
  434. if (!IS_ERR(esai_priv->extalclk))
  435. clk_disable_unprepare(esai_priv->extalclk);
  436. err_extalck:
  437. if (!IS_ERR(esai_priv->spbaclk))
  438. clk_disable_unprepare(esai_priv->spbaclk);
  439. err_spbaclk:
  440. clk_disable_unprepare(esai_priv->coreclk);
  441. return ret;
  442. }
  443. static int fsl_esai_hw_params(struct snd_pcm_substream *substream,
  444. struct snd_pcm_hw_params *params,
  445. struct snd_soc_dai *dai)
  446. {
  447. struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai);
  448. bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
  449. u32 width = params_width(params);
  450. u32 channels = params_channels(params);
  451. u32 pins = DIV_ROUND_UP(channels, esai_priv->slots);
  452. u32 slot_width = width;
  453. u32 bclk, mask, val;
  454. int ret;
  455. /* Override slot_width if being specifically set */
  456. if (esai_priv->slot_width)
  457. slot_width = esai_priv->slot_width;
  458. bclk = params_rate(params) * slot_width * esai_priv->slots;
  459. ret = fsl_esai_set_bclk(dai, tx, bclk);
  460. if (ret)
  461. return ret;
  462. /* Use Normal mode to support monaural audio */
  463. regmap_update_bits(esai_priv->regmap, REG_ESAI_xCR(tx),
  464. ESAI_xCR_xMOD_MASK, params_channels(params) > 1 ?
  465. ESAI_xCR_xMOD_NETWORK : 0);
  466. regmap_update_bits(esai_priv->regmap, REG_ESAI_xFCR(tx),
  467. ESAI_xFCR_xFR_MASK, ESAI_xFCR_xFR);
  468. mask = ESAI_xFCR_xFR_MASK | ESAI_xFCR_xWA_MASK | ESAI_xFCR_xFWM_MASK |
  469. (tx ? ESAI_xFCR_TE_MASK | ESAI_xFCR_TIEN : ESAI_xFCR_RE_MASK);
  470. val = ESAI_xFCR_xWA(width) | ESAI_xFCR_xFWM(esai_priv->fifo_depth) |
  471. (tx ? ESAI_xFCR_TE(pins) | ESAI_xFCR_TIEN : ESAI_xFCR_RE(pins));
  472. regmap_update_bits(esai_priv->regmap, REG_ESAI_xFCR(tx), mask, val);
  473. mask = ESAI_xCR_xSWS_MASK | (tx ? ESAI_xCR_PADC : 0);
  474. val = ESAI_xCR_xSWS(slot_width, width) | (tx ? ESAI_xCR_PADC : 0);
  475. regmap_update_bits(esai_priv->regmap, REG_ESAI_xCR(tx), mask, val);
  476. /* Remove ESAI personal reset by configuring ESAI_PCRC and ESAI_PRRC */
  477. regmap_update_bits(esai_priv->regmap, REG_ESAI_PRRC,
  478. ESAI_PRRC_PDC_MASK, ESAI_PRRC_PDC(ESAI_GPIO));
  479. regmap_update_bits(esai_priv->regmap, REG_ESAI_PCRC,
  480. ESAI_PCRC_PC_MASK, ESAI_PCRC_PC(ESAI_GPIO));
  481. return 0;
  482. }
  483. static void fsl_esai_shutdown(struct snd_pcm_substream *substream,
  484. struct snd_soc_dai *dai)
  485. {
  486. struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai);
  487. if (!IS_ERR(esai_priv->fsysclk))
  488. clk_disable_unprepare(esai_priv->fsysclk);
  489. if (!IS_ERR(esai_priv->extalclk))
  490. clk_disable_unprepare(esai_priv->extalclk);
  491. if (!IS_ERR(esai_priv->spbaclk))
  492. clk_disable_unprepare(esai_priv->spbaclk);
  493. clk_disable_unprepare(esai_priv->coreclk);
  494. }
  495. static int fsl_esai_trigger(struct snd_pcm_substream *substream, int cmd,
  496. struct snd_soc_dai *dai)
  497. {
  498. struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai);
  499. bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
  500. u8 i, channels = substream->runtime->channels;
  501. u32 pins = DIV_ROUND_UP(channels, esai_priv->slots);
  502. u32 mask;
  503. switch (cmd) {
  504. case SNDRV_PCM_TRIGGER_START:
  505. case SNDRV_PCM_TRIGGER_RESUME:
  506. case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
  507. regmap_update_bits(esai_priv->regmap, REG_ESAI_xFCR(tx),
  508. ESAI_xFCR_xFEN_MASK, ESAI_xFCR_xFEN);
  509. /* Write initial words reqiured by ESAI as normal procedure */
  510. for (i = 0; tx && i < channels; i++)
  511. regmap_write(esai_priv->regmap, REG_ESAI_ETDR, 0x0);
  512. /*
  513. * When set the TE/RE in the end of enablement flow, there
  514. * will be channel swap issue for multi data line case.
  515. * In order to workaround this issue, we switch the bit
  516. * enablement sequence to below sequence
  517. * 1) clear the xSMB & xSMA: which is done in probe and
  518. * stop state.
  519. * 2) set TE/RE
  520. * 3) set xSMB
  521. * 4) set xSMA: xSMA is the last one in this flow, which
  522. * will trigger esai to start.
  523. */
  524. regmap_update_bits(esai_priv->regmap, REG_ESAI_xCR(tx),
  525. tx ? ESAI_xCR_TE_MASK : ESAI_xCR_RE_MASK,
  526. tx ? ESAI_xCR_TE(pins) : ESAI_xCR_RE(pins));
  527. mask = tx ? esai_priv->tx_mask : esai_priv->rx_mask;
  528. regmap_update_bits(esai_priv->regmap, REG_ESAI_xSMB(tx),
  529. ESAI_xSMB_xS_MASK, ESAI_xSMB_xS(mask));
  530. regmap_update_bits(esai_priv->regmap, REG_ESAI_xSMA(tx),
  531. ESAI_xSMA_xS_MASK, ESAI_xSMA_xS(mask));
  532. break;
  533. case SNDRV_PCM_TRIGGER_SUSPEND:
  534. case SNDRV_PCM_TRIGGER_STOP:
  535. case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
  536. regmap_update_bits(esai_priv->regmap, REG_ESAI_xCR(tx),
  537. tx ? ESAI_xCR_TE_MASK : ESAI_xCR_RE_MASK, 0);
  538. regmap_update_bits(esai_priv->regmap, REG_ESAI_xSMA(tx),
  539. ESAI_xSMA_xS_MASK, 0);
  540. regmap_update_bits(esai_priv->regmap, REG_ESAI_xSMB(tx),
  541. ESAI_xSMB_xS_MASK, 0);
  542. /* Disable and reset FIFO */
  543. regmap_update_bits(esai_priv->regmap, REG_ESAI_xFCR(tx),
  544. ESAI_xFCR_xFR | ESAI_xFCR_xFEN, ESAI_xFCR_xFR);
  545. regmap_update_bits(esai_priv->regmap, REG_ESAI_xFCR(tx),
  546. ESAI_xFCR_xFR, 0);
  547. break;
  548. default:
  549. return -EINVAL;
  550. }
  551. return 0;
  552. }
  553. static const struct snd_soc_dai_ops fsl_esai_dai_ops = {
  554. .startup = fsl_esai_startup,
  555. .shutdown = fsl_esai_shutdown,
  556. .trigger = fsl_esai_trigger,
  557. .hw_params = fsl_esai_hw_params,
  558. .set_sysclk = fsl_esai_set_dai_sysclk,
  559. .set_fmt = fsl_esai_set_dai_fmt,
  560. .set_tdm_slot = fsl_esai_set_dai_tdm_slot,
  561. };
  562. static int fsl_esai_dai_probe(struct snd_soc_dai *dai)
  563. {
  564. struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai);
  565. snd_soc_dai_init_dma_data(dai, &esai_priv->dma_params_tx,
  566. &esai_priv->dma_params_rx);
  567. return 0;
  568. }
  569. static struct snd_soc_dai_driver fsl_esai_dai = {
  570. .probe = fsl_esai_dai_probe,
  571. .playback = {
  572. .stream_name = "CPU-Playback",
  573. .channels_min = 1,
  574. .channels_max = 12,
  575. .rates = SNDRV_PCM_RATE_8000_192000,
  576. .formats = FSL_ESAI_FORMATS,
  577. },
  578. .capture = {
  579. .stream_name = "CPU-Capture",
  580. .channels_min = 1,
  581. .channels_max = 8,
  582. .rates = SNDRV_PCM_RATE_8000_192000,
  583. .formats = FSL_ESAI_FORMATS,
  584. },
  585. .ops = &fsl_esai_dai_ops,
  586. };
  587. static const struct snd_soc_component_driver fsl_esai_component = {
  588. .name = "fsl-esai",
  589. };
  590. static const struct reg_default fsl_esai_reg_defaults[] = {
  591. {REG_ESAI_ETDR, 0x00000000},
  592. {REG_ESAI_ECR, 0x00000000},
  593. {REG_ESAI_TFCR, 0x00000000},
  594. {REG_ESAI_RFCR, 0x00000000},
  595. {REG_ESAI_TX0, 0x00000000},
  596. {REG_ESAI_TX1, 0x00000000},
  597. {REG_ESAI_TX2, 0x00000000},
  598. {REG_ESAI_TX3, 0x00000000},
  599. {REG_ESAI_TX4, 0x00000000},
  600. {REG_ESAI_TX5, 0x00000000},
  601. {REG_ESAI_TSR, 0x00000000},
  602. {REG_ESAI_SAICR, 0x00000000},
  603. {REG_ESAI_TCR, 0x00000000},
  604. {REG_ESAI_TCCR, 0x00000000},
  605. {REG_ESAI_RCR, 0x00000000},
  606. {REG_ESAI_RCCR, 0x00000000},
  607. {REG_ESAI_TSMA, 0x0000ffff},
  608. {REG_ESAI_TSMB, 0x0000ffff},
  609. {REG_ESAI_RSMA, 0x0000ffff},
  610. {REG_ESAI_RSMB, 0x0000ffff},
  611. {REG_ESAI_PRRC, 0x00000000},
  612. {REG_ESAI_PCRC, 0x00000000},
  613. };
  614. static bool fsl_esai_readable_reg(struct device *dev, unsigned int reg)
  615. {
  616. switch (reg) {
  617. case REG_ESAI_ERDR:
  618. case REG_ESAI_ECR:
  619. case REG_ESAI_ESR:
  620. case REG_ESAI_TFCR:
  621. case REG_ESAI_TFSR:
  622. case REG_ESAI_RFCR:
  623. case REG_ESAI_RFSR:
  624. case REG_ESAI_RX0:
  625. case REG_ESAI_RX1:
  626. case REG_ESAI_RX2:
  627. case REG_ESAI_RX3:
  628. case REG_ESAI_SAISR:
  629. case REG_ESAI_SAICR:
  630. case REG_ESAI_TCR:
  631. case REG_ESAI_TCCR:
  632. case REG_ESAI_RCR:
  633. case REG_ESAI_RCCR:
  634. case REG_ESAI_TSMA:
  635. case REG_ESAI_TSMB:
  636. case REG_ESAI_RSMA:
  637. case REG_ESAI_RSMB:
  638. case REG_ESAI_PRRC:
  639. case REG_ESAI_PCRC:
  640. return true;
  641. default:
  642. return false;
  643. }
  644. }
  645. static bool fsl_esai_volatile_reg(struct device *dev, unsigned int reg)
  646. {
  647. switch (reg) {
  648. case REG_ESAI_ERDR:
  649. case REG_ESAI_ESR:
  650. case REG_ESAI_TFSR:
  651. case REG_ESAI_RFSR:
  652. case REG_ESAI_RX0:
  653. case REG_ESAI_RX1:
  654. case REG_ESAI_RX2:
  655. case REG_ESAI_RX3:
  656. case REG_ESAI_SAISR:
  657. return true;
  658. default:
  659. return false;
  660. }
  661. }
  662. static bool fsl_esai_writeable_reg(struct device *dev, unsigned int reg)
  663. {
  664. switch (reg) {
  665. case REG_ESAI_ETDR:
  666. case REG_ESAI_ECR:
  667. case REG_ESAI_TFCR:
  668. case REG_ESAI_RFCR:
  669. case REG_ESAI_TX0:
  670. case REG_ESAI_TX1:
  671. case REG_ESAI_TX2:
  672. case REG_ESAI_TX3:
  673. case REG_ESAI_TX4:
  674. case REG_ESAI_TX5:
  675. case REG_ESAI_TSR:
  676. case REG_ESAI_SAICR:
  677. case REG_ESAI_TCR:
  678. case REG_ESAI_TCCR:
  679. case REG_ESAI_RCR:
  680. case REG_ESAI_RCCR:
  681. case REG_ESAI_TSMA:
  682. case REG_ESAI_TSMB:
  683. case REG_ESAI_RSMA:
  684. case REG_ESAI_RSMB:
  685. case REG_ESAI_PRRC:
  686. case REG_ESAI_PCRC:
  687. return true;
  688. default:
  689. return false;
  690. }
  691. }
  692. static const struct regmap_config fsl_esai_regmap_config = {
  693. .reg_bits = 32,
  694. .reg_stride = 4,
  695. .val_bits = 32,
  696. .max_register = REG_ESAI_PCRC,
  697. .reg_defaults = fsl_esai_reg_defaults,
  698. .num_reg_defaults = ARRAY_SIZE(fsl_esai_reg_defaults),
  699. .readable_reg = fsl_esai_readable_reg,
  700. .volatile_reg = fsl_esai_volatile_reg,
  701. .writeable_reg = fsl_esai_writeable_reg,
  702. .cache_type = REGCACHE_FLAT,
  703. };
  704. static int fsl_esai_probe(struct platform_device *pdev)
  705. {
  706. struct device_node *np = pdev->dev.of_node;
  707. struct fsl_esai *esai_priv;
  708. struct resource *res;
  709. const __be32 *iprop;
  710. void __iomem *regs;
  711. int irq, ret;
  712. esai_priv = devm_kzalloc(&pdev->dev, sizeof(*esai_priv), GFP_KERNEL);
  713. if (!esai_priv)
  714. return -ENOMEM;
  715. esai_priv->pdev = pdev;
  716. strncpy(esai_priv->name, np->name, sizeof(esai_priv->name) - 1);
  717. /* Get the addresses and IRQ */
  718. res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  719. regs = devm_ioremap_resource(&pdev->dev, res);
  720. if (IS_ERR(regs))
  721. return PTR_ERR(regs);
  722. esai_priv->regmap = devm_regmap_init_mmio_clk(&pdev->dev,
  723. "core", regs, &fsl_esai_regmap_config);
  724. if (IS_ERR(esai_priv->regmap)) {
  725. dev_err(&pdev->dev, "failed to init regmap: %ld\n",
  726. PTR_ERR(esai_priv->regmap));
  727. return PTR_ERR(esai_priv->regmap);
  728. }
  729. esai_priv->coreclk = devm_clk_get(&pdev->dev, "core");
  730. if (IS_ERR(esai_priv->coreclk)) {
  731. dev_err(&pdev->dev, "failed to get core clock: %ld\n",
  732. PTR_ERR(esai_priv->coreclk));
  733. return PTR_ERR(esai_priv->coreclk);
  734. }
  735. esai_priv->extalclk = devm_clk_get(&pdev->dev, "extal");
  736. if (IS_ERR(esai_priv->extalclk))
  737. dev_warn(&pdev->dev, "failed to get extal clock: %ld\n",
  738. PTR_ERR(esai_priv->extalclk));
  739. esai_priv->fsysclk = devm_clk_get(&pdev->dev, "fsys");
  740. if (IS_ERR(esai_priv->fsysclk))
  741. dev_warn(&pdev->dev, "failed to get fsys clock: %ld\n",
  742. PTR_ERR(esai_priv->fsysclk));
  743. esai_priv->spbaclk = devm_clk_get(&pdev->dev, "spba");
  744. if (IS_ERR(esai_priv->spbaclk))
  745. dev_warn(&pdev->dev, "failed to get spba clock: %ld\n",
  746. PTR_ERR(esai_priv->spbaclk));
  747. irq = platform_get_irq(pdev, 0);
  748. if (irq < 0) {
  749. dev_err(&pdev->dev, "no irq for node %s\n", pdev->name);
  750. return irq;
  751. }
  752. ret = devm_request_irq(&pdev->dev, irq, esai_isr, 0,
  753. esai_priv->name, esai_priv);
  754. if (ret) {
  755. dev_err(&pdev->dev, "failed to claim irq %u\n", irq);
  756. return ret;
  757. }
  758. /* Set a default slot number */
  759. esai_priv->slots = 2;
  760. /* Set a default master/slave state */
  761. esai_priv->slave_mode = true;
  762. /* Determine the FIFO depth */
  763. iprop = of_get_property(np, "fsl,fifo-depth", NULL);
  764. if (iprop)
  765. esai_priv->fifo_depth = be32_to_cpup(iprop);
  766. else
  767. esai_priv->fifo_depth = 64;
  768. esai_priv->dma_params_tx.maxburst = 16;
  769. esai_priv->dma_params_rx.maxburst = 16;
  770. esai_priv->dma_params_tx.addr = res->start + REG_ESAI_ETDR;
  771. esai_priv->dma_params_rx.addr = res->start + REG_ESAI_ERDR;
  772. esai_priv->synchronous =
  773. of_property_read_bool(np, "fsl,esai-synchronous");
  774. /* Implement full symmetry for synchronous mode */
  775. if (esai_priv->synchronous) {
  776. fsl_esai_dai.symmetric_rates = 1;
  777. fsl_esai_dai.symmetric_channels = 1;
  778. fsl_esai_dai.symmetric_samplebits = 1;
  779. }
  780. dev_set_drvdata(&pdev->dev, esai_priv);
  781. /* Reset ESAI unit */
  782. ret = regmap_write(esai_priv->regmap, REG_ESAI_ECR, ESAI_ECR_ERST);
  783. if (ret) {
  784. dev_err(&pdev->dev, "failed to reset ESAI: %d\n", ret);
  785. return ret;
  786. }
  787. /*
  788. * We need to enable ESAI so as to access some of its registers.
  789. * Otherwise, we would fail to dump regmap from user space.
  790. */
  791. ret = regmap_write(esai_priv->regmap, REG_ESAI_ECR, ESAI_ECR_ESAIEN);
  792. if (ret) {
  793. dev_err(&pdev->dev, "failed to enable ESAI: %d\n", ret);
  794. return ret;
  795. }
  796. esai_priv->tx_mask = 0xFFFFFFFF;
  797. esai_priv->rx_mask = 0xFFFFFFFF;
  798. /* Clear the TSMA, TSMB, RSMA, RSMB */
  799. regmap_write(esai_priv->regmap, REG_ESAI_TSMA, 0);
  800. regmap_write(esai_priv->regmap, REG_ESAI_TSMB, 0);
  801. regmap_write(esai_priv->regmap, REG_ESAI_RSMA, 0);
  802. regmap_write(esai_priv->regmap, REG_ESAI_RSMB, 0);
  803. ret = devm_snd_soc_register_component(&pdev->dev, &fsl_esai_component,
  804. &fsl_esai_dai, 1);
  805. if (ret) {
  806. dev_err(&pdev->dev, "failed to register DAI: %d\n", ret);
  807. return ret;
  808. }
  809. ret = imx_pcm_dma_init(pdev, IMX_ESAI_DMABUF_SIZE);
  810. if (ret)
  811. dev_err(&pdev->dev, "failed to init imx pcm dma: %d\n", ret);
  812. return ret;
  813. }
  814. static const struct of_device_id fsl_esai_dt_ids[] = {
  815. { .compatible = "fsl,imx35-esai", },
  816. { .compatible = "fsl,vf610-esai", },
  817. {}
  818. };
  819. MODULE_DEVICE_TABLE(of, fsl_esai_dt_ids);
  820. #ifdef CONFIG_PM_SLEEP
  821. static int fsl_esai_suspend(struct device *dev)
  822. {
  823. struct fsl_esai *esai = dev_get_drvdata(dev);
  824. regcache_cache_only(esai->regmap, true);
  825. regcache_mark_dirty(esai->regmap);
  826. return 0;
  827. }
  828. static int fsl_esai_resume(struct device *dev)
  829. {
  830. struct fsl_esai *esai = dev_get_drvdata(dev);
  831. int ret;
  832. regcache_cache_only(esai->regmap, false);
  833. /* FIFO reset for safety */
  834. regmap_update_bits(esai->regmap, REG_ESAI_TFCR,
  835. ESAI_xFCR_xFR, ESAI_xFCR_xFR);
  836. regmap_update_bits(esai->regmap, REG_ESAI_RFCR,
  837. ESAI_xFCR_xFR, ESAI_xFCR_xFR);
  838. ret = regcache_sync(esai->regmap);
  839. if (ret)
  840. return ret;
  841. /* FIFO reset done */
  842. regmap_update_bits(esai->regmap, REG_ESAI_TFCR, ESAI_xFCR_xFR, 0);
  843. regmap_update_bits(esai->regmap, REG_ESAI_RFCR, ESAI_xFCR_xFR, 0);
  844. return 0;
  845. }
  846. #endif /* CONFIG_PM_SLEEP */
  847. static const struct dev_pm_ops fsl_esai_pm_ops = {
  848. SET_SYSTEM_SLEEP_PM_OPS(fsl_esai_suspend, fsl_esai_resume)
  849. };
  850. static struct platform_driver fsl_esai_driver = {
  851. .probe = fsl_esai_probe,
  852. .driver = {
  853. .name = "fsl-esai-dai",
  854. .pm = &fsl_esai_pm_ops,
  855. .of_match_table = fsl_esai_dt_ids,
  856. },
  857. };
  858. module_platform_driver(fsl_esai_driver);
  859. MODULE_AUTHOR("Freescale Semiconductor, Inc.");
  860. MODULE_DESCRIPTION("Freescale ESAI CPU DAI driver");
  861. MODULE_LICENSE("GPL v2");
  862. MODULE_ALIAS("platform:fsl-esai-dai");