diff options
Diffstat (limited to 'sound/soc/soc-core.c')
-rw-r--r-- | sound/soc/soc-core.c | 86 |
1 files changed, 79 insertions, 7 deletions
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 754e3ef8d7ae..921622a01944 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c | |||
@@ -34,6 +34,7 @@ | |||
34 | #include <linux/ctype.h> | 34 | #include <linux/ctype.h> |
35 | #include <linux/slab.h> | 35 | #include <linux/slab.h> |
36 | #include <linux/of.h> | 36 | #include <linux/of.h> |
37 | #include <linux/of_graph.h> | ||
37 | #include <linux/dmi.h> | 38 | #include <linux/dmi.h> |
38 | #include <sound/core.h> | 39 | #include <sound/core.h> |
39 | #include <sound/jack.h> | 40 | #include <sound/jack.h> |
@@ -68,6 +69,20 @@ static int pmdown_time = 5000; | |||
68 | module_param(pmdown_time, int, 0); | 69 | module_param(pmdown_time, int, 0); |
69 | MODULE_PARM_DESC(pmdown_time, "DAPM stream powerdown time (msecs)"); | 70 | MODULE_PARM_DESC(pmdown_time, "DAPM stream powerdown time (msecs)"); |
70 | 71 | ||
72 | /* If a DMI filed contain strings in this blacklist (e.g. | ||
73 | * "Type2 - Board Manufacturer" or "Type1 - TBD by OEM"), it will be taken | ||
74 | * as invalid and dropped when setting the card long name from DMI info. | ||
75 | */ | ||
76 | static const char * const dmi_blacklist[] = { | ||
77 | "To be filled by OEM", | ||
78 | "TBD by OEM", | ||
79 | "Default String", | ||
80 | "Board Manufacturer", | ||
81 | "Board Vendor Name", | ||
82 | "Board Product Name", | ||
83 | NULL, /* terminator */ | ||
84 | }; | ||
85 | |||
71 | /* returns the minimum number of bytes needed to represent | 86 | /* returns the minimum number of bytes needed to represent |
72 | * a particular given value */ | 87 | * a particular given value */ |
73 | static int min_bytes_needed(unsigned long val) | 88 | static int min_bytes_needed(unsigned long val) |
@@ -1933,6 +1948,22 @@ static void cleanup_dmi_name(char *name) | |||
1933 | name[j] = '\0'; | 1948 | name[j] = '\0'; |
1934 | } | 1949 | } |
1935 | 1950 | ||
1951 | /* Check if a DMI field is valid, i.e. not containing any string | ||
1952 | * in the black list. | ||
1953 | */ | ||
1954 | static int is_dmi_valid(const char *field) | ||
1955 | { | ||
1956 | int i = 0; | ||
1957 | |||
1958 | while (dmi_blacklist[i]) { | ||
1959 | if (strstr(field, dmi_blacklist[i])) | ||
1960 | return 0; | ||
1961 | i++; | ||
1962 | } | ||
1963 | |||
1964 | return 1; | ||
1965 | } | ||
1966 | |||
1936 | /** | 1967 | /** |
1937 | * snd_soc_set_dmi_name() - Register DMI names to card | 1968 | * snd_soc_set_dmi_name() - Register DMI names to card |
1938 | * @card: The card to register DMI names | 1969 | * @card: The card to register DMI names |
@@ -1975,17 +2006,18 @@ int snd_soc_set_dmi_name(struct snd_soc_card *card, const char *flavour) | |||
1975 | 2006 | ||
1976 | /* make up dmi long name as: vendor.product.version.board */ | 2007 | /* make up dmi long name as: vendor.product.version.board */ |
1977 | vendor = dmi_get_system_info(DMI_BOARD_VENDOR); | 2008 | vendor = dmi_get_system_info(DMI_BOARD_VENDOR); |
1978 | if (!vendor) { | 2009 | if (!vendor || !is_dmi_valid(vendor)) { |
1979 | dev_warn(card->dev, "ASoC: no DMI vendor name!\n"); | 2010 | dev_warn(card->dev, "ASoC: no DMI vendor name!\n"); |
1980 | return 0; | 2011 | return 0; |
1981 | } | 2012 | } |
1982 | 2013 | ||
2014 | |||
1983 | snprintf(card->dmi_longname, sizeof(card->snd_card->longname), | 2015 | snprintf(card->dmi_longname, sizeof(card->snd_card->longname), |
1984 | "%s", vendor); | 2016 | "%s", vendor); |
1985 | cleanup_dmi_name(card->dmi_longname); | 2017 | cleanup_dmi_name(card->dmi_longname); |
1986 | 2018 | ||
1987 | product = dmi_get_system_info(DMI_PRODUCT_NAME); | 2019 | product = dmi_get_system_info(DMI_PRODUCT_NAME); |
1988 | if (product) { | 2020 | if (product && is_dmi_valid(product)) { |
1989 | len = strlen(card->dmi_longname); | 2021 | len = strlen(card->dmi_longname); |
1990 | snprintf(card->dmi_longname + len, | 2022 | snprintf(card->dmi_longname + len, |
1991 | longname_buf_size - len, | 2023 | longname_buf_size - len, |
@@ -1999,7 +2031,7 @@ int snd_soc_set_dmi_name(struct snd_soc_card *card, const char *flavour) | |||
1999 | * name in the product version field | 2031 | * name in the product version field |
2000 | */ | 2032 | */ |
2001 | product_version = dmi_get_system_info(DMI_PRODUCT_VERSION); | 2033 | product_version = dmi_get_system_info(DMI_PRODUCT_VERSION); |
2002 | if (product_version) { | 2034 | if (product_version && is_dmi_valid(product_version)) { |
2003 | len = strlen(card->dmi_longname); | 2035 | len = strlen(card->dmi_longname); |
2004 | snprintf(card->dmi_longname + len, | 2036 | snprintf(card->dmi_longname + len, |
2005 | longname_buf_size - len, | 2037 | longname_buf_size - len, |
@@ -2012,7 +2044,7 @@ int snd_soc_set_dmi_name(struct snd_soc_card *card, const char *flavour) | |||
2012 | } | 2044 | } |
2013 | 2045 | ||
2014 | board = dmi_get_system_info(DMI_BOARD_NAME); | 2046 | board = dmi_get_system_info(DMI_BOARD_NAME); |
2015 | if (board) { | 2047 | if (board && is_dmi_valid(board)) { |
2016 | len = strlen(card->dmi_longname); | 2048 | len = strlen(card->dmi_longname); |
2017 | snprintf(card->dmi_longname + len, | 2049 | snprintf(card->dmi_longname + len, |
2018 | longname_buf_size - len, | 2050 | longname_buf_size - len, |
@@ -3961,11 +3993,15 @@ unsigned int snd_soc_of_parse_daifmt(struct device_node *np, | |||
3961 | prefix = ""; | 3993 | prefix = ""; |
3962 | 3994 | ||
3963 | /* | 3995 | /* |
3964 | * check "[prefix]format = xxx" | 3996 | * check "dai-format = xxx" |
3997 | * or "[prefix]format = xxx" | ||
3965 | * SND_SOC_DAIFMT_FORMAT_MASK area | 3998 | * SND_SOC_DAIFMT_FORMAT_MASK area |
3966 | */ | 3999 | */ |
3967 | snprintf(prop, sizeof(prop), "%sformat", prefix); | 4000 | ret = of_property_read_string(np, "dai-format", &str); |
3968 | ret = of_property_read_string(np, prop, &str); | 4001 | if (ret < 0) { |
4002 | snprintf(prop, sizeof(prop), "%sformat", prefix); | ||
4003 | ret = of_property_read_string(np, prop, &str); | ||
4004 | } | ||
3969 | if (ret == 0) { | 4005 | if (ret == 0) { |
3970 | for (i = 0; i < ARRAY_SIZE(of_fmt_table); i++) { | 4006 | for (i = 0; i < ARRAY_SIZE(of_fmt_table); i++) { |
3971 | if (strcmp(str, of_fmt_table[i].name) == 0) { | 4007 | if (strcmp(str, of_fmt_table[i].name) == 0) { |
@@ -4045,6 +4081,42 @@ unsigned int snd_soc_of_parse_daifmt(struct device_node *np, | |||
4045 | } | 4081 | } |
4046 | EXPORT_SYMBOL_GPL(snd_soc_of_parse_daifmt); | 4082 | EXPORT_SYMBOL_GPL(snd_soc_of_parse_daifmt); |
4047 | 4083 | ||
4084 | int snd_soc_get_dai_id(struct device_node *ep) | ||
4085 | { | ||
4086 | struct snd_soc_component *pos; | ||
4087 | struct device_node *node; | ||
4088 | int ret; | ||
4089 | |||
4090 | node = of_graph_get_port_parent(ep); | ||
4091 | |||
4092 | /* | ||
4093 | * For example HDMI case, HDMI has video/sound port, | ||
4094 | * but ALSA SoC needs sound port number only. | ||
4095 | * Thus counting HDMI DT port/endpoint doesn't work. | ||
4096 | * Then, it should have .of_xlate_dai_id | ||
4097 | */ | ||
4098 | ret = -ENOTSUPP; | ||
4099 | mutex_lock(&client_mutex); | ||
4100 | list_for_each_entry(pos, &component_list, list) { | ||
4101 | struct device_node *component_of_node = pos->dev->of_node; | ||
4102 | |||
4103 | if (!component_of_node && pos->dev->parent) | ||
4104 | component_of_node = pos->dev->parent->of_node; | ||
4105 | |||
4106 | if (component_of_node != node) | ||
4107 | continue; | ||
4108 | |||
4109 | if (pos->driver->of_xlate_dai_id) | ||
4110 | ret = pos->driver->of_xlate_dai_id(pos, ep); | ||
4111 | |||
4112 | break; | ||
4113 | } | ||
4114 | mutex_unlock(&client_mutex); | ||
4115 | |||
4116 | return ret; | ||
4117 | } | ||
4118 | EXPORT_SYMBOL_GPL(snd_soc_get_dai_id); | ||
4119 | |||
4048 | int snd_soc_get_dai_name(struct of_phandle_args *args, | 4120 | int snd_soc_get_dai_name(struct of_phandle_args *args, |
4049 | const char **dai_name) | 4121 | const char **dai_name) |
4050 | { | 4122 | { |