xref: /linux/sound/soc/soc-ops.c (revision a1ff5a7d78a036d6c2178ee5acd6ba4946243800)
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