| 1 |
|
| 2 | #ifndef __SOUND_CORE_H
|
| 3 | #define __SOUND_CORE_H
|
| 4 |
|
| 5 | |
| 6 | * Main header file for the ALSA driver
|
| 7 | * Copyright (c) 1994-2001 by Jaroslav Kysela <[email protected]>
|
| 8 |
|
| 9 |
|
| 10 | #include <linux/device.h>
|
| 11 | #include <linux/sched.h>
|
| 12 | #include <linux/mutex.h>
|
| 13 | #include <linux/rwsem.h>
|
| 14 | #include <linux/pm.h>
|
| 15 | #include <linux/stringify.h>
|
| 16 | #include <linux/printk.h>
|
| 17 | #include <linux/xarray.h>
|
| 18 |
|
| 19 |
|
| 20 | #ifdef CONFIG_SND_DYNAMIC_MINORS
|
| 21 | #define SNDRV_CARDS CONFIG_SND_MAX_CARDS
|
| 22 | #else
|
| 23 | #define SNDRV_CARDS 8
|
| 24 | #endif
|
| 25 |
|
| 26 | #define CONFIG_SND_MAJOR 116
|
| 27 |
|
| 28 |
|
| 29 | struct pci_dev;
|
| 30 | struct module;
|
| 31 | struct completion;
|
| 32 |
|
| 33 |
|
| 34 |
|
| 35 | |
| 36 | * this also defines the calling order
|
| 37 |
|
| 38 | enum snd_device_type {
|
| 39 | SNDRV_DEV_LOWLEVEL,
|
| 40 | SNDRV_DEV_INFO,
|
| 41 | SNDRV_DEV_BUS,
|
| 42 | SNDRV_DEV_CODEC,
|
| 43 | SNDRV_DEV_PCM,
|
| 44 | SNDRV_DEV_COMPRESS,
|
| 45 | SNDRV_DEV_RAWMIDI,
|
| 46 | SNDRV_DEV_TIMER,
|
| 47 | SNDRV_DEV_SEQUENCER,
|
| 48 | SNDRV_DEV_HWDEP,
|
| 49 | SNDRV_DEV_JACK,
|
| 50 | SNDRV_DEV_CONTROL,
|
| 51 | };
|
| 52 |
|
| 53 | enum snd_device_state {
|
| 54 | SNDRV_DEV_BUILD,
|
| 55 | SNDRV_DEV_REGISTERED,
|
| 56 | SNDRV_DEV_DISCONNECTED,
|
| 57 | };
|
| 58 |
|
| 59 | struct snd_device;
|
| 60 |
|
| 61 | struct snd_device_ops {
|
| 62 | int (*dev_free)(struct snd_device *dev);
|
| 63 | int (*dev_register)(struct snd_device *dev);
|
| 64 | int (*dev_disconnect)(struct snd_device *dev);
|
| 65 | };
|
| 66 |
|
| 67 | struct snd_device {
|
| 68 | struct list_head list;
|
| 69 | struct snd_card *card;
|
| 70 | enum snd_device_state state;
|
| 71 | enum snd_device_type type;
|
| 72 | void *device_data;
|
| 73 | const struct snd_device_ops *ops;
|
| 74 | };
|
| 75 |
|
| 76 | #define snd_device(n) list_entry(n, struct snd_device, list)
|
| 77 |
|
| 78 | |
| 79 | * A simple reference counter with a wait queue;
|
| 80 | * typically used for usage counts, and you can synchronize at finishing
|
| 81 | * via snd_refcount_sync(), which is woken up when the refcount reaches to
|
| 82 | * zero again.
|
| 83 |
|
| 84 | struct snd_refcount {
|
| 85 | atomic_t count;
|
| 86 | wait_queue_head_t waiter;
|
| 87 | };
|
| 88 |
|
| 89 | void snd_refcount_init(struct snd_refcount *ref);
|
| 90 |
|
| 91 | static inline void snd_refcount_get(struct snd_refcount *ref)
|
| 92 | {
|
| 93 | atomic_inc(&ref->count);
|
| 94 | }
|
| 95 |
|
| 96 | void snd_refcount_put(struct snd_refcount *ref);
|
| 97 | void snd_refcount_sync(struct snd_refcount *ref);
|
| 98 |
|
| 99 |
|
| 100 |
|
| 101 | struct snd_card {
|
| 102 | int number; |
| 103 | snd_cards)
|
| 104 |
|
| 105 | char id[16];
|
| 106 | char driver[16];
|
| 107 | char shortname[32];
|
| 108 | char longname[80];
|
| 109 | char irq_descr[32];
|
| 110 | char mixername[80];
|
| 111 | char *components;
|
| 112 | unsigned int components_alloc_size;
|
| 113 | struct module *module;
|
| 114 |
|
| 115 | void *private_data;
|
| 116 | void (*private_free) (struct snd_card *card); |
| 117 | private data
|
| 118 | struct list_head devices;
|
| 119 |
|
| 120 | struct device *ctl_dev;
|
| 121 | unsigned int last_numid;
|
| 122 | struct rw_semaphore controls_rwsem;
|
| 123 | rwlock_t controls_rwlock;
|
| 124 | int controls_count;
|
| 125 | size_t user_ctl_alloc_size; |
| 126 | struct list_head controls;
|
| 127 | struct list_head ctl_files;
|
| 128 | #ifdef CONFIG_SND_CTL_FAST_LOOKUP
|
| 129 | struct xarray ctl_numids;
|
| 130 | struct xarray ctl_hash;
|
| 131 | bool ctl_hash_collision;
|
| 132 | #endif
|
| 133 |
|
| 134 | struct snd_info_entry *proc_root;
|
| 135 | struct proc_dir_entry *proc_root_link;
|
| 136 |
|
| 137 | struct list_head files_list;
|
| 138 | struct snd_shutdown_f_ops *s_f_ops; |
| 139 | state
|
| 140 | spinlock_t files_lock;
|
| 141 | int shutdown;
|
| 142 | struct completion *release_completion;
|
| 143 | struct device *dev;
|
| 144 | struct device card_dev;
|
| 145 | const struct attribute_group *dev_groups[4];
|
| 146 | bool registered;
|
| 147 | bool managed;
|
| 148 | bool releasing;
|
| 149 | int sync_irq;
|
| 150 | wait_queue_head_t remove_sleep;
|
| 151 |
|
| 152 | size_t total_pcm_alloc_bytes;
|
| 153 | struct mutex memory_mutex;
|
| 154 | #ifdef CONFIG_SND_DEBUG
|
| 155 | struct dentry *debugfs_root;
|
| 156 | #endif
|
| 157 | #ifdef CONFIG_SND_CTL_DEBUG
|
| 158 | struct snd_ctl_elem_value *value_buf;
|
| 159 | #endif
|
| 160 |
|
| 161 | #ifdef CONFIG_PM
|
| 162 | unsigned int power_state;
|
| 163 | wait_queue_head_t power_sleep;
|
| 164 | struct snd_refcount power_ref;
|
| 165 | #endif
|
| 166 |
|
| 167 | #if IS_ENABLED(CONFIG_SND_MIXER_OSS)
|
| 168 | struct snd_mixer_oss *mixer_oss;
|
| 169 | int mixer_oss_change_count;
|
| 170 | #endif
|
| 171 |
|
| 172 | unsigned char private_data_area[] __aligned(__alignof__(unsigned long long));
|
| 173 | };
|
| 174 |
|
| 175 | #define dev_to_snd_card(p) container_of(p, struct snd_card, card_dev)
|
| 176 |
|
| 177 | #ifdef CONFIG_PM
|
| 178 | static inline unsigned int snd_power_get_state(struct snd_card *card)
|
| 179 | {
|
| 180 | return READ_ONCE(card->power_state);
|
| 181 | }
|
| 182 |
|
| 183 | static inline void snd_power_change_state(struct snd_card *card, unsigned int state)
|
| 184 | {
|
| 185 | WRITE_ONCE(card->power_state, state);
|
| 186 | wake_up(&card->power_sleep);
|
| 187 | }
|
| 188 |
|
| 189 | |
| 190 | * snd_power_ref - Take the reference count for power control
|
| 191 | * @card: sound card object
|
| 192 | *
|
| 193 | * The power_ref reference of the card is used for managing to block
|
| 194 | * the snd_power_sync_ref() operation. This function increments the reference.
|
| 195 | * The counterpart snd_power_unref() has to be called appropriately later.
|
| 196 |
|
| 197 | static inline void snd_power_ref(struct snd_card *card)
|
| 198 | {
|
| 199 | snd_refcount_get(&card->power_ref);
|
| 200 | }
|
| 201 |
|
| 202 | |
| 203 | * snd_power_unref - Release the reference count for power control
|
| 204 | * @card: sound card object
|
| 205 |
|
| 206 | static inline void snd_power_unref(struct snd_card *card)
|
| 207 | {
|
| 208 | snd_refcount_put(&card->power_ref);
|
| 209 | }
|
| 210 |
|
| 211 | |
| 212 | * snd_power_sync_ref - wait until the card power_ref is freed
|
| 213 | * @card: sound card object
|
| 214 | *
|
| 215 | * This function is used to synchronize with the pending power_ref being
|
| 216 | * released.
|
| 217 |
|
| 218 | static inline void snd_power_sync_ref(struct snd_card *card)
|
| 219 | {
|
| 220 | snd_refcount_sync(&card->power_ref);
|
| 221 | }
|
| 222 |
|
| 223 |
|
| 224 | int snd_power_wait(struct snd_card *card);
|
| 225 | int snd_power_ref_and_wait(struct snd_card *card);
|
| 226 |
|
| 227 | #else
|
| 228 |
|
| 229 | static inline int snd_power_wait(struct snd_card *card) { return 0; }
|
| 230 | static inline void snd_power_ref(struct snd_card *card) {}
|
| 231 | static inline void snd_power_unref(struct snd_card *card) {}
|
| 232 | static inline int snd_power_ref_and_wait(struct snd_card *card) { return 0; }
|
| 233 | static inline void snd_power_sync_ref(struct snd_card *card) {}
|
| 234 | #define snd_power_get_state(card) ({ (void)(card); SNDRV_CTL_POWER_D0; })
|
| 235 | #define snd_power_change_state(card, state) do { (void)(card); } while (0)
|
| 236 |
|
| 237 | #endif
|
| 238 |
|
| 239 | struct snd_minor {
|
| 240 | int type;
|
| 241 | int card;
|
| 242 | int device;
|
| 243 | const struct file_operations *f_ops;
|
| 244 | void *private_data;
|
| 245 | struct device *dev;
|
| 246 | struct snd_card *card_ptr;
|
| 247 | };
|
| 248 |
|
| 249 |
|
| 250 | static inline struct device *snd_card_get_device_link(struct snd_card *card)
|
| 251 | {
|
| 252 | return card ? &card->card_dev : NULL;
|
| 253 | }
|
| 254 |
|
| 255 |
|
| 256 |
|
| 257 | extern int snd_major;
|
| 258 | extern int snd_ecards_limit;
|
| 259 | extern const struct class sound_class;
|
| 260 | #ifdef CONFIG_SND_DEBUG
|
| 261 | extern struct dentry *sound_debugfs_root;
|
| 262 | #endif
|
| 263 |
|
| 264 | void snd_request_card(int card);
|
| 265 |
|
| 266 | int snd_device_alloc(struct device **dev_p, struct snd_card *card);
|
| 267 |
|
| 268 | int snd_register_device(int type, struct snd_card *card, int dev,
|
| 269 | const struct file_operations *f_ops,
|
| 270 | void *private_data, struct device *device);
|
| 271 | int snd_unregister_device(struct device *dev);
|
| 272 | void *snd_lookup_minor_data(unsigned int minor, int type);
|
| 273 |
|
| 274 | #ifdef CONFIG_SND_OSSEMUL
|
| 275 | int snd_register_oss_device(int type, struct snd_card *card, int dev,
|
| 276 | const struct file_operations *f_ops, void *private_data);
|
| 277 | int snd_unregister_oss_device(int type, struct snd_card *card, int dev);
|
| 278 | void *snd_lookup_oss_minor_data(unsigned int minor, int type);
|
| 279 | #endif
|
| 280 |
|
| 281 | int snd_minor_info_init(void);
|
| 282 |
|
| 283 |
|
| 284 |
|
| 285 | #ifdef CONFIG_SND_OSSEMUL
|
| 286 | int snd_minor_info_oss_init(void);
|
| 287 | #else
|
| 288 | static inline int snd_minor_info_oss_init(void) { return 0; }
|
| 289 | #endif
|
| 290 |
|
| 291 |
|
| 292 |
|
| 293 | int copy_to_user_fromio(void __user *dst, const volatile void __iomem *src, size_t count);
|
| 294 | int copy_from_user_toio(volatile void __iomem *dst, const void __user *src, size_t count);
|
| 295 |
|
| 296 |
|
| 297 |
|
| 298 | int snd_card_locked(int card);
|
| 299 | #if IS_ENABLED(CONFIG_SND_MIXER_OSS)
|
| 300 | #define SND_MIXER_OSS_NOTIFY_REGISTER 0
|
| 301 | #define SND_MIXER_OSS_NOTIFY_DISCONNECT 1
|
| 302 | #define SND_MIXER_OSS_NOTIFY_FREE 2
|
| 303 | extern int (*snd_mixer_oss_notify_callback)(struct snd_card *card, int cmd);
|
| 304 | #endif
|
| 305 |
|
| 306 | int snd_card_new(struct device *parent, int idx, const char *xid,
|
| 307 | struct module *module, int extra_size,
|
| 308 | struct snd_card **card_ret);
|
| 309 | int snd_devm_card_new(struct device *parent, int idx, const char *xid,
|
| 310 | struct module *module, size_t extra_size,
|
| 311 | struct snd_card **card_ret);
|
| 312 |
|
| 313 | void snd_card_disconnect(struct snd_card *card);
|
| 314 | void snd_card_disconnect_sync(struct snd_card *card);
|
| 315 | void snd_card_free(struct snd_card *card);
|
| 316 | void snd_card_free_when_closed(struct snd_card *card);
|
| 317 | int snd_card_free_on_error(struct device *dev, int ret);
|
| 318 | void snd_card_set_id(struct snd_card *card, const char *id);
|
| 319 | int snd_card_register(struct snd_card *card);
|
| 320 | int snd_card_info_init(void);
|
| 321 | int snd_card_add_dev_attr(struct snd_card *card,
|
| 322 | const struct attribute_group *group);
|
| 323 | int snd_component_add(struct snd_card *card, const char *component);
|
| 324 | int snd_card_file_add(struct snd_card *card, struct file *file);
|
| 325 | int snd_card_file_remove(struct snd_card *card, struct file *file);
|
| 326 |
|
| 327 | struct snd_card *snd_card_ref(int card);
|
| 328 |
|
| 329 | |
| 330 | * snd_card_unref - Unreference the card object
|
| 331 | * @card: the card object to unreference
|
| 332 | *
|
| 333 | * Call this function for the card object that was obtained via snd_card_ref()
|
| 334 | * or snd_lookup_minor_data().
|
| 335 |
|
| 336 | static inline void snd_card_unref(struct snd_card *card)
|
| 337 | {
|
| 338 | put_device(&card->card_dev);
|
| 339 | }
|
| 340 |
|
| 341 | DEFINE_FREE(snd_card_unref, struct snd_card *, if (_T) snd_card_unref(_T))
|
| 342 |
|
| 343 | |
| 344 | * For automatic error handling at probe time, assign the card like:
|
| 345 | * struct snd_card *card __free(snd_card_free) = NULL;
|
| 346 | * then create and process as usual.
|
| 347 | * But, don't forget to clear to NULL at successful return for avoiding
|
| 348 | * the unexpected cleanup!
|
| 349 |
|
| 350 | DEFINE_FREE(snd_card_free, struct snd_card *, if (_T) snd_card_free(_T))
|
| 351 |
|
| 352 | #define snd_card_set_dev(card, devptr) ((card)->dev = (devptr))
|
| 353 |
|
| 354 |
|
| 355 |
|
| 356 | int snd_device_new(struct snd_card *card, enum snd_device_type type,
|
| 357 | void *device_data, const struct snd_device_ops *ops);
|
| 358 | int snd_device_register(struct snd_card *card, void *device_data);
|
| 359 | int snd_device_register_all(struct snd_card *card);
|
| 360 | void snd_device_disconnect(struct snd_card *card, void *device_data);
|
| 361 | void snd_device_disconnect_all(struct snd_card *card);
|
| 362 | void snd_device_free(struct snd_card *card, void *device_data);
|
| 363 | void snd_device_free_all(struct snd_card *card);
|
| 364 |
|
| 365 |
|
| 366 |
|
| 367 | #ifdef CONFIG_ISA_DMA_API
|
| 368 | #define DMA_MODE_NO_ENABLE 0x0100
|
| 369 |
|
| 370 | void snd_dma_program(unsigned long dma, unsigned long addr, unsigned int size, unsigned short mode);
|
| 371 | void snd_dma_disable(unsigned long dma);
|
| 372 | unsigned int snd_dma_pointer(unsigned long dma, unsigned int size);
|
| 373 | int snd_devm_request_dma(struct device *dev, int dma, const char *name);
|
| 374 | #endif
|
| 375 |
|
| 376 |
|
| 377 | struct resource;
|
| 378 | void release_and_free_resource(struct resource *res);
|
| 379 |
|
| 380 |
|
| 381 |
|
| 382 | #ifdef CONFIG_SND_DEBUG
|
| 383 | |
| 384 | * snd_BUG - give a BUG warning message and stack trace
|
| 385 | *
|
| 386 | * Calls WARN() if CONFIG_SND_DEBUG is set.
|
| 387 | * Ignored when CONFIG_SND_DEBUG is not set.
|
| 388 |
|
| 389 | #define snd_BUG() WARN(1, "BUG?\n")
|
| 390 |
|
| 391 | |
| 392 | * snd_BUG_ON - debugging check macro
|
| 393 | * @cond: condition to evaluate
|
| 394 | *
|
| 395 | * Has the same behavior as WARN_ON when CONFIG_SND_DEBUG is set,
|
| 396 | * otherwise just evaluates the conditional and returns the value.
|
| 397 |
|
| 398 | #define snd_BUG_ON(cond) WARN_ON((cond))
|
| 399 |
|
| 400 | #else
|
| 401 |
|
| 402 | #define snd_BUG() do { } while (0)
|
| 403 |
|
| 404 | #define snd_BUG_ON(condition) ({ \
|
| 405 | int __ret_warn_on = !!(condition); \
|
| 406 | unlikely(__ret_warn_on); \
|
| 407 | })
|
| 408 |
|
| 409 | #endif
|
| 410 |
|
| 411 | #define SNDRV_OSS_VERSION ((3<<16)|(8<<8)|(1<<4)|(0))
|
| 412 |
|
| 413 |
|
| 414 | #if IS_ENABLED(CONFIG_GAMEPORT)
|
| 415 | #define gameport_set_dev_parent(gp,xdev) ((gp)->dev.parent = (xdev))
|
| 416 | #define gameport_set_port_data(gp,r) ((gp)->port_data = (r))
|
| 417 | #define gameport_get_port_data(gp) (gp)->port_data
|
| 418 | #endif
|
| 419 |
|
| 420 |
|
| 421 | struct snd_pci_quirk {
|
| 422 | unsigned short subvendor;
|
| 423 | unsigned short subdevice;
|
| 424 | unsigned short subdevice_mask;
|
| 425 | int value;
|
| 426 | #ifdef CONFIG_SND_DEBUG_VERBOSE
|
| 427 | const char *name;
|
| 428 | #endif
|
| 429 | };
|
| 430 |
|
| 431 | #define _SND_PCI_QUIRK_ID_MASK(vend, mask, dev) \
|
| 432 | .subvendor = (vend), .subdevice = (dev), .subdevice_mask = (mask)
|
| 433 | #define _SND_PCI_QUIRK_ID(vend, dev) \
|
| 434 | _SND_PCI_QUIRK_ID_MASK(vend, 0xffff, dev)
|
| 435 | #define SND_PCI_QUIRK_ID(vend,dev) {_SND_PCI_QUIRK_ID(vend, dev)}
|
| 436 | #ifdef CONFIG_SND_DEBUG_VERBOSE
|
| 437 | #define SND_PCI_QUIRK(vend,dev,xname,val) \
|
| 438 | {_SND_PCI_QUIRK_ID(vend, dev), .value = (val), .name = (xname)}
|
| 439 | #define SND_PCI_QUIRK_VENDOR(vend, xname, val) \
|
| 440 | {_SND_PCI_QUIRK_ID_MASK(vend, 0, 0), .value = (val), .name = (xname)}
|
| 441 | #define SND_PCI_QUIRK_MASK(vend, mask, dev, xname, val) \
|
| 442 | {_SND_PCI_QUIRK_ID_MASK(vend, mask, dev), \
|
| 443 | .value = (val), .name = (xname)}
|
| 444 | #define snd_pci_quirk_name(q) ((q)->name)
|
| 445 | #else
|
| 446 | #define SND_PCI_QUIRK(vend,dev,xname,val) \
|
| 447 | {_SND_PCI_QUIRK_ID(vend, dev), .value = (val)}
|
| 448 | #define SND_PCI_QUIRK_MASK(vend, mask, dev, xname, val) \
|
| 449 | {_SND_PCI_QUIRK_ID_MASK(vend, mask, dev), .value = (val)}
|
| 450 | #define SND_PCI_QUIRK_VENDOR(vend, xname, val) \
|
| 451 | {_SND_PCI_QUIRK_ID_MASK(vend, 0, 0), .value = (val)}
|
| 452 | #define snd_pci_quirk_name(q) ""
|
| 453 | #endif
|
| 454 |
|
| 455 | #ifdef CONFIG_PCI
|
| 456 | const struct snd_pci_quirk *
|
| 457 | snd_pci_quirk_lookup(struct pci_dev *pci, const struct snd_pci_quirk *list);
|
| 458 |
|
| 459 | const struct snd_pci_quirk *
|
| 460 | snd_pci_quirk_lookup_id(u16 vendor, u16 device,
|
| 461 | const struct snd_pci_quirk *list);
|
| 462 | #else
|
| 463 | static inline const struct snd_pci_quirk *
|
| 464 | snd_pci_quirk_lookup(struct pci_dev *pci, const struct snd_pci_quirk *list)
|
| 465 | {
|
| 466 | return NULL;
|
| 467 | }
|
| 468 |
|
| 469 | static inline const struct snd_pci_quirk *
|
| 470 | snd_pci_quirk_lookup_id(u16 vendor, u16 device,
|
| 471 | const struct snd_pci_quirk *list)
|
| 472 | {
|
| 473 | return NULL;
|
| 474 | }
|
| 475 | #endif
|
| 476 |
|
| 477 |
|
| 478 | struct snd_fasync;
|
| 479 |
|
| 480 | int snd_fasync_helper(int fd, struct file *file, int on,
|
| 481 | struct snd_fasync **fasyncp);
|
| 482 | void snd_kill_fasync(struct snd_fasync *fasync, int signal, int poll);
|
| 483 | void snd_fasync_free(struct snd_fasync *fasync);
|
| 484 |
|
| 485 | #endif
|