aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/hda/hda_intel.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/pci/hda/hda_intel.c')
-rw-r--r--sound/pci/hda/hda_intel.c39
1 files changed, 35 insertions, 4 deletions
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index bcd40ee488e3..7b213d589ef6 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -1889,6 +1889,26 @@ static void azx_timecounter_init(struct snd_pcm_substream *substream,
1889 tc->cycle_last = last; 1889 tc->cycle_last = last;
1890} 1890}
1891 1891
1892static u64 azx_adjust_codec_delay(struct snd_pcm_substream *substream,
1893 u64 nsec)
1894{
1895 struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
1896 struct hda_pcm_stream *hinfo = apcm->hinfo[substream->stream];
1897 u64 codec_frames, codec_nsecs;
1898
1899 if (!hinfo->ops.get_delay)
1900 return nsec;
1901
1902 codec_frames = hinfo->ops.get_delay(hinfo, apcm->codec, substream);
1903 codec_nsecs = div_u64(codec_frames * 1000000000LL,
1904 substream->runtime->rate);
1905
1906 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
1907 return nsec + codec_nsecs;
1908
1909 return (nsec > codec_nsecs) ? nsec - codec_nsecs : 0;
1910}
1911
1892static int azx_get_wallclock_tstamp(struct snd_pcm_substream *substream, 1912static int azx_get_wallclock_tstamp(struct snd_pcm_substream *substream,
1893 struct timespec *ts) 1913 struct timespec *ts)
1894{ 1914{
@@ -1897,6 +1917,7 @@ static int azx_get_wallclock_tstamp(struct snd_pcm_substream *substream,
1897 1917
1898 nsec = timecounter_read(&azx_dev->azx_tc); 1918 nsec = timecounter_read(&azx_dev->azx_tc);
1899 nsec = div_u64(nsec, 3); /* can be optimized */ 1919 nsec = div_u64(nsec, 3); /* can be optimized */
1920 nsec = azx_adjust_codec_delay(substream, nsec);
1900 1921
1901 *ts = ns_to_timespec(nsec); 1922 *ts = ns_to_timespec(nsec);
1902 1923
@@ -2349,8 +2370,11 @@ static unsigned int azx_get_position(struct azx *chip,
2349 struct azx_dev *azx_dev, 2370 struct azx_dev *azx_dev,
2350 bool with_check) 2371 bool with_check)
2351{ 2372{
2373 struct snd_pcm_substream *substream = azx_dev->substream;
2374 struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
2352 unsigned int pos; 2375 unsigned int pos;
2353 int stream = azx_dev->substream->stream; 2376 int stream = substream->stream;
2377 struct hda_pcm_stream *hinfo = apcm->hinfo[stream];
2354 int delay = 0; 2378 int delay = 0;
2355 2379
2356 switch (chip->position_fix[stream]) { 2380 switch (chip->position_fix[stream]) {
@@ -2381,7 +2405,7 @@ static unsigned int azx_get_position(struct azx *chip,
2381 pos = 0; 2405 pos = 0;
2382 2406
2383 /* calculate runtime delay from LPIB */ 2407 /* calculate runtime delay from LPIB */
2384 if (azx_dev->substream->runtime && 2408 if (substream->runtime &&
2385 chip->position_fix[stream] == POS_FIX_POSBUF && 2409 chip->position_fix[stream] == POS_FIX_POSBUF &&
2386 (chip->driver_caps & AZX_DCAPS_COUNT_LPIB_DELAY)) { 2410 (chip->driver_caps & AZX_DCAPS_COUNT_LPIB_DELAY)) {
2387 unsigned int lpib_pos = azx_sd_readl(azx_dev, SD_LPIB); 2411 unsigned int lpib_pos = azx_sd_readl(azx_dev, SD_LPIB);
@@ -2399,9 +2423,16 @@ static unsigned int azx_get_position(struct azx *chip,
2399 delay = 0; 2423 delay = 0;
2400 chip->driver_caps &= ~AZX_DCAPS_COUNT_LPIB_DELAY; 2424 chip->driver_caps &= ~AZX_DCAPS_COUNT_LPIB_DELAY;
2401 } 2425 }
2402 azx_dev->substream->runtime->delay = 2426 delay = bytes_to_frames(substream->runtime, delay);
2403 bytes_to_frames(azx_dev->substream->runtime, delay);
2404 } 2427 }
2428
2429 if (substream->runtime) {
2430 if (hinfo->ops.get_delay)
2431 delay += hinfo->ops.get_delay(hinfo, apcm->codec,
2432 substream);
2433 substream->runtime->delay = delay;
2434 }
2435
2405 trace_azx_get_position(chip, azx_dev, pos, delay); 2436 trace_azx_get_position(chip, azx_dev, pos, delay);
2406 return pos; 2437 return pos;
2407} 2438}