From acde50a7bf1fd6ae0baa4402f0a02c4b1bd4c990 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 27 Apr 2015 12:44:25 +0200 Subject: ASoC: dmaengine_pcm: Make FLAG_NO_RESIDUE internal Whether residue can be reported or not is not a property of the audio controller but of the DMA controller. The FLAG_NO_RESIDUE was initially added when the DMAengine framework had no support for describing the residue reporting capabilities of the controller. Support for this was added quite a while ago and recently the DMAengine framework started to complain if a driver does not describe its capabilities and a lot of patches have been merged that add support for this where it was missing. So it should be safe to assume that driver on actively used platforms properly implement the DMA capabilities API. This patch makes the FLAG_NO_RESIDUE internal and no longer allows audio controller drivers to manually set the flag. If a DMA driver against expectations does not support reporting its capabilities for now the generic DMAengine PCM driver will now emit a warning and simply assume that residue reporting is not supported. In the future this might be changed to aborting with an error. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- include/sound/dmaengine_pcm.h | 5 ----- 1 file changed, 5 deletions(-) (limited to 'include/sound') 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 @@ -90,11 +90,6 @@ void snd_dmaengine_pcm_set_config_from_dai_data( * makes sense if SND_DMAENGINE_PCM_FLAG_COMPAT is set as well. */ #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. -- cgit v1.2.1 From 2dc0f16b83b43fd1f86a2358d46f46488230c6c8 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 21 Apr 2015 07:02:34 +0000 Subject: ASoC: soc.h: tidyup struct snd_soc_dai_link definition order Current struct snd_soc_dai_link has many members, but definition order was random. Especially, bool / bit field are defined randomly. This patch tidyups these definition order to calculate data alignment easy. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- include/sound/soc.h | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) (limited to 'include/sound') diff --git a/include/sound/soc.h b/include/sound/soc.h index fcb312b3f258..38757fe7a3d8 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -949,6 +949,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; @@ -957,9 +975,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; @@ -972,21 +987,6 @@ struct snd_soc_dai_link { /* 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 { -- cgit v1.2.1 From 39ed68c8cd3aff417603a95d0594308598b9f469 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 27 Apr 2015 22:13:22 +0200 Subject: ASoC: Add helper function getting CODEC's DAPM context The DAPM context in the snd_soc_codec struct is redundant and scheduled to be replaced by the DAPM context in the snd_soc_component struct. This patch introduces a new helper function snd_soc_codec_get_dapm() which should be used for getting the DAPM context for a CODEC rather then directly accessing the dapm field. Once there are no more direct users of the dapm field left it is possible to transparently switch all drivers to the component DAPM context by updating snd_soc_codec_get_dapm() function. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- include/sound/soc.h | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'include/sound') diff --git a/include/sound/soc.h b/include/sound/soc.h index fcb312b3f258..2f742009da4b 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -807,7 +807,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 @@ -1269,6 +1269,18 @@ static inline struct snd_soc_dapm_context *snd_soc_component_get_dapm( return component->dapm_ptr; } +/** + * 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_kcontrol_codec() - Returns the codec associated to a kcontrol * @kcontrol: The kcontrol -- cgit v1.2.1 From fa880775ab0d5a8d540972f7b6800fad1af16b75 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 27 Apr 2015 22:13:23 +0200 Subject: ASoC: Add helper functions bias level management Currently drivers are responsible for managing the bias_level field of their DAPM context. The DAPM state itself is managed by the DAPM core though and the core has certain expectations on how and when the bias_level field should be updated. If drivers don't adhere to these undefined behavior can occur. This patch adds a few helper functions for manipulating the DAPM context state, each function with a description on when it should be used and what its effects are. This will also help us to move more of the bias_level management from drivers to the DAPM core. For convenience also add snd_soc_codec_* wrappers around these helpers. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- include/sound/soc-dapm.h | 34 ++++++++++++++++++++++++++++++++++ include/sound/soc.h | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+) (limited to 'include/sound') diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h index 0bc83647d3fa..70216d20e897 100644 --- a/include/sound/soc-dapm.h +++ b/include/sound/soc-dapm.h @@ -444,6 +444,9 @@ 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 */ @@ -623,4 +626,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.h b/include/sound/soc.h index 2f742009da4b..7781bfe85c5d 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -1281,6 +1281,46 @@ static inline struct snd_soc_dapm_context *snd_soc_codec_get_dapm( 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 -- cgit v1.2.1 From 5967cb3d87802908fe5ab96aa0b417606bf4ca3b Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Fri, 1 May 2015 12:37:23 +0100 Subject: ASoC: Correct typo in SOC_VALUE_ENUM_SINGLE macro xnitmes is clearly intended to be xnitems, but all other macros just refer to this as xitems, so change it to that. Signed-off-by: Charles Keepax Reviewed-by: Lars-Peter Clausen Tested-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- include/sound/soc.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'include/sound') diff --git a/include/sound/soc.h b/include/sound/soc.h index 7781bfe85c5d..b257a09a98d1 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -190,8 +190,8 @@ #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_ENUM_SINGLE_VIRT(xitems, xtexts) \ SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, xitems, xtexts) #define SOC_ENUM(xname, xenum) \ -- cgit v1.2.1 From 561ed680b764b288feeb74a24e1d9fb3da98ec7b Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Fri, 1 May 2015 12:37:26 +0100 Subject: ASoC: dapm: Add support for autodisable mux controls Commit 57295073b6ac ("ASoC: dapm: Implement mixer input auto-disable") added support for autodisable controls, controls whose values are only written to the hardware when their respective widgets are powered up. But it only added support for controls based on the mixer abstraction. This patch add support for mux controls (DAPM controls based on the enum abstraction) to be auto-disabled as well. As each mux can only have a single control, there is no need to tie the autodisable widget to the inputs (as is done for the mixer controls) it can be tided directly to the mux widget itself. Note that it is assumed that the first entry in a autodisable mux control will always represent the off state for the mux and is what the mux will be set to whilst it is disabled. Signed-off-by: Charles Keepax Reviewed-by: Lars-Peter Clausen Tested-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- include/sound/soc.h | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'include/sound') diff --git a/include/sound/soc.h b/include/sound/soc.h index b257a09a98d1..2f2e59e1513e 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -192,6 +192,10 @@ .mask = xmask, .items = xitems, .texts = xtexts, .values = 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 +316,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) @@ -1188,6 +1197,7 @@ struct soc_enum { unsigned int mask; const char * const *texts; const unsigned int *values; + unsigned int autodisable:1; }; /** -- cgit v1.2.1 From d714f97c5b8c4c5da56b89a7289acb3f12ef7abb Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 1 May 2015 18:02:43 +0200 Subject: ASoC: dapm: Add demux support A demux is conceptually similar to a mux. Where a mux has multiple input and one output and selects one of the inputs to be connected to the output, the demux has one input and multiple outputs and selects one of the outputs to which the input gets connected. This similarity makes it straight forward to support them in DAPM using the existing mux support, we only need to swap sinks and sources when initially setting up the paths. The only slightly tricky part is that there can only be one control per path. Since mixers/muxes are at the sink of a path and a demux is at the source and both types want a control it is not possible to directly connect a demux output to a mixer/mux input. The patch adds some sanity checks to make sure that this does not happen. Drivers who want to model hardware which directly connects a demux output to a mixer/mux input can do this by inserting a dummy widget between the two. E.g.: { "Dummy", "Demux Control", "Demux" }, { "Mixer", "Mixer Control", "Dummy" }, Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- include/sound/soc-dapm.h | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'include/sound') diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h index 70216d20e897..96c5e0ec81d1 100644 --- a/include/sound/soc-dapm.h +++ b/include/sound/soc-dapm.h @@ -107,6 +107,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,\ @@ -452,6 +456,7 @@ 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) */ -- cgit v1.2.1 From ac4fc3eeb79e06499779db99937522526e863ab6 Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Tue, 5 May 2015 21:42:01 +0800 Subject: ASoC: rt5645: remove unused field in pdata We can know if dmic is used by reading the value of dmic1_data_pin and dmic2_data_pin. Also IRQ must be used if codec JD or button detection function is used. So, dmic_en and en_jd_func can be remove from platform data. Signed-off-by: Bard Liao Signed-off-by: Mark Brown --- include/sound/rt5645.h | 3 --- 1 file changed, 3 deletions(-) (limited to 'include/sound') 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; }; -- cgit v1.2.1 From 45a110a1377d9f7afbbf53e351b72cf813ac426e Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Mon, 11 May 2015 13:50:30 +0100 Subject: ASoC: dapm: Add cache to speed up adding of routes Some CODECs have a significant number of DAPM routes and for each route, when it is added to the card, the entire card widget list must be searched. When adding routes it is very likely, however, that adjacent routes will require adjacent widgets. For example all the routes for a mux are likely added in a block and the sink widget will be the same each time and it is also quite likely that the source widgets are sequential located in the widget list. This patch adds a cache to the DAPM context, this cache will hold the source and sink widgets from the last call to snd_soc_dapm_add_route for that context. A small search of the widget list will be made from those points for both the sink and source. Currently this search only checks both the last widget and the one adjacent to it. On wm8280 which has approximately 500 widgets and 30000 routes (one of the largest CODECs in mainline), the number of paths that hit the cache is 24000, which significantly improves probe time. Signed-off-by: Charles Keepax Signed-off-by: Mark Brown --- include/sound/soc-dapm.h | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'include/sound') diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h index 96c5e0ec81d1..b9170e2bc5ab 100644 --- a/include/sound/soc-dapm.h +++ b/include/sound/soc-dapm.h @@ -593,6 +593,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; @@ -614,6 +618,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 -- cgit v1.2.1 From b073ed4e21268da59c40a4fc5d56e3af808ecc4d Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 12 May 2015 02:03:33 +0000 Subject: ASoC: soc-pcm: DPCM cares BE format Current DPCM is caring only FE format. but it will be no sound if FE/BE was below style, and user selects S24_LE format. FE: S16_LE/S24_LE BE: S16_LE DPCM can rewrite the format, so basically we don't want to constrain with the BE constraints. But sometimes it will be trouble. This patch adds new .dpcm_merged_format on struct snd_soc_dai_link. DPCM will use FE / BE merged format if .struct snd_soc_dai_link has it. We can have other .dpcm_merged_xxx in the future .dpcm_merged_foramt .dpcm_merged_rate .dpcm_merged_chan Signed-off-by: Kuninori Morimoto Tested-by: Keita Kobayashi Signed-off-by: Mark Brown --- include/sound/soc.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'include/sound') diff --git a/include/sound/soc.h b/include/sound/soc.h index 38757fe7a3d8..cf63ac1c8968 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -985,6 +985,9 @@ 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; }; -- cgit v1.2.1 From c147c0e17b532a0d35ab92c86bbce0dfe1c1aaf4 Mon Sep 17 00:00:00 2001 From: Liam Girdwood Date: Fri, 29 May 2015 19:06:13 +0100 Subject: ASoC: topology: Add topology UAPI header The ASoC topology UAPI header defines the structures required to define any DSP firmware audio topology and control objects from userspace. The following objects are supported :- o kcontrols including TLV controls. o DAPM widgets and graph elements o Vendor bespoke objects. o Coefficient data o FE PCM capabilities and config. o BE link capabilities and config. o Codec <-> codec link capabilities and config. o Topology object manifest. The file format is simple and divided into blocks for each object type and each block has a header that defines it's size and type. Blocks can be in any order of type and can either all be in a single file or spread across more than one file. Blocks also have a group identifier ID so that they can be loaded and unloaded by ID. Signed-off-by: Liam Girdwood Signed-off-by: Mark Brown --- include/sound/soc-dapm.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include/sound') diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h index b9170e2bc5ab..0dd6070e73cb 100644 --- a/include/sound/soc-dapm.h +++ b/include/sound/soc-dapm.h @@ -15,6 +15,7 @@ #include #include +#include struct device; -- cgit v1.2.1 From 8a9782346dccd82cf912552735bda619de4efd8c Mon Sep 17 00:00:00 2001 From: Liam Girdwood Date: Fri, 29 May 2015 19:06:14 +0100 Subject: ASoC: topology: Add topology core The topology core parses the FW topology file for known block types and instanciates any common ALSA/ASoC objects that it discovers. The core also passes any block that is does not understand to client component drivers for enumeration. The core exports some APIs to client drivers in order to load and unload firmware topology data as use case require. Currently the core deals with the following object types :- o kcontrols. This includes TLV, enumerated and bytes controls. o DAPM widgets. All types with any associated kcontrol. o DAPM graph. o FE PCM. FE PCM capabilities and configuration can be defined. o BE DAI Link. BE DAI link capabilities and configuration can be defined. o Codec <-> codec style links capabilities and configuration. Signed-off-by: Liam Girdwood Signed-off-by: Mark Brown --- include/sound/soc-dapm.h | 2 + include/sound/soc-topology.h | 168 +++++++++++++++++++++++++++++++++++++++++++ include/sound/soc.h | 11 +++ 3 files changed, 181 insertions(+) create mode 100644 include/sound/soc-topology.h (limited to 'include/sound') diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h index 0dd6070e73cb..24a71d5d2d37 100644 --- a/include/sound/soc-dapm.h +++ b/include/sound/soc-dapm.h @@ -15,6 +15,7 @@ #include #include +#include #include struct device; @@ -572,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; 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 +#include + +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 2f2e59e1513e..bfd84a7edfa5 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -27,6 +27,7 @@ #include #include #include +#include /* * Convenience kcontrol builders @@ -764,6 +765,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 @@ -1108,6 +1112,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; @@ -1167,6 +1174,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 { @@ -1177,6 +1185,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); @@ -1198,6 +1208,7 @@ struct soc_enum { const char * const *texts; const unsigned int *values; unsigned int autodisable:1; + struct snd_soc_dobj dobj; }; /** -- cgit v1.2.1 From 932ae8809469770a07ce19d6967d2ce303befa08 Mon Sep 17 00:00:00 2001 From: Liam Girdwood Date: Fri, 29 May 2015 19:06:15 +0100 Subject: ALSA: topology: Export ID types for TLV controls. Make sure userspace can define TLV controls for topology using the correct type numbers and channel mappings. Signed-off-by: Liam Girdwood Acked-by: Takashi Iwai Signed-off-by: Mark Brown --- include/sound/tlv.h | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) (limited to 'include/sound') 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 #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 */ -- cgit v1.2.1