1 /*
2 * Copyright (c) 2023 HPMicro
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7
8 #ifndef HPM_LVB_DRV_H
9 #define HPM_LVB_DRV_H
10
11 /**
12 * @brief LVB APIs
13 * @defgroup lvb_interface LVB driver APIs
14 * @ingroup lvb_interfaces
15 * @{
16 */
17
18 #include "hpm_common.h"
19 #include "hpm_soc.h"
20 #include "hpm_lvb_regs.h"
21
22 /**
23 * @brief LVB DI vsync polarity
24 */
25 typedef enum lvb_di_vsync_polarity {
26 lvb_di_vsync_polarity_active_high = 0,
27 lvb_di_vsync_polarity_active_low
28 } lvb_di_vsync_polarity_t;
29
30 /**
31 * @brief Shift the LVDS TX PHY clock in relation to the data
32 */
33 typedef enum lvb_txclk_shift {
34 lvb_txclk_shift_1100011 = 0,
35 lvb_txclk_shift_1110001,
36 lvb_txclk_shift_1111000,
37 lvb_txclk_shift_1000111,
38 lvb_txclk_shift_0001111,
39 lvb_txclk_shift_0011110,
40 lvb_txclk_shift_0111100,
41 } lvb_txclk_shift_t;
42
43 /**
44 * @brief LVB config
45 */
46 typedef struct lvb_config {
47 bool split_ch_is_reverse; /*!< Just for split mode, reverse two channel data */
48 bool split_ch_data_is_unaligned; /*!< Just for split mode, two channel pixel data are aligned */
49 bool split_hswhbp_width_is_even; /*!< Just for split mode, the sum of HSW and HBP width is even */
50 bool split_mode_en; /*!< Note: when using split mode, ch0/1 should be enabled, and should select same DI */
51 lvb_di_vsync_polarity_t di1_vsync_polarity; /*!< lvb di1 vsync polarity */
52 lvb_di_vsync_polarity_t di0_vsync_polarity; /*!< lvb di0 vsync polarity */
53 lvb_txclk_shift_t txclk_shift; /*!< Shift the LVDS TX PHY clock in relation to the data */
54 } lvb_config_t;
55
56 /**
57 * @brief LVB channel pixel data mapping
58 */
59 typedef enum lvb_ch_mapping {
60 lvb_ch_mapping_vesa = 0,
61 lvb_ch_mapping_jeida,
62 } lvb_ch_mapping_t;
63
64 /**
65 * @brief LVB channel pixel data source
66 */
67 typedef enum lvb_ch_data_source {
68 lvb_ch_data_source_di0 = 0,
69 lvb_ch_data_source_di1,
70 } lv_ch_data_source_t;
71
72 /**
73 * @brief LVB channel number
74 */
75 typedef enum lvb_ch_num {
76 lvb_ch_num_0 = 0,
77 lvb_ch_num_1 = 1
78 } lvb_ch_num_t;
79
80 /**
81 * @brief LVB channel config
82 */
83 typedef struct lvb_ch_config {
84 lvb_ch_mapping_t map;
85 lv_ch_data_source_t data_src;
86 } lvb_ch_config_t;
87
88 typedef enum lvb_lvds_lane_phase_sel {
89 lvb_lvds_lane_phase_sel_0_ui = 0,
90 lvb_lvds_lane_phase_sel_1_16_ui,
91 lvb_lvds_lane_phase_sel_2_16_ui,
92 lvb_lvds_lane_phase_sel_3_16_ui,
93 lvb_lvds_lane_phase_sel_4_16_ui,
94 lvb_lvds_lane_phase_sel_5_16_ui,
95 lvb_lvds_lane_phase_sel_6_16_ui,
96 lvb_lvds_lane_phase_sel_7_16_ui,
97 lvb_lvds_lane_phase_sel_8_16_ui,
98 lvb_lvds_lane_phase_sel_9_16_ui,
99 lvb_lvds_lane_phase_sel_10_16_ui,
100 lvb_lvds_lane_phase_sel_11_16_ui,
101 lvb_lvds_lane_phase_sel_12_16_ui,
102 lvb_lvds_lane_phase_sel_13_16_ui,
103 lvb_lvds_lane_phase_sel_14_16_ui,
104 lvb_lvds_lane_phase_sel_15_16_ui,
105 } lvb_lvds_lane_phase_sel_t;
106
107 typedef enum lvb_lvds_lane_amp {
108 lvb_lvds_lane_amp_50_mv = 0,
109 lvb_lvds_lane_amp_100_mv,
110 lvb_lvds_lane_amp_150_mv,
111 lvb_lvds_lane_amp_200_mv,
112 lvb_lvds_lane_amp_250_mv,
113 lvb_lvds_lane_amp_300_mv,
114 lvb_lvds_lane_amp_350_mv,
115 lvb_lvds_lane_amp_400_mv,
116 lvb_lvds_lane_amp_450_mv,
117 lvb_lvds_lane_amp_500_mv,
118 lvb_lvds_lane_amp_550_mv,
119 lvb_lvds_lane_amp_600_mv
120 } lvb_lvds_lane_amp_t;
121
122 typedef enum lvb_lvds_lane_vcom {
123 lvb_lvds_lane_vcom_0_7_v = 0,
124 lvb_lvds_lane_vcom_0_8_v,
125 lvb_lvds_lane_vcom_0_9_v,
126 lvb_lvds_lane_vcom_1_0_v,
127 lvb_lvds_lane_vcom_1_1_v,
128 lvb_lvds_lane_vcom_1_2_v,
129 lvb_lvds_lane_vcom_1_3_v,
130 lvb_lvds_lane_vcom_1_4_v,
131 lvb_lvds_lane_vcom_1_5_v,
132 } lvb_lvds_lane_vcom_t;
133
134 typedef struct lvb_lvds_phy_lane_config {
135 bool rterm_enable;
136 bool tx_idle;
137 lvb_lvds_lane_phase_sel_t phase_sel;
138 lvb_lvds_lane_amp_t amp;
139 lvb_lvds_lane_vcom_t vcom;
140 bool fvco_div4;
141 } lvb_lvds_phy_lane_config_t;
142
143 typedef enum lvb_lvds_lane_idx {
144 lvb_lvds_lane_idx_lvds0_tx0 = LVB_TX_PHY_LVDS0_TX0,
145 lvb_lvds_lane_idx_lvds0_tx1 = LVB_TX_PHY_LVDS0_TX1,
146 lvb_lvds_lane_idx_lvds0_tx2 = LVB_TX_PHY_LVDS0_TX2,
147 lvb_lvds_lane_idx_lvds0_tx3 = LVB_TX_PHY_LVDS0_TX3,
148 lvb_lvds_lane_idx_lvds0_txck = LVB_TX_PHY_LVDS0_TXCK,
149 lvb_lvds_lane_idx_lvds1_tx0 = LVB_TX_PHY_LVDS1_TX0,
150 lvb_lvds_lane_idx_lvds1_tx1 = LVB_TX_PHY_LVDS1_TX1,
151 lvb_lvds_lane_idx_lvds1_tx2 = LVB_TX_PHY_LVDS1_TX2,
152 lvb_lvds_lane_idx_lvds1_tx3 = LVB_TX_PHY_LVDS1_TX3,
153 lvb_lvds_lane_idx_lvds1_txck = LVB_TX_PHY_LVDS1_TXCK,
154 } lvb_lvds_lane_idx_t;
155
156 #ifdef __cplusplus
157 extern "C" {
158 #endif
159
160 /**
161 * @brief get LVB of default config
162 *
163 * @param[out] cfg config of LVB
164 */
165 void lvb_get_default_config(lvb_config_t *cfg);
166
167 /**
168 * @brief LVB init
169 *
170 * @param[in] ptr LVB base address
171 * @param[in] cfg config of LVB
172 */
173 void lvb_init(LVB_Type *ptr, lvb_config_t *cfg);
174
175 /**
176 * @brief get LVB channel of default config
177 *
178 * @param[out] cfg config of LVB
179 */
180 void lvb_get_ch_default_config(lvb_ch_config_t *ch_cfg);
181
182 /**
183 * @brief LVB channel config
184 *
185 * @param[in] ptr LVB base address
186 * @param[in] ch_num LVB channel number
187 * @param[in] cfg config of LVB channel
188 */
189 void lvb_ch_config(LVB_Type *ptr, lvb_ch_num_t ch_num, lvb_ch_config_t *ch_cfg);
190
191 /**
192 * @brief LVB channel enable
193 *
194 * @param[in] ptr LVB base address
195 * @param[in] ch_num LVB channel number
196 */
197 void lvb_ch_enable(LVB_Type *ptr, lvb_ch_num_t ch_num);
198
199 /**
200 * @brief LVB channel disable
201 *
202 * @param[in] ptr LVB base address
203 * @param[in] ch_num LVB channel number
204 */
205 void lvb_ch_disable(LVB_Type *ptr, lvb_ch_num_t ch_num);
206
207 /**
208 * @brief check LVB phy0 is lock
209 *
210 * @param[in] ptr LVB base address
211 */
lvb_lvds_phy0_pll_is_lock(LVB_Type * ptr)212 static inline bool lvb_lvds_phy0_pll_is_lock(LVB_Type *ptr)
213 {
214 return !!LVB_PHY_STAT_LVDS0_TX_PHY_PLL_LOCK_GET(ptr->PHY_STAT);
215 }
216
217 /**
218 * @brief check LVB phy1 is lock
219 *
220 * @param[in] ptr LVB base address
221 */
lvb_lvds_phy1_pll_is_lock(LVB_Type * ptr)222 static inline bool lvb_lvds_phy1_pll_is_lock(LVB_Type *ptr)
223 {
224 return !!LVB_PHY_STAT_LVDS1_TX_PHY_PLL_LOCK_GET(ptr->PHY_STAT);
225 }
226
227 /**
228 * @brief check LVB phy0 and phy1 is lock
229 *
230 * @param[in] ptr LVB base address
231 */
lvb_lvds_phy_split_pll_is_lock(LVB_Type * ptr)232 static inline bool lvb_lvds_phy_split_pll_is_lock(LVB_Type *ptr)
233 {
234 return !!LVB_PHY_STAT_LVDS0_TX_PHY_PLL_LOCK_GET(ptr->PHY_STAT) &&
235 !!LVB_PHY_STAT_LVDS1_TX_PHY_PLL_LOCK_GET(ptr->PHY_STAT);
236 }
237
238 /**
239 * @brief lvb lvds lane get default config
240 *
241 * @param[out] cfg lvds lane config @ref lvb_lvds_phy_lane_config_t
242 */
243 void lvb_lvds_phy_lane_get_default_config(lvb_lvds_phy_lane_config_t *cfg);
244
245 /**
246 * @brief lvb lvds lane init and config
247 *
248 * @param[in] ptr LVB base address
249 * @param[in] tx_index lvds phy lane index @ref lvb_lvds_lane_idx_t
250 * @param[in] cfg lvds lane config @ref lvb_lvds_phy_lane_config_t
251 */
252 void lvb_lvds_phy_lane_init(LVB_Type *ptr, lvb_lvds_lane_idx_t tx_index, lvb_lvds_phy_lane_config_t *cfg);
253
254 /**
255 * @brief power on LVB phy0
256 *
257 * @param[in] ptr LVB base address
258 */
259 void lvb_lvds_phy0_poweron(LVB_Type *ptr);
260
261 /**
262 * @brief power on LVB phy1
263 *
264 * @param[in] ptr LVB base address
265 */
266 void lvb_lvds_phy1_poweron(LVB_Type *ptr);
267
268 /**
269 * @brief power down LVB phy0
270 *
271 * @param[in] ptr LVB base address
272 */
273 void lvb_lvds_phy0_powerdown(LVB_Type *ptr);
274
275 /**
276 * @brief power down LVB phy0
277 *
278 * @param[in] ptr LVB base address
279 */
280 void lvb_lvds_phy1_powerdown(LVB_Type *ptr);
281
282 #ifdef __cplusplus
283 }
284 #endif
285
286 /**
287 * @}
288 */
289 #endif /* HPM_LVB_DRV_H */
290