wcd9xxx-resmgr.h 7.8 KB

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