1
2
3
4
5
6
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/module.h>
13#include <linux/of.h>
14#include <linux/of_device.h>
15#include <linux/overflow.h>
16#include <linux/platform_device.h>
17#include <linux/pm_runtime.h>
18#include <linux/reset.h>
19
20#include <drm/drm.h>
21#include <drm/drm_atomic.h>
22#include <drm/drm_atomic_uapi.h>
23#include <drm/drm_crtc.h>
24#include <drm/drm_flip_work.h>
25#include <drm/drm_fourcc.h>
26#include <drm/drm_gem_atomic_helper.h>
27#include <drm/drm_gem_framebuffer_helper.h>
28#include <drm/drm_plane_helper.h>
29#include <drm/drm_probe_helper.h>
30#include <drm/drm_self_refresh_helper.h>
31#include <drm/drm_vblank.h>
32
33#ifdef CONFIG_DRM_ANALOGIX_DP
34#include <drm/bridge/analogix_dp.h>
35#endif
36
37#include "rockchip_drm_drv.h"
38#include "rockchip_drm_gem.h"
39#include "rockchip_drm_fb.h"
40#include "rockchip_drm_vop.h"
41#include "rockchip_rgb.h"
42
43#define VOP_WIN_SET(vop, win, name, v) \
44 vop_reg_set(vop, &win->phy->name, win->base, ~0, v, #name)
45#define VOP_SCL_SET(vop, win, name, v) \
46 vop_reg_set(vop, &win->phy->scl->name, win->base, ~0, v, #name)
47#define VOP_SCL_SET_EXT(vop, win, name, v) \
48 vop_reg_set(vop, &win->phy->scl->ext->name, \
49 win->base, ~0, v, #name)
50
51#define VOP_WIN_YUV2YUV_SET(vop, win_yuv2yuv, name, v) \
52 do { \
53 if (win_yuv2yuv && win_yuv2yuv->name.mask) \
54 vop_reg_set(vop, &win_yuv2yuv->name, 0, ~0, v, #name); \
55 } while (0)
56
57#define VOP_WIN_YUV2YUV_COEFFICIENT_SET(vop, win_yuv2yuv, name, v) \
58 do { \
59 if (win_yuv2yuv && win_yuv2yuv->phy->name.mask) \
60 vop_reg_set(vop, &win_yuv2yuv->phy->name, win_yuv2yuv->base, ~0, v, #name); \
61 } while (0)
62
63#define VOP_INTR_SET_MASK(vop, name, mask, v) \
64 vop_reg_set(vop, &vop->data->intr->name, 0, mask, v, #name)
65
66#define VOP_REG_SET(vop, group, name, v) \
67 vop_reg_set(vop, &vop->data->group->name, 0, ~0, v, #name)
68
69#define VOP_INTR_SET_TYPE(vop, name, type, v) \
70 do { \
71 int i, reg = 0, mask = 0; \
72 for (i = 0; i < vop->data->intr->nintrs; i++) { \
73 if (vop->data->intr->intrs[i] & type) { \
74 reg |= (v) << i; \
75 mask |= 1 << i; \
76 } \
77 } \
78 VOP_INTR_SET_MASK(vop, name, mask, reg); \
79 } while (0)
80#define VOP_INTR_GET_TYPE(vop, name, type) \
81 vop_get_intr_type(vop, &vop->data->intr->name, type)
82
83#define VOP_WIN_GET(vop, win, name) \
84 vop_read_reg(vop, win->base, &win->phy->name)
85
86#define VOP_WIN_HAS_REG(win, name) \
87 (!!(win->phy->name.mask))
88
89#define VOP_WIN_GET_YRGBADDR(vop, win) \
90 vop_readl(vop, win->base + win->phy->yrgb_mst.offset)
91
92#define VOP_WIN_TO_INDEX(vop_win) \
93 ((vop_win) - (vop_win)->vop->win)
94
95#define VOP_AFBC_SET(vop, name, v) \
96 do { \
97 if ((vop)->data->afbc) \
98 vop_reg_set((vop), &(vop)->data->afbc->name, \
99 0, ~0, v, #name); \
100 } while (0)
101
102#define to_vop(x) container_of(x, struct vop, crtc)
103#define to_vop_win(x) container_of(x, struct vop_win, base)
104
105#define AFBC_FMT_RGB565 0x0
106#define AFBC_FMT_U8U8U8U8 0x5
107#define AFBC_FMT_U8U8U8 0x4
108
109#define AFBC_TILE_16x16 BIT(4)
110
111
112
113
114
115
116static const uint32_t bt601_yuv2rgb[] = {
117 0x4A8, 0x0, 0x662,
118 0x4A8, 0x1E6F, 0x1CBF,
119 0x4A8, 0x812, 0x0,
120 0x321168, 0x0877CF, 0x2EB127
121};
122
123enum vop_pending {
124 VOP_PENDING_FB_UNREF,
125};
126
127struct vop_win {
128 struct drm_plane base;
129 const struct vop_win_data *data;
130 const struct vop_win_yuv2yuv_data *yuv2yuv_data;
131 struct vop *vop;
132};
133
134struct rockchip_rgb;
135struct vop {
136 struct drm_crtc crtc;
137 struct device *dev;
138 struct drm_device *drm_dev;
139 bool is_enabled;
140
141 struct completion dsp_hold_completion;
142 unsigned int win_enabled;
143
144
145 struct drm_pending_vblank_event *event;
146
147 struct drm_flip_work fb_unref_work;
148 unsigned long pending;
149
150 struct completion line_flag_completion;
151
152 const struct vop_data *data;
153
154 uint32_t *regsbak;
155 void __iomem *regs;
156 void __iomem *lut_regs;
157
158
159 uint32_t len;
160
161
162 spinlock_t reg_lock;
163
164 spinlock_t irq_lock;
165
166 struct mutex vop_lock;
167
168 unsigned int irq;
169
170
171 struct clk *hclk;
172
173 struct clk *dclk;
174
175 struct clk *aclk;
176
177
178 struct reset_control *dclk_rst;
179
180
181 struct rockchip_rgb *rgb;
182
183 struct vop_win win[];
184};
185
186static inline void vop_writel(struct vop *vop, uint32_t offset, uint32_t v)
187{
188 writel(v, vop->regs + offset);
189 vop->regsbak[offset >> 2] = v;
190}
191
192static inline uint32_t vop_readl(struct vop *vop, uint32_t offset)
193{
194 return readl(vop->regs + offset);
195}
196
197static inline uint32_t vop_read_reg(struct vop *vop, uint32_t base,
198 const struct vop_reg *reg)
199{
200 return (vop_readl(vop, base + reg->offset) >> reg->shift) & reg->mask;
201}
202
203static void vop_reg_set(struct vop *vop, const struct vop_reg *reg,
204 uint32_t _offset, uint32_t _mask, uint32_t v,
205 const char *reg_name)
206{
207 int offset, mask, shift;
208
209 if (!reg || !reg->mask) {
210 DRM_DEV_DEBUG(vop->dev, "Warning: not support %s\n", reg_name);
211 return;
212 }
213
214 offset = reg->offset + _offset;
215 mask = reg->mask & _mask;
216 shift = reg->shift;
217
218 if (reg->write_mask) {
219 v = ((v << shift) & 0xffff) | (mask << (shift + 16));
220 } else {
221 uint32_t cached_val = vop->regsbak[offset >> 2];
222
223 v = (cached_val & ~(mask << shift)) | ((v & mask) << shift);
224 vop->regsbak[offset >> 2] = v;
225 }
226
227 if (reg->relaxed)
228 writel_relaxed(v, vop->regs + offset);
229 else
230 writel(v, vop->regs + offset);
231}
232
233static inline uint32_t vop_get_intr_type(struct vop *vop,
234 const struct vop_reg *reg, int type)
235{
236 uint32_t i, ret = 0;
237 uint32_t regs = vop_read_reg(vop, 0, reg);
238
239 for (i = 0; i < vop->data->intr->nintrs; i++) {
240 if ((type & vop->data->intr->intrs[i]) && (regs & 1 << i))
241 ret |= vop->data->intr->intrs[i];
242 }
243
244 return ret;
245}
246
247static inline void vop_cfg_done(struct vop *vop)
248{
249 VOP_REG_SET(vop, common, cfg_done, 1);
250}
251
252static bool has_rb_swapped(uint32_t format)
253{
254 switch (format) {
255 case DRM_FORMAT_XBGR8888:
256 case DRM_FORMAT_ABGR8888:
257 case DRM_FORMAT_BGR888:
258 case DRM_FORMAT_BGR565:
259 return true;
260 default:
261 return false;
262 }
263}
264
265static enum vop_data_format vop_convert_format(uint32_t format)
266{
267 switch (format) {
268 case DRM_FORMAT_XRGB8888:
269 case DRM_FORMAT_ARGB8888:
270 case DRM_FORMAT_XBGR8888:
271 case DRM_FORMAT_ABGR8888:
272 return VOP_FMT_ARGB8888;
273 case DRM_FORMAT_RGB888:
274 case DRM_FORMAT_BGR888:
275 return VOP_FMT_RGB888;
276 case DRM_FORMAT_RGB565:
277 case DRM_FORMAT_BGR565:
278 return VOP_FMT_RGB565;
279 case DRM_FORMAT_NV12:
280 return VOP_FMT_YUV420SP;
281 case DRM_FORMAT_NV16:
282 return VOP_FMT_YUV422SP;
283 case DRM_FORMAT_NV24:
284 return VOP_FMT_YUV444SP;
285 default:
286 DRM_ERROR("unsupported format[%08x]\n", format);
287 return -EINVAL;
288 }
289}
290
291static int vop_convert_afbc_format(uint32_t format)
292{
293 switch (format) {
294 case DRM_FORMAT_XRGB8888:
295 case DRM_FORMAT_ARGB8888:
296 case DRM_FORMAT_XBGR8888:
297 case DRM_FORMAT_ABGR8888:
298 return AFBC_FMT_U8U8U8U8;
299 case DRM_FORMAT_RGB888:
300 case DRM_FORMAT_BGR888:
301 return AFBC_FMT_U8U8U8;
302 case DRM_FORMAT_RGB565:
303 case DRM_FORMAT_BGR565:
304 return AFBC_FMT_RGB565;
305
306 default:
307 DRM_WARN_ONCE("unsupported AFBC format[%08x]\n", format);
308 return -EINVAL;
309 }
310
311 return -EINVAL;
312}
313
314static uint16_t scl_vop_cal_scale(enum scale_mode mode, uint32_t src,
315 uint32_t dst, bool is_horizontal,
316 int vsu_mode, int *vskiplines)
317{
318 uint16_t val = 1 << SCL_FT_DEFAULT_FIXPOINT_SHIFT;
319
320 if (vskiplines)
321 *vskiplines = 0;
322
323 if (is_horizontal) {
324 if (mode == SCALE_UP)
325 val = GET_SCL_FT_BIC(src, dst);
326 else if (mode == SCALE_DOWN)
327 val = GET_SCL_FT_BILI_DN(src, dst);
328 } else {
329 if (mode == SCALE_UP) {
330 if (vsu_mode == SCALE_UP_BIL)
331 val = GET_SCL_FT_BILI_UP(src, dst);
332 else
333 val = GET_SCL_FT_BIC(src, dst);
334 } else if (mode == SCALE_DOWN) {
335 if (vskiplines) {
336 *vskiplines = scl_get_vskiplines(src, dst);
337 val = scl_get_bili_dn_vskip(src, dst,
338 *vskiplines);
339 } else {
340 val = GET_SCL_FT_BILI_DN(src, dst);
341 }
342 }
343 }
344
345 return val;
346}
347
348static void scl_vop_cal_scl_fac(struct vop *vop, const struct vop_win_data *win,
349 uint32_t src_w, uint32_t src_h, uint32_t dst_w,
350 uint32_t dst_h, const struct drm_format_info *info)
351{
352 uint16_t yrgb_hor_scl_mode, yrgb_ver_scl_mode;
353 uint16_t cbcr_hor_scl_mode = SCALE_NONE;
354 uint16_t cbcr_ver_scl_mode = SCALE_NONE;
355 bool is_yuv = false;
356 uint16_t cbcr_src_w = src_w / info->hsub;
357 uint16_t cbcr_src_h = src_h / info->vsub;
358 uint16_t vsu_mode;
359 uint16_t lb_mode;
360 uint32_t val;
361 int vskiplines;
362
363 if (info->is_yuv)
364 is_yuv = true;
365
366 if (dst_w > 3840) {
367 DRM_DEV_ERROR(vop->dev, "Maximum dst width (3840) exceeded\n");
368 return;
369 }
370
371 if (!win->phy->scl->ext) {
372 VOP_SCL_SET(vop, win, scale_yrgb_x,
373 scl_cal_scale2(src_w, dst_w));
374 VOP_SCL_SET(vop, win, scale_yrgb_y,
375 scl_cal_scale2(src_h, dst_h));
376 if (is_yuv) {
377 VOP_SCL_SET(vop, win, scale_cbcr_x,
378 scl_cal_scale2(cbcr_src_w, dst_w));
379 VOP_SCL_SET(vop, win, scale_cbcr_y,
380 scl_cal_scale2(cbcr_src_h, dst_h));
381 }
382 return;
383 }
384
385 yrgb_hor_scl_mode = scl_get_scl_mode(src_w, dst_w);
386 yrgb_ver_scl_mode = scl_get_scl_mode(src_h, dst_h);
387
388 if (is_yuv) {
389 cbcr_hor_scl_mode = scl_get_scl_mode(cbcr_src_w, dst_w);
390 cbcr_ver_scl_mode = scl_get_scl_mode(cbcr_src_h, dst_h);
391 if (cbcr_hor_scl_mode == SCALE_DOWN)
392 lb_mode = scl_vop_cal_lb_mode(dst_w, true);
393 else
394 lb_mode = scl_vop_cal_lb_mode(cbcr_src_w, true);
395 } else {
396 if (yrgb_hor_scl_mode == SCALE_DOWN)
397 lb_mode = scl_vop_cal_lb_mode(dst_w, false);
398 else
399 lb_mode = scl_vop_cal_lb_mode(src_w, false);
400 }
401
402 VOP_SCL_SET_EXT(vop, win, lb_mode, lb_mode);
403 if (lb_mode == LB_RGB_3840X2) {
404 if (yrgb_ver_scl_mode != SCALE_NONE) {
405 DRM_DEV_ERROR(vop->dev, "not allow yrgb ver scale\n");
406 return;
407 }
408 if (cbcr_ver_scl_mode != SCALE_NONE) {
409 DRM_DEV_ERROR(vop->dev, "not allow cbcr ver scale\n");
410 return;
411 }
412 vsu_mode = SCALE_UP_BIL;
413 } else if (lb_mode == LB_RGB_2560X4) {
414 vsu_mode = SCALE_UP_BIL;
415 } else {
416 vsu_mode = SCALE_UP_BIC;
417 }
418
419 val = scl_vop_cal_scale(yrgb_hor_scl_mode, src_w, dst_w,
420 true, 0, NULL);
421 VOP_SCL_SET(vop, win, scale_yrgb_x, val);
422 val = scl_vop_cal_scale(yrgb_ver_scl_mode, src_h, dst_h,
423 false, vsu_mode, &vskiplines);
424 VOP_SCL_SET(vop, win, scale_yrgb_y, val);
425
426 VOP_SCL_SET_EXT(vop, win, vsd_yrgb_gt4, vskiplines == 4);
427 VOP_SCL_SET_EXT(vop, win, vsd_yrgb_gt2, vskiplines == 2);
428
429 VOP_SCL_SET_EXT(vop, win, yrgb_hor_scl_mode, yrgb_hor_scl_mode);
430 VOP_SCL_SET_EXT(vop, win, yrgb_ver_scl_mode, yrgb_ver_scl_mode);
431 VOP_SCL_SET_EXT(vop, win, yrgb_hsd_mode, SCALE_DOWN_BIL);
432 VOP_SCL_SET_EXT(vop, win, yrgb_vsd_mode, SCALE_DOWN_BIL);
433 VOP_SCL_SET_EXT(vop, win, yrgb_vsu_mode, vsu_mode);
434 if (is_yuv) {
435 val = scl_vop_cal_scale(cbcr_hor_scl_mode, cbcr_src_w,
436 dst_w, true, 0, NULL);
437 VOP_SCL_SET(vop, win, scale_cbcr_x, val);
438 val = scl_vop_cal_scale(cbcr_ver_scl_mode, cbcr_src_h,
439 dst_h, false, vsu_mode, &vskiplines);
440 VOP_SCL_SET(vop, win, scale_cbcr_y, val);
441
442 VOP_SCL_SET_EXT(vop, win, vsd_cbcr_gt4, vskiplines == 4);
443 VOP_SCL_SET_EXT(vop, win, vsd_cbcr_gt2, vskiplines == 2);
444 VOP_SCL_SET_EXT(vop, win, cbcr_hor_scl_mode, cbcr_hor_scl_mode);
445 VOP_SCL_SET_EXT(vop, win, cbcr_ver_scl_mode, cbcr_ver_scl_mode);
446 VOP_SCL_SET_EXT(vop, win, cbcr_hsd_mode, SCALE_DOWN_BIL);
447 VOP_SCL_SET_EXT(vop, win, cbcr_vsd_mode, SCALE_DOWN_BIL);
448 VOP_SCL_SET_EXT(vop, win, cbcr_vsu_mode, vsu_mode);
449 }
450}
451
452static void vop_dsp_hold_valid_irq_enable(struct vop *vop)
453{
454 unsigned long flags;
455
456 if (WARN_ON(!vop->is_enabled))
457 return;
458
459 spin_lock_irqsave(&vop->irq_lock, flags);
460
461 VOP_INTR_SET_TYPE(vop, clear, DSP_HOLD_VALID_INTR, 1);
462 VOP_INTR_SET_TYPE(vop, enable, DSP_HOLD_VALID_INTR, 1);
463
464 spin_unlock_irqrestore(&vop->irq_lock, flags);
465}
466
467static void vop_dsp_hold_valid_irq_disable(struct vop *vop)
468{
469 unsigned long flags;
470
471 if (WARN_ON(!vop->is_enabled))
472 return;
473
474 spin_lock_irqsave(&vop->irq_lock, flags);
475
476 VOP_INTR_SET_TYPE(vop, enable, DSP_HOLD_VALID_INTR, 0);
477
478 spin_unlock_irqrestore(&vop->irq_lock, flags);
479}
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503static bool vop_line_flag_irq_is_enabled(struct vop *vop)
504{
505 uint32_t line_flag_irq;
506 unsigned long flags;
507
508 spin_lock_irqsave(&vop->irq_lock, flags);
509
510 line_flag_irq = VOP_INTR_GET_TYPE(vop, enable, LINE_FLAG_INTR);
511
512 spin_unlock_irqrestore(&vop->irq_lock, flags);
513
514 return !!line_flag_irq;
515}
516
517static void vop_line_flag_irq_enable(struct vop *vop)
518{
519 unsigned long flags;
520
521 if (WARN_ON(!vop->is_enabled))
522 return;
523
524 spin_lock_irqsave(&vop->irq_lock, flags);
525
526 VOP_INTR_SET_TYPE(vop, clear, LINE_FLAG_INTR, 1);
527 VOP_INTR_SET_TYPE(vop, enable, LINE_FLAG_INTR, 1);
528
529 spin_unlock_irqrestore(&vop->irq_lock, flags);
530}
531
532static void vop_line_flag_irq_disable(struct vop *vop)
533{
534 unsigned long flags;
535
536 if (WARN_ON(!vop->is_enabled))
537 return;
538
539 spin_lock_irqsave(&vop->irq_lock, flags);
540
541 VOP_INTR_SET_TYPE(vop, enable, LINE_FLAG_INTR, 0);
542
543 spin_unlock_irqrestore(&vop->irq_lock, flags);
544}
545
546static int vop_core_clks_enable(struct vop *vop)
547{
548 int ret;
549
550 ret = clk_enable(vop->hclk);
551 if (ret < 0)
552 return ret;
553
554 ret = clk_enable(vop->aclk);
555 if (ret < 0)
556 goto err_disable_hclk;
557
558 return 0;
559
560err_disable_hclk:
561 clk_disable(vop->hclk);
562 return ret;
563}
564
565static void vop_core_clks_disable(struct vop *vop)
566{
567 clk_disable(vop->aclk);
568 clk_disable(vop->hclk);
569}
570
571static void vop_win_disable(struct vop *vop, const struct vop_win *vop_win)
572{
573 const struct vop_win_data *win = vop_win->data;
574
575 if (win->phy->scl && win->phy->scl->ext) {
576 VOP_SCL_SET_EXT(vop, win, yrgb_hor_scl_mode, SCALE_NONE);
577 VOP_SCL_SET_EXT(vop, win, yrgb_ver_scl_mode, SCALE_NONE);
578 VOP_SCL_SET_EXT(vop, win, cbcr_hor_scl_mode, SCALE_NONE);
579 VOP_SCL_SET_EXT(vop, win, cbcr_ver_scl_mode, SCALE_NONE);
580 }
581
582 VOP_WIN_SET(vop, win, enable, 0);
583 vop->win_enabled &= ~BIT(VOP_WIN_TO_INDEX(vop_win));
584}
585
586static int vop_enable(struct drm_crtc *crtc, struct drm_crtc_state *old_state)
587{
588 struct vop *vop = to_vop(crtc);
589 int ret, i;
590
591 ret = pm_runtime_get_sync(vop->dev);
592 if (ret < 0) {
593 DRM_DEV_ERROR(vop->dev, "failed to get pm runtime: %d\n", ret);
594 return ret;
595 }
596
597 ret = vop_core_clks_enable(vop);
598 if (WARN_ON(ret < 0))
599 goto err_put_pm_runtime;
600
601 ret = clk_enable(vop->dclk);
602 if (WARN_ON(ret < 0))
603 goto err_disable_core;
604
605
606
607
608
609
610
611 ret = rockchip_drm_dma_attach_device(vop->drm_dev, vop->dev);
612 if (ret) {
613 DRM_DEV_ERROR(vop->dev,
614 "failed to attach dma mapping, %d\n", ret);
615 goto err_disable_dclk;
616 }
617
618 spin_lock(&vop->reg_lock);
619 for (i = 0; i < vop->len; i += 4)
620 writel_relaxed(vop->regsbak[i / 4], vop->regs + i);
621
622
623
624
625
626
627
628
629
630
631 if (!old_state || !old_state->self_refresh_active) {
632 for (i = 0; i < vop->data->win_size; i++) {
633 struct vop_win *vop_win = &vop->win[i];
634
635 vop_win_disable(vop, vop_win);
636 }
637 }
638
639 if (vop->data->afbc) {
640 struct rockchip_crtc_state *s;
641
642
643
644 VOP_AFBC_SET(vop, enable, 0);
645 s = to_rockchip_crtc_state(crtc->state);
646 s->enable_afbc = false;
647 }
648
649 vop_cfg_done(vop);
650
651 spin_unlock(&vop->reg_lock);
652
653
654
655
656 vop->is_enabled = true;
657
658 spin_lock(&vop->reg_lock);
659
660 VOP_REG_SET(vop, common, standby, 1);
661
662 spin_unlock(&vop->reg_lock);
663
664 drm_crtc_vblank_on(crtc);
665
666 return 0;
667
668err_disable_dclk:
669 clk_disable(vop->dclk);
670err_disable_core:
671 vop_core_clks_disable(vop);
672err_put_pm_runtime:
673 pm_runtime_put_sync(vop->dev);
674 return ret;
675}
676
677static void rockchip_drm_set_win_enabled(struct drm_crtc *crtc, bool enabled)
678{
679 struct vop *vop = to_vop(crtc);
680 int i;
681
682 spin_lock(&vop->reg_lock);
683
684 for (i = 0; i < vop->data->win_size; i++) {
685 struct vop_win *vop_win = &vop->win[i];
686 const struct vop_win_data *win = vop_win->data;
687
688 VOP_WIN_SET(vop, win, enable,
689 enabled && (vop->win_enabled & BIT(i)));
690 }
691 vop_cfg_done(vop);
692
693 spin_unlock(&vop->reg_lock);
694}
695
696static void vop_crtc_atomic_disable(struct drm_crtc *crtc,
697 struct drm_atomic_state *state)
698{
699 struct vop *vop = to_vop(crtc);
700
701 WARN_ON(vop->event);
702
703 if (crtc->state->self_refresh_active)
704 rockchip_drm_set_win_enabled(crtc, false);
705
706 mutex_lock(&vop->vop_lock);
707
708 drm_crtc_vblank_off(crtc);
709
710 if (crtc->state->self_refresh_active)
711 goto out;
712
713
714
715
716
717
718
719
720 reinit_completion(&vop->dsp_hold_completion);
721 vop_dsp_hold_valid_irq_enable(vop);
722
723 spin_lock(&vop->reg_lock);
724
725 VOP_REG_SET(vop, common, standby, 1);
726
727 spin_unlock(&vop->reg_lock);
728
729 wait_for_completion(&vop->dsp_hold_completion);
730
731 vop_dsp_hold_valid_irq_disable(vop);
732
733 vop->is_enabled = false;
734
735
736
737
738 rockchip_drm_dma_detach_device(vop->drm_dev, vop->dev);
739
740 clk_disable(vop->dclk);
741 vop_core_clks_disable(vop);
742 pm_runtime_put(vop->dev);
743
744out:
745 mutex_unlock(&vop->vop_lock);
746
747 if (crtc->state->event && !crtc->state->active) {
748 spin_lock_irq(&crtc->dev->event_lock);
749 drm_crtc_send_vblank_event(crtc, crtc->state->event);
750 spin_unlock_irq(&crtc->dev->event_lock);
751
752 crtc->state->event = NULL;
753 }
754}
755
756static void vop_plane_destroy(struct drm_plane *plane)
757{
758 drm_plane_cleanup(plane);
759}
760
761static inline bool rockchip_afbc(u64 modifier)
762{
763 return modifier == ROCKCHIP_AFBC_MOD;
764}
765
766static bool rockchip_mod_supported(struct drm_plane *plane,
767 u32 format, u64 modifier)
768{
769 if (modifier == DRM_FORMAT_MOD_LINEAR)
770 return true;
771
772 if (!rockchip_afbc(modifier)) {
773 DRM_DEBUG_KMS("Unsupported format modifier 0x%llx\n", modifier);
774
775 return false;
776 }
777
778 return vop_convert_afbc_format(format) >= 0;
779}
780
781static int vop_plane_atomic_check(struct drm_plane *plane,
782 struct drm_atomic_state *state)
783{
784 struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state,
785 plane);
786 struct drm_crtc *crtc = new_plane_state->crtc;
787 struct drm_crtc_state *crtc_state;
788 struct drm_framebuffer *fb = new_plane_state->fb;
789 struct vop_win *vop_win = to_vop_win(plane);
790 const struct vop_win_data *win = vop_win->data;
791 int ret;
792 int min_scale = win->phy->scl ? FRAC_16_16(1, 8) :
793 DRM_PLANE_HELPER_NO_SCALING;
794 int max_scale = win->phy->scl ? FRAC_16_16(8, 1) :
795 DRM_PLANE_HELPER_NO_SCALING;
796
797 if (!crtc || WARN_ON(!fb))
798 return 0;
799
800 crtc_state = drm_atomic_get_existing_crtc_state(state,
801 crtc);
802 if (WARN_ON(!crtc_state))
803 return -EINVAL;
804
805 ret = drm_atomic_helper_check_plane_state(new_plane_state, crtc_state,
806 min_scale, max_scale,
807 true, true);
808 if (ret)
809 return ret;
810
811 if (!new_plane_state->visible)
812 return 0;
813
814 ret = vop_convert_format(fb->format->format);
815 if (ret < 0)
816 return ret;
817
818
819
820
821
822 if (fb->format->is_yuv && ((new_plane_state->src.x1 >> 16) % 2)) {
823 DRM_ERROR("Invalid Source: Yuv format not support odd xpos\n");
824 return -EINVAL;
825 }
826
827 if (fb->format->is_yuv && new_plane_state->rotation & DRM_MODE_REFLECT_Y) {
828 DRM_ERROR("Invalid Source: Yuv format does not support this rotation\n");
829 return -EINVAL;
830 }
831
832 if (rockchip_afbc(fb->modifier)) {
833 struct vop *vop = to_vop(crtc);
834
835 if (!vop->data->afbc) {
836 DRM_ERROR("vop does not support AFBC\n");
837 return -EINVAL;
838 }
839
840 ret = vop_convert_afbc_format(fb->format->format);
841 if (ret < 0)
842 return ret;
843
844 if (new_plane_state->src.x1 || new_plane_state->src.y1) {
845 DRM_ERROR("AFBC does not support offset display, xpos=%d, ypos=%d, offset=%d\n",
846 new_plane_state->src.x1,
847 new_plane_state->src.y1, fb->offsets[0]);
848 return -EINVAL;
849 }
850
851 if (new_plane_state->rotation && new_plane_state->rotation != DRM_MODE_ROTATE_0) {
852 DRM_ERROR("No rotation support in AFBC, rotation=%d\n",
853 new_plane_state->rotation);
854 return -EINVAL;
855 }
856 }
857
858 return 0;
859}
860
861static void vop_plane_atomic_disable(struct drm_plane *plane,
862 struct drm_atomic_state *state)
863{
864 struct drm_plane_state *old_state = drm_atomic_get_old_plane_state(state,
865 plane);
866 struct vop_win *vop_win = to_vop_win(plane);
867 struct vop *vop = to_vop(old_state->crtc);
868
869 if (!old_state->crtc)
870 return;
871
872 spin_lock(&vop->reg_lock);
873
874 vop_win_disable(vop, vop_win);
875
876 spin_unlock(&vop->reg_lock);
877}
878
879static void vop_plane_atomic_update(struct drm_plane *plane,
880 struct drm_atomic_state *state)
881{
882 struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state,
883 plane);
884 struct drm_crtc *crtc = new_state->crtc;
885 struct vop_win *vop_win = to_vop_win(plane);
886 const struct vop_win_data *win = vop_win->data;
887 const struct vop_win_yuv2yuv_data *win_yuv2yuv = vop_win->yuv2yuv_data;
888 struct vop *vop = to_vop(new_state->crtc);
889 struct drm_framebuffer *fb = new_state->fb;
890 unsigned int actual_w, actual_h;
891 unsigned int dsp_stx, dsp_sty;
892 uint32_t act_info, dsp_info, dsp_st;
893 struct drm_rect *src = &new_state->src;
894 struct drm_rect *dest = &new_state->dst;
895 struct drm_gem_object *obj, *uv_obj;
896 struct rockchip_gem_object *rk_obj, *rk_uv_obj;
897 unsigned long offset;
898 dma_addr_t dma_addr;
899 uint32_t val;
900 bool rb_swap;
901 int win_index = VOP_WIN_TO_INDEX(vop_win);
902 int format;
903 int is_yuv = fb->format->is_yuv;
904 int i;
905
906
907
908
909 if (WARN_ON(!crtc))
910 return;
911
912 if (WARN_ON(!vop->is_enabled))
913 return;
914
915 if (!new_state->visible) {
916 vop_plane_atomic_disable(plane, state);
917 return;
918 }
919
920 obj = fb->obj[0];
921 rk_obj = to_rockchip_obj(obj);
922
923 actual_w = drm_rect_width(src) >> 16;
924 actual_h = drm_rect_height(src) >> 16;
925 act_info = (actual_h - 1) << 16 | ((actual_w - 1) & 0xffff);
926
927 dsp_info = (drm_rect_height(dest) - 1) << 16;
928 dsp_info |= (drm_rect_width(dest) - 1) & 0xffff;
929
930 dsp_stx = dest->x1 + crtc->mode.htotal - crtc->mode.hsync_start;
931 dsp_sty = dest->y1 + crtc->mode.vtotal - crtc->mode.vsync_start;
932 dsp_st = dsp_sty << 16 | (dsp_stx & 0xffff);
933
934 offset = (src->x1 >> 16) * fb->format->cpp[0];
935 offset += (src->y1 >> 16) * fb->pitches[0];
936 dma_addr = rk_obj->dma_addr + offset + fb->offsets[0];
937
938
939
940
941
942 if (new_state->rotation & DRM_MODE_REFLECT_Y)
943 dma_addr += (actual_h - 1) * fb->pitches[0];
944
945 format = vop_convert_format(fb->format->format);
946
947 spin_lock(&vop->reg_lock);
948
949 if (rockchip_afbc(fb->modifier)) {
950 int afbc_format = vop_convert_afbc_format(fb->format->format);
951
952 VOP_AFBC_SET(vop, format, afbc_format | AFBC_TILE_16x16);
953 VOP_AFBC_SET(vop, hreg_block_split, 0);
954 VOP_AFBC_SET(vop, win_sel, VOP_WIN_TO_INDEX(vop_win));
955 VOP_AFBC_SET(vop, hdr_ptr, dma_addr);
956 VOP_AFBC_SET(vop, pic_size, act_info);
957 }
958
959 VOP_WIN_SET(vop, win, format, format);
960 VOP_WIN_SET(vop, win, yrgb_vir, DIV_ROUND_UP(fb->pitches[0], 4));
961 VOP_WIN_SET(vop, win, yrgb_mst, dma_addr);
962 VOP_WIN_YUV2YUV_SET(vop, win_yuv2yuv, y2r_en, is_yuv);
963 VOP_WIN_SET(vop, win, y_mir_en,
964 (new_state->rotation & DRM_MODE_REFLECT_Y) ? 1 : 0);
965 VOP_WIN_SET(vop, win, x_mir_en,
966 (new_state->rotation & DRM_MODE_REFLECT_X) ? 1 : 0);
967
968 if (is_yuv) {
969 int hsub = fb->format->hsub;
970 int vsub = fb->format->vsub;
971 int bpp = fb->format->cpp[1];
972
973 uv_obj = fb->obj[1];
974 rk_uv_obj = to_rockchip_obj(uv_obj);
975
976 offset = (src->x1 >> 16) * bpp / hsub;
977 offset += (src->y1 >> 16) * fb->pitches[1] / vsub;
978
979 dma_addr = rk_uv_obj->dma_addr + offset + fb->offsets[1];
980 VOP_WIN_SET(vop, win, uv_vir, DIV_ROUND_UP(fb->pitches[1], 4));
981 VOP_WIN_SET(vop, win, uv_mst, dma_addr);
982
983 for (i = 0; i < NUM_YUV2YUV_COEFFICIENTS; i++) {
984 VOP_WIN_YUV2YUV_COEFFICIENT_SET(vop,
985 win_yuv2yuv,
986 y2r_coefficients[i],
987 bt601_yuv2rgb[i]);
988 }
989 }
990
991 if (win->phy->scl)
992 scl_vop_cal_scl_fac(vop, win, actual_w, actual_h,
993 drm_rect_width(dest), drm_rect_height(dest),
994 fb->format);
995
996 VOP_WIN_SET(vop, win, act_info, act_info);
997 VOP_WIN_SET(vop, win, dsp_info, dsp_info);
998 VOP_WIN_SET(vop, win, dsp_st, dsp_st);
999
1000 rb_swap = has_rb_swapped(fb->format->format);
1001 VOP_WIN_SET(vop, win, rb_swap, rb_swap);
1002
1003
1004
1005
1006
1007
1008
1009
1010 if (fb->format->has_alpha && win_index > 0) {
1011 VOP_WIN_SET(vop, win, dst_alpha_ctl,
1012 DST_FACTOR_M0(ALPHA_SRC_INVERSE));
1013 val = SRC_ALPHA_EN(1) | SRC_COLOR_M0(ALPHA_SRC_PRE_MUL) |
1014 SRC_ALPHA_M0(ALPHA_STRAIGHT) |
1015 SRC_BLEND_M0(ALPHA_PER_PIX) |
1016 SRC_ALPHA_CAL_M0(ALPHA_NO_SATURATION) |
1017 SRC_FACTOR_M0(ALPHA_ONE);
1018 VOP_WIN_SET(vop, win, src_alpha_ctl, val);
1019
1020 VOP_WIN_SET(vop, win, alpha_pre_mul, ALPHA_SRC_PRE_MUL);
1021 VOP_WIN_SET(vop, win, alpha_mode, ALPHA_PER_PIX);
1022 VOP_WIN_SET(vop, win, alpha_en, 1);
1023 } else {
1024 VOP_WIN_SET(vop, win, src_alpha_ctl, SRC_ALPHA_EN(0));
1025 VOP_WIN_SET(vop, win, alpha_en, 0);
1026 }
1027
1028 VOP_WIN_SET(vop, win, enable, 1);
1029 vop->win_enabled |= BIT(win_index);
1030 spin_unlock(&vop->reg_lock);
1031}
1032
1033static int vop_plane_atomic_async_check(struct drm_plane *plane,
1034 struct drm_atomic_state *state)
1035{
1036 struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state,
1037 plane);
1038 struct vop_win *vop_win = to_vop_win(plane);
1039 const struct vop_win_data *win = vop_win->data;
1040 int min_scale = win->phy->scl ? FRAC_16_16(1, 8) :
1041 DRM_PLANE_HELPER_NO_SCALING;
1042 int max_scale = win->phy->scl ? FRAC_16_16(8, 1) :
1043 DRM_PLANE_HELPER_NO_SCALING;
1044 struct drm_crtc_state *crtc_state;
1045
1046 if (plane != new_plane_state->crtc->cursor)
1047 return -EINVAL;
1048
1049 if (!plane->state)
1050 return -EINVAL;
1051
1052 if (!plane->state->fb)
1053 return -EINVAL;
1054
1055 if (state)
1056 crtc_state = drm_atomic_get_existing_crtc_state(state,
1057 new_plane_state->crtc);
1058 else
1059 crtc_state = plane->crtc->state;
1060
1061 return drm_atomic_helper_check_plane_state(plane->state, crtc_state,
1062 min_scale, max_scale,
1063 true, true);
1064}
1065
1066static void vop_plane_atomic_async_update(struct drm_plane *plane,
1067 struct drm_atomic_state *state)
1068{
1069 struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state,
1070 plane);
1071 struct vop *vop = to_vop(plane->state->crtc);
1072 struct drm_framebuffer *old_fb = plane->state->fb;
1073
1074 plane->state->crtc_x = new_state->crtc_x;
1075 plane->state->crtc_y = new_state->crtc_y;
1076 plane->state->crtc_h = new_state->crtc_h;
1077 plane->state->crtc_w = new_state->crtc_w;
1078 plane->state->src_x = new_state->src_x;
1079 plane->state->src_y = new_state->src_y;
1080 plane->state->src_h = new_state->src_h;
1081 plane->state->src_w = new_state->src_w;
1082 swap(plane->state->fb, new_state->fb);
1083
1084 if (vop->is_enabled) {
1085 vop_plane_atomic_update(plane, state);
1086 spin_lock(&vop->reg_lock);
1087 vop_cfg_done(vop);
1088 spin_unlock(&vop->reg_lock);
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098 if (old_fb && plane->state->fb != old_fb) {
1099 drm_framebuffer_get(old_fb);
1100 WARN_ON(drm_crtc_vblank_get(plane->state->crtc) != 0);
1101 drm_flip_work_queue(&vop->fb_unref_work, old_fb);
1102 set_bit(VOP_PENDING_FB_UNREF, &vop->pending);
1103 }
1104 }
1105}
1106
1107static const struct drm_plane_helper_funcs plane_helper_funcs = {
1108 .atomic_check = vop_plane_atomic_check,
1109 .atomic_update = vop_plane_atomic_update,
1110 .atomic_disable = vop_plane_atomic_disable,
1111 .atomic_async_check = vop_plane_atomic_async_check,
1112 .atomic_async_update = vop_plane_atomic_async_update,
1113 .prepare_fb = drm_gem_plane_helper_prepare_fb,
1114};
1115
1116static const struct drm_plane_funcs vop_plane_funcs = {
1117 .update_plane = drm_atomic_helper_update_plane,
1118 .disable_plane = drm_atomic_helper_disable_plane,
1119 .destroy = vop_plane_destroy,
1120 .reset = drm_atomic_helper_plane_reset,
1121 .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
1122 .atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
1123 .format_mod_supported = rockchip_mod_supported,
1124};
1125
1126static int vop_crtc_enable_vblank(struct drm_crtc *crtc)
1127{
1128 struct vop *vop = to_vop(crtc);
1129 unsigned long flags;
1130
1131 if (WARN_ON(!vop->is_enabled))
1132 return -EPERM;
1133
1134 spin_lock_irqsave(&vop->irq_lock, flags);
1135
1136 VOP_INTR_SET_TYPE(vop, clear, FS_INTR, 1);
1137 VOP_INTR_SET_TYPE(vop, enable, FS_INTR, 1);
1138
1139 spin_unlock_irqrestore(&vop->irq_lock, flags);
1140
1141 return 0;
1142}
1143
1144static void vop_crtc_disable_vblank(struct drm_crtc *crtc)
1145{
1146 struct vop *vop = to_vop(crtc);
1147 unsigned long flags;
1148
1149 if (WARN_ON(!vop->is_enabled))
1150 return;
1151
1152 spin_lock_irqsave(&vop->irq_lock, flags);
1153
1154 VOP_INTR_SET_TYPE(vop, enable, FS_INTR, 0);
1155
1156 spin_unlock_irqrestore(&vop->irq_lock, flags);
1157}
1158
1159static bool vop_crtc_mode_fixup(struct drm_crtc *crtc,
1160 const struct drm_display_mode *mode,
1161 struct drm_display_mode *adjusted_mode)
1162{
1163 struct vop *vop = to_vop(crtc);
1164 unsigned long rate;
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197 rate = clk_round_rate(vop->dclk, adjusted_mode->clock * 1000 + 999);
1198 adjusted_mode->clock = DIV_ROUND_UP(rate, 1000);
1199
1200 return true;
1201}
1202
1203static bool vop_dsp_lut_is_enabled(struct vop *vop)
1204{
1205 return vop_read_reg(vop, 0, &vop->data->common->dsp_lut_en);
1206}
1207
1208static void vop_crtc_write_gamma_lut(struct vop *vop, struct drm_crtc *crtc)
1209{
1210 struct drm_color_lut *lut = crtc->state->gamma_lut->data;
1211 unsigned int i;
1212
1213 for (i = 0; i < crtc->gamma_size; i++) {
1214 u32 word;
1215
1216 word = (drm_color_lut_extract(lut[i].red, 10) << 20) |
1217 (drm_color_lut_extract(lut[i].green, 10) << 10) |
1218 drm_color_lut_extract(lut[i].blue, 10);
1219 writel(word, vop->lut_regs + i * 4);
1220 }
1221}
1222
1223static void vop_crtc_gamma_set(struct vop *vop, struct drm_crtc *crtc,
1224 struct drm_crtc_state *old_state)
1225{
1226 struct drm_crtc_state *state = crtc->state;
1227 unsigned int idle;
1228 int ret;
1229
1230 if (!vop->lut_regs)
1231 return;
1232
1233
1234
1235
1236 spin_lock(&vop->reg_lock);
1237 VOP_REG_SET(vop, common, dsp_lut_en, 0);
1238 vop_cfg_done(vop);
1239 spin_unlock(&vop->reg_lock);
1240
1241
1242
1243
1244
1245 ret = readx_poll_timeout(vop_dsp_lut_is_enabled, vop,
1246 idle, !idle, 5, 30 * 1000);
1247 if (ret) {
1248 DRM_DEV_ERROR(vop->dev, "display LUT RAM enable timeout!\n");
1249 return;
1250 }
1251
1252 if (!state->gamma_lut)
1253 return;
1254
1255 spin_lock(&vop->reg_lock);
1256 vop_crtc_write_gamma_lut(vop, crtc);
1257 VOP_REG_SET(vop, common, dsp_lut_en, 1);
1258 vop_cfg_done(vop);
1259 spin_unlock(&vop->reg_lock);
1260}
1261
1262static void vop_crtc_atomic_begin(struct drm_crtc *crtc,
1263 struct drm_atomic_state *state)
1264{
1265 struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state,
1266 crtc);
1267 struct drm_crtc_state *old_crtc_state = drm_atomic_get_old_crtc_state(state,
1268 crtc);
1269 struct vop *vop = to_vop(crtc);
1270
1271
1272
1273
1274
1275 if (crtc_state->color_mgmt_changed &&
1276 !crtc_state->active_changed)
1277 vop_crtc_gamma_set(vop, crtc, old_crtc_state);
1278}
1279
1280static void vop_crtc_atomic_enable(struct drm_crtc *crtc,
1281 struct drm_atomic_state *state)
1282{
1283 struct drm_crtc_state *old_state = drm_atomic_get_old_crtc_state(state,
1284 crtc);
1285 struct vop *vop = to_vop(crtc);
1286 const struct vop_data *vop_data = vop->data;
1287 struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc->state);
1288 struct drm_display_mode *adjusted_mode = &crtc->state->adjusted_mode;
1289 u16 hsync_len = adjusted_mode->hsync_end - adjusted_mode->hsync_start;
1290 u16 hdisplay = adjusted_mode->hdisplay;
1291 u16 htotal = adjusted_mode->htotal;
1292 u16 hact_st = adjusted_mode->htotal - adjusted_mode->hsync_start;
1293 u16 hact_end = hact_st + hdisplay;
1294 u16 vdisplay = adjusted_mode->vdisplay;
1295 u16 vtotal = adjusted_mode->vtotal;
1296 u16 vsync_len = adjusted_mode->vsync_end - adjusted_mode->vsync_start;
1297 u16 vact_st = adjusted_mode->vtotal - adjusted_mode->vsync_start;
1298 u16 vact_end = vact_st + vdisplay;
1299 uint32_t pin_pol, val;
1300 int dither_bpc = s->output_bpc ? s->output_bpc : 10;
1301 int ret;
1302
1303 if (old_state && old_state->self_refresh_active) {
1304 drm_crtc_vblank_on(crtc);
1305 rockchip_drm_set_win_enabled(crtc, true);
1306 return;
1307 }
1308
1309
1310
1311
1312
1313
1314 if (crtc->state->gamma_lut)
1315 vop_crtc_gamma_set(vop, crtc, old_state);
1316
1317 mutex_lock(&vop->vop_lock);
1318
1319 WARN_ON(vop->event);
1320
1321 ret = vop_enable(crtc, old_state);
1322 if (ret) {
1323 mutex_unlock(&vop->vop_lock);
1324 DRM_DEV_ERROR(vop->dev, "Failed to enable vop (%d)\n", ret);
1325 return;
1326 }
1327 pin_pol = (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC) ?
1328 BIT(HSYNC_POSITIVE) : 0;
1329 pin_pol |= (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC) ?
1330 BIT(VSYNC_POSITIVE) : 0;
1331 VOP_REG_SET(vop, output, pin_pol, pin_pol);
1332 VOP_REG_SET(vop, output, mipi_dual_channel_en, 0);
1333
1334 switch (s->output_type) {
1335 case DRM_MODE_CONNECTOR_LVDS:
1336 VOP_REG_SET(vop, output, rgb_dclk_pol, 1);
1337 VOP_REG_SET(vop, output, rgb_pin_pol, pin_pol);
1338 VOP_REG_SET(vop, output, rgb_en, 1);
1339 break;
1340 case DRM_MODE_CONNECTOR_eDP:
1341 VOP_REG_SET(vop, output, edp_dclk_pol, 1);
1342 VOP_REG_SET(vop, output, edp_pin_pol, pin_pol);
1343 VOP_REG_SET(vop, output, edp_en, 1);
1344 break;
1345 case DRM_MODE_CONNECTOR_HDMIA:
1346 VOP_REG_SET(vop, output, hdmi_dclk_pol, 1);
1347 VOP_REG_SET(vop, output, hdmi_pin_pol, pin_pol);
1348 VOP_REG_SET(vop, output, hdmi_en, 1);
1349 break;
1350 case DRM_MODE_CONNECTOR_DSI:
1351 VOP_REG_SET(vop, output, mipi_dclk_pol, 1);
1352 VOP_REG_SET(vop, output, mipi_pin_pol, pin_pol);
1353 VOP_REG_SET(vop, output, mipi_en, 1);
1354 VOP_REG_SET(vop, output, mipi_dual_channel_en,
1355 !!(s->output_flags & ROCKCHIP_OUTPUT_DSI_DUAL));
1356 break;
1357 case DRM_MODE_CONNECTOR_DisplayPort:
1358 VOP_REG_SET(vop, output, dp_dclk_pol, 0);
1359 VOP_REG_SET(vop, output, dp_pin_pol, pin_pol);
1360 VOP_REG_SET(vop, output, dp_en, 1);
1361 break;
1362 default:
1363 DRM_DEV_ERROR(vop->dev, "unsupported connector_type [%d]\n",
1364 s->output_type);
1365 }
1366
1367
1368
1369
1370 if (s->output_mode == ROCKCHIP_OUT_MODE_AAAA &&
1371 !(vop_data->feature & VOP_FEATURE_OUTPUT_RGB10))
1372 s->output_mode = ROCKCHIP_OUT_MODE_P888;
1373
1374 if (s->output_mode == ROCKCHIP_OUT_MODE_AAAA && dither_bpc <= 8)
1375 VOP_REG_SET(vop, common, pre_dither_down, 1);
1376 else
1377 VOP_REG_SET(vop, common, pre_dither_down, 0);
1378
1379 if (dither_bpc == 6) {
1380 VOP_REG_SET(vop, common, dither_down_sel, DITHER_DOWN_ALLEGRO);
1381 VOP_REG_SET(vop, common, dither_down_mode, RGB888_TO_RGB666);
1382 VOP_REG_SET(vop, common, dither_down_en, 1);
1383 } else {
1384 VOP_REG_SET(vop, common, dither_down_en, 0);
1385 }
1386
1387 VOP_REG_SET(vop, common, out_mode, s->output_mode);
1388
1389 VOP_REG_SET(vop, modeset, htotal_pw, (htotal << 16) | hsync_len);
1390 val = hact_st << 16;
1391 val |= hact_end;
1392 VOP_REG_SET(vop, modeset, hact_st_end, val);
1393 VOP_REG_SET(vop, modeset, hpost_st_end, val);
1394
1395 VOP_REG_SET(vop, modeset, vtotal_pw, (vtotal << 16) | vsync_len);
1396 val = vact_st << 16;
1397 val |= vact_end;
1398 VOP_REG_SET(vop, modeset, vact_st_end, val);
1399 VOP_REG_SET(vop, modeset, vpost_st_end, val);
1400
1401 VOP_REG_SET(vop, intr, line_flag_num[0], vact_end);
1402
1403 clk_set_rate(vop->dclk, adjusted_mode->clock * 1000);
1404
1405 VOP_REG_SET(vop, common, standby, 0);
1406 mutex_unlock(&vop->vop_lock);
1407}
1408
1409static bool vop_fs_irq_is_pending(struct vop *vop)
1410{
1411 return VOP_INTR_GET_TYPE(vop, status, FS_INTR);
1412}
1413
1414static void vop_wait_for_irq_handler(struct vop *vop)
1415{
1416 bool pending;
1417 int ret;
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427 ret = readx_poll_timeout_atomic(vop_fs_irq_is_pending, vop, pending,
1428 !pending, 0, 10 * 1000);
1429 if (ret)
1430 DRM_DEV_ERROR(vop->dev, "VOP vblank IRQ stuck for 10 ms\n");
1431
1432 synchronize_irq(vop->irq);
1433}
1434
1435static int vop_crtc_atomic_check(struct drm_crtc *crtc,
1436 struct drm_atomic_state *state)
1437{
1438 struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state,
1439 crtc);
1440 struct vop *vop = to_vop(crtc);
1441 struct drm_plane *plane;
1442 struct drm_plane_state *plane_state;
1443 struct rockchip_crtc_state *s;
1444 int afbc_planes = 0;
1445
1446 if (vop->lut_regs && crtc_state->color_mgmt_changed &&
1447 crtc_state->gamma_lut) {
1448 unsigned int len;
1449
1450 len = drm_color_lut_size(crtc_state->gamma_lut);
1451 if (len != crtc->gamma_size) {
1452 DRM_DEBUG_KMS("Invalid LUT size; got %d, expected %d\n",
1453 len, crtc->gamma_size);
1454 return -EINVAL;
1455 }
1456 }
1457
1458 drm_atomic_crtc_state_for_each_plane(plane, crtc_state) {
1459 plane_state =
1460 drm_atomic_get_plane_state(crtc_state->state, plane);
1461 if (IS_ERR(plane_state)) {
1462 DRM_DEBUG_KMS("Cannot get plane state for plane %s\n",
1463 plane->name);
1464 return PTR_ERR(plane_state);
1465 }
1466
1467 if (drm_is_afbc(plane_state->fb->modifier))
1468 ++afbc_planes;
1469 }
1470
1471 if (afbc_planes > 1) {
1472 DRM_DEBUG_KMS("Invalid number of AFBC planes; got %d, expected at most 1\n", afbc_planes);
1473 return -EINVAL;
1474 }
1475
1476 s = to_rockchip_crtc_state(crtc_state);
1477 s->enable_afbc = afbc_planes > 0;
1478
1479 return 0;
1480}
1481
1482static void vop_crtc_atomic_flush(struct drm_crtc *crtc,
1483 struct drm_atomic_state *state)
1484{
1485 struct drm_crtc_state *old_crtc_state = drm_atomic_get_old_crtc_state(state,
1486 crtc);
1487 struct drm_atomic_state *old_state = old_crtc_state->state;
1488 struct drm_plane_state *old_plane_state, *new_plane_state;
1489 struct vop *vop = to_vop(crtc);
1490 struct drm_plane *plane;
1491 struct rockchip_crtc_state *s;
1492 int i;
1493
1494 if (WARN_ON(!vop->is_enabled))
1495 return;
1496
1497 spin_lock(&vop->reg_lock);
1498
1499
1500 s = to_rockchip_crtc_state(crtc->state);
1501 VOP_AFBC_SET(vop, enable, s->enable_afbc);
1502 vop_cfg_done(vop);
1503
1504 spin_unlock(&vop->reg_lock);
1505
1506
1507
1508
1509
1510
1511 vop_wait_for_irq_handler(vop);
1512
1513 spin_lock_irq(&crtc->dev->event_lock);
1514 if (crtc->state->event) {
1515 WARN_ON(drm_crtc_vblank_get(crtc) != 0);
1516 WARN_ON(vop->event);
1517
1518 vop->event = crtc->state->event;
1519 crtc->state->event = NULL;
1520 }
1521 spin_unlock_irq(&crtc->dev->event_lock);
1522
1523 for_each_oldnew_plane_in_state(old_state, plane, old_plane_state,
1524 new_plane_state, i) {
1525 if (!old_plane_state->fb)
1526 continue;
1527
1528 if (old_plane_state->fb == new_plane_state->fb)
1529 continue;
1530
1531 drm_framebuffer_get(old_plane_state->fb);
1532 WARN_ON(drm_crtc_vblank_get(crtc) != 0);
1533 drm_flip_work_queue(&vop->fb_unref_work, old_plane_state->fb);
1534 set_bit(VOP_PENDING_FB_UNREF, &vop->pending);
1535 }
1536}
1537
1538static const struct drm_crtc_helper_funcs vop_crtc_helper_funcs = {
1539 .mode_fixup = vop_crtc_mode_fixup,
1540 .atomic_check = vop_crtc_atomic_check,
1541 .atomic_begin = vop_crtc_atomic_begin,
1542 .atomic_flush = vop_crtc_atomic_flush,
1543 .atomic_enable = vop_crtc_atomic_enable,
1544 .atomic_disable = vop_crtc_atomic_disable,
1545};
1546
1547static void vop_crtc_destroy(struct drm_crtc *crtc)
1548{
1549 drm_crtc_cleanup(crtc);
1550}
1551
1552static struct drm_crtc_state *vop_crtc_duplicate_state(struct drm_crtc *crtc)
1553{
1554 struct rockchip_crtc_state *rockchip_state;
1555
1556 rockchip_state = kzalloc(sizeof(*rockchip_state), GFP_KERNEL);
1557 if (!rockchip_state)
1558 return NULL;
1559
1560 __drm_atomic_helper_crtc_duplicate_state(crtc, &rockchip_state->base);
1561 return &rockchip_state->base;
1562}
1563
1564static void vop_crtc_destroy_state(struct drm_crtc *crtc,
1565 struct drm_crtc_state *state)
1566{
1567 struct rockchip_crtc_state *s = to_rockchip_crtc_state(state);
1568
1569 __drm_atomic_helper_crtc_destroy_state(&s->base);
1570 kfree(s);
1571}
1572
1573static void vop_crtc_reset(struct drm_crtc *crtc)
1574{
1575 struct rockchip_crtc_state *crtc_state =
1576 kzalloc(sizeof(*crtc_state), GFP_KERNEL);
1577
1578 if (crtc->state)
1579 vop_crtc_destroy_state(crtc, crtc->state);
1580
1581 __drm_atomic_helper_crtc_reset(crtc, &crtc_state->base);
1582}
1583
1584#ifdef CONFIG_DRM_ANALOGIX_DP
1585static struct drm_connector *vop_get_edp_connector(struct vop *vop)
1586{
1587 struct drm_connector *connector;
1588 struct drm_connector_list_iter conn_iter;
1589
1590 drm_connector_list_iter_begin(vop->drm_dev, &conn_iter);
1591 drm_for_each_connector_iter(connector, &conn_iter) {
1592 if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) {
1593 drm_connector_list_iter_end(&conn_iter);
1594 return connector;
1595 }
1596 }
1597 drm_connector_list_iter_end(&conn_iter);
1598
1599 return NULL;
1600}
1601
1602static int vop_crtc_set_crc_source(struct drm_crtc *crtc,
1603 const char *source_name)
1604{
1605 struct vop *vop = to_vop(crtc);
1606 struct drm_connector *connector;
1607 int ret;
1608
1609 connector = vop_get_edp_connector(vop);
1610 if (!connector)
1611 return -EINVAL;
1612
1613 if (source_name && strcmp(source_name, "auto") == 0)
1614 ret = analogix_dp_start_crc(connector);
1615 else if (!source_name)
1616 ret = analogix_dp_stop_crc(connector);
1617 else
1618 ret = -EINVAL;
1619
1620 return ret;
1621}
1622
1623static int
1624vop_crtc_verify_crc_source(struct drm_crtc *crtc, const char *source_name,
1625 size_t *values_cnt)
1626{
1627 if (source_name && strcmp(source_name, "auto") != 0)
1628 return -EINVAL;
1629
1630 *values_cnt = 3;
1631 return 0;
1632}
1633
1634#else
1635static int vop_crtc_set_crc_source(struct drm_crtc *crtc,
1636 const char *source_name)
1637{
1638 return -ENODEV;
1639}
1640
1641static int
1642vop_crtc_verify_crc_source(struct drm_crtc *crtc, const char *source_name,
1643 size_t *values_cnt)
1644{
1645 return -ENODEV;
1646}
1647#endif
1648
1649static const struct drm_crtc_funcs vop_crtc_funcs = {
1650 .set_config = drm_atomic_helper_set_config,
1651 .page_flip = drm_atomic_helper_page_flip,
1652 .destroy = vop_crtc_destroy,
1653 .reset = vop_crtc_reset,
1654 .atomic_duplicate_state = vop_crtc_duplicate_state,
1655 .atomic_destroy_state = vop_crtc_destroy_state,
1656 .enable_vblank = vop_crtc_enable_vblank,
1657 .disable_vblank = vop_crtc_disable_vblank,
1658 .set_crc_source = vop_crtc_set_crc_source,
1659 .verify_crc_source = vop_crtc_verify_crc_source,
1660};
1661
1662static void vop_fb_unref_worker(struct drm_flip_work *work, void *val)
1663{
1664 struct vop *vop = container_of(work, struct vop, fb_unref_work);
1665 struct drm_framebuffer *fb = val;
1666
1667 drm_crtc_vblank_put(&vop->crtc);
1668 drm_framebuffer_put(fb);
1669}
1670
1671static void vop_handle_vblank(struct vop *vop)
1672{
1673 struct drm_device *drm = vop->drm_dev;
1674 struct drm_crtc *crtc = &vop->crtc;
1675
1676 spin_lock(&drm->event_lock);
1677 if (vop->event) {
1678 drm_crtc_send_vblank_event(crtc, vop->event);
1679 drm_crtc_vblank_put(crtc);
1680 vop->event = NULL;
1681 }
1682 spin_unlock(&drm->event_lock);
1683
1684 if (test_and_clear_bit(VOP_PENDING_FB_UNREF, &vop->pending))
1685 drm_flip_work_commit(&vop->fb_unref_work, system_unbound_wq);
1686}
1687
1688static irqreturn_t vop_isr(int irq, void *data)
1689{
1690 struct vop *vop = data;
1691 struct drm_crtc *crtc = &vop->crtc;
1692 uint32_t active_irqs;
1693 int ret = IRQ_NONE;
1694
1695
1696
1697
1698
1699 if (!pm_runtime_get_if_in_use(vop->dev))
1700 return IRQ_NONE;
1701
1702 if (vop_core_clks_enable(vop)) {
1703 DRM_DEV_ERROR_RATELIMITED(vop->dev, "couldn't enable clocks\n");
1704 goto out;
1705 }
1706
1707
1708
1709
1710
1711 spin_lock(&vop->irq_lock);
1712
1713 active_irqs = VOP_INTR_GET_TYPE(vop, status, INTR_MASK);
1714
1715 if (active_irqs)
1716 VOP_INTR_SET_TYPE(vop, clear, active_irqs, 1);
1717
1718 spin_unlock(&vop->irq_lock);
1719
1720
1721 if (!active_irqs)
1722 goto out_disable;
1723
1724 if (active_irqs & DSP_HOLD_VALID_INTR) {
1725 complete(&vop->dsp_hold_completion);
1726 active_irqs &= ~DSP_HOLD_VALID_INTR;
1727 ret = IRQ_HANDLED;
1728 }
1729
1730 if (active_irqs & LINE_FLAG_INTR) {
1731 complete(&vop->line_flag_completion);
1732 active_irqs &= ~LINE_FLAG_INTR;
1733 ret = IRQ_HANDLED;
1734 }
1735
1736 if (active_irqs & FS_INTR) {
1737 drm_crtc_handle_vblank(crtc);
1738 vop_handle_vblank(vop);
1739 active_irqs &= ~FS_INTR;
1740 ret = IRQ_HANDLED;
1741 }
1742
1743
1744 if (active_irqs)
1745 DRM_DEV_ERROR(vop->dev, "Unknown VOP IRQs: %#02x\n",
1746 active_irqs);
1747
1748out_disable:
1749 vop_core_clks_disable(vop);
1750out:
1751 pm_runtime_put(vop->dev);
1752 return ret;
1753}
1754
1755static void vop_plane_add_properties(struct drm_plane *plane,
1756 const struct vop_win_data *win_data)
1757{
1758 unsigned int flags = 0;
1759
1760 flags |= VOP_WIN_HAS_REG(win_data, x_mir_en) ? DRM_MODE_REFLECT_X : 0;
1761 flags |= VOP_WIN_HAS_REG(win_data, y_mir_en) ? DRM_MODE_REFLECT_Y : 0;
1762 if (flags)
1763 drm_plane_create_rotation_property(plane, DRM_MODE_ROTATE_0,
1764 DRM_MODE_ROTATE_0 | flags);
1765}
1766
1767static int vop_create_crtc(struct vop *vop)
1768{
1769 const struct vop_data *vop_data = vop->data;
1770 struct device *dev = vop->dev;
1771 struct drm_device *drm_dev = vop->drm_dev;
1772 struct drm_plane *primary = NULL, *cursor = NULL, *plane, *tmp;
1773 struct drm_crtc *crtc = &vop->crtc;
1774 struct device_node *port;
1775 int ret;
1776 int i;
1777
1778
1779
1780
1781
1782
1783 for (i = 0; i < vop_data->win_size; i++) {
1784 struct vop_win *vop_win = &vop->win[i];
1785 const struct vop_win_data *win_data = vop_win->data;
1786
1787 if (win_data->type != DRM_PLANE_TYPE_PRIMARY &&
1788 win_data->type != DRM_PLANE_TYPE_CURSOR)
1789 continue;
1790
1791 ret = drm_universal_plane_init(vop->drm_dev, &vop_win->base,
1792 0, &vop_plane_funcs,
1793 win_data->phy->data_formats,
1794 win_data->phy->nformats,
1795 win_data->phy->format_modifiers,
1796 win_data->type, NULL);
1797 if (ret) {
1798 DRM_DEV_ERROR(vop->dev, "failed to init plane %d\n",
1799 ret);
1800 goto err_cleanup_planes;
1801 }
1802
1803 plane = &vop_win->base;
1804 drm_plane_helper_add(plane, &plane_helper_funcs);
1805 vop_plane_add_properties(plane, win_data);
1806 if (plane->type == DRM_PLANE_TYPE_PRIMARY)
1807 primary = plane;
1808 else if (plane->type == DRM_PLANE_TYPE_CURSOR)
1809 cursor = plane;
1810 }
1811
1812 ret = drm_crtc_init_with_planes(drm_dev, crtc, primary, cursor,
1813 &vop_crtc_funcs, NULL);
1814 if (ret)
1815 goto err_cleanup_planes;
1816
1817 drm_crtc_helper_add(crtc, &vop_crtc_helper_funcs);
1818 if (vop->lut_regs) {
1819 drm_mode_crtc_set_gamma_size(crtc, vop_data->lut_size);
1820 drm_crtc_enable_color_mgmt(crtc, 0, false, vop_data->lut_size);
1821 }
1822
1823
1824
1825
1826
1827 for (i = 0; i < vop_data->win_size; i++) {
1828 struct vop_win *vop_win = &vop->win[i];
1829 const struct vop_win_data *win_data = vop_win->data;
1830 unsigned long possible_crtcs = drm_crtc_mask(crtc);
1831
1832 if (win_data->type != DRM_PLANE_TYPE_OVERLAY)
1833 continue;
1834
1835 ret = drm_universal_plane_init(vop->drm_dev, &vop_win->base,
1836 possible_crtcs,
1837 &vop_plane_funcs,
1838 win_data->phy->data_formats,
1839 win_data->phy->nformats,
1840 win_data->phy->format_modifiers,
1841 win_data->type, NULL);
1842 if (ret) {
1843 DRM_DEV_ERROR(vop->dev, "failed to init overlay %d\n",
1844 ret);
1845 goto err_cleanup_crtc;
1846 }
1847 drm_plane_helper_add(&vop_win->base, &plane_helper_funcs);
1848 vop_plane_add_properties(&vop_win->base, win_data);
1849 }
1850
1851 port = of_get_child_by_name(dev->of_node, "port");
1852 if (!port) {
1853 DRM_DEV_ERROR(vop->dev, "no port node found in %pOF\n",
1854 dev->of_node);
1855 ret = -ENOENT;
1856 goto err_cleanup_crtc;
1857 }
1858
1859 drm_flip_work_init(&vop->fb_unref_work, "fb_unref",
1860 vop_fb_unref_worker);
1861
1862 init_completion(&vop->dsp_hold_completion);
1863 init_completion(&vop->line_flag_completion);
1864 crtc->port = port;
1865
1866 ret = drm_self_refresh_helper_init(crtc);
1867 if (ret)
1868 DRM_DEV_DEBUG_KMS(vop->dev,
1869 "Failed to init %s with SR helpers %d, ignoring\n",
1870 crtc->name, ret);
1871
1872 return 0;
1873
1874err_cleanup_crtc:
1875 drm_crtc_cleanup(crtc);
1876err_cleanup_planes:
1877 list_for_each_entry_safe(plane, tmp, &drm_dev->mode_config.plane_list,
1878 head)
1879 drm_plane_cleanup(plane);
1880 return ret;
1881}
1882
1883static void vop_destroy_crtc(struct vop *vop)
1884{
1885 struct drm_crtc *crtc = &vop->crtc;
1886 struct drm_device *drm_dev = vop->drm_dev;
1887 struct drm_plane *plane, *tmp;
1888
1889 drm_self_refresh_helper_cleanup(crtc);
1890
1891 of_node_put(crtc->port);
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901 list_for_each_entry_safe(plane, tmp, &drm_dev->mode_config.plane_list,
1902 head)
1903 vop_plane_destroy(plane);
1904
1905
1906
1907
1908
1909 drm_crtc_cleanup(crtc);
1910 drm_flip_work_cleanup(&vop->fb_unref_work);
1911}
1912
1913static int vop_initial(struct vop *vop)
1914{
1915 struct reset_control *ahb_rst;
1916 int i, ret;
1917
1918 vop->hclk = devm_clk_get(vop->dev, "hclk_vop");
1919 if (IS_ERR(vop->hclk)) {
1920 DRM_DEV_ERROR(vop->dev, "failed to get hclk source\n");
1921 return PTR_ERR(vop->hclk);
1922 }
1923 vop->aclk = devm_clk_get(vop->dev, "aclk_vop");
1924 if (IS_ERR(vop->aclk)) {
1925 DRM_DEV_ERROR(vop->dev, "failed to get aclk source\n");
1926 return PTR_ERR(vop->aclk);
1927 }
1928 vop->dclk = devm_clk_get(vop->dev, "dclk_vop");
1929 if (IS_ERR(vop->dclk)) {
1930 DRM_DEV_ERROR(vop->dev, "failed to get dclk source\n");
1931 return PTR_ERR(vop->dclk);
1932 }
1933
1934 ret = pm_runtime_get_sync(vop->dev);
1935 if (ret < 0) {
1936 DRM_DEV_ERROR(vop->dev, "failed to get pm runtime: %d\n", ret);
1937 return ret;
1938 }
1939
1940 ret = clk_prepare(vop->dclk);
1941 if (ret < 0) {
1942 DRM_DEV_ERROR(vop->dev, "failed to prepare dclk\n");
1943 goto err_put_pm_runtime;
1944 }
1945
1946
1947 ret = clk_prepare_enable(vop->hclk);
1948 if (ret < 0) {
1949 DRM_DEV_ERROR(vop->dev, "failed to prepare/enable hclk\n");
1950 goto err_unprepare_dclk;
1951 }
1952
1953 ret = clk_prepare_enable(vop->aclk);
1954 if (ret < 0) {
1955 DRM_DEV_ERROR(vop->dev, "failed to prepare/enable aclk\n");
1956 goto err_disable_hclk;
1957 }
1958
1959
1960
1961
1962 ahb_rst = devm_reset_control_get(vop->dev, "ahb");
1963 if (IS_ERR(ahb_rst)) {
1964 DRM_DEV_ERROR(vop->dev, "failed to get ahb reset\n");
1965 ret = PTR_ERR(ahb_rst);
1966 goto err_disable_aclk;
1967 }
1968 reset_control_assert(ahb_rst);
1969 usleep_range(10, 20);
1970 reset_control_deassert(ahb_rst);
1971
1972 VOP_INTR_SET_TYPE(vop, clear, INTR_MASK, 1);
1973 VOP_INTR_SET_TYPE(vop, enable, INTR_MASK, 0);
1974
1975 for (i = 0; i < vop->len; i += sizeof(u32))
1976 vop->regsbak[i / 4] = readl_relaxed(vop->regs + i);
1977
1978 VOP_REG_SET(vop, misc, global_regdone_en, 1);
1979 VOP_REG_SET(vop, common, dsp_blank, 0);
1980
1981 for (i = 0; i < vop->data->win_size; i++) {
1982 struct vop_win *vop_win = &vop->win[i];
1983 const struct vop_win_data *win = vop_win->data;
1984 int channel = i * 2 + 1;
1985
1986 VOP_WIN_SET(vop, win, channel, (channel + 1) << 4 | channel);
1987 vop_win_disable(vop, vop_win);
1988 VOP_WIN_SET(vop, win, gate, 1);
1989 }
1990
1991 vop_cfg_done(vop);
1992
1993
1994
1995
1996 vop->dclk_rst = devm_reset_control_get(vop->dev, "dclk");
1997 if (IS_ERR(vop->dclk_rst)) {
1998 DRM_DEV_ERROR(vop->dev, "failed to get dclk reset\n");
1999 ret = PTR_ERR(vop->dclk_rst);
2000 goto err_disable_aclk;
2001 }
2002 reset_control_assert(vop->dclk_rst);
2003 usleep_range(10, 20);
2004 reset_control_deassert(vop->dclk_rst);
2005
2006 clk_disable(vop->hclk);
2007 clk_disable(vop->aclk);
2008
2009 vop->is_enabled = false;
2010
2011 pm_runtime_put_sync(vop->dev);
2012
2013 return 0;
2014
2015err_disable_aclk:
2016 clk_disable_unprepare(vop->aclk);
2017err_disable_hclk:
2018 clk_disable_unprepare(vop->hclk);
2019err_unprepare_dclk:
2020 clk_unprepare(vop->dclk);
2021err_put_pm_runtime:
2022 pm_runtime_put_sync(vop->dev);
2023 return ret;
2024}
2025
2026
2027
2028
2029static void vop_win_init(struct vop *vop)
2030{
2031 const struct vop_data *vop_data = vop->data;
2032 unsigned int i;
2033
2034 for (i = 0; i < vop_data->win_size; i++) {
2035 struct vop_win *vop_win = &vop->win[i];
2036 const struct vop_win_data *win_data = &vop_data->win[i];
2037
2038 vop_win->data = win_data;
2039 vop_win->vop = vop;
2040
2041 if (vop_data->win_yuv2yuv)
2042 vop_win->yuv2yuv_data = &vop_data->win_yuv2yuv[i];
2043 }
2044}
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056int rockchip_drm_wait_vact_end(struct drm_crtc *crtc, unsigned int mstimeout)
2057{
2058 struct vop *vop = to_vop(crtc);
2059 unsigned long jiffies_left;
2060 int ret = 0;
2061
2062 if (!crtc || !vop->is_enabled)
2063 return -ENODEV;
2064
2065 mutex_lock(&vop->vop_lock);
2066 if (mstimeout <= 0) {
2067 ret = -EINVAL;
2068 goto out;
2069 }
2070
2071 if (vop_line_flag_irq_is_enabled(vop)) {
2072 ret = -EBUSY;
2073 goto out;
2074 }
2075
2076 reinit_completion(&vop->line_flag_completion);
2077 vop_line_flag_irq_enable(vop);
2078
2079 jiffies_left = wait_for_completion_timeout(&vop->line_flag_completion,
2080 msecs_to_jiffies(mstimeout));
2081 vop_line_flag_irq_disable(vop);
2082
2083 if (jiffies_left == 0) {
2084 DRM_DEV_ERROR(vop->dev, "Timeout waiting for IRQ\n");
2085 ret = -ETIMEDOUT;
2086 goto out;
2087 }
2088
2089out:
2090 mutex_unlock(&vop->vop_lock);
2091 return ret;
2092}
2093EXPORT_SYMBOL(rockchip_drm_wait_vact_end);
2094
2095static int vop_bind(struct device *dev, struct device *master, void *data)
2096{
2097 struct platform_device *pdev = to_platform_device(dev);
2098 const struct vop_data *vop_data;
2099 struct drm_device *drm_dev = data;
2100 struct vop *vop;
2101 struct resource *res;
2102 int ret, irq;
2103
2104 vop_data = of_device_get_match_data(dev);
2105 if (!vop_data)
2106 return -ENODEV;
2107
2108
2109 vop = devm_kzalloc(dev, struct_size(vop, win, vop_data->win_size),
2110 GFP_KERNEL);
2111 if (!vop)
2112 return -ENOMEM;
2113
2114 vop->dev = dev;
2115 vop->data = vop_data;
2116 vop->drm_dev = drm_dev;
2117 dev_set_drvdata(dev, vop);
2118
2119 vop_win_init(vop);
2120
2121 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
2122 vop->len = resource_size(res);
2123 vop->regs = devm_ioremap_resource(dev, res);
2124 if (IS_ERR(vop->regs))
2125 return PTR_ERR(vop->regs);
2126
2127 res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
2128 if (res) {
2129 if (!vop_data->lut_size) {
2130 DRM_DEV_ERROR(dev, "no gamma LUT size defined\n");
2131 return -EINVAL;
2132 }
2133 vop->lut_regs = devm_ioremap_resource(dev, res);
2134 if (IS_ERR(vop->lut_regs))
2135 return PTR_ERR(vop->lut_regs);
2136 }
2137
2138 vop->regsbak = devm_kzalloc(dev, vop->len, GFP_KERNEL);
2139 if (!vop->regsbak)
2140 return -ENOMEM;
2141
2142 irq = platform_get_irq(pdev, 0);
2143 if (irq < 0) {
2144 DRM_DEV_ERROR(dev, "cannot find irq for vop\n");
2145 return irq;
2146 }
2147 vop->irq = (unsigned int)irq;
2148
2149 spin_lock_init(&vop->reg_lock);
2150 spin_lock_init(&vop->irq_lock);
2151 mutex_init(&vop->vop_lock);
2152
2153 ret = vop_create_crtc(vop);
2154 if (ret)
2155 return ret;
2156
2157 pm_runtime_enable(&pdev->dev);
2158
2159 ret = vop_initial(vop);
2160 if (ret < 0) {
2161 DRM_DEV_ERROR(&pdev->dev,
2162 "cannot initial vop dev - err %d\n", ret);
2163 goto err_disable_pm_runtime;
2164 }
2165
2166 ret = devm_request_irq(dev, vop->irq, vop_isr,
2167 IRQF_SHARED, dev_name(dev), vop);
2168 if (ret)
2169 goto err_disable_pm_runtime;
2170
2171 if (vop->data->feature & VOP_FEATURE_INTERNAL_RGB) {
2172 vop->rgb = rockchip_rgb_init(dev, &vop->crtc, vop->drm_dev);
2173 if (IS_ERR(vop->rgb)) {
2174 ret = PTR_ERR(vop->rgb);
2175 goto err_disable_pm_runtime;
2176 }
2177 }
2178
2179 return 0;
2180
2181err_disable_pm_runtime:
2182 pm_runtime_disable(&pdev->dev);
2183 vop_destroy_crtc(vop);
2184 return ret;
2185}
2186
2187static void vop_unbind(struct device *dev, struct device *master, void *data)
2188{
2189 struct vop *vop = dev_get_drvdata(dev);
2190
2191 if (vop->rgb)
2192 rockchip_rgb_fini(vop->rgb);
2193
2194 pm_runtime_disable(dev);
2195 vop_destroy_crtc(vop);
2196
2197 clk_unprepare(vop->aclk);
2198 clk_unprepare(vop->hclk);
2199 clk_unprepare(vop->dclk);
2200}
2201
2202const struct component_ops vop_component_ops = {
2203 .bind = vop_bind,
2204 .unbind = vop_unbind,
2205};
2206EXPORT_SYMBOL_GPL(vop_component_ops);
2207