| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255 |
- #include "chip.h"
- #include "board.h"
- #include "qoi_dec.h"
- #define DEC_CTRL_REG 0x00
- #define DEC_SIZE_REG 0x04
- #define DEC_RD_ADDR_REG 0x08
- #define DEC_WB_ADDR_REG 0x0c
- #define DEC_WB_DATA_PER_FRAME_REG 0x10
- #define DEC_INT_EN_REG 0x14
- #define DEC_INT_CLR_REG 0x18
- #define DEC_STATUS_REG 0x1c
- #define DEC_WIDTH_RD_REG 0x20
- #define DEC_HEIGHT_RD_REG 0x24
- #define WB_FRAME_FINISH_INT (1<<3)
- #define BRESP_ERROR_INT (1<<2)
- #define FINISH_INT (1<<1)
- #define ERROR_INT (1<<0)
- #define QOI_INT_FLAGS (WB_FRAME_FINISH_INT | BRESP_ERROR_INT | FINISH_INT | ERROR_INT)
- #define QOI_MAX_WIDTH 1920
- #define QOI_MAX_HEIGHT 1080
- typedef enum _awlen_bits {
- AWLEN_4BIT = 4,
- AWLEN_5BIT = 5,
- AWLEN_6BIT = 6,
- AWLEN_7BIT = 7,
- AWLEN_8BIT = 8,
- } awlen_bits_t;
- typedef enum _arlen_bits {
- ARLEN_4BIT = 4,
- ARLEN_5BIT = 5,
- ARLEN_6BIT = 6,
- ARLEN_7BIT = 7,
- ARLEN_8BIT = 8,
- } arlen_bits_t;
- typedef struct _qoi_cfg {
- uint32_t wid;
- uint32_t rid;
- uint32_t min_burst;
- uint32_t max_burst;
- uint32_t fixed_burst_en;
- uint32_t src_w;
- uint32_t src_h;
- uint32_t src_addr;
- uint32_t wb_addr;
- uint32_t wb_size;
- uint32_t set_ints;
- uint32_t wbbvalid_dis;
- uint32_t wb_fifo_state_sel;
- uint32_t wrfifo_finish_sel;
- awlen_bits_t awlen_bits;
- arlen_bits_t arlen_bits;
- }qoi_cfg_t;
- typedef struct {
- uint32_t base;
- int irqn;
- SemaphoreHandle_t mutex_lock;
- QueueHandle_t complete;
- qoi_cfg_t cfg;
- } qoi_drv_t;
- static qoi_drv_t g_qoi = {
- .base = REGS_QOI_BASE,
- .irqn = QOI_IRQn,
- .mutex_lock = NULL,
- .complete = NULL,
- };
- static void qoi_enable(qoi_drv_t *qoi)
- {
- uint32_t val;
- val = readl(qoi->base + DEC_CTRL_REG);
- val |= 0x1;
- writel(val, qoi->base + DEC_CTRL_REG);
- }
- static void qoi_disable(qoi_drv_t *qoi)
- {
- uint32_t val;
- val = readl(qoi->base + DEC_CTRL_REG);
- val &= ~0x1;
- writel(val, qoi->base + DEC_CTRL_REG);
- }
- static void qoi_clear_intr(qoi_drv_t *qoi, uint32_t flags)
- {
- writel(flags, qoi->base + DEC_INT_CLR_REG);
- writel(0, qoi->base + DEC_INT_CLR_REG);
- }
- static void qoi_intr_handler(void *param)
- {
- qoi_drv_t *qoi = (qoi_drv_t *)param;
- uint32_t status;
- if (qoi) {
- status = readl(qoi->base + DEC_STATUS_REG);
- qoi_clear_intr(qoi, status);
- if (status & (BRESP_ERROR_INT | ERROR_INT | WB_FRAME_FINISH_INT)) {
- xQueueSendFromISR(qoi->complete, &status, 0);
- }
- }
- }
- static void qoi_config(qoi_drv_t *qoi)
- {
- uint32_t val;
- val = ((qoi->cfg.wbbvalid_dis & 0x1) << 28) |
- ((qoi->cfg.awlen_bits & 0xf) << 24) |
- ((qoi->cfg.wid & 0xf) << 20) |
- ((qoi->cfg.rid & 0xf) << 16) |
- ((qoi->cfg.arlen_bits & 0xf) << 12) |
- ((qoi->cfg.min_burst & 0xf) << 8) |
- ((qoi->cfg.max_burst & 0xf) << 4) |
- ((qoi->cfg.wb_fifo_state_sel & 0x1) << 3) |
- ((qoi->cfg.wrfifo_finish_sel & 0x1) << 2) |
- ((qoi->cfg.fixed_burst_en & 0x1) << 1);
- writel(val, qoi->base + DEC_CTRL_REG);
- val = ((qoi->cfg.src_h & 0xfff) << 12) | ((qoi->cfg.src_w & 0xfff) << 0);
- writel(val, qoi->base + DEC_SIZE_REG);
- writel(qoi->cfg.src_addr, qoi->base + DEC_RD_ADDR_REG);
- writel(qoi->cfg.wb_addr, qoi->base + DEC_WB_ADDR_REG);
- writel(qoi->cfg.wb_size, qoi->base + DEC_WB_DATA_PER_FRAME_REG);
- writel(qoi->cfg.set_ints, qoi->base + DEC_INT_EN_REG);
- }
- int qoi_get_img_size(qoi_info_t *info)
- {
- uint32_t width, height;
- char *src_addr;
- if (!info || !info->qoi_addr) {
- printf("ERR: %s Invalid info\n", __func__);
- return -1;
- }
- src_addr = info->qoi_addr;
- #if 0
- width = (src_addr[7]<<24) | (src_addr[6]<<16) | (src_addr[5]<<8) | (src_addr[4]<<0);
- height = (src_addr[11]<<24) | (src_addr[10]<<16) | (src_addr[9]<<8) | (src_addr[8]<<0);
- #else
- width = (src_addr[7]<<0) | (src_addr[6]<<8) | (src_addr[5]<<16) | (src_addr[4]<<24);
- height = (src_addr[11]<<0) | (src_addr[10]<<8) | (src_addr[9]<<16) | (src_addr[8]<<24);
- #endif
- if (width == 0 || width > QOI_MAX_WIDTH) {
- printf("ERR: %s qoi width(%d) out of range\n", __func__, width);
- return -1;
- }
- if (height == 0 || height > QOI_MAX_HEIGHT) {
- printf("ERR: %s qoi height(%d) out of range\n", __func__, height);
- return -1;
- }
- info->qoi_width = width;
- info->qoi_height = height;
- return 0;
- }
- int qoi_dec(qoi_info_t *info)
- {
- qoi_drv_t *qoi = &g_qoi;
- uint32_t int_status = 0;
- int ret = -1;
- if (!qoi) {
- printf("ERR: %s Invalid qoi\n", __func__);
- return -1;
- }
- if (!info || !info->qoi_addr || !info->dec_addr) {
- printf("ERR: %s Invalid info\n", __func__);
- return -1;
- }
- xSemaphoreTake(qoi->mutex_lock, portMAX_DELAY);
- sys_soft_reset(softreset_qoi);
- sys_soft_reset(softreset_qoi_core);
- /* dynamic parameters */
- qoi->cfg.src_w = (info->qoi_width % 2) ? (info->qoi_width + 1) : info->qoi_width;
- qoi->cfg.src_h = info->qoi_height;
- qoi->cfg.src_addr = (uint32_t)info->qoi_addr;
- qoi->cfg.wb_addr = (uint32_t)info->dec_addr;
- qoi->cfg.wb_size = info->qoi_width * info->qoi_height;
- qoi_config(qoi);
- xQueueReset(qoi->complete);
- qoi_enable(qoi);
- if (xQueueReceive(qoi->complete, &int_status, pdMS_TO_TICKS(100)) == pdTRUE) {
- if (int_status & BRESP_ERROR_INT)
- printf("ERR: %s QOI DEC BRESP ERROR\n", __func__);
- if (int_status & ERROR_INT)
- printf("ERR: %s QOI DEC ERROR\n", __func__);
- if (int_status & WB_FRAME_FINISH_INT) {
- info->dec_width = readl(qoi->base + DEC_WIDTH_RD_REG);
- info->dec_height = readl(qoi->base + DEC_HEIGHT_RD_REG);
- ret = 0;
- }
- } else {
- printf("ERR: %s QOI DEC TIMEOUT\n", __func__);
- }
- qoi_disable(qoi);
- xSemaphoreGive(qoi->mutex_lock);
- exit:
- return ret;
- }
- int qoi_dec_init(void)
- {
- qoi_drv_t *qoi = &g_qoi;
- qoi->mutex_lock = xSemaphoreCreateMutex();
- qoi->complete = xQueueCreate(1, 4);
- /* static parameters */
- qoi->cfg.wid = 3;
- qoi->cfg.rid = 5;
- qoi->cfg.min_burst = 2;
- qoi->cfg.max_burst = 6;
- qoi->cfg.fixed_burst_en = 0;
- qoi->cfg.src_w = 0;
- qoi->cfg.src_h = 0;
- qoi->cfg.src_addr = 0;
- qoi->cfg.wb_addr = 0;
- qoi->cfg.wb_size = 0;
- qoi->cfg.set_ints = QOI_INT_FLAGS;
- qoi->cfg.wbbvalid_dis = 0;
- qoi->cfg.awlen_bits = AWLEN_4BIT;
- qoi->cfg.arlen_bits = ARLEN_4BIT;
- qoi->cfg.wb_fifo_state_sel = 0;
- qoi->cfg.wrfifo_finish_sel = 0;
- request_irq(qoi->irqn, 0, qoi_intr_handler, qoi);
- return 0;
- }
|