1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (C) 2016 BayLibre, SAS
4 * Author: Neil Armstrong <narmstrong@baylibre.com>
5 * Copyright (C) 2015 Amlogic, Inc. All rights reserved.
6 * Copyright (C) 2014 Endless Mobile
9 * Jasper St. Pierre <jstpierre@mecheye.net>
12 #include <linux/bitfield.h>
13 #include <linux/soc/amlogic/meson-canvas.h>
15 #include <drm/drm_atomic_helper.h>
16 #include <drm/drm_device.h>
17 #include <drm/drm_print.h>
18 #include <drm/drm_probe_helper.h>
19 #include <drm/drm_vblank.h>
21 #include "meson_crtc.h"
22 #include "meson_plane.h"
23 #include "meson_registers.h"
24 #include "meson_venc.h"
25 #include "meson_viu.h"
26 #include "meson_rdma.h"
27 #include "meson_vpp.h"
28 #include "meson_osd_afbcd.h"
30 #define MESON_G12A_VIU_OFFSET 0x5ec0
36 struct drm_pending_vblank_event
*event
;
37 struct meson_drm
*priv
;
38 void (*enable_osd1
)(struct meson_drm
*priv
);
39 void (*enable_vd1
)(struct meson_drm
*priv
);
40 void (*enable_osd1_afbc
)(struct meson_drm
*priv
);
41 void (*disable_osd1_afbc
)(struct meson_drm
*priv
);
42 unsigned int viu_offset
;
46 #define to_meson_crtc(x) container_of(x, struct meson_crtc, base)
50 static int meson_crtc_enable_vblank(struct drm_crtc
*crtc
)
52 struct meson_crtc
*meson_crtc
= to_meson_crtc(crtc
);
53 struct meson_drm
*priv
= meson_crtc
->priv
;
55 meson_crtc
->vsync_disabled
= false;
56 meson_venc_enable_vsync(priv
);
61 static void meson_crtc_disable_vblank(struct drm_crtc
*crtc
)
63 struct meson_crtc
*meson_crtc
= to_meson_crtc(crtc
);
64 struct meson_drm
*priv
= meson_crtc
->priv
;
66 if (!meson_crtc
->vsync_forced
) {
67 meson_crtc
->vsync_disabled
= true;
68 meson_venc_disable_vsync(priv
);
72 static const struct drm_crtc_funcs meson_crtc_funcs
= {
73 .atomic_destroy_state
= drm_atomic_helper_crtc_destroy_state
,
74 .atomic_duplicate_state
= drm_atomic_helper_crtc_duplicate_state
,
75 .destroy
= drm_crtc_cleanup
,
76 .page_flip
= drm_atomic_helper_page_flip
,
77 .reset
= drm_atomic_helper_crtc_reset
,
78 .set_config
= drm_atomic_helper_set_config
,
79 .enable_vblank
= meson_crtc_enable_vblank
,
80 .disable_vblank
= meson_crtc_disable_vblank
,
84 static void meson_g12a_crtc_atomic_enable(struct drm_crtc
*crtc
,
85 struct drm_atomic_state
*state
)
87 struct meson_crtc
*meson_crtc
= to_meson_crtc(crtc
);
88 struct drm_crtc_state
*crtc_state
= crtc
->state
;
89 struct meson_drm
*priv
= meson_crtc
->priv
;
91 DRM_DEBUG_DRIVER("\n");
94 DRM_ERROR("Invalid crtc_state\n");
98 /* VD1 Preblend vertical start/end */
99 writel(FIELD_PREP(GENMASK(11, 0), 2303),
100 priv
->io_base
+ _REG(VPP_PREBLEND_VD1_V_START_END
));
103 writel(crtc_state
->mode
.hdisplay
|
104 crtc_state
->mode
.vdisplay
<< 16,
105 priv
->io_base
+ _REG(VPP_POSTBLEND_H_SIZE
));
107 writel_relaxed(0 << 16 |
108 (crtc_state
->mode
.hdisplay
- 1),
109 priv
->io_base
+ _REG(VPP_OSD1_BLD_H_SCOPE
));
110 writel_relaxed(0 << 16 |
111 (crtc_state
->mode
.vdisplay
- 1),
112 priv
->io_base
+ _REG(VPP_OSD1_BLD_V_SCOPE
));
113 writel_relaxed(crtc_state
->mode
.hdisplay
<< 16 |
114 crtc_state
->mode
.vdisplay
,
115 priv
->io_base
+ _REG(VPP_OUT_H_V_SIZE
));
117 drm_crtc_vblank_on(crtc
);
120 static void meson_crtc_atomic_enable(struct drm_crtc
*crtc
,
121 struct drm_atomic_state
*state
)
123 struct meson_crtc
*meson_crtc
= to_meson_crtc(crtc
);
124 struct drm_crtc_state
*crtc_state
= crtc
->state
;
125 struct meson_drm
*priv
= meson_crtc
->priv
;
127 DRM_DEBUG_DRIVER("\n");
130 DRM_ERROR("Invalid crtc_state\n");
134 /* Enable VPP Postblend */
135 writel(crtc_state
->mode
.hdisplay
,
136 priv
->io_base
+ _REG(VPP_POSTBLEND_H_SIZE
));
138 /* VD1 Preblend vertical start/end */
139 writel(FIELD_PREP(GENMASK(11, 0), 2303),
140 priv
->io_base
+ _REG(VPP_PREBLEND_VD1_V_START_END
));
142 writel_bits_relaxed(VPP_POSTBLEND_ENABLE
, VPP_POSTBLEND_ENABLE
,
143 priv
->io_base
+ _REG(VPP_MISC
));
145 drm_crtc_vblank_on(crtc
);
148 static void meson_g12a_crtc_atomic_disable(struct drm_crtc
*crtc
,
149 struct drm_atomic_state
*state
)
151 struct meson_crtc
*meson_crtc
= to_meson_crtc(crtc
);
152 struct meson_drm
*priv
= meson_crtc
->priv
;
154 DRM_DEBUG_DRIVER("\n");
156 drm_crtc_vblank_off(crtc
);
158 priv
->viu
.osd1_enabled
= false;
159 priv
->viu
.osd1_commit
= false;
161 priv
->viu
.vd1_enabled
= false;
162 priv
->viu
.vd1_commit
= false;
164 if (crtc
->state
->event
&& !crtc
->state
->active
) {
165 spin_lock_irq(&crtc
->dev
->event_lock
);
166 drm_crtc_send_vblank_event(crtc
, crtc
->state
->event
);
167 spin_unlock_irq(&crtc
->dev
->event_lock
);
169 crtc
->state
->event
= NULL
;
173 static void meson_crtc_atomic_disable(struct drm_crtc
*crtc
,
174 struct drm_atomic_state
*state
)
176 struct meson_crtc
*meson_crtc
= to_meson_crtc(crtc
);
177 struct meson_drm
*priv
= meson_crtc
->priv
;
179 DRM_DEBUG_DRIVER("\n");
181 drm_crtc_vblank_off(crtc
);
183 priv
->viu
.osd1_enabled
= false;
184 priv
->viu
.osd1_commit
= false;
186 priv
->viu
.vd1_enabled
= false;
187 priv
->viu
.vd1_commit
= false;
189 /* Disable VPP Postblend */
190 writel_bits_relaxed(VPP_OSD1_POSTBLEND
| VPP_VD1_POSTBLEND
|
191 VPP_VD1_PREBLEND
| VPP_POSTBLEND_ENABLE
, 0,
192 priv
->io_base
+ _REG(VPP_MISC
));
194 if (crtc
->state
->event
&& !crtc
->state
->active
) {
195 spin_lock_irq(&crtc
->dev
->event_lock
);
196 drm_crtc_send_vblank_event(crtc
, crtc
->state
->event
);
197 spin_unlock_irq(&crtc
->dev
->event_lock
);
199 crtc
->state
->event
= NULL
;
203 static void meson_crtc_atomic_begin(struct drm_crtc
*crtc
,
204 struct drm_atomic_state
*state
)
206 struct meson_crtc
*meson_crtc
= to_meson_crtc(crtc
);
209 if (crtc
->state
->event
) {
210 WARN_ON(drm_crtc_vblank_get(crtc
) != 0);
212 spin_lock_irqsave(&crtc
->dev
->event_lock
, flags
);
213 meson_crtc
->event
= crtc
->state
->event
;
214 spin_unlock_irqrestore(&crtc
->dev
->event_lock
, flags
);
215 crtc
->state
->event
= NULL
;
219 static void meson_crtc_atomic_flush(struct drm_crtc
*crtc
,
220 struct drm_atomic_state
*state
)
222 struct meson_crtc
*meson_crtc
= to_meson_crtc(crtc
);
223 struct meson_drm
*priv
= meson_crtc
->priv
;
225 priv
->viu
.osd1_commit
= true;
226 priv
->viu
.vd1_commit
= true;
229 static const struct drm_crtc_helper_funcs meson_crtc_helper_funcs
= {
230 .atomic_begin
= meson_crtc_atomic_begin
,
231 .atomic_flush
= meson_crtc_atomic_flush
,
232 .atomic_enable
= meson_crtc_atomic_enable
,
233 .atomic_disable
= meson_crtc_atomic_disable
,
236 static const struct drm_crtc_helper_funcs meson_g12a_crtc_helper_funcs
= {
237 .atomic_begin
= meson_crtc_atomic_begin
,
238 .atomic_flush
= meson_crtc_atomic_flush
,
239 .atomic_enable
= meson_g12a_crtc_atomic_enable
,
240 .atomic_disable
= meson_g12a_crtc_atomic_disable
,
243 static void meson_crtc_enable_osd1(struct meson_drm
*priv
)
245 writel_bits_relaxed(VPP_OSD1_POSTBLEND
, VPP_OSD1_POSTBLEND
,
246 priv
->io_base
+ _REG(VPP_MISC
));
249 static void meson_crtc_g12a_enable_osd1_afbc(struct meson_drm
*priv
)
251 writel_relaxed(priv
->viu
.osd1_blk2_cfg4
,
252 priv
->io_base
+ _REG(VIU_OSD1_BLK2_CFG_W4
));
254 writel_bits_relaxed(OSD_MEM_LINEAR_ADDR
, OSD_MEM_LINEAR_ADDR
,
255 priv
->io_base
+ _REG(VIU_OSD1_CTRL_STAT
));
257 writel_relaxed(priv
->viu
.osd1_blk1_cfg4
,
258 priv
->io_base
+ _REG(VIU_OSD1_BLK1_CFG_W4
));
260 meson_viu_g12a_enable_osd1_afbc(priv
);
262 writel_bits_relaxed(OSD_MEM_LINEAR_ADDR
, OSD_MEM_LINEAR_ADDR
,
263 priv
->io_base
+ _REG(VIU_OSD1_CTRL_STAT
));
265 writel_bits_relaxed(OSD_MALI_SRC_EN
, OSD_MALI_SRC_EN
,
266 priv
->io_base
+ _REG(VIU_OSD1_BLK0_CFG_W0
));
269 static void meson_g12a_crtc_enable_osd1(struct meson_drm
*priv
)
271 writel_relaxed(priv
->viu
.osd_blend_din0_scope_h
,
273 _REG(VIU_OSD_BLEND_DIN0_SCOPE_H
));
274 writel_relaxed(priv
->viu
.osd_blend_din0_scope_v
,
276 _REG(VIU_OSD_BLEND_DIN0_SCOPE_V
));
277 writel_relaxed(priv
->viu
.osb_blend0_size
,
279 _REG(VIU_OSD_BLEND_BLEND0_SIZE
));
280 writel_relaxed(priv
->viu
.osb_blend1_size
,
282 _REG(VIU_OSD_BLEND_BLEND1_SIZE
));
283 writel_bits_relaxed(3 << 8, 3 << 8,
284 priv
->io_base
+ _REG(OSD1_BLEND_SRC_CTRL
));
287 static void meson_crtc_enable_vd1(struct meson_drm
*priv
)
289 writel_bits_relaxed(VPP_VD1_PREBLEND
| VPP_VD1_POSTBLEND
|
290 VPP_COLOR_MNG_ENABLE
,
291 VPP_VD1_PREBLEND
| VPP_VD1_POSTBLEND
|
292 VPP_COLOR_MNG_ENABLE
,
293 priv
->io_base
+ _REG(VPP_MISC
));
295 writel_bits_relaxed(VIU_CTRL0_AFBC_TO_VD1
,
296 priv
->viu
.vd1_afbc
? VIU_CTRL0_AFBC_TO_VD1
: 0,
297 priv
->io_base
+ _REG(VIU_MISC_CTRL0
));
300 static void meson_g12a_crtc_enable_vd1(struct meson_drm
*priv
)
302 writel_relaxed(VD_BLEND_PREBLD_SRC_VD1
|
303 VD_BLEND_PREBLD_PREMULT_EN
|
304 VD_BLEND_POSTBLD_SRC_VD1
|
305 VD_BLEND_POSTBLD_PREMULT_EN
,
306 priv
->io_base
+ _REG(VD1_BLEND_SRC_CTRL
));
308 writel_relaxed(priv
->viu
.vd1_afbc
?
309 (VD1_AXI_SEL_AFBC
| AFBC_VD1_SEL
) : 0,
310 priv
->io_base
+ _REG(VD1_AFBCD0_MISC_CTRL
));
313 void meson_crtc_irq(struct meson_drm
*priv
)
315 struct meson_crtc
*meson_crtc
= to_meson_crtc(priv
->crtc
);
318 /* Update the OSD registers */
319 if (priv
->viu
.osd1_enabled
&& priv
->viu
.osd1_commit
) {
320 writel_relaxed(priv
->viu
.osd1_ctrl_stat
,
321 priv
->io_base
+ _REG(VIU_OSD1_CTRL_STAT
));
322 writel_relaxed(priv
->viu
.osd1_ctrl_stat2
,
323 priv
->io_base
+ _REG(VIU_OSD1_CTRL_STAT2
));
324 writel_relaxed(priv
->viu
.osd1_blk0_cfg
[0],
325 priv
->io_base
+ _REG(VIU_OSD1_BLK0_CFG_W0
));
326 writel_relaxed(priv
->viu
.osd1_blk0_cfg
[1],
327 priv
->io_base
+ _REG(VIU_OSD1_BLK0_CFG_W1
));
328 writel_relaxed(priv
->viu
.osd1_blk0_cfg
[2],
329 priv
->io_base
+ _REG(VIU_OSD1_BLK0_CFG_W2
));
330 writel_relaxed(priv
->viu
.osd1_blk0_cfg
[3],
331 priv
->io_base
+ _REG(VIU_OSD1_BLK0_CFG_W3
));
332 writel_relaxed(priv
->viu
.osd1_blk0_cfg
[4],
333 priv
->io_base
+ _REG(VIU_OSD1_BLK0_CFG_W4
));
335 if (priv
->viu
.osd1_afbcd
) {
336 if (meson_crtc
->enable_osd1_afbc
)
337 meson_crtc
->enable_osd1_afbc(priv
);
339 if (meson_crtc
->disable_osd1_afbc
)
340 meson_crtc
->disable_osd1_afbc(priv
);
341 if (priv
->afbcd
.ops
) {
342 priv
->afbcd
.ops
->reset(priv
);
343 priv
->afbcd
.ops
->disable(priv
);
345 meson_crtc
->vsync_forced
= false;
348 writel_relaxed(priv
->viu
.osd_sc_ctrl0
,
349 priv
->io_base
+ _REG(VPP_OSD_SC_CTRL0
));
350 writel_relaxed(priv
->viu
.osd_sc_i_wh_m1
,
351 priv
->io_base
+ _REG(VPP_OSD_SCI_WH_M1
));
352 writel_relaxed(priv
->viu
.osd_sc_o_h_start_end
,
353 priv
->io_base
+ _REG(VPP_OSD_SCO_H_START_END
));
354 writel_relaxed(priv
->viu
.osd_sc_o_v_start_end
,
355 priv
->io_base
+ _REG(VPP_OSD_SCO_V_START_END
));
356 writel_relaxed(priv
->viu
.osd_sc_v_ini_phase
,
357 priv
->io_base
+ _REG(VPP_OSD_VSC_INI_PHASE
));
358 writel_relaxed(priv
->viu
.osd_sc_v_phase_step
,
359 priv
->io_base
+ _REG(VPP_OSD_VSC_PHASE_STEP
));
360 writel_relaxed(priv
->viu
.osd_sc_h_ini_phase
,
361 priv
->io_base
+ _REG(VPP_OSD_HSC_INI_PHASE
));
362 writel_relaxed(priv
->viu
.osd_sc_h_phase_step
,
363 priv
->io_base
+ _REG(VPP_OSD_HSC_PHASE_STEP
));
364 writel_relaxed(priv
->viu
.osd_sc_h_ctrl0
,
365 priv
->io_base
+ _REG(VPP_OSD_HSC_CTRL0
));
366 writel_relaxed(priv
->viu
.osd_sc_v_ctrl0
,
367 priv
->io_base
+ _REG(VPP_OSD_VSC_CTRL0
));
369 if (!priv
->viu
.osd1_afbcd
)
370 meson_canvas_config(priv
->canvas
, priv
->canvas_id_osd1
,
372 priv
->viu
.osd1_stride
,
373 priv
->viu
.osd1_height
,
374 MESON_CANVAS_WRAP_NONE
,
375 MESON_CANVAS_BLKMODE_LINEAR
, 0);
378 if (meson_crtc
->enable_osd1
)
379 meson_crtc
->enable_osd1(priv
);
381 if (priv
->viu
.osd1_afbcd
) {
382 priv
->afbcd
.ops
->reset(priv
);
383 priv
->afbcd
.ops
->setup(priv
);
384 priv
->afbcd
.ops
->enable(priv
);
385 meson_crtc
->vsync_forced
= true;
388 priv
->viu
.osd1_commit
= false;
391 /* Update the VD1 registers */
392 if (priv
->viu
.vd1_enabled
&& priv
->viu
.vd1_commit
) {
394 if (priv
->viu
.vd1_afbc
) {
395 writel_relaxed(priv
->viu
.vd1_afbc_head_addr
,
397 _REG(AFBC_HEAD_BADDR
));
398 writel_relaxed(priv
->viu
.vd1_afbc_body_addr
,
400 _REG(AFBC_BODY_BADDR
));
401 writel_relaxed(priv
->viu
.vd1_afbc_en
,
404 writel_relaxed(priv
->viu
.vd1_afbc_mode
,
407 writel_relaxed(priv
->viu
.vd1_afbc_size_in
,
410 writel_relaxed(priv
->viu
.vd1_afbc_dec_def_color
,
412 _REG(AFBC_DEC_DEF_COLOR
));
413 writel_relaxed(priv
->viu
.vd1_afbc_conv_ctrl
,
415 _REG(AFBC_CONV_CTRL
));
416 writel_relaxed(priv
->viu
.vd1_afbc_size_out
,
418 _REG(AFBC_SIZE_OUT
));
419 writel_relaxed(priv
->viu
.vd1_afbc_vd_cfmt_ctrl
,
421 _REG(AFBC_VD_CFMT_CTRL
));
422 writel_relaxed(priv
->viu
.vd1_afbc_vd_cfmt_w
,
424 _REG(AFBC_VD_CFMT_W
));
425 writel_relaxed(priv
->viu
.vd1_afbc_mif_hor_scope
,
427 _REG(AFBC_MIF_HOR_SCOPE
));
428 writel_relaxed(priv
->viu
.vd1_afbc_mif_ver_scope
,
430 _REG(AFBC_MIF_VER_SCOPE
));
431 writel_relaxed(priv
->viu
.vd1_afbc_pixel_hor_scope
,
433 _REG(AFBC_PIXEL_HOR_SCOPE
));
434 writel_relaxed(priv
->viu
.vd1_afbc_pixel_ver_scope
,
436 _REG(AFBC_PIXEL_VER_SCOPE
));
437 writel_relaxed(priv
->viu
.vd1_afbc_vd_cfmt_h
,
439 _REG(AFBC_VD_CFMT_H
));
441 switch (priv
->viu
.vd1_planes
) {
443 meson_canvas_config(priv
->canvas
,
444 priv
->canvas_id_vd1_2
,
446 priv
->viu
.vd1_stride2
,
447 priv
->viu
.vd1_height2
,
448 MESON_CANVAS_WRAP_NONE
,
449 MESON_CANVAS_BLKMODE_LINEAR
,
450 MESON_CANVAS_ENDIAN_SWAP64
);
453 meson_canvas_config(priv
->canvas
,
454 priv
->canvas_id_vd1_1
,
456 priv
->viu
.vd1_stride1
,
457 priv
->viu
.vd1_height1
,
458 MESON_CANVAS_WRAP_NONE
,
459 MESON_CANVAS_BLKMODE_LINEAR
,
460 MESON_CANVAS_ENDIAN_SWAP64
);
463 meson_canvas_config(priv
->canvas
,
464 priv
->canvas_id_vd1_0
,
466 priv
->viu
.vd1_stride0
,
467 priv
->viu
.vd1_height0
,
468 MESON_CANVAS_WRAP_NONE
,
469 MESON_CANVAS_BLKMODE_LINEAR
,
470 MESON_CANVAS_ENDIAN_SWAP64
);
473 writel_relaxed(0, priv
->io_base
+ _REG(AFBC_ENABLE
));
476 writel_relaxed(priv
->viu
.vd1_if0_gen_reg
,
477 priv
->io_base
+ meson_crtc
->viu_offset
+
478 _REG(VD1_IF0_GEN_REG
));
479 writel_relaxed(priv
->viu
.vd1_if0_gen_reg
,
480 priv
->io_base
+ meson_crtc
->viu_offset
+
481 _REG(VD2_IF0_GEN_REG
));
482 writel_relaxed(priv
->viu
.vd1_if0_gen_reg2
,
483 priv
->io_base
+ meson_crtc
->viu_offset
+
484 _REG(VD1_IF0_GEN_REG2
));
485 writel_relaxed(priv
->viu
.viu_vd1_fmt_ctrl
,
486 priv
->io_base
+ meson_crtc
->viu_offset
+
487 _REG(VIU_VD1_FMT_CTRL
));
488 writel_relaxed(priv
->viu
.viu_vd1_fmt_ctrl
,
489 priv
->io_base
+ meson_crtc
->viu_offset
+
490 _REG(VIU_VD2_FMT_CTRL
));
491 writel_relaxed(priv
->viu
.viu_vd1_fmt_w
,
492 priv
->io_base
+ meson_crtc
->viu_offset
+
493 _REG(VIU_VD1_FMT_W
));
494 writel_relaxed(priv
->viu
.viu_vd1_fmt_w
,
495 priv
->io_base
+ meson_crtc
->viu_offset
+
496 _REG(VIU_VD2_FMT_W
));
497 writel_relaxed(priv
->viu
.vd1_if0_canvas0
,
498 priv
->io_base
+ meson_crtc
->viu_offset
+
499 _REG(VD1_IF0_CANVAS0
));
500 writel_relaxed(priv
->viu
.vd1_if0_canvas0
,
501 priv
->io_base
+ meson_crtc
->viu_offset
+
502 _REG(VD1_IF0_CANVAS1
));
503 writel_relaxed(priv
->viu
.vd1_if0_canvas0
,
504 priv
->io_base
+ meson_crtc
->viu_offset
+
505 _REG(VD2_IF0_CANVAS0
));
506 writel_relaxed(priv
->viu
.vd1_if0_canvas0
,
507 priv
->io_base
+ meson_crtc
->viu_offset
+
508 _REG(VD2_IF0_CANVAS1
));
509 writel_relaxed(priv
->viu
.vd1_if0_luma_x0
,
510 priv
->io_base
+ meson_crtc
->viu_offset
+
511 _REG(VD1_IF0_LUMA_X0
));
512 writel_relaxed(priv
->viu
.vd1_if0_luma_x0
,
513 priv
->io_base
+ meson_crtc
->viu_offset
+
514 _REG(VD1_IF0_LUMA_X1
));
515 writel_relaxed(priv
->viu
.vd1_if0_luma_x0
,
516 priv
->io_base
+ meson_crtc
->viu_offset
+
517 _REG(VD2_IF0_LUMA_X0
));
518 writel_relaxed(priv
->viu
.vd1_if0_luma_x0
,
519 priv
->io_base
+ meson_crtc
->viu_offset
+
520 _REG(VD2_IF0_LUMA_X1
));
521 writel_relaxed(priv
->viu
.vd1_if0_luma_y0
,
522 priv
->io_base
+ meson_crtc
->viu_offset
+
523 _REG(VD1_IF0_LUMA_Y0
));
524 writel_relaxed(priv
->viu
.vd1_if0_luma_y0
,
525 priv
->io_base
+ meson_crtc
->viu_offset
+
526 _REG(VD1_IF0_LUMA_Y1
));
527 writel_relaxed(priv
->viu
.vd1_if0_luma_y0
,
528 priv
->io_base
+ meson_crtc
->viu_offset
+
529 _REG(VD2_IF0_LUMA_Y0
));
530 writel_relaxed(priv
->viu
.vd1_if0_luma_y0
,
531 priv
->io_base
+ meson_crtc
->viu_offset
+
532 _REG(VD2_IF0_LUMA_Y1
));
533 writel_relaxed(priv
->viu
.vd1_if0_chroma_x0
,
534 priv
->io_base
+ meson_crtc
->viu_offset
+
535 _REG(VD1_IF0_CHROMA_X0
));
536 writel_relaxed(priv
->viu
.vd1_if0_chroma_x0
,
537 priv
->io_base
+ meson_crtc
->viu_offset
+
538 _REG(VD1_IF0_CHROMA_X1
));
539 writel_relaxed(priv
->viu
.vd1_if0_chroma_x0
,
540 priv
->io_base
+ meson_crtc
->viu_offset
+
541 _REG(VD2_IF0_CHROMA_X0
));
542 writel_relaxed(priv
->viu
.vd1_if0_chroma_x0
,
543 priv
->io_base
+ meson_crtc
->viu_offset
+
544 _REG(VD2_IF0_CHROMA_X1
));
545 writel_relaxed(priv
->viu
.vd1_if0_chroma_y0
,
546 priv
->io_base
+ meson_crtc
->viu_offset
+
547 _REG(VD1_IF0_CHROMA_Y0
));
548 writel_relaxed(priv
->viu
.vd1_if0_chroma_y0
,
549 priv
->io_base
+ meson_crtc
->viu_offset
+
550 _REG(VD1_IF0_CHROMA_Y1
));
551 writel_relaxed(priv
->viu
.vd1_if0_chroma_y0
,
552 priv
->io_base
+ meson_crtc
->viu_offset
+
553 _REG(VD2_IF0_CHROMA_Y0
));
554 writel_relaxed(priv
->viu
.vd1_if0_chroma_y0
,
555 priv
->io_base
+ meson_crtc
->viu_offset
+
556 _REG(VD2_IF0_CHROMA_Y1
));
557 writel_relaxed(priv
->viu
.vd1_if0_repeat_loop
,
558 priv
->io_base
+ meson_crtc
->viu_offset
+
559 _REG(VD1_IF0_RPT_LOOP
));
560 writel_relaxed(priv
->viu
.vd1_if0_repeat_loop
,
561 priv
->io_base
+ meson_crtc
->viu_offset
+
562 _REG(VD2_IF0_RPT_LOOP
));
563 writel_relaxed(priv
->viu
.vd1_if0_luma0_rpt_pat
,
564 priv
->io_base
+ meson_crtc
->viu_offset
+
565 _REG(VD1_IF0_LUMA0_RPT_PAT
));
566 writel_relaxed(priv
->viu
.vd1_if0_luma0_rpt_pat
,
567 priv
->io_base
+ meson_crtc
->viu_offset
+
568 _REG(VD2_IF0_LUMA0_RPT_PAT
));
569 writel_relaxed(priv
->viu
.vd1_if0_luma0_rpt_pat
,
570 priv
->io_base
+ meson_crtc
->viu_offset
+
571 _REG(VD1_IF0_LUMA1_RPT_PAT
));
572 writel_relaxed(priv
->viu
.vd1_if0_luma0_rpt_pat
,
573 priv
->io_base
+ meson_crtc
->viu_offset
+
574 _REG(VD2_IF0_LUMA1_RPT_PAT
));
575 writel_relaxed(priv
->viu
.vd1_if0_chroma0_rpt_pat
,
576 priv
->io_base
+ meson_crtc
->viu_offset
+
577 _REG(VD1_IF0_CHROMA0_RPT_PAT
));
578 writel_relaxed(priv
->viu
.vd1_if0_chroma0_rpt_pat
,
579 priv
->io_base
+ meson_crtc
->viu_offset
+
580 _REG(VD2_IF0_CHROMA0_RPT_PAT
));
581 writel_relaxed(priv
->viu
.vd1_if0_chroma0_rpt_pat
,
582 priv
->io_base
+ meson_crtc
->viu_offset
+
583 _REG(VD1_IF0_CHROMA1_RPT_PAT
));
584 writel_relaxed(priv
->viu
.vd1_if0_chroma0_rpt_pat
,
585 priv
->io_base
+ meson_crtc
->viu_offset
+
586 _REG(VD2_IF0_CHROMA1_RPT_PAT
));
587 writel_relaxed(0, priv
->io_base
+ meson_crtc
->viu_offset
+
588 _REG(VD1_IF0_LUMA_PSEL
));
589 writel_relaxed(0, priv
->io_base
+ meson_crtc
->viu_offset
+
590 _REG(VD1_IF0_CHROMA_PSEL
));
591 writel_relaxed(0, priv
->io_base
+ meson_crtc
->viu_offset
+
592 _REG(VD2_IF0_LUMA_PSEL
));
593 writel_relaxed(0, priv
->io_base
+ meson_crtc
->viu_offset
+
594 _REG(VD2_IF0_CHROMA_PSEL
));
595 writel_relaxed(priv
->viu
.vd1_range_map_y
,
596 priv
->io_base
+ meson_crtc
->viu_offset
+
597 _REG(VD1_IF0_RANGE_MAP_Y
));
598 writel_relaxed(priv
->viu
.vd1_range_map_cb
,
599 priv
->io_base
+ meson_crtc
->viu_offset
+
600 _REG(VD1_IF0_RANGE_MAP_CB
));
601 writel_relaxed(priv
->viu
.vd1_range_map_cr
,
602 priv
->io_base
+ meson_crtc
->viu_offset
+
603 _REG(VD1_IF0_RANGE_MAP_CR
));
604 writel_relaxed(VPP_VSC_BANK_LENGTH(4) |
605 VPP_HSC_BANK_LENGTH(4) |
606 VPP_SC_VD_EN_ENABLE
|
607 VPP_SC_TOP_EN_ENABLE
|
608 VPP_SC_HSC_EN_ENABLE
|
609 VPP_SC_VSC_EN_ENABLE
,
610 priv
->io_base
+ _REG(VPP_SC_MISC
));
611 writel_relaxed(priv
->viu
.vpp_pic_in_height
,
612 priv
->io_base
+ _REG(VPP_PIC_IN_HEIGHT
));
613 writel_relaxed(priv
->viu
.vpp_postblend_vd1_h_start_end
,
614 priv
->io_base
+ _REG(VPP_POSTBLEND_VD1_H_START_END
));
615 writel_relaxed(priv
->viu
.vpp_blend_vd2_h_start_end
,
616 priv
->io_base
+ _REG(VPP_BLEND_VD2_H_START_END
));
617 writel_relaxed(priv
->viu
.vpp_postblend_vd1_v_start_end
,
618 priv
->io_base
+ _REG(VPP_POSTBLEND_VD1_V_START_END
));
619 writel_relaxed(priv
->viu
.vpp_blend_vd2_v_start_end
,
620 priv
->io_base
+ _REG(VPP_BLEND_VD2_V_START_END
));
621 writel_relaxed(priv
->viu
.vpp_hsc_region12_startp
,
622 priv
->io_base
+ _REG(VPP_HSC_REGION12_STARTP
));
623 writel_relaxed(priv
->viu
.vpp_hsc_region34_startp
,
624 priv
->io_base
+ _REG(VPP_HSC_REGION34_STARTP
));
625 writel_relaxed(priv
->viu
.vpp_hsc_region4_endp
,
626 priv
->io_base
+ _REG(VPP_HSC_REGION4_ENDP
));
627 writel_relaxed(priv
->viu
.vpp_hsc_start_phase_step
,
628 priv
->io_base
+ _REG(VPP_HSC_START_PHASE_STEP
));
629 writel_relaxed(priv
->viu
.vpp_hsc_region1_phase_slope
,
630 priv
->io_base
+ _REG(VPP_HSC_REGION1_PHASE_SLOPE
));
631 writel_relaxed(priv
->viu
.vpp_hsc_region3_phase_slope
,
632 priv
->io_base
+ _REG(VPP_HSC_REGION3_PHASE_SLOPE
));
633 writel_relaxed(priv
->viu
.vpp_line_in_length
,
634 priv
->io_base
+ _REG(VPP_LINE_IN_LENGTH
));
635 writel_relaxed(priv
->viu
.vpp_preblend_h_size
,
636 priv
->io_base
+ _REG(VPP_PREBLEND_H_SIZE
));
637 writel_relaxed(priv
->viu
.vpp_vsc_region12_startp
,
638 priv
->io_base
+ _REG(VPP_VSC_REGION12_STARTP
));
639 writel_relaxed(priv
->viu
.vpp_vsc_region34_startp
,
640 priv
->io_base
+ _REG(VPP_VSC_REGION34_STARTP
));
641 writel_relaxed(priv
->viu
.vpp_vsc_region4_endp
,
642 priv
->io_base
+ _REG(VPP_VSC_REGION4_ENDP
));
643 writel_relaxed(priv
->viu
.vpp_vsc_start_phase_step
,
644 priv
->io_base
+ _REG(VPP_VSC_START_PHASE_STEP
));
645 writel_relaxed(priv
->viu
.vpp_vsc_ini_phase
,
646 priv
->io_base
+ _REG(VPP_VSC_INI_PHASE
));
647 writel_relaxed(priv
->viu
.vpp_vsc_phase_ctrl
,
648 priv
->io_base
+ _REG(VPP_VSC_PHASE_CTRL
));
649 writel_relaxed(priv
->viu
.vpp_hsc_phase_ctrl
,
650 priv
->io_base
+ _REG(VPP_HSC_PHASE_CTRL
));
651 writel_relaxed(0x42, priv
->io_base
+ _REG(VPP_SCALE_COEF_IDX
));
654 if (meson_crtc
->enable_vd1
)
655 meson_crtc
->enable_vd1(priv
);
657 priv
->viu
.vd1_commit
= false;
660 if (meson_crtc
->vsync_disabled
)
663 drm_crtc_handle_vblank(priv
->crtc
);
665 spin_lock_irqsave(&priv
->drm
->event_lock
, flags
);
666 if (meson_crtc
->event
) {
667 drm_crtc_send_vblank_event(priv
->crtc
, meson_crtc
->event
);
668 drm_crtc_vblank_put(priv
->crtc
);
669 meson_crtc
->event
= NULL
;
671 spin_unlock_irqrestore(&priv
->drm
->event_lock
, flags
);
674 int meson_crtc_create(struct meson_drm
*priv
)
676 struct meson_crtc
*meson_crtc
;
677 struct drm_crtc
*crtc
;
680 meson_crtc
= devm_kzalloc(priv
->drm
->dev
, sizeof(*meson_crtc
),
685 meson_crtc
->priv
= priv
;
686 crtc
= &meson_crtc
->base
;
687 ret
= drm_crtc_init_with_planes(priv
->drm
, crtc
,
688 priv
->primary_plane
, NULL
,
689 &meson_crtc_funcs
, "meson_crtc");
691 dev_err(priv
->drm
->dev
, "Failed to init CRTC\n");
695 if (meson_vpu_is_compatible(priv
, VPU_COMPATIBLE_G12A
)) {
696 meson_crtc
->enable_osd1
= meson_g12a_crtc_enable_osd1
;
697 meson_crtc
->enable_vd1
= meson_g12a_crtc_enable_vd1
;
698 meson_crtc
->viu_offset
= MESON_G12A_VIU_OFFSET
;
699 meson_crtc
->enable_osd1_afbc
=
700 meson_crtc_g12a_enable_osd1_afbc
;
701 meson_crtc
->disable_osd1_afbc
=
702 meson_viu_g12a_disable_osd1_afbc
;
703 drm_crtc_helper_add(crtc
, &meson_g12a_crtc_helper_funcs
);
705 meson_crtc
->enable_osd1
= meson_crtc_enable_osd1
;
706 meson_crtc
->enable_vd1
= meson_crtc_enable_vd1
;
707 if (meson_vpu_is_compatible(priv
, VPU_COMPATIBLE_GXM
)) {
708 meson_crtc
->enable_osd1_afbc
=
709 meson_viu_gxm_enable_osd1_afbc
;
710 meson_crtc
->disable_osd1_afbc
=
711 meson_viu_gxm_disable_osd1_afbc
;
713 drm_crtc_helper_add(crtc
, &meson_crtc_helper_funcs
);