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 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 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 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 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 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 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 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 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 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 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 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 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 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 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