dsi_clk_manager.c 35 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504
  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_display_link_clk_disable(l_clks,
  1101. (DSI_LINK_LP_CLK | DSI_LINK_HS_CLK),
  1102. mngr->dsi_ctrl_count, mngr->master_ndx);
  1103. if (rc) {
  1104. pr_err("%s, failed to stop link clk, rc = %d\n",
  1105. __func__, rc);
  1106. goto error;
  1107. }
  1108. rc = dsi_display_link_clk_enable(l_clks,
  1109. (DSI_LINK_LP_CLK | DSI_LINK_HS_CLK),
  1110. mngr->dsi_ctrl_count, mngr->master_ndx);
  1111. if (rc) {
  1112. pr_err("%s, failed to start link clk rc= %d\n",
  1113. __func__, rc);
  1114. goto error;
  1115. }
  1116. error:
  1117. mutex_unlock(&mngr->clk_mutex);
  1118. return rc;
  1119. }
  1120. int dsi_display_link_clk_force_update_ctrl(void *handle)
  1121. {
  1122. int rc = 0;
  1123. if (!handle) {
  1124. pr_err("%s: Invalid arg\n", __func__);
  1125. return -EINVAL;
  1126. }
  1127. mutex_lock(&dsi_mngr_clk_mutex);
  1128. rc = dsi_display_link_clk_force_update(handle);
  1129. mutex_unlock(&dsi_mngr_clk_mutex);
  1130. return rc;
  1131. }
  1132. int dsi_display_clk_ctrl(void *handle,
  1133. enum dsi_clk_type clk_type, enum dsi_clk_state clk_state)
  1134. {
  1135. int rc = 0;
  1136. if (!handle) {
  1137. pr_err("%s: Invalid arg\n", __func__);
  1138. return -EINVAL;
  1139. }
  1140. mutex_lock(&dsi_mngr_clk_mutex);
  1141. rc = dsi_clk_req_state(handle, clk_type, clk_state);
  1142. if (rc)
  1143. pr_err("%s: failed set clk state, rc = %d\n", __func__, rc);
  1144. mutex_unlock(&dsi_mngr_clk_mutex);
  1145. return rc;
  1146. }
  1147. void *dsi_register_clk_handle(void *clk_mngr, char *client)
  1148. {
  1149. void *handle = NULL;
  1150. struct dsi_clk_mngr *mngr = clk_mngr;
  1151. struct dsi_clk_client_info *c;
  1152. if (!mngr) {
  1153. pr_err("bad params\n");
  1154. return ERR_PTR(-EINVAL);
  1155. }
  1156. mutex_lock(&mngr->clk_mutex);
  1157. c = kzalloc(sizeof(*c), GFP_KERNEL);
  1158. if (!c) {
  1159. handle = ERR_PTR(-ENOMEM);
  1160. goto error;
  1161. }
  1162. strlcpy(c->name, client, MAX_STRING_LEN);
  1163. c->mngr = mngr;
  1164. list_add(&c->list, &mngr->client_list);
  1165. pr_debug("[%s]: Added new client (%s)\n", mngr->name, c->name);
  1166. handle = c;
  1167. error:
  1168. mutex_unlock(&mngr->clk_mutex);
  1169. return handle;
  1170. }
  1171. int dsi_deregister_clk_handle(void *client)
  1172. {
  1173. int rc = 0;
  1174. struct dsi_clk_client_info *c = client;
  1175. struct dsi_clk_mngr *mngr;
  1176. struct list_head *pos = NULL;
  1177. struct list_head *tmp = NULL;
  1178. struct dsi_clk_client_info *node = NULL;
  1179. if (!client) {
  1180. pr_err("Invalid params\n");
  1181. return -EINVAL;
  1182. }
  1183. mngr = c->mngr;
  1184. pr_debug("%s: ENTER\n", mngr->name);
  1185. mutex_lock(&mngr->clk_mutex);
  1186. c->core_clk_state = DSI_CLK_OFF;
  1187. c->link_clk_state = DSI_CLK_OFF;
  1188. rc = dsi_recheck_clk_state(mngr);
  1189. if (rc) {
  1190. pr_err("clock state recheck failed rc = %d\n", rc);
  1191. goto error;
  1192. }
  1193. list_for_each_safe(pos, tmp, &mngr->client_list) {
  1194. node = list_entry(pos, struct dsi_clk_client_info,
  1195. list);
  1196. if (node == c) {
  1197. list_del(&node->list);
  1198. pr_debug("Removed device (%s)\n", node->name);
  1199. kfree(node);
  1200. break;
  1201. }
  1202. }
  1203. error:
  1204. mutex_unlock(&mngr->clk_mutex);
  1205. pr_debug("%s: EXIT, rc = %d\n", mngr->name, rc);
  1206. return rc;
  1207. }
  1208. void dsi_display_clk_mngr_update_splash_status(void *clk_mgr, bool status)
  1209. {
  1210. struct dsi_clk_mngr *mngr;
  1211. if (!clk_mgr) {
  1212. pr_err("Invalid params\n");
  1213. return;
  1214. }
  1215. mngr = (struct dsi_clk_mngr *)clk_mgr;
  1216. mngr->is_cont_splash_enabled = status;
  1217. }
  1218. void *dsi_display_clk_mngr_register(struct dsi_clk_info *info)
  1219. {
  1220. struct dsi_clk_mngr *mngr;
  1221. int i = 0;
  1222. if (!info) {
  1223. pr_err("Invalid params\n");
  1224. return ERR_PTR(-EINVAL);
  1225. }
  1226. mngr = kzalloc(sizeof(*mngr), GFP_KERNEL);
  1227. if (!mngr) {
  1228. mngr = ERR_PTR(-ENOMEM);
  1229. goto error;
  1230. }
  1231. mutex_init(&mngr->clk_mutex);
  1232. mngr->dsi_ctrl_count = info->dsi_ctrl_count;
  1233. mngr->master_ndx = info->master_ndx;
  1234. if (mngr->dsi_ctrl_count > MAX_DSI_CTRL) {
  1235. kfree(mngr);
  1236. return ERR_PTR(-EINVAL);
  1237. }
  1238. for (i = 0; i < mngr->dsi_ctrl_count; i++) {
  1239. memcpy(&mngr->core_clks[i].clks, &info->c_clks[i],
  1240. sizeof(struct dsi_core_clk_info));
  1241. memcpy(&mngr->link_clks[i].hs_clks, &info->l_hs_clks[i],
  1242. sizeof(struct dsi_link_hs_clk_info));
  1243. memcpy(&mngr->link_clks[i].lp_clks, &info->l_lp_clks[i],
  1244. sizeof(struct dsi_link_lp_clk_info));
  1245. mngr->core_clks[i].bus_handle = info->bus_handle[i];
  1246. mngr->ctrl_index[i] = info->ctrl_index[i];
  1247. }
  1248. INIT_LIST_HEAD(&mngr->client_list);
  1249. mngr->pre_clkon_cb = info->pre_clkon_cb;
  1250. mngr->post_clkon_cb = info->post_clkon_cb;
  1251. mngr->pre_clkoff_cb = info->pre_clkoff_cb;
  1252. mngr->post_clkoff_cb = info->post_clkoff_cb;
  1253. mngr->priv_data = info->priv_data;
  1254. memcpy(mngr->name, info->name, MAX_STRING_LEN);
  1255. error:
  1256. pr_debug("EXIT, rc = %ld\n", PTR_ERR(mngr));
  1257. return mngr;
  1258. }
  1259. int dsi_display_clk_mngr_deregister(void *clk_mngr)
  1260. {
  1261. int rc = 0;
  1262. struct dsi_clk_mngr *mngr = clk_mngr;
  1263. struct list_head *position = NULL;
  1264. struct list_head *tmp = NULL;
  1265. struct dsi_clk_client_info *node = NULL;
  1266. if (!mngr) {
  1267. pr_err("Invalid params\n");
  1268. return -EINVAL;
  1269. }
  1270. pr_debug("%s: ENTER\n", mngr->name);
  1271. mutex_lock(&mngr->clk_mutex);
  1272. list_for_each_safe(position, tmp, &mngr->client_list) {
  1273. node = list_entry(position, struct dsi_clk_client_info,
  1274. list);
  1275. list_del(&node->list);
  1276. pr_debug("Removed device (%s)\n", node->name);
  1277. kfree(node);
  1278. }
  1279. rc = dsi_recheck_clk_state(mngr);
  1280. if (rc)
  1281. pr_err("failed to disable all clocks\n");
  1282. mutex_unlock(&mngr->clk_mutex);
  1283. pr_debug("%s: EXIT, rc = %d\n", mngr->name, rc);
  1284. kfree(mngr);
  1285. return rc;
  1286. }