From 48e4d089dc68ad29267fe6b9c7efc4a66611aeda Mon Sep 17 00:00:00 2001 From: Takashi Iwai <tiwai@suse.de> Date: Thu, 4 Dec 2008 15:21:40 +0100 Subject: [PATCH] Fix softvol access refine The commit a13707da6bb0161db855a146c3e4d1d849e4108b pcm_softvol plugin: remove access type change for refine breaks the softvol in the case of RW -> MMAP. The slave of softvol must be an mmap although the previous fix forces RW access. This patch reverts the commit, and the fixed access refine method to hanle non-interleaved <-> interleaved changes. Signed-off-by: Takashi Iwai <tiwai@suse.de> --- src/pcm/pcm_softvol.c | 56 +++++++++++++++++++++++++++++++++++++++++++++--- 1 files changed, 52 insertions(+), 4 deletions(-) diff --git a/src/pcm/pcm_softvol.c b/src/pcm/pcm_softvol.c index 4c5f0f7..637e5cb 100644 --- a/src/pcm/pcm_softvol.c +++ b/src/pcm/pcm_softvol.c @@ -399,6 +399,7 @@ static int snd_pcm_softvol_hw_refine_cprepare(snd_pcm_t *pcm, { int err; snd_pcm_softvol_t *svol = pcm->private_data; + snd_pcm_access_mask_t access_mask = { SND_PCM_ACCBIT_SHM }; snd_pcm_format_mask_t format_mask = { { (1ULL << SND_PCM_FORMAT_S16_LE) | @@ -412,6 +413,10 @@ static int snd_pcm_softvol_hw_refine_cprepare(snd_pcm_t *pcm, snd_pcm_format_mask_none(&format_mask); snd_pcm_format_mask_set(&format_mask, svol->sformat); } + err = _snd_pcm_hw_param_set_mask(params, SND_PCM_HW_PARAM_ACCESS, + &access_mask); + if (err < 0) + return err; err = _snd_pcm_hw_param_set_mask(params, SND_PCM_HW_PARAM_FORMAT, &format_mask); if (err < 0) @@ -429,7 +434,10 @@ static int snd_pcm_softvol_hw_refine_cprepare(snd_pcm_t *pcm, static int snd_pcm_softvol_hw_refine_sprepare(snd_pcm_t *pcm, snd_pcm_hw_params_t *sparams) { snd_pcm_softvol_t *svol = pcm->private_data; + snd_pcm_access_mask_t saccess_mask = { SND_PCM_ACCBIT_MMAP }; _snd_pcm_hw_params_any(sparams); + _snd_pcm_hw_param_set_mask(sparams, SND_PCM_HW_PARAM_ACCESS, + &saccess_mask); if (svol->sformat != SND_PCM_FORMAT_UNKNOWN) { _snd_pcm_hw_params_set_format(sparams, svol->sformat); _snd_pcm_hw_params_set_subformat(sparams, SND_PCM_SUBFORMAT_STD); @@ -437,14 +445,45 @@ static int snd_pcm_softvol_hw_refine_sprepare(snd_pcm_t *pcm, snd_pcm_hw_params_ return 0; } +/* + * refine the access mask + */ +static int check_access_mask(snd_pcm_hw_params_t *src, + snd_pcm_hw_params_t *dst) +{ + const snd_pcm_access_mask_t *mask; + snd_pcm_access_mask_t smask; + + mask = snd_pcm_hw_param_get_mask(src, SND_PCM_HW_PARAM_ACCESS); + snd_mask_none(&smask); + if (snd_pcm_access_mask_test(mask, SND_PCM_ACCESS_RW_INTERLEAVED) || + snd_pcm_access_mask_test(mask, SND_PCM_ACCESS_MMAP_INTERLEAVED)) { + snd_pcm_access_mask_set(&smask, + SND_PCM_ACCESS_RW_INTERLEAVED); + snd_pcm_access_mask_set(&smask, + SND_PCM_ACCESS_MMAP_INTERLEAVED); + } + if (snd_pcm_access_mask_test(mask, SND_PCM_ACCESS_RW_NONINTERLEAVED) || + snd_pcm_access_mask_test(mask, SND_PCM_ACCESS_MMAP_NONINTERLEAVED)) { + snd_pcm_access_mask_set(&smask, + SND_PCM_ACCESS_RW_NONINTERLEAVED); + snd_pcm_access_mask_set(&smask, + SND_PCM_ACCESS_MMAP_NONINTERLEAVED); + } + if (snd_pcm_access_mask_test(mask, SND_PCM_ACCESS_MMAP_COMPLEX)) + snd_pcm_access_mask_set(&smask, + SND_PCM_ACCESS_MMAP_COMPLEX); + + return _snd_pcm_hw_param_set_mask(dst, SND_PCM_HW_PARAM_ACCESS, &smask); +} + static int snd_pcm_softvol_hw_refine_schange(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_hw_params_t *sparams) { snd_pcm_softvol_t *svol = pcm->private_data; int err; - unsigned int links = (SND_PCM_HW_PARBIT_ACCESS | - SND_PCM_HW_PARBIT_CHANNELS | + unsigned int links = (SND_PCM_HW_PARBIT_CHANNELS | SND_PCM_HW_PARBIT_RATE | SND_PCM_HW_PARBIT_PERIODS | SND_PCM_HW_PARBIT_PERIOD_SIZE | @@ -459,6 +498,11 @@ static int snd_pcm_softvol_hw_refine_schange(snd_pcm_t *pcm, err = _snd_pcm_hw_params_refine(sparams, links, params); if (err < 0) return err; + + err = check_access_mask(params, sparams); + if (err < 0) + return err; + return 0; } @@ -468,8 +512,7 @@ static int snd_pcm_softvol_hw_refine_cchange(snd_pcm_t *pcm, { snd_pcm_softvol_t *svol = pcm->private_data; int err; - unsigned int links = (SND_PCM_HW_PARBIT_ACCESS | - SND_PCM_HW_PARBIT_CHANNELS | + unsigned int links = (SND_PCM_HW_PARBIT_CHANNELS | SND_PCM_HW_PARBIT_RATE | SND_PCM_HW_PARBIT_PERIODS | SND_PCM_HW_PARBIT_PERIOD_SIZE | @@ -484,6 +527,11 @@ static int snd_pcm_softvol_hw_refine_cchange(snd_pcm_t *pcm, err = _snd_pcm_hw_params_refine(params, links, sparams); if (err < 0) return err; + + err = check_access_mask(sparams, params); + if (err < 0) + return err; + return 0; } -- 1.6.1.2