18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0+
28c2ecf20Sopenharmony_ci//
38c2ecf20Sopenharmony_ci// soc-ops.c  --  Generic ASoC operations
48c2ecf20Sopenharmony_ci//
58c2ecf20Sopenharmony_ci// Copyright 2005 Wolfson Microelectronics PLC.
68c2ecf20Sopenharmony_ci// Copyright 2005 Openedhand Ltd.
78c2ecf20Sopenharmony_ci// Copyright (C) 2010 Slimlogic Ltd.
88c2ecf20Sopenharmony_ci// Copyright (C) 2010 Texas Instruments Inc.
98c2ecf20Sopenharmony_ci//
108c2ecf20Sopenharmony_ci// Author: Liam Girdwood <lrg@slimlogic.co.uk>
118c2ecf20Sopenharmony_ci//         with code, comments and ideas from :-
128c2ecf20Sopenharmony_ci//         Richard Purdie <richard@openedhand.com>
138c2ecf20Sopenharmony_ci
148c2ecf20Sopenharmony_ci#include <linux/module.h>
158c2ecf20Sopenharmony_ci#include <linux/moduleparam.h>
168c2ecf20Sopenharmony_ci#include <linux/init.h>
178c2ecf20Sopenharmony_ci#include <linux/delay.h>
188c2ecf20Sopenharmony_ci#include <linux/pm.h>
198c2ecf20Sopenharmony_ci#include <linux/bitops.h>
208c2ecf20Sopenharmony_ci#include <linux/ctype.h>
218c2ecf20Sopenharmony_ci#include <linux/slab.h>
228c2ecf20Sopenharmony_ci#include <sound/core.h>
238c2ecf20Sopenharmony_ci#include <sound/jack.h>
248c2ecf20Sopenharmony_ci#include <sound/pcm.h>
258c2ecf20Sopenharmony_ci#include <sound/pcm_params.h>
268c2ecf20Sopenharmony_ci#include <sound/soc.h>
278c2ecf20Sopenharmony_ci#include <sound/soc-dpcm.h>
288c2ecf20Sopenharmony_ci#include <sound/initval.h>
298c2ecf20Sopenharmony_ci
308c2ecf20Sopenharmony_ci/**
318c2ecf20Sopenharmony_ci * snd_soc_info_enum_double - enumerated double mixer info callback
328c2ecf20Sopenharmony_ci * @kcontrol: mixer control
338c2ecf20Sopenharmony_ci * @uinfo: control element information
348c2ecf20Sopenharmony_ci *
358c2ecf20Sopenharmony_ci * Callback to provide information about a double enumerated
368c2ecf20Sopenharmony_ci * mixer control.
378c2ecf20Sopenharmony_ci *
388c2ecf20Sopenharmony_ci * Returns 0 for success.
398c2ecf20Sopenharmony_ci */
408c2ecf20Sopenharmony_ciint snd_soc_info_enum_double(struct snd_kcontrol *kcontrol,
418c2ecf20Sopenharmony_ci	struct snd_ctl_elem_info *uinfo)
428c2ecf20Sopenharmony_ci{
438c2ecf20Sopenharmony_ci	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
448c2ecf20Sopenharmony_ci
458c2ecf20Sopenharmony_ci	return snd_ctl_enum_info(uinfo, e->shift_l == e->shift_r ? 1 : 2,
468c2ecf20Sopenharmony_ci				 e->items, e->texts);
478c2ecf20Sopenharmony_ci}
488c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(snd_soc_info_enum_double);
498c2ecf20Sopenharmony_ci
508c2ecf20Sopenharmony_ci/**
518c2ecf20Sopenharmony_ci * snd_soc_get_enum_double - enumerated double mixer get callback
528c2ecf20Sopenharmony_ci * @kcontrol: mixer control
538c2ecf20Sopenharmony_ci * @ucontrol: control element information
548c2ecf20Sopenharmony_ci *
558c2ecf20Sopenharmony_ci * Callback to get the value of a double enumerated mixer.
568c2ecf20Sopenharmony_ci *
578c2ecf20Sopenharmony_ci * Returns 0 for success.
588c2ecf20Sopenharmony_ci */
598c2ecf20Sopenharmony_ciint snd_soc_get_enum_double(struct snd_kcontrol *kcontrol,
608c2ecf20Sopenharmony_ci	struct snd_ctl_elem_value *ucontrol)
618c2ecf20Sopenharmony_ci{
628c2ecf20Sopenharmony_ci	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
638c2ecf20Sopenharmony_ci	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
648c2ecf20Sopenharmony_ci	unsigned int val, item;
658c2ecf20Sopenharmony_ci	unsigned int reg_val;
668c2ecf20Sopenharmony_ci
678c2ecf20Sopenharmony_ci	reg_val = snd_soc_component_read(component, e->reg);
688c2ecf20Sopenharmony_ci	val = (reg_val >> e->shift_l) & e->mask;
698c2ecf20Sopenharmony_ci	item = snd_soc_enum_val_to_item(e, val);
708c2ecf20Sopenharmony_ci	ucontrol->value.enumerated.item[0] = item;
718c2ecf20Sopenharmony_ci	if (e->shift_l != e->shift_r) {
728c2ecf20Sopenharmony_ci		val = (reg_val >> e->shift_r) & e->mask;
738c2ecf20Sopenharmony_ci		item = snd_soc_enum_val_to_item(e, val);
748c2ecf20Sopenharmony_ci		ucontrol->value.enumerated.item[1] = item;
758c2ecf20Sopenharmony_ci	}
768c2ecf20Sopenharmony_ci
778c2ecf20Sopenharmony_ci	return 0;
788c2ecf20Sopenharmony_ci}
798c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(snd_soc_get_enum_double);
808c2ecf20Sopenharmony_ci
818c2ecf20Sopenharmony_ci/**
828c2ecf20Sopenharmony_ci * snd_soc_put_enum_double - enumerated double mixer put callback
838c2ecf20Sopenharmony_ci * @kcontrol: mixer control
848c2ecf20Sopenharmony_ci * @ucontrol: control element information
858c2ecf20Sopenharmony_ci *
868c2ecf20Sopenharmony_ci * Callback to set the value of a double enumerated mixer.
878c2ecf20Sopenharmony_ci *
888c2ecf20Sopenharmony_ci * Returns 0 for success.
898c2ecf20Sopenharmony_ci */
908c2ecf20Sopenharmony_ciint snd_soc_put_enum_double(struct snd_kcontrol *kcontrol,
918c2ecf20Sopenharmony_ci	struct snd_ctl_elem_value *ucontrol)
928c2ecf20Sopenharmony_ci{
938c2ecf20Sopenharmony_ci	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
948c2ecf20Sopenharmony_ci	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
958c2ecf20Sopenharmony_ci	unsigned int *item = ucontrol->value.enumerated.item;
968c2ecf20Sopenharmony_ci	unsigned int val;
978c2ecf20Sopenharmony_ci	unsigned int mask;
988c2ecf20Sopenharmony_ci
998c2ecf20Sopenharmony_ci	if (item[0] >= e->items)
1008c2ecf20Sopenharmony_ci		return -EINVAL;
1018c2ecf20Sopenharmony_ci	val = snd_soc_enum_item_to_val(e, item[0]) << e->shift_l;
1028c2ecf20Sopenharmony_ci	mask = e->mask << e->shift_l;
1038c2ecf20Sopenharmony_ci	if (e->shift_l != e->shift_r) {
1048c2ecf20Sopenharmony_ci		if (item[1] >= e->items)
1058c2ecf20Sopenharmony_ci			return -EINVAL;
1068c2ecf20Sopenharmony_ci		val |= snd_soc_enum_item_to_val(e, item[1]) << e->shift_r;
1078c2ecf20Sopenharmony_ci		mask |= e->mask << e->shift_r;
1088c2ecf20Sopenharmony_ci	}
1098c2ecf20Sopenharmony_ci
1108c2ecf20Sopenharmony_ci	return snd_soc_component_update_bits(component, e->reg, mask, val);
1118c2ecf20Sopenharmony_ci}
1128c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(snd_soc_put_enum_double);
1138c2ecf20Sopenharmony_ci
1148c2ecf20Sopenharmony_ci/**
1158c2ecf20Sopenharmony_ci * snd_soc_read_signed - Read a codec register and interpret as signed value
1168c2ecf20Sopenharmony_ci * @component: component
1178c2ecf20Sopenharmony_ci * @reg: Register to read
1188c2ecf20Sopenharmony_ci * @mask: Mask to use after shifting the register value
1198c2ecf20Sopenharmony_ci * @shift: Right shift of register value
1208c2ecf20Sopenharmony_ci * @sign_bit: Bit that describes if a number is negative or not.
1218c2ecf20Sopenharmony_ci * @signed_val: Pointer to where the read value should be stored
1228c2ecf20Sopenharmony_ci *
1238c2ecf20Sopenharmony_ci * This functions reads a codec register. The register value is shifted right
1248c2ecf20Sopenharmony_ci * by 'shift' bits and masked with the given 'mask'. Afterwards it translates
1258c2ecf20Sopenharmony_ci * the given registervalue into a signed integer if sign_bit is non-zero.
1268c2ecf20Sopenharmony_ci *
1278c2ecf20Sopenharmony_ci * Returns 0 on sucess, otherwise an error value
1288c2ecf20Sopenharmony_ci */
1298c2ecf20Sopenharmony_cistatic int snd_soc_read_signed(struct snd_soc_component *component,
1308c2ecf20Sopenharmony_ci	unsigned int reg, unsigned int mask, unsigned int shift,
1318c2ecf20Sopenharmony_ci	unsigned int sign_bit, int *signed_val)
1328c2ecf20Sopenharmony_ci{
1338c2ecf20Sopenharmony_ci	int ret;
1348c2ecf20Sopenharmony_ci	unsigned int val;
1358c2ecf20Sopenharmony_ci
1368c2ecf20Sopenharmony_ci	val = snd_soc_component_read(component, reg);
1378c2ecf20Sopenharmony_ci	val = (val >> shift) & mask;
1388c2ecf20Sopenharmony_ci
1398c2ecf20Sopenharmony_ci	if (!sign_bit) {
1408c2ecf20Sopenharmony_ci		*signed_val = val;
1418c2ecf20Sopenharmony_ci		return 0;
1428c2ecf20Sopenharmony_ci	}
1438c2ecf20Sopenharmony_ci
1448c2ecf20Sopenharmony_ci	/* non-negative number */
1458c2ecf20Sopenharmony_ci	if (!(val & BIT(sign_bit))) {
1468c2ecf20Sopenharmony_ci		*signed_val = val;
1478c2ecf20Sopenharmony_ci		return 0;
1488c2ecf20Sopenharmony_ci	}
1498c2ecf20Sopenharmony_ci
1508c2ecf20Sopenharmony_ci	ret = val;
1518c2ecf20Sopenharmony_ci
1528c2ecf20Sopenharmony_ci	/*
1538c2ecf20Sopenharmony_ci	 * The register most probably does not contain a full-sized int.
1548c2ecf20Sopenharmony_ci	 * Instead we have an arbitrary number of bits in a signed
1558c2ecf20Sopenharmony_ci	 * representation which has to be translated into a full-sized int.
1568c2ecf20Sopenharmony_ci	 * This is done by filling up all bits above the sign-bit.
1578c2ecf20Sopenharmony_ci	 */
1588c2ecf20Sopenharmony_ci	ret |= ~((int)(BIT(sign_bit) - 1));
1598c2ecf20Sopenharmony_ci
1608c2ecf20Sopenharmony_ci	*signed_val = ret;
1618c2ecf20Sopenharmony_ci
1628c2ecf20Sopenharmony_ci	return 0;
1638c2ecf20Sopenharmony_ci}
1648c2ecf20Sopenharmony_ci
1658c2ecf20Sopenharmony_ci/**
1668c2ecf20Sopenharmony_ci * snd_soc_info_volsw - single mixer info callback
1678c2ecf20Sopenharmony_ci * @kcontrol: mixer control
1688c2ecf20Sopenharmony_ci * @uinfo: control element information
1698c2ecf20Sopenharmony_ci *
1708c2ecf20Sopenharmony_ci * Callback to provide information about a single mixer control, or a double
1718c2ecf20Sopenharmony_ci * mixer control that spans 2 registers.
1728c2ecf20Sopenharmony_ci *
1738c2ecf20Sopenharmony_ci * Returns 0 for success.
1748c2ecf20Sopenharmony_ci */
1758c2ecf20Sopenharmony_ciint snd_soc_info_volsw(struct snd_kcontrol *kcontrol,
1768c2ecf20Sopenharmony_ci	struct snd_ctl_elem_info *uinfo)
1778c2ecf20Sopenharmony_ci{
1788c2ecf20Sopenharmony_ci	struct soc_mixer_control *mc =
1798c2ecf20Sopenharmony_ci		(struct soc_mixer_control *)kcontrol->private_value;
1808c2ecf20Sopenharmony_ci	int platform_max;
1818c2ecf20Sopenharmony_ci
1828c2ecf20Sopenharmony_ci	if (!mc->platform_max)
1838c2ecf20Sopenharmony_ci		mc->platform_max = mc->max;
1848c2ecf20Sopenharmony_ci	platform_max = mc->platform_max;
1858c2ecf20Sopenharmony_ci
1868c2ecf20Sopenharmony_ci	if (platform_max == 1 && !strstr(kcontrol->id.name, " Volume"))
1878c2ecf20Sopenharmony_ci		uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
1888c2ecf20Sopenharmony_ci	else
1898c2ecf20Sopenharmony_ci		uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1908c2ecf20Sopenharmony_ci
1918c2ecf20Sopenharmony_ci	uinfo->count = snd_soc_volsw_is_stereo(mc) ? 2 : 1;
1928c2ecf20Sopenharmony_ci	uinfo->value.integer.min = 0;
1938c2ecf20Sopenharmony_ci	uinfo->value.integer.max = platform_max - mc->min;
1948c2ecf20Sopenharmony_ci	return 0;
1958c2ecf20Sopenharmony_ci}
1968c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(snd_soc_info_volsw);
1978c2ecf20Sopenharmony_ci
1988c2ecf20Sopenharmony_ci/**
1998c2ecf20Sopenharmony_ci * snd_soc_info_volsw_sx - Mixer info callback for SX TLV controls
2008c2ecf20Sopenharmony_ci * @kcontrol: mixer control
2018c2ecf20Sopenharmony_ci * @uinfo: control element information
2028c2ecf20Sopenharmony_ci *
2038c2ecf20Sopenharmony_ci * Callback to provide information about a single mixer control, or a double
2048c2ecf20Sopenharmony_ci * mixer control that spans 2 registers of the SX TLV type. SX TLV controls
2058c2ecf20Sopenharmony_ci * have a range that represents both positive and negative values either side
2068c2ecf20Sopenharmony_ci * of zero but without a sign bit.
2078c2ecf20Sopenharmony_ci *
2088c2ecf20Sopenharmony_ci * Returns 0 for success.
2098c2ecf20Sopenharmony_ci */
2108c2ecf20Sopenharmony_ciint snd_soc_info_volsw_sx(struct snd_kcontrol *kcontrol,
2118c2ecf20Sopenharmony_ci			  struct snd_ctl_elem_info *uinfo)
2128c2ecf20Sopenharmony_ci{
2138c2ecf20Sopenharmony_ci	struct soc_mixer_control *mc =
2148c2ecf20Sopenharmony_ci		(struct soc_mixer_control *)kcontrol->private_value;
2158c2ecf20Sopenharmony_ci
2168c2ecf20Sopenharmony_ci	snd_soc_info_volsw(kcontrol, uinfo);
2178c2ecf20Sopenharmony_ci	/* Max represents the number of levels in an SX control not the
2188c2ecf20Sopenharmony_ci	 * maximum value, so add the minimum value back on
2198c2ecf20Sopenharmony_ci	 */
2208c2ecf20Sopenharmony_ci	uinfo->value.integer.max += mc->min;
2218c2ecf20Sopenharmony_ci
2228c2ecf20Sopenharmony_ci	return 0;
2238c2ecf20Sopenharmony_ci}
2248c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(snd_soc_info_volsw_sx);
2258c2ecf20Sopenharmony_ci
2268c2ecf20Sopenharmony_ci/**
2278c2ecf20Sopenharmony_ci * snd_soc_get_volsw - single mixer get callback
2288c2ecf20Sopenharmony_ci * @kcontrol: mixer control
2298c2ecf20Sopenharmony_ci * @ucontrol: control element information
2308c2ecf20Sopenharmony_ci *
2318c2ecf20Sopenharmony_ci * Callback to get the value of a single mixer control, or a double mixer
2328c2ecf20Sopenharmony_ci * control that spans 2 registers.
2338c2ecf20Sopenharmony_ci *
2348c2ecf20Sopenharmony_ci * Returns 0 for success.
2358c2ecf20Sopenharmony_ci */
2368c2ecf20Sopenharmony_ciint snd_soc_get_volsw(struct snd_kcontrol *kcontrol,
2378c2ecf20Sopenharmony_ci	struct snd_ctl_elem_value *ucontrol)
2388c2ecf20Sopenharmony_ci{
2398c2ecf20Sopenharmony_ci	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
2408c2ecf20Sopenharmony_ci	struct soc_mixer_control *mc =
2418c2ecf20Sopenharmony_ci		(struct soc_mixer_control *)kcontrol->private_value;
2428c2ecf20Sopenharmony_ci	unsigned int reg = mc->reg;
2438c2ecf20Sopenharmony_ci	unsigned int reg2 = mc->rreg;
2448c2ecf20Sopenharmony_ci	unsigned int shift = mc->shift;
2458c2ecf20Sopenharmony_ci	unsigned int rshift = mc->rshift;
2468c2ecf20Sopenharmony_ci	int max = mc->max;
2478c2ecf20Sopenharmony_ci	int min = mc->min;
2488c2ecf20Sopenharmony_ci	int sign_bit = mc->sign_bit;
2498c2ecf20Sopenharmony_ci	unsigned int mask = (1 << fls(max)) - 1;
2508c2ecf20Sopenharmony_ci	unsigned int invert = mc->invert;
2518c2ecf20Sopenharmony_ci	int val;
2528c2ecf20Sopenharmony_ci	int ret;
2538c2ecf20Sopenharmony_ci
2548c2ecf20Sopenharmony_ci	if (sign_bit)
2558c2ecf20Sopenharmony_ci		mask = BIT(sign_bit + 1) - 1;
2568c2ecf20Sopenharmony_ci
2578c2ecf20Sopenharmony_ci	ret = snd_soc_read_signed(component, reg, mask, shift, sign_bit, &val);
2588c2ecf20Sopenharmony_ci	if (ret)
2598c2ecf20Sopenharmony_ci		return ret;
2608c2ecf20Sopenharmony_ci
2618c2ecf20Sopenharmony_ci	ucontrol->value.integer.value[0] = val - min;
2628c2ecf20Sopenharmony_ci	if (invert)
2638c2ecf20Sopenharmony_ci		ucontrol->value.integer.value[0] =
2648c2ecf20Sopenharmony_ci			max - ucontrol->value.integer.value[0];
2658c2ecf20Sopenharmony_ci
2668c2ecf20Sopenharmony_ci	if (snd_soc_volsw_is_stereo(mc)) {
2678c2ecf20Sopenharmony_ci		if (reg == reg2)
2688c2ecf20Sopenharmony_ci			ret = snd_soc_read_signed(component, reg, mask, rshift,
2698c2ecf20Sopenharmony_ci				sign_bit, &val);
2708c2ecf20Sopenharmony_ci		else
2718c2ecf20Sopenharmony_ci			ret = snd_soc_read_signed(component, reg2, mask, shift,
2728c2ecf20Sopenharmony_ci				sign_bit, &val);
2738c2ecf20Sopenharmony_ci		if (ret)
2748c2ecf20Sopenharmony_ci			return ret;
2758c2ecf20Sopenharmony_ci
2768c2ecf20Sopenharmony_ci		ucontrol->value.integer.value[1] = val - min;
2778c2ecf20Sopenharmony_ci		if (invert)
2788c2ecf20Sopenharmony_ci			ucontrol->value.integer.value[1] =
2798c2ecf20Sopenharmony_ci				max - ucontrol->value.integer.value[1];
2808c2ecf20Sopenharmony_ci	}
2818c2ecf20Sopenharmony_ci
2828c2ecf20Sopenharmony_ci	return 0;
2838c2ecf20Sopenharmony_ci}
2848c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(snd_soc_get_volsw);
2858c2ecf20Sopenharmony_ci
2868c2ecf20Sopenharmony_ci/**
2878c2ecf20Sopenharmony_ci * snd_soc_put_volsw - single mixer put callback
2888c2ecf20Sopenharmony_ci * @kcontrol: mixer control
2898c2ecf20Sopenharmony_ci * @ucontrol: control element information
2908c2ecf20Sopenharmony_ci *
2918c2ecf20Sopenharmony_ci * Callback to set the value of a single mixer control, or a double mixer
2928c2ecf20Sopenharmony_ci * control that spans 2 registers.
2938c2ecf20Sopenharmony_ci *
2948c2ecf20Sopenharmony_ci * Returns 0 for success.
2958c2ecf20Sopenharmony_ci */
2968c2ecf20Sopenharmony_ciint snd_soc_put_volsw(struct snd_kcontrol *kcontrol,
2978c2ecf20Sopenharmony_ci	struct snd_ctl_elem_value *ucontrol)
2988c2ecf20Sopenharmony_ci{
2998c2ecf20Sopenharmony_ci	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
3008c2ecf20Sopenharmony_ci	struct soc_mixer_control *mc =
3018c2ecf20Sopenharmony_ci		(struct soc_mixer_control *)kcontrol->private_value;
3028c2ecf20Sopenharmony_ci	unsigned int reg = mc->reg;
3038c2ecf20Sopenharmony_ci	unsigned int reg2 = mc->rreg;
3048c2ecf20Sopenharmony_ci	unsigned int shift = mc->shift;
3058c2ecf20Sopenharmony_ci	unsigned int rshift = mc->rshift;
3068c2ecf20Sopenharmony_ci	int max = mc->max;
3078c2ecf20Sopenharmony_ci	int min = mc->min;
3088c2ecf20Sopenharmony_ci	unsigned int sign_bit = mc->sign_bit;
3098c2ecf20Sopenharmony_ci	unsigned int mask = (1 << fls(max)) - 1;
3108c2ecf20Sopenharmony_ci	unsigned int invert = mc->invert;
3118c2ecf20Sopenharmony_ci	int err, ret;
3128c2ecf20Sopenharmony_ci	bool type_2r = false;
3138c2ecf20Sopenharmony_ci	unsigned int val2 = 0;
3148c2ecf20Sopenharmony_ci	unsigned int val, val_mask;
3158c2ecf20Sopenharmony_ci
3168c2ecf20Sopenharmony_ci	if (sign_bit)
3178c2ecf20Sopenharmony_ci		mask = BIT(sign_bit + 1) - 1;
3188c2ecf20Sopenharmony_ci
3198c2ecf20Sopenharmony_ci	val = ucontrol->value.integer.value[0];
3208c2ecf20Sopenharmony_ci	if (mc->platform_max && ((int)val + min) > mc->platform_max)
3218c2ecf20Sopenharmony_ci		return -EINVAL;
3228c2ecf20Sopenharmony_ci	if (val > max - min)
3238c2ecf20Sopenharmony_ci		return -EINVAL;
3248c2ecf20Sopenharmony_ci	if (val < 0)
3258c2ecf20Sopenharmony_ci		return -EINVAL;
3268c2ecf20Sopenharmony_ci	val = (val + min) & mask;
3278c2ecf20Sopenharmony_ci	if (invert)
3288c2ecf20Sopenharmony_ci		val = max - val;
3298c2ecf20Sopenharmony_ci	val_mask = mask << shift;
3308c2ecf20Sopenharmony_ci	val = val << shift;
3318c2ecf20Sopenharmony_ci	if (snd_soc_volsw_is_stereo(mc)) {
3328c2ecf20Sopenharmony_ci		val2 = ucontrol->value.integer.value[1];
3338c2ecf20Sopenharmony_ci		if (mc->platform_max && ((int)val2 + min) > mc->platform_max)
3348c2ecf20Sopenharmony_ci			return -EINVAL;
3358c2ecf20Sopenharmony_ci		if (val2 > max - min)
3368c2ecf20Sopenharmony_ci			return -EINVAL;
3378c2ecf20Sopenharmony_ci		if (val2 < 0)
3388c2ecf20Sopenharmony_ci			return -EINVAL;
3398c2ecf20Sopenharmony_ci		val2 = (val2 + min) & mask;
3408c2ecf20Sopenharmony_ci		if (invert)
3418c2ecf20Sopenharmony_ci			val2 = max - val2;
3428c2ecf20Sopenharmony_ci		if (reg == reg2) {
3438c2ecf20Sopenharmony_ci			val_mask |= mask << rshift;
3448c2ecf20Sopenharmony_ci			val |= val2 << rshift;
3458c2ecf20Sopenharmony_ci		} else {
3468c2ecf20Sopenharmony_ci			val2 = val2 << shift;
3478c2ecf20Sopenharmony_ci			type_2r = true;
3488c2ecf20Sopenharmony_ci		}
3498c2ecf20Sopenharmony_ci	}
3508c2ecf20Sopenharmony_ci	err = snd_soc_component_update_bits(component, reg, val_mask, val);
3518c2ecf20Sopenharmony_ci	if (err < 0)
3528c2ecf20Sopenharmony_ci		return err;
3538c2ecf20Sopenharmony_ci	ret = err;
3548c2ecf20Sopenharmony_ci
3558c2ecf20Sopenharmony_ci	if (type_2r) {
3568c2ecf20Sopenharmony_ci		err = snd_soc_component_update_bits(component, reg2, val_mask,
3578c2ecf20Sopenharmony_ci						    val2);
3588c2ecf20Sopenharmony_ci		/* Don't discard any error code or drop change flag */
3598c2ecf20Sopenharmony_ci		if (ret == 0 || err < 0) {
3608c2ecf20Sopenharmony_ci			ret = err;
3618c2ecf20Sopenharmony_ci		}
3628c2ecf20Sopenharmony_ci	}
3638c2ecf20Sopenharmony_ci
3648c2ecf20Sopenharmony_ci	return ret;
3658c2ecf20Sopenharmony_ci}
3668c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(snd_soc_put_volsw);
3678c2ecf20Sopenharmony_ci
3688c2ecf20Sopenharmony_ci/**
3698c2ecf20Sopenharmony_ci * snd_soc_get_volsw_sx - single mixer get callback
3708c2ecf20Sopenharmony_ci * @kcontrol: mixer control
3718c2ecf20Sopenharmony_ci * @ucontrol: control element information
3728c2ecf20Sopenharmony_ci *
3738c2ecf20Sopenharmony_ci * Callback to get the value of a single mixer control, or a double mixer
3748c2ecf20Sopenharmony_ci * control that spans 2 registers.
3758c2ecf20Sopenharmony_ci *
3768c2ecf20Sopenharmony_ci * Returns 0 for success.
3778c2ecf20Sopenharmony_ci */
3788c2ecf20Sopenharmony_ciint snd_soc_get_volsw_sx(struct snd_kcontrol *kcontrol,
3798c2ecf20Sopenharmony_ci		      struct snd_ctl_elem_value *ucontrol)
3808c2ecf20Sopenharmony_ci{
3818c2ecf20Sopenharmony_ci	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
3828c2ecf20Sopenharmony_ci	struct soc_mixer_control *mc =
3838c2ecf20Sopenharmony_ci	    (struct soc_mixer_control *)kcontrol->private_value;
3848c2ecf20Sopenharmony_ci	unsigned int reg = mc->reg;
3858c2ecf20Sopenharmony_ci	unsigned int reg2 = mc->rreg;
3868c2ecf20Sopenharmony_ci	unsigned int shift = mc->shift;
3878c2ecf20Sopenharmony_ci	unsigned int rshift = mc->rshift;
3888c2ecf20Sopenharmony_ci	int max = mc->max;
3898c2ecf20Sopenharmony_ci	int min = mc->min;
3908c2ecf20Sopenharmony_ci	unsigned int mask = (1U << (fls(min + max) - 1)) - 1;
3918c2ecf20Sopenharmony_ci	unsigned int val;
3928c2ecf20Sopenharmony_ci
3938c2ecf20Sopenharmony_ci	val = snd_soc_component_read(component, reg);
3948c2ecf20Sopenharmony_ci	ucontrol->value.integer.value[0] = ((val >> shift) - min) & mask;
3958c2ecf20Sopenharmony_ci
3968c2ecf20Sopenharmony_ci	if (snd_soc_volsw_is_stereo(mc)) {
3978c2ecf20Sopenharmony_ci		val = snd_soc_component_read(component, reg2);
3988c2ecf20Sopenharmony_ci		val = ((val >> rshift) - min) & mask;
3998c2ecf20Sopenharmony_ci		ucontrol->value.integer.value[1] = val;
4008c2ecf20Sopenharmony_ci	}
4018c2ecf20Sopenharmony_ci
4028c2ecf20Sopenharmony_ci	return 0;
4038c2ecf20Sopenharmony_ci}
4048c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(snd_soc_get_volsw_sx);
4058c2ecf20Sopenharmony_ci
4068c2ecf20Sopenharmony_ci/**
4078c2ecf20Sopenharmony_ci * snd_soc_put_volsw_sx - double mixer set callback
4088c2ecf20Sopenharmony_ci * @kcontrol: mixer control
4098c2ecf20Sopenharmony_ci * @ucontrol: control element information
4108c2ecf20Sopenharmony_ci *
4118c2ecf20Sopenharmony_ci * Callback to set the value of a double mixer control that spans 2 registers.
4128c2ecf20Sopenharmony_ci *
4138c2ecf20Sopenharmony_ci * Returns 0 for success.
4148c2ecf20Sopenharmony_ci */
4158c2ecf20Sopenharmony_ciint snd_soc_put_volsw_sx(struct snd_kcontrol *kcontrol,
4168c2ecf20Sopenharmony_ci			 struct snd_ctl_elem_value *ucontrol)
4178c2ecf20Sopenharmony_ci{
4188c2ecf20Sopenharmony_ci	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
4198c2ecf20Sopenharmony_ci	struct soc_mixer_control *mc =
4208c2ecf20Sopenharmony_ci	    (struct soc_mixer_control *)kcontrol->private_value;
4218c2ecf20Sopenharmony_ci
4228c2ecf20Sopenharmony_ci	unsigned int reg = mc->reg;
4238c2ecf20Sopenharmony_ci	unsigned int reg2 = mc->rreg;
4248c2ecf20Sopenharmony_ci	unsigned int shift = mc->shift;
4258c2ecf20Sopenharmony_ci	unsigned int rshift = mc->rshift;
4268c2ecf20Sopenharmony_ci	int max = mc->max;
4278c2ecf20Sopenharmony_ci	int min = mc->min;
4288c2ecf20Sopenharmony_ci	unsigned int mask = (1U << (fls(min + max) - 1)) - 1;
4298c2ecf20Sopenharmony_ci	int err = 0;
4308c2ecf20Sopenharmony_ci	unsigned int val, val_mask, val2 = 0;
4318c2ecf20Sopenharmony_ci
4328c2ecf20Sopenharmony_ci	val = ucontrol->value.integer.value[0];
4338c2ecf20Sopenharmony_ci	if (mc->platform_max && val > mc->platform_max)
4348c2ecf20Sopenharmony_ci		return -EINVAL;
4358c2ecf20Sopenharmony_ci	if (val > max)
4368c2ecf20Sopenharmony_ci		return -EINVAL;
4378c2ecf20Sopenharmony_ci	if (val < 0)
4388c2ecf20Sopenharmony_ci		return -EINVAL;
4398c2ecf20Sopenharmony_ci	val_mask = mask << shift;
4408c2ecf20Sopenharmony_ci	val = (val + min) & mask;
4418c2ecf20Sopenharmony_ci	val = val << shift;
4428c2ecf20Sopenharmony_ci
4438c2ecf20Sopenharmony_ci	err = snd_soc_component_update_bits(component, reg, val_mask, val);
4448c2ecf20Sopenharmony_ci	if (err < 0)
4458c2ecf20Sopenharmony_ci		return err;
4468c2ecf20Sopenharmony_ci
4478c2ecf20Sopenharmony_ci	if (snd_soc_volsw_is_stereo(mc)) {
4488c2ecf20Sopenharmony_ci		val2 = ucontrol->value.integer.value[1];
4498c2ecf20Sopenharmony_ci
4508c2ecf20Sopenharmony_ci		if (mc->platform_max && val2 > mc->platform_max)
4518c2ecf20Sopenharmony_ci			return -EINVAL;
4528c2ecf20Sopenharmony_ci		if (val2 > max)
4538c2ecf20Sopenharmony_ci			return -EINVAL;
4548c2ecf20Sopenharmony_ci
4558c2ecf20Sopenharmony_ci		val_mask = mask << rshift;
4568c2ecf20Sopenharmony_ci		val2 = (val2 + min) & mask;
4578c2ecf20Sopenharmony_ci		val2 = val2 << rshift;
4588c2ecf20Sopenharmony_ci
4598c2ecf20Sopenharmony_ci		err = snd_soc_component_update_bits(component, reg2, val_mask,
4608c2ecf20Sopenharmony_ci			val2);
4618c2ecf20Sopenharmony_ci	}
4628c2ecf20Sopenharmony_ci	return err;
4638c2ecf20Sopenharmony_ci}
4648c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(snd_soc_put_volsw_sx);
4658c2ecf20Sopenharmony_ci
4668c2ecf20Sopenharmony_ci/**
4678c2ecf20Sopenharmony_ci * snd_soc_info_volsw_range - single mixer info callback with range.
4688c2ecf20Sopenharmony_ci * @kcontrol: mixer control
4698c2ecf20Sopenharmony_ci * @uinfo: control element information
4708c2ecf20Sopenharmony_ci *
4718c2ecf20Sopenharmony_ci * Callback to provide information, within a range, about a single
4728c2ecf20Sopenharmony_ci * mixer control.
4738c2ecf20Sopenharmony_ci *
4748c2ecf20Sopenharmony_ci * returns 0 for success.
4758c2ecf20Sopenharmony_ci */
4768c2ecf20Sopenharmony_ciint snd_soc_info_volsw_range(struct snd_kcontrol *kcontrol,
4778c2ecf20Sopenharmony_ci	struct snd_ctl_elem_info *uinfo)
4788c2ecf20Sopenharmony_ci{
4798c2ecf20Sopenharmony_ci	struct soc_mixer_control *mc =
4808c2ecf20Sopenharmony_ci		(struct soc_mixer_control *)kcontrol->private_value;
4818c2ecf20Sopenharmony_ci	int platform_max;
4828c2ecf20Sopenharmony_ci	int min = mc->min;
4838c2ecf20Sopenharmony_ci
4848c2ecf20Sopenharmony_ci	if (!mc->platform_max)
4858c2ecf20Sopenharmony_ci		mc->platform_max = mc->max;
4868c2ecf20Sopenharmony_ci	platform_max = mc->platform_max;
4878c2ecf20Sopenharmony_ci
4888c2ecf20Sopenharmony_ci	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
4898c2ecf20Sopenharmony_ci	uinfo->count = snd_soc_volsw_is_stereo(mc) ? 2 : 1;
4908c2ecf20Sopenharmony_ci	uinfo->value.integer.min = 0;
4918c2ecf20Sopenharmony_ci	uinfo->value.integer.max = platform_max - min;
4928c2ecf20Sopenharmony_ci
4938c2ecf20Sopenharmony_ci	return 0;
4948c2ecf20Sopenharmony_ci}
4958c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(snd_soc_info_volsw_range);
4968c2ecf20Sopenharmony_ci
4978c2ecf20Sopenharmony_ci/**
4988c2ecf20Sopenharmony_ci * snd_soc_put_volsw_range - single mixer put value callback with range.
4998c2ecf20Sopenharmony_ci * @kcontrol: mixer control
5008c2ecf20Sopenharmony_ci * @ucontrol: control element information
5018c2ecf20Sopenharmony_ci *
5028c2ecf20Sopenharmony_ci * Callback to set the value, within a range, for a single mixer control.
5038c2ecf20Sopenharmony_ci *
5048c2ecf20Sopenharmony_ci * Returns 0 for success.
5058c2ecf20Sopenharmony_ci */
5068c2ecf20Sopenharmony_ciint snd_soc_put_volsw_range(struct snd_kcontrol *kcontrol,
5078c2ecf20Sopenharmony_ci	struct snd_ctl_elem_value *ucontrol)
5088c2ecf20Sopenharmony_ci{
5098c2ecf20Sopenharmony_ci	struct soc_mixer_control *mc =
5108c2ecf20Sopenharmony_ci		(struct soc_mixer_control *)kcontrol->private_value;
5118c2ecf20Sopenharmony_ci	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
5128c2ecf20Sopenharmony_ci	unsigned int reg = mc->reg;
5138c2ecf20Sopenharmony_ci	unsigned int rreg = mc->rreg;
5148c2ecf20Sopenharmony_ci	unsigned int shift = mc->shift;
5158c2ecf20Sopenharmony_ci	int min = mc->min;
5168c2ecf20Sopenharmony_ci	int max = mc->max;
5178c2ecf20Sopenharmony_ci	unsigned int mask = (1 << fls(max)) - 1;
5188c2ecf20Sopenharmony_ci	unsigned int invert = mc->invert;
5198c2ecf20Sopenharmony_ci	unsigned int val, val_mask;
5208c2ecf20Sopenharmony_ci	int err, ret, tmp;
5218c2ecf20Sopenharmony_ci
5228c2ecf20Sopenharmony_ci	tmp = ucontrol->value.integer.value[0];
5238c2ecf20Sopenharmony_ci	if (tmp < 0)
5248c2ecf20Sopenharmony_ci		return -EINVAL;
5258c2ecf20Sopenharmony_ci	if (mc->platform_max && tmp > mc->platform_max)
5268c2ecf20Sopenharmony_ci		return -EINVAL;
5278c2ecf20Sopenharmony_ci	if (tmp > mc->max - mc->min)
5288c2ecf20Sopenharmony_ci		return -EINVAL;
5298c2ecf20Sopenharmony_ci
5308c2ecf20Sopenharmony_ci	if (invert)
5318c2ecf20Sopenharmony_ci		val = (max - ucontrol->value.integer.value[0]) & mask;
5328c2ecf20Sopenharmony_ci	else
5338c2ecf20Sopenharmony_ci		val = ((ucontrol->value.integer.value[0] + min) & mask);
5348c2ecf20Sopenharmony_ci	val_mask = mask << shift;
5358c2ecf20Sopenharmony_ci	val = val << shift;
5368c2ecf20Sopenharmony_ci
5378c2ecf20Sopenharmony_ci	err = snd_soc_component_update_bits(component, reg, val_mask, val);
5388c2ecf20Sopenharmony_ci	if (err < 0)
5398c2ecf20Sopenharmony_ci		return err;
5408c2ecf20Sopenharmony_ci	ret = err;
5418c2ecf20Sopenharmony_ci
5428c2ecf20Sopenharmony_ci	if (snd_soc_volsw_is_stereo(mc)) {
5438c2ecf20Sopenharmony_ci		tmp = ucontrol->value.integer.value[1];
5448c2ecf20Sopenharmony_ci		if (tmp < 0)
5458c2ecf20Sopenharmony_ci			return -EINVAL;
5468c2ecf20Sopenharmony_ci		if (mc->platform_max && tmp > mc->platform_max)
5478c2ecf20Sopenharmony_ci			return -EINVAL;
5488c2ecf20Sopenharmony_ci		if (tmp > mc->max - mc->min)
5498c2ecf20Sopenharmony_ci			return -EINVAL;
5508c2ecf20Sopenharmony_ci
5518c2ecf20Sopenharmony_ci		if (invert)
5528c2ecf20Sopenharmony_ci			val = (max - ucontrol->value.integer.value[1]) & mask;
5538c2ecf20Sopenharmony_ci		else
5548c2ecf20Sopenharmony_ci			val = ((ucontrol->value.integer.value[1] + min) & mask);
5558c2ecf20Sopenharmony_ci		val_mask = mask << shift;
5568c2ecf20Sopenharmony_ci		val = val << shift;
5578c2ecf20Sopenharmony_ci
5588c2ecf20Sopenharmony_ci		err = snd_soc_component_update_bits(component, rreg, val_mask,
5598c2ecf20Sopenharmony_ci			val);
5608c2ecf20Sopenharmony_ci		/* Don't discard any error code or drop change flag */
5618c2ecf20Sopenharmony_ci		if (ret == 0 || err < 0) {
5628c2ecf20Sopenharmony_ci			ret = err;
5638c2ecf20Sopenharmony_ci		}
5648c2ecf20Sopenharmony_ci	}
5658c2ecf20Sopenharmony_ci
5668c2ecf20Sopenharmony_ci	return ret;
5678c2ecf20Sopenharmony_ci}
5688c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(snd_soc_put_volsw_range);
5698c2ecf20Sopenharmony_ci
5708c2ecf20Sopenharmony_ci/**
5718c2ecf20Sopenharmony_ci * snd_soc_get_volsw_range - single mixer get callback with range
5728c2ecf20Sopenharmony_ci * @kcontrol: mixer control
5738c2ecf20Sopenharmony_ci * @ucontrol: control element information
5748c2ecf20Sopenharmony_ci *
5758c2ecf20Sopenharmony_ci * Callback to get the value, within a range, of a single mixer control.
5768c2ecf20Sopenharmony_ci *
5778c2ecf20Sopenharmony_ci * Returns 0 for success.
5788c2ecf20Sopenharmony_ci */
5798c2ecf20Sopenharmony_ciint snd_soc_get_volsw_range(struct snd_kcontrol *kcontrol,
5808c2ecf20Sopenharmony_ci	struct snd_ctl_elem_value *ucontrol)
5818c2ecf20Sopenharmony_ci{
5828c2ecf20Sopenharmony_ci	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
5838c2ecf20Sopenharmony_ci	struct soc_mixer_control *mc =
5848c2ecf20Sopenharmony_ci		(struct soc_mixer_control *)kcontrol->private_value;
5858c2ecf20Sopenharmony_ci	unsigned int reg = mc->reg;
5868c2ecf20Sopenharmony_ci	unsigned int rreg = mc->rreg;
5878c2ecf20Sopenharmony_ci	unsigned int shift = mc->shift;
5888c2ecf20Sopenharmony_ci	int min = mc->min;
5898c2ecf20Sopenharmony_ci	int max = mc->max;
5908c2ecf20Sopenharmony_ci	unsigned int mask = (1 << fls(max)) - 1;
5918c2ecf20Sopenharmony_ci	unsigned int invert = mc->invert;
5928c2ecf20Sopenharmony_ci	unsigned int val;
5938c2ecf20Sopenharmony_ci
5948c2ecf20Sopenharmony_ci	val = snd_soc_component_read(component, reg);
5958c2ecf20Sopenharmony_ci	ucontrol->value.integer.value[0] = (val >> shift) & mask;
5968c2ecf20Sopenharmony_ci	if (invert)
5978c2ecf20Sopenharmony_ci		ucontrol->value.integer.value[0] =
5988c2ecf20Sopenharmony_ci			max - ucontrol->value.integer.value[0];
5998c2ecf20Sopenharmony_ci	else
6008c2ecf20Sopenharmony_ci		ucontrol->value.integer.value[0] =
6018c2ecf20Sopenharmony_ci			ucontrol->value.integer.value[0] - min;
6028c2ecf20Sopenharmony_ci
6038c2ecf20Sopenharmony_ci	if (snd_soc_volsw_is_stereo(mc)) {
6048c2ecf20Sopenharmony_ci		val = snd_soc_component_read(component, rreg);
6058c2ecf20Sopenharmony_ci		ucontrol->value.integer.value[1] = (val >> shift) & mask;
6068c2ecf20Sopenharmony_ci		if (invert)
6078c2ecf20Sopenharmony_ci			ucontrol->value.integer.value[1] =
6088c2ecf20Sopenharmony_ci				max - ucontrol->value.integer.value[1];
6098c2ecf20Sopenharmony_ci		else
6108c2ecf20Sopenharmony_ci			ucontrol->value.integer.value[1] =
6118c2ecf20Sopenharmony_ci				ucontrol->value.integer.value[1] - min;
6128c2ecf20Sopenharmony_ci	}
6138c2ecf20Sopenharmony_ci
6148c2ecf20Sopenharmony_ci	return 0;
6158c2ecf20Sopenharmony_ci}
6168c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(snd_soc_get_volsw_range);
6178c2ecf20Sopenharmony_ci
6188c2ecf20Sopenharmony_ci/**
6198c2ecf20Sopenharmony_ci * snd_soc_limit_volume - Set new limit to an existing volume control.
6208c2ecf20Sopenharmony_ci *
6218c2ecf20Sopenharmony_ci * @card: where to look for the control
6228c2ecf20Sopenharmony_ci * @name: Name of the control
6238c2ecf20Sopenharmony_ci * @max: new maximum limit
6248c2ecf20Sopenharmony_ci *
6258c2ecf20Sopenharmony_ci * Return 0 for success, else error.
6268c2ecf20Sopenharmony_ci */
6278c2ecf20Sopenharmony_ciint snd_soc_limit_volume(struct snd_soc_card *card,
6288c2ecf20Sopenharmony_ci	const char *name, int max)
6298c2ecf20Sopenharmony_ci{
6308c2ecf20Sopenharmony_ci	struct snd_kcontrol *kctl;
6318c2ecf20Sopenharmony_ci	struct soc_mixer_control *mc;
6328c2ecf20Sopenharmony_ci	int ret = -EINVAL;
6338c2ecf20Sopenharmony_ci
6348c2ecf20Sopenharmony_ci	/* Sanity check for name and max */
6358c2ecf20Sopenharmony_ci	if (unlikely(!name || max <= 0))
6368c2ecf20Sopenharmony_ci		return -EINVAL;
6378c2ecf20Sopenharmony_ci
6388c2ecf20Sopenharmony_ci	kctl = snd_soc_card_get_kcontrol(card, name);
6398c2ecf20Sopenharmony_ci	if (kctl) {
6408c2ecf20Sopenharmony_ci		mc = (struct soc_mixer_control *)kctl->private_value;
6418c2ecf20Sopenharmony_ci		if (max <= mc->max) {
6428c2ecf20Sopenharmony_ci			mc->platform_max = max;
6438c2ecf20Sopenharmony_ci			ret = 0;
6448c2ecf20Sopenharmony_ci		}
6458c2ecf20Sopenharmony_ci	}
6468c2ecf20Sopenharmony_ci	return ret;
6478c2ecf20Sopenharmony_ci}
6488c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(snd_soc_limit_volume);
6498c2ecf20Sopenharmony_ci
6508c2ecf20Sopenharmony_ciint snd_soc_bytes_info(struct snd_kcontrol *kcontrol,
6518c2ecf20Sopenharmony_ci		       struct snd_ctl_elem_info *uinfo)
6528c2ecf20Sopenharmony_ci{
6538c2ecf20Sopenharmony_ci	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
6548c2ecf20Sopenharmony_ci	struct soc_bytes *params = (void *)kcontrol->private_value;
6558c2ecf20Sopenharmony_ci
6568c2ecf20Sopenharmony_ci	uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
6578c2ecf20Sopenharmony_ci	uinfo->count = params->num_regs * component->val_bytes;
6588c2ecf20Sopenharmony_ci
6598c2ecf20Sopenharmony_ci	return 0;
6608c2ecf20Sopenharmony_ci}
6618c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(snd_soc_bytes_info);
6628c2ecf20Sopenharmony_ci
6638c2ecf20Sopenharmony_ciint snd_soc_bytes_get(struct snd_kcontrol *kcontrol,
6648c2ecf20Sopenharmony_ci		      struct snd_ctl_elem_value *ucontrol)
6658c2ecf20Sopenharmony_ci{
6668c2ecf20Sopenharmony_ci	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
6678c2ecf20Sopenharmony_ci	struct soc_bytes *params = (void *)kcontrol->private_value;
6688c2ecf20Sopenharmony_ci	int ret;
6698c2ecf20Sopenharmony_ci
6708c2ecf20Sopenharmony_ci	if (component->regmap)
6718c2ecf20Sopenharmony_ci		ret = regmap_raw_read(component->regmap, params->base,
6728c2ecf20Sopenharmony_ci				      ucontrol->value.bytes.data,
6738c2ecf20Sopenharmony_ci				      params->num_regs * component->val_bytes);
6748c2ecf20Sopenharmony_ci	else
6758c2ecf20Sopenharmony_ci		ret = -EINVAL;
6768c2ecf20Sopenharmony_ci
6778c2ecf20Sopenharmony_ci	/* Hide any masked bytes to ensure consistent data reporting */
6788c2ecf20Sopenharmony_ci	if (ret == 0 && params->mask) {
6798c2ecf20Sopenharmony_ci		switch (component->val_bytes) {
6808c2ecf20Sopenharmony_ci		case 1:
6818c2ecf20Sopenharmony_ci			ucontrol->value.bytes.data[0] &= ~params->mask;
6828c2ecf20Sopenharmony_ci			break;
6838c2ecf20Sopenharmony_ci		case 2:
6848c2ecf20Sopenharmony_ci			((u16 *)(&ucontrol->value.bytes.data))[0]
6858c2ecf20Sopenharmony_ci				&= cpu_to_be16(~params->mask);
6868c2ecf20Sopenharmony_ci			break;
6878c2ecf20Sopenharmony_ci		case 4:
6888c2ecf20Sopenharmony_ci			((u32 *)(&ucontrol->value.bytes.data))[0]
6898c2ecf20Sopenharmony_ci				&= cpu_to_be32(~params->mask);
6908c2ecf20Sopenharmony_ci			break;
6918c2ecf20Sopenharmony_ci		default:
6928c2ecf20Sopenharmony_ci			return -EINVAL;
6938c2ecf20Sopenharmony_ci		}
6948c2ecf20Sopenharmony_ci	}
6958c2ecf20Sopenharmony_ci
6968c2ecf20Sopenharmony_ci	return ret;
6978c2ecf20Sopenharmony_ci}
6988c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(snd_soc_bytes_get);
6998c2ecf20Sopenharmony_ci
7008c2ecf20Sopenharmony_ciint snd_soc_bytes_put(struct snd_kcontrol *kcontrol,
7018c2ecf20Sopenharmony_ci		      struct snd_ctl_elem_value *ucontrol)
7028c2ecf20Sopenharmony_ci{
7038c2ecf20Sopenharmony_ci	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
7048c2ecf20Sopenharmony_ci	struct soc_bytes *params = (void *)kcontrol->private_value;
7058c2ecf20Sopenharmony_ci	int ret, len;
7068c2ecf20Sopenharmony_ci	unsigned int val, mask;
7078c2ecf20Sopenharmony_ci	void *data;
7088c2ecf20Sopenharmony_ci
7098c2ecf20Sopenharmony_ci	if (!component->regmap || !params->num_regs)
7108c2ecf20Sopenharmony_ci		return -EINVAL;
7118c2ecf20Sopenharmony_ci
7128c2ecf20Sopenharmony_ci	len = params->num_regs * component->val_bytes;
7138c2ecf20Sopenharmony_ci
7148c2ecf20Sopenharmony_ci	data = kmemdup(ucontrol->value.bytes.data, len, GFP_KERNEL | GFP_DMA);
7158c2ecf20Sopenharmony_ci	if (!data)
7168c2ecf20Sopenharmony_ci		return -ENOMEM;
7178c2ecf20Sopenharmony_ci
7188c2ecf20Sopenharmony_ci	/*
7198c2ecf20Sopenharmony_ci	 * If we've got a mask then we need to preserve the register
7208c2ecf20Sopenharmony_ci	 * bits.  We shouldn't modify the incoming data so take a
7218c2ecf20Sopenharmony_ci	 * copy.
7228c2ecf20Sopenharmony_ci	 */
7238c2ecf20Sopenharmony_ci	if (params->mask) {
7248c2ecf20Sopenharmony_ci		ret = regmap_read(component->regmap, params->base, &val);
7258c2ecf20Sopenharmony_ci		if (ret != 0)
7268c2ecf20Sopenharmony_ci			goto out;
7278c2ecf20Sopenharmony_ci
7288c2ecf20Sopenharmony_ci		val &= params->mask;
7298c2ecf20Sopenharmony_ci
7308c2ecf20Sopenharmony_ci		switch (component->val_bytes) {
7318c2ecf20Sopenharmony_ci		case 1:
7328c2ecf20Sopenharmony_ci			((u8 *)data)[0] &= ~params->mask;
7338c2ecf20Sopenharmony_ci			((u8 *)data)[0] |= val;
7348c2ecf20Sopenharmony_ci			break;
7358c2ecf20Sopenharmony_ci		case 2:
7368c2ecf20Sopenharmony_ci			mask = ~params->mask;
7378c2ecf20Sopenharmony_ci			ret = regmap_parse_val(component->regmap,
7388c2ecf20Sopenharmony_ci							&mask, &mask);
7398c2ecf20Sopenharmony_ci			if (ret != 0)
7408c2ecf20Sopenharmony_ci				goto out;
7418c2ecf20Sopenharmony_ci
7428c2ecf20Sopenharmony_ci			((u16 *)data)[0] &= mask;
7438c2ecf20Sopenharmony_ci
7448c2ecf20Sopenharmony_ci			ret = regmap_parse_val(component->regmap,
7458c2ecf20Sopenharmony_ci							&val, &val);
7468c2ecf20Sopenharmony_ci			if (ret != 0)
7478c2ecf20Sopenharmony_ci				goto out;
7488c2ecf20Sopenharmony_ci
7498c2ecf20Sopenharmony_ci			((u16 *)data)[0] |= val;
7508c2ecf20Sopenharmony_ci			break;
7518c2ecf20Sopenharmony_ci		case 4:
7528c2ecf20Sopenharmony_ci			mask = ~params->mask;
7538c2ecf20Sopenharmony_ci			ret = regmap_parse_val(component->regmap,
7548c2ecf20Sopenharmony_ci							&mask, &mask);
7558c2ecf20Sopenharmony_ci			if (ret != 0)
7568c2ecf20Sopenharmony_ci				goto out;
7578c2ecf20Sopenharmony_ci
7588c2ecf20Sopenharmony_ci			((u32 *)data)[0] &= mask;
7598c2ecf20Sopenharmony_ci
7608c2ecf20Sopenharmony_ci			ret = regmap_parse_val(component->regmap,
7618c2ecf20Sopenharmony_ci							&val, &val);
7628c2ecf20Sopenharmony_ci			if (ret != 0)
7638c2ecf20Sopenharmony_ci				goto out;
7648c2ecf20Sopenharmony_ci
7658c2ecf20Sopenharmony_ci			((u32 *)data)[0] |= val;
7668c2ecf20Sopenharmony_ci			break;
7678c2ecf20Sopenharmony_ci		default:
7688c2ecf20Sopenharmony_ci			ret = -EINVAL;
7698c2ecf20Sopenharmony_ci			goto out;
7708c2ecf20Sopenharmony_ci		}
7718c2ecf20Sopenharmony_ci	}
7728c2ecf20Sopenharmony_ci
7738c2ecf20Sopenharmony_ci	ret = regmap_raw_write(component->regmap, params->base,
7748c2ecf20Sopenharmony_ci			       data, len);
7758c2ecf20Sopenharmony_ci
7768c2ecf20Sopenharmony_ciout:
7778c2ecf20Sopenharmony_ci	kfree(data);
7788c2ecf20Sopenharmony_ci
7798c2ecf20Sopenharmony_ci	return ret;
7808c2ecf20Sopenharmony_ci}
7818c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(snd_soc_bytes_put);
7828c2ecf20Sopenharmony_ci
7838c2ecf20Sopenharmony_ciint snd_soc_bytes_info_ext(struct snd_kcontrol *kcontrol,
7848c2ecf20Sopenharmony_ci			struct snd_ctl_elem_info *ucontrol)
7858c2ecf20Sopenharmony_ci{
7868c2ecf20Sopenharmony_ci	struct soc_bytes_ext *params = (void *)kcontrol->private_value;
7878c2ecf20Sopenharmony_ci
7888c2ecf20Sopenharmony_ci	ucontrol->type = SNDRV_CTL_ELEM_TYPE_BYTES;
7898c2ecf20Sopenharmony_ci	ucontrol->count = params->max;
7908c2ecf20Sopenharmony_ci
7918c2ecf20Sopenharmony_ci	return 0;
7928c2ecf20Sopenharmony_ci}
7938c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(snd_soc_bytes_info_ext);
7948c2ecf20Sopenharmony_ci
7958c2ecf20Sopenharmony_ciint snd_soc_bytes_tlv_callback(struct snd_kcontrol *kcontrol, int op_flag,
7968c2ecf20Sopenharmony_ci				unsigned int size, unsigned int __user *tlv)
7978c2ecf20Sopenharmony_ci{
7988c2ecf20Sopenharmony_ci	struct soc_bytes_ext *params = (void *)kcontrol->private_value;
7998c2ecf20Sopenharmony_ci	unsigned int count = size < params->max ? size : params->max;
8008c2ecf20Sopenharmony_ci	int ret = -ENXIO;
8018c2ecf20Sopenharmony_ci
8028c2ecf20Sopenharmony_ci	switch (op_flag) {
8038c2ecf20Sopenharmony_ci	case SNDRV_CTL_TLV_OP_READ:
8048c2ecf20Sopenharmony_ci		if (params->get)
8058c2ecf20Sopenharmony_ci			ret = params->get(kcontrol, tlv, count);
8068c2ecf20Sopenharmony_ci		break;
8078c2ecf20Sopenharmony_ci	case SNDRV_CTL_TLV_OP_WRITE:
8088c2ecf20Sopenharmony_ci		if (params->put)
8098c2ecf20Sopenharmony_ci			ret = params->put(kcontrol, tlv, count);
8108c2ecf20Sopenharmony_ci		break;
8118c2ecf20Sopenharmony_ci	}
8128c2ecf20Sopenharmony_ci	return ret;
8138c2ecf20Sopenharmony_ci}
8148c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(snd_soc_bytes_tlv_callback);
8158c2ecf20Sopenharmony_ci
8168c2ecf20Sopenharmony_ci/**
8178c2ecf20Sopenharmony_ci * snd_soc_info_xr_sx - signed multi register info callback
8188c2ecf20Sopenharmony_ci * @kcontrol: mreg control
8198c2ecf20Sopenharmony_ci * @uinfo: control element information
8208c2ecf20Sopenharmony_ci *
8218c2ecf20Sopenharmony_ci * Callback to provide information of a control that can
8228c2ecf20Sopenharmony_ci * span multiple codec registers which together
8238c2ecf20Sopenharmony_ci * forms a single signed value in a MSB/LSB manner.
8248c2ecf20Sopenharmony_ci *
8258c2ecf20Sopenharmony_ci * Returns 0 for success.
8268c2ecf20Sopenharmony_ci */
8278c2ecf20Sopenharmony_ciint snd_soc_info_xr_sx(struct snd_kcontrol *kcontrol,
8288c2ecf20Sopenharmony_ci	struct snd_ctl_elem_info *uinfo)
8298c2ecf20Sopenharmony_ci{
8308c2ecf20Sopenharmony_ci	struct soc_mreg_control *mc =
8318c2ecf20Sopenharmony_ci		(struct soc_mreg_control *)kcontrol->private_value;
8328c2ecf20Sopenharmony_ci	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
8338c2ecf20Sopenharmony_ci	uinfo->count = 1;
8348c2ecf20Sopenharmony_ci	uinfo->value.integer.min = mc->min;
8358c2ecf20Sopenharmony_ci	uinfo->value.integer.max = mc->max;
8368c2ecf20Sopenharmony_ci
8378c2ecf20Sopenharmony_ci	return 0;
8388c2ecf20Sopenharmony_ci}
8398c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(snd_soc_info_xr_sx);
8408c2ecf20Sopenharmony_ci
8418c2ecf20Sopenharmony_ci/**
8428c2ecf20Sopenharmony_ci * snd_soc_get_xr_sx - signed multi register get callback
8438c2ecf20Sopenharmony_ci * @kcontrol: mreg control
8448c2ecf20Sopenharmony_ci * @ucontrol: control element information
8458c2ecf20Sopenharmony_ci *
8468c2ecf20Sopenharmony_ci * Callback to get the value of a control that can span
8478c2ecf20Sopenharmony_ci * multiple codec registers which together forms a single
8488c2ecf20Sopenharmony_ci * signed value in a MSB/LSB manner. The control supports
8498c2ecf20Sopenharmony_ci * specifying total no of bits used to allow for bitfields
8508c2ecf20Sopenharmony_ci * across the multiple codec registers.
8518c2ecf20Sopenharmony_ci *
8528c2ecf20Sopenharmony_ci * Returns 0 for success.
8538c2ecf20Sopenharmony_ci */
8548c2ecf20Sopenharmony_ciint snd_soc_get_xr_sx(struct snd_kcontrol *kcontrol,
8558c2ecf20Sopenharmony_ci	struct snd_ctl_elem_value *ucontrol)
8568c2ecf20Sopenharmony_ci{
8578c2ecf20Sopenharmony_ci	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
8588c2ecf20Sopenharmony_ci	struct soc_mreg_control *mc =
8598c2ecf20Sopenharmony_ci		(struct soc_mreg_control *)kcontrol->private_value;
8608c2ecf20Sopenharmony_ci	unsigned int regbase = mc->regbase;
8618c2ecf20Sopenharmony_ci	unsigned int regcount = mc->regcount;
8628c2ecf20Sopenharmony_ci	unsigned int regwshift = component->val_bytes * BITS_PER_BYTE;
8638c2ecf20Sopenharmony_ci	unsigned int regwmask = (1UL<<regwshift)-1;
8648c2ecf20Sopenharmony_ci	unsigned int invert = mc->invert;
8658c2ecf20Sopenharmony_ci	unsigned long mask = (1UL<<mc->nbits)-1;
8668c2ecf20Sopenharmony_ci	long min = mc->min;
8678c2ecf20Sopenharmony_ci	long max = mc->max;
8688c2ecf20Sopenharmony_ci	long val = 0;
8698c2ecf20Sopenharmony_ci	unsigned int regval;
8708c2ecf20Sopenharmony_ci	unsigned int i;
8718c2ecf20Sopenharmony_ci
8728c2ecf20Sopenharmony_ci	for (i = 0; i < regcount; i++) {
8738c2ecf20Sopenharmony_ci		regval = snd_soc_component_read(component, regbase+i);
8748c2ecf20Sopenharmony_ci		val |= (regval & regwmask) << (regwshift*(regcount-i-1));
8758c2ecf20Sopenharmony_ci	}
8768c2ecf20Sopenharmony_ci	val &= mask;
8778c2ecf20Sopenharmony_ci	if (min < 0 && val > max)
8788c2ecf20Sopenharmony_ci		val |= ~mask;
8798c2ecf20Sopenharmony_ci	if (invert)
8808c2ecf20Sopenharmony_ci		val = max - val;
8818c2ecf20Sopenharmony_ci	ucontrol->value.integer.value[0] = val;
8828c2ecf20Sopenharmony_ci
8838c2ecf20Sopenharmony_ci	return 0;
8848c2ecf20Sopenharmony_ci}
8858c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(snd_soc_get_xr_sx);
8868c2ecf20Sopenharmony_ci
8878c2ecf20Sopenharmony_ci/**
8888c2ecf20Sopenharmony_ci * snd_soc_put_xr_sx - signed multi register get callback
8898c2ecf20Sopenharmony_ci * @kcontrol: mreg control
8908c2ecf20Sopenharmony_ci * @ucontrol: control element information
8918c2ecf20Sopenharmony_ci *
8928c2ecf20Sopenharmony_ci * Callback to set the value of a control that can span
8938c2ecf20Sopenharmony_ci * multiple codec registers which together forms a single
8948c2ecf20Sopenharmony_ci * signed value in a MSB/LSB manner. The control supports
8958c2ecf20Sopenharmony_ci * specifying total no of bits used to allow for bitfields
8968c2ecf20Sopenharmony_ci * across the multiple codec registers.
8978c2ecf20Sopenharmony_ci *
8988c2ecf20Sopenharmony_ci * Returns 0 for success.
8998c2ecf20Sopenharmony_ci */
9008c2ecf20Sopenharmony_ciint snd_soc_put_xr_sx(struct snd_kcontrol *kcontrol,
9018c2ecf20Sopenharmony_ci	struct snd_ctl_elem_value *ucontrol)
9028c2ecf20Sopenharmony_ci{
9038c2ecf20Sopenharmony_ci	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
9048c2ecf20Sopenharmony_ci	struct soc_mreg_control *mc =
9058c2ecf20Sopenharmony_ci		(struct soc_mreg_control *)kcontrol->private_value;
9068c2ecf20Sopenharmony_ci	unsigned int regbase = mc->regbase;
9078c2ecf20Sopenharmony_ci	unsigned int regcount = mc->regcount;
9088c2ecf20Sopenharmony_ci	unsigned int regwshift = component->val_bytes * BITS_PER_BYTE;
9098c2ecf20Sopenharmony_ci	unsigned int regwmask = (1UL<<regwshift)-1;
9108c2ecf20Sopenharmony_ci	unsigned int invert = mc->invert;
9118c2ecf20Sopenharmony_ci	unsigned long mask = (1UL<<mc->nbits)-1;
9128c2ecf20Sopenharmony_ci	long max = mc->max;
9138c2ecf20Sopenharmony_ci	long val = ucontrol->value.integer.value[0];
9148c2ecf20Sopenharmony_ci	unsigned int i, regval, regmask;
9158c2ecf20Sopenharmony_ci	int err;
9168c2ecf20Sopenharmony_ci
9178c2ecf20Sopenharmony_ci	if (val < mc->min || val > mc->max)
9188c2ecf20Sopenharmony_ci		return -EINVAL;
9198c2ecf20Sopenharmony_ci	if (invert)
9208c2ecf20Sopenharmony_ci		val = max - val;
9218c2ecf20Sopenharmony_ci	val &= mask;
9228c2ecf20Sopenharmony_ci	for (i = 0; i < regcount; i++) {
9238c2ecf20Sopenharmony_ci		regval = (val >> (regwshift*(regcount-i-1))) & regwmask;
9248c2ecf20Sopenharmony_ci		regmask = (mask >> (regwshift*(regcount-i-1))) & regwmask;
9258c2ecf20Sopenharmony_ci		err = snd_soc_component_update_bits(component, regbase+i,
9268c2ecf20Sopenharmony_ci				regmask, regval);
9278c2ecf20Sopenharmony_ci		if (err < 0)
9288c2ecf20Sopenharmony_ci			return err;
9298c2ecf20Sopenharmony_ci	}
9308c2ecf20Sopenharmony_ci
9318c2ecf20Sopenharmony_ci	return 0;
9328c2ecf20Sopenharmony_ci}
9338c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(snd_soc_put_xr_sx);
9348c2ecf20Sopenharmony_ci
9358c2ecf20Sopenharmony_ci/**
9368c2ecf20Sopenharmony_ci * snd_soc_get_strobe - strobe get callback
9378c2ecf20Sopenharmony_ci * @kcontrol: mixer control
9388c2ecf20Sopenharmony_ci * @ucontrol: control element information
9398c2ecf20Sopenharmony_ci *
9408c2ecf20Sopenharmony_ci * Callback get the value of a strobe mixer control.
9418c2ecf20Sopenharmony_ci *
9428c2ecf20Sopenharmony_ci * Returns 0 for success.
9438c2ecf20Sopenharmony_ci */
9448c2ecf20Sopenharmony_ciint snd_soc_get_strobe(struct snd_kcontrol *kcontrol,
9458c2ecf20Sopenharmony_ci	struct snd_ctl_elem_value *ucontrol)
9468c2ecf20Sopenharmony_ci{
9478c2ecf20Sopenharmony_ci	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
9488c2ecf20Sopenharmony_ci	struct soc_mixer_control *mc =
9498c2ecf20Sopenharmony_ci		(struct soc_mixer_control *)kcontrol->private_value;
9508c2ecf20Sopenharmony_ci	unsigned int reg = mc->reg;
9518c2ecf20Sopenharmony_ci	unsigned int shift = mc->shift;
9528c2ecf20Sopenharmony_ci	unsigned int mask = 1 << shift;
9538c2ecf20Sopenharmony_ci	unsigned int invert = mc->invert != 0;
9548c2ecf20Sopenharmony_ci	unsigned int val;
9558c2ecf20Sopenharmony_ci
9568c2ecf20Sopenharmony_ci	val = snd_soc_component_read(component, reg);
9578c2ecf20Sopenharmony_ci	val &= mask;
9588c2ecf20Sopenharmony_ci
9598c2ecf20Sopenharmony_ci	if (shift != 0 && val != 0)
9608c2ecf20Sopenharmony_ci		val = val >> shift;
9618c2ecf20Sopenharmony_ci	ucontrol->value.enumerated.item[0] = val ^ invert;
9628c2ecf20Sopenharmony_ci
9638c2ecf20Sopenharmony_ci	return 0;
9648c2ecf20Sopenharmony_ci}
9658c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(snd_soc_get_strobe);
9668c2ecf20Sopenharmony_ci
9678c2ecf20Sopenharmony_ci/**
9688c2ecf20Sopenharmony_ci * snd_soc_put_strobe - strobe put callback
9698c2ecf20Sopenharmony_ci * @kcontrol: mixer control
9708c2ecf20Sopenharmony_ci * @ucontrol: control element information
9718c2ecf20Sopenharmony_ci *
9728c2ecf20Sopenharmony_ci * Callback strobe a register bit to high then low (or the inverse)
9738c2ecf20Sopenharmony_ci * in one pass of a single mixer enum control.
9748c2ecf20Sopenharmony_ci *
9758c2ecf20Sopenharmony_ci * Returns 1 for success.
9768c2ecf20Sopenharmony_ci */
9778c2ecf20Sopenharmony_ciint snd_soc_put_strobe(struct snd_kcontrol *kcontrol,
9788c2ecf20Sopenharmony_ci	struct snd_ctl_elem_value *ucontrol)
9798c2ecf20Sopenharmony_ci{
9808c2ecf20Sopenharmony_ci	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
9818c2ecf20Sopenharmony_ci	struct soc_mixer_control *mc =
9828c2ecf20Sopenharmony_ci		(struct soc_mixer_control *)kcontrol->private_value;
9838c2ecf20Sopenharmony_ci	unsigned int reg = mc->reg;
9848c2ecf20Sopenharmony_ci	unsigned int shift = mc->shift;
9858c2ecf20Sopenharmony_ci	unsigned int mask = 1 << shift;
9868c2ecf20Sopenharmony_ci	unsigned int invert = mc->invert != 0;
9878c2ecf20Sopenharmony_ci	unsigned int strobe = ucontrol->value.enumerated.item[0] != 0;
9888c2ecf20Sopenharmony_ci	unsigned int val1 = (strobe ^ invert) ? mask : 0;
9898c2ecf20Sopenharmony_ci	unsigned int val2 = (strobe ^ invert) ? 0 : mask;
9908c2ecf20Sopenharmony_ci	int err;
9918c2ecf20Sopenharmony_ci
9928c2ecf20Sopenharmony_ci	err = snd_soc_component_update_bits(component, reg, mask, val1);
9938c2ecf20Sopenharmony_ci	if (err < 0)
9948c2ecf20Sopenharmony_ci		return err;
9958c2ecf20Sopenharmony_ci
9968c2ecf20Sopenharmony_ci	return snd_soc_component_update_bits(component, reg, mask, val2);
9978c2ecf20Sopenharmony_ci}
9988c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(snd_soc_put_strobe);
999