]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
Merge branch 'davinci' into for-2.6.32
authorMark Brown <broonie@opensource.wolfsonmicro.com>
Tue, 7 Jul 2009 18:18:46 +0000 (19:18 +0100)
committerMark Brown <broonie@opensource.wolfsonmicro.com>
Tue, 7 Jul 2009 18:18:46 +0000 (19:18 +0100)
Conflicts:
sound/soc/davinci/davinci-i2s.c

1  2 
sound/soc/davinci/davinci-i2s.c

index 88ccef79a5ebe12a9e711edc8344833346af096c,2f11970e6406595af1b4f9de7b4857895f55e4ac..7c4839994e2f6d79cbb19c69c893313763ee8393
@@@ -63,7 -63,6 +63,7 @@@
  #define DAVINCI_MCBSP_RCR_RWDLEN1(v)  ((v) << 5)
  #define DAVINCI_MCBSP_RCR_RFRLEN1(v)  ((v) << 8)
  #define DAVINCI_MCBSP_RCR_RDATDLY(v)  ((v) << 16)
 +#define DAVINCI_MCBSP_RCR_RFIG                (1 << 18)
  #define DAVINCI_MCBSP_RCR_RWDLEN2(v)  ((v) << 21)
  
  #define DAVINCI_MCBSP_XCR_XWDLEN1(v)  ((v) << 5)
  #define DAVINCI_MCBSP_PCR_FSRM                (1 << 10)
  #define DAVINCI_MCBSP_PCR_FSXM                (1 << 11)
  
 -#define MOD_REG_BIT(val, mask, set) do { \
 -      if (set) { \
 -              val |= mask; \
 -      } else { \
 -              val &= ~mask; \
 -      } \
 -} while (0)
 -
  enum {
        DAVINCI_MCBSP_WORD_8 = 0,
        DAVINCI_MCBSP_WORD_12,
@@@ -105,10 -112,6 +105,10 @@@ static struct davinci_pcm_dma_params da
  
  struct davinci_mcbsp_dev {
        void __iomem                    *base;
 +#define MOD_DSP_A     0
 +#define MOD_DSP_B     1
 +      int                             mode;
 +      u32                             pcr;
        struct clk                      *clk;
        struct davinci_pcm_dma_params   *dma_params[2];
  };
@@@ -124,100 -127,96 +124,100 @@@ static inline u32 davinci_mcbsp_read_re
        return __raw_readl(dev->base + reg);
  }
  
 -static void davinci_mcbsp_start(struct snd_pcm_substream *substream)
 +static void toggle_clock(struct davinci_mcbsp_dev *dev, int playback)
 +{
 +      u32 m = playback ? DAVINCI_MCBSP_PCR_CLKXP : DAVINCI_MCBSP_PCR_CLKRP;
 +      /* The clock needs to toggle to complete reset.
 +       * So, fake it by toggling the clk polarity.
 +       */
 +      davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_PCR_REG, dev->pcr ^ m);
 +      davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_PCR_REG, dev->pcr);
 +}
 +
 +static void davinci_mcbsp_start(struct davinci_mcbsp_dev *dev,
 +              struct snd_pcm_substream *substream)
  {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
 -      struct davinci_mcbsp_dev *dev = rtd->dai->cpu_dai->private_data;
        struct snd_soc_device *socdev = rtd->socdev;
        struct snd_soc_platform *platform = socdev->card->platform;
 -      u32 w;
 -      int ret;
 -
 -      /* Start the sample generator and enable transmitter/receiver */
 -      w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
 -      MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_GRST, 1);
 -      davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w);
 +      int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
 +      u32 spcr;
 +      u32 mask = playback ? DAVINCI_MCBSP_SPCR_XRST : DAVINCI_MCBSP_SPCR_RRST;
 +      spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
 +      if (spcr & mask) {
 +              /* start off disabled */
 +              davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG,
 +                              spcr & ~mask);
 +              toggle_clock(dev, playback);
 +      }
 +      if (dev->pcr & (DAVINCI_MCBSP_PCR_FSXM | DAVINCI_MCBSP_PCR_FSRM |
 +                      DAVINCI_MCBSP_PCR_CLKXM | DAVINCI_MCBSP_PCR_CLKRM)) {
 +              /* Start the sample generator */
 +              spcr |= DAVINCI_MCBSP_SPCR_GRST;
 +              davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr);
 +      }
  
 -      if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
 +      if (playback) {
                /* Stop the DMA to avoid data loss */
                /* while the transmitter is out of reset to handle XSYNCERR */
                if (platform->pcm_ops->trigger) {
 -                      ret = platform->pcm_ops->trigger(substream,
 +                      int ret = platform->pcm_ops->trigger(substream,
                                SNDRV_PCM_TRIGGER_STOP);
                        if (ret < 0)
                                printk(KERN_DEBUG "Playback DMA stop failed\n");
                }
  
                /* Enable the transmitter */
 -              w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
 -              MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_XRST, 1);
 -              davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w);
 +              spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
 +              spcr |= DAVINCI_MCBSP_SPCR_XRST;
 +              davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr);
  
                /* wait for any unexpected frame sync error to occur */
                udelay(100);
  
                /* Disable the transmitter to clear any outstanding XSYNCERR */
 -              w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
 -              MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_XRST, 0);
 -              davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w);
 +              spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
 +              spcr &= ~DAVINCI_MCBSP_SPCR_XRST;
 +              davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr);
 +              toggle_clock(dev, playback);
  
                /* Restart the DMA */
                if (platform->pcm_ops->trigger) {
 -                      ret = platform->pcm_ops->trigger(substream,
 +                      int ret = platform->pcm_ops->trigger(substream,
                                SNDRV_PCM_TRIGGER_START);
                        if (ret < 0)
                                printk(KERN_DEBUG "Playback DMA start failed\n");
                }
 -              /* Enable the transmitter */
 -              w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
 -              MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_XRST, 1);
 -              davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w);
 -
 -      } else {
 -
 -              /* Enable the reciever */
 -              w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
 -              MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_RRST, 1);
 -              davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w);
        }
  
 +      /* Enable transmitter or receiver */
 +      spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
 +      spcr |= mask;
  
 -      /* Start frame sync */
 -      w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
 -      MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_FRST, 1);
 -      davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w);
 +      if (dev->pcr & (DAVINCI_MCBSP_PCR_FSXM | DAVINCI_MCBSP_PCR_FSRM)) {
 +              /* Start frame sync */
 +              spcr |= DAVINCI_MCBSP_SPCR_FRST;
 +      }
 +      davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr);
  }
  
 -static void davinci_mcbsp_stop(struct snd_pcm_substream *substream)
 +static void davinci_mcbsp_stop(struct davinci_mcbsp_dev *dev, int playback)
  {
 -      struct snd_soc_pcm_runtime *rtd = substream->private_data;
 -      struct davinci_mcbsp_dev *dev = rtd->dai->cpu_dai->private_data;
 -      u32 w;
 +      u32 spcr;
  
        /* Reset transmitter/receiver and sample rate/frame sync generators */
 -      w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
 -      MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_GRST |
 -                     DAVINCI_MCBSP_SPCR_FRST, 0);
 -      if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
 -              MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_XRST, 0);
 -      else
 -              MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_RRST, 0);
 -      davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w);
 +      spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
 +      spcr &= ~(DAVINCI_MCBSP_SPCR_GRST | DAVINCI_MCBSP_SPCR_FRST);
 +      spcr &= playback ? ~DAVINCI_MCBSP_SPCR_XRST : ~DAVINCI_MCBSP_SPCR_RRST;
 +      davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr);
 +      toggle_clock(dev, playback);
  }
  
  static int davinci_i2s_startup(struct snd_pcm_substream *substream,
 -                             struct snd_soc_dai *dai)
 +                             struct snd_soc_dai *cpu_dai)
  {
 -      struct snd_soc_pcm_runtime *rtd = substream->private_data;
 -      struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
 -      struct davinci_mcbsp_dev *dev = rtd->dai->cpu_dai->private_data;
 -
 +      struct davinci_mcbsp_dev *dev = cpu_dai->private_data;
        cpu_dai->dma_data = dev->dma_params[substream->stream];
 -
        return 0;
  }
  
