1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3 * (C) Copyright 2022 Rockchip Electronics Co., Ltd
4 */
5
6 #include <clk.h>
7 #include "rk628.h"
8 #include "rk628_cru.h"
9 #include "rk628_dsi.h"
10 #include "rk628_gvi.h"
11 #include "rk628_hdmirx.h"
12 #include "rk628_hdmitx.h"
13 #include "rk628_lvds.h"
14 #include "rk628_post_process.h"
15 #include "rk628_rgb.h"
16
rk628_power_on(struct rk628 * rk628)17 static int rk628_power_on(struct rk628 *rk628)
18 {
19 if (rk628->power_supply)
20 regulator_set_enable(rk628->power_supply, 1);
21
22 if (dm_gpio_is_valid(&rk628->enable_gpio)) {
23 dm_gpio_set_value(&rk628->enable_gpio, 1);
24 mdelay(10);
25 }
26
27 if (dm_gpio_is_valid(&rk628->reset_gpio)) {
28 dm_gpio_set_value(&rk628->reset_gpio, 0);
29 mdelay(10);
30 dm_gpio_set_value(&rk628->reset_gpio, 1);
31 mdelay(10);
32 dm_gpio_set_value(&rk628->reset_gpio, 0);
33 mdelay(10);
34 }
35
36 /* selete int io function */
37 rk628_i2c_write(rk628, GRF_GPIO3AB_SEL_CON, 0x30002000);
38
39 return 0;
40 }
41
rk628_version_info(struct rk628 * rk628)42 static int rk628_version_info(struct rk628 *rk628)
43 {
44 int ret;
45 char *version;
46
47 ret = rk628_i2c_read(rk628, GRF_SOC_VERSION, &rk628->version);
48 if (ret < 0) {
49 printf("failed to access rk628 register: %d\n", ret);
50 return ret;
51 }
52
53 switch (rk628->version) {
54 case RK628D_VERSION:
55 version = "D/E";
56 break;
57 case RK628F_VERSION:
58 version = "F/H";
59 break;
60 default:
61 version = "unknown";
62 ret = -EINVAL;
63 }
64
65 printf("the IC version is: RK628-%s\n", version);
66
67 return ret;
68 }
69
rk628_display_route_info_parse(struct rk628 * rk628)70 static int rk628_display_route_info_parse(struct rk628 *rk628)
71 {
72 int ret = 0;
73 ofnode np;
74 u32 val;
75
76 if (dev_read_bool(rk628->dev, "rk628-hdmi-in") ||
77 dev_read_bool(rk628->dev, "rk628,hdmi-in")) {
78 rk628->input_mode = BIT(INPUT_MODE_HDMI);
79 } else if (dev_read_bool(rk628->dev, "rk628-rgb-in") ||
80 dev_read_bool(rk628->dev, "rk628,rgb-in")) {
81 rk628->input_mode = BIT(INPUT_MODE_RGB);
82 ret = rk628_rgbrx_parse(rk628);
83 } else if (dev_read_bool(rk628->dev, "rk628-bt1120-in") ||
84 dev_read_bool(rk628->dev, "rk628,bt1120-in")) {
85 rk628->input_mode = BIT(INPUT_MODE_BT1120);
86 ret = rk628_rgbrx_parse(rk628);
87 } else {
88 rk628->input_mode = BIT(INPUT_MODE_RGB);
89 }
90
91 if (ofnode_valid(dev_read_subnode(rk628->dev, "rk628-gvi-out")) ||
92 ofnode_valid(dev_read_subnode(rk628->dev, "rk628-gvi"))) {
93 np = dev_read_subnode(rk628->dev, "rk628-gvi-out");
94 if (!ofnode_valid(np))
95 np = dev_read_subnode(rk628->dev, "rk628-gvi");
96
97 rk628->output_mode |= BIT(OUTPUT_MODE_GVI);
98 ret = rk628_gvi_parse(rk628, np);
99 } else if (ofnode_valid(dev_read_subnode(rk628->dev, "rk628-lvds-out")) ||
100 ofnode_valid(dev_read_subnode(rk628->dev, "rk628-lvds"))) {
101 np = dev_read_subnode(rk628->dev, "rk628-lvds-out");
102 if (!ofnode_valid(np))
103 np = dev_read_subnode(rk628->dev, "rk628-lvds");
104
105 rk628->output_mode |= BIT(OUTPUT_MODE_LVDS);
106 ret = rk628_lvds_parse(rk628, np);
107 } else if (ofnode_valid(dev_read_subnode(rk628->dev, "rk628-dsi-out")) ||
108 ofnode_valid(dev_read_subnode(rk628->dev, "rk628-dsi"))) {
109 np = dev_read_subnode(rk628->dev, "rk628-dsi-out");
110 if (!ofnode_valid(np))
111 np = dev_read_subnode(rk628->dev, "rk628-dsi");
112
113 rk628->output_mode |= BIT(OUTPUT_MODE_DSI);
114 ret = rk628_dsi_parse(rk628, np);
115 } else if (dev_read_bool(rk628->dev, "rk628-csi-out") ||
116 dev_read_bool(rk628->dev, "rk628,csi-out")) {
117 rk628->output_mode |= BIT(OUTPUT_MODE_CSI);
118 }
119
120 if (dev_read_bool(rk628->dev, "rk628-hdmi-out") ||
121 dev_read_bool(rk628->dev, "rk628,hdmi-out"))
122 rk628->output_mode |= BIT(OUTPUT_MODE_HDMI);
123
124 if (dev_read_bool(rk628->dev, "rk628-rgb-out") ||
125 dev_read_bool(rk628->dev, "rk628-rgb")) {
126 np = dev_read_subnode(rk628->dev, "rk628-rgb-out");
127 if (!ofnode_valid(np))
128 np = dev_read_subnode(rk628->dev, "rk628-rgb");
129
130 rk628->output_mode |= BIT(OUTPUT_MODE_RGB);
131 ret = rk628_rgbtx_parse(rk628, np);
132 } else if (dev_read_bool(rk628->dev, "rk628-bt1120-out") ||
133 dev_read_bool(rk628->dev, "rk628-bt1120")) {
134 np = dev_read_subnode(rk628->dev, "rk628-bt1120-out");
135 if (!ofnode_valid(np))
136 np = dev_read_subnode(rk628->dev, "rk628-bt1120");
137
138 rk628->output_mode |= BIT(OUTPUT_MODE_BT1120);
139 ret = rk628_rgbtx_parse(rk628, np);
140 }
141
142 val = dev_read_u32_default(rk628->dev, "mode-sync-pol", 1);
143 rk628->sync_pol = (!val ? MODE_FLAG_NSYNC : MODE_FLAG_PSYNC);
144
145 return ret;
146 }
147
rk628_display_route_check(struct rk628 * rk628)148 static bool rk628_display_route_check(struct rk628 *rk628)
149 {
150 if (!hweight32(rk628->input_mode) || !hweight32(rk628->output_mode))
151 return false;
152
153 /*
154 * the RGB/BT1120 RX and RGB/BT1120 TX are the same shared IP
155 * and cannot be used as both input and output simultaneously.
156 */
157 if ((rk628_input_is_rgb(rk628) || rk628_input_is_bt1120(rk628)) &&
158 (rk628_output_is_rgb(rk628) || rk628_output_is_bt1120(rk628)))
159 return false;
160
161 if (rk628->version == RK628F_VERSION)
162 return true;
163
164 /* rk628d only support rgb and hdmi output simultaneously */
165 if (hweight32(rk628->output_mode) > 2)
166 return false;
167
168 if (hweight32(rk628->output_mode) == 2 &&
169 !(rk628_output_is_rgb(rk628) && rk628_output_is_hdmi(rk628)))
170 return false;
171
172 return true;
173 }
174
strlcat(char * dest,const char * src,size_t n)175 static inline size_t strlcat(char *dest, const char *src, size_t n)
176 {
177 strcat(dest, src);
178 return strlen(dest) + strlen(src);
179 }
180
rk628_current_display_route(struct rk628 * rk628,char * input_s,int input_s_len,char * output_s,int output_s_len)181 static void rk628_current_display_route(struct rk628 *rk628, char *input_s,
182 int input_s_len, char *output_s,
183 int output_s_len)
184 {
185 *input_s = '\0';
186 *output_s = '\0';
187
188 if (rk628_input_is_rgb(rk628))
189 strlcat(input_s, "RGB", input_s_len);
190 else if (rk628_input_is_bt1120(rk628))
191 strlcat(input_s, "BT1120", input_s_len);
192 else if (rk628_input_is_hdmi(rk628))
193 strlcat(input_s, "HDMI", input_s_len);
194 else
195 strlcat(input_s, "unknown", input_s_len);
196
197 if (rk628_output_is_rgb(rk628))
198 strlcat(output_s, "RGB ", output_s_len);
199
200 if (rk628_output_is_bt1120(rk628))
201 strlcat(output_s, "BT1120 ", output_s_len);
202
203 if (rk628_output_is_gvi(rk628))
204 strlcat(output_s, "GVI ", output_s_len);
205
206 if (rk628_output_is_lvds(rk628))
207 strncat(output_s, "LVDS ", output_s_len);
208
209 if (rk628_output_is_dsi(rk628))
210 strlcat(output_s, "DSI ", output_s_len);
211
212 if (rk628_output_is_csi(rk628))
213 strlcat(output_s, "CSI ", output_s_len);
214
215 if (rk628_output_is_hdmi(rk628))
216 strlcat(output_s, "HDMI ", output_s_len);
217
218 if (!strlen(output_s))
219 strlcat(output_s, "unknown", output_s_len);
220 }
221
rk628_show_current_display_route(struct rk628 * rk628)222 static void rk628_show_current_display_route(struct rk628 *rk628)
223 {
224 char input_s[10], output_s[30];
225
226 rk628_current_display_route(rk628, input_s, sizeof(input_s),
227 output_s, sizeof(output_s));
228
229 printf("rk628 input_mode: %s, output_mode: %s\n", input_s, output_s);
230 }
231
rk628_pwr_consumption_init(struct rk628 * rk628)232 static void rk628_pwr_consumption_init(struct rk628 *rk628)
233 {
234 /* set pin as int function to allow output interrupt */
235 rk628_i2c_write(rk628, GRF_GPIO3AB_SEL_CON, 0x30002000);
236
237 /*
238 * set unuse pin as GPIO input and
239 * pull down to reduce power consumption
240 */
241 rk628_i2c_write(rk628, GRF_GPIO2AB_SEL_CON, 0xffff0000);
242 rk628_i2c_write(rk628, GRF_GPIO2C_SEL_CON, 0xffff0000);
243 rk628_i2c_write(rk628, GRF_GPIO3AB_SEL_CON, 0x10b0000);
244 rk628_i2c_write(rk628, GRF_GPIO2C_P_CON, 0x3f0015);
245 rk628_i2c_write(rk628, GRF_GPIO3A_P_CON, 0xcc0044);
246
247 if (!rk628_output_is_hdmi(rk628)) {
248 u32 mask = SW_OUTPUT_MODE_MASK;
249 u32 val = SW_OUTPUT_MODE(OUTPUT_MODE_HDMI);
250
251 if (rk628->version == RK628F_VERSION) {
252 mask = SW_HDMITX_EN_MASK;
253 val = SW_HDMITX_EN(1);
254 }
255
256 /* disable clock/data channel and band gap when hdmitx not work */
257 rk628_i2c_update_bits(rk628, GRF_SYSTEM_CON0, mask, val);
258 rk628_i2c_write(rk628, HDMI_PHY_SYS_CTL, 0x17);
259 rk628_i2c_write(rk628, HDMI_PHY_CHG_PWR, 0x0);
260 rk628_i2c_update_bits(rk628, GRF_SYSTEM_CON0, mask, 0);
261 }
262 }
263
rk628_display_enable(struct rk628 * rk628)264 static void rk628_display_enable(struct rk628 *rk628)
265 {
266 if (rk628_input_is_rgb(rk628))
267 rk628_rgb_rx_enable(rk628);
268
269 /*
270 * bt1120 needs to configure the timing register, but hdmitx will modify
271 * the timing as needed, so the bt1120 enable process is moved to the
272 * configuration of post_process (function rk628_post_process_enable in
273 * rk628_post_process.c)
274 */
275
276 if (rk628_output_is_rgb(rk628))
277 rk628_rgb_tx_enable(rk628);
278
279 if (rk628_input_is_hdmi(rk628))
280 rk628_hdmirx_enable(rk628);
281
282 if (rk628_output_is_dsi(rk628)) {
283 rk628_mipi_dsi_pre_enable(rk628);
284 rk628_mipi_dsi_enable(rk628);
285 }
286
287
288 if (rk628_output_is_bt1120(rk628))
289 rk628_bt1120_tx_enable(rk628);
290
291 if (!rk628_output_is_hdmi(rk628)) {
292 rk628_post_process_init(rk628);
293 rk628_post_process_enable(rk628);
294 }
295
296 if (rk628_output_is_lvds(rk628))
297 rk628_lvds_enable(rk628);
298
299 if (rk628_output_is_gvi(rk628))
300 rk628_gvi_enable(rk628);
301 }
302
303 static void
of_parse_rk628_display_timing(ofnode np,struct rk628_videomode * vm)304 of_parse_rk628_display_timing( ofnode np, struct rk628_videomode *vm)
305 {
306 u32 val = 0;
307
308 ofnode_read_u32(np, "clock-frequency", &vm->pixelclock);
309 ofnode_read_u32(np, "hactive", &vm->hactive);
310 ofnode_read_u32(np, "hfront-porch", &vm->hfront_porch);
311 ofnode_read_u32(np, "hback-porch", &vm->hback_porch);
312 ofnode_read_u32(np, "hsync-len", &vm->hsync_len);
313
314 ofnode_read_u32(np, "vactive", &vm->vactive);
315 ofnode_read_u32(np, "vfront-porch", &vm->vfront_porch);
316 ofnode_read_u32(np, "vback-porch", &vm->vback_porch);
317 ofnode_read_u32(np, "vsync-len", &vm->vsync_len);
318
319 vm->flags = 0;
320 ofnode_read_u32(np, "hsync-active", &val);
321 vm->flags |= val ? DRM_MODE_FLAG_PHSYNC : DRM_MODE_FLAG_NHSYNC;
322
323 ofnode_read_u32(np, "vsync-active", &val);
324 vm->flags |= val ? DRM_MODE_FLAG_PVSYNC : DRM_MODE_FLAG_NVSYNC;
325 }
326
327 static void
rk628_display_mode_from_videomode(const struct rk628_videomode * vm,struct drm_display_mode * dmode)328 rk628_display_mode_from_videomode(const struct rk628_videomode *vm,
329 struct drm_display_mode *dmode)
330 {
331 dmode->hdisplay = vm->hactive;
332 dmode->hsync_start = dmode->hdisplay + vm->hfront_porch;
333 dmode->hsync_end = dmode->hsync_start + vm->hsync_len;
334 dmode->htotal = dmode->hsync_end + vm->hback_porch;
335
336 dmode->vdisplay = vm->vactive;
337 dmode->vsync_start = dmode->vdisplay + vm->vfront_porch;
338 dmode->vsync_end = dmode->vsync_start + vm->vsync_len;
339 dmode->vtotal = dmode->vsync_end + vm->vback_porch;
340
341 dmode->clock = vm->pixelclock / 1000;
342 dmode->flags = vm->flags;
343 }
344
rk628_get_video_mode(struct rk628 * rk628)345 static int rk628_get_video_mode(struct rk628 *rk628)
346 {
347 ofnode timings_np, src_np, dst_np;
348 struct rk628_videomode vm;
349
350 timings_np = ofnode_find_subnode(dev_ofnode(rk628->dev), "display-timings");
351 if (!ofnode_valid(timings_np))
352 return -EINVAL;
353
354 src_np = ofnode_find_subnode(timings_np, "src-timing");
355 if (!ofnode_valid(src_np)) {
356 printf("rk628 failed to found src timing\n");
357 return -EINVAL;
358 }
359
360 of_parse_rk628_display_timing(src_np, &vm);
361 rk628_display_mode_from_videomode(&vm, &rk628->src_mode);
362 printf("rk628 src mode: %d %d %d %d %d %d %d %d %d 0x%x\n",
363 rk628->src_mode.clock, rk628->src_mode.hdisplay, rk628->src_mode.hsync_start,
364 rk628->src_mode.hsync_end, rk628->src_mode.htotal, rk628->src_mode.vdisplay,
365 rk628->src_mode.vsync_start, rk628->src_mode.vsync_end, rk628->src_mode.vtotal,
366 rk628->src_mode.flags);
367
368 dst_np = ofnode_find_subnode(timings_np, "dst-timing");
369 if (!ofnode_valid(dst_np)) {
370 printf("rk628 failed to found dst timing\n");
371 return -EINVAL;
372 }
373
374 of_parse_rk628_display_timing(dst_np, &vm);
375 rk628_display_mode_from_videomode(&vm, &rk628->dst_mode);
376 printf("rk628 dst mode: %d %d %d %d %d %d %d %d %d 0x%x\n",
377 rk628->dst_mode.clock, rk628->dst_mode.hdisplay, rk628->dst_mode.hsync_start,
378 rk628->dst_mode.hsync_end, rk628->dst_mode.htotal, rk628->dst_mode.vdisplay,
379 rk628->dst_mode.vsync_start, rk628->dst_mode.vsync_end, rk628->dst_mode.vtotal,
380 rk628->dst_mode.flags);
381
382 return 0;
383 }
384
rk628_display_timings_get(struct rk628 * rk628)385 static int rk628_display_timings_get(struct rk628 *rk628)
386 {
387 int ret;
388
389 ret = rk628_get_video_mode(rk628);
390
391 return ret;
392
393 }
394
rk628_probe(struct udevice * dev)395 static int rk628_probe(struct udevice *dev)
396 {
397 struct rk628 *rk628 = dev_get_priv(dev);
398 int ret;
399
400 ret = i2c_set_chip_offset_len(dev, 4);
401 if (ret)
402 return ret;
403
404 rk628->dev = dev;
405
406 ret = rk628_display_route_info_parse(rk628);
407 if (ret) {
408 printf("display route parse err\n");
409 return ret;
410 }
411
412 if (!rk628_output_is_csi(rk628) && !rk628_output_is_hdmi(rk628)) {
413 ret = rk628_display_timings_get(rk628);
414 if (ret) {
415 printf("rk628 display timings err\n");
416 return ret;
417 }
418 }
419
420 ret = uclass_get_device_by_phandle(UCLASS_REGULATOR, dev,
421 "power-supply",
422 &rk628->power_supply);
423 if (ret && ret != -ENOENT) {
424 dev_err(dev, "Cannot get power supply: %d\n", ret);
425 return ret;
426 }
427
428 ret = gpio_request_by_name(dev, "enable-gpios", 0,
429 &rk628->enable_gpio, GPIOD_IS_OUT);
430 if (ret && ret != -ENOENT) {
431 dev_err(dev, "%s: failed to get enable GPIO: %d\n", __func__, ret);
432 return ret;
433 }
434
435 ret = gpio_request_by_name(dev, "reset-gpios", 0,
436 &rk628->reset_gpio, GPIOD_IS_OUT);
437 if (ret && ret != -ENOENT) {
438 dev_err(dev, "%s: failed to get reset GPIO: %d\n", __func__, ret);
439 return ret;
440 }
441
442 /*
443 * Process 'assigned-{clocks/clock-parents/clock-rates}'
444 * properties for ref clock from soc
445 */
446 ret = clk_set_defaults(dev);
447 if (ret)
448 dev_err(dev, "%s clk_set_defaults failed %d\n", __func__, ret);
449
450 rk628_power_on(rk628);
451 rk628_version_info(rk628);
452
453 rk628_show_current_display_route(rk628);
454
455 if (!rk628_display_route_check(rk628)) {
456 printf("rk628 display route check err\n");
457 return -EINVAL;
458 }
459
460 rk628_pwr_consumption_init(rk628);
461 rk628_cru_init(rk628);
462 rk628_display_enable(rk628);
463
464 return 0;
465 }
466
467 static const struct udevice_id rk628_of_match[] = {
468 { .compatible = "rockchip,rk628" },
469 {}
470 };
471
472 U_BOOT_DRIVER(rk628) = {
473 .name = "rk628",
474 .id = UCLASS_I2C_GENERIC,
475 .of_match = rk628_of_match,
476 .bind = dm_scan_fdt_dev,
477 .probe = rk628_probe,
478 .priv_auto_alloc_size = sizeof(struct rk628),
479 };
480