• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_pixelmux_drv.h"
10 
pixelmux_rgb_data_source_enable(pixelmux_rgb_select_t src)11 void pixelmux_rgb_data_source_enable(pixelmux_rgb_select_t src)
12 {
13     uint32_t reg_val = (HPM_PIXEL_MUX->PIXMUX & ~PIXELMUX_PIXMUX_RGB_SEL_MASK) |
14                         PIXELMUX_PIXMUX_RGB_EN_MASK | PIXELMUX_PIXMUX_RGB_SEL_SET(src);
15     HPM_PIXEL_MUX->PIXMUX = reg_val;
16 }
17 
pixelmux_rgb_data_source_disable(void)18 void pixelmux_rgb_data_source_disable(void)
19 {
20     HPM_PIXEL_MUX->PIXMUX &= ~PIXELMUX_PIXMUX_RGB_SEL_MASK;
21 }
22 
pixelmux_gwc1_data_source_enable(pixelmux_gwc1_select_t src)23 void pixelmux_gwc1_data_source_enable(pixelmux_gwc1_select_t src)
24 {
25     uint32_t reg_val = (HPM_PIXEL_MUX->PIXMUX & ~PIXELMUX_PIXMUX_GWC1_SEL_MASK) |
26                         PIXELMUX_PIXMUX_GWC1_EN_MASK | PIXELMUX_PIXMUX_GWC1_SEL_SET(src);
27     HPM_PIXEL_MUX->PIXMUX = reg_val;
28 }
29 
pixelmux_gwc1_data_source_disable(void)30 void pixelmux_gwc1_data_source_disable(void)
31 {
32     HPM_PIXEL_MUX->PIXMUX &= ~PIXELMUX_PIXMUX_GWC1_EN_MASK;
33 }
34 
pixelmux_gwc0_data_source_enable(pixelmux_gwc0_select_t src)35 void pixelmux_gwc0_data_source_enable(pixelmux_gwc0_select_t src)
36 {
37     uint32_t reg_val = (HPM_PIXEL_MUX->PIXMUX & ~PIXELMUX_PIXMUX_GWC0_SEL_MASK) |
38                         PIXELMUX_PIXMUX_GWC0_EN_MASK | PIXELMUX_PIXMUX_GWC0_SEL_SET(src);
39     HPM_PIXEL_MUX->PIXMUX = reg_val;
40 }
41 
pixelmux_gwc0_data_source_disable(void)42 void pixelmux_gwc0_data_source_disable(void)
43 {
44     HPM_PIXEL_MUX->PIXMUX &= ~PIXELMUX_PIXMUX_GWC0_EN_MASK;
45 }
46 
pixelmux_lvb_di1_data_source_enable(pixelmux_lvb_di1_select_t src)47 void pixelmux_lvb_di1_data_source_enable(pixelmux_lvb_di1_select_t src)
48 {
49     uint32_t reg_val = (HPM_PIXEL_MUX->PIXMUX & ~PIXELMUX_PIXMUX_LVB_DI1_SEL_MASK) |
50                         PIXELMUX_PIXMUX_LVB_DI1_EN_MASK | PIXELMUX_PIXMUX_LVB_DI1_SEL_SET(src);
51     HPM_PIXEL_MUX->PIXMUX = reg_val;
52 }
53 
pixelmux_lvb_di1_data_source_disable(void)54 void pixelmux_lvb_di1_data_source_disable(void)
55 {
56     HPM_PIXEL_MUX->PIXMUX &= ~PIXELMUX_PIXMUX_LVB_DI1_EN_MASK;
57 }
58 
pixelmux_lvb_di0_data_source_enable(pixelmux_lvb_di0_select_t src)59 void pixelmux_lvb_di0_data_source_enable(pixelmux_lvb_di0_select_t src)
60 {
61     uint32_t reg_val = (HPM_PIXEL_MUX->PIXMUX & ~PIXELMUX_PIXMUX_LVB_DI0_SEL_MASK) |
62                         PIXELMUX_PIXMUX_LVB_DI0_EN_MASK | PIXELMUX_PIXMUX_LVB_DI0_SEL_SET(src);
63     HPM_PIXEL_MUX->PIXMUX = reg_val;
64 }
65 
pixelmux_lvb_di0_data_source_disable(void)66 void pixelmux_lvb_di0_data_source_disable(void)
67 {
68     HPM_PIXEL_MUX->PIXMUX &= ~PIXELMUX_PIXMUX_LVB_DI0_EN_MASK;
69 }
70 
pixelmux_mipi_dsi1_data_source_enable(pixelmux_mipi_dsi1_select_t src)71 void pixelmux_mipi_dsi1_data_source_enable(pixelmux_mipi_dsi1_select_t src)
72 {
73     uint32_t reg_val = (HPM_PIXEL_MUX->PIXMUX & ~PIXELMUX_PIXMUX_DSI1_SEL_MASK) |
74                         PIXELMUX_PIXMUX_DSI1_EN_MASK | PIXELMUX_PIXMUX_DSI1_SEL_SET(src);
75     HPM_PIXEL_MUX->PIXMUX = reg_val;
76 }
77 
pixelmux_mipi_dsi1_data_source_disable(void)78 void pixelmux_mipi_dsi1_data_source_disable(void)
79 {
80     HPM_PIXEL_MUX->PIXMUX &= ~PIXELMUX_PIXMUX_DSI1_EN_MASK;
81 }
82 
pixelmux_mipi_dsi0_data_source_enable(pixelmux_mipi_dsi0_select_t src)83 void pixelmux_mipi_dsi0_data_source_enable(pixelmux_mipi_dsi0_select_t src)
84 {
85     uint32_t reg_val = (HPM_PIXEL_MUX->PIXMUX & ~PIXELMUX_PIXMUX_DSI0_SEL_MASK) |
86                         PIXELMUX_PIXMUX_DSI0_EN_MASK | PIXELMUX_PIXMUX_DSI0_SEL_SET(src);
87     HPM_PIXEL_MUX->PIXMUX = reg_val;
88 }
89 
pixelmux_mipi_dsi0_data_source_disable(void)90 void pixelmux_mipi_dsi0_data_source_disable(void)
91 {
92     HPM_PIXEL_MUX->PIXMUX &= ~PIXELMUX_PIXMUX_DSI0_EN_MASK;
93 }
94 
pixelmux_cam1_data_source_enable(pixelmux_cam1_select_t src)95 void pixelmux_cam1_data_source_enable(pixelmux_cam1_select_t src)
96 {
97     uint32_t reg_val = (HPM_PIXEL_MUX->PIXMUX & ~PIXELMUX_PIXMUX_CAM1_SEL_MASK) |
98                         PIXELMUX_PIXMUX_CAM1_EN_MASK | PIXELMUX_PIXMUX_CAM1_SEL_SET(src);
99     HPM_PIXEL_MUX->PIXMUX = reg_val;
100 }
101 
pixelmux_cam1_data_source_disable(void)102 void pixelmux_cam1_data_source_disable(void)
103 {
104     HPM_PIXEL_MUX->PIXMUX &= ~PIXELMUX_PIXMUX_CAM1_EN_MASK;
105 }
106 
pixelmux_cam0_data_source_enable(pixelmux_cam0_select_t src)107 void pixelmux_cam0_data_source_enable(pixelmux_cam0_select_t src)
108 {
109     uint32_t reg_val = (HPM_PIXEL_MUX->PIXMUX & ~PIXELMUX_PIXMUX_CAM0_SEL_MASK) |
110                         PIXELMUX_PIXMUX_CAM0_EN_MASK | PIXELMUX_PIXMUX_CAM0_SEL_SET(src);
111     HPM_PIXEL_MUX->PIXMUX = reg_val;
112 }
113 
pixelmux_cam0_data_source_disable(void)114 void pixelmux_cam0_data_source_disable(void)
115 {
116     HPM_PIXEL_MUX->PIXMUX &= ~PIXELMUX_PIXMUX_CAM0_EN_MASK;
117 }
118 
pixelmux_lvds_phy_calc_pll_cfg(uint32_t pixel_freq_hz,bool is_split,lvds_phy_clk_param_t * param)119 hpm_stat_t pixelmux_lvds_phy_calc_pll_cfg(uint32_t pixel_freq_hz, bool is_split, lvds_phy_clk_param_t *param)
120 {
121     uint32_t hsclk_freq_hz;
122     uint32_t data_rate_div4;
123     uint64_t fvco_freq_hz;
124     uint32_t fvco_fraction_freq_hz;
125     uint32_t lvds_rpck = is_split ? pixel_freq_hz / 2 : pixel_freq_hz;
126     uint32_t lane_data_rate_hz = lvds_rpck * 7;
127     uint32_t rate_lvds;
128     uint32_t pfd_freq_hz;
129     uint32_t pll_div_integer; /*pll_div[14:10]*/
130     uint32_t pll_div_fraction; /*pll_div[9:0]*/
131     int refclk_div;
132 
133     if (lvds_rpck / 16 > PIXELMUX_LVDS_TX_PHY_PFD_FREQ_MAX ||
134         lvds_rpck < PIXELMUX_LVDS_TX_PHY_PFD_FREQ_MIN) {
135         return status_invalid_argument;
136     }
137 
138     if (lane_data_rate_hz < PIXELMUX_LVDS_TX_PHY_VCO_FREQ_MIN / (8 * 4) ||
139         lane_data_rate_hz > PIXELMUX_LVDS_TX_PHY_DATA_LANE_FREQ_MAX) {
140         return status_invalid_argument;
141     }
142 
143     data_rate_div4 = 1;
144     if (lane_data_rate_hz > PIXELMUX_LVDS_TX_PHY_VCO_FREQ_MAX / 4) {
145         data_rate_div4 = 0;
146     }
147 
148     hsclk_freq_hz = data_rate_div4 ? lane_data_rate_hz * 4 : lane_data_rate_hz;
149     rate_lvds = 0;
150     fvco_freq_hz = 0;
151     while (rate_lvds <= 3) {
152         fvco_freq_hz = (uint64_t)hsclk_freq_hz * (1<<rate_lvds);
153         if (fvco_freq_hz >= PIXELMUX_LVDS_TX_PHY_VCO_FREQ_MIN) {
154             break;
155         }
156         rate_lvds++;
157     }
158 
159     if (rate_lvds > 3 || fvco_freq_hz > PIXELMUX_LVDS_TX_PHY_VCO_FREQ_MAX) {
160         return status_invalid_argument;
161     }
162 
163     refclk_div = 15;
164     pfd_freq_hz = 0;
165     while (refclk_div >= 0) {
166         pfd_freq_hz = lvds_rpck / (refclk_div + 1);
167         if (pfd_freq_hz >= PIXELMUX_LVDS_TX_PHY_PFD_FREQ_MIN) {
168             break;
169         }
170         refclk_div--;
171     }
172 
173     if (refclk_div < 0 || pfd_freq_hz < PIXELMUX_LVDS_TX_PHY_PFD_FREQ_MIN) {
174         return status_invalid_argument;
175     }
176 
177     while (refclk_div >= 0 && pfd_freq_hz < PIXELMUX_LVDS_TX_PHY_PFD_FREQ_MAX) {
178         pfd_freq_hz = lvds_rpck / (refclk_div + 1);
179         if (fvco_freq_hz / 8 / pfd_freq_hz <= 23) {
180             break;
181         }
182         refclk_div--;
183     }
184 
185     if (refclk_div < 0 || pfd_freq_hz > PIXELMUX_LVDS_TX_PHY_PFD_FREQ_MAX ||
186         (fvco_freq_hz / 8 / pfd_freq_hz) > 23 || (fvco_freq_hz / 8 / pfd_freq_hz) < 6) {
187         return status_invalid_argument;
188     }
189 
190     pll_div_integer = fvco_freq_hz / 8 / pfd_freq_hz;
191     fvco_fraction_freq_hz = fvco_freq_hz - pfd_freq_hz * pll_div_integer * 8;
192     pll_div_fraction = (fvco_fraction_freq_hz * 1024) / 8 / pfd_freq_hz;
193 
194     param->reg.rate_lvds = rate_lvds;
195     param->reg.data_rate_div4 = data_rate_div4;
196     param->reg.refclk_div = refclk_div;
197     param->reg.pll_div = pll_div_integer<<10 | pll_div_fraction;
198     param->fvco_freq_hz = fvco_freq_hz;
199     param->pfd_freq_hz = pfd_freq_hz;
200     param->lane_data_rate_hz = lane_data_rate_hz;
201     param->hsclk_freq_hz = hsclk_freq_hz;
202 
203     return status_success;
204 }
205 
pixelmux_config_tx_phy0_mode(pixelmux_tx_phy_mode_t mode)206 void pixelmux_config_tx_phy0_mode(pixelmux_tx_phy_mode_t mode)
207 {
208     HPM_PIXEL_MUX->GPR_WR_D2 = (HPM_PIXEL_MUX->GPR_WR_D2 &
209                                 ~PIXELMUX_GPR_WR_D2_TX_PHY0_PHY_MODE_MASK) |
210                                 PIXELMUX_GPR_WR_D2_TX_PHY0_PHY_MODE_SET(mode);
211 }
212 
pixelmux_config_tx_phy1_mode(pixelmux_tx_phy_mode_t mode)213 void pixelmux_config_tx_phy1_mode(pixelmux_tx_phy_mode_t mode)
214 {
215     HPM_PIXEL_MUX->GPR_WR_D5 = (HPM_PIXEL_MUX->GPR_WR_D5 &
216                                 ~PIXELMUX_GPR_WR_D5_TX_PHY1_PHY_MODE_MASK) |
217                                 PIXELMUX_GPR_WR_D5_TX_PHY1_PHY_MODE_SET(mode);
218 }
219 
pixelmux_config_lvds_tx_phy0_clk(const lvds_phy_clk_reg_t * clk_reg)220 void pixelmux_config_lvds_tx_phy0_clk(const lvds_phy_clk_reg_t *clk_reg)
221 {
222     HPM_PIXEL_MUX->GPR_WR_D2 = (HPM_PIXEL_MUX->GPR_WR_D2 &
223                                 ~(PIXELMUX_GPR_WR_D2_TX_PHY0_PORT_PLL_RDY_SEL_MASK |
224                                 PIXELMUX_GPR_WR_D2_TX_PHY0_RATE_LVDS_MASK |
225                                 PIXELMUX_GPR_WR_D2_TX_PHY0_PLL_DIV_MASK |
226                                 PIXELMUX_GPR_WR_D2_TX_PHY0_REFCLK_DIV_MASK)) |
227                                 PIXELMUX_GPR_WR_D2_TX_PHY0_RATE_LVDS_SET(clk_reg->rate_lvds) |
228                                 PIXELMUX_GPR_WR_D2_TX_PHY0_REFCLK_DIV_SET(clk_reg->refclk_div) |
229                                 PIXELMUX_GPR_WR_D2_TX_PHY0_PLL_DIV_SET(clk_reg->pll_div);
230 
231     /*
232      * lvds_rpck/refclk control signal
233      *  0: normal
234      *  1: inverter
235      */
236     HPM_PIXEL_MUX->GPR_WR_D3 &= ~(0x01ul<<29);
237 
238     /*
239      * ckphy_ctl[2:0]:CLK_PHY divide ratio select, must be 010:div7
240      * ckphy_ctl[8]:div4 enable signal
241      */
242     HPM_PIXEL_MUX->GPR_WR_D4 = (HPM_PIXEL_MUX->GPR_WR_D4 & ~PIXELMUX_GPR_WR_D4_TX_PHY0_CKPHY_CTL_MASK) |
243                                 PIXELMUX_GPR_WR_D4_TX_PHY0_CKPHY_CTL_SET((clk_reg->data_rate_div4 & 0x01)<<8 | 0x02);
244 }
245 
pixelmux_config_lvds_tx_phy1_clk(const lvds_phy_clk_reg_t * clk_reg)246 void pixelmux_config_lvds_tx_phy1_clk(const lvds_phy_clk_reg_t *clk_reg)
247 {
248     HPM_PIXEL_MUX->GPR_WR_D5 = (HPM_PIXEL_MUX->GPR_WR_D5 &
249                                 ~(PIXELMUX_GPR_WR_D5_TX_PHY1_PORT_PLL_RDY_SEL_MASK |
250                                 PIXELMUX_GPR_WR_D5_TX_PHY1_RATE_LVDS_MASK |
251                                 PIXELMUX_GPR_WR_D5_TX_PHY1_PLL_DIV_MASK |
252                                 PIXELMUX_GPR_WR_D5_TX_PHY1_REFCLK_DIV_MASK)) |
253                                 PIXELMUX_GPR_WR_D5_TX_PHY1_RATE_LVDS_SET(clk_reg->rate_lvds) |
254                                 PIXELMUX_GPR_WR_D5_TX_PHY1_REFCLK_DIV_SET(clk_reg->refclk_div) |
255                                 PIXELMUX_GPR_WR_D5_TX_PHY1_PLL_DIV_SET(clk_reg->pll_div);
256     /*
257      * lvds_rpck/refclk control signal
258      *  0: normal
259      *  1: inverter
260      */
261     HPM_PIXEL_MUX->GPR_WR_D6 &= ~(0x01ul<<29);
262 
263     /*
264      * ckphy_ctl[2:0]:CLK_PHY divide ratio select, must be 010:div7
265      * ckphy_ctl[8]:div4 enable signal
266      */
267     HPM_PIXEL_MUX->GPR_WR_D7 = (HPM_PIXEL_MUX->GPR_WR_D7 & ~PIXELMUX_GPR_WR_D7_TX_PHY1_CKPHY_CTL_MASK) |
268                                 PIXELMUX_GPR_WR_D7_TX_PHY1_CKPHY_CTL_SET((clk_reg->data_rate_div4 & 0x01)<<8 | 0x02);
269 }
270 
pixelmux_config_rx_phy0_mode(pixelmux_rx_phy_mode_t mode)271 void pixelmux_config_rx_phy0_mode(pixelmux_rx_phy_mode_t mode)
272 {
273     HPM_PIXEL_MUX->GPR_WR_D8 = (HPM_PIXEL_MUX->GPR_WR_D8 &
274                                 ~PIXELMUX_GPR_WR_D8_RX_PHY0_PHY_MODE_MASK) |
275                                 PIXELMUX_GPR_WR_D8_RX_PHY0_PHY_MODE_SET(mode);
276 }
277 
pixelmux_config_rx_phy1_mode(pixelmux_rx_phy_mode_t mode)278 void pixelmux_config_rx_phy1_mode(pixelmux_rx_phy_mode_t mode)
279 {
280     HPM_PIXEL_MUX->GPR_WR_D9 = (HPM_PIXEL_MUX->GPR_WR_D9 &
281                                 ~PIXELMUX_GPR_WR_D9_RX_PHY1_PHY_MODE_MASK) |
282                                 PIXELMUX_GPR_WR_D9_RX_PHY1_PHY_MODE_SET(mode);
283 }