xref: /openbmc/linux/sound/soc/soc-ops.c (revision 7f3d90a3)
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/delay.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  */
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  */
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  */
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  */
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  */
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;
1807077148fSMark Brown 	int platform_max;
1817077148fSMark Brown 
1827077148fSMark Brown 	if (!mc->platform_max)
1837077148fSMark Brown 		mc->platform_max = mc->max;
1847077148fSMark Brown 	platform_max = mc->platform_max;
1857077148fSMark Brown 
1867077148fSMark Brown 	if (platform_max == 1 && !strstr(kcontrol->id.name, " Volume"))
1877077148fSMark Brown 		uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
1887077148fSMark Brown 	else
1897077148fSMark Brown 		uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1907077148fSMark Brown 
1917077148fSMark Brown 	uinfo->count = snd_soc_volsw_is_stereo(mc) ? 2 : 1;
1927077148fSMark Brown 	uinfo->value.integer.min = 0;
1937077148fSMark Brown 	uinfo->value.integer.max = platform_max - mc->min;
1947077148fSMark Brown 	return 0;
1957077148fSMark Brown }
1967077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_info_volsw);
1977077148fSMark Brown 
1987077148fSMark Brown /**
19934198710SCharles Keepax  * snd_soc_info_volsw_sx - Mixer info callback for SX TLV controls
20034198710SCharles Keepax  * @kcontrol: mixer control
20134198710SCharles Keepax  * @uinfo: control element information
20234198710SCharles Keepax  *
20334198710SCharles Keepax  * Callback to provide information about a single mixer control, or a double
20434198710SCharles Keepax  * mixer control that spans 2 registers of the SX TLV type. SX TLV controls
20534198710SCharles Keepax  * have a range that represents both positive and negative values either side
20634198710SCharles Keepax  * of zero but without a sign bit.
20734198710SCharles Keepax  *
20834198710SCharles Keepax  * Returns 0 for success.
20934198710SCharles Keepax  */
21034198710SCharles Keepax int snd_soc_info_volsw_sx(struct snd_kcontrol *kcontrol,
21134198710SCharles Keepax 			  struct snd_ctl_elem_info *uinfo)
21234198710SCharles Keepax {
21334198710SCharles Keepax 	struct soc_mixer_control *mc =
21434198710SCharles Keepax 		(struct soc_mixer_control *)kcontrol->private_value;
21534198710SCharles Keepax 
21634198710SCharles Keepax 	snd_soc_info_volsw(kcontrol, uinfo);
21734198710SCharles Keepax 	/* Max represents the number of levels in an SX control not the
21834198710SCharles Keepax 	 * maximum value, so add the minimum value back on
21934198710SCharles Keepax 	 */
22034198710SCharles Keepax 	uinfo->value.integer.max += mc->min;
22134198710SCharles Keepax 
22234198710SCharles Keepax 	return 0;
22334198710SCharles Keepax }
22434198710SCharles Keepax EXPORT_SYMBOL_GPL(snd_soc_info_volsw_sx);
22534198710SCharles Keepax 
22634198710SCharles Keepax /**
2277077148fSMark Brown  * snd_soc_get_volsw - single mixer get callback
2287077148fSMark Brown  * @kcontrol: mixer control
2297077148fSMark Brown  * @ucontrol: control element information
2307077148fSMark Brown  *
2317077148fSMark Brown  * Callback to get the value of a single mixer control, or a double mixer
2327077148fSMark Brown  * control that spans 2 registers.
2337077148fSMark Brown  *
2347077148fSMark Brown  * Returns 0 for success.
2357077148fSMark Brown  */
2367077148fSMark Brown int snd_soc_get_volsw(struct snd_kcontrol *kcontrol,
2377077148fSMark Brown 	struct snd_ctl_elem_value *ucontrol)
2387077148fSMark Brown {
2397077148fSMark Brown 	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
2407077148fSMark Brown 	struct soc_mixer_control *mc =
2417077148fSMark Brown 		(struct soc_mixer_control *)kcontrol->private_value;
2427077148fSMark Brown 	unsigned int reg = mc->reg;
2437077148fSMark Brown 	unsigned int reg2 = mc->rreg;
2447077148fSMark Brown 	unsigned int shift = mc->shift;
2457077148fSMark Brown 	unsigned int rshift = mc->rshift;
2467077148fSMark Brown 	int max = mc->max;
2477077148fSMark Brown 	int min = mc->min;
2487077148fSMark Brown 	int sign_bit = mc->sign_bit;
2497077148fSMark Brown 	unsigned int mask = (1 << fls(max)) - 1;
2507077148fSMark Brown 	unsigned int invert = mc->invert;
2517077148fSMark Brown 	int val;
2527077148fSMark Brown 	int ret;
2537077148fSMark Brown 
2547077148fSMark Brown 	if (sign_bit)
2557077148fSMark Brown 		mask = BIT(sign_bit + 1) - 1;
2567077148fSMark Brown 
2577077148fSMark Brown 	ret = snd_soc_read_signed(component, reg, mask, shift, sign_bit, &val);
2587077148fSMark Brown 	if (ret)
2597077148fSMark Brown 		return ret;
2607077148fSMark Brown 
2617077148fSMark Brown 	ucontrol->value.integer.value[0] = val - min;
2627077148fSMark Brown 	if (invert)
2637077148fSMark Brown 		ucontrol->value.integer.value[0] =
2647077148fSMark Brown 			max - ucontrol->value.integer.value[0];
2657077148fSMark Brown 
2667077148fSMark Brown 	if (snd_soc_volsw_is_stereo(mc)) {
2677077148fSMark Brown 		if (reg == reg2)
2687077148fSMark Brown 			ret = snd_soc_read_signed(component, reg, mask, rshift,
2697077148fSMark Brown 				sign_bit, &val);
2707077148fSMark Brown 		else
2717077148fSMark Brown 			ret = snd_soc_read_signed(component, reg2, mask, shift,
2727077148fSMark Brown 				sign_bit, &val);
2737077148fSMark Brown 		if (ret)
2747077148fSMark Brown 			return ret;
2757077148fSMark Brown 
2767077148fSMark Brown 		ucontrol->value.integer.value[1] = val - min;
2777077148fSMark Brown 		if (invert)
2787077148fSMark Brown 			ucontrol->value.integer.value[1] =
2797077148fSMark Brown 				max - ucontrol->value.integer.value[1];
2807077148fSMark Brown 	}
2817077148fSMark Brown 
2827077148fSMark Brown 	return 0;
2837077148fSMark Brown }
2847077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_get_volsw);
2857077148fSMark Brown 
2867077148fSMark Brown /**
2877077148fSMark Brown  * snd_soc_put_volsw - single mixer put callback
2887077148fSMark Brown  * @kcontrol: mixer control
2897077148fSMark Brown  * @ucontrol: control element information
2907077148fSMark Brown  *
2917077148fSMark Brown  * Callback to set the value of a single mixer control, or a double mixer
2927077148fSMark Brown  * control that spans 2 registers.
2937077148fSMark Brown  *
2947077148fSMark Brown  * Returns 0 for success.
2957077148fSMark Brown  */
2967077148fSMark Brown int snd_soc_put_volsw(struct snd_kcontrol *kcontrol,
2977077148fSMark Brown 	struct snd_ctl_elem_value *ucontrol)
2987077148fSMark Brown {
2997077148fSMark Brown 	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
3007077148fSMark Brown 	struct soc_mixer_control *mc =
3017077148fSMark Brown 		(struct soc_mixer_control *)kcontrol->private_value;
3027077148fSMark Brown 	unsigned int reg = mc->reg;
3037077148fSMark Brown 	unsigned int reg2 = mc->rreg;
3047077148fSMark Brown 	unsigned int shift = mc->shift;
3057077148fSMark Brown 	unsigned int rshift = mc->rshift;
3067077148fSMark Brown 	int max = mc->max;
3077077148fSMark Brown 	int min = mc->min;
3087077148fSMark Brown 	unsigned int sign_bit = mc->sign_bit;
3097077148fSMark Brown 	unsigned int mask = (1 << fls(max)) - 1;
3107077148fSMark Brown 	unsigned int invert = mc->invert;
311564778d7SMark Brown 	int err, ret;
3127077148fSMark Brown 	bool type_2r = false;
3137077148fSMark Brown 	unsigned int val2 = 0;
3147077148fSMark Brown 	unsigned int val, val_mask;
3157077148fSMark Brown 
3167077148fSMark Brown 	if (sign_bit)
3177077148fSMark Brown 		mask = BIT(sign_bit + 1) - 1;
3187077148fSMark Brown 
3191601033dSMark Brown 	if (ucontrol->value.integer.value[0] < 0)
3201601033dSMark Brown 		return -EINVAL;
321817f7c93SMark Brown 	val = ucontrol->value.integer.value[0];
322817f7c93SMark Brown 	if (mc->platform_max && val > mc->platform_max)
323817f7c93SMark Brown 		return -EINVAL;
324817f7c93SMark Brown 	if (val > max - min)
325817f7c93SMark Brown 		return -EINVAL;
326817f7c93SMark Brown 	val = (val + min) & mask;
3277077148fSMark Brown 	if (invert)
3287077148fSMark Brown 		val = max - val;
3297077148fSMark Brown 	val_mask = mask << shift;
3307077148fSMark Brown 	val = val << shift;
3317077148fSMark Brown 	if (snd_soc_volsw_is_stereo(mc)) {
3321601033dSMark Brown 		if (ucontrol->value.integer.value[1] < 0)
3331601033dSMark Brown 			return -EINVAL;
334817f7c93SMark Brown 		val2 = ucontrol->value.integer.value[1];
335817f7c93SMark Brown 		if (mc->platform_max && val2 > mc->platform_max)
336817f7c93SMark Brown 			return -EINVAL;
337817f7c93SMark Brown 		if (val2 > max - min)
338817f7c93SMark Brown 			return -EINVAL;
339817f7c93SMark Brown 		val2 = (val2 + min) & mask;
3407077148fSMark Brown 		if (invert)
3417077148fSMark Brown 			val2 = max - val2;
3427077148fSMark Brown 		if (reg == reg2) {
3437077148fSMark Brown 			val_mask |= mask << rshift;
3447077148fSMark Brown 			val |= val2 << rshift;
3457077148fSMark Brown 		} else {
3467077148fSMark Brown 			val2 = val2 << shift;
3477077148fSMark Brown 			type_2r = true;
3487077148fSMark Brown 		}
3497077148fSMark Brown 	}
3507077148fSMark Brown 	err = snd_soc_component_update_bits(component, reg, val_mask, val);
3517077148fSMark Brown 	if (err < 0)
3527077148fSMark Brown 		return err;
353564778d7SMark Brown 	ret = err;
3547077148fSMark Brown 
355564778d7SMark Brown 	if (type_2r) {
3567077148fSMark Brown 		err = snd_soc_component_update_bits(component, reg2, val_mask,
3577077148fSMark Brown 						    val2);
358564778d7SMark Brown 		/* Don't discard any error code or drop change flag */
359564778d7SMark Brown 		if (ret == 0 || err < 0) {
360564778d7SMark Brown 			ret = err;
361564778d7SMark Brown 		}
362564778d7SMark Brown 	}
3637077148fSMark Brown 
364564778d7SMark Brown 	return ret;
3657077148fSMark Brown }
3667077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_put_volsw);
3677077148fSMark Brown 
3687077148fSMark Brown /**
3697077148fSMark Brown  * snd_soc_get_volsw_sx - single mixer get callback
3707077148fSMark Brown  * @kcontrol: mixer control
3717077148fSMark Brown  * @ucontrol: control element information
3727077148fSMark Brown  *
3737077148fSMark Brown  * Callback to get the value of a single mixer control, or a double mixer
3747077148fSMark Brown  * control that spans 2 registers.
3757077148fSMark Brown  *
3767077148fSMark Brown  * Returns 0 for success.
3777077148fSMark Brown  */
3787077148fSMark Brown int snd_soc_get_volsw_sx(struct snd_kcontrol *kcontrol,
3797077148fSMark Brown 		      struct snd_ctl_elem_value *ucontrol)
3807077148fSMark Brown {
3817077148fSMark Brown 	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
3827077148fSMark Brown 	struct soc_mixer_control *mc =
3837077148fSMark Brown 	    (struct soc_mixer_control *)kcontrol->private_value;
3847077148fSMark Brown 	unsigned int reg = mc->reg;
3857077148fSMark Brown 	unsigned int reg2 = mc->rreg;
3867077148fSMark Brown 	unsigned int shift = mc->shift;
3877077148fSMark Brown 	unsigned int rshift = mc->rshift;
3887077148fSMark Brown 	int max = mc->max;
3897077148fSMark Brown 	int min = mc->min;
390ae7d1247SRohit kumar 	unsigned int mask = (1U << (fls(min + max) - 1)) - 1;
3917077148fSMark Brown 	unsigned int val;
3927077148fSMark Brown 
393cf6e26c7SKuninori Morimoto 	val = snd_soc_component_read(component, reg);
3947077148fSMark Brown 	ucontrol->value.integer.value[0] = ((val >> shift) - min) & mask;
3957077148fSMark Brown 
3967077148fSMark Brown 	if (snd_soc_volsw_is_stereo(mc)) {
397cf6e26c7SKuninori Morimoto 		val = snd_soc_component_read(component, reg2);
3987077148fSMark Brown 		val = ((val >> rshift) - min) & mask;
3997077148fSMark Brown 		ucontrol->value.integer.value[1] = val;
4007077148fSMark Brown 	}
4017077148fSMark Brown 
4027077148fSMark Brown 	return 0;
4037077148fSMark Brown }
4047077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_get_volsw_sx);
4057077148fSMark Brown 
4067077148fSMark Brown /**
4077077148fSMark Brown  * snd_soc_put_volsw_sx - double mixer set callback
4087077148fSMark Brown  * @kcontrol: mixer control
4099a11ef7fSRandy Dunlap  * @ucontrol: control element information
4107077148fSMark Brown  *
4117077148fSMark Brown  * Callback to set the value of a double mixer control that spans 2 registers.
4127077148fSMark Brown  *
4137077148fSMark Brown  * Returns 0 for success.
4147077148fSMark Brown  */
4157077148fSMark Brown int snd_soc_put_volsw_sx(struct snd_kcontrol *kcontrol,
4167077148fSMark Brown 			 struct snd_ctl_elem_value *ucontrol)
4177077148fSMark Brown {
4187077148fSMark Brown 	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
4197077148fSMark Brown 	struct soc_mixer_control *mc =
4207077148fSMark Brown 	    (struct soc_mixer_control *)kcontrol->private_value;
4217077148fSMark Brown 
4227077148fSMark Brown 	unsigned int reg = mc->reg;
4237077148fSMark Brown 	unsigned int reg2 = mc->rreg;
4247077148fSMark Brown 	unsigned int shift = mc->shift;
4257077148fSMark Brown 	unsigned int rshift = mc->rshift;
4267077148fSMark Brown 	int max = mc->max;
4277077148fSMark Brown 	int min = mc->min;
428ae7d1247SRohit kumar 	unsigned int mask = (1U << (fls(min + max) - 1)) - 1;
4297077148fSMark Brown 	int err = 0;
430*7f3d90a3SMark Brown 	int ret;
43158f42dfdSKuninori Morimoto 	unsigned int val, val_mask;
4327077148fSMark Brown 
4331601033dSMark Brown 	if (ucontrol->value.integer.value[0] < 0)
4341601033dSMark Brown 		return -EINVAL;
4354f1e50d6SMark Brown 	val = ucontrol->value.integer.value[0];
4364f1e50d6SMark Brown 	if (mc->platform_max && val > mc->platform_max)
4374f1e50d6SMark Brown 		return -EINVAL;
4384f1e50d6SMark Brown 	if (val > max - min)
4394f1e50d6SMark Brown 		return -EINVAL;
4407077148fSMark Brown 	val_mask = mask << shift;
4414f1e50d6SMark Brown 	val = (val + min) & mask;
4427077148fSMark Brown 	val = val << shift;
4437077148fSMark Brown 
4447077148fSMark Brown 	err = snd_soc_component_update_bits(component, reg, val_mask, val);
4457077148fSMark Brown 	if (err < 0)
4467077148fSMark Brown 		return err;
447*7f3d90a3SMark Brown 	ret = err;
4487077148fSMark Brown 
4497077148fSMark Brown 	if (snd_soc_volsw_is_stereo(mc)) {
45058f42dfdSKuninori Morimoto 		unsigned int val2;
45158f42dfdSKuninori Morimoto 
4527077148fSMark Brown 		val_mask = mask << rshift;
4537077148fSMark Brown 		val2 = (ucontrol->value.integer.value[1] + min) & mask;
4547077148fSMark Brown 		val2 = val2 << rshift;
4557077148fSMark Brown 
4567077148fSMark Brown 		err = snd_soc_component_update_bits(component, reg2, val_mask,
4577077148fSMark Brown 			val2);
458*7f3d90a3SMark Brown 
459*7f3d90a3SMark Brown 		/* Don't discard any error code or drop change flag */
460*7f3d90a3SMark Brown 		if (ret == 0 || err < 0) {
461*7f3d90a3SMark Brown 			ret = err;
462*7f3d90a3SMark Brown 		}
4637077148fSMark Brown 	}
4647077148fSMark Brown 	return err;
4657077148fSMark Brown }
4667077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_put_volsw_sx);
4677077148fSMark Brown 
4687077148fSMark Brown /**
4697077148fSMark Brown  * snd_soc_info_volsw_range - single mixer info callback with range.
4707077148fSMark Brown  * @kcontrol: mixer control
4717077148fSMark Brown  * @uinfo: control element information
4727077148fSMark Brown  *
4737077148fSMark Brown  * Callback to provide information, within a range, about a single
4747077148fSMark Brown  * mixer control.
4757077148fSMark Brown  *
4767077148fSMark Brown  * returns 0 for success.
4777077148fSMark Brown  */
4787077148fSMark Brown int snd_soc_info_volsw_range(struct snd_kcontrol *kcontrol,
4797077148fSMark Brown 	struct snd_ctl_elem_info *uinfo)
4807077148fSMark Brown {
4817077148fSMark Brown 	struct soc_mixer_control *mc =
4827077148fSMark Brown 		(struct soc_mixer_control *)kcontrol->private_value;
4837077148fSMark Brown 	int platform_max;
4847077148fSMark Brown 	int min = mc->min;
4857077148fSMark Brown 
4867077148fSMark Brown 	if (!mc->platform_max)
4877077148fSMark Brown 		mc->platform_max = mc->max;
4887077148fSMark Brown 	platform_max = mc->platform_max;
4897077148fSMark Brown 
4907077148fSMark Brown 	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
4917077148fSMark Brown 	uinfo->count = snd_soc_volsw_is_stereo(mc) ? 2 : 1;
4927077148fSMark Brown 	uinfo->value.integer.min = 0;
4937077148fSMark Brown 	uinfo->value.integer.max = platform_max - min;
4947077148fSMark Brown 
4957077148fSMark Brown 	return 0;
4967077148fSMark Brown }
4977077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_info_volsw_range);
4987077148fSMark Brown 
4997077148fSMark Brown /**
5007077148fSMark Brown  * snd_soc_put_volsw_range - single mixer put value callback with range.
5017077148fSMark Brown  * @kcontrol: mixer control
5027077148fSMark Brown  * @ucontrol: control element information
5037077148fSMark Brown  *
5047077148fSMark Brown  * Callback to set the value, within a range, for a single mixer control.
5057077148fSMark Brown  *
5067077148fSMark Brown  * Returns 0 for success.
5077077148fSMark Brown  */
5087077148fSMark Brown int snd_soc_put_volsw_range(struct snd_kcontrol *kcontrol,
5097077148fSMark Brown 	struct snd_ctl_elem_value *ucontrol)
5107077148fSMark Brown {
5117077148fSMark Brown 	struct soc_mixer_control *mc =
5127077148fSMark Brown 		(struct soc_mixer_control *)kcontrol->private_value;
5137077148fSMark Brown 	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
5147077148fSMark Brown 	unsigned int reg = mc->reg;
5157077148fSMark Brown 	unsigned int rreg = mc->rreg;
5167077148fSMark Brown 	unsigned int shift = mc->shift;
5177077148fSMark Brown 	int min = mc->min;
5187077148fSMark Brown 	int max = mc->max;
5197077148fSMark Brown 	unsigned int mask = (1 << fls(max)) - 1;
5207077148fSMark Brown 	unsigned int invert = mc->invert;
5217077148fSMark Brown 	unsigned int val, val_mask;
5227077148fSMark Brown 	int ret;
5237077148fSMark Brown 
5247077148fSMark Brown 	if (invert)
5257077148fSMark Brown 		val = (max - ucontrol->value.integer.value[0]) & mask;
5267077148fSMark Brown 	else
5277077148fSMark Brown 		val = ((ucontrol->value.integer.value[0] + min) & mask);
5287077148fSMark Brown 	val_mask = mask << shift;
5297077148fSMark Brown 	val = val << shift;
5307077148fSMark Brown 
5317077148fSMark Brown 	ret = snd_soc_component_update_bits(component, reg, val_mask, val);
5327077148fSMark Brown 	if (ret < 0)
5337077148fSMark Brown 		return ret;
5347077148fSMark Brown 
5357077148fSMark Brown 	if (snd_soc_volsw_is_stereo(mc)) {
5367077148fSMark Brown 		if (invert)
5377077148fSMark Brown 			val = (max - ucontrol->value.integer.value[1]) & mask;
5387077148fSMark Brown 		else
5397077148fSMark Brown 			val = ((ucontrol->value.integer.value[1] + min) & mask);
5407077148fSMark Brown 		val_mask = mask << shift;
5417077148fSMark Brown 		val = val << shift;
5427077148fSMark Brown 
5437077148fSMark Brown 		ret = snd_soc_component_update_bits(component, rreg, val_mask,
5447077148fSMark Brown 			val);
5457077148fSMark Brown 	}
5467077148fSMark Brown 
5477077148fSMark Brown 	return ret;
5487077148fSMark Brown }
5497077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_put_volsw_range);
5507077148fSMark Brown 
5517077148fSMark Brown /**
5527077148fSMark Brown  * snd_soc_get_volsw_range - single mixer get callback with range
5537077148fSMark Brown  * @kcontrol: mixer control
5547077148fSMark Brown  * @ucontrol: control element information
5557077148fSMark Brown  *
5567077148fSMark Brown  * Callback to get the value, within a range, of a single mixer control.
5577077148fSMark Brown  *
5587077148fSMark Brown  * Returns 0 for success.
5597077148fSMark Brown  */
5607077148fSMark Brown int snd_soc_get_volsw_range(struct snd_kcontrol *kcontrol,
5617077148fSMark Brown 	struct snd_ctl_elem_value *ucontrol)
5627077148fSMark Brown {
5637077148fSMark Brown 	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
5647077148fSMark Brown 	struct soc_mixer_control *mc =
5657077148fSMark Brown 		(struct soc_mixer_control *)kcontrol->private_value;
5667077148fSMark Brown 	unsigned int reg = mc->reg;
5677077148fSMark Brown 	unsigned int rreg = mc->rreg;
5687077148fSMark Brown 	unsigned int shift = mc->shift;
5697077148fSMark Brown 	int min = mc->min;
5707077148fSMark Brown 	int max = mc->max;
5717077148fSMark Brown 	unsigned int mask = (1 << fls(max)) - 1;
5727077148fSMark Brown 	unsigned int invert = mc->invert;
5737077148fSMark Brown 	unsigned int val;
5747077148fSMark Brown 
575cf6e26c7SKuninori Morimoto 	val = snd_soc_component_read(component, reg);
5767077148fSMark Brown 	ucontrol->value.integer.value[0] = (val >> shift) & mask;
5777077148fSMark Brown 	if (invert)
5787077148fSMark Brown 		ucontrol->value.integer.value[0] =
5797077148fSMark Brown 			max - ucontrol->value.integer.value[0];
5807077148fSMark Brown 	else
5817077148fSMark Brown 		ucontrol->value.integer.value[0] =
5827077148fSMark Brown 			ucontrol->value.integer.value[0] - min;
5837077148fSMark Brown 
5847077148fSMark Brown 	if (snd_soc_volsw_is_stereo(mc)) {
585cf6e26c7SKuninori Morimoto 		val = snd_soc_component_read(component, rreg);
5867077148fSMark Brown 		ucontrol->value.integer.value[1] = (val >> shift) & mask;
5877077148fSMark Brown 		if (invert)
5887077148fSMark Brown 			ucontrol->value.integer.value[1] =
5897077148fSMark Brown 				max - ucontrol->value.integer.value[1];
5907077148fSMark Brown 		else
5917077148fSMark Brown 			ucontrol->value.integer.value[1] =
5927077148fSMark Brown 				ucontrol->value.integer.value[1] - min;
5937077148fSMark Brown 	}
5947077148fSMark Brown 
5957077148fSMark Brown 	return 0;
5967077148fSMark Brown }
5977077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_get_volsw_range);
5987077148fSMark Brown 
5997077148fSMark Brown /**
6007077148fSMark Brown  * snd_soc_limit_volume - Set new limit to an existing volume control.
6017077148fSMark Brown  *
60226d9ca34SLars-Peter Clausen  * @card: where to look for the control
6037077148fSMark Brown  * @name: Name of the control
6047077148fSMark Brown  * @max: new maximum limit
6057077148fSMark Brown  *
6067077148fSMark Brown  * Return 0 for success, else error.
6077077148fSMark Brown  */
60826d9ca34SLars-Peter Clausen int snd_soc_limit_volume(struct snd_soc_card *card,
6097077148fSMark Brown 	const char *name, int max)
6107077148fSMark Brown {
6117077148fSMark Brown 	struct snd_kcontrol *kctl;
6127077148fSMark Brown 	int ret = -EINVAL;
6137077148fSMark Brown 
6147077148fSMark Brown 	/* Sanity check for name and max */
6157077148fSMark Brown 	if (unlikely(!name || max <= 0))
6167077148fSMark Brown 		return -EINVAL;
6177077148fSMark Brown 
6180881ab6eSKuninori Morimoto 	kctl = snd_soc_card_get_kcontrol(card, name);
6190881ab6eSKuninori Morimoto 	if (kctl) {
620872040f7SKuninori Morimoto 		struct soc_mixer_control *mc = (struct soc_mixer_control *)kctl->private_value;
6217077148fSMark Brown 		if (max <= mc->max) {
6227077148fSMark Brown 			mc->platform_max = max;
6237077148fSMark Brown 			ret = 0;
6247077148fSMark Brown 		}
6257077148fSMark Brown 	}
6267077148fSMark Brown 	return ret;
6277077148fSMark Brown }
6287077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_limit_volume);
6297077148fSMark Brown 
6307077148fSMark Brown int snd_soc_bytes_info(struct snd_kcontrol *kcontrol,
6317077148fSMark Brown 		       struct snd_ctl_elem_info *uinfo)
6327077148fSMark Brown {
6337077148fSMark Brown 	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
6347077148fSMark Brown 	struct soc_bytes *params = (void *)kcontrol->private_value;
6357077148fSMark Brown 
6367077148fSMark Brown 	uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
6377077148fSMark Brown 	uinfo->count = params->num_regs * component->val_bytes;
6387077148fSMark Brown 
6397077148fSMark Brown 	return 0;
6407077148fSMark Brown }
6417077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_bytes_info);
6427077148fSMark Brown 
6437077148fSMark Brown int snd_soc_bytes_get(struct snd_kcontrol *kcontrol,
6447077148fSMark Brown 		      struct snd_ctl_elem_value *ucontrol)
6457077148fSMark Brown {
6467077148fSMark Brown 	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
6477077148fSMark Brown 	struct soc_bytes *params = (void *)kcontrol->private_value;
6487077148fSMark Brown 	int ret;
6497077148fSMark Brown 
6507077148fSMark Brown 	if (component->regmap)
6517077148fSMark Brown 		ret = regmap_raw_read(component->regmap, params->base,
6527077148fSMark Brown 				      ucontrol->value.bytes.data,
6537077148fSMark Brown 				      params->num_regs * component->val_bytes);
6547077148fSMark Brown 	else
6557077148fSMark Brown 		ret = -EINVAL;
6567077148fSMark Brown 
6577077148fSMark Brown 	/* Hide any masked bytes to ensure consistent data reporting */
6587077148fSMark Brown 	if (ret == 0 && params->mask) {
6597077148fSMark Brown 		switch (component->val_bytes) {
6607077148fSMark Brown 		case 1:
6617077148fSMark Brown 			ucontrol->value.bytes.data[0] &= ~params->mask;
6627077148fSMark Brown 			break;
6637077148fSMark Brown 		case 2:
6647077148fSMark Brown 			((u16 *)(&ucontrol->value.bytes.data))[0]
6657077148fSMark Brown 				&= cpu_to_be16(~params->mask);
6667077148fSMark Brown 			break;
6677077148fSMark Brown 		case 4:
6687077148fSMark Brown 			((u32 *)(&ucontrol->value.bytes.data))[0]
6697077148fSMark Brown 				&= cpu_to_be32(~params->mask);
6707077148fSMark Brown 			break;
6717077148fSMark Brown 		default:
6727077148fSMark Brown 			return -EINVAL;
6737077148fSMark Brown 		}
6747077148fSMark Brown 	}
6757077148fSMark Brown 
6767077148fSMark Brown 	return ret;
6777077148fSMark Brown }
6787077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_bytes_get);
6797077148fSMark Brown 
6807077148fSMark Brown int snd_soc_bytes_put(struct snd_kcontrol *kcontrol,
6817077148fSMark Brown 		      struct snd_ctl_elem_value *ucontrol)
6827077148fSMark Brown {
6837077148fSMark Brown 	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
6847077148fSMark Brown 	struct soc_bytes *params = (void *)kcontrol->private_value;
6857077148fSMark Brown 	int ret, len;
6867077148fSMark Brown 	unsigned int val, mask;
6877077148fSMark Brown 	void *data;
6887077148fSMark Brown 
6897077148fSMark Brown 	if (!component->regmap || !params->num_regs)
6907077148fSMark Brown 		return -EINVAL;
6917077148fSMark Brown 
6927077148fSMark Brown 	len = params->num_regs * component->val_bytes;
6937077148fSMark Brown 
6947077148fSMark Brown 	data = kmemdup(ucontrol->value.bytes.data, len, GFP_KERNEL | GFP_DMA);
6957077148fSMark Brown 	if (!data)
6967077148fSMark Brown 		return -ENOMEM;
6977077148fSMark Brown 
6987077148fSMark Brown 	/*
6997077148fSMark Brown 	 * If we've got a mask then we need to preserve the register
7007077148fSMark Brown 	 * bits.  We shouldn't modify the incoming data so take a
7017077148fSMark Brown 	 * copy.
7027077148fSMark Brown 	 */
7037077148fSMark Brown 	if (params->mask) {
7047077148fSMark Brown 		ret = regmap_read(component->regmap, params->base, &val);
7057077148fSMark Brown 		if (ret != 0)
7067077148fSMark Brown 			goto out;
7077077148fSMark Brown 
7087077148fSMark Brown 		val &= params->mask;
7097077148fSMark Brown 
7107077148fSMark Brown 		switch (component->val_bytes) {
7117077148fSMark Brown 		case 1:
7127077148fSMark Brown 			((u8 *)data)[0] &= ~params->mask;
7137077148fSMark Brown 			((u8 *)data)[0] |= val;
7147077148fSMark Brown 			break;
7157077148fSMark Brown 		case 2:
7167077148fSMark Brown 			mask = ~params->mask;
7177077148fSMark Brown 			ret = regmap_parse_val(component->regmap,
7187077148fSMark Brown 							&mask, &mask);
7197077148fSMark Brown 			if (ret != 0)
7207077148fSMark Brown 				goto out;
7217077148fSMark Brown 
7227077148fSMark Brown 			((u16 *)data)[0] &= mask;
7237077148fSMark Brown 
7247077148fSMark Brown 			ret = regmap_parse_val(component->regmap,
7257077148fSMark Brown 							&val, &val);
7267077148fSMark Brown 			if (ret != 0)
7277077148fSMark Brown 				goto out;
7287077148fSMark Brown 
7297077148fSMark Brown 			((u16 *)data)[0] |= val;
7307077148fSMark Brown 			break;
7317077148fSMark Brown 		case 4:
7327077148fSMark Brown 			mask = ~params->mask;
7337077148fSMark Brown 			ret = regmap_parse_val(component->regmap,
7347077148fSMark Brown 							&mask, &mask);
7357077148fSMark Brown 			if (ret != 0)
7367077148fSMark Brown 				goto out;
7377077148fSMark Brown 
7387077148fSMark Brown 			((u32 *)data)[0] &= mask;
7397077148fSMark Brown 
7407077148fSMark Brown 			ret = regmap_parse_val(component->regmap,
7417077148fSMark Brown 							&val, &val);
7427077148fSMark Brown 			if (ret != 0)
7437077148fSMark Brown 				goto out;
7447077148fSMark Brown 
7457077148fSMark Brown 			((u32 *)data)[0] |= val;
7467077148fSMark Brown 			break;
7477077148fSMark Brown 		default:
7487077148fSMark Brown 			ret = -EINVAL;
7497077148fSMark Brown 			goto out;
7507077148fSMark Brown 		}
7517077148fSMark Brown 	}
7527077148fSMark Brown 
7537077148fSMark Brown 	ret = regmap_raw_write(component->regmap, params->base,
7547077148fSMark Brown 			       data, len);
7557077148fSMark Brown 
7567077148fSMark Brown out:
7577077148fSMark Brown 	kfree(data);
7587077148fSMark Brown 
7597077148fSMark Brown 	return ret;
7607077148fSMark Brown }
7617077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_bytes_put);
7627077148fSMark Brown 
7637077148fSMark Brown int snd_soc_bytes_info_ext(struct snd_kcontrol *kcontrol,
7647077148fSMark Brown 			struct snd_ctl_elem_info *ucontrol)
7657077148fSMark Brown {
7667077148fSMark Brown 	struct soc_bytes_ext *params = (void *)kcontrol->private_value;
7677077148fSMark Brown 
7687077148fSMark Brown 	ucontrol->type = SNDRV_CTL_ELEM_TYPE_BYTES;
7697077148fSMark Brown 	ucontrol->count = params->max;
7707077148fSMark Brown 
7717077148fSMark Brown 	return 0;
7727077148fSMark Brown }
7737077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_bytes_info_ext);
7747077148fSMark Brown 
7757077148fSMark Brown int snd_soc_bytes_tlv_callback(struct snd_kcontrol *kcontrol, int op_flag,
7767077148fSMark Brown 				unsigned int size, unsigned int __user *tlv)
7777077148fSMark Brown {
7787077148fSMark Brown 	struct soc_bytes_ext *params = (void *)kcontrol->private_value;
7797077148fSMark Brown 	unsigned int count = size < params->max ? size : params->max;
7807077148fSMark Brown 	int ret = -ENXIO;
7817077148fSMark Brown 
7827077148fSMark Brown 	switch (op_flag) {
7837077148fSMark Brown 	case SNDRV_CTL_TLV_OP_READ:
7847077148fSMark Brown 		if (params->get)
785a1e5e7e9SMythri P K 			ret = params->get(kcontrol, tlv, count);
7867077148fSMark Brown 		break;
7877077148fSMark Brown 	case SNDRV_CTL_TLV_OP_WRITE:
7887077148fSMark Brown 		if (params->put)
789a1e5e7e9SMythri P K 			ret = params->put(kcontrol, tlv, count);
7907077148fSMark Brown 		break;
7917077148fSMark Brown 	}
7927077148fSMark Brown 	return ret;
7937077148fSMark Brown }
7947077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_bytes_tlv_callback);
7957077148fSMark Brown 
7967077148fSMark Brown /**
7977077148fSMark Brown  * snd_soc_info_xr_sx - signed multi register info callback
7987077148fSMark Brown  * @kcontrol: mreg control
7997077148fSMark Brown  * @uinfo: control element information
8007077148fSMark Brown  *
8017077148fSMark Brown  * Callback to provide information of a control that can
8027077148fSMark Brown  * span multiple codec registers which together
8037077148fSMark Brown  * forms a single signed value in a MSB/LSB manner.
8047077148fSMark Brown  *
8057077148fSMark Brown  * Returns 0 for success.
8067077148fSMark Brown  */
8077077148fSMark Brown int snd_soc_info_xr_sx(struct snd_kcontrol *kcontrol,
8087077148fSMark Brown 	struct snd_ctl_elem_info *uinfo)
8097077148fSMark Brown {
8107077148fSMark Brown 	struct soc_mreg_control *mc =
8117077148fSMark Brown 		(struct soc_mreg_control *)kcontrol->private_value;
8127077148fSMark Brown 	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
8137077148fSMark Brown 	uinfo->count = 1;
8147077148fSMark Brown 	uinfo->value.integer.min = mc->min;
8157077148fSMark Brown 	uinfo->value.integer.max = mc->max;
8167077148fSMark Brown 
8177077148fSMark Brown 	return 0;
8187077148fSMark Brown }
8197077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_info_xr_sx);
8207077148fSMark Brown 
8217077148fSMark Brown /**
8227077148fSMark Brown  * snd_soc_get_xr_sx - signed multi register get callback
8237077148fSMark Brown  * @kcontrol: mreg control
8247077148fSMark Brown  * @ucontrol: control element information
8257077148fSMark Brown  *
8267077148fSMark Brown  * Callback to get the value of a control that can span
8277077148fSMark Brown  * multiple codec registers which together forms a single
8287077148fSMark Brown  * signed value in a MSB/LSB manner. The control supports
8297077148fSMark Brown  * specifying total no of bits used to allow for bitfields
8307077148fSMark Brown  * across the multiple codec registers.
8317077148fSMark Brown  *
8327077148fSMark Brown  * Returns 0 for success.
8337077148fSMark Brown  */
8347077148fSMark Brown int snd_soc_get_xr_sx(struct snd_kcontrol *kcontrol,
8357077148fSMark Brown 	struct snd_ctl_elem_value *ucontrol)
8367077148fSMark Brown {
8377077148fSMark Brown 	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
8387077148fSMark Brown 	struct soc_mreg_control *mc =
8397077148fSMark Brown 		(struct soc_mreg_control *)kcontrol->private_value;
8407077148fSMark Brown 	unsigned int regbase = mc->regbase;
8417077148fSMark Brown 	unsigned int regcount = mc->regcount;
8427077148fSMark Brown 	unsigned int regwshift = component->val_bytes * BITS_PER_BYTE;
8430ab07091S이경택 	unsigned int regwmask = (1UL<<regwshift)-1;
8447077148fSMark Brown 	unsigned int invert = mc->invert;
8457077148fSMark Brown 	unsigned long mask = (1UL<<mc->nbits)-1;
8467077148fSMark Brown 	long min = mc->min;
8477077148fSMark Brown 	long max = mc->max;
8487077148fSMark Brown 	long val = 0;
8497077148fSMark Brown 	unsigned int i;
8507077148fSMark Brown 
8517077148fSMark Brown 	for (i = 0; i < regcount; i++) {
852b1ebecb9SKuninori Morimoto 		unsigned int regval = snd_soc_component_read(component, regbase+i);
8537077148fSMark Brown 		val |= (regval & regwmask) << (regwshift*(regcount-i-1));
8547077148fSMark Brown 	}
8557077148fSMark Brown 	val &= mask;
8567077148fSMark Brown 	if (min < 0 && val > max)
8577077148fSMark Brown 		val |= ~mask;
8587077148fSMark Brown 	if (invert)
8597077148fSMark Brown 		val = max - val;
8607077148fSMark Brown 	ucontrol->value.integer.value[0] = val;
8617077148fSMark Brown 
8627077148fSMark Brown 	return 0;
8637077148fSMark Brown }
8647077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_get_xr_sx);
8657077148fSMark Brown 
8667077148fSMark Brown /**
8677077148fSMark Brown  * snd_soc_put_xr_sx - signed multi register get callback
8687077148fSMark Brown  * @kcontrol: mreg control
8697077148fSMark Brown  * @ucontrol: control element information
8707077148fSMark Brown  *
8717077148fSMark Brown  * Callback to set the value of a control that can span
8727077148fSMark Brown  * multiple codec registers which together forms a single
8737077148fSMark Brown  * signed value in a MSB/LSB manner. The control supports
8747077148fSMark Brown  * specifying total no of bits used to allow for bitfields
8757077148fSMark Brown  * across the multiple codec registers.
8767077148fSMark Brown  *
8777077148fSMark Brown  * Returns 0 for success.
8787077148fSMark Brown  */
8797077148fSMark Brown int snd_soc_put_xr_sx(struct snd_kcontrol *kcontrol,
8807077148fSMark Brown 	struct snd_ctl_elem_value *ucontrol)
8817077148fSMark Brown {
8827077148fSMark Brown 	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
8837077148fSMark Brown 	struct soc_mreg_control *mc =
8847077148fSMark Brown 		(struct soc_mreg_control *)kcontrol->private_value;
8857077148fSMark Brown 	unsigned int regbase = mc->regbase;
8867077148fSMark Brown 	unsigned int regcount = mc->regcount;
8877077148fSMark Brown 	unsigned int regwshift = component->val_bytes * BITS_PER_BYTE;
8880ab07091S이경택 	unsigned int regwmask = (1UL<<regwshift)-1;
8897077148fSMark Brown 	unsigned int invert = mc->invert;
8907077148fSMark Brown 	unsigned long mask = (1UL<<mc->nbits)-1;
8917077148fSMark Brown 	long max = mc->max;
8927077148fSMark Brown 	long val = ucontrol->value.integer.value[0];
893b285b510SKuninori Morimoto 	unsigned int i;
8947077148fSMark Brown 
8954cf28e9aSMark Brown 	if (val < mc->min || val > mc->max)
8964cf28e9aSMark Brown 		return -EINVAL;
8977077148fSMark Brown 	if (invert)
8987077148fSMark Brown 		val = max - val;
8997077148fSMark Brown 	val &= mask;
9007077148fSMark Brown 	for (i = 0; i < regcount; i++) {
901b285b510SKuninori Morimoto 		unsigned int regval = (val >> (regwshift*(regcount-i-1))) & regwmask;
902b285b510SKuninori Morimoto 		unsigned int regmask = (mask >> (regwshift*(regcount-i-1))) & regwmask;
903b285b510SKuninori Morimoto 		int err = snd_soc_component_update_bits(component, regbase+i,
9047077148fSMark Brown 							regmask, regval);
9057077148fSMark Brown 		if (err < 0)
9067077148fSMark Brown 			return err;
9077077148fSMark Brown 	}
9087077148fSMark Brown 
9097077148fSMark Brown 	return 0;
9107077148fSMark Brown }
9117077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_put_xr_sx);
9127077148fSMark Brown 
9137077148fSMark Brown /**
9147077148fSMark Brown  * snd_soc_get_strobe - strobe get callback
9157077148fSMark Brown  * @kcontrol: mixer control
9167077148fSMark Brown  * @ucontrol: control element information
9177077148fSMark Brown  *
9187077148fSMark Brown  * Callback get the value of a strobe mixer control.
9197077148fSMark Brown  *
9207077148fSMark Brown  * Returns 0 for success.
9217077148fSMark Brown  */
9227077148fSMark Brown int snd_soc_get_strobe(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_mixer_control *mc =
9277077148fSMark Brown 		(struct soc_mixer_control *)kcontrol->private_value;
9287077148fSMark Brown 	unsigned int reg = mc->reg;
9297077148fSMark Brown 	unsigned int shift = mc->shift;
9307077148fSMark Brown 	unsigned int mask = 1 << shift;
9317077148fSMark Brown 	unsigned int invert = mc->invert != 0;
9327077148fSMark Brown 	unsigned int val;
9337077148fSMark Brown 
934cf6e26c7SKuninori Morimoto 	val = snd_soc_component_read(component, reg);
9357077148fSMark Brown 	val &= mask;
9367077148fSMark Brown 
9377077148fSMark Brown 	if (shift != 0 && val != 0)
9387077148fSMark Brown 		val = val >> shift;
9397077148fSMark Brown 	ucontrol->value.enumerated.item[0] = val ^ invert;
9407077148fSMark Brown 
9417077148fSMark Brown 	return 0;
9427077148fSMark Brown }
9437077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_get_strobe);
9447077148fSMark Brown 
9457077148fSMark Brown /**
9467077148fSMark Brown  * snd_soc_put_strobe - strobe put callback
9477077148fSMark Brown  * @kcontrol: mixer control
9487077148fSMark Brown  * @ucontrol: control element information
9497077148fSMark Brown  *
9507077148fSMark Brown  * Callback strobe a register bit to high then low (or the inverse)
9517077148fSMark Brown  * in one pass of a single mixer enum control.
9527077148fSMark Brown  *
9537077148fSMark Brown  * Returns 1 for success.
9547077148fSMark Brown  */
9557077148fSMark Brown int snd_soc_put_strobe(struct snd_kcontrol *kcontrol,
9567077148fSMark Brown 	struct snd_ctl_elem_value *ucontrol)
9577077148fSMark Brown {
9587077148fSMark Brown 	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
9597077148fSMark Brown 	struct soc_mixer_control *mc =
9607077148fSMark Brown 		(struct soc_mixer_control *)kcontrol->private_value;
9617077148fSMark Brown 	unsigned int reg = mc->reg;
9627077148fSMark Brown 	unsigned int shift = mc->shift;
9637077148fSMark Brown 	unsigned int mask = 1 << shift;
9647077148fSMark Brown 	unsigned int invert = mc->invert != 0;
9657077148fSMark Brown 	unsigned int strobe = ucontrol->value.enumerated.item[0] != 0;
9667077148fSMark Brown 	unsigned int val1 = (strobe ^ invert) ? mask : 0;
9677077148fSMark Brown 	unsigned int val2 = (strobe ^ invert) ? 0 : mask;
9687077148fSMark Brown 	int err;
9697077148fSMark Brown 
9707077148fSMark Brown 	err = snd_soc_component_update_bits(component, reg, mask, val1);
9717077148fSMark Brown 	if (err < 0)
9727077148fSMark Brown 		return err;
9737077148fSMark Brown 
9747077148fSMark Brown 	return snd_soc_component_update_bits(component, reg, mask, val2);
9757077148fSMark Brown }
9767077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_put_strobe);
977