xref: /OK3568_Linux_fs/kernel/sound/soc/codecs/wcd-clsh-v2.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun // Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
3*4882a593Smuzhiyun // Copyright (c) 2017-2018, Linaro Limited
4*4882a593Smuzhiyun 
5*4882a593Smuzhiyun #include <linux/slab.h>
6*4882a593Smuzhiyun #include <sound/soc.h>
7*4882a593Smuzhiyun #include <linux/kernel.h>
8*4882a593Smuzhiyun #include <linux/delay.h>
9*4882a593Smuzhiyun #include "wcd9335.h"
10*4882a593Smuzhiyun #include "wcd-clsh-v2.h"
11*4882a593Smuzhiyun 
12*4882a593Smuzhiyun struct wcd_clsh_ctrl {
13*4882a593Smuzhiyun 	int state;
14*4882a593Smuzhiyun 	int mode;
15*4882a593Smuzhiyun 	int flyback_users;
16*4882a593Smuzhiyun 	int buck_users;
17*4882a593Smuzhiyun 	int clsh_users;
18*4882a593Smuzhiyun 	int codec_version;
19*4882a593Smuzhiyun 	struct snd_soc_component *comp;
20*4882a593Smuzhiyun };
21*4882a593Smuzhiyun 
22*4882a593Smuzhiyun /* Class-H registers for codecs from and above WCD9335 */
23*4882a593Smuzhiyun #define WCD9XXX_A_CDC_RX0_RX_PATH_CFG0			WCD9335_REG(0xB, 0x42)
24*4882a593Smuzhiyun #define WCD9XXX_A_CDC_RX_PATH_CLSH_EN_MASK		BIT(6)
25*4882a593Smuzhiyun #define WCD9XXX_A_CDC_RX_PATH_CLSH_ENABLE		BIT(6)
26*4882a593Smuzhiyun #define WCD9XXX_A_CDC_RX_PATH_CLSH_DISABLE		0
27*4882a593Smuzhiyun #define WCD9XXX_A_CDC_RX1_RX_PATH_CFG0			WCD9335_REG(0xB, 0x56)
28*4882a593Smuzhiyun #define WCD9XXX_A_CDC_RX2_RX_PATH_CFG0			WCD9335_REG(0xB, 0x6A)
29*4882a593Smuzhiyun #define WCD9XXX_A_CDC_CLSH_K1_MSB			WCD9335_REG(0xC, 0x08)
30*4882a593Smuzhiyun #define WCD9XXX_A_CDC_CLSH_K1_MSB_COEF_MASK		GENMASK(3, 0)
31*4882a593Smuzhiyun #define WCD9XXX_A_CDC_CLSH_K1_LSB			WCD9335_REG(0xC, 0x09)
32*4882a593Smuzhiyun #define WCD9XXX_A_CDC_CLSH_K1_LSB_COEF_MASK		GENMASK(7, 0)
33*4882a593Smuzhiyun #define WCD9XXX_A_ANA_RX_SUPPLIES			WCD9335_REG(0x6, 0x08)
34*4882a593Smuzhiyun #define WCD9XXX_A_ANA_RX_REGULATOR_MODE_MASK		BIT(1)
35*4882a593Smuzhiyun #define WCD9XXX_A_ANA_RX_REGULATOR_MODE_CLS_H		0
36*4882a593Smuzhiyun #define WCD9XXX_A_ANA_RX_REGULATOR_MODE_CLS_AB		BIT(1)
37*4882a593Smuzhiyun #define WCD9XXX_A_ANA_RX_VNEG_PWR_LVL_MASK		BIT(2)
38*4882a593Smuzhiyun #define WCD9XXX_A_ANA_RX_VNEG_PWR_LVL_UHQA		BIT(2)
39*4882a593Smuzhiyun #define WCD9XXX_A_ANA_RX_VNEG_PWR_LVL_DEFAULT		0
40*4882a593Smuzhiyun #define WCD9XXX_A_ANA_RX_VPOS_PWR_LVL_MASK		BIT(3)
41*4882a593Smuzhiyun #define WCD9XXX_A_ANA_RX_VPOS_PWR_LVL_UHQA		BIT(3)
42*4882a593Smuzhiyun #define WCD9XXX_A_ANA_RX_VPOS_PWR_LVL_DEFAULT		0
43*4882a593Smuzhiyun #define WCD9XXX_A_ANA_RX_VNEG_EN_MASK			BIT(6)
44*4882a593Smuzhiyun #define WCD9XXX_A_ANA_RX_VNEG_EN_SHIFT			6
45*4882a593Smuzhiyun #define WCD9XXX_A_ANA_RX_VNEG_ENABLE			BIT(6)
46*4882a593Smuzhiyun #define WCD9XXX_A_ANA_RX_VNEG_DISABLE			0
47*4882a593Smuzhiyun #define WCD9XXX_A_ANA_RX_VPOS_EN_MASK			BIT(7)
48*4882a593Smuzhiyun #define WCD9XXX_A_ANA_RX_VPOS_EN_SHIFT			7
49*4882a593Smuzhiyun #define WCD9XXX_A_ANA_RX_VPOS_ENABLE			BIT(7)
50*4882a593Smuzhiyun #define WCD9XXX_A_ANA_RX_VPOS_DISABLE			0
51*4882a593Smuzhiyun #define WCD9XXX_A_ANA_HPH				WCD9335_REG(0x6, 0x09)
52*4882a593Smuzhiyun #define WCD9XXX_A_ANA_HPH_PWR_LEVEL_MASK		GENMASK(3, 2)
53*4882a593Smuzhiyun #define WCD9XXX_A_ANA_HPH_PWR_LEVEL_UHQA		0x08
54*4882a593Smuzhiyun #define WCD9XXX_A_ANA_HPH_PWR_LEVEL_LP			0x04
55*4882a593Smuzhiyun #define WCD9XXX_A_ANA_HPH_PWR_LEVEL_NORMAL		0x0
56*4882a593Smuzhiyun #define WCD9XXX_A_CDC_CLSH_CRC				WCD9335_REG(0xC, 0x01)
57*4882a593Smuzhiyun #define WCD9XXX_A_CDC_CLSH_CRC_CLK_EN_MASK		BIT(0)
58*4882a593Smuzhiyun #define WCD9XXX_A_CDC_CLSH_CRC_CLK_ENABLE		BIT(0)
59*4882a593Smuzhiyun #define WCD9XXX_A_CDC_CLSH_CRC_CLK_DISABLE		0
60*4882a593Smuzhiyun #define WCD9XXX_FLYBACK_EN				WCD9335_REG(0x6, 0xA4)
61*4882a593Smuzhiyun #define WCD9XXX_FLYBACK_EN_DELAY_SEL_MASK		GENMASK(6, 5)
62*4882a593Smuzhiyun #define WCD9XXX_FLYBACK_EN_DELAY_26P25_US		0x40
63*4882a593Smuzhiyun #define WCD9XXX_FLYBACK_EN_RESET_BY_EXT_MASK		BIT(4)
64*4882a593Smuzhiyun #define WCD9XXX_FLYBACK_EN_PWDN_WITHOUT_DELAY		BIT(4)
65*4882a593Smuzhiyun #define WCD9XXX_FLYBACK_EN_PWDN_WITH_DELAY			0
66*4882a593Smuzhiyun #define WCD9XXX_RX_BIAS_FLYB_BUFF			WCD9335_REG(0x6, 0xC7)
67*4882a593Smuzhiyun #define WCD9XXX_RX_BIAS_FLYB_VNEG_5_UA_MASK		GENMASK(7, 4)
68*4882a593Smuzhiyun #define WCD9XXX_RX_BIAS_FLYB_VPOS_5_UA_MASK		GENMASK(3, 0)
69*4882a593Smuzhiyun #define WCD9XXX_HPH_L_EN				WCD9335_REG(0x6, 0xD3)
70*4882a593Smuzhiyun #define WCD9XXX_HPH_CONST_SEL_L_MASK			GENMASK(7, 3)
71*4882a593Smuzhiyun #define WCD9XXX_HPH_CONST_SEL_BYPASS			0
72*4882a593Smuzhiyun #define WCD9XXX_HPH_CONST_SEL_LP_PATH			0x40
73*4882a593Smuzhiyun #define WCD9XXX_HPH_CONST_SEL_HQ_PATH			0x80
74*4882a593Smuzhiyun #define WCD9XXX_HPH_R_EN				WCD9335_REG(0x6, 0xD6)
75*4882a593Smuzhiyun #define WCD9XXX_HPH_REFBUFF_UHQA_CTL			WCD9335_REG(0x6, 0xDD)
76*4882a593Smuzhiyun #define WCD9XXX_HPH_REFBUFF_UHQA_GAIN_MASK		GENMASK(2, 0)
77*4882a593Smuzhiyun #define WCD9XXX_CLASSH_CTRL_VCL_2                       WCD9335_REG(0x6, 0x9B)
78*4882a593Smuzhiyun #define WCD9XXX_CLASSH_CTRL_VCL_2_VREF_FILT_1_MASK	GENMASK(5, 4)
79*4882a593Smuzhiyun #define WCD9XXX_CLASSH_CTRL_VCL_VREF_FILT_R_50KOHM	0x20
80*4882a593Smuzhiyun #define WCD9XXX_CLASSH_CTRL_VCL_VREF_FILT_R_0KOHM	0x0
81*4882a593Smuzhiyun #define WCD9XXX_CDC_RX1_RX_PATH_CTL			WCD9335_REG(0xB, 0x55)
82*4882a593Smuzhiyun #define WCD9XXX_CDC_RX2_RX_PATH_CTL			WCD9335_REG(0xB, 0x69)
83*4882a593Smuzhiyun #define WCD9XXX_CDC_CLK_RST_CTRL_MCLK_CONTROL		WCD9335_REG(0xD, 0x41)
84*4882a593Smuzhiyun #define WCD9XXX_CDC_CLK_RST_CTRL_MCLK_EN_MASK		BIT(0)
85*4882a593Smuzhiyun #define WCD9XXX_CDC_CLK_RST_CTRL_MCLK_11P3_EN_MASK	BIT(1)
86*4882a593Smuzhiyun #define WCD9XXX_CLASSH_CTRL_CCL_1                       WCD9335_REG(0x6, 0x9C)
87*4882a593Smuzhiyun #define WCD9XXX_CLASSH_CTRL_CCL_1_DELTA_IPEAK_MASK	GENMASK(7, 4)
88*4882a593Smuzhiyun #define WCD9XXX_CLASSH_CTRL_CCL_1_DELTA_IPEAK_50MA	0x50
89*4882a593Smuzhiyun #define WCD9XXX_CLASSH_CTRL_CCL_1_DELTA_IPEAK_30MA	0x30
90*4882a593Smuzhiyun 
91*4882a593Smuzhiyun #define CLSH_REQ_ENABLE		true
92*4882a593Smuzhiyun #define CLSH_REQ_DISABLE	false
93*4882a593Smuzhiyun #define WCD_USLEEP_RANGE	50
94*4882a593Smuzhiyun 
95*4882a593Smuzhiyun enum {
96*4882a593Smuzhiyun 	DAC_GAIN_0DB = 0,
97*4882a593Smuzhiyun 	DAC_GAIN_0P2DB,
98*4882a593Smuzhiyun 	DAC_GAIN_0P4DB,
99*4882a593Smuzhiyun 	DAC_GAIN_0P6DB,
100*4882a593Smuzhiyun 	DAC_GAIN_0P8DB,
101*4882a593Smuzhiyun 	DAC_GAIN_M0P2DB,
102*4882a593Smuzhiyun 	DAC_GAIN_M0P4DB,
103*4882a593Smuzhiyun 	DAC_GAIN_M0P6DB,
104*4882a593Smuzhiyun };
105*4882a593Smuzhiyun 
wcd_enable_clsh_block(struct wcd_clsh_ctrl * ctrl,bool enable)106*4882a593Smuzhiyun static inline void wcd_enable_clsh_block(struct wcd_clsh_ctrl *ctrl,
107*4882a593Smuzhiyun 					 bool enable)
108*4882a593Smuzhiyun {
109*4882a593Smuzhiyun 	struct snd_soc_component *comp = ctrl->comp;
110*4882a593Smuzhiyun 
111*4882a593Smuzhiyun 	if ((enable && ++ctrl->clsh_users == 1) ||
112*4882a593Smuzhiyun 	    (!enable && --ctrl->clsh_users == 0))
113*4882a593Smuzhiyun 		snd_soc_component_update_bits(comp, WCD9XXX_A_CDC_CLSH_CRC,
114*4882a593Smuzhiyun 				      WCD9XXX_A_CDC_CLSH_CRC_CLK_EN_MASK,
115*4882a593Smuzhiyun 				      enable);
116*4882a593Smuzhiyun 	if (ctrl->clsh_users < 0)
117*4882a593Smuzhiyun 		ctrl->clsh_users = 0;
118*4882a593Smuzhiyun }
119*4882a593Smuzhiyun 
wcd_clsh_enable_status(struct snd_soc_component * comp)120*4882a593Smuzhiyun static inline bool wcd_clsh_enable_status(struct snd_soc_component *comp)
121*4882a593Smuzhiyun {
122*4882a593Smuzhiyun 	return snd_soc_component_read(comp, WCD9XXX_A_CDC_CLSH_CRC) &
123*4882a593Smuzhiyun 					WCD9XXX_A_CDC_CLSH_CRC_CLK_EN_MASK;
124*4882a593Smuzhiyun }
125*4882a593Smuzhiyun 
wcd_clsh_set_buck_mode(struct snd_soc_component * comp,int mode)126*4882a593Smuzhiyun static inline void wcd_clsh_set_buck_mode(struct snd_soc_component *comp,
127*4882a593Smuzhiyun 					  int mode)
128*4882a593Smuzhiyun {
129*4882a593Smuzhiyun 	/* set to HIFI */
130*4882a593Smuzhiyun 	if (mode == CLS_H_HIFI)
131*4882a593Smuzhiyun 		snd_soc_component_update_bits(comp, WCD9XXX_A_ANA_RX_SUPPLIES,
132*4882a593Smuzhiyun 					WCD9XXX_A_ANA_RX_VPOS_PWR_LVL_MASK,
133*4882a593Smuzhiyun 					WCD9XXX_A_ANA_RX_VPOS_PWR_LVL_UHQA);
134*4882a593Smuzhiyun 	else
135*4882a593Smuzhiyun 		snd_soc_component_update_bits(comp, WCD9XXX_A_ANA_RX_SUPPLIES,
136*4882a593Smuzhiyun 					WCD9XXX_A_ANA_RX_VPOS_PWR_LVL_MASK,
137*4882a593Smuzhiyun 					WCD9XXX_A_ANA_RX_VPOS_PWR_LVL_DEFAULT);
138*4882a593Smuzhiyun }
139*4882a593Smuzhiyun 
wcd_clsh_set_flyback_mode(struct snd_soc_component * comp,int mode)140*4882a593Smuzhiyun static inline void wcd_clsh_set_flyback_mode(struct snd_soc_component *comp,
141*4882a593Smuzhiyun 					     int mode)
142*4882a593Smuzhiyun {
143*4882a593Smuzhiyun 	/* set to HIFI */
144*4882a593Smuzhiyun 	if (mode == CLS_H_HIFI)
145*4882a593Smuzhiyun 		snd_soc_component_update_bits(comp, WCD9XXX_A_ANA_RX_SUPPLIES,
146*4882a593Smuzhiyun 					WCD9XXX_A_ANA_RX_VNEG_PWR_LVL_MASK,
147*4882a593Smuzhiyun 					WCD9XXX_A_ANA_RX_VNEG_PWR_LVL_UHQA);
148*4882a593Smuzhiyun 	else
149*4882a593Smuzhiyun 		snd_soc_component_update_bits(comp, WCD9XXX_A_ANA_RX_SUPPLIES,
150*4882a593Smuzhiyun 					WCD9XXX_A_ANA_RX_VNEG_PWR_LVL_MASK,
151*4882a593Smuzhiyun 					WCD9XXX_A_ANA_RX_VNEG_PWR_LVL_DEFAULT);
152*4882a593Smuzhiyun }
153*4882a593Smuzhiyun 
wcd_clsh_buck_ctrl(struct wcd_clsh_ctrl * ctrl,int mode,bool enable)154*4882a593Smuzhiyun static void wcd_clsh_buck_ctrl(struct wcd_clsh_ctrl *ctrl,
155*4882a593Smuzhiyun 			       int mode,
156*4882a593Smuzhiyun 			       bool enable)
157*4882a593Smuzhiyun {
158*4882a593Smuzhiyun 	struct snd_soc_component *comp = ctrl->comp;
159*4882a593Smuzhiyun 
160*4882a593Smuzhiyun 	/* enable/disable buck */
161*4882a593Smuzhiyun 	if ((enable && (++ctrl->buck_users == 1)) ||
162*4882a593Smuzhiyun 	   (!enable && (--ctrl->buck_users == 0)))
163*4882a593Smuzhiyun 		snd_soc_component_update_bits(comp, WCD9XXX_A_ANA_RX_SUPPLIES,
164*4882a593Smuzhiyun 				WCD9XXX_A_ANA_RX_VPOS_EN_MASK,
165*4882a593Smuzhiyun 				enable << WCD9XXX_A_ANA_RX_VPOS_EN_SHIFT);
166*4882a593Smuzhiyun 	/*
167*4882a593Smuzhiyun 	 * 500us sleep is required after buck enable/disable
168*4882a593Smuzhiyun 	 * as per HW requirement
169*4882a593Smuzhiyun 	 */
170*4882a593Smuzhiyun 	usleep_range(500, 500 + WCD_USLEEP_RANGE);
171*4882a593Smuzhiyun }
172*4882a593Smuzhiyun 
wcd_clsh_flyback_ctrl(struct wcd_clsh_ctrl * ctrl,int mode,bool enable)173*4882a593Smuzhiyun static void wcd_clsh_flyback_ctrl(struct wcd_clsh_ctrl *ctrl,
174*4882a593Smuzhiyun 				  int mode,
175*4882a593Smuzhiyun 				  bool enable)
176*4882a593Smuzhiyun {
177*4882a593Smuzhiyun 	struct snd_soc_component *comp = ctrl->comp;
178*4882a593Smuzhiyun 
179*4882a593Smuzhiyun 	/* enable/disable flyback */
180*4882a593Smuzhiyun 	if ((enable && (++ctrl->flyback_users == 1)) ||
181*4882a593Smuzhiyun 	   (!enable && (--ctrl->flyback_users == 0))) {
182*4882a593Smuzhiyun 		snd_soc_component_update_bits(comp, WCD9XXX_A_ANA_RX_SUPPLIES,
183*4882a593Smuzhiyun 				WCD9XXX_A_ANA_RX_VNEG_EN_MASK,
184*4882a593Smuzhiyun 				enable << WCD9XXX_A_ANA_RX_VNEG_EN_SHIFT);
185*4882a593Smuzhiyun 		/* 100usec delay is needed as per HW requirement */
186*4882a593Smuzhiyun 		usleep_range(100, 110);
187*4882a593Smuzhiyun 	}
188*4882a593Smuzhiyun 	/*
189*4882a593Smuzhiyun 	 * 500us sleep is required after flyback enable/disable
190*4882a593Smuzhiyun 	 * as per HW requirement
191*4882a593Smuzhiyun 	 */
192*4882a593Smuzhiyun 	usleep_range(500, 500 + WCD_USLEEP_RANGE);
193*4882a593Smuzhiyun }
194*4882a593Smuzhiyun 
wcd_clsh_set_gain_path(struct wcd_clsh_ctrl * ctrl,int mode)195*4882a593Smuzhiyun static void wcd_clsh_set_gain_path(struct wcd_clsh_ctrl *ctrl, int mode)
196*4882a593Smuzhiyun {
197*4882a593Smuzhiyun 	struct snd_soc_component *comp = ctrl->comp;
198*4882a593Smuzhiyun 	int val = 0;
199*4882a593Smuzhiyun 
200*4882a593Smuzhiyun 	switch (mode) {
201*4882a593Smuzhiyun 	case CLS_H_NORMAL:
202*4882a593Smuzhiyun 	case CLS_AB:
203*4882a593Smuzhiyun 		val = WCD9XXX_HPH_CONST_SEL_BYPASS;
204*4882a593Smuzhiyun 		break;
205*4882a593Smuzhiyun 	case CLS_H_HIFI:
206*4882a593Smuzhiyun 		val = WCD9XXX_HPH_CONST_SEL_HQ_PATH;
207*4882a593Smuzhiyun 		break;
208*4882a593Smuzhiyun 	case CLS_H_LP:
209*4882a593Smuzhiyun 		val = WCD9XXX_HPH_CONST_SEL_LP_PATH;
210*4882a593Smuzhiyun 		break;
211*4882a593Smuzhiyun 	}
212*4882a593Smuzhiyun 
213*4882a593Smuzhiyun 	snd_soc_component_update_bits(comp, WCD9XXX_HPH_L_EN,
214*4882a593Smuzhiyun 					WCD9XXX_HPH_CONST_SEL_L_MASK,
215*4882a593Smuzhiyun 					val);
216*4882a593Smuzhiyun 
217*4882a593Smuzhiyun 	snd_soc_component_update_bits(comp, WCD9XXX_HPH_R_EN,
218*4882a593Smuzhiyun 					WCD9XXX_HPH_CONST_SEL_L_MASK,
219*4882a593Smuzhiyun 					val);
220*4882a593Smuzhiyun }
221*4882a593Smuzhiyun 
wcd_clsh_set_hph_mode(struct snd_soc_component * comp,int mode)222*4882a593Smuzhiyun static void wcd_clsh_set_hph_mode(struct snd_soc_component *comp,
223*4882a593Smuzhiyun 				  int mode)
224*4882a593Smuzhiyun {
225*4882a593Smuzhiyun 	int val = 0, gain = 0, res_val;
226*4882a593Smuzhiyun 	int ipeak = WCD9XXX_CLASSH_CTRL_CCL_1_DELTA_IPEAK_50MA;
227*4882a593Smuzhiyun 
228*4882a593Smuzhiyun 	res_val = WCD9XXX_CLASSH_CTRL_VCL_VREF_FILT_R_0KOHM;
229*4882a593Smuzhiyun 	switch (mode) {
230*4882a593Smuzhiyun 	case CLS_H_NORMAL:
231*4882a593Smuzhiyun 		res_val = WCD9XXX_CLASSH_CTRL_VCL_VREF_FILT_R_50KOHM;
232*4882a593Smuzhiyun 		val = WCD9XXX_A_ANA_HPH_PWR_LEVEL_NORMAL;
233*4882a593Smuzhiyun 		gain = DAC_GAIN_0DB;
234*4882a593Smuzhiyun 		ipeak = WCD9XXX_CLASSH_CTRL_CCL_1_DELTA_IPEAK_50MA;
235*4882a593Smuzhiyun 		break;
236*4882a593Smuzhiyun 	case CLS_AB:
237*4882a593Smuzhiyun 		val = WCD9XXX_A_ANA_HPH_PWR_LEVEL_NORMAL;
238*4882a593Smuzhiyun 		gain = DAC_GAIN_0DB;
239*4882a593Smuzhiyun 		ipeak = WCD9XXX_CLASSH_CTRL_CCL_1_DELTA_IPEAK_50MA;
240*4882a593Smuzhiyun 		break;
241*4882a593Smuzhiyun 	case CLS_H_HIFI:
242*4882a593Smuzhiyun 		val = WCD9XXX_A_ANA_HPH_PWR_LEVEL_UHQA;
243*4882a593Smuzhiyun 		gain = DAC_GAIN_M0P2DB;
244*4882a593Smuzhiyun 		ipeak = WCD9XXX_CLASSH_CTRL_CCL_1_DELTA_IPEAK_50MA;
245*4882a593Smuzhiyun 		break;
246*4882a593Smuzhiyun 	case CLS_H_LP:
247*4882a593Smuzhiyun 		val = WCD9XXX_A_ANA_HPH_PWR_LEVEL_LP;
248*4882a593Smuzhiyun 		ipeak = WCD9XXX_CLASSH_CTRL_CCL_1_DELTA_IPEAK_30MA;
249*4882a593Smuzhiyun 		break;
250*4882a593Smuzhiyun 	}
251*4882a593Smuzhiyun 
252*4882a593Smuzhiyun 	snd_soc_component_update_bits(comp, WCD9XXX_A_ANA_HPH,
253*4882a593Smuzhiyun 					WCD9XXX_A_ANA_HPH_PWR_LEVEL_MASK, val);
254*4882a593Smuzhiyun 	snd_soc_component_update_bits(comp, WCD9XXX_CLASSH_CTRL_VCL_2,
255*4882a593Smuzhiyun 				WCD9XXX_CLASSH_CTRL_VCL_2_VREF_FILT_1_MASK,
256*4882a593Smuzhiyun 				res_val);
257*4882a593Smuzhiyun 	if (mode != CLS_H_LP)
258*4882a593Smuzhiyun 		snd_soc_component_update_bits(comp,
259*4882a593Smuzhiyun 					WCD9XXX_HPH_REFBUFF_UHQA_CTL,
260*4882a593Smuzhiyun 					WCD9XXX_HPH_REFBUFF_UHQA_GAIN_MASK,
261*4882a593Smuzhiyun 					gain);
262*4882a593Smuzhiyun 	snd_soc_component_update_bits(comp, WCD9XXX_CLASSH_CTRL_CCL_1,
263*4882a593Smuzhiyun 				WCD9XXX_CLASSH_CTRL_CCL_1_DELTA_IPEAK_MASK,
264*4882a593Smuzhiyun 				ipeak);
265*4882a593Smuzhiyun }
266*4882a593Smuzhiyun 
wcd_clsh_set_flyback_current(struct snd_soc_component * comp,int mode)267*4882a593Smuzhiyun static void wcd_clsh_set_flyback_current(struct snd_soc_component *comp,
268*4882a593Smuzhiyun 					 int mode)
269*4882a593Smuzhiyun {
270*4882a593Smuzhiyun 
271*4882a593Smuzhiyun 	snd_soc_component_update_bits(comp, WCD9XXX_RX_BIAS_FLYB_BUFF,
272*4882a593Smuzhiyun 				WCD9XXX_RX_BIAS_FLYB_VPOS_5_UA_MASK, 0x0A);
273*4882a593Smuzhiyun 	snd_soc_component_update_bits(comp, WCD9XXX_RX_BIAS_FLYB_BUFF,
274*4882a593Smuzhiyun 				WCD9XXX_RX_BIAS_FLYB_VNEG_5_UA_MASK, 0x0A);
275*4882a593Smuzhiyun 	/* Sleep needed to avoid click and pop as per HW requirement */
276*4882a593Smuzhiyun 	usleep_range(100, 110);
277*4882a593Smuzhiyun }
278*4882a593Smuzhiyun 
wcd_clsh_set_buck_regulator_mode(struct snd_soc_component * comp,int mode)279*4882a593Smuzhiyun static void wcd_clsh_set_buck_regulator_mode(struct snd_soc_component *comp,
280*4882a593Smuzhiyun 					     int mode)
281*4882a593Smuzhiyun {
282*4882a593Smuzhiyun 	if (mode == CLS_AB)
283*4882a593Smuzhiyun 		snd_soc_component_update_bits(comp, WCD9XXX_A_ANA_RX_SUPPLIES,
284*4882a593Smuzhiyun 					WCD9XXX_A_ANA_RX_REGULATOR_MODE_MASK,
285*4882a593Smuzhiyun 					WCD9XXX_A_ANA_RX_REGULATOR_MODE_CLS_AB);
286*4882a593Smuzhiyun 	else
287*4882a593Smuzhiyun 		snd_soc_component_update_bits(comp, WCD9XXX_A_ANA_RX_SUPPLIES,
288*4882a593Smuzhiyun 					WCD9XXX_A_ANA_RX_REGULATOR_MODE_MASK,
289*4882a593Smuzhiyun 					WCD9XXX_A_ANA_RX_REGULATOR_MODE_CLS_H);
290*4882a593Smuzhiyun }
291*4882a593Smuzhiyun 
wcd_clsh_state_lo(struct wcd_clsh_ctrl * ctrl,int req_state,bool is_enable,int mode)292*4882a593Smuzhiyun static void wcd_clsh_state_lo(struct wcd_clsh_ctrl *ctrl, int req_state,
293*4882a593Smuzhiyun 			      bool is_enable, int mode)
294*4882a593Smuzhiyun {
295*4882a593Smuzhiyun 	struct snd_soc_component *comp = ctrl->comp;
296*4882a593Smuzhiyun 
297*4882a593Smuzhiyun 	if (mode != CLS_AB) {
298*4882a593Smuzhiyun 		dev_err(comp->dev, "%s: LO cannot be in this mode: %d\n",
299*4882a593Smuzhiyun 			__func__, mode);
300*4882a593Smuzhiyun 		return;
301*4882a593Smuzhiyun 	}
302*4882a593Smuzhiyun 
303*4882a593Smuzhiyun 	if (is_enable) {
304*4882a593Smuzhiyun 		wcd_clsh_set_buck_regulator_mode(comp, mode);
305*4882a593Smuzhiyun 		wcd_clsh_set_buck_mode(comp, mode);
306*4882a593Smuzhiyun 		wcd_clsh_set_flyback_mode(comp, mode);
307*4882a593Smuzhiyun 		wcd_clsh_flyback_ctrl(ctrl, mode, true);
308*4882a593Smuzhiyun 		wcd_clsh_set_flyback_current(comp, mode);
309*4882a593Smuzhiyun 		wcd_clsh_buck_ctrl(ctrl, mode, true);
310*4882a593Smuzhiyun 	} else {
311*4882a593Smuzhiyun 		wcd_clsh_buck_ctrl(ctrl, mode, false);
312*4882a593Smuzhiyun 		wcd_clsh_flyback_ctrl(ctrl, mode, false);
313*4882a593Smuzhiyun 		wcd_clsh_set_flyback_mode(comp, CLS_H_NORMAL);
314*4882a593Smuzhiyun 		wcd_clsh_set_buck_mode(comp, CLS_H_NORMAL);
315*4882a593Smuzhiyun 		wcd_clsh_set_buck_regulator_mode(comp, CLS_H_NORMAL);
316*4882a593Smuzhiyun 	}
317*4882a593Smuzhiyun }
318*4882a593Smuzhiyun 
wcd_clsh_state_hph_r(struct wcd_clsh_ctrl * ctrl,int req_state,bool is_enable,int mode)319*4882a593Smuzhiyun static void wcd_clsh_state_hph_r(struct wcd_clsh_ctrl *ctrl, int req_state,
320*4882a593Smuzhiyun 				 bool is_enable, int mode)
321*4882a593Smuzhiyun {
322*4882a593Smuzhiyun 	struct snd_soc_component *comp = ctrl->comp;
323*4882a593Smuzhiyun 
324*4882a593Smuzhiyun 	if (mode == CLS_H_NORMAL) {
325*4882a593Smuzhiyun 		dev_err(comp->dev, "%s: Normal mode not applicable for hph_r\n",
326*4882a593Smuzhiyun 			__func__);
327*4882a593Smuzhiyun 		return;
328*4882a593Smuzhiyun 	}
329*4882a593Smuzhiyun 
330*4882a593Smuzhiyun 	if (is_enable) {
331*4882a593Smuzhiyun 		if (mode != CLS_AB) {
332*4882a593Smuzhiyun 			wcd_enable_clsh_block(ctrl, true);
333*4882a593Smuzhiyun 			/*
334*4882a593Smuzhiyun 			 * These K1 values depend on the Headphone Impedance
335*4882a593Smuzhiyun 			 * For now it is assumed to be 16 ohm
336*4882a593Smuzhiyun 			 */
337*4882a593Smuzhiyun 			snd_soc_component_update_bits(comp,
338*4882a593Smuzhiyun 					WCD9XXX_A_CDC_CLSH_K1_MSB,
339*4882a593Smuzhiyun 					WCD9XXX_A_CDC_CLSH_K1_MSB_COEF_MASK,
340*4882a593Smuzhiyun 					0x00);
341*4882a593Smuzhiyun 			snd_soc_component_update_bits(comp,
342*4882a593Smuzhiyun 					WCD9XXX_A_CDC_CLSH_K1_LSB,
343*4882a593Smuzhiyun 					WCD9XXX_A_CDC_CLSH_K1_LSB_COEF_MASK,
344*4882a593Smuzhiyun 					0xC0);
345*4882a593Smuzhiyun 			snd_soc_component_update_bits(comp,
346*4882a593Smuzhiyun 					    WCD9XXX_A_CDC_RX2_RX_PATH_CFG0,
347*4882a593Smuzhiyun 					    WCD9XXX_A_CDC_RX_PATH_CLSH_EN_MASK,
348*4882a593Smuzhiyun 					    WCD9XXX_A_CDC_RX_PATH_CLSH_ENABLE);
349*4882a593Smuzhiyun 		}
350*4882a593Smuzhiyun 		wcd_clsh_set_buck_regulator_mode(comp, mode);
351*4882a593Smuzhiyun 		wcd_clsh_set_flyback_mode(comp, mode);
352*4882a593Smuzhiyun 		wcd_clsh_flyback_ctrl(ctrl, mode, true);
353*4882a593Smuzhiyun 		wcd_clsh_set_flyback_current(comp, mode);
354*4882a593Smuzhiyun 		wcd_clsh_set_buck_mode(comp, mode);
355*4882a593Smuzhiyun 		wcd_clsh_buck_ctrl(ctrl, mode, true);
356*4882a593Smuzhiyun 		wcd_clsh_set_hph_mode(comp, mode);
357*4882a593Smuzhiyun 		wcd_clsh_set_gain_path(ctrl, mode);
358*4882a593Smuzhiyun 	} else {
359*4882a593Smuzhiyun 		wcd_clsh_set_hph_mode(comp, CLS_H_NORMAL);
360*4882a593Smuzhiyun 
361*4882a593Smuzhiyun 		if (mode != CLS_AB) {
362*4882a593Smuzhiyun 			snd_soc_component_update_bits(comp,
363*4882a593Smuzhiyun 					    WCD9XXX_A_CDC_RX2_RX_PATH_CFG0,
364*4882a593Smuzhiyun 					    WCD9XXX_A_CDC_RX_PATH_CLSH_EN_MASK,
365*4882a593Smuzhiyun 					    WCD9XXX_A_CDC_RX_PATH_CLSH_DISABLE);
366*4882a593Smuzhiyun 			wcd_enable_clsh_block(ctrl, false);
367*4882a593Smuzhiyun 		}
368*4882a593Smuzhiyun 		/* buck and flyback set to default mode and disable */
369*4882a593Smuzhiyun 		wcd_clsh_buck_ctrl(ctrl, CLS_H_NORMAL, false);
370*4882a593Smuzhiyun 		wcd_clsh_flyback_ctrl(ctrl, CLS_H_NORMAL, false);
371*4882a593Smuzhiyun 		wcd_clsh_set_flyback_mode(comp, CLS_H_NORMAL);
372*4882a593Smuzhiyun 		wcd_clsh_set_buck_mode(comp, CLS_H_NORMAL);
373*4882a593Smuzhiyun 		wcd_clsh_set_buck_regulator_mode(comp, CLS_H_NORMAL);
374*4882a593Smuzhiyun 	}
375*4882a593Smuzhiyun }
376*4882a593Smuzhiyun 
wcd_clsh_state_hph_l(struct wcd_clsh_ctrl * ctrl,int req_state,bool is_enable,int mode)377*4882a593Smuzhiyun static void wcd_clsh_state_hph_l(struct wcd_clsh_ctrl *ctrl, int req_state,
378*4882a593Smuzhiyun 				 bool is_enable, int mode)
379*4882a593Smuzhiyun {
380*4882a593Smuzhiyun 	struct snd_soc_component *comp = ctrl->comp;
381*4882a593Smuzhiyun 
382*4882a593Smuzhiyun 	if (mode == CLS_H_NORMAL) {
383*4882a593Smuzhiyun 		dev_err(comp->dev, "%s: Normal mode not applicable for hph_l\n",
384*4882a593Smuzhiyun 			__func__);
385*4882a593Smuzhiyun 		return;
386*4882a593Smuzhiyun 	}
387*4882a593Smuzhiyun 
388*4882a593Smuzhiyun 	if (is_enable) {
389*4882a593Smuzhiyun 		if (mode != CLS_AB) {
390*4882a593Smuzhiyun 			wcd_enable_clsh_block(ctrl, true);
391*4882a593Smuzhiyun 			/*
392*4882a593Smuzhiyun 			 * These K1 values depend on the Headphone Impedance
393*4882a593Smuzhiyun 			 * For now it is assumed to be 16 ohm
394*4882a593Smuzhiyun 			 */
395*4882a593Smuzhiyun 			snd_soc_component_update_bits(comp,
396*4882a593Smuzhiyun 					WCD9XXX_A_CDC_CLSH_K1_MSB,
397*4882a593Smuzhiyun 					WCD9XXX_A_CDC_CLSH_K1_MSB_COEF_MASK,
398*4882a593Smuzhiyun 					0x00);
399*4882a593Smuzhiyun 			snd_soc_component_update_bits(comp,
400*4882a593Smuzhiyun 					WCD9XXX_A_CDC_CLSH_K1_LSB,
401*4882a593Smuzhiyun 					WCD9XXX_A_CDC_CLSH_K1_LSB_COEF_MASK,
402*4882a593Smuzhiyun 					0xC0);
403*4882a593Smuzhiyun 			snd_soc_component_update_bits(comp,
404*4882a593Smuzhiyun 					    WCD9XXX_A_CDC_RX1_RX_PATH_CFG0,
405*4882a593Smuzhiyun 					    WCD9XXX_A_CDC_RX_PATH_CLSH_EN_MASK,
406*4882a593Smuzhiyun 					    WCD9XXX_A_CDC_RX_PATH_CLSH_ENABLE);
407*4882a593Smuzhiyun 		}
408*4882a593Smuzhiyun 		wcd_clsh_set_buck_regulator_mode(comp, mode);
409*4882a593Smuzhiyun 		wcd_clsh_set_flyback_mode(comp, mode);
410*4882a593Smuzhiyun 		wcd_clsh_flyback_ctrl(ctrl, mode, true);
411*4882a593Smuzhiyun 		wcd_clsh_set_flyback_current(comp, mode);
412*4882a593Smuzhiyun 		wcd_clsh_set_buck_mode(comp, mode);
413*4882a593Smuzhiyun 		wcd_clsh_buck_ctrl(ctrl, mode, true);
414*4882a593Smuzhiyun 		wcd_clsh_set_hph_mode(comp, mode);
415*4882a593Smuzhiyun 		wcd_clsh_set_gain_path(ctrl, mode);
416*4882a593Smuzhiyun 	} else {
417*4882a593Smuzhiyun 		wcd_clsh_set_hph_mode(comp, CLS_H_NORMAL);
418*4882a593Smuzhiyun 
419*4882a593Smuzhiyun 		if (mode != CLS_AB) {
420*4882a593Smuzhiyun 			snd_soc_component_update_bits(comp,
421*4882a593Smuzhiyun 					    WCD9XXX_A_CDC_RX1_RX_PATH_CFG0,
422*4882a593Smuzhiyun 					    WCD9XXX_A_CDC_RX_PATH_CLSH_EN_MASK,
423*4882a593Smuzhiyun 					    WCD9XXX_A_CDC_RX_PATH_CLSH_DISABLE);
424*4882a593Smuzhiyun 			wcd_enable_clsh_block(ctrl, false);
425*4882a593Smuzhiyun 		}
426*4882a593Smuzhiyun 		/* set buck and flyback to Default Mode */
427*4882a593Smuzhiyun 		wcd_clsh_buck_ctrl(ctrl, CLS_H_NORMAL, false);
428*4882a593Smuzhiyun 		wcd_clsh_flyback_ctrl(ctrl, CLS_H_NORMAL, false);
429*4882a593Smuzhiyun 		wcd_clsh_set_flyback_mode(comp, CLS_H_NORMAL);
430*4882a593Smuzhiyun 		wcd_clsh_set_buck_mode(comp, CLS_H_NORMAL);
431*4882a593Smuzhiyun 		wcd_clsh_set_buck_regulator_mode(comp, CLS_H_NORMAL);
432*4882a593Smuzhiyun 	}
433*4882a593Smuzhiyun }
434*4882a593Smuzhiyun 
wcd_clsh_state_ear(struct wcd_clsh_ctrl * ctrl,int req_state,bool is_enable,int mode)435*4882a593Smuzhiyun static void wcd_clsh_state_ear(struct wcd_clsh_ctrl *ctrl, int req_state,
436*4882a593Smuzhiyun 			       bool is_enable, int mode)
437*4882a593Smuzhiyun {
438*4882a593Smuzhiyun 	struct snd_soc_component *comp = ctrl->comp;
439*4882a593Smuzhiyun 
440*4882a593Smuzhiyun 	if (mode != CLS_H_NORMAL) {
441*4882a593Smuzhiyun 		dev_err(comp->dev, "%s: mode: %d cannot be used for EAR\n",
442*4882a593Smuzhiyun 			__func__, mode);
443*4882a593Smuzhiyun 		return;
444*4882a593Smuzhiyun 	}
445*4882a593Smuzhiyun 
446*4882a593Smuzhiyun 	if (is_enable) {
447*4882a593Smuzhiyun 		wcd_enable_clsh_block(ctrl, true);
448*4882a593Smuzhiyun 		snd_soc_component_update_bits(comp,
449*4882a593Smuzhiyun 					WCD9XXX_A_CDC_RX0_RX_PATH_CFG0,
450*4882a593Smuzhiyun 					WCD9XXX_A_CDC_RX_PATH_CLSH_EN_MASK,
451*4882a593Smuzhiyun 					WCD9XXX_A_CDC_RX_PATH_CLSH_ENABLE);
452*4882a593Smuzhiyun 		wcd_clsh_set_buck_mode(comp, mode);
453*4882a593Smuzhiyun 		wcd_clsh_set_flyback_mode(comp, mode);
454*4882a593Smuzhiyun 		wcd_clsh_flyback_ctrl(ctrl, mode, true);
455*4882a593Smuzhiyun 		wcd_clsh_set_flyback_current(comp, mode);
456*4882a593Smuzhiyun 		wcd_clsh_buck_ctrl(ctrl, mode, true);
457*4882a593Smuzhiyun 	} else {
458*4882a593Smuzhiyun 		snd_soc_component_update_bits(comp,
459*4882a593Smuzhiyun 					WCD9XXX_A_CDC_RX0_RX_PATH_CFG0,
460*4882a593Smuzhiyun 					WCD9XXX_A_CDC_RX_PATH_CLSH_EN_MASK,
461*4882a593Smuzhiyun 					WCD9XXX_A_CDC_RX_PATH_CLSH_DISABLE);
462*4882a593Smuzhiyun 		wcd_enable_clsh_block(ctrl, false);
463*4882a593Smuzhiyun 		wcd_clsh_buck_ctrl(ctrl, mode, false);
464*4882a593Smuzhiyun 		wcd_clsh_flyback_ctrl(ctrl, mode, false);
465*4882a593Smuzhiyun 		wcd_clsh_set_flyback_mode(comp, CLS_H_NORMAL);
466*4882a593Smuzhiyun 		wcd_clsh_set_buck_mode(comp, CLS_H_NORMAL);
467*4882a593Smuzhiyun 	}
468*4882a593Smuzhiyun }
469*4882a593Smuzhiyun 
_wcd_clsh_ctrl_set_state(struct wcd_clsh_ctrl * ctrl,int req_state,bool is_enable,int mode)470*4882a593Smuzhiyun static int _wcd_clsh_ctrl_set_state(struct wcd_clsh_ctrl *ctrl, int req_state,
471*4882a593Smuzhiyun 				    bool is_enable, int mode)
472*4882a593Smuzhiyun {
473*4882a593Smuzhiyun 	switch (req_state) {
474*4882a593Smuzhiyun 	case WCD_CLSH_STATE_EAR:
475*4882a593Smuzhiyun 		wcd_clsh_state_ear(ctrl, req_state, is_enable, mode);
476*4882a593Smuzhiyun 		break;
477*4882a593Smuzhiyun 	case WCD_CLSH_STATE_HPHL:
478*4882a593Smuzhiyun 		wcd_clsh_state_hph_l(ctrl, req_state, is_enable, mode);
479*4882a593Smuzhiyun 		break;
480*4882a593Smuzhiyun 	case WCD_CLSH_STATE_HPHR:
481*4882a593Smuzhiyun 		wcd_clsh_state_hph_r(ctrl, req_state, is_enable, mode);
482*4882a593Smuzhiyun 		break;
483*4882a593Smuzhiyun 		break;
484*4882a593Smuzhiyun 	case WCD_CLSH_STATE_LO:
485*4882a593Smuzhiyun 		wcd_clsh_state_lo(ctrl, req_state, is_enable, mode);
486*4882a593Smuzhiyun 		break;
487*4882a593Smuzhiyun 	default:
488*4882a593Smuzhiyun 		break;
489*4882a593Smuzhiyun 	}
490*4882a593Smuzhiyun 
491*4882a593Smuzhiyun 	return 0;
492*4882a593Smuzhiyun }
493*4882a593Smuzhiyun 
494*4882a593Smuzhiyun /*
495*4882a593Smuzhiyun  * Function: wcd_clsh_is_state_valid
496*4882a593Smuzhiyun  * Params: state
497*4882a593Smuzhiyun  * Description:
498*4882a593Smuzhiyun  * Provides information on valid states of Class H configuration
499*4882a593Smuzhiyun  */
wcd_clsh_is_state_valid(int state)500*4882a593Smuzhiyun static bool wcd_clsh_is_state_valid(int state)
501*4882a593Smuzhiyun {
502*4882a593Smuzhiyun 	switch (state) {
503*4882a593Smuzhiyun 	case WCD_CLSH_STATE_IDLE:
504*4882a593Smuzhiyun 	case WCD_CLSH_STATE_EAR:
505*4882a593Smuzhiyun 	case WCD_CLSH_STATE_HPHL:
506*4882a593Smuzhiyun 	case WCD_CLSH_STATE_HPHR:
507*4882a593Smuzhiyun 	case WCD_CLSH_STATE_LO:
508*4882a593Smuzhiyun 		return true;
509*4882a593Smuzhiyun 	default:
510*4882a593Smuzhiyun 		return false;
511*4882a593Smuzhiyun 	};
512*4882a593Smuzhiyun }
513*4882a593Smuzhiyun 
514*4882a593Smuzhiyun /*
515*4882a593Smuzhiyun  * Function: wcd_clsh_fsm
516*4882a593Smuzhiyun  * Params: ctrl, req_state, req_type, clsh_event
517*4882a593Smuzhiyun  * Description:
518*4882a593Smuzhiyun  * This function handles PRE DAC and POST DAC conditions of different devices
519*4882a593Smuzhiyun  * and updates class H configuration of different combination of devices
520*4882a593Smuzhiyun  * based on validity of their states. ctrl will contain current
521*4882a593Smuzhiyun  * class h state information
522*4882a593Smuzhiyun  */
wcd_clsh_ctrl_set_state(struct wcd_clsh_ctrl * ctrl,enum wcd_clsh_event clsh_event,int nstate,enum wcd_clsh_mode mode)523*4882a593Smuzhiyun int wcd_clsh_ctrl_set_state(struct wcd_clsh_ctrl *ctrl,
524*4882a593Smuzhiyun 			    enum wcd_clsh_event clsh_event,
525*4882a593Smuzhiyun 			    int nstate,
526*4882a593Smuzhiyun 			    enum wcd_clsh_mode mode)
527*4882a593Smuzhiyun {
528*4882a593Smuzhiyun 	struct snd_soc_component *comp = ctrl->comp;
529*4882a593Smuzhiyun 
530*4882a593Smuzhiyun 	if (nstate == ctrl->state)
531*4882a593Smuzhiyun 		return 0;
532*4882a593Smuzhiyun 
533*4882a593Smuzhiyun 	if (!wcd_clsh_is_state_valid(nstate)) {
534*4882a593Smuzhiyun 		dev_err(comp->dev, "Class-H not a valid new state:\n");
535*4882a593Smuzhiyun 		return -EINVAL;
536*4882a593Smuzhiyun 	}
537*4882a593Smuzhiyun 
538*4882a593Smuzhiyun 	switch (clsh_event) {
539*4882a593Smuzhiyun 	case WCD_CLSH_EVENT_PRE_DAC:
540*4882a593Smuzhiyun 		_wcd_clsh_ctrl_set_state(ctrl, nstate, CLSH_REQ_ENABLE, mode);
541*4882a593Smuzhiyun 		break;
542*4882a593Smuzhiyun 	case WCD_CLSH_EVENT_POST_PA:
543*4882a593Smuzhiyun 		_wcd_clsh_ctrl_set_state(ctrl, nstate, CLSH_REQ_DISABLE, mode);
544*4882a593Smuzhiyun 		break;
545*4882a593Smuzhiyun 	}
546*4882a593Smuzhiyun 
547*4882a593Smuzhiyun 	ctrl->state = nstate;
548*4882a593Smuzhiyun 	ctrl->mode = mode;
549*4882a593Smuzhiyun 
550*4882a593Smuzhiyun 	return 0;
551*4882a593Smuzhiyun }
552*4882a593Smuzhiyun 
wcd_clsh_ctrl_get_state(struct wcd_clsh_ctrl * ctrl)553*4882a593Smuzhiyun int wcd_clsh_ctrl_get_state(struct wcd_clsh_ctrl *ctrl)
554*4882a593Smuzhiyun {
555*4882a593Smuzhiyun 	return ctrl->state;
556*4882a593Smuzhiyun }
557*4882a593Smuzhiyun 
wcd_clsh_ctrl_alloc(struct snd_soc_component * comp,int version)558*4882a593Smuzhiyun struct wcd_clsh_ctrl *wcd_clsh_ctrl_alloc(struct snd_soc_component *comp,
559*4882a593Smuzhiyun 					  int version)
560*4882a593Smuzhiyun {
561*4882a593Smuzhiyun 	struct wcd_clsh_ctrl *ctrl;
562*4882a593Smuzhiyun 
563*4882a593Smuzhiyun 	ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL);
564*4882a593Smuzhiyun 	if (!ctrl)
565*4882a593Smuzhiyun 		return ERR_PTR(-ENOMEM);
566*4882a593Smuzhiyun 
567*4882a593Smuzhiyun 	ctrl->state = WCD_CLSH_STATE_IDLE;
568*4882a593Smuzhiyun 	ctrl->comp = comp;
569*4882a593Smuzhiyun 
570*4882a593Smuzhiyun 	return ctrl;
571*4882a593Smuzhiyun }
572*4882a593Smuzhiyun 
wcd_clsh_ctrl_free(struct wcd_clsh_ctrl * ctrl)573*4882a593Smuzhiyun void wcd_clsh_ctrl_free(struct wcd_clsh_ctrl *ctrl)
574*4882a593Smuzhiyun {
575*4882a593Smuzhiyun 	kfree(ctrl);
576*4882a593Smuzhiyun }
577