static int snd_pcm_hw_param_mask(struct snd_pcm_substream *pcm, struct snd_pcm_hw_params *params, snd_pcm_hw_param_t var, const struct snd_mask *val) { int changed = _snd_pcm_hw_param_mask(params, var, val); if (changed < 0) return changed; if (params->rmask) { int err = snd_pcm_hw_refine(pcm, params); if (err < 0) return err; } return 0; }
/** * snd_pcm_hw_param_set * @pcm: PCM instance * @params: the hw_params instance * @var: parameter to retrieve * @val: value to set * @dir: pointer to the direction (-1,0,1) or NULL * * Inside configuration space defined by PARAMS remove from PAR all * values != VAL. Reduce configuration space accordingly. * Return VAL or -EINVAL if the configuration space is empty */ static int snd_pcm_hw_param_set(struct snd_pcm_substream *pcm, struct snd_pcm_hw_params *params, snd_pcm_hw_param_t var, unsigned int val, int dir) { int changed = _snd_pcm_hw_param_set(params, var, val, dir); if (changed < 0) return changed; if (params->rmask) { int err = snd_pcm_hw_refine(pcm, params); if (err < 0) return err; } return snd_pcm_hw_param_value(params, var, NULL); }
/* both for HW_PARAMS and HW_REFINE */ static int _snd_ioctl32_pcm_hw_params(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file, unsigned int native_ctl) { struct sndrv_pcm_hw_params32 __user *data32; struct sndrv_pcm_hw_params *data; snd_pcm_file_t *pcm_file; snd_pcm_substream_t *substream; snd_pcm_runtime_t *runtime; int err; if (sanity_check_pcm(file)) return -ENOTTY; if (! (pcm_file = file->private_data)) return -ENOTTY; if (! (substream = pcm_file->substream)) return -ENOTTY; if (! (runtime = substream->runtime)) return -ENOTTY; data32 = compat_ptr(arg); data = kmalloc(sizeof(*data), GFP_KERNEL); if (data == NULL) return -ENOMEM; if (copy_from_user(data, data32, sizeof(*data32))) { err = -EFAULT; goto error; } if (native_ctl == SNDRV_PCM_IOCTL_HW_REFINE) err = snd_pcm_hw_refine(substream, data); else err = snd_pcm_hw_params(substream, data); if (err < 0) goto error; if (copy_to_user(data32, data, sizeof(*data32)) || __put_user((u32)data->fifo_size, &data32->fifo_size)) { err = -EFAULT; goto error; } if (native_ctl == SNDRV_PCM_IOCTL_HW_PARAMS) recalculate_boundary(runtime); error: kfree(data); return err; }
/* both for HW_PARAMS and HW_REFINE */ static int snd_pcm_ioctl_hw_params_compat(struct snd_pcm_substream *substream, int refine, struct snd_pcm_hw_params32 __user *data32) { struct snd_pcm_hw_params *data; struct snd_pcm_runtime *runtime; int err; if (! (runtime = substream->runtime)) return -ENOTTY; data = kmalloc(sizeof(*data), GFP_KERNEL); if (!data) return -ENOMEM; /* only fifo_size (RO from userspace) is different, so just copy all */ if (copy_from_user(data, data32, sizeof(*data32))) { err = -EFAULT; goto error; } if (refine) err = snd_pcm_hw_refine(substream, data); else err = snd_pcm_hw_params(substream, data); if (err < 0) goto error; if (copy_to_user(data32, data, sizeof(*data32)) || put_user(data->fifo_size, &data32->fifo_size)) { err = -EFAULT; goto error; } if (! refine) { unsigned int new_boundary = recalculate_boundary(runtime); if (new_boundary) runtime->boundary = new_boundary; } error: kfree(data); return err; }
/* * here goes a really tricky part; hw_refine falls back to ACCESS_RW_* type * when ACCESS_MMAP_* isn't supported by the hardware. */ static int snd_pcm_mmap_emul_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params) { mmap_emul_t *map = pcm->private_data; int err = 0; snd_pcm_access_mask_t oldmask = *snd_pcm_hw_param_get_mask(params, SND_PCM_HW_PARAM_ACCESS); snd_pcm_access_mask_t mask; const snd_mask_t *pmask; snd_mask_none(&mask); err = snd_pcm_hw_refine(map->gen.slave, params); if (err < 0) { snd_pcm_hw_params_t new = *params; /* try to use RW_* */ if (snd_pcm_access_mask_test(&oldmask, SND_PCM_ACCESS_MMAP_INTERLEAVED) && !snd_pcm_access_mask_test(&oldmask, SND_PCM_ACCESS_RW_INTERLEAVED)) snd_pcm_access_mask_set(&mask, SND_PCM_ACCESS_RW_INTERLEAVED); if (snd_pcm_access_mask_test(&oldmask, SND_PCM_ACCESS_MMAP_NONINTERLEAVED) && !snd_pcm_access_mask_test(&oldmask, SND_PCM_ACCESS_RW_NONINTERLEAVED)) snd_pcm_access_mask_set(&mask, SND_PCM_ACCESS_RW_NONINTERLEAVED); if (snd_pcm_access_mask_empty(&mask)) return err; pmask = snd_pcm_hw_param_get_mask(&new, SND_PCM_HW_PARAM_ACCESS); *(snd_mask_t *)pmask = mask; err = snd_pcm_hw_refine(map->gen.slave, &new); if (err < 0) return err; *params = new; }
int ksnd_pcm_hw_params_any(ksnd_pcm_t *kpcm, ksnd_pcm_hw_params_t *params) { snd_pcm_substream_t *substream = kpcm->substream; _snd_pcm_hw_params_any(params); return snd_pcm_hw_refine(substream, params); }
int snd_pcm_generic_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params) { snd_pcm_generic_t *generic = pcm->private_data; return snd_pcm_hw_refine(generic->slave, params); }