aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKuninori Morimoto <kuninori.morimoto.gx@renesas.com>2014-06-22 20:55:59 -0400
committerMark Brown <broonie@linaro.org>2014-06-28 09:41:18 -0400
commit8457e0e9e274cae4898f84dd5aaeb5d2098126c8 (patch)
treec014473b23d6d09f79c061f4b9f444a2d69fdfe8
parentd403e24908836cf80531519530a9be84426e3a3f (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.c94
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
241struct fsi_clk { 238struct 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
1290static 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
1302static void fsi_dma_complete(void *data) 1284static 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
1313static void fsi_dma_do_work(struct work_struct *work) 1294static 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
1375static 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; 1342fsi_dma_transfer_err:
1343 return ret;
1380} 1344}
1381 1345
1382static int fsi_dma_push_start_stop(struct fsi_priv *fsi, struct fsi_stream *io, 1346static 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
1445static int fsi_dma_remove(struct fsi_priv *fsi, struct fsi_stream *io) 1407static 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)