external_display.c 37 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409
  1. #include <linux/delay.h>
  2. #include <linux/sched.h>
  3. #include <linux/semaphore.h>
  4. #include <linux/module.h>
  5. #include <linux/wait.h>
  6. #include <linux/kthread.h>
  7. #include <linux/mutex.h>
  8. #include <linux/vmalloc.h>
  9. #include "mtkfb_info.h"
  10. #include "mtkfb.h"
  11. #include "ddp_hal.h"
  12. #include "ddp_dump.h"
  13. #include "ddp_path.h"
  14. #include "ddp_drv.h"
  15. #include "ddp_info.h"
  16. #include <m4u.h>
  17. #include "cmdq_def.h"
  18. #include "cmdq_record.h"
  19. #include "cmdq_reg.h"
  20. #include "cmdq_core.h"
  21. #include "ddp_manager.h"
  22. #include "ddp_mmp.h"
  23. #include "ddp_ovl.h"
  24. #include "lcm_drv.h"
  25. #include "extd_platform.h"
  26. #include "extd_log.h"
  27. #include "extd_utils.h"
  28. #include "extd_hdmi_types.h"
  29. #include "external_display.h"
  30. #include "primary_display.h"
  31. #include "disp_session.h"
  32. #include "display_recorder.h"
  33. #include "extd_info.h"
  34. #ifdef CONFIG_SINGLE_PANEL_OUTPUT
  35. #include "extd_hdmi.h"
  36. #endif
  37. int ext_disp_use_cmdq;
  38. int ext_disp_use_m4u;
  39. enum EXT_DISP_PATH_MODE ext_disp_mode;
  40. static int is_context_inited;
  41. static int init_roi;
  42. struct ext_disp_path_context {
  43. enum EXTD_POWER_STATE state;
  44. enum EXTD_OVL_REQ_STATUS ovl_req_state;
  45. int init;
  46. unsigned int session;
  47. int need_trigger_overlay;
  48. int suspend_config;
  49. enum EXT_DISP_PATH_MODE mode;
  50. unsigned int last_vsync_tick;
  51. struct mutex lock;
  52. struct mutex vsync_lock;
  53. cmdqRecHandle cmdq_handle_config;
  54. cmdqRecHandle cmdq_handle_trigger;
  55. disp_path_handle dpmgr_handle;
  56. disp_path_handle ovl2mem_path_handle;
  57. };
  58. #define pgc _get_context()
  59. LCM_PARAMS extd_lcm_params;
  60. static struct ext_disp_path_context *_get_context(void)
  61. {
  62. static struct ext_disp_path_context g_context;
  63. if (!is_context_inited) {
  64. memset((void *)&g_context, 0, sizeof(struct ext_disp_path_context));
  65. is_context_inited = 1;
  66. EXT_DISP_LOG("_get_context set is_context_inited\n");
  67. }
  68. return &g_context;
  69. }
  70. enum EXT_DISP_PATH_MODE ext_disp_path_get_mode(unsigned int session)
  71. {
  72. return ext_disp_mode;
  73. }
  74. void ext_disp_path_set_mode(enum EXT_DISP_PATH_MODE mode, unsigned int session)
  75. {
  76. ext_disp_mode = mode;
  77. init_roi = (mode == EXTD_DIRECT_LINK_MODE ? 1 : 0);
  78. }
  79. static void _ext_disp_path_lock(void)
  80. {
  81. extd_sw_mutex_lock(NULL); /* /(&(pgc->lock)); */
  82. }
  83. static void _ext_disp_path_unlock(void)
  84. {
  85. extd_sw_mutex_unlock(NULL); /* (&(pgc->lock)); */
  86. }
  87. static void _ext_disp_vsync_lock(void)
  88. {
  89. mutex_lock(&(pgc->vsync_lock));
  90. }
  91. static void _ext_disp_vsync_unlock(void)
  92. {
  93. mutex_unlock(&(pgc->vsync_lock));
  94. }
  95. static DISP_MODULE_ENUM _get_dst_module_by_lcm(disp_path_handle pHandle)
  96. {
  97. return DISP_MODULE_DPI;
  98. }
  99. /***************************************************************
  100. ***trigger operation: VDO+CMDQ CMD+CMDQ VDO+CPU CMD+CPU
  101. *** 1.wait idle: N N Y Y
  102. *** 2.lcm update: N Y N Y
  103. *** 3.path start: idle->Y Y idle->Y Y
  104. *** 4.path trigger: idle->Y Y idle->Y Y
  105. *** 5.mutex enable: N N idle->Y Y
  106. *** 6.set cmdq dirty: N Y N N
  107. *** 7.flush cmdq: Y Y N N
  108. *** 8.reset cmdq: Y Y N N
  109. *** 9.cmdq insert token: Y Y N N
  110. ****************************************************************/
  111. /*
  112. * trigger operation: VDO+CMDQ CMD+CMDQ VDO+CPU CMD+CPU
  113. * 1.wait idle: N N Y Y
  114. */
  115. static int _should_wait_path_idle(void)
  116. {
  117. if (ext_disp_cmdq_enabled())
  118. return 0;
  119. else
  120. return dpmgr_path_is_busy(pgc->dpmgr_handle);
  121. }
  122. /* trigger operation: VDO+CMDQ CMD+CMDQ VDO+CPU CMD+CPU
  123. * 2.lcm update: N Y N Y
  124. */
  125. /*
  126. static int _should_update_lcm(void)
  127. {
  128. if (ext_disp_cmdq_enabled() || ext_disp_is_video_mode())
  129. return 0;
  130. else
  131. return 1;
  132. }
  133. */
  134. /* trigger operation: VDO+CMDQ CMD+CMDQ VDO+CPU CMD+CPU
  135. * 3.path start: idle->Y Y idle->Y Y
  136. */
  137. static int _should_start_path(void)
  138. {
  139. if (ext_disp_is_video_mode())
  140. return dpmgr_path_is_idle(pgc->dpmgr_handle);
  141. else
  142. return 1;
  143. }
  144. /* trigger operation: VDO+CMDQ CMD+CMDQ VDO+CPU CMD+CPU
  145. * 4. path trigger: idle->Y Y idle->Y Y
  146. * 5. mutex enable: N N idle->Y Y
  147. */
  148. static int _should_trigger_path(void)
  149. {
  150. /* this is not a perfect design, we can't decide path trigger(ovl/rdma/dsi..) separately with mutex enable */
  151. /* but it's lucky because path trigger and mutex enable is the same w/o cmdq, and it's correct w/ CMDQ(Y+N). */
  152. if (ext_disp_is_video_mode())
  153. return dpmgr_path_is_idle(pgc->dpmgr_handle);
  154. else if (ext_disp_cmdq_enabled())
  155. return 0;
  156. else
  157. return 1;
  158. }
  159. /* trigger operation: VDO+CMDQ CMD+CMDQ VDO+CPU CMD+CPU
  160. * 6. set cmdq dirty: N Y N N
  161. */
  162. static int _should_set_cmdq_dirty(void)
  163. {
  164. if (ext_disp_cmdq_enabled() && (ext_disp_is_video_mode() == 0))
  165. return 1;
  166. else
  167. return 0;
  168. }
  169. /* trigger operation: VDO+CMDQ CMD+CMDQ VDO+CPU CMD+CPU
  170. * 7. flush cmdq: Y Y N N
  171. */
  172. static int _should_flush_cmdq_config_handle(void)
  173. {
  174. return ext_disp_cmdq_enabled() ? 1 : 0;
  175. }
  176. /* trigger operation: VDO+CMDQ CMD+CMDQ VDO+CPU CMD+CPU
  177. * 8. reset cmdq: Y Y N N
  178. */
  179. static int _should_reset_cmdq_config_handle(void)
  180. {
  181. return ext_disp_cmdq_enabled() ? 1 : 0;
  182. }
  183. /* trigger operation: VDO+CMDQ CMD+CMDQ VDO+CPU CMD+CPU
  184. * 9. cmdq insert token: Y Y N N
  185. */
  186. static int _should_insert_wait_frame_done_token(void)
  187. {
  188. return ext_disp_cmdq_enabled() ? 1 : 0;
  189. }
  190. static int _should_trigger_interface(void)
  191. {
  192. if (pgc->mode == EXTD_DECOUPLE_MODE)
  193. return 0;
  194. else
  195. return 1;
  196. }
  197. static int _should_config_ovl_input(void)
  198. {
  199. /* should extend this when display path dynamic switch is ready */
  200. /* if(pgc->mode == EXTD_SINGLE_LAYER_MODE ||pgc->mode == EXTD_RDMA_DPI_MODE) */
  201. /* return 0; */
  202. /* else */
  203. /* return 1; */
  204. if (ext_disp_mode == EXTD_SINGLE_LAYER_MODE || ext_disp_mode == EXTD_RDMA_DPI_MODE)
  205. return 0;
  206. else
  207. return 1;
  208. }
  209. #define OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
  210. static long int get_current_time_us(void)
  211. {
  212. struct timeval t;
  213. do_gettimeofday(&t);
  214. return (t.tv_sec & 0xFFF) * 1000000 + t.tv_usec;
  215. }
  216. /*
  217. static enum hrtimer_restart _DISP_CmdModeTimer_handler(struct hrtimer *timer)
  218. {
  219. EXT_DISP_LOG("fake timer, wake up\n");
  220. dpmgr_signal_event(pgc->dpmgr_handle, DISP_PATH_EVENT_IF_VSYNC);
  221. #if 0
  222. if ((get_current_time_us() - pgc->last_vsync_tick) > 16666) {
  223. dpmgr_signal_event(pgc->dpmgr_handle, DISP_PATH_EVENT_IF_VSYNC);
  224. pgc->last_vsync_tick = get_current_time_us();
  225. }
  226. #endif
  227. return HRTIMER_RESTART;
  228. }
  229. static int _init_vsync_fake_monitor(int fps)
  230. {
  231. static struct hrtimer cmd_mode_update_timer;
  232. static ktime_t cmd_mode_update_timer_period;
  233. if (fps == 0)
  234. fps = 60;
  235. cmd_mode_update_timer_period = ktime_set(0, 1000 / fps * 1000);
  236. EXT_DISP_LOG("[MTKFB] vsync timer_period=%d\n", 1000 / fps);
  237. hrtimer_init(&cmd_mode_update_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
  238. cmd_mode_update_timer.function = _DISP_CmdModeTimer_handler;
  239. return 0;
  240. }
  241. */
  242. static int _build_path_direct_link(void)
  243. {
  244. int ret = 0;
  245. DISP_MODULE_ENUM dst_module = 0;
  246. EXT_DISP_FUNC();
  247. pgc->mode = EXTD_DIRECT_LINK_MODE;
  248. pgc->dpmgr_handle = dpmgr_create_path(DDP_SCENARIO_SUB_DISP, pgc->cmdq_handle_config);
  249. if (pgc->dpmgr_handle)
  250. EXT_DISP_LOG("dpmgr create path SUCCESS(%p)\n", pgc->dpmgr_handle);
  251. else {
  252. EXT_DISP_LOG("dpmgr create path FAIL\n");
  253. return -1;
  254. }
  255. dst_module = DISP_MODULE_DPI;
  256. dpmgr_path_set_dst_module(pgc->dpmgr_handle, dst_module);
  257. /* EXT_DISP_LOG("dpmgr set dst module FINISHED(%s)\n", ddp_get_module_name(dst_module)); */
  258. /*
  259. {
  260. M4U_PORT_STRUCT sPort;
  261. sPort.ePortID = M4U_PORT_DISP_OVL1;
  262. sPort.Virtuality = ext_disp_use_m4u;
  263. sPort.Security = 0;
  264. sPort.Distance = 1;
  265. sPort.Direction = 0;
  266. ret = m4u_config_port(&sPort);
  267. if (ret == 0) {
  268. EXT_DISP_LOG("config M4U Port %s to %s SUCCESS\n",
  269. ddp_get_module_name(M4U_PORT_DISP_OVL1), ext_disp_use_m4u ? "virtual" : "physical");
  270. } else {
  271. EXT_DISP_LOG("config M4U Port %s to %s FAIL(ret=%d)\n", ddp_get_module_name(M4U_PORT_DISP_OVL1),
  272. ext_disp_use_m4u ? "virtual" : "physical", ret);
  273. return -1;
  274. }
  275. }
  276. */
  277. dpmgr_set_lcm_utils(pgc->dpmgr_handle, NULL);
  278. #ifdef CONFIG_SINGLE_PANEL_OUTPUT
  279. _ext_disp_vsync_lock();
  280. dpmgr_enable_event(pgc->dpmgr_handle, DISP_PATH_EVENT_IF_VSYNC);
  281. _ext_disp_vsync_unlock();
  282. #else
  283. dpmgr_enable_event(pgc->dpmgr_handle, DISP_PATH_EVENT_IF_VSYNC);
  284. #endif
  285. dpmgr_enable_event(pgc->dpmgr_handle, DISP_PATH_EVENT_FRAME_DONE);
  286. dpmgr_enable_event(pgc->dpmgr_handle, DISP_PATH_EVENT_FRAME_START);
  287. return ret;
  288. }
  289. static int _build_path_decouple(void)
  290. {
  291. return 0;
  292. }
  293. static int _build_path_single_layer(void)
  294. {
  295. return 0;
  296. }
  297. static int _build_path_rdma_dpi(void)
  298. {
  299. int ret = 0;
  300. DISP_MODULE_ENUM dst_module = 0;
  301. pgc->mode = EXTD_RDMA_DPI_MODE;
  302. pgc->dpmgr_handle = dpmgr_create_path(DDP_SCENARIO_SUB_RDMA1_DISP, pgc->cmdq_handle_config);
  303. if (pgc->dpmgr_handle)
  304. EXT_DISP_LOG("dpmgr create path SUCCESS(%p)\n", pgc->dpmgr_handle);
  305. else {
  306. EXT_DISP_LOG("dpmgr create path FAIL\n");
  307. return -1;
  308. }
  309. dst_module = _get_dst_module_by_lcm(pgc->dpmgr_handle);
  310. dpmgr_path_set_dst_module(pgc->dpmgr_handle, dst_module);
  311. EXT_DISP_LOG("dpmgr set dst module FINISHED(%s)\n", ddp_get_module_name(dst_module));
  312. {
  313. #ifdef MTK_FB_RDMA1_SUPPORT
  314. M4U_PORT_STRUCT sPort;
  315. sPort.ePortID = M4U_PORT_DISP_RDMA1;
  316. sPort.Virtuality = ext_disp_use_m4u;
  317. sPort.Security = 0;
  318. sPort.Distance = 1;
  319. sPort.Direction = 0;
  320. ret = m4u_config_port(&sPort);
  321. if (ret == 0) {
  322. EXT_DISP_LOG("config M4U Port %s to %s SUCCESS\n", ddp_get_module_name(DISP_MODULE_RDMA1),
  323. ext_disp_use_m4u ? "virtual" : "physical");
  324. } else {
  325. EXT_DISP_LOG("config M4U Port %s to %s FAIL(ret=%d)\n", ddp_get_module_name(DISP_MODULE_RDMA1),
  326. ext_disp_use_m4u ? "virtual" : "physical", ret);
  327. return -1;
  328. }
  329. #endif
  330. }
  331. dpmgr_set_lcm_utils(pgc->dpmgr_handle, NULL);
  332. #ifdef CONFIG_SINGLE_PANEL_OUTPUT
  333. _ext_disp_vsync_lock();
  334. dpmgr_enable_event(pgc->dpmgr_handle, DISP_PATH_EVENT_IF_VSYNC);
  335. _ext_disp_vsync_unlock();
  336. #else
  337. dpmgr_enable_event(pgc->dpmgr_handle, DISP_PATH_EVENT_IF_VSYNC);
  338. #endif
  339. dpmgr_enable_event(pgc->dpmgr_handle, DISP_PATH_EVENT_FRAME_DONE);
  340. return ret;
  341. }
  342. static void _cmdq_build_trigger_loop(void)
  343. {
  344. int ret = 0;
  345. cmdqRecCreate(CMDQ_SCENARIO_TRIGGER_LOOP, &(pgc->cmdq_handle_trigger));
  346. EXT_DISP_LOG("ext_disp path trigger thread cmd handle=%p\n", pgc->cmdq_handle_trigger);
  347. cmdqRecReset(pgc->cmdq_handle_trigger);
  348. if (ext_disp_is_video_mode()) {
  349. /* wait and clear stream_done, HW will assert mutex enable automatically in frame done reset. */
  350. /* todo: should let dpmanager to decide wait which mutex's eof. */
  351. ret = cmdqRecWait(pgc->cmdq_handle_trigger,
  352. dpmgr_path_get_mutex(pgc->dpmgr_handle) + CMDQ_EVENT_MUTEX0_STREAM_EOF);
  353. /* for some module(like COLOR) to read hw register to GPR after frame done */
  354. dpmgr_path_build_cmdq(pgc->dpmgr_handle, pgc->cmdq_handle_trigger, CMDQ_AFTER_STREAM_EOF);
  355. } else {
  356. /* DSI command mode doesn't have mutex_stream_eof, need use CMDQ token instead */
  357. ret = cmdqRecWait(pgc->cmdq_handle_trigger, CMDQ_SYNC_TOKEN_CONFIG_DIRTY);
  358. /* ret = cmdqRecWait(pgc->cmdq_handle_trigger, CMDQ_EVENT_MDP_DSI0_TE_SOF); */
  359. /* for operations before frame transfer, such as waiting for DSI TE */
  360. dpmgr_path_build_cmdq(pgc->dpmgr_handle, pgc->cmdq_handle_trigger, CMDQ_BEFORE_STREAM_SOF);
  361. /* cleat frame done token, now the config thread will not allowed to config registers. */
  362. /* remember that config thread's priority is higher than trigger thread*/
  363. /* so all the config queued before will be applied then STREAM_EOF token be cleared */
  364. /* this is what CMDQ did as "Merge" */
  365. ret = cmdqRecClearEventToken(pgc->cmdq_handle_trigger, CMDQ_SYNC_TOKEN_STREAM_EOF);
  366. /* enable mutex, only cmd mode need this */
  367. /* this is what CMDQ did as "Trigger" */
  368. dpmgr_path_trigger(pgc->dpmgr_handle, pgc->cmdq_handle_trigger, CMDQ_ENABLE);
  369. /* waiting for frame done, because we can't use mutex stream eof here*/
  370. /* so need to let dpmanager help to decide which event to wait */
  371. /* most time we wait rdmax frame done event. */
  372. ret = cmdqRecWait(pgc->cmdq_handle_trigger, CMDQ_EVENT_DISP_RDMA1_EOF);
  373. dpmgr_path_build_cmdq(pgc->dpmgr_handle, pgc->cmdq_handle_trigger, CMDQ_WAIT_STREAM_EOF_EVENT);
  374. /* dsi is not idle rightly after rdma frame done, */
  375. /* so we need to polling about 1us for dsi returns to idle */
  376. /* do not polling dsi idle directly which will decrease CMDQ performance */
  377. dpmgr_path_build_cmdq(pgc->dpmgr_handle, pgc->cmdq_handle_trigger, CMDQ_CHECK_IDLE_AFTER_STREAM_EOF);
  378. /* for some module(like COLOR) to read hw register to GPR after frame done */
  379. dpmgr_path_build_cmdq(pgc->dpmgr_handle, pgc->cmdq_handle_trigger, CMDQ_AFTER_STREAM_EOF);
  380. /* polling DSI idle */
  381. /* ret = cmdqRecPoll(pgc->cmdq_handle_trigger, 0x1401b00c, 0, 0x80000000); */
  382. /* polling wdma frame done */
  383. /* ret = cmdqRecPoll(pgc->cmdq_handle_trigger, 0x140060A0, 1, 0x1); */
  384. /* now frame done, config thread is allowed to config register now */
  385. ret = cmdqRecSetEventToken(pgc->cmdq_handle_trigger, CMDQ_SYNC_TOKEN_STREAM_EOF);
  386. /* RUN forever!!!! */
  387. BUG_ON(ret < 0);
  388. }
  389. /* dump trigger loop instructions to check whether dpmgr_path_build_cmdq works correctly */
  390. cmdqRecDumpCommand(pgc->cmdq_handle_trigger);
  391. EXT_DISP_LOG("ext display BUILD cmdq trigger loop finished\n");
  392. }
  393. static void _cmdq_start_trigger_loop(void)
  394. {
  395. int ret = 0;
  396. /* this should be called only once because trigger loop will nevet stop */
  397. ret = cmdqRecStartLoop(pgc->cmdq_handle_trigger);
  398. if (!ext_disp_is_video_mode()) {
  399. /* need to set STREAM_EOF for the first time, otherwise we will stuck in dead loop */
  400. cmdqCoreSetEvent(CMDQ_SYNC_TOKEN_STREAM_EOF);
  401. /* /dprec_event_op(DPREC_EVENT_CMDQ_SET_EVENT_ALLOW); */
  402. }
  403. EXT_DISP_LOG("START cmdq trigger loop finished\n");
  404. }
  405. static void _cmdq_stop_trigger_loop(void)
  406. {
  407. int ret = 0;
  408. /* this should be called only once because trigger loop will nevet stop */
  409. ret = cmdqRecStopLoop(pgc->cmdq_handle_trigger);
  410. EXT_DISP_LOG("ext display STOP cmdq trigger loop finished\n");
  411. }
  412. static void _cmdq_set_config_handle_dirty(void)
  413. {
  414. if (!ext_disp_is_video_mode()) {
  415. /* only command mode need to set dirty */
  416. cmdqRecSetEventToken(pgc->cmdq_handle_config, CMDQ_SYNC_TOKEN_CONFIG_DIRTY);
  417. /* /dprec_event_op(DPREC_EVENT_CMDQ_SET_DIRTY); */
  418. }
  419. }
  420. static void _cmdq_reset_config_handle(void)
  421. {
  422. cmdqRecReset(pgc->cmdq_handle_config);
  423. /* /dprec_event_op(DPREC_EVENT_CMDQ_RESET); */
  424. }
  425. static void _cmdq_flush_config_handle(int blocking, void *callback, unsigned int userdata)
  426. {
  427. if (blocking) {
  428. /* it will be blocked until mutex done */
  429. cmdqRecFlush(pgc->cmdq_handle_config);
  430. } else {
  431. if (callback)
  432. cmdqRecFlushAsyncCallback(pgc->cmdq_handle_config, callback, userdata);
  433. else
  434. cmdqRecFlushAsync(pgc->cmdq_handle_config);
  435. }
  436. /* dprec_event_op(DPREC_EVENT_CMDQ_FLUSH); */
  437. }
  438. static void _cmdq_insert_wait_frame_done_token(int clear_event)
  439. {
  440. if (ext_disp_is_video_mode()) {
  441. if (clear_event == 0) {
  442. cmdqRecWaitNoClear(pgc->cmdq_handle_config,
  443. dpmgr_path_get_mutex(pgc->dpmgr_handle) + CMDQ_EVENT_MUTEX0_STREAM_EOF);
  444. } else {
  445. cmdqRecWait(pgc->cmdq_handle_config,
  446. dpmgr_path_get_mutex(pgc->dpmgr_handle) + CMDQ_EVENT_MUTEX0_STREAM_EOF);
  447. }
  448. } else {
  449. if (clear_event == 0)
  450. cmdqRecWaitNoClear(pgc->cmdq_handle_config, CMDQ_SYNC_TOKEN_STREAM_EOF);
  451. else
  452. cmdqRecWait(pgc->cmdq_handle_config, CMDQ_SYNC_TOKEN_STREAM_EOF);
  453. }
  454. /* /dprec_event_op(DPREC_EVENT_CMDQ_WAIT_STREAM_EOF); */
  455. }
  456. static int _convert_disp_input_to_rdma(RDMA_CONFIG_STRUCT *dst, disp_input_config *src)
  457. {
  458. int ret = 0;
  459. unsigned int Bpp = 0;
  460. unsigned int bpp = 0;
  461. if (!src || !dst) {
  462. EXT_DISP_ERR("%s src(0x%p) or dst(0x%p) is null\n",
  463. __func__, src, dst);
  464. return -1;
  465. }
  466. ret = disp_fmt_to_hw_fmt(src->src_fmt, &(dst->inputFormat), &Bpp, &bpp);
  467. dst->address = (unsigned long)src->src_phy_addr;
  468. dst->width = src->src_width;
  469. dst->height = src->src_height;
  470. dst->pitch = src->src_pitch * Bpp;
  471. return ret;
  472. }
  473. static int _convert_disp_input_to_ovl(OVL_CONFIG_STRUCT *dst, disp_input_config *src)
  474. {
  475. int ret;
  476. unsigned int Bpp = 0;
  477. unsigned int bpp = 0;
  478. if (!src || !dst) {
  479. EXT_DISP_ERR("%s src(0x%p) or dst(0x%p) is null\n",
  480. __func__, src, dst);
  481. return -1;
  482. }
  483. dst->layer = src->layer_id;
  484. dst->isDirty = 1;
  485. dst->buff_idx = src->next_buff_idx;
  486. dst->layer_en = src->layer_enable;
  487. /* if layer is disable, we just needs config above params. */
  488. if (!src->layer_enable)
  489. return 0;
  490. ret = disp_fmt_to_hw_fmt(src->src_fmt, (unsigned int *)(&(dst->fmt)),
  491. (unsigned int *)(&Bpp), (unsigned int *)(&bpp));
  492. dst->addr = (unsigned long)src->src_phy_addr;
  493. dst->vaddr = (unsigned long)src->src_base_addr;
  494. dst->src_x = src->src_offset_x;
  495. dst->src_y = src->src_offset_y;
  496. dst->src_w = src->src_width;
  497. dst->src_h = src->src_height;
  498. dst->src_pitch = src->src_pitch * Bpp;
  499. dst->dst_x = src->tgt_offset_x;
  500. dst->dst_y = src->tgt_offset_y;
  501. /* dst W/H should <= src W/H */
  502. if (src->buffer_source != DISP_BUFFER_ALPHA) {
  503. dst->dst_w = min(src->src_width, src->tgt_width);
  504. dst->dst_h = min(src->src_height, src->tgt_height);
  505. } else {
  506. dst->dst_w = src->tgt_width;
  507. dst->dst_h = src->tgt_height;
  508. }
  509. dst->keyEn = src->src_use_color_key;
  510. dst->key = src->src_color_key;
  511. dst->aen = src->alpha_enable;
  512. dst->alpha = src->alpha;
  513. dst->sur_aen = src->sur_aen;
  514. dst->src_alpha = src->src_alpha;
  515. dst->dst_alpha = src->dst_alpha;
  516. #ifdef DISP_DISABLE_X_CHANNEL_ALPHA
  517. if (DISP_FORMAT_ARGB8888 == src->src_fmt ||
  518. DISP_FORMAT_ABGR8888 == src->src_fmt ||
  519. DISP_FORMAT_RGBA8888 == src->src_fmt ||
  520. DISP_FORMAT_BGRA8888 == src->src_fmt || src->buffer_source == DISP_BUFFER_ALPHA) {
  521. /* nothing */
  522. } else {
  523. dst->aen = FALSE;
  524. dst->sur_aen = FALSE;
  525. }
  526. #endif
  527. dst->identity = src->identity;
  528. dst->connected_type = src->connected_type;
  529. dst->security = src->security;
  530. dst->yuv_range = src->yuv_range;
  531. if (src->buffer_source == DISP_BUFFER_ALPHA)
  532. dst->source = OVL_LAYER_SOURCE_RESERVED; /* dim layer, constant alpha */
  533. else if (src->buffer_source == DISP_BUFFER_ION || src->buffer_source == DISP_BUFFER_MVA)
  534. dst->source = OVL_LAYER_SOURCE_MEM; /* from memory */
  535. else {
  536. EXT_DISP_ERR("unknown source = %d", src->buffer_source);
  537. dst->source = OVL_LAYER_SOURCE_MEM;
  538. }
  539. return ret;
  540. }
  541. static int _ext_disp_trigger(int blocking, void *callback, unsigned int userdata)
  542. {
  543. bool reg_flush = false;
  544. /*disp_session_vsync_config vsync_config;*/
  545. EXT_DISP_FUNC();
  546. if (_should_wait_path_idle())
  547. dpmgr_wait_event_timeout(pgc->dpmgr_handle, DISP_PATH_EVENT_FRAME_DONE, HZ / 2);
  548. if (_should_start_path()) {
  549. reg_flush = true;
  550. dpmgr_path_start(pgc->dpmgr_handle, ext_disp_cmdq_enabled());
  551. MMProfileLogEx(ddp_mmp_get_events()->Extd_State, MMProfileFlagPulse, Trigger, 1);
  552. }
  553. if (_should_trigger_path()) {
  554. /* trigger_loop_handle is used only for build trigger loop*/
  555. dpmgr_path_trigger(pgc->dpmgr_handle, NULL, ext_disp_cmdq_enabled());
  556. }
  557. if (_should_set_cmdq_dirty())
  558. _cmdq_set_config_handle_dirty();
  559. if (_should_flush_cmdq_config_handle()) {
  560. if (reg_flush)
  561. MMProfileLogEx(ddp_mmp_get_events()->Extd_State, MMProfileFlagPulse, Trigger, 2);
  562. /*
  563. if (_should_start_path()) {
  564. EXT_DISP_LOG("Wait Main Display Vsync\n");
  565. primary_display_wait_for_vsync(&vsync_config);
  566. }
  567. */
  568. _cmdq_flush_config_handle(blocking, callback, userdata);
  569. }
  570. if (_should_reset_cmdq_config_handle())
  571. _cmdq_reset_config_handle();
  572. if (_should_insert_wait_frame_done_token())
  573. _cmdq_insert_wait_frame_done_token(0);
  574. return 0;
  575. }
  576. static int _ext_disp_trigger_EPD(int blocking, void *callback, unsigned int userdata)
  577. {
  578. /* /EXT_DISP_FUNC(); */
  579. if (_should_wait_path_idle())
  580. dpmgr_wait_event_timeout(pgc->dpmgr_handle, DISP_PATH_EVENT_FRAME_DONE, HZ / 2);
  581. if (_should_start_path()) {
  582. dpmgr_path_start(pgc->dpmgr_handle, ext_disp_cmdq_enabled());
  583. MMProfileLogEx(ddp_mmp_get_events()->Extd_State, MMProfileFlagPulse, Trigger, 1);
  584. }
  585. if (_should_trigger_path()) {
  586. /* trigger_loop_handle is used only for build trigger loop*/
  587. dpmgr_path_trigger(pgc->dpmgr_handle, NULL, ext_disp_cmdq_enabled());
  588. }
  589. if (_should_set_cmdq_dirty())
  590. _cmdq_set_config_handle_dirty();
  591. if (_should_flush_cmdq_config_handle())
  592. _cmdq_flush_config_handle(blocking, callback, userdata);
  593. if (_should_reset_cmdq_config_handle())
  594. _cmdq_reset_config_handle();
  595. if (_should_insert_wait_frame_done_token()) {
  596. /* 1 for clear event, cmdqRecWait */
  597. _cmdq_insert_wait_frame_done_token(1);
  598. }
  599. return 0;
  600. }
  601. /* <-- Donglei for K2 compile
  602. //need remove
  603. static unsigned int cmdqDdpClockOn(uint64_t engineFlag)
  604. {
  605. return 0;
  606. }
  607. static unsigned int cmdqDdpClockOff(uint64_t engineFlag)
  608. {
  609. return 0;
  610. }
  611. static unsigned int cmdqDdpDumpInfo(uint64_t engineFlag,
  612. char *pOutBuf,
  613. unsigned int bufSize)
  614. {
  615. ext_disp_diagnose();
  616. return 0;
  617. }
  618. static unsigned int cmdqDdpResetEng(uint64_t engineFlag)
  619. {
  620. return 0;
  621. }
  622. */
  623. void ext_disp_probe(void)
  624. {
  625. EXT_DISP_FUNC();
  626. ext_disp_use_cmdq = CMDQ_ENABLE;
  627. ext_disp_use_m4u = 1;
  628. ext_disp_mode = EXTD_DIRECT_LINK_MODE;
  629. }
  630. int ext_disp_init(char *lcm_name, unsigned int session)
  631. {
  632. disp_ddp_path_config *data_config;
  633. enum EXT_DISP_STATUS ret;
  634. EXT_DISP_FUNC();
  635. ret = EXT_DISP_STATUS_OK;
  636. dpmgr_init();
  637. extd_mutex_init(&(pgc->lock));
  638. #ifdef CONFIG_SINGLE_PANEL_OUTPUT
  639. extd_mutex_init(&(pgc->vsync_lock));
  640. #endif
  641. _ext_disp_path_lock();
  642. #if 0
  643. ret = cmdqCoreRegisterCB(CMDQ_GROUP_DISP, cmdqDdpClockOn, cmdqDdpDumpInfo, cmdqDdpResetEng, cmdqDdpClockOff);
  644. if (ret) {
  645. EXT_DISP_ERR("cmdqCoreRegisterCB failed, ret=%d\n", ret);
  646. ret = EXT_DISP_STATUS_ERROR;
  647. goto done;
  648. }
  649. #endif
  650. ret = cmdqRecCreate(CMDQ_SCENARIO_MHL_DISP, &(pgc->cmdq_handle_config));
  651. if (ret) {
  652. EXT_DISP_LOG("cmdqRecCreate FAIL, ret=%d\n", ret);
  653. ret = EXT_DISP_STATUS_ERROR;
  654. goto done;
  655. } else
  656. EXT_DISP_LOG("cmdqRecCreate SUCCESS, g_cmdq_handle=%p\n", pgc->cmdq_handle_config);
  657. if (ext_disp_mode == EXTD_DIRECT_LINK_MODE)
  658. _build_path_direct_link();
  659. else if (ext_disp_mode == EXTD_DECOUPLE_MODE)
  660. _build_path_decouple();
  661. else if (ext_disp_mode == EXTD_SINGLE_LAYER_MODE)
  662. _build_path_single_layer();
  663. else if (ext_disp_mode == EXTD_RDMA_DPI_MODE)
  664. _build_path_rdma_dpi();
  665. else
  666. EXT_DISP_LOG("ext_disp display mode is WRONG\n");
  667. if (ext_disp_use_cmdq == CMDQ_ENABLE) {
  668. if (DISP_SESSION_DEV(session) != DEV_EINK + 1) {
  669. _cmdq_build_trigger_loop();
  670. EXT_DISP_LOG("ext_disp display BUILD cmdq trigger loop finished\n");
  671. _cmdq_start_trigger_loop();
  672. }
  673. }
  674. pgc->session = session;
  675. EXT_DISP_LOG("ext_disp display START cmdq trigger loop finished\n");
  676. dpmgr_path_set_video_mode(pgc->dpmgr_handle, ext_disp_is_video_mode());
  677. dpmgr_path_init(pgc->dpmgr_handle, CMDQ_DISABLE);
  678. data_config = vmalloc(sizeof(disp_ddp_path_config));
  679. if (data_config) {
  680. memset((void *)data_config, 0, sizeof(disp_ddp_path_config));
  681. memcpy(&(data_config->dispif_config), &extd_lcm_params, sizeof(LCM_PARAMS));
  682. data_config->dst_w = extd_lcm_params.dpi.width;
  683. data_config->dst_h = extd_lcm_params.dpi.height;
  684. data_config->dst_dirty = 1;
  685. init_roi = 0;
  686. ret = dpmgr_path_config(pgc->dpmgr_handle, data_config, CMDQ_DISABLE);
  687. EXT_DISP_LOG("ext_disp_init roi w:%d, h:%d\n", data_config->dst_w, data_config->dst_h);
  688. } else
  689. EXT_DISP_LOG("allocate buffer failed!!!\n");
  690. /* this will be set to always enable cmdq later */
  691. if (ext_disp_is_video_mode()) {
  692. #ifdef CONFIG_SINGLE_PANEL_OUTPUT
  693. dpmgr_map_event_to_irq(pgc->dpmgr_handle, DISP_PATH_EVENT_IF_VSYNC, DDP_IRQ_RDMA0_DONE);
  694. #else
  695. dpmgr_map_event_to_irq(pgc->dpmgr_handle, DISP_PATH_EVENT_IF_VSYNC, DDP_IRQ_RDMA1_DONE);
  696. #endif
  697. }
  698. if (ext_disp_use_cmdq == CMDQ_ENABLE)
  699. _cmdq_reset_config_handle();
  700. mutex_init(&(pgc->vsync_lock));
  701. pgc->state = EXTD_INIT;
  702. done:
  703. _ext_disp_path_unlock();
  704. dpmgr_path_stop(pgc->dpmgr_handle, CMDQ_DISABLE);
  705. EXT_DISP_LOG("ext_disp_init done\n");
  706. return ret;
  707. }
  708. int ext_disp_deinit(unsigned int session)
  709. {
  710. EXT_DISP_FUNC();
  711. _ext_disp_path_lock();
  712. if (pgc->state == EXTD_DEINIT)
  713. goto deinit_exit;
  714. if (pgc->state == EXTD_SUSPEND)
  715. dpmgr_path_power_on(pgc->dpmgr_handle, CMDQ_DISABLE);
  716. #ifdef CONFIG_SINGLE_PANEL_OUTPUT
  717. _ext_disp_vsync_lock();
  718. dpmgr_disable_event(pgc->dpmgr_handle, DISP_PATH_EVENT_IF_VSYNC);
  719. #endif
  720. dpmgr_path_deinit(pgc->dpmgr_handle, CMDQ_DISABLE);
  721. dpmgr_destroy_path(pgc->dpmgr_handle, NULL);
  722. #ifdef CONFIG_SINGLE_PANEL_OUTPUT
  723. _ext_disp_vsync_unlock();
  724. #endif
  725. cmdqRecDestroy(pgc->cmdq_handle_config);
  726. cmdqRecDestroy(pgc->cmdq_handle_trigger);
  727. pgc->state = EXTD_DEINIT;
  728. deinit_exit:
  729. _ext_disp_path_unlock();
  730. is_context_inited = 0;
  731. EXT_DISP_LOG("ext_disp_deinit done\n");
  732. return 0;
  733. }
  734. int ext_disp_wait_for_vsync(void *config, unsigned int session)
  735. {
  736. int ret = 0;
  737. disp_session_vsync_config *c = (disp_session_vsync_config *) config;
  738. _ext_disp_path_lock();
  739. #ifdef CONFIG_SINGLE_PANEL_OUTPUT
  740. if ((pgc->state != EXTD_INIT && pgc->state != EXTD_RESUME) || !is_hdmi_video_on()) {
  741. EXT_DISP_ERR("ext display path not ready yet\n");
  742. _ext_disp_path_unlock();
  743. msleep(20);
  744. return -1;
  745. }
  746. #else
  747. if (pgc->state == EXTD_DEINIT) {
  748. _ext_disp_path_unlock();
  749. msleep(20);
  750. return -1;
  751. }
  752. #endif
  753. _ext_disp_path_unlock();
  754. _ext_disp_vsync_lock();
  755. #ifdef CONFIG_SINGLE_PANEL_OUTPUT
  756. if (pgc->dpmgr_handle == NULL) {
  757. EXT_DISP_ERR("vsync for ext display path not ready yet\n");
  758. _ext_disp_vsync_unlock();
  759. return -1;
  760. }
  761. ret = dpmgr_wait_event_timeout(pgc->dpmgr_handle, DISP_PATH_EVENT_IF_VSYNC, HZ/10);
  762. #else
  763. ret = dpmgr_wait_event(pgc->dpmgr_handle, DISP_PATH_EVENT_IF_VSYNC);
  764. #endif
  765. if (ret == -2) {
  766. EXT_DISP_ERR("vsync for ext display path not enabled yet\n");
  767. _ext_disp_vsync_unlock();
  768. return -1;
  769. }
  770. EXT_DISP_LOG("ext_disp_wait_for_vsync - vsync signaled\n");
  771. c->vsync_ts = get_current_time_us();
  772. c->vsync_cnt++;
  773. _ext_disp_vsync_unlock();
  774. return ret;
  775. }
  776. int ext_disp_suspend(unsigned int session)
  777. {
  778. enum EXT_DISP_STATUS ret = EXT_DISP_STATUS_OK;
  779. EXT_DISP_FUNC();
  780. _ext_disp_path_lock();
  781. if (pgc->state == EXTD_DEINIT || pgc->state == EXTD_SUSPEND || session != pgc->session) {
  782. EXT_DISP_ERR("status is not EXTD_RESUME or session is not match\n");
  783. goto done;
  784. }
  785. pgc->need_trigger_overlay = 0;
  786. if (dpmgr_path_is_busy(pgc->dpmgr_handle))
  787. dpmgr_wait_event_timeout(pgc->dpmgr_handle, DISP_PATH_EVENT_FRAME_DONE, HZ / 30);
  788. if (ext_disp_use_cmdq == CMDQ_ENABLE && DISP_SESSION_DEV(session) != DEV_EINK + 1)
  789. _cmdq_stop_trigger_loop();
  790. dpmgr_path_stop(pgc->dpmgr_handle, CMDQ_DISABLE);
  791. if (dpmgr_path_is_busy(pgc->dpmgr_handle))
  792. dpmgr_wait_event_timeout(pgc->dpmgr_handle, DISP_PATH_EVENT_FRAME_DONE, HZ / 30);
  793. dpmgr_path_reset(pgc->dpmgr_handle, CMDQ_DISABLE);
  794. dpmgr_path_power_off(pgc->dpmgr_handle, CMDQ_DISABLE);
  795. pgc->state = EXTD_SUSPEND;
  796. done:
  797. _ext_disp_path_unlock();
  798. EXT_DISP_LOG("ext_disp_suspend done\n");
  799. return ret;
  800. }
  801. int ext_disp_resume(unsigned int session)
  802. {
  803. enum EXT_DISP_STATUS ret = EXT_DISP_STATUS_OK;
  804. EXT_DISP_FUNC();
  805. _ext_disp_path_lock();
  806. if (pgc->state != EXTD_SUSPEND) {
  807. EXT_DISP_ERR("EXTD_DEINIT/EXTD_INIT/EXTD_RESUME\n");
  808. goto done;
  809. }
  810. if (_should_reset_cmdq_config_handle() && DISP_SESSION_DEV(session) != DEV_EINK + 1)
  811. _cmdq_reset_config_handle();
  812. dpmgr_path_power_on(pgc->dpmgr_handle, CMDQ_DISABLE);
  813. if (ext_disp_use_cmdq == CMDQ_ENABLE && DISP_SESSION_DEV(session) != DEV_EINK + 1)
  814. _cmdq_start_trigger_loop();
  815. if (dpmgr_path_is_busy(pgc->dpmgr_handle)) {
  816. EXT_DISP_LOG("stop display path failed, still busy\n");
  817. ret = -1;
  818. goto done;
  819. }
  820. if (DISP_SESSION_DEV(session) == DEV_EINK + 1)
  821. pgc->suspend_config = 0;
  822. pgc->state = EXTD_RESUME;
  823. done:
  824. _ext_disp_path_unlock();
  825. EXT_DISP_LOG("ext_disp_resume done\n");
  826. MMProfileLogEx(ddp_mmp_get_events()->Extd_State, MMProfileFlagPulse, Resume, 1);
  827. return ret;
  828. }
  829. int ext_disp_trigger(int blocking, void *callback, unsigned int userdata, unsigned int session)
  830. {
  831. int ret = 0;
  832. EXT_DISP_FUNC();
  833. if (pgc->state == EXTD_DEINIT || pgc->state == EXTD_SUSPEND || pgc->need_trigger_overlay < 1) {
  834. EXT_DISP_LOG("trigger ext display is already slept\n");
  835. MMProfileLogEx(ddp_mmp_get_events()->Extd_ErrorInfo, MMProfileFlagPulse, Trigger, 0);
  836. return -1;
  837. }
  838. _ext_disp_path_lock();
  839. if (_should_trigger_interface()) {
  840. if (DISP_SESSION_TYPE(session) == DISP_SESSION_EXTERNAL && DISP_SESSION_DEV(session) == DEV_MHL + 1)
  841. _ext_disp_trigger(blocking, callback, userdata);
  842. else if (DISP_SESSION_TYPE(session) == DISP_SESSION_EXTERNAL
  843. && DISP_SESSION_DEV(session) == DEV_EINK + 1)
  844. _ext_disp_trigger_EPD(blocking, callback, userdata);
  845. } else
  846. dpmgr_path_trigger(pgc->ovl2mem_path_handle, NULL, ext_disp_use_cmdq);
  847. pgc->state = EXTD_RESUME;
  848. _ext_disp_path_unlock();
  849. EXT_DISP_LOG("ext_disp_trigger done\n");
  850. return ret;
  851. }
  852. int ext_disp_suspend_trigger(void *callback, unsigned int userdata, unsigned int session)
  853. {
  854. enum EXT_DISP_STATUS ret = EXT_DISP_STATUS_OK;
  855. EXT_DISP_FUNC();
  856. if (pgc->state != EXTD_RESUME) {
  857. EXT_DISP_LOG("trigger ext display is already slept\n");
  858. MMProfileLogEx(ddp_mmp_get_events()->Extd_ErrorInfo, MMProfileFlagPulse, Trigger, 0);
  859. return -1;
  860. }
  861. MMProfileLogEx(ddp_mmp_get_events()->Extd_State, MMProfileFlagPulse, Suspend, 0);
  862. _ext_disp_path_lock();
  863. if (_should_reset_cmdq_config_handle())
  864. _cmdq_reset_config_handle();
  865. if (_should_insert_wait_frame_done_token())
  866. _cmdq_insert_wait_frame_done_token(0);
  867. pgc->need_trigger_overlay = 0;
  868. if (ext_disp_use_cmdq == CMDQ_ENABLE && DISP_SESSION_DEV(session) != DEV_EINK + 1)
  869. _cmdq_stop_trigger_loop();
  870. dpmgr_path_stop(pgc->dpmgr_handle, ext_disp_cmdq_enabled());
  871. if (_should_flush_cmdq_config_handle()) {
  872. _cmdq_flush_config_handle(1, 0, 0);
  873. _cmdq_reset_config_handle();
  874. }
  875. dpmgr_path_reset(pgc->dpmgr_handle, CMDQ_DISABLE);
  876. dpmgr_path_power_off(pgc->dpmgr_handle, CMDQ_DISABLE);
  877. if (DISP_SESSION_DEV(session) == DEV_EINK + 1)
  878. pgc->suspend_config = 1;
  879. pgc->state = EXTD_SUSPEND;
  880. _ext_disp_path_unlock();
  881. MMProfileLogEx(ddp_mmp_get_events()->Extd_State, MMProfileFlagPulse, Suspend, 1);
  882. return ret;
  883. }
  884. int ext_disp_config_input_multiple(disp_session_input_config *input, int idx, unsigned int session)
  885. {
  886. int ret = 0;
  887. int i = 0;
  888. int config_layer_id = 0;
  889. #ifdef MTK_FB_RDMA1_SUPPORT
  890. M4U_PORT_STRUCT sPort;
  891. #endif
  892. /* /EXT_DISP_FUNC(); */
  893. disp_ddp_path_config *data_config;
  894. if (pgc->state != EXTD_INIT && pgc->state != EXTD_RESUME && pgc->suspend_config != 1) {
  895. EXT_DISP_LOG("config ext disp is already slept, state:%d\n", pgc->state);
  896. MMProfileLogEx(ddp_mmp_get_events()->Extd_ErrorInfo, MMProfileFlagPulse, Config, idx);
  897. return -2;
  898. }
  899. _ext_disp_path_lock();
  900. /* all dirty should be cleared in dpmgr_path_get_last_config() */
  901. data_config = dpmgr_path_get_last_config(pgc->dpmgr_handle);
  902. /* hope we can use only 1 input struct for input config, just set layer number */
  903. if (_should_config_ovl_input()) {
  904. for (i = 0; i < input->config_layer_num; i++) {
  905. config_layer_id = input->config[i].layer_id;
  906. ret = _convert_disp_input_to_ovl(&(data_config->ovl_config[config_layer_id]),
  907. &(input->config[i]));
  908. dprec_mmp_dump_ovl_layer(&(data_config->ovl_config[config_layer_id]), config_layer_id, 2);
  909. if (init_roi == 1) {
  910. memcpy(&(data_config->dispif_config), &extd_lcm_params, sizeof(LCM_PARAMS));
  911. EXT_DISP_LOG("set dest w:%d, h:%d\n",
  912. extd_lcm_params.dpi.width, extd_lcm_params.dpi.height);
  913. data_config->dst_w = extd_lcm_params.dpi.width;
  914. data_config->dst_h = extd_lcm_params.dpi.height;
  915. data_config->dst_dirty = 1;
  916. data_config->rdma_config.address = 0;
  917. }
  918. data_config->ovl_dirty = 1;
  919. pgc->need_trigger_overlay = 1;
  920. }
  921. } else {
  922. OVL_CONFIG_STRUCT ovl_config;
  923. _convert_disp_input_to_ovl(&ovl_config, &(input->config[i]));
  924. dprec_mmp_dump_ovl_layer(&ovl_config, input->config[i].layer_id, 2);
  925. ret = _convert_disp_input_to_rdma(&(data_config->rdma_config), &(input->config[i]));
  926. if (data_config->rdma_config.address) {
  927. data_config->rdma_dirty = 1;
  928. pgc->need_trigger_overlay = 1;
  929. }
  930. if (pgc->ovl_req_state == EXTD_OVL_REMOVE_REQ) {
  931. EXT_DISP_LOG("config M4U Port DISP_MODULE_RDMA1\n");
  932. #ifdef MTK_FB_RDMA1_SUPPORT
  933. sPort.ePortID = M4U_PORT_DISP_RDMA1;
  934. sPort.Virtuality = 1;
  935. sPort.Security = 0;
  936. sPort.Distance = 1;
  937. sPort.Direction = 0;
  938. ret = m4u_config_port(&sPort);
  939. if (ret != 0)
  940. EXT_DISP_LOG("config M4U Port DISP_MODULE_RDMA1 FAIL\n");
  941. #endif
  942. pgc->ovl_req_state = EXTD_OVL_REMOVING;
  943. }
  944. }
  945. if (_should_wait_path_idle())
  946. dpmgr_wait_event_timeout(pgc->dpmgr_handle, DISP_PATH_EVENT_FRAME_DONE, HZ / 2);
  947. memcpy(&(data_config->dispif_config), &extd_lcm_params, sizeof(LCM_PARAMS));
  948. ret = dpmgr_path_config(pgc->dpmgr_handle, data_config,
  949. ext_disp_cmdq_enabled() ? pgc->cmdq_handle_config : NULL);
  950. /* this is used for decouple mode, to indicate whether we need to trigger ovl */
  951. /* pgc->need_trigger_overlay = 1; */
  952. init_roi = 0;
  953. _ext_disp_path_unlock();
  954. if (data_config->ovl_dirty) {
  955. EXT_DISP_LOG("config_input_multiple idx:%d -w:%d, h:%d, pitch:%d\n",
  956. idx, data_config->ovl_config[0].src_w, data_config->ovl_config[0].src_h,
  957. data_config->ovl_config[0].src_pitch);
  958. } else {
  959. EXT_DISP_LOG("config_input_multiple idx:%d -w:%d, h:%d, pitch:%d, mva:0x%lx\n",
  960. idx, data_config->rdma_config.width, data_config->rdma_config.height,
  961. data_config->rdma_config.pitch, data_config->rdma_config.address);
  962. }
  963. return ret;
  964. }
  965. int ext_disp_is_alive(void)
  966. {
  967. unsigned int temp = 0;
  968. EXT_DISP_FUNC();
  969. _ext_disp_path_lock();
  970. temp = pgc->state;
  971. _ext_disp_path_unlock();
  972. return temp;
  973. }
  974. int ext_disp_is_sleepd(void)
  975. {
  976. unsigned int temp = 0;
  977. /* EXT_DISP_FUNC(); */
  978. _ext_disp_path_lock();
  979. temp = !pgc->state;
  980. _ext_disp_path_unlock();
  981. return temp;
  982. }
  983. int ext_disp_get_width(void)
  984. {
  985. return 0;
  986. }
  987. int ext_disp_get_height(void)
  988. {
  989. return 0;
  990. }
  991. unsigned int ext_disp_get_sess_id(void)
  992. {
  993. unsigned int session_id = is_context_inited > 0 ? pgc->session : 0;
  994. return session_id;
  995. }
  996. int ext_disp_is_video_mode(void)
  997. {
  998. /* TODO: we should store the video/cmd mode in runtime, because ROME will support cmd/vdo dynamic switch */
  999. return true;
  1000. }
  1001. int ext_disp_diagnose(void)
  1002. {
  1003. int ret = 0;
  1004. if (is_context_inited > 0) {
  1005. EXT_DISP_LOG("ext_disp_diagnose, is_context_inited --%d\n", is_context_inited);
  1006. dpmgr_check_status(pgc->dpmgr_handle);
  1007. }
  1008. return ret;
  1009. }
  1010. CMDQ_SWITCH ext_disp_cmdq_enabled(void)
  1011. {
  1012. return ext_disp_use_cmdq;
  1013. }
  1014. int ext_disp_switch_cmdq(CMDQ_SWITCH use_cmdq)
  1015. {
  1016. _ext_disp_path_lock();
  1017. ext_disp_use_cmdq = use_cmdq;
  1018. EXT_DISP_LOG("display driver use %s to config register now\n", (use_cmdq == CMDQ_ENABLE) ? "CMDQ" : "CPU");
  1019. _ext_disp_path_unlock();
  1020. return ext_disp_use_cmdq;
  1021. }
  1022. void ext_disp_get_curr_addr(unsigned long *input_curr_addr, int module)
  1023. {
  1024. if (module == 1)
  1025. ovl_get_address(DISP_MODULE_OVL1, input_curr_addr);
  1026. else
  1027. dpmgr_get_input_address(pgc->dpmgr_handle, input_curr_addr);
  1028. }
  1029. int ext_disp_factory_test(int mode, void *config)
  1030. {
  1031. dpmgr_factory_mode_test(DISP_MODULE_DPI, NULL, config);
  1032. return 0;
  1033. }
  1034. int ext_disp_get_handle(disp_path_handle *dp_handle, cmdqRecHandle *pHandle)
  1035. {
  1036. *dp_handle = pgc->dpmgr_handle;
  1037. *pHandle = pgc->cmdq_handle_config;
  1038. return pgc->mode;
  1039. }
  1040. int ext_disp_set_ovl1_status(int status)
  1041. {
  1042. dpmgr_set_ovl1_status(status);
  1043. return 0;
  1044. }
  1045. int ext_disp_set_lcm_param(LCM_PARAMS *pLCMParam)
  1046. {
  1047. if (pLCMParam)
  1048. memcpy(&extd_lcm_params, pLCMParam, sizeof(LCM_PARAMS));
  1049. return 0;
  1050. }
  1051. enum EXTD_OVL_REQ_STATUS ext_disp_get_ovl_req_status(unsigned int session)
  1052. {
  1053. enum EXTD_OVL_REQ_STATUS ret = EXTD_OVL_NO_REQ;
  1054. _ext_disp_path_lock();
  1055. ret = pgc->ovl_req_state;
  1056. _ext_disp_path_unlock();
  1057. return ret;
  1058. }
  1059. int ext_disp_path_change(enum EXTD_OVL_REQ_STATUS action, unsigned int session)
  1060. {
  1061. EXT_DISP_FUNC();
  1062. /* if(pgc->state == EXTD_DEINIT) */
  1063. /* { */
  1064. /* EXT_DISP_LOG("external display do not init!\n"); */
  1065. /* return -1; */
  1066. /* } */
  1067. if (EXTD_OVERLAY_CNT > 0) {
  1068. _ext_disp_path_lock();
  1069. switch (action) {
  1070. case EXTD_OVL_NO_REQ:
  1071. if (pgc->ovl_req_state == EXTD_OVL_REMOVED) {
  1072. /* 0 - DDP_OVL1_STATUS_IDLE */
  1073. dpmgr_set_ovl1_status(0);
  1074. }
  1075. pgc->ovl_req_state = EXTD_OVL_NO_REQ;
  1076. break;
  1077. case EXTD_OVL_REQUSTING_REQ:
  1078. if (ovl_get_status() == DDP_OVL1_STATUS_PRIMARY) {
  1079. /* 1 - DDP_OVL1_STATUS_SUB_REQUESTING */
  1080. dpmgr_set_ovl1_status(DDP_OVL1_STATUS_SUB_REQUESTING);
  1081. }
  1082. break;
  1083. case EXTD_OVL_IDLE_REQ:
  1084. if (ovl_get_status() == DDP_OVL1_STATUS_SUB) {
  1085. /* 1 - DDP_OVL1_STATUS_SUB_REQUESTING */
  1086. dpmgr_set_ovl1_status(DDP_OVL1_STATUS_IDLE);
  1087. }
  1088. break;
  1089. case EXTD_OVL_SUB_REQ:
  1090. pgc->ovl_req_state = EXTD_OVL_SUB_REQ;
  1091. break;
  1092. case EXTD_OVL_REMOVE_REQ:
  1093. if (DISP_SESSION_DEV(session) != DEV_EINK + 1) {
  1094. dpmgr_remove_ovl1_sub(pgc->dpmgr_handle, pgc->cmdq_handle_config);
  1095. ext_disp_path_set_mode(EXTD_RDMA_DPI_MODE, session);
  1096. pgc->ovl_req_state = EXTD_OVL_REMOVE_REQ;
  1097. }
  1098. break;
  1099. case EXTD_OVL_REMOVING:
  1100. pgc->ovl_req_state = EXTD_OVL_REMOVING;
  1101. break;
  1102. case EXTD_OVL_REMOVED:
  1103. pgc->ovl_req_state = EXTD_OVL_REMOVED;
  1104. break;
  1105. case EXTD_OVL_INSERT_REQ:
  1106. if (ext_disp_mode != EXTD_DIRECT_LINK_MODE) {
  1107. dpmgr_insert_ovl1_sub(pgc->dpmgr_handle, pgc->cmdq_handle_config);
  1108. ext_disp_path_set_mode(EXTD_DIRECT_LINK_MODE, session);
  1109. pgc->ovl_req_state = EXTD_OVL_INSERT_REQ;
  1110. }
  1111. break;
  1112. case EXTD_OVL_INSERTED:
  1113. pgc->ovl_req_state = EXTD_OVL_INSERTED;
  1114. break;
  1115. default:
  1116. break;
  1117. }
  1118. _ext_disp_path_unlock();
  1119. }
  1120. return 0;
  1121. }
  1122. int ext_disp_wait_ovl_available(int ovl_num)
  1123. {
  1124. int ret = 0;
  1125. if (EXTD_OVERLAY_CNT > 0) {
  1126. /*wait OVL can be used by external display */
  1127. ret = dpmgr_wait_ovl_available(ovl_num);
  1128. }
  1129. return ret;
  1130. }
  1131. bool ext_disp_path_source_is_RDMA(unsigned int session)
  1132. {
  1133. bool is_rdma = false;
  1134. if ((ext_disp_mode == EXTD_RDMA_DPI_MODE) && (pgc->ovl_req_state != EXTD_OVL_REMOVE_REQ)
  1135. && (pgc->ovl_req_state != EXTD_OVL_REMOVING)) {
  1136. /* path source module is RDMA */
  1137. is_rdma = true;
  1138. }
  1139. return is_rdma;
  1140. }
  1141. int ext_disp_is_dim_layer(unsigned long mva)
  1142. {
  1143. int ret = 0;
  1144. ret = is_dim_layer(mva);
  1145. return ret;
  1146. }