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