treewide: remove redundant IS_ERR() before error code check
[linux/fpc-iii.git] / drivers / gpu / drm / meson / meson_crtc.c
blobe66b6271ff58a75990e79fda9309cde659abe931
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
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
8 * Written by:
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
32 /* CRTC definition */
34 struct meson_crtc {
35 struct drm_crtc base;
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;
43 bool vsync_forced;
44 bool vsync_disabled;
46 #define to_meson_crtc(x) container_of(x, struct meson_crtc, base)
48 /* CRTC */
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);
58 return 0;
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");
93 if (!crtc_state) {
94 DRM_ERROR("Invalid crtc_state\n");
95 return;
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));
102 /* Setup Blender */
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");
129 if (!crtc_state) {
130 DRM_ERROR("Invalid crtc_state\n");
131 return;
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);
207 unsigned long flags;
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,
272 priv->io_base +
273 _REG(VIU_OSD_BLEND_DIN0_SCOPE_H));
274 writel_relaxed(priv->viu.osd_blend_din0_scope_v,
275 priv->io_base +
276 _REG(VIU_OSD_BLEND_DIN0_SCOPE_V));
277 writel_relaxed(priv->viu.osb_blend0_size,
278 priv->io_base +
279 _REG(VIU_OSD_BLEND_BLEND0_SIZE));
280 writel_relaxed(priv->viu.osb_blend1_size,
281 priv->io_base +
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);
308 unsigned long flags;
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);
330 } else {
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,
363 priv->viu.osd1_addr,
364 priv->viu.osd1_stride,
365 priv->viu.osd1_height,
366 MESON_CANVAS_WRAP_NONE,
367 MESON_CANVAS_BLKMODE_LINEAR, 0);
369 /* Enable OSD1 */
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) {
387 case 3:
388 meson_canvas_config(priv->canvas,
389 priv->canvas_id_vd1_2,
390 priv->viu.vd1_addr2,
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);
396 /* fallthrough */
397 case 2:
398 meson_canvas_config(priv->canvas,
399 priv->canvas_id_vd1_1,
400 priv->viu.vd1_addr1,
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);
406 /* fallthrough */
407 case 1:
408 meson_canvas_config(priv->canvas,
409 priv->canvas_id_vd1_0,
410 priv->viu.vd1_addr0,
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));
595 /* Enable VD1 */
596 if (meson_crtc->enable_vd1)
597 meson_crtc->enable_vd1(priv);
599 priv->viu.vd1_commit = false;
602 if (meson_crtc->vsync_disabled)
603 return;
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;
620 int ret;
622 meson_crtc = devm_kzalloc(priv->drm->dev, sizeof(*meson_crtc),
623 GFP_KERNEL);
624 if (!meson_crtc)
625 return -ENOMEM;
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");
632 if (ret) {
633 dev_err(priv->drm->dev, "Failed to init CRTC\n");
634 return ret;
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);
646 } else {
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);
658 priv->crtc = crtc;
660 return 0;