@@@ -229,11 -228,12 +229,11 @@@ static int davinci_i2s_set_dai_fmt(stru
        struct davinci_mcbsp_dev *dev = cpu_dai->private_data;
        unsigned int pcr;
        unsigned int srgr;
 -      unsigned int rcr;
 -      unsigned int xcr;
        srgr = DAVINCI_MCBSP_SRGR_FSGM |
                DAVINCI_MCBSP_SRGR_FPER(DEFAULT_BITPERSAMPLE * 2 - 1) |
                DAVINCI_MCBSP_SRGR_FWID(DEFAULT_BITPERSAMPLE - 1);
  
 +      /* set master/slave audio interface */
        switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
        case SND_SOC_DAIFMT_CBS_CFS:
                /* cpu is master */
                return -EINVAL;
        }
  
 -      rcr = DAVINCI_MCBSP_RCR_RFRLEN1(1);
 -      xcr = DAVINCI_MCBSP_XCR_XFIG | DAVINCI_MCBSP_XCR_XFRLEN1(1);
 +      /* interface format */
        switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
 -      case SND_SOC_DAIFMT_DSP_B:
 -              break;
        case SND_SOC_DAIFMT_I2S:
                /* Davinci doesn't support TRUE I2S, but some codecs will have
                 * the left and right channels contiguous. This allows
                 */
                fmt ^= SND_SOC_DAIFMT_NB_IF;
        case SND_SOC_DAIFMT_DSP_A:
 -              rcr |= DAVINCI_MCBSP_RCR_RDATDLY(1);
 -              xcr |= DAVINCI_MCBSP_XCR_XDATDLY(1);
 +              dev->mode = MOD_DSP_A;
 +              break;
 +      case SND_SOC_DAIFMT_DSP_B:
 +              dev->mode = MOD_DSP_B;
                break;
        default:
                printk(KERN_ERR "%s:bad format\n", __func__);
                return -EINVAL;
        }
        davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SRGR_REG, srgr);
 +      dev->pcr = pcr;
        davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_PCR_REG, pcr);
 -      davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_RCR_REG, rcr);
 -      davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_XCR_REG, xcr);
        return 0;
  }
  
