dsi_clk_manager.c 35 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved.
  4. */
  5. #include <linux/of.h>
  6. #include <linux/delay.h>
  7. #include <linux/slab.h>
  8. #include <linux/pm_runtime.h>
  9. #include "dsi_clk.h"
  10. #include "dsi_defs.h"
  11. struct dsi_core_clks {
  12. struct dsi_core_clk_info clks;
  13. };
  14. struct dsi_link_clks {
  15. struct dsi_link_hs_clk_info hs_clks;
  16. struct dsi_link_lp_clk_info lp_clks;
  17. struct link_clk_freq freq;
  18. };
  19. struct dsi_clk_mngr {
  20. char name[MAX_STRING_LEN];
  21. struct mutex clk_mutex;
  22. struct list_head client_list;
  23. u32 dsi_ctrl_count;
  24. u32 master_ndx;
  25. struct dsi_core_clks core_clks[MAX_DSI_CTRL];
  26. struct dsi_link_clks link_clks[MAX_DSI_CTRL];
  27. u32 ctrl_index[MAX_DSI_CTRL];
  28. u32 core_clk_state;
  29. u32 link_clk_state;
  30. phy_configure_cb phy_config_cb;
  31. pll_toggle_cb phy_pll_toggle_cb;
  32. pre_clockoff_cb pre_clkoff_cb;
  33. post_clockoff_cb post_clkoff_cb;
  34. post_clockon_cb post_clkon_cb;
  35. pre_clockon_cb pre_clkon_cb;
  36. bool is_cont_splash_enabled;
  37. void *priv_data;
  38. };
  39. struct dsi_clk_client_info {
  40. char name[MAX_STRING_LEN];
  41. u32 core_refcount;
  42. u32 link_refcount;
  43. u32 core_clk_state;
  44. u32 link_clk_state;
  45. struct list_head list;
  46. struct dsi_clk_mngr *mngr;
  47. };
  48. static int _get_clk_mngr_index(struct dsi_clk_mngr *mngr,
  49. u32 dsi_ctrl_index,
  50. u32 *clk_mngr_index)
  51. {
  52. int i;
  53. for (i = 0; i < mngr->dsi_ctrl_count; i++) {
  54. if (mngr->ctrl_index[i] == dsi_ctrl_index) {
  55. *clk_mngr_index = i;
  56. return 0;
  57. }
  58. }
  59. return -EINVAL;
  60. }
  61. /**
  62. * dsi_clk_set_link_frequencies() - set frequencies for link clks
  63. * @clks: Link clock information
  64. * @pixel_clk: pixel clock frequency in KHz.
  65. * @byte_clk: Byte clock frequency in KHz.
  66. * @esc_clk: Escape clock frequency in KHz.
  67. *
  68. * return: error code in case of failure or 0 for success.
  69. */
  70. int dsi_clk_set_link_frequencies(void *client, struct link_clk_freq freq,
  71. u32 index)
  72. {
  73. int rc = 0, clk_mngr_index = 0;
  74. struct dsi_clk_client_info *c = client;
  75. struct dsi_clk_mngr *mngr;
  76. if (!client) {
  77. DSI_ERR("invalid params\n");
  78. return -EINVAL;
  79. }
  80. mngr = c->mngr;
  81. rc = _get_clk_mngr_index(mngr, index, &clk_mngr_index);
  82. if (rc) {
  83. DSI_ERR("failed to map control index %d\n", index);
  84. return -EINVAL;
  85. }
  86. memcpy(&mngr->link_clks[clk_mngr_index].freq, &freq,
  87. sizeof(struct link_clk_freq));
  88. return rc;
  89. }
  90. /**
  91. * dsi_clk_set_pixel_clk_rate() - set frequency for pixel clock
  92. * @clks: DSI link clock information.
  93. * @pixel_clk: Pixel clock rate in KHz.
  94. * @index: Index of the DSI controller.
  95. *
  96. * return: error code in case of failure or 0 for success.
  97. */
  98. int dsi_clk_set_pixel_clk_rate(void *client, u64 pixel_clk, u32 index)
  99. {
  100. int rc = 0;
  101. struct dsi_clk_client_info *c = client;
  102. struct dsi_clk_mngr *mngr;
  103. mngr = c->mngr;
  104. rc = clk_set_rate(mngr->link_clks[index].hs_clks.pixel_clk, pixel_clk);
  105. if (rc)
  106. DSI_ERR("failed to set clk rate for pixel clk, rc=%d\n", rc);
  107. else
  108. mngr->link_clks[index].freq.pix_clk_rate = pixel_clk;
  109. return rc;
  110. }
  111. /**
  112. * dsi_clk_set_byte_clk_rate() - set frequency for byte clock
  113. * @client: DSI clock client pointer.
  114. * @byte_clk: Byte clock rate in Hz.
  115. * @byte_intf_clk: Byte interface clock rate in Hz.
  116. * @index: Index of the DSI controller.
  117. * return: error code in case of failure or 0 for success.
  118. */
  119. int dsi_clk_set_byte_clk_rate(void *client, u64 byte_clk,
  120. u64 byte_intf_clk, u32 index)
  121. {
  122. int rc = 0;
  123. struct dsi_clk_client_info *c = client;
  124. struct dsi_clk_mngr *mngr;
  125. mngr = c->mngr;
  126. rc = clk_set_rate(mngr->link_clks[index].hs_clks.byte_clk, byte_clk);
  127. if (rc)
  128. DSI_ERR("failed to set clk rate for byte clk, rc=%d\n", rc);
  129. else
  130. mngr->link_clks[index].freq.byte_clk_rate = byte_clk;
  131. if (mngr->link_clks[index].hs_clks.byte_intf_clk) {
  132. rc = clk_set_rate(mngr->link_clks[index].hs_clks.byte_intf_clk,
  133. byte_intf_clk);
  134. if (rc)
  135. DSI_ERR("failed to set clk rate for byte intf clk=%d\n",
  136. rc);
  137. else
  138. mngr->link_clks[index].freq.byte_intf_clk_rate =
  139. byte_intf_clk;
  140. }
  141. return rc;
  142. }
  143. /**
  144. * dsi_clk_update_parent() - update parent clocks for specified clock
  145. * @parent: link clock pair which are set as parent.
  146. * @child: link clock pair whose parent has to be set.
  147. */
  148. int dsi_clk_update_parent(struct dsi_clk_link_set *parent,
  149. struct dsi_clk_link_set *child)
  150. {
  151. int rc = 0;
  152. rc = clk_set_parent(child->byte_clk, parent->byte_clk);
  153. if (rc) {
  154. DSI_ERR("failed to set byte clk parent\n");
  155. goto error;
  156. }
  157. rc = clk_set_parent(child->pixel_clk, parent->pixel_clk);
  158. if (rc) {
  159. DSI_ERR("failed to set pixel clk parent\n");
  160. goto error;
  161. }
  162. error:
  163. return rc;
  164. }
  165. /**
  166. * dsi_clk_prepare_enable() - prepare and enable dsi src clocks
  167. * @clk: list of src clocks.
  168. *
  169. * @return: Zero on success and err no on failure.
  170. */
  171. int dsi_clk_prepare_enable(struct dsi_clk_link_set *clk)
  172. {
  173. int rc;
  174. rc = clk_prepare_enable(clk->byte_clk);
  175. if (rc) {
  176. DSI_ERR("failed to enable byte src clk %d\n", rc);
  177. return rc;
  178. }
  179. rc = clk_prepare_enable(clk->pixel_clk);
  180. if (rc) {
  181. DSI_ERR("failed to enable pixel src clk %d\n", rc);
  182. return rc;
  183. }
  184. return 0;
  185. }
  186. /**
  187. * dsi_clk_disable_unprepare() - disable and unprepare dsi src clocks
  188. * @clk: list of src clocks.
  189. */
  190. void dsi_clk_disable_unprepare(struct dsi_clk_link_set *clk)
  191. {
  192. clk_disable_unprepare(clk->pixel_clk);
  193. clk_disable_unprepare(clk->byte_clk);
  194. }
  195. int dsi_core_clk_start(struct dsi_core_clks *c_clks)
  196. {
  197. int rc = 0;
  198. if (c_clks->clks.mdp_core_clk) {
  199. rc = clk_prepare_enable(c_clks->clks.mdp_core_clk);
  200. if (rc) {
  201. DSI_ERR("failed to enable mdp_core_clk, rc=%d\n", rc);
  202. goto error;
  203. }
  204. }
  205. if (c_clks->clks.mnoc_clk) {
  206. rc = clk_prepare_enable(c_clks->clks.mnoc_clk);
  207. if (rc) {
  208. DSI_ERR("failed to enable mnoc_clk, rc=%d\n", rc);
  209. goto error_disable_core_clk;
  210. }
  211. }
  212. if (c_clks->clks.iface_clk) {
  213. rc = clk_prepare_enable(c_clks->clks.iface_clk);
  214. if (rc) {
  215. DSI_ERR("failed to enable iface_clk, rc=%d\n", rc);
  216. goto error_disable_mnoc_clk;
  217. }
  218. }
  219. if (c_clks->clks.bus_clk) {
  220. rc = clk_prepare_enable(c_clks->clks.bus_clk);
  221. if (rc) {
  222. DSI_ERR("failed to enable bus_clk, rc=%d\n", rc);
  223. goto error_disable_iface_clk;
  224. }
  225. }
  226. if (c_clks->clks.core_mmss_clk) {
  227. rc = clk_prepare_enable(c_clks->clks.core_mmss_clk);
  228. if (rc) {
  229. DSI_ERR("failed to enable core_mmss_clk, rc=%d\n", rc);
  230. goto error_disable_bus_clk;
  231. }
  232. }
  233. return rc;
  234. error_disable_bus_clk:
  235. if (c_clks->clks.bus_clk)
  236. clk_disable_unprepare(c_clks->clks.bus_clk);
  237. error_disable_iface_clk:
  238. if (c_clks->clks.iface_clk)
  239. clk_disable_unprepare(c_clks->clks.iface_clk);
  240. error_disable_mnoc_clk:
  241. if (c_clks->clks.mnoc_clk)
  242. clk_disable_unprepare(c_clks->clks.mnoc_clk);
  243. error_disable_core_clk:
  244. if (c_clks->clks.mdp_core_clk)
  245. clk_disable_unprepare(c_clks->clks.mdp_core_clk);
  246. error:
  247. return rc;
  248. }
  249. int dsi_core_clk_stop(struct dsi_core_clks *c_clks)
  250. {
  251. int rc = 0;
  252. if (c_clks->clks.core_mmss_clk)
  253. clk_disable_unprepare(c_clks->clks.core_mmss_clk);
  254. if (c_clks->clks.bus_clk)
  255. clk_disable_unprepare(c_clks->clks.bus_clk);
  256. if (c_clks->clks.iface_clk)
  257. clk_disable_unprepare(c_clks->clks.iface_clk);
  258. if (c_clks->clks.mnoc_clk)
  259. clk_disable_unprepare(c_clks->clks.mnoc_clk);
  260. if (c_clks->clks.mdp_core_clk)
  261. clk_disable_unprepare(c_clks->clks.mdp_core_clk);
  262. return rc;
  263. }
  264. static int dsi_link_hs_clk_set_rate(struct dsi_link_hs_clk_info *link_hs_clks,
  265. int index)
  266. {
  267. int rc = 0;
  268. struct dsi_clk_mngr *mngr;
  269. struct dsi_link_clks *l_clks;
  270. if (index >= MAX_DSI_CTRL) {
  271. DSI_ERR("Invalid DSI ctrl index\n");
  272. return -EINVAL;
  273. }
  274. l_clks = container_of(link_hs_clks, struct dsi_link_clks, hs_clks);
  275. mngr = container_of(l_clks, struct dsi_clk_mngr, link_clks[index]);
  276. /*
  277. * In an ideal world, cont_splash_enabled should not be required inside
  278. * the clock manager. But, in the current driver cont_splash_enabled
  279. * flag is set inside mdp driver and there is no interface event
  280. * associated with this flag setting.
  281. */
  282. if (mngr->is_cont_splash_enabled)
  283. return 0;
  284. rc = clk_set_rate(link_hs_clks->byte_clk,
  285. l_clks->freq.byte_clk_rate);
  286. if (rc) {
  287. DSI_ERR("clk_set_rate failed for byte_clk rc = %d\n", rc);
  288. goto error;
  289. }
  290. rc = clk_set_rate(link_hs_clks->pixel_clk,
  291. l_clks->freq.pix_clk_rate);
  292. if (rc) {
  293. DSI_ERR("clk_set_rate failed for pixel_clk rc = %d\n", rc);
  294. goto error;
  295. }
  296. /*
  297. * If byte_intf_clk is present, set rate for that too.
  298. */
  299. if (link_hs_clks->byte_intf_clk) {
  300. rc = clk_set_rate(link_hs_clks->byte_intf_clk,
  301. l_clks->freq.byte_intf_clk_rate);
  302. if (rc) {
  303. DSI_ERR("set_rate failed for byte_intf_clk rc = %d\n",
  304. rc);
  305. goto error;
  306. }
  307. }
  308. error:
  309. return rc;
  310. }
  311. static int dsi_link_hs_clk_prepare(struct dsi_link_hs_clk_info *link_hs_clks)
  312. {
  313. int rc = 0;
  314. rc = clk_prepare(link_hs_clks->byte_clk);
  315. if (rc) {
  316. DSI_ERR("Failed to prepare dsi byte clk, rc=%d\n", rc);
  317. goto byte_clk_err;
  318. }
  319. rc = clk_prepare(link_hs_clks->pixel_clk);
  320. if (rc) {
  321. DSI_ERR("Failed to prepare dsi pixel clk, rc=%d\n", rc);
  322. goto pixel_clk_err;
  323. }
  324. if (link_hs_clks->byte_intf_clk) {
  325. rc = clk_prepare(link_hs_clks->byte_intf_clk);
  326. if (rc) {
  327. DSI_ERR("Failed to prepare dsi byte intf clk, rc=%d\n",
  328. rc);
  329. goto byte_intf_clk_err;
  330. }
  331. }
  332. return rc;
  333. byte_intf_clk_err:
  334. clk_unprepare(link_hs_clks->pixel_clk);
  335. pixel_clk_err:
  336. clk_unprepare(link_hs_clks->byte_clk);
  337. byte_clk_err:
  338. return rc;
  339. }
  340. static void dsi_link_hs_clk_unprepare(struct dsi_link_hs_clk_info *link_hs_clks)
  341. {
  342. if (link_hs_clks->byte_intf_clk)
  343. clk_unprepare(link_hs_clks->byte_intf_clk);
  344. clk_unprepare(link_hs_clks->pixel_clk);
  345. clk_unprepare(link_hs_clks->byte_clk);
  346. }
  347. static int dsi_link_hs_clk_enable(struct dsi_link_hs_clk_info *link_hs_clks)
  348. {
  349. int rc = 0;
  350. rc = clk_enable(link_hs_clks->byte_clk);
  351. if (rc) {
  352. DSI_ERR("Failed to enable dsi byte clk, rc=%d\n", rc);
  353. goto byte_clk_err;
  354. }
  355. rc = clk_enable(link_hs_clks->pixel_clk);
  356. if (rc) {
  357. DSI_ERR("Failed to enable dsi pixel clk, rc=%d\n", rc);
  358. goto pixel_clk_err;
  359. }
  360. if (link_hs_clks->byte_intf_clk) {
  361. rc = clk_enable(link_hs_clks->byte_intf_clk);
  362. if (rc) {
  363. DSI_ERR("Failed to enable dsi byte intf clk, rc=%d\n",
  364. rc);
  365. goto byte_intf_clk_err;
  366. }
  367. }
  368. return rc;
  369. byte_intf_clk_err:
  370. clk_disable(link_hs_clks->pixel_clk);
  371. pixel_clk_err:
  372. clk_disable(link_hs_clks->byte_clk);
  373. byte_clk_err:
  374. return rc;
  375. }
  376. static void dsi_link_hs_clk_disable(struct dsi_link_hs_clk_info *link_hs_clks)
  377. {
  378. if (link_hs_clks->byte_intf_clk)
  379. clk_disable(link_hs_clks->byte_intf_clk);
  380. clk_disable(link_hs_clks->pixel_clk);
  381. clk_disable(link_hs_clks->byte_clk);
  382. }
  383. /**
  384. * dsi_link_clk_start() - enable dsi link clocks
  385. */
  386. static int dsi_link_hs_clk_start(struct dsi_link_hs_clk_info *link_hs_clks,
  387. enum dsi_link_clk_op_type op_type, int index)
  388. {
  389. int rc = 0;
  390. if (index >= MAX_DSI_CTRL) {
  391. DSI_ERR("Invalid DSI ctrl index\n");
  392. return -EINVAL;
  393. }
  394. if (op_type & DSI_LINK_CLK_SET_RATE) {
  395. rc = dsi_link_hs_clk_set_rate(link_hs_clks, index);
  396. if (rc) {
  397. DSI_ERR("failed to set HS clk rates, rc = %d\n", rc);
  398. goto error;
  399. }
  400. }
  401. if (op_type & DSI_LINK_CLK_PREPARE) {
  402. rc = dsi_link_hs_clk_prepare(link_hs_clks);
  403. if (rc) {
  404. DSI_ERR("failed to prepare link HS clks, rc = %d\n",
  405. rc);
  406. goto error;
  407. }
  408. }
  409. if (op_type & DSI_LINK_CLK_ENABLE) {
  410. rc = dsi_link_hs_clk_enable(link_hs_clks);
  411. if (rc) {
  412. DSI_ERR("failed to enable link HS clks, rc = %d\n", rc);
  413. goto error_unprepare;
  414. }
  415. }
  416. DSI_DEBUG("HS Link clocks are enabled\n");
  417. return rc;
  418. error_unprepare:
  419. dsi_link_hs_clk_unprepare(link_hs_clks);
  420. error:
  421. return rc;
  422. }
  423. /**
  424. * dsi_link_clk_stop() - Stop DSI link clocks.
  425. */
  426. static int dsi_link_hs_clk_stop(struct dsi_link_hs_clk_info *link_hs_clks)
  427. {
  428. dsi_link_hs_clk_disable(link_hs_clks);
  429. dsi_link_hs_clk_unprepare(link_hs_clks);
  430. DSI_DEBUG("HS Link clocks disabled\n");
  431. return 0;
  432. }
  433. static int dsi_link_lp_clk_start(struct dsi_link_lp_clk_info *link_lp_clks,
  434. int index)
  435. {
  436. int rc = 0;
  437. struct dsi_clk_mngr *mngr;
  438. struct dsi_link_clks *l_clks;
  439. if (index >= MAX_DSI_CTRL) {
  440. DSI_ERR("Invalid DSI ctrl index\n");
  441. return -EINVAL;
  442. }
  443. l_clks = container_of(link_lp_clks, struct dsi_link_clks, lp_clks);
  444. mngr = container_of(l_clks, struct dsi_clk_mngr, link_clks[index]);
  445. if (!mngr)
  446. return -EINVAL;
  447. /*
  448. * In an ideal world, cont_splash_enabled should not be required inside
  449. * the clock manager. But, in the current driver cont_splash_enabled
  450. * flag is set inside mdp driver and there is no interface event
  451. * associated with this flag setting. Also, set rate for clock need not
  452. * be called for every enable call. It should be done only once when
  453. * coming out of suspend.
  454. */
  455. if (mngr->is_cont_splash_enabled)
  456. goto prepare;
  457. rc = clk_set_rate(link_lp_clks->esc_clk, l_clks->freq.esc_clk_rate);
  458. if (rc) {
  459. DSI_ERR("clk_set_rate failed for esc_clk rc = %d\n", rc);
  460. goto error;
  461. }
  462. prepare:
  463. rc = clk_prepare_enable(link_lp_clks->esc_clk);
  464. if (rc) {
  465. DSI_ERR("Failed to enable dsi esc clk\n");
  466. clk_unprepare(l_clks->lp_clks.esc_clk);
  467. }
  468. error:
  469. DSI_DEBUG("LP Link clocks are enabled\n");
  470. return rc;
  471. }
  472. static int dsi_link_lp_clk_stop(
  473. struct dsi_link_lp_clk_info *link_lp_clks)
  474. {
  475. struct dsi_link_clks *l_clks;
  476. l_clks = container_of(link_lp_clks, struct dsi_link_clks, lp_clks);
  477. clk_disable_unprepare(l_clks->lp_clks.esc_clk);
  478. DSI_DEBUG("LP Link clocks are disabled\n");
  479. return 0;
  480. }
  481. static int dsi_display_core_clk_enable(struct dsi_core_clks *clks,
  482. u32 ctrl_count, u32 master_ndx)
  483. {
  484. int rc = 0;
  485. int i;
  486. struct dsi_core_clks *clk, *m_clks;
  487. /*
  488. * In case of split DSI usecases, the clock for master controller should
  489. * be enabled before the other controller. Master controller in the
  490. * clock context refers to the controller that sources the clock.
  491. */
  492. m_clks = &clks[master_ndx];
  493. rc = dsi_core_clk_start(m_clks);
  494. if (rc) {
  495. DSI_ERR("failed to turn on master clocks, rc=%d\n", rc);
  496. goto error;
  497. }
  498. /* Turn on rest of the core clocks */
  499. for (i = 0; i < ctrl_count; i++) {
  500. clk = &clks[i];
  501. if (!clk || (clk == m_clks))
  502. continue;
  503. rc = dsi_core_clk_start(clk);
  504. if (rc) {
  505. DSI_ERR("failed to turn on clocks, rc=%d\n", rc);
  506. goto error_disable_master;
  507. }
  508. }
  509. return rc;
  510. error_disable_master:
  511. (void)dsi_core_clk_stop(m_clks);
  512. error:
  513. return rc;
  514. }
  515. static int dsi_display_link_clk_enable(struct dsi_link_clks *clks,
  516. enum dsi_lclk_type l_type, u32 ctrl_count, u32 master_ndx)
  517. {
  518. int rc = 0;
  519. int i;
  520. struct dsi_link_clks *clk, *m_clks;
  521. struct dsi_clk_mngr *mngr;
  522. mngr = container_of(clks, struct dsi_clk_mngr, link_clks[master_ndx]);
  523. /*
  524. * In case of split DSI usecases, the clock for master controller should
  525. * be enabled before the other controller. Master controller in the
  526. * clock context refers to the controller that sources the clock.
  527. */
  528. m_clks = &clks[master_ndx];
  529. if (l_type & DSI_LINK_LP_CLK) {
  530. rc = dsi_link_lp_clk_start(&m_clks->lp_clks, master_ndx);
  531. if (rc) {
  532. DSI_ERR("failed to turn on master lp link clocks, rc=%d\n",
  533. rc);
  534. goto error;
  535. }
  536. }
  537. if (l_type & DSI_LINK_HS_CLK) {
  538. if (!mngr->is_cont_splash_enabled) {
  539. mngr->phy_config_cb(mngr->priv_data, true);
  540. mngr->phy_pll_toggle_cb(mngr->priv_data, true);
  541. }
  542. rc = dsi_link_hs_clk_start(&m_clks->hs_clks,
  543. DSI_LINK_CLK_START, master_ndx);
  544. if (rc) {
  545. DSI_ERR("failed to turn on master hs link clocks, rc=%d\n",
  546. rc);
  547. goto error;
  548. }
  549. }
  550. for (i = 0; i < ctrl_count; i++) {
  551. clk = &clks[i];
  552. if (!clk || (clk == m_clks))
  553. continue;
  554. if (l_type & DSI_LINK_LP_CLK) {
  555. rc = dsi_link_lp_clk_start(&clk->lp_clks, i);
  556. if (rc) {
  557. DSI_ERR("failed to turn on lp link clocks, rc=%d\n",
  558. rc);
  559. goto error_disable_master;
  560. }
  561. }
  562. if (l_type & DSI_LINK_HS_CLK) {
  563. rc = dsi_link_hs_clk_start(&clk->hs_clks,
  564. DSI_LINK_CLK_START, i);
  565. if (rc) {
  566. DSI_ERR("failed to turn on hs link clocks, rc=%d\n",
  567. rc);
  568. goto error_disable_master;
  569. }
  570. }
  571. }
  572. return rc;
  573. error_disable_master:
  574. if (l_type == DSI_LINK_LP_CLK)
  575. (void)dsi_link_lp_clk_stop(&m_clks->lp_clks);
  576. else if (l_type == DSI_LINK_HS_CLK)
  577. (void)dsi_link_hs_clk_stop(&m_clks->hs_clks);
  578. error:
  579. return rc;
  580. }
  581. static int dsi_display_core_clk_disable(struct dsi_core_clks *clks,
  582. u32 ctrl_count, u32 master_ndx)
  583. {
  584. int rc = 0;
  585. int i;
  586. struct dsi_core_clks *clk, *m_clks;
  587. /*
  588. * In case of split DSI usecases, clock for slave DSI controllers should
  589. * be disabled first before disabling clock for master controller. Slave
  590. * controllers in the clock context refer to controller which source
  591. * clock from another controller.
  592. */
  593. m_clks = &clks[master_ndx];
  594. /* Turn off non-master core clocks */
  595. for (i = 0; i < ctrl_count; i++) {
  596. clk = &clks[i];
  597. if (!clk || (clk == m_clks))
  598. continue;
  599. rc = dsi_core_clk_stop(clk);
  600. if (rc) {
  601. DSI_DEBUG("failed to turn off clocks, rc=%d\n", rc);
  602. goto error;
  603. }
  604. }
  605. rc = dsi_core_clk_stop(m_clks);
  606. if (rc) {
  607. DSI_ERR("failed to turn off master clocks, rc=%d\n", rc);
  608. goto error;
  609. }
  610. error:
  611. return rc;
  612. }
  613. static int dsi_display_link_clk_disable(struct dsi_link_clks *clks,
  614. enum dsi_lclk_type l_type, u32 ctrl_count, u32 master_ndx)
  615. {
  616. int rc = 0;
  617. int i;
  618. struct dsi_link_clks *clk, *m_clks;
  619. struct dsi_clk_mngr *mngr;
  620. mngr = container_of(clks, struct dsi_clk_mngr, link_clks[master_ndx]);
  621. /*
  622. * In case of split DSI usecases, clock for slave DSI controllers should
  623. * be disabled first before disabling clock for master controller. Slave
  624. * controllers in the clock context refer to controller which source
  625. * clock from another controller.
  626. */
  627. m_clks = &clks[master_ndx];
  628. /* Turn off non-master link clocks */
  629. for (i = 0; i < ctrl_count; i++) {
  630. clk = &clks[i];
  631. if (!clk || (clk == m_clks))
  632. continue;
  633. if (l_type & DSI_LINK_LP_CLK) {
  634. rc = dsi_link_lp_clk_stop(&clk->lp_clks);
  635. if (rc)
  636. DSI_ERR("failed to turn off lp link clocks, rc=%d\n",
  637. rc);
  638. }
  639. if (l_type & DSI_LINK_HS_CLK) {
  640. rc = dsi_link_hs_clk_stop(&clk->hs_clks);
  641. if (rc)
  642. DSI_ERR("failed to turn off hs link clocks, rc=%d\n",
  643. rc);
  644. }
  645. }
  646. if (l_type & DSI_LINK_LP_CLK) {
  647. rc = dsi_link_lp_clk_stop(&m_clks->lp_clks);
  648. if (rc)
  649. DSI_ERR("failed to turn off master lp link clocks, rc=%d\n",
  650. rc);
  651. }
  652. if (l_type & DSI_LINK_HS_CLK) {
  653. rc = dsi_link_hs_clk_stop(&m_clks->hs_clks);
  654. if (rc)
  655. DSI_ERR("failed to turn off master hs link clocks, rc=%d\n",
  656. rc);
  657. mngr->phy_pll_toggle_cb(mngr->priv_data, false);
  658. }
  659. return rc;
  660. }
  661. static int dsi_clk_update_link_clk_state(struct dsi_clk_mngr *mngr,
  662. struct dsi_link_clks *l_clks, enum dsi_lclk_type l_type, u32 l_state,
  663. bool enable)
  664. {
  665. int rc = 0;
  666. if (!mngr)
  667. return -EINVAL;
  668. if (enable) {
  669. if (mngr->pre_clkon_cb) {
  670. rc = mngr->pre_clkon_cb(mngr->priv_data, DSI_LINK_CLK,
  671. l_type, l_state);
  672. if (rc) {
  673. DSI_ERR("pre link clk on cb failed for type %d\n",
  674. l_type);
  675. goto error;
  676. }
  677. }
  678. rc = dsi_display_link_clk_enable(l_clks, l_type,
  679. mngr->dsi_ctrl_count, mngr->master_ndx);
  680. if (rc) {
  681. DSI_ERR("failed to start link clk type %d rc=%d\n",
  682. l_type, rc);
  683. goto error;
  684. }
  685. if (mngr->post_clkon_cb) {
  686. rc = mngr->post_clkon_cb(mngr->priv_data, DSI_LINK_CLK,
  687. l_type, l_state);
  688. if (rc) {
  689. DSI_ERR("post link clk on cb failed for type %d\n",
  690. l_type);
  691. goto error;
  692. }
  693. }
  694. } else {
  695. if (mngr->pre_clkoff_cb) {
  696. rc = mngr->pre_clkoff_cb(mngr->priv_data,
  697. DSI_LINK_CLK, l_type, l_state);
  698. if (rc)
  699. DSI_ERR("pre link clk off cb failed\n");
  700. }
  701. rc = dsi_display_link_clk_disable(l_clks, l_type,
  702. mngr->dsi_ctrl_count, mngr->master_ndx);
  703. if (rc) {
  704. DSI_ERR("failed to stop link clk type %d, rc = %d\n",
  705. l_type, rc);
  706. goto error;
  707. }
  708. if (mngr->post_clkoff_cb) {
  709. rc = mngr->post_clkoff_cb(mngr->priv_data,
  710. DSI_LINK_CLK, l_type, l_state);
  711. if (rc)
  712. DSI_ERR("post link clk off cb failed\n");
  713. }
  714. }
  715. error:
  716. return rc;
  717. }
  718. static int dsi_update_core_clks(struct dsi_clk_mngr *mngr,
  719. struct dsi_core_clks *c_clks)
  720. {
  721. int rc = 0;
  722. if (mngr->core_clk_state == DSI_CLK_OFF) {
  723. rc = mngr->pre_clkon_cb(mngr->priv_data,
  724. DSI_CORE_CLK,
  725. DSI_LINK_NONE,
  726. DSI_CLK_ON);
  727. if (rc) {
  728. DSI_ERR("failed to turn on MDP FS rc= %d\n", rc);
  729. goto error;
  730. }
  731. }
  732. rc = dsi_display_core_clk_enable(c_clks, mngr->dsi_ctrl_count,
  733. mngr->master_ndx);
  734. if (rc) {
  735. DSI_ERR("failed to turn on core clks rc = %d\n", rc);
  736. goto error;
  737. }
  738. if (mngr->post_clkon_cb) {
  739. rc = mngr->post_clkon_cb(mngr->priv_data,
  740. DSI_CORE_CLK,
  741. DSI_LINK_NONE,
  742. DSI_CLK_ON);
  743. if (rc)
  744. DSI_ERR("post clk on cb failed, rc = %d\n", rc);
  745. }
  746. mngr->core_clk_state = DSI_CLK_ON;
  747. error:
  748. return rc;
  749. }
  750. static int dsi_update_clk_state(struct dsi_clk_mngr *mngr,
  751. struct dsi_core_clks *c_clks, u32 c_state,
  752. struct dsi_link_clks *l_clks, u32 l_state)
  753. {
  754. int rc = 0;
  755. bool l_c_on = false;
  756. if (!mngr)
  757. return -EINVAL;
  758. DSI_DEBUG("c_state = %d, l_state = %d\n",
  759. c_clks ? c_state : -1, l_clks ? l_state : -1);
  760. /*
  761. * Below is the sequence to toggle DSI clocks:
  762. * 1. For ON sequence, Core clocks before link clocks
  763. * 2. For OFF sequence, Link clocks before core clocks.
  764. */
  765. if (c_clks && (c_state == DSI_CLK_ON))
  766. rc = dsi_update_core_clks(mngr, c_clks);
  767. if (rc)
  768. goto error;
  769. if (l_clks) {
  770. if (l_state == DSI_CLK_ON) {
  771. rc = dsi_clk_update_link_clk_state(mngr, l_clks,
  772. DSI_LINK_LP_CLK, l_state, true);
  773. if (rc)
  774. goto error;
  775. rc = dsi_clk_update_link_clk_state(mngr, l_clks,
  776. DSI_LINK_HS_CLK, l_state, true);
  777. if (rc)
  778. goto error;
  779. } else {
  780. /*
  781. * Two conditions that need to be checked for Link
  782. * clocks:
  783. * 1. Link clocks need core clocks to be on when
  784. * transitioning from EARLY_GATE to OFF state.
  785. * 2. ULPS mode might have to be enabled in case of OFF
  786. * state. For ULPS, Link clocks should be turned ON
  787. * first before they are turned off again.
  788. *
  789. * If Link is going from EARLY_GATE to OFF state AND
  790. * Core clock is already in EARLY_GATE or OFF state,
  791. * turn on Core clocks and link clocks.
  792. *
  793. * ULPS state is managed as part of the pre_clkoff_cb.
  794. */
  795. if ((l_state == DSI_CLK_OFF) &&
  796. (mngr->link_clk_state ==
  797. DSI_CLK_EARLY_GATE) &&
  798. (mngr->core_clk_state !=
  799. DSI_CLK_ON)) {
  800. rc = dsi_display_core_clk_enable(
  801. mngr->core_clks, mngr->dsi_ctrl_count,
  802. mngr->master_ndx);
  803. if (rc) {
  804. DSI_ERR("core clks did not start\n");
  805. goto error;
  806. }
  807. rc = dsi_display_link_clk_enable(l_clks,
  808. (DSI_LINK_LP_CLK & DSI_LINK_HS_CLK),
  809. mngr->dsi_ctrl_count, mngr->master_ndx);
  810. if (rc) {
  811. DSI_ERR("LP Link clks did not start\n");
  812. goto error;
  813. }
  814. l_c_on = true;
  815. DSI_DEBUG("ECG: core and Link_on\n");
  816. }
  817. rc = dsi_clk_update_link_clk_state(mngr, l_clks,
  818. DSI_LINK_HS_CLK, l_state, false);
  819. if (rc)
  820. goto error;
  821. rc = dsi_clk_update_link_clk_state(mngr, l_clks,
  822. DSI_LINK_LP_CLK, l_state, false);
  823. if (rc)
  824. goto error;
  825. /*
  826. * This check is to save unnecessary clock state
  827. * change when going from EARLY_GATE to OFF. In the
  828. * case where the request happens for both Core and Link
  829. * clocks in the same call, core clocks need to be
  830. * turned on first before OFF state can be entered.
  831. *
  832. * Core clocks are turned on here for Link clocks to go
  833. * to OFF state. If core clock request is also present,
  834. * then core clocks can be turned off Core clocks are
  835. * transitioned to OFF state.
  836. */
  837. if (l_c_on && (!(c_clks && (c_state == DSI_CLK_OFF)
  838. && (mngr->core_clk_state ==
  839. DSI_CLK_EARLY_GATE)))) {
  840. rc = dsi_display_core_clk_disable(
  841. mngr->core_clks, mngr->dsi_ctrl_count,
  842. mngr->master_ndx);
  843. if (rc) {
  844. DSI_ERR("core clks did not stop\n");
  845. goto error;
  846. }
  847. l_c_on = false;
  848. DSI_DEBUG("ECG: core off\n");
  849. } else
  850. DSI_DEBUG("ECG: core off skip\n");
  851. }
  852. mngr->link_clk_state = l_state;
  853. }
  854. if (c_clks && (c_state != DSI_CLK_ON)) {
  855. /*
  856. * When going to OFF state from EARLY GATE state, Core clocks
  857. * should be turned on first so that the IOs can be clamped.
  858. * l_c_on flag is set, then the core clocks were turned before
  859. * to the Link clocks go to OFF state. So Core clocks are
  860. * already ON and this step can be skipped.
  861. *
  862. * IOs are clamped in pre_clkoff_cb callback.
  863. */
  864. if ((c_state == DSI_CLK_OFF) &&
  865. (mngr->core_clk_state ==
  866. DSI_CLK_EARLY_GATE) && !l_c_on) {
  867. rc = dsi_display_core_clk_enable(mngr->core_clks,
  868. mngr->dsi_ctrl_count, mngr->master_ndx);
  869. if (rc) {
  870. DSI_ERR("core clks did not start\n");
  871. goto error;
  872. }
  873. DSI_DEBUG("ECG: core on\n");
  874. } else
  875. DSI_DEBUG("ECG: core on skip\n");
  876. if (mngr->pre_clkoff_cb) {
  877. rc = mngr->pre_clkoff_cb(mngr->priv_data,
  878. DSI_CORE_CLK,
  879. DSI_LINK_NONE,
  880. c_state);
  881. if (rc)
  882. DSI_ERR("pre core clk off cb failed\n");
  883. }
  884. rc = dsi_display_core_clk_disable(c_clks, mngr->dsi_ctrl_count,
  885. mngr->master_ndx);
  886. if (rc) {
  887. DSI_ERR("failed to turn off core clks rc = %d\n", rc);
  888. goto error;
  889. }
  890. if (c_state == DSI_CLK_OFF) {
  891. if (mngr->post_clkoff_cb) {
  892. rc = mngr->post_clkoff_cb(mngr->priv_data,
  893. DSI_CORE_CLK,
  894. DSI_LINK_NONE,
  895. DSI_CLK_OFF);
  896. if (rc)
  897. DSI_ERR("post clkoff cb fail, rc = %d\n",
  898. rc);
  899. }
  900. }
  901. mngr->core_clk_state = c_state;
  902. }
  903. error:
  904. return rc;
  905. }
  906. static int dsi_recheck_clk_state(struct dsi_clk_mngr *mngr)
  907. {
  908. int rc = 0;
  909. struct list_head *pos = NULL;
  910. struct dsi_clk_client_info *c;
  911. u32 new_core_clk_state = DSI_CLK_OFF;
  912. u32 new_link_clk_state = DSI_CLK_OFF;
  913. u32 old_c_clk_state = DSI_CLK_OFF;
  914. u32 old_l_clk_state = DSI_CLK_OFF;
  915. struct dsi_core_clks *c_clks = NULL;
  916. struct dsi_link_clks *l_clks = NULL;
  917. /*
  918. * Conditions to maintain DSI manager clock state based on
  919. * clock states of various clients:
  920. * 1. If any client has clock in ON state, DSI manager clock state
  921. * should be ON.
  922. * 2. If any client is in ECG state with rest of them turned OFF,
  923. * go to Early gate state.
  924. * 3. If all clients have clocks as OFF, then go to OFF state.
  925. */
  926. list_for_each(pos, &mngr->client_list) {
  927. c = list_entry(pos, struct dsi_clk_client_info, list);
  928. if (c->core_clk_state == DSI_CLK_ON) {
  929. new_core_clk_state = DSI_CLK_ON;
  930. break;
  931. } else if (c->core_clk_state == DSI_CLK_EARLY_GATE) {
  932. new_core_clk_state = DSI_CLK_EARLY_GATE;
  933. }
  934. }
  935. list_for_each(pos, &mngr->client_list) {
  936. c = list_entry(pos, struct dsi_clk_client_info, list);
  937. if (c->link_clk_state == DSI_CLK_ON) {
  938. new_link_clk_state = DSI_CLK_ON;
  939. break;
  940. } else if (c->link_clk_state == DSI_CLK_EARLY_GATE) {
  941. new_link_clk_state = DSI_CLK_EARLY_GATE;
  942. }
  943. }
  944. if (new_core_clk_state != mngr->core_clk_state)
  945. c_clks = mngr->core_clks;
  946. if (new_link_clk_state != mngr->link_clk_state)
  947. l_clks = mngr->link_clks;
  948. old_c_clk_state = mngr->core_clk_state;
  949. old_l_clk_state = mngr->link_clk_state;
  950. DSI_DEBUG("c_clk_state (%d -> %d)\n", old_c_clk_state,
  951. new_core_clk_state);
  952. DSI_DEBUG("l_clk_state (%d -> %d)\n", old_l_clk_state,
  953. new_link_clk_state);
  954. if (c_clks || l_clks) {
  955. rc = dsi_update_clk_state(mngr, c_clks, new_core_clk_state,
  956. l_clks, new_link_clk_state);
  957. if (rc) {
  958. DSI_ERR("failed to update clock state, rc = %d\n", rc);
  959. goto error;
  960. }
  961. }
  962. error:
  963. return rc;
  964. }
  965. int dsi_clk_req_state(void *client, enum dsi_clk_type clk,
  966. enum dsi_clk_state state)
  967. {
  968. int rc = 0;
  969. struct dsi_clk_client_info *c = client;
  970. struct dsi_clk_mngr *mngr;
  971. bool changed = false;
  972. if (!client || !clk || clk > (DSI_CORE_CLK | DSI_LINK_CLK) ||
  973. state > DSI_CLK_EARLY_GATE) {
  974. DSI_ERR("Invalid params, client = %pK, clk = 0x%x, state = %d\n",
  975. client, clk, state);
  976. return -EINVAL;
  977. }
  978. mngr = c->mngr;
  979. mutex_lock(&mngr->clk_mutex);
  980. DSI_DEBUG("[%s]%s: CLK=%d, new_state=%d, core=%d, linkl=%d\n",
  981. mngr->name, c->name, clk, state, c->core_clk_state,
  982. c->link_clk_state);
  983. /*
  984. * Clock refcount handling as below:
  985. * i. Increment refcount whenever ON is called.
  986. * ii. Decrement refcount when transitioning from ON state to
  987. * either OFF or EARLY_GATE.
  988. * iii. Do not decrement refcount when changing from
  989. * EARLY_GATE to OFF.
  990. */
  991. if (state == DSI_CLK_ON) {
  992. if (clk & DSI_CORE_CLK) {
  993. c->core_refcount++;
  994. if (c->core_clk_state != DSI_CLK_ON) {
  995. c->core_clk_state = DSI_CLK_ON;
  996. changed = true;
  997. }
  998. }
  999. if (clk & DSI_LINK_CLK) {
  1000. c->link_refcount++;
  1001. if (c->link_clk_state != DSI_CLK_ON) {
  1002. c->link_clk_state = DSI_CLK_ON;
  1003. changed = true;
  1004. }
  1005. }
  1006. } else if ((state == DSI_CLK_EARLY_GATE) ||
  1007. (state == DSI_CLK_OFF)) {
  1008. if (clk & DSI_CORE_CLK) {
  1009. if (c->core_refcount == 0) {
  1010. if ((c->core_clk_state ==
  1011. DSI_CLK_EARLY_GATE) &&
  1012. (state == DSI_CLK_OFF)) {
  1013. changed = true;
  1014. c->core_clk_state = DSI_CLK_OFF;
  1015. } else {
  1016. DSI_WARN("Core refcount is zero for %s\n",
  1017. c->name);
  1018. }
  1019. } else {
  1020. c->core_refcount--;
  1021. if (c->core_refcount == 0) {
  1022. c->core_clk_state = state;
  1023. changed = true;
  1024. }
  1025. }
  1026. }
  1027. if (clk & DSI_LINK_CLK) {
  1028. if (c->link_refcount == 0) {
  1029. if ((c->link_clk_state ==
  1030. DSI_CLK_EARLY_GATE) &&
  1031. (state == DSI_CLK_OFF)) {
  1032. changed = true;
  1033. c->link_clk_state = DSI_CLK_OFF;
  1034. } else {
  1035. DSI_WARN("Link refcount is zero for %s\n",
  1036. c->name);
  1037. }
  1038. } else {
  1039. c->link_refcount--;
  1040. if (c->link_refcount == 0) {
  1041. c->link_clk_state = state;
  1042. changed = true;
  1043. }
  1044. }
  1045. }
  1046. }
  1047. DSI_DEBUG("[%s]%s: change=%d, Core (ref=%d, state=%d), Link (ref=%d, state=%d)\n",
  1048. mngr->name, c->name, changed, c->core_refcount,
  1049. c->core_clk_state, c->link_refcount, c->link_clk_state);
  1050. if (changed) {
  1051. rc = dsi_recheck_clk_state(mngr);
  1052. if (rc)
  1053. DSI_ERR("Failed to adjust clock state rc = %d\n", rc);
  1054. }
  1055. mutex_unlock(&mngr->clk_mutex);
  1056. return rc;
  1057. }
  1058. DEFINE_MUTEX(dsi_mngr_clk_mutex);
  1059. static int dsi_display_link_clk_force_update(void *client)
  1060. {
  1061. int rc = 0;
  1062. struct dsi_clk_client_info *c = client;
  1063. struct dsi_clk_mngr *mngr;
  1064. struct dsi_link_clks *l_clks;
  1065. mngr = c->mngr;
  1066. mutex_lock(&mngr->clk_mutex);
  1067. l_clks = mngr->link_clks;
  1068. /*
  1069. * When link_clk_state is DSI_CLK_OFF, don't change DSI clock rate
  1070. * since it is possible to be overwritten, and return -EAGAIN to
  1071. * dynamic DSI writing interface to defer the reenabling to the next
  1072. * drm commit.
  1073. */
  1074. if (mngr->link_clk_state == DSI_CLK_OFF) {
  1075. rc = -EAGAIN;
  1076. goto error;
  1077. }
  1078. rc = dsi_clk_update_link_clk_state(mngr, l_clks, (DSI_LINK_LP_CLK |
  1079. DSI_LINK_HS_CLK), DSI_CLK_OFF, false);
  1080. if (rc)
  1081. goto error;
  1082. rc = dsi_clk_update_link_clk_state(mngr, l_clks, (DSI_LINK_LP_CLK |
  1083. DSI_LINK_HS_CLK), DSI_CLK_ON, true);
  1084. if (rc)
  1085. goto error;
  1086. error:
  1087. mutex_unlock(&mngr->clk_mutex);
  1088. return rc;
  1089. }
  1090. int dsi_display_link_clk_force_update_ctrl(void *handle)
  1091. {
  1092. int rc = 0;
  1093. if (!handle) {
  1094. DSI_ERR("Invalid arg\n");
  1095. return -EINVAL;
  1096. }
  1097. mutex_lock(&dsi_mngr_clk_mutex);
  1098. rc = dsi_display_link_clk_force_update(handle);
  1099. mutex_unlock(&dsi_mngr_clk_mutex);
  1100. return rc;
  1101. }
  1102. int dsi_display_clk_ctrl(void *handle,
  1103. u32 clk_type, u32 clk_state)
  1104. {
  1105. int rc = 0;
  1106. if ((!handle) || (clk_type > DSI_ALL_CLKS) ||
  1107. (clk_state > DSI_CLK_EARLY_GATE)) {
  1108. DSI_ERR("Invalid arg\n");
  1109. return -EINVAL;
  1110. }
  1111. mutex_lock(&dsi_mngr_clk_mutex);
  1112. rc = dsi_clk_req_state(handle, clk_type, clk_state);
  1113. if (rc)
  1114. DSI_ERR("failed set clk state, rc = %d\n", rc);
  1115. mutex_unlock(&dsi_mngr_clk_mutex);
  1116. return rc;
  1117. }
  1118. void *dsi_register_clk_handle(void *clk_mngr, char *client)
  1119. {
  1120. void *handle = NULL;
  1121. struct dsi_clk_mngr *mngr = clk_mngr;
  1122. struct dsi_clk_client_info *c;
  1123. if (!mngr) {
  1124. DSI_ERR("bad params\n");
  1125. return ERR_PTR(-EINVAL);
  1126. }
  1127. mutex_lock(&mngr->clk_mutex);
  1128. c = kzalloc(sizeof(*c), GFP_KERNEL);
  1129. if (!c) {
  1130. handle = ERR_PTR(-ENOMEM);
  1131. goto error;
  1132. }
  1133. strlcpy(c->name, client, MAX_STRING_LEN);
  1134. c->mngr = mngr;
  1135. list_add(&c->list, &mngr->client_list);
  1136. DSI_DEBUG("[%s]: Added new client (%s)\n", mngr->name, c->name);
  1137. handle = c;
  1138. error:
  1139. mutex_unlock(&mngr->clk_mutex);
  1140. return handle;
  1141. }
  1142. int dsi_deregister_clk_handle(void *client)
  1143. {
  1144. int rc = 0;
  1145. struct dsi_clk_client_info *c = client;
  1146. struct dsi_clk_mngr *mngr;
  1147. struct list_head *pos = NULL;
  1148. struct list_head *tmp = NULL;
  1149. struct dsi_clk_client_info *node = NULL;
  1150. if (!client) {
  1151. DSI_ERR("Invalid params\n");
  1152. return -EINVAL;
  1153. }
  1154. mngr = c->mngr;
  1155. DSI_DEBUG("%s: ENTER\n", mngr->name);
  1156. mutex_lock(&mngr->clk_mutex);
  1157. c->core_clk_state = DSI_CLK_OFF;
  1158. c->link_clk_state = DSI_CLK_OFF;
  1159. rc = dsi_recheck_clk_state(mngr);
  1160. if (rc) {
  1161. DSI_ERR("clock state recheck failed rc = %d\n", rc);
  1162. goto error;
  1163. }
  1164. list_for_each_safe(pos, tmp, &mngr->client_list) {
  1165. node = list_entry(pos, struct dsi_clk_client_info,
  1166. list);
  1167. if (node == c) {
  1168. list_del(&node->list);
  1169. DSI_DEBUG("Removed device (%s)\n", node->name);
  1170. kfree(node);
  1171. break;
  1172. }
  1173. }
  1174. error:
  1175. mutex_unlock(&mngr->clk_mutex);
  1176. DSI_DEBUG("%s: EXIT, rc = %d\n", mngr->name, rc);
  1177. return rc;
  1178. }
  1179. void dsi_display_clk_mngr_update_splash_status(void *clk_mgr, bool status)
  1180. {
  1181. struct dsi_clk_mngr *mngr;
  1182. if (!clk_mgr) {
  1183. DSI_ERR("Invalid params\n");
  1184. return;
  1185. }
  1186. mngr = (struct dsi_clk_mngr *)clk_mgr;
  1187. mngr->is_cont_splash_enabled = status;
  1188. }
  1189. int dsi_display_dump_clk_handle_state(void *client)
  1190. {
  1191. struct dsi_clk_mngr *mngr;
  1192. struct dsi_clk_client_info *c = client;
  1193. if (!c || !c->mngr) {
  1194. DSI_ERR("Invalid params\n");
  1195. return -EINVAL;
  1196. }
  1197. mngr = c->mngr;
  1198. mutex_lock(&mngr->clk_mutex);
  1199. DSI_INFO("[%s]%s: Core (ref=%d, state=%d), Link (ref=%d, state=%d)\n",
  1200. mngr->name, c->name, c->core_refcount,
  1201. c->core_clk_state, c->link_refcount,
  1202. c->link_clk_state);
  1203. mutex_unlock(&mngr->clk_mutex);
  1204. return 0;
  1205. }
  1206. void *dsi_display_clk_mngr_register(struct dsi_clk_info *info)
  1207. {
  1208. struct dsi_clk_mngr *mngr;
  1209. int i = 0;
  1210. if (!info) {
  1211. DSI_ERR("Invalid params\n");
  1212. return ERR_PTR(-EINVAL);
  1213. }
  1214. mngr = kzalloc(sizeof(*mngr), GFP_KERNEL);
  1215. if (!mngr) {
  1216. mngr = ERR_PTR(-ENOMEM);
  1217. goto error;
  1218. }
  1219. mutex_init(&mngr->clk_mutex);
  1220. mngr->dsi_ctrl_count = info->dsi_ctrl_count;
  1221. mngr->master_ndx = info->master_ndx;
  1222. if (mngr->dsi_ctrl_count > MAX_DSI_CTRL) {
  1223. kfree(mngr);
  1224. return ERR_PTR(-EINVAL);
  1225. }
  1226. for (i = 0; i < mngr->dsi_ctrl_count; i++) {
  1227. memcpy(&mngr->core_clks[i].clks, &info->c_clks[i],
  1228. sizeof(struct dsi_core_clk_info));
  1229. memcpy(&mngr->link_clks[i].hs_clks, &info->l_hs_clks[i],
  1230. sizeof(struct dsi_link_hs_clk_info));
  1231. memcpy(&mngr->link_clks[i].lp_clks, &info->l_lp_clks[i],
  1232. sizeof(struct dsi_link_lp_clk_info));
  1233. mngr->ctrl_index[i] = info->ctrl_index[i];
  1234. }
  1235. INIT_LIST_HEAD(&mngr->client_list);
  1236. mngr->pre_clkon_cb = info->pre_clkon_cb;
  1237. mngr->post_clkon_cb = info->post_clkon_cb;
  1238. mngr->pre_clkoff_cb = info->pre_clkoff_cb;
  1239. mngr->post_clkoff_cb = info->post_clkoff_cb;
  1240. mngr->phy_config_cb = info->phy_config_cb;
  1241. mngr->phy_pll_toggle_cb = info->phy_pll_toggle_cb;
  1242. mngr->priv_data = info->priv_data;
  1243. memcpy(mngr->name, info->name, MAX_STRING_LEN);
  1244. error:
  1245. DSI_DEBUG("EXIT, rc = %ld\n", PTR_ERR(mngr));
  1246. return mngr;
  1247. }
  1248. int dsi_display_clk_mngr_deregister(void *clk_mngr)
  1249. {
  1250. int rc = 0;
  1251. struct dsi_clk_mngr *mngr = clk_mngr;
  1252. struct list_head *position = NULL;
  1253. struct list_head *tmp = NULL;
  1254. struct dsi_clk_client_info *node = NULL;
  1255. if (!mngr) {
  1256. DSI_ERR("Invalid params\n");
  1257. return -EINVAL;
  1258. }
  1259. DSI_DEBUG("%s: ENTER\n", mngr->name);
  1260. mutex_lock(&mngr->clk_mutex);
  1261. list_for_each_safe(position, tmp, &mngr->client_list) {
  1262. node = list_entry(position, struct dsi_clk_client_info,
  1263. list);
  1264. list_del(&node->list);
  1265. DSI_DEBUG("Removed device (%s)\n", node->name);
  1266. kfree(node);
  1267. }
  1268. rc = dsi_recheck_clk_state(mngr);
  1269. if (rc)
  1270. DSI_ERR("failed to disable all clocks\n");
  1271. mutex_unlock(&mngr->clk_mutex);
  1272. DSI_DEBUG("%s: EXIT, rc = %d\n", mngr->name, rc);
  1273. kfree(mngr);
  1274. return rc;
  1275. }