cs35l41.c 41 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469
  1. // SPDX-License-Identifier: GPL-2.0
  2. //
  3. // cs35l41.c -- CS35l41 ALSA SoC audio driver
  4. //
  5. // Copyright 2017-2021 Cirrus Logic, Inc.
  6. //
  7. // Author: David Rhodes <[email protected]>
  8. #include <linux/acpi.h>
  9. #include <linux/delay.h>
  10. #include <linux/err.h>
  11. #include <linux/init.h>
  12. #include <linux/kernel.h>
  13. #include <linux/module.h>
  14. #include <linux/moduleparam.h>
  15. #include <linux/of_device.h>
  16. #include <linux/pm_runtime.h>
  17. #include <linux/property.h>
  18. #include <sound/initval.h>
  19. #include <sound/pcm.h>
  20. #include <sound/pcm_params.h>
  21. #include <sound/soc.h>
  22. #include <sound/soc-dapm.h>
  23. #include <sound/tlv.h>
  24. #include "cs35l41.h"
  25. static const char * const cs35l41_supplies[CS35L41_NUM_SUPPLIES] = {
  26. "VA",
  27. "VP",
  28. };
  29. struct cs35l41_pll_sysclk_config {
  30. int freq;
  31. int clk_cfg;
  32. };
  33. static const struct cs35l41_pll_sysclk_config cs35l41_pll_sysclk[] = {
  34. { 32768, 0x00 },
  35. { 8000, 0x01 },
  36. { 11025, 0x02 },
  37. { 12000, 0x03 },
  38. { 16000, 0x04 },
  39. { 22050, 0x05 },
  40. { 24000, 0x06 },
  41. { 32000, 0x07 },
  42. { 44100, 0x08 },
  43. { 48000, 0x09 },
  44. { 88200, 0x0A },
  45. { 96000, 0x0B },
  46. { 128000, 0x0C },
  47. { 176400, 0x0D },
  48. { 192000, 0x0E },
  49. { 256000, 0x0F },
  50. { 352800, 0x10 },
  51. { 384000, 0x11 },
  52. { 512000, 0x12 },
  53. { 705600, 0x13 },
  54. { 750000, 0x14 },
  55. { 768000, 0x15 },
  56. { 1000000, 0x16 },
  57. { 1024000, 0x17 },
  58. { 1200000, 0x18 },
  59. { 1411200, 0x19 },
  60. { 1500000, 0x1A },
  61. { 1536000, 0x1B },
  62. { 2000000, 0x1C },
  63. { 2048000, 0x1D },
  64. { 2400000, 0x1E },
  65. { 2822400, 0x1F },
  66. { 3000000, 0x20 },
  67. { 3072000, 0x21 },
  68. { 3200000, 0x22 },
  69. { 4000000, 0x23 },
  70. { 4096000, 0x24 },
  71. { 4800000, 0x25 },
  72. { 5644800, 0x26 },
  73. { 6000000, 0x27 },
  74. { 6144000, 0x28 },
  75. { 6250000, 0x29 },
  76. { 6400000, 0x2A },
  77. { 6500000, 0x2B },
  78. { 6750000, 0x2C },
  79. { 7526400, 0x2D },
  80. { 8000000, 0x2E },
  81. { 8192000, 0x2F },
  82. { 9600000, 0x30 },
  83. { 11289600, 0x31 },
  84. { 12000000, 0x32 },
  85. { 12288000, 0x33 },
  86. { 12500000, 0x34 },
  87. { 12800000, 0x35 },
  88. { 13000000, 0x36 },
  89. { 13500000, 0x37 },
  90. { 19200000, 0x38 },
  91. { 22579200, 0x39 },
  92. { 24000000, 0x3A },
  93. { 24576000, 0x3B },
  94. { 25000000, 0x3C },
  95. { 25600000, 0x3D },
  96. { 26000000, 0x3E },
  97. { 27000000, 0x3F },
  98. };
  99. struct cs35l41_fs_mon_config {
  100. int freq;
  101. unsigned int fs1;
  102. unsigned int fs2;
  103. };
  104. static const struct cs35l41_fs_mon_config cs35l41_fs_mon[] = {
  105. { 32768, 2254, 3754 },
  106. { 8000, 9220, 15364 },
  107. { 11025, 6148, 10244 },
  108. { 12000, 6148, 10244 },
  109. { 16000, 4612, 7684 },
  110. { 22050, 3076, 5124 },
  111. { 24000, 3076, 5124 },
  112. { 32000, 2308, 3844 },
  113. { 44100, 1540, 2564 },
  114. { 48000, 1540, 2564 },
  115. { 88200, 772, 1284 },
  116. { 96000, 772, 1284 },
  117. { 128000, 580, 964 },
  118. { 176400, 388, 644 },
  119. { 192000, 388, 644 },
  120. { 256000, 292, 484 },
  121. { 352800, 196, 324 },
  122. { 384000, 196, 324 },
  123. { 512000, 148, 244 },
  124. { 705600, 100, 164 },
  125. { 750000, 100, 164 },
  126. { 768000, 100, 164 },
  127. { 1000000, 76, 124 },
  128. { 1024000, 76, 124 },
  129. { 1200000, 64, 104 },
  130. { 1411200, 52, 84 },
  131. { 1500000, 52, 84 },
  132. { 1536000, 52, 84 },
  133. { 2000000, 40, 64 },
  134. { 2048000, 40, 64 },
  135. { 2400000, 34, 54 },
  136. { 2822400, 28, 44 },
  137. { 3000000, 28, 44 },
  138. { 3072000, 28, 44 },
  139. { 3200000, 27, 42 },
  140. { 4000000, 22, 34 },
  141. { 4096000, 22, 34 },
  142. { 4800000, 19, 29 },
  143. { 5644800, 16, 24 },
  144. { 6000000, 16, 24 },
  145. { 6144000, 16, 24 },
  146. };
  147. static int cs35l41_get_fs_mon_config_index(int freq)
  148. {
  149. int i;
  150. for (i = 0; i < ARRAY_SIZE(cs35l41_fs_mon); i++) {
  151. if (cs35l41_fs_mon[i].freq == freq)
  152. return i;
  153. }
  154. return -EINVAL;
  155. }
  156. static const DECLARE_TLV_DB_RANGE(dig_vol_tlv,
  157. 0, 0, TLV_DB_SCALE_ITEM(TLV_DB_GAIN_MUTE, 0, 1),
  158. 1, 913, TLV_DB_MINMAX_ITEM(-10200, 1200));
  159. static DECLARE_TLV_DB_SCALE(amp_gain_tlv, 50, 100, 0);
  160. static const struct snd_kcontrol_new dre_ctrl =
  161. SOC_DAPM_SINGLE("Switch", CS35L41_PWR_CTRL3, 20, 1, 0);
  162. static const char * const cs35l41_pcm_sftramp_text[] = {
  163. "Off", ".5ms", "1ms", "2ms", "4ms", "8ms", "15ms", "30ms"
  164. };
  165. static SOC_ENUM_SINGLE_DECL(pcm_sft_ramp,
  166. CS35L41_AMP_DIG_VOL_CTRL, 0,
  167. cs35l41_pcm_sftramp_text);
  168. static int cs35l41_dsp_preload_ev(struct snd_soc_dapm_widget *w,
  169. struct snd_kcontrol *kcontrol, int event)
  170. {
  171. struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
  172. struct cs35l41_private *cs35l41 = snd_soc_component_get_drvdata(component);
  173. int ret;
  174. switch (event) {
  175. case SND_SOC_DAPM_PRE_PMU:
  176. if (cs35l41->dsp.cs_dsp.booted)
  177. return 0;
  178. return wm_adsp_early_event(w, kcontrol, event);
  179. case SND_SOC_DAPM_PRE_PMD:
  180. if (cs35l41->dsp.preloaded)
  181. return 0;
  182. if (cs35l41->dsp.cs_dsp.running) {
  183. ret = wm_adsp_event(w, kcontrol, event);
  184. if (ret)
  185. return ret;
  186. }
  187. return wm_adsp_early_event(w, kcontrol, event);
  188. default:
  189. return 0;
  190. }
  191. }
  192. static int cs35l41_dsp_audio_ev(struct snd_soc_dapm_widget *w,
  193. struct snd_kcontrol *kcontrol, int event)
  194. {
  195. struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
  196. struct cs35l41_private *cs35l41 = snd_soc_component_get_drvdata(component);
  197. unsigned int fw_status;
  198. int ret;
  199. switch (event) {
  200. case SND_SOC_DAPM_POST_PMU:
  201. if (!cs35l41->dsp.cs_dsp.running)
  202. return wm_adsp_event(w, kcontrol, event);
  203. ret = regmap_read(cs35l41->regmap, CS35L41_DSP_MBOX_2, &fw_status);
  204. if (ret < 0) {
  205. dev_err(cs35l41->dev,
  206. "Failed to read firmware status: %d\n", ret);
  207. return ret;
  208. }
  209. switch (fw_status) {
  210. case CSPL_MBOX_STS_RUNNING:
  211. case CSPL_MBOX_STS_PAUSED:
  212. break;
  213. default:
  214. dev_err(cs35l41->dev, "Firmware status is invalid: %u\n",
  215. fw_status);
  216. return -EINVAL;
  217. }
  218. return cs35l41_set_cspl_mbox_cmd(cs35l41->dev, cs35l41->regmap,
  219. CSPL_MBOX_CMD_RESUME);
  220. case SND_SOC_DAPM_PRE_PMD:
  221. return cs35l41_set_cspl_mbox_cmd(cs35l41->dev, cs35l41->regmap,
  222. CSPL_MBOX_CMD_PAUSE);
  223. default:
  224. return 0;
  225. }
  226. }
  227. static const char * const cs35l41_pcm_source_texts[] = {"ASP", "DSP"};
  228. static const unsigned int cs35l41_pcm_source_values[] = {0x08, 0x32};
  229. static SOC_VALUE_ENUM_SINGLE_DECL(cs35l41_pcm_source_enum,
  230. CS35L41_DAC_PCM1_SRC,
  231. 0, CS35L41_ASP_SOURCE_MASK,
  232. cs35l41_pcm_source_texts,
  233. cs35l41_pcm_source_values);
  234. static const struct snd_kcontrol_new pcm_source_mux =
  235. SOC_DAPM_ENUM("PCM Source", cs35l41_pcm_source_enum);
  236. static const char * const cs35l41_tx_input_texts[] = {
  237. "Zero", "ASPRX1", "ASPRX2", "VMON", "IMON",
  238. "VPMON", "VBSTMON", "DSPTX1", "DSPTX2"
  239. };
  240. static const unsigned int cs35l41_tx_input_values[] = {
  241. 0x00, CS35L41_INPUT_SRC_ASPRX1, CS35L41_INPUT_SRC_ASPRX2,
  242. CS35L41_INPUT_SRC_VMON, CS35L41_INPUT_SRC_IMON, CS35L41_INPUT_SRC_VPMON,
  243. CS35L41_INPUT_SRC_VBSTMON, CS35L41_INPUT_DSP_TX1, CS35L41_INPUT_DSP_TX2
  244. };
  245. static SOC_VALUE_ENUM_SINGLE_DECL(cs35l41_asptx1_enum,
  246. CS35L41_ASP_TX1_SRC,
  247. 0, CS35L41_ASP_SOURCE_MASK,
  248. cs35l41_tx_input_texts,
  249. cs35l41_tx_input_values);
  250. static const struct snd_kcontrol_new asp_tx1_mux =
  251. SOC_DAPM_ENUM("ASPTX1 SRC", cs35l41_asptx1_enum);
  252. static SOC_VALUE_ENUM_SINGLE_DECL(cs35l41_asptx2_enum,
  253. CS35L41_ASP_TX2_SRC,
  254. 0, CS35L41_ASP_SOURCE_MASK,
  255. cs35l41_tx_input_texts,
  256. cs35l41_tx_input_values);
  257. static const struct snd_kcontrol_new asp_tx2_mux =
  258. SOC_DAPM_ENUM("ASPTX2 SRC", cs35l41_asptx2_enum);
  259. static SOC_VALUE_ENUM_SINGLE_DECL(cs35l41_asptx3_enum,
  260. CS35L41_ASP_TX3_SRC,
  261. 0, CS35L41_ASP_SOURCE_MASK,
  262. cs35l41_tx_input_texts,
  263. cs35l41_tx_input_values);
  264. static const struct snd_kcontrol_new asp_tx3_mux =
  265. SOC_DAPM_ENUM("ASPTX3 SRC", cs35l41_asptx3_enum);
  266. static SOC_VALUE_ENUM_SINGLE_DECL(cs35l41_asptx4_enum,
  267. CS35L41_ASP_TX4_SRC,
  268. 0, CS35L41_ASP_SOURCE_MASK,
  269. cs35l41_tx_input_texts,
  270. cs35l41_tx_input_values);
  271. static const struct snd_kcontrol_new asp_tx4_mux =
  272. SOC_DAPM_ENUM("ASPTX4 SRC", cs35l41_asptx4_enum);
  273. static SOC_VALUE_ENUM_SINGLE_DECL(cs35l41_dsprx1_enum,
  274. CS35L41_DSP1_RX1_SRC,
  275. 0, CS35L41_ASP_SOURCE_MASK,
  276. cs35l41_tx_input_texts,
  277. cs35l41_tx_input_values);
  278. static const struct snd_kcontrol_new dsp_rx1_mux =
  279. SOC_DAPM_ENUM("DSPRX1 SRC", cs35l41_dsprx1_enum);
  280. static SOC_VALUE_ENUM_SINGLE_DECL(cs35l41_dsprx2_enum,
  281. CS35L41_DSP1_RX2_SRC,
  282. 0, CS35L41_ASP_SOURCE_MASK,
  283. cs35l41_tx_input_texts,
  284. cs35l41_tx_input_values);
  285. static const struct snd_kcontrol_new dsp_rx2_mux =
  286. SOC_DAPM_ENUM("DSPRX2 SRC", cs35l41_dsprx2_enum);
  287. static const struct snd_kcontrol_new cs35l41_aud_controls[] = {
  288. SOC_SINGLE_SX_TLV("Digital PCM Volume", CS35L41_AMP_DIG_VOL_CTRL,
  289. 3, 0x4CF, 0x391, dig_vol_tlv),
  290. SOC_SINGLE_TLV("Analog PCM Volume", CS35L41_AMP_GAIN_CTRL, 5, 0x14, 0,
  291. amp_gain_tlv),
  292. SOC_ENUM("PCM Soft Ramp", pcm_sft_ramp),
  293. SOC_SINGLE("HW Noise Gate Enable", CS35L41_NG_CFG, 8, 63, 0),
  294. SOC_SINGLE("HW Noise Gate Delay", CS35L41_NG_CFG, 4, 7, 0),
  295. SOC_SINGLE("HW Noise Gate Threshold", CS35L41_NG_CFG, 0, 7, 0),
  296. SOC_SINGLE("Aux Noise Gate CH1 Switch",
  297. CS35L41_MIXER_NGATE_CH1_CFG, 16, 1, 0),
  298. SOC_SINGLE("Aux Noise Gate CH1 Entry Delay",
  299. CS35L41_MIXER_NGATE_CH1_CFG, 8, 15, 0),
  300. SOC_SINGLE("Aux Noise Gate CH1 Threshold",
  301. CS35L41_MIXER_NGATE_CH1_CFG, 0, 7, 0),
  302. SOC_SINGLE("Aux Noise Gate CH2 Entry Delay",
  303. CS35L41_MIXER_NGATE_CH2_CFG, 8, 15, 0),
  304. SOC_SINGLE("Aux Noise Gate CH2 Switch",
  305. CS35L41_MIXER_NGATE_CH2_CFG, 16, 1, 0),
  306. SOC_SINGLE("Aux Noise Gate CH2 Threshold",
  307. CS35L41_MIXER_NGATE_CH2_CFG, 0, 7, 0),
  308. SOC_SINGLE("SCLK Force Switch", CS35L41_SP_FORMAT, CS35L41_SCLK_FRC_SHIFT, 1, 0),
  309. SOC_SINGLE("LRCLK Force Switch", CS35L41_SP_FORMAT, CS35L41_LRCLK_FRC_SHIFT, 1, 0),
  310. SOC_SINGLE("Invert Class D Switch", CS35L41_AMP_DIG_VOL_CTRL,
  311. CS35L41_AMP_INV_PCM_SHIFT, 1, 0),
  312. SOC_SINGLE("Amp Gain ZC Switch", CS35L41_AMP_GAIN_CTRL,
  313. CS35L41_AMP_GAIN_ZC_SHIFT, 1, 0),
  314. WM_ADSP2_PRELOAD_SWITCH("DSP1", 1),
  315. WM_ADSP_FW_CONTROL("DSP1", 0),
  316. };
  317. static void cs35l41_boost_enable(struct cs35l41_private *cs35l41, unsigned int enable)
  318. {
  319. switch (cs35l41->hw_cfg.bst_type) {
  320. case CS35L41_INT_BOOST:
  321. enable = enable ? CS35L41_BST_EN_DEFAULT : CS35L41_BST_DIS_FET_OFF;
  322. regmap_update_bits(cs35l41->regmap, CS35L41_PWR_CTRL2, CS35L41_BST_EN_MASK,
  323. enable << CS35L41_BST_EN_SHIFT);
  324. break;
  325. default:
  326. break;
  327. }
  328. }
  329. static irqreturn_t cs35l41_irq(int irq, void *data)
  330. {
  331. struct cs35l41_private *cs35l41 = data;
  332. unsigned int status[4] = { 0, 0, 0, 0 };
  333. unsigned int masks[4] = { 0, 0, 0, 0 };
  334. unsigned int i;
  335. int ret;
  336. ret = pm_runtime_resume_and_get(cs35l41->dev);
  337. if (ret < 0) {
  338. dev_err(cs35l41->dev,
  339. "pm_runtime_resume_and_get failed in %s: %d\n",
  340. __func__, ret);
  341. return IRQ_NONE;
  342. }
  343. ret = IRQ_NONE;
  344. for (i = 0; i < ARRAY_SIZE(status); i++) {
  345. regmap_read(cs35l41->regmap,
  346. CS35L41_IRQ1_STATUS1 + (i * CS35L41_REGSTRIDE),
  347. &status[i]);
  348. regmap_read(cs35l41->regmap,
  349. CS35L41_IRQ1_MASK1 + (i * CS35L41_REGSTRIDE),
  350. &masks[i]);
  351. }
  352. /* Check to see if unmasked bits are active */
  353. if (!(status[0] & ~masks[0]) && !(status[1] & ~masks[1]) &&
  354. !(status[2] & ~masks[2]) && !(status[3] & ~masks[3]))
  355. goto done;
  356. if (status[3] & CS35L41_OTP_BOOT_DONE) {
  357. regmap_update_bits(cs35l41->regmap, CS35L41_IRQ1_MASK4,
  358. CS35L41_OTP_BOOT_DONE, CS35L41_OTP_BOOT_DONE);
  359. }
  360. /*
  361. * The following interrupts require a
  362. * protection release cycle to get the
  363. * speaker out of Safe-Mode.
  364. */
  365. if (status[0] & CS35L41_AMP_SHORT_ERR) {
  366. dev_crit_ratelimited(cs35l41->dev, "Amp short error\n");
  367. regmap_write(cs35l41->regmap, CS35L41_IRQ1_STATUS1,
  368. CS35L41_AMP_SHORT_ERR);
  369. regmap_write(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN, 0);
  370. regmap_update_bits(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN,
  371. CS35L41_AMP_SHORT_ERR_RLS,
  372. CS35L41_AMP_SHORT_ERR_RLS);
  373. regmap_update_bits(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN,
  374. CS35L41_AMP_SHORT_ERR_RLS, 0);
  375. ret = IRQ_HANDLED;
  376. }
  377. if (status[0] & CS35L41_TEMP_WARN) {
  378. dev_crit_ratelimited(cs35l41->dev, "Over temperature warning\n");
  379. regmap_write(cs35l41->regmap, CS35L41_IRQ1_STATUS1,
  380. CS35L41_TEMP_WARN);
  381. regmap_write(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN, 0);
  382. regmap_update_bits(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN,
  383. CS35L41_TEMP_WARN_ERR_RLS,
  384. CS35L41_TEMP_WARN_ERR_RLS);
  385. regmap_update_bits(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN,
  386. CS35L41_TEMP_WARN_ERR_RLS, 0);
  387. ret = IRQ_HANDLED;
  388. }
  389. if (status[0] & CS35L41_TEMP_ERR) {
  390. dev_crit_ratelimited(cs35l41->dev, "Over temperature error\n");
  391. regmap_write(cs35l41->regmap, CS35L41_IRQ1_STATUS1,
  392. CS35L41_TEMP_ERR);
  393. regmap_write(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN, 0);
  394. regmap_update_bits(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN,
  395. CS35L41_TEMP_ERR_RLS,
  396. CS35L41_TEMP_ERR_RLS);
  397. regmap_update_bits(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN,
  398. CS35L41_TEMP_ERR_RLS, 0);
  399. ret = IRQ_HANDLED;
  400. }
  401. if (status[0] & CS35L41_BST_OVP_ERR) {
  402. dev_crit_ratelimited(cs35l41->dev, "VBST Over Voltage error\n");
  403. cs35l41_boost_enable(cs35l41, 0);
  404. regmap_write(cs35l41->regmap, CS35L41_IRQ1_STATUS1,
  405. CS35L41_BST_OVP_ERR);
  406. regmap_write(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN, 0);
  407. regmap_update_bits(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN,
  408. CS35L41_BST_OVP_ERR_RLS,
  409. CS35L41_BST_OVP_ERR_RLS);
  410. regmap_update_bits(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN,
  411. CS35L41_BST_OVP_ERR_RLS, 0);
  412. cs35l41_boost_enable(cs35l41, 1);
  413. ret = IRQ_HANDLED;
  414. }
  415. if (status[0] & CS35L41_BST_DCM_UVP_ERR) {
  416. dev_crit_ratelimited(cs35l41->dev, "DCM VBST Under Voltage Error\n");
  417. cs35l41_boost_enable(cs35l41, 0);
  418. regmap_write(cs35l41->regmap, CS35L41_IRQ1_STATUS1,
  419. CS35L41_BST_DCM_UVP_ERR);
  420. regmap_write(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN, 0);
  421. regmap_update_bits(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN,
  422. CS35L41_BST_UVP_ERR_RLS,
  423. CS35L41_BST_UVP_ERR_RLS);
  424. regmap_update_bits(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN,
  425. CS35L41_BST_UVP_ERR_RLS, 0);
  426. cs35l41_boost_enable(cs35l41, 1);
  427. ret = IRQ_HANDLED;
  428. }
  429. if (status[0] & CS35L41_BST_SHORT_ERR) {
  430. dev_crit_ratelimited(cs35l41->dev, "LBST error: powering off!\n");
  431. cs35l41_boost_enable(cs35l41, 0);
  432. regmap_write(cs35l41->regmap, CS35L41_IRQ1_STATUS1,
  433. CS35L41_BST_SHORT_ERR);
  434. regmap_write(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN, 0);
  435. regmap_update_bits(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN,
  436. CS35L41_BST_SHORT_ERR_RLS,
  437. CS35L41_BST_SHORT_ERR_RLS);
  438. regmap_update_bits(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN,
  439. CS35L41_BST_SHORT_ERR_RLS, 0);
  440. cs35l41_boost_enable(cs35l41, 1);
  441. ret = IRQ_HANDLED;
  442. }
  443. done:
  444. pm_runtime_mark_last_busy(cs35l41->dev);
  445. pm_runtime_put_autosuspend(cs35l41->dev);
  446. return ret;
  447. }
  448. static const struct reg_sequence cs35l41_pup_patch[] = {
  449. { CS35L41_TEST_KEY_CTL, 0x00000055 },
  450. { CS35L41_TEST_KEY_CTL, 0x000000AA },
  451. { 0x00002084, 0x002F1AA0 },
  452. { CS35L41_TEST_KEY_CTL, 0x000000CC },
  453. { CS35L41_TEST_KEY_CTL, 0x00000033 },
  454. };
  455. static const struct reg_sequence cs35l41_pdn_patch[] = {
  456. { CS35L41_TEST_KEY_CTL, 0x00000055 },
  457. { CS35L41_TEST_KEY_CTL, 0x000000AA },
  458. { 0x00002084, 0x002F1AA3 },
  459. { CS35L41_TEST_KEY_CTL, 0x000000CC },
  460. { CS35L41_TEST_KEY_CTL, 0x00000033 },
  461. };
  462. static int cs35l41_main_amp_event(struct snd_soc_dapm_widget *w,
  463. struct snd_kcontrol *kcontrol, int event)
  464. {
  465. struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
  466. struct cs35l41_private *cs35l41 = snd_soc_component_get_drvdata(component);
  467. unsigned int val;
  468. int ret = 0;
  469. switch (event) {
  470. case SND_SOC_DAPM_PRE_PMU:
  471. regmap_multi_reg_write_bypassed(cs35l41->regmap,
  472. cs35l41_pup_patch,
  473. ARRAY_SIZE(cs35l41_pup_patch));
  474. cs35l41_global_enable(cs35l41->regmap, cs35l41->hw_cfg.bst_type, 1);
  475. break;
  476. case SND_SOC_DAPM_POST_PMD:
  477. cs35l41_global_enable(cs35l41->regmap, cs35l41->hw_cfg.bst_type, 0);
  478. ret = regmap_read_poll_timeout(cs35l41->regmap, CS35L41_IRQ1_STATUS1,
  479. val, val & CS35L41_PDN_DONE_MASK,
  480. 1000, 100000);
  481. if (ret)
  482. dev_warn(cs35l41->dev, "PDN failed: %d\n", ret);
  483. regmap_write(cs35l41->regmap, CS35L41_IRQ1_STATUS1,
  484. CS35L41_PDN_DONE_MASK);
  485. regmap_multi_reg_write_bypassed(cs35l41->regmap,
  486. cs35l41_pdn_patch,
  487. ARRAY_SIZE(cs35l41_pdn_patch));
  488. break;
  489. default:
  490. dev_err(cs35l41->dev, "Invalid event = 0x%x\n", event);
  491. ret = -EINVAL;
  492. }
  493. return ret;
  494. }
  495. static const struct snd_soc_dapm_widget cs35l41_dapm_widgets[] = {
  496. SND_SOC_DAPM_SPK("DSP1 Preload", NULL),
  497. SND_SOC_DAPM_SUPPLY_S("DSP1 Preloader", 100, SND_SOC_NOPM, 0, 0,
  498. cs35l41_dsp_preload_ev,
  499. SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD),
  500. SND_SOC_DAPM_OUT_DRV_E("DSP1", SND_SOC_NOPM, 0, 0, NULL, 0,
  501. cs35l41_dsp_audio_ev,
  502. SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
  503. SND_SOC_DAPM_OUTPUT("SPK"),
  504. SND_SOC_DAPM_AIF_IN("ASPRX1", NULL, 0, CS35L41_SP_ENABLES, 16, 0),
  505. SND_SOC_DAPM_AIF_IN("ASPRX2", NULL, 0, CS35L41_SP_ENABLES, 17, 0),
  506. SND_SOC_DAPM_AIF_OUT("ASPTX1", NULL, 0, CS35L41_SP_ENABLES, 0, 0),
  507. SND_SOC_DAPM_AIF_OUT("ASPTX2", NULL, 0, CS35L41_SP_ENABLES, 1, 0),
  508. SND_SOC_DAPM_AIF_OUT("ASPTX3", NULL, 0, CS35L41_SP_ENABLES, 2, 0),
  509. SND_SOC_DAPM_AIF_OUT("ASPTX4", NULL, 0, CS35L41_SP_ENABLES, 3, 0),
  510. SND_SOC_DAPM_SIGGEN("VSENSE"),
  511. SND_SOC_DAPM_SIGGEN("ISENSE"),
  512. SND_SOC_DAPM_SIGGEN("VP"),
  513. SND_SOC_DAPM_SIGGEN("VBST"),
  514. SND_SOC_DAPM_SIGGEN("TEMP"),
  515. SND_SOC_DAPM_SUPPLY("VMON", CS35L41_PWR_CTRL2, 12, 0, NULL, 0),
  516. SND_SOC_DAPM_SUPPLY("IMON", CS35L41_PWR_CTRL2, 13, 0, NULL, 0),
  517. SND_SOC_DAPM_SUPPLY("VPMON", CS35L41_PWR_CTRL2, 8, 0, NULL, 0),
  518. SND_SOC_DAPM_SUPPLY("VBSTMON", CS35L41_PWR_CTRL2, 9, 0, NULL, 0),
  519. SND_SOC_DAPM_SUPPLY("TEMPMON", CS35L41_PWR_CTRL2, 10, 0, NULL, 0),
  520. SND_SOC_DAPM_ADC("VMON ADC", NULL, SND_SOC_NOPM, 0, 0),
  521. SND_SOC_DAPM_ADC("IMON ADC", NULL, SND_SOC_NOPM, 0, 0),
  522. SND_SOC_DAPM_ADC("VPMON ADC", NULL, SND_SOC_NOPM, 0, 0),
  523. SND_SOC_DAPM_ADC("VBSTMON ADC", NULL, SND_SOC_NOPM, 0, 0),
  524. SND_SOC_DAPM_ADC("TEMPMON ADC", NULL, SND_SOC_NOPM, 0, 0),
  525. SND_SOC_DAPM_ADC("CLASS H", NULL, CS35L41_PWR_CTRL3, 4, 0),
  526. SND_SOC_DAPM_OUT_DRV_E("Main AMP", CS35L41_PWR_CTRL2, 0, 0, NULL, 0,
  527. cs35l41_main_amp_event,
  528. SND_SOC_DAPM_POST_PMD | SND_SOC_DAPM_PRE_PMU),
  529. SND_SOC_DAPM_MUX("ASP TX1 Source", SND_SOC_NOPM, 0, 0, &asp_tx1_mux),
  530. SND_SOC_DAPM_MUX("ASP TX2 Source", SND_SOC_NOPM, 0, 0, &asp_tx2_mux),
  531. SND_SOC_DAPM_MUX("ASP TX3 Source", SND_SOC_NOPM, 0, 0, &asp_tx3_mux),
  532. SND_SOC_DAPM_MUX("ASP TX4 Source", SND_SOC_NOPM, 0, 0, &asp_tx4_mux),
  533. SND_SOC_DAPM_MUX("DSP RX1 Source", SND_SOC_NOPM, 0, 0, &dsp_rx1_mux),
  534. SND_SOC_DAPM_MUX("DSP RX2 Source", SND_SOC_NOPM, 0, 0, &dsp_rx2_mux),
  535. SND_SOC_DAPM_MUX("PCM Source", SND_SOC_NOPM, 0, 0, &pcm_source_mux),
  536. SND_SOC_DAPM_SWITCH("DRE", SND_SOC_NOPM, 0, 0, &dre_ctrl),
  537. };
  538. static const struct snd_soc_dapm_route cs35l41_audio_map[] = {
  539. {"DSP RX1 Source", "ASPRX1", "ASPRX1"},
  540. {"DSP RX1 Source", "ASPRX2", "ASPRX2"},
  541. {"DSP RX2 Source", "ASPRX1", "ASPRX1"},
  542. {"DSP RX2 Source", "ASPRX2", "ASPRX2"},
  543. {"DSP1", NULL, "DSP RX1 Source"},
  544. {"DSP1", NULL, "DSP RX2 Source"},
  545. {"ASP TX1 Source", "VMON", "VMON ADC"},
  546. {"ASP TX1 Source", "IMON", "IMON ADC"},
  547. {"ASP TX1 Source", "VPMON", "VPMON ADC"},
  548. {"ASP TX1 Source", "VBSTMON", "VBSTMON ADC"},
  549. {"ASP TX1 Source", "DSPTX1", "DSP1"},
  550. {"ASP TX1 Source", "DSPTX2", "DSP1"},
  551. {"ASP TX1 Source", "ASPRX1", "ASPRX1" },
  552. {"ASP TX1 Source", "ASPRX2", "ASPRX2" },
  553. {"ASP TX2 Source", "VMON", "VMON ADC"},
  554. {"ASP TX2 Source", "IMON", "IMON ADC"},
  555. {"ASP TX2 Source", "VPMON", "VPMON ADC"},
  556. {"ASP TX2 Source", "VBSTMON", "VBSTMON ADC"},
  557. {"ASP TX2 Source", "DSPTX1", "DSP1"},
  558. {"ASP TX2 Source", "DSPTX2", "DSP1"},
  559. {"ASP TX2 Source", "ASPRX1", "ASPRX1" },
  560. {"ASP TX2 Source", "ASPRX2", "ASPRX2" },
  561. {"ASP TX3 Source", "VMON", "VMON ADC"},
  562. {"ASP TX3 Source", "IMON", "IMON ADC"},
  563. {"ASP TX3 Source", "VPMON", "VPMON ADC"},
  564. {"ASP TX3 Source", "VBSTMON", "VBSTMON ADC"},
  565. {"ASP TX3 Source", "DSPTX1", "DSP1"},
  566. {"ASP TX3 Source", "DSPTX2", "DSP1"},
  567. {"ASP TX3 Source", "ASPRX1", "ASPRX1" },
  568. {"ASP TX3 Source", "ASPRX2", "ASPRX2" },
  569. {"ASP TX4 Source", "VMON", "VMON ADC"},
  570. {"ASP TX4 Source", "IMON", "IMON ADC"},
  571. {"ASP TX4 Source", "VPMON", "VPMON ADC"},
  572. {"ASP TX4 Source", "VBSTMON", "VBSTMON ADC"},
  573. {"ASP TX4 Source", "DSPTX1", "DSP1"},
  574. {"ASP TX4 Source", "DSPTX2", "DSP1"},
  575. {"ASP TX4 Source", "ASPRX1", "ASPRX1" },
  576. {"ASP TX4 Source", "ASPRX2", "ASPRX2" },
  577. {"ASPTX1", NULL, "ASP TX1 Source"},
  578. {"ASPTX2", NULL, "ASP TX2 Source"},
  579. {"ASPTX3", NULL, "ASP TX3 Source"},
  580. {"ASPTX4", NULL, "ASP TX4 Source"},
  581. {"AMP Capture", NULL, "ASPTX1"},
  582. {"AMP Capture", NULL, "ASPTX2"},
  583. {"AMP Capture", NULL, "ASPTX3"},
  584. {"AMP Capture", NULL, "ASPTX4"},
  585. {"DSP1", NULL, "VMON"},
  586. {"DSP1", NULL, "IMON"},
  587. {"DSP1", NULL, "VPMON"},
  588. {"DSP1", NULL, "VBSTMON"},
  589. {"DSP1", NULL, "TEMPMON"},
  590. {"VMON ADC", NULL, "VMON"},
  591. {"IMON ADC", NULL, "IMON"},
  592. {"VPMON ADC", NULL, "VPMON"},
  593. {"VBSTMON ADC", NULL, "VBSTMON"},
  594. {"TEMPMON ADC", NULL, "TEMPMON"},
  595. {"VMON ADC", NULL, "VSENSE"},
  596. {"IMON ADC", NULL, "ISENSE"},
  597. {"VPMON ADC", NULL, "VP"},
  598. {"VBSTMON ADC", NULL, "VBST"},
  599. {"TEMPMON ADC", NULL, "TEMP"},
  600. {"DSP1 Preload", NULL, "DSP1 Preloader"},
  601. {"DSP1", NULL, "DSP1 Preloader"},
  602. {"ASPRX1", NULL, "AMP Playback"},
  603. {"ASPRX2", NULL, "AMP Playback"},
  604. {"DRE", "Switch", "CLASS H"},
  605. {"Main AMP", NULL, "CLASS H"},
  606. {"Main AMP", NULL, "DRE"},
  607. {"SPK", NULL, "Main AMP"},
  608. {"PCM Source", "ASP", "ASPRX1"},
  609. {"PCM Source", "DSP", "DSP1"},
  610. {"CLASS H", NULL, "PCM Source"},
  611. };
  612. static int cs35l41_set_channel_map(struct snd_soc_dai *dai, unsigned int tx_n,
  613. unsigned int *tx_slot, unsigned int rx_n, unsigned int *rx_slot)
  614. {
  615. struct cs35l41_private *cs35l41 = snd_soc_component_get_drvdata(dai->component);
  616. return cs35l41_set_channels(cs35l41->dev, cs35l41->regmap, tx_n, tx_slot, rx_n, rx_slot);
  617. }
  618. static int cs35l41_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
  619. {
  620. struct cs35l41_private *cs35l41 = snd_soc_component_get_drvdata(dai->component);
  621. unsigned int daifmt = 0;
  622. switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {
  623. case SND_SOC_DAIFMT_CBP_CFP:
  624. daifmt |= CS35L41_SCLK_MSTR_MASK | CS35L41_LRCLK_MSTR_MASK;
  625. break;
  626. case SND_SOC_DAIFMT_CBC_CFC:
  627. break;
  628. default:
  629. dev_warn(cs35l41->dev, "Mixed provider/consumer mode unsupported\n");
  630. return -EINVAL;
  631. }
  632. switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
  633. case SND_SOC_DAIFMT_DSP_A:
  634. break;
  635. case SND_SOC_DAIFMT_I2S:
  636. daifmt |= 2 << CS35L41_ASP_FMT_SHIFT;
  637. break;
  638. default:
  639. dev_warn(cs35l41->dev, "Invalid or unsupported DAI format\n");
  640. return -EINVAL;
  641. }
  642. switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
  643. case SND_SOC_DAIFMT_NB_IF:
  644. daifmt |= CS35L41_LRCLK_INV_MASK;
  645. break;
  646. case SND_SOC_DAIFMT_IB_NF:
  647. daifmt |= CS35L41_SCLK_INV_MASK;
  648. break;
  649. case SND_SOC_DAIFMT_IB_IF:
  650. daifmt |= CS35L41_LRCLK_INV_MASK | CS35L41_SCLK_INV_MASK;
  651. break;
  652. case SND_SOC_DAIFMT_NB_NF:
  653. break;
  654. default:
  655. dev_warn(cs35l41->dev, "Invalid DAI clock INV\n");
  656. return -EINVAL;
  657. }
  658. return regmap_update_bits(cs35l41->regmap, CS35L41_SP_FORMAT,
  659. CS35L41_SCLK_MSTR_MASK | CS35L41_LRCLK_MSTR_MASK |
  660. CS35L41_ASP_FMT_MASK | CS35L41_LRCLK_INV_MASK |
  661. CS35L41_SCLK_INV_MASK, daifmt);
  662. }
  663. struct cs35l41_global_fs_config {
  664. int rate;
  665. int fs_cfg;
  666. };
  667. static const struct cs35l41_global_fs_config cs35l41_fs_rates[] = {
  668. { 12000, 0x01 },
  669. { 24000, 0x02 },
  670. { 48000, 0x03 },
  671. { 96000, 0x04 },
  672. { 192000, 0x05 },
  673. { 11025, 0x09 },
  674. { 22050, 0x0A },
  675. { 44100, 0x0B },
  676. { 88200, 0x0C },
  677. { 176400, 0x0D },
  678. { 8000, 0x11 },
  679. { 16000, 0x12 },
  680. { 32000, 0x13 },
  681. };
  682. static int cs35l41_pcm_hw_params(struct snd_pcm_substream *substream,
  683. struct snd_pcm_hw_params *params,
  684. struct snd_soc_dai *dai)
  685. {
  686. struct cs35l41_private *cs35l41 = snd_soc_component_get_drvdata(dai->component);
  687. unsigned int rate = params_rate(params);
  688. u8 asp_wl;
  689. int i;
  690. for (i = 0; i < ARRAY_SIZE(cs35l41_fs_rates); i++) {
  691. if (rate == cs35l41_fs_rates[i].rate)
  692. break;
  693. }
  694. if (i >= ARRAY_SIZE(cs35l41_fs_rates)) {
  695. dev_err(cs35l41->dev, "Unsupported rate: %u\n", rate);
  696. return -EINVAL;
  697. }
  698. asp_wl = params_width(params);
  699. if (i < ARRAY_SIZE(cs35l41_fs_rates))
  700. regmap_update_bits(cs35l41->regmap, CS35L41_GLOBAL_CLK_CTRL,
  701. CS35L41_GLOBAL_FS_MASK,
  702. cs35l41_fs_rates[i].fs_cfg << CS35L41_GLOBAL_FS_SHIFT);
  703. if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
  704. regmap_update_bits(cs35l41->regmap, CS35L41_SP_FORMAT,
  705. CS35L41_ASP_WIDTH_RX_MASK,
  706. asp_wl << CS35L41_ASP_WIDTH_RX_SHIFT);
  707. regmap_update_bits(cs35l41->regmap, CS35L41_SP_RX_WL,
  708. CS35L41_ASP_RX_WL_MASK,
  709. asp_wl << CS35L41_ASP_RX_WL_SHIFT);
  710. } else {
  711. regmap_update_bits(cs35l41->regmap, CS35L41_SP_FORMAT,
  712. CS35L41_ASP_WIDTH_TX_MASK,
  713. asp_wl << CS35L41_ASP_WIDTH_TX_SHIFT);
  714. regmap_update_bits(cs35l41->regmap, CS35L41_SP_TX_WL,
  715. CS35L41_ASP_TX_WL_MASK,
  716. asp_wl << CS35L41_ASP_TX_WL_SHIFT);
  717. }
  718. return 0;
  719. }
  720. static int cs35l41_get_clk_config(int freq)
  721. {
  722. int i;
  723. for (i = 0; i < ARRAY_SIZE(cs35l41_pll_sysclk); i++) {
  724. if (cs35l41_pll_sysclk[i].freq == freq)
  725. return cs35l41_pll_sysclk[i].clk_cfg;
  726. }
  727. return -EINVAL;
  728. }
  729. static const unsigned int cs35l41_src_rates[] = {
  730. 8000, 12000, 11025, 16000, 22050, 24000, 32000,
  731. 44100, 48000, 88200, 96000, 176400, 192000
  732. };
  733. static const struct snd_pcm_hw_constraint_list cs35l41_constraints = {
  734. .count = ARRAY_SIZE(cs35l41_src_rates),
  735. .list = cs35l41_src_rates,
  736. };
  737. static int cs35l41_pcm_startup(struct snd_pcm_substream *substream,
  738. struct snd_soc_dai *dai)
  739. {
  740. if (substream->runtime)
  741. return snd_pcm_hw_constraint_list(substream->runtime, 0,
  742. SNDRV_PCM_HW_PARAM_RATE,
  743. &cs35l41_constraints);
  744. return 0;
  745. }
  746. static int cs35l41_component_set_sysclk(struct snd_soc_component *component,
  747. int clk_id, int source,
  748. unsigned int freq, int dir)
  749. {
  750. struct cs35l41_private *cs35l41 = snd_soc_component_get_drvdata(component);
  751. int extclk_cfg, clksrc;
  752. switch (clk_id) {
  753. case CS35L41_CLKID_SCLK:
  754. clksrc = CS35L41_PLLSRC_SCLK;
  755. break;
  756. case CS35L41_CLKID_LRCLK:
  757. clksrc = CS35L41_PLLSRC_LRCLK;
  758. break;
  759. case CS35L41_CLKID_MCLK:
  760. clksrc = CS35L41_PLLSRC_MCLK;
  761. break;
  762. default:
  763. dev_err(cs35l41->dev, "Invalid CLK Config\n");
  764. return -EINVAL;
  765. }
  766. extclk_cfg = cs35l41_get_clk_config(freq);
  767. if (extclk_cfg < 0) {
  768. dev_err(cs35l41->dev, "Invalid CLK Config: %d, freq: %u\n",
  769. extclk_cfg, freq);
  770. return -EINVAL;
  771. }
  772. regmap_update_bits(cs35l41->regmap, CS35L41_PLL_CLK_CTRL,
  773. CS35L41_PLL_OPENLOOP_MASK,
  774. 1 << CS35L41_PLL_OPENLOOP_SHIFT);
  775. regmap_update_bits(cs35l41->regmap, CS35L41_PLL_CLK_CTRL,
  776. CS35L41_REFCLK_FREQ_MASK,
  777. extclk_cfg << CS35L41_REFCLK_FREQ_SHIFT);
  778. regmap_update_bits(cs35l41->regmap, CS35L41_PLL_CLK_CTRL,
  779. CS35L41_PLL_CLK_EN_MASK,
  780. 0 << CS35L41_PLL_CLK_EN_SHIFT);
  781. regmap_update_bits(cs35l41->regmap, CS35L41_PLL_CLK_CTRL,
  782. CS35L41_PLL_CLK_SEL_MASK, clksrc);
  783. regmap_update_bits(cs35l41->regmap, CS35L41_PLL_CLK_CTRL,
  784. CS35L41_PLL_OPENLOOP_MASK,
  785. 0 << CS35L41_PLL_OPENLOOP_SHIFT);
  786. regmap_update_bits(cs35l41->regmap, CS35L41_PLL_CLK_CTRL,
  787. CS35L41_PLL_CLK_EN_MASK,
  788. 1 << CS35L41_PLL_CLK_EN_SHIFT);
  789. return 0;
  790. }
  791. static int cs35l41_dai_set_sysclk(struct snd_soc_dai *dai,
  792. int clk_id, unsigned int freq, int dir)
  793. {
  794. struct cs35l41_private *cs35l41 = snd_soc_component_get_drvdata(dai->component);
  795. unsigned int fs1_val;
  796. unsigned int fs2_val;
  797. unsigned int val;
  798. int fsindex;
  799. fsindex = cs35l41_get_fs_mon_config_index(freq);
  800. if (fsindex < 0) {
  801. dev_err(cs35l41->dev, "Invalid CLK Config freq: %u\n", freq);
  802. return -EINVAL;
  803. }
  804. dev_dbg(cs35l41->dev, "Set DAI sysclk %d\n", freq);
  805. if (freq <= 6144000) {
  806. /* Use the lookup table */
  807. fs1_val = cs35l41_fs_mon[fsindex].fs1;
  808. fs2_val = cs35l41_fs_mon[fsindex].fs2;
  809. } else {
  810. /* Use hard-coded values */
  811. fs1_val = 0x10;
  812. fs2_val = 0x24;
  813. }
  814. val = fs1_val;
  815. val |= (fs2_val << CS35L41_FS2_WINDOW_SHIFT) & CS35L41_FS2_WINDOW_MASK;
  816. regmap_write(cs35l41->regmap, CS35L41_TST_FS_MON0, val);
  817. return 0;
  818. }
  819. static int cs35l41_set_pdata(struct cs35l41_private *cs35l41)
  820. {
  821. struct cs35l41_hw_cfg *hw_cfg = &cs35l41->hw_cfg;
  822. int ret;
  823. if (!hw_cfg->valid)
  824. return -EINVAL;
  825. if (hw_cfg->bst_type == CS35L41_EXT_BOOST_NO_VSPK_SWITCH)
  826. return -EINVAL;
  827. /* Required */
  828. ret = cs35l41_init_boost(cs35l41->dev, cs35l41->regmap, hw_cfg);
  829. if (ret)
  830. return ret;
  831. /* Optional */
  832. if (hw_cfg->dout_hiz <= CS35L41_ASP_DOUT_HIZ_MASK && hw_cfg->dout_hiz >= 0)
  833. regmap_update_bits(cs35l41->regmap, CS35L41_SP_HIZ_CTRL, CS35L41_ASP_DOUT_HIZ_MASK,
  834. hw_cfg->dout_hiz);
  835. return 0;
  836. }
  837. static const struct snd_soc_dapm_route cs35l41_ext_bst_routes[] = {
  838. {"Main AMP", NULL, "VSPK"},
  839. };
  840. static const struct snd_soc_dapm_widget cs35l41_ext_bst_widget[] = {
  841. SND_SOC_DAPM_SUPPLY("VSPK", CS35L41_GPIO1_CTRL1, CS35L41_GPIO_LVL_SHIFT, 0, NULL, 0),
  842. };
  843. static int cs35l41_component_probe(struct snd_soc_component *component)
  844. {
  845. struct cs35l41_private *cs35l41 = snd_soc_component_get_drvdata(component);
  846. struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
  847. int ret;
  848. if (cs35l41->hw_cfg.bst_type == CS35L41_EXT_BOOST) {
  849. ret = snd_soc_dapm_new_controls(dapm, cs35l41_ext_bst_widget,
  850. ARRAY_SIZE(cs35l41_ext_bst_widget));
  851. if (ret)
  852. return ret;
  853. ret = snd_soc_dapm_add_routes(dapm, cs35l41_ext_bst_routes,
  854. ARRAY_SIZE(cs35l41_ext_bst_routes));
  855. if (ret)
  856. return ret;
  857. }
  858. return wm_adsp2_component_probe(&cs35l41->dsp, component);
  859. }
  860. static void cs35l41_component_remove(struct snd_soc_component *component)
  861. {
  862. struct cs35l41_private *cs35l41 = snd_soc_component_get_drvdata(component);
  863. wm_adsp2_component_remove(&cs35l41->dsp, component);
  864. }
  865. static const struct snd_soc_dai_ops cs35l41_ops = {
  866. .startup = cs35l41_pcm_startup,
  867. .set_fmt = cs35l41_set_dai_fmt,
  868. .hw_params = cs35l41_pcm_hw_params,
  869. .set_sysclk = cs35l41_dai_set_sysclk,
  870. .set_channel_map = cs35l41_set_channel_map,
  871. };
  872. static struct snd_soc_dai_driver cs35l41_dai[] = {
  873. {
  874. .name = "cs35l41-pcm",
  875. .id = 0,
  876. .playback = {
  877. .stream_name = "AMP Playback",
  878. .channels_min = 1,
  879. .channels_max = 2,
  880. .rates = SNDRV_PCM_RATE_KNOT,
  881. .formats = CS35L41_RX_FORMATS,
  882. },
  883. .capture = {
  884. .stream_name = "AMP Capture",
  885. .channels_min = 1,
  886. .channels_max = 4,
  887. .rates = SNDRV_PCM_RATE_KNOT,
  888. .formats = CS35L41_TX_FORMATS,
  889. },
  890. .ops = &cs35l41_ops,
  891. .symmetric_rate = 1,
  892. },
  893. };
  894. static const struct snd_soc_component_driver soc_component_dev_cs35l41 = {
  895. .name = "cs35l41-codec",
  896. .probe = cs35l41_component_probe,
  897. .remove = cs35l41_component_remove,
  898. .dapm_widgets = cs35l41_dapm_widgets,
  899. .num_dapm_widgets = ARRAY_SIZE(cs35l41_dapm_widgets),
  900. .dapm_routes = cs35l41_audio_map,
  901. .num_dapm_routes = ARRAY_SIZE(cs35l41_audio_map),
  902. .controls = cs35l41_aud_controls,
  903. .num_controls = ARRAY_SIZE(cs35l41_aud_controls),
  904. .set_sysclk = cs35l41_component_set_sysclk,
  905. .endianness = 1,
  906. };
  907. static int cs35l41_handle_pdata(struct device *dev, struct cs35l41_hw_cfg *hw_cfg)
  908. {
  909. struct cs35l41_gpio_cfg *gpio1 = &hw_cfg->gpio1;
  910. struct cs35l41_gpio_cfg *gpio2 = &hw_cfg->gpio2;
  911. unsigned int val;
  912. int ret;
  913. ret = device_property_read_u32(dev, "cirrus,boost-type", &val);
  914. if (ret >= 0)
  915. hw_cfg->bst_type = val;
  916. ret = device_property_read_u32(dev, "cirrus,boost-peak-milliamp", &val);
  917. if (ret >= 0)
  918. hw_cfg->bst_ipk = val;
  919. else
  920. hw_cfg->bst_ipk = -1;
  921. ret = device_property_read_u32(dev, "cirrus,boost-ind-nanohenry", &val);
  922. if (ret >= 0)
  923. hw_cfg->bst_ind = val;
  924. else
  925. hw_cfg->bst_ind = -1;
  926. ret = device_property_read_u32(dev, "cirrus,boost-cap-microfarad", &val);
  927. if (ret >= 0)
  928. hw_cfg->bst_cap = val;
  929. else
  930. hw_cfg->bst_cap = -1;
  931. ret = device_property_read_u32(dev, "cirrus,asp-sdout-hiz", &val);
  932. if (ret >= 0)
  933. hw_cfg->dout_hiz = val;
  934. else
  935. hw_cfg->dout_hiz = -1;
  936. /* GPIO1 Pin Config */
  937. gpio1->pol_inv = device_property_read_bool(dev, "cirrus,gpio1-polarity-invert");
  938. gpio1->out_en = device_property_read_bool(dev, "cirrus,gpio1-output-enable");
  939. ret = device_property_read_u32(dev, "cirrus,gpio1-src-select", &val);
  940. if (ret >= 0) {
  941. gpio1->func = val;
  942. gpio1->valid = true;
  943. }
  944. /* GPIO2 Pin Config */
  945. gpio2->pol_inv = device_property_read_bool(dev, "cirrus,gpio2-polarity-invert");
  946. gpio2->out_en = device_property_read_bool(dev, "cirrus,gpio2-output-enable");
  947. ret = device_property_read_u32(dev, "cirrus,gpio2-src-select", &val);
  948. if (ret >= 0) {
  949. gpio2->func = val;
  950. gpio2->valid = true;
  951. }
  952. hw_cfg->valid = true;
  953. return 0;
  954. }
  955. static int cs35l41_dsp_init(struct cs35l41_private *cs35l41)
  956. {
  957. struct wm_adsp *dsp;
  958. int ret;
  959. dsp = &cs35l41->dsp;
  960. dsp->part = "cs35l41";
  961. dsp->fw = 9; /* 9 is WM_ADSP_FW_SPK_PROT in wm_adsp.c */
  962. dsp->toggle_preload = true;
  963. cs35l41_configure_cs_dsp(cs35l41->dev, cs35l41->regmap, &dsp->cs_dsp);
  964. ret = cs35l41_write_fs_errata(cs35l41->dev, cs35l41->regmap);
  965. if (ret < 0)
  966. return ret;
  967. ret = wm_halo_init(dsp);
  968. if (ret) {
  969. dev_err(cs35l41->dev, "wm_halo_init failed: %d\n", ret);
  970. return ret;
  971. }
  972. ret = regmap_write(cs35l41->regmap, CS35L41_DSP1_RX5_SRC,
  973. CS35L41_INPUT_SRC_VPMON);
  974. if (ret < 0) {
  975. dev_err(cs35l41->dev, "Write INPUT_SRC_VPMON failed: %d\n", ret);
  976. goto err_dsp;
  977. }
  978. ret = regmap_write(cs35l41->regmap, CS35L41_DSP1_RX6_SRC,
  979. CS35L41_INPUT_SRC_CLASSH);
  980. if (ret < 0) {
  981. dev_err(cs35l41->dev, "Write INPUT_SRC_CLASSH failed: %d\n", ret);
  982. goto err_dsp;
  983. }
  984. ret = regmap_write(cs35l41->regmap, CS35L41_DSP1_RX7_SRC,
  985. CS35L41_INPUT_SRC_TEMPMON);
  986. if (ret < 0) {
  987. dev_err(cs35l41->dev, "Write INPUT_SRC_TEMPMON failed: %d\n", ret);
  988. goto err_dsp;
  989. }
  990. ret = regmap_write(cs35l41->regmap, CS35L41_DSP1_RX8_SRC,
  991. CS35L41_INPUT_SRC_RSVD);
  992. if (ret < 0) {
  993. dev_err(cs35l41->dev, "Write INPUT_SRC_RSVD failed: %d\n", ret);
  994. goto err_dsp;
  995. }
  996. return 0;
  997. err_dsp:
  998. wm_adsp2_remove(dsp);
  999. return ret;
  1000. }
  1001. static int cs35l41_acpi_get_name(struct cs35l41_private *cs35l41)
  1002. {
  1003. acpi_handle handle = ACPI_HANDLE(cs35l41->dev);
  1004. const char *sub;
  1005. /* If there is no ACPI_HANDLE, there is no ACPI for this system, return 0 */
  1006. if (!handle)
  1007. return 0;
  1008. sub = acpi_get_subsystem_id(handle);
  1009. if (IS_ERR(sub)) {
  1010. /* If bad ACPI, return 0 and fallback to legacy firmware path, otherwise fail */
  1011. if (PTR_ERR(sub) == -ENODATA)
  1012. return 0;
  1013. else
  1014. return PTR_ERR(sub);
  1015. }
  1016. cs35l41->dsp.system_name = sub;
  1017. dev_dbg(cs35l41->dev, "Subsystem ID: %s\n", cs35l41->dsp.system_name);
  1018. return 0;
  1019. }
  1020. int cs35l41_probe(struct cs35l41_private *cs35l41, const struct cs35l41_hw_cfg *hw_cfg)
  1021. {
  1022. u32 regid, reg_revid, i, mtl_revid, int_status, chipid_match;
  1023. int irq_pol = 0;
  1024. int ret;
  1025. if (hw_cfg) {
  1026. cs35l41->hw_cfg = *hw_cfg;
  1027. } else {
  1028. ret = cs35l41_handle_pdata(cs35l41->dev, &cs35l41->hw_cfg);
  1029. if (ret != 0)
  1030. return ret;
  1031. }
  1032. for (i = 0; i < CS35L41_NUM_SUPPLIES; i++)
  1033. cs35l41->supplies[i].supply = cs35l41_supplies[i];
  1034. ret = devm_regulator_bulk_get(cs35l41->dev, CS35L41_NUM_SUPPLIES,
  1035. cs35l41->supplies);
  1036. if (ret != 0) {
  1037. dev_err(cs35l41->dev, "Failed to request core supplies: %d\n", ret);
  1038. return ret;
  1039. }
  1040. ret = regulator_bulk_enable(CS35L41_NUM_SUPPLIES, cs35l41->supplies);
  1041. if (ret != 0) {
  1042. dev_err(cs35l41->dev, "Failed to enable core supplies: %d\n", ret);
  1043. return ret;
  1044. }
  1045. /* returning NULL can be an option if in stereo mode */
  1046. cs35l41->reset_gpio = devm_gpiod_get_optional(cs35l41->dev, "reset",
  1047. GPIOD_OUT_LOW);
  1048. if (IS_ERR(cs35l41->reset_gpio)) {
  1049. ret = PTR_ERR(cs35l41->reset_gpio);
  1050. cs35l41->reset_gpio = NULL;
  1051. if (ret == -EBUSY) {
  1052. dev_info(cs35l41->dev,
  1053. "Reset line busy, assuming shared reset\n");
  1054. } else {
  1055. dev_err(cs35l41->dev,
  1056. "Failed to get reset GPIO: %d\n", ret);
  1057. goto err;
  1058. }
  1059. }
  1060. if (cs35l41->reset_gpio) {
  1061. /* satisfy minimum reset pulse width spec */
  1062. usleep_range(2000, 2100);
  1063. gpiod_set_value_cansleep(cs35l41->reset_gpio, 1);
  1064. }
  1065. usleep_range(2000, 2100);
  1066. ret = regmap_read_poll_timeout(cs35l41->regmap, CS35L41_IRQ1_STATUS4,
  1067. int_status, int_status & CS35L41_OTP_BOOT_DONE,
  1068. 1000, 100000);
  1069. if (ret) {
  1070. dev_err(cs35l41->dev,
  1071. "Failed waiting for OTP_BOOT_DONE: %d\n", ret);
  1072. goto err;
  1073. }
  1074. regmap_read(cs35l41->regmap, CS35L41_IRQ1_STATUS3, &int_status);
  1075. if (int_status & CS35L41_OTP_BOOT_ERR) {
  1076. dev_err(cs35l41->dev, "OTP Boot error\n");
  1077. ret = -EINVAL;
  1078. goto err;
  1079. }
  1080. ret = regmap_read(cs35l41->regmap, CS35L41_DEVID, &regid);
  1081. if (ret < 0) {
  1082. dev_err(cs35l41->dev, "Get Device ID failed: %d\n", ret);
  1083. goto err;
  1084. }
  1085. ret = regmap_read(cs35l41->regmap, CS35L41_REVID, &reg_revid);
  1086. if (ret < 0) {
  1087. dev_err(cs35l41->dev, "Get Revision ID failed: %d\n", ret);
  1088. goto err;
  1089. }
  1090. mtl_revid = reg_revid & CS35L41_MTLREVID_MASK;
  1091. /* CS35L41 will have even MTLREVID
  1092. * CS35L41R will have odd MTLREVID
  1093. */
  1094. chipid_match = (mtl_revid % 2) ? CS35L41R_CHIP_ID : CS35L41_CHIP_ID;
  1095. if (regid != chipid_match) {
  1096. dev_err(cs35l41->dev, "CS35L41 Device ID (%X). Expected ID %X\n",
  1097. regid, chipid_match);
  1098. ret = -ENODEV;
  1099. goto err;
  1100. }
  1101. cs35l41_test_key_unlock(cs35l41->dev, cs35l41->regmap);
  1102. ret = cs35l41_register_errata_patch(cs35l41->dev, cs35l41->regmap, reg_revid);
  1103. if (ret)
  1104. goto err;
  1105. ret = cs35l41_otp_unpack(cs35l41->dev, cs35l41->regmap);
  1106. if (ret < 0) {
  1107. dev_err(cs35l41->dev, "OTP Unpack failed: %d\n", ret);
  1108. goto err;
  1109. }
  1110. cs35l41_test_key_lock(cs35l41->dev, cs35l41->regmap);
  1111. irq_pol = cs35l41_gpio_config(cs35l41->regmap, &cs35l41->hw_cfg);
  1112. /* Set interrupt masks for critical errors */
  1113. regmap_write(cs35l41->regmap, CS35L41_IRQ1_MASK1,
  1114. CS35L41_INT1_MASK_DEFAULT);
  1115. ret = devm_request_threaded_irq(cs35l41->dev, cs35l41->irq, NULL, cs35l41_irq,
  1116. IRQF_ONESHOT | IRQF_SHARED | irq_pol,
  1117. "cs35l41", cs35l41);
  1118. if (ret != 0) {
  1119. dev_err(cs35l41->dev, "Failed to request IRQ: %d\n", ret);
  1120. goto err;
  1121. }
  1122. ret = cs35l41_set_pdata(cs35l41);
  1123. if (ret < 0) {
  1124. dev_err(cs35l41->dev, "Set pdata failed: %d\n", ret);
  1125. goto err;
  1126. }
  1127. ret = cs35l41_acpi_get_name(cs35l41);
  1128. if (ret < 0)
  1129. goto err;
  1130. ret = cs35l41_dsp_init(cs35l41);
  1131. if (ret < 0)
  1132. goto err;
  1133. pm_runtime_set_autosuspend_delay(cs35l41->dev, 3000);
  1134. pm_runtime_use_autosuspend(cs35l41->dev);
  1135. pm_runtime_mark_last_busy(cs35l41->dev);
  1136. pm_runtime_set_active(cs35l41->dev);
  1137. pm_runtime_get_noresume(cs35l41->dev);
  1138. pm_runtime_enable(cs35l41->dev);
  1139. ret = devm_snd_soc_register_component(cs35l41->dev,
  1140. &soc_component_dev_cs35l41,
  1141. cs35l41_dai, ARRAY_SIZE(cs35l41_dai));
  1142. if (ret < 0) {
  1143. dev_err(cs35l41->dev, "Register codec failed: %d\n", ret);
  1144. goto err_pm;
  1145. }
  1146. pm_runtime_put_autosuspend(cs35l41->dev);
  1147. dev_info(cs35l41->dev, "Cirrus Logic CS35L41 (%x), Revision: %02X\n",
  1148. regid, reg_revid);
  1149. return 0;
  1150. err_pm:
  1151. pm_runtime_dont_use_autosuspend(cs35l41->dev);
  1152. pm_runtime_disable(cs35l41->dev);
  1153. pm_runtime_put_noidle(cs35l41->dev);
  1154. wm_adsp2_remove(&cs35l41->dsp);
  1155. err:
  1156. cs35l41_safe_reset(cs35l41->regmap, cs35l41->hw_cfg.bst_type);
  1157. regulator_bulk_disable(CS35L41_NUM_SUPPLIES, cs35l41->supplies);
  1158. gpiod_set_value_cansleep(cs35l41->reset_gpio, 0);
  1159. return ret;
  1160. }
  1161. EXPORT_SYMBOL_GPL(cs35l41_probe);
  1162. void cs35l41_remove(struct cs35l41_private *cs35l41)
  1163. {
  1164. pm_runtime_get_sync(cs35l41->dev);
  1165. pm_runtime_dont_use_autosuspend(cs35l41->dev);
  1166. pm_runtime_disable(cs35l41->dev);
  1167. regmap_write(cs35l41->regmap, CS35L41_IRQ1_MASK1, 0xFFFFFFFF);
  1168. kfree(cs35l41->dsp.system_name);
  1169. wm_adsp2_remove(&cs35l41->dsp);
  1170. cs35l41_safe_reset(cs35l41->regmap, cs35l41->hw_cfg.bst_type);
  1171. pm_runtime_put_noidle(cs35l41->dev);
  1172. regulator_bulk_disable(CS35L41_NUM_SUPPLIES, cs35l41->supplies);
  1173. gpiod_set_value_cansleep(cs35l41->reset_gpio, 0);
  1174. }
  1175. EXPORT_SYMBOL_GPL(cs35l41_remove);
  1176. static int __maybe_unused cs35l41_runtime_suspend(struct device *dev)
  1177. {
  1178. struct cs35l41_private *cs35l41 = dev_get_drvdata(dev);
  1179. dev_dbg(cs35l41->dev, "Runtime suspend\n");
  1180. if (!cs35l41->dsp.preloaded || !cs35l41->dsp.cs_dsp.running)
  1181. return 0;
  1182. cs35l41_enter_hibernate(dev, cs35l41->regmap, cs35l41->hw_cfg.bst_type);
  1183. regcache_cache_only(cs35l41->regmap, true);
  1184. regcache_mark_dirty(cs35l41->regmap);
  1185. return 0;
  1186. }
  1187. static int __maybe_unused cs35l41_runtime_resume(struct device *dev)
  1188. {
  1189. struct cs35l41_private *cs35l41 = dev_get_drvdata(dev);
  1190. int ret;
  1191. dev_dbg(cs35l41->dev, "Runtime resume\n");
  1192. if (!cs35l41->dsp.preloaded || !cs35l41->dsp.cs_dsp.running)
  1193. return 0;
  1194. regcache_cache_only(cs35l41->regmap, false);
  1195. ret = cs35l41_exit_hibernate(cs35l41->dev, cs35l41->regmap);
  1196. if (ret)
  1197. return ret;
  1198. /* Test key needs to be unlocked to allow the OTP settings to re-apply */
  1199. cs35l41_test_key_unlock(cs35l41->dev, cs35l41->regmap);
  1200. ret = regcache_sync(cs35l41->regmap);
  1201. cs35l41_test_key_lock(cs35l41->dev, cs35l41->regmap);
  1202. if (ret) {
  1203. dev_err(cs35l41->dev, "Failed to restore register cache: %d\n", ret);
  1204. return ret;
  1205. }
  1206. cs35l41_init_boost(cs35l41->dev, cs35l41->regmap, &cs35l41->hw_cfg);
  1207. return 0;
  1208. }
  1209. static int __maybe_unused cs35l41_sys_suspend(struct device *dev)
  1210. {
  1211. struct cs35l41_private *cs35l41 = dev_get_drvdata(dev);
  1212. dev_dbg(cs35l41->dev, "System suspend, disabling IRQ\n");
  1213. disable_irq(cs35l41->irq);
  1214. return 0;
  1215. }
  1216. static int __maybe_unused cs35l41_sys_suspend_noirq(struct device *dev)
  1217. {
  1218. struct cs35l41_private *cs35l41 = dev_get_drvdata(dev);
  1219. dev_dbg(cs35l41->dev, "Late system suspend, reenabling IRQ\n");
  1220. enable_irq(cs35l41->irq);
  1221. return 0;
  1222. }
  1223. static int __maybe_unused cs35l41_sys_resume_noirq(struct device *dev)
  1224. {
  1225. struct cs35l41_private *cs35l41 = dev_get_drvdata(dev);
  1226. dev_dbg(cs35l41->dev, "Early system resume, disabling IRQ\n");
  1227. disable_irq(cs35l41->irq);
  1228. return 0;
  1229. }
  1230. static int __maybe_unused cs35l41_sys_resume(struct device *dev)
  1231. {
  1232. struct cs35l41_private *cs35l41 = dev_get_drvdata(dev);
  1233. dev_dbg(cs35l41->dev, "System resume, reenabling IRQ\n");
  1234. enable_irq(cs35l41->irq);
  1235. return 0;
  1236. }
  1237. const struct dev_pm_ops cs35l41_pm_ops = {
  1238. SET_RUNTIME_PM_OPS(cs35l41_runtime_suspend, cs35l41_runtime_resume, NULL)
  1239. SET_SYSTEM_SLEEP_PM_OPS(cs35l41_sys_suspend, cs35l41_sys_resume)
  1240. SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(cs35l41_sys_suspend_noirq, cs35l41_sys_resume_noirq)
  1241. };
  1242. EXPORT_SYMBOL_GPL(cs35l41_pm_ops);
  1243. MODULE_DESCRIPTION("ASoC CS35L41 driver");
  1244. MODULE_AUTHOR("David Rhodes, Cirrus Logic Inc, <[email protected]>");
  1245. MODULE_LICENSE("GPL");