hpm_lvgl.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534
  1. /*
  2. * Copyright (c) 2023-2024 HPMicro
  3. * SPDX-License-Identifier: BSD-3-Clause
  4. *
  5. */
  6. #include "hpm_lvgl.h"
  7. #include <hpm_touch.h>
  8. #include <hpm_panel.h>
  9. #include <board.h>
  10. #include <hpm_soc.h>
  11. #include <hpm_csr_regs.h>
  12. #include <hpm_interrupt.h>
  13. #include <hpm_lcdc_drv.h>
  14. #include <hpm_l1c_drv.h>
  15. #include <hpm_pdma_drv.h>
  16. #include <hpm_mchtmr_drv.h>
  17. #if (LV_USE_OS != LV_OS_NONE)
  18. #include <FreeRTOS.h>
  19. #include <task.h>
  20. #include <semphr.h>
  21. #endif
  22. #ifndef LV_INV_BUF_SIZE
  23. #define LV_INV_BUF_SIZE 32 /*Buffer size for invalid areas*/
  24. #endif
  25. #define HPM_LVGL_RUNNING_CORE HPM_CORE0
  26. #define HPM_LVGL_LCDC_BASE BOARD_LCD_BASE
  27. #define HPM_LVGL_LCDC_LAYER_INDEX (0)
  28. #define HPM_LVGL_LCDC_IRQ_NUM BOARD_LCD_IRQ
  29. #define HPM_LVGL_LCDC_IRQ_PRIORITY 7
  30. #define HPM_LVGL_PIXEL_SIZE (LV_COLOR_DEPTH / 8)
  31. #define HPM_LVGL_LCD_WIDTH (BOARD_LCD_WIDTH)
  32. #define HPM_LVGL_LCD_HEIGHT (BOARD_LCD_HEIGHT)
  33. #define HPM_LVGL_FB_SIZE HPM_L1C_CACHELINE_ALIGN_UP(HPM_LVGL_LCD_WIDTH * HPM_LVGL_LCD_HEIGHT * HPM_LVGL_PIXEL_SIZE)
  34. #define HPM_LVGL_MCHTMR HPM_MCHTMR
  35. #define HPM_LVGL_MCHTMR_CLK clock_mchtmr0
  36. #if defined(LV_USE_HPM_PDMA_FLUSH) && LV_USE_HPM_PDMA_FLUSH
  37. #define HPM_LVGL_PDMA_IRQ_NUM IRQn_PDMA_D0
  38. #define HPM_LVGL_PDMA_IRQ_PRIORITY 6
  39. #define HPM_LVGL_PDMA_BASE HPM_PDMA
  40. #define LVGL_PDMA_CLOCK clock_pdma
  41. typedef void (*hpm_lvgl_pdma_finish_cb_t)(void *cb_data);
  42. typedef struct hpm_lvgl_pdma_flush_context {
  43. struct {
  44. uint32_t pixel_size;
  45. uint32_t stride;
  46. pdma_plane_config_t plane_src;
  47. pdma_output_config_t output;
  48. } cfg;
  49. void *pdma_base;
  50. uint32_t dst_addr;
  51. uint32_t src_addr;
  52. lv_area_t areas[LV_INV_BUF_SIZE];
  53. volatile uint16_t area_num;
  54. volatile uint16_t area_num_cnt;
  55. hpm_lvgl_pdma_finish_cb_t finish_cb;
  56. void *finish_cb_data;
  57. } hpm_lvgl_pdma_flush_context_t;
  58. #endif
  59. typedef struct hpm_lvgl_context {
  60. #if defined(LV_USE_HPM_PDMA_FLUSH) && LV_USE_HPM_PDMA_FLUSH
  61. hpm_lvgl_pdma_flush_context_t pdma_ctx;
  62. #endif
  63. lv_display_t *disp;
  64. lv_indev_t *indev;
  65. volatile int lcdc_vsync_flag;
  66. int lcdc_is_enable;
  67. int render_mode;
  68. #if (LV_USE_OS != LV_OS_NONE)
  69. SemaphoreHandle_t sync;
  70. #endif
  71. } hpm_lvgl_context_t;
  72. hpm_lvgl_context_t hpm_lvgl_context;
  73. #define FB_SECTION ".framebuffer"
  74. static uint8_t __attribute__((section(FB_SECTION), aligned(HPM_L1C_CACHELINE_SIZE))) hpm_lvgl_fb0[HPM_LVGL_FB_SIZE];
  75. static uint8_t __attribute__((section(FB_SECTION), aligned(HPM_L1C_CACHELINE_SIZE))) hpm_lvgl_fb1[HPM_LVGL_FB_SIZE];
  76. #if defined(LV_USE_HPM_PDMA_FLUSH) && LV_USE_HPM_PDMA_FLUSH
  77. static uint8_t __attribute__((section(FB_SECTION), aligned(HPM_L1C_CACHELINE_SIZE))) hpm_lcdc_fb[HPM_LVGL_FB_SIZE];
  78. #endif
  79. static inline uint32_t hpm_lvgl_irq_lock(void)
  80. {
  81. return disable_global_irq(CSR_MSTATUS_MIE_MASK);
  82. }
  83. static inline void hpm_lvgl_irq_unlock(uint32_t state)
  84. {
  85. restore_global_irq(state);
  86. }
  87. #if (LV_USE_OS != LV_OS_NONE)
  88. int hpm_lvgl_lcdc_vsync_init(hpm_lvgl_context_t *ctx)
  89. {
  90. ctx->sync = xSemaphoreCreateBinary();
  91. return 0;
  92. }
  93. ATTR_RAMFUNC int hpm_lvgl_lcdc_vsync_wait(hpm_lvgl_context_t *ctx)
  94. {
  95. xSemaphoreTake(ctx->sync, portMAX_DELAY);
  96. return 0;
  97. }
  98. ATTR_RAMFUNC int hpm_lvgl_lcdc_vsync_signal(hpm_lvgl_context_t *ctx)
  99. {
  100. portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
  101. xSemaphoreGiveFromISR(ctx->sync, &xHigherPriorityTaskWoken);
  102. if (xHigherPriorityTaskWoken != pdFALSE )
  103. portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
  104. return 0;
  105. }
  106. ATTR_RAMFUNC uint32_t hpm_lvgl_tick_get_cb(void)
  107. {
  108. return xTaskGetTickCount();
  109. }
  110. ATTR_RAMFUNC void hpm_lvgl_delay_cb(uint32_t ms)
  111. {
  112. vTaskDelay(ms);
  113. }
  114. void hpm_lvgl_tick_init(void)
  115. {
  116. lv_tick_set_cb(hpm_lvgl_tick_get_cb);
  117. lv_delay_set_cb(hpm_lvgl_delay_cb);
  118. }
  119. #else
  120. int hpm_lvgl_lcdc_vsync_wait(hpm_lvgl_context_t *ctx)
  121. {
  122. (void) ctx;
  123. return 0;
  124. }
  125. ATTR_RAMFUNC int hpm_lvgl_lcdc_vsync_signal(hpm_lvgl_context_t *ctx)
  126. {
  127. (void) ctx;
  128. return 0;
  129. }
  130. ATTR_RAMFUNC int hpm_lvgl_lcdc_vsync_init(hpm_lvgl_context_t *ctx)
  131. {
  132. (void) ctx;
  133. return 0;
  134. }
  135. ATTR_RAMFUNC uint32_t hpm_lvgl_tick_get_cb(void)
  136. {
  137. static uint32_t mchtmr_freq_in_khz = 0;
  138. if (!mchtmr_freq_in_khz) {
  139. clock_add_to_group(HPM_LVGL_MCHTMR_CLK, 0);
  140. mchtmr_freq_in_khz = clock_get_frequency(HPM_LVGL_MCHTMR_CLK) / 1000;
  141. }
  142. return mchtmr_get_count(HPM_LVGL_MCHTMR) / mchtmr_freq_in_khz;
  143. }
  144. void hpm_lvgl_tick_init(void)
  145. {
  146. lv_tick_set_cb(hpm_lvgl_tick_get_cb);
  147. }
  148. #endif /* LV_USE_OS != LV_OS_NONE */
  149. #if defined(LV_USE_HPM_PDMA_FLUSH) && LV_USE_HPM_PDMA_FLUSH
  150. static void hpm_lvgl_pdma_init(hpm_lvgl_pdma_flush_context_t *ctx, void *pdma_base, uint32_t pixel_size)
  151. {
  152. pdma_config_t config;
  153. display_pixel_format_t pixel_format;
  154. pdma_plane_config_t *plane_src_cfg = &ctx->cfg.plane_src;
  155. pdma_output_config_t *output_cfg = &ctx->cfg.output;
  156. PDMA_Type *pdma_ptr = (PDMA_Type *)pdma_base;
  157. ctx->pdma_base = pdma_base;
  158. ctx->cfg.pixel_size = pixel_size;
  159. clock_add_to_group(LVGL_PDMA_CLOCK, HPM_LVGL_RUNNING_CORE);
  160. pixel_format = (pixel_size == 4) ? display_pixel_format_argb8888 : display_pixel_format_rgb565;
  161. pdma_get_default_config(pdma_ptr, &config, pixel_format);
  162. config.enable_plane = pdma_plane_src;
  163. config.block_size = pdma_blocksize_16x16;
  164. pdma_init(pdma_ptr, &config);
  165. pdma_get_default_plane_config(pdma_ptr, plane_src_cfg, pixel_format);
  166. pdma_get_default_output_config(pdma_ptr, output_cfg, pixel_format);
  167. intc_m_enable_irq_with_priority(HPM_LVGL_PDMA_IRQ_NUM, HPM_LVGL_PDMA_IRQ_PRIORITY);
  168. }
  169. ATTR_RAMFUNC static int hpm_lvgl_pdma_copy_start(hpm_lvgl_pdma_flush_context_t *ctx, uint32_t dst, uint32_t src)
  170. {
  171. PDMA_Type *pdma_ptr;
  172. lv_area_t *area;
  173. pdma_plane_config_t *plane_src_cfg;
  174. pdma_output_config_t *output_cfg;
  175. if (ctx->area_num < 1)
  176. return -1;
  177. ctx->area_num_cnt = 0;
  178. ctx->dst_addr = dst;
  179. ctx->src_addr = src;
  180. pdma_ptr = (PDMA_Type *)ctx->pdma_base;
  181. area = &ctx->areas[ctx->area_num_cnt];
  182. plane_src_cfg = &ctx->cfg.plane_src;
  183. output_cfg = &ctx->cfg.output;
  184. pdma_stop(pdma_ptr);
  185. plane_src_cfg->buffer = (uint32_t)src + (area->y1 * ctx->cfg.stride + area->x1 * ctx->cfg.pixel_size);
  186. plane_src_cfg->width = lv_area_get_width(area);
  187. plane_src_cfg->height = lv_area_get_height(area);
  188. plane_src_cfg->pitch = ctx->cfg.stride;
  189. plane_src_cfg->background = 0x0;
  190. pdma_config_planes(pdma_ptr, plane_src_cfg, NULL, NULL);
  191. output_cfg->plane[pdma_plane_src].x = 0;
  192. output_cfg->plane[pdma_plane_src].y = 0;
  193. output_cfg->plane[pdma_plane_src].width = plane_src_cfg->width;
  194. output_cfg->plane[pdma_plane_src].height = plane_src_cfg->height;
  195. output_cfg->alphablend.src_alpha = 0xFF;
  196. output_cfg->alphablend.src_alpha_op = display_alpha_op_override;
  197. output_cfg->alphablend.mode = display_alphablend_mode_clear;
  198. output_cfg->width = plane_src_cfg->width;
  199. output_cfg->height = plane_src_cfg->height;
  200. output_cfg->buffer = (uint32_t)dst + (area->y1 * ctx->cfg.stride + area->x1 * ctx->cfg.pixel_size);
  201. output_cfg->pitch = ctx->cfg.stride;
  202. pdma_config_output(pdma_ptr, output_cfg);
  203. pdma_start(pdma_ptr);
  204. pdma_enable_irq(pdma_ptr, PDMA_CTRL_PDMA_DONE_IRQ_EN_MASK, true);
  205. return 0;
  206. }
  207. ATTR_RAMFUNC static void hpm_lvgl_pdma_copy_done(hpm_lvgl_pdma_flush_context_t *ctx)
  208. {
  209. PDMA_Type *pdma_ptr;
  210. lv_area_t *area;;
  211. pdma_plane_config_t *plane_src_cfg;
  212. pdma_output_config_t *output_cfg;
  213. uint32_t dst, src;
  214. if (ctx->area_num < 1)
  215. return;
  216. ctx->area_num_cnt++;
  217. if (ctx->area_num == ctx->area_num_cnt) {
  218. ctx->area_num = 0;
  219. if (ctx->finish_cb)
  220. ctx->finish_cb(ctx->finish_cb_data);
  221. return;
  222. }
  223. dst = ctx->dst_addr;
  224. src = ctx->src_addr;
  225. pdma_ptr = (PDMA_Type *)ctx->pdma_base;
  226. area = &ctx->areas[ctx->area_num_cnt];
  227. plane_src_cfg = &ctx->cfg.plane_src;
  228. output_cfg = &ctx->cfg.output;
  229. plane_src_cfg->buffer = (uint32_t)src + (area->y1 * ctx->cfg.stride + area->x1 * ctx->cfg.pixel_size);
  230. plane_src_cfg->width = lv_area_get_width(area);
  231. plane_src_cfg->height = lv_area_get_height(area);
  232. plane_src_cfg->pitch = ctx->cfg.stride;
  233. plane_src_cfg->background = 0xFFFFFFFF;
  234. pdma_config_planes(pdma_ptr, plane_src_cfg, NULL, NULL);
  235. output_cfg->plane[pdma_plane_src].x = 0;
  236. output_cfg->plane[pdma_plane_src].y = 0;
  237. output_cfg->plane[pdma_plane_src].width = plane_src_cfg->width;
  238. output_cfg->plane[pdma_plane_src].height = plane_src_cfg->height;
  239. output_cfg->alphablend.src_alpha = 0xFF;
  240. output_cfg->alphablend.src_alpha_op = display_alpha_op_override;
  241. output_cfg->alphablend.mode = display_alphablend_mode_clear;
  242. output_cfg->width = plane_src_cfg->width;
  243. output_cfg->height = plane_src_cfg->height;
  244. output_cfg->buffer = (uint32_t)dst + (area->y1 * ctx->cfg.stride + area->x1 * ctx->cfg.pixel_size);
  245. output_cfg->pitch = ctx->cfg.stride;
  246. pdma_config_output(pdma_ptr, output_cfg);
  247. pdma_start(pdma_ptr);
  248. pdma_enable_irq(pdma_ptr, PDMA_CTRL_PDMA_DONE_IRQ_EN_MASK, true);
  249. }
  250. ATTR_RAMFUNC static void hpm_lvgl_pdma_copy_register_finish_cb(hpm_lvgl_pdma_flush_context_t *ctx, hpm_lvgl_pdma_finish_cb_t cb, void *cb_data)
  251. {
  252. ctx->finish_cb = cb;
  253. ctx->finish_cb_data = cb_data;
  254. }
  255. ATTR_RAMFUNC static int hpm_lvgl_pdma_add_area(hpm_lvgl_pdma_flush_context_t *ctx, const lv_area_t *area)
  256. {
  257. lv_area_copy(&ctx->areas[ctx->area_num], area);
  258. ctx->area_num++;
  259. return 0;
  260. }
  261. SDK_DECLARE_EXT_ISR_M(HPM_LVGL_PDMA_IRQ_NUM, hpm_lvgl_pdma_isr)
  262. void hpm_lvgl_pdma_isr(void)
  263. {
  264. PDMA_Type *pdma_ptr;
  265. hpm_lvgl_pdma_flush_context_t *ctx;
  266. ctx = &hpm_lvgl_context.pdma_ctx;
  267. pdma_ptr = (PDMA_Type *)ctx->pdma_base;
  268. pdma_ptr->STAT = PDMA_STAT_PDMA_DONE_MASK;
  269. pdma_stop(pdma_ptr);
  270. pdma_enable_irq(pdma_ptr, PDMA_CTRL_PDMA_DONE_IRQ_EN_MASK, false);
  271. hpm_lvgl_pdma_copy_done(ctx);
  272. }
  273. #endif /* defined(LV_USE_HPM_PDMA_FLUSH) && LV_USE_HPM_PDMA_FLUSH */
  274. ATTR_RAMFUNC void hpm_lvgl_lcdc_vsync_flag_set(hpm_lvgl_context_t *ctx, int val)
  275. {
  276. uint32_t state;
  277. state = hpm_lvgl_irq_lock();
  278. ctx->lcdc_vsync_flag = val;
  279. hpm_lvgl_irq_unlock(state);
  280. }
  281. ATTR_RAMFUNC int hpm_lvgl_lcdc_vsync_flag_get(hpm_lvgl_context_t *ctx)
  282. {
  283. return ctx->lcdc_vsync_flag;
  284. }
  285. void hpm_lvgl_wait_lcdc_vsync(hpm_lvgl_context_t *ctx)
  286. {
  287. hpm_lvgl_lcdc_vsync_flag_set(ctx, 0);
  288. while (!hpm_lvgl_lcdc_vsync_flag_get(ctx))
  289. hpm_lvgl_lcdc_vsync_wait(ctx);
  290. }
  291. SDK_DECLARE_EXT_ISR_M(HPM_LVGL_LCDC_IRQ_NUM, hpm_lvgl_lcdc_vsync_isr)
  292. void hpm_lvgl_lcdc_vsync_isr(void)
  293. {
  294. hpm_lvgl_context_t *ctx = &hpm_lvgl_context;
  295. lcdc_clear_status(HPM_LVGL_LCDC_BASE, LCDC_ST_VS_BLANK_MASK);
  296. hpm_lvgl_lcdc_vsync_flag_set(ctx, 1);
  297. hpm_lvgl_lcdc_vsync_signal(ctx);
  298. }
  299. static void hpm_lvgl_lcdc_enable(uint32_t fb_buffer)
  300. {
  301. display_pixel_format_t pixel_format;
  302. lcdc_config_t config = {0};
  303. lcdc_layer_config_t layer;
  304. lcdc_get_default_config(HPM_LVGL_LCDC_BASE, &config);
  305. board_panel_para_to_lcdc(&config);
  306. #if LV_COLOR_DEPTH == 32
  307. pixel_format = display_pixel_format_argb8888;
  308. #elif LV_COLOR_DEPTH == 16
  309. pixel_format = display_pixel_format_rgb565;
  310. #else
  311. #error only support 16 or 32 color depth
  312. #endif
  313. lcdc_init(HPM_LVGL_LCDC_BASE, &config);
  314. lcdc_get_default_layer_config(HPM_LVGL_LCDC_BASE, &layer, pixel_format, HPM_LVGL_LCDC_LAYER_INDEX);
  315. layer.position_x = 0;
  316. layer.position_y = 0;
  317. layer.width = HPM_LVGL_LCD_WIDTH;
  318. layer.height = HPM_LVGL_LCD_HEIGHT;
  319. layer.buffer = fb_buffer;
  320. layer.background.u = 0;
  321. layer.max_bytes = lcdc_layer_max_bytes_512;
  322. if (status_success != lcdc_config_layer(HPM_LVGL_LCDC_BASE, HPM_LVGL_LCDC_LAYER_INDEX, &layer, true)) {
  323. printf("failed to configure layer\n");
  324. while (1) {
  325. }
  326. }
  327. lcdc_turn_on_display(HPM_LVGL_LCDC_BASE);
  328. lcdc_enable_interrupt(HPM_LVGL_LCDC_BASE, LCDC_INT_EN_VS_BLANK_MASK);
  329. intc_m_enable_irq_with_priority(HPM_LVGL_LCDC_IRQ_NUM, HPM_LVGL_LCDC_IRQ_PRIORITY);
  330. }
  331. void hpm_lvgl_display_flush_cb(lv_display_t *disp, const lv_area_t *area, uint8_t *px_map)
  332. {
  333. hpm_lvgl_context_t *ctx = (hpm_lvgl_context_t *)lv_display_get_user_data(disp);
  334. #if defined(LV_USE_HPM_PDMA_FLUSH) && LV_USE_HPM_PDMA_FLUSH
  335. hpm_lvgl_pdma_add_area(&ctx->pdma_ctx, area);
  336. #endif
  337. if (ctx->render_mode == LV_DISPLAY_RENDER_MODE_DIRECT && lv_display_flush_is_last(disp) == 0) {
  338. lv_display_flush_ready(disp);
  339. return;
  340. }
  341. if (l1c_dc_is_enabled()) {
  342. l1c_dc_writeback((uint32_t)px_map, HPM_LVGL_FB_SIZE);
  343. }
  344. #if defined(LV_USE_HPM_PDMA_FLUSH) && LV_USE_HPM_PDMA_FLUSH
  345. #if defined(LV_USE_HPM_PDMA_WAIT_VSYNC) && LV_USE_HPM_PDMA_WAIT_VSYNC
  346. hpm_lvgl_wait_lcdc_vsync(ctx);
  347. #endif
  348. hpm_lvgl_pdma_copy_start(&ctx->pdma_ctx, (uint32_t)hpm_lcdc_fb, (uint32_t)px_map);
  349. #else
  350. do {
  351. lcdc_layer_set_next_buffer(HPM_LVGL_LCDC_BASE, HPM_LVGL_LCDC_LAYER_INDEX, (uint32_t)px_map);
  352. hpm_lvgl_wait_lcdc_vsync(ctx);
  353. } while (!lcdc_layer_control_shadow_loaded(HPM_LVGL_LCDC_BASE, HPM_LVGL_LCDC_LAYER_INDEX));
  354. lv_display_flush_ready(disp);
  355. #endif
  356. }
  357. #if defined(LV_USE_HPM_PDMA_FLUSH) && LV_USE_HPM_PDMA_FLUSH
  358. ATTR_RAMFUNC void hpm_lvgl_pdma_finish_callback(void *cb_data)
  359. {
  360. hpm_lvgl_context_t *ctx = (hpm_lvgl_context_t *)cb_data;
  361. lv_display_flush_ready(ctx->disp);
  362. }
  363. #endif
  364. void hpm_lvgl_display_init(void)
  365. {
  366. lv_display_render_mode_t render_mode;
  367. lv_display_t *disp;
  368. uint32_t lcdc_fb_buffer;
  369. hpm_lvgl_context_t *ctx = &hpm_lvgl_context;
  370. #if defined(LV_USE_HPM_MODE_DIRECT) && LV_USE_HPM_MODE_DIRECT
  371. render_mode = LV_DISPLAY_RENDER_MODE_DIRECT;
  372. #else
  373. render_mode = LV_DISPLAY_RENDER_MODE_FULL;
  374. #endif
  375. lcdc_fb_buffer = (uint32_t)hpm_lvgl_fb1;
  376. disp = lv_display_create(HPM_LVGL_LCD_WIDTH, HPM_LVGL_LCD_HEIGHT);
  377. lv_display_set_buffers(disp, hpm_lvgl_fb0, hpm_lvgl_fb1, HPM_LVGL_FB_SIZE, render_mode);
  378. lv_display_set_flush_cb(disp, hpm_lvgl_display_flush_cb);
  379. lv_display_set_user_data(disp, ctx);
  380. ctx->render_mode = render_mode;
  381. ctx->disp = disp;
  382. #if defined(LV_USE_HPM_PDMA_FLUSH) && LV_USE_HPM_PDMA_FLUSH
  383. lv_color_format_t cf = lv_display_get_color_format(disp);
  384. uint32_t stride = lv_draw_buf_width_to_stride(HPM_LVGL_LCD_WIDTH, cf);
  385. ctx->pdma_ctx.cfg.stride = stride;
  386. lcdc_fb_buffer = (uint32_t)hpm_lcdc_fb;
  387. hpm_lvgl_pdma_init(&ctx->pdma_ctx, HPM_LVGL_PDMA_BASE, LV_COLOR_DEPTH / 8);
  388. hpm_lvgl_pdma_copy_register_finish_cb(&ctx->pdma_ctx, hpm_lvgl_pdma_finish_callback, ctx);
  389. #endif
  390. memset((void *)lcdc_fb_buffer, 0x00, HPM_LVGL_FB_SIZE);
  391. hpm_lvgl_lcdc_vsync_init(ctx);
  392. hpm_lvgl_lcdc_enable(lcdc_fb_buffer);
  393. }
  394. static hpm_stat_t hpm_lvgl_touchpad_init(void)
  395. {
  396. hpm_stat_t stat;
  397. hpm_panel_t *panel;
  398. const char *name;
  399. panel = hpm_panel_find_device_default();
  400. name = hpm_panel_get_name(panel);
  401. if (!strcmp(name, "mc10128007_31b")) {
  402. touch_config(1, 0, 1);
  403. }
  404. stat = touch_init(BOARD_CAP_I2C_BASE);
  405. if (stat != status_success) {
  406. printf("Warning: touch init failed\n");
  407. }
  408. return stat;
  409. }
  410. static void hpm_lvgl_indev_read_cb(lv_indev_t *indev, lv_indev_data_t *data)
  411. {
  412. hpm_stat_t stat;
  413. touch_point_t touch_points[HPM_TOUCH_MAX_POINTS];
  414. uint8_t num_of_points;
  415. static lv_indev_data_t pre_data;
  416. stat = touch_get_data(touch_points, &num_of_points);
  417. if (stat == status_success) {
  418. if ((num_of_points < HPM_TOUCH_MAX_POINTS) && num_of_points) {
  419. pre_data.state = LV_INDEV_STATE_PRESSED;
  420. pre_data.point.x = touch_points[0].x;
  421. pre_data.point.y = touch_points[0].y;
  422. }
  423. } else if (stat == status_touch_points_over_number) {
  424. pre_data.state = LV_INDEV_STATE_RELEASED;
  425. }
  426. data->state = pre_data.state;
  427. data->point.x = pre_data.point.x;
  428. data->point.y = pre_data.point.y;
  429. }
  430. void hpm_lvgl_indev_init(void)
  431. {
  432. lv_indev_t *indev;
  433. if (hpm_lvgl_touchpad_init() == status_success) {
  434. indev = lv_indev_create();
  435. lv_indev_set_type(indev, LV_INDEV_TYPE_POINTER);
  436. lv_indev_set_read_cb(indev, hpm_lvgl_indev_read_cb);
  437. lv_indev_set_user_data(indev, &hpm_lvgl_context);
  438. hpm_lvgl_context.indev = indev;
  439. }
  440. }
  441. void hpm_lvgl_init(void)
  442. {
  443. lv_init();
  444. hpm_lvgl_tick_init();
  445. hpm_lvgl_display_init();
  446. hpm_lvgl_indev_init();
  447. }