diff options
author | Takashi Iwai <tiwai@suse.de> | 2015-06-08 20:47:53 +0200 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2015-06-08 20:47:53 +0200 |
commit | 8ffc57093bb1c270050f4229b5afd38ee8cef2bd (patch) | |
tree | ba78b568b446b9c119385ef17a0fa5d5d0724be2 /include/sound | |
parent | 83b0b677f90a2056a53f1930881bbee2741b048f (diff) | |
parent | 11e688862c4c8162119a4ca51c3326555966c8bb (diff) |
Merge tag 'asoc-v4.2' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound into for-next
ASoC: Updates for v4.2
The big thing this release has been Liam's addition of topology support
to the core. We've also seen quite a bit of driver work and the
continuation of Lars' refactoring for component support.
- Support for loading ASoC topology maps from firmware, intended to be
used to allow self-describing DSP firmware images to be built which
can map controls added by the DSP to userspace without the kernel
needing to know about individual DSP firmwares.
- Lots of refactoring to avoid direct access to snd_soc_codec where
it's not needed supporting future refactoring.
- Big refactoring and cleanup serieses for the Wolfson ADSP and TI
TAS2552 drivers.
- Support for TI TAS571x power amplifiers.
- Support for Qualcomm APQ8016 and ZTE ZX296702 SoCs.
- Support for x86 systems with RT5650 and Qualcomm Storm.
Diffstat (limited to 'include/sound')
-rw-r--r-- | include/sound/dmaengine_pcm.h | 5 | ||||
-rw-r--r-- | include/sound/rt5645.h | 3 | ||||
-rw-r--r-- | include/sound/soc-dapm.h | 49 | ||||
-rw-r--r-- | include/sound/soc-topology.h | 168 | ||||
-rw-r--r-- | include/sound/soc.h | 118 | ||||
-rw-r--r-- | include/sound/tlv.h | 15 |
6 files changed, 315 insertions, 43 deletions
diff --git a/include/sound/dmaengine_pcm.h b/include/sound/dmaengine_pcm.h index eb73a3a39ec2..f86ef5ea9b01 100644 --- a/include/sound/dmaengine_pcm.h +++ b/include/sound/dmaengine_pcm.h @@ -91,11 +91,6 @@ void snd_dmaengine_pcm_set_config_from_dai_data( */ #define SND_DMAENGINE_PCM_FLAG_NO_DT BIT(1) /* - * The platforms dmaengine driver does not support reporting the amount of - * bytes that are still left to transfer. - */ -#define SND_DMAENGINE_PCM_FLAG_NO_RESIDUE BIT(2) -/* * The PCM is half duplex and the DMA channel is shared between capture and * playback. */ diff --git a/include/sound/rt5645.h b/include/sound/rt5645.h index 120d9610054e..652cb9e4afe5 100644 --- a/include/sound/rt5645.h +++ b/include/sound/rt5645.h @@ -15,7 +15,6 @@ struct rt5645_platform_data { /* IN2 can optionally be differential */ bool in2_diff; - bool dmic_en; unsigned int dmic1_data_pin; /* 0 = IN2N; 1 = GPIO5; 2 = GPIO11 */ unsigned int dmic2_data_pin; @@ -24,8 +23,6 @@ struct rt5645_platform_data { unsigned int hp_det_gpio; bool gpio_hp_det_active_high; - /* true if codec's jd function is used */ - bool en_jd_func; unsigned int jd_mode; }; diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h index 1065095c6973..37d95a898275 100644 --- a/include/sound/soc-dapm.h +++ b/include/sound/soc-dapm.h @@ -15,6 +15,8 @@ #include <linux/types.h> #include <sound/control.h> +#include <sound/soc-topology.h> +#include <sound/asoc.h> struct device; @@ -107,6 +109,10 @@ struct device; { .id = snd_soc_dapm_mux, .name = wname, \ SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \ .kcontrol_news = wcontrols, .num_kcontrols = 1} +#define SND_SOC_DAPM_DEMUX(wname, wreg, wshift, winvert, wcontrols) \ +{ .id = snd_soc_dapm_demux, .name = wname, \ + SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \ + .kcontrol_news = wcontrols, .num_kcontrols = 1} /* Simplified versions of above macros, assuming wncontrols = ARRAY_SIZE(wcontrols) */ #define SOC_PGA_ARRAY(wname, wreg, wshift, winvert,\ @@ -444,11 +450,15 @@ int snd_soc_dapm_dai_get_connected_widgets(struct snd_soc_dai *dai, int stream, struct snd_soc_dapm_context *snd_soc_dapm_kcontrol_dapm( struct snd_kcontrol *kcontrol); +int snd_soc_dapm_force_bias_level(struct snd_soc_dapm_context *dapm, + enum snd_soc_bias_level level); + /* dapm widget types */ enum snd_soc_dapm_type { snd_soc_dapm_input = 0, /* input pin */ snd_soc_dapm_output, /* output pin */ snd_soc_dapm_mux, /* selects 1 analog signal from many inputs */ + snd_soc_dapm_demux, /* connects the input to one of multiple outputs */ snd_soc_dapm_mixer, /* mixes several analog signals together */ snd_soc_dapm_mixer_named_ctl, /* mixer with named controls */ snd_soc_dapm_pga, /* programmable gain/attenuation (volume) */ @@ -563,6 +573,7 @@ struct snd_soc_dapm_widget { int num_kcontrols; const struct snd_kcontrol_new *kcontrol_news; struct snd_kcontrol **kcontrols; + struct snd_soc_dobj dobj; /* widget input and outputs */ struct list_head sources; @@ -585,6 +596,10 @@ struct snd_soc_dapm_update { int val; }; +struct snd_soc_dapm_wcache { + struct snd_soc_dapm_widget *widget; +}; + /* DAPM context */ struct snd_soc_dapm_context { enum snd_soc_bias_level bias_level; @@ -606,6 +621,9 @@ struct snd_soc_dapm_context { int (*set_bias_level)(struct snd_soc_dapm_context *dapm, enum snd_soc_bias_level level); + struct snd_soc_dapm_wcache path_sink_cache; + struct snd_soc_dapm_wcache path_source_cache; + #ifdef CONFIG_DEBUG_FS struct dentry *debugfs_dapm; #endif @@ -623,4 +641,35 @@ struct snd_soc_dapm_stats { int neighbour_checks; }; +/** + * snd_soc_dapm_init_bias_level() - Initialize DAPM bias level + * @dapm: The DAPM context to initialize + * @level: The DAPM level to initialize to + * + * This function only sets the driver internal state of the DAPM level and will + * not modify the state of the device. Hence it should not be used during normal + * operation, but only to synchronize the internal state to the device state. + * E.g. during driver probe to set the DAPM level to the one corresponding with + * the power-on reset state of the device. + * + * To change the DAPM state of the device use snd_soc_dapm_set_bias_level(). + */ +static inline void snd_soc_dapm_init_bias_level( + struct snd_soc_dapm_context *dapm, enum snd_soc_bias_level level) +{ + dapm->bias_level = level; +} + +/** + * snd_soc_dapm_get_bias_level() - Get current DAPM bias level + * @dapm: The context for which to get the bias level + * + * Returns: The current bias level of the passed DAPM context. + */ +static inline enum snd_soc_bias_level snd_soc_dapm_get_bias_level( + struct snd_soc_dapm_context *dapm) +{ + return dapm->bias_level; +} + #endif diff --git a/include/sound/soc-topology.h b/include/sound/soc-topology.h new file mode 100644 index 000000000000..865a141b118b --- /dev/null +++ b/include/sound/soc-topology.h @@ -0,0 +1,168 @@ +/* + * linux/sound/soc-topology.h -- ALSA SoC Firmware Controls and DAPM + * + * Copyright (C) 2012 Texas Instruments Inc. + * Copyright (C) 2015 Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Simple file API to load FW that includes mixers, coefficients, DAPM graphs, + * algorithms, equalisers, DAIs, widgets, FE caps, BE caps, codec link caps etc. + */ + +#ifndef __LINUX_SND_SOC_TPLG_H +#define __LINUX_SND_SOC_TPLG_H + +#include <sound/asoc.h> +#include <linux/list.h> + +struct firmware; +struct snd_kcontrol; +struct snd_soc_tplg_pcm_be; +struct snd_ctl_elem_value; +struct snd_ctl_elem_info; +struct snd_soc_dapm_widget; +struct snd_soc_component; +struct snd_soc_tplg_pcm_fe; +struct snd_soc_dapm_context; +struct snd_soc_card; + +/* object scan be loaded and unloaded in groups with identfying indexes */ +#define SND_SOC_TPLG_INDEX_ALL 0 /* ID that matches all FW objects */ + +/* dynamic object type */ +enum snd_soc_dobj_type { + SND_SOC_DOBJ_NONE = 0, /* object is not dynamic */ + SND_SOC_DOBJ_MIXER, + SND_SOC_DOBJ_ENUM, + SND_SOC_DOBJ_BYTES, + SND_SOC_DOBJ_PCM, + SND_SOC_DOBJ_DAI_LINK, + SND_SOC_DOBJ_CODEC_LINK, + SND_SOC_DOBJ_WIDGET, +}; + +/* dynamic control object */ +struct snd_soc_dobj_control { + struct snd_kcontrol *kcontrol; + char **dtexts; + unsigned long *dvalues; +}; + +/* dynamic widget object */ +struct snd_soc_dobj_widget { + unsigned int kcontrol_enum:1; /* this widget is an enum kcontrol */ +}; + +/* dynamic PCM DAI object */ +struct snd_soc_dobj_pcm_dai { + struct snd_soc_tplg_pcm_dai *pd; + unsigned int count; +}; + +/* generic dynamic object - all dynamic objects belong to this struct */ +struct snd_soc_dobj { + enum snd_soc_dobj_type type; + unsigned int index; /* objects can belong in different groups */ + struct list_head list; + struct snd_soc_tplg_ops *ops; + union { + struct snd_soc_dobj_control control; + struct snd_soc_dobj_widget widget; + struct snd_soc_dobj_pcm_dai pcm_dai; + }; + void *private; /* core does not touch this */ +}; + +/* + * Kcontrol operations - used to map handlers onto firmware based controls. + */ +struct snd_soc_tplg_kcontrol_ops { + u32 id; + int (*get)(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol); + int (*put)(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol); + int (*info)(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo); +}; + +/* + * DAPM widget event handlers - used to map handlers onto widgets. + */ +struct snd_soc_tplg_widget_events { + u16 type; + int (*event_handler)(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *k, int event); +}; + +/* + * Public API - Used by component drivers to load and unload dynamic objects + * and their resources. + */ +struct snd_soc_tplg_ops { + + /* external kcontrol init - used for any driver specific init */ + int (*control_load)(struct snd_soc_component *, + struct snd_kcontrol_new *, struct snd_soc_tplg_ctl_hdr *); + int (*control_unload)(struct snd_soc_component *, + struct snd_soc_dobj *); + + /* external widget init - used for any driver specific init */ + int (*widget_load)(struct snd_soc_component *, + struct snd_soc_dapm_widget *, + struct snd_soc_tplg_dapm_widget *); + int (*widget_unload)(struct snd_soc_component *, + struct snd_soc_dobj *); + + /* FE - used for any driver specific init */ + int (*pcm_dai_load)(struct snd_soc_component *, + struct snd_soc_tplg_pcm_dai *pcm_dai, int num_fe); + int (*pcm_dai_unload)(struct snd_soc_component *, + struct snd_soc_dobj *); + + /* callback to handle vendor bespoke data */ + int (*vendor_load)(struct snd_soc_component *, + struct snd_soc_tplg_hdr *); + int (*vendor_unload)(struct snd_soc_component *, + struct snd_soc_tplg_hdr *); + + /* completion - called at completion of firmware loading */ + void (*complete)(struct snd_soc_component *); + + /* manifest - optional to inform component of manifest */ + int (*manifest)(struct snd_soc_component *, + struct snd_soc_tplg_manifest *); + + /* bespoke kcontrol handlers available for binding */ + const struct snd_soc_tplg_kcontrol_ops *io_ops; + int io_ops_count; +}; + +/* gets a pointer to data from the firmware block header */ +static inline const void *snd_soc_tplg_get_data(struct snd_soc_tplg_hdr *hdr) +{ + const void *ptr = hdr; + + return ptr + sizeof(*hdr); +} + +/* Dynamic Object loading and removal for component drivers */ +int snd_soc_tplg_component_load(struct snd_soc_component *comp, + struct snd_soc_tplg_ops *ops, const struct firmware *fw, + u32 index); +int snd_soc_tplg_component_remove(struct snd_soc_component *comp, u32 index); + +/* Widget removal - widgets also removed wth component API */ +void snd_soc_tplg_widget_remove(struct snd_soc_dapm_widget *w); +void snd_soc_tplg_widget_remove_all(struct snd_soc_dapm_context *dapm, + u32 index); + +/* Binds event handlers to dynamic widgets */ +int snd_soc_tplg_widget_bind_event(struct snd_soc_dapm_widget *w, + const struct snd_soc_tplg_widget_events *events, int num_events, + u16 event_type); + +#endif diff --git a/include/sound/soc.h b/include/sound/soc.h index f6226914acfe..93df8bf9d54a 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -27,6 +27,7 @@ #include <sound/compress_driver.h> #include <sound/control.h> #include <sound/ac97_codec.h> +#include <sound/soc-topology.h> /* * Convenience kcontrol builders @@ -190,8 +191,12 @@ #define SOC_VALUE_ENUM_DOUBLE(xreg, xshift_l, xshift_r, xmask, xitems, xtexts, xvalues) \ { .reg = xreg, .shift_l = xshift_l, .shift_r = xshift_r, \ .mask = xmask, .items = xitems, .texts = xtexts, .values = xvalues} -#define SOC_VALUE_ENUM_SINGLE(xreg, xshift, xmask, xnitmes, xtexts, xvalues) \ - SOC_VALUE_ENUM_DOUBLE(xreg, xshift, xshift, xmask, xnitmes, xtexts, xvalues) +#define SOC_VALUE_ENUM_SINGLE(xreg, xshift, xmask, xitems, xtexts, xvalues) \ + SOC_VALUE_ENUM_DOUBLE(xreg, xshift, xshift, xmask, xitems, xtexts, xvalues) +#define SOC_VALUE_ENUM_SINGLE_AUTODISABLE(xreg, xshift, xmask, xitems, xtexts, xvalues) \ +{ .reg = xreg, .shift_l = xshift, .shift_r = xshift, \ + .mask = xmask, .items = xitems, .texts = xtexts, \ + .values = xvalues, .autodisable = 1} #define SOC_ENUM_SINGLE_VIRT(xitems, xtexts) \ SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, xitems, xtexts) #define SOC_ENUM(xname, xenum) \ @@ -312,6 +317,11 @@ ARRAY_SIZE(xtexts), xtexts, xvalues) #define SOC_VALUE_ENUM_SINGLE_DECL(name, xreg, xshift, xmask, xtexts, xvalues) \ SOC_VALUE_ENUM_DOUBLE_DECL(name, xreg, xshift, xshift, xmask, xtexts, xvalues) + +#define SOC_VALUE_ENUM_SINGLE_AUTODISABLE_DECL(name, xreg, xshift, xmask, xtexts, xvalues) \ + const struct soc_enum name = SOC_VALUE_ENUM_SINGLE_AUTODISABLE(xreg, \ + xshift, xmask, ARRAY_SIZE(xtexts), xtexts, xvalues) + #define SOC_ENUM_SINGLE_VIRT_DECL(name, xtexts) \ const struct soc_enum name = SOC_ENUM_SINGLE_VIRT(ARRAY_SIZE(xtexts), xtexts) @@ -767,6 +777,9 @@ struct snd_soc_component { struct mutex io_mutex; + /* attached dynamic objects */ + struct list_head dobj_list; + #ifdef CONFIG_DEBUG_FS struct dentry *debugfs_root; #endif @@ -819,7 +832,7 @@ struct snd_soc_codec { /* component */ struct snd_soc_component component; - /* dapm */ + /* Don't access this directly, use snd_soc_codec_get_dapm() */ struct snd_soc_dapm_context dapm; #ifdef CONFIG_DEBUG_FS @@ -961,6 +974,24 @@ struct snd_soc_dai_link { enum snd_soc_dpcm_trigger trigger[2]; /* trigger type for DPCM */ + /* codec/machine specific init - e.g. add machine controls */ + int (*init)(struct snd_soc_pcm_runtime *rtd); + + /* optional hw_params re-writing for BE and FE sync */ + int (*be_hw_params_fixup)(struct snd_soc_pcm_runtime *rtd, + struct snd_pcm_hw_params *params); + + /* machine stream operations */ + const struct snd_soc_ops *ops; + const struct snd_soc_compr_ops *compr_ops; + + /* For unidirectional dai links */ + bool playback_only; + bool capture_only; + + /* Mark this pcm with non atomic ops */ + bool nonatomic; + /* Keep DAI active over suspend */ unsigned int ignore_suspend:1; @@ -969,9 +1000,6 @@ 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; @@ -982,23 +1010,11 @@ struct snd_soc_dai_link { unsigned int dpcm_capture:1; unsigned int dpcm_playback:1; + /* DPCM used FE & BE merged format */ + unsigned int dpcm_merged_format:1; + /* pmdown_time is ignored at stop */ unsigned int ignore_pmdown_time:1; - - /* codec/machine specific init - e.g. add machine controls */ - int (*init)(struct snd_soc_pcm_runtime *rtd); - - /* optional hw_params re-writing for BE and FE sync */ - int (*be_hw_params_fixup)(struct snd_soc_pcm_runtime *rtd, - struct snd_pcm_hw_params *params); - - /* machine stream operations */ - const struct snd_soc_ops *ops; - const struct snd_soc_compr_ops *compr_ops; - - /* For unidirectional dai links */ - bool playback_only; - bool capture_only; }; struct snd_soc_codec_conf { @@ -1111,6 +1127,9 @@ struct snd_soc_card { struct list_head dapm_list; struct list_head dapm_dirty; + /* attached dynamic objects */ + struct list_head dobj_list; + /* Generic DAPM context for the card */ struct snd_soc_dapm_context dapm; struct snd_soc_dapm_stats dapm_stats; @@ -1170,6 +1189,7 @@ struct soc_mixer_control { unsigned int sign_bit; unsigned int invert:1; unsigned int autodisable:1; + struct snd_soc_dobj dobj; }; struct soc_bytes { @@ -1180,6 +1200,8 @@ struct soc_bytes { struct soc_bytes_ext { int max; + struct snd_soc_dobj dobj; + /* used for TLV byte control */ int (*get)(unsigned int __user *bytes, unsigned int size); int (*put)(const unsigned int __user *bytes, unsigned int size); @@ -1200,6 +1222,8 @@ struct soc_enum { unsigned int mask; const char * const *texts; const unsigned int *values; + unsigned int autodisable:1; + struct snd_soc_dobj dobj; }; /** @@ -1282,6 +1306,58 @@ static inline struct snd_soc_dapm_context *snd_soc_component_get_dapm( } /** + * snd_soc_codec_get_dapm() - Returns the DAPM context for the CODEC + * @codec: The CODEC for which to get the DAPM context + * + * Note: Use this function instead of directly accessing the CODEC's dapm field + */ +static inline struct snd_soc_dapm_context *snd_soc_codec_get_dapm( + struct snd_soc_codec *codec) +{ + return &codec->dapm; +} + +/** + * snd_soc_dapm_init_bias_level() - Initialize CODEC DAPM bias level + * @dapm: The CODEC for which to initialize the DAPM bias level + * @level: The DAPM level to initialize to + * + * Initializes the CODEC DAPM bias level. See snd_soc_dapm_init_bias_level(). + */ +static inline void snd_soc_codec_init_bias_level(struct snd_soc_codec *codec, + enum snd_soc_bias_level level) +{ + snd_soc_dapm_init_bias_level(snd_soc_codec_get_dapm(codec), level); +} + +/** + * snd_soc_dapm_get_bias_level() - Get current CODEC DAPM bias level + * @codec: The CODEC for which to get the DAPM bias level + * + * Returns: The current DAPM bias level of the CODEC. + */ +static inline enum snd_soc_bias_level snd_soc_codec_get_bias_level( + struct snd_soc_codec *codec) +{ + return snd_soc_dapm_get_bias_level(snd_soc_codec_get_dapm(codec)); +} + +/** + * snd_soc_codec_force_bias_level() - Set the CODEC DAPM bias level + * @codec: The CODEC for which to set the level + * @level: The level to set to + * + * Forces the CODEC bias level to a specific state. See + * snd_soc_dapm_force_bias_level(). + */ +static inline int snd_soc_codec_force_bias_level(struct snd_soc_codec *codec, + enum snd_soc_bias_level level) +{ + return snd_soc_dapm_force_bias_level(snd_soc_codec_get_dapm(codec), + level); +} + +/** * snd_soc_dapm_kcontrol_codec() - Returns the codec associated to a kcontrol * @kcontrol: The kcontrol * diff --git a/include/sound/tlv.h b/include/sound/tlv.h index e11e179420a1..df97d1966468 100644 --- a/include/sound/tlv.h +++ b/include/sound/tlv.h @@ -31,12 +31,7 @@ * ~(sizeof(unsigned int) - 1)) .... */ -#define SNDRV_CTL_TLVT_CONTAINER 0 /* one level down - group of TLVs */ -#define SNDRV_CTL_TLVT_DB_SCALE 1 /* dB scale */ -#define SNDRV_CTL_TLVT_DB_LINEAR 2 /* linear volume */ -#define SNDRV_CTL_TLVT_DB_RANGE 3 /* dB range container */ -#define SNDRV_CTL_TLVT_DB_MINMAX 4 /* dB scale with min/max */ -#define SNDRV_CTL_TLVT_DB_MINMAX_MUTE 5 /* dB scale with min/max with mute */ +#include <uapi/sound/tlv.h> #define TLV_ITEM(type, ...) \ (type), TLV_LENGTH(__VA_ARGS__), __VA_ARGS__ @@ -90,12 +85,4 @@ #define TLV_DB_GAIN_MUTE -9999999 -/* - * channel-mapping TLV items - * TLV length must match with num_channels - */ -#define SNDRV_CTL_TLVT_CHMAP_FIXED 0x101 /* fixed channel position */ -#define SNDRV_CTL_TLVT_CHMAP_VAR 0x102 /* channels freely swappable */ -#define SNDRV_CTL_TLVT_CHMAP_PAIRED 0x103 /* pair-wise swappable */ - #endif /* __SOUND_TLV_H */ |