aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/omap
diff options
context:
space:
mode:
authorEduardo Valentin <eduardo.valentin@nokia.com>2009-08-20 09:18:25 -0400
committerMark Brown <broonie@opensource.wolfsonmicro.com>2009-08-20 15:10:29 -0400
commitcaebc0cb3ba1e88f5311fbe7aa58b8dff18dd763 (patch)
tree875d14cdc7603da1fba730b2ac419cdb642afd73 /sound/soc/omap
parentca6e2ce08679c094878d7f39a0349a7db1d13675 (diff)
ASoC: OMAP: Use McBSP threshold to playback and capture
This patch changes the way DMA is done in omap-pcm.c in order to reduce power consumption. There is no need to have so much SW control in order to have DMA in idle state during audio streaming. Configuring McBSP threshold value and DMA to FRAME_SYNC are sufficient. Signed-off-by: Eduardo Valentin <eduardo.valentin@nokia.com> Acked-by: Jarkko Nikula <jhnikula@gmail.com> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'sound/soc/omap')
-rw-r--r--sound/soc/omap/omap-mcbsp.c47
-rw-r--r--sound/soc/omap/omap-pcm.c7
-rw-r--r--sound/soc/omap/omap-pcm.h2
3 files changed, 49 insertions, 7 deletions
diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c
index 6e855080e6ea..580de5a8dba6 100644
--- a/sound/soc/omap/omap-mcbsp.c
+++ b/sound/soc/omap/omap-mcbsp.c
@@ -139,28 +139,59 @@ static const unsigned long omap34xx_mcbsp_port[][2] = {
139static const unsigned long omap34xx_mcbsp_port[][2] = {}; 139static const unsigned long omap34xx_mcbsp_port[][2] = {};
140#endif 140#endif
141 141
142static void omap_mcbsp_set_threshold(struct snd_pcm_substream *substream)
143{
144 struct snd_soc_pcm_runtime *rtd = substream->private_data;
145 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
146 struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
147 int samples = snd_pcm_lib_period_bytes(substream) >> 1;
148
149 /* Configure McBSP internal buffer usage */
150 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
151 omap_mcbsp_set_tx_threshold(mcbsp_data->bus_id, samples - 1);
152 else
153 omap_mcbsp_set_rx_threshold(mcbsp_data->bus_id, samples - 1);
154}
155
142static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream, 156static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream,
143 struct snd_soc_dai *dai) 157 struct snd_soc_dai *dai)
144{ 158{
145 struct snd_soc_pcm_runtime *rtd = substream->private_data; 159 struct snd_soc_pcm_runtime *rtd = substream->private_data;
146 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; 160 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
147 struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data); 161 struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
162 int bus_id = mcbsp_data->bus_id;
148 int err = 0; 163 int err = 0;
149 164
150 if (cpu_is_omap343x() && mcbsp_data->bus_id == 1) { 165 if (!cpu_dai->active)
166 err = omap_mcbsp_request(bus_id);
167
168 if (cpu_is_omap343x()) {
169 int max_period;
170
151 /* 171 /*
152 * McBSP2 in OMAP3 has 1024 * 32-bit internal audio buffer. 172 * McBSP2 in OMAP3 has 1024 * 32-bit internal audio buffer.
153 * Set constraint for minimum buffer size to the same than FIFO 173 * Set constraint for minimum buffer size to the same than FIFO
154 * size in order to avoid underruns in playback startup because 174 * size in order to avoid underruns in playback startup because
155 * HW is keeping the DMA request active until FIFO is filled. 175 * HW is keeping the DMA request active until FIFO is filled.
156 */ 176 */
177 if (bus_id == 1)
178 snd_pcm_hw_constraint_minmax(substream->runtime,
179 SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
180 4096, UINT_MAX);
181
182 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
183 max_period = omap_mcbsp_get_max_tx_threshold(bus_id);
184 else
185 max_period = omap_mcbsp_get_max_rx_threshold(bus_id);
186
187 max_period++;
188 max_period <<= 1;
189
157 snd_pcm_hw_constraint_minmax(substream->runtime, 190 snd_pcm_hw_constraint_minmax(substream->runtime,
158 SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 4096, UINT_MAX); 191 SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
192 32, max_period);
159 } 193 }
160 194
161 if (!cpu_dai->active)
162 err = omap_mcbsp_request(mcbsp_data->bus_id);
163
164 return err; 195 return err;
165} 196}
166 197
@@ -220,7 +251,7 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
220 struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data); 251 struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
221 struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs; 252 struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs;
222 int dma, bus_id = mcbsp_data->bus_id, id = cpu_dai->id; 253 int dma, bus_id = mcbsp_data->bus_id, id = cpu_dai->id;
223 int wlen, channels, wpf; 254 int wlen, channels, wpf, sync_mode = OMAP_DMA_SYNC_ELEMENT;
224 unsigned long port; 255 unsigned long port;
225 unsigned int format; 256 unsigned int format;
226 257
@@ -236,6 +267,9 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
236 } else if (cpu_is_omap343x()) { 267 } else if (cpu_is_omap343x()) {
237 dma = omap24xx_dma_reqs[bus_id][substream->stream]; 268 dma = omap24xx_dma_reqs[bus_id][substream->stream];
238 port = omap34xx_mcbsp_port[bus_id][substream->stream]; 269 port = omap34xx_mcbsp_port[bus_id][substream->stream];
270 omap_mcbsp_dai_dma_params[id][substream->stream].set_threshold =
271 omap_mcbsp_set_threshold;
272 sync_mode = OMAP_DMA_SYNC_FRAME;
239 } else { 273 } else {
240 return -ENODEV; 274 return -ENODEV;
241 } 275 }
@@ -243,6 +277,7 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
243 substream->stream ? "Audio Capture" : "Audio Playback"; 277 substream->stream ? "Audio Capture" : "Audio Playback";
244 omap_mcbsp_dai_dma_params[id][substream->stream].dma_req = dma; 278 omap_mcbsp_dai_dma_params[id][substream->stream].dma_req = dma;
245 omap_mcbsp_dai_dma_params[id][substream->stream].port_addr = port; 279 omap_mcbsp_dai_dma_params[id][substream->stream].port_addr = port;
280 omap_mcbsp_dai_dma_params[id][substream->stream].sync_mode = sync_mode;
246 cpu_dai->dma_data = &omap_mcbsp_dai_dma_params[id][substream->stream]; 281 cpu_dai->dma_data = &omap_mcbsp_dai_dma_params[id][substream->stream];
247 282
248 if (mcbsp_data->configured) { 283 if (mcbsp_data->configured) {
diff --git a/sound/soc/omap/omap-pcm.c b/sound/soc/omap/omap-pcm.c
index b9633d5a9557..5735945788bf 100644
--- a/sound/soc/omap/omap-pcm.c
+++ b/sound/soc/omap/omap-pcm.c
@@ -162,7 +162,7 @@ static int omap_pcm_prepare(struct snd_pcm_substream *substream)
162 */ 162 */
163 dma_params.data_type = OMAP_DMA_DATA_TYPE_S16; 163 dma_params.data_type = OMAP_DMA_DATA_TYPE_S16;
164 dma_params.trigger = dma_data->dma_req; 164 dma_params.trigger = dma_data->dma_req;
165 dma_params.sync_mode = OMAP_DMA_SYNC_ELEMENT; 165 dma_params.sync_mode = dma_data->sync_mode;
166 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 166 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
167 dma_params.src_amode = OMAP_DMA_AMODE_POST_INC; 167 dma_params.src_amode = OMAP_DMA_AMODE_POST_INC;
168 dma_params.dst_amode = OMAP_DMA_AMODE_CONSTANT; 168 dma_params.dst_amode = OMAP_DMA_AMODE_CONSTANT;
@@ -205,6 +205,7 @@ static int omap_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
205{ 205{
206 struct snd_pcm_runtime *runtime = substream->runtime; 206 struct snd_pcm_runtime *runtime = substream->runtime;
207 struct omap_runtime_data *prtd = runtime->private_data; 207 struct omap_runtime_data *prtd = runtime->private_data;
208 struct omap_pcm_dma_data *dma_data = prtd->dma_data;
208 unsigned long flags; 209 unsigned long flags;
209 int ret = 0; 210 int ret = 0;
210 211
@@ -214,6 +215,10 @@ static int omap_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
214 case SNDRV_PCM_TRIGGER_RESUME: 215 case SNDRV_PCM_TRIGGER_RESUME:
215 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 216 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
216 prtd->period_index = 0; 217 prtd->period_index = 0;
218 /* Configure McBSP internal buffer usage */
219 if (dma_data->set_threshold)
220 dma_data->set_threshold(substream);
221
217 omap_start_dma(prtd->dma_ch); 222 omap_start_dma(prtd->dma_ch);
218 break; 223 break;
219 224
diff --git a/sound/soc/omap/omap-pcm.h b/sound/soc/omap/omap-pcm.h
index 8d9d26916b05..38a821dd4118 100644
--- a/sound/soc/omap/omap-pcm.h
+++ b/sound/soc/omap/omap-pcm.h
@@ -29,6 +29,8 @@ struct omap_pcm_dma_data {
29 char *name; /* stream identifier */ 29 char *name; /* stream identifier */
30 int dma_req; /* DMA request line */ 30 int dma_req; /* DMA request line */
31 unsigned long port_addr; /* transmit/receive register */ 31 unsigned long port_addr; /* transmit/receive register */
32 int sync_mode; /* DMA sync mode */
33 void (*set_threshold)(struct snd_pcm_substream *substream);
32}; 34};
33 35
34extern struct snd_soc_platform omap_soc_platform; 36extern struct snd_soc_platform omap_soc_platform;