xref: /openbmc/linux/sound/soc/soc-ops.c (revision 80ca762f)
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 
147077148fSMark Brown #include <linux/module.h>
157077148fSMark Brown #include <linux/moduleparam.h>
167077148fSMark Brown #include <linux/init.h>
177077148fSMark Brown #include <linux/pm.h>
187077148fSMark Brown #include <linux/bitops.h>
197077148fSMark Brown #include <linux/ctype.h>
207077148fSMark Brown #include <linux/slab.h>
217077148fSMark Brown #include <sound/core.h>
227077148fSMark Brown #include <sound/jack.h>
237077148fSMark Brown #include <sound/pcm.h>
247077148fSMark Brown #include <sound/pcm_params.h>
257077148fSMark Brown #include <sound/soc.h>
267077148fSMark Brown #include <sound/soc-dpcm.h>
277077148fSMark Brown #include <sound/initval.h>
287077148fSMark Brown 
297077148fSMark Brown /**
307077148fSMark Brown  * snd_soc_info_enum_double - enumerated double mixer info callback
317077148fSMark Brown  * @kcontrol: mixer control
327077148fSMark Brown  * @uinfo: control element information
337077148fSMark Brown  *
347077148fSMark Brown  * Callback to provide information about a double enumerated
357077148fSMark Brown  * mixer control.
367077148fSMark Brown  *
377077148fSMark Brown  * Returns 0 for success.
387077148fSMark Brown  */
snd_soc_info_enum_double(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)397077148fSMark Brown int snd_soc_info_enum_double(struct snd_kcontrol *kcontrol,
407077148fSMark Brown 	struct snd_ctl_elem_info *uinfo)
417077148fSMark Brown {
427077148fSMark Brown 	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
437077148fSMark Brown 
447077148fSMark Brown 	return snd_ctl_enum_info(uinfo, e->shift_l == e->shift_r ? 1 : 2,
457077148fSMark Brown 				 e->items, e->texts);
467077148fSMark Brown }
477077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_info_enum_double);
487077148fSMark Brown 
497077148fSMark Brown /**
507077148fSMark Brown  * snd_soc_get_enum_double - enumerated double mixer get callback
517077148fSMark Brown  * @kcontrol: mixer control
527077148fSMark Brown  * @ucontrol: control element information
537077148fSMark Brown  *
547077148fSMark Brown  * Callback to get the value of a double enumerated mixer.
557077148fSMark Brown  *
567077148fSMark Brown  * Returns 0 for success.
577077148fSMark Brown  */
snd_soc_get_enum_double(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)587077148fSMark Brown int snd_soc_get_enum_double(struct snd_kcontrol *kcontrol,
597077148fSMark Brown 	struct snd_ctl_elem_value *ucontrol)
607077148fSMark Brown {
617077148fSMark Brown 	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
627077148fSMark Brown 	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
637077148fSMark Brown 	unsigned int val, item;
647077148fSMark Brown 	unsigned int reg_val;
657077148fSMark Brown 
66cf6e26c7SKuninori Morimoto 	reg_val = snd_soc_component_read(component, e->reg);
677077148fSMark Brown 	val = (reg_val >> e->shift_l) & e->mask;
687077148fSMark Brown 	item = snd_soc_enum_val_to_item(e, val);
697077148fSMark Brown 	ucontrol->value.enumerated.item[0] = item;
707077148fSMark Brown 	if (e->shift_l != e->shift_r) {
71189f06c0SJaswinder Jassal 		val = (reg_val >> e->shift_r) & e->mask;
727077148fSMark Brown 		item = snd_soc_enum_val_to_item(e, val);
737077148fSMark Brown 		ucontrol->value.enumerated.item[1] = item;
747077148fSMark Brown 	}
757077148fSMark Brown 
767077148fSMark Brown 	return 0;
777077148fSMark Brown }
787077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_get_enum_double);
797077148fSMark Brown 
807077148fSMark Brown /**
817077148fSMark Brown  * snd_soc_put_enum_double - enumerated double mixer put callback
827077148fSMark Brown  * @kcontrol: mixer control
837077148fSMark Brown  * @ucontrol: control element information
847077148fSMark Brown  *
857077148fSMark Brown  * Callback to set the value of a double enumerated mixer.
867077148fSMark Brown  *
877077148fSMark Brown  * Returns 0 for success.
887077148fSMark Brown  */
snd_soc_put_enum_double(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)897077148fSMark Brown int snd_soc_put_enum_double(struct snd_kcontrol *kcontrol,
907077148fSMark Brown 	struct snd_ctl_elem_value *ucontrol)
917077148fSMark Brown {
927077148fSMark Brown 	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
937077148fSMark Brown 	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
947077148fSMark Brown 	unsigned int *item = ucontrol->value.enumerated.item;
957077148fSMark Brown 	unsigned int val;
967077148fSMark Brown 	unsigned int mask;
977077148fSMark Brown 
987077148fSMark Brown 	if (item[0] >= e->items)
997077148fSMark Brown 		return -EINVAL;
1007077148fSMark Brown 	val = snd_soc_enum_item_to_val(e, item[0]) << e->shift_l;
1017077148fSMark Brown 	mask = e->mask << e->shift_l;
1027077148fSMark Brown 	if (e->shift_l != e->shift_r) {
1037077148fSMark Brown 		if (item[1] >= e->items)
1047077148fSMark Brown 			return -EINVAL;
1057077148fSMark Brown 		val |= snd_soc_enum_item_to_val(e, item[1]) << e->shift_r;
1067077148fSMark Brown 		mask |= e->mask << e->shift_r;
1077077148fSMark Brown 	}
1087077148fSMark Brown 
1097077148fSMark Brown 	return snd_soc_component_update_bits(component, e->reg, mask, val);
1107077148fSMark Brown }
1117077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_put_enum_double);
1127077148fSMark Brown 
1137077148fSMark Brown /**
1148abab35fSCharles Keepax  * snd_soc_read_signed - Read a codec register and interpret as signed value
1157077148fSMark Brown  * @component: component
1167077148fSMark Brown  * @reg: Register to read
1177077148fSMark Brown  * @mask: Mask to use after shifting the register value
1187077148fSMark Brown  * @shift: Right shift of register value
1197077148fSMark Brown  * @sign_bit: Bit that describes if a number is negative or not.
1207077148fSMark Brown  * @signed_val: Pointer to where the read value should be stored
1217077148fSMark Brown  *
1227077148fSMark Brown  * This functions reads a codec register. The register value is shifted right
1237077148fSMark Brown  * by 'shift' bits and masked with the given 'mask'. Afterwards it translates
1247077148fSMark Brown  * the given registervalue into a signed integer if sign_bit is non-zero.
1257077148fSMark Brown  *
1267077148fSMark Brown  * Returns 0 on sucess, otherwise an error value
1277077148fSMark 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)1287077148fSMark Brown static int snd_soc_read_signed(struct snd_soc_component *component,
1297077148fSMark Brown 	unsigned int reg, unsigned int mask, unsigned int shift,
1307077148fSMark Brown 	unsigned int sign_bit, int *signed_val)
1317077148fSMark Brown {
1327077148fSMark Brown 	int ret;
1337077148fSMark Brown 	unsigned int val;
1347077148fSMark Brown 
135cf6e26c7SKuninori Morimoto 	val = snd_soc_component_read(component, reg);
1367077148fSMark Brown 	val = (val >> shift) & mask;
1377077148fSMark Brown 
1387077148fSMark Brown 	if (!sign_bit) {
1397077148fSMark Brown 		*signed_val = val;
1407077148fSMark Brown 		return 0;
1417077148fSMark Brown 	}
1427077148fSMark Brown 
1437077148fSMark Brown 	/* non-negative number */
1447077148fSMark Brown 	if (!(val & BIT(sign_bit))) {
1457077148fSMark Brown 		*signed_val = val;
1467077148fSMark Brown 		return 0;
1477077148fSMark Brown 	}
1487077148fSMark Brown 
1497077148fSMark Brown 	ret = val;
1507077148fSMark Brown 
1517077148fSMark Brown 	/*
1527077148fSMark Brown 	 * The register most probably does not contain a full-sized int.
1537077148fSMark Brown 	 * Instead we have an arbitrary number of bits in a signed
1547077148fSMark Brown 	 * representation which has to be translated into a full-sized int.
1557077148fSMark Brown 	 * This is done by filling up all bits above the sign-bit.
1567077148fSMark Brown 	 */
1577077148fSMark Brown 	ret |= ~((int)(BIT(sign_bit) - 1));
1587077148fSMark Brown 
1597077148fSMark Brown 	*signed_val = ret;
1607077148fSMark Brown 
1617077148fSMark Brown 	return 0;
1627077148fSMark Brown }
1637077148fSMark Brown 
1647077148fSMark Brown /**
1657077148fSMark Brown  * snd_soc_info_volsw - single mixer info callback
1667077148fSMark Brown  * @kcontrol: mixer control
1677077148fSMark Brown  * @uinfo: control element information
1687077148fSMark Brown  *
1697077148fSMark Brown  * Callback to provide information about a single mixer control, or a double
1707077148fSMark Brown  * mixer control that spans 2 registers.
1717077148fSMark Brown  *
1727077148fSMark Brown  * Returns 0 for success.
1737077148fSMark Brown  */
snd_soc_info_volsw(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)1747077148fSMark Brown int snd_soc_info_volsw(struct snd_kcontrol *kcontrol,
1757077148fSMark Brown 	struct snd_ctl_elem_info *uinfo)
1767077148fSMark Brown {
1777077148fSMark Brown 	struct soc_mixer_control *mc =
1787077148fSMark Brown 		(struct soc_mixer_control *)kcontrol->private_value;
179aa2a4b89SMark Brown 	const char *vol_string = NULL;
18030ac4984SMark Brown 	int max;
1817077148fSMark Brown 
18230ac4984SMark Brown 	max = uinfo->value.integer.max = mc->max - mc->min;
18330ac4984SMark Brown 	if (mc->platform_max && mc->platform_max < max)
18430ac4984SMark Brown 		max = mc->platform_max;
1857077148fSMark Brown 
186aa2a4b89SMark Brown 	if (max == 1) {
18744230200SStefan Binding 		/* Even two value controls ending in Volume should always be integer */
188aa2a4b89SMark Brown 		vol_string = strstr(kcontrol->id.name, " Volume");
18944230200SStefan Binding 		if (vol_string && !strcmp(vol_string, " Volume"))
1907077148fSMark Brown 			uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
19144230200SStefan Binding 		else
19244230200SStefan Binding 			uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
19344230200SStefan Binding 	} else {
19444230200SStefan Binding 		uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
19544230200SStefan Binding 	}
1967077148fSMark Brown 
1977077148fSMark Brown 	uinfo->count = snd_soc_volsw_is_stereo(mc) ? 2 : 1;
1987077148fSMark Brown 	uinfo->value.integer.min = 0;
19930ac4984SMark Brown 	uinfo->value.integer.max = max;
20030ac4984SMark Brown 
2017077148fSMark Brown 	return 0;
2027077148fSMark Brown }
2037077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_info_volsw);
2047077148fSMark Brown 
2057077148fSMark Brown /**
20634198710SCharles Keepax  * snd_soc_info_volsw_sx - Mixer info callback for SX TLV controls
20734198710SCharles Keepax  * @kcontrol: mixer control
20834198710SCharles Keepax  * @uinfo: control element information
20934198710SCharles Keepax  *
21034198710SCharles Keepax  * Callback to provide information about a single mixer control, or a double
21134198710SCharles Keepax  * mixer control that spans 2 registers of the SX TLV type. SX TLV controls
21234198710SCharles Keepax  * have a range that represents both positive and negative values either side
21399b5c107SMark Brown  * of zero but without a sign bit. min is the minimum register value, max is
21499b5c107SMark Brown  * the number of steps.
21534198710SCharles Keepax  *
21634198710SCharles Keepax  * Returns 0 for success.
21734198710SCharles Keepax  */
snd_soc_info_volsw_sx(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)21834198710SCharles Keepax int snd_soc_info_volsw_sx(struct snd_kcontrol *kcontrol,
21934198710SCharles Keepax 			  struct snd_ctl_elem_info *uinfo)
22034198710SCharles Keepax {
22134198710SCharles Keepax 	struct soc_mixer_control *mc =
22234198710SCharles Keepax 		(struct soc_mixer_control *)kcontrol->private_value;
22399b5c107SMark Brown 	int max;
22434198710SCharles Keepax 
22599b5c107SMark Brown 	if (mc->platform_max)
22699b5c107SMark Brown 		max = mc->platform_max;
22799b5c107SMark Brown 	else
22899b5c107SMark Brown 		max = mc->max;
22999b5c107SMark Brown 
23099b5c107SMark Brown 	if (max == 1 && !strstr(kcontrol->id.name, " Volume"))
23199b5c107SMark Brown 		uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
23299b5c107SMark Brown 	else
23399b5c107SMark Brown 		uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
23499b5c107SMark Brown 
23599b5c107SMark Brown 	uinfo->count = snd_soc_volsw_is_stereo(mc) ? 2 : 1;
23699b5c107SMark Brown 	uinfo->value.integer.min = 0;
23799b5c107SMark Brown 	uinfo->value.integer.max = max;
23834198710SCharles Keepax 
23934198710SCharles Keepax 	return 0;
24034198710SCharles Keepax }
24134198710SCharles Keepax EXPORT_SYMBOL_GPL(snd_soc_info_volsw_sx);
24234198710SCharles Keepax 
24334198710SCharles Keepax /**
2447077148fSMark Brown  * snd_soc_get_volsw - single mixer get callback
2457077148fSMark Brown  * @kcontrol: mixer control
2467077148fSMark Brown  * @ucontrol: control element information
2477077148fSMark Brown  *
2487077148fSMark Brown  * Callback to get the value of a single mixer control, or a double mixer
2497077148fSMark Brown  * control that spans 2 registers.
2507077148fSMark Brown  *
2517077148fSMark Brown  * Returns 0 for success.
2527077148fSMark Brown  */
snd_soc_get_volsw(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)2537077148fSMark Brown int snd_soc_get_volsw(struct snd_kcontrol *kcontrol,
2547077148fSMark Brown 	struct snd_ctl_elem_value *ucontrol)
2557077148fSMark Brown {
2567077148fSMark Brown 	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
2577077148fSMark Brown 	struct soc_mixer_control *mc =
2587077148fSMark Brown 		(struct soc_mixer_control *)kcontrol->private_value;
2597077148fSMark Brown 	unsigned int reg = mc->reg;
2607077148fSMark Brown 	unsigned int reg2 = mc->rreg;
2617077148fSMark Brown 	unsigned int shift = mc->shift;
2627077148fSMark Brown 	unsigned int rshift = mc->rshift;
2637077148fSMark Brown 	int max = mc->max;
2647077148fSMark Brown 	int min = mc->min;
2657077148fSMark Brown 	int sign_bit = mc->sign_bit;
266*80ca762fSStephen Lee 	unsigned int mask = (1ULL << fls(max)) - 1;
2677077148fSMark Brown 	unsigned int invert = mc->invert;
2687077148fSMark Brown 	int val;
2697077148fSMark Brown 	int ret;
2707077148fSMark Brown 
2717077148fSMark Brown 	if (sign_bit)
2727077148fSMark Brown 		mask = BIT(sign_bit + 1) - 1;
2737077148fSMark Brown 
2747077148fSMark Brown 	ret = snd_soc_read_signed(component, reg, mask, shift, sign_bit, &val);
2757077148fSMark Brown 	if (ret)
2767077148fSMark Brown 		return ret;
2777077148fSMark Brown 
2787077148fSMark Brown 	ucontrol->value.integer.value[0] = val - min;
2797077148fSMark Brown 	if (invert)
2807077148fSMark Brown 		ucontrol->value.integer.value[0] =
2817077148fSMark Brown 			max - ucontrol->value.integer.value[0];
2827077148fSMark Brown 
2837077148fSMark Brown 	if (snd_soc_volsw_is_stereo(mc)) {
2847077148fSMark Brown 		if (reg == reg2)
2857077148fSMark Brown 			ret = snd_soc_read_signed(component, reg, mask, rshift,
2867077148fSMark Brown 				sign_bit, &val);
2877077148fSMark Brown 		else
2887077148fSMark Brown 			ret = snd_soc_read_signed(component, reg2, mask, shift,
2897077148fSMark Brown 				sign_bit, &val);
2907077148fSMark Brown 		if (ret)
2917077148fSMark Brown 			return ret;
2927077148fSMark Brown 
2937077148fSMark Brown 		ucontrol->value.integer.value[1] = val - min;
2947077148fSMark Brown 		if (invert)
2957077148fSMark Brown 			ucontrol->value.integer.value[1] =
2967077148fSMark Brown 				max - ucontrol->value.integer.value[1];
2977077148fSMark Brown 	}
2987077148fSMark Brown 
2997077148fSMark Brown 	return 0;
3007077148fSMark Brown }
3017077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_get_volsw);
3027077148fSMark Brown 
3037077148fSMark Brown /**
3047077148fSMark Brown  * snd_soc_put_volsw - single mixer put callback
3057077148fSMark Brown  * @kcontrol: mixer control
3067077148fSMark Brown  * @ucontrol: control element information
3077077148fSMark Brown  *
3087077148fSMark Brown  * Callback to set the value of a single mixer control, or a double mixer
3097077148fSMark Brown  * control that spans 2 registers.
3107077148fSMark Brown  *
3117077148fSMark Brown  * Returns 0 for success.
3127077148fSMark Brown  */
snd_soc_put_volsw(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)3137077148fSMark Brown int snd_soc_put_volsw(struct snd_kcontrol *kcontrol,
3147077148fSMark Brown 	struct snd_ctl_elem_value *ucontrol)
3157077148fSMark Brown {
3167077148fSMark Brown 	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
3177077148fSMark Brown 	struct soc_mixer_control *mc =
3187077148fSMark Brown 		(struct soc_mixer_control *)kcontrol->private_value;
3197077148fSMark Brown 	unsigned int reg = mc->reg;
3207077148fSMark Brown 	unsigned int reg2 = mc->rreg;
3217077148fSMark Brown 	unsigned int shift = mc->shift;
3227077148fSMark Brown 	unsigned int rshift = mc->rshift;
3237077148fSMark Brown 	int max = mc->max;
3247077148fSMark Brown 	int min = mc->min;
3257077148fSMark Brown 	unsigned int sign_bit = mc->sign_bit;
3267077148fSMark Brown 	unsigned int mask = (1 << fls(max)) - 1;
3277077148fSMark Brown 	unsigned int invert = mc->invert;
328564778d7SMark Brown 	int err, ret;
3297077148fSMark Brown 	bool type_2r = false;
3307077148fSMark Brown 	unsigned int val2 = 0;
3317077148fSMark Brown 	unsigned int val, val_mask;
3327077148fSMark Brown 
3337077148fSMark Brown 	if (sign_bit)
3347077148fSMark Brown 		mask = BIT(sign_bit + 1) - 1;
3357077148fSMark Brown 
3361601033dSMark Brown 	if (ucontrol->value.integer.value[0] < 0)
3371601033dSMark Brown 		return -EINVAL;
338817f7c93SMark Brown 	val = ucontrol->value.integer.value[0];
3399bdd10d5SMarek Vasut 	if (mc->platform_max && ((int)val + min) > mc->platform_max)
340817f7c93SMark Brown 		return -EINVAL;
341817f7c93SMark Brown 	if (val > max - min)
342817f7c93SMark Brown 		return -EINVAL;
343817f7c93SMark Brown 	val = (val + min) & mask;
3447077148fSMark Brown 	if (invert)
3457077148fSMark Brown 		val = max - val;
3467077148fSMark Brown 	val_mask = mask << shift;
3477077148fSMark Brown 	val = val << shift;
3487077148fSMark Brown 	if (snd_soc_volsw_is_stereo(mc)) {
3491601033dSMark Brown 		if (ucontrol->value.integer.value[1] < 0)
3501601033dSMark Brown 			return -EINVAL;
351817f7c93SMark Brown 		val2 = ucontrol->value.integer.value[1];
3529bdd10d5SMarek Vasut 		if (mc->platform_max && ((int)val2 + min) > mc->platform_max)
353817f7c93SMark Brown 			return -EINVAL;
354817f7c93SMark Brown 		if (val2 > max - min)
355817f7c93SMark Brown 			return -EINVAL;
356817f7c93SMark Brown 		val2 = (val2 + min) & mask;
3577077148fSMark Brown 		if (invert)
3587077148fSMark Brown 			val2 = max - val2;
3597077148fSMark Brown 		if (reg == reg2) {
3607077148fSMark Brown 			val_mask |= mask << rshift;
3617077148fSMark Brown 			val |= val2 << rshift;
3627077148fSMark Brown 		} else {
3637077148fSMark Brown 			val2 = val2 << shift;
3647077148fSMark Brown 			type_2r = true;
3657077148fSMark Brown 		}
3667077148fSMark Brown 	}
3677077148fSMark Brown 	err = snd_soc_component_update_bits(component, reg, val_mask, val);
3687077148fSMark Brown 	if (err < 0)
3697077148fSMark Brown 		return err;
370564778d7SMark Brown 	ret = err;
3717077148fSMark Brown 
372564778d7SMark Brown 	if (type_2r) {
3737077148fSMark Brown 		err = snd_soc_component_update_bits(component, reg2, val_mask,
3747077148fSMark Brown 						    val2);
375564778d7SMark Brown 		/* Don't discard any error code or drop change flag */
376564778d7SMark Brown 		if (ret == 0 || err < 0) {
377564778d7SMark Brown 			ret = err;
378564778d7SMark Brown 		}
379564778d7SMark Brown 	}
3807077148fSMark Brown 
381564778d7SMark Brown 	return ret;
3827077148fSMark Brown }
3837077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_put_volsw);
3847077148fSMark Brown 
3857077148fSMark Brown /**
3867077148fSMark Brown  * snd_soc_get_volsw_sx - single mixer get callback
3877077148fSMark Brown  * @kcontrol: mixer control
3887077148fSMark Brown  * @ucontrol: control element information
3897077148fSMark Brown  *
3907077148fSMark Brown  * Callback to get the value of a single mixer control, or a double mixer
3917077148fSMark Brown  * control that spans 2 registers.
3927077148fSMark Brown  *
3937077148fSMark Brown  * Returns 0 for success.
3947077148fSMark Brown  */
snd_soc_get_volsw_sx(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)3957077148fSMark Brown int snd_soc_get_volsw_sx(struct snd_kcontrol *kcontrol,
3967077148fSMark Brown 		      struct snd_ctl_elem_value *ucontrol)
3977077148fSMark Brown {
3987077148fSMark Brown 	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
3997077148fSMark Brown 	struct soc_mixer_control *mc =
4007077148fSMark Brown 	    (struct soc_mixer_control *)kcontrol->private_value;
4017077148fSMark Brown 	unsigned int reg = mc->reg;
4027077148fSMark Brown 	unsigned int reg2 = mc->rreg;
4037077148fSMark Brown 	unsigned int shift = mc->shift;
4047077148fSMark Brown 	unsigned int rshift = mc->rshift;
4057077148fSMark Brown 	int max = mc->max;
4067077148fSMark Brown 	int min = mc->min;
407ae7d1247SRohit kumar 	unsigned int mask = (1U << (fls(min + max) - 1)) - 1;
4087077148fSMark Brown 	unsigned int val;
4097077148fSMark Brown 
410cf6e26c7SKuninori Morimoto 	val = snd_soc_component_read(component, reg);
4117077148fSMark Brown 	ucontrol->value.integer.value[0] = ((val >> shift) - min) & mask;
4127077148fSMark Brown 
4137077148fSMark Brown 	if (snd_soc_volsw_is_stereo(mc)) {
414cf6e26c7SKuninori Morimoto 		val = snd_soc_component_read(component, reg2);
4157077148fSMark Brown 		val = ((val >> rshift) - min) & mask;
4167077148fSMark Brown 		ucontrol->value.integer.value[1] = val;
4177077148fSMark Brown 	}
4187077148fSMark Brown 
4197077148fSMark Brown 	return 0;
4207077148fSMark Brown }
4217077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_get_volsw_sx);
4227077148fSMark Brown 
4237077148fSMark Brown /**
4247077148fSMark Brown  * snd_soc_put_volsw_sx - double mixer set callback
4257077148fSMark Brown  * @kcontrol: mixer control
4269a11ef7fSRandy Dunlap  * @ucontrol: control element information
4277077148fSMark Brown  *
4287077148fSMark Brown  * Callback to set the value of a double mixer control that spans 2 registers.
4297077148fSMark Brown  *
4307077148fSMark Brown  * Returns 0 for success.
4317077148fSMark Brown  */
snd_soc_put_volsw_sx(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)4327077148fSMark Brown int snd_soc_put_volsw_sx(struct snd_kcontrol *kcontrol,
4337077148fSMark Brown 			 struct snd_ctl_elem_value *ucontrol)
4347077148fSMark Brown {
4357077148fSMark Brown 	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
4367077148fSMark Brown 	struct soc_mixer_control *mc =
4377077148fSMark Brown 	    (struct soc_mixer_control *)kcontrol->private_value;
4387077148fSMark Brown 
4397077148fSMark Brown 	unsigned int reg = mc->reg;
4407077148fSMark Brown 	unsigned int reg2 = mc->rreg;
4417077148fSMark Brown 	unsigned int shift = mc->shift;
4427077148fSMark Brown 	unsigned int rshift = mc->rshift;
4437077148fSMark Brown 	int max = mc->max;
4447077148fSMark Brown 	int min = mc->min;
445ae7d1247SRohit kumar 	unsigned int mask = (1U << (fls(min + max) - 1)) - 1;
4467077148fSMark Brown 	int err = 0;
4477f3d90a3SMark Brown 	int ret;
44858f42dfdSKuninori Morimoto 	unsigned int val, val_mask;
4497077148fSMark Brown 
4501601033dSMark Brown 	if (ucontrol->value.integer.value[0] < 0)
4511601033dSMark Brown 		return -EINVAL;
4524f1e50d6SMark Brown 	val = ucontrol->value.integer.value[0];
4534f1e50d6SMark Brown 	if (mc->platform_max && val > mc->platform_max)
4544f1e50d6SMark Brown 		return -EINVAL;
455698813baSMark Brown 	if (val > max)
4564f1e50d6SMark Brown 		return -EINVAL;
4577077148fSMark Brown 	val_mask = mask << shift;
4584f1e50d6SMark Brown 	val = (val + min) & mask;
4597077148fSMark Brown 	val = val << shift;
4607077148fSMark Brown 
4617077148fSMark Brown 	err = snd_soc_component_update_bits(component, reg, val_mask, val);
4627077148fSMark Brown 	if (err < 0)
4637077148fSMark Brown 		return err;
4647f3d90a3SMark Brown 	ret = err;
4657077148fSMark Brown 
4667077148fSMark Brown 	if (snd_soc_volsw_is_stereo(mc)) {
467f33bcc50SCharles Keepax 		unsigned int val2 = ucontrol->value.integer.value[1];
46897eea946SMark Brown 
46997eea946SMark Brown 		if (mc->platform_max && val2 > mc->platform_max)
47097eea946SMark Brown 			return -EINVAL;
47197eea946SMark Brown 		if (val2 > max)
47297eea946SMark Brown 			return -EINVAL;
47397eea946SMark Brown 
474f33bcc50SCharles Keepax 		val_mask = mask << rshift;
475f33bcc50SCharles Keepax 		val2 = (val2 + min) & mask;
4767077148fSMark Brown 		val2 = val2 << rshift;
4777077148fSMark Brown 
4787077148fSMark Brown 		err = snd_soc_component_update_bits(component, reg2, val_mask,
4797077148fSMark Brown 			val2);
4807f3d90a3SMark Brown 
4817f3d90a3SMark Brown 		/* Don't discard any error code or drop change flag */
4827f3d90a3SMark Brown 		if (ret == 0 || err < 0) {
4837f3d90a3SMark Brown 			ret = err;
4847f3d90a3SMark Brown 		}
4857077148fSMark Brown 	}
486eb577320SPierre-Louis Bossart 	return ret;
4877077148fSMark Brown }
4887077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_put_volsw_sx);
4897077148fSMark Brown 
4907077148fSMark Brown /**
4917077148fSMark Brown  * snd_soc_info_volsw_range - single mixer info callback with range.
4927077148fSMark Brown  * @kcontrol: mixer control
4937077148fSMark Brown  * @uinfo: control element information
4947077148fSMark Brown  *
4957077148fSMark Brown  * Callback to provide information, within a range, about a single
4967077148fSMark Brown  * mixer control.
4977077148fSMark Brown  *
4987077148fSMark Brown  * returns 0 for success.
4997077148fSMark Brown  */
snd_soc_info_volsw_range(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)5007077148fSMark Brown int snd_soc_info_volsw_range(struct snd_kcontrol *kcontrol,
5017077148fSMark Brown 	struct snd_ctl_elem_info *uinfo)
5027077148fSMark Brown {
5037077148fSMark Brown 	struct soc_mixer_control *mc =
5047077148fSMark Brown 		(struct soc_mixer_control *)kcontrol->private_value;
5057077148fSMark Brown 	int platform_max;
5067077148fSMark Brown 	int min = mc->min;
5077077148fSMark Brown 
5087077148fSMark Brown 	if (!mc->platform_max)
5097077148fSMark Brown 		mc->platform_max = mc->max;
5107077148fSMark Brown 	platform_max = mc->platform_max;
5117077148fSMark Brown 
5127077148fSMark Brown 	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
5137077148fSMark Brown 	uinfo->count = snd_soc_volsw_is_stereo(mc) ? 2 : 1;
5147077148fSMark Brown 	uinfo->value.integer.min = 0;
5157077148fSMark Brown 	uinfo->value.integer.max = platform_max - min;
5167077148fSMark Brown 
5177077148fSMark Brown 	return 0;
5187077148fSMark Brown }
5197077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_info_volsw_range);
5207077148fSMark Brown 
5217077148fSMark Brown /**
5227077148fSMark Brown  * snd_soc_put_volsw_range - single mixer put value callback with range.
5237077148fSMark Brown  * @kcontrol: mixer control
5247077148fSMark Brown  * @ucontrol: control element information
5257077148fSMark Brown  *
5267077148fSMark Brown  * Callback to set the value, within a range, for a single mixer control.
5277077148fSMark Brown  *
5287077148fSMark Brown  * Returns 0 for success.
5297077148fSMark Brown  */
snd_soc_put_volsw_range(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)5307077148fSMark Brown int snd_soc_put_volsw_range(struct snd_kcontrol *kcontrol,
5317077148fSMark Brown 	struct snd_ctl_elem_value *ucontrol)
5327077148fSMark Brown {
5337077148fSMark Brown 	struct soc_mixer_control *mc =
5347077148fSMark Brown 		(struct soc_mixer_control *)kcontrol->private_value;
5357077148fSMark Brown 	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
5367077148fSMark Brown 	unsigned int reg = mc->reg;
5377077148fSMark Brown 	unsigned int rreg = mc->rreg;
5387077148fSMark Brown 	unsigned int shift = mc->shift;
5397077148fSMark Brown 	int min = mc->min;
5407077148fSMark Brown 	int max = mc->max;
5417077148fSMark Brown 	unsigned int mask = (1 << fls(max)) - 1;
5427077148fSMark Brown 	unsigned int invert = mc->invert;
5437077148fSMark Brown 	unsigned int val, val_mask;
544aa22125cSMark Brown 	int err, ret, tmp;
545aa22125cSMark Brown 
546aa22125cSMark Brown 	tmp = ucontrol->value.integer.value[0];
547aa22125cSMark Brown 	if (tmp < 0)
548aa22125cSMark Brown 		return -EINVAL;
549aa22125cSMark Brown 	if (mc->platform_max && tmp > mc->platform_max)
550aa22125cSMark Brown 		return -EINVAL;
5515871321fSMark Brown 	if (tmp > mc->max - mc->min)
552aa22125cSMark Brown 		return -EINVAL;
5537077148fSMark Brown 
5547077148fSMark Brown 	if (invert)
5557077148fSMark Brown 		val = (max - ucontrol->value.integer.value[0]) & mask;
5567077148fSMark Brown 	else
5577077148fSMark Brown 		val = ((ucontrol->value.integer.value[0] + min) & mask);
5587077148fSMark Brown 	val_mask = mask << shift;
5597077148fSMark Brown 	val = val << shift;
5607077148fSMark Brown 
561650204deSMark Brown 	err = snd_soc_component_update_bits(component, reg, val_mask, val);
562650204deSMark Brown 	if (err < 0)
563650204deSMark Brown 		return err;
564650204deSMark Brown 	ret = err;
5657077148fSMark Brown 
5667077148fSMark Brown 	if (snd_soc_volsw_is_stereo(mc)) {
567aa22125cSMark Brown 		tmp = ucontrol->value.integer.value[1];
568aa22125cSMark Brown 		if (tmp < 0)
569aa22125cSMark Brown 			return -EINVAL;
570aa22125cSMark Brown 		if (mc->platform_max && tmp > mc->platform_max)
571aa22125cSMark Brown 			return -EINVAL;
5725871321fSMark Brown 		if (tmp > mc->max - mc->min)
573aa22125cSMark Brown 			return -EINVAL;
574aa22125cSMark Brown 
5757077148fSMark Brown 		if (invert)
5767077148fSMark Brown 			val = (max - ucontrol->value.integer.value[1]) & mask;
5777077148fSMark Brown 		else
5787077148fSMark Brown 			val = ((ucontrol->value.integer.value[1] + min) & mask);
5797077148fSMark Brown 		val_mask = mask << shift;
5807077148fSMark Brown 		val = val << shift;
5817077148fSMark Brown 
582650204deSMark Brown 		err = snd_soc_component_update_bits(component, rreg, val_mask,
5837077148fSMark Brown 			val);
584650204deSMark Brown 		/* Don't discard any error code or drop change flag */
585650204deSMark Brown 		if (ret == 0 || err < 0) {
586650204deSMark Brown 			ret = err;
587650204deSMark Brown 		}
5887077148fSMark Brown 	}
5897077148fSMark Brown 
5907077148fSMark Brown 	return ret;
5917077148fSMark Brown }
5927077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_put_volsw_range);
5937077148fSMark Brown 
5947077148fSMark Brown /**
5957077148fSMark Brown  * snd_soc_get_volsw_range - single mixer get callback with range
5967077148fSMark Brown  * @kcontrol: mixer control
5977077148fSMark Brown  * @ucontrol: control element information
5987077148fSMark Brown  *
5997077148fSMark Brown  * Callback to get the value, within a range, of a single mixer control.
6007077148fSMark Brown  *
6017077148fSMark Brown  * Returns 0 for success.
6027077148fSMark Brown  */
snd_soc_get_volsw_range(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)6037077148fSMark Brown int snd_soc_get_volsw_range(struct snd_kcontrol *kcontrol,
6047077148fSMark Brown 	struct snd_ctl_elem_value *ucontrol)
6057077148fSMark Brown {
6067077148fSMark Brown 	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
6077077148fSMark Brown 	struct soc_mixer_control *mc =
6087077148fSMark Brown 		(struct soc_mixer_control *)kcontrol->private_value;
6097077148fSMark Brown 	unsigned int reg = mc->reg;
6107077148fSMark Brown 	unsigned int rreg = mc->rreg;
6117077148fSMark Brown 	unsigned int shift = mc->shift;
6127077148fSMark Brown 	int min = mc->min;
6137077148fSMark Brown 	int max = mc->max;
6147077148fSMark Brown 	unsigned int mask = (1 << fls(max)) - 1;
6157077148fSMark Brown 	unsigned int invert = mc->invert;
6167077148fSMark Brown 	unsigned int val;
6177077148fSMark Brown 
618cf6e26c7SKuninori Morimoto 	val = snd_soc_component_read(component, reg);
6197077148fSMark Brown 	ucontrol->value.integer.value[0] = (val >> shift) & mask;
6207077148fSMark Brown 	if (invert)
6217077148fSMark Brown 		ucontrol->value.integer.value[0] =
6227077148fSMark Brown 			max - ucontrol->value.integer.value[0];
6237077148fSMark Brown 	else
6247077148fSMark Brown 		ucontrol->value.integer.value[0] =
6257077148fSMark Brown 			ucontrol->value.integer.value[0] - min;
6267077148fSMark Brown 
6277077148fSMark Brown 	if (snd_soc_volsw_is_stereo(mc)) {
628cf6e26c7SKuninori Morimoto 		val = snd_soc_component_read(component, rreg);
6297077148fSMark Brown 		ucontrol->value.integer.value[1] = (val >> shift) & mask;
6307077148fSMark Brown 		if (invert)
6317077148fSMark Brown 			ucontrol->value.integer.value[1] =
6327077148fSMark Brown 				max - ucontrol->value.integer.value[1];
6337077148fSMark Brown 		else
6347077148fSMark Brown 			ucontrol->value.integer.value[1] =
6357077148fSMark Brown 				ucontrol->value.integer.value[1] - min;
6367077148fSMark Brown 	}
6377077148fSMark Brown 
6387077148fSMark Brown 	return 0;
6397077148fSMark Brown }
6407077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_get_volsw_range);
6417077148fSMark Brown 
6427077148fSMark Brown /**
6437077148fSMark Brown  * snd_soc_limit_volume - Set new limit to an existing volume control.
6447077148fSMark Brown  *
64526d9ca34SLars-Peter Clausen  * @card: where to look for the control
6467077148fSMark Brown  * @name: Name of the control
6477077148fSMark Brown  * @max: new maximum limit
6487077148fSMark Brown  *
6497077148fSMark Brown  * Return 0 for success, else error.
6507077148fSMark Brown  */
snd_soc_limit_volume(struct snd_soc_card * card,const char * name,int max)65126d9ca34SLars-Peter Clausen int snd_soc_limit_volume(struct snd_soc_card *card,
6527077148fSMark Brown 	const char *name, int max)
6537077148fSMark Brown {
6547077148fSMark Brown 	struct snd_kcontrol *kctl;
6557077148fSMark Brown 	int ret = -EINVAL;
6567077148fSMark Brown 
6577077148fSMark Brown 	/* Sanity check for name and max */
6587077148fSMark Brown 	if (unlikely(!name || max <= 0))
6597077148fSMark Brown 		return -EINVAL;
6607077148fSMark Brown 
6610881ab6eSKuninori Morimoto 	kctl = snd_soc_card_get_kcontrol(card, name);
6620881ab6eSKuninori Morimoto 	if (kctl) {
663872040f7SKuninori Morimoto 		struct soc_mixer_control *mc = (struct soc_mixer_control *)kctl->private_value;
664395e52b7SSrinivas Kandagatla 		if (max <= mc->max - mc->min) {
6657077148fSMark Brown 			mc->platform_max = max;
6667077148fSMark Brown 			ret = 0;
6677077148fSMark Brown 		}
6687077148fSMark Brown 	}
6697077148fSMark Brown 	return ret;
6707077148fSMark Brown }
6717077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_limit_volume);
6727077148fSMark Brown 
snd_soc_bytes_info(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)6737077148fSMark Brown int snd_soc_bytes_info(struct snd_kcontrol *kcontrol,
6747077148fSMark Brown 		       struct snd_ctl_elem_info *uinfo)
6757077148fSMark Brown {
6767077148fSMark Brown 	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
6777077148fSMark Brown 	struct soc_bytes *params = (void *)kcontrol->private_value;
6787077148fSMark Brown 
6797077148fSMark Brown 	uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
6807077148fSMark Brown 	uinfo->count = params->num_regs * component->val_bytes;
6817077148fSMark Brown 
6827077148fSMark Brown 	return 0;
6837077148fSMark Brown }
6847077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_bytes_info);
6857077148fSMark Brown 
snd_soc_bytes_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)6867077148fSMark Brown int snd_soc_bytes_get(struct snd_kcontrol *kcontrol,
6877077148fSMark Brown 		      struct snd_ctl_elem_value *ucontrol)
6887077148fSMark Brown {
6897077148fSMark Brown 	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
6907077148fSMark Brown 	struct soc_bytes *params = (void *)kcontrol->private_value;
6917077148fSMark Brown 	int ret;
6927077148fSMark Brown 
6937077148fSMark Brown 	if (component->regmap)
6947077148fSMark Brown 		ret = regmap_raw_read(component->regmap, params->base,
6957077148fSMark Brown 				      ucontrol->value.bytes.data,
6967077148fSMark Brown 				      params->num_regs * component->val_bytes);
6977077148fSMark Brown 	else
6987077148fSMark Brown 		ret = -EINVAL;
6997077148fSMark Brown 
7007077148fSMark Brown 	/* Hide any masked bytes to ensure consistent data reporting */
7017077148fSMark Brown 	if (ret == 0 && params->mask) {
7027077148fSMark Brown 		switch (component->val_bytes) {
7037077148fSMark Brown 		case 1:
7047077148fSMark Brown 			ucontrol->value.bytes.data[0] &= ~params->mask;
7057077148fSMark Brown 			break;
7067077148fSMark Brown 		case 2:
7077077148fSMark Brown 			((u16 *)(&ucontrol->value.bytes.data))[0]
7087077148fSMark Brown 				&= cpu_to_be16(~params->mask);
7097077148fSMark Brown 			break;
7107077148fSMark Brown 		case 4:
7117077148fSMark Brown 			((u32 *)(&ucontrol->value.bytes.data))[0]
7127077148fSMark Brown 				&= cpu_to_be32(~params->mask);
7137077148fSMark Brown 			break;
7147077148fSMark Brown 		default:
7157077148fSMark Brown 			return -EINVAL;
7167077148fSMark Brown 		}
7177077148fSMark Brown 	}
7187077148fSMark Brown 
7197077148fSMark Brown 	return ret;
7207077148fSMark Brown }
7217077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_bytes_get);
7227077148fSMark Brown 
snd_soc_bytes_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)7237077148fSMark Brown int snd_soc_bytes_put(struct snd_kcontrol *kcontrol,
7247077148fSMark Brown 		      struct snd_ctl_elem_value *ucontrol)
7257077148fSMark Brown {
7267077148fSMark Brown 	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
7277077148fSMark Brown 	struct soc_bytes *params = (void *)kcontrol->private_value;
7287077148fSMark Brown 	int ret, len;
7297077148fSMark Brown 	unsigned int val, mask;
7307077148fSMark Brown 	void *data;
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 
7377077148fSMark Brown 	data = kmemdup(ucontrol->value.bytes.data, len, GFP_KERNEL | GFP_DMA);
7387077148fSMark Brown 	if (!data)
7397077148fSMark Brown 		return -ENOMEM;
7407077148fSMark Brown 
7417077148fSMark Brown 	/*
7427077148fSMark Brown 	 * If we've got a mask then we need to preserve the register
7437077148fSMark Brown 	 * bits.  We shouldn't modify the incoming data so take a
7447077148fSMark Brown 	 * copy.
7457077148fSMark Brown 	 */
7467077148fSMark Brown 	if (params->mask) {
7477077148fSMark Brown 		ret = regmap_read(component->regmap, params->base, &val);
7487077148fSMark Brown 		if (ret != 0)
7497077148fSMark Brown 			goto out;
7507077148fSMark Brown 
7517077148fSMark Brown 		val &= params->mask;
7527077148fSMark Brown 
7537077148fSMark Brown 		switch (component->val_bytes) {
7547077148fSMark Brown 		case 1:
7557077148fSMark Brown 			((u8 *)data)[0] &= ~params->mask;
7567077148fSMark Brown 			((u8 *)data)[0] |= val;
7577077148fSMark Brown 			break;
7587077148fSMark Brown 		case 2:
7597077148fSMark Brown 			mask = ~params->mask;
7607077148fSMark Brown 			ret = regmap_parse_val(component->regmap,
7617077148fSMark Brown 							&mask, &mask);
7627077148fSMark Brown 			if (ret != 0)
7637077148fSMark Brown 				goto out;
7647077148fSMark Brown 
7657077148fSMark Brown 			((u16 *)data)[0] &= mask;
7667077148fSMark Brown 
7677077148fSMark Brown 			ret = regmap_parse_val(component->regmap,
7687077148fSMark Brown 							&val, &val);
7697077148fSMark Brown 			if (ret != 0)
7707077148fSMark Brown 				goto out;
7717077148fSMark Brown 
7727077148fSMark Brown 			((u16 *)data)[0] |= val;
7737077148fSMark Brown 			break;
7747077148fSMark Brown 		case 4:
7757077148fSMark Brown 			mask = ~params->mask;
7767077148fSMark Brown 			ret = regmap_parse_val(component->regmap,
7777077148fSMark Brown 							&mask, &mask);
7787077148fSMark Brown 			if (ret != 0)
7797077148fSMark Brown 				goto out;
7807077148fSMark Brown 
7817077148fSMark Brown 			((u32 *)data)[0] &= mask;
7827077148fSMark Brown 
7837077148fSMark Brown 			ret = regmap_parse_val(component->regmap,
7847077148fSMark Brown 							&val, &val);
7857077148fSMark Brown 			if (ret != 0)
7867077148fSMark Brown 				goto out;
7877077148fSMark Brown 
7887077148fSMark Brown 			((u32 *)data)[0] |= val;
7897077148fSMark Brown 			break;
7907077148fSMark Brown 		default:
7917077148fSMark Brown 			ret = -EINVAL;
7927077148fSMark Brown 			goto out;
7937077148fSMark Brown 		}
7947077148fSMark Brown 	}
7957077148fSMark Brown 
7967077148fSMark Brown 	ret = regmap_raw_write(component->regmap, params->base,
7977077148fSMark Brown 			       data, len);
7987077148fSMark Brown 
7997077148fSMark Brown out:
8007077148fSMark Brown 	kfree(data);
8017077148fSMark Brown 
8027077148fSMark Brown 	return ret;
8037077148fSMark Brown }
8047077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_bytes_put);
8057077148fSMark Brown 
snd_soc_bytes_info_ext(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * ucontrol)8067077148fSMark Brown int snd_soc_bytes_info_ext(struct snd_kcontrol *kcontrol,
8077077148fSMark Brown 			struct snd_ctl_elem_info *ucontrol)
8087077148fSMark Brown {
8097077148fSMark Brown 	struct soc_bytes_ext *params = (void *)kcontrol->private_value;
8107077148fSMark Brown 
8117077148fSMark Brown 	ucontrol->type = SNDRV_CTL_ELEM_TYPE_BYTES;
8127077148fSMark Brown 	ucontrol->count = params->max;
8137077148fSMark Brown 
8147077148fSMark Brown 	return 0;
8157077148fSMark Brown }
8167077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_bytes_info_ext);
8177077148fSMark Brown 
snd_soc_bytes_tlv_callback(struct snd_kcontrol * kcontrol,int op_flag,unsigned int size,unsigned int __user * tlv)8187077148fSMark Brown int snd_soc_bytes_tlv_callback(struct snd_kcontrol *kcontrol, int op_flag,
8197077148fSMark Brown 				unsigned int size, unsigned int __user *tlv)
8207077148fSMark Brown {
8217077148fSMark Brown 	struct soc_bytes_ext *params = (void *)kcontrol->private_value;
8227077148fSMark Brown 	unsigned int count = size < params->max ? size : params->max;
8237077148fSMark Brown 	int ret = -ENXIO;
8247077148fSMark Brown 
8257077148fSMark Brown 	switch (op_flag) {
8267077148fSMark Brown 	case SNDRV_CTL_TLV_OP_READ:
8277077148fSMark Brown 		if (params->get)
828a1e5e7e9SMythri P K 			ret = params->get(kcontrol, tlv, count);
8297077148fSMark Brown 		break;
8307077148fSMark Brown 	case SNDRV_CTL_TLV_OP_WRITE:
8317077148fSMark Brown 		if (params->put)
832a1e5e7e9SMythri P K 			ret = params->put(kcontrol, tlv, count);
8337077148fSMark Brown 		break;
8347077148fSMark Brown 	}
8357077148fSMark Brown 	return ret;
8367077148fSMark Brown }
8377077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_bytes_tlv_callback);
8387077148fSMark Brown 
8397077148fSMark Brown /**
8407077148fSMark Brown  * snd_soc_info_xr_sx - signed multi register info callback
8417077148fSMark Brown  * @kcontrol: mreg control
8427077148fSMark Brown  * @uinfo: control element information
8437077148fSMark Brown  *
8447077148fSMark Brown  * Callback to provide information of a control that can
8457077148fSMark Brown  * span multiple codec registers which together
8467077148fSMark Brown  * forms a single signed value in a MSB/LSB manner.
8477077148fSMark Brown  *
8487077148fSMark Brown  * Returns 0 for success.
8497077148fSMark Brown  */
snd_soc_info_xr_sx(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)8507077148fSMark Brown int snd_soc_info_xr_sx(struct snd_kcontrol *kcontrol,
8517077148fSMark Brown 	struct snd_ctl_elem_info *uinfo)
8527077148fSMark Brown {
8537077148fSMark Brown 	struct soc_mreg_control *mc =
8547077148fSMark Brown 		(struct soc_mreg_control *)kcontrol->private_value;
8557077148fSMark Brown 	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
8567077148fSMark Brown 	uinfo->count = 1;
8577077148fSMark Brown 	uinfo->value.integer.min = mc->min;
8587077148fSMark Brown 	uinfo->value.integer.max = mc->max;
8597077148fSMark Brown 
8607077148fSMark Brown 	return 0;
8617077148fSMark Brown }
8627077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_info_xr_sx);
8637077148fSMark Brown 
8647077148fSMark Brown /**
8657077148fSMark Brown  * snd_soc_get_xr_sx - signed multi register get callback
8667077148fSMark Brown  * @kcontrol: mreg control
8677077148fSMark Brown  * @ucontrol: control element information
8687077148fSMark Brown  *
8697077148fSMark Brown  * Callback to get the value of a control that can span
8707077148fSMark Brown  * multiple codec registers which together forms a single
8717077148fSMark Brown  * signed value in a MSB/LSB manner. The control supports
8727077148fSMark Brown  * specifying total no of bits used to allow for bitfields
8737077148fSMark Brown  * across the multiple codec registers.
8747077148fSMark Brown  *
8757077148fSMark Brown  * Returns 0 for success.
8767077148fSMark Brown  */
snd_soc_get_xr_sx(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)8777077148fSMark Brown int snd_soc_get_xr_sx(struct snd_kcontrol *kcontrol,
8787077148fSMark Brown 	struct snd_ctl_elem_value *ucontrol)
8797077148fSMark Brown {
8807077148fSMark Brown 	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
8817077148fSMark Brown 	struct soc_mreg_control *mc =
8827077148fSMark Brown 		(struct soc_mreg_control *)kcontrol->private_value;
8837077148fSMark Brown 	unsigned int regbase = mc->regbase;
8847077148fSMark Brown 	unsigned int regcount = mc->regcount;
8857077148fSMark Brown 	unsigned int regwshift = component->val_bytes * BITS_PER_BYTE;
8860ab07091S이경택 	unsigned int regwmask = (1UL<<regwshift)-1;
8877077148fSMark Brown 	unsigned int invert = mc->invert;
8887077148fSMark Brown 	unsigned long mask = (1UL<<mc->nbits)-1;
8897077148fSMark Brown 	long min = mc->min;
8907077148fSMark Brown 	long max = mc->max;
8917077148fSMark Brown 	long val = 0;
8927077148fSMark Brown 	unsigned int i;
8937077148fSMark Brown 
8947077148fSMark Brown 	for (i = 0; i < regcount; i++) {
895b1ebecb9SKuninori Morimoto 		unsigned int regval = snd_soc_component_read(component, regbase+i);
8967077148fSMark Brown 		val |= (regval & regwmask) << (regwshift*(regcount-i-1));
8977077148fSMark Brown 	}
8987077148fSMark Brown 	val &= mask;
8997077148fSMark Brown 	if (min < 0 && val > max)
9007077148fSMark Brown 		val |= ~mask;
9017077148fSMark Brown 	if (invert)
9027077148fSMark Brown 		val = max - val;
9037077148fSMark Brown 	ucontrol->value.integer.value[0] = val;
9047077148fSMark Brown 
9057077148fSMark Brown 	return 0;
9067077148fSMark Brown }
9077077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_get_xr_sx);
9087077148fSMark Brown 
9097077148fSMark Brown /**
9107077148fSMark Brown  * snd_soc_put_xr_sx - signed multi register get callback
9117077148fSMark Brown  * @kcontrol: mreg control
9127077148fSMark Brown  * @ucontrol: control element information
9137077148fSMark Brown  *
9147077148fSMark Brown  * Callback to set the value of a control that can span
9157077148fSMark Brown  * multiple codec registers which together forms a single
9167077148fSMark Brown  * signed value in a MSB/LSB manner. The control supports
9177077148fSMark Brown  * specifying total no of bits used to allow for bitfields
9187077148fSMark Brown  * across the multiple codec registers.
9197077148fSMark Brown  *
9207077148fSMark Brown  * Returns 0 for success.
9217077148fSMark Brown  */
snd_soc_put_xr_sx(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)9227077148fSMark Brown int snd_soc_put_xr_sx(struct snd_kcontrol *kcontrol,
9237077148fSMark Brown 	struct snd_ctl_elem_value *ucontrol)
9247077148fSMark Brown {
9257077148fSMark Brown 	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
9267077148fSMark Brown 	struct soc_mreg_control *mc =
9277077148fSMark Brown 		(struct soc_mreg_control *)kcontrol->private_value;
9287077148fSMark Brown 	unsigned int regbase = mc->regbase;
9297077148fSMark Brown 	unsigned int regcount = mc->regcount;
9307077148fSMark Brown 	unsigned int regwshift = component->val_bytes * BITS_PER_BYTE;
9310ab07091S이경택 	unsigned int regwmask = (1UL<<regwshift)-1;
9327077148fSMark Brown 	unsigned int invert = mc->invert;
9337077148fSMark Brown 	unsigned long mask = (1UL<<mc->nbits)-1;
9347077148fSMark Brown 	long max = mc->max;
9357077148fSMark Brown 	long val = ucontrol->value.integer.value[0];
9362b7c4636SMark Brown 	int ret = 0;
937b285b510SKuninori Morimoto 	unsigned int i;
9387077148fSMark Brown 
9394cf28e9aSMark Brown 	if (val < mc->min || val > mc->max)
9404cf28e9aSMark Brown 		return -EINVAL;
9417077148fSMark Brown 	if (invert)
9427077148fSMark Brown 		val = max - val;
9437077148fSMark Brown 	val &= mask;
9447077148fSMark Brown 	for (i = 0; i < regcount; i++) {
945b285b510SKuninori Morimoto 		unsigned int regval = (val >> (regwshift*(regcount-i-1))) & regwmask;
946b285b510SKuninori Morimoto 		unsigned int regmask = (mask >> (regwshift*(regcount-i-1))) & regwmask;
947b285b510SKuninori Morimoto 		int err = snd_soc_component_update_bits(component, regbase+i,
9487077148fSMark Brown 							regmask, regval);
9497077148fSMark Brown 		if (err < 0)
9507077148fSMark Brown 			return err;
9512b7c4636SMark Brown 		if (err > 0)
9522b7c4636SMark Brown 			ret = err;
9537077148fSMark Brown 	}
9547077148fSMark Brown 
9552b7c4636SMark Brown 	return ret;
9567077148fSMark Brown }
9577077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_put_xr_sx);
9587077148fSMark Brown 
9597077148fSMark Brown /**
9607077148fSMark Brown  * snd_soc_get_strobe - strobe get callback
9617077148fSMark Brown  * @kcontrol: mixer control
9627077148fSMark Brown  * @ucontrol: control element information
9637077148fSMark Brown  *
9647077148fSMark Brown  * Callback get the value of a strobe mixer control.
9657077148fSMark Brown  *
9667077148fSMark Brown  * Returns 0 for success.
9677077148fSMark Brown  */
snd_soc_get_strobe(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)9687077148fSMark Brown int snd_soc_get_strobe(struct snd_kcontrol *kcontrol,
9697077148fSMark Brown 	struct snd_ctl_elem_value *ucontrol)
9707077148fSMark Brown {
9717077148fSMark Brown 	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
9727077148fSMark Brown 	struct soc_mixer_control *mc =
9737077148fSMark Brown 		(struct soc_mixer_control *)kcontrol->private_value;
9747077148fSMark Brown 	unsigned int reg = mc->reg;
9757077148fSMark Brown 	unsigned int shift = mc->shift;
9767077148fSMark Brown 	unsigned int mask = 1 << shift;
9777077148fSMark Brown 	unsigned int invert = mc->invert != 0;
9787077148fSMark Brown 	unsigned int val;
9797077148fSMark Brown 
980cf6e26c7SKuninori Morimoto 	val = snd_soc_component_read(component, reg);
9817077148fSMark Brown 	val &= mask;
9827077148fSMark Brown 
9837077148fSMark Brown 	if (shift != 0 && val != 0)
9847077148fSMark Brown 		val = val >> shift;
9857077148fSMark Brown 	ucontrol->value.enumerated.item[0] = val ^ invert;
9867077148fSMark Brown 
9877077148fSMark Brown 	return 0;
9887077148fSMark Brown }
9897077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_get_strobe);
9907077148fSMark Brown 
9917077148fSMark Brown /**
9927077148fSMark Brown  * snd_soc_put_strobe - strobe put callback
9937077148fSMark Brown  * @kcontrol: mixer control
9947077148fSMark Brown  * @ucontrol: control element information
9957077148fSMark Brown  *
9967077148fSMark Brown  * Callback strobe a register bit to high then low (or the inverse)
9977077148fSMark Brown  * in one pass of a single mixer enum control.
9987077148fSMark Brown  *
9997077148fSMark Brown  * Returns 1 for success.
10007077148fSMark Brown  */
snd_soc_put_strobe(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)10017077148fSMark Brown int snd_soc_put_strobe(struct snd_kcontrol *kcontrol,
10027077148fSMark Brown 	struct snd_ctl_elem_value *ucontrol)
10037077148fSMark Brown {
10047077148fSMark Brown 	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
10057077148fSMark Brown 	struct soc_mixer_control *mc =
10067077148fSMark Brown 		(struct soc_mixer_control *)kcontrol->private_value;
10077077148fSMark Brown 	unsigned int reg = mc->reg;
10087077148fSMark Brown 	unsigned int shift = mc->shift;
10097077148fSMark Brown 	unsigned int mask = 1 << shift;
10107077148fSMark Brown 	unsigned int invert = mc->invert != 0;
10117077148fSMark Brown 	unsigned int strobe = ucontrol->value.enumerated.item[0] != 0;
10127077148fSMark Brown 	unsigned int val1 = (strobe ^ invert) ? mask : 0;
10137077148fSMark Brown 	unsigned int val2 = (strobe ^ invert) ? 0 : mask;
10147077148fSMark Brown 	int err;
10157077148fSMark Brown 
10167077148fSMark Brown 	err = snd_soc_component_update_bits(component, reg, mask, val1);
10177077148fSMark Brown 	if (err < 0)
10187077148fSMark Brown 		return err;
10197077148fSMark Brown 
10207077148fSMark Brown 	return snd_soc_component_update_bits(component, reg, mask, val2);
10217077148fSMark Brown }
10227077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_put_strobe);
1023