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