dsi_clk_manager.c 35 KB

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