diff options
author | Mark Brown <broonie@linaro.org> | 2013-08-30 06:04:22 -0400 |
---|---|---|
committer | Mark Brown <broonie@linaro.org> | 2013-08-30 06:04:22 -0400 |
commit | 812e6bbf2caea2c2e55b5838f1148f4a577944ee (patch) | |
tree | 08cc94b795fc676f4cab3b9a4d02805907ddd52f /sound | |
parent | 429aff708200fdf971c51c4b37cfd9fbc8e49991 (diff) | |
parent | 53110a256a334c5e01db2d94c5306b4880a9180e (diff) |
Merge remote-tracking branch 'asoc/topic/fsi' into tmp
Diffstat (limited to 'sound')
-rw-r--r-- | sound/soc/sh/fsi.c | 51 |
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 | ||
240 | struct fsi_clk { | 242 | struct 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 | ||
1308 | static dma_addr_t fsi_dma_get_area(struct fsi_stream *io) | 1312 | static 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 | ||
1315 | static void fsi_dma_complete(void *data) | 1323 | static 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 |