root/sound/soc/fsl/fsl_esai.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. esai_isr
  2. fsl_esai_divisor_cal
  3. fsl_esai_set_dai_sysclk
  4. fsl_esai_set_bclk
  5. fsl_esai_set_dai_tdm_slot
  6. fsl_esai_set_dai_fmt
  7. fsl_esai_startup
  8. fsl_esai_hw_params
  9. fsl_esai_hw_init
  10. fsl_esai_register_restore
  11. fsl_esai_trigger_start
  12. fsl_esai_trigger_stop
  13. fsl_esai_hw_reset
  14. fsl_esai_trigger
  15. fsl_esai_dai_probe
  16. fsl_esai_readable_reg
  17. fsl_esai_volatile_reg
  18. fsl_esai_writeable_reg
  19. fsl_esai_probe
  20. fsl_esai_remove
  21. fsl_esai_runtime_resume
  22. fsl_esai_runtime_suspend

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

/* [<][>][^][v][top][bottom][index][help] */