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