]> git.alsa-project.org Git - alsa-lib.git/commitdiff
Fix softvol access refine
authorTakashi Iwai <tiwai@suse.de>
Thu, 4 Dec 2008 14:21:40 +0000 (15:21 +0100)
committerTakashi Iwai <tiwai@suse.de>
Thu, 4 Dec 2008 15:01:22 +0000 (16:01 +0100)
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

index 4c5f0f7a1c0b66d2a99671635a1f0b12f79ac1bd..637e5cb3ce7130d4d0b0bd8c3d9b06147ed80835 100644 (file)
@@ -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;
 }