1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd
4 * Author:Mark Yao <mark.yao@rock-chips.com>
8 #include <linux/component.h>
9 #include <linux/delay.h>
10 #include <linux/iopoll.h>
11 #include <linux/kernel.h>
12 #include <linux/module.h>
14 #include <linux/of_device.h>
15 #include <linux/overflow.h>
16 #include <linux/platform_device.h>
17 #include <linux/pm_runtime.h>
18 #include <linux/reset.h>
21 #include <drm/drm_atomic.h>
22 #include <drm/drm_atomic_uapi.h>
23 #include <drm/drm_crtc.h>
24 #include <drm/drm_flip_work.h>
25 #include <drm/drm_fourcc.h>
26 #include <drm/drm_gem_framebuffer_helper.h>
27 #include <drm/drm_plane_helper.h>
28 #include <drm/drm_probe_helper.h>
29 #include <drm/drm_self_refresh_helper.h>
30 #include <drm/drm_vblank.h>
32 #ifdef CONFIG_DRM_ANALOGIX_DP
33 #include <drm/bridge/analogix_dp.h>
36 #include "rockchip_drm_drv.h"
37 #include "rockchip_drm_gem.h"
38 #include "rockchip_drm_fb.h"
39 #include "rockchip_drm_vop.h"
40 #include "rockchip_rgb.h"
42 #define VOP_WIN_SET(vop, win, name, v) \
43 vop_reg_set(vop, &win->phy->name, win->base, ~0, v, #name)
44 #define VOP_SCL_SET(vop, win, name, v) \
45 vop_reg_set(vop, &win->phy->scl->name, win->base, ~0, v, #name)
46 #define VOP_SCL_SET_EXT(vop, win, name, v) \
47 vop_reg_set(vop, &win->phy->scl->ext->name, \
48 win->base, ~0, v, #name)
50 #define VOP_WIN_YUV2YUV_SET(vop, win_yuv2yuv, name, v) \
52 if (win_yuv2yuv && win_yuv2yuv->name.mask) \
53 vop_reg_set(vop, &win_yuv2yuv->name, 0, ~0, v, #name); \
56 #define VOP_WIN_YUV2YUV_COEFFICIENT_SET(vop, win_yuv2yuv, name, v) \
58 if (win_yuv2yuv && win_yuv2yuv->phy->name.mask) \
59 vop_reg_set(vop, &win_yuv2yuv->phy->name, win_yuv2yuv->base, ~0, v, #name); \
62 #define VOP_INTR_SET_MASK(vop, name, mask, v) \
63 vop_reg_set(vop, &vop->data->intr->name, 0, mask, v, #name)
65 #define VOP_REG_SET(vop, group, name, v) \
66 vop_reg_set(vop, &vop->data->group->name, 0, ~0, v, #name)
68 #define VOP_INTR_SET_TYPE(vop, name, type, v) \
70 int i, reg = 0, mask = 0; \
71 for (i = 0; i < vop->data->intr->nintrs; i++) { \
72 if (vop->data->intr->intrs[i] & type) { \
77 VOP_INTR_SET_MASK(vop, name, mask, reg); \
79 #define VOP_INTR_GET_TYPE(vop, name, type) \
80 vop_get_intr_type(vop, &vop->data->intr->name, type)
82 #define VOP_WIN_GET(vop, win, name) \
83 vop_read_reg(vop, win->base, &win->phy->name)
85 #define VOP_WIN_HAS_REG(win, name) \
86 (!!(win->phy->name.mask))
88 #define VOP_WIN_GET_YRGBADDR(vop, win) \
89 vop_readl(vop, win->base + win->phy->yrgb_mst.offset)
91 #define VOP_WIN_TO_INDEX(vop_win) \
92 ((vop_win) - (vop_win)->vop->win)
94 #define to_vop(x) container_of(x, struct vop, crtc)
95 #define to_vop_win(x) container_of(x, struct vop_win, base)
98 * The coefficients of the following matrix are all fixed points.
99 * The format is S2.10 for the 3x3 part of the matrix, and S9.12 for the offsets.
100 * They are all represented in two's complement.
102 static const uint32_t bt601_yuv2rgb
[] = {
104 0x4A8, 0x1E6F, 0x1CBF,
106 0x321168, 0x0877CF, 0x2EB127
110 VOP_PENDING_FB_UNREF
,
114 struct drm_plane base
;
115 const struct vop_win_data
*data
;
116 const struct vop_win_yuv2yuv_data
*yuv2yuv_data
;
122 struct drm_crtc crtc
;
124 struct drm_device
*drm_dev
;
127 struct completion dsp_hold_completion
;
128 unsigned int win_enabled
;
130 /* protected by dev->event_lock */
131 struct drm_pending_vblank_event
*event
;
133 struct drm_flip_work fb_unref_work
;
134 unsigned long pending
;
136 struct completion line_flag_completion
;
138 const struct vop_data
*data
;
142 void __iomem
*lut_regs
;
144 /* physical map length of vop register */
147 /* one time only one process allowed to config the register */
149 /* lock vop irq reg */
151 /* protects crtc enable/disable */
152 struct mutex vop_lock
;
160 /* vop share memory frequency */
164 struct reset_control
*dclk_rst
;
166 /* optional internal rgb encoder */
167 struct rockchip_rgb
*rgb
;
169 struct vop_win win
[];
172 static inline void vop_writel(struct vop
*vop
, uint32_t offset
, uint32_t v
)
174 writel(v
, vop
->regs
+ offset
);
175 vop
->regsbak
[offset
>> 2] = v
;
178 static inline uint32_t vop_readl(struct vop
*vop
, uint32_t offset
)
180 return readl(vop
->regs
+ offset
);
183 static inline uint32_t vop_read_reg(struct vop
*vop
, uint32_t base
,
184 const struct vop_reg
*reg
)
186 return (vop_readl(vop
, base
+ reg
->offset
) >> reg
->shift
) & reg
->mask
;
189 static void vop_reg_set(struct vop
*vop
, const struct vop_reg
*reg
,
190 uint32_t _offset
, uint32_t _mask
, uint32_t v
,
191 const char *reg_name
)
193 int offset
, mask
, shift
;
195 if (!reg
|| !reg
->mask
) {
196 DRM_DEV_DEBUG(vop
->dev
, "Warning: not support %s\n", reg_name
);
200 offset
= reg
->offset
+ _offset
;
201 mask
= reg
->mask
& _mask
;
204 if (reg
->write_mask
) {
205 v
= ((v
<< shift
) & 0xffff) | (mask
<< (shift
+ 16));
207 uint32_t cached_val
= vop
->regsbak
[offset
>> 2];
209 v
= (cached_val
& ~(mask
<< shift
)) | ((v
& mask
) << shift
);
210 vop
->regsbak
[offset
>> 2] = v
;
214 writel_relaxed(v
, vop
->regs
+ offset
);
216 writel(v
, vop
->regs
+ offset
);
219 static inline uint32_t vop_get_intr_type(struct vop
*vop
,
220 const struct vop_reg
*reg
, int type
)
223 uint32_t regs
= vop_read_reg(vop
, 0, reg
);
225 for (i
= 0; i
< vop
->data
->intr
->nintrs
; i
++) {
226 if ((type
& vop
->data
->intr
->intrs
[i
]) && (regs
& 1 << i
))
227 ret
|= vop
->data
->intr
->intrs
[i
];
233 static inline void vop_cfg_done(struct vop
*vop
)
235 VOP_REG_SET(vop
, common
, cfg_done
, 1);
238 static bool has_rb_swapped(uint32_t format
)
241 case DRM_FORMAT_XBGR8888
:
242 case DRM_FORMAT_ABGR8888
:
243 case DRM_FORMAT_BGR888
:
244 case DRM_FORMAT_BGR565
:
251 static enum vop_data_format
vop_convert_format(uint32_t format
)
254 case DRM_FORMAT_XRGB8888
:
255 case DRM_FORMAT_ARGB8888
:
256 case DRM_FORMAT_XBGR8888
:
257 case DRM_FORMAT_ABGR8888
:
258 return VOP_FMT_ARGB8888
;
259 case DRM_FORMAT_RGB888
:
260 case DRM_FORMAT_BGR888
:
261 return VOP_FMT_RGB888
;
262 case DRM_FORMAT_RGB565
:
263 case DRM_FORMAT_BGR565
:
264 return VOP_FMT_RGB565
;
265 case DRM_FORMAT_NV12
:
266 return VOP_FMT_YUV420SP
;
267 case DRM_FORMAT_NV16
:
268 return VOP_FMT_YUV422SP
;
269 case DRM_FORMAT_NV24
:
270 return VOP_FMT_YUV444SP
;
272 DRM_ERROR("unsupported format[%08x]\n", format
);
277 static uint16_t scl_vop_cal_scale(enum scale_mode mode
, uint32_t src
,
278 uint32_t dst
, bool is_horizontal
,
279 int vsu_mode
, int *vskiplines
)
281 uint16_t val
= 1 << SCL_FT_DEFAULT_FIXPOINT_SHIFT
;
287 if (mode
== SCALE_UP
)
288 val
= GET_SCL_FT_BIC(src
, dst
);
289 else if (mode
== SCALE_DOWN
)
290 val
= GET_SCL_FT_BILI_DN(src
, dst
);
292 if (mode
== SCALE_UP
) {
293 if (vsu_mode
== SCALE_UP_BIL
)
294 val
= GET_SCL_FT_BILI_UP(src
, dst
);
296 val
= GET_SCL_FT_BIC(src
, dst
);
297 } else if (mode
== SCALE_DOWN
) {
299 *vskiplines
= scl_get_vskiplines(src
, dst
);
300 val
= scl_get_bili_dn_vskip(src
, dst
,
303 val
= GET_SCL_FT_BILI_DN(src
, dst
);
311 static void scl_vop_cal_scl_fac(struct vop
*vop
, const struct vop_win_data
*win
,
312 uint32_t src_w
, uint32_t src_h
, uint32_t dst_w
,
313 uint32_t dst_h
, const struct drm_format_info
*info
)
315 uint16_t yrgb_hor_scl_mode
, yrgb_ver_scl_mode
;
316 uint16_t cbcr_hor_scl_mode
= SCALE_NONE
;
317 uint16_t cbcr_ver_scl_mode
= SCALE_NONE
;
319 uint16_t cbcr_src_w
= src_w
/ info
->hsub
;
320 uint16_t cbcr_src_h
= src_h
/ info
->vsub
;
330 DRM_DEV_ERROR(vop
->dev
, "Maximum dst width (3840) exceeded\n");
334 if (!win
->phy
->scl
->ext
) {
335 VOP_SCL_SET(vop
, win
, scale_yrgb_x
,
336 scl_cal_scale2(src_w
, dst_w
));
337 VOP_SCL_SET(vop
, win
, scale_yrgb_y
,
338 scl_cal_scale2(src_h
, dst_h
));
340 VOP_SCL_SET(vop
, win
, scale_cbcr_x
,
341 scl_cal_scale2(cbcr_src_w
, dst_w
));
342 VOP_SCL_SET(vop
, win
, scale_cbcr_y
,
343 scl_cal_scale2(cbcr_src_h
, dst_h
));
348 yrgb_hor_scl_mode
= scl_get_scl_mode(src_w
, dst_w
);
349 yrgb_ver_scl_mode
= scl_get_scl_mode(src_h
, dst_h
);
352 cbcr_hor_scl_mode
= scl_get_scl_mode(cbcr_src_w
, dst_w
);
353 cbcr_ver_scl_mode
= scl_get_scl_mode(cbcr_src_h
, dst_h
);
354 if (cbcr_hor_scl_mode
== SCALE_DOWN
)
355 lb_mode
= scl_vop_cal_lb_mode(dst_w
, true);
357 lb_mode
= scl_vop_cal_lb_mode(cbcr_src_w
, true);
359 if (yrgb_hor_scl_mode
== SCALE_DOWN
)
360 lb_mode
= scl_vop_cal_lb_mode(dst_w
, false);
362 lb_mode
= scl_vop_cal_lb_mode(src_w
, false);
365 VOP_SCL_SET_EXT(vop
, win
, lb_mode
, lb_mode
);
366 if (lb_mode
== LB_RGB_3840X2
) {
367 if (yrgb_ver_scl_mode
!= SCALE_NONE
) {
368 DRM_DEV_ERROR(vop
->dev
, "not allow yrgb ver scale\n");
371 if (cbcr_ver_scl_mode
!= SCALE_NONE
) {
372 DRM_DEV_ERROR(vop
->dev
, "not allow cbcr ver scale\n");
375 vsu_mode
= SCALE_UP_BIL
;
376 } else if (lb_mode
== LB_RGB_2560X4
) {
377 vsu_mode
= SCALE_UP_BIL
;
379 vsu_mode
= SCALE_UP_BIC
;
382 val
= scl_vop_cal_scale(yrgb_hor_scl_mode
, src_w
, dst_w
,
384 VOP_SCL_SET(vop
, win
, scale_yrgb_x
, val
);
385 val
= scl_vop_cal_scale(yrgb_ver_scl_mode
, src_h
, dst_h
,
386 false, vsu_mode
, &vskiplines
);
387 VOP_SCL_SET(vop
, win
, scale_yrgb_y
, val
);
389 VOP_SCL_SET_EXT(vop
, win
, vsd_yrgb_gt4
, vskiplines
== 4);
390 VOP_SCL_SET_EXT(vop
, win
, vsd_yrgb_gt2
, vskiplines
== 2);
392 VOP_SCL_SET_EXT(vop
, win
, yrgb_hor_scl_mode
, yrgb_hor_scl_mode
);
393 VOP_SCL_SET_EXT(vop
, win
, yrgb_ver_scl_mode
, yrgb_ver_scl_mode
);
394 VOP_SCL_SET_EXT(vop
, win
, yrgb_hsd_mode
, SCALE_DOWN_BIL
);
395 VOP_SCL_SET_EXT(vop
, win
, yrgb_vsd_mode
, SCALE_DOWN_BIL
);
396 VOP_SCL_SET_EXT(vop
, win
, yrgb_vsu_mode
, vsu_mode
);
398 val
= scl_vop_cal_scale(cbcr_hor_scl_mode
, cbcr_src_w
,
399 dst_w
, true, 0, NULL
);
400 VOP_SCL_SET(vop
, win
, scale_cbcr_x
, val
);
401 val
= scl_vop_cal_scale(cbcr_ver_scl_mode
, cbcr_src_h
,
402 dst_h
, false, vsu_mode
, &vskiplines
);
403 VOP_SCL_SET(vop
, win
, scale_cbcr_y
, val
);
405 VOP_SCL_SET_EXT(vop
, win
, vsd_cbcr_gt4
, vskiplines
== 4);
406 VOP_SCL_SET_EXT(vop
, win
, vsd_cbcr_gt2
, vskiplines
== 2);
407 VOP_SCL_SET_EXT(vop
, win
, cbcr_hor_scl_mode
, cbcr_hor_scl_mode
);
408 VOP_SCL_SET_EXT(vop
, win
, cbcr_ver_scl_mode
, cbcr_ver_scl_mode
);
409 VOP_SCL_SET_EXT(vop
, win
, cbcr_hsd_mode
, SCALE_DOWN_BIL
);
410 VOP_SCL_SET_EXT(vop
, win
, cbcr_vsd_mode
, SCALE_DOWN_BIL
);
411 VOP_SCL_SET_EXT(vop
, win
, cbcr_vsu_mode
, vsu_mode
);
415 static void vop_dsp_hold_valid_irq_enable(struct vop
*vop
)
419 if (WARN_ON(!vop
->is_enabled
))
422 spin_lock_irqsave(&vop
->irq_lock
, flags
);
424 VOP_INTR_SET_TYPE(vop
, clear
, DSP_HOLD_VALID_INTR
, 1);
425 VOP_INTR_SET_TYPE(vop
, enable
, DSP_HOLD_VALID_INTR
, 1);
427 spin_unlock_irqrestore(&vop
->irq_lock
, flags
);
430 static void vop_dsp_hold_valid_irq_disable(struct vop
*vop
)
434 if (WARN_ON(!vop
->is_enabled
))
437 spin_lock_irqsave(&vop
->irq_lock
, flags
);
439 VOP_INTR_SET_TYPE(vop
, enable
, DSP_HOLD_VALID_INTR
, 0);
441 spin_unlock_irqrestore(&vop
->irq_lock
, flags
);
445 * (1) each frame starts at the start of the Vsync pulse which is signaled by
446 * the "FRAME_SYNC" interrupt.
447 * (2) the active data region of each frame ends at dsp_vact_end
448 * (3) we should program this same number (dsp_vact_end) into dsp_line_frag_num,
449 * to get "LINE_FLAG" interrupt at the end of the active on screen data.
451 * VOP_INTR_CTRL0.dsp_line_frag_num = VOP_DSP_VACT_ST_END.dsp_vact_end
453 * LINE_FLAG -------------------------------+
457 * | Vsync | Vbp | Vactive | Vfp |
461 * dsp_vs_end ------------+ | | | VOP_DSP_VTOTAL_VS_END
462 * dsp_vact_start --------------+ | | VOP_DSP_VACT_ST_END
463 * dsp_vact_end ----------------------------+ | VOP_DSP_VACT_ST_END
464 * dsp_total -------------------------------------+ VOP_DSP_VTOTAL_VS_END
466 static bool vop_line_flag_irq_is_enabled(struct vop
*vop
)
468 uint32_t line_flag_irq
;
471 spin_lock_irqsave(&vop
->irq_lock
, flags
);
473 line_flag_irq
= VOP_INTR_GET_TYPE(vop
, enable
, LINE_FLAG_INTR
);
475 spin_unlock_irqrestore(&vop
->irq_lock
, flags
);
477 return !!line_flag_irq
;
480 static void vop_line_flag_irq_enable(struct vop
*vop
)
484 if (WARN_ON(!vop
->is_enabled
))
487 spin_lock_irqsave(&vop
->irq_lock
, flags
);
489 VOP_INTR_SET_TYPE(vop
, clear
, LINE_FLAG_INTR
, 1);
490 VOP_INTR_SET_TYPE(vop
, enable
, LINE_FLAG_INTR
, 1);
492 spin_unlock_irqrestore(&vop
->irq_lock
, flags
);
495 static void vop_line_flag_irq_disable(struct vop
*vop
)
499 if (WARN_ON(!vop
->is_enabled
))
502 spin_lock_irqsave(&vop
->irq_lock
, flags
);
504 VOP_INTR_SET_TYPE(vop
, enable
, LINE_FLAG_INTR
, 0);
506 spin_unlock_irqrestore(&vop
->irq_lock
, flags
);
509 static int vop_core_clks_enable(struct vop
*vop
)
513 ret
= clk_enable(vop
->hclk
);
517 ret
= clk_enable(vop
->aclk
);
519 goto err_disable_hclk
;
524 clk_disable(vop
->hclk
);
528 static void vop_core_clks_disable(struct vop
*vop
)
530 clk_disable(vop
->aclk
);
531 clk_disable(vop
->hclk
);
534 static void vop_win_disable(struct vop
*vop
, const struct vop_win
*vop_win
)
536 const struct vop_win_data
*win
= vop_win
->data
;
538 if (win
->phy
->scl
&& win
->phy
->scl
->ext
) {
539 VOP_SCL_SET_EXT(vop
, win
, yrgb_hor_scl_mode
, SCALE_NONE
);
540 VOP_SCL_SET_EXT(vop
, win
, yrgb_ver_scl_mode
, SCALE_NONE
);
541 VOP_SCL_SET_EXT(vop
, win
, cbcr_hor_scl_mode
, SCALE_NONE
);
542 VOP_SCL_SET_EXT(vop
, win
, cbcr_ver_scl_mode
, SCALE_NONE
);
545 VOP_WIN_SET(vop
, win
, enable
, 0);
546 vop
->win_enabled
&= ~BIT(VOP_WIN_TO_INDEX(vop_win
));
549 static int vop_enable(struct drm_crtc
*crtc
, struct drm_crtc_state
*old_state
)
551 struct vop
*vop
= to_vop(crtc
);
554 ret
= pm_runtime_get_sync(vop
->dev
);
556 DRM_DEV_ERROR(vop
->dev
, "failed to get pm runtime: %d\n", ret
);
560 ret
= vop_core_clks_enable(vop
);
561 if (WARN_ON(ret
< 0))
562 goto err_put_pm_runtime
;
564 ret
= clk_enable(vop
->dclk
);
565 if (WARN_ON(ret
< 0))
566 goto err_disable_core
;
569 * Slave iommu shares power, irq and clock with vop. It was associated
570 * automatically with this master device via common driver code.
571 * Now that we have enabled the clock we attach it to the shared drm
574 ret
= rockchip_drm_dma_attach_device(vop
->drm_dev
, vop
->dev
);
576 DRM_DEV_ERROR(vop
->dev
,
577 "failed to attach dma mapping, %d\n", ret
);
578 goto err_disable_dclk
;
581 spin_lock(&vop
->reg_lock
);
582 for (i
= 0; i
< vop
->len
; i
+= 4)
583 writel_relaxed(vop
->regsbak
[i
/ 4], vop
->regs
+ i
);
586 * We need to make sure that all windows are disabled before we
587 * enable the crtc. Otherwise we might try to scan from a destroyed
590 * In the case of enable-after-PSR, we don't need to worry about this
591 * case since the buffer is guaranteed to be valid and disabling the
592 * window will result in screen glitches on PSR exit.
594 if (!old_state
|| !old_state
->self_refresh_active
) {
595 for (i
= 0; i
< vop
->data
->win_size
; i
++) {
596 struct vop_win
*vop_win
= &vop
->win
[i
];
598 vop_win_disable(vop
, vop_win
);
601 spin_unlock(&vop
->reg_lock
);
606 * At here, vop clock & iommu is enable, R/W vop regs would be safe.
608 vop
->is_enabled
= true;
610 spin_lock(&vop
->reg_lock
);
612 VOP_REG_SET(vop
, common
, standby
, 1);
614 spin_unlock(&vop
->reg_lock
);
616 drm_crtc_vblank_on(crtc
);
621 clk_disable(vop
->dclk
);
623 vop_core_clks_disable(vop
);
625 pm_runtime_put_sync(vop
->dev
);
629 static void rockchip_drm_set_win_enabled(struct drm_crtc
*crtc
, bool enabled
)
631 struct vop
*vop
= to_vop(crtc
);
634 spin_lock(&vop
->reg_lock
);
636 for (i
= 0; i
< vop
->data
->win_size
; i
++) {
637 struct vop_win
*vop_win
= &vop
->win
[i
];
638 const struct vop_win_data
*win
= vop_win
->data
;
640 VOP_WIN_SET(vop
, win
, enable
,
641 enabled
&& (vop
->win_enabled
& BIT(i
)));
645 spin_unlock(&vop
->reg_lock
);
648 static void vop_crtc_atomic_disable(struct drm_crtc
*crtc
,
649 struct drm_crtc_state
*old_state
)
651 struct vop
*vop
= to_vop(crtc
);
655 if (crtc
->state
->self_refresh_active
)
656 rockchip_drm_set_win_enabled(crtc
, false);
658 mutex_lock(&vop
->vop_lock
);
660 drm_crtc_vblank_off(crtc
);
662 if (crtc
->state
->self_refresh_active
)
666 * Vop standby will take effect at end of current frame,
667 * if dsp hold valid irq happen, it means standby complete.
669 * we must wait standby complete when we want to disable aclk,
670 * if not, memory bus maybe dead.
672 reinit_completion(&vop
->dsp_hold_completion
);
673 vop_dsp_hold_valid_irq_enable(vop
);
675 spin_lock(&vop
->reg_lock
);
677 VOP_REG_SET(vop
, common
, standby
, 1);
679 spin_unlock(&vop
->reg_lock
);
681 wait_for_completion(&vop
->dsp_hold_completion
);
683 vop_dsp_hold_valid_irq_disable(vop
);
685 vop
->is_enabled
= false;
688 * vop standby complete, so iommu detach is safe.
690 rockchip_drm_dma_detach_device(vop
->drm_dev
, vop
->dev
);
692 clk_disable(vop
->dclk
);
693 vop_core_clks_disable(vop
);
694 pm_runtime_put(vop
->dev
);
697 mutex_unlock(&vop
->vop_lock
);
699 if (crtc
->state
->event
&& !crtc
->state
->active
) {
700 spin_lock_irq(&crtc
->dev
->event_lock
);
701 drm_crtc_send_vblank_event(crtc
, crtc
->state
->event
);
702 spin_unlock_irq(&crtc
->dev
->event_lock
);
704 crtc
->state
->event
= NULL
;
708 static void vop_plane_destroy(struct drm_plane
*plane
)
710 drm_plane_cleanup(plane
);
713 static int vop_plane_atomic_check(struct drm_plane
*plane
,
714 struct drm_plane_state
*state
)
716 struct drm_crtc
*crtc
= state
->crtc
;
717 struct drm_crtc_state
*crtc_state
;
718 struct drm_framebuffer
*fb
= state
->fb
;
719 struct vop_win
*vop_win
= to_vop_win(plane
);
720 const struct vop_win_data
*win
= vop_win
->data
;
722 int min_scale
= win
->phy
->scl
? FRAC_16_16(1, 8) :
723 DRM_PLANE_HELPER_NO_SCALING
;
724 int max_scale
= win
->phy
->scl
? FRAC_16_16(8, 1) :
725 DRM_PLANE_HELPER_NO_SCALING
;
730 crtc_state
= drm_atomic_get_existing_crtc_state(state
->state
, crtc
);
731 if (WARN_ON(!crtc_state
))
734 ret
= drm_atomic_helper_check_plane_state(state
, crtc_state
,
735 min_scale
, max_scale
,
743 ret
= vop_convert_format(fb
->format
->format
);
748 * Src.x1 can be odd when do clip, but yuv plane start point
749 * need align with 2 pixel.
751 if (fb
->format
->is_yuv
&& ((state
->src
.x1
>> 16) % 2)) {
752 DRM_ERROR("Invalid Source: Yuv format not support odd xpos\n");
756 if (fb
->format
->is_yuv
&& state
->rotation
& DRM_MODE_REFLECT_Y
) {
757 DRM_ERROR("Invalid Source: Yuv format does not support this rotation\n");
764 static void vop_plane_atomic_disable(struct drm_plane
*plane
,
765 struct drm_plane_state
*old_state
)
767 struct vop_win
*vop_win
= to_vop_win(plane
);
768 struct vop
*vop
= to_vop(old_state
->crtc
);
770 if (!old_state
->crtc
)
773 spin_lock(&vop
->reg_lock
);
775 vop_win_disable(vop
, vop_win
);
777 spin_unlock(&vop
->reg_lock
);
780 static void vop_plane_atomic_update(struct drm_plane
*plane
,
781 struct drm_plane_state
*old_state
)
783 struct drm_plane_state
*state
= plane
->state
;
784 struct drm_crtc
*crtc
= state
->crtc
;
785 struct vop_win
*vop_win
= to_vop_win(plane
);
786 const struct vop_win_data
*win
= vop_win
->data
;
787 const struct vop_win_yuv2yuv_data
*win_yuv2yuv
= vop_win
->yuv2yuv_data
;
788 struct vop
*vop
= to_vop(state
->crtc
);
789 struct drm_framebuffer
*fb
= state
->fb
;
790 unsigned int actual_w
, actual_h
;
791 unsigned int dsp_stx
, dsp_sty
;
792 uint32_t act_info
, dsp_info
, dsp_st
;
793 struct drm_rect
*src
= &state
->src
;
794 struct drm_rect
*dest
= &state
->dst
;
795 struct drm_gem_object
*obj
, *uv_obj
;
796 struct rockchip_gem_object
*rk_obj
, *rk_uv_obj
;
797 unsigned long offset
;
801 int win_index
= VOP_WIN_TO_INDEX(vop_win
);
803 int is_yuv
= fb
->format
->is_yuv
;
807 * can't update plane when vop is disabled.
812 if (WARN_ON(!vop
->is_enabled
))
815 if (!state
->visible
) {
816 vop_plane_atomic_disable(plane
, old_state
);
821 rk_obj
= to_rockchip_obj(obj
);
823 actual_w
= drm_rect_width(src
) >> 16;
824 actual_h
= drm_rect_height(src
) >> 16;
825 act_info
= (actual_h
- 1) << 16 | ((actual_w
- 1) & 0xffff);
827 dsp_info
= (drm_rect_height(dest
) - 1) << 16;
828 dsp_info
|= (drm_rect_width(dest
) - 1) & 0xffff;
830 dsp_stx
= dest
->x1
+ crtc
->mode
.htotal
- crtc
->mode
.hsync_start
;
831 dsp_sty
= dest
->y1
+ crtc
->mode
.vtotal
- crtc
->mode
.vsync_start
;
832 dsp_st
= dsp_sty
<< 16 | (dsp_stx
& 0xffff);
834 offset
= (src
->x1
>> 16) * fb
->format
->cpp
[0];
835 offset
+= (src
->y1
>> 16) * fb
->pitches
[0];
836 dma_addr
= rk_obj
->dma_addr
+ offset
+ fb
->offsets
[0];
839 * For y-mirroring we need to move address
840 * to the beginning of the last line.
842 if (state
->rotation
& DRM_MODE_REFLECT_Y
)
843 dma_addr
+= (actual_h
- 1) * fb
->pitches
[0];
845 format
= vop_convert_format(fb
->format
->format
);
847 spin_lock(&vop
->reg_lock
);
849 VOP_WIN_SET(vop
, win
, format
, format
);
850 VOP_WIN_SET(vop
, win
, yrgb_vir
, DIV_ROUND_UP(fb
->pitches
[0], 4));
851 VOP_WIN_SET(vop
, win
, yrgb_mst
, dma_addr
);
852 VOP_WIN_YUV2YUV_SET(vop
, win_yuv2yuv
, y2r_en
, is_yuv
);
853 VOP_WIN_SET(vop
, win
, y_mir_en
,
854 (state
->rotation
& DRM_MODE_REFLECT_Y
) ? 1 : 0);
855 VOP_WIN_SET(vop
, win
, x_mir_en
,
856 (state
->rotation
& DRM_MODE_REFLECT_X
) ? 1 : 0);
859 int hsub
= fb
->format
->hsub
;
860 int vsub
= fb
->format
->vsub
;
861 int bpp
= fb
->format
->cpp
[1];
864 rk_uv_obj
= to_rockchip_obj(uv_obj
);
866 offset
= (src
->x1
>> 16) * bpp
/ hsub
;
867 offset
+= (src
->y1
>> 16) * fb
->pitches
[1] / vsub
;
869 dma_addr
= rk_uv_obj
->dma_addr
+ offset
+ fb
->offsets
[1];
870 VOP_WIN_SET(vop
, win
, uv_vir
, DIV_ROUND_UP(fb
->pitches
[1], 4));
871 VOP_WIN_SET(vop
, win
, uv_mst
, dma_addr
);
873 for (i
= 0; i
< NUM_YUV2YUV_COEFFICIENTS
; i
++) {
874 VOP_WIN_YUV2YUV_COEFFICIENT_SET(vop
,
882 scl_vop_cal_scl_fac(vop
, win
, actual_w
, actual_h
,
883 drm_rect_width(dest
), drm_rect_height(dest
),
886 VOP_WIN_SET(vop
, win
, act_info
, act_info
);
887 VOP_WIN_SET(vop
, win
, dsp_info
, dsp_info
);
888 VOP_WIN_SET(vop
, win
, dsp_st
, dsp_st
);
890 rb_swap
= has_rb_swapped(fb
->format
->format
);
891 VOP_WIN_SET(vop
, win
, rb_swap
, rb_swap
);
894 * Blending win0 with the background color doesn't seem to work
895 * correctly. We only get the background color, no matter the contents
896 * of the win0 framebuffer. However, blending pre-multiplied color
897 * with the default opaque black default background color is a no-op,
898 * so we can just disable blending to get the correct result.
900 if (fb
->format
->has_alpha
&& win_index
> 0) {
901 VOP_WIN_SET(vop
, win
, dst_alpha_ctl
,
902 DST_FACTOR_M0(ALPHA_SRC_INVERSE
));
903 val
= SRC_ALPHA_EN(1) | SRC_COLOR_M0(ALPHA_SRC_PRE_MUL
) |
904 SRC_ALPHA_M0(ALPHA_STRAIGHT
) |
905 SRC_BLEND_M0(ALPHA_PER_PIX
) |
906 SRC_ALPHA_CAL_M0(ALPHA_NO_SATURATION
) |
907 SRC_FACTOR_M0(ALPHA_ONE
);
908 VOP_WIN_SET(vop
, win
, src_alpha_ctl
, val
);
910 VOP_WIN_SET(vop
, win
, src_alpha_ctl
, SRC_ALPHA_EN(0));
913 VOP_WIN_SET(vop
, win
, enable
, 1);
914 vop
->win_enabled
|= BIT(win_index
);
915 spin_unlock(&vop
->reg_lock
);
918 static int vop_plane_atomic_async_check(struct drm_plane
*plane
,
919 struct drm_plane_state
*state
)
921 struct vop_win
*vop_win
= to_vop_win(plane
);
922 const struct vop_win_data
*win
= vop_win
->data
;
923 int min_scale
= win
->phy
->scl
? FRAC_16_16(1, 8) :
924 DRM_PLANE_HELPER_NO_SCALING
;
925 int max_scale
= win
->phy
->scl
? FRAC_16_16(8, 1) :
926 DRM_PLANE_HELPER_NO_SCALING
;
927 struct drm_crtc_state
*crtc_state
;
929 if (plane
!= state
->crtc
->cursor
)
935 if (!plane
->state
->fb
)
939 crtc_state
= drm_atomic_get_existing_crtc_state(state
->state
,
941 else /* Special case for asynchronous cursor updates. */
942 crtc_state
= plane
->crtc
->state
;
944 return drm_atomic_helper_check_plane_state(plane
->state
, crtc_state
,
945 min_scale
, max_scale
,
949 static void vop_plane_atomic_async_update(struct drm_plane
*plane
,
950 struct drm_plane_state
*new_state
)
952 struct vop
*vop
= to_vop(plane
->state
->crtc
);
953 struct drm_framebuffer
*old_fb
= plane
->state
->fb
;
955 plane
->state
->crtc_x
= new_state
->crtc_x
;
956 plane
->state
->crtc_y
= new_state
->crtc_y
;
957 plane
->state
->crtc_h
= new_state
->crtc_h
;
958 plane
->state
->crtc_w
= new_state
->crtc_w
;
959 plane
->state
->src_x
= new_state
->src_x
;
960 plane
->state
->src_y
= new_state
->src_y
;
961 plane
->state
->src_h
= new_state
->src_h
;
962 plane
->state
->src_w
= new_state
->src_w
;
963 swap(plane
->state
->fb
, new_state
->fb
);
965 if (vop
->is_enabled
) {
966 vop_plane_atomic_update(plane
, plane
->state
);
967 spin_lock(&vop
->reg_lock
);
969 spin_unlock(&vop
->reg_lock
);
972 * A scanout can still be occurring, so we can't drop the
973 * reference to the old framebuffer. To solve this we get a
974 * reference to old_fb and set a worker to release it later.
975 * FIXME: if we perform 500 async_update calls before the
976 * vblank, then we can have 500 different framebuffers waiting
979 if (old_fb
&& plane
->state
->fb
!= old_fb
) {
980 drm_framebuffer_get(old_fb
);
981 WARN_ON(drm_crtc_vblank_get(plane
->state
->crtc
) != 0);
982 drm_flip_work_queue(&vop
->fb_unref_work
, old_fb
);
983 set_bit(VOP_PENDING_FB_UNREF
, &vop
->pending
);
988 static const struct drm_plane_helper_funcs plane_helper_funcs
= {
989 .atomic_check
= vop_plane_atomic_check
,
990 .atomic_update
= vop_plane_atomic_update
,
991 .atomic_disable
= vop_plane_atomic_disable
,
992 .atomic_async_check
= vop_plane_atomic_async_check
,
993 .atomic_async_update
= vop_plane_atomic_async_update
,
994 .prepare_fb
= drm_gem_fb_prepare_fb
,
997 static const struct drm_plane_funcs vop_plane_funcs
= {
998 .update_plane
= drm_atomic_helper_update_plane
,
999 .disable_plane
= drm_atomic_helper_disable_plane
,
1000 .destroy
= vop_plane_destroy
,
1001 .reset
= drm_atomic_helper_plane_reset
,
1002 .atomic_duplicate_state
= drm_atomic_helper_plane_duplicate_state
,
1003 .atomic_destroy_state
= drm_atomic_helper_plane_destroy_state
,
1006 static int vop_crtc_enable_vblank(struct drm_crtc
*crtc
)
1008 struct vop
*vop
= to_vop(crtc
);
1009 unsigned long flags
;
1011 if (WARN_ON(!vop
->is_enabled
))
1014 spin_lock_irqsave(&vop
->irq_lock
, flags
);
1016 VOP_INTR_SET_TYPE(vop
, clear
, FS_INTR
, 1);
1017 VOP_INTR_SET_TYPE(vop
, enable
, FS_INTR
, 1);
1019 spin_unlock_irqrestore(&vop
->irq_lock
, flags
);
1024 static void vop_crtc_disable_vblank(struct drm_crtc
*crtc
)
1026 struct vop
*vop
= to_vop(crtc
);
1027 unsigned long flags
;
1029 if (WARN_ON(!vop
->is_enabled
))
1032 spin_lock_irqsave(&vop
->irq_lock
, flags
);
1034 VOP_INTR_SET_TYPE(vop
, enable
, FS_INTR
, 0);
1036 spin_unlock_irqrestore(&vop
->irq_lock
, flags
);
1039 static bool vop_crtc_mode_fixup(struct drm_crtc
*crtc
,
1040 const struct drm_display_mode
*mode
,
1041 struct drm_display_mode
*adjusted_mode
)
1043 struct vop
*vop
= to_vop(crtc
);
1051 * - DRM works in in kHz.
1052 * - Clock framework works in Hz.
1053 * - Rockchip's clock driver picks the clock rate that is the
1054 * same _OR LOWER_ than the one requested.
1058 * 1. When DRM gives us a mode, we should add 999 Hz to it. That way
1059 * if the clock we need is 60000001 Hz (~60 MHz) and DRM tells us to
1060 * make 60000 kHz then the clock framework will actually give us
1063 * NOTE: if the PLL (maybe through a divider) could actually make
1064 * a clock rate 999 Hz higher instead of the one we want then this
1065 * could be a problem. Unfortunately there's not much we can do
1066 * since it's baked into DRM to use kHz. It shouldn't matter in
1067 * practice since Rockchip PLLs are controlled by tables and
1068 * even if there is a divider in the middle I wouldn't expect PLL
1069 * rates in the table that are just a few kHz different.
1071 * 2. Get the clock framework to round the rate for us to tell us
1072 * what it will actually make.
1074 * 3. Store the rounded up rate so that we don't need to worry about
1075 * this in the actual clk_set_rate().
1077 rate
= clk_round_rate(vop
->dclk
, adjusted_mode
->clock
* 1000 + 999);
1078 adjusted_mode
->clock
= DIV_ROUND_UP(rate
, 1000);
1083 static bool vop_dsp_lut_is_enabled(struct vop
*vop
)
1085 return vop_read_reg(vop
, 0, &vop
->data
->common
->dsp_lut_en
);
1088 static void vop_crtc_write_gamma_lut(struct vop
*vop
, struct drm_crtc
*crtc
)
1090 struct drm_color_lut
*lut
= crtc
->state
->gamma_lut
->data
;
1093 for (i
= 0; i
< crtc
->gamma_size
; i
++) {
1096 word
= (drm_color_lut_extract(lut
[i
].red
, 10) << 20) |
1097 (drm_color_lut_extract(lut
[i
].green
, 10) << 10) |
1098 drm_color_lut_extract(lut
[i
].blue
, 10);
1099 writel(word
, vop
->lut_regs
+ i
* 4);
1103 static void vop_crtc_gamma_set(struct vop
*vop
, struct drm_crtc
*crtc
,
1104 struct drm_crtc_state
*old_state
)
1106 struct drm_crtc_state
*state
= crtc
->state
;
1113 * To disable gamma (gamma_lut is null) or to write
1114 * an update to the LUT, clear dsp_lut_en.
1116 spin_lock(&vop
->reg_lock
);
1117 VOP_REG_SET(vop
, common
, dsp_lut_en
, 0);
1119 spin_unlock(&vop
->reg_lock
);
1122 * In order to write the LUT to the internal memory,
1123 * we need to first make sure the dsp_lut_en bit is cleared.
1125 ret
= readx_poll_timeout(vop_dsp_lut_is_enabled
, vop
,
1126 idle
, !idle
, 5, 30 * 1000);
1128 DRM_DEV_ERROR(vop
->dev
, "display LUT RAM enable timeout!\n");
1132 if (!state
->gamma_lut
)
1135 spin_lock(&vop
->reg_lock
);
1136 vop_crtc_write_gamma_lut(vop
, crtc
);
1137 VOP_REG_SET(vop
, common
, dsp_lut_en
, 1);
1139 spin_unlock(&vop
->reg_lock
);
1142 static void vop_crtc_atomic_begin(struct drm_crtc
*crtc
,
1143 struct drm_crtc_state
*old_crtc_state
)
1145 struct vop
*vop
= to_vop(crtc
);
1148 * Only update GAMMA if the 'active' flag is not changed,
1149 * otherwise it's updated by .atomic_enable.
1151 if (crtc
->state
->color_mgmt_changed
&&
1152 !crtc
->state
->active_changed
)
1153 vop_crtc_gamma_set(vop
, crtc
, old_crtc_state
);
1156 static void vop_crtc_atomic_enable(struct drm_crtc
*crtc
,
1157 struct drm_crtc_state
*old_state
)
1159 struct vop
*vop
= to_vop(crtc
);
1160 const struct vop_data
*vop_data
= vop
->data
;
1161 struct rockchip_crtc_state
*s
= to_rockchip_crtc_state(crtc
->state
);
1162 struct drm_display_mode
*adjusted_mode
= &crtc
->state
->adjusted_mode
;
1163 u16 hsync_len
= adjusted_mode
->hsync_end
- adjusted_mode
->hsync_start
;
1164 u16 hdisplay
= adjusted_mode
->hdisplay
;
1165 u16 htotal
= adjusted_mode
->htotal
;
1166 u16 hact_st
= adjusted_mode
->htotal
- adjusted_mode
->hsync_start
;
1167 u16 hact_end
= hact_st
+ hdisplay
;
1168 u16 vdisplay
= adjusted_mode
->vdisplay
;
1169 u16 vtotal
= adjusted_mode
->vtotal
;
1170 u16 vsync_len
= adjusted_mode
->vsync_end
- adjusted_mode
->vsync_start
;
1171 u16 vact_st
= adjusted_mode
->vtotal
- adjusted_mode
->vsync_start
;
1172 u16 vact_end
= vact_st
+ vdisplay
;
1173 uint32_t pin_pol
, val
;
1174 int dither_bpc
= s
->output_bpc
? s
->output_bpc
: 10;
1177 if (old_state
&& old_state
->self_refresh_active
) {
1178 drm_crtc_vblank_on(crtc
);
1179 rockchip_drm_set_win_enabled(crtc
, true);
1184 * If we have a GAMMA LUT in the state, then let's make sure
1185 * it's updated. We might be coming out of suspend,
1186 * which means the LUT internal memory needs to be re-written.
1188 if (crtc
->state
->gamma_lut
)
1189 vop_crtc_gamma_set(vop
, crtc
, old_state
);
1191 mutex_lock(&vop
->vop_lock
);
1193 WARN_ON(vop
->event
);
1195 ret
= vop_enable(crtc
, old_state
);
1197 mutex_unlock(&vop
->vop_lock
);
1198 DRM_DEV_ERROR(vop
->dev
, "Failed to enable vop (%d)\n", ret
);
1201 pin_pol
= (adjusted_mode
->flags
& DRM_MODE_FLAG_PHSYNC
) ?
1202 BIT(HSYNC_POSITIVE
) : 0;
1203 pin_pol
|= (adjusted_mode
->flags
& DRM_MODE_FLAG_PVSYNC
) ?
1204 BIT(VSYNC_POSITIVE
) : 0;
1205 VOP_REG_SET(vop
, output
, pin_pol
, pin_pol
);
1206 VOP_REG_SET(vop
, output
, mipi_dual_channel_en
, 0);
1208 switch (s
->output_type
) {
1209 case DRM_MODE_CONNECTOR_LVDS
:
1210 VOP_REG_SET(vop
, output
, rgb_dclk_pol
, 1);
1211 VOP_REG_SET(vop
, output
, rgb_pin_pol
, pin_pol
);
1212 VOP_REG_SET(vop
, output
, rgb_en
, 1);
1214 case DRM_MODE_CONNECTOR_eDP
:
1215 VOP_REG_SET(vop
, output
, edp_dclk_pol
, 1);
1216 VOP_REG_SET(vop
, output
, edp_pin_pol
, pin_pol
);
1217 VOP_REG_SET(vop
, output
, edp_en
, 1);
1219 case DRM_MODE_CONNECTOR_HDMIA
:
1220 VOP_REG_SET(vop
, output
, hdmi_dclk_pol
, 1);
1221 VOP_REG_SET(vop
, output
, hdmi_pin_pol
, pin_pol
);
1222 VOP_REG_SET(vop
, output
, hdmi_en
, 1);
1224 case DRM_MODE_CONNECTOR_DSI
:
1225 VOP_REG_SET(vop
, output
, mipi_dclk_pol
, 1);
1226 VOP_REG_SET(vop
, output
, mipi_pin_pol
, pin_pol
);
1227 VOP_REG_SET(vop
, output
, mipi_en
, 1);
1228 VOP_REG_SET(vop
, output
, mipi_dual_channel_en
,
1229 !!(s
->output_flags
& ROCKCHIP_OUTPUT_DSI_DUAL
));
1231 case DRM_MODE_CONNECTOR_DisplayPort
:
1232 VOP_REG_SET(vop
, output
, dp_dclk_pol
, 0);
1233 VOP_REG_SET(vop
, output
, dp_pin_pol
, pin_pol
);
1234 VOP_REG_SET(vop
, output
, dp_en
, 1);
1237 DRM_DEV_ERROR(vop
->dev
, "unsupported connector_type [%d]\n",
1242 * if vop is not support RGB10 output, need force RGB10 to RGB888.
1244 if (s
->output_mode
== ROCKCHIP_OUT_MODE_AAAA
&&
1245 !(vop_data
->feature
& VOP_FEATURE_OUTPUT_RGB10
))
1246 s
->output_mode
= ROCKCHIP_OUT_MODE_P888
;
1248 if (s
->output_mode
== ROCKCHIP_OUT_MODE_AAAA
&& dither_bpc
<= 8)
1249 VOP_REG_SET(vop
, common
, pre_dither_down
, 1);
1251 VOP_REG_SET(vop
, common
, pre_dither_down
, 0);
1253 if (dither_bpc
== 6) {
1254 VOP_REG_SET(vop
, common
, dither_down_sel
, DITHER_DOWN_ALLEGRO
);
1255 VOP_REG_SET(vop
, common
, dither_down_mode
, RGB888_TO_RGB666
);
1256 VOP_REG_SET(vop
, common
, dither_down_en
, 1);
1258 VOP_REG_SET(vop
, common
, dither_down_en
, 0);
1261 VOP_REG_SET(vop
, common
, out_mode
, s
->output_mode
);
1263 VOP_REG_SET(vop
, modeset
, htotal_pw
, (htotal
<< 16) | hsync_len
);
1264 val
= hact_st
<< 16;
1266 VOP_REG_SET(vop
, modeset
, hact_st_end
, val
);
1267 VOP_REG_SET(vop
, modeset
, hpost_st_end
, val
);
1269 VOP_REG_SET(vop
, modeset
, vtotal_pw
, (vtotal
<< 16) | vsync_len
);
1270 val
= vact_st
<< 16;
1272 VOP_REG_SET(vop
, modeset
, vact_st_end
, val
);
1273 VOP_REG_SET(vop
, modeset
, vpost_st_end
, val
);
1275 VOP_REG_SET(vop
, intr
, line_flag_num
[0], vact_end
);
1277 clk_set_rate(vop
->dclk
, adjusted_mode
->clock
* 1000);
1279 VOP_REG_SET(vop
, common
, standby
, 0);
1280 mutex_unlock(&vop
->vop_lock
);
1283 static bool vop_fs_irq_is_pending(struct vop
*vop
)
1285 return VOP_INTR_GET_TYPE(vop
, status
, FS_INTR
);
1288 static void vop_wait_for_irq_handler(struct vop
*vop
)
1294 * Spin until frame start interrupt status bit goes low, which means
1295 * that interrupt handler was invoked and cleared it. The timeout of
1296 * 10 msecs is really too long, but it is just a safety measure if
1297 * something goes really wrong. The wait will only happen in the very
1298 * unlikely case of a vblank happening exactly at the same time and
1299 * shouldn't exceed microseconds range.
1301 ret
= readx_poll_timeout_atomic(vop_fs_irq_is_pending
, vop
, pending
,
1302 !pending
, 0, 10 * 1000);
1304 DRM_DEV_ERROR(vop
->dev
, "VOP vblank IRQ stuck for 10 ms\n");
1306 synchronize_irq(vop
->irq
);
1309 static int vop_crtc_atomic_check(struct drm_crtc
*crtc
,
1310 struct drm_crtc_state
*crtc_state
)
1312 struct vop
*vop
= to_vop(crtc
);
1314 if (vop
->lut_regs
&& crtc_state
->color_mgmt_changed
&&
1315 crtc_state
->gamma_lut
) {
1318 len
= drm_color_lut_size(crtc_state
->gamma_lut
);
1319 if (len
!= crtc
->gamma_size
) {
1320 DRM_DEBUG_KMS("Invalid LUT size; got %d, expected %d\n",
1321 len
, crtc
->gamma_size
);
1329 static void vop_crtc_atomic_flush(struct drm_crtc
*crtc
,
1330 struct drm_crtc_state
*old_crtc_state
)
1332 struct drm_atomic_state
*old_state
= old_crtc_state
->state
;
1333 struct drm_plane_state
*old_plane_state
, *new_plane_state
;
1334 struct vop
*vop
= to_vop(crtc
);
1335 struct drm_plane
*plane
;
1338 if (WARN_ON(!vop
->is_enabled
))
1341 spin_lock(&vop
->reg_lock
);
1345 spin_unlock(&vop
->reg_lock
);
1348 * There is a (rather unlikely) possiblity that a vblank interrupt
1349 * fired before we set the cfg_done bit. To avoid spuriously
1350 * signalling flip completion we need to wait for it to finish.
1352 vop_wait_for_irq_handler(vop
);
1354 spin_lock_irq(&crtc
->dev
->event_lock
);
1355 if (crtc
->state
->event
) {
1356 WARN_ON(drm_crtc_vblank_get(crtc
) != 0);
1357 WARN_ON(vop
->event
);
1359 vop
->event
= crtc
->state
->event
;
1360 crtc
->state
->event
= NULL
;
1362 spin_unlock_irq(&crtc
->dev
->event_lock
);
1364 for_each_oldnew_plane_in_state(old_state
, plane
, old_plane_state
,
1365 new_plane_state
, i
) {
1366 if (!old_plane_state
->fb
)
1369 if (old_plane_state
->fb
== new_plane_state
->fb
)
1372 drm_framebuffer_get(old_plane_state
->fb
);
1373 WARN_ON(drm_crtc_vblank_get(crtc
) != 0);
1374 drm_flip_work_queue(&vop
->fb_unref_work
, old_plane_state
->fb
);
1375 set_bit(VOP_PENDING_FB_UNREF
, &vop
->pending
);
1379 static const struct drm_crtc_helper_funcs vop_crtc_helper_funcs
= {
1380 .mode_fixup
= vop_crtc_mode_fixup
,
1381 .atomic_check
= vop_crtc_atomic_check
,
1382 .atomic_begin
= vop_crtc_atomic_begin
,
1383 .atomic_flush
= vop_crtc_atomic_flush
,
1384 .atomic_enable
= vop_crtc_atomic_enable
,
1385 .atomic_disable
= vop_crtc_atomic_disable
,
1388 static void vop_crtc_destroy(struct drm_crtc
*crtc
)
1390 drm_crtc_cleanup(crtc
);
1393 static struct drm_crtc_state
*vop_crtc_duplicate_state(struct drm_crtc
*crtc
)
1395 struct rockchip_crtc_state
*rockchip_state
;
1397 rockchip_state
= kzalloc(sizeof(*rockchip_state
), GFP_KERNEL
);
1398 if (!rockchip_state
)
1401 __drm_atomic_helper_crtc_duplicate_state(crtc
, &rockchip_state
->base
);
1402 return &rockchip_state
->base
;
1405 static void vop_crtc_destroy_state(struct drm_crtc
*crtc
,
1406 struct drm_crtc_state
*state
)
1408 struct rockchip_crtc_state
*s
= to_rockchip_crtc_state(state
);
1410 __drm_atomic_helper_crtc_destroy_state(&s
->base
);
1414 static void vop_crtc_reset(struct drm_crtc
*crtc
)
1416 struct rockchip_crtc_state
*crtc_state
=
1417 kzalloc(sizeof(*crtc_state
), GFP_KERNEL
);
1420 vop_crtc_destroy_state(crtc
, crtc
->state
);
1422 __drm_atomic_helper_crtc_reset(crtc
, &crtc_state
->base
);
1425 #ifdef CONFIG_DRM_ANALOGIX_DP
1426 static struct drm_connector
*vop_get_edp_connector(struct vop
*vop
)
1428 struct drm_connector
*connector
;
1429 struct drm_connector_list_iter conn_iter
;
1431 drm_connector_list_iter_begin(vop
->drm_dev
, &conn_iter
);
1432 drm_for_each_connector_iter(connector
, &conn_iter
) {
1433 if (connector
->connector_type
== DRM_MODE_CONNECTOR_eDP
) {
1434 drm_connector_list_iter_end(&conn_iter
);
1438 drm_connector_list_iter_end(&conn_iter
);
1443 static int vop_crtc_set_crc_source(struct drm_crtc
*crtc
,
1444 const char *source_name
)
1446 struct vop
*vop
= to_vop(crtc
);
1447 struct drm_connector
*connector
;
1450 connector
= vop_get_edp_connector(vop
);
1454 if (source_name
&& strcmp(source_name
, "auto") == 0)
1455 ret
= analogix_dp_start_crc(connector
);
1456 else if (!source_name
)
1457 ret
= analogix_dp_stop_crc(connector
);
1465 vop_crtc_verify_crc_source(struct drm_crtc
*crtc
, const char *source_name
,
1468 if (source_name
&& strcmp(source_name
, "auto") != 0)
1476 static int vop_crtc_set_crc_source(struct drm_crtc
*crtc
,
1477 const char *source_name
)
1483 vop_crtc_verify_crc_source(struct drm_crtc
*crtc
, const char *source_name
,
1490 static const struct drm_crtc_funcs vop_crtc_funcs
= {
1491 .set_config
= drm_atomic_helper_set_config
,
1492 .page_flip
= drm_atomic_helper_page_flip
,
1493 .destroy
= vop_crtc_destroy
,
1494 .reset
= vop_crtc_reset
,
1495 .atomic_duplicate_state
= vop_crtc_duplicate_state
,
1496 .atomic_destroy_state
= vop_crtc_destroy_state
,
1497 .enable_vblank
= vop_crtc_enable_vblank
,
1498 .disable_vblank
= vop_crtc_disable_vblank
,
1499 .set_crc_source
= vop_crtc_set_crc_source
,
1500 .verify_crc_source
= vop_crtc_verify_crc_source
,
1501 .gamma_set
= drm_atomic_helper_legacy_gamma_set
,
1504 static void vop_fb_unref_worker(struct drm_flip_work
*work
, void *val
)
1506 struct vop
*vop
= container_of(work
, struct vop
, fb_unref_work
);
1507 struct drm_framebuffer
*fb
= val
;
1509 drm_crtc_vblank_put(&vop
->crtc
);
1510 drm_framebuffer_put(fb
);
1513 static void vop_handle_vblank(struct vop
*vop
)
1515 struct drm_device
*drm
= vop
->drm_dev
;
1516 struct drm_crtc
*crtc
= &vop
->crtc
;
1518 spin_lock(&drm
->event_lock
);
1520 drm_crtc_send_vblank_event(crtc
, vop
->event
);
1521 drm_crtc_vblank_put(crtc
);
1524 spin_unlock(&drm
->event_lock
);
1526 if (test_and_clear_bit(VOP_PENDING_FB_UNREF
, &vop
->pending
))
1527 drm_flip_work_commit(&vop
->fb_unref_work
, system_unbound_wq
);
1530 static irqreturn_t
vop_isr(int irq
, void *data
)
1532 struct vop
*vop
= data
;
1533 struct drm_crtc
*crtc
= &vop
->crtc
;
1534 uint32_t active_irqs
;
1538 * The irq is shared with the iommu. If the runtime-pm state of the
1539 * vop-device is disabled the irq has to be targeted at the iommu.
1541 if (!pm_runtime_get_if_in_use(vop
->dev
))
1544 if (vop_core_clks_enable(vop
)) {
1545 DRM_DEV_ERROR_RATELIMITED(vop
->dev
, "couldn't enable clocks\n");
1550 * interrupt register has interrupt status, enable and clear bits, we
1551 * must hold irq_lock to avoid a race with enable/disable_vblank().
1553 spin_lock(&vop
->irq_lock
);
1555 active_irqs
= VOP_INTR_GET_TYPE(vop
, status
, INTR_MASK
);
1556 /* Clear all active interrupt sources */
1558 VOP_INTR_SET_TYPE(vop
, clear
, active_irqs
, 1);
1560 spin_unlock(&vop
->irq_lock
);
1562 /* This is expected for vop iommu irqs, since the irq is shared */
1566 if (active_irqs
& DSP_HOLD_VALID_INTR
) {
1567 complete(&vop
->dsp_hold_completion
);
1568 active_irqs
&= ~DSP_HOLD_VALID_INTR
;
1572 if (active_irqs
& LINE_FLAG_INTR
) {
1573 complete(&vop
->line_flag_completion
);
1574 active_irqs
&= ~LINE_FLAG_INTR
;
1578 if (active_irqs
& FS_INTR
) {
1579 drm_crtc_handle_vblank(crtc
);
1580 vop_handle_vblank(vop
);
1581 active_irqs
&= ~FS_INTR
;
1585 /* Unhandled irqs are spurious. */
1587 DRM_DEV_ERROR(vop
->dev
, "Unknown VOP IRQs: %#02x\n",
1591 vop_core_clks_disable(vop
);
1593 pm_runtime_put(vop
->dev
);
1597 static void vop_plane_add_properties(struct drm_plane
*plane
,
1598 const struct vop_win_data
*win_data
)
1600 unsigned int flags
= 0;
1602 flags
|= VOP_WIN_HAS_REG(win_data
, x_mir_en
) ? DRM_MODE_REFLECT_X
: 0;
1603 flags
|= VOP_WIN_HAS_REG(win_data
, y_mir_en
) ? DRM_MODE_REFLECT_Y
: 0;
1605 drm_plane_create_rotation_property(plane
, DRM_MODE_ROTATE_0
,
1606 DRM_MODE_ROTATE_0
| flags
);
1609 static int vop_create_crtc(struct vop
*vop
)
1611 const struct vop_data
*vop_data
= vop
->data
;
1612 struct device
*dev
= vop
->dev
;
1613 struct drm_device
*drm_dev
= vop
->drm_dev
;
1614 struct drm_plane
*primary
= NULL
, *cursor
= NULL
, *plane
, *tmp
;
1615 struct drm_crtc
*crtc
= &vop
->crtc
;
1616 struct device_node
*port
;
1621 * Create drm_plane for primary and cursor planes first, since we need
1622 * to pass them to drm_crtc_init_with_planes, which sets the
1623 * "possible_crtcs" to the newly initialized crtc.
1625 for (i
= 0; i
< vop_data
->win_size
; i
++) {
1626 struct vop_win
*vop_win
= &vop
->win
[i
];
1627 const struct vop_win_data
*win_data
= vop_win
->data
;
1629 if (win_data
->type
!= DRM_PLANE_TYPE_PRIMARY
&&
1630 win_data
->type
!= DRM_PLANE_TYPE_CURSOR
)
1633 ret
= drm_universal_plane_init(vop
->drm_dev
, &vop_win
->base
,
1634 0, &vop_plane_funcs
,
1635 win_data
->phy
->data_formats
,
1636 win_data
->phy
->nformats
,
1637 NULL
, win_data
->type
, NULL
);
1639 DRM_DEV_ERROR(vop
->dev
, "failed to init plane %d\n",
1641 goto err_cleanup_planes
;
1644 plane
= &vop_win
->base
;
1645 drm_plane_helper_add(plane
, &plane_helper_funcs
);
1646 vop_plane_add_properties(plane
, win_data
);
1647 if (plane
->type
== DRM_PLANE_TYPE_PRIMARY
)
1649 else if (plane
->type
== DRM_PLANE_TYPE_CURSOR
)
1653 ret
= drm_crtc_init_with_planes(drm_dev
, crtc
, primary
, cursor
,
1654 &vop_crtc_funcs
, NULL
);
1656 goto err_cleanup_planes
;
1658 drm_crtc_helper_add(crtc
, &vop_crtc_helper_funcs
);
1659 if (vop
->lut_regs
) {
1660 drm_mode_crtc_set_gamma_size(crtc
, vop_data
->lut_size
);
1661 drm_crtc_enable_color_mgmt(crtc
, 0, false, vop_data
->lut_size
);
1665 * Create drm_planes for overlay windows with possible_crtcs restricted
1666 * to the newly created crtc.
1668 for (i
= 0; i
< vop_data
->win_size
; i
++) {
1669 struct vop_win
*vop_win
= &vop
->win
[i
];
1670 const struct vop_win_data
*win_data
= vop_win
->data
;
1671 unsigned long possible_crtcs
= drm_crtc_mask(crtc
);
1673 if (win_data
->type
!= DRM_PLANE_TYPE_OVERLAY
)
1676 ret
= drm_universal_plane_init(vop
->drm_dev
, &vop_win
->base
,
1679 win_data
->phy
->data_formats
,
1680 win_data
->phy
->nformats
,
1681 NULL
, win_data
->type
, NULL
);
1683 DRM_DEV_ERROR(vop
->dev
, "failed to init overlay %d\n",
1685 goto err_cleanup_crtc
;
1687 drm_plane_helper_add(&vop_win
->base
, &plane_helper_funcs
);
1688 vop_plane_add_properties(&vop_win
->base
, win_data
);
1691 port
= of_get_child_by_name(dev
->of_node
, "port");
1693 DRM_DEV_ERROR(vop
->dev
, "no port node found in %pOF\n",
1696 goto err_cleanup_crtc
;
1699 drm_flip_work_init(&vop
->fb_unref_work
, "fb_unref",
1700 vop_fb_unref_worker
);
1702 init_completion(&vop
->dsp_hold_completion
);
1703 init_completion(&vop
->line_flag_completion
);
1706 ret
= drm_self_refresh_helper_init(crtc
);
1708 DRM_DEV_DEBUG_KMS(vop
->dev
,
1709 "Failed to init %s with SR helpers %d, ignoring\n",
1715 drm_crtc_cleanup(crtc
);
1717 list_for_each_entry_safe(plane
, tmp
, &drm_dev
->mode_config
.plane_list
,
1719 drm_plane_cleanup(plane
);
1723 static void vop_destroy_crtc(struct vop
*vop
)
1725 struct drm_crtc
*crtc
= &vop
->crtc
;
1726 struct drm_device
*drm_dev
= vop
->drm_dev
;
1727 struct drm_plane
*plane
, *tmp
;
1729 drm_self_refresh_helper_cleanup(crtc
);
1731 of_node_put(crtc
->port
);
1734 * We need to cleanup the planes now. Why?
1736 * The planes are "&vop->win[i].base". That means the memory is
1737 * all part of the big "struct vop" chunk of memory. That memory
1738 * was devm allocated and associated with this component. We need to
1739 * free it ourselves before vop_unbind() finishes.
1741 list_for_each_entry_safe(plane
, tmp
, &drm_dev
->mode_config
.plane_list
,
1743 vop_plane_destroy(plane
);
1746 * Destroy CRTC after vop_plane_destroy() since vop_disable_plane()
1747 * references the CRTC.
1749 drm_crtc_cleanup(crtc
);
1750 drm_flip_work_cleanup(&vop
->fb_unref_work
);
1753 static int vop_initial(struct vop
*vop
)
1755 struct reset_control
*ahb_rst
;
1758 vop
->hclk
= devm_clk_get(vop
->dev
, "hclk_vop");
1759 if (IS_ERR(vop
->hclk
)) {
1760 DRM_DEV_ERROR(vop
->dev
, "failed to get hclk source\n");
1761 return PTR_ERR(vop
->hclk
);
1763 vop
->aclk
= devm_clk_get(vop
->dev
, "aclk_vop");
1764 if (IS_ERR(vop
->aclk
)) {
1765 DRM_DEV_ERROR(vop
->dev
, "failed to get aclk source\n");
1766 return PTR_ERR(vop
->aclk
);
1768 vop
->dclk
= devm_clk_get(vop
->dev
, "dclk_vop");
1769 if (IS_ERR(vop
->dclk
)) {
1770 DRM_DEV_ERROR(vop
->dev
, "failed to get dclk source\n");
1771 return PTR_ERR(vop
->dclk
);
1774 ret
= pm_runtime_get_sync(vop
->dev
);
1776 DRM_DEV_ERROR(vop
->dev
, "failed to get pm runtime: %d\n", ret
);
1780 ret
= clk_prepare(vop
->dclk
);
1782 DRM_DEV_ERROR(vop
->dev
, "failed to prepare dclk\n");
1783 goto err_put_pm_runtime
;
1786 /* Enable both the hclk and aclk to setup the vop */
1787 ret
= clk_prepare_enable(vop
->hclk
);
1789 DRM_DEV_ERROR(vop
->dev
, "failed to prepare/enable hclk\n");
1790 goto err_unprepare_dclk
;
1793 ret
= clk_prepare_enable(vop
->aclk
);
1795 DRM_DEV_ERROR(vop
->dev
, "failed to prepare/enable aclk\n");
1796 goto err_disable_hclk
;
1800 * do hclk_reset, reset all vop registers.
1802 ahb_rst
= devm_reset_control_get(vop
->dev
, "ahb");
1803 if (IS_ERR(ahb_rst
)) {
1804 DRM_DEV_ERROR(vop
->dev
, "failed to get ahb reset\n");
1805 ret
= PTR_ERR(ahb_rst
);
1806 goto err_disable_aclk
;
1808 reset_control_assert(ahb_rst
);
1809 usleep_range(10, 20);
1810 reset_control_deassert(ahb_rst
);
1812 VOP_INTR_SET_TYPE(vop
, clear
, INTR_MASK
, 1);
1813 VOP_INTR_SET_TYPE(vop
, enable
, INTR_MASK
, 0);
1815 for (i
= 0; i
< vop
->len
; i
+= sizeof(u32
))
1816 vop
->regsbak
[i
/ 4] = readl_relaxed(vop
->regs
+ i
);
1818 VOP_REG_SET(vop
, misc
, global_regdone_en
, 1);
1819 VOP_REG_SET(vop
, common
, dsp_blank
, 0);
1821 for (i
= 0; i
< vop
->data
->win_size
; i
++) {
1822 struct vop_win
*vop_win
= &vop
->win
[i
];
1823 const struct vop_win_data
*win
= vop_win
->data
;
1824 int channel
= i
* 2 + 1;
1826 VOP_WIN_SET(vop
, win
, channel
, (channel
+ 1) << 4 | channel
);
1827 vop_win_disable(vop
, vop_win
);
1828 VOP_WIN_SET(vop
, win
, gate
, 1);
1834 * do dclk_reset, let all config take affect.
1836 vop
->dclk_rst
= devm_reset_control_get(vop
->dev
, "dclk");
1837 if (IS_ERR(vop
->dclk_rst
)) {
1838 DRM_DEV_ERROR(vop
->dev
, "failed to get dclk reset\n");
1839 ret
= PTR_ERR(vop
->dclk_rst
);
1840 goto err_disable_aclk
;
1842 reset_control_assert(vop
->dclk_rst
);
1843 usleep_range(10, 20);
1844 reset_control_deassert(vop
->dclk_rst
);
1846 clk_disable(vop
->hclk
);
1847 clk_disable(vop
->aclk
);
1849 vop
->is_enabled
= false;
1851 pm_runtime_put_sync(vop
->dev
);
1856 clk_disable_unprepare(vop
->aclk
);
1858 clk_disable_unprepare(vop
->hclk
);
1860 clk_unprepare(vop
->dclk
);
1862 pm_runtime_put_sync(vop
->dev
);
1867 * Initialize the vop->win array elements.
1869 static void vop_win_init(struct vop
*vop
)
1871 const struct vop_data
*vop_data
= vop
->data
;
1874 for (i
= 0; i
< vop_data
->win_size
; i
++) {
1875 struct vop_win
*vop_win
= &vop
->win
[i
];
1876 const struct vop_win_data
*win_data
= &vop_data
->win
[i
];
1878 vop_win
->data
= win_data
;
1881 if (vop_data
->win_yuv2yuv
)
1882 vop_win
->yuv2yuv_data
= &vop_data
->win_yuv2yuv
[i
];
1887 * rockchip_drm_wait_vact_end
1888 * @crtc: CRTC to enable line flag
1889 * @mstimeout: millisecond for timeout
1891 * Wait for vact_end line flag irq or timeout.
1894 * Zero on success, negative errno on failure.
1896 int rockchip_drm_wait_vact_end(struct drm_crtc
*crtc
, unsigned int mstimeout
)
1898 struct vop
*vop
= to_vop(crtc
);
1899 unsigned long jiffies_left
;
1902 if (!crtc
|| !vop
->is_enabled
)
1905 mutex_lock(&vop
->vop_lock
);
1906 if (mstimeout
<= 0) {
1911 if (vop_line_flag_irq_is_enabled(vop
)) {
1916 reinit_completion(&vop
->line_flag_completion
);
1917 vop_line_flag_irq_enable(vop
);
1919 jiffies_left
= wait_for_completion_timeout(&vop
->line_flag_completion
,
1920 msecs_to_jiffies(mstimeout
));
1921 vop_line_flag_irq_disable(vop
);
1923 if (jiffies_left
== 0) {
1924 DRM_DEV_ERROR(vop
->dev
, "Timeout waiting for IRQ\n");
1930 mutex_unlock(&vop
->vop_lock
);
1933 EXPORT_SYMBOL(rockchip_drm_wait_vact_end
);
1935 static int vop_bind(struct device
*dev
, struct device
*master
, void *data
)
1937 struct platform_device
*pdev
= to_platform_device(dev
);
1938 const struct vop_data
*vop_data
;
1939 struct drm_device
*drm_dev
= data
;
1941 struct resource
*res
;
1944 vop_data
= of_device_get_match_data(dev
);
1948 /* Allocate vop struct and its vop_win array */
1949 vop
= devm_kzalloc(dev
, struct_size(vop
, win
, vop_data
->win_size
),
1955 vop
->data
= vop_data
;
1956 vop
->drm_dev
= drm_dev
;
1957 dev_set_drvdata(dev
, vop
);
1961 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
1962 vop
->len
= resource_size(res
);
1963 vop
->regs
= devm_ioremap_resource(dev
, res
);
1964 if (IS_ERR(vop
->regs
))
1965 return PTR_ERR(vop
->regs
);
1967 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 1);
1969 if (!vop_data
->lut_size
) {
1970 DRM_DEV_ERROR(dev
, "no gamma LUT size defined\n");
1973 vop
->lut_regs
= devm_ioremap_resource(dev
, res
);
1974 if (IS_ERR(vop
->lut_regs
))
1975 return PTR_ERR(vop
->lut_regs
);
1978 vop
->regsbak
= devm_kzalloc(dev
, vop
->len
, GFP_KERNEL
);
1982 irq
= platform_get_irq(pdev
, 0);
1984 DRM_DEV_ERROR(dev
, "cannot find irq for vop\n");
1987 vop
->irq
= (unsigned int)irq
;
1989 spin_lock_init(&vop
->reg_lock
);
1990 spin_lock_init(&vop
->irq_lock
);
1991 mutex_init(&vop
->vop_lock
);
1993 ret
= vop_create_crtc(vop
);
1997 pm_runtime_enable(&pdev
->dev
);
1999 ret
= vop_initial(vop
);
2001 DRM_DEV_ERROR(&pdev
->dev
,
2002 "cannot initial vop dev - err %d\n", ret
);
2003 goto err_disable_pm_runtime
;
2006 ret
= devm_request_irq(dev
, vop
->irq
, vop_isr
,
2007 IRQF_SHARED
, dev_name(dev
), vop
);
2009 goto err_disable_pm_runtime
;
2011 if (vop
->data
->feature
& VOP_FEATURE_INTERNAL_RGB
) {
2012 vop
->rgb
= rockchip_rgb_init(dev
, &vop
->crtc
, vop
->drm_dev
);
2013 if (IS_ERR(vop
->rgb
)) {
2014 ret
= PTR_ERR(vop
->rgb
);
2015 goto err_disable_pm_runtime
;
2021 err_disable_pm_runtime
:
2022 pm_runtime_disable(&pdev
->dev
);
2023 vop_destroy_crtc(vop
);
2027 static void vop_unbind(struct device
*dev
, struct device
*master
, void *data
)
2029 struct vop
*vop
= dev_get_drvdata(dev
);
2032 rockchip_rgb_fini(vop
->rgb
);
2034 pm_runtime_disable(dev
);
2035 vop_destroy_crtc(vop
);
2037 clk_unprepare(vop
->aclk
);
2038 clk_unprepare(vop
->hclk
);
2039 clk_unprepare(vop
->dclk
);
2042 const struct component_ops vop_component_ops
= {
2044 .unbind
= vop_unbind
,
2046 EXPORT_SYMBOL_GPL(vop_component_ops
);