wcd937x.c 39 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412
  1. /*
  2. * Copyright (c) 2018, The Linux Foundation. All rights reserved.
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License version 2 and
  6. * only version 2 as published by the Free Software Foundation.
  7. *
  8. * This program is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. */
  13. #include <linux/module.h>
  14. #include <linux/slab.h>
  15. #include <linux/platform_device.h>
  16. #include <linux/device.h>
  17. #include <linux/delay.h>
  18. #include <linux/kernel.h>
  19. #include <linux/component.h>
  20. #include <sound/soc.h>
  21. #include <sound/tlv.h>
  22. #include <soc/soundwire.h>
  23. #include <linux/regmap.h>
  24. #include <sound/soc.h>
  25. #include <sound/soc-dapm.h>
  26. #include "internal.h"
  27. #include "../wcdcal-hwdep.h"
  28. #include "wcd937x-registers.h"
  29. #include "../msm-cdc-pinctrl.h"
  30. #define WCD9370_VARIANT 0
  31. #define WCD9375_VARIANT 5
  32. static const DECLARE_TLV_DB_SCALE(line_gain, 0, 7, 1);
  33. static const DECLARE_TLV_DB_SCALE(analog_gain, 0, 25, 1);
  34. static int wcd937x_init_reg(struct snd_soc_codec *codec)
  35. {
  36. snd_soc_update_bits(codec, WCD937X_SLEEP_CTL, 0x0E, 0x0E);
  37. snd_soc_update_bits(codec, WCD937X_SLEEP_CTL, 0x80, 0x80);
  38. usleep_range(1000, 1010);
  39. snd_soc_update_bits(codec, WCD937X_SLEEP_CTL, 0x40, 0x40);
  40. usleep_range(1000, 1010);
  41. snd_soc_update_bits(codec, WCD937X_LDORXTX_CONFIG, 0x10, 0x00);
  42. snd_soc_update_bits(codec, WCD937X_BIAS_VBG_FINE_ADJ, 0xF0, 0x80);
  43. snd_soc_update_bits(codec, WCD937X_ANA_BIAS, 0x80, 0x80);
  44. snd_soc_update_bits(codec, WCD937X_ANA_BIAS, 0x40, 0x40);
  45. usleep_range(10000, 10010);
  46. snd_soc_update_bits(codec, WCD937X_ANA_BIAS, 0x40, 0x00);
  47. return 0;
  48. }
  49. static int wcd937x_rx_clk_enable(struct snd_soc_codec *codec)
  50. {
  51. struct wcd937x_priv *wcd937x = snd_soc_codec_get_drvdata(codec);
  52. if (wcd937x->rx_clk_cnt == 0) {
  53. snd_soc_update_bits(codec, WCD937X_DIGITAL_CDC_DIG_CLK_CTL,
  54. 0x08, 0x08);
  55. snd_soc_update_bits(codec, WCD937X_DIGITAL_CDC_ANA_CLK_CTL,
  56. 0x01, 0x01);
  57. snd_soc_update_bits(codec, WCD937X_ANA_RX_SUPPLIES, 0x01, 0x01);
  58. snd_soc_update_bits(codec, WCD937X_DIGITAL_CDC_RX0_CTL,
  59. 0x40, 0x00);
  60. snd_soc_update_bits(codec, WCD937X_DIGITAL_CDC_ANA_CLK_CTL,
  61. 0x02, 0x02);
  62. }
  63. wcd937x->rx_clk_cnt++;
  64. return 0;
  65. }
  66. static int wcd937x_rx_clk_disable(struct snd_soc_codec *codec)
  67. {
  68. struct wcd937x_priv *wcd937x = snd_soc_codec_get_drvdata(codec);
  69. wcd937x->rx_clk_cnt--;
  70. if (wcd937x->rx_clk_cnt == 0) {
  71. snd_soc_update_bits(codec, WCD937X_ANA_RX_SUPPLIES, 0x40, 0x00);
  72. snd_soc_update_bits(codec, WCD937X_ANA_RX_SUPPLIES, 0x80, 0x00);
  73. snd_soc_update_bits(codec, WCD937X_ANA_RX_SUPPLIES, 0x01, 0x00);
  74. snd_soc_update_bits(codec, WCD937X_DIGITAL_CDC_ANA_CLK_CTL,
  75. 0x02, 0x00);
  76. snd_soc_update_bits(codec, WCD937X_DIGITAL_CDC_ANA_CLK_CTL,
  77. 0x01, 0x00);
  78. }
  79. return 0;
  80. }
  81. static int wcd937x_codec_hphl_dac_event(struct snd_soc_dapm_widget *w,
  82. struct snd_kcontrol *kcontrol,
  83. int event)
  84. {
  85. struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
  86. dev_dbg(codec->dev, "%s wname: %s event: %d\n", __func__,
  87. w->name, event);
  88. switch (event) {
  89. case SND_SOC_DAPM_PRE_PMU:
  90. wcd937x_rx_clk_enable(codec);
  91. snd_soc_update_bits(codec, WCD937X_DIGITAL_CDC_DIG_CLK_CTL,
  92. 0x01, 0x01);
  93. snd_soc_update_bits(codec, WCD937X_DIGITAL_CDC_HPH_GAIN_CTL,
  94. 0x04, 0x04);
  95. snd_soc_update_bits(codec, WCD937X_HPH_RDAC_CLK_CTL1,
  96. 0x80, 0x00);
  97. break;
  98. case SND_SOC_DAPM_POST_PMU:
  99. snd_soc_update_bits(codec, WCD937X_HPH_NEW_INT_RDAC_HD2_CTL_L,
  100. 0x0F, 0x02);
  101. snd_soc_update_bits(codec, WCD937X_DIGITAL_CDC_COMP_CTL_0,
  102. 0x02, 0x02);
  103. usleep_range(5000, 5010);
  104. snd_soc_update_bits(codec, WCD937X_HPH_NEW_INT_HPH_TIMER1,
  105. 0x02, 0x00);
  106. break;
  107. }
  108. return 0;
  109. }
  110. static int wcd937x_codec_hphr_dac_event(struct snd_soc_dapm_widget *w,
  111. struct snd_kcontrol *kcontrol,
  112. int event)
  113. {
  114. struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
  115. dev_dbg(codec->dev, "%s wname: %s event: %d\n", __func__,
  116. w->name, event);
  117. switch (event) {
  118. case SND_SOC_DAPM_PRE_PMU:
  119. wcd937x_rx_clk_enable(codec);
  120. snd_soc_update_bits(codec, WCD937X_DIGITAL_CDC_DIG_CLK_CTL,
  121. 0x02, 0x02);
  122. snd_soc_update_bits(codec, WCD937X_DIGITAL_CDC_HPH_GAIN_CTL,
  123. 0x08, 0x08);
  124. snd_soc_update_bits(codec, WCD937X_HPH_RDAC_CLK_CTL1,
  125. 0x80, 0x00);
  126. break;
  127. case SND_SOC_DAPM_POST_PMU:
  128. snd_soc_update_bits(codec, WCD937X_HPH_NEW_INT_RDAC_HD2_CTL_R,
  129. 0x0F, 0x02);
  130. snd_soc_update_bits(codec, WCD937X_DIGITAL_CDC_COMP_CTL_0,
  131. 0x01, 0x01);
  132. usleep_range(5000, 5010);
  133. snd_soc_update_bits(codec, WCD937X_HPH_NEW_INT_HPH_TIMER1,
  134. 0x02, 0x00);
  135. break;
  136. }
  137. return 0;
  138. }
  139. static int wcd937x_codec_ear_dac_event(struct snd_soc_dapm_widget *w,
  140. struct snd_kcontrol *kcontrol,
  141. int event)
  142. {
  143. struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
  144. dev_dbg(codec->dev, "%s wname: %s event: %d\n", __func__,
  145. w->name, event);
  146. switch (event) {
  147. case SND_SOC_DAPM_PRE_PMU:
  148. wcd937x_rx_clk_enable(codec);
  149. snd_soc_update_bits(codec, WCD937X_DIGITAL_CDC_HPH_GAIN_CTL,
  150. 0x04, 0x04);
  151. snd_soc_update_bits(codec, WCD937X_DIGITAL_CDC_DIG_CLK_CTL,
  152. 0x01, 0x01);
  153. snd_soc_update_bits(codec, WCD937X_DIGITAL_CDC_COMP_CTL_0,
  154. 0x02, 0x02);
  155. usleep_range(5000, 5010);
  156. break;
  157. };
  158. return 0;
  159. }
  160. static int wcd937x_codec_aux_dac_event(struct snd_soc_dapm_widget *w,
  161. struct snd_kcontrol *kcontrol,
  162. int event)
  163. {
  164. struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
  165. dev_dbg(codec->dev, "%s wname: %s event: %d\n", __func__,
  166. w->name, event);
  167. switch (event) {
  168. case SND_SOC_DAPM_PRE_PMU:
  169. wcd937x_rx_clk_enable(codec);
  170. snd_soc_update_bits(codec, WCD937X_DIGITAL_CDC_ANA_CLK_CTL,
  171. 0x04, 0x04);
  172. snd_soc_update_bits(codec, WCD937X_DIGITAL_CDC_DIG_CLK_CTL,
  173. 0x04, 0x04);
  174. snd_soc_update_bits(codec, WCD937X_DIGITAL_CDC_AUX_GAIN_CTL,
  175. 0x01, 0x01);
  176. break;
  177. case SND_SOC_DAPM_POST_PMD:
  178. wcd937x_rx_clk_disable(codec);
  179. snd_soc_update_bits(codec, WCD937X_DIGITAL_CDC_ANA_CLK_CTL,
  180. 0x04, 0x00);
  181. break;
  182. };
  183. return 0;
  184. }
  185. static int wcd937x_codec_enable_hphr_pa(struct snd_soc_dapm_widget *w,
  186. struct snd_kcontrol *kcontrol,
  187. int event)
  188. {
  189. struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
  190. dev_dbg(codec->dev, "%s wname: %s event: %d\n", __func__,
  191. w->name, event);
  192. switch (event) {
  193. case SND_SOC_DAPM_PRE_PMU:
  194. snd_soc_update_bits(codec, WCD937X_ANA_HPH, 0x10, 0x10);
  195. usleep_range(100, 110);
  196. break;
  197. case SND_SOC_DAPM_POST_PMU:
  198. usleep_range(7000, 7010);
  199. snd_soc_update_bits(codec, WCD937X_HPH_NEW_INT_HPH_TIMER1,
  200. 0x02, 0x02);
  201. snd_soc_update_bits(codec, WCD937X_ANA_RX_SUPPLIES,
  202. 0x02, 0x02);
  203. break;
  204. case SND_SOC_DAPM_POST_PMD:
  205. usleep_range(7000, 7010);
  206. snd_soc_update_bits(codec, WCD937X_ANA_HPH, 0x10, 0x00);
  207. break;
  208. };
  209. return 0;
  210. }
  211. static int wcd937x_codec_enable_hphl_pa(struct snd_soc_dapm_widget *w,
  212. struct snd_kcontrol *kcontrol,
  213. int event)
  214. {
  215. struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
  216. switch (event) {
  217. case SND_SOC_DAPM_PRE_PMU:
  218. snd_soc_update_bits(codec, WCD937X_ANA_HPH, 0x0C, 0x08);
  219. snd_soc_update_bits(codec, WCD937X_ANA_HPH, 0x20, 0x20);
  220. usleep_range(100, 110);
  221. break;
  222. case SND_SOC_DAPM_POST_PMU:
  223. usleep_range(7000, 7010);
  224. snd_soc_update_bits(codec, WCD937X_HPH_NEW_INT_HPH_TIMER1,
  225. 0x02, 0x02);
  226. snd_soc_update_bits(codec, WCD937X_ANA_RX_SUPPLIES,
  227. 0x02, 0x02);
  228. break;
  229. case SND_SOC_DAPM_POST_PMD:
  230. usleep_range(7000, 7010);
  231. snd_soc_update_bits(codec, WCD937X_ANA_HPH, 0x20, 0x00);
  232. break;
  233. };
  234. return 0;
  235. }
  236. static int wcd937x_codec_enable_aux_pa(struct snd_soc_dapm_widget *w,
  237. struct snd_kcontrol *kcontrol,
  238. int event)
  239. {
  240. struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
  241. dev_dbg(codec->dev, "%s wname: %s event: %d\n", __func__,
  242. w->name, event);
  243. switch (event) {
  244. case SND_SOC_DAPM_PRE_PMU:
  245. snd_soc_update_bits(codec, WCD937X_ANA_RX_SUPPLIES,
  246. 0x80, 0x80);
  247. usleep_range(500, 510);
  248. snd_soc_update_bits(codec, WCD937X_CLASSH_MODE_2, 0xFF, 0x3A);
  249. usleep_range(500, 510);
  250. break;
  251. case SND_SOC_DAPM_POST_PMU:
  252. usleep_range(1000, 1010);
  253. snd_soc_update_bits(codec, WCD937X_ANA_RX_SUPPLIES,
  254. 0x20, 0x20);
  255. break;
  256. case SND_SOC_DAPM_POST_PMD:
  257. usleep_range(1000, 1010);
  258. usleep_range(1000, 1010);
  259. break;
  260. };
  261. return 0;
  262. }
  263. static int wcd937x_codec_enable_ear_pa(struct snd_soc_dapm_widget *w,
  264. struct snd_kcontrol *kcontrol,
  265. int event)
  266. {
  267. struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
  268. dev_dbg(codec->dev, "%s wname: %s event: %d\n", __func__,
  269. w->name, event);
  270. switch (event) {
  271. case SND_SOC_DAPM_PRE_PMU:
  272. snd_soc_update_bits(codec, WCD937X_ANA_RX_SUPPLIES,
  273. 0x08, 0x08);
  274. usleep_range(500, 510);
  275. snd_soc_update_bits(codec, WCD937X_CLASSH_MODE_2, 0xFF, 0x3A);
  276. usleep_range(500, 510);
  277. break;
  278. case SND_SOC_DAPM_POST_PMU:
  279. usleep_range(6000, 6010);
  280. snd_soc_update_bits(codec, WCD937X_ANA_RX_SUPPLIES,
  281. 0x02, 0x02);
  282. break;
  283. case SND_SOC_DAPM_POST_PMD:
  284. usleep_range(7000, 7010);
  285. break;
  286. };
  287. return 0;
  288. }
  289. static int wcd937x_enable_rx1(struct snd_soc_dapm_widget *w,
  290. struct snd_kcontrol *kcontrol,
  291. int event)
  292. {
  293. struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
  294. dev_dbg(codec->dev, "%s wname: %s event: %d\n", __func__,
  295. w->name, event);
  296. switch (event) {
  297. case SND_SOC_DAPM_PRE_PMU:
  298. snd_soc_update_bits(codec, WCD937X_FLYBACK_VNEG_CTRL_4,
  299. 0xF0, 0x80);
  300. snd_soc_update_bits(codec, WCD937X_FLYBACK_VNEGDAC_CTRL_2,
  301. 0xE0, 0xA0);
  302. snd_soc_update_bits(codec, WCD937X_CLASSH_MODE_3,
  303. 0x02, 0x02);
  304. snd_soc_update_bits(codec, WCD937X_CLASSH_MODE_2,
  305. 0xFF, 0x1C);
  306. snd_soc_update_bits(codec, WCD937X_ANA_RX_SUPPLIES,
  307. 0x40, 0x40);
  308. usleep_range(100, 110);
  309. snd_soc_update_bits(codec, WCD937X_FLYBACK_VNEGDAC_CTRL_2,
  310. 0xE0, 0xE0);
  311. usleep_range(100, 110);
  312. snd_soc_update_bits(codec, WCD937X_ANA_RX_SUPPLIES,
  313. 0x80, 0x80);
  314. usleep_range(500, 510);
  315. snd_soc_update_bits(codec, WCD937X_CLASSH_MODE_2, 0xFF, 0x3A);
  316. usleep_range(500, 510);
  317. break;
  318. case SND_SOC_DAPM_POST_PMD:
  319. wcd937x_rx_clk_disable(codec);
  320. snd_soc_update_bits(codec, WCD937X_DIGITAL_CDC_DIG_CLK_CTL,
  321. 0x01, 0x00);
  322. break;
  323. };
  324. return 0;
  325. }
  326. static int wcd937x_enable_rx2(struct snd_soc_dapm_widget *w,
  327. struct snd_kcontrol *kcontrol, int event)
  328. {
  329. struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
  330. dev_dbg(codec->dev, "%s wname: %s event: %d\n", __func__,
  331. w->name, event);
  332. switch (event) {
  333. case SND_SOC_DAPM_PRE_PMU:
  334. snd_soc_update_bits(codec, WCD937X_FLYBACK_VNEG_CTRL_4,
  335. 0xF0, 0x80);
  336. snd_soc_update_bits(codec, WCD937X_FLYBACK_VNEGDAC_CTRL_2,
  337. 0xE0, 0xA0);
  338. snd_soc_update_bits(codec, WCD937X_CLASSH_MODE_3, 0x02, 0x02);
  339. snd_soc_update_bits(codec, WCD937X_CLASSH_MODE_2, 0xFF, 0x1C);
  340. snd_soc_update_bits(codec, WCD937X_ANA_RX_SUPPLIES,
  341. 0x40, 0x40);
  342. usleep_range(100, 110);
  343. snd_soc_update_bits(codec, WCD937X_FLYBACK_VNEGDAC_CTRL_2,
  344. 0xE0, 0xE0);
  345. usleep_range(100, 110);
  346. snd_soc_update_bits(codec, WCD937X_ANA_RX_SUPPLIES,
  347. 0x80, 0x80);
  348. usleep_range(500, 510);
  349. snd_soc_update_bits(codec, WCD937X_CLASSH_MODE_2, 0xFF, 0x3A);
  350. usleep_range(500, 510);
  351. break;
  352. case SND_SOC_DAPM_POST_PMD:
  353. wcd937x_rx_clk_disable(codec);
  354. snd_soc_update_bits(codec, WCD937X_DIGITAL_CDC_DIG_CLK_CTL,
  355. 0x02, 0x00);
  356. break;
  357. };
  358. return 0;
  359. }
  360. static int wcd937x_enable_rx3(struct snd_soc_dapm_widget *w,
  361. struct snd_kcontrol *kcontrol,
  362. int event)
  363. {
  364. struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
  365. dev_dbg(codec->dev, "%s wname: %s event: %d\n", __func__,
  366. w->name, event);
  367. switch (event) {
  368. case SND_SOC_DAPM_PRE_PMU:
  369. snd_soc_update_bits(codec, WCD937X_FLYBACK_VNEG_CTRL_2,
  370. 0xE0, 0xA0);
  371. snd_soc_update_bits(codec, WCD937X_CLASSH_MODE_3, 0x02, 0x02);
  372. snd_soc_update_bits(codec, WCD937X_CLASSH_MODE_2, 0xFF, 0x1C);
  373. snd_soc_update_bits(codec, WCD937X_ANA_RX_SUPPLIES,
  374. 0x40, 0x40);
  375. usleep_range(100, 110);
  376. snd_soc_update_bits(codec, WCD937X_FLYBACK_VNEG_CTRL_2,
  377. 0xE0, 0xE0);
  378. usleep_range(100, 110);
  379. break;
  380. case SND_SOC_DAPM_POST_PMD:
  381. usleep_range(6000, 6010);
  382. wcd937x_rx_clk_disable(codec);
  383. snd_soc_update_bits(codec, WCD937X_DIGITAL_CDC_DIG_CLK_CTL,
  384. 0x04, 0x00);
  385. break;
  386. }
  387. return 0;
  388. }
  389. static int wcd937x_codec_enable_dmic(struct snd_soc_dapm_widget *w,
  390. struct snd_kcontrol *kcontrol,
  391. int event)
  392. {
  393. struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
  394. struct wcd937x_priv *wcd937x = snd_soc_codec_get_drvdata(codec);
  395. u16 dmic_clk_reg;
  396. s32 *dmic_clk_cnt;
  397. unsigned int dmic;
  398. char *wname;
  399. int ret = 0;
  400. wname = strpbrk(w->name, "012345");
  401. if (!wname) {
  402. dev_err(codec->dev, "%s: widget not found\n", __func__);
  403. return -EINVAL;
  404. }
  405. ret = kstrtouint(wname, 10, &dmic);
  406. if (ret < 0) {
  407. dev_err(codec->dev, "%s: Invalid DMIC line on the codec\n",
  408. __func__);
  409. return -EINVAL;
  410. }
  411. dev_dbg(codec->dev, "%s wname: %s event: %d\n", __func__,
  412. w->name, event);
  413. switch (dmic) {
  414. case 0:
  415. case 1:
  416. dmic_clk_cnt = &(wcd937x->dmic_0_1_clk_cnt);
  417. dmic_clk_reg = WCD937X_DIGITAL_CDC_DMIC0_CTL;
  418. break;
  419. case 2:
  420. case 3:
  421. dmic_clk_cnt = &(wcd937x->dmic_2_3_clk_cnt);
  422. dmic_clk_reg = WCD937X_DIGITAL_CDC_DMIC1_CTL;
  423. break;
  424. case 4:
  425. case 5:
  426. dmic_clk_cnt = &(wcd937x->dmic_4_5_clk_cnt);
  427. dmic_clk_reg = WCD937X_DIGITAL_CDC_DMIC2_CTL;
  428. break;
  429. default:
  430. dev_err(codec->dev, "%s: Invalid DMIC Selection\n",
  431. __func__);
  432. return -EINVAL;
  433. };
  434. dev_dbg(codec->dev, "%s: event %d DMIC%d dmic_clk_cnt %d\n",
  435. __func__, event, dmic, *dmic_clk_cnt);
  436. switch (event) {
  437. case SND_SOC_DAPM_PRE_PMU:
  438. snd_soc_update_bits(codec, WCD937X_DIGITAL_CDC_DIG_CLK_CTL,
  439. 0x80, 0x80);
  440. snd_soc_update_bits(codec, dmic_clk_reg, 0x07, 0x02);
  441. snd_soc_update_bits(codec, dmic_clk_reg, 0x08, 0x08);
  442. snd_soc_update_bits(codec, dmic_clk_reg, 0x70, 0x20);
  443. break;
  444. case SND_SOC_DAPM_POST_PMD:
  445. break;
  446. };
  447. return 0;
  448. }
  449. static int wcd937x_codec_enable_adc(struct snd_soc_dapm_widget *w,
  450. struct snd_kcontrol *kcontrol,
  451. int event){
  452. struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
  453. dev_dbg(codec->dev, "%s wname: %s event: %d\n", __func__,
  454. w->name, event);
  455. switch (event) {
  456. case SND_SOC_DAPM_PRE_PMU:
  457. snd_soc_update_bits(codec, WCD937X_DIGITAL_CDC_DIG_CLK_CTL,
  458. 0x80, 0x80);
  459. snd_soc_update_bits(codec, WCD937X_DIGITAL_CDC_ANA_CLK_CTL,
  460. 0x08, 0x08);
  461. snd_soc_update_bits(codec, WCD937X_DIGITAL_CDC_ANA_CLK_CTL,
  462. 0x10, 0x10);
  463. break;
  464. case SND_SOC_DAPM_POST_PMD:
  465. snd_soc_update_bits(codec, WCD937X_DIGITAL_CDC_ANA_CLK_CTL,
  466. 0x08, 0x00);
  467. break;
  468. };
  469. return 0;
  470. }
  471. static int wcd937x_enable_req(struct snd_soc_dapm_widget *w,
  472. struct snd_kcontrol *kcontrol, int event)
  473. {
  474. struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
  475. dev_dbg(codec->dev, "%s wname: %s event: %d\n", __func__,
  476. w->name, event);
  477. switch (event) {
  478. case SND_SOC_DAPM_PRE_PMU:
  479. snd_soc_update_bits(codec, WCD937X_DIGITAL_CDC_REQ_CTL,
  480. 0x02, 0x02);
  481. snd_soc_update_bits(codec, WCD937X_DIGITAL_CDC_REQ_CTL, 0x01,
  482. 0x00);
  483. snd_soc_update_bits(codec, WCD937X_ANA_TX_CH2, 0x40, 0x40);
  484. snd_soc_update_bits(codec, WCD937X_DIGITAL_CDC_DIG_CLK_CTL,
  485. 0x10, 0x10);
  486. snd_soc_update_bits(codec, WCD937X_ANA_TX_CH1, 0x80, 0x80);
  487. snd_soc_update_bits(codec, WCD937X_ANA_TX_CH2, 0x40, 0x00);
  488. break;
  489. case SND_SOC_DAPM_POST_PMD:
  490. snd_soc_update_bits(codec, WCD937X_ANA_TX_CH1, 0x80, 0x00);
  491. snd_soc_update_bits(codec, WCD937X_DIGITAL_CDC_DIG_CLK_CTL,
  492. 0x10, 0x00);
  493. snd_soc_update_bits(codec, WCD937X_DIGITAL_CDC_ANA_CLK_CTL,
  494. 0x10, 0x00);
  495. snd_soc_update_bits(codec, WCD937X_DIGITAL_CDC_DIG_CLK_CTL,
  496. 0x80, 0x00);
  497. break;
  498. };
  499. return 0;
  500. }
  501. static int wcd937x_micbias_control(struct snd_soc_codec *codec,
  502. int micb_num, int req, bool is_dapm)
  503. {
  504. struct wcd937x_priv *wcd937x = snd_soc_codec_get_drvdata(codec);
  505. int micb_index = micb_num - 1;
  506. u16 micb_reg;
  507. int pre_off_event = 0, post_off_event = 0;
  508. int post_on_event = 0, post_dapm_off = 0;
  509. int post_dapm_on = 0;
  510. if ((micb_index < 0) || (micb_index > WCD937X_MAX_MICBIAS - 1)) {
  511. dev_err(codec->dev, "%s: Invalid micbias index, micb_ind:%d\n",
  512. __func__, micb_index);
  513. return -EINVAL;
  514. }
  515. switch (micb_num) {
  516. case MIC_BIAS_1:
  517. micb_reg = WCD937X_ANA_MICB1;
  518. break;
  519. case MIC_BIAS_2:
  520. micb_reg = WCD937X_ANA_MICB2;
  521. pre_off_event = WCD_EVENT_PRE_MICBIAS_2_OFF;
  522. post_off_event = WCD_EVENT_POST_MICBIAS_2_OFF;
  523. post_on_event = WCD_EVENT_POST_MICBIAS_2_ON;
  524. post_dapm_on = WCD_EVENT_POST_DAPM_MICBIAS_2_ON;
  525. post_dapm_off = WCD_EVENT_POST_DAPM_MICBIAS_2_OFF;
  526. break;
  527. case MIC_BIAS_3:
  528. micb_reg = WCD937X_ANA_MICB3;
  529. break;
  530. default:
  531. dev_err(codec->dev, "%s: Invalid micbias number: %d\n",
  532. __func__, micb_num);
  533. return -EINVAL;
  534. };
  535. mutex_lock(&wcd937x->micb_lock);
  536. switch (req) {
  537. case MICB_PULLUP_ENABLE:
  538. wcd937x->pullup_ref[micb_index]++;
  539. if ((wcd937x->pullup_ref[micb_index] == 1) &&
  540. (wcd937x->micb_ref[micb_index] == 0))
  541. snd_soc_update_bits(codec, micb_reg, 0xC0, 0x80);
  542. break;
  543. case MICB_PULLUP_DISABLE:
  544. if (wcd937x->pullup_ref[micb_index] > 0)
  545. wcd937x->pullup_ref[micb_index]--;
  546. if ((wcd937x->pullup_ref[micb_index] == 0) &&
  547. (wcd937x->micb_ref[micb_index] == 0))
  548. snd_soc_update_bits(codec, micb_reg, 0xC0, 0x00);
  549. break;
  550. case MICB_ENABLE:
  551. wcd937x->micb_ref[micb_index]++;
  552. if (wcd937x->micb_ref[micb_index] == 1) {
  553. snd_soc_update_bits(codec, micb_reg, 0xC0, 0x40);
  554. if (post_on_event)
  555. blocking_notifier_call_chain(&wcd937x->notifier,
  556. post_on_event,
  557. &wcd937x->mbhc);
  558. }
  559. if (is_dapm && post_dapm_on)
  560. blocking_notifier_call_chain(&wcd937x->notifier,
  561. post_dapm_on,
  562. &wcd937x->mbhc);
  563. break;
  564. case MICB_DISABLE:
  565. if (wcd937x->micb_ref[micb_index] > 0)
  566. wcd937x->micb_ref[micb_index]--;
  567. if ((wcd937x->micb_ref[micb_index] == 0) &&
  568. (wcd937x->pullup_ref[micb_index] > 0))
  569. snd_soc_update_bits(codec, micb_reg, 0xC0, 0x80);
  570. else if ((wcd937x->micb_ref[micb_index] == 0) &&
  571. (wcd937x->pullup_ref[micb_index] == 0)) {
  572. if (pre_off_event)
  573. blocking_notifier_call_chain(&wcd937x->notifier,
  574. pre_off_event,
  575. &wcd937x->mbhc);
  576. snd_soc_update_bits(codec, micb_reg, 0xC0, 0x00);
  577. if (post_off_event)
  578. blocking_notifier_call_chain(&wcd937x->notifier,
  579. post_off_event,
  580. &wcd937x->mbhc);
  581. }
  582. if (is_dapm && post_dapm_off)
  583. blocking_notifier_call_chain(&wcd937x->notifier,
  584. post_dapm_off,
  585. &wcd937x->mbhc);
  586. break;
  587. };
  588. dev_dbg(codec->dev, "%s: micb_num:%d, micb_ref: %d, pullup_ref: %d\n",
  589. __func__, micb_num, wcd937x->micb_ref[micb_index],
  590. wcd937x->pullup_ref[micb_index]);
  591. mutex_unlock(&wcd937x->micb_lock);
  592. return 0;
  593. }
  594. static int __wcd937x_codec_enable_micbias(struct snd_soc_dapm_widget *w,
  595. int event)
  596. {
  597. struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
  598. int micb_num;
  599. dev_dbg(codec->dev, "%s: wname: %s, event: %d\n",
  600. __func__, w->name, event);
  601. if (strnstr(w->name, "MIC BIAS1", sizeof("MIC BIAS1")))
  602. micb_num = MIC_BIAS_1;
  603. else if (strnstr(w->name, "MIC BIAS2", sizeof("MIC BIAS2")))
  604. micb_num = MIC_BIAS_2;
  605. else if (strnstr(w->name, "MIC BIAS3", sizeof("MIC BIAS3")))
  606. micb_num = MIC_BIAS_3;
  607. else
  608. return -EINVAL;
  609. switch (event) {
  610. case SND_SOC_DAPM_PRE_PMU:
  611. wcd937x_micbias_control(codec, micb_num, MICB_ENABLE, true);
  612. break;
  613. case SND_SOC_DAPM_POST_PMU:
  614. usleep_range(1000, 1100);
  615. break;
  616. case SND_SOC_DAPM_POST_PMD:
  617. wcd937x_micbias_control(codec, micb_num, MICB_DISABLE, true);
  618. break;
  619. };
  620. return 0;
  621. }
  622. static int wcd937x_codec_enable_micbias(struct snd_soc_dapm_widget *w,
  623. struct snd_kcontrol *kcontrol,
  624. int event)
  625. {
  626. return __wcd937x_codec_enable_micbias(w, event);
  627. }
  628. static int wcd937x_rx_hph_mode_get(struct snd_kcontrol *kcontrol,
  629. struct snd_ctl_elem_value *ucontrol)
  630. {
  631. struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
  632. struct wcd937x_priv *wcd937x = snd_soc_codec_get_drvdata(codec);
  633. ucontrol->value.integer.value[0] = wcd937x->hph_mode;
  634. return 0;
  635. }
  636. static int wcd937x_rx_hph_mode_put(struct snd_kcontrol *kcontrol,
  637. struct snd_ctl_elem_value *ucontrol)
  638. {
  639. struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
  640. struct wcd937x_priv *wcd937x = snd_soc_codec_get_drvdata(codec);
  641. u32 mode_val;
  642. mode_val = ucontrol->value.enumerated.item[0];
  643. dev_dbg(codec->dev, "%s: mode: %d\n", __func__, mode_val);
  644. if (mode_val == 0) {
  645. dev_warn(codec->dev, "%s:Invalid HPH Mode, default to class_AB\n",
  646. __func__);
  647. mode_val = 3; /* enum will be updated later */
  648. }
  649. wcd937x->hph_mode = mode_val;
  650. return 0;
  651. }
  652. static const char * const rx_hph_mode_mux_text[] = {
  653. "CLS_H_INVALID", "CLS_H_HIFI", "CLS_H_LP", "CLS_AB", "CLS_H_LOHIFI",
  654. "CLS_H_ULP", "CLS_AB_HIFI",
  655. };
  656. static const struct soc_enum rx_hph_mode_mux_enum =
  657. SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(rx_hph_mode_mux_text),
  658. rx_hph_mode_mux_text);
  659. static const struct snd_kcontrol_new wcd937x_snd_controls[] = {
  660. SOC_ENUM_EXT("RX HPH Mode", rx_hph_mode_mux_enum,
  661. wcd937x_rx_hph_mode_get, wcd937x_rx_hph_mode_put),
  662. SOC_SINGLE_TLV("HPHL Volume", WCD937X_HPH_L_EN, 0, 20, 1, line_gain),
  663. SOC_SINGLE_TLV("HPHR Volume", WCD937X_HPH_R_EN, 0, 20, 1, line_gain),
  664. SOC_SINGLE_TLV("ADC1 Volume", WCD937X_ANA_TX_CH1, 0, 20, 0, analog_gain),
  665. SOC_SINGLE_TLV("ADC2 Volume", WCD937X_ANA_TX_CH2, 0, 20, 0, analog_gain),
  666. SOC_SINGLE_TLV("ADC3 Volume", WCD937X_ANA_TX_CH3, 0, 20, 0, analog_gain),
  667. };
  668. static const struct snd_kcontrol_new adc1_switch[] = {
  669. SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0)
  670. };
  671. static const struct snd_kcontrol_new adc2_switch[] = {
  672. SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0)
  673. };
  674. static const struct snd_kcontrol_new adc3_switch[] = {
  675. SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0)
  676. };
  677. static const struct snd_kcontrol_new dmic1_switch[] = {
  678. SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0)
  679. };
  680. static const struct snd_kcontrol_new dmic2_switch[] = {
  681. SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0)
  682. };
  683. static const struct snd_kcontrol_new dmic3_switch[] = {
  684. SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0)
  685. };
  686. static const struct snd_kcontrol_new dmic4_switch[] = {
  687. SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0)
  688. };
  689. static const struct snd_kcontrol_new dmic5_switch[] = {
  690. SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0)
  691. };
  692. static const struct snd_kcontrol_new dmic6_switch[] = {
  693. SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0)
  694. };
  695. static const struct snd_kcontrol_new ear_rdac_switch[] = {
  696. SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0)
  697. };
  698. static const struct snd_kcontrol_new aux_rdac_switch[] = {
  699. SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0)
  700. };
  701. static const struct snd_kcontrol_new hphl_rdac_switch[] = {
  702. SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0)
  703. };
  704. static const struct snd_kcontrol_new hphr_rdac_switch[] = {
  705. SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0)
  706. };
  707. static const char * const adc2_mux_text[] = {
  708. "INP2", "INP3"
  709. };
  710. static const char * const rdac3_mux_text[] = {
  711. "RX1", "RX3"
  712. };
  713. static const struct soc_enum adc2_enum =
  714. SOC_ENUM_SINGLE(WCD937X_TX_NEW_TX_CH2_SEL, 7,
  715. ARRAY_SIZE(adc2_mux_text), adc2_mux_text);
  716. static const struct soc_enum rdac3_enum =
  717. SOC_ENUM_SINGLE(WCD937X_DIGITAL_CDC_EAR_PATH_CTL, 0,
  718. ARRAY_SIZE(rdac3_mux_text), rdac3_mux_text);
  719. static const struct snd_kcontrol_new tx_adc2_mux =
  720. SOC_DAPM_ENUM("ADC2 MUX Mux", adc2_enum);
  721. static const struct snd_kcontrol_new rx_rdac3_mux =
  722. SOC_DAPM_ENUM("RDAC3_MUX Mux", rdac3_enum);
  723. static const struct snd_soc_dapm_widget wcd937x_dapm_widgets[] = {
  724. /*input widgets*/
  725. SND_SOC_DAPM_INPUT("AMIC1"),
  726. SND_SOC_DAPM_INPUT("AMIC2"),
  727. SND_SOC_DAPM_INPUT("AMIC3"),
  728. SND_SOC_DAPM_INPUT("IN1_HPHL"),
  729. SND_SOC_DAPM_INPUT("IN2_HPHR"),
  730. SND_SOC_DAPM_INPUT("IN3_AUX"),
  731. /*tx widgets*/
  732. SND_SOC_DAPM_ADC_E("ADC1", NULL, SND_SOC_NOPM, 0, 0,
  733. wcd937x_codec_enable_adc,
  734. SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
  735. SND_SOC_DAPM_ADC_E("ADC2", NULL, SND_SOC_NOPM, 0, 0,
  736. wcd937x_codec_enable_adc,
  737. SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
  738. SND_SOC_DAPM_MIXER_E("ADC1 REQ", SND_SOC_NOPM, 0, 0,
  739. NULL, 0, wcd937x_enable_req,
  740. SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
  741. SND_SOC_DAPM_MIXER_E("ADC2 REQ", SND_SOC_NOPM, 0, 0,
  742. NULL, 0, wcd937x_enable_req,
  743. SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
  744. SND_SOC_DAPM_MUX("ADC2 MUX", SND_SOC_NOPM, 0, 0,
  745. &tx_adc2_mux),
  746. /*tx mixers*/
  747. SND_SOC_DAPM_MIXER("ADC1_MIXER", SND_SOC_NOPM, 0,
  748. 0, adc1_switch, ARRAY_SIZE(adc1_switch)),
  749. SND_SOC_DAPM_MIXER("ADC2_MIXER", SND_SOC_NOPM, 0,
  750. 0, adc2_switch, ARRAY_SIZE(adc2_switch)),
  751. /* micbias widgets*/
  752. SND_SOC_DAPM_MICBIAS_E("MIC BIAS1", SND_SOC_NOPM, 0, 0,
  753. wcd937x_codec_enable_micbias,
  754. SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
  755. SND_SOC_DAPM_POST_PMD),
  756. SND_SOC_DAPM_MICBIAS_E("MIC BIAS2", SND_SOC_NOPM, 0, 0,
  757. wcd937x_codec_enable_micbias,
  758. SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
  759. SND_SOC_DAPM_POST_PMD),
  760. SND_SOC_DAPM_MICBIAS_E("MIC BIAS3", SND_SOC_NOPM, 0, 0,
  761. wcd937x_codec_enable_micbias,
  762. SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
  763. SND_SOC_DAPM_POST_PMD),
  764. /*rx widgets*/
  765. SND_SOC_DAPM_PGA_E("EAR PGA", WCD937X_ANA_EAR, 7, 0, NULL, 0,
  766. wcd937x_codec_enable_ear_pa,
  767. SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
  768. SND_SOC_DAPM_POST_PMD),
  769. SND_SOC_DAPM_PGA_E("AUX PGA", WCD937X_AUX_AUXPA, 7, 0, NULL, 0,
  770. wcd937x_codec_enable_aux_pa,
  771. SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
  772. SND_SOC_DAPM_POST_PMD),
  773. SND_SOC_DAPM_PGA_E("HPHL PGA", WCD937X_ANA_HPH, 7, 0, NULL, 0,
  774. wcd937x_codec_enable_hphl_pa,
  775. SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
  776. SND_SOC_DAPM_POST_PMD),
  777. SND_SOC_DAPM_PGA_E("HPHR PGA", WCD937X_ANA_HPH, 6, 0, NULL, 0,
  778. wcd937x_codec_enable_hphr_pa,
  779. SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
  780. SND_SOC_DAPM_POST_PMD),
  781. SND_SOC_DAPM_DAC_E("RDAC1", NULL, SND_SOC_NOPM, 0, 0,
  782. wcd937x_codec_hphl_dac_event,
  783. SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
  784. SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
  785. SND_SOC_DAPM_DAC_E("RDAC2", NULL, SND_SOC_NOPM, 0, 0,
  786. wcd937x_codec_hphr_dac_event,
  787. SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
  788. SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
  789. SND_SOC_DAPM_DAC_E("RDAC3", NULL, SND_SOC_NOPM, 0, 0,
  790. wcd937x_codec_ear_dac_event,
  791. SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
  792. SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
  793. SND_SOC_DAPM_DAC_E("RDAC4", NULL, SND_SOC_NOPM, 0, 0,
  794. wcd937x_codec_aux_dac_event,
  795. SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
  796. SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
  797. SND_SOC_DAPM_MUX("RDAC3_MUX", SND_SOC_NOPM, 0, 0, &rx_rdac3_mux),
  798. SND_SOC_DAPM_MIXER_E("RX1", SND_SOC_NOPM, 0, 0, NULL, 0,
  799. wcd937x_enable_rx1, SND_SOC_DAPM_PRE_PMU |
  800. SND_SOC_DAPM_POST_PMD),
  801. SND_SOC_DAPM_MIXER_E("RX2", SND_SOC_NOPM, 0, 0, NULL, 0,
  802. wcd937x_enable_rx2, SND_SOC_DAPM_PRE_PMU |
  803. SND_SOC_DAPM_POST_PMD),
  804. SND_SOC_DAPM_MIXER_E("RX3", SND_SOC_NOPM, 0, 0, NULL, 0,
  805. wcd937x_enable_rx3, SND_SOC_DAPM_PRE_PMU |
  806. SND_SOC_DAPM_POST_PMD),
  807. /* rx mixer widgets*/
  808. SND_SOC_DAPM_MIXER("EAR_RDAC", SND_SOC_NOPM, 0, 0,
  809. ear_rdac_switch, ARRAY_SIZE(ear_rdac_switch)),
  810. SND_SOC_DAPM_MIXER("AUX_RDAC", SND_SOC_NOPM, 0, 0,
  811. aux_rdac_switch, ARRAY_SIZE(aux_rdac_switch)),
  812. SND_SOC_DAPM_MIXER("HPHL_RDAC", SND_SOC_NOPM, 0, 0,
  813. hphl_rdac_switch, ARRAY_SIZE(hphl_rdac_switch)),
  814. SND_SOC_DAPM_MIXER("HPHR_RDAC", SND_SOC_NOPM, 0, 0,
  815. hphr_rdac_switch, ARRAY_SIZE(hphr_rdac_switch)),
  816. /*output widgets tx*/
  817. SND_SOC_DAPM_OUTPUT("ADC1_OUTPUT"),
  818. SND_SOC_DAPM_OUTPUT("ADC2_OUTPUT"),
  819. /*output widgets rx*/
  820. SND_SOC_DAPM_OUTPUT("EAR"),
  821. SND_SOC_DAPM_OUTPUT("AUX"),
  822. SND_SOC_DAPM_OUTPUT("HPHL"),
  823. SND_SOC_DAPM_OUTPUT("HPHR"),
  824. };
  825. static const struct snd_soc_dapm_widget wcd9375_dapm_widgets[] = {
  826. /*input widgets*/
  827. SND_SOC_DAPM_INPUT("AMIC4"),
  828. /*tx widgets*/
  829. SND_SOC_DAPM_ADC_E("ADC3", NULL, SND_SOC_NOPM, 0, 0,
  830. wcd937x_codec_enable_adc,
  831. SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
  832. SND_SOC_DAPM_MIXER_E("ADC3 REQ", SND_SOC_NOPM, 0, 0,
  833. NULL, 0, wcd937x_enable_req,
  834. SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
  835. SND_SOC_DAPM_ADC_E("DMIC1", NULL, SND_SOC_NOPM, 0, 0,
  836. wcd937x_codec_enable_dmic,
  837. SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
  838. SND_SOC_DAPM_ADC_E("DMIC2", NULL, SND_SOC_NOPM, 0, 0,
  839. wcd937x_codec_enable_dmic,
  840. SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
  841. SND_SOC_DAPM_ADC_E("DMIC3", NULL, SND_SOC_NOPM, 0, 0,
  842. wcd937x_codec_enable_dmic,
  843. SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
  844. SND_SOC_DAPM_ADC_E("DMIC4", NULL, SND_SOC_NOPM, 0, 0,
  845. wcd937x_codec_enable_dmic,
  846. SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
  847. SND_SOC_DAPM_ADC_E("DMIC5", NULL, SND_SOC_NOPM, 0, 0,
  848. wcd937x_codec_enable_dmic,
  849. SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
  850. SND_SOC_DAPM_ADC_E("DMIC6", NULL, SND_SOC_NOPM, 0, 0,
  851. wcd937x_codec_enable_dmic,
  852. SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
  853. /*tx mixer widgets*/
  854. SND_SOC_DAPM_MIXER("DMIC1_MIXER", SND_SOC_NOPM, 0,
  855. 0, dmic1_switch, ARRAY_SIZE(dmic1_switch)),
  856. SND_SOC_DAPM_MIXER("DMIC2_MIXER", SND_SOC_NOPM, 0,
  857. 0, dmic2_switch, ARRAY_SIZE(dmic2_switch)),
  858. SND_SOC_DAPM_MIXER("DMIC3_MIXER", SND_SOC_NOPM, 0,
  859. 0, dmic3_switch, ARRAY_SIZE(dmic3_switch)),
  860. SND_SOC_DAPM_MIXER("DMIC4_MIXER", SND_SOC_NOPM, 0,
  861. 0, dmic4_switch, ARRAY_SIZE(dmic4_switch)),
  862. SND_SOC_DAPM_MIXER("DMIC5_MIXER", SND_SOC_NOPM, 0,
  863. 0, dmic5_switch, ARRAY_SIZE(dmic5_switch)),
  864. SND_SOC_DAPM_MIXER("DMIC6_MIXER", SND_SOC_NOPM, 0,
  865. 0, dmic6_switch, ARRAY_SIZE(dmic6_switch)),
  866. SND_SOC_DAPM_MIXER("ADC3_MIXER", SND_SOC_NOPM, 0,
  867. 0, adc3_switch, ARRAY_SIZE(adc3_switch)),
  868. /*output widgets*/
  869. SND_SOC_DAPM_OUTPUT("DMIC1_OUTPUT"),
  870. SND_SOC_DAPM_OUTPUT("DMIC2_OUTPUT"),
  871. SND_SOC_DAPM_OUTPUT("DMIC3_OUTPUT"),
  872. SND_SOC_DAPM_OUTPUT("DMIC4_OUTPUT"),
  873. SND_SOC_DAPM_OUTPUT("DMIC5_OUTPUT"),
  874. SND_SOC_DAPM_OUTPUT("DMIC6_OUTPUT"),
  875. SND_SOC_DAPM_OUTPUT("ADC3_OUTPUT"),
  876. };
  877. static const struct snd_soc_dapm_route wcd937x_audio_map[] = {
  878. {"ADC2_OUTPUT", NULL, "ADC2_MIXER"},
  879. {"ADC2_MIXER", "Switch", "ADC2 REQ"},
  880. {"ADC2 REQ", "NULL", "ADC2"},
  881. {"ADC2", "NULL", "ADC2 MUX"},
  882. {"ADC2 MUX", "INP3", "AMIC3"},
  883. {"ADC2 MUX", "INP2", "AMIC2"},
  884. {"ADC1_OUTPUT", NULL, "ADC1_MIXER"},
  885. {"ADC1_MIXER", "Switch", "ADC1 REQ"},
  886. {"ADC1 REQ", NULL, "ADC1"},
  887. {"ADC1", NULL, "AMIC1"},
  888. {"RX1", NULL, "IN1_HPHL"},
  889. {"RDAC1", NULL, "RX1"},
  890. {"HPHL_RDAC", "Switch", "RDAC1"},
  891. {"HPHL PGA", NULL, "HPHL_RDAC"},
  892. {"HPHL", NULL, "HPHL PGA"},
  893. {"RX2", NULL, "IN2_HPHR"},
  894. {"RDAC2", NULL, "RX2"},
  895. {"HPHR_RDAC", "Switch", "RDAC2"},
  896. {"HPHR PGA", NULL, "HPHR_RDAC"},
  897. {"HPHR", NULL, "HPHR PGA"},
  898. {"RX3", NULL, "IN3_AUX"},
  899. {"RDAC4", NULL, "RX3"},
  900. {"AUX_RDAC", "Switch", "RDAC4"},
  901. {"AUX PGA", NULL, "AUX_RDAC"},
  902. {"AUX", NULL, "AUX PGA"},
  903. {"RDAC3_MUX", "RX3", "RX3"},
  904. {"RDAC3_MUX", "RX1", "RX1"},
  905. {"RDAC3", NULL, "RDAC3_MUX"},
  906. {"EAR_RDAC", "Switch", "RDAC3"},
  907. {"EAR PGA", NULL, "EAR_RDAC"},
  908. {"EAR", NULL, "EAR PGA"},
  909. };
  910. static const struct snd_soc_dapm_route wcd9375_audio_map[] = {
  911. {"ADC3_OUTPUT", NULL, "ADC3_MIXER"},
  912. {"ADC3_MIXER", "Switch", "ADC3 REQ"},
  913. {"ADC3 REQ", NULL, "ADC3"},
  914. {"ADC3", NULL, "AMIC4"},
  915. {"DMIC1_OUTPUT", NULL, "DMIC1_MIXER"},
  916. {"DMIC1_MIXER", "Switch", "DMIC1"},
  917. {"DMIC2_OUTPUT", NULL, "DMIC2_MIXER"},
  918. {"DMIC2_MIXER", "Switch", "DMIC2"},
  919. {"DMIC3_OUTPUT", NULL, "DMIC3_MIXER"},
  920. {"DMIC3_MIXER", "Switch", "DMIC3"},
  921. {"DMIC4_OUTPUT", NULL, "DMIC4_MIXER"},
  922. {"DMIC4_MIXER", "Switch", "DMIC4"},
  923. {"DMIC5_OUTPUT", NULL, "DMIC5_MIXER"},
  924. {"DMIC5_MIXER", "Switch", "DMIC5"},
  925. {"DMIC6_OUTPUT", NULL, "DMIC6_MIXER"},
  926. {"DMIC6_MIXER", "Switch", "DMIC6"},
  927. };
  928. static int wcd937x_soc_codec_probe(struct snd_soc_codec *codec)
  929. {
  930. struct wcd937x_priv *wcd937x = snd_soc_codec_get_drvdata(codec);
  931. struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
  932. int variant;
  933. int ret = -EINVAL;
  934. dev_info(codec->dev, "%s()\n", __func__);
  935. wcd937x = snd_soc_codec_get_drvdata(codec);
  936. if (!wcd937x)
  937. return -EINVAL;
  938. wcd937x->codec = codec;
  939. variant = (snd_soc_read(codec, WCD937X_DIGITAL_EFUSE_REG_0) & 0x0E) >> 1;
  940. wcd937x->variant = variant;
  941. wcd937x->fw_data = devm_kzalloc(codec->dev,
  942. sizeof(*(wcd937x->fw_data)),
  943. GFP_KERNEL);
  944. if (!wcd937x->fw_data) {
  945. dev_err(codec->dev, "Failed to allocate fw_data\n");
  946. ret = -ENOMEM;
  947. goto err;
  948. }
  949. set_bit(WCD9XXX_MBHC_CAL, wcd937x->fw_data->cal_bit);
  950. ret = wcd_cal_create_hwdep(wcd937x->fw_data,
  951. WCD9XXX_CODEC_HWDEP_NODE, codec);
  952. if (ret < 0) {
  953. dev_err(codec->dev, "%s hwdep failed %d\n", __func__, ret);
  954. goto err_hwdep;
  955. }
  956. wcd937x_init_reg(codec);
  957. if (wcd937x->variant == WCD9375_VARIANT) {
  958. ret = snd_soc_dapm_new_controls(dapm, wcd9375_dapm_widgets,
  959. ARRAY_SIZE(wcd9375_dapm_widgets));
  960. if (ret < 0) {
  961. dev_err(codec->dev, "%s: Failed to add snd_ctls\n",
  962. __func__);
  963. goto err_hwdep;
  964. }
  965. ret = snd_soc_dapm_add_routes(dapm, wcd9375_audio_map,
  966. ARRAY_SIZE(wcd9375_audio_map));
  967. if (ret < 0) {
  968. dev_err(codec->dev, "%s: Failed to add routes\n",
  969. __func__);
  970. goto err_hwdep;
  971. }
  972. ret = snd_soc_dapm_new_widgets(dapm->card);
  973. if (ret < 0) {
  974. dev_err(codec->dev, "%s: Failed to add widgets\n",
  975. __func__);
  976. goto err_hwdep;
  977. }
  978. }
  979. return ret;
  980. err_hwdep:
  981. wcd937x->fw_data = NULL;
  982. err:
  983. return ret;
  984. }
  985. static int wcd937x_soc_codec_remove(struct snd_soc_codec *codec)
  986. {
  987. struct wcd937x_priv *wcd937x = snd_soc_codec_get_drvdata(codec);
  988. if (!wcd937x)
  989. return -EINVAL;
  990. return 0;
  991. }
  992. static struct regmap *wcd937x_get_regmap(struct device *dev)
  993. {
  994. struct wcd937x_priv *wcd937x = dev_get_drvdata(dev);
  995. return wcd937x->regmap;
  996. }
  997. static struct snd_soc_codec_driver soc_codec_dev_wcd937x = {
  998. .probe = wcd937x_soc_codec_probe,
  999. .remove = wcd937x_soc_codec_remove,
  1000. .get_regmap = wcd937x_get_regmap,
  1001. .component_driver = {
  1002. .controls = wcd937x_snd_controls,
  1003. .num_controls = ARRAY_SIZE(wcd937x_snd_controls),
  1004. .dapm_widgets = wcd937x_dapm_widgets,
  1005. .num_dapm_widgets = ARRAY_SIZE(wcd937x_dapm_widgets),
  1006. .dapm_routes = wcd937x_audio_map,
  1007. .num_dapm_routes = ARRAY_SIZE(wcd937x_audio_map),
  1008. },
  1009. };
  1010. int wcd937x_reset(struct device *dev)
  1011. {
  1012. struct wcd937x_priv *wcd937x = NULL;
  1013. int rc = 0;
  1014. int value = 0;
  1015. if (!dev)
  1016. return -ENODEV;
  1017. wcd937x = dev_get_drvdata(dev);
  1018. if (!wcd937x)
  1019. return -EINVAL;
  1020. if (!wcd937x->rst_np) {
  1021. dev_err(dev, "%s: reset gpio device node not specified\n",
  1022. __func__);
  1023. return -EINVAL;
  1024. }
  1025. value = msm_cdc_pinctrl_get_state(wcd937x->rst_np);
  1026. if (value > 0)
  1027. return 0;
  1028. rc = msm_cdc_pinctrl_select_sleep_state(wcd937x->rst_np);
  1029. if (rc) {
  1030. dev_err(dev, "%s: wcd sleep state request fail!\n",
  1031. __func__);
  1032. return rc;
  1033. }
  1034. /* 20ms sleep required after pulling the reset gpio to LOW */
  1035. usleep_range(20, 30);
  1036. rc = msm_cdc_pinctrl_select_active_state(wcd937x->rst_np);
  1037. if (rc) {
  1038. dev_err(dev, "%s: wcd active state request fail!\n",
  1039. __func__);
  1040. return rc;
  1041. }
  1042. /* 20ms sleep required after pulling the reset gpio to HIGH */
  1043. usleep_range(20, 30);
  1044. return rc;
  1045. }
  1046. struct wcd937x_pdata *wcd937x_populate_dt_data(struct device *dev)
  1047. {
  1048. struct wcd937x_pdata *pdata = NULL;
  1049. pdata = devm_kzalloc(dev, sizeof(struct wcd937x_pdata),
  1050. GFP_KERNEL);
  1051. if (!pdata)
  1052. return NULL;
  1053. pdata->rst_np = of_parse_phandle(dev->of_node,
  1054. "qcom,wcd937x-reset-node", 0);
  1055. if (!pdata->rst_np) {
  1056. dev_err(dev, "%s: Looking up %s property in node %s failed\n",
  1057. __func__, "qcom,wcd937x-reset-node",
  1058. dev->of_node->full_name);
  1059. return NULL;
  1060. }
  1061. pdata->rx_slave = of_parse_phandle(dev->of_node, "qcom,rx-slave", 0);
  1062. pdata->tx_slave = of_parse_phandle(dev->of_node, "qcom,tx-slave", 0);
  1063. return pdata;
  1064. }
  1065. static int wcd937x_bind(struct device *dev)
  1066. {
  1067. int ret = 0;
  1068. struct wcd937x_priv *wcd937x = NULL;
  1069. struct wcd937x_pdata *pdata = NULL;
  1070. wcd937x = devm_kzalloc(dev, sizeof(struct wcd937x_priv), GFP_KERNEL);
  1071. if (!wcd937x)
  1072. return -ENOMEM;
  1073. dev_set_drvdata(dev, wcd937x);
  1074. pdata = wcd937x_populate_dt_data(dev);
  1075. if (!pdata) {
  1076. dev_err(dev, "%s: Fail to obtain platform data\n", __func__);
  1077. return -EINVAL;
  1078. }
  1079. wcd937x->rst_np = pdata->rst_np;
  1080. wcd937x_reset(dev);
  1081. /*
  1082. * Add 5msec delay to provide sufficient time for
  1083. * soundwire auto enumeration of slave devices as
  1084. * as per HW requirement.
  1085. */
  1086. usleep_range(5000, 5010);
  1087. ret = component_bind_all(dev, wcd937x);
  1088. if (ret) {
  1089. dev_err(dev, "%s: Slave bind failed, ret = %d\n",
  1090. __func__, ret);
  1091. return ret;
  1092. }
  1093. wcd937x->rx_swr_dev = get_matching_swr_slave_device(pdata->rx_slave);
  1094. if (!wcd937x->rx_swr_dev) {
  1095. dev_err(dev, "%s: Could not find RX swr slave device\n",
  1096. __func__);
  1097. ret = -ENODEV;
  1098. goto err;
  1099. }
  1100. wcd937x->tx_swr_dev = get_matching_swr_slave_device(pdata->tx_slave);
  1101. if (!wcd937x->tx_swr_dev) {
  1102. dev_err(dev, "%s: Could not find TX swr slave device\n",
  1103. __func__);
  1104. ret = -ENODEV;
  1105. goto err;
  1106. }
  1107. wcd937x->regmap = devm_regmap_init_swr(wcd937x->tx_swr_dev,
  1108. &wcd937x_regmap_config);
  1109. if (!wcd937x->regmap) {
  1110. dev_err(dev, "%s: Regmap init failed\n",
  1111. __func__);
  1112. goto err;
  1113. }
  1114. ret = snd_soc_register_codec(dev, &soc_codec_dev_wcd937x,
  1115. NULL, 0);
  1116. if (ret) {
  1117. dev_err(dev, "%s: Codec registration failed\n",
  1118. __func__);
  1119. goto err;
  1120. }
  1121. return ret;
  1122. err:
  1123. component_unbind_all(dev, wcd937x);
  1124. return ret;
  1125. }
  1126. static void wcd937x_unbind(struct device *dev)
  1127. {
  1128. struct wcd937x_priv *wcd937x = dev_get_drvdata(dev);
  1129. snd_soc_unregister_codec(dev);
  1130. component_unbind_all(dev, wcd937x);
  1131. }
  1132. static const struct of_device_id wcd937x_dt_match[] = {
  1133. { .compatible = "qcom,wcd937x-codec" },
  1134. {}
  1135. };
  1136. static const struct component_master_ops wcd937x_comp_ops = {
  1137. .bind = wcd937x_bind,
  1138. .unbind = wcd937x_unbind,
  1139. };
  1140. static int wcd937x_compare_of(struct device *dev, void *data)
  1141. {
  1142. return dev->of_node == data;
  1143. }
  1144. static void wcd937x_release_of(struct device *dev, void *data)
  1145. {
  1146. of_node_put(data);
  1147. }
  1148. static int wcd937x_add_slave_components(struct device *dev,
  1149. struct component_match **matchptr)
  1150. {
  1151. struct device_node *np, *rx_node, *tx_node;
  1152. np = dev->of_node;
  1153. rx_node = of_parse_phandle(np, "qcom,rx-slave", 0);
  1154. if (!rx_node) {
  1155. dev_err(dev, "%s: Rx-slave node not defined\n", __func__);
  1156. return -ENODEV;
  1157. }
  1158. of_node_get(rx_node);
  1159. component_match_add_release(dev, matchptr,
  1160. wcd937x_release_of,
  1161. wcd937x_compare_of,
  1162. rx_node);
  1163. tx_node = of_parse_phandle(np, "qcom,tx-slave", 0);
  1164. if (!tx_node) {
  1165. dev_err(dev, "%s: Tx-slave node not defined\n", __func__);
  1166. return -ENODEV;
  1167. }
  1168. of_node_get(tx_node);
  1169. component_match_add_release(dev, matchptr,
  1170. wcd937x_release_of,
  1171. wcd937x_compare_of,
  1172. tx_node);
  1173. return 0;
  1174. }
  1175. static int wcd937x_probe(struct platform_device *pdev)
  1176. {
  1177. struct component_match *match = NULL;
  1178. int ret;
  1179. ret = wcd937x_add_slave_components(&pdev->dev, &match);
  1180. if (ret)
  1181. return ret;
  1182. return component_master_add_with_match(&pdev->dev,
  1183. &wcd937x_comp_ops, match);
  1184. }
  1185. static int wcd937x_remove(struct platform_device *pdev)
  1186. {
  1187. component_master_del(&pdev->dev, &wcd937x_comp_ops);
  1188. return 0;
  1189. }
  1190. static struct platform_driver wcd937x_codec_driver = {
  1191. .probe = wcd937x_probe,
  1192. .remove = wcd937x_remove,
  1193. .driver = {
  1194. .name = "wcd937x_codec",
  1195. .owner = THIS_MODULE,
  1196. .of_match_table = of_match_ptr(wcd937x_dt_match),
  1197. },
  1198. };
  1199. module_platform_driver(wcd937x_codec_driver);
  1200. MODULE_DESCRIPTION("WCD937X Codec driver");
  1201. MODULE_LICENSE("GPL v2");