mirror of
https://gitee.com/Vancouver2017/luban-lite.git
synced 2025-12-26 14:08:53 +00:00
V1.0.6
This commit is contained in:
244
packages/artinchip/mpp/ve/encoder/jpeg/jpeg_enc_hal.c
Normal file
244
packages/artinchip/mpp/ve/encoder/jpeg/jpeg_enc_hal.c
Normal file
@@ -0,0 +1,244 @@
|
||||
/*
|
||||
* Copyright (C) 2020-2024 ArtInChip Technology Co. Ltd
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Author: <qi.xu@artinchip.com>
|
||||
* Desc: jpeg encoder hal
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "ve_top_register.h"
|
||||
#include "jpeg_register.h"
|
||||
#include "mpp_log.h"
|
||||
#include "ve_buffer.h"
|
||||
#include "ve.h"
|
||||
#include "jpeg_enc_ctx.h"
|
||||
|
||||
static void config_ve_top_reg(struct jpeg_ctx *s)
|
||||
{
|
||||
logd("config mjpeg reg");
|
||||
write_reg_u32(s->regs_base + VE_CLK_REG, 1);
|
||||
write_reg_u32(s->regs_base + VE_RST_REG, RST_JPG_PIC_MODULE);
|
||||
|
||||
while (1) {
|
||||
uint32_t 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_header_info(struct jpeg_ctx *s)
|
||||
{
|
||||
uint32_t val = 0;
|
||||
write_reg_u32(s->regs_base + JPG_START_POS_REG, 0);
|
||||
|
||||
write_reg_u32(s->regs_base + JPG_CTRL_REG, (3 << 12) | (3 << 8) | (3 << 3));
|
||||
|
||||
int width_align = (s->width + 15) & (~15);
|
||||
val = s->height | (width_align << 16);
|
||||
write_reg_u32(s->regs_base + JPG_SIZE_REG, val);
|
||||
|
||||
int total_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];
|
||||
val = s->v_count[2] | (s->h_count[2] << 2) |
|
||||
(s->v_count[1] << 4) | (s->h_count[1] << 6) |
|
||||
(s->v_count[0] << 8) | (s->h_count[0] << 10) |
|
||||
(s->comp_num << 12) | (total_blks << 16);
|
||||
write_reg_u32(s->regs_base + JPG_MCU_INFO_REG, val);
|
||||
|
||||
val = 12 / total_blks;
|
||||
write_reg_u32(s->regs_base + JPG_HANDLE_NUM_REG, val);
|
||||
|
||||
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, 0);
|
||||
write_reg_u32(s->regs_base + JPG_INTRRUPT_EN_REG, 0);
|
||||
}
|
||||
|
||||
static void config_picture_info_register(struct jpeg_ctx *s)
|
||||
{
|
||||
uint32_t val = 0;
|
||||
uint32_t color_mode = 0;
|
||||
|
||||
if (s->cur_frame->buf.format == MPP_FMT_YUV420P || s->cur_frame->buf.format == MPP_FMT_NV12) {
|
||||
color_mode = 0;
|
||||
} else if (s->cur_frame->buf.format == MPP_FMT_YUV444P) {
|
||||
color_mode = 3;
|
||||
} else if (s->cur_frame->buf.format == MPP_FMT_YUV400) {
|
||||
color_mode = 4;
|
||||
} else if (s->cur_frame->buf.format == MPP_FMT_YUV422P) {
|
||||
color_mode = 1;
|
||||
} else {
|
||||
loge("not supprt this format(%d)", s->cur_frame->buf.format);
|
||||
}
|
||||
|
||||
val = s->y_stride | (s->uv_interleave << 16) | (color_mode << 17);
|
||||
write_reg_u32(s->regs_base + PIC_INFO_START_REG, val);
|
||||
|
||||
val = s->height | (s->y_stride << 16);
|
||||
write_reg_u32(s->regs_base + PIC_INFO_START_REG + 4, val);
|
||||
write_reg_u32(s->regs_base + PIC_INFO_START_REG + 8, s->phy_addr[0]);
|
||||
write_reg_u32(s->regs_base + PIC_INFO_START_REG + 12, s->phy_addr[1]);
|
||||
write_reg_u32(s->regs_base + PIC_INFO_START_REG + 16, s->phy_addr[2]);
|
||||
}
|
||||
|
||||
/*
|
||||
quant matrix store in zigzag order
|
||||
*/
|
||||
static void ve_config_quant_matrix(struct jpeg_ctx *s)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
uint32_t val;
|
||||
unsigned int* quant_tab[3] = { s->luma_quant_table, s->chroma_quant_table, s->chroma_quant_table };
|
||||
for (int comp = 0; comp < 3; comp++) {
|
||||
write_reg_u32(s->regs_base + JPG_QMAT_INFO_REG, (comp << 6) | 3);
|
||||
write_reg_u32(s->regs_base + JPG_QMAT_ADDR_REG, comp << 6);
|
||||
for (i = 0; i < 64; i++) {
|
||||
j = zigzag_direct[i];
|
||||
// qmatrix should be (1<<19)/q
|
||||
val = (1 << QUANT_FIXED_POINT_BITS) / quant_tab[comp][j];
|
||||
write_reg_u32(s->regs_base + JPG_QMAT_VAL_REG, val);
|
||||
}
|
||||
}
|
||||
|
||||
write_reg_u32(s->regs_base + JPG_QMAT_INFO_REG, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
huffman table include 4 tables: DC_Luma\DC_Chroma\AC_LUMA\AC_Chroma
|
||||
internal SRAM in VE is 544x20bit
|
||||
20bit data: [19:16]: code_length-1; [15:0]: code word
|
||||
address of the 4 tables:
|
||||
Luma_AC: 0-255
|
||||
Chroma_AC: 256-511
|
||||
Luma_DC: 512-528
|
||||
Chroma_DC: 528-544
|
||||
*/
|
||||
static void ve_config_huffman_table(struct jpeg_ctx *s)
|
||||
{
|
||||
int i;
|
||||
uint32_t val;
|
||||
|
||||
write_reg_u32(s->regs_base + JPG_HUFF_INFO_REG, 3);
|
||||
write_reg_u32(s->regs_base + JPG_HUFF_ADDR_REG, 0);
|
||||
|
||||
// luma ac
|
||||
for (i = 0; i < 256; i++) {
|
||||
val = ((s->huff_size_ac_luminance[i] - 1) << 16) | s->huff_code_ac_luminance[i];
|
||||
write_reg_u32(s->regs_base + JPG_HUFF_VAL_REG, val);
|
||||
}
|
||||
|
||||
// chroma ac
|
||||
for (i = 0; i < 256; i++) {
|
||||
val = ((s->huff_size_ac_chrominance[i] - 1) << 16) | s->huff_code_ac_chrominance[i];
|
||||
write_reg_u32(s->regs_base + JPG_HUFF_VAL_REG, val);
|
||||
}
|
||||
|
||||
// luma dc
|
||||
for (i = 0; i < 12; i++) {
|
||||
val = ((s->huff_size_dc_luminance[i] - 1) << 16) | s->huff_code_dc_luminance[i];
|
||||
write_reg_u32(s->regs_base + JPG_HUFF_VAL_REG, val);
|
||||
}
|
||||
|
||||
// chroma dc
|
||||
write_reg_u32(s->regs_base + JPG_HUFF_INFO_REG, 3);
|
||||
write_reg_u32(s->regs_base + JPG_HUFF_ADDR_REG, 528);
|
||||
for (i = 0; i < 12; i++) {
|
||||
val = ((s->huff_size_dc_chrominance[i] - 1) << 16) | s->huff_code_dc_chrominance[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 ve_config_stream_register(struct jpeg_ctx *s)
|
||||
{
|
||||
int head_offset = s->header_offset;
|
||||
int stream_num = s->stream_num;
|
||||
// end addr of output stream
|
||||
unsigned int align_256_addr = s->bitstream_phy_addr + stream_num * 256;
|
||||
write_reg_u32(s->regs_base + JPG_STREAM_END_ADDR_REG, align_256_addr);
|
||||
// base addr of output stream
|
||||
write_reg_u32(s->regs_base + JPG_BAS_ADDR_REG, s->bitstream_phy_addr + head_offset);
|
||||
// start addr of output stream
|
||||
write_reg_u32(s->regs_base + JPG_STREAM_START_ADDR_REG, s->bitstream_phy_addr + head_offset);
|
||||
|
||||
write_reg_u32(s->regs_base + JPG_STREAM_WRITE_PTR_REG, s->bitstream_phy_addr + head_offset);
|
||||
write_reg_u32(s->regs_base + JPG_STREAM_READ_PTR_REG, s->bitstream_phy_addr + head_offset);
|
||||
|
||||
// current stream pos
|
||||
write_reg_u32(s->regs_base + JPG_CUR_POS_REG, 0);
|
||||
write_reg_u32(s->regs_base + JPG_DATA_CNT_REG, 64);
|
||||
|
||||
write_reg_u32(s->regs_base + JPG_MEM_EA_REG, 0x7f);
|
||||
write_reg_u32(s->regs_base + JPG_MEM_IA_REG, 0x40);
|
||||
write_reg_u32(s->regs_base + JPG_MEM_HA_REG, 0x40);
|
||||
|
||||
write_reg_u32(s->regs_base + JPG_BITREQ_EN_REG, 1);
|
||||
}
|
||||
|
||||
int jpeg_hw_encode(struct jpeg_ctx *s)
|
||||
{
|
||||
int ret = 0;
|
||||
uint32_t status;
|
||||
|
||||
ve_get_client();
|
||||
|
||||
// 1. config ve top
|
||||
config_ve_top_reg(s);
|
||||
|
||||
// 2. config jpeg header
|
||||
config_header_info(s);
|
||||
|
||||
// 3. config picture info
|
||||
config_picture_info_register(s);
|
||||
|
||||
// 4. config quant/huffman table
|
||||
ve_config_quant_matrix(s);
|
||||
ve_config_huffman_table(s);
|
||||
|
||||
// 5. config bitstream
|
||||
ve_config_stream_register(s);
|
||||
|
||||
write_reg_u32(s->regs_base + JPG_STATUS_REG, 0xf);
|
||||
write_reg_u32(s->regs_base + JPG_START_REG, 1);
|
||||
|
||||
if (ve_wait((unsigned int*)&status) < 0) {
|
||||
loge("ve wait irq timeout");
|
||||
logi("read JPG_STATUS_REG %x", read_reg_u32(s->regs_base + JPG_STATUS_REG));
|
||||
|
||||
ve_reset();
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if(status > 1) {
|
||||
loge("status error");
|
||||
ve_reset();
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
uint32_t cycles = 0;
|
||||
cycles = read_reg_u32(s->regs_base + JPG_CYCLES_REG);
|
||||
|
||||
uint32_t end_addr = 0;
|
||||
end_addr = read_reg_u32(s->regs_base + JPG_STREAM_WRITE_PTR_REG);
|
||||
s->encode_data_len = end_addr - s->bitstream_phy_addr;
|
||||
|
||||
logi("cycles: %"PRIu32", data len: %d", cycles, s->encode_data_len);
|
||||
|
||||
// disable jpeg module
|
||||
write_reg_u32(s->regs_base + VE_JPG_EN_REG, 0);
|
||||
|
||||
out:
|
||||
ve_put_client();
|
||||
return ret;
|
||||
}
|
||||
Reference in New Issue
Block a user