xref: /rk3399_rockchip-uboot/drivers/video/drm/rk628/rk628.c (revision ab3bc87339b1566ceabcfb54995e11928492c356)
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