mirror of
https://gitee.com/Vancouver2017/luban-lite-t3e-pro.git
synced 2025-12-15 02:48:54 +00:00
634 lines
21 KiB
C
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 *)®_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 *)®_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 *)®_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 *)®_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 *)®_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 *)®_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 *)®_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 *)®_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 *)®_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 *)®_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 *)®_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 *)®_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 *)®_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 *)®_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 *)®_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 *)®_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 *)®_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 *)®_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 *)®_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 *)®_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 *)®_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;
|
|
}
|