diff options
Diffstat (limited to 'include/sound/soc.h')
-rw-r--r-- | include/sound/soc.h | 734 |
1 files changed, 436 insertions, 298 deletions
diff --git a/include/sound/soc.h b/include/sound/soc.h index 3b038c563ae1..1fffef311c41 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -10,65 +10,64 @@ #ifndef __LINUX_SND_SOC_H #define __LINUX_SND_SOC_H +#include <linux/args.h> +#include <linux/array_size.h> +#include <linux/device.h> +#include <linux/errno.h> +#include <linux/interrupt.h> +#include <linux/lockdep.h> +#include <linux/log2.h> +#include <linux/mutex.h> +#include <linux/notifier.h> #include <linux/of.h> -#include <linux/platform_device.h> #include <linux/types.h> -#include <linux/notifier.h> #include <linux/workqueue.h> -#include <linux/interrupt.h> -#include <linux/kernel.h> -#include <linux/regmap.h> -#include <linux/log2.h> -#include <sound/core.h> -#include <sound/pcm.h> + +#include <sound/ac97_codec.h> #include <sound/compress_driver.h> #include <sound/control.h> -#include <sound/ac97_codec.h> +#include <sound/core.h> +#include <sound/pcm.h> + +struct module; +struct platform_device; + +/* For the current users of sound/soc.h to avoid build issues */ +#include <linux/platform_device.h> +#include <linux/regmap.h> /* * Convenience kcontrol builders */ -#define SOC_DOUBLE_VALUE(xreg, shift_left, shift_right, xmax, xinvert, xautodisable) \ - ((unsigned long)&(struct soc_mixer_control) \ - {.reg = xreg, .rreg = xreg, .shift = shift_left, \ - .rshift = shift_right, .max = xmax, .platform_max = xmax, \ - .invert = xinvert, .autodisable = xautodisable}) -#define SOC_DOUBLE_S_VALUE(xreg, shift_left, shift_right, xmin, xmax, xsign_bit, xinvert, xautodisable) \ +#define SOC_DOUBLE_S_VALUE(xreg, shift_left, shift_right, xmin, xmax, xsign_bit, \ + xinvert, xautodisable) \ ((unsigned long)&(struct soc_mixer_control) \ {.reg = xreg, .rreg = xreg, .shift = shift_left, \ - .rshift = shift_right, .min = xmin, .max = xmax, .platform_max = xmax, \ + .rshift = shift_right, .min = xmin, .max = xmax, \ .sign_bit = xsign_bit, .invert = xinvert, .autodisable = xautodisable}) -#define SOC_SINGLE_VALUE(xreg, xshift, xmax, xinvert, xautodisable) \ - SOC_DOUBLE_VALUE(xreg, xshift, xshift, xmax, xinvert, xautodisable) -#define SOC_SINGLE_VALUE_EXT(xreg, xmax, xinvert) \ - ((unsigned long)&(struct soc_mixer_control) \ - {.reg = xreg, .max = xmax, .platform_max = xmax, .invert = xinvert}) -#define SOC_DOUBLE_R_VALUE(xlreg, xrreg, xshift, xmax, xinvert) \ - ((unsigned long)&(struct soc_mixer_control) \ - {.reg = xlreg, .rreg = xrreg, .shift = xshift, .rshift = xshift, \ - .max = xmax, .platform_max = xmax, .invert = xinvert}) +#define SOC_DOUBLE_VALUE(xreg, shift_left, shift_right, xmin, xmax, xinvert, xautodisable) \ + SOC_DOUBLE_S_VALUE(xreg, shift_left, shift_right, xmin, xmax, 0, xinvert, \ + xautodisable) +#define SOC_SINGLE_VALUE(xreg, xshift, xmin, xmax, xinvert, xautodisable) \ + SOC_DOUBLE_VALUE(xreg, xshift, xshift, xmin, xmax, xinvert, xautodisable) #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, \ + .max = xmax, .min = xmin, .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, \ - .min = xmin, .max = xmax, .platform_max = xmax, .invert = xinvert}) +#define SOC_DOUBLE_R_VALUE(xlreg, xrreg, xshift, xmin, xmax, xinvert) \ + SOC_DOUBLE_R_S_VALUE(xlreg, xrreg, xshift, xmin, xmax, 0, xinvert) + #define SOC_SINGLE(xname, reg, shift, max, invert) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ .info = snd_soc_info_volsw, .get = snd_soc_get_volsw,\ .put = snd_soc_put_volsw, \ - .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert, 0) } + .private_value = SOC_SINGLE_VALUE(reg, shift, 0, max, invert, 0) } #define SOC_SINGLE_RANGE(xname, xreg, xshift, xmin, xmax, xinvert) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\ - .info = snd_soc_info_volsw_range, .get = snd_soc_get_volsw_range, \ - .put = snd_soc_put_volsw_range, \ - .private_value = (unsigned long)&(struct soc_mixer_control) \ - {.reg = xreg, .rreg = xreg, .shift = xshift, \ - .rshift = xshift, .min = xmin, .max = xmax, \ - .platform_max = xmax, .invert = xinvert} } + .info = snd_soc_info_volsw, .get = snd_soc_get_volsw, \ + .put = snd_soc_put_volsw, \ + .private_value = SOC_SINGLE_VALUE(xreg, xshift, xmin, xmax, xinvert, 0) } #define SOC_SINGLE_TLV(xname, reg, shift, max, invert, tlv_array) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\ @@ -76,7 +75,7 @@ .tlv.p = (tlv_array), \ .info = snd_soc_info_volsw, .get = snd_soc_get_volsw,\ .put = snd_soc_put_volsw, \ - .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert, 0) } + .private_value = SOC_SINGLE_VALUE(reg, shift, 0, max, invert, 0) } #define SOC_SINGLE_SX_TLV(xname, xreg, xshift, xmin, xmax, tlv_array) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \ @@ -85,27 +84,21 @@ .info = snd_soc_info_volsw_sx, \ .get = snd_soc_get_volsw_sx,\ .put = snd_soc_put_volsw_sx, \ - .private_value = (unsigned long)&(struct soc_mixer_control) \ - {.reg = xreg, .rreg = xreg, \ - .shift = xshift, .rshift = xshift, \ - .max = xmax, .min = xmin} } + .private_value = SOC_SINGLE_VALUE(xreg, xshift, xmin, xmax, 0, 0) } #define SOC_SINGLE_RANGE_TLV(xname, xreg, xshift, xmin, xmax, 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_range, \ - .get = snd_soc_get_volsw_range, .put = snd_soc_put_volsw_range, \ - .private_value = (unsigned long)&(struct soc_mixer_control) \ - {.reg = xreg, .rreg = xreg, .shift = xshift, \ - .rshift = xshift, .min = xmin, .max = xmax, \ - .platform_max = xmax, .invert = xinvert} } + .info = snd_soc_info_volsw, \ + .get = snd_soc_get_volsw, .put = snd_soc_put_volsw, \ + .private_value = SOC_SINGLE_VALUE(xreg, xshift, xmin, xmax, xinvert, 0) } #define SOC_DOUBLE(xname, reg, shift_left, shift_right, max, invert) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\ .info = snd_soc_info_volsw, .get = snd_soc_get_volsw, \ .put = snd_soc_put_volsw, \ .private_value = SOC_DOUBLE_VALUE(reg, shift_left, shift_right, \ - max, invert, 0) } + 0, max, invert, 0) } #define SOC_DOUBLE_STS(xname, reg, shift_left, shift_right, max, invert) \ { \ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ @@ -113,19 +106,19 @@ .access = SNDRV_CTL_ELEM_ACCESS_READ | \ SNDRV_CTL_ELEM_ACCESS_VOLATILE, \ .private_value = SOC_DOUBLE_VALUE(reg, shift_left, shift_right, \ - max, invert, 0) } + 0, max, invert, 0) } #define SOC_DOUBLE_R(xname, reg_left, reg_right, xshift, xmax, xinvert) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ .info = snd_soc_info_volsw, \ .get = snd_soc_get_volsw, .put = snd_soc_put_volsw, \ .private_value = SOC_DOUBLE_R_VALUE(reg_left, reg_right, xshift, \ - xmax, xinvert) } + 0, xmax, xinvert) } #define SOC_DOUBLE_R_RANGE(xname, reg_left, reg_right, xshift, xmin, \ xmax, xinvert) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\ - .info = snd_soc_info_volsw_range, \ - .get = snd_soc_get_volsw_range, .put = snd_soc_put_volsw_range, \ - .private_value = SOC_DOUBLE_R_RANGE_VALUE(reg_left, reg_right, \ + .info = snd_soc_info_volsw, \ + .get = snd_soc_get_volsw, .put = snd_soc_put_volsw, \ + .private_value = SOC_DOUBLE_R_VALUE(reg_left, reg_right, \ xshift, xmin, xmax, xinvert) } #define SOC_DOUBLE_TLV(xname, reg, shift_left, shift_right, max, invert, tlv_array) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\ @@ -135,7 +128,27 @@ .info = snd_soc_info_volsw, .get = snd_soc_get_volsw, \ .put = snd_soc_put_volsw, \ .private_value = SOC_DOUBLE_VALUE(reg, shift_left, shift_right, \ - max, invert, 0) } + 0, max, invert, 0) } +#define SOC_DOUBLE_SX_TLV(xname, xreg, shift_left, shift_right, xmin, xmax, 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_sx, \ + .get = snd_soc_get_volsw_sx, \ + .put = snd_soc_put_volsw_sx, \ + .private_value = SOC_DOUBLE_VALUE(xreg, shift_left, shift_right, \ + xmin, xmax, 0, 0) } +#define SOC_DOUBLE_RANGE_TLV(xname, xreg, xshift_left, xshift_right, xmin, xmax, \ + 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_VALUE(xreg, xshift_left, xshift_right, \ + xmin, xmax, xinvert, 0) } #define SOC_DOUBLE_R_TLV(xname, reg_left, reg_right, xshift, xmax, xinvert, tlv_array) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\ .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\ @@ -144,16 +157,16 @@ .info = snd_soc_info_volsw, \ .get = snd_soc_get_volsw, .put = snd_soc_put_volsw, \ .private_value = SOC_DOUBLE_R_VALUE(reg_left, reg_right, xshift, \ - xmax, xinvert) } + 0, xmax, xinvert) } #define SOC_DOUBLE_R_RANGE_TLV(xname, reg_left, reg_right, xshift, xmin, \ xmax, 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_range, \ - .get = snd_soc_get_volsw_range, .put = snd_soc_put_volsw_range, \ - .private_value = SOC_DOUBLE_R_RANGE_VALUE(reg_left, reg_right, \ + .info = snd_soc_info_volsw, \ + .get = snd_soc_get_volsw, .put = snd_soc_put_volsw, \ + .private_value = SOC_DOUBLE_R_VALUE(reg_left, reg_right, \ xshift, xmin, xmax, xinvert) } #define SOC_DOUBLE_R_SX_TLV(xname, xreg, xrreg, xshift, xmin, xmax, tlv_array) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ @@ -163,10 +176,7 @@ .info = snd_soc_info_volsw_sx, \ .get = snd_soc_get_volsw_sx, \ .put = snd_soc_put_volsw_sx, \ - .private_value = (unsigned long)&(struct soc_mixer_control) \ - {.reg = xreg, .rreg = xrreg, \ - .shift = xshift, .rshift = xshift, \ - .max = xmax, .min = xmin} } + .private_value = SOC_DOUBLE_R_VALUE(xreg, xrreg, xshift, xmin, xmax, 0) } #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 |\ @@ -176,6 +186,8 @@ .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_SINGLE_S_TLV(xname, xreg, xshift, xmin, xmax, xsign_bit, xinvert, tlv_array) \ + SOC_DOUBLE_R_S_TLV(xname, xreg, xreg, xshift, xmin, xmax, xsign_bit, xinvert, tlv_array) #define SOC_SINGLE_S8_TLV(xname, xreg, xmin, xmax, tlv_array) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \ @@ -185,7 +197,7 @@ .put = snd_soc_put_volsw, \ .private_value = (unsigned long)&(struct soc_mixer_control) \ {.reg = xreg, .rreg = xreg, \ - .min = xmin, .max = xmax, .platform_max = xmax, \ + .min = xmin, .max = xmax, \ .sign_bit = 7,} } #define SOC_DOUBLE_S8_TLV(xname, xreg, xmin, xmax, tlv_array) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ @@ -224,21 +236,21 @@ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ .info = snd_soc_info_volsw, \ .get = xhandler_get, .put = xhandler_put, \ - .private_value = SOC_SINGLE_VALUE(xreg, xshift, xmax, xinvert, 0) } + .private_value = SOC_SINGLE_VALUE(xreg, xshift, 0, xmax, xinvert, 0) } #define SOC_DOUBLE_EXT(xname, reg, shift_left, shift_right, max, invert,\ xhandler_get, xhandler_put) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\ .info = snd_soc_info_volsw, \ .get = xhandler_get, .put = xhandler_put, \ .private_value = \ - SOC_DOUBLE_VALUE(reg, shift_left, shift_right, max, invert, 0) } + SOC_DOUBLE_VALUE(reg, shift_left, shift_right, 0, max, invert, 0) } #define SOC_DOUBLE_R_EXT(xname, reg_left, reg_right, xshift, xmax, xinvert,\ xhandler_get, xhandler_put) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ .info = snd_soc_info_volsw, \ .get = xhandler_get, .put = xhandler_put, \ .private_value = SOC_DOUBLE_R_VALUE(reg_left, reg_right, xshift, \ - xmax, xinvert) } + 0, xmax, xinvert) } #define SOC_SINGLE_EXT_TLV(xname, xreg, xshift, xmax, xinvert,\ xhandler_get, xhandler_put, tlv_array) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ @@ -247,19 +259,16 @@ .tlv.p = (tlv_array), \ .info = snd_soc_info_volsw, \ .get = xhandler_get, .put = xhandler_put, \ - .private_value = SOC_SINGLE_VALUE(xreg, xshift, xmax, xinvert, 0) } + .private_value = SOC_SINGLE_VALUE(xreg, xshift, 0, xmax, xinvert, 0) } #define SOC_SINGLE_RANGE_EXT_TLV(xname, xreg, xshift, xmin, xmax, xinvert, \ xhandler_get, xhandler_put, 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_range, \ + .info = snd_soc_info_volsw, \ .get = xhandler_get, .put = xhandler_put, \ - .private_value = (unsigned long)&(struct soc_mixer_control) \ - {.reg = xreg, .rreg = xreg, .shift = xshift, \ - .rshift = xshift, .min = xmin, .max = xmax, \ - .platform_max = xmax, .invert = xinvert} } + .private_value = SOC_SINGLE_VALUE(xreg, xshift, xmin, xmax, xinvert, 0) } #define SOC_DOUBLE_EXT_TLV(xname, xreg, shift_left, shift_right, xmax, xinvert,\ xhandler_get, xhandler_put, tlv_array) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ @@ -269,7 +278,7 @@ .info = snd_soc_info_volsw, \ .get = xhandler_get, .put = xhandler_put, \ .private_value = SOC_DOUBLE_VALUE(xreg, shift_left, shift_right, \ - xmax, xinvert, 0) } + 0, xmax, xinvert, 0) } #define SOC_DOUBLE_R_EXT_TLV(xname, reg_left, reg_right, xshift, xmax, xinvert,\ xhandler_get, xhandler_put, tlv_array) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ @@ -279,7 +288,24 @@ .info = snd_soc_info_volsw, \ .get = xhandler_get, .put = xhandler_put, \ .private_value = SOC_DOUBLE_R_VALUE(reg_left, reg_right, xshift, \ - xmax, xinvert) } + 0, xmax, xinvert) } +#define SOC_DOUBLE_R_S_EXT_TLV(xname, reg_left, reg_right, xshift, xmin, xmax, \ + xsign_bit, xinvert, xhandler_get, xhandler_put, \ + 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 = xhandler_get, .put = xhandler_put, \ + .private_value = SOC_DOUBLE_R_S_VALUE(reg_left, reg_right, xshift, \ + xmin, xmax, xsign_bit, xinvert) } +#define SOC_SINGLE_S_EXT_TLV(xname, xreg, xshift, xmin, xmax, \ + xsign_bit, xinvert, xhandler_get, xhandler_put, \ + tlv_array) \ + SOC_DOUBLE_R_S_EXT_TLV(xname, xreg, xreg, xshift, xmin, xmax, \ + xsign_bit, xinvert, xhandler_get, xhandler_put, \ + tlv_array) #define SOC_SINGLE_BOOL_EXT(xname, xdata, xhandler_get, xhandler_put) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ .info = snd_soc_info_bool_ext, \ @@ -368,37 +394,29 @@ #define SOC_ENUM_SINGLE_VIRT_DECL(name, xtexts) \ const struct soc_enum name = SOC_ENUM_SINGLE_VIRT(ARRAY_SIZE(xtexts), xtexts) -struct device_node; -struct snd_jack; struct snd_soc_card; -struct snd_soc_pcm_stream; -struct snd_soc_ops; struct snd_soc_pcm_runtime; struct snd_soc_dai; struct snd_soc_dai_driver; struct snd_soc_dai_link; struct snd_soc_component; struct snd_soc_component_driver; -struct soc_enum; struct snd_soc_jack; -struct snd_soc_jack_zone; struct snd_soc_jack_pin; + #include <sound/soc-dapm.h> #include <sound/soc-dpcm.h> #include <sound/soc-topology.h> -struct snd_soc_jack_gpio; - -typedef int (*hw_write_t)(void *,const char* ,int); - enum snd_soc_pcm_subclass { SND_SOC_PCM_CLASS_PCM = 0, SND_SOC_PCM_CLASS_BE = 1, }; int snd_soc_register_card(struct snd_soc_card *card); -int snd_soc_unregister_card(struct snd_soc_card *card); +void snd_soc_unregister_card(struct snd_soc_card *card); int devm_snd_soc_register_card(struct device *dev, struct snd_soc_card *card); +int devm_snd_soc_register_deferrable_card(struct device *dev, struct snd_soc_card *card); #ifdef CONFIG_PM_SLEEP int snd_soc_suspend(struct device *dev); int snd_soc_resume(struct device *dev); @@ -426,7 +444,7 @@ int snd_soc_register_component(struct device *dev, int devm_snd_soc_register_component(struct device *dev, const struct snd_soc_component_driver *component_driver, struct snd_soc_dai_driver *dai_drv, int num_dai); -void snd_soc_unregister_component(struct device *dev); +#define snd_soc_unregister_component(dev) snd_soc_unregister_component_by_driver(dev, NULL) void snd_soc_unregister_component_by_driver(struct device *dev, const struct snd_soc_component_driver *component_driver); struct snd_soc_component *snd_soc_lookup_component_nolocked(struct device *dev, @@ -434,18 +452,16 @@ struct snd_soc_component *snd_soc_lookup_component_nolocked(struct device *dev, struct snd_soc_component *snd_soc_lookup_component(struct device *dev, const char *driver_name); -int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num); +int soc_new_pcm(struct snd_soc_pcm_runtime *rtd); #ifdef CONFIG_SND_SOC_COMPRESS -int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num); +int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd); #else -static inline int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num) +static inline int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd) { return 0; } #endif -void snd_soc_disconnect_sync(struct device *dev); - struct snd_soc_pcm_runtime *snd_soc_get_pcm_runtime(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link); @@ -470,66 +486,24 @@ int snd_soc_runtime_calc_hw(struct snd_soc_pcm_runtime *rtd, int snd_soc_runtime_set_dai_fmt(struct snd_soc_pcm_runtime *rtd, unsigned int dai_fmt); -#ifdef CONFIG_DMI -int snd_soc_set_dmi_name(struct snd_soc_card *card, const char *flavour); -#else -static inline int snd_soc_set_dmi_name(struct snd_soc_card *card, - const char *flavour) -{ - return 0; -} -#endif - /* 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); +int snd_soc_params_to_frame_size(const struct snd_pcm_hw_params *params); int snd_soc_calc_bclk(int fs, int sample_size, int channels, int tdm_slots); -int snd_soc_params_to_bclk(struct snd_pcm_hw_params *parms); +int snd_soc_params_to_bclk(const struct snd_pcm_hw_params *parms); +int snd_soc_tdm_params_to_bclk(const struct snd_pcm_hw_params *params, + int tdm_width, int tdm_slots, int slot_multiple); +int snd_soc_ret(const struct device *dev, int ret, const char *fmt, ...); /* set runtime hw params */ -int snd_soc_set_runtime_hwparams(struct snd_pcm_substream *substream, - const struct snd_pcm_hardware *hw); - -/* Jack reporting */ -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); -void snd_soc_jack_notifier_register(struct snd_soc_jack *jack, - struct notifier_block *nb); -void snd_soc_jack_notifier_unregister(struct snd_soc_jack *jack, - struct notifier_block *nb); -int snd_soc_jack_add_zones(struct snd_soc_jack *jack, int count, - struct snd_soc_jack_zone *zones); -int snd_soc_jack_get_type(struct snd_soc_jack *jack, int micbias_voltage); -#ifdef CONFIG_GPIOLIB -int snd_soc_jack_add_gpios(struct snd_soc_jack *jack, int count, - struct snd_soc_jack_gpio *gpios); -int snd_soc_jack_add_gpiods(struct device *gpiod_dev, - struct snd_soc_jack *jack, - int count, struct snd_soc_jack_gpio *gpios); -void snd_soc_jack_free_gpios(struct snd_soc_jack *jack, int count, - struct snd_soc_jack_gpio *gpios); -#else -static inline int snd_soc_jack_add_gpios(struct snd_soc_jack *jack, int count, - struct snd_soc_jack_gpio *gpios) +static inline int snd_soc_set_runtime_hwparams(struct snd_pcm_substream *substream, + const struct snd_pcm_hardware *hw) { - return 0; -} + substream->runtime->hw = *hw; -static inline int snd_soc_jack_add_gpiods(struct device *gpiod_dev, - struct snd_soc_jack *jack, - int count, - struct snd_soc_jack_gpio *gpios) -{ return 0; } -static inline void snd_soc_jack_free_gpios(struct snd_soc_jack *jack, int count, - struct snd_soc_jack_gpio *gpios) -{ -} -#endif - struct snd_ac97 *snd_soc_alloc_ac97_component(struct snd_soc_component *component); struct snd_ac97 *snd_soc_new_ac97_component(struct snd_soc_component *component, unsigned int id, unsigned int id_mask); @@ -587,12 +561,6 @@ int snd_soc_get_volsw_sx(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); int snd_soc_put_volsw_sx(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); -int snd_soc_info_volsw_range(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo); -int snd_soc_put_volsw_range(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol); -int snd_soc_get_volsw_range(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol); int snd_soc_limit_volume(struct snd_soc_card *card, const char *name, int max); int snd_soc_bytes_info(struct snd_kcontrol *kcontrol, @@ -616,91 +584,19 @@ int snd_soc_get_strobe(struct snd_kcontrol *kcontrol, int snd_soc_put_strobe(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); -/** - * struct snd_soc_jack_pin - Describes a pin to update based on jack detection - * - * @pin: name of the pin to update - * @mask: bits to check for in reported jack status - * @invert: if non-zero then pin is enabled when status is not reported - * @list: internal list entry - */ -struct snd_soc_jack_pin { - struct list_head list; - const char *pin; - int mask; - bool invert; -}; - -/** - * struct snd_soc_jack_zone - Describes voltage zones of jack detection - * - * @min_mv: start voltage in mv - * @max_mv: end voltage in mv - * @jack_type: type of jack that is expected for this voltage - * @debounce_time: debounce_time for jack, codec driver should wait for this - * duration before reading the adc for voltages - * @list: internal list entry - */ -struct snd_soc_jack_zone { - unsigned int min_mv; - unsigned int max_mv; - unsigned int jack_type; - unsigned int debounce_time; - struct list_head list; -}; - -/** - * struct snd_soc_jack_gpio - Describes a gpio pin for jack detection - * - * @gpio: legacy gpio number - * @idx: gpio descriptor index within the function of the GPIO - * consumer device - * @gpiod_dev: GPIO consumer device - * @name: gpio name. Also as connection ID for the GPIO consumer - * device function name lookup - * @report: value to report when jack detected - * @invert: report presence in low state - * @debounce_time: debounce time in ms - * @wake: enable as wake source - * @jack_status_check: callback function which overrides the detection - * to provide more complex checks (eg, reading an - * ADC). - */ -struct snd_soc_jack_gpio { - unsigned int gpio; - unsigned int idx; - struct device *gpiod_dev; - const char *name; - int report; - int invert; - int debounce_time; - bool wake; - - /* private: */ - struct snd_soc_jack *jack; - struct delayed_work work; - struct notifier_block pm_notifier; - struct gpio_desc *desc; - - void *data; - /* public: */ - int (*jack_status_check)(void *data); -}; +enum snd_soc_trigger_order { + /* start stop */ + SND_SOC_TRIGGER_ORDER_DEFAULT = 0, /* Link->Component->DAI DAI->Component->Link */ + SND_SOC_TRIGGER_ORDER_LDC, /* Link->DAI->Component Component->DAI->Link */ -struct snd_soc_jack { - struct mutex mutex; - struct snd_jack *jack; - struct snd_soc_card *card; - struct list_head pins; - int status; - struct blocking_notifier_head notifier; - struct list_head jack_zones; + SND_SOC_TRIGGER_ORDER_MAX, }; /* SoC PCM stream information */ struct snd_soc_pcm_stream { const char *stream_name; u64 formats; /* SNDRV_PCM_FMTBIT_* */ + u32 subformats; /* for S32_LE format, SNDRV_PCM_SUBFMTBIT_* */ unsigned int rates; /* SNDRV_PCM_RATE_* */ unsigned int rate_min; /* min rate */ unsigned int rate_max; /* max rate */ @@ -723,7 +619,6 @@ struct snd_soc_compr_ops { int (*startup)(struct snd_compr_stream *); void (*shutdown)(struct snd_compr_stream *); int (*set_params)(struct snd_compr_stream *); - int (*trigger)(struct snd_compr_stream *); }; struct snd_soc_component* @@ -734,6 +629,60 @@ struct snd_soc_dai_link_component { const char *name; struct device_node *of_node; const char *dai_name; + const struct of_phandle_args *dai_args; + + /* + * Extra format = SND_SOC_DAIFMT_Bx_Fx + * + * [Note] it is Bx_Fx base, not CBx_CFx + * + * It will be used with dai_link->dai_fmt + * see + * snd_soc_runtime_set_dai_fmt() + */ + unsigned int ext_fmt; +}; + +/* + * [dai_link->ch_maps Image sample] + * + *------------------------- + * CPU0 <---> Codec0 + * + * ch-map[0].cpu = 0 ch-map[0].codec = 0 + * + *------------------------- + * CPU0 <---> Codec0 + * CPU1 <---> Codec1 + * CPU2 <---> Codec2 + * + * ch-map[0].cpu = 0 ch-map[0].codec = 0 + * ch-map[1].cpu = 1 ch-map[1].codec = 1 + * ch-map[2].cpu = 2 ch-map[2].codec = 2 + * + *------------------------- + * CPU0 <---> Codec0 + * CPU1 <-+-> Codec1 + * CPU2 <-/ + * + * ch-map[0].cpu = 0 ch-map[0].codec = 0 + * ch-map[1].cpu = 1 ch-map[1].codec = 1 + * ch-map[2].cpu = 2 ch-map[2].codec = 1 + * + *------------------------- + * CPU0 <---> Codec0 + * CPU1 <-+-> Codec1 + * \-> Codec2 + * + * ch-map[0].cpu = 0 ch-map[0].codec = 0 + * ch-map[1].cpu = 1 ch-map[1].codec = 1 + * ch-map[2].cpu = 1 ch-map[2].codec = 2 + * + */ +struct snd_soc_dai_link_ch_map { + unsigned int cpu; + unsigned int codec; + unsigned int ch_mask; }; struct snd_soc_dai_link { @@ -764,6 +713,9 @@ struct snd_soc_dai_link { struct snd_soc_dai_link_component *codecs; unsigned int num_codecs; + /* num_ch_maps = max(num_cpu, num_codecs) */ + struct snd_soc_dai_link_ch_map *ch_maps; + /* * You MAY specify the link's platform/PCM/DMA driver, either by * device name, or by DT/OF node, but not both. Some forms of link @@ -774,8 +726,11 @@ struct snd_soc_dai_link { int id; /* optional ID for machine driver link identification */ - const struct snd_soc_pcm_stream *params; - unsigned int num_params; + /* + * for Codec2Codec + */ + const struct snd_soc_pcm_stream *c2c_params; + unsigned int num_c2c_params; unsigned int dai_fmt; /* format to set on init */ @@ -795,6 +750,15 @@ struct snd_soc_dai_link { const struct snd_soc_ops *ops; const struct snd_soc_compr_ops *compr_ops; + /* + * soc_pcm_trigger() start/stop sequence. + * see also + * snd_soc_component_driver + * soc_pcm_trigger() + */ + enum snd_soc_trigger_order trigger_start; + enum snd_soc_trigger_order trigger_stop; + /* Mark this pcm with non atomic ops */ unsigned int nonatomic:1; @@ -806,9 +770,9 @@ struct snd_soc_dai_link { unsigned int ignore_suspend:1; /* Symmetry requirements */ - unsigned int symmetric_rates:1; + unsigned int symmetric_rate:1; unsigned int symmetric_channels:1; - unsigned int symmetric_samplebits:1; + unsigned int symmetric_sample_bits:1; /* Do not create a PCM for this DAI link (Backend link) */ unsigned int no_pcm:1; @@ -816,10 +780,6 @@ struct snd_soc_dai_link { /* This DAI link can route to other DAI links at runtime (Frontend)*/ unsigned int dynamic:1; - /* DPCM capture and Playback support */ - unsigned int dpcm_capture:1; - unsigned int dpcm_playback:1; - /* DPCM used FE & BE merged format */ unsigned int dpcm_merged_format:1; /* DPCM used FE & BE merged channel */ @@ -837,20 +797,49 @@ struct snd_soc_dai_link { struct snd_soc_dobj dobj; /* For topology */ #endif }; + +static inline int snd_soc_link_num_ch_map(const struct snd_soc_dai_link *link) +{ + return max(link->num_cpus, link->num_codecs); +} + +static inline struct snd_soc_dai_link_component* +snd_soc_link_to_cpu(struct snd_soc_dai_link *link, int n) { + return &(link)->cpus[n]; +} + +static inline struct snd_soc_dai_link_component* +snd_soc_link_to_codec(struct snd_soc_dai_link *link, int n) { + return &(link)->codecs[n]; +} + +static inline struct snd_soc_dai_link_component* +snd_soc_link_to_platform(struct snd_soc_dai_link *link, int n) { + return &(link)->platforms[n]; +} + #define for_each_link_codecs(link, i, codec) \ for ((i) = 0; \ - ((i) < link->num_codecs) && ((codec) = &link->codecs[i]); \ + ((i) < link->num_codecs) && \ + ((codec) = snd_soc_link_to_codec(link, i)); \ (i)++) #define for_each_link_platforms(link, i, platform) \ for ((i) = 0; \ ((i) < link->num_platforms) && \ - ((platform) = &link->platforms[i]); \ + ((platform) = snd_soc_link_to_platform(link, i)); \ (i)++) #define for_each_link_cpus(link, i, cpu) \ for ((i) = 0; \ - ((i) < link->num_cpus) && ((cpu) = &link->cpus[i]); \ + ((i) < link->num_cpus) && \ + ((cpu) = snd_soc_link_to_cpu(link, i)); \ + (i)++) + +#define for_each_link_ch_maps(link, i, ch_map) \ + for ((i) = 0; \ + ((i) < snd_soc_link_num_ch_map(link) && \ + ((ch_map) = link->ch_maps + i)); \ (i)++) /* @@ -916,12 +905,8 @@ struct snd_soc_dai_link { .platforms = platform, \ .num_platforms = ARRAY_SIZE(platform) -#define SND_SOC_DAILINK_REGx(_1, _2, _3, func, ...) func #define SND_SOC_DAILINK_REG(...) \ - SND_SOC_DAILINK_REGx(__VA_ARGS__, \ - SND_SOC_DAILINK_REG3, \ - SND_SOC_DAILINK_REG2, \ - SND_SOC_DAILINK_REG1)(__VA_ARGS__) + CONCATENATE(SND_SOC_DAILINK_REG, COUNT_ARGS(__VA_ARGS__))(__VA_ARGS__) #define SND_SOC_DAILINK_DEF(name, def...) \ static struct snd_soc_dai_link_component name[] = { def } @@ -938,10 +923,11 @@ struct snd_soc_dai_link { #define COMP_PLATFORM(_name) { .name = _name } #define COMP_AUX(_name) { .name = _name } #define COMP_CODEC_CONF(_name) { .name = _name } -#define COMP_DUMMY() { .name = "snd-soc-dummy", .dai_name = "snd-soc-dummy-dai", } +#define COMP_DUMMY() /* see snd_soc_fill_dummy_dai() */ extern struct snd_soc_dai_link_component null_dailink_component[0]; - +extern struct snd_soc_dai_link_component snd_soc_dummy_dlc; +int snd_soc_dlc_is_dummy(struct snd_soc_dai_link_component *dlc); struct snd_soc_codec_conf { /* @@ -977,6 +963,17 @@ struct snd_soc_card { #ifdef CONFIG_DMI char dmi_longname[80]; #endif /* CONFIG_DMI */ + +#ifdef CONFIG_PCI + /* + * PCI does not define 0 as invalid, so pci_subsystem_set indicates + * whether a value has been written to these fields. + */ + unsigned short pci_subsystem_vendor; + unsigned short pci_subsystem_device; + bool pci_subsystem_set; +#endif /* CONFIG_PCI */ + char topology_shortname[32]; struct device *dev; @@ -990,10 +987,9 @@ struct snd_soc_card { struct mutex pcm_mutex; enum snd_soc_pcm_subclass pcm_subclass; - spinlock_t dpcm_lock; - int (*probe)(struct snd_soc_card *card); int (*late_probe)(struct snd_soc_card *card); + void (*fixup_controls)(struct snd_soc_card *card); int (*remove)(struct snd_soc_card *card); /* the pre and post PM functions are used to do any PM work before and @@ -1068,7 +1064,6 @@ struct snd_soc_card { /* Generic DAPM context for the card */ struct snd_soc_dapm_context dapm; struct snd_soc_dapm_stats dapm_stats; - struct snd_soc_dapm_update *update; #ifdef CONFIG_DEBUG_FS struct dentry *debugfs_card_root; @@ -1082,8 +1077,9 @@ struct snd_soc_card { unsigned int instantiated:1; unsigned int topology_shortname_created:1; unsigned int fully_routed:1; - unsigned int disable_route_checks:1; unsigned int probed:1; + unsigned int component_chaining:1; + struct device *devres_dev; void *drvdata; }; @@ -1118,6 +1114,12 @@ struct snd_soc_card { #define for_each_card_widgets_safe(card, w, _w) \ list_for_each_entry_safe(w, _w, &card->widgets, list) + +static inline int snd_soc_card_is_instantiated(struct snd_soc_card *card) +{ + return card && card->instantiated; +} + /* SoC machine DAI configuration, glues a codec and cpu DAI together */ struct snd_soc_pcm_runtime { struct device *dev; @@ -1125,10 +1127,11 @@ struct snd_soc_pcm_runtime { struct snd_soc_dai_link *dai_link; struct snd_pcm_ops ops; - unsigned int params_select; /* currently selected param for dai link */ + unsigned int c2c_params_select; /* currently selected c2c_param for dai link */ /* Dynamic PCM BE runtime data */ - struct snd_soc_dpcm_runtime dpcm[2]; + struct snd_soc_dpcm_runtime dpcm[SNDRV_PCM_STREAM_LAST + 1]; + struct snd_soc_dapm_widget *c2c_widget[SNDRV_PCM_STREAM_LAST + 1]; long pmdown_time; @@ -1140,15 +1143,10 @@ struct snd_soc_pcm_runtime { * dais = cpu_dai + codec_dai * see * soc_new_pcm_runtime() - * asoc_rtd_to_cpu() - * asoc_rtd_to_codec() + * snd_soc_rtd_to_cpu() + * snd_soc_rtd_to_codec() */ struct snd_soc_dai **dais; - unsigned int num_codecs; - unsigned int num_cpus; - - struct snd_soc_dapm_widget *playback_widget; - struct snd_soc_dapm_widget *capture_widget; struct delayed_work delayed_work; void (*close_delayed_work_func)(struct snd_soc_pcm_runtime *rtd); @@ -1156,24 +1154,34 @@ struct snd_soc_pcm_runtime { struct dentry *debugfs_dpcm_root; #endif - unsigned int num; /* 0-based and monotonic increasing */ + unsigned int id; /* 0-based and monotonic increasing */ struct list_head list; /* rtd list of the soc card */ /* function mark */ struct snd_pcm_substream *mark_startup; + struct snd_pcm_substream *mark_hw_params; + struct snd_pcm_substream *mark_trigger; + struct snd_compr_stream *mark_compr_startup; /* bit field */ unsigned int pop_wait:1; unsigned int fe_compr:1; /* for Dynamic PCM */ + unsigned int initialized:1; + /* CPU/Codec/Platform */ int num_components; - struct snd_soc_component *components[]; /* CPU/Codec/Platform */ + struct snd_soc_component *components[] __counted_by(num_components); }; + /* see soc_new_pcm_runtime() */ -#define asoc_rtd_to_cpu(rtd, n) (rtd)->dais[n] -#define asoc_rtd_to_codec(rtd, n) (rtd)->dais[n + (rtd)->num_cpus] -#define asoc_substream_to_rtd(substream) \ - (struct snd_soc_pcm_runtime *)snd_pcm_substream_chip(substream) +#define snd_soc_rtd_to_cpu(rtd, n) (rtd)->dais[n] +#define snd_soc_rtd_to_codec(rtd, n) (rtd)->dais[n + (rtd)->dai_link->num_cpus] + +static inline struct snd_soc_pcm_runtime * +snd_soc_substream_to_rtd(const struct snd_pcm_substream *substream) +{ + return snd_pcm_substream_chip(substream); +} #define for_each_rtd_components(rtd, i, component) \ for ((i) = 0, component = NULL; \ @@ -1181,31 +1189,34 @@ struct snd_soc_pcm_runtime { (i)++) #define for_each_rtd_cpu_dais(rtd, i, dai) \ for ((i) = 0; \ - ((i) < rtd->num_cpus) && ((dai) = asoc_rtd_to_cpu(rtd, i)); \ + ((i) < rtd->dai_link->num_cpus) && ((dai) = snd_soc_rtd_to_cpu(rtd, i)); \ (i)++) -#define for_each_rtd_cpu_dais_rollback(rtd, i, dai) \ - for (; (--(i) >= 0) && ((dai) = asoc_rtd_to_cpu(rtd, i));) #define for_each_rtd_codec_dais(rtd, i, dai) \ for ((i) = 0; \ - ((i) < rtd->num_codecs) && ((dai) = asoc_rtd_to_codec(rtd, i)); \ + ((i) < rtd->dai_link->num_codecs) && ((dai) = snd_soc_rtd_to_codec(rtd, i)); \ (i)++) -#define for_each_rtd_codec_dais_rollback(rtd, i, dai) \ - for (; (--(i) >= 0) && ((dai) = asoc_rtd_to_codec(rtd, i));) #define for_each_rtd_dais(rtd, i, dai) \ for ((i) = 0; \ - ((i) < (rtd)->num_cpus + (rtd)->num_codecs) && \ + ((i) < (rtd)->dai_link->num_cpus + (rtd)->dai_link->num_codecs) && \ ((dai) = (rtd)->dais[i]); \ (i)++) -#define for_each_rtd_dais_rollback(rtd, i, dai) \ - for (; (--(i) >= 0) && ((dai) = (rtd)->dais[i]);) +#define for_each_rtd_dais_reverse(rtd, i, dai) \ + for ((i) = (rtd)->dai_link->num_cpus + (rtd)->dai_link->num_codecs - 1; \ + (i) >= 0 && ((dai) = (rtd)->dais[i]); \ + (i)--) +#define for_each_rtd_ch_maps(rtd, i, ch_maps) for_each_link_ch_maps(rtd->dai_link, i, ch_maps) void snd_soc_close_delayed_work(struct snd_soc_pcm_runtime *rtd); /* mixer control */ struct soc_mixer_control { - int min, max, platform_max; + /* Minimum and maximum specified as written to the hardware */ + int min, max; + /* Limited maximum value specified as presented through the control */ + int platform_max; int reg, rreg; unsigned int shift, rshift; + u32 num_channels; unsigned int sign_bit; unsigned int invert:1; unsigned int autodisable:1; @@ -1253,7 +1264,7 @@ struct soc_enum { #endif }; -static inline bool snd_soc_volsw_is_stereo(struct soc_mixer_control *mc) +static inline bool snd_soc_volsw_is_stereo(const struct soc_mixer_control *mc) { if (mc->reg == mc->rreg && mc->shift == mc->rshift) return false; @@ -1265,7 +1276,7 @@ static inline bool snd_soc_volsw_is_stereo(struct soc_mixer_control *mc) return true; } -static inline unsigned int snd_soc_enum_val_to_item(struct soc_enum *e, +static inline unsigned int snd_soc_enum_val_to_item(const struct soc_enum *e, unsigned int val) { unsigned int i; @@ -1280,7 +1291,7 @@ static inline unsigned int snd_soc_enum_val_to_item(struct soc_enum *e, return 0; } -static inline unsigned int snd_soc_enum_item_to_val(struct soc_enum *e, +static inline unsigned int snd_soc_enum_item_to_val(const struct soc_enum *e, unsigned int item) { if (!e->values) @@ -1312,6 +1323,7 @@ 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_pin_switches(struct snd_soc_card *card, const char *prop); int snd_soc_of_get_slot_mask(struct device_node *np, const char *prop_name, unsigned int *mask); @@ -1337,32 +1349,58 @@ void snd_soc_of_parse_audio_prefix(struct snd_soc_card *card, int snd_soc_of_parse_audio_routing(struct snd_soc_card *card, const char *propname); int snd_soc_of_parse_aux_devs(struct snd_soc_card *card, const char *propname); -unsigned int snd_soc_of_parse_daifmt(struct device_node *np, - const char *prefix, - struct device_node **bitclkmaster, - struct device_node **framemaster); + +unsigned int snd_soc_daifmt_clock_provider_flipped(unsigned int dai_fmt); +unsigned int snd_soc_daifmt_clock_provider_from_bitmap(unsigned int bit_frame); + +unsigned int snd_soc_daifmt_parse_format(struct device_node *np, const char *prefix); +unsigned int snd_soc_daifmt_parse_clock_provider_raw(struct device_node *np, + const char *prefix, + struct device_node **bitclkmaster, + struct device_node **framemaster); +#define snd_soc_daifmt_parse_clock_provider_as_bitmap(np, prefix) \ + snd_soc_daifmt_parse_clock_provider_raw(np, prefix, NULL, NULL) +#define snd_soc_daifmt_parse_clock_provider_as_phandle \ + snd_soc_daifmt_parse_clock_provider_raw +#define snd_soc_daifmt_parse_clock_provider_as_flag(np, prefix) \ + snd_soc_daifmt_clock_provider_from_bitmap( \ + snd_soc_daifmt_parse_clock_provider_as_bitmap(np, prefix)) + +int snd_soc_get_stream_cpu(const struct snd_soc_dai_link *dai_link, int stream); +int snd_soc_get_dlc(const struct of_phandle_args *args, + struct snd_soc_dai_link_component *dlc); +int snd_soc_of_get_dlc(struct device_node *of_node, + struct of_phandle_args *args, + struct snd_soc_dai_link_component *dlc, + int index); int snd_soc_get_dai_id(struct device_node *ep); -int snd_soc_get_dai_name(struct of_phandle_args *args, +int snd_soc_get_dai_name(const struct of_phandle_args *args, const char **dai_name); int snd_soc_of_get_dai_name(struct device_node *of_node, - const char **dai_name); + const char **dai_name, int index); int snd_soc_of_get_dai_link_codecs(struct device *dev, struct device_node *of_node, struct snd_soc_dai_link *dai_link); void snd_soc_of_put_dai_link_codecs(struct snd_soc_dai_link *dai_link); - -int snd_soc_add_pcm_runtime(struct snd_soc_card *card, - struct snd_soc_dai_link *dai_link); +int snd_soc_of_get_dai_link_cpus(struct device *dev, + struct device_node *of_node, + struct snd_soc_dai_link *dai_link); +void snd_soc_of_put_dai_link_cpus(struct snd_soc_dai_link *dai_link); + +int snd_soc_add_pcm_runtimes(struct snd_soc_card *card, + struct snd_soc_dai_link *dai_link, + int num_dai_link); void snd_soc_remove_pcm_runtime(struct snd_soc_card *card, struct snd_soc_pcm_runtime *rtd); +void snd_soc_dlc_use_cpu_as_platform(struct snd_soc_dai_link_component *platforms, + struct snd_soc_dai_link_component *cpus); +struct of_phandle_args *snd_soc_copy_dai_args(struct device *dev, + const struct of_phandle_args *args); +struct snd_soc_dai *snd_soc_get_dai_via_args(const struct of_phandle_args *dai_args); struct snd_soc_dai *snd_soc_register_dai(struct snd_soc_component *component, struct snd_soc_dai_driver *dai_drv, bool legacy_dai_naming); -struct snd_soc_dai *devm_snd_soc_register_dai(struct device *dev, - struct snd_soc_component *component, - struct snd_soc_dai_driver *dai_drv, - bool legacy_dai_naming); void snd_soc_unregister_dai(struct snd_soc_dai *dai); struct snd_soc_dai *snd_soc_find_dai( @@ -1385,13 +1423,17 @@ int snd_soc_fixup_dai_links_platform_name(struct snd_soc_card *card, /* set platform name for each dailink */ for_each_card_prelinks(card, i, dai_link) { - name = devm_kstrdup(card->dev, platform_name, GFP_KERNEL); - if (!name) - return -ENOMEM; + /* only single platform is supported for now */ + if (dai_link->num_platforms != 1) + return -EINVAL; if (!dai_link->platforms) return -EINVAL; + name = devm_kstrdup(card->dev, platform_name, GFP_KERNEL); + if (!name) + return -ENOMEM; + /* only single platform is supported for now */ dai_link->platforms->name = name; } @@ -1405,18 +1447,114 @@ 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) +/* + * DAPM helper functions + */ +enum snd_soc_dapm_subclass { + SND_SOC_DAPM_CLASS_ROOT = 0, + SND_SOC_DAPM_CLASS_RUNTIME = 1, +}; + +static inline void _snd_soc_dapm_mutex_lock_root_c(struct snd_soc_card *card) +{ + mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_ROOT); +} + +static inline void _snd_soc_dapm_mutex_lock_c(struct snd_soc_card *card) { - mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); + mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); } -static inline void snd_soc_dapm_mutex_unlock(struct snd_soc_dapm_context *dapm) +static inline void _snd_soc_dapm_mutex_unlock_c(struct snd_soc_card *card) { - mutex_unlock(&dapm->card->dapm_mutex); + mutex_unlock(&card->dapm_mutex); } +static inline void _snd_soc_dapm_mutex_assert_held_c(struct snd_soc_card *card) +{ + lockdep_assert_held(&card->dapm_mutex); +} + +static inline void _snd_soc_dapm_mutex_lock_root_d(struct snd_soc_dapm_context *dapm) +{ + _snd_soc_dapm_mutex_lock_root_c(dapm->card); +} + +static inline void _snd_soc_dapm_mutex_lock_d(struct snd_soc_dapm_context *dapm) +{ + _snd_soc_dapm_mutex_lock_c(dapm->card); +} + +static inline void _snd_soc_dapm_mutex_unlock_d(struct snd_soc_dapm_context *dapm) +{ + _snd_soc_dapm_mutex_unlock_c(dapm->card); +} + +static inline void _snd_soc_dapm_mutex_assert_held_d(struct snd_soc_dapm_context *dapm) +{ + _snd_soc_dapm_mutex_assert_held_c(dapm->card); +} + +#define snd_soc_dapm_mutex_lock_root(x) _Generic((x), \ + struct snd_soc_card * : _snd_soc_dapm_mutex_lock_root_c, \ + struct snd_soc_dapm_context * : _snd_soc_dapm_mutex_lock_root_d)(x) +#define snd_soc_dapm_mutex_lock(x) _Generic((x), \ + struct snd_soc_card * : _snd_soc_dapm_mutex_lock_c, \ + struct snd_soc_dapm_context * : _snd_soc_dapm_mutex_lock_d)(x) +#define snd_soc_dapm_mutex_unlock(x) _Generic((x), \ + struct snd_soc_card * : _snd_soc_dapm_mutex_unlock_c, \ + struct snd_soc_dapm_context * : _snd_soc_dapm_mutex_unlock_d)(x) +#define snd_soc_dapm_mutex_assert_held(x) _Generic((x), \ + struct snd_soc_card * : _snd_soc_dapm_mutex_assert_held_c, \ + struct snd_soc_dapm_context * : _snd_soc_dapm_mutex_assert_held_d)(x) + +/* + * PCM helper functions + */ +static inline void _snd_soc_dpcm_mutex_lock_c(struct snd_soc_card *card) +{ + mutex_lock_nested(&card->pcm_mutex, card->pcm_subclass); +} + +static inline void _snd_soc_dpcm_mutex_unlock_c(struct snd_soc_card *card) +{ + mutex_unlock(&card->pcm_mutex); +} + +static inline void _snd_soc_dpcm_mutex_assert_held_c(struct snd_soc_card *card) +{ + lockdep_assert_held(&card->pcm_mutex); +} + +static inline void _snd_soc_dpcm_mutex_lock_r(struct snd_soc_pcm_runtime *rtd) +{ + _snd_soc_dpcm_mutex_lock_c(rtd->card); +} + +static inline void _snd_soc_dpcm_mutex_unlock_r(struct snd_soc_pcm_runtime *rtd) +{ + _snd_soc_dpcm_mutex_unlock_c(rtd->card); +} + +static inline void _snd_soc_dpcm_mutex_assert_held_r(struct snd_soc_pcm_runtime *rtd) +{ + _snd_soc_dpcm_mutex_assert_held_c(rtd->card); +} + +#define snd_soc_dpcm_mutex_lock(x) _Generic((x), \ + struct snd_soc_card * : _snd_soc_dpcm_mutex_lock_c, \ + struct snd_soc_pcm_runtime * : _snd_soc_dpcm_mutex_lock_r)(x) + +#define snd_soc_dpcm_mutex_unlock(x) _Generic((x), \ + struct snd_soc_card * : _snd_soc_dpcm_mutex_unlock_c, \ + struct snd_soc_pcm_runtime * : _snd_soc_dpcm_mutex_unlock_r)(x) + +#define snd_soc_dpcm_mutex_assert_held(x) _Generic((x), \ + struct snd_soc_card * : _snd_soc_dpcm_mutex_assert_held_c, \ + struct snd_soc_pcm_runtime * : _snd_soc_dpcm_mutex_assert_held_r)(x) + #include <sound/soc-component.h> #include <sound/soc-card.h> +#include <sound/soc-jack.h> #endif |