cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

rockchip_drm_vop2.c (79605B)


      1// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
      2/*
      3 * Copyright (c) 2020 Rockchip Electronics Co., Ltd.
      4 * Author: Andy Yan <andy.yan@rock-chips.com>
      5 */
      6#include <linux/bitfield.h>
      7#include <linux/clk.h>
      8#include <linux/component.h>
      9#include <linux/delay.h>
     10#include <linux/iopoll.h>
     11#include <linux/kernel.h>
     12#include <linux/mfd/syscon.h>
     13#include <linux/module.h>
     14#include <linux/of.h>
     15#include <linux/of_device.h>
     16#include <linux/of_graph.h>
     17#include <linux/platform_device.h>
     18#include <linux/pm_runtime.h>
     19#include <linux/regmap.h>
     20#include <linux/swab.h>
     21
     22#include <drm/drm.h>
     23#include <drm/drm_atomic.h>
     24#include <drm/drm_atomic_uapi.h>
     25#include <drm/drm_crtc.h>
     26#include <drm/drm_crtc_helper.h>
     27#include <drm/drm_debugfs.h>
     28#include <drm/drm_flip_work.h>
     29#include <drm/drm_plane_helper.h>
     30#include <drm/drm_probe_helper.h>
     31#include <drm/drm_vblank.h>
     32
     33#include <uapi/linux/videodev2.h>
     34#include <dt-bindings/soc/rockchip,vop2.h>
     35
     36#include "rockchip_drm_drv.h"
     37#include "rockchip_drm_gem.h"
     38#include "rockchip_drm_fb.h"
     39#include "rockchip_drm_vop2.h"
     40
     41/*
     42 * VOP2 architecture
     43 *
     44 +----------+   +-------------+                                                        +-----------+
     45 |  Cluster |   | Sel 1 from 6|                                                        | 1 from 3  |
     46 |  window0 |   |    Layer0   |                                                        |    RGB    |
     47 +----------+   +-------------+              +---------------+    +-------------+      +-----------+
     48 +----------+   +-------------+              |N from 6 layers|    |             |
     49 |  Cluster |   | Sel 1 from 6|              |   Overlay0    +--->| Video Port0 |      +-----------+
     50 |  window1 |   |    Layer1   |              |               |    |             |      | 1 from 3  |
     51 +----------+   +-------------+              +---------------+    +-------------+      |   LVDS    |
     52 +----------+   +-------------+                                                        +-----------+
     53 |  Esmart  |   | Sel 1 from 6|
     54 |  window0 |   |   Layer2    |              +---------------+    +-------------+      +-----------+
     55 +----------+   +-------------+              |N from 6 Layers|    |             | +--> | 1 from 3  |
     56 +----------+   +-------------+   -------->  |   Overlay1    +--->| Video Port1 |      |   MIPI    |
     57 |  Esmart  |   | Sel 1 from 6|   -------->  |               |    |             |      +-----------+
     58 |  Window1 |   |   Layer3    |              +---------------+    +-------------+
     59 +----------+   +-------------+                                                        +-----------+
     60 +----------+   +-------------+                                                        | 1 from 3  |
     61 |  Smart   |   | Sel 1 from 6|              +---------------+    +-------------+      |   HDMI    |
     62 |  Window0 |   |    Layer4   |              |N from 6 Layers|    |             |      +-----------+
     63 +----------+   +-------------+              |   Overlay2    +--->| Video Port2 |
     64 +----------+   +-------------+              |               |    |             |      +-----------+
     65 |  Smart   |   | Sel 1 from 6|              +---------------+    +-------------+      |  1 from 3 |
     66 |  Window1 |   |    Layer5   |                                                        |    eDP    |
     67 +----------+   +-------------+                                                        +-----------+
     68 *
     69 */
     70
     71enum vop2_data_format {
     72	VOP2_FMT_ARGB8888 = 0,
     73	VOP2_FMT_RGB888,
     74	VOP2_FMT_RGB565,
     75	VOP2_FMT_XRGB101010,
     76	VOP2_FMT_YUV420SP,
     77	VOP2_FMT_YUV422SP,
     78	VOP2_FMT_YUV444SP,
     79	VOP2_FMT_YUYV422 = 8,
     80	VOP2_FMT_YUYV420,
     81	VOP2_FMT_VYUY422,
     82	VOP2_FMT_VYUY420,
     83	VOP2_FMT_YUV420SP_TILE_8x4 = 0x10,
     84	VOP2_FMT_YUV420SP_TILE_16x2,
     85	VOP2_FMT_YUV422SP_TILE_8x4,
     86	VOP2_FMT_YUV422SP_TILE_16x2,
     87	VOP2_FMT_YUV420SP_10,
     88	VOP2_FMT_YUV422SP_10,
     89	VOP2_FMT_YUV444SP_10,
     90};
     91
     92enum vop2_afbc_format {
     93	VOP2_AFBC_FMT_RGB565,
     94	VOP2_AFBC_FMT_ARGB2101010 = 2,
     95	VOP2_AFBC_FMT_YUV420_10BIT,
     96	VOP2_AFBC_FMT_RGB888,
     97	VOP2_AFBC_FMT_ARGB8888,
     98	VOP2_AFBC_FMT_YUV420 = 9,
     99	VOP2_AFBC_FMT_YUV422 = 0xb,
    100	VOP2_AFBC_FMT_YUV422_10BIT = 0xe,
    101	VOP2_AFBC_FMT_INVALID = -1,
    102};
    103
    104union vop2_alpha_ctrl {
    105	u32 val;
    106	struct {
    107		/* [0:1] */
    108		u32 color_mode:1;
    109		u32 alpha_mode:1;
    110		/* [2:3] */
    111		u32 blend_mode:2;
    112		u32 alpha_cal_mode:1;
    113		/* [5:7] */
    114		u32 factor_mode:3;
    115		/* [8:9] */
    116		u32 alpha_en:1;
    117		u32 src_dst_swap:1;
    118		u32 reserved:6;
    119		/* [16:23] */
    120		u32 glb_alpha:8;
    121	} bits;
    122};
    123
    124struct vop2_alpha {
    125	union vop2_alpha_ctrl src_color_ctrl;
    126	union vop2_alpha_ctrl dst_color_ctrl;
    127	union vop2_alpha_ctrl src_alpha_ctrl;
    128	union vop2_alpha_ctrl dst_alpha_ctrl;
    129};
    130
    131struct vop2_alpha_config {
    132	bool src_premulti_en;
    133	bool dst_premulti_en;
    134	bool src_pixel_alpha_en;
    135	bool dst_pixel_alpha_en;
    136	u16 src_glb_alpha_value;
    137	u16 dst_glb_alpha_value;
    138};
    139
    140struct vop2_win {
    141	struct vop2 *vop2;
    142	struct drm_plane base;
    143	const struct vop2_win_data *data;
    144	struct regmap_field *reg[VOP2_WIN_MAX_REG];
    145
    146	/**
    147	 * @win_id: graphic window id, a cluster may be split into two
    148	 * graphics windows.
    149	 */
    150	u8 win_id;
    151	u8 delay;
    152	u32 offset;
    153
    154	enum drm_plane_type type;
    155};
    156
    157struct vop2_video_port {
    158	struct drm_crtc crtc;
    159	struct vop2 *vop2;
    160	struct clk *dclk;
    161	unsigned int id;
    162	const struct vop2_video_port_regs *regs;
    163	const struct vop2_video_port_data *data;
    164
    165	struct completion dsp_hold_completion;
    166
    167	/**
    168	 * @win_mask: Bitmask of windows attached to the video port;
    169	 */
    170	u32 win_mask;
    171
    172	struct vop2_win *primary_plane;
    173	struct drm_pending_vblank_event *event;
    174
    175	unsigned int nlayers;
    176};
    177
    178struct vop2 {
    179	struct device *dev;
    180	struct drm_device *drm;
    181	struct vop2_video_port vps[ROCKCHIP_MAX_CRTC];
    182
    183	const struct vop2_data *data;
    184	/*
    185	 * Number of windows that are registered as plane, may be less than the
    186	 * total number of hardware windows.
    187	 */
    188	u32 registered_num_wins;
    189
    190	void __iomem *regs;
    191	struct regmap *map;
    192
    193	struct regmap *grf;
    194
    195	/* physical map length of vop2 register */
    196	u32 len;
    197
    198	void __iomem *lut_regs;
    199
    200	/* protects crtc enable/disable */
    201	struct mutex vop2_lock;
    202
    203	int irq;
    204
    205	/*
    206	 * Some global resources are shared between all video ports(crtcs), so
    207	 * we need a ref counter here.
    208	 */
    209	unsigned int enable_count;
    210	struct clk *hclk;
    211	struct clk *aclk;
    212
    213	/* must be put at the end of the struct */
    214	struct vop2_win win[];
    215};
    216
    217static struct vop2_video_port *to_vop2_video_port(struct drm_crtc *crtc)
    218{
    219	return container_of(crtc, struct vop2_video_port, crtc);
    220}
    221
    222static struct vop2_win *to_vop2_win(struct drm_plane *p)
    223{
    224	return container_of(p, struct vop2_win, base);
    225}
    226
    227static void vop2_lock(struct vop2 *vop2)
    228{
    229	mutex_lock(&vop2->vop2_lock);
    230}
    231
    232static void vop2_unlock(struct vop2 *vop2)
    233{
    234	mutex_unlock(&vop2->vop2_lock);
    235}
    236
    237static void vop2_writel(struct vop2 *vop2, u32 offset, u32 v)
    238{
    239	regmap_write(vop2->map, offset, v);
    240}
    241
    242static void vop2_vp_write(struct vop2_video_port *vp, u32 offset, u32 v)
    243{
    244	regmap_write(vp->vop2->map, vp->data->offset + offset, v);
    245}
    246
    247static u32 vop2_readl(struct vop2 *vop2, u32 offset)
    248{
    249	u32 val;
    250
    251	regmap_read(vop2->map, offset, &val);
    252
    253	return val;
    254}
    255
    256static void vop2_win_write(const struct vop2_win *win, unsigned int reg, u32 v)
    257{
    258	regmap_field_write(win->reg[reg], v);
    259}
    260
    261static bool vop2_cluster_window(const struct vop2_win *win)
    262{
    263	return win->data->feature & WIN_FEATURE_CLUSTER;
    264}
    265
    266static void vop2_cfg_done(struct vop2_video_port *vp)
    267{
    268	struct vop2 *vop2 = vp->vop2;
    269
    270	regmap_set_bits(vop2->map, RK3568_REG_CFG_DONE,
    271			BIT(vp->id) | RK3568_REG_CFG_DONE__GLB_CFG_DONE_EN);
    272}
    273
    274static void vop2_win_disable(struct vop2_win *win)
    275{
    276	vop2_win_write(win, VOP2_WIN_ENABLE, 0);
    277
    278	if (vop2_cluster_window(win))
    279		vop2_win_write(win, VOP2_WIN_CLUSTER_ENABLE, 0);
    280}
    281
    282static enum vop2_data_format vop2_convert_format(u32 format)
    283{
    284	switch (format) {
    285	case DRM_FORMAT_XRGB8888:
    286	case DRM_FORMAT_ARGB8888:
    287	case DRM_FORMAT_XBGR8888:
    288	case DRM_FORMAT_ABGR8888:
    289		return VOP2_FMT_ARGB8888;
    290	case DRM_FORMAT_RGB888:
    291	case DRM_FORMAT_BGR888:
    292		return VOP2_FMT_RGB888;
    293	case DRM_FORMAT_RGB565:
    294	case DRM_FORMAT_BGR565:
    295		return VOP2_FMT_RGB565;
    296	case DRM_FORMAT_NV12:
    297		return VOP2_FMT_YUV420SP;
    298	case DRM_FORMAT_NV16:
    299		return VOP2_FMT_YUV422SP;
    300	case DRM_FORMAT_NV24:
    301		return VOP2_FMT_YUV444SP;
    302	case DRM_FORMAT_YUYV:
    303	case DRM_FORMAT_YVYU:
    304		return VOP2_FMT_VYUY422;
    305	case DRM_FORMAT_VYUY:
    306	case DRM_FORMAT_UYVY:
    307		return VOP2_FMT_YUYV422;
    308	default:
    309		DRM_ERROR("unsupported format[%08x]\n", format);
    310		return -EINVAL;
    311	}
    312}
    313
    314static enum vop2_afbc_format vop2_convert_afbc_format(u32 format)
    315{
    316	switch (format) {
    317	case DRM_FORMAT_XRGB8888:
    318	case DRM_FORMAT_ARGB8888:
    319	case DRM_FORMAT_XBGR8888:
    320	case DRM_FORMAT_ABGR8888:
    321		return VOP2_AFBC_FMT_ARGB8888;
    322	case DRM_FORMAT_RGB888:
    323	case DRM_FORMAT_BGR888:
    324		return VOP2_AFBC_FMT_RGB888;
    325	case DRM_FORMAT_RGB565:
    326	case DRM_FORMAT_BGR565:
    327		return VOP2_AFBC_FMT_RGB565;
    328	case DRM_FORMAT_NV12:
    329		return VOP2_AFBC_FMT_YUV420;
    330	case DRM_FORMAT_NV16:
    331		return VOP2_AFBC_FMT_YUV422;
    332	default:
    333		return VOP2_AFBC_FMT_INVALID;
    334	}
    335
    336	return VOP2_AFBC_FMT_INVALID;
    337}
    338
    339static bool vop2_win_rb_swap(u32 format)
    340{
    341	switch (format) {
    342	case DRM_FORMAT_XBGR8888:
    343	case DRM_FORMAT_ABGR8888:
    344	case DRM_FORMAT_BGR888:
    345	case DRM_FORMAT_BGR565:
    346		return true;
    347	default:
    348		return false;
    349	}
    350}
    351
    352static bool vop2_afbc_rb_swap(u32 format)
    353{
    354	switch (format) {
    355	case DRM_FORMAT_NV24:
    356		return true;
    357	default:
    358		return false;
    359	}
    360}
    361
    362static bool vop2_afbc_uv_swap(u32 format)
    363{
    364	switch (format) {
    365	case DRM_FORMAT_NV12:
    366	case DRM_FORMAT_NV16:
    367		return true;
    368	default:
    369		return false;
    370	}
    371}
    372
    373static bool vop2_win_uv_swap(u32 format)
    374{
    375	switch (format) {
    376	case DRM_FORMAT_NV12:
    377	case DRM_FORMAT_NV16:
    378	case DRM_FORMAT_NV24:
    379		return true;
    380	default:
    381		return false;
    382	}
    383}
    384
    385static bool vop2_win_dither_up(u32 format)
    386{
    387	switch (format) {
    388	case DRM_FORMAT_BGR565:
    389	case DRM_FORMAT_RGB565:
    390		return true;
    391	default:
    392		return false;
    393	}
    394}
    395
    396static bool vop2_output_uv_swap(u32 bus_format, u32 output_mode)
    397{
    398	/*
    399	 * FIXME:
    400	 *
    401	 * There is no media type for YUV444 output,
    402	 * so when out_mode is AAAA or P888, assume output is YUV444 on
    403	 * yuv format.
    404	 *
    405	 * From H/W testing, YUV444 mode need a rb swap.
    406	 */
    407	if (bus_format == MEDIA_BUS_FMT_YVYU8_1X16 ||
    408	    bus_format == MEDIA_BUS_FMT_VYUY8_1X16 ||
    409	    bus_format == MEDIA_BUS_FMT_YVYU8_2X8 ||
    410	    bus_format == MEDIA_BUS_FMT_VYUY8_2X8 ||
    411	    ((bus_format == MEDIA_BUS_FMT_YUV8_1X24 ||
    412	      bus_format == MEDIA_BUS_FMT_YUV10_1X30) &&
    413	     (output_mode == ROCKCHIP_OUT_MODE_AAAA ||
    414	      output_mode == ROCKCHIP_OUT_MODE_P888)))
    415		return true;
    416	else
    417		return false;
    418}
    419
    420static bool is_yuv_output(u32 bus_format)
    421{
    422	switch (bus_format) {
    423	case MEDIA_BUS_FMT_YUV8_1X24:
    424	case MEDIA_BUS_FMT_YUV10_1X30:
    425	case MEDIA_BUS_FMT_UYYVYY8_0_5X24:
    426	case MEDIA_BUS_FMT_UYYVYY10_0_5X30:
    427	case MEDIA_BUS_FMT_YUYV8_2X8:
    428	case MEDIA_BUS_FMT_YVYU8_2X8:
    429	case MEDIA_BUS_FMT_UYVY8_2X8:
    430	case MEDIA_BUS_FMT_VYUY8_2X8:
    431	case MEDIA_BUS_FMT_YUYV8_1X16:
    432	case MEDIA_BUS_FMT_YVYU8_1X16:
    433	case MEDIA_BUS_FMT_UYVY8_1X16:
    434	case MEDIA_BUS_FMT_VYUY8_1X16:
    435		return true;
    436	default:
    437		return false;
    438	}
    439}
    440
    441static bool rockchip_afbc(struct drm_plane *plane, u64 modifier)
    442{
    443	int i;
    444
    445	if (modifier == DRM_FORMAT_MOD_LINEAR)
    446		return false;
    447
    448	for (i = 0 ; i < plane->modifier_count; i++)
    449		if (plane->modifiers[i] == modifier)
    450			return true;
    451
    452	return false;
    453}
    454
    455static bool rockchip_vop2_mod_supported(struct drm_plane *plane, u32 format,
    456					u64 modifier)
    457{
    458	struct vop2_win *win = to_vop2_win(plane);
    459	struct vop2 *vop2 = win->vop2;
    460
    461	if (modifier == DRM_FORMAT_MOD_INVALID)
    462		return false;
    463
    464	if (modifier == DRM_FORMAT_MOD_LINEAR)
    465		return true;
    466
    467	if (!rockchip_afbc(plane, modifier)) {
    468		drm_err(vop2->drm, "Unsupported format modifier 0x%llx\n",
    469			modifier);
    470
    471		return false;
    472	}
    473
    474	return vop2_convert_afbc_format(format) >= 0;
    475}
    476
    477static u32 vop2_afbc_transform_offset(struct drm_plane_state *pstate,
    478				      bool afbc_half_block_en)
    479{
    480	struct drm_rect *src = &pstate->src;
    481	struct drm_framebuffer *fb = pstate->fb;
    482	u32 bpp = fb->format->cpp[0] * 8;
    483	u32 vir_width = (fb->pitches[0] << 3) / bpp;
    484	u32 width = drm_rect_width(src) >> 16;
    485	u32 height = drm_rect_height(src) >> 16;
    486	u32 act_xoffset = src->x1 >> 16;
    487	u32 act_yoffset = src->y1 >> 16;
    488	u32 align16_crop = 0;
    489	u32 align64_crop = 0;
    490	u32 height_tmp;
    491	u8 tx, ty;
    492	u8 bottom_crop_line_num = 0;
    493
    494	/* 16 pixel align */
    495	if (height & 0xf)
    496		align16_crop = 16 - (height & 0xf);
    497
    498	height_tmp = height + align16_crop;
    499
    500	/* 64 pixel align */
    501	if (height_tmp & 0x3f)
    502		align64_crop = 64 - (height_tmp & 0x3f);
    503
    504	bottom_crop_line_num = align16_crop + align64_crop;
    505
    506	switch (pstate->rotation &
    507		(DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y |
    508		 DRM_MODE_ROTATE_90 | DRM_MODE_ROTATE_270)) {
    509	case DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y:
    510		tx = 16 - ((act_xoffset + width) & 0xf);
    511		ty = bottom_crop_line_num - act_yoffset;
    512		break;
    513	case DRM_MODE_REFLECT_X | DRM_MODE_ROTATE_90:
    514		tx = bottom_crop_line_num - act_yoffset;
    515		ty = vir_width - width - act_xoffset;
    516		break;
    517	case DRM_MODE_REFLECT_X | DRM_MODE_ROTATE_270:
    518		tx = act_yoffset;
    519		ty = act_xoffset;
    520		break;
    521	case DRM_MODE_REFLECT_X:
    522		tx = 16 - ((act_xoffset + width) & 0xf);
    523		ty = act_yoffset;
    524		break;
    525	case DRM_MODE_REFLECT_Y:
    526		tx = act_xoffset;
    527		ty = bottom_crop_line_num - act_yoffset;
    528		break;
    529	case DRM_MODE_ROTATE_90:
    530		tx = bottom_crop_line_num - act_yoffset;
    531		ty = act_xoffset;
    532		break;
    533	case DRM_MODE_ROTATE_270:
    534		tx = act_yoffset;
    535		ty = vir_width - width - act_xoffset;
    536		break;
    537	case 0:
    538		tx = act_xoffset;
    539		ty = act_yoffset;
    540		break;
    541	}
    542
    543	if (afbc_half_block_en)
    544		ty &= 0x7f;
    545
    546#define TRANSFORM_XOFFSET GENMASK(7, 0)
    547#define TRANSFORM_YOFFSET GENMASK(23, 16)
    548	return FIELD_PREP(TRANSFORM_XOFFSET, tx) |
    549		FIELD_PREP(TRANSFORM_YOFFSET, ty);
    550}
    551
    552/*
    553 * A Cluster window has 2048 x 16 line buffer, which can
    554 * works at 2048 x 16(Full) or 4096 x 8 (Half) mode.
    555 * for Cluster_lb_mode register:
    556 * 0: half mode, for plane input width range 2048 ~ 4096
    557 * 1: half mode, for cluster work at 2 * 2048 plane mode
    558 * 2: half mode, for rotate_90/270 mode
    559 *
    560 */
    561static int vop2_get_cluster_lb_mode(struct vop2_win *win,
    562				    struct drm_plane_state *pstate)
    563{
    564	if ((pstate->rotation & DRM_MODE_ROTATE_270) ||
    565	    (pstate->rotation & DRM_MODE_ROTATE_90))
    566		return 2;
    567	else
    568		return 0;
    569}
    570
    571static u16 vop2_scale_factor(u32 src, u32 dst)
    572{
    573	u32 fac;
    574	int shift;
    575
    576	if (src == dst)
    577		return 0;
    578
    579	if (dst < 2)
    580		return U16_MAX;
    581
    582	if (src < 2)
    583		return 0;
    584
    585	if (src > dst)
    586		shift = 12;
    587	else
    588		shift = 16;
    589
    590	src--;
    591	dst--;
    592
    593	fac = DIV_ROUND_UP(src << shift, dst) - 1;
    594
    595	if (fac > U16_MAX)
    596		return U16_MAX;
    597
    598	return fac;
    599}
    600
    601static void vop2_setup_scale(struct vop2 *vop2, const struct vop2_win *win,
    602			     u32 src_w, u32 src_h, u32 dst_w,
    603			     u32 dst_h, u32 pixel_format)
    604{
    605	const struct drm_format_info *info;
    606	u16 hor_scl_mode, ver_scl_mode;
    607	u16 hscl_filter_mode, vscl_filter_mode;
    608	u8 gt2 = 0;
    609	u8 gt4 = 0;
    610	u32 val;
    611
    612	info = drm_format_info(pixel_format);
    613
    614	if (src_h >= (4 * dst_h)) {
    615		gt4 = 1;
    616		src_h >>= 2;
    617	} else if (src_h >= (2 * dst_h)) {
    618		gt2 = 1;
    619		src_h >>= 1;
    620	}
    621
    622	hor_scl_mode = scl_get_scl_mode(src_w, dst_w);
    623	ver_scl_mode = scl_get_scl_mode(src_h, dst_h);
    624
    625	if (hor_scl_mode == SCALE_UP)
    626		hscl_filter_mode = VOP2_SCALE_UP_BIC;
    627	else
    628		hscl_filter_mode = VOP2_SCALE_DOWN_BIL;
    629
    630	if (ver_scl_mode == SCALE_UP)
    631		vscl_filter_mode = VOP2_SCALE_UP_BIL;
    632	else
    633		vscl_filter_mode = VOP2_SCALE_DOWN_BIL;
    634
    635	/*
    636	 * RK3568 VOP Esmart/Smart dsp_w should be even pixel
    637	 * at scale down mode
    638	 */
    639	if (!(win->data->feature & WIN_FEATURE_AFBDC)) {
    640		if ((hor_scl_mode == SCALE_DOWN) && (dst_w & 0x1)) {
    641			drm_dbg(vop2->drm, "%s dst_w[%d] should align as 2 pixel\n",
    642				win->data->name, dst_w);
    643			dst_w++;
    644		}
    645	}
    646
    647	val = vop2_scale_factor(src_w, dst_w);
    648	vop2_win_write(win, VOP2_WIN_SCALE_YRGB_X, val);
    649	val = vop2_scale_factor(src_h, dst_h);
    650	vop2_win_write(win, VOP2_WIN_SCALE_YRGB_Y, val);
    651
    652	vop2_win_write(win, VOP2_WIN_VSD_YRGB_GT4, gt4);
    653	vop2_win_write(win, VOP2_WIN_VSD_YRGB_GT2, gt2);
    654
    655	vop2_win_write(win, VOP2_WIN_YRGB_HOR_SCL_MODE, hor_scl_mode);
    656	vop2_win_write(win, VOP2_WIN_YRGB_VER_SCL_MODE, ver_scl_mode);
    657
    658	if (vop2_cluster_window(win))
    659		return;
    660
    661	vop2_win_write(win, VOP2_WIN_YRGB_HSCL_FILTER_MODE, hscl_filter_mode);
    662	vop2_win_write(win, VOP2_WIN_YRGB_VSCL_FILTER_MODE, vscl_filter_mode);
    663
    664	if (info->is_yuv) {
    665		src_w /= info->hsub;
    666		src_h /= info->vsub;
    667
    668		gt4 = 0;
    669		gt2 = 0;
    670
    671		if (src_h >= (4 * dst_h)) {
    672			gt4 = 1;
    673			src_h >>= 2;
    674		} else if (src_h >= (2 * dst_h)) {
    675			gt2 = 1;
    676			src_h >>= 1;
    677		}
    678
    679		hor_scl_mode = scl_get_scl_mode(src_w, dst_w);
    680		ver_scl_mode = scl_get_scl_mode(src_h, dst_h);
    681
    682		val = vop2_scale_factor(src_w, dst_w);
    683		vop2_win_write(win, VOP2_WIN_SCALE_CBCR_X, val);
    684
    685		val = vop2_scale_factor(src_h, dst_h);
    686		vop2_win_write(win, VOP2_WIN_SCALE_CBCR_Y, val);
    687
    688		vop2_win_write(win, VOP2_WIN_VSD_CBCR_GT4, gt4);
    689		vop2_win_write(win, VOP2_WIN_VSD_CBCR_GT2, gt2);
    690		vop2_win_write(win, VOP2_WIN_CBCR_HOR_SCL_MODE, hor_scl_mode);
    691		vop2_win_write(win, VOP2_WIN_CBCR_VER_SCL_MODE, ver_scl_mode);
    692		vop2_win_write(win, VOP2_WIN_CBCR_HSCL_FILTER_MODE, hscl_filter_mode);
    693		vop2_win_write(win, VOP2_WIN_CBCR_VSCL_FILTER_MODE, vscl_filter_mode);
    694	}
    695}
    696
    697static int vop2_convert_csc_mode(int csc_mode)
    698{
    699	switch (csc_mode) {
    700	case V4L2_COLORSPACE_SMPTE170M:
    701	case V4L2_COLORSPACE_470_SYSTEM_M:
    702	case V4L2_COLORSPACE_470_SYSTEM_BG:
    703		return CSC_BT601L;
    704	case V4L2_COLORSPACE_REC709:
    705	case V4L2_COLORSPACE_SMPTE240M:
    706	case V4L2_COLORSPACE_DEFAULT:
    707		return CSC_BT709L;
    708	case V4L2_COLORSPACE_JPEG:
    709		return CSC_BT601F;
    710	case V4L2_COLORSPACE_BT2020:
    711		return CSC_BT2020;
    712	default:
    713		return CSC_BT709L;
    714	}
    715}
    716
    717/*
    718 * colorspace path:
    719 *      Input        Win csc                     Output
    720 * 1. YUV(2020)  --> Y2R->2020To709->R2Y   --> YUV_OUTPUT(601/709)
    721 *    RGB        --> R2Y                  __/
    722 *
    723 * 2. YUV(2020)  --> bypasss               --> YUV_OUTPUT(2020)
    724 *    RGB        --> 709To2020->R2Y       __/
    725 *
    726 * 3. YUV(2020)  --> Y2R->2020To709        --> RGB_OUTPUT(709)
    727 *    RGB        --> R2Y                  __/
    728 *
    729 * 4. YUV(601/709)-> Y2R->709To2020->R2Y   --> YUV_OUTPUT(2020)
    730 *    RGB        --> 709To2020->R2Y       __/
    731 *
    732 * 5. YUV(601/709)-> bypass                --> YUV_OUTPUT(709)
    733 *    RGB        --> R2Y                  __/
    734 *
    735 * 6. YUV(601/709)-> bypass                --> YUV_OUTPUT(601)
    736 *    RGB        --> R2Y(601)             __/
    737 *
    738 * 7. YUV        --> Y2R(709)              --> RGB_OUTPUT(709)
    739 *    RGB        --> bypass               __/
    740 *
    741 * 8. RGB        --> 709To2020->R2Y        --> YUV_OUTPUT(2020)
    742 *
    743 * 9. RGB        --> R2Y(709)              --> YUV_OUTPUT(709)
    744 *
    745 * 10. RGB       --> R2Y(601)              --> YUV_OUTPUT(601)
    746 *
    747 * 11. RGB       --> bypass                --> RGB_OUTPUT(709)
    748 */
    749
    750static void vop2_setup_csc_mode(struct vop2_video_port *vp,
    751				struct vop2_win *win,
    752				struct drm_plane_state *pstate)
    753{
    754	struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(vp->crtc.state);
    755	int is_input_yuv = pstate->fb->format->is_yuv;
    756	int is_output_yuv = is_yuv_output(vcstate->bus_format);
    757	int input_csc = V4L2_COLORSPACE_DEFAULT;
    758	int output_csc = vcstate->color_space;
    759	bool r2y_en, y2r_en;
    760	int csc_mode;
    761
    762	if (is_input_yuv && !is_output_yuv) {
    763		y2r_en = true;
    764		r2y_en = false;
    765		csc_mode = vop2_convert_csc_mode(input_csc);
    766	} else if (!is_input_yuv && is_output_yuv) {
    767		y2r_en = false;
    768		r2y_en = true;
    769		csc_mode = vop2_convert_csc_mode(output_csc);
    770	} else {
    771		y2r_en = false;
    772		r2y_en = false;
    773		csc_mode = false;
    774	}
    775
    776	vop2_win_write(win, VOP2_WIN_Y2R_EN, y2r_en);
    777	vop2_win_write(win, VOP2_WIN_R2Y_EN, r2y_en);
    778	vop2_win_write(win, VOP2_WIN_CSC_MODE, csc_mode);
    779}
    780
    781static void vop2_crtc_enable_irq(struct vop2_video_port *vp, u32 irq)
    782{
    783	struct vop2 *vop2 = vp->vop2;
    784
    785	vop2_writel(vop2, RK3568_VP_INT_CLR(vp->id), irq << 16 | irq);
    786	vop2_writel(vop2, RK3568_VP_INT_EN(vp->id), irq << 16 | irq);
    787}
    788
    789static void vop2_crtc_disable_irq(struct vop2_video_port *vp, u32 irq)
    790{
    791	struct vop2 *vop2 = vp->vop2;
    792
    793	vop2_writel(vop2, RK3568_VP_INT_EN(vp->id), irq << 16);
    794}
    795
    796static int vop2_core_clks_prepare_enable(struct vop2 *vop2)
    797{
    798	int ret;
    799
    800	ret = clk_prepare_enable(vop2->hclk);
    801	if (ret < 0) {
    802		drm_err(vop2->drm, "failed to enable hclk - %d\n", ret);
    803		return ret;
    804	}
    805
    806	ret = clk_prepare_enable(vop2->aclk);
    807	if (ret < 0) {
    808		drm_err(vop2->drm, "failed to enable aclk - %d\n", ret);
    809		goto err;
    810	}
    811
    812	return 0;
    813err:
    814	clk_disable_unprepare(vop2->hclk);
    815
    816	return ret;
    817}
    818
    819static void vop2_enable(struct vop2 *vop2)
    820{
    821	int ret;
    822
    823	ret = pm_runtime_get_sync(vop2->dev);
    824	if (ret < 0) {
    825		drm_err(vop2->drm, "failed to get pm runtime: %d\n", ret);
    826		return;
    827	}
    828
    829	ret = vop2_core_clks_prepare_enable(vop2);
    830	if (ret) {
    831		pm_runtime_put_sync(vop2->dev);
    832		return;
    833	}
    834
    835	ret = rockchip_drm_dma_attach_device(vop2->drm, vop2->dev);
    836	if (ret) {
    837		drm_err(vop2->drm, "failed to attach dma mapping, %d\n", ret);
    838		return;
    839	}
    840
    841	if (vop2->data->soc_id == 3566)
    842		vop2_writel(vop2, RK3568_OTP_WIN_EN, 1);
    843
    844	vop2_writel(vop2, RK3568_REG_CFG_DONE, RK3568_REG_CFG_DONE__GLB_CFG_DONE_EN);
    845
    846	/*
    847	 * Disable auto gating, this is a workaround to
    848	 * avoid display image shift when a window enabled.
    849	 */
    850	regmap_clear_bits(vop2->map, RK3568_SYS_AUTO_GATING_CTRL,
    851			  RK3568_SYS_AUTO_GATING_CTRL__AUTO_GATING_EN);
    852
    853	vop2_writel(vop2, RK3568_SYS0_INT_CLR,
    854		    VOP2_INT_BUS_ERRPR << 16 | VOP2_INT_BUS_ERRPR);
    855	vop2_writel(vop2, RK3568_SYS0_INT_EN,
    856		    VOP2_INT_BUS_ERRPR << 16 | VOP2_INT_BUS_ERRPR);
    857	vop2_writel(vop2, RK3568_SYS1_INT_CLR,
    858		    VOP2_INT_BUS_ERRPR << 16 | VOP2_INT_BUS_ERRPR);
    859	vop2_writel(vop2, RK3568_SYS1_INT_EN,
    860		    VOP2_INT_BUS_ERRPR << 16 | VOP2_INT_BUS_ERRPR);
    861}
    862
    863static void vop2_disable(struct vop2 *vop2)
    864{
    865	rockchip_drm_dma_detach_device(vop2->drm, vop2->dev);
    866
    867	pm_runtime_put_sync(vop2->dev);
    868
    869	clk_disable_unprepare(vop2->aclk);
    870	clk_disable_unprepare(vop2->hclk);
    871}
    872
    873static void vop2_crtc_atomic_disable(struct drm_crtc *crtc,
    874				     struct drm_atomic_state *state)
    875{
    876	struct vop2_video_port *vp = to_vop2_video_port(crtc);
    877	struct vop2 *vop2 = vp->vop2;
    878	int ret;
    879
    880	vop2_lock(vop2);
    881
    882	drm_crtc_vblank_off(crtc);
    883
    884	/*
    885	 * Vop standby will take effect at end of current frame,
    886	 * if dsp hold valid irq happen, it means standby complete.
    887	 *
    888	 * we must wait standby complete when we want to disable aclk,
    889	 * if not, memory bus maybe dead.
    890	 */
    891	reinit_completion(&vp->dsp_hold_completion);
    892
    893	vop2_crtc_enable_irq(vp, VP_INT_DSP_HOLD_VALID);
    894
    895	vop2_vp_write(vp, RK3568_VP_DSP_CTRL, RK3568_VP_DSP_CTRL__STANDBY);
    896
    897	ret = wait_for_completion_timeout(&vp->dsp_hold_completion,
    898					  msecs_to_jiffies(50));
    899	if (!ret)
    900		drm_info(vop2->drm, "wait for vp%d dsp_hold timeout\n", vp->id);
    901
    902	vop2_crtc_disable_irq(vp, VP_INT_DSP_HOLD_VALID);
    903
    904	clk_disable_unprepare(vp->dclk);
    905
    906	vop2->enable_count--;
    907
    908	if (!vop2->enable_count)
    909		vop2_disable(vop2);
    910
    911	vop2_unlock(vop2);
    912
    913	if (crtc->state->event && !crtc->state->active) {
    914		spin_lock_irq(&crtc->dev->event_lock);
    915		drm_crtc_send_vblank_event(crtc, crtc->state->event);
    916		spin_unlock_irq(&crtc->dev->event_lock);
    917
    918		crtc->state->event = NULL;
    919	}
    920}
    921
    922static int vop2_plane_atomic_check(struct drm_plane *plane,
    923				   struct drm_atomic_state *astate)
    924{
    925	struct drm_plane_state *pstate = drm_atomic_get_new_plane_state(astate, plane);
    926	struct drm_framebuffer *fb = pstate->fb;
    927	struct drm_crtc *crtc = pstate->crtc;
    928	struct drm_crtc_state *cstate;
    929	struct vop2_video_port *vp;
    930	struct vop2 *vop2;
    931	const struct vop2_data *vop2_data;
    932	struct drm_rect *dest = &pstate->dst;
    933	struct drm_rect *src = &pstate->src;
    934	int min_scale = FRAC_16_16(1, 8);
    935	int max_scale = FRAC_16_16(8, 1);
    936	int format;
    937	int ret;
    938
    939	if (!crtc)
    940		return 0;
    941
    942	vp = to_vop2_video_port(crtc);
    943	vop2 = vp->vop2;
    944	vop2_data = vop2->data;
    945
    946	cstate = drm_atomic_get_existing_crtc_state(pstate->state, crtc);
    947	if (WARN_ON(!cstate))
    948		return -EINVAL;
    949
    950	ret = drm_atomic_helper_check_plane_state(pstate, cstate,
    951						  min_scale, max_scale,
    952						  true, true);
    953	if (ret)
    954		return ret;
    955
    956	if (!pstate->visible)
    957		return 0;
    958
    959	format = vop2_convert_format(fb->format->format);
    960	if (format < 0)
    961		return format;
    962
    963	if (drm_rect_width(src) >> 16 < 4 || drm_rect_height(src) >> 16 < 4 ||
    964	    drm_rect_width(dest) < 4 || drm_rect_width(dest) < 4) {
    965		drm_err(vop2->drm, "Invalid size: %dx%d->%dx%d, min size is 4x4\n",
    966			drm_rect_width(src) >> 16, drm_rect_height(src) >> 16,
    967			drm_rect_width(dest), drm_rect_height(dest));
    968		pstate->visible = false;
    969		return 0;
    970	}
    971
    972	if (drm_rect_width(src) >> 16 > vop2_data->max_input.width ||
    973	    drm_rect_height(src) >> 16 > vop2_data->max_input.height) {
    974		drm_err(vop2->drm, "Invalid source: %dx%d. max input: %dx%d\n",
    975			drm_rect_width(src) >> 16,
    976			drm_rect_height(src) >> 16,
    977			vop2_data->max_input.width,
    978			vop2_data->max_input.height);
    979		return -EINVAL;
    980	}
    981
    982	/*
    983	 * Src.x1 can be odd when do clip, but yuv plane start point
    984	 * need align with 2 pixel.
    985	 */
    986	if (fb->format->is_yuv && ((pstate->src.x1 >> 16) % 2)) {
    987		drm_err(vop2->drm, "Invalid Source: Yuv format not support odd xpos\n");
    988		return -EINVAL;
    989	}
    990
    991	return 0;
    992}
    993
    994static void vop2_plane_atomic_disable(struct drm_plane *plane,
    995				      struct drm_atomic_state *state)
    996{
    997	struct drm_plane_state *old_pstate = drm_atomic_get_old_plane_state(state, plane);
    998	struct vop2_win *win = to_vop2_win(plane);
    999	struct vop2 *vop2 = win->vop2;
   1000
   1001	drm_dbg(vop2->drm, "%s disable\n", win->data->name);
   1002
   1003	if (!old_pstate->crtc)
   1004		return;
   1005
   1006	vop2_win_disable(win);
   1007	vop2_win_write(win, VOP2_WIN_YUV_CLIP, 0);
   1008}
   1009
   1010/*
   1011 * The color key is 10 bit, so all format should
   1012 * convert to 10 bit here.
   1013 */
   1014static void vop2_plane_setup_color_key(struct drm_plane *plane, u32 color_key)
   1015{
   1016	struct drm_plane_state *pstate = plane->state;
   1017	struct drm_framebuffer *fb = pstate->fb;
   1018	struct vop2_win *win = to_vop2_win(plane);
   1019	u32 color_key_en = 0;
   1020	u32 r = 0;
   1021	u32 g = 0;
   1022	u32 b = 0;
   1023
   1024	if (!(color_key & VOP2_COLOR_KEY_MASK) || fb->format->is_yuv) {
   1025		vop2_win_write(win, VOP2_WIN_COLOR_KEY_EN, 0);
   1026		return;
   1027	}
   1028
   1029	switch (fb->format->format) {
   1030	case DRM_FORMAT_RGB565:
   1031	case DRM_FORMAT_BGR565:
   1032		r = (color_key & 0xf800) >> 11;
   1033		g = (color_key & 0x7e0) >> 5;
   1034		b = (color_key & 0x1f);
   1035		r <<= 5;
   1036		g <<= 4;
   1037		b <<= 5;
   1038		color_key_en = 1;
   1039		break;
   1040	case DRM_FORMAT_XRGB8888:
   1041	case DRM_FORMAT_ARGB8888:
   1042	case DRM_FORMAT_XBGR8888:
   1043	case DRM_FORMAT_ABGR8888:
   1044	case DRM_FORMAT_RGB888:
   1045	case DRM_FORMAT_BGR888:
   1046		r = (color_key & 0xff0000) >> 16;
   1047		g = (color_key & 0xff00) >> 8;
   1048		b = (color_key & 0xff);
   1049		r <<= 2;
   1050		g <<= 2;
   1051		b <<= 2;
   1052		color_key_en = 1;
   1053		break;
   1054	}
   1055
   1056	vop2_win_write(win, VOP2_WIN_COLOR_KEY_EN, color_key_en);
   1057	vop2_win_write(win, VOP2_WIN_COLOR_KEY, (r << 20) | (g << 10) | b);
   1058}
   1059
   1060static void vop2_plane_atomic_update(struct drm_plane *plane,
   1061				     struct drm_atomic_state *state)
   1062{
   1063	struct drm_plane_state *pstate = plane->state;
   1064	struct drm_crtc *crtc = pstate->crtc;
   1065	struct vop2_win *win = to_vop2_win(plane);
   1066	struct vop2_video_port *vp = to_vop2_video_port(crtc);
   1067	struct drm_display_mode *adjusted_mode = &crtc->state->adjusted_mode;
   1068	struct vop2 *vop2 = win->vop2;
   1069	struct drm_framebuffer *fb = pstate->fb;
   1070	u32 bpp = fb->format->cpp[0] * 8;
   1071	u32 actual_w, actual_h, dsp_w, dsp_h;
   1072	u32 act_info, dsp_info;
   1073	u32 format;
   1074	u32 afbc_format;
   1075	u32 rb_swap;
   1076	u32 uv_swap;
   1077	struct drm_rect *src = &pstate->src;
   1078	struct drm_rect *dest = &pstate->dst;
   1079	u32 afbc_tile_num;
   1080	u32 transform_offset;
   1081	bool dither_up;
   1082	bool xmirror = pstate->rotation & DRM_MODE_REFLECT_X ? true : false;
   1083	bool ymirror = pstate->rotation & DRM_MODE_REFLECT_Y ? true : false;
   1084	bool rotate_270 = pstate->rotation & DRM_MODE_ROTATE_270;
   1085	bool rotate_90 = pstate->rotation & DRM_MODE_ROTATE_90;
   1086	struct rockchip_gem_object *rk_obj;
   1087	unsigned long offset;
   1088	bool afbc_en;
   1089	dma_addr_t yrgb_mst;
   1090	dma_addr_t uv_mst;
   1091
   1092	/*
   1093	 * can't update plane when vop2 is disabled.
   1094	 */
   1095	if (WARN_ON(!crtc))
   1096		return;
   1097
   1098	if (!pstate->visible) {
   1099		vop2_plane_atomic_disable(plane, state);
   1100		return;
   1101	}
   1102
   1103	afbc_en = rockchip_afbc(plane, fb->modifier);
   1104
   1105	offset = (src->x1 >> 16) * fb->format->cpp[0];
   1106
   1107	/*
   1108	 * AFBC HDR_PTR must set to the zero offset of the framebuffer.
   1109	 */
   1110	if (afbc_en)
   1111		offset = 0;
   1112	else if (pstate->rotation & DRM_MODE_REFLECT_Y)
   1113		offset += ((src->y2 >> 16) - 1) * fb->pitches[0];
   1114	else
   1115		offset += (src->y1 >> 16) * fb->pitches[0];
   1116
   1117	rk_obj = to_rockchip_obj(fb->obj[0]);
   1118
   1119	yrgb_mst = rk_obj->dma_addr + offset + fb->offsets[0];
   1120	if (fb->format->is_yuv) {
   1121		int hsub = fb->format->hsub;
   1122		int vsub = fb->format->vsub;
   1123
   1124		offset = (src->x1 >> 16) * fb->format->cpp[1] / hsub;
   1125		offset += (src->y1 >> 16) * fb->pitches[1] / vsub;
   1126
   1127		if ((pstate->rotation & DRM_MODE_REFLECT_Y) && !afbc_en)
   1128			offset += fb->pitches[1] * ((pstate->src_h >> 16) - 2) / vsub;
   1129
   1130		rk_obj = to_rockchip_obj(fb->obj[0]);
   1131		uv_mst = rk_obj->dma_addr + offset + fb->offsets[1];
   1132	}
   1133
   1134	actual_w = drm_rect_width(src) >> 16;
   1135	actual_h = drm_rect_height(src) >> 16;
   1136	dsp_w = drm_rect_width(dest);
   1137
   1138	if (dest->x1 + dsp_w > adjusted_mode->hdisplay) {
   1139		drm_err(vop2->drm, "vp%d %s dest->x1[%d] + dsp_w[%d] exceed mode hdisplay[%d]\n",
   1140			vp->id, win->data->name, dest->x1, dsp_w, adjusted_mode->hdisplay);
   1141		dsp_w = adjusted_mode->hdisplay - dest->x1;
   1142		if (dsp_w < 4)
   1143			dsp_w = 4;
   1144		actual_w = dsp_w * actual_w / drm_rect_width(dest);
   1145	}
   1146
   1147	dsp_h = drm_rect_height(dest);
   1148
   1149	if (dest->y1 + dsp_h > adjusted_mode->vdisplay) {
   1150		drm_err(vop2->drm, "vp%d %s dest->y1[%d] + dsp_h[%d] exceed mode vdisplay[%d]\n",
   1151			vp->id, win->data->name, dest->y1, dsp_h, adjusted_mode->vdisplay);
   1152		dsp_h = adjusted_mode->vdisplay - dest->y1;
   1153		if (dsp_h < 4)
   1154			dsp_h = 4;
   1155		actual_h = dsp_h * actual_h / drm_rect_height(dest);
   1156	}
   1157
   1158	/*
   1159	 * This is workaround solution for IC design:
   1160	 * esmart can't support scale down when actual_w % 16 == 1.
   1161	 */
   1162	if (!(win->data->feature & WIN_FEATURE_AFBDC)) {
   1163		if (actual_w > dsp_w && (actual_w & 0xf) == 1) {
   1164			drm_err(vop2->drm, "vp%d %s act_w[%d] MODE 16 == 1\n",
   1165				vp->id, win->data->name, actual_w);
   1166			actual_w -= 1;
   1167		}
   1168	}
   1169
   1170	if (afbc_en && actual_w % 4) {
   1171		drm_err(vop2->drm, "vp%d %s actual_w[%d] not 4 pixel aligned\n",
   1172			vp->id, win->data->name, actual_w);
   1173		actual_w = ALIGN_DOWN(actual_w, 4);
   1174	}
   1175
   1176	act_info = (actual_h - 1) << 16 | ((actual_w - 1) & 0xffff);
   1177	dsp_info = (dsp_h - 1) << 16 | ((dsp_w - 1) & 0xffff);
   1178
   1179	format = vop2_convert_format(fb->format->format);
   1180
   1181	drm_dbg(vop2->drm, "vp%d update %s[%dx%d->%dx%d@%dx%d] fmt[%p4cc_%s] addr[%pad]\n",
   1182		vp->id, win->data->name, actual_w, actual_h, dsp_w, dsp_h,
   1183		dest->x1, dest->y1,
   1184		&fb->format->format,
   1185		afbc_en ? "AFBC" : "", &yrgb_mst);
   1186
   1187	if (afbc_en) {
   1188		u32 stride;
   1189
   1190		/* the afbc superblock is 16 x 16 */
   1191		afbc_format = vop2_convert_afbc_format(fb->format->format);
   1192
   1193		/* Enable color transform for YTR */
   1194		if (fb->modifier & AFBC_FORMAT_MOD_YTR)
   1195			afbc_format |= (1 << 4);
   1196
   1197		afbc_tile_num = ALIGN(actual_w, 16) >> 4;
   1198
   1199		/*
   1200		 * AFBC pic_vir_width is count by pixel, this is different
   1201		 * with WIN_VIR_STRIDE.
   1202		 */
   1203		stride = (fb->pitches[0] << 3) / bpp;
   1204		if ((stride & 0x3f) && (xmirror || rotate_90 || rotate_270))
   1205			drm_err(vop2->drm, "vp%d %s stride[%d] not 64 pixel aligened\n",
   1206				vp->id, win->data->name, stride);
   1207
   1208		rb_swap = vop2_afbc_rb_swap(fb->format->format);
   1209		uv_swap = vop2_afbc_uv_swap(fb->format->format);
   1210		/*
   1211		 * This is a workaround for crazy IC design, Cluster
   1212		 * and Esmart/Smart use different format configuration map:
   1213		 * YUV420_10BIT: 0x10 for Cluster, 0x14 for Esmart/Smart.
   1214		 *
   1215		 * This is one thing we can make the convert simple:
   1216		 * AFBCD decode all the YUV data to YUV444. So we just
   1217		 * set all the yuv 10 bit to YUV444_10.
   1218		 */
   1219		if (fb->format->is_yuv && bpp == 10)
   1220			format = VOP2_CLUSTER_YUV444_10;
   1221
   1222		if (vop2_cluster_window(win))
   1223			vop2_win_write(win, VOP2_WIN_AFBC_ENABLE, 1);
   1224		vop2_win_write(win, VOP2_WIN_AFBC_FORMAT, afbc_format);
   1225		vop2_win_write(win, VOP2_WIN_AFBC_RB_SWAP, rb_swap);
   1226		vop2_win_write(win, VOP2_WIN_AFBC_UV_SWAP, uv_swap);
   1227		vop2_win_write(win, VOP2_WIN_AFBC_AUTO_GATING_EN, 0);
   1228		vop2_win_write(win, VOP2_WIN_AFBC_BLOCK_SPLIT_EN, 0);
   1229		if (pstate->rotation & (DRM_MODE_ROTATE_270 | DRM_MODE_ROTATE_90)) {
   1230			vop2_win_write(win, VOP2_WIN_AFBC_HALF_BLOCK_EN, 0);
   1231			transform_offset = vop2_afbc_transform_offset(pstate, false);
   1232		} else {
   1233			vop2_win_write(win, VOP2_WIN_AFBC_HALF_BLOCK_EN, 1);
   1234			transform_offset = vop2_afbc_transform_offset(pstate, true);
   1235		}
   1236		vop2_win_write(win, VOP2_WIN_AFBC_HDR_PTR, yrgb_mst);
   1237		vop2_win_write(win, VOP2_WIN_AFBC_PIC_SIZE, act_info);
   1238		vop2_win_write(win, VOP2_WIN_AFBC_TRANSFORM_OFFSET, transform_offset);
   1239		vop2_win_write(win, VOP2_WIN_AFBC_PIC_OFFSET, ((src->x1 >> 16) | src->y1));
   1240		vop2_win_write(win, VOP2_WIN_AFBC_DSP_OFFSET, (dest->x1 | (dest->y1 << 16)));
   1241		vop2_win_write(win, VOP2_WIN_AFBC_PIC_VIR_WIDTH, stride);
   1242		vop2_win_write(win, VOP2_WIN_AFBC_TILE_NUM, afbc_tile_num);
   1243		vop2_win_write(win, VOP2_WIN_XMIRROR, xmirror);
   1244		vop2_win_write(win, VOP2_WIN_AFBC_ROTATE_270, rotate_270);
   1245		vop2_win_write(win, VOP2_WIN_AFBC_ROTATE_90, rotate_90);
   1246	} else {
   1247		vop2_win_write(win, VOP2_WIN_YRGB_VIR, DIV_ROUND_UP(fb->pitches[0], 4));
   1248	}
   1249
   1250	vop2_win_write(win, VOP2_WIN_YMIRROR, ymirror);
   1251
   1252	if (rotate_90 || rotate_270) {
   1253		act_info = swahw32(act_info);
   1254		actual_w = drm_rect_height(src) >> 16;
   1255		actual_h = drm_rect_width(src) >> 16;
   1256	}
   1257
   1258	vop2_win_write(win, VOP2_WIN_FORMAT, format);
   1259	vop2_win_write(win, VOP2_WIN_YRGB_MST, yrgb_mst);
   1260
   1261	rb_swap = vop2_win_rb_swap(fb->format->format);
   1262	vop2_win_write(win, VOP2_WIN_RB_SWAP, rb_swap);
   1263	if (!vop2_cluster_window(win)) {
   1264		uv_swap = vop2_win_uv_swap(fb->format->format);
   1265		vop2_win_write(win, VOP2_WIN_UV_SWAP, uv_swap);
   1266	}
   1267
   1268	if (fb->format->is_yuv) {
   1269		vop2_win_write(win, VOP2_WIN_UV_VIR, DIV_ROUND_UP(fb->pitches[1], 4));
   1270		vop2_win_write(win, VOP2_WIN_UV_MST, uv_mst);
   1271	}
   1272
   1273	vop2_setup_scale(vop2, win, actual_w, actual_h, dsp_w, dsp_h, fb->format->format);
   1274	if (!vop2_cluster_window(win))
   1275		vop2_plane_setup_color_key(plane, 0);
   1276	vop2_win_write(win, VOP2_WIN_ACT_INFO, act_info);
   1277	vop2_win_write(win, VOP2_WIN_DSP_INFO, dsp_info);
   1278	vop2_win_write(win, VOP2_WIN_DSP_ST, dest->y1 << 16 | (dest->x1 & 0xffff));
   1279
   1280	vop2_setup_csc_mode(vp, win, pstate);
   1281
   1282	dither_up = vop2_win_dither_up(fb->format->format);
   1283	vop2_win_write(win, VOP2_WIN_DITHER_UP, dither_up);
   1284
   1285	vop2_win_write(win, VOP2_WIN_ENABLE, 1);
   1286
   1287	if (vop2_cluster_window(win)) {
   1288		int lb_mode = vop2_get_cluster_lb_mode(win, pstate);
   1289
   1290		vop2_win_write(win, VOP2_WIN_CLUSTER_LB_MODE, lb_mode);
   1291		vop2_win_write(win, VOP2_WIN_CLUSTER_ENABLE, 1);
   1292	}
   1293}
   1294
   1295static const struct drm_plane_helper_funcs vop2_plane_helper_funcs = {
   1296	.atomic_check = vop2_plane_atomic_check,
   1297	.atomic_update = vop2_plane_atomic_update,
   1298	.atomic_disable = vop2_plane_atomic_disable,
   1299};
   1300
   1301static const struct drm_plane_funcs vop2_plane_funcs = {
   1302	.update_plane	= drm_atomic_helper_update_plane,
   1303	.disable_plane	= drm_atomic_helper_disable_plane,
   1304	.destroy = drm_plane_cleanup,
   1305	.reset = drm_atomic_helper_plane_reset,
   1306	.atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
   1307	.atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
   1308	.format_mod_supported = rockchip_vop2_mod_supported,
   1309};
   1310
   1311static int vop2_crtc_enable_vblank(struct drm_crtc *crtc)
   1312{
   1313	struct vop2_video_port *vp = to_vop2_video_port(crtc);
   1314
   1315	vop2_crtc_enable_irq(vp, VP_INT_FS_FIELD);
   1316
   1317	return 0;
   1318}
   1319
   1320static void vop2_crtc_disable_vblank(struct drm_crtc *crtc)
   1321{
   1322	struct vop2_video_port *vp = to_vop2_video_port(crtc);
   1323
   1324	vop2_crtc_disable_irq(vp, VP_INT_FS_FIELD);
   1325}
   1326
   1327static bool vop2_crtc_mode_fixup(struct drm_crtc *crtc,
   1328				 const struct drm_display_mode *mode,
   1329				 struct drm_display_mode *adj_mode)
   1330{
   1331	drm_mode_set_crtcinfo(adj_mode, CRTC_INTERLACE_HALVE_V |
   1332					CRTC_STEREO_DOUBLE);
   1333
   1334	return true;
   1335}
   1336
   1337static void vop2_dither_setup(struct drm_crtc *crtc, u32 *dsp_ctrl)
   1338{
   1339	struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state);
   1340
   1341	switch (vcstate->bus_format) {
   1342	case MEDIA_BUS_FMT_RGB565_1X16:
   1343		*dsp_ctrl |= RK3568_VP_DSP_CTRL__DITHER_DOWN_EN;
   1344		break;
   1345	case MEDIA_BUS_FMT_RGB666_1X18:
   1346	case MEDIA_BUS_FMT_RGB666_1X24_CPADHI:
   1347	case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG:
   1348		*dsp_ctrl |= RK3568_VP_DSP_CTRL__DITHER_DOWN_EN;
   1349		*dsp_ctrl |= RGB888_TO_RGB666;
   1350		break;
   1351	case MEDIA_BUS_FMT_YUV8_1X24:
   1352	case MEDIA_BUS_FMT_UYYVYY8_0_5X24:
   1353		*dsp_ctrl |= RK3568_VP_DSP_CTRL__PRE_DITHER_DOWN_EN;
   1354		break;
   1355	default:
   1356		break;
   1357	}
   1358
   1359	if (vcstate->output_mode != ROCKCHIP_OUT_MODE_AAAA)
   1360		*dsp_ctrl |= RK3568_VP_DSP_CTRL__PRE_DITHER_DOWN_EN;
   1361
   1362	*dsp_ctrl |= FIELD_PREP(RK3568_VP_DSP_CTRL__DITHER_DOWN_SEL,
   1363				DITHER_DOWN_ALLEGRO);
   1364}
   1365
   1366static void vop2_post_config(struct drm_crtc *crtc)
   1367{
   1368	struct vop2_video_port *vp = to_vop2_video_port(crtc);
   1369	struct drm_display_mode *mode = &crtc->state->adjusted_mode;
   1370	u16 vtotal = mode->crtc_vtotal;
   1371	u16 hdisplay = mode->crtc_hdisplay;
   1372	u16 hact_st = mode->crtc_htotal - mode->crtc_hsync_start;
   1373	u16 vdisplay = mode->crtc_vdisplay;
   1374	u16 vact_st = mode->crtc_vtotal - mode->crtc_vsync_start;
   1375	u32 left_margin = 100, right_margin = 100;
   1376	u32 top_margin = 100, bottom_margin = 100;
   1377	u16 hsize = hdisplay * (left_margin + right_margin) / 200;
   1378	u16 vsize = vdisplay * (top_margin + bottom_margin) / 200;
   1379	u16 hact_end, vact_end;
   1380	u32 val;
   1381
   1382	vsize = rounddown(vsize, 2);
   1383	hsize = rounddown(hsize, 2);
   1384	hact_st += hdisplay * (100 - left_margin) / 200;
   1385	hact_end = hact_st + hsize;
   1386	val = hact_st << 16;
   1387	val |= hact_end;
   1388	vop2_vp_write(vp, RK3568_VP_POST_DSP_HACT_INFO, val);
   1389	vact_st += vdisplay * (100 - top_margin) / 200;
   1390	vact_end = vact_st + vsize;
   1391	val = vact_st << 16;
   1392	val |= vact_end;
   1393	vop2_vp_write(vp, RK3568_VP_POST_DSP_VACT_INFO, val);
   1394	val = scl_cal_scale2(vdisplay, vsize) << 16;
   1395	val |= scl_cal_scale2(hdisplay, hsize);
   1396	vop2_vp_write(vp, RK3568_VP_POST_SCL_FACTOR_YRGB, val);
   1397
   1398	val = 0;
   1399	if (hdisplay != hsize)
   1400		val |= RK3568_VP_POST_SCL_CTRL__HSCALEDOWN;
   1401	if (vdisplay != vsize)
   1402		val |= RK3568_VP_POST_SCL_CTRL__VSCALEDOWN;
   1403	vop2_vp_write(vp, RK3568_VP_POST_SCL_CTRL, val);
   1404
   1405	if (mode->flags & DRM_MODE_FLAG_INTERLACE) {
   1406		u16 vact_st_f1 = vtotal + vact_st + 1;
   1407		u16 vact_end_f1 = vact_st_f1 + vsize;
   1408
   1409		val = vact_st_f1 << 16 | vact_end_f1;
   1410		vop2_vp_write(vp, RK3568_VP_POST_DSP_VACT_INFO_F1, val);
   1411	}
   1412
   1413	vop2_vp_write(vp, RK3568_VP_DSP_BG, 0);
   1414}
   1415
   1416static void rk3568_set_intf_mux(struct vop2_video_port *vp, int id,
   1417				u32 polflags)
   1418{
   1419	struct vop2 *vop2 = vp->vop2;
   1420	u32 die, dip;
   1421
   1422	die = vop2_readl(vop2, RK3568_DSP_IF_EN);
   1423	dip = vop2_readl(vop2, RK3568_DSP_IF_POL);
   1424
   1425	switch (id) {
   1426	case ROCKCHIP_VOP2_EP_RGB0:
   1427		die &= ~RK3568_SYS_DSP_INFACE_EN_RGB_MUX;
   1428		die |= RK3568_SYS_DSP_INFACE_EN_RGB |
   1429			   FIELD_PREP(RK3568_SYS_DSP_INFACE_EN_RGB_MUX, vp->id);
   1430		if (polflags & POLFLAG_DCLK_INV)
   1431			regmap_write(vop2->grf, RK3568_GRF_VO_CON1, BIT(3 + 16) | BIT(3));
   1432		else
   1433			regmap_write(vop2->grf, RK3568_GRF_VO_CON1, BIT(3 + 16));
   1434		break;
   1435	case ROCKCHIP_VOP2_EP_HDMI0:
   1436		die &= ~RK3568_SYS_DSP_INFACE_EN_HDMI_MUX;
   1437		die |= RK3568_SYS_DSP_INFACE_EN_HDMI |
   1438			   FIELD_PREP(RK3568_SYS_DSP_INFACE_EN_HDMI_MUX, vp->id);
   1439		break;
   1440	case ROCKCHIP_VOP2_EP_EDP0:
   1441		die &= ~RK3568_SYS_DSP_INFACE_EN_EDP_MUX;
   1442		die |= RK3568_SYS_DSP_INFACE_EN_EDP |
   1443			   FIELD_PREP(RK3568_SYS_DSP_INFACE_EN_EDP_MUX, vp->id);
   1444		break;
   1445	case ROCKCHIP_VOP2_EP_MIPI0:
   1446		die &= ~RK3568_SYS_DSP_INFACE_EN_MIPI0_MUX;
   1447		die |= RK3568_SYS_DSP_INFACE_EN_MIPI0 |
   1448			   FIELD_PREP(RK3568_SYS_DSP_INFACE_EN_MIPI0_MUX, vp->id);
   1449		dip &= ~RK3568_DSP_IF_POL__MIPI_PIN_POL;
   1450		dip |= FIELD_PREP(RK3568_DSP_IF_POL__MIPI_PIN_POL, polflags);
   1451		break;
   1452	case ROCKCHIP_VOP2_EP_MIPI1:
   1453		die &= ~RK3568_SYS_DSP_INFACE_EN_MIPI1_MUX;
   1454		die |= RK3568_SYS_DSP_INFACE_EN_MIPI1 |
   1455			   FIELD_PREP(RK3568_SYS_DSP_INFACE_EN_MIPI1_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_LVDS0:
   1460		die &= ~RK3568_SYS_DSP_INFACE_EN_LVDS0_MUX;
   1461		die |= RK3568_SYS_DSP_INFACE_EN_LVDS0 |
   1462			   FIELD_PREP(RK3568_SYS_DSP_INFACE_EN_LVDS0_MUX, vp->id);
   1463		dip &= ~RK3568_DSP_IF_POL__RGB_LVDS_PIN_POL;
   1464		dip |= FIELD_PREP(RK3568_DSP_IF_POL__RGB_LVDS_PIN_POL, polflags);
   1465		break;
   1466	case ROCKCHIP_VOP2_EP_LVDS1:
   1467		die &= ~RK3568_SYS_DSP_INFACE_EN_LVDS1_MUX;
   1468		die |= RK3568_SYS_DSP_INFACE_EN_LVDS1 |
   1469			   FIELD_PREP(RK3568_SYS_DSP_INFACE_EN_LVDS1_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	default:
   1474		drm_err(vop2->drm, "Invalid interface id %d on vp%d\n", id, vp->id);
   1475		return;
   1476	};
   1477
   1478	dip |= RK3568_DSP_IF_POL__CFG_DONE_IMD;
   1479
   1480	vop2_writel(vop2, RK3568_DSP_IF_EN, die);
   1481	vop2_writel(vop2, RK3568_DSP_IF_POL, dip);
   1482}
   1483
   1484static int us_to_vertical_line(struct drm_display_mode *mode, int us)
   1485{
   1486	return us * mode->clock / mode->htotal / 1000;
   1487}
   1488
   1489static void vop2_crtc_atomic_enable(struct drm_crtc *crtc,
   1490				    struct drm_atomic_state *state)
   1491{
   1492	struct vop2_video_port *vp = to_vop2_video_port(crtc);
   1493	struct vop2 *vop2 = vp->vop2;
   1494	const struct vop2_data *vop2_data = vop2->data;
   1495	const struct vop2_video_port_data *vp_data = &vop2_data->vp[vp->id];
   1496	struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
   1497	struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state);
   1498	struct drm_display_mode *mode = &crtc->state->adjusted_mode;
   1499	unsigned long clock = mode->crtc_clock * 1000;
   1500	u16 hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start;
   1501	u16 hdisplay = mode->crtc_hdisplay;
   1502	u16 htotal = mode->crtc_htotal;
   1503	u16 hact_st = mode->crtc_htotal - mode->crtc_hsync_start;
   1504	u16 hact_end = hact_st + hdisplay;
   1505	u16 vdisplay = mode->crtc_vdisplay;
   1506	u16 vtotal = mode->crtc_vtotal;
   1507	u16 vsync_len = mode->crtc_vsync_end - mode->crtc_vsync_start;
   1508	u16 vact_st = mode->crtc_vtotal - mode->crtc_vsync_start;
   1509	u16 vact_end = vact_st + vdisplay;
   1510	u8 out_mode;
   1511	u32 dsp_ctrl = 0;
   1512	int act_end;
   1513	u32 val, polflags;
   1514	int ret;
   1515	struct drm_encoder *encoder;
   1516
   1517	drm_dbg(vop2->drm, "Update mode to %dx%d%s%d, type: %d for vp%d\n",
   1518		hdisplay, vdisplay, mode->flags & DRM_MODE_FLAG_INTERLACE ? "i" : "p",
   1519		drm_mode_vrefresh(mode), vcstate->output_type, vp->id);
   1520
   1521	vop2_lock(vop2);
   1522
   1523	ret = clk_prepare_enable(vp->dclk);
   1524	if (ret < 0) {
   1525		drm_err(vop2->drm, "failed to enable dclk for video port%d - %d\n",
   1526			vp->id, ret);
   1527		return;
   1528	}
   1529
   1530	if (!vop2->enable_count)
   1531		vop2_enable(vop2);
   1532
   1533	vop2->enable_count++;
   1534
   1535	vop2_crtc_enable_irq(vp, VP_INT_POST_BUF_EMPTY);
   1536
   1537	polflags = 0;
   1538	if (vcstate->bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE)
   1539		polflags |= POLFLAG_DCLK_INV;
   1540	if (mode->flags & DRM_MODE_FLAG_PHSYNC)
   1541		polflags |= BIT(HSYNC_POSITIVE);
   1542	if (mode->flags & DRM_MODE_FLAG_PVSYNC)
   1543		polflags |= BIT(VSYNC_POSITIVE);
   1544
   1545	drm_for_each_encoder_mask(encoder, crtc->dev, crtc_state->encoder_mask) {
   1546		struct rockchip_encoder *rkencoder = to_rockchip_encoder(encoder);
   1547
   1548		rk3568_set_intf_mux(vp, rkencoder->crtc_endpoint_id, polflags);
   1549	}
   1550
   1551	if (vcstate->output_mode == ROCKCHIP_OUT_MODE_AAAA &&
   1552	    !(vp_data->feature & VOP_FEATURE_OUTPUT_10BIT))
   1553		out_mode = ROCKCHIP_OUT_MODE_P888;
   1554	else
   1555		out_mode = vcstate->output_mode;
   1556
   1557	dsp_ctrl |= FIELD_PREP(RK3568_VP_DSP_CTRL__OUT_MODE, out_mode);
   1558
   1559	if (vop2_output_uv_swap(vcstate->bus_format, vcstate->output_mode))
   1560		dsp_ctrl |= RK3568_VP_DSP_CTRL__DSP_RB_SWAP;
   1561
   1562	if (is_yuv_output(vcstate->bus_format))
   1563		dsp_ctrl |= RK3568_VP_DSP_CTRL__POST_DSP_OUT_R2Y;
   1564
   1565	vop2_dither_setup(crtc, &dsp_ctrl);
   1566
   1567	vop2_vp_write(vp, RK3568_VP_DSP_HTOTAL_HS_END, (htotal << 16) | hsync_len);
   1568	val = hact_st << 16;
   1569	val |= hact_end;
   1570	vop2_vp_write(vp, RK3568_VP_DSP_HACT_ST_END, val);
   1571
   1572	val = vact_st << 16;
   1573	val |= vact_end;
   1574	vop2_vp_write(vp, RK3568_VP_DSP_VACT_ST_END, val);
   1575
   1576	if (mode->flags & DRM_MODE_FLAG_INTERLACE) {
   1577		u16 vact_st_f1 = vtotal + vact_st + 1;
   1578		u16 vact_end_f1 = vact_st_f1 + vdisplay;
   1579
   1580		val = vact_st_f1 << 16 | vact_end_f1;
   1581		vop2_vp_write(vp, RK3568_VP_DSP_VACT_ST_END_F1, val);
   1582
   1583		val = vtotal << 16 | (vtotal + vsync_len);
   1584		vop2_vp_write(vp, RK3568_VP_DSP_VS_ST_END_F1, val);
   1585		dsp_ctrl |= RK3568_VP_DSP_CTRL__DSP_INTERLACE;
   1586		dsp_ctrl |= RK3568_VP_DSP_CTRL__DSP_FILED_POL;
   1587		dsp_ctrl |= RK3568_VP_DSP_CTRL__P2I_EN;
   1588		vtotal += vtotal + 1;
   1589		act_end = vact_end_f1;
   1590	} else {
   1591		act_end = vact_end;
   1592	}
   1593
   1594	vop2_writel(vop2, RK3568_VP_LINE_FLAG(vp->id),
   1595		    (act_end - us_to_vertical_line(mode, 0)) << 16 | act_end);
   1596
   1597	vop2_vp_write(vp, RK3568_VP_DSP_VTOTAL_VS_END, vtotal << 16 | vsync_len);
   1598
   1599	if (mode->flags & DRM_MODE_FLAG_DBLCLK) {
   1600		dsp_ctrl |= RK3568_VP_DSP_CTRL__CORE_DCLK_DIV;
   1601		clock *= 2;
   1602	}
   1603
   1604	vop2_vp_write(vp, RK3568_VP_MIPI_CTRL, 0);
   1605
   1606	clk_set_rate(vp->dclk, clock);
   1607
   1608	vop2_post_config(crtc);
   1609
   1610	vop2_cfg_done(vp);
   1611
   1612	vop2_vp_write(vp, RK3568_VP_DSP_CTRL, dsp_ctrl);
   1613
   1614	drm_crtc_vblank_on(crtc);
   1615
   1616	vop2_unlock(vop2);
   1617}
   1618
   1619static int vop2_crtc_atomic_check(struct drm_crtc *crtc,
   1620				  struct drm_atomic_state *state)
   1621{
   1622	struct vop2_video_port *vp = to_vop2_video_port(crtc);
   1623	struct drm_plane *plane;
   1624	int nplanes = 0;
   1625	struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
   1626
   1627	drm_atomic_crtc_state_for_each_plane(plane, crtc_state)
   1628		nplanes++;
   1629
   1630	if (nplanes > vp->nlayers)
   1631		return -EINVAL;
   1632
   1633	return 0;
   1634}
   1635
   1636static bool is_opaque(u16 alpha)
   1637{
   1638	return (alpha >> 8) == 0xff;
   1639}
   1640
   1641static void vop2_parse_alpha(struct vop2_alpha_config *alpha_config,
   1642			     struct vop2_alpha *alpha)
   1643{
   1644	int src_glb_alpha_en = is_opaque(alpha_config->src_glb_alpha_value) ? 0 : 1;
   1645	int dst_glb_alpha_en = is_opaque(alpha_config->dst_glb_alpha_value) ? 0 : 1;
   1646	int src_color_mode = alpha_config->src_premulti_en ?
   1647				ALPHA_SRC_PRE_MUL : ALPHA_SRC_NO_PRE_MUL;
   1648	int dst_color_mode = alpha_config->dst_premulti_en ?
   1649				ALPHA_SRC_PRE_MUL : ALPHA_SRC_NO_PRE_MUL;
   1650
   1651	alpha->src_color_ctrl.val = 0;
   1652	alpha->dst_color_ctrl.val = 0;
   1653	alpha->src_alpha_ctrl.val = 0;
   1654	alpha->dst_alpha_ctrl.val = 0;
   1655
   1656	if (!alpha_config->src_pixel_alpha_en)
   1657		alpha->src_color_ctrl.bits.blend_mode = ALPHA_GLOBAL;
   1658	else if (alpha_config->src_pixel_alpha_en && !src_glb_alpha_en)
   1659		alpha->src_color_ctrl.bits.blend_mode = ALPHA_PER_PIX;
   1660	else
   1661		alpha->src_color_ctrl.bits.blend_mode = ALPHA_PER_PIX_GLOBAL;
   1662
   1663	alpha->src_color_ctrl.bits.alpha_en = 1;
   1664
   1665	if (alpha->src_color_ctrl.bits.blend_mode == ALPHA_GLOBAL) {
   1666		alpha->src_color_ctrl.bits.color_mode = src_color_mode;
   1667		alpha->src_color_ctrl.bits.factor_mode = SRC_FAC_ALPHA_SRC_GLOBAL;
   1668	} else if (alpha->src_color_ctrl.bits.blend_mode == ALPHA_PER_PIX) {
   1669		alpha->src_color_ctrl.bits.color_mode = src_color_mode;
   1670		alpha->src_color_ctrl.bits.factor_mode = SRC_FAC_ALPHA_ONE;
   1671	} else {
   1672		alpha->src_color_ctrl.bits.color_mode = ALPHA_SRC_PRE_MUL;
   1673		alpha->src_color_ctrl.bits.factor_mode = SRC_FAC_ALPHA_SRC_GLOBAL;
   1674	}
   1675	alpha->src_color_ctrl.bits.glb_alpha = alpha_config->src_glb_alpha_value >> 8;
   1676	alpha->src_color_ctrl.bits.alpha_mode = ALPHA_STRAIGHT;
   1677	alpha->src_color_ctrl.bits.alpha_cal_mode = ALPHA_SATURATION;
   1678
   1679	alpha->dst_color_ctrl.bits.alpha_mode = ALPHA_STRAIGHT;
   1680	alpha->dst_color_ctrl.bits.alpha_cal_mode = ALPHA_SATURATION;
   1681	alpha->dst_color_ctrl.bits.blend_mode = ALPHA_GLOBAL;
   1682	alpha->dst_color_ctrl.bits.glb_alpha = alpha_config->dst_glb_alpha_value >> 8;
   1683	alpha->dst_color_ctrl.bits.color_mode = dst_color_mode;
   1684	alpha->dst_color_ctrl.bits.factor_mode = ALPHA_SRC_INVERSE;
   1685
   1686	alpha->src_alpha_ctrl.bits.alpha_mode = ALPHA_STRAIGHT;
   1687	alpha->src_alpha_ctrl.bits.blend_mode = alpha->src_color_ctrl.bits.blend_mode;
   1688	alpha->src_alpha_ctrl.bits.alpha_cal_mode = ALPHA_SATURATION;
   1689	alpha->src_alpha_ctrl.bits.factor_mode = ALPHA_ONE;
   1690
   1691	alpha->dst_alpha_ctrl.bits.alpha_mode = ALPHA_STRAIGHT;
   1692	if (alpha_config->dst_pixel_alpha_en && !dst_glb_alpha_en)
   1693		alpha->dst_alpha_ctrl.bits.blend_mode = ALPHA_PER_PIX;
   1694	else
   1695		alpha->dst_alpha_ctrl.bits.blend_mode = ALPHA_PER_PIX_GLOBAL;
   1696	alpha->dst_alpha_ctrl.bits.alpha_cal_mode = ALPHA_NO_SATURATION;
   1697	alpha->dst_alpha_ctrl.bits.factor_mode = ALPHA_SRC_INVERSE;
   1698}
   1699
   1700static int vop2_find_start_mixer_id_for_vp(struct vop2 *vop2, u8 port_id)
   1701{
   1702	struct vop2_video_port *vp;
   1703	int used_layer = 0;
   1704	int i;
   1705
   1706	for (i = 0; i < port_id; i++) {
   1707		vp = &vop2->vps[i];
   1708		used_layer += hweight32(vp->win_mask);
   1709	}
   1710
   1711	return used_layer;
   1712}
   1713
   1714static void vop2_setup_cluster_alpha(struct vop2 *vop2, struct vop2_win *main_win)
   1715{
   1716	u32 offset = (main_win->data->phys_id * 0x10);
   1717	struct vop2_alpha_config alpha_config;
   1718	struct vop2_alpha alpha;
   1719	struct drm_plane_state *bottom_win_pstate;
   1720	bool src_pixel_alpha_en = false;
   1721	u16 src_glb_alpha_val, dst_glb_alpha_val;
   1722	bool premulti_en = false;
   1723	bool swap = false;
   1724
   1725	/* At one win mode, win0 is dst/bottom win, and win1 is a all zero src/top win */
   1726	bottom_win_pstate = main_win->base.state;
   1727	src_glb_alpha_val = 0;
   1728	dst_glb_alpha_val = main_win->base.state->alpha;
   1729
   1730	if (!bottom_win_pstate->fb)
   1731		return;
   1732
   1733	alpha_config.src_premulti_en = premulti_en;
   1734	alpha_config.dst_premulti_en = false;
   1735	alpha_config.src_pixel_alpha_en = src_pixel_alpha_en;
   1736	alpha_config.dst_pixel_alpha_en = true; /* alpha value need transfer to next mix */
   1737	alpha_config.src_glb_alpha_value = src_glb_alpha_val;
   1738	alpha_config.dst_glb_alpha_value = dst_glb_alpha_val;
   1739	vop2_parse_alpha(&alpha_config, &alpha);
   1740
   1741	alpha.src_color_ctrl.bits.src_dst_swap = swap;
   1742	vop2_writel(vop2, RK3568_CLUSTER0_MIX_SRC_COLOR_CTRL + offset,
   1743		    alpha.src_color_ctrl.val);
   1744	vop2_writel(vop2, RK3568_CLUSTER0_MIX_DST_COLOR_CTRL + offset,
   1745		    alpha.dst_color_ctrl.val);
   1746	vop2_writel(vop2, RK3568_CLUSTER0_MIX_SRC_ALPHA_CTRL + offset,
   1747		    alpha.src_alpha_ctrl.val);
   1748	vop2_writel(vop2, RK3568_CLUSTER0_MIX_DST_ALPHA_CTRL + offset,
   1749		    alpha.dst_alpha_ctrl.val);
   1750}
   1751
   1752static void vop2_setup_alpha(struct vop2_video_port *vp)
   1753{
   1754	struct vop2 *vop2 = vp->vop2;
   1755	struct drm_framebuffer *fb;
   1756	struct vop2_alpha_config alpha_config;
   1757	struct vop2_alpha alpha;
   1758	struct drm_plane *plane;
   1759	int pixel_alpha_en;
   1760	int premulti_en, gpremulti_en = 0;
   1761	int mixer_id;
   1762	u32 offset;
   1763	bool bottom_layer_alpha_en = false;
   1764	u32 dst_global_alpha = DRM_BLEND_ALPHA_OPAQUE;
   1765
   1766	mixer_id = vop2_find_start_mixer_id_for_vp(vop2, vp->id);
   1767	alpha_config.dst_pixel_alpha_en = true; /* alpha value need transfer to next mix */
   1768
   1769	drm_atomic_crtc_for_each_plane(plane, &vp->crtc) {
   1770		struct vop2_win *win = to_vop2_win(plane);
   1771
   1772		if (plane->state->normalized_zpos == 0 &&
   1773		    !is_opaque(plane->state->alpha) &&
   1774		    !vop2_cluster_window(win)) {
   1775			/*
   1776			 * If bottom layer have global alpha effect [except cluster layer,
   1777			 * because cluster have deal with bottom layer global alpha value
   1778			 * at cluster mix], bottom layer mix need deal with global alpha.
   1779			 */
   1780			bottom_layer_alpha_en = true;
   1781			dst_global_alpha = plane->state->alpha;
   1782		}
   1783	}
   1784
   1785	drm_atomic_crtc_for_each_plane(plane, &vp->crtc) {
   1786		struct vop2_win *win = to_vop2_win(plane);
   1787		int zpos = plane->state->normalized_zpos;
   1788
   1789		if (plane->state->pixel_blend_mode == DRM_MODE_BLEND_PREMULTI)
   1790			premulti_en = 1;
   1791		else
   1792			premulti_en = 0;
   1793
   1794		plane = &win->base;
   1795		fb = plane->state->fb;
   1796
   1797		pixel_alpha_en = fb->format->has_alpha;
   1798
   1799		alpha_config.src_premulti_en = premulti_en;
   1800
   1801		if (bottom_layer_alpha_en && zpos == 1) {
   1802			gpremulti_en = premulti_en;
   1803			/* Cd = Cs + (1 - As) * Cd * Agd */
   1804			alpha_config.dst_premulti_en = false;
   1805			alpha_config.src_pixel_alpha_en = pixel_alpha_en;
   1806			alpha_config.src_glb_alpha_value = plane->state->alpha;
   1807			alpha_config.dst_glb_alpha_value = dst_global_alpha;
   1808		} else if (vop2_cluster_window(win)) {
   1809			/* Mix output data only have pixel alpha */
   1810			alpha_config.dst_premulti_en = true;
   1811			alpha_config.src_pixel_alpha_en = true;
   1812			alpha_config.src_glb_alpha_value = DRM_BLEND_ALPHA_OPAQUE;
   1813			alpha_config.dst_glb_alpha_value = DRM_BLEND_ALPHA_OPAQUE;
   1814		} else {
   1815			/* Cd = Cs + (1 - As) * Cd */
   1816			alpha_config.dst_premulti_en = true;
   1817			alpha_config.src_pixel_alpha_en = pixel_alpha_en;
   1818			alpha_config.src_glb_alpha_value = plane->state->alpha;
   1819			alpha_config.dst_glb_alpha_value = DRM_BLEND_ALPHA_OPAQUE;
   1820		}
   1821
   1822		vop2_parse_alpha(&alpha_config, &alpha);
   1823
   1824		offset = (mixer_id + zpos - 1) * 0x10;
   1825		vop2_writel(vop2, RK3568_MIX0_SRC_COLOR_CTRL + offset,
   1826			    alpha.src_color_ctrl.val);
   1827		vop2_writel(vop2, RK3568_MIX0_DST_COLOR_CTRL + offset,
   1828			    alpha.dst_color_ctrl.val);
   1829		vop2_writel(vop2, RK3568_MIX0_SRC_ALPHA_CTRL + offset,
   1830			    alpha.src_alpha_ctrl.val);
   1831		vop2_writel(vop2, RK3568_MIX0_DST_ALPHA_CTRL + offset,
   1832			    alpha.dst_alpha_ctrl.val);
   1833	}
   1834
   1835	if (vp->id == 0) {
   1836		if (bottom_layer_alpha_en) {
   1837			/* Transfer pixel alpha to hdr mix */
   1838			alpha_config.src_premulti_en = gpremulti_en;
   1839			alpha_config.dst_premulti_en = true;
   1840			alpha_config.src_pixel_alpha_en = true;
   1841			alpha_config.src_glb_alpha_value = DRM_BLEND_ALPHA_OPAQUE;
   1842			alpha_config.dst_glb_alpha_value = DRM_BLEND_ALPHA_OPAQUE;
   1843			vop2_parse_alpha(&alpha_config, &alpha);
   1844
   1845			vop2_writel(vop2, RK3568_HDR0_SRC_COLOR_CTRL,
   1846				    alpha.src_color_ctrl.val);
   1847			vop2_writel(vop2, RK3568_HDR0_DST_COLOR_CTRL,
   1848				    alpha.dst_color_ctrl.val);
   1849			vop2_writel(vop2, RK3568_HDR0_SRC_ALPHA_CTRL,
   1850				    alpha.src_alpha_ctrl.val);
   1851			vop2_writel(vop2, RK3568_HDR0_DST_ALPHA_CTRL,
   1852				    alpha.dst_alpha_ctrl.val);
   1853		} else {
   1854			vop2_writel(vop2, RK3568_HDR0_SRC_COLOR_CTRL, 0);
   1855		}
   1856	}
   1857}
   1858
   1859static void vop2_setup_layer_mixer(struct vop2_video_port *vp)
   1860{
   1861	struct vop2 *vop2 = vp->vop2;
   1862	struct drm_plane *plane;
   1863	u32 layer_sel = 0;
   1864	u32 port_sel;
   1865	unsigned int nlayer, ofs;
   1866	struct drm_display_mode *adjusted_mode;
   1867	u16 hsync_len;
   1868	u16 hdisplay;
   1869	u32 bg_dly;
   1870	u32 pre_scan_dly;
   1871	int i;
   1872	struct vop2_video_port *vp0 = &vop2->vps[0];
   1873	struct vop2_video_port *vp1 = &vop2->vps[1];
   1874	struct vop2_video_port *vp2 = &vop2->vps[2];
   1875
   1876	adjusted_mode = &vp->crtc.state->adjusted_mode;
   1877	hsync_len = adjusted_mode->crtc_hsync_end - adjusted_mode->crtc_hsync_start;
   1878	hdisplay = adjusted_mode->crtc_hdisplay;
   1879
   1880	bg_dly = vp->data->pre_scan_max_dly[3];
   1881	vop2_writel(vop2, RK3568_VP_BG_MIX_CTRL(vp->id),
   1882		    FIELD_PREP(RK3568_VP_BG_MIX_CTRL__BG_DLY, bg_dly));
   1883
   1884	pre_scan_dly = ((bg_dly + (hdisplay >> 1) - 1) << 16) | hsync_len;
   1885	vop2_vp_write(vp, RK3568_VP_PRE_SCAN_HTIMING, pre_scan_dly);
   1886
   1887	vop2_writel(vop2, RK3568_OVL_CTRL, 0);
   1888	port_sel = vop2_readl(vop2, RK3568_OVL_PORT_SEL);
   1889	port_sel &= RK3568_OVL_PORT_SEL__SEL_PORT;
   1890
   1891	if (vp0->nlayers)
   1892		port_sel |= FIELD_PREP(RK3568_OVL_PORT_SET__PORT0_MUX,
   1893				     vp0->nlayers - 1);
   1894	else
   1895		port_sel |= FIELD_PREP(RK3568_OVL_PORT_SET__PORT0_MUX, 8);
   1896
   1897	if (vp1->nlayers)
   1898		port_sel |= FIELD_PREP(RK3568_OVL_PORT_SET__PORT1_MUX,
   1899				     (vp0->nlayers + vp1->nlayers - 1));
   1900	else
   1901		port_sel |= FIELD_PREP(RK3568_OVL_PORT_SET__PORT1_MUX, 8);
   1902
   1903	if (vp2->nlayers)
   1904		port_sel |= FIELD_PREP(RK3568_OVL_PORT_SET__PORT2_MUX,
   1905			(vp2->nlayers + vp1->nlayers + vp0->nlayers - 1));
   1906	else
   1907		port_sel |= FIELD_PREP(RK3568_OVL_PORT_SET__PORT1_MUX, 8);
   1908
   1909	layer_sel = vop2_readl(vop2, RK3568_OVL_LAYER_SEL);
   1910
   1911	ofs = 0;
   1912	for (i = 0; i < vp->id; i++)
   1913		ofs += vop2->vps[i].nlayers;
   1914
   1915	nlayer = 0;
   1916	drm_atomic_crtc_for_each_plane(plane, &vp->crtc) {
   1917		struct vop2_win *win = to_vop2_win(plane);
   1918
   1919		switch (win->data->phys_id) {
   1920		case ROCKCHIP_VOP2_CLUSTER0:
   1921			port_sel &= ~RK3568_OVL_PORT_SEL__CLUSTER0;
   1922			port_sel |= FIELD_PREP(RK3568_OVL_PORT_SEL__CLUSTER0, vp->id);
   1923			break;
   1924		case ROCKCHIP_VOP2_CLUSTER1:
   1925			port_sel &= ~RK3568_OVL_PORT_SEL__CLUSTER1;
   1926			port_sel |= FIELD_PREP(RK3568_OVL_PORT_SEL__CLUSTER1, vp->id);
   1927			break;
   1928		case ROCKCHIP_VOP2_ESMART0:
   1929			port_sel &= ~RK3568_OVL_PORT_SEL__ESMART0;
   1930			port_sel |= FIELD_PREP(RK3568_OVL_PORT_SEL__ESMART0, vp->id);
   1931			break;
   1932		case ROCKCHIP_VOP2_ESMART1:
   1933			port_sel &= ~RK3568_OVL_PORT_SEL__ESMART1;
   1934			port_sel |= FIELD_PREP(RK3568_OVL_PORT_SEL__ESMART1, vp->id);
   1935			break;
   1936		case ROCKCHIP_VOP2_SMART0:
   1937			port_sel &= ~RK3568_OVL_PORT_SEL__SMART0;
   1938			port_sel |= FIELD_PREP(RK3568_OVL_PORT_SEL__SMART0, vp->id);
   1939			break;
   1940		case ROCKCHIP_VOP2_SMART1:
   1941			port_sel &= ~RK3568_OVL_PORT_SEL__SMART1;
   1942			port_sel |= FIELD_PREP(RK3568_OVL_PORT_SEL__SMART1, vp->id);
   1943			break;
   1944		}
   1945
   1946		layer_sel &= ~RK3568_OVL_LAYER_SEL__LAYER(plane->state->normalized_zpos + ofs,
   1947							  0x7);
   1948		layer_sel |= RK3568_OVL_LAYER_SEL__LAYER(plane->state->normalized_zpos + ofs,
   1949							 win->data->layer_sel_id);
   1950		nlayer++;
   1951	}
   1952
   1953	/* configure unused layers to 0x5 (reserved) */
   1954	for (; nlayer < vp->nlayers; nlayer++) {
   1955		layer_sel &= ~RK3568_OVL_LAYER_SEL__LAYER(nlayer + ofs, 0x7);
   1956		layer_sel |= RK3568_OVL_LAYER_SEL__LAYER(nlayer + ofs, 5);
   1957	}
   1958
   1959	vop2_writel(vop2, RK3568_OVL_LAYER_SEL, layer_sel);
   1960	vop2_writel(vop2, RK3568_OVL_PORT_SEL, port_sel);
   1961	vop2_writel(vop2, RK3568_OVL_CTRL, RK3568_OVL_CTRL__LAYERSEL_REGDONE_IMD);
   1962}
   1963
   1964static void vop2_setup_dly_for_windows(struct vop2 *vop2)
   1965{
   1966	struct vop2_win *win;
   1967	int i = 0;
   1968	u32 cdly = 0, sdly = 0;
   1969
   1970	for (i = 0; i < vop2->data->win_size; i++) {
   1971		u32 dly;
   1972
   1973		win = &vop2->win[i];
   1974		dly = win->delay;
   1975
   1976		switch (win->data->phys_id) {
   1977		case ROCKCHIP_VOP2_CLUSTER0:
   1978			cdly |= FIELD_PREP(RK3568_CLUSTER_DLY_NUM__CLUSTER0_0, dly);
   1979			cdly |= FIELD_PREP(RK3568_CLUSTER_DLY_NUM__CLUSTER0_1, dly);
   1980			break;
   1981		case ROCKCHIP_VOP2_CLUSTER1:
   1982			cdly |= FIELD_PREP(RK3568_CLUSTER_DLY_NUM__CLUSTER1_0, dly);
   1983			cdly |= FIELD_PREP(RK3568_CLUSTER_DLY_NUM__CLUSTER1_1, dly);
   1984			break;
   1985		case ROCKCHIP_VOP2_ESMART0:
   1986			sdly |= FIELD_PREP(RK3568_SMART_DLY_NUM__ESMART0, dly);
   1987			break;
   1988		case ROCKCHIP_VOP2_ESMART1:
   1989			sdly |= FIELD_PREP(RK3568_SMART_DLY_NUM__ESMART1, dly);
   1990			break;
   1991		case ROCKCHIP_VOP2_SMART0:
   1992			sdly |= FIELD_PREP(RK3568_SMART_DLY_NUM__SMART0, dly);
   1993			break;
   1994		case ROCKCHIP_VOP2_SMART1:
   1995			sdly |= FIELD_PREP(RK3568_SMART_DLY_NUM__SMART1, dly);
   1996			break;
   1997		}
   1998	}
   1999
   2000	vop2_writel(vop2, RK3568_CLUSTER_DLY_NUM, cdly);
   2001	vop2_writel(vop2, RK3568_SMART_DLY_NUM, sdly);
   2002}
   2003
   2004static void vop2_crtc_atomic_begin(struct drm_crtc *crtc,
   2005				   struct drm_atomic_state *state)
   2006{
   2007	struct vop2_video_port *vp = to_vop2_video_port(crtc);
   2008	struct vop2 *vop2 = vp->vop2;
   2009	struct drm_plane *plane;
   2010
   2011	vp->win_mask = 0;
   2012
   2013	drm_atomic_crtc_for_each_plane(plane, crtc) {
   2014		struct vop2_win *win = to_vop2_win(plane);
   2015
   2016		win->delay = win->data->dly[VOP2_DLY_MODE_DEFAULT];
   2017
   2018		vp->win_mask |= BIT(win->data->phys_id);
   2019
   2020		if (vop2_cluster_window(win))
   2021			vop2_setup_cluster_alpha(vop2, win);
   2022	}
   2023
   2024	if (!vp->win_mask)
   2025		return;
   2026
   2027	vop2_setup_layer_mixer(vp);
   2028	vop2_setup_alpha(vp);
   2029	vop2_setup_dly_for_windows(vop2);
   2030}
   2031
   2032static void vop2_crtc_atomic_flush(struct drm_crtc *crtc,
   2033				   struct drm_atomic_state *state)
   2034{
   2035	struct vop2_video_port *vp = to_vop2_video_port(crtc);
   2036
   2037	vop2_post_config(crtc);
   2038
   2039	vop2_cfg_done(vp);
   2040
   2041	spin_lock_irq(&crtc->dev->event_lock);
   2042
   2043	if (crtc->state->event) {
   2044		WARN_ON(drm_crtc_vblank_get(crtc));
   2045		vp->event = crtc->state->event;
   2046		crtc->state->event = NULL;
   2047	}
   2048
   2049	spin_unlock_irq(&crtc->dev->event_lock);
   2050}
   2051
   2052static const struct drm_crtc_helper_funcs vop2_crtc_helper_funcs = {
   2053	.mode_fixup = vop2_crtc_mode_fixup,
   2054	.atomic_check = vop2_crtc_atomic_check,
   2055	.atomic_begin = vop2_crtc_atomic_begin,
   2056	.atomic_flush = vop2_crtc_atomic_flush,
   2057	.atomic_enable = vop2_crtc_atomic_enable,
   2058	.atomic_disable = vop2_crtc_atomic_disable,
   2059};
   2060
   2061static void vop2_crtc_reset(struct drm_crtc *crtc)
   2062{
   2063	struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state);
   2064
   2065	if (crtc->state) {
   2066		__drm_atomic_helper_crtc_destroy_state(crtc->state);
   2067		kfree(vcstate);
   2068	}
   2069
   2070	vcstate = kzalloc(sizeof(*vcstate), GFP_KERNEL);
   2071	if (!vcstate)
   2072		return;
   2073
   2074	crtc->state = &vcstate->base;
   2075	crtc->state->crtc = crtc;
   2076}
   2077
   2078static struct drm_crtc_state *vop2_crtc_duplicate_state(struct drm_crtc *crtc)
   2079{
   2080	struct rockchip_crtc_state *vcstate, *old_vcstate;
   2081
   2082	old_vcstate = to_rockchip_crtc_state(crtc->state);
   2083
   2084	vcstate = kmemdup(old_vcstate, sizeof(*old_vcstate), GFP_KERNEL);
   2085	if (!vcstate)
   2086		return NULL;
   2087
   2088	__drm_atomic_helper_crtc_duplicate_state(crtc, &vcstate->base);
   2089
   2090	return &vcstate->base;
   2091}
   2092
   2093static void vop2_crtc_destroy_state(struct drm_crtc *crtc,
   2094				    struct drm_crtc_state *state)
   2095{
   2096	struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(state);
   2097
   2098	__drm_atomic_helper_crtc_destroy_state(&vcstate->base);
   2099	kfree(vcstate);
   2100}
   2101
   2102static const struct drm_crtc_funcs vop2_crtc_funcs = {
   2103	.set_config = drm_atomic_helper_set_config,
   2104	.page_flip = drm_atomic_helper_page_flip,
   2105	.destroy = drm_crtc_cleanup,
   2106	.reset = vop2_crtc_reset,
   2107	.atomic_duplicate_state = vop2_crtc_duplicate_state,
   2108	.atomic_destroy_state = vop2_crtc_destroy_state,
   2109	.enable_vblank = vop2_crtc_enable_vblank,
   2110	.disable_vblank = vop2_crtc_disable_vblank,
   2111};
   2112
   2113static irqreturn_t vop2_isr(int irq, void *data)
   2114{
   2115	struct vop2 *vop2 = data;
   2116	const struct vop2_data *vop2_data = vop2->data;
   2117	u32 axi_irqs[VOP2_SYS_AXI_BUS_NUM];
   2118	int ret = IRQ_NONE;
   2119	int i;
   2120
   2121	/*
   2122	 * The irq is shared with the iommu. If the runtime-pm state of the
   2123	 * vop2-device is disabled the irq has to be targeted at the iommu.
   2124	 */
   2125	if (!pm_runtime_get_if_in_use(vop2->dev))
   2126		return IRQ_NONE;
   2127
   2128	for (i = 0; i < vop2_data->nr_vps; i++) {
   2129		struct vop2_video_port *vp = &vop2->vps[i];
   2130		struct drm_crtc *crtc = &vp->crtc;
   2131		u32 irqs;
   2132
   2133		irqs = vop2_readl(vop2, RK3568_VP_INT_STATUS(vp->id));
   2134		vop2_writel(vop2, RK3568_VP_INT_CLR(vp->id), irqs << 16 | irqs);
   2135
   2136		if (irqs & VP_INT_DSP_HOLD_VALID) {
   2137			complete(&vp->dsp_hold_completion);
   2138			ret = IRQ_HANDLED;
   2139		}
   2140
   2141		if (irqs & VP_INT_FS_FIELD) {
   2142			drm_crtc_handle_vblank(crtc);
   2143			spin_lock(&crtc->dev->event_lock);
   2144			if (vp->event) {
   2145				u32 val = vop2_readl(vop2, RK3568_REG_CFG_DONE);
   2146
   2147				if (!(val & BIT(vp->id))) {
   2148					drm_crtc_send_vblank_event(crtc, vp->event);
   2149					vp->event = NULL;
   2150					drm_crtc_vblank_put(crtc);
   2151				}
   2152			}
   2153			spin_unlock(&crtc->dev->event_lock);
   2154
   2155			ret = IRQ_HANDLED;
   2156		}
   2157
   2158		if (irqs & VP_INT_POST_BUF_EMPTY) {
   2159			drm_err_ratelimited(vop2->drm,
   2160					    "POST_BUF_EMPTY irq err at vp%d\n",
   2161					    vp->id);
   2162			ret = IRQ_HANDLED;
   2163		}
   2164	}
   2165
   2166	axi_irqs[0] = vop2_readl(vop2, RK3568_SYS0_INT_STATUS);
   2167	vop2_writel(vop2, RK3568_SYS0_INT_CLR, axi_irqs[0] << 16 | axi_irqs[0]);
   2168	axi_irqs[1] = vop2_readl(vop2, RK3568_SYS1_INT_STATUS);
   2169	vop2_writel(vop2, RK3568_SYS1_INT_CLR, axi_irqs[1] << 16 | axi_irqs[1]);
   2170
   2171	for (i = 0; i < ARRAY_SIZE(axi_irqs); i++) {
   2172		if (axi_irqs[i] & VOP2_INT_BUS_ERRPR) {
   2173			drm_err_ratelimited(vop2->drm, "BUS_ERROR irq err\n");
   2174			ret = IRQ_HANDLED;
   2175		}
   2176	}
   2177
   2178	pm_runtime_put(vop2->dev);
   2179
   2180	return ret;
   2181}
   2182
   2183static int vop2_plane_init(struct vop2 *vop2, struct vop2_win *win,
   2184			   unsigned long possible_crtcs)
   2185{
   2186	const struct vop2_win_data *win_data = win->data;
   2187	unsigned int blend_caps = BIT(DRM_MODE_BLEND_PIXEL_NONE) |
   2188				  BIT(DRM_MODE_BLEND_PREMULTI) |
   2189				  BIT(DRM_MODE_BLEND_COVERAGE);
   2190	int ret;
   2191
   2192	ret = drm_universal_plane_init(vop2->drm, &win->base, possible_crtcs,
   2193				       &vop2_plane_funcs, win_data->formats,
   2194				       win_data->nformats,
   2195				       win_data->format_modifiers,
   2196				       win->type, win_data->name);
   2197	if (ret) {
   2198		drm_err(vop2->drm, "failed to initialize plane %d\n", ret);
   2199		return ret;
   2200	}
   2201
   2202	drm_plane_helper_add(&win->base, &vop2_plane_helper_funcs);
   2203
   2204	if (win->data->supported_rotations)
   2205		drm_plane_create_rotation_property(&win->base, DRM_MODE_ROTATE_0,
   2206						   DRM_MODE_ROTATE_0 |
   2207						   win->data->supported_rotations);
   2208	drm_plane_create_alpha_property(&win->base);
   2209	drm_plane_create_blend_mode_property(&win->base, blend_caps);
   2210	drm_plane_create_zpos_property(&win->base, win->win_id, 0,
   2211				       vop2->registered_num_wins - 1);
   2212
   2213	return 0;
   2214}
   2215
   2216static struct vop2_video_port *find_vp_without_primary(struct vop2 *vop2)
   2217{
   2218	int i;
   2219
   2220	for (i = 0; i < vop2->data->nr_vps; i++) {
   2221		struct vop2_video_port *vp = &vop2->vps[i];
   2222
   2223		if (!vp->crtc.port)
   2224			continue;
   2225		if (vp->primary_plane)
   2226			continue;
   2227
   2228		return vp;
   2229	}
   2230
   2231	return NULL;
   2232}
   2233
   2234#define NR_LAYERS 6
   2235
   2236static int vop2_create_crtc(struct vop2 *vop2)
   2237{
   2238	const struct vop2_data *vop2_data = vop2->data;
   2239	struct drm_device *drm = vop2->drm;
   2240	struct device *dev = vop2->dev;
   2241	struct drm_plane *plane;
   2242	struct device_node *port;
   2243	struct vop2_video_port *vp;
   2244	int i, nvp, nvps = 0;
   2245	int ret;
   2246
   2247	for (i = 0; i < vop2_data->nr_vps; i++) {
   2248		const struct vop2_video_port_data *vp_data;
   2249		struct device_node *np;
   2250		char dclk_name[9];
   2251
   2252		vp_data = &vop2_data->vp[i];
   2253		vp = &vop2->vps[i];
   2254		vp->vop2 = vop2;
   2255		vp->id = vp_data->id;
   2256		vp->regs = vp_data->regs;
   2257		vp->data = vp_data;
   2258
   2259		snprintf(dclk_name, sizeof(dclk_name), "dclk_vp%d", vp->id);
   2260		vp->dclk = devm_clk_get(vop2->dev, dclk_name);
   2261		if (IS_ERR(vp->dclk)) {
   2262			drm_err(vop2->drm, "failed to get %s\n", dclk_name);
   2263			return PTR_ERR(vp->dclk);
   2264		}
   2265
   2266		np = of_graph_get_remote_node(dev->of_node, i, -1);
   2267		if (!np) {
   2268			drm_dbg(vop2->drm, "%s: No remote for vp%d\n", __func__, i);
   2269			continue;
   2270		}
   2271		of_node_put(np);
   2272
   2273		port = of_graph_get_port_by_id(dev->of_node, i);
   2274		if (!port) {
   2275			drm_err(vop2->drm, "no port node found for video_port%d\n", i);
   2276			return -ENOENT;
   2277		}
   2278
   2279		vp->crtc.port = port;
   2280		nvps++;
   2281	}
   2282
   2283	nvp = 0;
   2284	for (i = 0; i < vop2->registered_num_wins; i++) {
   2285		struct vop2_win *win = &vop2->win[i];
   2286		u32 possible_crtcs;
   2287
   2288		if (vop2->data->soc_id == 3566) {
   2289			/*
   2290			 * On RK3566 these windows don't have an independent
   2291			 * framebuffer. They share the framebuffer with smart0,
   2292			 * esmart0 and cluster0 respectively.
   2293			 */
   2294			switch (win->data->phys_id) {
   2295			case ROCKCHIP_VOP2_SMART1:
   2296			case ROCKCHIP_VOP2_ESMART1:
   2297			case ROCKCHIP_VOP2_CLUSTER1:
   2298				continue;
   2299			}
   2300		}
   2301
   2302		if (win->type == DRM_PLANE_TYPE_PRIMARY) {
   2303			vp = find_vp_without_primary(vop2);
   2304			if (vp) {
   2305				possible_crtcs = BIT(nvp);
   2306				vp->primary_plane = win;
   2307				nvp++;
   2308			} else {
   2309				/* change the unused primary window to overlay window */
   2310				win->type = DRM_PLANE_TYPE_OVERLAY;
   2311			}
   2312		}
   2313
   2314		if (win->type == DRM_PLANE_TYPE_OVERLAY)
   2315			possible_crtcs = (1 << nvps) - 1;
   2316
   2317		ret = vop2_plane_init(vop2, win, possible_crtcs);
   2318		if (ret) {
   2319			drm_err(vop2->drm, "failed to init plane %s: %d\n",
   2320				win->data->name, ret);
   2321			return ret;
   2322		}
   2323	}
   2324
   2325	for (i = 0; i < vop2_data->nr_vps; i++) {
   2326		vp = &vop2->vps[i];
   2327
   2328		if (!vp->crtc.port)
   2329			continue;
   2330
   2331		plane = &vp->primary_plane->base;
   2332
   2333		ret = drm_crtc_init_with_planes(drm, &vp->crtc, plane, NULL,
   2334						&vop2_crtc_funcs,
   2335						"video_port%d", vp->id);
   2336		if (ret) {
   2337			drm_err(vop2->drm, "crtc init for video_port%d failed\n", i);
   2338			return ret;
   2339		}
   2340
   2341		drm_crtc_helper_add(&vp->crtc, &vop2_crtc_helper_funcs);
   2342
   2343		init_completion(&vp->dsp_hold_completion);
   2344	}
   2345
   2346	/*
   2347	 * On the VOP2 it's very hard to change the number of layers on a VP
   2348	 * during runtime, so we distribute the layers equally over the used
   2349	 * VPs
   2350	 */
   2351	for (i = 0; i < vop2->data->nr_vps; i++) {
   2352		struct vop2_video_port *vp = &vop2->vps[i];
   2353
   2354		if (vp->crtc.port)
   2355			vp->nlayers = NR_LAYERS / nvps;
   2356	}
   2357
   2358	return 0;
   2359}
   2360
   2361static void vop2_destroy_crtc(struct drm_crtc *crtc)
   2362{
   2363	of_node_put(crtc->port);
   2364
   2365	/*
   2366	 * Destroy CRTC after vop2_plane_destroy() since vop2_disable_plane()
   2367	 * references the CRTC.
   2368	 */
   2369	drm_crtc_cleanup(crtc);
   2370}
   2371
   2372static struct reg_field vop2_cluster_regs[VOP2_WIN_MAX_REG] = {
   2373	[VOP2_WIN_ENABLE] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 0, 0),
   2374	[VOP2_WIN_FORMAT] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 1, 5),
   2375	[VOP2_WIN_RB_SWAP] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 14, 14),
   2376	[VOP2_WIN_DITHER_UP] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 18, 18),
   2377	[VOP2_WIN_ACT_INFO] = REG_FIELD(RK3568_CLUSTER_WIN_ACT_INFO, 0, 31),
   2378	[VOP2_WIN_DSP_INFO] = REG_FIELD(RK3568_CLUSTER_WIN_DSP_INFO, 0, 31),
   2379	[VOP2_WIN_DSP_ST] = REG_FIELD(RK3568_CLUSTER_WIN_DSP_ST, 0, 31),
   2380	[VOP2_WIN_YRGB_MST] = REG_FIELD(RK3568_CLUSTER_WIN_YRGB_MST, 0, 31),
   2381	[VOP2_WIN_UV_MST] = REG_FIELD(RK3568_CLUSTER_WIN_CBR_MST, 0, 31),
   2382	[VOP2_WIN_YUV_CLIP] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 19, 19),
   2383	[VOP2_WIN_YRGB_VIR] = REG_FIELD(RK3568_CLUSTER_WIN_VIR, 0, 15),
   2384	[VOP2_WIN_UV_VIR] = REG_FIELD(RK3568_CLUSTER_WIN_VIR, 16, 31),
   2385	[VOP2_WIN_Y2R_EN] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 8, 8),
   2386	[VOP2_WIN_R2Y_EN] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 9, 9),
   2387	[VOP2_WIN_CSC_MODE] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 10, 11),
   2388
   2389	/* Scale */
   2390	[VOP2_WIN_SCALE_YRGB_X] = REG_FIELD(RK3568_CLUSTER_WIN_SCL_FACTOR_YRGB, 0, 15),
   2391	[VOP2_WIN_SCALE_YRGB_Y] = REG_FIELD(RK3568_CLUSTER_WIN_SCL_FACTOR_YRGB, 16, 31),
   2392	[VOP2_WIN_YRGB_VER_SCL_MODE] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL1, 14, 15),
   2393	[VOP2_WIN_YRGB_HOR_SCL_MODE] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL1, 12, 13),
   2394	[VOP2_WIN_BIC_COE_SEL] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL1, 2, 3),
   2395	[VOP2_WIN_VSD_YRGB_GT2] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL1, 28, 28),
   2396	[VOP2_WIN_VSD_YRGB_GT4] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL1, 29, 29),
   2397
   2398	/* cluster regs */
   2399	[VOP2_WIN_AFBC_ENABLE] = REG_FIELD(RK3568_CLUSTER_CTRL, 1, 1),
   2400	[VOP2_WIN_CLUSTER_ENABLE] = REG_FIELD(RK3568_CLUSTER_CTRL, 0, 0),
   2401	[VOP2_WIN_CLUSTER_LB_MODE] = REG_FIELD(RK3568_CLUSTER_CTRL, 4, 7),
   2402
   2403	/* afbc regs */
   2404	[VOP2_WIN_AFBC_FORMAT] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_CTRL, 2, 6),
   2405	[VOP2_WIN_AFBC_RB_SWAP] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_CTRL, 9, 9),
   2406	[VOP2_WIN_AFBC_UV_SWAP] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_CTRL, 10, 10),
   2407	[VOP2_WIN_AFBC_AUTO_GATING_EN] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_OUTPUT_CTRL, 4, 4),
   2408	[VOP2_WIN_AFBC_HALF_BLOCK_EN] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_CTRL, 7, 7),
   2409	[VOP2_WIN_AFBC_BLOCK_SPLIT_EN] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_CTRL, 8, 8),
   2410	[VOP2_WIN_AFBC_HDR_PTR] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_HDR_PTR, 0, 31),
   2411	[VOP2_WIN_AFBC_PIC_SIZE] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_PIC_SIZE, 0, 31),
   2412	[VOP2_WIN_AFBC_PIC_VIR_WIDTH] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_VIR_WIDTH, 0, 15),
   2413	[VOP2_WIN_AFBC_TILE_NUM] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_VIR_WIDTH, 16, 31),
   2414	[VOP2_WIN_AFBC_PIC_OFFSET] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_PIC_OFFSET, 0, 31),
   2415	[VOP2_WIN_AFBC_DSP_OFFSET] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_DSP_OFFSET, 0, 31),
   2416	[VOP2_WIN_AFBC_TRANSFORM_OFFSET] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_TRANSFORM_OFFSET, 0, 31),
   2417	[VOP2_WIN_AFBC_ROTATE_90] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_ROTATE_MODE, 0, 0),
   2418	[VOP2_WIN_AFBC_ROTATE_270] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_ROTATE_MODE, 1, 1),
   2419	[VOP2_WIN_XMIRROR] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_ROTATE_MODE, 2, 2),
   2420	[VOP2_WIN_YMIRROR] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_ROTATE_MODE, 3, 3),
   2421	[VOP2_WIN_UV_SWAP] = { .reg = 0xffffffff },
   2422	[VOP2_WIN_COLOR_KEY] = { .reg = 0xffffffff },
   2423	[VOP2_WIN_COLOR_KEY_EN] = { .reg = 0xffffffff },
   2424	[VOP2_WIN_SCALE_CBCR_X] = { .reg = 0xffffffff },
   2425	[VOP2_WIN_SCALE_CBCR_Y] = { .reg = 0xffffffff },
   2426	[VOP2_WIN_YRGB_HSCL_FILTER_MODE] = { .reg = 0xffffffff },
   2427	[VOP2_WIN_YRGB_VSCL_FILTER_MODE] = { .reg = 0xffffffff },
   2428	[VOP2_WIN_CBCR_VER_SCL_MODE] = { .reg = 0xffffffff },
   2429	[VOP2_WIN_CBCR_HSCL_FILTER_MODE] = { .reg = 0xffffffff },
   2430	[VOP2_WIN_CBCR_HOR_SCL_MODE] = { .reg = 0xffffffff },
   2431	[VOP2_WIN_CBCR_VSCL_FILTER_MODE] = { .reg = 0xffffffff },
   2432	[VOP2_WIN_VSD_CBCR_GT2] = { .reg = 0xffffffff },
   2433	[VOP2_WIN_VSD_CBCR_GT4] = { .reg = 0xffffffff },
   2434};
   2435
   2436static int vop2_cluster_init(struct vop2_win *win)
   2437{
   2438	struct vop2 *vop2 = win->vop2;
   2439	struct reg_field *cluster_regs;
   2440	int ret, i;
   2441
   2442	cluster_regs = kmemdup(vop2_cluster_regs, sizeof(vop2_cluster_regs),
   2443			       GFP_KERNEL);
   2444	if (!cluster_regs)
   2445		return -ENOMEM;
   2446
   2447	for (i = 0; i < ARRAY_SIZE(vop2_cluster_regs); i++)
   2448		if (cluster_regs[i].reg != 0xffffffff)
   2449			cluster_regs[i].reg += win->offset;
   2450
   2451	ret = devm_regmap_field_bulk_alloc(vop2->dev, vop2->map, win->reg,
   2452					   cluster_regs,
   2453					   ARRAY_SIZE(vop2_cluster_regs));
   2454
   2455	kfree(cluster_regs);
   2456
   2457	return ret;
   2458};
   2459
   2460static struct reg_field vop2_esmart_regs[VOP2_WIN_MAX_REG] = {
   2461	[VOP2_WIN_ENABLE] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 0, 0),
   2462	[VOP2_WIN_FORMAT] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 1, 5),
   2463	[VOP2_WIN_DITHER_UP] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 12, 12),
   2464	[VOP2_WIN_RB_SWAP] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 14, 14),
   2465	[VOP2_WIN_UV_SWAP] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 16, 16),
   2466	[VOP2_WIN_ACT_INFO] = REG_FIELD(RK3568_SMART_REGION0_ACT_INFO, 0, 31),
   2467	[VOP2_WIN_DSP_INFO] = REG_FIELD(RK3568_SMART_REGION0_DSP_INFO, 0, 31),
   2468	[VOP2_WIN_DSP_ST] = REG_FIELD(RK3568_SMART_REGION0_DSP_ST, 0, 28),
   2469	[VOP2_WIN_YRGB_MST] = REG_FIELD(RK3568_SMART_REGION0_YRGB_MST, 0, 31),
   2470	[VOP2_WIN_UV_MST] = REG_FIELD(RK3568_SMART_REGION0_CBR_MST, 0, 31),
   2471	[VOP2_WIN_YUV_CLIP] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 17, 17),
   2472	[VOP2_WIN_YRGB_VIR] = REG_FIELD(RK3568_SMART_REGION0_VIR, 0, 15),
   2473	[VOP2_WIN_UV_VIR] = REG_FIELD(RK3568_SMART_REGION0_VIR, 16, 31),
   2474	[VOP2_WIN_Y2R_EN] = REG_FIELD(RK3568_SMART_CTRL0, 0, 0),
   2475	[VOP2_WIN_R2Y_EN] = REG_FIELD(RK3568_SMART_CTRL0, 1, 1),
   2476	[VOP2_WIN_CSC_MODE] = REG_FIELD(RK3568_SMART_CTRL0, 2, 3),
   2477	[VOP2_WIN_YMIRROR] = REG_FIELD(RK3568_SMART_CTRL1, 31, 31),
   2478	[VOP2_WIN_COLOR_KEY] = REG_FIELD(RK3568_SMART_COLOR_KEY_CTRL, 0, 29),
   2479	[VOP2_WIN_COLOR_KEY_EN] = REG_FIELD(RK3568_SMART_COLOR_KEY_CTRL, 31, 31),
   2480
   2481	/* Scale */
   2482	[VOP2_WIN_SCALE_YRGB_X] = REG_FIELD(RK3568_SMART_REGION0_SCL_FACTOR_YRGB, 0, 15),
   2483	[VOP2_WIN_SCALE_YRGB_Y] = REG_FIELD(RK3568_SMART_REGION0_SCL_FACTOR_YRGB, 16, 31),
   2484	[VOP2_WIN_SCALE_CBCR_X] = REG_FIELD(RK3568_SMART_REGION0_SCL_FACTOR_CBR, 0, 15),
   2485	[VOP2_WIN_SCALE_CBCR_Y] = REG_FIELD(RK3568_SMART_REGION0_SCL_FACTOR_CBR, 16, 31),
   2486	[VOP2_WIN_YRGB_HOR_SCL_MODE] = REG_FIELD(RK3568_SMART_REGION0_SCL_CTRL, 0, 1),
   2487	[VOP2_WIN_YRGB_HSCL_FILTER_MODE] = REG_FIELD(RK3568_SMART_REGION0_SCL_CTRL, 2, 3),
   2488	[VOP2_WIN_YRGB_VER_SCL_MODE] = REG_FIELD(RK3568_SMART_REGION0_SCL_CTRL, 4, 5),
   2489	[VOP2_WIN_YRGB_VSCL_FILTER_MODE] = REG_FIELD(RK3568_SMART_REGION0_SCL_CTRL, 6, 7),
   2490	[VOP2_WIN_CBCR_HOR_SCL_MODE] = REG_FIELD(RK3568_SMART_REGION0_SCL_CTRL, 8, 9),
   2491	[VOP2_WIN_CBCR_HSCL_FILTER_MODE] = REG_FIELD(RK3568_SMART_REGION0_SCL_CTRL, 10, 11),
   2492	[VOP2_WIN_CBCR_VER_SCL_MODE] = REG_FIELD(RK3568_SMART_REGION0_SCL_CTRL, 12, 13),
   2493	[VOP2_WIN_CBCR_VSCL_FILTER_MODE] = REG_FIELD(RK3568_SMART_REGION0_SCL_CTRL, 14, 15),
   2494	[VOP2_WIN_BIC_COE_SEL] = REG_FIELD(RK3568_SMART_REGION0_SCL_CTRL, 16, 17),
   2495	[VOP2_WIN_VSD_YRGB_GT2] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 8, 8),
   2496	[VOP2_WIN_VSD_YRGB_GT4] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 9, 9),
   2497	[VOP2_WIN_VSD_CBCR_GT2] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 10, 10),
   2498	[VOP2_WIN_VSD_CBCR_GT4] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 11, 11),
   2499	[VOP2_WIN_XMIRROR] = { .reg = 0xffffffff },
   2500	[VOP2_WIN_CLUSTER_ENABLE] = { .reg = 0xffffffff },
   2501	[VOP2_WIN_AFBC_ENABLE] = { .reg = 0xffffffff },
   2502	[VOP2_WIN_CLUSTER_LB_MODE] = { .reg = 0xffffffff },
   2503	[VOP2_WIN_AFBC_FORMAT] = { .reg = 0xffffffff },
   2504	[VOP2_WIN_AFBC_RB_SWAP] = { .reg = 0xffffffff },
   2505	[VOP2_WIN_AFBC_UV_SWAP] = { .reg = 0xffffffff },
   2506	[VOP2_WIN_AFBC_AUTO_GATING_EN] = { .reg = 0xffffffff },
   2507	[VOP2_WIN_AFBC_BLOCK_SPLIT_EN] = { .reg = 0xffffffff },
   2508	[VOP2_WIN_AFBC_PIC_VIR_WIDTH] = { .reg = 0xffffffff },
   2509	[VOP2_WIN_AFBC_TILE_NUM] = { .reg = 0xffffffff },
   2510	[VOP2_WIN_AFBC_PIC_OFFSET] = { .reg = 0xffffffff },
   2511	[VOP2_WIN_AFBC_PIC_SIZE] = { .reg = 0xffffffff },
   2512	[VOP2_WIN_AFBC_DSP_OFFSET] = { .reg = 0xffffffff },
   2513	[VOP2_WIN_AFBC_TRANSFORM_OFFSET] = { .reg = 0xffffffff },
   2514	[VOP2_WIN_AFBC_HDR_PTR] = { .reg = 0xffffffff },
   2515	[VOP2_WIN_AFBC_HALF_BLOCK_EN] = { .reg = 0xffffffff },
   2516	[VOP2_WIN_AFBC_ROTATE_270] = { .reg = 0xffffffff },
   2517	[VOP2_WIN_AFBC_ROTATE_90] = { .reg = 0xffffffff },
   2518};
   2519
   2520static int vop2_esmart_init(struct vop2_win *win)
   2521{
   2522	struct vop2 *vop2 = win->vop2;
   2523	struct reg_field *esmart_regs;
   2524	int ret, i;
   2525
   2526	esmart_regs = kmemdup(vop2_esmart_regs, sizeof(vop2_esmart_regs),
   2527			      GFP_KERNEL);
   2528	if (!esmart_regs)
   2529		return -ENOMEM;
   2530
   2531	for (i = 0; i < ARRAY_SIZE(vop2_esmart_regs); i++)
   2532		if (esmart_regs[i].reg != 0xffffffff)
   2533			esmart_regs[i].reg += win->offset;
   2534
   2535	ret = devm_regmap_field_bulk_alloc(vop2->dev, vop2->map, win->reg,
   2536					   esmart_regs,
   2537					   ARRAY_SIZE(vop2_esmart_regs));
   2538
   2539	kfree(esmart_regs);
   2540
   2541	return ret;
   2542};
   2543
   2544static int vop2_win_init(struct vop2 *vop2)
   2545{
   2546	const struct vop2_data *vop2_data = vop2->data;
   2547	struct vop2_win *win;
   2548	int i, ret;
   2549
   2550	for (i = 0; i < vop2_data->win_size; i++) {
   2551		const struct vop2_win_data *win_data = &vop2_data->win[i];
   2552
   2553		win = &vop2->win[i];
   2554		win->data = win_data;
   2555		win->type = win_data->type;
   2556		win->offset = win_data->base;
   2557		win->win_id = i;
   2558		win->vop2 = vop2;
   2559		if (vop2_cluster_window(win))
   2560			ret = vop2_cluster_init(win);
   2561		else
   2562			ret = vop2_esmart_init(win);
   2563		if (ret)
   2564			return ret;
   2565	}
   2566
   2567	vop2->registered_num_wins = vop2_data->win_size;
   2568
   2569	return 0;
   2570}
   2571
   2572/*
   2573 * The window registers are only updated when config done is written.
   2574 * Until that they read back the old value. As we read-modify-write
   2575 * these registers mark them as non-volatile. This makes sure we read
   2576 * the new values from the regmap register cache.
   2577 */
   2578static const struct regmap_range vop2_nonvolatile_range[] = {
   2579	regmap_reg_range(0x1000, 0x23ff),
   2580};
   2581
   2582static const struct regmap_access_table vop2_volatile_table = {
   2583	.no_ranges = vop2_nonvolatile_range,
   2584	.n_no_ranges = ARRAY_SIZE(vop2_nonvolatile_range),
   2585};
   2586
   2587static const struct regmap_config vop2_regmap_config = {
   2588	.reg_bits	= 32,
   2589	.val_bits	= 32,
   2590	.reg_stride	= 4,
   2591	.max_register	= 0x3000,
   2592	.name		= "vop2",
   2593	.volatile_table	= &vop2_volatile_table,
   2594	.cache_type	= REGCACHE_RBTREE,
   2595};
   2596
   2597static int vop2_bind(struct device *dev, struct device *master, void *data)
   2598{
   2599	struct platform_device *pdev = to_platform_device(dev);
   2600	const struct vop2_data *vop2_data;
   2601	struct drm_device *drm = data;
   2602	struct vop2 *vop2;
   2603	struct resource *res;
   2604	size_t alloc_size;
   2605	int ret;
   2606
   2607	vop2_data = of_device_get_match_data(dev);
   2608	if (!vop2_data)
   2609		return -ENODEV;
   2610
   2611	/* Allocate vop2 struct and its vop2_win array */
   2612	alloc_size = sizeof(*vop2) + sizeof(*vop2->win) * vop2_data->win_size;
   2613	vop2 = devm_kzalloc(dev, alloc_size, GFP_KERNEL);
   2614	if (!vop2)
   2615		return -ENOMEM;
   2616
   2617	vop2->dev = dev;
   2618	vop2->data = vop2_data;
   2619	vop2->drm = drm;
   2620
   2621	dev_set_drvdata(dev, vop2);
   2622
   2623	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "vop");
   2624	if (!res) {
   2625		drm_err(vop2->drm, "failed to get vop2 register byname\n");
   2626		return -EINVAL;
   2627	}
   2628
   2629	vop2->regs = devm_ioremap_resource(dev, res);
   2630	if (IS_ERR(vop2->regs))
   2631		return PTR_ERR(vop2->regs);
   2632	vop2->len = resource_size(res);
   2633
   2634	vop2->map = devm_regmap_init_mmio(dev, vop2->regs, &vop2_regmap_config);
   2635
   2636	ret = vop2_win_init(vop2);
   2637	if (ret)
   2638		return ret;
   2639
   2640	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "gamma-lut");
   2641	if (res) {
   2642		vop2->lut_regs = devm_ioremap_resource(dev, res);
   2643		if (IS_ERR(vop2->lut_regs))
   2644			return PTR_ERR(vop2->lut_regs);
   2645	}
   2646
   2647	vop2->grf = syscon_regmap_lookup_by_phandle(dev->of_node, "rockchip,grf");
   2648
   2649	vop2->hclk = devm_clk_get(vop2->dev, "hclk");
   2650	if (IS_ERR(vop2->hclk)) {
   2651		drm_err(vop2->drm, "failed to get hclk source\n");
   2652		return PTR_ERR(vop2->hclk);
   2653	}
   2654
   2655	vop2->aclk = devm_clk_get(vop2->dev, "aclk");
   2656	if (IS_ERR(vop2->aclk)) {
   2657		drm_err(vop2->drm, "failed to get aclk source\n");
   2658		return PTR_ERR(vop2->aclk);
   2659	}
   2660
   2661	vop2->irq = platform_get_irq(pdev, 0);
   2662	if (vop2->irq < 0) {
   2663		drm_err(vop2->drm, "cannot find irq for vop2\n");
   2664		return vop2->irq;
   2665	}
   2666
   2667	mutex_init(&vop2->vop2_lock);
   2668
   2669	ret = devm_request_irq(dev, vop2->irq, vop2_isr, IRQF_SHARED, dev_name(dev), vop2);
   2670	if (ret)
   2671		return ret;
   2672
   2673	ret = vop2_create_crtc(vop2);
   2674	if (ret)
   2675		return ret;
   2676
   2677	rockchip_drm_dma_init_device(vop2->drm, vop2->dev);
   2678
   2679	pm_runtime_enable(&pdev->dev);
   2680
   2681	return 0;
   2682}
   2683
   2684static void vop2_unbind(struct device *dev, struct device *master, void *data)
   2685{
   2686	struct vop2 *vop2 = dev_get_drvdata(dev);
   2687	struct drm_device *drm = vop2->drm;
   2688	struct list_head *plane_list = &drm->mode_config.plane_list;
   2689	struct list_head *crtc_list = &drm->mode_config.crtc_list;
   2690	struct drm_crtc *crtc, *tmpc;
   2691	struct drm_plane *plane, *tmpp;
   2692
   2693	pm_runtime_disable(dev);
   2694
   2695	list_for_each_entry_safe(plane, tmpp, plane_list, head)
   2696		drm_plane_cleanup(plane);
   2697
   2698	list_for_each_entry_safe(crtc, tmpc, crtc_list, head)
   2699		vop2_destroy_crtc(crtc);
   2700}
   2701
   2702const struct component_ops vop2_component_ops = {
   2703	.bind = vop2_bind,
   2704	.unbind = vop2_unbind,
   2705};
   2706EXPORT_SYMBOL_GPL(vop2_component_ops);