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