@@@ -356,36 -358,26 +356,36 @@@ static int davinci_i2s_hw_params(struc
        struct davinci_mcbsp_dev *dev = rtd->dai->cpu_dai->private_data;
        struct snd_interval *i = NULL;
        int mcbsp_word_length;
 -      u32 w;
 +      unsigned int rcr, xcr, srgr;
 +      u32 spcr;
  
        /* general line settings */
 -      w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
 +      spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
        if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
 -              w |= DAVINCI_MCBSP_SPCR_RINTM(3) | DAVINCI_MCBSP_SPCR_FREE;
 -              davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w);
 +              spcr |= DAVINCI_MCBSP_SPCR_RINTM(3) | DAVINCI_MCBSP_SPCR_FREE;
 +              davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr);
        } else {
 -              w |= DAVINCI_MCBSP_SPCR_XINTM(3) | DAVINCI_MCBSP_SPCR_FREE;
 -              davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w);
 +              spcr |= DAVINCI_MCBSP_SPCR_XINTM(3) | DAVINCI_MCBSP_SPCR_FREE;
 +              davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr);
        }
  
        i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS);
 -      w = DAVINCI_MCBSP_SRGR_FSGM;
 -      MOD_REG_BIT(w, DAVINCI_MCBSP_SRGR_FWID(snd_interval_value(i) - 1), 1);
 +      srgr = DAVINCI_MCBSP_SRGR_FSGM;
 +      srgr |= DAVINCI_MCBSP_SRGR_FWID(snd_interval_value(i) - 1);
  
        i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_FRAME_BITS);
 -      MOD_REG_BIT(w, DAVINCI_MCBSP_SRGR_FPER(snd_interval_value(i) - 1), 1);
 -      davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SRGR_REG, w);
 +      srgr |= DAVINCI_MCBSP_SRGR_FPER(snd_interval_value(i) - 1);
 +      davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SRGR_REG, srgr);
  
 +      rcr = DAVINCI_MCBSP_RCR_RFIG;
 +      xcr = DAVINCI_MCBSP_XCR_XFIG;
 +      if (dev->mode == MOD_DSP_B) {
 +              rcr |= DAVINCI_MCBSP_RCR_RDATDLY(0);
 +              xcr |= DAVINCI_MCBSP_XCR_XDATDLY(0);
 +      } else {
 +              rcr |= DAVINCI_MCBSP_RCR_RDATDLY(1);
 +              xcr |= DAVINCI_MCBSP_XCR_XDATDLY(1);
 +      }
        /* Determine xfer data type */
        switch (params_format(params)) {
        case SNDRV_PCM_FORMAT_S8:
                return -EINVAL;
        }
  
 -      if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
 -              w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_RCR_REG);
 -              MOD_REG_BIT(w, DAVINCI_MCBSP_RCR_RWDLEN1(mcbsp_word_length) |
 -                             DAVINCI_MCBSP_RCR_RWDLEN2(mcbsp_word_length), 1);
 -              davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_RCR_REG, w);
 +      rcr |= DAVINCI_MCBSP_RCR_RFRLEN1(1);
 +      xcr |= DAVINCI_MCBSP_XCR_XFRLEN1(1);
  
 -      } else {
 -              w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_XCR_REG);
 -              MOD_REG_BIT(w, DAVINCI_MCBSP_XCR_XWDLEN1(mcbsp_word_length) |
 -                             DAVINCI_MCBSP_XCR_XWDLEN2(mcbsp_word_length), 1);
 -              davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_XCR_REG, w);
 +      rcr |= DAVINCI_MCBSP_RCR_RWDLEN1(mcbsp_word_length) |
 +              DAVINCI_MCBSP_RCR_RWDLEN2(mcbsp_word_length);
 +      xcr |= DAVINCI_MCBSP_XCR_XWDLEN1(mcbsp_word_length) |
 +              DAVINCI_MCBSP_XCR_XWDLEN2(mcbsp_word_length);
 +
 +      if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
 +              davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_XCR_REG, xcr);
 +      else
 +              davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_RCR_REG, rcr);
 +      return 0;
 +}
  
 +static int davinci_i2s_prepare(struct snd_pcm_substream *substream,
 +              struct snd_soc_dai *dai)
 +{
 +      struct snd_soc_pcm_runtime *rtd = substream->private_data;
 +      struct davinci_mcbsp_dev *dev = rtd->dai->cpu_dai->private_data;
 +      int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
 +      davinci_mcbsp_stop(dev, playback);
 +      if ((dev->pcr & DAVINCI_MCBSP_PCR_FSXM) == 0) {
 +              /* codec is master */
 +              davinci_mcbsp_start(dev, substream);
        }
        return 0;
  }
  static int davinci_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
                               struct snd_soc_dai *dai)
  {
 +      struct snd_soc_pcm_runtime *rtd = substream->private_data;
 +      struct davinci_mcbsp_dev *dev = rtd->dai->cpu_dai->private_data;
        int ret = 0;
 +      int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
 +      if ((dev->pcr & DAVINCI_MCBSP_PCR_FSXM) == 0)
 +              return 0;       /* return if codec is master */
  
        switch (cmd) {
        case SNDRV_PCM_TRIGGER_START:
        case SNDRV_PCM_TRIGGER_RESUME:
        case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
 -              davinci_mcbsp_start(substream);
 +              davinci_mcbsp_start(dev, substream);
                break;
        case SNDRV_PCM_TRIGGER_STOP:
        case SNDRV_PCM_TRIGGER_SUSPEND:
        case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
 -              davinci_mcbsp_stop(substream);
 +              davinci_mcbsp_stop(dev, playback);
                break;
        default:
                ret = -EINVAL;
        }
 -
        return ret;
  }
  
