diff options
Diffstat (limited to 'sound/soc/soc-core.c')
-rw-r--r-- | sound/soc/soc-core.c | 328 |
1 files changed, 264 insertions, 64 deletions
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index b37ee8077ed1..f219b2f7ee68 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c | |||
@@ -812,13 +812,15 @@ static int soc_bind_dai_link(struct snd_soc_card *card, int num) | |||
812 | 812 | ||
813 | /* Find CPU DAI from registered DAIs*/ | 813 | /* Find CPU DAI from registered DAIs*/ |
814 | list_for_each_entry(cpu_dai, &dai_list, list) { | 814 | list_for_each_entry(cpu_dai, &dai_list, list) { |
815 | if (dai_link->cpu_dai_of_node) { | 815 | if (dai_link->cpu_of_node && |
816 | if (cpu_dai->dev->of_node != dai_link->cpu_dai_of_node) | 816 | (cpu_dai->dev->of_node != dai_link->cpu_of_node)) |
817 | continue; | 817 | continue; |
818 | } else { | 818 | if (dai_link->cpu_name && |
819 | if (strcmp(cpu_dai->name, dai_link->cpu_dai_name)) | 819 | strcmp(dev_name(cpu_dai->dev), dai_link->cpu_name)) |
820 | continue; | 820 | continue; |
821 | } | 821 | if (dai_link->cpu_dai_name && |
822 | strcmp(cpu_dai->name, dai_link->cpu_dai_name)) | ||
823 | continue; | ||
822 | 824 | ||
823 | rtd->cpu_dai = cpu_dai; | 825 | rtd->cpu_dai = cpu_dai; |
824 | } | 826 | } |
@@ -896,6 +898,28 @@ static int soc_bind_dai_link(struct snd_soc_card *card, int num) | |||
896 | return 0; | 898 | return 0; |
897 | } | 899 | } |
898 | 900 | ||
901 | static int soc_remove_platform(struct snd_soc_platform *platform) | ||
902 | { | ||
903 | int ret; | ||
904 | |||
905 | if (platform->driver->remove) { | ||
906 | ret = platform->driver->remove(platform); | ||
907 | if (ret < 0) | ||
908 | pr_err("asoc: failed to remove %s: %d\n", | ||
909 | platform->name, ret); | ||
910 | } | ||
911 | |||
912 | /* Make sure all DAPM widgets are freed */ | ||
913 | snd_soc_dapm_free(&platform->dapm); | ||
914 | |||
915 | soc_cleanup_platform_debugfs(platform); | ||
916 | platform->probed = 0; | ||
917 | list_del(&platform->card_list); | ||
918 | module_put(platform->dev->driver->owner); | ||
919 | |||
920 | return 0; | ||
921 | } | ||
922 | |||
899 | static void soc_remove_codec(struct snd_soc_codec *codec) | 923 | static void soc_remove_codec(struct snd_soc_codec *codec) |
900 | { | 924 | { |
901 | int err; | 925 | int err; |
@@ -917,11 +941,9 @@ static void soc_remove_codec(struct snd_soc_codec *codec) | |||
917 | module_put(codec->dev->driver->owner); | 941 | module_put(codec->dev->driver->owner); |
918 | } | 942 | } |
919 | 943 | ||
920 | static void soc_remove_dai_link(struct snd_soc_card *card, int num, int order) | 944 | static void soc_remove_link_dais(struct snd_soc_card *card, int num, int order) |
921 | { | 945 | { |
922 | struct snd_soc_pcm_runtime *rtd = &card->rtd[num]; | 946 | struct snd_soc_pcm_runtime *rtd = &card->rtd[num]; |
923 | struct snd_soc_codec *codec = rtd->codec; | ||
924 | struct snd_soc_platform *platform = rtd->platform; | ||
925 | struct snd_soc_dai *codec_dai = rtd->codec_dai, *cpu_dai = rtd->cpu_dai; | 947 | struct snd_soc_dai *codec_dai = rtd->codec_dai, *cpu_dai = rtd->cpu_dai; |
926 | int err; | 948 | int err; |
927 | 949 | ||
@@ -946,30 +968,6 @@ static void soc_remove_dai_link(struct snd_soc_card *card, int num, int order) | |||
946 | list_del(&codec_dai->card_list); | 968 | list_del(&codec_dai->card_list); |
947 | } | 969 | } |
948 | 970 | ||
949 | /* remove the platform */ | ||
950 | if (platform && platform->probed && | ||
951 | platform->driver->remove_order == order) { | ||
952 | if (platform->driver->remove) { | ||
953 | err = platform->driver->remove(platform); | ||
954 | if (err < 0) | ||
955 | pr_err("asoc: failed to remove %s: %d\n", | ||
956 | platform->name, err); | ||
957 | } | ||
958 | |||
959 | /* Make sure all DAPM widgets are freed */ | ||
960 | snd_soc_dapm_free(&platform->dapm); | ||
961 | |||
962 | soc_cleanup_platform_debugfs(platform); | ||
963 | platform->probed = 0; | ||
964 | list_del(&platform->card_list); | ||
965 | module_put(platform->dev->driver->owner); | ||
966 | } | ||
967 | |||
968 | /* remove the CODEC */ | ||
969 | if (codec && codec->probed && | ||
970 | codec->driver->remove_order == order) | ||
971 | soc_remove_codec(codec); | ||
972 | |||
973 | /* remove the cpu_dai */ | 971 | /* remove the cpu_dai */ |
974 | if (cpu_dai && cpu_dai->probed && | 972 | if (cpu_dai && cpu_dai->probed && |
975 | cpu_dai->driver->remove_order == order) { | 973 | cpu_dai->driver->remove_order == order) { |
@@ -981,7 +979,43 @@ static void soc_remove_dai_link(struct snd_soc_card *card, int num, int order) | |||
981 | } | 979 | } |
982 | cpu_dai->probed = 0; | 980 | cpu_dai->probed = 0; |
983 | list_del(&cpu_dai->card_list); | 981 | list_del(&cpu_dai->card_list); |
984 | module_put(cpu_dai->dev->driver->owner); | 982 | |
983 | if (!cpu_dai->codec) { | ||
984 | snd_soc_dapm_free(&cpu_dai->dapm); | ||
985 | module_put(cpu_dai->dev->driver->owner); | ||
986 | } | ||
987 | } | ||
988 | } | ||
989 | |||
990 | static void soc_remove_link_components(struct snd_soc_card *card, int num, | ||
991 | int order) | ||
992 | { | ||
993 | struct snd_soc_pcm_runtime *rtd = &card->rtd[num]; | ||
994 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
995 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
996 | struct snd_soc_platform *platform = rtd->platform; | ||
997 | struct snd_soc_codec *codec; | ||
998 | |||
999 | /* remove the platform */ | ||
1000 | if (platform && platform->probed && | ||
1001 | platform->driver->remove_order == order) { | ||
1002 | soc_remove_platform(platform); | ||
1003 | } | ||
1004 | |||
1005 | /* remove the CODEC-side CODEC */ | ||
1006 | if (codec_dai) { | ||
1007 | codec = codec_dai->codec; | ||
1008 | if (codec && codec->probed && | ||
1009 | codec->driver->remove_order == order) | ||
1010 | soc_remove_codec(codec); | ||
1011 | } | ||
1012 | |||
1013 | /* remove any CPU-side CODEC */ | ||
1014 | if (cpu_dai) { | ||
1015 | codec = cpu_dai->codec; | ||
1016 | if (codec && codec->probed && | ||
1017 | codec->driver->remove_order == order) | ||
1018 | soc_remove_codec(codec); | ||
985 | } | 1019 | } |
986 | } | 1020 | } |
987 | 1021 | ||
@@ -992,8 +1026,15 @@ static void soc_remove_dai_links(struct snd_soc_card *card) | |||
992 | for (order = SND_SOC_COMP_ORDER_FIRST; order <= SND_SOC_COMP_ORDER_LAST; | 1026 | for (order = SND_SOC_COMP_ORDER_FIRST; order <= SND_SOC_COMP_ORDER_LAST; |
993 | order++) { | 1027 | order++) { |
994 | for (dai = 0; dai < card->num_rtd; dai++) | 1028 | for (dai = 0; dai < card->num_rtd; dai++) |
995 | soc_remove_dai_link(card, dai, order); | 1029 | soc_remove_link_dais(card, dai, order); |
996 | } | 1030 | } |
1031 | |||
1032 | for (order = SND_SOC_COMP_ORDER_FIRST; order <= SND_SOC_COMP_ORDER_LAST; | ||
1033 | order++) { | ||
1034 | for (dai = 0; dai < card->num_rtd; dai++) | ||
1035 | soc_remove_link_components(card, dai, order); | ||
1036 | } | ||
1037 | |||
997 | card->num_rtd = 0; | 1038 | card->num_rtd = 0; |
998 | } | 1039 | } |
999 | 1040 | ||
@@ -1054,6 +1095,10 @@ static int soc_probe_codec(struct snd_soc_card *card, | |||
1054 | } | 1095 | } |
1055 | } | 1096 | } |
1056 | 1097 | ||
1098 | /* If the driver didn't set I/O up try regmap */ | ||
1099 | if (!codec->control_data) | ||
1100 | snd_soc_codec_set_cache_io(codec, 0, 0, SND_SOC_REGMAP); | ||
1101 | |||
1057 | if (driver->controls) | 1102 | if (driver->controls) |
1058 | snd_soc_add_codec_controls(codec, driver->controls, | 1103 | snd_soc_add_codec_controls(codec, driver->controls, |
1059 | driver->num_controls); | 1104 | driver->num_controls); |
@@ -1230,7 +1275,44 @@ out: | |||
1230 | return 0; | 1275 | return 0; |
1231 | } | 1276 | } |
1232 | 1277 | ||
1233 | static int soc_probe_dai_link(struct snd_soc_card *card, int num, int order) | 1278 | static int soc_probe_link_components(struct snd_soc_card *card, int num, |
1279 | int order) | ||
1280 | { | ||
1281 | struct snd_soc_pcm_runtime *rtd = &card->rtd[num]; | ||
1282 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
1283 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
1284 | struct snd_soc_platform *platform = rtd->platform; | ||
1285 | int ret; | ||
1286 | |||
1287 | /* probe the CPU-side component, if it is a CODEC */ | ||
1288 | if (cpu_dai->codec && | ||
1289 | !cpu_dai->codec->probed && | ||
1290 | cpu_dai->codec->driver->probe_order == order) { | ||
1291 | ret = soc_probe_codec(card, cpu_dai->codec); | ||
1292 | if (ret < 0) | ||
1293 | return ret; | ||
1294 | } | ||
1295 | |||
1296 | /* probe the CODEC-side component */ | ||
1297 | if (!codec_dai->codec->probed && | ||
1298 | codec_dai->codec->driver->probe_order == order) { | ||
1299 | ret = soc_probe_codec(card, codec_dai->codec); | ||
1300 | if (ret < 0) | ||
1301 | return ret; | ||
1302 | } | ||
1303 | |||
1304 | /* probe the platform */ | ||
1305 | if (!platform->probed && | ||
1306 | platform->driver->probe_order == order) { | ||
1307 | ret = soc_probe_platform(card, platform); | ||
1308 | if (ret < 0) | ||
1309 | return ret; | ||
1310 | } | ||
1311 | |||
1312 | return 0; | ||
1313 | } | ||
1314 | |||
1315 | static int soc_probe_link_dais(struct snd_soc_card *card, int num, int order) | ||
1234 | { | 1316 | { |
1235 | struct snd_soc_dai_link *dai_link = &card->dai_link[num]; | 1317 | struct snd_soc_dai_link *dai_link = &card->dai_link[num]; |
1236 | struct snd_soc_pcm_runtime *rtd = &card->rtd[num]; | 1318 | struct snd_soc_pcm_runtime *rtd = &card->rtd[num]; |
@@ -1255,11 +1337,14 @@ static int soc_probe_dai_link(struct snd_soc_card *card, int num, int order) | |||
1255 | /* probe the cpu_dai */ | 1337 | /* probe the cpu_dai */ |
1256 | if (!cpu_dai->probed && | 1338 | if (!cpu_dai->probed && |
1257 | cpu_dai->driver->probe_order == order) { | 1339 | cpu_dai->driver->probe_order == order) { |
1258 | cpu_dai->dapm.card = card; | 1340 | if (!cpu_dai->codec) { |
1259 | if (!try_module_get(cpu_dai->dev->driver->owner)) | 1341 | cpu_dai->dapm.card = card; |
1260 | return -ENODEV; | 1342 | if (!try_module_get(cpu_dai->dev->driver->owner)) |
1343 | return -ENODEV; | ||
1261 | 1344 | ||
1262 | snd_soc_dapm_new_dai_widgets(&cpu_dai->dapm, cpu_dai); | 1345 | list_add(&cpu_dai->dapm.list, &card->dapm_list); |
1346 | snd_soc_dapm_new_dai_widgets(&cpu_dai->dapm, cpu_dai); | ||
1347 | } | ||
1263 | 1348 | ||
1264 | if (cpu_dai->driver->probe) { | 1349 | if (cpu_dai->driver->probe) { |
1265 | ret = cpu_dai->driver->probe(cpu_dai); | 1350 | ret = cpu_dai->driver->probe(cpu_dai); |
@@ -1275,22 +1360,6 @@ static int soc_probe_dai_link(struct snd_soc_card *card, int num, int order) | |||
1275 | list_add(&cpu_dai->card_list, &card->dai_dev_list); | 1360 | list_add(&cpu_dai->card_list, &card->dai_dev_list); |
1276 | } | 1361 | } |
1277 | 1362 | ||
1278 | /* probe the CODEC */ | ||
1279 | if (!codec->probed && | ||
1280 | codec->driver->probe_order == order) { | ||
1281 | ret = soc_probe_codec(card, codec); | ||
1282 | if (ret < 0) | ||
1283 | return ret; | ||
1284 | } | ||
1285 | |||
1286 | /* probe the platform */ | ||
1287 | if (!platform->probed && | ||
1288 | platform->driver->probe_order == order) { | ||
1289 | ret = soc_probe_platform(card, platform); | ||
1290 | if (ret < 0) | ||
1291 | return ret; | ||
1292 | } | ||
1293 | |||
1294 | /* probe the CODEC DAI */ | 1363 | /* probe the CODEC DAI */ |
1295 | if (!codec_dai->probed && codec_dai->driver->probe_order == order) { | 1364 | if (!codec_dai->probed && codec_dai->driver->probe_order == order) { |
1296 | if (codec_dai->driver->probe) { | 1365 | if (codec_dai->driver->probe) { |
@@ -1565,14 +1634,27 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card) | |||
1565 | goto card_probe_error; | 1634 | goto card_probe_error; |
1566 | } | 1635 | } |
1567 | 1636 | ||
1568 | /* early DAI link probe */ | 1637 | /* probe all components used by DAI links on this card */ |
1569 | for (order = SND_SOC_COMP_ORDER_FIRST; order <= SND_SOC_COMP_ORDER_LAST; | 1638 | for (order = SND_SOC_COMP_ORDER_FIRST; order <= SND_SOC_COMP_ORDER_LAST; |
1570 | order++) { | 1639 | order++) { |
1571 | for (i = 0; i < card->num_links; i++) { | 1640 | for (i = 0; i < card->num_links; i++) { |
1572 | ret = soc_probe_dai_link(card, i, order); | 1641 | ret = soc_probe_link_components(card, i, order); |
1573 | if (ret < 0) { | 1642 | if (ret < 0) { |
1574 | pr_err("asoc: failed to instantiate card %s: %d\n", | 1643 | pr_err("asoc: failed to instantiate card %s: %d\n", |
1575 | card->name, ret); | 1644 | card->name, ret); |
1645 | goto probe_dai_err; | ||
1646 | } | ||
1647 | } | ||
1648 | } | ||
1649 | |||
1650 | /* probe all DAI links on this card */ | ||
1651 | for (order = SND_SOC_COMP_ORDER_FIRST; order <= SND_SOC_COMP_ORDER_LAST; | ||
1652 | order++) { | ||
1653 | for (i = 0; i < card->num_links; i++) { | ||
1654 | ret = soc_probe_link_dais(card, i, order); | ||
1655 | if (ret < 0) { | ||
1656 | pr_err("asoc: failed to instantiate card %s: %d\n", | ||
1657 | card->name, ret); | ||
1576 | goto probe_dai_err; | 1658 | goto probe_dai_err; |
1577 | } | 1659 | } |
1578 | } | 1660 | } |
@@ -2790,6 +2872,104 @@ int snd_soc_put_volsw_s8(struct snd_kcontrol *kcontrol, | |||
2790 | EXPORT_SYMBOL_GPL(snd_soc_put_volsw_s8); | 2872 | EXPORT_SYMBOL_GPL(snd_soc_put_volsw_s8); |
2791 | 2873 | ||
2792 | /** | 2874 | /** |
2875 | * snd_soc_info_volsw_range - single mixer info callback with range. | ||
2876 | * @kcontrol: mixer control | ||
2877 | * @uinfo: control element information | ||
2878 | * | ||
2879 | * Callback to provide information, within a range, about a single | ||
2880 | * mixer control. | ||
2881 | * | ||
2882 | * returns 0 for success. | ||
2883 | */ | ||
2884 | int snd_soc_info_volsw_range(struct snd_kcontrol *kcontrol, | ||
2885 | struct snd_ctl_elem_info *uinfo) | ||
2886 | { | ||
2887 | struct soc_mixer_control *mc = | ||
2888 | (struct soc_mixer_control *)kcontrol->private_value; | ||
2889 | int platform_max; | ||
2890 | int min = mc->min; | ||
2891 | |||
2892 | if (!mc->platform_max) | ||
2893 | mc->platform_max = mc->max; | ||
2894 | platform_max = mc->platform_max; | ||
2895 | |||
2896 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
2897 | uinfo->count = 1; | ||
2898 | uinfo->value.integer.min = 0; | ||
2899 | uinfo->value.integer.max = platform_max - min; | ||
2900 | |||
2901 | return 0; | ||
2902 | } | ||
2903 | EXPORT_SYMBOL_GPL(snd_soc_info_volsw_range); | ||
2904 | |||
2905 | /** | ||
2906 | * snd_soc_put_volsw_range - single mixer put value callback with range. | ||
2907 | * @kcontrol: mixer control | ||
2908 | * @ucontrol: control element information | ||
2909 | * | ||
2910 | * Callback to set the value, within a range, for a single mixer control. | ||
2911 | * | ||
2912 | * Returns 0 for success. | ||
2913 | */ | ||
2914 | int snd_soc_put_volsw_range(struct snd_kcontrol *kcontrol, | ||
2915 | struct snd_ctl_elem_value *ucontrol) | ||
2916 | { | ||
2917 | struct soc_mixer_control *mc = | ||
2918 | (struct soc_mixer_control *)kcontrol->private_value; | ||
2919 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
2920 | unsigned int reg = mc->reg; | ||
2921 | unsigned int shift = mc->shift; | ||
2922 | int min = mc->min; | ||
2923 | int max = mc->max; | ||
2924 | unsigned int mask = (1 << fls(max)) - 1; | ||
2925 | unsigned int invert = mc->invert; | ||
2926 | unsigned int val, val_mask; | ||
2927 | |||
2928 | val = ((ucontrol->value.integer.value[0] + min) & mask); | ||
2929 | if (invert) | ||
2930 | val = max - val; | ||
2931 | val_mask = mask << shift; | ||
2932 | val = val << shift; | ||
2933 | |||
2934 | return snd_soc_update_bits_locked(codec, reg, val_mask, val); | ||
2935 | } | ||
2936 | EXPORT_SYMBOL_GPL(snd_soc_put_volsw_range); | ||
2937 | |||
2938 | /** | ||
2939 | * snd_soc_get_volsw_range - single mixer get callback with range | ||
2940 | * @kcontrol: mixer control | ||
2941 | * @ucontrol: control element information | ||
2942 | * | ||
2943 | * Callback to get the value, within a range, of a single mixer control. | ||
2944 | * | ||
2945 | * Returns 0 for success. | ||
2946 | */ | ||
2947 | int snd_soc_get_volsw_range(struct snd_kcontrol *kcontrol, | ||
2948 | struct snd_ctl_elem_value *ucontrol) | ||
2949 | { | ||
2950 | struct soc_mixer_control *mc = | ||
2951 | (struct soc_mixer_control *)kcontrol->private_value; | ||
2952 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
2953 | unsigned int reg = mc->reg; | ||
2954 | unsigned int shift = mc->shift; | ||
2955 | int min = mc->min; | ||
2956 | int max = mc->max; | ||
2957 | unsigned int mask = (1 << fls(max)) - 1; | ||
2958 | unsigned int invert = mc->invert; | ||
2959 | |||
2960 | ucontrol->value.integer.value[0] = | ||
2961 | (snd_soc_read(codec, reg) >> shift) & mask; | ||
2962 | if (invert) | ||
2963 | ucontrol->value.integer.value[0] = | ||
2964 | max - ucontrol->value.integer.value[0]; | ||
2965 | ucontrol->value.integer.value[0] = | ||
2966 | ucontrol->value.integer.value[0] - min; | ||
2967 | |||
2968 | return 0; | ||
2969 | } | ||
2970 | EXPORT_SYMBOL_GPL(snd_soc_get_volsw_range); | ||
2971 | |||
2972 | /** | ||
2793 | * snd_soc_limit_volume - Set new limit to an existing volume control. | 2973 | * snd_soc_limit_volume - Set new limit to an existing volume control. |
2794 | * | 2974 | * |
2795 | * @codec: where to look for the control | 2975 | * @codec: where to look for the control |
@@ -3346,6 +3526,12 @@ int snd_soc_register_card(struct snd_soc_card *card) | |||
3346 | link->name); | 3526 | link->name); |
3347 | return -EINVAL; | 3527 | return -EINVAL; |
3348 | } | 3528 | } |
3529 | /* Codec DAI name must be specified */ | ||
3530 | if (!link->codec_dai_name) { | ||
3531 | dev_err(card->dev, "codec_dai_name not set for %s\n", | ||
3532 | link->name); | ||
3533 | return -EINVAL; | ||
3534 | } | ||
3349 | 3535 | ||
3350 | /* | 3536 | /* |
3351 | * Platform may be specified by either name or OF node, but | 3537 | * Platform may be specified by either name or OF node, but |
@@ -3358,12 +3544,24 @@ int snd_soc_register_card(struct snd_soc_card *card) | |||
3358 | } | 3544 | } |
3359 | 3545 | ||
3360 | /* | 3546 | /* |
3361 | * CPU DAI must be specified by 1 of name or OF node, | 3547 | * CPU device may be specified by either name or OF node, but |
3362 | * not both or neither. | 3548 | * can be left unspecified, and will be matched based on DAI |
3549 | * name alone.. | ||
3550 | */ | ||
3551 | if (link->cpu_name && link->cpu_of_node) { | ||
3552 | dev_err(card->dev, | ||
3553 | "Neither/both cpu name/of_node are set for %s\n", | ||
3554 | link->name); | ||
3555 | return -EINVAL; | ||
3556 | } | ||
3557 | /* | ||
3558 | * At least one of CPU DAI name or CPU device name/node must be | ||
3559 | * specified | ||
3363 | */ | 3560 | */ |
3364 | if (!!link->cpu_dai_name == !!link->cpu_dai_of_node) { | 3561 | if (!link->cpu_dai_name && |
3562 | !(link->cpu_name || link->cpu_of_node)) { | ||
3365 | dev_err(card->dev, | 3563 | dev_err(card->dev, |
3366 | "Neither/both cpu_dai name/of_node are set for %s\n", | 3564 | "Neither cpu_dai_name nor cpu_name/of_node are set for %s\n", |
3367 | link->name); | 3565 | link->name); |
3368 | return -EINVAL; | 3566 | return -EINVAL; |
3369 | } | 3567 | } |
@@ -3938,6 +4136,7 @@ int snd_soc_of_parse_audio_routing(struct snd_soc_card *card, | |||
3938 | dev_err(card->dev, | 4136 | dev_err(card->dev, |
3939 | "Property '%s' index %d could not be read: %d\n", | 4137 | "Property '%s' index %d could not be read: %d\n", |
3940 | propname, 2 * i, ret); | 4138 | propname, 2 * i, ret); |
4139 | kfree(routes); | ||
3941 | return -EINVAL; | 4140 | return -EINVAL; |
3942 | } | 4141 | } |
3943 | ret = of_property_read_string_index(np, propname, | 4142 | ret = of_property_read_string_index(np, propname, |
@@ -3946,6 +4145,7 @@ int snd_soc_of_parse_audio_routing(struct snd_soc_card *card, | |||
3946 | dev_err(card->dev, | 4145 | dev_err(card->dev, |
3947 | "Property '%s' index %d could not be read: %d\n", | 4146 | "Property '%s' index %d could not be read: %d\n", |
3948 | propname, (2 * i) + 1, ret); | 4147 | propname, (2 * i) + 1, ret); |
4148 | kfree(routes); | ||
3949 | return -EINVAL; | 4149 | return -EINVAL; |
3950 | } | 4150 | } |
3951 | } | 4151 | } |