Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0-or-later */
0002 #ifndef __SOUND_CONTROL_H
0003 #define __SOUND_CONTROL_H
0004 
0005 /*
0006  *  Header file for control interface
0007  *  Copyright (c) by Jaroslav Kysela <perex@perex.cz>
0008  */
0009 
0010 #include <linux/wait.h>
0011 #include <linux/nospec.h>
0012 #include <sound/asound.h>
0013 
0014 #define snd_kcontrol_chip(kcontrol) ((kcontrol)->private_data)
0015 
0016 struct snd_kcontrol;
0017 typedef int (snd_kcontrol_info_t) (struct snd_kcontrol * kcontrol, struct snd_ctl_elem_info * uinfo);
0018 typedef int (snd_kcontrol_get_t) (struct snd_kcontrol * kcontrol, struct snd_ctl_elem_value * ucontrol);
0019 typedef int (snd_kcontrol_put_t) (struct snd_kcontrol * kcontrol, struct snd_ctl_elem_value * ucontrol);
0020 typedef int (snd_kcontrol_tlv_rw_t)(struct snd_kcontrol *kcontrol,
0021                     int op_flag, /* SNDRV_CTL_TLV_OP_XXX */
0022                     unsigned int size,
0023                     unsigned int __user *tlv);
0024 
0025 /* internal flag for skipping validations */
0026 #ifdef CONFIG_SND_CTL_DEBUG
0027 #define SNDRV_CTL_ELEM_ACCESS_SKIP_CHECK    (1 << 24)
0028 #define snd_ctl_skip_validation(info) \
0029     ((info)->access & SNDRV_CTL_ELEM_ACCESS_SKIP_CHECK)
0030 #else
0031 #define SNDRV_CTL_ELEM_ACCESS_SKIP_CHECK    0
0032 #define snd_ctl_skip_validation(info)       true
0033 #endif
0034 
0035 /* kernel only - LED bits */
0036 #define SNDRV_CTL_ELEM_ACCESS_LED_SHIFT     25
0037 #define SNDRV_CTL_ELEM_ACCESS_LED_MASK      (7<<25) /* kernel three bits - LED group */
0038 #define SNDRV_CTL_ELEM_ACCESS_SPK_LED       (1<<25) /* kernel speaker (output) LED flag */
0039 #define SNDRV_CTL_ELEM_ACCESS_MIC_LED       (2<<25) /* kernel microphone (input) LED flag */
0040 
0041 enum {
0042     SNDRV_CTL_TLV_OP_READ = 0,
0043     SNDRV_CTL_TLV_OP_WRITE = 1,
0044     SNDRV_CTL_TLV_OP_CMD = -1,
0045 };
0046 
0047 struct snd_kcontrol_new {
0048     snd_ctl_elem_iface_t iface; /* interface identifier */
0049     unsigned int device;        /* device/client number */
0050     unsigned int subdevice;     /* subdevice (substream) number */
0051     const char *name;       /* ASCII name of item */
0052     unsigned int index;     /* index of item */
0053     unsigned int access;        /* access rights */
0054     unsigned int count;     /* count of same elements */
0055     snd_kcontrol_info_t *info;
0056     snd_kcontrol_get_t *get;
0057     snd_kcontrol_put_t *put;
0058     union {
0059         snd_kcontrol_tlv_rw_t *c;
0060         const unsigned int *p;
0061     } tlv;
0062     unsigned long private_value;
0063 };
0064 
0065 struct snd_kcontrol_volatile {
0066     struct snd_ctl_file *owner; /* locked */
0067     unsigned int access;    /* access rights */
0068 };
0069 
0070 struct snd_kcontrol {
0071     struct list_head list;      /* list of controls */
0072     struct snd_ctl_elem_id id;
0073     unsigned int count;     /* count of same elements */
0074     snd_kcontrol_info_t *info;
0075     snd_kcontrol_get_t *get;
0076     snd_kcontrol_put_t *put;
0077     union {
0078         snd_kcontrol_tlv_rw_t *c;
0079         const unsigned int *p;
0080     } tlv;
0081     unsigned long private_value;
0082     void *private_data;
0083     void (*private_free)(struct snd_kcontrol *kcontrol);
0084     struct snd_kcontrol_volatile vd[];  /* volatile data */
0085 };
0086 
0087 #define snd_kcontrol(n) list_entry(n, struct snd_kcontrol, list)
0088 
0089 struct snd_kctl_event {
0090     struct list_head list;  /* list of events */
0091     struct snd_ctl_elem_id id;
0092     unsigned int mask;
0093 };
0094 
0095 #define snd_kctl_event(n) list_entry(n, struct snd_kctl_event, list)
0096 
0097 struct pid;
0098 
0099 enum {
0100     SND_CTL_SUBDEV_PCM,
0101     SND_CTL_SUBDEV_RAWMIDI,
0102     SND_CTL_SUBDEV_ITEMS,
0103 };
0104 
0105 struct snd_ctl_file {
0106     struct list_head list;      /* list of all control files */
0107     struct snd_card *card;
0108     struct pid *pid;
0109     int preferred_subdevice[SND_CTL_SUBDEV_ITEMS];
0110     wait_queue_head_t change_sleep;
0111     spinlock_t read_lock;
0112     struct snd_fasync *fasync;
0113     int subscribed;         /* read interface is activated */
0114     struct list_head events;    /* waiting events for read */
0115 };
0116 
0117 struct snd_ctl_layer_ops {
0118     struct snd_ctl_layer_ops *next;
0119     const char *module_name;
0120     void (*lregister)(struct snd_card *card);
0121     void (*ldisconnect)(struct snd_card *card);
0122     void (*lnotify)(struct snd_card *card, unsigned int mask, struct snd_kcontrol *kctl, unsigned int ioff);
0123 };
0124 
0125 #define snd_ctl_file(n) list_entry(n, struct snd_ctl_file, list)
0126 
0127 typedef int (*snd_kctl_ioctl_func_t) (struct snd_card * card,
0128                       struct snd_ctl_file * control,
0129                       unsigned int cmd, unsigned long arg);
0130 
0131 void snd_ctl_notify(struct snd_card * card, unsigned int mask, struct snd_ctl_elem_id * id);
0132 void snd_ctl_notify_one(struct snd_card * card, unsigned int mask, struct snd_kcontrol * kctl, unsigned int ioff);
0133 
0134 struct snd_kcontrol *snd_ctl_new1(const struct snd_kcontrol_new * kcontrolnew, void * private_data);
0135 void snd_ctl_free_one(struct snd_kcontrol * kcontrol);
0136 int snd_ctl_add(struct snd_card * card, struct snd_kcontrol * kcontrol);
0137 int snd_ctl_remove(struct snd_card * card, struct snd_kcontrol * kcontrol);
0138 int snd_ctl_replace(struct snd_card *card, struct snd_kcontrol *kcontrol, bool add_on_replace);
0139 int snd_ctl_remove_id(struct snd_card * card, struct snd_ctl_elem_id *id);
0140 int snd_ctl_rename_id(struct snd_card * card, struct snd_ctl_elem_id *src_id, struct snd_ctl_elem_id *dst_id);
0141 int snd_ctl_activate_id(struct snd_card *card, struct snd_ctl_elem_id *id, int active);
0142 struct snd_kcontrol *snd_ctl_find_numid(struct snd_card * card, unsigned int numid);
0143 struct snd_kcontrol *snd_ctl_find_id(struct snd_card * card, struct snd_ctl_elem_id *id);
0144 
0145 int snd_ctl_create(struct snd_card *card);
0146 
0147 int snd_ctl_register_ioctl(snd_kctl_ioctl_func_t fcn);
0148 int snd_ctl_unregister_ioctl(snd_kctl_ioctl_func_t fcn);
0149 #ifdef CONFIG_COMPAT
0150 int snd_ctl_register_ioctl_compat(snd_kctl_ioctl_func_t fcn);
0151 int snd_ctl_unregister_ioctl_compat(snd_kctl_ioctl_func_t fcn);
0152 #else
0153 #define snd_ctl_register_ioctl_compat(fcn)
0154 #define snd_ctl_unregister_ioctl_compat(fcn)
0155 #endif
0156 
0157 int snd_ctl_request_layer(const char *module_name);
0158 void snd_ctl_register_layer(struct snd_ctl_layer_ops *lops);
0159 void snd_ctl_disconnect_layer(struct snd_ctl_layer_ops *lops);
0160 
0161 int snd_ctl_get_preferred_subdevice(struct snd_card *card, int type);
0162 
0163 static inline unsigned int snd_ctl_get_ioffnum(struct snd_kcontrol *kctl, struct snd_ctl_elem_id *id)
0164 {
0165     unsigned int ioff = id->numid - kctl->id.numid;
0166     return array_index_nospec(ioff, kctl->count);
0167 }
0168 
0169 static inline unsigned int snd_ctl_get_ioffidx(struct snd_kcontrol *kctl, struct snd_ctl_elem_id *id)
0170 {
0171     unsigned int ioff = id->index - kctl->id.index;
0172     return array_index_nospec(ioff, kctl->count);
0173 }
0174 
0175 static inline unsigned int snd_ctl_get_ioff(struct snd_kcontrol *kctl, struct snd_ctl_elem_id *id)
0176 {
0177     if (id->numid) {
0178         return snd_ctl_get_ioffnum(kctl, id);
0179     } else {
0180         return snd_ctl_get_ioffidx(kctl, id);
0181     }
0182 }
0183 
0184 static inline struct snd_ctl_elem_id *snd_ctl_build_ioff(struct snd_ctl_elem_id *dst_id,
0185                             struct snd_kcontrol *src_kctl,
0186                             unsigned int offset)
0187 {
0188     *dst_id = src_kctl->id;
0189     dst_id->index += offset;
0190     dst_id->numid += offset;
0191     return dst_id;
0192 }
0193 
0194 /*
0195  * Frequently used control callbacks/helpers
0196  */
0197 int snd_ctl_boolean_mono_info(struct snd_kcontrol *kcontrol,
0198                   struct snd_ctl_elem_info *uinfo);
0199 int snd_ctl_boolean_stereo_info(struct snd_kcontrol *kcontrol,
0200                 struct snd_ctl_elem_info *uinfo);
0201 int snd_ctl_enum_info(struct snd_ctl_elem_info *info, unsigned int channels,
0202               unsigned int items, const char *const names[]);
0203 
0204 /*
0205  * virtual master control
0206  */
0207 struct snd_kcontrol *snd_ctl_make_virtual_master(char *name,
0208                          const unsigned int *tlv);
0209 int _snd_ctl_add_follower(struct snd_kcontrol *master,
0210               struct snd_kcontrol *follower,
0211               unsigned int flags);
0212 /* optional flags for follower */
0213 #define SND_CTL_FOLLOWER_NEED_UPDATE    (1 << 0)
0214 
0215 /**
0216  * snd_ctl_add_follower - Add a virtual follower control
0217  * @master: vmaster element
0218  * @follower: follower element to add
0219  *
0220  * Add a virtual follower control to the given master element created via
0221  * snd_ctl_create_virtual_master() beforehand.
0222  *
0223  * All followers must be the same type (returning the same information
0224  * via info callback).  The function doesn't check it, so it's your
0225  * responsibility.
0226  *
0227  * Also, some additional limitations:
0228  * at most two channels,
0229  * logarithmic volume control (dB level) thus no linear volume,
0230  * master can only attenuate the volume without gain
0231  *
0232  * Return: Zero if successful or a negative error code.
0233  */
0234 static inline int
0235 snd_ctl_add_follower(struct snd_kcontrol *master, struct snd_kcontrol *follower)
0236 {
0237     return _snd_ctl_add_follower(master, follower, 0);
0238 }
0239 
0240 /**
0241  * snd_ctl_add_follower_uncached - Add a virtual follower control
0242  * @master: vmaster element
0243  * @follower: follower element to add
0244  *
0245  * Add a virtual follower control to the given master.
0246  * Unlike snd_ctl_add_follower(), the element added via this function
0247  * is supposed to have volatile values, and get callback is called
0248  * at each time queried from the master.
0249  *
0250  * When the control peeks the hardware values directly and the value
0251  * can be changed by other means than the put callback of the element,
0252  * this function should be used to keep the value always up-to-date.
0253  *
0254  * Return: Zero if successful or a negative error code.
0255  */
0256 static inline int
0257 snd_ctl_add_follower_uncached(struct snd_kcontrol *master,
0258                   struct snd_kcontrol *follower)
0259 {
0260     return _snd_ctl_add_follower(master, follower, SND_CTL_FOLLOWER_NEED_UPDATE);
0261 }
0262 
0263 int snd_ctl_add_vmaster_hook(struct snd_kcontrol *kctl,
0264                  void (*hook)(void *private_data, int),
0265                  void *private_data);
0266 void snd_ctl_sync_vmaster(struct snd_kcontrol *kctl, bool hook_only);
0267 #define snd_ctl_sync_vmaster_hook(kctl) snd_ctl_sync_vmaster(kctl, true)
0268 int snd_ctl_apply_vmaster_followers(struct snd_kcontrol *kctl,
0269                     int (*func)(struct snd_kcontrol *vfollower,
0270                         struct snd_kcontrol *follower,
0271                         void *arg),
0272                     void *arg);
0273 
0274 /*
0275  * Control LED trigger layer
0276  */
0277 #define SND_CTL_LAYER_MODULE_LED    "snd-ctl-led"
0278 
0279 #if IS_MODULE(CONFIG_SND_CTL_LED)
0280 static inline int snd_ctl_led_request(void) { return snd_ctl_request_layer(SND_CTL_LAYER_MODULE_LED); }
0281 #else
0282 static inline int snd_ctl_led_request(void) { return 0; }
0283 #endif
0284 
0285 /*
0286  * Helper functions for jack-detection controls
0287  */
0288 struct snd_kcontrol *
0289 snd_kctl_jack_new(const char *name, struct snd_card *card);
0290 void snd_kctl_jack_report(struct snd_card *card,
0291               struct snd_kcontrol *kctl, bool status);
0292 
0293 #endif  /* __SOUND_CONTROL_H */