de_lark.c 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320
  1. /*
  2. * Copyright (c) 2020 Actions Technology Co., Ltd
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. #include <soc.h>
  7. #include <spicache.h>
  8. #include <drivers/display.h>
  9. #include <drivers/display/display_controller.h>
  10. #include <drivers/display/display_engine.h>
  11. #include <assert.h>
  12. #include <string.h>
  13. #include <sys/byteorder.h>
  14. #include <tracing/tracing.h>
  15. #include "../de_common.h"
  16. #include "../de_device.h"
  17. #include "de_lark.h"
  18. /* TODO: unstable feature */
  19. #define CONFIG_DE_USE_POST_PRECONFIG 0
  20. #define DEV_DBG(...)
  21. #define DEV_ERR(...) printk("[DE][E]: " __VA_ARGS__);
  22. #define MAX_NUM_OVERLAYS 2
  23. #define MIN_WB_WIDTH 3
  24. #define MIN_DEV_WIDTH 2
  25. #define SUPPORTED_OUTPUT_PIXEL_FORMATS \
  26. (PIXEL_FORMAT_ARGB_8888 | PIXEL_FORMAT_BGR_565 | PIXEL_FORMAT_RGB_888)
  27. #define SUPPORTED_INPUT_PIXEL_FORMATS \
  28. (SUPPORTED_OUTPUT_PIXEL_FORMATS | PIXEL_FORMAT_BGR_888 |PIXEL_FORMAT_BGRA_6666 | \
  29. PIXEL_FORMAT_RGBA_6666 | PIXEL_FORMAT_RGB_565 | PIXEL_FORMAT_BGR_565 | \
  30. PIXEL_FORMAT_A8 | PIXEL_FORMAT_A4_LE | PIXEL_FORMAT_A1_LE)
  31. #define SUPPORTED_ROTATE_PIXEL_FORMATS (PIXEL_FORMAT_ARGB_8888 | PIXEL_FORMAT_BGR_565)
  32. #define GUESS_PITCH(buffer, bits_per_pixel) \
  33. ((buffer)->desc.pitch > 0 ? (buffer)->desc.pitch : ((buffer)->desc.width * (bits_per_pixel) / 8))
  34. #define GUESS_PITCH_BYTES(buffer, bytes_per_pixel) \
  35. ((buffer)->desc.pitch > 0 ? (buffer)->desc.pitch : ((buffer)->desc.width * (bytes_per_pixel)))
  36. #define DE ((DE_Type *)DE_REG_BASE)
  37. #define DE_INVALID_ADDR 0x02000000
  38. #define A1_FONT_STRIDE(size) ROUND_UP(size, 8)
  39. #define A4_FONT_STRIDE(size) ROUND_UP(size, 2)
  40. #define A8_FONT_STRIDE(size) (size)
  41. #define IS_WB_REQUIRE_WORD_ALIGN(addr) ((uint32_t)(addr) >= 0x0102C000)
  42. #ifdef CONFIG_DISPLAY_ENGINE_GAMMA_LUT
  43. static int de_config_gamma(const uint8_t *gamma_lut, int len);
  44. static const uint8_t dts_gamma_lut[] = CONFIG_DISPLAY_ENGINE_GAMMA_LUT;
  45. #endif
  46. static bool s_last_ovl_is_wb = false;
  47. __de_func static void de_clk_set_en(bool en)
  48. {
  49. static int8_t clken_count;
  50. unsigned int key = irq_lock();
  51. if (en) {
  52. if (clken_count++ == 0)
  53. acts_clock_peripheral_enable(CLOCK_ID_DE);
  54. } else {
  55. if (--clken_count == 0)
  56. acts_clock_peripheral_disable(CLOCK_ID_DE);
  57. }
  58. DEV_DBG("de: clk en %d, cnt %d\n", en, clken_count);
  59. irq_unlock(key);
  60. }
  61. static void de_reset(struct de_data *data)
  62. {
  63. acts_reset_peripheral_assert(RESET_ID_DE);
  64. de_clk_set_en(true);
  65. acts_reset_peripheral_deassert(RESET_ID_DE);
  66. #ifdef CONFIG_DISPLAY_ENGINE_GAMMA_LUT
  67. de_config_gamma(dts_gamma_lut, ARRAY_SIZE(dts_gamma_lut));
  68. #endif
  69. DE->MEM_OPT = (DE->MEM_OPT & ~(DE_MEM_BURST_LEN_MASK | DE_SW_FRAME_RST_MASK)) |
  70. (DE_MEM_BURST_32 | DE_SW_FRAME_RST_LEN(2));
  71. DE->IRQ_CTL = data->display_sync_en ?
  72. DE_IRQ_WB_FTC | DE_IRQ_DEV_FTC | DE_IRQ_DEV_FIFO_HF | DE_IRQ_DEV_FIFO_UDF :
  73. DE_IRQ_WB_FTC | DE_IRQ_DEV_FTC;
  74. data->preconfiged = false;
  75. /* keep clock disabled */
  76. de_clk_set_en(false);
  77. }
  78. static int de_open(const struct device *dev, uint32_t flags)
  79. {
  80. struct de_data *data = dev->data;
  81. int inst = -EMFILE;
  82. if (data->display_sync_en && !(flags & DISPLAY_ENGINE_FLAG_POST)) {
  83. DEV_DBG("de busy in lcd-sync\n");
  84. return -1;
  85. }
  86. k_mutex_lock(&data->mutex, K_FOREVER);
  87. inst = de_alloc_instance(flags);
  88. if (inst < 0)
  89. goto out_unlock;
  90. if (data->open_count++ == 0) {
  91. de_reset(data);
  92. }
  93. out_unlock:
  94. k_mutex_unlock(&data->mutex);
  95. return inst;
  96. }
  97. static int de_close(const struct device *dev, int inst)
  98. {
  99. struct de_data *data = dev->data;
  100. int ret = -EBUSY;
  101. ret = de_instance_poll(inst, -1);
  102. if (ret < 0)
  103. return ret;
  104. k_mutex_lock(&data->mutex, K_FOREVER);
  105. de_free_instance(inst);
  106. k_mutex_unlock(&data->mutex);
  107. return 0;
  108. }
  109. void de_dump(void)
  110. {
  111. int i;
  112. de_clk_set_en(true);
  113. printk("de regs:\n");
  114. printk("\t ctl 0x%08x\n", DE->CTL);
  115. printk("\t gate_ctl 0x%08x\n", DE->GAT_CTL);
  116. printk("\t reg_ud 0x%08x\n", DE->REG_UD);
  117. printk("\t irq_ctl 0x%08x\n", DE->IRQ_CTL);
  118. printk("\t bg_size 0x%08x\n", DE->BG_SIZE);
  119. printk("\t bg_color 0x%08x\n", DE->BG_COLOR);
  120. printk("\t mem_opt 0x%08x\n", DE->MEM_OPT);
  121. printk("\t en 0x%08x\n", DE->EN);
  122. printk("\t ctl2 0x%08x\n", DE->CTL2);
  123. for (i = 0; i < ARRAY_SIZE(DE->LAYER_CTL); i++) {
  124. printk("\t l%d_pos 0x%08x\n", i, DE->LAYER_CTL[i].POS);
  125. printk("\t l%d_size 0x%08x\n", i, DE->LAYER_CTL[i].SIZE);
  126. printk("\t l%d_addr 0x%08x\n", i, DE->LAYER_CTL[i].ADDR);
  127. printk("\t l%d_stride 0x%08x\n", i, DE->LAYER_CTL[i].STRIDE);
  128. printk("\t l%d_length 0x%08x\n", i, DE->LAYER_CTL[i].LENGTH);
  129. printk("\t l%d_color_gain 0x%08x\n", i, DE->LAYER_CTL[i].COLOR_GAIN);
  130. printk("\t l%d_color_offset 0x%08x\n", i, DE->LAYER_CTL[i].COLOR_OFFSET);
  131. printk("\t l%d_def_color 0x%08x\n", i, DE->LAYER_CTL[i].DEF_COLOR);
  132. }
  133. printk("\t alpha_ctl 0x%08x\n", DE->ALPHA_CTL);
  134. printk("\t alpha_pos 0x%08x\n", DE->ALPHA_POS);
  135. printk("\t alpha_size 0x%08x\n", DE->ALPHA_SIZE);
  136. printk("\t sta 0x%08x\n", DE->STA);
  137. printk("\t gamma_ctl 0x%08x\n", DE->GAMMA_CTL);
  138. printk("\t dither_ctl 0x%08x\n", DE->DITHER_CTL);
  139. printk("\t wb_addr 0x%08x\n", DE->WB_MEM_ADR);
  140. printk("\t wb_stride 0x%08x\n", DE->WB_MEM_STRIDE);
  141. printk("\t color_fill_pos 0x%08x\n", DE->COLOR_FILL_POS);
  142. printk("\t color_fill_size 0x%08x\n", DE->COLOR_FILL_SIZE);
  143. printk("\t fill_color 0x%08x\n", DE->FILL_COLOR);
  144. printk("\t a148_color 0x%08x\n", DE->A148_COLOR);
  145. printk("\t a14_ctl 0x%08x\n", DE->A14_CTL);
  146. #if 0
  147. printk("\t rt_ctl 0x%08x\n", DE->RT_CTL);
  148. printk("\t rt_img_size 0x%08x\n", DE->RT_IMG_SIZE);
  149. printk("\t rt_src_addr 0x%08x\n", DE->RT_SRC_ADDR);
  150. printk("\t rt_src_stride 0x%08x\n", DE->RT_SRC_STRIDE);
  151. printk("\t rt_dst_addr 0x%08x\n", DE->RT_DST_ADDR);
  152. printk("\t rt_dst_stride 0x%08x\n", DE->RT_DST_STRIDE);
  153. printk("\t rt_start_height 0x%08x\n", DE->RT_START_HEIGHT);
  154. printk("\t rt_sw_x_xy 0x%08x\n", DE->RT_SW_X_XY);
  155. printk("\t rt_sw_y_xy 0x%08x\n", DE->RT_SW_Y_XY);
  156. printk("\t rt_sw_x0 0x%08x\n", DE->RT_SW_X0);
  157. printk("\t rt_sw_y0 0x%08x\n", DE->RT_SW_Y0);
  158. printk("\t rt_sw_first_dist 0x%08x\n", DE->RT_SW_FIRST_DIST);
  159. printk("\t rt_r1m2 0x%08x\n", DE->RT_R1M2);
  160. printk("\t rt_r0m2 0x%08x\n", DE->RT_R0M2);
  161. printk("\t rt_fill_color 0x%08x\n", DE->RT_FILL_COLOR);
  162. printk("\t rt_result_x0 0x%08x\n", DE->RT_RESULT_X0);
  163. printk("\t rt_result_y0 0x%08x\n", DE->RT_RESULT_Y0);
  164. printk("\t rt_result_first_dist 0x%08x\n", DE->RT_RESULT_FIRST_DIST);
  165. printk("\t rt_result_src_addr 0x%08x\n", DE->RT_RESULT_SRC_ADDR);
  166. #endif
  167. de_clk_set_en(false);
  168. }
  169. #ifdef CONFIG_DISPLAY_ENGINE_GAMMA_LUT
  170. /* gamma correction look-up table: First R0-255, then G0-255, last B0-255 */
  171. static int de_config_gamma(const uint8_t *gamma_lut, int len)
  172. {
  173. int i;
  174. if (len != 0x300) { /* 256 * 3 */
  175. return -EINVAL;
  176. }
  177. DE->GAT_CTL |= DE_GAMMA_AHB_GATING_EN;
  178. for (i = 0; i < len; i += 4) {
  179. DE->GAMMA_CTL = DE_GAMMA_RAM_INDEX(i / 4);
  180. DE->PATH_GAMMA_RAM = sys_get_le32(&gamma_lut[i]);
  181. }
  182. DE->GAT_CTL &= ~DE_GAMMA_AHB_GATING_EN;
  183. return 0;
  184. }
  185. #endif /* CONFIG_DISPLAY_ENGINE_GAMMA_LUT */
  186. __de_func static int de_config_layer(int layer_idx, display_layer_t *ovl)
  187. {
  188. static const uint32_t ly_argb_8888[] = { DE_CTL_L0_FORMAT_ARGB8888, DE_CTL_L1_FORMAT_ARGB8888 };
  189. static const uint32_t ly_rgb_565[] = { DE_CTL_L0_FORMAT_RGB565, DE_CTL_L1_FORMAT_RGB565 };
  190. static const uint32_t ly_rgb_565_le[] = { DE_CTL_L0_FORMAT_RGB565_SWAP, DE_CTL_L1_FORMAT_RGB565_SWAP };
  191. static const uint32_t ly_argb_6666[] = { DE_CTL_L0_FORMAT_ARGB6666, DE_CTL_L1_FORMAT_ARGB6666 };
  192. static const uint32_t ly_abgr_6666[] = { DE_CTL_L0_FORMAT_ABGR6666, DE_CTL_L1_FORMAT_ABGR6666 };
  193. static const uint32_t ly_rgb_888[] = { DE_CTL_L0_FORMAT_RGB888, DE_CTL_L1_FORMAT_RGB888 };
  194. static const uint32_t ly_bgr_888[] = { DE_CTL_L0_FORMAT_BGR888, DE_CTL_L1_FORMAT_BGR888 };
  195. static const uint32_t ly_ax[] = { DE_CTL_L0_FORMAT_AX, DE_CTL_L1_FORMAT_AX };
  196. const display_buffer_t *buffer = ovl->buffer;
  197. uint32_t format, addr;
  198. uint16_t bytes_per_line;
  199. uint8_t no_stride_en, halfword_en, bpp;
  200. if (buffer == NULL) {
  201. DE->LAYER_CTL[layer_idx].DEF_COLOR = ovl->color.full;
  202. /* HW Bug:
  203. * de still reads the memory though not used, so just give it
  204. * an invalid address which do not cause the bus halt.
  205. */
  206. addr = DE_INVALID_ADDR;
  207. no_stride_en = 1;
  208. halfword_en = 0;
  209. format = DE_CTL_L1_FORMAT_RGB565 | DE_CTL_L1_COLOR_FILL_EN;
  210. bytes_per_line = ovl->frame.w * 2;
  211. } else {
  212. switch (buffer->desc.pixel_format) {
  213. case PIXEL_FORMAT_ARGB_8888:
  214. bpp = 32;
  215. format = ly_argb_8888[layer_idx];
  216. break;
  217. case PIXEL_FORMAT_BGR_565:
  218. bpp = 16;
  219. format = ly_rgb_565[layer_idx];
  220. break;
  221. case PIXEL_FORMAT_RGB_565:
  222. bpp = 16;
  223. format = ly_rgb_565_le[layer_idx];
  224. break;
  225. case PIXEL_FORMAT_BGRA_6666:
  226. bpp = 24;
  227. format = ly_argb_6666[layer_idx];
  228. break;
  229. case PIXEL_FORMAT_RGBA_6666:
  230. bpp = 24;
  231. format = ly_abgr_6666[layer_idx];
  232. break;
  233. case PIXEL_FORMAT_RGB_888:
  234. bpp = 24;
  235. format = ly_rgb_888[layer_idx];
  236. break;
  237. case PIXEL_FORMAT_BGR_888:
  238. bpp = 24;
  239. format = ly_bgr_888[layer_idx];
  240. break;
  241. case PIXEL_FORMAT_A8:
  242. bpp = 8;
  243. format = ly_ax[layer_idx];
  244. DE->A148_COLOR = DE_TYPE_A8 | (ovl->color.full & 0xffffff);
  245. break;
  246. case PIXEL_FORMAT_A4_LE:
  247. bpp = 4;
  248. format = ly_ax[layer_idx];
  249. DE->A148_COLOR = DE_TYPE_A4 | (ovl->color.full & 0xffffff);
  250. DE->A14_CTL = DE_A14_FONT(2, 2, ovl->frame.w);
  251. break;
  252. case PIXEL_FORMAT_A1_LE:
  253. bpp = 1;
  254. format = ly_ax[layer_idx];
  255. DE->A148_COLOR = DE_TYPE_A1 | (ovl->color.full & 0xffffff);
  256. DE->A14_CTL = DE_A14_FONT(8, 8, ovl->frame.w);
  257. break;
  258. default:
  259. DEV_ERR("unsupported format %d\n", buffer->desc.pixel_format);
  260. return -EINVAL;
  261. }
  262. addr = buffer->addr;
  263. bytes_per_line = buffer->desc.pitch;
  264. halfword_en = (addr & 0x3) ? 1 : 0;
  265. no_stride_en = !halfword_en && (buffer->desc.pitch == ovl->frame.w * bpp / 8);
  266. /* Keep default value.
  267. *
  268. * DE->LAYER_CTL[layer_idx].COLOR_GAIN = DE_L_COLOR_GAIN(0x80, 0x80, 0x80);
  269. * DE->LAYER_CTL[layer_idx].COLOR_OFFSET = DE_L_COLOR_GAIN(0, 0, 0);
  270. */
  271. }
  272. if (layer_idx == 0) {
  273. DE->CTL |= DE_CTL_L0_EN | format | DE_CTL_L0_NO_STRIDE_EN(no_stride_en) | DE_CTL_L0_HALFWORD_EN(halfword_en);
  274. } else {
  275. DE->CTL |= DE_CTL_L1_EN | format | DE_CTL_L1_NO_STRIDE_EN(no_stride_en) | DE_CTL_L1_HALFWORD_EN(halfword_en);
  276. }
  277. DE->LAYER_CTL[layer_idx].ADDR = addr & ~0x3;
  278. DE->LAYER_CTL[layer_idx].POS = DE_L_POS(ovl->frame.x, ovl->frame.y);
  279. DE->LAYER_CTL[layer_idx].SIZE = DE_L_SIZE(ovl->frame.w, ovl->frame.h);
  280. DE->LAYER_CTL[layer_idx].STRIDE = bytes_per_line; /* only used by stride mode */
  281. DE->LAYER_CTL[layer_idx].LENGTH = bytes_per_line * ovl->frame.h; /* only used by no-stride mode */
  282. return 0;
  283. }
  284. __de_func static int de_apply_overlay_cfg(struct de_data *data, struct de_command_entry *entry, bool preconfig)
  285. {
  286. de_overlay_cfg_t *cfg = (de_overlay_cfg_t *)entry->cfg;
  287. display_buffer_t *target = &cfg->target;
  288. display_layer_t *ovls = cfg->ovls;
  289. int top_idx = cfg->num_ovls - 1;
  290. uint32_t target_format;
  291. uint16_t target_length_per_line;
  292. uint8_t target_bytes_per_pixel;
  293. if (target->addr == 0) {
  294. if (s_last_ovl_is_wb) {
  295. s_last_ovl_is_wb = false;
  296. preconfig = false;
  297. de_reset(data);
  298. }
  299. } else {
  300. s_last_ovl_is_wb = true;
  301. }
  302. #if CONFIG_DE_USE_POST_PRECONFIG == 0
  303. preconfig = false;
  304. #endif /* CONFIG_DE_USE_POST_PRECONFIG */
  305. if (preconfig == false) {
  306. sys_trace_u32x3(SYS_TRACE_ID_DE_DRAW, entry->cmd, cfg->target_rect.w, cfg->target_rect.h);
  307. DE->GAT_CTL = DE_LAYER_GATING_EN | DE_OUTPUT_GATING_EN | DE_PATH_GATING_EN;
  308. if (target->addr == 0 && data->prepare_fn)
  309. data->prepare_fn(data->prepare_fn_arg, &cfg->target_rect);
  310. if (data->preconfiged) {
  311. DEV_DBG("preconfiged\n");
  312. goto out;
  313. }
  314. }
  315. if (target->addr > 0) {
  316. target_bytes_per_pixel = display_format_get_bits_per_pixel(target->desc.pixel_format) / 8;
  317. uint8_t no_stride_en = (target->desc.pitch == target->desc.width * target_bytes_per_pixel);
  318. #ifdef CONFIG_DISPLAY_ENGINE_GAMMA_LUT
  319. DE->GAMMA_CTL = 0;
  320. #endif
  321. DE->CTL = DE_CTL_TRANSFER_MODE_TRIGGER | DE_CTL_OUT_MODE_WB |
  322. DE_CTL_WB_NO_STRIDE_EN(no_stride_en);
  323. DE->WB_MEM_ADR = target->addr;
  324. DE->WB_MEM_STRIDE = target->desc.pitch;
  325. target_format = target->desc.pixel_format;
  326. } else {
  327. DE->CTL = DE_CTL_OUT_MODE_DISPLAY | (data->display_sync_en ?
  328. DE_CTL_TRANSFER_MODE_CONTINUE : DE_CTL_TRANSFER_MODE_TRIGGER);
  329. #ifdef CONFIG_DISPLAY_ENGINE_GAMMA_LUT
  330. DE->GAMMA_CTL = DE_GAMMA_EN;
  331. #endif
  332. target_format = data->display_format;
  333. target_bytes_per_pixel = data->display_bytes_per_pixel;
  334. }
  335. switch (target_format) {
  336. case PIXEL_FORMAT_ARGB_8888:
  337. DE->CTL |= DE_CTL_OUT_FORMAT_RGB888_WB_ARGB8888;
  338. break;
  339. case PIXEL_FORMAT_RGB_888:
  340. DE->CTL |= DE_CTL_OUT_FORMAT_RGB888;
  341. break;
  342. case PIXEL_FORMAT_BGR_565:
  343. default:
  344. DE->CTL |= DE_CTL_OUT_FORMAT_RGB565;
  345. break;
  346. }
  347. /* set default bg */
  348. DE->BG_SIZE = DE_BG_SIZE(cfg->target_rect.w, cfg->target_rect.h);
  349. DE->BG_COLOR = 0;
  350. /* Hardware demand */
  351. target_length_per_line = target_bytes_per_pixel * cfg->target_rect.w;
  352. if (target_length_per_line >= 32 * 4) {
  353. DE->MEM_OPT = (DE->MEM_OPT & ~DE_MEM_BURST_LEN_MASK) | DE_MEM_BURST_32;
  354. } else if (target_length_per_line >= 16 * 4) {
  355. DE->MEM_OPT = (DE->MEM_OPT & ~DE_MEM_BURST_LEN_MASK) | DE_MEM_BURST_16;
  356. } else {
  357. DE->MEM_OPT = (DE->MEM_OPT & ~DE_MEM_BURST_LEN_MASK) | DE_MEM_BURST_8;
  358. }
  359. /* 1 ovl at least */
  360. assert(top_idx >= 0);
  361. /* 1 fill color layer */
  362. if (ovls[top_idx].buffer == NULL &&
  363. (top_idx == 0 || ovls[top_idx].blending == DISPLAY_BLENDING_NONE)) {
  364. DE->CTL |= DE_CTL_OUT_COLOR_FILL_EN;
  365. DE->FILL_COLOR = ovls[top_idx].color.full;
  366. DE->COLOR_FILL_POS = DE_COLOR_FILL_POS(
  367. ovls[top_idx].frame.x, ovls[top_idx].frame.y);
  368. DE->COLOR_FILL_SIZE = DE_COLOR_FILL_SIZE(
  369. ovls[top_idx].frame.w, ovls[top_idx].frame.h);
  370. if (--top_idx < 0)
  371. goto out;
  372. }
  373. /* 1 background layer */
  374. if (ovls[0].buffer == NULL) {
  375. DE->BG_COLOR = ovls[0].color.full;
  376. ovls++;
  377. if (--top_idx < 0)
  378. goto out;
  379. }
  380. /* 2 normal ovls */
  381. assert(top_idx < 2);
  382. DE->ALPHA_CTL = 0;
  383. if (top_idx > 0 && ovls[top_idx].blending != DISPLAY_BLENDING_NONE) {
  384. uint32_t alpha_mode = (ovls[top_idx].blending == DISPLAY_BLENDING_PREMULT) ?
  385. DE_ALPHA_PREMULTIPLIED : DE_ALPHA_COVERAGE;
  386. /* don't double use the color alpha */
  387. uint8_t alpha = ovls[top_idx].buffer ? ovls[top_idx].color.a : 255;
  388. /* DE will only blend the pixels both inside ALPHA_AREA and L0 & L1 */
  389. DE->ALPHA_CTL = DE_ALPHA_EN | alpha_mode | DE_ALPHA_PLANE_ALPHA(alpha);
  390. DE->ALPHA_POS = DE_ALPHA_POS(0, 0);
  391. DE->ALPHA_SIZE = DE_ALPHA_SIZE(cfg->target_rect.w, cfg->target_rect.h);
  392. }
  393. for (; top_idx >= 0; top_idx--) {
  394. if (de_config_layer(top_idx, &ovls[top_idx]))
  395. break;
  396. }
  397. assert(top_idx == -1);
  398. out:
  399. #if CONFIG_DE_USE_POST_PRECONFIG
  400. data->preconfiged = preconfig;
  401. if (preconfig == true) {
  402. return 0;
  403. }
  404. #endif
  405. /* sequence:
  406. * 1) modify configuration registers
  407. * 2) modify REG_UD=1
  408. * 3) modify EN=1
  409. * 4) make sure EN is really 1 (read and compare with 1)
  410. * 5) REG_UD becomes 0
  411. * 6) hw START
  412. **/
  413. DE->REG_UD = 1;
  414. if (DE->EN == 0) {
  415. DE->EN = 1;
  416. while (DE->EN == 0);
  417. if (data->display_sync_en == 0) {
  418. k_work_schedule(&data->timeout_work,
  419. K_MSEC(CONFIG_DISPLAY_ENGINE_COMMAND_TIMEOUT_MS));
  420. }
  421. /* however, set write back start */
  422. DE->CTL2 = DE_CTL2_WB_START;
  423. /* FIXME: better to start display at DEV FIFO HALFULL (DE_STAT_DEV_FIFO_HF) */
  424. if (data->display_sync_en == 0 && target->addr == 0 && data->start_fn) {
  425. data->start_fn(data->start_fn_arg);
  426. }
  427. }
  428. return 0;
  429. }
  430. static int de_apply_rotate_cfg(struct de_data *data, struct de_command_entry *entry)
  431. {
  432. de_rotate_cfg_t *cfg = (de_rotate_cfg_t *)entry->cfg;
  433. sys_trace_u32x3(SYS_TRACE_ID_DE_DRAW, DE_CMD_ROTATE_CIRCLE,
  434. cfg->img_size & 0x1FF, (cfg->img_size >> 16) - cfg->start_height);
  435. DE->GAT_CTL = DE_ROTATE_GATING_EN;
  436. DE->EN = 1;
  437. DE->RT_DST_ADDR = cfg->dst_addr;
  438. DE->RT_DST_STRIDE = cfg->dst_stride;
  439. DE->RT_FILL_COLOR = cfg->fill_color;
  440. DE->RT_IMG_SIZE = cfg->img_size;
  441. DE->RT_R1M2 = cfg->r1m2;
  442. DE->RT_R0M2 = cfg->r0m2;
  443. DE->RT_SW_FIRST_DIST = cfg->sw_first_dist;
  444. DE->RT_START_HEIGHT = cfg->start_height;
  445. DE->RT_SRC_ADDR = cfg->src_addr;
  446. DE->RT_SRC_STRIDE = cfg->src_stride;
  447. DE->RT_SW_X_XY = cfg->sw_x_xy;
  448. DE->RT_SW_Y_XY = cfg->sw_y_xy;
  449. DE->RT_SW_X0 = cfg->sw_x0;
  450. DE->RT_SW_Y0 = cfg->sw_y0;
  451. k_work_schedule(&data->timeout_work,
  452. K_MSEC(CONFIG_DISPLAY_ENGINE_COMMAND_TIMEOUT_MS));
  453. DE->RT_CTL = cfg->ctl;
  454. return 0;
  455. }
  456. __de_func static void de_process_next_cmd(struct de_data *data, bool skipped)
  457. {
  458. struct de_command_entry *entry;
  459. sys_snode_t *node = NULL;
  460. #ifdef CONFIG_DISPLAY_ENGINE_HIHG_PRIO_INSTANCE
  461. if (data->cmd_node) {
  462. node = sys_slist_peek_head(&data->high_cmd_list);
  463. if (node == data->cmd_node) {
  464. sys_slist_remove(&data->high_cmd_list, NULL, data->cmd_node);
  465. } else {
  466. assert(data->cmd_node == sys_slist_peek_head(&data->cmd_list));
  467. sys_slist_remove(&data->cmd_list, NULL, data->cmd_node);
  468. }
  469. data->cmd_num--;
  470. }
  471. #else /* CONFIG_DISPLAY_ENGINE_HIHG_PRIO_INSTANCE */
  472. if (data->cmd_node) {
  473. assert(data->cmd_node == sys_slist_peek_head(&data->cmd_list));
  474. sys_slist_remove(&data->cmd_list, NULL, data->cmd_node);
  475. data->cmd_num--;
  476. }
  477. #endif /* CONFIG_DISPLAY_ENGINE_HIHG_PRIO_INSTANCE */
  478. /* find and execute next command */
  479. #ifdef CONFIG_DISPLAY_ENGINE_HIHG_PRIO_INSTANCE
  480. node = sys_slist_peek_head(&data->high_cmd_list);
  481. if (!node)
  482. node = sys_slist_peek_head(&data->cmd_list);
  483. #else /* CONFIG_DISPLAY_ENGINE_HIHG_PRIO_INSTANCE */
  484. node = sys_slist_peek_head(&data->cmd_list);
  485. #endif /* CONFIG_DISPLAY_ENGINE_HIHG_PRIO_INSTANCE */
  486. if (node) {
  487. if (data->cmd_node == NULL) /* new command from idle */
  488. de_clk_set_en(true);
  489. entry = CONTAINER_OF(node, struct de_command_entry, node);
  490. if (skipped == false) {
  491. switch (entry->cmd) {
  492. case DE_CMD_ROTATE_CIRCLE:
  493. de_apply_rotate_cfg(data, entry);
  494. break;
  495. default:
  496. de_apply_overlay_cfg(data, entry, false);
  497. break;
  498. }
  499. #if CONFIG_DE_USE_POST_PRECONFIG
  500. if (s_last_ovl_is_wb == false) {
  501. sys_snode_t *next_node = node->next;
  502. #ifdef CONFIG_DISPLAY_ENGINE_HIHG_PRIO_INSTANCE
  503. if (next_node == NULL && node == sys_slist_peek_head(&data->high_cmd_list)) {
  504. next_node = sys_slist_peek_head(&data->cmd_list);
  505. }
  506. #endif
  507. if (next_node) {
  508. entry = CONTAINER_OF(next_node, struct de_command_entry, node);
  509. if (entry->cmd == DE_CMD_COMPOSE) {
  510. de_apply_overlay_cfg(data, &entry->ovl_cfg, entry->cmd, true);
  511. }
  512. }
  513. }
  514. #endif /* CONFIG_DE_USE_POST_PRECONFIG */
  515. }
  516. } else { /* no more commands, become idle */
  517. de_clk_set_en(false);
  518. if (data->waiting) {
  519. data->waiting = 0;
  520. k_sem_give(&data->wait_sem);
  521. }
  522. }
  523. /* free previous command entry */
  524. if (data->cmd_node) {
  525. entry = CONTAINER_OF(data->cmd_node, struct de_command_entry, node);
  526. de_instance_notify(entry, data->cmd_status);
  527. de_instance_free_entry(entry);
  528. }
  529. /* point to the new command */
  530. data->cmd_node = node;
  531. }
  532. __de_func static void de_complete_cmd(struct de_data *data, int status)
  533. {
  534. sys_trace_end_call(SYS_TRACE_ID_DE_DRAW);
  535. if (data->display_sync_en == 0) {
  536. DE->EN = 0;
  537. DE->RT_CTL = RT_STAT_COMPLETE;
  538. DE->GAT_CTL = 0;
  539. }
  540. data->cmd_status = status;
  541. de_process_next_cmd(data, false);
  542. }
  543. static void de_cleanup_all_cmd(struct de_data *data)
  544. {
  545. unsigned int key = irq_lock();
  546. while (data->cmd_num > 0) {
  547. de_process_next_cmd(data, true);
  548. }
  549. irq_unlock(key);
  550. }
  551. __de_func static void de_append_cmd(struct de_data *data, struct de_command_entry *entry, bool high_prio)
  552. {
  553. unsigned int key = irq_lock();
  554. #ifdef CONFIG_DISPLAY_ENGINE_HIHG_PRIO_INSTANCE
  555. if (high_prio) {
  556. sys_slist_append(&data->high_cmd_list, &entry->node);
  557. } else {
  558. sys_slist_append(&data->cmd_list, &entry->node);
  559. }
  560. #else
  561. sys_slist_append(&data->cmd_list, &entry->node);
  562. #endif
  563. ++data->cmd_num;
  564. if (data->cmd_num == 1) {
  565. de_process_next_cmd(data, false);
  566. } else if (data->cmd_num == 2) {
  567. if (entry->cmd == DE_CMD_COMPOSE) {
  568. de_apply_overlay_cfg(data, entry, true);
  569. }
  570. }
  571. irq_unlock(key);
  572. }
  573. __de_func static int de_insert_overlay_cmd(const struct device *dev, int inst,
  574. const display_buffer_t *target, const display_layer_t *ovls,
  575. uint8_t num_ovls, uint8_t cmd)
  576. {
  577. struct de_data *data = dev->data;
  578. struct de_command_entry *entry;
  579. de_overlay_cfg_t *cfg;
  580. struct display_rect dst_rect;
  581. uint32_t dst_addr = 0;
  582. uint8_t bpp, halfword_en;
  583. uint16_t dst_pitch = 0, ovl_pitch[MAX_NUM_OVERLAYS] = { 0 };
  584. uint8_t has_ax_format = 0;
  585. int i;
  586. if (sizeof(de_overlay_cfg_t) < sizeof(((struct de_command_entry *)0)->cfg)) {
  587. printk("DE: must increase command cfg size to %u\n", sizeof(de_overlay_cfg_t));
  588. return -ENOMEM;
  589. }
  590. if (target != NULL && data->op_mode != DISPLAY_ENGINE_MODE_DEFAULT) {
  591. DEV_DBG("de display-only\n");
  592. return -EBUSY;
  593. }
  594. /* validate layer parameters */
  595. for (int i = 0; i < num_ovls; i++) {
  596. if (!ovls[i].buffer) {
  597. continue;
  598. }
  599. if ((ovls[i].buffer->desc.pixel_format & SUPPORTED_INPUT_PIXEL_FORMATS) == 0) {
  600. DEV_DBG("L%d format %d unsupported\n", i, ovls[i].buffer->desc.pixel_format);
  601. return -EINVAL;
  602. }
  603. if (ovls[i].buffer->desc.pixel_format & (PIXEL_FORMAT_A8 | PIXEL_FORMAT_A4_LE | PIXEL_FORMAT_A1_LE)) {
  604. if (has_ax_format) {
  605. DEV_DBG("L%d only one layer can be Ax\n", i);
  606. return -EINVAL;
  607. }
  608. if (ovls[i].buffer->desc.pixel_format == PIXEL_FORMAT_A4_LE && (ovls[i].frame.w & 0x1)) {
  609. DEV_DBG("L%d frame w of A4 must be mutiple of 2\n", i);
  610. return -EINVAL;
  611. }
  612. if (ovls[i].buffer->desc.pixel_format == PIXEL_FORMAT_A1_LE && (ovls[i].frame.w & 0x7)) {
  613. DEV_DBG("L%d frame w of A1 must be mutiple of 8\n", i);
  614. return -EINVAL;
  615. }
  616. has_ax_format = 1;
  617. }
  618. if (ovls[i].matrix != NULL ||
  619. ovls[i].frame.w == 0 || ovls[i].frame.w != ovls[i].buffer->desc.width ||
  620. ovls[i].frame.h == 0 || ovls[i].frame.h != ovls[i].buffer->desc.height) {
  621. DEV_DBG("L%d transform (%dx%d->%dx%d, %p) unsupported\n",
  622. i, ovls[i].buffer->desc.width, ovls[i].buffer->desc.height,
  623. ovls[i].frame.w, ovls[i].frame.h, ovls[i].matrix);
  624. return -EINVAL;
  625. }
  626. bpp = display_format_get_bits_per_pixel(ovls[i].buffer->desc.pixel_format);
  627. ovl_pitch[i] = GUESS_PITCH(ovls[i].buffer, bpp);
  628. /* Only rgb565 support half word aligned.
  629. * In this case, hardware implemention assumes the origin image is 4-byte aligned,
  630. * and then cropped (1, 0, xx, xx) which lead to the half-word aligned address.
  631. */
  632. halfword_en = (ovls[i].buffer->addr & 0x3) ? 1 : 0;
  633. if (halfword_en > 0) {
  634. if ((ovls[i].buffer->desc.pixel_format != PIXEL_FORMAT_BGR_565 &&
  635. ovls[i].buffer->desc.pixel_format != PIXEL_FORMAT_RGB_565)) {
  636. DEV_DBG("L%d address 0x%x unaligned\n", i, ovls[i].buffer->addr);
  637. return -EINVAL;
  638. }
  639. if (ovl_pitch[i] < ovls[i].buffer->desc.width * 2 + 2) {
  640. DEV_DBG("L%d width %u should not greater than pitch %u (hwa=%u)\n", i,
  641. ovls[i].buffer->desc.width, ovl_pitch[i], halfword_en);
  642. return -EINVAL;
  643. }
  644. }
  645. if ((ovl_pitch[i] & 0x3) && (halfword_en ||
  646. ovl_pitch[i] != ovls[i].buffer->desc.width * bpp / 8)) {
  647. DEV_DBG("L%d pitch %u unaligned (hwa=%u)\n", i, ovl_pitch[i], halfword_en);
  648. return -EINVAL;
  649. }
  650. }
  651. /* compute target area */
  652. memcpy(&dst_rect, &ovls[0].frame, sizeof(dst_rect));
  653. for (i = 1; i < num_ovls; i++) {
  654. display_rect_merge(&dst_rect, &ovls[i].frame);
  655. }
  656. /* validate target parameters */
  657. if (target) {
  658. uint8_t bytes_per_pixel;
  659. uint8_t min_w = MIN_WB_WIDTH;
  660. if ((target->desc.pixel_format & SUPPORTED_OUTPUT_PIXEL_FORMATS) == 0) {
  661. DEV_DBG("target format 0x%x unsupported\n", target->desc.pixel_format);
  662. return -EINVAL;
  663. }
  664. bytes_per_pixel = display_format_get_bits_per_pixel(target->desc.pixel_format) / 8;
  665. dst_pitch = GUESS_PITCH_BYTES(target, bytes_per_pixel);
  666. dst_addr = target->addr + dst_rect.y * dst_pitch + dst_rect.x * bytes_per_pixel;
  667. if (buf_is_psram(dst_addr)) {
  668. dst_addr = (uint32_t)cache_to_uncache((void *)dst_addr);
  669. min_w = (target->desc.pixel_format != PIXEL_FORMAT_BGR_565) ? 4 : 8;
  670. }
  671. if (display_rect_get_width(&dst_rect) < min_w) {
  672. DEV_DBG("bg width less than %d\n", min_w);
  673. return -EINVAL;
  674. }
  675. /* Only rgb565 support half word aligned.
  676. * In this case, hardware implemention assumes the origin target image is 4-byte aligned,
  677. * and writing to the area (1, 0, xx, xx) which lead to the half-word aligned address.
  678. */
  679. halfword_en = (dst_addr & 0x3) ? 1 : 0;
  680. if (target->desc.pixel_format != PIXEL_FORMAT_BGR_565) {
  681. if (halfword_en > 0) {
  682. DEV_DBG("target address 0x%x unaligned\n", dst_addr);
  683. return -EINVAL;
  684. }
  685. if ((dst_pitch & 0x3) && dst_pitch != target->desc.width * bytes_per_pixel) {
  686. DEV_DBG("target pitch %u unaligned (hwa=%u)\n", dst_pitch, halfword_en);
  687. return -EINVAL;
  688. }
  689. } else if (!(target->desc.width & 0x1)) {
  690. if (halfword_en || (dst_pitch != target->desc.width * bytes_per_pixel && (dst_pitch & 0x3))) {
  691. DEV_DBG("target address 0x%x unaligned (pitch %u, width %u)\n",
  692. dst_addr, dst_pitch, target->desc.width);
  693. return -EINVAL;
  694. }
  695. }
  696. /* HW Bug: SPI-Controller only support word aligned access from DE */
  697. if (IS_WB_REQUIRE_WORD_ALIGN(dst_addr)) {
  698. uint16_t bytes_to_copy = (target->desc.width * bytes_per_pixel);
  699. if (halfword_en || (bytes_to_copy & 0x3) || (dst_pitch & 0x3)) {
  700. DEV_DBG("target width %u & pitch %u not aligned for psram (hwa=%u)\n",
  701. target->desc.width, dst_pitch, halfword_en);
  702. return -EINVAL;
  703. }
  704. }
  705. } else {
  706. if (data->display_format == 0) {
  707. DEV_DBG("display mode not configured\n");
  708. return -EINVAL;
  709. }
  710. if (display_rect_get_width(&dst_rect) < MIN_DEV_WIDTH) {
  711. DEV_DBG("bg width less than 2\n");
  712. return -EINVAL;
  713. }
  714. }
  715. entry = de_instance_alloc_entry(inst);
  716. if (!entry)
  717. return -EBUSY;
  718. entry->cmd = cmd;
  719. cfg = (de_overlay_cfg_t *)entry->cfg;
  720. cfg->num_ovls = num_ovls;
  721. memcpy(cfg->ovls, ovls, num_ovls * sizeof(*ovls));
  722. memcpy(&cfg->target_rect, &dst_rect, sizeof(dst_rect));
  723. for (i = 0; i < num_ovls; i++) {
  724. if (ovls[i].buffer) {
  725. cfg->ovls[i].buffer = &cfg->bufs[i];
  726. memcpy(&cfg->bufs[i], ovls[i].buffer, sizeof(*target));
  727. cfg->bufs[i].desc.pitch = ovl_pitch[i];
  728. if (buf_is_psram(ovls[i].buffer->addr)) {
  729. cfg->bufs[i].addr =
  730. (uint32_t)cache_to_uncache((void *)ovls[i].buffer->addr);
  731. }
  732. }
  733. display_rect_move(&cfg->ovls[i].frame, -dst_rect.x, -dst_rect.y);
  734. }
  735. if (target) {
  736. cfg->target.desc.pixel_format = target->desc.pixel_format;
  737. cfg->target.desc.pitch = dst_pitch;
  738. cfg->target.desc.width = dst_rect.w;
  739. cfg->target.desc.height = dst_rect.h;
  740. cfg->target.addr = dst_addr;
  741. } else {
  742. cfg->target.addr = 0;
  743. }
  744. de_append_cmd(data, entry, de_instance_has_flag(inst, DISPLAY_ENGINE_FLAG_HIGH_PRIO));
  745. return entry->seq;
  746. }
  747. __de_func static int de_fill(const struct device *dev, int inst,
  748. const display_buffer_t *dest, display_color_t color)
  749. {
  750. display_buffer_t dest_fake;
  751. display_layer_t layer;
  752. /* fake as ARGB8888, min_w >= 3 */
  753. if (dest->desc.pixel_format == PIXEL_FORMAT_BGR_565) {
  754. uint16_t pitch = GUESS_PITCH_BYTES(dest, 2);
  755. /* min_w >= 3 */
  756. if (!(pitch & 0x3) && !(dest->addr & 0x3) &&
  757. !(dest->desc.width & 0x1) && (dest->desc.width >= MIN_WB_WIDTH * 2)) {
  758. dest_fake = (display_buffer_t) {
  759. .addr = dest->addr,
  760. .desc = {
  761. .pixel_format = PIXEL_FORMAT_ARGB_8888,
  762. .width = dest->desc.width / 2,
  763. .height = dest->desc.height,
  764. .pitch = pitch,
  765. },
  766. };
  767. dest = &dest_fake;
  768. color.full = ((color.r & 0xf8) << 8) | ((color.g & 0xfc) << 3) | (color.b >> 3);
  769. color.full = (color.full << 16) | color.full;
  770. }
  771. }
  772. layer.buffer = NULL;
  773. layer.color = color;
  774. layer.frame = (display_rect_t) { 0, 0, dest->desc.width, dest->desc.height };
  775. return de_insert_overlay_cmd(dev, inst, dest, &layer, 1, DE_CMD_FILL);
  776. }
  777. __de_func static int de_blit(const struct device *dev,
  778. int inst, const display_buffer_t *dest, const display_buffer_t *src)
  779. {
  780. display_layer_t layer = {
  781. .buffer = src,
  782. .color = { .a = 0xff, .r = 0, .g = 0, .b = 0, },
  783. .frame = { 0, 0, dest->desc.width, dest->desc.height },
  784. };
  785. if (dest->desc.width != src->desc.width || dest->desc.height != src->desc.height)
  786. return -EINVAL;
  787. if (buf_is_nor(src->addr))
  788. return -EACCES;
  789. return de_insert_overlay_cmd(dev, inst, dest, &layer, 1, DE_CMD_BLIT);
  790. }
  791. __de_func static int de_blend(const struct device *dev,
  792. int inst, const display_buffer_t *dest,
  793. const display_buffer_t *fg, display_color_t fg_color,
  794. const display_buffer_t *bg, display_color_t bg_color)
  795. {
  796. display_layer_t ovls[2] = {
  797. {
  798. .buffer = bg,
  799. .color = bg_color,
  800. .frame = { 0, 0, dest->desc.width, dest->desc.height },
  801. },
  802. {
  803. .buffer = fg,
  804. .color = fg_color,
  805. .blending = DISPLAY_BLENDING_COVERAGE,
  806. .frame = { 0, 0, dest->desc.width, dest->desc.height },
  807. },
  808. };
  809. if (bg == NULL || dest->desc.width != bg->desc.width || dest->desc.height != bg->desc.height) {
  810. return -EINVAL;
  811. }
  812. if (fg != NULL && (dest->desc.width != fg->desc.width || dest->desc.height != fg->desc.height)) {
  813. return -EINVAL;
  814. }
  815. if ((fg != NULL && buf_is_nor(fg->addr)) || buf_is_nor(bg->addr)) {
  816. return -EACCES;
  817. }
  818. if (fg != NULL && display_format_is_opaque(fg->desc.pixel_format) && fg_color.a == 255) {
  819. ovls[1].blending = DISPLAY_BLENDING_NONE;
  820. }
  821. return de_insert_overlay_cmd(dev, inst, dest, ovls, 2, fg ? DE_CMD_BLEND : DE_CMD_BLEND_FG);
  822. }
  823. __de_func static int de_compose(const struct device *dev, int inst,
  824. const display_buffer_t *target, const display_layer_t *ovls, int num_ovls)
  825. {
  826. uint8_t cmd = target ? DE_CMD_COMPOSE_WB :
  827. DE_CMD_COMPOSE;
  828. if (num_ovls > MAX_NUM_OVERLAYS || num_ovls <= 0) {
  829. DEV_DBG("unsupported ovl num %d\n", num_ovls);
  830. return -EINVAL;
  831. }
  832. return de_insert_overlay_cmd(dev, inst, target, ovls, num_ovls, cmd);
  833. }
  834. static int de_transform(const struct device *dev,
  835. int inst, const display_buffer_t *dest, const display_buffer_t *src,
  836. const display_engine_transform_param_t *param)
  837. {
  838. struct de_data *data = dev->data;
  839. struct de_command_entry *entry;
  840. de_rotate_cfg_t *cfg;
  841. uint16_t outer_diameter = src->desc.width - 1;
  842. uint8_t bytes_per_pixel;
  843. if (data->op_mode != DISPLAY_ENGINE_MODE_DEFAULT) {
  844. DEV_DBG("de display-only\n");
  845. return -EBUSY;
  846. }
  847. if (!param->is_circle) {
  848. return -EINVAL;
  849. }
  850. if (src->desc.pixel_format != dest->desc.pixel_format ||
  851. src->desc.width != dest->desc.width ||
  852. src->desc.width != src->desc.height) {
  853. DEV_DBG("src and dest must meet circle rotation demand\n");
  854. return -EINVAL;
  855. }
  856. if (param->circle.line_start + dest->desc.height > src->desc.width) {
  857. DEV_DBG("circle rotation line range exceed\n");
  858. return -EINVAL;
  859. }
  860. entry = de_instance_alloc_entry(inst);
  861. if (!entry)
  862. return -EBUSY;
  863. cfg = (de_rotate_cfg_t *)entry->cfg;
  864. cfg->start_height = param->circle.line_start;
  865. cfg->img_size = RT_IMG_WIDTH(dest->desc.width) |
  866. RT_END_HEIGHT(param->circle.line_start + dest->desc.height);
  867. cfg->r1m2 = param->circle.outer_radius_sq;
  868. cfg->r0m2 = param->circle.inner_radius_sq;
  869. cfg->sw_first_dist = outer_diameter * outer_diameter +
  870. (outer_diameter - 2 * param->circle.line_start) *
  871. (outer_diameter - 2 * param->circle.line_start);
  872. cfg->sw_x0 = param->matrix.tx;
  873. cfg->sw_y0 = param->matrix.ty;
  874. cfg->sw_x_xy = RT_SW_DELTA_XY(param->matrix.sx, param->matrix.shy);
  875. cfg->sw_y_xy = RT_SW_DELTA_XY(param->matrix.shx, param->matrix.sy);
  876. bytes_per_pixel = display_format_get_bits_per_pixel(src->desc.pixel_format) / 8;
  877. cfg->src_stride = GUESS_PITCH_BYTES(src, bytes_per_pixel);
  878. cfg->src_addr = buf_is_psram(src->addr) ?
  879. (uint32_t)cache_to_uncache((void *)src->addr) : src->addr;
  880. cfg->src_addr += (cfg->sw_y0 >> 12) * (int32_t)src->desc.pitch + (cfg->sw_x0 >> 12) * bytes_per_pixel;
  881. cfg->dst_stride = GUESS_PITCH_BYTES(dest, bytes_per_pixel);
  882. cfg->dst_addr = buf_is_psram(dest->addr) ?
  883. (uint32_t)cache_to_uncache((void *)dest->addr) : dest->addr;
  884. cfg->ctl = RT_EN | RT_IRQ_EN | RT_FILTER_BILINEAR | RT_COLOR_FILL_EN;
  885. if (src->desc.pixel_format == PIXEL_FORMAT_BGR_565) {
  886. cfg->ctl |= RT_FORMAT_RGB565;
  887. cfg->fill_color = RT_COLOR_RGB_565(param->color.r,
  888. param->color.g, param->color.b);
  889. } else {
  890. cfg->ctl |= RT_FORMAT_ARGB8888;
  891. cfg->fill_color = param->color.full & 0xFFFFFF;
  892. }
  893. entry->cmd = DE_CMD_ROTATE_CIRCLE;
  894. de_append_cmd(data, entry, de_instance_has_flag(inst, DISPLAY_ENGINE_FLAG_HIGH_PRIO));
  895. return entry->seq;
  896. }
  897. static int de_poll(const struct device *dev, int inst, int timeout_ms)
  898. {
  899. if (inst >= 0) {
  900. return de_instance_poll(inst, timeout_ms);
  901. }
  902. return -EINVAL;
  903. }
  904. static int de_register_callback(const struct device *dev,
  905. int inst, display_engine_instance_callback_t callback, void *user_data)
  906. {
  907. struct de_data *data = dev->data;
  908. int res;
  909. k_mutex_lock(&data->mutex, K_FOREVER);
  910. res = de_instance_register_callback(inst, callback, user_data);
  911. k_mutex_unlock(&data->mutex);
  912. return res;
  913. }
  914. static void de_get_capabilities(const struct device *dev,
  915. struct display_engine_capabilities *capabilities)
  916. {
  917. capabilities->num_overlays = MAX_NUM_OVERLAYS;
  918. capabilities->max_width = 512;
  919. capabilities->max_height = 512;
  920. capabilities->max_pitch = 4095;
  921. capabilities->support_fill = 1;
  922. capabilities->support_blend = 1;
  923. capabilities->support_blend_fg = 1;
  924. capabilities->support_blend_bg = 0;
  925. capabilities->supported_output_pixel_formats = SUPPORTED_OUTPUT_PIXEL_FORMATS;
  926. capabilities->supported_input_pixel_formats = SUPPORTED_INPUT_PIXEL_FORMATS;
  927. capabilities->supported_rotate_pixel_formats = SUPPORTED_ROTATE_PIXEL_FORMATS;
  928. }
  929. static int de_control(const struct device *dev, int cmd, void *arg1, void *arg2)
  930. {
  931. struct de_data *data = dev->data;
  932. int ret = 0;
  933. switch (cmd) {
  934. case DISPLAY_ENGINE_CTRL_DISPLAY_PREPARE_CB:
  935. data->prepare_fn_arg = arg2;
  936. data->prepare_fn = arg1;
  937. break;
  938. case DISPLAY_ENGINE_CTRL_DISPLAY_START_CB:
  939. data->start_fn_arg = arg2;
  940. data->start_fn = arg1;
  941. break;
  942. case DISPLAY_ENGINE_CTRL_DISPLAY_MODE:
  943. data->display_format = ((struct display_videomode *)arg1)->pixel_format;
  944. data->display_bytes_per_pixel = display_format_get_bits_per_pixel(data->display_format) / 8;
  945. break;
  946. case DISPLAY_ENGINE_CTRL_DISPLAY_PORT:
  947. data->display_sync_en =
  948. (((struct display_videoport *)arg1)->type == DISPLAY_PORT_QSPI_SYNC);
  949. if (data->display_sync_en) {
  950. data->op_mode = DISPLAY_ENGINE_MODE_DISPLAY_ONLY;
  951. }
  952. break;
  953. case DISPLAY_ENGINE_CTRL_DISPLAY_SYNC_STOP:
  954. if (data->display_sync_en) {
  955. int32_t wait_ms = (int32_t)arg1;
  956. /* wait command queue empty */
  957. data->display_sync_en = 0;
  958. while (data->cmd_num > 0 && wait_ms > 0) {
  959. k_msleep(2);
  960. wait_ms -= 2;
  961. }
  962. if (data->cmd_num > 0) {
  963. DEV_ERR("de sync stop timeout (stat=0x%x)\n", DE->STA);
  964. de_cleanup_all_cmd(data);
  965. ret = -ETIME;
  966. }
  967. data->display_sync_en = 1;
  968. /* FIXME: any better way to do this ? */
  969. de_reset(data);
  970. }
  971. break;
  972. case DISPLAY_ENGINE_CTRL_WORK_MODE:
  973. if (!data->display_sync_en) {
  974. uint8_t mode = (uint8_t)((intptr_t)arg1);
  975. if (mode != data->op_mode) {
  976. data->op_mode = mode;
  977. if (mode == DISPLAY_ENGINE_MODE_DISPLAY_ONLY) {
  978. unsigned int key = irq_lock();
  979. data->waiting = (data->cmd_num > 0);
  980. irq_unlock(key);
  981. if (data->waiting) {
  982. k_sem_take(&data->wait_sem, K_MSEC(5000));
  983. }
  984. }
  985. }
  986. }
  987. break;
  988. default:
  989. return -EINVAL;
  990. }
  991. return ret;
  992. }
  993. __de_func void de_isr(const void *arg)
  994. {
  995. const struct device *dev = arg;
  996. struct de_data *data = dev->data;
  997. uint32_t status = DE->STA;
  998. uint32_t rt_stat = DE->RT_CTL;
  999. bool completed = false;
  1000. DE->STA = status;
  1001. if (rt_stat & RT_STAT_COMPLETE) {
  1002. DEV_DBG("de rt complete 0x%08x\n", rt_stat);
  1003. completed = true;
  1004. }
  1005. if (status & (DE_STAT_WB_FTC | DE_STAT_DEV_FTC)) {
  1006. DEV_DBG("de ovl complete 0x%08x\n", status);
  1007. completed = true;
  1008. }
  1009. if (completed) {
  1010. if (data->display_sync_en == 0)
  1011. k_work_cancel_delayable(&data->timeout_work);
  1012. if (data->display_sync_en == 0 || data->cmd_num > 1)
  1013. de_complete_cmd(data, 0);
  1014. }
  1015. if (status & DE_STAT_DEV_FIFO_HF) {
  1016. DEV_DBG("de dev halfull\n");
  1017. if (data->display_sync_en && data->start_fn)
  1018. data->start_fn(data->start_fn_arg);
  1019. }
  1020. if (status & DE_STAT_DEV_FIFO_UDF) {
  1021. if (data->display_sync_en) {
  1022. DEV_ERR("de dev underflow 0x%08x\n", status);
  1023. de_reset(data);
  1024. de_complete_cmd(data, DE_STAT_DEV_FIFO_UDF);
  1025. }
  1026. }
  1027. /* RGB and SPI_QUAD_SYNC have vsync signal*/
  1028. if (status & DE_STAT_DEV_VSYNC) {
  1029. /* TODO: refresh frames */
  1030. DEV_DBG("vsync arrived\n");
  1031. }
  1032. /* update frames for those do not have vsync signal */
  1033. if (status & DE_STAT_PRELINE) {
  1034. /* TODO: refresh frames */
  1035. DEV_DBG("preline arrived\n");
  1036. }
  1037. }
  1038. static void de_timeout_work_handler(struct k_work *work)
  1039. {
  1040. struct de_data *data = CONTAINER_OF(work, struct de_data, timeout_work);
  1041. printk("de timeout\n");
  1042. de_dump();
  1043. de_complete_cmd(data, -ETIME);
  1044. }
  1045. extern uint32_t drv_de_version_dump(void);
  1046. int de_init(const struct device *dev)
  1047. {
  1048. struct de_data *data = dev->data;
  1049. drv_de_version_dump();
  1050. /* set invalid value */
  1051. data->display_format = 0;
  1052. k_sem_init(&data->wait_sem, 0, 1);
  1053. k_mutex_init(&data->mutex);
  1054. k_work_init_delayable(&data->timeout_work, de_timeout_work_handler);
  1055. sys_slist_init(&data->cmd_list);
  1056. #ifdef CONFIG_DISPLAY_ENGINE_HIHG_PRIO_INSTANCE
  1057. sys_slist_init(&data->high_cmd_list);
  1058. #endif
  1059. de_command_pools_init();
  1060. return 0;
  1061. }
  1062. #ifdef CONFIG_PM_DEVICE
  1063. int de_pm_control(const struct device *dev, enum pm_device_action action)
  1064. {
  1065. struct de_data *data = dev->data;
  1066. int ret = 0;
  1067. switch (action) {
  1068. case PM_DEVICE_ACTION_SUSPEND:
  1069. case PM_DEVICE_ACTION_FORCE_SUSPEND:
  1070. case PM_DEVICE_ACTION_TURN_OFF:
  1071. ret = (data->cmd_num > 0) ? -EBUSY : 0;
  1072. break;
  1073. case PM_DEVICE_ACTION_RESUME:
  1074. de_reset(data);
  1075. break;
  1076. default:
  1077. break;
  1078. }
  1079. return ret;
  1080. }
  1081. #endif /* CONFIG_PM_DEVICE */
  1082. const struct display_engine_driver_api de_drv_api = {
  1083. .control = de_control,
  1084. .open = de_open,
  1085. .close = de_close,
  1086. .get_capabilities = de_get_capabilities,
  1087. .register_callback = de_register_callback,
  1088. .fill = de_fill,
  1089. .blit = de_blit,
  1090. .blend = de_blend,
  1091. .compose = de_compose,
  1092. .transform = de_transform,
  1093. .poll = de_poll,
  1094. };
  1095. struct de_data de_drv_data;