mtk_drm_assert.c 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437
  1. /*
  2. * Copyright (C) 2019 MediaTek Inc.
  3. *
  4. * This program is free software: you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License version 2 as
  6. * published by the Free Software Foundation.
  7. *
  8. * This program is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. */
  13. #include <drm/drmP.h>
  14. #include <drm/drm_gem.h>
  15. #include <linux/dma-buf.h>
  16. #include <linux/dma-mapping.h>
  17. #include <linux/kmemleak.h>
  18. #include <drm/mediatek_drm.h>
  19. #include "mtk_drm_crtc.h"
  20. #include "mtk_drm_ddp_comp.h"
  21. #include "mtk_drm_drv.h"
  22. #include "mtk_drm_fb.h"
  23. #include "mtk_drm_gem.h"
  24. #include "mtk_drm_plane.h"
  25. #include "mtk_drm_assert.h"
  26. #include "mtk_drm_fbconsole.h"
  27. #include "mtk_drm_mmp.h"
  28. #define RGB888_To_RGB565(x) \
  29. ((((x)&0xF80000) >> 8) | (((x)&0x00FC00) >> 5) | (((x)&0x0000F8) >> 3))
  30. #define MAKE_TWO_RGB565_COLOR(high, low) (((low) << 16) | (high))
  31. #define DAL_STR_BUF_LEN (1024)
  32. #define DAL_BPP (2)
  33. #define MTK_FB_ALIGNMENT 32
  34. static DEFINE_SEMAPHORE(dal_sem);
  35. static inline int DAL_LOCK(void)
  36. {
  37. if (down_interruptible(&dal_sem)) {
  38. DDPPR_ERR("Can't get semaphore in %s\n", __func__);
  39. return -1;
  40. }
  41. return 0;
  42. }
  43. #define DAL_UNLOCK() up(&dal_sem)
  44. struct mtk_drm_gem_obj *dal_buff;
  45. static void *mfc_handle;
  46. char drm_dal_str_buf[DAL_STR_BUF_LEN];
  47. /* DAL layer only surve CRTC0 only */
  48. static int drm_dal_enable;
  49. static struct drm_crtc *dal_crtc;
  50. static void *dal_va;
  51. static u32 dal_pa;
  52. static u32 DAL_GetLayerSize(void)
  53. {
  54. static unsigned int size;
  55. if (!size) {
  56. struct MFC_CONTEXT *ctxt = (struct MFC_CONTEXT *)mfc_handle;
  57. if (ctxt)
  58. size = ctxt->fb_width * ctxt->fb_height * DAL_BPP;
  59. else
  60. DDPPR_ERR("%s MFC_CONTEXT is NULL\n", __func__);
  61. }
  62. return size;
  63. }
  64. int mtk_drm_dal_setscreencolor(enum DAL_COLOR color)
  65. {
  66. u32 i, size, bg_color, offset;
  67. struct MFC_CONTEXT *ctxt;
  68. u32 *addr;
  69. color = RGB888_To_RGB565(color);
  70. bg_color = MAKE_TWO_RGB565_COLOR(color, color);
  71. ctxt = (struct MFC_CONTEXT *)mfc_handle;
  72. if (!ctxt)
  73. return -1;
  74. if (ctxt->screen_color == color)
  75. return 0;
  76. offset = MFC_Get_Cursor_Offset(mfc_handle);
  77. addr = (u32 *)(ctxt->fb_addr + offset);
  78. size = DAL_GetLayerSize();
  79. if (!size) {
  80. DDPPR_ERR("%s wrong fb size\n", __func__);
  81. return 0;
  82. }
  83. size -= offset;
  84. for (i = 0; i < size / sizeof(u32); ++i)
  85. *addr++ = bg_color;
  86. ctxt->screen_color = color;
  87. return 0;
  88. }
  89. int DAL_SetScreenColor(enum DAL_COLOR color)
  90. {
  91. uint32_t i;
  92. uint32_t size;
  93. uint32_t bg_color;
  94. struct MFC_CONTEXT *ctxt = NULL;
  95. uint32_t offset;
  96. unsigned int *addr;
  97. if (!mfc_handle)
  98. return -1;
  99. color = RGB888_To_RGB565(color);
  100. bg_color = MAKE_TWO_RGB565_COLOR(color, color);
  101. ctxt = (struct MFC_CONTEXT *)mfc_handle;
  102. if (!ctxt)
  103. return -1;
  104. if (ctxt->screen_color == color)
  105. return 0;
  106. offset = MFC_Get_Cursor_Offset(mfc_handle);
  107. addr = (unsigned int *)(ctxt->fb_addr + offset);
  108. size = DAL_GetLayerSize();
  109. if (!size) {
  110. DDPPR_ERR("%s wrong fb size\n", __func__);
  111. return 0;
  112. }
  113. size -= offset;
  114. for (i = 0; i < size / sizeof(uint32_t); ++i)
  115. *addr++ = bg_color;
  116. ctxt->screen_color = color;
  117. return 0;
  118. }
  119. EXPORT_SYMBOL(DAL_SetScreenColor);
  120. int DAL_SetColor(unsigned int fgColor, unsigned int bgColor)
  121. {
  122. if (!mfc_handle)
  123. return -1;
  124. DAL_LOCK();
  125. MFC_SetColor(mfc_handle, RGB888_To_RGB565(fgColor),
  126. RGB888_To_RGB565(bgColor));
  127. DAL_UNLOCK();
  128. return 0;
  129. }
  130. EXPORT_SYMBOL(DAL_SetColor);
  131. static struct mtk_ddp_comp *_handle_phy_top_plane(struct mtk_drm_crtc *mtk_crtc)
  132. {
  133. int i, j, type;
  134. int lay_num;
  135. struct drm_plane *plane;
  136. struct mtk_plane_state *plane_state;
  137. struct mtk_plane_comp_state comp_state;
  138. struct mtk_ddp_comp *ovl_comp = NULL;
  139. struct mtk_ddp_comp *comp;
  140. for_each_comp_in_cur_crtc_path(comp, mtk_crtc, i, j) {
  141. type = mtk_ddp_comp_get_type(comp->id);
  142. if (type == MTK_DISP_OVL)
  143. ovl_comp = comp;
  144. else if (type == MTK_DISP_RDMA)
  145. break;
  146. }
  147. if (ovl_comp == NULL) {
  148. DDPPR_ERR("No proper ovl module in CRTC %s\n",
  149. mtk_crtc->base.name);
  150. return NULL;
  151. }
  152. lay_num = mtk_ovl_layer_num(ovl_comp);
  153. if (lay_num < 0) {
  154. DDPPR_ERR("invalid layer number:%d\n", lay_num);
  155. return NULL;
  156. }
  157. for (i = 0 ; i < mtk_crtc->layer_nr; ++i) {
  158. plane = &mtk_crtc->planes[i].base;
  159. plane_state = to_mtk_plane_state(plane->state);
  160. comp_state = plane_state->comp_state;
  161. /*find been cascaded ovl comp */
  162. if (comp_state.comp_id == ovl_comp->id &&
  163. comp_state.lye_id == lay_num - 1) {
  164. plane_state->pending.enable = false;
  165. plane_state->pending.dirty = 1;
  166. }
  167. }
  168. return ovl_comp;
  169. }
  170. static void mtk_drm_cmdq_done(struct cmdq_cb_data data)
  171. {
  172. struct cmdq_pkt *cmdq_handle = data.data;
  173. cmdq_pkt_destroy(cmdq_handle);
  174. }
  175. static struct mtk_plane_state *drm_set_dal_plane_state(struct drm_crtc *crtc,
  176. bool enable)
  177. {
  178. struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc);
  179. struct drm_plane *plane;
  180. struct mtk_plane_state *plane_state;
  181. struct mtk_plane_pending_state *pending;
  182. struct mtk_ddp_comp *ovl_comp = _handle_phy_top_plane(mtk_crtc);
  183. struct MFC_CONTEXT *ctxt = (struct MFC_CONTEXT *)mfc_handle;
  184. int layer_id = -1;
  185. if (ovl_comp)
  186. layer_id = mtk_ovl_layer_num(ovl_comp) - 1;
  187. if (!ctxt) {
  188. DDPPR_ERR("%s MFC_CONTEXT is NULL\n", __func__);
  189. return NULL;
  190. }
  191. if (layer_id < 0) {
  192. DDPPR_ERR("%s invalid layer id:%d\n", __func__, layer_id);
  193. return NULL;
  194. }
  195. plane = &mtk_crtc->planes[mtk_crtc->layer_nr - 1].base;
  196. plane_state = to_mtk_plane_state(plane->state);
  197. pending = &plane_state->pending;
  198. plane_state->pending.addr = dal_pa;
  199. plane_state->pending.pitch = ctxt->fb_width * DAL_BPP;
  200. plane_state->pending.format = DRM_FORMAT_RGB565;
  201. plane_state->pending.src_x = 0;
  202. plane_state->pending.src_y = 0;
  203. plane_state->pending.dst_x = 0;
  204. plane_state->pending.dst_y = 0;
  205. plane_state->pending.height = ctxt->fb_height;
  206. plane_state->pending.width = ctxt->fb_width;
  207. plane_state->pending.config = 1;
  208. plane_state->pending.dirty = 1;
  209. plane_state->pending.enable = !!enable;
  210. plane_state->pending.is_sec = false;
  211. pending->prop_val[PLANE_PROP_ALPHA_CON] = 0x1;
  212. pending->prop_val[PLANE_PROP_PLANE_ALPHA] = 0x80;
  213. pending->prop_val[PLANE_PROP_COMPRESS] = 0;
  214. plane_state->comp_state.comp_id = ovl_comp->id;
  215. plane_state->comp_state.lye_id = layer_id;
  216. plane_state->comp_state.ext_lye_id = 0;
  217. return plane_state;
  218. }
  219. int drm_show_dal(struct drm_crtc *crtc, bool enable)
  220. {
  221. struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc);
  222. struct mtk_plane_state *plane_state;
  223. struct mtk_ddp_comp *ovl_comp = _handle_phy_top_plane(mtk_crtc);
  224. struct cmdq_pkt *cmdq_handle;
  225. int layer_id;
  226. if (ovl_comp == NULL) {
  227. DDPPR_ERR("%s: can't find ovl comp\n", __func__);
  228. return 0;
  229. }
  230. layer_id = mtk_ovl_layer_num(ovl_comp) - 1;
  231. if (layer_id < 0) {
  232. DDPPR_ERR("%s invalid layer id:%d\n", __func__, layer_id);
  233. return 0;
  234. }
  235. DDP_MUTEX_LOCK(&mtk_crtc->lock, __func__, __LINE__);
  236. if (!mtk_crtc->enabled) {
  237. DDP_MUTEX_UNLOCK(&mtk_crtc->lock, __func__, __LINE__);
  238. return 0;
  239. }
  240. plane_state = drm_set_dal_plane_state(crtc, enable);
  241. if (!plane_state) {
  242. DDPPR_ERR("%s: can't set dal plane_state\n", __func__);
  243. DDP_MUTEX_UNLOCK(&mtk_crtc->lock, __func__, __LINE__);
  244. return 0;
  245. }
  246. mtk_drm_idlemgr_kick(__func__, crtc, 0);
  247. /* set DAL config and trigger display */
  248. cmdq_handle = mtk_crtc_gce_commit_begin(crtc);
  249. mtk_ddp_comp_layer_config(ovl_comp, layer_id, plane_state, cmdq_handle);
  250. mtk_crtc_gce_flush(crtc, mtk_drm_cmdq_done, cmdq_handle, cmdq_handle);
  251. DDP_MUTEX_UNLOCK(&mtk_crtc->lock, __func__, __LINE__);
  252. return 0;
  253. }
  254. void drm_set_dal(struct drm_crtc *crtc, struct cmdq_pkt *cmdq_handle)
  255. {
  256. struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc);
  257. struct mtk_plane_state *plane_state;
  258. struct mtk_ddp_comp *ovl_comp = _handle_phy_top_plane(mtk_crtc);
  259. int layer_id;
  260. if (ovl_comp == NULL) {
  261. DDPPR_ERR("%s: can't find ovl comp\n", __func__);
  262. return;
  263. }
  264. layer_id = mtk_ovl_layer_num(ovl_comp) - 1;
  265. if (layer_id < 0) {
  266. DDPPR_ERR("%s invalid layer id:%d\n", __func__, layer_id);
  267. return;
  268. }
  269. plane_state = drm_set_dal_plane_state(crtc, true);
  270. if (!plane_state) {
  271. DDPPR_ERR("%s: can't set dal plane_state\n", __func__);
  272. return;
  273. }
  274. mtk_ddp_comp_layer_config(ovl_comp, layer_id, plane_state, cmdq_handle);
  275. }
  276. int DAL_Clean(void)
  277. {
  278. struct MFC_CONTEXT *ctxt = (struct MFC_CONTEXT *)mfc_handle;
  279. if (!mfc_handle)
  280. return 0;
  281. DAL_LOCK();
  282. if (MFC_ResetCursor(mfc_handle) != MFC_STATUS_OK)
  283. goto end;
  284. ctxt->screen_color = 0;
  285. DAL_SetScreenColor(DAL_COLOR_RED);
  286. if (drm_dal_enable == 1) {
  287. drm_dal_enable = 0;
  288. drm_show_dal(dal_crtc, false);
  289. }
  290. end:
  291. DAL_UNLOCK();
  292. return 0;
  293. }
  294. EXPORT_SYMBOL(DAL_Clean);
  295. int DAL_Printf(const char *fmt, ...)
  296. {
  297. va_list args;
  298. u32 i;
  299. if (!mfc_handle)
  300. return -1;
  301. if (!fmt)
  302. return -1;
  303. DAL_LOCK();
  304. va_start(args, fmt);
  305. i = vsprintf(drm_dal_str_buf, fmt, args);
  306. va_end(args);
  307. if (i >= DAL_STR_BUF_LEN) {
  308. DDPPR_ERR("%s, string size %u exceed limit\n", __func__, i);
  309. return -1;
  310. }
  311. MFC_Print(mfc_handle, drm_dal_str_buf);
  312. if (drm_dal_enable == 0)
  313. drm_dal_enable = 1;
  314. drm_show_dal(dal_crtc, true);
  315. DAL_UNLOCK();
  316. return 0;
  317. }
  318. EXPORT_SYMBOL(DAL_Printf);
  319. int mtk_drm_dal_enable(void)
  320. {
  321. return drm_dal_enable;
  322. }
  323. void mtk_drm_assert_fb_init(struct drm_device *dev, u32 width, u32 height)
  324. {
  325. struct mtk_drm_gem_obj *mtk_gem;
  326. u32 size = width * height * DAL_BPP;
  327. mtk_gem = mtk_drm_gem_create(dev, size, true);
  328. if (IS_ERR(mtk_gem)) {
  329. DDPINFO("alloc buffer fail\n");
  330. drm_gem_object_release(&mtk_gem->base);
  331. return;
  332. }
  333. //Avoid kmemleak to scan
  334. kmemleak_ignore(mtk_gem);
  335. dal_va = mtk_gem->kvaddr;
  336. dal_pa = mtk_gem->dma_addr;
  337. MFC_Open(&mfc_handle, mtk_gem->kvaddr, width, height, DAL_BPP,
  338. RGB888_To_RGB565(DAL_COLOR_WHITE),
  339. RGB888_To_RGB565(DAL_COLOR_RED), mtk_gem->base.filp);
  340. }
  341. int mtk_drm_assert_layer_init(struct drm_crtc *crtc)
  342. {
  343. if (!dal_pa || !dal_va) {
  344. DDPPR_ERR("init DAL without proper buffer\n");
  345. return -1;
  346. }
  347. dal_crtc = crtc;
  348. DAL_SetScreenColor(DAL_COLOR_RED);
  349. return 0;
  350. }