cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

control.h (9961B)


      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 <perex@perex.cz>
      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
     16struct snd_kcontrol;
     17typedef int (snd_kcontrol_info_t) (struct snd_kcontrol * kcontrol, struct snd_ctl_elem_info * uinfo);
     18typedef int (snd_kcontrol_get_t) (struct snd_kcontrol * kcontrol, struct snd_ctl_elem_value * ucontrol);
     19typedef int (snd_kcontrol_put_t) (struct snd_kcontrol * kcontrol, struct snd_ctl_elem_value * ucontrol);
     20typedef 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_VALIDATION
     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
     41enum {
     42	SNDRV_CTL_TLV_OP_READ = 0,
     43	SNDRV_CTL_TLV_OP_WRITE = 1,
     44	SNDRV_CTL_TLV_OP_CMD = -1,
     45};
     46
     47struct 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
     65struct snd_kcontrol_volatile {
     66	struct snd_ctl_file *owner;	/* locked */
     67	unsigned int access;	/* access rights */
     68};
     69
     70struct 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[];	/* volatile data */
     85};
     86
     87#define snd_kcontrol(n) list_entry(n, struct snd_kcontrol, list)
     88
     89struct 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
     97struct pid;
     98
     99enum {
    100	SND_CTL_SUBDEV_PCM,
    101	SND_CTL_SUBDEV_RAWMIDI,
    102	SND_CTL_SUBDEV_ITEMS,
    103};
    104
    105struct 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 fasync_struct *fasync;
    113	int subscribed;			/* read interface is activated */
    114	struct list_head events;	/* waiting events for read */
    115};
    116
    117struct 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
    127typedef int (*snd_kctl_ioctl_func_t) (struct snd_card * card,
    128				      struct snd_ctl_file * control,
    129				      unsigned int cmd, unsigned long arg);
    130
    131void snd_ctl_notify(struct snd_card * card, unsigned int mask, struct snd_ctl_elem_id * id);
    132void snd_ctl_notify_one(struct snd_card * card, unsigned int mask, struct snd_kcontrol * kctl, unsigned int ioff);
    133
    134struct snd_kcontrol *snd_ctl_new1(const struct snd_kcontrol_new * kcontrolnew, void * private_data);
    135void snd_ctl_free_one(struct snd_kcontrol * kcontrol);
    136int snd_ctl_add(struct snd_card * card, struct snd_kcontrol * kcontrol);
    137int snd_ctl_remove(struct snd_card * card, struct snd_kcontrol * kcontrol);
    138int snd_ctl_replace(struct snd_card *card, struct snd_kcontrol *kcontrol, bool add_on_replace);
    139int snd_ctl_remove_id(struct snd_card * card, struct snd_ctl_elem_id *id);
    140int snd_ctl_rename_id(struct snd_card * card, struct snd_ctl_elem_id *src_id, struct snd_ctl_elem_id *dst_id);
    141int snd_ctl_activate_id(struct snd_card *card, struct snd_ctl_elem_id *id, int active);
    142struct snd_kcontrol *snd_ctl_find_numid(struct snd_card * card, unsigned int numid);
    143struct snd_kcontrol *snd_ctl_find_id(struct snd_card * card, struct snd_ctl_elem_id *id);
    144
    145int snd_ctl_create(struct snd_card *card);
    146
    147int snd_ctl_register_ioctl(snd_kctl_ioctl_func_t fcn);
    148int snd_ctl_unregister_ioctl(snd_kctl_ioctl_func_t fcn);
    149#ifdef CONFIG_COMPAT
    150int snd_ctl_register_ioctl_compat(snd_kctl_ioctl_func_t fcn);
    151int snd_ctl_unregister_ioctl_compat(snd_kctl_ioctl_func_t fcn);
    152#else
    153#define snd_ctl_register_ioctl_compat(fcn)
    154#define snd_ctl_unregister_ioctl_compat(fcn)
    155#endif
    156
    157int snd_ctl_request_layer(const char *module_name);
    158void snd_ctl_register_layer(struct snd_ctl_layer_ops *lops);
    159void snd_ctl_disconnect_layer(struct snd_ctl_layer_ops *lops);
    160
    161int snd_ctl_get_preferred_subdevice(struct snd_card *card, int type);
    162
    163static inline unsigned int snd_ctl_get_ioffnum(struct snd_kcontrol *kctl, struct snd_ctl_elem_id *id)
    164{
    165	unsigned int ioff = id->numid - kctl->id.numid;
    166	return array_index_nospec(ioff, kctl->count);
    167}
    168
    169static inline unsigned int snd_ctl_get_ioffidx(struct snd_kcontrol *kctl, struct snd_ctl_elem_id *id)
    170{
    171	unsigned int ioff = id->index - kctl->id.index;
    172	return array_index_nospec(ioff, kctl->count);
    173}
    174
    175static inline unsigned int snd_ctl_get_ioff(struct snd_kcontrol *kctl, struct snd_ctl_elem_id *id)
    176{
    177	if (id->numid) {
    178		return snd_ctl_get_ioffnum(kctl, id);
    179	} else {
    180		return snd_ctl_get_ioffidx(kctl, id);
    181	}
    182}
    183
    184static inline struct snd_ctl_elem_id *snd_ctl_build_ioff(struct snd_ctl_elem_id *dst_id,
    185						    struct snd_kcontrol *src_kctl,
    186						    unsigned int offset)
    187{
    188	*dst_id = src_kctl->id;
    189	dst_id->index += offset;
    190	dst_id->numid += offset;
    191	return dst_id;
    192}
    193
    194/*
    195 * Frequently used control callbacks/helpers
    196 */
    197int snd_ctl_boolean_mono_info(struct snd_kcontrol *kcontrol,
    198			      struct snd_ctl_elem_info *uinfo);
    199int snd_ctl_boolean_stereo_info(struct snd_kcontrol *kcontrol,
    200				struct snd_ctl_elem_info *uinfo);
    201int snd_ctl_enum_info(struct snd_ctl_elem_info *info, unsigned int channels,
    202		      unsigned int items, const char *const names[]);
    203
    204/*
    205 * virtual master control
    206 */
    207struct snd_kcontrol *snd_ctl_make_virtual_master(char *name,
    208						 const unsigned int *tlv);
    209int _snd_ctl_add_follower(struct snd_kcontrol *master,
    210			  struct snd_kcontrol *follower,
    211			  unsigned int flags);
    212/* optional flags for follower */
    213#define SND_CTL_FOLLOWER_NEED_UPDATE	(1 << 0)
    214
    215/**
    216 * snd_ctl_add_follower - Add a virtual follower control
    217 * @master: vmaster element
    218 * @follower: follower element to add
    219 *
    220 * Add a virtual follower control to the given master element created via
    221 * snd_ctl_create_virtual_master() beforehand.
    222 *
    223 * All followers must be the same type (returning the same information
    224 * via info callback).  The function doesn't check it, so it's your
    225 * responsibility.
    226 *
    227 * Also, some additional limitations:
    228 * at most two channels,
    229 * logarithmic volume control (dB level) thus no linear volume,
    230 * master can only attenuate the volume without gain
    231 *
    232 * Return: Zero if successful or a negative error code.
    233 */
    234static inline int
    235snd_ctl_add_follower(struct snd_kcontrol *master, struct snd_kcontrol *follower)
    236{
    237	return _snd_ctl_add_follower(master, follower, 0);
    238}
    239
    240/**
    241 * snd_ctl_add_follower_uncached - Add a virtual follower control
    242 * @master: vmaster element
    243 * @follower: follower element to add
    244 *
    245 * Add a virtual follower control to the given master.
    246 * Unlike snd_ctl_add_follower(), the element added via this function
    247 * is supposed to have volatile values, and get callback is called
    248 * at each time queried from the master.
    249 *
    250 * When the control peeks the hardware values directly and the value
    251 * can be changed by other means than the put callback of the element,
    252 * this function should be used to keep the value always up-to-date.
    253 *
    254 * Return: Zero if successful or a negative error code.
    255 */
    256static inline int
    257snd_ctl_add_follower_uncached(struct snd_kcontrol *master,
    258			      struct snd_kcontrol *follower)
    259{
    260	return _snd_ctl_add_follower(master, follower, SND_CTL_FOLLOWER_NEED_UPDATE);
    261}
    262
    263int snd_ctl_add_vmaster_hook(struct snd_kcontrol *kctl,
    264			     void (*hook)(void *private_data, int),
    265			     void *private_data);
    266void snd_ctl_sync_vmaster(struct snd_kcontrol *kctl, bool hook_only);
    267#define snd_ctl_sync_vmaster_hook(kctl)	snd_ctl_sync_vmaster(kctl, true)
    268int snd_ctl_apply_vmaster_followers(struct snd_kcontrol *kctl,
    269				    int (*func)(struct snd_kcontrol *vfollower,
    270						struct snd_kcontrol *follower,
    271						void *arg),
    272				    void *arg);
    273
    274/*
    275 * Control LED trigger layer
    276 */
    277#define SND_CTL_LAYER_MODULE_LED	"snd-ctl-led"
    278
    279#if IS_MODULE(CONFIG_SND_CTL_LED)
    280static inline int snd_ctl_led_request(void) { return snd_ctl_request_layer(SND_CTL_LAYER_MODULE_LED); }
    281#else
    282static inline int snd_ctl_led_request(void) { return 0; }
    283#endif
    284
    285/*
    286 * Helper functions for jack-detection controls
    287 */
    288struct snd_kcontrol *
    289snd_kctl_jack_new(const char *name, struct snd_card *card);
    290void snd_kctl_jack_report(struct snd_card *card,
    291			  struct snd_kcontrol *kctl, bool status);
    292
    293#endif	/* __SOUND_CONTROL_H */