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_crtc_state
*old_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_crtc_state
*old_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_crtc_state
*old_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_crtc_state
*old_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_crtc_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_crtc_state
*old_crtc_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
));
296 static void meson_g12a_crtc_enable_vd1(struct meson_drm
*priv
)
298 writel_relaxed(VD_BLEND_PREBLD_SRC_VD1
|
299 VD_BLEND_PREBLD_PREMULT_EN
|
300 VD_BLEND_POSTBLD_SRC_VD1
|
301 VD_BLEND_POSTBLD_PREMULT_EN
,
302 priv
->io_base
+ _REG(VD1_BLEND_SRC_CTRL
));
305 void meson_crtc_irq(struct meson_drm
*priv
)
307 struct meson_crtc
*meson_crtc
= to_meson_crtc(priv
->crtc
);
310 /* Update the OSD registers */
311 if (priv
->viu
.osd1_enabled
&& priv
->viu
.osd1_commit
) {
312 writel_relaxed(priv
->viu
.osd1_ctrl_stat
,
313 priv
->io_base
+ _REG(VIU_OSD1_CTRL_STAT
));
314 writel_relaxed(priv
->viu
.osd1_ctrl_stat2
,
315 priv
->io_base
+ _REG(VIU_OSD1_CTRL_STAT2
));
316 writel_relaxed(priv
->viu
.osd1_blk0_cfg
[0],
317 priv
->io_base
+ _REG(VIU_OSD1_BLK0_CFG_W0
));
318 writel_relaxed(priv
->viu
.osd1_blk0_cfg
[1],
319 priv
->io_base
+ _REG(VIU_OSD1_BLK0_CFG_W1
));
320 writel_relaxed(priv
->viu
.osd1_blk0_cfg
[2],
321 priv
->io_base
+ _REG(VIU_OSD1_BLK0_CFG_W2
));
322 writel_relaxed(priv
->viu
.osd1_blk0_cfg
[3],
323 priv
->io_base
+ _REG(VIU_OSD1_BLK0_CFG_W3
));
324 writel_relaxed(priv
->viu
.osd1_blk0_cfg
[4],
325 priv
->io_base
+ _REG(VIU_OSD1_BLK0_CFG_W4
));
327 if (priv
->viu
.osd1_afbcd
) {
328 if (meson_crtc
->enable_osd1_afbc
)
329 meson_crtc
->enable_osd1_afbc(priv
);
331 if (meson_crtc
->disable_osd1_afbc
)
332 meson_crtc
->disable_osd1_afbc(priv
);
333 if (priv
->afbcd
.ops
) {
334 priv
->afbcd
.ops
->reset(priv
);
335 priv
->afbcd
.ops
->disable(priv
);
337 meson_crtc
->vsync_forced
= false;
340 writel_relaxed(priv
->viu
.osd_sc_ctrl0
,
341 priv
->io_base
+ _REG(VPP_OSD_SC_CTRL0
));
342 writel_relaxed(priv
->viu
.osd_sc_i_wh_m1
,
343 priv
->io_base
+ _REG(VPP_OSD_SCI_WH_M1
));
344 writel_relaxed(priv
->viu
.osd_sc_o_h_start_end
,
345 priv
->io_base
+ _REG(VPP_OSD_SCO_H_START_END
));
346 writel_relaxed(priv
->viu
.osd_sc_o_v_start_end
,
347 priv
->io_base
+ _REG(VPP_OSD_SCO_V_START_END
));
348 writel_relaxed(priv
->viu
.osd_sc_v_ini_phase
,
349 priv
->io_base
+ _REG(VPP_OSD_VSC_INI_PHASE
));
350 writel_relaxed(priv
->viu
.osd_sc_v_phase_step
,
351 priv
->io_base
+ _REG(VPP_OSD_VSC_PHASE_STEP
));
352 writel_relaxed(priv
->viu
.osd_sc_h_ini_phase
,
353 priv
->io_base
+ _REG(VPP_OSD_HSC_INI_PHASE
));
354 writel_relaxed(priv
->viu
.osd_sc_h_phase_step
,
355 priv
->io_base
+ _REG(VPP_OSD_HSC_PHASE_STEP
));
356 writel_relaxed(priv
->viu
.osd_sc_h_ctrl0
,
357 priv
->io_base
+ _REG(VPP_OSD_HSC_CTRL0
));
358 writel_relaxed(priv
->viu
.osd_sc_v_ctrl0
,
359 priv
->io_base
+ _REG(VPP_OSD_VSC_CTRL0
));
361 if (!priv
->viu
.osd1_afbcd
)
362 meson_canvas_config(priv
->canvas
, priv
->canvas_id_osd1
,
364 priv
->viu
.osd1_stride
,
365 priv
->viu
.osd1_height
,
366 MESON_CANVAS_WRAP_NONE
,
367 MESON_CANVAS_BLKMODE_LINEAR
, 0);
370 if (meson_crtc
->enable_osd1
)
371 meson_crtc
->enable_osd1(priv
);
373 if (priv
->viu
.osd1_afbcd
) {
374 priv
->afbcd
.ops
->reset(priv
);
375 priv
->afbcd
.ops
->setup(priv
);
376 priv
->afbcd
.ops
->enable(priv
);
377 meson_crtc
->vsync_forced
= true;
380 priv
->viu
.osd1_commit
= false;
383 /* Update the VD1 registers */
384 if (priv
->viu
.vd1_enabled
&& priv
->viu
.vd1_commit
) {
386 switch (priv
->viu
.vd1_planes
) {
388 meson_canvas_config(priv
->canvas
,
389 priv
->canvas_id_vd1_2
,
391 priv
->viu
.vd1_stride2
,
392 priv
->viu
.vd1_height2
,
393 MESON_CANVAS_WRAP_NONE
,
394 MESON_CANVAS_BLKMODE_LINEAR
,
395 MESON_CANVAS_ENDIAN_SWAP64
);
398 meson_canvas_config(priv
->canvas
,
399 priv
->canvas_id_vd1_1
,
401 priv
->viu
.vd1_stride1
,
402 priv
->viu
.vd1_height1
,
403 MESON_CANVAS_WRAP_NONE
,
404 MESON_CANVAS_BLKMODE_LINEAR
,
405 MESON_CANVAS_ENDIAN_SWAP64
);
408 meson_canvas_config(priv
->canvas
,
409 priv
->canvas_id_vd1_0
,
411 priv
->viu
.vd1_stride0
,
412 priv
->viu
.vd1_height0
,
413 MESON_CANVAS_WRAP_NONE
,
414 MESON_CANVAS_BLKMODE_LINEAR
,
415 MESON_CANVAS_ENDIAN_SWAP64
);
418 writel_relaxed(priv
->viu
.vd1_if0_gen_reg
,
419 priv
->io_base
+ meson_crtc
->viu_offset
+
420 _REG(VD1_IF0_GEN_REG
));
421 writel_relaxed(priv
->viu
.vd1_if0_gen_reg
,
422 priv
->io_base
+ meson_crtc
->viu_offset
+
423 _REG(VD2_IF0_GEN_REG
));
424 writel_relaxed(priv
->viu
.vd1_if0_gen_reg2
,
425 priv
->io_base
+ meson_crtc
->viu_offset
+
426 _REG(VD1_IF0_GEN_REG2
));
427 writel_relaxed(priv
->viu
.viu_vd1_fmt_ctrl
,
428 priv
->io_base
+ meson_crtc
->viu_offset
+
429 _REG(VIU_VD1_FMT_CTRL
));
430 writel_relaxed(priv
->viu
.viu_vd1_fmt_ctrl
,
431 priv
->io_base
+ meson_crtc
->viu_offset
+
432 _REG(VIU_VD2_FMT_CTRL
));
433 writel_relaxed(priv
->viu
.viu_vd1_fmt_w
,
434 priv
->io_base
+ meson_crtc
->viu_offset
+
435 _REG(VIU_VD1_FMT_W
));
436 writel_relaxed(priv
->viu
.viu_vd1_fmt_w
,
437 priv
->io_base
+ meson_crtc
->viu_offset
+
438 _REG(VIU_VD2_FMT_W
));
439 writel_relaxed(priv
->viu
.vd1_if0_canvas0
,
440 priv
->io_base
+ meson_crtc
->viu_offset
+
441 _REG(VD1_IF0_CANVAS0
));
442 writel_relaxed(priv
->viu
.vd1_if0_canvas0
,
443 priv
->io_base
+ meson_crtc
->viu_offset
+
444 _REG(VD1_IF0_CANVAS1
));
445 writel_relaxed(priv
->viu
.vd1_if0_canvas0
,
446 priv
->io_base
+ meson_crtc
->viu_offset
+
447 _REG(VD2_IF0_CANVAS0
));
448 writel_relaxed(priv
->viu
.vd1_if0_canvas0
,
449 priv
->io_base
+ meson_crtc
->viu_offset
+
450 _REG(VD2_IF0_CANVAS1
));
451 writel_relaxed(priv
->viu
.vd1_if0_luma_x0
,
452 priv
->io_base
+ meson_crtc
->viu_offset
+
453 _REG(VD1_IF0_LUMA_X0
));
454 writel_relaxed(priv
->viu
.vd1_if0_luma_x0
,
455 priv
->io_base
+ meson_crtc
->viu_offset
+
456 _REG(VD1_IF0_LUMA_X1
));
457 writel_relaxed(priv
->viu
.vd1_if0_luma_x0
,
458 priv
->io_base
+ meson_crtc
->viu_offset
+
459 _REG(VD2_IF0_LUMA_X0
));
460 writel_relaxed(priv
->viu
.vd1_if0_luma_x0
,
461 priv
->io_base
+ meson_crtc
->viu_offset
+
462 _REG(VD2_IF0_LUMA_X1
));
463 writel_relaxed(priv
->viu
.vd1_if0_luma_y0
,
464 priv
->io_base
+ meson_crtc
->viu_offset
+
465 _REG(VD1_IF0_LUMA_Y0
));
466 writel_relaxed(priv
->viu
.vd1_if0_luma_y0
,
467 priv
->io_base
+ meson_crtc
->viu_offset
+
468 _REG(VD1_IF0_LUMA_Y1
));
469 writel_relaxed(priv
->viu
.vd1_if0_luma_y0
,
470 priv
->io_base
+ meson_crtc
->viu_offset
+
471 _REG(VD2_IF0_LUMA_Y0
));
472 writel_relaxed(priv
->viu
.vd1_if0_luma_y0
,
473 priv
->io_base
+ meson_crtc
->viu_offset
+
474 _REG(VD2_IF0_LUMA_Y1
));
475 writel_relaxed(priv
->viu
.vd1_if0_chroma_x0
,
476 priv
->io_base
+ meson_crtc
->viu_offset
+
477 _REG(VD1_IF0_CHROMA_X0
));
478 writel_relaxed(priv
->viu
.vd1_if0_chroma_x0
,
479 priv
->io_base
+ meson_crtc
->viu_offset
+
480 _REG(VD1_IF0_CHROMA_X1
));
481 writel_relaxed(priv
->viu
.vd1_if0_chroma_x0
,
482 priv
->io_base
+ meson_crtc
->viu_offset
+
483 _REG(VD2_IF0_CHROMA_X0
));
484 writel_relaxed(priv
->viu
.vd1_if0_chroma_x0
,
485 priv
->io_base
+ meson_crtc
->viu_offset
+
486 _REG(VD2_IF0_CHROMA_X1
));
487 writel_relaxed(priv
->viu
.vd1_if0_chroma_y0
,
488 priv
->io_base
+ meson_crtc
->viu_offset
+
489 _REG(VD1_IF0_CHROMA_Y0
));
490 writel_relaxed(priv
->viu
.vd1_if0_chroma_y0
,
491 priv
->io_base
+ meson_crtc
->viu_offset
+
492 _REG(VD1_IF0_CHROMA_Y1
));
493 writel_relaxed(priv
->viu
.vd1_if0_chroma_y0
,
494 priv
->io_base
+ meson_crtc
->viu_offset
+
495 _REG(VD2_IF0_CHROMA_Y0
));
496 writel_relaxed(priv
->viu
.vd1_if0_chroma_y0
,
497 priv
->io_base
+ meson_crtc
->viu_offset
+
498 _REG(VD2_IF0_CHROMA_Y1
));
499 writel_relaxed(priv
->viu
.vd1_if0_repeat_loop
,
500 priv
->io_base
+ meson_crtc
->viu_offset
+
501 _REG(VD1_IF0_RPT_LOOP
));
502 writel_relaxed(priv
->viu
.vd1_if0_repeat_loop
,
503 priv
->io_base
+ meson_crtc
->viu_offset
+
504 _REG(VD2_IF0_RPT_LOOP
));
505 writel_relaxed(priv
->viu
.vd1_if0_luma0_rpt_pat
,
506 priv
->io_base
+ meson_crtc
->viu_offset
+
507 _REG(VD1_IF0_LUMA0_RPT_PAT
));
508 writel_relaxed(priv
->viu
.vd1_if0_luma0_rpt_pat
,
509 priv
->io_base
+ meson_crtc
->viu_offset
+
510 _REG(VD2_IF0_LUMA0_RPT_PAT
));
511 writel_relaxed(priv
->viu
.vd1_if0_luma0_rpt_pat
,
512 priv
->io_base
+ meson_crtc
->viu_offset
+
513 _REG(VD1_IF0_LUMA1_RPT_PAT
));
514 writel_relaxed(priv
->viu
.vd1_if0_luma0_rpt_pat
,
515 priv
->io_base
+ meson_crtc
->viu_offset
+
516 _REG(VD2_IF0_LUMA1_RPT_PAT
));
517 writel_relaxed(priv
->viu
.vd1_if0_chroma0_rpt_pat
,
518 priv
->io_base
+ meson_crtc
->viu_offset
+
519 _REG(VD1_IF0_CHROMA0_RPT_PAT
));
520 writel_relaxed(priv
->viu
.vd1_if0_chroma0_rpt_pat
,
521 priv
->io_base
+ meson_crtc
->viu_offset
+
522 _REG(VD2_IF0_CHROMA0_RPT_PAT
));
523 writel_relaxed(priv
->viu
.vd1_if0_chroma0_rpt_pat
,
524 priv
->io_base
+ meson_crtc
->viu_offset
+
525 _REG(VD1_IF0_CHROMA1_RPT_PAT
));
526 writel_relaxed(priv
->viu
.vd1_if0_chroma0_rpt_pat
,
527 priv
->io_base
+ meson_crtc
->viu_offset
+
528 _REG(VD2_IF0_CHROMA1_RPT_PAT
));
529 writel_relaxed(0, priv
->io_base
+ meson_crtc
->viu_offset
+
530 _REG(VD1_IF0_LUMA_PSEL
));
531 writel_relaxed(0, priv
->io_base
+ meson_crtc
->viu_offset
+
532 _REG(VD1_IF0_CHROMA_PSEL
));
533 writel_relaxed(0, priv
->io_base
+ meson_crtc
->viu_offset
+
534 _REG(VD2_IF0_LUMA_PSEL
));
535 writel_relaxed(0, priv
->io_base
+ meson_crtc
->viu_offset
+
536 _REG(VD2_IF0_CHROMA_PSEL
));
537 writel_relaxed(priv
->viu
.vd1_range_map_y
,
538 priv
->io_base
+ meson_crtc
->viu_offset
+
539 _REG(VD1_IF0_RANGE_MAP_Y
));
540 writel_relaxed(priv
->viu
.vd1_range_map_cb
,
541 priv
->io_base
+ meson_crtc
->viu_offset
+
542 _REG(VD1_IF0_RANGE_MAP_CB
));
543 writel_relaxed(priv
->viu
.vd1_range_map_cr
,
544 priv
->io_base
+ meson_crtc
->viu_offset
+
545 _REG(VD1_IF0_RANGE_MAP_CR
));
546 writel_relaxed(VPP_VSC_BANK_LENGTH(4) |
547 VPP_HSC_BANK_LENGTH(4) |
548 VPP_SC_VD_EN_ENABLE
|
549 VPP_SC_TOP_EN_ENABLE
|
550 VPP_SC_HSC_EN_ENABLE
|
551 VPP_SC_VSC_EN_ENABLE
,
552 priv
->io_base
+ _REG(VPP_SC_MISC
));
553 writel_relaxed(priv
->viu
.vpp_pic_in_height
,
554 priv
->io_base
+ _REG(VPP_PIC_IN_HEIGHT
));
555 writel_relaxed(priv
->viu
.vpp_postblend_vd1_h_start_end
,
556 priv
->io_base
+ _REG(VPP_POSTBLEND_VD1_H_START_END
));
557 writel_relaxed(priv
->viu
.vpp_blend_vd2_h_start_end
,
558 priv
->io_base
+ _REG(VPP_BLEND_VD2_H_START_END
));
559 writel_relaxed(priv
->viu
.vpp_postblend_vd1_v_start_end
,
560 priv
->io_base
+ _REG(VPP_POSTBLEND_VD1_V_START_END
));
561 writel_relaxed(priv
->viu
.vpp_blend_vd2_v_start_end
,
562 priv
->io_base
+ _REG(VPP_BLEND_VD2_V_START_END
));
563 writel_relaxed(priv
->viu
.vpp_hsc_region12_startp
,
564 priv
->io_base
+ _REG(VPP_HSC_REGION12_STARTP
));
565 writel_relaxed(priv
->viu
.vpp_hsc_region34_startp
,
566 priv
->io_base
+ _REG(VPP_HSC_REGION34_STARTP
));
567 writel_relaxed(priv
->viu
.vpp_hsc_region4_endp
,
568 priv
->io_base
+ _REG(VPP_HSC_REGION4_ENDP
));
569 writel_relaxed(priv
->viu
.vpp_hsc_start_phase_step
,
570 priv
->io_base
+ _REG(VPP_HSC_START_PHASE_STEP
));
571 writel_relaxed(priv
->viu
.vpp_hsc_region1_phase_slope
,
572 priv
->io_base
+ _REG(VPP_HSC_REGION1_PHASE_SLOPE
));
573 writel_relaxed(priv
->viu
.vpp_hsc_region3_phase_slope
,
574 priv
->io_base
+ _REG(VPP_HSC_REGION3_PHASE_SLOPE
));
575 writel_relaxed(priv
->viu
.vpp_line_in_length
,
576 priv
->io_base
+ _REG(VPP_LINE_IN_LENGTH
));
577 writel_relaxed(priv
->viu
.vpp_preblend_h_size
,
578 priv
->io_base
+ _REG(VPP_PREBLEND_H_SIZE
));
579 writel_relaxed(priv
->viu
.vpp_vsc_region12_startp
,
580 priv
->io_base
+ _REG(VPP_VSC_REGION12_STARTP
));
581 writel_relaxed(priv
->viu
.vpp_vsc_region34_startp
,
582 priv
->io_base
+ _REG(VPP_VSC_REGION34_STARTP
));
583 writel_relaxed(priv
->viu
.vpp_vsc_region4_endp
,
584 priv
->io_base
+ _REG(VPP_VSC_REGION4_ENDP
));
585 writel_relaxed(priv
->viu
.vpp_vsc_start_phase_step
,
586 priv
->io_base
+ _REG(VPP_VSC_START_PHASE_STEP
));
587 writel_relaxed(priv
->viu
.vpp_vsc_ini_phase
,
588 priv
->io_base
+ _REG(VPP_VSC_INI_PHASE
));
589 writel_relaxed(priv
->viu
.vpp_vsc_phase_ctrl
,
590 priv
->io_base
+ _REG(VPP_VSC_PHASE_CTRL
));
591 writel_relaxed(priv
->viu
.vpp_hsc_phase_ctrl
,
592 priv
->io_base
+ _REG(VPP_HSC_PHASE_CTRL
));
593 writel_relaxed(0x42, priv
->io_base
+ _REG(VPP_SCALE_COEF_IDX
));
596 if (meson_crtc
->enable_vd1
)
597 meson_crtc
->enable_vd1(priv
);
599 priv
->viu
.vd1_commit
= false;
602 if (meson_crtc
->vsync_disabled
)
605 drm_crtc_handle_vblank(priv
->crtc
);
607 spin_lock_irqsave(&priv
->drm
->event_lock
, flags
);
608 if (meson_crtc
->event
) {
609 drm_crtc_send_vblank_event(priv
->crtc
, meson_crtc
->event
);
610 drm_crtc_vblank_put(priv
->crtc
);
611 meson_crtc
->event
= NULL
;
613 spin_unlock_irqrestore(&priv
->drm
->event_lock
, flags
);
616 int meson_crtc_create(struct meson_drm
*priv
)
618 struct meson_crtc
*meson_crtc
;
619 struct drm_crtc
*crtc
;
622 meson_crtc
= devm_kzalloc(priv
->drm
->dev
, sizeof(*meson_crtc
),
627 meson_crtc
->priv
= priv
;
628 crtc
= &meson_crtc
->base
;
629 ret
= drm_crtc_init_with_planes(priv
->drm
, crtc
,
630 priv
->primary_plane
, NULL
,
631 &meson_crtc_funcs
, "meson_crtc");
633 dev_err(priv
->drm
->dev
, "Failed to init CRTC\n");
637 if (meson_vpu_is_compatible(priv
, VPU_COMPATIBLE_G12A
)) {
638 meson_crtc
->enable_osd1
= meson_g12a_crtc_enable_osd1
;
639 meson_crtc
->enable_vd1
= meson_g12a_crtc_enable_vd1
;
640 meson_crtc
->viu_offset
= MESON_G12A_VIU_OFFSET
;
641 meson_crtc
->enable_osd1_afbc
=
642 meson_crtc_g12a_enable_osd1_afbc
;
643 meson_crtc
->disable_osd1_afbc
=
644 meson_viu_g12a_disable_osd1_afbc
;
645 drm_crtc_helper_add(crtc
, &meson_g12a_crtc_helper_funcs
);
647 meson_crtc
->enable_osd1
= meson_crtc_enable_osd1
;
648 meson_crtc
->enable_vd1
= meson_crtc_enable_vd1
;
649 if (meson_vpu_is_compatible(priv
, VPU_COMPATIBLE_GXM
)) {
650 meson_crtc
->enable_osd1_afbc
=
651 meson_viu_gxm_enable_osd1_afbc
;
652 meson_crtc
->disable_osd1_afbc
=
653 meson_viu_gxm_disable_osd1_afbc
;
655 drm_crtc_helper_add(crtc
, &meson_crtc_helper_funcs
);