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/io.h> 15 #include <linux/module.h> 16 #include <linux/platform_device.h> 17 #include <linux/dmaengine.h> 18 19 #include <sound/core.h> 20 #include <sound/ac97_codec.h> 21 #include <sound/soc.h> 22 #include <sound/pxa2xx-lib.h> 23 #include <sound/dmaengine_pcm.h> 24 25 #include <mach/hardware.h> 26 #include <mach/regs-ac97.h> 27 #include <mach/audio.h> 28 29 #include "pxa2xx-ac97.h" 30 31 static void pxa2xx_ac97_warm_reset(struct snd_ac97 *ac97) 32 { 33 pxa2xx_ac97_try_warm_reset(ac97); 34 35 pxa2xx_ac97_finish_reset(ac97); 36 } 37 38 static void pxa2xx_ac97_cold_reset(struct snd_ac97 *ac97) 39 { 40 pxa2xx_ac97_try_cold_reset(ac97); 41 42 pxa2xx_ac97_finish_reset(ac97); 43 } 44 45 static struct snd_ac97_bus_ops pxa2xx_ac97_ops = { 46 .read = pxa2xx_ac97_read, 47 .write = pxa2xx_ac97_write, 48 .warm_reset = pxa2xx_ac97_warm_reset, 49 .reset = pxa2xx_ac97_cold_reset, 50 }; 51 52 static unsigned long pxa2xx_ac97_pcm_stereo_in_req = 11; 53 static struct snd_dmaengine_dai_dma_data pxa2xx_ac97_pcm_stereo_in = { 54 .addr = __PREG(PCDR), 55 .addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES, 56 .maxburst = 32, 57 .filter_data = &pxa2xx_ac97_pcm_stereo_in_req, 58 }; 59 60 static unsigned long pxa2xx_ac97_pcm_stereo_out_req = 12; 61 static struct snd_dmaengine_dai_dma_data pxa2xx_ac97_pcm_stereo_out = { 62 .addr = __PREG(PCDR), 63 .addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES, 64 .maxburst = 32, 65 .filter_data = &pxa2xx_ac97_pcm_stereo_out_req, 66 }; 67 68 static unsigned long pxa2xx_ac97_pcm_aux_mono_out_req = 10; 69 static struct snd_dmaengine_dai_dma_data pxa2xx_ac97_pcm_aux_mono_out = { 70 .addr = __PREG(MODR), 71 .addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES, 72 .maxburst = 16, 73 .filter_data = &pxa2xx_ac97_pcm_aux_mono_out_req, 74 }; 75 76 static unsigned long pxa2xx_ac97_pcm_aux_mono_in_req = 9; 77 static struct snd_dmaengine_dai_dma_data pxa2xx_ac97_pcm_aux_mono_in = { 78 .addr = __PREG(MODR), 79 .addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES, 80 .maxburst = 16, 81 .filter_data = &pxa2xx_ac97_pcm_aux_mono_in_req, 82 }; 83 84 static unsigned long pxa2xx_ac97_pcm_aux_mic_mono_req = 8; 85 static struct snd_dmaengine_dai_dma_data pxa2xx_ac97_pcm_mic_mono_in = { 86 .addr = __PREG(MCDR), 87 .addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES, 88 .maxburst = 16, 89 .filter_data = &pxa2xx_ac97_pcm_aux_mic_mono_req, 90 }; 91 92 static int pxa2xx_ac97_hw_params(struct snd_pcm_substream *substream, 93 struct snd_pcm_hw_params *params, 94 struct snd_soc_dai *cpu_dai) 95 { 96 struct snd_dmaengine_dai_dma_data *dma_data; 97 98 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 99 dma_data = &pxa2xx_ac97_pcm_stereo_out; 100 else 101 dma_data = &pxa2xx_ac97_pcm_stereo_in; 102 103 snd_soc_dai_set_dma_data(cpu_dai, substream, dma_data); 104 105 return 0; 106 } 107 108 static int pxa2xx_ac97_hw_aux_params(struct snd_pcm_substream *substream, 109 struct snd_pcm_hw_params *params, 110 struct snd_soc_dai *cpu_dai) 111 { 112 struct snd_dmaengine_dai_dma_data *dma_data; 113 114 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 115 dma_data = &pxa2xx_ac97_pcm_aux_mono_out; 116 else 117 dma_data = &pxa2xx_ac97_pcm_aux_mono_in; 118 119 snd_soc_dai_set_dma_data(cpu_dai, substream, dma_data); 120 121 return 0; 122 } 123 124 static int pxa2xx_ac97_hw_mic_params(struct snd_pcm_substream *substream, 125 struct snd_pcm_hw_params *params, 126 struct snd_soc_dai *cpu_dai) 127 { 128 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 129 return -ENODEV; 130 else 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 .hw_params = pxa2xx_ac97_hw_params, 143 }; 144 145 static const struct snd_soc_dai_ops pxa_ac97_aux_dai_ops = { 146 .hw_params = pxa2xx_ac97_hw_aux_params, 147 }; 148 149 static const struct snd_soc_dai_ops pxa_ac97_mic_dai_ops = { 150 .hw_params = pxa2xx_ac97_hw_mic_params, 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 }; 208 209 static int pxa2xx_ac97_dev_probe(struct platform_device *pdev) 210 { 211 int ret; 212 213 if (pdev->id != -1) { 214 dev_err(&pdev->dev, "PXA2xx has only one AC97 port.\n"); 215 return -ENXIO; 216 } 217 218 ret = pxa2xx_ac97_hw_probe(pdev); 219 if (ret) { 220 dev_err(&pdev->dev, "PXA2xx AC97 hw probe error (%d)\n", ret); 221 return ret; 222 } 223 224 ret = snd_soc_set_ac97_ops(&pxa2xx_ac97_ops); 225 if (ret != 0) 226 return ret; 227 228 /* Punt most of the init to the SoC probe; we may need the machine 229 * driver to do interesting things with the clocking to get us up 230 * and running. 231 */ 232 return snd_soc_register_component(&pdev->dev, &pxa_ac97_component, 233 pxa_ac97_dai_driver, ARRAY_SIZE(pxa_ac97_dai_driver)); 234 } 235 236 static int pxa2xx_ac97_dev_remove(struct platform_device *pdev) 237 { 238 snd_soc_unregister_component(&pdev->dev); 239 snd_soc_set_ac97_ops(NULL); 240 pxa2xx_ac97_hw_remove(pdev); 241 return 0; 242 } 243 244 #ifdef CONFIG_PM_SLEEP 245 static int pxa2xx_ac97_dev_suspend(struct device *dev) 246 { 247 return pxa2xx_ac97_hw_suspend(); 248 } 249 250 static int pxa2xx_ac97_dev_resume(struct device *dev) 251 { 252 return pxa2xx_ac97_hw_resume(); 253 } 254 255 static SIMPLE_DEV_PM_OPS(pxa2xx_ac97_pm_ops, 256 pxa2xx_ac97_dev_suspend, pxa2xx_ac97_dev_resume); 257 #endif 258 259 static struct platform_driver pxa2xx_ac97_driver = { 260 .probe = pxa2xx_ac97_dev_probe, 261 .remove = pxa2xx_ac97_dev_remove, 262 .driver = { 263 .name = "pxa2xx-ac97", 264 #ifdef CONFIG_PM_SLEEP 265 .pm = &pxa2xx_ac97_pm_ops, 266 #endif 267 }, 268 }; 269 270 module_platform_driver(pxa2xx_ac97_driver); 271 272 MODULE_AUTHOR("Nicolas Pitre"); 273 MODULE_DESCRIPTION("AC97 driver for the Intel PXA2xx chip"); 274 MODULE_LICENSE("GPL"); 275