summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sound/x86/intel_hdmi_audio.c14
-rw-r--r--sound/x86/intel_hdmi_lpe_audio.h2
2 files changed, 13 insertions, 3 deletions
diff --git a/sound/x86/intel_hdmi_audio.c b/sound/x86/intel_hdmi_audio.c
index 73a662d20201..d2136498defe 100644
--- a/sound/x86/intel_hdmi_audio.c
+++ b/sound/x86/intel_hdmi_audio.c
@@ -822,6 +822,11 @@ static int had_prog_n(u32 aud_samp_freq, u32 *n_param,
822 * 822 *
823 * For nperiods < 4, the remaining BDs out of 4 are marked as invalid, so that 823 * For nperiods < 4, the remaining BDs out of 4 are marked as invalid, so that
824 * the hardware skips those BDs in the loop. 824 * the hardware skips those BDs in the loop.
825 *
826 * An exceptional setup is the case with nperiods=1. Since we have to update
827 * BDs after finishing one BD processing, we'd need at least two BDs, where
828 * both BDs point to the same content, the same address, the same size of the
829 * whole PCM buffer.
825 */ 830 */
826 831
827#define AUD_BUF_ADDR(x) (AUD_BUF_A_ADDR + (x) * HAD_REG_WIDTH) 832#define AUD_BUF_ADDR(x) (AUD_BUF_A_ADDR + (x) * HAD_REG_WIDTH)
@@ -864,6 +869,8 @@ static void had_init_ringbuf(struct snd_pcm_substream *substream,
864 869
865 num_periods = runtime->periods; 870 num_periods = runtime->periods;
866 intelhaddata->num_bds = min(num_periods, HAD_NUM_OF_RING_BUFS); 871 intelhaddata->num_bds = min(num_periods, HAD_NUM_OF_RING_BUFS);
872 /* set the minimum 2 BDs for num_periods=1 */
873 intelhaddata->num_bds = max(intelhaddata->num_bds, 2U);
867 intelhaddata->period_bytes = 874 intelhaddata->period_bytes =
868 frames_to_bytes(runtime, runtime->period_size); 875 frames_to_bytes(runtime, runtime->period_size);
869 WARN_ON(intelhaddata->period_bytes & 0x3f); 876 WARN_ON(intelhaddata->period_bytes & 0x3f);
@@ -873,7 +880,7 @@ static void had_init_ringbuf(struct snd_pcm_substream *substream,
873 intelhaddata->pcmbuf_filled = 0; 880 intelhaddata->pcmbuf_filled = 0;
874 881
875 for (i = 0; i < HAD_NUM_OF_RING_BUFS; i++) { 882 for (i = 0; i < HAD_NUM_OF_RING_BUFS; i++) {
876 if (i < num_periods) 883 if (i < intelhaddata->num_bds)
877 had_prog_bd(substream, intelhaddata); 884 had_prog_bd(substream, intelhaddata);
878 else /* invalidate the rest */ 885 else /* invalidate the rest */
879 had_invalidate_bd(intelhaddata, i); 886 had_invalidate_bd(intelhaddata, i);
@@ -1255,7 +1262,10 @@ static snd_pcm_uframes_t had_pcm_pointer(struct snd_pcm_substream *substream)
1255 len = had_process_ringbuf(substream, intelhaddata); 1262 len = had_process_ringbuf(substream, intelhaddata);
1256 if (len < 0) 1263 if (len < 0)
1257 return SNDRV_PCM_POS_XRUN; 1264 return SNDRV_PCM_POS_XRUN;
1258 return bytes_to_frames(substream->runtime, len); 1265 len = bytes_to_frames(substream->runtime, len);
1266 /* wrapping may happen when periods=1 */
1267 len %= substream->runtime->buffer_size;
1268 return len;
1259} 1269}
1260 1270
1261/* 1271/*
diff --git a/sound/x86/intel_hdmi_lpe_audio.h b/sound/x86/intel_hdmi_lpe_audio.h
index 97bbca19333a..477e5153307c 100644
--- a/sound/x86/intel_hdmi_lpe_audio.h
+++ b/sound/x86/intel_hdmi_lpe_audio.h
@@ -31,7 +31,7 @@
31#define HAD_MAX_BUFFER ((1024 * 1024 - 1) & ~0x3f) 31#define HAD_MAX_BUFFER ((1024 * 1024 - 1) & ~0x3f)
32#define HAD_DEFAULT_BUFFER (600 * 1024) /* default prealloc size */ 32#define HAD_DEFAULT_BUFFER (600 * 1024) /* default prealloc size */
33#define HAD_MAX_PERIODS 256 /* arbitrary, but should suffice */ 33#define HAD_MAX_PERIODS 256 /* arbitrary, but should suffice */
34#define HAD_MIN_PERIODS 2 34#define HAD_MIN_PERIODS 1
35#define HAD_MAX_PERIOD_BYTES ((HAD_MAX_BUFFER / HAD_MIN_PERIODS) & ~0x3f) 35#define HAD_MAX_PERIOD_BYTES ((HAD_MAX_BUFFER / HAD_MIN_PERIODS) & ~0x3f)
36#define HAD_MIN_PERIOD_BYTES 1024 /* might be smaller */ 36#define HAD_MIN_PERIOD_BYTES 1024 /* might be smaller */
37#define HAD_FIFO_SIZE 0 /* fifo not being used */ 37#define HAD_FIFO_SIZE 0 /* fifo not being used */