1 // Copyright 2018 The Fuchsia Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <assert.h>
6 #include <stdint.h>
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include <unistd.h>
11 #include <ddk/device.h>
12 #include <ddk/driver.h>
13 #include <ddk/debug.h>
14 #include <ddk/binding.h>
15 #include <ddk/io-buffer.h>
16 #include <ddk/platform-defs.h>
17 #include <ddk/protocol/platform/device.h>
18
19 #include <zircon/syscalls.h>
20 #include <zircon/assert.h>
21 #include <hw/reg.h>
22 #include "vim-display.h"
23 #include "hdmitx.h"
24
25 // Uncomment to print all HDMI REG writes
26 // #define LOG_HDMITX
27
28 static mtx_t hdmi_register_lock = MTX_INIT;
29
hdmitx_writereg(const vim2_display_t * display,uint32_t addr,uint32_t data)30 void hdmitx_writereg(const vim2_display_t* display, uint32_t addr, uint32_t data) {
31 // determine if we are writing to HDMI TOP (AMLOGIC Wrapper) or HDMI IP
32 uint32_t offset = (addr & DWC_OFFSET_MASK) >> 24;
33 addr = addr & 0xffff;
34
35 mtx_lock(&hdmi_register_lock);
36 WRITE32_HDMITX_REG(HDMITX_ADDR_PORT + offset, addr);
37 WRITE32_HDMITX_REG(HDMITX_ADDR_PORT + offset, addr); // FIXME: Need to write twice!
38 WRITE32_HDMITX_REG(HDMITX_DATA_PORT + offset, data);
39 mtx_unlock(&hdmi_register_lock);
40
41 #ifdef LOG_HDMITX
42 DISP_INFO("%s wr[0x%x] 0x%x\n", offset ? "DWC" : "TOP",
43 addr, data);
44 #endif
45 }
46
hdmitx_readreg(const vim2_display_t * display,uint32_t addr)47 uint32_t hdmitx_readreg(const vim2_display_t* display, uint32_t addr) {
48 // determine if we are writing to HDMI TOP (AMLOGIC Wrapper) or HDMI IP
49 uint32_t ret;
50 uint32_t offset = (addr & DWC_OFFSET_MASK) >> 24;
51 addr = addr & 0xffff;
52
53 mtx_lock(&hdmi_register_lock);
54 WRITE32_HDMITX_REG(HDMITX_ADDR_PORT + offset, addr);
55 WRITE32_HDMITX_REG(HDMITX_ADDR_PORT + offset, addr); // FIXME: Need to write twice!
56 ret = (READ32_HDMITX_REG(HDMITX_DATA_PORT + offset));
57 mtx_unlock(&hdmi_register_lock);
58
59 return ret;
60 }
61
hdmi_scdc_read(vim2_display_t * display,uint8_t addr,uint8_t * val)62 void hdmi_scdc_read(vim2_display_t* display, uint8_t addr, uint8_t* val) {
63 hdmitx_writereg(display, HDMITX_DWC_I2CM_SLAVE, 0x54);
64 hdmitx_writereg(display, HDMITX_DWC_I2CM_ADDRESS, addr);
65 hdmitx_writereg(display, HDMITX_DWC_I2CM_OPERATION, 1);
66 usleep(2000);
67 *val = (uint8_t) hdmitx_readreg(display, HDMITX_DWC_I2CM_DATAI);
68 }
69
hdmi_scdc_write(vim2_display_t * display,uint8_t addr,uint8_t val)70 void hdmi_scdc_write(vim2_display_t* display, uint8_t addr, uint8_t val) {
71 hdmitx_writereg(display, HDMITX_DWC_I2CM_SLAVE, 0x54);
72 hdmitx_writereg(display, HDMITX_DWC_I2CM_ADDRESS, addr);
73 hdmitx_writereg(display, HDMITX_DWC_I2CM_DATAO, val);
74 hdmitx_writereg(display, HDMITX_DWC_I2CM_OPERATION, 0x10);
75 usleep(2000);
76 }
77
hdmi_shutdown(vim2_display_t * display)78 void hdmi_shutdown(vim2_display_t* display)
79 {
80 /* Close HDMITX PHY */
81 WRITE32_REG(HHI,HHI_HDMI_PHY_CNTL0, 0);
82 WRITE32_REG(HHI,HHI_HDMI_PHY_CNTL3, 0);
83 /* Disable HPLL */
84 WRITE32_REG(HHI,HHI_HDMI_PLL_CNTL, 0);
85 }
86
init_hdmi_hardware(vim2_display_t * display)87 void init_hdmi_hardware(vim2_display_t* display) {
88
89
90 /* Step 1: Initialize various clocks related to the HDMI Interface*/
91 SET_BIT32(CBUS, PAD_PULL_UP_EN_REG1, 0, 2, 21);
92 SET_BIT32(CBUS, PAD_PULL_UP_REG1, 0, 2, 21);
93 SET_BIT32(CBUS, P_PREG_PAD_GPIO1_EN_N, 3, 2, 21);
94 SET_BIT32(CBUS, PERIPHS_PIN_MUX_6, 3, 2, 29);
95
96 // enable clocks
97 SET_BIT32(HHI, HHI_HDMI_CLK_CNTL, 0x0100, 16, 0);
98
99 // enable clk81 (needed for HDMI module and a bunch of other modules)
100 SET_BIT32(HHI, HHI_GCLK_MPEG2, 1, 1, 4);
101
102 // power up HDMI Memory (bits 15:8)
103 SET_BIT32(HHI, HHI_MEM_PD_REG0, 0, 8, 8);
104
105 // reset hdmi related blocks (HIU, HDMI SYS, HDMI_TX)
106 WRITE32_PRESET_REG(PRESET0_REGISTER, (1 << 19));
107
108 /* FIXME: This will reset the entire HDMI subsystem including the HDCP engine.
109 * At this point, we have no way of initializing HDCP block, so we need to
110 * skip this for now.
111 */
112 // WRITE32_PRESET_REG(PRESET2_REGISTER, (1 << 15)); // Will mess up hdcp stuff
113
114 WRITE32_PRESET_REG(PRESET2_REGISTER, (1 << 2));
115
116 // Enable APB3 fail on error (TODO: where is this defined?)
117 SET_BIT32(HDMITX, 0x8, 1, 1, 15);
118 SET_BIT32(HDMITX, 0x18, 1, 1, 15);
119
120 // Bring HDMI out of reset
121 hdmitx_writereg(display, HDMITX_TOP_SW_RESET, 0);
122 usleep(200);
123 hdmitx_writereg(display, HDMITX_TOP_CLK_CNTL, 0x000000ff);
124 hdmitx_writereg(display, HDMITX_DWC_MC_LOCKONCLOCK, 0xff);
125 hdmitx_writereg(display, HDMITX_DWC_MC_CLKDIS, 0x00);
126
127 /* Step 2: Initialize DDC Interface (For EDID) */
128
129 // FIXME: Pinmux i2c pins (skip for now since uboot it doing it)
130
131 // Configure i2c interface
132 // a. disable all interrupts (read_req, done, nack, arbitration)
133 hdmitx_writereg(display, HDMITX_DWC_I2CM_INT, 0);
134 hdmitx_writereg(display, HDMITX_DWC_I2CM_CTLINT, 0);
135
136 // b. set interface to standard mode
137 hdmitx_writereg(display, HDMITX_DWC_I2CM_DIV, 0);
138
139 // c. Setup i2c timings (based on u-boot source)
140 hdmitx_writereg(display, HDMITX_DWC_I2CM_SS_SCL_HCNT_1, 0);
141 hdmitx_writereg(display, HDMITX_DWC_I2CM_SS_SCL_HCNT_0, 0x67);
142 hdmitx_writereg(display, HDMITX_DWC_I2CM_SS_SCL_LCNT_1, 0);
143 hdmitx_writereg(display, HDMITX_DWC_I2CM_SS_SCL_LCNT_0, 0x78);
144 hdmitx_writereg(display, HDMITX_DWC_I2CM_FS_SCL_HCNT_1, 0);
145 hdmitx_writereg(display, HDMITX_DWC_I2CM_FS_SCL_HCNT_0, 0x0f);
146 hdmitx_writereg(display, HDMITX_DWC_I2CM_FS_SCL_LCNT_1, 0);
147 hdmitx_writereg(display, HDMITX_DWC_I2CM_FS_SCL_LCNT_0, 0x20);
148 hdmitx_writereg(display, HDMITX_DWC_I2CM_SDA_HOLD, 0x08);
149
150 // d. disable any SCDC operations for now
151 hdmitx_writereg(display, HDMITX_DWC_I2CM_SCDC_UPDATE, 0);
152 DISP_INFO("done!!\n");
153 }
154
hdmi_config_csc(vim2_display_t * display,const struct hdmi_param * p)155 static void hdmi_config_csc(vim2_display_t* display, const struct hdmi_param* p) {
156 uint8_t csc_coef_a1_msb;
157 uint8_t csc_coef_a1_lsb;
158 uint8_t csc_coef_a2_msb;
159 uint8_t csc_coef_a2_lsb;
160 uint8_t csc_coef_a3_msb;
161 uint8_t csc_coef_a3_lsb;
162 uint8_t csc_coef_a4_msb;
163 uint8_t csc_coef_a4_lsb;
164 uint8_t csc_coef_b1_msb;
165 uint8_t csc_coef_b1_lsb;
166 uint8_t csc_coef_b2_msb;
167 uint8_t csc_coef_b2_lsb;
168 uint8_t csc_coef_b3_msb;
169 uint8_t csc_coef_b3_lsb;
170 uint8_t csc_coef_b4_msb;
171 uint8_t csc_coef_b4_lsb;
172 uint8_t csc_coef_c1_msb;
173 uint8_t csc_coef_c1_lsb;
174 uint8_t csc_coef_c2_msb;
175 uint8_t csc_coef_c2_lsb;
176 uint8_t csc_coef_c3_msb;
177 uint8_t csc_coef_c3_lsb;
178 uint8_t csc_coef_c4_msb;
179 uint8_t csc_coef_c4_lsb;
180 uint8_t csc_scale;
181 uint32_t hdmi_data;
182
183 if (display->input_color_format == display->output_color_format) {
184 // no need to convert
185 hdmi_data = MC_FLOWCTRL_BYPASS_CSC;
186 } else {
187 // conversion will be needed
188 hdmi_data = MC_FLOWCTRL_ENB_CSC;
189 }
190 hdmitx_writereg(display, HDMITX_DWC_MC_FLOWCTRL, hdmi_data);
191
192 // Since we don't support 422 at this point, set csc_cfg to 0
193 hdmitx_writereg(display, HDMITX_DWC_CSC_CFG, 0);
194
195 // Co-efficient values are from DesignWare Core HDMI TX Video Datapath Application Note V2.1
196
197 // First determine whether we need to convert or not
198 if (display->input_color_format != display->output_color_format) {
199 if (display->input_color_format == HDMI_COLOR_FORMAT_RGB) {
200 // from RGB
201 csc_coef_a1_msb = 0x25;
202 csc_coef_a1_lsb = 0x91;
203 csc_coef_a2_msb = 0x13;
204 csc_coef_a2_lsb = 0x23;
205 csc_coef_a3_msb = 0x07;
206 csc_coef_a3_lsb = 0x4C;
207 csc_coef_a4_msb = 0x00;
208 csc_coef_a4_lsb = 0x00;
209 csc_coef_b1_msb = 0xE5;
210 csc_coef_b1_lsb = 0x34;
211 csc_coef_b2_msb = 0x20;
212 csc_coef_b2_lsb = 0x00;
213 csc_coef_b3_msb = 0xFA;
214 csc_coef_b3_lsb = 0xCC;
215 if (display->color_depth == HDMI_COLOR_DEPTH_24B) {
216 csc_coef_b4_msb = 0x02;
217 csc_coef_b4_lsb = 0x00;
218 csc_coef_c4_msb = 0x02;
219 csc_coef_c4_lsb = 0x00;
220 } else if (display->color_depth == HDMI_COLOR_DEPTH_30B) {
221 csc_coef_b4_msb = 0x08;
222 csc_coef_b4_lsb = 0x00;
223 csc_coef_c4_msb = 0x08;
224 csc_coef_c4_lsb = 0x00;
225 } else if (display->color_depth == HDMI_COLOR_DEPTH_36B) {
226 csc_coef_b4_msb = 0x20;
227 csc_coef_b4_lsb = 0x00;
228 csc_coef_c4_msb = 0x20;
229 csc_coef_c4_lsb = 0x00;
230 } else {
231 csc_coef_b4_msb = 0x20;
232 csc_coef_b4_lsb = 0x00;
233 csc_coef_c4_msb = 0x20;
234 csc_coef_c4_lsb = 0x00;
235 }
236 csc_coef_c1_msb = 0xEA;
237 csc_coef_c1_lsb = 0xCD;
238 csc_coef_c2_msb = 0xF5;
239 csc_coef_c2_lsb = 0x33;
240 csc_coef_c3_msb = 0x20;
241 csc_coef_c3_lsb = 0x00;
242 csc_scale = 0;
243 } else {
244 // to RGB
245 csc_coef_a1_msb =0x10;
246 csc_coef_a1_lsb =0x00;
247 csc_coef_a2_msb =0xf4;
248 csc_coef_a2_lsb =0x93;
249 csc_coef_a3_msb =0xfa;
250 csc_coef_a3_lsb =0x7f;
251 csc_coef_b1_msb =0x10;
252 csc_coef_b1_lsb =0x00;
253 csc_coef_b2_msb =0x16;
254 csc_coef_b2_lsb =0x6e;
255 csc_coef_b3_msb =0x00;
256 csc_coef_b3_lsb =0x00;
257 if (display->color_depth == HDMI_COLOR_DEPTH_24B) {
258 csc_coef_a4_msb = 0x00;
259 csc_coef_a4_lsb = 0x87;
260 csc_coef_b4_msb = 0xff;
261 csc_coef_b4_lsb = 0x4d;
262 csc_coef_c4_msb = 0xff;
263 csc_coef_c4_lsb = 0x1e;
264 } else if (display->color_depth == HDMI_COLOR_DEPTH_30B) {
265 csc_coef_a4_msb = 0x02;
266 csc_coef_a4_lsb = 0x1d;
267 csc_coef_b4_msb = 0xfd;
268 csc_coef_b4_lsb = 0x33;
269 csc_coef_c4_msb = 0xfc;
270 csc_coef_c4_lsb = 0x75;
271 } else if (display->color_depth == HDMI_COLOR_DEPTH_36B) {
272 csc_coef_a4_msb = 0x08;
273 csc_coef_a4_lsb = 0x77;
274 csc_coef_b4_msb = 0xf4;
275 csc_coef_b4_lsb = 0xc9;
276 csc_coef_c4_msb = 0xf1;
277 csc_coef_c4_lsb = 0xd3;
278 } else {
279 csc_coef_a4_msb = 0x08;
280 csc_coef_a4_lsb = 0x77;
281 csc_coef_b4_msb = 0xf4;
282 csc_coef_b4_lsb = 0xc9;
283 csc_coef_c4_msb = 0xf1;
284 csc_coef_c4_lsb = 0xd3;
285 }
286 csc_coef_b4_msb =0xff;
287 csc_coef_b4_lsb =0x4d;
288 csc_coef_c1_msb =0x10;
289 csc_coef_c1_lsb =0x00;
290 csc_coef_c2_msb =0x00;
291 csc_coef_c2_lsb =0x00;
292 csc_coef_c3_msb =0x1c;
293 csc_coef_c3_lsb =0x5a;
294 csc_coef_c4_msb =0xff;
295 csc_coef_c4_lsb =0x1e;
296 csc_scale = 2;
297 }
298 } else {
299 // No conversion. re-write default values just in case
300 csc_coef_a1_msb = 0x20;
301 csc_coef_a1_lsb = 0x00;
302 csc_coef_a2_msb = 0x00;
303 csc_coef_a2_lsb = 0x00;
304 csc_coef_a3_msb = 0x00;
305 csc_coef_a3_lsb = 0x00;
306 csc_coef_a4_msb = 0x00;
307 csc_coef_a4_lsb = 0x00;
308 csc_coef_b1_msb = 0x00;
309 csc_coef_b1_lsb = 0x00;
310 csc_coef_b2_msb = 0x20;
311 csc_coef_b2_lsb = 0x00;
312 csc_coef_b3_msb = 0x00;
313 csc_coef_b3_lsb = 0x00;
314 csc_coef_b4_msb = 0x00;
315 csc_coef_b4_lsb = 0x00;
316 csc_coef_c1_msb = 0x00;
317 csc_coef_c1_lsb = 0x00;
318 csc_coef_c2_msb = 0x00;
319 csc_coef_c2_lsb = 0x00;
320 csc_coef_c3_msb = 0x20;
321 csc_coef_c3_lsb = 0x00;
322 csc_coef_c4_msb = 0x00;
323 csc_coef_c4_lsb = 0x00;
324 csc_scale = 1;
325 }
326
327 hdmitx_writereg(display, HDMITX_DWC_CSC_COEF_A1_MSB, csc_coef_a1_msb);
328 hdmitx_writereg(display, HDMITX_DWC_CSC_COEF_A1_LSB, csc_coef_a1_lsb);
329 hdmitx_writereg(display, HDMITX_DWC_CSC_COEF_A2_MSB, csc_coef_a2_msb);
330 hdmitx_writereg(display, HDMITX_DWC_CSC_COEF_A2_LSB, csc_coef_a2_lsb);
331 hdmitx_writereg(display, HDMITX_DWC_CSC_COEF_A3_MSB, csc_coef_a3_msb);
332 hdmitx_writereg(display, HDMITX_DWC_CSC_COEF_A3_LSB, csc_coef_a3_lsb);
333 hdmitx_writereg(display, HDMITX_DWC_CSC_COEF_A4_MSB, csc_coef_a4_msb);
334 hdmitx_writereg(display, HDMITX_DWC_CSC_COEF_A4_LSB, csc_coef_a4_lsb);
335 hdmitx_writereg(display, HDMITX_DWC_CSC_COEF_B1_MSB, csc_coef_b1_msb);
336 hdmitx_writereg(display, HDMITX_DWC_CSC_COEF_B1_LSB, csc_coef_b1_lsb);
337 hdmitx_writereg(display, HDMITX_DWC_CSC_COEF_B2_MSB, csc_coef_b2_msb);
338 hdmitx_writereg(display, HDMITX_DWC_CSC_COEF_B2_LSB, csc_coef_b2_lsb);
339 hdmitx_writereg(display, HDMITX_DWC_CSC_COEF_B3_MSB, csc_coef_b3_msb);
340 hdmitx_writereg(display, HDMITX_DWC_CSC_COEF_B3_LSB, csc_coef_b3_lsb);
341 hdmitx_writereg(display, HDMITX_DWC_CSC_COEF_B4_MSB, csc_coef_b4_msb);
342 hdmitx_writereg(display, HDMITX_DWC_CSC_COEF_B4_LSB, csc_coef_b4_lsb);
343 hdmitx_writereg(display, HDMITX_DWC_CSC_COEF_C1_MSB, csc_coef_c1_msb);
344 hdmitx_writereg(display, HDMITX_DWC_CSC_COEF_C1_LSB, csc_coef_c1_lsb);
345 hdmitx_writereg(display, HDMITX_DWC_CSC_COEF_C2_MSB, csc_coef_c2_msb);
346 hdmitx_writereg(display, HDMITX_DWC_CSC_COEF_C2_LSB, csc_coef_c2_lsb);
347 hdmitx_writereg(display, HDMITX_DWC_CSC_COEF_C3_MSB, csc_coef_c3_msb);
348 hdmitx_writereg(display, HDMITX_DWC_CSC_COEF_C3_LSB, csc_coef_c3_lsb);
349 hdmitx_writereg(display, HDMITX_DWC_CSC_COEF_C4_MSB, csc_coef_c4_msb);
350 hdmitx_writereg(display, HDMITX_DWC_CSC_COEF_C4_LSB, csc_coef_c4_lsb);
351
352 hdmi_data = 0;
353 hdmi_data |= CSC_SCALE_COLOR_DEPTH(display->color_depth);
354 hdmi_data |= CSC_SCALE_CSCSCALE(csc_scale);
355 hdmitx_writereg(display, HDMITX_DWC_CSC_SCALE, hdmi_data);
356
357 }
358
hdmi_config_encoder(vim2_display_t * display,const struct hdmi_param * p)359 static void hdmi_config_encoder(vim2_display_t* display, const struct hdmi_param* p) {
360 uint32_t h_begin, h_end;
361 uint32_t v_begin, v_end;
362 uint32_t hs_begin, hs_end;
363 uint32_t vs_begin, vs_end;
364 uint32_t vsync_adjust = 0;
365 uint32_t active_lines, total_lines;
366 uint32_t venc_total_pixels, venc_active_pixels, venc_fp, venc_hsync;
367
368
369 active_lines = (p->timings.vactive / (1 + p->timings.interlace_mode));
370 total_lines = (active_lines + p->timings.vblank0) +
371 ((active_lines + p->timings.vblank1)*p->timings.interlace_mode);
372
373 venc_total_pixels = (p->timings.htotal / (p->timings.pixel_repeat + 1)) *
374 (p->timings.venc_pixel_repeat + 1);
375
376 venc_active_pixels = (p->timings.hactive / (p->timings.pixel_repeat + 1)) *
377 (p->timings.venc_pixel_repeat + 1);
378
379 venc_fp = (p->timings.hfront / (p->timings.pixel_repeat + 1)) *
380 (p->timings.venc_pixel_repeat + 1);
381
382 venc_hsync = (p->timings.hsync / (p->timings.pixel_repeat + 1)) *
383 (p->timings.venc_pixel_repeat + 1);
384
385
386 SET_BIT32(VPU, VPU_ENCP_VIDEO_MODE, 1, 1, 14); // DE Signal polarity
387 WRITE32_REG(VPU, VPU_ENCP_VIDEO_HAVON_BEGIN, p->timings.hsync + p->timings.hback);
388 WRITE32_REG(VPU, VPU_ENCP_VIDEO_HAVON_END, p->timings.hsync + p->timings.hback +
389 p->timings.hactive - 1);
390
391 WRITE32_REG(VPU, VPU_ENCP_VIDEO_VAVON_BLINE, p->timings.vsync + p->timings.vback);
392 WRITE32_REG(VPU, VPU_ENCP_VIDEO_VAVON_ELINE, p->timings.vsync + p->timings.vback +
393 p->timings.vactive - 1);
394
395 WRITE32_REG(VPU, VPU_ENCP_VIDEO_HSO_BEGIN, 0);
396 WRITE32_REG(VPU, VPU_ENCP_VIDEO_HSO_END, p->timings.hsync);
397
398 WRITE32_REG(VPU, VPU_ENCP_VIDEO_VSO_BLINE, 0);
399 WRITE32_REG(VPU, VPU_ENCP_VIDEO_VSO_ELINE, p->timings.vsync);
400
401 // Below calculations assume no pixel repeat and progressive mode.
402 // HActive Start/End
403 h_begin = p->timings.hsync + p->timings.hback + 2; // 2 is the HDMI Latency
404
405 h_begin = h_begin % venc_total_pixels; // wrap around if needed
406 h_end = h_begin + venc_active_pixels;
407 h_end = h_end % venc_total_pixels; // wrap around if needed
408 WRITE32_REG(VPU, VPU_ENCP_DE_H_BEGIN, h_begin);
409 WRITE32_REG(VPU, VPU_ENCP_DE_H_END, h_end);
410
411 // VActive Start/End
412 v_begin = p->timings.vsync + p->timings.vback;
413 v_end = v_begin + active_lines;
414 WRITE32_REG(VPU, VPU_ENCP_DE_V_BEGIN_EVEN, v_begin);
415 WRITE32_REG(VPU, VPU_ENCP_DE_V_END_EVEN, v_end);
416
417 if (p->timings.interlace_mode) {
418 // TODO: Add support for interlace mdoe
419 // We should not even get here
420 DISP_ERROR("Interface mode not supported\n");
421 }
422
423 // HSync Timings
424 hs_begin = h_end + venc_fp;
425 if (hs_begin >= venc_total_pixels) {
426 hs_begin -= venc_total_pixels;
427 vsync_adjust = 1;
428 }
429
430 hs_end = hs_begin + venc_hsync;
431 hs_end = hs_end % venc_total_pixels;
432 WRITE32_REG(VPU, VPU_ENCP_DVI_HSO_BEGIN, hs_begin);
433 WRITE32_REG(VPU, VPU_ENCP_DVI_HSO_END, hs_end);
434
435 // VSync Timings
436 if (v_begin >= (p->timings.vback + p->timings.vsync + (1 - vsync_adjust))) {
437 vs_begin = v_begin - p->timings.vback - p->timings.vsync - (1 - vsync_adjust);
438 } else {
439 vs_begin = p->timings.vtotal + v_begin - p->timings.vback - p->timings.vsync -
440 (1 - vsync_adjust);
441 }
442 vs_end = vs_begin + p->timings.vsync;
443 vs_end = vs_end % total_lines;
444
445 WRITE32_REG(VPU, VPU_ENCP_DVI_VSO_BLINE_EVN, vs_begin);
446 WRITE32_REG(VPU, VPU_ENCP_DVI_VSO_ELINE_EVN, vs_end);
447 WRITE32_REG(VPU, VPU_ENCP_DVI_VSO_BEGIN_EVN, hs_begin);
448 WRITE32_REG(VPU, VPU_ENCP_DVI_VSO_END_EVN, hs_begin);
449
450 WRITE32_REG(VPU, VPU_HDMI_SETTING, 0);
451 // hsync, vsync active high. output CbYCr (GRB)
452 // TODO: output desired format is hardcoded here to CbYCr (GRB)
453 WRITE32_REG(VPU, VPU_HDMI_SETTING, (p->timings.hpol << 2) | (p->timings.vpol << 3) | (4 << 5));
454
455 if (p->timings.venc_pixel_repeat) {
456 SET_BIT32(VPU, VPU_HDMI_SETTING, 1, 1, 8);
457 }
458
459 // Select ENCP data to HDMI
460 SET_BIT32(VPU, VPU_HDMI_SETTING, 2, 2, 0);
461
462 DISP_INFO("done\n");
463 }
464
hdmi_config_hdmitx(vim2_display_t * display,const struct hdmi_param * p)465 static void hdmi_config_hdmitx(vim2_display_t* display, const struct hdmi_param* p) {
466 uint32_t hdmi_data;
467
468 // Output normal TMDS Data
469 hdmi_data = (1 << 12);
470 hdmitx_writereg(display, HDMITX_TOP_BIST_CNTL, hdmi_data);
471
472 // setup video input mapping
473 hdmi_data = 0;
474 if (display->input_color_format == HDMI_COLOR_FORMAT_RGB) {
475 switch (display->color_depth) {
476 case HDMI_COLOR_DEPTH_24B:
477 hdmi_data |= TX_INVID0_VM_RGB444_8B;
478 break;
479 case HDMI_COLOR_DEPTH_30B:
480 hdmi_data |= TX_INVID0_VM_RGB444_10B;
481 break;
482 case HDMI_COLOR_DEPTH_36B:
483 hdmi_data |= TX_INVID0_VM_RGB444_12B;
484 break;
485 case HDMI_COLOR_DEPTH_48B:
486 default:
487 hdmi_data |= TX_INVID0_VM_RGB444_16B;
488 break;
489 }
490 } else if (display->input_color_format == HDMI_COLOR_FORMAT_444) {
491 switch (display->color_depth) {
492 case HDMI_COLOR_DEPTH_24B:
493 hdmi_data |= TX_INVID0_VM_YCBCR444_8B;
494 break;
495 case HDMI_COLOR_DEPTH_30B:
496 hdmi_data |= TX_INVID0_VM_YCBCR444_10B;
497 break;
498 case HDMI_COLOR_DEPTH_36B:
499 hdmi_data |= TX_INVID0_VM_YCBCR444_12B;
500 break;
501 case HDMI_COLOR_DEPTH_48B:
502 default:
503 hdmi_data |= TX_INVID0_VM_YCBCR444_16B;
504 break;
505 }
506 } else {
507 DISP_ERROR("Unsupported format!\n");
508 return;
509 }
510 hdmitx_writereg(display, HDMITX_DWC_TX_INVID0, hdmi_data);
511
512
513 // Disable video input stuffing and zero-out related registers
514 hdmitx_writereg(display, HDMITX_DWC_TX_INSTUFFING, 0x00);
515 hdmitx_writereg(display, HDMITX_DWC_TX_GYDATA0, 0x00);
516 hdmitx_writereg(display, HDMITX_DWC_TX_GYDATA1, 0x00);
517 hdmitx_writereg(display, HDMITX_DWC_TX_RCRDATA0, 0x00);
518 hdmitx_writereg(display, HDMITX_DWC_TX_RCRDATA1, 0x00);
519 hdmitx_writereg(display, HDMITX_DWC_TX_BCBDATA0, 0x00);
520 hdmitx_writereg(display, HDMITX_DWC_TX_BCBDATA1, 0x00);
521
522 // configure CSC (Color Space Converter)
523 hdmi_config_csc(display, p);
524
525 // Video packet color depth and pixel repetition (none). writing 0 is also valid
526 // hdmi_data = (4 << 4); // 4 == 24bit
527 // hdmi_data = (display->color_depth << 4); // 4 == 24bit
528 hdmi_data = (0 << 4); // 4 == 24bit
529 hdmitx_writereg(display, HDMITX_DWC_VP_PR_CD, hdmi_data);
530
531 // setup video packet stuffing (nothing fancy to be done here)
532 hdmi_data = 0;
533 hdmitx_writereg(display, HDMITX_DWC_VP_STUFF, hdmi_data);
534
535 // setup video packet remap (nothing here as well since we don't support 422)
536 hdmi_data = 0;
537 hdmitx_writereg(display, HDMITX_DWC_VP_REMAP, hdmi_data);
538
539 // vp packet output configuration
540 // hdmi_data = 0;
541 hdmi_data = VP_CONF_BYPASS_EN;
542 hdmi_data |= VP_CONF_BYPASS_SEL_VP;
543 hdmi_data |= VP_CONF_OUTSELECTOR;
544 hdmitx_writereg(display, HDMITX_DWC_VP_CONF, hdmi_data);
545
546 // Video packet Interrupt Mask
547 hdmi_data = 0xFF; // set all bits
548 hdmitx_writereg(display, HDMITX_DWC_VP_MASK, hdmi_data);
549
550 // TODO: For now skip audio configuration
551
552 // Setup frame composer
553
554 // fc_invidconf setup
555 hdmi_data = 0;
556 hdmi_data |= FC_INVIDCONF_HDCP_KEEPOUT;
557 hdmi_data |= FC_INVIDCONF_VSYNC_POL(p->timings.vpol);
558 hdmi_data |= FC_INVIDCONF_HSYNC_POL(p->timings.hpol);
559 hdmi_data |= FC_INVIDCONF_DE_POL_H;
560 hdmi_data |= FC_INVIDCONF_DVI_HDMI_MODE;
561 if (p->timings.interlace_mode) {
562 hdmi_data |= FC_INVIDCONF_VBLANK_OSC | FC_INVIDCONF_IN_VID_INTERLACED;
563 }
564 hdmitx_writereg(display, HDMITX_DWC_FC_INVIDCONF, hdmi_data);
565
566 // HActive
567 hdmi_data = p->timings.hactive;
568 hdmitx_writereg(display, HDMITX_DWC_FC_INHACTV0, (hdmi_data & 0xff));
569 hdmitx_writereg(display, HDMITX_DWC_FC_INHACTV1, ((hdmi_data >> 8) & 0x3f));
570
571 // HBlank
572 hdmi_data = p->timings.hblank;
573 hdmitx_writereg(display, HDMITX_DWC_FC_INHBLANK0, (hdmi_data & 0xff));
574 hdmitx_writereg(display, HDMITX_DWC_FC_INHBLANK1, ((hdmi_data >> 8) & 0x1f));
575
576 // VActive
577 hdmi_data = p->timings.vactive;
578 hdmitx_writereg(display, HDMITX_DWC_FC_INVACTV0, (hdmi_data & 0xff));
579 hdmitx_writereg(display, HDMITX_DWC_FC_INVACTV1, ((hdmi_data >> 8) & 0x1f));
580
581 // VBlank
582 hdmi_data = p->timings.vblank0;
583 hdmitx_writereg(display, HDMITX_DWC_FC_INVBLANK, (hdmi_data & 0xff));
584
585 // HFP
586 hdmi_data = p->timings.hfront;
587 hdmitx_writereg(display, HDMITX_DWC_FC_HSYNCINDELAY0, (hdmi_data & 0xff));
588 hdmitx_writereg(display, HDMITX_DWC_FC_HSYNCINDELAY1, ((hdmi_data >> 8) & 0x1f));
589
590 // HSync
591 hdmi_data = p->timings.hsync;
592 hdmitx_writereg(display, HDMITX_DWC_FC_HSYNCINWIDTH0, (hdmi_data & 0xff));
593 hdmitx_writereg(display, HDMITX_DWC_FC_HSYNCINWIDTH1, ((hdmi_data >> 8) & 0x3));
594
595 // VFront
596 hdmi_data = p->timings.vfront;
597 hdmitx_writereg(display, HDMITX_DWC_FC_VSYNCINDELAY, (hdmi_data & 0xff));
598
599 //VSync
600 hdmi_data = p->timings.vsync;
601 hdmitx_writereg(display, HDMITX_DWC_FC_VSYNCINWIDTH, (hdmi_data & 0x3f));
602
603 // Frame Composer control period duration (set to 12 per spec)
604 hdmitx_writereg(display, HDMITX_DWC_FC_CTRLDUR, 12);
605
606 // Frame Composer extended control period duration (set to 32 per spec)
607 hdmitx_writereg(display, HDMITX_DWC_FC_EXCTRLDUR, 32);
608
609 // Frame Composer extended control period max spacing (FIXME: spec says 50, uboot sets to 1)
610 hdmitx_writereg(display, HDMITX_DWC_FC_EXCTRLSPAC, 1);
611
612 // Frame Composer preamble filler (from uBoot)
613
614 // Frame Composer GCP packet config
615 hdmi_data = (1 << 1); // set avmute. defauly_phase is 0
616 hdmitx_writereg(display, HDMITX_DWC_FC_GCP, hdmi_data);
617
618 // Frame Composer AVI Packet config (set active_format_present bit)
619 // aviconf0 populates Table 10 of CEA spec (AVI InfoFrame Data Byte 1)
620 // Y1Y0 = 00 for RGB, 10 for 444
621 if (display->output_color_format == HDMI_COLOR_FORMAT_RGB) {
622 hdmi_data = FC_AVICONF0_RGB;
623 } else {
624 hdmi_data = FC_AVICONF0_444;
625 }
626 // A0 = 1 Active Formate present on R3R0
627 hdmi_data |= FC_AVICONF0_A0;
628 hdmitx_writereg(display, HDMITX_DWC_FC_AVICONF0, hdmi_data);
629
630 // aviconf1 populates Table 11 of AVI InfoFrame Data Byte 2
631 // C1C0 = 0, M1M0=0x2 (16:9), R3R2R1R0=0x8 (same of M1M0)
632 hdmi_data = FC_AVICONF1_R3R0; // set to 0x8 (same as coded frame aspect ratio)
633 hdmi_data |= FC_AVICONF1_M1M0(p->aspect_ratio);
634 hdmi_data |= FC_AVICONF1_C1C0(p->colorimetry);
635 hdmitx_writereg(display, HDMITX_DWC_FC_AVICONF1, hdmi_data);
636
637 // Since we are support RGB/444, no need to write to ECx
638 hdmitx_writereg(display, HDMITX_DWC_FC_AVICONF2, 0x0);
639
640 // YCC and IT Quantizations according to CEA spec (limited range for now)
641 hdmitx_writereg(display, HDMITX_DWC_FC_AVICONF3, 0x0);
642
643 // Set AVI InfoFrame VIC
644 // hdmitx_writereg(display, HDMITX_DWC_FC_AVIVID, (p->vic >= VESA_OFFSET)? 0 : p->vic);
645
646 hdmitx_writereg(display, HDMITX_DWC_FC_ACTSPC_HDLR_CFG, 0);
647
648 // Frame composer 2d vact config
649 hdmi_data = p->timings.vactive;
650 hdmitx_writereg(display, HDMITX_DWC_FC_INVACT_2D_0, (hdmi_data & 0xff));
651 hdmitx_writereg(display, HDMITX_DWC_FC_INVACT_2D_1, ((hdmi_data >> 8) & 0xf));
652
653 // disable all Frame Composer interrupts
654 hdmitx_writereg(display, HDMITX_DWC_FC_MASK0, 0xe7);
655 hdmitx_writereg(display, HDMITX_DWC_FC_MASK1, 0xfb);
656 hdmitx_writereg(display, HDMITX_DWC_FC_MASK2, 0x3);
657
658 // No pixel repeition for the currently supported resolution
659 hdmitx_writereg(display, HDMITX_DWC_FC_PRCONF,
660 ((p->timings.pixel_repeat + 1) << 4) |
661 (p->timings.pixel_repeat) << 0);
662
663 // Skip HDCP for now
664
665 // Clear Interrupts
666 hdmitx_writereg(display, HDMITX_DWC_IH_FC_STAT0, 0xff);
667 hdmitx_writereg(display, HDMITX_DWC_IH_FC_STAT1, 0xff);
668 hdmitx_writereg(display, HDMITX_DWC_IH_FC_STAT2, 0xff);
669 hdmitx_writereg(display, HDMITX_DWC_IH_AS_STAT0, 0xff);
670 hdmitx_writereg(display, HDMITX_DWC_IH_PHY_STAT0, 0xff);
671 hdmitx_writereg(display, HDMITX_DWC_IH_I2CM_STAT0, 0xff);
672 hdmitx_writereg(display, HDMITX_DWC_IH_CEC_STAT0, 0xff);
673 hdmitx_writereg(display, HDMITX_DWC_IH_VP_STAT0, 0xff);
674 hdmitx_writereg(display, HDMITX_DWC_IH_I2CMPHY_STAT0, 0xff);
675 hdmitx_writereg(display, HDMITX_DWC_A_APIINTCLR, 0xff);
676 hdmitx_writereg(display, HDMITX_DWC_HDCP22REG_STAT, 0xff);
677
678 hdmitx_writereg(display, HDMITX_TOP_INTR_STAT_CLR, 0x0000001f);
679
680 // setup interrupts we care about
681 hdmitx_writereg(display, HDMITX_DWC_IH_MUTE_FC_STAT0, 0xff);
682 hdmitx_writereg(display, HDMITX_DWC_IH_MUTE_FC_STAT1, 0xff);
683 hdmitx_writereg(display, HDMITX_DWC_IH_MUTE_FC_STAT2, 0x3);
684
685 hdmitx_writereg(display, HDMITX_DWC_IH_MUTE_AS_STAT0, 0x7); // mute all
686
687 hdmitx_writereg(display, HDMITX_DWC_IH_MUTE_PHY_STAT0, 0x3f);
688
689 hdmi_data = (1 << 1); // mute i2c master done.
690 hdmitx_writereg(display, HDMITX_DWC_IH_MUTE_I2CM_STAT0, hdmi_data);
691
692 // turn all cec-related interrupts on
693 hdmitx_writereg(display, HDMITX_DWC_IH_MUTE_CEC_STAT0, 0x0);
694
695 hdmitx_writereg(display, HDMITX_DWC_IH_MUTE_VP_STAT0, 0xff);
696
697 hdmitx_writereg(display, HDMITX_DWC_IH_MUTE_I2CMPHY_STAT0, 0x03);
698
699 // enable global interrupt
700 hdmitx_writereg(display, HDMITX_DWC_IH_MUTE, 0x0);
701
702 hdmitx_writereg(display, HDMITX_TOP_INTR_MASKN, 0x1f);
703
704 // reset
705 hdmitx_writereg(display, HDMITX_DWC_MC_SWRSTZREQ, 0x00);
706 usleep(10);
707 hdmitx_writereg(display, HDMITX_DWC_MC_SWRSTZREQ, 0xdd);
708 // why???
709 hdmitx_writereg(display, HDMITX_DWC_FC_VSYNCINWIDTH, hdmitx_readreg(display, HDMITX_DWC_FC_VSYNCINWIDTH));
710
711 // dump_regs(display);
712 DISP_INFO("done\n");
713 }
714
hdmi_config_phy(vim2_display_t * display,const struct hdmi_param * p)715 static void hdmi_config_phy(vim2_display_t* display, const struct hdmi_param* p) {
716
717 WRITE32_REG(HHI, HHI_HDMI_PHY_CNTL0, 0);
718 SET_BIT32(HHI, HHI_HDMI_PHY_CNTL1, 0x0390, 16, 16);
719 SET_BIT32(HHI, HHI_HDMI_PHY_CNTL1, 0x0, 4, 0);
720
721 SET_BIT32(HHI, HHI_HDMI_PHY_CNTL1, 0xf, 4, 0);
722 usleep(2);
723 SET_BIT32(HHI, HHI_HDMI_PHY_CNTL1, 0xe, 4, 0);
724 usleep(2);
725 SET_BIT32(HHI, HHI_HDMI_PHY_CNTL1, 0xf, 4, 0);
726 usleep(2);
727 SET_BIT32(HHI, HHI_HDMI_PHY_CNTL1, 0xe, 4, 0);
728 usleep(2);
729
730 switch (p->phy_mode) {
731 case 1: /* 5.94Gbps, 3.7125Gbsp */
732 WRITE32_REG(HHI, HHI_HDMI_PHY_CNTL0, 0x333d3282);
733 WRITE32_REG(HHI, HHI_HDMI_PHY_CNTL3, 0x2136315b);
734 break;
735 case 2: /* 2.97Gbps */
736 WRITE32_REG(HHI, HHI_HDMI_PHY_CNTL0, 0x33303382);
737 WRITE32_REG(HHI, HHI_HDMI_PHY_CNTL3, 0x2036315b);
738 break;
739 case 3: /* 1.485Gbps */
740 WRITE32_REG(HHI, HHI_HDMI_PHY_CNTL0, 0x33303042);
741 WRITE32_REG(HHI, HHI_HDMI_PHY_CNTL3, 0x2016315b);
742 break;
743 default: /* 742.5Mbps, and below */
744 WRITE32_REG(HHI, HHI_HDMI_PHY_CNTL0, 0x33604132);
745 WRITE32_REG(HHI, HHI_HDMI_PHY_CNTL3, 0x0016315b);
746 break;
747
748 }
749 usleep(20);
750 DISP_INFO("done!\n");
751 }
752
753 #if 0
754 /* FIXME: Write better HDMI Test functions
755 * Leave this function commented out for now
756 */
757 void hdmi_test(vim2_display_t* display, uint32_t width) {
758 SET_BIT32(VPU, VPU_ENCP_VIDEO_MODE_ADV, 0, 1, 3);
759 WRITE32_REG(VPU, VPU_VENC_VIDEO_TST_EN, 1);
760 DISP_INFO("width = %d\n", width);
761 while (1) {
762 // (107, 202, 222)
763 WRITE32_REG(VPU, VPU_VENC_VIDEO_TST_MDSEL, 0);
764 WRITE32_REG(VPU, VPU_VENC_VIDEO_TST_Y, 107);
765 WRITE32_REG(VPU, VPU_VENC_VIDEO_TST_CB, 202);
766 WRITE32_REG(VPU, VPU_VENC_VIDEO_TST_CR, 222);
767 sleep(5);
768 WRITE32_REG(VPU, VPU_VENC_VIDEO_TST_MDSEL, 1);
769 WRITE32_REG(VPU, VPU_VENC_VIDEO_TST_CLRBAR_WIDTH, 250);
770 WRITE32_REG(VPU, VPU_VENC_VIDEO_TST_CLRBAR_STRT, 0);
771 sleep(5);
772 WRITE32_REG(VPU, VPU_VENC_VIDEO_TST_MDSEL, 2);
773 sleep(5);
774 WRITE32_REG(VPU, VPU_VENC_VIDEO_TST_MDSEL, 3);
775 sleep(5);
776 }
777 }
778 #endif
779
init_hdmi_interface(vim2_display_t * display,const struct hdmi_param * p)780 void init_hdmi_interface(vim2_display_t* display, const struct hdmi_param* p) {
781
782 uint8_t scdc_data = 0;
783 uint32_t regval = 0;
784
785 // FIXME: Need documentation for HDMI PLL initialization
786 configure_pll(display, p, &p->pll_p_24b);
787
788 for (size_t i = 0; ENC_LUT_GEN[i].reg != 0xFFFFFFFF; i++) {
789 WRITE32_REG(VPU, ENC_LUT_GEN[i].reg, ENC_LUT_GEN[i].val);
790 }
791
792 WRITE32_REG(VPU, VPU_ENCP_VIDEO_MAX_PXCNT, (p->timings.venc_pixel_repeat)?
793 ((p->timings.htotal << 1) - 1) : (p->timings.htotal - 1));
794 WRITE32_REG(VPU, VPU_ENCP_VIDEO_MAX_LNCNT, p->timings.vtotal - 1);
795
796 if (p->timings.venc_pixel_repeat) {
797 SET_BIT32(VPU, VPU_ENCP_VIDEO_MODE_ADV, 1, 1, 0);
798 }
799
800 // Configure Encoder with detailed timing info (based on resolution)
801 hdmi_config_encoder(display, p);
802
803 // Configure VDAC
804 WRITE32_REG(HHI, HHI_VDAC_CNTL0, 0);
805 WRITE32_REG(HHI, HHI_VDAC_CNTL1, 8); // set Cdac_pwd [whatever that is]
806
807 // Configure HDMI TX IP
808 hdmi_config_hdmitx(display, p);
809
810 if (p->is4K) {
811 // Setup TMDS Clocks (magic numbers)
812 hdmitx_writereg(display, HDMITX_TOP_TMDS_CLK_PTTN_01, 0);
813 hdmitx_writereg(display, HDMITX_TOP_TMDS_CLK_PTTN_23, 0x03ff03ff);
814 hdmitx_writereg(display, HDMITX_DWC_FC_SCRAMBLER_CTRL,
815 hdmitx_readreg(display, HDMITX_DWC_FC_SCRAMBLER_CTRL) | (1 << 0));
816 } else {
817 hdmitx_writereg(display, HDMITX_TOP_TMDS_CLK_PTTN_01, 0x001f001f);
818 hdmitx_writereg(display, HDMITX_TOP_TMDS_CLK_PTTN_23, 0x001f001f);
819 hdmitx_writereg(display, HDMITX_DWC_FC_SCRAMBLER_CTRL, 0);
820 }
821
822 hdmitx_writereg(display, HDMITX_TOP_TMDS_CLK_PTTN_CNTL, 0x1);
823 usleep(2);
824 hdmitx_writereg(display, HDMITX_TOP_TMDS_CLK_PTTN_CNTL, 0x2);
825
826 hdmi_scdc_read(display, 0x1, &scdc_data);
827 DISP_INFO("version is %s\n", (scdc_data == 1)? "2.0" : "<= 1.4");
828 // scdc write is done twice in uboot
829 // TODO: find scdc register def
830 hdmi_scdc_write(display, 0x2, 0x1);
831 hdmi_scdc_write(display, 0x2, 0x1);
832
833 if (p->is4K) {
834 hdmi_scdc_write(display, 0x20, 3);
835 hdmi_scdc_write(display, 0x20, 3);
836 } else {
837 hdmi_scdc_write(display, 0x20, 0);
838 hdmi_scdc_write(display, 0x20, 0);
839 }
840
841 // Setup HDMI related registers in VPU
842
843 // not really needed since we are not converting from 420/422. but set anyways
844 WRITE32_REG(VPU, VPU_HDMI_FMT_CTRL, (2 << 2));
845
846 // setup some magic registers
847 SET_BIT32(VPU, VPU_HDMI_FMT_CTRL, 0, 1, 4);
848 SET_BIT32(VPU, VPU_HDMI_FMT_CTRL, 1, 1, 10);
849 SET_BIT32(VPU, VPU_HDMI_DITH_CNTL, 1, 1, 4);
850 SET_BIT32(VPU, VPU_HDMI_DITH_CNTL, 0, 2, 2);
851
852 // reset vpu bridge
853 regval = (READ32_REG(VPU, VPU_HDMI_SETTING) & 0xf00) >> 8;
854 WRITE32_REG(VPU, VPU_ENCP_VIDEO_EN, 0);
855 SET_BIT32(VPU, VPU_HDMI_SETTING, 0, 2, 0); // disable hdmi source
856 SET_BIT32(VPU, VPU_HDMI_SETTING, 0, 4, 8); // why???
857 usleep(1);
858 WRITE32_REG(VPU, VPU_ENCP_VIDEO_EN, 1);
859 usleep(1);
860 SET_BIT32(VPU, VPU_HDMI_SETTING, regval, 4, 8); // why???
861 usleep(1);
862 SET_BIT32(VPU, VPU_HDMI_SETTING, 2, 2, 0); // select encp data to hdmi
863
864 regval = hdmitx_readreg(display, HDMITX_DWC_FC_INVIDCONF);
865 regval &= ~(1 << 3); // clear hdmi mode select
866 hdmitx_writereg(display,HDMITX_DWC_FC_INVIDCONF, regval);
867 usleep(1);
868 regval = hdmitx_readreg(display, HDMITX_DWC_FC_INVIDCONF);
869 regval |= (1 << 3); // clear hdmi mode select
870 hdmitx_writereg(display,HDMITX_DWC_FC_INVIDCONF, regval);
871 usleep(1);
872
873 // setup hdmi phy
874 hdmi_config_phy(display, p);
875 hdmitx_writereg(display, HDMITX_DWC_FC_GCP, (1 << 0));
876
877 DISP_INFO("done!!\n");
878 }
879
dump_regs(vim2_display_t * display)880 void dump_regs(vim2_display_t* display)
881 {
882 unsigned int reg_adr;
883 unsigned int reg_val;
884 unsigned int ladr;
885 for (reg_adr = 0x0000; reg_adr < 0x0100; reg_adr ++) {
886 ladr = (reg_adr << 2);
887 reg_val = READ32_REG(HHI, ladr);
888 DISP_INFO("[0x%08x] = 0x%X\n", ladr, reg_val);
889 }
890 #define VPU_REG_ADDR(reg) ((reg << 2))
891 for (reg_adr = 0x1b00; reg_adr < 0x1c00; reg_adr ++) {
892 ladr = VPU_REG_ADDR(reg_adr);
893 reg_val = READ32_REG(VPU, ladr);
894 DISP_INFO("[0x%08x] = 0x%X\n", ladr, reg_val);
895 }
896 for (reg_adr = 0x1c01; reg_adr < 0x1d00; reg_adr ++) {
897 ladr = VPU_REG_ADDR(reg_adr);
898 reg_val = READ32_REG(VPU, ladr);
899 DISP_INFO("[0x%08x] = 0x%X\n", ladr, reg_val);
900 }
901 for (reg_adr = 0x2700; reg_adr < 0x2780; reg_adr ++) {
902 ladr = VPU_REG_ADDR(reg_adr);
903 reg_val = READ32_REG(VPU, ladr);
904 DISP_INFO("[0x%08x] = 0x%X\n", ladr, reg_val);
905 }
906 for (reg_adr = HDMITX_TOP_SW_RESET; reg_adr < HDMITX_TOP_STAT0 + 1; reg_adr ++) {
907 reg_val = hdmitx_readreg(display, reg_adr);
908 DISP_INFO("TOP[0x%x]: 0x%x\n", reg_adr, reg_val);
909 }
910 for (reg_adr = HDMITX_DWC_DESIGN_ID; reg_adr < HDMITX_DWC_I2CM_SCDC_UPDATE1 + 1; reg_adr ++) {
911 if ((reg_adr > HDMITX_DWC_HDCP_BSTATUS_0 -1) && (reg_adr < HDMITX_DWC_HDCPREG_BKSV0)) {
912 reg_val = 0;
913 } else {
914 reg_val = hdmitx_readreg(display, reg_adr);
915 }
916 if (reg_val) {
917 // excluse HDCP regisiters
918 if ((reg_adr < HDMITX_DWC_A_HDCPCFG0) || (reg_adr > HDMITX_DWC_CEC_CTRL))
919 DISP_INFO("DWC[0x%x]: 0x%x\n", reg_adr, reg_val);
920 }
921 }
922 }
923