Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: (GPL-2.0+ OR MIT)
0002 /*
0003  * Copyright (c) 2020 Rockchip Electronics Co., Ltd.
0004  * Author: Andy Yan <andy.yan@rock-chips.com>
0005  */
0006 #include <linux/bitfield.h>
0007 #include <linux/clk.h>
0008 #include <linux/component.h>
0009 #include <linux/delay.h>
0010 #include <linux/iopoll.h>
0011 #include <linux/kernel.h>
0012 #include <linux/media-bus-format.h>
0013 #include <linux/mfd/syscon.h>
0014 #include <linux/module.h>
0015 #include <linux/of.h>
0016 #include <linux/of_device.h>
0017 #include <linux/of_graph.h>
0018 #include <linux/platform_device.h>
0019 #include <linux/pm_runtime.h>
0020 #include <linux/regmap.h>
0021 #include <linux/swab.h>
0022 
0023 #include <drm/drm.h>
0024 #include <drm/drm_atomic.h>
0025 #include <drm/drm_atomic_uapi.h>
0026 #include <drm/drm_blend.h>
0027 #include <drm/drm_crtc.h>
0028 #include <drm/drm_crtc_helper.h>
0029 #include <drm/drm_debugfs.h>
0030 #include <drm/drm_flip_work.h>
0031 #include <drm/drm_framebuffer.h>
0032 #include <drm/drm_plane_helper.h>
0033 #include <drm/drm_probe_helper.h>
0034 #include <drm/drm_vblank.h>
0035 
0036 #include <uapi/linux/videodev2.h>
0037 #include <dt-bindings/soc/rockchip,vop2.h>
0038 
0039 #include "rockchip_drm_drv.h"
0040 #include "rockchip_drm_gem.h"
0041 #include "rockchip_drm_fb.h"
0042 #include "rockchip_drm_vop2.h"
0043 
0044 /*
0045  * VOP2 architecture
0046  *
0047  +----------+   +-------------+                                                        +-----------+
0048  |  Cluster |   | Sel 1 from 6|                                                        | 1 from 3  |
0049  |  window0 |   |    Layer0   |                                                        |    RGB    |
0050  +----------+   +-------------+              +---------------+    +-------------+      +-----------+
0051  +----------+   +-------------+              |N from 6 layers|    |             |
0052  |  Cluster |   | Sel 1 from 6|              |   Overlay0    +--->| Video Port0 |      +-----------+
0053  |  window1 |   |    Layer1   |              |               |    |             |      | 1 from 3  |
0054  +----------+   +-------------+              +---------------+    +-------------+      |   LVDS    |
0055  +----------+   +-------------+                                                        +-----------+
0056  |  Esmart  |   | Sel 1 from 6|
0057  |  window0 |   |   Layer2    |              +---------------+    +-------------+      +-----------+
0058  +----------+   +-------------+              |N from 6 Layers|    |             | +--> | 1 from 3  |
0059  +----------+   +-------------+   -------->  |   Overlay1    +--->| Video Port1 |      |   MIPI    |
0060  |  Esmart  |   | Sel 1 from 6|   -------->  |               |    |             |      +-----------+
0061  |  Window1 |   |   Layer3    |              +---------------+    +-------------+
0062  +----------+   +-------------+                                                        +-----------+
0063  +----------+   +-------------+                                                        | 1 from 3  |
0064  |  Smart   |   | Sel 1 from 6|              +---------------+    +-------------+      |   HDMI    |
0065  |  Window0 |   |    Layer4   |              |N from 6 Layers|    |             |      +-----------+
0066  +----------+   +-------------+              |   Overlay2    +--->| Video Port2 |
0067  +----------+   +-------------+              |               |    |             |      +-----------+
0068  |  Smart   |   | Sel 1 from 6|              +---------------+    +-------------+      |  1 from 3 |
0069  |  Window1 |   |    Layer5   |                                                        |    eDP    |
0070  +----------+   +-------------+                                                        +-----------+
0071  *
0072  */
0073 
0074 enum vop2_data_format {
0075     VOP2_FMT_ARGB8888 = 0,
0076     VOP2_FMT_RGB888,
0077     VOP2_FMT_RGB565,
0078     VOP2_FMT_XRGB101010,
0079     VOP2_FMT_YUV420SP,
0080     VOP2_FMT_YUV422SP,
0081     VOP2_FMT_YUV444SP,
0082     VOP2_FMT_YUYV422 = 8,
0083     VOP2_FMT_YUYV420,
0084     VOP2_FMT_VYUY422,
0085     VOP2_FMT_VYUY420,
0086     VOP2_FMT_YUV420SP_TILE_8x4 = 0x10,
0087     VOP2_FMT_YUV420SP_TILE_16x2,
0088     VOP2_FMT_YUV422SP_TILE_8x4,
0089     VOP2_FMT_YUV422SP_TILE_16x2,
0090     VOP2_FMT_YUV420SP_10,
0091     VOP2_FMT_YUV422SP_10,
0092     VOP2_FMT_YUV444SP_10,
0093 };
0094 
0095 enum vop2_afbc_format {
0096     VOP2_AFBC_FMT_RGB565,
0097     VOP2_AFBC_FMT_ARGB2101010 = 2,
0098     VOP2_AFBC_FMT_YUV420_10BIT,
0099     VOP2_AFBC_FMT_RGB888,
0100     VOP2_AFBC_FMT_ARGB8888,
0101     VOP2_AFBC_FMT_YUV420 = 9,
0102     VOP2_AFBC_FMT_YUV422 = 0xb,
0103     VOP2_AFBC_FMT_YUV422_10BIT = 0xe,
0104     VOP2_AFBC_FMT_INVALID = -1,
0105 };
0106 
0107 union vop2_alpha_ctrl {
0108     u32 val;
0109     struct {
0110         /* [0:1] */
0111         u32 color_mode:1;
0112         u32 alpha_mode:1;
0113         /* [2:3] */
0114         u32 blend_mode:2;
0115         u32 alpha_cal_mode:1;
0116         /* [5:7] */
0117         u32 factor_mode:3;
0118         /* [8:9] */
0119         u32 alpha_en:1;
0120         u32 src_dst_swap:1;
0121         u32 reserved:6;
0122         /* [16:23] */
0123         u32 glb_alpha:8;
0124     } bits;
0125 };
0126 
0127 struct vop2_alpha {
0128     union vop2_alpha_ctrl src_color_ctrl;
0129     union vop2_alpha_ctrl dst_color_ctrl;
0130     union vop2_alpha_ctrl src_alpha_ctrl;
0131     union vop2_alpha_ctrl dst_alpha_ctrl;
0132 };
0133 
0134 struct vop2_alpha_config {
0135     bool src_premulti_en;
0136     bool dst_premulti_en;
0137     bool src_pixel_alpha_en;
0138     bool dst_pixel_alpha_en;
0139     u16 src_glb_alpha_value;
0140     u16 dst_glb_alpha_value;
0141 };
0142 
0143 struct vop2_win {
0144     struct vop2 *vop2;
0145     struct drm_plane base;
0146     const struct vop2_win_data *data;
0147     struct regmap_field *reg[VOP2_WIN_MAX_REG];
0148 
0149     /**
0150      * @win_id: graphic window id, a cluster may be split into two
0151      * graphics windows.
0152      */
0153     u8 win_id;
0154     u8 delay;
0155     u32 offset;
0156 
0157     enum drm_plane_type type;
0158 };
0159 
0160 struct vop2_video_port {
0161     struct drm_crtc crtc;
0162     struct vop2 *vop2;
0163     struct clk *dclk;
0164     unsigned int id;
0165     const struct vop2_video_port_regs *regs;
0166     const struct vop2_video_port_data *data;
0167 
0168     struct completion dsp_hold_completion;
0169 
0170     /**
0171      * @win_mask: Bitmask of windows attached to the video port;
0172      */
0173     u32 win_mask;
0174 
0175     struct vop2_win *primary_plane;
0176     struct drm_pending_vblank_event *event;
0177 
0178     unsigned int nlayers;
0179 };
0180 
0181 struct vop2 {
0182     struct device *dev;
0183     struct drm_device *drm;
0184     struct vop2_video_port vps[ROCKCHIP_MAX_CRTC];
0185 
0186     const struct vop2_data *data;
0187     /*
0188      * Number of windows that are registered as plane, may be less than the
0189      * total number of hardware windows.
0190      */
0191     u32 registered_num_wins;
0192 
0193     void __iomem *regs;
0194     struct regmap *map;
0195 
0196     struct regmap *grf;
0197 
0198     /* physical map length of vop2 register */
0199     u32 len;
0200 
0201     void __iomem *lut_regs;
0202 
0203     /* protects crtc enable/disable */
0204     struct mutex vop2_lock;
0205 
0206     int irq;
0207 
0208     /*
0209      * Some global resources are shared between all video ports(crtcs), so
0210      * we need a ref counter here.
0211      */
0212     unsigned int enable_count;
0213     struct clk *hclk;
0214     struct clk *aclk;
0215 
0216     /* must be put at the end of the struct */
0217     struct vop2_win win[];
0218 };
0219 
0220 static struct vop2_video_port *to_vop2_video_port(struct drm_crtc *crtc)
0221 {
0222     return container_of(crtc, struct vop2_video_port, crtc);
0223 }
0224 
0225 static struct vop2_win *to_vop2_win(struct drm_plane *p)
0226 {
0227     return container_of(p, struct vop2_win, base);
0228 }
0229 
0230 static void vop2_lock(struct vop2 *vop2)
0231 {
0232     mutex_lock(&vop2->vop2_lock);
0233 }
0234 
0235 static void vop2_unlock(struct vop2 *vop2)
0236 {
0237     mutex_unlock(&vop2->vop2_lock);
0238 }
0239 
0240 static void vop2_writel(struct vop2 *vop2, u32 offset, u32 v)
0241 {
0242     regmap_write(vop2->map, offset, v);
0243 }
0244 
0245 static void vop2_vp_write(struct vop2_video_port *vp, u32 offset, u32 v)
0246 {
0247     regmap_write(vp->vop2->map, vp->data->offset + offset, v);
0248 }
0249 
0250 static u32 vop2_readl(struct vop2 *vop2, u32 offset)
0251 {
0252     u32 val;
0253 
0254     regmap_read(vop2->map, offset, &val);
0255 
0256     return val;
0257 }
0258 
0259 static void vop2_win_write(const struct vop2_win *win, unsigned int reg, u32 v)
0260 {
0261     regmap_field_write(win->reg[reg], v);
0262 }
0263 
0264 static bool vop2_cluster_window(const struct vop2_win *win)
0265 {
0266     return win->data->feature & WIN_FEATURE_CLUSTER;
0267 }
0268 
0269 static void vop2_cfg_done(struct vop2_video_port *vp)
0270 {
0271     struct vop2 *vop2 = vp->vop2;
0272 
0273     regmap_set_bits(vop2->map, RK3568_REG_CFG_DONE,
0274             BIT(vp->id) | RK3568_REG_CFG_DONE__GLB_CFG_DONE_EN);
0275 }
0276 
0277 static void vop2_win_disable(struct vop2_win *win)
0278 {
0279     vop2_win_write(win, VOP2_WIN_ENABLE, 0);
0280 
0281     if (vop2_cluster_window(win))
0282         vop2_win_write(win, VOP2_WIN_CLUSTER_ENABLE, 0);
0283 }
0284 
0285 static enum vop2_data_format vop2_convert_format(u32 format)
0286 {
0287     switch (format) {
0288     case DRM_FORMAT_XRGB8888:
0289     case DRM_FORMAT_ARGB8888:
0290     case DRM_FORMAT_XBGR8888:
0291     case DRM_FORMAT_ABGR8888:
0292         return VOP2_FMT_ARGB8888;
0293     case DRM_FORMAT_RGB888:
0294     case DRM_FORMAT_BGR888:
0295         return VOP2_FMT_RGB888;
0296     case DRM_FORMAT_RGB565:
0297     case DRM_FORMAT_BGR565:
0298         return VOP2_FMT_RGB565;
0299     case DRM_FORMAT_NV12:
0300         return VOP2_FMT_YUV420SP;
0301     case DRM_FORMAT_NV16:
0302         return VOP2_FMT_YUV422SP;
0303     case DRM_FORMAT_NV24:
0304         return VOP2_FMT_YUV444SP;
0305     case DRM_FORMAT_YUYV:
0306     case DRM_FORMAT_YVYU:
0307         return VOP2_FMT_VYUY422;
0308     case DRM_FORMAT_VYUY:
0309     case DRM_FORMAT_UYVY:
0310         return VOP2_FMT_YUYV422;
0311     default:
0312         DRM_ERROR("unsupported format[%08x]\n", format);
0313         return -EINVAL;
0314     }
0315 }
0316 
0317 static enum vop2_afbc_format vop2_convert_afbc_format(u32 format)
0318 {
0319     switch (format) {
0320     case DRM_FORMAT_XRGB8888:
0321     case DRM_FORMAT_ARGB8888:
0322     case DRM_FORMAT_XBGR8888:
0323     case DRM_FORMAT_ABGR8888:
0324         return VOP2_AFBC_FMT_ARGB8888;
0325     case DRM_FORMAT_RGB888:
0326     case DRM_FORMAT_BGR888:
0327         return VOP2_AFBC_FMT_RGB888;
0328     case DRM_FORMAT_RGB565:
0329     case DRM_FORMAT_BGR565:
0330         return VOP2_AFBC_FMT_RGB565;
0331     case DRM_FORMAT_NV12:
0332         return VOP2_AFBC_FMT_YUV420;
0333     case DRM_FORMAT_NV16:
0334         return VOP2_AFBC_FMT_YUV422;
0335     default:
0336         return VOP2_AFBC_FMT_INVALID;
0337     }
0338 
0339     return VOP2_AFBC_FMT_INVALID;
0340 }
0341 
0342 static bool vop2_win_rb_swap(u32 format)
0343 {
0344     switch (format) {
0345     case DRM_FORMAT_XBGR8888:
0346     case DRM_FORMAT_ABGR8888:
0347     case DRM_FORMAT_BGR888:
0348     case DRM_FORMAT_BGR565:
0349         return true;
0350     default:
0351         return false;
0352     }
0353 }
0354 
0355 static bool vop2_afbc_rb_swap(u32 format)
0356 {
0357     switch (format) {
0358     case DRM_FORMAT_NV24:
0359         return true;
0360     default:
0361         return false;
0362     }
0363 }
0364 
0365 static bool vop2_afbc_uv_swap(u32 format)
0366 {
0367     switch (format) {
0368     case DRM_FORMAT_NV12:
0369     case DRM_FORMAT_NV16:
0370         return true;
0371     default:
0372         return false;
0373     }
0374 }
0375 
0376 static bool vop2_win_uv_swap(u32 format)
0377 {
0378     switch (format) {
0379     case DRM_FORMAT_NV12:
0380     case DRM_FORMAT_NV16:
0381     case DRM_FORMAT_NV24:
0382         return true;
0383     default:
0384         return false;
0385     }
0386 }
0387 
0388 static bool vop2_win_dither_up(u32 format)
0389 {
0390     switch (format) {
0391     case DRM_FORMAT_BGR565:
0392     case DRM_FORMAT_RGB565:
0393         return true;
0394     default:
0395         return false;
0396     }
0397 }
0398 
0399 static bool vop2_output_uv_swap(u32 bus_format, u32 output_mode)
0400 {
0401     /*
0402      * FIXME:
0403      *
0404      * There is no media type for YUV444 output,
0405      * so when out_mode is AAAA or P888, assume output is YUV444 on
0406      * yuv format.
0407      *
0408      * From H/W testing, YUV444 mode need a rb swap.
0409      */
0410     if (bus_format == MEDIA_BUS_FMT_YVYU8_1X16 ||
0411         bus_format == MEDIA_BUS_FMT_VYUY8_1X16 ||
0412         bus_format == MEDIA_BUS_FMT_YVYU8_2X8 ||
0413         bus_format == MEDIA_BUS_FMT_VYUY8_2X8 ||
0414         ((bus_format == MEDIA_BUS_FMT_YUV8_1X24 ||
0415           bus_format == MEDIA_BUS_FMT_YUV10_1X30) &&
0416          (output_mode == ROCKCHIP_OUT_MODE_AAAA ||
0417           output_mode == ROCKCHIP_OUT_MODE_P888)))
0418         return true;
0419     else
0420         return false;
0421 }
0422 
0423 static bool is_yuv_output(u32 bus_format)
0424 {
0425     switch (bus_format) {
0426     case MEDIA_BUS_FMT_YUV8_1X24:
0427     case MEDIA_BUS_FMT_YUV10_1X30:
0428     case MEDIA_BUS_FMT_UYYVYY8_0_5X24:
0429     case MEDIA_BUS_FMT_UYYVYY10_0_5X30:
0430     case MEDIA_BUS_FMT_YUYV8_2X8:
0431     case MEDIA_BUS_FMT_YVYU8_2X8:
0432     case MEDIA_BUS_FMT_UYVY8_2X8:
0433     case MEDIA_BUS_FMT_VYUY8_2X8:
0434     case MEDIA_BUS_FMT_YUYV8_1X16:
0435     case MEDIA_BUS_FMT_YVYU8_1X16:
0436     case MEDIA_BUS_FMT_UYVY8_1X16:
0437     case MEDIA_BUS_FMT_VYUY8_1X16:
0438         return true;
0439     default:
0440         return false;
0441     }
0442 }
0443 
0444 static bool rockchip_afbc(struct drm_plane *plane, u64 modifier)
0445 {
0446     int i;
0447 
0448     if (modifier == DRM_FORMAT_MOD_LINEAR)
0449         return false;
0450 
0451     for (i = 0 ; i < plane->modifier_count; i++)
0452         if (plane->modifiers[i] == modifier)
0453             return true;
0454 
0455     return false;
0456 }
0457 
0458 static bool rockchip_vop2_mod_supported(struct drm_plane *plane, u32 format,
0459                     u64 modifier)
0460 {
0461     struct vop2_win *win = to_vop2_win(plane);
0462     struct vop2 *vop2 = win->vop2;
0463 
0464     if (modifier == DRM_FORMAT_MOD_INVALID)
0465         return false;
0466 
0467     if (modifier == DRM_FORMAT_MOD_LINEAR)
0468         return true;
0469 
0470     if (!rockchip_afbc(plane, modifier)) {
0471         drm_err(vop2->drm, "Unsupported format modifier 0x%llx\n",
0472             modifier);
0473 
0474         return false;
0475     }
0476 
0477     return vop2_convert_afbc_format(format) >= 0;
0478 }
0479 
0480 static u32 vop2_afbc_transform_offset(struct drm_plane_state *pstate,
0481                       bool afbc_half_block_en)
0482 {
0483     struct drm_rect *src = &pstate->src;
0484     struct drm_framebuffer *fb = pstate->fb;
0485     u32 bpp = fb->format->cpp[0] * 8;
0486     u32 vir_width = (fb->pitches[0] << 3) / bpp;
0487     u32 width = drm_rect_width(src) >> 16;
0488     u32 height = drm_rect_height(src) >> 16;
0489     u32 act_xoffset = src->x1 >> 16;
0490     u32 act_yoffset = src->y1 >> 16;
0491     u32 align16_crop = 0;
0492     u32 align64_crop = 0;
0493     u32 height_tmp;
0494     u8 tx, ty;
0495     u8 bottom_crop_line_num = 0;
0496 
0497     /* 16 pixel align */
0498     if (height & 0xf)
0499         align16_crop = 16 - (height & 0xf);
0500 
0501     height_tmp = height + align16_crop;
0502 
0503     /* 64 pixel align */
0504     if (height_tmp & 0x3f)
0505         align64_crop = 64 - (height_tmp & 0x3f);
0506 
0507     bottom_crop_line_num = align16_crop + align64_crop;
0508 
0509     switch (pstate->rotation &
0510         (DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y |
0511          DRM_MODE_ROTATE_90 | DRM_MODE_ROTATE_270)) {
0512     case DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y:
0513         tx = 16 - ((act_xoffset + width) & 0xf);
0514         ty = bottom_crop_line_num - act_yoffset;
0515         break;
0516     case DRM_MODE_REFLECT_X | DRM_MODE_ROTATE_90:
0517         tx = bottom_crop_line_num - act_yoffset;
0518         ty = vir_width - width - act_xoffset;
0519         break;
0520     case DRM_MODE_REFLECT_X | DRM_MODE_ROTATE_270:
0521         tx = act_yoffset;
0522         ty = act_xoffset;
0523         break;
0524     case DRM_MODE_REFLECT_X:
0525         tx = 16 - ((act_xoffset + width) & 0xf);
0526         ty = act_yoffset;
0527         break;
0528     case DRM_MODE_REFLECT_Y:
0529         tx = act_xoffset;
0530         ty = bottom_crop_line_num - act_yoffset;
0531         break;
0532     case DRM_MODE_ROTATE_90:
0533         tx = bottom_crop_line_num - act_yoffset;
0534         ty = act_xoffset;
0535         break;
0536     case DRM_MODE_ROTATE_270:
0537         tx = act_yoffset;
0538         ty = vir_width - width - act_xoffset;
0539         break;
0540     case 0:
0541         tx = act_xoffset;
0542         ty = act_yoffset;
0543         break;
0544     }
0545 
0546     if (afbc_half_block_en)
0547         ty &= 0x7f;
0548 
0549 #define TRANSFORM_XOFFSET GENMASK(7, 0)
0550 #define TRANSFORM_YOFFSET GENMASK(23, 16)
0551     return FIELD_PREP(TRANSFORM_XOFFSET, tx) |
0552         FIELD_PREP(TRANSFORM_YOFFSET, ty);
0553 }
0554 
0555 /*
0556  * A Cluster window has 2048 x 16 line buffer, which can
0557  * works at 2048 x 16(Full) or 4096 x 8 (Half) mode.
0558  * for Cluster_lb_mode register:
0559  * 0: half mode, for plane input width range 2048 ~ 4096
0560  * 1: half mode, for cluster work at 2 * 2048 plane mode
0561  * 2: half mode, for rotate_90/270 mode
0562  *
0563  */
0564 static int vop2_get_cluster_lb_mode(struct vop2_win *win,
0565                     struct drm_plane_state *pstate)
0566 {
0567     if ((pstate->rotation & DRM_MODE_ROTATE_270) ||
0568         (pstate->rotation & DRM_MODE_ROTATE_90))
0569         return 2;
0570     else
0571         return 0;
0572 }
0573 
0574 static u16 vop2_scale_factor(u32 src, u32 dst)
0575 {
0576     u32 fac;
0577     int shift;
0578 
0579     if (src == dst)
0580         return 0;
0581 
0582     if (dst < 2)
0583         return U16_MAX;
0584 
0585     if (src < 2)
0586         return 0;
0587 
0588     if (src > dst)
0589         shift = 12;
0590     else
0591         shift = 16;
0592 
0593     src--;
0594     dst--;
0595 
0596     fac = DIV_ROUND_UP(src << shift, dst) - 1;
0597 
0598     if (fac > U16_MAX)
0599         return U16_MAX;
0600 
0601     return fac;
0602 }
0603 
0604 static void vop2_setup_scale(struct vop2 *vop2, const struct vop2_win *win,
0605                  u32 src_w, u32 src_h, u32 dst_w,
0606                  u32 dst_h, u32 pixel_format)
0607 {
0608     const struct drm_format_info *info;
0609     u16 hor_scl_mode, ver_scl_mode;
0610     u16 hscl_filter_mode, vscl_filter_mode;
0611     u8 gt2 = 0;
0612     u8 gt4 = 0;
0613     u32 val;
0614 
0615     info = drm_format_info(pixel_format);
0616 
0617     if (src_h >= (4 * dst_h)) {
0618         gt4 = 1;
0619         src_h >>= 2;
0620     } else if (src_h >= (2 * dst_h)) {
0621         gt2 = 1;
0622         src_h >>= 1;
0623     }
0624 
0625     hor_scl_mode = scl_get_scl_mode(src_w, dst_w);
0626     ver_scl_mode = scl_get_scl_mode(src_h, dst_h);
0627 
0628     if (hor_scl_mode == SCALE_UP)
0629         hscl_filter_mode = VOP2_SCALE_UP_BIC;
0630     else
0631         hscl_filter_mode = VOP2_SCALE_DOWN_BIL;
0632 
0633     if (ver_scl_mode == SCALE_UP)
0634         vscl_filter_mode = VOP2_SCALE_UP_BIL;
0635     else
0636         vscl_filter_mode = VOP2_SCALE_DOWN_BIL;
0637 
0638     /*
0639      * RK3568 VOP Esmart/Smart dsp_w should be even pixel
0640      * at scale down mode
0641      */
0642     if (!(win->data->feature & WIN_FEATURE_AFBDC)) {
0643         if ((hor_scl_mode == SCALE_DOWN) && (dst_w & 0x1)) {
0644             drm_dbg(vop2->drm, "%s dst_w[%d] should align as 2 pixel\n",
0645                 win->data->name, dst_w);
0646             dst_w++;
0647         }
0648     }
0649 
0650     val = vop2_scale_factor(src_w, dst_w);
0651     vop2_win_write(win, VOP2_WIN_SCALE_YRGB_X, val);
0652     val = vop2_scale_factor(src_h, dst_h);
0653     vop2_win_write(win, VOP2_WIN_SCALE_YRGB_Y, val);
0654 
0655     vop2_win_write(win, VOP2_WIN_VSD_YRGB_GT4, gt4);
0656     vop2_win_write(win, VOP2_WIN_VSD_YRGB_GT2, gt2);
0657 
0658     vop2_win_write(win, VOP2_WIN_YRGB_HOR_SCL_MODE, hor_scl_mode);
0659     vop2_win_write(win, VOP2_WIN_YRGB_VER_SCL_MODE, ver_scl_mode);
0660 
0661     if (vop2_cluster_window(win))
0662         return;
0663 
0664     vop2_win_write(win, VOP2_WIN_YRGB_HSCL_FILTER_MODE, hscl_filter_mode);
0665     vop2_win_write(win, VOP2_WIN_YRGB_VSCL_FILTER_MODE, vscl_filter_mode);
0666 
0667     if (info->is_yuv) {
0668         src_w /= info->hsub;
0669         src_h /= info->vsub;
0670 
0671         gt4 = 0;
0672         gt2 = 0;
0673 
0674         if (src_h >= (4 * dst_h)) {
0675             gt4 = 1;
0676             src_h >>= 2;
0677         } else if (src_h >= (2 * dst_h)) {
0678             gt2 = 1;
0679             src_h >>= 1;
0680         }
0681 
0682         hor_scl_mode = scl_get_scl_mode(src_w, dst_w);
0683         ver_scl_mode = scl_get_scl_mode(src_h, dst_h);
0684 
0685         val = vop2_scale_factor(src_w, dst_w);
0686         vop2_win_write(win, VOP2_WIN_SCALE_CBCR_X, val);
0687 
0688         val = vop2_scale_factor(src_h, dst_h);
0689         vop2_win_write(win, VOP2_WIN_SCALE_CBCR_Y, val);
0690 
0691         vop2_win_write(win, VOP2_WIN_VSD_CBCR_GT4, gt4);
0692         vop2_win_write(win, VOP2_WIN_VSD_CBCR_GT2, gt2);
0693         vop2_win_write(win, VOP2_WIN_CBCR_HOR_SCL_MODE, hor_scl_mode);
0694         vop2_win_write(win, VOP2_WIN_CBCR_VER_SCL_MODE, ver_scl_mode);
0695         vop2_win_write(win, VOP2_WIN_CBCR_HSCL_FILTER_MODE, hscl_filter_mode);
0696         vop2_win_write(win, VOP2_WIN_CBCR_VSCL_FILTER_MODE, vscl_filter_mode);
0697     }
0698 }
0699 
0700 static int vop2_convert_csc_mode(int csc_mode)
0701 {
0702     switch (csc_mode) {
0703     case V4L2_COLORSPACE_SMPTE170M:
0704     case V4L2_COLORSPACE_470_SYSTEM_M:
0705     case V4L2_COLORSPACE_470_SYSTEM_BG:
0706         return CSC_BT601L;
0707     case V4L2_COLORSPACE_REC709:
0708     case V4L2_COLORSPACE_SMPTE240M:
0709     case V4L2_COLORSPACE_DEFAULT:
0710         return CSC_BT709L;
0711     case V4L2_COLORSPACE_JPEG:
0712         return CSC_BT601F;
0713     case V4L2_COLORSPACE_BT2020:
0714         return CSC_BT2020;
0715     default:
0716         return CSC_BT709L;
0717     }
0718 }
0719 
0720 /*
0721  * colorspace path:
0722  *      Input        Win csc                     Output
0723  * 1. YUV(2020)  --> Y2R->2020To709->R2Y   --> YUV_OUTPUT(601/709)
0724  *    RGB        --> R2Y                  __/
0725  *
0726  * 2. YUV(2020)  --> bypasss               --> YUV_OUTPUT(2020)
0727  *    RGB        --> 709To2020->R2Y       __/
0728  *
0729  * 3. YUV(2020)  --> Y2R->2020To709        --> RGB_OUTPUT(709)
0730  *    RGB        --> R2Y                  __/
0731  *
0732  * 4. YUV(601/709)-> Y2R->709To2020->R2Y   --> YUV_OUTPUT(2020)
0733  *    RGB        --> 709To2020->R2Y       __/
0734  *
0735  * 5. YUV(601/709)-> bypass                --> YUV_OUTPUT(709)
0736  *    RGB        --> R2Y                  __/
0737  *
0738  * 6. YUV(601/709)-> bypass                --> YUV_OUTPUT(601)
0739  *    RGB        --> R2Y(601)             __/
0740  *
0741  * 7. YUV        --> Y2R(709)              --> RGB_OUTPUT(709)
0742  *    RGB        --> bypass               __/
0743  *
0744  * 8. RGB        --> 709To2020->R2Y        --> YUV_OUTPUT(2020)
0745  *
0746  * 9. RGB        --> R2Y(709)              --> YUV_OUTPUT(709)
0747  *
0748  * 10. RGB       --> R2Y(601)              --> YUV_OUTPUT(601)
0749  *
0750  * 11. RGB       --> bypass                --> RGB_OUTPUT(709)
0751  */
0752 
0753 static void vop2_setup_csc_mode(struct vop2_video_port *vp,
0754                 struct vop2_win *win,
0755                 struct drm_plane_state *pstate)
0756 {
0757     struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(vp->crtc.state);
0758     int is_input_yuv = pstate->fb->format->is_yuv;
0759     int is_output_yuv = is_yuv_output(vcstate->bus_format);
0760     int input_csc = V4L2_COLORSPACE_DEFAULT;
0761     int output_csc = vcstate->color_space;
0762     bool r2y_en, y2r_en;
0763     int csc_mode;
0764 
0765     if (is_input_yuv && !is_output_yuv) {
0766         y2r_en = true;
0767         r2y_en = false;
0768         csc_mode = vop2_convert_csc_mode(input_csc);
0769     } else if (!is_input_yuv && is_output_yuv) {
0770         y2r_en = false;
0771         r2y_en = true;
0772         csc_mode = vop2_convert_csc_mode(output_csc);
0773     } else {
0774         y2r_en = false;
0775         r2y_en = false;
0776         csc_mode = false;
0777     }
0778 
0779     vop2_win_write(win, VOP2_WIN_Y2R_EN, y2r_en);
0780     vop2_win_write(win, VOP2_WIN_R2Y_EN, r2y_en);
0781     vop2_win_write(win, VOP2_WIN_CSC_MODE, csc_mode);
0782 }
0783 
0784 static void vop2_crtc_enable_irq(struct vop2_video_port *vp, u32 irq)
0785 {
0786     struct vop2 *vop2 = vp->vop2;
0787 
0788     vop2_writel(vop2, RK3568_VP_INT_CLR(vp->id), irq << 16 | irq);
0789     vop2_writel(vop2, RK3568_VP_INT_EN(vp->id), irq << 16 | irq);
0790 }
0791 
0792 static void vop2_crtc_disable_irq(struct vop2_video_port *vp, u32 irq)
0793 {
0794     struct vop2 *vop2 = vp->vop2;
0795 
0796     vop2_writel(vop2, RK3568_VP_INT_EN(vp->id), irq << 16);
0797 }
0798 
0799 static int vop2_core_clks_prepare_enable(struct vop2 *vop2)
0800 {
0801     int ret;
0802 
0803     ret = clk_prepare_enable(vop2->hclk);
0804     if (ret < 0) {
0805         drm_err(vop2->drm, "failed to enable hclk - %d\n", ret);
0806         return ret;
0807     }
0808 
0809     ret = clk_prepare_enable(vop2->aclk);
0810     if (ret < 0) {
0811         drm_err(vop2->drm, "failed to enable aclk - %d\n", ret);
0812         goto err;
0813     }
0814 
0815     return 0;
0816 err:
0817     clk_disable_unprepare(vop2->hclk);
0818 
0819     return ret;
0820 }
0821 
0822 static void vop2_enable(struct vop2 *vop2)
0823 {
0824     int ret;
0825 
0826     ret = pm_runtime_get_sync(vop2->dev);
0827     if (ret < 0) {
0828         drm_err(vop2->drm, "failed to get pm runtime: %d\n", ret);
0829         return;
0830     }
0831 
0832     ret = vop2_core_clks_prepare_enable(vop2);
0833     if (ret) {
0834         pm_runtime_put_sync(vop2->dev);
0835         return;
0836     }
0837 
0838     ret = rockchip_drm_dma_attach_device(vop2->drm, vop2->dev);
0839     if (ret) {
0840         drm_err(vop2->drm, "failed to attach dma mapping, %d\n", ret);
0841         return;
0842     }
0843 
0844     if (vop2->data->soc_id == 3566)
0845         vop2_writel(vop2, RK3568_OTP_WIN_EN, 1);
0846 
0847     vop2_writel(vop2, RK3568_REG_CFG_DONE, RK3568_REG_CFG_DONE__GLB_CFG_DONE_EN);
0848 
0849     /*
0850      * Disable auto gating, this is a workaround to
0851      * avoid display image shift when a window enabled.
0852      */
0853     regmap_clear_bits(vop2->map, RK3568_SYS_AUTO_GATING_CTRL,
0854               RK3568_SYS_AUTO_GATING_CTRL__AUTO_GATING_EN);
0855 
0856     vop2_writel(vop2, RK3568_SYS0_INT_CLR,
0857             VOP2_INT_BUS_ERRPR << 16 | VOP2_INT_BUS_ERRPR);
0858     vop2_writel(vop2, RK3568_SYS0_INT_EN,
0859             VOP2_INT_BUS_ERRPR << 16 | VOP2_INT_BUS_ERRPR);
0860     vop2_writel(vop2, RK3568_SYS1_INT_CLR,
0861             VOP2_INT_BUS_ERRPR << 16 | VOP2_INT_BUS_ERRPR);
0862     vop2_writel(vop2, RK3568_SYS1_INT_EN,
0863             VOP2_INT_BUS_ERRPR << 16 | VOP2_INT_BUS_ERRPR);
0864 }
0865 
0866 static void vop2_disable(struct vop2 *vop2)
0867 {
0868     rockchip_drm_dma_detach_device(vop2->drm, vop2->dev);
0869 
0870     pm_runtime_put_sync(vop2->dev);
0871 
0872     clk_disable_unprepare(vop2->aclk);
0873     clk_disable_unprepare(vop2->hclk);
0874 }
0875 
0876 static void vop2_crtc_atomic_disable(struct drm_crtc *crtc,
0877                      struct drm_atomic_state *state)
0878 {
0879     struct vop2_video_port *vp = to_vop2_video_port(crtc);
0880     struct vop2 *vop2 = vp->vop2;
0881     int ret;
0882 
0883     vop2_lock(vop2);
0884 
0885     drm_crtc_vblank_off(crtc);
0886 
0887     /*
0888      * Vop standby will take effect at end of current frame,
0889      * if dsp hold valid irq happen, it means standby complete.
0890      *
0891      * we must wait standby complete when we want to disable aclk,
0892      * if not, memory bus maybe dead.
0893      */
0894     reinit_completion(&vp->dsp_hold_completion);
0895 
0896     vop2_crtc_enable_irq(vp, VP_INT_DSP_HOLD_VALID);
0897 
0898     vop2_vp_write(vp, RK3568_VP_DSP_CTRL, RK3568_VP_DSP_CTRL__STANDBY);
0899 
0900     ret = wait_for_completion_timeout(&vp->dsp_hold_completion,
0901                       msecs_to_jiffies(50));
0902     if (!ret)
0903         drm_info(vop2->drm, "wait for vp%d dsp_hold timeout\n", vp->id);
0904 
0905     vop2_crtc_disable_irq(vp, VP_INT_DSP_HOLD_VALID);
0906 
0907     clk_disable_unprepare(vp->dclk);
0908 
0909     vop2->enable_count--;
0910 
0911     if (!vop2->enable_count)
0912         vop2_disable(vop2);
0913 
0914     vop2_unlock(vop2);
0915 
0916     if (crtc->state->event && !crtc->state->active) {
0917         spin_lock_irq(&crtc->dev->event_lock);
0918         drm_crtc_send_vblank_event(crtc, crtc->state->event);
0919         spin_unlock_irq(&crtc->dev->event_lock);
0920 
0921         crtc->state->event = NULL;
0922     }
0923 }
0924 
0925 static int vop2_plane_atomic_check(struct drm_plane *plane,
0926                    struct drm_atomic_state *astate)
0927 {
0928     struct drm_plane_state *pstate = drm_atomic_get_new_plane_state(astate, plane);
0929     struct drm_framebuffer *fb = pstate->fb;
0930     struct drm_crtc *crtc = pstate->crtc;
0931     struct drm_crtc_state *cstate;
0932     struct vop2_video_port *vp;
0933     struct vop2 *vop2;
0934     const struct vop2_data *vop2_data;
0935     struct drm_rect *dest = &pstate->dst;
0936     struct drm_rect *src = &pstate->src;
0937     int min_scale = FRAC_16_16(1, 8);
0938     int max_scale = FRAC_16_16(8, 1);
0939     int format;
0940     int ret;
0941 
0942     if (!crtc)
0943         return 0;
0944 
0945     vp = to_vop2_video_port(crtc);
0946     vop2 = vp->vop2;
0947     vop2_data = vop2->data;
0948 
0949     cstate = drm_atomic_get_existing_crtc_state(pstate->state, crtc);
0950     if (WARN_ON(!cstate))
0951         return -EINVAL;
0952 
0953     ret = drm_atomic_helper_check_plane_state(pstate, cstate,
0954                           min_scale, max_scale,
0955                           true, true);
0956     if (ret)
0957         return ret;
0958 
0959     if (!pstate->visible)
0960         return 0;
0961 
0962     format = vop2_convert_format(fb->format->format);
0963     if (format < 0)
0964         return format;
0965 
0966     if (drm_rect_width(src) >> 16 < 4 || drm_rect_height(src) >> 16 < 4 ||
0967         drm_rect_width(dest) < 4 || drm_rect_width(dest) < 4) {
0968         drm_err(vop2->drm, "Invalid size: %dx%d->%dx%d, min size is 4x4\n",
0969             drm_rect_width(src) >> 16, drm_rect_height(src) >> 16,
0970             drm_rect_width(dest), drm_rect_height(dest));
0971         pstate->visible = false;
0972         return 0;
0973     }
0974 
0975     if (drm_rect_width(src) >> 16 > vop2_data->max_input.width ||
0976         drm_rect_height(src) >> 16 > vop2_data->max_input.height) {
0977         drm_err(vop2->drm, "Invalid source: %dx%d. max input: %dx%d\n",
0978             drm_rect_width(src) >> 16,
0979             drm_rect_height(src) >> 16,
0980             vop2_data->max_input.width,
0981             vop2_data->max_input.height);
0982         return -EINVAL;
0983     }
0984 
0985     /*
0986      * Src.x1 can be odd when do clip, but yuv plane start point
0987      * need align with 2 pixel.
0988      */
0989     if (fb->format->is_yuv && ((pstate->src.x1 >> 16) % 2)) {
0990         drm_err(vop2->drm, "Invalid Source: Yuv format not support odd xpos\n");
0991         return -EINVAL;
0992     }
0993 
0994     return 0;
0995 }
0996 
0997 static void vop2_plane_atomic_disable(struct drm_plane *plane,
0998                       struct drm_atomic_state *state)
0999 {
1000     struct drm_plane_state *old_pstate = drm_atomic_get_old_plane_state(state, plane);
1001     struct vop2_win *win = to_vop2_win(plane);
1002     struct vop2 *vop2 = win->vop2;
1003 
1004     drm_dbg(vop2->drm, "%s disable\n", win->data->name);
1005 
1006     if (!old_pstate->crtc)
1007         return;
1008 
1009     vop2_win_disable(win);
1010     vop2_win_write(win, VOP2_WIN_YUV_CLIP, 0);
1011 }
1012 
1013 /*
1014  * The color key is 10 bit, so all format should
1015  * convert to 10 bit here.
1016  */
1017 static void vop2_plane_setup_color_key(struct drm_plane *plane, u32 color_key)
1018 {
1019     struct drm_plane_state *pstate = plane->state;
1020     struct drm_framebuffer *fb = pstate->fb;
1021     struct vop2_win *win = to_vop2_win(plane);
1022     u32 color_key_en = 0;
1023     u32 r = 0;
1024     u32 g = 0;
1025     u32 b = 0;
1026 
1027     if (!(color_key & VOP2_COLOR_KEY_MASK) || fb->format->is_yuv) {
1028         vop2_win_write(win, VOP2_WIN_COLOR_KEY_EN, 0);
1029         return;
1030     }
1031 
1032     switch (fb->format->format) {
1033     case DRM_FORMAT_RGB565:
1034     case DRM_FORMAT_BGR565:
1035         r = (color_key & 0xf800) >> 11;
1036         g = (color_key & 0x7e0) >> 5;
1037         b = (color_key & 0x1f);
1038         r <<= 5;
1039         g <<= 4;
1040         b <<= 5;
1041         color_key_en = 1;
1042         break;
1043     case DRM_FORMAT_XRGB8888:
1044     case DRM_FORMAT_ARGB8888:
1045     case DRM_FORMAT_XBGR8888:
1046     case DRM_FORMAT_ABGR8888:
1047     case DRM_FORMAT_RGB888:
1048     case DRM_FORMAT_BGR888:
1049         r = (color_key & 0xff0000) >> 16;
1050         g = (color_key & 0xff00) >> 8;
1051         b = (color_key & 0xff);
1052         r <<= 2;
1053         g <<= 2;
1054         b <<= 2;
1055         color_key_en = 1;
1056         break;
1057     }
1058 
1059     vop2_win_write(win, VOP2_WIN_COLOR_KEY_EN, color_key_en);
1060     vop2_win_write(win, VOP2_WIN_COLOR_KEY, (r << 20) | (g << 10) | b);
1061 }
1062 
1063 static void vop2_plane_atomic_update(struct drm_plane *plane,
1064                      struct drm_atomic_state *state)
1065 {
1066     struct drm_plane_state *pstate = plane->state;
1067     struct drm_crtc *crtc = pstate->crtc;
1068     struct vop2_win *win = to_vop2_win(plane);
1069     struct vop2_video_port *vp = to_vop2_video_port(crtc);
1070     struct drm_display_mode *adjusted_mode = &crtc->state->adjusted_mode;
1071     struct vop2 *vop2 = win->vop2;
1072     struct drm_framebuffer *fb = pstate->fb;
1073     u32 bpp = fb->format->cpp[0] * 8;
1074     u32 actual_w, actual_h, dsp_w, dsp_h;
1075     u32 act_info, dsp_info;
1076     u32 format;
1077     u32 afbc_format;
1078     u32 rb_swap;
1079     u32 uv_swap;
1080     struct drm_rect *src = &pstate->src;
1081     struct drm_rect *dest = &pstate->dst;
1082     u32 afbc_tile_num;
1083     u32 transform_offset;
1084     bool dither_up;
1085     bool xmirror = pstate->rotation & DRM_MODE_REFLECT_X ? true : false;
1086     bool ymirror = pstate->rotation & DRM_MODE_REFLECT_Y ? true : false;
1087     bool rotate_270 = pstate->rotation & DRM_MODE_ROTATE_270;
1088     bool rotate_90 = pstate->rotation & DRM_MODE_ROTATE_90;
1089     struct rockchip_gem_object *rk_obj;
1090     unsigned long offset;
1091     bool afbc_en;
1092     dma_addr_t yrgb_mst;
1093     dma_addr_t uv_mst;
1094 
1095     /*
1096      * can't update plane when vop2 is disabled.
1097      */
1098     if (WARN_ON(!crtc))
1099         return;
1100 
1101     if (!pstate->visible) {
1102         vop2_plane_atomic_disable(plane, state);
1103         return;
1104     }
1105 
1106     afbc_en = rockchip_afbc(plane, fb->modifier);
1107 
1108     offset = (src->x1 >> 16) * fb->format->cpp[0];
1109 
1110     /*
1111      * AFBC HDR_PTR must set to the zero offset of the framebuffer.
1112      */
1113     if (afbc_en)
1114         offset = 0;
1115     else if (pstate->rotation & DRM_MODE_REFLECT_Y)
1116         offset += ((src->y2 >> 16) - 1) * fb->pitches[0];
1117     else
1118         offset += (src->y1 >> 16) * fb->pitches[0];
1119 
1120     rk_obj = to_rockchip_obj(fb->obj[0]);
1121 
1122     yrgb_mst = rk_obj->dma_addr + offset + fb->offsets[0];
1123     if (fb->format->is_yuv) {
1124         int hsub = fb->format->hsub;
1125         int vsub = fb->format->vsub;
1126 
1127         offset = (src->x1 >> 16) * fb->format->cpp[1] / hsub;
1128         offset += (src->y1 >> 16) * fb->pitches[1] / vsub;
1129 
1130         if ((pstate->rotation & DRM_MODE_REFLECT_Y) && !afbc_en)
1131             offset += fb->pitches[1] * ((pstate->src_h >> 16) - 2) / vsub;
1132 
1133         rk_obj = to_rockchip_obj(fb->obj[0]);
1134         uv_mst = rk_obj->dma_addr + offset + fb->offsets[1];
1135     }
1136 
1137     actual_w = drm_rect_width(src) >> 16;
1138     actual_h = drm_rect_height(src) >> 16;
1139     dsp_w = drm_rect_width(dest);
1140 
1141     if (dest->x1 + dsp_w > adjusted_mode->hdisplay) {
1142         drm_err(vop2->drm, "vp%d %s dest->x1[%d] + dsp_w[%d] exceed mode hdisplay[%d]\n",
1143             vp->id, win->data->name, dest->x1, dsp_w, adjusted_mode->hdisplay);
1144         dsp_w = adjusted_mode->hdisplay - dest->x1;
1145         if (dsp_w < 4)
1146             dsp_w = 4;
1147         actual_w = dsp_w * actual_w / drm_rect_width(dest);
1148     }
1149 
1150     dsp_h = drm_rect_height(dest);
1151 
1152     if (dest->y1 + dsp_h > adjusted_mode->vdisplay) {
1153         drm_err(vop2->drm, "vp%d %s dest->y1[%d] + dsp_h[%d] exceed mode vdisplay[%d]\n",
1154             vp->id, win->data->name, dest->y1, dsp_h, adjusted_mode->vdisplay);
1155         dsp_h = adjusted_mode->vdisplay - dest->y1;
1156         if (dsp_h < 4)
1157             dsp_h = 4;
1158         actual_h = dsp_h * actual_h / drm_rect_height(dest);
1159     }
1160 
1161     /*
1162      * This is workaround solution for IC design:
1163      * esmart can't support scale down when actual_w % 16 == 1.
1164      */
1165     if (!(win->data->feature & WIN_FEATURE_AFBDC)) {
1166         if (actual_w > dsp_w && (actual_w & 0xf) == 1) {
1167             drm_err(vop2->drm, "vp%d %s act_w[%d] MODE 16 == 1\n",
1168                 vp->id, win->data->name, actual_w);
1169             actual_w -= 1;
1170         }
1171     }
1172 
1173     if (afbc_en && actual_w % 4) {
1174         drm_err(vop2->drm, "vp%d %s actual_w[%d] not 4 pixel aligned\n",
1175             vp->id, win->data->name, actual_w);
1176         actual_w = ALIGN_DOWN(actual_w, 4);
1177     }
1178 
1179     act_info = (actual_h - 1) << 16 | ((actual_w - 1) & 0xffff);
1180     dsp_info = (dsp_h - 1) << 16 | ((dsp_w - 1) & 0xffff);
1181 
1182     format = vop2_convert_format(fb->format->format);
1183 
1184     drm_dbg(vop2->drm, "vp%d update %s[%dx%d->%dx%d@%dx%d] fmt[%p4cc_%s] addr[%pad]\n",
1185         vp->id, win->data->name, actual_w, actual_h, dsp_w, dsp_h,
1186         dest->x1, dest->y1,
1187         &fb->format->format,
1188         afbc_en ? "AFBC" : "", &yrgb_mst);
1189 
1190     if (afbc_en) {
1191         u32 stride;
1192 
1193         /* the afbc superblock is 16 x 16 */
1194         afbc_format = vop2_convert_afbc_format(fb->format->format);
1195 
1196         /* Enable color transform for YTR */
1197         if (fb->modifier & AFBC_FORMAT_MOD_YTR)
1198             afbc_format |= (1 << 4);
1199 
1200         afbc_tile_num = ALIGN(actual_w, 16) >> 4;
1201 
1202         /*
1203          * AFBC pic_vir_width is count by pixel, this is different
1204          * with WIN_VIR_STRIDE.
1205          */
1206         stride = (fb->pitches[0] << 3) / bpp;
1207         if ((stride & 0x3f) && (xmirror || rotate_90 || rotate_270))
1208             drm_err(vop2->drm, "vp%d %s stride[%d] not 64 pixel aligned\n",
1209                 vp->id, win->data->name, stride);
1210 
1211         rb_swap = vop2_afbc_rb_swap(fb->format->format);
1212         uv_swap = vop2_afbc_uv_swap(fb->format->format);
1213         /*
1214          * This is a workaround for crazy IC design, Cluster
1215          * and Esmart/Smart use different format configuration map:
1216          * YUV420_10BIT: 0x10 for Cluster, 0x14 for Esmart/Smart.
1217          *
1218          * This is one thing we can make the convert simple:
1219          * AFBCD decode all the YUV data to YUV444. So we just
1220          * set all the yuv 10 bit to YUV444_10.
1221          */
1222         if (fb->format->is_yuv && bpp == 10)
1223             format = VOP2_CLUSTER_YUV444_10;
1224 
1225         if (vop2_cluster_window(win))
1226             vop2_win_write(win, VOP2_WIN_AFBC_ENABLE, 1);
1227         vop2_win_write(win, VOP2_WIN_AFBC_FORMAT, afbc_format);
1228         vop2_win_write(win, VOP2_WIN_AFBC_RB_SWAP, rb_swap);
1229         vop2_win_write(win, VOP2_WIN_AFBC_UV_SWAP, uv_swap);
1230         vop2_win_write(win, VOP2_WIN_AFBC_AUTO_GATING_EN, 0);
1231         vop2_win_write(win, VOP2_WIN_AFBC_BLOCK_SPLIT_EN, 0);
1232         if (pstate->rotation & (DRM_MODE_ROTATE_270 | DRM_MODE_ROTATE_90)) {
1233             vop2_win_write(win, VOP2_WIN_AFBC_HALF_BLOCK_EN, 0);
1234             transform_offset = vop2_afbc_transform_offset(pstate, false);
1235         } else {
1236             vop2_win_write(win, VOP2_WIN_AFBC_HALF_BLOCK_EN, 1);
1237             transform_offset = vop2_afbc_transform_offset(pstate, true);
1238         }
1239         vop2_win_write(win, VOP2_WIN_AFBC_HDR_PTR, yrgb_mst);
1240         vop2_win_write(win, VOP2_WIN_AFBC_PIC_SIZE, act_info);
1241         vop2_win_write(win, VOP2_WIN_AFBC_TRANSFORM_OFFSET, transform_offset);
1242         vop2_win_write(win, VOP2_WIN_AFBC_PIC_OFFSET, ((src->x1 >> 16) | src->y1));
1243         vop2_win_write(win, VOP2_WIN_AFBC_DSP_OFFSET, (dest->x1 | (dest->y1 << 16)));
1244         vop2_win_write(win, VOP2_WIN_AFBC_PIC_VIR_WIDTH, stride);
1245         vop2_win_write(win, VOP2_WIN_AFBC_TILE_NUM, afbc_tile_num);
1246         vop2_win_write(win, VOP2_WIN_XMIRROR, xmirror);
1247         vop2_win_write(win, VOP2_WIN_AFBC_ROTATE_270, rotate_270);
1248         vop2_win_write(win, VOP2_WIN_AFBC_ROTATE_90, rotate_90);
1249     } else {
1250         vop2_win_write(win, VOP2_WIN_YRGB_VIR, DIV_ROUND_UP(fb->pitches[0], 4));
1251     }
1252 
1253     vop2_win_write(win, VOP2_WIN_YMIRROR, ymirror);
1254 
1255     if (rotate_90 || rotate_270) {
1256         act_info = swahw32(act_info);
1257         actual_w = drm_rect_height(src) >> 16;
1258         actual_h = drm_rect_width(src) >> 16;
1259     }
1260 
1261     vop2_win_write(win, VOP2_WIN_FORMAT, format);
1262     vop2_win_write(win, VOP2_WIN_YRGB_MST, yrgb_mst);
1263 
1264     rb_swap = vop2_win_rb_swap(fb->format->format);
1265     vop2_win_write(win, VOP2_WIN_RB_SWAP, rb_swap);
1266     if (!vop2_cluster_window(win)) {
1267         uv_swap = vop2_win_uv_swap(fb->format->format);
1268         vop2_win_write(win, VOP2_WIN_UV_SWAP, uv_swap);
1269     }
1270 
1271     if (fb->format->is_yuv) {
1272         vop2_win_write(win, VOP2_WIN_UV_VIR, DIV_ROUND_UP(fb->pitches[1], 4));
1273         vop2_win_write(win, VOP2_WIN_UV_MST, uv_mst);
1274     }
1275 
1276     vop2_setup_scale(vop2, win, actual_w, actual_h, dsp_w, dsp_h, fb->format->format);
1277     if (!vop2_cluster_window(win))
1278         vop2_plane_setup_color_key(plane, 0);
1279     vop2_win_write(win, VOP2_WIN_ACT_INFO, act_info);
1280     vop2_win_write(win, VOP2_WIN_DSP_INFO, dsp_info);
1281     vop2_win_write(win, VOP2_WIN_DSP_ST, dest->y1 << 16 | (dest->x1 & 0xffff));
1282 
1283     vop2_setup_csc_mode(vp, win, pstate);
1284 
1285     dither_up = vop2_win_dither_up(fb->format->format);
1286     vop2_win_write(win, VOP2_WIN_DITHER_UP, dither_up);
1287 
1288     vop2_win_write(win, VOP2_WIN_ENABLE, 1);
1289 
1290     if (vop2_cluster_window(win)) {
1291         int lb_mode = vop2_get_cluster_lb_mode(win, pstate);
1292 
1293         vop2_win_write(win, VOP2_WIN_CLUSTER_LB_MODE, lb_mode);
1294         vop2_win_write(win, VOP2_WIN_CLUSTER_ENABLE, 1);
1295     }
1296 }
1297 
1298 static const struct drm_plane_helper_funcs vop2_plane_helper_funcs = {
1299     .atomic_check = vop2_plane_atomic_check,
1300     .atomic_update = vop2_plane_atomic_update,
1301     .atomic_disable = vop2_plane_atomic_disable,
1302 };
1303 
1304 static const struct drm_plane_funcs vop2_plane_funcs = {
1305     .update_plane   = drm_atomic_helper_update_plane,
1306     .disable_plane  = drm_atomic_helper_disable_plane,
1307     .destroy = drm_plane_cleanup,
1308     .reset = drm_atomic_helper_plane_reset,
1309     .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
1310     .atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
1311     .format_mod_supported = rockchip_vop2_mod_supported,
1312 };
1313 
1314 static int vop2_crtc_enable_vblank(struct drm_crtc *crtc)
1315 {
1316     struct vop2_video_port *vp = to_vop2_video_port(crtc);
1317 
1318     vop2_crtc_enable_irq(vp, VP_INT_FS_FIELD);
1319 
1320     return 0;
1321 }
1322 
1323 static void vop2_crtc_disable_vblank(struct drm_crtc *crtc)
1324 {
1325     struct vop2_video_port *vp = to_vop2_video_port(crtc);
1326 
1327     vop2_crtc_disable_irq(vp, VP_INT_FS_FIELD);
1328 }
1329 
1330 static bool vop2_crtc_mode_fixup(struct drm_crtc *crtc,
1331                  const struct drm_display_mode *mode,
1332                  struct drm_display_mode *adj_mode)
1333 {
1334     drm_mode_set_crtcinfo(adj_mode, CRTC_INTERLACE_HALVE_V |
1335                     CRTC_STEREO_DOUBLE);
1336 
1337     return true;
1338 }
1339 
1340 static void vop2_dither_setup(struct drm_crtc *crtc, u32 *dsp_ctrl)
1341 {
1342     struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state);
1343 
1344     switch (vcstate->bus_format) {
1345     case MEDIA_BUS_FMT_RGB565_1X16:
1346         *dsp_ctrl |= RK3568_VP_DSP_CTRL__DITHER_DOWN_EN;
1347         break;
1348     case MEDIA_BUS_FMT_RGB666_1X18:
1349     case MEDIA_BUS_FMT_RGB666_1X24_CPADHI:
1350     case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG:
1351         *dsp_ctrl |= RK3568_VP_DSP_CTRL__DITHER_DOWN_EN;
1352         *dsp_ctrl |= RGB888_TO_RGB666;
1353         break;
1354     case MEDIA_BUS_FMT_YUV8_1X24:
1355     case MEDIA_BUS_FMT_UYYVYY8_0_5X24:
1356         *dsp_ctrl |= RK3568_VP_DSP_CTRL__PRE_DITHER_DOWN_EN;
1357         break;
1358     default:
1359         break;
1360     }
1361 
1362     if (vcstate->output_mode != ROCKCHIP_OUT_MODE_AAAA)
1363         *dsp_ctrl |= RK3568_VP_DSP_CTRL__PRE_DITHER_DOWN_EN;
1364 
1365     *dsp_ctrl |= FIELD_PREP(RK3568_VP_DSP_CTRL__DITHER_DOWN_SEL,
1366                 DITHER_DOWN_ALLEGRO);
1367 }
1368 
1369 static void vop2_post_config(struct drm_crtc *crtc)
1370 {
1371     struct vop2_video_port *vp = to_vop2_video_port(crtc);
1372     struct drm_display_mode *mode = &crtc->state->adjusted_mode;
1373     u16 vtotal = mode->crtc_vtotal;
1374     u16 hdisplay = mode->crtc_hdisplay;
1375     u16 hact_st = mode->crtc_htotal - mode->crtc_hsync_start;
1376     u16 vdisplay = mode->crtc_vdisplay;
1377     u16 vact_st = mode->crtc_vtotal - mode->crtc_vsync_start;
1378     u32 left_margin = 100, right_margin = 100;
1379     u32 top_margin = 100, bottom_margin = 100;
1380     u16 hsize = hdisplay * (left_margin + right_margin) / 200;
1381     u16 vsize = vdisplay * (top_margin + bottom_margin) / 200;
1382     u16 hact_end, vact_end;
1383     u32 val;
1384 
1385     vsize = rounddown(vsize, 2);
1386     hsize = rounddown(hsize, 2);
1387     hact_st += hdisplay * (100 - left_margin) / 200;
1388     hact_end = hact_st + hsize;
1389     val = hact_st << 16;
1390     val |= hact_end;
1391     vop2_vp_write(vp, RK3568_VP_POST_DSP_HACT_INFO, val);
1392     vact_st += vdisplay * (100 - top_margin) / 200;
1393     vact_end = vact_st + vsize;
1394     val = vact_st << 16;
1395     val |= vact_end;
1396     vop2_vp_write(vp, RK3568_VP_POST_DSP_VACT_INFO, val);
1397     val = scl_cal_scale2(vdisplay, vsize) << 16;
1398     val |= scl_cal_scale2(hdisplay, hsize);
1399     vop2_vp_write(vp, RK3568_VP_POST_SCL_FACTOR_YRGB, val);
1400 
1401     val = 0;
1402     if (hdisplay != hsize)
1403         val |= RK3568_VP_POST_SCL_CTRL__HSCALEDOWN;
1404     if (vdisplay != vsize)
1405         val |= RK3568_VP_POST_SCL_CTRL__VSCALEDOWN;
1406     vop2_vp_write(vp, RK3568_VP_POST_SCL_CTRL, val);
1407 
1408     if (mode->flags & DRM_MODE_FLAG_INTERLACE) {
1409         u16 vact_st_f1 = vtotal + vact_st + 1;
1410         u16 vact_end_f1 = vact_st_f1 + vsize;
1411 
1412         val = vact_st_f1 << 16 | vact_end_f1;
1413         vop2_vp_write(vp, RK3568_VP_POST_DSP_VACT_INFO_F1, val);
1414     }
1415 
1416     vop2_vp_write(vp, RK3568_VP_DSP_BG, 0);
1417 }
1418 
1419 static void rk3568_set_intf_mux(struct vop2_video_port *vp, int id,
1420                 u32 polflags)
1421 {
1422     struct vop2 *vop2 = vp->vop2;
1423     u32 die, dip;
1424 
1425     die = vop2_readl(vop2, RK3568_DSP_IF_EN);
1426     dip = vop2_readl(vop2, RK3568_DSP_IF_POL);
1427 
1428     switch (id) {
1429     case ROCKCHIP_VOP2_EP_RGB0:
1430         die &= ~RK3568_SYS_DSP_INFACE_EN_RGB_MUX;
1431         die |= RK3568_SYS_DSP_INFACE_EN_RGB |
1432                FIELD_PREP(RK3568_SYS_DSP_INFACE_EN_RGB_MUX, vp->id);
1433         if (polflags & POLFLAG_DCLK_INV)
1434             regmap_write(vop2->grf, RK3568_GRF_VO_CON1, BIT(3 + 16) | BIT(3));
1435         else
1436             regmap_write(vop2->grf, RK3568_GRF_VO_CON1, BIT(3 + 16));
1437         break;
1438     case ROCKCHIP_VOP2_EP_HDMI0:
1439         die &= ~RK3568_SYS_DSP_INFACE_EN_HDMI_MUX;
1440         die |= RK3568_SYS_DSP_INFACE_EN_HDMI |
1441                FIELD_PREP(RK3568_SYS_DSP_INFACE_EN_HDMI_MUX, vp->id);
1442         dip &= ~RK3568_DSP_IF_POL__HDMI_PIN_POL;
1443         dip |= FIELD_PREP(RK3568_DSP_IF_POL__HDMI_PIN_POL, polflags);
1444         break;
1445     case ROCKCHIP_VOP2_EP_EDP0:
1446         die &= ~RK3568_SYS_DSP_INFACE_EN_EDP_MUX;
1447         die |= RK3568_SYS_DSP_INFACE_EN_EDP |
1448                FIELD_PREP(RK3568_SYS_DSP_INFACE_EN_EDP_MUX, vp->id);
1449         dip &= ~RK3568_DSP_IF_POL__EDP_PIN_POL;
1450         dip |= FIELD_PREP(RK3568_DSP_IF_POL__EDP_PIN_POL, polflags);
1451         break;
1452     case ROCKCHIP_VOP2_EP_MIPI0:
1453         die &= ~RK3568_SYS_DSP_INFACE_EN_MIPI0_MUX;
1454         die |= RK3568_SYS_DSP_INFACE_EN_MIPI0 |
1455                FIELD_PREP(RK3568_SYS_DSP_INFACE_EN_MIPI0_MUX, vp->id);
1456         dip &= ~RK3568_DSP_IF_POL__MIPI_PIN_POL;
1457         dip |= FIELD_PREP(RK3568_DSP_IF_POL__MIPI_PIN_POL, polflags);
1458         break;
1459     case ROCKCHIP_VOP2_EP_MIPI1:
1460         die &= ~RK3568_SYS_DSP_INFACE_EN_MIPI1_MUX;
1461         die |= RK3568_SYS_DSP_INFACE_EN_MIPI1 |
1462                FIELD_PREP(RK3568_SYS_DSP_INFACE_EN_MIPI1_MUX, vp->id);
1463         dip &= ~RK3568_DSP_IF_POL__MIPI_PIN_POL;
1464         dip |= FIELD_PREP(RK3568_DSP_IF_POL__MIPI_PIN_POL, polflags);
1465         break;
1466     case ROCKCHIP_VOP2_EP_LVDS0:
1467         die &= ~RK3568_SYS_DSP_INFACE_EN_LVDS0_MUX;
1468         die |= RK3568_SYS_DSP_INFACE_EN_LVDS0 |
1469                FIELD_PREP(RK3568_SYS_DSP_INFACE_EN_LVDS0_MUX, vp->id);
1470         dip &= ~RK3568_DSP_IF_POL__RGB_LVDS_PIN_POL;
1471         dip |= FIELD_PREP(RK3568_DSP_IF_POL__RGB_LVDS_PIN_POL, polflags);
1472         break;
1473     case ROCKCHIP_VOP2_EP_LVDS1:
1474         die &= ~RK3568_SYS_DSP_INFACE_EN_LVDS1_MUX;
1475         die |= RK3568_SYS_DSP_INFACE_EN_LVDS1 |
1476                FIELD_PREP(RK3568_SYS_DSP_INFACE_EN_LVDS1_MUX, vp->id);
1477         dip &= ~RK3568_DSP_IF_POL__RGB_LVDS_PIN_POL;
1478         dip |= FIELD_PREP(RK3568_DSP_IF_POL__RGB_LVDS_PIN_POL, polflags);
1479         break;
1480     default:
1481         drm_err(vop2->drm, "Invalid interface id %d on vp%d\n", id, vp->id);
1482         return;
1483     }
1484 
1485     dip |= RK3568_DSP_IF_POL__CFG_DONE_IMD;
1486 
1487     vop2_writel(vop2, RK3568_DSP_IF_EN, die);
1488     vop2_writel(vop2, RK3568_DSP_IF_POL, dip);
1489 }
1490 
1491 static int us_to_vertical_line(struct drm_display_mode *mode, int us)
1492 {
1493     return us * mode->clock / mode->htotal / 1000;
1494 }
1495 
1496 static void vop2_crtc_atomic_enable(struct drm_crtc *crtc,
1497                     struct drm_atomic_state *state)
1498 {
1499     struct vop2_video_port *vp = to_vop2_video_port(crtc);
1500     struct vop2 *vop2 = vp->vop2;
1501     const struct vop2_data *vop2_data = vop2->data;
1502     const struct vop2_video_port_data *vp_data = &vop2_data->vp[vp->id];
1503     struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
1504     struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state);
1505     struct drm_display_mode *mode = &crtc->state->adjusted_mode;
1506     unsigned long clock = mode->crtc_clock * 1000;
1507     u16 hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start;
1508     u16 hdisplay = mode->crtc_hdisplay;
1509     u16 htotal = mode->crtc_htotal;
1510     u16 hact_st = mode->crtc_htotal - mode->crtc_hsync_start;
1511     u16 hact_end = hact_st + hdisplay;
1512     u16 vdisplay = mode->crtc_vdisplay;
1513     u16 vtotal = mode->crtc_vtotal;
1514     u16 vsync_len = mode->crtc_vsync_end - mode->crtc_vsync_start;
1515     u16 vact_st = mode->crtc_vtotal - mode->crtc_vsync_start;
1516     u16 vact_end = vact_st + vdisplay;
1517     u8 out_mode;
1518     u32 dsp_ctrl = 0;
1519     int act_end;
1520     u32 val, polflags;
1521     int ret;
1522     struct drm_encoder *encoder;
1523 
1524     drm_dbg(vop2->drm, "Update mode to %dx%d%s%d, type: %d for vp%d\n",
1525         hdisplay, vdisplay, mode->flags & DRM_MODE_FLAG_INTERLACE ? "i" : "p",
1526         drm_mode_vrefresh(mode), vcstate->output_type, vp->id);
1527 
1528     vop2_lock(vop2);
1529 
1530     ret = clk_prepare_enable(vp->dclk);
1531     if (ret < 0) {
1532         drm_err(vop2->drm, "failed to enable dclk for video port%d - %d\n",
1533             vp->id, ret);
1534         vop2_unlock(vop2);
1535         return;
1536     }
1537 
1538     if (!vop2->enable_count)
1539         vop2_enable(vop2);
1540 
1541     vop2->enable_count++;
1542 
1543     vop2_crtc_enable_irq(vp, VP_INT_POST_BUF_EMPTY);
1544 
1545     polflags = 0;
1546     if (vcstate->bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE)
1547         polflags |= POLFLAG_DCLK_INV;
1548     if (mode->flags & DRM_MODE_FLAG_PHSYNC)
1549         polflags |= BIT(HSYNC_POSITIVE);
1550     if (mode->flags & DRM_MODE_FLAG_PVSYNC)
1551         polflags |= BIT(VSYNC_POSITIVE);
1552 
1553     drm_for_each_encoder_mask(encoder, crtc->dev, crtc_state->encoder_mask) {
1554         struct rockchip_encoder *rkencoder = to_rockchip_encoder(encoder);
1555 
1556         rk3568_set_intf_mux(vp, rkencoder->crtc_endpoint_id, polflags);
1557     }
1558 
1559     if (vcstate->output_mode == ROCKCHIP_OUT_MODE_AAAA &&
1560         !(vp_data->feature & VOP_FEATURE_OUTPUT_10BIT))
1561         out_mode = ROCKCHIP_OUT_MODE_P888;
1562     else
1563         out_mode = vcstate->output_mode;
1564 
1565     dsp_ctrl |= FIELD_PREP(RK3568_VP_DSP_CTRL__OUT_MODE, out_mode);
1566 
1567     if (vop2_output_uv_swap(vcstate->bus_format, vcstate->output_mode))
1568         dsp_ctrl |= RK3568_VP_DSP_CTRL__DSP_RB_SWAP;
1569 
1570     if (is_yuv_output(vcstate->bus_format))
1571         dsp_ctrl |= RK3568_VP_DSP_CTRL__POST_DSP_OUT_R2Y;
1572 
1573     vop2_dither_setup(crtc, &dsp_ctrl);
1574 
1575     vop2_vp_write(vp, RK3568_VP_DSP_HTOTAL_HS_END, (htotal << 16) | hsync_len);
1576     val = hact_st << 16;
1577     val |= hact_end;
1578     vop2_vp_write(vp, RK3568_VP_DSP_HACT_ST_END, val);
1579 
1580     val = vact_st << 16;
1581     val |= vact_end;
1582     vop2_vp_write(vp, RK3568_VP_DSP_VACT_ST_END, val);
1583 
1584     if (mode->flags & DRM_MODE_FLAG_INTERLACE) {
1585         u16 vact_st_f1 = vtotal + vact_st + 1;
1586         u16 vact_end_f1 = vact_st_f1 + vdisplay;
1587 
1588         val = vact_st_f1 << 16 | vact_end_f1;
1589         vop2_vp_write(vp, RK3568_VP_DSP_VACT_ST_END_F1, val);
1590 
1591         val = vtotal << 16 | (vtotal + vsync_len);
1592         vop2_vp_write(vp, RK3568_VP_DSP_VS_ST_END_F1, val);
1593         dsp_ctrl |= RK3568_VP_DSP_CTRL__DSP_INTERLACE;
1594         dsp_ctrl |= RK3568_VP_DSP_CTRL__DSP_FILED_POL;
1595         dsp_ctrl |= RK3568_VP_DSP_CTRL__P2I_EN;
1596         vtotal += vtotal + 1;
1597         act_end = vact_end_f1;
1598     } else {
1599         act_end = vact_end;
1600     }
1601 
1602     vop2_writel(vop2, RK3568_VP_LINE_FLAG(vp->id),
1603             (act_end - us_to_vertical_line(mode, 0)) << 16 | act_end);
1604 
1605     vop2_vp_write(vp, RK3568_VP_DSP_VTOTAL_VS_END, vtotal << 16 | vsync_len);
1606 
1607     if (mode->flags & DRM_MODE_FLAG_DBLCLK) {
1608         dsp_ctrl |= RK3568_VP_DSP_CTRL__CORE_DCLK_DIV;
1609         clock *= 2;
1610     }
1611 
1612     vop2_vp_write(vp, RK3568_VP_MIPI_CTRL, 0);
1613 
1614     clk_set_rate(vp->dclk, clock);
1615 
1616     vop2_post_config(crtc);
1617 
1618     vop2_cfg_done(vp);
1619 
1620     vop2_vp_write(vp, RK3568_VP_DSP_CTRL, dsp_ctrl);
1621 
1622     drm_crtc_vblank_on(crtc);
1623 
1624     vop2_unlock(vop2);
1625 }
1626 
1627 static int vop2_crtc_atomic_check(struct drm_crtc *crtc,
1628                   struct drm_atomic_state *state)
1629 {
1630     struct vop2_video_port *vp = to_vop2_video_port(crtc);
1631     struct drm_plane *plane;
1632     int nplanes = 0;
1633     struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
1634 
1635     drm_atomic_crtc_state_for_each_plane(plane, crtc_state)
1636         nplanes++;
1637 
1638     if (nplanes > vp->nlayers)
1639         return -EINVAL;
1640 
1641     return 0;
1642 }
1643 
1644 static bool is_opaque(u16 alpha)
1645 {
1646     return (alpha >> 8) == 0xff;
1647 }
1648 
1649 static void vop2_parse_alpha(struct vop2_alpha_config *alpha_config,
1650                  struct vop2_alpha *alpha)
1651 {
1652     int src_glb_alpha_en = is_opaque(alpha_config->src_glb_alpha_value) ? 0 : 1;
1653     int dst_glb_alpha_en = is_opaque(alpha_config->dst_glb_alpha_value) ? 0 : 1;
1654     int src_color_mode = alpha_config->src_premulti_en ?
1655                 ALPHA_SRC_PRE_MUL : ALPHA_SRC_NO_PRE_MUL;
1656     int dst_color_mode = alpha_config->dst_premulti_en ?
1657                 ALPHA_SRC_PRE_MUL : ALPHA_SRC_NO_PRE_MUL;
1658 
1659     alpha->src_color_ctrl.val = 0;
1660     alpha->dst_color_ctrl.val = 0;
1661     alpha->src_alpha_ctrl.val = 0;
1662     alpha->dst_alpha_ctrl.val = 0;
1663 
1664     if (!alpha_config->src_pixel_alpha_en)
1665         alpha->src_color_ctrl.bits.blend_mode = ALPHA_GLOBAL;
1666     else if (alpha_config->src_pixel_alpha_en && !src_glb_alpha_en)
1667         alpha->src_color_ctrl.bits.blend_mode = ALPHA_PER_PIX;
1668     else
1669         alpha->src_color_ctrl.bits.blend_mode = ALPHA_PER_PIX_GLOBAL;
1670 
1671     alpha->src_color_ctrl.bits.alpha_en = 1;
1672 
1673     if (alpha->src_color_ctrl.bits.blend_mode == ALPHA_GLOBAL) {
1674         alpha->src_color_ctrl.bits.color_mode = src_color_mode;
1675         alpha->src_color_ctrl.bits.factor_mode = SRC_FAC_ALPHA_SRC_GLOBAL;
1676     } else if (alpha->src_color_ctrl.bits.blend_mode == ALPHA_PER_PIX) {
1677         alpha->src_color_ctrl.bits.color_mode = src_color_mode;
1678         alpha->src_color_ctrl.bits.factor_mode = SRC_FAC_ALPHA_ONE;
1679     } else {
1680         alpha->src_color_ctrl.bits.color_mode = ALPHA_SRC_PRE_MUL;
1681         alpha->src_color_ctrl.bits.factor_mode = SRC_FAC_ALPHA_SRC_GLOBAL;
1682     }
1683     alpha->src_color_ctrl.bits.glb_alpha = alpha_config->src_glb_alpha_value >> 8;
1684     alpha->src_color_ctrl.bits.alpha_mode = ALPHA_STRAIGHT;
1685     alpha->src_color_ctrl.bits.alpha_cal_mode = ALPHA_SATURATION;
1686 
1687     alpha->dst_color_ctrl.bits.alpha_mode = ALPHA_STRAIGHT;
1688     alpha->dst_color_ctrl.bits.alpha_cal_mode = ALPHA_SATURATION;
1689     alpha->dst_color_ctrl.bits.blend_mode = ALPHA_GLOBAL;
1690     alpha->dst_color_ctrl.bits.glb_alpha = alpha_config->dst_glb_alpha_value >> 8;
1691     alpha->dst_color_ctrl.bits.color_mode = dst_color_mode;
1692     alpha->dst_color_ctrl.bits.factor_mode = ALPHA_SRC_INVERSE;
1693 
1694     alpha->src_alpha_ctrl.bits.alpha_mode = ALPHA_STRAIGHT;
1695     alpha->src_alpha_ctrl.bits.blend_mode = alpha->src_color_ctrl.bits.blend_mode;
1696     alpha->src_alpha_ctrl.bits.alpha_cal_mode = ALPHA_SATURATION;
1697     alpha->src_alpha_ctrl.bits.factor_mode = ALPHA_ONE;
1698 
1699     alpha->dst_alpha_ctrl.bits.alpha_mode = ALPHA_STRAIGHT;
1700     if (alpha_config->dst_pixel_alpha_en && !dst_glb_alpha_en)
1701         alpha->dst_alpha_ctrl.bits.blend_mode = ALPHA_PER_PIX;
1702     else
1703         alpha->dst_alpha_ctrl.bits.blend_mode = ALPHA_PER_PIX_GLOBAL;
1704     alpha->dst_alpha_ctrl.bits.alpha_cal_mode = ALPHA_NO_SATURATION;
1705     alpha->dst_alpha_ctrl.bits.factor_mode = ALPHA_SRC_INVERSE;
1706 }
1707 
1708 static int vop2_find_start_mixer_id_for_vp(struct vop2 *vop2, u8 port_id)
1709 {
1710     struct vop2_video_port *vp;
1711     int used_layer = 0;
1712     int i;
1713 
1714     for (i = 0; i < port_id; i++) {
1715         vp = &vop2->vps[i];
1716         used_layer += hweight32(vp->win_mask);
1717     }
1718 
1719     return used_layer;
1720 }
1721 
1722 static void vop2_setup_cluster_alpha(struct vop2 *vop2, struct vop2_win *main_win)
1723 {
1724     u32 offset = (main_win->data->phys_id * 0x10);
1725     struct vop2_alpha_config alpha_config;
1726     struct vop2_alpha alpha;
1727     struct drm_plane_state *bottom_win_pstate;
1728     bool src_pixel_alpha_en = false;
1729     u16 src_glb_alpha_val, dst_glb_alpha_val;
1730     bool premulti_en = false;
1731     bool swap = false;
1732 
1733     /* At one win mode, win0 is dst/bottom win, and win1 is a all zero src/top win */
1734     bottom_win_pstate = main_win->base.state;
1735     src_glb_alpha_val = 0;
1736     dst_glb_alpha_val = main_win->base.state->alpha;
1737 
1738     if (!bottom_win_pstate->fb)
1739         return;
1740 
1741     alpha_config.src_premulti_en = premulti_en;
1742     alpha_config.dst_premulti_en = false;
1743     alpha_config.src_pixel_alpha_en = src_pixel_alpha_en;
1744     alpha_config.dst_pixel_alpha_en = true; /* alpha value need transfer to next mix */
1745     alpha_config.src_glb_alpha_value = src_glb_alpha_val;
1746     alpha_config.dst_glb_alpha_value = dst_glb_alpha_val;
1747     vop2_parse_alpha(&alpha_config, &alpha);
1748 
1749     alpha.src_color_ctrl.bits.src_dst_swap = swap;
1750     vop2_writel(vop2, RK3568_CLUSTER0_MIX_SRC_COLOR_CTRL + offset,
1751             alpha.src_color_ctrl.val);
1752     vop2_writel(vop2, RK3568_CLUSTER0_MIX_DST_COLOR_CTRL + offset,
1753             alpha.dst_color_ctrl.val);
1754     vop2_writel(vop2, RK3568_CLUSTER0_MIX_SRC_ALPHA_CTRL + offset,
1755             alpha.src_alpha_ctrl.val);
1756     vop2_writel(vop2, RK3568_CLUSTER0_MIX_DST_ALPHA_CTRL + offset,
1757             alpha.dst_alpha_ctrl.val);
1758 }
1759 
1760 static void vop2_setup_alpha(struct vop2_video_port *vp)
1761 {
1762     struct vop2 *vop2 = vp->vop2;
1763     struct drm_framebuffer *fb;
1764     struct vop2_alpha_config alpha_config;
1765     struct vop2_alpha alpha;
1766     struct drm_plane *plane;
1767     int pixel_alpha_en;
1768     int premulti_en, gpremulti_en = 0;
1769     int mixer_id;
1770     u32 offset;
1771     bool bottom_layer_alpha_en = false;
1772     u32 dst_global_alpha = DRM_BLEND_ALPHA_OPAQUE;
1773 
1774     mixer_id = vop2_find_start_mixer_id_for_vp(vop2, vp->id);
1775     alpha_config.dst_pixel_alpha_en = true; /* alpha value need transfer to next mix */
1776 
1777     drm_atomic_crtc_for_each_plane(plane, &vp->crtc) {
1778         struct vop2_win *win = to_vop2_win(plane);
1779 
1780         if (plane->state->normalized_zpos == 0 &&
1781             !is_opaque(plane->state->alpha) &&
1782             !vop2_cluster_window(win)) {
1783             /*
1784              * If bottom layer have global alpha effect [except cluster layer,
1785              * because cluster have deal with bottom layer global alpha value
1786              * at cluster mix], bottom layer mix need deal with global alpha.
1787              */
1788             bottom_layer_alpha_en = true;
1789             dst_global_alpha = plane->state->alpha;
1790         }
1791     }
1792 
1793     drm_atomic_crtc_for_each_plane(plane, &vp->crtc) {
1794         struct vop2_win *win = to_vop2_win(plane);
1795         int zpos = plane->state->normalized_zpos;
1796 
1797         if (plane->state->pixel_blend_mode == DRM_MODE_BLEND_PREMULTI)
1798             premulti_en = 1;
1799         else
1800             premulti_en = 0;
1801 
1802         plane = &win->base;
1803         fb = plane->state->fb;
1804 
1805         pixel_alpha_en = fb->format->has_alpha;
1806 
1807         alpha_config.src_premulti_en = premulti_en;
1808 
1809         if (bottom_layer_alpha_en && zpos == 1) {
1810             gpremulti_en = premulti_en;
1811             /* Cd = Cs + (1 - As) * Cd * Agd */
1812             alpha_config.dst_premulti_en = false;
1813             alpha_config.src_pixel_alpha_en = pixel_alpha_en;
1814             alpha_config.src_glb_alpha_value = plane->state->alpha;
1815             alpha_config.dst_glb_alpha_value = dst_global_alpha;
1816         } else if (vop2_cluster_window(win)) {
1817             /* Mix output data only have pixel alpha */
1818             alpha_config.dst_premulti_en = true;
1819             alpha_config.src_pixel_alpha_en = true;
1820             alpha_config.src_glb_alpha_value = DRM_BLEND_ALPHA_OPAQUE;
1821             alpha_config.dst_glb_alpha_value = DRM_BLEND_ALPHA_OPAQUE;
1822         } else {
1823             /* Cd = Cs + (1 - As) * Cd */
1824             alpha_config.dst_premulti_en = true;
1825             alpha_config.src_pixel_alpha_en = pixel_alpha_en;
1826             alpha_config.src_glb_alpha_value = plane->state->alpha;
1827             alpha_config.dst_glb_alpha_value = DRM_BLEND_ALPHA_OPAQUE;
1828         }
1829 
1830         vop2_parse_alpha(&alpha_config, &alpha);
1831 
1832         offset = (mixer_id + zpos - 1) * 0x10;
1833         vop2_writel(vop2, RK3568_MIX0_SRC_COLOR_CTRL + offset,
1834                 alpha.src_color_ctrl.val);
1835         vop2_writel(vop2, RK3568_MIX0_DST_COLOR_CTRL + offset,
1836                 alpha.dst_color_ctrl.val);
1837         vop2_writel(vop2, RK3568_MIX0_SRC_ALPHA_CTRL + offset,
1838                 alpha.src_alpha_ctrl.val);
1839         vop2_writel(vop2, RK3568_MIX0_DST_ALPHA_CTRL + offset,
1840                 alpha.dst_alpha_ctrl.val);
1841     }
1842 
1843     if (vp->id == 0) {
1844         if (bottom_layer_alpha_en) {
1845             /* Transfer pixel alpha to hdr mix */
1846             alpha_config.src_premulti_en = gpremulti_en;
1847             alpha_config.dst_premulti_en = true;
1848             alpha_config.src_pixel_alpha_en = true;
1849             alpha_config.src_glb_alpha_value = DRM_BLEND_ALPHA_OPAQUE;
1850             alpha_config.dst_glb_alpha_value = DRM_BLEND_ALPHA_OPAQUE;
1851             vop2_parse_alpha(&alpha_config, &alpha);
1852 
1853             vop2_writel(vop2, RK3568_HDR0_SRC_COLOR_CTRL,
1854                     alpha.src_color_ctrl.val);
1855             vop2_writel(vop2, RK3568_HDR0_DST_COLOR_CTRL,
1856                     alpha.dst_color_ctrl.val);
1857             vop2_writel(vop2, RK3568_HDR0_SRC_ALPHA_CTRL,
1858                     alpha.src_alpha_ctrl.val);
1859             vop2_writel(vop2, RK3568_HDR0_DST_ALPHA_CTRL,
1860                     alpha.dst_alpha_ctrl.val);
1861         } else {
1862             vop2_writel(vop2, RK3568_HDR0_SRC_COLOR_CTRL, 0);
1863         }
1864     }
1865 }
1866 
1867 static void vop2_setup_layer_mixer(struct vop2_video_port *vp)
1868 {
1869     struct vop2 *vop2 = vp->vop2;
1870     struct drm_plane *plane;
1871     u32 layer_sel = 0;
1872     u32 port_sel;
1873     unsigned int nlayer, ofs;
1874     struct drm_display_mode *adjusted_mode;
1875     u16 hsync_len;
1876     u16 hdisplay;
1877     u32 bg_dly;
1878     u32 pre_scan_dly;
1879     int i;
1880     struct vop2_video_port *vp0 = &vop2->vps[0];
1881     struct vop2_video_port *vp1 = &vop2->vps[1];
1882     struct vop2_video_port *vp2 = &vop2->vps[2];
1883 
1884     adjusted_mode = &vp->crtc.state->adjusted_mode;
1885     hsync_len = adjusted_mode->crtc_hsync_end - adjusted_mode->crtc_hsync_start;
1886     hdisplay = adjusted_mode->crtc_hdisplay;
1887 
1888     bg_dly = vp->data->pre_scan_max_dly[3];
1889     vop2_writel(vop2, RK3568_VP_BG_MIX_CTRL(vp->id),
1890             FIELD_PREP(RK3568_VP_BG_MIX_CTRL__BG_DLY, bg_dly));
1891 
1892     pre_scan_dly = ((bg_dly + (hdisplay >> 1) - 1) << 16) | hsync_len;
1893     vop2_vp_write(vp, RK3568_VP_PRE_SCAN_HTIMING, pre_scan_dly);
1894 
1895     vop2_writel(vop2, RK3568_OVL_CTRL, 0);
1896     port_sel = vop2_readl(vop2, RK3568_OVL_PORT_SEL);
1897     port_sel &= RK3568_OVL_PORT_SEL__SEL_PORT;
1898 
1899     if (vp0->nlayers)
1900         port_sel |= FIELD_PREP(RK3568_OVL_PORT_SET__PORT0_MUX,
1901                      vp0->nlayers - 1);
1902     else
1903         port_sel |= FIELD_PREP(RK3568_OVL_PORT_SET__PORT0_MUX, 8);
1904 
1905     if (vp1->nlayers)
1906         port_sel |= FIELD_PREP(RK3568_OVL_PORT_SET__PORT1_MUX,
1907                      (vp0->nlayers + vp1->nlayers - 1));
1908     else
1909         port_sel |= FIELD_PREP(RK3568_OVL_PORT_SET__PORT1_MUX, 8);
1910 
1911     if (vp2->nlayers)
1912         port_sel |= FIELD_PREP(RK3568_OVL_PORT_SET__PORT2_MUX,
1913             (vp2->nlayers + vp1->nlayers + vp0->nlayers - 1));
1914     else
1915         port_sel |= FIELD_PREP(RK3568_OVL_PORT_SET__PORT1_MUX, 8);
1916 
1917     layer_sel = vop2_readl(vop2, RK3568_OVL_LAYER_SEL);
1918 
1919     ofs = 0;
1920     for (i = 0; i < vp->id; i++)
1921         ofs += vop2->vps[i].nlayers;
1922 
1923     nlayer = 0;
1924     drm_atomic_crtc_for_each_plane(plane, &vp->crtc) {
1925         struct vop2_win *win = to_vop2_win(plane);
1926 
1927         switch (win->data->phys_id) {
1928         case ROCKCHIP_VOP2_CLUSTER0:
1929             port_sel &= ~RK3568_OVL_PORT_SEL__CLUSTER0;
1930             port_sel |= FIELD_PREP(RK3568_OVL_PORT_SEL__CLUSTER0, vp->id);
1931             break;
1932         case ROCKCHIP_VOP2_CLUSTER1:
1933             port_sel &= ~RK3568_OVL_PORT_SEL__CLUSTER1;
1934             port_sel |= FIELD_PREP(RK3568_OVL_PORT_SEL__CLUSTER1, vp->id);
1935             break;
1936         case ROCKCHIP_VOP2_ESMART0:
1937             port_sel &= ~RK3568_OVL_PORT_SEL__ESMART0;
1938             port_sel |= FIELD_PREP(RK3568_OVL_PORT_SEL__ESMART0, vp->id);
1939             break;
1940         case ROCKCHIP_VOP2_ESMART1:
1941             port_sel &= ~RK3568_OVL_PORT_SEL__ESMART1;
1942             port_sel |= FIELD_PREP(RK3568_OVL_PORT_SEL__ESMART1, vp->id);
1943             break;
1944         case ROCKCHIP_VOP2_SMART0:
1945             port_sel &= ~RK3568_OVL_PORT_SEL__SMART0;
1946             port_sel |= FIELD_PREP(RK3568_OVL_PORT_SEL__SMART0, vp->id);
1947             break;
1948         case ROCKCHIP_VOP2_SMART1:
1949             port_sel &= ~RK3568_OVL_PORT_SEL__SMART1;
1950             port_sel |= FIELD_PREP(RK3568_OVL_PORT_SEL__SMART1, vp->id);
1951             break;
1952         }
1953 
1954         layer_sel &= ~RK3568_OVL_LAYER_SEL__LAYER(plane->state->normalized_zpos + ofs,
1955                               0x7);
1956         layer_sel |= RK3568_OVL_LAYER_SEL__LAYER(plane->state->normalized_zpos + ofs,
1957                              win->data->layer_sel_id);
1958         nlayer++;
1959     }
1960 
1961     /* configure unused layers to 0x5 (reserved) */
1962     for (; nlayer < vp->nlayers; nlayer++) {
1963         layer_sel &= ~RK3568_OVL_LAYER_SEL__LAYER(nlayer + ofs, 0x7);
1964         layer_sel |= RK3568_OVL_LAYER_SEL__LAYER(nlayer + ofs, 5);
1965     }
1966 
1967     vop2_writel(vop2, RK3568_OVL_LAYER_SEL, layer_sel);
1968     vop2_writel(vop2, RK3568_OVL_PORT_SEL, port_sel);
1969     vop2_writel(vop2, RK3568_OVL_CTRL, RK3568_OVL_CTRL__LAYERSEL_REGDONE_IMD);
1970 }
1971 
1972 static void vop2_setup_dly_for_windows(struct vop2 *vop2)
1973 {
1974     struct vop2_win *win;
1975     int i = 0;
1976     u32 cdly = 0, sdly = 0;
1977 
1978     for (i = 0; i < vop2->data->win_size; i++) {
1979         u32 dly;
1980 
1981         win = &vop2->win[i];
1982         dly = win->delay;
1983 
1984         switch (win->data->phys_id) {
1985         case ROCKCHIP_VOP2_CLUSTER0:
1986             cdly |= FIELD_PREP(RK3568_CLUSTER_DLY_NUM__CLUSTER0_0, dly);
1987             cdly |= FIELD_PREP(RK3568_CLUSTER_DLY_NUM__CLUSTER0_1, dly);
1988             break;
1989         case ROCKCHIP_VOP2_CLUSTER1:
1990             cdly |= FIELD_PREP(RK3568_CLUSTER_DLY_NUM__CLUSTER1_0, dly);
1991             cdly |= FIELD_PREP(RK3568_CLUSTER_DLY_NUM__CLUSTER1_1, dly);
1992             break;
1993         case ROCKCHIP_VOP2_ESMART0:
1994             sdly |= FIELD_PREP(RK3568_SMART_DLY_NUM__ESMART0, dly);
1995             break;
1996         case ROCKCHIP_VOP2_ESMART1:
1997             sdly |= FIELD_PREP(RK3568_SMART_DLY_NUM__ESMART1, dly);
1998             break;
1999         case ROCKCHIP_VOP2_SMART0:
2000             sdly |= FIELD_PREP(RK3568_SMART_DLY_NUM__SMART0, dly);
2001             break;
2002         case ROCKCHIP_VOP2_SMART1:
2003             sdly |= FIELD_PREP(RK3568_SMART_DLY_NUM__SMART1, dly);
2004             break;
2005         }
2006     }
2007 
2008     vop2_writel(vop2, RK3568_CLUSTER_DLY_NUM, cdly);
2009     vop2_writel(vop2, RK3568_SMART_DLY_NUM, sdly);
2010 }
2011 
2012 static void vop2_crtc_atomic_begin(struct drm_crtc *crtc,
2013                    struct drm_atomic_state *state)
2014 {
2015     struct vop2_video_port *vp = to_vop2_video_port(crtc);
2016     struct vop2 *vop2 = vp->vop2;
2017     struct drm_plane *plane;
2018 
2019     vp->win_mask = 0;
2020 
2021     drm_atomic_crtc_for_each_plane(plane, crtc) {
2022         struct vop2_win *win = to_vop2_win(plane);
2023 
2024         win->delay = win->data->dly[VOP2_DLY_MODE_DEFAULT];
2025 
2026         vp->win_mask |= BIT(win->data->phys_id);
2027 
2028         if (vop2_cluster_window(win))
2029             vop2_setup_cluster_alpha(vop2, win);
2030     }
2031 
2032     if (!vp->win_mask)
2033         return;
2034 
2035     vop2_setup_layer_mixer(vp);
2036     vop2_setup_alpha(vp);
2037     vop2_setup_dly_for_windows(vop2);
2038 }
2039 
2040 static void vop2_crtc_atomic_flush(struct drm_crtc *crtc,
2041                    struct drm_atomic_state *state)
2042 {
2043     struct vop2_video_port *vp = to_vop2_video_port(crtc);
2044 
2045     vop2_post_config(crtc);
2046 
2047     vop2_cfg_done(vp);
2048 
2049     spin_lock_irq(&crtc->dev->event_lock);
2050 
2051     if (crtc->state->event) {
2052         WARN_ON(drm_crtc_vblank_get(crtc));
2053         vp->event = crtc->state->event;
2054         crtc->state->event = NULL;
2055     }
2056 
2057     spin_unlock_irq(&crtc->dev->event_lock);
2058 }
2059 
2060 static const struct drm_crtc_helper_funcs vop2_crtc_helper_funcs = {
2061     .mode_fixup = vop2_crtc_mode_fixup,
2062     .atomic_check = vop2_crtc_atomic_check,
2063     .atomic_begin = vop2_crtc_atomic_begin,
2064     .atomic_flush = vop2_crtc_atomic_flush,
2065     .atomic_enable = vop2_crtc_atomic_enable,
2066     .atomic_disable = vop2_crtc_atomic_disable,
2067 };
2068 
2069 static void vop2_crtc_reset(struct drm_crtc *crtc)
2070 {
2071     struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state);
2072 
2073     if (crtc->state) {
2074         __drm_atomic_helper_crtc_destroy_state(crtc->state);
2075         kfree(vcstate);
2076     }
2077 
2078     vcstate = kzalloc(sizeof(*vcstate), GFP_KERNEL);
2079     if (!vcstate)
2080         return;
2081 
2082     crtc->state = &vcstate->base;
2083     crtc->state->crtc = crtc;
2084 }
2085 
2086 static struct drm_crtc_state *vop2_crtc_duplicate_state(struct drm_crtc *crtc)
2087 {
2088     struct rockchip_crtc_state *vcstate, *old_vcstate;
2089 
2090     old_vcstate = to_rockchip_crtc_state(crtc->state);
2091 
2092     vcstate = kmemdup(old_vcstate, sizeof(*old_vcstate), GFP_KERNEL);
2093     if (!vcstate)
2094         return NULL;
2095 
2096     __drm_atomic_helper_crtc_duplicate_state(crtc, &vcstate->base);
2097 
2098     return &vcstate->base;
2099 }
2100 
2101 static void vop2_crtc_destroy_state(struct drm_crtc *crtc,
2102                     struct drm_crtc_state *state)
2103 {
2104     struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(state);
2105 
2106     __drm_atomic_helper_crtc_destroy_state(&vcstate->base);
2107     kfree(vcstate);
2108 }
2109 
2110 static const struct drm_crtc_funcs vop2_crtc_funcs = {
2111     .set_config = drm_atomic_helper_set_config,
2112     .page_flip = drm_atomic_helper_page_flip,
2113     .destroy = drm_crtc_cleanup,
2114     .reset = vop2_crtc_reset,
2115     .atomic_duplicate_state = vop2_crtc_duplicate_state,
2116     .atomic_destroy_state = vop2_crtc_destroy_state,
2117     .enable_vblank = vop2_crtc_enable_vblank,
2118     .disable_vblank = vop2_crtc_disable_vblank,
2119 };
2120 
2121 static irqreturn_t vop2_isr(int irq, void *data)
2122 {
2123     struct vop2 *vop2 = data;
2124     const struct vop2_data *vop2_data = vop2->data;
2125     u32 axi_irqs[VOP2_SYS_AXI_BUS_NUM];
2126     int ret = IRQ_NONE;
2127     int i;
2128 
2129     /*
2130      * The irq is shared with the iommu. If the runtime-pm state of the
2131      * vop2-device is disabled the irq has to be targeted at the iommu.
2132      */
2133     if (!pm_runtime_get_if_in_use(vop2->dev))
2134         return IRQ_NONE;
2135 
2136     for (i = 0; i < vop2_data->nr_vps; i++) {
2137         struct vop2_video_port *vp = &vop2->vps[i];
2138         struct drm_crtc *crtc = &vp->crtc;
2139         u32 irqs;
2140 
2141         irqs = vop2_readl(vop2, RK3568_VP_INT_STATUS(vp->id));
2142         vop2_writel(vop2, RK3568_VP_INT_CLR(vp->id), irqs << 16 | irqs);
2143 
2144         if (irqs & VP_INT_DSP_HOLD_VALID) {
2145             complete(&vp->dsp_hold_completion);
2146             ret = IRQ_HANDLED;
2147         }
2148 
2149         if (irqs & VP_INT_FS_FIELD) {
2150             drm_crtc_handle_vblank(crtc);
2151             spin_lock(&crtc->dev->event_lock);
2152             if (vp->event) {
2153                 u32 val = vop2_readl(vop2, RK3568_REG_CFG_DONE);
2154 
2155                 if (!(val & BIT(vp->id))) {
2156                     drm_crtc_send_vblank_event(crtc, vp->event);
2157                     vp->event = NULL;
2158                     drm_crtc_vblank_put(crtc);
2159                 }
2160             }
2161             spin_unlock(&crtc->dev->event_lock);
2162 
2163             ret = IRQ_HANDLED;
2164         }
2165 
2166         if (irqs & VP_INT_POST_BUF_EMPTY) {
2167             drm_err_ratelimited(vop2->drm,
2168                         "POST_BUF_EMPTY irq err at vp%d\n",
2169                         vp->id);
2170             ret = IRQ_HANDLED;
2171         }
2172     }
2173 
2174     axi_irqs[0] = vop2_readl(vop2, RK3568_SYS0_INT_STATUS);
2175     vop2_writel(vop2, RK3568_SYS0_INT_CLR, axi_irqs[0] << 16 | axi_irqs[0]);
2176     axi_irqs[1] = vop2_readl(vop2, RK3568_SYS1_INT_STATUS);
2177     vop2_writel(vop2, RK3568_SYS1_INT_CLR, axi_irqs[1] << 16 | axi_irqs[1]);
2178 
2179     for (i = 0; i < ARRAY_SIZE(axi_irqs); i++) {
2180         if (axi_irqs[i] & VOP2_INT_BUS_ERRPR) {
2181             drm_err_ratelimited(vop2->drm, "BUS_ERROR irq err\n");
2182             ret = IRQ_HANDLED;
2183         }
2184     }
2185 
2186     pm_runtime_put(vop2->dev);
2187 
2188     return ret;
2189 }
2190 
2191 static int vop2_plane_init(struct vop2 *vop2, struct vop2_win *win,
2192                unsigned long possible_crtcs)
2193 {
2194     const struct vop2_win_data *win_data = win->data;
2195     unsigned int blend_caps = BIT(DRM_MODE_BLEND_PIXEL_NONE) |
2196                   BIT(DRM_MODE_BLEND_PREMULTI) |
2197                   BIT(DRM_MODE_BLEND_COVERAGE);
2198     int ret;
2199 
2200     ret = drm_universal_plane_init(vop2->drm, &win->base, possible_crtcs,
2201                        &vop2_plane_funcs, win_data->formats,
2202                        win_data->nformats,
2203                        win_data->format_modifiers,
2204                        win->type, win_data->name);
2205     if (ret) {
2206         drm_err(vop2->drm, "failed to initialize plane %d\n", ret);
2207         return ret;
2208     }
2209 
2210     drm_plane_helper_add(&win->base, &vop2_plane_helper_funcs);
2211 
2212     if (win->data->supported_rotations)
2213         drm_plane_create_rotation_property(&win->base, DRM_MODE_ROTATE_0,
2214                            DRM_MODE_ROTATE_0 |
2215                            win->data->supported_rotations);
2216     drm_plane_create_alpha_property(&win->base);
2217     drm_plane_create_blend_mode_property(&win->base, blend_caps);
2218     drm_plane_create_zpos_property(&win->base, win->win_id, 0,
2219                        vop2->registered_num_wins - 1);
2220 
2221     return 0;
2222 }
2223 
2224 static struct vop2_video_port *find_vp_without_primary(struct vop2 *vop2)
2225 {
2226     int i;
2227 
2228     for (i = 0; i < vop2->data->nr_vps; i++) {
2229         struct vop2_video_port *vp = &vop2->vps[i];
2230 
2231         if (!vp->crtc.port)
2232             continue;
2233         if (vp->primary_plane)
2234             continue;
2235 
2236         return vp;
2237     }
2238 
2239     return NULL;
2240 }
2241 
2242 #define NR_LAYERS 6
2243 
2244 static int vop2_create_crtc(struct vop2 *vop2)
2245 {
2246     const struct vop2_data *vop2_data = vop2->data;
2247     struct drm_device *drm = vop2->drm;
2248     struct device *dev = vop2->dev;
2249     struct drm_plane *plane;
2250     struct device_node *port;
2251     struct vop2_video_port *vp;
2252     int i, nvp, nvps = 0;
2253     int ret;
2254 
2255     for (i = 0; i < vop2_data->nr_vps; i++) {
2256         const struct vop2_video_port_data *vp_data;
2257         struct device_node *np;
2258         char dclk_name[9];
2259 
2260         vp_data = &vop2_data->vp[i];
2261         vp = &vop2->vps[i];
2262         vp->vop2 = vop2;
2263         vp->id = vp_data->id;
2264         vp->regs = vp_data->regs;
2265         vp->data = vp_data;
2266 
2267         snprintf(dclk_name, sizeof(dclk_name), "dclk_vp%d", vp->id);
2268         vp->dclk = devm_clk_get(vop2->dev, dclk_name);
2269         if (IS_ERR(vp->dclk)) {
2270             drm_err(vop2->drm, "failed to get %s\n", dclk_name);
2271             return PTR_ERR(vp->dclk);
2272         }
2273 
2274         np = of_graph_get_remote_node(dev->of_node, i, -1);
2275         if (!np) {
2276             drm_dbg(vop2->drm, "%s: No remote for vp%d\n", __func__, i);
2277             continue;
2278         }
2279         of_node_put(np);
2280 
2281         port = of_graph_get_port_by_id(dev->of_node, i);
2282         if (!port) {
2283             drm_err(vop2->drm, "no port node found for video_port%d\n", i);
2284             return -ENOENT;
2285         }
2286 
2287         vp->crtc.port = port;
2288         nvps++;
2289     }
2290 
2291     nvp = 0;
2292     for (i = 0; i < vop2->registered_num_wins; i++) {
2293         struct vop2_win *win = &vop2->win[i];
2294         u32 possible_crtcs;
2295 
2296         if (vop2->data->soc_id == 3566) {
2297             /*
2298              * On RK3566 these windows don't have an independent
2299              * framebuffer. They share the framebuffer with smart0,
2300              * esmart0 and cluster0 respectively.
2301              */
2302             switch (win->data->phys_id) {
2303             case ROCKCHIP_VOP2_SMART1:
2304             case ROCKCHIP_VOP2_ESMART1:
2305             case ROCKCHIP_VOP2_CLUSTER1:
2306                 continue;
2307             }
2308         }
2309 
2310         if (win->type == DRM_PLANE_TYPE_PRIMARY) {
2311             vp = find_vp_without_primary(vop2);
2312             if (vp) {
2313                 possible_crtcs = BIT(nvp);
2314                 vp->primary_plane = win;
2315                 nvp++;
2316             } else {
2317                 /* change the unused primary window to overlay window */
2318                 win->type = DRM_PLANE_TYPE_OVERLAY;
2319             }
2320         }
2321 
2322         if (win->type == DRM_PLANE_TYPE_OVERLAY)
2323             possible_crtcs = (1 << nvps) - 1;
2324 
2325         ret = vop2_plane_init(vop2, win, possible_crtcs);
2326         if (ret) {
2327             drm_err(vop2->drm, "failed to init plane %s: %d\n",
2328                 win->data->name, ret);
2329             return ret;
2330         }
2331     }
2332 
2333     for (i = 0; i < vop2_data->nr_vps; i++) {
2334         vp = &vop2->vps[i];
2335 
2336         if (!vp->crtc.port)
2337             continue;
2338 
2339         plane = &vp->primary_plane->base;
2340 
2341         ret = drm_crtc_init_with_planes(drm, &vp->crtc, plane, NULL,
2342                         &vop2_crtc_funcs,
2343                         "video_port%d", vp->id);
2344         if (ret) {
2345             drm_err(vop2->drm, "crtc init for video_port%d failed\n", i);
2346             return ret;
2347         }
2348 
2349         drm_crtc_helper_add(&vp->crtc, &vop2_crtc_helper_funcs);
2350 
2351         init_completion(&vp->dsp_hold_completion);
2352     }
2353 
2354     /*
2355      * On the VOP2 it's very hard to change the number of layers on a VP
2356      * during runtime, so we distribute the layers equally over the used
2357      * VPs
2358      */
2359     for (i = 0; i < vop2->data->nr_vps; i++) {
2360         struct vop2_video_port *vp = &vop2->vps[i];
2361 
2362         if (vp->crtc.port)
2363             vp->nlayers = NR_LAYERS / nvps;
2364     }
2365 
2366     return 0;
2367 }
2368 
2369 static void vop2_destroy_crtc(struct drm_crtc *crtc)
2370 {
2371     of_node_put(crtc->port);
2372 
2373     /*
2374      * Destroy CRTC after vop2_plane_destroy() since vop2_disable_plane()
2375      * references the CRTC.
2376      */
2377     drm_crtc_cleanup(crtc);
2378 }
2379 
2380 static struct reg_field vop2_cluster_regs[VOP2_WIN_MAX_REG] = {
2381     [VOP2_WIN_ENABLE] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 0, 0),
2382     [VOP2_WIN_FORMAT] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 1, 5),
2383     [VOP2_WIN_RB_SWAP] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 14, 14),
2384     [VOP2_WIN_DITHER_UP] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 18, 18),
2385     [VOP2_WIN_ACT_INFO] = REG_FIELD(RK3568_CLUSTER_WIN_ACT_INFO, 0, 31),
2386     [VOP2_WIN_DSP_INFO] = REG_FIELD(RK3568_CLUSTER_WIN_DSP_INFO, 0, 31),
2387     [VOP2_WIN_DSP_ST] = REG_FIELD(RK3568_CLUSTER_WIN_DSP_ST, 0, 31),
2388     [VOP2_WIN_YRGB_MST] = REG_FIELD(RK3568_CLUSTER_WIN_YRGB_MST, 0, 31),
2389     [VOP2_WIN_UV_MST] = REG_FIELD(RK3568_CLUSTER_WIN_CBR_MST, 0, 31),
2390     [VOP2_WIN_YUV_CLIP] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 19, 19),
2391     [VOP2_WIN_YRGB_VIR] = REG_FIELD(RK3568_CLUSTER_WIN_VIR, 0, 15),
2392     [VOP2_WIN_UV_VIR] = REG_FIELD(RK3568_CLUSTER_WIN_VIR, 16, 31),
2393     [VOP2_WIN_Y2R_EN] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 8, 8),
2394     [VOP2_WIN_R2Y_EN] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 9, 9),
2395     [VOP2_WIN_CSC_MODE] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 10, 11),
2396 
2397     /* Scale */
2398     [VOP2_WIN_SCALE_YRGB_X] = REG_FIELD(RK3568_CLUSTER_WIN_SCL_FACTOR_YRGB, 0, 15),
2399     [VOP2_WIN_SCALE_YRGB_Y] = REG_FIELD(RK3568_CLUSTER_WIN_SCL_FACTOR_YRGB, 16, 31),
2400     [VOP2_WIN_YRGB_VER_SCL_MODE] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL1, 14, 15),
2401     [VOP2_WIN_YRGB_HOR_SCL_MODE] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL1, 12, 13),
2402     [VOP2_WIN_BIC_COE_SEL] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL1, 2, 3),
2403     [VOP2_WIN_VSD_YRGB_GT2] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL1, 28, 28),
2404     [VOP2_WIN_VSD_YRGB_GT4] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL1, 29, 29),
2405 
2406     /* cluster regs */
2407     [VOP2_WIN_AFBC_ENABLE] = REG_FIELD(RK3568_CLUSTER_CTRL, 1, 1),
2408     [VOP2_WIN_CLUSTER_ENABLE] = REG_FIELD(RK3568_CLUSTER_CTRL, 0, 0),
2409     [VOP2_WIN_CLUSTER_LB_MODE] = REG_FIELD(RK3568_CLUSTER_CTRL, 4, 7),
2410 
2411     /* afbc regs */
2412     [VOP2_WIN_AFBC_FORMAT] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_CTRL, 2, 6),
2413     [VOP2_WIN_AFBC_RB_SWAP] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_CTRL, 9, 9),
2414     [VOP2_WIN_AFBC_UV_SWAP] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_CTRL, 10, 10),
2415     [VOP2_WIN_AFBC_AUTO_GATING_EN] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_OUTPUT_CTRL, 4, 4),
2416     [VOP2_WIN_AFBC_HALF_BLOCK_EN] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_CTRL, 7, 7),
2417     [VOP2_WIN_AFBC_BLOCK_SPLIT_EN] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_CTRL, 8, 8),
2418     [VOP2_WIN_AFBC_HDR_PTR] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_HDR_PTR, 0, 31),
2419     [VOP2_WIN_AFBC_PIC_SIZE] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_PIC_SIZE, 0, 31),
2420     [VOP2_WIN_AFBC_PIC_VIR_WIDTH] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_VIR_WIDTH, 0, 15),
2421     [VOP2_WIN_AFBC_TILE_NUM] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_VIR_WIDTH, 16, 31),
2422     [VOP2_WIN_AFBC_PIC_OFFSET] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_PIC_OFFSET, 0, 31),
2423     [VOP2_WIN_AFBC_DSP_OFFSET] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_DSP_OFFSET, 0, 31),
2424     [VOP2_WIN_AFBC_TRANSFORM_OFFSET] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_TRANSFORM_OFFSET, 0, 31),
2425     [VOP2_WIN_AFBC_ROTATE_90] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_ROTATE_MODE, 0, 0),
2426     [VOP2_WIN_AFBC_ROTATE_270] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_ROTATE_MODE, 1, 1),
2427     [VOP2_WIN_XMIRROR] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_ROTATE_MODE, 2, 2),
2428     [VOP2_WIN_YMIRROR] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_ROTATE_MODE, 3, 3),
2429     [VOP2_WIN_UV_SWAP] = { .reg = 0xffffffff },
2430     [VOP2_WIN_COLOR_KEY] = { .reg = 0xffffffff },
2431     [VOP2_WIN_COLOR_KEY_EN] = { .reg = 0xffffffff },
2432     [VOP2_WIN_SCALE_CBCR_X] = { .reg = 0xffffffff },
2433     [VOP2_WIN_SCALE_CBCR_Y] = { .reg = 0xffffffff },
2434     [VOP2_WIN_YRGB_HSCL_FILTER_MODE] = { .reg = 0xffffffff },
2435     [VOP2_WIN_YRGB_VSCL_FILTER_MODE] = { .reg = 0xffffffff },
2436     [VOP2_WIN_CBCR_VER_SCL_MODE] = { .reg = 0xffffffff },
2437     [VOP2_WIN_CBCR_HSCL_FILTER_MODE] = { .reg = 0xffffffff },
2438     [VOP2_WIN_CBCR_HOR_SCL_MODE] = { .reg = 0xffffffff },
2439     [VOP2_WIN_CBCR_VSCL_FILTER_MODE] = { .reg = 0xffffffff },
2440     [VOP2_WIN_VSD_CBCR_GT2] = { .reg = 0xffffffff },
2441     [VOP2_WIN_VSD_CBCR_GT4] = { .reg = 0xffffffff },
2442 };
2443 
2444 static int vop2_cluster_init(struct vop2_win *win)
2445 {
2446     struct vop2 *vop2 = win->vop2;
2447     struct reg_field *cluster_regs;
2448     int ret, i;
2449 
2450     cluster_regs = kmemdup(vop2_cluster_regs, sizeof(vop2_cluster_regs),
2451                    GFP_KERNEL);
2452     if (!cluster_regs)
2453         return -ENOMEM;
2454 
2455     for (i = 0; i < ARRAY_SIZE(vop2_cluster_regs); i++)
2456         if (cluster_regs[i].reg != 0xffffffff)
2457             cluster_regs[i].reg += win->offset;
2458 
2459     ret = devm_regmap_field_bulk_alloc(vop2->dev, vop2->map, win->reg,
2460                        cluster_regs,
2461                        ARRAY_SIZE(vop2_cluster_regs));
2462 
2463     kfree(cluster_regs);
2464 
2465     return ret;
2466 };
2467 
2468 static struct reg_field vop2_esmart_regs[VOP2_WIN_MAX_REG] = {
2469     [VOP2_WIN_ENABLE] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 0, 0),
2470     [VOP2_WIN_FORMAT] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 1, 5),
2471     [VOP2_WIN_DITHER_UP] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 12, 12),
2472     [VOP2_WIN_RB_SWAP] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 14, 14),
2473     [VOP2_WIN_UV_SWAP] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 16, 16),
2474     [VOP2_WIN_ACT_INFO] = REG_FIELD(RK3568_SMART_REGION0_ACT_INFO, 0, 31),
2475     [VOP2_WIN_DSP_INFO] = REG_FIELD(RK3568_SMART_REGION0_DSP_INFO, 0, 31),
2476     [VOP2_WIN_DSP_ST] = REG_FIELD(RK3568_SMART_REGION0_DSP_ST, 0, 28),
2477     [VOP2_WIN_YRGB_MST] = REG_FIELD(RK3568_SMART_REGION0_YRGB_MST, 0, 31),
2478     [VOP2_WIN_UV_MST] = REG_FIELD(RK3568_SMART_REGION0_CBR_MST, 0, 31),
2479     [VOP2_WIN_YUV_CLIP] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 17, 17),
2480     [VOP2_WIN_YRGB_VIR] = REG_FIELD(RK3568_SMART_REGION0_VIR, 0, 15),
2481     [VOP2_WIN_UV_VIR] = REG_FIELD(RK3568_SMART_REGION0_VIR, 16, 31),
2482     [VOP2_WIN_Y2R_EN] = REG_FIELD(RK3568_SMART_CTRL0, 0, 0),
2483     [VOP2_WIN_R2Y_EN] = REG_FIELD(RK3568_SMART_CTRL0, 1, 1),
2484     [VOP2_WIN_CSC_MODE] = REG_FIELD(RK3568_SMART_CTRL0, 2, 3),
2485     [VOP2_WIN_YMIRROR] = REG_FIELD(RK3568_SMART_CTRL1, 31, 31),
2486     [VOP2_WIN_COLOR_KEY] = REG_FIELD(RK3568_SMART_COLOR_KEY_CTRL, 0, 29),
2487     [VOP2_WIN_COLOR_KEY_EN] = REG_FIELD(RK3568_SMART_COLOR_KEY_CTRL, 31, 31),
2488 
2489     /* Scale */
2490     [VOP2_WIN_SCALE_YRGB_X] = REG_FIELD(RK3568_SMART_REGION0_SCL_FACTOR_YRGB, 0, 15),
2491     [VOP2_WIN_SCALE_YRGB_Y] = REG_FIELD(RK3568_SMART_REGION0_SCL_FACTOR_YRGB, 16, 31),
2492     [VOP2_WIN_SCALE_CBCR_X] = REG_FIELD(RK3568_SMART_REGION0_SCL_FACTOR_CBR, 0, 15),
2493     [VOP2_WIN_SCALE_CBCR_Y] = REG_FIELD(RK3568_SMART_REGION0_SCL_FACTOR_CBR, 16, 31),
2494     [VOP2_WIN_YRGB_HOR_SCL_MODE] = REG_FIELD(RK3568_SMART_REGION0_SCL_CTRL, 0, 1),
2495     [VOP2_WIN_YRGB_HSCL_FILTER_MODE] = REG_FIELD(RK3568_SMART_REGION0_SCL_CTRL, 2, 3),
2496     [VOP2_WIN_YRGB_VER_SCL_MODE] = REG_FIELD(RK3568_SMART_REGION0_SCL_CTRL, 4, 5),
2497     [VOP2_WIN_YRGB_VSCL_FILTER_MODE] = REG_FIELD(RK3568_SMART_REGION0_SCL_CTRL, 6, 7),
2498     [VOP2_WIN_CBCR_HOR_SCL_MODE] = REG_FIELD(RK3568_SMART_REGION0_SCL_CTRL, 8, 9),
2499     [VOP2_WIN_CBCR_HSCL_FILTER_MODE] = REG_FIELD(RK3568_SMART_REGION0_SCL_CTRL, 10, 11),
2500     [VOP2_WIN_CBCR_VER_SCL_MODE] = REG_FIELD(RK3568_SMART_REGION0_SCL_CTRL, 12, 13),
2501     [VOP2_WIN_CBCR_VSCL_FILTER_MODE] = REG_FIELD(RK3568_SMART_REGION0_SCL_CTRL, 14, 15),
2502     [VOP2_WIN_BIC_COE_SEL] = REG_FIELD(RK3568_SMART_REGION0_SCL_CTRL, 16, 17),
2503     [VOP2_WIN_VSD_YRGB_GT2] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 8, 8),
2504     [VOP2_WIN_VSD_YRGB_GT4] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 9, 9),
2505     [VOP2_WIN_VSD_CBCR_GT2] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 10, 10),
2506     [VOP2_WIN_VSD_CBCR_GT4] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 11, 11),
2507     [VOP2_WIN_XMIRROR] = { .reg = 0xffffffff },
2508     [VOP2_WIN_CLUSTER_ENABLE] = { .reg = 0xffffffff },
2509     [VOP2_WIN_AFBC_ENABLE] = { .reg = 0xffffffff },
2510     [VOP2_WIN_CLUSTER_LB_MODE] = { .reg = 0xffffffff },
2511     [VOP2_WIN_AFBC_FORMAT] = { .reg = 0xffffffff },
2512     [VOP2_WIN_AFBC_RB_SWAP] = { .reg = 0xffffffff },
2513     [VOP2_WIN_AFBC_UV_SWAP] = { .reg = 0xffffffff },
2514     [VOP2_WIN_AFBC_AUTO_GATING_EN] = { .reg = 0xffffffff },
2515     [VOP2_WIN_AFBC_BLOCK_SPLIT_EN] = { .reg = 0xffffffff },
2516     [VOP2_WIN_AFBC_PIC_VIR_WIDTH] = { .reg = 0xffffffff },
2517     [VOP2_WIN_AFBC_TILE_NUM] = { .reg = 0xffffffff },
2518     [VOP2_WIN_AFBC_PIC_OFFSET] = { .reg = 0xffffffff },
2519     [VOP2_WIN_AFBC_PIC_SIZE] = { .reg = 0xffffffff },
2520     [VOP2_WIN_AFBC_DSP_OFFSET] = { .reg = 0xffffffff },
2521     [VOP2_WIN_AFBC_TRANSFORM_OFFSET] = { .reg = 0xffffffff },
2522     [VOP2_WIN_AFBC_HDR_PTR] = { .reg = 0xffffffff },
2523     [VOP2_WIN_AFBC_HALF_BLOCK_EN] = { .reg = 0xffffffff },
2524     [VOP2_WIN_AFBC_ROTATE_270] = { .reg = 0xffffffff },
2525     [VOP2_WIN_AFBC_ROTATE_90] = { .reg = 0xffffffff },
2526 };
2527 
2528 static int vop2_esmart_init(struct vop2_win *win)
2529 {
2530     struct vop2 *vop2 = win->vop2;
2531     struct reg_field *esmart_regs;
2532     int ret, i;
2533 
2534     esmart_regs = kmemdup(vop2_esmart_regs, sizeof(vop2_esmart_regs),
2535                   GFP_KERNEL);
2536     if (!esmart_regs)
2537         return -ENOMEM;
2538 
2539     for (i = 0; i < ARRAY_SIZE(vop2_esmart_regs); i++)
2540         if (esmart_regs[i].reg != 0xffffffff)
2541             esmart_regs[i].reg += win->offset;
2542 
2543     ret = devm_regmap_field_bulk_alloc(vop2->dev, vop2->map, win->reg,
2544                        esmart_regs,
2545                        ARRAY_SIZE(vop2_esmart_regs));
2546 
2547     kfree(esmart_regs);
2548 
2549     return ret;
2550 };
2551 
2552 static int vop2_win_init(struct vop2 *vop2)
2553 {
2554     const struct vop2_data *vop2_data = vop2->data;
2555     struct vop2_win *win;
2556     int i, ret;
2557 
2558     for (i = 0; i < vop2_data->win_size; i++) {
2559         const struct vop2_win_data *win_data = &vop2_data->win[i];
2560 
2561         win = &vop2->win[i];
2562         win->data = win_data;
2563         win->type = win_data->type;
2564         win->offset = win_data->base;
2565         win->win_id = i;
2566         win->vop2 = vop2;
2567         if (vop2_cluster_window(win))
2568             ret = vop2_cluster_init(win);
2569         else
2570             ret = vop2_esmart_init(win);
2571         if (ret)
2572             return ret;
2573     }
2574 
2575     vop2->registered_num_wins = vop2_data->win_size;
2576 
2577     return 0;
2578 }
2579 
2580 /*
2581  * The window registers are only updated when config done is written.
2582  * Until that they read back the old value. As we read-modify-write
2583  * these registers mark them as non-volatile. This makes sure we read
2584  * the new values from the regmap register cache.
2585  */
2586 static const struct regmap_range vop2_nonvolatile_range[] = {
2587     regmap_reg_range(0x1000, 0x23ff),
2588 };
2589 
2590 static const struct regmap_access_table vop2_volatile_table = {
2591     .no_ranges = vop2_nonvolatile_range,
2592     .n_no_ranges = ARRAY_SIZE(vop2_nonvolatile_range),
2593 };
2594 
2595 static const struct regmap_config vop2_regmap_config = {
2596     .reg_bits   = 32,
2597     .val_bits   = 32,
2598     .reg_stride = 4,
2599     .max_register   = 0x3000,
2600     .name       = "vop2",
2601     .volatile_table = &vop2_volatile_table,
2602     .cache_type = REGCACHE_RBTREE,
2603 };
2604 
2605 static int vop2_bind(struct device *dev, struct device *master, void *data)
2606 {
2607     struct platform_device *pdev = to_platform_device(dev);
2608     const struct vop2_data *vop2_data;
2609     struct drm_device *drm = data;
2610     struct vop2 *vop2;
2611     struct resource *res;
2612     size_t alloc_size;
2613     int ret;
2614 
2615     vop2_data = of_device_get_match_data(dev);
2616     if (!vop2_data)
2617         return -ENODEV;
2618 
2619     /* Allocate vop2 struct and its vop2_win array */
2620     alloc_size = sizeof(*vop2) + sizeof(*vop2->win) * vop2_data->win_size;
2621     vop2 = devm_kzalloc(dev, alloc_size, GFP_KERNEL);
2622     if (!vop2)
2623         return -ENOMEM;
2624 
2625     vop2->dev = dev;
2626     vop2->data = vop2_data;
2627     vop2->drm = drm;
2628 
2629     dev_set_drvdata(dev, vop2);
2630 
2631     res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "vop");
2632     if (!res) {
2633         drm_err(vop2->drm, "failed to get vop2 register byname\n");
2634         return -EINVAL;
2635     }
2636 
2637     vop2->regs = devm_ioremap_resource(dev, res);
2638     if (IS_ERR(vop2->regs))
2639         return PTR_ERR(vop2->regs);
2640     vop2->len = resource_size(res);
2641 
2642     vop2->map = devm_regmap_init_mmio(dev, vop2->regs, &vop2_regmap_config);
2643 
2644     ret = vop2_win_init(vop2);
2645     if (ret)
2646         return ret;
2647 
2648     res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "gamma-lut");
2649     if (res) {
2650         vop2->lut_regs = devm_ioremap_resource(dev, res);
2651         if (IS_ERR(vop2->lut_regs))
2652             return PTR_ERR(vop2->lut_regs);
2653     }
2654 
2655     vop2->grf = syscon_regmap_lookup_by_phandle(dev->of_node, "rockchip,grf");
2656 
2657     vop2->hclk = devm_clk_get(vop2->dev, "hclk");
2658     if (IS_ERR(vop2->hclk)) {
2659         drm_err(vop2->drm, "failed to get hclk source\n");
2660         return PTR_ERR(vop2->hclk);
2661     }
2662 
2663     vop2->aclk = devm_clk_get(vop2->dev, "aclk");
2664     if (IS_ERR(vop2->aclk)) {
2665         drm_err(vop2->drm, "failed to get aclk source\n");
2666         return PTR_ERR(vop2->aclk);
2667     }
2668 
2669     vop2->irq = platform_get_irq(pdev, 0);
2670     if (vop2->irq < 0) {
2671         drm_err(vop2->drm, "cannot find irq for vop2\n");
2672         return vop2->irq;
2673     }
2674 
2675     mutex_init(&vop2->vop2_lock);
2676 
2677     ret = devm_request_irq(dev, vop2->irq, vop2_isr, IRQF_SHARED, dev_name(dev), vop2);
2678     if (ret)
2679         return ret;
2680 
2681     ret = vop2_create_crtc(vop2);
2682     if (ret)
2683         return ret;
2684 
2685     rockchip_drm_dma_init_device(vop2->drm, vop2->dev);
2686 
2687     pm_runtime_enable(&pdev->dev);
2688 
2689     return 0;
2690 }
2691 
2692 static void vop2_unbind(struct device *dev, struct device *master, void *data)
2693 {
2694     struct vop2 *vop2 = dev_get_drvdata(dev);
2695     struct drm_device *drm = vop2->drm;
2696     struct list_head *plane_list = &drm->mode_config.plane_list;
2697     struct list_head *crtc_list = &drm->mode_config.crtc_list;
2698     struct drm_crtc *crtc, *tmpc;
2699     struct drm_plane *plane, *tmpp;
2700 
2701     pm_runtime_disable(dev);
2702 
2703     list_for_each_entry_safe(plane, tmpp, plane_list, head)
2704         drm_plane_cleanup(plane);
2705 
2706     list_for_each_entry_safe(crtc, tmpc, crtc_list, head)
2707         vop2_destroy_crtc(crtc);
2708 }
2709 
2710 const struct component_ops vop2_component_ops = {
2711     .bind = vop2_bind,
2712     .unbind = vop2_unbind,
2713 };
2714 EXPORT_SYMBOL_GPL(vop2_component_ops);