diff options
| author | Dave Airlie <airlied@redhat.com> | 2015-09-03 23:08:40 -0400 |
|---|---|---|
| committer | Dave Airlie <airlied@redhat.com> | 2015-09-03 23:08:40 -0400 |
| commit | aed160eac581258f5f280b6e4b3f49b106973a78 (patch) | |
| tree | 03c21c3be98fe9c3e20961a6544f3da8b8b9018d | |
| parent | 41e8a0a3046530911bf2f2fc28c971bf588858b8 (diff) | |
| parent | 4c156c21c7948a0be854cbe5914af3181303e529 (diff) | |
Merge branch 'drm-rockchip-2015-08-26' of https://github.com/markyzq/kernel-drm-rockchip into drm-next
Here are some fixes and some new features for rockchip drm,
tested on popmetal rk3288 board, can you land them?
* 'drm-rockchip-2015-08-26' of https://github.com/markyzq/kernel-drm-rockchip:
drm/rockchip: vop: support plane scale
drm/rockchip: vop: restore vop registers when resume
drm/rockchip: vop: Default enable win2/3 area0 bit
drm/rockchip: vop: Add yuv plane support
drm/rockchip: vop: Fix window dest start point
drm/rockchip: vop: Fix virtual stride calculation
| -rw-r--r-- | drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 269 | ||||
| -rw-r--r-- | drivers/gpu/drm/rockchip/rockchip_drm_vop.h | 88 |
2 files changed, 348 insertions, 9 deletions
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c index 34b78e736532..5d8ae5e49c44 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c | |||
| @@ -50,6 +50,8 @@ | |||
| 50 | 50 | ||
| 51 | #define VOP_WIN_SET(x, win, name, v) \ | 51 | #define VOP_WIN_SET(x, win, name, v) \ |
| 52 | REG_SET(x, win->base, win->phy->name, v, RELAXED) | 52 | REG_SET(x, win->base, win->phy->name, v, RELAXED) |
| 53 | #define VOP_SCL_SET(x, win, name, v) \ | ||
| 54 | REG_SET(x, win->base, win->phy->scl->name, v, RELAXED) | ||
| 53 | #define VOP_CTRL_SET(x, name, v) \ | 55 | #define VOP_CTRL_SET(x, name, v) \ |
| 54 | REG_SET(x, 0, (x)->data->ctrl->name, v, NORMAL) | 56 | REG_SET(x, 0, (x)->data->ctrl->name, v, NORMAL) |
| 55 | 57 | ||
| @@ -164,7 +166,37 @@ struct vop_ctrl { | |||
| 164 | struct vop_reg vpost_st_end; | 166 | struct vop_reg vpost_st_end; |
| 165 | }; | 167 | }; |
| 166 | 168 | ||
| 169 | struct vop_scl_regs { | ||
| 170 | struct vop_reg cbcr_vsd_mode; | ||
| 171 | struct vop_reg cbcr_vsu_mode; | ||
| 172 | struct vop_reg cbcr_hsd_mode; | ||
| 173 | struct vop_reg cbcr_ver_scl_mode; | ||
| 174 | struct vop_reg cbcr_hor_scl_mode; | ||
| 175 | struct vop_reg yrgb_vsd_mode; | ||
| 176 | struct vop_reg yrgb_vsu_mode; | ||
| 177 | struct vop_reg yrgb_hsd_mode; | ||
| 178 | struct vop_reg yrgb_ver_scl_mode; | ||
| 179 | struct vop_reg yrgb_hor_scl_mode; | ||
| 180 | struct vop_reg line_load_mode; | ||
| 181 | struct vop_reg cbcr_axi_gather_num; | ||
| 182 | struct vop_reg yrgb_axi_gather_num; | ||
| 183 | struct vop_reg vsd_cbcr_gt2; | ||
| 184 | struct vop_reg vsd_cbcr_gt4; | ||
| 185 | struct vop_reg vsd_yrgb_gt2; | ||
| 186 | struct vop_reg vsd_yrgb_gt4; | ||
| 187 | struct vop_reg bic_coe_sel; | ||
| 188 | struct vop_reg cbcr_axi_gather_en; | ||
| 189 | struct vop_reg yrgb_axi_gather_en; | ||
| 190 | |||
| 191 | struct vop_reg lb_mode; | ||
| 192 | struct vop_reg scale_yrgb_x; | ||
| 193 | struct vop_reg scale_yrgb_y; | ||
| 194 | struct vop_reg scale_cbcr_x; | ||
| 195 | struct vop_reg scale_cbcr_y; | ||
| 196 | }; | ||
| 197 | |||
| 167 | struct vop_win_phy { | 198 | struct vop_win_phy { |
| 199 | const struct vop_scl_regs *scl; | ||
| 168 | const uint32_t *data_formats; | 200 | const uint32_t *data_formats; |
| 169 | uint32_t nformats; | 201 | uint32_t nformats; |
| 170 | 202 | ||
| @@ -222,7 +254,36 @@ static const uint32_t formats_234[] = { | |||
| 222 | DRM_FORMAT_BGR565, | 254 | DRM_FORMAT_BGR565, |
| 223 | }; | 255 | }; |
| 224 | 256 | ||
| 257 | static const struct vop_scl_regs win_full_scl = { | ||
| 258 | .cbcr_vsd_mode = VOP_REG(WIN0_CTRL1, 0x1, 31), | ||
| 259 | .cbcr_vsu_mode = VOP_REG(WIN0_CTRL1, 0x1, 30), | ||
| 260 | .cbcr_hsd_mode = VOP_REG(WIN0_CTRL1, 0x3, 28), | ||
| 261 | .cbcr_ver_scl_mode = VOP_REG(WIN0_CTRL1, 0x3, 26), | ||
| 262 | .cbcr_hor_scl_mode = VOP_REG(WIN0_CTRL1, 0x3, 24), | ||
| 263 | .yrgb_vsd_mode = VOP_REG(WIN0_CTRL1, 0x1, 23), | ||
| 264 | .yrgb_vsu_mode = VOP_REG(WIN0_CTRL1, 0x1, 22), | ||
| 265 | .yrgb_hsd_mode = VOP_REG(WIN0_CTRL1, 0x3, 20), | ||
| 266 | .yrgb_ver_scl_mode = VOP_REG(WIN0_CTRL1, 0x3, 18), | ||
| 267 | .yrgb_hor_scl_mode = VOP_REG(WIN0_CTRL1, 0x3, 16), | ||
| 268 | .line_load_mode = VOP_REG(WIN0_CTRL1, 0x1, 15), | ||
| 269 | .cbcr_axi_gather_num = VOP_REG(WIN0_CTRL1, 0x7, 12), | ||
| 270 | .yrgb_axi_gather_num = VOP_REG(WIN0_CTRL1, 0xf, 8), | ||
| 271 | .vsd_cbcr_gt2 = VOP_REG(WIN0_CTRL1, 0x1, 7), | ||
| 272 | .vsd_cbcr_gt4 = VOP_REG(WIN0_CTRL1, 0x1, 6), | ||
| 273 | .vsd_yrgb_gt2 = VOP_REG(WIN0_CTRL1, 0x1, 5), | ||
| 274 | .vsd_yrgb_gt4 = VOP_REG(WIN0_CTRL1, 0x1, 4), | ||
| 275 | .bic_coe_sel = VOP_REG(WIN0_CTRL1, 0x3, 2), | ||
| 276 | .cbcr_axi_gather_en = VOP_REG(WIN0_CTRL1, 0x1, 1), | ||
| 277 | .yrgb_axi_gather_en = VOP_REG(WIN0_CTRL1, 0x1, 0), | ||
| 278 | .lb_mode = VOP_REG(WIN0_CTRL0, 0x7, 5), | ||
| 279 | .scale_yrgb_x = VOP_REG(WIN0_SCL_FACTOR_YRGB, 0xffff, 0x0), | ||
| 280 | .scale_yrgb_y = VOP_REG(WIN0_SCL_FACTOR_YRGB, 0xffff, 16), | ||
| 281 | .scale_cbcr_x = VOP_REG(WIN0_SCL_FACTOR_CBR, 0xffff, 0x0), | ||
| 282 | .scale_cbcr_y = VOP_REG(WIN0_SCL_FACTOR_CBR, 0xffff, 16), | ||
| 283 | }; | ||
| 284 | |||
| 225 | static const struct vop_win_phy win01_data = { | 285 | static const struct vop_win_phy win01_data = { |
| 286 | .scl = &win_full_scl, | ||
| 226 | .data_formats = formats_01, | 287 | .data_formats = formats_01, |
| 227 | .nformats = ARRAY_SIZE(formats_01), | 288 | .nformats = ARRAY_SIZE(formats_01), |
| 228 | .enable = VOP_REG(WIN0_CTRL0, 0x1, 0), | 289 | .enable = VOP_REG(WIN0_CTRL0, 0x1, 0), |
| @@ -279,6 +340,12 @@ static const struct vop_reg_data vop_init_reg_table[] = { | |||
| 279 | {DSP_CTRL0, 0x00000000}, | 340 | {DSP_CTRL0, 0x00000000}, |
| 280 | {WIN0_CTRL0, 0x00000080}, | 341 | {WIN0_CTRL0, 0x00000080}, |
| 281 | {WIN1_CTRL0, 0x00000080}, | 342 | {WIN1_CTRL0, 0x00000080}, |
| 343 | /* TODO: Win2/3 support multiple area function, but we haven't found | ||
| 344 | * a suitable way to use it yet, so let's just use them as other windows | ||
| 345 | * with only area 0 enabled. | ||
| 346 | */ | ||
| 347 | {WIN2_CTRL0, 0x00000010}, | ||
| 348 | {WIN3_CTRL0, 0x00000010}, | ||
| 282 | }; | 349 | }; |
| 283 | 350 | ||
| 284 | /* | 351 | /* |
| @@ -393,6 +460,18 @@ static enum vop_data_format vop_convert_format(uint32_t format) | |||
| 393 | } | 460 | } |
| 394 | } | 461 | } |
| 395 | 462 | ||
| 463 | static bool is_yuv_support(uint32_t format) | ||
| 464 | { | ||
| 465 | switch (format) { | ||
| 466 | case DRM_FORMAT_NV12: | ||
| 467 | case DRM_FORMAT_NV16: | ||
| 468 | case DRM_FORMAT_NV24: | ||
| 469 | return true; | ||
| 470 | default: | ||
| 471 | return false; | ||
| 472 | } | ||
| 473 | } | ||
| 474 | |||
| 396 | static bool is_alpha_support(uint32_t format) | 475 | static bool is_alpha_support(uint32_t format) |
| 397 | { | 476 | { |
| 398 | switch (format) { | 477 | switch (format) { |
| @@ -404,6 +483,126 @@ static bool is_alpha_support(uint32_t format) | |||
| 404 | } | 483 | } |
| 405 | } | 484 | } |
| 406 | 485 | ||
| 486 | static uint16_t scl_vop_cal_scale(enum scale_mode mode, uint32_t src, | ||
| 487 | uint32_t dst, bool is_horizontal, | ||
| 488 | int vsu_mode, int *vskiplines) | ||
| 489 | { | ||
| 490 | uint16_t val = 1 << SCL_FT_DEFAULT_FIXPOINT_SHIFT; | ||
| 491 | |||
| 492 | if (is_horizontal) { | ||
| 493 | if (mode == SCALE_UP) | ||
| 494 | val = GET_SCL_FT_BIC(src, dst); | ||
| 495 | else if (mode == SCALE_DOWN) | ||
| 496 | val = GET_SCL_FT_BILI_DN(src, dst); | ||
| 497 | } else { | ||
| 498 | if (mode == SCALE_UP) { | ||
| 499 | if (vsu_mode == SCALE_UP_BIL) | ||
| 500 | val = GET_SCL_FT_BILI_UP(src, dst); | ||
| 501 | else | ||
| 502 | val = GET_SCL_FT_BIC(src, dst); | ||
| 503 | } else if (mode == SCALE_DOWN) { | ||
| 504 | if (vskiplines) { | ||
| 505 | *vskiplines = scl_get_vskiplines(src, dst); | ||
| 506 | val = scl_get_bili_dn_vskip(src, dst, | ||
| 507 | *vskiplines); | ||
| 508 | } else { | ||
| 509 | val = GET_SCL_FT_BILI_DN(src, dst); | ||
| 510 | } | ||
| 511 | } | ||
| 512 | } | ||
| 513 | |||
| 514 | return val; | ||
| 515 | } | ||
| 516 | |||
| 517 | static void scl_vop_cal_scl_fac(struct vop *vop, const struct vop_win_data *win, | ||
| 518 | uint32_t src_w, uint32_t src_h, uint32_t dst_w, | ||
| 519 | uint32_t dst_h, uint32_t pixel_format) | ||
| 520 | { | ||
| 521 | uint16_t yrgb_hor_scl_mode, yrgb_ver_scl_mode; | ||
| 522 | uint16_t cbcr_hor_scl_mode = SCALE_NONE; | ||
| 523 | uint16_t cbcr_ver_scl_mode = SCALE_NONE; | ||
| 524 | int hsub = drm_format_horz_chroma_subsampling(pixel_format); | ||
| 525 | int vsub = drm_format_vert_chroma_subsampling(pixel_format); | ||
| 526 | bool is_yuv = is_yuv_support(pixel_format); | ||
| 527 | uint16_t cbcr_src_w = src_w / hsub; | ||
| 528 | uint16_t cbcr_src_h = src_h / vsub; | ||
| 529 | uint16_t vsu_mode; | ||
| 530 | uint16_t lb_mode; | ||
| 531 | uint32_t val; | ||
| 532 | int vskiplines; | ||
| 533 | |||
| 534 | if (dst_w > 3840) { | ||
| 535 | DRM_ERROR("Maximum destination width (3840) exceeded\n"); | ||
| 536 | return; | ||
| 537 | } | ||
| 538 | |||
| 539 | yrgb_hor_scl_mode = scl_get_scl_mode(src_w, dst_w); | ||
| 540 | yrgb_ver_scl_mode = scl_get_scl_mode(src_h, dst_h); | ||
| 541 | |||
| 542 | if (is_yuv) { | ||
| 543 | cbcr_hor_scl_mode = scl_get_scl_mode(cbcr_src_w, dst_w); | ||
| 544 | cbcr_ver_scl_mode = scl_get_scl_mode(cbcr_src_h, dst_h); | ||
| 545 | if (cbcr_hor_scl_mode == SCALE_DOWN) | ||
| 546 | lb_mode = scl_vop_cal_lb_mode(dst_w, true); | ||
| 547 | else | ||
| 548 | lb_mode = scl_vop_cal_lb_mode(cbcr_src_w, true); | ||
| 549 | } else { | ||
| 550 | if (yrgb_hor_scl_mode == SCALE_DOWN) | ||
| 551 | lb_mode = scl_vop_cal_lb_mode(dst_w, false); | ||
| 552 | else | ||
| 553 | lb_mode = scl_vop_cal_lb_mode(src_w, false); | ||
| 554 | } | ||
| 555 | |||
| 556 | VOP_SCL_SET(vop, win, lb_mode, lb_mode); | ||
| 557 | if (lb_mode == LB_RGB_3840X2) { | ||
| 558 | if (yrgb_ver_scl_mode != SCALE_NONE) { | ||
| 559 | DRM_ERROR("ERROR : not allow yrgb ver scale\n"); | ||
| 560 | return; | ||
| 561 | } | ||
| 562 | if (cbcr_ver_scl_mode != SCALE_NONE) { | ||
| 563 | DRM_ERROR("ERROR : not allow cbcr ver scale\n"); | ||
| 564 | return; | ||
| 565 | } | ||
| 566 | vsu_mode = SCALE_UP_BIL; | ||
| 567 | } else if (lb_mode == LB_RGB_2560X4) { | ||
| 568 | vsu_mode = SCALE_UP_BIL; | ||
| 569 | } else { | ||
| 570 | vsu_mode = SCALE_UP_BIC; | ||
| 571 | } | ||
| 572 | |||
| 573 | val = scl_vop_cal_scale(yrgb_hor_scl_mode, src_w, dst_w, | ||
| 574 | true, 0, NULL); | ||
| 575 | VOP_SCL_SET(vop, win, scale_yrgb_x, val); | ||
| 576 | val = scl_vop_cal_scale(yrgb_ver_scl_mode, src_h, dst_h, | ||
| 577 | false, vsu_mode, &vskiplines); | ||
| 578 | VOP_SCL_SET(vop, win, scale_yrgb_y, val); | ||
| 579 | |||
| 580 | VOP_SCL_SET(vop, win, vsd_yrgb_gt4, vskiplines == 4); | ||
| 581 | VOP_SCL_SET(vop, win, vsd_yrgb_gt2, vskiplines == 2); | ||
| 582 | |||
| 583 | VOP_SCL_SET(vop, win, yrgb_hor_scl_mode, yrgb_hor_scl_mode); | ||
| 584 | VOP_SCL_SET(vop, win, yrgb_ver_scl_mode, yrgb_ver_scl_mode); | ||
| 585 | VOP_SCL_SET(vop, win, yrgb_hsd_mode, SCALE_DOWN_BIL); | ||
| 586 | VOP_SCL_SET(vop, win, yrgb_vsd_mode, SCALE_DOWN_BIL); | ||
| 587 | VOP_SCL_SET(vop, win, yrgb_vsu_mode, vsu_mode); | ||
| 588 | if (is_yuv) { | ||
| 589 | val = scl_vop_cal_scale(cbcr_hor_scl_mode, cbcr_src_w, | ||
| 590 | dst_w, true, 0, NULL); | ||
| 591 | VOP_SCL_SET(vop, win, scale_cbcr_x, val); | ||
| 592 | val = scl_vop_cal_scale(cbcr_ver_scl_mode, cbcr_src_h, | ||
| 593 | dst_h, false, vsu_mode, &vskiplines); | ||
| 594 | VOP_SCL_SET(vop, win, scale_cbcr_y, val); | ||
| 595 | |||
| 596 | VOP_SCL_SET(vop, win, vsd_cbcr_gt4, vskiplines == 4); | ||
| 597 | VOP_SCL_SET(vop, win, vsd_cbcr_gt2, vskiplines == 2); | ||
| 598 | VOP_SCL_SET(vop, win, cbcr_hor_scl_mode, cbcr_hor_scl_mode); | ||
| 599 | VOP_SCL_SET(vop, win, cbcr_ver_scl_mode, cbcr_ver_scl_mode); | ||
| 600 | VOP_SCL_SET(vop, win, cbcr_hsd_mode, SCALE_DOWN_BIL); | ||
| 601 | VOP_SCL_SET(vop, win, cbcr_vsd_mode, SCALE_DOWN_BIL); | ||
| 602 | VOP_SCL_SET(vop, win, cbcr_vsu_mode, vsu_mode); | ||
| 603 | } | ||
| 604 | } | ||
| 605 | |||
| 407 | static void vop_dsp_hold_valid_irq_enable(struct vop *vop) | 606 | static void vop_dsp_hold_valid_irq_enable(struct vop *vop) |
| 408 | { | 607 | { |
| 409 | unsigned long flags; | 608 | unsigned long flags; |
| @@ -478,6 +677,7 @@ static void vop_enable(struct drm_crtc *crtc) | |||
| 478 | goto err_disable_aclk; | 677 | goto err_disable_aclk; |
| 479 | } | 678 | } |
| 480 | 679 | ||
| 680 | memcpy(vop->regs, vop->regsbak, vop->len); | ||
| 481 | /* | 681 | /* |
| 482 | * At here, vop clock & iommu is enable, R/W vop regs would be safe. | 682 | * At here, vop clock & iommu is enable, R/W vop regs would be safe. |
| 483 | */ | 683 | */ |
| @@ -598,17 +798,22 @@ static int vop_update_plane_event(struct drm_plane *plane, | |||
| 598 | struct vop *vop = to_vop(crtc); | 798 | struct vop *vop = to_vop(crtc); |
| 599 | struct drm_gem_object *obj; | 799 | struct drm_gem_object *obj; |
| 600 | struct rockchip_gem_object *rk_obj; | 800 | struct rockchip_gem_object *rk_obj; |
| 801 | struct drm_gem_object *uv_obj; | ||
| 802 | struct rockchip_gem_object *rk_uv_obj; | ||
| 601 | unsigned long offset; | 803 | unsigned long offset; |
| 602 | unsigned int actual_w; | 804 | unsigned int actual_w; |
| 603 | unsigned int actual_h; | 805 | unsigned int actual_h; |
| 604 | unsigned int dsp_stx; | 806 | unsigned int dsp_stx; |
| 605 | unsigned int dsp_sty; | 807 | unsigned int dsp_sty; |
| 606 | unsigned int y_vir_stride; | 808 | unsigned int y_vir_stride; |
| 809 | unsigned int uv_vir_stride = 0; | ||
| 607 | dma_addr_t yrgb_mst; | 810 | dma_addr_t yrgb_mst; |
| 811 | dma_addr_t uv_mst = 0; | ||
| 608 | enum vop_data_format format; | 812 | enum vop_data_format format; |
| 609 | uint32_t val; | 813 | uint32_t val; |
| 610 | bool is_alpha; | 814 | bool is_alpha; |
| 611 | bool rb_swap; | 815 | bool rb_swap; |
| 816 | bool is_yuv; | ||
| 612 | bool visible; | 817 | bool visible; |
| 613 | int ret; | 818 | int ret; |
| 614 | struct drm_rect dest = { | 819 | struct drm_rect dest = { |
| @@ -629,11 +834,15 @@ static int vop_update_plane_event(struct drm_plane *plane, | |||
| 629 | .y2 = crtc->mode.vdisplay, | 834 | .y2 = crtc->mode.vdisplay, |
| 630 | }; | 835 | }; |
| 631 | bool can_position = plane->type != DRM_PLANE_TYPE_PRIMARY; | 836 | bool can_position = plane->type != DRM_PLANE_TYPE_PRIMARY; |
| 837 | int min_scale = win->phy->scl ? FRAC_16_16(1, 8) : | ||
| 838 | DRM_PLANE_HELPER_NO_SCALING; | ||
| 839 | int max_scale = win->phy->scl ? FRAC_16_16(8, 1) : | ||
| 840 | DRM_PLANE_HELPER_NO_SCALING; | ||
| 632 | 841 | ||
| 633 | ret = drm_plane_helper_check_update(plane, crtc, fb, | 842 | ret = drm_plane_helper_check_update(plane, crtc, fb, |
| 634 | &src, &dest, &clip, | 843 | &src, &dest, &clip, |
| 635 | DRM_PLANE_HELPER_NO_SCALING, | 844 | min_scale, |
| 636 | DRM_PLANE_HELPER_NO_SCALING, | 845 | max_scale, |
| 637 | can_position, false, &visible); | 846 | can_position, false, &visible); |
| 638 | if (ret) | 847 | if (ret) |
| 639 | return ret; | 848 | return ret; |
| @@ -643,6 +852,8 @@ static int vop_update_plane_event(struct drm_plane *plane, | |||
| 643 | 852 | ||
| 644 | is_alpha = is_alpha_support(fb->pixel_format); | 853 | is_alpha = is_alpha_support(fb->pixel_format); |
| 645 | rb_swap = has_rb_swapped(fb->pixel_format); | 854 | rb_swap = has_rb_swapped(fb->pixel_format); |
| 855 | is_yuv = is_yuv_support(fb->pixel_format); | ||
| 856 | |||
| 646 | format = vop_convert_format(fb->pixel_format); | 857 | format = vop_convert_format(fb->pixel_format); |
| 647 | if (format < 0) | 858 | if (format < 0) |
| 648 | return format; | 859 | return format; |
| @@ -655,19 +866,46 @@ static int vop_update_plane_event(struct drm_plane *plane, | |||
| 655 | 866 | ||
| 656 | rk_obj = to_rockchip_obj(obj); | 867 | rk_obj = to_rockchip_obj(obj); |
| 657 | 868 | ||
| 869 | if (is_yuv) { | ||
| 870 | /* | ||
| 871 | * Src.x1 can be odd when do clip, but yuv plane start point | ||
| 872 | * need align with 2 pixel. | ||
| 873 | */ | ||
| 874 | val = (src.x1 >> 16) % 2; | ||
| 875 | src.x1 += val << 16; | ||
| 876 | src.x2 += val << 16; | ||
| 877 | } | ||
| 878 | |||
| 658 | actual_w = (src.x2 - src.x1) >> 16; | 879 | actual_w = (src.x2 - src.x1) >> 16; |
| 659 | actual_h = (src.y2 - src.y1) >> 16; | 880 | actual_h = (src.y2 - src.y1) >> 16; |
| 660 | crtc_x = max(0, crtc_x); | ||
| 661 | crtc_y = max(0, crtc_y); | ||
| 662 | 881 | ||
| 663 | dsp_stx = crtc_x + crtc->mode.htotal - crtc->mode.hsync_start; | 882 | dsp_stx = dest.x1 + crtc->mode.htotal - crtc->mode.hsync_start; |
| 664 | dsp_sty = crtc_y + crtc->mode.vtotal - crtc->mode.vsync_start; | 883 | dsp_sty = dest.y1 + crtc->mode.vtotal - crtc->mode.vsync_start; |
| 665 | 884 | ||
| 666 | offset = (src.x1 >> 16) * (fb->bits_per_pixel >> 3); | 885 | offset = (src.x1 >> 16) * drm_format_plane_cpp(fb->pixel_format, 0); |
| 667 | offset += (src.y1 >> 16) * fb->pitches[0]; | 886 | offset += (src.y1 >> 16) * fb->pitches[0]; |
| 668 | yrgb_mst = rk_obj->dma_addr + offset; | ||
| 669 | 887 | ||
| 670 | y_vir_stride = fb->pitches[0] / (fb->bits_per_pixel >> 3); | 888 | yrgb_mst = rk_obj->dma_addr + offset + fb->offsets[0]; |
| 889 | y_vir_stride = fb->pitches[0] >> 2; | ||
| 890 | |||
| 891 | if (is_yuv) { | ||
| 892 | int hsub = drm_format_horz_chroma_subsampling(fb->pixel_format); | ||
| 893 | int vsub = drm_format_vert_chroma_subsampling(fb->pixel_format); | ||
| 894 | int bpp = drm_format_plane_cpp(fb->pixel_format, 1); | ||
| 895 | |||
| 896 | uv_obj = rockchip_fb_get_gem_obj(fb, 1); | ||
| 897 | if (!uv_obj) { | ||
| 898 | DRM_ERROR("fail to get uv object from framebuffer\n"); | ||
| 899 | return -EINVAL; | ||
| 900 | } | ||
| 901 | rk_uv_obj = to_rockchip_obj(uv_obj); | ||
| 902 | uv_vir_stride = fb->pitches[1] >> 2; | ||
| 903 | |||
| 904 | offset = (src.x1 >> 16) * bpp / hsub; | ||
| 905 | offset += (src.y1 >> 16) * fb->pitches[1] / vsub; | ||
| 906 | |||
| 907 | uv_mst = rk_uv_obj->dma_addr + offset + fb->offsets[1]; | ||
| 908 | } | ||
| 671 | 909 | ||
| 672 | /* | 910 | /* |
| 673 | * If this plane update changes the plane's framebuffer, (or more | 911 | * If this plane update changes the plane's framebuffer, (or more |
| @@ -704,9 +942,22 @@ static int vop_update_plane_event(struct drm_plane *plane, | |||
| 704 | VOP_WIN_SET(vop, win, format, format); | 942 | VOP_WIN_SET(vop, win, format, format); |
| 705 | VOP_WIN_SET(vop, win, yrgb_vir, y_vir_stride); | 943 | VOP_WIN_SET(vop, win, yrgb_vir, y_vir_stride); |
| 706 | VOP_WIN_SET(vop, win, yrgb_mst, yrgb_mst); | 944 | VOP_WIN_SET(vop, win, yrgb_mst, yrgb_mst); |
| 945 | if (is_yuv) { | ||
| 946 | VOP_WIN_SET(vop, win, uv_vir, uv_vir_stride); | ||
| 947 | VOP_WIN_SET(vop, win, uv_mst, uv_mst); | ||
| 948 | } | ||
| 949 | |||
| 950 | if (win->phy->scl) | ||
| 951 | scl_vop_cal_scl_fac(vop, win, actual_w, actual_h, | ||
| 952 | dest.x2 - dest.x1, dest.y2 - dest.y1, | ||
| 953 | fb->pixel_format); | ||
| 954 | |||
| 707 | val = (actual_h - 1) << 16; | 955 | val = (actual_h - 1) << 16; |
| 708 | val |= (actual_w - 1) & 0xffff; | 956 | val |= (actual_w - 1) & 0xffff; |
| 709 | VOP_WIN_SET(vop, win, act_info, val); | 957 | VOP_WIN_SET(vop, win, act_info, val); |
| 958 | |||
| 959 | val = (dest.y2 - dest.y1 - 1) << 16; | ||
| 960 | val |= (dest.x2 - dest.x1 - 1) & 0xffff; | ||
| 710 | VOP_WIN_SET(vop, win, dsp_info, val); | 961 | VOP_WIN_SET(vop, win, dsp_info, val); |
| 711 | val = (dsp_sty - 1) << 16; | 962 | val = (dsp_sty - 1) << 16; |
| 712 | val |= (dsp_stx - 1) & 0xffff; | 963 | val |= (dsp_stx - 1) & 0xffff; |
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h index 63e9b3a084c5..a2d4ddb896fa 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h | |||
| @@ -198,4 +198,92 @@ enum factor_mode { | |||
| 198 | ALPHA_SRC_GLOBAL, | 198 | ALPHA_SRC_GLOBAL, |
| 199 | }; | 199 | }; |
| 200 | 200 | ||
| 201 | enum scale_mode { | ||
| 202 | SCALE_NONE = 0x0, | ||
| 203 | SCALE_UP = 0x1, | ||
| 204 | SCALE_DOWN = 0x2 | ||
| 205 | }; | ||
| 206 | |||
| 207 | enum lb_mode { | ||
| 208 | LB_YUV_3840X5 = 0x0, | ||
| 209 | LB_YUV_2560X8 = 0x1, | ||
| 210 | LB_RGB_3840X2 = 0x2, | ||
| 211 | LB_RGB_2560X4 = 0x3, | ||
| 212 | LB_RGB_1920X5 = 0x4, | ||
| 213 | LB_RGB_1280X8 = 0x5 | ||
| 214 | }; | ||
| 215 | |||
| 216 | enum sacle_up_mode { | ||
| 217 | SCALE_UP_BIL = 0x0, | ||
| 218 | SCALE_UP_BIC = 0x1 | ||
| 219 | }; | ||
| 220 | |||
| 221 | enum scale_down_mode { | ||
| 222 | SCALE_DOWN_BIL = 0x0, | ||
| 223 | SCALE_DOWN_AVG = 0x1 | ||
| 224 | }; | ||
| 225 | |||
| 226 | #define FRAC_16_16(mult, div) (((mult) << 16) / (div)) | ||
| 227 | #define SCL_FT_DEFAULT_FIXPOINT_SHIFT 12 | ||
| 228 | #define SCL_MAX_VSKIPLINES 4 | ||
| 229 | #define MIN_SCL_FT_AFTER_VSKIP 1 | ||
| 230 | |||
| 231 | static inline uint16_t scl_cal_scale(int src, int dst, int shift) | ||
| 232 | { | ||
| 233 | return ((src * 2 - 3) << (shift - 1)) / (dst - 1); | ||
| 234 | } | ||
| 235 | |||
| 236 | #define GET_SCL_FT_BILI_DN(src, dst) scl_cal_scale(src, dst, 12) | ||
| 237 | #define GET_SCL_FT_BILI_UP(src, dst) scl_cal_scale(src, dst, 16) | ||
| 238 | #define GET_SCL_FT_BIC(src, dst) scl_cal_scale(src, dst, 16) | ||
| 239 | |||
| 240 | static inline uint16_t scl_get_bili_dn_vskip(int src_h, int dst_h, | ||
| 241 | int vskiplines) | ||
| 242 | { | ||
| 243 | int act_height; | ||
| 244 | |||
| 245 | act_height = (src_h + vskiplines - 1) / vskiplines; | ||
| 246 | |||
| 247 | return GET_SCL_FT_BILI_DN(act_height, dst_h); | ||
| 248 | } | ||
| 249 | |||
| 250 | static inline enum scale_mode scl_get_scl_mode(int src, int dst) | ||
| 251 | { | ||
| 252 | if (src < dst) | ||
| 253 | return SCALE_UP; | ||
| 254 | else if (src > dst) | ||
| 255 | return SCALE_DOWN; | ||
| 256 | |||
| 257 | return SCALE_NONE; | ||
| 258 | } | ||
| 259 | |||
| 260 | static inline int scl_get_vskiplines(uint32_t srch, uint32_t dsth) | ||
| 261 | { | ||
| 262 | uint32_t vskiplines; | ||
| 263 | |||
| 264 | for (vskiplines = SCL_MAX_VSKIPLINES; vskiplines > 1; vskiplines /= 2) | ||
| 265 | if (srch >= vskiplines * dsth * MIN_SCL_FT_AFTER_VSKIP) | ||
| 266 | break; | ||
| 267 | |||
| 268 | return vskiplines; | ||
| 269 | } | ||
| 270 | |||
| 271 | static inline int scl_vop_cal_lb_mode(int width, bool is_yuv) | ||
| 272 | { | ||
| 273 | int lb_mode; | ||
| 274 | |||
| 275 | if (width > 2560) | ||
| 276 | lb_mode = LB_RGB_3840X2; | ||
| 277 | else if (width > 1920) | ||
| 278 | lb_mode = LB_RGB_2560X4; | ||
| 279 | else if (!is_yuv) | ||
| 280 | lb_mode = LB_RGB_1920X5; | ||
| 281 | else if (width > 1280) | ||
| 282 | lb_mode = LB_YUV_3840X5; | ||
| 283 | else | ||
| 284 | lb_mode = LB_YUV_2560X8; | ||
| 285 | |||
| 286 | return lb_mode; | ||
| 287 | } | ||
| 288 | |||
| 201 | #endif /* _ROCKCHIP_DRM_VOP_H */ | 289 | #endif /* _ROCKCHIP_DRM_VOP_H */ |
