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 #pragma once
6 
7 #include <assert.h>
8 #include <stdint.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <ddk/device.h>
13 #include <ddk/io-buffer.h>
14 #include <ddk/protocol/platform/device.h>
15 #include <zircon/listnode.h>
16 #include <zircon/types.h>
17 #include <threads.h>
18 #include "vpu.h"
19 #include "dwc-hdmi.h"
20 
21 __BEGIN_CDECLS
22 
23 #define DISPLAY_MASK(start, count) (((1 << (count)) - 1) << (start))
24 #define DISPLAY_SET_MASK(mask, start, count, value) \
25                         ((mask & ~DISPLAY_MASK(start, count)) | \
26                                 (((value) << (start)) & DISPLAY_MASK(start, count)))
27 
28 #define READ32_PRESET_REG(a)             display->mmio_preset->Read32(a)
29 #define WRITE32_PRESET_REG(a, v)         display->mmio_preset->Write32(v, a)
30 
31 #define READ32_HDMITX_REG(a)             display->mmio_hdmitx->Read32(a)
32 #define WRITE32_HDMITX_REG(a, v)         display->mmio_hdmitx->Write32(v, a)
33 
34 #define READ32_HHI_REG(a)                display->mmio_hiu->Read32(a)
35 #define WRITE32_HHI_REG(a, v)            display->mmio_hiu->Write32(v, a)
36 
37 #define READ32_VPU_REG(a)                display->mmio_vpu->Read32(a)
38 #define WRITE32_VPU_REG(a, v)            display->mmio_vpu->Write32(v, a)
39 
40 #define READ32_HDMITX_SEC_REG(a)         display->mmio_hdmitx_sec->Read32(a)
41 #define WRITE32_HDMITX_SEC_REG(a, v)     display->mmio_hdmitx_sec->Write32(v, a)
42 
43 #define READ32_CBUS_REG(a)               display->mmio_cbus->Read32(0x400 + a)
44 #define WRITE32_CBUS_REG(a, v)           display->mmio_cbus->Write32(v, 0x400 + a)
45 
46 #define SET_BIT32(x, dest, value, count, start) \
47             WRITE32_##x##_REG(dest, (READ32_##x##_REG(dest) & ~DISPLAY_MASK(start, count)) | \
48                                 (((value) << (start)) & DISPLAY_MASK(start, count)))
49 
50 #define WRITE32_REG(x, a, v)    WRITE32_##x##_REG(a, v)
51 #define READ32_REG(x, a)        READ32_##x##_REG(a)
52 
53 #define SEC_OFFSET           (0x1UL << 24)
54 #define TOP_OFFSET_MASK      (0x0UL << 24)
55 #define TOP_SEC_OFFSET_MASK  ((TOP_OFFSET_MASK) | (SEC_OFFSET))
56 #define DWC_OFFSET_MASK      (0x10UL << 24)
57 #define DWC_SEC_OFFSET_MASK  ((DWC_OFFSET_MASK) | (SEC_OFFSET))
58 
59 #define DMC_CAV_LUT_DATAL           (0x12 << 2)
60 #define DMC_CAV_LUT_DATAH           (0x13 << 2)
61 #define DMC_CAV_LUT_ADDR             (0x14 << 2)
62 
63 #define DMC_CAV_ADDR_LMASK       0x1fffffff
64 #define DMC_CAV_WIDTH_LMASK      0x7
65 #define DMC_CAV_WIDTH_LWID       3
66 #define DMC_CAV_WIDTH_LBIT       29
67 
68 #define DMC_CAV_WIDTH_HMASK      0x1ff
69 #define DMC_CAV_WIDTH_HBIT       0
70 #define DMC_CAV_HEIGHT_MASK      0x1fff
71 #define DMC_CAV_HEIGHT_BIT       9
72 
73 #define DMC_CAV_LUT_ADDR_INDEX_MASK  0x7
74 #define DMC_CAV_LUT_ADDR_RD_EN       (1 << 8)
75 #define DMC_CAV_LUT_ADDR_WR_EN       (2 << 8)
76 
77 
78 // P RESET
79 #define PRESET_REGISTER                                 (0x400)
80 #define PRESET0_REGISTER                                (0x404)
81 #define PRESET2_REGISTER                                (0x40C)
82 
83 // HDMITX ADDRESS and DATA PORTS
84 #define HDMITX_ADDR_PORT                                (0x00)
85 #define HDMITX_DATA_PORT                                (0x04)
86 #define HDMITX_CTRL_PORT                                (0x08)
87 
88 
89 // HDMI TOP
90 #define HDMITX_TOP_SW_RESET                             (TOP_OFFSET_MASK + 0x000)
91 #define HDMITX_TOP_CLK_CNTL                             (TOP_OFFSET_MASK + 0x001)
92 #define HDMITX_TOP_HPD_FILTER                           (TOP_OFFSET_MASK + 0x002)
93 #define HDMITX_TOP_INTR_MASKN                           (TOP_OFFSET_MASK + 0x003)
94 #define HDMITX_TOP_INTR_STAT                            (TOP_OFFSET_MASK + 0x004)
95 #define HDMITX_TOP_INTR_STAT_CLR                        (TOP_OFFSET_MASK + 0x005)
96 #define HDMITX_TOP_BIST_CNTL                            (TOP_OFFSET_MASK + 0x006)
97 #define HDMITX_TOP_SHIFT_PTTN_012                       (TOP_OFFSET_MASK + 0x007)
98 #define HDMITX_TOP_SHIFT_PTTN_345                       (TOP_OFFSET_MASK + 0x008)
99 #define HDMITX_TOP_SHIFT_PTTN_67                        (TOP_OFFSET_MASK + 0x009)
100 #define HDMITX_TOP_TMDS_CLK_PTTN_01                     (TOP_OFFSET_MASK + 0x00A)
101 #define HDMITX_TOP_TMDS_CLK_PTTN_23                     (TOP_OFFSET_MASK + 0x00B)
102 #define HDMITX_TOP_TMDS_CLK_PTTN_CNTL                   (TOP_OFFSET_MASK + 0x00C)
103 #define HDMITX_TOP_REVOCMEM_STAT                        (TOP_OFFSET_MASK + 0x00D)
104 #define HDMITX_TOP_STAT0                                (TOP_OFFSET_MASK + 0x00E)
105 #define HDMITX_TOP_SKP_CNTL_STAT                        (TOP_SEC_OFFSET_MASK + 0x010)
106 #define HDMITX_TOP_NONCE_0                              (TOP_SEC_OFFSET_MASK + 0x011)
107 #define HDMITX_TOP_NONCE_1                              (TOP_SEC_OFFSET_MASK + 0x012)
108 #define HDMITX_TOP_NONCE_2                              (TOP_SEC_OFFSET_MASK + 0x013)
109 #define HDMITX_TOP_NONCE_3                              (TOP_SEC_OFFSET_MASK + 0x014)
110 #define HDMITX_TOP_PKF_0                                (TOP_SEC_OFFSET_MASK + 0x015)
111 #define HDMITX_TOP_PKF_1                                (TOP_SEC_OFFSET_MASK + 0x016)
112 #define HDMITX_TOP_PKF_2                                (TOP_SEC_OFFSET_MASK + 0x017)
113 #define HDMITX_TOP_PKF_3                                (TOP_SEC_OFFSET_MASK + 0x018)
114 #define HDMITX_TOP_DUK_0                                (TOP_SEC_OFFSET_MASK + 0x019)
115 #define HDMITX_TOP_DUK_1                                (TOP_SEC_OFFSET_MASK + 0x01A)
116 #define HDMITX_TOP_DUK_2                                (TOP_SEC_OFFSET_MASK + 0x01B)
117 #define HDMITX_TOP_DUK_3                                (TOP_SEC_OFFSET_MASK + 0x01C)
118 #define HDMITX_TOP_INFILTER                             (TOP_OFFSET_MASK + 0x01D)
119 #define HDMITX_TOP_NSEC_SCRATCH                         (TOP_OFFSET_MASK + 0x01E)
120 #define HDMITX_TOP_SEC_SCRATCH                          (TOP_SEC_OFFSET_MASK + 0x01F)
121 #define HDMITX_TOP_DONT_TOUCH0                          (TOP_OFFSET_MASK + 0x0FE)
122 #define HDMITX_TOP_DONT_TOUCH1                          (TOP_OFFSET_MASK + 0x0FF)
123 
124 
125 
126 
127 #define PAD_PULL_UP_EN_REG1                             (0x49 << 2)
128 #define PAD_PULL_UP_REG1                                (0x3d << 2)
129 #define P_PREG_PAD_GPIO1_EN_N                           (0x0f << 2)
130 #define PERIPHS_PIN_MUX_6                               (0x32 << 2)
131 
132 struct reg_val_pair {
133     uint32_t    reg;
134     uint32_t    val;
135 };
136 
137 static const struct reg_val_pair ENC_LUT_GEN[] = {
138     {VPU_ENCP_VIDEO_EN, 0,},
139     {VPU_ENCI_VIDEO_EN, 0,},
140     {VPU_ENCP_VIDEO_MODE, 0x4040,},
141     {VPU_ENCP_VIDEO_MODE_ADV, 0x18,},
142     {VPU_VPU_VIU_VENC_MUX_CTRL, 0xA},
143     {VPU_ENCP_VIDEO_VSO_BEGIN, 16},
144     {VPU_ENCP_VIDEO_VSO_END, 32},
145     {VPU_ENCI_VIDEO_EN, 0},
146     {VPU_ENCP_VIDEO_EN, 1},
147     { 0xFFFFFFFF, 0},
148 };
149 
150 struct cea_timing {
151     bool                interlace_mode;
152     uint32_t            pfreq;
153     uint8_t             ln;
154     uint8_t             pixel_repeat;
155     uint8_t             venc_pixel_repeat;
156 
157     uint32_t            hfreq;
158     uint32_t            hactive;
159     uint32_t            htotal;
160     uint32_t            hblank;
161     uint32_t            hfront;
162     uint32_t            hsync;
163     uint32_t            hback;
164     bool                hpol;
165 
166     uint32_t            vfreq;
167     uint32_t            vactive;
168     uint32_t            vtotal;
169     uint32_t            vblank0;    // in case of interlace
170     uint32_t            vblank1;    // vblank0 + 1 for interlace
171     uint32_t            vfront;
172     uint32_t            vsync;
173     uint32_t            vback;
174     bool                vpol;
175 };
176 
177 #define VID_PLL_DIV_1      0
178 #define VID_PLL_DIV_2      1
179 #define VID_PLL_DIV_3      2
180 #define VID_PLL_DIV_3p5    3
181 #define VID_PLL_DIV_3p75   4
182 #define VID_PLL_DIV_4      5
183 #define VID_PLL_DIV_5      6
184 #define VID_PLL_DIV_6      7
185 #define VID_PLL_DIV_6p25   8
186 #define VID_PLL_DIV_7      9
187 #define VID_PLL_DIV_7p5    10
188 #define VID_PLL_DIV_12     11
189 #define VID_PLL_DIV_14     12
190 #define VID_PLL_DIV_15     13
191 #define VID_PLL_DIV_2p5    14
192 
193 enum viu_type {
194     VIU_ENCL = 0,
195     VIU_ENCI,
196     VIU_ENCP,
197     VIU_ENCT,
198 };
199 
200 struct pll_param {
201     uint32_t mode;
202     uint32_t viu_channel;
203     uint32_t viu_type;
204     uint32_t hpll_clk_out;
205     uint32_t od1;
206     uint32_t od2;
207     uint32_t od3;
208     uint32_t vid_pll_div;
209     uint32_t vid_clk_div;
210     uint32_t hdmi_tx_pixel_div;
211     uint32_t encp_div;
212     uint32_t enci_div;
213 };
214 
215 struct hdmi_param {
216     uint16_t                        vic;
217     uint8_t                         aspect_ratio;
218     uint8_t                         colorimetry;
219     uint8_t                         phy_mode;
220     struct pll_param                pll_p_24b;
221     struct cea_timing               timings;
222     bool                            is4K;
223 };
224 
225 #define HDMI_COLOR_DEPTH_24B    4
226 #define HDMI_COLOR_DEPTH_30B    5
227 #define HDMI_COLOR_DEPTH_36B    6
228 #define HDMI_COLOR_DEPTH_48B    7
229 
230 #define HDMI_COLOR_FORMAT_RGB   0
231 #define HDMI_COLOR_FORMAT_444   1
232 
233 #define HDMI_ASPECT_RATIO_NONE  0
234 #define HDMI_ASPECT_RATIO_4x3   1
235 #define HDMI_ASPECT_RATIO_16x9  2
236 
237 #define HDMI_COLORIMETRY_ITU601  1
238 #define HDMI_COLORIMETRY_ITU709  2
239 
240 /* VIC lookup */
241  #define VIC_720x480p_60Hz_4x3                  2
242  #define VIC_720x480p_60Hz_16x9                 3
243  #define VIC_1280x720p_60Hz_16x9                4
244  #define VIC_1920x1080i_60Hz_16x9               5
245  #define VIC_720x480i_60Hz_4x3                  6
246  #define VIC_720x480i_60Hz_16x9                 7
247  #define VIC_720x240p_60Hz_4x3                  8
248  #define VIC_720x240p_60Hz_16x9                 9
249  #define VIC_2880x480i_60Hz_4x3                 10
250  #define VIC_2880x480i_60Hz_16x9                11
251  #define VIC_2880x240p_60Hz_4x3                 12
252  #define VIC_2880x240p_60Hz_16x9                13
253  #define VIC_1440x480p_60Hz_4x3                 14
254  #define VIC_1440x480p_60Hz_16x9                15
255  #define VIC_1920x1080p_60Hz_16x9               16
256  #define VIC_720x576p_50Hz_4x3                  17
257  #define VIC_720x576p_50Hz_16x9                 18
258  #define VIC_1280x720p_50Hz_16x9                19
259  #define VIC_1920x1080i_50Hz_16x9               20
260  #define VIC_720x576i_50Hz_4x3                  21
261  #define VIC_720x576i_50Hz_16x9                 22
262  #define VIC_720x288p_50Hz_4x3                  23
263  #define VIC_720x288p_50Hz_16x9                 24
264  #define VIC_2880x576i_50Hz_4x3                 25
265  #define VIC_2880x576i_50Hz_16x9                26
266  #define VIC_2880x288p_50Hz_4x3                 27
267  #define VIC_2880x288p_50Hz_16x9                28
268  #define VIC_1440x576p_50Hz_4x3                 29
269  #define VIC_1440x576p_50Hz_16x9                30
270  #define VIC_1920x1080p_50Hz_16x9               31
271  #define VIC_1920x1080p_24Hz_16x9               32
272  #define VIC_1920x1080p_25Hz_16x9               33
273  #define VIC_1920x1080p_30Hz_16x9               34
274  #define VIC_2880x480p_60Hz_4x3                 35
275  #define VIC_2880x480p_60Hz_16x9                36
276  #define VIC_2880x576p_50Hz_4x3                 37
277  #define VIC_2880x576p_50Hz_16x9                38
278  #define VIC_1920x1080i_1250_50Hz_16x9          39
279  #define VIC_1920x1080i_100Hz_16x9              40
280  #define VIC_1280x720p_100Hz_16x9               41
281  #define VIC_720x576p_100Hz_4x3                 42
282  #define VIC_720x576p_100Hz_16x9                43
283  #define VIC_720x576i_100Hz_4x3                 44
284  #define VIC_720x576i_100Hz_16x9                45
285  #define VIC_1920x1080i_120Hz_16x9              46
286  #define VIC_1280x720p_120Hz_16x9               47
287  #define VIC_720x480p_120Hz_4x3                 48
288  #define VIC_720x480p_120Hz_16x9                49
289  #define VIC_720x480i_120Hz_4x3                 50
290  #define VIC_720x480i_120Hz_16x9                51
291  #define VIC_720x576p_200Hz_4x3                 52
292  #define VIC_720x576p_200Hz_16x9                53
293  #define VIC_720x576i_200Hz_4x3                 54
294  #define VIC_720x576i_200Hz_16x9                55
295  #define VIC_720x480p_240Hz_4x3                 56
296  #define VIC_720x480p_240Hz_16x9                57
297  #define VIC_720x480i_240Hz_4x3                 58
298  #define VIC_720x480i_240Hz_16x9                59
299  #define VIC_1280x720p_24Hz_16x9                60
300  #define VIC_1280x720p_25Hz_16x9                61
301  #define VIC_1280x720p_30Hz_16x9                62
302  #define VIC_1920x1080p_120Hz_16x9              63
303  #define VIC_1920x1080p_100Hz_16x9              64
304  #define VESA_OFFSET                            300
305  #define VIC_VESA_640x480p_60Hz_4x3             300
306  #define VIC_VESA_1280x800p_60Hz_16x9           301
307  #define VIC_VESA_1280x1024p_60Hz_5x4           302
308  #define VIC_VESA_1920x1200p_60Hz_8x5           303
309  #define VIC_VESA_800x600p_60Hz                 304
310  #define VIC_VESA_1024x768p_60Hz                305
311 
312 struct vim2_display;  // fwd decl
313 
314 void hdmitx_writereg(const struct vim2_display* display, uint32_t addr, uint32_t data);
315 uint32_t hdmitx_readreg(const struct vim2_display* display, uint32_t addr);
316 void init_hdmi_hardware(struct vim2_display* display);
317 void dump_regs(struct vim2_display* display);
318 void init_hdmi_interface(struct vim2_display* display, const struct hdmi_param* p);
319 void hdmi_test(struct vim2_display* display, uint32_t width);
320 zx_status_t configure_pll(struct vim2_display* display, const struct hdmi_param* p,
321     const struct pll_param* pll);
322 void hdmi_shutdown(struct vim2_display* display);
323 
324 __END_CDECLS
325