1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (C) ST-Ericsson SA 2012 4 * 5 * Author: Ola Lilja <ola.o.lilja@stericsson.com>, 6 * Roger Nilsson <roger.xr.nilsson@stericsson.com> 7 * for ST-Ericsson. 8 */ 9 10 #include <asm/page.h> 11 12 #include <linux/module.h> 13 #include <linux/dma-mapping.h> 14 #include <linux/dmaengine.h> 15 #include <linux/slab.h> 16 17 #include <sound/pcm.h> 18 #include <sound/pcm_params.h> 19 #include <sound/soc.h> 20 #include <sound/dmaengine_pcm.h> 21 22 #include "ux500_msp_i2s.h" 23 #include "ux500_pcm.h" 24 25 #define UX500_PLATFORM_PERIODS_BYTES_MIN 128 26 #define UX500_PLATFORM_PERIODS_BYTES_MAX (64 * PAGE_SIZE) 27 #define UX500_PLATFORM_PERIODS_MIN 2 28 #define UX500_PLATFORM_PERIODS_MAX 48 29 #define UX500_PLATFORM_BUFFER_BYTES_MAX (2048 * PAGE_SIZE) 30 31 static int ux500_pcm_prepare_slave_config(struct snd_pcm_substream *substream, 32 struct snd_pcm_hw_params *params, 33 struct dma_slave_config *slave_config) 34 { 35 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 36 struct snd_dmaengine_dai_dma_data *snd_dma_params; 37 dma_addr_t dma_addr; 38 int ret; 39 40 snd_dma_params = snd_soc_dai_get_dma_data(asoc_rtd_to_cpu(rtd, 0), substream); 41 dma_addr = snd_dma_params->addr; 42 43 ret = snd_hwparams_to_dma_slave_config(substream, params, slave_config); 44 if (ret) 45 return ret; 46 47 slave_config->dst_maxburst = 4; 48 slave_config->src_maxburst = 4; 49 50 slave_config->src_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES; 51 slave_config->dst_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES; 52 53 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 54 slave_config->dst_addr = dma_addr; 55 else 56 slave_config->src_addr = dma_addr; 57 58 return 0; 59 } 60 61 static const struct snd_dmaengine_pcm_config ux500_dmaengine_of_pcm_config = { 62 .prepare_slave_config = ux500_pcm_prepare_slave_config, 63 }; 64 65 int ux500_pcm_register_platform(struct platform_device *pdev) 66 { 67 int ret; 68 69 ret = snd_dmaengine_pcm_register(&pdev->dev, 70 &ux500_dmaengine_of_pcm_config, 0); 71 if (ret < 0) { 72 dev_err(&pdev->dev, 73 "%s: ERROR: Failed to register platform '%s' (%d)!\n", 74 __func__, pdev->name, ret); 75 return ret; 76 } 77 78 return 0; 79 } 80 EXPORT_SYMBOL_GPL(ux500_pcm_register_platform); 81 82 int ux500_pcm_unregister_platform(struct platform_device *pdev) 83 { 84 snd_dmaengine_pcm_unregister(&pdev->dev); 85 return 0; 86 } 87 EXPORT_SYMBOL_GPL(ux500_pcm_unregister_platform); 88 89 MODULE_AUTHOR("Ola Lilja"); 90 MODULE_AUTHOR("Roger Nilsson"); 91 MODULE_DESCRIPTION("ASoC UX500 driver"); 92 MODULE_LICENSE("GPL v2"); 93