linux/sound/soc/pxa/pxa2xx-i2s.c
<<
>>
Prefs
   1/*
   2 * pxa2xx-i2s.c  --  ALSA Soc Audio Layer
   3 *
   4 * Copyright 2005 Wolfson Microelectronics PLC.
   5 * Author: Liam Girdwood
   6 *         lrg@slimlogic.co.uk
   7 *
   8 *  This program is free software; you can redistribute  it and/or modify it
   9 *  under  the terms of  the GNU General  Public License as published by the
  10 *  Free Software Foundation;  either version 2 of the  License, or (at your
  11 *  option) any later version.
  12 */
  13
  14#include <linux/init.h>
  15#include <linux/module.h>
  16#include <linux/device.h>
  17#include <linux/delay.h>
  18#include <linux/clk.h>
  19#include <linux/platform_device.h>
  20#include <sound/core.h>
  21#include <sound/pcm.h>
  22#include <sound/initval.h>
  23#include <sound/soc.h>
  24#include <sound/pxa2xx-lib.h>
  25
  26#include <mach/hardware.h>
  27#include <mach/dma.h>
  28#include <mach/audio.h>
  29
  30#include "pxa2xx-i2s.h"
  31
  32/*
  33 * I2S Controller Register and Bit Definitions
  34 */
  35#define SACR0           __REG(0x40400000)  /* Global Control Register */
  36#define SACR1           __REG(0x40400004)  /* Serial Audio I 2 S/MSB-Justified Control Register */
  37#define SASR0           __REG(0x4040000C)  /* Serial Audio I 2 S/MSB-Justified Interface and FIFO Status Register */
  38#define SAIMR           __REG(0x40400014)  /* Serial Audio Interrupt Mask Register */
  39#define SAICR           __REG(0x40400018)  /* Serial Audio Interrupt Clear Register */
  40#define SADIV           __REG(0x40400060)  /* Audio Clock Divider Register. */
  41#define SADR            __REG(0x40400080)  /* Serial Audio Data Register (TX and RX FIFO access Register). */
  42
  43#define SACR0_RFTH(x)   ((x) << 12)     /* Rx FIFO Interrupt or DMA Trigger Threshold */
  44#define SACR0_TFTH(x)   ((x) << 8)      /* Tx FIFO Interrupt or DMA Trigger Threshold */
  45#define SACR0_STRF      (1 << 5)        /* FIFO Select for EFWR Special Function */
  46#define SACR0_EFWR      (1 << 4)        /* Enable EFWR Function  */
  47#define SACR0_RST       (1 << 3)        /* FIFO, i2s Register Reset */
  48#define SACR0_BCKD      (1 << 2)        /* Bit Clock Direction */
  49#define SACR0_ENB       (1 << 0)        /* Enable I2S Link */
  50#define SACR1_ENLBF     (1 << 5)        /* Enable Loopback */
  51#define SACR1_DRPL      (1 << 4)        /* Disable Replaying Function */
  52#define SACR1_DREC      (1 << 3)        /* Disable Recording Function */
  53#define SACR1_AMSL      (1 << 0)        /* Specify Alternate Mode */
  54
  55#define SASR0_I2SOFF    (1 << 7)        /* Controller Status */
  56#define SASR0_ROR       (1 << 6)        /* Rx FIFO Overrun */
  57#define SASR0_TUR       (1 << 5)        /* Tx FIFO Underrun */
  58#define SASR0_RFS       (1 << 4)        /* Rx FIFO Service Request */
  59#define SASR0_TFS       (1 << 3)        /* Tx FIFO Service Request */
  60#define SASR0_BSY       (1 << 2)        /* I2S Busy */
  61#define SASR0_RNE       (1 << 1)        /* Rx FIFO Not Empty */
  62#define SASR0_TNF       (1 << 0)        /* Tx FIFO Not Empty */
  63
  64#define SAICR_ROR       (1 << 6)        /* Clear Rx FIFO Overrun Interrupt */
  65#define SAICR_TUR       (1 << 5)        /* Clear Tx FIFO Underrun Interrupt */
  66
  67#define SAIMR_ROR       (1 << 6)        /* Enable Rx FIFO Overrun Condition Interrupt */
  68#define SAIMR_TUR       (1 << 5)        /* Enable Tx FIFO Underrun Condition Interrupt */
  69#define SAIMR_RFS       (1 << 4)        /* Enable Rx FIFO Service Interrupt */
  70#define SAIMR_TFS       (1 << 3)        /* Enable Tx FIFO Service Interrupt */
  71
  72struct pxa_i2s_port {
  73        u32 sadiv;
  74        u32 sacr0;
  75        u32 sacr1;
  76        u32 saimr;
  77        int master;
  78        u32 fmt;
  79};
  80static struct pxa_i2s_port pxa_i2s;
  81static struct clk *clk_i2s;
  82static int clk_ena = 0;
  83
  84static struct pxa2xx_pcm_dma_params pxa2xx_i2s_pcm_stereo_out = {
  85        .name                   = "I2S PCM Stereo out",
  86        .dev_addr               = __PREG(SADR),
  87        .drcmr                  = &DRCMR(3),
  88        .dcmd                   = DCMD_INCSRCADDR | DCMD_FLOWTRG |
  89                                  DCMD_BURST32 | DCMD_WIDTH4,
  90};
  91
  92static struct pxa2xx_pcm_dma_params pxa2xx_i2s_pcm_stereo_in = {
  93        .name                   = "I2S PCM Stereo in",
  94        .dev_addr               = __PREG(SADR),
  95        .drcmr                  = &DRCMR(2),
  96        .dcmd                   = DCMD_INCTRGADDR | DCMD_FLOWSRC |
  97                                  DCMD_BURST32 | DCMD_WIDTH4,
  98};
  99
 100static int pxa2xx_i2s_startup(struct snd_pcm_substream *substream,
 101                              struct snd_soc_dai *dai)
 102{
 103        struct snd_soc_pcm_runtime *rtd = substream->private_data;
 104        struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
 105
 106        if (IS_ERR(clk_i2s))
 107                return PTR_ERR(clk_i2s);
 108
 109        if (!cpu_dai->active)
 110                SACR0 = 0;
 111
 112        return 0;
 113}
 114
 115/* wait for I2S controller to be ready */
 116static int pxa_i2s_wait(void)
 117{
 118        int i;
 119
 120        /* flush the Rx FIFO */
 121        for(i = 0; i < 16; i++)
 122                SADR;
 123        return 0;
 124}
 125
 126static int pxa2xx_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,
 127                unsigned int fmt)
 128{
 129        /* interface format */
 130        switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
 131        case SND_SOC_DAIFMT_I2S:
 132                pxa_i2s.fmt = 0;
 133                break;
 134        case SND_SOC_DAIFMT_LEFT_J:
 135                pxa_i2s.fmt = SACR1_AMSL;
 136                break;
 137        }
 138
 139        switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
 140        case SND_SOC_DAIFMT_CBS_CFS:
 141                pxa_i2s.master = 1;
 142                break;
 143        case SND_SOC_DAIFMT_CBM_CFS:
 144                pxa_i2s.master = 0;
 145                break;
 146        default:
 147                break;
 148        }
 149        return 0;
 150}
 151
 152static int pxa2xx_i2s_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
 153                int clk_id, unsigned int freq, int dir)
 154{
 155        if (clk_id != PXA2XX_I2S_SYSCLK)
 156                return -ENODEV;
 157
 158        return 0;
 159}
 160
 161static int pxa2xx_i2s_hw_params(struct snd_pcm_substream *substream,
 162                                struct snd_pcm_hw_params *params,
 163                                struct snd_soc_dai *dai)
 164{
 165        struct pxa2xx_pcm_dma_params *dma_data;
 166
 167        BUG_ON(IS_ERR(clk_i2s));
 168        clk_enable(clk_i2s);
 169        clk_ena = 1;
 170        pxa_i2s_wait();
 171
 172        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
 173                dma_data = &pxa2xx_i2s_pcm_stereo_out;
 174        else
 175                dma_data = &pxa2xx_i2s_pcm_stereo_in;
 176
 177        snd_soc_dai_set_dma_data(dai, substream, dma_data);
 178
 179        /* is port used by another stream */
 180        if (!(SACR0 & SACR0_ENB)) {
 181                SACR0 = 0;
 182                if (pxa_i2s.master)
 183                        SACR0 |= SACR0_BCKD;
 184
 185                SACR0 |= SACR0_RFTH(14) | SACR0_TFTH(1);
 186                SACR1 |= pxa_i2s.fmt;
 187        }
 188        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
 189                SAIMR |= SAIMR_TFS;
 190        else
 191                SAIMR |= SAIMR_RFS;
 192
 193        switch (params_rate(params)) {
 194        case 8000:
 195                SADIV = 0x48;
 196                break;
 197        case 11025:
 198                SADIV = 0x34;
 199                break;
 200        case 16000:
 201                SADIV = 0x24;
 202                break;
 203        case 22050:
 204                SADIV = 0x1a;
 205                break;
 206        case 44100:
 207                SADIV = 0xd;
 208                break;
 209        case 48000:
 210                SADIV = 0xc;
 211                break;
 212        case 96000: /* not in manual and possibly slightly inaccurate */
 213                SADIV = 0x6;
 214                break;
 215        }
 216
 217        return 0;
 218}
 219
 220static int pxa2xx_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
 221                              struct snd_soc_dai *dai)
 222{
 223        int ret = 0;
 224
 225        switch (cmd) {
 226        case SNDRV_PCM_TRIGGER_START:
 227                if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
 228                        SACR1 &= ~SACR1_DRPL;
 229                else
 230                        SACR1 &= ~SACR1_DREC;
 231                SACR0 |= SACR0_ENB;
 232                break;
 233        case SNDRV_PCM_TRIGGER_RESUME:
 234        case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
 235        case SNDRV_PCM_TRIGGER_STOP:
 236        case SNDRV_PCM_TRIGGER_SUSPEND:
 237        case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
 238                break;
 239        default:
 240                ret = -EINVAL;
 241        }
 242
 243        return ret;
 244}
 245
 246static void pxa2xx_i2s_shutdown(struct snd_pcm_substream *substream,
 247                                struct snd_soc_dai *dai)
 248{
 249        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
 250                SACR1 |= SACR1_DRPL;
 251                SAIMR &= ~SAIMR_TFS;
 252        } else {
 253                SACR1 |= SACR1_DREC;
 254                SAIMR &= ~SAIMR_RFS;
 255        }
 256
 257        if ((SACR1 & (SACR1_DREC | SACR1_DRPL)) == (SACR1_DREC | SACR1_DRPL)) {
 258                SACR0 &= ~SACR0_ENB;
 259                pxa_i2s_wait();
 260                if (clk_ena) {
 261                        clk_disable(clk_i2s);
 262                        clk_ena = 0;
 263                }
 264        }
 265}
 266
 267#ifdef CONFIG_PM
 268static int pxa2xx_i2s_suspend(struct snd_soc_dai *dai)
 269{
 270        /* store registers */
 271        pxa_i2s.sacr0 = SACR0;
 272        pxa_i2s.sacr1 = SACR1;
 273        pxa_i2s.saimr = SAIMR;
 274        pxa_i2s.sadiv = SADIV;
 275
 276        /* deactivate link */
 277        SACR0 &= ~SACR0_ENB;
 278        pxa_i2s_wait();
 279        return 0;
 280}
 281
 282static int pxa2xx_i2s_resume(struct snd_soc_dai *dai)
 283{
 284        pxa_i2s_wait();
 285
 286        SACR0 = pxa_i2s.sacr0 & ~SACR0_ENB;
 287        SACR1 = pxa_i2s.sacr1;
 288        SAIMR = pxa_i2s.saimr;
 289        SADIV = pxa_i2s.sadiv;
 290
 291        SACR0 = pxa_i2s.sacr0;
 292
 293        return 0;
 294}
 295
 296#else
 297#define pxa2xx_i2s_suspend      NULL
 298#define pxa2xx_i2s_resume       NULL
 299#endif
 300
 301static int pxa2xx_i2s_probe(struct snd_soc_dai *dai)
 302{
 303        clk_i2s = clk_get(dai->dev, "I2SCLK");
 304        if (IS_ERR(clk_i2s))
 305                return PTR_ERR(clk_i2s);
 306
 307        /*
 308         * PXA Developer's Manual:
 309         * If SACR0[ENB] is toggled in the middle of a normal operation,
 310         * the SACR0[RST] bit must also be set and cleared to reset all
 311         * I2S controller registers.
 312         */
 313        SACR0 = SACR0_RST;
 314        SACR0 = 0;
 315        /* Make sure RPL and REC are disabled */
 316        SACR1 = SACR1_DRPL | SACR1_DREC;
 317        /* Along with FIFO servicing */
 318        SAIMR &= ~(SAIMR_RFS | SAIMR_TFS);
 319
 320        return 0;
 321}
 322
 323static int  pxa2xx_i2s_remove(struct snd_soc_dai *dai)
 324{
 325        clk_put(clk_i2s);
 326        clk_i2s = ERR_PTR(-ENOENT);
 327        return 0;
 328}
 329
 330#define PXA2XX_I2S_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
 331                SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 | \
 332                SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000)
 333
 334static struct snd_soc_dai_ops pxa_i2s_dai_ops = {
 335        .startup        = pxa2xx_i2s_startup,
 336        .shutdown       = pxa2xx_i2s_shutdown,
 337        .trigger        = pxa2xx_i2s_trigger,
 338        .hw_params      = pxa2xx_i2s_hw_params,
 339        .set_fmt        = pxa2xx_i2s_set_dai_fmt,
 340        .set_sysclk     = pxa2xx_i2s_set_dai_sysclk,
 341};
 342
 343static struct snd_soc_dai_driver pxa_i2s_dai = {
 344        .probe = pxa2xx_i2s_probe,
 345        .remove = pxa2xx_i2s_remove,
 346        .suspend = pxa2xx_i2s_suspend,
 347        .resume = pxa2xx_i2s_resume,
 348        .playback = {
 349                .channels_min = 2,
 350                .channels_max = 2,
 351                .rates = PXA2XX_I2S_RATES,
 352                .formats = SNDRV_PCM_FMTBIT_S16_LE,},
 353        .capture = {
 354                .channels_min = 2,
 355                .channels_max = 2,
 356                .rates = PXA2XX_I2S_RATES,
 357                .formats = SNDRV_PCM_FMTBIT_S16_LE,},
 358        .ops = &pxa_i2s_dai_ops,
 359        .symmetric_rates = 1,
 360};
 361
 362static int pxa2xx_i2s_drv_probe(struct platform_device *pdev)
 363{
 364        return snd_soc_register_dai(&pdev->dev, &pxa_i2s_dai);
 365}
 366
 367static int __devexit pxa2xx_i2s_drv_remove(struct platform_device *pdev)
 368{
 369        snd_soc_unregister_dai(&pdev->dev);
 370        return 0;
 371}
 372
 373static struct platform_driver pxa2xx_i2s_driver = {
 374        .probe = pxa2xx_i2s_drv_probe,
 375        .remove = __devexit_p(pxa2xx_i2s_drv_remove),
 376
 377        .driver = {
 378                .name = "pxa2xx-i2s",
 379                .owner = THIS_MODULE,
 380        },
 381};
 382
 383static int __init pxa2xx_i2s_init(void)
 384{
 385        clk_i2s = ERR_PTR(-ENOENT);
 386        return platform_driver_register(&pxa2xx_i2s_driver);
 387}
 388
 389static void __exit pxa2xx_i2s_exit(void)
 390{
 391        platform_driver_unregister(&pxa2xx_i2s_driver);
 392}
 393
 394module_init(pxa2xx_i2s_init);
 395module_exit(pxa2xx_i2s_exit);
 396
 397/* Module information */
 398MODULE_AUTHOR("Liam Girdwood, lrg@slimlogic.co.uk");
 399MODULE_DESCRIPTION("pxa2xx I2S SoC Interface");
 400MODULE_LICENSE("GPL");
 401MODULE_ALIAS("platform:pxa2xx-i2s");
 402