1 /*
2 * Copyright (c) 2023 HPMicro
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7
8 #include "hpm_common.h"
9 #include "hpm_lvb_drv.h"
10
lvb_get_default_config(lvb_config_t * cfg)11 void lvb_get_default_config(lvb_config_t *cfg)
12 {
13 cfg->split_ch_is_reverse = false;
14 cfg->split_ch_data_is_unaligned = false;
15 cfg->split_hswhbp_width_is_even = true;
16 cfg->split_mode_en = false;
17 cfg->di0_vsync_polarity = lvb_di_vsync_polarity_active_high;
18 cfg->di1_vsync_polarity = lvb_di_vsync_polarity_active_high;
19 cfg->txclk_shift = lvb_txclk_shift_1100011;
20 }
21
lvb_init(LVB_Type * ptr,lvb_config_t * cfg)22 void lvb_init(LVB_Type *ptr, lvb_config_t *cfg)
23 {
24 ptr->CTRL = (ptr->CTRL & ~(LVB_CTRL_SPLIT_CH_REVERSE_MASK |
25 LVB_CTRL_SPLIT_CH_MODE_MASK |
26 LVB_CTRL_SPLIT_HSWHBP_WIDTH_MASK |
27 LVB_CTRL_SPLIT_MODE_EN_MASK |
28 LVB_CTRL_DI1_VSYNC_POLARITY_MASK |
29 LVB_CTRL_DI0_VSYNC_POLARITY_MASK |
30 LVB_CTRL_LVDS_TXCLK_SHIFT_MASK)) |
31 LVB_CTRL_SPLIT_CH_REVERSE_SET(cfg->split_ch_is_reverse) |
32 LVB_CTRL_SPLIT_CH_MODE_SET(cfg->split_ch_data_is_unaligned) |
33 LVB_CTRL_SPLIT_HSWHBP_WIDTH_SET(cfg->split_hswhbp_width_is_even) |
34 LVB_CTRL_SPLIT_MODE_EN_SET(cfg->split_mode_en) |
35 LVB_CTRL_DI1_VSYNC_POLARITY_SET(cfg->di1_vsync_polarity) |
36 LVB_CTRL_DI0_VSYNC_POLARITY_SET(cfg->di0_vsync_polarity) |
37 LVB_CTRL_LVDS_TXCLK_SHIFT_SET(cfg->txclk_shift);
38 }
39
lvb_get_ch_default_config(lvb_ch_config_t * ch_cfg)40 void lvb_get_ch_default_config(lvb_ch_config_t *ch_cfg)
41 {
42 ch_cfg->data_src = lvb_ch_data_source_di0;
43 ch_cfg->map = lvb_ch_mapping_vesa;
44 }
45
lvb_ch_config(LVB_Type * ptr,lvb_ch_num_t ch_num,lvb_ch_config_t * ch_cfg)46 void lvb_ch_config(LVB_Type *ptr, lvb_ch_num_t ch_num, lvb_ch_config_t *ch_cfg)
47 {
48 uint32_t reg_val;
49
50 if (ch_num == lvb_ch_num_0) {
51 reg_val = (ptr->CTRL & ~(LVB_CTRL_CH0_BIT_MAPPING_MASK | LVB_CTRL_CH0_SEL_MASK)) |
52 LVB_CTRL_CH0_BIT_MAPPING_SET(ch_cfg->map) |
53 LVB_CTRL_CH0_SEL_SET(ch_cfg->data_src);
54 } else {
55 reg_val = (ptr->CTRL & ~(LVB_CTRL_CH1_BIT_MAPPING_MASK | LVB_CTRL_CH1_SEL_MASK)) |
56 LVB_CTRL_CH1_BIT_MAPPING_SET(ch_cfg->map) |
57 LVB_CTRL_CH1_SEL_SET(ch_cfg->data_src);
58 }
59
60 ptr->CTRL = reg_val;
61 }
62
lvb_ch_enable(LVB_Type * ptr,lvb_ch_num_t ch_num)63 void lvb_ch_enable(LVB_Type *ptr, lvb_ch_num_t ch_num)
64 {
65 if (ch_num == lvb_ch_num_0) {
66 ptr->CTRL |= LVB_CTRL_CH0_EN_MASK;
67 } else {
68 ptr->CTRL |= LVB_CTRL_CH1_EN_MASK;
69 }
70 }
71
lvb_ch_disable(LVB_Type * ptr,lvb_ch_num_t ch_num)72 void lvb_ch_disable(LVB_Type *ptr, lvb_ch_num_t ch_num)
73 {
74 if (ch_num == lvb_ch_num_0) {
75 ptr->CTRL &= ~LVB_CTRL_CH0_EN_MASK;
76 } else {
77 ptr->CTRL &= ~LVB_CTRL_CH1_EN_MASK;
78 }
79 }
80
lvb_lvds_phy_lane_get_default_config(lvb_lvds_phy_lane_config_t * cfg)81 void lvb_lvds_phy_lane_get_default_config(lvb_lvds_phy_lane_config_t *cfg)
82 {
83 cfg->tx_idle = false;
84 cfg->rterm_enable = true;
85 cfg->phase_sel = lvb_lvds_lane_phase_sel_4_16_ui;
86 cfg->amp = lvb_lvds_lane_amp_300_mv;
87 cfg->vcom = lvb_lvds_lane_vcom_1_2_v;
88 cfg->fvco_div4 = true;
89 }
90
lvb_lvds_phy_lane_init(LVB_Type * ptr,lvb_lvds_lane_idx_t tx_index,lvb_lvds_phy_lane_config_t * cfg)91 void lvb_lvds_phy_lane_init(LVB_Type *ptr, lvb_lvds_lane_idx_t tx_index, lvb_lvds_phy_lane_config_t *cfg)
92 {
93 ptr->TX_PHY[tx_index].CTL0 = (ptr->TX_PHY[tx_index].CTL0 & ~(LVB_TX_PHY_CTL0_TX_IDLE_MASK |
94 LVB_TX_PHY_CTL0_TX_RTERM_EN_MASK |
95 LVB_TX_PHY_CTL0_TX_BUS_WIDTH_MASK |
96 LVB_TX_PHY_CTL0_TX_PHASE_SEL_MASK |
97 LVB_TX_PHY_CTL0_TX_VCOM_MASK |
98 LVB_TX_PHY_CTL0_TX_AMP_MASK)) |
99 (cfg->tx_idle ? LVB_TX_PHY_CTL0_TX_IDLE_MASK : 0) |
100 (cfg->rterm_enable ? LVB_TX_PHY_CTL0_TX_RTERM_EN_MASK : 0) |
101 LVB_TX_PHY_CTL0_TX_BUS_WIDTH_SET(2) | /* only 7bit */
102 LVB_TX_PHY_CTL0_TX_PHASE_SEL_SET(cfg->phase_sel) |
103 LVB_TX_PHY_CTL0_TX_VCOM_SET(cfg->vcom) |
104 LVB_TX_PHY_CTL0_TX_AMP_SET(cfg->amp);
105
106 if (cfg->fvco_div4) {
107 ptr->TX_PHY[tx_index].CTL0 |= (1ul<<7);
108 } else {
109 ptr->TX_PHY[tx_index].CTL0 &= ~(1ul<<7);
110 }
111 }
112
lvb_lvds_phy0_poweron(LVB_Type * ptr)113 void lvb_lvds_phy0_poweron(LVB_Type *ptr)
114 {
115 ptr->PHY_POW_CTRL[0] = (ptr->PHY_POW_CTRL[0] & ~(LVB_PHY_POW_CTRL_TXCK_PD_MASK |
116 LVB_PHY_POW_CTRL_TX3_PD_MASK | LVB_PHY_POW_CTRL_TX2_PD_MASK |
117 LVB_PHY_POW_CTRL_TX1_PD_MASK | LVB_PHY_POW_CTRL_TX0_PD_MASK)) |
118 LVB_PHY_POW_CTRL_PWON_PLL_MASK;
119 }
120
lvb_lvds_phy1_poweron(LVB_Type * ptr)121 void lvb_lvds_phy1_poweron(LVB_Type *ptr)
122 {
123 ptr->PHY_POW_CTRL[1] = (ptr->PHY_POW_CTRL[1] & ~(LVB_PHY_POW_CTRL_TXCK_PD_MASK |
124 LVB_PHY_POW_CTRL_TX3_PD_MASK | LVB_PHY_POW_CTRL_TX2_PD_MASK |
125 LVB_PHY_POW_CTRL_TX1_PD_MASK | LVB_PHY_POW_CTRL_TX0_PD_MASK)) |
126 LVB_PHY_POW_CTRL_PWON_PLL_MASK;
127 }
128
lvb_lvds_phy0_powerdown(LVB_Type * ptr)129 void lvb_lvds_phy0_powerdown(LVB_Type *ptr)
130 {
131 ptr->PHY_POW_CTRL[0] = (ptr->PHY_POW_CTRL[0] & ~LVB_PHY_POW_CTRL_PWON_PLL_MASK) |
132 LVB_PHY_POW_CTRL_TXCK_PD_MASK | LVB_PHY_POW_CTRL_TX3_PD_MASK |
133 LVB_PHY_POW_CTRL_TX2_PD_MASK | LVB_PHY_POW_CTRL_TX1_PD_MASK |
134 LVB_PHY_POW_CTRL_TX0_PD_MASK;
135 }
136
lvb_lvds_phy1_powerdown(LVB_Type * ptr)137 void lvb_lvds_phy1_powerdown(LVB_Type *ptr)
138 {
139 ptr->PHY_POW_CTRL[1] = (ptr->PHY_POW_CTRL[1] & ~LVB_PHY_POW_CTRL_PWON_PLL_MASK) |
140 LVB_PHY_POW_CTRL_TXCK_PD_MASK | LVB_PHY_POW_CTRL_TX3_PD_MASK |
141 LVB_PHY_POW_CTRL_TX2_PD_MASK | LVB_PHY_POW_CTRL_TX1_PD_MASK |
142 LVB_PHY_POW_CTRL_TX0_PD_MASK;
143 }