GK SDK 源码库: XMIPCLinuxV100R005C00SPC030 (kernel/tools/open_source excluded)

This commit is contained in:
lai
2026-09-06 03:52:57 +08:00
commit b1928b41c0
21813 changed files with 4413081 additions and 0 deletions
+933
View File
@@ -0,0 +1,933 @@
#include "stdio.h"
#include "xmedia_type.h"
#include "xmedia_vi.h"
#include "defines.h"
#include "hal_vi.h"
/*
* 系统控制寄存器,MISC_CTRL81
* BIT [0] :
* 0:MIPI_RX_PHY1连接MIPI_2L_RX0控制器
* 1:MIPI_RX_PHY1连接MIPI_4L_RX0控制器
* BIT [1] :
* 0:MIPI_RX_PHY3连接MIPI_2L_RX1控制器
* 1:MIPI_RX_PHY3连接MIPI_4L_RX1控制器
* */
#define MIPI_MISC_CTRL 0x12028900
#define VIPROC_EXTERNAL_TIMING_EN_ADDR 0x1202899C
#define CRG_REGS_ADDR 0x12010000
#define VICAP_IRQ_NUM 66
#define VIPROC0_IRQ_NUM 63
#define VI_RESET_WAIT_CNT 100
typedef struct {
xmedia_u32 phy0_data_lane0;
xmedia_u32 phy0_data_lane1;
xmedia_u32 phy1_data_lane0;
xmedia_u32 phy1_data_lane1;
xmedia_u32 phy0_clk_sel;
xmedia_u32 phy1_clk_sel;
} mipi_lane_swap_attr;
volatile xmedia_u32 g_vicap_all_reg[VICAP_IP_NUM] = { 0x11000000 };
volatile xmedia_u32 g_viproc_all_reg[VIPROC_IP_NUM] = { 0x11200000 };
STAGE1_GLOBAL volatile xmedia_u32 g_mipi_rx_reg[VI_MIPI_RX_NUM] = { 0x10fe0000, 0x11010000 };
STAGE1_GLOBAL volatile xmedia_u32 g_mipi_phy_reg_addr = 0x12028900;
STAGE1_FUNC static xmedia_u32 vi_read_reg(volatile xmedia_uintptr_t addr)
{
return *(volatile xmedia_u32 *)(addr);
}
STAGE1_FUNC static xmedia_void vi_write_reg(volatile xmedia_uintptr_t addr, xmedia_u32 val)
{
*(volatile xmedia_u32 *)(addr) = val;
}
STAGE1_FUNC xmedia_void vi_reg_write_bit(xmedia_u32 addr, xmedia_u32 value, xmedia_u32 bit_pos)
{
xmedia_u32 t, mask;
mask = 1 << bit_pos;
t = vi_read_reg(addr);
t &= ~mask;
t |= (value << bit_pos) & mask;
vi_write_reg(addr, t);
}
STAGE1_FUNC xmedia_void vi_reg_write_32(xmedia_u32 addr, xmedia_u32 value, xmedia_u32 bit_pos, xmedia_u32 bit_count)
{
xmedia_u32 t;
xmedia_u32 mask;
t = vi_read_reg(addr);
mask = ((1U << bit_count) - 1) << bit_pos;
t &= ~mask;
t |= (value << bit_pos) & mask;
vi_write_reg(addr, t);
}
static xmedia_s32 vi_dev_reset(xmedia_s32 dev, xmedia_bool reset)
{
xmedia_bool reset_state = 0;
xmedia_u32 wait_cnt = 0;
xmedia_u32 reg;
vi_reg_write_bit(CRG_REGS_ADDR + 0xf4, reset, 4 + dev); // 4 : pt0 offset
reg = vi_read_reg(CRG_REGS_ADDR + 0x1e4);
reset_state = (reg & (0x1 << (8 + dev))) >> (8 + dev); // bit[8:12]: pt0-pt4 reset state
while (reset_state != reset) {
sleep_us(1);
wait_cnt++;
reg = vi_read_reg(CRG_REGS_ADDR + 0x1e4);
reset_state = (reg & (0x1 << (8 + dev))) >> (8 + dev); // bit[8:12]: pt0-pt4 reset state
if (reset_state != reset && wait_cnt > VI_RESET_WAIT_CNT) {
puts("dev reset err\n");
return XMEDIA_FAILURE;
}
}
return XMEDIA_SUCCESS;
}
static xmedia_s32 vi_vicap_fe_reset(xmedia_s32 fe_id, xmedia_bool reset)
{
xmedia_bool reset_state = 0;
xmedia_u32 reg;
xmedia_u32 wait_cnt = 0;
vi_reg_write_bit(CRG_REGS_ADDR + 0xf4, reset, 9 + fe_id); // 9 : fe0 offset
reg = vi_read_reg(CRG_REGS_ADDR + 0x1e4);
reset_state = (reg & (0x1 << (13 + fe_id))) >> (13 + fe_id); // bit[13:20]: fe0-fe7 reset state
while (reset_state != reset) {
sleep_us(1);
wait_cnt++;
reg = vi_read_reg(CRG_REGS_ADDR + 0x1e4);
reset_state = (reg & (0x1 << (13 + fe_id))) >> (13 + fe_id); // bit[13:20]: fe0-fe7 reset state
if (reset_state != reset && wait_cnt > VI_RESET_WAIT_CNT) {
puts("vicap reset failed\n");
return XMEDIA_FAILURE;
}
}
return XMEDIA_SUCCESS;
}
static xmedia_s32 vi_viproc_reset_set(xmedia_u32 proc_id, xmedia_bool reset)
{
xmedia_bool reset_state = 0;
xmedia_u32 wait_cnt = 0;
xmedia_u32 reg;
vi_reg_write_bit(CRG_REGS_ADDR + 0xfc, reset, 4); // 4 : viproc reset offset
reg = vi_read_reg(CRG_REGS_ADDR + 0x1e4);
reset_state = (reg & 0x80) >> 7; // bit[7]: viproc reset state
while (reset_state != reset) {
sleep_us(1);
wait_cnt++;
reg = vi_read_reg(CRG_REGS_ADDR + 0x1e4);
reset_state = (reg & 0x80) >> 7; // bit[7]: viproc reset state
if (reset_state != reset && wait_cnt > VI_RESET_WAIT_CNT) {
puts("viproc reset failed\n");
return XMEDIA_FAILURE;
}
}
return XMEDIA_SUCCESS;
}
static xmedia_s32 vi_vicap_all_reset(xmedia_bool reset)
{
xmedia_bool reset_state = 0;
xmedia_u32 reg;
xmedia_u32 wait_cnt = 0;
vi_reg_write_bit(CRG_REGS_ADDR + 0xf4, reset, 17); // [17] : vicap总软复位请求
reg = vi_read_reg(CRG_REGS_ADDR + 0x1e4);
reset_state = (reg & (0x1 << 21)) >> 21; // bit[21]: vicap all state
while (reset_state != reset) {
sleep_us(1);
wait_cnt++;
reg = vi_read_reg(CRG_REGS_ADDR + 0x1e4);
reset_state = (reg & (0x1 << 21)) >> 21; // bit[21]: vicap all state
if (reset_state != reset && wait_cnt > VI_RESET_WAIT_CNT) {
puts("vicap reset failed\n");
return XMEDIA_FAILURE;
}
}
return XMEDIA_SUCCESS;
}
static xmedia_s32 vi_vicap_clk_reset_init(xmedia_u32 cap_id)
{
xmedia_s32 dev;
xmedia_s32 fe;
vi_reg_write_bit(CRG_REGS_ADDR + 0xf4, XMEDIA_TRUE, 0); // enable vicap clk
sleep_us(5); // 等待时钟稳定
if (vi_vicap_all_reset(XMEDIA_FALSE) != XMEDIA_SUCCESS) {
return XMEDIA_FAILURE;
}
for (dev = 0; dev < VI_MAX_DEV_NUM; dev++) {
if (vi_dev_reset(dev, XMEDIA_TRUE) != 0) {
return XMEDIA_FAILURE;
}
}
for (fe = 0; fe < VI_MAX_PHY_PIPE_NUM; fe++) {
if (vi_vicap_fe_reset(fe, XMEDIA_TRUE) != 0) {
return XMEDIA_FAILURE;
}
}
for (dev = 0; dev < VI_MAX_DEV_NUM; dev++) {
if (vi_dev_reset(dev, XMEDIA_FALSE) != 0) {
return XMEDIA_FAILURE;
}
}
for (fe = 0; fe < VI_MAX_PHY_PIPE_NUM; fe++) {
if (vi_vicap_fe_reset(fe, XMEDIA_FALSE) != 0) {
return XMEDIA_FAILURE;
}
}
return XMEDIA_SUCCESS;
}
static xmedia_void vi_vicap_clk_reset_deinit(xmedia_u32 cap_id)
{
xmedia_s32 dev;
xmedia_s32 fe;
for (dev = 0; dev < VI_MAX_DEV_NUM; dev++) {
vi_dev_reset(dev, XMEDIA_TRUE);
}
for (fe = 0; fe < VI_MAX_PHY_PIPE_NUM; fe++) {
vi_vicap_fe_reset(fe, XMEDIA_TRUE);
}
vi_vicap_all_reset(XMEDIA_TRUE);
vi_reg_write_bit(CRG_REGS_ADDR + 0xf4, 0, 0);
}
static xmedia_s32 vi_viproc_clk_reset_init(xmedia_u32 proc_id)
{
vi_reg_write_bit(CRG_REGS_ADDR + 0xfc, XMEDIA_TRUE, 0);
sleep_us(5); // 等待时钟稳定
if (vi_viproc_reset_set(proc_id, XMEDIA_FALSE) != 0) {
puts("viproc clk reset false failed\n");
return XMEDIA_FAILURE;
}
return XMEDIA_SUCCESS;
}
static xmedia_void vi_viproc_clk_reset_deinit(xmedia_u32 proc_id)
{
vi_viproc_reset_set(proc_id, XMEDIA_TRUE);
vi_viproc_reset_set(proc_id, XMEDIA_FALSE);
vi_reg_write_bit(CRG_REGS_ADDR + 0xfc, XMEDIA_FALSE, 0);
}
STAGE1_FUNC static xmedia_void mipi_rx_set_misc_sel(xmedia_s32 dev_id, xmedia_vi_mipi_lane_divide_mode mipi_lane_num)
{
volatile xmedia_u32 mipi_misc_reg = MIPI_MISC_CTRL;
if (mipi_lane_num == XMEDIA_VI_MIPI_LANE_DIVIDE_MODE_4_LANE) {
if (dev_id == 0) {
vi_reg_write_bit(mipi_misc_reg, 1, 0);
} else {
vi_reg_write_bit(mipi_misc_reg, 1, 1);
}
} else {
if (dev_id == 0 || dev_id == 1) {
vi_reg_write_bit(mipi_misc_reg, 0, 0);
} else {
vi_reg_write_bit(mipi_misc_reg, 0, 1);
}
}
}
static xmedia_void mipi_rx_phy_get_lane_swap(xmedia_s32 dev_id, const xmedia_vi_dev_config *dev_config,
mipi_lane_swap_attr *lane_swap_mode)
{
/*
* 默认phy与lane的链接关系:
* mipi0-phy0-data0-lane0
* mipi0-phy0-data1-lane1
* mipi1-phy1-data0-lane2
* mipi1-phy1-data1-lane3
*/
if (dev_config->mipi_lane_num == XMEDIA_VI_MIPI_LANE_DIVIDE_MODE_4_LANE) {
lane_swap_mode->phy0_data_lane0 = 0;
lane_swap_mode->phy0_data_lane1 = 1;
lane_swap_mode->phy1_data_lane0 = 2;
lane_swap_mode->phy1_data_lane1 = 3;
lane_swap_mode->phy0_clk_sel = 0;
lane_swap_mode->phy1_clk_sel = 1;
} else {
if (dev_id == 0) {
lane_swap_mode->phy0_data_lane0 = 0;
lane_swap_mode->phy0_data_lane1 = 1;
lane_swap_mode->phy0_clk_sel = 0;
} else { // VI_DEV1
lane_swap_mode->phy1_data_lane0 = 2;
lane_swap_mode->phy1_data_lane1 = 3;
lane_swap_mode->phy1_clk_sel = 0;
}
}
if (dev_config->lane_config.enable != XMEDIA_TRUE) {
return;
}
// 用户任意配置链接关系
if (dev_config->mipi_lane_num == XMEDIA_VI_MIPI_LANE_DIVIDE_MODE_4_LANE) {
lane_swap_mode->phy0_data_lane0 = dev_config->lane_config.lane_cfg[0];
lane_swap_mode->phy0_data_lane1 = dev_config->lane_config.lane_cfg[1];
lane_swap_mode->phy1_data_lane0 = dev_config->lane_config.lane_cfg[2];
lane_swap_mode->phy1_data_lane1 = dev_config->lane_config.lane_cfg[3];
lane_swap_mode->phy0_clk_sel = 0;
lane_swap_mode->phy1_clk_sel = 1;
} else {
if (dev_id == 0) {
lane_swap_mode->phy0_data_lane0 = dev_config->lane_config.lane_cfg[0];
lane_swap_mode->phy0_data_lane1 = dev_config->lane_config.lane_cfg[1];
lane_swap_mode->phy0_clk_sel = (lane_swap_mode->phy0_data_lane0 > 1) ? 1 : 0;
} else {
lane_swap_mode->phy1_data_lane0 = dev_config->lane_config.lane_cfg[0];
lane_swap_mode->phy1_data_lane1 = dev_config->lane_config.lane_cfg[1];
lane_swap_mode->phy1_clk_sel = (lane_swap_mode->phy1_data_lane0 > 1) ? 0 : 1;
}
}
}
static xmedia_void mipi_rx_phy_lane_swap(xmedia_s32 dev_id, xmedia_vi_mipi_lane_divide_mode lane_mode,
mipi_lane_swap_attr *lane_swap)
{
volatile xmedia_u32 mipi_phy_addr = g_mipi_phy_reg_addr;
if (lane_mode == XMEDIA_VI_MIPI_LANE_DIVIDE_MODE_4_LANE) {
vi_reg_write_32(mipi_phy_addr + 0xac, lane_swap->phy0_data_lane0, 0, 2);
vi_reg_write_32(mipi_phy_addr + 0xac, lane_swap->phy0_data_lane1, 2, 2);
vi_reg_write_32(mipi_phy_addr + 0xac, lane_swap->phy1_data_lane0, 4, 2);
vi_reg_write_32(mipi_phy_addr + 0xac, lane_swap->phy1_data_lane1, 6, 2);
vi_reg_write_32(mipi_phy_addr + 0xac, lane_swap->phy0_clk_sel, 8, 1);
vi_reg_write_32(mipi_phy_addr + 0xac, lane_swap->phy1_clk_sel, 9, 1);
} else if (lane_mode == XMEDIA_VI_MIPI_LANE_DIVIDE_MODE_2_LANE) {
if (dev_id == 0) {
vi_reg_write_32(mipi_phy_addr + 0xac, lane_swap->phy0_data_lane0, 0, 2);
vi_reg_write_32(mipi_phy_addr + 0xac, lane_swap->phy0_data_lane1, 2, 2);
vi_reg_write_32(mipi_phy_addr + 0xac, lane_swap->phy0_clk_sel, 8, 1);
} else { // VI_DEV1
vi_reg_write_32(mipi_phy_addr + 0xac, lane_swap->phy1_data_lane0, 4, 2);
vi_reg_write_32(mipi_phy_addr + 0xac, lane_swap->phy1_data_lane1, 6, 2);
vi_reg_write_32(mipi_phy_addr + 0xac, lane_swap->phy1_clk_sel, 9, 1);
}
} else {
if (dev_id == 0) {
vi_reg_write_32(mipi_phy_addr + 0xac, lane_swap->phy0_data_lane0, 0, 2);
vi_reg_write_32(mipi_phy_addr + 0xac, lane_swap->phy0_clk_sel, 8, 1);
} else { // VI_DEV1
vi_reg_write_32(mipi_phy_addr + 0xac, lane_swap->phy1_data_lane0, 4, 2);
vi_reg_write_32(mipi_phy_addr + 0xac, lane_swap->phy1_clk_sel, 9, 1);
}
}
}
STAGE1_FUNC static xmedia_void mipi_rx_phy_init(xmedia_s32 dev_id, xmedia_u32 mipi_rate,
xmedia_vi_mipi_lane_divide_mode mipi_lane_num,
mipi_lane_swap_attr *lane_swap)
{
volatile xmedia_u32 mipi_phy_addr = g_mipi_phy_reg_addr;
xmedia_u32 data_rate;
xmedia_u32 td_term_en_max;
xmedia_u32 td_term_en;
xmedia_u32 ths_settle_max;
xmedia_u32 ths_settle;
xmedia_u32 tclk_term_en_max;
xmedia_u32 tclk_term_en;
xmedia_u32 tclk_settle_max;
xmedia_u32 tclk_settle;
xmedia_u32 tx_clk_esc = 24; // 24MHz 晶振配置 (T-tx_clk_esc = 41.7 ns)
if (mipi_rate == 0) {
puts("mipi_rate invalid");
puts("\n");
}
if (mipi_lane_num == XMEDIA_VI_MIPI_LANE_DIVIDE_MODE_4_LANE) {
vi_reg_write_bit(mipi_phy_addr, 1, 0); // mipirxphy_sel
} else {
vi_reg_write_bit(mipi_phy_addr, 0, 0); // mipirxphy_sel
}
mipi_rx_phy_lane_swap(dev_id, mipi_lane_num, lane_swap);
data_rate = mipi_rate;
td_term_en_max = 35 + 4000 / data_rate;
td_term_en = td_term_en_max * data_rate / 2000 - 1;
ths_settle_max = 145 + 10 * 1000 / data_rate;
ths_settle = (ths_settle_max - td_term_en * 2000 / data_rate) * data_rate / 2000 - 1;
tclk_term_en_max = 38;
tclk_term_en = (tx_clk_esc * tclk_term_en_max) / 1000;
tclk_settle_max = 300;
tclk_settle = (tclk_settle_max - tclk_term_en * 1000 / tx_clk_esc) * tx_clk_esc / 1000 - 1;
if (dev_id == 0) {
vi_reg_write_32(mipi_phy_addr + 0xb4, td_term_en, 24, 8); // time_hs_term_en
vi_reg_write_32(mipi_phy_addr + 0xb4, ths_settle, 16, 8); // time_hs_settle
vi_reg_write_32(mipi_phy_addr + 0xb4, tclk_term_en, 8, 8); // time_ck_term_en
vi_reg_write_32(mipi_phy_addr + 0xb4, tclk_settle, 0, 8); // time_ck_settle
vi_reg_write_bit(mipi_phy_addr + 0xb0, XMEDIA_TRUE, 0); // cr_csi_en
vi_reg_write_bit(mipi_phy_addr + 0xb0, XMEDIA_TRUE, 1); // dl0_enable
vi_reg_write_bit(mipi_phy_addr + 0xb0, XMEDIA_TRUE, 2); // dl1_enable
} else if (dev_id == 1) {
vi_reg_write_32(mipi_phy_addr + 0xd4, td_term_en, 24, 8); // time_hs_term_en
vi_reg_write_32(mipi_phy_addr + 0xd4, ths_settle, 16, 8); // time_hs_settle
vi_reg_write_32(mipi_phy_addr + 0xd4, tclk_term_en, 8, 8); // time_ck_term_en
vi_reg_write_32(mipi_phy_addr + 0xd4, tclk_settle, 0, 8); // time_ck_settle
vi_reg_write_bit(mipi_phy_addr + 0xd0, XMEDIA_TRUE, 0); // cr_csi_en
vi_reg_write_bit(mipi_phy_addr + 0xd0, XMEDIA_TRUE, 1); // dl0_enable
vi_reg_write_bit(mipi_phy_addr + 0xd0, XMEDIA_TRUE, 2); // dl1_enable
} else {
puts("mipi phy num err, dev_id ");
putdec(dev_id);
puts("\n");
}
}
STAGE1_GLOBAL static xmedia_u32 ret_mipi_date_type[10] = { 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x27, 0x18, 0x1a, 0x1e };
STAGE1_FUNC xmedia_u32 mipi_rx_get_data_type(xmedia_intf_mipi_csi_data_type data_type)
{
return ret_mipi_date_type[data_type];
}
STAGE1_FUNC xmedia_void mipi_rx_set_ipi_reg(xmedia_s32 dev_id, xmedia_intf_mipi_csi_data_type data_type)
{
volatile unsigned int mipi_rx_addr = g_mipi_rx_reg[dev_id];
xmedia_u32 ipi_data_type;
vi_reg_write_bit(mipi_rx_addr + 0x80, 1, 24); // ipi enable
vi_reg_write_bit(mipi_rx_addr + 0x80, 1, 16); // ipi_cut_through
// ipi_color_com
if (data_type <= XMEDIA_INTF_MIPI_CSI_DATA_TYPE_RAW_16BIT) {
vi_reg_write_bit(mipi_rx_addr + 0x80, 1, 8);
} else {
vi_reg_write_bit(mipi_rx_addr + 0x80, 0, 8);
}
vi_reg_write_32(mipi_rx_addr + 0x84, 0, 0, 2); // ipi vc id
ipi_data_type = mipi_rx_get_data_type(data_type);
vi_reg_write_32(mipi_rx_addr + 0x88, ipi_data_type, 0, 6); // ipi data type
vi_reg_write_bit(mipi_rx_addr + 0x88, 1, 8); // embedded_data[A]
vi_reg_write_bit(mipi_rx_addr + 0x8c, 1, 8); // ipi mem auto flush
vi_reg_write_32(mipi_rx_addr + 0x90, 0xa, 0, 12); // hsa
vi_reg_write_32(mipi_rx_addr + 0x94, 0xa, 0, 12); // hbp
vi_reg_write_32(mipi_rx_addr + 0x98, 0xa, 0, 12); // hsd
vi_reg_write_32(mipi_rx_addr + 0x9c, 0x898, 0, 15); // hline_time
vi_reg_write_bit(mipi_rx_addr + 0xa0, 1, 0); // soft reset
// advanced feature
vi_reg_write_bit(mipi_rx_addr + 0xac, 0, 0);
vi_reg_write_32(mipi_rx_addr + 0xac, 0, 8, 6);
vi_reg_write_bit(mipi_rx_addr + 0xac, 1, 16);
vi_reg_write_bit(mipi_rx_addr + 0xac, 1, 17);
vi_reg_write_bit(mipi_rx_addr + 0xac, 1, 18);
vi_reg_write_bit(mipi_rx_addr + 0xac, 1, 19);
vi_reg_write_bit(mipi_rx_addr + 0xac, 1, 20);
vi_reg_write_bit(mipi_rx_addr + 0xac, 1, 21);
vi_reg_write_bit(mipi_rx_addr + 0xac, 1, 22);
vi_reg_write_bit(mipi_rx_addr + 0xac, 1, 24);
}
xmedia_u32 vi_get_bit_width(xmedia_video_data_width data_width)
{
xmedia_u32 bit_width;
switch (data_width) {
case XMEDIA_VIDEO_DATA_WIDTH_8:
bit_width = 8;
break;
case XMEDIA_VIDEO_DATA_WIDTH_10:
bit_width = 10;
break;
case XMEDIA_VIDEO_DATA_WIDTH_12:
bit_width = 12;
break;
case XMEDIA_VIDEO_DATA_WIDTH_14:
bit_width = 14;
break;
case XMEDIA_VIDEO_DATA_WIDTH_16:
bit_width = 16;
break;
default:
bit_width = 16;
break;
}
return bit_width;
}
xmedia_u32 vi_viproc_get_bit_deepth(xmedia_video_data_width bit_width, xmedia_video_wdr_mode wdr_mode)
{
if (wdr_mode == XMEDIA_VIDEO_WDR_MODE_NONE) {
return VI_PACK_12BIT;
} else if (wdr_mode == XMEDIA_VIDEO_WDR_MODE_BUILT_IN) {
if (bit_width == XMEDIA_VIDEO_DATA_WIDTH_8) {
return VI_PACK_8BIT;
} else if (bit_width == XMEDIA_VIDEO_DATA_WIDTH_10) {
return VI_PACK_10BIT;
} else if (bit_width == XMEDIA_VIDEO_DATA_WIDTH_12) {
return VI_PACK_12BIT;
} else if (bit_width == XMEDIA_VIDEO_DATA_WIDTH_14) {
return VI_PACK_14BIT;
} else if (bit_width == XMEDIA_VIDEO_DATA_WIDTH_16) {
return VI_PACK_16BIT;
} else {
puts("viproc built-in wdr mode not support bit_width ");
putdec(bit_width);
puts("\n");
return VI_PACK_12BIT;
}
} else {
puts("viproc not support wdr_mode ");
putdec(wdr_mode);
puts("\n");
return VI_PACK_12BIT;
}
}
xmedia_void hal_vi_vicap_reg_newer(xmedia_s32 fe_id)
{
xmedia_u32 vicap_addr = g_vicap_all_reg[0];
vi_reg_write_bit(vicap_addr + ((fe_id + 6) * 0x1000 + 0x48), 1, 0);
}
xmedia_void hal_vi_vicap_online_config(xmedia_s32 fe_id, xmedia_vi_pipe_config *pipe_config)
{
xmedia_u32 vicap_addr = g_vicap_all_reg[0];
xmedia_u32 bit_width;
// input_size
vi_reg_write_32(vicap_addr + ((fe_id + 6) * 0x1000 + 0x4), pipe_config->width, 0, 14);
vi_reg_write_32(vicap_addr + ((fe_id + 6) * 0x1000 + 0x4), pipe_config->height, 16, 14);
// bit_width
bit_width = vi_get_bit_width(pipe_config->bit_width);
vi_reg_write_32(vicap_addr + ((fe_id + 6) * 0x1000 + 0x28), bit_width, 16, 6);
// output_size
vi_reg_write_32(vicap_addr + ((fe_id + 6) * 0x1000 + 0x2c), pipe_config->width, 0, 14);
vi_reg_write_32(vicap_addr + ((fe_id + 6) * 0x1000 + 0x2c), pipe_config->height, 16, 14);
// vicap reg newer
hal_vi_vicap_reg_newer(fe_id);
// todo offline set_output_memory
if (pipe_config->vi_work_mode == 1) {
}
}
xmedia_u32 hal_vi_vicap_get_top_int_status(xmedia_u32 vicap_id)
{
xmedia_u32 top_int_status;
xmedia_u32 vicap_addr = g_vicap_all_reg[vicap_id];
top_int_status = vi_read_reg(vicap_addr + 0x10);
return top_int_status;
}
xmedia_u32 hal_vi_vicap_get_top_int_mask(xmedia_u32 vicap_id)
{
xmedia_u32 top_int_mask;
xmedia_u32 vicap_addr = g_vicap_all_reg[vicap_id];
top_int_mask = vi_read_reg(vicap_addr + 0x14);
return top_int_mask;
}
xmedia_u32 hal_vi_vicap_get_chn_int_status(xmedia_s32 fe_id)
{
xmedia_u32 irq_status;
xmedia_u32 vicap_addr = g_vicap_all_reg[0];
irq_status = vi_read_reg(vicap_addr + ((fe_id + 6) * 0x1000 + 0x40));
return irq_status;
}
xmedia_void hal_vi_vicap_clear_int(xmedia_s32 fe_id, xmedia_u32 mask)
{
xmedia_u32 vicap_addr = g_vicap_all_reg[0];
vi_write_reg(vicap_addr + ((fe_id + 6) * 0x1000 + 0x40), mask); // clear int
}
xmedia_s32 hal_vi_get_vicap_irq_num(xmedia_u32 vicap_id)
{
return VICAP_IRQ_NUM;
}
xmedia_s32 hal_vi_get_viproc_irq_num(xmedia_u32 viproc_id)
{
return VIPROC0_IRQ_NUM;
}
xmedia_u32 hal_viproc_get_reg_public_int_status(xmedia_u32 viproc_id)
{
xmedia_u32 int_status;
xmedia_u32 viproc_addr = g_viproc_all_reg[viproc_id];
int_status = vi_read_reg(viproc_addr + 0x48);
return int_status;
}
xmedia_u32 hal_viproc_get_reg_public_int_mask(xmedia_u32 viproc_id)
{
xmedia_u32 int_mask;
xmedia_u32 viproc_addr = g_viproc_all_reg[viproc_id];
int_mask = vi_read_reg(viproc_addr + 0x2c);
return int_mask;
}
xmedia_u32 hal_viproc_common_get_reg_early_mask(xmedia_u32 viproc_id)
{
xmedia_u32 int_mask;
xmedia_u32 viproc_addr = g_viproc_all_reg[viproc_id];
int_mask = vi_read_reg(viproc_addr + 0x1e8);
return int_mask;
}
xmedia_void hal_viproc_clr_reg_int(xmedia_u32 viproc_id, xmedia_u32 mask)
{
xmedia_u32 viproc_addr = g_viproc_all_reg[viproc_id];
vi_write_reg(viproc_addr + 0x48, mask);
}
STAGE1_FUNC xmedia_void hal_mipi_init(xmedia_void)
{
vi_reg_write_32(CRG_REGS_ADDR + 0xa0, 0, 0, 3); // bit[0:2]: mipi_rx_clk_sel
}
STAGE1_FUNC xmedia_s32 hal_mipi_enable(xmedia_s32 dev, xmedia_vi_dev_config *dev_config)
{
xmedia_u32 mipi_lane_num = 0;
xmedia_u32 mipi_rx_addr = g_mipi_rx_reg[dev];
xmedia_u32 sys_config_addr = CRG_REGS_ADDR + 0xf8;
mipi_lane_swap_attr lane_swap_mode = { 0 };
// mipi_rx mipi_phy clk enable
vi_reg_write_bit(sys_config_addr, XMEDIA_TRUE, dev); // mipi_rx_cken
if (dev_config->mipi_lane_num == XMEDIA_VI_MIPI_LANE_DIVIDE_MODE_4_LANE) {
vi_reg_write_bit(sys_config_addr, XMEDIA_TRUE, 3); // mipi_rx0_4line_cken
}
vi_reg_write_bit(sys_config_addr, XMEDIA_TRUE, 9); // mipi_phy0_cken
// 延时5 us,等待时钟稳定
sleep_us(5);
// mipi_rx复位
vi_reg_write_bit(mipi_rx_addr + 0x8, XMEDIA_FALSE, 0);
sleep_us(5);
vi_reg_write_bit(mipi_rx_addr + 0x8, XMEDIA_TRUE, 0);
if (dev_config->mipi_lane_num == XMEDIA_VI_MIPI_LANE_DIVIDE_MODE_1_LANE) {
mipi_lane_num = 0x0;
} else if (dev_config->mipi_lane_num == XMEDIA_VI_MIPI_LANE_DIVIDE_MODE_2_LANE) {
mipi_lane_num = 0x1;
} else if (dev_config->mipi_lane_num == XMEDIA_VI_MIPI_LANE_DIVIDE_MODE_4_LANE) {
mipi_lane_num = 0x3;
} else {
// mipi_lane错误参数
puts("vi mipi lane is invalid\n");
}
vi_reg_write_32(mipi_rx_addr + 0x4, mipi_lane_num, 0, 3); // mipi_lane
vi_reg_write_bit(mipi_rx_addr + 0x44, 1, 0); // mipi0_dphy_rstz
vi_reg_write_bit(mipi_rx_addr + 0x40, 1, 0); // mipi0_phy_shutdownz
mipi_rx_set_misc_sel(dev, dev_config->mipi_lane_num);
mipi_rx_phy_get_lane_swap(dev, dev_config, &lane_swap_mode);
mipi_rx_phy_init(dev, dev_config->mipi_rate, dev_config->mipi_lane_num, &lane_swap_mode);
if (dev_config->mipi_lane_num == XMEDIA_VI_MIPI_LANE_DIVIDE_MODE_4_LANE) {
mipi_rx_phy_init(dev + 1, dev_config->mipi_rate, dev_config->mipi_lane_num, &lane_swap_mode);
}
sleep_us(5);
mipi_rx_set_ipi_reg(dev, dev_config->data_type); // ipi cfg, todo:暂不考虑wdr
vi_reg_write_32(mipi_rx_addr + 0x640, 0, 0, 3); // hdr_data_mode,0:VC
vi_reg_write_32(mipi_rx_addr + 0x654, 0x142, 0, 16); // rft_speeder
return XMEDIA_SUCCESS;
}
xmedia_void hal_vi_init(xmedia_void)
{
xmedia_u32 vicap_addr = g_vicap_all_reg[0];
xmedia_u32 viproc_addr = g_viproc_all_reg[0];
// 初始化mipi_rx、vicap、viproc时钟
// vi_reg_write_32(CRG_REGS_ADDR + 0xa0, 0, 0, 3); // bit[0:2]: mipi_rx_clk_sel
vi_reg_write_32(CRG_REGS_ADDR + 0xa0, 0, 3, 3); // bit[3:5]: vicap_clk_sel
vi_reg_write_32(CRG_REGS_ADDR + 0xa0, 0, 6, 3); // bit[6:8]: viproc_clk_sel
// vicap时钟使能,dev、fe复位
vi_vicap_clk_reset_init(0);
// viproc时钟使能、复位,init开启时钟,isp_init需要配置viproc算法寄存器
vi_viproc_clk_reset_init(0);
// vicap viproc outstanding
vi_reg_write_32(vicap_addr + 0x74, 0x88, 0, 9);
vi_reg_write_32(viproc_addr + 0x10, 0x10, 8, 5); // wr outstanding
vi_reg_write_32(viproc_addr + 0x10, 0x20, 16, 6); // rd outstanding
// 屏蔽中断
vi_reg_write_32(vicap_addr + 0x14, 0x7fffff, 0, 23); // top mask
}
xmedia_void hal_vi_exit(xmedia_void)
{
// viproc时钟去使能,dev、fe复位
// vi_viproc_clk_reset_deinit(0);
// vicap时钟去使能,dev、fe复位
vi_vicap_clk_reset_deinit(0);
}
xmedia_s32 hal_vi_enable_dev(xmedia_s32 dev)
{
xmedia_u32 vicap_addr = g_vicap_all_reg[0];
// pt intf modetodo :其他接口待适配
if (dev == 0) {
vi_reg_write_32(vicap_addr + 0xc, 0, 0, 2);
} else if (dev == 1) {
vi_reg_write_32(vicap_addr + 0xc, 0, 2, 2);
} else if (dev == 2) {
vi_reg_write_32(vicap_addr + 0xc, 0, 4, 3);
} else {
puts("dev_id is err ");
putdec(dev);
puts("\n");
}
// enable pt
vi_reg_write_bit(vicap_addr, XMEDIA_TRUE, dev);
if (dev < 2) {
vi_reg_write_bit(vicap_addr + ((dev + 1) * 0x1000), XMEDIA_TRUE, 0); // pt_timing_en
vi_reg_write_bit(vicap_addr + ((dev + 1) * 0x1000), XMEDIA_TRUE, 4); // debug_en
} else {
vi_reg_write_bit(vicap_addr + ((dev + 1) * 0x1000), XMEDIA_TRUE, 0); // pt_timing_en
}
return XMEDIA_SUCCESS;
}
xmedia_void hal_vi_disable_dev(xmedia_s32 dev, xmedia_vi_dev_config *dev_config)
{
xmedia_u32 vicap_addr = g_vicap_all_reg[0];
#if 0
xmedia_u32 mipi_rx_addr = g_mipi_rx_reg[dev];
xmedia_u32 sys_config_addr = CRG_REGS_ADDR + 0xf8;
vi_reg_write_bit(mipi_rx_addr + 0x44, 0, 0); //mipi0_dphy_rstz
vi_reg_write_bit(mipi_rx_addr + 0x40, 0, 0); //mipi0_phy_shutdownz
// mipi_rx mipi_phy clk disable
vi_reg_write_bit(sys_config_addr, 0, dev); // diable mipi_rx clk
vi_reg_write_bit(sys_config_addr, 0, 9 + dev); // diable mipi_rx phy clk
if (dev_config->mipi_lane_num == XMEDIA_VI_MIPI_LANE_DIVIDE_MODE_4_LANE) {
vi_reg_write_bit(sys_config_addr, 0, 9 + dev + 1);
}
#endif
// disable pt
vi_reg_write_bit(vicap_addr, XMEDIA_FALSE, dev);
if (dev < 2) {
vi_reg_write_bit(vicap_addr + ((dev + 1) * 0x1000), XMEDIA_FALSE, 0); // pt_timing_en
vi_reg_write_bit(vicap_addr + ((dev + 1) * 0x1000), XMEDIA_FALSE, 4); // debug_en
vi_reg_write_bit(vicap_addr + ((dev + 1) * 0x1000), XMEDIA_FALSE, 2); // ck_dyn_gt_en
} else {
vi_reg_write_bit(vicap_addr + ((dev + 1) * 0x1000), XMEDIA_FALSE, 0); // pt_timing_en
vi_reg_write_bit(vicap_addr + ((dev + 1) * 0x1000) + 0x2c, XMEDIA_FALSE, 0); // ck_dyn_gt_en
}
}
xmedia_s32 hal_vi_set_dev_bind_pipe(xmedia_s32 dev, xmedia_s32 fe_id)
{
xmedia_u32 vicap_addr = g_vicap_all_reg[0];
vi_reg_write_32(vicap_addr + 0x4, dev, (fe_id * 3), 3);
return XMEDIA_SUCCESS;
}
xmedia_void hal_vi_set_dev_unbind_pipe(xmedia_s32 dev, xmedia_s32 fe_id)
{
xmedia_u32 vicap_addr = g_vicap_all_reg[0];
vi_reg_write_32(vicap_addr + 0x4, 0, (fe_id * 3), 3);
}
xmedia_s32 hal_vi_start_vicap(xmedia_s32 fe_id, xmedia_vi_pipe_config *pipe_config)
{
xmedia_u32 vicap_addr = g_vicap_all_reg[0];
vi_vicap_fe_reset(fe_id, XMEDIA_FALSE);
// 打开对应fe上报中断开关、中断掩码
vi_reg_write_bit(vicap_addr + 0x14, 0, fe_id + 5);
vi_reg_write_32(vicap_addr + ((fe_id + 6) * 0x1000 + 0x3c), 0x6, 0, 16);
// 在线离线工作模式
if (pipe_config->vi_work_mode == 0) {
vi_reg_write_bit(vicap_addr + ((fe_id + 6) * 0x1000), XMEDIA_TRUE, 0); // online_en
vi_reg_write_bit(VIPROC_EXTERNAL_TIMING_EN_ADDR, XMEDIA_TRUE, 1); // viproc_external_timing_en
} else {
vi_reg_write_bit(vicap_addr + ((fe_id + 6) * 0x1000), 0, 0);
vi_reg_write_bit(VIPROC_EXTERNAL_TIMING_EN_ADDR, XMEDIA_FALSE, 1);
}
// 设置early行号、early位置
vi_reg_write_32(vicap_addr + ((fe_id + 6) * 0x1000 + 0x1c), 1, 0, 2);
vi_reg_write_32(vicap_addr + ((fe_id + 6) * 0x1000 + 0x1c), (pipe_config->height * 4 / 5), 8, 13);
// clear_int
vi_reg_write_32(vicap_addr + ((fe_id + 6) * 0x1000 + 0x40), 0xffff, 0, 16);
hal_vi_vicap_online_config(fe_id, pipe_config);
// enable fe
vi_reg_write_bit(vicap_addr, XMEDIA_TRUE, fe_id + 5);
return XMEDIA_SUCCESS;
}
xmedia_void hal_vi_viproc_reg_start(xmedia_u32 viproc_id)
{
xmedia_u32 viproc_addr = g_viproc_all_reg[viproc_id];
vi_reg_write_bit(viproc_addr + 0x14, XMEDIA_TRUE, 0); // ctl_up_finish_enable
vi_reg_write_bit(viproc_addr + 0x14, XMEDIA_TRUE, 4); // filter_up_finish_enable
}
xmedia_void hal_vi_viproc_online_config(xmedia_s32 fe_id, xmedia_vi_pipe_config *pipe_config)
{
xmedia_u32 bit_deepth;
xmedia_u32 viproc_addr = g_viproc_all_reg[0];
// inch0_path_sel
vi_reg_write_32(viproc_addr + 0x174, 0, 1, 2);
// list_mode_enable false
vi_reg_write_bit(viproc_addr + 0x14, 0, 8);
// early line/location
vi_reg_write_32(viproc_addr + 0x1dc, 1, 4, 2);
vi_reg_write_32(viproc_addr + 0x1e0, (pipe_config->height * 4 / 5), 16, 14);
// inch0_en
vi_reg_write_bit(viproc_addr + 0x174, XMEDIA_TRUE, 0);
// inch0_bit_deepth
bit_deepth = vi_viproc_get_bit_deepth(pipe_config->bit_width, pipe_config->wdr_mode);
vi_reg_write_32(viproc_addr + 0x174, bit_deepth, 16, 5);
// input_data_mode
vi_reg_write_bit(viproc_addr + 0x16c, 0, 3);
// valid_in_width/height
vi_reg_write_32(viproc_addr + 0x190, pipe_config->width, 0, 14);
vi_reg_write_32(viproc_addr + 0x190, pipe_config->height, 16, 14);
// early mask
vi_reg_write_32(viproc_addr + 0x1e8, 0x6, 0, 3);
// todo:node id
}
xmedia_s32 hal_vi_start_viproc(xmedia_s32 fe_id, xmedia_vi_pipe_config *pipe_config)
{
xmedia_u32 viproc_addr = g_viproc_all_reg[0];
// vi_viproc_clk_reset_init(0);
// viproc 中断掩码
vi_reg_write_32(viproc_addr + 0x2c, 0x20, 0, 32);
// viproc clear int
vi_reg_write_32(viproc_addr + 0x48, 0xffffffff, 0, 32);
hal_vi_viproc_online_config(fe_id, pipe_config);
// ctl_up_finish_enable/filter_up_finish_enable
hal_vi_viproc_reg_start(0);
return XMEDIA_SUCCESS;
}
xmedia_void hal_vi_stop_viproc(xmedia_s32 fe_id)
{
vi_viproc_clk_reset_deinit(0);
}
xmedia_void hal_vi_stop_vicap(xmedia_s32 fe_id)
{
xmedia_u32 vicap_addr = g_vicap_all_reg[0];
// disable fe
vi_reg_write_bit(vicap_addr, XMEDIA_FALSE, fe_id + 5);
// ck_dyn_gt_en_enable
vi_reg_write_bit(vicap_addr + ((fe_id + 6) * 0x1000 + 0xa0), XMEDIA_FALSE, 0);
// int none mask
vi_reg_write_32(vicap_addr + ((fe_id + 6) * 0x1000 + 0x3c), 0xffff, 0, 16);
// clear int
vi_reg_write_32(vicap_addr + ((fe_id + 6) * 0x1000 + 0x40), 0xffff, 0, 16);
vi_vicap_fe_reset(fe_id, XMEDIA_TRUE);
vi_vicap_fe_reset(fe_id, XMEDIA_FALSE);
}