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 .pcm_construct = pxa2xx_soc_pcm_new, 208 .pcm_destruct = pxa2xx_soc_pcm_free, 209 .open = pxa2xx_soc_pcm_open, 210 .close = pxa2xx_soc_pcm_close, 211 .ioctl = snd_soc_pcm_lib_ioctl, 212 .hw_params = pxa2xx_soc_pcm_hw_params, 213 .hw_free = pxa2xx_soc_pcm_hw_free, 214 .prepare = pxa2xx_soc_pcm_prepare, 215 .trigger = pxa2xx_soc_pcm_trigger, 216 .pointer = pxa2xx_soc_pcm_pointer, 217 .mmap = pxa2xx_soc_pcm_mmap, 218 }; 219 220 #ifdef CONFIG_OF 221 static const struct of_device_id pxa2xx_ac97_dt_ids[] = { 222 { .compatible = "marvell,pxa250-ac97", }, 223 { .compatible = "marvell,pxa270-ac97", }, 224 { .compatible = "marvell,pxa300-ac97", }, 225 { } 226 }; 227 MODULE_DEVICE_TABLE(of, pxa2xx_ac97_dt_ids); 228 229 #endif 230 231 static int pxa2xx_ac97_dev_probe(struct platform_device *pdev) 232 { 233 int ret; 234 struct ac97_controller *ctrl; 235 pxa2xx_audio_ops_t *pdata = pdev->dev.platform_data; 236 void **codecs_pdata; 237 238 if (pdev->id != -1) { 239 dev_err(&pdev->dev, "PXA2xx has only one AC97 port.\n"); 240 return -ENXIO; 241 } 242 243 ret = pxa2xx_ac97_hw_probe(pdev); 244 if (ret) { 245 dev_err(&pdev->dev, "PXA2xx AC97 hw probe error (%d)\n", ret); 246 return ret; 247 } 248 249 codecs_pdata = pdata ? pdata->codec_pdata : NULL; 250 ctrl = snd_ac97_controller_register(&pxa2xx_ac97_ops, &pdev->dev, 251 AC97_SLOTS_AVAILABLE_ALL, 252 codecs_pdata); 253 if (IS_ERR(ctrl)) 254 return PTR_ERR(ctrl); 255 256 platform_set_drvdata(pdev, ctrl); 257 /* Punt most of the init to the SoC probe; we may need the machine 258 * driver to do interesting things with the clocking to get us up 259 * and running. 260 */ 261 return devm_snd_soc_register_component(&pdev->dev, &pxa_ac97_component, 262 pxa_ac97_dai_driver, ARRAY_SIZE(pxa_ac97_dai_driver)); 263 } 264 265 static int pxa2xx_ac97_dev_remove(struct platform_device *pdev) 266 { 267 struct ac97_controller *ctrl = platform_get_drvdata(pdev); 268 269 snd_ac97_controller_unregister(ctrl); 270 pxa2xx_ac97_hw_remove(pdev); 271 return 0; 272 } 273 274 #ifdef CONFIG_PM_SLEEP 275 static int pxa2xx_ac97_dev_suspend(struct device *dev) 276 { 277 return pxa2xx_ac97_hw_suspend(); 278 } 279 280 static int pxa2xx_ac97_dev_resume(struct device *dev) 281 { 282 return pxa2xx_ac97_hw_resume(); 283 } 284 285 static SIMPLE_DEV_PM_OPS(pxa2xx_ac97_pm_ops, 286 pxa2xx_ac97_dev_suspend, pxa2xx_ac97_dev_resume); 287 #endif 288 289 static struct platform_driver pxa2xx_ac97_driver = { 290 .probe = pxa2xx_ac97_dev_probe, 291 .remove = pxa2xx_ac97_dev_remove, 292 .driver = { 293 .name = "pxa2xx-ac97", 294 #ifdef CONFIG_PM_SLEEP 295 .pm = &pxa2xx_ac97_pm_ops, 296 #endif 297 .of_match_table = of_match_ptr(pxa2xx_ac97_dt_ids), 298 }, 299 }; 300 301 module_platform_driver(pxa2xx_ac97_driver); 302 303 MODULE_AUTHOR("Nicolas Pitre"); 304 MODULE_DESCRIPTION("AC97 driver for the Intel PXA2xx chip"); 305 MODULE_LICENSE("GPL"); 306 MODULE_ALIAS("platform:pxa2xx-ac97"); 307