^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /* SPDX-License-Identifier: GPL-2.0-or-later */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) #ifndef __SOUND_CONTROL_H
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) #define __SOUND_CONTROL_H
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Header file for control interface
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/wait.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/nospec.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <sound/asound.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #define snd_kcontrol_chip(kcontrol) ((kcontrol)->private_data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) struct snd_kcontrol;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) typedef int (snd_kcontrol_info_t) (struct snd_kcontrol * kcontrol, struct snd_ctl_elem_info * uinfo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) typedef int (snd_kcontrol_get_t) (struct snd_kcontrol * kcontrol, struct snd_ctl_elem_value * ucontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) typedef int (snd_kcontrol_put_t) (struct snd_kcontrol * kcontrol, struct snd_ctl_elem_value * ucontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) typedef int (snd_kcontrol_tlv_rw_t)(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) int op_flag, /* SNDRV_CTL_TLV_OP_XXX */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) unsigned int size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) unsigned int __user *tlv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) /* internal flag for skipping validations */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #ifdef CONFIG_SND_CTL_VALIDATION
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #define SNDRV_CTL_ELEM_ACCESS_SKIP_CHECK (1 << 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #define snd_ctl_skip_validation(info) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) ((info)->access & SNDRV_CTL_ELEM_ACCESS_SKIP_CHECK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define SNDRV_CTL_ELEM_ACCESS_SKIP_CHECK 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define snd_ctl_skip_validation(info) true
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) enum {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) SNDRV_CTL_TLV_OP_READ = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) SNDRV_CTL_TLV_OP_WRITE = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) SNDRV_CTL_TLV_OP_CMD = -1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) struct snd_kcontrol_new {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) snd_ctl_elem_iface_t iface; /* interface identifier */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) unsigned int device; /* device/client number */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) unsigned int subdevice; /* subdevice (substream) number */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) const char *name; /* ASCII name of item */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) unsigned int index; /* index of item */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) unsigned int access; /* access rights */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) unsigned int count; /* count of same elements */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) snd_kcontrol_info_t *info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) snd_kcontrol_get_t *get;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) snd_kcontrol_put_t *put;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) union {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) snd_kcontrol_tlv_rw_t *c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) const unsigned int *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) } tlv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) unsigned long private_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) struct snd_kcontrol_volatile {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) struct snd_ctl_file *owner; /* locked */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) unsigned int access; /* access rights */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) struct snd_kcontrol {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) struct list_head list; /* list of controls */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) struct snd_ctl_elem_id id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) unsigned int count; /* count of same elements */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) snd_kcontrol_info_t *info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) snd_kcontrol_get_t *get;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) snd_kcontrol_put_t *put;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) union {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) snd_kcontrol_tlv_rw_t *c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) const unsigned int *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) } tlv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) unsigned long private_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) void *private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) void (*private_free)(struct snd_kcontrol *kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) struct snd_kcontrol_volatile vd[]; /* volatile data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) #define snd_kcontrol(n) list_entry(n, struct snd_kcontrol, list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) struct snd_kctl_event {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) struct list_head list; /* list of events */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) struct snd_ctl_elem_id id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) unsigned int mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) #define snd_kctl_event(n) list_entry(n, struct snd_kctl_event, list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) struct pid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) enum {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) SND_CTL_SUBDEV_PCM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) SND_CTL_SUBDEV_RAWMIDI,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) SND_CTL_SUBDEV_ITEMS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) struct snd_ctl_file {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) struct list_head list; /* list of all control files */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) struct snd_card *card;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) struct pid *pid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) int preferred_subdevice[SND_CTL_SUBDEV_ITEMS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) wait_queue_head_t change_sleep;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) spinlock_t read_lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) struct fasync_struct *fasync;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) int subscribed; /* read interface is activated */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) struct list_head events; /* waiting events for read */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) #define snd_ctl_file(n) list_entry(n, struct snd_ctl_file, list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) typedef int (*snd_kctl_ioctl_func_t) (struct snd_card * card,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) struct snd_ctl_file * control,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) unsigned int cmd, unsigned long arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) void snd_ctl_notify(struct snd_card * card, unsigned int mask, struct snd_ctl_elem_id * id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) struct snd_kcontrol *snd_ctl_new1(const struct snd_kcontrol_new * kcontrolnew, void * private_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) void snd_ctl_free_one(struct snd_kcontrol * kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) int snd_ctl_add(struct snd_card * card, struct snd_kcontrol * kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) int snd_ctl_remove(struct snd_card * card, struct snd_kcontrol * kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) int snd_ctl_replace(struct snd_card *card, struct snd_kcontrol *kcontrol, bool add_on_replace);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) int snd_ctl_remove_id(struct snd_card * card, struct snd_ctl_elem_id *id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) int snd_ctl_rename_id(struct snd_card * card, struct snd_ctl_elem_id *src_id, struct snd_ctl_elem_id *dst_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) int snd_ctl_activate_id(struct snd_card *card, struct snd_ctl_elem_id *id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) int active);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) struct snd_kcontrol *snd_ctl_find_numid(struct snd_card * card, unsigned int numid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) struct snd_kcontrol *snd_ctl_find_id(struct snd_card * card, struct snd_ctl_elem_id *id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) int snd_ctl_create(struct snd_card *card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) int snd_ctl_register_ioctl(snd_kctl_ioctl_func_t fcn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) int snd_ctl_unregister_ioctl(snd_kctl_ioctl_func_t fcn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) #ifdef CONFIG_COMPAT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) int snd_ctl_register_ioctl_compat(snd_kctl_ioctl_func_t fcn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) int snd_ctl_unregister_ioctl_compat(snd_kctl_ioctl_func_t fcn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) #define snd_ctl_register_ioctl_compat(fcn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) #define snd_ctl_unregister_ioctl_compat(fcn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) int snd_ctl_get_preferred_subdevice(struct snd_card *card, int type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) static inline unsigned int snd_ctl_get_ioffnum(struct snd_kcontrol *kctl, struct snd_ctl_elem_id *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) unsigned int ioff = id->numid - kctl->id.numid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) return array_index_nospec(ioff, kctl->count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) static inline unsigned int snd_ctl_get_ioffidx(struct snd_kcontrol *kctl, struct snd_ctl_elem_id *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) unsigned int ioff = id->index - kctl->id.index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) return array_index_nospec(ioff, kctl->count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) static inline unsigned int snd_ctl_get_ioff(struct snd_kcontrol *kctl, struct snd_ctl_elem_id *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) if (id->numid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) return snd_ctl_get_ioffnum(kctl, id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) return snd_ctl_get_ioffidx(kctl, id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) static inline struct snd_ctl_elem_id *snd_ctl_build_ioff(struct snd_ctl_elem_id *dst_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) struct snd_kcontrol *src_kctl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) unsigned int offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) *dst_id = src_kctl->id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) dst_id->index += offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) dst_id->numid += offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) return dst_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) * Frequently used control callbacks/helpers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) int snd_ctl_boolean_mono_info(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) struct snd_ctl_elem_info *uinfo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) int snd_ctl_boolean_stereo_info(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) struct snd_ctl_elem_info *uinfo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) int snd_ctl_enum_info(struct snd_ctl_elem_info *info, unsigned int channels,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) unsigned int items, const char *const names[]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) * virtual master control
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) struct snd_kcontrol *snd_ctl_make_virtual_master(char *name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) const unsigned int *tlv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) int _snd_ctl_add_follower(struct snd_kcontrol *master,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) struct snd_kcontrol *follower,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) unsigned int flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) /* optional flags for follower */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) #define SND_CTL_FOLLOWER_NEED_UPDATE (1 << 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) * snd_ctl_add_follower - Add a virtual follower control
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) * @master: vmaster element
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) * @follower: follower element to add
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) * Add a virtual follower control to the given master element created via
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) * snd_ctl_create_virtual_master() beforehand.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) * All followers must be the same type (returning the same information
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) * via info callback). The function doesn't check it, so it's your
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) * responsibility.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) * Also, some additional limitations:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) * at most two channels,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) * logarithmic volume control (dB level) thus no linear volume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) * master can only attenuate the volume without gain
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) * Return: Zero if successful or a negative error code.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) static inline int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) snd_ctl_add_follower(struct snd_kcontrol *master, struct snd_kcontrol *follower)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) return _snd_ctl_add_follower(master, follower, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) * snd_ctl_add_follower_uncached - Add a virtual follower control
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) * @master: vmaster element
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) * @follower: follower element to add
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) * Add a virtual follower control to the given master.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) * Unlike snd_ctl_add_follower(), the element added via this function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) * is supposed to have volatile values, and get callback is called
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) * at each time queried from the master.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) * When the control peeks the hardware values directly and the value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) * can be changed by other means than the put callback of the element,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) * this function should be used to keep the value always up-to-date.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) * Return: Zero if successful or a negative error code.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) static inline int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) snd_ctl_add_follower_uncached(struct snd_kcontrol *master,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) struct snd_kcontrol *follower)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) return _snd_ctl_add_follower(master, follower, SND_CTL_FOLLOWER_NEED_UPDATE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) int snd_ctl_add_vmaster_hook(struct snd_kcontrol *kctl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) void (*hook)(void *private_data, int),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) void *private_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) void snd_ctl_sync_vmaster(struct snd_kcontrol *kctl, bool hook_only);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) #define snd_ctl_sync_vmaster_hook(kctl) snd_ctl_sync_vmaster(kctl, true)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) int snd_ctl_apply_vmaster_followers(struct snd_kcontrol *kctl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) int (*func)(struct snd_kcontrol *vfollower,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) struct snd_kcontrol *follower,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) void *arg),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) void *arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) * Helper functions for jack-detection controls
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) struct snd_kcontrol *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) snd_kctl_jack_new(const char *name, struct snd_card *card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) void snd_kctl_jack_report(struct snd_card *card,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) struct snd_kcontrol *kctl, bool status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) #endif /* __SOUND_CONTROL_H */