primary_display.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786
  1. /* Copyright Statement:
  2. *
  3. * This software/firmware and related documentation ("MediaTek Software") are
  4. * protected under relevant copyright laws. The information contained herein
  5. * is confidential and proprietary to MediaTek Inc. and/or its licensors.
  6. * Without the prior written permission of MediaTek inc. and/or its licensors,
  7. * any reproduction, modification, use or disclosure of MediaTek Software,
  8. * and information contained herein, in whole or in part, shall be strictly prohibited.
  9. */
  10. /* MediaTek Inc. (C) 2015. All rights reserved.
  11. *
  12. * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
  13. * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
  14. * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON
  15. * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
  16. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
  17. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
  18. * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
  19. * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
  20. * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH
  21. * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES
  22. * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES
  23. * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK
  24. * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
  25. * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND
  26. * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
  27. * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
  28. * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO
  29. * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
  30. */
  31. #include <video_fb.h>
  32. #include <target/board.h>
  33. #include <env.h>
  34. #include "lcm_drv.h"
  35. #include <string.h>
  36. #include <stdlib.h>
  37. #include <platform/mt_gpt.h>
  38. #include <platform/disp_drv_platform.h>
  39. #include <platform/disp_drv_log.h>
  40. #include <platform/boot_mode.h>
  41. #include <platform/primary_display.h>
  42. #include <platform/disp_lcm.h>
  43. #define DDP_LK_BOOT
  44. #ifndef HZ
  45. #define HZ 100
  46. #endif
  47. int primary_display_use_cmdq = CMDQ_DISABLE;
  48. int primary_display_use_m4u = 1;
  49. DISP_PRIMARY_PATH_MODE primary_display_mode = DIRECT_LINK_MODE;
  50. typedef struct {
  51. int state;
  52. int need_trigger_overlay;
  53. DISP_PRIMARY_PATH_MODE mode;
  54. unsigned int last_vsync_tick;
  55. disp_lcm_handle *plcm;
  56. cmdqRecHandle cmdq_handle_config;
  57. cmdqRecHandle cmdq_handle_trigger;
  58. disp_path_handle dpmgr_handle;
  59. disp_path_handle ovl2mem_path_handle;
  60. } display_primary_path_context;
  61. #define pgc _get_context()
  62. static display_primary_path_context* _get_context(void)
  63. {
  64. static int is_context_inited = 0;
  65. static display_primary_path_context g_context;
  66. if (!is_context_inited) {
  67. memset((void*)&g_context, 0, sizeof(display_primary_path_context));
  68. is_context_inited = 1;
  69. }
  70. return &g_context;
  71. }
  72. static DISP_MODULE_ENUM _get_dst_module_by_lcm(disp_lcm_handle *plcm)
  73. {
  74. if (plcm == NULL) {
  75. DISPERR("plcm is null\n");
  76. return DISP_MODULE_UNKNOWN;
  77. }
  78. if (plcm->params->type == LCM_TYPE_DSI) {
  79. if (plcm->lcm_if_id == LCM_INTERFACE_DSI0) {
  80. return DISP_MODULE_DSI0;
  81. } else if (plcm->lcm_if_id == LCM_INTERFACE_DSI1) {
  82. return DISP_MODULE_DSI1;
  83. } else if (plcm->lcm_if_id == LCM_INTERFACE_DSI_DUAL) {
  84. return DISP_MODULE_DSIDUAL;
  85. } else {
  86. return DISP_MODULE_DSI0;
  87. }
  88. } else if (plcm->params->type == LCM_TYPE_DPI) {
  89. return DISP_MODULE_DPI;
  90. } else {
  91. DISPERR("can't find primary path dst module\n");
  92. return DISP_MODULE_UNKNOWN;
  93. }
  94. }
  95. extern int ddp_dsi_set_lcm_utils(DISP_MODULE_ENUM module, LCM_DRIVER *lcm_drv);
  96. static int _build_path_direct_link(void)
  97. {
  98. int ret = 0;
  99. DISP_MODULE_ENUM dst_module = 0;
  100. DISPFUNC();
  101. pgc->mode = DIRECT_LINK_MODE;
  102. pgc->dpmgr_handle = dpmgr_create_path(DDP_SCENARIO_PRIMARY_DISP, NULL);
  103. if (pgc->dpmgr_handle) {
  104. DISPCHECK("dpmgr create path SUCCESS(0x%08x)\n", pgc->dpmgr_handle);
  105. } else {
  106. DISPCHECK("dpmgr create path FAIL\n");
  107. return -1;
  108. }
  109. dst_module = _get_dst_module_by_lcm(pgc->plcm);
  110. dpmgr_path_set_dst_module(pgc->dpmgr_handle, dst_module);
  111. DISPCHECK("dpmgr set dst module FINISHED(%s)\n", ddp_get_module_name(dst_module));
  112. dpmgr_set_lcm_utils(pgc->dpmgr_handle, pgc->plcm->drv);
  113. return ret;
  114. }
  115. static int _convert_disp_input_to_rdma(RDMA_CONFIG_STRUCT *dst, disp_input_config* src)
  116. {
  117. if (src && dst) {
  118. dst->inputFormat = src->fmt;
  119. dst->address = src->addr;
  120. dst->width = src->src_w;
  121. dst->height = src->src_h;
  122. dst->pitch = src->src_pitch;
  123. return 0;
  124. } else {
  125. DISPERR("src(0x%08x) or dst(0x%08x) is null\n", src, dst);
  126. return -1;
  127. }
  128. }
  129. static int _convert_disp_input_to_ovl(OVL_CONFIG_STRUCT *dst, disp_input_config* src)
  130. {
  131. if (src && dst) {
  132. dst->layer = src->layer;
  133. dst->layer_en = src->layer_en;
  134. dst->fmt = src->fmt;
  135. dst->addr = src->addr;
  136. dst->vaddr = src->vaddr;
  137. dst->src_x = src->src_x;
  138. dst->src_y = src->src_y;
  139. dst->src_w = src->src_w;
  140. dst->src_h = src->src_h;
  141. dst->src_pitch = src->src_pitch;
  142. dst->dst_x = src->dst_x;
  143. dst->dst_y = src->dst_y;
  144. dst->dst_w = src->dst_w;
  145. dst->dst_h = src->dst_h;
  146. dst->keyEn = src->keyEn;
  147. dst->key = src->key;
  148. dst->aen = src->aen;
  149. dst->alpha = src->alpha;
  150. dst->isDirty = src->isDirty;
  151. dst->buff_idx = src->buff_idx;
  152. dst->identity = src->identity;
  153. dst->connected_type = src->connected_type;
  154. dst->security = src->security;
  155. return 0;
  156. } else {
  157. DISPERR("src(0x%08x) or dst(0x%08x) is null\n", src, dst);
  158. return -1;
  159. }
  160. }
  161. int primary_display_is_lcm_connected(void)
  162. {
  163. return pgc->plcm->is_connected;
  164. }
  165. const char* primary_display_get_lcm_name(void)
  166. {
  167. return disp_lcm_get_name(pgc->plcm);
  168. }
  169. void _dump_lcm_info_by_video_printf(void)
  170. {
  171. int i = 0;
  172. LCM_DRIVER *l = NULL;
  173. LCM_PARAMS *p = NULL;
  174. disp_lcm_handle *plcm = pgc->plcm;
  175. if (plcm == NULL) {
  176. DISPERR("plcm is null\n");
  177. return;
  178. }
  179. l = plcm->drv;
  180. p = plcm->params;
  181. if (l && p) {
  182. video_printf("[LCM] name: %s\n", l->name);
  183. video_printf("[LCM] resolution: %d x %d\n", p->width, p->height);
  184. video_printf("[LCM] physical size: %d x %d\n", p->physical_width, p->physical_height);
  185. video_printf("[LCM] physical size: %d x %d\n", p->physical_width, p->physical_height);
  186. switch (p->lcm_if) {
  187. case LCM_INTERFACE_DSI0:
  188. video_printf("[LCM] interface: DSI0\n");
  189. break;
  190. case LCM_INTERFACE_DSI1:
  191. video_printf("[LCM] interface: DSI1\n");
  192. break;
  193. default:
  194. video_printf("[LCM] interface: unknown\n");
  195. break;
  196. }
  197. switch (p->type) {
  198. case LCM_TYPE_DSI:
  199. video_printf("[LCM] Type: DSI\n");
  200. break;
  201. default:
  202. video_printf("[LCM] TYPE: unknown\n");
  203. break;
  204. }
  205. if (p->type == LCM_TYPE_DSI) {
  206. switch (p->dsi.mode) {
  207. case CMD_MODE:
  208. video_printf("[LCM] DSI Mode: CMD_MODE\n");
  209. break;
  210. case SYNC_PULSE_VDO_MODE:
  211. video_printf("[LCM] DSI Mode: SYNC_PULSE_VDO_MODE\n");
  212. break;
  213. case SYNC_EVENT_VDO_MODE:
  214. video_printf("[LCM] DSI Mode: SYNC_EVENT_VDO_MODE\n");
  215. break;
  216. case BURST_VDO_MODE:
  217. video_printf("[LCM] DSI Mode: BURST_VDO_MODE\n");
  218. break;
  219. default:
  220. video_printf("[LCM] DSI Mode: Unknown\n");
  221. break;
  222. }
  223. }
  224. if (p->type == LCM_TYPE_DSI) {
  225. video_printf("[LCM] LANE_NUM: %d,data_format: %d,vertical_sync_active: %d\n",p->dsi.LANE_NUM,p->dsi.data_format);
  226. video_printf("[LCM] vact: %d, vbp: %d, vfp: %d, vact_line: %d, hact: %d, hbp: %d, hfp: %d, hblank: %d, hblank: %d\n",p->dsi.vertical_sync_active, p->dsi.vertical_backporch,p->dsi.vertical_frontporch,p->dsi.vertical_active_line,p->dsi.horizontal_sync_active,p->dsi.horizontal_backporch,p->dsi.horizontal_frontporch,p->dsi.horizontal_blanking_pixel);
  227. video_printf("[LCM] pll_select: %d, pll_div1: %d, pll_div2: %d, fbk_div: %d,fbk_sel: %d, rg_bir: %d\n",p->dsi.pll_select,p->dsi.pll_div1,p->dsi.pll_div2,p->dsi.fbk_div,p->dsi.fbk_sel,p->dsi.rg_bir);
  228. video_printf("[LCM] rg_bic: %d, rg_bp: %d, PLL_CLOCK: %d, dsi_clock: %d, ssc_range: %d, ssc_disable: %d, compatibility_for_nvk: %d, cont_clock: %d\n", p->dsi.rg_bic, p->dsi.rg_bp,p->dsi.PLL_CLOCK,p->dsi.dsi_clock,p->dsi.ssc_range,p->dsi.ssc_disable,p->dsi.compatibility_for_nvk,p->dsi.cont_clock);
  229. video_printf("[LCM] lcm_ext_te_enable: %d, noncont_clock: %d, noncont_clock_period: %d\n", p->dsi.lcm_ext_te_enable,p->dsi.noncont_clock,p->dsi.noncont_clock_period);
  230. }
  231. }
  232. return;
  233. }
  234. typedef struct _disp_dfo_item {
  235. char name[32];
  236. int value;
  237. } disp_dfo_item_t;
  238. static disp_dfo_item_t disp_dfo_setting[] = {
  239. {"LCM_FAKE_WIDTH", 0},
  240. {"LCM_FAKE_HEIGHT", 0},
  241. {"DISP_DEBUG_SWITCH", 0}
  242. };
  243. unsigned int mt_disp_parse_dfo_setting(void)
  244. {
  245. unsigned int i, j = 0, k = 0;
  246. char tmp[11];
  247. char *buffer = NULL;
  248. char *ptr = NULL;
  249. buffer = (char *)get_env("DFO");
  250. DISPMSG("env buffer = %s\n", buffer);
  251. if (buffer != NULL) {
  252. for (i = 0; i< (sizeof(disp_dfo_setting)/sizeof(disp_dfo_item_t)); i++) {
  253. memset((void*)tmp, 0, sizeof(tmp)/sizeof(tmp[0]));
  254. ptr = strstr(buffer, disp_dfo_setting[i].name);
  255. k = strlen(tmp);
  256. if (ptr == NULL) continue;
  257. DISPMSG("disp_dfo_setting[%d].name = [%s], name_lenght = %d\n", i, ptr, k);
  258. do { k--; } while (((*ptr) != '\0') && ((*ptr++) != ',') && (k >= 0));
  259. do {
  260. tmp[j++] = *ptr++;
  261. k--;
  262. } while (((*ptr) != '\0') && (*ptr != ',') && (j < sizeof(tmp)/sizeof(tmp[0])) && (k >= 0));
  263. disp_dfo_setting[i].value = atoi((const char*)tmp);
  264. DISPMSG("disp_dfo_setting[%d].name = [%s|%d]\n", i, tmp, disp_dfo_setting[i].value);
  265. }
  266. } else {
  267. DISPMSG("env buffer = NULL\n");
  268. }
  269. return 0;
  270. }
  271. int mt_disp_get_dfo_setting(const char *string, unsigned int *value)
  272. {
  273. char *disp_name;
  274. int disp_value;
  275. unsigned int i = 0;
  276. if (string == NULL)
  277. return -1;
  278. for (i=0; i<(sizeof(disp_dfo_setting)/sizeof(disp_dfo_item_t)); i++) {
  279. disp_name = disp_dfo_setting[i].name;
  280. disp_value = disp_dfo_setting[i].value;
  281. if (!strcmp(disp_name, string)) {
  282. *value = disp_value;
  283. DISPMSG("%s = [DEC]%d [HEX]0x%08x\n", disp_name, disp_value, disp_value);
  284. return 0;
  285. }
  286. }
  287. return 0;
  288. }
  289. int primary_display_change_lcm_resolution(unsigned int width, unsigned int height)
  290. {
  291. if (pgc->plcm) {
  292. DISPMSG("LCM Resolution will be changed, original: %dx%d, now: %dx%d\n", pgc->plcm->params->width, pgc->plcm->params->height, width, height);
  293. // align with 4 is the minimal check, to ensure we can boot up into kernel, and could modify dfo setting again using meta tool
  294. // otherwise we will have a panic in lk(root cause unknown).
  295. if (width >pgc->plcm->params->width || height > pgc->plcm->params->height || width == 0 || height == 0 || width %4 || height %2) {
  296. DISPERR("Invalid resolution: %dx%d\n", width, height);
  297. return -1;
  298. }
  299. if (primary_display_is_video_mode()) {
  300. DISPERR("Warning!!!Video Mode can't support multiple resolution!\n");
  301. return -1;
  302. }
  303. pgc->plcm->params->width = width;
  304. pgc->plcm->params->height = height;
  305. return 0;
  306. } else {
  307. return -1;
  308. }
  309. }
  310. int primary_display_init(char *lcm_name)
  311. {
  312. DISP_STATUS ret = DISP_STATUS_OK;
  313. DISP_MODULE_ENUM dst_module = 0;
  314. unsigned int lcm_fake_width = 0;
  315. unsigned int lcm_fake_height = 0;
  316. LCM_PARAMS *lcm_param = NULL;
  317. LCM_INTERFACE_ID lcm_id = LCM_INTERFACE_NOTDEFINED;
  318. DISPFUNC();
  319. dpmgr_init();
  320. if (pgc->plcm == NULL)
  321. pgc->plcm = disp_lcm_probe( lcm_name, LCM_INTERFACE_NOTDEFINED);
  322. mt_disp_parse_dfo_setting();
  323. if ((0 == mt_disp_get_dfo_setting("LCM_FAKE_WIDTH", &lcm_fake_width)) && (0 == mt_disp_get_dfo_setting("LCM_FAKE_HEIGHT", &lcm_fake_height))) {
  324. if (0 != primary_display_change_lcm_resolution(lcm_fake_width, lcm_fake_height)) {
  325. DISPERR("[DISP_DFO]WARNING!!! Change LCM Resolution FAILED!!!\n");
  326. }
  327. }
  328. if (pgc->plcm == NULL) {
  329. DISPCHECK("disp_lcm_probe returns null\n");
  330. ret = DISP_STATUS_ERROR;
  331. goto done;
  332. } else {
  333. DISPCHECK("disp_lcm_probe SUCCESS\n");
  334. }
  335. lcm_param = disp_lcm_get_params(pgc->plcm);
  336. if (lcm_param == NULL) {
  337. DISPERR("get lcm params FAILED\n");
  338. ret = DISP_STATUS_ERROR;
  339. goto done;
  340. }
  341. if (primary_display_mode == DIRECT_LINK_MODE) {
  342. _build_path_direct_link();
  343. DISPCHECK("primary display is DIRECT LINK MODE\n");
  344. } else {
  345. DISPCHECK("primary display mode is WRONG\n");
  346. }
  347. dpmgr_path_set_video_mode(pgc->dpmgr_handle, primary_display_is_video_mode());
  348. dpmgr_path_init(pgc->dpmgr_handle, CMDQ_DISABLE);
  349. #ifdef MACH_FPGA
  350. dpmgr_path_reset(pgc->dpmgr_handle, CMDQ_DISABLE);
  351. #endif
  352. disp_ddp_path_config data_config;
  353. memset((void*)&data_config, 0, sizeof(disp_ddp_path_config));
  354. memcpy(&(data_config.dsi_config), &(lcm_param->dsi), sizeof(LCM_DSI_PARAMS));
  355. data_config.dst_w = lcm_param->width;
  356. data_config.dst_h = lcm_param->height;
  357. if (lcm_param->type == LCM_TYPE_DSI) {
  358. if (lcm_param->dsi.data_format.format == LCM_DSI_FORMAT_RGB888)
  359. data_config.lcm_bpp = 24;
  360. else if (lcm_param->dsi.data_format.format == LCM_DSI_FORMAT_RGB565)
  361. data_config.lcm_bpp = 16;
  362. else if (lcm_param->dsi.data_format.format == LCM_DSI_FORMAT_RGB666)
  363. data_config.lcm_bpp = 18;
  364. } else if (lcm_param->type == LCM_TYPE_DPI) {
  365. if ( lcm_param->dpi.format == LCM_DPI_FORMAT_RGB888)
  366. data_config.lcm_bpp = 24;
  367. else if ( lcm_param->dpi.format == LCM_DPI_FORMAT_RGB565)
  368. data_config.lcm_bpp = 16;
  369. if ( lcm_param->dpi.format == LCM_DPI_FORMAT_RGB666)
  370. data_config.lcm_bpp = 18;
  371. }
  372. data_config.dst_dirty = 1;
  373. #ifdef MACH_FPGA
  374. data_config.ovl_dirty = 1;
  375. #endif
  376. ret = dpmgr_path_config(pgc->dpmgr_handle, &data_config, CMDQ_DISABLE);
  377. ret = disp_lcm_init(pgc->plcm);
  378. if (primary_display_is_video_mode()) {
  379. dpmgr_map_event_to_irq(pgc->dpmgr_handle, DISP_PATH_EVENT_IF_VSYNC, DDP_IRQ_RDMA0_DONE);
  380. }
  381. dpmgr_enable_event(pgc->dpmgr_handle, DISP_PATH_EVENT_IF_VSYNC);
  382. dpmgr_enable_event(pgc->dpmgr_handle, DISP_PATH_EVENT_FRAME_DONE);
  383. pgc->state = 1;
  384. done:
  385. return ret;
  386. }
  387. // register rdma done event
  388. int primary_display_wait_for_idle(void)
  389. {
  390. DISP_STATUS ret = DISP_STATUS_OK;
  391. DISPFUNC();
  392. done:
  393. return ret;
  394. }
  395. int priamry_display_wait_for_vsync(void)
  396. {
  397. int ret = 0;
  398. ret = dpmgr_wait_event(pgc->dpmgr_handle, DISP_PATH_EVENT_IF_VSYNC);
  399. if (ret == -2) {
  400. DISPCHECK("vsync for primary display path not enabled yet\n");
  401. return -1;
  402. }
  403. pgc->last_vsync_tick = 0;
  404. return 0;
  405. }
  406. #ifdef MTK_ROUND_CORNER_SUPPORT
  407. LCM_ROUND_CORNER *primary_display_get_corner_params(void)
  408. {
  409. if (pgc->plcm == NULL) {
  410. return NULL;
  411. }
  412. if (pgc->plcm->params) {
  413. return &(pgc->plcm->params->round_corner_params);
  414. } else {
  415. DISPERR("lcm_params is null\n");
  416. return NULL;
  417. }
  418. }
  419. int disp_get_round_corner_size(void)
  420. {
  421. /* size = pattern_w * pattern_h * 2(top/bottom) * BPP */
  422. return DISP_GetScreenWidth() * DISP_GetScreenHeight() * 4;
  423. }
  424. #endif
  425. int primary_display_get_width(void)
  426. {
  427. if (pgc->plcm == NULL) {
  428. pgc->plcm = disp_lcm_probe(NULL, LCM_INTERFACE_NOTDEFINED);
  429. DISPMSG("lcm handle is null, after probe:0x%08x\n",pgc->plcm);
  430. if (pgc->plcm == NULL)
  431. return 0;
  432. }
  433. if (pgc->plcm->params) {
  434. return pgc->plcm->params->width;
  435. } else {
  436. DISPERR("lcm_params is null!\n");
  437. return 0;
  438. }
  439. }
  440. int primary_display_get_height(void)
  441. {
  442. if (pgc->plcm == NULL) {
  443. pgc->plcm = disp_lcm_probe(NULL, LCM_INTERFACE_NOTDEFINED);
  444. DISPMSG("lcm handle is null, after probe:0x%08x\n",pgc->plcm);
  445. if (pgc->plcm == NULL)
  446. return 0;
  447. }
  448. if (pgc->plcm->params) {
  449. return pgc->plcm->params->height;
  450. } else {
  451. DISPERR("lcm_params is null!\n");
  452. return 0;
  453. }
  454. }
  455. int primary_display_get_bpp(void)
  456. {
  457. return 32;
  458. }
  459. int primary_display_get_pages(void)
  460. {
  461. return 3;
  462. }
  463. int primary_display_diagnose(void)
  464. {
  465. int ret = 0;
  466. dpmgr_check_status(pgc->dpmgr_handle);
  467. return ret;
  468. }
  469. int primary_display_trigger(int blocking)
  470. {
  471. int ret = 0;
  472. static int count = 0;
  473. DISPFUNC();
  474. if (pgc->mode == DIRECT_LINK_MODE || pgc->mode == SINGLE_LAYER_MODE) {
  475. if (dpmgr_path_is_busy(pgc->dpmgr_handle)) {
  476. if (primary_display_is_video_mode()) {
  477. return 0;
  478. }
  479. dpmgr_wait_event_timeout(pgc->dpmgr_handle, DISP_PATH_EVENT_FRAME_DONE, HZ*1);
  480. }
  481. DISPCHECK("trigger mode: %s\n", (pgc->mode == DIRECT_LINK_MODE)?"DIRECT_LINK":"SINGLE_LAYER");
  482. if (count++ ==0)
  483. disp_lcm_update(pgc->plcm, 0, 0, pgc->plcm->params->width, pgc->plcm->params->height, 0);
  484. dpmgr_path_start(pgc->dpmgr_handle, primary_display_use_cmdq);
  485. if (primary_display_use_cmdq == CMDQ_DISABLE) {
  486. dpmgr_path_trigger(pgc->dpmgr_handle, NULL, primary_display_use_cmdq);
  487. }
  488. } else {
  489. DISPCHECK("primary display mode is WRONG(%d)\n", (unsigned int)pgc->mode);
  490. }
  491. return ret;
  492. }
  493. extern int DSI_BIST_Pattern_Test(DISP_MODULE_ENUM module, void* cmdq, bool enable, unsigned int color);
  494. int primary_display_config_input(disp_input_config* input)
  495. {
  496. int ret = 0;
  497. int i=0;
  498. int layer =0;
  499. disp_ddp_path_config data_config;
  500. DISPFUNC();
  501. // all dirty should be cleared in dpmgr_path_get_last_config()
  502. memcpy((void*)&data_config, (void*)dpmgr_path_get_last_config(pgc->dpmgr_handle), sizeof(disp_ddp_path_config));
  503. // no need do this dirty = 0; dpmgr_path_get_last_config do this.
  504. data_config.dst_dirty = 0;
  505. data_config.ovl_dirty = 0;
  506. data_config.rdma_dirty = 0;
  507. data_config.wdma_dirty = 0;
  508. if (pgc->mode == DIRECT_LINK_MODE || pgc->mode == DECOUPLE_MODE) {
  509. if (dpmgr_path_is_busy(pgc->dpmgr_handle)) {
  510. if (primary_display_is_video_mode()) {
  511. dpmgr_wait_event_timeout(pgc->dpmgr_handle, DISP_PATH_EVENT_FRAME_DONE, HZ*1);
  512. }
  513. }
  514. ret = _convert_disp_input_to_ovl(&(data_config.ovl_config[input->layer]), input);
  515. data_config.ovl_dirty = 1;
  516. ret = dpmgr_path_config(pgc->dpmgr_handle, &data_config, primary_display_use_cmdq);
  517. // this is used for decouple mode, to indicate whether we need to trigger ovl
  518. pgc->need_trigger_overlay = 1;
  519. } else if (pgc->mode == SINGLE_LAYER_MODE) {
  520. ret = _convert_disp_input_to_rdma(&data_config.rdma_config, input);
  521. data_config.rdma_dirty= 1;
  522. ret = dpmgr_path_config(pgc->dpmgr_handle, &data_config, primary_display_use_cmdq);
  523. } else if (pgc->mode == DEBUG_RDMA1_DSI0_MODE) {
  524. ret = _convert_disp_input_to_rdma(&(data_config.rdma_config), input);
  525. data_config.rdma_dirty= 1;
  526. if (primary_display_is_video_mode() && dpmgr_path_is_busy(pgc->dpmgr_handle) == 1) {
  527. // TODO: should use wait_event_timeout_or_idle
  528. dpmgr_wait_event_timeout(pgc->dpmgr_handle, DISP_PATH_EVENT_FRAME_DONE, HZ*5);
  529. }
  530. ret = dpmgr_path_config(pgc->dpmgr_handle, &data_config, CMDQ_DISABLE);
  531. } else {
  532. DISPCHECK("primary display mode is WRONG(%d)\n", (unsigned int)pgc->mode);
  533. }
  534. return ret;
  535. }
  536. int primary_display_is_video_mode(void)
  537. {
  538. // TODO: we should store the video/cmd mode in runtime, because will support cmd/vdo dynamic switch
  539. return disp_lcm_is_video_mode(pgc->plcm);
  540. }
  541. int primary_display_get_vsync_interval(void)
  542. {
  543. int ret = 0;
  544. unsigned int time0 = 0;
  545. unsigned int time1 = 0;
  546. unsigned int lcd_time = 0;
  547. ret = dpmgr_wait_event_timeout(pgc->dpmgr_handle, DISP_PATH_EVENT_IF_VSYNC, 2000);
  548. if (ret <= 0)
  549. goto fail;
  550. ret = dpmgr_wait_event_timeout(pgc->dpmgr_handle, DISP_PATH_EVENT_IF_VSYNC, 2000);
  551. if (ret <= 0)
  552. goto fail;
  553. // because we are polling irq status, so the first event should be ignored
  554. time0 = gpt4_tick2time_us(gpt4_get_current_tick());
  555. ret = dpmgr_wait_event_timeout(pgc->dpmgr_handle, DISP_PATH_EVENT_IF_VSYNC, 2000);
  556. if (ret <= 0)
  557. goto fail;
  558. ret = dpmgr_wait_event_timeout(pgc->dpmgr_handle, DISP_PATH_EVENT_IF_VSYNC, 2000);
  559. if (ret > 0) {
  560. time1 = gpt4_tick2time_us(gpt4_get_current_tick());
  561. } else
  562. goto fail;
  563. lcd_time = (time1 - time0)/2;
  564. if (0 != lcd_time)
  565. return (100000000/lcd_time);
  566. else
  567. return (6000);
  568. fail:
  569. DISPERR("wait event fail\n");
  570. return 0;
  571. }
  572. int primary_display_setbacklight(unsigned int level)
  573. {
  574. DISPMSG("lk %s level=%d\n",__func__,level);
  575. int ret=0;
  576. if (pgc->dpmgr_handle == NULL) {
  577. DISPCHECK("lk set backlight early!\n");
  578. return 0;
  579. }
  580. if (dpmgr_path_is_busy(pgc->dpmgr_handle)) {
  581. DISPCHECK("primary display path is busy\n");
  582. ret = dpmgr_wait_event_timeout(pgc->dpmgr_handle, DISP_PATH_EVENT_FRAME_DONE, HZ*1);
  583. DISPCHECK("wait frame done ret:%d\n", ret);
  584. }
  585. disp_lcm_set_backlight(pgc->plcm,level);
  586. return 0;
  587. }
  588. UINT32 DISP_GetScreenWidth(void)
  589. {
  590. return primary_display_get_width();
  591. }
  592. UINT32 DISP_GetScreenHeight(void)
  593. {
  594. return primary_display_get_height();
  595. }
  596. UINT32 DISP_GetActiveHeight(void)
  597. {
  598. if (pgc->plcm == NULL) {
  599. pgc->plcm = disp_lcm_probe(NULL, LCM_INTERFACE_NOTDEFINED);
  600. DISPERR("lcm handle is null, after probe:0x%08x\n",pgc->plcm);
  601. if (pgc->plcm == NULL)return 0;
  602. }
  603. if (pgc->plcm->params) {
  604. return pgc->plcm->params->physical_height;
  605. } else {
  606. DISPERR("lcm_params is null!\n");
  607. return 0;
  608. }
  609. }
  610. UINT32 DISP_GetActiveWidth(void)
  611. {
  612. if (pgc->plcm == NULL) {
  613. pgc->plcm = disp_lcm_probe(NULL, LCM_INTERFACE_NOTDEFINED);
  614. DISPERR("lcm handle is null, after probe:0x%08x\n",pgc->plcm);
  615. if (pgc->plcm == NULL)return 0;
  616. }
  617. if (pgc->plcm->params) {
  618. return pgc->plcm->params->physical_width;
  619. } else {
  620. DISPERR("lcm_params is null!\n");
  621. return 0;
  622. }
  623. }
  624. int primary_display_capture_framebuffer(unsigned int *pbuf)
  625. {
  626. return 0;
  627. }
  628. #define ALIGN_TO(x, n) \
  629. (((x) + ((n) - 1)) & ~((n) - 1))
  630. static UINT32 disp_fb_bpp = 32; ///ARGB8888
  631. static UINT32 disp_fb_pages = 3; //three for framebuffer, one for dim layer
  632. UINT32 DISP_GetScreenBpp(void)
  633. {
  634. return disp_fb_bpp;
  635. }
  636. UINT32 DISP_GetPages(void)
  637. {
  638. return disp_fb_pages; // Double Buffers
  639. }
  640. // TODO: could we use the same header file between lk/kernel to avoid definition non-match issue?
  641. #define DAL_BPP (2)
  642. #define DAL_WIDTH (DISP_GetScreenWidth())
  643. #define DAL_HEIGHT (DISP_GetScreenHeight())
  644. UINT32 DAL_GetLayerSize(void)
  645. {
  646. return DAL_WIDTH * DAL_HEIGHT * DAL_BPP + 4096;
  647. }
  648. UINT32 DISP_GetFBRamSize(void)
  649. {
  650. return ALIGN_TO(DISP_GetScreenWidth(), MTK_FB_ALIGNMENT) * ALIGN_TO(DISP_GetScreenHeight(), MTK_FB_ALIGNMENT) * ((DISP_GetScreenBpp() + 7) >> 3) * DISP_GetPages();
  651. }
  652. unsigned int DISP_GetVRamSize(void)
  653. {
  654. static UINT32 vramSize = 0;
  655. #ifdef MTK_ROUND_CORNER_SUPPORT
  656. LCM_ROUND_CORNER *corner_params;
  657. char *pixel;
  658. #endif
  659. if (0 == vramSize) {
  660. vramSize = DISP_GetFBRamSize();
  661. vramSize += DAL_GetLayerSize();
  662. #ifdef MTK_ROUND_CORNER_SUPPORT
  663. corner_params = primary_display_get_corner_params();
  664. vramSize += disp_get_round_corner_size();
  665. DISPDBG("round corner size: %u bytes\n", disp_get_round_corner_size());
  666. #endif
  667. vramSize = ALIGN_TO(vramSize, 0x100000);
  668. DISPMSG("DISP_GetVRamSize: %u bytes\n", vramSize);
  669. }
  670. return vramSize;
  671. }