diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-04-15 15:41:41 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-04-15 15:41:41 -0700 |
commit | d0a3997c0c3f9351e24029349dee65dd1d9e8d84 (patch) | |
tree | 7a04fe282b0c7b329cd87cdb891f0f3879dc71a6 /include | |
parent | 6d50ff91d9780263160262daeb6adfdda8ddbc6c (diff) | |
parent | d6eb9e3ec78c98324097bab8eea266c3bb0d0ac7 (diff) |
Merge tag 'sound-4.1-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound
Pull sound updates from Takashi Iwai:
"There have been major modernization with the standard bus: in ALSA
sequencer core and HD-audio. Also, HD-audio receives the regmap
support replacing the in-house cache register cache code. These
changes shouldn't impact the existing behavior, but rather
refactoring.
In addition, HD-audio got the code split to a core library part and
the "legacy" driver parts. This is a preliminary work for adapting
the upcoming ASoC HD-audio driver, and the whole transition is still
work in progress, likely finished in 4.1.
Along with them, there are many updates in ASoC area as usual, too:
lots of cleanups, Intel code shuffling, etc.
Here are some highlights:
ALSA core:
- PCM: the audio timestamp / wallclock enhancement
- PCM: fixes in DPCM management
- Fixes / cleanups of user-space control element management
- Sequencer: modernization using the standard bus
HD-audio:
- Modernization using the standard bus
- Regmap support
- Use standard runtime PM for codec power saving
- Widget-path based power-saving for IDT, VIA and Realtek codecs
- Reorganized sysfs entries for each codec object
- More Dell headset support
ASoC:
- Move of jack registration to the card level
- Lots of ASoC cleanups, mainly moving things from the CODEC level to
the card level
- Support for DAPM routes specified by both the machine driver and DT
- Continuing improvements to rcar
- pcm512x enhacements
- Intel platforms updates
- rt5670 updates / fixes
- New platforms / devices: some non-DSP Qualcomm platforms, Google's
Storm platform, Maxmim MAX98925 CODECs and the Ingenic JZ4780 SoC
Misc:
- ice1724: Improved ESI W192M support
- emu10k1: Emu 1010 fixes/enhancement"
* tag 'sound-4.1-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (411 commits)
ALSA: hda - set GET bit when adding a vendor verb to the codec regmap
ALSA: hda/realtek - Enable the ALC292 dock fixup on the Thinkpad T450
ALSA: hda - Fix another race in runtime PM refcounting
ALSA: hda - Expose codec type sysfs
ALSA: ctl: fix to handle several elements added by one operation for userspace element
ASoC: Intel: fix array_size.cocci warnings
ASoC: n810: Automatically disconnect non-connected pins
ASoC: n810: Consistently pass the card DAPM context to n810_ext_control()
ASoC: davinci-evm: Use card DAPM context to access widgets
ASoC: mop500_ab8500: Use card DAPM context to access widgets
ASoC: wm1133-ev1: Use card DAPM context to access widgets
ASoC: atmel: Improve machine driver compile test coverage
ASoC: atmel: Add dependency to SND_SOC_I2C_AND_SPI where necessary
ALSA: control: Fix a typo of SNDRV_CTL_ELEM_ACCESS_TLV_* with SNDRV_CTL_TLV_OP_*
ALSA: usb-audio: Don't attempt to get Microsoft Lifecam Cinema sample rate
ASoC: rnsd: fix build regression without CONFIG_OF
ALSA: emu10k1: add toggles for E-mu 1010 optical ports
ALSA: ctl: fill identical information to return value when adding userspace elements
ALSA: ctl: fix a bug to return no identical information in info operation for userspace controls
ALSA: ctl: confirm to return all identical information in 'activate' event
...
Diffstat (limited to 'include')
-rw-r--r-- | include/sound/ac97_codec.h | 4 | ||||
-rw-r--r-- | include/sound/compress_driver.h | 4 | ||||
-rw-r--r-- | include/sound/control.h | 2 | ||||
-rw-r--r-- | include/sound/core.h | 3 | ||||
-rw-r--r-- | include/sound/hda_regmap.h | 217 | ||||
-rw-r--r-- | include/sound/hdaudio.h | 247 | ||||
-rw-r--r-- | include/sound/pcm.h | 66 | ||||
-rw-r--r-- | include/sound/pcm_params.h | 7 | ||||
-rw-r--r-- | include/sound/rt5670.h | 1 | ||||
-rw-r--r-- | include/sound/seq_device.h | 46 | ||||
-rw-r--r-- | include/sound/seq_kernel.h | 6 | ||||
-rw-r--r-- | include/sound/simple_card.h | 1 | ||||
-rw-r--r-- | include/sound/soc-dapm.h | 6 | ||||
-rw-r--r-- | include/sound/soc-dpcm.h | 2 | ||||
-rw-r--r-- | include/sound/soc.h | 32 | ||||
-rw-r--r-- | include/uapi/sound/asequencer.h | 1 | ||||
-rw-r--r-- | include/uapi/sound/asound.h | 39 | ||||
-rw-r--r-- | include/uapi/sound/compress_offload.h | 2 | ||||
-rw-r--r-- | include/uapi/sound/emu10k1.h | 3 | ||||
-rw-r--r-- | include/uapi/sound/hdspm.h | 6 |
20 files changed, 649 insertions, 46 deletions
diff --git a/include/sound/ac97_codec.h b/include/sound/ac97_codec.h index d315a08d6c6d..0e9d75b49bed 100644 --- a/include/sound/ac97_codec.h +++ b/include/sound/ac97_codec.h @@ -608,7 +608,9 @@ struct ac97_quirk { int type; /* quirk type above */ }; -int snd_ac97_tune_hardware(struct snd_ac97 *ac97, struct ac97_quirk *quirk, const char *override); +int snd_ac97_tune_hardware(struct snd_ac97 *ac97, + const struct ac97_quirk *quirk, + const char *override); int snd_ac97_set_rate(struct snd_ac97 *ac97, int reg, unsigned int rate); /* diff --git a/include/sound/compress_driver.h b/include/sound/compress_driver.h index f48089d364c5..fa1d05512c09 100644 --- a/include/sound/compress_driver.h +++ b/include/sound/compress_driver.h @@ -70,7 +70,7 @@ struct snd_compr_runtime { * @device: device pointer * @direction: stream direction, playback/recording * @metadata_set: metadata set flag, true when set - * @next_track: has userspace signall next track transistion, true when set + * @next_track: has userspace signal next track transition, true when set * @private_data: pointer to DSP private data */ struct snd_compr_stream { @@ -95,7 +95,7 @@ struct snd_compr_stream { * and the stream properties * @get_params: retrieve the codec parameters, mandatory * @set_metadata: Set the metadata values for a stream - * @get_metadata: retreives the requested metadata values from stream + * @get_metadata: retrieves the requested metadata values from stream * @trigger: Trigger operations like start, pause, resume, drain, stop. * This callback is mandatory * @pointer: Retrieve current h/w pointer information. Mandatory diff --git a/include/sound/control.h b/include/sound/control.h index 75f3054023f7..95aad6d3fd1a 100644 --- a/include/sound/control.h +++ b/include/sound/control.h @@ -227,7 +227,7 @@ snd_ctl_add_slave(struct snd_kcontrol *master, struct snd_kcontrol *slave) * Add a virtual slave control to the given master. * Unlike snd_ctl_add_slave(), the element added via this function * is supposed to have volatile values, and get callback is called - * at each time quried from the master. + * at each time queried from the master. * * When the control peeks the hardware values directly and the value * can be changed by other means than the put callback of the element, diff --git a/include/sound/core.h b/include/sound/core.h index da5748289968..b12931f513f4 100644 --- a/include/sound/core.h +++ b/include/sound/core.h @@ -278,7 +278,8 @@ int snd_device_new(struct snd_card *card, enum snd_device_type type, void *device_data, struct snd_device_ops *ops); int snd_device_register(struct snd_card *card, void *device_data); int snd_device_register_all(struct snd_card *card); -int snd_device_disconnect_all(struct snd_card *card); +void snd_device_disconnect(struct snd_card *card, void *device_data); +void snd_device_disconnect_all(struct snd_card *card); void snd_device_free(struct snd_card *card, void *device_data); void snd_device_free_all(struct snd_card *card); diff --git a/include/sound/hda_regmap.h b/include/sound/hda_regmap.h new file mode 100644 index 000000000000..53a18b3635e2 --- /dev/null +++ b/include/sound/hda_regmap.h @@ -0,0 +1,217 @@ +/* + * HD-audio regmap helpers + */ + +#ifndef __SOUND_HDA_REGMAP_H +#define __SOUND_HDA_REGMAP_H + +#include <linux/regmap.h> +#include <sound/core.h> +#include <sound/hdaudio.h> + +int snd_hdac_regmap_init(struct hdac_device *codec); +void snd_hdac_regmap_exit(struct hdac_device *codec); +int snd_hdac_regmap_add_vendor_verb(struct hdac_device *codec, + unsigned int verb); +int snd_hdac_regmap_read_raw(struct hdac_device *codec, unsigned int reg, + unsigned int *val); +int snd_hdac_regmap_write_raw(struct hdac_device *codec, unsigned int reg, + unsigned int val); +int snd_hdac_regmap_update_raw(struct hdac_device *codec, unsigned int reg, + unsigned int mask, unsigned int val); + +/** + * snd_hdac_regmap_encode_verb - encode the verb to a pseudo register + * @nid: widget NID + * @verb: codec verb + * + * Returns an encoded pseudo register. + */ +#define snd_hdac_regmap_encode_verb(nid, verb) \ + (((verb) << 8) | 0x80000 | ((unsigned int)(nid) << 20)) + +/** + * snd_hdac_regmap_encode_amp - encode the AMP verb to a pseudo register + * @nid: widget NID + * @ch: channel (left = 0, right = 1) + * @dir: direction (#HDA_INPUT, #HDA_OUTPUT) + * @idx: input index value + * + * Returns an encoded pseudo register. + */ +#define snd_hdac_regmap_encode_amp(nid, ch, dir, idx) \ + (snd_hdac_regmap_encode_verb(nid, AC_VERB_GET_AMP_GAIN_MUTE) | \ + ((ch) ? AC_AMP_GET_RIGHT : AC_AMP_GET_LEFT) | \ + ((dir) == HDA_OUTPUT ? AC_AMP_GET_OUTPUT : AC_AMP_GET_INPUT) | \ + (idx)) + +/** + * snd_hdac_regmap_encode_amp_stereo - encode a pseudo register for stereo AMPs + * @nid: widget NID + * @dir: direction (#HDA_INPUT, #HDA_OUTPUT) + * @idx: input index value + * + * Returns an encoded pseudo register. + */ +#define snd_hdac_regmap_encode_amp_stereo(nid, dir, idx) \ + (snd_hdac_regmap_encode_verb(nid, AC_VERB_GET_AMP_GAIN_MUTE) | \ + AC_AMP_SET_LEFT | AC_AMP_SET_RIGHT | /* both bits set! */ \ + ((dir) == HDA_OUTPUT ? AC_AMP_GET_OUTPUT : AC_AMP_GET_INPUT) | \ + (idx)) + +/** + * snd_hdac_regmap_write - Write a verb with caching + * @nid: codec NID + * @reg: verb to write + * @val: value to write + * + * For writing an amp value, use snd_hda_regmap_amp_update(). + */ +static inline int +snd_hdac_regmap_write(struct hdac_device *codec, hda_nid_t nid, + unsigned int verb, unsigned int val) +{ + unsigned int cmd = snd_hdac_regmap_encode_verb(nid, verb); + + return snd_hdac_regmap_write_raw(codec, cmd, val); +} + +/** + * snd_hda_regmap_update - Update a verb value with caching + * @nid: codec NID + * @verb: verb to update + * @mask: bit mask to update + * @val: value to update + * + * For updating an amp value, use snd_hda_regmap_amp_update(). + */ +static inline int +snd_hdac_regmap_update(struct hdac_device *codec, hda_nid_t nid, + unsigned int verb, unsigned int mask, + unsigned int val) +{ + unsigned int cmd = snd_hdac_regmap_encode_verb(nid, verb); + + return snd_hdac_regmap_update_raw(codec, cmd, mask, val); +} + +/** + * snd_hda_regmap_read - Read a verb with caching + * @nid: codec NID + * @verb: verb to read + * @val: pointer to store the value + * + * For reading an amp value, use snd_hda_regmap_get_amp(). + */ +static inline int +snd_hdac_regmap_read(struct hdac_device *codec, hda_nid_t nid, + unsigned int verb, unsigned int *val) +{ + unsigned int cmd = snd_hdac_regmap_encode_verb(nid, verb); + + return snd_hdac_regmap_read_raw(codec, cmd, val); +} + +/** + * snd_hdac_regmap_get_amp - Read AMP value + * @codec: HD-audio codec + * @nid: NID to read the AMP value + * @ch: channel (left=0 or right=1) + * @direction: #HDA_INPUT or #HDA_OUTPUT + * @index: the index value (only for input direction) + * @val: the pointer to store the value + * + * Read AMP value. The volume is between 0 to 0x7f, 0x80 = mute bit. + * Returns the value or a negative error. + */ +static inline int +snd_hdac_regmap_get_amp(struct hdac_device *codec, hda_nid_t nid, + int ch, int dir, int idx) +{ + unsigned int cmd = snd_hdac_regmap_encode_amp(nid, ch, dir, idx); + int err, val; + + err = snd_hdac_regmap_read_raw(codec, cmd, &val); + return err < 0 ? err : val; +} + +/** + * snd_hdac_regmap_update_amp - update the AMP value + * @codec: HD-audio codec + * @nid: NID to read the AMP value + * @ch: channel (left=0 or right=1) + * @direction: #HDA_INPUT or #HDA_OUTPUT + * @idx: the index value (only for input direction) + * @mask: bit mask to set + * @val: the bits value to set + * + * Update the AMP value with a bit mask. + * Returns 0 if the value is unchanged, 1 if changed, or a negative error. + */ +static inline int +snd_hdac_regmap_update_amp(struct hdac_device *codec, hda_nid_t nid, + int ch, int dir, int idx, int mask, int val) +{ + unsigned int cmd = snd_hdac_regmap_encode_amp(nid, ch, dir, idx); + + return snd_hdac_regmap_update_raw(codec, cmd, mask, val); +} + +/** + * snd_hdac_regmap_get_amp_stereo - Read stereo AMP values + * @codec: HD-audio codec + * @nid: NID to read the AMP value + * @ch: channel (left=0 or right=1) + * @direction: #HDA_INPUT or #HDA_OUTPUT + * @index: the index value (only for input direction) + * @val: the pointer to store the value + * + * Read stereo AMP values. The lower byte is left, the upper byte is right. + * Returns the value or a negative error. + */ +static inline int +snd_hdac_regmap_get_amp_stereo(struct hdac_device *codec, hda_nid_t nid, + int dir, int idx) +{ + unsigned int cmd = snd_hdac_regmap_encode_amp_stereo(nid, dir, idx); + int err, val; + + err = snd_hdac_regmap_read_raw(codec, cmd, &val); + return err < 0 ? err : val; +} + +/** + * snd_hdac_regmap_update_amp_stereo - update the stereo AMP value + * @codec: HD-audio codec + * @nid: NID to read the AMP value + * @direction: #HDA_INPUT or #HDA_OUTPUT + * @idx: the index value (only for input direction) + * @mask: bit mask to set + * @val: the bits value to set + * + * Update the stereo AMP value with a bit mask. + * The lower byte is left, the upper byte is right. + * Returns 0 if the value is unchanged, 1 if changed, or a negative error. + */ +static inline int +snd_hdac_regmap_update_amp_stereo(struct hdac_device *codec, hda_nid_t nid, + int dir, int idx, int mask, int val) +{ + unsigned int cmd = snd_hdac_regmap_encode_amp_stereo(nid, dir, idx); + + return snd_hdac_regmap_update_raw(codec, cmd, mask, val); +} + +/** + * snd_hdac_regmap_sync_node - sync the widget node attributes + * @codec: HD-audio codec + * @nid: NID to sync + */ +static inline void +snd_hdac_regmap_sync_node(struct hdac_device *codec, hda_nid_t nid) +{ + regcache_mark_dirty(codec->regmap); + regcache_sync_region(codec->regmap, nid << 20, ((nid + 1) << 20) - 1); +} + +#endif /* __SOUND_HDA_REGMAP_H */ diff --git a/include/sound/hdaudio.h b/include/sound/hdaudio.h new file mode 100644 index 000000000000..2a8aa9dfb83d --- /dev/null +++ b/include/sound/hdaudio.h @@ -0,0 +1,247 @@ +/* + * HD-audio core stuff + */ + +#ifndef __SOUND_HDAUDIO_H +#define __SOUND_HDAUDIO_H + +#include <linux/device.h> +#include <sound/hda_verbs.h> + +/* codec node id */ +typedef u16 hda_nid_t; + +struct hdac_bus; +struct hdac_device; +struct hdac_driver; +struct hdac_widget_tree; + +/* + * exported bus type + */ +extern struct bus_type snd_hda_bus_type; + +/* + * generic arrays + */ +struct snd_array { + unsigned int used; + unsigned int alloced; + unsigned int elem_size; + unsigned int alloc_align; + void *list; +}; + +/* + * HD-audio codec base device + */ +struct hdac_device { + struct device dev; + int type; + struct hdac_bus *bus; + unsigned int addr; /* codec address */ + struct list_head list; /* list point for bus codec_list */ + + hda_nid_t afg; /* AFG node id */ + hda_nid_t mfg; /* MFG node id */ + + /* ids */ + unsigned int vendor_id; + unsigned int subsystem_id; + unsigned int revision_id; + unsigned int afg_function_id; + unsigned int mfg_function_id; + unsigned int afg_unsol:1; + unsigned int mfg_unsol:1; + + unsigned int power_caps; /* FG power caps */ + + const char *vendor_name; /* codec vendor name */ + const char *chip_name; /* codec chip name */ + + /* verb exec op override */ + int (*exec_verb)(struct hdac_device *dev, unsigned int cmd, + unsigned int flags, unsigned int *res); + + /* widgets */ + unsigned int num_nodes; + hda_nid_t start_nid, end_nid; + + /* misc flags */ + atomic_t in_pm; /* suspend/resume being performed */ + + /* sysfs */ + struct hdac_widget_tree *widgets; + + /* regmap */ + struct regmap *regmap; + struct snd_array vendor_verbs; + bool lazy_cache:1; /* don't wake up for writes */ + bool caps_overwriting:1; /* caps overwrite being in process */ + bool cache_coef:1; /* cache COEF read/write too */ +}; + +/* device/driver type used for matching */ +enum { + HDA_DEV_CORE, + HDA_DEV_LEGACY, +}; + +/* direction */ +enum { + HDA_INPUT, HDA_OUTPUT +}; + +#define dev_to_hdac_dev(_dev) container_of(_dev, struct hdac_device, dev) + +int snd_hdac_device_init(struct hdac_device *dev, struct hdac_bus *bus, + const char *name, unsigned int addr); +void snd_hdac_device_exit(struct hdac_device *dev); +int snd_hdac_device_register(struct hdac_device *codec); +void snd_hdac_device_unregister(struct hdac_device *codec); + +int snd_hdac_refresh_widgets(struct hdac_device *codec); + +unsigned int snd_hdac_make_cmd(struct hdac_device *codec, hda_nid_t nid, + unsigned int verb, unsigned int parm); +int snd_hdac_exec_verb(struct hdac_device *codec, unsigned int cmd, + unsigned int flags, unsigned int *res); +int snd_hdac_read(struct hdac_device *codec, hda_nid_t nid, + unsigned int verb, unsigned int parm, unsigned int *res); +int _snd_hdac_read_parm(struct hdac_device *codec, hda_nid_t nid, int parm, + unsigned int *res); +int snd_hdac_read_parm_uncached(struct hdac_device *codec, hda_nid_t nid, + int parm); +int snd_hdac_override_parm(struct hdac_device *codec, hda_nid_t nid, + unsigned int parm, unsigned int val); +int snd_hdac_get_connections(struct hdac_device *codec, hda_nid_t nid, + hda_nid_t *conn_list, int max_conns); +int snd_hdac_get_sub_nodes(struct hdac_device *codec, hda_nid_t nid, + hda_nid_t *start_id); + +/** + * snd_hdac_read_parm - read a codec parameter + * @codec: the codec object + * @nid: NID to read a parameter + * @parm: parameter to read + * + * Returns -1 for error. If you need to distinguish the error more + * strictly, use _snd_hdac_read_parm() directly. + */ +static inline int snd_hdac_read_parm(struct hdac_device *codec, hda_nid_t nid, + int parm) +{ + unsigned int val; + + return _snd_hdac_read_parm(codec, nid, parm, &val) < 0 ? -1 : val; +} + +#ifdef CONFIG_PM +void snd_hdac_power_up(struct hdac_device *codec); +void snd_hdac_power_down(struct hdac_device *codec); +void snd_hdac_power_up_pm(struct hdac_device *codec); +void snd_hdac_power_down_pm(struct hdac_device *codec); +#else +static inline void snd_hdac_power_up(struct hdac_device *codec) {} +static inline void snd_hdac_power_down(struct hdac_device *codec) {} +static inline void snd_hdac_power_up_pm(struct hdac_device *codec) {} +static inline void snd_hdac_power_down_pm(struct hdac_device *codec) {} +#endif + +/* + * HD-audio codec base driver + */ +struct hdac_driver { + struct device_driver driver; + int type; + int (*match)(struct hdac_device *dev, struct hdac_driver *drv); + void (*unsol_event)(struct hdac_device *dev, unsigned int event); +}; + +#define drv_to_hdac_driver(_drv) container_of(_drv, struct hdac_driver, driver) + +/* + * HD-audio bus base driver + */ +struct hdac_bus_ops { + /* send a single command */ + int (*command)(struct hdac_bus *bus, unsigned int cmd); + /* get a response from the last command */ + int (*get_response)(struct hdac_bus *bus, unsigned int addr, + unsigned int *res); +}; + +#define HDA_UNSOL_QUEUE_SIZE 64 + +struct hdac_bus { + struct device *dev; + const struct hdac_bus_ops *ops; + + /* codec linked list */ + struct list_head codec_list; + unsigned int num_codecs; + + /* link caddr -> codec */ + struct hdac_device *caddr_tbl[HDA_MAX_CODEC_ADDRESS + 1]; + + /* unsolicited event queue */ + u32 unsol_queue[HDA_UNSOL_QUEUE_SIZE * 2]; /* ring buffer */ + unsigned int unsol_rp, unsol_wp; + struct work_struct unsol_work; + + /* bit flags of powered codecs */ + unsigned long codec_powered; + + /* flags */ + bool sync_write:1; /* sync after verb write */ + + /* locks */ + struct mutex cmd_mutex; +}; + +int snd_hdac_bus_init(struct hdac_bus *bus, struct device *dev, + const struct hdac_bus_ops *ops); +void snd_hdac_bus_exit(struct hdac_bus *bus); +int snd_hdac_bus_exec_verb(struct hdac_bus *bus, unsigned int addr, + unsigned int cmd, unsigned int *res); +int snd_hdac_bus_exec_verb_unlocked(struct hdac_bus *bus, unsigned int addr, + unsigned int cmd, unsigned int *res); +void snd_hdac_bus_queue_event(struct hdac_bus *bus, u32 res, u32 res_ex); + +int snd_hdac_bus_add_device(struct hdac_bus *bus, struct hdac_device *codec); +void snd_hdac_bus_remove_device(struct hdac_bus *bus, + struct hdac_device *codec); + +static inline void snd_hdac_codec_link_up(struct hdac_device *codec) +{ + set_bit(codec->addr, &codec->bus->codec_powered); +} + +static inline void snd_hdac_codec_link_down(struct hdac_device *codec) +{ + clear_bit(codec->addr, &codec->bus->codec_powered); +} + +/* + * generic array helpers + */ +void *snd_array_new(struct snd_array *array); +void snd_array_free(struct snd_array *array); +static inline void snd_array_init(struct snd_array *array, unsigned int size, + unsigned int align) +{ + array->elem_size = size; + array->alloc_align = align; +} + +static inline void *snd_array_elem(struct snd_array *array, unsigned int idx) +{ + return array->list + idx * array->elem_size; +} + +static inline unsigned int snd_array_index(struct snd_array *array, void *ptr) +{ + return (unsigned long)(ptr - array->list) / array->elem_size; +} + +#endif /* __SOUND_HDAUDIO_H */ diff --git a/include/sound/pcm.h b/include/sound/pcm.h index c0ddb7e69c28..0cb7f3f5df7b 100644 --- a/include/sound/pcm.h +++ b/include/sound/pcm.h @@ -60,6 +60,9 @@ struct snd_pcm_hardware { struct snd_pcm_substream; +struct snd_pcm_audio_tstamp_config; /* definitions further down */ +struct snd_pcm_audio_tstamp_report; + struct snd_pcm_ops { int (*open)(struct snd_pcm_substream *substream); int (*close)(struct snd_pcm_substream *substream); @@ -71,8 +74,10 @@ struct snd_pcm_ops { int (*prepare)(struct snd_pcm_substream *substream); int (*trigger)(struct snd_pcm_substream *substream, int cmd); snd_pcm_uframes_t (*pointer)(struct snd_pcm_substream *substream); - int (*wall_clock)(struct snd_pcm_substream *substream, - struct timespec *audio_ts); + int (*get_time_info)(struct snd_pcm_substream *substream, + struct timespec *system_ts, struct timespec *audio_ts, + struct snd_pcm_audio_tstamp_config *audio_tstamp_config, + struct snd_pcm_audio_tstamp_report *audio_tstamp_report); int (*copy)(struct snd_pcm_substream *substream, int channel, snd_pcm_uframes_t pos, void __user *buf, snd_pcm_uframes_t count); @@ -281,6 +286,58 @@ struct snd_pcm_hw_constraint_ranges { struct snd_pcm_hwptr_log; +/* + * userspace-provided audio timestamp config to kernel, + * structure is for internal use only and filled with dedicated unpack routine + */ +struct snd_pcm_audio_tstamp_config { + /* 5 of max 16 bits used */ + u32 type_requested:4; + u32 report_delay:1; /* add total delay to A/D or D/A */ +}; + +static inline void snd_pcm_unpack_audio_tstamp_config(__u32 data, + struct snd_pcm_audio_tstamp_config *config) +{ + config->type_requested = data & 0xF; + config->report_delay = (data >> 4) & 1; +} + +/* + * kernel-provided audio timestamp report to user-space + * structure is for internal use only and read by dedicated pack routine + */ +struct snd_pcm_audio_tstamp_report { + /* 6 of max 16 bits used for bit-fields */ + + /* for backwards compatibility */ + u32 valid:1; + + /* actual type if hardware could not support requested timestamp */ + u32 actual_type:4; + + /* accuracy represented in ns units */ + u32 accuracy_report:1; /* 0 if accuracy unknown, 1 if accuracy field is valid */ + u32 accuracy; /* up to 4.29s, will be packed in separate field */ +}; + +static inline void snd_pcm_pack_audio_tstamp_report(__u32 *data, __u32 *accuracy, + const struct snd_pcm_audio_tstamp_report *report) +{ + u32 tmp; + + tmp = report->accuracy_report; + tmp <<= 4; + tmp |= report->actual_type; + tmp <<= 1; + tmp |= report->valid; + + *data &= 0xffff; /* zero-clear MSBs */ + *data |= (tmp << 16); + *accuracy = report->accuracy; +} + + struct snd_pcm_runtime { /* -- Status -- */ struct snd_pcm_substream *trigger_master; @@ -361,6 +418,11 @@ struct snd_pcm_runtime { struct snd_dma_buffer *dma_buffer_p; /* allocated buffer */ + /* -- audio timestamp config -- */ + struct snd_pcm_audio_tstamp_config audio_tstamp_config; + struct snd_pcm_audio_tstamp_report audio_tstamp_report; + struct timespec driver_tstamp; + #if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE) /* -- OSS things -- */ struct snd_pcm_oss_runtime oss; diff --git a/include/sound/pcm_params.h b/include/sound/pcm_params.h index 3c45f3924ba7..c704357775fc 100644 --- a/include/sound/pcm_params.h +++ b/include/sound/pcm_params.h @@ -366,4 +366,11 @@ static inline int params_physical_width(const struct snd_pcm_hw_params *p) return snd_pcm_format_physical_width(params_format(p)); } +static inline void +params_set_format(struct snd_pcm_hw_params *p, snd_pcm_format_t fmt) +{ + snd_mask_set(hw_param_mask(p, SNDRV_PCM_HW_PARAM_FORMAT), + (__force int)fmt); +} + #endif /* __SOUND_PCM_PARAMS_H */ diff --git a/include/sound/rt5670.h b/include/sound/rt5670.h index bd311197a3b5..b7d60510819b 100644 --- a/include/sound/rt5670.h +++ b/include/sound/rt5670.h @@ -14,6 +14,7 @@ struct rt5670_platform_data { int jd_mode; bool in2_diff; + bool dev_gpio; bool dmic_en; unsigned int dmic1_data_pin; diff --git a/include/sound/seq_device.h b/include/sound/seq_device.h index 2b5f24cc7548..ddc0d504cf39 100644 --- a/include/sound/seq_device.h +++ b/include/sound/seq_device.h @@ -25,29 +25,26 @@ * registered device information */ -#define ID_LEN 32 - -/* status flag */ -#define SNDRV_SEQ_DEVICE_FREE 0 -#define SNDRV_SEQ_DEVICE_REGISTERED 1 - struct snd_seq_device { /* device info */ struct snd_card *card; /* sound card */ int device; /* device number */ - char id[ID_LEN]; /* driver id */ + const char *id; /* driver id */ char name[80]; /* device name */ int argsize; /* size of the argument */ void *driver_data; /* private data for driver */ - int status; /* flag - read only */ void *private_data; /* private data for the caller */ void (*private_free)(struct snd_seq_device *device); - struct list_head list; /* link to next device */ + struct device dev; }; +#define to_seq_dev(_dev) \ + container_of(_dev, struct snd_seq_device, dev) + +/* sequencer driver */ /* driver operators - * init_device: + * probe: * Initialize the device with given parameters. * Typically, * 1. call snd_hwdep_new @@ -55,25 +52,40 @@ struct snd_seq_device { * 3. call snd_hwdep_register * 4. store the instance to dev->driver_data pointer. * - * free_device: + * remove: * Release the private data. * Typically, call snd_device_free(dev->card, dev->driver_data) */ -struct snd_seq_dev_ops { - int (*init_device)(struct snd_seq_device *dev); - int (*free_device)(struct snd_seq_device *dev); +struct snd_seq_driver { + struct device_driver driver; + char *id; + int argsize; }; +#define to_seq_drv(_drv) \ + container_of(_drv, struct snd_seq_driver, driver) + /* * prototypes */ +#ifdef CONFIG_MODULES void snd_seq_device_load_drivers(void); -int snd_seq_device_new(struct snd_card *card, int device, char *id, int argsize, struct snd_seq_device **result); -int snd_seq_device_register_driver(char *id, struct snd_seq_dev_ops *entry, int argsize); -int snd_seq_device_unregister_driver(char *id); +#else +#define snd_seq_device_load_drivers() +#endif +int snd_seq_device_new(struct snd_card *card, int device, const char *id, + int argsize, struct snd_seq_device **result); #define SNDRV_SEQ_DEVICE_ARGPTR(dev) (void *)((char *)(dev) + sizeof(struct snd_seq_device)) +int __must_check __snd_seq_driver_register(struct snd_seq_driver *drv, + struct module *mod); +#define snd_seq_driver_register(drv) \ + __snd_seq_driver_register(drv, THIS_MODULE) +void snd_seq_driver_unregister(struct snd_seq_driver *drv); + +#define module_snd_seq_driver(drv) \ + module_driver(drv, snd_seq_driver_register, snd_seq_driver_unregister) /* * id strings for generic devices diff --git a/include/sound/seq_kernel.h b/include/sound/seq_kernel.h index 18a2ac58b88f..feb58d455560 100644 --- a/include/sound/seq_kernel.h +++ b/include/sound/seq_kernel.h @@ -99,13 +99,9 @@ int snd_seq_event_port_attach(int client, struct snd_seq_port_callback *pcbp, int snd_seq_event_port_detach(int client, int port); #ifdef CONFIG_MODULES -void snd_seq_autoload_lock(void); -void snd_seq_autoload_unlock(void); void snd_seq_autoload_init(void); -#define snd_seq_autoload_exit() snd_seq_autoload_lock() +void snd_seq_autoload_exit(void); #else -#define snd_seq_autoload_lock() -#define snd_seq_autoload_unlock() #define snd_seq_autoload_init() #define snd_seq_autoload_exit() #endif diff --git a/include/sound/simple_card.h b/include/sound/simple_card.h index 1255ddb1d3e2..b9b4f289fe6b 100644 --- a/include/sound/simple_card.h +++ b/include/sound/simple_card.h @@ -16,7 +16,6 @@ struct asoc_simple_dai { const char *name; - unsigned int fmt; unsigned int sysclk; int slots; int slot_width; diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h index 8d7416e46861..0bc83647d3fa 100644 --- a/include/sound/soc-dapm.h +++ b/include/sound/soc-dapm.h @@ -378,6 +378,7 @@ int snd_soc_dapm_link_dai_widgets(struct snd_soc_card *card); void snd_soc_dapm_connect_dai_link_widgets(struct snd_soc_card *card); int snd_soc_dapm_new_pcm(struct snd_soc_card *card, const struct snd_soc_pcm_stream *params, + unsigned int num_params, struct snd_soc_dapm_widget *source, struct snd_soc_dapm_widget *sink); @@ -440,7 +441,6 @@ void dapm_mark_endpoints_dirty(struct snd_soc_card *card); int snd_soc_dapm_dai_get_connected_widgets(struct snd_soc_dai *dai, int stream, struct snd_soc_dapm_widget_list **list); -struct snd_soc_codec *snd_soc_dapm_kcontrol_codec(struct snd_kcontrol *kcontrol); struct snd_soc_dapm_context *snd_soc_dapm_kcontrol_dapm( struct snd_kcontrol *kcontrol); @@ -531,6 +531,8 @@ struct snd_soc_dapm_widget { void *priv; /* widget specific data */ struct regulator *regulator; /* attached regulator */ const struct snd_soc_pcm_stream *params; /* params for dai links */ + unsigned int num_params; /* number of params for dai links */ + unsigned int params_select; /* currently selected param for dai link */ /* dapm control */ int reg; /* negative reg = no direct dapm */ @@ -586,8 +588,6 @@ struct snd_soc_dapm_update { /* DAPM context */ struct snd_soc_dapm_context { enum snd_soc_bias_level bias_level; - enum snd_soc_bias_level suspend_bias_level; - struct delayed_work delayed_work; unsigned int idle_bias_off:1; /* Use BIAS_OFF instead of STANDBY */ /* Go to BIAS_OFF in suspend if the DAPM context is idle */ unsigned int suspend_bias_off:1; diff --git a/include/sound/soc-dpcm.h b/include/sound/soc-dpcm.h index 98f2ade0266e..806059052bfc 100644 --- a/include/sound/soc-dpcm.h +++ b/include/sound/soc-dpcm.h @@ -135,7 +135,7 @@ void snd_soc_dpcm_be_set_state(struct snd_soc_pcm_runtime *be, int stream, /* internal use only */ int soc_dpcm_be_digital_mute(struct snd_soc_pcm_runtime *fe, int mute); -int soc_dpcm_debugfs_add(struct snd_soc_pcm_runtime *rtd); +void soc_dpcm_debugfs_add(struct snd_soc_pcm_runtime *rtd); int soc_dpcm_runtime_update(struct snd_soc_card *); int dpcm_path_get(struct snd_soc_pcm_runtime *fe, diff --git a/include/sound/soc.h b/include/sound/soc.h index 0d1ade195628..fcb312b3f258 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -450,8 +450,10 @@ int soc_dai_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *dai); /* Jack reporting */ -int snd_soc_jack_new(struct snd_soc_codec *codec, const char *id, int type, - struct snd_soc_jack *jack); +int snd_soc_card_jack_new(struct snd_soc_card *card, const char *id, int type, + struct snd_soc_jack *jack, struct snd_soc_jack_pin *pins, + unsigned int num_pins); + void snd_soc_jack_report(struct snd_soc_jack *jack, int status, int mask); int snd_soc_jack_add_pins(struct snd_soc_jack *jack, int count, struct snd_soc_jack_pin *pins); @@ -659,7 +661,7 @@ struct snd_soc_jack_gpio { struct snd_soc_jack { struct mutex mutex; struct snd_jack *jack; - struct snd_soc_codec *codec; + struct snd_soc_card *card; struct list_head pins; int status; struct blocking_notifier_head notifier; @@ -941,6 +943,7 @@ struct snd_soc_dai_link { int be_id; /* optional ID for machine driver BE identification */ const struct snd_soc_pcm_stream *params; + unsigned int num_params; unsigned int dai_fmt; /* format to set on init */ @@ -954,6 +957,9 @@ struct snd_soc_dai_link { unsigned int symmetric_channels:1; unsigned int symmetric_samplebits:1; + /* Mark this pcm with non atomic ops */ + bool nonatomic; + /* Do not create a PCM for this DAI link (Backend link) */ unsigned int no_pcm:1; @@ -1071,11 +1077,16 @@ struct snd_soc_card { /* * Card-specific routes and widgets. + * Note: of_dapm_xxx for Device Tree; Otherwise for driver build-in. */ const struct snd_soc_dapm_widget *dapm_widgets; int num_dapm_widgets; const struct snd_soc_dapm_route *dapm_routes; int num_dapm_routes; + const struct snd_soc_dapm_widget *of_dapm_widgets; + int num_of_dapm_widgets; + const struct snd_soc_dapm_route *of_dapm_routes; + int num_of_dapm_routes; bool fully_routed; struct work_struct deferred_resume_work; @@ -1258,6 +1269,19 @@ static inline struct snd_soc_dapm_context *snd_soc_component_get_dapm( return component->dapm_ptr; } +/** + * snd_soc_dapm_kcontrol_codec() - Returns the codec associated to a kcontrol + * @kcontrol: The kcontrol + * + * This function must only be used on DAPM contexts that are known to be part of + * a CODEC (e.g. in a CODEC driver). Otherwise the behavior is undefined. + */ +static inline struct snd_soc_codec *snd_soc_dapm_kcontrol_codec( + struct snd_kcontrol *kcontrol) +{ + return snd_soc_dapm_to_codec(snd_soc_dapm_kcontrol_dapm(kcontrol)); +} + /* codec IO */ unsigned int snd_soc_read(struct snd_soc_codec *codec, unsigned int reg); int snd_soc_write(struct snd_soc_codec *codec, unsigned int reg, @@ -1469,7 +1493,7 @@ static inline struct snd_soc_codec *snd_soc_kcontrol_codec( } /** - * snd_soc_kcontrol_platform() - Returns the platform that registerd the control + * snd_soc_kcontrol_platform() - Returns the platform that registered the control * @kcontrol: The control for which to get the platform * * Note: This function will only work correctly if the control has been diff --git a/include/uapi/sound/asequencer.h b/include/uapi/sound/asequencer.h index 09c8a00ea503..5a5fa4956ebd 100644 --- a/include/uapi/sound/asequencer.h +++ b/include/uapi/sound/asequencer.h @@ -22,6 +22,7 @@ #ifndef _UAPI__SOUND_ASEQUENCER_H #define _UAPI__SOUND_ASEQUENCER_H +#include <sound/asound.h> /** version of the sequencer */ #define SNDRV_SEQ_VERSION SNDRV_PROTOCOL_VERSION (1, 0, 1) diff --git a/include/uapi/sound/asound.h b/include/uapi/sound/asound.h index 0e88e7a0f0eb..46145a5277fe 100644 --- a/include/uapi/sound/asound.h +++ b/include/uapi/sound/asound.h @@ -25,6 +25,9 @@ #include <linux/types.h> +#ifndef __KERNEL__ +#include <stdlib.h> +#endif /* * protocol version @@ -140,7 +143,7 @@ struct snd_hwdep_dsp_image { * * *****************************************************************************/ -#define SNDRV_PCM_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 12) +#define SNDRV_PCM_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 13) typedef unsigned long snd_pcm_uframes_t; typedef signed long snd_pcm_sframes_t; @@ -267,10 +270,17 @@ typedef int __bitwise snd_pcm_subformat_t; #define SNDRV_PCM_INFO_JOINT_DUPLEX 0x00200000 /* playback and capture stream are somewhat correlated */ #define SNDRV_PCM_INFO_SYNC_START 0x00400000 /* pcm support some kind of sync go */ #define SNDRV_PCM_INFO_NO_PERIOD_WAKEUP 0x00800000 /* period wakeup can be disabled */ -#define SNDRV_PCM_INFO_HAS_WALL_CLOCK 0x01000000 /* has audio wall clock for audio/system time sync */ +#define SNDRV_PCM_INFO_HAS_WALL_CLOCK 0x01000000 /* (Deprecated)has audio wall clock for audio/system time sync */ +#define SNDRV_PCM_INFO_HAS_LINK_ATIME 0x01000000 /* report hardware link audio time, reset on startup */ +#define SNDRV_PCM_INFO_HAS_LINK_ABSOLUTE_ATIME 0x02000000 /* report absolute hardware link audio time, not reset on startup */ +#define SNDRV_PCM_INFO_HAS_LINK_ESTIMATED_ATIME 0x04000000 /* report estimated link audio time */ +#define SNDRV_PCM_INFO_HAS_LINK_SYNCHRONIZED_ATIME 0x08000000 /* report synchronized audio/system time */ + #define SNDRV_PCM_INFO_DRAIN_TRIGGER 0x40000000 /* internal kernel flag - trigger in drain */ #define SNDRV_PCM_INFO_FIFO_IN_FRAMES 0x80000000 /* internal kernel flag - FIFO size is in frames */ + + typedef int __bitwise snd_pcm_state_t; #define SNDRV_PCM_STATE_OPEN ((__force snd_pcm_state_t) 0) /* stream is open */ #define SNDRV_PCM_STATE_SETUP ((__force snd_pcm_state_t) 1) /* stream has a setup */ @@ -408,6 +418,22 @@ struct snd_pcm_channel_info { unsigned int step; /* samples distance in bits */ }; +enum { + /* + * first definition for backwards compatibility only, + * maps to wallclock/link time for HDAudio playback and DEFAULT/DMA time for everything else + */ + SNDRV_PCM_AUDIO_TSTAMP_TYPE_COMPAT = 0, + + /* timestamp definitions */ + SNDRV_PCM_AUDIO_TSTAMP_TYPE_DEFAULT = 1, /* DMA time, reported as per hw_ptr */ + SNDRV_PCM_AUDIO_TSTAMP_TYPE_LINK = 2, /* link time reported by sample or wallclock counter, reset on startup */ + SNDRV_PCM_AUDIO_TSTAMP_TYPE_LINK_ABSOLUTE = 3, /* link time reported by sample or wallclock counter, not reset on startup */ + SNDRV_PCM_AUDIO_TSTAMP_TYPE_LINK_ESTIMATED = 4, /* link time estimated indirectly */ + SNDRV_PCM_AUDIO_TSTAMP_TYPE_LINK_SYNCHRONIZED = 5, /* link time synchronized with system time */ + SNDRV_PCM_AUDIO_TSTAMP_TYPE_LAST = SNDRV_PCM_AUDIO_TSTAMP_TYPE_LINK_SYNCHRONIZED +}; + struct snd_pcm_status { snd_pcm_state_t state; /* stream state */ struct timespec trigger_tstamp; /* time when stream was started/stopped/paused */ @@ -419,9 +445,11 @@ struct snd_pcm_status { snd_pcm_uframes_t avail_max; /* max frames available on hw since last status */ snd_pcm_uframes_t overrange; /* count of ADC (capture) overrange detections from last status */ snd_pcm_state_t suspended_state; /* suspended stream state */ - __u32 reserved_alignment; /* must be filled with zero */ - struct timespec audio_tstamp; /* from sample counter or wall clock */ - unsigned char reserved[56-sizeof(struct timespec)]; /* must be filled with zero */ + __u32 audio_tstamp_data; /* needed for 64-bit alignment, used for configs/report to/from userspace */ + struct timespec audio_tstamp; /* sample counter, wall clock, PHC or on-demand sync'ed */ + struct timespec driver_tstamp; /* useful in case reference system tstamp is reported with delay */ + __u32 audio_tstamp_accuracy; /* in ns units, only valid if indicated in audio_tstamp_data */ + unsigned char reserved[52-2*sizeof(struct timespec)]; /* must be filled with zero */ }; struct snd_pcm_mmap_status { @@ -534,6 +562,7 @@ enum { #define SNDRV_PCM_IOCTL_DELAY _IOR('A', 0x21, snd_pcm_sframes_t) #define SNDRV_PCM_IOCTL_HWSYNC _IO('A', 0x22) #define SNDRV_PCM_IOCTL_SYNC_PTR _IOWR('A', 0x23, struct snd_pcm_sync_ptr) +#define SNDRV_PCM_IOCTL_STATUS_EXT _IOWR('A', 0x24, struct snd_pcm_status) #define SNDRV_PCM_IOCTL_CHANNEL_INFO _IOR('A', 0x32, struct snd_pcm_channel_info) #define SNDRV_PCM_IOCTL_PREPARE _IO('A', 0x40) #define SNDRV_PCM_IOCTL_RESET _IO('A', 0x41) diff --git a/include/uapi/sound/compress_offload.h b/include/uapi/sound/compress_offload.h index 22ed8cb7800b..e00d8cbfc628 100644 --- a/include/uapi/sound/compress_offload.h +++ b/include/uapi/sound/compress_offload.h @@ -75,7 +75,7 @@ struct snd_compr_tstamp { /** * struct snd_compr_avail - avail descriptor * @avail: Number of bytes available in ring buffer for writing/reading - * @tstamp: timestamp infomation + * @tstamp: timestamp information */ struct snd_compr_avail { __u64 avail; diff --git a/include/uapi/sound/emu10k1.h b/include/uapi/sound/emu10k1.h index d1bbaf78457a..ec1535bb6aed 100644 --- a/include/uapi/sound/emu10k1.h +++ b/include/uapi/sound/emu10k1.h @@ -23,8 +23,7 @@ #define _UAPI__SOUND_EMU10K1_H #include <linux/types.h> - - +#include <sound/asound.h> /* * ---- FX8010 ---- diff --git a/include/uapi/sound/hdspm.h b/include/uapi/sound/hdspm.h index b357f1a5e29c..5737332d38f2 100644 --- a/include/uapi/sound/hdspm.h +++ b/include/uapi/sound/hdspm.h @@ -20,6 +20,12 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#ifdef __KERNEL__ +#include <linux/types.h> +#else +#include <stdint.h> +#endif + /* Maximum channels is 64 even on 56Mode you have 64playbacks to matrix */ #define HDSPM_MAX_CHANNELS 64 |