dsi_clk_manager.c 34 KB

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