diff options
author | Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> | 2014-06-22 20:55:59 -0400 |
---|---|---|
committer | Mark Brown <broonie@linaro.org> | 2014-06-28 09:41:18 -0400 |
commit | 8457e0e9e274cae4898f84dd5aaeb5d2098126c8 (patch) | |
tree | c014473b23d6d09f79c061f4b9f444a2d69fdfe8 | |
parent | d403e24908836cf80531519530a9be84426e3a3f (diff) |
ASoC: fsi: use dmaengine_prep_dma_cyclic() for DMA transfer
Current FSI driver is using DMAEngine directly,
but, ASoC is requesting to use common DMA transfer method,
like snd_dmaengine_pcm_trigger() or dmaengine_pcm_ops.
It is difficult to switch at this point, since Renesas
driver is also supporting PIO transfer.
This patch uses dmaengine_prep_dma_cyclic() instead
of dmaengine_prep_slave_single().
It is used in requested method,
and is good first step to switch over.
Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Signed-off-by: Mark Brown <broonie@linaro.org>
-rw-r--r-- | sound/soc/sh/fsi.c | 94 |
1 files changed, 27 insertions, 67 deletions
diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c index 820a40833c04..a57eb96e57eb 100644 --- a/sound/soc/sh/fsi.c +++ b/sound/soc/sh/fsi.c | |||
@@ -232,10 +232,7 @@ struct fsi_stream { | |||
232 | * these are for DMAEngine | 232 | * these are for DMAEngine |
233 | */ | 233 | */ |
234 | struct dma_chan *chan; | 234 | struct dma_chan *chan; |
235 | struct work_struct work; | ||
236 | int dma_id; | 235 | int dma_id; |
237 | int loop_cnt; | ||
238 | int additional_pos; | ||
239 | }; | 236 | }; |
240 | 237 | ||
241 | struct fsi_clk { | 238 | struct fsi_clk { |
@@ -1281,24 +1278,9 @@ static int fsi_dma_init(struct fsi_priv *fsi, struct fsi_stream *io) | |||
1281 | io->bus_option = BUSOP_SET(24, PACKAGE_24BITBUS_BACK) | | 1278 | io->bus_option = BUSOP_SET(24, PACKAGE_24BITBUS_BACK) | |
1282 | BUSOP_SET(16, PACKAGE_16BITBUS_STREAM); | 1279 | BUSOP_SET(16, PACKAGE_16BITBUS_STREAM); |
1283 | 1280 | ||
1284 | io->loop_cnt = 2; /* push 1st, 2nd period first, then 3rd, 4th... */ | ||
1285 | io->additional_pos = 0; | ||
1286 | |||
1287 | return 0; | 1281 | return 0; |
1288 | } | 1282 | } |
1289 | 1283 | ||
1290 | static dma_addr_t fsi_dma_get_area(struct fsi_stream *io, int additional) | ||
1291 | { | ||
1292 | struct snd_pcm_runtime *runtime = io->substream->runtime; | ||
1293 | int period = io->period_pos + additional; | ||
1294 | |||
1295 | if (period >= runtime->periods) | ||
1296 | period = 0; | ||
1297 | |||
1298 | return runtime->dma_addr + | ||
1299 | samples_to_bytes(runtime, period * io->period_samples); | ||
1300 | } | ||
1301 | |||
1302 | static void fsi_dma_complete(void *data) | 1284 | static void fsi_dma_complete(void *data) |
1303 | { | 1285 | { |
1304 | struct fsi_stream *io = (struct fsi_stream *)data; | 1286 | struct fsi_stream *io = (struct fsi_stream *)data; |
@@ -1307,53 +1289,37 @@ static void fsi_dma_complete(void *data) | |||
1307 | fsi_pointer_update(io, io->period_samples); | 1289 | fsi_pointer_update(io, io->period_samples); |
1308 | 1290 | ||
1309 | fsi_count_fifo_err(fsi); | 1291 | fsi_count_fifo_err(fsi); |
1310 | fsi_stream_transfer(io); | ||
1311 | } | 1292 | } |
1312 | 1293 | ||
1313 | static void fsi_dma_do_work(struct work_struct *work) | 1294 | static int fsi_dma_transfer(struct fsi_priv *fsi, struct fsi_stream *io) |
1314 | { | 1295 | { |
1315 | struct fsi_stream *io = container_of(work, struct fsi_stream, work); | 1296 | struct snd_soc_dai *dai = fsi_get_dai(io->substream); |
1316 | struct fsi_priv *fsi = fsi_stream_to_priv(io); | 1297 | struct snd_pcm_substream *substream = io->substream; |
1317 | struct snd_soc_dai *dai; | ||
1318 | struct dma_async_tx_descriptor *desc; | 1298 | struct dma_async_tx_descriptor *desc; |
1319 | struct snd_pcm_runtime *runtime; | ||
1320 | enum dma_data_direction dir; | ||
1321 | int is_play = fsi_stream_is_play(fsi, io); | 1299 | int is_play = fsi_stream_is_play(fsi, io); |
1322 | int len, i; | 1300 | enum dma_data_direction dir = is_play ? DMA_TO_DEVICE : DMA_FROM_DEVICE; |
1323 | dma_addr_t buf; | 1301 | int ret = -EIO; |
1324 | 1302 | ||
1325 | if (!fsi_stream_is_working(fsi, io)) | 1303 | desc = dmaengine_prep_dma_cyclic(io->chan, |
1326 | return; | 1304 | substream->runtime->dma_addr, |
1327 | 1305 | snd_pcm_lib_buffer_bytes(substream), | |
1328 | dai = fsi_get_dai(io->substream); | 1306 | snd_pcm_lib_period_bytes(substream), |
1329 | runtime = io->substream->runtime; | 1307 | dir, |
1330 | dir = is_play ? DMA_TO_DEVICE : DMA_FROM_DEVICE; | 1308 | DMA_PREP_INTERRUPT | DMA_CTRL_ACK); |
1331 | len = samples_to_bytes(runtime, io->period_samples); | 1309 | if (!desc) { |
1332 | 1310 | dev_err(dai->dev, "dmaengine_prep_dma_cyclic() fail\n"); | |
1333 | for (i = 0; i < io->loop_cnt; i++) { | 1311 | goto fsi_dma_transfer_err; |
1334 | buf = fsi_dma_get_area(io, io->additional_pos); | 1312 | } |
1335 | |||
1336 | desc = dmaengine_prep_slave_single(io->chan, buf, len, dir, | ||
1337 | DMA_PREP_INTERRUPT | DMA_CTRL_ACK); | ||
1338 | if (!desc) { | ||
1339 | dev_err(dai->dev, "dmaengine_prep_slave_sg() fail\n"); | ||
1340 | return; | ||
1341 | } | ||
1342 | |||
1343 | desc->callback = fsi_dma_complete; | ||
1344 | desc->callback_param = io; | ||
1345 | |||
1346 | if (dmaengine_submit(desc) < 0) { | ||
1347 | dev_err(dai->dev, "tx_submit() fail\n"); | ||
1348 | return; | ||
1349 | } | ||
1350 | 1313 | ||
1351 | dma_async_issue_pending(io->chan); | 1314 | desc->callback = fsi_dma_complete; |
1315 | desc->callback_param = io; | ||
1352 | 1316 | ||
1353 | io->additional_pos = 1; | 1317 | if (dmaengine_submit(desc) < 0) { |
1318 | dev_err(dai->dev, "tx_submit() fail\n"); | ||
1319 | goto fsi_dma_transfer_err; | ||
1354 | } | 1320 | } |
1355 | 1321 | ||
1356 | io->loop_cnt = 1; | 1322 | dma_async_issue_pending(io->chan); |
1357 | 1323 | ||
1358 | /* | 1324 | /* |
1359 | * FIXME | 1325 | * FIXME |
@@ -1370,13 +1336,11 @@ static void fsi_dma_do_work(struct work_struct *work) | |||
1370 | fsi_reg_write(fsi, DIFF_ST, 0); | 1336 | fsi_reg_write(fsi, DIFF_ST, 0); |
1371 | } | 1337 | } |
1372 | } | 1338 | } |
1373 | } | ||
1374 | 1339 | ||
1375 | static int fsi_dma_transfer(struct fsi_priv *fsi, struct fsi_stream *io) | 1340 | ret = 0; |
1376 | { | ||
1377 | schedule_work(&io->work); | ||
1378 | 1341 | ||
1379 | return 0; | 1342 | fsi_dma_transfer_err: |
1343 | return ret; | ||
1380 | } | 1344 | } |
1381 | 1345 | ||
1382 | static int fsi_dma_push_start_stop(struct fsi_priv *fsi, struct fsi_stream *io, | 1346 | static int fsi_dma_push_start_stop(struct fsi_priv *fsi, struct fsi_stream *io, |
@@ -1437,15 +1401,11 @@ static int fsi_dma_probe(struct fsi_priv *fsi, struct fsi_stream *io, struct dev | |||
1437 | return fsi_stream_probe(fsi, dev); | 1401 | return fsi_stream_probe(fsi, dev); |
1438 | } | 1402 | } |
1439 | 1403 | ||
1440 | INIT_WORK(&io->work, fsi_dma_do_work); | ||
1441 | |||
1442 | return 0; | 1404 | return 0; |
1443 | } | 1405 | } |
1444 | 1406 | ||
1445 | static int fsi_dma_remove(struct fsi_priv *fsi, struct fsi_stream *io) | 1407 | static int fsi_dma_remove(struct fsi_priv *fsi, struct fsi_stream *io) |
1446 | { | 1408 | { |
1447 | cancel_work_sync(&io->work); | ||
1448 | |||
1449 | fsi_stream_stop(fsi, io); | 1409 | fsi_stream_stop(fsi, io); |
1450 | 1410 | ||
1451 | if (io->chan) | 1411 | if (io->chan) |
@@ -1618,9 +1578,9 @@ static int fsi_dai_trigger(struct snd_pcm_substream *substream, int cmd, | |||
1618 | if (!ret) | 1578 | if (!ret) |
1619 | ret = fsi_hw_startup(fsi, io, dai->dev); | 1579 | ret = fsi_hw_startup(fsi, io, dai->dev); |
1620 | if (!ret) | 1580 | if (!ret) |
1621 | ret = fsi_stream_transfer(io); | 1581 | ret = fsi_stream_start(fsi, io); |
1622 | if (!ret) | 1582 | if (!ret) |
1623 | fsi_stream_start(fsi, io); | 1583 | ret = fsi_stream_transfer(io); |
1624 | break; | 1584 | break; |
1625 | case SNDRV_PCM_TRIGGER_STOP: | 1585 | case SNDRV_PCM_TRIGGER_STOP: |
1626 | if (!ret) | 1586 | if (!ret) |