qoi_dec.c 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. #include "chip.h"
  2. #include "board.h"
  3. #include "qoi_dec.h"
  4. #define DEC_CTRL_REG 0x00
  5. #define DEC_SIZE_REG 0x04
  6. #define DEC_RD_ADDR_REG 0x08
  7. #define DEC_WB_ADDR_REG 0x0c
  8. #define DEC_WB_DATA_PER_FRAME_REG 0x10
  9. #define DEC_INT_EN_REG 0x14
  10. #define DEC_INT_CLR_REG 0x18
  11. #define DEC_STATUS_REG 0x1c
  12. #define DEC_WIDTH_RD_REG 0x20
  13. #define DEC_HEIGHT_RD_REG 0x24
  14. #define WB_FRAME_FINISH_INT (1<<3)
  15. #define BRESP_ERROR_INT (1<<2)
  16. #define FINISH_INT (1<<1)
  17. #define ERROR_INT (1<<0)
  18. #define QOI_INT_FLAGS (WB_FRAME_FINISH_INT | BRESP_ERROR_INT | FINISH_INT | ERROR_INT)
  19. #define QOI_MAX_WIDTH 1920
  20. #define QOI_MAX_HEIGHT 1080
  21. typedef enum _awlen_bits {
  22. AWLEN_4BIT = 4,
  23. AWLEN_5BIT = 5,
  24. AWLEN_6BIT = 6,
  25. AWLEN_7BIT = 7,
  26. AWLEN_8BIT = 8,
  27. } awlen_bits_t;
  28. typedef enum _arlen_bits {
  29. ARLEN_4BIT = 4,
  30. ARLEN_5BIT = 5,
  31. ARLEN_6BIT = 6,
  32. ARLEN_7BIT = 7,
  33. ARLEN_8BIT = 8,
  34. } arlen_bits_t;
  35. typedef struct _qoi_cfg {
  36. uint32_t wid;
  37. uint32_t rid;
  38. uint32_t min_burst;
  39. uint32_t max_burst;
  40. uint32_t fixed_burst_en;
  41. uint32_t src_w;
  42. uint32_t src_h;
  43. uint32_t src_addr;
  44. uint32_t wb_addr;
  45. uint32_t wb_size;
  46. uint32_t set_ints;
  47. uint32_t wbbvalid_dis;
  48. uint32_t wb_fifo_state_sel;
  49. uint32_t wrfifo_finish_sel;
  50. awlen_bits_t awlen_bits;
  51. arlen_bits_t arlen_bits;
  52. }qoi_cfg_t;
  53. typedef struct {
  54. uint32_t base;
  55. int irqn;
  56. SemaphoreHandle_t mutex_lock;
  57. QueueHandle_t complete;
  58. qoi_cfg_t cfg;
  59. } qoi_drv_t;
  60. static qoi_drv_t g_qoi = {
  61. .base = REGS_QOI_BASE,
  62. .irqn = QOI_IRQn,
  63. .mutex_lock = NULL,
  64. .complete = NULL,
  65. };
  66. static void qoi_enable(qoi_drv_t *qoi)
  67. {
  68. uint32_t val;
  69. val = readl(qoi->base + DEC_CTRL_REG);
  70. val |= 0x1;
  71. writel(val, qoi->base + DEC_CTRL_REG);
  72. }
  73. static void qoi_disable(qoi_drv_t *qoi)
  74. {
  75. uint32_t val;
  76. val = readl(qoi->base + DEC_CTRL_REG);
  77. val &= ~0x1;
  78. writel(val, qoi->base + DEC_CTRL_REG);
  79. }
  80. static void qoi_clear_intr(qoi_drv_t *qoi, uint32_t flags)
  81. {
  82. writel(flags, qoi->base + DEC_INT_CLR_REG);
  83. writel(0, qoi->base + DEC_INT_CLR_REG);
  84. }
  85. static void qoi_intr_handler(void *param)
  86. {
  87. qoi_drv_t *qoi = (qoi_drv_t *)param;
  88. uint32_t status;
  89. if (qoi) {
  90. status = readl(qoi->base + DEC_STATUS_REG);
  91. qoi_clear_intr(qoi, status);
  92. if (status & (BRESP_ERROR_INT | ERROR_INT | WB_FRAME_FINISH_INT)) {
  93. xQueueSendFromISR(qoi->complete, &status, 0);
  94. }
  95. }
  96. }
  97. static void qoi_config(qoi_drv_t *qoi)
  98. {
  99. uint32_t val;
  100. val = ((qoi->cfg.wbbvalid_dis & 0x1) << 28) |
  101. ((qoi->cfg.awlen_bits & 0xf) << 24) |
  102. ((qoi->cfg.wid & 0xf) << 20) |
  103. ((qoi->cfg.rid & 0xf) << 16) |
  104. ((qoi->cfg.arlen_bits & 0xf) << 12) |
  105. ((qoi->cfg.min_burst & 0xf) << 8) |
  106. ((qoi->cfg.max_burst & 0xf) << 4) |
  107. ((qoi->cfg.wb_fifo_state_sel & 0x1) << 3) |
  108. ((qoi->cfg.wrfifo_finish_sel & 0x1) << 2) |
  109. ((qoi->cfg.fixed_burst_en & 0x1) << 1);
  110. writel(val, qoi->base + DEC_CTRL_REG);
  111. val = ((qoi->cfg.src_h & 0xfff) << 12) | ((qoi->cfg.src_w & 0xfff) << 0);
  112. writel(val, qoi->base + DEC_SIZE_REG);
  113. writel(qoi->cfg.src_addr, qoi->base + DEC_RD_ADDR_REG);
  114. writel(qoi->cfg.wb_addr, qoi->base + DEC_WB_ADDR_REG);
  115. writel(qoi->cfg.wb_size, qoi->base + DEC_WB_DATA_PER_FRAME_REG);
  116. writel(qoi->cfg.set_ints, qoi->base + DEC_INT_EN_REG);
  117. }
  118. int qoi_get_img_size(qoi_info_t *info)
  119. {
  120. uint32_t width, height;
  121. char *src_addr;
  122. if (!info || !info->qoi_addr) {
  123. printf("ERR: %s Invalid info\n", __func__);
  124. return -1;
  125. }
  126. src_addr = info->qoi_addr;
  127. #if 0
  128. width = (src_addr[7]<<24) | (src_addr[6]<<16) | (src_addr[5]<<8) | (src_addr[4]<<0);
  129. height = (src_addr[11]<<24) | (src_addr[10]<<16) | (src_addr[9]<<8) | (src_addr[8]<<0);
  130. #else
  131. width = (src_addr[7]<<0) | (src_addr[6]<<8) | (src_addr[5]<<16) | (src_addr[4]<<24);
  132. height = (src_addr[11]<<0) | (src_addr[10]<<8) | (src_addr[9]<<16) | (src_addr[8]<<24);
  133. #endif
  134. if (width == 0 || width > QOI_MAX_WIDTH) {
  135. printf("ERR: %s qoi width(%d) out of range\n", __func__, width);
  136. return -1;
  137. }
  138. if (height == 0 || height > QOI_MAX_HEIGHT) {
  139. printf("ERR: %s qoi height(%d) out of range\n", __func__, height);
  140. return -1;
  141. }
  142. info->qoi_width = width;
  143. info->qoi_height = height;
  144. return 0;
  145. }
  146. int qoi_dec(qoi_info_t *info)
  147. {
  148. qoi_drv_t *qoi = &g_qoi;
  149. uint32_t int_status = 0;
  150. int ret = -1;
  151. if (!qoi) {
  152. printf("ERR: %s Invalid qoi\n", __func__);
  153. return -1;
  154. }
  155. if (!info || !info->qoi_addr || !info->dec_addr) {
  156. printf("ERR: %s Invalid info\n", __func__);
  157. return -1;
  158. }
  159. xSemaphoreTake(qoi->mutex_lock, portMAX_DELAY);
  160. sys_soft_reset(softreset_qoi);
  161. sys_soft_reset(softreset_qoi_core);
  162. /* dynamic parameters */
  163. qoi->cfg.src_w = (info->qoi_width % 2) ? (info->qoi_width + 1) : info->qoi_width;
  164. qoi->cfg.src_h = info->qoi_height;
  165. qoi->cfg.src_addr = (uint32_t)info->qoi_addr;
  166. qoi->cfg.wb_addr = (uint32_t)info->dec_addr;
  167. qoi->cfg.wb_size = info->qoi_width * info->qoi_height;
  168. qoi_config(qoi);
  169. xQueueReset(qoi->complete);
  170. qoi_enable(qoi);
  171. if (xQueueReceive(qoi->complete, &int_status, pdMS_TO_TICKS(100)) == pdTRUE) {
  172. if (int_status & BRESP_ERROR_INT)
  173. printf("ERR: %s QOI DEC BRESP ERROR\n", __func__);
  174. if (int_status & ERROR_INT)
  175. printf("ERR: %s QOI DEC ERROR\n", __func__);
  176. if (int_status & WB_FRAME_FINISH_INT) {
  177. info->dec_width = readl(qoi->base + DEC_WIDTH_RD_REG);
  178. info->dec_height = readl(qoi->base + DEC_HEIGHT_RD_REG);
  179. ret = 0;
  180. }
  181. } else {
  182. printf("ERR: %s QOI DEC TIMEOUT\n", __func__);
  183. }
  184. qoi_disable(qoi);
  185. xSemaphoreGive(qoi->mutex_lock);
  186. exit:
  187. return ret;
  188. }
  189. int qoi_dec_init(void)
  190. {
  191. qoi_drv_t *qoi = &g_qoi;
  192. qoi->mutex_lock = xSemaphoreCreateMutex();
  193. qoi->complete = xQueueCreate(1, 4);
  194. /* static parameters */
  195. qoi->cfg.wid = 3;
  196. qoi->cfg.rid = 5;
  197. qoi->cfg.min_burst = 2;
  198. qoi->cfg.max_burst = 6;
  199. qoi->cfg.fixed_burst_en = 0;
  200. qoi->cfg.src_w = 0;
  201. qoi->cfg.src_h = 0;
  202. qoi->cfg.src_addr = 0;
  203. qoi->cfg.wb_addr = 0;
  204. qoi->cfg.wb_size = 0;
  205. qoi->cfg.set_ints = QOI_INT_FLAGS;
  206. qoi->cfg.wbbvalid_dis = 0;
  207. qoi->cfg.awlen_bits = AWLEN_4BIT;
  208. qoi->cfg.arlen_bits = ARLEN_4BIT;
  209. qoi->cfg.wb_fifo_state_sel = 0;
  210. qoi->cfg.wrfifo_finish_sel = 0;
  211. request_irq(qoi->irqn, 0, qoi_intr_handler, qoi);
  212. return 0;
  213. }