- static int davinci_i2s_probe(struct platform_device *pdev,
-                            struct snd_soc_dai *dai)
 +static void davinci_i2s_shutdown(struct snd_pcm_substream *substream,
 +              struct snd_soc_dai *dai)
 +{
 +      struct snd_soc_pcm_runtime *rtd = substream->private_data;
 +      struct davinci_mcbsp_dev *dev = rtd->dai->cpu_dai->private_data;
 +      int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
 +      davinci_mcbsp_stop(dev, playback);
 +}
 +
+ #define DAVINCI_I2S_RATES     SNDRV_PCM_RATE_8000_96000
+ static struct snd_soc_dai_ops davinci_i2s_dai_ops = {
+       .startup        = davinci_i2s_startup,
++      .shutdown       = davinci_i2s_shutdown,
++      .prepare        = davinci_i2s_prepare,
+       .trigger        = davinci_i2s_trigger,
+       .hw_params      = davinci_i2s_hw_params,
+       .set_fmt        = davinci_i2s_set_dai_fmt,
+ };
+ struct snd_soc_dai davinci_i2s_dai = {
+       .name = "davinci-i2s",
+       .id = 0,
+       .playback = {
+               .channels_min = 2,
+               .channels_max = 2,
+               .rates = DAVINCI_I2S_RATES,
+               .formats = SNDRV_PCM_FMTBIT_S16_LE,},
+       .capture = {
+               .channels_min = 2,
+               .channels_max = 2,
+               .rates = DAVINCI_I2S_RATES,
+               .formats = SNDRV_PCM_FMTBIT_S16_LE,},
+       .ops = &davinci_i2s_dai_ops,
+ };
+ EXPORT_SYMBOL_GPL(davinci_i2s_dai);
+ static int davinci_i2s_probe(struct platform_device *pdev)
  {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_card *card = socdev->card;
-       struct snd_soc_dai *cpu_dai = card->dai_link->cpu_dai;
+       struct snd_platform_data *pdata = pdev->dev.platform_data;
        struct davinci_mcbsp_dev *dev;
-       struct resource *mem, *ioarea;
-       struct evm_snd_platform_data *pdata;
+       struct resource *mem, *ioarea, *res;
        int ret;
  
        mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
                goto err_release_region;
        }
  
