diff options
| -rw-r--r-- | include/sound/soc.h | 41 | ||||
| -rw-r--r-- | sound/soc/soc-core.c | 237 |
2 files changed, 174 insertions, 104 deletions
diff --git a/include/sound/soc.h b/include/sound/soc.h index a72af6327987..b13eecbaea78 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h | |||
| @@ -13,6 +13,7 @@ | |||
| 13 | #ifndef __LINUX_SND_SOC_H | 13 | #ifndef __LINUX_SND_SOC_H |
| 14 | #define __LINUX_SND_SOC_H | 14 | #define __LINUX_SND_SOC_H |
| 15 | 15 | ||
| 16 | #include <linux/of.h> | ||
| 16 | #include <linux/platform_device.h> | 17 | #include <linux/platform_device.h> |
| 17 | #include <linux/types.h> | 18 | #include <linux/types.h> |
| 18 | #include <linux/notifier.h> | 19 | #include <linux/notifier.h> |
| @@ -630,6 +631,26 @@ struct snd_soc_compr_ops { | |||
| 630 | int (*trigger)(struct snd_compr_stream *); | 631 | int (*trigger)(struct snd_compr_stream *); |
| 631 | }; | 632 | }; |
| 632 | 633 | ||
| 634 | /* component interface */ | ||
| 635 | struct snd_soc_component_driver { | ||
| 636 | const char *name; | ||
| 637 | |||
| 638 | /* DT */ | ||
| 639 | int (*of_xlate_dai_name)(struct snd_soc_component *component, | ||
| 640 | struct of_phandle_args *args, | ||
| 641 | const char **dai_name); | ||
| 642 | }; | ||
| 643 | |||
| 644 | struct snd_soc_component { | ||
| 645 | const char *name; | ||
| 646 | int id; | ||
| 647 | int num_dai; | ||
| 648 | struct device *dev; | ||
| 649 | struct list_head list; | ||
| 650 | |||
| 651 | const struct snd_soc_component_driver *driver; | ||
| 652 | }; | ||
| 653 | |||
| 633 | /* SoC Audio Codec device */ | 654 | /* SoC Audio Codec device */ |
| 634 | struct snd_soc_codec { | 655 | struct snd_soc_codec { |
| 635 | const char *name; | 656 | const char *name; |
| @@ -670,6 +691,9 @@ struct snd_soc_codec { | |||
| 670 | struct mutex cache_rw_mutex; | 691 | struct mutex cache_rw_mutex; |
| 671 | int val_bytes; | 692 | int val_bytes; |
| 672 | 693 | ||
| 694 | /* component */ | ||
| 695 | struct snd_soc_component component; | ||
| 696 | |||
| 673 | /* dapm */ | 697 | /* dapm */ |
| 674 | struct snd_soc_dapm_context dapm; | 698 | struct snd_soc_dapm_context dapm; |
| 675 | unsigned int ignore_pmdown_time:1; /* pmdown_time is ignored at stop */ | 699 | unsigned int ignore_pmdown_time:1; /* pmdown_time is ignored at stop */ |
| @@ -688,6 +712,7 @@ struct snd_soc_codec_driver { | |||
| 688 | int (*remove)(struct snd_soc_codec *); | 712 | int (*remove)(struct snd_soc_codec *); |
| 689 | int (*suspend)(struct snd_soc_codec *); | 713 | int (*suspend)(struct snd_soc_codec *); |
| 690 | int (*resume)(struct snd_soc_codec *); | 714 | int (*resume)(struct snd_soc_codec *); |
| 715 | struct snd_soc_component_driver component_driver; | ||
| 691 | 716 | ||
| 692 | /* Default control and setup, added after probe() is run */ | 717 | /* Default control and setup, added after probe() is run */ |
| 693 | const struct snd_kcontrol_new *controls; | 718 | const struct snd_kcontrol_new *controls; |
| @@ -801,20 +826,6 @@ struct snd_soc_platform { | |||
| 801 | #endif | 826 | #endif |
| 802 | }; | 827 | }; |
| 803 | 828 | ||
| 804 | struct snd_soc_component_driver { | ||
| 805 | const char *name; | ||
| 806 | }; | ||
| 807 | |||
| 808 | struct snd_soc_component { | ||
| 809 | const char *name; | ||
| 810 | int id; | ||
| 811 | int num_dai; | ||
| 812 | struct device *dev; | ||
| 813 | struct list_head list; | ||
| 814 | |||
| 815 | const struct snd_soc_component_driver *driver; | ||
| 816 | }; | ||
| 817 | |||
| 818 | struct snd_soc_dai_link { | 829 | struct snd_soc_dai_link { |
| 819 | /* config - must be set by machine driver */ | 830 | /* config - must be set by machine driver */ |
| 820 | const char *name; /* Codec name */ | 831 | const char *name; /* Codec name */ |
| @@ -1145,6 +1156,8 @@ int snd_soc_of_parse_audio_routing(struct snd_soc_card *card, | |||
| 1145 | const char *propname); | 1156 | const char *propname); |
| 1146 | unsigned int snd_soc_of_parse_daifmt(struct device_node *np, | 1157 | unsigned int snd_soc_of_parse_daifmt(struct device_node *np, |
| 1147 | const char *prefix); | 1158 | const char *prefix); |
| 1159 | int snd_soc_of_get_dai_name(struct device_node *of_node, | ||
| 1160 | const char **dai_name); | ||
| 1148 | 1161 | ||
| 1149 | #include <sound/soc-dai.h> | 1162 | #include <sound/soc-dai.h> |
| 1150 | 1163 | ||
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 16a3930c6375..67cfb5f5ca96 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c | |||
| @@ -3996,6 +3996,112 @@ static void snd_soc_unregister_dais(struct device *dev, size_t count) | |||
| 3996 | } | 3996 | } |
| 3997 | 3997 | ||
| 3998 | /** | 3998 | /** |
| 3999 | * snd_soc_register_component - Register a component with the ASoC core | ||
| 4000 | * | ||
| 4001 | */ | ||
| 4002 | static int | ||
| 4003 | __snd_soc_register_component(struct device *dev, | ||
| 4004 | struct snd_soc_component *cmpnt, | ||
| 4005 | const struct snd_soc_component_driver *cmpnt_drv, | ||
| 4006 | struct snd_soc_dai_driver *dai_drv, | ||
| 4007 | int num_dai, bool allow_single_dai) | ||
| 4008 | { | ||
| 4009 | int ret; | ||
| 4010 | |||
| 4011 | dev_dbg(dev, "component register %s\n", dev_name(dev)); | ||
| 4012 | |||
| 4013 | if (!cmpnt) { | ||
| 4014 | dev_err(dev, "ASoC: Failed to connecting component\n"); | ||
| 4015 | return -ENOMEM; | ||
| 4016 | } | ||
| 4017 | |||
| 4018 | cmpnt->name = fmt_single_name(dev, &cmpnt->id); | ||
| 4019 | if (!cmpnt->name) { | ||
| 4020 | dev_err(dev, "ASoC: Failed to simplifying name\n"); | ||
| 4021 | return -ENOMEM; | ||
| 4022 | } | ||
| 4023 | |||
| 4024 | cmpnt->dev = dev; | ||
| 4025 | cmpnt->driver = cmpnt_drv; | ||
| 4026 | cmpnt->num_dai = num_dai; | ||
| 4027 | |||
| 4028 | /* | ||
| 4029 | * snd_soc_register_dai() uses fmt_single_name(), and | ||
| 4030 | * snd_soc_register_dais() uses fmt_multiple_name() | ||
| 4031 | * for dai->name which is used for name based matching | ||
| 4032 | * | ||
| 4033 | * this function is used from cpu/codec. | ||
| 4034 | * allow_single_dai flag can ignore "codec" driver reworking | ||
| 4035 | * since it had been used snd_soc_register_dais(), | ||
| 4036 | */ | ||
| 4037 | if ((1 == num_dai) && allow_single_dai) | ||
| 4038 | ret = snd_soc_register_dai(dev, dai_drv); | ||
| 4039 | else | ||
| 4040 | ret = snd_soc_register_dais(dev, dai_drv, num_dai); | ||
| 4041 | if (ret < 0) { | ||
| 4042 | dev_err(dev, "ASoC: Failed to regster DAIs: %d\n", ret); | ||
| 4043 | goto error_component_name; | ||
| 4044 | } | ||
| 4045 | |||
| 4046 | mutex_lock(&client_mutex); | ||
| 4047 | list_add(&cmpnt->list, &component_list); | ||
| 4048 | mutex_unlock(&client_mutex); | ||
| 4049 | |||
| 4050 | dev_dbg(cmpnt->dev, "ASoC: Registered component '%s'\n", cmpnt->name); | ||
| 4051 | |||
| 4052 | return ret; | ||
| 4053 | |||
| 4054 | error_component_name: | ||
| 4055 | kfree(cmpnt->name); | ||
| 4056 | |||
| 4057 | return ret; | ||
| 4058 | } | ||
| 4059 | |||
| 4060 | int snd_soc_register_component(struct device *dev, | ||
| 4061 | const struct snd_soc_component_driver *cmpnt_drv, | ||
| 4062 | struct snd_soc_dai_driver *dai_drv, | ||
| 4063 | int num_dai) | ||
| 4064 | { | ||
| 4065 | struct snd_soc_component *cmpnt; | ||
| 4066 | |||
| 4067 | cmpnt = devm_kzalloc(dev, sizeof(*cmpnt), GFP_KERNEL); | ||
| 4068 | if (!cmpnt) { | ||
| 4069 | dev_err(dev, "ASoC: Failed to allocate memory\n"); | ||
| 4070 | return -ENOMEM; | ||
| 4071 | } | ||
| 4072 | |||
| 4073 | return __snd_soc_register_component(dev, cmpnt, cmpnt_drv, | ||
| 4074 | dai_drv, num_dai, true); | ||
| 4075 | } | ||
| 4076 | EXPORT_SYMBOL_GPL(snd_soc_register_component); | ||
| 4077 | |||
| 4078 | /** | ||
| 4079 | * snd_soc_unregister_component - Unregister a component from the ASoC core | ||
| 4080 | * | ||
| 4081 | */ | ||
| 4082 | void snd_soc_unregister_component(struct device *dev) | ||
| 4083 | { | ||
| 4084 | struct snd_soc_component *cmpnt; | ||
| 4085 | |||
| 4086 | list_for_each_entry(cmpnt, &component_list, list) { | ||
| 4087 | if (dev == cmpnt->dev) | ||
| 4088 | goto found; | ||
| 4089 | } | ||
| 4090 | return; | ||
| 4091 | |||
| 4092 | found: | ||
| 4093 | snd_soc_unregister_dais(dev, cmpnt->num_dai); | ||
| 4094 | |||
| 4095 | mutex_lock(&client_mutex); | ||
| 4096 | list_del(&cmpnt->list); | ||
| 4097 | mutex_unlock(&client_mutex); | ||
| 4098 | |||
| 4099 | dev_dbg(dev, "ASoC: Unregistered component '%s'\n", cmpnt->name); | ||
| 4100 | kfree(cmpnt->name); | ||
