Linux Audio

Check our new training course

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