gk7205v200-uboot/product/osd/dec/jpegd_drv.c
2025-08-07 17:13:54 +08:00

470 lines
12 KiB
C
Executable File

/*
* Copyright (c) Hunan Goke,Chengdu Goke,Shandong Goke. 2021. All rights reserved.
*/
#include "jpegd_drv.h"
#include <common.h>
#define osal_readl(x) (*((volatile int *)(x)))
#define osal_writel(v, x) (*((volatile int *)(x)) = (v))
__inline static unsigned int get_low_addr(unsigned long long phyaddr)
{
return (unsigned int)phyaddr;
}
__inline static unsigned int get_high_addr(unsigned long long phyaddr)
{
return (unsigned int)(phyaddr >> 32); /* shift right 32 bits */
}
void jpegd_set_clock_en(int vpu_id, gk_bool is_run)
{
unsigned long t, mask;
const unsigned int offset = JPEGD_CKEN_OFFSET;
mask = 1 << offset;
t = osal_readl((const volatile void *)JPEGD_CRG_REG_ADDR);
t &= ~mask;
t |= ((unsigned int)is_run << offset) & mask;
osal_writel(t, (volatile void *)JPEGD_CRG_REG_ADDR);
return;
}
void jpegd_reset_select(int vpu_id, gk_bool is_run)
{
int i;
volatile U_JPEG_DEC_START D32;
S_JPGD_REGS_TYPE *jpegd_reg = (S_JPGD_REGS_TYPE *)jpegd_get_reg_addr(vpu_id);
if (is_run == GK_FALSE) {
for (i = 0; i < 1000; i++) { /* 1000 cycle time */
D32.u32 = jpegd_reg->JPEG_DEC_START.u32;
if (D32.bits.rst_busy == 0) {
break;
}
udelay(10); /* 10 delay time */
}
if (i >= 1000) { /* 1000 cycle time */
printf("JPEGD reset error!\n");
return;
}
}
unsigned long t, mask;
const unsigned int offset = 0;
mask = 1 << offset;
t = osal_readl((const volatile void *)JPEGD_CRG_REG_ADDR);
t &= ~mask;
t |= ((unsigned int)is_run << offset) & mask;
osal_writel(t, (volatile void *)JPEGD_CRG_REG_ADDR);
return;
}
void jpegd_set_outstanding(int vpu_id, int outstanding)
{
U_FREQ_SCALE D32;
S_JPGD_REGS_TYPE *jpegd_reg = (S_JPGD_REGS_TYPE *)jpegd_get_reg_addr(vpu_id);
D32.u32 = jpegd_reg->FREQ_SCALE.u32;
D32.bits.outstanding = outstanding;
jpegd_reg->FREQ_SCALE.u32 = D32.u32;
return;
}
void *jpegd_get_reg_addr(int vpu_id)
{
S_JPGD_REGS_TYPE *jpegd_reg = GK_NULL;
jpegd_reg = (S_JPGD_REGS_TYPE *)JPEGD_REGS_ADDR;
return jpegd_reg;
}
unsigned int jpegd_read_int(int vpu_id)
{
S_JPGD_REGS_TYPE *jpegd_reg = (S_JPGD_REGS_TYPE *)jpegd_get_reg_addr(vpu_id);
return jpegd_reg->JPEG_INT.u32;
}
void jpegd_clear_int(int vpu_id)
{
S_JPGD_REGS_TYPE *jpegd_reg = (S_JPGD_REGS_TYPE *)jpegd_get_reg_addr(vpu_id);
/* check if it's frame end */
jpegd_reg->JPEG_INT.u32 = 0xFFFFFFFF; /* 0xFFFFFFFF:interrupt value */
return;
}
void jpegd_set_int_mask(int vpu_id)
{
S_JPGD_REGS_TYPE *jpegd_reg = (S_JPGD_REGS_TYPE *)jpegd_get_reg_addr(vpu_id);
jpegd_reg->INT_MASK.u32 = 0x0; /* 0x0:interrupt mask value */
return;
}
void jpegd_reset(int vpu_id)
{
jpegd_reset_select(vpu_id, GK_TRUE);
jpegd_reset_select(vpu_id, GK_FALSE);
jpegd_set_int_mask(vpu_id);
jpegd_set_outstanding(vpu_id, 0x3); /* 0x3:outstanding value */
return;
}
void jpegd_start_vpu(int vpu_id)
{
U_JPEG_DEC_START D32;
S_JPGD_REGS_TYPE *jpegd_reg = (S_JPGD_REGS_TYPE *)jpegd_get_reg_addr(vpu_id);
D32.u32 = jpegd_reg->JPEG_DEC_START.u32;
D32.bits.jpeg_dec_start = 1;
jpegd_reg->JPEG_DEC_START.u32 = D32.u32;
return;
}
int jpegd_set_time_out(int vpu_id, int time_out)
{
S_JPGD_REGS_TYPE *jpegd_reg = (S_JPGD_REGS_TYPE *)jpegd_get_reg_addr(vpu_id);
jpegd_reg->OVER_TIME_THD = (unsigned int)time_out;
return GK_SUCCESS;
}
void jpegd_resume_start(S_JPGD_REGS_TYPE *jpegd_reg)
{
U_JPEG_RESUME_START D32;
D32.u32 = 0;
D32.bits.jpeg_resume_start = 0;
D32.bits.last_resume_in_pic = 1;
jpegd_reg->JPEG_RESUME_START.u32 = D32.u32;
return;
}
void jpegd_stride(S_JPGD_REGS_TYPE *jpegd_reg, jpegd_vpu_config *config)
{
U_JPEG_STRIDE D32;
D32.u32 = 0;
D32.bits.y_stride = config->y_stride;
D32.bits.uv_stride = config->c_stride;
jpegd_reg->JPEG_STRIDE.u32 = D32.u32;
return;
}
void jpegd_picture_size(S_JPGD_REGS_TYPE *jpegd_reg, jpegd_vpu_config *config)
{
U_PICTURE_SIZE D32;
D32.u32 = 0;
D32.bits.pic_width_in_mcu = config->width_in_mcu;
D32.bits.pic_height_in_mcu = config->height_in_mcu;
jpegd_reg->PICTURE_SIZE.u32 = D32.u32;
return;
}
void jpegd_picture_type(S_JPGD_REGS_TYPE *jpegd_reg, jpegd_vpu_config *config)
{
U_PICTURE_TYPE D32;
D32.u32 = 0;
D32.bits.pic_type = config->pic_type;
jpegd_reg->PICTURE_TYPE.u32 = D32.u32;
return;
}
void jpegd_rgb_out_stride(S_JPGD_REGS_TYPE *jpegd_reg, jpegd_vpu_config *config)
{
U_RGB_OUT_STRIDE D32;
D32.u32 = 0;
D32.bits.jcfg2jdo_out_stride = config->rgb_stride;
jpegd_reg->RGB_OUT_STRIDE.u32 = D32.u32;
return;
}
void jpegd_bit_buffer_addr(S_JPGD_REGS_TYPE *jpegd_reg, jpegd_vpu_config *config)
{
jpegd_reg->BITBUFFER_STADDR_LSB = get_low_addr(config->phy_str_buf_start);
jpegd_reg->BITBUFFER_STADDR_MSB.u32 = get_high_addr(config->phy_str_buf_start);
jpegd_reg->BITBUFFER_ENDADDR_LSB = get_low_addr(config->phy_str_buf_end);
jpegd_reg->BITBUFFER_ENDADDR_MSB.u32 = get_high_addr(config->phy_str_buf_end);
return;
}
void jpegd_bit_stream_addr(S_JPGD_REGS_TYPE *jpegd_reg, jpegd_vpu_config *config)
{
jpegd_reg->BITSTREAMS_STADDR_LSB = get_low_addr(config->phy_str_start);
jpegd_reg->BITSTREAMS_STADDR_MSB.u32 = get_high_addr(config->phy_str_start);
jpegd_reg->BITSTREAMS_ENDADDR_LSB = get_low_addr(config->phy_str_end);
jpegd_reg->BITSTREAMS_ENDADDR_MSB.u32 = get_high_addr(config->phy_str_end);
return;
}
void jpegd_pic_yuv_start_addr(S_JPGD_REGS_TYPE *jpegd_reg, jpegd_vpu_config *config)
{
jpegd_reg->PICTURE_YSTADDR_LSB = get_low_addr(config->y_phy_addr);
jpegd_reg->PICTURE_YSTADDR_MSB.u32 = get_high_addr(config->y_phy_addr);
if (config->out_yuv == GK_TRUE) {
jpegd_reg->PICTURE_UVSTADDR_LSB = get_low_addr(config->c_phy_addr);
jpegd_reg->PICTURE_UVSTADDR_MSB.u32 = get_high_addr(config->c_phy_addr);
}
return;
}
void jpegd_freq_scale(S_JPGD_REGS_TYPE *jpegd_reg, jpegd_vpu_config *config)
{
U_FREQ_SCALE D32;
D32.u32 = jpegd_reg->FREQ_SCALE.u32;
D32.bits.freq_scale = 0;
D32.bits.ck_gt_en = 0;
D32.bits.outstanding = 3; /* 3:Simulation recommendation */
D32.bits.axi_id = 0;
if (config->out_yuv == GK_TRUE) {
D32.bits.jidct_emar_en = 1;
} else {
D32.bits.jidct_emar_en = 0;
}
jpegd_reg->FREQ_SCALE.u32 = D32.u32;
return;
}
void jpegd_out_type(S_JPGD_REGS_TYPE *jpegd_reg, jpegd_vpu_config *config)
{
U_OUT_TYPE D32;
D32.u32 = 0;
if (config->out_yuv == GK_TRUE) {
if (config->pic_format == PICTURE_FORMAT_YUV400) {
D32.bits.jidct_yuv420_en = 0;
} else {
D32.bits.jidct_yuv420_en = 1;
}
} else {
D32.bits.jidct_yuv420_en = 0;
D32.bits.hor_med_en = 0;
D32.bits.ver_med_en = 0;
D32.bits.dither_en = 0;
if (config->pixel_format == PIXEL_FORMAT_ARGB_8888) {
D32.bits.out_rgb_type = 0;
} else if (config->pixel_format == PIXEL_FORMAT_ABGR_8888) {
D32.bits.out_rgb_type = 1;
} else if (config->pixel_format == PIXEL_FORMAT_ARGB_1555) {
D32.bits.out_rgb_type = 2; /* 2 pixel format ARGB1555 */
} else if (config->pixel_format == PIXEL_FORMAT_ABGR_1555) {
D32.bits.out_rgb_type = 3; /* 3 pixel format ABGR1555 */
} else if (config->pixel_format == PIXEL_FORMAT_RGB_565) {
D32.bits.out_rgb_type = 4; /* 4 pixel format RGB565 */
} else if (config->pixel_format == PIXEL_FORMAT_BGR_565) {
D32.bits.out_rgb_type = 5; /* 5 pixel format BGR565 */
} else if (config->pixel_format == PIXEL_FORMAT_RGB_888) {
D32.bits.out_rgb_type = 6; /* 6 pixel format RGB888 */
} else if (config->pixel_format == PIXEL_FORMAT_BGR_888) {
D32.bits.out_rgb_type = 7; /* 7 pixel format BGR888 */
}
}
jpegd_reg->OUT_TYPE.u32 = D32.u32;
return;
}
void jpegd_alpha(S_JPGD_REGS_TYPE *jpegd_reg, jpegd_vpu_config *config)
{
if (config->out_yuv == GK_FALSE) {
U_JPGD_ALPHA D32;
D32.u32 = 0;
D32.bits.jpgd_a = config->alpha;
jpegd_reg->JPGD_ALPHA.u32 = D32.u32;
}
return;
}
void jpegd_emar_buffer(S_JPGD_REGS_TYPE *jpegd_reg, jpegd_vpu_config *config)
{
unsigned int i;
for (i = 0; i < JPEGD_IP_NUM; i++) {
jpegd_reg->MTN_ADDRESS0_LSB = get_low_addr(config->phy_emar_buffer0);
jpegd_reg->MTN_ADDRESS0_MSB.u32 = get_high_addr(config->phy_emar_buffer0);
jpegd_reg->MTN_ADDRESS1_LSB = get_low_addr(config->phy_emar_buffer1);
jpegd_reg->MTN_ADDRESS1_MSB.u32 = get_high_addr(config->phy_emar_buffer1);
}
return;
}
void jpegd_pic_cut_pos(S_JPGD_REGS_TYPE *jpegd_reg, jpegd_vpu_config *config)
{
if (config->out_yuv == GK_FALSE) {
{
U_PICCUT_STARTPOS D32;
D32.u32 = 0;
D32.bits.jcfg2jytr_pic_startx = 0;
D32.bits.jcfg2jytr_pic_starty = 0;
jpegd_reg->PICCUT_STARTPOS.u32 = D32.u32;
}
{
U_PICCUT_ENDPOS D32;
D32.u32 = 0;
D32.bits.jcfg2jytr_pic_endx = config->width - 1;
D32.bits.jcfg2jytr_pic_endy = config->height - 1;
jpegd_reg->PICCUT_ENDPOS.u32 = D32.u32;
}
}
return;
}
void jpegd_sampling_factor(S_JPGD_REGS_TYPE *jpegd_reg, jpegd_vpu_config *config)
{
U_SAMPLING_FACTOR D32;
D32.u32 = 0;
D32.bits.v_fac = config->v_fac;
D32.bits.u_fac = config->u_fac;
D32.bits.y_fac = config->y_fac;
jpegd_reg->SAMPLING_FACTOR.u32 = D32.u32;
return;
}
void jpegd_dri(S_JPGD_REGS_TYPE *jpegd_reg, jpegd_vpu_config *config)
{
U_DRI D32;
D32.u32 = 0;
D32.bits.jcfg2jvld_ri = config->dri;
jpegd_reg->DRI.u32 = D32.u32;
return;
}
void jpegd_config_quant_table_regs(S_JPGD_REGS_TYPE *jpegd_reg, jpegd_vpu_config *config)
{
unsigned int i;
for (i = 0; i < QUANT_TABLE_SIZE; i++) {
jpegd_reg->QUANT_TABLE[i].u32 = config->quant_table[i];
}
return;
}
void jpegd_config_huffman_table_regs(S_JPGD_REGS_TYPE *jpegd_reg, jpegd_vpu_config *config)
{
unsigned int i;
for (i = 0; i < HDC_TABLE_SIZE; i++) {
jpegd_reg->HDC_TABLE[i].u32 = config->huffman_table[i];
}
for (i = 0; i < HAC_MIN_TABLE_SIZE; i++) {
jpegd_reg->HAC_MIN_TABLE[i].u32 = config->huffman_min_table[i];
}
for (i = 0; i < HAC_BASE_TABLE_SIZE; i++) {
jpegd_reg->HAC_BASE_TABLE[i].u32 = config->huffman_base_table[i];
}
for (i = 0; i < HAC_SYMBOL_TABLE_SIZE; i++) {
jpegd_reg->HAC_SYMBOL_TABLE[i] = config->huffman_symbol_table[i];
}
return;
}
void jpegd_drv_write_regs(S_JPGD_REGS_TYPE *reg_base, jpegd_vpu_config *config)
{
S_JPGD_REGS_TYPE *jpegd_reg = reg_base;
/* 1. JPEG_RESUME_START */
jpegd_resume_start(jpegd_reg);
/* 2. JPEG_STRIDE */
jpegd_stride(jpegd_reg, config);
/* 3. PICTURE_SIZE */
jpegd_picture_size(jpegd_reg, config);
/* 4. PICTURE_TYPE */
jpegd_picture_type(jpegd_reg, config);
/* . RGB_OUT_STRIDE */
jpegd_rgb_out_stride(jpegd_reg, config);
/* 5. BITBUFFER_STADDR */
/* 6. BITBUFFER_ENDADDR */
jpegd_bit_buffer_addr(jpegd_reg, config);
/* 7. BITSTREAMS_STADDR */
/* 8. BITSTREAMS_ENDADDR */
jpegd_bit_stream_addr(jpegd_reg, config);
/* 9. PICTURE_YSTADDR */
/* 10. PICTURE_UVSTADDR */
jpegd_pic_yuv_start_addr(jpegd_reg, config);
/* 11. FREQ_SCALE */
jpegd_freq_scale(jpegd_reg, config);
/* 12. OUT_TYPE */
jpegd_out_type(jpegd_reg, config);
/* . JPGD_ALPHA */
jpegd_alpha(jpegd_reg, config);
jpegd_emar_buffer(jpegd_reg, config);
/* PICCUT_STARTPOS U_PICCUT_ENDPOS */
jpegd_pic_cut_pos(jpegd_reg, config);
jpegd_sampling_factor(jpegd_reg, config);
/* 13. DRI */
jpegd_dri(jpegd_reg, config);
jpegd_config_quant_table_regs(jpegd_reg, config);
jpegd_config_huffman_table_regs(jpegd_reg, config);
return;
}
void jpegd_drv_read_regs(S_JPGD_REGS_TYPE *reg_base, jpegd_vpu_status *jpegd_vpu_status)
{
S_JPGD_REGS_TYPE *jpegd_reg = reg_base;
jpegd_vpu_status->int_dec_finish = jpegd_reg->JPEG_INT.bits.int_dec_fnsh;
jpegd_vpu_status->int_dec_err = jpegd_reg->JPEG_INT.bits.int_dec_err;
jpegd_vpu_status->int_over_time = jpegd_reg->JPEG_INT.bits.int_over_time;
jpegd_vpu_status->int_bs_res = jpegd_reg->JPEG_INT.bits.int_bs_res;
return;
}