aboutsummaryrefslogtreecommitdiff
path: root/sound/pci
diff options
context:
space:
mode:
authorPierre-Louis Bossart2012-09-21 18:39:06 -0500
committerTakashi Iwai2012-09-22 09:31:09 +0200
commit90accc58a6946e7245993da6079f88d8c29cb731 (patch)
tree89eae1d4817843f24836b7ed61e93e202587e30e /sound/pci
parent172d3b209622785ce7c4f4104319df06d9814b62 (diff)
ALSA: hda - use LPIB for delay estimation
DMA Position in Buffer (DPIB) should be used for ring buffer management, while LPIB register provides information on the number of samples transfered on the link. The difference between the two pieces of information corresponds to hardware/DMA buffering. This patch reports this difference in runtime->delay, and removes the use of the COMBO mode on recent Intel hardware. Credits to Takashi Iwai for an initial patch. [rebased to for-next branch and replaced snd_printk() with snd_printdd() by tiwai] Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci')
-rw-r--r--sound/pci/hda/hda_intel.c36
1 files changed, 29 insertions, 7 deletions
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index f4070a4f39fd..1c622e5e397c 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -555,6 +555,7 @@ enum {
#define AZX_DCAPS_ALIGN_BUFSIZE (1 << 22) /* buffer size alignment */
#define AZX_DCAPS_4K_BDLE_BOUNDARY (1 << 23) /* BDLE in 4k boundary */
#define AZX_DCAPS_POSFIX_COMBO (1 << 24) /* Use COMBO as default */
+#define AZX_DCAPS_COUNT_LPIB_DELAY (1 << 25) /* Take LPIB as delay */
/* quirks for ATI SB / AMD Hudson */
#define AZX_DCAPS_PRESET_ATI_SB \
@@ -2143,6 +2144,27 @@ static unsigned int azx_get_position(struct azx *chip,
if (pos >= azx_dev->bufsize)
pos = 0;
+
+ /* calculate runtime delay from LPIB */
+ if (azx_dev->substream->runtime &&
+ chip->position_fix[stream] == POS_FIX_POSBUF &&
+ (chip->driver_caps & AZX_DCAPS_COUNT_LPIB_DELAY)) {
+ unsigned int lpib_pos = azx_sd_readl(azx_dev, SD_LPIB);
+ int delay;
+ if (stream == SNDRV_PCM_STREAM_PLAYBACK)
+ delay = pos - lpib_pos;
+ else
+ delay = lpib_pos - pos;
+ if (delay < 0)
+ delay += azx_dev->bufsize;
+ if (delay >= azx_dev->period_bytes) {
+ snd_printdd("delay %d > period_bytes %d\n",
+ delay, azx_dev->period_bytes);
+ delay = 0; /* something is wrong */
+ }
+ azx_dev->substream->runtime->delay =
+ bytes_to_frames(azx_dev->substream->runtime, delay);
+ }
return pos;
}
@@ -3402,7 +3424,7 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = {
/* CPT */
{ PCI_DEVICE(0x8086, 0x1c20),
.driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP |
- AZX_DCAPS_BUFSIZE | AZX_DCAPS_POSFIX_COMBO },
+ AZX_DCAPS_BUFSIZE | AZX_DCAPS_COUNT_LPIB_DELAY },
/* PBG */
{ PCI_DEVICE(0x8086, 0x1d20),
.driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP |
@@ -3410,26 +3432,26 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = {
/* Panther Point */
{ PCI_DEVICE(0x8086, 0x1e20),
.driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP |
- AZX_DCAPS_BUFSIZE | AZX_DCAPS_POSFIX_COMBO },
+ AZX_DCAPS_BUFSIZE | AZX_DCAPS_COUNT_LPIB_DELAY },
/* Lynx Point */
{ PCI_DEVICE(0x8086, 0x8c20),
.driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP |
- AZX_DCAPS_BUFSIZE | AZX_DCAPS_POSFIX_COMBO },
+ AZX_DCAPS_BUFSIZE | AZX_DCAPS_COUNT_LPIB_DELAY },
/* Lynx Point-LP */
{ PCI_DEVICE(0x8086, 0x9c20),
.driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP |
- AZX_DCAPS_BUFSIZE | AZX_DCAPS_POSFIX_COMBO },
+ AZX_DCAPS_BUFSIZE | AZX_DCAPS_COUNT_LPIB_DELAY },
/* Lynx Point-LP */
{ PCI_DEVICE(0x8086, 0x9c21),
.driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP |
- AZX_DCAPS_BUFSIZE | AZX_DCAPS_POSFIX_COMBO },
+ AZX_DCAPS_BUFSIZE | AZX_DCAPS_COUNT_LPIB_DELAY },
/* Haswell */
{ PCI_DEVICE(0x8086, 0x0c0c),
.driver_data = AZX_DRIVER_SCH | AZX_DCAPS_SCH_SNOOP |
- AZX_DCAPS_BUFSIZE | AZX_DCAPS_POSFIX_COMBO },
+ AZX_DCAPS_BUFSIZE | AZX_DCAPS_COUNT_LPIB_DELAY },
{ PCI_DEVICE(0x8086, 0x0d0c),
.driver_data = AZX_DRIVER_SCH | AZX_DCAPS_SCH_SNOOP |
- AZX_DCAPS_BUFSIZE | AZX_DCAPS_POSFIX_COMBO },
+ AZX_DCAPS_BUFSIZE | AZX_DCAPS_COUNT_LPIB_DELAY },
/* SCH */
{ PCI_DEVICE(0x8086, 0x811b),
.driver_data = AZX_DRIVER_SCH | AZX_DCAPS_SCH_SNOOP |