-       cpu_dai->private_data = dev;
-       dev->clk = clk_get(&pdev->dev, NULL);
+       dev->clk = clk_get(&pdev->dev, pdata->clk_name);
        if (IS_ERR(dev->clk)) {
                ret = -ENODEV;
                goto err_free_mem;
        clk_enable(dev->clk);
  
        dev->base = (void __iomem *)IO_ADDRESS(mem->start);
-       pdata = pdev->dev.platform_data;
  
        dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK] = &davinci_i2s_pcm_out;
-       dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK]->channel = pdata->tx_dma_ch;
        dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK]->dma_addr =
            (dma_addr_t)(io_v2p(dev->base) + DAVINCI_MCBSP_DXR_REG);
  
        dev->dma_params[SNDRV_PCM_STREAM_CAPTURE] = &davinci_i2s_pcm_in;
-       dev->dma_params[SNDRV_PCM_STREAM_CAPTURE]->channel = pdata->rx_dma_ch;
        dev->dma_params[SNDRV_PCM_STREAM_CAPTURE]->dma_addr =
            (dma_addr_t)(io_v2p(dev->base) + DAVINCI_MCBSP_DRR_REG);
  
+       /* first TX, then RX */
+       res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
+       if (!res) {
+               dev_err(&pdev->dev, "no DMA resource\n");
+               ret = -ENXIO;
+               goto err_free_mem;
+       }
+       dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK]->channel = res->start;
+       res = platform_get_resource(pdev, IORESOURCE_DMA, 1);
+       if (!res) {
+               dev_err(&pdev->dev, "no DMA resource\n");
+               ret = -ENXIO;
+               goto err_free_mem;
+       }
+       dev->dma_params[SNDRV_PCM_STREAM_CAPTURE]->channel = res->start;
+       davinci_i2s_dai.private_data = dev;
+       ret = snd_soc_register_dai(&davinci_i2s_dai);
+       if (ret != 0)
+               goto err_free_mem;
        return 0;
  
  err_free_mem:
