2 * Copyright (C) ST-Ericsson SA 2012
4 * Author: Ola Lilja <ola.o.lilja@stericsson.com>,
5 * Roger Nilsson <roger.xr.nilsson@stericsson.com>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as published
12 * by the Free Software Foundation.
17 #include <linux/module.h>
18 #include <linux/dma-mapping.h>
19 #include <linux/dmaengine.h>
20 #include <linux/slab.h>
21 #include <linux/platform_data/dma-ste-dma40.h>
23 #include <sound/pcm.h>
24 #include <sound/pcm_params.h>
25 #include <sound/soc.h>
26 #include <sound/dmaengine_pcm.h>
28 #include "ux500_msp_i2s.h"
29 #include "ux500_pcm.h"
31 #define UX500_PLATFORM_MIN_RATE 8000
32 #define UX500_PLATFORM_MAX_RATE 48000
34 #define UX500_PLATFORM_MIN_CHANNELS 1
35 #define UX500_PLATFORM_MAX_CHANNELS 8
37 #define UX500_PLATFORM_PERIODS_BYTES_MIN 128
38 #define UX500_PLATFORM_PERIODS_BYTES_MAX (64 * PAGE_SIZE)
39 #define UX500_PLATFORM_PERIODS_MIN 2
40 #define UX500_PLATFORM_PERIODS_MAX 48
41 #define UX500_PLATFORM_BUFFER_BYTES_MAX (2048 * PAGE_SIZE)
43 static const struct snd_pcm_hardware ux500_pcm_hw
= {
44 .info
= SNDRV_PCM_INFO_INTERLEAVED
|
46 SNDRV_PCM_INFO_RESUME
|
48 .formats
= SNDRV_PCM_FMTBIT_S16_LE
|
49 SNDRV_PCM_FMTBIT_U16_LE
|
50 SNDRV_PCM_FMTBIT_S16_BE
|
51 SNDRV_PCM_FMTBIT_U16_BE
,
52 .rates
= SNDRV_PCM_RATE_KNOT
,
53 .rate_min
= UX500_PLATFORM_MIN_RATE
,
54 .rate_max
= UX500_PLATFORM_MAX_RATE
,
55 .channels_min
= UX500_PLATFORM_MIN_CHANNELS
,
56 .channels_max
= UX500_PLATFORM_MAX_CHANNELS
,
57 .buffer_bytes_max
= UX500_PLATFORM_BUFFER_BYTES_MAX
,
58 .period_bytes_min
= UX500_PLATFORM_PERIODS_BYTES_MIN
,
59 .period_bytes_max
= UX500_PLATFORM_PERIODS_BYTES_MAX
,
60 .periods_min
= UX500_PLATFORM_PERIODS_MIN
,
61 .periods_max
= UX500_PLATFORM_PERIODS_MAX
,
64 static struct dma_chan
*ux500_pcm_request_chan(struct snd_soc_pcm_runtime
*rtd
,
65 struct snd_pcm_substream
*substream
)
67 struct snd_soc_dai
*dai
= rtd
->cpu_dai
;
68 struct device
*dev
= dai
->dev
;
69 u16 per_data_width
, mem_data_width
;
70 struct stedma40_chan_cfg
*dma_cfg
;
71 struct ux500_msp_dma_params
*dma_params
;
73 dev_dbg(dev
, "%s: MSP %d (%s): Enter.\n", __func__
, dai
->id
,
74 snd_pcm_stream_str(substream
));
76 dma_params
= snd_soc_dai_get_dma_data(dai
, substream
);
77 dma_cfg
= dma_params
->dma_cfg
;
79 mem_data_width
= DMA_SLAVE_BUSWIDTH_2_BYTES
;
81 switch (dma_params
->data_size
) {
83 per_data_width
= DMA_SLAVE_BUSWIDTH_4_BYTES
;
86 per_data_width
= DMA_SLAVE_BUSWIDTH_2_BYTES
;
89 per_data_width
= DMA_SLAVE_BUSWIDTH_1_BYTE
;
92 per_data_width
= DMA_SLAVE_BUSWIDTH_4_BYTES
;
95 if (substream
->stream
== SNDRV_PCM_STREAM_PLAYBACK
) {
96 dma_cfg
->src_info
.data_width
= mem_data_width
;
97 dma_cfg
->dst_info
.data_width
= per_data_width
;
99 dma_cfg
->src_info
.data_width
= per_data_width
;
100 dma_cfg
->dst_info
.data_width
= mem_data_width
;
103 return snd_dmaengine_pcm_request_channel(stedma40_filter
, dma_cfg
);
106 static int ux500_pcm_prepare_slave_config(struct snd_pcm_substream
*substream
,
107 struct snd_pcm_hw_params
*params
,
108 struct dma_slave_config
*slave_config
)
110 struct snd_soc_pcm_runtime
*rtd
= substream
->private_data
;
111 struct ux500_msp_dma_params
*dma_params
;
112 struct stedma40_chan_cfg
*dma_cfg
;
115 dma_params
= snd_soc_dai_get_dma_data(rtd
->cpu_dai
, substream
);
116 dma_cfg
= dma_params
->dma_cfg
;
118 ret
= snd_hwparams_to_dma_slave_config(substream
, params
, slave_config
);
122 slave_config
->dst_maxburst
= 4;
123 slave_config
->dst_addr_width
= dma_cfg
->dst_info
.data_width
;
124 slave_config
->src_maxburst
= 4;
125 slave_config
->src_addr_width
= dma_cfg
->src_info
.data_width
;
127 if (substream
->stream
== SNDRV_PCM_STREAM_PLAYBACK
)
128 slave_config
->dst_addr
= dma_params
->tx_rx_addr
;
130 slave_config
->src_addr
= dma_params
->tx_rx_addr
;
135 static const struct snd_dmaengine_pcm_config ux500_dmaengine_pcm_config
= {
136 .pcm_hardware
= &ux500_pcm_hw
,
137 .compat_request_channel
= ux500_pcm_request_chan
,
138 .prealloc_buffer_size
= 128 * 1024,
139 .prepare_slave_config
= ux500_pcm_prepare_slave_config
,
142 int ux500_pcm_register_platform(struct platform_device
*pdev
)
146 ret
= snd_dmaengine_pcm_register(&pdev
->dev
,
147 &ux500_dmaengine_pcm_config
,
148 SND_DMAENGINE_PCM_FLAG_NO_RESIDUE
|
149 SND_DMAENGINE_PCM_FLAG_COMPAT
|
150 SND_DMAENGINE_PCM_FLAG_NO_DT
);
153 "%s: ERROR: Failed to register platform '%s' (%d)!\n",
154 __func__
, pdev
->name
, ret
);
160 EXPORT_SYMBOL_GPL(ux500_pcm_register_platform
);
162 int ux500_pcm_unregister_platform(struct platform_device
*pdev
)
164 snd_dmaengine_pcm_unregister(&pdev
->dev
);
167 EXPORT_SYMBOL_GPL(ux500_pcm_unregister_platform
);