diff options
author | Mark Brown <broonie@linaro.org> | 2014-04-08 21:22:08 +0100 |
---|---|---|
committer | Mark Brown <broonie@linaro.org> | 2014-04-08 21:22:08 +0100 |
commit | 30b58f22ccb02d316030ece8e3f6cf369244fb25 (patch) | |
tree | dafd057e7bf4941a32cfdb8f70a9361087a30a7d /include/sound/soc.h | |
parent | 455c6fdbd219161bd09b1165f11699d6d73de11c (diff) | |
parent | deeed33850c8a376addabbf971df433b2a1ba74c (diff) |
Merge tag 'asoc-v3.15' into asoc-linus
ASoC: Updates for v3.15
Quite a busy release for ASoC this time, more on janitorial work than
exciting new features but welcome nontheless:
- Lots of cleanups from Takashi for enumerations; the original API for
these was error prone so he's refactored lots of code to use more
modern APIs which avoid issues.
- Elimination of the ASoC level wrappers for I2C and SPI moving us
closer to converting to regmap completely and avoiding some
randconfig hassle.
- Provide both manually and transparently locked DAPM APIs rather than
a mix of the two fixing some concurrency issues.
- Start converting CODEC drivers to use separate bus interface drivers
rather than having them all in one file helping avoid dependency
issues.
- DPCM support for Intel Haswell and Bay Trail platforms.
- Lots of work on improvements for simple-card, DaVinci and the Renesas
rcar drivers.
- New drivers for Analog Devices ADAU1977, TI PCM512x and parts of the
CSR SiRF SoC.
# gpg: Signature made Wed 12 Mar 2014 23:05:45 GMT using RSA key ID 7EA229BD
# gpg: Good signature from "Mark Brown <broonie@sirena.org.uk>"
# gpg: aka "Mark Brown <broonie@debian.org>"
# gpg: aka "Mark Brown <broonie@kernel.org>"
# gpg: aka "Mark Brown <broonie@tardis.ed.ac.uk>"
# gpg: aka "Mark Brown <broonie@linaro.org>"
# gpg: aka "Mark Brown <Mark.Brown@linaro.org>"
Diffstat (limited to 'include/sound/soc.h')
-rw-r--r-- | include/sound/soc.h | 126 |
1 files changed, 98 insertions, 28 deletions
diff --git a/include/sound/soc.h b/include/sound/soc.h index 9a001472b96a..959f38949967 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -45,6 +45,11 @@ ((unsigned long)&(struct soc_mixer_control) \ {.reg = xlreg, .rreg = xrreg, .shift = xshift, .rshift = xshift, \ .max = xmax, .platform_max = xmax, .invert = xinvert}) +#define SOC_DOUBLE_R_S_VALUE(xlreg, xrreg, xshift, xmin, xmax, xsign_bit, xinvert) \ + ((unsigned long)&(struct soc_mixer_control) \ + {.reg = xlreg, .rreg = xrreg, .shift = xshift, .rshift = xshift, \ + .max = xmax, .min = xmin, .platform_max = xmax, .sign_bit = xsign_bit, \ + .invert = xinvert}) #define SOC_DOUBLE_R_RANGE_VALUE(xlreg, xrreg, xshift, xmin, xmax, xinvert) \ ((unsigned long)&(struct soc_mixer_control) \ {.reg = xlreg, .rreg = xrreg, .shift = xshift, .rshift = xshift, \ @@ -152,6 +157,15 @@ {.reg = xreg, .rreg = xrreg, \ .shift = xshift, .rshift = xshift, \ .max = xmax, .min = xmin} } +#define SOC_DOUBLE_R_S_TLV(xname, reg_left, reg_right, xshift, xmin, xmax, xsign_bit, xinvert, tlv_array) \ +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\ + .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\ + SNDRV_CTL_ELEM_ACCESS_READWRITE,\ + .tlv.p = (tlv_array), \ + .info = snd_soc_info_volsw, \ + .get = snd_soc_get_volsw, .put = snd_soc_put_volsw, \ + .private_value = SOC_DOUBLE_R_S_VALUE(reg_left, reg_right, xshift, \ + xmin, xmax, xsign_bit, xinvert) } #define SOC_DOUBLE_S8_TLV(xname, xreg, xmin, xmax, tlv_array) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \ @@ -162,30 +176,28 @@ .private_value = (unsigned long)&(struct soc_mixer_control) \ {.reg = xreg, .min = xmin, .max = xmax, \ .platform_max = xmax} } -#define SOC_ENUM_DOUBLE(xreg, xshift_l, xshift_r, xmax, xtexts) \ +#define SOC_ENUM_DOUBLE(xreg, xshift_l, xshift_r, xitems, xtexts) \ { .reg = xreg, .shift_l = xshift_l, .shift_r = xshift_r, \ - .max = xmax, .texts = xtexts, \ - .mask = xmax ? roundup_pow_of_two(xmax) - 1 : 0} -#define SOC_ENUM_SINGLE(xreg, xshift, xmax, xtexts) \ - SOC_ENUM_DOUBLE(xreg, xshift, xshift, xmax, xtexts) -#define SOC_ENUM_SINGLE_EXT(xmax, xtexts) \ -{ .max = xmax, .texts = xtexts } -#define SOC_VALUE_ENUM_DOUBLE(xreg, xshift_l, xshift_r, xmask, xmax, xtexts, xvalues) \ + .items = xitems, .texts = xtexts, \ + .mask = xitems ? roundup_pow_of_two(xitems) - 1 : 0} +#define SOC_ENUM_SINGLE(xreg, xshift, xitems, xtexts) \ + SOC_ENUM_DOUBLE(xreg, xshift, xshift, xitems, xtexts) +#define SOC_ENUM_SINGLE_EXT(xitems, xtexts) \ +{ .items = xitems, .texts = xtexts } +#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, .max = xmax, .texts = xtexts, .values = xvalues} -#define SOC_VALUE_ENUM_SINGLE(xreg, xshift, xmask, xmax, xtexts, xvalues) \ - SOC_VALUE_ENUM_DOUBLE(xreg, xshift, xshift, xmask, xmax, xtexts, xvalues) + .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_ENUM_SINGLE_VIRT(xitems, xtexts) \ + SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, xitems, xtexts) #define SOC_ENUM(xname, xenum) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname,\ .info = snd_soc_info_enum_double, \ .get = snd_soc_get_enum_double, .put = snd_soc_put_enum_double, \ .private_value = (unsigned long)&xenum } #define SOC_VALUE_ENUM(xname, xenum) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname,\ - .info = snd_soc_info_enum_double, \ - .get = snd_soc_get_value_enum_double, \ - .put = snd_soc_put_value_enum_double, \ - .private_value = (unsigned long)&xenum } + SOC_ENUM(xname, xenum) #define SOC_SINGLE_EXT(xname, xreg, xshift, xmax, xinvert,\ xhandler_get, xhandler_put) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ @@ -272,17 +284,19 @@ * ARRAY_SIZE internally */ #define SOC_ENUM_DOUBLE_DECL(name, xreg, xshift_l, xshift_r, xtexts) \ - struct soc_enum name = SOC_ENUM_DOUBLE(xreg, xshift_l, xshift_r, \ + const struct soc_enum name = SOC_ENUM_DOUBLE(xreg, xshift_l, xshift_r, \ ARRAY_SIZE(xtexts), xtexts) #define SOC_ENUM_SINGLE_DECL(name, xreg, xshift, xtexts) \ SOC_ENUM_DOUBLE_DECL(name, xreg, xshift, xshift, xtexts) #define SOC_ENUM_SINGLE_EXT_DECL(name, xtexts) \ - struct soc_enum name = SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(xtexts), xtexts) + const struct soc_enum name = SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(xtexts), xtexts) #define SOC_VALUE_ENUM_DOUBLE_DECL(name, xreg, xshift_l, xshift_r, xmask, xtexts, xvalues) \ - struct soc_enum name = SOC_VALUE_ENUM_DOUBLE(xreg, xshift_l, xshift_r, xmask, \ + const struct soc_enum name = SOC_VALUE_ENUM_DOUBLE(xreg, xshift_l, xshift_r, xmask, \ 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_ENUM_SINGLE_VIRT_DECL(name, xtexts) \ + const struct soc_enum name = SOC_ENUM_SINGLE_VIRT(ARRAY_SIZE(xtexts), xtexts) /* * Component probe and remove ordering levels for components with runtime @@ -413,6 +427,10 @@ struct snd_pcm_substream *snd_soc_get_dai_substream(struct snd_soc_card *card, struct snd_soc_pcm_runtime *snd_soc_get_pcm_runtime(struct snd_soc_card *card, const char *dai_link); +bool snd_soc_runtime_ignore_pmdown_time(struct snd_soc_pcm_runtime *rtd); +void snd_soc_runtime_activate(struct snd_soc_pcm_runtime *rtd, int stream); +void snd_soc_runtime_deactivate(struct snd_soc_pcm_runtime *rtd, int stream); + /* Utility functions to get clock rates from various things */ int snd_soc_calc_frame_size(int sample_size, int channels, int tdm_slots); int snd_soc_params_to_frame_size(struct snd_pcm_hw_params *params); @@ -496,10 +514,6 @@ int snd_soc_get_enum_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); int snd_soc_put_enum_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); -int snd_soc_get_value_enum_double(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol); -int snd_soc_put_value_enum_double(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol); int snd_soc_info_volsw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo); #define snd_soc_info_bool_ext snd_ctl_boolean_mono_info @@ -656,12 +670,19 @@ struct snd_soc_component { const char *name; int id; struct device *dev; + + unsigned int active; + + unsigned int ignore_pmdown_time:1; /* pmdown_time is ignored at stop */ + struct list_head list; struct snd_soc_dai_driver *dai_drv; int num_dai; const struct snd_soc_component_driver *driver; + + struct list_head dai_list; }; /* SoC Audio Codec device */ @@ -683,7 +704,6 @@ struct snd_soc_codec { /* runtime */ struct snd_ac97 *ac97; /* for ad-hoc ac97 devices */ - unsigned int active; unsigned int cache_bypass:1; /* Suppress access to the cache */ unsigned int suspended:1; /* Codec is in suspend PM state */ unsigned int probed:1; /* Codec has been probed */ @@ -709,7 +729,6 @@ struct snd_soc_codec { /* dapm */ struct snd_soc_dapm_context dapm; - unsigned int ignore_pmdown_time:1; /* pmdown_time is ignored at stop */ #ifdef CONFIG_DEBUG_FS struct dentry *debugfs_codec_root; @@ -1067,6 +1086,7 @@ struct soc_mixer_control { int min, max, platform_max; int reg, rreg; unsigned int shift, rshift; + unsigned int sign_bit; unsigned int invert:1; unsigned int autodisable:1; }; @@ -1085,11 +1105,10 @@ struct soc_mreg_control { /* enumerated kcontrol */ struct soc_enum { - unsigned short reg; - unsigned short reg2; + int reg; unsigned char shift_l; unsigned char shift_r; - unsigned int max; + unsigned int items; unsigned int mask; const char * const *texts; const unsigned int *values; @@ -1168,11 +1187,51 @@ static inline bool snd_soc_volsw_is_stereo(struct soc_mixer_control *mc) return 1; } +static inline unsigned int snd_soc_enum_val_to_item(struct soc_enum *e, + unsigned int val) +{ + unsigned int i; + + if (!e->values) + return val; + + for (i = 0; i < e->items; i++) + if (val == e->values[i]) + return i; + + return 0; +} + +static inline unsigned int snd_soc_enum_item_to_val(struct soc_enum *e, + unsigned int item) +{ + if (!e->values) + return item; + + return e->values[item]; +} + +static inline bool snd_soc_component_is_active( + struct snd_soc_component *component) +{ + return component->active != 0; +} + +static inline bool snd_soc_codec_is_active(struct snd_soc_codec *codec) +{ + return snd_soc_component_is_active(&codec->component); +} + int snd_soc_util_init(void); void snd_soc_util_exit(void); int snd_soc_of_parse_card_name(struct snd_soc_card *card, const char *propname); +int snd_soc_of_parse_audio_simple_widgets(struct snd_soc_card *card, + const char *propname); +int snd_soc_of_parse_tdm_slot(struct device_node *np, + unsigned int *slots, + unsigned int *slot_width); int snd_soc_of_parse_audio_routing(struct snd_soc_card *card, const char *propname); unsigned int snd_soc_of_parse_daifmt(struct device_node *np, @@ -1188,4 +1247,15 @@ extern struct dentry *snd_soc_debugfs_root; extern const struct dev_pm_ops snd_soc_pm_ops; +/* Helper functions */ +static inline void snd_soc_dapm_mutex_lock(struct snd_soc_dapm_context *dapm) +{ + mutex_lock(&dapm->card->dapm_mutex); +} + +static inline void snd_soc_dapm_mutex_unlock(struct snd_soc_dapm_context *dapm) +{ + mutex_unlock(&dapm->card->dapm_mutex); +} + #endif |