1 #include "bflb_csi.h"
2 #include "hardware/csi_reg.h"
3 #include "hardware/dtsrc_reg.h"
4
5 #define DTSRC_BASE 0x30012800
6
bflb_csi_phy_config(struct bflb_device_s * dev,uint32_t tx_clk_escape,uint32_t data_rate)7 static void bflb_csi_phy_config(struct bflb_device_s *dev, uint32_t tx_clk_escape, uint32_t data_rate)
8 {
9 uint32_t reg_base;
10 uint32_t regval;
11
12 /* Unit: ns */
13 float TD_TERM_EN_MAX = 35 + 4 * (1e3) / data_rate;
14 uint32_t TD_TERM_EN = (TD_TERM_EN_MAX * data_rate / 2 / (1e3)) - 1;
15 float THS_SETTLE_MAX = 145 + 10 * (1e3) / data_rate;
16 /* THS_SETTLE = reg_time_hs_settle + reg_time_hs_term_en */
17 uint32_t THS_SETTLE = ((THS_SETTLE_MAX - TD_TERM_EN * 2 * (1e3) / data_rate) * data_rate / 2 / (1e3)) - 1;
18 uint32_t TCLK_TERM_EN_MAX = 38;
19 uint32_t TCLK_TERM_EN = (tx_clk_escape * TCLK_TERM_EN_MAX) / (1e3);
20 uint32_t TCLK_SETTLE_MAX = 300;
21 /* TCLK_SETTLE = reg_time_ck_settle + reg_time_ck_term_en */
22 uint32_t TCLK_SETTLE = ((TCLK_SETTLE_MAX - TCLK_TERM_EN * (1e3) / tx_clk_escape) * tx_clk_escape / (1e3)) - 1;
23
24 uint32_t ANA_TERM_EN = 0x8;
25
26 reg_base = dev->reg_base;
27 regval = TD_TERM_EN << CSI_REG_TIME_HS_TERM_EN_SHIFT & CSI_REG_TIME_HS_TERM_EN_MASK;
28 regval |= THS_SETTLE << CSI_REG_TIME_HS_SETTLE_SHIFT & CSI_REG_TIME_HS_SETTLE_MASK;
29 regval |= TCLK_TERM_EN << CSI_REG_TIME_CK_TERM_EN_SHIFT & CSI_REG_TIME_CK_TERM_EN_MASK;
30 regval |= TCLK_SETTLE << CSI_REG_TIME_CK_SETTLE_SHIFT & CSI_REG_TIME_CK_SETTLE_MASK;
31 putreg32(regval, reg_base + CSI_DPHY_CONFIG_1_OFFSET);
32
33 regval = getreg32(DTSRC_BASE + CSI_DPHY_CONFIG_2_OFFSET);
34 regval &= ~CSI_REG_ANA_TERM_EN_MASK;
35 regval |= ANA_TERM_EN << CSI_REG_ANA_TERM_EN_SHIFT & CSI_REG_ANA_TERM_EN_MASK;
36 putreg32(regval, reg_base + CSI_DPHY_CONFIG_2_OFFSET);
37 }
38
bflb_csi_init(struct bflb_device_s * dev,const struct bflb_csi_config_s * config)39 void bflb_csi_init(struct bflb_device_s *dev, const struct bflb_csi_config_s *config)
40 {
41 uint32_t reg_base;
42 uint32_t regval;
43
44 reg_base = dev->reg_base;
45 regval = getreg32(DTSRC_BASE + DTSRC_CONFIG_OFFSET);
46 regval |= DTSRC_CR_SNSR_EN;
47 putreg32(regval, DTSRC_BASE + DTSRC_CONFIG_OFFSET);
48
49 regval = getreg32(reg_base + CSI_DPHY_CONFIG_0_OFFSET);
50 regval &= ~(CSI_DL0_ENABLE | CSI_DL1_ENABLE | CSI_CL_ENABLE | CSI_DL0_FORCERXMODE | CSI_DL1_FORCERXMODE | CSI_RESET_N);
51 putreg32(regval, reg_base + CSI_DPHY_CONFIG_0_OFFSET);
52 regval |= CSI_RESET_N;
53 putreg32(regval, reg_base + CSI_DPHY_CONFIG_0_OFFSET);
54
55 regval = getreg32(reg_base + CSI_MIPI_CONFIG_OFFSET);
56 if (config->lane_number) {
57 regval |= CSI_CR_LANE_NUM;
58 } else {
59 regval &= ~CSI_CR_LANE_NUM;
60 }
61 regval |= CSI_CR_UNPACK_EN | CSI_CR_SYNC_SP_EN;
62 putreg32(regval, reg_base + CSI_MIPI_CONFIG_OFFSET);
63
64 bflb_csi_phy_config(dev, config->tx_clk_escape / 1000000, config->data_rate / 1000000);
65
66 regval = getreg32(reg_base + CSI_DPHY_CONFIG_0_OFFSET);
67 regval |= CSI_DL0_ENABLE | CSI_CL_ENABLE | CSI_DL0_FORCERXMODE;
68 if (config->lane_number) {
69 regval |= CSI_DL1_ENABLE | CSI_DL1_FORCERXMODE;
70 }
71 putreg32(regval, reg_base + CSI_DPHY_CONFIG_0_OFFSET);
72
73 regval = getreg32(DTSRC_BASE + DTSRC_CONFIG_OFFSET);
74 regval |= DTSRC_CR_ENABLE;
75 putreg32(regval, DTSRC_BASE + DTSRC_CONFIG_OFFSET);
76 }
77
bflb_csi_start(struct bflb_device_s * dev)78 void bflb_csi_start(struct bflb_device_s *dev)
79 {
80 uint32_t reg_base;
81 uint32_t regval;
82
83 reg_base = dev->reg_base;
84 regval = getreg32(reg_base + CSI_MIPI_CONFIG_OFFSET);
85 regval |= CSI_CR_CSI_EN;
86 putreg32(regval, reg_base + CSI_MIPI_CONFIG_OFFSET);
87 }
88
bflb_csi_stop(struct bflb_device_s * dev)89 void bflb_csi_stop(struct bflb_device_s *dev)
90 {
91 uint32_t reg_base;
92 uint32_t regval;
93
94 reg_base = dev->reg_base;
95 regval = getreg32(reg_base + CSI_MIPI_CONFIG_OFFSET);
96 regval &= ~CSI_CR_CSI_EN;
97 putreg32(regval, reg_base + CSI_MIPI_CONFIG_OFFSET);
98 }
99
bflb_csi_set_line_threshold(struct bflb_device_s * dev,uint16_t resolution_x,uint32_t pixel_clock,uint32_t dsp_clock)100 void bflb_csi_set_line_threshold(struct bflb_device_s *dev, uint16_t resolution_x, uint32_t pixel_clock, uint32_t dsp_clock)
101 {
102 uint32_t threshold;
103
104 threshold = (dsp_clock - pixel_clock) / 1000 * resolution_x / (dsp_clock / 1000) + 10;
105 putreg32(threshold, DTSRC_BASE + DTSRC_SNSR2DVP_WAIT_POS_OFFSET);
106 }
107
bflb_csi_int_mask(struct bflb_device_s * dev,uint32_t int_type,bool mask)108 void bflb_csi_int_mask(struct bflb_device_s *dev, uint32_t int_type, bool mask)
109 {
110 uint32_t reg_base;
111 uint32_t regval;
112
113 reg_base = dev->reg_base;
114 regval = getreg32(reg_base + CSI_INT_MASK_OFFSET);
115 if (mask) {
116 regval |= int_type;
117 } else {
118 regval &= ~int_type;
119 }
120 putreg32(regval, reg_base + CSI_INT_MASK_OFFSET);
121 }
122
bflb_csi_int_clear(struct bflb_device_s * dev,uint32_t int_type)123 void bflb_csi_int_clear(struct bflb_device_s *dev, uint32_t int_type)
124 {
125 putreg32(int_type, dev->reg_base + CSI_INT_CLEAR_OFFSET);
126 }
127
bflb_csi_get_intstatus(struct bflb_device_s * dev)128 uint32_t bflb_csi_get_intstatus(struct bflb_device_s *dev)
129 {
130 return(getreg32(dev->reg_base + CSI_INT_STATUS_OFFSET));
131 }
132
bflb_csi_feature_control(struct bflb_device_s * dev,int cmd,size_t arg)133 int bflb_csi_feature_control(struct bflb_device_s *dev, int cmd, size_t arg)
134 {
135 int ret = 0;
136
137 switch (cmd) {
138 default:
139 ret = -EPERM;
140 break;
141 }
142 return ret;
143 }
144