Lines Matching +full:scl +full:- +full:output +full:- +full:only

1 // SPDX-License-Identifier: GPL-2.0-only
4 * Author:Mark Yao <mark.yao@rock-chips.com>
43 vop_reg_set(vop, &win->phy->name, win->base, ~0, v, #name)
45 vop_reg_set(vop, &win->phy->scl->name, win->base, ~0, v, #name)
47 vop_reg_set(vop, &win->phy->scl->ext->name, \
48 win->base, ~0, v, #name)
52 if (win_yuv2yuv && win_yuv2yuv->name.mask) \
53 vop_reg_set(vop, &win_yuv2yuv->name, 0, ~0, v, #name); \
58 if (win_yuv2yuv && win_yuv2yuv->phy->name.mask) \
59 vop_reg_set(vop, &win_yuv2yuv->phy->name, win_yuv2yuv->base, ~0, v, #name); \
63 vop_reg_set(vop, &vop->data->intr->name, 0, mask, v, #name)
66 vop_reg_set(vop, &vop->data->group->name, 0, ~0, v, #name)
71 for (i = 0; i < vop->data->intr->nintrs; i++) { \
72 if (vop->data->intr->intrs[i] & type) { \
80 vop_get_intr_type(vop, &vop->data->intr->name, type)
83 vop_read_reg(vop, win->base, &win->phy->name)
86 (!!(win->phy->name.mask))
89 vop_readl(vop, win->base + win->phy->yrgb_mst.offset)
92 ((vop_win) - (vop_win)->vop->win)
96 if ((vop)->data->afbc) \
97 vop_reg_set((vop), &(vop)->data->afbc->name, \
143 /* protected by dev->event_lock */
160 /* one time only one process allowed to config the register */
187 writel(v, vop->regs + offset); in vop_writel()
188 vop->regsbak[offset >> 2] = v; in vop_writel()
193 return readl(vop->regs + offset); in vop_readl()
199 return (vop_readl(vop, base + reg->offset) >> reg->shift) & reg->mask; in vop_read_reg()
208 if (!reg || !reg->mask) { in vop_reg_set()
209 DRM_DEV_DEBUG(vop->dev, "Warning: not support %s\n", reg_name); in vop_reg_set()
213 offset = reg->offset + _offset; in vop_reg_set()
214 mask = reg->mask & _mask; in vop_reg_set()
215 shift = reg->shift; in vop_reg_set()
217 if (reg->write_mask) { in vop_reg_set()
220 uint32_t cached_val = vop->regsbak[offset >> 2]; in vop_reg_set()
223 vop->regsbak[offset >> 2] = v; in vop_reg_set()
226 if (reg->relaxed) in vop_reg_set()
227 writel_relaxed(v, vop->regs + offset); in vop_reg_set()
229 writel(v, vop->regs + offset); in vop_reg_set()
238 for (i = 0; i < vop->data->intr->nintrs; i++) { in vop_get_intr_type()
239 if ((type & vop->data->intr->intrs[i]) && (regs & 1 << i)) in vop_get_intr_type()
240 ret |= vop->data->intr->intrs[i]; in vop_get_intr_type()
286 return -EINVAL; in vop_convert_format()
307 return -EINVAL; in vop_convert_afbc_format()
310 return -EINVAL; in vop_convert_afbc_format()
355 uint16_t cbcr_src_w = src_w / info->hsub; in scl_vop_cal_scl_fac()
356 uint16_t cbcr_src_h = src_h / info->vsub; in scl_vop_cal_scl_fac()
362 if (info->is_yuv) in scl_vop_cal_scl_fac()
366 DRM_DEV_ERROR(vop->dev, "Maximum dst width (3840) exceeded\n"); in scl_vop_cal_scl_fac()
370 if (!win->phy->scl->ext) { in scl_vop_cal_scl_fac()
404 DRM_DEV_ERROR(vop->dev, "not allow yrgb ver scale\n"); in scl_vop_cal_scl_fac()
408 DRM_DEV_ERROR(vop->dev, "not allow cbcr ver scale\n"); in scl_vop_cal_scl_fac()
455 if (WARN_ON(!vop->is_enabled)) in vop_dsp_hold_valid_irq_enable()
458 spin_lock_irqsave(&vop->irq_lock, flags); in vop_dsp_hold_valid_irq_enable()
463 spin_unlock_irqrestore(&vop->irq_lock, flags); in vop_dsp_hold_valid_irq_enable()
470 if (WARN_ON(!vop->is_enabled)) in vop_dsp_hold_valid_irq_disable()
473 spin_lock_irqsave(&vop->irq_lock, flags); in vop_dsp_hold_valid_irq_disable()
477 spin_unlock_irqrestore(&vop->irq_lock, flags); in vop_dsp_hold_valid_irq_disable()
489 * LINE_FLAG -------------------------------+
490 * FRAME_SYNC ----+ |
497 * dsp_vs_end ------------+ | | | VOP_DSP_VTOTAL_VS_END
498 * dsp_vact_start --------------+ | | VOP_DSP_VACT_ST_END
499 * dsp_vact_end ----------------------------+ | VOP_DSP_VACT_ST_END
500 * dsp_total -------------------------------------+ VOP_DSP_VTOTAL_VS_END
507 spin_lock_irqsave(&vop->irq_lock, flags); in vop_line_flag_irq_is_enabled()
511 spin_unlock_irqrestore(&vop->irq_lock, flags); in vop_line_flag_irq_is_enabled()
520 if (WARN_ON(!vop->is_enabled)) in vop_line_flag_irq_enable()
523 spin_lock_irqsave(&vop->irq_lock, flags); in vop_line_flag_irq_enable()
528 spin_unlock_irqrestore(&vop->irq_lock, flags); in vop_line_flag_irq_enable()
535 if (WARN_ON(!vop->is_enabled)) in vop_line_flag_irq_disable()
538 spin_lock_irqsave(&vop->irq_lock, flags); in vop_line_flag_irq_disable()
542 spin_unlock_irqrestore(&vop->irq_lock, flags); in vop_line_flag_irq_disable()
549 ret = clk_enable(vop->hclk); in vop_core_clks_enable()
553 ret = clk_enable(vop->aclk); in vop_core_clks_enable()
560 clk_disable(vop->hclk); in vop_core_clks_enable()
566 clk_disable(vop->aclk); in vop_core_clks_disable()
567 clk_disable(vop->hclk); in vop_core_clks_disable()
572 const struct vop_win_data *win = vop_win->data; in vop_win_disable()
574 if (win->phy->scl && win->phy->scl->ext) { in vop_win_disable()
582 vop->win_enabled &= ~BIT(VOP_WIN_TO_INDEX(vop_win)); in vop_win_disable()
590 ret = pm_runtime_get_sync(vop->dev); in vop_enable()
592 DRM_DEV_ERROR(vop->dev, "failed to get pm runtime: %d\n", ret); in vop_enable()
600 ret = clk_enable(vop->dclk); in vop_enable()
610 ret = rockchip_drm_dma_attach_device(vop->drm_dev, vop->dev); in vop_enable()
612 DRM_DEV_ERROR(vop->dev, in vop_enable()
617 spin_lock(&vop->reg_lock); in vop_enable()
618 for (i = 0; i < vop->len; i += 4) in vop_enable()
619 writel_relaxed(vop->regsbak[i / 4], vop->regs + i); in vop_enable()
626 * In the case of enable-after-PSR, we don't need to worry about this in vop_enable()
630 if (!old_state || !old_state->self_refresh_active) { in vop_enable()
631 for (i = 0; i < vop->data->win_size; i++) { in vop_enable()
632 struct vop_win *vop_win = &vop->win[i]; in vop_enable()
638 if (vop->data->afbc) { in vop_enable()
644 s = to_rockchip_crtc_state(crtc->state); in vop_enable()
645 s->enable_afbc = false; in vop_enable()
650 spin_unlock(&vop->reg_lock); in vop_enable()
655 vop->is_enabled = true; in vop_enable()
657 spin_lock(&vop->reg_lock); in vop_enable()
661 spin_unlock(&vop->reg_lock); in vop_enable()
668 clk_disable(vop->dclk); in vop_enable()
672 pm_runtime_put_sync(vop->dev); in vop_enable()
681 spin_lock(&vop->reg_lock); in rockchip_drm_set_win_enabled()
683 for (i = 0; i < vop->data->win_size; i++) { in rockchip_drm_set_win_enabled()
684 struct vop_win *vop_win = &vop->win[i]; in rockchip_drm_set_win_enabled()
685 const struct vop_win_data *win = vop_win->data; in rockchip_drm_set_win_enabled()
688 enabled && (vop->win_enabled & BIT(i))); in rockchip_drm_set_win_enabled()
692 spin_unlock(&vop->reg_lock); in rockchip_drm_set_win_enabled()
700 WARN_ON(vop->event); in vop_crtc_atomic_disable()
702 if (crtc->state->self_refresh_active) in vop_crtc_atomic_disable()
705 mutex_lock(&vop->vop_lock); in vop_crtc_atomic_disable()
709 if (crtc->state->self_refresh_active) in vop_crtc_atomic_disable()
719 reinit_completion(&vop->dsp_hold_completion); in vop_crtc_atomic_disable()
722 spin_lock(&vop->reg_lock); in vop_crtc_atomic_disable()
726 spin_unlock(&vop->reg_lock); in vop_crtc_atomic_disable()
728 wait_for_completion(&vop->dsp_hold_completion); in vop_crtc_atomic_disable()
732 vop->is_enabled = false; in vop_crtc_atomic_disable()
737 rockchip_drm_dma_detach_device(vop->drm_dev, vop->dev); in vop_crtc_atomic_disable()
739 clk_disable(vop->dclk); in vop_crtc_atomic_disable()
741 pm_runtime_put(vop->dev); in vop_crtc_atomic_disable()
744 mutex_unlock(&vop->vop_lock); in vop_crtc_atomic_disable()
746 if (crtc->state->event && !crtc->state->active) { in vop_crtc_atomic_disable()
747 spin_lock_irq(&crtc->dev->event_lock); in vop_crtc_atomic_disable()
748 drm_crtc_send_vblank_event(crtc, crtc->state->event); in vop_crtc_atomic_disable()
749 spin_unlock_irq(&crtc->dev->event_lock); in vop_crtc_atomic_disable()
751 crtc->state->event = NULL; in vop_crtc_atomic_disable()
783 struct drm_crtc *crtc = state->crtc; in vop_plane_atomic_check()
785 struct drm_framebuffer *fb = state->fb; in vop_plane_atomic_check()
787 const struct vop_win_data *win = vop_win->data; in vop_plane_atomic_check()
789 int min_scale = win->phy->scl ? FRAC_16_16(1, 8) : in vop_plane_atomic_check()
791 int max_scale = win->phy->scl ? FRAC_16_16(8, 1) : in vop_plane_atomic_check()
797 crtc_state = drm_atomic_get_existing_crtc_state(state->state, crtc); in vop_plane_atomic_check()
799 return -EINVAL; in vop_plane_atomic_check()
807 if (!state->visible) in vop_plane_atomic_check()
810 ret = vop_convert_format(fb->format->format); in vop_plane_atomic_check()
818 if (fb->format->is_yuv && ((state->src.x1 >> 16) % 2)) { in vop_plane_atomic_check()
820 return -EINVAL; in vop_plane_atomic_check()
823 if (fb->format->is_yuv && state->rotation & DRM_MODE_REFLECT_Y) { in vop_plane_atomic_check()
825 return -EINVAL; in vop_plane_atomic_check()
828 if (rockchip_afbc(fb->modifier)) { in vop_plane_atomic_check()
831 if (!vop->data->afbc) { in vop_plane_atomic_check()
833 return -EINVAL; in vop_plane_atomic_check()
836 ret = vop_convert_afbc_format(fb->format->format); in vop_plane_atomic_check()
840 if (state->src.x1 || state->src.y1) { in vop_plane_atomic_check()
841 … support offset display, xpos=%d, ypos=%d, offset=%d\n", state->src.x1, state->src.y1, fb->offsets… in vop_plane_atomic_check()
842 return -EINVAL; in vop_plane_atomic_check()
845 if (state->rotation && state->rotation != DRM_MODE_ROTATE_0) { in vop_plane_atomic_check()
847 state->rotation); in vop_plane_atomic_check()
848 return -EINVAL; in vop_plane_atomic_check()
859 struct vop *vop = to_vop(old_state->crtc); in vop_plane_atomic_disable()
861 if (!old_state->crtc) in vop_plane_atomic_disable()
864 spin_lock(&vop->reg_lock); in vop_plane_atomic_disable()
868 spin_unlock(&vop->reg_lock); in vop_plane_atomic_disable()
874 struct drm_plane_state *state = plane->state; in vop_plane_atomic_update()
875 struct drm_crtc *crtc = state->crtc; in vop_plane_atomic_update()
877 const struct vop_win_data *win = vop_win->data; in vop_plane_atomic_update()
878 const struct vop_win_yuv2yuv_data *win_yuv2yuv = vop_win->yuv2yuv_data; in vop_plane_atomic_update()
879 struct vop *vop = to_vop(state->crtc); in vop_plane_atomic_update()
880 struct drm_framebuffer *fb = state->fb; in vop_plane_atomic_update()
884 struct drm_rect *src = &state->src; in vop_plane_atomic_update()
885 struct drm_rect *dest = &state->dst; in vop_plane_atomic_update()
894 int is_yuv = fb->format->is_yuv; in vop_plane_atomic_update()
903 if (WARN_ON(!vop->is_enabled)) in vop_plane_atomic_update()
906 if (!state->visible) { in vop_plane_atomic_update()
911 obj = fb->obj[0]; in vop_plane_atomic_update()
916 act_info = (actual_h - 1) << 16 | ((actual_w - 1) & 0xffff); in vop_plane_atomic_update()
918 dsp_info = (drm_rect_height(dest) - 1) << 16; in vop_plane_atomic_update()
919 dsp_info |= (drm_rect_width(dest) - 1) & 0xffff; in vop_plane_atomic_update()
921 dsp_stx = dest->x1 + crtc->mode.htotal - crtc->mode.hsync_start; in vop_plane_atomic_update()
922 dsp_sty = dest->y1 + crtc->mode.vtotal - crtc->mode.vsync_start; in vop_plane_atomic_update()
925 offset = (src->x1 >> 16) * fb->format->cpp[0]; in vop_plane_atomic_update()
926 offset += (src->y1 >> 16) * fb->pitches[0]; in vop_plane_atomic_update()
927 dma_addr = rk_obj->dma_addr + offset + fb->offsets[0]; in vop_plane_atomic_update()
930 * For y-mirroring we need to move address in vop_plane_atomic_update()
933 if (state->rotation & DRM_MODE_REFLECT_Y) in vop_plane_atomic_update()
934 dma_addr += (actual_h - 1) * fb->pitches[0]; in vop_plane_atomic_update()
936 format = vop_convert_format(fb->format->format); in vop_plane_atomic_update()
938 spin_lock(&vop->reg_lock); in vop_plane_atomic_update()
940 if (rockchip_afbc(fb->modifier)) { in vop_plane_atomic_update()
941 int afbc_format = vop_convert_afbc_format(fb->format->format); in vop_plane_atomic_update()
951 VOP_WIN_SET(vop, win, yrgb_vir, DIV_ROUND_UP(fb->pitches[0], 4)); in vop_plane_atomic_update()
955 (state->rotation & DRM_MODE_REFLECT_Y) ? 1 : 0); in vop_plane_atomic_update()
957 (state->rotation & DRM_MODE_REFLECT_X) ? 1 : 0); in vop_plane_atomic_update()
960 int hsub = fb->format->hsub; in vop_plane_atomic_update()
961 int vsub = fb->format->vsub; in vop_plane_atomic_update()
962 int bpp = fb->format->cpp[1]; in vop_plane_atomic_update()
964 uv_obj = fb->obj[1]; in vop_plane_atomic_update()
967 offset = (src->x1 >> 16) * bpp / hsub; in vop_plane_atomic_update()
968 offset += (src->y1 >> 16) * fb->pitches[1] / vsub; in vop_plane_atomic_update()
970 dma_addr = rk_uv_obj->dma_addr + offset + fb->offsets[1]; in vop_plane_atomic_update()
971 VOP_WIN_SET(vop, win, uv_vir, DIV_ROUND_UP(fb->pitches[1], 4)); in vop_plane_atomic_update()
982 if (win->phy->scl) in vop_plane_atomic_update()
985 fb->format); in vop_plane_atomic_update()
991 rb_swap = has_rb_swapped(fb->format->format); in vop_plane_atomic_update()
996 * correctly. We only get the background color, no matter the contents in vop_plane_atomic_update()
997 * of the win0 framebuffer. However, blending pre-multiplied color in vop_plane_atomic_update()
998 * with the default opaque black default background color is a no-op, in vop_plane_atomic_update()
1001 if (fb->format->has_alpha && win_index > 0) { in vop_plane_atomic_update()
1019 vop->win_enabled |= BIT(win_index); in vop_plane_atomic_update()
1020 spin_unlock(&vop->reg_lock); in vop_plane_atomic_update()
1027 const struct vop_win_data *win = vop_win->data; in vop_plane_atomic_async_check()
1028 int min_scale = win->phy->scl ? FRAC_16_16(1, 8) : in vop_plane_atomic_async_check()
1030 int max_scale = win->phy->scl ? FRAC_16_16(8, 1) : in vop_plane_atomic_async_check()
1034 if (plane != state->crtc->cursor) in vop_plane_atomic_async_check()
1035 return -EINVAL; in vop_plane_atomic_async_check()
1037 if (!plane->state) in vop_plane_atomic_async_check()
1038 return -EINVAL; in vop_plane_atomic_async_check()
1040 if (!plane->state->fb) in vop_plane_atomic_async_check()
1041 return -EINVAL; in vop_plane_atomic_async_check()
1043 if (state->state) in vop_plane_atomic_async_check()
1044 crtc_state = drm_atomic_get_existing_crtc_state(state->state, in vop_plane_atomic_async_check()
1045 state->crtc); in vop_plane_atomic_async_check()
1047 crtc_state = plane->crtc->state; in vop_plane_atomic_async_check()
1049 return drm_atomic_helper_check_plane_state(plane->state, crtc_state, in vop_plane_atomic_async_check()
1057 struct vop *vop = to_vop(plane->state->crtc); in vop_plane_atomic_async_update()
1058 struct drm_framebuffer *old_fb = plane->state->fb; in vop_plane_atomic_async_update()
1060 plane->state->crtc_x = new_state->crtc_x; in vop_plane_atomic_async_update()
1061 plane->state->crtc_y = new_state->crtc_y; in vop_plane_atomic_async_update()
1062 plane->state->crtc_h = new_state->crtc_h; in vop_plane_atomic_async_update()
1063 plane->state->crtc_w = new_state->crtc_w; in vop_plane_atomic_async_update()
1064 plane->state->src_x = new_state->src_x; in vop_plane_atomic_async_update()
1065 plane->state->src_y = new_state->src_y; in vop_plane_atomic_async_update()
1066 plane->state->src_h = new_state->src_h; in vop_plane_atomic_async_update()
1067 plane->state->src_w = new_state->src_w; in vop_plane_atomic_async_update()
1068 swap(plane->state->fb, new_state->fb); in vop_plane_atomic_async_update()
1070 if (vop->is_enabled) { in vop_plane_atomic_async_update()
1071 vop_plane_atomic_update(plane, plane->state); in vop_plane_atomic_async_update()
1072 spin_lock(&vop->reg_lock); in vop_plane_atomic_async_update()
1074 spin_unlock(&vop->reg_lock); in vop_plane_atomic_async_update()
1084 if (old_fb && plane->state->fb != old_fb) { in vop_plane_atomic_async_update()
1086 WARN_ON(drm_crtc_vblank_get(plane->state->crtc) != 0); in vop_plane_atomic_async_update()
1087 drm_flip_work_queue(&vop->fb_unref_work, old_fb); in vop_plane_atomic_async_update()
1088 set_bit(VOP_PENDING_FB_UNREF, &vop->pending); in vop_plane_atomic_async_update()
1117 if (WARN_ON(!vop->is_enabled)) in vop_crtc_enable_vblank()
1118 return -EPERM; in vop_crtc_enable_vblank()
1120 spin_lock_irqsave(&vop->irq_lock, flags); in vop_crtc_enable_vblank()
1125 spin_unlock_irqrestore(&vop->irq_lock, flags); in vop_crtc_enable_vblank()
1135 if (WARN_ON(!vop->is_enabled)) in vop_crtc_disable_vblank()
1138 spin_lock_irqsave(&vop->irq_lock, flags); in vop_crtc_disable_vblank()
1142 spin_unlock_irqrestore(&vop->irq_lock, flags); in vop_crtc_disable_vblank()
1157 * - DRM works in in kHz. in vop_crtc_mode_fixup()
1158 * - Clock framework works in Hz. in vop_crtc_mode_fixup()
1159 * - Rockchip's clock driver picks the clock rate that is the in vop_crtc_mode_fixup()
1183 rate = clk_round_rate(vop->dclk, adjusted_mode->clock * 1000 + 999); in vop_crtc_mode_fixup()
1184 adjusted_mode->clock = DIV_ROUND_UP(rate, 1000); in vop_crtc_mode_fixup()
1191 return vop_read_reg(vop, 0, &vop->data->common->dsp_lut_en); in vop_dsp_lut_is_enabled()
1196 struct drm_color_lut *lut = crtc->state->gamma_lut->data; in vop_crtc_write_gamma_lut()
1199 for (i = 0; i < crtc->gamma_size; i++) { in vop_crtc_write_gamma_lut()
1205 writel(word, vop->lut_regs + i * 4); in vop_crtc_write_gamma_lut()
1212 struct drm_crtc_state *state = crtc->state; in vop_crtc_gamma_set()
1216 if (!vop->lut_regs) in vop_crtc_gamma_set()
1222 spin_lock(&vop->reg_lock); in vop_crtc_gamma_set()
1225 spin_unlock(&vop->reg_lock); in vop_crtc_gamma_set()
1234 DRM_DEV_ERROR(vop->dev, "display LUT RAM enable timeout!\n"); in vop_crtc_gamma_set()
1238 if (!state->gamma_lut) in vop_crtc_gamma_set()
1241 spin_lock(&vop->reg_lock); in vop_crtc_gamma_set()
1245 spin_unlock(&vop->reg_lock); in vop_crtc_gamma_set()
1254 * Only update GAMMA if the 'active' flag is not changed, in vop_crtc_atomic_begin()
1257 if (crtc->state->color_mgmt_changed && in vop_crtc_atomic_begin()
1258 !crtc->state->active_changed) in vop_crtc_atomic_begin()
1266 const struct vop_data *vop_data = vop->data; in vop_crtc_atomic_enable()
1267 struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc->state); in vop_crtc_atomic_enable()
1268 struct drm_display_mode *adjusted_mode = &crtc->state->adjusted_mode; in vop_crtc_atomic_enable()
1269 u16 hsync_len = adjusted_mode->hsync_end - adjusted_mode->hsync_start; in vop_crtc_atomic_enable()
1270 u16 hdisplay = adjusted_mode->hdisplay; in vop_crtc_atomic_enable()
1271 u16 htotal = adjusted_mode->htotal; in vop_crtc_atomic_enable()
1272 u16 hact_st = adjusted_mode->htotal - adjusted_mode->hsync_start; in vop_crtc_atomic_enable()
1274 u16 vdisplay = adjusted_mode->vdisplay; in vop_crtc_atomic_enable()
1275 u16 vtotal = adjusted_mode->vtotal; in vop_crtc_atomic_enable()
1276 u16 vsync_len = adjusted_mode->vsync_end - adjusted_mode->vsync_start; in vop_crtc_atomic_enable()
1277 u16 vact_st = adjusted_mode->vtotal - adjusted_mode->vsync_start; in vop_crtc_atomic_enable()
1280 int dither_bpc = s->output_bpc ? s->output_bpc : 10; in vop_crtc_atomic_enable()
1283 if (old_state && old_state->self_refresh_active) { in vop_crtc_atomic_enable()
1292 * which means the LUT internal memory needs to be re-written. in vop_crtc_atomic_enable()
1294 if (crtc->state->gamma_lut) in vop_crtc_atomic_enable()
1297 mutex_lock(&vop->vop_lock); in vop_crtc_atomic_enable()
1299 WARN_ON(vop->event); in vop_crtc_atomic_enable()
1303 mutex_unlock(&vop->vop_lock); in vop_crtc_atomic_enable()
1304 DRM_DEV_ERROR(vop->dev, "Failed to enable vop (%d)\n", ret); in vop_crtc_atomic_enable()
1307 pin_pol = (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC) ? in vop_crtc_atomic_enable()
1309 pin_pol |= (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC) ? in vop_crtc_atomic_enable()
1311 VOP_REG_SET(vop, output, pin_pol, pin_pol); in vop_crtc_atomic_enable()
1312 VOP_REG_SET(vop, output, mipi_dual_channel_en, 0); in vop_crtc_atomic_enable()
1314 switch (s->output_type) { in vop_crtc_atomic_enable()
1316 VOP_REG_SET(vop, output, rgb_dclk_pol, 1); in vop_crtc_atomic_enable()
1317 VOP_REG_SET(vop, output, rgb_pin_pol, pin_pol); in vop_crtc_atomic_enable()
1318 VOP_REG_SET(vop, output, rgb_en, 1); in vop_crtc_atomic_enable()
1321 VOP_REG_SET(vop, output, edp_dclk_pol, 1); in vop_crtc_atomic_enable()
1322 VOP_REG_SET(vop, output, edp_pin_pol, pin_pol); in vop_crtc_atomic_enable()
1323 VOP_REG_SET(vop, output, edp_en, 1); in vop_crtc_atomic_enable()
1326 VOP_REG_SET(vop, output, hdmi_dclk_pol, 1); in vop_crtc_atomic_enable()
1327 VOP_REG_SET(vop, output, hdmi_pin_pol, pin_pol); in vop_crtc_atomic_enable()
1328 VOP_REG_SET(vop, output, hdmi_en, 1); in vop_crtc_atomic_enable()
1331 VOP_REG_SET(vop, output, mipi_dclk_pol, 1); in vop_crtc_atomic_enable()
1332 VOP_REG_SET(vop, output, mipi_pin_pol, pin_pol); in vop_crtc_atomic_enable()
1333 VOP_REG_SET(vop, output, mipi_en, 1); in vop_crtc_atomic_enable()
1334 VOP_REG_SET(vop, output, mipi_dual_channel_en, in vop_crtc_atomic_enable()
1335 !!(s->output_flags & ROCKCHIP_OUTPUT_DSI_DUAL)); in vop_crtc_atomic_enable()
1338 VOP_REG_SET(vop, output, dp_dclk_pol, 0); in vop_crtc_atomic_enable()
1339 VOP_REG_SET(vop, output, dp_pin_pol, pin_pol); in vop_crtc_atomic_enable()
1340 VOP_REG_SET(vop, output, dp_en, 1); in vop_crtc_atomic_enable()
1343 DRM_DEV_ERROR(vop->dev, "unsupported connector_type [%d]\n", in vop_crtc_atomic_enable()
1344 s->output_type); in vop_crtc_atomic_enable()
1348 * if vop is not support RGB10 output, need force RGB10 to RGB888. in vop_crtc_atomic_enable()
1350 if (s->output_mode == ROCKCHIP_OUT_MODE_AAAA && in vop_crtc_atomic_enable()
1351 !(vop_data->feature & VOP_FEATURE_OUTPUT_RGB10)) in vop_crtc_atomic_enable()
1352 s->output_mode = ROCKCHIP_OUT_MODE_P888; in vop_crtc_atomic_enable()
1354 if (s->output_mode == ROCKCHIP_OUT_MODE_AAAA && dither_bpc <= 8) in vop_crtc_atomic_enable()
1367 VOP_REG_SET(vop, common, out_mode, s->output_mode); in vop_crtc_atomic_enable()
1383 clk_set_rate(vop->dclk, adjusted_mode->clock * 1000); in vop_crtc_atomic_enable()
1386 mutex_unlock(&vop->vop_lock); in vop_crtc_atomic_enable()
1403 * something goes really wrong. The wait will only happen in the very in vop_wait_for_irq_handler()
1410 DRM_DEV_ERROR(vop->dev, "VOP vblank IRQ stuck for 10 ms\n"); in vop_wait_for_irq_handler()
1412 synchronize_irq(vop->irq); in vop_wait_for_irq_handler()
1424 if (vop->lut_regs && crtc_state->color_mgmt_changed && in vop_crtc_atomic_check()
1425 crtc_state->gamma_lut) { in vop_crtc_atomic_check()
1428 len = drm_color_lut_size(crtc_state->gamma_lut); in vop_crtc_atomic_check()
1429 if (len != crtc->gamma_size) { in vop_crtc_atomic_check()
1431 len, crtc->gamma_size); in vop_crtc_atomic_check()
1432 return -EINVAL; in vop_crtc_atomic_check()
1438 drm_atomic_get_plane_state(crtc_state->state, plane); in vop_crtc_atomic_check()
1441 plane->name); in vop_crtc_atomic_check()
1445 if (drm_is_afbc(plane_state->fb->modifier)) in vop_crtc_atomic_check()
1451 return -EINVAL; in vop_crtc_atomic_check()
1455 s->enable_afbc = afbc_planes > 0; in vop_crtc_atomic_check()
1463 struct drm_atomic_state *old_state = old_crtc_state->state; in vop_crtc_atomic_flush()
1470 if (WARN_ON(!vop->is_enabled)) in vop_crtc_atomic_flush()
1473 spin_lock(&vop->reg_lock); in vop_crtc_atomic_flush()
1476 s = to_rockchip_crtc_state(crtc->state); in vop_crtc_atomic_flush()
1477 VOP_AFBC_SET(vop, enable, s->enable_afbc); in vop_crtc_atomic_flush()
1480 spin_unlock(&vop->reg_lock); in vop_crtc_atomic_flush()
1489 spin_lock_irq(&crtc->dev->event_lock); in vop_crtc_atomic_flush()
1490 if (crtc->state->event) { in vop_crtc_atomic_flush()
1492 WARN_ON(vop->event); in vop_crtc_atomic_flush()
1494 vop->event = crtc->state->event; in vop_crtc_atomic_flush()
1495 crtc->state->event = NULL; in vop_crtc_atomic_flush()
1497 spin_unlock_irq(&crtc->dev->event_lock); in vop_crtc_atomic_flush()
1501 if (!old_plane_state->fb) in vop_crtc_atomic_flush()
1504 if (old_plane_state->fb == new_plane_state->fb) in vop_crtc_atomic_flush()
1507 drm_framebuffer_get(old_plane_state->fb); in vop_crtc_atomic_flush()
1509 drm_flip_work_queue(&vop->fb_unref_work, old_plane_state->fb); in vop_crtc_atomic_flush()
1510 set_bit(VOP_PENDING_FB_UNREF, &vop->pending); in vop_crtc_atomic_flush()
1536 __drm_atomic_helper_crtc_duplicate_state(crtc, &rockchip_state->base); in vop_crtc_duplicate_state()
1537 return &rockchip_state->base; in vop_crtc_duplicate_state()
1545 __drm_atomic_helper_crtc_destroy_state(&s->base); in vop_crtc_destroy_state()
1554 if (crtc->state) in vop_crtc_reset()
1555 vop_crtc_destroy_state(crtc, crtc->state); in vop_crtc_reset()
1557 __drm_atomic_helper_crtc_reset(crtc, &crtc_state->base); in vop_crtc_reset()
1566 drm_connector_list_iter_begin(vop->drm_dev, &conn_iter); in vop_get_edp_connector()
1568 if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) { in vop_get_edp_connector()
1587 return -EINVAL; in vop_crtc_set_crc_source()
1594 ret = -EINVAL; in vop_crtc_set_crc_source()
1604 return -EINVAL; in vop_crtc_verify_crc_source()
1614 return -ENODEV; in vop_crtc_set_crc_source()
1621 return -ENODEV; in vop_crtc_verify_crc_source()
1644 drm_crtc_vblank_put(&vop->crtc); in vop_fb_unref_worker()
1650 struct drm_device *drm = vop->drm_dev; in vop_handle_vblank()
1651 struct drm_crtc *crtc = &vop->crtc; in vop_handle_vblank()
1653 spin_lock(&drm->event_lock); in vop_handle_vblank()
1654 if (vop->event) { in vop_handle_vblank()
1655 drm_crtc_send_vblank_event(crtc, vop->event); in vop_handle_vblank()
1657 vop->event = NULL; in vop_handle_vblank()
1659 spin_unlock(&drm->event_lock); in vop_handle_vblank()
1661 if (test_and_clear_bit(VOP_PENDING_FB_UNREF, &vop->pending)) in vop_handle_vblank()
1662 drm_flip_work_commit(&vop->fb_unref_work, system_unbound_wq); in vop_handle_vblank()
1668 struct drm_crtc *crtc = &vop->crtc; in vop_isr()
1673 * The irq is shared with the iommu. If the runtime-pm state of the in vop_isr()
1674 * vop-device is disabled the irq has to be targeted at the iommu. in vop_isr()
1676 if (!pm_runtime_get_if_in_use(vop->dev)) in vop_isr()
1680 DRM_DEV_ERROR_RATELIMITED(vop->dev, "couldn't enable clocks\n"); in vop_isr()
1688 spin_lock(&vop->irq_lock); in vop_isr()
1695 spin_unlock(&vop->irq_lock); in vop_isr()
1702 complete(&vop->dsp_hold_completion); in vop_isr()
1708 complete(&vop->line_flag_completion); in vop_isr()
1722 DRM_DEV_ERROR(vop->dev, "Unknown VOP IRQs: %#02x\n", in vop_isr()
1728 pm_runtime_put(vop->dev); in vop_isr()
1746 const struct vop_data *vop_data = vop->data; in vop_create_crtc()
1747 struct device *dev = vop->dev; in vop_create_crtc()
1748 struct drm_device *drm_dev = vop->drm_dev; in vop_create_crtc()
1750 struct drm_crtc *crtc = &vop->crtc; in vop_create_crtc()
1760 for (i = 0; i < vop_data->win_size; i++) { in vop_create_crtc()
1761 struct vop_win *vop_win = &vop->win[i]; in vop_create_crtc()
1762 const struct vop_win_data *win_data = vop_win->data; in vop_create_crtc()
1764 if (win_data->type != DRM_PLANE_TYPE_PRIMARY && in vop_create_crtc()
1765 win_data->type != DRM_PLANE_TYPE_CURSOR) in vop_create_crtc()
1768 ret = drm_universal_plane_init(vop->drm_dev, &vop_win->base, in vop_create_crtc()
1770 win_data->phy->data_formats, in vop_create_crtc()
1771 win_data->phy->nformats, in vop_create_crtc()
1772 win_data->phy->format_modifiers, in vop_create_crtc()
1773 win_data->type, NULL); in vop_create_crtc()
1775 DRM_DEV_ERROR(vop->dev, "failed to init plane %d\n", in vop_create_crtc()
1780 plane = &vop_win->base; in vop_create_crtc()
1783 if (plane->type == DRM_PLANE_TYPE_PRIMARY) in vop_create_crtc()
1785 else if (plane->type == DRM_PLANE_TYPE_CURSOR) in vop_create_crtc()
1795 if (vop->lut_regs) { in vop_create_crtc()
1796 drm_mode_crtc_set_gamma_size(crtc, vop_data->lut_size); in vop_create_crtc()
1797 drm_crtc_enable_color_mgmt(crtc, 0, false, vop_data->lut_size); in vop_create_crtc()
1804 for (i = 0; i < vop_data->win_size; i++) { in vop_create_crtc()
1805 struct vop_win *vop_win = &vop->win[i]; in vop_create_crtc()
1806 const struct vop_win_data *win_data = vop_win->data; in vop_create_crtc()
1809 if (win_data->type != DRM_PLANE_TYPE_OVERLAY) in vop_create_crtc()
1812 ret = drm_universal_plane_init(vop->drm_dev, &vop_win->base, in vop_create_crtc()
1815 win_data->phy->data_formats, in vop_create_crtc()
1816 win_data->phy->nformats, in vop_create_crtc()
1817 win_data->phy->format_modifiers, in vop_create_crtc()
1818 win_data->type, NULL); in vop_create_crtc()
1820 DRM_DEV_ERROR(vop->dev, "failed to init overlay %d\n", in vop_create_crtc()
1824 drm_plane_helper_add(&vop_win->base, &plane_helper_funcs); in vop_create_crtc()
1825 vop_plane_add_properties(&vop_win->base, win_data); in vop_create_crtc()
1828 port = of_get_child_by_name(dev->of_node, "port"); in vop_create_crtc()
1830 DRM_DEV_ERROR(vop->dev, "no port node found in %pOF\n", in vop_create_crtc()
1831 dev->of_node); in vop_create_crtc()
1832 ret = -ENOENT; in vop_create_crtc()
1836 drm_flip_work_init(&vop->fb_unref_work, "fb_unref", in vop_create_crtc()
1839 init_completion(&vop->dsp_hold_completion); in vop_create_crtc()
1840 init_completion(&vop->line_flag_completion); in vop_create_crtc()
1841 crtc->port = port; in vop_create_crtc()
1845 DRM_DEV_DEBUG_KMS(vop->dev, in vop_create_crtc()
1847 crtc->name, ret); in vop_create_crtc()
1854 list_for_each_entry_safe(plane, tmp, &drm_dev->mode_config.plane_list, in vop_create_crtc()
1862 struct drm_crtc *crtc = &vop->crtc; in vop_destroy_crtc()
1863 struct drm_device *drm_dev = vop->drm_dev; in vop_destroy_crtc()
1868 of_node_put(crtc->port); in vop_destroy_crtc()
1873 * The planes are "&vop->win[i].base". That means the memory is in vop_destroy_crtc()
1878 list_for_each_entry_safe(plane, tmp, &drm_dev->mode_config.plane_list, in vop_destroy_crtc()
1887 drm_flip_work_cleanup(&vop->fb_unref_work); in vop_destroy_crtc()
1895 vop->hclk = devm_clk_get(vop->dev, "hclk_vop"); in vop_initial()
1896 if (IS_ERR(vop->hclk)) { in vop_initial()
1897 DRM_DEV_ERROR(vop->dev, "failed to get hclk source\n"); in vop_initial()
1898 return PTR_ERR(vop->hclk); in vop_initial()
1900 vop->aclk = devm_clk_get(vop->dev, "aclk_vop"); in vop_initial()
1901 if (IS_ERR(vop->aclk)) { in vop_initial()
1902 DRM_DEV_ERROR(vop->dev, "failed to get aclk source\n"); in vop_initial()
1903 return PTR_ERR(vop->aclk); in vop_initial()
1905 vop->dclk = devm_clk_get(vop->dev, "dclk_vop"); in vop_initial()
1906 if (IS_ERR(vop->dclk)) { in vop_initial()
1907 DRM_DEV_ERROR(vop->dev, "failed to get dclk source\n"); in vop_initial()
1908 return PTR_ERR(vop->dclk); in vop_initial()
1911 ret = pm_runtime_get_sync(vop->dev); in vop_initial()
1913 DRM_DEV_ERROR(vop->dev, "failed to get pm runtime: %d\n", ret); in vop_initial()
1917 ret = clk_prepare(vop->dclk); in vop_initial()
1919 DRM_DEV_ERROR(vop->dev, "failed to prepare dclk\n"); in vop_initial()
1924 ret = clk_prepare_enable(vop->hclk); in vop_initial()
1926 DRM_DEV_ERROR(vop->dev, "failed to prepare/enable hclk\n"); in vop_initial()
1930 ret = clk_prepare_enable(vop->aclk); in vop_initial()
1932 DRM_DEV_ERROR(vop->dev, "failed to prepare/enable aclk\n"); in vop_initial()
1939 ahb_rst = devm_reset_control_get(vop->dev, "ahb"); in vop_initial()
1941 DRM_DEV_ERROR(vop->dev, "failed to get ahb reset\n"); in vop_initial()
1952 for (i = 0; i < vop->len; i += sizeof(u32)) in vop_initial()
1953 vop->regsbak[i / 4] = readl_relaxed(vop->regs + i); in vop_initial()
1958 for (i = 0; i < vop->data->win_size; i++) { in vop_initial()
1959 struct vop_win *vop_win = &vop->win[i]; in vop_initial()
1960 const struct vop_win_data *win = vop_win->data; in vop_initial()
1973 vop->dclk_rst = devm_reset_control_get(vop->dev, "dclk"); in vop_initial()
1974 if (IS_ERR(vop->dclk_rst)) { in vop_initial()
1975 DRM_DEV_ERROR(vop->dev, "failed to get dclk reset\n"); in vop_initial()
1976 ret = PTR_ERR(vop->dclk_rst); in vop_initial()
1979 reset_control_assert(vop->dclk_rst); in vop_initial()
1981 reset_control_deassert(vop->dclk_rst); in vop_initial()
1983 clk_disable(vop->hclk); in vop_initial()
1984 clk_disable(vop->aclk); in vop_initial()
1986 vop->is_enabled = false; in vop_initial()
1988 pm_runtime_put_sync(vop->dev); in vop_initial()
1993 clk_disable_unprepare(vop->aclk); in vop_initial()
1995 clk_disable_unprepare(vop->hclk); in vop_initial()
1997 clk_unprepare(vop->dclk); in vop_initial()
1999 pm_runtime_put_sync(vop->dev); in vop_initial()
2004 * Initialize the vop->win array elements.
2008 const struct vop_data *vop_data = vop->data; in vop_win_init()
2011 for (i = 0; i < vop_data->win_size; i++) { in vop_win_init()
2012 struct vop_win *vop_win = &vop->win[i]; in vop_win_init()
2013 const struct vop_win_data *win_data = &vop_data->win[i]; in vop_win_init()
2015 vop_win->data = win_data; in vop_win_init()
2016 vop_win->vop = vop; in vop_win_init()
2018 if (vop_data->win_yuv2yuv) in vop_win_init()
2019 vop_win->yuv2yuv_data = &vop_data->win_yuv2yuv[i]; in vop_win_init()
2039 if (!crtc || !vop->is_enabled) in rockchip_drm_wait_vact_end()
2040 return -ENODEV; in rockchip_drm_wait_vact_end()
2042 mutex_lock(&vop->vop_lock); in rockchip_drm_wait_vact_end()
2044 ret = -EINVAL; in rockchip_drm_wait_vact_end()
2049 ret = -EBUSY; in rockchip_drm_wait_vact_end()
2053 reinit_completion(&vop->line_flag_completion); in rockchip_drm_wait_vact_end()
2056 jiffies_left = wait_for_completion_timeout(&vop->line_flag_completion, in rockchip_drm_wait_vact_end()
2061 DRM_DEV_ERROR(vop->dev, "Timeout waiting for IRQ\n"); in rockchip_drm_wait_vact_end()
2062 ret = -ETIMEDOUT; in rockchip_drm_wait_vact_end()
2067 mutex_unlock(&vop->vop_lock); in rockchip_drm_wait_vact_end()
2083 return -ENODEV; in vop_bind()
2086 vop = devm_kzalloc(dev, struct_size(vop, win, vop_data->win_size), in vop_bind()
2089 return -ENOMEM; in vop_bind()
2091 vop->dev = dev; in vop_bind()
2092 vop->data = vop_data; in vop_bind()
2093 vop->drm_dev = drm_dev; in vop_bind()
2099 vop->len = resource_size(res); in vop_bind()
2100 vop->regs = devm_ioremap_resource(dev, res); in vop_bind()
2101 if (IS_ERR(vop->regs)) in vop_bind()
2102 return PTR_ERR(vop->regs); in vop_bind()
2106 if (!vop_data->lut_size) { in vop_bind()
2108 return -EINVAL; in vop_bind()
2110 vop->lut_regs = devm_ioremap_resource(dev, res); in vop_bind()
2111 if (IS_ERR(vop->lut_regs)) in vop_bind()
2112 return PTR_ERR(vop->lut_regs); in vop_bind()
2115 vop->regsbak = devm_kzalloc(dev, vop->len, GFP_KERNEL); in vop_bind()
2116 if (!vop->regsbak) in vop_bind()
2117 return -ENOMEM; in vop_bind()
2124 vop->irq = (unsigned int)irq; in vop_bind()
2126 spin_lock_init(&vop->reg_lock); in vop_bind()
2127 spin_lock_init(&vop->irq_lock); in vop_bind()
2128 mutex_init(&vop->vop_lock); in vop_bind()
2134 pm_runtime_enable(&pdev->dev); in vop_bind()
2138 DRM_DEV_ERROR(&pdev->dev, in vop_bind()
2139 "cannot initial vop dev - err %d\n", ret); in vop_bind()
2143 ret = devm_request_irq(dev, vop->irq, vop_isr, in vop_bind()
2148 if (vop->data->feature & VOP_FEATURE_INTERNAL_RGB) { in vop_bind()
2149 vop->rgb = rockchip_rgb_init(dev, &vop->crtc, vop->drm_dev); in vop_bind()
2150 if (IS_ERR(vop->rgb)) { in vop_bind()
2151 ret = PTR_ERR(vop->rgb); in vop_bind()
2159 pm_runtime_disable(&pdev->dev); in vop_bind()
2168 if (vop->rgb) in vop_unbind()
2169 rockchip_rgb_fini(vop->rgb); in vop_unbind()
2174 clk_unprepare(vop->aclk); in vop_unbind()
2175 clk_unprepare(vop->hclk); in vop_unbind()
2176 clk_unprepare(vop->dclk); in vop_unbind()