linux/sound/soc/pxa/pxa2xx-ac97.c
<<
>>
Prefs
   1/*
   2 * linux/sound/pxa2xx-ac97.c -- AC97 support for the Intel PXA2xx chip.
   3 *
   4 * Author:      Nicolas Pitre
   5 * Created:     Dec 02, 2004
   6 * Copyright:   MontaVista Software Inc.
   7 *
   8 * This program is free software; you can redistribute it and/or modify
   9 * it under the terms of the GNU General Public License version 2 as
  10 * published by the Free Software Foundation.
  11 */
  12
  13#include <linux/init.h>
  14#include <linux/module.h>
  15#include <linux/platform_device.h>
  16
  17#include <sound/core.h>
  18#include <sound/ac97_codec.h>
  19#include <sound/soc.h>
  20#include <sound/pxa2xx-lib.h>
  21
  22#include <mach/hardware.h>
  23#include <mach/pxa-regs.h>
  24#include <mach/regs-ac97.h>
  25
  26#include "pxa2xx-pcm.h"
  27#include "pxa2xx-ac97.h"
  28
  29static void pxa2xx_ac97_warm_reset(struct snd_ac97 *ac97)
  30{
  31        pxa2xx_ac97_try_warm_reset(ac97);
  32
  33        pxa2xx_ac97_finish_reset(ac97);
  34}
  35
  36static void pxa2xx_ac97_cold_reset(struct snd_ac97 *ac97)
  37{
  38        pxa2xx_ac97_try_cold_reset(ac97);
  39
  40        pxa2xx_ac97_finish_reset(ac97);
  41}
  42
  43struct snd_ac97_bus_ops soc_ac97_ops = {
  44        .read   = pxa2xx_ac97_read,
  45        .write  = pxa2xx_ac97_write,
  46        .warm_reset     = pxa2xx_ac97_warm_reset,
  47        .reset  = pxa2xx_ac97_cold_reset,
  48};
  49
  50static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_stereo_out = {
  51        .name                   = "AC97 PCM Stereo out",
  52        .dev_addr               = __PREG(PCDR),
  53        .drcmr                  = &DRCMR(12),
  54        .dcmd                   = DCMD_INCSRCADDR | DCMD_FLOWTRG |
  55                                  DCMD_BURST32 | DCMD_WIDTH4,
  56};
  57
  58static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_stereo_in = {
  59        .name                   = "AC97 PCM Stereo in",
  60        .dev_addr               = __PREG(PCDR),
  61        .drcmr                  = &DRCMR(11),
  62        .dcmd                   = DCMD_INCTRGADDR | DCMD_FLOWSRC |
  63                                  DCMD_BURST32 | DCMD_WIDTH4,
  64};
  65
  66static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_aux_mono_out = {
  67        .name                   = "AC97 Aux PCM (Slot 5) Mono out",
  68        .dev_addr               = __PREG(MODR),
  69        .drcmr                  = &DRCMR(10),
  70        .dcmd                   = DCMD_INCSRCADDR | DCMD_FLOWTRG |
  71                                  DCMD_BURST16 | DCMD_WIDTH2,
  72};
  73
  74static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_aux_mono_in = {
  75        .name                   = "AC97 Aux PCM (Slot 5) Mono in",
  76        .dev_addr               = __PREG(MODR),
  77        .drcmr                  = &DRCMR(9),
  78        .dcmd                   = DCMD_INCTRGADDR | DCMD_FLOWSRC |
  79                                  DCMD_BURST16 | DCMD_WIDTH2,
  80};
  81
  82static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_mic_mono_in = {
  83        .name                   = "AC97 Mic PCM (Slot 6) Mono in",
  84        .dev_addr               = __PREG(MCDR),
  85        .drcmr                  = &DRCMR(8),
  86        .dcmd                   = DCMD_INCTRGADDR | DCMD_FLOWSRC |
  87                                  DCMD_BURST16 | DCMD_WIDTH2,
  88};
  89
  90#ifdef CONFIG_PM
  91static int pxa2xx_ac97_suspend(struct snd_soc_dai *dai)
  92{
  93        return pxa2xx_ac97_hw_suspend();
  94}
  95
  96static int pxa2xx_ac97_resume(struct snd_soc_dai *dai)
  97{
  98        return pxa2xx_ac97_hw_resume();
  99}
 100
 101#else
 102#define pxa2xx_ac97_suspend     NULL
 103#define pxa2xx_ac97_resume      NULL
 104#endif
 105
 106static int pxa2xx_ac97_probe(struct platform_device *pdev,
 107                             struct snd_soc_dai *dai)
 108{
 109        return pxa2xx_ac97_hw_probe(pdev);
 110}
 111
 112static void pxa2xx_ac97_remove(struct platform_device *pdev,
 113                               struct snd_soc_dai *dai)
 114{
 115        pxa2xx_ac97_hw_remove(pdev);
 116}
 117
 118static int pxa2xx_ac97_hw_params(struct snd_pcm_substream *substream,
 119                                 struct snd_pcm_hw_params *params,
 120                                 struct snd_soc_dai *dai)
 121{
 122        struct snd_soc_pcm_runtime *rtd = substream->private_data;
 123        struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
 124
 125        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
 126                cpu_dai->dma_data = &pxa2xx_ac97_pcm_stereo_out;
 127        else
 128                cpu_dai->dma_data = &pxa2xx_ac97_pcm_stereo_in;
 129
 130        return 0;
 131}
 132
 133static int pxa2xx_ac97_hw_aux_params(struct snd_pcm_substream *substream,
 134                                     struct snd_pcm_hw_params *params,
 135                                     struct snd_soc_dai *dai)
 136{
 137        struct snd_soc_pcm_runtime *rtd = substream->private_data;
 138        struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
 139
 140        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
 141                cpu_dai->dma_data = &pxa2xx_ac97_pcm_aux_mono_out;
 142        else
 143                cpu_dai->dma_data = &pxa2xx_ac97_pcm_aux_mono_in;
 144
 145        return 0;
 146}
 147
 148static int pxa2xx_ac97_hw_mic_params(struct snd_pcm_substream *substream,
 149                                     struct snd_pcm_hw_params *params,
 150                                     struct snd_soc_dai *dai)
 151{
 152        struct snd_soc_pcm_runtime *rtd = substream->private_data;
 153        struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
 154
 155        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
 156                return -ENODEV;
 157        else
 158                cpu_dai->dma_data = &pxa2xx_ac97_pcm_mic_mono_in;
 159
 160        return 0;
 161}
 162
 163#define PXA2XX_AC97_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
 164                SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 | \
 165                SNDRV_PCM_RATE_48000)
 166
 167/*
 168 * There is only 1 physical AC97 interface for pxa2xx, but it
 169 * has extra fifo's that can be used for aux DACs and ADCs.
 170 */
 171struct snd_soc_dai pxa_ac97_dai[] = {
 172{
 173        .name = "pxa2xx-ac97",
 174        .id = 0,
 175        .ac97_control = 1,
 176        .probe = pxa2xx_ac97_probe,
 177        .remove = pxa2xx_ac97_remove,
 178        .suspend = pxa2xx_ac97_suspend,
 179        .resume = pxa2xx_ac97_resume,
 180        .playback = {
 181                .stream_name = "AC97 Playback",
 182                .channels_min = 2,
 183                .channels_max = 2,
 184                .rates = PXA2XX_AC97_RATES,
 185                .formats = SNDRV_PCM_FMTBIT_S16_LE,},
 186        .capture = {
 187                .stream_name = "AC97 Capture",
 188                .channels_min = 2,
 189                .channels_max = 2,
 190                .rates = PXA2XX_AC97_RATES,
 191                .formats = SNDRV_PCM_FMTBIT_S16_LE,},
 192        .ops = {
 193                .hw_params = pxa2xx_ac97_hw_params,},
 194},
 195{
 196        .name = "pxa2xx-ac97-aux",
 197        .id = 1,
 198        .ac97_control = 1,
 199        .playback = {
 200                .stream_name = "AC97 Aux Playback",
 201                .channels_min = 1,
 202                .channels_max = 1,
 203                .rates = PXA2XX_AC97_RATES,
 204                .formats = SNDRV_PCM_FMTBIT_S16_LE,},
 205        .capture = {
 206                .stream_name = "AC97 Aux Capture",
 207                .channels_min = 1,
 208                .channels_max = 1,
 209                .rates = PXA2XX_AC97_RATES,
 210                .formats = SNDRV_PCM_FMTBIT_S16_LE,},
 211        .ops = {
 212                .hw_params = pxa2xx_ac97_hw_aux_params,},
 213},
 214{
 215        .name = "pxa2xx-ac97-mic",
 216        .id = 2,
 217        .ac97_control = 1,
 218        .capture = {
 219                .stream_name = "AC97 Mic Capture",
 220                .channels_min = 1,
 221                .channels_max = 1,
 222                .rates = PXA2XX_AC97_RATES,
 223                .formats = SNDRV_PCM_FMTBIT_S16_LE,},
 224        .ops = {
 225                .hw_params = pxa2xx_ac97_hw_mic_params,},
 226},
 227};
 228
 229EXPORT_SYMBOL_GPL(pxa_ac97_dai);
 230EXPORT_SYMBOL_GPL(soc_ac97_ops);
 231
 232static int __init pxa_ac97_init(void)
 233{
 234        return snd_soc_register_dais(pxa_ac97_dai, ARRAY_SIZE(pxa_ac97_dai));
 235}
 236module_init(pxa_ac97_init);
 237
 238static void __exit pxa_ac97_exit(void)
 239{
 240        snd_soc_unregister_dais(pxa_ac97_dai, ARRAY_SIZE(pxa_ac97_dai));
 241}
 242module_exit(pxa_ac97_exit);
 243
 244MODULE_AUTHOR("Nicolas Pitre");
 245MODULE_DESCRIPTION("AC97 driver for the Intel PXA2xx chip");
 246MODULE_LICENSE("GPL");
 247
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.