Lines Matching +full:dclk +full:- +full:div
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,
160 struct clk *dclk; member
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()
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()
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()
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()
742 if (!(win->data->feature & WIN_FEATURE_AFBDC)) { in vop2_setup_scale()
744 drm_dbg(vop2->drm, "%s dst_w[%d] should align as 2 pixel\n", in vop2_setup_scale()
745 win->data->name, dst_w); in vop2_setup_scale()
767 if (info->is_yuv) { in vop2_setup_scale()
768 cbcr_src_w /= info->hsub; in vop2_setup_scale()
769 cbcr_src_h /= info->vsub; in vop2_setup_scale()
823 * 1. YUV(2020) --> Y2R->2020To709->R2Y --> YUV_OUTPUT(601/709)
824 * RGB --> R2Y __/
826 * 2. YUV(2020) --> bypasss --> YUV_OUTPUT(2020)
827 * RGB --> 709To2020->R2Y __/
829 * 3. YUV(2020) --> Y2R->2020To709 --> RGB_OUTPUT(709)
830 * RGB --> R2Y __/
832 * 4. YUV(601/709)-> Y2R->709To2020->R2Y --> YUV_OUTPUT(2020)
833 * RGB --> 709To2020->R2Y __/
835 * 5. YUV(601/709)-> bypass --> YUV_OUTPUT(709)
836 * RGB --> R2Y __/
838 * 6. YUV(601/709)-> bypass --> YUV_OUTPUT(601)
839 * RGB --> R2Y(601) __/
841 * 7. YUV --> Y2R(709) --> RGB_OUTPUT(709)
842 * RGB --> bypass __/
844 * 8. RGB --> 709To2020->R2Y --> YUV_OUTPUT(2020)
846 * 9. RGB --> R2Y(709) --> YUV_OUTPUT(709)
848 * 10. RGB --> R2Y(601) --> YUV_OUTPUT(601)
850 * 11. RGB --> bypass --> RGB_OUTPUT(709)
857 struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(vp->crtc.state); in vop2_setup_csc_mode()
858 int is_input_yuv = pstate->fb->format->is_yuv; in vop2_setup_csc_mode()
859 int is_output_yuv = is_yuv_output(vcstate->bus_format); in vop2_setup_csc_mode()
861 int output_csc = vcstate->color_space; in vop2_setup_csc_mode()
886 struct vop2 *vop2 = vp->vop2; in vop2_crtc_enable_irq()
888 vop2_writel(vop2, RK3568_VP_INT_CLR(vp->id), irq << 16 | irq); in vop2_crtc_enable_irq()
889 vop2_writel(vop2, RK3568_VP_INT_EN(vp->id), irq << 16 | irq); in vop2_crtc_enable_irq()
894 struct vop2 *vop2 = vp->vop2; in vop2_crtc_disable_irq()
896 vop2_writel(vop2, RK3568_VP_INT_EN(vp->id), irq << 16); in vop2_crtc_disable_irq()
903 ret = clk_prepare_enable(vop2->hclk); in vop2_core_clks_prepare_enable()
905 drm_err(vop2->drm, "failed to enable hclk - %d\n", ret); in vop2_core_clks_prepare_enable()
909 ret = clk_prepare_enable(vop2->aclk); in vop2_core_clks_prepare_enable()
911 drm_err(vop2->drm, "failed to enable aclk - %d\n", ret); in vop2_core_clks_prepare_enable()
915 ret = clk_prepare_enable(vop2->pclk); in vop2_core_clks_prepare_enable()
917 drm_err(vop2->drm, "failed to enable pclk - %d\n", ret); in vop2_core_clks_prepare_enable()
923 clk_disable_unprepare(vop2->aclk); in vop2_core_clks_prepare_enable()
925 clk_disable_unprepare(vop2->hclk); in vop2_core_clks_prepare_enable()
945 ret = pm_runtime_resume_and_get(vop2->dev); in vop2_enable()
947 drm_err(vop2->drm, "failed to get pm runtime: %d\n", ret); in vop2_enable()
953 pm_runtime_put_sync(vop2->dev); in vop2_enable()
957 ret = rockchip_drm_dma_attach_device(vop2->drm, vop2->dev); in vop2_enable()
959 drm_err(vop2->drm, "failed to attach dma mapping, %d\n", ret); in vop2_enable()
963 if (vop2->data->soc_id == 3566) in vop2_enable()
966 if (vop2->data->soc_id == 3588) in vop2_enable()
975 regmap_clear_bits(vop2->map, RK3568_SYS_AUTO_GATING_CTRL, in vop2_enable()
990 rockchip_drm_dma_detach_device(vop2->drm, vop2->dev); in vop2_disable()
992 pm_runtime_put_sync(vop2->dev); in vop2_disable()
994 regcache_drop_region(vop2->map, 0, vop2_regmap_config.max_register); in vop2_disable()
996 clk_disable_unprepare(vop2->pclk); in vop2_disable()
997 clk_disable_unprepare(vop2->aclk); in vop2_disable()
998 clk_disable_unprepare(vop2->hclk); in vop2_disable()
1005 struct vop2 *vop2 = vp->vop2; in vop2_crtc_atomic_disable()
1023 reinit_completion(&vp->dsp_hold_completion); in vop2_crtc_atomic_disable()
1029 ret = wait_for_completion_timeout(&vp->dsp_hold_completion, in vop2_crtc_atomic_disable()
1032 drm_info(vop2->drm, "wait for vp%d dsp_hold timeout\n", vp->id); in vop2_crtc_atomic_disable()
1036 clk_disable_unprepare(vp->dclk); in vop2_crtc_atomic_disable()
1038 vop2->enable_count--; in vop2_crtc_atomic_disable()
1040 if (!vop2->enable_count) in vop2_crtc_atomic_disable()
1045 if (crtc->state->event && !crtc->state->active) { in vop2_crtc_atomic_disable()
1046 spin_lock_irq(&crtc->dev->event_lock); in vop2_crtc_atomic_disable()
1047 drm_crtc_send_vblank_event(crtc, crtc->state->event); in vop2_crtc_atomic_disable()
1048 spin_unlock_irq(&crtc->dev->event_lock); in vop2_crtc_atomic_disable()
1050 crtc->state->event = NULL; in vop2_crtc_atomic_disable()
1058 struct drm_framebuffer *fb = pstate->fb; in vop2_plane_atomic_check()
1059 struct drm_crtc *crtc = pstate->crtc; in vop2_plane_atomic_check()
1064 struct drm_rect *dest = &pstate->dst; in vop2_plane_atomic_check()
1065 struct drm_rect *src = &pstate->src; in vop2_plane_atomic_check()
1075 vop2 = vp->vop2; in vop2_plane_atomic_check()
1076 vop2_data = vop2->data; in vop2_plane_atomic_check()
1078 cstate = drm_atomic_get_existing_crtc_state(pstate->state, crtc); in vop2_plane_atomic_check()
1080 return -EINVAL; in vop2_plane_atomic_check()
1088 if (!pstate->visible) in vop2_plane_atomic_check()
1091 format = vop2_convert_format(fb->format->format); in vop2_plane_atomic_check()
1097 drm_err(vop2->drm, "Invalid size: %dx%d->%dx%d, min size is 4x4\n", in vop2_plane_atomic_check()
1100 pstate->visible = false; in vop2_plane_atomic_check()
1104 if (drm_rect_width(src) >> 16 > vop2_data->max_input.width || in vop2_plane_atomic_check()
1105 drm_rect_height(src) >> 16 > vop2_data->max_input.height) { in vop2_plane_atomic_check()
1106 drm_err(vop2->drm, "Invalid source: %dx%d. max input: %dx%d\n", in vop2_plane_atomic_check()
1109 vop2_data->max_input.width, in vop2_plane_atomic_check()
1110 vop2_data->max_input.height); in vop2_plane_atomic_check()
1111 return -EINVAL; in vop2_plane_atomic_check()
1118 if (fb->format->is_yuv && ((pstate->src.x1 >> 16) % 2)) { in vop2_plane_atomic_check()
1119 drm_err(vop2->drm, "Invalid Source: Yuv format not support odd xpos\n"); in vop2_plane_atomic_check()
1120 return -EINVAL; in vop2_plane_atomic_check()
1131 struct vop2 *vop2 = win->vop2; in vop2_plane_atomic_disable()
1133 drm_dbg(vop2->drm, "%s disable\n", win->data->name); in vop2_plane_atomic_disable()
1137 if (old_pstate && !old_pstate->crtc) in vop2_plane_atomic_disable()
1150 struct drm_plane_state *pstate = plane->state; in vop2_plane_setup_color_key()
1151 struct drm_framebuffer *fb = pstate->fb; in vop2_plane_setup_color_key()
1158 if (!(color_key & VOP2_COLOR_KEY_MASK) || fb->format->is_yuv) { in vop2_plane_setup_color_key()
1163 switch (fb->format->format) { in vop2_plane_setup_color_key()
1197 struct drm_plane_state *pstate = plane->state; in vop2_plane_atomic_update()
1198 struct drm_crtc *crtc = pstate->crtc; in vop2_plane_atomic_update()
1201 struct drm_display_mode *adjusted_mode = &crtc->state->adjusted_mode; in vop2_plane_atomic_update()
1202 struct vop2 *vop2 = win->vop2; in vop2_plane_atomic_update()
1203 struct drm_framebuffer *fb = pstate->fb; in vop2_plane_atomic_update()
1204 u32 bpp = vop2_get_bpp(fb->format); in vop2_plane_atomic_update()
1211 struct drm_rect *src = &pstate->src; in vop2_plane_atomic_update()
1212 struct drm_rect *dest = &pstate->dst; in vop2_plane_atomic_update()
1216 bool xmirror = pstate->rotation & DRM_MODE_REFLECT_X ? true : false; in vop2_plane_atomic_update()
1217 bool ymirror = pstate->rotation & DRM_MODE_REFLECT_Y ? true : false; in vop2_plane_atomic_update()
1218 bool rotate_270 = pstate->rotation & DRM_MODE_ROTATE_270; in vop2_plane_atomic_update()
1219 bool rotate_90 = pstate->rotation & DRM_MODE_ROTATE_90; in vop2_plane_atomic_update()
1233 if (!pstate->visible) { in vop2_plane_atomic_update()
1238 afbc_en = rockchip_afbc(plane, fb->modifier); in vop2_plane_atomic_update()
1240 offset = (src->x1 >> 16) * fb->format->cpp[0]; in vop2_plane_atomic_update()
1247 else if (pstate->rotation & DRM_MODE_REFLECT_Y) in vop2_plane_atomic_update()
1248 offset += ((src->y2 >> 16) - 1) * fb->pitches[0]; in vop2_plane_atomic_update()
1250 offset += (src->y1 >> 16) * fb->pitches[0]; in vop2_plane_atomic_update()
1252 rk_obj = to_rockchip_obj(fb->obj[0]); in vop2_plane_atomic_update()
1254 yrgb_mst = rk_obj->dma_addr + offset + fb->offsets[0]; in vop2_plane_atomic_update()
1255 if (fb->format->is_yuv) { in vop2_plane_atomic_update()
1256 int hsub = fb->format->hsub; in vop2_plane_atomic_update()
1257 int vsub = fb->format->vsub; in vop2_plane_atomic_update()
1259 offset = (src->x1 >> 16) * fb->format->cpp[1] / hsub; in vop2_plane_atomic_update()
1260 offset += (src->y1 >> 16) * fb->pitches[1] / vsub; in vop2_plane_atomic_update()
1262 if ((pstate->rotation & DRM_MODE_REFLECT_Y) && !afbc_en) in vop2_plane_atomic_update()
1263 offset += fb->pitches[1] * ((pstate->src_h >> 16) - 2) / vsub; in vop2_plane_atomic_update()
1265 rk_obj = to_rockchip_obj(fb->obj[0]); in vop2_plane_atomic_update()
1266 uv_mst = rk_obj->dma_addr + offset + fb->offsets[1]; in vop2_plane_atomic_update()
1273 if (dest->x1 + dsp_w > adjusted_mode->hdisplay) { in vop2_plane_atomic_update()
1274 drm_err(vop2->drm, "vp%d %s dest->x1[%d] + dsp_w[%d] exceed mode hdisplay[%d]\n", in vop2_plane_atomic_update()
1275 vp->id, win->data->name, dest->x1, dsp_w, adjusted_mode->hdisplay); in vop2_plane_atomic_update()
1276 dsp_w = adjusted_mode->hdisplay - dest->x1; in vop2_plane_atomic_update()
1284 if (dest->y1 + dsp_h > adjusted_mode->vdisplay) { in vop2_plane_atomic_update()
1285 drm_err(vop2->drm, "vp%d %s dest->y1[%d] + dsp_h[%d] exceed mode vdisplay[%d]\n", in vop2_plane_atomic_update()
1286 vp->id, win->data->name, dest->y1, dsp_h, adjusted_mode->vdisplay); in vop2_plane_atomic_update()
1287 dsp_h = adjusted_mode->vdisplay - dest->y1; in vop2_plane_atomic_update()
1297 if (!(win->data->feature & WIN_FEATURE_AFBDC)) { in vop2_plane_atomic_update()
1299 drm_err(vop2->drm, "vp%d %s act_w[%d] MODE 16 == 1\n", in vop2_plane_atomic_update()
1300 vp->id, win->data->name, actual_w); in vop2_plane_atomic_update()
1301 actual_w -= 1; in vop2_plane_atomic_update()
1306 drm_err(vop2->drm, "vp%d %s actual_w[%d] not 4 pixel aligned\n", in vop2_plane_atomic_update()
1307 vp->id, win->data->name, actual_w); in vop2_plane_atomic_update()
1311 act_info = (actual_h - 1) << 16 | ((actual_w - 1) & 0xffff); in vop2_plane_atomic_update()
1312 dsp_info = (dsp_h - 1) << 16 | ((dsp_w - 1) & 0xffff); in vop2_plane_atomic_update()
1314 format = vop2_convert_format(fb->format->format); in vop2_plane_atomic_update()
1317 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()
1318 vp->id, win->data->name, actual_w, actual_h, dsp_w, dsp_h, in vop2_plane_atomic_update()
1319 dest->x1, dest->y1, in vop2_plane_atomic_update()
1320 &fb->format->format, in vop2_plane_atomic_update()
1330 afbc_format = vop2_convert_afbc_format(fb->format->format); in vop2_plane_atomic_update()
1333 if (fb->modifier & AFBC_FORMAT_MOD_YTR) in vop2_plane_atomic_update()
1342 stride = (fb->pitches[0] << 3) / bpp; in vop2_plane_atomic_update()
1344 drm_err(vop2->drm, "vp%d %s stride[%d] not 64 pixel aligned\n", in vop2_plane_atomic_update()
1345 vp->id, win->data->name, stride); in vop2_plane_atomic_update()
1347 uv_swap = vop2_afbc_uv_swap(fb->format->format); in vop2_plane_atomic_update()
1357 if (fb->format->is_yuv && bpp == 10) in vop2_plane_atomic_update()
1372 if (vop2->data->soc_id == 3566 || vop2->data->soc_id == 3568) in vop2_plane_atomic_update()
1382 vop2_win_write(win, VOP2_WIN_AFBC_PIC_OFFSET, ((src->x1 >> 16) | src->y1)); in vop2_plane_atomic_update()
1383 vop2_win_write(win, VOP2_WIN_AFBC_DSP_OFFSET, (dest->x1 | (dest->y1 << 16))); in vop2_plane_atomic_update()
1395 vop2_win_write(win, VOP2_WIN_YRGB_VIR, DIV_ROUND_UP(fb->pitches[0], 4)); in vop2_plane_atomic_update()
1409 rb_swap = vop2_win_rb_swap(fb->format->format); in vop2_plane_atomic_update()
1412 uv_swap = vop2_win_uv_swap(fb->format->format); in vop2_plane_atomic_update()
1416 if (fb->format->is_yuv) { in vop2_plane_atomic_update()
1417 vop2_win_write(win, VOP2_WIN_UV_VIR, DIV_ROUND_UP(fb->pitches[1], 4)); in vop2_plane_atomic_update()
1421 vop2_setup_scale(vop2, win, actual_w, actual_h, dsp_w, dsp_h, fb->format->format); in vop2_plane_atomic_update()
1426 vop2_win_write(win, VOP2_WIN_DSP_ST, dest->y1 << 16 | (dest->x1 & 0xffff)); in vop2_plane_atomic_update()
1430 dither_up = vop2_win_dither_up(fb->format->format); in vop2_plane_atomic_update()
1487 struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state); in vop2_dither_setup()
1489 switch (vcstate->bus_format) { in vop2_dither_setup()
1507 if (vcstate->output_mode != ROCKCHIP_OUT_MODE_AAAA) in vop2_dither_setup()
1517 struct drm_display_mode *mode = &crtc->state->adjusted_mode; in vop2_post_config()
1518 u16 vtotal = mode->crtc_vtotal; in vop2_post_config()
1519 u16 hdisplay = mode->crtc_hdisplay; in vop2_post_config()
1520 u16 hact_st = mode->crtc_htotal - mode->crtc_hsync_start; in vop2_post_config()
1521 u16 vdisplay = mode->crtc_vdisplay; in vop2_post_config()
1522 u16 vact_st = mode->crtc_vtotal - mode->crtc_vsync_start; in vop2_post_config()
1527 u16 hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start; in vop2_post_config()
1533 bg_dly = vp->data->pre_scan_max_dly[3]; in vop2_post_config()
1534 vop2_writel(vp->vop2, RK3568_VP_BG_MIX_CTRL(vp->id), in vop2_post_config()
1537 pre_scan_dly = ((bg_dly + (hdisplay >> 1) - 1) << 16) | hsync_len; in vop2_post_config()
1542 hact_st += hdisplay * (100 - left_margin) / 200; in vop2_post_config()
1547 vact_st += vdisplay * (100 - top_margin) / 200; in vop2_post_config()
1563 if (mode->flags & DRM_MODE_FLAG_INTERLACE) { in vop2_post_config()
1576 struct vop2 *vop2 = vp->vop2; in rk3568_set_intf_mux()
1577 struct drm_crtc *crtc = &vp->crtc; in rk3568_set_intf_mux()
1587 FIELD_PREP(RK3568_SYS_DSP_INFACE_EN_RGB_MUX, vp->id); in rk3568_set_intf_mux()
1591 regmap_write(vop2->sys_grf, RK3568_GRF_VO_CON1, BIT(3 + 16) | BIT(3)); in rk3568_set_intf_mux()
1593 regmap_write(vop2->sys_grf, RK3568_GRF_VO_CON1, BIT(3 + 16)); in rk3568_set_intf_mux()
1598 FIELD_PREP(RK3568_SYS_DSP_INFACE_EN_HDMI_MUX, vp->id); in rk3568_set_intf_mux()
1605 FIELD_PREP(RK3568_SYS_DSP_INFACE_EN_EDP_MUX, vp->id); in rk3568_set_intf_mux()
1612 FIELD_PREP(RK3568_SYS_DSP_INFACE_EN_MIPI0_MUX, vp->id); in rk3568_set_intf_mux()
1619 FIELD_PREP(RK3568_SYS_DSP_INFACE_EN_MIPI1_MUX, vp->id); in rk3568_set_intf_mux()
1626 FIELD_PREP(RK3568_SYS_DSP_INFACE_EN_LVDS0_MUX, vp->id); in rk3568_set_intf_mux()
1633 FIELD_PREP(RK3568_SYS_DSP_INFACE_EN_LVDS1_MUX, vp->id); in rk3568_set_intf_mux()
1638 drm_err(vop2->drm, "Invalid interface id %d on vp%d\n", id, vp->id); in rk3568_set_intf_mux()
1647 return crtc->state->adjusted_mode.crtc_clock * 1000LL; in rk3568_set_intf_mux()
1651 * calc the dclk on rk3588
1652 * the available div of dclk is 1, 2, 4
1676 struct vop2 *vop2 = vp->vop2; in rk3588_calc_cru_cfg()
1677 struct drm_crtc *crtc = &vp->crtc; in rk3588_calc_cru_cfg()
1678 struct drm_display_mode *adjusted_mode = &crtc->state->adjusted_mode; in rk3588_calc_cru_cfg()
1679 struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state); in rk3588_calc_cru_cfg()
1680 int output_mode = vcstate->output_mode; in rk3588_calc_cru_cfg()
1681 unsigned long v_pixclk = adjusted_mode->crtc_clock * 1000LL; /* video timing pixclk */ in rk3588_calc_cru_cfg()
1726 drm_err(vop2->drm, "DP dclk_out_rate out of range, dclk_out_rate: %ld KHZ\n", in rk3588_calc_cru_cfg()
1743 drm_err(vop2->drm, "MIPI dclk out of range, dclk_out_rate: %ld KHZ\n", in rk3588_calc_cru_cfg()
1762 drm_dbg(vop2->drm, "dclk: %ld, pixclk_div: %d, dclk_div: %d\n", in rk3588_calc_cru_cfg()
1796 struct vop2 *vop2 = vp->vop2; in rk3588_set_intf_mux()
1799 u32 die, dip, div, vp_clk_div, val; in rk3588_set_intf_mux() local
1811 div = vop2_readl(vop2, RK3568_DSP_IF_CTRL); in rk3588_set_intf_mux()
1815 div &= ~RK3588_DSP_IF_EDP_HDMI0_DCLK_DIV; in rk3588_set_intf_mux()
1816 div &= ~RK3588_DSP_IF_EDP_HDMI0_PCLK_DIV; in rk3588_set_intf_mux()
1817 div |= FIELD_PREP(RK3588_DSP_IF_EDP_HDMI0_DCLK_DIV, if_dclk_div); in rk3588_set_intf_mux()
1818 div |= FIELD_PREP(RK3588_DSP_IF_EDP_HDMI0_PCLK_DIV, if_pixclk_div); in rk3588_set_intf_mux()
1821 FIELD_PREP(RK3588_SYS_DSP_INFACE_EN_EDP_HDMI0_MUX, vp->id); in rk3588_set_intf_mux()
1823 regmap_write(vop2->vop_grf, RK3588_GRF_VOP_CON2, HIWORD_UPDATE(1, 1, 1)); in rk3588_set_intf_mux()
1824 regmap_write(vop2->vo1_grf, RK3588_GRF_VO1_CON0, HIWORD_UPDATE(val, 6, 5)); in rk3588_set_intf_mux()
1827 div &= ~RK3588_DSP_IF_EDP_HDMI1_DCLK_DIV; in rk3588_set_intf_mux()
1828 div &= ~RK3588_DSP_IF_EDP_HDMI1_PCLK_DIV; in rk3588_set_intf_mux()
1829 div |= FIELD_PREP(RK3588_DSP_IF_EDP_HDMI1_DCLK_DIV, if_dclk_div); in rk3588_set_intf_mux()
1830 div |= FIELD_PREP(RK3588_DSP_IF_EDP_HDMI1_PCLK_DIV, if_pixclk_div); in rk3588_set_intf_mux()
1833 FIELD_PREP(RK3588_SYS_DSP_INFACE_EN_EDP_HDMI1_MUX, vp->id); in rk3588_set_intf_mux()
1835 regmap_write(vop2->vop_grf, RK3588_GRF_VOP_CON2, HIWORD_UPDATE(1, 4, 4)); in rk3588_set_intf_mux()
1836 regmap_write(vop2->vo1_grf, RK3588_GRF_VO1_CON0, HIWORD_UPDATE(val, 8, 7)); in rk3588_set_intf_mux()
1839 div &= ~RK3588_DSP_IF_EDP_HDMI0_DCLK_DIV; in rk3588_set_intf_mux()
1840 div &= ~RK3588_DSP_IF_EDP_HDMI0_PCLK_DIV; in rk3588_set_intf_mux()
1841 div |= FIELD_PREP(RK3588_DSP_IF_EDP_HDMI0_DCLK_DIV, if_dclk_div); in rk3588_set_intf_mux()
1842 div |= FIELD_PREP(RK3588_DSP_IF_EDP_HDMI0_PCLK_DIV, if_pixclk_div); in rk3588_set_intf_mux()
1845 FIELD_PREP(RK3588_SYS_DSP_INFACE_EN_EDP_HDMI0_MUX, vp->id); in rk3588_set_intf_mux()
1846 regmap_write(vop2->vop_grf, RK3588_GRF_VOP_CON2, HIWORD_UPDATE(1, 0, 0)); in rk3588_set_intf_mux()
1849 div &= ~RK3588_DSP_IF_EDP_HDMI1_DCLK_DIV; in rk3588_set_intf_mux()
1850 div &= ~RK3588_DSP_IF_EDP_HDMI1_PCLK_DIV; in rk3588_set_intf_mux()
1851 div |= FIELD_PREP(RK3588_DSP_IF_EDP_HDMI0_DCLK_DIV, if_dclk_div); in rk3588_set_intf_mux()
1852 div |= FIELD_PREP(RK3588_DSP_IF_EDP_HDMI0_PCLK_DIV, if_pixclk_div); in rk3588_set_intf_mux()
1855 FIELD_PREP(RK3588_SYS_DSP_INFACE_EN_EDP_HDMI1_MUX, vp->id); in rk3588_set_intf_mux()
1856 regmap_write(vop2->vop_grf, RK3588_GRF_VOP_CON2, HIWORD_UPDATE(1, 3, 3)); in rk3588_set_intf_mux()
1859 div &= ~RK3588_DSP_IF_MIPI0_PCLK_DIV; in rk3588_set_intf_mux()
1860 div |= FIELD_PREP(RK3588_DSP_IF_MIPI0_PCLK_DIV, if_pixclk_div); in rk3588_set_intf_mux()
1862 val = rk3588_get_mipi_port_mux(vp->id); in rk3588_set_intf_mux()
1867 div &= ~RK3588_DSP_IF_MIPI1_PCLK_DIV; in rk3588_set_intf_mux()
1868 div |= FIELD_PREP(RK3588_DSP_IF_MIPI1_PCLK_DIV, if_pixclk_div); in rk3588_set_intf_mux()
1870 val = rk3588_get_mipi_port_mux(vp->id); in rk3588_set_intf_mux()
1877 FIELD_PREP(RK3588_SYS_DSP_INFACE_EN_DP0_MUX, vp->id); in rk3588_set_intf_mux()
1884 FIELD_PREP(RK3588_SYS_DSP_INFACE_EN_MIPI1_MUX, vp->id); in rk3588_set_intf_mux()
1889 drm_err(vop2->drm, "Invalid interface id %d on vp%d\n", id, vp->id); in rk3588_set_intf_mux()
1897 vop2_writel(vop2, RK3568_DSP_IF_CTRL, div); in rk3588_set_intf_mux()
1905 struct vop2 *vop2 = vp->vop2; in vop2_set_intf_mux()
1907 if (vop2->data->soc_id == 3566 || vop2->data->soc_id == 3568) in vop2_set_intf_mux()
1909 else if (vop2->data->soc_id == 3588) in vop2_set_intf_mux()
1917 return us * mode->clock / mode->htotal / 1000; in us_to_vertical_line()
1924 struct vop2 *vop2 = vp->vop2; in vop2_crtc_atomic_enable()
1925 const struct vop2_data *vop2_data = vop2->data; in vop2_crtc_atomic_enable()
1926 const struct vop2_video_port_data *vp_data = &vop2_data->vp[vp->id]; in vop2_crtc_atomic_enable()
1928 struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state); in vop2_crtc_atomic_enable()
1929 struct drm_display_mode *mode = &crtc->state->adjusted_mode; in vop2_crtc_atomic_enable()
1930 unsigned long clock = mode->crtc_clock * 1000; in vop2_crtc_atomic_enable()
1931 u16 hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start; in vop2_crtc_atomic_enable()
1932 u16 hdisplay = mode->crtc_hdisplay; in vop2_crtc_atomic_enable()
1933 u16 htotal = mode->crtc_htotal; in vop2_crtc_atomic_enable()
1934 u16 hact_st = mode->crtc_htotal - mode->crtc_hsync_start; in vop2_crtc_atomic_enable()
1936 u16 vdisplay = mode->crtc_vdisplay; in vop2_crtc_atomic_enable()
1937 u16 vtotal = mode->crtc_vtotal; in vop2_crtc_atomic_enable()
1938 u16 vsync_len = mode->crtc_vsync_end - mode->crtc_vsync_start; in vop2_crtc_atomic_enable()
1939 u16 vact_st = mode->crtc_vtotal - mode->crtc_vsync_start; in vop2_crtc_atomic_enable()
1948 drm_dbg(vop2->drm, "Update mode to %dx%d%s%d, type: %d for vp%d\n", in vop2_crtc_atomic_enable()
1949 hdisplay, vdisplay, mode->flags & DRM_MODE_FLAG_INTERLACE ? "i" : "p", in vop2_crtc_atomic_enable()
1950 drm_mode_vrefresh(mode), vcstate->output_type, vp->id); in vop2_crtc_atomic_enable()
1954 ret = clk_prepare_enable(vp->dclk); in vop2_crtc_atomic_enable()
1956 drm_err(vop2->drm, "failed to enable dclk for video port%d - %d\n", in vop2_crtc_atomic_enable()
1957 vp->id, ret); in vop2_crtc_atomic_enable()
1962 if (!vop2->enable_count) in vop2_crtc_atomic_enable()
1965 vop2->enable_count++; in vop2_crtc_atomic_enable()
1967 vcstate->yuv_overlay = is_yuv_output(vcstate->bus_format); in vop2_crtc_atomic_enable()
1972 if (vcstate->bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE) in vop2_crtc_atomic_enable()
1974 if (mode->flags & DRM_MODE_FLAG_PHSYNC) in vop2_crtc_atomic_enable()
1976 if (mode->flags & DRM_MODE_FLAG_PVSYNC) in vop2_crtc_atomic_enable()
1979 drm_for_each_encoder_mask(encoder, crtc->dev, crtc_state->encoder_mask) { in vop2_crtc_atomic_enable()
1984 * process multi(1/2/4/8) pixels per cycle, so the dclk feed by the in vop2_crtc_atomic_enable()
1985 * system cru may be the 1/2 or 1/4 of mode->clock. in vop2_crtc_atomic_enable()
1987 clock = vop2_set_intf_mux(vp, rkencoder->crtc_endpoint_id, polflags); in vop2_crtc_atomic_enable()
1995 if (vcstate->output_mode == ROCKCHIP_OUT_MODE_AAAA && in vop2_crtc_atomic_enable()
1996 !(vp_data->feature & VOP2_VP_FEATURE_OUTPUT_10BIT)) in vop2_crtc_atomic_enable()
1999 out_mode = vcstate->output_mode; in vop2_crtc_atomic_enable()
2003 if (vop2_output_uv_swap(vcstate->bus_format, vcstate->output_mode)) in vop2_crtc_atomic_enable()
2005 if (vop2_output_rg_swap(vop2, vcstate->bus_format)) in vop2_crtc_atomic_enable()
2008 if (vcstate->yuv_overlay) in vop2_crtc_atomic_enable()
2022 if (mode->flags & DRM_MODE_FLAG_INTERLACE) { in vop2_crtc_atomic_enable()
2040 vop2_writel(vop2, RK3568_VP_LINE_FLAG(vp->id), in vop2_crtc_atomic_enable()
2041 (act_end - us_to_vertical_line(mode, 0)) << 16 | act_end); in vop2_crtc_atomic_enable()
2045 if (mode->flags & DRM_MODE_FLAG_DBLCLK) { in vop2_crtc_atomic_enable()
2052 clk_set_rate(vp->dclk, clock); in vop2_crtc_atomic_enable()
2076 if (nplanes > vp->nlayers) in vop2_crtc_atomic_check()
2077 return -EINVAL; in vop2_crtc_atomic_check()
2090 int src_glb_alpha_en = is_opaque(alpha_config->src_glb_alpha_value) ? 0 : 1; in vop2_parse_alpha()
2091 int dst_glb_alpha_en = is_opaque(alpha_config->dst_glb_alpha_value) ? 0 : 1; in vop2_parse_alpha()
2092 int src_color_mode = alpha_config->src_premulti_en ? in vop2_parse_alpha()
2094 int dst_color_mode = alpha_config->dst_premulti_en ? in vop2_parse_alpha()
2097 alpha->src_color_ctrl.val = 0; in vop2_parse_alpha()
2098 alpha->dst_color_ctrl.val = 0; in vop2_parse_alpha()
2099 alpha->src_alpha_ctrl.val = 0; in vop2_parse_alpha()
2100 alpha->dst_alpha_ctrl.val = 0; in vop2_parse_alpha()
2102 if (!alpha_config->src_pixel_alpha_en) in vop2_parse_alpha()
2103 alpha->src_color_ctrl.bits.blend_mode = ALPHA_GLOBAL; in vop2_parse_alpha()
2104 else if (alpha_config->src_pixel_alpha_en && !src_glb_alpha_en) in vop2_parse_alpha()
2105 alpha->src_color_ctrl.bits.blend_mode = ALPHA_PER_PIX; in vop2_parse_alpha()
2107 alpha->src_color_ctrl.bits.blend_mode = ALPHA_PER_PIX_GLOBAL; in vop2_parse_alpha()
2109 alpha->src_color_ctrl.bits.alpha_en = 1; in vop2_parse_alpha()
2111 if (alpha->src_color_ctrl.bits.blend_mode == ALPHA_GLOBAL) { in vop2_parse_alpha()
2112 alpha->src_color_ctrl.bits.color_mode = src_color_mode; in vop2_parse_alpha()
2113 alpha->src_color_ctrl.bits.factor_mode = SRC_FAC_ALPHA_SRC_GLOBAL; in vop2_parse_alpha()
2114 } else if (alpha->src_color_ctrl.bits.blend_mode == ALPHA_PER_PIX) { in vop2_parse_alpha()
2115 alpha->src_color_ctrl.bits.color_mode = src_color_mode; in vop2_parse_alpha()
2116 alpha->src_color_ctrl.bits.factor_mode = SRC_FAC_ALPHA_ONE; in vop2_parse_alpha()
2118 alpha->src_color_ctrl.bits.color_mode = ALPHA_SRC_PRE_MUL; in vop2_parse_alpha()
2119 alpha->src_color_ctrl.bits.factor_mode = SRC_FAC_ALPHA_SRC_GLOBAL; in vop2_parse_alpha()
2121 alpha->src_color_ctrl.bits.glb_alpha = alpha_config->src_glb_alpha_value >> 8; in vop2_parse_alpha()
2122 alpha->src_color_ctrl.bits.alpha_mode = ALPHA_STRAIGHT; in vop2_parse_alpha()
2123 alpha->src_color_ctrl.bits.alpha_cal_mode = ALPHA_SATURATION; in vop2_parse_alpha()
2125 alpha->dst_color_ctrl.bits.alpha_mode = ALPHA_STRAIGHT; in vop2_parse_alpha()
2126 alpha->dst_color_ctrl.bits.alpha_cal_mode = ALPHA_SATURATION; in vop2_parse_alpha()
2127 alpha->dst_color_ctrl.bits.blend_mode = ALPHA_GLOBAL; in vop2_parse_alpha()
2128 alpha->dst_color_ctrl.bits.glb_alpha = alpha_config->dst_glb_alpha_value >> 8; in vop2_parse_alpha()
2129 alpha->dst_color_ctrl.bits.color_mode = dst_color_mode; in vop2_parse_alpha()
2130 alpha->dst_color_ctrl.bits.factor_mode = ALPHA_SRC_INVERSE; in vop2_parse_alpha()
2132 alpha->src_alpha_ctrl.bits.alpha_mode = ALPHA_STRAIGHT; in vop2_parse_alpha()
2133 alpha->src_alpha_ctrl.bits.blend_mode = alpha->src_color_ctrl.bits.blend_mode; in vop2_parse_alpha()
2134 alpha->src_alpha_ctrl.bits.alpha_cal_mode = ALPHA_SATURATION; in vop2_parse_alpha()
2135 alpha->src_alpha_ctrl.bits.factor_mode = ALPHA_ONE; in vop2_parse_alpha()
2137 alpha->dst_alpha_ctrl.bits.alpha_mode = ALPHA_STRAIGHT; in vop2_parse_alpha()
2138 if (alpha_config->dst_pixel_alpha_en && !dst_glb_alpha_en) in vop2_parse_alpha()
2139 alpha->dst_alpha_ctrl.bits.blend_mode = ALPHA_PER_PIX; in vop2_parse_alpha()
2141 alpha->dst_alpha_ctrl.bits.blend_mode = ALPHA_PER_PIX_GLOBAL; in vop2_parse_alpha()
2142 alpha->dst_alpha_ctrl.bits.alpha_cal_mode = ALPHA_NO_SATURATION; in vop2_parse_alpha()
2143 alpha->dst_alpha_ctrl.bits.factor_mode = ALPHA_SRC_INVERSE; in vop2_parse_alpha()
2153 vp = &vop2->vps[i]; in vop2_find_start_mixer_id_for_vp()
2154 used_layer += hweight32(vp->win_mask); in vop2_find_start_mixer_id_for_vp()
2162 u32 offset = (main_win->data->phys_id * 0x10); in vop2_setup_cluster_alpha()
2172 bottom_win_pstate = main_win->base.state; in vop2_setup_cluster_alpha()
2174 dst_glb_alpha_val = main_win->base.state->alpha; in vop2_setup_cluster_alpha()
2176 if (!bottom_win_pstate->fb) in vop2_setup_cluster_alpha()
2200 struct vop2 *vop2 = vp->vop2; in vop2_setup_alpha()
2212 mixer_id = vop2_find_start_mixer_id_for_vp(vop2, vp->id); in vop2_setup_alpha()
2215 drm_atomic_crtc_for_each_plane(plane, &vp->crtc) { in vop2_setup_alpha()
2218 if (plane->state->normalized_zpos == 0 && in vop2_setup_alpha()
2219 !is_opaque(plane->state->alpha) && in vop2_setup_alpha()
2227 dst_global_alpha = plane->state->alpha; in vop2_setup_alpha()
2231 drm_atomic_crtc_for_each_plane(plane, &vp->crtc) { in vop2_setup_alpha()
2233 int zpos = plane->state->normalized_zpos; in vop2_setup_alpha()
2235 if (plane->state->pixel_blend_mode == DRM_MODE_BLEND_PREMULTI) in vop2_setup_alpha()
2240 plane = &win->base; in vop2_setup_alpha()
2241 fb = plane->state->fb; in vop2_setup_alpha()
2243 pixel_alpha_en = fb->format->has_alpha; in vop2_setup_alpha()
2249 /* Cd = Cs + (1 - As) * Cd * Agd */ in vop2_setup_alpha()
2252 alpha_config.src_glb_alpha_value = plane->state->alpha; in vop2_setup_alpha()
2261 /* Cd = Cs + (1 - As) * Cd */ in vop2_setup_alpha()
2264 alpha_config.src_glb_alpha_value = plane->state->alpha; in vop2_setup_alpha()
2270 offset = (mixer_id + zpos - 1) * 0x10; in vop2_setup_alpha()
2281 if (vp->id == 0) { in vop2_setup_alpha()
2307 struct vop2 *vop2 = vp->vop2; in vop2_setup_layer_mixer()
2314 struct vop2_video_port *vp0 = &vop2->vps[0]; in vop2_setup_layer_mixer()
2315 struct vop2_video_port *vp1 = &vop2->vps[1]; in vop2_setup_layer_mixer()
2316 struct vop2_video_port *vp2 = &vop2->vps[2]; in vop2_setup_layer_mixer()
2317 struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(vp->crtc.state); in vop2_setup_layer_mixer()
2321 if (vcstate->yuv_overlay) in vop2_setup_layer_mixer()
2322 ovl_ctrl |= RK3568_OVL_CTRL__YUV_MODE(vp->id); in vop2_setup_layer_mixer()
2324 ovl_ctrl &= ~RK3568_OVL_CTRL__YUV_MODE(vp->id); in vop2_setup_layer_mixer()
2331 if (vp0->nlayers) in vop2_setup_layer_mixer()
2333 vp0->nlayers - 1); in vop2_setup_layer_mixer()
2337 if (vp1->nlayers) in vop2_setup_layer_mixer()
2339 (vp0->nlayers + vp1->nlayers - 1)); in vop2_setup_layer_mixer()
2343 if (vp2->nlayers) in vop2_setup_layer_mixer()
2345 (vp2->nlayers + vp1->nlayers + vp0->nlayers - 1)); in vop2_setup_layer_mixer()
2352 for (i = 0; i < vp->id; i++) in vop2_setup_layer_mixer()
2353 ofs += vop2->vps[i].nlayers; in vop2_setup_layer_mixer()
2356 drm_atomic_crtc_for_each_plane(plane, &vp->crtc) { in vop2_setup_layer_mixer()
2359 switch (win->data->phys_id) { in vop2_setup_layer_mixer()
2362 port_sel |= FIELD_PREP(RK3568_OVL_PORT_SEL__CLUSTER0, vp->id); in vop2_setup_layer_mixer()
2366 port_sel |= FIELD_PREP(RK3568_OVL_PORT_SEL__CLUSTER1, vp->id); in vop2_setup_layer_mixer()
2370 port_sel |= FIELD_PREP(RK3588_OVL_PORT_SEL__CLUSTER2, vp->id); in vop2_setup_layer_mixer()
2374 port_sel |= FIELD_PREP(RK3588_OVL_PORT_SEL__CLUSTER3, vp->id); in vop2_setup_layer_mixer()
2378 port_sel |= FIELD_PREP(RK3568_OVL_PORT_SEL__ESMART0, vp->id); in vop2_setup_layer_mixer()
2382 port_sel |= FIELD_PREP(RK3568_OVL_PORT_SEL__ESMART1, vp->id); in vop2_setup_layer_mixer()
2386 port_sel |= FIELD_PREP(RK3588_OVL_PORT_SEL__ESMART2, vp->id); in vop2_setup_layer_mixer()
2390 port_sel |= FIELD_PREP(RK3588_OVL_PORT_SEL__ESMART3, vp->id); in vop2_setup_layer_mixer()
2394 port_sel |= FIELD_PREP(RK3568_OVL_PORT_SEL__SMART0, vp->id); in vop2_setup_layer_mixer()
2398 port_sel |= FIELD_PREP(RK3568_OVL_PORT_SEL__SMART1, vp->id); in vop2_setup_layer_mixer()
2402 layer_sel &= ~RK3568_OVL_LAYER_SEL__LAYER(plane->state->normalized_zpos + ofs, in vop2_setup_layer_mixer()
2404 layer_sel |= RK3568_OVL_LAYER_SEL__LAYER(plane->state->normalized_zpos + ofs, in vop2_setup_layer_mixer()
2405 win->data->layer_sel_id); in vop2_setup_layer_mixer()
2410 for (; nlayer < vp->nlayers; nlayer++) { in vop2_setup_layer_mixer()
2425 for (i = 0; i < vop2->data->win_size; i++) { in vop2_setup_dly_for_windows()
2428 win = &vop2->win[i]; in vop2_setup_dly_for_windows()
2429 dly = win->delay; in vop2_setup_dly_for_windows()
2431 switch (win->data->phys_id) { in vop2_setup_dly_for_windows()
2463 struct vop2 *vop2 = vp->vop2; in vop2_crtc_atomic_begin()
2466 vp->win_mask = 0; in vop2_crtc_atomic_begin()
2471 win->delay = win->data->dly[VOP2_DLY_MODE_DEFAULT]; in vop2_crtc_atomic_begin()
2473 vp->win_mask |= BIT(win->data->phys_id); in vop2_crtc_atomic_begin()
2479 if (!vp->win_mask) in vop2_crtc_atomic_begin()
2496 spin_lock_irq(&crtc->dev->event_lock); in vop2_crtc_atomic_flush()
2498 if (crtc->state->event) { in vop2_crtc_atomic_flush()
2500 vp->event = crtc->state->event; in vop2_crtc_atomic_flush()
2501 crtc->state->event = NULL; in vop2_crtc_atomic_flush()
2504 spin_unlock_irq(&crtc->dev->event_lock); in vop2_crtc_atomic_flush()
2520 if (WARN_ON(!crtc->state)) in vop2_crtc_duplicate_state()
2523 vcstate = kmemdup(to_rockchip_crtc_state(crtc->state), in vop2_crtc_duplicate_state()
2528 __drm_atomic_helper_crtc_duplicate_state(crtc, &vcstate->base); in vop2_crtc_duplicate_state()
2530 return &vcstate->base; in vop2_crtc_duplicate_state()
2538 __drm_atomic_helper_crtc_destroy_state(&vcstate->base); in vop2_crtc_destroy_state()
2547 if (crtc->state) in vop2_crtc_reset()
2548 vop2_crtc_destroy_state(crtc, crtc->state); in vop2_crtc_reset()
2551 __drm_atomic_helper_crtc_reset(crtc, &vcstate->base); in vop2_crtc_reset()
2570 const struct vop2_data *vop2_data = vop2->data; in vop2_isr()
2576 * The irq is shared with the iommu. If the runtime-pm state of the in vop2_isr()
2577 * vop2-device is disabled the irq has to be targeted at the iommu. in vop2_isr()
2579 if (!pm_runtime_get_if_in_use(vop2->dev)) in vop2_isr()
2582 for (i = 0; i < vop2_data->nr_vps; i++) { in vop2_isr()
2583 struct vop2_video_port *vp = &vop2->vps[i]; in vop2_isr()
2584 struct drm_crtc *crtc = &vp->crtc; in vop2_isr()
2587 irqs = vop2_readl(vop2, RK3568_VP_INT_STATUS(vp->id)); in vop2_isr()
2588 vop2_writel(vop2, RK3568_VP_INT_CLR(vp->id), irqs << 16 | irqs); in vop2_isr()
2591 complete(&vp->dsp_hold_completion); in vop2_isr()
2597 spin_lock(&crtc->dev->event_lock); in vop2_isr()
2598 if (vp->event) { in vop2_isr()
2601 if (!(val & BIT(vp->id))) { in vop2_isr()
2602 drm_crtc_send_vblank_event(crtc, vp->event); in vop2_isr()
2603 vp->event = NULL; in vop2_isr()
2607 spin_unlock(&crtc->dev->event_lock); in vop2_isr()
2613 drm_err_ratelimited(vop2->drm, in vop2_isr()
2615 vp->id); in vop2_isr()
2627 drm_err_ratelimited(vop2->drm, "BUS_ERROR irq err\n"); in vop2_isr()
2632 pm_runtime_put(vop2->dev); in vop2_isr()
2640 const struct vop2_win_data *win_data = win->data; in vop2_plane_init()
2646 ret = drm_universal_plane_init(vop2->drm, &win->base, possible_crtcs, in vop2_plane_init()
2647 &vop2_plane_funcs, win_data->formats, in vop2_plane_init()
2648 win_data->nformats, in vop2_plane_init()
2649 win_data->format_modifiers, in vop2_plane_init()
2650 win->type, win_data->name); in vop2_plane_init()
2652 drm_err(vop2->drm, "failed to initialize plane %d\n", ret); in vop2_plane_init()
2656 drm_plane_helper_add(&win->base, &vop2_plane_helper_funcs); in vop2_plane_init()
2658 if (win->data->supported_rotations) in vop2_plane_init()
2659 drm_plane_create_rotation_property(&win->base, DRM_MODE_ROTATE_0, in vop2_plane_init()
2661 win->data->supported_rotations); in vop2_plane_init()
2662 drm_plane_create_alpha_property(&win->base); in vop2_plane_init()
2663 drm_plane_create_blend_mode_property(&win->base, blend_caps); in vop2_plane_init()
2664 drm_plane_create_zpos_property(&win->base, win->win_id, 0, in vop2_plane_init()
2665 vop2->registered_num_wins - 1); in vop2_plane_init()
2674 for (i = 0; i < vop2->data->nr_vps; i++) { in find_vp_without_primary()
2675 struct vop2_video_port *vp = &vop2->vps[i]; in find_vp_without_primary()
2677 if (!vp->crtc.port) in find_vp_without_primary()
2679 if (vp->primary_plane) in find_vp_without_primary()
2690 const struct vop2_data *vop2_data = vop2->data; in vop2_create_crtcs()
2691 struct drm_device *drm = vop2->drm; in vop2_create_crtcs()
2692 struct device *dev = vop2->dev; in vop2_create_crtcs()
2699 for (i = 0; i < vop2_data->nr_vps; i++) { in vop2_create_crtcs()
2704 vp_data = &vop2_data->vp[i]; in vop2_create_crtcs()
2705 vp = &vop2->vps[i]; in vop2_create_crtcs()
2706 vp->vop2 = vop2; in vop2_create_crtcs()
2707 vp->id = vp_data->id; in vop2_create_crtcs()
2708 vp->data = vp_data; in vop2_create_crtcs()
2710 snprintf(dclk_name, sizeof(dclk_name), "dclk_vp%d", vp->id); in vop2_create_crtcs()
2711 vp->dclk = devm_clk_get(vop2->dev, dclk_name); in vop2_create_crtcs()
2712 if (IS_ERR(vp->dclk)) { in vop2_create_crtcs()
2713 drm_err(vop2->drm, "failed to get %s\n", dclk_name); in vop2_create_crtcs()
2714 return PTR_ERR(vp->dclk); in vop2_create_crtcs()
2717 np = of_graph_get_remote_node(dev->of_node, i, -1); in vop2_create_crtcs()
2719 drm_dbg(vop2->drm, "%s: No remote for vp%d\n", __func__, i); in vop2_create_crtcs()
2724 port = of_graph_get_port_by_id(dev->of_node, i); in vop2_create_crtcs()
2726 drm_err(vop2->drm, "no port node found for video_port%d\n", i); in vop2_create_crtcs()
2727 return -ENOENT; in vop2_create_crtcs()
2730 vp->crtc.port = port; in vop2_create_crtcs()
2735 for (i = 0; i < vop2->registered_num_wins; i++) { in vop2_create_crtcs()
2736 struct vop2_win *win = &vop2->win[i]; in vop2_create_crtcs()
2739 if (vop2->data->soc_id == 3566) { in vop2_create_crtcs()
2745 switch (win->data->phys_id) { in vop2_create_crtcs()
2753 if (win->type == DRM_PLANE_TYPE_PRIMARY) { in vop2_create_crtcs()
2757 vp->primary_plane = win; in vop2_create_crtcs()
2761 win->type = DRM_PLANE_TYPE_OVERLAY; in vop2_create_crtcs()
2765 if (win->type == DRM_PLANE_TYPE_OVERLAY) in vop2_create_crtcs()
2766 possible_crtcs = (1 << nvps) - 1; in vop2_create_crtcs()
2770 drm_err(vop2->drm, "failed to init plane %s: %d\n", in vop2_create_crtcs()
2771 win->data->name, ret); in vop2_create_crtcs()
2776 for (i = 0; i < vop2_data->nr_vps; i++) { in vop2_create_crtcs()
2777 vp = &vop2->vps[i]; in vop2_create_crtcs()
2779 if (!vp->crtc.port) in vop2_create_crtcs()
2782 plane = &vp->primary_plane->base; in vop2_create_crtcs()
2784 ret = drm_crtc_init_with_planes(drm, &vp->crtc, plane, NULL, in vop2_create_crtcs()
2786 "video_port%d", vp->id); in vop2_create_crtcs()
2788 drm_err(vop2->drm, "crtc init for video_port%d failed\n", i); in vop2_create_crtcs()
2792 drm_crtc_helper_add(&vp->crtc, &vop2_crtc_helper_funcs); in vop2_create_crtcs()
2794 init_completion(&vp->dsp_hold_completion); in vop2_create_crtcs()
2802 for (i = 0; i < vop2->data->nr_vps; i++) { in vop2_create_crtcs()
2803 struct vop2_video_port *vp = &vop2->vps[i]; in vop2_create_crtcs()
2805 if (vp->crtc.port) in vop2_create_crtcs()
2806 vp->nlayers = vop2_data->win_size / nvps; in vop2_create_crtcs()
2814 struct drm_device *drm = vop2->drm; in vop2_destroy_crtcs()
2815 struct list_head *crtc_list = &drm->mode_config.crtc_list; in vop2_destroy_crtcs()
2816 struct list_head *plane_list = &drm->mode_config.plane_list; in vop2_destroy_crtcs()
2828 of_node_put(crtc->port); in vop2_destroy_crtcs()
2835 struct device_node *node = vop2->dev->of_node; in vop2_find_rgb_encoder()
2839 for (i = 0; i < vop2->data->nr_vps; i++) { in vop2_find_rgb_encoder()
2849 return -ENOENT; in vop2_find_rgb_encoder()
2918 struct vop2 *vop2 = win->vop2; in vop2_cluster_init()
2925 return -ENOMEM; in vop2_cluster_init()
2929 cluster_regs[i].reg += win->offset; in vop2_cluster_init()
2931 ret = devm_regmap_field_bulk_alloc(vop2->dev, vop2->map, win->reg, in vop2_cluster_init()
3002 struct vop2 *vop2 = win->vop2; in vop2_esmart_init()
3009 return -ENOMEM; in vop2_esmart_init()
3013 esmart_regs[i].reg += win->offset; in vop2_esmart_init()
3015 ret = devm_regmap_field_bulk_alloc(vop2->dev, vop2->map, win->reg, in vop2_esmart_init()
3026 const struct vop2_data *vop2_data = vop2->data; in vop2_win_init()
3030 for (i = 0; i < vop2_data->win_size; i++) { in vop2_win_init()
3031 const struct vop2_win_data *win_data = &vop2_data->win[i]; in vop2_win_init()
3033 win = &vop2->win[i]; in vop2_win_init()
3034 win->data = win_data; in vop2_win_init()
3035 win->type = win_data->type; in vop2_win_init()
3036 win->offset = win_data->base; in vop2_win_init()
3037 win->win_id = i; in vop2_win_init()
3038 win->vop2 = vop2; in vop2_win_init()
3047 vop2->registered_num_wins = vop2_data->win_size; in vop2_win_init()
3054 * Until that they read back the old value. As we read-modify-write
3055 * these registers mark them as non-volatile. This makes sure we read
3089 return -ENODEV; in vop2_bind()
3092 alloc_size = struct_size(vop2, win, vop2_data->win_size); in vop2_bind()
3095 return -ENOMEM; in vop2_bind()
3097 vop2->dev = dev; in vop2_bind()
3098 vop2->data = vop2_data; in vop2_bind()
3099 vop2->drm = drm; in vop2_bind()
3105 drm_err(vop2->drm, "failed to get vop2 register byname\n"); in vop2_bind()
3106 return -EINVAL; in vop2_bind()
3109 vop2->regs = devm_ioremap_resource(dev, res); in vop2_bind()
3110 if (IS_ERR(vop2->regs)) in vop2_bind()
3111 return PTR_ERR(vop2->regs); in vop2_bind()
3112 vop2->len = resource_size(res); in vop2_bind()
3114 vop2->map = devm_regmap_init_mmio(dev, vop2->regs, &vop2_regmap_config); in vop2_bind()
3115 if (IS_ERR(vop2->map)) in vop2_bind()
3116 return PTR_ERR(vop2->map); in vop2_bind()
3122 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "gamma-lut"); in vop2_bind()
3124 vop2->lut_regs = devm_ioremap_resource(dev, res); in vop2_bind()
3125 if (IS_ERR(vop2->lut_regs)) in vop2_bind()
3126 return PTR_ERR(vop2->lut_regs); in vop2_bind()
3128 if (vop2_data->feature & VOP2_FEATURE_HAS_SYS_GRF) { in vop2_bind()
3129 vop2->sys_grf = syscon_regmap_lookup_by_phandle(dev->of_node, "rockchip,grf"); in vop2_bind()
3130 if (IS_ERR(vop2->sys_grf)) in vop2_bind()
3131 return dev_err_probe(dev, PTR_ERR(vop2->sys_grf), "cannot get sys_grf"); in vop2_bind()
3134 if (vop2_data->feature & VOP2_FEATURE_HAS_VOP_GRF) { in vop2_bind()
3135 vop2->vop_grf = syscon_regmap_lookup_by_phandle(dev->of_node, "rockchip,vop-grf"); in vop2_bind()
3136 if (IS_ERR(vop2->vop_grf)) in vop2_bind()
3137 return dev_err_probe(dev, PTR_ERR(vop2->vop_grf), "cannot get vop_grf"); in vop2_bind()
3140 if (vop2_data->feature & VOP2_FEATURE_HAS_VO1_GRF) { in vop2_bind()
3141 vop2->vo1_grf = syscon_regmap_lookup_by_phandle(dev->of_node, "rockchip,vo1-grf"); in vop2_bind()
3142 if (IS_ERR(vop2->vo1_grf)) in vop2_bind()
3143 return dev_err_probe(dev, PTR_ERR(vop2->vo1_grf), "cannot get vo1_grf"); in vop2_bind()
3146 if (vop2_data->feature & VOP2_FEATURE_HAS_SYS_PMU) { in vop2_bind()
3147 vop2->sys_pmu = syscon_regmap_lookup_by_phandle(dev->of_node, "rockchip,pmu"); in vop2_bind()
3148 if (IS_ERR(vop2->sys_pmu)) in vop2_bind()
3149 return dev_err_probe(dev, PTR_ERR(vop2->sys_pmu), "cannot get sys_pmu"); in vop2_bind()
3152 vop2->hclk = devm_clk_get(vop2->dev, "hclk"); in vop2_bind()
3153 if (IS_ERR(vop2->hclk)) { in vop2_bind()
3154 drm_err(vop2->drm, "failed to get hclk source\n"); in vop2_bind()
3155 return PTR_ERR(vop2->hclk); in vop2_bind()
3158 vop2->aclk = devm_clk_get(vop2->dev, "aclk"); in vop2_bind()
3159 if (IS_ERR(vop2->aclk)) { in vop2_bind()
3160 drm_err(vop2->drm, "failed to get aclk source\n"); in vop2_bind()
3161 return PTR_ERR(vop2->aclk); in vop2_bind()
3164 vop2->pclk = devm_clk_get_optional(vop2->dev, "pclk_vop"); in vop2_bind()
3165 if (IS_ERR(vop2->pclk)) { in vop2_bind()
3166 drm_err(vop2->drm, "failed to get pclk source\n"); in vop2_bind()
3167 return PTR_ERR(vop2->pclk); in vop2_bind()
3170 vop2->irq = platform_get_irq(pdev, 0); in vop2_bind()
3171 if (vop2->irq < 0) { in vop2_bind()
3172 drm_err(vop2->drm, "cannot find irq for vop2\n"); in vop2_bind()
3173 return vop2->irq; in vop2_bind()
3176 mutex_init(&vop2->vop2_lock); in vop2_bind()
3178 ret = devm_request_irq(dev, vop2->irq, vop2_isr, IRQF_SHARED, dev_name(dev), vop2); in vop2_bind()
3188 vop2->rgb = rockchip_rgb_init(dev, &vop2->vps[ret].crtc, in vop2_bind()
3189 vop2->drm, ret); in vop2_bind()
3190 if (IS_ERR(vop2->rgb)) { in vop2_bind()
3191 if (PTR_ERR(vop2->rgb) == -EPROBE_DEFER) { in vop2_bind()
3192 ret = PTR_ERR(vop2->rgb); in vop2_bind()
3195 vop2->rgb = NULL; in vop2_bind()
3199 rockchip_drm_dma_init_device(vop2->drm, vop2->dev); in vop2_bind()
3201 pm_runtime_enable(&pdev->dev); in vop2_bind()
3217 if (vop2->rgb) in vop2_unbind()
3218 rockchip_rgb_fini(vop2->rgb); in vop2_unbind()