162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0+
262306a36Sopenharmony_ci//
362306a36Sopenharmony_ci// soc-ops.c  --  Generic ASoC operations
462306a36Sopenharmony_ci//
562306a36Sopenharmony_ci// Copyright 2005 Wolfson Microelectronics PLC.
662306a36Sopenharmony_ci// Copyright 2005 Openedhand Ltd.
762306a36Sopenharmony_ci// Copyright (C) 2010 Slimlogic Ltd.
862306a36Sopenharmony_ci// Copyright (C) 2010 Texas Instruments Inc.
962306a36Sopenharmony_ci//
1062306a36Sopenharmony_ci// Author: Liam Girdwood <lrg@slimlogic.co.uk>
1162306a36Sopenharmony_ci//         with code, comments and ideas from :-
1262306a36Sopenharmony_ci//         Richard Purdie <richard@openedhand.com>
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_ci#include <linux/module.h>
1562306a36Sopenharmony_ci#include <linux/moduleparam.h>
1662306a36Sopenharmony_ci#include <linux/init.h>
1762306a36Sopenharmony_ci#include <linux/pm.h>
1862306a36Sopenharmony_ci#include <linux/bitops.h>
1962306a36Sopenharmony_ci#include <linux/ctype.h>
2062306a36Sopenharmony_ci#include <linux/slab.h>
2162306a36Sopenharmony_ci#include <sound/core.h>
2262306a36Sopenharmony_ci#include <sound/jack.h>
2362306a36Sopenharmony_ci#include <sound/pcm.h>
2462306a36Sopenharmony_ci#include <sound/pcm_params.h>
2562306a36Sopenharmony_ci#include <sound/soc.h>
2662306a36Sopenharmony_ci#include <sound/soc-dpcm.h>
2762306a36Sopenharmony_ci#include <sound/initval.h>
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_ci/**
3062306a36Sopenharmony_ci * snd_soc_info_enum_double - enumerated double mixer info callback
3162306a36Sopenharmony_ci * @kcontrol: mixer control
3262306a36Sopenharmony_ci * @uinfo: control element information
3362306a36Sopenharmony_ci *
3462306a36Sopenharmony_ci * Callback to provide information about a double enumerated
3562306a36Sopenharmony_ci * mixer control.
3662306a36Sopenharmony_ci *
3762306a36Sopenharmony_ci * Returns 0 for success.
3862306a36Sopenharmony_ci */
3962306a36Sopenharmony_ciint snd_soc_info_enum_double(struct snd_kcontrol *kcontrol,
4062306a36Sopenharmony_ci	struct snd_ctl_elem_info *uinfo)
4162306a36Sopenharmony_ci{
4262306a36Sopenharmony_ci	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_ci	return snd_ctl_enum_info(uinfo, e->shift_l == e->shift_r ? 1 : 2,
4562306a36Sopenharmony_ci				 e->items, e->texts);
4662306a36Sopenharmony_ci}
4762306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(snd_soc_info_enum_double);
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ci/**
5062306a36Sopenharmony_ci * snd_soc_get_enum_double - enumerated double mixer get callback
5162306a36Sopenharmony_ci * @kcontrol: mixer control
5262306a36Sopenharmony_ci * @ucontrol: control element information
5362306a36Sopenharmony_ci *
5462306a36Sopenharmony_ci * Callback to get the value of a double enumerated mixer.
5562306a36Sopenharmony_ci *
5662306a36Sopenharmony_ci * Returns 0 for success.
5762306a36Sopenharmony_ci */
5862306a36Sopenharmony_ciint snd_soc_get_enum_double(struct snd_kcontrol *kcontrol,
5962306a36Sopenharmony_ci	struct snd_ctl_elem_value *ucontrol)
6062306a36Sopenharmony_ci{
6162306a36Sopenharmony_ci	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
6262306a36Sopenharmony_ci	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
6362306a36Sopenharmony_ci	unsigned int val, item;
6462306a36Sopenharmony_ci	unsigned int reg_val;
6562306a36Sopenharmony_ci
6662306a36Sopenharmony_ci	reg_val = snd_soc_component_read(component, e->reg);
6762306a36Sopenharmony_ci	val = (reg_val >> e->shift_l) & e->mask;
6862306a36Sopenharmony_ci	item = snd_soc_enum_val_to_item(e, val);
6962306a36Sopenharmony_ci	ucontrol->value.enumerated.item[0] = item;
7062306a36Sopenharmony_ci	if (e->shift_l != e->shift_r) {
7162306a36Sopenharmony_ci		val = (reg_val >> e->shift_r) & e->mask;
7262306a36Sopenharmony_ci		item = snd_soc_enum_val_to_item(e, val);
7362306a36Sopenharmony_ci		ucontrol->value.enumerated.item[1] = item;
7462306a36Sopenharmony_ci	}
7562306a36Sopenharmony_ci
7662306a36Sopenharmony_ci	return 0;
7762306a36Sopenharmony_ci}
7862306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(snd_soc_get_enum_double);
7962306a36Sopenharmony_ci
8062306a36Sopenharmony_ci/**
8162306a36Sopenharmony_ci * snd_soc_put_enum_double - enumerated double mixer put callback
8262306a36Sopenharmony_ci * @kcontrol: mixer control
8362306a36Sopenharmony_ci * @ucontrol: control element information
8462306a36Sopenharmony_ci *
8562306a36Sopenharmony_ci * Callback to set the value of a double enumerated mixer.
8662306a36Sopenharmony_ci *
8762306a36Sopenharmony_ci * Returns 0 for success.
8862306a36Sopenharmony_ci */
8962306a36Sopenharmony_ciint snd_soc_put_enum_double(struct snd_kcontrol *kcontrol,
9062306a36Sopenharmony_ci	struct snd_ctl_elem_value *ucontrol)
9162306a36Sopenharmony_ci{
9262306a36Sopenharmony_ci	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
9362306a36Sopenharmony_ci	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
9462306a36Sopenharmony_ci	unsigned int *item = ucontrol->value.enumerated.item;
9562306a36Sopenharmony_ci	unsigned int val;
9662306a36Sopenharmony_ci	unsigned int mask;
9762306a36Sopenharmony_ci
9862306a36Sopenharmony_ci	if (item[0] >= e->items)
9962306a36Sopenharmony_ci		return -EINVAL;
10062306a36Sopenharmony_ci	val = snd_soc_enum_item_to_val(e, item[0]) << e->shift_l;
10162306a36Sopenharmony_ci	mask = e->mask << e->shift_l;
10262306a36Sopenharmony_ci	if (e->shift_l != e->shift_r) {
10362306a36Sopenharmony_ci		if (item[1] >= e->items)
10462306a36Sopenharmony_ci			return -EINVAL;
10562306a36Sopenharmony_ci		val |= snd_soc_enum_item_to_val(e, item[1]) << e->shift_r;
10662306a36Sopenharmony_ci		mask |= e->mask << e->shift_r;
10762306a36Sopenharmony_ci	}
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_ci	return snd_soc_component_update_bits(component, e->reg, mask, val);
11062306a36Sopenharmony_ci}
11162306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(snd_soc_put_enum_double);
11262306a36Sopenharmony_ci
11362306a36Sopenharmony_ci/**
11462306a36Sopenharmony_ci * snd_soc_read_signed - Read a codec register and interpret as signed value
11562306a36Sopenharmony_ci * @component: component
11662306a36Sopenharmony_ci * @reg: Register to read
11762306a36Sopenharmony_ci * @mask: Mask to use after shifting the register value
11862306a36Sopenharmony_ci * @shift: Right shift of register value
11962306a36Sopenharmony_ci * @sign_bit: Bit that describes if a number is negative or not.
12062306a36Sopenharmony_ci * @signed_val: Pointer to where the read value should be stored
12162306a36Sopenharmony_ci *
12262306a36Sopenharmony_ci * This functions reads a codec register. The register value is shifted right
12362306a36Sopenharmony_ci * by 'shift' bits and masked with the given 'mask'. Afterwards it translates
12462306a36Sopenharmony_ci * the given registervalue into a signed integer if sign_bit is non-zero.
12562306a36Sopenharmony_ci *
12662306a36Sopenharmony_ci * Returns 0 on sucess, otherwise an error value
12762306a36Sopenharmony_ci */
12862306a36Sopenharmony_cistatic int snd_soc_read_signed(struct snd_soc_component *component,
12962306a36Sopenharmony_ci	unsigned int reg, unsigned int mask, unsigned int shift,
13062306a36Sopenharmony_ci	unsigned int sign_bit, int *signed_val)
13162306a36Sopenharmony_ci{
13262306a36Sopenharmony_ci	int ret;
13362306a36Sopenharmony_ci	unsigned int val;
13462306a36Sopenharmony_ci
13562306a36Sopenharmony_ci	val = snd_soc_component_read(component, reg);
13662306a36Sopenharmony_ci	val = (val >> shift) & mask;
13762306a36Sopenharmony_ci
13862306a36Sopenharmony_ci	if (!sign_bit) {
13962306a36Sopenharmony_ci		*signed_val = val;
14062306a36Sopenharmony_ci		return 0;
14162306a36Sopenharmony_ci	}
14262306a36Sopenharmony_ci
14362306a36Sopenharmony_ci	/* non-negative number */
14462306a36Sopenharmony_ci	if (!(val & BIT(sign_bit))) {
14562306a36Sopenharmony_ci		*signed_val = val;
14662306a36Sopenharmony_ci		return 0;
14762306a36Sopenharmony_ci	}
14862306a36Sopenharmony_ci
14962306a36Sopenharmony_ci	ret = val;
15062306a36Sopenharmony_ci
15162306a36Sopenharmony_ci	/*
15262306a36Sopenharmony_ci	 * The register most probably does not contain a full-sized int.
15362306a36Sopenharmony_ci	 * Instead we have an arbitrary number of bits in a signed
15462306a36Sopenharmony_ci	 * representation which has to be translated into a full-sized int.
15562306a36Sopenharmony_ci	 * This is done by filling up all bits above the sign-bit.
15662306a36Sopenharmony_ci	 */
15762306a36Sopenharmony_ci	ret |= ~((int)(BIT(sign_bit) - 1));
15862306a36Sopenharmony_ci
15962306a36Sopenharmony_ci	*signed_val = ret;
16062306a36Sopenharmony_ci
16162306a36Sopenharmony_ci	return 0;
16262306a36Sopenharmony_ci}
16362306a36Sopenharmony_ci
16462306a36Sopenharmony_ci/**
16562306a36Sopenharmony_ci * snd_soc_info_volsw - single mixer info callback
16662306a36Sopenharmony_ci * @kcontrol: mixer control
16762306a36Sopenharmony_ci * @uinfo: control element information
16862306a36Sopenharmony_ci *
16962306a36Sopenharmony_ci * Callback to provide information about a single mixer control, or a double
17062306a36Sopenharmony_ci * mixer control that spans 2 registers.
17162306a36Sopenharmony_ci *
17262306a36Sopenharmony_ci * Returns 0 for success.
17362306a36Sopenharmony_ci */
17462306a36Sopenharmony_ciint snd_soc_info_volsw(struct snd_kcontrol *kcontrol,
17562306a36Sopenharmony_ci	struct snd_ctl_elem_info *uinfo)
17662306a36Sopenharmony_ci{
17762306a36Sopenharmony_ci	struct soc_mixer_control *mc =
17862306a36Sopenharmony_ci		(struct soc_mixer_control *)kcontrol->private_value;
17962306a36Sopenharmony_ci	const char *vol_string = NULL;
18062306a36Sopenharmony_ci	int max;
18162306a36Sopenharmony_ci
18262306a36Sopenharmony_ci	max = uinfo->value.integer.max = mc->max - mc->min;
18362306a36Sopenharmony_ci	if (mc->platform_max && mc->platform_max < max)
18462306a36Sopenharmony_ci		max = mc->platform_max;
18562306a36Sopenharmony_ci
18662306a36Sopenharmony_ci	if (max == 1) {
18762306a36Sopenharmony_ci		/* Even two value controls ending in Volume should always be integer */
18862306a36Sopenharmony_ci		vol_string = strstr(kcontrol->id.name, " Volume");
18962306a36Sopenharmony_ci		if (vol_string && !strcmp(vol_string, " Volume"))
19062306a36Sopenharmony_ci			uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
19162306a36Sopenharmony_ci		else
19262306a36Sopenharmony_ci			uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
19362306a36Sopenharmony_ci	} else {
19462306a36Sopenharmony_ci		uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
19562306a36Sopenharmony_ci	}
19662306a36Sopenharmony_ci
19762306a36Sopenharmony_ci	uinfo->count = snd_soc_volsw_is_stereo(mc) ? 2 : 1;
19862306a36Sopenharmony_ci	uinfo->value.integer.min = 0;
19962306a36Sopenharmony_ci	uinfo->value.integer.max = max;
20062306a36Sopenharmony_ci
20162306a36Sopenharmony_ci	return 0;
20262306a36Sopenharmony_ci}
20362306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(snd_soc_info_volsw);
20462306a36Sopenharmony_ci
20562306a36Sopenharmony_ci/**
20662306a36Sopenharmony_ci * snd_soc_info_volsw_sx - Mixer info callback for SX TLV controls
20762306a36Sopenharmony_ci * @kcontrol: mixer control
20862306a36Sopenharmony_ci * @uinfo: control element information
20962306a36Sopenharmony_ci *
21062306a36Sopenharmony_ci * Callback to provide information about a single mixer control, or a double
21162306a36Sopenharmony_ci * mixer control that spans 2 registers of the SX TLV type. SX TLV controls
21262306a36Sopenharmony_ci * have a range that represents both positive and negative values either side
21362306a36Sopenharmony_ci * of zero but without a sign bit. min is the minimum register value, max is
21462306a36Sopenharmony_ci * the number of steps.
21562306a36Sopenharmony_ci *
21662306a36Sopenharmony_ci * Returns 0 for success.
21762306a36Sopenharmony_ci */
21862306a36Sopenharmony_ciint snd_soc_info_volsw_sx(struct snd_kcontrol *kcontrol,
21962306a36Sopenharmony_ci			  struct snd_ctl_elem_info *uinfo)
22062306a36Sopenharmony_ci{
22162306a36Sopenharmony_ci	struct soc_mixer_control *mc =
22262306a36Sopenharmony_ci		(struct soc_mixer_control *)kcontrol->private_value;
22362306a36Sopenharmony_ci	int max;
22462306a36Sopenharmony_ci
22562306a36Sopenharmony_ci	if (mc->platform_max)
22662306a36Sopenharmony_ci		max = mc->platform_max;
22762306a36Sopenharmony_ci	else
22862306a36Sopenharmony_ci		max = mc->max;
22962306a36Sopenharmony_ci
23062306a36Sopenharmony_ci	if (max == 1 && !strstr(kcontrol->id.name, " Volume"))
23162306a36Sopenharmony_ci		uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
23262306a36Sopenharmony_ci	else
23362306a36Sopenharmony_ci		uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
23462306a36Sopenharmony_ci
23562306a36Sopenharmony_ci	uinfo->count = snd_soc_volsw_is_stereo(mc) ? 2 : 1;
23662306a36Sopenharmony_ci	uinfo->value.integer.min = 0;
23762306a36Sopenharmony_ci	uinfo->value.integer.max = max;
23862306a36Sopenharmony_ci
23962306a36Sopenharmony_ci	return 0;
24062306a36Sopenharmony_ci}
24162306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(snd_soc_info_volsw_sx);
24262306a36Sopenharmony_ci
24362306a36Sopenharmony_ci/**
24462306a36Sopenharmony_ci * snd_soc_get_volsw - single mixer get callback
24562306a36Sopenharmony_ci * @kcontrol: mixer control
24662306a36Sopenharmony_ci * @ucontrol: control element information
24762306a36Sopenharmony_ci *
24862306a36Sopenharmony_ci * Callback to get the value of a single mixer control, or a double mixer
24962306a36Sopenharmony_ci * control that spans 2 registers.
25062306a36Sopenharmony_ci *
25162306a36Sopenharmony_ci * Returns 0 for success.
25262306a36Sopenharmony_ci */
25362306a36Sopenharmony_ciint snd_soc_get_volsw(struct snd_kcontrol *kcontrol,
25462306a36Sopenharmony_ci	struct snd_ctl_elem_value *ucontrol)
25562306a36Sopenharmony_ci{
25662306a36Sopenharmony_ci	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
25762306a36Sopenharmony_ci	struct soc_mixer_control *mc =
25862306a36Sopenharmony_ci		(struct soc_mixer_control *)kcontrol->private_value;
25962306a36Sopenharmony_ci	unsigned int reg = mc->reg;
26062306a36Sopenharmony_ci	unsigned int reg2 = mc->rreg;
26162306a36Sopenharmony_ci	unsigned int shift = mc->shift;
26262306a36Sopenharmony_ci	unsigned int rshift = mc->rshift;
26362306a36Sopenharmony_ci	int max = mc->max;
26462306a36Sopenharmony_ci	int min = mc->min;
26562306a36Sopenharmony_ci	int sign_bit = mc->sign_bit;
26662306a36Sopenharmony_ci	unsigned int mask = (1 << fls(max)) - 1;
26762306a36Sopenharmony_ci	unsigned int invert = mc->invert;
26862306a36Sopenharmony_ci	int val;
26962306a36Sopenharmony_ci	int ret;
27062306a36Sopenharmony_ci
27162306a36Sopenharmony_ci	if (sign_bit)
27262306a36Sopenharmony_ci		mask = BIT(sign_bit + 1) - 1;
27362306a36Sopenharmony_ci
27462306a36Sopenharmony_ci	ret = snd_soc_read_signed(component, reg, mask, shift, sign_bit, &val);
27562306a36Sopenharmony_ci	if (ret)
27662306a36Sopenharmony_ci		return ret;
27762306a36Sopenharmony_ci
27862306a36Sopenharmony_ci	ucontrol->value.integer.value[0] = val - min;
27962306a36Sopenharmony_ci	if (invert)
28062306a36Sopenharmony_ci		ucontrol->value.integer.value[0] =
28162306a36Sopenharmony_ci			max - ucontrol->value.integer.value[0];
28262306a36Sopenharmony_ci
28362306a36Sopenharmony_ci	if (snd_soc_volsw_is_stereo(mc)) {
28462306a36Sopenharmony_ci		if (reg == reg2)
28562306a36Sopenharmony_ci			ret = snd_soc_read_signed(component, reg, mask, rshift,
28662306a36Sopenharmony_ci				sign_bit, &val);
28762306a36Sopenharmony_ci		else
28862306a36Sopenharmony_ci			ret = snd_soc_read_signed(component, reg2, mask, shift,
28962306a36Sopenharmony_ci				sign_bit, &val);
29062306a36Sopenharmony_ci		if (ret)
29162306a36Sopenharmony_ci			return ret;
29262306a36Sopenharmony_ci
29362306a36Sopenharmony_ci		ucontrol->value.integer.value[1] = val - min;
29462306a36Sopenharmony_ci		if (invert)
29562306a36Sopenharmony_ci			ucontrol->value.integer.value[1] =
29662306a36Sopenharmony_ci				max - ucontrol->value.integer.value[1];
29762306a36Sopenharmony_ci	}
29862306a36Sopenharmony_ci
29962306a36Sopenharmony_ci	return 0;
30062306a36Sopenharmony_ci}
30162306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(snd_soc_get_volsw);
30262306a36Sopenharmony_ci
30362306a36Sopenharmony_ci/**
30462306a36Sopenharmony_ci * snd_soc_put_volsw - single mixer put callback
30562306a36Sopenharmony_ci * @kcontrol: mixer control
30662306a36Sopenharmony_ci * @ucontrol: control element information
30762306a36Sopenharmony_ci *
30862306a36Sopenharmony_ci * Callback to set the value of a single mixer control, or a double mixer
30962306a36Sopenharmony_ci * control that spans 2 registers.
31062306a36Sopenharmony_ci *
31162306a36Sopenharmony_ci * Returns 0 for success.
31262306a36Sopenharmony_ci */
31362306a36Sopenharmony_ciint snd_soc_put_volsw(struct snd_kcontrol *kcontrol,
31462306a36Sopenharmony_ci	struct snd_ctl_elem_value *ucontrol)
31562306a36Sopenharmony_ci{
31662306a36Sopenharmony_ci	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
31762306a36Sopenharmony_ci	struct soc_mixer_control *mc =
31862306a36Sopenharmony_ci		(struct soc_mixer_control *)kcontrol->private_value;
31962306a36Sopenharmony_ci	unsigned int reg = mc->reg;
32062306a36Sopenharmony_ci	unsigned int reg2 = mc->rreg;
32162306a36Sopenharmony_ci	unsigned int shift = mc->shift;
32262306a36Sopenharmony_ci	unsigned int rshift = mc->rshift;
32362306a36Sopenharmony_ci	int max = mc->max;
32462306a36Sopenharmony_ci	int min = mc->min;
32562306a36Sopenharmony_ci	unsigned int sign_bit = mc->sign_bit;
32662306a36Sopenharmony_ci	unsigned int mask = (1 << fls(max)) - 1;
32762306a36Sopenharmony_ci	unsigned int invert = mc->invert;
32862306a36Sopenharmony_ci	int err, ret;
32962306a36Sopenharmony_ci	bool type_2r = false;
33062306a36Sopenharmony_ci	unsigned int val2 = 0;
33162306a36Sopenharmony_ci	unsigned int val, val_mask;
33262306a36Sopenharmony_ci
33362306a36Sopenharmony_ci	if (sign_bit)
33462306a36Sopenharmony_ci		mask = BIT(sign_bit + 1) - 1;
33562306a36Sopenharmony_ci
33662306a36Sopenharmony_ci	if (ucontrol->value.integer.value[0] < 0)
33762306a36Sopenharmony_ci		return -EINVAL;
33862306a36Sopenharmony_ci	val = ucontrol->value.integer.value[0];
33962306a36Sopenharmony_ci	if (mc->platform_max && ((int)val + min) > mc->platform_max)
34062306a36Sopenharmony_ci		return -EINVAL;
34162306a36Sopenharmony_ci	if (val > max - min)
34262306a36Sopenharmony_ci		return -EINVAL;
34362306a36Sopenharmony_ci	val = (val + min) & mask;
34462306a36Sopenharmony_ci	if (invert)
34562306a36Sopenharmony_ci		val = max - val;
34662306a36Sopenharmony_ci	val_mask = mask << shift;
34762306a36Sopenharmony_ci	val = val << shift;
34862306a36Sopenharmony_ci	if (snd_soc_volsw_is_stereo(mc)) {
34962306a36Sopenharmony_ci		if (ucontrol->value.integer.value[1] < 0)
35062306a36Sopenharmony_ci			return -EINVAL;
35162306a36Sopenharmony_ci		val2 = ucontrol->value.integer.value[1];
35262306a36Sopenharmony_ci		if (mc->platform_max && ((int)val2 + min) > mc->platform_max)
35362306a36Sopenharmony_ci			return -EINVAL;
35462306a36Sopenharmony_ci		if (val2 > max - min)
35562306a36Sopenharmony_ci			return -EINVAL;
35662306a36Sopenharmony_ci		val2 = (val2 + min) & mask;
35762306a36Sopenharmony_ci		if (invert)
35862306a36Sopenharmony_ci			val2 = max - val2;
35962306a36Sopenharmony_ci		if (reg == reg2) {
36062306a36Sopenharmony_ci			val_mask |= mask << rshift;
36162306a36Sopenharmony_ci			val |= val2 << rshift;
36262306a36Sopenharmony_ci		} else {
36362306a36Sopenharmony_ci			val2 = val2 << shift;
36462306a36Sopenharmony_ci			type_2r = true;
36562306a36Sopenharmony_ci		}
36662306a36Sopenharmony_ci	}
36762306a36Sopenharmony_ci	err = snd_soc_component_update_bits(component, reg, val_mask, val);
36862306a36Sopenharmony_ci	if (err < 0)
36962306a36Sopenharmony_ci		return err;
37062306a36Sopenharmony_ci	ret = err;
37162306a36Sopenharmony_ci
37262306a36Sopenharmony_ci	if (type_2r) {
37362306a36Sopenharmony_ci		err = snd_soc_component_update_bits(component, reg2, val_mask,
37462306a36Sopenharmony_ci						    val2);
37562306a36Sopenharmony_ci		/* Don't discard any error code or drop change flag */
37662306a36Sopenharmony_ci		if (ret == 0 || err < 0) {
37762306a36Sopenharmony_ci			ret = err;
37862306a36Sopenharmony_ci		}
37962306a36Sopenharmony_ci	}
38062306a36Sopenharmony_ci
38162306a36Sopenharmony_ci	return ret;
38262306a36Sopenharmony_ci}
38362306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(snd_soc_put_volsw);
38462306a36Sopenharmony_ci
38562306a36Sopenharmony_ci/**
38662306a36Sopenharmony_ci * snd_soc_get_volsw_sx - single mixer get callback
38762306a36Sopenharmony_ci * @kcontrol: mixer control
38862306a36Sopenharmony_ci * @ucontrol: control element information
38962306a36Sopenharmony_ci *
39062306a36Sopenharmony_ci * Callback to get the value of a single mixer control, or a double mixer
39162306a36Sopenharmony_ci * control that spans 2 registers.
39262306a36Sopenharmony_ci *
39362306a36Sopenharmony_ci * Returns 0 for success.
39462306a36Sopenharmony_ci */
39562306a36Sopenharmony_ciint snd_soc_get_volsw_sx(struct snd_kcontrol *kcontrol,
39662306a36Sopenharmony_ci		      struct snd_ctl_elem_value *ucontrol)
39762306a36Sopenharmony_ci{
39862306a36Sopenharmony_ci	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
39962306a36Sopenharmony_ci	struct soc_mixer_control *mc =
40062306a36Sopenharmony_ci	    (struct soc_mixer_control *)kcontrol->private_value;
40162306a36Sopenharmony_ci	unsigned int reg = mc->reg;
40262306a36Sopenharmony_ci	unsigned int reg2 = mc->rreg;
40362306a36Sopenharmony_ci	unsigned int shift = mc->shift;
40462306a36Sopenharmony_ci	unsigned int rshift = mc->rshift;
40562306a36Sopenharmony_ci	int max = mc->max;
40662306a36Sopenharmony_ci	int min = mc->min;
40762306a36Sopenharmony_ci	unsigned int mask = (1U << (fls(min + max) - 1)) - 1;
40862306a36Sopenharmony_ci	unsigned int val;
40962306a36Sopenharmony_ci
41062306a36Sopenharmony_ci	val = snd_soc_component_read(component, reg);
41162306a36Sopenharmony_ci	ucontrol->value.integer.value[0] = ((val >> shift) - min) & mask;
41262306a36Sopenharmony_ci
41362306a36Sopenharmony_ci	if (snd_soc_volsw_is_stereo(mc)) {
41462306a36Sopenharmony_ci		val = snd_soc_component_read(component, reg2);
41562306a36Sopenharmony_ci		val = ((val >> rshift) - min) & mask;
41662306a36Sopenharmony_ci		ucontrol->value.integer.value[1] = val;
41762306a36Sopenharmony_ci	}
41862306a36Sopenharmony_ci
41962306a36Sopenharmony_ci	return 0;
42062306a36Sopenharmony_ci}
42162306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(snd_soc_get_volsw_sx);
42262306a36Sopenharmony_ci
42362306a36Sopenharmony_ci/**
42462306a36Sopenharmony_ci * snd_soc_put_volsw_sx - double mixer set callback
42562306a36Sopenharmony_ci * @kcontrol: mixer control
42662306a36Sopenharmony_ci * @ucontrol: control element information
42762306a36Sopenharmony_ci *
42862306a36Sopenharmony_ci * Callback to set the value of a double mixer control that spans 2 registers.
42962306a36Sopenharmony_ci *
43062306a36Sopenharmony_ci * Returns 0 for success.
43162306a36Sopenharmony_ci */
43262306a36Sopenharmony_ciint snd_soc_put_volsw_sx(struct snd_kcontrol *kcontrol,
43362306a36Sopenharmony_ci			 struct snd_ctl_elem_value *ucontrol)
43462306a36Sopenharmony_ci{
43562306a36Sopenharmony_ci	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
43662306a36Sopenharmony_ci	struct soc_mixer_control *mc =
43762306a36Sopenharmony_ci	    (struct soc_mixer_control *)kcontrol->private_value;
43862306a36Sopenharmony_ci
43962306a36Sopenharmony_ci	unsigned int reg = mc->reg;
44062306a36Sopenharmony_ci	unsigned int reg2 = mc->rreg;
44162306a36Sopenharmony_ci	unsigned int shift = mc->shift;
44262306a36Sopenharmony_ci	unsigned int rshift = mc->rshift;
44362306a36Sopenharmony_ci	int max = mc->max;
44462306a36Sopenharmony_ci	int min = mc->min;
44562306a36Sopenharmony_ci	unsigned int mask = (1U << (fls(min + max) - 1)) - 1;
44662306a36Sopenharmony_ci	int err = 0;
44762306a36Sopenharmony_ci	int ret;
44862306a36Sopenharmony_ci	unsigned int val, val_mask;
44962306a36Sopenharmony_ci
45062306a36Sopenharmony_ci	if (ucontrol->value.integer.value[0] < 0)
45162306a36Sopenharmony_ci		return -EINVAL;
45262306a36Sopenharmony_ci	val = ucontrol->value.integer.value[0];
45362306a36Sopenharmony_ci	if (mc->platform_max && val > mc->platform_max)
45462306a36Sopenharmony_ci		return -EINVAL;
45562306a36Sopenharmony_ci	if (val > max)
45662306a36Sopenharmony_ci		return -EINVAL;
45762306a36Sopenharmony_ci	val_mask = mask << shift;
45862306a36Sopenharmony_ci	val = (val + min) & mask;
45962306a36Sopenharmony_ci	val = val << shift;
46062306a36Sopenharmony_ci
46162306a36Sopenharmony_ci	err = snd_soc_component_update_bits(component, reg, val_mask, val);
46262306a36Sopenharmony_ci	if (err < 0)
46362306a36Sopenharmony_ci		return err;
46462306a36Sopenharmony_ci	ret = err;
46562306a36Sopenharmony_ci
46662306a36Sopenharmony_ci	if (snd_soc_volsw_is_stereo(mc)) {
46762306a36Sopenharmony_ci		unsigned int val2 = ucontrol->value.integer.value[1];
46862306a36Sopenharmony_ci
46962306a36Sopenharmony_ci		if (mc->platform_max && val2 > mc->platform_max)
47062306a36Sopenharmony_ci			return -EINVAL;
47162306a36Sopenharmony_ci		if (val2 > max)
47262306a36Sopenharmony_ci			return -EINVAL;
47362306a36Sopenharmony_ci
47462306a36Sopenharmony_ci		val_mask = mask << rshift;
47562306a36Sopenharmony_ci		val2 = (val2 + min) & mask;
47662306a36Sopenharmony_ci		val2 = val2 << rshift;
47762306a36Sopenharmony_ci
47862306a36Sopenharmony_ci		err = snd_soc_component_update_bits(component, reg2, val_mask,
47962306a36Sopenharmony_ci			val2);
48062306a36Sopenharmony_ci
48162306a36Sopenharmony_ci		/* Don't discard any error code or drop change flag */
48262306a36Sopenharmony_ci		if (ret == 0 || err < 0) {
48362306a36Sopenharmony_ci			ret = err;
48462306a36Sopenharmony_ci		}
48562306a36Sopenharmony_ci	}
48662306a36Sopenharmony_ci	return ret;
48762306a36Sopenharmony_ci}
48862306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(snd_soc_put_volsw_sx);
48962306a36Sopenharmony_ci
49062306a36Sopenharmony_ci/**
49162306a36Sopenharmony_ci * snd_soc_info_volsw_range - single mixer info callback with range.
49262306a36Sopenharmony_ci * @kcontrol: mixer control
49362306a36Sopenharmony_ci * @uinfo: control element information
49462306a36Sopenharmony_ci *
49562306a36Sopenharmony_ci * Callback to provide information, within a range, about a single
49662306a36Sopenharmony_ci * mixer control.
49762306a36Sopenharmony_ci *
49862306a36Sopenharmony_ci * returns 0 for success.
49962306a36Sopenharmony_ci */
50062306a36Sopenharmony_ciint snd_soc_info_volsw_range(struct snd_kcontrol *kcontrol,
50162306a36Sopenharmony_ci	struct snd_ctl_elem_info *uinfo)
50262306a36Sopenharmony_ci{
50362306a36Sopenharmony_ci	struct soc_mixer_control *mc =
50462306a36Sopenharmony_ci		(struct soc_mixer_control *)kcontrol->private_value;
50562306a36Sopenharmony_ci	int platform_max;
50662306a36Sopenharmony_ci	int min = mc->min;
50762306a36Sopenharmony_ci
50862306a36Sopenharmony_ci	if (!mc->platform_max)
50962306a36Sopenharmony_ci		mc->platform_max = mc->max;
51062306a36Sopenharmony_ci	platform_max = mc->platform_max;
51162306a36Sopenharmony_ci
51262306a36Sopenharmony_ci	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
51362306a36Sopenharmony_ci	uinfo->count = snd_soc_volsw_is_stereo(mc) ? 2 : 1;
51462306a36Sopenharmony_ci	uinfo->value.integer.min = 0;
51562306a36Sopenharmony_ci	uinfo->value.integer.max = platform_max - min;
51662306a36Sopenharmony_ci
51762306a36Sopenharmony_ci	return 0;
51862306a36Sopenharmony_ci}
51962306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(snd_soc_info_volsw_range);
52062306a36Sopenharmony_ci
52162306a36Sopenharmony_ci/**
52262306a36Sopenharmony_ci * snd_soc_put_volsw_range - single mixer put value callback with range.
52362306a36Sopenharmony_ci * @kcontrol: mixer control
52462306a36Sopenharmony_ci * @ucontrol: control element information
52562306a36Sopenharmony_ci *
52662306a36Sopenharmony_ci * Callback to set the value, within a range, for a single mixer control.
52762306a36Sopenharmony_ci *
52862306a36Sopenharmony_ci * Returns 0 for success.
52962306a36Sopenharmony_ci */
53062306a36Sopenharmony_ciint snd_soc_put_volsw_range(struct snd_kcontrol *kcontrol,
53162306a36Sopenharmony_ci	struct snd_ctl_elem_value *ucontrol)
53262306a36Sopenharmony_ci{
53362306a36Sopenharmony_ci	struct soc_mixer_control *mc =
53462306a36Sopenharmony_ci		(struct soc_mixer_control *)kcontrol->private_value;
53562306a36Sopenharmony_ci	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
53662306a36Sopenharmony_ci	unsigned int reg = mc->reg;
53762306a36Sopenharmony_ci	unsigned int rreg = mc->rreg;
53862306a36Sopenharmony_ci	unsigned int shift = mc->shift;
53962306a36Sopenharmony_ci	int min = mc->min;
54062306a36Sopenharmony_ci	int max = mc->max;
54162306a36Sopenharmony_ci	unsigned int mask = (1 << fls(max)) - 1;
54262306a36Sopenharmony_ci	unsigned int invert = mc->invert;
54362306a36Sopenharmony_ci	unsigned int val, val_mask;
54462306a36Sopenharmony_ci	int err, ret, tmp;
54562306a36Sopenharmony_ci
54662306a36Sopenharmony_ci	tmp = ucontrol->value.integer.value[0];
54762306a36Sopenharmony_ci	if (tmp < 0)
54862306a36Sopenharmony_ci		return -EINVAL;
54962306a36Sopenharmony_ci	if (mc->platform_max && tmp > mc->platform_max)
55062306a36Sopenharmony_ci		return -EINVAL;
55162306a36Sopenharmony_ci	if (tmp > mc->max - mc->min)
55262306a36Sopenharmony_ci		return -EINVAL;
55362306a36Sopenharmony_ci
55462306a36Sopenharmony_ci	if (invert)
55562306a36Sopenharmony_ci		val = (max - ucontrol->value.integer.value[0]) & mask;
55662306a36Sopenharmony_ci	else
55762306a36Sopenharmony_ci		val = ((ucontrol->value.integer.value[0] + min) & mask);
55862306a36Sopenharmony_ci	val_mask = mask << shift;
55962306a36Sopenharmony_ci	val = val << shift;
56062306a36Sopenharmony_ci
56162306a36Sopenharmony_ci	err = snd_soc_component_update_bits(component, reg, val_mask, val);
56262306a36Sopenharmony_ci	if (err < 0)
56362306a36Sopenharmony_ci		return err;
56462306a36Sopenharmony_ci	ret = err;
56562306a36Sopenharmony_ci
56662306a36Sopenharmony_ci	if (snd_soc_volsw_is_stereo(mc)) {
56762306a36Sopenharmony_ci		tmp = ucontrol->value.integer.value[1];
56862306a36Sopenharmony_ci		if (tmp < 0)
56962306a36Sopenharmony_ci			return -EINVAL;
57062306a36Sopenharmony_ci		if (mc->platform_max && tmp > mc->platform_max)
57162306a36Sopenharmony_ci			return -EINVAL;
57262306a36Sopenharmony_ci		if (tmp > mc->max - mc->min)
57362306a36Sopenharmony_ci			return -EINVAL;
57462306a36Sopenharmony_ci
57562306a36Sopenharmony_ci		if (invert)
57662306a36Sopenharmony_ci			val = (max - ucontrol->value.integer.value[1]) & mask;
57762306a36Sopenharmony_ci		else
57862306a36Sopenharmony_ci			val = ((ucontrol->value.integer.value[1] + min) & mask);
57962306a36Sopenharmony_ci		val_mask = mask << shift;
58062306a36Sopenharmony_ci		val = val << shift;
58162306a36Sopenharmony_ci
58262306a36Sopenharmony_ci		err = snd_soc_component_update_bits(component, rreg, val_mask,
58362306a36Sopenharmony_ci			val);
58462306a36Sopenharmony_ci		/* Don't discard any error code or drop change flag */
58562306a36Sopenharmony_ci		if (ret == 0 || err < 0) {
58662306a36Sopenharmony_ci			ret = err;
58762306a36Sopenharmony_ci		}
58862306a36Sopenharmony_ci	}
58962306a36Sopenharmony_ci
59062306a36Sopenharmony_ci	return ret;
59162306a36Sopenharmony_ci}
59262306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(snd_soc_put_volsw_range);
59362306a36Sopenharmony_ci
59462306a36Sopenharmony_ci/**
59562306a36Sopenharmony_ci * snd_soc_get_volsw_range - single mixer get callback with range
59662306a36Sopenharmony_ci * @kcontrol: mixer control
59762306a36Sopenharmony_ci * @ucontrol: control element information
59862306a36Sopenharmony_ci *
59962306a36Sopenharmony_ci * Callback to get the value, within a range, of a single mixer control.
60062306a36Sopenharmony_ci *
60162306a36Sopenharmony_ci * Returns 0 for success.
60262306a36Sopenharmony_ci */
60362306a36Sopenharmony_ciint snd_soc_get_volsw_range(struct snd_kcontrol *kcontrol,
60462306a36Sopenharmony_ci	struct snd_ctl_elem_value *ucontrol)
60562306a36Sopenharmony_ci{
60662306a36Sopenharmony_ci	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
60762306a36Sopenharmony_ci	struct soc_mixer_control *mc =
60862306a36Sopenharmony_ci		(struct soc_mixer_control *)kcontrol->private_value;
60962306a36Sopenharmony_ci	unsigned int reg = mc->reg;
61062306a36Sopenharmony_ci	unsigned int rreg = mc->rreg;
61162306a36Sopenharmony_ci	unsigned int shift = mc->shift;
61262306a36Sopenharmony_ci	int min = mc->min;
61362306a36Sopenharmony_ci	int max = mc->max;
61462306a36Sopenharmony_ci	unsigned int mask = (1 << fls(max)) - 1;
61562306a36Sopenharmony_ci	unsigned int invert = mc->invert;
61662306a36Sopenharmony_ci	unsigned int val;
61762306a36Sopenharmony_ci
61862306a36Sopenharmony_ci	val = snd_soc_component_read(component, reg);
61962306a36Sopenharmony_ci	ucontrol->value.integer.value[0] = (val >> shift) & mask;
62062306a36Sopenharmony_ci	if (invert)
62162306a36Sopenharmony_ci		ucontrol->value.integer.value[0] =
62262306a36Sopenharmony_ci			max - ucontrol->value.integer.value[0];
62362306a36Sopenharmony_ci	else
62462306a36Sopenharmony_ci		ucontrol->value.integer.value[0] =
62562306a36Sopenharmony_ci			ucontrol->value.integer.value[0] - min;
62662306a36Sopenharmony_ci
62762306a36Sopenharmony_ci	if (snd_soc_volsw_is_stereo(mc)) {
62862306a36Sopenharmony_ci		val = snd_soc_component_read(component, rreg);
62962306a36Sopenharmony_ci		ucontrol->value.integer.value[1] = (val >> shift) & mask;
63062306a36Sopenharmony_ci		if (invert)
63162306a36Sopenharmony_ci			ucontrol->value.integer.value[1] =
63262306a36Sopenharmony_ci				max - ucontrol->value.integer.value[1];
63362306a36Sopenharmony_ci		else
63462306a36Sopenharmony_ci			ucontrol->value.integer.value[1] =
63562306a36Sopenharmony_ci				ucontrol->value.integer.value[1] - min;
63662306a36Sopenharmony_ci	}
63762306a36Sopenharmony_ci
63862306a36Sopenharmony_ci	return 0;
63962306a36Sopenharmony_ci}
64062306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(snd_soc_get_volsw_range);
64162306a36Sopenharmony_ci
64262306a36Sopenharmony_ci/**
64362306a36Sopenharmony_ci * snd_soc_limit_volume - Set new limit to an existing volume control.
64462306a36Sopenharmony_ci *
64562306a36Sopenharmony_ci * @card: where to look for the control
64662306a36Sopenharmony_ci * @name: Name of the control
64762306a36Sopenharmony_ci * @max: new maximum limit
64862306a36Sopenharmony_ci *
64962306a36Sopenharmony_ci * Return 0 for success, else error.
65062306a36Sopenharmony_ci */
65162306a36Sopenharmony_ciint snd_soc_limit_volume(struct snd_soc_card *card,
65262306a36Sopenharmony_ci	const char *name, int max)
65362306a36Sopenharmony_ci{
65462306a36Sopenharmony_ci	struct snd_kcontrol *kctl;
65562306a36Sopenharmony_ci	int ret = -EINVAL;
65662306a36Sopenharmony_ci
65762306a36Sopenharmony_ci	/* Sanity check for name and max */
65862306a36Sopenharmony_ci	if (unlikely(!name || max <= 0))
65962306a36Sopenharmony_ci		return -EINVAL;
66062306a36Sopenharmony_ci
66162306a36Sopenharmony_ci	kctl = snd_soc_card_get_kcontrol(card, name);
66262306a36Sopenharmony_ci	if (kctl) {
66362306a36Sopenharmony_ci		struct soc_mixer_control *mc = (struct soc_mixer_control *)kctl->private_value;
66462306a36Sopenharmony_ci		if (max <= mc->max - mc->min) {
66562306a36Sopenharmony_ci			mc->platform_max = max;
66662306a36Sopenharmony_ci			ret = 0;
66762306a36Sopenharmony_ci		}
66862306a36Sopenharmony_ci	}
66962306a36Sopenharmony_ci	return ret;
67062306a36Sopenharmony_ci}
67162306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(snd_soc_limit_volume);
67262306a36Sopenharmony_ci
67362306a36Sopenharmony_ciint snd_soc_bytes_info(struct snd_kcontrol *kcontrol,
67462306a36Sopenharmony_ci		       struct snd_ctl_elem_info *uinfo)
67562306a36Sopenharmony_ci{
67662306a36Sopenharmony_ci	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
67762306a36Sopenharmony_ci	struct soc_bytes *params = (void *)kcontrol->private_value;
67862306a36Sopenharmony_ci
67962306a36Sopenharmony_ci	uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
68062306a36Sopenharmony_ci	uinfo->count = params->num_regs * component->val_bytes;
68162306a36Sopenharmony_ci
68262306a36Sopenharmony_ci	return 0;
68362306a36Sopenharmony_ci}
68462306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(snd_soc_bytes_info);
68562306a36Sopenharmony_ci
68662306a36Sopenharmony_ciint snd_soc_bytes_get(struct snd_kcontrol *kcontrol,
68762306a36Sopenharmony_ci		      struct snd_ctl_elem_value *ucontrol)
68862306a36Sopenharmony_ci{
68962306a36Sopenharmony_ci	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
69062306a36Sopenharmony_ci	struct soc_bytes *params = (void *)kcontrol->private_value;
69162306a36Sopenharmony_ci	int ret;
69262306a36Sopenharmony_ci
69362306a36Sopenharmony_ci	if (component->regmap)
69462306a36Sopenharmony_ci		ret = regmap_raw_read(component->regmap, params->base,
69562306a36Sopenharmony_ci				      ucontrol->value.bytes.data,
69662306a36Sopenharmony_ci				      params->num_regs * component->val_bytes);
69762306a36Sopenharmony_ci	else
69862306a36Sopenharmony_ci		ret = -EINVAL;
69962306a36Sopenharmony_ci
70062306a36Sopenharmony_ci	/* Hide any masked bytes to ensure consistent data reporting */
70162306a36Sopenharmony_ci	if (ret == 0 && params->mask) {
70262306a36Sopenharmony_ci		switch (component->val_bytes) {
70362306a36Sopenharmony_ci		case 1:
70462306a36Sopenharmony_ci			ucontrol->value.bytes.data[0] &= ~params->mask;
70562306a36Sopenharmony_ci			break;
70662306a36Sopenharmony_ci		case 2:
70762306a36Sopenharmony_ci			((u16 *)(&ucontrol->value.bytes.data))[0]
70862306a36Sopenharmony_ci				&= cpu_to_be16(~params->mask);
70962306a36Sopenharmony_ci			break;
71062306a36Sopenharmony_ci		case 4:
71162306a36Sopenharmony_ci			((u32 *)(&ucontrol->value.bytes.data))[0]
71262306a36Sopenharmony_ci				&= cpu_to_be32(~params->mask);
71362306a36Sopenharmony_ci			break;
71462306a36Sopenharmony_ci		default:
71562306a36Sopenharmony_ci			return -EINVAL;
71662306a36Sopenharmony_ci		}
71762306a36Sopenharmony_ci	}
71862306a36Sopenharmony_ci
71962306a36Sopenharmony_ci	return ret;
72062306a36Sopenharmony_ci}
72162306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(snd_soc_bytes_get);
72262306a36Sopenharmony_ci
72362306a36Sopenharmony_ciint snd_soc_bytes_put(struct snd_kcontrol *kcontrol,
72462306a36Sopenharmony_ci		      struct snd_ctl_elem_value *ucontrol)
72562306a36Sopenharmony_ci{
72662306a36Sopenharmony_ci	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
72762306a36Sopenharmony_ci	struct soc_bytes *params = (void *)kcontrol->private_value;
72862306a36Sopenharmony_ci	int ret, len;
72962306a36Sopenharmony_ci	unsigned int val, mask;
73062306a36Sopenharmony_ci	void *data;
73162306a36Sopenharmony_ci
73262306a36Sopenharmony_ci	if (!component->regmap || !params->num_regs)
73362306a36Sopenharmony_ci		return -EINVAL;
73462306a36Sopenharmony_ci
73562306a36Sopenharmony_ci	len = params->num_regs * component->val_bytes;
73662306a36Sopenharmony_ci
73762306a36Sopenharmony_ci	data = kmemdup(ucontrol->value.bytes.data, len, GFP_KERNEL | GFP_DMA);
73862306a36Sopenharmony_ci	if (!data)
73962306a36Sopenharmony_ci		return -ENOMEM;
74062306a36Sopenharmony_ci
74162306a36Sopenharmony_ci	/*
74262306a36Sopenharmony_ci	 * If we've got a mask then we need to preserve the register
74362306a36Sopenharmony_ci	 * bits.  We shouldn't modify the incoming data so take a
74462306a36Sopenharmony_ci	 * copy.
74562306a36Sopenharmony_ci	 */
74662306a36Sopenharmony_ci	if (params->mask) {
74762306a36Sopenharmony_ci		ret = regmap_read(component->regmap, params->base, &val);
74862306a36Sopenharmony_ci		if (ret != 0)
74962306a36Sopenharmony_ci			goto out;
75062306a36Sopenharmony_ci
75162306a36Sopenharmony_ci		val &= params->mask;
75262306a36Sopenharmony_ci
75362306a36Sopenharmony_ci		switch (component->val_bytes) {
75462306a36Sopenharmony_ci		case 1:
75562306a36Sopenharmony_ci			((u8 *)data)[0] &= ~params->mask;
75662306a36Sopenharmony_ci			((u8 *)data)[0] |= val;
75762306a36Sopenharmony_ci			break;
75862306a36Sopenharmony_ci		case 2:
75962306a36Sopenharmony_ci			mask = ~params->mask;
76062306a36Sopenharmony_ci			ret = regmap_parse_val(component->regmap,
76162306a36Sopenharmony_ci							&mask, &mask);
76262306a36Sopenharmony_ci			if (ret != 0)
76362306a36Sopenharmony_ci				goto out;
76462306a36Sopenharmony_ci
76562306a36Sopenharmony_ci			((u16 *)data)[0] &= mask;
76662306a36Sopenharmony_ci
76762306a36Sopenharmony_ci			ret = regmap_parse_val(component->regmap,
76862306a36Sopenharmony_ci							&val, &val);
76962306a36Sopenharmony_ci			if (ret != 0)
77062306a36Sopenharmony_ci				goto out;
77162306a36Sopenharmony_ci
77262306a36Sopenharmony_ci			((u16 *)data)[0] |= val;
77362306a36Sopenharmony_ci			break;
77462306a36Sopenharmony_ci		case 4:
77562306a36Sopenharmony_ci			mask = ~params->mask;
77662306a36Sopenharmony_ci			ret = regmap_parse_val(component->regmap,
77762306a36Sopenharmony_ci							&mask, &mask);
77862306a36Sopenharmony_ci			if (ret != 0)
77962306a36Sopenharmony_ci				goto out;
78062306a36Sopenharmony_ci
78162306a36Sopenharmony_ci			((u32 *)data)[0] &= mask;
78262306a36Sopenharmony_ci
78362306a36Sopenharmony_ci			ret = regmap_parse_val(component->regmap,
78462306a36Sopenharmony_ci							&val, &val);
78562306a36Sopenharmony_ci			if (ret != 0)
78662306a36Sopenharmony_ci				goto out;
78762306a36Sopenharmony_ci
78862306a36Sopenharmony_ci			((u32 *)data)[0] |= val;
78962306a36Sopenharmony_ci			break;
79062306a36Sopenharmony_ci		default:
79162306a36Sopenharmony_ci			ret = -EINVAL;
79262306a36Sopenharmony_ci			goto out;
79362306a36Sopenharmony_ci		}
79462306a36Sopenharmony_ci	}
79562306a36Sopenharmony_ci
79662306a36Sopenharmony_ci	ret = regmap_raw_write(component->regmap, params->base,
79762306a36Sopenharmony_ci			       data, len);
79862306a36Sopenharmony_ci
79962306a36Sopenharmony_ciout:
80062306a36Sopenharmony_ci	kfree(data);
80162306a36Sopenharmony_ci
80262306a36Sopenharmony_ci	return ret;
80362306a36Sopenharmony_ci}
80462306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(snd_soc_bytes_put);
80562306a36Sopenharmony_ci
80662306a36Sopenharmony_ciint snd_soc_bytes_info_ext(struct snd_kcontrol *kcontrol,
80762306a36Sopenharmony_ci			struct snd_ctl_elem_info *ucontrol)
80862306a36Sopenharmony_ci{
80962306a36Sopenharmony_ci	struct soc_bytes_ext *params = (void *)kcontrol->private_value;
81062306a36Sopenharmony_ci
81162306a36Sopenharmony_ci	ucontrol->type = SNDRV_CTL_ELEM_TYPE_BYTES;
81262306a36Sopenharmony_ci	ucontrol->count = params->max;
81362306a36Sopenharmony_ci
81462306a36Sopenharmony_ci	return 0;
81562306a36Sopenharmony_ci}
81662306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(snd_soc_bytes_info_ext);
81762306a36Sopenharmony_ci
81862306a36Sopenharmony_ciint snd_soc_bytes_tlv_callback(struct snd_kcontrol *kcontrol, int op_flag,
81962306a36Sopenharmony_ci				unsigned int size, unsigned int __user *tlv)
82062306a36Sopenharmony_ci{
82162306a36Sopenharmony_ci	struct soc_bytes_ext *params = (void *)kcontrol->private_value;
82262306a36Sopenharmony_ci	unsigned int count = size < params->max ? size : params->max;
82362306a36Sopenharmony_ci	int ret = -ENXIO;
82462306a36Sopenharmony_ci
82562306a36Sopenharmony_ci	switch (op_flag) {
82662306a36Sopenharmony_ci	case SNDRV_CTL_TLV_OP_READ:
82762306a36Sopenharmony_ci		if (params->get)
82862306a36Sopenharmony_ci			ret = params->get(kcontrol, tlv, count);
82962306a36Sopenharmony_ci		break;
83062306a36Sopenharmony_ci	case SNDRV_CTL_TLV_OP_WRITE:
83162306a36Sopenharmony_ci		if (params->put)
83262306a36Sopenharmony_ci			ret = params->put(kcontrol, tlv, count);
83362306a36Sopenharmony_ci		break;
83462306a36Sopenharmony_ci	}
83562306a36Sopenharmony_ci	return ret;
83662306a36Sopenharmony_ci}
83762306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(snd_soc_bytes_tlv_callback);
83862306a36Sopenharmony_ci
83962306a36Sopenharmony_ci/**
84062306a36Sopenharmony_ci * snd_soc_info_xr_sx - signed multi register info callback
84162306a36Sopenharmony_ci * @kcontrol: mreg control
84262306a36Sopenharmony_ci * @uinfo: control element information
84362306a36Sopenharmony_ci *
84462306a36Sopenharmony_ci * Callback to provide information of a control that can
84562306a36Sopenharmony_ci * span multiple codec registers which together
84662306a36Sopenharmony_ci * forms a single signed value in a MSB/LSB manner.
84762306a36Sopenharmony_ci *
84862306a36Sopenharmony_ci * Returns 0 for success.
84962306a36Sopenharmony_ci */
85062306a36Sopenharmony_ciint snd_soc_info_xr_sx(struct snd_kcontrol *kcontrol,
85162306a36Sopenharmony_ci	struct snd_ctl_elem_info *uinfo)
85262306a36Sopenharmony_ci{
85362306a36Sopenharmony_ci	struct soc_mreg_control *mc =
85462306a36Sopenharmony_ci		(struct soc_mreg_control *)kcontrol->private_value;
85562306a36Sopenharmony_ci	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
85662306a36Sopenharmony_ci	uinfo->count = 1;
85762306a36Sopenharmony_ci	uinfo->value.integer.min = mc->min;
85862306a36Sopenharmony_ci	uinfo->value.integer.max = mc->max;
85962306a36Sopenharmony_ci
86062306a36Sopenharmony_ci	return 0;
86162306a36Sopenharmony_ci}
86262306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(snd_soc_info_xr_sx);
86362306a36Sopenharmony_ci
86462306a36Sopenharmony_ci/**
86562306a36Sopenharmony_ci * snd_soc_get_xr_sx - signed multi register get callback
86662306a36Sopenharmony_ci * @kcontrol: mreg control
86762306a36Sopenharmony_ci * @ucontrol: control element information
86862306a36Sopenharmony_ci *
86962306a36Sopenharmony_ci * Callback to get the value of a control that can span
87062306a36Sopenharmony_ci * multiple codec registers which together forms a single
87162306a36Sopenharmony_ci * signed value in a MSB/LSB manner. The control supports
87262306a36Sopenharmony_ci * specifying total no of bits used to allow for bitfields
87362306a36Sopenharmony_ci * across the multiple codec registers.
87462306a36Sopenharmony_ci *
87562306a36Sopenharmony_ci * Returns 0 for success.
87662306a36Sopenharmony_ci */
87762306a36Sopenharmony_ciint snd_soc_get_xr_sx(struct snd_kcontrol *kcontrol,
87862306a36Sopenharmony_ci	struct snd_ctl_elem_value *ucontrol)
87962306a36Sopenharmony_ci{
88062306a36Sopenharmony_ci	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
88162306a36Sopenharmony_ci	struct soc_mreg_control *mc =
88262306a36Sopenharmony_ci		(struct soc_mreg_control *)kcontrol->private_value;
88362306a36Sopenharmony_ci	unsigned int regbase = mc->regbase;
88462306a36Sopenharmony_ci	unsigned int regcount = mc->regcount;
88562306a36Sopenharmony_ci	unsigned int regwshift = component->val_bytes * BITS_PER_BYTE;
88662306a36Sopenharmony_ci	unsigned int regwmask = (1UL<<regwshift)-1;
88762306a36Sopenharmony_ci	unsigned int invert = mc->invert;
88862306a36Sopenharmony_ci	unsigned long mask = (1UL<<mc->nbits)-1;
88962306a36Sopenharmony_ci	long min = mc->min;
89062306a36Sopenharmony_ci	long max = mc->max;
89162306a36Sopenharmony_ci	long val = 0;
89262306a36Sopenharmony_ci	unsigned int i;
89362306a36Sopenharmony_ci
89462306a36Sopenharmony_ci	for (i = 0; i < regcount; i++) {
89562306a36Sopenharmony_ci		unsigned int regval = snd_soc_component_read(component, regbase+i);
89662306a36Sopenharmony_ci		val |= (regval & regwmask) << (regwshift*(regcount-i-1));
89762306a36Sopenharmony_ci	}
89862306a36Sopenharmony_ci	val &= mask;
89962306a36Sopenharmony_ci	if (min < 0 && val > max)
90062306a36Sopenharmony_ci		val |= ~mask;
90162306a36Sopenharmony_ci	if (invert)
90262306a36Sopenharmony_ci		val = max - val;
90362306a36Sopenharmony_ci	ucontrol->value.integer.value[0] = val;
90462306a36Sopenharmony_ci
90562306a36Sopenharmony_ci	return 0;
90662306a36Sopenharmony_ci}
90762306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(snd_soc_get_xr_sx);
90862306a36Sopenharmony_ci
90962306a36Sopenharmony_ci/**
91062306a36Sopenharmony_ci * snd_soc_put_xr_sx - signed multi register get callback
91162306a36Sopenharmony_ci * @kcontrol: mreg control
91262306a36Sopenharmony_ci * @ucontrol: control element information
91362306a36Sopenharmony_ci *
91462306a36Sopenharmony_ci * Callback to set the value of a control that can span
91562306a36Sopenharmony_ci * multiple codec registers which together forms a single
91662306a36Sopenharmony_ci * signed value in a MSB/LSB manner. The control supports
91762306a36Sopenharmony_ci * specifying total no of bits used to allow for bitfields
91862306a36Sopenharmony_ci * across the multiple codec registers.
91962306a36Sopenharmony_ci *
92062306a36Sopenharmony_ci * Returns 0 for success.
92162306a36Sopenharmony_ci */
92262306a36Sopenharmony_ciint snd_soc_put_xr_sx(struct snd_kcontrol *kcontrol,
92362306a36Sopenharmony_ci	struct snd_ctl_elem_value *ucontrol)
92462306a36Sopenharmony_ci{
92562306a36Sopenharmony_ci	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
92662306a36Sopenharmony_ci	struct soc_mreg_control *mc =
92762306a36Sopenharmony_ci		(struct soc_mreg_control *)kcontrol->private_value;
92862306a36Sopenharmony_ci	unsigned int regbase = mc->regbase;
92962306a36Sopenharmony_ci	unsigned int regcount = mc->regcount;
93062306a36Sopenharmony_ci	unsigned int regwshift = component->val_bytes * BITS_PER_BYTE;
93162306a36Sopenharmony_ci	unsigned int regwmask = (1UL<<regwshift)-1;
93262306a36Sopenharmony_ci	unsigned int invert = mc->invert;
93362306a36Sopenharmony_ci	unsigned long mask = (1UL<<mc->nbits)-1;
93462306a36Sopenharmony_ci	long max = mc->max;
93562306a36Sopenharmony_ci	long val = ucontrol->value.integer.value[0];
93662306a36Sopenharmony_ci	int ret = 0;
93762306a36Sopenharmony_ci	unsigned int i;
93862306a36Sopenharmony_ci
93962306a36Sopenharmony_ci	if (val < mc->min || val > mc->max)
94062306a36Sopenharmony_ci		return -EINVAL;
94162306a36Sopenharmony_ci	if (invert)
94262306a36Sopenharmony_ci		val = max - val;
94362306a36Sopenharmony_ci	val &= mask;
94462306a36Sopenharmony_ci	for (i = 0; i < regcount; i++) {
94562306a36Sopenharmony_ci		unsigned int regval = (val >> (regwshift*(regcount-i-1))) & regwmask;
94662306a36Sopenharmony_ci		unsigned int regmask = (mask >> (regwshift*(regcount-i-1))) & regwmask;
94762306a36Sopenharmony_ci		int err = snd_soc_component_update_bits(component, regbase+i,
94862306a36Sopenharmony_ci							regmask, regval);
94962306a36Sopenharmony_ci		if (err < 0)
95062306a36Sopenharmony_ci			return err;
95162306a36Sopenharmony_ci		if (err > 0)
95262306a36Sopenharmony_ci			ret = err;
95362306a36Sopenharmony_ci	}
95462306a36Sopenharmony_ci
95562306a36Sopenharmony_ci	return ret;
95662306a36Sopenharmony_ci}
95762306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(snd_soc_put_xr_sx);
95862306a36Sopenharmony_ci
95962306a36Sopenharmony_ci/**
96062306a36Sopenharmony_ci * snd_soc_get_strobe - strobe get callback
96162306a36Sopenharmony_ci * @kcontrol: mixer control
96262306a36Sopenharmony_ci * @ucontrol: control element information
96362306a36Sopenharmony_ci *
96462306a36Sopenharmony_ci * Callback get the value of a strobe mixer control.
96562306a36Sopenharmony_ci *
96662306a36Sopenharmony_ci * Returns 0 for success.
96762306a36Sopenharmony_ci */
96862306a36Sopenharmony_ciint snd_soc_get_strobe(struct snd_kcontrol *kcontrol,
96962306a36Sopenharmony_ci	struct snd_ctl_elem_value *ucontrol)
97062306a36Sopenharmony_ci{
97162306a36Sopenharmony_ci	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
97262306a36Sopenharmony_ci	struct soc_mixer_control *mc =
97362306a36Sopenharmony_ci		(struct soc_mixer_control *)kcontrol->private_value;
97462306a36Sopenharmony_ci	unsigned int reg = mc->reg;
97562306a36Sopenharmony_ci	unsigned int shift = mc->shift;
97662306a36Sopenharmony_ci	unsigned int mask = 1 << shift;
97762306a36Sopenharmony_ci	unsigned int invert = mc->invert != 0;
97862306a36Sopenharmony_ci	unsigned int val;
97962306a36Sopenharmony_ci
98062306a36Sopenharmony_ci	val = snd_soc_component_read(component, reg);
98162306a36Sopenharmony_ci	val &= mask;
98262306a36Sopenharmony_ci
98362306a36Sopenharmony_ci	if (shift != 0 && val != 0)
98462306a36Sopenharmony_ci		val = val >> shift;
98562306a36Sopenharmony_ci	ucontrol->value.enumerated.item[0] = val ^ invert;
98662306a36Sopenharmony_ci
98762306a36Sopenharmony_ci	return 0;
98862306a36Sopenharmony_ci}
98962306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(snd_soc_get_strobe);
99062306a36Sopenharmony_ci
99162306a36Sopenharmony_ci/**
99262306a36Sopenharmony_ci * snd_soc_put_strobe - strobe put callback
99362306a36Sopenharmony_ci * @kcontrol: mixer control
99462306a36Sopenharmony_ci * @ucontrol: control element information
99562306a36Sopenharmony_ci *
99662306a36Sopenharmony_ci * Callback strobe a register bit to high then low (or the inverse)
99762306a36Sopenharmony_ci * in one pass of a single mixer enum control.
99862306a36Sopenharmony_ci *
99962306a36Sopenharmony_ci * Returns 1 for success.
100062306a36Sopenharmony_ci */
100162306a36Sopenharmony_ciint snd_soc_put_strobe(struct snd_kcontrol *kcontrol,
100262306a36Sopenharmony_ci	struct snd_ctl_elem_value *ucontrol)
100362306a36Sopenharmony_ci{
100462306a36Sopenharmony_ci	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
100562306a36Sopenharmony_ci	struct soc_mixer_control *mc =
100662306a36Sopenharmony_ci		(struct soc_mixer_control *)kcontrol->private_value;
100762306a36Sopenharmony_ci	unsigned int reg = mc->reg;
100862306a36Sopenharmony_ci	unsigned int shift = mc->shift;
100962306a36Sopenharmony_ci	unsigned int mask = 1 << shift;
101062306a36Sopenharmony_ci	unsigned int invert = mc->invert != 0;
101162306a36Sopenharmony_ci	unsigned int strobe = ucontrol->value.enumerated.item[0] != 0;
101262306a36Sopenharmony_ci	unsigned int val1 = (strobe ^ invert) ? mask : 0;
101362306a36Sopenharmony_ci	unsigned int val2 = (strobe ^ invert) ? 0 : mask;
101462306a36Sopenharmony_ci	int err;
101562306a36Sopenharmony_ci
101662306a36Sopenharmony_ci	err = snd_soc_component_update_bits(component, reg, mask, val1);
101762306a36Sopenharmony_ci	if (err < 0)
101862306a36Sopenharmony_ci		return err;
101962306a36Sopenharmony_ci
102062306a36Sopenharmony_ci	return snd_soc_component_update_bits(component, reg, mask, val2);
102162306a36Sopenharmony_ci}
102262306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(snd_soc_put_strobe);
1023