fsl_esai.c 32 KB

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