aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2008-03-18 12:11:05 -0400
committerTakashi Iwai <tiwai@suse.de>2008-04-24 06:00:27 -0400
commit850f0e5212a73a548b9c29faf452b4a14d80f43b (patch)
tree1a855bbd6f7d17e595866771b0cfb60674817f58 /sound
parentf081374b607f2656ca79a94d96d99cd5a2f60b68 (diff)
[ALSA] hda-intel - Add sync support
Addded the support of sync streams to hda-intel driver. Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound')
-rw-r--r--sound/pci/hda/hda_intel.c96
1 files changed, 79 insertions, 17 deletions
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index 557f269f83ab..bc3867e1945c 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -221,6 +221,9 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 };
221/* SD_CTL bits */ 221/* SD_CTL bits */
222#define SD_CTL_STREAM_RESET 0x01 /* stream reset bit */ 222#define SD_CTL_STREAM_RESET 0x01 /* stream reset bit */
223#define SD_CTL_DMA_START 0x02 /* stream DMA start bit */ 223#define SD_CTL_DMA_START 0x02 /* stream DMA start bit */
224#define SD_CTL_STRIPE (3 << 16) /* stripe control */
225#define SD_CTL_TRAFFIC_PRIO (1 << 18) /* traffic priority */
226#define SD_CTL_DIR (1 << 19) /* bi-directional stream */
224#define SD_CTL_STREAM_TAG_MASK (0xf << 20) 227#define SD_CTL_STREAM_TAG_MASK (0xf << 20)
225#define SD_CTL_STREAM_TAG_SHIFT 20 228#define SD_CTL_STREAM_TAG_SHIFT 20
226 229
@@ -1180,7 +1183,8 @@ static struct snd_pcm_hardware azx_pcm_hw = {
1180 SNDRV_PCM_INFO_MMAP_VALID | 1183 SNDRV_PCM_INFO_MMAP_VALID |
1181 /* No full-resume yet implemented */ 1184 /* No full-resume yet implemented */
1182 /* SNDRV_PCM_INFO_RESUME |*/ 1185 /* SNDRV_PCM_INFO_RESUME |*/
1183 SNDRV_PCM_INFO_PAUSE), 1186 SNDRV_PCM_INFO_PAUSE |
1187 SNDRV_PCM_INFO_SYNC_START),
1184 .formats = SNDRV_PCM_FMTBIT_S16_LE, 1188 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1185 .rates = SNDRV_PCM_RATE_48000, 1189 .rates = SNDRV_PCM_RATE_48000,
1186 .rate_min = 48000, 1190 .rate_min = 48000,
@@ -1242,6 +1246,7 @@ static int azx_pcm_open(struct snd_pcm_substream *substream)
1242 spin_unlock_irqrestore(&chip->reg_lock, flags); 1246 spin_unlock_irqrestore(&chip->reg_lock, flags);
1243 1247
1244 runtime->private_data = azx_dev; 1248 runtime->private_data = azx_dev;
1249 snd_pcm_set_sync(substream);
1245 mutex_unlock(&chip->open_mutex); 1250 mutex_unlock(&chip->open_mutex);
1246 return 0; 1251 return 0;
1247} 1252}
@@ -1326,37 +1331,94 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream)
1326static int azx_pcm_trigger(struct snd_pcm_substream *substream, int cmd) 1331static int azx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
1327{ 1332{
1328 struct azx_pcm *apcm = snd_pcm_substream_chip(substream); 1333 struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
1329 struct azx_dev *azx_dev = get_azx_dev(substream);
1330 struct azx *chip = apcm->chip; 1334 struct azx *chip = apcm->chip;
1331 int err = 0; 1335 struct azx_dev *azx_dev;
1336 struct snd_pcm_substream *s;
1337 int start, nsync = 0, sbits = 0;
1338 int nwait, timeout;
1332 1339
1333 spin_lock(&chip->reg_lock);
1334 switch (cmd) { 1340 switch (cmd) {
1335 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 1341 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
1336 case SNDRV_PCM_TRIGGER_RESUME: 1342 case SNDRV_PCM_TRIGGER_RESUME:
1337 case SNDRV_PCM_TRIGGER_START: 1343 case SNDRV_PCM_TRIGGER_START:
1338 azx_stream_start(chip, azx_dev); 1344 start = 1;
1339 azx_dev->running = 1;
1340 break; 1345 break;
1341 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 1346 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
1342 case SNDRV_PCM_TRIGGER_SUSPEND: 1347 case SNDRV_PCM_TRIGGER_SUSPEND:
1343 case SNDRV_PCM_TRIGGER_STOP: 1348 case SNDRV_PCM_TRIGGER_STOP:
1344 azx_stream_stop(chip, azx_dev); 1349 start = 0;
1345 azx_dev->running = 0;
1346 break; 1350 break;
1347 default: 1351 default:
1348 err = -EINVAL; 1352 return -EINVAL;
1353 }
1354
1355 snd_pcm_group_for_each_entry(s, substream) {
1356 if (s->pcm->card != substream->pcm->card)
1357 continue;
1358 azx_dev = get_azx_dev(s);
1359 sbits |= 1 << azx_dev->index;
1360 nsync++;
1361 snd_pcm_trigger_done(s, substream);
1362 }
1363
1364 spin_lock(&chip->reg_lock);
1365 if (nsync > 1) {
1366 /* first, set SYNC bits of corresponding streams */
1367 azx_writel(chip, SYNC, azx_readl(chip, SYNC) | sbits);
1368 }
1369 snd_pcm_group_for_each_entry(s, substream) {
1370 if (s->pcm->card != substream->pcm->card)
1371 continue;
1372 azx_dev = get_azx_dev(s);
1373 if (start)
1374 azx_stream_start(chip, azx_dev);
1375 else
1376 azx_stream_stop(chip, azx_dev);
1377 azx_dev->running = start;
1349 } 1378 }
1350 spin_unlock(&chip->reg_lock); 1379 spin_unlock(&chip->reg_lock);
1351 if (cmd == SNDRV_PCM_TRIGGER_PAUSE_PUSH || 1380 if (start) {
1352 cmd == SNDRV_PCM_TRIGGER_SUSPEND || 1381 if (nsync == 1)
1353 cmd == SNDRV_PCM_TRIGGER_STOP) { 1382 return 0;
1354 int timeout = 5000; 1383 /* wait until all FIFOs get ready */
1355 while ((azx_sd_readb(azx_dev, SD_CTL) & SD_CTL_DMA_START) && 1384 for (timeout = 5000; timeout; timeout--) {
1356 --timeout) 1385 nwait = 0;
1357 ; 1386 snd_pcm_group_for_each_entry(s, substream) {
1387 if (s->pcm->card != substream->pcm->card)
1388 continue;
1389 azx_dev = get_azx_dev(s);
1390 if (!(azx_sd_readb(azx_dev, SD_STS) &
1391 SD_STS_FIFO_READY))
1392 nwait++;
1393 }
1394 if (!nwait)
1395 break;
1396 cpu_relax();
1397 }
1398 } else {
1399 /* wait until all RUN bits are cleared */
1400 for (timeout = 5000; timeout; timeout--) {
1401 nwait = 0;
1402 snd_pcm_group_for_each_entry(s, substream) {
1403 if (s->pcm->card != substream->pcm->card)
1404 continue;
1405 azx_dev = get_azx_dev(s);
1406 if (azx_sd_readb(azx_dev, SD_CTL) &
1407 SD_CTL_DMA_START)
1408 nwait++;
1409 }
1410 if (!nwait)
1411 break;
1412 cpu_relax();
1413 }
1358 } 1414 }
1359 return err; 1415 if (nsync > 1) {
1416 spin_lock(&chip->reg_lock);
1417 /* reset SYNC bits */
1418 azx_writel(chip, SYNC, azx_readl(chip, SYNC) & ~sbits);
1419 spin_unlock(&chip->reg_lock);
1420 }
1421 return 0;
1360} 1422}
1361 1423
1362static snd_pcm_uframes_t azx_pcm_pointer(struct snd_pcm_substream *substream) 1424static snd_pcm_uframes_t azx_pcm_pointer(struct snd_pcm_substream *substream)