diff options
author | Takashi Iwai <tiwai@suse.de> | 2008-03-18 12:11:05 -0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2008-04-24 06:00:27 -0400 |
commit | 850f0e5212a73a548b9c29faf452b4a14d80f43b (patch) | |
tree | 1a855bbd6f7d17e595866771b0cfb60674817f58 /sound/pci/hda | |
parent | f081374b607f2656ca79a94d96d99cd5a2f60b68 (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/pci/hda')
-rw-r--r-- | sound/pci/hda/hda_intel.c | 96 |
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) | |||
1326 | static int azx_pcm_trigger(struct snd_pcm_substream *substream, int cmd) | 1331 | static 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 | ||
1362 | static snd_pcm_uframes_t azx_pcm_pointer(struct snd_pcm_substream *substream) | 1424 | static snd_pcm_uframes_t azx_pcm_pointer(struct snd_pcm_substream *substream) |