1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Au12x0/Au1550 PSC ALSA ASoC audio support. 4 * 5 * (c) 2007-2008 MSC Vertriebsges.m.b.H., 6 * Manuel Lauss <manuel.lauss@gmail.com> 7 * 8 * DMA glue for Au1x-PSC audio. 9 */ 10 11 12 #include <linux/module.h> 13 #include <linux/init.h> 14 #include <linux/platform_device.h> 15 #include <linux/slab.h> 16 #include <linux/dma-mapping.h> 17 18 #include <sound/core.h> 19 #include <sound/pcm.h> 20 #include <sound/pcm_params.h> 21 #include <sound/soc.h> 22 23 #include <asm/mach-au1x00/au1000.h> 24 #include <asm/mach-au1x00/au1xxx_dbdma.h> 25 #include <asm/mach-au1x00/au1xxx_psc.h> 26 27 #include "psc.h" 28 29 /*#define PCM_DEBUG*/ 30 31 #define DRV_NAME "dbdma2" 32 33 #define MSG(x...) printk(KERN_INFO "au1xpsc_pcm: " x) 34 #ifdef PCM_DEBUG 35 #define DBG MSG 36 #else 37 #define DBG(x...) do {} while (0) 38 #endif 39 40 struct au1xpsc_audio_dmadata { 41 /* DDMA control data */ 42 unsigned int ddma_id; /* DDMA direction ID for this PSC */ 43 u32 ddma_chan; /* DDMA context */ 44 45 /* PCM context (for irq handlers) */ 46 struct snd_pcm_substream *substream; 47 unsigned long curr_period; /* current segment DDMA is working on */ 48 unsigned long q_period; /* queue period(s) */ 49 dma_addr_t dma_area; /* address of queued DMA area */ 50 dma_addr_t dma_area_s; /* start address of DMA area */ 51 unsigned long pos; /* current byte position being played */ 52 unsigned long periods; /* number of SG segments in total */ 53 unsigned long period_bytes; /* size in bytes of one SG segment */ 54 55 /* runtime data */ 56 int msbits; 57 }; 58 59 /* 60 * These settings are somewhat okay, at least on my machine audio plays 61 * almost skip-free. Especially the 64kB buffer seems to help a LOT. 62 */ 63 #define AU1XPSC_PERIOD_MIN_BYTES 1024 64 #define AU1XPSC_BUFFER_MIN_BYTES 65536 65 66 /* PCM hardware DMA capabilities - platform specific */ 67 static const struct snd_pcm_hardware au1xpsc_pcm_hardware = { 68 .info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | 69 SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BATCH, 70 .period_bytes_min = AU1XPSC_PERIOD_MIN_BYTES, 71 .period_bytes_max = 4096 * 1024 - 1, 72 .periods_min = 2, 73 .periods_max = 4096, /* 2 to as-much-as-you-like */ 74 .buffer_bytes_max = 4096 * 1024 - 1, 75 .fifo_size = 16, /* fifo entries of AC97/I2S PSC */ 76 }; 77 78 static void au1x_pcm_queue_tx(struct au1xpsc_audio_dmadata *cd) 79 { 80 au1xxx_dbdma_put_source(cd->ddma_chan, cd->dma_area, 81 cd->period_bytes, DDMA_FLAGS_IE); 82 83 /* update next-to-queue period */ 84 ++cd->q_period; 85 cd->dma_area += cd->period_bytes; 86 if (cd->q_period >= cd->periods) { 87 cd->q_period = 0; 88 cd->dma_area = cd->dma_area_s; 89 } 90 } 91 92 static void au1x_pcm_queue_rx(struct au1xpsc_audio_dmadata *cd) 93 { 94 au1xxx_dbdma_put_dest(cd->ddma_chan, cd->dma_area, 95 cd->period_bytes, DDMA_FLAGS_IE); 96 97 /* update next-to-queue period */ 98 ++cd->q_period; 99 cd->dma_area += cd->period_bytes; 100 if (cd->q_period >= cd->periods) { 101 cd->q_period = 0; 102 cd->dma_area = cd->dma_area_s; 103 } 104 } 105 106 static void au1x_pcm_dmatx_cb(int irq, void *dev_id) 107 { 108 struct au1xpsc_audio_dmadata *cd = dev_id; 109 110 cd->pos += cd->period_bytes; 111 if (++cd->curr_period >= cd->periods) { 112 cd->pos = 0; 113 cd->curr_period = 0; 114 } 115 snd_pcm_period_elapsed(cd->substream); 116 au1x_pcm_queue_tx(cd); 117 } 118 119 static void au1x_pcm_dmarx_cb(int irq, void *dev_id) 120 { 121 struct au1xpsc_audio_dmadata *cd = dev_id; 122 123 cd->pos += cd->period_bytes; 124 if (++cd->curr_period >= cd->periods) { 125 cd->pos = 0; 126 cd->curr_period = 0; 127 } 128 snd_pcm_period_elapsed(cd->substream); 129 au1x_pcm_queue_rx(cd); 130 } 131 132 static void au1x_pcm_dbdma_free(struct au1xpsc_audio_dmadata *pcd) 133 { 134 if (pcd->ddma_chan) { 135 au1xxx_dbdma_stop(pcd->ddma_chan); 136 au1xxx_dbdma_reset(pcd->ddma_chan); 137 au1xxx_dbdma_chan_free(pcd->ddma_chan); 138 pcd->ddma_chan = 0; 139 pcd->msbits = 0; 140 } 141 } 142 143 /* in case of missing DMA ring or changed TX-source / RX-dest bit widths, 144 * allocate (or reallocate) a 2-descriptor DMA ring with bit depth according 145 * to ALSA-supplied sample depth. This is due to limitations in the dbdma api 146 * (cannot adjust source/dest widths of already allocated descriptor ring). 147 */ 148 static int au1x_pcm_dbdma_realloc(struct au1xpsc_audio_dmadata *pcd, 149 int stype, int msbits) 150 { 151 /* DMA only in 8/16/32 bit widths */ 152 if (msbits == 24) 153 msbits = 32; 154 155 /* check current config: correct bits and descriptors allocated? */ 156 if ((pcd->ddma_chan) && (msbits == pcd->msbits)) 157 goto out; /* all ok! */ 158 159 au1x_pcm_dbdma_free(pcd); 160 161 if (stype == SNDRV_PCM_STREAM_CAPTURE) 162 pcd->ddma_chan = au1xxx_dbdma_chan_alloc(pcd->ddma_id, 163 DSCR_CMD0_ALWAYS, 164 au1x_pcm_dmarx_cb, (void *)pcd); 165 else 166 pcd->ddma_chan = au1xxx_dbdma_chan_alloc(DSCR_CMD0_ALWAYS, 167 pcd->ddma_id, 168 au1x_pcm_dmatx_cb, (void *)pcd); 169 170 if (!pcd->ddma_chan) 171 return -ENOMEM; 172 173 au1xxx_dbdma_set_devwidth(pcd->ddma_chan, msbits); 174 au1xxx_dbdma_ring_alloc(pcd->ddma_chan, 2); 175 176 pcd->msbits = msbits; 177 178 au1xxx_dbdma_stop(pcd->ddma_chan); 179 au1xxx_dbdma_reset(pcd->ddma_chan); 180 181 out: 182 return 0; 183 } 184 185 static inline struct au1xpsc_audio_dmadata *to_dmadata(struct snd_pcm_substream *ss, 186 struct snd_soc_component *component) 187 { 188 struct au1xpsc_audio_dmadata *pcd = snd_soc_component_get_drvdata(component); 189 return &pcd[ss->stream]; 190 } 191 192 static int au1xpsc_pcm_hw_params(struct snd_soc_component *component, 193 struct snd_pcm_substream *substream, 194 struct snd_pcm_hw_params *params) 195 { 196 struct snd_pcm_runtime *runtime = substream->runtime; 197 struct au1xpsc_audio_dmadata *pcd; 198 int stype, ret; 199 200 ret = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params)); 201 if (ret < 0) 202 goto out; 203 204 stype = substream->stream; 205 pcd = to_dmadata(substream, component); 206 207 DBG("runtime->dma_area = 0x%08lx dma_addr_t = 0x%08lx dma_size = %zu " 208 "runtime->min_align %lu\n", 209 (unsigned long)runtime->dma_area, 210 (unsigned long)runtime->dma_addr, runtime->dma_bytes, 211 runtime->min_align); 212 213 DBG("bits %d frags %d frag_bytes %d is_rx %d\n", params->msbits, 214 params_periods(params), params_period_bytes(params), stype); 215 216 ret = au1x_pcm_dbdma_realloc(pcd, stype, params->msbits); 217 if (ret) { 218 MSG("DDMA channel (re)alloc failed!\n"); 219 goto out; 220 } 221 222 pcd->substream = substream; 223 pcd->period_bytes = params_period_bytes(params); 224 pcd->periods = params_periods(params); 225 pcd->dma_area_s = pcd->dma_area = runtime->dma_addr; 226 pcd->q_period = 0; 227 pcd->curr_period = 0; 228 pcd->pos = 0; 229 230 ret = 0; 231 out: 232 return ret; 233 } 234 235 static int au1xpsc_pcm_hw_free(struct snd_soc_component *component, 236 struct snd_pcm_substream *substream) 237 { 238 snd_pcm_lib_free_pages(substream); 239 return 0; 240 } 241 242 static int au1xpsc_pcm_prepare(struct snd_soc_component *component, 243 struct snd_pcm_substream *substream) 244 { 245 struct au1xpsc_audio_dmadata *pcd = to_dmadata(substream, component); 246 247 au1xxx_dbdma_reset(pcd->ddma_chan); 248 249 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { 250 au1x_pcm_queue_rx(pcd); 251 au1x_pcm_queue_rx(pcd); 252 } else { 253 au1x_pcm_queue_tx(pcd); 254 au1x_pcm_queue_tx(pcd); 255 } 256 257 return 0; 258 } 259 260 static int au1xpsc_pcm_trigger(struct snd_soc_component *component, 261 struct snd_pcm_substream *substream, int cmd) 262 { 263 u32 c = to_dmadata(substream, component)->ddma_chan; 264 265 switch (cmd) { 266 case SNDRV_PCM_TRIGGER_START: 267 case SNDRV_PCM_TRIGGER_RESUME: 268 au1xxx_dbdma_start(c); 269 break; 270 case SNDRV_PCM_TRIGGER_STOP: 271 case SNDRV_PCM_TRIGGER_SUSPEND: 272 au1xxx_dbdma_stop(c); 273 break; 274 default: 275 return -EINVAL; 276 } 277 return 0; 278 } 279 280 static snd_pcm_uframes_t 281 au1xpsc_pcm_pointer(struct snd_soc_component *component, 282 struct snd_pcm_substream *substream) 283 { 284 return bytes_to_frames(substream->runtime, 285 to_dmadata(substream, component)->pos); 286 } 287 288 static int au1xpsc_pcm_open(struct snd_soc_component *component, 289 struct snd_pcm_substream *substream) 290 { 291 struct au1xpsc_audio_dmadata *pcd = to_dmadata(substream, component); 292 struct snd_soc_pcm_runtime *rtd = substream->private_data; 293 int stype = substream->stream, *dmaids; 294 295 dmaids = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); 296 if (!dmaids) 297 return -ENODEV; /* whoa, has ordering changed? */ 298 299 pcd->ddma_id = dmaids[stype]; 300 301 snd_soc_set_runtime_hwparams(substream, &au1xpsc_pcm_hardware); 302 return 0; 303 } 304 305 static int au1xpsc_pcm_close(struct snd_soc_component *component, 306 struct snd_pcm_substream *substream) 307 { 308 au1x_pcm_dbdma_free(to_dmadata(substream, component)); 309 return 0; 310 } 311 312 static int au1xpsc_pcm_new(struct snd_soc_component *component, 313 struct snd_soc_pcm_runtime *rtd) 314 { 315 struct snd_card *card = rtd->card->snd_card; 316 struct snd_pcm *pcm = rtd->pcm; 317 318 snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, 319 card->dev, AU1XPSC_BUFFER_MIN_BYTES, (4096 * 1024) - 1); 320 321 return 0; 322 } 323 324 /* au1xpsc audio platform */ 325 static struct snd_soc_component_driver au1xpsc_soc_component = { 326 .name = DRV_NAME, 327 .open = au1xpsc_pcm_open, 328 .close = au1xpsc_pcm_close, 329 .ioctl = snd_soc_pcm_lib_ioctl, 330 .hw_params = au1xpsc_pcm_hw_params, 331 .hw_free = au1xpsc_pcm_hw_free, 332 .prepare = au1xpsc_pcm_prepare, 333 .trigger = au1xpsc_pcm_trigger, 334 .pointer = au1xpsc_pcm_pointer, 335 .pcm_construct = au1xpsc_pcm_new, 336 }; 337 338 static int au1xpsc_pcm_drvprobe(struct platform_device *pdev) 339 { 340 struct au1xpsc_audio_dmadata *dmadata; 341 342 dmadata = devm_kcalloc(&pdev->dev, 343 2, sizeof(struct au1xpsc_audio_dmadata), 344 GFP_KERNEL); 345 if (!dmadata) 346 return -ENOMEM; 347 348 platform_set_drvdata(pdev, dmadata); 349 350 return devm_snd_soc_register_component(&pdev->dev, 351 &au1xpsc_soc_component, NULL, 0); 352 } 353 354 static struct platform_driver au1xpsc_pcm_driver = { 355 .driver = { 356 .name = "au1xpsc-pcm", 357 }, 358 .probe = au1xpsc_pcm_drvprobe, 359 }; 360 361 module_platform_driver(au1xpsc_pcm_driver); 362 363 MODULE_LICENSE("GPL"); 364 MODULE_DESCRIPTION("Au12x0/Au1550 PSC Audio DMA driver"); 365 MODULE_AUTHOR("Manuel Lauss"); 366