blob: b104a6ba37fa89dc9f8ecc3515522213c1132902 [file] [log] [blame]
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08001/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12
13#include <linux/module.h>
Phani Kumar Uppalapati01a77e12013-08-08 15:31:35 -070014#include <linux/slab.h>
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -080015#include <sound/soc.h>
16#include <linux/kernel.h>
17#include <linux/delay.h>
18#include <linux/mfd/wcd9xxx/wcd9xxx_registers.h>
19#include "wcd9xxx-common.h"
20
21#define CLSH_COMPUTE_EAR 0x01
22#define CLSH_COMPUTE_HPH_L 0x02
23#define CLSH_COMPUTE_HPH_R 0x03
24
Joonwoo Parkd535b8a2013-08-01 18:44:56 -070025#define BUCK_VREF_0P494V 0x3F
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -080026#define BUCK_VREF_2V 0xFF
Joonwoo Park58d4a162013-07-23 16:19:37 -070027#define BUCK_VREF_0P494V 0x3F
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -080028#define BUCK_VREF_1P8V 0xE6
29
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -080030#define BUCK_SETTLE_TIME_US 50
31#define NCP_SETTLE_TIME_US 50
32
Santosh Mardi93a69192013-07-03 23:37:29 +053033#define MAX_IMPED_PARAMS 13
34
Phani Kumar Uppalapati01a77e12013-08-08 15:31:35 -070035#define USLEEP_RANGE_MARGIN_US 100
36
Santosh Mardi93a69192013-07-03 23:37:29 +053037struct wcd9xxx_imped_val {
38 u32 imped_val;
39 u8 index;
40};
41
42static const struct wcd9xxx_reg_mask_val imped_table[][MAX_IMPED_PARAMS] = {
43 {
44 {WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_L, 0xff, 0x46},
45 {WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_U, 0xff, 0x04},
46 {WCD9XXX_A_CDC_CLSH_K_ADDR, 0xff, 0x00},
47 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x11},
48 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x02},
49 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x9B},
50 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x02},
51 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x15},
52 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
53 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x1C},
54 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
55 {WCD9XXX_A_CDC_CLSH_IDLE_HPH_THSD, 0xff, 0x04},
56 {WCD9XXX_A_CDC_CLSH_FCLKONLY_HPH_THSD, 0xff, 0x0C},
57 },
58 {
59 {WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_L, 0xff, 0x47},
60 {WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_U, 0xff, 0x05},
61 {WCD9XXX_A_CDC_CLSH_K_ADDR, 0xff, 0x00},
62 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x11},
63 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x02},
64 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x9B},
65 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x02},
66 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x15},
67 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
68 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x1C},
69 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
70 {WCD9XXX_A_CDC_CLSH_IDLE_HPH_THSD, 0xff, 0x05},
71 {WCD9XXX_A_CDC_CLSH_FCLKONLY_HPH_THSD, 0xff, 0x0C},
72 },
73 {
74 {WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_L, 0xff, 0x49},
75 {WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_U, 0xff, 0x07},
76 {WCD9XXX_A_CDC_CLSH_K_ADDR, 0xff, 0x00},
77 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
78 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x02},
79 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x12},
80 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
81 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x35},
82 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
83 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x4E},
84 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
85 {WCD9XXX_A_CDC_CLSH_IDLE_HPH_THSD, 0xff, 0x06},
86 {WCD9XXX_A_CDC_CLSH_FCLKONLY_HPH_THSD, 0xff, 0x0E},
87 },
88 {
89 {WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_L, 0xff, 0x49},
90 {WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_U, 0xff, 0x16},
91 {WCD9XXX_A_CDC_CLSH_K_ADDR, 0xff, 0x00},
92 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0xAC},
93 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x02},
94 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x17},
95 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
96 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x5F},
97 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
98 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0xCF},
99 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
100 {WCD9XXX_A_CDC_CLSH_IDLE_HPH_THSD, 0xff, 0x06},
101 {WCD9XXX_A_CDC_CLSH_FCLKONLY_HPH_THSD, 0xff, 0x0F},
102 },
103 {
104 {WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_L, 0xff, 0x59},
105 {WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_U, 0xff, 0x15},
106 {WCD9XXX_A_CDC_CLSH_K_ADDR, 0xff, 0x00},
107 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x9C},
108 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x02},
109 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x1B},
110 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
111 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0xCE},
112 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
113 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0xBD},
114 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
115 {WCD9XXX_A_CDC_CLSH_IDLE_HPH_THSD, 0xff, 0x07},
116 {WCD9XXX_A_CDC_CLSH_FCLKONLY_HPH_THSD, 0xff, 0x10},
117 },
118 {
119 {WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_L, 0xff, 0x66},
120 {WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_U, 0xff, 0x04},
121 {WCD9XXX_A_CDC_CLSH_K_ADDR, 0xff, 0x00},
122 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x9A},
123 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x02},
124 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x2E},
125 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
126 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0xBD},
127 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
128 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0xA6},
129 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
130 {WCD9XXX_A_CDC_CLSH_IDLE_HPH_THSD, 0xff, 0x07},
131 {WCD9XXX_A_CDC_CLSH_FCLKONLY_HPH_THSD, 0xff, 0x11},
132 },
133 {
134 {WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_L, 0xff, 0x79},
135 {WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_U, 0xff, 0x04},
136 {WCD9XXX_A_CDC_CLSH_K_ADDR, 0xff, 0x00},
137 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x11},
138 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
139 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x37},
140 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
141 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0xA6},
142 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
143 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0xAD},
144 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
145 {WCD9XXX_A_CDC_CLSH_IDLE_HPH_THSD, 0xff, 0x08},
146 {WCD9XXX_A_CDC_CLSH_FCLKONLY_HPH_THSD, 0xff, 0x12},
147 },
148 {
149 {WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_L, 0xff, 0x76},
150 {WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_U, 0xff, 0x04},
151 {WCD9XXX_A_CDC_CLSH_K_ADDR, 0xff, 0x00},
152 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x11},
153 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
154 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x4E},
155 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
156 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0xAD},
157 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
158 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0xAC},
159 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
160 {WCD9XXX_A_CDC_CLSH_IDLE_HPH_THSD, 0xff, 0x09},
161 {WCD9XXX_A_CDC_CLSH_FCLKONLY_HPH_THSD, 0xff, 0x12},
162 },
163 {
164 {WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_L, 0xff, 0x78},
165 {WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_U, 0xff, 0x05},
166 {WCD9XXX_A_CDC_CLSH_K_ADDR, 0xff, 0x00},
167 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x12},
168 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
169 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0xD0},
170 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
171 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0xAC},
172 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
173 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x13},
174 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
175 {WCD9XXX_A_CDC_CLSH_IDLE_HPH_THSD, 0xff, 0x0A},
176 {WCD9XXX_A_CDC_CLSH_FCLKONLY_HPH_THSD, 0xff, 0x13},
177 },
178 {
179 {WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_L, 0xff, 0x7A},
180 {WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_U, 0xff, 0x06},
181 {WCD9XXX_A_CDC_CLSH_K_ADDR, 0xff, 0x00},
182 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x14},
183 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
184 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0xB7},
185 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
186 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x13},
187 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
188 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x14},
189 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
190 {WCD9XXX_A_CDC_CLSH_IDLE_HPH_THSD, 0xff, 0x0B},
191 {WCD9XXX_A_CDC_CLSH_FCLKONLY_HPH_THSD, 0xff, 0x14},
192 },
193 {
194 {WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_L, 0xff, 0x60},
195 {WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_U, 0xff, 0x09},
196 {WCD9XXX_A_CDC_CLSH_K_ADDR, 0xff, 0x00},
197 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x1C},
198 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
199 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0xA4},
200 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
201 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x14},
202 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
203 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x1F},
204 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
205 {WCD9XXX_A_CDC_CLSH_IDLE_HPH_THSD, 0xff, 0x0C},
206 {WCD9XXX_A_CDC_CLSH_FCLKONLY_HPH_THSD, 0xff, 0x14},
207 },
208 {
209 {WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_L, 0xff, 0x79},
210 {WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_U, 0xff, 0x17},
211 {WCD9XXX_A_CDC_CLSH_K_ADDR, 0xff, 0x00},
212 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x25},
213 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
214 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0xAE},
215 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
216 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x1F},
217 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
218 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x1D},
219 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
220 {WCD9XXX_A_CDC_CLSH_IDLE_HPH_THSD, 0xff, 0x0D},
221 {WCD9XXX_A_CDC_CLSH_FCLKONLY_HPH_THSD, 0xff, 0x15},
222 },
223 {
224 {WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_L, 0xff, 0x78},
225 {WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_U, 0xff, 0x16},
226 {WCD9XXX_A_CDC_CLSH_K_ADDR, 0xff, 0x00},
227 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x2C},
228 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
229 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0xAC},
230 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
231 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x1D},
232 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
233 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x1C},
234 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
235 {WCD9XXX_A_CDC_CLSH_IDLE_HPH_THSD, 0xff, 0x0E},
236 {WCD9XXX_A_CDC_CLSH_FCLKONLY_HPH_THSD, 0xff, 0x16},
237 },
238 {
239 {WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_L, 0xff, 0x89},
240 {WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_U, 0xff, 0x05},
241 {WCD9XXX_A_CDC_CLSH_K_ADDR, 0xff, 0x00},
242 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x40},
243 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
244 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x13},
245 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
246 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x1C},
247 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
248 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x1B},
249 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
250 {WCD9XXX_A_CDC_CLSH_IDLE_HPH_THSD, 0xff, 0x10},
251 {WCD9XXX_A_CDC_CLSH_FCLKONLY_HPH_THSD, 0xff, 0x16},
252 },
253 {
254 {WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_L, 0xff, 0x97},
255 {WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_U, 0xff, 0x05},
256 {WCD9XXX_A_CDC_CLSH_K_ADDR, 0xff, 0x00},
257 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0xD0},
258 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
259 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x14},
260 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
261 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x1B},
262 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
263 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x1B},
264 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
265 {WCD9XXX_A_CDC_CLSH_IDLE_HPH_THSD, 0xff, 0x12},
266 {WCD9XXX_A_CDC_CLSH_FCLKONLY_HPH_THSD, 0xff, 0x17},
267 },
268 {
269 {WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_L, 0xff, 0x8A},
270 {WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_U, 0xff, 0x06},
271 {WCD9XXX_A_CDC_CLSH_K_ADDR, 0xff, 0x00},
272 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0xB7},
273 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
274 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x10},
275 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
276 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x1B},
277 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
278 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x24},
279 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
280 {WCD9XXX_A_CDC_CLSH_IDLE_HPH_THSD, 0xff, 0x13},
281 {WCD9XXX_A_CDC_CLSH_FCLKONLY_HPH_THSD, 0xff, 0x17},
282 },
283 {
284 {WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_L, 0xff, 0x8A},
285 {WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_U, 0xff, 0x07},
286 {WCD9XXX_A_CDC_CLSH_K_ADDR, 0xff, 0x00},
287 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0xA4},
288 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
289 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x1D},
290 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
291 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x24},
292 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
293 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x25},
294 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
295 {WCD9XXX_A_CDC_CLSH_IDLE_HPH_THSD, 0xff, 0x15},
296 {WCD9XXX_A_CDC_CLSH_FCLKONLY_HPH_THSD, 0xff, 0x18},
297 },
298 {
299 {WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_L, 0xff, 0x9A},
300 {WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_U, 0xff, 0x08},
301 {WCD9XXX_A_CDC_CLSH_K_ADDR, 0xff, 0x00},
302 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0xAE},
303 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
304 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x1C},
305 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
306 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x25},
307 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
308 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x27},
309 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
310 {WCD9XXX_A_CDC_CLSH_IDLE_HPH_THSD, 0xff, 0x18},
311 {WCD9XXX_A_CDC_CLSH_FCLKONLY_HPH_THSD, 0xff, 0x19},
312 },
313 {
314 {WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_L, 0xff, 0x8B},
315 {WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_U, 0xff, 0x18},
316 {WCD9XXX_A_CDC_CLSH_K_ADDR, 0xff, 0x00},
317 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0xAC},
318 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
319 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x1B},
320 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
321 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x20},
322 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
323 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x2E},
324 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
325 {WCD9XXX_A_CDC_CLSH_IDLE_HPH_THSD, 0xff, 0x1A},
326 {WCD9XXX_A_CDC_CLSH_FCLKONLY_HPH_THSD, 0xff, 0x19},
327 },
328 {
329 {WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_L, 0xff, 0x9A},
330 {WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_U, 0xff, 0x17},
331 {WCD9XXX_A_CDC_CLSH_K_ADDR, 0xff, 0x00},
332 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x13},
333 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
334 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x1B},
335 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
336 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x2E},
337 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
338 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x2D},
339 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
340 {WCD9XXX_A_CDC_CLSH_IDLE_HPH_THSD, 0xff, 0x1D},
341 {WCD9XXX_A_CDC_CLSH_FCLKONLY_HPH_THSD, 0xff, 0x1A},
342 },
343 {
344 {WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_L, 0xff, 0xA9},
345 {WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_U, 0xff, 0x06},
346 {WCD9XXX_A_CDC_CLSH_K_ADDR, 0xff, 0x00},
347 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x14},
348 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
349 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x24},
350 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
351 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x2D},
352 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
353 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x2C},
354 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
355 {WCD9XXX_A_CDC_CLSH_IDLE_HPH_THSD, 0xff, 0x1F},
356 {WCD9XXX_A_CDC_CLSH_FCLKONLY_HPH_THSD, 0xff, 0x19},
357 },
358 {
359 {WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_L, 0xff, 0xB9},
360 {WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_U, 0xff, 0x06},
361 {WCD9XXX_A_CDC_CLSH_K_ADDR, 0xff, 0x00},
362 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x10},
363 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
364 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x25},
365 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
366 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x2C},
367 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
368 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x2C},
369 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
370 {WCD9XXX_A_CDC_CLSH_IDLE_HPH_THSD, 0xff, 0x23},
371 {WCD9XXX_A_CDC_CLSH_FCLKONLY_HPH_THSD, 0xff, 0x18},
372 },
373 {
374 {WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_L, 0xff, 0xA9},
375 {WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_U, 0xff, 0x07},
376 {WCD9XXX_A_CDC_CLSH_K_ADDR, 0xff, 0x00},
377 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x1D},
378 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
379 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x27},
380 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
381 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x2C},
382 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
383 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x35},
384 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
385 {WCD9XXX_A_CDC_CLSH_IDLE_HPH_THSD, 0xff, 0x26},
386 {WCD9XXX_A_CDC_CLSH_FCLKONLY_HPH_THSD, 0xff, 0x16},
387 },
388};
389
390static const struct wcd9xxx_imped_val imped_index[] = {
391 {4000, 0},
392 {4500, 1},
393 {5000, 2},
394 {5500, 3},
395 {6000, 4},
396 {6500, 5},
397 {7000, 6},
398 {7700, 7},
399 {8470, 8},
400 {9317, 9},
401 {10248, 10},
402 {11273, 11},
403 {12400, 12},
404 {13641, 13},
405 {15005, 14},
406 {16505, 15},
407 {18156, 16},
408 {19971, 17},
409 {21969, 18},
410 {24165, 19},
411 {26582, 20},
412 {29240, 21},
413 {32164, 22},
414};
415
Joonwoo Park6aa12162013-06-11 17:08:57 -0700416static inline void
417wcd9xxx_enable_clsh_block(struct snd_soc_codec *codec,
Joonwoo Park58d4a162013-07-23 16:19:37 -0700418 struct wcd9xxx_clsh_cdc_data *clsh_d, bool enable)
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -0800419{
Joonwoo Park58d4a162013-07-23 16:19:37 -0700420 if ((enable && ++clsh_d->clsh_users == 1) ||
421 (!enable && --clsh_d->clsh_users == 0))
Joonwoo Park6aa12162013-06-11 17:08:57 -0700422 snd_soc_update_bits(codec, WCD9XXX_A_CDC_CLSH_B1_CTL,
Joonwoo Park58d4a162013-07-23 16:19:37 -0700423 0x01, enable ? 0x01 : 0x00);
424 dev_dbg(codec->dev, "%s: clsh_users %d, enable %d", __func__,
425 clsh_d->clsh_users, enable);
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -0800426}
427
428static inline void wcd9xxx_enable_anc_delay(
429 struct snd_soc_codec *codec,
430 bool on)
431{
432 snd_soc_update_bits(codec, WCD9XXX_A_CDC_CLSH_B1_CTL,
433 0x02, on ? 0x02 : 0x00);
434}
435
Joonwoo Park6aa12162013-06-11 17:08:57 -0700436static inline void
437wcd9xxx_enable_buck(struct snd_soc_codec *codec,
Joonwoo Park58d4a162013-07-23 16:19:37 -0700438 struct wcd9xxx_clsh_cdc_data *clsh_d, bool enable)
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -0800439{
Joonwoo Park58d4a162013-07-23 16:19:37 -0700440 if ((enable && ++clsh_d->buck_users == 1) ||
441 (!enable && --clsh_d->buck_users == 0))
Joonwoo Park6aa12162013-06-11 17:08:57 -0700442 snd_soc_update_bits(codec, WCD9XXX_A_BUCK_MODE_1,
Joonwoo Park58d4a162013-07-23 16:19:37 -0700443 0x80, enable ? 0x80 : 0x00);
444 dev_dbg(codec->dev, "%s: buck_users %d, enable %d", __func__,
445 clsh_d->buck_users, enable);
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -0800446}
447
Joonwoo Park6aa12162013-06-11 17:08:57 -0700448static void (*clsh_state_fp[NUM_CLSH_STATES])(struct snd_soc_codec *,
449 struct wcd9xxx_clsh_cdc_data *,
450 u8 req_state, bool req_type);
451
452static const char *state_to_str(u8 state, char *buf, size_t buflen)
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -0800453{
Joonwoo Park6aa12162013-06-11 17:08:57 -0700454 int i;
455 int cnt = 0;
456 /*
457 * This array of strings should match with enum wcd9xxx_clsh_state_bit.
458 */
459 const char *states[] = {
460 "STATE_EAR",
461 "STATE_HPH_L",
462 "STATE_HPH_R",
463 "STATE_LO",
464 };
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -0800465
Joonwoo Park6aa12162013-06-11 17:08:57 -0700466 if (state == WCD9XXX_CLSH_STATE_IDLE) {
467 snprintf(buf, buflen, "[STATE_IDLE]");
468 goto done;
469 }
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -0800470
Joonwoo Park6aa12162013-06-11 17:08:57 -0700471 buf[0] = '\0';
472 for (i = 0; i < ARRAY_SIZE(states); i++) {
473 if (!(state & (1 << i)))
474 continue;
475 cnt = snprintf(buf, buflen - cnt - 1, "%s%s%s", buf,
476 buf[0] == '\0' ? "[" : "|",
477 states[i]);
478 }
479 if (cnt > 0)
480 strlcat(buf + cnt, "]", buflen);
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -0800481
Joonwoo Park6aa12162013-06-11 17:08:57 -0700482done:
483 if (buf[0] == '\0')
484 snprintf(buf, buflen, "[STATE_UNKNOWN]");
485 return buf;
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -0800486}
487
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -0800488static void wcd9xxx_cfg_clsh_param_common(
489 struct snd_soc_codec *codec)
490{
491 int i;
492 const struct wcd9xxx_reg_mask_val reg_set[] = {
493 {WCD9XXX_A_CDC_CLSH_BUCK_NCP_VARS, 0x3 << 0, 0},
494 {WCD9XXX_A_CDC_CLSH_BUCK_NCP_VARS, 0x3 << 2, 1 << 2},
495 {WCD9XXX_A_CDC_CLSH_BUCK_NCP_VARS, (0x1 << 4), 0},
496 {WCD9XXX_A_CDC_CLSH_B2_CTL, (0x3 << 0), 0x01},
497 {WCD9XXX_A_CDC_CLSH_B2_CTL, (0x3 << 2), (0x01 << 2)},
498 {WCD9XXX_A_CDC_CLSH_B2_CTL, (0xf << 4), (0x03 << 4)},
499 {WCD9XXX_A_CDC_CLSH_B3_CTL, (0xf << 4), (0x03 << 4)},
500 {WCD9XXX_A_CDC_CLSH_B3_CTL, (0xf << 0), (0x0B)},
501 {WCD9XXX_A_CDC_CLSH_B1_CTL, (0x1 << 5), (0x01 << 5)},
502 {WCD9XXX_A_CDC_CLSH_B1_CTL, (0x1 << 1), (0x01 << 1)},
503 };
504
505 for (i = 0; i < ARRAY_SIZE(reg_set); i++)
506 snd_soc_update_bits(codec, reg_set[i].reg, reg_set[i].mask,
507 reg_set[i].val);
508
509 dev_dbg(codec->dev, "%s: Programmed class H controller common parameters",
510 __func__);
511}
512
Joonwoo Park6aa12162013-06-11 17:08:57 -0700513static void wcd9xxx_chargepump_request(struct snd_soc_codec *codec, bool on)
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -0800514{
515 static int cp_count;
516
517 if (on && (++cp_count == 1)) {
518 snd_soc_update_bits(codec, WCD9XXX_A_CDC_CLK_OTHR_CTL,
Joonwoo Park6aa12162013-06-11 17:08:57 -0700519 0x01, 0x01);
Bhalchandra Gajaredb8ffcb2013-02-27 13:58:17 -0800520 dev_dbg(codec->dev, "%s: Charge Pump enabled, count = %d\n",
Joonwoo Park6aa12162013-06-11 17:08:57 -0700521 __func__, cp_count);
522 } else if (!on) {
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -0800523 if (--cp_count < 0) {
Joonwoo Park6aa12162013-06-11 17:08:57 -0700524 dev_dbg(codec->dev,
525 "%s: Unbalanced disable for charge pump\n",
526 __func__);
527 if (snd_soc_read(codec, WCD9XXX_A_CDC_CLK_OTHR_CTL) &
528 0x01) {
529 dev_dbg(codec->dev,
530 "%s: Actual chargepump is ON\n",
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -0800531 __func__);
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -0800532 }
533 cp_count = 0;
534 WARN_ON(1);
535 }
536
537 if (cp_count == 0) {
538 snd_soc_update_bits(codec, WCD9XXX_A_CDC_CLK_OTHR_CTL,
Joonwoo Park6aa12162013-06-11 17:08:57 -0700539 0x01, 0x00);
540 dev_dbg(codec->dev,
541 "%s: Charge pump disabled, count = %d\n",
542 __func__, cp_count);
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -0800543 }
544 }
545}
546
Santosh Mardi93a69192013-07-03 23:37:29 +0530547static int get_impedance_index(u32 imped)
548{
549 int i = 0;
550 if (imped < imped_index[i].imped_val) {
551 pr_debug("%s, detected impedance is less than 4 Ohm\n",
552 __func__);
553 goto ret;
554 }
555 for (i = 0; i < ARRAY_SIZE(imped_index); i++) {
556 if (imped >= imped_index[i].imped_val &&
557 imped < imped_index[i + 1].imped_val)
558 break;
559 }
560ret:
561 pr_debug("%s: selected impedance index = %d\n",
562 __func__, imped_index[i].index);
563 return imped_index[i].index;
564}
565
566void wcd9xxx_clsh_imped_config(struct snd_soc_codec *codec,
567 int imped)
568{
569 int i = 0;
570 int index = 0;
571 index = get_impedance_index(imped);
572 if (index > ARRAY_SIZE(imped_index)) {
573 pr_err("%s, invalid imped = %d\n", __func__, imped);
574 return;
575 }
576 for (i = 0; i < MAX_IMPED_PARAMS; i++)
577 snd_soc_write(codec, imped_table[index][i].reg,
578 imped_table[index][i].val);
579}
580
Joonwoo Parka08e0552013-03-05 18:28:23 -0800581static void wcd9xxx_clsh_comp_req(struct snd_soc_codec *codec,
582 struct wcd9xxx_clsh_cdc_data *clsh_d,
583 int compute_pa, bool on)
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -0800584{
Joonwoo Parka08e0552013-03-05 18:28:23 -0800585 u8 shift;
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -0800586
Joonwoo Parka08e0552013-03-05 18:28:23 -0800587 if (compute_pa == CLSH_COMPUTE_EAR) {
588 snd_soc_update_bits(codec, WCD9XXX_A_CDC_CLSH_B1_CTL, 0x10,
589 (on ? 0x10 : 0));
590 } else {
591 if (compute_pa == CLSH_COMPUTE_HPH_L) {
592 shift = 3;
593 } else if (compute_pa == CLSH_COMPUTE_HPH_R) {
594 shift = 2;
595 } else {
596 dev_dbg(codec->dev,
597 "%s: classh computation request is incorrect\n",
598 __func__);
599 return;
600 }
601
602 if (on)
603 wcd9xxx_resmgr_add_cond_update_bits(clsh_d->resmgr,
604 WCD9XXX_COND_HPH,
605 WCD9XXX_A_CDC_CLSH_B1_CTL,
606 shift, false);
607 else
608 wcd9xxx_resmgr_rm_cond_update_bits(clsh_d->resmgr,
609 WCD9XXX_COND_HPH,
610 WCD9XXX_A_CDC_CLSH_B1_CTL,
611 shift, false);
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -0800612 }
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -0800613}
614
Phani Kumar Uppalapati01a77e12013-08-08 15:31:35 -0700615int wcd9xxx_soc_update_bits_push(struct snd_soc_codec *codec,
616 struct list_head *list,
617 uint16_t reg, uint8_t mask,
618 uint8_t value, int delay)
619{
620 int rc;
621 struct wcd9xxx_register_save_node *node;
622
623 node = kmalloc(sizeof(*node), GFP_KERNEL);
624 if (unlikely(!node)) {
625 pr_err("%s: Not enough memory\n", __func__);
626 return -ENOMEM;
627 }
628 node->reg = reg;
629 node->value = snd_soc_read(codec, reg);
630 list_add(&node->lh, list);
631 if (mask == 0xFF)
632 rc = snd_soc_write(codec, reg, value);
633 else
634 rc = snd_soc_update_bits(codec, reg, mask, value);
635 if (delay)
636 usleep_range(delay, delay + USLEEP_RANGE_MARGIN_US);
637 return rc;
638}
639EXPORT_SYMBOL(wcd9xxx_soc_update_bits_push);
640
641void wcd9xxx_restore_registers(struct snd_soc_codec *codec,
642 struct list_head *lh)
643{
644 struct wcd9xxx_register_save_node *node, *nodetmp;
645
646 list_for_each_entry_safe(node, nodetmp, lh, lh) {
647 snd_soc_write(codec, node->reg, node->value);
648 list_del(&node->lh);
649 kfree(node);
650 }
651}
652EXPORT_SYMBOL(wcd9xxx_restore_registers);
653
Joonwoo Park6aa12162013-06-11 17:08:57 -0700654static void wcd9xxx_set_buck_mode(struct snd_soc_codec *codec, u8 buck_vref)
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -0800655{
656 int i;
657 const struct wcd9xxx_reg_mask_val reg_set[] = {
Joonwoo Park58d4a162013-07-23 16:19:37 -0700658 {WCD9XXX_A_BUCK_MODE_5, 0x02, 0x02},
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -0800659 {WCD9XXX_A_BUCK_MODE_4, 0xFF, buck_vref},
660 {WCD9XXX_A_BUCK_MODE_1, 0x04, 0x04},
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -0800661 {WCD9XXX_A_BUCK_MODE_3, 0x04, 0x00},
662 {WCD9XXX_A_BUCK_MODE_3, 0x08, 0x00},
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -0800663 };
664
665 for (i = 0; i < ARRAY_SIZE(reg_set); i++)
666 snd_soc_update_bits(codec, reg_set[i].reg,
667 reg_set[i].mask, reg_set[i].val);
668
669 dev_dbg(codec->dev, "%s: Done\n", __func__);
670 usleep_range(BUCK_SETTLE_TIME_US, BUCK_SETTLE_TIME_US);
671}
672
Bhalchandra Gajare7c739522013-06-20 15:31:02 -0700673
674/* This will be called for all states except Lineout */
675static void wcd9xxx_clsh_enable_post_pa(struct snd_soc_codec *codec,
676 struct wcd9xxx_clsh_cdc_data *cdc_clsh_d)
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -0800677{
678 int i;
679 const struct wcd9xxx_reg_mask_val reg_set[] = {
680 {WCD9XXX_A_BUCK_MODE_5, 0x02, 0x00},
681 {WCD9XXX_A_NCP_STATIC, 0x20, 0x00},
682 {WCD9XXX_A_BUCK_MODE_3, 0x04, 0x04},
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -0800683 };
684
685 for (i = 0; i < ARRAY_SIZE(reg_set); i++)
686 snd_soc_update_bits(codec, reg_set[i].reg,
687 reg_set[i].mask, reg_set[i].val);
688
Bhalchandra Gajare7c739522013-06-20 15:31:02 -0700689 if (!cdc_clsh_d->is_dynamic_vdd_cp)
690 snd_soc_update_bits(codec, WCD9XXX_A_BUCK_MODE_3,
691 0x08, 0x08);
692
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -0800693 dev_dbg(codec->dev, "%s: completed clsh mode settings after PA enable\n",
694 __func__);
695
696}
697
Joonwoo Park6aa12162013-06-11 17:08:57 -0700698static void wcd9xxx_set_fclk_get_ncp(struct snd_soc_codec *codec,
699 struct wcd9xxx_clsh_cdc_data *clsh_d,
700 enum ncp_fclk_level fclk_level)
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -0800701{
Joonwoo Park6aa12162013-06-11 17:08:57 -0700702 clsh_d->ncp_users[fclk_level]++;
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -0800703
Joonwoo Park6aa12162013-06-11 17:08:57 -0700704 pr_debug("%s: enter ncp type %d users fclk8 %d, fclk5 %d\n", __func__,
705 fclk_level, clsh_d->ncp_users[NCP_FCLK_LEVEL_8],
706 clsh_d->ncp_users[NCP_FCLK_LEVEL_5]);
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -0800707
Joonwoo Park6aa12162013-06-11 17:08:57 -0700708 snd_soc_update_bits(codec, WCD9XXX_A_NCP_STATIC, 0x10, 0x00);
709 /* fclk level 8 dominates level 5 */
710 if (clsh_d->ncp_users[NCP_FCLK_LEVEL_8] > 0)
711 snd_soc_update_bits(codec, WCD9XXX_A_NCP_STATIC, 0x0F, 0x08);
712 else if (clsh_d->ncp_users[NCP_FCLK_LEVEL_5] > 0)
713 snd_soc_update_bits(codec, WCD9XXX_A_NCP_STATIC, 0x0F, 0x05);
714 else
715 WARN_ONCE(1, "Unexpected users %d,%d\n",
716 clsh_d->ncp_users[NCP_FCLK_LEVEL_8],
717 clsh_d->ncp_users[NCP_FCLK_LEVEL_5]);
718 snd_soc_update_bits(codec, WCD9XXX_A_NCP_STATIC, 0x20, 0x20);
719
720 /* enable NCP and wait until settles down */
721 if (snd_soc_update_bits(codec, WCD9XXX_A_NCP_EN, 0x01, 0x01))
722 usleep_range(NCP_SETTLE_TIME_US, NCP_SETTLE_TIME_US);
723 pr_debug("%s: leave\n", __func__);
724}
725
726static void wcd9xxx_set_fclk_put_ncp(struct snd_soc_codec *codec,
727 struct wcd9xxx_clsh_cdc_data *clsh_d,
728 enum ncp_fclk_level fclk_level)
729{
730 clsh_d->ncp_users[fclk_level]--;
731
732 pr_debug("%s: enter ncp type %d users fclk8 %d, fclk5 %d\n", __func__,
733 fclk_level, clsh_d->ncp_users[NCP_FCLK_LEVEL_8],
734 clsh_d->ncp_users[NCP_FCLK_LEVEL_5]);
735
736 if (clsh_d->ncp_users[NCP_FCLK_LEVEL_8] == 0 &&
737 clsh_d->ncp_users[NCP_FCLK_LEVEL_5] == 0)
738 snd_soc_update_bits(codec, WCD9XXX_A_NCP_EN, 0x01, 0x00);
739 else if (clsh_d->ncp_users[NCP_FCLK_LEVEL_8] == 0)
740 /* if dominating level 8 has gone, switch to 5 */
741 snd_soc_update_bits(codec, WCD9XXX_A_NCP_STATIC, 0x0F, 0x05);
742 pr_debug("%s: leave\n", __func__);
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -0800743}
744
745static void wcd9xxx_cfg_clsh_param_ear(struct snd_soc_codec *codec)
746{
747 int i;
748 const struct wcd9xxx_reg_mask_val reg_set[] = {
749 {WCD9XXX_A_CDC_CLSH_B1_CTL, (0x1 << 7), 0},
750 {WCD9XXX_A_CDC_CLSH_V_PA_HD_EAR, (0x3f << 0), 0x0D},
751 {WCD9XXX_A_CDC_CLSH_V_PA_MIN_EAR, (0x3f << 0), 0x3A},
752
753 /* Under assumption that EAR load is 10.7ohm */
754 {WCD9XXX_A_CDC_CLSH_IDLE_EAR_THSD, (0x3f << 0), 0x26},
755 {WCD9XXX_A_CDC_CLSH_FCLKONLY_EAR_THSD, (0x3f << 0), 0x2C},
756 {WCD9XXX_A_CDC_CLSH_I_PA_FACT_EAR_L, 0xff, 0xA9},
757 {WCD9XXX_A_CDC_CLSH_I_PA_FACT_EAR_U, 0xff, 0x07},
758 {WCD9XXX_A_CDC_CLSH_K_ADDR, (0x1 << 7), 0},
759 {WCD9XXX_A_CDC_CLSH_K_ADDR, (0xf << 0), 0x08},
760 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x1b},
761 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
762 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x2d},
763 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
764 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x36},
765 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
766 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x37},
767 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
768 };
769
770 for (i = 0; i < ARRAY_SIZE(reg_set); i++)
771 snd_soc_update_bits(codec, reg_set[i].reg,
772 reg_set[i].mask, reg_set[i].val);
773
774 dev_dbg(codec->dev, "%s: Programmed Class H controller EAR specific params\n",
775 __func__);
776}
777
778static void wcd9xxx_cfg_clsh_param_hph(struct snd_soc_codec *codec)
779{
780 int i;
781 const struct wcd9xxx_reg_mask_val reg_set[] = {
782 {WCD9XXX_A_CDC_CLSH_B1_CTL, (0x1 << 6), 0},
783 {WCD9XXX_A_CDC_CLSH_V_PA_HD_HPH, 0x3f, 0x0D},
784 {WCD9XXX_A_CDC_CLSH_V_PA_MIN_HPH, 0x3f, 0x1D},
785
786 /* Under assumption that HPH load is 16ohm per channel */
787 {WCD9XXX_A_CDC_CLSH_IDLE_HPH_THSD, 0x3f, 0x13},
788 {WCD9XXX_A_CDC_CLSH_FCLKONLY_HPH_THSD, 0x1f, 0x19},
789 {WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_L, 0xff, 0x97},
790 {WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_U, 0xff, 0x05},
791 {WCD9XXX_A_CDC_CLSH_K_ADDR, (0x1 << 7), 0},
792 {WCD9XXX_A_CDC_CLSH_K_ADDR, 0x0f, 0},
793 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0xAE},
794 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
795 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x1C},
796 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
797 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x24},
798 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
799 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x25},
800 {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
801 };
802
803 for (i = 0; i < ARRAY_SIZE(reg_set); i++)
804 snd_soc_update_bits(codec, reg_set[i].reg, reg_set[i].mask,
805 reg_set[i].val);
806 dev_dbg(codec->dev, "%s: Programmed Class H controller HPH specific params\n",
807 __func__);
808}
809
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -0800810static void wcd9xxx_clsh_state_ear(struct snd_soc_codec *codec,
811 struct wcd9xxx_clsh_cdc_data *clsh_d,
812 u8 req_state, bool is_enable)
813{
Joonwoo Park6aa12162013-06-11 17:08:57 -0700814 pr_debug("%s: enter %s\n", __func__, is_enable ? "enable" : "disable");
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -0800815 if (is_enable) {
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -0800816 wcd9xxx_cfg_clsh_param_common(codec);
817 wcd9xxx_cfg_clsh_param_ear(codec);
Joonwoo Park6aa12162013-06-11 17:08:57 -0700818 wcd9xxx_enable_clsh_block(codec, clsh_d, true);
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -0800819 wcd9xxx_chargepump_request(codec, true);
820 wcd9xxx_enable_anc_delay(codec, true);
Joonwoo Parka08e0552013-03-05 18:28:23 -0800821 wcd9xxx_clsh_comp_req(codec, clsh_d, CLSH_COMPUTE_EAR, true);
Joonwoo Park6aa12162013-06-11 17:08:57 -0700822 wcd9xxx_set_buck_mode(codec, BUCK_VREF_2V);
823 wcd9xxx_enable_buck(codec, clsh_d, true);
824 wcd9xxx_set_fclk_get_ncp(codec, clsh_d, NCP_FCLK_LEVEL_8);
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -0800825
826 dev_dbg(codec->dev, "%s: Enabled ear mode class h\n", __func__);
827 } else {
828 dev_dbg(codec->dev, "%s: stub fallback to ear\n", __func__);
Joonwoo Park6aa12162013-06-11 17:08:57 -0700829 wcd9xxx_set_fclk_put_ncp(codec, clsh_d, NCP_FCLK_LEVEL_8);
830 wcd9xxx_enable_buck(codec, clsh_d, false);
831 wcd9xxx_clsh_comp_req(codec, clsh_d, CLSH_COMPUTE_EAR, true);
832 wcd9xxx_chargepump_request(codec, false);
833 wcd9xxx_enable_clsh_block(codec, clsh_d, false);
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -0800834 }
835}
836
837static void wcd9xxx_clsh_state_hph_l(struct snd_soc_codec *codec,
838 struct wcd9xxx_clsh_cdc_data *clsh_d,
839 u8 req_state, bool is_enable)
840{
Joonwoo Park6aa12162013-06-11 17:08:57 -0700841 pr_debug("%s: enter %s\n", __func__, is_enable ? "enable" : "disable");
842
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -0800843 if (is_enable) {
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -0800844 wcd9xxx_cfg_clsh_param_common(codec);
845 wcd9xxx_cfg_clsh_param_hph(codec);
Joonwoo Park6aa12162013-06-11 17:08:57 -0700846 wcd9xxx_enable_clsh_block(codec, clsh_d, true);
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -0800847 wcd9xxx_chargepump_request(codec, true);
848 wcd9xxx_enable_anc_delay(codec, true);
Joonwoo Parka08e0552013-03-05 18:28:23 -0800849 wcd9xxx_clsh_comp_req(codec, clsh_d, CLSH_COMPUTE_HPH_L, true);
Joonwoo Park6aa12162013-06-11 17:08:57 -0700850 wcd9xxx_set_buck_mode(codec, BUCK_VREF_0P494V);
851 wcd9xxx_enable_buck(codec, clsh_d, true);
852 wcd9xxx_set_fclk_get_ncp(codec, clsh_d, NCP_FCLK_LEVEL_8);
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -0800853
854 dev_dbg(codec->dev, "%s: Done\n", __func__);
855 } else {
Joonwoo Park6aa12162013-06-11 17:08:57 -0700856 wcd9xxx_set_fclk_put_ncp(codec, clsh_d, NCP_FCLK_LEVEL_8);
857 wcd9xxx_enable_buck(codec, clsh_d, false);
858 wcd9xxx_clsh_comp_req(codec, clsh_d, CLSH_COMPUTE_HPH_L, false);
859 wcd9xxx_chargepump_request(codec, false);
860 wcd9xxx_enable_clsh_block(codec, clsh_d, false);
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -0800861 }
862}
863
864static void wcd9xxx_clsh_state_hph_r(struct snd_soc_codec *codec,
865 struct wcd9xxx_clsh_cdc_data *clsh_d,
866 u8 req_state, bool is_enable)
867{
Joonwoo Park6aa12162013-06-11 17:08:57 -0700868 pr_debug("%s: enter %s\n", __func__, is_enable ? "enable" : "disable");
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -0800869
Joonwoo Park6aa12162013-06-11 17:08:57 -0700870 if (is_enable) {
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -0800871 wcd9xxx_cfg_clsh_param_common(codec);
872 wcd9xxx_cfg_clsh_param_hph(codec);
Joonwoo Park6aa12162013-06-11 17:08:57 -0700873 wcd9xxx_enable_clsh_block(codec, clsh_d, true);
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -0800874 wcd9xxx_chargepump_request(codec, true);
875 wcd9xxx_enable_anc_delay(codec, true);
Joonwoo Parka08e0552013-03-05 18:28:23 -0800876 wcd9xxx_clsh_comp_req(codec, clsh_d, CLSH_COMPUTE_HPH_R, true);
Joonwoo Park6aa12162013-06-11 17:08:57 -0700877 wcd9xxx_set_buck_mode(codec, BUCK_VREF_0P494V);
878 wcd9xxx_enable_buck(codec, clsh_d, true);
879 wcd9xxx_set_fclk_get_ncp(codec, clsh_d, NCP_FCLK_LEVEL_8);
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -0800880
881 dev_dbg(codec->dev, "%s: Done\n", __func__);
882 } else {
Joonwoo Park6aa12162013-06-11 17:08:57 -0700883 wcd9xxx_set_fclk_put_ncp(codec, clsh_d, NCP_FCLK_LEVEL_8);
884 wcd9xxx_enable_buck(codec, clsh_d, false);
885 wcd9xxx_clsh_comp_req(codec, clsh_d, CLSH_COMPUTE_HPH_R, false);
886 wcd9xxx_chargepump_request(codec, false);
887 wcd9xxx_enable_clsh_block(codec, clsh_d, false);
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -0800888 }
889}
890
891static void wcd9xxx_clsh_state_hph_st(struct snd_soc_codec *codec,
892 struct wcd9xxx_clsh_cdc_data *clsh_d,
893 u8 req_state, bool is_enable)
894{
Joonwoo Park6aa12162013-06-11 17:08:57 -0700895 pr_debug("%s: enter %s\n", __func__, is_enable ? "enable" : "disable");
896
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -0800897 if (is_enable) {
Joonwoo Parka08e0552013-03-05 18:28:23 -0800898 wcd9xxx_clsh_comp_req(codec, clsh_d, CLSH_COMPUTE_HPH_L, true);
Joonwoo Park58d4a162013-07-23 16:19:37 -0700899 wcd9xxx_clsh_comp_req(codec, clsh_d, CLSH_COMPUTE_HPH_R, true);
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -0800900 } else {
901 dev_dbg(codec->dev, "%s: stub fallback to hph_st\n", __func__);
902 }
903}
904
905static void wcd9xxx_clsh_state_lo(struct snd_soc_codec *codec,
906 struct wcd9xxx_clsh_cdc_data *clsh_d,
907 u8 req_state, bool is_enable)
908{
Joonwoo Park58d4a162013-07-23 16:19:37 -0700909 pr_debug("%s: enter %s, buck_mv %d\n", __func__,
910 is_enable ? "enable" : "disable", clsh_d->buck_mv);
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -0800911
Joonwoo Park6aa12162013-06-11 17:08:57 -0700912 if (is_enable) {
913 wcd9xxx_set_buck_mode(codec, BUCK_VREF_1P8V);
914 wcd9xxx_enable_buck(codec, clsh_d, true);
915 wcd9xxx_set_fclk_get_ncp(codec, clsh_d, NCP_FCLK_LEVEL_5);
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -0800916
917 if (clsh_d->buck_mv == WCD9XXX_CDC_BUCK_MV_1P8) {
Joonwoo Park6aa12162013-06-11 17:08:57 -0700918 wcd9xxx_enable_buck(codec, clsh_d, false);
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -0800919 snd_soc_update_bits(codec, WCD9XXX_A_NCP_STATIC,
Joonwoo Park6aa12162013-06-11 17:08:57 -0700920 1 << 4, 1 << 4);
Bhalchandra Gajare8b90bc22013-06-19 00:38:24 -0700921 /* NCP settle time recommended by codec specification */
922 usleep_range(NCP_SETTLE_TIME_US,
Joonwoo Park6aa12162013-06-11 17:08:57 -0700923 NCP_SETTLE_TIME_US + 10);
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -0800924 } else {
Bhalchandra Gajare8b90bc22013-06-19 00:38:24 -0700925 /* NCP settle time recommended by codec specification */
926 usleep_range(NCP_SETTLE_TIME_US,
Joonwoo Park6aa12162013-06-11 17:08:57 -0700927 NCP_SETTLE_TIME_US + 10);
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -0800928 snd_soc_update_bits(codec, WCD9XXX_A_BUCK_MODE_5,
Joonwoo Park58d4a162013-07-23 16:19:37 -0700929 0x01, (0x01 & 0x03));
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -0800930 snd_soc_update_bits(codec, WCD9XXX_A_BUCK_MODE_5,
Joonwoo Park58d4a162013-07-23 16:19:37 -0700931 0xFC, (0xFC & 0xB));
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -0800932 }
Joonwoo Park6aa12162013-06-11 17:08:57 -0700933 snd_soc_update_bits(codec, WCD9XXX_A_BUCK_MODE_1, 0x04, 0x00);
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -0800934 } else {
935 dev_dbg(codec->dev, "%s: stub fallback to lineout\n", __func__);
Joonwoo Park6aa12162013-06-11 17:08:57 -0700936 wcd9xxx_set_fclk_put_ncp(codec, clsh_d, NCP_FCLK_LEVEL_5);
937 if (clsh_d->buck_mv != WCD9XXX_CDC_BUCK_MV_1P8)
938 wcd9xxx_enable_buck(codec, clsh_d, false);
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -0800939 }
940}
941
942static void wcd9xxx_clsh_state_err(struct snd_soc_codec *codec,
943 struct wcd9xxx_clsh_cdc_data *clsh_d,
944 u8 req_state, bool is_enable)
945{
Joonwoo Park6aa12162013-06-11 17:08:57 -0700946 char msg[128];
947
948 dev_dbg(codec->dev,
949 "%s Wrong request for class H state machine requested to %s %s",
950 __func__, is_enable ? "enable" : "disable",
951 state_to_str(req_state, msg, sizeof(msg)));
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -0800952 WARN_ON(1);
953}
954
955void wcd9xxx_clsh_fsm(struct snd_soc_codec *codec,
956 struct wcd9xxx_clsh_cdc_data *cdc_clsh_d,
957 u8 req_state, bool req_type, u8 clsh_event)
958{
959 u8 old_state, new_state;
Joonwoo Park6aa12162013-06-11 17:08:57 -0700960 char msg0[128], msg1[128];
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -0800961
962 switch (clsh_event) {
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -0800963 case WCD9XXX_CLSH_EVENT_PRE_DAC:
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -0800964 /* PRE_DAC event should be used only for Enable */
965 BUG_ON(req_type != WCD9XXX_CLSH_REQ_ENABLE);
966
967 old_state = cdc_clsh_d->state;
968 new_state = old_state | req_state;
969
Joonwoo Park6aa12162013-06-11 17:08:57 -0700970 (*clsh_state_fp[req_state]) (codec, cdc_clsh_d, req_state,
971 req_type);
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -0800972 cdc_clsh_d->state = new_state;
Bhalchandra Gajaredb8ffcb2013-02-27 13:58:17 -0800973 dev_dbg(codec->dev, "%s: ClassH state transition from %s to %s\n",
Joonwoo Park6aa12162013-06-11 17:08:57 -0700974 __func__, state_to_str(old_state, msg0, sizeof(msg0)),
975 state_to_str(cdc_clsh_d->state, msg1, sizeof(msg1)));
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -0800976
977 break;
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -0800978 case WCD9XXX_CLSH_EVENT_POST_PA:
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -0800979 if (req_type == WCD9XXX_CLSH_REQ_DISABLE) {
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -0800980 old_state = cdc_clsh_d->state;
981 new_state = old_state & (~req_state);
982
983 if (new_state < NUM_CLSH_STATES) {
Joonwoo Park6aa12162013-06-11 17:08:57 -0700984 (*clsh_state_fp[req_state]) (codec, cdc_clsh_d,
985 req_state,
986 req_type);
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -0800987 cdc_clsh_d->state = new_state;
Bhalchandra Gajaredb8ffcb2013-02-27 13:58:17 -0800988 dev_dbg(codec->dev, "%s: ClassH state transition from %s to %s\n",
Joonwoo Park6aa12162013-06-11 17:08:57 -0700989 __func__, state_to_str(old_state, msg0,
990 sizeof(msg0)),
991 state_to_str(cdc_clsh_d->state, msg1,
992 sizeof(msg1)));
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -0800993
994 } else {
995 dev_dbg(codec->dev, "%s: wrong new state = %x\n",
996 __func__, new_state);
997 }
Joonwoo Park6aa12162013-06-11 17:08:57 -0700998 } else if (!(cdc_clsh_d->state & WCD9XXX_CLSH_STATE_LO)) {
Bhalchandra Gajare7c739522013-06-20 15:31:02 -0700999 wcd9xxx_clsh_enable_post_pa(codec, cdc_clsh_d);
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08001000 }
1001
1002 break;
1003 }
1004
1005}
1006EXPORT_SYMBOL_GPL(wcd9xxx_clsh_fsm);
1007
Joonwoo Parka08e0552013-03-05 18:28:23 -08001008void wcd9xxx_clsh_init(struct wcd9xxx_clsh_cdc_data *clsh,
1009 struct wcd9xxx_resmgr *resmgr)
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08001010{
1011 int i;
1012 clsh->state = WCD9XXX_CLSH_STATE_IDLE;
Joonwoo Parka08e0552013-03-05 18:28:23 -08001013 clsh->resmgr = resmgr;
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08001014
1015 for (i = 0; i < NUM_CLSH_STATES; i++)
1016 clsh_state_fp[i] = wcd9xxx_clsh_state_err;
1017
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08001018 clsh_state_fp[WCD9XXX_CLSH_STATE_EAR] = wcd9xxx_clsh_state_ear;
1019 clsh_state_fp[WCD9XXX_CLSH_STATE_HPHL] =
1020 wcd9xxx_clsh_state_hph_l;
1021 clsh_state_fp[WCD9XXX_CLSH_STATE_HPHR] =
1022 wcd9xxx_clsh_state_hph_r;
1023 clsh_state_fp[WCD9XXX_CLSH_STATE_HPH_ST] =
1024 wcd9xxx_clsh_state_hph_st;
1025 clsh_state_fp[WCD9XXX_CLSH_STATE_LO] = wcd9xxx_clsh_state_lo;
1026
1027}
1028EXPORT_SYMBOL_GPL(wcd9xxx_clsh_init);
1029
1030MODULE_DESCRIPTION("WCD9XXX Common");
1031MODULE_LICENSE("GPL v2");