diff options
author | Knut Petersen <Knut_Petersen@t-online.de> | 2013-08-13 15:18:12 -0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2013-08-14 11:02:36 -0400 |
commit | b892ca1c9fe71e829e7b9ed79b8398649de259d7 (patch) | |
tree | ecdb5c181dbcbff9df362b64d3b9874e783ed5e1 | |
parent | e80c60f3cbe76fa95029abc53b1a29172b51b96a (diff) |
ALSA: rme96: Add pcm stream synchronization
The hardware does support synchronized start/pause/stop of pcm streams,
so there is no reason not to add that feature after more than ten years.
Some minor coding style / white space fixes in the surroundings of the
changes.
Signed-off-by: Knut Petersen <Knut_Petersen@t-online.de>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
-rw-r--r-- | sound/pci/rme96.c | 185 |
1 files changed, 110 insertions, 75 deletions
diff --git a/sound/pci/rme96.c b/sound/pci/rme96.c index 2a8ad9d1a2ae..4e9a5563eeca 100644 --- a/sound/pci/rme96.c +++ b/sound/pci/rme96.c | |||
@@ -198,6 +198,31 @@ MODULE_PARM_DESC(enable, "Enable RME Digi96 soundcard."); | |||
198 | #define RME96_AD1852_VOL_BITS 14 | 198 | #define RME96_AD1852_VOL_BITS 14 |
199 | #define RME96_AD1855_VOL_BITS 10 | 199 | #define RME96_AD1855_VOL_BITS 10 |
200 | 200 | ||
201 | /* Defines for snd_rme96_trigger */ | ||
202 | #define RME96_TB_START_PLAYBACK 1 | ||
203 | #define RME96_TB_START_CAPTURE 2 | ||
204 | #define RME96_TB_STOP_PLAYBACK 4 | ||
205 | #define RME96_TB_STOP_CAPTURE 8 | ||
206 | #define RME96_TB_RESET_PLAYPOS 16 | ||
207 | #define RME96_TB_RESET_CAPTUREPOS 32 | ||
208 | #define RME96_TB_CLEAR_PLAYBACK_IRQ 64 | ||
209 | #define RME96_TB_CLEAR_CAPTURE_IRQ 128 | ||
210 | #define RME96_RESUME_PLAYBACK (RME96_TB_START_PLAYBACK) | ||
211 | #define RME96_RESUME_CAPTURE (RME96_TB_START_CAPTURE) | ||
212 | #define RME96_RESUME_BOTH (RME96_RESUME_PLAYBACK \ | ||
213 | | RME96_RESUME_CAPTURE) | ||
214 | #define RME96_START_PLAYBACK (RME96_TB_START_PLAYBACK \ | ||
215 | | RME96_TB_RESET_PLAYPOS) | ||
216 | #define RME96_START_CAPTURE (RME96_TB_START_CAPTURE \ | ||
217 | | RME96_TB_RESET_CAPTUREPOS) | ||
218 | #define RME96_START_BOTH (RME96_START_PLAYBACK \ | ||
219 | | RME96_START_CAPTURE) | ||
220 | #define RME96_STOP_PLAYBACK (RME96_TB_STOP_PLAYBACK \ | ||
221 | | RME96_TB_CLEAR_PLAYBACK_IRQ) | ||
222 | #define RME96_STOP_CAPTURE (RME96_TB_STOP_CAPTURE \ | ||
223 | | RME96_TB_CLEAR_CAPTURE_IRQ) | ||
224 | #define RME96_STOP_BOTH (RME96_STOP_PLAYBACK \ | ||
225 | | RME96_STOP_CAPTURE) | ||
201 | 226 | ||
202 | struct rme96 { | 227 | struct rme96 { |
203 | spinlock_t lock; | 228 | spinlock_t lock; |
@@ -344,6 +369,7 @@ static struct snd_pcm_hardware snd_rme96_playback_spdif_info = | |||
344 | { | 369 | { |
345 | .info = (SNDRV_PCM_INFO_MMAP_IOMEM | | 370 | .info = (SNDRV_PCM_INFO_MMAP_IOMEM | |
346 | SNDRV_PCM_INFO_MMAP_VALID | | 371 | SNDRV_PCM_INFO_MMAP_VALID | |
372 | SNDRV_PCM_INFO_SYNC_START | | ||
347 | SNDRV_PCM_INFO_INTERLEAVED | | 373 | SNDRV_PCM_INFO_INTERLEAVED | |
348 | SNDRV_PCM_INFO_PAUSE), | 374 | SNDRV_PCM_INFO_PAUSE), |
349 | .formats = (SNDRV_PCM_FMTBIT_S16_LE | | 375 | .formats = (SNDRV_PCM_FMTBIT_S16_LE | |
@@ -373,6 +399,7 @@ static struct snd_pcm_hardware snd_rme96_capture_spdif_info = | |||
373 | { | 399 | { |
374 | .info = (SNDRV_PCM_INFO_MMAP_IOMEM | | 400 | .info = (SNDRV_PCM_INFO_MMAP_IOMEM | |
375 | SNDRV_PCM_INFO_MMAP_VALID | | 401 | SNDRV_PCM_INFO_MMAP_VALID | |
402 | SNDRV_PCM_INFO_SYNC_START | | ||
376 | SNDRV_PCM_INFO_INTERLEAVED | | 403 | SNDRV_PCM_INFO_INTERLEAVED | |
377 | SNDRV_PCM_INFO_PAUSE), | 404 | SNDRV_PCM_INFO_PAUSE), |
378 | .formats = (SNDRV_PCM_FMTBIT_S16_LE | | 405 | .formats = (SNDRV_PCM_FMTBIT_S16_LE | |
@@ -402,6 +429,7 @@ static struct snd_pcm_hardware snd_rme96_playback_adat_info = | |||
402 | { | 429 | { |
403 | .info = (SNDRV_PCM_INFO_MMAP_IOMEM | | 430 | .info = (SNDRV_PCM_INFO_MMAP_IOMEM | |
404 | SNDRV_PCM_INFO_MMAP_VALID | | 431 | SNDRV_PCM_INFO_MMAP_VALID | |
432 | SNDRV_PCM_INFO_SYNC_START | | ||
405 | SNDRV_PCM_INFO_INTERLEAVED | | 433 | SNDRV_PCM_INFO_INTERLEAVED | |
406 | SNDRV_PCM_INFO_PAUSE), | 434 | SNDRV_PCM_INFO_PAUSE), |
407 | .formats = (SNDRV_PCM_FMTBIT_S16_LE | | 435 | .formats = (SNDRV_PCM_FMTBIT_S16_LE | |
@@ -427,6 +455,7 @@ static struct snd_pcm_hardware snd_rme96_capture_adat_info = | |||
427 | { | 455 | { |
428 | .info = (SNDRV_PCM_INFO_MMAP_IOMEM | | 456 | .info = (SNDRV_PCM_INFO_MMAP_IOMEM | |
429 | SNDRV_PCM_INFO_MMAP_VALID | | 457 | SNDRV_PCM_INFO_MMAP_VALID | |
458 | SNDRV_PCM_INFO_SYNC_START | | ||
430 | SNDRV_PCM_INFO_INTERLEAVED | | 459 | SNDRV_PCM_INFO_INTERLEAVED | |
431 | SNDRV_PCM_INFO_PAUSE), | 460 | SNDRV_PCM_INFO_PAUSE), |
432 | .formats = (SNDRV_PCM_FMTBIT_S16_LE | | 461 | .formats = (SNDRV_PCM_FMTBIT_S16_LE | |
@@ -1045,54 +1074,35 @@ snd_rme96_capture_hw_params(struct snd_pcm_substream *substream, | |||
1045 | } | 1074 | } |
1046 | 1075 | ||
1047 | static void | 1076 | static void |
1048 | snd_rme96_playback_start(struct rme96 *rme96, | 1077 | snd_rme96_trigger(struct rme96 *rme96, |
1049 | int from_pause) | 1078 | int op) |
1050 | { | 1079 | { |
1051 | if (!from_pause) { | 1080 | if (op & RME96_TB_RESET_PLAYPOS) |
1052 | writel(0, rme96->iobase + RME96_IO_RESET_PLAY_POS); | 1081 | writel(0, rme96->iobase + RME96_IO_RESET_PLAY_POS); |
1053 | } | 1082 | if (op & RME96_TB_RESET_CAPTUREPOS) |
1054 | |||
1055 | rme96->wcreg |= RME96_WCR_START; | ||
1056 | writel(rme96->wcreg, rme96->iobase + RME96_IO_CONTROL_REGISTER); | ||
1057 | } | ||
1058 | |||
1059 | static void | ||
1060 | snd_rme96_capture_start(struct rme96 *rme96, | ||
1061 | int from_pause) | ||
1062 | { | ||
1063 | if (!from_pause) { | ||
1064 | writel(0, rme96->iobase + RME96_IO_RESET_REC_POS); | 1083 | writel(0, rme96->iobase + RME96_IO_RESET_REC_POS); |
1065 | } | 1084 | if (op & RME96_TB_CLEAR_PLAYBACK_IRQ) { |
1066 | 1085 | rme96->rcreg = readl(rme96->iobase + RME96_IO_CONTROL_REGISTER); | |
1067 | rme96->wcreg |= RME96_WCR_START_2; | 1086 | if (rme96->rcreg & RME96_RCR_IRQ) |
1087 | writel(0, rme96->iobase + RME96_IO_CONFIRM_PLAY_IRQ); | ||
1088 | } | ||
1089 | if (op & RME96_TB_CLEAR_CAPTURE_IRQ) { | ||
1090 | rme96->rcreg = readl(rme96->iobase + RME96_IO_CONTROL_REGISTER); | ||
1091 | if (rme96->rcreg & RME96_RCR_IRQ_2) | ||
1092 | writel(0, rme96->iobase + RME96_IO_CONFIRM_REC_IRQ); | ||
1093 | } | ||
1094 | if (op & RME96_TB_START_PLAYBACK) | ||
1095 | rme96->wcreg |= RME96_WCR_START; | ||
1096 | if (op & RME96_TB_STOP_PLAYBACK) | ||
1097 | rme96->wcreg &= ~RME96_WCR_START; | ||
1098 | if (op & RME96_TB_START_CAPTURE) | ||
1099 | rme96->wcreg |= RME96_WCR_START_2; | ||
1100 | if (op & RME96_TB_STOP_CAPTURE) | ||
1101 | rme96->wcreg &= ~RME96_WCR_START_2; | ||
1068 | writel(rme96->wcreg, rme96->iobase + RME96_IO_CONTROL_REGISTER); | 1102 | writel(rme96->wcreg, rme96->iobase + RME96_IO_CONTROL_REGISTER); |
1069 | } | 1103 | } |
1070 | 1104 | ||
1071 | static void | ||
1072 | snd_rme96_playback_stop(struct rme96 *rme96) | ||
1073 | { | ||
1074 | /* | ||
1075 | * Check if there is an unconfirmed IRQ, if so confirm it, or else | ||
1076 | * the hardware will not stop generating interrupts | ||
1077 | */ | ||
1078 | rme96->rcreg = readl(rme96->iobase + RME96_IO_CONTROL_REGISTER); | ||
1079 | if (rme96->rcreg & RME96_RCR_IRQ) { | ||
1080 | writel(0, rme96->iobase + RME96_IO_CONFIRM_PLAY_IRQ); | ||
1081 | } | ||
1082 | rme96->wcreg &= ~RME96_WCR_START; | ||
1083 | writel(rme96->wcreg, rme96->iobase + RME96_IO_CONTROL_REGISTER); | ||
1084 | } | ||
1085 | 1105 | ||
1086 | static void | ||
1087 | snd_rme96_capture_stop(struct rme96 *rme96) | ||
1088 | { | ||
1089 | rme96->rcreg = readl(rme96->iobase + RME96_IO_CONTROL_REGISTER); | ||
1090 | if (rme96->rcreg & RME96_RCR_IRQ_2) { | ||
1091 | writel(0, rme96->iobase + RME96_IO_CONFIRM_REC_IRQ); | ||
1092 | } | ||
1093 | rme96->wcreg &= ~RME96_WCR_START_2; | ||
1094 | writel(rme96->wcreg, rme96->iobase + RME96_IO_CONTROL_REGISTER); | ||
1095 | } | ||
1096 | 1106 | ||
1097 | static irqreturn_t | 1107 | static irqreturn_t |
1098 | snd_rme96_interrupt(int irq, | 1108 | snd_rme96_interrupt(int irq, |
@@ -1155,6 +1165,7 @@ snd_rme96_playback_spdif_open(struct snd_pcm_substream *substream) | |||
1155 | struct rme96 *rme96 = snd_pcm_substream_chip(substream); | 1165 | struct rme96 *rme96 = snd_pcm_substream_chip(substream); |
1156 | struct snd_pcm_runtime *runtime = substream->runtime; | 1166 | struct snd_pcm_runtime *runtime = substream->runtime; |
1157 | 1167 | ||
1168 | snd_pcm_set_sync(substream); | ||
1158 | spin_lock_irq(&rme96->lock); | 1169 | spin_lock_irq(&rme96->lock); |
1159 | if (rme96->playback_substream != NULL) { | 1170 | if (rme96->playback_substream != NULL) { |
1160 | spin_unlock_irq(&rme96->lock); | 1171 | spin_unlock_irq(&rme96->lock); |
@@ -1191,6 +1202,7 @@ snd_rme96_capture_spdif_open(struct snd_pcm_substream *substream) | |||
1191 | struct rme96 *rme96 = snd_pcm_substream_chip(substream); | 1202 | struct rme96 *rme96 = snd_pcm_substream_chip(substream); |
1192 | struct snd_pcm_runtime *runtime = substream->runtime; | 1203 | struct snd_pcm_runtime *runtime = substream->runtime; |
1193 | 1204 | ||
1205 | snd_pcm_set_sync(substream); | ||
1194 | runtime->hw = snd_rme96_capture_spdif_info; | 1206 | runtime->hw = snd_rme96_capture_spdif_info; |
1195 | if (snd_rme96_getinputtype(rme96) != RME96_INPUT_ANALOG && | 1207 | if (snd_rme96_getinputtype(rme96) != RME96_INPUT_ANALOG && |
1196 | (rate = snd_rme96_capture_getrate(rme96, &isadat)) > 0) | 1208 | (rate = snd_rme96_capture_getrate(rme96, &isadat)) > 0) |
@@ -1222,6 +1234,7 @@ snd_rme96_playback_adat_open(struct snd_pcm_substream *substream) | |||
1222 | struct rme96 *rme96 = snd_pcm_substream_chip(substream); | 1234 | struct rme96 *rme96 = snd_pcm_substream_chip(substream); |
1223 | struct snd_pcm_runtime *runtime = substream->runtime; | 1235 | struct snd_pcm_runtime *runtime = substream->runtime; |
1224 | 1236 | ||
1237 | snd_pcm_set_sync(substream); | ||
1225 | spin_lock_irq(&rme96->lock); | 1238 | spin_lock_irq(&rme96->lock); |
1226 | if (rme96->playback_substream != NULL) { | 1239 | if (rme96->playback_substream != NULL) { |
1227 | spin_unlock_irq(&rme96->lock); | 1240 | spin_unlock_irq(&rme96->lock); |
@@ -1253,6 +1266,7 @@ snd_rme96_capture_adat_open(struct snd_pcm_substream *substream) | |||
1253 | struct rme96 *rme96 = snd_pcm_substream_chip(substream); | 1266 | struct rme96 *rme96 = snd_pcm_substream_chip(substream); |
1254 | struct snd_pcm_runtime *runtime = substream->runtime; | 1267 | struct snd_pcm_runtime *runtime = substream->runtime; |
1255 | 1268 | ||
1269 | snd_pcm_set_sync(substream); | ||
1256 | runtime->hw = snd_rme96_capture_adat_info; | 1270 | runtime->hw = snd_rme96_capture_adat_info; |
1257 | if (snd_rme96_getinputtype(rme96) == RME96_INPUT_ANALOG) { | 1271 | if (snd_rme96_getinputtype(rme96) == RME96_INPUT_ANALOG) { |
1258 | /* makes no sense to use analog input. Note that analog | 1272 | /* makes no sense to use analog input. Note that analog |
@@ -1288,7 +1302,7 @@ snd_rme96_playback_close(struct snd_pcm_substream *substream) | |||
1288 | 1302 | ||
1289 | spin_lock_irq(&rme96->lock); | 1303 | spin_lock_irq(&rme96->lock); |
1290 | if (RME96_ISPLAYING(rme96)) { | 1304 | if (RME96_ISPLAYING(rme96)) { |
1291 | snd_rme96_playback_stop(rme96); | 1305 | snd_rme96_trigger(rme96, RME96_STOP_PLAYBACK); |
1292 | } | 1306 | } |
1293 | rme96->playback_substream = NULL; | 1307 | rme96->playback_substream = NULL; |
1294 | rme96->playback_periodsize = 0; | 1308 | rme96->playback_periodsize = 0; |
@@ -1309,7 +1323,7 @@ snd_rme96_capture_close(struct snd_pcm_substream *substream) | |||
1309 | 1323 | ||
1310 | spin_lock_irq(&rme96->lock); | 1324 | spin_lock_irq(&rme96->lock); |
1311 | if (RME96_ISRECORDING(rme96)) { | 1325 | if (RME96_ISRECORDING(rme96)) { |
1312 | snd_rme96_capture_stop(rme96); | 1326 | snd_rme96_trigger(rme96, RME96_STOP_CAPTURE); |
1313 | } | 1327 | } |
1314 | rme96->capture_substream = NULL; | 1328 | rme96->capture_substream = NULL; |
1315 | rme96->capture_periodsize = 0; | 1329 | rme96->capture_periodsize = 0; |
@@ -1324,7 +1338,7 @@ snd_rme96_playback_prepare(struct snd_pcm_substream *substream) | |||
1324 | 1338 | ||
1325 | spin_lock_irq(&rme96->lock); | 1339 | spin_lock_irq(&rme96->lock); |
1326 | if (RME96_ISPLAYING(rme96)) { | 1340 | if (RME96_ISPLAYING(rme96)) { |
1327 | snd_rme96_playback_stop(rme96); | 1341 | snd_rme96_trigger(rme96, RME96_STOP_PLAYBACK); |
1328 | } | 1342 | } |
1329 | writel(0, rme96->iobase + RME96_IO_RESET_PLAY_POS); | 1343 | writel(0, rme96->iobase + RME96_IO_RESET_PLAY_POS); |
1330 | spin_unlock_irq(&rme96->lock); | 1344 | spin_unlock_irq(&rme96->lock); |
@@ -1338,7 +1352,7 @@ snd_rme96_capture_prepare(struct snd_pcm_substream *substream) | |||
1338 | 1352 | ||
1339 | spin_lock_irq(&rme96->lock); | 1353 | spin_lock_irq(&rme96->lock); |
1340 | if (RME96_ISRECORDING(rme96)) { | 1354 | if (RME96_ISRECORDING(rme96)) { |
1341 | snd_rme96_capture_stop(rme96); | 1355 | snd_rme96_trigger(rme96, RME96_STOP_CAPTURE); |
1342 | } | 1356 | } |
1343 | writel(0, rme96->iobase + RME96_IO_RESET_REC_POS); | 1357 | writel(0, rme96->iobase + RME96_IO_RESET_REC_POS); |
1344 | spin_unlock_irq(&rme96->lock); | 1358 | spin_unlock_irq(&rme96->lock); |
@@ -1350,41 +1364,53 @@ snd_rme96_playback_trigger(struct snd_pcm_substream *substream, | |||
1350 | int cmd) | 1364 | int cmd) |
1351 | { | 1365 | { |
1352 | struct rme96 *rme96 = snd_pcm_substream_chip(substream); | 1366 | struct rme96 *rme96 = snd_pcm_substream_chip(substream); |
1367 | struct snd_pcm_substream *s; | ||
1368 | bool sync; | ||
1369 | |||
1370 | snd_pcm_group_for_each_entry(s, substream) { | ||
1371 | if (snd_pcm_substream_chip(s) == rme96) | ||
1372 | snd_pcm_trigger_done(s, substream); | ||
1373 | } | ||
1374 | |||
1375 | sync = (rme96->playback_substream && rme96->capture_substream) && | ||
1376 | (rme96->playback_substream->group == | ||
1377 | rme96->capture_substream->group); | ||
1353 | 1378 | ||
1354 | switch (cmd) { | 1379 | switch (cmd) { |
1355 | case SNDRV_PCM_TRIGGER_START: | 1380 | case SNDRV_PCM_TRIGGER_START: |
1356 | if (!RME96_ISPLAYING(rme96)) { | 1381 | if (!RME96_ISPLAYING(rme96)) { |
1357 | if (substream != rme96->playback_substream) { | 1382 | if (substream != rme96->playback_substream) |
1358 | return -EBUSY; | 1383 | return -EBUSY; |
1359 | } | 1384 | snd_rme96_trigger(rme96, sync ? RME96_START_BOTH |
1360 | snd_rme96_playback_start(rme96, 0); | 1385 | : RME96_START_PLAYBACK); |
1361 | } | 1386 | } |
1362 | break; | 1387 | break; |
1363 | 1388 | ||
1364 | case SNDRV_PCM_TRIGGER_STOP: | 1389 | case SNDRV_PCM_TRIGGER_STOP: |
1365 | if (RME96_ISPLAYING(rme96)) { | 1390 | if (RME96_ISPLAYING(rme96)) { |
1366 | if (substream != rme96->playback_substream) { | 1391 | if (substream != rme96->playback_substream) |
1367 | return -EBUSY; | 1392 | return -EBUSY; |
1368 | } | 1393 | snd_rme96_trigger(rme96, sync ? RME96_STOP_BOTH |
1369 | snd_rme96_playback_stop(rme96); | 1394 | : RME96_STOP_PLAYBACK); |
1370 | } | 1395 | } |
1371 | break; | 1396 | break; |
1372 | 1397 | ||
1373 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | 1398 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: |
1374 | if (RME96_ISPLAYING(rme96)) { | 1399 | if (RME96_ISPLAYING(rme96)) |
1375 | snd_rme96_playback_stop(rme96); | 1400 | snd_rme96_trigger(rme96, sync ? RME96_STOP_BOTH |
1376 | } | 1401 | : RME96_STOP_PLAYBACK); |
1377 | break; | 1402 | break; |
1378 | 1403 | ||
1379 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | 1404 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: |
1380 | if (!RME96_ISPLAYING(rme96)) { | 1405 | if (!RME96_ISPLAYING(rme96)) |
1381 | snd_rme96_playback_start(rme96, 1); | 1406 | snd_rme96_trigger(rme96, sync ? RME96_RESUME_BOTH |
1382 | } | 1407 | : RME96_RESUME_PLAYBACK); |
1383 | break; | 1408 | break; |
1384 | 1409 | ||
1385 | default: | 1410 | default: |
1386 | return -EINVAL; | 1411 | return -EINVAL; |
1387 | } | 1412 | } |
1413 | |||
1388 | return 0; | 1414 | return 0; |
1389 | } | 1415 | } |
1390 | 1416 | ||
@@ -1393,38 +1419,49 @@ snd_rme96_capture_trigger(struct snd_pcm_substream *substream, | |||
1393 | int cmd) | 1419 | int cmd) |
1394 | { | 1420 | { |
1395 | struct rme96 *rme96 = snd_pcm_substream_chip(substream); | 1421 | struct rme96 *rme96 = snd_pcm_substream_chip(substream); |
1422 | struct snd_pcm_substream *s; | ||
1423 | bool sync; | ||
1424 | |||
1425 | snd_pcm_group_for_each_entry(s, substream) { | ||
1426 | if (snd_pcm_substream_chip(s) == rme96) | ||
1427 | snd_pcm_trigger_done(s, substream); | ||
1428 | } | ||
1429 | |||
1430 | sync = (rme96->playback_substream && rme96->capture_substream) && | ||
1431 | (rme96->playback_substream->group == | ||
1432 | rme96->capture_substream->group); | ||
1396 | 1433 | ||
1397 | switch (cmd) { | 1434 | switch (cmd) { |
1398 | case SNDRV_PCM_TRIGGER_START: | 1435 | case SNDRV_PCM_TRIGGER_START: |
1399 | if (!RME96_ISRECORDING(rme96)) { | 1436 | if (!RME96_ISRECORDING(rme96)) { |
1400 | if (substream != rme96->capture_substream) { | 1437 | if (substream != rme96->capture_substream) |
1401 | return -EBUSY; | 1438 | return -EBUSY; |
1402 | } | 1439 | snd_rme96_trigger(rme96, sync ? RME96_START_BOTH |
1403 | snd_rme96_capture_start(rme96, 0); | 1440 | : RME96_START_CAPTURE); |
1404 | } | 1441 | } |
1405 | break; | 1442 | break; |
1406 | 1443 | ||
1407 | case SNDRV_PCM_TRIGGER_STOP: | 1444 | case SNDRV_PCM_TRIGGER_STOP: |
1408 | if (RME96_ISRECORDING(rme96)) { | 1445 | if (RME96_ISRECORDING(rme96)) { |
1409 | if (substream != rme96->capture_substream) { | 1446 | if (substream != rme96->capture_substream) |
1410 | return -EBUSY; | 1447 | return -EBUSY; |
1411 | } | 1448 | snd_rme96_trigger(rme96, sync ? RME96_STOP_BOTH |
1412 | snd_rme96_capture_stop(rme96); | 1449 | : RME96_STOP_CAPTURE); |
1413 | } | 1450 | } |
1414 | break; | 1451 | break; |
1415 | 1452 | ||
1416 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | 1453 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: |
1417 | if (RME96_ISRECORDING(rme96)) { | 1454 | if (RME96_ISRECORDING(rme96)) |
1418 | snd_rme96_capture_stop(rme96); | 1455 | snd_rme96_trigger(rme96, sync ? RME96_STOP_BOTH |
1419 | } | 1456 | : RME96_STOP_CAPTURE); |
1420 | break; | 1457 | break; |
1421 | 1458 | ||
1422 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | 1459 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: |
1423 | if (!RME96_ISRECORDING(rme96)) { | 1460 | if (!RME96_ISRECORDING(rme96)) |
1424 | snd_rme96_capture_start(rme96, 1); | 1461 | snd_rme96_trigger(rme96, sync ? RME96_RESUME_BOTH |
1425 | } | 1462 | : RME96_RESUME_CAPTURE); |
1426 | break; | 1463 | break; |
1427 | 1464 | ||
1428 | default: | 1465 | default: |
1429 | return -EINVAL; | 1466 | return -EINVAL; |
1430 | } | 1467 | } |
@@ -1505,8 +1542,7 @@ snd_rme96_free(void *private_data) | |||
1505 | return; | 1542 | return; |
1506 | } | 1543 | } |
1507 | if (rme96->irq >= 0) { | 1544 | if (rme96->irq >= 0) { |
1508 | snd_rme96_playback_stop(rme96); | 1545 | snd_rme96_trigger(rme96, RME96_STOP_BOTH); |
1509 | snd_rme96_capture_stop(rme96); | ||
1510 | rme96->areg &= ~RME96_AR_DAC_EN; | 1546 | rme96->areg &= ~RME96_AR_DAC_EN; |
1511 | writel(rme96->areg, rme96->iobase + RME96_IO_ADDITIONAL_REG); | 1547 | writel(rme96->areg, rme96->iobase + RME96_IO_ADDITIONAL_REG); |
1512 | free_irq(rme96->irq, (void *)rme96); | 1548 | free_irq(rme96->irq, (void *)rme96); |
@@ -1606,8 +1642,7 @@ snd_rme96_create(struct rme96 *rme96) | |||
1606 | rme96->capture_periodsize = 0; | 1642 | rme96->capture_periodsize = 0; |
1607 | 1643 | ||
1608 | /* make sure playback/capture is stopped, if by some reason active */ | 1644 | /* make sure playback/capture is stopped, if by some reason active */ |
1609 | snd_rme96_playback_stop(rme96); | 1645 | snd_rme96_trigger(rme96, RME96_STOP_BOTH); |
1610 | snd_rme96_capture_stop(rme96); | ||
1611 | 1646 | ||
1612 | /* set default values in registers */ | 1647 | /* set default values in registers */ |
1613 | rme96->wcreg = | 1648 | rme96->wcreg = |