14eef5a90SKuninori Morimoto // SPDX-License-Identifier: GPL-2.0+
24eef5a90SKuninori Morimoto //
34eef5a90SKuninori Morimoto // soc-ops.c -- Generic ASoC operations
44eef5a90SKuninori Morimoto //
54eef5a90SKuninori Morimoto // Copyright 2005 Wolfson Microelectronics PLC.
64eef5a90SKuninori Morimoto // Copyright 2005 Openedhand Ltd.
74eef5a90SKuninori Morimoto // Copyright (C) 2010 Slimlogic Ltd.
84eef5a90SKuninori Morimoto // Copyright (C) 2010 Texas Instruments Inc.
94eef5a90SKuninori Morimoto //
104eef5a90SKuninori Morimoto // Author: Liam Girdwood <lrg@slimlogic.co.uk>
114eef5a90SKuninori Morimoto // with code, comments and ideas from :-
124eef5a90SKuninori Morimoto // Richard Purdie <richard@openedhand.com>
137077148fSMark Brown
14*1a7b8468SKrzysztof Kozlowski #include <linux/cleanup.h>
157077148fSMark Brown #include <linux/module.h>
167077148fSMark Brown #include <linux/moduleparam.h>
177077148fSMark Brown #include <linux/init.h>
187077148fSMark Brown #include <linux/pm.h>
197077148fSMark Brown #include <linux/bitops.h>
207077148fSMark Brown #include <linux/ctype.h>
217077148fSMark Brown #include <linux/slab.h>
227077148fSMark Brown #include <sound/core.h>
237077148fSMark Brown #include <sound/jack.h>
247077148fSMark Brown #include <sound/pcm.h>
257077148fSMark Brown #include <sound/pcm_params.h>
267077148fSMark Brown #include <sound/soc.h>
277077148fSMark Brown #include <sound/soc-dpcm.h>
287077148fSMark Brown #include <sound/initval.h>
297077148fSMark Brown
307077148fSMark Brown /**
317077148fSMark Brown * snd_soc_info_enum_double - enumerated double mixer info callback
327077148fSMark Brown * @kcontrol: mixer control
337077148fSMark Brown * @uinfo: control element information
347077148fSMark Brown *
357077148fSMark Brown * Callback to provide information about a double enumerated
367077148fSMark Brown * mixer control.
377077148fSMark Brown *
387077148fSMark Brown * Returns 0 for success.
397077148fSMark Brown */
snd_soc_info_enum_double(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)407077148fSMark Brown int snd_soc_info_enum_double(struct snd_kcontrol *kcontrol,
417077148fSMark Brown struct snd_ctl_elem_info *uinfo)
427077148fSMark Brown {
437077148fSMark Brown struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
447077148fSMark Brown
457077148fSMark Brown return snd_ctl_enum_info(uinfo, e->shift_l == e->shift_r ? 1 : 2,
467077148fSMark Brown e->items, e->texts);
477077148fSMark Brown }
487077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_info_enum_double);
497077148fSMark Brown
507077148fSMark Brown /**
517077148fSMark Brown * snd_soc_get_enum_double - enumerated double mixer get callback
527077148fSMark Brown * @kcontrol: mixer control
537077148fSMark Brown * @ucontrol: control element information
547077148fSMark Brown *
557077148fSMark Brown * Callback to get the value of a double enumerated mixer.
567077148fSMark Brown *
577077148fSMark Brown * Returns 0 for success.
587077148fSMark Brown */
snd_soc_get_enum_double(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)597077148fSMark Brown int snd_soc_get_enum_double(struct snd_kcontrol *kcontrol,
607077148fSMark Brown struct snd_ctl_elem_value *ucontrol)
617077148fSMark Brown {
627077148fSMark Brown struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
637077148fSMark Brown struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
647077148fSMark Brown unsigned int val, item;
657077148fSMark Brown unsigned int reg_val;
667077148fSMark Brown
67cf6e26c7SKuninori Morimoto reg_val = snd_soc_component_read(component, e->reg);
687077148fSMark Brown val = (reg_val >> e->shift_l) & e->mask;
697077148fSMark Brown item = snd_soc_enum_val_to_item(e, val);
707077148fSMark Brown ucontrol->value.enumerated.item[0] = item;
717077148fSMark Brown if (e->shift_l != e->shift_r) {
72189f06c0SJaswinder Jassal val = (reg_val >> e->shift_r) & e->mask;
737077148fSMark Brown item = snd_soc_enum_val_to_item(e, val);
747077148fSMark Brown ucontrol->value.enumerated.item[1] = item;
757077148fSMark Brown }
767077148fSMark Brown
777077148fSMark Brown return 0;
787077148fSMark Brown }
797077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_get_enum_double);
807077148fSMark Brown
817077148fSMark Brown /**
827077148fSMark Brown * snd_soc_put_enum_double - enumerated double mixer put callback
837077148fSMark Brown * @kcontrol: mixer control
847077148fSMark Brown * @ucontrol: control element information
857077148fSMark Brown *
867077148fSMark Brown * Callback to set the value of a double enumerated mixer.
877077148fSMark Brown *
887077148fSMark Brown * Returns 0 for success.
897077148fSMark Brown */
snd_soc_put_enum_double(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)907077148fSMark Brown int snd_soc_put_enum_double(struct snd_kcontrol *kcontrol,
917077148fSMark Brown struct snd_ctl_elem_value *ucontrol)
927077148fSMark Brown {
937077148fSMark Brown struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
947077148fSMark Brown struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
957077148fSMark Brown unsigned int *item = ucontrol->value.enumerated.item;
967077148fSMark Brown unsigned int val;
977077148fSMark Brown unsigned int mask;
987077148fSMark Brown
997077148fSMark Brown if (item[0] >= e->items)
1007077148fSMark Brown return -EINVAL;
1017077148fSMark Brown val = snd_soc_enum_item_to_val(e, item[0]) << e->shift_l;
1027077148fSMark Brown mask = e->mask << e->shift_l;
1037077148fSMark Brown if (e->shift_l != e->shift_r) {
1047077148fSMark Brown if (item[1] >= e->items)
1057077148fSMark Brown return -EINVAL;
1067077148fSMark Brown val |= snd_soc_enum_item_to_val(e, item[1]) << e->shift_r;
1077077148fSMark Brown mask |= e->mask << e->shift_r;
1087077148fSMark Brown }
1097077148fSMark Brown
1107077148fSMark Brown return snd_soc_component_update_bits(component, e->reg, mask, val);
1117077148fSMark Brown }
1127077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_put_enum_double);
1137077148fSMark Brown
1147077148fSMark Brown /**
1158abab35fSCharles Keepax * snd_soc_read_signed - Read a codec register and interpret as signed value
1167077148fSMark Brown * @component: component
1177077148fSMark Brown * @reg: Register to read
1187077148fSMark Brown * @mask: Mask to use after shifting the register value
1197077148fSMark Brown * @shift: Right shift of register value
1207077148fSMark Brown * @sign_bit: Bit that describes if a number is negative or not.
1217077148fSMark Brown * @signed_val: Pointer to where the read value should be stored
1227077148fSMark Brown *
1237077148fSMark Brown * This functions reads a codec register. The register value is shifted right
1247077148fSMark Brown * by 'shift' bits and masked with the given 'mask'. Afterwards it translates
1257077148fSMark Brown * the given registervalue into a signed integer if sign_bit is non-zero.
1267077148fSMark Brown *
1277077148fSMark Brown * Returns 0 on sucess, otherwise an error value
1287077148fSMark Brown */
snd_soc_read_signed(struct snd_soc_component * component,unsigned int reg,unsigned int mask,unsigned int shift,unsigned int sign_bit,int * signed_val)1297077148fSMark Brown static int snd_soc_read_signed(struct snd_soc_component *component,
1307077148fSMark Brown unsigned int reg, unsigned int mask, unsigned int shift,
1317077148fSMark Brown unsigned int sign_bit, int *signed_val)
1327077148fSMark Brown {
1337077148fSMark Brown int ret;
1347077148fSMark Brown unsigned int val;
1357077148fSMark Brown
136cf6e26c7SKuninori Morimoto val = snd_soc_component_read(component, reg);
1377077148fSMark Brown val = (val >> shift) & mask;
1387077148fSMark Brown
1397077148fSMark Brown if (!sign_bit) {
1407077148fSMark Brown *signed_val = val;
1417077148fSMark Brown return 0;
1427077148fSMark Brown }
1437077148fSMark Brown
1447077148fSMark Brown /* non-negative number */
1457077148fSMark Brown if (!(val & BIT(sign_bit))) {
1467077148fSMark Brown *signed_val = val;
1477077148fSMark Brown return 0;
1487077148fSMark Brown }
1497077148fSMark Brown
1507077148fSMark Brown ret = val;
1517077148fSMark Brown
1527077148fSMark Brown /*
1537077148fSMark Brown * The register most probably does not contain a full-sized int.
1547077148fSMark Brown * Instead we have an arbitrary number of bits in a signed
1557077148fSMark Brown * representation which has to be translated into a full-sized int.
1567077148fSMark Brown * This is done by filling up all bits above the sign-bit.
1577077148fSMark Brown */
1587077148fSMark Brown ret |= ~((int)(BIT(sign_bit) - 1));
1597077148fSMark Brown
1607077148fSMark Brown *signed_val = ret;
1617077148fSMark Brown
1627077148fSMark Brown return 0;
1637077148fSMark Brown }
1647077148fSMark Brown
1657077148fSMark Brown /**
1667077148fSMark Brown * snd_soc_info_volsw - single mixer info callback
1677077148fSMark Brown * @kcontrol: mixer control
1687077148fSMark Brown * @uinfo: control element information
1697077148fSMark Brown *
1707077148fSMark Brown * Callback to provide information about a single mixer control, or a double
1717077148fSMark Brown * mixer control that spans 2 registers.
1727077148fSMark Brown *
1737077148fSMark Brown * Returns 0 for success.
1747077148fSMark Brown */
snd_soc_info_volsw(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)1757077148fSMark Brown int snd_soc_info_volsw(struct snd_kcontrol *kcontrol,
1767077148fSMark Brown struct snd_ctl_elem_info *uinfo)
1777077148fSMark Brown {
1787077148fSMark Brown struct soc_mixer_control *mc =
1797077148fSMark Brown (struct soc_mixer_control *)kcontrol->private_value;
180aa2a4b89SMark Brown const char *vol_string = NULL;
18130ac4984SMark Brown int max;
1827077148fSMark Brown
18330ac4984SMark Brown max = uinfo->value.integer.max = mc->max - mc->min;
18430ac4984SMark Brown if (mc->platform_max && mc->platform_max < max)
18530ac4984SMark Brown max = mc->platform_max;
1867077148fSMark Brown
187aa2a4b89SMark Brown if (max == 1) {
18844230200SStefan Binding /* Even two value controls ending in Volume should always be integer */
189aa2a4b89SMark Brown vol_string = strstr(kcontrol->id.name, " Volume");
19044230200SStefan Binding if (vol_string && !strcmp(vol_string, " Volume"))
1917077148fSMark Brown uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
19244230200SStefan Binding else
19344230200SStefan Binding uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
19444230200SStefan Binding } else {
19544230200SStefan Binding uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
19644230200SStefan Binding }
1977077148fSMark Brown
1987077148fSMark Brown uinfo->count = snd_soc_volsw_is_stereo(mc) ? 2 : 1;
1997077148fSMark Brown uinfo->value.integer.min = 0;
20030ac4984SMark Brown uinfo->value.integer.max = max;
20130ac4984SMark Brown
2027077148fSMark Brown return 0;
2037077148fSMark Brown }
2047077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_info_volsw);
2057077148fSMark Brown
2067077148fSMark Brown /**
20734198710SCharles Keepax * snd_soc_info_volsw_sx - Mixer info callback for SX TLV controls
20834198710SCharles Keepax * @kcontrol: mixer control
20934198710SCharles Keepax * @uinfo: control element information
21034198710SCharles Keepax *
21134198710SCharles Keepax * Callback to provide information about a single mixer control, or a double
21234198710SCharles Keepax * mixer control that spans 2 registers of the SX TLV type. SX TLV controls
21334198710SCharles Keepax * have a range that represents both positive and negative values either side
21499b5c107SMark Brown * of zero but without a sign bit. min is the minimum register value, max is
21599b5c107SMark Brown * the number of steps.
21634198710SCharles Keepax *
21734198710SCharles Keepax * Returns 0 for success.
21834198710SCharles Keepax */
snd_soc_info_volsw_sx(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)21934198710SCharles Keepax int snd_soc_info_volsw_sx(struct snd_kcontrol *kcontrol,
22034198710SCharles Keepax struct snd_ctl_elem_info *uinfo)
22134198710SCharles Keepax {
22234198710SCharles Keepax struct soc_mixer_control *mc =
22334198710SCharles Keepax (struct soc_mixer_control *)kcontrol->private_value;
22499b5c107SMark Brown int max;
22534198710SCharles Keepax
22699b5c107SMark Brown if (mc->platform_max)
22799b5c107SMark Brown max = mc->platform_max;
22899b5c107SMark Brown else
22999b5c107SMark Brown max = mc->max;
23099b5c107SMark Brown
23199b5c107SMark Brown if (max == 1 && !strstr(kcontrol->id.name, " Volume"))
23299b5c107SMark Brown uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
23399b5c107SMark Brown else
23499b5c107SMark Brown uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
23599b5c107SMark Brown
23699b5c107SMark Brown uinfo->count = snd_soc_volsw_is_stereo(mc) ? 2 : 1;
23799b5c107SMark Brown uinfo->value.integer.min = 0;
23899b5c107SMark Brown uinfo->value.integer.max = max;
23934198710SCharles Keepax
24034198710SCharles Keepax return 0;
24134198710SCharles Keepax }
24234198710SCharles Keepax EXPORT_SYMBOL_GPL(snd_soc_info_volsw_sx);
24334198710SCharles Keepax
24434198710SCharles Keepax /**
2457077148fSMark Brown * snd_soc_get_volsw - single mixer get callback
2467077148fSMark Brown * @kcontrol: mixer control
2477077148fSMark Brown * @ucontrol: control element information
2487077148fSMark Brown *
2497077148fSMark Brown * Callback to get the value of a single mixer control, or a double mixer
2507077148fSMark Brown * control that spans 2 registers.
2517077148fSMark Brown *
2527077148fSMark Brown * Returns 0 for success.
2537077148fSMark Brown */
snd_soc_get_volsw(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)2547077148fSMark Brown int snd_soc_get_volsw(struct snd_kcontrol *kcontrol,
2557077148fSMark Brown struct snd_ctl_elem_value *ucontrol)
2567077148fSMark Brown {
2577077148fSMark Brown struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
2587077148fSMark Brown struct soc_mixer_control *mc =
2597077148fSMark Brown (struct soc_mixer_control *)kcontrol->private_value;
2607077148fSMark Brown unsigned int reg = mc->reg;
2617077148fSMark Brown unsigned int reg2 = mc->rreg;
2627077148fSMark Brown unsigned int shift = mc->shift;
2637077148fSMark Brown unsigned int rshift = mc->rshift;
2647077148fSMark Brown int max = mc->max;
2657077148fSMark Brown int min = mc->min;
2667077148fSMark Brown int sign_bit = mc->sign_bit;
267fc563aa9SStephen Lee unsigned int mask = (1ULL << fls(max)) - 1;
2687077148fSMark Brown unsigned int invert = mc->invert;
2697077148fSMark Brown int val;
2707077148fSMark Brown int ret;
2717077148fSMark Brown
2727077148fSMark Brown if (sign_bit)
2737077148fSMark Brown mask = BIT(sign_bit + 1) - 1;
2747077148fSMark Brown
2757077148fSMark Brown ret = snd_soc_read_signed(component, reg, mask, shift, sign_bit, &val);
2767077148fSMark Brown if (ret)
2777077148fSMark Brown return ret;
2787077148fSMark Brown
2797077148fSMark Brown ucontrol->value.integer.value[0] = val - min;
2807077148fSMark Brown if (invert)
2817077148fSMark Brown ucontrol->value.integer.value[0] =
2827077148fSMark Brown max - ucontrol->value.integer.value[0];
2837077148fSMark Brown
2847077148fSMark Brown if (snd_soc_volsw_is_stereo(mc)) {
2857077148fSMark Brown if (reg == reg2)
2867077148fSMark Brown ret = snd_soc_read_signed(component, reg, mask, rshift,
2877077148fSMark Brown sign_bit, &val);
2887077148fSMark Brown else
2897077148fSMark Brown ret = snd_soc_read_signed(component, reg2, mask, shift,
2907077148fSMark Brown sign_bit, &val);
2917077148fSMark Brown if (ret)
2927077148fSMark Brown return ret;
2937077148fSMark Brown
2947077148fSMark Brown ucontrol->value.integer.value[1] = val - min;
2957077148fSMark Brown if (invert)
2967077148fSMark Brown ucontrol->value.integer.value[1] =
2977077148fSMark Brown max - ucontrol->value.integer.value[1];
2987077148fSMark Brown }
2997077148fSMark Brown
3007077148fSMark Brown return 0;
3017077148fSMark Brown }
3027077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_get_volsw);
3037077148fSMark Brown
3047077148fSMark Brown /**
3057077148fSMark Brown * snd_soc_put_volsw - single mixer put callback
3067077148fSMark Brown * @kcontrol: mixer control
3077077148fSMark Brown * @ucontrol: control element information
3087077148fSMark Brown *
3097077148fSMark Brown * Callback to set the value of a single mixer control, or a double mixer
3107077148fSMark Brown * control that spans 2 registers.
3117077148fSMark Brown *
3127077148fSMark Brown * Returns 0 for success.
3137077148fSMark Brown */
snd_soc_put_volsw(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)3147077148fSMark Brown int snd_soc_put_volsw(struct snd_kcontrol *kcontrol,
3157077148fSMark Brown struct snd_ctl_elem_value *ucontrol)
3167077148fSMark Brown {
3177077148fSMark Brown struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
3187077148fSMark Brown struct soc_mixer_control *mc =
3197077148fSMark Brown (struct soc_mixer_control *)kcontrol->private_value;
3207077148fSMark Brown unsigned int reg = mc->reg;
3217077148fSMark Brown unsigned int reg2 = mc->rreg;
3227077148fSMark Brown unsigned int shift = mc->shift;
3237077148fSMark Brown unsigned int rshift = mc->rshift;
3247077148fSMark Brown int max = mc->max;
3257077148fSMark Brown int min = mc->min;
3267077148fSMark Brown unsigned int sign_bit = mc->sign_bit;
3277077148fSMark Brown unsigned int mask = (1 << fls(max)) - 1;
3287077148fSMark Brown unsigned int invert = mc->invert;
329564778d7SMark Brown int err, ret;
3307077148fSMark Brown bool type_2r = false;
3317077148fSMark Brown unsigned int val2 = 0;
3327077148fSMark Brown unsigned int val, val_mask;
3337077148fSMark Brown
3347077148fSMark Brown if (sign_bit)
3357077148fSMark Brown mask = BIT(sign_bit + 1) - 1;
3367077148fSMark Brown
3371601033dSMark Brown if (ucontrol->value.integer.value[0] < 0)
3381601033dSMark Brown return -EINVAL;
339817f7c93SMark Brown val = ucontrol->value.integer.value[0];
3409bdd10d5SMarek Vasut if (mc->platform_max && ((int)val + min) > mc->platform_max)
341817f7c93SMark Brown return -EINVAL;
342817f7c93SMark Brown if (val > max - min)
343817f7c93SMark Brown return -EINVAL;
344817f7c93SMark Brown val = (val + min) & mask;
3457077148fSMark Brown if (invert)
3467077148fSMark Brown val = max - val;
3477077148fSMark Brown val_mask = mask << shift;
3487077148fSMark Brown val = val << shift;
3497077148fSMark Brown if (snd_soc_volsw_is_stereo(mc)) {
3501601033dSMark Brown if (ucontrol->value.integer.value[1] < 0)
3511601033dSMark Brown return -EINVAL;
352817f7c93SMark Brown val2 = ucontrol->value.integer.value[1];
3539bdd10d5SMarek Vasut if (mc->platform_max && ((int)val2 + min) > mc->platform_max)
354817f7c93SMark Brown return -EINVAL;
355817f7c93SMark Brown if (val2 > max - min)
356817f7c93SMark Brown return -EINVAL;
357817f7c93SMark Brown val2 = (val2 + min) & mask;
3587077148fSMark Brown if (invert)
3597077148fSMark Brown val2 = max - val2;
3607077148fSMark Brown if (reg == reg2) {
3617077148fSMark Brown val_mask |= mask << rshift;
3627077148fSMark Brown val |= val2 << rshift;
3637077148fSMark Brown } else {
3647077148fSMark Brown val2 = val2 << shift;
3657077148fSMark Brown type_2r = true;
3667077148fSMark Brown }
3677077148fSMark Brown }
3687077148fSMark Brown err = snd_soc_component_update_bits(component, reg, val_mask, val);
3697077148fSMark Brown if (err < 0)
3707077148fSMark Brown return err;
371564778d7SMark Brown ret = err;
3727077148fSMark Brown
373564778d7SMark Brown if (type_2r) {
3747077148fSMark Brown err = snd_soc_component_update_bits(component, reg2, val_mask,
3757077148fSMark Brown val2);
376564778d7SMark Brown /* Don't discard any error code or drop change flag */
377564778d7SMark Brown if (ret == 0 || err < 0) {
378564778d7SMark Brown ret = err;
379564778d7SMark Brown }
380564778d7SMark Brown }
3817077148fSMark Brown
382564778d7SMark Brown return ret;
3837077148fSMark Brown }
3847077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_put_volsw);
3857077148fSMark Brown
3867077148fSMark Brown /**
3877077148fSMark Brown * snd_soc_get_volsw_sx - single mixer get callback
3887077148fSMark Brown * @kcontrol: mixer control
3897077148fSMark Brown * @ucontrol: control element information
3907077148fSMark Brown *
3917077148fSMark Brown * Callback to get the value of a single mixer control, or a double mixer
3927077148fSMark Brown * control that spans 2 registers.
3937077148fSMark Brown *
3947077148fSMark Brown * Returns 0 for success.
3957077148fSMark Brown */
snd_soc_get_volsw_sx(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)3967077148fSMark Brown int snd_soc_get_volsw_sx(struct snd_kcontrol *kcontrol,
3977077148fSMark Brown struct snd_ctl_elem_value *ucontrol)
3987077148fSMark Brown {
3997077148fSMark Brown struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
4007077148fSMark Brown struct soc_mixer_control *mc =
4017077148fSMark Brown (struct soc_mixer_control *)kcontrol->private_value;
4027077148fSMark Brown unsigned int reg = mc->reg;
4037077148fSMark Brown unsigned int reg2 = mc->rreg;
4047077148fSMark Brown unsigned int shift = mc->shift;
4057077148fSMark Brown unsigned int rshift = mc->rshift;
4067077148fSMark Brown int max = mc->max;
4077077148fSMark Brown int min = mc->min;
408ae7d1247SRohit kumar unsigned int mask = (1U << (fls(min + max) - 1)) - 1;
4097077148fSMark Brown unsigned int val;
4107077148fSMark Brown
411cf6e26c7SKuninori Morimoto val = snd_soc_component_read(component, reg);
4127077148fSMark Brown ucontrol->value.integer.value[0] = ((val >> shift) - min) & mask;
4137077148fSMark Brown
4147077148fSMark Brown if (snd_soc_volsw_is_stereo(mc)) {
415cf6e26c7SKuninori Morimoto val = snd_soc_component_read(component, reg2);
4167077148fSMark Brown val = ((val >> rshift) - min) & mask;
4177077148fSMark Brown ucontrol->value.integer.value[1] = val;
4187077148fSMark Brown }
4197077148fSMark Brown
4207077148fSMark Brown return 0;
4217077148fSMark Brown }
4227077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_get_volsw_sx);
4237077148fSMark Brown
4247077148fSMark Brown /**
4257077148fSMark Brown * snd_soc_put_volsw_sx - double mixer set callback
4267077148fSMark Brown * @kcontrol: mixer control
4279a11ef7fSRandy Dunlap * @ucontrol: control element information
4287077148fSMark Brown *
4297077148fSMark Brown * Callback to set the value of a double mixer control that spans 2 registers.
4307077148fSMark Brown *
4317077148fSMark Brown * Returns 0 for success.
4327077148fSMark Brown */
snd_soc_put_volsw_sx(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)4337077148fSMark Brown int snd_soc_put_volsw_sx(struct snd_kcontrol *kcontrol,
4347077148fSMark Brown struct snd_ctl_elem_value *ucontrol)
4357077148fSMark Brown {
4367077148fSMark Brown struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
4377077148fSMark Brown struct soc_mixer_control *mc =
4387077148fSMark Brown (struct soc_mixer_control *)kcontrol->private_value;
4397077148fSMark Brown
4407077148fSMark Brown unsigned int reg = mc->reg;
4417077148fSMark Brown unsigned int reg2 = mc->rreg;
4427077148fSMark Brown unsigned int shift = mc->shift;
4437077148fSMark Brown unsigned int rshift = mc->rshift;
4447077148fSMark Brown int max = mc->max;
4457077148fSMark Brown int min = mc->min;
446ae7d1247SRohit kumar unsigned int mask = (1U << (fls(min + max) - 1)) - 1;
4477077148fSMark Brown int err = 0;
4487f3d90a3SMark Brown int ret;
44958f42dfdSKuninori Morimoto unsigned int val, val_mask;
4507077148fSMark Brown
4511601033dSMark Brown if (ucontrol->value.integer.value[0] < 0)
4521601033dSMark Brown return -EINVAL;
4534f1e50d6SMark Brown val = ucontrol->value.integer.value[0];
4544f1e50d6SMark Brown if (mc->platform_max && val > mc->platform_max)
4554f1e50d6SMark Brown return -EINVAL;
456698813baSMark Brown if (val > max)
4574f1e50d6SMark Brown return -EINVAL;
4587077148fSMark Brown val_mask = mask << shift;
4594f1e50d6SMark Brown val = (val + min) & mask;
4607077148fSMark Brown val = val << shift;
4617077148fSMark Brown
4627077148fSMark Brown err = snd_soc_component_update_bits(component, reg, val_mask, val);
4637077148fSMark Brown if (err < 0)
4647077148fSMark Brown return err;
4657f3d90a3SMark Brown ret = err;
4667077148fSMark Brown
4677077148fSMark Brown if (snd_soc_volsw_is_stereo(mc)) {
468f33bcc50SCharles Keepax unsigned int val2 = ucontrol->value.integer.value[1];
46997eea946SMark Brown
47097eea946SMark Brown if (mc->platform_max && val2 > mc->platform_max)
47197eea946SMark Brown return -EINVAL;
47297eea946SMark Brown if (val2 > max)
47397eea946SMark Brown return -EINVAL;
47497eea946SMark Brown
475f33bcc50SCharles Keepax val_mask = mask << rshift;
476f33bcc50SCharles Keepax val2 = (val2 + min) & mask;
4777077148fSMark Brown val2 = val2 << rshift;
4787077148fSMark Brown
4797077148fSMark Brown err = snd_soc_component_update_bits(component, reg2, val_mask,
4807077148fSMark Brown val2);
4817f3d90a3SMark Brown
4827f3d90a3SMark Brown /* Don't discard any error code or drop change flag */
4837f3d90a3SMark Brown if (ret == 0 || err < 0) {
4847f3d90a3SMark Brown ret = err;
4857f3d90a3SMark Brown }
4867077148fSMark Brown }
487eb577320SPierre-Louis Bossart return ret;
4887077148fSMark Brown }
4897077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_put_volsw_sx);
4907077148fSMark Brown
4917077148fSMark Brown /**
4927077148fSMark Brown * snd_soc_info_volsw_range - single mixer info callback with range.
4937077148fSMark Brown * @kcontrol: mixer control
4947077148fSMark Brown * @uinfo: control element information
4957077148fSMark Brown *
4967077148fSMark Brown * Callback to provide information, within a range, about a single
4977077148fSMark Brown * mixer control.
4987077148fSMark Brown *
4997077148fSMark Brown * returns 0 for success.
5007077148fSMark Brown */
snd_soc_info_volsw_range(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)5017077148fSMark Brown int snd_soc_info_volsw_range(struct snd_kcontrol *kcontrol,
5027077148fSMark Brown struct snd_ctl_elem_info *uinfo)
5037077148fSMark Brown {
5047077148fSMark Brown struct soc_mixer_control *mc =
5057077148fSMark Brown (struct soc_mixer_control *)kcontrol->private_value;
5067077148fSMark Brown int platform_max;
5077077148fSMark Brown int min = mc->min;
5087077148fSMark Brown
5097077148fSMark Brown if (!mc->platform_max)
5107077148fSMark Brown mc->platform_max = mc->max;
5117077148fSMark Brown platform_max = mc->platform_max;
5127077148fSMark Brown
5137077148fSMark Brown uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
5147077148fSMark Brown uinfo->count = snd_soc_volsw_is_stereo(mc) ? 2 : 1;
5157077148fSMark Brown uinfo->value.integer.min = 0;
5167077148fSMark Brown uinfo->value.integer.max = platform_max - min;
5177077148fSMark Brown
5187077148fSMark Brown return 0;
5197077148fSMark Brown }
5207077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_info_volsw_range);
5217077148fSMark Brown
5227077148fSMark Brown /**
5237077148fSMark Brown * snd_soc_put_volsw_range - single mixer put value callback with range.
5247077148fSMark Brown * @kcontrol: mixer control
5257077148fSMark Brown * @ucontrol: control element information
5267077148fSMark Brown *
5277077148fSMark Brown * Callback to set the value, within a range, for a single mixer control.
5287077148fSMark Brown *
5297077148fSMark Brown * Returns 0 for success.
5307077148fSMark Brown */
snd_soc_put_volsw_range(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)5317077148fSMark Brown int snd_soc_put_volsw_range(struct snd_kcontrol *kcontrol,
5327077148fSMark Brown struct snd_ctl_elem_value *ucontrol)
5337077148fSMark Brown {
5347077148fSMark Brown struct soc_mixer_control *mc =
5357077148fSMark Brown (struct soc_mixer_control *)kcontrol->private_value;
5367077148fSMark Brown struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
5377077148fSMark Brown unsigned int reg = mc->reg;
5387077148fSMark Brown unsigned int rreg = mc->rreg;
5397077148fSMark Brown unsigned int shift = mc->shift;
5407077148fSMark Brown int min = mc->min;
5417077148fSMark Brown int max = mc->max;
5427077148fSMark Brown unsigned int mask = (1 << fls(max)) - 1;
5437077148fSMark Brown unsigned int invert = mc->invert;
5447077148fSMark Brown unsigned int val, val_mask;
545aa22125cSMark Brown int err, ret, tmp;
546aa22125cSMark Brown
547aa22125cSMark Brown tmp = ucontrol->value.integer.value[0];
548aa22125cSMark Brown if (tmp < 0)
549aa22125cSMark Brown return -EINVAL;
550aa22125cSMark Brown if (mc->platform_max && tmp > mc->platform_max)
551aa22125cSMark Brown return -EINVAL;
5525871321fSMark Brown if (tmp > mc->max - mc->min)
553aa22125cSMark Brown return -EINVAL;
5547077148fSMark Brown
5557077148fSMark Brown if (invert)
5567077148fSMark Brown val = (max - ucontrol->value.integer.value[0]) & mask;
5577077148fSMark Brown else
5587077148fSMark Brown val = ((ucontrol->value.integer.value[0] + min) & mask);
5597077148fSMark Brown val_mask = mask << shift;
5607077148fSMark Brown val = val << shift;
5617077148fSMark Brown
562650204deSMark Brown err = snd_soc_component_update_bits(component, reg, val_mask, val);
563650204deSMark Brown if (err < 0)
564650204deSMark Brown return err;
565650204deSMark Brown ret = err;
5667077148fSMark Brown
5677077148fSMark Brown if (snd_soc_volsw_is_stereo(mc)) {
568aa22125cSMark Brown tmp = ucontrol->value.integer.value[1];
569aa22125cSMark Brown if (tmp < 0)
570aa22125cSMark Brown return -EINVAL;
571aa22125cSMark Brown if (mc->platform_max && tmp > mc->platform_max)
572aa22125cSMark Brown return -EINVAL;
5735871321fSMark Brown if (tmp > mc->max - mc->min)
574aa22125cSMark Brown return -EINVAL;
575aa22125cSMark Brown
5767077148fSMark Brown if (invert)
5777077148fSMark Brown val = (max - ucontrol->value.integer.value[1]) & mask;
5787077148fSMark Brown else
5797077148fSMark Brown val = ((ucontrol->value.integer.value[1] + min) & mask);
5807077148fSMark Brown val_mask = mask << shift;
5817077148fSMark Brown val = val << shift;
5827077148fSMark Brown
583650204deSMark Brown err = snd_soc_component_update_bits(component, rreg, val_mask,
5847077148fSMark Brown val);
585650204deSMark Brown /* Don't discard any error code or drop change flag */
586650204deSMark Brown if (ret == 0 || err < 0) {
587650204deSMark Brown ret = err;
588650204deSMark Brown }
5897077148fSMark Brown }
5907077148fSMark Brown
5917077148fSMark Brown return ret;
5927077148fSMark Brown }
5937077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_put_volsw_range);
5947077148fSMark Brown
5957077148fSMark Brown /**
5967077148fSMark Brown * snd_soc_get_volsw_range - single mixer get callback with range
5977077148fSMark Brown * @kcontrol: mixer control
5987077148fSMark Brown * @ucontrol: control element information
5997077148fSMark Brown *
6007077148fSMark Brown * Callback to get the value, within a range, of a single mixer control.
6017077148fSMark Brown *
6027077148fSMark Brown * Returns 0 for success.
6037077148fSMark Brown */
snd_soc_get_volsw_range(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)6047077148fSMark Brown int snd_soc_get_volsw_range(struct snd_kcontrol *kcontrol,
6057077148fSMark Brown struct snd_ctl_elem_value *ucontrol)
6067077148fSMark Brown {
6077077148fSMark Brown struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
6087077148fSMark Brown struct soc_mixer_control *mc =
6097077148fSMark Brown (struct soc_mixer_control *)kcontrol->private_value;
6107077148fSMark Brown unsigned int reg = mc->reg;
6117077148fSMark Brown unsigned int rreg = mc->rreg;
6127077148fSMark Brown unsigned int shift = mc->shift;
6137077148fSMark Brown int min = mc->min;
6147077148fSMark Brown int max = mc->max;
6157077148fSMark Brown unsigned int mask = (1 << fls(max)) - 1;
6167077148fSMark Brown unsigned int invert = mc->invert;
6177077148fSMark Brown unsigned int val;
6187077148fSMark Brown
619cf6e26c7SKuninori Morimoto val = snd_soc_component_read(component, reg);
6207077148fSMark Brown ucontrol->value.integer.value[0] = (val >> shift) & mask;
6217077148fSMark Brown if (invert)
6227077148fSMark Brown ucontrol->value.integer.value[0] =
6237077148fSMark Brown max - ucontrol->value.integer.value[0];
6247077148fSMark Brown else
6257077148fSMark Brown ucontrol->value.integer.value[0] =
6267077148fSMark Brown ucontrol->value.integer.value[0] - min;
6277077148fSMark Brown
6287077148fSMark Brown if (snd_soc_volsw_is_stereo(mc)) {
629cf6e26c7SKuninori Morimoto val = snd_soc_component_read(component, rreg);
6307077148fSMark Brown ucontrol->value.integer.value[1] = (val >> shift) & mask;
6317077148fSMark Brown if (invert)
6327077148fSMark Brown ucontrol->value.integer.value[1] =
6337077148fSMark Brown max - ucontrol->value.integer.value[1];
6347077148fSMark Brown else
6357077148fSMark Brown ucontrol->value.integer.value[1] =
6367077148fSMark Brown ucontrol->value.integer.value[1] - min;
6377077148fSMark Brown }
6387077148fSMark Brown
6397077148fSMark Brown return 0;
6407077148fSMark Brown }
6417077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_get_volsw_range);
6427077148fSMark Brown
6437077148fSMark Brown /**
6447077148fSMark Brown * snd_soc_limit_volume - Set new limit to an existing volume control.
6457077148fSMark Brown *
64626d9ca34SLars-Peter Clausen * @card: where to look for the control
6477077148fSMark Brown * @name: Name of the control
6487077148fSMark Brown * @max: new maximum limit
6497077148fSMark Brown *
6507077148fSMark Brown * Return 0 for success, else error.
6517077148fSMark Brown */
snd_soc_limit_volume(struct snd_soc_card * card,const char * name,int max)65226d9ca34SLars-Peter Clausen int snd_soc_limit_volume(struct snd_soc_card *card,
6537077148fSMark Brown const char *name, int max)
6547077148fSMark Brown {
6557077148fSMark Brown struct snd_kcontrol *kctl;
6567077148fSMark Brown int ret = -EINVAL;
6577077148fSMark Brown
6587077148fSMark Brown /* Sanity check for name and max */
6597077148fSMark Brown if (unlikely(!name || max <= 0))
6607077148fSMark Brown return -EINVAL;
6617077148fSMark Brown
6620881ab6eSKuninori Morimoto kctl = snd_soc_card_get_kcontrol(card, name);
6630881ab6eSKuninori Morimoto if (kctl) {
664872040f7SKuninori Morimoto struct soc_mixer_control *mc = (struct soc_mixer_control *)kctl->private_value;
665fb9ad244SSrinivas Kandagatla if (max <= mc->max - mc->min) {
6667077148fSMark Brown mc->platform_max = max;
6677077148fSMark Brown ret = 0;
6687077148fSMark Brown }
6697077148fSMark Brown }
6707077148fSMark Brown return ret;
6717077148fSMark Brown }
6727077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_limit_volume);
6737077148fSMark Brown
snd_soc_bytes_info(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)6747077148fSMark Brown int snd_soc_bytes_info(struct snd_kcontrol *kcontrol,
6757077148fSMark Brown struct snd_ctl_elem_info *uinfo)
6767077148fSMark Brown {
6777077148fSMark Brown struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
6787077148fSMark Brown struct soc_bytes *params = (void *)kcontrol->private_value;
6797077148fSMark Brown
6807077148fSMark Brown uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
6817077148fSMark Brown uinfo->count = params->num_regs * component->val_bytes;
6827077148fSMark Brown
6837077148fSMark Brown return 0;
6847077148fSMark Brown }
6857077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_bytes_info);
6867077148fSMark Brown
snd_soc_bytes_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)6877077148fSMark Brown int snd_soc_bytes_get(struct snd_kcontrol *kcontrol,
6887077148fSMark Brown struct snd_ctl_elem_value *ucontrol)
6897077148fSMark Brown {
6907077148fSMark Brown struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
6917077148fSMark Brown struct soc_bytes *params = (void *)kcontrol->private_value;
6927077148fSMark Brown int ret;
6937077148fSMark Brown
6947077148fSMark Brown if (component->regmap)
6957077148fSMark Brown ret = regmap_raw_read(component->regmap, params->base,
6967077148fSMark Brown ucontrol->value.bytes.data,
6977077148fSMark Brown params->num_regs * component->val_bytes);
6987077148fSMark Brown else
6997077148fSMark Brown ret = -EINVAL;
7007077148fSMark Brown
7017077148fSMark Brown /* Hide any masked bytes to ensure consistent data reporting */
7027077148fSMark Brown if (ret == 0 && params->mask) {
7037077148fSMark Brown switch (component->val_bytes) {
7047077148fSMark Brown case 1:
7057077148fSMark Brown ucontrol->value.bytes.data[0] &= ~params->mask;
7067077148fSMark Brown break;
7077077148fSMark Brown case 2:
7087077148fSMark Brown ((u16 *)(&ucontrol->value.bytes.data))[0]
7097077148fSMark Brown &= cpu_to_be16(~params->mask);
7107077148fSMark Brown break;
7117077148fSMark Brown case 4:
7127077148fSMark Brown ((u32 *)(&ucontrol->value.bytes.data))[0]
7137077148fSMark Brown &= cpu_to_be32(~params->mask);
7147077148fSMark Brown break;
7157077148fSMark Brown default:
7167077148fSMark Brown return -EINVAL;
7177077148fSMark Brown }
7187077148fSMark Brown }
7197077148fSMark Brown
7207077148fSMark Brown return ret;
7217077148fSMark Brown }
7227077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_bytes_get);
7237077148fSMark Brown
snd_soc_bytes_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)7247077148fSMark Brown int snd_soc_bytes_put(struct snd_kcontrol *kcontrol,
7257077148fSMark Brown struct snd_ctl_elem_value *ucontrol)
7267077148fSMark Brown {
7277077148fSMark Brown struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
7287077148fSMark Brown struct soc_bytes *params = (void *)kcontrol->private_value;
7297077148fSMark Brown int ret, len;
7307077148fSMark Brown unsigned int val, mask;
7317077148fSMark Brown
7327077148fSMark Brown if (!component->regmap || !params->num_regs)
7337077148fSMark Brown return -EINVAL;
7347077148fSMark Brown
7357077148fSMark Brown len = params->num_regs * component->val_bytes;
7367077148fSMark Brown
737*1a7b8468SKrzysztof Kozlowski void *data __free(kfree) = kmemdup(ucontrol->value.bytes.data, len,
738*1a7b8468SKrzysztof Kozlowski GFP_KERNEL | GFP_DMA);
7397077148fSMark Brown if (!data)
7407077148fSMark Brown return -ENOMEM;
7417077148fSMark Brown
7427077148fSMark Brown /*
7437077148fSMark Brown * If we've got a mask then we need to preserve the register
7447077148fSMark Brown * bits. We shouldn't modify the incoming data so take a
7457077148fSMark Brown * copy.
7467077148fSMark Brown */
7477077148fSMark Brown if (params->mask) {
7487077148fSMark Brown ret = regmap_read(component->regmap, params->base, &val);
7497077148fSMark Brown if (ret != 0)
750*1a7b8468SKrzysztof Kozlowski return ret;
7517077148fSMark Brown
7527077148fSMark Brown val &= params->mask;
7537077148fSMark Brown
7547077148fSMark Brown switch (component->val_bytes) {
7557077148fSMark Brown case 1:
7567077148fSMark Brown ((u8 *)data)[0] &= ~params->mask;
7577077148fSMark Brown ((u8 *)data)[0] |= val;
7587077148fSMark Brown break;
7597077148fSMark Brown case 2:
7607077148fSMark Brown mask = ~params->mask;
7617077148fSMark Brown ret = regmap_parse_val(component->regmap,
7627077148fSMark Brown &mask, &mask);
7637077148fSMark Brown if (ret != 0)
764*1a7b8468SKrzysztof Kozlowski return ret;
7657077148fSMark Brown
7667077148fSMark Brown ((u16 *)data)[0] &= mask;
7677077148fSMark Brown
7687077148fSMark Brown ret = regmap_parse_val(component->regmap,
7697077148fSMark Brown &val, &val);
7707077148fSMark Brown if (ret != 0)
771*1a7b8468SKrzysztof Kozlowski return ret;
7727077148fSMark Brown
7737077148fSMark Brown ((u16 *)data)[0] |= val;
7747077148fSMark Brown break;
7757077148fSMark Brown case 4:
7767077148fSMark Brown mask = ~params->mask;
7777077148fSMark Brown ret = regmap_parse_val(component->regmap,
7787077148fSMark Brown &mask, &mask);
7797077148fSMark Brown if (ret != 0)
780*1a7b8468SKrzysztof Kozlowski return ret;
7817077148fSMark Brown
7827077148fSMark Brown ((u32 *)data)[0] &= mask;
7837077148fSMark Brown
7847077148fSMark Brown ret = regmap_parse_val(component->regmap,
7857077148fSMark Brown &val, &val);
7867077148fSMark Brown if (ret != 0)
787*1a7b8468SKrzysztof Kozlowski return ret;
7887077148fSMark Brown
7897077148fSMark Brown ((u32 *)data)[0] |= val;
7907077148fSMark Brown break;
7917077148fSMark Brown default:
792*1a7b8468SKrzysztof Kozlowski return -EINVAL;
7937077148fSMark Brown }
7947077148fSMark Brown }
7957077148fSMark Brown
796*1a7b8468SKrzysztof Kozlowski return regmap_raw_write(component->regmap, params->base, data, len);
7977077148fSMark Brown }
7987077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_bytes_put);
7997077148fSMark Brown
snd_soc_bytes_info_ext(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * ucontrol)8007077148fSMark Brown int snd_soc_bytes_info_ext(struct snd_kcontrol *kcontrol,
8017077148fSMark Brown struct snd_ctl_elem_info *ucontrol)
8027077148fSMark Brown {
8037077148fSMark Brown struct soc_bytes_ext *params = (void *)kcontrol->private_value;
8047077148fSMark Brown
8057077148fSMark Brown ucontrol->type = SNDRV_CTL_ELEM_TYPE_BYTES;
8067077148fSMark Brown ucontrol->count = params->max;
8077077148fSMark Brown
8087077148fSMark Brown return 0;
8097077148fSMark Brown }
8107077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_bytes_info_ext);
8117077148fSMark Brown
snd_soc_bytes_tlv_callback(struct snd_kcontrol * kcontrol,int op_flag,unsigned int size,unsigned int __user * tlv)8127077148fSMark Brown int snd_soc_bytes_tlv_callback(struct snd_kcontrol *kcontrol, int op_flag,
8137077148fSMark Brown unsigned int size, unsigned int __user *tlv)
8147077148fSMark Brown {
8157077148fSMark Brown struct soc_bytes_ext *params = (void *)kcontrol->private_value;
8167077148fSMark Brown unsigned int count = size < params->max ? size : params->max;
8177077148fSMark Brown int ret = -ENXIO;
8187077148fSMark Brown
8197077148fSMark Brown switch (op_flag) {
8207077148fSMark Brown case SNDRV_CTL_TLV_OP_READ:
8217077148fSMark Brown if (params->get)
822a1e5e7e9SMythri P K ret = params->get(kcontrol, tlv, count);
8237077148fSMark Brown break;
8247077148fSMark Brown case SNDRV_CTL_TLV_OP_WRITE:
8257077148fSMark Brown if (params->put)
826a1e5e7e9SMythri P K ret = params->put(kcontrol, tlv, count);
8277077148fSMark Brown break;
8287077148fSMark Brown }
8297077148fSMark Brown return ret;
8307077148fSMark Brown }
8317077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_bytes_tlv_callback);
8327077148fSMark Brown
8337077148fSMark Brown /**
8347077148fSMark Brown * snd_soc_info_xr_sx - signed multi register info callback
8357077148fSMark Brown * @kcontrol: mreg control
8367077148fSMark Brown * @uinfo: control element information
8377077148fSMark Brown *
8387077148fSMark Brown * Callback to provide information of a control that can
8397077148fSMark Brown * span multiple codec registers which together
8407077148fSMark Brown * forms a single signed value in a MSB/LSB manner.
8417077148fSMark Brown *
8427077148fSMark Brown * Returns 0 for success.
8437077148fSMark Brown */
snd_soc_info_xr_sx(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)8447077148fSMark Brown int snd_soc_info_xr_sx(struct snd_kcontrol *kcontrol,
8457077148fSMark Brown struct snd_ctl_elem_info *uinfo)
8467077148fSMark Brown {
8477077148fSMark Brown struct soc_mreg_control *mc =
8487077148fSMark Brown (struct soc_mreg_control *)kcontrol->private_value;
8497077148fSMark Brown uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
8507077148fSMark Brown uinfo->count = 1;
8517077148fSMark Brown uinfo->value.integer.min = mc->min;
8527077148fSMark Brown uinfo->value.integer.max = mc->max;
8537077148fSMark Brown
8547077148fSMark Brown return 0;
8557077148fSMark Brown }
8567077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_info_xr_sx);
8577077148fSMark Brown
8587077148fSMark Brown /**
8597077148fSMark Brown * snd_soc_get_xr_sx - signed multi register get callback
8607077148fSMark Brown * @kcontrol: mreg control
8617077148fSMark Brown * @ucontrol: control element information
8627077148fSMark Brown *
8637077148fSMark Brown * Callback to get the value of a control that can span
8647077148fSMark Brown * multiple codec registers which together forms a single
8657077148fSMark Brown * signed value in a MSB/LSB manner. The control supports
8667077148fSMark Brown * specifying total no of bits used to allow for bitfields
8677077148fSMark Brown * across the multiple codec registers.
8687077148fSMark Brown *
8697077148fSMark Brown * Returns 0 for success.
8707077148fSMark Brown */
snd_soc_get_xr_sx(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)8717077148fSMark Brown int snd_soc_get_xr_sx(struct snd_kcontrol *kcontrol,
8727077148fSMark Brown struct snd_ctl_elem_value *ucontrol)
8737077148fSMark Brown {
8747077148fSMark Brown struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
8757077148fSMark Brown struct soc_mreg_control *mc =
8767077148fSMark Brown (struct soc_mreg_control *)kcontrol->private_value;
8777077148fSMark Brown unsigned int regbase = mc->regbase;
8787077148fSMark Brown unsigned int regcount = mc->regcount;
8797077148fSMark Brown unsigned int regwshift = component->val_bytes * BITS_PER_BYTE;
8800ab07091S이경택 unsigned int regwmask = (1UL<<regwshift)-1;
8817077148fSMark Brown unsigned int invert = mc->invert;
8827077148fSMark Brown unsigned long mask = (1UL<<mc->nbits)-1;
8837077148fSMark Brown long min = mc->min;
8847077148fSMark Brown long max = mc->max;
8857077148fSMark Brown long val = 0;
8867077148fSMark Brown unsigned int i;
8877077148fSMark Brown
8887077148fSMark Brown for (i = 0; i < regcount; i++) {
889b1ebecb9SKuninori Morimoto unsigned int regval = snd_soc_component_read(component, regbase+i);
8907077148fSMark Brown val |= (regval & regwmask) << (regwshift*(regcount-i-1));
8917077148fSMark Brown }
8927077148fSMark Brown val &= mask;
8937077148fSMark Brown if (min < 0 && val > max)
8947077148fSMark Brown val |= ~mask;
8957077148fSMark Brown if (invert)
8967077148fSMark Brown val = max - val;
8977077148fSMark Brown ucontrol->value.integer.value[0] = val;
8987077148fSMark Brown
8997077148fSMark Brown return 0;
9007077148fSMark Brown }
9017077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_get_xr_sx);
9027077148fSMark Brown
9037077148fSMark Brown /**
9047077148fSMark Brown * snd_soc_put_xr_sx - signed multi register get callback
9057077148fSMark Brown * @kcontrol: mreg control
9067077148fSMark Brown * @ucontrol: control element information
9077077148fSMark Brown *
9087077148fSMark Brown * Callback to set the value of a control that can span
9097077148fSMark Brown * multiple codec registers which together forms a single
9107077148fSMark Brown * signed value in a MSB/LSB manner. The control supports
9117077148fSMark Brown * specifying total no of bits used to allow for bitfields
9127077148fSMark Brown * across the multiple codec registers.
9137077148fSMark Brown *
9147077148fSMark Brown * Returns 0 for success.
9157077148fSMark Brown */
snd_soc_put_xr_sx(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)9167077148fSMark Brown int snd_soc_put_xr_sx(struct snd_kcontrol *kcontrol,
9177077148fSMark Brown struct snd_ctl_elem_value *ucontrol)
9187077148fSMark Brown {
9197077148fSMark Brown struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
9207077148fSMark Brown struct soc_mreg_control *mc =
9217077148fSMark Brown (struct soc_mreg_control *)kcontrol->private_value;
9227077148fSMark Brown unsigned int regbase = mc->regbase;
9237077148fSMark Brown unsigned int regcount = mc->regcount;
9247077148fSMark Brown unsigned int regwshift = component->val_bytes * BITS_PER_BYTE;
9250ab07091S이경택 unsigned int regwmask = (1UL<<regwshift)-1;
9267077148fSMark Brown unsigned int invert = mc->invert;
9277077148fSMark Brown unsigned long mask = (1UL<<mc->nbits)-1;
9287077148fSMark Brown long max = mc->max;
9297077148fSMark Brown long val = ucontrol->value.integer.value[0];
9302b7c4636SMark Brown int ret = 0;
931b285b510SKuninori Morimoto unsigned int i;
9327077148fSMark Brown
9334cf28e9aSMark Brown if (val < mc->min || val > mc->max)
9344cf28e9aSMark Brown return -EINVAL;
9357077148fSMark Brown if (invert)
9367077148fSMark Brown val = max - val;
9377077148fSMark Brown val &= mask;
9387077148fSMark Brown for (i = 0; i < regcount; i++) {
939b285b510SKuninori Morimoto unsigned int regval = (val >> (regwshift*(regcount-i-1))) & regwmask;
940b285b510SKuninori Morimoto unsigned int regmask = (mask >> (regwshift*(regcount-i-1))) & regwmask;
941b285b510SKuninori Morimoto int err = snd_soc_component_update_bits(component, regbase+i,
9427077148fSMark Brown regmask, regval);
9437077148fSMark Brown if (err < 0)
9447077148fSMark Brown return err;
9452b7c4636SMark Brown if (err > 0)
9462b7c4636SMark Brown ret = err;
9477077148fSMark Brown }
9487077148fSMark Brown
9492b7c4636SMark Brown return ret;
9507077148fSMark Brown }
9517077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_put_xr_sx);
9527077148fSMark Brown
9537077148fSMark Brown /**
9547077148fSMark Brown * snd_soc_get_strobe - strobe get callback
9557077148fSMark Brown * @kcontrol: mixer control
9567077148fSMark Brown * @ucontrol: control element information
9577077148fSMark Brown *
9587077148fSMark Brown * Callback get the value of a strobe mixer control.
9597077148fSMark Brown *
9607077148fSMark Brown * Returns 0 for success.
9617077148fSMark Brown */
snd_soc_get_strobe(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)9627077148fSMark Brown int snd_soc_get_strobe(struct snd_kcontrol *kcontrol,
9637077148fSMark Brown struct snd_ctl_elem_value *ucontrol)
9647077148fSMark Brown {
9657077148fSMark Brown struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
9667077148fSMark Brown struct soc_mixer_control *mc =
9677077148fSMark Brown (struct soc_mixer_control *)kcontrol->private_value;
9687077148fSMark Brown unsigned int reg = mc->reg;
9697077148fSMark Brown unsigned int shift = mc->shift;
9707077148fSMark Brown unsigned int mask = 1 << shift;
9717077148fSMark Brown unsigned int invert = mc->invert != 0;
9727077148fSMark Brown unsigned int val;
9737077148fSMark Brown
974cf6e26c7SKuninori Morimoto val = snd_soc_component_read(component, reg);
9757077148fSMark Brown val &= mask;
9767077148fSMark Brown
9777077148fSMark Brown if (shift != 0 && val != 0)
9787077148fSMark Brown val = val >> shift;
9797077148fSMark Brown ucontrol->value.enumerated.item[0] = val ^ invert;
9807077148fSMark Brown
9817077148fSMark Brown return 0;
9827077148fSMark Brown }
9837077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_get_strobe);
9847077148fSMark Brown
9857077148fSMark Brown /**
9867077148fSMark Brown * snd_soc_put_strobe - strobe put callback
9877077148fSMark Brown * @kcontrol: mixer control
9887077148fSMark Brown * @ucontrol: control element information
9897077148fSMark Brown *
9907077148fSMark Brown * Callback strobe a register bit to high then low (or the inverse)
9917077148fSMark Brown * in one pass of a single mixer enum control.
9927077148fSMark Brown *
9937077148fSMark Brown * Returns 1 for success.
9947077148fSMark Brown */
snd_soc_put_strobe(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)9957077148fSMark Brown int snd_soc_put_strobe(struct snd_kcontrol *kcontrol,
9967077148fSMark Brown struct snd_ctl_elem_value *ucontrol)
9977077148fSMark Brown {
9987077148fSMark Brown struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
9997077148fSMark Brown struct soc_mixer_control *mc =
10007077148fSMark Brown (struct soc_mixer_control *)kcontrol->private_value;
10017077148fSMark Brown unsigned int reg = mc->reg;
10027077148fSMark Brown unsigned int shift = mc->shift;
10037077148fSMark Brown unsigned int mask = 1 << shift;
10047077148fSMark Brown unsigned int invert = mc->invert != 0;
10057077148fSMark Brown unsigned int strobe = ucontrol->value.enumerated.item[0] != 0;
10067077148fSMark Brown unsigned int val1 = (strobe ^ invert) ? mask : 0;
10077077148fSMark Brown unsigned int val2 = (strobe ^ invert) ? 0 : mask;
10087077148fSMark Brown int err;
10097077148fSMark Brown
10107077148fSMark Brown err = snd_soc_component_update_bits(component, reg, mask, val1);
10117077148fSMark Brown if (err < 0)
10127077148fSMark Brown return err;
10137077148fSMark Brown
10147077148fSMark Brown return snd_soc_component_update_bits(component, reg, mask, val2);
10157077148fSMark Brown }
10167077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_put_strobe);
1017