@@@ -532,64 -539,40 +575,40 @@@ err_release_region
        return ret;
  }
  
- static void davinci_i2s_remove(struct platform_device *pdev,
-                              struct snd_soc_dai *dai)
+ static int davinci_i2s_remove(struct platform_device *pdev)
  {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_card *card = socdev->card;
-       struct snd_soc_dai *cpu_dai = card->dai_link->cpu_dai;
-       struct davinci_mcbsp_dev *dev = cpu_dai->private_data;
+       struct davinci_mcbsp_dev *dev = davinci_i2s_dai.private_data;
        struct resource *mem;
  
+       snd_soc_unregister_dai(&davinci_i2s_dai);
        clk_disable(dev->clk);
        clk_put(dev->clk);
        dev->clk = NULL;
        kfree(dev);
        mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        release_mem_region(mem->start, (mem->end - mem->start) + 1);
- }
- #define DAVINCI_I2S_RATES     SNDRV_PCM_RATE_8000_96000
  
- static struct snd_soc_dai_ops davinci_i2s_dai_ops = {
-       .startup        = davinci_i2s_startup,
-       .shutdown       = davinci_i2s_shutdown,
-       .prepare        = davinci_i2s_prepare,
-       .trigger        = davinci_i2s_trigger,
-       .hw_params      = davinci_i2s_hw_params,
-       .set_fmt        = davinci_i2s_set_dai_fmt,
- };
+       return 0;
+ }
  
- struct snd_soc_dai davinci_i2s_dai = {
-       .name = "davinci-i2s",
-       .id = 0,
-       .probe = davinci_i2s_probe,
-       .remove = davinci_i2s_remove,
-       .playback = {
-               .channels_min = 2,
-               .channels_max = 2,
-               .rates = DAVINCI_I2S_RATES,
-               .formats = SNDRV_PCM_FMTBIT_S16_LE,},
-       .capture = {
-               .channels_min = 2,
-               .channels_max = 2,
-               .rates = DAVINCI_I2S_RATES,
-               .formats = SNDRV_PCM_FMTBIT_S16_LE,},
-       .ops = &davinci_i2s_dai_ops,
+ static struct platform_driver davinci_mcbsp_driver = {
+       .probe          = davinci_i2s_probe,
+       .remove         = davinci_i2s_remove,
+       .driver         = {
+               .name   = "davinci-asp",
+               .owner  = THIS_MODULE,
+       },
  };
- EXPORT_SYMBOL_GPL(davinci_i2s_dai);
  
  static int __init davinci_i2s_init(void)
  {
-       return snd_soc_register_dai(&davinci_i2s_dai);
+       return platform_driver_register(&davinci_mcbsp_driver);
  }
  module_init(davinci_i2s_init);
  
  static void __exit davinci_i2s_exit(void)
  {
-       snd_soc_unregister_dai(&davinci_i2s_dai);
+       platform_driver_unregister(&davinci_mcbsp_driver);
  }
  module_exit(davinci_i2s_exit);