]>
Commit | Line | Data |
---|---|---|
e1e96ba6 SB |
1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | /* | |
3 | * Copyright (C) 2016 Nexell Co., Ltd. | |
4 | * | |
5 | * Author: junghyun, kim <jhkim@nexell.co.kr> | |
6 | */ | |
7 | ||
8 | #include <config.h> | |
d678a59d | 9 | #include <common.h> |
e1e96ba6 SB |
10 | #include <errno.h> |
11 | #include <log.h> | |
12 | ||
13 | #include <asm/arch/nexell.h> | |
14 | #include <asm/arch/tieoff.h> | |
15 | #include <asm/arch/reset.h> | |
16 | #include <asm/arch/display.h> | |
17 | ||
18 | #include <linux/delay.h> | |
19 | ||
20 | #include "soc/s5pxx18_soc_dpc.h" | |
21 | #include "soc/s5pxx18_soc_hdmi.h" | |
22 | #include "soc/s5pxx18_soc_disptop.h" | |
23 | #include "soc/s5pxx18_soc_disptop_clk.h" | |
24 | ||
25 | #define __io_address(a) (void *)(uintptr_t)(a) | |
26 | ||
27 | static const u8 hdmiphy_preset74_25[32] = { | |
28 | 0xd1, 0x1f, 0x10, 0x40, 0x40, 0xf8, 0xc8, 0x81, | |
29 | 0xe8, 0xba, 0xd8, 0x45, 0xa0, 0xac, 0x80, 0x0a, | |
30 | 0x80, 0x09, 0x84, 0x05, 0x22, 0x24, 0x86, 0x54, | |
31 | 0xa5, 0x24, 0x01, 0x00, 0x00, 0x01, 0x10, 0x80, | |
32 | }; | |
33 | ||
34 | static const u8 hdmiphy_preset148_5[32] = { | |
35 | 0xd1, 0x1f, 0x00, 0x40, 0x40, 0xf8, 0xc8, 0x81, | |
36 | 0xe8, 0xba, 0xd8, 0x45, 0xa0, 0xac, 0x80, 0x0a, | |
37 | 0x80, 0x09, 0x84, 0x05, 0x22, 0x24, 0x86, 0x54, | |
38 | 0x4b, 0x25, 0x03, 0x00, 0x00, 0x01, 0x80, | |
39 | }; | |
40 | ||
41 | #define HDMIPHY_PRESET_TABLE_SIZE (32) | |
42 | ||
43 | enum NXP_HDMI_PRESET { | |
44 | NXP_HDMI_PRESET_720P = 0, /* 1280 x 720 */ | |
45 | NXP_HDMI_PRESET_1080P, /* 1920 x 1080 */ | |
46 | NXP_HDMI_PRESET_MAX | |
47 | }; | |
48 | ||
49 | static void hdmi_reset(void) | |
50 | { | |
51 | nx_rstcon_setrst(RESET_ID_HDMI_VIDEO, RSTCON_ASSERT); | |
52 | nx_rstcon_setrst(RESET_ID_HDMI_SPDIF, RSTCON_ASSERT); | |
53 | nx_rstcon_setrst(RESET_ID_HDMI_TMDS, RSTCON_ASSERT); | |
54 | nx_rstcon_setrst(RESET_ID_HDMI_VIDEO, RSTCON_NEGATE); | |
55 | nx_rstcon_setrst(RESET_ID_HDMI_SPDIF, RSTCON_NEGATE); | |
56 | nx_rstcon_setrst(RESET_ID_HDMI_TMDS, RSTCON_NEGATE); | |
57 | } | |
58 | ||
59 | static int hdmi_phy_enable(int preset, int enable) | |
60 | { | |
61 | const u8 *table = NULL; | |
62 | int size = 0; | |
63 | u32 addr, i = 0; | |
64 | ||
65 | if (!enable) | |
66 | return 0; | |
67 | ||
68 | switch (preset) { | |
69 | case NXP_HDMI_PRESET_720P: | |
70 | table = hdmiphy_preset74_25; | |
71 | size = 32; | |
72 | break; | |
73 | case NXP_HDMI_PRESET_1080P: | |
74 | table = hdmiphy_preset148_5; | |
75 | size = 31; | |
76 | break; | |
77 | default: | |
78 | printf("hdmi: phy not support preset %d\n", preset); | |
79 | return -EINVAL; | |
80 | } | |
81 | ||
82 | nx_hdmi_set_reg(0, HDMI_PHY_REG7C, (0 << 7)); | |
83 | nx_hdmi_set_reg(0, HDMI_PHY_REG7C, (0 << 7)); | |
84 | nx_hdmi_set_reg(0, HDMI_PHY_REG04, (0 << 4)); | |
85 | nx_hdmi_set_reg(0, HDMI_PHY_REG04, (0 << 4)); | |
86 | nx_hdmi_set_reg(0, HDMI_PHY_REG24, (1 << 7)); | |
87 | nx_hdmi_set_reg(0, HDMI_PHY_REG24, (1 << 7)); | |
88 | ||
89 | for (i = 0, addr = HDMI_PHY_REG04; size > i; i++, addr += 4) { | |
90 | nx_hdmi_set_reg(0, addr, table[i]); | |
91 | nx_hdmi_set_reg(0, addr, table[i]); | |
92 | } | |
93 | ||
94 | nx_hdmi_set_reg(0, HDMI_PHY_REG7C, 0x80); | |
95 | nx_hdmi_set_reg(0, HDMI_PHY_REG7C, 0x80); | |
96 | nx_hdmi_set_reg(0, HDMI_PHY_REG7C, (1 << 7)); | |
97 | nx_hdmi_set_reg(0, HDMI_PHY_REG7C, (1 << 7)); | |
98 | debug("%s: preset = %d\n", __func__, preset); | |
99 | ||
100 | return 0; | |
101 | } | |
102 | ||
103 | static inline int hdmi_wait_phy_ready(void) | |
104 | { | |
105 | int count = 500; | |
106 | ||
107 | do { | |
108 | u32 val = nx_hdmi_get_reg(0, HDMI_LINK_PHY_STATUS_0); | |
109 | ||
110 | if (val & 0x01) { | |
111 | printf("HDMI: phy ready...\n"); | |
112 | return 1; | |
113 | } | |
114 | mdelay(10); | |
115 | } while (count--); | |
116 | ||
117 | return 0; | |
118 | } | |
119 | ||
120 | static inline int hdmi_get_vsync(int preset, | |
121 | struct dp_sync_info *sync, | |
122 | struct dp_ctrl_info *ctrl) | |
123 | { | |
124 | switch (preset) { | |
125 | case NXP_HDMI_PRESET_720P: /* 720p: 1280x720 */ | |
126 | sync->h_active_len = 1280; | |
127 | sync->h_sync_width = 40; | |
128 | sync->h_back_porch = 220; | |
129 | sync->h_front_porch = 110; | |
130 | sync->h_sync_invert = 0; | |
131 | sync->v_active_len = 720; | |
132 | sync->v_sync_width = 5; | |
133 | sync->v_back_porch = 20; | |
134 | sync->v_front_porch = 5; | |
135 | sync->v_sync_invert = 0; | |
136 | break; | |
137 | ||
138 | case NXP_HDMI_PRESET_1080P: /* 1080p: 1920x1080 */ | |
139 | sync->h_active_len = 1920; | |
140 | sync->h_sync_width = 44; | |
141 | sync->h_back_porch = 148; | |
142 | sync->h_front_porch = 88; | |
143 | sync->h_sync_invert = 0; | |
144 | sync->v_active_len = 1080; | |
145 | sync->v_sync_width = 5; | |
146 | sync->v_back_porch = 36; | |
147 | sync->v_front_porch = 4; | |
148 | sync->v_sync_invert = 0; | |
149 | break; | |
150 | default: | |
151 | printf("HDMI: not support preset sync %d\n", preset); | |
152 | return -EINVAL; | |
153 | } | |
154 | ||
155 | ctrl->clk_src_lv0 = 4; | |
156 | ctrl->clk_div_lv0 = 1; | |
157 | ctrl->clk_src_lv1 = 7; | |
158 | ctrl->clk_div_lv1 = 1; | |
159 | ||
160 | ctrl->out_format = outputformat_rgb888; | |
161 | ctrl->delay_mask = (DP_SYNC_DELAY_RGB_PVD | DP_SYNC_DELAY_HSYNC_CP1 | | |
162 | DP_SYNC_DELAY_VSYNC_FRAM | DP_SYNC_DELAY_DE_CP); | |
163 | ctrl->d_rgb_pvd = 0; | |
164 | ctrl->d_hsync_cp1 = 0; | |
165 | ctrl->d_vsync_fram = 0; | |
166 | ctrl->d_de_cp2 = 7; | |
167 | ||
168 | /* HFP + HSW + HBP + AVWidth-VSCLRPIXEL- 1; */ | |
169 | ctrl->vs_start_offset = (sync->h_front_porch + sync->h_sync_width + | |
170 | sync->h_back_porch + sync->h_active_len - 1); | |
171 | ctrl->vs_end_offset = 0; | |
172 | ||
173 | /* HFP + HSW + HBP + AVWidth-EVENVSCLRPIXEL- 1 */ | |
174 | ctrl->ev_start_offset = (sync->h_front_porch + sync->h_sync_width + | |
175 | sync->h_back_porch + sync->h_active_len - 1); | |
176 | ctrl->ev_end_offset = 0; | |
177 | debug("%s: preset: %d\n", __func__, preset); | |
178 | ||
179 | return 0; | |
180 | } | |
181 | ||
182 | static void hdmi_clock(void) | |
183 | { | |
184 | void *base = | |
185 | __io_address(nx_disp_top_clkgen_get_physical_address | |
186 | (to_mipi_clkgen)); | |
187 | ||
188 | nx_disp_top_clkgen_set_base_address(to_mipi_clkgen, base); | |
189 | nx_disp_top_clkgen_set_clock_divisor_enable(to_mipi_clkgen, 0); | |
190 | nx_disp_top_clkgen_set_clock_pclk_mode(to_mipi_clkgen, | |
191 | nx_pclkmode_always); | |
192 | nx_disp_top_clkgen_set_clock_source(to_mipi_clkgen, HDMI_SPDIF_CLKOUT, | |
193 | 2); | |
194 | nx_disp_top_clkgen_set_clock_divisor(to_mipi_clkgen, HDMI_SPDIF_CLKOUT, | |
195 | 2); | |
196 | nx_disp_top_clkgen_set_clock_source(to_mipi_clkgen, 1, 7); | |
197 | nx_disp_top_clkgen_set_clock_divisor_enable(to_mipi_clkgen, 1); | |
198 | ||
199 | /* must initialize this !!! */ | |
200 | nx_disp_top_hdmi_set_vsync_hsstart_end(0, 0); | |
201 | nx_disp_top_hdmi_set_vsync_start(0); | |
202 | nx_disp_top_hdmi_set_hactive_start(0); | |
203 | nx_disp_top_hdmi_set_hactive_end(0); | |
204 | } | |
205 | ||
206 | static void hdmi_vsync(struct dp_sync_info *sync) | |
207 | { | |
208 | int width = sync->h_active_len; | |
209 | int hsw = sync->h_sync_width; | |
210 | int hbp = sync->h_back_porch; | |
211 | int height = sync->v_active_len; | |
212 | int vsw = sync->v_sync_width; | |
213 | int vbp = sync->v_back_porch; | |
214 | ||
215 | int v_sync_s = vsw + vbp + height - 1; | |
216 | int h_active_s = hsw + hbp; | |
217 | int h_active_e = width + hsw + hbp; | |
218 | int v_sync_hs_se0 = hsw + hbp + 1; | |
219 | int v_sync_hs_se1 = hsw + hbp + 2; | |
220 | ||
221 | nx_disp_top_hdmi_set_vsync_start(v_sync_s); | |
222 | nx_disp_top_hdmi_set_hactive_start(h_active_s); | |
223 | nx_disp_top_hdmi_set_hactive_end(h_active_e); | |
224 | nx_disp_top_hdmi_set_vsync_hsstart_end(v_sync_hs_se0, v_sync_hs_se1); | |
225 | } | |
226 | ||
227 | static int hdmi_prepare(struct dp_sync_info *sync) | |
228 | { | |
229 | int width = sync->h_active_len; | |
230 | int hsw = sync->h_sync_width; | |
231 | int hfp = sync->h_front_porch; | |
232 | int hbp = sync->h_back_porch; | |
233 | int height = sync->v_active_len; | |
234 | int vsw = sync->v_sync_width; | |
235 | int vfp = sync->v_front_porch; | |
236 | int vbp = sync->v_back_porch; | |
237 | ||
238 | u32 h_blank, h_line, h_sync_start, h_sync_end; | |
239 | u32 v_blank, v2_blank, v_line; | |
240 | u32 v_sync_line_bef_1, v_sync_line_bef_2; | |
241 | ||
242 | u32 fixed_ffff = 0xffff; | |
243 | ||
244 | /* calculate sync variables */ | |
245 | h_blank = hfp + hsw + hbp; | |
246 | v_blank = vfp + vsw + vbp; | |
247 | v2_blank = height + vfp + vsw + vbp; | |
248 | v_line = height + vfp + vsw + vbp; /* total v */ | |
249 | h_line = width + hfp + hsw + hbp; /* total h */ | |
250 | h_sync_start = hfp; | |
251 | h_sync_end = hfp + hsw; | |
252 | v_sync_line_bef_1 = vfp; | |
253 | v_sync_line_bef_2 = vfp + vsw; | |
254 | ||
255 | /* no blue screen mode, encoding order as it is */ | |
256 | nx_hdmi_set_reg(0, HDMI_LINK_HDMI_CON_0, (0 << 5) | (1 << 4)); | |
257 | ||
258 | /* set HDMI_LINK_BLUE_SCREEN_* to 0x0 */ | |
259 | nx_hdmi_set_reg(0, HDMI_LINK_BLUE_SCREEN_R_0, 0x5555); | |
260 | nx_hdmi_set_reg(0, HDMI_LINK_BLUE_SCREEN_R_1, 0x5555); | |
261 | nx_hdmi_set_reg(0, HDMI_LINK_BLUE_SCREEN_G_0, 0x5555); | |
262 | nx_hdmi_set_reg(0, HDMI_LINK_BLUE_SCREEN_G_1, 0x5555); | |
263 | nx_hdmi_set_reg(0, HDMI_LINK_BLUE_SCREEN_B_0, 0x5555); | |
264 | nx_hdmi_set_reg(0, HDMI_LINK_BLUE_SCREEN_B_1, 0x5555); | |
265 | ||
266 | /* set HDMI_CON_1 to 0x0 */ | |
267 | nx_hdmi_set_reg(0, HDMI_LINK_HDMI_CON_1, 0x0); | |
268 | nx_hdmi_set_reg(0, HDMI_LINK_HDMI_CON_2, 0x0); | |
269 | ||
270 | /* set interrupt : enable hpd_plug, hpd_unplug */ | |
271 | nx_hdmi_set_reg(0, HDMI_LINK_INTC_CON_0, | |
272 | (1 << 6) | (1 << 3) | (1 << 2)); | |
273 | ||
274 | /* set STATUS_EN to 0x17 */ | |
275 | nx_hdmi_set_reg(0, HDMI_LINK_STATUS_EN, 0x17); | |
276 | ||
277 | /* TODO set HDP to 0x0 : later check hpd */ | |
278 | nx_hdmi_set_reg(0, HDMI_LINK_HPD, 0x0); | |
279 | ||
280 | /* set MODE_SEL to 0x02 */ | |
281 | nx_hdmi_set_reg(0, HDMI_LINK_MODE_SEL, 0x2); | |
282 | ||
283 | /* set H_BLANK_*, V1_BLANK_*, V2_BLANK_*, V_LINE_*, | |
284 | * H_LINE_*, H_SYNC_START_*, H_SYNC_END_ * | |
285 | * V_SYNC_LINE_BEF_1_*, V_SYNC_LINE_BEF_2_* | |
286 | */ | |
287 | nx_hdmi_set_reg(0, HDMI_LINK_H_BLANK_0, h_blank % 256); | |
288 | nx_hdmi_set_reg(0, HDMI_LINK_H_BLANK_1, h_blank >> 8); | |
289 | nx_hdmi_set_reg(0, HDMI_LINK_V1_BLANK_0, v_blank % 256); | |
290 | nx_hdmi_set_reg(0, HDMI_LINK_V1_BLANK_1, v_blank >> 8); | |
291 | nx_hdmi_set_reg(0, HDMI_LINK_V2_BLANK_0, v2_blank % 256); | |
292 | nx_hdmi_set_reg(0, HDMI_LINK_V2_BLANK_1, v2_blank >> 8); | |
293 | nx_hdmi_set_reg(0, HDMI_LINK_V_LINE_0, v_line % 256); | |
294 | nx_hdmi_set_reg(0, HDMI_LINK_V_LINE_1, v_line >> 8); | |
295 | nx_hdmi_set_reg(0, HDMI_LINK_H_LINE_0, h_line % 256); | |
296 | nx_hdmi_set_reg(0, HDMI_LINK_H_LINE_1, h_line >> 8); | |
297 | ||
298 | if (width == 1280) { | |
299 | nx_hdmi_set_reg(0, HDMI_LINK_HSYNC_POL, 0x1); | |
300 | nx_hdmi_set_reg(0, HDMI_LINK_VSYNC_POL, 0x1); | |
301 | } else { | |
302 | nx_hdmi_set_reg(0, HDMI_LINK_HSYNC_POL, 0x0); | |
303 | nx_hdmi_set_reg(0, HDMI_LINK_VSYNC_POL, 0x0); | |
304 | } | |
305 | ||
306 | nx_hdmi_set_reg(0, HDMI_LINK_INT_PRO_MODE, 0x0); | |
307 | ||
308 | nx_hdmi_set_reg(0, HDMI_LINK_H_SYNC_START_0, (h_sync_start % 256) - 2); | |
309 | nx_hdmi_set_reg(0, HDMI_LINK_H_SYNC_START_1, h_sync_start >> 8); | |
310 | nx_hdmi_set_reg(0, HDMI_LINK_H_SYNC_END_0, (h_sync_end % 256) - 2); | |
311 | nx_hdmi_set_reg(0, HDMI_LINK_H_SYNC_END_1, h_sync_end >> 8); | |
312 | nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_BEF_1_0, | |
313 | v_sync_line_bef_1 % 256); | |
314 | nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_BEF_1_1, | |
315 | v_sync_line_bef_1 >> 8); | |
316 | nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_BEF_2_0, | |
317 | v_sync_line_bef_2 % 256); | |
318 | nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_BEF_2_1, | |
319 | v_sync_line_bef_2 >> 8); | |
320 | ||
321 | /* Set V_SYNC_LINE_AFT*, V_SYNC_LINE_AFT_PXL*, VACT_SPACE* */ | |
322 | nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_AFT_1_0, fixed_ffff % 256); | |
323 | nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_AFT_1_1, fixed_ffff >> 8); | |
324 | nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_AFT_2_0, fixed_ffff % 256); | |
325 | nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_AFT_2_1, fixed_ffff >> 8); | |
326 | nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_AFT_3_0, fixed_ffff % 256); | |
327 | nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_AFT_3_1, fixed_ffff >> 8); | |
328 | nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_AFT_4_0, fixed_ffff % 256); | |
329 | nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_AFT_4_1, fixed_ffff >> 8); | |
330 | nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_AFT_5_0, fixed_ffff % 256); | |
331 | nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_AFT_5_1, fixed_ffff >> 8); | |
332 | nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_AFT_6_0, fixed_ffff % 256); | |
333 | nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_AFT_6_1, fixed_ffff >> 8); | |
334 | ||
335 | nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_AFT_PXL_1_0, fixed_ffff % 256); | |
336 | nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_AFT_PXL_1_1, fixed_ffff >> 8); | |
337 | nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_AFT_PXL_2_0, fixed_ffff % 256); | |
338 | nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_AFT_PXL_2_1, fixed_ffff >> 8); | |
339 | nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_AFT_PXL_3_0, fixed_ffff % 256); | |
340 | nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_AFT_PXL_3_1, fixed_ffff >> 8); | |
341 | nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_AFT_PXL_4_0, fixed_ffff % 256); | |
342 | nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_AFT_PXL_4_1, fixed_ffff >> 8); | |
343 | nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_AFT_PXL_5_0, fixed_ffff % 256); | |
344 | nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_AFT_PXL_5_1, fixed_ffff >> 8); | |
345 | nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_AFT_PXL_6_0, fixed_ffff % 256); | |
346 | nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_AFT_PXL_6_1, fixed_ffff >> 8); | |
347 | ||
348 | nx_hdmi_set_reg(0, HDMI_LINK_VACT_SPACE1_0, fixed_ffff % 256); | |
349 | nx_hdmi_set_reg(0, HDMI_LINK_VACT_SPACE1_1, fixed_ffff >> 8); | |
350 | nx_hdmi_set_reg(0, HDMI_LINK_VACT_SPACE2_0, fixed_ffff % 256); | |
351 | nx_hdmi_set_reg(0, HDMI_LINK_VACT_SPACE2_1, fixed_ffff >> 8); | |
352 | nx_hdmi_set_reg(0, HDMI_LINK_VACT_SPACE3_0, fixed_ffff % 256); | |
353 | nx_hdmi_set_reg(0, HDMI_LINK_VACT_SPACE3_1, fixed_ffff >> 8); | |
354 | nx_hdmi_set_reg(0, HDMI_LINK_VACT_SPACE4_0, fixed_ffff % 256); | |
355 | nx_hdmi_set_reg(0, HDMI_LINK_VACT_SPACE4_1, fixed_ffff >> 8); | |
356 | nx_hdmi_set_reg(0, HDMI_LINK_VACT_SPACE5_0, fixed_ffff % 256); | |
357 | nx_hdmi_set_reg(0, HDMI_LINK_VACT_SPACE5_1, fixed_ffff >> 8); | |
358 | nx_hdmi_set_reg(0, HDMI_LINK_VACT_SPACE6_0, fixed_ffff % 256); | |
359 | nx_hdmi_set_reg(0, HDMI_LINK_VACT_SPACE6_1, fixed_ffff >> 8); | |
360 | ||
361 | nx_hdmi_set_reg(0, HDMI_LINK_CSC_MUX, 0x0); | |
362 | nx_hdmi_set_reg(0, HDMI_LINK_SYNC_GEN_MUX, 0x0); | |
363 | ||
364 | nx_hdmi_set_reg(0, HDMI_LINK_SEND_START_0, 0xfd); | |
365 | nx_hdmi_set_reg(0, HDMI_LINK_SEND_START_1, 0x01); | |
366 | nx_hdmi_set_reg(0, HDMI_LINK_SEND_END_0, 0x0d); | |
367 | nx_hdmi_set_reg(0, HDMI_LINK_SEND_END_1, 0x3a); | |
368 | nx_hdmi_set_reg(0, HDMI_LINK_SEND_END_2, 0x08); | |
369 | ||
370 | /* Set DC_CONTROL to 0x00 */ | |
371 | nx_hdmi_set_reg(0, HDMI_LINK_DC_CONTROL, 0x0); | |
372 | ||
373 | if (IS_ENABLED(CONFIG_HDMI_PATTERN)) | |
374 | nx_hdmi_set_reg(0, HDMI_LINK_VIDEO_PATTERN_GEN, 0x1); | |
375 | else | |
376 | nx_hdmi_set_reg(0, HDMI_LINK_VIDEO_PATTERN_GEN, 0x0); | |
377 | ||
378 | nx_hdmi_set_reg(0, HDMI_LINK_GCP_CON, 0x0a); | |
379 | return 0; | |
380 | } | |
381 | ||
382 | static void hdmi_init(void) | |
383 | { | |
384 | void *base; | |
385 | /** | |
386 | * [SEQ 2] set the HDMI CLKGEN's PCLKMODE to always enabled | |
387 | */ | |
388 | base = | |
389 | __io_address(nx_disp_top_clkgen_get_physical_address(hdmi_clkgen)); | |
390 | nx_disp_top_clkgen_set_base_address(hdmi_clkgen, base); | |
391 | nx_disp_top_clkgen_set_clock_pclk_mode(hdmi_clkgen, nx_pclkmode_always); | |
392 | ||
393 | base = __io_address(nx_hdmi_get_physical_address(0)); | |
394 | nx_hdmi_set_base_address(0, base); | |
395 | ||
396 | /** | |
397 | * [SEQ 3] set the 0xC001100C[0] to 1 | |
398 | */ | |
399 | nx_tieoff_set(NX_TIEOFF_DISPLAYTOP0_i_HDMI_PHY_REFCLK_SEL, 1); | |
400 | ||
401 | /** | |
402 | * [SEQ 4] release the resets of HDMI.i_PHY_nRST and HDMI.i_nRST | |
403 | */ | |
404 | nx_rstcon_setrst(RESET_ID_HDMI_PHY, RSTCON_ASSERT); | |
405 | nx_rstcon_setrst(RESET_ID_HDMI, RSTCON_ASSERT); | |
406 | nx_rstcon_setrst(RESET_ID_HDMI_PHY, RSTCON_NEGATE); | |
407 | nx_rstcon_setrst(RESET_ID_HDMI, RSTCON_NEGATE); | |
408 | } | |
409 | ||
410 | void hdmi_enable(int input, int preset, struct dp_sync_info *sync, int enable) | |
411 | { | |
412 | if (enable) { | |
413 | nx_hdmi_set_reg(0, HDMI_LINK_HDMI_CON_0, | |
414 | (nx_hdmi_get_reg(0, HDMI_LINK_HDMI_CON_0) | | |
415 | 0x1)); | |
416 | hdmi_vsync(sync); | |
417 | } else { | |
418 | hdmi_phy_enable(preset, 0); | |
419 | } | |
420 | } | |
421 | ||
422 | static int hdmi_setup(int input, int preset, | |
423 | struct dp_sync_info *sync, struct dp_ctrl_info *ctrl) | |
424 | { | |
425 | u32 HDMI_SEL = 0; | |
426 | int ret; | |
427 | ||
428 | switch (input) { | |
429 | case DP_DEVICE_DP0: | |
430 | HDMI_SEL = primary_mlc; | |
431 | break; | |
432 | case DP_DEVICE_DP1: | |
433 | HDMI_SEL = secondary_mlc; | |
434 | break; | |
435 | case DP_DEVICE_RESCONV: | |
436 | HDMI_SEL = resolution_conv; | |
437 | break; | |
438 | default: | |
439 | printf("HDMI: not support source device %d\n", input); | |
440 | return -EINVAL; | |
441 | } | |
442 | ||
443 | /** | |
444 | * [SEQ 5] set up the HDMI PHY to specific video clock. | |
445 | */ | |
446 | ret = hdmi_phy_enable(preset, 1); | |
447 | if (ret < 0) | |
448 | return ret; | |
449 | ||
450 | /** | |
451 | * [SEQ 6] I2S (or SPDIFTX) configuration for the source audio data | |
452 | * this is done in another user app - ex> Android Audio HAL | |
453 | */ | |
454 | ||
455 | /** | |
456 | * [SEQ 7] Wait for ECID ready | |
457 | */ | |
458 | ||
459 | /** | |
460 | * [SEQ 8] release the resets of HDMI.i_VIDEO_nRST and HDMI.i_SPDIF_nRST | |
461 | * and HDMI.i_TMDS_nRST | |
462 | */ | |
463 | hdmi_reset(); | |
464 | ||
465 | /** | |
466 | * [SEQ 9] Wait for HDMI PHY ready (wait until 0xC0200020.[0], 1) | |
467 | */ | |
468 | if (hdmi_wait_phy_ready() == 0) { | |
469 | printf("%s: failed to wait for hdmiphy ready\n", __func__); | |
470 | hdmi_phy_enable(preset, 0); | |
471 | return -EIO; | |
472 | } | |
473 | /* set mux */ | |
474 | nx_disp_top_set_hdmimux(1, HDMI_SEL); | |
475 | ||
476 | /** | |
477 | * [SEC 10] Set the DPC CLKGEN's Source Clock to HDMI_CLK & | |
478 | * Set Sync Parameter | |
479 | */ | |
480 | hdmi_clock(); | |
481 | /* set hdmi link clk to clkgen vs default is hdmi phy clk */ | |
482 | ||
483 | /** | |
484 | * [SEQ 11] Set up the HDMI Converter parameters | |
485 | */ | |
486 | hdmi_get_vsync(preset, sync, ctrl); | |
487 | hdmi_prepare(sync); | |
488 | ||
489 | return 0; | |
490 | } | |
491 | ||
492 | void nx_hdmi_display(int module, | |
493 | struct dp_sync_info *sync, struct dp_ctrl_info *ctrl, | |
494 | struct dp_plane_top *top, struct dp_plane_info *planes, | |
495 | struct dp_hdmi_dev *dev) | |
496 | { | |
497 | struct dp_plane_info *plane = planes; | |
498 | int input = module == 0 ? DP_DEVICE_DP0 : DP_DEVICE_DP1; | |
499 | int count = top->plane_num; | |
500 | int preset = dev->preset; | |
501 | int i = 0; | |
502 | ||
503 | debug("HDMI: display.%d\n", module); | |
504 | ||
505 | switch (preset) { | |
506 | case 0: | |
507 | top->screen_width = 1280; | |
508 | top->screen_height = 720; | |
509 | sync->h_active_len = 1280; | |
510 | sync->v_active_len = 720; | |
511 | break; | |
512 | case 1: | |
513 | top->screen_width = 1920; | |
514 | top->screen_height = 1080; | |
515 | sync->h_active_len = 1920; | |
516 | sync->v_active_len = 1080; | |
517 | break; | |
518 | default: | |
519 | printf("hdmi not support preset %d\n", preset); | |
520 | return; | |
521 | } | |
522 | ||
523 | printf("HDMI: display.%d, preset %d (%4d * %4d)\n", | |
524 | module, preset, top->screen_width, top->screen_height); | |
525 | ||
526 | dp_control_init(module); | |
527 | dp_plane_init(module); | |
528 | ||
529 | hdmi_init(); | |
530 | hdmi_setup(input, preset, sync, ctrl); | |
531 | ||
532 | dp_plane_screen_setup(module, top); | |
533 | for (i = 0; count > i; i++, plane++) { | |
534 | if (!plane->enable) | |
535 | continue; | |
536 | dp_plane_layer_setup(module, plane); | |
537 | dp_plane_layer_enable(module, plane, 1); | |
538 | } | |
539 | dp_plane_screen_enable(module, 1); | |
540 | ||
541 | dp_control_setup(module, sync, ctrl); | |
542 | dp_control_enable(module, 1); | |
543 | ||
544 | hdmi_enable(input, preset, sync, 1); | |
545 | } |