jcs's openbsd hax
openbsd

rkvop: add rk3126 support

+329 -102
+329 -102
sys/dev/fdt/rkvop.c
··· 37 37 #include <dev/ofw/ofw_clock.h> 38 38 #include <dev/ofw/ofw_gpio.h> 39 39 #include <dev/ofw/ofw_misc.h> 40 + #include <dev/ofw/ofw_power.h> 40 41 #include <dev/ofw/fdt.h> 41 42 42 43 #include <drm/drm_atomic.h> ··· 48 49 49 50 #include <dev/fdt/rkdrm.h> 50 51 52 + /* RK3399 VOP registers */ 51 53 #define VOP_REG_CFG_DONE 0x0000 52 54 #define REG_LOAD_EN (1 << 0) 53 55 #define VOP_SYS_CTRL 0x0008 ··· 105 107 #define DSP_VACT_ST(x) (((x) & 0x1fff) << 16) 106 108 #define DSP_VACT_END(x) (((x) & 0x1fff) << 0) 107 109 110 + /* RK3036/RK3126 VOP registers */ 111 + #define RK3036_SYS_CTRL 0x00 112 + #define RK3036_STANDBY_EN (1 << 30) 113 + #define RK3036_DSP_CTRL0 0x04 114 + #define RK3036_DSP_CTRL1 0x08 115 + #define RK3036_DSP_BLANK_EN (1 << 24) 116 + #define RK3036_DSP_BLACK_EN (1 << 25) 117 + #define RK3036_DSP_OUT_ZERO (1 << 31) 118 + #define RK3036_DSP_BG 0x0c 119 + #define RK3036_INT_STATUS 0x10 120 + #define RK3036_ALPHA_CTRL 0x14 121 + #define RK3036_WIN0_COLOR_KEY 0x18 122 + #define RK3036_WIN0_YRGB_MST 0x20 123 + #define RK3036_AXI_BUS_CTRL 0x2c 124 + #define RK3036_HDMI_DCLK_EN (1 << 22) 125 + #define RK3036_RGB_DCLK_EN (1 << 24) 126 + #define RK3036_LVDS_DCLK_EN (1 << 26) /* rk312x */ 127 + #define RK3036_LVDS_DCLK_INVERT (1 << 27) /* rk312x */ 128 + #define RK3036_MIPI_DCLK_EN (1 << 28) 129 + #define RK3036_HDMI_OUT_EN RK3036_HDMI_DCLK_EN 130 + #define RK3036_RGB_OUT_EN RK3036_RGB_DCLK_EN 131 + #define RK3036_MIPI_OUT_EN RK3036_MIPI_DCLK_EN 132 + #define RK3036_WIN0_VIR 0x30 133 + #define RK3036_WIN0_ACT_INFO 0x34 134 + #define RK3036_WIN0_DSP_INFO 0x38 135 + #define RK3036_WIN0_DSP_ST 0x3c 136 + #define RK3036_DSP_HTOTAL_HS_END 0x6c 137 + #define RK3036_DSP_HACT_ST_END 0x70 138 + #define RK3036_DSP_VTOTAL_VS_END 0x74 139 + #define RK3036_DSP_VACT_ST_END 0x78 140 + #define RK3036_REG_CFG_DONE 0x90 141 + 108 142 /* 109 143 * Polarity fields are in different locations depending on SoC and output type, 110 144 * but always in the same order. ··· 120 154 VOP_EP_HDMI, 121 155 VOP_EP_MIPI1, 122 156 VOP_EP_DP, 157 + VOP_EP_LVDS, 158 + VOP_EP_RGB, 123 159 VOP_NEP 160 + }; 161 + 162 + enum rkvop_type { 163 + VOP_RK3399, 164 + VOP_RK3126, 124 165 }; 125 166 126 167 struct rkvop_softc; ··· 152 193 153 194 struct rkvop_config { 154 195 char *descr; 196 + enum rkvop_type type; 155 197 u_int out_mode; 156 198 void (*init)(struct rkvop_softc *); 157 199 void (*set_polarity)(struct rkvop_softc *, ··· 167 209 168 210 void rk3399_vop_init(struct rkvop_softc *); 169 211 void rk3399_vop_set_polarity(struct rkvop_softc *, enum vop_ep_type, uint32_t); 212 + void rk3126_vop_init(struct rkvop_softc *); 213 + void rk3126_vop_set_polarity(struct rkvop_softc *, enum vop_ep_type, uint32_t); 170 214 171 215 int rkvop_ep_activate(void *, struct endpoint *, void *); 172 216 void *rkvop_ep_get_cookie(void *, struct endpoint *); 173 217 174 218 struct rkvop_config rk3399_vop_big_config = { 175 219 .descr = "RK3399 VOPB", 220 + .type = VOP_RK3399, 176 221 .out_mode = DSP_OUT_MODE_RGBaaa, 177 222 .init = rk3399_vop_init, 178 223 .set_polarity = rk3399_vop_set_polarity, ··· 180 225 181 226 struct rkvop_config rk3399_vop_lit_config = { 182 227 .descr = "RK3399 VOPL", 228 + .type = VOP_RK3399, 183 229 .out_mode = DSP_OUT_MODE_RGB888, 184 230 .init = rk3399_vop_init, 185 231 .set_polarity = rk3399_vop_set_polarity, 232 + }; 233 + 234 + struct rkvop_config rk3126_vop_config = { 235 + .descr = "RK3126 VOP", 236 + .type = VOP_RK3126, 237 + .out_mode = DSP_OUT_MODE_RGB888, 238 + .init = rk3126_vop_init, 239 + .set_polarity = rk3126_vop_set_polarity, 186 240 }; 187 241 188 242 const struct cfattach rkvop_ca = { ··· 199 253 struct fdt_attach_args *faa = aux; 200 254 201 255 return (OF_is_compatible(faa->fa_node, "rockchip,rk3399-vop-big") || 202 - OF_is_compatible(faa->fa_node, "rockchip,rk3399-vop-lit")); 256 + OF_is_compatible(faa->fa_node, "rockchip,rk3399-vop-lit") || 257 + OF_is_compatible(faa->fa_node, "rockchip,rk3126-vop")); 203 258 } 204 259 205 260 void ··· 212 267 if (faa->fa_nreg < 1) 213 268 return; 214 269 270 + power_domain_enable(faa->fa_node); 215 271 clock_set_assigned(faa->fa_node); 216 272 217 273 reset_deassert(faa->fa_node, "axi"); ··· 232 288 233 289 if (OF_is_compatible(faa->fa_node, "rockchip,rk3399-vop-big")) 234 290 sc->sc_conf = &rk3399_vop_big_config; 235 - if (OF_is_compatible(faa->fa_node, "rockchip,rk3399-vop-lit")) 291 + else if (OF_is_compatible(faa->fa_node, "rockchip,rk3399-vop-lit")) 236 292 sc->sc_conf = &rk3399_vop_lit_config; 293 + else if (OF_is_compatible(faa->fa_node, "rockchip,rk3126-vop")) 294 + sc->sc_conf = &rk3126_vop_config; 237 295 238 296 printf(": %s\n", sc->sc_conf->descr); 239 297 ··· 246 304 sc->sc_ports.dp_ep_get_cookie = rkvop_ep_get_cookie; 247 305 device_ports_register(&sc->sc_ports, EP_DRM_CRTC); 248 306 249 - paddr = HREAD4(sc, VOP_WIN0_YRGB_MST); 250 - if (paddr != 0) { 251 - uint32_t stride, height; 307 + switch (sc->sc_conf->type) { 308 + case VOP_RK3126: 309 + paddr = HREAD4(sc, RK3036_WIN0_YRGB_MST); 310 + if (paddr != 0) { 311 + uint32_t stride, height; 252 312 253 - stride = HREAD4(sc, VOP_WIN0_VIR) & 0xffff; 254 - height = (HREAD4(sc, VOP_WIN0_DSP_INFO) >> 16) + 1; 255 - rasops_claim_framebuffer(paddr, height * stride * 4, self); 313 + stride = HREAD4(sc, RK3036_WIN0_VIR) & 0xffff; 314 + height = (HREAD4(sc, RK3036_WIN0_DSP_INFO) >> 16) + 1; 315 + rasops_claim_framebuffer(paddr, height * stride * 4, 316 + self); 317 + } 318 + break; 319 + case VOP_RK3399: 320 + paddr = HREAD4(sc, VOP_WIN0_YRGB_MST); 321 + if (paddr != 0) { 322 + uint32_t stride, height; 323 + 324 + stride = HREAD4(sc, VOP_WIN0_VIR) & 0xffff; 325 + height = (HREAD4(sc, VOP_WIN0_DSP_INFO) >> 16) + 1; 326 + rasops_claim_framebuffer(paddr, height * stride * 4, 327 + self); 328 + } 329 + break; 256 330 } 257 331 } 258 332 ··· 296 370 u_int lb_mode; 297 371 uint32_t val; 298 372 299 - val = WIN0_ACT_WIDTH(act_width - 1) | 300 - WIN0_ACT_HEIGHT(act_height - 1); 301 - HWRITE4(sc, VOP_WIN0_ACT_INFO, val); 373 + switch (sc->sc_conf->type) { 374 + case VOP_RK3126: 375 + val = WIN0_ACT_WIDTH(act_width - 1) | 376 + WIN0_ACT_HEIGHT(act_height - 1); 377 + HWRITE4(sc, RK3036_WIN0_ACT_INFO, val); 302 378 303 - val = WIN0_DSP_WIDTH(drm_rect_width(dst) - 1) | 304 - WIN0_DSP_HEIGHT(drm_rect_height(dst) - 1); 305 - HWRITE4(sc, VOP_WIN0_DSP_INFO, val); 379 + val = WIN0_DSP_WIDTH(drm_rect_width(dst) - 1) | 380 + WIN0_DSP_HEIGHT(drm_rect_height(dst) - 1); 381 + HWRITE4(sc, RK3036_WIN0_DSP_INFO, val); 306 382 307 - val = WIN0_DSP_XST(dst->x1 + htotal - hsync_start) | 308 - WIN0_DSP_YST(dst->y1 + vtotal - vsync_start); 309 - HWRITE4(sc, VOP_WIN0_DSP_ST, val); 383 + val = WIN0_DSP_XST(dst->x1 + htotal - hsync_start) | 384 + WIN0_DSP_YST(dst->y1 + vtotal - vsync_start); 385 + HWRITE4(sc, RK3036_WIN0_DSP_ST, val); 310 386 311 - HWRITE4(sc, VOP_WIN0_COLOR_KEY, 0); 387 + HWRITE4(sc, RK3036_WIN0_COLOR_KEY, 0); 312 388 313 - if (act_width > 2560) 314 - lb_mode = WIN0_LB_MODE_RGB_3840X2; 315 - else if (act_width > 1920) 316 - lb_mode = WIN0_LB_MODE_RGB_2560X4; 317 - else if (act_width > 1280) 318 - lb_mode = WIN0_LB_MODE_RGB_1920X5; 319 - else 320 - lb_mode = WIN0_LB_MODE_RGB_1280X8; 389 + HWRITE4(sc, RK3036_SYS_CTRL, 390 + (1 << 0) | /* win0 enable */ 391 + (WIN0_DATA_FMT_ARGB888 << 3)); /* win0 format */ 321 392 322 - val = WIN0_LB_MODE(lb_mode) | 323 - WIN0_DATA_FMT(WIN0_DATA_FMT_ARGB888) | 324 - WIN0_EN; 325 - HWRITE4(sc, VOP_WIN0_CTRL, val); 393 + val = WIN0_VIR_STRIDE(fb->pitches[0] / 4); 394 + HWRITE4(sc, RK3036_WIN0_VIR, val); 326 395 327 - val = WIN0_VIR_STRIDE(fb->pitches[0] / 4); 328 - HWRITE4(sc, VOP_WIN0_VIR, val); 396 + /* Framebuffer start address */ 397 + paddr = (uint64_t)rkfb->obj->dmamap->dm_segs[0].ds_addr; 398 + paddr += (src->y1 >> 16) * fb->pitches[0]; 399 + paddr += (src->x1 >> 16) * fb->format->cpp[0]; 400 + KASSERT((paddr & ~0xffffffff) == 0); 401 + HWRITE4(sc, RK3036_WIN0_YRGB_MST, (uint32_t)paddr); 402 + break; 403 + case VOP_RK3399: 404 + val = WIN0_ACT_WIDTH(act_width - 1) | 405 + WIN0_ACT_HEIGHT(act_height - 1); 406 + HWRITE4(sc, VOP_WIN0_ACT_INFO, val); 329 407 330 - /* Framebuffer start address */ 331 - paddr = (uint64_t)rkfb->obj->dmamap->dm_segs[0].ds_addr; 332 - paddr += (src->y1 >> 16) * fb->pitches[0]; 333 - paddr += (src->x1 >> 16) * fb->format->cpp[0]; 334 - KASSERT((paddr & ~0xffffffff) == 0); 335 - HWRITE4(sc, VOP_WIN0_YRGB_MST, (uint32_t)paddr); 408 + val = WIN0_DSP_WIDTH(drm_rect_width(dst) - 1) | 409 + WIN0_DSP_HEIGHT(drm_rect_height(dst) - 1); 410 + HWRITE4(sc, VOP_WIN0_DSP_INFO, val); 411 + 412 + val = WIN0_DSP_XST(dst->x1 + htotal - hsync_start) | 413 + WIN0_DSP_YST(dst->y1 + vtotal - vsync_start); 414 + HWRITE4(sc, VOP_WIN0_DSP_ST, val); 415 + 416 + HWRITE4(sc, VOP_WIN0_COLOR_KEY, 0); 417 + 418 + if (act_width > 2560) 419 + lb_mode = WIN0_LB_MODE_RGB_3840X2; 420 + else if (act_width > 1920) 421 + lb_mode = WIN0_LB_MODE_RGB_2560X4; 422 + else if (act_width > 1280) 423 + lb_mode = WIN0_LB_MODE_RGB_1920X5; 424 + else 425 + lb_mode = WIN0_LB_MODE_RGB_1280X8; 426 + 427 + val = WIN0_LB_MODE(lb_mode) | 428 + WIN0_DATA_FMT(WIN0_DATA_FMT_ARGB888) | 429 + WIN0_EN; 430 + HWRITE4(sc, VOP_WIN0_CTRL, val); 431 + 432 + val = WIN0_VIR_STRIDE(fb->pitches[0] / 4); 433 + HWRITE4(sc, VOP_WIN0_VIR, val); 434 + 435 + /* Framebuffer start address */ 436 + paddr = (uint64_t)rkfb->obj->dmamap->dm_segs[0].ds_addr; 437 + paddr += (src->y1 >> 16) * fb->pitches[0]; 438 + paddr += (src->x1 >> 16) * fb->format->cpp[0]; 439 + KASSERT((paddr & ~0xffffffff) == 0); 440 + HWRITE4(sc, VOP_WIN0_YRGB_MST, (uint32_t)paddr); 441 + break; 442 + } 336 443 } 337 444 338 445 struct drm_plane_helper_funcs rkvop_plane_helper_funcs = { ··· 356 463 struct rkvop_softc *sc = rkcrtc->sc; 357 464 uint32_t val; 358 465 359 - val = HREAD4(sc, VOP_SYS_CTRL); 360 - 361 - switch (mode) { 362 - case DRM_MODE_DPMS_ON: 363 - val &= ~VOP_STANDBY_EN; 466 + switch (sc->sc_conf->type) { 467 + case VOP_RK3126: 468 + /* 469 + * Shadow register - can't use read-modify-write. 470 + * Standby ON clears everything, standby OFF restores 471 + * win0 enable which will be re-set by plane_update. 472 + */ 473 + switch (mode) { 474 + case DRM_MODE_DPMS_ON: 475 + HWRITE4(sc, RK3036_SYS_CTRL, 0); 476 + break; 477 + case DRM_MODE_DPMS_STANDBY: 478 + case DRM_MODE_DPMS_SUSPEND: 479 + case DRM_MODE_DPMS_OFF: 480 + HWRITE4(sc, RK3036_SYS_CTRL, RK3036_STANDBY_EN); 481 + break; 482 + } 483 + HWRITE4(sc, RK3036_REG_CFG_DONE, REG_LOAD_EN); 364 484 break; 365 - case DRM_MODE_DPMS_STANDBY: 366 - case DRM_MODE_DPMS_SUSPEND: 367 - case DRM_MODE_DPMS_OFF: 368 - val |= VOP_STANDBY_EN; 485 + case VOP_RK3399: 486 + val = HREAD4(sc, VOP_SYS_CTRL); 487 + switch (mode) { 488 + case DRM_MODE_DPMS_ON: 489 + val &= ~VOP_STANDBY_EN; 490 + break; 491 + case DRM_MODE_DPMS_STANDBY: 492 + case DRM_MODE_DPMS_SUSPEND: 493 + case DRM_MODE_DPMS_OFF: 494 + val |= VOP_STANDBY_EN; 495 + break; 496 + } 497 + HWRITE4(sc, VOP_SYS_CTRL, val); 498 + HWRITE4(sc, VOP_REG_CFG_DONE, REG_LOAD_EN); 369 499 break; 370 500 } 371 - 372 - HWRITE4(sc, VOP_SYS_CTRL, val); 373 - 374 - /* Commit settings */ 375 - HWRITE4(sc, VOP_REG_CFG_DONE, REG_LOAD_EN); 376 501 } 377 502 378 503 bool ··· 410 535 u_int hactive = adjusted_mode->hdisplay; 411 536 u_int hsync_len = adjusted_mode->hsync_end - adjusted_mode->hsync_start; 412 537 u_int hback_porch = adjusted_mode->htotal - adjusted_mode->hsync_end; 413 - u_int hfront_porch = adjusted_mode->hsync_start - adjusted_mode->hdisplay; 538 + u_int hfront_porch = adjusted_mode->hsync_start - 539 + adjusted_mode->hdisplay; 414 540 415 541 u_int vactive = adjusted_mode->vdisplay; 416 542 u_int vsync_len = adjusted_mode->vsync_end - adjusted_mode->vsync_start; 417 543 u_int vback_porch = adjusted_mode->vtotal - adjusted_mode->vsync_end; 418 - u_int vfront_porch = adjusted_mode->vsync_start - adjusted_mode->vdisplay; 544 + u_int vfront_porch = adjusted_mode->vsync_start - 545 + adjusted_mode->vdisplay; 419 546 420 - clock_set_frequency(sc->sc_node, "dclk_vop", adjusted_mode->clock * 1000); 547 + clock_set_frequency(sc->sc_node, "dclk_vop", 548 + adjusted_mode->clock * 1000); 421 549 422 550 pol = DSP_DCLK_POL; 423 551 if ((adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC) != 0) ··· 435 563 } 436 564 } 437 565 438 - switch (connector_type) { 439 - case DRM_MODE_CONNECTOR_HDMIA: 440 - sc->sc_conf->set_polarity(sc, VOP_EP_HDMI, pol); 441 - break; 442 - case DRM_MODE_CONNECTOR_eDP: 443 - sc->sc_conf->set_polarity(sc, VOP_EP_EDP, pol); 566 + switch (sc->sc_conf->type) { 567 + case VOP_RK3126: 568 + /* RK3126 VOP uses shadow registers so use full writes */ 569 + 570 + /* SYS_CTRL: clear standby */ 571 + HWRITE4(sc, RK3036_SYS_CTRL, 0); 572 + HWRITE4(sc, RK3036_REG_CFG_DONE, REG_LOAD_EN); 573 + delay(1000); 574 + 575 + /* 576 + * DSP_CTRL0: output mode, no polarity bits. 577 + * RK code sets DSP_CTRL0=0 for LVDS (no DCLK invert). 578 + */ 579 + HWRITE4(sc, RK3036_DSP_CTRL0, 580 + DSP_OUT_MODE(sc->sc_conf->out_mode)); 581 + 582 + /* DSP_CTRL1: clear BLANK_EN (set by default after reset) */ 583 + HWRITE4(sc, RK3036_DSP_CTRL1, 0); 584 + 585 + /* 586 + * AXI_BUS_CTRL: enable display clock for the output type. 587 + * RK code writes 0x0c000000 for LVDS (DCLK_EN+INVERT). 588 + */ 589 + switch (connector_type) { 590 + case DRM_MODE_CONNECTOR_HDMIA: 591 + HWRITE4(sc, RK3036_AXI_BUS_CTRL, RK3036_HDMI_DCLK_EN); 592 + break; 593 + case DRM_MODE_CONNECTOR_LVDS: 594 + HWRITE4(sc, RK3036_AXI_BUS_CTRL, 595 + RK3036_LVDS_DCLK_EN | RK3036_LVDS_DCLK_INVERT); 596 + break; 597 + } 598 + 599 + /* 600 + * RK3036/RK3126 timing registers have fields swapped compared 601 + * to RK3399: total/period in upper 16 bits, sync width in 602 + * lower 16 bits. 603 + */ 604 + val = DSP_HS_END(hsync_len + hback_porch + hactive + 605 + hfront_porch) | DSP_HTOTAL(hsync_len); 606 + HWRITE4(sc, RK3036_DSP_HTOTAL_HS_END, val); 607 + 608 + val = DSP_HACT_ST(hsync_len + hback_porch) | 609 + DSP_HACT_END(hsync_len + hback_porch + hactive); 610 + HWRITE4(sc, RK3036_DSP_HACT_ST_END, val); 611 + 612 + val = DSP_VS_END(vsync_len + vback_porch + vactive + 613 + vfront_porch) | DSP_VTOTAL(vsync_len); 614 + HWRITE4(sc, RK3036_DSP_VTOTAL_VS_END, val); 615 + 616 + val = DSP_VACT_ST(vsync_len + vback_porch) | 617 + DSP_VACT_END(vsync_len + vback_porch + vactive); 618 + HWRITE4(sc, RK3036_DSP_VACT_ST_END, val); 619 + 620 + HWRITE4(sc, RK3036_REG_CFG_DONE, REG_LOAD_EN); 444 621 break; 445 - } 622 + case VOP_RK3399: 623 + switch (connector_type) { 624 + case DRM_MODE_CONNECTOR_HDMIA: 625 + sc->sc_conf->set_polarity(sc, VOP_EP_HDMI, pol); 626 + break; 627 + case DRM_MODE_CONNECTOR_eDP: 628 + sc->sc_conf->set_polarity(sc, VOP_EP_EDP, pol); 629 + break; 630 + } 446 631 447 - val = HREAD4(sc, VOP_SYS_CTRL); 448 - val &= ~VOP_STANDBY_EN; 449 - val &= ~(MIPI_OUT_EN|EDP_OUT_EN|HDMI_OUT_EN|RGB_OUT_EN); 632 + val = HREAD4(sc, VOP_SYS_CTRL); 633 + val &= ~VOP_STANDBY_EN; 634 + val &= ~(MIPI_OUT_EN|EDP_OUT_EN|HDMI_OUT_EN|RGB_OUT_EN); 450 635 451 - switch (connector_type) { 452 - case DRM_MODE_CONNECTOR_HDMIA: 453 - val |= HDMI_OUT_EN; 454 - break; 455 - case DRM_MODE_CONNECTOR_eDP: 456 - val |= EDP_OUT_EN; 457 - break; 458 - } 459 - HWRITE4(sc, VOP_SYS_CTRL, val); 636 + switch (connector_type) { 637 + case DRM_MODE_CONNECTOR_HDMIA: 638 + val |= HDMI_OUT_EN; 639 + break; 640 + case DRM_MODE_CONNECTOR_eDP: 641 + val |= EDP_OUT_EN; 642 + break; 643 + } 644 + HWRITE4(sc, VOP_SYS_CTRL, val); 460 645 461 - val = HREAD4(sc, VOP_DSP_CTRL0); 462 - val &= ~DSP_OUT_MODE(DSP_OUT_MODE_MASK); 463 - val |= DSP_OUT_MODE(sc->sc_conf->out_mode); 464 - HWRITE4(sc, VOP_DSP_CTRL0, val); 646 + val = HREAD4(sc, VOP_DSP_CTRL0); 647 + val &= ~DSP_OUT_MODE(DSP_OUT_MODE_MASK); 648 + val |= DSP_OUT_MODE(sc->sc_conf->out_mode); 649 + HWRITE4(sc, VOP_DSP_CTRL0, val); 465 650 466 - val = DSP_HACT_ST_POST(hsync_len + hback_porch) | 467 - DSP_HACT_END_POST(hsync_len + hback_porch + hactive); 468 - HWRITE4(sc, VOP_POST_DSP_HACT_INFO, val); 651 + val = DSP_HACT_ST_POST(hsync_len + hback_porch) | 652 + DSP_HACT_END_POST(hsync_len + hback_porch + hactive); 653 + HWRITE4(sc, VOP_POST_DSP_HACT_INFO, val); 469 654 470 - val = DSP_HACT_ST(hsync_len + hback_porch) | 471 - DSP_HACT_END(hsync_len + hback_porch + hactive); 472 - HWRITE4(sc, VOP_DSP_HACT_ST_END, val); 655 + val = DSP_HACT_ST(hsync_len + hback_porch) | 656 + DSP_HACT_END(hsync_len + hback_porch + hactive); 657 + HWRITE4(sc, VOP_DSP_HACT_ST_END, val); 473 658 474 - val = DSP_HTOTAL(hsync_len) | 475 - DSP_HS_END(hsync_len + hback_porch + hactive + hfront_porch); 476 - HWRITE4(sc, VOP_DSP_HTOTAL_HS_END, val); 659 + val = DSP_HTOTAL(hsync_len) | 660 + DSP_HS_END(hsync_len + hback_porch + hactive + 661 + hfront_porch); 662 + HWRITE4(sc, VOP_DSP_HTOTAL_HS_END, val); 477 663 478 - val = DSP_VACT_ST_POST(vsync_len + vback_porch) | 479 - DSP_VACT_END_POST(vsync_len + vback_porch + vactive); 480 - HWRITE4(sc, VOP_POST_DSP_VACT_INFO, val); 664 + val = DSP_VACT_ST_POST(vsync_len + vback_porch) | 665 + DSP_VACT_END_POST(vsync_len + vback_porch + vactive); 666 + HWRITE4(sc, VOP_POST_DSP_VACT_INFO, val); 481 667 482 - val = DSP_VACT_ST(vsync_len + vback_porch) | 483 - DSP_VACT_END(vsync_len + vback_porch + vactive); 484 - HWRITE4(sc, VOP_DSP_VACT_ST_END, val); 668 + val = DSP_VACT_ST(vsync_len + vback_porch) | 669 + DSP_VACT_END(vsync_len + vback_porch + vactive); 670 + HWRITE4(sc, VOP_DSP_VACT_ST_END, val); 485 671 486 - val = DSP_VTOTAL(vsync_len) | 487 - DSP_VS_END(vsync_len + vback_porch + vactive + vfront_porch); 488 - HWRITE4(sc, VOP_DSP_VTOTAL_VS_END, val); 672 + val = DSP_VTOTAL(vsync_len) | 673 + DSP_VS_END(vsync_len + vback_porch + vactive + 674 + vfront_porch); 675 + HWRITE4(sc, VOP_DSP_VTOTAL_VS_END, val); 676 + break; 677 + } 489 678 } 490 679 491 680 void ··· 495 684 struct rkvop_softc *sc = rkcrtc->sc; 496 685 497 686 /* Commit settings */ 498 - HWRITE4(sc, VOP_REG_CFG_DONE, REG_LOAD_EN); 687 + switch (sc->sc_conf->type) { 688 + case VOP_RK3126: 689 + HWRITE4(sc, RK3036_REG_CFG_DONE, REG_LOAD_EN); 690 + break; 691 + case VOP_RK3399: 692 + HWRITE4(sc, VOP_REG_CFG_DONE, REG_LOAD_EN); 693 + break; 694 + } 499 695 } 500 696 501 697 struct drm_crtc_helper_funcs rkvop_crtc_helper_funcs = { ··· 522 718 struct drm_device *ddev = arg; 523 719 struct drm_plane *plane = &sc->sc_plane; 524 720 struct drm_crtc *crtc = &sc->sc_crtc.base; 525 - uint32_t formats[] = { DRM_FORMAT_ARGB8888 }; 721 + uint32_t formats[] = { DRM_FORMAT_ARGB8888, DRM_FORMAT_XRGB8888 }; 526 722 int error; 527 723 528 724 if (sc->sc_crtc.sc) ··· 540 736 if (error) 541 737 return -error; 542 738 543 - printf("%s: using CRTC %d for %s\n", sc->sc_dev.dv_xname, 544 - drm_crtc_index(&sc->sc_crtc.base), sc->sc_conf->descr); 545 - 546 739 sc->sc_crtc.sc = sc; 547 740 return 0; 548 741 } ··· 576 769 } 577 770 578 771 void 579 - rk3399_vop_set_polarity(struct rkvop_softc *sc, enum vop_ep_type ep_type, uint32_t pol) 772 + rk3399_vop_set_polarity(struct rkvop_softc *sc, enum vop_ep_type ep_type, 773 + uint32_t pol) 580 774 { 581 775 uint32_t mask, val; 582 776 ··· 607 801 val |= pol; 608 802 HWRITE4(sc, VOP_DSP_CTRL1, val); 609 803 } 804 + 805 + /* 806 + * RK3126 VOP 807 + */ 808 + void 809 + rk3126_vop_init(struct rkvop_softc *sc) 810 + { 811 + /* clear standby (shadow regs) */ 812 + HWRITE4(sc, RK3036_SYS_CTRL, 0); 813 + HWRITE4(sc, RK3036_REG_CFG_DONE, REG_LOAD_EN); 814 + } 815 + 816 + void 817 + rk3126_vop_set_polarity(struct rkvop_softc *sc, enum vop_ep_type ep_type, 818 + uint32_t pol) 819 + { 820 + uint32_t val; 821 + 822 + /* 823 + * Polarity is in DSP_CTRL0 bits 4-7 for RK3036/RK3126. 824 + * RK code does not set any polarity bits for LVDS output 825 + * (DSP_CTRL0 polarity field = 0x00), so clear all polarity bits 826 + * for LVDS. Only apply polarity for non-LVDS outputs. 827 + */ 828 + val = HREAD4(sc, RK3036_DSP_CTRL0); 829 + val &= ~(0xf << 4); 830 + if (ep_type != VOP_EP_LVDS) 831 + val |= (pol << 4); 832 + HWRITE4(sc, RK3036_DSP_CTRL0, val); 833 + 834 + /* commit register changes */ 835 + HWRITE4(sc, RK3036_REG_CFG_DONE, REG_LOAD_EN); 836 + }