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