xref: /openbmc/linux/sound/soc/codecs/wcd-clsh-v2.c (revision 11b0b802)
1cc2e324dSSrinivas Kandagatla // SPDX-License-Identifier: GPL-2.0
2cc2e324dSSrinivas Kandagatla // Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
3cc2e324dSSrinivas Kandagatla // Copyright (c) 2017-2018, Linaro Limited
4cc2e324dSSrinivas Kandagatla 
5cc2e324dSSrinivas Kandagatla #include <linux/slab.h>
6cc2e324dSSrinivas Kandagatla #include <sound/soc.h>
7cc2e324dSSrinivas Kandagatla #include <linux/kernel.h>
8cc2e324dSSrinivas Kandagatla #include <linux/delay.h>
9cc2e324dSSrinivas Kandagatla #include "wcd9335.h"
10cc2e324dSSrinivas Kandagatla #include "wcd-clsh-v2.h"
11cc2e324dSSrinivas Kandagatla 
12cc2e324dSSrinivas Kandagatla struct wcd_clsh_ctrl {
13cc2e324dSSrinivas Kandagatla 	int state;
14cc2e324dSSrinivas Kandagatla 	int mode;
15cc2e324dSSrinivas Kandagatla 	int flyback_users;
16cc2e324dSSrinivas Kandagatla 	int buck_users;
17cc2e324dSSrinivas Kandagatla 	int clsh_users;
18cc2e324dSSrinivas Kandagatla 	int codec_version;
19cc2e324dSSrinivas Kandagatla 	struct snd_soc_component *comp;
20cc2e324dSSrinivas Kandagatla };
21cc2e324dSSrinivas Kandagatla 
22cc2e324dSSrinivas Kandagatla /* Class-H registers for codecs from and above WCD9335 */
23cc2e324dSSrinivas Kandagatla #define WCD9XXX_A_CDC_RX0_RX_PATH_CFG0			WCD9335_REG(0xB, 0x42)
24cc2e324dSSrinivas Kandagatla #define WCD9XXX_A_CDC_RX_PATH_CLSH_EN_MASK		BIT(6)
25cc2e324dSSrinivas Kandagatla #define WCD9XXX_A_CDC_RX_PATH_CLSH_ENABLE		BIT(6)
26cc2e324dSSrinivas Kandagatla #define WCD9XXX_A_CDC_RX_PATH_CLSH_DISABLE		0
27cc2e324dSSrinivas Kandagatla #define WCD9XXX_A_CDC_RX1_RX_PATH_CFG0			WCD9335_REG(0xB, 0x56)
28cc2e324dSSrinivas Kandagatla #define WCD9XXX_A_CDC_RX2_RX_PATH_CFG0			WCD9335_REG(0xB, 0x6A)
29cc2e324dSSrinivas Kandagatla #define WCD9XXX_A_CDC_CLSH_K1_MSB			WCD9335_REG(0xC, 0x08)
30cc2e324dSSrinivas Kandagatla #define WCD9XXX_A_CDC_CLSH_K1_MSB_COEF_MASK		GENMASK(3, 0)
31cc2e324dSSrinivas Kandagatla #define WCD9XXX_A_CDC_CLSH_K1_LSB			WCD9335_REG(0xC, 0x09)
32cc2e324dSSrinivas Kandagatla #define WCD9XXX_A_CDC_CLSH_K1_LSB_COEF_MASK		GENMASK(7, 0)
33cc2e324dSSrinivas Kandagatla #define WCD9XXX_A_ANA_RX_SUPPLIES			WCD9335_REG(0x6, 0x08)
34cc2e324dSSrinivas Kandagatla #define WCD9XXX_A_ANA_RX_REGULATOR_MODE_MASK		BIT(1)
35cc2e324dSSrinivas Kandagatla #define WCD9XXX_A_ANA_RX_REGULATOR_MODE_CLS_H		0
36cc2e324dSSrinivas Kandagatla #define WCD9XXX_A_ANA_RX_REGULATOR_MODE_CLS_AB		BIT(1)
37cc2e324dSSrinivas Kandagatla #define WCD9XXX_A_ANA_RX_VNEG_PWR_LVL_MASK		BIT(2)
38cc2e324dSSrinivas Kandagatla #define WCD9XXX_A_ANA_RX_VNEG_PWR_LVL_UHQA		BIT(2)
39cc2e324dSSrinivas Kandagatla #define WCD9XXX_A_ANA_RX_VNEG_PWR_LVL_DEFAULT		0
40cc2e324dSSrinivas Kandagatla #define WCD9XXX_A_ANA_RX_VPOS_PWR_LVL_MASK		BIT(3)
41cc2e324dSSrinivas Kandagatla #define WCD9XXX_A_ANA_RX_VPOS_PWR_LVL_UHQA		BIT(3)
42cc2e324dSSrinivas Kandagatla #define WCD9XXX_A_ANA_RX_VPOS_PWR_LVL_DEFAULT		0
43cc2e324dSSrinivas Kandagatla #define WCD9XXX_A_ANA_RX_VNEG_EN_MASK			BIT(6)
44cc2e324dSSrinivas Kandagatla #define WCD9XXX_A_ANA_RX_VNEG_EN_SHIFT			6
45cc2e324dSSrinivas Kandagatla #define WCD9XXX_A_ANA_RX_VNEG_ENABLE			BIT(6)
46cc2e324dSSrinivas Kandagatla #define WCD9XXX_A_ANA_RX_VNEG_DISABLE			0
47cc2e324dSSrinivas Kandagatla #define WCD9XXX_A_ANA_RX_VPOS_EN_MASK			BIT(7)
48cc2e324dSSrinivas Kandagatla #define WCD9XXX_A_ANA_RX_VPOS_EN_SHIFT			7
49cc2e324dSSrinivas Kandagatla #define WCD9XXX_A_ANA_RX_VPOS_ENABLE			BIT(7)
50cc2e324dSSrinivas Kandagatla #define WCD9XXX_A_ANA_RX_VPOS_DISABLE			0
51cc2e324dSSrinivas Kandagatla #define WCD9XXX_A_ANA_HPH				WCD9335_REG(0x6, 0x09)
52cc2e324dSSrinivas Kandagatla #define WCD9XXX_A_ANA_HPH_PWR_LEVEL_MASK		GENMASK(3, 2)
53cc2e324dSSrinivas Kandagatla #define WCD9XXX_A_ANA_HPH_PWR_LEVEL_UHQA		0x08
54cc2e324dSSrinivas Kandagatla #define WCD9XXX_A_ANA_HPH_PWR_LEVEL_LP			0x04
55cc2e324dSSrinivas Kandagatla #define WCD9XXX_A_ANA_HPH_PWR_LEVEL_NORMAL		0x0
56cc2e324dSSrinivas Kandagatla #define WCD9XXX_A_CDC_CLSH_CRC				WCD9335_REG(0xC, 0x01)
57cc2e324dSSrinivas Kandagatla #define WCD9XXX_A_CDC_CLSH_CRC_CLK_EN_MASK		BIT(0)
58cc2e324dSSrinivas Kandagatla #define WCD9XXX_A_CDC_CLSH_CRC_CLK_ENABLE		BIT(0)
59cc2e324dSSrinivas Kandagatla #define WCD9XXX_A_CDC_CLSH_CRC_CLK_DISABLE		0
60cc2e324dSSrinivas Kandagatla #define WCD9XXX_FLYBACK_EN				WCD9335_REG(0x6, 0xA4)
61cc2e324dSSrinivas Kandagatla #define WCD9XXX_FLYBACK_EN_DELAY_SEL_MASK		GENMASK(6, 5)
62cc2e324dSSrinivas Kandagatla #define WCD9XXX_FLYBACK_EN_DELAY_26P25_US		0x40
63cc2e324dSSrinivas Kandagatla #define WCD9XXX_FLYBACK_EN_RESET_BY_EXT_MASK		BIT(4)
64cc2e324dSSrinivas Kandagatla #define WCD9XXX_FLYBACK_EN_PWDN_WITHOUT_DELAY		BIT(4)
65cc2e324dSSrinivas Kandagatla #define WCD9XXX_FLYBACK_EN_PWDN_WITH_DELAY			0
66cc2e324dSSrinivas Kandagatla #define WCD9XXX_RX_BIAS_FLYB_BUFF			WCD9335_REG(0x6, 0xC7)
67cc2e324dSSrinivas Kandagatla #define WCD9XXX_RX_BIAS_FLYB_VNEG_5_UA_MASK		GENMASK(7, 4)
68f7408a3dSJoe Perches #define WCD9XXX_RX_BIAS_FLYB_VPOS_5_UA_MASK		GENMASK(3, 0)
69cc2e324dSSrinivas Kandagatla #define WCD9XXX_HPH_L_EN				WCD9335_REG(0x6, 0xD3)
70cc2e324dSSrinivas Kandagatla #define WCD9XXX_HPH_CONST_SEL_L_MASK			GENMASK(7, 3)
71cc2e324dSSrinivas Kandagatla #define WCD9XXX_HPH_CONST_SEL_BYPASS			0
72cc2e324dSSrinivas Kandagatla #define WCD9XXX_HPH_CONST_SEL_LP_PATH			0x40
73cc2e324dSSrinivas Kandagatla #define WCD9XXX_HPH_CONST_SEL_HQ_PATH			0x80
74cc2e324dSSrinivas Kandagatla #define WCD9XXX_HPH_R_EN				WCD9335_REG(0x6, 0xD6)
75cc2e324dSSrinivas Kandagatla #define WCD9XXX_HPH_REFBUFF_UHQA_CTL			WCD9335_REG(0x6, 0xDD)
76cc2e324dSSrinivas Kandagatla #define WCD9XXX_HPH_REFBUFF_UHQA_GAIN_MASK		GENMASK(2, 0)
77cc2e324dSSrinivas Kandagatla #define WCD9XXX_CLASSH_CTRL_VCL_2                       WCD9335_REG(0x6, 0x9B)
78cc2e324dSSrinivas Kandagatla #define WCD9XXX_CLASSH_CTRL_VCL_2_VREF_FILT_1_MASK	GENMASK(5, 4)
79cc2e324dSSrinivas Kandagatla #define WCD9XXX_CLASSH_CTRL_VCL_VREF_FILT_R_50KOHM	0x20
80cc2e324dSSrinivas Kandagatla #define WCD9XXX_CLASSH_CTRL_VCL_VREF_FILT_R_0KOHM	0x0
81cc2e324dSSrinivas Kandagatla #define WCD9XXX_CDC_RX1_RX_PATH_CTL			WCD9335_REG(0xB, 0x55)
82cc2e324dSSrinivas Kandagatla #define WCD9XXX_CDC_RX2_RX_PATH_CTL			WCD9335_REG(0xB, 0x69)
83cc2e324dSSrinivas Kandagatla #define WCD9XXX_CDC_CLK_RST_CTRL_MCLK_CONTROL		WCD9335_REG(0xD, 0x41)
84cc2e324dSSrinivas Kandagatla #define WCD9XXX_CDC_CLK_RST_CTRL_MCLK_EN_MASK		BIT(0)
85cc2e324dSSrinivas Kandagatla #define WCD9XXX_CDC_CLK_RST_CTRL_MCLK_11P3_EN_MASK	BIT(1)
86cc2e324dSSrinivas Kandagatla #define WCD9XXX_CLASSH_CTRL_CCL_1                       WCD9335_REG(0x6, 0x9C)
87cc2e324dSSrinivas Kandagatla #define WCD9XXX_CLASSH_CTRL_CCL_1_DELTA_IPEAK_MASK	GENMASK(7, 4)
88cc2e324dSSrinivas Kandagatla #define WCD9XXX_CLASSH_CTRL_CCL_1_DELTA_IPEAK_50MA	0x50
89cc2e324dSSrinivas Kandagatla #define WCD9XXX_CLASSH_CTRL_CCL_1_DELTA_IPEAK_30MA	0x30
90cc2e324dSSrinivas Kandagatla 
9119c5d1f6SSrinivas Kandagatla #define WCD9XXX_BASE_ADDRESS				0x3000
9219c5d1f6SSrinivas Kandagatla #define WCD9XXX_ANA_RX_SUPPLIES				(WCD9XXX_BASE_ADDRESS+0x008)
9319c5d1f6SSrinivas Kandagatla #define WCD9XXX_ANA_HPH					(WCD9XXX_BASE_ADDRESS+0x009)
9419c5d1f6SSrinivas Kandagatla #define WCD9XXX_CLASSH_MODE_2				(WCD9XXX_BASE_ADDRESS+0x098)
9519c5d1f6SSrinivas Kandagatla #define WCD9XXX_CLASSH_MODE_3				(WCD9XXX_BASE_ADDRESS+0x099)
9619c5d1f6SSrinivas Kandagatla #define WCD9XXX_FLYBACK_VNEG_CTRL_1			(WCD9XXX_BASE_ADDRESS+0x0A5)
9719c5d1f6SSrinivas Kandagatla #define WCD9XXX_FLYBACK_VNEG_CTRL_4			(WCD9XXX_BASE_ADDRESS+0x0A8)
9819c5d1f6SSrinivas Kandagatla #define WCD9XXX_FLYBACK_VNEGDAC_CTRL_2			(WCD9XXX_BASE_ADDRESS+0x0AF)
9919c5d1f6SSrinivas Kandagatla #define WCD9XXX_RX_BIAS_HPH_LOWPOWER			(WCD9XXX_BASE_ADDRESS+0x0BF)
10019c5d1f6SSrinivas Kandagatla #define WCD9XXX_V3_RX_BIAS_FLYB_BUFF			(WCD9XXX_BASE_ADDRESS+0x0C7)
10119c5d1f6SSrinivas Kandagatla #define WCD9XXX_HPH_PA_CTL1				(WCD9XXX_BASE_ADDRESS+0x0D1)
10219c5d1f6SSrinivas Kandagatla #define WCD9XXX_HPH_NEW_INT_PA_MISC2			(WCD9XXX_BASE_ADDRESS+0x138)
10319c5d1f6SSrinivas Kandagatla 
104cc2e324dSSrinivas Kandagatla #define CLSH_REQ_ENABLE		true
105cc2e324dSSrinivas Kandagatla #define CLSH_REQ_DISABLE	false
106cc2e324dSSrinivas Kandagatla #define WCD_USLEEP_RANGE	50
107cc2e324dSSrinivas Kandagatla 
108cc2e324dSSrinivas Kandagatla enum {
109cc2e324dSSrinivas Kandagatla 	DAC_GAIN_0DB = 0,
110cc2e324dSSrinivas Kandagatla 	DAC_GAIN_0P2DB,
111cc2e324dSSrinivas Kandagatla 	DAC_GAIN_0P4DB,
112cc2e324dSSrinivas Kandagatla 	DAC_GAIN_0P6DB,
113cc2e324dSSrinivas Kandagatla 	DAC_GAIN_0P8DB,
114cc2e324dSSrinivas Kandagatla 	DAC_GAIN_M0P2DB,
115cc2e324dSSrinivas Kandagatla 	DAC_GAIN_M0P4DB,
116cc2e324dSSrinivas Kandagatla 	DAC_GAIN_M0P6DB,
117cc2e324dSSrinivas Kandagatla };
118cc2e324dSSrinivas Kandagatla 
wcd_enable_clsh_block(struct wcd_clsh_ctrl * ctrl,bool enable)119cc2e324dSSrinivas Kandagatla static inline void wcd_enable_clsh_block(struct wcd_clsh_ctrl *ctrl,
120cc2e324dSSrinivas Kandagatla 					 bool enable)
121cc2e324dSSrinivas Kandagatla {
122cc2e324dSSrinivas Kandagatla 	struct snd_soc_component *comp = ctrl->comp;
123cc2e324dSSrinivas Kandagatla 
124cc2e324dSSrinivas Kandagatla 	if ((enable && ++ctrl->clsh_users == 1) ||
125cc2e324dSSrinivas Kandagatla 	    (!enable && --ctrl->clsh_users == 0))
126cc2e324dSSrinivas Kandagatla 		snd_soc_component_update_bits(comp, WCD9XXX_A_CDC_CLSH_CRC,
127cc2e324dSSrinivas Kandagatla 				      WCD9XXX_A_CDC_CLSH_CRC_CLK_EN_MASK,
128cc2e324dSSrinivas Kandagatla 				      enable);
129cc2e324dSSrinivas Kandagatla 	if (ctrl->clsh_users < 0)
130cc2e324dSSrinivas Kandagatla 		ctrl->clsh_users = 0;
131cc2e324dSSrinivas Kandagatla }
132cc2e324dSSrinivas Kandagatla 
wcd_clsh_set_buck_mode(struct snd_soc_component * comp,int mode)133cc2e324dSSrinivas Kandagatla static inline void wcd_clsh_set_buck_mode(struct snd_soc_component *comp,
134cc2e324dSSrinivas Kandagatla 					  int mode)
135cc2e324dSSrinivas Kandagatla {
136cc2e324dSSrinivas Kandagatla 	/* set to HIFI */
137cc2e324dSSrinivas Kandagatla 	if (mode == CLS_H_HIFI)
138cc2e324dSSrinivas Kandagatla 		snd_soc_component_update_bits(comp, WCD9XXX_A_ANA_RX_SUPPLIES,
139cc2e324dSSrinivas Kandagatla 					WCD9XXX_A_ANA_RX_VPOS_PWR_LVL_MASK,
140cc2e324dSSrinivas Kandagatla 					WCD9XXX_A_ANA_RX_VPOS_PWR_LVL_UHQA);
141cc2e324dSSrinivas Kandagatla 	else
142cc2e324dSSrinivas Kandagatla 		snd_soc_component_update_bits(comp, WCD9XXX_A_ANA_RX_SUPPLIES,
143cc2e324dSSrinivas Kandagatla 					WCD9XXX_A_ANA_RX_VPOS_PWR_LVL_MASK,
144cc2e324dSSrinivas Kandagatla 					WCD9XXX_A_ANA_RX_VPOS_PWR_LVL_DEFAULT);
145cc2e324dSSrinivas Kandagatla }
146cc2e324dSSrinivas Kandagatla 
wcd_clsh_v3_set_buck_mode(struct snd_soc_component * component,int mode)14719c5d1f6SSrinivas Kandagatla static void wcd_clsh_v3_set_buck_mode(struct snd_soc_component *component,
14819c5d1f6SSrinivas Kandagatla 					  int mode)
14919c5d1f6SSrinivas Kandagatla {
15019c5d1f6SSrinivas Kandagatla 	if (mode == CLS_H_HIFI || mode == CLS_H_LOHIFI ||
15119c5d1f6SSrinivas Kandagatla 	    mode == CLS_AB_HIFI || mode == CLS_AB_LOHIFI)
15219c5d1f6SSrinivas Kandagatla 		snd_soc_component_update_bits(component,
15319c5d1f6SSrinivas Kandagatla 				WCD9XXX_ANA_RX_SUPPLIES,
15419c5d1f6SSrinivas Kandagatla 				0x08, 0x08); /* set to HIFI */
15519c5d1f6SSrinivas Kandagatla 	else
15619c5d1f6SSrinivas Kandagatla 		snd_soc_component_update_bits(component,
15719c5d1f6SSrinivas Kandagatla 				WCD9XXX_ANA_RX_SUPPLIES,
15819c5d1f6SSrinivas Kandagatla 				0x08, 0x00); /* set to default */
15919c5d1f6SSrinivas Kandagatla }
16019c5d1f6SSrinivas Kandagatla 
wcd_clsh_set_flyback_mode(struct snd_soc_component * comp,int mode)161cc2e324dSSrinivas Kandagatla static inline void wcd_clsh_set_flyback_mode(struct snd_soc_component *comp,
162cc2e324dSSrinivas Kandagatla 					     int mode)
163cc2e324dSSrinivas Kandagatla {
164cc2e324dSSrinivas Kandagatla 	/* set to HIFI */
165cc2e324dSSrinivas Kandagatla 	if (mode == CLS_H_HIFI)
166cc2e324dSSrinivas Kandagatla 		snd_soc_component_update_bits(comp, WCD9XXX_A_ANA_RX_SUPPLIES,
167cc2e324dSSrinivas Kandagatla 					WCD9XXX_A_ANA_RX_VNEG_PWR_LVL_MASK,
168cc2e324dSSrinivas Kandagatla 					WCD9XXX_A_ANA_RX_VNEG_PWR_LVL_UHQA);
169cc2e324dSSrinivas Kandagatla 	else
170cc2e324dSSrinivas Kandagatla 		snd_soc_component_update_bits(comp, WCD9XXX_A_ANA_RX_SUPPLIES,
171cc2e324dSSrinivas Kandagatla 					WCD9XXX_A_ANA_RX_VNEG_PWR_LVL_MASK,
172cc2e324dSSrinivas Kandagatla 					WCD9XXX_A_ANA_RX_VNEG_PWR_LVL_DEFAULT);
173cc2e324dSSrinivas Kandagatla }
174cc2e324dSSrinivas Kandagatla 
wcd_clsh_buck_ctrl(struct wcd_clsh_ctrl * ctrl,int mode,bool enable)175cc2e324dSSrinivas Kandagatla static void wcd_clsh_buck_ctrl(struct wcd_clsh_ctrl *ctrl,
176cc2e324dSSrinivas Kandagatla 			       int mode,
177cc2e324dSSrinivas Kandagatla 			       bool enable)
178cc2e324dSSrinivas Kandagatla {
179cc2e324dSSrinivas Kandagatla 	struct snd_soc_component *comp = ctrl->comp;
180cc2e324dSSrinivas Kandagatla 
181cc2e324dSSrinivas Kandagatla 	/* enable/disable buck */
182cc2e324dSSrinivas Kandagatla 	if ((enable && (++ctrl->buck_users == 1)) ||
183cc2e324dSSrinivas Kandagatla 	   (!enable && (--ctrl->buck_users == 0)))
184cc2e324dSSrinivas Kandagatla 		snd_soc_component_update_bits(comp, WCD9XXX_A_ANA_RX_SUPPLIES,
185cc2e324dSSrinivas Kandagatla 				WCD9XXX_A_ANA_RX_VPOS_EN_MASK,
186cc2e324dSSrinivas Kandagatla 				enable << WCD9XXX_A_ANA_RX_VPOS_EN_SHIFT);
187cc2e324dSSrinivas Kandagatla 	/*
188cc2e324dSSrinivas Kandagatla 	 * 500us sleep is required after buck enable/disable
189cc2e324dSSrinivas Kandagatla 	 * as per HW requirement
190cc2e324dSSrinivas Kandagatla 	 */
191cc2e324dSSrinivas Kandagatla 	usleep_range(500, 500 + WCD_USLEEP_RANGE);
192cc2e324dSSrinivas Kandagatla }
193cc2e324dSSrinivas Kandagatla 
wcd_clsh_v3_buck_ctrl(struct snd_soc_component * component,struct wcd_clsh_ctrl * ctrl,int mode,bool enable)19419c5d1f6SSrinivas Kandagatla static void wcd_clsh_v3_buck_ctrl(struct snd_soc_component *component,
19519c5d1f6SSrinivas Kandagatla 			       struct wcd_clsh_ctrl *ctrl,
19619c5d1f6SSrinivas Kandagatla 			       int mode,
19719c5d1f6SSrinivas Kandagatla 			       bool enable)
19819c5d1f6SSrinivas Kandagatla {
19919c5d1f6SSrinivas Kandagatla 	/* enable/disable buck */
20019c5d1f6SSrinivas Kandagatla 	if ((enable && (++ctrl->buck_users == 1)) ||
20119c5d1f6SSrinivas Kandagatla 	   (!enable && (--ctrl->buck_users == 0))) {
20219c5d1f6SSrinivas Kandagatla 		snd_soc_component_update_bits(component,
20319c5d1f6SSrinivas Kandagatla 				WCD9XXX_ANA_RX_SUPPLIES,
20419c5d1f6SSrinivas Kandagatla 				(1 << 7), (enable << 7));
20519c5d1f6SSrinivas Kandagatla 		/*
20619c5d1f6SSrinivas Kandagatla 		 * 500us sleep is required after buck enable/disable
20719c5d1f6SSrinivas Kandagatla 		 * as per HW requirement
20819c5d1f6SSrinivas Kandagatla 		 */
20919c5d1f6SSrinivas Kandagatla 		usleep_range(500, 510);
21019c5d1f6SSrinivas Kandagatla 		if (mode == CLS_H_LOHIFI || mode == CLS_H_ULP ||
21119c5d1f6SSrinivas Kandagatla 			mode == CLS_H_HIFI || mode == CLS_H_LP)
21219c5d1f6SSrinivas Kandagatla 			snd_soc_component_update_bits(component,
21319c5d1f6SSrinivas Kandagatla 					WCD9XXX_CLASSH_MODE_3,
21419c5d1f6SSrinivas Kandagatla 					0x02, 0x00);
21519c5d1f6SSrinivas Kandagatla 
21619c5d1f6SSrinivas Kandagatla 		snd_soc_component_update_bits(component,
21719c5d1f6SSrinivas Kandagatla 					WCD9XXX_CLASSH_MODE_2,
21819c5d1f6SSrinivas Kandagatla 					0xFF, 0x3A);
21919c5d1f6SSrinivas Kandagatla 		/* 500usec delay is needed as per HW requirement */
22019c5d1f6SSrinivas Kandagatla 		usleep_range(500, 500 + WCD_USLEEP_RANGE);
22119c5d1f6SSrinivas Kandagatla 	}
22219c5d1f6SSrinivas Kandagatla }
22319c5d1f6SSrinivas Kandagatla 
wcd_clsh_flyback_ctrl(struct wcd_clsh_ctrl * ctrl,int mode,bool enable)224cc2e324dSSrinivas Kandagatla static void wcd_clsh_flyback_ctrl(struct wcd_clsh_ctrl *ctrl,
225cc2e324dSSrinivas Kandagatla 				  int mode,
226cc2e324dSSrinivas Kandagatla 				  bool enable)
227cc2e324dSSrinivas Kandagatla {
228cc2e324dSSrinivas Kandagatla 	struct snd_soc_component *comp = ctrl->comp;
229cc2e324dSSrinivas Kandagatla 
230cc2e324dSSrinivas Kandagatla 	/* enable/disable flyback */
231cc2e324dSSrinivas Kandagatla 	if ((enable && (++ctrl->flyback_users == 1)) ||
232cc2e324dSSrinivas Kandagatla 	   (!enable && (--ctrl->flyback_users == 0))) {
233cc2e324dSSrinivas Kandagatla 		snd_soc_component_update_bits(comp, WCD9XXX_A_ANA_RX_SUPPLIES,
234cc2e324dSSrinivas Kandagatla 				WCD9XXX_A_ANA_RX_VNEG_EN_MASK,
235cc2e324dSSrinivas Kandagatla 				enable << WCD9XXX_A_ANA_RX_VNEG_EN_SHIFT);
236cc2e324dSSrinivas Kandagatla 		/* 100usec delay is needed as per HW requirement */
237cc2e324dSSrinivas Kandagatla 		usleep_range(100, 110);
238cc2e324dSSrinivas Kandagatla 	}
239cc2e324dSSrinivas Kandagatla 	/*
240cc2e324dSSrinivas Kandagatla 	 * 500us sleep is required after flyback enable/disable
241cc2e324dSSrinivas Kandagatla 	 * as per HW requirement
242cc2e324dSSrinivas Kandagatla 	 */
243cc2e324dSSrinivas Kandagatla 	usleep_range(500, 500 + WCD_USLEEP_RANGE);
244cc2e324dSSrinivas Kandagatla }
245cc2e324dSSrinivas Kandagatla 
wcd_clsh_set_gain_path(struct wcd_clsh_ctrl * ctrl,int mode)246cc2e324dSSrinivas Kandagatla static void wcd_clsh_set_gain_path(struct wcd_clsh_ctrl *ctrl, int mode)
247cc2e324dSSrinivas Kandagatla {
248cc2e324dSSrinivas Kandagatla 	struct snd_soc_component *comp = ctrl->comp;
249cc2e324dSSrinivas Kandagatla 	int val = 0;
250cc2e324dSSrinivas Kandagatla 
251cc2e324dSSrinivas Kandagatla 	switch (mode) {
252cc2e324dSSrinivas Kandagatla 	case CLS_H_NORMAL:
253cc2e324dSSrinivas Kandagatla 	case CLS_AB:
254cc2e324dSSrinivas Kandagatla 		val = WCD9XXX_HPH_CONST_SEL_BYPASS;
255cc2e324dSSrinivas Kandagatla 		break;
256cc2e324dSSrinivas Kandagatla 	case CLS_H_HIFI:
257cc2e324dSSrinivas Kandagatla 		val = WCD9XXX_HPH_CONST_SEL_HQ_PATH;
258cc2e324dSSrinivas Kandagatla 		break;
259cc2e324dSSrinivas Kandagatla 	case CLS_H_LP:
260cc2e324dSSrinivas Kandagatla 		val = WCD9XXX_HPH_CONST_SEL_LP_PATH;
261cc2e324dSSrinivas Kandagatla 		break;
262afb86626Skbuild test robot 	}
263cc2e324dSSrinivas Kandagatla 
264cc2e324dSSrinivas Kandagatla 	snd_soc_component_update_bits(comp, WCD9XXX_HPH_L_EN,
265cc2e324dSSrinivas Kandagatla 					WCD9XXX_HPH_CONST_SEL_L_MASK,
266cc2e324dSSrinivas Kandagatla 					val);
267cc2e324dSSrinivas Kandagatla 
268cc2e324dSSrinivas Kandagatla 	snd_soc_component_update_bits(comp, WCD9XXX_HPH_R_EN,
269cc2e324dSSrinivas Kandagatla 					WCD9XXX_HPH_CONST_SEL_L_MASK,
270cc2e324dSSrinivas Kandagatla 					val);
271cc2e324dSSrinivas Kandagatla }
272cc2e324dSSrinivas Kandagatla 
wcd_clsh_v2_set_hph_mode(struct snd_soc_component * comp,int mode)27319c5d1f6SSrinivas Kandagatla static void wcd_clsh_v2_set_hph_mode(struct snd_soc_component *comp, int mode)
274cc2e324dSSrinivas Kandagatla {
275cc2e324dSSrinivas Kandagatla 	int val = 0, gain = 0, res_val;
276cc2e324dSSrinivas Kandagatla 	int ipeak = WCD9XXX_CLASSH_CTRL_CCL_1_DELTA_IPEAK_50MA;
277cc2e324dSSrinivas Kandagatla 
278cc2e324dSSrinivas Kandagatla 	res_val = WCD9XXX_CLASSH_CTRL_VCL_VREF_FILT_R_0KOHM;
279cc2e324dSSrinivas Kandagatla 	switch (mode) {
280cc2e324dSSrinivas Kandagatla 	case CLS_H_NORMAL:
281cc2e324dSSrinivas Kandagatla 		res_val = WCD9XXX_CLASSH_CTRL_VCL_VREF_FILT_R_50KOHM;
282cc2e324dSSrinivas Kandagatla 		val = WCD9XXX_A_ANA_HPH_PWR_LEVEL_NORMAL;
283cc2e324dSSrinivas Kandagatla 		gain = DAC_GAIN_0DB;
284cc2e324dSSrinivas Kandagatla 		ipeak = WCD9XXX_CLASSH_CTRL_CCL_1_DELTA_IPEAK_50MA;
285cc2e324dSSrinivas Kandagatla 		break;
286cc2e324dSSrinivas Kandagatla 	case CLS_AB:
287cc2e324dSSrinivas Kandagatla 		val = WCD9XXX_A_ANA_HPH_PWR_LEVEL_NORMAL;
288cc2e324dSSrinivas Kandagatla 		gain = DAC_GAIN_0DB;
289cc2e324dSSrinivas Kandagatla 		ipeak = WCD9XXX_CLASSH_CTRL_CCL_1_DELTA_IPEAK_50MA;
290cc2e324dSSrinivas Kandagatla 		break;
291cc2e324dSSrinivas Kandagatla 	case CLS_H_HIFI:
292cc2e324dSSrinivas Kandagatla 		val = WCD9XXX_A_ANA_HPH_PWR_LEVEL_UHQA;
293cc2e324dSSrinivas Kandagatla 		gain = DAC_GAIN_M0P2DB;
294cc2e324dSSrinivas Kandagatla 		ipeak = WCD9XXX_CLASSH_CTRL_CCL_1_DELTA_IPEAK_50MA;
295cc2e324dSSrinivas Kandagatla 		break;
296cc2e324dSSrinivas Kandagatla 	case CLS_H_LP:
297cc2e324dSSrinivas Kandagatla 		val = WCD9XXX_A_ANA_HPH_PWR_LEVEL_LP;
298cc2e324dSSrinivas Kandagatla 		ipeak = WCD9XXX_CLASSH_CTRL_CCL_1_DELTA_IPEAK_30MA;
299cc2e324dSSrinivas Kandagatla 		break;
300afb86626Skbuild test robot 	}
301cc2e324dSSrinivas Kandagatla 
302cc2e324dSSrinivas Kandagatla 	snd_soc_component_update_bits(comp, WCD9XXX_A_ANA_HPH,
303cc2e324dSSrinivas Kandagatla 					WCD9XXX_A_ANA_HPH_PWR_LEVEL_MASK, val);
304cc2e324dSSrinivas Kandagatla 	snd_soc_component_update_bits(comp, WCD9XXX_CLASSH_CTRL_VCL_2,
305cc2e324dSSrinivas Kandagatla 				WCD9XXX_CLASSH_CTRL_VCL_2_VREF_FILT_1_MASK,
306cc2e324dSSrinivas Kandagatla 				res_val);
307cc2e324dSSrinivas Kandagatla 	if (mode != CLS_H_LP)
308cc2e324dSSrinivas Kandagatla 		snd_soc_component_update_bits(comp,
309cc2e324dSSrinivas Kandagatla 					WCD9XXX_HPH_REFBUFF_UHQA_CTL,
310cc2e324dSSrinivas Kandagatla 					WCD9XXX_HPH_REFBUFF_UHQA_GAIN_MASK,
311cc2e324dSSrinivas Kandagatla 					gain);
312cc2e324dSSrinivas Kandagatla 	snd_soc_component_update_bits(comp, WCD9XXX_CLASSH_CTRL_CCL_1,
313cc2e324dSSrinivas Kandagatla 				WCD9XXX_CLASSH_CTRL_CCL_1_DELTA_IPEAK_MASK,
314cc2e324dSSrinivas Kandagatla 				ipeak);
315cc2e324dSSrinivas Kandagatla }
316cc2e324dSSrinivas Kandagatla 
wcd_clsh_v3_set_hph_mode(struct snd_soc_component * component,int mode)31719c5d1f6SSrinivas Kandagatla static void wcd_clsh_v3_set_hph_mode(struct snd_soc_component *component,
31819c5d1f6SSrinivas Kandagatla 				  int mode)
31919c5d1f6SSrinivas Kandagatla {
32019c5d1f6SSrinivas Kandagatla 	u8 val;
32119c5d1f6SSrinivas Kandagatla 
32219c5d1f6SSrinivas Kandagatla 	switch (mode) {
32319c5d1f6SSrinivas Kandagatla 	case CLS_H_NORMAL:
32419c5d1f6SSrinivas Kandagatla 		val = 0x00;
32519c5d1f6SSrinivas Kandagatla 		break;
32619c5d1f6SSrinivas Kandagatla 	case CLS_AB:
32719c5d1f6SSrinivas Kandagatla 	case CLS_H_ULP:
32819c5d1f6SSrinivas Kandagatla 		val = 0x0C;
32919c5d1f6SSrinivas Kandagatla 		break;
33019c5d1f6SSrinivas Kandagatla 	case CLS_AB_HIFI:
33119c5d1f6SSrinivas Kandagatla 	case CLS_H_HIFI:
33219c5d1f6SSrinivas Kandagatla 		val = 0x08;
33319c5d1f6SSrinivas Kandagatla 		break;
33419c5d1f6SSrinivas Kandagatla 	case CLS_H_LP:
33519c5d1f6SSrinivas Kandagatla 	case CLS_H_LOHIFI:
33619c5d1f6SSrinivas Kandagatla 	case CLS_AB_LP:
33719c5d1f6SSrinivas Kandagatla 	case CLS_AB_LOHIFI:
33819c5d1f6SSrinivas Kandagatla 		val = 0x04;
33919c5d1f6SSrinivas Kandagatla 		break;
34019c5d1f6SSrinivas Kandagatla 	default:
34119c5d1f6SSrinivas Kandagatla 		dev_err(component->dev, "%s:Invalid mode %d\n", __func__, mode);
34219c5d1f6SSrinivas Kandagatla 		return;
34319c5d1f6SSrinivas Kandagatla 	}
34419c5d1f6SSrinivas Kandagatla 
34519c5d1f6SSrinivas Kandagatla 	snd_soc_component_update_bits(component, WCD9XXX_ANA_HPH, 0x0C, val);
34619c5d1f6SSrinivas Kandagatla }
34719c5d1f6SSrinivas Kandagatla 
wcd_clsh_set_hph_mode(struct wcd_clsh_ctrl * ctrl,int mode)34819c5d1f6SSrinivas Kandagatla void wcd_clsh_set_hph_mode(struct wcd_clsh_ctrl *ctrl, int mode)
34919c5d1f6SSrinivas Kandagatla {
35019c5d1f6SSrinivas Kandagatla 	struct snd_soc_component *comp = ctrl->comp;
35119c5d1f6SSrinivas Kandagatla 
35219c5d1f6SSrinivas Kandagatla 	if (ctrl->codec_version >= WCD937X)
35319c5d1f6SSrinivas Kandagatla 		wcd_clsh_v3_set_hph_mode(comp, mode);
35419c5d1f6SSrinivas Kandagatla 	else
35519c5d1f6SSrinivas Kandagatla 		wcd_clsh_v2_set_hph_mode(comp, mode);
35619c5d1f6SSrinivas Kandagatla 
35719c5d1f6SSrinivas Kandagatla }
358*11b0b802SKrzysztof Kozlowski EXPORT_SYMBOL_GPL(wcd_clsh_set_hph_mode);
35919c5d1f6SSrinivas Kandagatla 
wcd_clsh_set_flyback_current(struct snd_soc_component * comp,int mode)360cc2e324dSSrinivas Kandagatla static void wcd_clsh_set_flyback_current(struct snd_soc_component *comp,
361cc2e324dSSrinivas Kandagatla 					 int mode)
362cc2e324dSSrinivas Kandagatla {
363cc2e324dSSrinivas Kandagatla 
364cc2e324dSSrinivas Kandagatla 	snd_soc_component_update_bits(comp, WCD9XXX_RX_BIAS_FLYB_BUFF,
365cc2e324dSSrinivas Kandagatla 				WCD9XXX_RX_BIAS_FLYB_VPOS_5_UA_MASK, 0x0A);
366cc2e324dSSrinivas Kandagatla 	snd_soc_component_update_bits(comp, WCD9XXX_RX_BIAS_FLYB_BUFF,
367cc2e324dSSrinivas Kandagatla 				WCD9XXX_RX_BIAS_FLYB_VNEG_5_UA_MASK, 0x0A);
368cc2e324dSSrinivas Kandagatla 	/* Sleep needed to avoid click and pop as per HW requirement */
369cc2e324dSSrinivas Kandagatla 	usleep_range(100, 110);
370cc2e324dSSrinivas Kandagatla }
371cc2e324dSSrinivas Kandagatla 
wcd_clsh_set_buck_regulator_mode(struct snd_soc_component * comp,int mode)372cc2e324dSSrinivas Kandagatla static void wcd_clsh_set_buck_regulator_mode(struct snd_soc_component *comp,
373cc2e324dSSrinivas Kandagatla 					     int mode)
374cc2e324dSSrinivas Kandagatla {
375cc2e324dSSrinivas Kandagatla 	if (mode == CLS_AB)
376cc2e324dSSrinivas Kandagatla 		snd_soc_component_update_bits(comp, WCD9XXX_A_ANA_RX_SUPPLIES,
377cc2e324dSSrinivas Kandagatla 					WCD9XXX_A_ANA_RX_REGULATOR_MODE_MASK,
378cc2e324dSSrinivas Kandagatla 					WCD9XXX_A_ANA_RX_REGULATOR_MODE_CLS_AB);
379cc2e324dSSrinivas Kandagatla 	else
380cc2e324dSSrinivas Kandagatla 		snd_soc_component_update_bits(comp, WCD9XXX_A_ANA_RX_SUPPLIES,
381cc2e324dSSrinivas Kandagatla 					WCD9XXX_A_ANA_RX_REGULATOR_MODE_MASK,
382cc2e324dSSrinivas Kandagatla 					WCD9XXX_A_ANA_RX_REGULATOR_MODE_CLS_H);
383cc2e324dSSrinivas Kandagatla }
384cc2e324dSSrinivas Kandagatla 
wcd_clsh_v3_set_buck_regulator_mode(struct snd_soc_component * component,int mode)38519c5d1f6SSrinivas Kandagatla static void wcd_clsh_v3_set_buck_regulator_mode(struct snd_soc_component *component,
38619c5d1f6SSrinivas Kandagatla 						int mode)
38719c5d1f6SSrinivas Kandagatla {
38819c5d1f6SSrinivas Kandagatla 	snd_soc_component_update_bits(component, WCD9XXX_ANA_RX_SUPPLIES,
38919c5d1f6SSrinivas Kandagatla 			    0x02, 0x00);
39019c5d1f6SSrinivas Kandagatla }
39119c5d1f6SSrinivas Kandagatla 
wcd_clsh_v3_set_flyback_mode(struct snd_soc_component * component,int mode)39219c5d1f6SSrinivas Kandagatla static void wcd_clsh_v3_set_flyback_mode(struct snd_soc_component *component,
39319c5d1f6SSrinivas Kandagatla 						int mode)
39419c5d1f6SSrinivas Kandagatla {
39519c5d1f6SSrinivas Kandagatla 	if (mode == CLS_H_HIFI || mode == CLS_H_LOHIFI ||
39619c5d1f6SSrinivas Kandagatla 	    mode == CLS_AB_HIFI || mode == CLS_AB_LOHIFI) {
39719c5d1f6SSrinivas Kandagatla 		snd_soc_component_update_bits(component,
39819c5d1f6SSrinivas Kandagatla 				WCD9XXX_ANA_RX_SUPPLIES,
39919c5d1f6SSrinivas Kandagatla 				0x04, 0x04);
40019c5d1f6SSrinivas Kandagatla 		snd_soc_component_update_bits(component,
40119c5d1f6SSrinivas Kandagatla 				WCD9XXX_FLYBACK_VNEG_CTRL_4,
40219c5d1f6SSrinivas Kandagatla 				0xF0, 0x80);
40319c5d1f6SSrinivas Kandagatla 	} else {
40419c5d1f6SSrinivas Kandagatla 		snd_soc_component_update_bits(component,
40519c5d1f6SSrinivas Kandagatla 				WCD9XXX_ANA_RX_SUPPLIES,
40619c5d1f6SSrinivas Kandagatla 				0x04, 0x00); /* set to Default */
40719c5d1f6SSrinivas Kandagatla 		snd_soc_component_update_bits(component,
40819c5d1f6SSrinivas Kandagatla 				WCD9XXX_FLYBACK_VNEG_CTRL_4,
40919c5d1f6SSrinivas Kandagatla 				0xF0, 0x70);
41019c5d1f6SSrinivas Kandagatla 	}
41119c5d1f6SSrinivas Kandagatla }
41219c5d1f6SSrinivas Kandagatla 
wcd_clsh_v3_force_iq_ctl(struct snd_soc_component * component,int mode,bool enable)41319c5d1f6SSrinivas Kandagatla static void wcd_clsh_v3_force_iq_ctl(struct snd_soc_component *component,
41419c5d1f6SSrinivas Kandagatla 					 int mode, bool enable)
41519c5d1f6SSrinivas Kandagatla {
41619c5d1f6SSrinivas Kandagatla 	if (enable) {
41719c5d1f6SSrinivas Kandagatla 		snd_soc_component_update_bits(component,
41819c5d1f6SSrinivas Kandagatla 				WCD9XXX_FLYBACK_VNEGDAC_CTRL_2,
41919c5d1f6SSrinivas Kandagatla 				0xE0, 0xA0);
42019c5d1f6SSrinivas Kandagatla 		/* 100usec delay is needed as per HW requirement */
42119c5d1f6SSrinivas Kandagatla 		usleep_range(100, 110);
42219c5d1f6SSrinivas Kandagatla 		snd_soc_component_update_bits(component,
42319c5d1f6SSrinivas Kandagatla 				WCD9XXX_CLASSH_MODE_3,
42419c5d1f6SSrinivas Kandagatla 				0x02, 0x02);
42519c5d1f6SSrinivas Kandagatla 		snd_soc_component_update_bits(component,
42619c5d1f6SSrinivas Kandagatla 				WCD9XXX_CLASSH_MODE_2,
42719c5d1f6SSrinivas Kandagatla 				0xFF, 0x1C);
42819c5d1f6SSrinivas Kandagatla 		if (mode == CLS_H_LOHIFI || mode == CLS_AB_LOHIFI) {
42919c5d1f6SSrinivas Kandagatla 			snd_soc_component_update_bits(component,
43019c5d1f6SSrinivas Kandagatla 					WCD9XXX_HPH_NEW_INT_PA_MISC2,
43119c5d1f6SSrinivas Kandagatla 					0x20, 0x20);
43219c5d1f6SSrinivas Kandagatla 			snd_soc_component_update_bits(component,
43319c5d1f6SSrinivas Kandagatla 					WCD9XXX_RX_BIAS_HPH_LOWPOWER,
43419c5d1f6SSrinivas Kandagatla 					0xF0, 0xC0);
43519c5d1f6SSrinivas Kandagatla 			snd_soc_component_update_bits(component,
43619c5d1f6SSrinivas Kandagatla 					WCD9XXX_HPH_PA_CTL1,
43719c5d1f6SSrinivas Kandagatla 					0x0E, 0x02);
43819c5d1f6SSrinivas Kandagatla 		}
43919c5d1f6SSrinivas Kandagatla 	} else {
44019c5d1f6SSrinivas Kandagatla 		snd_soc_component_update_bits(component,
44119c5d1f6SSrinivas Kandagatla 				WCD9XXX_HPH_NEW_INT_PA_MISC2,
44219c5d1f6SSrinivas Kandagatla 				0x20, 0x00);
44319c5d1f6SSrinivas Kandagatla 		snd_soc_component_update_bits(component,
44419c5d1f6SSrinivas Kandagatla 				WCD9XXX_RX_BIAS_HPH_LOWPOWER,
44519c5d1f6SSrinivas Kandagatla 				0xF0, 0x80);
44619c5d1f6SSrinivas Kandagatla 		snd_soc_component_update_bits(component,
44719c5d1f6SSrinivas Kandagatla 				WCD9XXX_HPH_PA_CTL1,
44819c5d1f6SSrinivas Kandagatla 				0x0E, 0x06);
44919c5d1f6SSrinivas Kandagatla 	}
45019c5d1f6SSrinivas Kandagatla }
45119c5d1f6SSrinivas Kandagatla 
wcd_clsh_v3_flyback_ctrl(struct snd_soc_component * component,struct wcd_clsh_ctrl * ctrl,int mode,bool enable)45219c5d1f6SSrinivas Kandagatla static void wcd_clsh_v3_flyback_ctrl(struct snd_soc_component *component,
45319c5d1f6SSrinivas Kandagatla 				  struct wcd_clsh_ctrl *ctrl,
45419c5d1f6SSrinivas Kandagatla 				  int mode,
45519c5d1f6SSrinivas Kandagatla 				  bool enable)
45619c5d1f6SSrinivas Kandagatla {
45719c5d1f6SSrinivas Kandagatla 	/* enable/disable flyback */
45819c5d1f6SSrinivas Kandagatla 	if ((enable && (++ctrl->flyback_users == 1)) ||
45919c5d1f6SSrinivas Kandagatla 	   (!enable && (--ctrl->flyback_users == 0))) {
46019c5d1f6SSrinivas Kandagatla 		snd_soc_component_update_bits(component,
46119c5d1f6SSrinivas Kandagatla 				WCD9XXX_FLYBACK_VNEG_CTRL_1,
46219c5d1f6SSrinivas Kandagatla 				0xE0, 0xE0);
46319c5d1f6SSrinivas Kandagatla 		snd_soc_component_update_bits(component,
46419c5d1f6SSrinivas Kandagatla 				WCD9XXX_ANA_RX_SUPPLIES,
46519c5d1f6SSrinivas Kandagatla 				(1 << 6), (enable << 6));
46619c5d1f6SSrinivas Kandagatla 		/*
46719c5d1f6SSrinivas Kandagatla 		 * 100us sleep is required after flyback enable/disable
46819c5d1f6SSrinivas Kandagatla 		 * as per HW requirement
46919c5d1f6SSrinivas Kandagatla 		 */
47019c5d1f6SSrinivas Kandagatla 		usleep_range(100, 110);
47119c5d1f6SSrinivas Kandagatla 		snd_soc_component_update_bits(component,
47219c5d1f6SSrinivas Kandagatla 				WCD9XXX_FLYBACK_VNEGDAC_CTRL_2,
47319c5d1f6SSrinivas Kandagatla 				0xE0, 0xE0);
47419c5d1f6SSrinivas Kandagatla 		/* 500usec delay is needed as per HW requirement */
47519c5d1f6SSrinivas Kandagatla 		usleep_range(500, 500 + WCD_USLEEP_RANGE);
47619c5d1f6SSrinivas Kandagatla 	}
47719c5d1f6SSrinivas Kandagatla }
47819c5d1f6SSrinivas Kandagatla 
wcd_clsh_v3_set_flyback_current(struct snd_soc_component * component,int mode)47919c5d1f6SSrinivas Kandagatla static void wcd_clsh_v3_set_flyback_current(struct snd_soc_component *component,
48019c5d1f6SSrinivas Kandagatla 				int mode)
48119c5d1f6SSrinivas Kandagatla {
48219c5d1f6SSrinivas Kandagatla 	snd_soc_component_update_bits(component, WCD9XXX_V3_RX_BIAS_FLYB_BUFF,
48319c5d1f6SSrinivas Kandagatla 				0x0F, 0x0A);
48419c5d1f6SSrinivas Kandagatla 	snd_soc_component_update_bits(component, WCD9XXX_V3_RX_BIAS_FLYB_BUFF,
48519c5d1f6SSrinivas Kandagatla 				0xF0, 0xA0);
48619c5d1f6SSrinivas Kandagatla 	/* Sleep needed to avoid click and pop as per HW requirement */
48719c5d1f6SSrinivas Kandagatla 	usleep_range(100, 110);
48819c5d1f6SSrinivas Kandagatla }
48919c5d1f6SSrinivas Kandagatla 
wcd_clsh_v3_state_aux(struct wcd_clsh_ctrl * ctrl,int req_state,bool is_enable,int mode)49019c5d1f6SSrinivas Kandagatla static void wcd_clsh_v3_state_aux(struct wcd_clsh_ctrl *ctrl, int req_state,
49119c5d1f6SSrinivas Kandagatla 			      bool is_enable, int mode)
49219c5d1f6SSrinivas Kandagatla {
49319c5d1f6SSrinivas Kandagatla 	struct snd_soc_component *component = ctrl->comp;
49419c5d1f6SSrinivas Kandagatla 
49519c5d1f6SSrinivas Kandagatla 	if (is_enable) {
49619c5d1f6SSrinivas Kandagatla 		wcd_clsh_v3_set_buck_mode(component, mode);
49719c5d1f6SSrinivas Kandagatla 		wcd_clsh_v3_set_flyback_mode(component, mode);
49819c5d1f6SSrinivas Kandagatla 		wcd_clsh_v3_flyback_ctrl(component, ctrl, mode, true);
49919c5d1f6SSrinivas Kandagatla 		wcd_clsh_v3_set_flyback_current(component, mode);
50019c5d1f6SSrinivas Kandagatla 		wcd_clsh_v3_buck_ctrl(component, ctrl, mode, true);
50119c5d1f6SSrinivas Kandagatla 	} else {
50219c5d1f6SSrinivas Kandagatla 		wcd_clsh_v3_buck_ctrl(component, ctrl, mode, false);
50319c5d1f6SSrinivas Kandagatla 		wcd_clsh_v3_flyback_ctrl(component, ctrl, mode, false);
50419c5d1f6SSrinivas Kandagatla 		wcd_clsh_v3_set_flyback_mode(component, CLS_H_NORMAL);
50519c5d1f6SSrinivas Kandagatla 		wcd_clsh_v3_set_buck_mode(component, CLS_H_NORMAL);
50619c5d1f6SSrinivas Kandagatla 	}
50719c5d1f6SSrinivas Kandagatla }
50819c5d1f6SSrinivas Kandagatla 
wcd_clsh_state_lo(struct wcd_clsh_ctrl * ctrl,int req_state,bool is_enable,int mode)509cc2e324dSSrinivas Kandagatla static void wcd_clsh_state_lo(struct wcd_clsh_ctrl *ctrl, int req_state,
510cc2e324dSSrinivas Kandagatla 			      bool is_enable, int mode)
511cc2e324dSSrinivas Kandagatla {
512cc2e324dSSrinivas Kandagatla 	struct snd_soc_component *comp = ctrl->comp;
513cc2e324dSSrinivas Kandagatla 
514cc2e324dSSrinivas Kandagatla 	if (mode != CLS_AB) {
515cc2e324dSSrinivas Kandagatla 		dev_err(comp->dev, "%s: LO cannot be in this mode: %d\n",
516cc2e324dSSrinivas Kandagatla 			__func__, mode);
517cc2e324dSSrinivas Kandagatla 		return;
518cc2e324dSSrinivas Kandagatla 	}
519cc2e324dSSrinivas Kandagatla 
520cc2e324dSSrinivas Kandagatla 	if (is_enable) {
521cc2e324dSSrinivas Kandagatla 		wcd_clsh_set_buck_regulator_mode(comp, mode);
522cc2e324dSSrinivas Kandagatla 		wcd_clsh_set_buck_mode(comp, mode);
523cc2e324dSSrinivas Kandagatla 		wcd_clsh_set_flyback_mode(comp, mode);
524cc2e324dSSrinivas Kandagatla 		wcd_clsh_flyback_ctrl(ctrl, mode, true);
525cc2e324dSSrinivas Kandagatla 		wcd_clsh_set_flyback_current(comp, mode);
526cc2e324dSSrinivas Kandagatla 		wcd_clsh_buck_ctrl(ctrl, mode, true);
527cc2e324dSSrinivas Kandagatla 	} else {
528cc2e324dSSrinivas Kandagatla 		wcd_clsh_buck_ctrl(ctrl, mode, false);
529cc2e324dSSrinivas Kandagatla 		wcd_clsh_flyback_ctrl(ctrl, mode, false);
530cc2e324dSSrinivas Kandagatla 		wcd_clsh_set_flyback_mode(comp, CLS_H_NORMAL);
531cc2e324dSSrinivas Kandagatla 		wcd_clsh_set_buck_mode(comp, CLS_H_NORMAL);
532cc2e324dSSrinivas Kandagatla 		wcd_clsh_set_buck_regulator_mode(comp, CLS_H_NORMAL);
533cc2e324dSSrinivas Kandagatla 	}
534cc2e324dSSrinivas Kandagatla }
535cc2e324dSSrinivas Kandagatla 
wcd_clsh_v3_state_hph_r(struct wcd_clsh_ctrl * ctrl,int req_state,bool is_enable,int mode)53619c5d1f6SSrinivas Kandagatla static void wcd_clsh_v3_state_hph_r(struct wcd_clsh_ctrl *ctrl, int req_state,
53719c5d1f6SSrinivas Kandagatla 				 bool is_enable, int mode)
53819c5d1f6SSrinivas Kandagatla {
53919c5d1f6SSrinivas Kandagatla 	struct snd_soc_component *component = ctrl->comp;
54019c5d1f6SSrinivas Kandagatla 
54119c5d1f6SSrinivas Kandagatla 	if (mode == CLS_H_NORMAL) {
54219c5d1f6SSrinivas Kandagatla 		dev_dbg(component->dev, "%s: Normal mode not applicable for hph_r\n",
54319c5d1f6SSrinivas Kandagatla 			__func__);
54419c5d1f6SSrinivas Kandagatla 		return;
54519c5d1f6SSrinivas Kandagatla 	}
54619c5d1f6SSrinivas Kandagatla 
54719c5d1f6SSrinivas Kandagatla 	if (is_enable) {
54819c5d1f6SSrinivas Kandagatla 		wcd_clsh_v3_set_buck_regulator_mode(component, mode);
54919c5d1f6SSrinivas Kandagatla 		wcd_clsh_v3_set_flyback_mode(component, mode);
55019c5d1f6SSrinivas Kandagatla 		wcd_clsh_v3_force_iq_ctl(component, mode, true);
55119c5d1f6SSrinivas Kandagatla 		wcd_clsh_v3_flyback_ctrl(component, ctrl, mode, true);
55219c5d1f6SSrinivas Kandagatla 		wcd_clsh_v3_set_flyback_current(component, mode);
55319c5d1f6SSrinivas Kandagatla 		wcd_clsh_v3_set_buck_mode(component, mode);
55419c5d1f6SSrinivas Kandagatla 		wcd_clsh_v3_buck_ctrl(component, ctrl, mode, true);
55519c5d1f6SSrinivas Kandagatla 		wcd_clsh_v3_set_hph_mode(component, mode);
55619c5d1f6SSrinivas Kandagatla 	} else {
55719c5d1f6SSrinivas Kandagatla 		wcd_clsh_v3_set_hph_mode(component, CLS_H_NORMAL);
55819c5d1f6SSrinivas Kandagatla 
55919c5d1f6SSrinivas Kandagatla 		/* buck and flyback set to default mode and disable */
56019c5d1f6SSrinivas Kandagatla 		wcd_clsh_v3_flyback_ctrl(component, ctrl, CLS_H_NORMAL, false);
56119c5d1f6SSrinivas Kandagatla 		wcd_clsh_v3_buck_ctrl(component, ctrl, CLS_H_NORMAL, false);
56219c5d1f6SSrinivas Kandagatla 		wcd_clsh_v3_force_iq_ctl(component, CLS_H_NORMAL, false);
56319c5d1f6SSrinivas Kandagatla 		wcd_clsh_v3_set_flyback_mode(component, CLS_H_NORMAL);
56419c5d1f6SSrinivas Kandagatla 		wcd_clsh_v3_set_buck_mode(component, CLS_H_NORMAL);
56519c5d1f6SSrinivas Kandagatla 	}
56619c5d1f6SSrinivas Kandagatla }
56719c5d1f6SSrinivas Kandagatla 
wcd_clsh_state_hph_r(struct wcd_clsh_ctrl * ctrl,int req_state,bool is_enable,int mode)568cc2e324dSSrinivas Kandagatla static void wcd_clsh_state_hph_r(struct wcd_clsh_ctrl *ctrl, int req_state,
569cc2e324dSSrinivas Kandagatla 				 bool is_enable, int mode)
570cc2e324dSSrinivas Kandagatla {
571cc2e324dSSrinivas Kandagatla 	struct snd_soc_component *comp = ctrl->comp;
572cc2e324dSSrinivas Kandagatla 
573cc2e324dSSrinivas Kandagatla 	if (mode == CLS_H_NORMAL) {
574cc2e324dSSrinivas Kandagatla 		dev_err(comp->dev, "%s: Normal mode not applicable for hph_r\n",
575cc2e324dSSrinivas Kandagatla 			__func__);
576cc2e324dSSrinivas Kandagatla 		return;
577cc2e324dSSrinivas Kandagatla 	}
578cc2e324dSSrinivas Kandagatla 
579cc2e324dSSrinivas Kandagatla 	if (is_enable) {
580cc2e324dSSrinivas Kandagatla 		if (mode != CLS_AB) {
581cc2e324dSSrinivas Kandagatla 			wcd_enable_clsh_block(ctrl, true);
582cc2e324dSSrinivas Kandagatla 			/*
583cc2e324dSSrinivas Kandagatla 			 * These K1 values depend on the Headphone Impedance
584cc2e324dSSrinivas Kandagatla 			 * For now it is assumed to be 16 ohm
585cc2e324dSSrinivas Kandagatla 			 */
586cc2e324dSSrinivas Kandagatla 			snd_soc_component_update_bits(comp,
587cc2e324dSSrinivas Kandagatla 					WCD9XXX_A_CDC_CLSH_K1_MSB,
588cc2e324dSSrinivas Kandagatla 					WCD9XXX_A_CDC_CLSH_K1_MSB_COEF_MASK,
589cc2e324dSSrinivas Kandagatla 					0x00);
590cc2e324dSSrinivas Kandagatla 			snd_soc_component_update_bits(comp,
591cc2e324dSSrinivas Kandagatla 					WCD9XXX_A_CDC_CLSH_K1_LSB,
592cc2e324dSSrinivas Kandagatla 					WCD9XXX_A_CDC_CLSH_K1_LSB_COEF_MASK,
593cc2e324dSSrinivas Kandagatla 					0xC0);
594cc2e324dSSrinivas Kandagatla 			snd_soc_component_update_bits(comp,
595cc2e324dSSrinivas Kandagatla 					    WCD9XXX_A_CDC_RX2_RX_PATH_CFG0,
596cc2e324dSSrinivas Kandagatla 					    WCD9XXX_A_CDC_RX_PATH_CLSH_EN_MASK,
597cc2e324dSSrinivas Kandagatla 					    WCD9XXX_A_CDC_RX_PATH_CLSH_ENABLE);
598cc2e324dSSrinivas Kandagatla 		}
599cc2e324dSSrinivas Kandagatla 		wcd_clsh_set_buck_regulator_mode(comp, mode);
600cc2e324dSSrinivas Kandagatla 		wcd_clsh_set_flyback_mode(comp, mode);
601cc2e324dSSrinivas Kandagatla 		wcd_clsh_flyback_ctrl(ctrl, mode, true);
602cc2e324dSSrinivas Kandagatla 		wcd_clsh_set_flyback_current(comp, mode);
603cc2e324dSSrinivas Kandagatla 		wcd_clsh_set_buck_mode(comp, mode);
604cc2e324dSSrinivas Kandagatla 		wcd_clsh_buck_ctrl(ctrl, mode, true);
60519c5d1f6SSrinivas Kandagatla 		wcd_clsh_v2_set_hph_mode(comp, mode);
606cc2e324dSSrinivas Kandagatla 		wcd_clsh_set_gain_path(ctrl, mode);
607cc2e324dSSrinivas Kandagatla 	} else {
60819c5d1f6SSrinivas Kandagatla 		wcd_clsh_v2_set_hph_mode(comp, CLS_H_NORMAL);
609cc2e324dSSrinivas Kandagatla 
610cc2e324dSSrinivas Kandagatla 		if (mode != CLS_AB) {
611cc2e324dSSrinivas Kandagatla 			snd_soc_component_update_bits(comp,
612cc2e324dSSrinivas Kandagatla 					    WCD9XXX_A_CDC_RX2_RX_PATH_CFG0,
613cc2e324dSSrinivas Kandagatla 					    WCD9XXX_A_CDC_RX_PATH_CLSH_EN_MASK,
614cc2e324dSSrinivas Kandagatla 					    WCD9XXX_A_CDC_RX_PATH_CLSH_DISABLE);
615cc2e324dSSrinivas Kandagatla 			wcd_enable_clsh_block(ctrl, false);
616cc2e324dSSrinivas Kandagatla 		}
617cc2e324dSSrinivas Kandagatla 		/* buck and flyback set to default mode and disable */
618cc2e324dSSrinivas Kandagatla 		wcd_clsh_buck_ctrl(ctrl, CLS_H_NORMAL, false);
619cc2e324dSSrinivas Kandagatla 		wcd_clsh_flyback_ctrl(ctrl, CLS_H_NORMAL, false);
620cc2e324dSSrinivas Kandagatla 		wcd_clsh_set_flyback_mode(comp, CLS_H_NORMAL);
621cc2e324dSSrinivas Kandagatla 		wcd_clsh_set_buck_mode(comp, CLS_H_NORMAL);
622cc2e324dSSrinivas Kandagatla 		wcd_clsh_set_buck_regulator_mode(comp, CLS_H_NORMAL);
623cc2e324dSSrinivas Kandagatla 	}
624cc2e324dSSrinivas Kandagatla }
625cc2e324dSSrinivas Kandagatla 
wcd_clsh_v3_state_hph_l(struct wcd_clsh_ctrl * ctrl,int req_state,bool is_enable,int mode)62619c5d1f6SSrinivas Kandagatla static void wcd_clsh_v3_state_hph_l(struct wcd_clsh_ctrl *ctrl, int req_state,
62719c5d1f6SSrinivas Kandagatla 				 bool is_enable, int mode)
62819c5d1f6SSrinivas Kandagatla {
62919c5d1f6SSrinivas Kandagatla 	struct snd_soc_component *component = ctrl->comp;
63019c5d1f6SSrinivas Kandagatla 
63119c5d1f6SSrinivas Kandagatla 	if (mode == CLS_H_NORMAL) {
63219c5d1f6SSrinivas Kandagatla 		dev_dbg(component->dev, "%s: Normal mode not applicable for hph_l\n",
63319c5d1f6SSrinivas Kandagatla 			__func__);
63419c5d1f6SSrinivas Kandagatla 		return;
63519c5d1f6SSrinivas Kandagatla 	}
63619c5d1f6SSrinivas Kandagatla 
63719c5d1f6SSrinivas Kandagatla 	if (is_enable) {
63819c5d1f6SSrinivas Kandagatla 		wcd_clsh_v3_set_buck_regulator_mode(component, mode);
63919c5d1f6SSrinivas Kandagatla 		wcd_clsh_v3_set_flyback_mode(component, mode);
64019c5d1f6SSrinivas Kandagatla 		wcd_clsh_v3_force_iq_ctl(component, mode, true);
64119c5d1f6SSrinivas Kandagatla 		wcd_clsh_v3_flyback_ctrl(component, ctrl, mode, true);
64219c5d1f6SSrinivas Kandagatla 		wcd_clsh_v3_set_flyback_current(component, mode);
64319c5d1f6SSrinivas Kandagatla 		wcd_clsh_v3_set_buck_mode(component, mode);
64419c5d1f6SSrinivas Kandagatla 		wcd_clsh_v3_buck_ctrl(component, ctrl, mode, true);
64519c5d1f6SSrinivas Kandagatla 		wcd_clsh_v3_set_hph_mode(component, mode);
64619c5d1f6SSrinivas Kandagatla 	} else {
64719c5d1f6SSrinivas Kandagatla 		wcd_clsh_v3_set_hph_mode(component, CLS_H_NORMAL);
64819c5d1f6SSrinivas Kandagatla 
64919c5d1f6SSrinivas Kandagatla 		/* set buck and flyback to Default Mode */
65019c5d1f6SSrinivas Kandagatla 		wcd_clsh_v3_flyback_ctrl(component, ctrl, CLS_H_NORMAL, false);
65119c5d1f6SSrinivas Kandagatla 		wcd_clsh_v3_buck_ctrl(component, ctrl, CLS_H_NORMAL, false);
65219c5d1f6SSrinivas Kandagatla 		wcd_clsh_v3_force_iq_ctl(component, CLS_H_NORMAL, false);
65319c5d1f6SSrinivas Kandagatla 		wcd_clsh_v3_set_flyback_mode(component, CLS_H_NORMAL);
65419c5d1f6SSrinivas Kandagatla 		wcd_clsh_v3_set_buck_mode(component, CLS_H_NORMAL);
65519c5d1f6SSrinivas Kandagatla 	}
65619c5d1f6SSrinivas Kandagatla }
65719c5d1f6SSrinivas Kandagatla 
wcd_clsh_state_hph_l(struct wcd_clsh_ctrl * ctrl,int req_state,bool is_enable,int mode)658cc2e324dSSrinivas Kandagatla static void wcd_clsh_state_hph_l(struct wcd_clsh_ctrl *ctrl, int req_state,
659cc2e324dSSrinivas Kandagatla 				 bool is_enable, int mode)
660cc2e324dSSrinivas Kandagatla {
661cc2e324dSSrinivas Kandagatla 	struct snd_soc_component *comp = ctrl->comp;
662cc2e324dSSrinivas Kandagatla 
663cc2e324dSSrinivas Kandagatla 	if (mode == CLS_H_NORMAL) {
664cc2e324dSSrinivas Kandagatla 		dev_err(comp->dev, "%s: Normal mode not applicable for hph_l\n",
665cc2e324dSSrinivas Kandagatla 			__func__);
666cc2e324dSSrinivas Kandagatla 		return;
667cc2e324dSSrinivas Kandagatla 	}
668cc2e324dSSrinivas Kandagatla 
669cc2e324dSSrinivas Kandagatla 	if (is_enable) {
670cc2e324dSSrinivas Kandagatla 		if (mode != CLS_AB) {
671cc2e324dSSrinivas Kandagatla 			wcd_enable_clsh_block(ctrl, true);
672cc2e324dSSrinivas Kandagatla 			/*
673cc2e324dSSrinivas Kandagatla 			 * These K1 values depend on the Headphone Impedance
674cc2e324dSSrinivas Kandagatla 			 * For now it is assumed to be 16 ohm
675cc2e324dSSrinivas Kandagatla 			 */
676cc2e324dSSrinivas Kandagatla 			snd_soc_component_update_bits(comp,
677cc2e324dSSrinivas Kandagatla 					WCD9XXX_A_CDC_CLSH_K1_MSB,
678cc2e324dSSrinivas Kandagatla 					WCD9XXX_A_CDC_CLSH_K1_MSB_COEF_MASK,
679cc2e324dSSrinivas Kandagatla 					0x00);
680cc2e324dSSrinivas Kandagatla 			snd_soc_component_update_bits(comp,
681cc2e324dSSrinivas Kandagatla 					WCD9XXX_A_CDC_CLSH_K1_LSB,
682cc2e324dSSrinivas Kandagatla 					WCD9XXX_A_CDC_CLSH_K1_LSB_COEF_MASK,
683cc2e324dSSrinivas Kandagatla 					0xC0);
684cc2e324dSSrinivas Kandagatla 			snd_soc_component_update_bits(comp,
685cc2e324dSSrinivas Kandagatla 					    WCD9XXX_A_CDC_RX1_RX_PATH_CFG0,
686cc2e324dSSrinivas Kandagatla 					    WCD9XXX_A_CDC_RX_PATH_CLSH_EN_MASK,
687cc2e324dSSrinivas Kandagatla 					    WCD9XXX_A_CDC_RX_PATH_CLSH_ENABLE);
688cc2e324dSSrinivas Kandagatla 		}
689cc2e324dSSrinivas Kandagatla 		wcd_clsh_set_buck_regulator_mode(comp, mode);
690cc2e324dSSrinivas Kandagatla 		wcd_clsh_set_flyback_mode(comp, mode);
691cc2e324dSSrinivas Kandagatla 		wcd_clsh_flyback_ctrl(ctrl, mode, true);
692cc2e324dSSrinivas Kandagatla 		wcd_clsh_set_flyback_current(comp, mode);
693cc2e324dSSrinivas Kandagatla 		wcd_clsh_set_buck_mode(comp, mode);
694cc2e324dSSrinivas Kandagatla 		wcd_clsh_buck_ctrl(ctrl, mode, true);
69519c5d1f6SSrinivas Kandagatla 		wcd_clsh_v2_set_hph_mode(comp, mode);
696cc2e324dSSrinivas Kandagatla 		wcd_clsh_set_gain_path(ctrl, mode);
697cc2e324dSSrinivas Kandagatla 	} else {
69819c5d1f6SSrinivas Kandagatla 		wcd_clsh_v2_set_hph_mode(comp, CLS_H_NORMAL);
699cc2e324dSSrinivas Kandagatla 
700cc2e324dSSrinivas Kandagatla 		if (mode != CLS_AB) {
701cc2e324dSSrinivas Kandagatla 			snd_soc_component_update_bits(comp,
702cc2e324dSSrinivas Kandagatla 					    WCD9XXX_A_CDC_RX1_RX_PATH_CFG0,
703cc2e324dSSrinivas Kandagatla 					    WCD9XXX_A_CDC_RX_PATH_CLSH_EN_MASK,
704cc2e324dSSrinivas Kandagatla 					    WCD9XXX_A_CDC_RX_PATH_CLSH_DISABLE);
705cc2e324dSSrinivas Kandagatla 			wcd_enable_clsh_block(ctrl, false);
706cc2e324dSSrinivas Kandagatla 		}
707cc2e324dSSrinivas Kandagatla 		/* set buck and flyback to Default Mode */
708cc2e324dSSrinivas Kandagatla 		wcd_clsh_buck_ctrl(ctrl, CLS_H_NORMAL, false);
709cc2e324dSSrinivas Kandagatla 		wcd_clsh_flyback_ctrl(ctrl, CLS_H_NORMAL, false);
710cc2e324dSSrinivas Kandagatla 		wcd_clsh_set_flyback_mode(comp, CLS_H_NORMAL);
711cc2e324dSSrinivas Kandagatla 		wcd_clsh_set_buck_mode(comp, CLS_H_NORMAL);
712cc2e324dSSrinivas Kandagatla 		wcd_clsh_set_buck_regulator_mode(comp, CLS_H_NORMAL);
713cc2e324dSSrinivas Kandagatla 	}
714cc2e324dSSrinivas Kandagatla }
715cc2e324dSSrinivas Kandagatla 
wcd_clsh_v3_state_ear(struct wcd_clsh_ctrl * ctrl,int req_state,bool is_enable,int mode)71619c5d1f6SSrinivas Kandagatla static void wcd_clsh_v3_state_ear(struct wcd_clsh_ctrl *ctrl, int req_state,
71719c5d1f6SSrinivas Kandagatla 			       bool is_enable, int mode)
71819c5d1f6SSrinivas Kandagatla {
71919c5d1f6SSrinivas Kandagatla 	struct snd_soc_component *component = ctrl->comp;
72019c5d1f6SSrinivas Kandagatla 
72119c5d1f6SSrinivas Kandagatla 	if (is_enable) {
72219c5d1f6SSrinivas Kandagatla 		wcd_clsh_v3_set_buck_regulator_mode(component, mode);
72319c5d1f6SSrinivas Kandagatla 		wcd_clsh_v3_set_flyback_mode(component, mode);
72419c5d1f6SSrinivas Kandagatla 		wcd_clsh_v3_force_iq_ctl(component, mode, true);
72519c5d1f6SSrinivas Kandagatla 		wcd_clsh_v3_flyback_ctrl(component, ctrl, mode, true);
72619c5d1f6SSrinivas Kandagatla 		wcd_clsh_v3_set_flyback_current(component, mode);
72719c5d1f6SSrinivas Kandagatla 		wcd_clsh_v3_set_buck_mode(component, mode);
72819c5d1f6SSrinivas Kandagatla 		wcd_clsh_v3_buck_ctrl(component, ctrl, mode, true);
72919c5d1f6SSrinivas Kandagatla 		wcd_clsh_v3_set_hph_mode(component, mode);
73019c5d1f6SSrinivas Kandagatla 	} else {
73119c5d1f6SSrinivas Kandagatla 		wcd_clsh_v3_set_hph_mode(component, CLS_H_NORMAL);
73219c5d1f6SSrinivas Kandagatla 
73319c5d1f6SSrinivas Kandagatla 		/* set buck and flyback to Default Mode */
73419c5d1f6SSrinivas Kandagatla 		wcd_clsh_v3_flyback_ctrl(component, ctrl, CLS_H_NORMAL, false);
73519c5d1f6SSrinivas Kandagatla 		wcd_clsh_v3_buck_ctrl(component, ctrl, CLS_H_NORMAL, false);
73619c5d1f6SSrinivas Kandagatla 		wcd_clsh_v3_force_iq_ctl(component, CLS_H_NORMAL, false);
73719c5d1f6SSrinivas Kandagatla 		wcd_clsh_v3_set_flyback_mode(component, CLS_H_NORMAL);
73819c5d1f6SSrinivas Kandagatla 		wcd_clsh_v3_set_buck_mode(component, CLS_H_NORMAL);
73919c5d1f6SSrinivas Kandagatla 	}
74019c5d1f6SSrinivas Kandagatla }
74119c5d1f6SSrinivas Kandagatla 
wcd_clsh_state_ear(struct wcd_clsh_ctrl * ctrl,int req_state,bool is_enable,int mode)742cc2e324dSSrinivas Kandagatla static void wcd_clsh_state_ear(struct wcd_clsh_ctrl *ctrl, int req_state,
743cc2e324dSSrinivas Kandagatla 			       bool is_enable, int mode)
744cc2e324dSSrinivas Kandagatla {
745cc2e324dSSrinivas Kandagatla 	struct snd_soc_component *comp = ctrl->comp;
746cc2e324dSSrinivas Kandagatla 
747cc2e324dSSrinivas Kandagatla 	if (mode != CLS_H_NORMAL) {
748cc2e324dSSrinivas Kandagatla 		dev_err(comp->dev, "%s: mode: %d cannot be used for EAR\n",
749cc2e324dSSrinivas Kandagatla 			__func__, mode);
750cc2e324dSSrinivas Kandagatla 		return;
751cc2e324dSSrinivas Kandagatla 	}
752cc2e324dSSrinivas Kandagatla 
753cc2e324dSSrinivas Kandagatla 	if (is_enable) {
754cc2e324dSSrinivas Kandagatla 		wcd_enable_clsh_block(ctrl, true);
755cc2e324dSSrinivas Kandagatla 		snd_soc_component_update_bits(comp,
756cc2e324dSSrinivas Kandagatla 					WCD9XXX_A_CDC_RX0_RX_PATH_CFG0,
757cc2e324dSSrinivas Kandagatla 					WCD9XXX_A_CDC_RX_PATH_CLSH_EN_MASK,
758cc2e324dSSrinivas Kandagatla 					WCD9XXX_A_CDC_RX_PATH_CLSH_ENABLE);
759cc2e324dSSrinivas Kandagatla 		wcd_clsh_set_buck_mode(comp, mode);
760cc2e324dSSrinivas Kandagatla 		wcd_clsh_set_flyback_mode(comp, mode);
761cc2e324dSSrinivas Kandagatla 		wcd_clsh_flyback_ctrl(ctrl, mode, true);
762cc2e324dSSrinivas Kandagatla 		wcd_clsh_set_flyback_current(comp, mode);
763cc2e324dSSrinivas Kandagatla 		wcd_clsh_buck_ctrl(ctrl, mode, true);
764cc2e324dSSrinivas Kandagatla 	} else {
765cc2e324dSSrinivas Kandagatla 		snd_soc_component_update_bits(comp,
766cc2e324dSSrinivas Kandagatla 					WCD9XXX_A_CDC_RX0_RX_PATH_CFG0,
767cc2e324dSSrinivas Kandagatla 					WCD9XXX_A_CDC_RX_PATH_CLSH_EN_MASK,
768cc2e324dSSrinivas Kandagatla 					WCD9XXX_A_CDC_RX_PATH_CLSH_DISABLE);
769cc2e324dSSrinivas Kandagatla 		wcd_enable_clsh_block(ctrl, false);
770cc2e324dSSrinivas Kandagatla 		wcd_clsh_buck_ctrl(ctrl, mode, false);
771cc2e324dSSrinivas Kandagatla 		wcd_clsh_flyback_ctrl(ctrl, mode, false);
772cc2e324dSSrinivas Kandagatla 		wcd_clsh_set_flyback_mode(comp, CLS_H_NORMAL);
773cc2e324dSSrinivas Kandagatla 		wcd_clsh_set_buck_mode(comp, CLS_H_NORMAL);
774cc2e324dSSrinivas Kandagatla 	}
775cc2e324dSSrinivas Kandagatla }
776cc2e324dSSrinivas Kandagatla 
_wcd_clsh_ctrl_set_state(struct wcd_clsh_ctrl * ctrl,int req_state,bool is_enable,int mode)777cc2e324dSSrinivas Kandagatla static int _wcd_clsh_ctrl_set_state(struct wcd_clsh_ctrl *ctrl, int req_state,
778cc2e324dSSrinivas Kandagatla 				    bool is_enable, int mode)
779cc2e324dSSrinivas Kandagatla {
780cc2e324dSSrinivas Kandagatla 	switch (req_state) {
781cc2e324dSSrinivas Kandagatla 	case WCD_CLSH_STATE_EAR:
78219c5d1f6SSrinivas Kandagatla 		if (ctrl->codec_version >= WCD937X)
78319c5d1f6SSrinivas Kandagatla 			wcd_clsh_v3_state_ear(ctrl, req_state, is_enable, mode);
78419c5d1f6SSrinivas Kandagatla 		else
785cc2e324dSSrinivas Kandagatla 			wcd_clsh_state_ear(ctrl, req_state, is_enable, mode);
786cc2e324dSSrinivas Kandagatla 		break;
787cc2e324dSSrinivas Kandagatla 	case WCD_CLSH_STATE_HPHL:
78819c5d1f6SSrinivas Kandagatla 		if (ctrl->codec_version >= WCD937X)
78919c5d1f6SSrinivas Kandagatla 			wcd_clsh_v3_state_hph_l(ctrl, req_state, is_enable, mode);
79019c5d1f6SSrinivas Kandagatla 		else
791cc2e324dSSrinivas Kandagatla 			wcd_clsh_state_hph_l(ctrl, req_state, is_enable, mode);
792cc2e324dSSrinivas Kandagatla 		break;
793cc2e324dSSrinivas Kandagatla 	case WCD_CLSH_STATE_HPHR:
79419c5d1f6SSrinivas Kandagatla 		if (ctrl->codec_version >= WCD937X)
79519c5d1f6SSrinivas Kandagatla 			wcd_clsh_v3_state_hph_r(ctrl, req_state, is_enable, mode);
79619c5d1f6SSrinivas Kandagatla 		else
797cc2e324dSSrinivas Kandagatla 			wcd_clsh_state_hph_r(ctrl, req_state, is_enable, mode);
798cc2e324dSSrinivas Kandagatla 		break;
799cc2e324dSSrinivas Kandagatla 	case WCD_CLSH_STATE_LO:
80019c5d1f6SSrinivas Kandagatla 		if (ctrl->codec_version < WCD937X)
801cc2e324dSSrinivas Kandagatla 			wcd_clsh_state_lo(ctrl, req_state, is_enable, mode);
802cc2e324dSSrinivas Kandagatla 		break;
80319c5d1f6SSrinivas Kandagatla 	case WCD_CLSH_STATE_AUX:
80419c5d1f6SSrinivas Kandagatla 		if (ctrl->codec_version >= WCD937X)
80519c5d1f6SSrinivas Kandagatla 			wcd_clsh_v3_state_aux(ctrl, req_state, is_enable, mode);
80619c5d1f6SSrinivas Kandagatla 		break;
807cc2e324dSSrinivas Kandagatla 	default:
808cc2e324dSSrinivas Kandagatla 		break;
809cc2e324dSSrinivas Kandagatla 	}
810cc2e324dSSrinivas Kandagatla 
811cc2e324dSSrinivas Kandagatla 	return 0;
812cc2e324dSSrinivas Kandagatla }
813cc2e324dSSrinivas Kandagatla 
814cc2e324dSSrinivas Kandagatla /*
815cc2e324dSSrinivas Kandagatla  * Function: wcd_clsh_is_state_valid
816cc2e324dSSrinivas Kandagatla  * Params: state
817cc2e324dSSrinivas Kandagatla  * Description:
818cc2e324dSSrinivas Kandagatla  * Provides information on valid states of Class H configuration
819cc2e324dSSrinivas Kandagatla  */
wcd_clsh_is_state_valid(int state)820cc2e324dSSrinivas Kandagatla static bool wcd_clsh_is_state_valid(int state)
821cc2e324dSSrinivas Kandagatla {
822cc2e324dSSrinivas Kandagatla 	switch (state) {
823cc2e324dSSrinivas Kandagatla 	case WCD_CLSH_STATE_IDLE:
824cc2e324dSSrinivas Kandagatla 	case WCD_CLSH_STATE_EAR:
825cc2e324dSSrinivas Kandagatla 	case WCD_CLSH_STATE_HPHL:
826cc2e324dSSrinivas Kandagatla 	case WCD_CLSH_STATE_HPHR:
827cc2e324dSSrinivas Kandagatla 	case WCD_CLSH_STATE_LO:
82819c5d1f6SSrinivas Kandagatla 	case WCD_CLSH_STATE_AUX:
829cc2e324dSSrinivas Kandagatla 		return true;
830cc2e324dSSrinivas Kandagatla 	default:
831cc2e324dSSrinivas Kandagatla 		return false;
832cc2e324dSSrinivas Kandagatla 	};
833cc2e324dSSrinivas Kandagatla }
834cc2e324dSSrinivas Kandagatla 
835cc2e324dSSrinivas Kandagatla /*
836cc2e324dSSrinivas Kandagatla  * Function: wcd_clsh_fsm
837cc2e324dSSrinivas Kandagatla  * Params: ctrl, req_state, req_type, clsh_event
838cc2e324dSSrinivas Kandagatla  * Description:
839cc2e324dSSrinivas Kandagatla  * This function handles PRE DAC and POST DAC conditions of different devices
840cc2e324dSSrinivas Kandagatla  * and updates class H configuration of different combination of devices
841cc2e324dSSrinivas Kandagatla  * based on validity of their states. ctrl will contain current
842cc2e324dSSrinivas Kandagatla  * class h state information
843cc2e324dSSrinivas Kandagatla  */
wcd_clsh_ctrl_set_state(struct wcd_clsh_ctrl * ctrl,enum wcd_clsh_event clsh_event,int nstate,enum wcd_clsh_mode mode)844cc2e324dSSrinivas Kandagatla int wcd_clsh_ctrl_set_state(struct wcd_clsh_ctrl *ctrl,
845cc2e324dSSrinivas Kandagatla 			    enum wcd_clsh_event clsh_event,
846cc2e324dSSrinivas Kandagatla 			    int nstate,
847cc2e324dSSrinivas Kandagatla 			    enum wcd_clsh_mode mode)
848cc2e324dSSrinivas Kandagatla {
849cc2e324dSSrinivas Kandagatla 	struct snd_soc_component *comp = ctrl->comp;
850cc2e324dSSrinivas Kandagatla 
851cc2e324dSSrinivas Kandagatla 	if (nstate == ctrl->state)
852cc2e324dSSrinivas Kandagatla 		return 0;
853cc2e324dSSrinivas Kandagatla 
854cc2e324dSSrinivas Kandagatla 	if (!wcd_clsh_is_state_valid(nstate)) {
855cc2e324dSSrinivas Kandagatla 		dev_err(comp->dev, "Class-H not a valid new state:\n");
856cc2e324dSSrinivas Kandagatla 		return -EINVAL;
857cc2e324dSSrinivas Kandagatla 	}
858cc2e324dSSrinivas Kandagatla 
859cc2e324dSSrinivas Kandagatla 	switch (clsh_event) {
860cc2e324dSSrinivas Kandagatla 	case WCD_CLSH_EVENT_PRE_DAC:
861cc2e324dSSrinivas Kandagatla 		_wcd_clsh_ctrl_set_state(ctrl, nstate, CLSH_REQ_ENABLE, mode);
862cc2e324dSSrinivas Kandagatla 		break;
863cc2e324dSSrinivas Kandagatla 	case WCD_CLSH_EVENT_POST_PA:
864cc2e324dSSrinivas Kandagatla 		_wcd_clsh_ctrl_set_state(ctrl, nstate, CLSH_REQ_DISABLE, mode);
865cc2e324dSSrinivas Kandagatla 		break;
866afb86626Skbuild test robot 	}
867cc2e324dSSrinivas Kandagatla 
868cc2e324dSSrinivas Kandagatla 	ctrl->state = nstate;
869cc2e324dSSrinivas Kandagatla 	ctrl->mode = mode;
870cc2e324dSSrinivas Kandagatla 
871cc2e324dSSrinivas Kandagatla 	return 0;
872cc2e324dSSrinivas Kandagatla }
873*11b0b802SKrzysztof Kozlowski EXPORT_SYMBOL_GPL(wcd_clsh_ctrl_set_state);
874cc2e324dSSrinivas Kandagatla 
wcd_clsh_ctrl_get_state(struct wcd_clsh_ctrl * ctrl)875cc2e324dSSrinivas Kandagatla int wcd_clsh_ctrl_get_state(struct wcd_clsh_ctrl *ctrl)
876cc2e324dSSrinivas Kandagatla {
877cc2e324dSSrinivas Kandagatla 	return ctrl->state;
878cc2e324dSSrinivas Kandagatla }
879*11b0b802SKrzysztof Kozlowski EXPORT_SYMBOL_GPL(wcd_clsh_ctrl_get_state);
880cc2e324dSSrinivas Kandagatla 
wcd_clsh_ctrl_alloc(struct snd_soc_component * comp,int version)881cc2e324dSSrinivas Kandagatla struct wcd_clsh_ctrl *wcd_clsh_ctrl_alloc(struct snd_soc_component *comp,
882cc2e324dSSrinivas Kandagatla 					  int version)
883cc2e324dSSrinivas Kandagatla {
884cc2e324dSSrinivas Kandagatla 	struct wcd_clsh_ctrl *ctrl;
885cc2e324dSSrinivas Kandagatla 
886cc2e324dSSrinivas Kandagatla 	ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL);
887cc2e324dSSrinivas Kandagatla 	if (!ctrl)
888cc2e324dSSrinivas Kandagatla 		return ERR_PTR(-ENOMEM);
889cc2e324dSSrinivas Kandagatla 
890cc2e324dSSrinivas Kandagatla 	ctrl->state = WCD_CLSH_STATE_IDLE;
891cc2e324dSSrinivas Kandagatla 	ctrl->comp = comp;
89219c5d1f6SSrinivas Kandagatla 	ctrl->codec_version = version;
893cc2e324dSSrinivas Kandagatla 
894cc2e324dSSrinivas Kandagatla 	return ctrl;
895cc2e324dSSrinivas Kandagatla }
896*11b0b802SKrzysztof Kozlowski EXPORT_SYMBOL_GPL(wcd_clsh_ctrl_alloc);
897cc2e324dSSrinivas Kandagatla 
wcd_clsh_ctrl_free(struct wcd_clsh_ctrl * ctrl)898cc2e324dSSrinivas Kandagatla void wcd_clsh_ctrl_free(struct wcd_clsh_ctrl *ctrl)
899cc2e324dSSrinivas Kandagatla {
900cc2e324dSSrinivas Kandagatla 	kfree(ctrl);
901cc2e324dSSrinivas Kandagatla }
902*11b0b802SKrzysztof Kozlowski EXPORT_SYMBOL_GPL(wcd_clsh_ctrl_free);
903*11b0b802SKrzysztof Kozlowski 
904*11b0b802SKrzysztof Kozlowski MODULE_DESCRIPTION("WCD93XX Class-H driver");
905*11b0b802SKrzysztof Kozlowski MODULE_LICENSE("GPL");
906