xref: /openbmc/linux/sound/soc/ux500/ux500_pcm.c (revision 9a87ffc99ec8eb8d35eed7c4f816d75f5cc9662e)
1d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
201a0c113SOla Lilja /*
301a0c113SOla Lilja  * Copyright (C) ST-Ericsson SA 2012
401a0c113SOla Lilja  *
501a0c113SOla Lilja  * Author: Ola Lilja <ola.o.lilja@stericsson.com>,
601a0c113SOla Lilja  *         Roger Nilsson <roger.xr.nilsson@stericsson.com>
701a0c113SOla Lilja  *         for ST-Ericsson.
801a0c113SOla Lilja  */
901a0c113SOla Lilja 
1001a0c113SOla Lilja #include <asm/page.h>
1101a0c113SOla Lilja 
1201a0c113SOla Lilja #include <linux/module.h>
1301a0c113SOla Lilja #include <linux/dma-mapping.h>
1401a0c113SOla Lilja #include <linux/dmaengine.h>
1501a0c113SOla Lilja #include <linux/slab.h>
1601a0c113SOla Lilja 
1701a0c113SOla Lilja #include <sound/pcm.h>
1801a0c113SOla Lilja #include <sound/pcm_params.h>
1901a0c113SOla Lilja #include <sound/soc.h>
2001a0c113SOla Lilja #include <sound/dmaengine_pcm.h>
2101a0c113SOla Lilja 
2201a0c113SOla Lilja #include "ux500_msp_i2s.h"
2301a0c113SOla Lilja #include "ux500_pcm.h"
2401a0c113SOla Lilja 
2569b6f196SLars-Peter Clausen #define UX500_PLATFORM_PERIODS_BYTES_MIN	128
2669b6f196SLars-Peter Clausen #define UX500_PLATFORM_PERIODS_BYTES_MAX	(64 * PAGE_SIZE)
2769b6f196SLars-Peter Clausen #define UX500_PLATFORM_PERIODS_MIN		2
2869b6f196SLars-Peter Clausen #define UX500_PLATFORM_PERIODS_MAX		48
2969b6f196SLars-Peter Clausen #define UX500_PLATFORM_BUFFER_BYTES_MAX		(2048 * PAGE_SIZE)
3069b6f196SLars-Peter Clausen 
ux500_pcm_prepare_slave_config(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params,struct dma_slave_config * slave_config)31eef6473fSFabio Baltieri static int ux500_pcm_prepare_slave_config(struct snd_pcm_substream *substream,
32eef6473fSFabio Baltieri 		struct snd_pcm_hw_params *params,
33eef6473fSFabio Baltieri 		struct dma_slave_config *slave_config)
34eef6473fSFabio Baltieri {
353e44c479SKuninori Morimoto 	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
36f6c37752SLee Jones 	struct snd_dmaengine_dai_dma_data *snd_dma_params;
37f6c37752SLee Jones 	dma_addr_t dma_addr;
38eef6473fSFabio Baltieri 	int ret;
39eef6473fSFabio Baltieri 
401766ac52SArnd Bergmann 	snd_dma_params = snd_soc_dai_get_dma_data(asoc_rtd_to_cpu(rtd, 0), substream);
41f6c37752SLee Jones 	dma_addr = snd_dma_params->addr;
42eef6473fSFabio Baltieri 
43eef6473fSFabio Baltieri 	ret = snd_hwparams_to_dma_slave_config(substream, params, slave_config);
44eef6473fSFabio Baltieri 	if (ret)
45eef6473fSFabio Baltieri 		return ret;
46eef6473fSFabio Baltieri 
47eef6473fSFabio Baltieri 	slave_config->dst_maxburst = 4;
48eef6473fSFabio Baltieri 	slave_config->src_maxburst = 4;
49609a3050SLee Jones 
50609a3050SLee Jones 	slave_config->src_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
51609a3050SLee Jones 	slave_config->dst_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
52eef6473fSFabio Baltieri 
53eef6473fSFabio Baltieri 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
54f6c37752SLee Jones 		slave_config->dst_addr = dma_addr;
55eef6473fSFabio Baltieri 	else
56f6c37752SLee Jones 		slave_config->src_addr = dma_addr;
57eef6473fSFabio Baltieri 
58eef6473fSFabio Baltieri 	return 0;
59eef6473fSFabio Baltieri }
60eef6473fSFabio Baltieri 
6186a3fdfcSLee Jones static const struct snd_dmaengine_pcm_config ux500_dmaengine_of_pcm_config = {
6286a3fdfcSLee Jones 	.prepare_slave_config = ux500_pcm_prepare_slave_config,
6386a3fdfcSLee Jones };
6486a3fdfcSLee Jones 
ux500_pcm_register_platform(struct platform_device * pdev)65da794876SBill Pemberton int ux500_pcm_register_platform(struct platform_device *pdev)
6601a0c113SOla Lilja {
6701a0c113SOla Lilja 	int ret;
6801a0c113SOla Lilja 
691766ac52SArnd Bergmann 	ret = snd_dmaengine_pcm_register(&pdev->dev,
70*aafe9375SArnd Bergmann 					 &ux500_dmaengine_of_pcm_config, 0);
7101a0c113SOla Lilja 	if (ret < 0) {
7201a0c113SOla Lilja 		dev_err(&pdev->dev,
7301a0c113SOla Lilja 			"%s: ERROR: Failed to register platform '%s' (%d)!\n",
7401a0c113SOla Lilja 			__func__, pdev->name, ret);
7501a0c113SOla Lilja 		return ret;
7601a0c113SOla Lilja 	}
7701a0c113SOla Lilja 
7801a0c113SOla Lilja 	return 0;
7901a0c113SOla Lilja }
801428c20fSLee Jones EXPORT_SYMBOL_GPL(ux500_pcm_register_platform);
8101a0c113SOla Lilja 
ux500_pcm_unregister_platform(struct platform_device * pdev)82da794876SBill Pemberton int ux500_pcm_unregister_platform(struct platform_device *pdev)
8301a0c113SOla Lilja {
8422f38f79SLars-Peter Clausen 	snd_dmaengine_pcm_unregister(&pdev->dev);
8501a0c113SOla Lilja 	return 0;
8601a0c113SOla Lilja }
871428c20fSLee Jones EXPORT_SYMBOL_GPL(ux500_pcm_unregister_platform);
881783c9d7SArnd Bergmann 
891783c9d7SArnd Bergmann MODULE_AUTHOR("Ola Lilja");
901783c9d7SArnd Bergmann MODULE_AUTHOR("Roger Nilsson");
911783c9d7SArnd Bergmann MODULE_DESCRIPTION("ASoC UX500 driver");
921783c9d7SArnd Bergmann MODULE_LICENSE("GPL v2");
93