aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorMark Brown <broonie@linaro.org>2013-08-30 06:04:22 -0400
committerMark Brown <broonie@linaro.org>2013-08-30 06:04:22 -0400
commit812e6bbf2caea2c2e55b5838f1148f4a577944ee (patch)
tree08cc94b795fc676f4cab3b9a4d02805907ddd52f /sound
parent429aff708200fdf971c51c4b37cfd9fbc8e49991 (diff)
parent53110a256a334c5e01db2d94c5306b4880a9180e (diff)
Merge remote-tracking branch 'asoc/topic/fsi' into tmp
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