Files
luban-lite-t3e-pro/packages/artinchip/mpp/ve/decoder/jpeg/jpeg_hal.c
2025-09-30 11:56:06 +08:00

634 lines
21 KiB
C

/*
* Copyright (C) 2020-2024 ArtInChip Technology Co. Ltd
*
* SPDX-License-Identifier: Apache-2.0
* author: <qi.xu@artinchip.com>
* Desc: jpeg register configuration
*/
#define LOG_TAG "jpeg_hal"
#include <string.h>
#include <unistd.h>
#include "jpeg_hal.h"
#include "ve.h"
#include "mpp_log.h"
#ifdef DEBUG_REGS
static void dump_regs(struct mjpeg_dec_ctx *s)
{
u32 i = 0;
for(i = 0; i< 0x2ff; i+=4) {
logi("addr: %08x, val: %08x", i, read_reg_u32(s->regs_base + JPG_REG_OFFSET_ADDR + i));
}
}
#endif
static void ve_config_ve_top_reg(struct mjpeg_dec_ctx *s)
{
int i;
logd("config mjpeg reg");
write_reg_u32(s->regs_base + VE_CLK_REG, 1);
// [9:8]: pic module reset, [3:2]: jpeg module reset
write_reg_u32(s->regs_base + VE_RST_REG, RST_JPG_PIC_MODULE);
for (i = 0; i < 10; i++) {
u32 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_JPG_EN_REG, 1);
}
static void config_crop_register(struct mjpeg_dec_ctx *s)
{
if(s->decoder.crop_en == 0)
return;
#ifndef AIC_VE_DRV_V10
int crop_out_x = 0;
// crop out addr is byte unit
if(s->pix_fmt == MPP_FMT_ARGB_8888 || s->pix_fmt == MPP_FMT_ABGR_8888
|| s->pix_fmt == MPP_FMT_RGBA_8888 || s->pix_fmt == MPP_FMT_BGRA_8888)
crop_out_x = s->decoder.output_x * 4;
else if(s->pix_fmt == MPP_FMT_RGB_888 || s->pix_fmt == MPP_FMT_BGR_888)
crop_out_x = s->decoder.output_x * 3;
else if(s->pix_fmt == MPP_FMT_RGB_565 || s->pix_fmt == MPP_FMT_BGR_565)
crop_out_x = s->decoder.output_x * 2;
write_reg_u32(s->regs_base + JPG_CLIP_REG, 2);
write_reg_u32(s->regs_base + JPG_CLIP_BASE_REG,
(s->decoder.crop_x << 16) | s->decoder.crop_y);
write_reg_u32(s->regs_base + JPG_CLIP_SIZE_REG,
(s->decoder.crop_width << 16) | s->decoder.crop_height);
write_reg_u32(s->regs_base + JPG_CLIP_OUT_BASE_REG,
(crop_out_x << 16) | s->decoder.output_y);
#endif
}
static void ve_config_pp_register(struct mjpeg_dec_ctx *s)
{
int rotate = MPP_ROTATION_GET(s->decoder.rotmir_flag);
int flip_v = MPP_FLIP_V_GET(s->decoder.rotmir_flag);
int flip_h = MPP_FLIP_H_GET(s->decoder.rotmir_flag);
jpg_reg_list *reg_list = (jpg_reg_list *)s->reg_list;
u32 *pval;
logd("config pp");
if (s->decoder.hor_scale || s->decoder.ver_scale) {
reg_list->_20_scale_reg.scale_en = 1;
reg_list->_20_scale_reg.h_ratio = s->decoder.hor_scale;
reg_list->_20_scale_reg.v_ratio = s->decoder.ver_scale;
pval = (u32 *)&reg_list->_20_scale_reg;
write_reg_u32(s->regs_base + JPG_SCALE_REG, *pval);
}
// rotate & mirror
if (rotate != MPP_ROTATION_0 || flip_v || flip_h) {
reg_list->_1c_rotmir_reg.rotmir_en = 1;
if (rotate == MPP_ROTATION_0)
reg_list->_1c_rotmir_reg.rotate = 0;
else if(rotate == MPP_ROTATION_270) // left rotate 90
reg_list->_1c_rotmir_reg.rotate = 1;
else if (rotate == MPP_ROTATION_180)
reg_list->_1c_rotmir_reg.rotate = 2;
else if (rotate == MPP_ROTATION_90)
reg_list->_1c_rotmir_reg.rotate = 3;
if (flip_v)
reg_list->_1c_rotmir_reg.mirror = 1;
else if (flip_h)
reg_list->_1c_rotmir_reg.mirror = 2;
else if(flip_v && flip_h)
reg_list->_1c_rotmir_reg.mirror = 3;
else
reg_list->_1c_rotmir_reg.mirror = 0;
pval = (u32 *)&reg_list->_1c_rotmir_reg;
write_reg_u32(s->regs_base + JPG_ROTMIR_REG, *pval);
}
#ifndef AIC_VE_DRV_V10
if(s->yuv2rgb) {
u32 val;
val = (255 << 8) | 1;
if(s->out_pix_fmt == MPP_FMT_ARGB_8888)
val |= 0;
else if(s->out_pix_fmt == MPP_FMT_ABGR_8888)
val |= (1<<1);
else if(s->out_pix_fmt == MPP_FMT_RGBA_8888)
val |= (2<<1);
else if(s->out_pix_fmt == MPP_FMT_BGRA_8888)
val |= (3<<1);
else if(s->out_pix_fmt == MPP_FMT_RGB_888)
val |= (4<<1);
else if(s->out_pix_fmt == MPP_FMT_BGR_888)
val |= (5<<1);
else if(s->out_pix_fmt == MPP_FMT_RGB_565)
val |= (6<<1);
else if(s->out_pix_fmt == MPP_FMT_BGR_565)
val |= (7<<1);
write_reg_u32(s->regs_base + JPG_RGB_REG, val);
}
#endif
}
static void ve_config_bitstream_register(struct mjpeg_dec_ctx *s, int offset, int is_last)
{
int busy = 1;
int bit_offset = 0;
// Note: if it is the last stream, we need add 1 here, or it will halt
int stream_num = 0;
#ifdef AIC_VE_DRV_V10
stream_num = (s->curr_packet->size + 255) / 256 +1;
#else
stream_num = (s->curr_packet->size + 255) / 256 +2;
#endif
u32 packet_base_addr = s->curr_packet->phy_base + s->curr_packet->phy_offset;
u32 base_addr = (packet_base_addr + offset) & (~7);
bit_offset = ((packet_base_addr + offset) - base_addr)*8;
// stream end address, 256 byte align
//u32 end_addr = packet_base_addr + (stream_num * 256);
//write_reg_u32(s->regs_base + JPG_STREAM_END_ADDR_REG, end_addr);
// stream read ptr
write_reg_u32(s->regs_base + JPG_STREAM_READ_PTR_REG, 0);
// bas address
write_reg_u32(s->regs_base + JPG_BAS_ADDR_REG, base_addr);
// start address of bitstream
write_reg_u32(s->regs_base + JPG_STREAM_START_ADDR_REG, base_addr);
// read data cnt 64x32bit
write_reg_u32(s->regs_base + JPG_DATA_CNT_REG, 64);
// bit request enable
write_reg_u32(s->regs_base + JPG_BITREQ_EN_REG, 1);
write_reg_u32(s->regs_base + JPG_CUR_POS_REG, 0);
write_reg_u32(s->regs_base + JPG_STREAM_NUM_REG, stream_num);
write_reg_u32(s->regs_base + JPG_MEM_SA_REG, 0);
write_reg_u32(s->regs_base + JPG_MEM_EA_REG, 0x7f);
write_reg_u32(s->regs_base + JPG_MEM_IA_REG, 0);
write_reg_u32(s->regs_base + JPG_MEM_HA_REG, 0);
write_reg_u32(s->regs_base + JPG_STATUS_REG, 0xf);
write_reg_u32(s->regs_base + JPG_REQ_REG, 1);
do {
busy = read_reg_u32(s->regs_base + JPG_BUSY_REG);
} while(busy == 1);
#ifndef AIC_VE_DRV_V10
write_reg_u32(s->regs_base + JPG_REQ_REG, 1);
do {
busy = read_reg_u32(s->regs_base + JPG_BUSY_REG);
} while(busy == 1);
#endif
// init sub module before start
#ifdef AIC_VE_DRV_V10
write_reg_u32(s->regs_base + JPG_SUB_CTRL_REG, 4);
write_reg_u32(s->regs_base + JPG_RBIT_OFFSET_REG, bit_offset);
write_reg_u32(s->regs_base + JPG_SUB_CTRL_REG, 2);
#else
write_reg_u32(s->regs_base + JPG_SUB_CTRL_REG, 2);
write_reg_u32(s->regs_base + JPG_RBIT_OFFSET_REG, bit_offset);
write_reg_u32(s->regs_base + JPG_SUB_CTRL_REG, 1);
#endif
}
/*
quant matrix should be stored in zigzag order, it is also the order parse from DQT
*/
static void ve_config_quant_matrix(struct mjpeg_dec_ctx *s)
{
int i;
jpg_reg_list *reg_list = (jpg_reg_list *)s->reg_list;
u32 *pval;
u32 val;
logd("config quant matrix");
for (int comp = 0; comp < 3; comp++) {
pval = (u32 *)&reg_list->_90_qmat_info_reg;
reg_list->_90_qmat_info_reg.qmat_auto = 1;
reg_list->_90_qmat_info_reg.qmat_enable = 1;
reg_list->_90_qmat_info_reg.qmat_idx = comp;
write_reg_u32(s->regs_base + JPG_QMAT_INFO_REG, *pval);
pval = (u32 *)&reg_list->_94_qmat_addr_reg;
reg_list->_94_qmat_addr_reg.qmat_idx = comp;
reg_list->_94_qmat_addr_reg.qmat_addr = 0;
write_reg_u32(s->regs_base + JPG_QMAT_ADDR_REG, *pval);
for (i = 0; i < 64; i++) {
val = s->q_matrixes[s->quant_index[comp]][i];
write_reg_u32(s->regs_base + JPG_QMAT_VAL_REG, val);
}
}
write_reg_u32(s->regs_base + JPG_QMAT_INFO_REG, 0);
}
/*
4 huffman tables, including DC_Luma\DC_Chroma\AC_LUMA\AC_Chroma
every table including 4 parts:
1)start_code: the minimum huffman code in all codes with the same code length,
for example, the minimum code of code length 3 is 3'b101, it is 16'Hffff if not exist
2)max_code: the max huffman code in all codes with the same code length, it is 16'Hffff if not exist
3)huff_offset: the symbol offset in huff_val, the symbol is the start code in code length i
4)huff_val: the symbols of all the huffman code
DC_Luma huff_val address 0-11
DC_Chroma huff_val address 12-23
AC_Luma huff_val address 24-185
AC_Chroma huff_val address 186-347
*/
static void ve_config_huffman_table(struct mjpeg_dec_ctx *s)
{
int i;
jpg_reg_list *reg_list = (jpg_reg_list *)s->reg_list;
u32 *pval;
u32 val;
logd("config huffman table");
// 1. config start_code
reg_list->_80_huff_info_reg.huff_auto = 1;
reg_list->_80_huff_info_reg.enable = 1;
reg_list->_80_huff_info_reg.huff_idx = 0;
pval = (u32 *)&reg_list->_80_huff_info_reg;
write_reg_u32(s->regs_base + JPG_HUFF_INFO_REG, *pval);
reg_list->_84_huff_addr_reg.huff_idx = 0;
reg_list->_84_huff_addr_reg.huff_addr = 0;
pval = (u32 *)&reg_list->_84_huff_addr_reg;
write_reg_u32(s->regs_base + JPG_HUFF_ADDR_REG, *pval);
// DC_LUMA -> DC_CHROMA -> AC_LUMA ->AC_CHROMA ->
for (i = 0; i < 16; i++) {
val = s->huffman_table[0][s->dc_index[0]].start_code[i];
write_reg_u32(s->regs_base + JPG_HUFF_VAL_REG, val);
}
for (i = 0; i < 16; i++) {
val = s->huffman_table[0][s->dc_index[1]].start_code[i];
write_reg_u32(s->regs_base + JPG_HUFF_VAL_REG, val);
}
for (i = 0; i < 16; i++) {
val = s->huffman_table[1][s->ac_index[0]].start_code[i];
write_reg_u32(s->regs_base + JPG_HUFF_VAL_REG, val);
}
for (i = 0; i < 16; i++) {
val = s->huffman_table[1][s->ac_index[1]].start_code[i];
write_reg_u32(s->regs_base + JPG_HUFF_VAL_REG, val);
}
// 2. config max code
logd("max_code");
pval = (u32 *)&reg_list->_80_huff_info_reg;
reg_list->_80_huff_info_reg.huff_auto = 1;
reg_list->_80_huff_info_reg.enable = 1;
reg_list->_80_huff_info_reg.huff_idx = 1;
write_reg_u32(s->regs_base + JPG_HUFF_INFO_REG, *pval);
pval = (u32 *)&reg_list->_84_huff_addr_reg;
reg_list->_84_huff_addr_reg.huff_idx = 1;
reg_list->_84_huff_addr_reg.huff_addr = 0;
write_reg_u32(s->regs_base + JPG_HUFF_ADDR_REG, *pval);
for (i = 0; i < 16; i++) {
val = s->huffman_table[0][s->dc_index[0]].max_code[i];
write_reg_u32(s->regs_base + JPG_HUFF_VAL_REG, val);
}
for (i = 0; i < 16; i++) {
val = s->huffman_table[0][s->dc_index[1]].max_code[i];
write_reg_u32(s->regs_base + JPG_HUFF_VAL_REG, val);
}
for (i = 0; i < 16; i++) {
val = s->huffman_table[1][s->ac_index[0]].max_code[i];
write_reg_u32(s->regs_base + JPG_HUFF_VAL_REG, val);
}
for (i = 0; i < 16; i++) {
val = s->huffman_table[1][s->ac_index[1]].max_code[i];
write_reg_u32(s->regs_base + JPG_HUFF_VAL_REG, val);
}
// 3. config huffman offset
pval = (u32 *)&reg_list->_80_huff_info_reg;
reg_list->_80_huff_info_reg.huff_auto = 1;
reg_list->_80_huff_info_reg.enable = 1;
reg_list->_80_huff_info_reg.huff_idx = 2;
write_reg_u32(s->regs_base + JPG_HUFF_INFO_REG, *pval);
pval = (u32 *)&reg_list->_84_huff_addr_reg;
reg_list->_84_huff_addr_reg.huff_idx = 2;
reg_list->_84_huff_addr_reg.huff_addr = 0;
write_reg_u32(s->regs_base + JPG_HUFF_ADDR_REG, *pval);
for (i = 0; i < 16; i++) {
val = s->huffman_table[0][s->dc_index[0]].offset[i];
write_reg_u32(s->regs_base + JPG_HUFF_VAL_REG, val);
}
for (i = 0; i < 16; i++) {
val = s->huffman_table[0][s->dc_index[1]].offset[i];
write_reg_u32(s->regs_base + JPG_HUFF_VAL_REG, val);
}
for (i = 0; i < 16; i++) {
val = s->huffman_table[1][s->ac_index[0]].offset[i];
write_reg_u32(s->regs_base + JPG_HUFF_VAL_REG, val);
}
for (i = 0; i < 16; i++) {
val = s->huffman_table[1][s->ac_index[1]].offset[i];
write_reg_u32(s->regs_base + JPG_HUFF_VAL_REG, val);
}
// 4.1 config huffman val (dc luma)
logd("huff_val dc_luma");
pval = (u32 *)&reg_list->_80_huff_info_reg;
reg_list->_80_huff_info_reg.huff_auto = 1;
reg_list->_80_huff_info_reg.enable = 1;
reg_list->_80_huff_info_reg.huff_idx = 3;
write_reg_u32(s->regs_base + JPG_HUFF_INFO_REG, *pval);
pval = (u32 *)&reg_list->_84_huff_addr_reg;
reg_list->_84_huff_addr_reg.huff_idx = 3;
reg_list->_84_huff_addr_reg.huff_addr = 0;
write_reg_u32(s->regs_base + JPG_HUFF_ADDR_REG, *pval);
if (s->huffman_table[0][s->dc_index[0]].total_code > 12) {
loge("dc luma code num : %d", s->huffman_table[0][s->dc_index[0]].total_code);
//abort();
}
for (i = 0; i < s->huffman_table[0][s->dc_index[0]].total_code; i++) {
val = s->huffman_table[0][s->dc_index[0]].symbol[i];
write_reg_u32(s->regs_base + JPG_HUFF_VAL_REG, val);
}
// 4.2 config huffman val (dc chroma)
logd("huff_val dc_chroma");
pval = (u32 *)&reg_list->_80_huff_info_reg;
reg_list->_80_huff_info_reg.huff_auto = 1;
reg_list->_80_huff_info_reg.enable = 1;
reg_list->_80_huff_info_reg.huff_idx = 3;
write_reg_u32(s->regs_base + JPG_HUFF_INFO_REG, *pval);
logv("write JPG_HUFF_INFO_REG %02X %02X", JPG_HUFF_INFO_REG, *pval);
pval = (u32 *)&reg_list->_84_huff_addr_reg;
reg_list->_84_huff_addr_reg.huff_idx = 3;
reg_list->_84_huff_addr_reg.huff_addr = 12;
write_reg_u32(s->regs_base + JPG_HUFF_ADDR_REG, *pval);
logv("write JPG_HUFF_ADDR_REG %02X %02X", JPG_HUFF_ADDR_REG, *pval);
if (s->huffman_table[0][s->dc_index[1]].total_code > 12) {
loge("dc chroma code num : %d", s->huffman_table[0][s->dc_index[1]].total_code);
//abort();
}
for (i = 0; i < s->huffman_table[0][s->dc_index[1]].total_code; i++) {
val = s->huffman_table[0][s->dc_index[1]].symbol[i];
write_reg_u32(s->regs_base + JPG_HUFF_VAL_REG, val);
logv("write JPG_HUFF_VAL_REG %02X %02X", JPG_HUFF_VAL_REG, val);
}
// 4.3 config huffman val (ac luma)
pval = (u32 *)&reg_list->_80_huff_info_reg;
reg_list->_80_huff_info_reg.huff_auto = 1;
reg_list->_80_huff_info_reg.enable = 1;
reg_list->_80_huff_info_reg.huff_idx = 3;
write_reg_u32(s->regs_base + JPG_HUFF_INFO_REG, *pval);
pval = (u32 *)&reg_list->_84_huff_addr_reg;
reg_list->_84_huff_addr_reg.huff_idx = 3;
reg_list->_84_huff_addr_reg.huff_addr = 24;
write_reg_u32(s->regs_base + JPG_HUFF_ADDR_REG, *pval);
if (s->huffman_table[1][s->ac_index[0]].total_code > 162) {
loge("ac luma code num : %d", s->huffman_table[1][s->ac_index[0]].total_code);
//abort();
}
for (i = 0; i < s->huffman_table[1][s->ac_index[0]].total_code; i++) {
val = s->huffman_table[1][s->ac_index[0]].symbol[i];
write_reg_u32(s->regs_base + JPG_HUFF_VAL_REG, val);
}
// 4.4 config huffman val (ac chroma)
pval = (u32 *)&reg_list->_80_huff_info_reg;
reg_list->_80_huff_info_reg.huff_auto = 1;
reg_list->_80_huff_info_reg.enable = 1;
reg_list->_80_huff_info_reg.huff_idx = 3;
write_reg_u32(s->regs_base + JPG_HUFF_INFO_REG, *pval);
pval = (u32 *)&reg_list->_84_huff_addr_reg;
reg_list->_84_huff_addr_reg.huff_idx = 3;
reg_list->_84_huff_addr_reg.huff_addr = 186;
write_reg_u32(s->regs_base + JPG_HUFF_ADDR_REG, *pval);
if (s->huffman_table[1][s->ac_index[1]].total_code > 162) {
loge("dc chroma code num : %d", s->huffman_table[1][s->ac_index[1]].total_code);
//abort();
}
for (i = 0; i < s->huffman_table[1][s->ac_index[1]].total_code; i++) {
val = s->huffman_table[1][s->ac_index[1]].symbol[i];
write_reg_u32(s->regs_base + JPG_HUFF_VAL_REG, val);
}
// clear
write_reg_u32(s->regs_base + JPG_HUFF_INFO_REG, 0);
}
static void config_jpeg_picture_info_register(struct mjpeg_dec_ctx *s)
{
u32 *pval;
logd("config picture info register");
struct frame_format_reg frame_format;
memset(&frame_format, 0, sizeof(int));
struct frame_size_reg frame_size;
memset(&frame_size, 0, sizeof(int));
frame_size.pic_xsize = s->rm_h_real_size[0];
frame_size.pic_ysize = s->rm_v_real_size[0];
frame_format.cbcr_interleaved = s->uv_interleave;
#ifdef AIC_VE_DRV_V10
frame_format.stride = s->curr_frame->mpp_frame.buf.stride[0];
#else
if(MPP_ROTATION_GET(s->decoder.rotmir_flag) == MPP_ROTATION_270 ||
MPP_ROTATION_GET(s->decoder.rotmir_flag) == MPP_ROTATION_90)
frame_format.stride = s->curr_frame->mpp_frame.buf.size.height;
else
frame_format.stride = s->curr_frame->mpp_frame.buf.stride[0];
#endif
if (s->pix_fmt == MPP_FMT_YUV420P || s->pix_fmt == MPP_FMT_NV12 || s->pix_fmt == MPP_FMT_NV21) {
frame_format.color_mode = 0;
} else if(s->pix_fmt == MPP_FMT_YUV444P) {
frame_format.color_mode = 3;
} else if (s->pix_fmt == MPP_FMT_YUV400) {
frame_format.color_mode = 4;
} else if (s->pix_fmt == MPP_FMT_YUV422P || s->pix_fmt == MPP_FMT_NV16 || s->pix_fmt == MPP_FMT_NV61) {
// YUV422 rotate 90/270 is YUV224
frame_format.color_mode = 1;
if(MPP_ROTATION_GET(s->decoder.rotmir_flag) == MPP_ROTATION_270 ||
MPP_ROTATION_GET(s->decoder.rotmir_flag) == MPP_ROTATION_90)
frame_format.color_mode = 2; // yuv224, display not support
} else {
logi("rgb format(%d)", s->pix_fmt);
frame_format.color_mode = 4;
}
pval = (u32 *)&frame_format;
write_reg_u32(s->regs_base + FRAME_FORMAT_REG(0), *pval);
pval = (u32 *)&frame_size;
write_reg_u32(s->regs_base + FRAME_SIZE_REG(0), *pval);
write_reg_u32(s->regs_base + FRAME_YADDR_REG(0), s->curr_frame->phy_addr[0]);
write_reg_u32(s->regs_base + FRAME_CBADDR_REG(0), s->curr_frame->phy_addr[1]);
write_reg_u32(s->regs_base + FRAME_CRADDR_REG(0), s->curr_frame->phy_addr[2]);
#ifndef AIC_VE_DRV_V10
write_reg_u32(s->regs_base + PIC_INFO_WRITE_END_REG, 0);
#endif
}
static void config_header_info(struct mjpeg_dec_ctx *s)
{
jpg_reg_list *reg_list = (jpg_reg_list *)s->reg_list;
u32 *pval;
write_reg_u32(s->regs_base + JPG_START_POS_REG, 0);
reg_list->_10_ctrl_reg.encode = 0;
reg_list->_10_ctrl_reg.dir = 0;
reg_list->_10_ctrl_reg.use_huff_en = s->have_dht;
reg_list->_10_ctrl_reg.dc_huff_idx = (s->dc_index[0] <<2) | (s->dc_index[1] <<1) | s->dc_index[2];
reg_list->_10_ctrl_reg.ac_huff_idx = (s->ac_index[0] <<2) | (s->ac_index[1] <<1) | s->ac_index[2];
pval = (u32 *)&reg_list->_10_ctrl_reg;
write_reg_u32(s->regs_base + JPG_CTRL_REG, *pval);
logd("picture size");
int mcu_w = s->h_count[0] * 8;
int mcu_h = s->v_count[0] * 8;
reg_list->_14_size_reg.jpeg_hsize = (s->width + mcu_w - 1) / mcu_w * mcu_w;
reg_list->_14_size_reg.jpeg_vsize = (s->height + mcu_h - 1) / mcu_h * mcu_h;
pval = (u32 *)&reg_list->_14_size_reg;
write_reg_u32(s->regs_base + JPG_SIZE_REG, *pval);
int tatal_blks = s->h_count[0] * s->v_count[0] +
s->h_count[1] * s->v_count[1] + s->h_count[2] * s->v_count[2];
reg_list->_18_mcu_reg.y_h_size = s->h_count[0];
reg_list->_18_mcu_reg.y_v_size = s->v_count[0];
reg_list->_18_mcu_reg.cb_h_size = s->h_count[1];
reg_list->_18_mcu_reg.cb_v_size = s->v_count[1];
reg_list->_18_mcu_reg.cr_h_size = s->h_count[1];
reg_list->_18_mcu_reg.cr_v_size = s->v_count[1];
reg_list->_18_mcu_reg.comp_num = s->nb_components;
reg_list->_18_mcu_reg.blk_num = tatal_blks;
pval = (u32 *)&reg_list->_18_mcu_reg;
write_reg_u32(s->regs_base + JPG_MCU_INFO_REG, *pval);
int num = 12 / tatal_blks;
#ifdef AIC_VE_DRV_V10
num = num > 4? 4: num;
#else
if(s->yuv2rgb)
num = 0;
else
num = num > 4? 3: num - 1;
#endif
write_reg_u32(s->regs_base + JPG_HANDLE_NUM_REG, num > 4? 4: num);
write_reg_u32(s->regs_base + JPG_UV_REG, s->uv_interleave);
write_reg_u32(s->regs_base + JPG_FRAME_IDX_REG, 0);
write_reg_u32(s->regs_base + JPG_RST_INTERVAL_REG, s->restart_interval);
#ifdef AIC_VE_DRV_V10
write_reg_u32(s->regs_base + JPG_INTRRUPT_EN_REG, 0);
#else
write_reg_u32(s->regs_base + JPG_INTRRUPT_EN_REG, 7);
#endif
}
int ve_decode_jpeg(struct mjpeg_dec_ctx *s, int byte_offset)
{
unsigned int status;
ve_get_client();
ve_reset();
// 1. config ve top
ve_config_ve_top_reg(s);
// 2. config header info
config_header_info(s);
config_jpeg_picture_info_register(s);
// 3. config quant matrix
ve_config_quant_matrix(s);
// 4. config huffman table
if(s->have_dht) {
ve_config_huffman_table(s);
}
// 5. config post process
ve_config_pp_register(s);
config_crop_register(s);
// 6. config bitstream
ve_config_bitstream_register(s, byte_offset, 1);
logi("======= config all regs ==========");
//dump_regs(s);
// 7. decode start
write_reg_u32(s->regs_base + JPG_START_REG, 1);
if(ve_wait(&status) < 0) {
loge("ve wait irq timeout");
logi("read JPG_STATUS_REG %x", read_reg_u32(s->regs_base + JPG_STATUS_REG));
ve_reset();
ve_put_client();
return -1;
}
if(status > 1) {
int errmb = read_reg_u32(s->regs_base + 0x08);
loge("status error:%x, errmb: %d", status, errmb);
ve_reset();
ve_put_client();
return -1;
}
logi("ve status %x, mb: %d", status, read_reg_u32(s->regs_base + 0x08));
logi("read JPG_CYCLES_REG %x", read_reg_u32(s->regs_base + JPG_CYCLES_REG));
// disable jpeg module
write_reg_u32(s->regs_base + VE_JPG_EN_REG, 0);
ve_put_client();
return 0;
}