Skip to content

Commit

Permalink
ALSA: hda - use LPIB for delay estimation
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Pierre-Louis Bossart authored and Takashi Iwai committed Sep 22, 2012
1 parent 172d3b2 commit 90accc5
Showing 1 changed file with 29 additions and 7 deletions.
36 changes: 29 additions & 7 deletions sound/pci/hda/hda_intel.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 \
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -3402,34 +3424,34 @@ 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 |
AZX_DCAPS_BUFSIZE},
/* 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 |
Expand Down

0 comments on commit 90accc5

Please sign in to comment.