aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/soc-core.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/soc-core.c')
-rw-r--r--sound/soc/soc-core.c74
1 files changed, 67 insertions, 7 deletions
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index a9786ab70504..fc0fd3485e7d 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -2763,6 +2763,25 @@ int snd_soc_bytes_get(struct snd_kcontrol *kcontrol,
2763 else 2763 else
2764 ret = -EINVAL; 2764 ret = -EINVAL;
2765 2765
2766 /* Hide any masked bytes to ensure consistent data reporting */
2767 if (ret == 0 && params->mask) {
2768 switch (codec->val_bytes) {
2769 case 1:
2770 ucontrol->value.bytes.data[0] &= ~params->mask;
2771 break;
2772 case 2:
2773 ((u16 *)(&ucontrol->value.bytes.data))[0]
2774 &= ~params->mask;
2775 break;
2776 case 4:
2777 ((u32 *)(&ucontrol->value.bytes.data))[0]
2778 &= ~params->mask;
2779 break;
2780 default:
2781 return -EINVAL;
2782 }
2783 }
2784
2766 return ret; 2785 return ret;
2767} 2786}
2768EXPORT_SYMBOL_GPL(snd_soc_bytes_get); 2787EXPORT_SYMBOL_GPL(snd_soc_bytes_get);
@@ -2772,14 +2791,55 @@ int snd_soc_bytes_put(struct snd_kcontrol *kcontrol,
2772{ 2791{
2773 struct soc_bytes *params = (void *)kcontrol->private_value; 2792 struct soc_bytes *params = (void *)kcontrol->private_value;
2774 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); 2793 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
2775 int ret; 2794 int ret, len;
2795 unsigned int val;
2796 void *data;
2776 2797
2777 if (codec->using_regmap) 2798 if (!codec->using_regmap)
2778 ret = regmap_raw_write(codec->control_data, params->base, 2799 return -EINVAL;
2779 ucontrol->value.bytes.data, 2800
2780 params->num_regs * codec->val_bytes); 2801 data = ucontrol->value.bytes.data;
2781 else 2802 len = params->num_regs * codec->val_bytes;
2782 ret = -EINVAL; 2803
2804 /*
2805 * If we've got a mask then we need to preserve the register
2806 * bits. We shouldn't modify the incoming data so take a
2807 * copy.
2808 */
2809 if (params->mask) {
2810 ret = regmap_read(codec->control_data, params->base, &val);
2811 if (ret != 0)
2812 return ret;
2813
2814 val &= params->mask;
2815
2816 data = kmemdup(data, len, GFP_KERNEL);
2817 if (!data)
2818 return -ENOMEM;
2819
2820 switch (codec->val_bytes) {
2821 case 1:
2822 ((u8 *)data)[0] &= ~params->mask;
2823 ((u8 *)data)[0] |= val;
2824 break;
2825 case 2:
2826 ((u16 *)data)[0] &= cpu_to_be16(~params->mask);
2827 ((u16 *)data)[0] |= cpu_to_be16(val);
2828 break;
2829 case 4:
2830 ((u32 *)data)[0] &= cpu_to_be32(~params->mask);
2831 ((u32 *)data)[0] |= cpu_to_be32(val);
2832 break;
2833 default:
2834 return -EINVAL;
2835 }
2836 }
2837
2838 ret = regmap_raw_write(codec->control_data, params->base,
2839 data, len);
2840
2841 if (params->mask)
2842 kfree(data);
2783 2843
2784 return ret; 2844 return ret;
2785} 2845}