maxim_dsm.c 48 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162
  1. #include <linux/delay.h>
  2. #include <linux/i2c.h>
  3. #include <linux/module.h>
  4. #include <linux/regmap.h>
  5. #include <linux/slab.h>
  6. #include <sound/pcm.h>
  7. #include <sound/pcm_params.h>
  8. #include <sound/soc.h>
  9. #include <sound/tlv.h>
  10. #include <sound/maxim_dsm.h>
  11. #ifdef CONFIG_COMPAT
  12. #include <linux/compat.h>
  13. #endif /* CONFIG_COMPAT */
  14. #if defined(CONFIG_SND_SOC_QDSP6V2) || defined(CONFIG_SND_SOC_QDSP6)
  15. #include <sound/q6afe-v2.h>
  16. #endif /* CONFIG_SND_SOC_QDSP6V2 || CONFIG_SND_SOC_QDSP6 */
  17. #define DEBUG_MAXIM_DSM
  18. #ifdef DEBUG_MAXIM_DSM
  19. #define dbg_maxdsm(format, args...) \
  20. pr_info("[MAXIM_DSM] %s: " format "\n", __func__, ## args)
  21. #else
  22. #define dbg_maxdsm(format, args...)
  23. #endif /* DEBUG_MAXIM_DSM */
  24. static struct maxim_dsm maxdsm = {
  25. .regmap = NULL,
  26. .param_size = PARAM_DSM_3_5_MAX,
  27. .platform_type = PLATFORM_TYPE_A,
  28. .port_id = DSM_RX_PORT_ID,
  29. .rx_mod_id = AFE_PARAM_ID_ENABLE_DSM_RX,
  30. .tx_mod_id = AFE_PARAM_ID_ENABLE_DSM_TX,
  31. .filter_set = DSM_ID_FILTER_GET_AFE_PARAMS,
  32. .version = VERSION_3_5_A,
  33. .registered = 0,
  34. .update_cal = 0,
  35. .ignore_mask =
  36. MAXDSM_IGNORE_MASK_VOICE_COIL |
  37. MAXDSM_IGNORE_MASK_AMBIENT_TEMP,
  38. };
  39. module_param_named(ignore_mask, maxdsm.ignore_mask, uint,
  40. S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
  41. static struct param_set_data maxdsm_saved_params[] = {
  42. {
  43. .name = PARAM_FEATURE_SET,
  44. .value = 0x1F,
  45. },
  46. };
  47. static struct param_info g_pbi[(PARAM_A_DSM_4_0_MAX >> 1)] = {
  48. {
  49. .id = PARAM_A_VOICE_COIL_TEMP,
  50. .addr = 0x2A004C,
  51. .size = 2,
  52. .type = sizeof(uint32_t),
  53. .val = 0,
  54. },
  55. {
  56. .id = PARAM_A_EXCURSION,
  57. .addr = 0x2A004E,
  58. .size = 2,
  59. .type = sizeof(uint32_t),
  60. .val = 0,
  61. },
  62. {
  63. .id = PARAM_A_RDC,
  64. .addr = 0x2A0050,
  65. .size = 2,
  66. .type = sizeof(uint32_t),
  67. .val = 0,
  68. },
  69. {
  70. .id = PARAM_A_Q_LO,
  71. .addr = 0x2A0052,
  72. .size = 2,
  73. .type = sizeof(uint32_t),
  74. .val = 0,
  75. },
  76. {
  77. .id = PARAM_A_Q_HI,
  78. .addr = 0x2A0054,
  79. .size = 2,
  80. .type = sizeof(uint32_t),
  81. .val = 0,
  82. },
  83. {
  84. .id = PARAM_A_FRES_LO,
  85. .addr = 0x2A0056,
  86. .size = 2,
  87. .type = sizeof(uint32_t),
  88. .val = 0,
  89. },
  90. {
  91. .id = PARAM_A_FRES_HI,
  92. .addr = 0x2A0058,
  93. .size = 2,
  94. .type = sizeof(uint32_t),
  95. .val = 0,
  96. },
  97. {
  98. .id = PARAM_A_EXCUR_LIMIT,
  99. .addr = 0x2A005A,
  100. .size = 2,
  101. .type = sizeof(uint32_t),
  102. .val = 0,
  103. },
  104. {
  105. .id = PARAM_A_VOICE_COIL,
  106. .addr = 0x2A005C,
  107. .size = 2,
  108. .type = sizeof(uint32_t),
  109. .val = 0,
  110. },
  111. {
  112. .id = PARAM_A_THERMAL_LIMIT,
  113. .addr = 0x2A005E,
  114. .size = 2,
  115. .type = sizeof(uint32_t),
  116. .val = 0,
  117. },
  118. {
  119. .id = PARAM_A_RELEASE_TIME,
  120. .addr = 0x2A0060,
  121. .size = 2,
  122. .type = sizeof(uint32_t),
  123. .val = 0,
  124. },
  125. {
  126. .id = PARAM_A_ONOFF,
  127. .addr = 0x2A0062,
  128. .size = 2,
  129. .type = sizeof(uint32_t),
  130. .val = 0,
  131. },
  132. {
  133. .id = PARAM_A_STATIC_GAIN,
  134. .addr = 0x2A0064,
  135. .size = 2,
  136. .type = sizeof(uint32_t),
  137. .val = 0,
  138. },
  139. {
  140. .id = PARAM_A_LFX_GAIN,
  141. .addr = 0x2A0066,
  142. .size = 2,
  143. .type = sizeof(uint32_t),
  144. .val = 0,
  145. },
  146. {
  147. .id = PARAM_A_PILOT_GAIN,
  148. .addr = 0x2A0068,
  149. .size = 2,
  150. .type = sizeof(uint32_t),
  151. .val = 0,
  152. },
  153. {
  154. .id = PARAM_A_FEATURE_SET,
  155. .addr = 0x2A006A,
  156. .size = 2,
  157. .type = sizeof(uint32_t),
  158. .val = 0,
  159. },
  160. {
  161. .id = PARAM_A_SMOOTH_VOLT,
  162. .addr = 0x2A006C,
  163. .size = 2,
  164. .type = sizeof(uint32_t),
  165. .val = 0,
  166. },
  167. {
  168. .id = PARAM_A_HPF_CUTOFF,
  169. .addr = 0x2A006E,
  170. .size = 2,
  171. .type = sizeof(uint32_t),
  172. .val = 0,
  173. },
  174. {
  175. .id = PARAM_A_LEAD_R,
  176. .addr = 0x2A0070,
  177. .size = 2,
  178. .type = sizeof(uint32_t),
  179. .val = 0,
  180. },
  181. {
  182. .id = PARAM_A_RMS_SMOO_FAC,
  183. .addr = 0x2A0072,
  184. .size = 2,
  185. .type = sizeof(uint32_t),
  186. .val = 0,
  187. },
  188. {
  189. .id = PARAM_A_CLIP_LIMIT,
  190. .addr = 0x2A0074,
  191. .size = 2,
  192. .type = sizeof(uint32_t),
  193. .val = 0,
  194. },
  195. {
  196. .id = PARAM_A_THERMAL_COEF,
  197. .addr = 0x2A0076,
  198. .size = 2,
  199. .type = sizeof(uint32_t),
  200. .val = 0,
  201. },
  202. {
  203. .id = PARAM_A_QSPK,
  204. .addr = 0x2A0078,
  205. .size = 2,
  206. .type = sizeof(uint32_t),
  207. .val = 0,
  208. },
  209. {
  210. .id = PARAM_A_EXCUR_LOG_THRESH,
  211. .addr = 0x2A007A,
  212. .size = 2,
  213. .type = sizeof(uint32_t),
  214. .val = 0,
  215. },
  216. {
  217. .id = PARAM_A_TEMP_LOG_THRESH,
  218. .addr = 0x2A007C,
  219. .size = 2,
  220. .type = sizeof(uint32_t),
  221. .val = 0,
  222. },
  223. {
  224. .id = PARAM_A_RES_FREQ,
  225. .addr = 0x2A007E,
  226. .size = 2,
  227. .type = sizeof(uint32_t),
  228. .val = 0,
  229. },
  230. {
  231. .id = PARAM_A_RES_FREQ_GUARD_BAND,
  232. .addr = 0x2A0080,
  233. .size = 2,
  234. .type = sizeof(uint32_t),
  235. .val = 0,
  236. },
  237. {
  238. .id = PARAM_A_AMBIENT_TEMP,
  239. .addr = 0x2A0182,
  240. .size = 2,
  241. .type = sizeof(uint32_t),
  242. .val = 0,
  243. },
  244. {
  245. .id = PARAM_A_ADMITTANCE_A1,
  246. .addr = 0x2A0184,
  247. .size = 2,
  248. .type = sizeof(uint32_t),
  249. .val = 0,
  250. },
  251. {
  252. .id = PARAM_A_ADMITTANCE_A2,
  253. .addr = 0x2A0186,
  254. .size = 2,
  255. .type = sizeof(uint32_t),
  256. .val = 0,
  257. },
  258. {
  259. .id = PARAM_A_ADMITTANCE_B0,
  260. .addr = 0x2A0188,
  261. .size = 2,
  262. .type = sizeof(uint32_t),
  263. .val = 0,
  264. },
  265. {
  266. .id = PARAM_A_ADMITTANCE_B1,
  267. .addr = 0x2A018A,
  268. .size = 2,
  269. .type = sizeof(uint32_t),
  270. .val = 0,
  271. },
  272. {
  273. .id = PARAM_A_ADMITTANCE_B2,
  274. .addr = 0x2A018C,
  275. .size = 2,
  276. .type = sizeof(uint32_t),
  277. .val = 0,
  278. },
  279. {
  280. .id = PARAM_A_RTH1_HI,
  281. .addr = 0x2A018E,
  282. .size = 2,
  283. .type = sizeof(uint32_t),
  284. .val = 0,
  285. },
  286. {
  287. .id = PARAM_A_RTH1_LO,
  288. .addr = 0x2A0190,
  289. .size = 2,
  290. .type = sizeof(uint32_t),
  291. .val = 0,
  292. },
  293. {
  294. .id = PARAM_A_RTH2_HI,
  295. .addr = 0x2A0192,
  296. .size = 2,
  297. .type = sizeof(uint32_t),
  298. .val = 0,
  299. },
  300. {
  301. .id = PARAM_A_RTH2_LO,
  302. .addr = 0x2A0194,
  303. .size = 2,
  304. .type = sizeof(uint32_t),
  305. .val = 0,
  306. },
  307. {
  308. .id = PARAM_A_STL_ATENGAIN_HI,
  309. .addr = 0x2A0196,
  310. .size = 2,
  311. .type = sizeof(uint32_t),
  312. .val = 0,
  313. },
  314. {
  315. .id = PARAM_A_STL_ATENGAIN_LO,
  316. .addr = 0x2A0198,
  317. .size = 2,
  318. .type = sizeof(uint32_t),
  319. .val = 0,
  320. },
  321. {
  322. .id = PARAM_A_SPT_RAMP_DOWN_FRAMES,
  323. .addr = 0x2A019A,
  324. .size = 2,
  325. .type = sizeof(uint32_t),
  326. .val = 0,
  327. },
  328. {
  329. .id = PARAM_A_SPT_THRESHOLD_HI,
  330. .addr = 0x2A019C,
  331. .size = 2,
  332. .type = sizeof(uint32_t),
  333. .val = 0,
  334. },
  335. {
  336. .id = PARAM_A_SPT_THRESHOLD_LO,
  337. .addr = 0x2A019E,
  338. .size = 2,
  339. .type = sizeof(uint32_t),
  340. .val = 0,
  341. },
  342. {
  343. .id = PARAM_A_T_HORIZON,
  344. .addr = 0x2A01A0,
  345. .size = 2,
  346. .type = sizeof(uint32_t),
  347. .val = 0,
  348. },
  349. {
  350. .id = PARAM_A_LFX_ADMITTANCE_A1,
  351. .addr = 0x2A01A2,
  352. .size = 2,
  353. .type = sizeof(uint32_t),
  354. .val = 0,
  355. },
  356. {
  357. .id = PARAM_A_LFX_ADMITTANCE_A2,
  358. .addr = 0x2A01A4,
  359. .size = 2,
  360. .type = sizeof(uint32_t),
  361. .val = 0,
  362. },
  363. {
  364. .id = PARAM_A_LFX_ADMITTANCE_B0,
  365. .addr = 0x2A01A6,
  366. .size = 2,
  367. .type = sizeof(uint32_t),
  368. .val = 0,
  369. },
  370. {
  371. .id = PARAM_A_LFX_ADMITTANCE_B1,
  372. .addr = 0x2A01A8,
  373. .size = 2,
  374. .type = sizeof(uint32_t),
  375. .val = 0,
  376. },
  377. {
  378. .id = PARAM_A_LFX_ADMITTANCE_B2,
  379. .addr = 0x2A01AA,
  380. .size = 2,
  381. .type = sizeof(uint32_t),
  382. .val = 0,
  383. },
  384. {
  385. .id = PARAM_A_ALGORITHM_X_MAX,
  386. .addr = 0x2A01AC,
  387. .size = 2,
  388. .type = sizeof(uint32_t),
  389. .val = 0,
  390. },
  391. {
  392. .id = PARAM_A_STL_TCTH1_HI,
  393. .addr = 0x2A01AE,
  394. .size = 2,
  395. .type = sizeof(uint32_t),
  396. .val = 0,
  397. },
  398. {
  399. .id = PARAM_A_STL_TCTH1_LO,
  400. .addr = 0x2A01B0,
  401. .size = 2,
  402. .type = sizeof(uint32_t),
  403. .val = 0,
  404. },
  405. {
  406. .id = PARAM_A_STL_TCTH2_HI,
  407. .addr = 0x2A01B2,
  408. .size = 2,
  409. .type = sizeof(uint32_t),
  410. .val = 0,
  411. },
  412. {
  413. .id = PARAM_A_STL_TCTH2_LO,
  414. .addr = 0x2A01B4,
  415. .size = 2,
  416. .type = sizeof(uint32_t),
  417. .val = 0,
  418. },
  419. {
  420. .id = PARAM_A_STL_ATTACK_HI,
  421. .addr = 0x2A01B6,
  422. .size = 2,
  423. .type = sizeof(uint32_t),
  424. .val = 0,
  425. },
  426. {
  427. .id = PARAM_A_STL_ATTACK_LO,
  428. .addr = 0x2A01B8,
  429. .size = 2,
  430. .type = sizeof(uint32_t),
  431. .val = 0,
  432. },
  433. {
  434. .id = PARAM_A_STL_RELEASE_HI,
  435. .addr = 0x2A01BA,
  436. .size = 2,
  437. .type = sizeof(uint32_t),
  438. .val = 0,
  439. },
  440. {
  441. .id = PARAM_A_STL_RELEASE_LO,
  442. .addr = 0x2A01BC,
  443. .size = 2,
  444. .type = sizeof(uint32_t),
  445. .val = 0,
  446. },
  447. {
  448. .id = PARAM_A_STL_SPK_FS,
  449. .addr = 0x2A01BE,
  450. .size = 2,
  451. .type = sizeof(uint32_t),
  452. .val = 0,
  453. },
  454. {
  455. .id = PARAM_A_Q_GUARD_BAND_HI,
  456. .addr = 0x2A01C0,
  457. .size = 2,
  458. .type = sizeof(uint32_t),
  459. .val = 0,
  460. },
  461. {
  462. .id = PARAM_A_Q_GUARD_BAND_LO,
  463. .addr = 0x2A01C2,
  464. .size = 2,
  465. .type = sizeof(uint32_t),
  466. .val = 0,
  467. },
  468. {
  469. .id = PARAM_A_STIMPEDMODEL_COEFFS_A1_HI,
  470. .addr = 0x2A01C4,
  471. .size = 2,
  472. .type = sizeof(uint32_t),
  473. .val = 0,
  474. },
  475. {
  476. .id = PARAM_A_STIMPEDMODEL_COEFFS_A1_LO,
  477. .addr = 0x2A01C6,
  478. .size = 2,
  479. .type = sizeof(uint32_t),
  480. .val = 0,
  481. },
  482. {
  483. .id = PARAM_A_STIMPEDMODEL_COEFFS_A2_HI,
  484. .addr = 0x2A01C8,
  485. .size = 2,
  486. .type = sizeof(uint32_t),
  487. .val = 0,
  488. },
  489. {
  490. .id = PARAM_A_STIMPEDMODEL_COEFFS_A2_LO,
  491. .addr = 0x2A01CA,
  492. .size = 2,
  493. .type = sizeof(uint32_t),
  494. .val = 0,
  495. },
  496. {
  497. .id = PARAM_A_STIMPEDMODEL_COEFFS_B0_HI,
  498. .addr = 0x2A01CC,
  499. .size = 2,
  500. .type = sizeof(uint32_t),
  501. .val = 0,
  502. },
  503. {
  504. .id = PARAM_A_STIMPEDMODEL_COEFFS_B0_LO,
  505. .addr = 0x2A01CE,
  506. .size = 2,
  507. .type = sizeof(uint32_t),
  508. .val = 0,
  509. },
  510. {
  511. .id = PARAM_A_STIMPEDMODEL_COEFFS_B1_HI,
  512. .addr = 0x2A01D0,
  513. .size = 2,
  514. .type = sizeof(uint32_t),
  515. .val = 0,
  516. },
  517. {
  518. .id = PARAM_A_STIMPEDMODEL_COEFFS_B1_LO,
  519. .addr = 0x2A01D2,
  520. .size = 2,
  521. .type = sizeof(uint32_t),
  522. .val = 0,
  523. },
  524. {
  525. .id = PARAM_A_STIMPEDMODEL_COEFFS_B2_HI,
  526. .addr = 0x2A01D4,
  527. .size = 2,
  528. .type = sizeof(uint32_t),
  529. .val = 0,
  530. },
  531. {
  532. .id = PARAM_A_STIMPEDMODEL_COEFFS_B2_LO,
  533. .addr = 0x2A01D6,
  534. .size = 2,
  535. .type = sizeof(uint32_t),
  536. .val = 0,
  537. },
  538. {
  539. .id = PARAM_A_STIMPEDMODEL_FLAG,
  540. .addr = 0x2A01D8,
  541. .size = 2,
  542. .type = sizeof(uint32_t),
  543. .val = 0,
  544. },
  545. {
  546. .id = PARAM_A_Q_NOTCH_HI,
  547. .addr = 0x2A01DA,
  548. .size = 2,
  549. .type = sizeof(uint32_t),
  550. .val = 0,
  551. },
  552. {
  553. .id = PARAM_A_Q_NOTCH_LO,
  554. .addr = 0x2A01DC,
  555. .size = 2,
  556. .type = sizeof(uint32_t),
  557. .val = 0,
  558. },
  559. };
  560. static DEFINE_MUTEX(dsm_fs_lock);
  561. static DEFINE_MUTEX(dsm_dsp_lock);
  562. #ifdef USE_DSM_LOG
  563. static DEFINE_MUTEX(maxdsm_log_lock);
  564. static uint32_t ex_seq_count_temp;
  565. static uint32_t ex_seq_count_excur;
  566. static uint32_t new_log_avail;
  567. static int maxdsm_log_present;
  568. static struct tm maxdsm_log_timestamp;
  569. static uint8_t maxdsm_byte_log_array[BEFORE_BUFSIZE];
  570. static uint32_t maxdsm_int_log_array[BEFORE_BUFSIZE];
  571. static uint8_t maxdsm_after_prob_byte_log_array[AFTER_BUFSIZE];
  572. static uint32_t maxdsm_after_prob_int_log_array[AFTER_BUFSIZE];
  573. static struct param_info g_lbi[MAX_LOG_BUFFER_POS] = {
  574. {
  575. .id = WRITE_PROTECT,
  576. .addr = 0x2A0082,
  577. .size = 2,
  578. },
  579. {
  580. .id = LOG_AVAILABLE,
  581. .addr = 0x2A0084,
  582. .size = 2,
  583. .type = sizeof(uint8_t),
  584. },
  585. {
  586. .id = VERSION_INFO,
  587. .addr = 0x2A0086,
  588. .size = 2,
  589. .type = sizeof(uint8_t),
  590. },
  591. {
  592. .id = LAST_2_SEC_TEMP,
  593. .addr = 0x2A0088,
  594. .size = 20,
  595. .type = sizeof(uint8_t),
  596. },
  597. {
  598. .id = LAST_2_SEC_EXCUR,
  599. .addr = 0x2A009C,
  600. .size = 20,
  601. .type = sizeof(uint8_t),
  602. },
  603. {
  604. .id = RESERVED_1,
  605. .addr = 0x2A00B0,
  606. .size = 2,
  607. },
  608. {
  609. .id = SEQUENCE_OF_TEMP,
  610. .addr = 0x2A00B2,
  611. .size = 2,
  612. .type = sizeof(uint32_t),
  613. },
  614. {
  615. .id = SEQUENCE_OF_EXCUR,
  616. .addr = 0x2A00B4,
  617. .size = 2,
  618. .type = sizeof(uint32_t),
  619. },
  620. {
  621. .id = LAST_2_SEC_RDC,
  622. .addr = 0x2A00B6,
  623. .size = 20,
  624. .type = sizeof(uint32_t),
  625. },
  626. {
  627. .id = LAST_2_SEC_FREQ,
  628. .addr = 0x2A00CA,
  629. .size = 20,
  630. .type = sizeof(uint32_t),
  631. },
  632. {
  633. .id = RESERVED_2,
  634. .addr = 0x2A00DE,
  635. .size = 2,
  636. },
  637. {
  638. .id = RESERVED_3,
  639. .addr = 0x2A00E0,
  640. .size = 2,
  641. },
  642. {
  643. .id = AFTER_2_SEC_TEMP_TEMP,
  644. .addr = 0x2A00E2,
  645. .size = 20,
  646. .type = sizeof(uint8_t) * 2,
  647. },
  648. {
  649. .id = AFTER_2_SEC_EXCUR_TEMP,
  650. .addr = 0x2A00F6,
  651. .size = 20,
  652. .type = sizeof(uint8_t) * 2,
  653. },
  654. {
  655. .id = AFTER_2_SEC_TEMP_EXCUR,
  656. .addr = 0x2A010A,
  657. .size = 20,
  658. .type = sizeof(uint8_t) * 2,
  659. },
  660. {
  661. .id = AFTER_2_SEC_EXCUR_EXCUR,
  662. .addr = 0x2A011E,
  663. .size = 20,
  664. .type = sizeof(uint8_t) * 2,
  665. },
  666. {
  667. .id = AFTER_2_SEC_RDC_TEMP,
  668. .addr = 0x2A0132,
  669. .size = 20,
  670. .type = sizeof(uint32_t) * 2,
  671. },
  672. {
  673. .id = AFTER_2_SEC_FREQ_TEMP,
  674. .addr = 0x2A0146,
  675. .size = 20,
  676. .type = sizeof(uint32_t) * 2,
  677. },
  678. {
  679. .id = AFTER_2_SEC_RDC_EXCUR,
  680. .addr = 0x2A015A,
  681. .size = 20,
  682. .type = sizeof(uint32_t) * 2,
  683. },
  684. {
  685. .id = AFTER_2_SEC_FREQ_EXCUR,
  686. .addr = 0x2A016E,
  687. .size = 20,
  688. .type = sizeof(uint32_t) * 2,
  689. },
  690. };
  691. #endif /* USE_DSM_LOG */
  692. #if !defined(CONFIG_SND_SOC_QDSP6V2) && !defined(CONFIG_SND_SOC_QDSP6)
  693. static inline int32_t dsm_open(void *data)
  694. {
  695. return 0;
  696. }
  697. #endif /* !CONFIG_SND_SOC_QDSP6V2 && !CONFIG_SND_SOC_QDSP6 */
  698. static inline int32_t maxdsm_dsm_open(void *data)
  699. {
  700. int32_t ret;
  701. if (maxdsm.ignore_mask == MAXDSM_IGNORE_MASK_ALL &&
  702. maxdsm.filter_set == DSM_ID_FILTER_SET_AFE_CNTRLS)
  703. return -EPERM;
  704. mutex_lock(&dsm_dsp_lock);
  705. ret = dsm_open(data);
  706. mutex_unlock(&dsm_dsp_lock);
  707. return ret;
  708. }
  709. void maxdsm_set_regmap(struct regmap *regmap)
  710. {
  711. maxdsm.regmap = regmap;
  712. dbg_maxdsm("Regmap for maxdsm was set by 0x%p",
  713. maxdsm.regmap);
  714. }
  715. EXPORT_SYMBOL_GPL(maxdsm_set_regmap);
  716. static int maxdsm_check_ignore_mask(uint32_t reg, uint32_t mask)
  717. {
  718. int ret = 0;
  719. if ((mask & MAXDSM_IGNORE_MASK_VOICE_COIL) &&
  720. (reg == g_pbi[PARAM_A_VOICE_COIL >> 1].addr))
  721. ret = -EPERM;
  722. else if ((mask & MAXDSM_IGNORE_MASK_AMBIENT_TEMP) &&
  723. (reg == g_pbi[PARAM_A_AMBIENT_TEMP >> 1].addr))
  724. ret = -EPERM;
  725. else if (mask & MAXDSM_IGNORE_MASK_ALL)
  726. ret = -EPERM;
  727. return ret;
  728. }
  729. static int maxdsm_regmap_read(unsigned int reg,
  730. unsigned int *val)
  731. {
  732. return maxdsm.regmap ?
  733. regmap_read(maxdsm.regmap, reg, val) : -ENXIO;
  734. }
  735. static int maxdsm_regmap_write(unsigned int reg,
  736. unsigned int val)
  737. {
  738. if (maxdsm_check_ignore_mask(reg, maxdsm.ignore_mask)) {
  739. dbg_maxdsm("Ignored 0x%x register", reg);
  740. return 0;
  741. }
  742. return maxdsm.regmap ?
  743. regmap_write(maxdsm.regmap, reg, val) : -ENXIO;
  744. }
  745. static void maxdsm_read_all(void)
  746. {
  747. switch (maxdsm.platform_type) {
  748. case PLATFORM_TYPE_A:
  749. {
  750. int param_idx, pbi_idx = 0;
  751. uint32_t data;
  752. while (pbi_idx++ < (maxdsm.param_size >> 1)) {
  753. param_idx = (pbi_idx - 1) << 1;
  754. data = 0;
  755. maxdsm_regmap_read(g_pbi[pbi_idx - 1].addr, &data);
  756. maxdsm.param[param_idx] = data;
  757. maxdsm.param[param_idx + 1] =
  758. (1 << maxdsm.binfo[pbi_idx - 1]);
  759. dbg_maxdsm("[%d,%d]: 0x%08x / 0x%08x (addr:0x%08x",
  760. param_idx, param_idx + 1,
  761. maxdsm.param[param_idx],
  762. maxdsm.param[param_idx + 1],
  763. g_pbi[pbi_idx - 1].addr);
  764. }
  765. break;
  766. }
  767. case PLATFORM_TYPE_B:
  768. maxdsm.filter_set = DSM_ID_FILTER_GET_AFE_PARAMS;
  769. maxdsm_dsm_open(&maxdsm);
  770. break;
  771. }
  772. }
  773. static void maxdsm_write_all(void)
  774. {
  775. switch (maxdsm.platform_type) {
  776. case PLATFORM_TYPE_A:
  777. {
  778. int param_idx, pbi_idx = 0;
  779. while (pbi_idx++ < (maxdsm.param_size >> 1)) {
  780. param_idx = (pbi_idx - 1) << 1;
  781. maxdsm_regmap_write(
  782. g_pbi[pbi_idx - 1].addr,
  783. maxdsm.param[param_idx]);
  784. dbg_maxdsm("[%d,%d]: 0x%08x / 0x%08x (0x%08x)",
  785. param_idx, param_idx + 1,
  786. maxdsm.param[param_idx],
  787. maxdsm.param[param_idx + 1],
  788. g_pbi[pbi_idx - 1].addr);
  789. }
  790. break;
  791. }
  792. case PLATFORM_TYPE_B:
  793. maxdsm.filter_set = DSM_ID_FILTER_SET_AFE_CNTRLS;
  794. maxdsm_dsm_open(&maxdsm);
  795. break;
  796. }
  797. }
  798. static int maxdsm_read_wrapper(unsigned int reg,
  799. unsigned int *val)
  800. {
  801. switch (maxdsm.platform_type) {
  802. case PLATFORM_TYPE_A:
  803. if (reg >= START_ADDR_FOR_LSI &&
  804. reg <= END_ADDR_FOR_LSI)
  805. maxdsm_regmap_read(reg, val);
  806. break;
  807. case PLATFORM_TYPE_B:
  808. if (reg < PARAM_DSM_4_0_MAX) {
  809. maxdsm_read_all();
  810. *val = maxdsm.param[reg];
  811. }
  812. break;
  813. }
  814. return *val;
  815. }
  816. static int maxdsm_write_wrapper(unsigned int reg,
  817. unsigned int val, unsigned int flag)
  818. {
  819. int ret = -ENODATA;
  820. switch (maxdsm.platform_type) {
  821. case PLATFORM_TYPE_A:
  822. maxdsm_regmap_write(reg, val);
  823. maxdsm_regmap_read(reg, &ret);
  824. break;
  825. case PLATFORM_TYPE_B:
  826. if (reg > maxdsm.param_size)
  827. pr_err("%s: Unknown parameter index. %d\n",
  828. __func__, reg);
  829. else {
  830. maxdsm.param[PARAM_WRITE_FLAG] = flag;
  831. maxdsm.param[reg] = val;
  832. maxdsm_write_all();
  833. maxdsm_read_all();
  834. ret = maxdsm.param[reg];
  835. }
  836. break;
  837. }
  838. return ret;
  839. }
  840. #ifdef USE_DSM_LOG
  841. void maxdsm_log_update(const void *byte_log_array,
  842. const void *int_log_array,
  843. const void *after_prob_byte_log_array,
  844. const void *after_prob_int_log_array)
  845. {
  846. struct timeval tv;
  847. mutex_lock(&maxdsm_log_lock);
  848. memcpy(maxdsm_byte_log_array,
  849. byte_log_array, sizeof(maxdsm_byte_log_array));
  850. memcpy(maxdsm_int_log_array,
  851. int_log_array, sizeof(maxdsm_int_log_array));
  852. memcpy(maxdsm_after_prob_byte_log_array,
  853. after_prob_byte_log_array,
  854. sizeof(maxdsm_after_prob_byte_log_array));
  855. memcpy(maxdsm_after_prob_int_log_array,
  856. after_prob_int_log_array,
  857. sizeof(maxdsm_after_prob_int_log_array));
  858. do_gettimeofday(&tv);
  859. time_to_tm(tv.tv_sec, 0, &maxdsm_log_timestamp);
  860. maxdsm_log_present = 1;
  861. mutex_unlock(&maxdsm_log_lock);
  862. }
  863. EXPORT_SYMBOL_GPL(maxdsm_log_update);
  864. void maxdsm_read_logbuf_reg(void)
  865. {
  866. int idx;
  867. int b_idx, i_idx;
  868. int apb_idx, api_idx;
  869. int loop;
  870. uint32_t data;
  871. struct timeval tv;
  872. switch (maxdsm.platform_type) {
  873. case PLATFORM_TYPE_B:
  874. return;
  875. }
  876. mutex_lock(&maxdsm_log_lock);
  877. /* If the following variables are not initialized,
  878. * these can not have zero data on some linux platform.
  879. */
  880. idx = b_idx = i_idx = apb_idx = api_idx = 0;
  881. while (idx < MAX_LOG_BUFFER_POS) {
  882. for (loop = 0; loop < g_lbi[idx].size; loop += 2) {
  883. if (!g_lbi[idx].type)
  884. continue;
  885. maxdsm_regmap_read(g_lbi[idx].addr + loop, &data);
  886. switch (g_lbi[idx].type) {
  887. case sizeof(uint8_t):
  888. maxdsm_byte_log_array[b_idx++] =
  889. data & 0xFF;
  890. break;
  891. case sizeof(uint32_t):
  892. maxdsm_int_log_array[i_idx++] =
  893. data & 0xFFFFFFFF;
  894. break;
  895. case sizeof(uint8_t)*2:
  896. maxdsm_after_prob_byte_log_array[apb_idx++] =
  897. data & 0xFF;
  898. break;
  899. case sizeof(uint32_t)*2:
  900. maxdsm_after_prob_int_log_array[api_idx++] =
  901. data & 0xFFFFFFFF;
  902. break;
  903. }
  904. }
  905. idx++;
  906. }
  907. do_gettimeofday(&tv);
  908. time_to_tm(tv.tv_sec, 0, &maxdsm_log_timestamp);
  909. maxdsm_log_present = 1;
  910. mutex_unlock(&maxdsm_log_lock);
  911. }
  912. int maxdsm_get_dump_status(void)
  913. {
  914. int ret = 0;
  915. switch (maxdsm.platform_type) {
  916. case PLATFORM_TYPE_A:
  917. ret = maxdsm_regmap_read(g_lbi[LOG_AVAILABLE].addr,
  918. &new_log_avail);
  919. break;
  920. }
  921. return !ret ? (new_log_avail & 0x03) : ret;
  922. }
  923. EXPORT_SYMBOL_GPL(maxdsm_get_dump_status);
  924. void maxdsm_update_param(void)
  925. {
  926. switch (maxdsm.platform_type) {
  927. case PLATFORM_TYPE_A:
  928. maxdsm_regmap_write(g_lbi[WRITE_PROTECT].addr, 1);
  929. maxdsm_read_logbuf_reg();
  930. maxdsm_regmap_write(g_lbi[WRITE_PROTECT].addr, 0);
  931. break;
  932. case PLATFORM_TYPE_B:
  933. maxdsm.filter_set = DSM_ID_FILTER_GET_AFE_PARAMS;
  934. maxdsm_dsm_open(&maxdsm);
  935. if (maxdsm.param[PARAM_EXCUR_LIMIT] != 0
  936. && maxdsm.param[PARAM_THERMAL_LIMIT] != 0)
  937. new_log_avail |= 0x1;
  938. break;
  939. }
  940. }
  941. EXPORT_SYMBOL_GPL(maxdsm_update_param);
  942. static void maxdsm_log_free(void **byte_log_array, void **int_log_array,
  943. void **afterbyte_log_array, void **after_int_log_array)
  944. {
  945. if (likely(*byte_log_array)) {
  946. kfree(*byte_log_array);
  947. *byte_log_array = NULL;
  948. }
  949. if (likely(*int_log_array)) {
  950. kfree(*int_log_array);
  951. *int_log_array = NULL;
  952. }
  953. if (likely(*afterbyte_log_array)) {
  954. kfree(*afterbyte_log_array);
  955. *afterbyte_log_array = NULL;
  956. }
  957. if (likely(*after_int_log_array)) {
  958. kfree(*after_int_log_array);
  959. *after_int_log_array = NULL;
  960. }
  961. }
  962. static int maxdsm_log_duplicate(void **byte_log_array, void **int_log_array,
  963. void **afterbyte_log_array, void **after_int_log_array)
  964. {
  965. void *blog_buf = NULL, *ilog_buf = NULL;
  966. void *after_blog_buf = NULL, *after_ilog_buf = NULL;
  967. int rc = 0;
  968. mutex_lock(&maxdsm_log_lock);
  969. if (unlikely(!maxdsm_log_present)) {
  970. rc = -ENODATA;
  971. goto abort;
  972. }
  973. blog_buf = kzalloc(sizeof(maxdsm_byte_log_array), GFP_KERNEL);
  974. ilog_buf = kzalloc(sizeof(maxdsm_int_log_array), GFP_KERNEL);
  975. after_blog_buf
  976. = kzalloc(sizeof(maxdsm_after_prob_byte_log_array), GFP_KERNEL);
  977. after_ilog_buf
  978. = kzalloc(sizeof(maxdsm_after_prob_int_log_array), GFP_KERNEL);
  979. if (unlikely(!blog_buf || !ilog_buf
  980. || !after_blog_buf || !after_ilog_buf)) {
  981. rc = -ENOMEM;
  982. goto abort;
  983. }
  984. memcpy(blog_buf, maxdsm_byte_log_array, sizeof(maxdsm_byte_log_array));
  985. memcpy(ilog_buf, maxdsm_int_log_array, sizeof(maxdsm_int_log_array));
  986. memcpy(after_blog_buf, maxdsm_after_prob_byte_log_array,
  987. sizeof(maxdsm_after_prob_byte_log_array));
  988. memcpy(after_ilog_buf, maxdsm_after_prob_int_log_array,
  989. sizeof(maxdsm_after_prob_int_log_array));
  990. goto out;
  991. abort:
  992. maxdsm_log_free(&blog_buf, &ilog_buf, &after_blog_buf, &after_ilog_buf);
  993. out:
  994. *byte_log_array = blog_buf;
  995. *int_log_array = ilog_buf;
  996. *afterbyte_log_array = after_blog_buf;
  997. *after_int_log_array = after_ilog_buf;
  998. mutex_unlock(&maxdsm_log_lock);
  999. return rc;
  1000. }
  1001. ssize_t maxdsm_log_prepare(char *buf)
  1002. {
  1003. uint8_t *byte_log_array = NULL;
  1004. uint32_t *int_log_array = NULL;
  1005. uint8_t *afterbyte_log_array = NULL;
  1006. uint32_t *after_int_log_array = NULL;
  1007. int rc = 0;
  1008. uint8_t log_available;
  1009. uint8_t version_id;
  1010. uint8_t *coil_temp_log_array;
  1011. uint8_t *excur_log_array;
  1012. uint8_t *after_coil_temp_log_array;
  1013. uint8_t *after_excur_log_array;
  1014. uint8_t *excur_after_coil_temp_log_array;
  1015. uint8_t *excur_after_excur_log_array;
  1016. uint32_t seq_count_temp;
  1017. uint32_t seq_count_excur;
  1018. uint32_t *rdc_log_array;
  1019. uint32_t *freq_log_array;
  1020. uint32_t *after_rdc_log_array;
  1021. uint32_t *after_freq_log_array;
  1022. uint32_t *excur_after_rdc_log_array;
  1023. uint32_t *excur_after_freq_log_array;
  1024. int param_excur_limit = PARAM_A_EXCUR_LIMIT;
  1025. int param_thermal_limit = PARAM_A_THERMAL_LIMIT;
  1026. int param_voice_coil = PARAM_A_VOICE_COIL;
  1027. int param_release_time = PARAM_A_RELEASE_TIME;
  1028. int param_static_gain = PARAM_A_STATIC_GAIN;
  1029. int param_lfx_gain = PARAM_A_LFX_GAIN;
  1030. int param_pilot_gain = PARAM_A_PILOT_GAIN;
  1031. rc = maxdsm_log_duplicate((void **)&byte_log_array,
  1032. (void **)&int_log_array, (void **)&afterbyte_log_array,
  1033. (void **)&after_int_log_array);
  1034. switch (maxdsm.platform_type) {
  1035. case PLATFORM_TYPE_A:
  1036. /* Already initialized */
  1037. break;
  1038. case PLATFORM_TYPE_B:
  1039. param_excur_limit = PARAM_EXCUR_LIMIT;
  1040. param_thermal_limit = PARAM_THERMAL_LIMIT;
  1041. param_voice_coil = PARAM_VOICE_COIL;
  1042. param_release_time = PARAM_RELEASE_TIME;
  1043. param_static_gain = PARAM_STATIC_GAIN;
  1044. param_lfx_gain = PARAM_LFX_GAIN;
  1045. param_pilot_gain = PARAM_PILOT_GAIN;
  1046. break;
  1047. }
  1048. if (unlikely(rc)) {
  1049. rc = snprintf(buf, PAGE_SIZE, "no log\n");
  1050. if (maxdsm.param[param_excur_limit] != 0 &&
  1051. maxdsm.param[param_thermal_limit] != 0) {
  1052. rc += snprintf(buf+rc, PAGE_SIZE,
  1053. "[Parameter Set] excursionlimit:0x%x, ",
  1054. maxdsm.param[param_excur_limit]);
  1055. rc += snprintf(buf+rc, PAGE_SIZE,
  1056. "rdcroomtemp:0x%x, coilthermallimit:0x%x, ",
  1057. maxdsm.param[param_voice_coil],
  1058. maxdsm.param[param_thermal_limit]);
  1059. rc += snprintf(buf+rc, PAGE_SIZE,
  1060. "releasetime:0x%x\n",
  1061. maxdsm.param[param_release_time]);
  1062. rc += snprintf(buf+rc, PAGE_SIZE,
  1063. "[Parameter Set] staticgain:0x%x, ",
  1064. maxdsm.param[param_static_gain]);
  1065. rc += snprintf(buf+rc, PAGE_SIZE,
  1066. "lfxgain:0x%x, pilotgain:0x%0x\n",
  1067. maxdsm.param[param_lfx_gain],
  1068. maxdsm.param[param_pilot_gain]);
  1069. }
  1070. goto out;
  1071. }
  1072. log_available = byte_log_array[0];
  1073. version_id = byte_log_array[1];
  1074. coil_temp_log_array = &byte_log_array[2];
  1075. excur_log_array = &byte_log_array[2+LOG_BUFFER_ARRAY_SIZE];
  1076. seq_count_temp = int_log_array[0];
  1077. seq_count_excur = int_log_array[1];
  1078. rdc_log_array = &int_log_array[2];
  1079. freq_log_array = &int_log_array[2+LOG_BUFFER_ARRAY_SIZE];
  1080. after_coil_temp_log_array = &afterbyte_log_array[0];
  1081. after_excur_log_array = &afterbyte_log_array[LOG_BUFFER_ARRAY_SIZE];
  1082. after_rdc_log_array = &after_int_log_array[0];
  1083. after_freq_log_array = &after_int_log_array[LOG_BUFFER_ARRAY_SIZE];
  1084. excur_after_coil_temp_log_array
  1085. = &afterbyte_log_array[LOG_BUFFER_ARRAY_SIZE*2];
  1086. excur_after_excur_log_array
  1087. = &afterbyte_log_array[LOG_BUFFER_ARRAY_SIZE*3];
  1088. excur_after_rdc_log_array
  1089. = &after_int_log_array[LOG_BUFFER_ARRAY_SIZE*2];
  1090. excur_after_freq_log_array
  1091. = &after_int_log_array[LOG_BUFFER_ARRAY_SIZE*3];
  1092. if (log_available > 0 &&
  1093. (ex_seq_count_temp != seq_count_temp
  1094. || ex_seq_count_excur != seq_count_excur)) {
  1095. ex_seq_count_temp = seq_count_temp;
  1096. ex_seq_count_excur = seq_count_excur;
  1097. new_log_avail |= 0x2;
  1098. }
  1099. rc += snprintf(buf+rc, PAGE_SIZE,
  1100. "DSM LogData saved at %4d-%02d-%02d %02d:%02d:%02d (UTC)\n",
  1101. (int)(maxdsm_log_timestamp.tm_year + 1900),
  1102. (int)(maxdsm_log_timestamp.tm_mon + 1),
  1103. (int)(maxdsm_log_timestamp.tm_mday),
  1104. (int)(maxdsm_log_timestamp.tm_hour),
  1105. (int)(maxdsm_log_timestamp.tm_min),
  1106. (int)(maxdsm_log_timestamp.tm_sec));
  1107. if ((log_available & 0x1) == 0x1) {
  1108. rc += snprintf(buf+rc, PAGE_SIZE,
  1109. "*** Excursion Limit was exceeded.\n");
  1110. rc += snprintf(buf+rc, PAGE_SIZE,
  1111. "Seq:%d, log_available=%d, version_id:3.1.%d\n",
  1112. seq_count_excur, log_available, version_id);
  1113. rc += snprintf(buf+rc, PAGE_SIZE,
  1114. "Temperature={ %d, %d, %d, %d, %d, %d, %d, %d, %d, %d }\n",
  1115. excur_after_coil_temp_log_array[0],
  1116. excur_after_coil_temp_log_array[1],
  1117. excur_after_coil_temp_log_array[2],
  1118. excur_after_coil_temp_log_array[3],
  1119. excur_after_coil_temp_log_array[4],
  1120. excur_after_coil_temp_log_array[5],
  1121. excur_after_coil_temp_log_array[6],
  1122. excur_after_coil_temp_log_array[7],
  1123. excur_after_coil_temp_log_array[8],
  1124. excur_after_coil_temp_log_array[9]);
  1125. rc += snprintf(buf+rc, PAGE_SIZE,
  1126. "Excursion={ %d, %d, %d, %d, %d, %d, %d, %d, %d, %d }\n",
  1127. excur_after_excur_log_array[0],
  1128. excur_after_excur_log_array[1],
  1129. excur_after_excur_log_array[2],
  1130. excur_after_excur_log_array[3],
  1131. excur_after_excur_log_array[4],
  1132. excur_after_excur_log_array[5],
  1133. excur_after_excur_log_array[6],
  1134. excur_after_excur_log_array[7],
  1135. excur_after_excur_log_array[8],
  1136. excur_after_excur_log_array[9]);
  1137. rc += snprintf(buf+rc, PAGE_SIZE,
  1138. "Rdc={ %d, %d, %d, %d, %d, %d, %d, %d, %d, %d }\n",
  1139. excur_after_rdc_log_array[0],
  1140. excur_after_rdc_log_array[1],
  1141. excur_after_rdc_log_array[2],
  1142. excur_after_rdc_log_array[3],
  1143. excur_after_rdc_log_array[4],
  1144. excur_after_rdc_log_array[5],
  1145. excur_after_rdc_log_array[6],
  1146. excur_after_rdc_log_array[7],
  1147. excur_after_rdc_log_array[8],
  1148. excur_after_rdc_log_array[9]);
  1149. rc += snprintf(buf+rc, PAGE_SIZE,
  1150. "Frequency={ %d, %d, %d, %d, %d, %d, %d, %d, %d, %d }\n",
  1151. excur_after_freq_log_array[0],
  1152. excur_after_freq_log_array[1],
  1153. excur_after_freq_log_array[2],
  1154. excur_after_freq_log_array[3],
  1155. excur_after_freq_log_array[4],
  1156. excur_after_freq_log_array[5],
  1157. excur_after_freq_log_array[6],
  1158. excur_after_freq_log_array[7],
  1159. excur_after_freq_log_array[8],
  1160. excur_after_freq_log_array[9]);
  1161. }
  1162. if ((log_available & 0x2) == 0x2) {
  1163. rc += snprintf(buf+rc, PAGE_SIZE,
  1164. "*** Temperature Limit was exceeded.\n");
  1165. rc += snprintf(buf+rc, PAGE_SIZE,
  1166. "Seq:%d, log_available=%d, version_id:3.1.%d\n",
  1167. seq_count_temp, log_available, version_id);
  1168. rc += snprintf(buf+rc, PAGE_SIZE,
  1169. "Temperature={ %d, %d, %d, %d, %d, %d, %d, %d, %d, %d,\n",
  1170. coil_temp_log_array[0],
  1171. coil_temp_log_array[1],
  1172. coil_temp_log_array[2],
  1173. coil_temp_log_array[3],
  1174. coil_temp_log_array[4],
  1175. coil_temp_log_array[5],
  1176. coil_temp_log_array[6],
  1177. coil_temp_log_array[7],
  1178. coil_temp_log_array[8],
  1179. coil_temp_log_array[9]);
  1180. rc += snprintf(buf+rc, PAGE_SIZE,
  1181. " %d, %d, %d, %d, %d, %d, %d, %d, %d, %d }\n",
  1182. after_coil_temp_log_array[0],
  1183. after_coil_temp_log_array[1],
  1184. after_coil_temp_log_array[2],
  1185. after_coil_temp_log_array[3],
  1186. after_coil_temp_log_array[4],
  1187. after_coil_temp_log_array[5],
  1188. after_coil_temp_log_array[6],
  1189. after_coil_temp_log_array[7],
  1190. after_coil_temp_log_array[8],
  1191. after_coil_temp_log_array[9]);
  1192. rc += snprintf(buf+rc, PAGE_SIZE,
  1193. "Excursion={ %d, %d, %d, %d, %d, %d, %d, %d, %d, %d,\n",
  1194. excur_log_array[0],
  1195. excur_log_array[1],
  1196. excur_log_array[2],
  1197. excur_log_array[3],
  1198. excur_log_array[4],
  1199. excur_log_array[5],
  1200. excur_log_array[6],
  1201. excur_log_array[7],
  1202. excur_log_array[8],
  1203. excur_log_array[9]);
  1204. rc += snprintf(buf+rc, PAGE_SIZE,
  1205. " %d, %d, %d, %d, %d, %d, %d, %d, %d, %d }\n",
  1206. after_excur_log_array[0],
  1207. after_excur_log_array[1],
  1208. after_excur_log_array[2],
  1209. after_excur_log_array[3],
  1210. after_excur_log_array[4],
  1211. after_excur_log_array[5],
  1212. after_excur_log_array[6],
  1213. after_excur_log_array[7],
  1214. after_excur_log_array[8],
  1215. after_excur_log_array[9]);
  1216. rc += snprintf(buf+rc, PAGE_SIZE,
  1217. "Rdc={ %d, %d, %d, %d, %d, %d, %d, %d, %d, %d,\n",
  1218. rdc_log_array[0],
  1219. rdc_log_array[1],
  1220. rdc_log_array[2],
  1221. rdc_log_array[3],
  1222. rdc_log_array[4],
  1223. rdc_log_array[5],
  1224. rdc_log_array[6],
  1225. rdc_log_array[7],
  1226. rdc_log_array[8],
  1227. rdc_log_array[9]);
  1228. rc += snprintf(buf+rc, PAGE_SIZE,
  1229. " %d, %d, %d, %d, %d, %d, %d, %d, %d, %d }\n",
  1230. after_rdc_log_array[0],
  1231. after_rdc_log_array[1],
  1232. after_rdc_log_array[2],
  1233. after_rdc_log_array[3],
  1234. after_rdc_log_array[4],
  1235. after_rdc_log_array[5],
  1236. after_rdc_log_array[6],
  1237. after_rdc_log_array[7],
  1238. after_rdc_log_array[8],
  1239. after_rdc_log_array[9]);
  1240. rc += snprintf(buf+rc, PAGE_SIZE,
  1241. "Frequency={ %d, %d, %d, %d, %d, %d, %d, %d, %d, %d,\n",
  1242. freq_log_array[0],
  1243. freq_log_array[1],
  1244. freq_log_array[2],
  1245. freq_log_array[3],
  1246. freq_log_array[4],
  1247. freq_log_array[5],
  1248. freq_log_array[6],
  1249. freq_log_array[7],
  1250. freq_log_array[8],
  1251. freq_log_array[9]);
  1252. rc += snprintf(buf+rc, PAGE_SIZE,
  1253. " %d, %d, %d, %d, %d, %d, %d, %d, %d, %d }\n",
  1254. after_freq_log_array[0],
  1255. after_freq_log_array[1],
  1256. after_freq_log_array[2],
  1257. after_freq_log_array[3],
  1258. after_freq_log_array[4],
  1259. after_freq_log_array[5],
  1260. after_freq_log_array[6],
  1261. after_freq_log_array[7],
  1262. after_freq_log_array[8],
  1263. after_freq_log_array[9]);
  1264. }
  1265. if (maxdsm.param[param_excur_limit] != 0 &&
  1266. maxdsm.param[param_thermal_limit] != 0) {
  1267. rc += snprintf(buf+rc, PAGE_SIZE,
  1268. "[Parameter Set] excursionlimit:0x%x, ",
  1269. maxdsm.param[param_excur_limit]);
  1270. rc += snprintf(buf+rc, PAGE_SIZE,
  1271. "rdcroomtemp:0x%x, coilthermallimit:0x%x, ",
  1272. maxdsm.param[param_voice_coil],
  1273. maxdsm.param[param_thermal_limit]);
  1274. rc += snprintf(buf+rc, PAGE_SIZE,
  1275. "releasetime:0x%x\n",
  1276. maxdsm.param[param_release_time]);
  1277. rc += snprintf(buf+rc, PAGE_SIZE,
  1278. "[Parameter Set] staticgain:0x%x, ",
  1279. maxdsm.param[param_static_gain]);
  1280. rc += snprintf(buf+rc, PAGE_SIZE,
  1281. "lfxgain:0x%x, pilotgain:0x%x\n",
  1282. maxdsm.param[param_lfx_gain],
  1283. maxdsm.param[param_pilot_gain]);
  1284. }
  1285. out:
  1286. return (ssize_t)rc;
  1287. }
  1288. EXPORT_SYMBOL_GPL(maxdsm_log_prepare);
  1289. #endif /* USE_DSM_LOG */
  1290. #ifdef USE_DSM_UPDATE_CAL
  1291. ssize_t maxdsm_cal_prepare(char *buf)
  1292. {
  1293. int rc = 0;
  1294. int x;
  1295. if (maxdsm.update_cal) {
  1296. for (x = 0; x < (maxdsm.param_size >> 1); x++) {
  1297. rc += snprintf(buf+rc, PAGE_SIZE,
  1298. "[%2d] 0x%08x, ",
  1299. x,
  1300. (int)(g_pbi[x].val));
  1301. if ((x%5) == 4)
  1302. rc += snprintf(buf+rc, PAGE_SIZE,
  1303. "\n");
  1304. }
  1305. rc += snprintf(buf+rc, PAGE_SIZE,
  1306. "Use Updated Parameters.\n");
  1307. } else
  1308. rc += snprintf(buf+rc, PAGE_SIZE,
  1309. "Use Default Parameters.\n");
  1310. return (ssize_t)rc;
  1311. }
  1312. EXPORT_SYMBOL_GPL(maxdsm_cal_prepare);
  1313. #endif /* USE_DSM_UPDATE_CAL */
  1314. static int maxdsm_set_param(struct param_set_data *data, int size)
  1315. {
  1316. int loop, ret = 0;
  1317. switch (maxdsm.platform_type) {
  1318. case PLATFORM_TYPE_A:
  1319. for (loop = 0; loop < size; loop++)
  1320. maxdsm_regmap_write(data[loop].addr, data[loop].value);
  1321. break;
  1322. case PLATFORM_TYPE_B:
  1323. maxdsm.filter_set = DSM_ID_FILTER_GET_AFE_PARAMS;
  1324. ret = maxdsm_dsm_open(&maxdsm);
  1325. maxdsm.param[PARAM_WRITE_FLAG] = data[0].wflag;
  1326. for (loop = 0; loop < size; loop++)
  1327. maxdsm.param[data[loop].name] = data[loop].value;
  1328. maxdsm.filter_set = DSM_ID_FILTER_SET_AFE_CNTRLS;
  1329. ret = maxdsm_dsm_open(&maxdsm);
  1330. break;
  1331. default:
  1332. return -ENODATA;
  1333. }
  1334. return ret < 0 ? ret : 0;
  1335. }
  1336. static int maxdsm_find_index_of_saved_params(
  1337. struct param_set_data *params,
  1338. int size,
  1339. uint32_t param_name)
  1340. {
  1341. while (size-- > 0)
  1342. if (params[size].name == param_name)
  1343. break;
  1344. return size;
  1345. }
  1346. uint32_t maxdsm_get_platform_type(void)
  1347. {
  1348. dbg_maxdsm("platform_type=%d", maxdsm.platform_type);
  1349. return maxdsm.platform_type;
  1350. }
  1351. EXPORT_SYMBOL_GPL(maxdsm_get_platform_type);
  1352. int maxdsm_update_feature_en_adc(int apply)
  1353. {
  1354. unsigned int val = 0;
  1355. unsigned int reg;
  1356. struct param_set_data data = {
  1357. .name = PARAM_FEATURE_SET,
  1358. .addr = 0x2A006A,
  1359. .value = 0x200,
  1360. .wflag = FLAG_WRITE_FEATURE_ONLY,
  1361. };
  1362. switch (maxdsm.platform_type) {
  1363. case PLATFORM_TYPE_A:
  1364. reg = data.addr;
  1365. break;
  1366. case PLATFORM_TYPE_B:
  1367. reg = data.name;
  1368. data.value <<= 1;
  1369. break;
  1370. default:
  1371. return -ENODATA;
  1372. }
  1373. maxdsm_read_wrapper(reg, &val);
  1374. if (apply)
  1375. data.value = val | data.value;
  1376. else
  1377. data.value = val & ~data.value;
  1378. dbg_maxdsm("apply=%d data.value=0x%x val=0x%x reg=%x",
  1379. apply, data.value, val, reg);
  1380. return maxdsm_set_param(&data, 1);
  1381. }
  1382. EXPORT_SYMBOL_GPL(maxdsm_update_feature_en_adc);
  1383. int maxdsm_set_feature_en(int on)
  1384. {
  1385. int index;
  1386. struct param_set_data data = {
  1387. .name = PARAM_FEATURE_SET,
  1388. .value = 0,
  1389. .wflag = FLAG_WRITE_FEATURE_ONLY,
  1390. };
  1391. index = maxdsm_find_index_of_saved_params(
  1392. maxdsm_saved_params,
  1393. sizeof(maxdsm_saved_params)
  1394. / sizeof(struct param_set_data),
  1395. PARAM_FEATURE_SET);
  1396. if (index < 0 || !maxdsm.platform_type)
  1397. return -ENODATA;
  1398. if (on) {
  1399. if (maxdsm_saved_params[index].value & 0x40) {
  1400. pr_err("%s: feature_en has already 0x40\n",
  1401. __func__);
  1402. return -EALREADY;
  1403. }
  1404. maxdsm.filter_set = DSM_ID_FILTER_GET_AFE_PARAMS;
  1405. maxdsm_dsm_open(&maxdsm);
  1406. maxdsm_saved_params[index].value
  1407. = maxdsm.param[PARAM_FEATURE_SET];
  1408. data.value =
  1409. maxdsm_saved_params[index].value | 0x40;
  1410. dbg_maxdsm("data.value=0x%08x", data.value);
  1411. dbg_maxdsm("maxdsm_saved_params[%d].value=0x%08x",
  1412. index, maxdsm_saved_params[index].value);
  1413. } else {
  1414. data.value =
  1415. maxdsm_saved_params[index].value & ~0x40;
  1416. dbg_maxdsm("data.value=0x%08x", data.value);
  1417. dbg_maxdsm("maxdsm_saved_params[%d].value=0x%08x",
  1418. index, maxdsm_saved_params[index].value);
  1419. }
  1420. return maxdsm_set_param(&data, 1);
  1421. }
  1422. EXPORT_SYMBOL_GPL(maxdsm_set_feature_en);
  1423. int maxdsm_set_rdc_temp(uint32_t rdc, uint32_t temp)
  1424. {
  1425. struct param_set_data data[] = {
  1426. {
  1427. .name = PARAM_VOICE_COIL,
  1428. .value = rdc, /* This was already calculated. */
  1429. .wflag = FLAG_WRITE_RDC_CAL_ONLY,
  1430. },
  1431. {
  1432. .name = PARAM_AMBIENT_TEMP,
  1433. .value = temp << 19,
  1434. .wflag = FLAG_WRITE_RDC_CAL_ONLY,
  1435. },
  1436. };
  1437. dbg_maxdsm("rdc=0x%08x(0x%08x) temp=0x%08x(0x%08x)",
  1438. rdc, data[0].value, temp, data[1].value);
  1439. return maxdsm_set_param(
  1440. data,
  1441. sizeof(data) / sizeof(struct param_set_data));
  1442. }
  1443. EXPORT_SYMBOL_GPL(maxdsm_set_rdc_temp);
  1444. int maxdsm_set_dsm_onoff_status(int on)
  1445. {
  1446. struct param_set_data data[] = {
  1447. {
  1448. .name = PARAM_ONOFF,
  1449. .value = on,
  1450. .wflag = FLAG_WRITE_ONOFF_ONLY,
  1451. },
  1452. };
  1453. return maxdsm_set_param(
  1454. data,
  1455. sizeof(data) / sizeof(struct param_set_data));
  1456. }
  1457. EXPORT_SYMBOL_GPL(maxdsm_set_dsm_onoff_status);
  1458. uint32_t maxdsm_get_dcresistance(void)
  1459. {
  1460. maxdsm.filter_set = DSM_ID_FILTER_GET_AFE_PARAMS;
  1461. maxdsm_dsm_open(&maxdsm);
  1462. return maxdsm.param[PARAM_RDC]
  1463. << maxdsm.param[PARAM_RDC_SZ];
  1464. }
  1465. EXPORT_SYMBOL_GPL(maxdsm_get_dcresistance);
  1466. uint32_t maxdsm_get_dsm_onoff_status(void)
  1467. {
  1468. return maxdsm.param[PARAM_ONOFF];
  1469. }
  1470. #define V30_SIZE (PARAM_DSM_3_0_MAX >> 1)
  1471. #define V35_SIZE ((PARAM_DSM_3_5_MAX - PARAM_DSM_3_0_MAX) >> 1)
  1472. #define V40_SIZE ((PARAM_DSM_4_0_MAX - PARAM_DSM_3_5_MAX) >> 1)
  1473. #define A_V35_SIZE (PARAM_A_DSM_3_5_MAX >> 1)
  1474. #define A_V40_SIZE ((PARAM_A_DSM_4_0_MAX - PARAM_A_DSM_3_5_MAX) >> 1)
  1475. int maxdsm_update_param_info(struct maxim_dsm *maxdsm)
  1476. {
  1477. uint32_t binfo_v30[V30_SIZE] = {
  1478. /* dcResistance, coilTemp, qualityFactor */
  1479. 27, 19, 29,
  1480. /* resonanceFreq, excursionMeasure, rdcroomtemp */
  1481. 9, 0, 27,
  1482. /* releasetime, coilthermallimit, excursionlimit */
  1483. 30, 19, 27,
  1484. /* dsmenable */
  1485. 0,
  1486. /* staticgain, lfxgain, pilotgain */
  1487. 29, 30, 31,
  1488. /* flagToWrite, featureSetEnable */
  1489. 0, 0,
  1490. /* smooFacVoltClip, highPassCutOffFactor, leadResistance */
  1491. 30, 30, 27,
  1492. /* rmsSmooFac, clipLimit, thermalCoeff */
  1493. 31, 27, 20,
  1494. /* qSpk, excurLoggingThresh, coilTempLoggingThresh */
  1495. 29, 0, 0,
  1496. /* resFreq, resFreqGuardBand */
  1497. 9, 9
  1498. }; /* 26 */
  1499. uint32_t binfo_v35[V35_SIZE] = {
  1500. /* Ambient_Temp, STL_attack_tiem, STL_release_time */
  1501. 19, 19, 19,
  1502. /* STL_Admittance_a1, STL_Admittance_a2 */
  1503. 30, 30,
  1504. /* STL_Admittance_b1, STL_Admittance_b1, STL_Admittance_b2 */
  1505. 30, 30, 30,
  1506. /* Tch1, Rth1, Tch2, Rth2 */
  1507. 24, 24, 24, 24,
  1508. /* STL_Attenuation_Gain */
  1509. 30,
  1510. /* SPT_rampDownFrames, SPT_Threshold */
  1511. 0, 19,
  1512. /* T_horizon */
  1513. 0,
  1514. /* LFX_Admittance_a1, LFX_Admittance_a2 */
  1515. 28, 28,
  1516. /* LFX_Admittance_b0, LFX_Admittance_b1, LFX_Admittance_b2 */
  1517. 28, 28, 28,
  1518. }; /* 21 */
  1519. uint32_t binfo_v40[V40_SIZE] = {
  1520. /* X_MAX, SPK_FS, Q_GUARD_BAND */
  1521. 0, 0, 0,
  1522. /* STIMPEDMODEL_CEFS_A1, A2, B0, B1, B2 */
  1523. 0, 0, 0, 0, 0,
  1524. /* STIMPEDEMODEL_FLAG, Q_NOTCH */
  1525. 0, 0,
  1526. };
  1527. uint32_t binfo_a_v35[A_V35_SIZE] = {
  1528. /* temp, excur, rdc, qc_low, qc_hi, fc_low, fc_high */
  1529. 0, 0, 0, 0, 0, 0, 0,
  1530. /* excur limit, rdc roomt temp, temp limit */
  1531. 1, 1, 1,
  1532. /* rel time, dsm on/off */
  1533. 2, 2,
  1534. /* makeup gain, lfx gain, pilot gain */
  1535. 3, 3, 3,
  1536. /* feature, smoofact, hpfcutoff, lead, rms_smoofact */
  1537. 4, 4, 4, 4, 4,
  1538. /* volt, thermal coeff, qspk, excursion log, temp log */
  1539. 5, 5, 5, 5, 5,
  1540. /* res freq, res freq guardband */
  1541. 6, 6,
  1542. /* ambient temp, stl a1, stl a2, stl b0, stl b1, stl b2 */
  1543. 10, 10, 10, 10, 10, 10,
  1544. /* rth1 hi, rth2 hi, rth1 lo, rth2 lo */
  1545. 11, 12, 13, 14,
  1546. /* stl atengain hi, stl atengain lo */
  1547. 15, 16,
  1548. /* ramp down, spt threshold hi, spt threshold lo */
  1549. 17, 18, 19,
  1550. /* t horizon, lfx a1, lfx a2 */
  1551. 20, 21, 22,
  1552. /* lfx b0, lfx b1, lfx b2, algorithm x */
  1553. 23, 24, 25, 26,
  1554. };
  1555. uint32_t binfo_a_v40[A_V40_SIZE] = {
  1556. /* TCTH1 hi, TCTH1 lo, TCTH2 hi, TCTH2 lo */
  1557. 1, 2, 3, 4,
  1558. /* ATTACK hi, ATTACK lo, RELEASE hi, RELEASE lo */
  1559. 5, 6, 7, 8,
  1560. /* STL_SPK_FS, Q_GUARD_BAND hi, Q_GUARD_BAND lo */
  1561. 9, 10, 11,
  1562. /* STIMPEDMODEL_CEFS_A1 hi, lo */
  1563. 12, 13,
  1564. /* STIMPEDMODEL_CEFS_A2 hi, lo */
  1565. 14, 15,
  1566. /* STIMPEDMODEL_CEFS_B0 hi, lo */
  1567. 16, 17,
  1568. /* STIMPEDMODEL_CEFS_B1 hi, lo */
  1569. 18, 19,
  1570. /* STIMPEDMODEL_CEFS_B2 hi, lo */
  1571. 20, 21,
  1572. /* STIMPEDMODEL_FLAG, Q_NOTCH hi/lo */
  1573. 22, 23, 24,
  1574. };
  1575. /* Try to get parameter size. */
  1576. switch (maxdsm->version) {
  1577. case VERSION_4_0_A:
  1578. maxdsm->param_size = PARAM_A_DSM_4_0_MAX;
  1579. break;
  1580. case VERSION_4_0_B:
  1581. maxdsm->param_size = PARAM_DSM_4_0_MAX;
  1582. break;
  1583. case VERSION_3_5_A:
  1584. maxdsm->param_size = PARAM_A_DSM_3_5_MAX;
  1585. break;
  1586. case VERSION_3_5_B:
  1587. maxdsm->param_size = PARAM_DSM_3_5_MAX;
  1588. break;
  1589. case VERSION_3_0:
  1590. maxdsm->param_size = PARAM_DSM_3_0_MAX;
  1591. break;
  1592. default:
  1593. pr_err("%s: Unknown version. %d\n", __func__,
  1594. maxdsm->version);
  1595. return -EINVAL;
  1596. }
  1597. kfree(maxdsm->binfo);
  1598. maxdsm->binfo = kzalloc(
  1599. sizeof(uint32_t) * maxdsm->param_size, GFP_KERNEL);
  1600. if (!maxdsm->binfo)
  1601. return -ENOMEM;
  1602. /* Try to copy parameter size. */
  1603. switch (maxdsm->version) {
  1604. case VERSION_4_0_A:
  1605. memcpy(&maxdsm->binfo[ARRAY_SIZE(binfo_a_v35)],
  1606. binfo_a_v40, sizeof(binfo_a_v40));
  1607. case VERSION_3_5_A:
  1608. memcpy(maxdsm->binfo,
  1609. binfo_a_v35, sizeof(binfo_a_v35));
  1610. break;
  1611. case VERSION_4_0_B:
  1612. memcpy(&maxdsm->binfo[
  1613. ARRAY_SIZE(binfo_v30) + ARRAY_SIZE(binfo_v35)],
  1614. binfo_v40, sizeof(binfo_v40));
  1615. case VERSION_3_5_B:
  1616. memcpy(&maxdsm->binfo[ARRAY_SIZE(binfo_v30)],
  1617. binfo_v35, sizeof(binfo_v35));
  1618. case VERSION_3_0:
  1619. memcpy(maxdsm->binfo,
  1620. binfo_v30, sizeof(binfo_v30));
  1621. break;
  1622. }
  1623. kfree(maxdsm->param);
  1624. maxdsm->param = kzalloc(
  1625. sizeof(uint32_t) * maxdsm->param_size, GFP_KERNEL);
  1626. if (!maxdsm->param) {
  1627. kfree(maxdsm->binfo);
  1628. return -ENOMEM;
  1629. }
  1630. dbg_maxdsm("version=%d, platform_type=%d",
  1631. maxdsm->version, maxdsm->platform_type);
  1632. return 0;
  1633. }
  1634. int maxdsm_update_info(uint32_t *pinfo)
  1635. {
  1636. int ret = 0;
  1637. int32_t *data = pinfo;
  1638. if (pinfo == NULL) {
  1639. pr_debug("%s: pinfo was not set.\n",
  1640. __func__);
  1641. ret = -EINVAL;
  1642. return ret;
  1643. }
  1644. maxdsm.platform_type = data[PARAM_OFFSET_PLATFORM];
  1645. maxdsm.port_id = data[PARAM_OFFSET_PORT_ID];
  1646. maxdsm.rx_mod_id = data[PARAM_OFFSET_RX_MOD_ID];
  1647. maxdsm.tx_mod_id = data[PARAM_OFFSET_TX_MOD_ID];
  1648. maxdsm.filter_set = data[PARAM_OFFSET_FILTER_SET];
  1649. maxdsm.version = data[PARAM_OFFSET_VERSION];
  1650. ret = maxdsm_update_param_info(&maxdsm);
  1651. return ret;
  1652. }
  1653. EXPORT_SYMBOL_GPL(maxdsm_update_info);
  1654. int maxdsm_get_port_id(void)
  1655. {
  1656. return maxdsm.port_id;
  1657. }
  1658. EXPORT_SYMBOL_GPL(maxdsm_get_port_id);
  1659. int maxdsm_get_rx_mod_id(void)
  1660. {
  1661. return maxdsm.rx_mod_id;
  1662. }
  1663. EXPORT_SYMBOL_GPL(maxdsm_get_rx_mod_id);
  1664. int maxdsm_get_tx_mod_id(void)
  1665. {
  1666. return maxdsm.tx_mod_id;
  1667. }
  1668. EXPORT_SYMBOL_GPL(maxdsm_get_tx_mod_id);
  1669. int maxdsm_get_spk_state(void)
  1670. {
  1671. return maxdsm.spk_state;
  1672. }
  1673. EXPORT_SYMBOL_GPL(maxdsm_get_spk_state);
  1674. void maxdsm_set_spk_state(int state)
  1675. {
  1676. maxdsm.spk_state = state;
  1677. }
  1678. EXPORT_SYMBOL_GPL(maxdsm_set_spk_state);
  1679. int maxdsm_set_pilot_signal_state(int on)
  1680. {
  1681. int ret = 0;
  1682. /* update dsm parameters */
  1683. maxdsm.filter_set = DSM_ID_FILTER_GET_AFE_PARAMS;
  1684. ret = maxdsm_dsm_open(&maxdsm);
  1685. if (ret)
  1686. goto error;
  1687. /* feature_set parameter is set by pilot signal off */
  1688. maxdsm.param[PARAM_WRITE_FLAG] = FLAG_WRITE_FEATURE_ONLY;
  1689. maxdsm.param[PARAM_FEATURE_SET] =
  1690. on ? maxdsm.param[PARAM_FEATURE_SET] & ~0x200
  1691. : maxdsm.param[PARAM_FEATURE_SET] | 0x200;
  1692. maxdsm.filter_set = DSM_ID_FILTER_SET_AFE_CNTRLS;
  1693. ret = maxdsm_dsm_open(&maxdsm);
  1694. if (ret)
  1695. goto error;
  1696. else {
  1697. if (on == 0)
  1698. usleep_range(179999, 180000);
  1699. }
  1700. /* check feature_set parameter */
  1701. maxdsm.filter_set = DSM_ID_FILTER_GET_AFE_PARAMS;
  1702. ret = maxdsm_dsm_open(&maxdsm);
  1703. if (!(maxdsm.param[PARAM_FEATURE_SET] & 0x200)) {
  1704. dbg_maxdsm("Feature set param was not updated. 0x%08x",
  1705. maxdsm.param[PARAM_FEATURE_SET]);
  1706. ret = -EAGAIN;
  1707. }
  1708. error:
  1709. return ret;
  1710. }
  1711. static int maxdsm_validation_check(uint32_t flag)
  1712. {
  1713. int ret = 0;
  1714. /* Validation check */
  1715. switch (flag) {
  1716. case FLAG_WRITE_ALL:
  1717. case FLAG_WRITE_ONOFF_ONLY:
  1718. case FLAG_WRITE_RDC_CAL_ONLY:
  1719. case FLAG_WRITE_FEATURE_ONLY:
  1720. break;
  1721. default:
  1722. pr_err("%s: Wrong information was received.\n", __func__);
  1723. ret = -EINVAL;
  1724. }
  1725. return ret;
  1726. }
  1727. #ifdef USE_DSM_UPDATE_CAL
  1728. int maxdsm_update_caldata(int on)
  1729. {
  1730. int x;
  1731. uint32_t val;
  1732. int ret = 0;
  1733. if (!maxdsm.update_cal || on == 0) {
  1734. dbg_maxdsm("Calibration data is not available. Cmd:%d", on);
  1735. return ret;
  1736. }
  1737. switch (maxdsm.platform_type) {
  1738. case PLATFORM_TYPE_A:
  1739. for (x = 0; x < (maxdsm.param_size >> 1); x++) {
  1740. ret = maxdsm_regmap_read(g_pbi[x].addr, &val);
  1741. if (val != g_pbi[x].val) {
  1742. maxdsm_regmap_write(g_pbi[x].addr,
  1743. g_pbi[x].val);
  1744. dbg_maxdsm("[%d]: 0x%08x / 0x%08x",
  1745. x, g_pbi[x].addr, g_pbi[x].val);
  1746. }
  1747. }
  1748. break;
  1749. case PLATFORM_TYPE_B:
  1750. for (x = 0; x < maxdsm.param_size; x += 2) {
  1751. maxdsm.param[x] = g_pbi[x>>1].val;
  1752. maxdsm.param[x+1] = 1 << maxdsm.binfo[x>>1];
  1753. dbg_maxdsm("[%d]: 0x%08x / 0x%08x",
  1754. x, maxdsm.param[x], maxdsm.param[x+1]);
  1755. }
  1756. maxdsm.param[PARAM_WRITE_FLAG] = FLAG_WRITE_ALL;
  1757. maxdsm.filter_set = DSM_ID_FILTER_SET_AFE_CNTRLS;
  1758. maxdsm_dsm_open(&maxdsm);
  1759. break;
  1760. }
  1761. return ret;
  1762. }
  1763. int maxdsm_cal_avail(void)
  1764. {
  1765. return maxdsm.update_cal;
  1766. }
  1767. static void maxdsm_store_caldata(void)
  1768. {
  1769. int x;
  1770. for (x = 0; x < (maxdsm.param_size >> 1); x++) {
  1771. g_pbi[x].val = maxdsm.param[x<<1];
  1772. dbg_maxdsm("[%d]: 0x%08x",
  1773. x, g_pbi[x].val);
  1774. }
  1775. maxdsm.update_cal = 1;
  1776. }
  1777. #endif /* USE_DSM_UPDATE_CAL */
  1778. static int maxdsm_open(struct inode *inode, struct file *filep)
  1779. {
  1780. return 0;
  1781. }
  1782. static long maxdsm_ioctl_handler(struct file *file,
  1783. unsigned int cmd, unsigned int arg,
  1784. void __user *argp)
  1785. {
  1786. unsigned int reg, val;
  1787. long ret = -EINVAL;
  1788. mutex_lock(&dsm_fs_lock);
  1789. switch (cmd) {
  1790. case MAXDSM_IOCTL_GET_VERSION:
  1791. ret = maxdsm.version;
  1792. if (copy_to_user(argp,
  1793. &maxdsm.version,
  1794. sizeof(maxdsm.version)))
  1795. goto error;
  1796. break;
  1797. case MAXDSM_IOCTL_SET_VERSION:
  1798. if (arg < VERSION_3_0 ||
  1799. arg > VERSION_4_0_B)
  1800. goto error;
  1801. maxdsm.version = arg;
  1802. ret = maxdsm_update_param_info(&maxdsm);
  1803. if (!ret)
  1804. goto error;
  1805. ret = maxdsm.version;
  1806. break;
  1807. case MAXDSM_IOCTL_GET_ALL_PARAMS:
  1808. maxdsm_read_all();
  1809. if (copy_to_user(argp, maxdsm.param,
  1810. sizeof(int) * maxdsm.param_size))
  1811. goto error;
  1812. break;
  1813. case MAXDSM_IOCTL_SET_ALL_PARAMS:
  1814. if (copy_from_user(maxdsm.param, argp,
  1815. sizeof(int) * maxdsm.param_size))
  1816. goto error;
  1817. maxdsm_write_all();
  1818. break;
  1819. case MAXDSM_IOCTL_GET_PARAM:
  1820. reg = (unsigned int)(arg & 0xFFFFFFFF);
  1821. val = 0;
  1822. /*
  1823. * protocol rule.
  1824. * PLATFORM_TYPE_A:
  1825. * reg : register
  1826. * val : value
  1827. * PLATFORM_TYPE_B:
  1828. * reg : parameter index
  1829. * val : value
  1830. */
  1831. maxdsm_read_wrapper(reg, &val);
  1832. ret = val;
  1833. if (copy_to_user(argp, &val, sizeof(val)))
  1834. goto error;
  1835. break;
  1836. case MAXDSM_IOCTL_SET_PARAM:
  1837. if (copy_from_user(maxdsm.param, argp,
  1838. sizeof(int) * 3/* reg, val, flag */))
  1839. goto error;
  1840. ret = maxdsm_write_wrapper(maxdsm.param[0],
  1841. maxdsm.param[1], maxdsm.param[2]);
  1842. break;
  1843. #ifdef USE_DSM_UPDATE_CAL
  1844. case MAXDSM_IOCTL_GET_CAL_DATA:
  1845. /* todo */
  1846. break;
  1847. case MAXDSM_IOCTL_SET_CAL_DATA:
  1848. if (copy_from_user(maxdsm.param, argp,
  1849. sizeof(int) * maxdsm.param_size))
  1850. goto error;
  1851. maxdsm_store_caldata();
  1852. break;
  1853. #endif /* USE_DSM_UPDATE_CAL */
  1854. case MAXDSM_IOCTL_GET_PLATFORM_TYPE:
  1855. ret = maxdsm.platform_type;
  1856. if (copy_to_user(argp,
  1857. &maxdsm.platform_type,
  1858. sizeof(maxdsm.platform_type)))
  1859. goto error;
  1860. break;
  1861. case MAXDSM_IOCTL_SET_PLATFORM_TYPE:
  1862. if (arg < PLATFORM_TYPE_A ||
  1863. arg > PLATFORM_TYPE_B)
  1864. goto error;
  1865. maxdsm.platform_type = arg;
  1866. ret = maxdsm.platform_type;
  1867. break;
  1868. default:
  1869. break;
  1870. }
  1871. error:
  1872. mutex_unlock(&dsm_fs_lock);
  1873. return ret;
  1874. }
  1875. static long maxdsm_ioctl(struct file *file,
  1876. unsigned int cmd, unsigned long arg)
  1877. {
  1878. return maxdsm_ioctl_handler(file, cmd, arg,
  1879. (void __user *)arg);
  1880. }
  1881. #ifdef CONFIG_COMPAT
  1882. static long maxdsm_compat_ioctl(struct file *file,
  1883. unsigned int cmd, unsigned long arg)
  1884. {
  1885. return maxdsm_ioctl_handler(file, cmd, arg,
  1886. (void __user *)(unsigned long)arg);
  1887. }
  1888. #endif /* CONFIG_COMPAT */
  1889. static ssize_t maxdsm_read(struct file *filep, char __user *buf,
  1890. size_t count, loff_t *ppos)
  1891. {
  1892. int ret;
  1893. mutex_lock(&dsm_fs_lock);
  1894. maxdsm_read_all();
  1895. /* copy params to user */
  1896. ret = copy_to_user(buf, maxdsm.param,
  1897. sizeof(uint32_t) * maxdsm.param_size < count ?
  1898. sizeof(uint32_t) * maxdsm.param_size : count);
  1899. if (ret)
  1900. pr_err("%s: copy_to_user failed - %d\n", __func__, ret);
  1901. mutex_unlock(&dsm_fs_lock);
  1902. return ret;
  1903. }
  1904. static ssize_t maxdsm_write(struct file *filep, const char __user *buf,
  1905. size_t count, loff_t *ppos)
  1906. {
  1907. int ret = 0;
  1908. mutex_lock(&dsm_fs_lock);
  1909. if (copy_from_user(maxdsm.param, buf,
  1910. sizeof(uint32_t) * maxdsm.param_size)) {
  1911. pr_err("%s: Failed to copy user data.\n", __func__);
  1912. goto error;
  1913. }
  1914. switch (maxdsm.platform_type) {
  1915. case PLATFORM_TYPE_A:
  1916. /* We will check validation for parameter.
  1917. * If received parameter from user is good,
  1918. * it will be applied. */
  1919. dbg_maxdsm("reg=0x%x val=0x%x flag=%x regmap=%p",
  1920. maxdsm.param[0],
  1921. maxdsm.param[1],
  1922. maxdsm.param[2],
  1923. maxdsm.regmap);
  1924. ret = maxdsm_validation_check(maxdsm.param[2]);
  1925. if (!ret)
  1926. maxdsm_regmap_write(maxdsm.param[0], maxdsm.param[1]);
  1927. break;
  1928. case PLATFORM_TYPE_B:
  1929. ret = maxdsm_validation_check(maxdsm.param[PARAM_WRITE_FLAG]);
  1930. if (!ret) {
  1931. /* set params from the algorithm to application */
  1932. maxdsm.filter_set = DSM_ID_FILTER_SET_AFE_CNTRLS;
  1933. maxdsm_dsm_open(&maxdsm);
  1934. }
  1935. break;
  1936. default:
  1937. dbg_maxdsm("Unknown platform type %d",
  1938. maxdsm.platform_type);
  1939. ret = -ENODATA;
  1940. break;
  1941. }
  1942. error:
  1943. mutex_unlock(&dsm_fs_lock);
  1944. return ret;
  1945. }
  1946. static const struct file_operations dsm_ctrl_fops = {
  1947. .owner = THIS_MODULE,
  1948. .open = maxdsm_open,
  1949. .release = NULL,
  1950. .unlocked_ioctl = maxdsm_ioctl,
  1951. #ifdef CONFIG_COMPAT
  1952. .compat_ioctl = maxdsm_compat_ioctl,
  1953. #endif /* CONFIG_COMPAT */
  1954. .read = maxdsm_read,
  1955. .write = maxdsm_write,
  1956. .mmap = NULL,
  1957. .poll = NULL,
  1958. .fasync = NULL,
  1959. .llseek = NULL,
  1960. };
  1961. static struct miscdevice dsm_ctrl_miscdev = {
  1962. .minor = MISC_DYNAMIC_MINOR,
  1963. .name = "dsm_ctrl_dev",
  1964. .fops = &dsm_ctrl_fops
  1965. };
  1966. int maxdsm_deinit(void)
  1967. {
  1968. kfree(maxdsm.binfo);
  1969. kfree(maxdsm.param);
  1970. return misc_deregister(&dsm_ctrl_miscdev);
  1971. }
  1972. EXPORT_SYMBOL_GPL(maxdsm_deinit);
  1973. int maxdsm_init(void)
  1974. {
  1975. int ret;
  1976. if (maxdsm.registered) {
  1977. dbg_maxdsm("%s: Already registered.\n", __func__);
  1978. return -EALREADY;
  1979. }
  1980. ret = misc_register(&dsm_ctrl_miscdev);
  1981. if (!ret) {
  1982. maxdsm.registered = 1;
  1983. ret = maxdsm_update_param_info(&maxdsm);
  1984. }
  1985. return ret;
  1986. }
  1987. EXPORT_SYMBOL_GPL(maxdsm_init);
  1988. MODULE_DESCRIPTION("Module for test Maxim DSM");
  1989. MODULE_LICENSE("GPL");