xref: /openbmc/linux/sound/soc/soc-ops.c (revision 26d9ca34)
17077148fSMark Brown /*
27077148fSMark Brown  * soc-ops.c  --  Generic ASoC operations
37077148fSMark Brown  *
47077148fSMark Brown  * Copyright 2005 Wolfson Microelectronics PLC.
57077148fSMark Brown  * Copyright 2005 Openedhand Ltd.
67077148fSMark Brown  * Copyright (C) 2010 Slimlogic Ltd.
77077148fSMark Brown  * Copyright (C) 2010 Texas Instruments Inc.
87077148fSMark Brown  *
97077148fSMark Brown  * Author: Liam Girdwood <lrg@slimlogic.co.uk>
107077148fSMark Brown  *         with code, comments and ideas from :-
117077148fSMark Brown  *         Richard Purdie <richard@openedhand.com>
127077148fSMark Brown  *
137077148fSMark Brown  *  This program is free software; you can redistribute  it and/or modify it
147077148fSMark Brown  *  under  the terms of  the GNU General  Public License as published by the
157077148fSMark Brown  *  Free Software Foundation;  either version 2 of the  License, or (at your
167077148fSMark Brown  *  option) any later version.
177077148fSMark Brown  */
187077148fSMark Brown 
197077148fSMark Brown #include <linux/module.h>
207077148fSMark Brown #include <linux/moduleparam.h>
217077148fSMark Brown #include <linux/init.h>
227077148fSMark Brown #include <linux/delay.h>
237077148fSMark Brown #include <linux/pm.h>
247077148fSMark Brown #include <linux/bitops.h>
257077148fSMark Brown #include <linux/ctype.h>
267077148fSMark Brown #include <linux/slab.h>
277077148fSMark Brown #include <sound/core.h>
287077148fSMark Brown #include <sound/jack.h>
297077148fSMark Brown #include <sound/pcm.h>
307077148fSMark Brown #include <sound/pcm_params.h>
317077148fSMark Brown #include <sound/soc.h>
327077148fSMark Brown #include <sound/soc-dpcm.h>
337077148fSMark Brown #include <sound/initval.h>
347077148fSMark Brown 
357077148fSMark Brown /**
367077148fSMark Brown  * snd_soc_info_enum_double - enumerated double mixer info callback
377077148fSMark Brown  * @kcontrol: mixer control
387077148fSMark Brown  * @uinfo: control element information
397077148fSMark Brown  *
407077148fSMark Brown  * Callback to provide information about a double enumerated
417077148fSMark Brown  * mixer control.
427077148fSMark Brown  *
437077148fSMark Brown  * Returns 0 for success.
447077148fSMark Brown  */
457077148fSMark Brown int snd_soc_info_enum_double(struct snd_kcontrol *kcontrol,
467077148fSMark Brown 	struct snd_ctl_elem_info *uinfo)
477077148fSMark Brown {
487077148fSMark Brown 	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
497077148fSMark Brown 
507077148fSMark Brown 	return snd_ctl_enum_info(uinfo, e->shift_l == e->shift_r ? 1 : 2,
517077148fSMark Brown 				 e->items, e->texts);
527077148fSMark Brown }
537077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_info_enum_double);
547077148fSMark Brown 
557077148fSMark Brown /**
567077148fSMark Brown  * snd_soc_get_enum_double - enumerated double mixer get callback
577077148fSMark Brown  * @kcontrol: mixer control
587077148fSMark Brown  * @ucontrol: control element information
597077148fSMark Brown  *
607077148fSMark Brown  * Callback to get the value of a double enumerated mixer.
617077148fSMark Brown  *
627077148fSMark Brown  * Returns 0 for success.
637077148fSMark Brown  */
647077148fSMark Brown int snd_soc_get_enum_double(struct snd_kcontrol *kcontrol,
657077148fSMark Brown 	struct snd_ctl_elem_value *ucontrol)
667077148fSMark Brown {
677077148fSMark Brown 	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
687077148fSMark Brown 	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
697077148fSMark Brown 	unsigned int val, item;
707077148fSMark Brown 	unsigned int reg_val;
717077148fSMark Brown 	int ret;
727077148fSMark Brown 
737077148fSMark Brown 	ret = snd_soc_component_read(component, e->reg, &reg_val);
747077148fSMark Brown 	if (ret)
757077148fSMark Brown 		return ret;
767077148fSMark Brown 	val = (reg_val >> e->shift_l) & e->mask;
777077148fSMark Brown 	item = snd_soc_enum_val_to_item(e, val);
787077148fSMark Brown 	ucontrol->value.enumerated.item[0] = item;
797077148fSMark Brown 	if (e->shift_l != e->shift_r) {
807077148fSMark Brown 		val = (reg_val >> e->shift_l) & e->mask;
817077148fSMark Brown 		item = snd_soc_enum_val_to_item(e, val);
827077148fSMark Brown 		ucontrol->value.enumerated.item[1] = item;
837077148fSMark Brown 	}
847077148fSMark Brown 
857077148fSMark Brown 	return 0;
867077148fSMark Brown }
877077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_get_enum_double);
887077148fSMark Brown 
897077148fSMark Brown /**
907077148fSMark Brown  * snd_soc_put_enum_double - enumerated double mixer put callback
917077148fSMark Brown  * @kcontrol: mixer control
927077148fSMark Brown  * @ucontrol: control element information
937077148fSMark Brown  *
947077148fSMark Brown  * Callback to set the value of a double enumerated mixer.
957077148fSMark Brown  *
967077148fSMark Brown  * Returns 0 for success.
977077148fSMark Brown  */
987077148fSMark Brown int snd_soc_put_enum_double(struct snd_kcontrol *kcontrol,
997077148fSMark Brown 	struct snd_ctl_elem_value *ucontrol)
1007077148fSMark Brown {
1017077148fSMark Brown 	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
1027077148fSMark Brown 	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
1037077148fSMark Brown 	unsigned int *item = ucontrol->value.enumerated.item;
1047077148fSMark Brown 	unsigned int val;
1057077148fSMark Brown 	unsigned int mask;
1067077148fSMark Brown 
1077077148fSMark Brown 	if (item[0] >= e->items)
1087077148fSMark Brown 		return -EINVAL;
1097077148fSMark Brown 	val = snd_soc_enum_item_to_val(e, item[0]) << e->shift_l;
1107077148fSMark Brown 	mask = e->mask << e->shift_l;
1117077148fSMark Brown 	if (e->shift_l != e->shift_r) {
1127077148fSMark Brown 		if (item[1] >= e->items)
1137077148fSMark Brown 			return -EINVAL;
1147077148fSMark Brown 		val |= snd_soc_enum_item_to_val(e, item[1]) << e->shift_r;
1157077148fSMark Brown 		mask |= e->mask << e->shift_r;
1167077148fSMark Brown 	}
1177077148fSMark Brown 
1187077148fSMark Brown 	return snd_soc_component_update_bits(component, e->reg, mask, val);
1197077148fSMark Brown }
1207077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_put_enum_double);
1217077148fSMark Brown 
1227077148fSMark Brown /**
1237077148fSMark Brown  * snd_soc_read_signed - Read a codec register and interprete as signed value
1247077148fSMark Brown  * @component: component
1257077148fSMark Brown  * @reg: Register to read
1267077148fSMark Brown  * @mask: Mask to use after shifting the register value
1277077148fSMark Brown  * @shift: Right shift of register value
1287077148fSMark Brown  * @sign_bit: Bit that describes if a number is negative or not.
1297077148fSMark Brown  * @signed_val: Pointer to where the read value should be stored
1307077148fSMark Brown  *
1317077148fSMark Brown  * This functions reads a codec register. The register value is shifted right
1327077148fSMark Brown  * by 'shift' bits and masked with the given 'mask'. Afterwards it translates
1337077148fSMark Brown  * the given registervalue into a signed integer if sign_bit is non-zero.
1347077148fSMark Brown  *
1357077148fSMark Brown  * Returns 0 on sucess, otherwise an error value
1367077148fSMark Brown  */
1377077148fSMark Brown static int snd_soc_read_signed(struct snd_soc_component *component,
1387077148fSMark Brown 	unsigned int reg, unsigned int mask, unsigned int shift,
1397077148fSMark Brown 	unsigned int sign_bit, int *signed_val)
1407077148fSMark Brown {
1417077148fSMark Brown 	int ret;
1427077148fSMark Brown 	unsigned int val;
1437077148fSMark Brown 
1447077148fSMark Brown 	ret = snd_soc_component_read(component, reg, &val);
1457077148fSMark Brown 	if (ret < 0)
1467077148fSMark Brown 		return ret;
1477077148fSMark Brown 
1487077148fSMark Brown 	val = (val >> shift) & mask;
1497077148fSMark Brown 
1507077148fSMark Brown 	if (!sign_bit) {
1517077148fSMark Brown 		*signed_val = val;
1527077148fSMark Brown 		return 0;
1537077148fSMark Brown 	}
1547077148fSMark Brown 
1557077148fSMark Brown 	/* non-negative number */
1567077148fSMark Brown 	if (!(val & BIT(sign_bit))) {
1577077148fSMark Brown 		*signed_val = val;
1587077148fSMark Brown 		return 0;
1597077148fSMark Brown 	}
1607077148fSMark Brown 
1617077148fSMark Brown 	ret = val;
1627077148fSMark Brown 
1637077148fSMark Brown 	/*
1647077148fSMark Brown 	 * The register most probably does not contain a full-sized int.
1657077148fSMark Brown 	 * Instead we have an arbitrary number of bits in a signed
1667077148fSMark Brown 	 * representation which has to be translated into a full-sized int.
1677077148fSMark Brown 	 * This is done by filling up all bits above the sign-bit.
1687077148fSMark Brown 	 */
1697077148fSMark Brown 	ret |= ~((int)(BIT(sign_bit) - 1));
1707077148fSMark Brown 
1717077148fSMark Brown 	*signed_val = ret;
1727077148fSMark Brown 
1737077148fSMark Brown 	return 0;
1747077148fSMark Brown }
1757077148fSMark Brown 
1767077148fSMark Brown /**
1777077148fSMark Brown  * snd_soc_info_volsw - single mixer info callback
1787077148fSMark Brown  * @kcontrol: mixer control
1797077148fSMark Brown  * @uinfo: control element information
1807077148fSMark Brown  *
1817077148fSMark Brown  * Callback to provide information about a single mixer control, or a double
1827077148fSMark Brown  * mixer control that spans 2 registers.
1837077148fSMark Brown  *
1847077148fSMark Brown  * Returns 0 for success.
1857077148fSMark Brown  */
1867077148fSMark Brown int snd_soc_info_volsw(struct snd_kcontrol *kcontrol,
1877077148fSMark Brown 	struct snd_ctl_elem_info *uinfo)
1887077148fSMark Brown {
1897077148fSMark Brown 	struct soc_mixer_control *mc =
1907077148fSMark Brown 		(struct soc_mixer_control *)kcontrol->private_value;
1917077148fSMark Brown 	int platform_max;
1927077148fSMark Brown 
1937077148fSMark Brown 	if (!mc->platform_max)
1947077148fSMark Brown 		mc->platform_max = mc->max;
1957077148fSMark Brown 	platform_max = mc->platform_max;
1967077148fSMark Brown 
1977077148fSMark Brown 	if (platform_max == 1 && !strstr(kcontrol->id.name, " Volume"))
1987077148fSMark Brown 		uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
1997077148fSMark Brown 	else
2007077148fSMark Brown 		uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
2017077148fSMark Brown 
2027077148fSMark Brown 	uinfo->count = snd_soc_volsw_is_stereo(mc) ? 2 : 1;
2037077148fSMark Brown 	uinfo->value.integer.min = 0;
2047077148fSMark Brown 	uinfo->value.integer.max = platform_max - mc->min;
2057077148fSMark Brown 	return 0;
2067077148fSMark Brown }
2077077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_info_volsw);
2087077148fSMark Brown 
2097077148fSMark Brown /**
2107077148fSMark Brown  * snd_soc_get_volsw - single mixer get callback
2117077148fSMark Brown  * @kcontrol: mixer control
2127077148fSMark Brown  * @ucontrol: control element information
2137077148fSMark Brown  *
2147077148fSMark Brown  * Callback to get the value of a single mixer control, or a double mixer
2157077148fSMark Brown  * control that spans 2 registers.
2167077148fSMark Brown  *
2177077148fSMark Brown  * Returns 0 for success.
2187077148fSMark Brown  */
2197077148fSMark Brown int snd_soc_get_volsw(struct snd_kcontrol *kcontrol,
2207077148fSMark Brown 	struct snd_ctl_elem_value *ucontrol)
2217077148fSMark Brown {
2227077148fSMark Brown 	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
2237077148fSMark Brown 	struct soc_mixer_control *mc =
2247077148fSMark Brown 		(struct soc_mixer_control *)kcontrol->private_value;
2257077148fSMark Brown 	unsigned int reg = mc->reg;
2267077148fSMark Brown 	unsigned int reg2 = mc->rreg;
2277077148fSMark Brown 	unsigned int shift = mc->shift;
2287077148fSMark Brown 	unsigned int rshift = mc->rshift;
2297077148fSMark Brown 	int max = mc->max;
2307077148fSMark Brown 	int min = mc->min;
2317077148fSMark Brown 	int sign_bit = mc->sign_bit;
2327077148fSMark Brown 	unsigned int mask = (1 << fls(max)) - 1;
2337077148fSMark Brown 	unsigned int invert = mc->invert;
2347077148fSMark Brown 	int val;
2357077148fSMark Brown 	int ret;
2367077148fSMark Brown 
2377077148fSMark Brown 	if (sign_bit)
2387077148fSMark Brown 		mask = BIT(sign_bit + 1) - 1;
2397077148fSMark Brown 
2407077148fSMark Brown 	ret = snd_soc_read_signed(component, reg, mask, shift, sign_bit, &val);
2417077148fSMark Brown 	if (ret)
2427077148fSMark Brown 		return ret;
2437077148fSMark Brown 
2447077148fSMark Brown 	ucontrol->value.integer.value[0] = val - min;
2457077148fSMark Brown 	if (invert)
2467077148fSMark Brown 		ucontrol->value.integer.value[0] =
2477077148fSMark Brown 			max - ucontrol->value.integer.value[0];
2487077148fSMark Brown 
2497077148fSMark Brown 	if (snd_soc_volsw_is_stereo(mc)) {
2507077148fSMark Brown 		if (reg == reg2)
2517077148fSMark Brown 			ret = snd_soc_read_signed(component, reg, mask, rshift,
2527077148fSMark Brown 				sign_bit, &val);
2537077148fSMark Brown 		else
2547077148fSMark Brown 			ret = snd_soc_read_signed(component, reg2, mask, shift,
2557077148fSMark Brown 				sign_bit, &val);
2567077148fSMark Brown 		if (ret)
2577077148fSMark Brown 			return ret;
2587077148fSMark Brown 
2597077148fSMark Brown 		ucontrol->value.integer.value[1] = val - min;
2607077148fSMark Brown 		if (invert)
2617077148fSMark Brown 			ucontrol->value.integer.value[1] =
2627077148fSMark Brown 				max - ucontrol->value.integer.value[1];
2637077148fSMark Brown 	}
2647077148fSMark Brown 
2657077148fSMark Brown 	return 0;
2667077148fSMark Brown }
2677077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_get_volsw);
2687077148fSMark Brown 
2697077148fSMark Brown /**
2707077148fSMark Brown  * snd_soc_put_volsw - single mixer put callback
2717077148fSMark Brown  * @kcontrol: mixer control
2727077148fSMark Brown  * @ucontrol: control element information
2737077148fSMark Brown  *
2747077148fSMark Brown  * Callback to set the value of a single mixer control, or a double mixer
2757077148fSMark Brown  * control that spans 2 registers.
2767077148fSMark Brown  *
2777077148fSMark Brown  * Returns 0 for success.
2787077148fSMark Brown  */
2797077148fSMark Brown int snd_soc_put_volsw(struct snd_kcontrol *kcontrol,
2807077148fSMark Brown 	struct snd_ctl_elem_value *ucontrol)
2817077148fSMark Brown {
2827077148fSMark Brown 	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
2837077148fSMark Brown 	struct soc_mixer_control *mc =
2847077148fSMark Brown 		(struct soc_mixer_control *)kcontrol->private_value;
2857077148fSMark Brown 	unsigned int reg = mc->reg;
2867077148fSMark Brown 	unsigned int reg2 = mc->rreg;
2877077148fSMark Brown 	unsigned int shift = mc->shift;
2887077148fSMark Brown 	unsigned int rshift = mc->rshift;
2897077148fSMark Brown 	int max = mc->max;
2907077148fSMark Brown 	int min = mc->min;
2917077148fSMark Brown 	unsigned int sign_bit = mc->sign_bit;
2927077148fSMark Brown 	unsigned int mask = (1 << fls(max)) - 1;
2937077148fSMark Brown 	unsigned int invert = mc->invert;
2947077148fSMark Brown 	int err;
2957077148fSMark Brown 	bool type_2r = false;
2967077148fSMark Brown 	unsigned int val2 = 0;
2977077148fSMark Brown 	unsigned int val, val_mask;
2987077148fSMark Brown 
2997077148fSMark Brown 	if (sign_bit)
3007077148fSMark Brown 		mask = BIT(sign_bit + 1) - 1;
3017077148fSMark Brown 
3027077148fSMark Brown 	val = ((ucontrol->value.integer.value[0] + min) & mask);
3037077148fSMark Brown 	if (invert)
3047077148fSMark Brown 		val = max - val;
3057077148fSMark Brown 	val_mask = mask << shift;
3067077148fSMark Brown 	val = val << shift;
3077077148fSMark Brown 	if (snd_soc_volsw_is_stereo(mc)) {
3087077148fSMark Brown 		val2 = ((ucontrol->value.integer.value[1] + min) & mask);
3097077148fSMark Brown 		if (invert)
3107077148fSMark Brown 			val2 = max - val2;
3117077148fSMark Brown 		if (reg == reg2) {
3127077148fSMark Brown 			val_mask |= mask << rshift;
3137077148fSMark Brown 			val |= val2 << rshift;
3147077148fSMark Brown 		} else {
3157077148fSMark Brown 			val2 = val2 << shift;
3167077148fSMark Brown 			type_2r = true;
3177077148fSMark Brown 		}
3187077148fSMark Brown 	}
3197077148fSMark Brown 	err = snd_soc_component_update_bits(component, reg, val_mask, val);
3207077148fSMark Brown 	if (err < 0)
3217077148fSMark Brown 		return err;
3227077148fSMark Brown 
3237077148fSMark Brown 	if (type_2r)
3247077148fSMark Brown 		err = snd_soc_component_update_bits(component, reg2, val_mask,
3257077148fSMark Brown 			val2);
3267077148fSMark Brown 
3277077148fSMark Brown 	return err;
3287077148fSMark Brown }
3297077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_put_volsw);
3307077148fSMark Brown 
3317077148fSMark Brown /**
3327077148fSMark Brown  * snd_soc_get_volsw_sx - single mixer get callback
3337077148fSMark Brown  * @kcontrol: mixer control
3347077148fSMark Brown  * @ucontrol: control element information
3357077148fSMark Brown  *
3367077148fSMark Brown  * Callback to get the value of a single mixer control, or a double mixer
3377077148fSMark Brown  * control that spans 2 registers.
3387077148fSMark Brown  *
3397077148fSMark Brown  * Returns 0 for success.
3407077148fSMark Brown  */
3417077148fSMark Brown int snd_soc_get_volsw_sx(struct snd_kcontrol *kcontrol,
3427077148fSMark Brown 		      struct snd_ctl_elem_value *ucontrol)
3437077148fSMark Brown {
3447077148fSMark Brown 	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
3457077148fSMark Brown 	struct soc_mixer_control *mc =
3467077148fSMark Brown 	    (struct soc_mixer_control *)kcontrol->private_value;
3477077148fSMark Brown 	unsigned int reg = mc->reg;
3487077148fSMark Brown 	unsigned int reg2 = mc->rreg;
3497077148fSMark Brown 	unsigned int shift = mc->shift;
3507077148fSMark Brown 	unsigned int rshift = mc->rshift;
3517077148fSMark Brown 	int max = mc->max;
3527077148fSMark Brown 	int min = mc->min;
3537077148fSMark Brown 	int mask = (1 << (fls(min + max) - 1)) - 1;
3547077148fSMark Brown 	unsigned int val;
3557077148fSMark Brown 	int ret;
3567077148fSMark Brown 
3577077148fSMark Brown 	ret = snd_soc_component_read(component, reg, &val);
3587077148fSMark Brown 	if (ret < 0)
3597077148fSMark Brown 		return ret;
3607077148fSMark Brown 
3617077148fSMark Brown 	ucontrol->value.integer.value[0] = ((val >> shift) - min) & mask;
3627077148fSMark Brown 
3637077148fSMark Brown 	if (snd_soc_volsw_is_stereo(mc)) {
3647077148fSMark Brown 		ret = snd_soc_component_read(component, reg2, &val);
3657077148fSMark Brown 		if (ret < 0)
3667077148fSMark Brown 			return ret;
3677077148fSMark Brown 
3687077148fSMark Brown 		val = ((val >> rshift) - min) & mask;
3697077148fSMark Brown 		ucontrol->value.integer.value[1] = val;
3707077148fSMark Brown 	}
3717077148fSMark Brown 
3727077148fSMark Brown 	return 0;
3737077148fSMark Brown }
3747077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_get_volsw_sx);
3757077148fSMark Brown 
3767077148fSMark Brown /**
3777077148fSMark Brown  * snd_soc_put_volsw_sx - double mixer set callback
3787077148fSMark Brown  * @kcontrol: mixer control
3797077148fSMark Brown  * @uinfo: control element information
3807077148fSMark Brown  *
3817077148fSMark Brown  * Callback to set the value of a double mixer control that spans 2 registers.
3827077148fSMark Brown  *
3837077148fSMark Brown  * Returns 0 for success.
3847077148fSMark Brown  */
3857077148fSMark Brown int snd_soc_put_volsw_sx(struct snd_kcontrol *kcontrol,
3867077148fSMark Brown 			 struct snd_ctl_elem_value *ucontrol)
3877077148fSMark Brown {
3887077148fSMark Brown 	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
3897077148fSMark Brown 	struct soc_mixer_control *mc =
3907077148fSMark Brown 	    (struct soc_mixer_control *)kcontrol->private_value;
3917077148fSMark Brown 
3927077148fSMark Brown 	unsigned int reg = mc->reg;
3937077148fSMark Brown 	unsigned int reg2 = mc->rreg;
3947077148fSMark Brown 	unsigned int shift = mc->shift;
3957077148fSMark Brown 	unsigned int rshift = mc->rshift;
3967077148fSMark Brown 	int max = mc->max;
3977077148fSMark Brown 	int min = mc->min;
3987077148fSMark Brown 	int mask = (1 << (fls(min + max) - 1)) - 1;
3997077148fSMark Brown 	int err = 0;
4007077148fSMark Brown 	unsigned int val, val_mask, val2 = 0;
4017077148fSMark Brown 
4027077148fSMark Brown 	val_mask = mask << shift;
4037077148fSMark Brown 	val = (ucontrol->value.integer.value[0] + min) & mask;
4047077148fSMark Brown 	val = val << shift;
4057077148fSMark Brown 
4067077148fSMark Brown 	err = snd_soc_component_update_bits(component, reg, val_mask, val);
4077077148fSMark Brown 	if (err < 0)
4087077148fSMark Brown 		return err;
4097077148fSMark Brown 
4107077148fSMark Brown 	if (snd_soc_volsw_is_stereo(mc)) {
4117077148fSMark Brown 		val_mask = mask << rshift;
4127077148fSMark Brown 		val2 = (ucontrol->value.integer.value[1] + min) & mask;
4137077148fSMark Brown 		val2 = val2 << rshift;
4147077148fSMark Brown 
4157077148fSMark Brown 		err = snd_soc_component_update_bits(component, reg2, val_mask,
4167077148fSMark Brown 			val2);
4177077148fSMark Brown 	}
4187077148fSMark Brown 	return err;
4197077148fSMark Brown }
4207077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_put_volsw_sx);
4217077148fSMark Brown 
4227077148fSMark Brown /**
4237077148fSMark Brown  * snd_soc_info_volsw_range - single mixer info callback with range.
4247077148fSMark Brown  * @kcontrol: mixer control
4257077148fSMark Brown  * @uinfo: control element information
4267077148fSMark Brown  *
4277077148fSMark Brown  * Callback to provide information, within a range, about a single
4287077148fSMark Brown  * mixer control.
4297077148fSMark Brown  *
4307077148fSMark Brown  * returns 0 for success.
4317077148fSMark Brown  */
4327077148fSMark Brown int snd_soc_info_volsw_range(struct snd_kcontrol *kcontrol,
4337077148fSMark Brown 	struct snd_ctl_elem_info *uinfo)
4347077148fSMark Brown {
4357077148fSMark Brown 	struct soc_mixer_control *mc =
4367077148fSMark Brown 		(struct soc_mixer_control *)kcontrol->private_value;
4377077148fSMark Brown 	int platform_max;
4387077148fSMark Brown 	int min = mc->min;
4397077148fSMark Brown 
4407077148fSMark Brown 	if (!mc->platform_max)
4417077148fSMark Brown 		mc->platform_max = mc->max;
4427077148fSMark Brown 	platform_max = mc->platform_max;
4437077148fSMark Brown 
4447077148fSMark Brown 	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
4457077148fSMark Brown 	uinfo->count = snd_soc_volsw_is_stereo(mc) ? 2 : 1;
4467077148fSMark Brown 	uinfo->value.integer.min = 0;
4477077148fSMark Brown 	uinfo->value.integer.max = platform_max - min;
4487077148fSMark Brown 
4497077148fSMark Brown 	return 0;
4507077148fSMark Brown }
4517077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_info_volsw_range);
4527077148fSMark Brown 
4537077148fSMark Brown /**
4547077148fSMark Brown  * snd_soc_put_volsw_range - single mixer put value callback with range.
4557077148fSMark Brown  * @kcontrol: mixer control
4567077148fSMark Brown  * @ucontrol: control element information
4577077148fSMark Brown  *
4587077148fSMark Brown  * Callback to set the value, within a range, for a single mixer control.
4597077148fSMark Brown  *
4607077148fSMark Brown  * Returns 0 for success.
4617077148fSMark Brown  */
4627077148fSMark Brown int snd_soc_put_volsw_range(struct snd_kcontrol *kcontrol,
4637077148fSMark Brown 	struct snd_ctl_elem_value *ucontrol)
4647077148fSMark Brown {
4657077148fSMark Brown 	struct soc_mixer_control *mc =
4667077148fSMark Brown 		(struct soc_mixer_control *)kcontrol->private_value;
4677077148fSMark Brown 	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
4687077148fSMark Brown 	unsigned int reg = mc->reg;
4697077148fSMark Brown 	unsigned int rreg = mc->rreg;
4707077148fSMark Brown 	unsigned int shift = mc->shift;
4717077148fSMark Brown 	int min = mc->min;
4727077148fSMark Brown 	int max = mc->max;
4737077148fSMark Brown 	unsigned int mask = (1 << fls(max)) - 1;
4747077148fSMark Brown 	unsigned int invert = mc->invert;
4757077148fSMark Brown 	unsigned int val, val_mask;
4767077148fSMark Brown 	int ret;
4777077148fSMark Brown 
4787077148fSMark Brown 	if (invert)
4797077148fSMark Brown 		val = (max - ucontrol->value.integer.value[0]) & mask;
4807077148fSMark Brown 	else
4817077148fSMark Brown 		val = ((ucontrol->value.integer.value[0] + min) & mask);
4827077148fSMark Brown 	val_mask = mask << shift;
4837077148fSMark Brown 	val = val << shift;
4847077148fSMark Brown 
4857077148fSMark Brown 	ret = snd_soc_component_update_bits(component, reg, val_mask, val);
4867077148fSMark Brown 	if (ret < 0)
4877077148fSMark Brown 		return ret;
4887077148fSMark Brown 
4897077148fSMark Brown 	if (snd_soc_volsw_is_stereo(mc)) {
4907077148fSMark Brown 		if (invert)
4917077148fSMark Brown 			val = (max - ucontrol->value.integer.value[1]) & mask;
4927077148fSMark Brown 		else
4937077148fSMark Brown 			val = ((ucontrol->value.integer.value[1] + min) & mask);
4947077148fSMark Brown 		val_mask = mask << shift;
4957077148fSMark Brown 		val = val << shift;
4967077148fSMark Brown 
4977077148fSMark Brown 		ret = snd_soc_component_update_bits(component, rreg, val_mask,
4987077148fSMark Brown 			val);
4997077148fSMark Brown 	}
5007077148fSMark Brown 
5017077148fSMark Brown 	return ret;
5027077148fSMark Brown }
5037077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_put_volsw_range);
5047077148fSMark Brown 
5057077148fSMark Brown /**
5067077148fSMark Brown  * snd_soc_get_volsw_range - single mixer get callback with range
5077077148fSMark Brown  * @kcontrol: mixer control
5087077148fSMark Brown  * @ucontrol: control element information
5097077148fSMark Brown  *
5107077148fSMark Brown  * Callback to get the value, within a range, of a single mixer control.
5117077148fSMark Brown  *
5127077148fSMark Brown  * Returns 0 for success.
5137077148fSMark Brown  */
5147077148fSMark Brown int snd_soc_get_volsw_range(struct snd_kcontrol *kcontrol,
5157077148fSMark Brown 	struct snd_ctl_elem_value *ucontrol)
5167077148fSMark Brown {
5177077148fSMark Brown 	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
5187077148fSMark Brown 	struct soc_mixer_control *mc =
5197077148fSMark Brown 		(struct soc_mixer_control *)kcontrol->private_value;
5207077148fSMark Brown 	unsigned int reg = mc->reg;
5217077148fSMark Brown 	unsigned int rreg = mc->rreg;
5227077148fSMark Brown 	unsigned int shift = mc->shift;
5237077148fSMark Brown 	int min = mc->min;
5247077148fSMark Brown 	int max = mc->max;
5257077148fSMark Brown 	unsigned int mask = (1 << fls(max)) - 1;
5267077148fSMark Brown 	unsigned int invert = mc->invert;
5277077148fSMark Brown 	unsigned int val;
5287077148fSMark Brown 	int ret;
5297077148fSMark Brown 
5307077148fSMark Brown 	ret = snd_soc_component_read(component, reg, &val);
5317077148fSMark Brown 	if (ret)
5327077148fSMark Brown 		return ret;
5337077148fSMark Brown 
5347077148fSMark Brown 	ucontrol->value.integer.value[0] = (val >> shift) & mask;
5357077148fSMark Brown 	if (invert)
5367077148fSMark Brown 		ucontrol->value.integer.value[0] =
5377077148fSMark Brown 			max - ucontrol->value.integer.value[0];
5387077148fSMark Brown 	else
5397077148fSMark Brown 		ucontrol->value.integer.value[0] =
5407077148fSMark Brown 			ucontrol->value.integer.value[0] - min;
5417077148fSMark Brown 
5427077148fSMark Brown 	if (snd_soc_volsw_is_stereo(mc)) {
5437077148fSMark Brown 		ret = snd_soc_component_read(component, rreg, &val);
5447077148fSMark Brown 		if (ret)
5457077148fSMark Brown 			return ret;
5467077148fSMark Brown 
5477077148fSMark Brown 		ucontrol->value.integer.value[1] = (val >> shift) & mask;
5487077148fSMark Brown 		if (invert)
5497077148fSMark Brown 			ucontrol->value.integer.value[1] =
5507077148fSMark Brown 				max - ucontrol->value.integer.value[1];
5517077148fSMark Brown 		else
5527077148fSMark Brown 			ucontrol->value.integer.value[1] =
5537077148fSMark Brown 				ucontrol->value.integer.value[1] - min;
5547077148fSMark Brown 	}
5557077148fSMark Brown 
5567077148fSMark Brown 	return 0;
5577077148fSMark Brown }
5587077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_get_volsw_range);
5597077148fSMark Brown 
5607077148fSMark Brown /**
5617077148fSMark Brown  * snd_soc_limit_volume - Set new limit to an existing volume control.
5627077148fSMark Brown  *
56326d9ca34SLars-Peter Clausen  * @card: where to look for the control
5647077148fSMark Brown  * @name: Name of the control
5657077148fSMark Brown  * @max: new maximum limit
5667077148fSMark Brown  *
5677077148fSMark Brown  * Return 0 for success, else error.
5687077148fSMark Brown  */
56926d9ca34SLars-Peter Clausen int snd_soc_limit_volume(struct snd_soc_card *card,
5707077148fSMark Brown 	const char *name, int max)
5717077148fSMark Brown {
57226d9ca34SLars-Peter Clausen 	struct snd_card *snd_card = card->snd_card;
5737077148fSMark Brown 	struct snd_kcontrol *kctl;
5747077148fSMark Brown 	struct soc_mixer_control *mc;
5757077148fSMark Brown 	int found = 0;
5767077148fSMark Brown 	int ret = -EINVAL;
5777077148fSMark Brown 
5787077148fSMark Brown 	/* Sanity check for name and max */
5797077148fSMark Brown 	if (unlikely(!name || max <= 0))
5807077148fSMark Brown 		return -EINVAL;
5817077148fSMark Brown 
58226d9ca34SLars-Peter Clausen 	list_for_each_entry(kctl, &snd_card->controls, list) {
5837077148fSMark Brown 		if (!strncmp(kctl->id.name, name, sizeof(kctl->id.name))) {
5847077148fSMark Brown 			found = 1;
5857077148fSMark Brown 			break;
5867077148fSMark Brown 		}
5877077148fSMark Brown 	}
5887077148fSMark Brown 	if (found) {
5897077148fSMark Brown 		mc = (struct soc_mixer_control *)kctl->private_value;
5907077148fSMark Brown 		if (max <= mc->max) {
5917077148fSMark Brown 			mc->platform_max = max;
5927077148fSMark Brown 			ret = 0;
5937077148fSMark Brown 		}
5947077148fSMark Brown 	}
5957077148fSMark Brown 	return ret;
5967077148fSMark Brown }
5977077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_limit_volume);
5987077148fSMark Brown 
5997077148fSMark Brown int snd_soc_bytes_info(struct snd_kcontrol *kcontrol,
6007077148fSMark Brown 		       struct snd_ctl_elem_info *uinfo)
6017077148fSMark Brown {
6027077148fSMark Brown 	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
6037077148fSMark Brown 	struct soc_bytes *params = (void *)kcontrol->private_value;
6047077148fSMark Brown 
6057077148fSMark Brown 	uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
6067077148fSMark Brown 	uinfo->count = params->num_regs * component->val_bytes;
6077077148fSMark Brown 
6087077148fSMark Brown 	return 0;
6097077148fSMark Brown }
6107077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_bytes_info);
6117077148fSMark Brown 
6127077148fSMark Brown int snd_soc_bytes_get(struct snd_kcontrol *kcontrol,
6137077148fSMark Brown 		      struct snd_ctl_elem_value *ucontrol)
6147077148fSMark Brown {
6157077148fSMark Brown 	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
6167077148fSMark Brown 	struct soc_bytes *params = (void *)kcontrol->private_value;
6177077148fSMark Brown 	int ret;
6187077148fSMark Brown 
6197077148fSMark Brown 	if (component->regmap)
6207077148fSMark Brown 		ret = regmap_raw_read(component->regmap, params->base,
6217077148fSMark Brown 				      ucontrol->value.bytes.data,
6227077148fSMark Brown 				      params->num_regs * component->val_bytes);
6237077148fSMark Brown 	else
6247077148fSMark Brown 		ret = -EINVAL;
6257077148fSMark Brown 
6267077148fSMark Brown 	/* Hide any masked bytes to ensure consistent data reporting */
6277077148fSMark Brown 	if (ret == 0 && params->mask) {
6287077148fSMark Brown 		switch (component->val_bytes) {
6297077148fSMark Brown 		case 1:
6307077148fSMark Brown 			ucontrol->value.bytes.data[0] &= ~params->mask;
6317077148fSMark Brown 			break;
6327077148fSMark Brown 		case 2:
6337077148fSMark Brown 			((u16 *)(&ucontrol->value.bytes.data))[0]
6347077148fSMark Brown 				&= cpu_to_be16(~params->mask);
6357077148fSMark Brown 			break;
6367077148fSMark Brown 		case 4:
6377077148fSMark Brown 			((u32 *)(&ucontrol->value.bytes.data))[0]
6387077148fSMark Brown 				&= cpu_to_be32(~params->mask);
6397077148fSMark Brown 			break;
6407077148fSMark Brown 		default:
6417077148fSMark Brown 			return -EINVAL;
6427077148fSMark Brown 		}
6437077148fSMark Brown 	}
6447077148fSMark Brown 
6457077148fSMark Brown 	return ret;
6467077148fSMark Brown }
6477077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_bytes_get);
6487077148fSMark Brown 
6497077148fSMark Brown int snd_soc_bytes_put(struct snd_kcontrol *kcontrol,
6507077148fSMark Brown 		      struct snd_ctl_elem_value *ucontrol)
6517077148fSMark Brown {
6527077148fSMark Brown 	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
6537077148fSMark Brown 	struct soc_bytes *params = (void *)kcontrol->private_value;
6547077148fSMark Brown 	int ret, len;
6557077148fSMark Brown 	unsigned int val, mask;
6567077148fSMark Brown 	void *data;
6577077148fSMark Brown 
6587077148fSMark Brown 	if (!component->regmap || !params->num_regs)
6597077148fSMark Brown 		return -EINVAL;
6607077148fSMark Brown 
6617077148fSMark Brown 	len = params->num_regs * component->val_bytes;
6627077148fSMark Brown 
6637077148fSMark Brown 	data = kmemdup(ucontrol->value.bytes.data, len, GFP_KERNEL | GFP_DMA);
6647077148fSMark Brown 	if (!data)
6657077148fSMark Brown 		return -ENOMEM;
6667077148fSMark Brown 
6677077148fSMark Brown 	/*
6687077148fSMark Brown 	 * If we've got a mask then we need to preserve the register
6697077148fSMark Brown 	 * bits.  We shouldn't modify the incoming data so take a
6707077148fSMark Brown 	 * copy.
6717077148fSMark Brown 	 */
6727077148fSMark Brown 	if (params->mask) {
6737077148fSMark Brown 		ret = regmap_read(component->regmap, params->base, &val);
6747077148fSMark Brown 		if (ret != 0)
6757077148fSMark Brown 			goto out;
6767077148fSMark Brown 
6777077148fSMark Brown 		val &= params->mask;
6787077148fSMark Brown 
6797077148fSMark Brown 		switch (component->val_bytes) {
6807077148fSMark Brown 		case 1:
6817077148fSMark Brown 			((u8 *)data)[0] &= ~params->mask;
6827077148fSMark Brown 			((u8 *)data)[0] |= val;
6837077148fSMark Brown 			break;
6847077148fSMark Brown 		case 2:
6857077148fSMark Brown 			mask = ~params->mask;
6867077148fSMark Brown 			ret = regmap_parse_val(component->regmap,
6877077148fSMark Brown 							&mask, &mask);
6887077148fSMark Brown 			if (ret != 0)
6897077148fSMark Brown 				goto out;
6907077148fSMark Brown 
6917077148fSMark Brown 			((u16 *)data)[0] &= mask;
6927077148fSMark Brown 
6937077148fSMark Brown 			ret = regmap_parse_val(component->regmap,
6947077148fSMark Brown 							&val, &val);
6957077148fSMark Brown 			if (ret != 0)
6967077148fSMark Brown 				goto out;
6977077148fSMark Brown 
6987077148fSMark Brown 			((u16 *)data)[0] |= val;
6997077148fSMark Brown 			break;
7007077148fSMark Brown 		case 4:
7017077148fSMark Brown 			mask = ~params->mask;
7027077148fSMark Brown 			ret = regmap_parse_val(component->regmap,
7037077148fSMark Brown 							&mask, &mask);
7047077148fSMark Brown 			if (ret != 0)
7057077148fSMark Brown 				goto out;
7067077148fSMark Brown 
7077077148fSMark Brown 			((u32 *)data)[0] &= mask;
7087077148fSMark Brown 
7097077148fSMark Brown 			ret = regmap_parse_val(component->regmap,
7107077148fSMark Brown 							&val, &val);
7117077148fSMark Brown 			if (ret != 0)
7127077148fSMark Brown 				goto out;
7137077148fSMark Brown 
7147077148fSMark Brown 			((u32 *)data)[0] |= val;
7157077148fSMark Brown 			break;
7167077148fSMark Brown 		default:
7177077148fSMark Brown 			ret = -EINVAL;
7187077148fSMark Brown 			goto out;
7197077148fSMark Brown 		}
7207077148fSMark Brown 	}
7217077148fSMark Brown 
7227077148fSMark Brown 	ret = regmap_raw_write(component->regmap, params->base,
7237077148fSMark Brown 			       data, len);
7247077148fSMark Brown 
7257077148fSMark Brown out:
7267077148fSMark Brown 	kfree(data);
7277077148fSMark Brown 
7287077148fSMark Brown 	return ret;
7297077148fSMark Brown }
7307077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_bytes_put);
7317077148fSMark Brown 
7327077148fSMark Brown int snd_soc_bytes_info_ext(struct snd_kcontrol *kcontrol,
7337077148fSMark Brown 			struct snd_ctl_elem_info *ucontrol)
7347077148fSMark Brown {
7357077148fSMark Brown 	struct soc_bytes_ext *params = (void *)kcontrol->private_value;
7367077148fSMark Brown 
7377077148fSMark Brown 	ucontrol->type = SNDRV_CTL_ELEM_TYPE_BYTES;
7387077148fSMark Brown 	ucontrol->count = params->max;
7397077148fSMark Brown 
7407077148fSMark Brown 	return 0;
7417077148fSMark Brown }
7427077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_bytes_info_ext);
7437077148fSMark Brown 
7447077148fSMark Brown int snd_soc_bytes_tlv_callback(struct snd_kcontrol *kcontrol, int op_flag,
7457077148fSMark Brown 				unsigned int size, unsigned int __user *tlv)
7467077148fSMark Brown {
7477077148fSMark Brown 	struct soc_bytes_ext *params = (void *)kcontrol->private_value;
7487077148fSMark Brown 	unsigned int count = size < params->max ? size : params->max;
7497077148fSMark Brown 	int ret = -ENXIO;
7507077148fSMark Brown 
7517077148fSMark Brown 	switch (op_flag) {
7527077148fSMark Brown 	case SNDRV_CTL_TLV_OP_READ:
7537077148fSMark Brown 		if (params->get)
7547077148fSMark Brown 			ret = params->get(tlv, count);
7557077148fSMark Brown 		break;
7567077148fSMark Brown 	case SNDRV_CTL_TLV_OP_WRITE:
7577077148fSMark Brown 		if (params->put)
7587077148fSMark Brown 			ret = params->put(tlv, count);
7597077148fSMark Brown 		break;
7607077148fSMark Brown 	}
7617077148fSMark Brown 	return ret;
7627077148fSMark Brown }
7637077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_bytes_tlv_callback);
7647077148fSMark Brown 
7657077148fSMark Brown /**
7667077148fSMark Brown  * snd_soc_info_xr_sx - signed multi register info callback
7677077148fSMark Brown  * @kcontrol: mreg control
7687077148fSMark Brown  * @uinfo: control element information
7697077148fSMark Brown  *
7707077148fSMark Brown  * Callback to provide information of a control that can
7717077148fSMark Brown  * span multiple codec registers which together
7727077148fSMark Brown  * forms a single signed value in a MSB/LSB manner.
7737077148fSMark Brown  *
7747077148fSMark Brown  * Returns 0 for success.
7757077148fSMark Brown  */
7767077148fSMark Brown int snd_soc_info_xr_sx(struct snd_kcontrol *kcontrol,
7777077148fSMark Brown 	struct snd_ctl_elem_info *uinfo)
7787077148fSMark Brown {
7797077148fSMark Brown 	struct soc_mreg_control *mc =
7807077148fSMark Brown 		(struct soc_mreg_control *)kcontrol->private_value;
7817077148fSMark Brown 	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
7827077148fSMark Brown 	uinfo->count = 1;
7837077148fSMark Brown 	uinfo->value.integer.min = mc->min;
7847077148fSMark Brown 	uinfo->value.integer.max = mc->max;
7857077148fSMark Brown 
7867077148fSMark Brown 	return 0;
7877077148fSMark Brown }
7887077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_info_xr_sx);
7897077148fSMark Brown 
7907077148fSMark Brown /**
7917077148fSMark Brown  * snd_soc_get_xr_sx - signed multi register get callback
7927077148fSMark Brown  * @kcontrol: mreg control
7937077148fSMark Brown  * @ucontrol: control element information
7947077148fSMark Brown  *
7957077148fSMark Brown  * Callback to get the value of a control that can span
7967077148fSMark Brown  * multiple codec registers which together forms a single
7977077148fSMark Brown  * signed value in a MSB/LSB manner. The control supports
7987077148fSMark Brown  * specifying total no of bits used to allow for bitfields
7997077148fSMark Brown  * across the multiple codec registers.
8007077148fSMark Brown  *
8017077148fSMark Brown  * Returns 0 for success.
8027077148fSMark Brown  */
8037077148fSMark Brown int snd_soc_get_xr_sx(struct snd_kcontrol *kcontrol,
8047077148fSMark Brown 	struct snd_ctl_elem_value *ucontrol)
8057077148fSMark Brown {
8067077148fSMark Brown 	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
8077077148fSMark Brown 	struct soc_mreg_control *mc =
8087077148fSMark Brown 		(struct soc_mreg_control *)kcontrol->private_value;
8097077148fSMark Brown 	unsigned int regbase = mc->regbase;
8107077148fSMark Brown 	unsigned int regcount = mc->regcount;
8117077148fSMark Brown 	unsigned int regwshift = component->val_bytes * BITS_PER_BYTE;
8127077148fSMark Brown 	unsigned int regwmask = (1<<regwshift)-1;
8137077148fSMark Brown 	unsigned int invert = mc->invert;
8147077148fSMark Brown 	unsigned long mask = (1UL<<mc->nbits)-1;
8157077148fSMark Brown 	long min = mc->min;
8167077148fSMark Brown 	long max = mc->max;
8177077148fSMark Brown 	long val = 0;
8187077148fSMark Brown 	unsigned int regval;
8197077148fSMark Brown 	unsigned int i;
8207077148fSMark Brown 	int ret;
8217077148fSMark Brown 
8227077148fSMark Brown 	for (i = 0; i < regcount; i++) {
8237077148fSMark Brown 		ret = snd_soc_component_read(component, regbase+i, &regval);
8247077148fSMark Brown 		if (ret)
8257077148fSMark Brown 			return ret;
8267077148fSMark Brown 		val |= (regval & regwmask) << (regwshift*(regcount-i-1));
8277077148fSMark Brown 	}
8287077148fSMark Brown 	val &= mask;
8297077148fSMark Brown 	if (min < 0 && val > max)
8307077148fSMark Brown 		val |= ~mask;
8317077148fSMark Brown 	if (invert)
8327077148fSMark Brown 		val = max - val;
8337077148fSMark Brown 	ucontrol->value.integer.value[0] = val;
8347077148fSMark Brown 
8357077148fSMark Brown 	return 0;
8367077148fSMark Brown }
8377077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_get_xr_sx);
8387077148fSMark Brown 
8397077148fSMark Brown /**
8407077148fSMark Brown  * snd_soc_put_xr_sx - signed multi register get callback
8417077148fSMark Brown  * @kcontrol: mreg control
8427077148fSMark Brown  * @ucontrol: control element information
8437077148fSMark Brown  *
8447077148fSMark Brown  * Callback to set the value of a control that can span
8457077148fSMark Brown  * multiple codec registers which together forms a single
8467077148fSMark Brown  * signed value in a MSB/LSB manner. The control supports
8477077148fSMark Brown  * specifying total no of bits used to allow for bitfields
8487077148fSMark Brown  * across the multiple codec registers.
8497077148fSMark Brown  *
8507077148fSMark Brown  * Returns 0 for success.
8517077148fSMark Brown  */
8527077148fSMark Brown int snd_soc_put_xr_sx(struct snd_kcontrol *kcontrol,
8537077148fSMark Brown 	struct snd_ctl_elem_value *ucontrol)
8547077148fSMark Brown {
8557077148fSMark Brown 	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
8567077148fSMark Brown 	struct soc_mreg_control *mc =
8577077148fSMark Brown 		(struct soc_mreg_control *)kcontrol->private_value;
8587077148fSMark Brown 	unsigned int regbase = mc->regbase;
8597077148fSMark Brown 	unsigned int regcount = mc->regcount;
8607077148fSMark Brown 	unsigned int regwshift = component->val_bytes * BITS_PER_BYTE;
8617077148fSMark Brown 	unsigned int regwmask = (1<<regwshift)-1;
8627077148fSMark Brown 	unsigned int invert = mc->invert;
8637077148fSMark Brown 	unsigned long mask = (1UL<<mc->nbits)-1;
8647077148fSMark Brown 	long max = mc->max;
8657077148fSMark Brown 	long val = ucontrol->value.integer.value[0];
8667077148fSMark Brown 	unsigned int i, regval, regmask;
8677077148fSMark Brown 	int err;
8687077148fSMark Brown 
8697077148fSMark Brown 	if (invert)
8707077148fSMark Brown 		val = max - val;
8717077148fSMark Brown 	val &= mask;
8727077148fSMark Brown 	for (i = 0; i < regcount; i++) {
8737077148fSMark Brown 		regval = (val >> (regwshift*(regcount-i-1))) & regwmask;
8747077148fSMark Brown 		regmask = (mask >> (regwshift*(regcount-i-1))) & regwmask;
8757077148fSMark Brown 		err = snd_soc_component_update_bits(component, regbase+i,
8767077148fSMark Brown 				regmask, regval);
8777077148fSMark Brown 		if (err < 0)
8787077148fSMark Brown 			return err;
8797077148fSMark Brown 	}
8807077148fSMark Brown 
8817077148fSMark Brown 	return 0;
8827077148fSMark Brown }
8837077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_put_xr_sx);
8847077148fSMark Brown 
8857077148fSMark Brown /**
8867077148fSMark Brown  * snd_soc_get_strobe - strobe get callback
8877077148fSMark Brown  * @kcontrol: mixer control
8887077148fSMark Brown  * @ucontrol: control element information
8897077148fSMark Brown  *
8907077148fSMark Brown  * Callback get the value of a strobe mixer control.
8917077148fSMark Brown  *
8927077148fSMark Brown  * Returns 0 for success.
8937077148fSMark Brown  */
8947077148fSMark Brown int snd_soc_get_strobe(struct snd_kcontrol *kcontrol,
8957077148fSMark Brown 	struct snd_ctl_elem_value *ucontrol)
8967077148fSMark Brown {
8977077148fSMark Brown 	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
8987077148fSMark Brown 	struct soc_mixer_control *mc =
8997077148fSMark Brown 		(struct soc_mixer_control *)kcontrol->private_value;
9007077148fSMark Brown 	unsigned int reg = mc->reg;
9017077148fSMark Brown 	unsigned int shift = mc->shift;
9027077148fSMark Brown 	unsigned int mask = 1 << shift;
9037077148fSMark Brown 	unsigned int invert = mc->invert != 0;
9047077148fSMark Brown 	unsigned int val;
9057077148fSMark Brown 	int ret;
9067077148fSMark Brown 
9077077148fSMark Brown 	ret = snd_soc_component_read(component, reg, &val);
9087077148fSMark Brown 	if (ret)
9097077148fSMark Brown 		return ret;
9107077148fSMark Brown 
9117077148fSMark Brown 	val &= mask;
9127077148fSMark Brown 
9137077148fSMark Brown 	if (shift != 0 && val != 0)
9147077148fSMark Brown 		val = val >> shift;
9157077148fSMark Brown 	ucontrol->value.enumerated.item[0] = val ^ invert;
9167077148fSMark Brown 
9177077148fSMark Brown 	return 0;
9187077148fSMark Brown }
9197077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_get_strobe);
9207077148fSMark Brown 
9217077148fSMark Brown /**
9227077148fSMark Brown  * snd_soc_put_strobe - strobe put callback
9237077148fSMark Brown  * @kcontrol: mixer control
9247077148fSMark Brown  * @ucontrol: control element information
9257077148fSMark Brown  *
9267077148fSMark Brown  * Callback strobe a register bit to high then low (or the inverse)
9277077148fSMark Brown  * in one pass of a single mixer enum control.
9287077148fSMark Brown  *
9297077148fSMark Brown  * Returns 1 for success.
9307077148fSMark Brown  */
9317077148fSMark Brown int snd_soc_put_strobe(struct snd_kcontrol *kcontrol,
9327077148fSMark Brown 	struct snd_ctl_elem_value *ucontrol)
9337077148fSMark Brown {
9347077148fSMark Brown 	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
9357077148fSMark Brown 	struct soc_mixer_control *mc =
9367077148fSMark Brown 		(struct soc_mixer_control *)kcontrol->private_value;
9377077148fSMark Brown 	unsigned int reg = mc->reg;
9387077148fSMark Brown 	unsigned int shift = mc->shift;
9397077148fSMark Brown 	unsigned int mask = 1 << shift;
9407077148fSMark Brown 	unsigned int invert = mc->invert != 0;
9417077148fSMark Brown 	unsigned int strobe = ucontrol->value.enumerated.item[0] != 0;
9427077148fSMark Brown 	unsigned int val1 = (strobe ^ invert) ? mask : 0;
9437077148fSMark Brown 	unsigned int val2 = (strobe ^ invert) ? 0 : mask;
9447077148fSMark Brown 	int err;
9457077148fSMark Brown 
9467077148fSMark Brown 	err = snd_soc_component_update_bits(component, reg, mask, val1);
9477077148fSMark Brown 	if (err < 0)
9487077148fSMark Brown 		return err;
9497077148fSMark Brown 
9507077148fSMark Brown 	return snd_soc_component_update_bits(component, reg, mask, val2);
9517077148fSMark Brown }
9527077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_put_strobe);
953