external_display.c 36 KB

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