external_display.c 36 KB

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