Files
luban-lite-t3e-pro/packages/artinchip/mpp/ve/decoder/png/png_hal.c
刘可亮 803cac77d5 V1.0.6
2024-09-03 11:16:08 +08:00

223 lines
6.1 KiB
C

/*
* Copyright (C) 2020-2024 ArtInChip Technology Co. Ltd
*
* SPDX-License-Identifier: Apache-2.0
* author: <qi.xu@artinchip.com>
* Desc: png register configure
*
*/
#define LOG_TAG "png_hal"
#include <aic_core.h>
#include "png_hal.h"
#include "ve.h"
#include "ve_top_register.h"
#include "mpp_log.h"
#ifdef DEBUG_REGS
static void dump_regs(struct png_dec_ctx *s)
{
u32 i = 0;
for(i = 0; i< 0xff; i+=4) {
logi("addr: %08x, val: %08x", i, read_reg_u32(s->regs_base + PNG_REG_OFFSET_ADDR + i));
}
}
#endif
void config_ve_top_reg(struct png_dec_ctx *s)
{
int i;
u32 val;
write_reg_u32(s->regs_base + VE_CLK_REG, 1);
// [9:8]: pic module reset; [5:4]: png module reset
write_reg_u32(s->regs_base + VE_RST_REG, RST_PNG_PIC_MODULE);
for (i = 0; i < 10; i++) {
val = read_reg_u32(s->regs_base + VE_RST_REG);
if ((val>>16) == 0)
break;
}
write_reg_u32(s->regs_base + VE_INIT_REG, 1);
write_reg_u32(s->regs_base + VE_IRQ_REG, 1);
write_reg_u32(s->regs_base + VE_PNG_EN_REG, 1);
}
void png_reset(struct png_dec_ctx *s)
{
write_reg_u32(s->regs_base + INFLATE_RESET_REG, 1);
}
static int set_bitstream_and_wait(struct png_dec_ctx *s, unsigned char *data, int length)
{
int offset = s->vbv_offset;
int is_first = 1;
int is_last = 1;
unsigned int status = 0;
struct png_register_list *reg_list = (struct png_register_list *)s->reg_list;
u32 *pval;
u32 val;
logd("config bit stream");
val = s->idat_mpp_buf->phy_addr;
write_reg_u32(s->regs_base + INPUT_BS_START_ADDR_REG, val);
val = s->idat_mpp_buf->phy_addr + s->idat_mpp_buf->size - 1;
write_reg_u32(s->regs_base + INPUT_BS_END_ADDR_REG, val);
write_reg_u32(s->regs_base + INPUT_BS_OFFSET_REG, offset * 8);
write_reg_u32(s->regs_base + INPUT_BS_LENGTH_REG, length * 8);
pval = (u32 *)&reg_list->_48_inflate_valid;
reg_list->_48_inflate_valid.first = is_first;
reg_list->_48_inflate_valid.last = is_last;
reg_list->_48_inflate_valid.valid = 1;
write_reg_u32(s->regs_base + INPUT_BS_DATA_VALID_REG, *pval);
// wait IRQ
if(ve_wait(&status) < 0) {
aicos_msleep(10);
ve_reset();
loge("png timeout");
return -1;
}
if(status & PNG_ERROR) {
loge("png decode error, status: %08x", status);
aicos_msleep(10);
ve_reset();
return -1;
} else if(status & PNG_FINISH) {
return 0;
} else if(status & PNG_BITREQ) {
loge("png bit request, not support now");
// TODO
return -1;
}
return 0;
}
static void png_set_clip_info(struct png_dec_ctx *s)
{
if(s->decoder.crop_en == 0)
return;
#ifndef AIC_VE_DRV_V10
write_reg_u32(s->regs_base + PNG_CLIP_BASE_REG, s->decoder.crop_x << 16 | s->decoder.crop_y);
write_reg_u32(s->regs_base + PNG_CLIP_SIZE_REG, (1U << 31) | (s->decoder.crop_width << 16) | s->decoder.crop_height);
#endif
}
int png_hardware_decode(struct png_dec_ctx *s, unsigned char *buf, int length)
{
struct png_register_list *reg_list = (struct png_register_list *)s->reg_list;
u32 *pval;
u32 val;
memset(reg_list, 0, sizeof(struct png_register_list));
s->hw_size = s->stride * s->height;
ve_get_client();
// 1. reset ve
config_ve_top_reg(s);
png_reset(s);
// 2.set png info
pval = (u32 *)&reg_list->_10_png_ctrl;
reg_list->_10_png_ctrl.bit_depth = s->bit_depth;
reg_list->_10_png_ctrl.color_type = s->color_type;
reg_list->_10_png_ctrl.dec_type = 1;
write_reg_u32(s->regs_base + PNG_CTRL_REG, *pval);
// 3. set picture size
pval = (u32 *)&reg_list->_14_png_size;
reg_list->_14_png_size.width = s->width;
reg_list->_14_png_size.height = s->height;
write_reg_u32(s->regs_base + PNG_SIZE_REG, *pval);
write_reg_u32(s->regs_base + PNG_STRIDE_REG, s->curr_frame->mpp_frame.buf.stride[0]);
int format = 0;
if(s->pix_fmt == MPP_FMT_RGBA_8888)
format = RGBA8888;
else if(s->pix_fmt == MPP_FMT_BGRA_8888)
format = BGRA8888;
else if(s->pix_fmt == MPP_FMT_ABGR_8888)
format = ABGR8888;
else if(s->pix_fmt == MPP_FMT_ARGB_8888)
format = ARGB8888;
else if(s->pix_fmt == MPP_FMT_BGR_888)
format = BGR888;
else if(s->pix_fmt == MPP_FMT_RGB_888)
format = RGB888;
else if(s->pix_fmt == MPP_FMT_BGR_565)
format = BGR565;
else if(s->pix_fmt == MPP_FMT_RGB_565)
format = RGB565;
write_reg_u32(s->regs_base + PNG_FORMAT_REG, format);
// 4. set output buffer
int channel = (s->pix_fmt == MPP_FMT_BGR_888 || s->pix_fmt == MPP_FMT_RGB_888) ? 3 : 4;
int stride = s->curr_frame->mpp_frame.buf.stride[0];
int out_offset = s->decoder.output_y * stride + s->decoder.output_x * channel;
val = s->curr_frame->phy_addr[0] + out_offset;
write_reg_u32(s->regs_base + OUTPUT_BUFFER_ADDR_REG, val);
#ifdef AIC_VE_DRV_V10
write_reg_u32(s->regs_base + OUTPUT_BUFFER_LENGTH_REG, s->height * stride);
#else
write_reg_u32(s->regs_base + OUTPUT_BUFFER_LENGTH_REG, s->curr_frame->phy_addr[0] + s->height * stride);
#endif
// 5. set LZ77 buffer 32K
val = s->lz77_mpp_buf->phy_addr;
write_reg_u32(s->regs_base + INFLATE_WINDOW_BUFFER_ADDR_REG, val);
// PNG filter line buffer address
val = s->filter_mpp_buf->phy_addr;
write_reg_u32(s->regs_base + PNG_FILTER_LINE_BUF_ADDR_REG, val);
// 6. set memory register for palette
if (s->color_type == PNG_COLOR_TYPE_PALETTE) {
unsigned char* palette_buf = (unsigned char*)&s->palette;
memcpy(s->palette_mpp_buf->vir_addr, palette_buf, 256 * 4);
ve_buffer_sync(s->palette_mpp_buf, CACHE_CLEAN);
val = s->palette_mpp_buf->phy_addr;
write_reg_u32(s->regs_base + PNG_PNG_PALETTE_ADDR_REG, val);
}
// 7. set clip info
png_set_clip_info(s);
// 8. decode start
logd("config start");
write_reg_u32(s->regs_base + INFLATE_INTERRUPT_REG, 15);
write_reg_u32(s->regs_base + INFLATE_STATUS_REG, 15);
write_reg_u32(s->regs_base + INFLATE_START_REG, 7);
// 9.set bitstream
if (set_bitstream_and_wait(s, buf, length)) {
ve_put_client();
return -1;
}
val = read_reg_u32(s->regs_base + PNG_COUNT_REG);
logi("png clock: %d", val);
// disable png module
write_reg_u32(s->regs_base + VE_PNG_EN_REG, 0);
ve_put_client();
return 0;
}