aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorKuninori Morimoto <kuninori.morimoto.gx@renesas.com>2013-08-26 02:36:23 -0400
committerMark Brown <broonie@linaro.org>2013-08-26 08:02:36 -0400
commit53110a256a334c5e01db2d94c5306b4880a9180e (patch)
tree47fece24f8cffb48c415d67edacf0c3966e9a2aa /sound
parentb36f4be3de1b123d8601de062e7dbfc904f305fb (diff)
ASoC: fsi: reserve prefetch period on DMA transferring
Current FSI is supporting DMAEngine transfer, but, it needs to use work queue. Therefore, DMA transfer settings might be late if there is heavy task. This patch reserves next period beforehand on DMA transfer function. Android sound will be breaking up without this patch. Tested-by: Tomohito Esaki <etom@igel.co.jp> Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> Signed-off-by: Mark Brown <broonie@linaro.org>
Diffstat (limited to 'sound')
-rw-r--r--sound/soc/sh/fsi.c51
1 files changed, 33 insertions, 18 deletions
diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c
index 30390260bb67..b33ca7cd085b 100644
--- a/sound/soc/sh/fsi.c
+++ b/sound/soc/sh/fsi.c
@@ -235,6 +235,8 @@ struct fsi_stream {
235 struct sh_dmae_slave slave; /* see fsi_handler_init() */ 235 struct sh_dmae_slave slave; /* see fsi_handler_init() */
236 struct work_struct work; 236 struct work_struct work;
237 dma_addr_t dma; 237 dma_addr_t dma;
238 int loop_cnt;
239 int additional_pos;
238}; 240};
239 241
240struct fsi_clk { 242struct fsi_clk {
@@ -1289,6 +1291,8 @@ static int fsi_dma_init(struct fsi_priv *fsi, struct fsi_stream *io)
1289 io->bus_option = BUSOP_SET(24, PACKAGE_24BITBUS_BACK) | 1291 io->bus_option = BUSOP_SET(24, PACKAGE_24BITBUS_BACK) |
1290 BUSOP_SET(16, PACKAGE_16BITBUS_STREAM); 1292 BUSOP_SET(16, PACKAGE_16BITBUS_STREAM);
1291 1293
1294 io->loop_cnt = 2; /* push 1st, 2nd period first, then 3rd, 4th... */
1295 io->additional_pos = 0;
1292 io->dma = dma_map_single(dai->dev, runtime->dma_area, 1296 io->dma = dma_map_single(dai->dev, runtime->dma_area,
1293 snd_pcm_lib_buffer_bytes(io->substream), dir); 1297 snd_pcm_lib_buffer_bytes(io->substream), dir);
1294 return 0; 1298 return 0;
@@ -1305,11 +1309,15 @@ static int fsi_dma_quit(struct fsi_priv *fsi, struct fsi_stream *io)
1305 return 0; 1309 return 0;
1306} 1310}
1307 1311
1308static dma_addr_t fsi_dma_get_area(struct fsi_stream *io) 1312static dma_addr_t fsi_dma_get_area(struct fsi_stream *io, int additional)
1309{ 1313{
1310 struct snd_pcm_runtime *runtime = io->substream->runtime; 1314 struct snd_pcm_runtime *runtime = io->substream->runtime;
1315 int period = io->period_pos + additional;
1311 1316
1312 return io->dma + samples_to_bytes(runtime, io->buff_sample_pos); 1317 if (period >= runtime->periods)
1318 period = 0;
1319
1320 return io->dma + samples_to_bytes(runtime, period * io->period_samples);
1313} 1321}
1314 1322
1315static void fsi_dma_complete(void *data) 1323static void fsi_dma_complete(void *data)
@@ -1321,7 +1329,7 @@ static void fsi_dma_complete(void *data)
1321 enum dma_data_direction dir = fsi_stream_is_play(fsi, io) ? 1329 enum dma_data_direction dir = fsi_stream_is_play(fsi, io) ?
1322 DMA_TO_DEVICE : DMA_FROM_DEVICE; 1330 DMA_TO_DEVICE : DMA_FROM_DEVICE;
1323 1331
1324 dma_sync_single_for_cpu(dai->dev, fsi_dma_get_area(io), 1332 dma_sync_single_for_cpu(dai->dev, fsi_dma_get_area(io, 0),
1325 samples_to_bytes(runtime, io->period_samples), dir); 1333 samples_to_bytes(runtime, io->period_samples), dir);
1326 1334
1327 io->buff_sample_pos += io->period_samples; 1335 io->buff_sample_pos += io->period_samples;
@@ -1347,7 +1355,7 @@ static void fsi_dma_do_work(struct work_struct *work)
1347 struct snd_pcm_runtime *runtime; 1355 struct snd_pcm_runtime *runtime;
1348 enum dma_data_direction dir; 1356 enum dma_data_direction dir;
1349 int is_play = fsi_stream_is_play(fsi, io); 1357 int is_play = fsi_stream_is_play(fsi, io);
1350 int len; 1358 int len, i;
1351 dma_addr_t buf; 1359 dma_addr_t buf;
1352 1360
1353 if (!fsi_stream_is_working(fsi, io)) 1361 if (!fsi_stream_is_working(fsi, io))
@@ -1357,26 +1365,33 @@ static void fsi_dma_do_work(struct work_struct *work)
1357 runtime = io->substream->runtime; 1365 runtime = io->substream->runtime;
1358 dir = is_play ? DMA_TO_DEVICE : DMA_FROM_DEVICE; 1366 dir = is_play ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
1359 len = samples_to_bytes(runtime, io->period_samples); 1367 len = samples_to_bytes(runtime, io->period_samples);
1360 buf = fsi_dma_get_area(io);
1361 1368
1362 dma_sync_single_for_device(dai->dev, buf, len, dir); 1369 for (i = 0; i < io->loop_cnt; i++) {
1370 buf = fsi_dma_get_area(io, io->additional_pos);
1363 1371
1364 desc = dmaengine_prep_slave_single(io->chan, buf, len, dir, 1372 dma_sync_single_for_device(dai->dev, buf, len, dir);
1365 DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
1366 if (!desc) {
1367 dev_err(dai->dev, "dmaengine_prep_slave_sg() fail\n");
1368 return;
1369 }
1370 1373
1371 desc->callback = fsi_dma_complete; 1374 desc = dmaengine_prep_slave_single(io->chan, buf, len, dir,
1372 desc->callback_param = io; 1375 DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
1376 if (!desc) {
1377 dev_err(dai->dev, "dmaengine_prep_slave_sg() fail\n");
1378 return;
1379 }
1373 1380
1374 if (dmaengine_submit(desc) < 0) { 1381 desc->callback = fsi_dma_complete;
1375 dev_err(dai->dev, "tx_submit() fail\n"); 1382 desc->callback_param = io;
1376 return; 1383
1384 if (dmaengine_submit(desc) < 0) {
1385 dev_err(dai->dev, "tx_submit() fail\n");
1386 return;
1387 }
1388
1389 dma_async_issue_pending(io->chan);
1390
1391 io->additional_pos = 1;
1377 } 1392 }
1378 1393
1379 dma_async_issue_pending(io->chan); 1394 io->loop_cnt = 1;
1380 1395
1381 /* 1396 /*
1382 * FIXME 1397 * FIXME