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