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