diff options
Diffstat (limited to 'sound/soc/sh/fsi.c')
-rw-r--r-- | sound/soc/sh/fsi.c | 201 |
1 files changed, 58 insertions, 143 deletions
diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c index 710a079a7377..c76344350e44 100644 --- a/sound/soc/sh/fsi.c +++ b/sound/soc/sh/fsi.c | |||
@@ -232,11 +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 | dma_addr_t dma; | ||
237 | int dma_id; | 235 | int dma_id; |
238 | int loop_cnt; | ||
239 | int additional_pos; | ||
240 | }; | 236 | }; |
241 | 237 | ||
242 | struct fsi_clk { | 238 | struct fsi_clk { |
@@ -264,12 +260,12 @@ struct fsi_priv { | |||
264 | u32 fmt; | 260 | u32 fmt; |
265 | 261 | ||
266 | int chan_num:16; | 262 | int chan_num:16; |
267 | int clk_master:1; | 263 | unsigned int clk_master:1; |
268 | int clk_cpg:1; | 264 | unsigned int clk_cpg:1; |
269 | int spdif:1; | 265 | unsigned int spdif:1; |
270 | int enable_stream:1; | 266 | unsigned int enable_stream:1; |
271 | int bit_clk_inv:1; | 267 | unsigned int bit_clk_inv:1; |
272 | int lr_clk_inv:1; | 268 | unsigned int lr_clk_inv:1; |
273 | }; | 269 | }; |
274 | 270 | ||
275 | struct fsi_stream_handler { | 271 | struct fsi_stream_handler { |
@@ -1042,6 +1038,26 @@ static int fsi_clk_set_rate_cpg(struct device *dev, | |||
1042 | return ret; | 1038 | return ret; |
1043 | } | 1039 | } |
1044 | 1040 | ||
1041 | static void fsi_pointer_update(struct fsi_stream *io, int size) | ||
1042 | { | ||
1043 | io->buff_sample_pos += size; | ||
1044 | |||
1045 | if (io->buff_sample_pos >= | ||
1046 | io->period_samples * (io->period_pos + 1)) { | ||
1047 | struct snd_pcm_substream *substream = io->substream; | ||
1048 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
1049 | |||
1050 | io->period_pos++; | ||
1051 | |||
1052 | if (io->period_pos >= runtime->periods) { | ||
1053 | io->buff_sample_pos = 0; | ||
1054 | io->period_pos = 0; | ||
1055 | } | ||
1056 | |||
1057 | snd_pcm_period_elapsed(substream); | ||
1058 | } | ||
1059 | } | ||
1060 | |||
1045 | /* | 1061 | /* |
1046 | * pio data transfer handler | 1062 | * pio data transfer handler |
1047 | */ | 1063 | */ |
@@ -1108,31 +1124,11 @@ static int fsi_pio_transfer(struct fsi_priv *fsi, struct fsi_stream *io, | |||
1108 | void (*run32)(struct fsi_priv *fsi, u8 *buf, int samples), | 1124 | void (*run32)(struct fsi_priv *fsi, u8 *buf, int samples), |
1109 | int samples) | 1125 | int samples) |
1110 | { | 1126 | { |
1111 | struct snd_pcm_runtime *runtime; | ||
1112 | struct snd_pcm_substream *substream; | ||
1113 | u8 *buf; | 1127 | u8 *buf; |
1114 | int over_period; | ||
1115 | 1128 | ||
1116 | if (!fsi_stream_is_working(fsi, io)) | 1129 | if (!fsi_stream_is_working(fsi, io)) |
1117 | return -EINVAL; | 1130 | return -EINVAL; |
1118 | 1131 | ||
1119 | over_period = 0; | ||
1120 | substream = io->substream; | ||
1121 | runtime = substream->runtime; | ||
1122 | |||
1123 | /* FSI FIFO has limit. | ||
1124 | * So, this driver can not send periods data at a time | ||
1125 | */ | ||
1126 | if (io->buff_sample_pos >= | ||
1127 | io->period_samples * (io->period_pos + 1)) { | ||
1128 | |||
1129 | over_period = 1; | ||
1130 | io->period_pos = (io->period_pos + 1) % runtime->periods; | ||
1131 | |||
1132 | if (0 == io->period_pos) | ||
1133 | io->buff_sample_pos = 0; | ||
1134 | } | ||
1135 | |||
1136 | buf = fsi_pio_get_area(fsi, io); | 1132 | buf = fsi_pio_get_area(fsi, io); |
1137 | 1133 | ||
1138 | switch (io->sample_width) { | 1134 | switch (io->sample_width) { |
@@ -1146,11 +1142,7 @@ static int fsi_pio_transfer(struct fsi_priv *fsi, struct fsi_stream *io, | |||
1146 | return -EINVAL; | 1142 | return -EINVAL; |
1147 | } | 1143 | } |
1148 | 1144 | ||
1149 | /* update buff_sample_pos */ | 1145 | fsi_pointer_update(io, samples); |
1150 | io->buff_sample_pos += samples; | ||
1151 | |||
1152 | if (over_period) | ||
1153 | snd_pcm_period_elapsed(substream); | ||
1154 | 1146 | ||
1155 | return 0; | 1147 | return 0; |
1156 | } | 1148 | } |
@@ -1279,11 +1271,6 @@ static irqreturn_t fsi_interrupt(int irq, void *data) | |||
1279 | */ | 1271 | */ |
1280 | static int fsi_dma_init(struct fsi_priv *fsi, struct fsi_stream *io) | 1272 | static int fsi_dma_init(struct fsi_priv *fsi, struct fsi_stream *io) |
1281 | { | 1273 | { |
1282 | struct snd_pcm_runtime *runtime = io->substream->runtime; | ||
1283 | struct snd_soc_dai *dai = fsi_get_dai(io->substream); | ||
1284 | enum dma_data_direction dir = fsi_stream_is_play(fsi, io) ? | ||
1285 | DMA_TO_DEVICE : DMA_FROM_DEVICE; | ||
1286 | |||
1287 | /* | 1274 | /* |
1288 | * 24bit data : 24bit bus / package in back | 1275 | * 24bit data : 24bit bus / package in back |
1289 | * 16bit data : 16bit bus / stream mode | 1276 | * 16bit data : 16bit bus / stream mode |
@@ -1291,107 +1278,48 @@ static int fsi_dma_init(struct fsi_priv *fsi, struct fsi_stream *io) | |||
1291 | io->bus_option = BUSOP_SET(24, PACKAGE_24BITBUS_BACK) | | 1278 | io->bus_option = BUSOP_SET(24, PACKAGE_24BITBUS_BACK) | |
1292 | BUSOP_SET(16, PACKAGE_16BITBUS_STREAM); | 1279 | BUSOP_SET(16, PACKAGE_16BITBUS_STREAM); |
1293 | 1280 | ||
1294 | io->loop_cnt = 2; /* push 1st, 2nd period first, then 3rd, 4th... */ | ||
1295 | io->additional_pos = 0; | ||
1296 | io->dma = dma_map_single(dai->dev, runtime->dma_area, | ||
1297 | snd_pcm_lib_buffer_bytes(io->substream), dir); | ||
1298 | return 0; | 1281 | return 0; |
1299 | } | 1282 | } |
1300 | 1283 | ||
1301 | static int fsi_dma_quit(struct fsi_priv *fsi, struct fsi_stream *io) | ||
1302 | { | ||
1303 | struct snd_soc_dai *dai = fsi_get_dai(io->substream); | ||
1304 | enum dma_data_direction dir = fsi_stream_is_play(fsi, io) ? | ||
1305 | DMA_TO_DEVICE : DMA_FROM_DEVICE; | ||
1306 | |||
1307 | dma_unmap_single(dai->dev, io->dma, | ||
1308 | snd_pcm_lib_buffer_bytes(io->substream), dir); | ||
1309 | return 0; | ||
1310 | } | ||
1311 | |||
1312 | static dma_addr_t fsi_dma_get_area(struct fsi_stream *io, int additional) | ||
1313 | { | ||
1314 | struct snd_pcm_runtime *runtime = io->substream->runtime; | ||
1315 | int period = io->period_pos + additional; | ||
1316 | |||
1317 | if (period >= runtime->periods) | ||
1318 | period = 0; | ||
1319 | |||
1320 | return io->dma + samples_to_bytes(runtime, period * io->period_samples); | ||
1321 | } | ||
1322 | |||
1323 | static void fsi_dma_complete(void *data) | 1284 | static void fsi_dma_complete(void *data) |
1324 | { | 1285 | { |
1325 | struct fsi_stream *io = (struct fsi_stream *)data; | 1286 | struct fsi_stream *io = (struct fsi_stream *)data; |
1326 | struct fsi_priv *fsi = fsi_stream_to_priv(io); | 1287 | struct fsi_priv *fsi = fsi_stream_to_priv(io); |
1327 | struct snd_pcm_runtime *runtime = io->substream->runtime; | ||
1328 | struct snd_soc_dai *dai = fsi_get_dai(io->substream); | ||
1329 | enum dma_data_direction dir = fsi_stream_is_play(fsi, io) ? | ||
1330 | DMA_TO_DEVICE : DMA_FROM_DEVICE; | ||
1331 | 1288 | ||
1332 | dma_sync_single_for_cpu(dai->dev, fsi_dma_get_area(io, 0), | 1289 | fsi_pointer_update(io, io->period_samples); |
1333 | samples_to_bytes(runtime, io->period_samples), dir); | ||
1334 | |||
1335 | io->buff_sample_pos += io->period_samples; | ||
1336 | io->period_pos++; | ||
1337 | |||
1338 | if (io->period_pos >= runtime->periods) { | ||
1339 | io->period_pos = 0; | ||
1340 | io->buff_sample_pos = 0; | ||
1341 | } | ||
1342 | 1290 | ||
1343 | fsi_count_fifo_err(fsi); | 1291 | fsi_count_fifo_err(fsi); |
1344 | fsi_stream_transfer(io); | ||
1345 | |||
1346 | snd_pcm_period_elapsed(io->substream); | ||
1347 | } | 1292 | } |
1348 | 1293 | ||
1349 | static void fsi_dma_do_work(struct work_struct *work) | 1294 | static int fsi_dma_transfer(struct fsi_priv *fsi, struct fsi_stream *io) |
1350 | { | 1295 | { |
1351 | struct fsi_stream *io = container_of(work, struct fsi_stream, work); | 1296 | struct snd_soc_dai *dai = fsi_get_dai(io->substream); |
1352 | struct fsi_priv *fsi = fsi_stream_to_priv(io); | 1297 | struct snd_pcm_substream *substream = io->substream; |
1353 | struct snd_soc_dai *dai; | ||
1354 | struct dma_async_tx_descriptor *desc; | 1298 | struct dma_async_tx_descriptor *desc; |
1355 | struct snd_pcm_runtime *runtime; | ||
1356 | enum dma_data_direction dir; | ||
1357 | int is_play = fsi_stream_is_play(fsi, io); | 1299 | int is_play = fsi_stream_is_play(fsi, io); |
1358 | int len, i; | 1300 | enum dma_data_direction dir = is_play ? DMA_TO_DEVICE : DMA_FROM_DEVICE; |
1359 | dma_addr_t buf; | 1301 | int ret = -EIO; |
1360 | 1302 | ||
1361 | if (!fsi_stream_is_working(fsi, io)) | 1303 | desc = dmaengine_prep_dma_cyclic(io->chan, |
1362 | return; | 1304 | substream->runtime->dma_addr, |
1363 | 1305 | snd_pcm_lib_buffer_bytes(substream), | |
1364 | dai = fsi_get_dai(io->substream); | 1306 | snd_pcm_lib_period_bytes(substream), |
1365 | runtime = io->substream->runtime; | 1307 | dir, |
1366 | dir = is_play ? DMA_TO_DEVICE : DMA_FROM_DEVICE; | 1308 | DMA_PREP_INTERRUPT | DMA_CTRL_ACK); |
1367 | len = samples_to_bytes(runtime, io->period_samples); | 1309 | if (!desc) { |
1368 | 1310 | dev_err(dai->dev, "dmaengine_prep_dma_cyclic() fail\n"); | |
1369 | for (i = 0; i < io->loop_cnt; i++) { | 1311 | goto fsi_dma_transfer_err; |
1370 | buf = fsi_dma_get_area(io, io->additional_pos); | 1312 | } |
1371 | |||
1372 | dma_sync_single_for_device(dai->dev, buf, len, dir); | ||
1373 | |||
1374 | desc = dmaengine_prep_slave_single(io->chan, buf, len, dir, | ||
1375 | DMA_PREP_INTERRUPT | DMA_CTRL_ACK); | ||
1376 | if (!desc) { | ||
1377 | dev_err(dai->dev, "dmaengine_prep_slave_sg() fail\n"); | ||
1378 | return; | ||
1379 | } | ||
1380 | |||
1381 | desc->callback = fsi_dma_complete; | ||
1382 | desc->callback_param = io; | ||
1383 | |||
1384 | if (dmaengine_submit(desc) < 0) { | ||
1385 | dev_err(dai->dev, "tx_submit() fail\n"); | ||
1386 | return; | ||
1387 | } | ||
1388 | 1313 | ||
1389 | dma_async_issue_pending(io->chan); | 1314 | desc->callback = fsi_dma_complete; |
1315 | desc->callback_param = io; | ||
1390 | 1316 | ||
1391 | 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; | ||
1392 | } | 1320 | } |
1393 | 1321 | ||
1394 | io->loop_cnt = 1; | 1322 | dma_async_issue_pending(io->chan); |
1395 | 1323 | ||
1396 | /* | 1324 | /* |
1397 | * FIXME | 1325 | * FIXME |
@@ -1408,13 +1336,11 @@ static void fsi_dma_do_work(struct work_struct *work) | |||
1408 | fsi_reg_write(fsi, DIFF_ST, 0); | 1336 | fsi_reg_write(fsi, DIFF_ST, 0); |
1409 | } | 1337 | } |
1410 | } | 1338 | } |
1411 | } | ||
1412 | 1339 | ||
1413 | static int fsi_dma_transfer(struct fsi_priv *fsi, struct fsi_stream *io) | 1340 | ret = 0; |
1414 | { | ||
1415 | schedule_work(&io->work); | ||
1416 | 1341 | ||
1417 | return 0; | 1342 | fsi_dma_transfer_err: |
1343 | return ret; | ||
1418 | } | 1344 | } |
1419 | 1345 | ||
1420 | 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, |
@@ -1475,15 +1401,11 @@ static int fsi_dma_probe(struct fsi_priv *fsi, struct fsi_stream *io, struct dev | |||
1475 | return fsi_stream_probe(fsi, dev); | 1401 | return fsi_stream_probe(fsi, dev); |
1476 | } | 1402 | } |
1477 | 1403 | ||
1478 | INIT_WORK(&io->work, fsi_dma_do_work); | ||
1479 | |||
1480 | return 0; | 1404 | return 0; |
1481 | } | 1405 | } |
1482 | 1406 | ||
1483 | 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) |
1484 | { | 1408 | { |
1485 | cancel_work_sync(&io->work); | ||
1486 | |||
1487 | fsi_stream_stop(fsi, io); | 1409 | fsi_stream_stop(fsi, io); |
1488 | 1410 | ||
1489 | if (io->chan) | 1411 | if (io->chan) |
@@ -1495,7 +1417,6 @@ static int fsi_dma_remove(struct fsi_priv *fsi, struct fsi_stream *io) | |||
1495 | 1417 | ||
1496 | static struct fsi_stream_handler fsi_dma_push_handler = { | 1418 | static struct fsi_stream_handler fsi_dma_push_handler = { |
1497 | .init = fsi_dma_init, | 1419 | .init = fsi_dma_init, |
1498 | .quit = fsi_dma_quit, | ||
1499 | .probe = fsi_dma_probe, | 1420 | .probe = fsi_dma_probe, |
1500 | .transfer = fsi_dma_transfer, | 1421 | .transfer = fsi_dma_transfer, |
1501 | .remove = fsi_dma_remove, | 1422 | .remove = fsi_dma_remove, |
@@ -1657,9 +1578,9 @@ static int fsi_dai_trigger(struct snd_pcm_substream *substream, int cmd, | |||
1657 | if (!ret) | 1578 | if (!ret) |
1658 | ret = fsi_hw_startup(fsi, io, dai->dev); | 1579 | ret = fsi_hw_startup(fsi, io, dai->dev); |
1659 | if (!ret) | 1580 | if (!ret) |
1660 | ret = fsi_stream_transfer(io); | 1581 | ret = fsi_stream_start(fsi, io); |
1661 | if (!ret) | 1582 | if (!ret) |
1662 | fsi_stream_start(fsi, io); | 1583 | ret = fsi_stream_transfer(io); |
1663 | break; | 1584 | break; |
1664 | case SNDRV_PCM_TRIGGER_STOP: | 1585 | case SNDRV_PCM_TRIGGER_STOP: |
1665 | if (!ret) | 1586 | if (!ret) |
@@ -1850,16 +1771,10 @@ static void fsi_pcm_free(struct snd_pcm *pcm) | |||
1850 | 1771 | ||
1851 | static int fsi_pcm_new(struct snd_soc_pcm_runtime *rtd) | 1772 | static int fsi_pcm_new(struct snd_soc_pcm_runtime *rtd) |
1852 | { | 1773 | { |
1853 | struct snd_pcm *pcm = rtd->pcm; | ||
1854 | |||
1855 | /* | ||
1856 | * dont use SNDRV_DMA_TYPE_DEV, since it will oops the SH kernel | ||
1857 | * in MMAP mode (i.e. aplay -M) | ||
1858 | */ | ||
1859 | return snd_pcm_lib_preallocate_pages_for_all( | 1774 | return snd_pcm_lib_preallocate_pages_for_all( |
1860 | pcm, | 1775 | rtd->pcm, |
1861 | SNDRV_DMA_TYPE_CONTINUOUS, | 1776 | SNDRV_DMA_TYPE_DEV, |
1862 | snd_dma_continuous_data(GFP_KERNEL), | 1777 | rtd->card->snd_card->dev, |
1863 | PREALLOC_BUFFER, PREALLOC_BUFFER_MAX); | 1778 | PREALLOC_BUFFER, PREALLOC_BUFFER_MAX); |
1864 | } | 1779 | } |
1865 | 1780 | ||