diff options
author | Mark Brown <broonie@linaro.org> | 2014-08-15 07:51:28 -0400 |
---|---|---|
committer | Mark Brown <broonie@linaro.org> | 2014-08-15 07:51:28 -0400 |
commit | 543c675482bcf1e7b9f85bb1589314f38f60c520 (patch) | |
tree | 904f425393ac99539827d3164d2b0f78ac1607c5 /sound/soc/sh | |
parent | 2fa4a285ddfd39cfa711da3f5e898ec2ce80ef87 (diff) | |
parent | ae34a78c430c37c06404f032fb04e51315204281 (diff) |
Merge tag 'asoc-v3.17' into asoc-linus
ASoC: Updates for v3.17
This has been a pretty exciting release in terms of the framework, we've
finally got support for multiple CODECs attached to a single DAI link
which has been something there's been interest in as long as I've been
working on ASoC. A big thanks to Benoit and Misael for their work on
this.
Otherwise it's been a fairly standard release for development, including
more componentisation work from Lars-Peter and a good selection of both
CODEC and CPU drivers.
- Support for multiple CODECs attached to a single DAI, enabling
systems with for example multiple DAC/speaker drivers on a single
link, contributed by Benoit Cousson based on work from Misael Lopez
Cruz.
- Support for byte controls larger than 256 bytes based on the use of
TLVs contributed by Omair Mohammed Abdullah.
- More componentisation work from Lars-Peter Clausen.
- The remainder of the conversions of CODEC drivers to params_width()
- Drivers for Cirrus Logic CS4265, Freescale i.MX ASRC blocks, Realtek
RT286 and RT5670, Rockchip RK3xxx I2S controllers and Texas Instruments
TAS2552.
- Lots of updates and fixes, especially to the DaVinci, Intel,
Freescale, Realtek, and rcar drivers.
# gpg: Signature made Mon 04 Aug 2014 17:13:21 BST using RSA key ID 7EA229BD
# gpg: Good signature from "Mark Brown <broonie@sirena.org.uk>"
# gpg: aka "Mark Brown <broonie@debian.org>"
# gpg: aka "Mark Brown <broonie@kernel.org>"
# gpg: aka "Mark Brown <broonie@tardis.ed.ac.uk>"
# gpg: aka "Mark Brown <broonie@linaro.org>"
# gpg: aka "Mark Brown <Mark.Brown@linaro.org>"
Diffstat (limited to 'sound/soc/sh')
-rw-r--r-- | sound/soc/sh/Kconfig | 2 | ||||
-rw-r--r-- | sound/soc/sh/fsi.c | 201 | ||||
-rw-r--r-- | sound/soc/sh/rcar/core.c | 243 | ||||
-rw-r--r-- | sound/soc/sh/rcar/dvc.c | 135 | ||||
-rw-r--r-- | sound/soc/sh/rcar/gen.c | 553 | ||||
-rw-r--r-- | sound/soc/sh/rcar/rsnd.h | 26 | ||||
-rw-r--r-- | sound/soc/sh/rcar/src.c | 86 | ||||
-rw-r--r-- | sound/soc/sh/rcar/ssi.c | 33 |
8 files changed, 652 insertions, 627 deletions
diff --git a/sound/soc/sh/Kconfig b/sound/soc/sh/Kconfig index b43fdf0d08af..80245b6eebd6 100644 --- a/sound/soc/sh/Kconfig +++ b/sound/soc/sh/Kconfig | |||
@@ -37,7 +37,7 @@ config SND_SOC_SH4_SIU | |||
37 | config SND_SOC_RCAR | 37 | config SND_SOC_RCAR |
38 | tristate "R-Car series SRU/SCU/SSIU/SSI support" | 38 | tristate "R-Car series SRU/SCU/SSIU/SSI support" |
39 | select SND_SIMPLE_CARD | 39 | select SND_SIMPLE_CARD |
40 | select REGMAP | 40 | select REGMAP_MMIO |
41 | help | 41 | help |
42 | This option enables R-Car SUR/SCU/SSIU/SSI sound support | 42 | This option enables R-Car SUR/SCU/SSIU/SSI sound support |
43 | 43 | ||
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 | ||
diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index ed76901f8202..19f78963e8b9 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c | |||
@@ -138,6 +138,17 @@ char *rsnd_mod_name(struct rsnd_mod *mod) | |||
138 | return mod->ops->name; | 138 | return mod->ops->name; |
139 | } | 139 | } |
140 | 140 | ||
141 | char *rsnd_mod_dma_name(struct rsnd_mod *mod) | ||
142 | { | ||
143 | if (!mod || !mod->ops) | ||
144 | return "unknown"; | ||
145 | |||
146 | if (!mod->ops->dma_name) | ||
147 | return mod->ops->name; | ||
148 | |||
149 | return mod->ops->dma_name(mod); | ||
150 | } | ||
151 | |||
141 | void rsnd_mod_init(struct rsnd_priv *priv, | 152 | void rsnd_mod_init(struct rsnd_priv *priv, |
142 | struct rsnd_mod *mod, | 153 | struct rsnd_mod *mod, |
143 | struct rsnd_mod_ops *ops, | 154 | struct rsnd_mod_ops *ops, |
@@ -153,26 +164,8 @@ void rsnd_mod_init(struct rsnd_priv *priv, | |||
153 | /* | 164 | /* |
154 | * rsnd_dma functions | 165 | * rsnd_dma functions |
155 | */ | 166 | */ |
156 | static void __rsnd_dma_start(struct rsnd_dma *dma); | ||
157 | static void rsnd_dma_continue(struct rsnd_dma *dma) | ||
158 | { | ||
159 | /* push next A or B plane */ | ||
160 | dma->submit_loop = 1; | ||
161 | schedule_work(&dma->work); | ||
162 | } | ||
163 | |||
164 | void rsnd_dma_start(struct rsnd_dma *dma) | ||
165 | { | ||
166 | /* push both A and B plane*/ | ||
167 | dma->offset = 0; | ||
168 | dma->submit_loop = 2; | ||
169 | __rsnd_dma_start(dma); | ||
170 | } | ||
171 | |||
172 | void rsnd_dma_stop(struct rsnd_dma *dma) | 167 | void rsnd_dma_stop(struct rsnd_dma *dma) |
173 | { | 168 | { |
174 | dma->submit_loop = 0; | ||
175 | cancel_work_sync(&dma->work); | ||
176 | dmaengine_terminate_all(dma->chan); | 169 | dmaengine_terminate_all(dma->chan); |
177 | } | 170 | } |
178 | 171 | ||
@@ -180,11 +173,7 @@ static void rsnd_dma_complete(void *data) | |||
180 | { | 173 | { |
181 | struct rsnd_dma *dma = (struct rsnd_dma *)data; | 174 | struct rsnd_dma *dma = (struct rsnd_dma *)data; |
182 | struct rsnd_mod *mod = rsnd_dma_to_mod(dma); | 175 | struct rsnd_mod *mod = rsnd_dma_to_mod(dma); |
183 | struct rsnd_priv *priv = rsnd_mod_to_priv(rsnd_dma_to_mod(dma)); | ||
184 | struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); | 176 | struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); |
185 | unsigned long flags; | ||
186 | |||
187 | rsnd_lock(priv, flags); | ||
188 | 177 | ||
189 | /* | 178 | /* |
190 | * Renesas sound Gen1 needs 1 DMAC, | 179 | * Renesas sound Gen1 needs 1 DMAC, |
@@ -197,57 +186,41 @@ static void rsnd_dma_complete(void *data) | |||
197 | * rsnd_dai_pointer_update() will be called twice, | 186 | * rsnd_dai_pointer_update() will be called twice, |
198 | * ant it will breaks io->byte_pos | 187 | * ant it will breaks io->byte_pos |
199 | */ | 188 | */ |
200 | if (dma->submit_loop) | ||
201 | rsnd_dma_continue(dma); | ||
202 | |||
203 | rsnd_unlock(priv, flags); | ||
204 | 189 | ||
205 | rsnd_dai_pointer_update(io, io->byte_per_period); | 190 | rsnd_dai_pointer_update(io, io->byte_per_period); |
206 | } | 191 | } |
207 | 192 | ||
208 | static void __rsnd_dma_start(struct rsnd_dma *dma) | 193 | void rsnd_dma_start(struct rsnd_dma *dma) |
209 | { | 194 | { |
210 | struct rsnd_mod *mod = rsnd_dma_to_mod(dma); | 195 | struct rsnd_mod *mod = rsnd_dma_to_mod(dma); |
211 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); | 196 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); |
212 | struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); | 197 | struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); |
213 | struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); | 198 | struct snd_pcm_substream *substream = io->substream; |
214 | struct device *dev = rsnd_priv_to_dev(priv); | 199 | struct device *dev = rsnd_priv_to_dev(priv); |
215 | struct dma_async_tx_descriptor *desc; | 200 | struct dma_async_tx_descriptor *desc; |
216 | dma_addr_t buf; | ||
217 | size_t len = io->byte_per_period; | ||
218 | int i; | ||
219 | 201 | ||
220 | for (i = 0; i < dma->submit_loop; i++) { | 202 | desc = dmaengine_prep_dma_cyclic(dma->chan, |
221 | 203 | (dma->addr) ? dma->addr : | |
222 | buf = runtime->dma_addr + | 204 | substream->runtime->dma_addr, |
223 | rsnd_dai_pointer_offset(io, dma->offset + len); | 205 | snd_pcm_lib_buffer_bytes(substream), |
224 | dma->offset = len; | 206 | snd_pcm_lib_period_bytes(substream), |
225 | 207 | dma->dir, | |
226 | desc = dmaengine_prep_slave_single( | 208 | DMA_PREP_INTERRUPT | DMA_CTRL_ACK); |
227 | dma->chan, buf, len, dma->dir, | ||
228 | DMA_PREP_INTERRUPT | DMA_CTRL_ACK); | ||
229 | if (!desc) { | ||
230 | dev_err(dev, "dmaengine_prep_slave_sg() fail\n"); | ||
231 | return; | ||
232 | } | ||
233 | 209 | ||
234 | desc->callback = rsnd_dma_complete; | 210 | if (!desc) { |
235 | desc->callback_param = dma; | 211 | dev_err(dev, "dmaengine_prep_slave_sg() fail\n"); |
212 | return; | ||
213 | } | ||
236 | 214 | ||
237 | if (dmaengine_submit(desc) < 0) { | 215 | desc->callback = rsnd_dma_complete; |
238 | dev_err(dev, "dmaengine_submit() fail\n"); | 216 | desc->callback_param = dma; |
239 | return; | ||
240 | } | ||
241 | 217 | ||
242 | dma_async_issue_pending(dma->chan); | 218 | if (dmaengine_submit(desc) < 0) { |
219 | dev_err(dev, "dmaengine_submit() fail\n"); | ||
220 | return; | ||
243 | } | 221 | } |
244 | } | ||
245 | |||
246 | static void rsnd_dma_do_work(struct work_struct *work) | ||
247 | { | ||
248 | struct rsnd_dma *dma = container_of(work, struct rsnd_dma, work); | ||
249 | 222 | ||
250 | __rsnd_dma_start(dma); | 223 | dma_async_issue_pending(dma->chan); |
251 | } | 224 | } |
252 | 225 | ||
253 | int rsnd_dma_available(struct rsnd_dma *dma) | 226 | int rsnd_dma_available(struct rsnd_dma *dma) |
@@ -261,14 +234,27 @@ static int _rsnd_dma_of_name(char *dma_name, struct rsnd_mod *mod) | |||
261 | { | 234 | { |
262 | if (mod) | 235 | if (mod) |
263 | return snprintf(dma_name, DMA_NAME_SIZE / 2, "%s%d", | 236 | return snprintf(dma_name, DMA_NAME_SIZE / 2, "%s%d", |
264 | rsnd_mod_name(mod), rsnd_mod_id(mod)); | 237 | rsnd_mod_dma_name(mod), rsnd_mod_id(mod)); |
265 | else | 238 | else |
266 | return snprintf(dma_name, DMA_NAME_SIZE / 2, "mem"); | 239 | return snprintf(dma_name, DMA_NAME_SIZE / 2, "mem"); |
267 | 240 | ||
268 | } | 241 | } |
269 | 242 | ||
270 | static void rsnd_dma_of_name(struct rsnd_dma *dma, | 243 | static void rsnd_dma_of_name(struct rsnd_mod *mod_from, |
271 | int is_play, char *dma_name) | 244 | struct rsnd_mod *mod_to, |
245 | char *dma_name) | ||
246 | { | ||
247 | int index = 0; | ||
248 | |||
249 | index = _rsnd_dma_of_name(dma_name + index, mod_from); | ||
250 | *(dma_name + index++) = '_'; | ||
251 | index = _rsnd_dma_of_name(dma_name + index, mod_to); | ||
252 | } | ||
253 | |||
254 | static void rsnd_dma_of_path(struct rsnd_dma *dma, | ||
255 | int is_play, | ||
256 | struct rsnd_mod **mod_from, | ||
257 | struct rsnd_mod **mod_to) | ||
272 | { | 258 | { |
273 | struct rsnd_mod *this = rsnd_dma_to_mod(dma); | 259 | struct rsnd_mod *this = rsnd_dma_to_mod(dma); |
274 | struct rsnd_dai_stream *io = rsnd_mod_to_io(this); | 260 | struct rsnd_dai_stream *io = rsnd_mod_to_io(this); |
@@ -276,7 +262,6 @@ static void rsnd_dma_of_name(struct rsnd_dma *dma, | |||
276 | struct rsnd_mod *src = rsnd_io_to_mod_src(io); | 262 | struct rsnd_mod *src = rsnd_io_to_mod_src(io); |
277 | struct rsnd_mod *dvc = rsnd_io_to_mod_dvc(io); | 263 | struct rsnd_mod *dvc = rsnd_io_to_mod_dvc(io); |
278 | struct rsnd_mod *mod[MOD_MAX]; | 264 | struct rsnd_mod *mod[MOD_MAX]; |
279 | struct rsnd_mod *src_mod, *dst_mod; | ||
280 | int i, index; | 265 | int i, index; |
281 | 266 | ||
282 | 267 | ||
@@ -301,7 +286,13 @@ static void rsnd_dma_of_name(struct rsnd_dma *dma, | |||
301 | mod[i] = src; | 286 | mod[i] = src; |
302 | src = NULL; | 287 | src = NULL; |
303 | } else { | 288 | } else { |
304 | mod[i] = dvc; | 289 | if ((!is_play) && (this == src)) |
290 | this = dvc; | ||
291 | |||
292 | mod[i] = (is_play) ? src : dvc; | ||
293 | i++; | ||
294 | mod[i] = (is_play) ? dvc : src; | ||
295 | src = NULL; | ||
305 | dvc = NULL; | 296 | dvc = NULL; |
306 | } | 297 | } |
307 | 298 | ||
@@ -313,17 +304,12 @@ static void rsnd_dma_of_name(struct rsnd_dma *dma, | |||
313 | } | 304 | } |
314 | 305 | ||
315 | if (is_play) { | 306 | if (is_play) { |
316 | src_mod = mod[index - 1]; | 307 | *mod_from = mod[index - 1]; |
317 | dst_mod = mod[index]; | 308 | *mod_to = mod[index]; |
318 | } else { | 309 | } else { |
319 | src_mod = mod[index]; | 310 | *mod_from = mod[index]; |
320 | dst_mod = mod[index - 1]; | 311 | *mod_to = mod[index - 1]; |
321 | } | 312 | } |
322 | |||
323 | index = 0; | ||
324 | index = _rsnd_dma_of_name(dma_name + index, src_mod); | ||
325 | *(dma_name + index++) = '_'; | ||
326 | index = _rsnd_dma_of_name(dma_name + index, dst_mod); | ||
327 | } | 313 | } |
328 | 314 | ||
329 | int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma, | 315 | int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma, |
@@ -331,6 +317,8 @@ int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma, | |||
331 | { | 317 | { |
332 | struct device *dev = rsnd_priv_to_dev(priv); | 318 | struct device *dev = rsnd_priv_to_dev(priv); |
333 | struct dma_slave_config cfg; | 319 | struct dma_slave_config cfg; |
320 | struct rsnd_mod *mod_from; | ||
321 | struct rsnd_mod *mod_to; | ||
334 | char dma_name[DMA_NAME_SIZE]; | 322 | char dma_name[DMA_NAME_SIZE]; |
335 | dma_cap_mask_t mask; | 323 | dma_cap_mask_t mask; |
336 | int ret; | 324 | int ret; |
@@ -343,13 +331,18 @@ int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma, | |||
343 | dma_cap_zero(mask); | 331 | dma_cap_zero(mask); |
344 | dma_cap_set(DMA_SLAVE, mask); | 332 | dma_cap_set(DMA_SLAVE, mask); |
345 | 333 | ||
346 | if (dev->of_node) | 334 | rsnd_dma_of_path(dma, is_play, &mod_from, &mod_to); |
347 | rsnd_dma_of_name(dma, is_play, dma_name); | 335 | rsnd_dma_of_name(mod_from, mod_to, dma_name); |
348 | else | 336 | |
349 | snprintf(dma_name, DMA_NAME_SIZE, | 337 | cfg.slave_id = id; |
350 | is_play ? "tx" : "rx"); | 338 | cfg.direction = is_play ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM; |
339 | cfg.src_addr = rsnd_gen_dma_addr(priv, mod_from, is_play, 1); | ||
340 | cfg.dst_addr = rsnd_gen_dma_addr(priv, mod_to, is_play, 0); | ||
341 | cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; | ||
342 | cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; | ||
351 | 343 | ||
352 | dev_dbg(dev, "dma name : %s\n", dma_name); | 344 | dev_dbg(dev, "dma : %s %pad -> %pad\n", |
345 | dma_name, &cfg.src_addr, &cfg.dst_addr); | ||
353 | 346 | ||
354 | dma->chan = dma_request_slave_channel_compat(mask, shdma_chan_filter, | 347 | dma->chan = dma_request_slave_channel_compat(mask, shdma_chan_filter, |
355 | (void *)id, dev, | 348 | (void *)id, dev, |
@@ -359,14 +352,12 @@ int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma, | |||
359 | return -EIO; | 352 | return -EIO; |
360 | } | 353 | } |
361 | 354 | ||
362 | rsnd_gen_dma_addr(priv, dma, &cfg, is_play, id); | ||
363 | |||
364 | ret = dmaengine_slave_config(dma->chan, &cfg); | 355 | ret = dmaengine_slave_config(dma->chan, &cfg); |
365 | if (ret < 0) | 356 | if (ret < 0) |
366 | goto rsnd_dma_init_err; | 357 | goto rsnd_dma_init_err; |
367 | 358 | ||
368 | dma->dir = is_play ? DMA_TO_DEVICE : DMA_FROM_DEVICE; | 359 | dma->addr = is_play ? cfg.src_addr : cfg.dst_addr; |
369 | INIT_WORK(&dma->work, rsnd_dma_do_work); | 360 | dma->dir = is_play ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM; |
370 | 361 | ||
371 | return 0; | 362 | return 0; |
372 | 363 | ||
@@ -633,40 +624,41 @@ static int rsnd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) | |||
633 | return -EINVAL; | 624 | return -EINVAL; |
634 | } | 625 | } |
635 | 626 | ||
636 | /* set clock inversion */ | ||
637 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { | ||
638 | case SND_SOC_DAIFMT_NB_IF: | ||
639 | rdai->bit_clk_inv = 0; | ||
640 | rdai->frm_clk_inv = 1; | ||
641 | break; | ||
642 | case SND_SOC_DAIFMT_IB_NF: | ||
643 | rdai->bit_clk_inv = 1; | ||
644 | rdai->frm_clk_inv = 0; | ||
645 | break; | ||
646 | case SND_SOC_DAIFMT_IB_IF: | ||
647 | rdai->bit_clk_inv = 1; | ||
648 | rdai->frm_clk_inv = 1; | ||
649 | break; | ||
650 | case SND_SOC_DAIFMT_NB_NF: | ||
651 | default: | ||
652 | rdai->bit_clk_inv = 0; | ||
653 | rdai->frm_clk_inv = 0; | ||
654 | break; | ||
655 | } | ||
656 | |||
657 | /* set format */ | 627 | /* set format */ |
658 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | 628 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { |
659 | case SND_SOC_DAIFMT_I2S: | 629 | case SND_SOC_DAIFMT_I2S: |
660 | rdai->sys_delay = 0; | 630 | rdai->sys_delay = 0; |
661 | rdai->data_alignment = 0; | 631 | rdai->data_alignment = 0; |
632 | rdai->frm_clk_inv = 0; | ||
662 | break; | 633 | break; |
663 | case SND_SOC_DAIFMT_LEFT_J: | 634 | case SND_SOC_DAIFMT_LEFT_J: |
664 | rdai->sys_delay = 1; | 635 | rdai->sys_delay = 1; |
665 | rdai->data_alignment = 0; | 636 | rdai->data_alignment = 0; |
637 | rdai->frm_clk_inv = 1; | ||
666 | break; | 638 | break; |
667 | case SND_SOC_DAIFMT_RIGHT_J: | 639 | case SND_SOC_DAIFMT_RIGHT_J: |
668 | rdai->sys_delay = 1; | 640 | rdai->sys_delay = 1; |
669 | rdai->data_alignment = 1; | 641 | rdai->data_alignment = 1; |
642 | rdai->frm_clk_inv = 1; | ||
643 | break; | ||
644 | } | ||
645 | |||
646 | /* set clock inversion */ | ||
647 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { | ||
648 | case SND_SOC_DAIFMT_NB_IF: | ||
649 | rdai->bit_clk_inv = rdai->bit_clk_inv; | ||
650 | rdai->frm_clk_inv = !rdai->frm_clk_inv; | ||
651 | break; | ||
652 | case SND_SOC_DAIFMT_IB_NF: | ||
653 | rdai->bit_clk_inv = !rdai->bit_clk_inv; | ||
654 | rdai->frm_clk_inv = rdai->frm_clk_inv; | ||
655 | break; | ||
656 | case SND_SOC_DAIFMT_IB_IF: | ||
657 | rdai->bit_clk_inv = !rdai->bit_clk_inv; | ||
658 | rdai->frm_clk_inv = !rdai->frm_clk_inv; | ||
659 | break; | ||
660 | case SND_SOC_DAIFMT_NB_NF: | ||
661 | default: | ||
670 | break; | 662 | break; |
671 | } | 663 | } |
672 | 664 | ||
@@ -736,12 +728,13 @@ static void rsnd_of_parse_dai(struct platform_device *pdev, | |||
736 | struct device_node *dai_node, *dai_np; | 728 | struct device_node *dai_node, *dai_np; |
737 | struct device_node *ssi_node, *ssi_np; | 729 | struct device_node *ssi_node, *ssi_np; |
738 | struct device_node *src_node, *src_np; | 730 | struct device_node *src_node, *src_np; |
731 | struct device_node *dvc_node, *dvc_np; | ||
739 | struct device_node *playback, *capture; | 732 | struct device_node *playback, *capture; |
740 | struct rsnd_dai_platform_info *dai_info; | 733 | struct rsnd_dai_platform_info *dai_info; |
741 | struct rcar_snd_info *info = rsnd_priv_to_info(priv); | 734 | struct rcar_snd_info *info = rsnd_priv_to_info(priv); |
742 | struct device *dev = &pdev->dev; | 735 | struct device *dev = &pdev->dev; |
743 | int nr, i; | 736 | int nr, i; |
744 | int dai_i, ssi_i, src_i; | 737 | int dai_i, ssi_i, src_i, dvc_i; |
745 | 738 | ||
746 | if (!of_data) | 739 | if (!of_data) |
747 | return; | 740 | return; |
@@ -767,6 +760,7 @@ static void rsnd_of_parse_dai(struct platform_device *pdev, | |||
767 | 760 | ||
768 | ssi_node = of_get_child_by_name(dev->of_node, "rcar_sound,ssi"); | 761 | ssi_node = of_get_child_by_name(dev->of_node, "rcar_sound,ssi"); |
769 | src_node = of_get_child_by_name(dev->of_node, "rcar_sound,src"); | 762 | src_node = of_get_child_by_name(dev->of_node, "rcar_sound,src"); |
763 | dvc_node = of_get_child_by_name(dev->of_node, "rcar_sound,dvc"); | ||
770 | 764 | ||
771 | #define mod_parse(name) \ | 765 | #define mod_parse(name) \ |
772 | if (name##_node) { \ | 766 | if (name##_node) { \ |
@@ -802,6 +796,7 @@ if (name##_node) { \ | |||
802 | 796 | ||
803 | mod_parse(ssi); | 797 | mod_parse(ssi); |
804 | mod_parse(src); | 798 | mod_parse(src); |
799 | mod_parse(dvc); | ||
805 | 800 | ||
806 | if (playback) | 801 | if (playback) |
807 | of_node_put(playback); | 802 | of_node_put(playback); |
@@ -950,19 +945,17 @@ static struct snd_pcm_ops rsnd_pcm_ops = { | |||
950 | 945 | ||
951 | static int rsnd_pcm_new(struct snd_soc_pcm_runtime *rtd) | 946 | static int rsnd_pcm_new(struct snd_soc_pcm_runtime *rtd) |
952 | { | 947 | { |
953 | struct rsnd_priv *priv = snd_soc_dai_get_drvdata(rtd->cpu_dai); | 948 | struct snd_soc_dai *dai = rtd->cpu_dai; |
954 | struct rsnd_dai *rdai; | 949 | struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai); |
955 | int i, ret; | 950 | int ret; |
956 | 951 | ||
957 | for_each_rsnd_dai(rdai, priv, i) { | 952 | ret = rsnd_dai_call(pcm_new, &rdai->playback, rdai, rtd); |
958 | ret = rsnd_dai_call(pcm_new, &rdai->playback, rdai, rtd); | 953 | if (ret) |
959 | if (ret) | 954 | return ret; |
960 | return ret; | ||
961 | 955 | ||
962 | ret = rsnd_dai_call(pcm_new, &rdai->capture, rdai, rtd); | 956 | ret = rsnd_dai_call(pcm_new, &rdai->capture, rdai, rtd); |
963 | if (ret) | 957 | if (ret) |
964 | return ret; | 958 | return ret; |
965 | } | ||
966 | 959 | ||
967 | return snd_pcm_lib_preallocate_pages_for_all( | 960 | return snd_pcm_lib_preallocate_pages_for_all( |
968 | rtd->pcm, | 961 | rtd->pcm, |
@@ -1049,11 +1042,11 @@ static int rsnd_probe(struct platform_device *pdev) | |||
1049 | for_each_rsnd_dai(rdai, priv, i) { | 1042 | for_each_rsnd_dai(rdai, priv, i) { |
1050 | ret = rsnd_dai_call(probe, &rdai->playback, rdai); | 1043 | ret = rsnd_dai_call(probe, &rdai->playback, rdai); |
1051 | if (ret) | 1044 | if (ret) |
1052 | return ret; | 1045 | goto exit_snd_probe; |
1053 | 1046 | ||
1054 | ret = rsnd_dai_call(probe, &rdai->capture, rdai); | 1047 | ret = rsnd_dai_call(probe, &rdai->capture, rdai); |
1055 | if (ret) | 1048 | if (ret) |
1056 | return ret; | 1049 | goto exit_snd_probe; |
1057 | } | 1050 | } |
1058 | 1051 | ||
1059 | /* | 1052 | /* |
@@ -1081,6 +1074,11 @@ static int rsnd_probe(struct platform_device *pdev) | |||
1081 | 1074 | ||
1082 | exit_snd_soc: | 1075 | exit_snd_soc: |
1083 | snd_soc_unregister_platform(dev); | 1076 | snd_soc_unregister_platform(dev); |
1077 | exit_snd_probe: | ||
1078 | for_each_rsnd_dai(rdai, priv, i) { | ||
1079 | rsnd_dai_call(remove, &rdai->playback, rdai); | ||
1080 | rsnd_dai_call(remove, &rdai->capture, rdai); | ||
1081 | } | ||
1084 | 1082 | ||
1085 | return ret; | 1083 | return ret; |
1086 | } | 1084 | } |
@@ -1089,21 +1087,16 @@ static int rsnd_remove(struct platform_device *pdev) | |||
1089 | { | 1087 | { |
1090 | struct rsnd_priv *priv = dev_get_drvdata(&pdev->dev); | 1088 | struct rsnd_priv *priv = dev_get_drvdata(&pdev->dev); |
1091 | struct rsnd_dai *rdai; | 1089 | struct rsnd_dai *rdai; |
1092 | int ret, i; | 1090 | int ret = 0, i; |
1093 | 1091 | ||
1094 | pm_runtime_disable(&pdev->dev); | 1092 | pm_runtime_disable(&pdev->dev); |
1095 | 1093 | ||
1096 | for_each_rsnd_dai(rdai, priv, i) { | 1094 | for_each_rsnd_dai(rdai, priv, i) { |
1097 | ret = rsnd_dai_call(remove, &rdai->playback, rdai); | 1095 | ret |= rsnd_dai_call(remove, &rdai->playback, rdai); |
1098 | if (ret) | 1096 | ret |= rsnd_dai_call(remove, &rdai->capture, rdai); |
1099 | return ret; | ||
1100 | |||
1101 | ret = rsnd_dai_call(remove, &rdai->capture, rdai); | ||
1102 | if (ret) | ||
1103 | return ret; | ||
1104 | } | 1097 | } |
1105 | 1098 | ||
1106 | return 0; | 1099 | return ret; |
1107 | } | 1100 | } |
1108 | 1101 | ||
1109 | static struct platform_driver rsnd_driver = { | 1102 | static struct platform_driver rsnd_driver = { |
diff --git a/sound/soc/sh/rcar/dvc.c b/sound/soc/sh/rcar/dvc.c index ed0007006899..3f443930c2b1 100644 --- a/sound/soc/sh/rcar/dvc.c +++ b/sound/soc/sh/rcar/dvc.c | |||
@@ -20,7 +20,8 @@ struct rsnd_dvc { | |||
20 | struct rsnd_dvc_platform_info *info; /* rcar_snd.h */ | 20 | struct rsnd_dvc_platform_info *info; /* rcar_snd.h */ |
21 | struct rsnd_mod mod; | 21 | struct rsnd_mod mod; |
22 | struct clk *clk; | 22 | struct clk *clk; |
23 | long volume[RSND_DVC_VOLUME_NUM]; | 23 | u8 volume[RSND_DVC_VOLUME_NUM]; |
24 | u8 mute[RSND_DVC_VOLUME_NUM]; | ||
24 | }; | 25 | }; |
25 | 26 | ||
26 | #define rsnd_mod_to_dvc(_mod) \ | 27 | #define rsnd_mod_to_dvc(_mod) \ |
@@ -37,13 +38,18 @@ static void rsnd_dvc_volume_update(struct rsnd_mod *mod) | |||
37 | struct rsnd_dvc *dvc = rsnd_mod_to_dvc(mod); | 38 | struct rsnd_dvc *dvc = rsnd_mod_to_dvc(mod); |
38 | u32 max = (0x00800000 - 1); | 39 | u32 max = (0x00800000 - 1); |
39 | u32 vol[RSND_DVC_VOLUME_NUM]; | 40 | u32 vol[RSND_DVC_VOLUME_NUM]; |
41 | u32 mute = 0; | ||
40 | int i; | 42 | int i; |
41 | 43 | ||
42 | for (i = 0; i < RSND_DVC_VOLUME_NUM; i++) | 44 | for (i = 0; i < RSND_DVC_VOLUME_NUM; i++) { |
43 | vol[i] = max / RSND_DVC_VOLUME_MAX * dvc->volume[i]; | 45 | vol[i] = max / RSND_DVC_VOLUME_MAX * dvc->volume[i]; |
46 | mute |= (!!dvc->mute[i]) << i; | ||
47 | } | ||
44 | 48 | ||
45 | rsnd_mod_write(mod, DVC_VOL0R, vol[0]); | 49 | rsnd_mod_write(mod, DVC_VOL0R, vol[0]); |
46 | rsnd_mod_write(mod, DVC_VOL1R, vol[1]); | 50 | rsnd_mod_write(mod, DVC_VOL1R, vol[1]); |
51 | |||
52 | rsnd_mod_write(mod, DVC_ZCMCR, mute); | ||
47 | } | 53 | } |
48 | 54 | ||
49 | static int rsnd_dvc_probe_gen2(struct rsnd_mod *mod, | 55 | static int rsnd_dvc_probe_gen2(struct rsnd_mod *mod, |
@@ -96,8 +102,8 @@ static int rsnd_dvc_init(struct rsnd_mod *dvc_mod, | |||
96 | 102 | ||
97 | rsnd_mod_write(dvc_mod, DVC_ADINR, rsnd_get_adinr(dvc_mod)); | 103 | rsnd_mod_write(dvc_mod, DVC_ADINR, rsnd_get_adinr(dvc_mod)); |
98 | 104 | ||
99 | /* enable Volume */ | 105 | /* enable Volume / Mute */ |
100 | rsnd_mod_write(dvc_mod, DVC_DVUCR, 0x100); | 106 | rsnd_mod_write(dvc_mod, DVC_DVUCR, 0x101); |
101 | 107 | ||
102 | /* ch0/ch1 Volume */ | 108 | /* ch0/ch1 Volume */ |
103 | rsnd_dvc_volume_update(dvc_mod); | 109 | rsnd_dvc_volume_update(dvc_mod); |
@@ -140,10 +146,20 @@ static int rsnd_dvc_stop(struct rsnd_mod *mod, | |||
140 | static int rsnd_dvc_volume_info(struct snd_kcontrol *kctrl, | 146 | static int rsnd_dvc_volume_info(struct snd_kcontrol *kctrl, |
141 | struct snd_ctl_elem_info *uinfo) | 147 | struct snd_ctl_elem_info *uinfo) |
142 | { | 148 | { |
143 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | 149 | struct rsnd_mod *mod = snd_kcontrol_chip(kctrl); |
150 | struct rsnd_dvc *dvc = rsnd_mod_to_dvc(mod); | ||
151 | u8 *val = (u8 *)kctrl->private_value; | ||
152 | |||
144 | uinfo->count = RSND_DVC_VOLUME_NUM; | 153 | uinfo->count = RSND_DVC_VOLUME_NUM; |
145 | uinfo->value.integer.min = 0; | 154 | uinfo->value.integer.min = 0; |
146 | uinfo->value.integer.max = RSND_DVC_VOLUME_MAX; | 155 | |
156 | if (val == dvc->volume) { | ||
157 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
158 | uinfo->value.integer.max = RSND_DVC_VOLUME_MAX; | ||
159 | } else { | ||
160 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
161 | uinfo->value.integer.max = 1; | ||
162 | } | ||
147 | 163 | ||
148 | return 0; | 164 | return 0; |
149 | } | 165 | } |
@@ -151,12 +167,11 @@ static int rsnd_dvc_volume_info(struct snd_kcontrol *kctrl, | |||
151 | static int rsnd_dvc_volume_get(struct snd_kcontrol *kctrl, | 167 | static int rsnd_dvc_volume_get(struct snd_kcontrol *kctrl, |
152 | struct snd_ctl_elem_value *ucontrol) | 168 | struct snd_ctl_elem_value *ucontrol) |
153 | { | 169 | { |
154 | struct rsnd_mod *mod = snd_kcontrol_chip(kctrl); | 170 | u8 *val = (u8 *)kctrl->private_value; |
155 | struct rsnd_dvc *dvc = rsnd_mod_to_dvc(mod); | ||
156 | int i; | 171 | int i; |
157 | 172 | ||
158 | for (i = 0; i < RSND_DVC_VOLUME_NUM; i++) | 173 | for (i = 0; i < RSND_DVC_VOLUME_NUM; i++) |
159 | ucontrol->value.integer.value[i] = dvc->volume[i]; | 174 | ucontrol->value.integer.value[i] = val[i]; |
160 | 175 | ||
161 | return 0; | 176 | return 0; |
162 | } | 177 | } |
@@ -165,51 +180,38 @@ static int rsnd_dvc_volume_put(struct snd_kcontrol *kctrl, | |||
165 | struct snd_ctl_elem_value *ucontrol) | 180 | struct snd_ctl_elem_value *ucontrol) |
166 | { | 181 | { |
167 | struct rsnd_mod *mod = snd_kcontrol_chip(kctrl); | 182 | struct rsnd_mod *mod = snd_kcontrol_chip(kctrl); |
168 | struct rsnd_dvc *dvc = rsnd_mod_to_dvc(mod); | 183 | u8 *val = (u8 *)kctrl->private_value; |
169 | int i, change = 0; | 184 | int i, change = 0; |
170 | 185 | ||
171 | for (i = 0; i < RSND_DVC_VOLUME_NUM; i++) { | 186 | for (i = 0; i < RSND_DVC_VOLUME_NUM; i++) { |
172 | if (ucontrol->value.integer.value[i] < 0 || | 187 | change |= (ucontrol->value.integer.value[i] != val[i]); |
173 | ucontrol->value.integer.value[i] > RSND_DVC_VOLUME_MAX) | 188 | val[i] = ucontrol->value.integer.value[i]; |
174 | return -EINVAL; | ||
175 | |||
176 | change |= (ucontrol->value.integer.value[i] != dvc->volume[i]); | ||
177 | } | 189 | } |
178 | 190 | ||
179 | if (change) { | 191 | if (change) |
180 | for (i = 0; i < RSND_DVC_VOLUME_NUM; i++) | ||
181 | dvc->volume[i] = ucontrol->value.integer.value[i]; | ||
182 | |||
183 | rsnd_dvc_volume_update(mod); | 192 | rsnd_dvc_volume_update(mod); |
184 | } | ||
185 | 193 | ||
186 | return change; | 194 | return change; |
187 | } | 195 | } |
188 | 196 | ||
189 | static int rsnd_dvc_pcm_new(struct rsnd_mod *mod, | 197 | static int __rsnd_dvc_pcm_new(struct rsnd_mod *mod, |
190 | struct rsnd_dai *rdai, | 198 | struct rsnd_dai *rdai, |
191 | struct snd_soc_pcm_runtime *rtd) | 199 | struct snd_soc_pcm_runtime *rtd, |
200 | const unsigned char *name, | ||
201 | u8 *private) | ||
192 | { | 202 | { |
193 | struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); | ||
194 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); | ||
195 | struct device *dev = rsnd_priv_to_dev(priv); | ||
196 | struct snd_card *card = rtd->card->snd_card; | 203 | struct snd_card *card = rtd->card->snd_card; |
197 | struct snd_kcontrol *kctrl; | 204 | struct snd_kcontrol *kctrl; |
198 | static struct snd_kcontrol_new knew = { | 205 | struct snd_kcontrol_new knew = { |
199 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 206 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
200 | .name = "Playback Volume", | 207 | .name = name, |
201 | .info = rsnd_dvc_volume_info, | 208 | .info = rsnd_dvc_volume_info, |
202 | .get = rsnd_dvc_volume_get, | 209 | .get = rsnd_dvc_volume_get, |
203 | .put = rsnd_dvc_volume_put, | 210 | .put = rsnd_dvc_volume_put, |
211 | .private_value = (unsigned long)private, | ||
204 | }; | 212 | }; |
205 | int ret; | 213 | int ret; |
206 | 214 | ||
207 | if (!rsnd_dai_is_play(rdai, io)) { | ||
208 | dev_err(dev, "DVC%d is connected to Capture DAI\n", | ||
209 | rsnd_mod_id(mod)); | ||
210 | return -EINVAL; | ||
211 | } | ||
212 | |||
213 | kctrl = snd_ctl_new1(&knew, mod); | 215 | kctrl = snd_ctl_new1(&knew, mod); |
214 | if (!kctrl) | 216 | if (!kctrl) |
215 | return -ENOMEM; | 217 | return -ENOMEM; |
@@ -221,6 +223,33 @@ static int rsnd_dvc_pcm_new(struct rsnd_mod *mod, | |||
221 | return 0; | 223 | return 0; |
222 | } | 224 | } |
223 | 225 | ||
226 | static int rsnd_dvc_pcm_new(struct rsnd_mod *mod, | ||
227 | struct rsnd_dai *rdai, | ||
228 | struct snd_soc_pcm_runtime *rtd) | ||
229 | { | ||
230 | struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); | ||
231 | struct rsnd_dvc *dvc = rsnd_mod_to_dvc(mod); | ||
232 | int ret; | ||
233 | |||
234 | /* Volume */ | ||
235 | ret = __rsnd_dvc_pcm_new(mod, rdai, rtd, | ||
236 | rsnd_dai_is_play(rdai, io) ? | ||
237 | "DVC Out Playback Volume" : "DVC In Capture Volume", | ||
238 | dvc->volume); | ||
239 | if (ret < 0) | ||
240 | return ret; | ||
241 | |||
242 | /* Mute */ | ||
243 | ret = __rsnd_dvc_pcm_new(mod, rdai, rtd, | ||
244 | rsnd_dai_is_play(rdai, io) ? | ||
245 | "DVC Out Mute Switch" : "DVC In Mute Switch", | ||
246 | dvc->mute); | ||
247 | if (ret < 0) | ||
248 | return ret; | ||
249 | |||
250 | return 0; | ||
251 | } | ||
252 | |||
224 | static struct rsnd_mod_ops rsnd_dvc_ops = { | 253 | static struct rsnd_mod_ops rsnd_dvc_ops = { |
225 | .name = DVC_NAME, | 254 | .name = DVC_NAME, |
226 | .probe = rsnd_dvc_probe_gen2, | 255 | .probe = rsnd_dvc_probe_gen2, |
@@ -239,6 +268,42 @@ struct rsnd_mod *rsnd_dvc_mod_get(struct rsnd_priv *priv, int id) | |||
239 | return &((struct rsnd_dvc *)(priv->dvc) + id)->mod; | 268 | return &((struct rsnd_dvc *)(priv->dvc) + id)->mod; |
240 | } | 269 | } |
241 | 270 | ||
271 | static void rsnd_of_parse_dvc(struct platform_device *pdev, | ||
272 | const struct rsnd_of_data *of_data, | ||
273 | struct rsnd_priv *priv) | ||
274 | { | ||
275 | struct device_node *node; | ||
276 | struct rsnd_dvc_platform_info *dvc_info; | ||
277 | struct rcar_snd_info *info = rsnd_priv_to_info(priv); | ||
278 | struct device *dev = &pdev->dev; | ||
279 | int nr; | ||
280 | |||
281 | if (!of_data) | ||
282 | return; | ||
283 | |||
284 | node = of_get_child_by_name(dev->of_node, "rcar_sound,dvc"); | ||
285 | if (!node) | ||
286 | return; | ||
287 | |||
288 | nr = of_get_child_count(node); | ||
289 | if (!nr) | ||
290 | goto rsnd_of_parse_dvc_end; | ||
291 | |||
292 | dvc_info = devm_kzalloc(dev, | ||
293 | sizeof(struct rsnd_dvc_platform_info) * nr, | ||
294 | GFP_KERNEL); | ||
295 | if (!dvc_info) { | ||
296 | dev_err(dev, "dvc info allocation error\n"); | ||
297 | goto rsnd_of_parse_dvc_end; | ||
298 | } | ||
299 | |||
300 | info->dvc_info = dvc_info; | ||
301 | info->dvc_info_nr = nr; | ||
302 | |||
303 | rsnd_of_parse_dvc_end: | ||
304 | of_node_put(node); | ||
305 | } | ||
306 | |||
242 | int rsnd_dvc_probe(struct platform_device *pdev, | 307 | int rsnd_dvc_probe(struct platform_device *pdev, |
243 | const struct rsnd_of_data *of_data, | 308 | const struct rsnd_of_data *of_data, |
244 | struct rsnd_priv *priv) | 309 | struct rsnd_priv *priv) |
@@ -250,6 +315,8 @@ int rsnd_dvc_probe(struct platform_device *pdev, | |||
250 | char name[RSND_DVC_NAME_SIZE]; | 315 | char name[RSND_DVC_NAME_SIZE]; |
251 | int i, nr; | 316 | int i, nr; |
252 | 317 | ||
318 | rsnd_of_parse_dvc(pdev, of_data, priv); | ||
319 | |||
253 | nr = info->dvc_info_nr; | 320 | nr = info->dvc_info_nr; |
254 | if (!nr) | 321 | if (!nr) |
255 | return 0; | 322 | return 0; |
diff --git a/sound/soc/sh/rcar/gen.c b/sound/soc/sh/rcar/gen.c index 0280a11c0899..3fdf3be7b99a 100644 --- a/sound/soc/sh/rcar/gen.c +++ b/sound/soc/sh/rcar/gen.c | |||
@@ -15,63 +15,35 @@ struct rsnd_gen { | |||
15 | 15 | ||
16 | struct rsnd_gen_ops *ops; | 16 | struct rsnd_gen_ops *ops; |
17 | 17 | ||
18 | struct regmap *regmap; | 18 | struct regmap *regmap[RSND_BASE_MAX]; |
19 | struct regmap_field *regs[RSND_REG_MAX]; | 19 | struct regmap_field *regs[RSND_REG_MAX]; |
20 | }; | 20 | }; |
21 | 21 | ||
22 | #define rsnd_priv_to_gen(p) ((struct rsnd_gen *)(p)->gen) | 22 | #define rsnd_priv_to_gen(p) ((struct rsnd_gen *)(p)->gen) |
23 | 23 | ||
24 | #define RSND_REG_SET(gen, id, reg_id, offset, _id_offset, _id_size) \ | 24 | struct rsnd_regmap_field_conf { |
25 | [id] = { \ | 25 | int idx; |
26 | .reg = (unsigned int)gen->base[reg_id] + offset, \ | 26 | unsigned int reg_offset; |
27 | .lsb = 0, \ | 27 | unsigned int id_offset; |
28 | .msb = 31, \ | 28 | }; |
29 | .id_size = _id_size, \ | ||
30 | .id_offset = _id_offset, \ | ||
31 | } | ||
32 | |||
33 | /* | ||
34 | * basic function | ||
35 | */ | ||
36 | static int rsnd_regmap_write32(void *context, const void *_data, size_t count) | ||
37 | { | ||
38 | struct rsnd_priv *priv = context; | ||
39 | struct device *dev = rsnd_priv_to_dev(priv); | ||
40 | u32 *data = (u32 *)_data; | ||
41 | u32 val = data[1]; | ||
42 | void __iomem *reg = (void *)data[0]; | ||
43 | |||
44 | iowrite32(val, reg); | ||
45 | |||
46 | dev_dbg(dev, "w %p : %08x\n", reg, val); | ||
47 | |||
48 | return 0; | ||
49 | } | ||
50 | |||
51 | static int rsnd_regmap_read32(void *context, | ||
52 | const void *_data, size_t reg_size, | ||
53 | void *_val, size_t val_size) | ||
54 | { | ||
55 | struct rsnd_priv *priv = context; | ||
56 | struct device *dev = rsnd_priv_to_dev(priv); | ||
57 | u32 *data = (u32 *)_data; | ||
58 | u32 *val = (u32 *)_val; | ||
59 | void __iomem *reg = (void *)data[0]; | ||
60 | |||
61 | *val = ioread32(reg); | ||
62 | |||
63 | dev_dbg(dev, "r %p : %08x\n", reg, *val); | ||
64 | 29 | ||
65 | return 0; | 30 | #define RSND_REG_SET(id, offset, _id_offset) \ |
31 | { \ | ||
32 | .idx = id, \ | ||
33 | .reg_offset = offset, \ | ||
34 | .id_offset = _id_offset, \ | ||
66 | } | 35 | } |
36 | /* single address mapping */ | ||
37 | #define RSND_GEN_S_REG(id, offset) \ | ||
38 | RSND_REG_SET(RSND_REG_##id, offset, 0) | ||
67 | 39 | ||
68 | static struct regmap_bus rsnd_regmap_bus = { | 40 | /* multi address mapping */ |
69 | .write = rsnd_regmap_write32, | 41 | #define RSND_GEN_M_REG(id, offset, _id_offset) \ |
70 | .read = rsnd_regmap_read32, | 42 | RSND_REG_SET(RSND_REG_##id, offset, _id_offset) |
71 | .reg_format_endian_default = REGMAP_ENDIAN_NATIVE, | ||
72 | .val_format_endian_default = REGMAP_ENDIAN_NATIVE, | ||
73 | }; | ||
74 | 43 | ||
44 | /* | ||
45 | * basic function | ||
46 | */ | ||
75 | static int rsnd_is_accessible_reg(struct rsnd_priv *priv, | 47 | static int rsnd_is_accessible_reg(struct rsnd_priv *priv, |
76 | struct rsnd_gen *gen, enum rsnd_reg reg) | 48 | struct rsnd_gen *gen, enum rsnd_reg reg) |
77 | { | 49 | { |
@@ -88,6 +60,7 @@ static int rsnd_is_accessible_reg(struct rsnd_priv *priv, | |||
88 | u32 rsnd_read(struct rsnd_priv *priv, | 60 | u32 rsnd_read(struct rsnd_priv *priv, |
89 | struct rsnd_mod *mod, enum rsnd_reg reg) | 61 | struct rsnd_mod *mod, enum rsnd_reg reg) |
90 | { | 62 | { |
63 | struct device *dev = rsnd_priv_to_dev(priv); | ||
91 | struct rsnd_gen *gen = rsnd_priv_to_gen(priv); | 64 | struct rsnd_gen *gen = rsnd_priv_to_gen(priv); |
92 | u32 val; | 65 | u32 val; |
93 | 66 | ||
@@ -96,6 +69,8 @@ u32 rsnd_read(struct rsnd_priv *priv, | |||
96 | 69 | ||
97 | regmap_fields_read(gen->regs[reg], rsnd_mod_id(mod), &val); | 70 | regmap_fields_read(gen->regs[reg], rsnd_mod_id(mod), &val); |
98 | 71 | ||
72 | dev_dbg(dev, "r %s - 0x%04d : %08x\n", rsnd_mod_name(mod), reg, val); | ||
73 | |||
99 | return val; | 74 | return val; |
100 | } | 75 | } |
101 | 76 | ||
@@ -103,17 +78,21 @@ void rsnd_write(struct rsnd_priv *priv, | |||
103 | struct rsnd_mod *mod, | 78 | struct rsnd_mod *mod, |
104 | enum rsnd_reg reg, u32 data) | 79 | enum rsnd_reg reg, u32 data) |
105 | { | 80 | { |
81 | struct device *dev = rsnd_priv_to_dev(priv); | ||
106 | struct rsnd_gen *gen = rsnd_priv_to_gen(priv); | 82 | struct rsnd_gen *gen = rsnd_priv_to_gen(priv); |
107 | 83 | ||
108 | if (!rsnd_is_accessible_reg(priv, gen, reg)) | 84 | if (!rsnd_is_accessible_reg(priv, gen, reg)) |
109 | return; | 85 | return; |
110 | 86 | ||
111 | regmap_fields_write(gen->regs[reg], rsnd_mod_id(mod), data); | 87 | regmap_fields_write(gen->regs[reg], rsnd_mod_id(mod), data); |
88 | |||
89 | dev_dbg(dev, "w %s - 0x%04d : %08x\n", rsnd_mod_name(mod), reg, data); | ||
112 | } | 90 | } |
113 | 91 | ||
114 | void rsnd_bset(struct rsnd_priv *priv, struct rsnd_mod *mod, | 92 | void rsnd_bset(struct rsnd_priv *priv, struct rsnd_mod *mod, |
115 | enum rsnd_reg reg, u32 mask, u32 data) | 93 | enum rsnd_reg reg, u32 mask, u32 data) |
116 | { | 94 | { |
95 | struct device *dev = rsnd_priv_to_dev(priv); | ||
117 | struct rsnd_gen *gen = rsnd_priv_to_gen(priv); | 96 | struct rsnd_gen *gen = rsnd_priv_to_gen(priv); |
118 | 97 | ||
119 | if (!rsnd_is_accessible_reg(priv, gen, reg)) | 98 | if (!rsnd_is_accessible_reg(priv, gen, reg)) |
@@ -121,35 +100,63 @@ void rsnd_bset(struct rsnd_priv *priv, struct rsnd_mod *mod, | |||
121 | 100 | ||
122 | regmap_fields_update_bits(gen->regs[reg], rsnd_mod_id(mod), | 101 | regmap_fields_update_bits(gen->regs[reg], rsnd_mod_id(mod), |
123 | mask, data); | 102 | mask, data); |
103 | |||
104 | dev_dbg(dev, "b %s - 0x%04d : %08x/%08x\n", | ||
105 | rsnd_mod_name(mod), reg, data, mask); | ||
124 | } | 106 | } |
125 | 107 | ||
126 | static int rsnd_gen_regmap_init(struct rsnd_priv *priv, | 108 | #define rsnd_gen_regmap_init(priv, id_size, reg_id, conf) \ |
127 | struct rsnd_gen *gen, | 109 | _rsnd_gen_regmap_init(priv, id_size, reg_id, conf, ARRAY_SIZE(conf)) |
128 | struct reg_field *regf) | 110 | static int _rsnd_gen_regmap_init(struct rsnd_priv *priv, |
111 | int id_size, | ||
112 | int reg_id, | ||
113 | struct rsnd_regmap_field_conf *conf, | ||
114 | int conf_size) | ||
129 | { | 115 | { |
130 | int i; | 116 | struct platform_device *pdev = rsnd_priv_to_pdev(priv); |
117 | struct rsnd_gen *gen = rsnd_priv_to_gen(priv); | ||
131 | struct device *dev = rsnd_priv_to_dev(priv); | 118 | struct device *dev = rsnd_priv_to_dev(priv); |
119 | struct resource *res; | ||
132 | struct regmap_config regc; | 120 | struct regmap_config regc; |
121 | struct regmap_field *regs; | ||
122 | struct regmap *regmap; | ||
123 | struct reg_field regf; | ||
124 | void __iomem *base; | ||
125 | int i; | ||
133 | 126 | ||
134 | memset(®c, 0, sizeof(regc)); | 127 | memset(®c, 0, sizeof(regc)); |
135 | regc.reg_bits = 32; | 128 | regc.reg_bits = 32; |
136 | regc.val_bits = 32; | 129 | regc.val_bits = 32; |
130 | regc.reg_stride = 4; | ||
137 | 131 | ||
138 | gen->regmap = devm_regmap_init(dev, &rsnd_regmap_bus, priv, ®c); | 132 | res = platform_get_resource(pdev, IORESOURCE_MEM, reg_id); |
139 | if (IS_ERR(gen->regmap)) { | 133 | if (!res) |
140 | dev_err(dev, "regmap error %ld\n", PTR_ERR(gen->regmap)); | 134 | return -ENODEV; |
141 | return PTR_ERR(gen->regmap); | 135 | |
142 | } | 136 | base = devm_ioremap_resource(dev, res); |
137 | if (IS_ERR(base)) | ||
138 | return PTR_ERR(base); | ||
139 | |||
140 | regmap = devm_regmap_init_mmio(dev, base, ®c); | ||
141 | if (IS_ERR(regmap)) | ||
142 | return PTR_ERR(regmap); | ||
143 | |||
144 | gen->base[reg_id] = base; | ||
145 | gen->regmap[reg_id] = regmap; | ||
143 | 146 | ||
144 | for (i = 0; i < RSND_REG_MAX; i++) { | 147 | for (i = 0; i < conf_size; i++) { |
145 | gen->regs[i] = NULL; | ||
146 | if (!regf[i].reg) | ||
147 | continue; | ||
148 | 148 | ||
149 | gen->regs[i] = devm_regmap_field_alloc(dev, gen->regmap, regf[i]); | 149 | regf.reg = conf[i].reg_offset; |
150 | if (IS_ERR(gen->regs[i])) | 150 | regf.id_offset = conf[i].id_offset; |
151 | return PTR_ERR(gen->regs[i]); | 151 | regf.lsb = 0; |
152 | regf.msb = 31; | ||
153 | regf.id_size = id_size; | ||
152 | 154 | ||
155 | regs = devm_regmap_field_alloc(dev, regmap, regf); | ||
156 | if (IS_ERR(regs)) | ||
157 | return PTR_ERR(regs); | ||
158 | |||
159 | gen->regs[conf[i].idx] = regs; | ||
153 | } | 160 | } |
154 | 161 | ||
155 | return 0; | 162 | return 0; |
@@ -165,15 +172,19 @@ static int rsnd_gen_regmap_init(struct rsnd_priv *priv, | |||
165 | * | 172 | * |
166 | * ex) R-Car H2 case | 173 | * ex) R-Car H2 case |
167 | * mod / DMAC in / DMAC out / DMAC PP in / DMAC pp out | 174 | * mod / DMAC in / DMAC out / DMAC PP in / DMAC pp out |
168 | * SSI : 0xec541000 / 0xec241008 / 0xec24100c / 0xec400000 / 0xec400000 | 175 | * SSI : 0xec541000 / 0xec241008 / 0xec24100c |
176 | * SSIU: 0xec541000 / 0xec100000 / 0xec100000 / 0xec400000 / 0xec400000 | ||
169 | * SCU : 0xec500000 / 0xec000000 / 0xec004000 / 0xec300000 / 0xec304000 | 177 | * SCU : 0xec500000 / 0xec000000 / 0xec004000 / 0xec300000 / 0xec304000 |
170 | * CMD : 0xec500000 / 0xec008000 0xec308000 | 178 | * CMD : 0xec500000 / / 0xec008000 0xec308000 |
171 | */ | 179 | */ |
172 | #define RDMA_SSI_I_N(addr, i) (addr ##_reg - 0x00300000 + (0x40 * i) + 0x8) | 180 | #define RDMA_SSI_I_N(addr, i) (addr ##_reg - 0x00300000 + (0x40 * i) + 0x8) |
173 | #define RDMA_SSI_O_N(addr, i) (addr ##_reg - 0x00300000 + (0x40 * i) + 0xc) | 181 | #define RDMA_SSI_O_N(addr, i) (addr ##_reg - 0x00300000 + (0x40 * i) + 0xc) |
174 | 182 | ||
175 | #define RDMA_SSI_I_P(addr, i) (addr ##_reg - 0x00141000 + (0x1000 * i)) | 183 | #define RDMA_SSIU_I_N(addr, i) (addr ##_reg - 0x00441000 + (0x1000 * i)) |
176 | #define RDMA_SSI_O_P(addr, i) (addr ##_reg - 0x00141000 + (0x1000 * i)) | 184 | #define RDMA_SSIU_O_N(addr, i) (addr ##_reg - 0x00441000 + (0x1000 * i)) |
185 | |||
186 | #define RDMA_SSIU_I_P(addr, i) (addr ##_reg - 0x00141000 + (0x1000 * i)) | ||
187 | #define RDMA_SSIU_O_P(addr, i) (addr ##_reg - 0x00141000 + (0x1000 * i)) | ||
177 | 188 | ||
178 | #define RDMA_SRC_I_N(addr, i) (addr ##_reg - 0x00500000 + (0x400 * i)) | 189 | #define RDMA_SRC_I_N(addr, i) (addr ##_reg - 0x00500000 + (0x400 * i)) |
179 | #define RDMA_SRC_O_N(addr, i) (addr ##_reg - 0x004fc000 + (0x400 * i)) | 190 | #define RDMA_SRC_O_N(addr, i) (addr ##_reg - 0x004fc000 + (0x400 * i)) |
@@ -184,14 +195,13 @@ static int rsnd_gen_regmap_init(struct rsnd_priv *priv, | |||
184 | #define RDMA_CMD_O_N(addr, i) (addr ##_reg - 0x004f8000 + (0x400 * i)) | 195 | #define RDMA_CMD_O_N(addr, i) (addr ##_reg - 0x004f8000 + (0x400 * i)) |
185 | #define RDMA_CMD_O_P(addr, i) (addr ##_reg - 0x001f8000 + (0x400 * i)) | 196 | #define RDMA_CMD_O_P(addr, i) (addr ##_reg - 0x001f8000 + (0x400 * i)) |
186 | 197 | ||
187 | static void rsnd_gen2_dma_addr(struct rsnd_priv *priv, | 198 | static dma_addr_t |
188 | struct rsnd_dma *dma, | 199 | rsnd_gen2_dma_addr(struct rsnd_priv *priv, |
189 | struct dma_slave_config *cfg, | 200 | struct rsnd_mod *mod, |
190 | int is_play, int slave_id) | 201 | int is_play, int is_from) |
191 | { | 202 | { |
192 | struct platform_device *pdev = rsnd_priv_to_pdev(priv); | 203 | struct platform_device *pdev = rsnd_priv_to_pdev(priv); |
193 | struct device *dev = rsnd_priv_to_dev(priv); | 204 | struct device *dev = rsnd_priv_to_dev(priv); |
194 | struct rsnd_mod *mod = rsnd_dma_to_mod(dma); | ||
195 | struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); | 205 | struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); |
196 | dma_addr_t ssi_reg = platform_get_resource(pdev, | 206 | dma_addr_t ssi_reg = platform_get_resource(pdev, |
197 | IORESOURCE_MEM, RSND_GEN2_SSI)->start; | 207 | IORESOURCE_MEM, RSND_GEN2_SSI)->start; |
@@ -202,179 +212,152 @@ static void rsnd_gen2_dma_addr(struct rsnd_priv *priv, | |||
202 | int use_dvc = !!rsnd_io_to_mod_dvc(io); | 212 | int use_dvc = !!rsnd_io_to_mod_dvc(io); |
203 | int id = rsnd_mod_id(mod); | 213 | int id = rsnd_mod_id(mod); |
204 | struct dma_addr { | 214 | struct dma_addr { |
205 | dma_addr_t src_addr; | 215 | dma_addr_t out_addr; |
206 | dma_addr_t dst_addr; | 216 | dma_addr_t in_addr; |
207 | } dma_addrs[2][2][3] = { | 217 | } dma_addrs[3][2][3] = { |
208 | { /* SRC */ | 218 | /* SRC */ |
209 | /* Capture */ | 219 | {{{ 0, 0 }, |
210 | {{ 0, 0 }, | 220 | /* Capture */ |
211 | { RDMA_SRC_O_N(src, id), 0 }, | 221 | { RDMA_SRC_O_N(src, id), RDMA_SRC_I_P(src, id) }, |
212 | { RDMA_CMD_O_N(src, id), 0 }}, | 222 | { RDMA_CMD_O_N(src, id), RDMA_SRC_I_P(src, id) } }, |
213 | /* Playback */ | 223 | /* Playback */ |
214 | {{ 0, 0, }, | 224 | {{ 0, 0, }, |
215 | { 0, RDMA_SRC_I_N(src, id) }, | 225 | { RDMA_SRC_O_P(src, id), RDMA_SRC_I_N(src, id) }, |
216 | { 0, RDMA_SRC_I_N(src, id) }} | 226 | { RDMA_CMD_O_P(src, id), RDMA_SRC_I_N(src, id) } } |
217 | }, { /* SSI */ | 227 | }, |
218 | /* Capture */ | 228 | /* SSI */ |
219 | {{ RDMA_SSI_O_N(ssi, id), 0 }, | 229 | /* Capture */ |
220 | { RDMA_SSI_O_P(ssi, id), RDMA_SRC_I_P(src, id) }, | 230 | {{{ RDMA_SSI_O_N(ssi, id), 0 }, |
221 | { RDMA_SSI_O_P(ssi, id), RDMA_SRC_I_P(src, id) }}, | 231 | { RDMA_SSIU_O_P(ssi, id), 0 }, |
222 | /* Playback */ | 232 | { RDMA_SSIU_O_P(ssi, id), 0 } }, |
223 | {{ 0, RDMA_SSI_I_N(ssi, id) }, | 233 | /* Playback */ |
224 | { RDMA_SRC_O_P(src, id), RDMA_SSI_I_P(ssi, id) }, | 234 | {{ 0, RDMA_SSI_I_N(ssi, id) }, |
225 | { RDMA_CMD_O_P(src, id), RDMA_SSI_I_P(ssi, id) }} | 235 | { 0, RDMA_SSIU_I_P(ssi, id) }, |
226 | } | 236 | { 0, RDMA_SSIU_I_P(ssi, id) } } |
237 | }, | ||
238 | /* SSIU */ | ||
239 | /* Capture */ | ||
240 | {{{ RDMA_SSIU_O_N(ssi, id), 0 }, | ||
241 | { RDMA_SSIU_O_P(ssi, id), 0 }, | ||
242 | { RDMA_SSIU_O_P(ssi, id), 0 } }, | ||
243 | /* Playback */ | ||
244 | {{ 0, RDMA_SSIU_I_N(ssi, id) }, | ||
245 | { 0, RDMA_SSIU_I_P(ssi, id) }, | ||
246 | { 0, RDMA_SSIU_I_P(ssi, id) } } }, | ||
227 | }; | 247 | }; |
228 | 248 | ||
229 | /* it shouldn't happen */ | 249 | /* it shouldn't happen */ |
230 | if (use_dvc & !use_src) { | 250 | if (use_dvc & !use_src) |
231 | dev_err(dev, "DVC is selected without SRC\n"); | 251 | dev_err(dev, "DVC is selected without SRC\n"); |
232 | return; | ||
233 | } | ||
234 | 252 | ||
235 | cfg->src_addr = dma_addrs[is_ssi][is_play][use_src + use_dvc].src_addr; | 253 | /* use SSIU or SSI ? */ |
236 | cfg->dst_addr = dma_addrs[is_ssi][is_play][use_src + use_dvc].dst_addr; | 254 | if (is_ssi && (0 == strcmp(rsnd_mod_dma_name(mod), "ssiu"))) |
255 | is_ssi++; | ||
237 | 256 | ||
238 | dev_dbg(dev, "dma%d addr - src : %x / dst : %x\n", | 257 | return (is_from) ? |
239 | id, cfg->src_addr, cfg->dst_addr); | 258 | dma_addrs[is_ssi][is_play][use_src + use_dvc].out_addr : |
259 | dma_addrs[is_ssi][is_play][use_src + use_dvc].in_addr; | ||
240 | } | 260 | } |
241 | 261 | ||
242 | void rsnd_gen_dma_addr(struct rsnd_priv *priv, | 262 | dma_addr_t rsnd_gen_dma_addr(struct rsnd_priv *priv, |
243 | struct rsnd_dma *dma, | 263 | struct rsnd_mod *mod, |
244 | struct dma_slave_config *cfg, | 264 | int is_play, int is_from) |
245 | int is_play, int slave_id) | ||
246 | { | 265 | { |
247 | cfg->slave_id = slave_id; | ||
248 | cfg->src_addr = 0; | ||
249 | cfg->dst_addr = 0; | ||
250 | cfg->direction = is_play ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM; | ||
251 | |||
252 | /* | 266 | /* |
253 | * gen1 uses default DMA addr | 267 | * gen1 uses default DMA addr |
254 | */ | 268 | */ |
255 | if (rsnd_is_gen1(priv)) | 269 | if (rsnd_is_gen1(priv)) |
256 | return; | 270 | return 0; |
257 | 271 | ||
258 | rsnd_gen2_dma_addr(priv, dma, cfg, is_play, slave_id); | 272 | if (!mod) |
259 | } | 273 | return 0; |
260 | 274 | ||
275 | return rsnd_gen2_dma_addr(priv, mod, is_play, is_from); | ||
276 | } | ||
261 | 277 | ||
262 | /* | 278 | /* |
263 | * Gen2 | 279 | * Gen2 |
264 | */ | 280 | */ |
265 | |||
266 | /* single address mapping */ | ||
267 | #define RSND_GEN2_S_REG(gen, reg, id, offset) \ | ||
268 | RSND_REG_SET(gen, RSND_REG_##id, RSND_GEN2_##reg, offset, 0, 10) | ||
269 | |||
270 | /* multi address mapping */ | ||
271 | #define RSND_GEN2_M_REG(gen, reg, id, offset, _id_offset) \ | ||
272 | RSND_REG_SET(gen, RSND_REG_##id, RSND_GEN2_##reg, offset, _id_offset, 10) | ||
273 | |||
274 | static int rsnd_gen2_regmap_init(struct rsnd_priv *priv, struct rsnd_gen *gen) | ||
275 | { | ||
276 | struct reg_field regf[RSND_REG_MAX] = { | ||
277 | RSND_GEN2_S_REG(gen, SSIU, SSI_MODE0, 0x800), | ||
278 | RSND_GEN2_S_REG(gen, SSIU, SSI_MODE1, 0x804), | ||
279 | /* FIXME: it needs SSI_MODE2/3 in the future */ | ||
280 | RSND_GEN2_M_REG(gen, SSIU, SSI_BUSIF_MODE, 0x0, 0x80), | ||
281 | RSND_GEN2_M_REG(gen, SSIU, SSI_BUSIF_ADINR,0x4, 0x80), | ||
282 | RSND_GEN2_M_REG(gen, SSIU, SSI_CTRL, 0x10, 0x80), | ||
283 | RSND_GEN2_M_REG(gen, SSIU, INT_ENABLE, 0x18, 0x80), | ||
284 | |||
285 | RSND_GEN2_M_REG(gen, SCU, SRC_BUSIF_MODE, 0x0, 0x20), | ||
286 | RSND_GEN2_M_REG(gen, SCU, SRC_ROUTE_MODE0,0xc, 0x20), | ||
287 | RSND_GEN2_M_REG(gen, SCU, SRC_CTRL, 0x10, 0x20), | ||
288 | RSND_GEN2_M_REG(gen, SCU, CMD_ROUTE_SLCT, 0x18c, 0x20), | ||
289 | RSND_GEN2_M_REG(gen, SCU, CMD_CTRL, 0x190, 0x20), | ||
290 | RSND_GEN2_M_REG(gen, SCU, SRC_SWRSR, 0x200, 0x40), | ||
291 | RSND_GEN2_M_REG(gen, SCU, SRC_SRCIR, 0x204, 0x40), | ||
292 | RSND_GEN2_M_REG(gen, SCU, SRC_ADINR, 0x214, 0x40), | ||
293 | RSND_GEN2_M_REG(gen, SCU, SRC_IFSCR, 0x21c, 0x40), | ||
294 | RSND_GEN2_M_REG(gen, SCU, SRC_IFSVR, 0x220, 0x40), | ||
295 | RSND_GEN2_M_REG(gen, SCU, SRC_SRCCR, 0x224, 0x40), | ||
296 | RSND_GEN2_M_REG(gen, SCU, SRC_BSDSR, 0x22c, 0x40), | ||
297 | RSND_GEN2_M_REG(gen, SCU, SRC_BSISR, 0x238, 0x40), | ||
298 | RSND_GEN2_M_REG(gen, SCU, DVC_SWRSR, 0xe00, 0x100), | ||
299 | RSND_GEN2_M_REG(gen, SCU, DVC_DVUIR, 0xe04, 0x100), | ||
300 | RSND_GEN2_M_REG(gen, SCU, DVC_ADINR, 0xe08, 0x100), | ||
301 | RSND_GEN2_M_REG(gen, SCU, DVC_DVUCR, 0xe10, 0x100), | ||
302 | RSND_GEN2_M_REG(gen, SCU, DVC_ZCMCR, 0xe14, 0x100), | ||
303 | RSND_GEN2_M_REG(gen, SCU, DVC_VOL0R, 0xe28, 0x100), | ||
304 | RSND_GEN2_M_REG(gen, SCU, DVC_VOL1R, 0xe2c, 0x100), | ||
305 | RSND_GEN2_M_REG(gen, SCU, DVC_DVUER, 0xe48, 0x100), | ||
306 | |||
307 | RSND_GEN2_S_REG(gen, ADG, BRRA, 0x00), | ||
308 | RSND_GEN2_S_REG(gen, ADG, BRRB, 0x04), | ||
309 | RSND_GEN2_S_REG(gen, ADG, SSICKR, 0x08), | ||
310 | RSND_GEN2_S_REG(gen, ADG, AUDIO_CLK_SEL0, 0x0c), | ||
311 | RSND_GEN2_S_REG(gen, ADG, AUDIO_CLK_SEL1, 0x10), | ||
312 | RSND_GEN2_S_REG(gen, ADG, AUDIO_CLK_SEL2, 0x14), | ||
313 | RSND_GEN2_S_REG(gen, ADG, DIV_EN, 0x30), | ||
314 | RSND_GEN2_S_REG(gen, ADG, SRCIN_TIMSEL0, 0x34), | ||
315 | RSND_GEN2_S_REG(gen, ADG, SRCIN_TIMSEL1, 0x38), | ||
316 | RSND_GEN2_S_REG(gen, ADG, SRCIN_TIMSEL2, 0x3c), | ||
317 | RSND_GEN2_S_REG(gen, ADG, SRCIN_TIMSEL3, 0x40), | ||
318 | RSND_GEN2_S_REG(gen, ADG, SRCIN_TIMSEL4, 0x44), | ||
319 | RSND_GEN2_S_REG(gen, ADG, SRCOUT_TIMSEL0, 0x48), | ||
320 | RSND_GEN2_S_REG(gen, ADG, SRCOUT_TIMSEL1, 0x4c), | ||
321 | RSND_GEN2_S_REG(gen, ADG, SRCOUT_TIMSEL2, 0x50), | ||
322 | RSND_GEN2_S_REG(gen, ADG, SRCOUT_TIMSEL3, 0x54), | ||
323 | RSND_GEN2_S_REG(gen, ADG, SRCOUT_TIMSEL4, 0x58), | ||
324 | RSND_GEN2_S_REG(gen, ADG, CMDOUT_TIMSEL, 0x5c), | ||
325 | |||
326 | RSND_GEN2_M_REG(gen, SSI, SSICR, 0x00, 0x40), | ||
327 | RSND_GEN2_M_REG(gen, SSI, SSISR, 0x04, 0x40), | ||
328 | RSND_GEN2_M_REG(gen, SSI, SSITDR, 0x08, 0x40), | ||
329 | RSND_GEN2_M_REG(gen, SSI, SSIRDR, 0x0c, 0x40), | ||
330 | RSND_GEN2_M_REG(gen, SSI, SSIWSR, 0x20, 0x40), | ||
331 | }; | ||
332 | |||
333 | return rsnd_gen_regmap_init(priv, gen, regf); | ||
334 | } | ||
335 | |||
336 | static int rsnd_gen2_probe(struct platform_device *pdev, | 281 | static int rsnd_gen2_probe(struct platform_device *pdev, |
337 | struct rsnd_priv *priv) | 282 | struct rsnd_priv *priv) |
338 | { | 283 | { |
339 | struct device *dev = rsnd_priv_to_dev(priv); | 284 | struct device *dev = rsnd_priv_to_dev(priv); |
340 | struct rsnd_gen *gen = rsnd_priv_to_gen(priv); | 285 | struct rsnd_regmap_field_conf conf_ssiu[] = { |
341 | struct resource *scu_res; | 286 | RSND_GEN_S_REG(SSI_MODE0, 0x800), |
342 | struct resource *adg_res; | 287 | RSND_GEN_S_REG(SSI_MODE1, 0x804), |
343 | struct resource *ssiu_res; | 288 | /* FIXME: it needs SSI_MODE2/3 in the future */ |
344 | struct resource *ssi_res; | 289 | RSND_GEN_M_REG(SSI_BUSIF_MODE, 0x0, 0x80), |
345 | int ret; | 290 | RSND_GEN_M_REG(SSI_BUSIF_ADINR, 0x4, 0x80), |
346 | 291 | RSND_GEN_M_REG(BUSIF_DALIGN, 0x8, 0x80), | |
347 | /* | 292 | RSND_GEN_M_REG(SSI_CTRL, 0x10, 0x80), |
348 | * map address | 293 | RSND_GEN_M_REG(INT_ENABLE, 0x18, 0x80), |
349 | */ | 294 | }; |
350 | scu_res = platform_get_resource(pdev, IORESOURCE_MEM, RSND_GEN2_SCU); | 295 | struct rsnd_regmap_field_conf conf_scu[] = { |
351 | adg_res = platform_get_resource(pdev, IORESOURCE_MEM, RSND_GEN2_ADG); | 296 | RSND_GEN_M_REG(SRC_BUSIF_MODE, 0x0, 0x20), |
352 | ssiu_res = platform_get_resource(pdev, IORESOURCE_MEM, RSND_GEN2_SSIU); | 297 | RSND_GEN_M_REG(SRC_ROUTE_MODE0, 0xc, 0x20), |
353 | ssi_res = platform_get_resource(pdev, IORESOURCE_MEM, RSND_GEN2_SSI); | 298 | RSND_GEN_M_REG(SRC_CTRL, 0x10, 0x20), |
354 | 299 | RSND_GEN_M_REG(CMD_ROUTE_SLCT, 0x18c, 0x20), | |
355 | gen->base[RSND_GEN2_SCU] = devm_ioremap_resource(dev, scu_res); | 300 | RSND_GEN_M_REG(CMD_CTRL, 0x190, 0x20), |
356 | gen->base[RSND_GEN2_ADG] = devm_ioremap_resource(dev, adg_res); | 301 | RSND_GEN_M_REG(SRC_SWRSR, 0x200, 0x40), |
357 | gen->base[RSND_GEN2_SSIU] = devm_ioremap_resource(dev, ssiu_res); | 302 | RSND_GEN_M_REG(SRC_SRCIR, 0x204, 0x40), |
358 | gen->base[RSND_GEN2_SSI] = devm_ioremap_resource(dev, ssi_res); | 303 | RSND_GEN_M_REG(SRC_ADINR, 0x214, 0x40), |
359 | if (IS_ERR(gen->base[RSND_GEN2_SCU]) || | 304 | RSND_GEN_M_REG(SRC_IFSCR, 0x21c, 0x40), |
360 | IS_ERR(gen->base[RSND_GEN2_ADG]) || | 305 | RSND_GEN_M_REG(SRC_IFSVR, 0x220, 0x40), |
361 | IS_ERR(gen->base[RSND_GEN2_SSIU]) || | 306 | RSND_GEN_M_REG(SRC_SRCCR, 0x224, 0x40), |
362 | IS_ERR(gen->base[RSND_GEN2_SSI])) | 307 | RSND_GEN_M_REG(SRC_BSDSR, 0x22c, 0x40), |
363 | return -ENODEV; | 308 | RSND_GEN_M_REG(SRC_BSISR, 0x238, 0x40), |
364 | 309 | RSND_GEN_M_REG(DVC_SWRSR, 0xe00, 0x100), | |
365 | ret = rsnd_gen2_regmap_init(priv, gen); | 310 | RSND_GEN_M_REG(DVC_DVUIR, 0xe04, 0x100), |
366 | if (ret < 0) | 311 | RSND_GEN_M_REG(DVC_ADINR, 0xe08, 0x100), |
367 | return ret; | 312 | RSND_GEN_M_REG(DVC_DVUCR, 0xe10, 0x100), |
368 | 313 | RSND_GEN_M_REG(DVC_ZCMCR, 0xe14, 0x100), | |
369 | dev_dbg(dev, "Gen2 device probed\n"); | 314 | RSND_GEN_M_REG(DVC_VOL0R, 0xe28, 0x100), |
370 | dev_dbg(dev, "SCU : %pap => %p\n", &scu_res->start, | 315 | RSND_GEN_M_REG(DVC_VOL1R, 0xe2c, 0x100), |
371 | gen->base[RSND_GEN2_SCU]); | 316 | RSND_GEN_M_REG(DVC_DVUER, 0xe48, 0x100), |
372 | dev_dbg(dev, "ADG : %pap => %p\n", &adg_res->start, | 317 | }; |
373 | gen->base[RSND_GEN2_ADG]); | 318 | struct rsnd_regmap_field_conf conf_adg[] = { |
374 | dev_dbg(dev, "SSIU : %pap => %p\n", &ssiu_res->start, | 319 | RSND_GEN_S_REG(BRRA, 0x00), |
375 | gen->base[RSND_GEN2_SSIU]); | 320 | RSND_GEN_S_REG(BRRB, 0x04), |
376 | dev_dbg(dev, "SSI : %pap => %p\n", &ssi_res->start, | 321 | RSND_GEN_S_REG(SSICKR, 0x08), |
377 | gen->base[RSND_GEN2_SSI]); | 322 | RSND_GEN_S_REG(AUDIO_CLK_SEL0, 0x0c), |
323 | RSND_GEN_S_REG(AUDIO_CLK_SEL1, 0x10), | ||
324 | RSND_GEN_S_REG(AUDIO_CLK_SEL2, 0x14), | ||
325 | RSND_GEN_S_REG(DIV_EN, 0x30), | ||
326 | RSND_GEN_S_REG(SRCIN_TIMSEL0, 0x34), | ||
327 | RSND_GEN_S_REG(SRCIN_TIMSEL1, 0x38), | ||
328 | RSND_GEN_S_REG(SRCIN_TIMSEL2, 0x3c), | ||
329 | RSND_GEN_S_REG(SRCIN_TIMSEL3, 0x40), | ||
330 | RSND_GEN_S_REG(SRCIN_TIMSEL4, 0x44), | ||
331 | RSND_GEN_S_REG(SRCOUT_TIMSEL0, 0x48), | ||
332 | RSND_GEN_S_REG(SRCOUT_TIMSEL1, 0x4c), | ||
333 | RSND_GEN_S_REG(SRCOUT_TIMSEL2, 0x50), | ||
334 | RSND_GEN_S_REG(SRCOUT_TIMSEL3, 0x54), | ||
335 | RSND_GEN_S_REG(SRCOUT_TIMSEL4, 0x58), | ||
336 | RSND_GEN_S_REG(CMDOUT_TIMSEL, 0x5c), | ||
337 | }; | ||
338 | struct rsnd_regmap_field_conf conf_ssi[] = { | ||
339 | RSND_GEN_M_REG(SSICR, 0x00, 0x40), | ||
340 | RSND_GEN_M_REG(SSISR, 0x04, 0x40), | ||
341 | RSND_GEN_M_REG(SSITDR, 0x08, 0x40), | ||
342 | RSND_GEN_M_REG(SSIRDR, 0x0c, 0x40), | ||
343 | RSND_GEN_M_REG(SSIWSR, 0x20, 0x40), | ||
344 | }; | ||
345 | int ret_ssiu; | ||
346 | int ret_scu; | ||
347 | int ret_adg; | ||
348 | int ret_ssi; | ||
349 | |||
350 | ret_ssiu = rsnd_gen_regmap_init(priv, 10, RSND_GEN2_SSIU, conf_ssiu); | ||
351 | ret_scu = rsnd_gen_regmap_init(priv, 10, RSND_GEN2_SCU, conf_scu); | ||
352 | ret_adg = rsnd_gen_regmap_init(priv, 10, RSND_GEN2_ADG, conf_adg); | ||
353 | ret_ssi = rsnd_gen_regmap_init(priv, 10, RSND_GEN2_SSI, conf_ssi); | ||
354 | if (ret_ssiu < 0 || | ||
355 | ret_scu < 0 || | ||
356 | ret_adg < 0 || | ||
357 | ret_ssi < 0) | ||
358 | return ret_ssiu | ret_scu | ret_adg | ret_ssi; | ||
359 | |||
360 | dev_dbg(dev, "Gen2 is probed\n"); | ||
378 | 361 | ||
379 | return 0; | 362 | return 0; |
380 | } | 363 | } |
@@ -383,92 +366,60 @@ static int rsnd_gen2_probe(struct platform_device *pdev, | |||
383 | * Gen1 | 366 | * Gen1 |
384 | */ | 367 | */ |
385 | 368 | ||
386 | /* single address mapping */ | ||
387 | #define RSND_GEN1_S_REG(gen, reg, id, offset) \ | ||
388 | RSND_REG_SET(gen, RSND_REG_##id, RSND_GEN1_##reg, offset, 0, 9) | ||
389 | |||
390 | /* multi address mapping */ | ||
391 | #define RSND_GEN1_M_REG(gen, reg, id, offset, _id_offset) \ | ||
392 | RSND_REG_SET(gen, RSND_REG_##id, RSND_GEN1_##reg, offset, _id_offset, 9) | ||
393 | |||
394 | static int rsnd_gen1_regmap_init(struct rsnd_priv *priv, struct rsnd_gen *gen) | ||
395 | { | ||
396 | struct reg_field regf[RSND_REG_MAX] = { | ||
397 | RSND_GEN1_S_REG(gen, SRU, SRC_ROUTE_SEL, 0x00), | ||
398 | RSND_GEN1_S_REG(gen, SRU, SRC_TMG_SEL0, 0x08), | ||
399 | RSND_GEN1_S_REG(gen, SRU, SRC_TMG_SEL1, 0x0c), | ||
400 | RSND_GEN1_S_REG(gen, SRU, SRC_TMG_SEL2, 0x10), | ||
401 | RSND_GEN1_S_REG(gen, SRU, SRC_ROUTE_CTRL, 0xc0), | ||
402 | RSND_GEN1_S_REG(gen, SRU, SSI_MODE0, 0xD0), | ||
403 | RSND_GEN1_S_REG(gen, SRU, SSI_MODE1, 0xD4), | ||
404 | RSND_GEN1_M_REG(gen, SRU, SRC_BUSIF_MODE, 0x20, 0x4), | ||
405 | RSND_GEN1_M_REG(gen, SRU, SRC_ROUTE_MODE0,0x50, 0x8), | ||
406 | RSND_GEN1_M_REG(gen, SRU, SRC_SWRSR, 0x200, 0x40), | ||
407 | RSND_GEN1_M_REG(gen, SRU, SRC_SRCIR, 0x204, 0x40), | ||
408 | RSND_GEN1_M_REG(gen, SRU, SRC_ADINR, 0x214, 0x40), | ||
409 | RSND_GEN1_M_REG(gen, SRU, SRC_IFSCR, 0x21c, 0x40), | ||
410 | RSND_GEN1_M_REG(gen, SRU, SRC_IFSVR, 0x220, 0x40), | ||
411 | RSND_GEN1_M_REG(gen, SRU, SRC_SRCCR, 0x224, 0x40), | ||
412 | RSND_GEN1_M_REG(gen, SRU, SRC_MNFSR, 0x228, 0x40), | ||
413 | |||
414 | RSND_GEN1_S_REG(gen, ADG, BRRA, 0x00), | ||
415 | RSND_GEN1_S_REG(gen, ADG, BRRB, 0x04), | ||
416 | RSND_GEN1_S_REG(gen, ADG, SSICKR, 0x08), | ||
417 | RSND_GEN1_S_REG(gen, ADG, AUDIO_CLK_SEL0, 0x0c), | ||
418 | RSND_GEN1_S_REG(gen, ADG, AUDIO_CLK_SEL1, 0x10), | ||
419 | RSND_GEN1_S_REG(gen, ADG, AUDIO_CLK_SEL3, 0x18), | ||
420 | RSND_GEN1_S_REG(gen, ADG, AUDIO_CLK_SEL4, 0x1c), | ||
421 | RSND_GEN1_S_REG(gen, ADG, AUDIO_CLK_SEL5, 0x20), | ||
422 | |||
423 | RSND_GEN1_M_REG(gen, SSI, SSICR, 0x00, 0x40), | ||
424 | RSND_GEN1_M_REG(gen, SSI, SSISR, 0x04, 0x40), | ||
425 | RSND_GEN1_M_REG(gen, SSI, SSITDR, 0x08, 0x40), | ||
426 | RSND_GEN1_M_REG(gen, SSI, SSIRDR, 0x0c, 0x40), | ||
427 | RSND_GEN1_M_REG(gen, SSI, SSIWSR, 0x20, 0x40), | ||
428 | }; | ||
429 | |||
430 | return rsnd_gen_regmap_init(priv, gen, regf); | ||
431 | } | ||
432 | |||
433 | static int rsnd_gen1_probe(struct platform_device *pdev, | 369 | static int rsnd_gen1_probe(struct platform_device *pdev, |
434 | struct rsnd_priv *priv) | 370 | struct rsnd_priv *priv) |
435 | { | 371 | { |
436 | struct device *dev = rsnd_priv_to_dev(priv); | 372 | struct device *dev = rsnd_priv_to_dev(priv); |
437 | struct rsnd_gen *gen = rsnd_priv_to_gen(priv); | 373 | struct rsnd_regmap_field_conf conf_sru[] = { |
438 | struct resource *sru_res; | 374 | RSND_GEN_S_REG(SRC_ROUTE_SEL, 0x00), |
439 | struct resource *adg_res; | 375 | RSND_GEN_S_REG(SRC_TMG_SEL0, 0x08), |
440 | struct resource *ssi_res; | 376 | RSND_GEN_S_REG(SRC_TMG_SEL1, 0x0c), |
441 | int ret; | 377 | RSND_GEN_S_REG(SRC_TMG_SEL2, 0x10), |
442 | 378 | RSND_GEN_S_REG(SRC_ROUTE_CTRL, 0xc0), | |
443 | /* | 379 | RSND_GEN_S_REG(SSI_MODE0, 0xD0), |
444 | * map address | 380 | RSND_GEN_S_REG(SSI_MODE1, 0xD4), |
445 | */ | 381 | RSND_GEN_M_REG(SRC_BUSIF_MODE, 0x20, 0x4), |
446 | sru_res = platform_get_resource(pdev, IORESOURCE_MEM, RSND_GEN1_SRU); | 382 | RSND_GEN_M_REG(SRC_ROUTE_MODE0, 0x50, 0x8), |
447 | adg_res = platform_get_resource(pdev, IORESOURCE_MEM, RSND_GEN1_ADG); | 383 | RSND_GEN_M_REG(SRC_SWRSR, 0x200, 0x40), |
448 | ssi_res = platform_get_resource(pdev, IORESOURCE_MEM, RSND_GEN1_SSI); | 384 | RSND_GEN_M_REG(SRC_SRCIR, 0x204, 0x40), |
449 | 385 | RSND_GEN_M_REG(SRC_ADINR, 0x214, 0x40), | |
450 | gen->base[RSND_GEN1_SRU] = devm_ioremap_resource(dev, sru_res); | 386 | RSND_GEN_M_REG(SRC_IFSCR, 0x21c, 0x40), |
451 | gen->base[RSND_GEN1_ADG] = devm_ioremap_resource(dev, adg_res); | 387 | RSND_GEN_M_REG(SRC_IFSVR, 0x220, 0x40), |
452 | gen->base[RSND_GEN1_SSI] = devm_ioremap_resource(dev, ssi_res); | 388 | RSND_GEN_M_REG(SRC_SRCCR, 0x224, 0x40), |
453 | if (IS_ERR(gen->base[RSND_GEN1_SRU]) || | 389 | RSND_GEN_M_REG(SRC_MNFSR, 0x228, 0x40), |
454 | IS_ERR(gen->base[RSND_GEN1_ADG]) || | 390 | }; |
455 | IS_ERR(gen->base[RSND_GEN1_SSI])) | 391 | struct rsnd_regmap_field_conf conf_adg[] = { |
456 | return -ENODEV; | 392 | RSND_GEN_S_REG(BRRA, 0x00), |
393 | RSND_GEN_S_REG(BRRB, 0x04), | ||
394 | RSND_GEN_S_REG(SSICKR, 0x08), | ||
395 | RSND_GEN_S_REG(AUDIO_CLK_SEL0, 0x0c), | ||
396 | RSND_GEN_S_REG(AUDIO_CLK_SEL1, 0x10), | ||
397 | RSND_GEN_S_REG(AUDIO_CLK_SEL3, 0x18), | ||
398 | RSND_GEN_S_REG(AUDIO_CLK_SEL4, 0x1c), | ||
399 | RSND_GEN_S_REG(AUDIO_CLK_SEL5, 0x20), | ||
400 | }; | ||
401 | struct rsnd_regmap_field_conf conf_ssi[] = { | ||
402 | RSND_GEN_M_REG(SSICR, 0x00, 0x40), | ||
403 | RSND_GEN_M_REG(SSISR, 0x04, 0x40), | ||
404 | RSND_GEN_M_REG(SSITDR, 0x08, 0x40), | ||
405 | RSND_GEN_M_REG(SSIRDR, 0x0c, 0x40), | ||
406 | RSND_GEN_M_REG(SSIWSR, 0x20, 0x40), | ||
407 | }; | ||
408 | int ret_sru; | ||
409 | int ret_adg; | ||
410 | int ret_ssi; | ||
457 | 411 | ||
458 | ret = rsnd_gen1_regmap_init(priv, gen); | 412 | ret_sru = rsnd_gen_regmap_init(priv, 9, RSND_GEN1_SRU, conf_sru); |
459 | if (ret < 0) | 413 | ret_adg = rsnd_gen_regmap_init(priv, 9, RSND_GEN1_ADG, conf_adg); |
460 | return ret; | 414 | ret_ssi = rsnd_gen_regmap_init(priv, 9, RSND_GEN1_SSI, conf_ssi); |
415 | if (ret_sru < 0 || | ||
416 | ret_adg < 0 || | ||
417 | ret_ssi < 0) | ||
418 | return ret_sru | ret_adg | ret_ssi; | ||
461 | 419 | ||
462 | dev_dbg(dev, "Gen1 device probed\n"); | 420 | dev_dbg(dev, "Gen1 is probed\n"); |
463 | dev_dbg(dev, "SRU : %pap => %p\n", &sru_res->start, | ||
464 | gen->base[RSND_GEN1_SRU]); | ||
465 | dev_dbg(dev, "ADG : %pap => %p\n", &adg_res->start, | ||
466 | gen->base[RSND_GEN1_ADG]); | ||
467 | dev_dbg(dev, "SSI : %pap => %p\n", &ssi_res->start, | ||
468 | gen->base[RSND_GEN1_SSI]); | ||
469 | 421 | ||
470 | return 0; | 422 | return 0; |
471 | |||
472 | } | 423 | } |
473 | 424 | ||
474 | /* | 425 | /* |
diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index 39d98af5ee05..d119adf97c9c 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h | |||
@@ -90,6 +90,7 @@ enum rsnd_reg { | |||
90 | RSND_REG_SHARE19, | 90 | RSND_REG_SHARE19, |
91 | RSND_REG_SHARE20, | 91 | RSND_REG_SHARE20, |
92 | RSND_REG_SHARE21, | 92 | RSND_REG_SHARE21, |
93 | RSND_REG_SHARE22, | ||
93 | 94 | ||
94 | RSND_REG_MAX, | 95 | RSND_REG_MAX, |
95 | }; | 96 | }; |
@@ -127,6 +128,7 @@ enum rsnd_reg { | |||
127 | #define RSND_REG_AUDIO_CLK_SEL2 RSND_REG_SHARE19 | 128 | #define RSND_REG_AUDIO_CLK_SEL2 RSND_REG_SHARE19 |
128 | #define RSND_REG_CMD_CTRL RSND_REG_SHARE20 | 129 | #define RSND_REG_CMD_CTRL RSND_REG_SHARE20 |
129 | #define RSND_REG_CMDOUT_TIMSEL RSND_REG_SHARE21 | 130 | #define RSND_REG_CMDOUT_TIMSEL RSND_REG_SHARE21 |
131 | #define RSND_REG_BUSIF_DALIGN RSND_REG_SHARE22 | ||
130 | 132 | ||
131 | struct rsnd_of_data; | 133 | struct rsnd_of_data; |
132 | struct rsnd_priv; | 134 | struct rsnd_priv; |
@@ -156,12 +158,9 @@ u32 rsnd_get_adinr(struct rsnd_mod *mod); | |||
156 | */ | 158 | */ |
157 | struct rsnd_dma { | 159 | struct rsnd_dma { |
158 | struct sh_dmae_slave slave; | 160 | struct sh_dmae_slave slave; |
159 | struct work_struct work; | ||
160 | struct dma_chan *chan; | 161 | struct dma_chan *chan; |
161 | enum dma_data_direction dir; | 162 | enum dma_transfer_direction dir; |
162 | 163 | dma_addr_t addr; | |
163 | int submit_loop; | ||
164 | int offset; /* it cares A/B plane */ | ||
165 | }; | 164 | }; |
166 | 165 | ||
167 | void rsnd_dma_start(struct rsnd_dma *dma); | 166 | void rsnd_dma_start(struct rsnd_dma *dma); |
@@ -185,6 +184,7 @@ enum rsnd_mod_type { | |||
185 | 184 | ||
186 | struct rsnd_mod_ops { | 185 | struct rsnd_mod_ops { |
187 | char *name; | 186 | char *name; |
187 | char* (*dma_name)(struct rsnd_mod *mod); | ||
188 | int (*probe)(struct rsnd_mod *mod, | 188 | int (*probe)(struct rsnd_mod *mod, |
189 | struct rsnd_dai *rdai); | 189 | struct rsnd_dai *rdai); |
190 | int (*remove)(struct rsnd_mod *mod, | 190 | int (*remove)(struct rsnd_mod *mod, |
@@ -224,6 +224,7 @@ void rsnd_mod_init(struct rsnd_priv *priv, | |||
224 | enum rsnd_mod_type type, | 224 | enum rsnd_mod_type type, |
225 | int id); | 225 | int id); |
226 | char *rsnd_mod_name(struct rsnd_mod *mod); | 226 | char *rsnd_mod_name(struct rsnd_mod *mod); |
227 | char *rsnd_mod_dma_name(struct rsnd_mod *mod); | ||
227 | 228 | ||
228 | /* | 229 | /* |
229 | * R-Car sound DAI | 230 | * R-Car sound DAI |
@@ -281,10 +282,9 @@ int rsnd_gen_probe(struct platform_device *pdev, | |||
281 | void __iomem *rsnd_gen_reg_get(struct rsnd_priv *priv, | 282 | void __iomem *rsnd_gen_reg_get(struct rsnd_priv *priv, |
282 | struct rsnd_mod *mod, | 283 | struct rsnd_mod *mod, |
283 | enum rsnd_reg reg); | 284 | enum rsnd_reg reg); |
284 | void rsnd_gen_dma_addr(struct rsnd_priv *priv, | 285 | dma_addr_t rsnd_gen_dma_addr(struct rsnd_priv *priv, |
285 | struct rsnd_dma *dma, | 286 | struct rsnd_mod *mod, |
286 | struct dma_slave_config *cfg, | 287 | int is_play, int is_from); |
287 | int is_play, int slave_id); | ||
288 | 288 | ||
289 | #define rsnd_is_gen1(s) (((s)->info->flags & RSND_GEN_MASK) == RSND_GEN1) | 289 | #define rsnd_is_gen1(s) (((s)->info->flags & RSND_GEN_MASK) == RSND_GEN1) |
290 | #define rsnd_is_gen2(s) (((s)->info->flags & RSND_GEN_MASK) == RSND_GEN2) | 290 | #define rsnd_is_gen2(s) (((s)->info->flags & RSND_GEN_MASK) == RSND_GEN2) |
@@ -391,8 +391,12 @@ struct rsnd_mod *rsnd_src_mod_get(struct rsnd_priv *priv, int id); | |||
391 | unsigned int rsnd_src_get_ssi_rate(struct rsnd_priv *priv, | 391 | unsigned int rsnd_src_get_ssi_rate(struct rsnd_priv *priv, |
392 | struct rsnd_dai_stream *io, | 392 | struct rsnd_dai_stream *io, |
393 | struct snd_pcm_runtime *runtime); | 393 | struct snd_pcm_runtime *runtime); |
394 | int rsnd_src_ssi_mode_init(struct rsnd_mod *ssi_mod, | 394 | int rsnd_src_ssiu_start(struct rsnd_mod *ssi_mod, |
395 | struct rsnd_dai *rdai); | 395 | struct rsnd_dai *rdai, |
396 | int use_busif); | ||
397 | int rsnd_src_ssiu_stop(struct rsnd_mod *ssi_mod, | ||
398 | struct rsnd_dai *rdai, | ||
399 | int use_busif); | ||
396 | int rsnd_src_enable_ssi_irq(struct rsnd_mod *ssi_mod, | 400 | int rsnd_src_enable_ssi_irq(struct rsnd_mod *ssi_mod, |
397 | struct rsnd_dai *rdai); | 401 | struct rsnd_dai *rdai); |
398 | 402 | ||
diff --git a/sound/soc/sh/rcar/src.c b/sound/soc/sh/rcar/src.c index 200eda019bc7..9183e0145503 100644 --- a/sound/soc/sh/rcar/src.c +++ b/sound/soc/sh/rcar/src.c | |||
@@ -106,18 +106,19 @@ struct rsnd_src { | |||
106 | /* | 106 | /* |
107 | * Gen1/Gen2 common functions | 107 | * Gen1/Gen2 common functions |
108 | */ | 108 | */ |
109 | int rsnd_src_ssi_mode_init(struct rsnd_mod *ssi_mod, | 109 | int rsnd_src_ssiu_start(struct rsnd_mod *ssi_mod, |
110 | struct rsnd_dai *rdai) | 110 | struct rsnd_dai *rdai, |
111 | int use_busif) | ||
111 | { | 112 | { |
112 | struct rsnd_dai_stream *io = rsnd_mod_to_io(ssi_mod); | 113 | struct rsnd_dai_stream *io = rsnd_mod_to_io(ssi_mod); |
113 | struct rsnd_mod *src_mod = rsnd_io_to_mod_src(io); | 114 | struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); |
114 | int ssi_id = rsnd_mod_id(ssi_mod); | 115 | int ssi_id = rsnd_mod_id(ssi_mod); |
115 | 116 | ||
116 | /* | 117 | /* |
117 | * SSI_MODE0 | 118 | * SSI_MODE0 |
118 | */ | 119 | */ |
119 | rsnd_mod_bset(ssi_mod, SSI_MODE0, (1 << ssi_id), | 120 | rsnd_mod_bset(ssi_mod, SSI_MODE0, (1 << ssi_id), |
120 | src_mod ? 0 : (1 << ssi_id)); | 121 | !use_busif << ssi_id); |
121 | 122 | ||
122 | /* | 123 | /* |
123 | * SSI_MODE1 | 124 | * SSI_MODE1 |
@@ -143,6 +144,46 @@ int rsnd_src_ssi_mode_init(struct rsnd_mod *ssi_mod, | |||
143 | 0x2 << shift : 0x1 << shift); | 144 | 0x2 << shift : 0x1 << shift); |
144 | } | 145 | } |
145 | 146 | ||
147 | /* | ||
148 | * DMA settings for SSIU | ||
149 | */ | ||
150 | if (use_busif) { | ||
151 | u32 val = 0x76543210; | ||
152 | u32 mask = ~0; | ||
153 | |||
154 | rsnd_mod_write(ssi_mod, SSI_BUSIF_ADINR, | ||
155 | rsnd_get_adinr(ssi_mod)); | ||
156 | rsnd_mod_write(ssi_mod, SSI_BUSIF_MODE, 1); | ||
157 | rsnd_mod_write(ssi_mod, SSI_CTRL, 0x1); | ||
158 | |||
159 | mask <<= runtime->channels * 4; | ||
160 | val = val & mask; | ||
161 | |||
162 | switch (runtime->sample_bits) { | ||
163 | case 16: | ||
164 | val |= 0x67452301 & ~mask; | ||
165 | break; | ||
166 | case 32: | ||
167 | val |= 0x76543210 & ~mask; | ||
168 | break; | ||
169 | } | ||
170 | rsnd_mod_write(ssi_mod, BUSIF_DALIGN, val); | ||
171 | |||
172 | } | ||
173 | |||
174 | return 0; | ||
175 | } | ||
176 | |||
177 | int rsnd_src_ssiu_stop(struct rsnd_mod *ssi_mod, | ||
178 | struct rsnd_dai *rdai, | ||
179 | int use_busif) | ||
180 | { | ||
181 | /* | ||
182 | * DMA settings for SSIU | ||
183 | */ | ||
184 | if (use_busif) | ||
185 | rsnd_mod_write(ssi_mod, SSI_CTRL, 0); | ||
186 | |||
146 | return 0; | 187 | return 0; |
147 | } | 188 | } |
148 | 189 | ||
@@ -461,18 +502,45 @@ static struct rsnd_mod_ops rsnd_src_gen1_ops = { | |||
461 | static int rsnd_src_set_convert_rate_gen2(struct rsnd_mod *mod, | 502 | static int rsnd_src_set_convert_rate_gen2(struct rsnd_mod *mod, |
462 | struct rsnd_dai *rdai) | 503 | struct rsnd_dai *rdai) |
463 | { | 504 | { |
505 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); | ||
506 | struct device *dev = rsnd_priv_to_dev(priv); | ||
507 | struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); | ||
508 | struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); | ||
509 | struct rsnd_src *src = rsnd_mod_to_src(mod); | ||
510 | uint ratio; | ||
464 | int ret; | 511 | int ret; |
465 | 512 | ||
513 | /* 6 - 1/6 are very enough ratio for SRC_BSDSR */ | ||
514 | if (!rsnd_src_convert_rate(src)) | ||
515 | ratio = 0; | ||
516 | else if (rsnd_src_convert_rate(src) > runtime->rate) | ||
517 | ratio = 100 * rsnd_src_convert_rate(src) / runtime->rate; | ||
518 | else | ||
519 | ratio = 100 * runtime->rate / rsnd_src_convert_rate(src); | ||
520 | |||
521 | if (ratio > 600) { | ||
522 | dev_err(dev, "FSO/FSI ratio error\n"); | ||
523 | return -EINVAL; | ||
524 | } | ||
525 | |||
466 | ret = rsnd_src_set_convert_rate(mod, rdai); | 526 | ret = rsnd_src_set_convert_rate(mod, rdai); |
467 | if (ret < 0) | 527 | if (ret < 0) |
468 | return ret; | 528 | return ret; |
469 | 529 | ||
470 | rsnd_mod_write(mod, SSI_BUSIF_ADINR, rsnd_get_adinr(mod)); | ||
471 | rsnd_mod_write(mod, SSI_BUSIF_MODE, 1); | ||
472 | |||
473 | rsnd_mod_write(mod, SRC_SRCCR, 0x00011110); | 530 | rsnd_mod_write(mod, SRC_SRCCR, 0x00011110); |
474 | 531 | ||
475 | rsnd_mod_write(mod, SRC_BSDSR, 0x01800000); | 532 | switch (rsnd_mod_id(mod)) { |
533 | case 5: | ||
534 | case 6: | ||
535 | case 7: | ||
536 | case 8: | ||
537 | rsnd_mod_write(mod, SRC_BSDSR, 0x02400000); | ||
538 | break; | ||
539 | default: | ||
540 | rsnd_mod_write(mod, SRC_BSDSR, 0x01800000); | ||
541 | break; | ||
542 | } | ||
543 | |||
476 | rsnd_mod_write(mod, SRC_BSISR, 0x00100060); | 544 | rsnd_mod_write(mod, SRC_BSISR, 0x00100060); |
477 | 545 | ||
478 | return 0; | 546 | return 0; |
@@ -554,7 +622,6 @@ static int rsnd_src_start_gen2(struct rsnd_mod *mod, | |||
554 | 622 | ||
555 | rsnd_dma_start(rsnd_mod_to_dma(&src->mod)); | 623 | rsnd_dma_start(rsnd_mod_to_dma(&src->mod)); |
556 | 624 | ||
557 | rsnd_mod_write(mod, SSI_CTRL, 0x1); | ||
558 | rsnd_mod_write(mod, SRC_CTRL, val); | 625 | rsnd_mod_write(mod, SRC_CTRL, val); |
559 | 626 | ||
560 | return rsnd_src_start(mod, rdai); | 627 | return rsnd_src_start(mod, rdai); |
@@ -565,7 +632,6 @@ static int rsnd_src_stop_gen2(struct rsnd_mod *mod, | |||
565 | { | 632 | { |
566 | struct rsnd_src *src = rsnd_mod_to_src(mod); | 633 | struct rsnd_src *src = rsnd_mod_to_src(mod); |
567 | 634 | ||
568 | rsnd_mod_write(mod, SSI_CTRL, 0); | ||
569 | rsnd_mod_write(mod, SRC_CTRL, 0); | 635 | rsnd_mod_write(mod, SRC_CTRL, 0); |
570 | 636 | ||
571 | rsnd_dma_stop(rsnd_mod_to_dma(&src->mod)); | 637 | rsnd_dma_stop(rsnd_mod_to_dma(&src->mod)); |
diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index 2df723df5d19..34e84009162b 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c | |||
@@ -90,6 +90,20 @@ struct rsnd_ssi { | |||
90 | #define rsnd_ssi_mode_flags(p) ((p)->info->flags) | 90 | #define rsnd_ssi_mode_flags(p) ((p)->info->flags) |
91 | #define rsnd_ssi_dai_id(ssi) ((ssi)->info->dai_id) | 91 | #define rsnd_ssi_dai_id(ssi) ((ssi)->info->dai_id) |
92 | 92 | ||
93 | static int rsnd_ssi_use_busif(struct rsnd_mod *mod) | ||
94 | { | ||
95 | struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); | ||
96 | struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); | ||
97 | int use_busif = 0; | ||
98 | |||
99 | if (!(rsnd_ssi_mode_flags(ssi) & RSND_SSI_NO_BUSIF)) | ||
100 | use_busif = 1; | ||
101 | if (rsnd_io_to_mod_src(io)) | ||
102 | use_busif = 1; | ||
103 | |||
104 | return use_busif; | ||
105 | } | ||
106 | |||
93 | static void rsnd_ssi_status_check(struct rsnd_mod *mod, | 107 | static void rsnd_ssi_status_check(struct rsnd_mod *mod, |
94 | u32 bit) | 108 | u32 bit) |
95 | { | 109 | { |
@@ -289,8 +303,6 @@ static int rsnd_ssi_init(struct rsnd_mod *mod, | |||
289 | ssi->cr_own = cr; | 303 | ssi->cr_own = cr; |
290 | ssi->err = -1; /* ignore 1st error */ | 304 | ssi->err = -1; /* ignore 1st error */ |
291 | 305 | ||
292 | rsnd_src_ssi_mode_init(mod, rdai); | ||
293 | |||
294 | return 0; | 306 | return 0; |
295 | } | 307 | } |
296 | 308 | ||
@@ -389,6 +401,8 @@ static int rsnd_ssi_pio_start(struct rsnd_mod *mod, | |||
389 | /* enable PIO IRQ */ | 401 | /* enable PIO IRQ */ |
390 | ssi->cr_etc = UIEN | OIEN | DIEN; | 402 | ssi->cr_etc = UIEN | OIEN | DIEN; |
391 | 403 | ||
404 | rsnd_src_ssiu_start(mod, rdai, 0); | ||
405 | |||
392 | rsnd_src_enable_ssi_irq(mod, rdai); | 406 | rsnd_src_enable_ssi_irq(mod, rdai); |
393 | 407 | ||
394 | rsnd_ssi_hw_start(ssi, rdai, io); | 408 | rsnd_ssi_hw_start(ssi, rdai, io); |
@@ -405,6 +419,8 @@ static int rsnd_ssi_pio_stop(struct rsnd_mod *mod, | |||
405 | 419 | ||
406 | rsnd_ssi_hw_stop(ssi, rdai); | 420 | rsnd_ssi_hw_stop(ssi, rdai); |
407 | 421 | ||
422 | rsnd_src_ssiu_stop(mod, rdai, 0); | ||
423 | |||
408 | return 0; | 424 | return 0; |
409 | } | 425 | } |
410 | 426 | ||
@@ -457,6 +473,8 @@ static int rsnd_ssi_dma_start(struct rsnd_mod *mod, | |||
457 | /* enable DMA transfer */ | 473 | /* enable DMA transfer */ |
458 | ssi->cr_etc = DMEN; | 474 | ssi->cr_etc = DMEN; |
459 | 475 | ||
476 | rsnd_src_ssiu_start(mod, rdai, rsnd_ssi_use_busif(mod)); | ||
477 | |||
460 | rsnd_dma_start(dma); | 478 | rsnd_dma_start(dma); |
461 | 479 | ||
462 | rsnd_ssi_hw_start(ssi, ssi->rdai, io); | 480 | rsnd_ssi_hw_start(ssi, ssi->rdai, io); |
@@ -482,11 +500,19 @@ static int rsnd_ssi_dma_stop(struct rsnd_mod *mod, | |||
482 | 500 | ||
483 | rsnd_dma_stop(dma); | 501 | rsnd_dma_stop(dma); |
484 | 502 | ||
503 | rsnd_src_ssiu_stop(mod, rdai, 1); | ||
504 | |||
485 | return 0; | 505 | return 0; |
486 | } | 506 | } |
487 | 507 | ||
508 | static char *rsnd_ssi_dma_name(struct rsnd_mod *mod) | ||
509 | { | ||
510 | return rsnd_ssi_use_busif(mod) ? "ssiu" : SSI_NAME; | ||
511 | } | ||
512 | |||
488 | static struct rsnd_mod_ops rsnd_ssi_dma_ops = { | 513 | static struct rsnd_mod_ops rsnd_ssi_dma_ops = { |
489 | .name = SSI_NAME, | 514 | .name = SSI_NAME, |
515 | .dma_name = rsnd_ssi_dma_name, | ||
490 | .probe = rsnd_ssi_dma_probe, | 516 | .probe = rsnd_ssi_dma_probe, |
491 | .remove = rsnd_ssi_dma_remove, | 517 | .remove = rsnd_ssi_dma_remove, |
492 | .init = rsnd_ssi_init, | 518 | .init = rsnd_ssi_init, |
@@ -595,6 +621,9 @@ static void rsnd_of_parse_ssi(struct platform_device *pdev, | |||
595 | */ | 621 | */ |
596 | ssi_info->dma_id = of_get_property(np, "pio-transfer", NULL) ? | 622 | ssi_info->dma_id = of_get_property(np, "pio-transfer", NULL) ? |
597 | 0 : 1; | 623 | 0 : 1; |
624 | |||
625 | if (of_get_property(np, "no-busif", NULL)) | ||
626 | ssi_info->flags |= RSND_SSI_NO_BUSIF; | ||
598 | } | 627 | } |
599 | 628 | ||
600 | rsnd_of_parse_ssi_end: | 629 | rsnd_of_parse_ssi_end: |