1 /*
2 * Copyright 2018, 2020 NXP
3 * All rights reserved.
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 */
7
8 #include "fsl_video_common.h"
9 #include "fsl_display.h"
10 #include "fsl_it6263.h"
11
12 /*******************************************************************************
13 * Definitions
14 ******************************************************************************/
15 #define IT6263_LVDS_ID (0x66U / 2U)
16
17 #define IT6263_HDMI_VENDER_ID 0x01ca1376U
18 #define IT6263_LVDS_VENDER_ID 0x15ca6162U
19
20 #define IT6263_I2C_WriteReg(handle, addr, reg, value) \
21 VIDEO_I2C_WriteReg(addr, kVIDEO_RegAddr8Bit, (reg), kVIDEO_RegWidth8Bit, (value), \
22 ((const it6263_resource_t *)((handle)->resource))->i2cSendFunc)
23
24 #define IT6263_I2C_ReadReg(handle, addr, reg, value) \
25 VIDEO_I2C_ReadReg(addr, kVIDEO_RegAddr8Bit, (reg), kVIDEO_RegWidth8Bit, (value), \
26 ((const it6263_resource_t *)((handle)->resource))->i2cReceiveFunc)
27
28 #define IT6263_I2C_ModifyReg(handle, addr, reg, mask, value) \
29 VIDEO_I2C_ModifyReg(addr, kVIDEO_RegAddr8Bit, (reg), kVIDEO_RegWidth8Bit, mask, (value), \
30 ((const it6263_resource_t *)((handle)->resource))->i2cReceiveFunc, \
31 ((const it6263_resource_t *)((handle)->resource))->i2cSendFunc)
32
33 #define IT6263_I2C_ReadRegs(handle, addr, reg, value, len) \
34 VIDEO_I2C_ReadReg(addr, kVIDEO_RegAddr8Bit, (reg), (video_reg_width_t)len, (value), \
35 ((const it6263_resource_t *)((handle)->resource))->i2cReceiveFunc)
36
37 #define IT6263_SET_LVDS_ID_REG 0x1DU
38 #define IT6263_ENABLE_LVDS_ID_REG 0x1EU
39
40 #define IT6263_HDMI_VENDER_ID_REG 0
41 #define IT6263_LVDS_VENDER_ID_REG 0
42
43 #define IT6263_LVDS_COLOR_DEPTH(x) ((x) << 0U)
44 #define IT6263_LVDS_COLOR_DEPTH_MASK (3U << 0U)
45 #define IT6263_LVDS_MAP(x) ((x) << 4U)
46 #define IT6263_LVDS_MAP_MASK (1U << 4U)
47 #define IT6263_LVDS_DUAL_MODE(x) ((x) << 7U)
48 #define IT6263_LVDS_DUAL_MODE_MASK (1U << 7U)
49
50 /* Color depth. */
51 #define IT6263_LVDS_COLOR_6BIT IT6263_LVDS_COLOR_DEPTH(0U)
52 #define IT6263_LVDS_COLOR_8BIT IT6263_LVDS_COLOR_DEPTH(1U)
53 #define IT6263_LVDS_COLOR_10BIT IT6263_LVDS_COLOR_DEPTH(2U)
54 #define IT6263_LVDS_COLOR_12BIT IT6263_LVDS_COLOR_DEPTH(3U)
55
56 /* Pixel map. */
57 #define IT6263_LVDS_JEIDA IT6263_LVDS_MAP(0U)
58 #define IT6263_LVDS_VESA IT6263_LVDS_MAP(1U)
59
60 /* Dual mode. */
61 #define IT6263_LVDS_DISO IT6263_LVDS_DUAL_MODE(1U) /* Dual In / Single Out */
62 #define IT6263_LVDS_DIRECT IT6263_LVDS_DUAL_MODE(0U) /* Single In / Single Out or Dual In / Dual Out */
63
64 /* HDMI register 0x04. */
65 #define HDMI_REG_SW_RST 0x04U
66 #define IT6263_HDMI_04_SOFTREFRST_MASK (1U << 5U)
67 #define IT6263_HDMI_04_SOFTARST_MASK (1U << 4U)
68 #define IT6263_HDMI_04_SOFTVRST_MASK (1U << 3U)
69 #define IT6263_HDMI_04_AUDRST_MASK (1U << 2U)
70 #define IT6263_HDMI_04_HDCPRST_MASK (1U << 0U)
71 #define IT6263_HDMI_04_ALLRST_MASK ((1U << 5U) | (1U << 4U) | (1U << 3U) | (1U << 2U) | (1U << 0U))
72
73 /* HDMI register 0x61. */
74 #define IT6263_HDMI_61_DRV_PWD_MASK (1U << 5U)
75 #define IT6263_HDMI_61_DRV_RST_MASK (1U << 4U)
76
77 /* HDMI register 0xC1. */
78 #define IT6263_HDMI_C1_AVMUTE_MASK (1U << 0U)
79
80 /* HDMI register 0xC6. */
81 #define IT6263_HDMI_C6_PKTGENCTRLRPT_MASK (1U << 1U)
82 #define IT6263_HDMI_C6_PKTGENCTRLEN_MASK (1U << 0U)
83
84 /* LVDS register 0x05. */
85 #define IT6263_LVDS_05_SOFTREFRST_MASK (1U << 0U)
86 #define IT6263_LVDS_05_SOFTRST_MASK (1U << 1U)
87
88 #define IT6263_CHECK_RET(x) \
89 do \
90 { \
91 status = (x); \
92 if (kStatus_Success != status) \
93 { \
94 return status; \
95 } \
96 } while (false)
97
98 /*******************************************************************************
99 * Variables
100 ******************************************************************************/
101 const display_operations_t it6263_ops = {
102 .init = IT6263_Init,
103 .deinit = IT6263_Deinit,
104 .start = IT6263_Start,
105 .stop = IT6263_Stop,
106 };
107
108 /*******************************************************************************
109 * Code
110 ******************************************************************************/
111
IT6263_HardwareReset(display_handle_t * handle)112 static void IT6263_HardwareReset(display_handle_t *handle)
113 {
114 const it6263_resource_t *resource = (const it6263_resource_t *)(handle->resource);
115
116 resource->pullResetPin(true);
117
118 VIDEO_DelayMs(1);
119
120 resource->pullResetPin(false);
121
122 VIDEO_DelayMs(40);
123
124 resource->pullResetPin(true);
125
126 VIDEO_DelayMs(10);
127 }
128
IT6263_LVDSReset(display_handle_t * handle)129 static status_t IT6263_LVDSReset(display_handle_t *handle)
130 {
131 status_t status;
132
133 /* Reset the AFE PLL. */
134 IT6263_CHECK_RET(IT6263_I2C_ModifyReg(handle, IT6263_LVDS_ID, 0x3C, 0x1, 0x0));
135 VIDEO_DelayMs(1);
136 IT6263_CHECK_RET(IT6263_I2C_ModifyReg(handle, IT6263_LVDS_ID, 0x3C, 0x1, 0x1));
137
138 /* Reset the PCLK. */
139 status =
140 IT6263_I2C_ModifyReg(handle, IT6263_LVDS_ID, 0x05, IT6263_LVDS_05_SOFTRST_MASK, IT6263_LVDS_05_SOFTRST_MASK);
141 if (kStatus_Success != status)
142 {
143 return status;
144 }
145
146 VIDEO_DelayMs(1);
147 IT6263_CHECK_RET(IT6263_I2C_ModifyReg(handle, IT6263_LVDS_ID, 0x05, IT6263_LVDS_05_SOFTRST_MASK, 0));
148
149 VIDEO_DelayMs(1);
150
151 return kStatus_Success;
152 }
153
IT6263_InitLVDS_ID(display_handle_t * handle)154 static status_t IT6263_InitLVDS_ID(display_handle_t *handle)
155 {
156 status_t status;
157
158 uint8_t i2cAddr = (((const it6263_resource_t *)(handle->resource))->i2cAddr) / 2U;
159
160 status = IT6263_I2C_WriteReg(handle, i2cAddr, IT6263_SET_LVDS_ID_REG, IT6263_LVDS_ID * 2U);
161
162 if (kStatus_Success == status)
163 {
164 status = IT6263_I2C_WriteReg(handle, i2cAddr, IT6263_ENABLE_LVDS_ID_REG, 1);
165 }
166
167 return status;
168 }
169
IT6263_Identify(display_handle_t * handle)170 static status_t IT6263_Identify(display_handle_t *handle)
171 {
172 status_t status;
173 uint32_t hdmiVendorID = 0U;
174 uint32_t lvdsVendorID = 0U;
175
176 uint8_t i2cAddr = (((const it6263_resource_t *)(handle->resource))->i2cAddr) / 2U;
177
178 status = IT6263_I2C_ReadRegs(handle, i2cAddr, IT6263_HDMI_VENDER_ID_REG, &hdmiVendorID, sizeof(hdmiVendorID));
179 if (kStatus_Success != status)
180 {
181 return status;
182 }
183
184 status =
185 IT6263_I2C_ReadRegs(handle, IT6263_LVDS_ID, IT6263_LVDS_VENDER_ID_REG, &lvdsVendorID, sizeof(lvdsVendorID));
186 if (kStatus_Success != status)
187 {
188 return status;
189 }
190
191 if ((hdmiVendorID != IT6263_HDMI_VENDER_ID) || (lvdsVendorID != IT6263_LVDS_VENDER_ID))
192 {
193 return kStatus_Fail;
194 }
195 else
196 {
197 return kStatus_Success;
198 }
199 }
200
IT6263_InitLVDS(display_handle_t * handle)201 static status_t IT6263_InitLVDS(display_handle_t *handle)
202 {
203 status_t status;
204 uint8_t mask;
205 uint8_t val;
206
207 /* Configure LVDS. */
208 mask = IT6263_LVDS_COLOR_DEPTH_MASK | IT6263_LVDS_MAP_MASK | IT6263_LVDS_DUAL_MODE_MASK;
209 val = IT6263_LVDS_COLOR_8BIT | IT6263_LVDS_JEIDA | IT6263_LVDS_DIRECT;
210
211 IT6263_CHECK_RET(IT6263_I2C_ModifyReg(handle, IT6263_LVDS_ID, 0x2C, mask, val));
212
213 IT6263_CHECK_RET(IT6263_I2C_ModifyReg(handle, IT6263_LVDS_ID, 0x52, 0x02, 0x00));
214
215 /* AFE */
216 IT6263_CHECK_RET(IT6263_I2C_WriteReg(handle, IT6263_LVDS_ID, 0x3E, 0xAA));
217 IT6263_CHECK_RET(IT6263_I2C_WriteReg(handle, IT6263_LVDS_ID, 0x3F, 0x02));
218 IT6263_CHECK_RET(IT6263_I2C_WriteReg(handle, IT6263_LVDS_ID, 0x47, 0xAA));
219 IT6263_CHECK_RET(IT6263_I2C_WriteReg(handle, IT6263_LVDS_ID, 0x48, 0x02));
220 IT6263_CHECK_RET(IT6263_I2C_WriteReg(handle, IT6263_LVDS_ID, 0x4F, 0x11));
221
222 IT6263_CHECK_RET(IT6263_I2C_ModifyReg(handle, IT6263_LVDS_ID, 0x3C, 0x07, 0));
223
224 return kStatus_Success;
225 }
226
IT6263_Init(display_handle_t * handle,const display_config_t * config)227 status_t IT6263_Init(display_handle_t *handle, const display_config_t *config)
228 {
229 assert(handle);
230
231 status_t status;
232
233 uint8_t i2cAddr = ((const it6263_resource_t *)(handle->resource))->i2cAddr / 2U;
234
235 IT6263_HardwareReset(handle);
236
237 /* Software reset. */
238 status = IT6263_I2C_WriteReg(handle, i2cAddr, 0x04, IT6263_HDMI_04_ALLRST_MASK);
239 if (kStatus_Success != status)
240 {
241 return status;
242 }
243
244 VIDEO_DelayMs(1);
245
246 status = IT6263_InitLVDS_ID(handle);
247 if (kStatus_Success != status)
248 {
249 return status;
250 }
251
252 status = IT6263_Identify(handle);
253 if (kStatus_Success != status)
254 {
255 return status;
256 }
257
258 IT6263_CHECK_RET(IT6263_LVDSReset(handle));
259
260 IT6263_CHECK_RET(IT6263_InitLVDS(handle));
261
262 /*
263 * Set color:
264 * 0 RGB
265 * 1 YUV422
266 * 2 YUV444
267 */
268 IT6263_CHECK_RET(IT6263_I2C_ModifyReg(handle, i2cAddr, 0x70, 0x03U << 6U, 0));
269
270 /*
271 * No color space conversion.
272 * 0: No conversion
273 * 1: RGB -> YUV
274 * 2: YUV -> RGB
275 */
276 IT6263_CHECK_RET(IT6263_I2C_ModifyReg(handle, i2cAddr, 0x72, 0x03U << 0U, 0));
277
278 /*
279 * HDMI color dpeth:
280 * 000 - color depth is not indicate (as 8bit)
281 * 100 - 8/8/8 bit color
282 * 101 - 10/10/10 bit color
283 * 110 - 12/12/12 bit color)
284 */
285 IT6263_CHECK_RET(IT6263_I2C_ModifyReg(handle, i2cAddr, 0xC1, 0x07U << 4U, 0x04U << 0U));
286
287 /* Select HDMI. */
288 IT6263_CHECK_RET(IT6263_I2C_WriteReg(handle, i2cAddr, 0xC0, 0x01));
289
290 /* Set AFE */
291 if (config->pixelClock_Hz > 80000000U)
292 {
293 IT6263_CHECK_RET(IT6263_I2C_WriteReg(handle, i2cAddr, 0x62, 0x88));
294 IT6263_CHECK_RET(IT6263_I2C_WriteReg(handle, i2cAddr, 0x64, 0x84));
295 }
296 else
297 {
298 IT6263_CHECK_RET(IT6263_I2C_WriteReg(handle, i2cAddr, 0x62, 0x18));
299 IT6263_CHECK_RET(IT6263_I2C_WriteReg(handle, i2cAddr, 0x64, 0x0C));
300 }
301 IT6263_CHECK_RET(IT6263_I2C_WriteReg(handle, i2cAddr, 0x63, 0x10));
302
303 /*
304 * Output Color Mode
305 * 00 - RGB444 mode
306 * 01 - YCbCr422 mode
307 * 10 - YCbCr444 mode
308 */
309 IT6263_CHECK_RET(IT6263_I2C_ModifyReg(handle, i2cAddr, 0x0F, 0x03U << 0U, 0x01U << 0U)); /* Bank 0 */
310 IT6263_CHECK_RET(IT6263_I2C_ModifyReg(handle, i2cAddr, 0x58, 0x03U << 5U, 0x00U << 5U));
311 IT6263_CHECK_RET(IT6263_I2C_ModifyReg(handle, i2cAddr, 0x0F, 0x03U << 0U, 0x00U << 0U)); /* Bank 1 */
312
313 /* software video reset */
314 status = IT6263_I2C_ModifyReg(handle, i2cAddr, 0x04, IT6263_HDMI_04_SOFTVRST_MASK, IT6263_HDMI_04_SOFTVRST_MASK);
315 if (kStatus_Success != status)
316 {
317 return status;
318 }
319
320 VIDEO_DelayMs(100);
321
322 return kStatus_Success;
323 }
324
IT6263_Deinit(display_handle_t * handle)325 status_t IT6263_Deinit(display_handle_t *handle)
326 {
327 const it6263_resource_t *resource = (const it6263_resource_t *)(handle->resource);
328
329 resource->pullResetPin(false);
330
331 return kStatus_Success;
332 }
333
IT6263_Start(display_handle_t * handle)334 status_t IT6263_Start(display_handle_t *handle)
335 {
336 status_t status;
337
338 uint8_t i2cAddr = ((const it6263_resource_t *)(handle->resource))->i2cAddr / 2U;
339
340 IT6263_CHECK_RET(IT6263_I2C_ModifyReg(handle, i2cAddr, 0x04, IT6263_HDMI_04_SOFTVRST_MASK, 0));
341 IT6263_CHECK_RET(IT6263_I2C_WriteReg(handle, i2cAddr, 0x61, 0));
342 IT6263_CHECK_RET(IT6263_I2C_ModifyReg(handle, i2cAddr, 0xC1, IT6263_HDMI_C1_AVMUTE_MASK, 0));
343 return IT6263_I2C_WriteReg(handle, i2cAddr, 0xc6,
344 IT6263_HDMI_C6_PKTGENCTRLRPT_MASK | IT6263_HDMI_C6_PKTGENCTRLEN_MASK);
345 }
346
IT6263_Stop(display_handle_t * handle)347 status_t IT6263_Stop(display_handle_t *handle)
348 {
349 status_t status;
350 uint8_t i2cAddr = ((const it6263_resource_t *)(handle->resource))->i2cAddr / 2U;
351
352 status = IT6263_I2C_ModifyReg(handle, i2cAddr, 0xC1, IT6263_HDMI_C1_AVMUTE_MASK, IT6263_HDMI_C1_AVMUTE_MASK);
353
354 if (kStatus_Success == status)
355 {
356 status = IT6263_I2C_WriteReg(handle, i2cAddr, 0xC6, 0);
357 }
358
359 if (kStatus_Success == status)
360 {
361 status =
362 IT6263_I2C_ModifyReg(handle, i2cAddr, 0x04, IT6263_HDMI_04_SOFTVRST_MASK, IT6263_HDMI_04_SOFTVRST_MASK);
363 }
364
365 if (kStatus_Success == status)
366 {
367 status = IT6263_I2C_WriteReg(handle, i2cAddr, 0x61, IT6263_HDMI_61_DRV_PWD_MASK | IT6263_HDMI_61_DRV_RST_MASK);
368 }
369
370 return status;
371 }
372