Commit c36fd8c3cd682fa9bbe5b2cb4b99e16625a37c94

Authored by Clemens Ladisch
Committed by Jaroslav Kysela
1 parent ebe9e289d8

[ALSA] cmipci: fix distortion on rear channels

When playing multichannel data, the rear channels can get distorted if
the last sample of the last played stereo stream was not zero.  To avoid
this, add a hack to play a few silence samples after the stream is
stopped.

Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
Signed-off-by: Jaroslav Kysela <perex@suse.cz>

Showing 1 changed file with 67 additions and 1 deletions Side-by-side Diff

... ... @@ -434,6 +434,7 @@
434 434 u8 running; /* dac/adc running? */
435 435 u8 fmt; /* format bits */
436 436 u8 is_dac;
  437 + u8 needs_silencing;
437 438 unsigned int dma_size; /* in frames */
438 439 unsigned int shift;
439 440 unsigned int ch; /* channel (0/1) */
... ... @@ -903,6 +904,7 @@
903 904 cm->ctrl &= ~chen;
904 905 snd_cmipci_write(cm, CM_REG_FUNCTRL0, cm->ctrl | reset);
905 906 snd_cmipci_write(cm, CM_REG_FUNCTRL0, cm->ctrl & ~reset);
  907 + rec->needs_silencing = rec->is_dac;
906 908 break;
907 909 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
908 910 case SNDRV_PCM_TRIGGER_SUSPEND:
909 911  
910 912  
... ... @@ -1304,14 +1306,78 @@
1304 1306 return snd_cmipci_pcm_prepare(cm, &cm->channel[CM_CH_PLAY], substream);
1305 1307 }
1306 1308  
  1309 +/*
  1310 + * Apparently, the samples last played on channel A stay in some buffer, even
  1311 + * after the channel is reset, and get added to the data for the rear DACs when
  1312 + * playing a multichannel stream on channel B. This is likely to generate
  1313 + * wraparounds and thus distortions.
  1314 + * To avoid this, we play at least one zero sample after the actual stream has
  1315 + * stopped.
  1316 + */
  1317 +static void snd_cmipci_silence_hack(struct cmipci *cm, struct cmipci_pcm *rec)
  1318 +{
  1319 + struct snd_pcm_runtime *runtime = rec->substream->runtime;
  1320 + unsigned int reg, val;
  1321 +
  1322 + if (rec->needs_silencing && runtime && runtime->dma_area) {
  1323 + /* set up a small silence buffer */
  1324 + memset(runtime->dma_area, 0, PAGE_SIZE);
  1325 + reg = rec->ch ? CM_REG_CH1_FRAME2 : CM_REG_CH0_FRAME2;
  1326 + val = ((PAGE_SIZE / 4) - 1) | (((PAGE_SIZE / 4) / 2 - 1) << 16);
  1327 + snd_cmipci_write(cm, reg, val);
  1328 +
  1329 + /* configure for 16 bits, 2 channels, 8 kHz */
  1330 + if (runtime->channels > 2)
  1331 + set_dac_channels(cm, rec, 2);
  1332 + spin_lock_irq(&cm->reg_lock);
  1333 + val = snd_cmipci_read(cm, CM_REG_FUNCTRL1);
  1334 + val &= ~(CM_ASFC_MASK << (rec->ch * 3));
  1335 + val |= (4 << CM_ASFC_SHIFT) << (rec->ch * 3);
  1336 + snd_cmipci_write(cm, CM_REG_FUNCTRL1, val);
  1337 + val = snd_cmipci_read(cm, CM_REG_CHFORMAT);
  1338 + val &= ~(CM_CH0FMT_MASK << (rec->ch * 2));
  1339 + val |= (3 << CM_CH0FMT_SHIFT) << (rec->ch * 2);
  1340 + if (cm->chip_version == 68) {
  1341 + val &= ~(CM_CH0_SRATE_88K << (rec->ch * 2));
  1342 + val &= ~(CM_CH0_SRATE_96K << (rec->ch * 2));
  1343 + }
  1344 + snd_cmipci_write(cm, CM_REG_CHFORMAT, val);
  1345 +
  1346 + /* start stream (we don't need interrupts) */
  1347 + cm->ctrl |= CM_CHEN0 << rec->ch;
  1348 + snd_cmipci_write(cm, CM_REG_FUNCTRL0, cm->ctrl);
  1349 + spin_unlock_irq(&cm->reg_lock);
  1350 +
  1351 + msleep(1);
  1352 +
  1353 + /* stop and reset stream */
  1354 + spin_lock_irq(&cm->reg_lock);
  1355 + cm->ctrl &= ~(CM_CHEN0 << rec->ch);
  1356 + val = CM_RST_CH0 << rec->ch;
  1357 + snd_cmipci_write(cm, CM_REG_FUNCTRL0, cm->ctrl | val);
  1358 + snd_cmipci_write(cm, CM_REG_FUNCTRL0, cm->ctrl & ~val);
  1359 + spin_unlock_irq(&cm->reg_lock);
  1360 +
  1361 + rec->needs_silencing = 0;
  1362 + }
  1363 +}
  1364 +
1307 1365 static int snd_cmipci_playback_hw_free(struct snd_pcm_substream *substream)
1308 1366 {
1309 1367 struct cmipci *cm = snd_pcm_substream_chip(substream);
1310 1368 setup_spdif_playback(cm, substream, 0, 0);
1311 1369 restore_mixer_state(cm);
  1370 + snd_cmipci_silence_hack(cm, &cm->channel[0]);
1312 1371 return snd_cmipci_hw_free(substream);
1313 1372 }
1314 1373  
  1374 +static int snd_cmipci_playback2_hw_free(struct snd_pcm_substream *substream)
  1375 +{
  1376 + struct cmipci *cm = snd_pcm_substream_chip(substream);
  1377 + snd_cmipci_silence_hack(cm, &cm->channel[1]);
  1378 + return snd_cmipci_hw_free(substream);
  1379 +}
  1380 +
1315 1381 /* capture */
1316 1382 static int snd_cmipci_capture_prepare(struct snd_pcm_substream *substream)
1317 1383 {
... ... @@ -1736,7 +1802,7 @@
1736 1802 .close = snd_cmipci_playback2_close,
1737 1803 .ioctl = snd_pcm_lib_ioctl,
1738 1804 .hw_params = snd_cmipci_playback2_hw_params,
1739   - .hw_free = snd_cmipci_hw_free,
  1805 + .hw_free = snd_cmipci_playback2_hw_free,
1740 1806 .prepare = snd_cmipci_capture_prepare, /* channel B */
1741 1807 .trigger = snd_cmipci_capture_trigger, /* channel B */
1742 1808 .pointer = snd_cmipci_capture_pointer, /* channel B */