Files

933 lines
30 KiB
C
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#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);
}