mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-04-16 19:34:03 +00:00
ALSA: x86: Allow single period PCM operation
This is an implementation of PCM streaming with only 1 period. Since the hardware requires the refresh of BDs after each BD processing finishes, we'd need at least two BDs. The trick is that both BDs point to the same content: the address of the PCM buffer head, and the whole buffer size. Then it loops over to the whole buffer again after it finished once. Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
parent
a9ebdd0ef2
commit
8d48c0163d
2 changed files with 13 additions and 3 deletions
|
@ -822,6 +822,11 @@ static int had_prog_n(u32 aud_samp_freq, u32 *n_param,
|
||||||
*
|
*
|
||||||
* For nperiods < 4, the remaining BDs out of 4 are marked as invalid, so that
|
* For nperiods < 4, the remaining BDs out of 4 are marked as invalid, so that
|
||||||
* the hardware skips those BDs in the loop.
|
* the hardware skips those BDs in the loop.
|
||||||
|
*
|
||||||
|
* An exceptional setup is the case with nperiods=1. Since we have to update
|
||||||
|
* BDs after finishing one BD processing, we'd need at least two BDs, where
|
||||||
|
* both BDs point to the same content, the same address, the same size of the
|
||||||
|
* whole PCM buffer.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define AUD_BUF_ADDR(x) (AUD_BUF_A_ADDR + (x) * HAD_REG_WIDTH)
|
#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,
|
||||||
|
|
||||||
num_periods = runtime->periods;
|
num_periods = runtime->periods;
|
||||||
intelhaddata->num_bds = min(num_periods, HAD_NUM_OF_RING_BUFS);
|
intelhaddata->num_bds = min(num_periods, HAD_NUM_OF_RING_BUFS);
|
||||||
|
/* set the minimum 2 BDs for num_periods=1 */
|
||||||
|
intelhaddata->num_bds = max(intelhaddata->num_bds, 2U);
|
||||||
intelhaddata->period_bytes =
|
intelhaddata->period_bytes =
|
||||||
frames_to_bytes(runtime, runtime->period_size);
|
frames_to_bytes(runtime, runtime->period_size);
|
||||||
WARN_ON(intelhaddata->period_bytes & 0x3f);
|
WARN_ON(intelhaddata->period_bytes & 0x3f);
|
||||||
|
@ -873,7 +880,7 @@ static void had_init_ringbuf(struct snd_pcm_substream *substream,
|
||||||
intelhaddata->pcmbuf_filled = 0;
|
intelhaddata->pcmbuf_filled = 0;
|
||||||
|
|
||||||
for (i = 0; i < HAD_NUM_OF_RING_BUFS; i++) {
|
for (i = 0; i < HAD_NUM_OF_RING_BUFS; i++) {
|
||||||
if (i < num_periods)
|
if (i < intelhaddata->num_bds)
|
||||||
had_prog_bd(substream, intelhaddata);
|
had_prog_bd(substream, intelhaddata);
|
||||||
else /* invalidate the rest */
|
else /* invalidate the rest */
|
||||||
had_invalidate_bd(intelhaddata, i);
|
had_invalidate_bd(intelhaddata, i);
|
||||||
|
@ -1255,7 +1262,10 @@ static snd_pcm_uframes_t had_pcm_pointer(struct snd_pcm_substream *substream)
|
||||||
len = had_process_ringbuf(substream, intelhaddata);
|
len = had_process_ringbuf(substream, intelhaddata);
|
||||||
if (len < 0)
|
if (len < 0)
|
||||||
return SNDRV_PCM_POS_XRUN;
|
return SNDRV_PCM_POS_XRUN;
|
||||||
return bytes_to_frames(substream->runtime, len);
|
len = bytes_to_frames(substream->runtime, len);
|
||||||
|
/* wrapping may happen when periods=1 */
|
||||||
|
len %= substream->runtime->buffer_size;
|
||||||
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -31,7 +31,7 @@
|
||||||
#define HAD_MAX_BUFFER ((1024 * 1024 - 1) & ~0x3f)
|
#define HAD_MAX_BUFFER ((1024 * 1024 - 1) & ~0x3f)
|
||||||
#define HAD_DEFAULT_BUFFER (600 * 1024) /* default prealloc size */
|
#define HAD_DEFAULT_BUFFER (600 * 1024) /* default prealloc size */
|
||||||
#define HAD_MAX_PERIODS 256 /* arbitrary, but should suffice */
|
#define HAD_MAX_PERIODS 256 /* arbitrary, but should suffice */
|
||||||
#define HAD_MIN_PERIODS 2
|
#define HAD_MIN_PERIODS 1
|
||||||
#define HAD_MAX_PERIOD_BYTES ((HAD_MAX_BUFFER / HAD_MIN_PERIODS) & ~0x3f)
|
#define HAD_MAX_PERIOD_BYTES ((HAD_MAX_BUFFER / HAD_MIN_PERIODS) & ~0x3f)
|
||||||
#define HAD_MIN_PERIOD_BYTES 1024 /* might be smaller */
|
#define HAD_MIN_PERIOD_BYTES 1024 /* might be smaller */
|
||||||
#define HAD_FIFO_SIZE 0 /* fifo not being used */
|
#define HAD_FIFO_SIZE 0 /* fifo not being used */
|
||||||
|
|
Loading…
Add table
Reference in a new issue