diff options
Diffstat (limited to 'sound/soc/soc-core.c')
-rw-r--r-- | sound/soc/soc-core.c | 582 |
1 files changed, 331 insertions, 251 deletions
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index fe1df50805a3..359c2849b364 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c | |||
@@ -56,7 +56,6 @@ EXPORT_SYMBOL_GPL(snd_soc_debugfs_root); | |||
56 | #endif | 56 | #endif |
57 | 57 | ||
58 | static DEFINE_MUTEX(client_mutex); | 58 | static DEFINE_MUTEX(client_mutex); |
59 | static LIST_HEAD(dai_list); | ||
60 | static LIST_HEAD(platform_list); | 59 | static LIST_HEAD(platform_list); |
61 | static LIST_HEAD(codec_list); | 60 | static LIST_HEAD(codec_list); |
62 | static LIST_HEAD(component_list); | 61 | static LIST_HEAD(component_list); |
@@ -370,18 +369,22 @@ static ssize_t dai_list_read_file(struct file *file, char __user *user_buf, | |||
370 | { | 369 | { |
371 | char *buf = kmalloc(PAGE_SIZE, GFP_KERNEL); | 370 | char *buf = kmalloc(PAGE_SIZE, GFP_KERNEL); |
372 | ssize_t len, ret = 0; | 371 | ssize_t len, ret = 0; |
372 | struct snd_soc_component *component; | ||
373 | struct snd_soc_dai *dai; | 373 | struct snd_soc_dai *dai; |
374 | 374 | ||
375 | if (!buf) | 375 | if (!buf) |
376 | return -ENOMEM; | 376 | return -ENOMEM; |
377 | 377 | ||
378 | list_for_each_entry(dai, &dai_list, list) { | 378 | list_for_each_entry(component, &component_list, list) { |
379 | len = snprintf(buf + ret, PAGE_SIZE - ret, "%s\n", dai->name); | 379 | list_for_each_entry(dai, &component->dai_list, list) { |
380 | if (len >= 0) | 380 | len = snprintf(buf + ret, PAGE_SIZE - ret, "%s\n", |
381 | ret += len; | 381 | dai->name); |
382 | if (ret > PAGE_SIZE) { | 382 | if (len >= 0) |
383 | ret = PAGE_SIZE; | 383 | ret += len; |
384 | break; | 384 | if (ret > PAGE_SIZE) { |
385 | ret = PAGE_SIZE; | ||
386 | break; | ||
387 | } | ||
385 | } | 388 | } |
386 | } | 389 | } |
387 | 390 | ||
@@ -855,6 +858,7 @@ static int soc_bind_dai_link(struct snd_soc_card *card, int num) | |||
855 | { | 858 | { |
856 | struct snd_soc_dai_link *dai_link = &card->dai_link[num]; | 859 | struct snd_soc_dai_link *dai_link = &card->dai_link[num]; |
857 | struct snd_soc_pcm_runtime *rtd = &card->rtd[num]; | 860 | struct snd_soc_pcm_runtime *rtd = &card->rtd[num]; |
861 | struct snd_soc_component *component; | ||
858 | struct snd_soc_codec *codec; | 862 | struct snd_soc_codec *codec; |
859 | struct snd_soc_platform *platform; | 863 | struct snd_soc_platform *platform; |
860 | struct snd_soc_dai *codec_dai, *cpu_dai; | 864 | struct snd_soc_dai *codec_dai, *cpu_dai; |
@@ -863,18 +867,20 @@ static int soc_bind_dai_link(struct snd_soc_card *card, int num) | |||
863 | dev_dbg(card->dev, "ASoC: binding %s at idx %d\n", dai_link->name, num); | 867 | dev_dbg(card->dev, "ASoC: binding %s at idx %d\n", dai_link->name, num); |
864 | 868 | ||
865 | /* Find CPU DAI from registered DAIs*/ | 869 | /* Find CPU DAI from registered DAIs*/ |
866 | list_for_each_entry(cpu_dai, &dai_list, list) { | 870 | list_for_each_entry(component, &component_list, list) { |
867 | if (dai_link->cpu_of_node && | 871 | if (dai_link->cpu_of_node && |
868 | (cpu_dai->dev->of_node != dai_link->cpu_of_node)) | 872 | component->dev->of_node != dai_link->cpu_of_node) |
869 | continue; | 873 | continue; |
870 | if (dai_link->cpu_name && | 874 | if (dai_link->cpu_name && |
871 | strcmp(dev_name(cpu_dai->dev), dai_link->cpu_name)) | 875 | strcmp(dev_name(component->dev), dai_link->cpu_name)) |
872 | continue; | ||
873 | if (dai_link->cpu_dai_name && | ||
874 | strcmp(cpu_dai->name, dai_link->cpu_dai_name)) | ||
875 | continue; | 876 | continue; |
877 | list_for_each_entry(cpu_dai, &component->dai_list, list) { | ||
878 | if (dai_link->cpu_dai_name && | ||
879 | strcmp(cpu_dai->name, dai_link->cpu_dai_name)) | ||
880 | continue; | ||
876 | 881 | ||
877 | rtd->cpu_dai = cpu_dai; | 882 | rtd->cpu_dai = cpu_dai; |
883 | } | ||
878 | } | 884 | } |
879 | 885 | ||
880 | if (!rtd->cpu_dai) { | 886 | if (!rtd->cpu_dai) { |
@@ -899,12 +905,10 @@ static int soc_bind_dai_link(struct snd_soc_card *card, int num) | |||
899 | * CODEC found, so find CODEC DAI from registered DAIs from | 905 | * CODEC found, so find CODEC DAI from registered DAIs from |
900 | * this CODEC | 906 | * this CODEC |
901 | */ | 907 | */ |
902 | list_for_each_entry(codec_dai, &dai_list, list) { | 908 | list_for_each_entry(codec_dai, &codec->component.dai_list, list) { |
903 | if (codec->dev == codec_dai->dev && | 909 | if (!strcmp(codec_dai->name, dai_link->codec_dai_name)) { |
904 | !strcmp(codec_dai->name, | ||
905 | dai_link->codec_dai_name)) { | ||
906 | |||
907 | rtd->codec_dai = codec_dai; | 910 | rtd->codec_dai = codec_dai; |
911 | break; | ||
908 | } | 912 | } |
909 | } | 913 | } |
910 | 914 | ||
@@ -1128,12 +1132,8 @@ static int soc_probe_codec(struct snd_soc_card *card, | |||
1128 | driver->num_dapm_widgets); | 1132 | driver->num_dapm_widgets); |
1129 | 1133 | ||
1130 | /* Create DAPM widgets for each DAI stream */ | 1134 | /* Create DAPM widgets for each DAI stream */ |
1131 | list_for_each_entry(dai, &dai_list, list) { | 1135 | list_for_each_entry(dai, &codec->component.dai_list, list) |
1132 | if (dai->dev != codec->dev) | ||
1133 | continue; | ||
1134 | |||
1135 | snd_soc_dapm_new_dai_widgets(&codec->dapm, dai); | 1136 | snd_soc_dapm_new_dai_widgets(&codec->dapm, dai); |
1136 | } | ||
1137 | 1137 | ||
1138 | codec->dapm.idle_bias_off = driver->idle_bias_off; | 1138 | codec->dapm.idle_bias_off = driver->idle_bias_off; |
1139 | 1139 | ||
@@ -1180,6 +1180,7 @@ static int soc_probe_platform(struct snd_soc_card *card, | |||
1180 | { | 1180 | { |
1181 | int ret = 0; | 1181 | int ret = 0; |
1182 | const struct snd_soc_platform_driver *driver = platform->driver; | 1182 | const struct snd_soc_platform_driver *driver = platform->driver; |
1183 | struct snd_soc_component *component; | ||
1183 | struct snd_soc_dai *dai; | 1184 | struct snd_soc_dai *dai; |
1184 | 1185 | ||
1185 | platform->card = card; | 1186 | platform->card = card; |
@@ -1195,11 +1196,11 @@ static int soc_probe_platform(struct snd_soc_card *card, | |||
1195 | driver->dapm_widgets, driver->num_dapm_widgets); | 1196 | driver->dapm_widgets, driver->num_dapm_widgets); |
1196 | 1197 | ||
1197 | /* Create DAPM widgets for each DAI stream */ | 1198 | /* Create DAPM widgets for each DAI stream */ |
1198 | list_for_each_entry(dai, &dai_list, list) { | 1199 | list_for_each_entry(component, &component_list, list) { |
1199 | if (dai->dev != platform->dev) | 1200 | if (component->dev != platform->dev) |
1200 | continue; | 1201 | continue; |
1201 | 1202 | list_for_each_entry(dai, &component->dai_list, list) | |
1202 | snd_soc_dapm_new_dai_widgets(&platform->dapm, dai); | 1203 | snd_soc_dapm_new_dai_widgets(&platform->dapm, dai); |
1203 | } | 1204 | } |
1204 | 1205 | ||
1205 | platform->dapm.idle_bias_off = 1; | 1206 | platform->dapm.idle_bias_off = 1; |
@@ -2571,10 +2572,10 @@ int snd_soc_info_enum_double(struct snd_kcontrol *kcontrol, | |||
2571 | 2572 | ||
2572 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | 2573 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; |
2573 | uinfo->count = e->shift_l == e->shift_r ? 1 : 2; | 2574 | uinfo->count = e->shift_l == e->shift_r ? 1 : 2; |
2574 | uinfo->value.enumerated.items = e->max; | 2575 | uinfo->value.enumerated.items = e->items; |
2575 | 2576 | ||
2576 | if (uinfo->value.enumerated.item > e->max - 1) | 2577 | if (uinfo->value.enumerated.item >= e->items) |
2577 | uinfo->value.enumerated.item = e->max - 1; | 2578 | uinfo->value.enumerated.item = e->items - 1; |
2578 | strlcpy(uinfo->value.enumerated.name, | 2579 | strlcpy(uinfo->value.enumerated.name, |
2579 | e->texts[uinfo->value.enumerated.item], | 2580 | e->texts[uinfo->value.enumerated.item], |
2580 | sizeof(uinfo->value.enumerated.name)); | 2581 | sizeof(uinfo->value.enumerated.name)); |
@@ -2596,14 +2597,18 @@ int snd_soc_get_enum_double(struct snd_kcontrol *kcontrol, | |||
2596 | { | 2597 | { |
2597 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | 2598 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); |
2598 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; | 2599 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; |
2599 | unsigned int val; | 2600 | unsigned int val, item; |
2601 | unsigned int reg_val; | ||
2600 | 2602 | ||
2601 | val = snd_soc_read(codec, e->reg); | 2603 | reg_val = snd_soc_read(codec, e->reg); |
2602 | ucontrol->value.enumerated.item[0] | 2604 | val = (reg_val >> e->shift_l) & e->mask; |
2603 | = (val >> e->shift_l) & e->mask; | 2605 | item = snd_soc_enum_val_to_item(e, val); |
2604 | if (e->shift_l != e->shift_r) | 2606 | ucontrol->value.enumerated.item[0] = item; |
2605 | ucontrol->value.enumerated.item[1] = | 2607 | if (e->shift_l != e->shift_r) { |
2606 | (val >> e->shift_r) & e->mask; | 2608 | val = (reg_val >> e->shift_l) & e->mask; |
2609 | item = snd_soc_enum_val_to_item(e, val); | ||
2610 | ucontrol->value.enumerated.item[1] = item; | ||
2611 | } | ||
2607 | 2612 | ||
2608 | return 0; | 2613 | return 0; |
2609 | } | 2614 | } |
@@ -2623,17 +2628,18 @@ int snd_soc_put_enum_double(struct snd_kcontrol *kcontrol, | |||
2623 | { | 2628 | { |
2624 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | 2629 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); |
2625 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; | 2630 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; |
2631 | unsigned int *item = ucontrol->value.enumerated.item; | ||
2626 | unsigned int val; | 2632 | unsigned int val; |
2627 | unsigned int mask; | 2633 | unsigned int mask; |
2628 | 2634 | ||
2629 | if (ucontrol->value.enumerated.item[0] > e->max - 1) | 2635 | if (item[0] >= e->items) |
2630 | return -EINVAL; | 2636 | return -EINVAL; |
2631 | val = ucontrol->value.enumerated.item[0] << e->shift_l; | 2637 | val = snd_soc_enum_item_to_val(e, item[0]) << e->shift_l; |
2632 | mask = e->mask << e->shift_l; | 2638 | mask = e->mask << e->shift_l; |
2633 | if (e->shift_l != e->shift_r) { | 2639 | if (e->shift_l != e->shift_r) { |
2634 | if (ucontrol->value.enumerated.item[1] > e->max - 1) | 2640 | if (item[1] >= e->items) |
2635 | return -EINVAL; | 2641 | return -EINVAL; |
2636 | val |= ucontrol->value.enumerated.item[1] << e->shift_r; | 2642 | val |= snd_soc_enum_item_to_val(e, item[1]) << e->shift_r; |
2637 | mask |= e->mask << e->shift_r; | 2643 | mask |= e->mask << e->shift_r; |
2638 | } | 2644 | } |
2639 | 2645 | ||
@@ -2642,78 +2648,46 @@ int snd_soc_put_enum_double(struct snd_kcontrol *kcontrol, | |||
2642 | EXPORT_SYMBOL_GPL(snd_soc_put_enum_double); | 2648 | EXPORT_SYMBOL_GPL(snd_soc_put_enum_double); |
2643 | 2649 | ||
2644 | /** | 2650 | /** |
2645 | * snd_soc_get_value_enum_double - semi enumerated double mixer get callback | 2651 | * snd_soc_read_signed - Read a codec register and interprete as signed value |
2646 | * @kcontrol: mixer control | 2652 | * @codec: codec |
2647 | * @ucontrol: control element information | 2653 | * @reg: Register to read |
2648 | * | 2654 | * @mask: Mask to use after shifting the register value |
2649 | * Callback to get the value of a double semi enumerated mixer. | 2655 | * @shift: Right shift of register value |
2656 | * @sign_bit: Bit that describes if a number is negative or not. | ||
2650 | * | 2657 | * |
2651 | * Semi enumerated mixer: the enumerated items are referred as values. Can be | 2658 | * This functions reads a codec register. The register value is shifted right |
2652 | * used for handling bitfield coded enumeration for example. | 2659 | * by 'shift' bits and masked with the given 'mask'. Afterwards it translates |
2660 | * the given registervalue into a signed integer if sign_bit is non-zero. | ||
2653 | * | 2661 | * |
2654 | * Returns 0 for success. | 2662 | * Returns the register value as signed int. |
2655 | */ | 2663 | */ |
2656 | int snd_soc_get_value_enum_double(struct snd_kcontrol *kcontrol, | 2664 | static int snd_soc_read_signed(struct snd_soc_codec *codec, unsigned int reg, |
2657 | struct snd_ctl_elem_value *ucontrol) | 2665 | unsigned int mask, unsigned int shift, unsigned int sign_bit) |
2658 | { | 2666 | { |
2659 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | 2667 | int ret; |
2660 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; | 2668 | unsigned int val; |
2661 | unsigned int reg_val, val, mux; | ||
2662 | 2669 | ||
2663 | reg_val = snd_soc_read(codec, e->reg); | 2670 | val = (snd_soc_read(codec, reg) >> shift) & mask; |
2664 | val = (reg_val >> e->shift_l) & e->mask; | ||
2665 | for (mux = 0; mux < e->max; mux++) { | ||
2666 | if (val == e->values[mux]) | ||
2667 | break; | ||
2668 | } | ||
2669 | ucontrol->value.enumerated.item[0] = mux; | ||
2670 | if (e->shift_l != e->shift_r) { | ||
2671 | val = (reg_val >> e->shift_r) & e->mask; | ||
2672 | for (mux = 0; mux < e->max; mux++) { | ||
2673 | if (val == e->values[mux]) | ||
2674 | break; | ||
2675 | } | ||
2676 | ucontrol->value.enumerated.item[1] = mux; | ||
2677 | } | ||
2678 | 2671 | ||
2679 | return 0; | 2672 | if (!sign_bit) |
2680 | } | 2673 | return val; |
2681 | EXPORT_SYMBOL_GPL(snd_soc_get_value_enum_double); | ||
2682 | 2674 | ||
2683 | /** | 2675 | /* non-negative number */ |
2684 | * snd_soc_put_value_enum_double - semi enumerated double mixer put callback | 2676 | if (!(val & BIT(sign_bit))) |
2685 | * @kcontrol: mixer control | 2677 | return val; |
2686 | * @ucontrol: control element information | ||
2687 | * | ||
2688 | * Callback to set the value of a double semi enumerated mixer. | ||
2689 | * | ||
2690 | * Semi enumerated mixer: the enumerated items are referred as values. Can be | ||
2691 | * used for handling bitfield coded enumeration for example. | ||
2692 | * | ||
2693 | * Returns 0 for success. | ||
2694 | */ | ||
2695 | int snd_soc_put_value_enum_double(struct snd_kcontrol *kcontrol, | ||
2696 | struct snd_ctl_elem_value *ucontrol) | ||
2697 | { | ||
2698 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
2699 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; | ||
2700 | unsigned int val; | ||
2701 | unsigned int mask; | ||
2702 | 2678 | ||
2703 | if (ucontrol->value.enumerated.item[0] > e->max - 1) | 2679 | ret = val; |
2704 | return -EINVAL; | ||
2705 | val = e->values[ucontrol->value.enumerated.item[0]] << e->shift_l; | ||
2706 | mask = e->mask << e->shift_l; | ||
2707 | if (e->shift_l != e->shift_r) { | ||
2708 | if (ucontrol->value.enumerated.item[1] > e->max - 1) | ||
2709 | return -EINVAL; | ||
2710 | val |= e->values[ucontrol->value.enumerated.item[1]] << e->shift_r; | ||
2711 | mask |= e->mask << e->shift_r; | ||
2712 | } | ||
2713 | 2680 | ||
2714 | return snd_soc_update_bits_locked(codec, e->reg, mask, val); | 2681 | /* |
2682 | * The register most probably does not contain a full-sized int. | ||
2683 | * Instead we have an arbitrary number of bits in a signed | ||
2684 | * representation which has to be translated into a full-sized int. | ||
2685 | * This is done by filling up all bits above the sign-bit. | ||
2686 | */ | ||
2687 | ret |= ~((int)(BIT(sign_bit) - 1)); | ||
2688 | |||
2689 | return ret; | ||
2715 | } | 2690 | } |
2716 | EXPORT_SYMBOL_GPL(snd_soc_put_value_enum_double); | ||
2717 | 2691 | ||
2718 | /** | 2692 | /** |
2719 | * snd_soc_info_volsw - single mixer info callback | 2693 | * snd_soc_info_volsw - single mixer info callback |
@@ -2743,7 +2717,7 @@ int snd_soc_info_volsw(struct snd_kcontrol *kcontrol, | |||
2743 | 2717 | ||
2744 | uinfo->count = snd_soc_volsw_is_stereo(mc) ? 2 : 1; | 2718 | uinfo->count = snd_soc_volsw_is_stereo(mc) ? 2 : 1; |
2745 | uinfo->value.integer.min = 0; | 2719 | uinfo->value.integer.min = 0; |
2746 | uinfo->value.integer.max = platform_max; | 2720 | uinfo->value.integer.max = platform_max - mc->min; |
2747 | return 0; | 2721 | return 0; |
2748 | } | 2722 | } |
2749 | EXPORT_SYMBOL_GPL(snd_soc_info_volsw); | 2723 | EXPORT_SYMBOL_GPL(snd_soc_info_volsw); |
@@ -2769,11 +2743,16 @@ int snd_soc_get_volsw(struct snd_kcontrol *kcontrol, | |||
2769 | unsigned int shift = mc->shift; | 2743 | unsigned int shift = mc->shift; |
2770 | unsigned int rshift = mc->rshift; | 2744 | unsigned int rshift = mc->rshift; |
2771 | int max = mc->max; | 2745 | int max = mc->max; |
2746 | int min = mc->min; | ||
2747 | int sign_bit = mc->sign_bit; | ||
2772 | unsigned int mask = (1 << fls(max)) - 1; | 2748 | unsigned int mask = (1 << fls(max)) - 1; |
2773 | unsigned int invert = mc->invert; | 2749 | unsigned int invert = mc->invert; |
2774 | 2750 | ||
2775 | ucontrol->value.integer.value[0] = | 2751 | if (sign_bit) |
2776 | (snd_soc_read(codec, reg) >> shift) & mask; | 2752 | mask = BIT(sign_bit + 1) - 1; |
2753 | |||
2754 | ucontrol->value.integer.value[0] = snd_soc_read_signed(codec, reg, mask, | ||
2755 | shift, sign_bit) - min; | ||
2777 | if (invert) | 2756 | if (invert) |
2778 | ucontrol->value.integer.value[0] = | 2757 | ucontrol->value.integer.value[0] = |
2779 | max - ucontrol->value.integer.value[0]; | 2758 | max - ucontrol->value.integer.value[0]; |
@@ -2781,10 +2760,12 @@ int snd_soc_get_volsw(struct snd_kcontrol *kcontrol, | |||
2781 | if (snd_soc_volsw_is_stereo(mc)) { | 2760 | if (snd_soc_volsw_is_stereo(mc)) { |
2782 | if (reg == reg2) | 2761 | if (reg == reg2) |
2783 | ucontrol->value.integer.value[1] = | 2762 | ucontrol->value.integer.value[1] = |
2784 | (snd_soc_read(codec, reg) >> rshift) & mask; | 2763 | snd_soc_read_signed(codec, reg, mask, rshift, |
2764 | sign_bit) - min; | ||
2785 | else | 2765 | else |
2786 | ucontrol->value.integer.value[1] = | 2766 | ucontrol->value.integer.value[1] = |
2787 | (snd_soc_read(codec, reg2) >> shift) & mask; | 2767 | snd_soc_read_signed(codec, reg2, mask, shift, |
2768 | sign_bit) - min; | ||
2788 | if (invert) | 2769 | if (invert) |
2789 | ucontrol->value.integer.value[1] = | 2770 | ucontrol->value.integer.value[1] = |
2790 | max - ucontrol->value.integer.value[1]; | 2771 | max - ucontrol->value.integer.value[1]; |
@@ -2815,20 +2796,25 @@ int snd_soc_put_volsw(struct snd_kcontrol *kcontrol, | |||
2815 | unsigned int shift = mc->shift; | 2796 | unsigned int shift = mc->shift; |
2816 | unsigned int rshift = mc->rshift; | 2797 | unsigned int rshift = mc->rshift; |
2817 | int max = mc->max; | 2798 | int max = mc->max; |
2799 | int min = mc->min; | ||
2800 | unsigned int sign_bit = mc->sign_bit; | ||
2818 | unsigned int mask = (1 << fls(max)) - 1; | 2801 | unsigned int mask = (1 << fls(max)) - 1; |
2819 | unsigned int invert = mc->invert; | 2802 | unsigned int invert = mc->invert; |
2820 | int err; | 2803 | int err; |
2821 | bool type_2r = 0; | 2804 | bool type_2r = false; |
2822 | unsigned int val2 = 0; | 2805 | unsigned int val2 = 0; |
2823 | unsigned int val, val_mask; | 2806 | unsigned int val, val_mask; |
2824 | 2807 | ||
2825 | val = (ucontrol->value.integer.value[0] & mask); | 2808 | if (sign_bit) |
2809 | mask = BIT(sign_bit + 1) - 1; | ||
2810 | |||
2811 | val = ((ucontrol->value.integer.value[0] + min) & mask); | ||
2826 | if (invert) | 2812 | if (invert) |
2827 | val = max - val; | 2813 | val = max - val; |
2828 | val_mask = mask << shift; | 2814 | val_mask = mask << shift; |
2829 | val = val << shift; | 2815 | val = val << shift; |
2830 | if (snd_soc_volsw_is_stereo(mc)) { | 2816 | if (snd_soc_volsw_is_stereo(mc)) { |
2831 | val2 = (ucontrol->value.integer.value[1] & mask); | 2817 | val2 = ((ucontrol->value.integer.value[1] + min) & mask); |
2832 | if (invert) | 2818 | if (invert) |
2833 | val2 = max - val2; | 2819 | val2 = max - val2; |
2834 | if (reg == reg2) { | 2820 | if (reg == reg2) { |
@@ -2836,7 +2822,7 @@ int snd_soc_put_volsw(struct snd_kcontrol *kcontrol, | |||
2836 | val |= val2 << rshift; | 2822 | val |= val2 << rshift; |
2837 | } else { | 2823 | } else { |
2838 | val2 = val2 << shift; | 2824 | val2 = val2 << shift; |
2839 | type_2r = 1; | 2825 | type_2r = true; |
2840 | } | 2826 | } |
2841 | } | 2827 | } |
2842 | err = snd_soc_update_bits_locked(codec, reg, val_mask, val); | 2828 | err = snd_soc_update_bits_locked(codec, reg, val_mask, val); |
@@ -3234,7 +3220,7 @@ int snd_soc_bytes_put(struct snd_kcontrol *kcontrol, | |||
3234 | struct soc_bytes *params = (void *)kcontrol->private_value; | 3220 | struct soc_bytes *params = (void *)kcontrol->private_value; |
3235 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | 3221 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); |
3236 | int ret, len; | 3222 | int ret, len; |
3237 | unsigned int val; | 3223 | unsigned int val, mask; |
3238 | void *data; | 3224 | void *data; |
3239 | 3225 | ||
3240 | if (!codec->using_regmap) | 3226 | if (!codec->using_regmap) |
@@ -3264,12 +3250,36 @@ int snd_soc_bytes_put(struct snd_kcontrol *kcontrol, | |||
3264 | ((u8 *)data)[0] |= val; | 3250 | ((u8 *)data)[0] |= val; |
3265 | break; | 3251 | break; |
3266 | case 2: | 3252 | case 2: |
3267 | ((u16 *)data)[0] &= cpu_to_be16(~params->mask); | 3253 | mask = ~params->mask; |
3268 | ((u16 *)data)[0] |= cpu_to_be16(val); | 3254 | ret = regmap_parse_val(codec->control_data, |
3255 | &mask, &mask); | ||
3256 | if (ret != 0) | ||
3257 | goto out; | ||
3258 | |||
3259 | ((u16 *)data)[0] &= mask; | ||
3260 | |||
3261 | ret = regmap_parse_val(codec->control_data, | ||
3262 | &val, &val); | ||
3263 | if (ret != 0) | ||
3264 | goto out; | ||
3265 | |||
3266 | ((u16 *)data)[0] |= val; | ||
3269 | break; | 3267 | break; |
3270 | case 4: | 3268 | case 4: |
3271 | ((u32 *)data)[0] &= cpu_to_be32(~params->mask); | 3269 | mask = ~params->mask; |
3272 | ((u32 *)data)[0] |= cpu_to_be32(val); | 3270 | ret = regmap_parse_val(codec->control_data, |
3271 | &mask, &mask); | ||
3272 | if (ret != 0) | ||
3273 | goto out; | ||
3274 | |||
3275 | ((u32 *)data)[0] &= mask; | ||
3276 | |||
3277 | ret = regmap_parse_val(codec->control_data, | ||
3278 | &val, &val); | ||
3279 | if (ret != 0) | ||
3280 | goto out; | ||
3281 | |||
3282 | ((u32 *)data)[0] |= val; | ||
3273 | break; | 3283 | break; |
3274 | default: | 3284 | default: |
3275 | ret = -EINVAL; | 3285 | ret = -EINVAL; |
@@ -3609,6 +3619,30 @@ int snd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) | |||
3609 | EXPORT_SYMBOL_GPL(snd_soc_dai_set_fmt); | 3619 | EXPORT_SYMBOL_GPL(snd_soc_dai_set_fmt); |
3610 | 3620 | ||
3611 | /** | 3621 | /** |
3622 | * snd_soc_of_xlate_tdm_slot - generate tx/rx slot mask. | ||
3623 | * @slots: Number of slots in use. | ||
3624 | * @tx_mask: bitmask representing active TX slots. | ||
3625 | * @rx_mask: bitmask representing active RX slots. | ||
3626 | * | ||
3627 | * Generates the TDM tx and rx slot default masks for DAI. | ||
3628 | */ | ||
3629 | static int snd_soc_of_xlate_tdm_slot_mask(unsigned int slots, | ||
3630 | unsigned int *tx_mask, | ||
3631 | unsigned int *rx_mask) | ||
3632 | { | ||
3633 | if (*tx_mask || *rx_mask) | ||
3634 | return 0; | ||
3635 | |||
3636 | if (!slots) | ||
3637 | return -EINVAL; | ||
3638 | |||
3639 | *tx_mask = (1 << slots) - 1; | ||
3640 | *rx_mask = (1 << slots) - 1; | ||
3641 | |||
3642 | return 0; | ||
3643 | } | ||
3644 | |||
3645 | /** | ||
3612 | * snd_soc_dai_set_tdm_slot - configure DAI TDM. | 3646 | * snd_soc_dai_set_tdm_slot - configure DAI TDM. |
3613 | * @dai: DAI | 3647 | * @dai: DAI |
3614 | * @tx_mask: bitmask representing active TX slots. | 3648 | * @tx_mask: bitmask representing active TX slots. |
@@ -3622,11 +3656,17 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_fmt); | |||
3622 | int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai, | 3656 | int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai, |
3623 | unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width) | 3657 | unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width) |
3624 | { | 3658 | { |
3659 | if (dai->driver && dai->driver->ops->of_xlate_tdm_slot_mask) | ||
3660 | dai->driver->ops->of_xlate_tdm_slot_mask(slots, | ||
3661 | &tx_mask, &rx_mask); | ||
3662 | else | ||
3663 | snd_soc_of_xlate_tdm_slot_mask(slots, &tx_mask, &rx_mask); | ||
3664 | |||
3625 | if (dai->driver && dai->driver->ops->set_tdm_slot) | 3665 | if (dai->driver && dai->driver->ops->set_tdm_slot) |
3626 | return dai->driver->ops->set_tdm_slot(dai, tx_mask, rx_mask, | 3666 | return dai->driver->ops->set_tdm_slot(dai, tx_mask, rx_mask, |
3627 | slots, slot_width); | 3667 | slots, slot_width); |
3628 | else | 3668 | else |
3629 | return -EINVAL; | 3669 | return -ENOTSUPP; |
3630 | } | 3670 | } |
3631 | EXPORT_SYMBOL_GPL(snd_soc_dai_set_tdm_slot); | 3671 | EXPORT_SYMBOL_GPL(snd_soc_dai_set_tdm_slot); |
3632 | 3672 | ||
@@ -3882,95 +3922,42 @@ static inline char *fmt_multiple_name(struct device *dev, | |||
3882 | } | 3922 | } |
3883 | 3923 | ||
3884 | /** | 3924 | /** |
3885 | * snd_soc_register_dai - Register a DAI with the ASoC core | 3925 | * snd_soc_unregister_dai - Unregister DAIs from the ASoC core |
3886 | * | 3926 | * |
3887 | * @dai: DAI to register | 3927 | * @component: The component for which the DAIs should be unregistered |
3888 | */ | 3928 | */ |
3889 | static int snd_soc_register_dai(struct device *dev, | 3929 | static void snd_soc_unregister_dais(struct snd_soc_component *component) |
3890 | struct snd_soc_dai_driver *dai_drv) | ||
3891 | { | 3930 | { |
3892 | struct snd_soc_codec *codec; | 3931 | struct snd_soc_dai *dai, *_dai; |
3893 | struct snd_soc_dai *dai; | ||
3894 | |||
3895 | dev_dbg(dev, "ASoC: dai register %s\n", dev_name(dev)); | ||
3896 | 3932 | ||
3897 | dai = kzalloc(sizeof(struct snd_soc_dai), GFP_KERNEL); | 3933 | list_for_each_entry_safe(dai, _dai, &component->dai_list, list) { |
3898 | if (dai == NULL) | 3934 | dev_dbg(component->dev, "ASoC: Unregistered DAI '%s'\n", |
3899 | return -ENOMEM; | 3935 | dai->name); |
3900 | 3936 | list_del(&dai->list); | |
3901 | /* create DAI component name */ | 3937 | kfree(dai->name); |
3902 | dai->name = fmt_single_name(dev, &dai->id); | ||
3903 | if (dai->name == NULL) { | ||
3904 | kfree(dai); | 3938 | kfree(dai); |
3905 | return -ENOMEM; | ||
3906 | } | ||
3907 | |||
3908 | dai->dev = dev; | ||
3909 | dai->driver = dai_drv; | ||
3910 | dai->dapm.dev = dev; | ||
3911 | if (!dai->driver->ops) | ||
3912 | dai->driver->ops = &null_dai_ops; | ||
3913 | |||
3914 | mutex_lock(&client_mutex); | ||
3915 | |||
3916 | list_for_each_entry(codec, &codec_list, list) { | ||
3917 | if (codec->dev == dev) { | ||
3918 | dev_dbg(dev, "ASoC: Mapped DAI %s to CODEC %s\n", | ||
3919 | dai->name, codec->name); | ||
3920 | dai->codec = codec; | ||
3921 | break; | ||
3922 | } | ||
3923 | } | 3939 | } |
3924 | |||
3925 | if (!dai->codec) | ||
3926 | dai->dapm.idle_bias_off = 1; | ||
3927 | |||
3928 | list_add(&dai->list, &dai_list); | ||
3929 | |||
3930 | mutex_unlock(&client_mutex); | ||
3931 | |||
3932 | dev_dbg(dev, "ASoC: Registered DAI '%s'\n", dai->name); | ||
3933 | |||
3934 | return 0; | ||
3935 | } | 3940 | } |
3936 | 3941 | ||
3937 | /** | 3942 | /** |
3938 | * snd_soc_unregister_dai - Unregister a DAI from the ASoC core | 3943 | * snd_soc_register_dais - Register a DAI with the ASoC core |
3939 | * | 3944 | * |
3940 | * @dai: DAI to unregister | 3945 | * @component: The component the DAIs are registered for |
3941 | */ | 3946 | * @codec: The CODEC that the DAIs are registered for, NULL if the component is |
3942 | static void snd_soc_unregister_dai(struct device *dev) | 3947 | * not a CODEC. |
3943 | { | 3948 | * @dai_drv: DAI driver to use for the DAIs |
3944 | struct snd_soc_dai *dai; | ||
3945 | |||
3946 | list_for_each_entry(dai, &dai_list, list) { | ||
3947 | if (dev == dai->dev) | ||
3948 | goto found; | ||
3949 | } | ||
3950 | return; | ||
3951 | |||
3952 | found: | ||
3953 | mutex_lock(&client_mutex); | ||
3954 | list_del(&dai->list); | ||
3955 | mutex_unlock(&client_mutex); | ||
3956 | |||
3957 | dev_dbg(dev, "ASoC: Unregistered DAI '%s'\n", dai->name); | ||
3958 | kfree(dai->name); | ||
3959 | kfree(dai); | ||
3960 | } | ||
3961 | |||
3962 | /** | ||
3963 | * snd_soc_register_dais - Register multiple DAIs with the ASoC core | ||
3964 | * | ||
3965 | * @dai: Array of DAIs to register | ||
3966 | * @count: Number of DAIs | 3949 | * @count: Number of DAIs |
3950 | * @legacy_dai_naming: Use the legacy naming scheme and let the DAI inherit the | ||
3951 | * parent's name. | ||
3967 | */ | 3952 | */ |
3968 | static int snd_soc_register_dais(struct device *dev, | 3953 | static int snd_soc_register_dais(struct snd_soc_component *component, |
3969 | struct snd_soc_dai_driver *dai_drv, size_t count) | 3954 | struct snd_soc_codec *codec, struct snd_soc_dai_driver *dai_drv, |
3955 | size_t count, bool legacy_dai_naming) | ||
3970 | { | 3956 | { |
3971 | struct snd_soc_codec *codec; | 3957 | struct device *dev = component->dev; |
3972 | struct snd_soc_dai *dai; | 3958 | struct snd_soc_dai *dai; |
3973 | int i, ret = 0; | 3959 | unsigned int i; |
3960 | int ret; | ||
3974 | 3961 | ||
3975 | dev_dbg(dev, "ASoC: dai register %s #%Zu\n", dev_name(dev), count); | 3962 | dev_dbg(dev, "ASoC: dai register %s #%Zu\n", dev_name(dev), count); |
3976 | 3963 | ||
@@ -3982,70 +3969,54 @@ static int snd_soc_register_dais(struct device *dev, | |||
3982 | goto err; | 3969 | goto err; |
3983 | } | 3970 | } |
3984 | 3971 | ||
3985 | /* create DAI component name */ | 3972 | /* |
3986 | dai->name = fmt_multiple_name(dev, &dai_drv[i]); | 3973 | * Back in the old days when we still had component-less DAIs, |
3974 | * instead of having a static name, component-less DAIs would | ||
3975 | * inherit the name of the parent device so it is possible to | ||
3976 | * register multiple instances of the DAI. We still need to keep | ||
3977 | * the same naming style even though those DAIs are not | ||
3978 | * component-less anymore. | ||
3979 | */ | ||
3980 | if (count == 1 && legacy_dai_naming) { | ||
3981 | dai->name = fmt_single_name(dev, &dai->id); | ||
3982 | } else { | ||
3983 | dai->name = fmt_multiple_name(dev, &dai_drv[i]); | ||
3984 | if (dai_drv[i].id) | ||
3985 | dai->id = dai_drv[i].id; | ||
3986 | else | ||
3987 | dai->id = i; | ||
3988 | } | ||
3987 | if (dai->name == NULL) { | 3989 | if (dai->name == NULL) { |
3988 | kfree(dai); | 3990 | kfree(dai); |
3989 | ret = -EINVAL; | 3991 | ret = -ENOMEM; |
3990 | goto err; | 3992 | goto err; |
3991 | } | 3993 | } |
3992 | 3994 | ||
3995 | dai->component = component; | ||
3996 | dai->codec = codec; | ||
3993 | dai->dev = dev; | 3997 | dai->dev = dev; |
3994 | dai->driver = &dai_drv[i]; | 3998 | dai->driver = &dai_drv[i]; |
3995 | if (dai->driver->id) | ||
3996 | dai->id = dai->driver->id; | ||
3997 | else | ||
3998 | dai->id = i; | ||
3999 | dai->dapm.dev = dev; | 3999 | dai->dapm.dev = dev; |
4000 | if (!dai->driver->ops) | 4000 | if (!dai->driver->ops) |
4001 | dai->driver->ops = &null_dai_ops; | 4001 | dai->driver->ops = &null_dai_ops; |
4002 | 4002 | ||
4003 | mutex_lock(&client_mutex); | ||
4004 | |||
4005 | list_for_each_entry(codec, &codec_list, list) { | ||
4006 | if (codec->dev == dev) { | ||
4007 | dev_dbg(dev, | ||
4008 | "ASoC: Mapped DAI %s to CODEC %s\n", | ||
4009 | dai->name, codec->name); | ||
4010 | dai->codec = codec; | ||
4011 | break; | ||
4012 | } | ||
4013 | } | ||
4014 | |||
4015 | if (!dai->codec) | 4003 | if (!dai->codec) |
4016 | dai->dapm.idle_bias_off = 1; | 4004 | dai->dapm.idle_bias_off = 1; |
4017 | 4005 | ||
4018 | list_add(&dai->list, &dai_list); | 4006 | list_add(&dai->list, &component->dai_list); |
4019 | 4007 | ||
4020 | mutex_unlock(&client_mutex); | 4008 | dev_dbg(dev, "ASoC: Registered DAI '%s'\n", dai->name); |
4021 | |||
4022 | dev_dbg(dai->dev, "ASoC: Registered DAI '%s'\n", dai->name); | ||
4023 | } | 4009 | } |
4024 | 4010 | ||
4025 | return 0; | 4011 | return 0; |
4026 | 4012 | ||
4027 | err: | 4013 | err: |
4028 | for (i--; i >= 0; i--) | 4014 | snd_soc_unregister_dais(component); |
4029 | snd_soc_unregister_dai(dev); | ||
4030 | 4015 | ||
4031 | return ret; | 4016 | return ret; |
4032 | } | 4017 | } |
4033 | 4018 | ||
4034 | /** | 4019 | /** |
4035 | * snd_soc_unregister_dais - Unregister multiple DAIs from the ASoC core | ||
4036 | * | ||
4037 | * @dai: Array of DAIs to unregister | ||
4038 | * @count: Number of DAIs | ||
4039 | */ | ||
4040 | static void snd_soc_unregister_dais(struct device *dev, size_t count) | ||
4041 | { | ||
4042 | int i; | ||
4043 | |||
4044 | for (i = 0; i < count; i++) | ||
4045 | snd_soc_unregister_dai(dev); | ||
4046 | } | ||
4047 | |||
4048 | /** | ||
4049 | * snd_soc_register_component - Register a component with the ASoC core | 4020 | * snd_soc_register_component - Register a component with the ASoC core |
4050 | * | 4021 | * |
4051 | */ | 4022 | */ |
@@ -4053,6 +4024,7 @@ static int | |||
4053 | __snd_soc_register_component(struct device *dev, | 4024 | __snd_soc_register_component(struct device *dev, |
4054 | struct snd_soc_component *cmpnt, | 4025 | struct snd_soc_component *cmpnt, |
4055 | const struct snd_soc_component_driver *cmpnt_drv, | 4026 | const struct snd_soc_component_driver *cmpnt_drv, |
4027 | struct snd_soc_codec *codec, | ||
4056 | struct snd_soc_dai_driver *dai_drv, | 4028 | struct snd_soc_dai_driver *dai_drv, |
4057 | int num_dai, bool allow_single_dai) | 4029 | int num_dai, bool allow_single_dai) |
4058 | { | 4030 | { |
@@ -4075,20 +4047,10 @@ __snd_soc_register_component(struct device *dev, | |||
4075 | cmpnt->driver = cmpnt_drv; | 4047 | cmpnt->driver = cmpnt_drv; |
4076 | cmpnt->dai_drv = dai_drv; | 4048 | cmpnt->dai_drv = dai_drv; |
4077 | cmpnt->num_dai = num_dai; | 4049 | cmpnt->num_dai = num_dai; |
4050 | INIT_LIST_HEAD(&cmpnt->dai_list); | ||
4078 | 4051 | ||
4079 | /* | 4052 | ret = snd_soc_register_dais(cmpnt, codec, dai_drv, num_dai, |
4080 | * snd_soc_register_dai() uses fmt_single_name(), and | 4053 | allow_single_dai); |
4081 | * snd_soc_register_dais() uses fmt_multiple_name() | ||
4082 | * for dai->name which is used for name based matching | ||
4083 | * | ||
4084 | * this function is used from cpu/codec. | ||
4085 | * allow_single_dai flag can ignore "codec" driver reworking | ||
4086 | * since it had been used snd_soc_register_dais(), | ||
4087 | */ | ||
4088 | if ((1 == num_dai) && allow_single_dai) | ||
4089 | ret = snd_soc_register_dai(dev, dai_drv); | ||
4090 | else | ||
4091 | ret = snd_soc_register_dais(dev, dai_drv, num_dai); | ||
4092 | if (ret < 0) { | 4054 | if (ret < 0) { |
4093 | dev_err(dev, "ASoC: Failed to regster DAIs: %d\n", ret); | 4055 | dev_err(dev, "ASoC: Failed to regster DAIs: %d\n", ret); |
4094 | goto error_component_name; | 4056 | goto error_component_name; |
@@ -4121,7 +4083,9 @@ int snd_soc_register_component(struct device *dev, | |||
4121 | return -ENOMEM; | 4083 | return -ENOMEM; |
4122 | } | 4084 | } |
4123 | 4085 | ||
4124 | return __snd_soc_register_component(dev, cmpnt, cmpnt_drv, | 4086 | cmpnt->ignore_pmdown_time = true; |
4087 | |||
4088 | return __snd_soc_register_component(dev, cmpnt, cmpnt_drv, NULL, | ||
4125 | dai_drv, num_dai, true); | 4089 | dai_drv, num_dai, true); |
4126 | } | 4090 | } |
4127 | EXPORT_SYMBOL_GPL(snd_soc_register_component); | 4091 | EXPORT_SYMBOL_GPL(snd_soc_register_component); |
@@ -4141,7 +4105,7 @@ void snd_soc_unregister_component(struct device *dev) | |||
4141 | return; | 4105 | return; |
4142 | 4106 | ||
4143 | found: | 4107 | found: |
4144 | snd_soc_unregister_dais(dev, cmpnt->num_dai); | 4108 | snd_soc_unregister_dais(cmpnt); |
4145 | 4109 | ||
4146 | mutex_lock(&client_mutex); | 4110 | mutex_lock(&client_mutex); |
4147 | list_del(&cmpnt->list); | 4111 | list_del(&cmpnt->list); |
@@ -4319,7 +4283,7 @@ int snd_soc_register_codec(struct device *dev, | |||
4319 | codec->volatile_register = codec_drv->volatile_register; | 4283 | codec->volatile_register = codec_drv->volatile_register; |
4320 | codec->readable_register = codec_drv->readable_register; | 4284 | codec->readable_register = codec_drv->readable_register; |
4321 | codec->writable_register = codec_drv->writable_register; | 4285 | codec->writable_register = codec_drv->writable_register; |
4322 | codec->ignore_pmdown_time = codec_drv->ignore_pmdown_time; | 4286 | codec->component.ignore_pmdown_time = codec_drv->ignore_pmdown_time; |
4323 | codec->dapm.bias_level = SND_SOC_BIAS_OFF; | 4287 | codec->dapm.bias_level = SND_SOC_BIAS_OFF; |
4324 | codec->dapm.dev = dev; | 4288 | codec->dapm.dev = dev; |
4325 | codec->dapm.codec = codec; | 4289 | codec->dapm.codec = codec; |
@@ -4342,7 +4306,7 @@ int snd_soc_register_codec(struct device *dev, | |||
4342 | /* register component */ | 4306 | /* register component */ |
4343 | ret = __snd_soc_register_component(dev, &codec->component, | 4307 | ret = __snd_soc_register_component(dev, &codec->component, |
4344 | &codec_drv->component_driver, | 4308 | &codec_drv->component_driver, |
4345 | dai_drv, num_dai, false); | 4309 | codec, dai_drv, num_dai, false); |
4346 | if (ret < 0) { | 4310 | if (ret < 0) { |
4347 | dev_err(codec->dev, "ASoC: Failed to regster component: %d\n", ret); | 4311 | dev_err(codec->dev, "ASoC: Failed to regster component: %d\n", ret); |
4348 | goto fail_codec_name; | 4312 | goto fail_codec_name; |
@@ -4417,6 +4381,122 @@ int snd_soc_of_parse_card_name(struct snd_soc_card *card, | |||
4417 | } | 4381 | } |
4418 | EXPORT_SYMBOL_GPL(snd_soc_of_parse_card_name); | 4382 | EXPORT_SYMBOL_GPL(snd_soc_of_parse_card_name); |
4419 | 4383 | ||
4384 | static const struct snd_soc_dapm_widget simple_widgets[] = { | ||
4385 | SND_SOC_DAPM_MIC("Microphone", NULL), | ||
4386 | SND_SOC_DAPM_LINE("Line", NULL), | ||
4387 | SND_SOC_DAPM_HP("Headphone", NULL), | ||
4388 | SND_SOC_DAPM_SPK("Speaker", NULL), | ||
4389 | }; | ||
4390 | |||
4391 | int snd_soc_of_parse_audio_simple_widgets(struct snd_soc_card *card, | ||
4392 | const char *propname) | ||
4393 | { | ||
4394 | struct device_node *np = card->dev->of_node; | ||
4395 | struct snd_soc_dapm_widget *widgets; | ||
4396 | const char *template, *wname; | ||
4397 | int i, j, num_widgets, ret; | ||
4398 | |||
4399 | num_widgets = of_property_count_strings(np, propname); | ||
4400 | if (num_widgets < 0) { | ||
4401 | dev_err(card->dev, | ||
4402 | "ASoC: Property '%s' does not exist\n", propname); | ||
4403 | return -EINVAL; | ||
4404 | } | ||
4405 | if (num_widgets & 1) { | ||
4406 | dev_err(card->dev, | ||
4407 | "ASoC: Property '%s' length is not even\n", propname); | ||
4408 | return -EINVAL; | ||
4409 | } | ||
4410 | |||
4411 | num_widgets /= 2; | ||
4412 | if (!num_widgets) { | ||
4413 | dev_err(card->dev, "ASoC: Property '%s's length is zero\n", | ||
4414 | propname); | ||
4415 | return -EINVAL; | ||
4416 | } | ||
4417 | |||
4418 | widgets = devm_kcalloc(card->dev, num_widgets, sizeof(*widgets), | ||
4419 | GFP_KERNEL); | ||
4420 | if (!widgets) { | ||
4421 | dev_err(card->dev, | ||
4422 | "ASoC: Could not allocate memory for widgets\n"); | ||
4423 | return -ENOMEM; | ||
4424 | } | ||
4425 | |||
4426 | for (i = 0; i < num_widgets; i++) { | ||
4427 | ret = of_property_read_string_index(np, propname, | ||
4428 | 2 * i, &template); | ||
4429 | if (ret) { | ||
4430 | dev_err(card->dev, | ||
4431 | "ASoC: Property '%s' index %d read error:%d\n", | ||
4432 | propname, 2 * i, ret); | ||
4433 | return -EINVAL; | ||
4434 | } | ||
4435 | |||
4436 | for (j = 0; j < ARRAY_SIZE(simple_widgets); j++) { | ||
4437 | if (!strncmp(template, simple_widgets[j].name, | ||
4438 | strlen(simple_widgets[j].name))) { | ||
4439 | widgets[i] = simple_widgets[j]; | ||
4440 | break; | ||
4441 | } | ||
4442 | } | ||
4443 | |||
4444 | if (j >= ARRAY_SIZE(simple_widgets)) { | ||
4445 | dev_err(card->dev, | ||
4446 | "ASoC: DAPM widget '%s' is not supported\n", | ||
4447 | template); | ||
4448 | return -EINVAL; | ||
4449 | } | ||
4450 | |||
4451 | ret = of_property_read_string_index(np, propname, | ||
4452 | (2 * i) + 1, | ||
4453 | &wname); | ||
4454 | if (ret) { | ||
4455 | dev_err(card->dev, | ||
4456 | "ASoC: Property '%s' index %d read error:%d\n", | ||
4457 | propname, (2 * i) + 1, ret); | ||
4458 | return -EINVAL; | ||
4459 | } | ||
4460 | |||
4461 | widgets[i].name = wname; | ||
4462 | } | ||
4463 | |||
4464 | card->dapm_widgets = widgets; | ||
4465 | card->num_dapm_widgets = num_widgets; | ||
4466 | |||
4467 | return 0; | ||
4468 | } | ||
4469 | EXPORT_SYMBOL_GPL(snd_soc_of_parse_audio_simple_widgets); | ||
4470 | |||
4471 | int snd_soc_of_parse_tdm_slot(struct device_node *np, | ||
4472 | unsigned int *slots, | ||
4473 | unsigned int *slot_width) | ||
4474 | { | ||
4475 | u32 val; | ||
4476 | int ret; | ||
4477 | |||
4478 | if (of_property_read_bool(np, "dai-tdm-slot-num")) { | ||
4479 | ret = of_property_read_u32(np, "dai-tdm-slot-num", &val); | ||
4480 | if (ret) | ||
4481 | return ret; | ||
4482 | |||
4483 | if (slots) | ||
4484 | *slots = val; | ||
4485 | } | ||
4486 | |||
4487 | if (of_property_read_bool(np, "dai-tdm-slot-width")) { | ||
4488 | ret = of_property_read_u32(np, "dai-tdm-slot-width", &val); | ||
4489 | if (ret) | ||
4490 | return ret; | ||
4491 | |||
4492 | if (slot_width) | ||
4493 | *slot_width = val; | ||
4494 | } | ||
4495 | |||
4496 | return 0; | ||
4497 | } | ||
4498 | EXPORT_SYMBOL_GPL(snd_soc_of_parse_tdm_slot); | ||
4499 | |||
4420 | int snd_soc_of_parse_audio_routing(struct snd_soc_card *card, | 4500 | int snd_soc_of_parse_audio_routing(struct snd_soc_card *card, |
4421 | const char *propname) | 4501 | const char *propname) |
4422 | { | 4502 | { |