Lines Matching +full:rk3568 +full:- +full:vop
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>
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,
107 * bus-format types.
141 mutex_lock(&vop2->vop2_lock);
146 mutex_unlock(&vop2->vop2_lock); in vop2_unlock()
159 switch (format->format) { in vop2_get_bpp()
216 return -EINVAL; in vop2_convert_format()
339 if (vop2->version == VOP_VERSION_RK3588) { in vop2_output_rg_swap()
376 for (i = 0 ; i < plane->modifier_count; i++) in rockchip_afbc()
377 if (plane->modifiers[i] == modifier) in rockchip_afbc()
387 struct vop2 *vop2 = win->vop2; in rockchip_vop2_mod_supported()
392 if (vop2->version == VOP_VERSION_RK3568) { in rockchip_vop2_mod_supported()
395 drm_dbg_kms(vop2->drm, in rockchip_vop2_mod_supported()
403 if (vop2->version == VOP_VERSION_RK3588) { in rockchip_vop2_mod_supported()
405 drm_dbg_kms(vop2->drm, "Only support 32 bpp format with afbc\n"); in rockchip_vop2_mod_supported()
415 drm_dbg_kms(vop2->drm, "Unsupported format modifier 0x%llx\n", in rockchip_vop2_mod_supported()
430 if (pstate->rotation & (DRM_MODE_ROTATE_270 | DRM_MODE_ROTATE_90)) in vop2_half_block_enable()
439 struct drm_rect *src = &pstate->src; in vop2_afbc_transform_offset()
440 struct drm_framebuffer *fb = pstate->fb; in vop2_afbc_transform_offset()
441 u32 bpp = vop2_get_bpp(fb->format); in vop2_afbc_transform_offset()
442 u32 vir_width = (fb->pitches[0] << 3) / bpp; in vop2_afbc_transform_offset()
445 u32 act_xoffset = src->x1 >> 16; in vop2_afbc_transform_offset()
446 u32 act_yoffset = src->y1 >> 16; in vop2_afbc_transform_offset()
455 align16_crop = 16 - (height & 0xf); in vop2_afbc_transform_offset()
461 align64_crop = 64 - (height_tmp & 0x3f); in vop2_afbc_transform_offset()
465 switch (pstate->rotation & in vop2_afbc_transform_offset()
469 tx = 16 - ((act_xoffset + width) & 0xf); in vop2_afbc_transform_offset()
470 ty = bottom_crop_line_num - act_yoffset; in vop2_afbc_transform_offset()
473 tx = bottom_crop_line_num - act_yoffset; in vop2_afbc_transform_offset()
474 ty = vir_width - width - act_xoffset; in vop2_afbc_transform_offset()
481 tx = 16 - ((act_xoffset + width) & 0xf); in vop2_afbc_transform_offset()
486 ty = bottom_crop_line_num - act_yoffset; in vop2_afbc_transform_offset()
489 tx = bottom_crop_line_num - act_yoffset; in vop2_afbc_transform_offset()
494 ty = vir_width - width - act_xoffset; in vop2_afbc_transform_offset()
523 if ((pstate->rotation & DRM_MODE_ROTATE_270) || in vop2_get_cluster_lb_mode()
524 (pstate->rotation & DRM_MODE_ROTATE_90)) in vop2_get_cluster_lb_mode()
549 src--; in vop2_scale_factor()
550 dst--; in vop2_scale_factor()
552 fac = DIV_ROUND_UP(src << shift, dst) - 1; in vop2_scale_factor()
597 * RK3568 VOP Esmart/Smart dsp_w should be even pixel in vop2_setup_scale()
600 if (!(win->data->feature & WIN_FEATURE_AFBDC)) { in vop2_setup_scale()
602 drm_dbg(vop2->drm, "%s dst_w[%d] should align as 2 pixel\n", in vop2_setup_scale()
603 win->data->name, dst_w); in vop2_setup_scale()
625 if (info->is_yuv) { in vop2_setup_scale()
626 cbcr_src_w /= info->hsub; in vop2_setup_scale()
627 cbcr_src_h /= info->vsub; in vop2_setup_scale()
681 * 1. YUV(2020) --> Y2R->2020To709->R2Y --> YUV_OUTPUT(601/709)
682 * RGB --> R2Y __/
684 * 2. YUV(2020) --> bypasss --> YUV_OUTPUT(2020)
685 * RGB --> 709To2020->R2Y __/
687 * 3. YUV(2020) --> Y2R->2020To709 --> RGB_OUTPUT(709)
688 * RGB --> R2Y __/
690 * 4. YUV(601/709)-> Y2R->709To2020->R2Y --> YUV_OUTPUT(2020)
691 * RGB --> 709To2020->R2Y __/
693 * 5. YUV(601/709)-> bypass --> YUV_OUTPUT(709)
694 * RGB --> R2Y __/
696 * 6. YUV(601/709)-> bypass --> YUV_OUTPUT(601)
697 * RGB --> R2Y(601) __/
699 * 7. YUV --> Y2R(709) --> RGB_OUTPUT(709)
700 * RGB --> bypass __/
702 * 8. RGB --> 709To2020->R2Y --> YUV_OUTPUT(2020)
704 * 9. RGB --> R2Y(709) --> YUV_OUTPUT(709)
706 * 10. RGB --> R2Y(601) --> YUV_OUTPUT(601)
708 * 11. RGB --> bypass --> RGB_OUTPUT(709)
715 struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(vp->crtc.state); in vop2_setup_csc_mode()
716 int is_input_yuv = pstate->fb->format->is_yuv; in vop2_setup_csc_mode()
717 int is_output_yuv = is_yuv_output(vcstate->bus_format); in vop2_setup_csc_mode()
719 int output_csc = vcstate->color_space; in vop2_setup_csc_mode()
744 struct vop2 *vop2 = vp->vop2; in vop2_crtc_enable_irq()
746 vop2_writel(vop2, RK3568_VP_INT_CLR(vp->id), irq << 16 | irq); in vop2_crtc_enable_irq()
747 vop2_writel(vop2, RK3568_VP_INT_EN(vp->id), irq << 16 | irq); in vop2_crtc_enable_irq()
752 struct vop2 *vop2 = vp->vop2; in vop2_crtc_disable_irq()
754 vop2_writel(vop2, RK3568_VP_INT_EN(vp->id), irq << 16); in vop2_crtc_disable_irq()
761 ret = clk_prepare_enable(vop2->hclk); in vop2_core_clks_prepare_enable()
763 drm_err(vop2->drm, "failed to enable hclk - %d\n", ret); in vop2_core_clks_prepare_enable()
767 ret = clk_prepare_enable(vop2->aclk); in vop2_core_clks_prepare_enable()
769 drm_err(vop2->drm, "failed to enable aclk - %d\n", ret); in vop2_core_clks_prepare_enable()
773 ret = clk_prepare_enable(vop2->pclk); in vop2_core_clks_prepare_enable()
775 drm_err(vop2->drm, "failed to enable pclk - %d\n", ret); in vop2_core_clks_prepare_enable()
781 clk_disable_unprepare(vop2->aclk); in vop2_core_clks_prepare_enable()
783 clk_disable_unprepare(vop2->hclk); in vop2_core_clks_prepare_enable()
804 ret = pm_runtime_resume_and_get(vop2->dev); in vop2_enable()
806 drm_err(vop2->drm, "failed to get pm runtime: %d\n", ret); in vop2_enable()
812 pm_runtime_put_sync(vop2->dev); in vop2_enable()
816 ret = rockchip_drm_dma_attach_device(vop2->drm, vop2->dev); in vop2_enable()
818 drm_err(vop2->drm, "failed to attach dma mapping, %d\n", ret); in vop2_enable()
823 if (version != vop2->version) { in vop2_enable()
824 drm_err(vop2->drm, "Hardware version(0x%08x) mismatch\n", version); in vop2_enable()
829 * rk3566 share the same vop version with rk3568, so in vop2_enable()
832 if (vop2->data->soc_id == 3566) in vop2_enable()
835 if (vop2->version == VOP_VERSION_RK3588) in vop2_enable()
838 if (vop2->version <= VOP_VERSION_RK3588) { in vop2_enable()
839 vop2->old_layer_sel = vop2_readl(vop2, RK3568_OVL_LAYER_SEL); in vop2_enable()
840 vop2->old_port_sel = vop2_readl(vop2, RK3568_OVL_PORT_SEL); in vop2_enable()
849 regmap_clear_bits(vop2->map, RK3568_SYS_AUTO_GATING_CTRL, in vop2_enable()
864 rockchip_drm_dma_detach_device(vop2->drm, vop2->dev); in vop2_disable()
866 pm_runtime_put_sync(vop2->dev); in vop2_disable()
868 regcache_drop_region(vop2->map, 0, vop2_regmap_config.max_register); in vop2_disable()
870 clk_disable_unprepare(vop2->pclk); in vop2_disable()
871 clk_disable_unprepare(vop2->aclk); in vop2_disable()
872 clk_disable_unprepare(vop2->hclk); in vop2_disable()
896 drm_err(vp->vop2->drm, "display LUT RAM enable timeout!\n"); in vop2_vp_dsp_lut_poll_disabled()
921 return vop2->version != VOP_VERSION_RK3568; in vop2_supports_seamless_gamma_lut_update()
926 const int nr_vps = vop2->data->nr_vps; in vop2_gamma_lut_in_use()
930 if (vop2_vp_dsp_lut_is_enabled(&vop2->vps[gamma_en_vp_id])) in vop2_gamma_lut_in_use()
933 return gamma_en_vp_id != nr_vps && gamma_en_vp_id != vp->id; in vop2_gamma_lut_in_use()
940 struct vop2 *vop2 = vp->vop2; in vop2_crtc_atomic_disable()
952 * Vop standby will take effect at end of current frame, in vop2_crtc_atomic_disable()
958 reinit_completion(&vp->dsp_hold_completion); in vop2_crtc_atomic_disable()
964 ret = wait_for_completion_timeout(&vp->dsp_hold_completion, in vop2_crtc_atomic_disable()
967 drm_info(vop2->drm, "wait for vp%d dsp_hold timeout\n", vp->id); in vop2_crtc_atomic_disable()
971 if (vp->dclk_src) in vop2_crtc_atomic_disable()
972 clk_set_parent(vp->dclk, vp->dclk_src); in vop2_crtc_atomic_disable()
974 clk_disable_unprepare(vp->dclk); in vop2_crtc_atomic_disable()
976 vop2->enable_count--; in vop2_crtc_atomic_disable()
978 if (!vop2->enable_count) in vop2_crtc_atomic_disable()
983 if (crtc->state->event && !crtc->state->active) { in vop2_crtc_atomic_disable()
984 spin_lock_irq(&crtc->dev->event_lock); in vop2_crtc_atomic_disable()
985 drm_crtc_send_vblank_event(crtc, crtc->state->event); in vop2_crtc_atomic_disable()
986 spin_unlock_irq(&crtc->dev->event_lock); in vop2_crtc_atomic_disable()
988 crtc->state->event = NULL; in vop2_crtc_atomic_disable()
996 struct drm_framebuffer *fb = pstate->fb; in vop2_plane_atomic_check()
997 struct drm_crtc *crtc = pstate->crtc; in vop2_plane_atomic_check()
1002 struct drm_rect *dest = &pstate->dst; in vop2_plane_atomic_check()
1003 struct drm_rect *src = &pstate->src; in vop2_plane_atomic_check()
1013 vop2 = vp->vop2; in vop2_plane_atomic_check()
1014 vop2_data = vop2->data; in vop2_plane_atomic_check()
1016 cstate = drm_atomic_get_existing_crtc_state(pstate->state, crtc); in vop2_plane_atomic_check()
1018 return -EINVAL; in vop2_plane_atomic_check()
1026 if (!pstate->visible) in vop2_plane_atomic_check()
1029 format = vop2_convert_format(fb->format->format); in vop2_plane_atomic_check()
1035 drm_err(vop2->drm, "Invalid size: %dx%d->%dx%d, min size is 4x4\n", in vop2_plane_atomic_check()
1038 pstate->visible = false; in vop2_plane_atomic_check()
1042 if (drm_rect_width(src) >> 16 > vop2_data->max_input.width || in vop2_plane_atomic_check()
1043 drm_rect_height(src) >> 16 > vop2_data->max_input.height) { in vop2_plane_atomic_check()
1044 drm_err(vop2->drm, "Invalid source: %dx%d. max input: %dx%d\n", in vop2_plane_atomic_check()
1047 vop2_data->max_input.width, in vop2_plane_atomic_check()
1048 vop2_data->max_input.height); in vop2_plane_atomic_check()
1049 return -EINVAL; in vop2_plane_atomic_check()
1056 if (fb->format->is_yuv && ((pstate->src.x1 >> 16) % 2)) { in vop2_plane_atomic_check()
1057 drm_err(vop2->drm, "Invalid Source: Yuv format not support odd xpos\n"); in vop2_plane_atomic_check()
1058 return -EINVAL; in vop2_plane_atomic_check()
1069 struct vop2 *vop2 = win->vop2; in vop2_plane_atomic_disable()
1071 drm_dbg(vop2->drm, "%s disable\n", win->data->name); in vop2_plane_atomic_disable()
1075 if (old_pstate && !old_pstate->crtc) in vop2_plane_atomic_disable()
1088 struct drm_plane_state *pstate = plane->state; in vop2_plane_setup_color_key()
1089 struct drm_framebuffer *fb = pstate->fb; in vop2_plane_setup_color_key()
1096 if (!(color_key & VOP2_COLOR_KEY_MASK) || fb->format->is_yuv) { in vop2_plane_setup_color_key()
1101 switch (fb->format->format) { in vop2_plane_setup_color_key()
1135 struct drm_plane_state *pstate = plane->state; in vop2_plane_atomic_update()
1136 struct drm_crtc *crtc = pstate->crtc; in vop2_plane_atomic_update()
1139 struct drm_display_mode *adjusted_mode = &crtc->state->adjusted_mode; in vop2_plane_atomic_update()
1140 struct vop2 *vop2 = win->vop2; in vop2_plane_atomic_update()
1141 struct drm_framebuffer *fb = pstate->fb; in vop2_plane_atomic_update()
1142 u32 bpp = vop2_get_bpp(fb->format); in vop2_plane_atomic_update()
1149 struct drm_rect *src = &pstate->src; in vop2_plane_atomic_update()
1150 struct drm_rect *dest = &pstate->dst; in vop2_plane_atomic_update()
1154 bool xmirror = pstate->rotation & DRM_MODE_REFLECT_X ? true : false; in vop2_plane_atomic_update()
1155 bool ymirror = pstate->rotation & DRM_MODE_REFLECT_Y ? true : false; in vop2_plane_atomic_update()
1156 bool rotate_270 = pstate->rotation & DRM_MODE_ROTATE_270; in vop2_plane_atomic_update()
1157 bool rotate_90 = pstate->rotation & DRM_MODE_ROTATE_90; in vop2_plane_atomic_update()
1171 if (!pstate->visible) { in vop2_plane_atomic_update()
1176 afbc_en = rockchip_afbc(plane, fb->modifier); in vop2_plane_atomic_update()
1178 offset = (src->x1 >> 16) * fb->format->cpp[0]; in vop2_plane_atomic_update()
1185 else if (pstate->rotation & DRM_MODE_REFLECT_Y) in vop2_plane_atomic_update()
1186 offset += ((src->y2 >> 16) - 1) * fb->pitches[0]; in vop2_plane_atomic_update()
1188 offset += (src->y1 >> 16) * fb->pitches[0]; in vop2_plane_atomic_update()
1190 rk_obj = to_rockchip_obj(fb->obj[0]); in vop2_plane_atomic_update()
1192 yrgb_mst = rk_obj->dma_addr + offset + fb->offsets[0]; in vop2_plane_atomic_update()
1193 if (fb->format->is_yuv) { in vop2_plane_atomic_update()
1194 int hsub = fb->format->hsub; in vop2_plane_atomic_update()
1195 int vsub = fb->format->vsub; in vop2_plane_atomic_update()
1197 offset = (src->x1 >> 16) * fb->format->cpp[1] / hsub; in vop2_plane_atomic_update()
1198 offset += (src->y1 >> 16) * fb->pitches[1] / vsub; in vop2_plane_atomic_update()
1200 if ((pstate->rotation & DRM_MODE_REFLECT_Y) && !afbc_en) in vop2_plane_atomic_update()
1201 offset += fb->pitches[1] * ((pstate->src_h >> 16) - 2) / vsub; in vop2_plane_atomic_update()
1203 rk_obj = to_rockchip_obj(fb->obj[0]); in vop2_plane_atomic_update()
1204 uv_mst = rk_obj->dma_addr + offset + fb->offsets[1]; in vop2_plane_atomic_update()
1211 if (dest->x1 + dsp_w > adjusted_mode->hdisplay) { in vop2_plane_atomic_update()
1212 drm_dbg_kms(vop2->drm, in vop2_plane_atomic_update()
1213 "vp%d %s dest->x1[%d] + dsp_w[%d] exceed mode hdisplay[%d]\n", in vop2_plane_atomic_update()
1214 vp->id, win->data->name, dest->x1, dsp_w, adjusted_mode->hdisplay); in vop2_plane_atomic_update()
1215 dsp_w = adjusted_mode->hdisplay - dest->x1; in vop2_plane_atomic_update()
1223 if (dest->y1 + dsp_h > adjusted_mode->vdisplay) { in vop2_plane_atomic_update()
1224 drm_dbg_kms(vop2->drm, in vop2_plane_atomic_update()
1225 "vp%d %s dest->y1[%d] + dsp_h[%d] exceed mode vdisplay[%d]\n", in vop2_plane_atomic_update()
1226 vp->id, win->data->name, dest->y1, dsp_h, adjusted_mode->vdisplay); in vop2_plane_atomic_update()
1227 dsp_h = adjusted_mode->vdisplay - dest->y1; in vop2_plane_atomic_update()
1237 if (!(win->data->feature & WIN_FEATURE_AFBDC)) { in vop2_plane_atomic_update()
1239 drm_dbg_kms(vop2->drm, "vp%d %s act_w[%d] MODE 16 == 1\n", in vop2_plane_atomic_update()
1240 vp->id, win->data->name, actual_w); in vop2_plane_atomic_update()
1241 actual_w -= 1; in vop2_plane_atomic_update()
1246 drm_dbg_kms(vop2->drm, "vp%d %s actual_w[%d] not 4 pixel aligned\n", in vop2_plane_atomic_update()
1247 vp->id, win->data->name, actual_w); in vop2_plane_atomic_update()
1251 act_info = (actual_h - 1) << 16 | ((actual_w - 1) & 0xffff); in vop2_plane_atomic_update()
1252 dsp_info = (dsp_h - 1) << 16 | ((dsp_w - 1) & 0xffff); in vop2_plane_atomic_update()
1254 format = vop2_convert_format(fb->format->format); in vop2_plane_atomic_update()
1257 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()
1258 vp->id, win->data->name, actual_w, actual_h, dsp_w, dsp_h, in vop2_plane_atomic_update()
1259 dest->x1, dest->y1, in vop2_plane_atomic_update()
1260 &fb->format->format, in vop2_plane_atomic_update()
1263 if (vop2->version > VOP_VERSION_RK3568) { in vop2_plane_atomic_update()
1264 vop2_win_write(win, VOP2_WIN_AXI_BUS_ID, win->data->axi_bus_id); in vop2_plane_atomic_update()
1265 vop2_win_write(win, VOP2_WIN_AXI_YRGB_R_ID, win->data->axi_yrgb_r_id); in vop2_plane_atomic_update()
1266 vop2_win_write(win, VOP2_WIN_AXI_UV_R_ID, win->data->axi_uv_r_id); in vop2_plane_atomic_update()
1269 if (vop2->version >= VOP_VERSION_RK3576) in vop2_plane_atomic_update()
1270 vop2_win_write(win, VOP2_WIN_VP_SEL, vp->id); in vop2_plane_atomic_update()
1279 block_w = fb->modifier & AFBC_FORMAT_MOD_BLOCK_SIZE_32x8 ? 32 : 16; in vop2_plane_atomic_update()
1281 afbc_format = vop2_convert_afbc_format(fb->format->format); in vop2_plane_atomic_update()
1284 if (fb->modifier & AFBC_FORMAT_MOD_YTR) in vop2_plane_atomic_update()
1293 stride = (fb->pitches[0] << 3) / bpp; in vop2_plane_atomic_update()
1295 drm_dbg_kms(vop2->drm, "vp%d %s stride[%d] not 64 pixel aligned\n", in vop2_plane_atomic_update()
1296 vp->id, win->data->name, stride); in vop2_plane_atomic_update()
1301 uv_swap = vop2_afbc_uv_swap(fb->format->format); in vop2_plane_atomic_update()
1311 if (fb->format->is_yuv && bpp == 10) in vop2_plane_atomic_update()
1326 if (vop2->version == VOP_VERSION_RK3568) in vop2_plane_atomic_update()
1331 if (fb->modifier & AFBC_FORMAT_MOD_SPLIT) in vop2_plane_atomic_update()
1336 if (vop2->version >= VOP_VERSION_RK3576) { in vop2_plane_atomic_update()
1345 vop2_win_write(win, VOP2_WIN_AFBC_PIC_OFFSET, ((src->x1 >> 16) | src->y1)); in vop2_plane_atomic_update()
1346 vop2_win_write(win, VOP2_WIN_AFBC_DSP_OFFSET, (dest->x1 | (dest->y1 << 16))); in vop2_plane_atomic_update()
1358 vop2_win_write(win, VOP2_WIN_YRGB_VIR, DIV_ROUND_UP(fb->pitches[0], 4)); in vop2_plane_atomic_update()
1372 rb_swap = vop2_win_rb_swap(fb->format->format); in vop2_plane_atomic_update()
1374 uv_swap = vop2_win_uv_swap(fb->format->format); in vop2_plane_atomic_update()
1377 if (fb->format->is_yuv) { in vop2_plane_atomic_update()
1378 vop2_win_write(win, VOP2_WIN_UV_VIR, DIV_ROUND_UP(fb->pitches[1], 4)); in vop2_plane_atomic_update()
1382 vop2_setup_scale(vop2, win, actual_w, actual_h, dsp_w, dsp_h, fb->format->format); in vop2_plane_atomic_update()
1387 vop2_win_write(win, VOP2_WIN_DSP_ST, dest->y1 << 16 | (dest->x1 & 0xffff)); in vop2_plane_atomic_update()
1391 dither_up = vop2_win_dither_up(fb->format->format); in vop2_plane_atomic_update()
1449 const struct vop2_video_port_data *vp_data = &vop2->data->vp[vp->id]; in vop2_crtc_write_gamma_lut()
1450 struct drm_color_lut *lut = crtc->state->gamma_lut->data; in vop2_crtc_write_gamma_lut()
1451 unsigned int i, bpc = ilog2(vp_data->gamma_lut_len); in vop2_crtc_write_gamma_lut()
1454 for (i = 0; i < crtc->gamma_size; i++) { in vop2_crtc_write_gamma_lut()
1459 writel(word, vop2->lut_regs + i * 4); in vop2_crtc_write_gamma_lut()
1468 FIELD_PREP(RK3588_LUT_PORT_SEL__GAMMA_AHB_WRITE_SEL, vp->id)); in vop2_crtc_atomic_set_gamma_seamless()
1483 vop2_writel(vop2, RK3568_LUT_PORT_SEL, vp->id); in vop2_crtc_atomic_set_gamma_rk356x()
1493 if (!vop2->lut_regs) in vop2_crtc_atomic_try_set_gamma()
1496 if (!crtc_state->gamma_lut) { in vop2_crtc_atomic_try_set_gamma()
1519 struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state); in vop2_dither_setup()
1521 switch (vcstate->bus_format) { in vop2_dither_setup()
1539 if (vcstate->output_mode != ROCKCHIP_OUT_MODE_AAAA) in vop2_dither_setup()
1549 struct vop2 *vop2 = vp->vop2; in vop2_post_config()
1550 struct drm_display_mode *mode = &crtc->state->adjusted_mode; in vop2_post_config()
1551 u16 vtotal = mode->crtc_vtotal; in vop2_post_config()
1552 u16 hdisplay = mode->crtc_hdisplay; in vop2_post_config()
1553 u16 hact_st = mode->crtc_htotal - mode->crtc_hsync_start; in vop2_post_config()
1554 u16 vdisplay = mode->crtc_vdisplay; in vop2_post_config()
1555 u16 vact_st = mode->crtc_vtotal - mode->crtc_vsync_start; in vop2_post_config()
1563 vop2->ops->setup_bg_dly(vp); in vop2_post_config()
1567 hact_st += hdisplay * (100 - left_margin) / 200; in vop2_post_config()
1572 vact_st += vdisplay * (100 - top_margin) / 200; in vop2_post_config()
1588 if (mode->flags & DRM_MODE_FLAG_INTERLACE) { in vop2_post_config()
1601 return us * mode->clock / mode->htotal / 1000; in us_to_vertical_line()
1608 struct vop2 *vop2 = vp->vop2; in vop2_crtc_atomic_enable()
1609 const struct vop2_data *vop2_data = vop2->data; in vop2_crtc_atomic_enable()
1610 const struct vop2_video_port_data *vp_data = &vop2_data->vp[vp->id]; in vop2_crtc_atomic_enable()
1612 struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state); in vop2_crtc_atomic_enable()
1613 struct drm_display_mode *mode = &crtc->state->adjusted_mode; in vop2_crtc_atomic_enable()
1614 unsigned long clock = mode->crtc_clock * 1000; in vop2_crtc_atomic_enable()
1615 u16 hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start; in vop2_crtc_atomic_enable()
1616 u16 hdisplay = mode->crtc_hdisplay; in vop2_crtc_atomic_enable()
1617 u16 htotal = mode->crtc_htotal; in vop2_crtc_atomic_enable()
1618 u16 hact_st = mode->crtc_htotal - mode->crtc_hsync_start; in vop2_crtc_atomic_enable()
1620 u16 vdisplay = mode->crtc_vdisplay; in vop2_crtc_atomic_enable()
1621 u16 vtotal = mode->crtc_vtotal; in vop2_crtc_atomic_enable()
1622 u16 vsync_len = mode->crtc_vsync_end - mode->crtc_vsync_start; in vop2_crtc_atomic_enable()
1623 u16 vact_st = mode->crtc_vtotal - mode->crtc_vsync_start; in vop2_crtc_atomic_enable()
1632 drm_dbg(vop2->drm, "Update mode to %dx%d%s%d, type: %d for vp%d\n", in vop2_crtc_atomic_enable()
1633 hdisplay, vdisplay, mode->flags & DRM_MODE_FLAG_INTERLACE ? "i" : "p", in vop2_crtc_atomic_enable()
1634 drm_mode_vrefresh(mode), vcstate->output_type, vp->id); in vop2_crtc_atomic_enable()
1638 ret = clk_prepare_enable(vp->dclk); in vop2_crtc_atomic_enable()
1640 drm_err(vop2->drm, "failed to enable dclk for video port%d - %d\n", in vop2_crtc_atomic_enable()
1641 vp->id, ret); in vop2_crtc_atomic_enable()
1646 if (!vop2->enable_count) in vop2_crtc_atomic_enable()
1649 vop2->enable_count++; in vop2_crtc_atomic_enable()
1651 vcstate->yuv_overlay = is_yuv_output(vcstate->bus_format); in vop2_crtc_atomic_enable()
1656 if (vcstate->bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE) in vop2_crtc_atomic_enable()
1658 if (mode->flags & DRM_MODE_FLAG_PHSYNC) in vop2_crtc_atomic_enable()
1660 if (mode->flags & DRM_MODE_FLAG_PVSYNC) in vop2_crtc_atomic_enable()
1663 drm_for_each_encoder_mask(encoder, crtc->dev, crtc_state->encoder_mask) { in vop2_crtc_atomic_enable()
1667 * for drive a high resolution(4KP120, 8K), vop on rk3588/rk3576 need in vop2_crtc_atomic_enable()
1669 * system cru may be the 1/2 or 1/4 of mode->clock. in vop2_crtc_atomic_enable()
1671 clock = vop2->ops->setup_intf_mux(vp, rkencoder->crtc_endpoint_id, polflags); in vop2_crtc_atomic_enable()
1679 if (vcstate->output_mode == ROCKCHIP_OUT_MODE_AAAA && in vop2_crtc_atomic_enable()
1680 !(vp_data->feature & VOP2_VP_FEATURE_OUTPUT_10BIT)) in vop2_crtc_atomic_enable()
1683 out_mode = vcstate->output_mode; in vop2_crtc_atomic_enable()
1687 if (vop2_output_uv_swap(vcstate->bus_format, vcstate->output_mode)) in vop2_crtc_atomic_enable()
1689 if (vop2_output_rg_swap(vop2, vcstate->bus_format)) in vop2_crtc_atomic_enable()
1692 if (vcstate->yuv_overlay) in vop2_crtc_atomic_enable()
1706 if (mode->flags & DRM_MODE_FLAG_INTERLACE) { in vop2_crtc_atomic_enable()
1724 vop2_writel(vop2, RK3568_VP_LINE_FLAG(vp->id), in vop2_crtc_atomic_enable()
1725 (act_end - us_to_vertical_line(mode, 0)) << 16 | act_end); in vop2_crtc_atomic_enable()
1729 if (mode->flags & DRM_MODE_FLAG_DBLCLK) { in vop2_crtc_atomic_enable()
1740 if ((vop2->pll_hdmiphy0 || vop2->pll_hdmiphy1) && clock <= VOP2_MAX_DCLK_RATE) { in vop2_crtc_atomic_enable()
1741 drm_for_each_encoder_mask(encoder, crtc->dev, crtc_state->encoder_mask) { in vop2_crtc_atomic_enable()
1744 if (rkencoder->crtc_endpoint_id == ROCKCHIP_VOP2_EP_HDMI0) { in vop2_crtc_atomic_enable()
1745 if (!vop2->pll_hdmiphy0) in vop2_crtc_atomic_enable()
1748 if (!vp->dclk_src) in vop2_crtc_atomic_enable()
1749 vp->dclk_src = clk_get_parent(vp->dclk); in vop2_crtc_atomic_enable()
1751 ret = clk_set_parent(vp->dclk, vop2->pll_hdmiphy0); in vop2_crtc_atomic_enable()
1753 drm_warn(vop2->drm, in vop2_crtc_atomic_enable()
1758 if (rkencoder->crtc_endpoint_id == ROCKCHIP_VOP2_EP_HDMI1) { in vop2_crtc_atomic_enable()
1759 if (!vop2->pll_hdmiphy1) in vop2_crtc_atomic_enable()
1762 if (!vp->dclk_src) in vop2_crtc_atomic_enable()
1763 vp->dclk_src = clk_get_parent(vp->dclk); in vop2_crtc_atomic_enable()
1765 ret = clk_set_parent(vp->dclk, vop2->pll_hdmiphy1); in vop2_crtc_atomic_enable()
1767 drm_warn(vop2->drm, in vop2_crtc_atomic_enable()
1774 clk_set_rate(vp->dclk, clock); in vop2_crtc_atomic_enable()
1794 struct vop2 *vop2 = vp->vop2; in vop2_crtc_atomic_check_gamma()
1797 if (!vp->vop2->lut_regs || !crtc_state->color_mgmt_changed || in vop2_crtc_atomic_check_gamma()
1798 !crtc_state->gamma_lut) in vop2_crtc_atomic_check_gamma()
1801 len = drm_color_lut_size(crtc_state->gamma_lut); in vop2_crtc_atomic_check_gamma()
1802 if (len != crtc->gamma_size) { in vop2_crtc_atomic_check_gamma()
1803 drm_dbg(vop2->drm, "Invalid LUT size; got %d, expected %d\n", in vop2_crtc_atomic_check_gamma()
1804 len, crtc->gamma_size); in vop2_crtc_atomic_check_gamma()
1805 return -EINVAL; in vop2_crtc_atomic_check_gamma()
1809 drm_info(vop2->drm, "Gamma LUT can be enabled for only one CRTC at a time\n"); in vop2_crtc_atomic_check_gamma()
1810 return -EINVAL; in vop2_crtc_atomic_check_gamma()
1832 if (nplanes > vp->nlayers) in vop2_crtc_atomic_check()
1833 return -EINVAL; in vop2_crtc_atomic_check()
1842 struct vop2 *vop2 = vp->vop2; in vop2_crtc_atomic_begin()
1844 vop2->ops->setup_overlay(vp); in vop2_crtc_atomic_begin()
1852 struct vop2 *vop2 = vp->vop2; in vop2_crtc_atomic_flush()
1855 if (!drm_atomic_crtc_needs_modeset(crtc_state) && crtc_state->color_mgmt_changed) in vop2_crtc_atomic_flush()
1862 spin_lock_irq(&crtc->dev->event_lock); in vop2_crtc_atomic_flush()
1864 if (crtc->state->event) { in vop2_crtc_atomic_flush()
1866 vp->event = crtc->state->event; in vop2_crtc_atomic_flush()
1867 crtc->state->event = NULL; in vop2_crtc_atomic_flush()
1870 spin_unlock_irq(&crtc->dev->event_lock); in vop2_crtc_atomic_flush()
1887 drm_connector_list_iter_begin(crtc->dev, &conn_iter); in vop2_dump_connector_on_crtc()
1889 if (crtc->state->connector_mask & drm_connector_mask(connector)) in vop2_dump_connector_on_crtc()
1890 seq_printf(s, " Connector: %s\n", connector->name); in vop2_dump_connector_on_crtc()
1898 struct drm_plane_state *pstate = plane->state; in vop2_plane_state_dump()
1910 seq_printf(s, " %s: %s\n", win->data->name, !pstate ? in vop2_plane_state_dump()
1911 "DISABLED" : pstate->crtc ? "ACTIVE" : "DISABLED"); in vop2_plane_state_dump()
1913 if (!pstate || !pstate->fb) in vop2_plane_state_dump()
1916 fb = pstate->fb; in vop2_plane_state_dump()
1917 src = &pstate->src; in vop2_plane_state_dump()
1918 dst = &pstate->dst; in vop2_plane_state_dump()
1919 xmirror = pstate->rotation & DRM_MODE_REFLECT_X ? true : false; in vop2_plane_state_dump()
1920 ymirror = pstate->rotation & DRM_MODE_REFLECT_Y ? true : false; in vop2_plane_state_dump()
1921 rotate_270 = pstate->rotation & DRM_MODE_ROTATE_270; in vop2_plane_state_dump()
1922 rotate_90 = pstate->rotation & DRM_MODE_ROTATE_90; in vop2_plane_state_dump()
1924 seq_printf(s, "\twin_id: %d\n", win->win_id); in vop2_plane_state_dump()
1927 &fb->format->format, in vop2_plane_state_dump()
1928 drm_is_afbc(fb->modifier) ? "[AFBC]" : "", in vop2_plane_state_dump()
1929 pstate->alpha >> 8); in vop2_plane_state_dump()
1932 seq_printf(s, "\tzpos: %d\n", pstate->normalized_zpos); in vop2_plane_state_dump()
1933 seq_printf(s, "\tsrc: pos[%d, %d] rect[%d x %d]\n", src->x1 >> 16, in vop2_plane_state_dump()
1934 src->y1 >> 16, drm_rect_width(src) >> 16, in vop2_plane_state_dump()
1936 seq_printf(s, "\tdst: pos[%d, %d] rect[%d x %d]\n", dst->x1, dst->y1, in vop2_plane_state_dump()
1939 for (i = 0; i < fb->format->num_planes; i++) { in vop2_plane_state_dump()
1940 obj = fb->obj[i]; in vop2_plane_state_dump()
1942 fb_addr = rk_obj->dma_addr + fb->offsets[i]; in vop2_plane_state_dump()
1945 i, &fb_addr, fb->pitches[i], fb->offsets[i]); in vop2_plane_state_dump()
1954 struct drm_crtc_state *cstate = crtc->state; in vop2_crtc_state_dump()
1960 seq_printf(s, "Video Port%d: %s\n", vp->id, !cstate ? in vop2_crtc_state_dump()
1961 "DISABLED" : cstate->active ? "ACTIVE" : "DISABLED"); in vop2_crtc_state_dump()
1963 if (!cstate || !cstate->active) in vop2_crtc_state_dump()
1966 mode = &crtc->state->adjusted_mode; in vop2_crtc_state_dump()
1968 interlaced = !!(mode->flags & DRM_MODE_FLAG_INTERLACE); in vop2_crtc_state_dump()
1971 seq_printf(s, "\tbus_format[%x]: %s\n", vcstate->bus_format, in vop2_crtc_state_dump()
1972 drm_get_bus_format_name(vcstate->bus_format)); in vop2_crtc_state_dump()
1973 seq_printf(s, "\toutput_mode[%x]", vcstate->output_mode); in vop2_crtc_state_dump()
1974 seq_printf(s, " color_space[%d]\n", vcstate->color_space); in vop2_crtc_state_dump()
1976 mode->hdisplay, mode->vdisplay, interlaced ? "i" : "p", in vop2_crtc_state_dump()
1979 mode->clock, mode->crtc_clock, mode->type, mode->flags); in vop2_crtc_state_dump()
1980 seq_printf(s, "\tH: %d %d %d %d\n", mode->hdisplay, mode->hsync_start, in vop2_crtc_state_dump()
1981 mode->hsync_end, mode->htotal); in vop2_crtc_state_dump()
1982 seq_printf(s, "\tV: %d %d %d %d\n", mode->vdisplay, mode->vsync_start, in vop2_crtc_state_dump()
1983 mode->vsync_end, mode->vtotal); in vop2_crtc_state_dump()
1994 struct drm_info_node *node = s->private; in vop2_summary_show()
1995 struct drm_minor *minor = node->minor; in vop2_summary_show()
1996 struct drm_device *drm_dev = minor->dev; in vop2_summary_show()
2015 if (dump->en_mask && active_only) { in vop2_regs_print()
2016 val = vop2_readl(vop2, dump->base + dump->en_reg); in vop2_regs_print()
2017 if ((val & dump->en_mask) != dump->en_val) in vop2_regs_print()
2021 seq_printf(s, "\n%s:\n", dump->name); in vop2_regs_print()
2023 start = vop2->res->start + dump->base; in vop2_regs_print()
2024 for (i = 0; i < dump->size >> 2; i += 4) { in vop2_regs_print()
2026 vop2_readl(vop2, dump->base + (4 * i)), in vop2_regs_print()
2027 vop2_readl(vop2, dump->base + (4 * (i + 1))), in vop2_regs_print()
2028 vop2_readl(vop2, dump->base + (4 * (i + 2))), in vop2_regs_print()
2029 vop2_readl(vop2, dump->base + (4 * (i + 3)))); in vop2_regs_print()
2035 struct drm_info_node *node = s->private; in __vop2_regs_dump()
2036 struct vop2 *vop2 = node->info_ent->data; in __vop2_regs_dump()
2037 struct drm_minor *minor = node->minor; in __vop2_regs_dump()
2038 struct drm_device *drm_dev = minor->dev; in __vop2_regs_dump()
2044 regcache_drop_region(vop2->map, 0, vop2_regmap_config.max_register); in __vop2_regs_dump()
2046 if (vop2->enable_count) { in __vop2_regs_dump()
2047 for (i = 0; i < vop2->data->regs_dump_size; i++) { in __vop2_regs_dump()
2048 dump = &vop2->data->regs_dump[i]; in __vop2_regs_dump()
2052 seq_puts(s, "VOP disabled\n"); in __vop2_regs_dump()
2082 root = debugfs_create_dir("vop2", minor->debugfs_root); in vop2_debugfs_init()
2096 struct vop2 *vop2 = vp->vop2; in vop2_crtc_late_register()
2099 vop2_debugfs_init(vop2, crtc->dev->primary); in vop2_crtc_late_register()
2108 if (WARN_ON(!crtc->state)) in vop2_crtc_duplicate_state()
2111 vcstate = kmemdup(to_rockchip_crtc_state(crtc->state), in vop2_crtc_duplicate_state()
2116 __drm_atomic_helper_crtc_duplicate_state(crtc, &vcstate->base); in vop2_crtc_duplicate_state()
2118 return &vcstate->base; in vop2_crtc_duplicate_state()
2126 __drm_atomic_helper_crtc_destroy_state(&vcstate->base); in vop2_crtc_destroy_state()
2135 if (crtc->state) in vop2_crtc_reset()
2136 vop2_crtc_destroy_state(crtc, crtc->state); in vop2_crtc_reset()
2139 __drm_atomic_helper_crtc_reset(crtc, &vcstate->base); in vop2_crtc_reset()
2159 struct vop2 *vop2 = vp->vop2; in rk3576_vp_isr()
2160 struct drm_crtc *crtc = &vp->crtc; in rk3576_vp_isr()
2164 if (!pm_runtime_get_if_in_use(vop2->dev)) in rk3576_vp_isr()
2167 irqs = vop2_readl(vop2, RK3568_VP_INT_STATUS(vp->id)); in rk3576_vp_isr()
2168 vop2_writel(vop2, RK3568_VP_INT_CLR(vp->id), irqs << 16 | irqs); in rk3576_vp_isr()
2171 complete(&vp->dsp_hold_completion); in rk3576_vp_isr()
2177 spin_lock(&crtc->dev->event_lock); in rk3576_vp_isr()
2178 if (vp->event) { in rk3576_vp_isr()
2181 if (!(val & BIT(vp->id))) { in rk3576_vp_isr()
2182 drm_crtc_send_vblank_event(crtc, vp->event); in rk3576_vp_isr()
2183 vp->event = NULL; in rk3576_vp_isr()
2187 spin_unlock(&crtc->dev->event_lock); in rk3576_vp_isr()
2193 drm_err_ratelimited(vop2->drm, "POST_BUF_EMPTY irq err at vp%d\n", vp->id); in rk3576_vp_isr()
2197 pm_runtime_put(vop2->dev); in rk3576_vp_isr()
2205 const struct vop2_data *vop2_data = vop2->data; in vop2_isr()
2211 * The irq is shared with the iommu. If the runtime-pm state of the in vop2_isr()
2212 * vop2-device is disabled the irq has to be targeted at the iommu. in vop2_isr()
2214 if (!pm_runtime_get_if_in_use(vop2->dev)) in vop2_isr()
2217 if (vop2->version < VOP_VERSION_RK3576) { in vop2_isr()
2218 for (i = 0; i < vop2_data->nr_vps; i++) { in vop2_isr()
2219 struct vop2_video_port *vp = &vop2->vps[i]; in vop2_isr()
2220 struct drm_crtc *crtc = &vp->crtc; in vop2_isr()
2223 irqs = vop2_readl(vop2, RK3568_VP_INT_STATUS(vp->id)); in vop2_isr()
2224 vop2_writel(vop2, RK3568_VP_INT_CLR(vp->id), irqs << 16 | irqs); in vop2_isr()
2227 complete(&vp->dsp_hold_completion); in vop2_isr()
2233 spin_lock(&crtc->dev->event_lock); in vop2_isr()
2234 if (vp->event) { in vop2_isr()
2237 if (!(val & BIT(vp->id))) { in vop2_isr()
2238 drm_crtc_send_vblank_event(crtc, vp->event); in vop2_isr()
2239 vp->event = NULL; in vop2_isr()
2243 spin_unlock(&crtc->dev->event_lock); in vop2_isr()
2249 drm_err_ratelimited(vop2->drm, in vop2_isr()
2251 vp->id); in vop2_isr()
2264 drm_err_ratelimited(vop2->drm, "BUS_ERROR irq err\n"); in vop2_isr()
2269 pm_runtime_put(vop2->dev); in vop2_isr()
2277 const struct vop2_win_data *win_data = win->data; in vop2_plane_init()
2283 ret = drm_universal_plane_init(vop2->drm, &win->base, possible_crtcs, in vop2_plane_init()
2284 &vop2_plane_funcs, win_data->formats, in vop2_plane_init()
2285 win_data->nformats, in vop2_plane_init()
2286 win_data->format_modifiers, in vop2_plane_init()
2287 win->type, win_data->name); in vop2_plane_init()
2289 drm_err(vop2->drm, "failed to initialize plane %d\n", ret); in vop2_plane_init()
2293 drm_plane_helper_add(&win->base, &vop2_plane_helper_funcs); in vop2_plane_init()
2295 if (win->data->supported_rotations) in vop2_plane_init()
2296 drm_plane_create_rotation_property(&win->base, DRM_MODE_ROTATE_0, in vop2_plane_init()
2298 win->data->supported_rotations); in vop2_plane_init()
2299 drm_plane_create_alpha_property(&win->base); in vop2_plane_init()
2300 drm_plane_create_blend_mode_property(&win->base, blend_caps); in vop2_plane_init()
2301 drm_plane_create_zpos_property(&win->base, win->win_id, 0, in vop2_plane_init()
2302 vop2->registered_num_wins - 1); in vop2_plane_init()
2311 * And RK3566 share the same vop version with Rk3568, so we
2316 struct vop2 *vop2 = win->vop2; in vop2_is_mirror_win()
2318 if (vop2->data->soc_id == 3566) { in vop2_is_mirror_win()
2319 switch (win->data->phys_id) { in vop2_is_mirror_win()
2334 const struct vop2_data *vop2_data = vop2->data; in vop2_create_crtcs()
2335 struct drm_device *drm = vop2->drm; in vop2_create_crtcs()
2336 struct device *dev = vop2->dev; in vop2_create_crtcs()
2345 for (i = 0; i < vop2_data->nr_vps; i++) { in vop2_create_crtcs()
2350 vp_data = &vop2_data->vp[i]; in vop2_create_crtcs()
2351 vp = &vop2->vps[i]; in vop2_create_crtcs()
2352 vp->vop2 = vop2; in vop2_create_crtcs()
2353 vp->id = vp_data->id; in vop2_create_crtcs()
2354 vp->data = vp_data; in vop2_create_crtcs()
2356 snprintf(dclk_name, sizeof(dclk_name), "dclk_vp%d", vp->id); in vop2_create_crtcs()
2357 vp->dclk = devm_clk_get(vop2->dev, dclk_name); in vop2_create_crtcs()
2358 if (IS_ERR(vp->dclk)) in vop2_create_crtcs()
2359 return dev_err_probe(drm->dev, PTR_ERR(vp->dclk), in vop2_create_crtcs()
2362 np = of_graph_get_remote_node(dev->of_node, i, -1); in vop2_create_crtcs()
2364 drm_dbg(vop2->drm, "%s: No remote for vp%d\n", __func__, i); in vop2_create_crtcs()
2369 port = of_graph_get_port_by_id(dev->of_node, i); in vop2_create_crtcs()
2371 return dev_err_probe(drm->dev, -ENOENT, in vop2_create_crtcs()
2373 vp->crtc.port = port; in vop2_create_crtcs()
2379 for (i = 0; i < vop2_data->nr_vps; i++) { in vop2_create_crtcs()
2380 vp = &vop2->vps[i]; in vop2_create_crtcs()
2382 if (!vp->crtc.port) in vop2_create_crtcs()
2385 for (j = 0; j < vop2->registered_num_wins; j++) { in vop2_create_crtcs()
2386 win = &vop2->win[j]; in vop2_create_crtcs()
2389 if (win->base.type == DRM_PLANE_TYPE_PRIMARY) in vop2_create_crtcs()
2393 if (!(win->data->possible_vp_mask & BIT(vp->id))) in vop2_create_crtcs()
2399 if (win->type == DRM_PLANE_TYPE_PRIMARY) { in vop2_create_crtcs()
2401 vp->primary_plane = win; in vop2_create_crtcs()
2404 return dev_err_probe(drm->dev, ret, in vop2_create_crtcs()
2406 win->data->name); in vop2_create_crtcs()
2412 if (!vp->primary_plane) in vop2_create_crtcs()
2413 return dev_err_probe(drm->dev, -ENOENT, in vop2_create_crtcs()
2418 for (i = 0; i < vop2->registered_num_wins; i++) { in vop2_create_crtcs()
2419 win = &vop2->win[i]; in vop2_create_crtcs()
2422 if (win->base.type == DRM_PLANE_TYPE_PRIMARY) in vop2_create_crtcs()
2428 win->type = DRM_PLANE_TYPE_OVERLAY; in vop2_create_crtcs()
2432 for (j = 0; j < vop2_data->nr_vps; j++) { in vop2_create_crtcs()
2433 vp = &vop2->vps[j]; in vop2_create_crtcs()
2435 if (!vp->crtc.port) in vop2_create_crtcs()
2438 if (win->data->possible_vp_mask & BIT(vp->id)) in vop2_create_crtcs()
2445 return dev_err_probe(drm->dev, ret, "failed to init overlay plane %s\n", in vop2_create_crtcs()
2446 win->data->name); in vop2_create_crtcs()
2449 for (i = 0; i < vop2_data->nr_vps; i++) { in vop2_create_crtcs()
2450 vp = &vop2->vps[i]; in vop2_create_crtcs()
2452 if (!vp->crtc.port) in vop2_create_crtcs()
2455 plane = &vp->primary_plane->base; in vop2_create_crtcs()
2457 ret = drm_crtc_init_with_planes(drm, &vp->crtc, plane, NULL, in vop2_create_crtcs()
2459 "video_port%d", vp->id); in vop2_create_crtcs()
2461 return dev_err_probe(drm->dev, ret, in vop2_create_crtcs()
2464 drm_crtc_helper_add(&vp->crtc, &vop2_crtc_helper_funcs); in vop2_create_crtcs()
2465 if (vop2->lut_regs) { in vop2_create_crtcs()
2466 const struct vop2_video_port_data *vp_data = &vop2_data->vp[vp->id]; in vop2_create_crtcs()
2468 drm_mode_crtc_set_gamma_size(&vp->crtc, vp_data->gamma_lut_len); in vop2_create_crtcs()
2469 drm_crtc_enable_color_mgmt(&vp->crtc, 0, false, vp_data->gamma_lut_len); in vop2_create_crtcs()
2471 init_completion(&vp->dsp_hold_completion); in vop2_create_crtcs()
2479 for (i = 0; i < vop2->data->nr_vps; i++) { in vop2_create_crtcs()
2480 struct vop2_video_port *vp = &vop2->vps[i]; in vop2_create_crtcs()
2482 if (vp->crtc.port) in vop2_create_crtcs()
2483 vp->nlayers = vop2_data->win_size / nvps; in vop2_create_crtcs()
2491 struct drm_device *drm = vop2->drm; in vop2_destroy_crtcs()
2492 struct list_head *crtc_list = &drm->mode_config.crtc_list; in vop2_destroy_crtcs()
2493 struct list_head *plane_list = &drm->mode_config.plane_list; in vop2_destroy_crtcs()
2505 of_node_put(crtc->port); in vop2_destroy_crtcs()
2512 struct device_node *node = vop2->dev->of_node; in vop2_find_rgb_encoder()
2516 for (i = 0; i < vop2->data->nr_vps; i++) { in vop2_find_rgb_encoder()
2526 return -ENOENT; in vop2_find_rgb_encoder()
2532 struct vop2 *vop2 = win->vop2; in vop2_regmap_init()
2538 regs[i].reg + win->offset : regs[i].reg, in vop2_regmap_init()
2543 win->reg[i] = devm_regmap_field_alloc(vop2->dev, vop2->map, field); in vop2_regmap_init()
2544 if (IS_ERR(win->reg[i])) in vop2_regmap_init()
2545 return PTR_ERR(win->reg[i]); in vop2_regmap_init()
2553 const struct vop2_data *vop2_data = vop2->data; in vop2_win_init()
2557 for (i = 0; i < vop2_data->win_size; i++) { in vop2_win_init()
2558 const struct vop2_win_data *win_data = &vop2_data->win[i]; in vop2_win_init()
2560 win = &vop2->win[i]; in vop2_win_init()
2561 win->data = win_data; in vop2_win_init()
2562 win->type = win_data->type; in vop2_win_init()
2563 win->offset = win_data->base; in vop2_win_init()
2564 win->win_id = i; in vop2_win_init()
2565 win->vop2 = vop2; in vop2_win_init()
2567 ret = vop2_regmap_init(win, vop2->data->cluster_reg, in vop2_win_init()
2568 vop2->data->nr_cluster_regs); in vop2_win_init()
2570 ret = vop2_regmap_init(win, vop2->data->smart_reg, in vop2_win_init()
2571 vop2->data->nr_smart_regs); in vop2_win_init()
2576 vop2->registered_num_wins = vop2_data->win_size; in vop2_win_init()
2584 * read-modify-write these registers mark them as non-volatile. This
2619 return -ENODEV; in vop2_bind()
2622 alloc_size = struct_size(vop2, win, vop2_data->win_size); in vop2_bind()
2625 return -ENOMEM; in vop2_bind()
2627 vop2->dev = dev; in vop2_bind()
2628 vop2->data = vop2_data; in vop2_bind()
2629 vop2->ops = vop2_data->ops; in vop2_bind()
2630 vop2->version = vop2_data->version; in vop2_bind()
2631 vop2->drm = drm; in vop2_bind()
2635 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "vop"); in vop2_bind()
2637 return dev_err_probe(drm->dev, -EINVAL, in vop2_bind()
2640 vop2->res = res; in vop2_bind()
2641 vop2->regs = devm_ioremap_resource(dev, res); in vop2_bind()
2642 if (IS_ERR(vop2->regs)) in vop2_bind()
2643 return PTR_ERR(vop2->regs); in vop2_bind()
2644 vop2->len = resource_size(res); in vop2_bind()
2646 vop2->map = devm_regmap_init_mmio(dev, vop2->regs, &vop2_regmap_config); in vop2_bind()
2647 if (IS_ERR(vop2->map)) in vop2_bind()
2648 return PTR_ERR(vop2->map); in vop2_bind()
2654 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "gamma-lut"); in vop2_bind()
2656 vop2->lut_regs = devm_ioremap_resource(dev, res); in vop2_bind()
2657 if (IS_ERR(vop2->lut_regs)) in vop2_bind()
2658 return PTR_ERR(vop2->lut_regs); in vop2_bind()
2660 if (vop2_data->feature & VOP2_FEATURE_HAS_SYS_GRF) { in vop2_bind()
2661 vop2->sys_grf = syscon_regmap_lookup_by_phandle(dev->of_node, "rockchip,grf"); in vop2_bind()
2662 if (IS_ERR(vop2->sys_grf)) in vop2_bind()
2663 return dev_err_probe(drm->dev, PTR_ERR(vop2->sys_grf), in vop2_bind()
2667 if (vop2_data->feature & VOP2_FEATURE_HAS_VOP_GRF) { in vop2_bind()
2668 vop2->vop_grf = syscon_regmap_lookup_by_phandle(dev->of_node, "rockchip,vop-grf"); in vop2_bind()
2669 if (IS_ERR(vop2->vop_grf)) in vop2_bind()
2670 return dev_err_probe(drm->dev, PTR_ERR(vop2->vop_grf), in vop2_bind()
2674 if (vop2_data->feature & VOP2_FEATURE_HAS_VO1_GRF) { in vop2_bind()
2675 vop2->vo1_grf = syscon_regmap_lookup_by_phandle(dev->of_node, "rockchip,vo1-grf"); in vop2_bind()
2676 if (IS_ERR(vop2->vo1_grf)) in vop2_bind()
2677 return dev_err_probe(drm->dev, PTR_ERR(vop2->vo1_grf), in vop2_bind()
2681 if (vop2_data->feature & VOP2_FEATURE_HAS_SYS_PMU) { in vop2_bind()
2682 vop2->sys_pmu = syscon_regmap_lookup_by_phandle(dev->of_node, "rockchip,pmu"); in vop2_bind()
2683 if (IS_ERR(vop2->sys_pmu)) in vop2_bind()
2684 return dev_err_probe(drm->dev, PTR_ERR(vop2->sys_pmu), in vop2_bind()
2688 vop2->hclk = devm_clk_get(vop2->dev, "hclk"); in vop2_bind()
2689 if (IS_ERR(vop2->hclk)) in vop2_bind()
2690 return dev_err_probe(drm->dev, PTR_ERR(vop2->hclk), in vop2_bind()
2693 vop2->aclk = devm_clk_get(vop2->dev, "aclk"); in vop2_bind()
2694 if (IS_ERR(vop2->aclk)) in vop2_bind()
2695 return dev_err_probe(drm->dev, PTR_ERR(vop2->aclk), in vop2_bind()
2698 vop2->pclk = devm_clk_get_optional(vop2->dev, "pclk_vop"); in vop2_bind()
2699 if (IS_ERR(vop2->pclk)) in vop2_bind()
2700 return dev_err_probe(drm->dev, PTR_ERR(vop2->pclk), in vop2_bind()
2703 vop2->pll_hdmiphy0 = devm_clk_get_optional(vop2->dev, "pll_hdmiphy0"); in vop2_bind()
2704 if (IS_ERR(vop2->pll_hdmiphy0)) in vop2_bind()
2705 return dev_err_probe(drm->dev, PTR_ERR(vop2->pll_hdmiphy0), in vop2_bind()
2708 vop2->pll_hdmiphy1 = devm_clk_get_optional(vop2->dev, "pll_hdmiphy1"); in vop2_bind()
2709 if (IS_ERR(vop2->pll_hdmiphy1)) in vop2_bind()
2710 return dev_err_probe(drm->dev, PTR_ERR(vop2->pll_hdmiphy1), in vop2_bind()
2713 vop2->irq = platform_get_irq(pdev, 0); in vop2_bind()
2714 if (vop2->irq < 0) in vop2_bind()
2715 return dev_err_probe(drm->dev, vop2->irq, "cannot find irq for vop2\n"); in vop2_bind()
2717 mutex_init(&vop2->vop2_lock); in vop2_bind()
2718 mutex_init(&vop2->ovl_lock); in vop2_bind()
2720 ret = devm_request_irq(dev, vop2->irq, vop2_isr, IRQF_SHARED, dev_name(dev), vop2); in vop2_bind()
2728 if (vop2->version >= VOP_VERSION_RK3576) { in vop2_bind()
2734 const char *irq_name = devm_kasprintf(dev, GFP_KERNEL, "vp%d", vp->id); in vop2_bind()
2737 return -ENOMEM; in vop2_bind()
2741 return dev_err_probe(drm->dev, vp_irq, in vop2_bind()
2742 "cannot find irq for vop2 vp%d\n", vp->id); in vop2_bind()
2747 dev_err_probe(drm->dev, ret, in vop2_bind()
2748 "request irq for vop2 vp%d failed\n", vp->id); in vop2_bind()
2754 vop2->rgb = rockchip_rgb_init(dev, &vop2->vps[ret].crtc, in vop2_bind()
2755 vop2->drm, ret); in vop2_bind()
2756 if (IS_ERR(vop2->rgb)) { in vop2_bind()
2757 if (PTR_ERR(vop2->rgb) == -EPROBE_DEFER) { in vop2_bind()
2758 ret = PTR_ERR(vop2->rgb); in vop2_bind()
2761 vop2->rgb = NULL; in vop2_bind()
2765 rockchip_drm_dma_init_device(vop2->drm, vop2->dev); in vop2_bind()
2767 pm_runtime_enable(&pdev->dev); in vop2_bind()
2783 if (vop2->rgb) in vop2_unbind()
2784 rockchip_rgb_fini(vop2->rgb); in vop2_unbind()