/* * Copyright (C) 2020-2022 Artinchip Technology Co. Ltd * * author: author: * Desc: jpeg register configuration * */ #define LOG_TAG "jpeg_hal" #include #include #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; frame_format.stride = s->curr_frame->mpp_frame.buf.stride[0]; 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; }