root/sound/soc/pxa/pxa2xx-ac97.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. pxa2xx_ac97_warm_reset
  2. pxa2xx_ac97_cold_reset
  3. pxa2xx_ac97_read_actrl
  4. pxa2xx_ac97_write_actrl
  5. pxa2xx_ac97_hifi_startup
  6. pxa2xx_ac97_aux_startup
  7. pxa2xx_ac97_mic_startup
  8. pxa2xx_ac97_dev_probe
  9. pxa2xx_ac97_dev_remove
  10. pxa2xx_ac97_dev_suspend
  11. pxa2xx_ac97_dev_resume

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * linux/sound/pxa2xx-ac97.c -- AC97 support for the Intel PXA2xx chip.
   4  *
   5  * Author:      Nicolas Pitre
   6  * Created:     Dec 02, 2004
   7  * Copyright:   MontaVista Software Inc.
   8  */
   9 
  10 #include <linux/init.h>
  11 #include <linux/io.h>
  12 #include <linux/module.h>
  13 #include <linux/platform_device.h>
  14 #include <linux/dmaengine.h>
  15 #include <linux/dma/pxa-dma.h>
  16 
  17 #include <sound/ac97/controller.h>
  18 #include <sound/core.h>
  19 #include <sound/ac97_codec.h>
  20 #include <sound/soc.h>
  21 #include <sound/pxa2xx-lib.h>
  22 #include <sound/dmaengine_pcm.h>
  23 
  24 #include <mach/hardware.h>
  25 #include <mach/regs-ac97.h>
  26 #include <mach/audio.h>
  27 
  28 static void pxa2xx_ac97_warm_reset(struct ac97_controller *adrv)
  29 {
  30         pxa2xx_ac97_try_warm_reset();
  31 
  32         pxa2xx_ac97_finish_reset();
  33 }
  34 
  35 static void pxa2xx_ac97_cold_reset(struct ac97_controller *adrv)
  36 {
  37         pxa2xx_ac97_try_cold_reset();
  38 
  39         pxa2xx_ac97_finish_reset();
  40 }
  41 
  42 static int pxa2xx_ac97_read_actrl(struct ac97_controller *adrv, int slot,
  43                                   unsigned short reg)
  44 {
  45         return pxa2xx_ac97_read(slot, reg);
  46 }
  47 
  48 static int pxa2xx_ac97_write_actrl(struct ac97_controller *adrv, int slot,
  49                                    unsigned short reg, unsigned short val)
  50 {
  51         return pxa2xx_ac97_write(slot, reg, val);
  52 }
  53 
  54 static struct ac97_controller_ops pxa2xx_ac97_ops = {
  55         .read   = pxa2xx_ac97_read_actrl,
  56         .write  = pxa2xx_ac97_write_actrl,
  57         .warm_reset     = pxa2xx_ac97_warm_reset,
  58         .reset  = pxa2xx_ac97_cold_reset,
  59 };
  60 
  61 static struct snd_dmaengine_dai_dma_data pxa2xx_ac97_pcm_stereo_in = {
  62         .addr           = __PREG(PCDR),
  63         .addr_width     = DMA_SLAVE_BUSWIDTH_4_BYTES,
  64         .chan_name      = "pcm_pcm_stereo_in",
  65         .maxburst       = 32,
  66 };
  67 
  68 static struct snd_dmaengine_dai_dma_data pxa2xx_ac97_pcm_stereo_out = {
  69         .addr           = __PREG(PCDR),
  70         .addr_width     = DMA_SLAVE_BUSWIDTH_4_BYTES,
  71         .chan_name      = "pcm_pcm_stereo_out",
  72         .maxburst       = 32,
  73 };
  74 
  75 static struct snd_dmaengine_dai_dma_data pxa2xx_ac97_pcm_aux_mono_out = {
  76         .addr           = __PREG(MODR),
  77         .addr_width     = DMA_SLAVE_BUSWIDTH_2_BYTES,
  78         .chan_name      = "pcm_aux_mono_out",
  79         .maxburst       = 16,
  80 };
  81 
  82 static struct snd_dmaengine_dai_dma_data pxa2xx_ac97_pcm_aux_mono_in = {
  83         .addr           = __PREG(MODR),
  84         .addr_width     = DMA_SLAVE_BUSWIDTH_2_BYTES,
  85         .chan_name      = "pcm_aux_mono_in",
  86         .maxburst       = 16,
  87 };
  88 
  89 static struct snd_dmaengine_dai_dma_data pxa2xx_ac97_pcm_mic_mono_in = {
  90         .addr           = __PREG(MCDR),
  91         .addr_width     = DMA_SLAVE_BUSWIDTH_2_BYTES,
  92         .chan_name      = "pcm_aux_mic_mono",
  93         .maxburst       = 16,
  94 };
  95 
  96 static int pxa2xx_ac97_hifi_startup(struct snd_pcm_substream *substream,
  97                                     struct snd_soc_dai *cpu_dai)
  98 {
  99         struct snd_dmaengine_dai_dma_data *dma_data;
 100 
 101         if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
 102                 dma_data = &pxa2xx_ac97_pcm_stereo_out;
 103         else
 104                 dma_data = &pxa2xx_ac97_pcm_stereo_in;
 105 
 106         snd_soc_dai_set_dma_data(cpu_dai, substream, dma_data);
 107 
 108         return 0;
 109 }
 110 
 111 static int pxa2xx_ac97_aux_startup(struct snd_pcm_substream *substream,
 112                                    struct snd_soc_dai *cpu_dai)
 113 {
 114         struct snd_dmaengine_dai_dma_data *dma_data;
 115 
 116         if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
 117                 dma_data = &pxa2xx_ac97_pcm_aux_mono_out;
 118         else
 119                 dma_data = &pxa2xx_ac97_pcm_aux_mono_in;
 120 
 121         snd_soc_dai_set_dma_data(cpu_dai, substream, dma_data);
 122 
 123         return 0;
 124 }
 125 
 126 static int pxa2xx_ac97_mic_startup(struct snd_pcm_substream *substream,
 127                                    struct snd_soc_dai *cpu_dai)
 128 {
 129         if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
 130                 return -ENODEV;
 131         snd_soc_dai_set_dma_data(cpu_dai, substream,
 132                                  &pxa2xx_ac97_pcm_mic_mono_in);
 133 
 134         return 0;
 135 }
 136 
 137 #define PXA2XX_AC97_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
 138                 SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 | \
 139                 SNDRV_PCM_RATE_48000)
 140 
 141 static const struct snd_soc_dai_ops pxa_ac97_hifi_dai_ops = {
 142         .startup        = pxa2xx_ac97_hifi_startup,
 143 };
 144 
 145 static const struct snd_soc_dai_ops pxa_ac97_aux_dai_ops = {
 146         .startup        = pxa2xx_ac97_aux_startup,
 147 };
 148 
 149 static const struct snd_soc_dai_ops pxa_ac97_mic_dai_ops = {
 150         .startup        = pxa2xx_ac97_mic_startup,
 151 };
 152 
 153 /*
 154  * There is only 1 physical AC97 interface for pxa2xx, but it
 155  * has extra fifo's that can be used for aux DACs and ADCs.
 156  */
 157 static struct snd_soc_dai_driver pxa_ac97_dai_driver[] = {
 158 {
 159         .name = "pxa2xx-ac97",
 160         .bus_control = true,
 161         .playback = {
 162                 .stream_name = "AC97 Playback",
 163                 .channels_min = 2,
 164                 .channels_max = 2,
 165                 .rates = PXA2XX_AC97_RATES,
 166                 .formats = SNDRV_PCM_FMTBIT_S16_LE,},
 167         .capture = {
 168                 .stream_name = "AC97 Capture",
 169                 .channels_min = 2,
 170                 .channels_max = 2,
 171                 .rates = PXA2XX_AC97_RATES,
 172                 .formats = SNDRV_PCM_FMTBIT_S16_LE,},
 173         .ops = &pxa_ac97_hifi_dai_ops,
 174 },
 175 {
 176         .name = "pxa2xx-ac97-aux",
 177         .bus_control = true,
 178         .playback = {
 179                 .stream_name = "AC97 Aux Playback",
 180                 .channels_min = 1,
 181                 .channels_max = 1,
 182                 .rates = PXA2XX_AC97_RATES,
 183                 .formats = SNDRV_PCM_FMTBIT_S16_LE,},
 184         .capture = {
 185                 .stream_name = "AC97 Aux Capture",
 186                 .channels_min = 1,
 187                 .channels_max = 1,
 188                 .rates = PXA2XX_AC97_RATES,
 189                 .formats = SNDRV_PCM_FMTBIT_S16_LE,},
 190         .ops = &pxa_ac97_aux_dai_ops,
 191 },
 192 {
 193         .name = "pxa2xx-ac97-mic",
 194         .bus_control = true,
 195         .capture = {
 196                 .stream_name = "AC97 Mic Capture",
 197                 .channels_min = 1,
 198                 .channels_max = 1,
 199                 .rates = PXA2XX_AC97_RATES,
 200                 .formats = SNDRV_PCM_FMTBIT_S16_LE,},
 201         .ops = &pxa_ac97_mic_dai_ops,
 202 },
 203 };
 204 
 205 static const struct snd_soc_component_driver pxa_ac97_component = {
 206         .name           = "pxa-ac97",
 207         .ops            = &pxa2xx_pcm_ops,
 208         .pcm_new        = pxa2xx_soc_pcm_new,
 209         .pcm_free       = pxa2xx_pcm_free_dma_buffers,
 210 };
 211 
 212 #ifdef CONFIG_OF
 213 static const struct of_device_id pxa2xx_ac97_dt_ids[] = {
 214         { .compatible = "marvell,pxa250-ac97", },
 215         { .compatible = "marvell,pxa270-ac97", },
 216         { .compatible = "marvell,pxa300-ac97", },
 217         { }
 218 };
 219 MODULE_DEVICE_TABLE(of, pxa2xx_ac97_dt_ids);
 220 
 221 #endif
 222 
 223 static int pxa2xx_ac97_dev_probe(struct platform_device *pdev)
 224 {
 225         int ret;
 226         struct ac97_controller *ctrl;
 227         pxa2xx_audio_ops_t *pdata = pdev->dev.platform_data;
 228         void **codecs_pdata;
 229 
 230         if (pdev->id != -1) {
 231                 dev_err(&pdev->dev, "PXA2xx has only one AC97 port.\n");
 232                 return -ENXIO;
 233         }
 234 
 235         ret = pxa2xx_ac97_hw_probe(pdev);
 236         if (ret) {
 237                 dev_err(&pdev->dev, "PXA2xx AC97 hw probe error (%d)\n", ret);
 238                 return ret;
 239         }
 240 
 241         codecs_pdata = pdata ? pdata->codec_pdata : NULL;
 242         ctrl = snd_ac97_controller_register(&pxa2xx_ac97_ops, &pdev->dev,
 243                                             AC97_SLOTS_AVAILABLE_ALL,
 244                                             codecs_pdata);
 245         if (IS_ERR(ctrl))
 246                 return PTR_ERR(ctrl);
 247 
 248         platform_set_drvdata(pdev, ctrl);
 249         /* Punt most of the init to the SoC probe; we may need the machine
 250          * driver to do interesting things with the clocking to get us up
 251          * and running.
 252          */
 253         return devm_snd_soc_register_component(&pdev->dev, &pxa_ac97_component,
 254                                           pxa_ac97_dai_driver, ARRAY_SIZE(pxa_ac97_dai_driver));
 255 }
 256 
 257 static int pxa2xx_ac97_dev_remove(struct platform_device *pdev)
 258 {
 259         struct ac97_controller *ctrl = platform_get_drvdata(pdev);
 260 
 261         snd_ac97_controller_unregister(ctrl);
 262         pxa2xx_ac97_hw_remove(pdev);
 263         return 0;
 264 }
 265 
 266 #ifdef CONFIG_PM_SLEEP
 267 static int pxa2xx_ac97_dev_suspend(struct device *dev)
 268 {
 269         return pxa2xx_ac97_hw_suspend();
 270 }
 271 
 272 static int pxa2xx_ac97_dev_resume(struct device *dev)
 273 {
 274         return pxa2xx_ac97_hw_resume();
 275 }
 276 
 277 static SIMPLE_DEV_PM_OPS(pxa2xx_ac97_pm_ops,
 278                 pxa2xx_ac97_dev_suspend, pxa2xx_ac97_dev_resume);
 279 #endif
 280 
 281 static struct platform_driver pxa2xx_ac97_driver = {
 282         .probe          = pxa2xx_ac97_dev_probe,
 283         .remove         = pxa2xx_ac97_dev_remove,
 284         .driver         = {
 285                 .name   = "pxa2xx-ac97",
 286 #ifdef CONFIG_PM_SLEEP
 287                 .pm     = &pxa2xx_ac97_pm_ops,
 288 #endif
 289                 .of_match_table = of_match_ptr(pxa2xx_ac97_dt_ids),
 290         },
 291 };
 292 
 293 module_platform_driver(pxa2xx_ac97_driver);
 294 
 295 MODULE_AUTHOR("Nicolas Pitre");
 296 MODULE_DESCRIPTION("AC97 driver for the Intel PXA2xx chip");
 297 MODULE_LICENSE("GPL");
 298 MODULE_ALIAS("platform:pxa2xx-ac97");

/* [<][>][^][v][top][bottom][index][help] */