dma2d_lite.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571
  1. /*
  2. * Copyright (c) 2020 Actions Technology Co., Ltd
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. #include <assert.h>
  7. #include <string.h>
  8. #include <soc.h>
  9. #include <spicache.h>
  10. #include <drivers/display/display_engine.h>
  11. #ifdef CONFIG_SPI_FLASH_ACTS
  12. #include <flash/spi_flash.h>
  13. #endif
  14. #include <sys/atomic.h>
  15. #include <tracing/tracing.h>
  16. #include <linker/linker-defs.h>
  17. #include "dma2d_lite.h"
  18. #include <logging/log.h>
  19. LOG_MODULE_REGISTER(dma2dlite_dev, LOG_LEVEL_INF);
  20. #if CONFIG_DMA2D_LITE_SDMA_CHAN < 1 || CONFIG_DMA2D_LITE_SDMA_CHAN > 4
  21. # error "CONFIG_DMA2D_LITE_SDMA_CHAN must in range [1, 4]."
  22. #endif
  23. #define SDMA ((SDMA_Type *)SDMA_REG_BASE)
  24. #define SDMA_CHAN (&(SDMA->CHAN_CTL[CONFIG_DMA2D_LITE_SDMA_CHAN]))
  25. #define SDMA_LINE (&(SDMA->LINE_CTL[CONFIG_DMA2D_LITE_SDMA_CHAN]))
  26. #define __SDMA_IRQ_ID(n) (IRQ_ID_SDMA##n)
  27. #define _SDMA_IRQ_ID(n) __SDMA_IRQ_ID(n)
  28. #define SDMA_IRQ_ID _SDMA_IRQ_ID(CONFIG_DMA2D_LITE_SDMA_CHAN)
  29. #define MAX_WIDTH (((1 << 16) - 1) / 4)
  30. #define MAX_HEIGHT ((1 << 16) - 1)
  31. #define MAX_PITCH (((1 << 16) - 1) / 4)
  32. #define MAX_BYTES ((1 << 20) - 1)
  33. #define SUPPORTED_PIXEL_FORMATS \
  34. (PIXEL_FORMAT_ARGB_8888 | PIXEL_FORMAT_XRGB_8888 | PIXEL_FORMAT_RGB_888 | \
  35. PIXEL_FORMAT_BGR_888 | PIXEL_FORMAT_BGRA_6666 | PIXEL_FORMAT_RGBA_6666 | \
  36. PIXEL_FORMAT_BGRA_5658 | PIXEL_FORMAT_BGR_565 | PIXEL_FORMAT_RGB_565 | \
  37. PIXEL_FORMAT_BGRA_5551 | PIXEL_FORMAT_A8)
  38. struct sdma_instance {
  39. /* user callback */
  40. display_engine_instance_callback_t callback;
  41. void *user_data;
  42. /* poll sem */
  43. bool polling;
  44. struct k_sem sem;
  45. };
  46. struct sdma_data {
  47. bool waiting;
  48. int8_t cur_inst;
  49. uint16_t cmd_seq;
  50. uint16_t cplt_seq;
  51. atomic_t open_mask;
  52. struct sdma_instance instance[CONFIG_DMA2D_LITE_INSTANCE_NUM];
  53. struct k_sem wait_sem;
  54. struct k_spinlock lock;
  55. #ifdef CONFIG_SPI_FLASH_ACTS
  56. bool nor_locked;
  57. #endif
  58. };
  59. static k_spinlock_key_t _wait_idle_locked(struct sdma_data *data);
  60. static int sdma_poll(const struct device *dev, int inst, int timeout_ms);
  61. __de_func static void _set_nor_locked(struct sdma_data *data, bool locked)
  62. {
  63. #ifdef CONFIG_SPI_FLASH_ACTS
  64. if (locked != data->nor_locked) {
  65. data->nor_locked = locked;
  66. LOG_DBG("nor locked %d\n", locked);
  67. if (locked) {
  68. spi0_nor_xip_lock();
  69. } else {
  70. spi0_nor_xip_unlock();
  71. }
  72. }
  73. #endif
  74. }
  75. static bool _validate_inst(struct sdma_data *data, int inst)
  76. {
  77. if (inst < 0 || inst >= ARRAY_SIZE(data->instance))
  78. return false;
  79. return atomic_test_bit(&data->open_mask, inst);
  80. }
  81. static int sdma_open(const struct device *dev, uint32_t flags)
  82. {
  83. struct sdma_data *data = dev->data;
  84. int i;
  85. for (i = 0; i < ARRAY_SIZE(data->instance); i++) {
  86. if (false == atomic_test_and_set_bit(&data->open_mask, i)) {
  87. return i;
  88. }
  89. }
  90. LOG_ERR("no free instance");
  91. return -EMFILE;
  92. }
  93. static int sdma_close(const struct device *dev, int inst)
  94. {
  95. struct sdma_data *data = dev->data;
  96. int ret;
  97. ret = sdma_poll(dev, inst, -1);
  98. if (ret != -EINVAL) {
  99. data->instance[inst].callback = NULL;
  100. data->instance[inst].user_data = NULL;
  101. atomic_clear_bit(&data->open_mask, inst);
  102. }
  103. return ret;
  104. }
  105. __unused static void sdma_dump(void)
  106. {
  107. printk("SDMA-%d:\n", CONFIG_DMA2D_LITE_SDMA_CHAN);
  108. printk(" CTL 0x%08x\n", SDMA_CHAN->CTL);
  109. printk(" SADDR 0x%08x\n", SDMA_CHAN->SADDR);
  110. printk(" DADDR 0x%08x\n", SDMA_CHAN->DADDR);
  111. printk(" BC 0x%08x\n", SDMA_CHAN->BC);
  112. printk(" RC 0x%08x\n", SDMA_CHAN->RC);
  113. printk(" LINE_LENGTH 0x%08x\n", SDMA_LINE->LENGTH);
  114. printk(" LINE_COUNT 0x%08x\n", SDMA_LINE->COUNT);
  115. printk(" LINE_SSTRIDE 0x%08x\n", SDMA_LINE->SSTRIDE);
  116. printk(" LINE_DSTRIDE 0x%08x\n", SDMA_LINE->DSTRIDE);
  117. printk(" LINE_REMAIN 0x%08x\n", SDMA_LINE->REMAIN);
  118. printk("BYTE_REMAIN_IN_LINE 0x%08x\n", SDMA_LINE->BYTE_REMAIN_IN_LINE);
  119. #if CONFIG_DMA2D_LITE_SDMA_CHAN < 4
  120. printk(" COLOR_FILL_DATA0 0x%08x\n", SDMA->COLOR_FILL_DATA[0]);
  121. printk(" COLOR_FILL_DATA1 0x%08x\n", SDMA->COLOR_FILL_DATA[1]);
  122. printk(" COLOR_FILL_DATA2 0x%08x\n", SDMA->COLOR_FILL_DATA[2]);
  123. #endif
  124. }
  125. #if CONFIG_DMA2D_LITE_SDMA_CHAN < 4
  126. static uint8_t _convert_color(display_color_t *result, display_color_t color, uint32_t pixel_format)
  127. {
  128. uint8_t px_bytes = 0;
  129. switch (pixel_format) {
  130. case PIXEL_FORMAT_XRGB_8888:
  131. color.a = 0xFF;
  132. /* fall through */
  133. case PIXEL_FORMAT_ARGB_8888:
  134. result->full = color.full;
  135. px_bytes = 4;
  136. break;
  137. case PIXEL_FORMAT_BGR_565:
  138. result->c16[0] = ((color.full & 0x00f80000) >> 8) |
  139. ((color.full & 0x00fc00) >> 5) | ((color.full & 0xf8) >> 3);
  140. result->c16[1] = result->c16[0];
  141. px_bytes = 2;
  142. break;
  143. case PIXEL_FORMAT_RGB_565:
  144. result->c8[0] = (color.r & 0xF8) | (color.g >> 5);
  145. result->c8[1] = (color.g << 5) | (color.b >> 3);
  146. result->c16[1] = result->c16[0];
  147. px_bytes = 2;
  148. break;
  149. case PIXEL_FORMAT_BGRA_5551:
  150. result->c16[0] = ((color.full & 0x80000000) >> 16) | ((color.full & 0x00f80000) >> 9) |
  151. ((color.full & 0x00f800) >> 6) | ((color.full & 0xf8) >> 3);
  152. result->c16[1] = result->c16[0];
  153. px_bytes = 2;
  154. break;
  155. case PIXEL_FORMAT_RGB_888:
  156. result->c8[0] = color.r;
  157. result->c8[1] = color.g;
  158. result->c8[2] = color.b;
  159. result->c8[3] = 0;
  160. px_bytes = 3;
  161. break;
  162. case PIXEL_FORMAT_BGR_888:
  163. result->c8[0] = color.b;
  164. result->c8[1] = color.g;
  165. result->c8[2] = color.r;
  166. result->c8[3] = 0;
  167. px_bytes = 3;
  168. break;
  169. case PIXEL_FORMAT_BGRA_5658:
  170. result->c16[0] = ((color.full & 0x00f80000) >> 8) |
  171. ((color.full & 0x00fc00) >> 5) | ((color.full & 0xf8) >> 3);
  172. result->c8[2] = color.a;
  173. result->c8[3] = 0;
  174. px_bytes = 3;
  175. break;
  176. case PIXEL_FORMAT_BGRA_6666:
  177. result->c8[0] = ((color.g & 0x0c) << 4) | ((color.b & 0xfc) >> 2);
  178. result->c8[1] = ((color.r & 0x3c) << 2) | ((color.g & 0xf0) >> 4);
  179. result->c8[2] = (color.a & 0xfc) | ((color.r & 0xc0) >> 6);
  180. result->c8[3] = 0;
  181. px_bytes = 3;
  182. break;
  183. case PIXEL_FORMAT_RGBA_6666:
  184. result->c8[0] = ((color.g & 0x0c) << 4) | ((color.r & 0xfc) >> 2);
  185. result->c8[1] = ((color.b & 0x3c) << 2) | ((color.g & 0xf0) >> 4);
  186. result->c8[2] = (color.a & 0xfc) | ((color.b & 0xc0) >> 6);
  187. result->c8[3] = 0;
  188. px_bytes = 3;
  189. break;
  190. case PIXEL_FORMAT_A8:
  191. default:
  192. result->c8[0] = result->c8[1] = color.a;
  193. result->c16[1] = result->c16[0];
  194. px_bytes = 1;
  195. break;
  196. }
  197. return px_bytes;
  198. }
  199. static int sdma_fill(const struct device *dev, int inst,
  200. const display_buffer_t *dest, display_color_t color)
  201. {
  202. struct sdma_data *data = dev->data;
  203. k_spinlock_key_t key;
  204. display_color_t value;
  205. uint32_t dst_addr;
  206. uint32_t total_bytes;
  207. uint32_t row_bytes;
  208. uint8_t px_bytes;
  209. bool stride_mode;
  210. int ret = -EINVAL;
  211. if (false == _validate_inst(data, inst)) {
  212. return -EINVAL;
  213. }
  214. if ((dest->desc.pixel_format & SUPPORTED_PIXEL_FORMATS) == 0) {
  215. return -EINVAL;
  216. }
  217. px_bytes = _convert_color(&value, color, dest->desc.pixel_format);
  218. row_bytes = (uint32_t)px_bytes * dest->desc.width;
  219. total_bytes = row_bytes * dest->desc.height;
  220. if (total_bytes > MAX_BYTES) {
  221. return -EINVAL;
  222. }
  223. stride_mode = (dest->desc.pitch > 0 && dest->desc.pitch != row_bytes);
  224. if (stride_mode && (dest->desc.pitch > MAX_PITCH || dest->desc.height > MAX_HEIGHT)) {
  225. return -EINVAL;
  226. }
  227. dst_addr = (uint32_t)cache_to_uncache((void *)dest->addr);
  228. key = _wait_idle_locked(data);
  229. data->cur_inst = (int8_t)inst;
  230. ret = data->cmd_seq++;
  231. /* config registers */
  232. if (px_bytes == 3) {
  233. SDMA->COLOR_FILL_DATA[0] = value.full | (value.full << 24);
  234. SDMA->COLOR_FILL_DATA[1] = (value.full >> 8) | (value.full << 16);
  235. SDMA->COLOR_FILL_DATA[2] = (value.full >> 16) | (value.full << 8);
  236. } else {
  237. SDMA->COLOR_FILL_DATA[0] = value.full;
  238. SDMA->COLOR_FILL_DATA[1] = value.full;
  239. SDMA->COLOR_FILL_DATA[2] = value.full;
  240. }
  241. if (stride_mode) {
  242. SDMA_LINE->DSTRIDE = dest->desc.pitch;
  243. SDMA_LINE->COUNT = dest->desc.height;
  244. SDMA_LINE->LENGTH = row_bytes;
  245. SDMA_CHAN->CTL = BIT(24) | 2; /* stride mode; color_fill */
  246. } else {
  247. SDMA_CHAN->CTL = 2; /* stride mode; color_fill */
  248. }
  249. SDMA_CHAN->BC = total_bytes;
  250. SDMA_CHAN->DADDR = dst_addr;
  251. SDMA_CHAN->START = 1;
  252. k_spin_unlock(&data->lock, key);
  253. return ret;
  254. }
  255. #else
  256. static int sdma_fill(const struct device *dev, int inst,
  257. const display_buffer_t *dest, display_color_t color)
  258. {
  259. return -ENOTSUP;
  260. }
  261. #endif /* CONFIG_DMA2D_LITE_SDMA_CHAN < 4 */
  262. static int sdma_blit(const struct device *dev, int inst,
  263. const display_buffer_t *dest, const display_buffer_t *src)
  264. {
  265. struct sdma_data *data = dev->data;
  266. k_spinlock_key_t key;
  267. uint32_t dst_addr;
  268. uint32_t src_addr;
  269. uint32_t total_bytes;
  270. uint32_t row_bytes;
  271. uint8_t px_bytes;
  272. bool stride_mode;
  273. bool access_nor;
  274. int ret = -EINVAL;
  275. if (false == _validate_inst(data, inst)) {
  276. return -EINVAL;
  277. }
  278. if ((dest->desc.pixel_format & SUPPORTED_PIXEL_FORMATS) == 0) {
  279. return -EINVAL;
  280. }
  281. if (dest->desc.pixel_format != src->desc.pixel_format ||
  282. dest->desc.width != src->desc.width ||
  283. dest->desc.height != src->desc.height) {
  284. return -EINVAL;
  285. }
  286. px_bytes = display_format_get_bits_per_pixel(dest->desc.pixel_format) / 8;
  287. row_bytes = (uint32_t)px_bytes * dest->desc.width;
  288. total_bytes = row_bytes * dest->desc.height;
  289. if (total_bytes > MAX_BYTES) {
  290. return -EINVAL;
  291. }
  292. stride_mode = (dest->desc.pitch > 0 && dest->desc.pitch != row_bytes) ||
  293. (src->desc.pitch > 0 && src->desc.pitch != row_bytes);
  294. if (stride_mode && (src->desc.pitch > MAX_PITCH ||
  295. dest->desc.pitch > MAX_PITCH || dest->desc.height > MAX_HEIGHT)) {
  296. return -EINVAL;
  297. }
  298. dst_addr = (uint32_t)cache_to_uncache((void *)dest->addr);
  299. access_nor = buf_is_nor((void *)src->addr);
  300. if (access_nor) {
  301. src_addr = (uint32_t)cache_to_uncache_by_master((void *)src->addr, SPI0_CACHE_MASTER_SDMA);
  302. } else {
  303. src_addr = (uint32_t)cache_to_uncache((void *)src->addr);
  304. }
  305. key = _wait_idle_locked(data);
  306. if (access_nor) {
  307. _set_nor_locked(data, true);
  308. }
  309. data->cur_inst = (int8_t)inst;
  310. ret = data->cmd_seq++;
  311. /* config registers */
  312. if (stride_mode) {
  313. SDMA_LINE->COUNT = src->desc.height;
  314. SDMA_LINE->LENGTH = row_bytes;
  315. SDMA_LINE->SSTRIDE = (src->desc.pitch > 0) ? src->desc.pitch : row_bytes;
  316. SDMA_LINE->DSTRIDE = (dest->desc.pitch > 0) ? dest->desc.pitch : row_bytes;
  317. SDMA_CHAN->CTL = BIT(24); /* stride mode */
  318. } else {
  319. SDMA_CHAN->CTL = 0;
  320. }
  321. SDMA_CHAN->BC = total_bytes;
  322. SDMA_CHAN->SADDR = src_addr;
  323. SDMA_CHAN->DADDR = dst_addr;
  324. SDMA_CHAN->START = 1;
  325. k_spin_unlock(&data->lock, key);
  326. return ret;
  327. }
  328. static inline int sdma_blend(const struct device *dev,
  329. int inst, const display_buffer_t *dest,
  330. const display_buffer_t *fg, display_color_t fg_color,
  331. const display_buffer_t *bg, display_color_t bg_color)
  332. {
  333. return -ENOTSUP;
  334. }
  335. static int sdma_compose(const struct device *dev, int inst,
  336. const display_buffer_t *target, const display_layer_t *ovls, int num_ovls)
  337. {
  338. return -ENOTSUP;
  339. }
  340. static k_spinlock_key_t _wait_idle_locked(struct sdma_data *data)
  341. {
  342. k_spinlock_key_t key;
  343. do {
  344. key = k_spin_lock(&data->lock);
  345. data->waiting = (data->cur_inst >= 0);
  346. if (!data->waiting) {
  347. return key;
  348. }
  349. k_spin_unlock(&data->lock, key);
  350. k_sem_take(&data->wait_sem, K_FOREVER);
  351. } while (1);
  352. }
  353. static int sdma_poll(const struct device *dev, int inst, int timeout_ms)
  354. {
  355. struct sdma_data *data = dev->data;
  356. struct sdma_instance *instance = &data->instance[inst];
  357. k_spinlock_key_t key;
  358. int ret = 0;
  359. if (false == _validate_inst(data, inst)) {
  360. return -EINVAL;
  361. }
  362. key = k_spin_lock(&data->lock);
  363. instance->polling = (data->cur_inst == inst);
  364. k_spin_unlock(&data->lock, key);
  365. if (instance->polling) {
  366. ret = k_sem_take(&data->instance[inst].sem,
  367. (timeout_ms >= 0) ? K_MSEC(timeout_ms) : K_FOREVER);
  368. instance->polling = false;
  369. }
  370. return ret;
  371. }
  372. static int sdma_register_callback(const struct device *dev,
  373. int inst, display_engine_instance_callback_t callback, void *user_data)
  374. {
  375. struct sdma_data *data = dev->data;
  376. if (false == _validate_inst(data, inst)) {
  377. return -EINVAL;
  378. }
  379. data->instance[inst].user_data = user_data;
  380. data->instance[inst].callback = callback;
  381. return 0;
  382. }
  383. static void sdma_get_capabilities(const struct device *dev,
  384. struct display_engine_capabilities *capabilities)
  385. {
  386. /* considering 32bit pixel format */
  387. capabilities->max_width = MAX_WIDTH;
  388. capabilities->max_height = MAX_HEIGHT;
  389. capabilities->max_pitch = MAX_PITCH;
  390. capabilities->num_overlays = 1;
  391. capabilities->support_fill = (CONFIG_DMA2D_LITE_SDMA_CHAN < 4) ? 1 : 0;
  392. capabilities->support_blend = 0;
  393. capabilities->support_blend_fg = 0;
  394. capabilities->support_blend_bg = 0;
  395. capabilities->supported_output_pixel_formats = SUPPORTED_PIXEL_FORMATS;
  396. capabilities->supported_input_pixel_formats = SUPPORTED_PIXEL_FORMATS;
  397. capabilities->supported_rotate_pixel_formats = 0;
  398. }
  399. __de_func static void sdma_isr(const void *arg)
  400. {
  401. const struct device *dev = arg;
  402. struct sdma_data *data = dev->data;
  403. struct sdma_instance *instance = &data->instance[data->cur_inst];
  404. SDMA->IP = BIT(CONFIG_DMA2D_LITE_SDMA_CHAN);
  405. _set_nor_locked(data, false);
  406. if (instance->callback) {
  407. instance->callback(0, data->cplt_seq, instance->user_data);
  408. }
  409. data->cplt_seq++;
  410. data->cur_inst = -1;
  411. if (data->waiting) {
  412. k_sem_give(&data->wait_sem);
  413. }
  414. if (instance->polling) {
  415. k_sem_give(&instance->sem);
  416. }
  417. }
  418. DEVICE_DECLARE(dma2d_lite);
  419. static int sdma_init(const struct device *dev)
  420. {
  421. struct sdma_data *data = dev->data;
  422. int i;
  423. memset(data, 0, sizeof(*data));
  424. data->cur_inst = -1;
  425. k_sem_init(&data->wait_sem, 0, 1);
  426. for (i = 0; i < ARRAY_SIZE(data->instance); i++) {
  427. k_sem_init(&data->instance[i].sem, 0, 1);
  428. }
  429. SDMA->IE |= BIT(CONFIG_DMA2D_LITE_SDMA_CHAN);
  430. IRQ_CONNECT(SDMA_IRQ_ID, 0, sdma_isr, DEVICE_GET(dma2d_lite), 0);
  431. irq_enable(SDMA_IRQ_ID);
  432. return 0;
  433. }
  434. #ifdef CONFIG_PM_DEVICE
  435. static int sdma_pm_control(const struct device *dev, enum pm_device_action action)
  436. {
  437. struct sdma_data *data = dev->data;
  438. int ret = 0;
  439. switch (action) {
  440. case PM_DEVICE_ACTION_SUSPEND:
  441. case PM_DEVICE_ACTION_FORCE_SUSPEND:
  442. ret = (data->cur_inst >= 0) ? -EBUSY : 0;
  443. break;
  444. case PM_DEVICE_ACTION_RESUME:
  445. /* Make sure interrupt enabled */
  446. SDMA->IE |= BIT(CONFIG_DMA2D_LITE_SDMA_CHAN);
  447. break;
  448. default:
  449. break;
  450. }
  451. return ret;
  452. }
  453. #endif /* CONFIG_PM_DEVICE */
  454. static const struct display_engine_driver_api sdma_drv_api = {
  455. .open = sdma_open,
  456. .close = sdma_close,
  457. .get_capabilities = sdma_get_capabilities,
  458. .register_callback = sdma_register_callback,
  459. .fill = sdma_fill,
  460. .blit = sdma_blit,
  461. .blend = sdma_blend,
  462. .compose = sdma_compose,
  463. .poll = sdma_poll,
  464. };
  465. static struct sdma_data sdma_drv_data __in_section_unique(ram.noinit.drv_sdma);
  466. #if IS_ENABLED(CONFIG_DMA2D_LITE_DEV)
  467. DEVICE_DEFINE(dma2d_lite, CONFIG_DMA2D_LITE_DEV_NAME, &sdma_init,
  468. sdma_pm_control, &sdma_drv_data, NULL, POST_KERNEL,
  469. CONFIG_KERNEL_INIT_PRIORITY_DEVICE, &sdma_drv_api);
  470. #endif