Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/include/sound/control.h
26278 views
1
/* SPDX-License-Identifier: GPL-2.0-or-later */
2
#ifndef __SOUND_CONTROL_H
3
#define __SOUND_CONTROL_H
4
5
/*
6
* Header file for control interface
7
* Copyright (c) by Jaroslav Kysela <[email protected]>
8
*/
9
10
#include <linux/wait.h>
11
#include <linux/nospec.h>
12
#include <sound/asound.h>
13
14
#define snd_kcontrol_chip(kcontrol) ((kcontrol)->private_data)
15
16
struct snd_kcontrol;
17
typedef int (snd_kcontrol_info_t) (struct snd_kcontrol * kcontrol, struct snd_ctl_elem_info * uinfo);
18
typedef int (snd_kcontrol_get_t) (struct snd_kcontrol * kcontrol, struct snd_ctl_elem_value * ucontrol);
19
typedef int (snd_kcontrol_put_t) (struct snd_kcontrol * kcontrol, struct snd_ctl_elem_value * ucontrol);
20
typedef int (snd_kcontrol_tlv_rw_t)(struct snd_kcontrol *kcontrol,
21
int op_flag, /* SNDRV_CTL_TLV_OP_XXX */
22
unsigned int size,
23
unsigned int __user *tlv);
24
25
/* internal flag for skipping validations */
26
#ifdef CONFIG_SND_CTL_DEBUG
27
#define SNDRV_CTL_ELEM_ACCESS_SKIP_CHECK (1 << 24)
28
#define snd_ctl_skip_validation(info) \
29
((info)->access & SNDRV_CTL_ELEM_ACCESS_SKIP_CHECK)
30
#else
31
#define SNDRV_CTL_ELEM_ACCESS_SKIP_CHECK 0
32
#define snd_ctl_skip_validation(info) true
33
#endif
34
35
/* kernel only - LED bits */
36
#define SNDRV_CTL_ELEM_ACCESS_LED_SHIFT 25
37
#define SNDRV_CTL_ELEM_ACCESS_LED_MASK (7<<25) /* kernel three bits - LED group */
38
#define SNDRV_CTL_ELEM_ACCESS_SPK_LED (1<<25) /* kernel speaker (output) LED flag */
39
#define SNDRV_CTL_ELEM_ACCESS_MIC_LED (2<<25) /* kernel microphone (input) LED flag */
40
41
enum {
42
SNDRV_CTL_TLV_OP_READ = 0,
43
SNDRV_CTL_TLV_OP_WRITE = 1,
44
SNDRV_CTL_TLV_OP_CMD = -1,
45
};
46
47
struct snd_kcontrol_new {
48
snd_ctl_elem_iface_t iface; /* interface identifier */
49
unsigned int device; /* device/client number */
50
unsigned int subdevice; /* subdevice (substream) number */
51
const char *name; /* ASCII name of item */
52
unsigned int index; /* index of item */
53
unsigned int access; /* access rights */
54
unsigned int count; /* count of same elements */
55
snd_kcontrol_info_t *info;
56
snd_kcontrol_get_t *get;
57
snd_kcontrol_put_t *put;
58
union {
59
snd_kcontrol_tlv_rw_t *c;
60
const unsigned int *p;
61
} tlv;
62
unsigned long private_value;
63
};
64
65
struct snd_kcontrol_volatile {
66
struct snd_ctl_file *owner; /* locked */
67
unsigned int access; /* access rights */
68
};
69
70
struct snd_kcontrol {
71
struct list_head list; /* list of controls */
72
struct snd_ctl_elem_id id;
73
unsigned int count; /* count of same elements */
74
snd_kcontrol_info_t *info;
75
snd_kcontrol_get_t *get;
76
snd_kcontrol_put_t *put;
77
union {
78
snd_kcontrol_tlv_rw_t *c;
79
const unsigned int *p;
80
} tlv;
81
unsigned long private_value;
82
void *private_data;
83
void (*private_free)(struct snd_kcontrol *kcontrol);
84
struct snd_kcontrol_volatile vd[] __counted_by(count); /* volatile data */
85
};
86
87
#define snd_kcontrol(n) list_entry(n, struct snd_kcontrol, list)
88
89
struct snd_kctl_event {
90
struct list_head list; /* list of events */
91
struct snd_ctl_elem_id id;
92
unsigned int mask;
93
};
94
95
#define snd_kctl_event(n) list_entry(n, struct snd_kctl_event, list)
96
97
struct pid;
98
99
enum {
100
SND_CTL_SUBDEV_PCM,
101
SND_CTL_SUBDEV_RAWMIDI,
102
SND_CTL_SUBDEV_ITEMS,
103
};
104
105
struct snd_ctl_file {
106
struct list_head list; /* list of all control files */
107
struct snd_card *card;
108
struct pid *pid;
109
int preferred_subdevice[SND_CTL_SUBDEV_ITEMS];
110
wait_queue_head_t change_sleep;
111
spinlock_t read_lock;
112
struct snd_fasync *fasync;
113
int subscribed; /* read interface is activated */
114
struct list_head events; /* waiting events for read */
115
};
116
117
struct snd_ctl_layer_ops {
118
struct snd_ctl_layer_ops *next;
119
const char *module_name;
120
void (*lregister)(struct snd_card *card);
121
void (*ldisconnect)(struct snd_card *card);
122
void (*lnotify)(struct snd_card *card, unsigned int mask, struct snd_kcontrol *kctl, unsigned int ioff);
123
};
124
125
#define snd_ctl_file(n) list_entry(n, struct snd_ctl_file, list)
126
127
typedef int (*snd_kctl_ioctl_func_t) (struct snd_card * card,
128
struct snd_ctl_file * control,
129
unsigned int cmd, unsigned long arg);
130
131
void snd_ctl_notify(struct snd_card * card, unsigned int mask, struct snd_ctl_elem_id * id);
132
void snd_ctl_notify_one(struct snd_card * card, unsigned int mask, struct snd_kcontrol * kctl, unsigned int ioff);
133
134
struct snd_kcontrol *snd_ctl_new1(const struct snd_kcontrol_new * kcontrolnew, void * private_data);
135
void snd_ctl_free_one(struct snd_kcontrol * kcontrol);
136
int snd_ctl_add(struct snd_card * card, struct snd_kcontrol * kcontrol);
137
int snd_ctl_remove(struct snd_card * card, struct snd_kcontrol * kcontrol);
138
int snd_ctl_replace(struct snd_card *card, struct snd_kcontrol *kcontrol, bool add_on_replace);
139
int snd_ctl_remove_id(struct snd_card * card, struct snd_ctl_elem_id *id);
140
int snd_ctl_rename_id(struct snd_card * card, struct snd_ctl_elem_id *src_id, struct snd_ctl_elem_id *dst_id);
141
void snd_ctl_rename(struct snd_card *card, struct snd_kcontrol *kctl, const char *name);
142
int snd_ctl_activate_id(struct snd_card *card, struct snd_ctl_elem_id *id, int active);
143
struct snd_kcontrol *snd_ctl_find_numid(struct snd_card *card, unsigned int numid);
144
struct snd_kcontrol *snd_ctl_find_id(struct snd_card *card, const struct snd_ctl_elem_id *id);
145
146
/**
147
* snd_ctl_find_id_mixer - find the control instance with the given name string
148
* @card: the card instance
149
* @name: the name string
150
*
151
* Finds the control instance with the given name and
152
* @SNDRV_CTL_ELEM_IFACE_MIXER. Other fields are set to zero.
153
*
154
* This is merely a wrapper to snd_ctl_find_id().
155
*
156
* Return: The pointer of the instance if found, or %NULL if not.
157
*/
158
static inline struct snd_kcontrol *
159
snd_ctl_find_id_mixer(struct snd_card *card, const char *name)
160
{
161
struct snd_ctl_elem_id id = {};
162
163
id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
164
strscpy(id.name, name, sizeof(id.name));
165
return snd_ctl_find_id(card, &id);
166
}
167
168
int snd_ctl_create(struct snd_card *card);
169
170
int snd_ctl_register_ioctl(snd_kctl_ioctl_func_t fcn);
171
int snd_ctl_unregister_ioctl(snd_kctl_ioctl_func_t fcn);
172
#ifdef CONFIG_COMPAT
173
int snd_ctl_register_ioctl_compat(snd_kctl_ioctl_func_t fcn);
174
int snd_ctl_unregister_ioctl_compat(snd_kctl_ioctl_func_t fcn);
175
#else
176
#define snd_ctl_register_ioctl_compat(fcn)
177
#define snd_ctl_unregister_ioctl_compat(fcn)
178
#endif
179
180
int snd_ctl_request_layer(const char *module_name);
181
void snd_ctl_register_layer(struct snd_ctl_layer_ops *lops);
182
void snd_ctl_disconnect_layer(struct snd_ctl_layer_ops *lops);
183
184
int snd_ctl_get_preferred_subdevice(struct snd_card *card, int type);
185
186
static inline unsigned int snd_ctl_get_ioffnum(struct snd_kcontrol *kctl, struct snd_ctl_elem_id *id)
187
{
188
unsigned int ioff = id->numid - kctl->id.numid;
189
return array_index_nospec(ioff, kctl->count);
190
}
191
192
static inline unsigned int snd_ctl_get_ioffidx(struct snd_kcontrol *kctl, struct snd_ctl_elem_id *id)
193
{
194
unsigned int ioff = id->index - kctl->id.index;
195
return array_index_nospec(ioff, kctl->count);
196
}
197
198
static inline unsigned int snd_ctl_get_ioff(struct snd_kcontrol *kctl, struct snd_ctl_elem_id *id)
199
{
200
if (id->numid) {
201
return snd_ctl_get_ioffnum(kctl, id);
202
} else {
203
return snd_ctl_get_ioffidx(kctl, id);
204
}
205
}
206
207
static inline struct snd_ctl_elem_id *snd_ctl_build_ioff(struct snd_ctl_elem_id *dst_id,
208
struct snd_kcontrol *src_kctl,
209
unsigned int offset)
210
{
211
*dst_id = src_kctl->id;
212
dst_id->index += offset;
213
dst_id->numid += offset;
214
return dst_id;
215
}
216
217
/*
218
* Frequently used control callbacks/helpers
219
*/
220
int snd_ctl_boolean_mono_info(struct snd_kcontrol *kcontrol,
221
struct snd_ctl_elem_info *uinfo);
222
int snd_ctl_boolean_stereo_info(struct snd_kcontrol *kcontrol,
223
struct snd_ctl_elem_info *uinfo);
224
int snd_ctl_enum_info(struct snd_ctl_elem_info *info, unsigned int channels,
225
unsigned int items, const char *const names[]);
226
227
/*
228
* virtual master control
229
*/
230
struct snd_kcontrol *snd_ctl_make_virtual_master(char *name,
231
const unsigned int *tlv);
232
int _snd_ctl_add_follower(struct snd_kcontrol *master,
233
struct snd_kcontrol *follower,
234
unsigned int flags);
235
/* optional flags for follower */
236
#define SND_CTL_FOLLOWER_NEED_UPDATE (1 << 0)
237
238
/**
239
* snd_ctl_add_follower - Add a virtual follower control
240
* @master: vmaster element
241
* @follower: follower element to add
242
*
243
* Add a virtual follower control to the given master element created via
244
* snd_ctl_create_virtual_master() beforehand.
245
*
246
* All followers must be the same type (returning the same information
247
* via info callback). The function doesn't check it, so it's your
248
* responsibility.
249
*
250
* Also, some additional limitations:
251
* at most two channels,
252
* logarithmic volume control (dB level) thus no linear volume,
253
* master can only attenuate the volume without gain
254
*
255
* Return: Zero if successful or a negative error code.
256
*/
257
static inline int
258
snd_ctl_add_follower(struct snd_kcontrol *master, struct snd_kcontrol *follower)
259
{
260
return _snd_ctl_add_follower(master, follower, 0);
261
}
262
263
int snd_ctl_add_followers(struct snd_card *card, struct snd_kcontrol *master,
264
const char * const *list);
265
266
/**
267
* snd_ctl_add_follower_uncached - Add a virtual follower control
268
* @master: vmaster element
269
* @follower: follower element to add
270
*
271
* Add a virtual follower control to the given master.
272
* Unlike snd_ctl_add_follower(), the element added via this function
273
* is supposed to have volatile values, and get callback is called
274
* at each time queried from the master.
275
*
276
* When the control peeks the hardware values directly and the value
277
* can be changed by other means than the put callback of the element,
278
* this function should be used to keep the value always up-to-date.
279
*
280
* Return: Zero if successful or a negative error code.
281
*/
282
static inline int
283
snd_ctl_add_follower_uncached(struct snd_kcontrol *master,
284
struct snd_kcontrol *follower)
285
{
286
return _snd_ctl_add_follower(master, follower, SND_CTL_FOLLOWER_NEED_UPDATE);
287
}
288
289
int snd_ctl_add_vmaster_hook(struct snd_kcontrol *kctl,
290
void (*hook)(void *private_data, int),
291
void *private_data);
292
void snd_ctl_sync_vmaster(struct snd_kcontrol *kctl, bool hook_only);
293
#define snd_ctl_sync_vmaster_hook(kctl) snd_ctl_sync_vmaster(kctl, true)
294
int snd_ctl_apply_vmaster_followers(struct snd_kcontrol *kctl,
295
int (*func)(struct snd_kcontrol *vfollower,
296
struct snd_kcontrol *follower,
297
void *arg),
298
void *arg);
299
300
/*
301
* Control LED trigger layer
302
*/
303
#define SND_CTL_LAYER_MODULE_LED "snd-ctl-led"
304
305
#if IS_MODULE(CONFIG_SND_CTL_LED)
306
static inline int snd_ctl_led_request(void) { return snd_ctl_request_layer(SND_CTL_LAYER_MODULE_LED); }
307
#else
308
static inline int snd_ctl_led_request(void) { return 0; }
309
#endif
310
311
/*
312
* Helper functions for jack-detection controls
313
*/
314
struct snd_kcontrol *
315
snd_kctl_jack_new(const char *name, struct snd_card *card);
316
void snd_kctl_jack_report(struct snd_card *card,
317
struct snd_kcontrol *kctl, bool status);
318
319
#endif /* __SOUND_CONTROL_H */
320
321