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