xref: /openbmc/linux/sound/soc/soc-ops.c (revision a1e5e7e9)
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 /**
21034198710SCharles Keepax  * snd_soc_info_volsw_sx - Mixer info callback for SX TLV controls
21134198710SCharles Keepax  * @kcontrol: mixer control
21234198710SCharles Keepax  * @uinfo: control element information
21334198710SCharles Keepax  *
21434198710SCharles Keepax  * Callback to provide information about a single mixer control, or a double
21534198710SCharles Keepax  * mixer control that spans 2 registers of the SX TLV type. SX TLV controls
21634198710SCharles Keepax  * have a range that represents both positive and negative values either side
21734198710SCharles Keepax  * of zero but without a sign bit.
21834198710SCharles Keepax  *
21934198710SCharles Keepax  * Returns 0 for success.
22034198710SCharles Keepax  */
22134198710SCharles Keepax int snd_soc_info_volsw_sx(struct snd_kcontrol *kcontrol,
22234198710SCharles Keepax 			  struct snd_ctl_elem_info *uinfo)
22334198710SCharles Keepax {
22434198710SCharles Keepax 	struct soc_mixer_control *mc =
22534198710SCharles Keepax 		(struct soc_mixer_control *)kcontrol->private_value;
22634198710SCharles Keepax 
22734198710SCharles Keepax 	snd_soc_info_volsw(kcontrol, uinfo);
22834198710SCharles Keepax 	/* Max represents the number of levels in an SX control not the
22934198710SCharles Keepax 	 * maximum value, so add the minimum value back on
23034198710SCharles Keepax 	 */
23134198710SCharles Keepax 	uinfo->value.integer.max += mc->min;
23234198710SCharles Keepax 
23334198710SCharles Keepax 	return 0;
23434198710SCharles Keepax }
23534198710SCharles Keepax EXPORT_SYMBOL_GPL(snd_soc_info_volsw_sx);
23634198710SCharles Keepax 
23734198710SCharles Keepax /**
2387077148fSMark Brown  * snd_soc_get_volsw - single mixer get callback
2397077148fSMark Brown  * @kcontrol: mixer control
2407077148fSMark Brown  * @ucontrol: control element information
2417077148fSMark Brown  *
2427077148fSMark Brown  * Callback to get the value of a single mixer control, or a double mixer
2437077148fSMark Brown  * control that spans 2 registers.
2447077148fSMark Brown  *
2457077148fSMark Brown  * Returns 0 for success.
2467077148fSMark Brown  */
2477077148fSMark Brown int snd_soc_get_volsw(struct snd_kcontrol *kcontrol,
2487077148fSMark Brown 	struct snd_ctl_elem_value *ucontrol)
2497077148fSMark Brown {
2507077148fSMark Brown 	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
2517077148fSMark Brown 	struct soc_mixer_control *mc =
2527077148fSMark Brown 		(struct soc_mixer_control *)kcontrol->private_value;
2537077148fSMark Brown 	unsigned int reg = mc->reg;
2547077148fSMark Brown 	unsigned int reg2 = mc->rreg;
2557077148fSMark Brown 	unsigned int shift = mc->shift;
2567077148fSMark Brown 	unsigned int rshift = mc->rshift;
2577077148fSMark Brown 	int max = mc->max;
2587077148fSMark Brown 	int min = mc->min;
2597077148fSMark Brown 	int sign_bit = mc->sign_bit;
2607077148fSMark Brown 	unsigned int mask = (1 << fls(max)) - 1;
2617077148fSMark Brown 	unsigned int invert = mc->invert;
2627077148fSMark Brown 	int val;
2637077148fSMark Brown 	int ret;
2647077148fSMark Brown 
2657077148fSMark Brown 	if (sign_bit)
2667077148fSMark Brown 		mask = BIT(sign_bit + 1) - 1;
2677077148fSMark Brown 
2687077148fSMark Brown 	ret = snd_soc_read_signed(component, reg, mask, shift, sign_bit, &val);
2697077148fSMark Brown 	if (ret)
2707077148fSMark Brown 		return ret;
2717077148fSMark Brown 
2727077148fSMark Brown 	ucontrol->value.integer.value[0] = val - min;
2737077148fSMark Brown 	if (invert)
2747077148fSMark Brown 		ucontrol->value.integer.value[0] =
2757077148fSMark Brown 			max - ucontrol->value.integer.value[0];
2767077148fSMark Brown 
2777077148fSMark Brown 	if (snd_soc_volsw_is_stereo(mc)) {
2787077148fSMark Brown 		if (reg == reg2)
2797077148fSMark Brown 			ret = snd_soc_read_signed(component, reg, mask, rshift,
2807077148fSMark Brown 				sign_bit, &val);
2817077148fSMark Brown 		else
2827077148fSMark Brown 			ret = snd_soc_read_signed(component, reg2, mask, shift,
2837077148fSMark Brown 				sign_bit, &val);
2847077148fSMark Brown 		if (ret)
2857077148fSMark Brown 			return ret;
2867077148fSMark Brown 
2877077148fSMark Brown 		ucontrol->value.integer.value[1] = val - min;
2887077148fSMark Brown 		if (invert)
2897077148fSMark Brown 			ucontrol->value.integer.value[1] =
2907077148fSMark Brown 				max - ucontrol->value.integer.value[1];
2917077148fSMark Brown 	}
2927077148fSMark Brown 
2937077148fSMark Brown 	return 0;
2947077148fSMark Brown }
2957077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_get_volsw);
2967077148fSMark Brown 
2977077148fSMark Brown /**
2987077148fSMark Brown  * snd_soc_put_volsw - single mixer put callback
2997077148fSMark Brown  * @kcontrol: mixer control
3007077148fSMark Brown  * @ucontrol: control element information
3017077148fSMark Brown  *
3027077148fSMark Brown  * Callback to set the value of a single mixer control, or a double mixer
3037077148fSMark Brown  * control that spans 2 registers.
3047077148fSMark Brown  *
3057077148fSMark Brown  * Returns 0 for success.
3067077148fSMark Brown  */
3077077148fSMark Brown int snd_soc_put_volsw(struct snd_kcontrol *kcontrol,
3087077148fSMark Brown 	struct snd_ctl_elem_value *ucontrol)
3097077148fSMark Brown {
3107077148fSMark Brown 	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
3117077148fSMark Brown 	struct soc_mixer_control *mc =
3127077148fSMark Brown 		(struct soc_mixer_control *)kcontrol->private_value;
3137077148fSMark Brown 	unsigned int reg = mc->reg;
3147077148fSMark Brown 	unsigned int reg2 = mc->rreg;
3157077148fSMark Brown 	unsigned int shift = mc->shift;
3167077148fSMark Brown 	unsigned int rshift = mc->rshift;
3177077148fSMark Brown 	int max = mc->max;
3187077148fSMark Brown 	int min = mc->min;
3197077148fSMark Brown 	unsigned int sign_bit = mc->sign_bit;
3207077148fSMark Brown 	unsigned int mask = (1 << fls(max)) - 1;
3217077148fSMark Brown 	unsigned int invert = mc->invert;
3227077148fSMark Brown 	int err;
3237077148fSMark Brown 	bool type_2r = false;
3247077148fSMark Brown 	unsigned int val2 = 0;
3257077148fSMark Brown 	unsigned int val, val_mask;
3267077148fSMark Brown 
3277077148fSMark Brown 	if (sign_bit)
3287077148fSMark Brown 		mask = BIT(sign_bit + 1) - 1;
3297077148fSMark Brown 
3307077148fSMark Brown 	val = ((ucontrol->value.integer.value[0] + min) & mask);
3317077148fSMark Brown 	if (invert)
3327077148fSMark Brown 		val = max - val;
3337077148fSMark Brown 	val_mask = mask << shift;
3347077148fSMark Brown 	val = val << shift;
3357077148fSMark Brown 	if (snd_soc_volsw_is_stereo(mc)) {
3367077148fSMark Brown 		val2 = ((ucontrol->value.integer.value[1] + min) & mask);
3377077148fSMark Brown 		if (invert)
3387077148fSMark Brown 			val2 = max - val2;
3397077148fSMark Brown 		if (reg == reg2) {
3407077148fSMark Brown 			val_mask |= mask << rshift;
3417077148fSMark Brown 			val |= val2 << rshift;
3427077148fSMark Brown 		} else {
3437077148fSMark Brown 			val2 = val2 << shift;
3447077148fSMark Brown 			type_2r = true;
3457077148fSMark Brown 		}
3467077148fSMark Brown 	}
3477077148fSMark Brown 	err = snd_soc_component_update_bits(component, reg, val_mask, val);
3487077148fSMark Brown 	if (err < 0)
3497077148fSMark Brown 		return err;
3507077148fSMark Brown 
3517077148fSMark Brown 	if (type_2r)
3527077148fSMark Brown 		err = snd_soc_component_update_bits(component, reg2, val_mask,
3537077148fSMark Brown 			val2);
3547077148fSMark Brown 
3557077148fSMark Brown 	return err;
3567077148fSMark Brown }
3577077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_put_volsw);
3587077148fSMark Brown 
3597077148fSMark Brown /**
3607077148fSMark Brown  * snd_soc_get_volsw_sx - single mixer get callback
3617077148fSMark Brown  * @kcontrol: mixer control
3627077148fSMark Brown  * @ucontrol: control element information
3637077148fSMark Brown  *
3647077148fSMark Brown  * Callback to get the value of a single mixer control, or a double mixer
3657077148fSMark Brown  * control that spans 2 registers.
3667077148fSMark Brown  *
3677077148fSMark Brown  * Returns 0 for success.
3687077148fSMark Brown  */
3697077148fSMark Brown int snd_soc_get_volsw_sx(struct snd_kcontrol *kcontrol,
3707077148fSMark Brown 		      struct snd_ctl_elem_value *ucontrol)
3717077148fSMark Brown {
3727077148fSMark Brown 	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
3737077148fSMark Brown 	struct soc_mixer_control *mc =
3747077148fSMark Brown 	    (struct soc_mixer_control *)kcontrol->private_value;
3757077148fSMark Brown 	unsigned int reg = mc->reg;
3767077148fSMark Brown 	unsigned int reg2 = mc->rreg;
3777077148fSMark Brown 	unsigned int shift = mc->shift;
3787077148fSMark Brown 	unsigned int rshift = mc->rshift;
3797077148fSMark Brown 	int max = mc->max;
3807077148fSMark Brown 	int min = mc->min;
3817077148fSMark Brown 	int mask = (1 << (fls(min + max) - 1)) - 1;
3827077148fSMark Brown 	unsigned int val;
3837077148fSMark Brown 	int ret;
3847077148fSMark Brown 
3857077148fSMark Brown 	ret = snd_soc_component_read(component, reg, &val);
3867077148fSMark Brown 	if (ret < 0)
3877077148fSMark Brown 		return ret;
3887077148fSMark Brown 
3897077148fSMark Brown 	ucontrol->value.integer.value[0] = ((val >> shift) - min) & mask;
3907077148fSMark Brown 
3917077148fSMark Brown 	if (snd_soc_volsw_is_stereo(mc)) {
3927077148fSMark Brown 		ret = snd_soc_component_read(component, reg2, &val);
3937077148fSMark Brown 		if (ret < 0)
3947077148fSMark Brown 			return ret;
3957077148fSMark Brown 
3967077148fSMark Brown 		val = ((val >> rshift) - min) & mask;
3977077148fSMark Brown 		ucontrol->value.integer.value[1] = val;
3987077148fSMark Brown 	}
3997077148fSMark Brown 
4007077148fSMark Brown 	return 0;
4017077148fSMark Brown }
4027077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_get_volsw_sx);
4037077148fSMark Brown 
4047077148fSMark Brown /**
4057077148fSMark Brown  * snd_soc_put_volsw_sx - double mixer set callback
4067077148fSMark Brown  * @kcontrol: mixer control
4077077148fSMark Brown  * @uinfo: control element information
4087077148fSMark Brown  *
4097077148fSMark Brown  * Callback to set the value of a double mixer control that spans 2 registers.
4107077148fSMark Brown  *
4117077148fSMark Brown  * Returns 0 for success.
4127077148fSMark Brown  */
4137077148fSMark Brown int snd_soc_put_volsw_sx(struct snd_kcontrol *kcontrol,
4147077148fSMark Brown 			 struct snd_ctl_elem_value *ucontrol)
4157077148fSMark Brown {
4167077148fSMark Brown 	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
4177077148fSMark Brown 	struct soc_mixer_control *mc =
4187077148fSMark Brown 	    (struct soc_mixer_control *)kcontrol->private_value;
4197077148fSMark Brown 
4207077148fSMark Brown 	unsigned int reg = mc->reg;
4217077148fSMark Brown 	unsigned int reg2 = mc->rreg;
4227077148fSMark Brown 	unsigned int shift = mc->shift;
4237077148fSMark Brown 	unsigned int rshift = mc->rshift;
4247077148fSMark Brown 	int max = mc->max;
4257077148fSMark Brown 	int min = mc->min;
4267077148fSMark Brown 	int mask = (1 << (fls(min + max) - 1)) - 1;
4277077148fSMark Brown 	int err = 0;
4287077148fSMark Brown 	unsigned int val, val_mask, val2 = 0;
4297077148fSMark Brown 
4307077148fSMark Brown 	val_mask = mask << shift;
4317077148fSMark Brown 	val = (ucontrol->value.integer.value[0] + min) & mask;
4327077148fSMark Brown 	val = val << shift;
4337077148fSMark Brown 
4347077148fSMark Brown 	err = snd_soc_component_update_bits(component, reg, val_mask, val);
4357077148fSMark Brown 	if (err < 0)
4367077148fSMark Brown 		return err;
4377077148fSMark Brown 
4387077148fSMark Brown 	if (snd_soc_volsw_is_stereo(mc)) {
4397077148fSMark Brown 		val_mask = mask << rshift;
4407077148fSMark Brown 		val2 = (ucontrol->value.integer.value[1] + min) & mask;
4417077148fSMark Brown 		val2 = val2 << rshift;
4427077148fSMark Brown 
4437077148fSMark Brown 		err = snd_soc_component_update_bits(component, reg2, val_mask,
4447077148fSMark Brown 			val2);
4457077148fSMark Brown 	}
4467077148fSMark Brown 	return err;
4477077148fSMark Brown }
4487077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_put_volsw_sx);
4497077148fSMark Brown 
4507077148fSMark Brown /**
4517077148fSMark Brown  * snd_soc_info_volsw_range - single mixer info callback with range.
4527077148fSMark Brown  * @kcontrol: mixer control
4537077148fSMark Brown  * @uinfo: control element information
4547077148fSMark Brown  *
4557077148fSMark Brown  * Callback to provide information, within a range, about a single
4567077148fSMark Brown  * mixer control.
4577077148fSMark Brown  *
4587077148fSMark Brown  * returns 0 for success.
4597077148fSMark Brown  */
4607077148fSMark Brown int snd_soc_info_volsw_range(struct snd_kcontrol *kcontrol,
4617077148fSMark Brown 	struct snd_ctl_elem_info *uinfo)
4627077148fSMark Brown {
4637077148fSMark Brown 	struct soc_mixer_control *mc =
4647077148fSMark Brown 		(struct soc_mixer_control *)kcontrol->private_value;
4657077148fSMark Brown 	int platform_max;
4667077148fSMark Brown 	int min = mc->min;
4677077148fSMark Brown 
4687077148fSMark Brown 	if (!mc->platform_max)
4697077148fSMark Brown 		mc->platform_max = mc->max;
4707077148fSMark Brown 	platform_max = mc->platform_max;
4717077148fSMark Brown 
4727077148fSMark Brown 	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
4737077148fSMark Brown 	uinfo->count = snd_soc_volsw_is_stereo(mc) ? 2 : 1;
4747077148fSMark Brown 	uinfo->value.integer.min = 0;
4757077148fSMark Brown 	uinfo->value.integer.max = platform_max - min;
4767077148fSMark Brown 
4777077148fSMark Brown 	return 0;
4787077148fSMark Brown }
4797077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_info_volsw_range);
4807077148fSMark Brown 
4817077148fSMark Brown /**
4827077148fSMark Brown  * snd_soc_put_volsw_range - single mixer put value callback with range.
4837077148fSMark Brown  * @kcontrol: mixer control
4847077148fSMark Brown  * @ucontrol: control element information
4857077148fSMark Brown  *
4867077148fSMark Brown  * Callback to set the value, within a range, for a single mixer control.
4877077148fSMark Brown  *
4887077148fSMark Brown  * Returns 0 for success.
4897077148fSMark Brown  */
4907077148fSMark Brown int snd_soc_put_volsw_range(struct snd_kcontrol *kcontrol,
4917077148fSMark Brown 	struct snd_ctl_elem_value *ucontrol)
4927077148fSMark Brown {
4937077148fSMark Brown 	struct soc_mixer_control *mc =
4947077148fSMark Brown 		(struct soc_mixer_control *)kcontrol->private_value;
4957077148fSMark Brown 	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
4967077148fSMark Brown 	unsigned int reg = mc->reg;
4977077148fSMark Brown 	unsigned int rreg = mc->rreg;
4987077148fSMark Brown 	unsigned int shift = mc->shift;
4997077148fSMark Brown 	int min = mc->min;
5007077148fSMark Brown 	int max = mc->max;
5017077148fSMark Brown 	unsigned int mask = (1 << fls(max)) - 1;
5027077148fSMark Brown 	unsigned int invert = mc->invert;
5037077148fSMark Brown 	unsigned int val, val_mask;
5047077148fSMark Brown 	int ret;
5057077148fSMark Brown 
5067077148fSMark Brown 	if (invert)
5077077148fSMark Brown 		val = (max - ucontrol->value.integer.value[0]) & mask;
5087077148fSMark Brown 	else
5097077148fSMark Brown 		val = ((ucontrol->value.integer.value[0] + min) & mask);
5107077148fSMark Brown 	val_mask = mask << shift;
5117077148fSMark Brown 	val = val << shift;
5127077148fSMark Brown 
5137077148fSMark Brown 	ret = snd_soc_component_update_bits(component, reg, val_mask, val);
5147077148fSMark Brown 	if (ret < 0)
5157077148fSMark Brown 		return ret;
5167077148fSMark Brown 
5177077148fSMark Brown 	if (snd_soc_volsw_is_stereo(mc)) {
5187077148fSMark Brown 		if (invert)
5197077148fSMark Brown 			val = (max - ucontrol->value.integer.value[1]) & mask;
5207077148fSMark Brown 		else
5217077148fSMark Brown 			val = ((ucontrol->value.integer.value[1] + min) & mask);
5227077148fSMark Brown 		val_mask = mask << shift;
5237077148fSMark Brown 		val = val << shift;
5247077148fSMark Brown 
5257077148fSMark Brown 		ret = snd_soc_component_update_bits(component, rreg, val_mask,
5267077148fSMark Brown 			val);
5277077148fSMark Brown 	}
5287077148fSMark Brown 
5297077148fSMark Brown 	return ret;
5307077148fSMark Brown }
5317077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_put_volsw_range);
5327077148fSMark Brown 
5337077148fSMark Brown /**
5347077148fSMark Brown  * snd_soc_get_volsw_range - single mixer get callback with range
5357077148fSMark Brown  * @kcontrol: mixer control
5367077148fSMark Brown  * @ucontrol: control element information
5377077148fSMark Brown  *
5387077148fSMark Brown  * Callback to get the value, within a range, of a single mixer control.
5397077148fSMark Brown  *
5407077148fSMark Brown  * Returns 0 for success.
5417077148fSMark Brown  */
5427077148fSMark Brown int snd_soc_get_volsw_range(struct snd_kcontrol *kcontrol,
5437077148fSMark Brown 	struct snd_ctl_elem_value *ucontrol)
5447077148fSMark Brown {
5457077148fSMark Brown 	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
5467077148fSMark Brown 	struct soc_mixer_control *mc =
5477077148fSMark Brown 		(struct soc_mixer_control *)kcontrol->private_value;
5487077148fSMark Brown 	unsigned int reg = mc->reg;
5497077148fSMark Brown 	unsigned int rreg = mc->rreg;
5507077148fSMark Brown 	unsigned int shift = mc->shift;
5517077148fSMark Brown 	int min = mc->min;
5527077148fSMark Brown 	int max = mc->max;
5537077148fSMark Brown 	unsigned int mask = (1 << fls(max)) - 1;
5547077148fSMark Brown 	unsigned int invert = mc->invert;
5557077148fSMark Brown 	unsigned int val;
5567077148fSMark Brown 	int ret;
5577077148fSMark Brown 
5587077148fSMark Brown 	ret = snd_soc_component_read(component, reg, &val);
5597077148fSMark Brown 	if (ret)
5607077148fSMark Brown 		return ret;
5617077148fSMark Brown 
5627077148fSMark Brown 	ucontrol->value.integer.value[0] = (val >> shift) & mask;
5637077148fSMark Brown 	if (invert)
5647077148fSMark Brown 		ucontrol->value.integer.value[0] =
5657077148fSMark Brown 			max - ucontrol->value.integer.value[0];
5667077148fSMark Brown 	else
5677077148fSMark Brown 		ucontrol->value.integer.value[0] =
5687077148fSMark Brown 			ucontrol->value.integer.value[0] - min;
5697077148fSMark Brown 
5707077148fSMark Brown 	if (snd_soc_volsw_is_stereo(mc)) {
5717077148fSMark Brown 		ret = snd_soc_component_read(component, rreg, &val);
5727077148fSMark Brown 		if (ret)
5737077148fSMark Brown 			return ret;
5747077148fSMark Brown 
5757077148fSMark Brown 		ucontrol->value.integer.value[1] = (val >> shift) & mask;
5767077148fSMark Brown 		if (invert)
5777077148fSMark Brown 			ucontrol->value.integer.value[1] =
5787077148fSMark Brown 				max - ucontrol->value.integer.value[1];
5797077148fSMark Brown 		else
5807077148fSMark Brown 			ucontrol->value.integer.value[1] =
5817077148fSMark Brown 				ucontrol->value.integer.value[1] - min;
5827077148fSMark Brown 	}
5837077148fSMark Brown 
5847077148fSMark Brown 	return 0;
5857077148fSMark Brown }
5867077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_get_volsw_range);
5877077148fSMark Brown 
5887077148fSMark Brown /**
5897077148fSMark Brown  * snd_soc_limit_volume - Set new limit to an existing volume control.
5907077148fSMark Brown  *
59126d9ca34SLars-Peter Clausen  * @card: where to look for the control
5927077148fSMark Brown  * @name: Name of the control
5937077148fSMark Brown  * @max: new maximum limit
5947077148fSMark Brown  *
5957077148fSMark Brown  * Return 0 for success, else error.
5967077148fSMark Brown  */
59726d9ca34SLars-Peter Clausen int snd_soc_limit_volume(struct snd_soc_card *card,
5987077148fSMark Brown 	const char *name, int max)
5997077148fSMark Brown {
60026d9ca34SLars-Peter Clausen 	struct snd_card *snd_card = card->snd_card;
6017077148fSMark Brown 	struct snd_kcontrol *kctl;
6027077148fSMark Brown 	struct soc_mixer_control *mc;
6037077148fSMark Brown 	int found = 0;
6047077148fSMark Brown 	int ret = -EINVAL;
6057077148fSMark Brown 
6067077148fSMark Brown 	/* Sanity check for name and max */
6077077148fSMark Brown 	if (unlikely(!name || max <= 0))
6087077148fSMark Brown 		return -EINVAL;
6097077148fSMark Brown 
61026d9ca34SLars-Peter Clausen 	list_for_each_entry(kctl, &snd_card->controls, list) {
6117077148fSMark Brown 		if (!strncmp(kctl->id.name, name, sizeof(kctl->id.name))) {
6127077148fSMark Brown 			found = 1;
6137077148fSMark Brown 			break;
6147077148fSMark Brown 		}
6157077148fSMark Brown 	}
6167077148fSMark Brown 	if (found) {
6177077148fSMark Brown 		mc = (struct soc_mixer_control *)kctl->private_value;
6187077148fSMark Brown 		if (max <= mc->max) {
6197077148fSMark Brown 			mc->platform_max = max;
6207077148fSMark Brown 			ret = 0;
6217077148fSMark Brown 		}
6227077148fSMark Brown 	}
6237077148fSMark Brown 	return ret;
6247077148fSMark Brown }
6257077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_limit_volume);
6267077148fSMark Brown 
6277077148fSMark Brown int snd_soc_bytes_info(struct snd_kcontrol *kcontrol,
6287077148fSMark Brown 		       struct snd_ctl_elem_info *uinfo)
6297077148fSMark Brown {
6307077148fSMark Brown 	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
6317077148fSMark Brown 	struct soc_bytes *params = (void *)kcontrol->private_value;
6327077148fSMark Brown 
6337077148fSMark Brown 	uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
6347077148fSMark Brown 	uinfo->count = params->num_regs * component->val_bytes;
6357077148fSMark Brown 
6367077148fSMark Brown 	return 0;
6377077148fSMark Brown }
6387077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_bytes_info);
6397077148fSMark Brown 
6407077148fSMark Brown int snd_soc_bytes_get(struct snd_kcontrol *kcontrol,
6417077148fSMark Brown 		      struct snd_ctl_elem_value *ucontrol)
6427077148fSMark Brown {
6437077148fSMark Brown 	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
6447077148fSMark Brown 	struct soc_bytes *params = (void *)kcontrol->private_value;
6457077148fSMark Brown 	int ret;
6467077148fSMark Brown 
6477077148fSMark Brown 	if (component->regmap)
6487077148fSMark Brown 		ret = regmap_raw_read(component->regmap, params->base,
6497077148fSMark Brown 				      ucontrol->value.bytes.data,
6507077148fSMark Brown 				      params->num_regs * component->val_bytes);
6517077148fSMark Brown 	else
6527077148fSMark Brown 		ret = -EINVAL;
6537077148fSMark Brown 
6547077148fSMark Brown 	/* Hide any masked bytes to ensure consistent data reporting */
6557077148fSMark Brown 	if (ret == 0 && params->mask) {
6567077148fSMark Brown 		switch (component->val_bytes) {
6577077148fSMark Brown 		case 1:
6587077148fSMark Brown 			ucontrol->value.bytes.data[0] &= ~params->mask;
6597077148fSMark Brown 			break;
6607077148fSMark Brown 		case 2:
6617077148fSMark Brown 			((u16 *)(&ucontrol->value.bytes.data))[0]
6627077148fSMark Brown 				&= cpu_to_be16(~params->mask);
6637077148fSMark Brown 			break;
6647077148fSMark Brown 		case 4:
6657077148fSMark Brown 			((u32 *)(&ucontrol->value.bytes.data))[0]
6667077148fSMark Brown 				&= cpu_to_be32(~params->mask);
6677077148fSMark Brown 			break;
6687077148fSMark Brown 		default:
6697077148fSMark Brown 			return -EINVAL;
6707077148fSMark Brown 		}
6717077148fSMark Brown 	}
6727077148fSMark Brown 
6737077148fSMark Brown 	return ret;
6747077148fSMark Brown }
6757077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_bytes_get);
6767077148fSMark Brown 
6777077148fSMark Brown int snd_soc_bytes_put(struct snd_kcontrol *kcontrol,
6787077148fSMark Brown 		      struct snd_ctl_elem_value *ucontrol)
6797077148fSMark Brown {
6807077148fSMark Brown 	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
6817077148fSMark Brown 	struct soc_bytes *params = (void *)kcontrol->private_value;
6827077148fSMark Brown 	int ret, len;
6837077148fSMark Brown 	unsigned int val, mask;
6847077148fSMark Brown 	void *data;
6857077148fSMark Brown 
6867077148fSMark Brown 	if (!component->regmap || !params->num_regs)
6877077148fSMark Brown 		return -EINVAL;
6887077148fSMark Brown 
6897077148fSMark Brown 	len = params->num_regs * component->val_bytes;
6907077148fSMark Brown 
6917077148fSMark Brown 	data = kmemdup(ucontrol->value.bytes.data, len, GFP_KERNEL | GFP_DMA);
6927077148fSMark Brown 	if (!data)
6937077148fSMark Brown 		return -ENOMEM;
6947077148fSMark Brown 
6957077148fSMark Brown 	/*
6967077148fSMark Brown 	 * If we've got a mask then we need to preserve the register
6977077148fSMark Brown 	 * bits.  We shouldn't modify the incoming data so take a
6987077148fSMark Brown 	 * copy.
6997077148fSMark Brown 	 */
7007077148fSMark Brown 	if (params->mask) {
7017077148fSMark Brown 		ret = regmap_read(component->regmap, params->base, &val);
7027077148fSMark Brown 		if (ret != 0)
7037077148fSMark Brown 			goto out;
7047077148fSMark Brown 
7057077148fSMark Brown 		val &= params->mask;
7067077148fSMark Brown 
7077077148fSMark Brown 		switch (component->val_bytes) {
7087077148fSMark Brown 		case 1:
7097077148fSMark Brown 			((u8 *)data)[0] &= ~params->mask;
7107077148fSMark Brown 			((u8 *)data)[0] |= val;
7117077148fSMark Brown 			break;
7127077148fSMark Brown 		case 2:
7137077148fSMark Brown 			mask = ~params->mask;
7147077148fSMark Brown 			ret = regmap_parse_val(component->regmap,
7157077148fSMark Brown 							&mask, &mask);
7167077148fSMark Brown 			if (ret != 0)
7177077148fSMark Brown 				goto out;
7187077148fSMark Brown 
7197077148fSMark Brown 			((u16 *)data)[0] &= mask;
7207077148fSMark Brown 
7217077148fSMark Brown 			ret = regmap_parse_val(component->regmap,
7227077148fSMark Brown 							&val, &val);
7237077148fSMark Brown 			if (ret != 0)
7247077148fSMark Brown 				goto out;
7257077148fSMark Brown 
7267077148fSMark Brown 			((u16 *)data)[0] |= val;
7277077148fSMark Brown 			break;
7287077148fSMark Brown 		case 4:
7297077148fSMark Brown 			mask = ~params->mask;
7307077148fSMark Brown 			ret = regmap_parse_val(component->regmap,
7317077148fSMark Brown 							&mask, &mask);
7327077148fSMark Brown 			if (ret != 0)
7337077148fSMark Brown 				goto out;
7347077148fSMark Brown 
7357077148fSMark Brown 			((u32 *)data)[0] &= mask;
7367077148fSMark Brown 
7377077148fSMark Brown 			ret = regmap_parse_val(component->regmap,
7387077148fSMark Brown 							&val, &val);
7397077148fSMark Brown 			if (ret != 0)
7407077148fSMark Brown 				goto out;
7417077148fSMark Brown 
7427077148fSMark Brown 			((u32 *)data)[0] |= val;
7437077148fSMark Brown 			break;
7447077148fSMark Brown 		default:
7457077148fSMark Brown 			ret = -EINVAL;
7467077148fSMark Brown 			goto out;
7477077148fSMark Brown 		}
7487077148fSMark Brown 	}
7497077148fSMark Brown 
7507077148fSMark Brown 	ret = regmap_raw_write(component->regmap, params->base,
7517077148fSMark Brown 			       data, len);
7527077148fSMark Brown 
7537077148fSMark Brown out:
7547077148fSMark Brown 	kfree(data);
7557077148fSMark Brown 
7567077148fSMark Brown 	return ret;
7577077148fSMark Brown }
7587077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_bytes_put);
7597077148fSMark Brown 
7607077148fSMark Brown int snd_soc_bytes_info_ext(struct snd_kcontrol *kcontrol,
7617077148fSMark Brown 			struct snd_ctl_elem_info *ucontrol)
7627077148fSMark Brown {
7637077148fSMark Brown 	struct soc_bytes_ext *params = (void *)kcontrol->private_value;
7647077148fSMark Brown 
7657077148fSMark Brown 	ucontrol->type = SNDRV_CTL_ELEM_TYPE_BYTES;
7667077148fSMark Brown 	ucontrol->count = params->max;
7677077148fSMark Brown 
7687077148fSMark Brown 	return 0;
7697077148fSMark Brown }
7707077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_bytes_info_ext);
7717077148fSMark Brown 
7727077148fSMark Brown int snd_soc_bytes_tlv_callback(struct snd_kcontrol *kcontrol, int op_flag,
7737077148fSMark Brown 				unsigned int size, unsigned int __user *tlv)
7747077148fSMark Brown {
7757077148fSMark Brown 	struct soc_bytes_ext *params = (void *)kcontrol->private_value;
7767077148fSMark Brown 	unsigned int count = size < params->max ? size : params->max;
7777077148fSMark Brown 	int ret = -ENXIO;
7787077148fSMark Brown 
7797077148fSMark Brown 	switch (op_flag) {
7807077148fSMark Brown 	case SNDRV_CTL_TLV_OP_READ:
7817077148fSMark Brown 		if (params->get)
782a1e5e7e9SMythri P K 			ret = params->get(kcontrol, tlv, count);
7837077148fSMark Brown 		break;
7847077148fSMark Brown 	case SNDRV_CTL_TLV_OP_WRITE:
7857077148fSMark Brown 		if (params->put)
786a1e5e7e9SMythri P K 			ret = params->put(kcontrol, tlv, count);
7877077148fSMark Brown 		break;
7887077148fSMark Brown 	}
7897077148fSMark Brown 	return ret;
7907077148fSMark Brown }
7917077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_bytes_tlv_callback);
7927077148fSMark Brown 
7937077148fSMark Brown /**
7947077148fSMark Brown  * snd_soc_info_xr_sx - signed multi register info callback
7957077148fSMark Brown  * @kcontrol: mreg control
7967077148fSMark Brown  * @uinfo: control element information
7977077148fSMark Brown  *
7987077148fSMark Brown  * Callback to provide information of a control that can
7997077148fSMark Brown  * span multiple codec registers which together
8007077148fSMark Brown  * forms a single signed value in a MSB/LSB manner.
8017077148fSMark Brown  *
8027077148fSMark Brown  * Returns 0 for success.
8037077148fSMark Brown  */
8047077148fSMark Brown int snd_soc_info_xr_sx(struct snd_kcontrol *kcontrol,
8057077148fSMark Brown 	struct snd_ctl_elem_info *uinfo)
8067077148fSMark Brown {
8077077148fSMark Brown 	struct soc_mreg_control *mc =
8087077148fSMark Brown 		(struct soc_mreg_control *)kcontrol->private_value;
8097077148fSMark Brown 	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
8107077148fSMark Brown 	uinfo->count = 1;
8117077148fSMark Brown 	uinfo->value.integer.min = mc->min;
8127077148fSMark Brown 	uinfo->value.integer.max = mc->max;
8137077148fSMark Brown 
8147077148fSMark Brown 	return 0;
8157077148fSMark Brown }
8167077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_info_xr_sx);
8177077148fSMark Brown 
8187077148fSMark Brown /**
8197077148fSMark Brown  * snd_soc_get_xr_sx - signed multi register get callback
8207077148fSMark Brown  * @kcontrol: mreg control
8217077148fSMark Brown  * @ucontrol: control element information
8227077148fSMark Brown  *
8237077148fSMark Brown  * Callback to get the value of a control that can span
8247077148fSMark Brown  * multiple codec registers which together forms a single
8257077148fSMark Brown  * signed value in a MSB/LSB manner. The control supports
8267077148fSMark Brown  * specifying total no of bits used to allow for bitfields
8277077148fSMark Brown  * across the multiple codec registers.
8287077148fSMark Brown  *
8297077148fSMark Brown  * Returns 0 for success.
8307077148fSMark Brown  */
8317077148fSMark Brown int snd_soc_get_xr_sx(struct snd_kcontrol *kcontrol,
8327077148fSMark Brown 	struct snd_ctl_elem_value *ucontrol)
8337077148fSMark Brown {
8347077148fSMark Brown 	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
8357077148fSMark Brown 	struct soc_mreg_control *mc =
8367077148fSMark Brown 		(struct soc_mreg_control *)kcontrol->private_value;
8377077148fSMark Brown 	unsigned int regbase = mc->regbase;
8387077148fSMark Brown 	unsigned int regcount = mc->regcount;
8397077148fSMark Brown 	unsigned int regwshift = component->val_bytes * BITS_PER_BYTE;
8407077148fSMark Brown 	unsigned int regwmask = (1<<regwshift)-1;
8417077148fSMark Brown 	unsigned int invert = mc->invert;
8427077148fSMark Brown 	unsigned long mask = (1UL<<mc->nbits)-1;
8437077148fSMark Brown 	long min = mc->min;
8447077148fSMark Brown 	long max = mc->max;
8457077148fSMark Brown 	long val = 0;
8467077148fSMark Brown 	unsigned int regval;
8477077148fSMark Brown 	unsigned int i;
8487077148fSMark Brown 	int ret;
8497077148fSMark Brown 
8507077148fSMark Brown 	for (i = 0; i < regcount; i++) {
8517077148fSMark Brown 		ret = snd_soc_component_read(component, regbase+i, &regval);
8527077148fSMark Brown 		if (ret)
8537077148fSMark Brown 			return ret;
8547077148fSMark Brown 		val |= (regval & regwmask) << (regwshift*(regcount-i-1));
8557077148fSMark Brown 	}
8567077148fSMark Brown 	val &= mask;
8577077148fSMark Brown 	if (min < 0 && val > max)
8587077148fSMark Brown 		val |= ~mask;
8597077148fSMark Brown 	if (invert)
8607077148fSMark Brown 		val = max - val;
8617077148fSMark Brown 	ucontrol->value.integer.value[0] = val;
8627077148fSMark Brown 
8637077148fSMark Brown 	return 0;
8647077148fSMark Brown }
8657077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_get_xr_sx);
8667077148fSMark Brown 
8677077148fSMark Brown /**
8687077148fSMark Brown  * snd_soc_put_xr_sx - signed multi register get callback
8697077148fSMark Brown  * @kcontrol: mreg control
8707077148fSMark Brown  * @ucontrol: control element information
8717077148fSMark Brown  *
8727077148fSMark Brown  * Callback to set the value of a control that can span
8737077148fSMark Brown  * multiple codec registers which together forms a single
8747077148fSMark Brown  * signed value in a MSB/LSB manner. The control supports
8757077148fSMark Brown  * specifying total no of bits used to allow for bitfields
8767077148fSMark Brown  * across the multiple codec registers.
8777077148fSMark Brown  *
8787077148fSMark Brown  * Returns 0 for success.
8797077148fSMark Brown  */
8807077148fSMark Brown int snd_soc_put_xr_sx(struct snd_kcontrol *kcontrol,
8817077148fSMark Brown 	struct snd_ctl_elem_value *ucontrol)
8827077148fSMark Brown {
8837077148fSMark Brown 	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
8847077148fSMark Brown 	struct soc_mreg_control *mc =
8857077148fSMark Brown 		(struct soc_mreg_control *)kcontrol->private_value;
8867077148fSMark Brown 	unsigned int regbase = mc->regbase;
8877077148fSMark Brown 	unsigned int regcount = mc->regcount;
8887077148fSMark Brown 	unsigned int regwshift = component->val_bytes * BITS_PER_BYTE;
8897077148fSMark Brown 	unsigned int regwmask = (1<<regwshift)-1;
8907077148fSMark Brown 	unsigned int invert = mc->invert;
8917077148fSMark Brown 	unsigned long mask = (1UL<<mc->nbits)-1;
8927077148fSMark Brown 	long max = mc->max;
8937077148fSMark Brown 	long val = ucontrol->value.integer.value[0];
8947077148fSMark Brown 	unsigned int i, regval, regmask;
8957077148fSMark Brown 	int err;
8967077148fSMark Brown 
8977077148fSMark Brown 	if (invert)
8987077148fSMark Brown 		val = max - val;
8997077148fSMark Brown 	val &= mask;
9007077148fSMark Brown 	for (i = 0; i < regcount; i++) {
9017077148fSMark Brown 		regval = (val >> (regwshift*(regcount-i-1))) & regwmask;
9027077148fSMark Brown 		regmask = (mask >> (regwshift*(regcount-i-1))) & regwmask;
9037077148fSMark Brown 		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 	int ret;
9347077148fSMark Brown 
9357077148fSMark Brown 	ret = snd_soc_component_read(component, reg, &val);
9367077148fSMark Brown 	if (ret)
9377077148fSMark Brown 		return ret;
9387077148fSMark Brown 
9397077148fSMark Brown 	val &= mask;
9407077148fSMark Brown 
9417077148fSMark Brown 	if (shift != 0 && val != 0)
9427077148fSMark Brown 		val = val >> shift;
9437077148fSMark Brown 	ucontrol->value.enumerated.item[0] = val ^ invert;
9447077148fSMark Brown 
9457077148fSMark Brown 	return 0;
9467077148fSMark Brown }
9477077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_get_strobe);
9487077148fSMark Brown 
9497077148fSMark Brown /**
9507077148fSMark Brown  * snd_soc_put_strobe - strobe put callback
9517077148fSMark Brown  * @kcontrol: mixer control
9527077148fSMark Brown  * @ucontrol: control element information
9537077148fSMark Brown  *
9547077148fSMark Brown  * Callback strobe a register bit to high then low (or the inverse)
9557077148fSMark Brown  * in one pass of a single mixer enum control.
9567077148fSMark Brown  *
9577077148fSMark Brown  * Returns 1 for success.
9587077148fSMark Brown  */
9597077148fSMark Brown int snd_soc_put_strobe(struct snd_kcontrol *kcontrol,
9607077148fSMark Brown 	struct snd_ctl_elem_value *ucontrol)
9617077148fSMark Brown {
9627077148fSMark Brown 	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
9637077148fSMark Brown 	struct soc_mixer_control *mc =
9647077148fSMark Brown 		(struct soc_mixer_control *)kcontrol->private_value;
9657077148fSMark Brown 	unsigned int reg = mc->reg;
9667077148fSMark Brown 	unsigned int shift = mc->shift;
9677077148fSMark Brown 	unsigned int mask = 1 << shift;
9687077148fSMark Brown 	unsigned int invert = mc->invert != 0;
9697077148fSMark Brown 	unsigned int strobe = ucontrol->value.enumerated.item[0] != 0;
9707077148fSMark Brown 	unsigned int val1 = (strobe ^ invert) ? mask : 0;
9717077148fSMark Brown 	unsigned int val2 = (strobe ^ invert) ? 0 : mask;
9727077148fSMark Brown 	int err;
9737077148fSMark Brown 
9747077148fSMark Brown 	err = snd_soc_component_update_bits(component, reg, mask, val1);
9757077148fSMark Brown 	if (err < 0)
9767077148fSMark Brown 		return err;
9777077148fSMark Brown 
9787077148fSMark Brown 	return snd_soc_component_update_bits(component, reg, mask, val2);
9797077148fSMark Brown }
9807077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_put_strobe);
981