Lines Matching +full:layer +full:- +full:alpha +full:- +full:mode

1 // SPDX-License-Identifier: (GPL-2.0+ OR MIT)
4 * Author: Andy Yan <andy.yan@rock-chips.com>
12 #include <linux/media-bus-format.h>
34 #include <dt-bindings/soc/rockchip,vop2.h>
44 +----------+ +-------------+ +-----------+
47 +----------+ +-------------+ +---------------+ +-------------+ +-----------+
48 +----------+ +-------------+ |N from 6 layers| | |
49 | Cluster | | Sel 1 from 6| | Overlay0 +--->| Video Port0 | +-----------+
51 +----------+ +-------------+ +---------------+ +-------------+ | LVDS |
52 +----------+ +-------------+ +-----------+
54 | window0 | | Layer2 | +---------------+ +-------------+ +-----------+
55 +----------+ +-------------+ |N from 6 Layers| | | +--> | 1 from 3 |
56 +----------+ +-------------+ --------> | Overlay1 +--->| Video Port1 | | MIPI |
57 | Esmart | | Sel 1 from 6| --------> | | | | +-----------+
58 | Window1 | | Layer3 | +---------------+ +-------------+
59 +----------+ +-------------+ +-----------+
60 +----------+ +-------------+ | 1 from 3 |
61 | Smart | | Sel 1 from 6| +---------------+ +-------------+ | HDMI |
62 | Window0 | | Layer4 | |N from 6 Layers| | | +-----------+
63 +----------+ +-------------+ | Overlay2 +--->| Video Port2 |
64 +----------+ +-------------+ | | | | +-----------+
65 | Smart | | Sel 1 from 6| +---------------+ +-------------+ | 1 from 3 |
67 +----------+ +-------------+ +-----------+
101 VOP2_AFBC_FMT_INVALID = -1,
254 mutex_lock(&vop2->vop2_lock); in vop2_lock()
259 mutex_unlock(&vop2->vop2_lock); in vop2_unlock()
264 regmap_write(vop2->map, offset, v); in vop2_writel()
269 regmap_write(vp->vop2->map, vp->data->offset + offset, v); in vop2_vp_write()
276 regmap_read(vop2->map, offset, &val); in vop2_readl()
283 regmap_field_write(win->reg[reg], v); in vop2_win_write()
288 return win->data->feature & WIN_FEATURE_CLUSTER; in vop2_cluster_window()
302 struct vop2 *vop2 = vp->vop2; in vop2_cfg_done()
305 val |= BIT(vp->id) | (BIT(vp->id) << 16); in vop2_cfg_done()
307 regmap_set_bits(vop2->map, RK3568_REG_CFG_DONE, val); in vop2_cfg_done()
320 switch (format->format) { in vop2_get_bpp()
377 return -EINVAL; in vop2_convert_format()
483 * From H/W testing, YUV444 mode need a rb swap. in vop2_output_uv_swap()
500 if (vop2->data->soc_id == 3588) { in vop2_output_rg_swap()
537 for (i = 0 ; i < plane->modifier_count; i++) in rockchip_afbc()
538 if (plane->modifiers[i] == modifier) in rockchip_afbc()
548 struct vop2 *vop2 = win->vop2; in rockchip_vop2_mod_supported()
557 drm_dbg_kms(vop2->drm, "Unsupported format modifier 0x%llx\n", in rockchip_vop2_mod_supported()
567 * 0: Full mode, 16 lines for one tail
568 * 1: half block mode, 8 lines one tail
572 if (pstate->rotation & (DRM_MODE_ROTATE_270 | DRM_MODE_ROTATE_90)) in vop2_half_block_enable()
581 struct drm_rect *src = &pstate->src; in vop2_afbc_transform_offset()
582 struct drm_framebuffer *fb = pstate->fb; in vop2_afbc_transform_offset()
583 u32 bpp = vop2_get_bpp(fb->format); in vop2_afbc_transform_offset()
584 u32 vir_width = (fb->pitches[0] << 3) / bpp; in vop2_afbc_transform_offset()
587 u32 act_xoffset = src->x1 >> 16; in vop2_afbc_transform_offset()
588 u32 act_yoffset = src->y1 >> 16; in vop2_afbc_transform_offset()
597 align16_crop = 16 - (height & 0xf); in vop2_afbc_transform_offset()
603 align64_crop = 64 - (height_tmp & 0x3f); in vop2_afbc_transform_offset()
607 switch (pstate->rotation & in vop2_afbc_transform_offset()
611 tx = 16 - ((act_xoffset + width) & 0xf); in vop2_afbc_transform_offset()
612 ty = bottom_crop_line_num - act_yoffset; in vop2_afbc_transform_offset()
615 tx = bottom_crop_line_num - act_yoffset; in vop2_afbc_transform_offset()
616 ty = vir_width - width - act_xoffset; in vop2_afbc_transform_offset()
623 tx = 16 - ((act_xoffset + width) & 0xf); in vop2_afbc_transform_offset()
628 ty = bottom_crop_line_num - act_yoffset; in vop2_afbc_transform_offset()
631 tx = bottom_crop_line_num - act_yoffset; in vop2_afbc_transform_offset()
636 ty = vir_width - width - act_xoffset; in vop2_afbc_transform_offset()
655 * works at 2048 x 16(Full) or 4096 x 8 (Half) mode.
657 * 0: half mode, for plane input width range 2048 ~ 4096
658 * 1: half mode, for cluster work at 2 * 2048 plane mode
659 * 2: half mode, for rotate_90/270 mode
665 if ((pstate->rotation & DRM_MODE_ROTATE_270) || in vop2_get_cluster_lb_mode()
666 (pstate->rotation & DRM_MODE_ROTATE_90)) in vop2_get_cluster_lb_mode()
691 src--; in vop2_scale_factor()
692 dst--; in vop2_scale_factor()
694 fac = DIV_ROUND_UP(src << shift, dst) - 1; in vop2_scale_factor()
738 * at scale down mode in vop2_setup_scale()
740 if (!(win->data->feature & WIN_FEATURE_AFBDC)) { in vop2_setup_scale()
742 drm_dbg(vop2->drm, "%s dst_w[%d] should align as 2 pixel\n", in vop2_setup_scale()
743 win->data->name, dst_w); in vop2_setup_scale()
765 if (info->is_yuv) { in vop2_setup_scale()
766 src_w /= info->hsub; in vop2_setup_scale()
767 src_h /= info->vsub; in vop2_setup_scale()
821 * 1. YUV(2020) --> Y2R->2020To709->R2Y --> YUV_OUTPUT(601/709)
822 * RGB --> R2Y __/
824 * 2. YUV(2020) --> bypasss --> YUV_OUTPUT(2020)
825 * RGB --> 709To2020->R2Y __/
827 * 3. YUV(2020) --> Y2R->2020To709 --> RGB_OUTPUT(709)
828 * RGB --> R2Y __/
830 * 4. YUV(601/709)-> Y2R->709To2020->R2Y --> YUV_OUTPUT(2020)
831 * RGB --> 709To2020->R2Y __/
833 * 5. YUV(601/709)-> bypass --> YUV_OUTPUT(709)
834 * RGB --> R2Y __/
836 * 6. YUV(601/709)-> bypass --> YUV_OUTPUT(601)
837 * RGB --> R2Y(601) __/
839 * 7. YUV --> Y2R(709) --> RGB_OUTPUT(709)
840 * RGB --> bypass __/
842 * 8. RGB --> 709To2020->R2Y --> YUV_OUTPUT(2020)
844 * 9. RGB --> R2Y(709) --> YUV_OUTPUT(709)
846 * 10. RGB --> R2Y(601) --> YUV_OUTPUT(601)
848 * 11. RGB --> bypass --> RGB_OUTPUT(709)
855 struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(vp->crtc.state); in vop2_setup_csc_mode()
856 int is_input_yuv = pstate->fb->format->is_yuv; in vop2_setup_csc_mode()
857 int is_output_yuv = is_yuv_output(vcstate->bus_format); in vop2_setup_csc_mode()
859 int output_csc = vcstate->color_space; in vop2_setup_csc_mode()
884 struct vop2 *vop2 = vp->vop2; in vop2_crtc_enable_irq()
886 vop2_writel(vop2, RK3568_VP_INT_CLR(vp->id), irq << 16 | irq); in vop2_crtc_enable_irq()
887 vop2_writel(vop2, RK3568_VP_INT_EN(vp->id), irq << 16 | irq); in vop2_crtc_enable_irq()
892 struct vop2 *vop2 = vp->vop2; in vop2_crtc_disable_irq()
894 vop2_writel(vop2, RK3568_VP_INT_EN(vp->id), irq << 16); in vop2_crtc_disable_irq()
901 ret = clk_prepare_enable(vop2->hclk); in vop2_core_clks_prepare_enable()
903 drm_err(vop2->drm, "failed to enable hclk - %d\n", ret); in vop2_core_clks_prepare_enable()
907 ret = clk_prepare_enable(vop2->aclk); in vop2_core_clks_prepare_enable()
909 drm_err(vop2->drm, "failed to enable aclk - %d\n", ret); in vop2_core_clks_prepare_enable()
913 ret = clk_prepare_enable(vop2->pclk); in vop2_core_clks_prepare_enable()
915 drm_err(vop2->drm, "failed to enable pclk - %d\n", ret); in vop2_core_clks_prepare_enable()
921 clk_disable_unprepare(vop2->aclk); in vop2_core_clks_prepare_enable()
923 clk_disable_unprepare(vop2->hclk); in vop2_core_clks_prepare_enable()
943 ret = pm_runtime_resume_and_get(vop2->dev); in vop2_enable()
945 drm_err(vop2->drm, "failed to get pm runtime: %d\n", ret); in vop2_enable()
951 pm_runtime_put_sync(vop2->dev); in vop2_enable()
955 ret = rockchip_drm_dma_attach_device(vop2->drm, vop2->dev); in vop2_enable()
957 drm_err(vop2->drm, "failed to attach dma mapping, %d\n", ret); in vop2_enable()
961 if (vop2->data->soc_id == 3566) in vop2_enable()
964 if (vop2->data->soc_id == 3588) in vop2_enable()
973 regmap_clear_bits(vop2->map, RK3568_SYS_AUTO_GATING_CTRL, in vop2_enable()
988 rockchip_drm_dma_detach_device(vop2->drm, vop2->dev); in vop2_disable()
990 pm_runtime_put_sync(vop2->dev); in vop2_disable()
992 regcache_drop_region(vop2->map, 0, vop2_regmap_config.max_register); in vop2_disable()
994 clk_disable_unprepare(vop2->pclk); in vop2_disable()
995 clk_disable_unprepare(vop2->aclk); in vop2_disable()
996 clk_disable_unprepare(vop2->hclk); in vop2_disable()
1003 struct vop2 *vop2 = vp->vop2; in vop2_crtc_atomic_disable()
1021 reinit_completion(&vp->dsp_hold_completion); in vop2_crtc_atomic_disable()
1027 ret = wait_for_completion_timeout(&vp->dsp_hold_completion, in vop2_crtc_atomic_disable()
1030 drm_info(vop2->drm, "wait for vp%d dsp_hold timeout\n", vp->id); in vop2_crtc_atomic_disable()
1034 clk_disable_unprepare(vp->dclk); in vop2_crtc_atomic_disable()
1036 vop2->enable_count--; in vop2_crtc_atomic_disable()
1038 if (!vop2->enable_count) in vop2_crtc_atomic_disable()
1043 if (crtc->state->event && !crtc->state->active) { in vop2_crtc_atomic_disable()
1044 spin_lock_irq(&crtc->dev->event_lock); in vop2_crtc_atomic_disable()
1045 drm_crtc_send_vblank_event(crtc, crtc->state->event); in vop2_crtc_atomic_disable()
1046 spin_unlock_irq(&crtc->dev->event_lock); in vop2_crtc_atomic_disable()
1048 crtc->state->event = NULL; in vop2_crtc_atomic_disable()
1056 struct drm_framebuffer *fb = pstate->fb; in vop2_plane_atomic_check()
1057 struct drm_crtc *crtc = pstate->crtc; in vop2_plane_atomic_check()
1062 struct drm_rect *dest = &pstate->dst; in vop2_plane_atomic_check()
1063 struct drm_rect *src = &pstate->src; in vop2_plane_atomic_check()
1073 vop2 = vp->vop2; in vop2_plane_atomic_check()
1074 vop2_data = vop2->data; in vop2_plane_atomic_check()
1076 cstate = drm_atomic_get_existing_crtc_state(pstate->state, crtc); in vop2_plane_atomic_check()
1078 return -EINVAL; in vop2_plane_atomic_check()
1086 if (!pstate->visible) in vop2_plane_atomic_check()
1089 format = vop2_convert_format(fb->format->format); in vop2_plane_atomic_check()
1095 drm_err(vop2->drm, "Invalid size: %dx%d->%dx%d, min size is 4x4\n", in vop2_plane_atomic_check()
1098 pstate->visible = false; in vop2_plane_atomic_check()
1102 if (drm_rect_width(src) >> 16 > vop2_data->max_input.width || in vop2_plane_atomic_check()
1103 drm_rect_height(src) >> 16 > vop2_data->max_input.height) { in vop2_plane_atomic_check()
1104 drm_err(vop2->drm, "Invalid source: %dx%d. max input: %dx%d\n", in vop2_plane_atomic_check()
1107 vop2_data->max_input.width, in vop2_plane_atomic_check()
1108 vop2_data->max_input.height); in vop2_plane_atomic_check()
1109 return -EINVAL; in vop2_plane_atomic_check()
1116 if (fb->format->is_yuv && ((pstate->src.x1 >> 16) % 2)) { in vop2_plane_atomic_check()
1117 drm_err(vop2->drm, "Invalid Source: Yuv format not support odd xpos\n"); in vop2_plane_atomic_check()
1118 return -EINVAL; in vop2_plane_atomic_check()
1129 struct vop2 *vop2 = win->vop2; in vop2_plane_atomic_disable()
1131 drm_dbg(vop2->drm, "%s disable\n", win->data->name); in vop2_plane_atomic_disable()
1135 if (old_pstate && !old_pstate->crtc) in vop2_plane_atomic_disable()
1148 struct drm_plane_state *pstate = plane->state; in vop2_plane_setup_color_key()
1149 struct drm_framebuffer *fb = pstate->fb; in vop2_plane_setup_color_key()
1156 if (!(color_key & VOP2_COLOR_KEY_MASK) || fb->format->is_yuv) { in vop2_plane_setup_color_key()
1161 switch (fb->format->format) { in vop2_plane_setup_color_key()
1195 struct drm_plane_state *pstate = plane->state; in vop2_plane_atomic_update()
1196 struct drm_crtc *crtc = pstate->crtc; in vop2_plane_atomic_update()
1199 struct drm_display_mode *adjusted_mode = &crtc->state->adjusted_mode; in vop2_plane_atomic_update()
1200 struct vop2 *vop2 = win->vop2; in vop2_plane_atomic_update()
1201 struct drm_framebuffer *fb = pstate->fb; in vop2_plane_atomic_update()
1202 u32 bpp = vop2_get_bpp(fb->format); in vop2_plane_atomic_update()
1209 struct drm_rect *src = &pstate->src; in vop2_plane_atomic_update()
1210 struct drm_rect *dest = &pstate->dst; in vop2_plane_atomic_update()
1214 bool xmirror = pstate->rotation & DRM_MODE_REFLECT_X ? true : false; in vop2_plane_atomic_update()
1215 bool ymirror = pstate->rotation & DRM_MODE_REFLECT_Y ? true : false; in vop2_plane_atomic_update()
1216 bool rotate_270 = pstate->rotation & DRM_MODE_ROTATE_270; in vop2_plane_atomic_update()
1217 bool rotate_90 = pstate->rotation & DRM_MODE_ROTATE_90; in vop2_plane_atomic_update()
1231 if (!pstate->visible) { in vop2_plane_atomic_update()
1236 afbc_en = rockchip_afbc(plane, fb->modifier); in vop2_plane_atomic_update()
1238 offset = (src->x1 >> 16) * fb->format->cpp[0]; in vop2_plane_atomic_update()
1245 else if (pstate->rotation & DRM_MODE_REFLECT_Y) in vop2_plane_atomic_update()
1246 offset += ((src->y2 >> 16) - 1) * fb->pitches[0]; in vop2_plane_atomic_update()
1248 offset += (src->y1 >> 16) * fb->pitches[0]; in vop2_plane_atomic_update()
1250 rk_obj = to_rockchip_obj(fb->obj[0]); in vop2_plane_atomic_update()
1252 yrgb_mst = rk_obj->dma_addr + offset + fb->offsets[0]; in vop2_plane_atomic_update()
1253 if (fb->format->is_yuv) { in vop2_plane_atomic_update()
1254 int hsub = fb->format->hsub; in vop2_plane_atomic_update()
1255 int vsub = fb->format->vsub; in vop2_plane_atomic_update()
1257 offset = (src->x1 >> 16) * fb->format->cpp[1] / hsub; in vop2_plane_atomic_update()
1258 offset += (src->y1 >> 16) * fb->pitches[1] / vsub; in vop2_plane_atomic_update()
1260 if ((pstate->rotation & DRM_MODE_REFLECT_Y) && !afbc_en) in vop2_plane_atomic_update()
1261 offset += fb->pitches[1] * ((pstate->src_h >> 16) - 2) / vsub; in vop2_plane_atomic_update()
1263 rk_obj = to_rockchip_obj(fb->obj[0]); in vop2_plane_atomic_update()
1264 uv_mst = rk_obj->dma_addr + offset + fb->offsets[1]; in vop2_plane_atomic_update()
1271 if (dest->x1 + dsp_w > adjusted_mode->hdisplay) { in vop2_plane_atomic_update()
1272 drm_err(vop2->drm, "vp%d %s dest->x1[%d] + dsp_w[%d] exceed mode hdisplay[%d]\n", in vop2_plane_atomic_update()
1273 vp->id, win->data->name, dest->x1, dsp_w, adjusted_mode->hdisplay); in vop2_plane_atomic_update()
1274 dsp_w = adjusted_mode->hdisplay - dest->x1; in vop2_plane_atomic_update()
1282 if (dest->y1 + dsp_h > adjusted_mode->vdisplay) { in vop2_plane_atomic_update()
1283 drm_err(vop2->drm, "vp%d %s dest->y1[%d] + dsp_h[%d] exceed mode vdisplay[%d]\n", in vop2_plane_atomic_update()
1284 vp->id, win->data->name, dest->y1, dsp_h, adjusted_mode->vdisplay); in vop2_plane_atomic_update()
1285 dsp_h = adjusted_mode->vdisplay - dest->y1; in vop2_plane_atomic_update()
1295 if (!(win->data->feature & WIN_FEATURE_AFBDC)) { in vop2_plane_atomic_update()
1297 drm_err(vop2->drm, "vp%d %s act_w[%d] MODE 16 == 1\n", in vop2_plane_atomic_update()
1298 vp->id, win->data->name, actual_w); in vop2_plane_atomic_update()
1299 actual_w -= 1; in vop2_plane_atomic_update()
1304 drm_err(vop2->drm, "vp%d %s actual_w[%d] not 4 pixel aligned\n", in vop2_plane_atomic_update()
1305 vp->id, win->data->name, actual_w); in vop2_plane_atomic_update()
1309 act_info = (actual_h - 1) << 16 | ((actual_w - 1) & 0xffff); in vop2_plane_atomic_update()
1310 dsp_info = (dsp_h - 1) << 16 | ((dsp_w - 1) & 0xffff); in vop2_plane_atomic_update()
1312 format = vop2_convert_format(fb->format->format); in vop2_plane_atomic_update()
1315 drm_dbg(vop2->drm, "vp%d update %s[%dx%d->%dx%d@%dx%d] fmt[%p4cc_%s] addr[%pad]\n", in vop2_plane_atomic_update()
1316 vp->id, win->data->name, actual_w, actual_h, dsp_w, dsp_h, in vop2_plane_atomic_update()
1317 dest->x1, dest->y1, in vop2_plane_atomic_update()
1318 &fb->format->format, in vop2_plane_atomic_update()
1328 afbc_format = vop2_convert_afbc_format(fb->format->format); in vop2_plane_atomic_update()
1331 if (fb->modifier & AFBC_FORMAT_MOD_YTR) in vop2_plane_atomic_update()
1340 stride = (fb->pitches[0] << 3) / bpp; in vop2_plane_atomic_update()
1342 drm_err(vop2->drm, "vp%d %s stride[%d] not 64 pixel aligned\n", in vop2_plane_atomic_update()
1343 vp->id, win->data->name, stride); in vop2_plane_atomic_update()
1345 uv_swap = vop2_afbc_uv_swap(fb->format->format); in vop2_plane_atomic_update()
1355 if (fb->format->is_yuv && bpp == 10) in vop2_plane_atomic_update()
1370 if (vop2->data->soc_id == 3566 || vop2->data->soc_id == 3568) in vop2_plane_atomic_update()
1380 vop2_win_write(win, VOP2_WIN_AFBC_PIC_OFFSET, ((src->x1 >> 16) | src->y1)); in vop2_plane_atomic_update()
1381 vop2_win_write(win, VOP2_WIN_AFBC_DSP_OFFSET, (dest->x1 | (dest->y1 << 16))); in vop2_plane_atomic_update()
1393 vop2_win_write(win, VOP2_WIN_YRGB_VIR, DIV_ROUND_UP(fb->pitches[0], 4)); in vop2_plane_atomic_update()
1407 rb_swap = vop2_win_rb_swap(fb->format->format); in vop2_plane_atomic_update()
1410 uv_swap = vop2_win_uv_swap(fb->format->format); in vop2_plane_atomic_update()
1414 if (fb->format->is_yuv) { in vop2_plane_atomic_update()
1415 vop2_win_write(win, VOP2_WIN_UV_VIR, DIV_ROUND_UP(fb->pitches[1], 4)); in vop2_plane_atomic_update()
1419 vop2_setup_scale(vop2, win, actual_w, actual_h, dsp_w, dsp_h, fb->format->format); in vop2_plane_atomic_update()
1424 vop2_win_write(win, VOP2_WIN_DSP_ST, dest->y1 << 16 | (dest->x1 & 0xffff)); in vop2_plane_atomic_update()
1428 dither_up = vop2_win_dither_up(fb->format->format); in vop2_plane_atomic_update()
1474 const struct drm_display_mode *mode, in vop2_crtc_mode_fixup() argument
1485 struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state); in vop2_dither_setup()
1487 switch (vcstate->bus_format) { in vop2_dither_setup()
1505 if (vcstate->output_mode != ROCKCHIP_OUT_MODE_AAAA) in vop2_dither_setup()
1515 struct drm_display_mode *mode = &crtc->state->adjusted_mode; in vop2_post_config() local
1516 u16 vtotal = mode->crtc_vtotal; in vop2_post_config()
1517 u16 hdisplay = mode->crtc_hdisplay; in vop2_post_config()
1518 u16 hact_st = mode->crtc_htotal - mode->crtc_hsync_start; in vop2_post_config()
1519 u16 vdisplay = mode->crtc_vdisplay; in vop2_post_config()
1520 u16 vact_st = mode->crtc_vtotal - mode->crtc_vsync_start; in vop2_post_config()
1525 u16 hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start; in vop2_post_config()
1531 bg_dly = vp->data->pre_scan_max_dly[3]; in vop2_post_config()
1532 vop2_writel(vp->vop2, RK3568_VP_BG_MIX_CTRL(vp->id), in vop2_post_config()
1535 pre_scan_dly = ((bg_dly + (hdisplay >> 1) - 1) << 16) | hsync_len; in vop2_post_config()
1540 hact_st += hdisplay * (100 - left_margin) / 200; in vop2_post_config()
1545 vact_st += vdisplay * (100 - top_margin) / 200; in vop2_post_config()
1561 if (mode->flags & DRM_MODE_FLAG_INTERLACE) { in vop2_post_config()
1574 struct vop2 *vop2 = vp->vop2; in rk3568_set_intf_mux()
1575 struct drm_crtc *crtc = &vp->crtc; in rk3568_set_intf_mux()
1585 FIELD_PREP(RK3568_SYS_DSP_INFACE_EN_RGB_MUX, vp->id); in rk3568_set_intf_mux()
1589 regmap_write(vop2->sys_grf, RK3568_GRF_VO_CON1, BIT(3 + 16) | BIT(3)); in rk3568_set_intf_mux()
1591 regmap_write(vop2->sys_grf, RK3568_GRF_VO_CON1, BIT(3 + 16)); in rk3568_set_intf_mux()
1596 FIELD_PREP(RK3568_SYS_DSP_INFACE_EN_HDMI_MUX, vp->id); in rk3568_set_intf_mux()
1603 FIELD_PREP(RK3568_SYS_DSP_INFACE_EN_EDP_MUX, vp->id); in rk3568_set_intf_mux()
1610 FIELD_PREP(RK3568_SYS_DSP_INFACE_EN_MIPI0_MUX, vp->id); in rk3568_set_intf_mux()
1617 FIELD_PREP(RK3568_SYS_DSP_INFACE_EN_MIPI1_MUX, vp->id); in rk3568_set_intf_mux()
1624 FIELD_PREP(RK3568_SYS_DSP_INFACE_EN_LVDS0_MUX, vp->id); in rk3568_set_intf_mux()
1631 FIELD_PREP(RK3568_SYS_DSP_INFACE_EN_LVDS1_MUX, vp->id); in rk3568_set_intf_mux()
1636 drm_err(vop2->drm, "Invalid interface id %d on vp%d\n", id, vp->id); in rk3568_set_intf_mux()
1645 return crtc->state->adjusted_mode.crtc_clock * 1000LL; in rk3568_set_intf_mux()
1674 struct vop2 *vop2 = vp->vop2; in rk3588_calc_cru_cfg()
1675 struct drm_crtc *crtc = &vp->crtc; in rk3588_calc_cru_cfg()
1676 struct drm_display_mode *adjusted_mode = &crtc->state->adjusted_mode; in rk3588_calc_cru_cfg()
1677 struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state); in rk3588_calc_cru_cfg()
1678 int output_mode = vcstate->output_mode; in rk3588_calc_cru_cfg()
1679 unsigned long v_pixclk = adjusted_mode->crtc_clock * 1000LL; /* video timing pixclk */ in rk3588_calc_cru_cfg()
1724 drm_err(vop2->drm, "DP dclk_out_rate out of range, dclk_out_rate: %ld KHZ\n", in rk3588_calc_cru_cfg()
1741 drm_err(vop2->drm, "MIPI dclk out of range, dclk_out_rate: %ld KHZ\n", in rk3588_calc_cru_cfg()
1760 drm_dbg(vop2->drm, "dclk: %ld, pixclk_div: %d, dclk_div: %d\n", in rk3588_calc_cru_cfg()
1794 struct vop2 *vop2 = vp->vop2; in rk3588_set_intf_mux()
1819 FIELD_PREP(RK3588_SYS_DSP_INFACE_EN_EDP_HDMI0_MUX, vp->id); in rk3588_set_intf_mux()
1821 regmap_write(vop2->vop_grf, RK3588_GRF_VOP_CON2, HIWORD_UPDATE(1, 1, 1)); in rk3588_set_intf_mux()
1822 regmap_write(vop2->vo1_grf, RK3588_GRF_VO1_CON0, HIWORD_UPDATE(val, 6, 5)); in rk3588_set_intf_mux()
1831 FIELD_PREP(RK3588_SYS_DSP_INFACE_EN_EDP_HDMI1_MUX, vp->id); in rk3588_set_intf_mux()
1833 regmap_write(vop2->vop_grf, RK3588_GRF_VOP_CON2, HIWORD_UPDATE(1, 4, 4)); in rk3588_set_intf_mux()
1834 regmap_write(vop2->vo1_grf, RK3588_GRF_VO1_CON0, HIWORD_UPDATE(val, 8, 7)); in rk3588_set_intf_mux()
1843 FIELD_PREP(RK3588_SYS_DSP_INFACE_EN_EDP_HDMI0_MUX, vp->id); in rk3588_set_intf_mux()
1844 regmap_write(vop2->vop_grf, RK3588_GRF_VOP_CON2, HIWORD_UPDATE(1, 0, 0)); in rk3588_set_intf_mux()
1853 FIELD_PREP(RK3588_SYS_DSP_INFACE_EN_EDP_HDMI1_MUX, vp->id); in rk3588_set_intf_mux()
1854 regmap_write(vop2->vop_grf, RK3588_GRF_VOP_CON2, HIWORD_UPDATE(1, 3, 3)); in rk3588_set_intf_mux()
1860 val = rk3588_get_mipi_port_mux(vp->id); in rk3588_set_intf_mux()
1868 val = rk3588_get_mipi_port_mux(vp->id); in rk3588_set_intf_mux()
1875 FIELD_PREP(RK3588_SYS_DSP_INFACE_EN_DP0_MUX, vp->id); in rk3588_set_intf_mux()
1882 FIELD_PREP(RK3588_SYS_DSP_INFACE_EN_MIPI1_MUX, vp->id); in rk3588_set_intf_mux()
1887 drm_err(vop2->drm, "Invalid interface id %d on vp%d\n", id, vp->id); in rk3588_set_intf_mux()
1903 struct vop2 *vop2 = vp->vop2; in vop2_set_intf_mux()
1905 if (vop2->data->soc_id == 3566 || vop2->data->soc_id == 3568) in vop2_set_intf_mux()
1907 else if (vop2->data->soc_id == 3588) in vop2_set_intf_mux()
1913 static int us_to_vertical_line(struct drm_display_mode *mode, int us) in us_to_vertical_line() argument
1915 return us * mode->clock / mode->htotal / 1000; in us_to_vertical_line()
1922 struct vop2 *vop2 = vp->vop2; in vop2_crtc_atomic_enable()
1923 const struct vop2_data *vop2_data = vop2->data; in vop2_crtc_atomic_enable()
1924 const struct vop2_video_port_data *vp_data = &vop2_data->vp[vp->id]; in vop2_crtc_atomic_enable()
1926 struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state); in vop2_crtc_atomic_enable()
1927 struct drm_display_mode *mode = &crtc->state->adjusted_mode; in vop2_crtc_atomic_enable() local
1928 unsigned long clock = mode->crtc_clock * 1000; in vop2_crtc_atomic_enable()
1929 u16 hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start; in vop2_crtc_atomic_enable()
1930 u16 hdisplay = mode->crtc_hdisplay; in vop2_crtc_atomic_enable()
1931 u16 htotal = mode->crtc_htotal; in vop2_crtc_atomic_enable()
1932 u16 hact_st = mode->crtc_htotal - mode->crtc_hsync_start; in vop2_crtc_atomic_enable()
1934 u16 vdisplay = mode->crtc_vdisplay; in vop2_crtc_atomic_enable()
1935 u16 vtotal = mode->crtc_vtotal; in vop2_crtc_atomic_enable()
1936 u16 vsync_len = mode->crtc_vsync_end - mode->crtc_vsync_start; in vop2_crtc_atomic_enable()
1937 u16 vact_st = mode->crtc_vtotal - mode->crtc_vsync_start; in vop2_crtc_atomic_enable()
1946 drm_dbg(vop2->drm, "Update mode to %dx%d%s%d, type: %d for vp%d\n", in vop2_crtc_atomic_enable()
1947 hdisplay, vdisplay, mode->flags & DRM_MODE_FLAG_INTERLACE ? "i" : "p", in vop2_crtc_atomic_enable()
1948 drm_mode_vrefresh(mode), vcstate->output_type, vp->id); in vop2_crtc_atomic_enable()
1952 ret = clk_prepare_enable(vp->dclk); in vop2_crtc_atomic_enable()
1954 drm_err(vop2->drm, "failed to enable dclk for video port%d - %d\n", in vop2_crtc_atomic_enable()
1955 vp->id, ret); in vop2_crtc_atomic_enable()
1960 if (!vop2->enable_count) in vop2_crtc_atomic_enable()
1963 vop2->enable_count++; in vop2_crtc_atomic_enable()
1965 vcstate->yuv_overlay = is_yuv_output(vcstate->bus_format); in vop2_crtc_atomic_enable()
1970 if (vcstate->bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE) in vop2_crtc_atomic_enable()
1972 if (mode->flags & DRM_MODE_FLAG_PHSYNC) in vop2_crtc_atomic_enable()
1974 if (mode->flags & DRM_MODE_FLAG_PVSYNC) in vop2_crtc_atomic_enable()
1977 drm_for_each_encoder_mask(encoder, crtc->dev, crtc_state->encoder_mask) { in vop2_crtc_atomic_enable()
1983 * system cru may be the 1/2 or 1/4 of mode->clock. in vop2_crtc_atomic_enable()
1985 clock = vop2_set_intf_mux(vp, rkencoder->crtc_endpoint_id, polflags); in vop2_crtc_atomic_enable()
1993 if (vcstate->output_mode == ROCKCHIP_OUT_MODE_AAAA && in vop2_crtc_atomic_enable()
1994 !(vp_data->feature & VOP2_VP_FEATURE_OUTPUT_10BIT)) in vop2_crtc_atomic_enable()
1997 out_mode = vcstate->output_mode; in vop2_crtc_atomic_enable()
2001 if (vop2_output_uv_swap(vcstate->bus_format, vcstate->output_mode)) in vop2_crtc_atomic_enable()
2003 if (vop2_output_rg_swap(vop2, vcstate->bus_format)) in vop2_crtc_atomic_enable()
2006 if (vcstate->yuv_overlay) in vop2_crtc_atomic_enable()
2020 if (mode->flags & DRM_MODE_FLAG_INTERLACE) { in vop2_crtc_atomic_enable()
2038 vop2_writel(vop2, RK3568_VP_LINE_FLAG(vp->id), in vop2_crtc_atomic_enable()
2039 (act_end - us_to_vertical_line(mode, 0)) << 16 | act_end); in vop2_crtc_atomic_enable()
2043 if (mode->flags & DRM_MODE_FLAG_DBLCLK) { in vop2_crtc_atomic_enable()
2050 clk_set_rate(vp->dclk, clock); in vop2_crtc_atomic_enable()
2074 if (nplanes > vp->nlayers) in vop2_crtc_atomic_check()
2075 return -EINVAL; in vop2_crtc_atomic_check()
2080 static bool is_opaque(u16 alpha) in is_opaque() argument
2082 return (alpha >> 8) == 0xff; in is_opaque()
2086 struct vop2_alpha *alpha) in vop2_parse_alpha() argument
2088 int src_glb_alpha_en = is_opaque(alpha_config->src_glb_alpha_value) ? 0 : 1; in vop2_parse_alpha()
2089 int dst_glb_alpha_en = is_opaque(alpha_config->dst_glb_alpha_value) ? 0 : 1; in vop2_parse_alpha()
2090 int src_color_mode = alpha_config->src_premulti_en ? in vop2_parse_alpha()
2092 int dst_color_mode = alpha_config->dst_premulti_en ? in vop2_parse_alpha()
2095 alpha->src_color_ctrl.val = 0; in vop2_parse_alpha()
2096 alpha->dst_color_ctrl.val = 0; in vop2_parse_alpha()
2097 alpha->src_alpha_ctrl.val = 0; in vop2_parse_alpha()
2098 alpha->dst_alpha_ctrl.val = 0; in vop2_parse_alpha()
2100 if (!alpha_config->src_pixel_alpha_en) in vop2_parse_alpha()
2101 alpha->src_color_ctrl.bits.blend_mode = ALPHA_GLOBAL; in vop2_parse_alpha()
2102 else if (alpha_config->src_pixel_alpha_en && !src_glb_alpha_en) in vop2_parse_alpha()
2103 alpha->src_color_ctrl.bits.blend_mode = ALPHA_PER_PIX; in vop2_parse_alpha()
2105 alpha->src_color_ctrl.bits.blend_mode = ALPHA_PER_PIX_GLOBAL; in vop2_parse_alpha()
2107 alpha->src_color_ctrl.bits.alpha_en = 1; in vop2_parse_alpha()
2109 if (alpha->src_color_ctrl.bits.blend_mode == ALPHA_GLOBAL) { in vop2_parse_alpha()
2110 alpha->src_color_ctrl.bits.color_mode = src_color_mode; in vop2_parse_alpha()
2111 alpha->src_color_ctrl.bits.factor_mode = SRC_FAC_ALPHA_SRC_GLOBAL; in vop2_parse_alpha()
2112 } else if (alpha->src_color_ctrl.bits.blend_mode == ALPHA_PER_PIX) { in vop2_parse_alpha()
2113 alpha->src_color_ctrl.bits.color_mode = src_color_mode; in vop2_parse_alpha()
2114 alpha->src_color_ctrl.bits.factor_mode = SRC_FAC_ALPHA_ONE; in vop2_parse_alpha()
2116 alpha->src_color_ctrl.bits.color_mode = ALPHA_SRC_PRE_MUL; in vop2_parse_alpha()
2117 alpha->src_color_ctrl.bits.factor_mode = SRC_FAC_ALPHA_SRC_GLOBAL; in vop2_parse_alpha()
2119 alpha->src_color_ctrl.bits.glb_alpha = alpha_config->src_glb_alpha_value >> 8; in vop2_parse_alpha()
2120 alpha->src_color_ctrl.bits.alpha_mode = ALPHA_STRAIGHT; in vop2_parse_alpha()
2121 alpha->src_color_ctrl.bits.alpha_cal_mode = ALPHA_SATURATION; in vop2_parse_alpha()
2123 alpha->dst_color_ctrl.bits.alpha_mode = ALPHA_STRAIGHT; in vop2_parse_alpha()
2124 alpha->dst_color_ctrl.bits.alpha_cal_mode = ALPHA_SATURATION; in vop2_parse_alpha()
2125 alpha->dst_color_ctrl.bits.blend_mode = ALPHA_GLOBAL; in vop2_parse_alpha()
2126 alpha->dst_color_ctrl.bits.glb_alpha = alpha_config->dst_glb_alpha_value >> 8; in vop2_parse_alpha()
2127 alpha->dst_color_ctrl.bits.color_mode = dst_color_mode; in vop2_parse_alpha()
2128 alpha->dst_color_ctrl.bits.factor_mode = ALPHA_SRC_INVERSE; in vop2_parse_alpha()
2130 alpha->src_alpha_ctrl.bits.alpha_mode = ALPHA_STRAIGHT; in vop2_parse_alpha()
2131 alpha->src_alpha_ctrl.bits.blend_mode = alpha->src_color_ctrl.bits.blend_mode; in vop2_parse_alpha()
2132 alpha->src_alpha_ctrl.bits.alpha_cal_mode = ALPHA_SATURATION; in vop2_parse_alpha()
2133 alpha->src_alpha_ctrl.bits.factor_mode = ALPHA_ONE; in vop2_parse_alpha()
2135 alpha->dst_alpha_ctrl.bits.alpha_mode = ALPHA_STRAIGHT; in vop2_parse_alpha()
2136 if (alpha_config->dst_pixel_alpha_en && !dst_glb_alpha_en) in vop2_parse_alpha()
2137 alpha->dst_alpha_ctrl.bits.blend_mode = ALPHA_PER_PIX; in vop2_parse_alpha()
2139 alpha->dst_alpha_ctrl.bits.blend_mode = ALPHA_PER_PIX_GLOBAL; in vop2_parse_alpha()
2140 alpha->dst_alpha_ctrl.bits.alpha_cal_mode = ALPHA_NO_SATURATION; in vop2_parse_alpha()
2141 alpha->dst_alpha_ctrl.bits.factor_mode = ALPHA_SRC_INVERSE; in vop2_parse_alpha()
2151 vp = &vop2->vps[i]; in vop2_find_start_mixer_id_for_vp()
2152 used_layer += hweight32(vp->win_mask); in vop2_find_start_mixer_id_for_vp()
2160 u32 offset = (main_win->data->phys_id * 0x10); in vop2_setup_cluster_alpha()
2162 struct vop2_alpha alpha; in vop2_setup_cluster_alpha() local
2169 /* At one win mode, win0 is dst/bottom win, and win1 is a all zero src/top win */ in vop2_setup_cluster_alpha()
2170 bottom_win_pstate = main_win->base.state; in vop2_setup_cluster_alpha()
2172 dst_glb_alpha_val = main_win->base.state->alpha; in vop2_setup_cluster_alpha()
2174 if (!bottom_win_pstate->fb) in vop2_setup_cluster_alpha()
2180 alpha_config.dst_pixel_alpha_en = true; /* alpha value need transfer to next mix */ in vop2_setup_cluster_alpha()
2183 vop2_parse_alpha(&alpha_config, &alpha); in vop2_setup_cluster_alpha()
2185 alpha.src_color_ctrl.bits.src_dst_swap = swap; in vop2_setup_cluster_alpha()
2187 alpha.src_color_ctrl.val); in vop2_setup_cluster_alpha()
2189 alpha.dst_color_ctrl.val); in vop2_setup_cluster_alpha()
2191 alpha.src_alpha_ctrl.val); in vop2_setup_cluster_alpha()
2193 alpha.dst_alpha_ctrl.val); in vop2_setup_cluster_alpha()
2198 struct vop2 *vop2 = vp->vop2; in vop2_setup_alpha()
2201 struct vop2_alpha alpha; in vop2_setup_alpha() local
2210 mixer_id = vop2_find_start_mixer_id_for_vp(vop2, vp->id); in vop2_setup_alpha()
2211 alpha_config.dst_pixel_alpha_en = true; /* alpha value need transfer to next mix */ in vop2_setup_alpha()
2213 drm_atomic_crtc_for_each_plane(plane, &vp->crtc) { in vop2_setup_alpha()
2216 if (plane->state->normalized_zpos == 0 && in vop2_setup_alpha()
2217 !is_opaque(plane->state->alpha) && in vop2_setup_alpha()
2220 * If bottom layer have global alpha effect [except cluster layer, in vop2_setup_alpha()
2221 * because cluster have deal with bottom layer global alpha value in vop2_setup_alpha()
2222 * at cluster mix], bottom layer mix need deal with global alpha. in vop2_setup_alpha()
2225 dst_global_alpha = plane->state->alpha; in vop2_setup_alpha()
2229 drm_atomic_crtc_for_each_plane(plane, &vp->crtc) { in vop2_setup_alpha()
2231 int zpos = plane->state->normalized_zpos; in vop2_setup_alpha()
2233 if (plane->state->pixel_blend_mode == DRM_MODE_BLEND_PREMULTI) in vop2_setup_alpha()
2238 plane = &win->base; in vop2_setup_alpha()
2239 fb = plane->state->fb; in vop2_setup_alpha()
2241 pixel_alpha_en = fb->format->has_alpha; in vop2_setup_alpha()
2247 /* Cd = Cs + (1 - As) * Cd * Agd */ in vop2_setup_alpha()
2250 alpha_config.src_glb_alpha_value = plane->state->alpha; in vop2_setup_alpha()
2253 /* Mix output data only have pixel alpha */ in vop2_setup_alpha()
2259 /* Cd = Cs + (1 - As) * Cd */ in vop2_setup_alpha()
2262 alpha_config.src_glb_alpha_value = plane->state->alpha; in vop2_setup_alpha()
2266 vop2_parse_alpha(&alpha_config, &alpha); in vop2_setup_alpha()
2268 offset = (mixer_id + zpos - 1) * 0x10; in vop2_setup_alpha()
2270 alpha.src_color_ctrl.val); in vop2_setup_alpha()
2272 alpha.dst_color_ctrl.val); in vop2_setup_alpha()
2274 alpha.src_alpha_ctrl.val); in vop2_setup_alpha()
2276 alpha.dst_alpha_ctrl.val); in vop2_setup_alpha()
2279 if (vp->id == 0) { in vop2_setup_alpha()
2281 /* Transfer pixel alpha to hdr mix */ in vop2_setup_alpha()
2287 vop2_parse_alpha(&alpha_config, &alpha); in vop2_setup_alpha()
2290 alpha.src_color_ctrl.val); in vop2_setup_alpha()
2292 alpha.dst_color_ctrl.val); in vop2_setup_alpha()
2294 alpha.src_alpha_ctrl.val); in vop2_setup_alpha()
2296 alpha.dst_alpha_ctrl.val); in vop2_setup_alpha()
2305 struct vop2 *vop2 = vp->vop2; in vop2_setup_layer_mixer()
2312 struct vop2_video_port *vp0 = &vop2->vps[0]; in vop2_setup_layer_mixer()
2313 struct vop2_video_port *vp1 = &vop2->vps[1]; in vop2_setup_layer_mixer()
2314 struct vop2_video_port *vp2 = &vop2->vps[2]; in vop2_setup_layer_mixer()
2315 struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(vp->crtc.state); in vop2_setup_layer_mixer()
2319 if (vcstate->yuv_overlay) in vop2_setup_layer_mixer()
2320 ovl_ctrl |= RK3568_OVL_CTRL__YUV_MODE(vp->id); in vop2_setup_layer_mixer()
2322 ovl_ctrl &= ~RK3568_OVL_CTRL__YUV_MODE(vp->id); in vop2_setup_layer_mixer()
2329 if (vp0->nlayers) in vop2_setup_layer_mixer()
2331 vp0->nlayers - 1); in vop2_setup_layer_mixer()
2335 if (vp1->nlayers) in vop2_setup_layer_mixer()
2337 (vp0->nlayers + vp1->nlayers - 1)); in vop2_setup_layer_mixer()
2341 if (vp2->nlayers) in vop2_setup_layer_mixer()
2343 (vp2->nlayers + vp1->nlayers + vp0->nlayers - 1)); in vop2_setup_layer_mixer()
2350 for (i = 0; i < vp->id; i++) in vop2_setup_layer_mixer()
2351 ofs += vop2->vps[i].nlayers; in vop2_setup_layer_mixer()
2354 drm_atomic_crtc_for_each_plane(plane, &vp->crtc) { in vop2_setup_layer_mixer()
2357 switch (win->data->phys_id) { in vop2_setup_layer_mixer()
2360 port_sel |= FIELD_PREP(RK3568_OVL_PORT_SEL__CLUSTER0, vp->id); in vop2_setup_layer_mixer()
2364 port_sel |= FIELD_PREP(RK3568_OVL_PORT_SEL__CLUSTER1, vp->id); in vop2_setup_layer_mixer()
2368 port_sel |= FIELD_PREP(RK3588_OVL_PORT_SEL__CLUSTER2, vp->id); in vop2_setup_layer_mixer()
2372 port_sel |= FIELD_PREP(RK3588_OVL_PORT_SEL__CLUSTER3, vp->id); in vop2_setup_layer_mixer()
2376 port_sel |= FIELD_PREP(RK3568_OVL_PORT_SEL__ESMART0, vp->id); in vop2_setup_layer_mixer()
2380 port_sel |= FIELD_PREP(RK3568_OVL_PORT_SEL__ESMART1, vp->id); in vop2_setup_layer_mixer()
2384 port_sel |= FIELD_PREP(RK3588_OVL_PORT_SEL__ESMART2, vp->id); in vop2_setup_layer_mixer()
2388 port_sel |= FIELD_PREP(RK3588_OVL_PORT_SEL__ESMART3, vp->id); in vop2_setup_layer_mixer()
2392 port_sel |= FIELD_PREP(RK3568_OVL_PORT_SEL__SMART0, vp->id); in vop2_setup_layer_mixer()
2396 port_sel |= FIELD_PREP(RK3568_OVL_PORT_SEL__SMART1, vp->id); in vop2_setup_layer_mixer()
2400 layer_sel &= ~RK3568_OVL_LAYER_SEL__LAYER(plane->state->normalized_zpos + ofs, in vop2_setup_layer_mixer()
2402 layer_sel |= RK3568_OVL_LAYER_SEL__LAYER(plane->state->normalized_zpos + ofs, in vop2_setup_layer_mixer()
2403 win->data->layer_sel_id); in vop2_setup_layer_mixer()
2408 for (; nlayer < vp->nlayers; nlayer++) { in vop2_setup_layer_mixer()
2423 for (i = 0; i < vop2->data->win_size; i++) { in vop2_setup_dly_for_windows()
2426 win = &vop2->win[i]; in vop2_setup_dly_for_windows()
2427 dly = win->delay; in vop2_setup_dly_for_windows()
2429 switch (win->data->phys_id) { in vop2_setup_dly_for_windows()
2461 struct vop2 *vop2 = vp->vop2; in vop2_crtc_atomic_begin()
2464 vp->win_mask = 0; in vop2_crtc_atomic_begin()
2469 win->delay = win->data->dly[VOP2_DLY_MODE_DEFAULT]; in vop2_crtc_atomic_begin()
2471 vp->win_mask |= BIT(win->data->phys_id); in vop2_crtc_atomic_begin()
2477 if (!vp->win_mask) in vop2_crtc_atomic_begin()
2494 spin_lock_irq(&crtc->dev->event_lock); in vop2_crtc_atomic_flush()
2496 if (crtc->state->event) { in vop2_crtc_atomic_flush()
2498 vp->event = crtc->state->event; in vop2_crtc_atomic_flush()
2499 crtc->state->event = NULL; in vop2_crtc_atomic_flush()
2502 spin_unlock_irq(&crtc->dev->event_lock); in vop2_crtc_atomic_flush()
2518 if (WARN_ON(!crtc->state)) in vop2_crtc_duplicate_state()
2521 vcstate = kmemdup(to_rockchip_crtc_state(crtc->state), in vop2_crtc_duplicate_state()
2526 __drm_atomic_helper_crtc_duplicate_state(crtc, &vcstate->base); in vop2_crtc_duplicate_state()
2528 return &vcstate->base; in vop2_crtc_duplicate_state()
2536 __drm_atomic_helper_crtc_destroy_state(&vcstate->base); in vop2_crtc_destroy_state()
2545 if (crtc->state) in vop2_crtc_reset()
2546 vop2_crtc_destroy_state(crtc, crtc->state); in vop2_crtc_reset()
2549 __drm_atomic_helper_crtc_reset(crtc, &vcstate->base); in vop2_crtc_reset()
2568 const struct vop2_data *vop2_data = vop2->data; in vop2_isr()
2574 * The irq is shared with the iommu. If the runtime-pm state of the in vop2_isr()
2575 * vop2-device is disabled the irq has to be targeted at the iommu. in vop2_isr()
2577 if (!pm_runtime_get_if_in_use(vop2->dev)) in vop2_isr()
2580 for (i = 0; i < vop2_data->nr_vps; i++) { in vop2_isr()
2581 struct vop2_video_port *vp = &vop2->vps[i]; in vop2_isr()
2582 struct drm_crtc *crtc = &vp->crtc; in vop2_isr()
2585 irqs = vop2_readl(vop2, RK3568_VP_INT_STATUS(vp->id)); in vop2_isr()
2586 vop2_writel(vop2, RK3568_VP_INT_CLR(vp->id), irqs << 16 | irqs); in vop2_isr()
2589 complete(&vp->dsp_hold_completion); in vop2_isr()
2595 spin_lock(&crtc->dev->event_lock); in vop2_isr()
2596 if (vp->event) { in vop2_isr()
2599 if (!(val & BIT(vp->id))) { in vop2_isr()
2600 drm_crtc_send_vblank_event(crtc, vp->event); in vop2_isr()
2601 vp->event = NULL; in vop2_isr()
2605 spin_unlock(&crtc->dev->event_lock); in vop2_isr()
2611 drm_err_ratelimited(vop2->drm, in vop2_isr()
2613 vp->id); in vop2_isr()
2625 drm_err_ratelimited(vop2->drm, "BUS_ERROR irq err\n"); in vop2_isr()
2630 pm_runtime_put(vop2->dev); in vop2_isr()
2638 const struct vop2_win_data *win_data = win->data; in vop2_plane_init()
2644 ret = drm_universal_plane_init(vop2->drm, &win->base, possible_crtcs, in vop2_plane_init()
2645 &vop2_plane_funcs, win_data->formats, in vop2_plane_init()
2646 win_data->nformats, in vop2_plane_init()
2647 win_data->format_modifiers, in vop2_plane_init()
2648 win->type, win_data->name); in vop2_plane_init()
2650 drm_err(vop2->drm, "failed to initialize plane %d\n", ret); in vop2_plane_init()
2654 drm_plane_helper_add(&win->base, &vop2_plane_helper_funcs); in vop2_plane_init()
2656 if (win->data->supported_rotations) in vop2_plane_init()
2657 drm_plane_create_rotation_property(&win->base, DRM_MODE_ROTATE_0, in vop2_plane_init()
2659 win->data->supported_rotations); in vop2_plane_init()
2660 drm_plane_create_alpha_property(&win->base); in vop2_plane_init()
2661 drm_plane_create_blend_mode_property(&win->base, blend_caps); in vop2_plane_init()
2662 drm_plane_create_zpos_property(&win->base, win->win_id, 0, in vop2_plane_init()
2663 vop2->registered_num_wins - 1); in vop2_plane_init()
2672 for (i = 0; i < vop2->data->nr_vps; i++) { in find_vp_without_primary()
2673 struct vop2_video_port *vp = &vop2->vps[i]; in find_vp_without_primary()
2675 if (!vp->crtc.port) in find_vp_without_primary()
2677 if (vp->primary_plane) in find_vp_without_primary()
2688 const struct vop2_data *vop2_data = vop2->data; in vop2_create_crtcs()
2689 struct drm_device *drm = vop2->drm; in vop2_create_crtcs()
2690 struct device *dev = vop2->dev; in vop2_create_crtcs()
2697 for (i = 0; i < vop2_data->nr_vps; i++) { in vop2_create_crtcs()
2702 vp_data = &vop2_data->vp[i]; in vop2_create_crtcs()
2703 vp = &vop2->vps[i]; in vop2_create_crtcs()
2704 vp->vop2 = vop2; in vop2_create_crtcs()
2705 vp->id = vp_data->id; in vop2_create_crtcs()
2706 vp->data = vp_data; in vop2_create_crtcs()
2708 snprintf(dclk_name, sizeof(dclk_name), "dclk_vp%d", vp->id); in vop2_create_crtcs()
2709 vp->dclk = devm_clk_get(vop2->dev, dclk_name); in vop2_create_crtcs()
2710 if (IS_ERR(vp->dclk)) { in vop2_create_crtcs()
2711 drm_err(vop2->drm, "failed to get %s\n", dclk_name); in vop2_create_crtcs()
2712 return PTR_ERR(vp->dclk); in vop2_create_crtcs()
2715 np = of_graph_get_remote_node(dev->of_node, i, -1); in vop2_create_crtcs()
2717 drm_dbg(vop2->drm, "%s: No remote for vp%d\n", __func__, i); in vop2_create_crtcs()
2722 port = of_graph_get_port_by_id(dev->of_node, i); in vop2_create_crtcs()
2724 drm_err(vop2->drm, "no port node found for video_port%d\n", i); in vop2_create_crtcs()
2725 return -ENOENT; in vop2_create_crtcs()
2728 vp->crtc.port = port; in vop2_create_crtcs()
2733 for (i = 0; i < vop2->registered_num_wins; i++) { in vop2_create_crtcs()
2734 struct vop2_win *win = &vop2->win[i]; in vop2_create_crtcs()
2737 if (vop2->data->soc_id == 3566) { in vop2_create_crtcs()
2743 switch (win->data->phys_id) { in vop2_create_crtcs()
2751 if (win->type == DRM_PLANE_TYPE_PRIMARY) { in vop2_create_crtcs()
2755 vp->primary_plane = win; in vop2_create_crtcs()
2759 win->type = DRM_PLANE_TYPE_OVERLAY; in vop2_create_crtcs()
2763 if (win->type == DRM_PLANE_TYPE_OVERLAY) in vop2_create_crtcs()
2764 possible_crtcs = (1 << nvps) - 1; in vop2_create_crtcs()
2768 drm_err(vop2->drm, "failed to init plane %s: %d\n", in vop2_create_crtcs()
2769 win->data->name, ret); in vop2_create_crtcs()
2774 for (i = 0; i < vop2_data->nr_vps; i++) { in vop2_create_crtcs()
2775 vp = &vop2->vps[i]; in vop2_create_crtcs()
2777 if (!vp->crtc.port) in vop2_create_crtcs()
2780 plane = &vp->primary_plane->base; in vop2_create_crtcs()
2782 ret = drm_crtc_init_with_planes(drm, &vp->crtc, plane, NULL, in vop2_create_crtcs()
2784 "video_port%d", vp->id); in vop2_create_crtcs()
2786 drm_err(vop2->drm, "crtc init for video_port%d failed\n", i); in vop2_create_crtcs()
2790 drm_crtc_helper_add(&vp->crtc, &vop2_crtc_helper_funcs); in vop2_create_crtcs()
2792 init_completion(&vp->dsp_hold_completion); in vop2_create_crtcs()
2800 for (i = 0; i < vop2->data->nr_vps; i++) { in vop2_create_crtcs()
2801 struct vop2_video_port *vp = &vop2->vps[i]; in vop2_create_crtcs()
2803 if (vp->crtc.port) in vop2_create_crtcs()
2804 vp->nlayers = vop2_data->win_size / nvps; in vop2_create_crtcs()
2812 struct drm_device *drm = vop2->drm; in vop2_destroy_crtcs()
2813 struct list_head *crtc_list = &drm->mode_config.crtc_list; in vop2_destroy_crtcs()
2814 struct list_head *plane_list = &drm->mode_config.plane_list; in vop2_destroy_crtcs()
2826 of_node_put(crtc->port); in vop2_destroy_crtcs()
2833 struct device_node *node = vop2->dev->of_node; in vop2_find_rgb_encoder()
2837 for (i = 0; i < vop2->data->nr_vps; i++) { in vop2_find_rgb_encoder()
2847 return -ENOENT; in vop2_find_rgb_encoder()
2916 struct vop2 *vop2 = win->vop2; in vop2_cluster_init()
2923 return -ENOMEM; in vop2_cluster_init()
2927 cluster_regs[i].reg += win->offset; in vop2_cluster_init()
2929 ret = devm_regmap_field_bulk_alloc(vop2->dev, vop2->map, win->reg, in vop2_cluster_init()
3000 struct vop2 *vop2 = win->vop2; in vop2_esmart_init()
3007 return -ENOMEM; in vop2_esmart_init()
3011 esmart_regs[i].reg += win->offset; in vop2_esmart_init()
3013 ret = devm_regmap_field_bulk_alloc(vop2->dev, vop2->map, win->reg, in vop2_esmart_init()
3024 const struct vop2_data *vop2_data = vop2->data; in vop2_win_init()
3028 for (i = 0; i < vop2_data->win_size; i++) { in vop2_win_init()
3029 const struct vop2_win_data *win_data = &vop2_data->win[i]; in vop2_win_init()
3031 win = &vop2->win[i]; in vop2_win_init()
3032 win->data = win_data; in vop2_win_init()
3033 win->type = win_data->type; in vop2_win_init()
3034 win->offset = win_data->base; in vop2_win_init()
3035 win->win_id = i; in vop2_win_init()
3036 win->vop2 = vop2; in vop2_win_init()
3045 vop2->registered_num_wins = vop2_data->win_size; in vop2_win_init()
3052 * Until that they read back the old value. As we read-modify-write
3053 * these registers mark them as non-volatile. This makes sure we read
3087 return -ENODEV; in vop2_bind()
3090 alloc_size = struct_size(vop2, win, vop2_data->win_size); in vop2_bind()
3093 return -ENOMEM; in vop2_bind()
3095 vop2->dev = dev; in vop2_bind()
3096 vop2->data = vop2_data; in vop2_bind()
3097 vop2->drm = drm; in vop2_bind()
3103 drm_err(vop2->drm, "failed to get vop2 register byname\n"); in vop2_bind()
3104 return -EINVAL; in vop2_bind()
3107 vop2->regs = devm_ioremap_resource(dev, res); in vop2_bind()
3108 if (IS_ERR(vop2->regs)) in vop2_bind()
3109 return PTR_ERR(vop2->regs); in vop2_bind()
3110 vop2->len = resource_size(res); in vop2_bind()
3112 vop2->map = devm_regmap_init_mmio(dev, vop2->regs, &vop2_regmap_config); in vop2_bind()
3113 if (IS_ERR(vop2->map)) in vop2_bind()
3114 return PTR_ERR(vop2->map); in vop2_bind()
3120 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "gamma-lut"); in vop2_bind()
3122 vop2->lut_regs = devm_ioremap_resource(dev, res); in vop2_bind()
3123 if (IS_ERR(vop2->lut_regs)) in vop2_bind()
3124 return PTR_ERR(vop2->lut_regs); in vop2_bind()
3126 if (vop2_data->feature & VOP2_FEATURE_HAS_SYS_GRF) { in vop2_bind()
3127 vop2->sys_grf = syscon_regmap_lookup_by_phandle(dev->of_node, "rockchip,grf"); in vop2_bind()
3128 if (IS_ERR(vop2->sys_grf)) in vop2_bind()
3129 return dev_err_probe(dev, PTR_ERR(vop2->sys_grf), "cannot get sys_grf"); in vop2_bind()
3132 if (vop2_data->feature & VOP2_FEATURE_HAS_VOP_GRF) { in vop2_bind()
3133 vop2->vop_grf = syscon_regmap_lookup_by_phandle(dev->of_node, "rockchip,vop-grf"); in vop2_bind()
3134 if (IS_ERR(vop2->vop_grf)) in vop2_bind()
3135 return dev_err_probe(dev, PTR_ERR(vop2->vop_grf), "cannot get vop_grf"); in vop2_bind()
3138 if (vop2_data->feature & VOP2_FEATURE_HAS_VO1_GRF) { in vop2_bind()
3139 vop2->vo1_grf = syscon_regmap_lookup_by_phandle(dev->of_node, "rockchip,vo1-grf"); in vop2_bind()
3140 if (IS_ERR(vop2->vo1_grf)) in vop2_bind()
3141 return dev_err_probe(dev, PTR_ERR(vop2->vo1_grf), "cannot get vo1_grf"); in vop2_bind()
3144 if (vop2_data->feature & VOP2_FEATURE_HAS_SYS_PMU) { in vop2_bind()
3145 vop2->sys_pmu = syscon_regmap_lookup_by_phandle(dev->of_node, "rockchip,pmu"); in vop2_bind()
3146 if (IS_ERR(vop2->sys_pmu)) in vop2_bind()
3147 return dev_err_probe(dev, PTR_ERR(vop2->sys_pmu), "cannot get sys_pmu"); in vop2_bind()
3150 vop2->hclk = devm_clk_get(vop2->dev, "hclk"); in vop2_bind()
3151 if (IS_ERR(vop2->hclk)) { in vop2_bind()
3152 drm_err(vop2->drm, "failed to get hclk source\n"); in vop2_bind()
3153 return PTR_ERR(vop2->hclk); in vop2_bind()
3156 vop2->aclk = devm_clk_get(vop2->dev, "aclk"); in vop2_bind()
3157 if (IS_ERR(vop2->aclk)) { in vop2_bind()
3158 drm_err(vop2->drm, "failed to get aclk source\n"); in vop2_bind()
3159 return PTR_ERR(vop2->aclk); in vop2_bind()
3162 vop2->pclk = devm_clk_get_optional(vop2->dev, "pclk_vop"); in vop2_bind()
3163 if (IS_ERR(vop2->pclk)) { in vop2_bind()
3164 drm_err(vop2->drm, "failed to get pclk source\n"); in vop2_bind()
3165 return PTR_ERR(vop2->pclk); in vop2_bind()
3168 vop2->irq = platform_get_irq(pdev, 0); in vop2_bind()
3169 if (vop2->irq < 0) { in vop2_bind()
3170 drm_err(vop2->drm, "cannot find irq for vop2\n"); in vop2_bind()
3171 return vop2->irq; in vop2_bind()
3174 mutex_init(&vop2->vop2_lock); in vop2_bind()
3176 ret = devm_request_irq(dev, vop2->irq, vop2_isr, IRQF_SHARED, dev_name(dev), vop2); in vop2_bind()
3186 vop2->rgb = rockchip_rgb_init(dev, &vop2->vps[ret].crtc, in vop2_bind()
3187 vop2->drm, ret); in vop2_bind()
3188 if (IS_ERR(vop2->rgb)) { in vop2_bind()
3189 if (PTR_ERR(vop2->rgb) == -EPROBE_DEFER) { in vop2_bind()
3190 ret = PTR_ERR(vop2->rgb); in vop2_bind()
3193 vop2->rgb = NULL; in vop2_bind()
3197 rockchip_drm_dma_init_device(vop2->drm, vop2->dev); in vop2_bind()
3199 pm_runtime_enable(&pdev->dev); in vop2_bind()
3215 if (vop2->rgb) in vop2_unbind()
3216 rockchip_rgb_fini(vop2->rgb); in vop2_unbind()