Linux Audio

Check our new training course

Linux kernel drivers training

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