Merge tag 'core-rcu-2020-12-14' of git://git.kernel.org/pub/scm/linux/kernel/git...
[linux-2.6-microblaze.git] / drivers / gpu / drm / meson / meson_crtc.c
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
7  *
8  * Written by:
9  *     Jasper St. Pierre <jstpierre@mecheye.net>
10  */
11
12 #include <linux/bitfield.h>
13 #include <linux/soc/amlogic/meson-canvas.h>
14
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>
20
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"
29
30 #define MESON_G12A_VIU_OFFSET   0x5ec0
31
32 /* CRTC definition */
33
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;
45 };
46 #define to_meson_crtc(x) container_of(x, struct meson_crtc, base)
47
48 /* CRTC */
49
50 static int meson_crtc_enable_vblank(struct drm_crtc *crtc)
51 {
52         struct meson_crtc *meson_crtc = to_meson_crtc(crtc);
53         struct meson_drm *priv = meson_crtc->priv;
54
55         meson_crtc->vsync_disabled = false;
56         meson_venc_enable_vsync(priv);
57
58         return 0;
59 }
60
61 static void meson_crtc_disable_vblank(struct drm_crtc *crtc)
62 {
63         struct meson_crtc *meson_crtc = to_meson_crtc(crtc);
64         struct meson_drm *priv = meson_crtc->priv;
65
66         if (!meson_crtc->vsync_forced) {
67                 meson_crtc->vsync_disabled = true;
68                 meson_venc_disable_vsync(priv);
69         }
70 }
71
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,
81
82 };
83
84 static void meson_g12a_crtc_atomic_enable(struct drm_crtc *crtc,
85                                           struct drm_atomic_state *state)
86 {
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;
90
91         DRM_DEBUG_DRIVER("\n");
92
93         if (!crtc_state) {
94                 DRM_ERROR("Invalid crtc_state\n");
95                 return;
96         }
97
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));
101
102         /* Setup Blender */
103         writel(crtc_state->mode.hdisplay |
104                crtc_state->mode.vdisplay << 16,
105                priv->io_base + _REG(VPP_POSTBLEND_H_SIZE));
106
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));
116
117         drm_crtc_vblank_on(crtc);
118 }
119
120 static void meson_crtc_atomic_enable(struct drm_crtc *crtc,
121                                      struct drm_atomic_state *state)
122 {
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;
126
127         DRM_DEBUG_DRIVER("\n");
128
129         if (!crtc_state) {
130                 DRM_ERROR("Invalid crtc_state\n");
131                 return;
132         }
133
134         /* Enable VPP Postblend */
135         writel(crtc_state->mode.hdisplay,
136                priv->io_base + _REG(VPP_POSTBLEND_H_SIZE));
137
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));
141
142         writel_bits_relaxed(VPP_POSTBLEND_ENABLE, VPP_POSTBLEND_ENABLE,
143                             priv->io_base + _REG(VPP_MISC));
144
145         drm_crtc_vblank_on(crtc);
146 }
147
148 static void meson_g12a_crtc_atomic_disable(struct drm_crtc *crtc,
149                                            struct drm_atomic_state *state)
150 {
151         struct meson_crtc *meson_crtc = to_meson_crtc(crtc);
152         struct meson_drm *priv = meson_crtc->priv;
153
154         DRM_DEBUG_DRIVER("\n");
155
156         drm_crtc_vblank_off(crtc);
157
158         priv->viu.osd1_enabled = false;
159         priv->viu.osd1_commit = false;
160
161         priv->viu.vd1_enabled = false;
162         priv->viu.vd1_commit = false;
163
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);
168
169                 crtc->state->event = NULL;
170         }
171 }
172
173 static void meson_crtc_atomic_disable(struct drm_crtc *crtc,
174                                       struct drm_atomic_state *state)
175 {
176         struct meson_crtc *meson_crtc = to_meson_crtc(crtc);
177         struct meson_drm *priv = meson_crtc->priv;
178
179         DRM_DEBUG_DRIVER("\n");
180
181         drm_crtc_vblank_off(crtc);
182
183         priv->viu.osd1_enabled = false;
184         priv->viu.osd1_commit = false;
185
186         priv->viu.vd1_enabled = false;
187         priv->viu.vd1_commit = false;
188
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));
193
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);
198
199                 crtc->state->event = NULL;
200         }
201 }
202
203 static void meson_crtc_atomic_begin(struct drm_crtc *crtc,
204                                     struct drm_atomic_state *state)
205 {
206         struct meson_crtc *meson_crtc = to_meson_crtc(crtc);
207         unsigned long flags;
208
209         if (crtc->state->event) {
210                 WARN_ON(drm_crtc_vblank_get(crtc) != 0);
211
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;
216         }
217 }
218
219 static void meson_crtc_atomic_flush(struct drm_crtc *crtc,
220                                     struct drm_atomic_state *state)
221 {
222         struct meson_crtc *meson_crtc = to_meson_crtc(crtc);
223         struct meson_drm *priv = meson_crtc->priv;
224
225         priv->viu.osd1_commit = true;
226         priv->viu.vd1_commit = true;
227 }
228
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,
234 };
235
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,
241 };
242
243 static void meson_crtc_enable_osd1(struct meson_drm *priv)
244 {
245         writel_bits_relaxed(VPP_OSD1_POSTBLEND, VPP_OSD1_POSTBLEND,
246                             priv->io_base + _REG(VPP_MISC));
247 }
248
249 static void meson_crtc_g12a_enable_osd1_afbc(struct meson_drm *priv)
250 {
251         writel_relaxed(priv->viu.osd1_blk2_cfg4,
252                        priv->io_base + _REG(VIU_OSD1_BLK2_CFG_W4));
253
254         writel_bits_relaxed(OSD_MEM_LINEAR_ADDR, OSD_MEM_LINEAR_ADDR,
255                             priv->io_base + _REG(VIU_OSD1_CTRL_STAT));
256
257         writel_relaxed(priv->viu.osd1_blk1_cfg4,
258                        priv->io_base + _REG(VIU_OSD1_BLK1_CFG_W4));
259
260         meson_viu_g12a_enable_osd1_afbc(priv);
261
262         writel_bits_relaxed(OSD_MEM_LINEAR_ADDR, OSD_MEM_LINEAR_ADDR,
263                             priv->io_base + _REG(VIU_OSD1_CTRL_STAT));
264
265         writel_bits_relaxed(OSD_MALI_SRC_EN, OSD_MALI_SRC_EN,
266                             priv->io_base + _REG(VIU_OSD1_BLK0_CFG_W0));
267 }
268
269 static void meson_g12a_crtc_enable_osd1(struct meson_drm *priv)
270 {
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));
285 }
286
287 static void meson_crtc_enable_vd1(struct meson_drm *priv)
288 {
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));
294
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));
298 }
299
300 static void meson_g12a_crtc_enable_vd1(struct meson_drm *priv)
301 {
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));
307
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));
311 }
312
313 void meson_crtc_irq(struct meson_drm *priv)
314 {
315         struct meson_crtc *meson_crtc = to_meson_crtc(priv->crtc);
316         unsigned long flags;
317
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));
334
335                 if (priv->viu.osd1_afbcd) {
336                         if (meson_crtc->enable_osd1_afbc)
337                                 meson_crtc->enable_osd1_afbc(priv);
338                 } else {
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);
344                         }
345                         meson_crtc->vsync_forced = false;
346                 }
347
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));
368
369                 if (!priv->viu.osd1_afbcd)
370                         meson_canvas_config(priv->canvas, priv->canvas_id_osd1,
371                                             priv->viu.osd1_addr,
372                                             priv->viu.osd1_stride,
373                                             priv->viu.osd1_height,
374                                             MESON_CANVAS_WRAP_NONE,
375                                             MESON_CANVAS_BLKMODE_LINEAR, 0);
376
377                 /* Enable OSD1 */
378                 if (meson_crtc->enable_osd1)
379                         meson_crtc->enable_osd1(priv);
380
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;
386                 }
387
388                 priv->viu.osd1_commit = false;
389         }
390
391         /* Update the VD1 registers */
392         if (priv->viu.vd1_enabled && priv->viu.vd1_commit) {
393
394                 if (priv->viu.vd1_afbc) {
395                         writel_relaxed(priv->viu.vd1_afbc_head_addr,
396                                        priv->io_base +
397                                        _REG(AFBC_HEAD_BADDR));
398                         writel_relaxed(priv->viu.vd1_afbc_body_addr,
399                                        priv->io_base +
400                                        _REG(AFBC_BODY_BADDR));
401                         writel_relaxed(priv->viu.vd1_afbc_en,
402                                        priv->io_base +
403                                        _REG(AFBC_ENABLE));
404                         writel_relaxed(priv->viu.vd1_afbc_mode,
405                                        priv->io_base +
406                                        _REG(AFBC_MODE));
407                         writel_relaxed(priv->viu.vd1_afbc_size_in,
408                                        priv->io_base +
409                                        _REG(AFBC_SIZE_IN));
410                         writel_relaxed(priv->viu.vd1_afbc_dec_def_color,
411                                        priv->io_base +
412                                        _REG(AFBC_DEC_DEF_COLOR));
413                         writel_relaxed(priv->viu.vd1_afbc_conv_ctrl,
414                                        priv->io_base +
415                                        _REG(AFBC_CONV_CTRL));
416                         writel_relaxed(priv->viu.vd1_afbc_size_out,
417                                        priv->io_base +
418                                        _REG(AFBC_SIZE_OUT));
419                         writel_relaxed(priv->viu.vd1_afbc_vd_cfmt_ctrl,
420                                        priv->io_base +
421                                        _REG(AFBC_VD_CFMT_CTRL));
422                         writel_relaxed(priv->viu.vd1_afbc_vd_cfmt_w,
423                                        priv->io_base +
424                                        _REG(AFBC_VD_CFMT_W));
425                         writel_relaxed(priv->viu.vd1_afbc_mif_hor_scope,
426                                        priv->io_base +
427                                        _REG(AFBC_MIF_HOR_SCOPE));
428                         writel_relaxed(priv->viu.vd1_afbc_mif_ver_scope,
429                                        priv->io_base +
430                                        _REG(AFBC_MIF_VER_SCOPE));
431                         writel_relaxed(priv->viu.vd1_afbc_pixel_hor_scope,
432                                        priv->io_base+
433                                        _REG(AFBC_PIXEL_HOR_SCOPE));
434                         writel_relaxed(priv->viu.vd1_afbc_pixel_ver_scope,
435                                        priv->io_base +
436                                        _REG(AFBC_PIXEL_VER_SCOPE));
437                         writel_relaxed(priv->viu.vd1_afbc_vd_cfmt_h,
438                                        priv->io_base +
439                                        _REG(AFBC_VD_CFMT_H));
440                 } else {
441                         switch (priv->viu.vd1_planes) {
442                         case 3:
443                                 meson_canvas_config(priv->canvas,
444                                                     priv->canvas_id_vd1_2,
445                                                     priv->viu.vd1_addr2,
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);
451                                 fallthrough;
452                         case 2:
453                                 meson_canvas_config(priv->canvas,
454                                                     priv->canvas_id_vd1_1,
455                                                     priv->viu.vd1_addr1,
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);
461                                 fallthrough;
462                         case 1:
463                                 meson_canvas_config(priv->canvas,
464                                                     priv->canvas_id_vd1_0,
465                                                     priv->viu.vd1_addr0,
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);
471                         }
472
473                         writel_relaxed(0, priv->io_base + _REG(AFBC_ENABLE));
474                 }
475
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));
652
653                 /* Enable VD1 */
654                 if (meson_crtc->enable_vd1)
655                         meson_crtc->enable_vd1(priv);
656
657                 priv->viu.vd1_commit = false;
658         }
659
660         if (meson_crtc->vsync_disabled)
661                 return;
662
663         drm_crtc_handle_vblank(priv->crtc);
664
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;
670         }
671         spin_unlock_irqrestore(&priv->drm->event_lock, flags);
672 }
673
674 int meson_crtc_create(struct meson_drm *priv)
675 {
676         struct meson_crtc *meson_crtc;
677         struct drm_crtc *crtc;
678         int ret;
679
680         meson_crtc = devm_kzalloc(priv->drm->dev, sizeof(*meson_crtc),
681                                   GFP_KERNEL);
682         if (!meson_crtc)
683                 return -ENOMEM;
684
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");
690         if (ret) {
691                 dev_err(priv->drm->dev, "Failed to init CRTC\n");
692                 return ret;
693         }
694
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);
704         } else {
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;
712                 }
713                 drm_crtc_helper_add(crtc, &meson_crtc_helper_funcs);
714         }
715
716         priv->crtc = crtc;
717
718         return 0;
719 }