Guest User

fsl_esai_updated.c

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