blob: e35d6161d488c1e8b1bf175b0ae135b3f1e5d7f7 [file] [log] [blame]
Banajit Goswamide8271c2017-01-18 00:28:59 -08001/* Copyright (c) 2012-2014, 2016 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#ifndef __WCD9XXX_COMMON_H__
13#define __WCD9XXX_COMMON_H__
14
15#include <linux/notifier.h>
16#include <linux/mfd/wcd9xxx/core.h>
17#include <linux/mfd/wcd9xxx/wcd9xxx_registers.h>
18
19enum wcd9xxx_bandgap_type {
20 WCD9XXX_BANDGAP_OFF,
21 WCD9XXX_BANDGAP_AUDIO_MODE,
22 WCD9XXX_BANDGAP_MBHC_MODE,
23};
24
25enum wcd9xxx_cdc_type {
26 WCD9XXX_CDC_TYPE_INVALID = 0,
27 WCD9XXX_CDC_TYPE_TAIKO,
28 WCD9XXX_CDC_TYPE_TAPAN,
29 WCD9XXX_CDC_TYPE_HELICON,
30 WCD9XXX_CDC_TYPE_TOMTOM,
31};
32
33enum wcd9xxx_clock_type {
34 WCD9XXX_CLK_OFF,
35 WCD9XXX_CLK_RCO,
36 WCD9XXX_CLK_MCLK,
37};
38
39enum wcd9xxx_clock_config_mode {
40 WCD9XXX_CFG_MCLK = 0,
41 WCD9XXX_CFG_RCO,
42 WCD9XXX_CFG_CAL_RCO,
43};
44
45enum wcd9xxx_cfilt_sel {
46 WCD9XXX_CFILT1_SEL,
47 WCD9XXX_CFILT2_SEL,
48 WCD9XXX_CFILT3_SEL,
49 WCD9XXX_NUM_OF_CFILT,
50};
51
52struct wcd9xxx_reg_address {
53 u16 micb_4_ctl;
54 u16 micb_4_int_rbias;
55 u16 micb_4_mbhc;
56};
57
58enum wcd9xxx_notify_event {
59 WCD9XXX_EVENT_INVALID,
60
61 WCD9XXX_EVENT_PRE_RCO_ON,
62 WCD9XXX_EVENT_POST_RCO_ON,
63 WCD9XXX_EVENT_PRE_RCO_OFF,
64 WCD9XXX_EVENT_POST_RCO_OFF,
65
66 WCD9XXX_EVENT_PRE_MCLK_ON,
67 WCD9XXX_EVENT_POST_MCLK_ON,
68 WCD9XXX_EVENT_PRE_MCLK_OFF,
69 WCD9XXX_EVENT_POST_MCLK_OFF,
70
71 WCD9XXX_EVENT_PRE_BG_OFF,
72 WCD9XXX_EVENT_POST_BG_OFF,
73 WCD9XXX_EVENT_PRE_BG_AUDIO_ON,
74 WCD9XXX_EVENT_POST_BG_AUDIO_ON,
75 WCD9XXX_EVENT_PRE_BG_MBHC_ON,
76 WCD9XXX_EVENT_POST_BG_MBHC_ON,
77
78 WCD9XXX_EVENT_PRE_MICBIAS_1_OFF,
79 WCD9XXX_EVENT_POST_MICBIAS_1_OFF,
80 WCD9XXX_EVENT_PRE_MICBIAS_2_OFF,
81 WCD9XXX_EVENT_POST_MICBIAS_2_OFF,
82 WCD9XXX_EVENT_PRE_MICBIAS_3_OFF,
83 WCD9XXX_EVENT_POST_MICBIAS_3_OFF,
84 WCD9XXX_EVENT_PRE_MICBIAS_4_OFF,
85 WCD9XXX_EVENT_POST_MICBIAS_4_OFF,
86 WCD9XXX_EVENT_PRE_MICBIAS_1_ON,
87 WCD9XXX_EVENT_POST_MICBIAS_1_ON,
88 WCD9XXX_EVENT_PRE_MICBIAS_2_ON,
89 WCD9XXX_EVENT_POST_MICBIAS_2_ON,
90 WCD9XXX_EVENT_PRE_MICBIAS_3_ON,
91 WCD9XXX_EVENT_POST_MICBIAS_3_ON,
92 WCD9XXX_EVENT_PRE_MICBIAS_4_ON,
93 WCD9XXX_EVENT_POST_MICBIAS_4_ON,
94
95 WCD9XXX_EVENT_PRE_CFILT_1_OFF,
96 WCD9XXX_EVENT_POST_CFILT_1_OFF,
97 WCD9XXX_EVENT_PRE_CFILT_2_OFF,
98 WCD9XXX_EVENT_POST_CFILT_2_OFF,
99 WCD9XXX_EVENT_PRE_CFILT_3_OFF,
100 WCD9XXX_EVENT_POST_CFILT_3_OFF,
101 WCD9XXX_EVENT_PRE_CFILT_1_ON,
102 WCD9XXX_EVENT_POST_CFILT_1_ON,
103 WCD9XXX_EVENT_PRE_CFILT_2_ON,
104 WCD9XXX_EVENT_POST_CFILT_2_ON,
105 WCD9XXX_EVENT_PRE_CFILT_3_ON,
106 WCD9XXX_EVENT_POST_CFILT_3_ON,
107
108 WCD9XXX_EVENT_PRE_HPHL_PA_ON,
109 WCD9XXX_EVENT_POST_HPHL_PA_OFF,
110 WCD9XXX_EVENT_PRE_HPHR_PA_ON,
111 WCD9XXX_EVENT_POST_HPHR_PA_OFF,
112
113 WCD9XXX_EVENT_POST_RESUME,
114
115 WCD9XXX_EVENT_PRE_TX_3_ON,
116 WCD9XXX_EVENT_POST_TX_3_OFF,
117
118 WCD9XXX_EVENT_LAST,
119};
120
121struct wcd9xxx_resmgr_cb {
122 int (*cdc_rco_ctrl)(struct snd_soc_codec *, bool);
123};
124
125struct wcd9xxx_resmgr {
126 struct snd_soc_codec *codec;
127 struct wcd9xxx_core_resource *core_res;
128
129 u32 rx_bias_count;
130
131 /*
132 * bandgap_type, bg_audio_users and bg_mbhc_users have to be
133 * referred/manipulated after acquiring codec_bg_clk_lock mutex
134 */
135 enum wcd9xxx_bandgap_type bandgap_type;
136 u16 bg_audio_users;
137 u16 bg_mbhc_users;
138
139 /*
140 * clk_type, clk_rco_users and clk_mclk_users have to be
141 * referred/manipulated after acquiring codec_bg_clk_lock mutex
142 */
143 enum wcd9xxx_clock_type clk_type;
144 u16 clk_rco_users;
145 u16 clk_mclk_users;
146 u16 ext_clk_users;
147
148 /* cfilt users per cfilts */
149 u16 cfilt_users[WCD9XXX_NUM_OF_CFILT];
150
151 struct wcd9xxx_reg_address *reg_addr;
152
153 struct wcd9xxx_pdata *pdata;
154
155 struct wcd9xxx_micbias_setting *micbias_pdata;
156
157 struct blocking_notifier_head notifier;
158 /* Notifier needs mbhc pointer with resmgr */
159 struct wcd9xxx_mbhc *mbhc;
160
161 unsigned long cond_flags;
162 unsigned long cond_avail_flags;
163 struct list_head update_bit_cond_h;
164 struct mutex update_bit_cond_lock;
165
166 /*
167 * Currently, only used for mbhc purpose, to protect
168 * concurrent execution of mbhc threaded irq handlers and
169 * kill race between DAPM and MBHC. But can serve as a
170 * general lock to protect codec resource
171 */
172 struct mutex codec_resource_lock;
173 struct mutex codec_bg_clk_lock;
174
175 enum wcd9xxx_cdc_type codec_type;
176
177 const struct wcd9xxx_resmgr_cb *resmgr_cb;
178};
179
180int wcd9xxx_resmgr_init(struct wcd9xxx_resmgr *resmgr,
181 struct snd_soc_codec *codec,
182 struct wcd9xxx_core_resource *core_res,
183 struct wcd9xxx_pdata *pdata,
184 struct wcd9xxx_micbias_setting *micbias_pdata,
185 struct wcd9xxx_reg_address *reg_addr,
186 const struct wcd9xxx_resmgr_cb *resmgr_cb,
187 enum wcd9xxx_cdc_type cdc_type);
188void wcd9xxx_resmgr_deinit(struct wcd9xxx_resmgr *resmgr);
189
190int wcd9xxx_resmgr_enable_config_mode(struct wcd9xxx_resmgr *resmgr,
191 int enable);
192
193void wcd9xxx_resmgr_enable_rx_bias(struct wcd9xxx_resmgr *resmgr, u32 enable);
194void wcd9xxx_resmgr_get_clk_block(struct wcd9xxx_resmgr *resmgr,
195 enum wcd9xxx_clock_type type);
196void wcd9xxx_resmgr_put_clk_block(struct wcd9xxx_resmgr *resmgr,
197 enum wcd9xxx_clock_type type);
198void wcd9xxx_resmgr_get_bandgap(struct wcd9xxx_resmgr *resmgr,
199 const enum wcd9xxx_bandgap_type choice);
200void wcd9xxx_resmgr_put_bandgap(struct wcd9xxx_resmgr *resmgr,
201 enum wcd9xxx_bandgap_type choice);
202void wcd9xxx_resmgr_cfilt_get(struct wcd9xxx_resmgr *resmgr,
203 enum wcd9xxx_cfilt_sel cfilt_sel);
204void wcd9xxx_resmgr_cfilt_put(struct wcd9xxx_resmgr *resmgr,
205 enum wcd9xxx_cfilt_sel cfilt_sel);
206int wcd9xxx_resmgr_get_clk_type(struct wcd9xxx_resmgr *resmgr);
207
208void wcd9xxx_resmgr_bcl_lock(struct wcd9xxx_resmgr *resmgr);
209void wcd9xxx_resmgr_post_ssr(struct wcd9xxx_resmgr *resmgr);
210#define WCD9XXX_BCL_LOCK(resmgr) \
211{ \
212 pr_debug("%s: Acquiring BCL\n", __func__); \
213 wcd9xxx_resmgr_bcl_lock(resmgr); \
214 pr_debug("%s: Acquiring BCL done\n", __func__); \
215}
216
217void wcd9xxx_resmgr_bcl_unlock(struct wcd9xxx_resmgr *resmgr);
218#define WCD9XXX_BCL_UNLOCK(resmgr) \
219{ \
220 pr_debug("%s: Release BCL\n", __func__); \
221 wcd9xxx_resmgr_bcl_unlock(resmgr); \
222}
223
224#define WCD9XXX_BCL_ASSERT_LOCKED(resmgr) \
225{ \
226 WARN_ONCE(!mutex_is_locked(&resmgr->codec_resource_lock), \
227 "%s: BCL should have acquired\n", __func__); \
228}
229
230#define WCD9XXX_BG_CLK_LOCK(resmgr) \
231{ \
232 struct wcd9xxx_resmgr *__resmgr = resmgr; \
233 pr_debug("%s: Acquiring BG_CLK\n", __func__); \
234 mutex_lock(&__resmgr->codec_bg_clk_lock); \
235 pr_debug("%s: Acquiring BG_CLK done\n", __func__); \
236}
237
238#define WCD9XXX_BG_CLK_UNLOCK(resmgr) \
239{ \
240 struct wcd9xxx_resmgr *__resmgr = resmgr; \
241 pr_debug("%s: Releasing BG_CLK\n", __func__); \
242 mutex_unlock(&__resmgr->codec_bg_clk_lock); \
243}
244
245#define WCD9XXX_BG_CLK_ASSERT_LOCKED(resmgr) \
246{ \
247 WARN_ONCE(!mutex_is_locked(&resmgr->codec_bg_clk_lock), \
248 "%s: BG_CLK lock should have acquired\n", __func__); \
249}
250
251const char *wcd9xxx_get_event_string(enum wcd9xxx_notify_event type);
252int wcd9xxx_resmgr_get_k_val(struct wcd9xxx_resmgr *resmgr,
253 unsigned int cfilt_mv);
254int wcd9xxx_resmgr_register_notifier(struct wcd9xxx_resmgr *resmgr,
255 struct notifier_block *nblock);
256int wcd9xxx_resmgr_unregister_notifier(struct wcd9xxx_resmgr *resmgr,
257 struct notifier_block *nblock);
258void wcd9xxx_resmgr_notifier_call(struct wcd9xxx_resmgr *resmgr,
259 const enum wcd9xxx_notify_event e);
260
261enum wcd9xxx_resmgr_cond {
262 WCD9XXX_COND_HPH = 0x01, /* Headphone */
263 WCD9XXX_COND_HPH_MIC = 0x02, /* Microphone on the headset */
264};
265void wcd9xxx_regmgr_cond_register(struct wcd9xxx_resmgr *resmgr,
266 unsigned long condbits);
267void wcd9xxx_regmgr_cond_deregister(struct wcd9xxx_resmgr *resmgr,
268 unsigned long condbits);
269int wcd9xxx_resmgr_rm_cond_update_bits(struct wcd9xxx_resmgr *resmgr,
270 enum wcd9xxx_resmgr_cond cond,
271 unsigned short reg, int shift,
272 bool invert);
273int wcd9xxx_resmgr_add_cond_update_bits(struct wcd9xxx_resmgr *resmgr,
274 enum wcd9xxx_resmgr_cond cond,
275 unsigned short reg, int shift,
276 bool invert);
277void wcd9xxx_resmgr_cond_update_cond(struct wcd9xxx_resmgr *resmgr,
278 enum wcd9xxx_resmgr_cond cond, bool set);
279
280#endif /* __WCD9XXX_COMMON_H__ */