Backmerge remote-tracking branch 'drm/drm-next' into drm-misc-next
[linux-block.git] / drivers / gpu / drm / meson / meson_plane.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
14 #include <drm/drm_atomic.h>
15 #include <drm/drm_atomic_helper.h>
16 #include <drm/drm_device.h>
17 #include <drm/drm_fb_cma_helper.h>
18 #include <drm/drm_fourcc.h>
19 #include <drm/drm_gem_cma_helper.h>
20 #include <drm/drm_gem_framebuffer_helper.h>
21 #include <drm/drm_plane_helper.h>
22
23 #include "meson_plane.h"
24 #include "meson_registers.h"
25 #include "meson_viu.h"
26 #include "meson_osd_afbcd.h"
27
28 /* OSD_SCI_WH_M1 */
29 #define SCI_WH_M1_W(w)                  FIELD_PREP(GENMASK(28, 16), w)
30 #define SCI_WH_M1_H(h)                  FIELD_PREP(GENMASK(12, 0), h)
31
32 /* OSD_SCO_H_START_END */
33 /* OSD_SCO_V_START_END */
34 #define SCO_HV_START(start)             FIELD_PREP(GENMASK(27, 16), start)
35 #define SCO_HV_END(end)                 FIELD_PREP(GENMASK(11, 0), end)
36
37 /* OSD_SC_CTRL0 */
38 #define SC_CTRL0_PATH_EN                BIT(3)
39 #define SC_CTRL0_SEL_OSD1               BIT(2)
40
41 /* OSD_VSC_CTRL0 */
42 #define VSC_BANK_LEN(value)             FIELD_PREP(GENMASK(2, 0), value)
43 #define VSC_TOP_INI_RCV_NUM(value)      FIELD_PREP(GENMASK(6, 3), value)
44 #define VSC_TOP_RPT_L0_NUM(value)       FIELD_PREP(GENMASK(9, 8), value)
45 #define VSC_BOT_INI_RCV_NUM(value)      FIELD_PREP(GENMASK(14, 11), value)
46 #define VSC_BOT_RPT_L0_NUM(value)       FIELD_PREP(GENMASK(17, 16), value)
47 #define VSC_PROG_INTERLACE              BIT(23)
48 #define VSC_VERTICAL_SCALER_EN          BIT(24)
49
50 /* OSD_VSC_INI_PHASE */
51 #define VSC_INI_PHASE_BOT(bottom)       FIELD_PREP(GENMASK(31, 16), bottom)
52 #define VSC_INI_PHASE_TOP(top)          FIELD_PREP(GENMASK(15, 0), top)
53
54 /* OSD_HSC_CTRL0 */
55 #define HSC_BANK_LENGTH(value)          FIELD_PREP(GENMASK(2, 0), value)
56 #define HSC_INI_RCV_NUM0(value)         FIELD_PREP(GENMASK(6, 3), value)
57 #define HSC_RPT_P0_NUM0(value)          FIELD_PREP(GENMASK(9, 8), value)
58 #define HSC_HORIZ_SCALER_EN             BIT(22)
59
60 /* VPP_OSD_VSC_PHASE_STEP */
61 /* VPP_OSD_HSC_PHASE_STEP */
62 #define SC_PHASE_STEP(value)            FIELD_PREP(GENMASK(27, 0), value)
63
64 struct meson_plane {
65         struct drm_plane base;
66         struct meson_drm *priv;
67         bool enabled;
68 };
69 #define to_meson_plane(x) container_of(x, struct meson_plane, base)
70
71 #define FRAC_16_16(mult, div)    (((mult) << 16) / (div))
72
73 static int meson_plane_atomic_check(struct drm_plane *plane,
74                                     struct drm_plane_state *state)
75 {
76         struct drm_crtc_state *crtc_state;
77
78         if (!state->crtc)
79                 return 0;
80
81         crtc_state = drm_atomic_get_crtc_state(state->state, state->crtc);
82         if (IS_ERR(crtc_state))
83                 return PTR_ERR(crtc_state);
84
85         /*
86          * Only allow :
87          * - Upscaling up to 5x, vertical and horizontal
88          * - Final coordinates must match crtc size
89          */
90         return drm_atomic_helper_check_plane_state(state, crtc_state,
91                                                    FRAC_16_16(1, 5),
92                                                    DRM_PLANE_HELPER_NO_SCALING,
93                                                    false, true);
94 }
95
96 #define MESON_MOD_AFBC_VALID_BITS (AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |   \
97                                    AFBC_FORMAT_MOD_BLOCK_SIZE_32x8 |    \
98                                    AFBC_FORMAT_MOD_YTR |                \
99                                    AFBC_FORMAT_MOD_SPARSE |             \
100                                    AFBC_FORMAT_MOD_SPLIT)
101
102 /* Takes a fixed 16.16 number and converts it to integer. */
103 static inline int64_t fixed16_to_int(int64_t value)
104 {
105         return value >> 16;
106 }
107
108 static u32 meson_g12a_afbcd_line_stride(struct meson_drm *priv)
109 {
110         u32 line_stride = 0;
111
112         switch (priv->afbcd.format) {
113         case DRM_FORMAT_RGB565:
114                 line_stride = ((priv->viu.osd1_width << 4) + 127) >> 7;
115                 break;
116         case DRM_FORMAT_RGB888:
117         case DRM_FORMAT_XRGB8888:
118         case DRM_FORMAT_ARGB8888:
119         case DRM_FORMAT_XBGR8888:
120         case DRM_FORMAT_ABGR8888:
121                 line_stride = ((priv->viu.osd1_width << 5) + 127) >> 7;
122                 break;
123         }
124
125         return ((line_stride + 1) >> 1) << 1;
126 }
127
128 static void meson_plane_atomic_update(struct drm_plane *plane,
129                                       struct drm_plane_state *old_state)
130 {
131         struct meson_plane *meson_plane = to_meson_plane(plane);
132         struct drm_plane_state *state = plane->state;
133         struct drm_rect dest = drm_plane_state_dest(state);
134         struct meson_drm *priv = meson_plane->priv;
135         struct drm_framebuffer *fb = state->fb;
136         struct drm_gem_cma_object *gem;
137         unsigned long flags;
138         int vsc_ini_rcv_num, vsc_ini_rpt_p0_num;
139         int vsc_bot_rcv_num, vsc_bot_rpt_p0_num;
140         int hsc_ini_rcv_num, hsc_ini_rpt_p0_num;
141         int hf_phase_step, vf_phase_step;
142         int src_w, src_h, dst_w, dst_h;
143         int bot_ini_phase;
144         int hf_bank_len;
145         int vf_bank_len;
146         u8 canvas_id_osd1;
147
148         /*
149          * Update Coordinates
150          * Update Formats
151          * Update Buffer
152          * Enable Plane
153          */
154         spin_lock_irqsave(&priv->drm->event_lock, flags);
155
156         /* Check if AFBC decoder is required for this buffer */
157         if ((meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM) ||
158              meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) &&
159             fb->modifier & DRM_FORMAT_MOD_ARM_AFBC(MESON_MOD_AFBC_VALID_BITS))
160                 priv->viu.osd1_afbcd = true;
161         else
162                 priv->viu.osd1_afbcd = false;
163
164         /* Enable OSD and BLK0, set max global alpha */
165         priv->viu.osd1_ctrl_stat = OSD_ENABLE |
166                                    (0xFF << OSD_GLOBAL_ALPHA_SHIFT) |
167                                    OSD_BLK0_ENABLE;
168
169         priv->viu.osd1_ctrl_stat2 = readl(priv->io_base +
170                                           _REG(VIU_OSD1_CTRL_STAT2));
171
172         canvas_id_osd1 = priv->canvas_id_osd1;
173
174         /* Set up BLK0 to point to the right canvas */
175         priv->viu.osd1_blk0_cfg[0] = canvas_id_osd1 << OSD_CANVAS_SEL;
176
177         if (priv->viu.osd1_afbcd) {
178                 if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) {
179                         /* This is the internal decoding memory address */
180                         priv->viu.osd1_blk1_cfg4 = MESON_G12A_AFBCD_OUT_ADDR;
181                         priv->viu.osd1_blk0_cfg[0] |= OSD_ENDIANNESS_BE;
182                         priv->viu.osd1_ctrl_stat2 |= OSD_PENDING_STAT_CLEAN;
183                         priv->viu.osd1_ctrl_stat |= VIU_OSD1_CFG_SYN_EN;
184                 }
185
186                 if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM)) {
187                         priv->viu.osd1_blk0_cfg[0] |= OSD_ENDIANNESS_LE;
188                         priv->viu.osd1_ctrl_stat2 |= OSD_DPATH_MALI_AFBCD;
189                 }
190         } else {
191                 priv->viu.osd1_blk0_cfg[0] |= OSD_ENDIANNESS_LE;
192
193                 if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM))
194                         priv->viu.osd1_ctrl_stat2 &= ~OSD_DPATH_MALI_AFBCD;
195         }
196
197         /* On GXBB, Use the old non-HDR RGB2YUV converter */
198         if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXBB))
199                 priv->viu.osd1_blk0_cfg[0] |= OSD_OUTPUT_COLOR_RGB;
200
201         if (priv->viu.osd1_afbcd &&
202             meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) {
203                 priv->viu.osd1_blk0_cfg[0] |= OSD_MALI_SRC_EN |
204                         priv->afbcd.ops->fmt_to_blk_mode(fb->modifier,
205                                                           fb->format->format);
206         } else {
207                 switch (fb->format->format) {
208                 case DRM_FORMAT_XRGB8888:
209                 case DRM_FORMAT_ARGB8888:
210                         priv->viu.osd1_blk0_cfg[0] |= OSD_BLK_MODE_32 |
211                                                 OSD_COLOR_MATRIX_32_ARGB;
212                         break;
213                 case DRM_FORMAT_XBGR8888:
214                 case DRM_FORMAT_ABGR8888:
215                         priv->viu.osd1_blk0_cfg[0] |= OSD_BLK_MODE_32 |
216                                                 OSD_COLOR_MATRIX_32_ABGR;
217                         break;
218                 case DRM_FORMAT_RGB888:
219                         priv->viu.osd1_blk0_cfg[0] |= OSD_BLK_MODE_24 |
220                                                 OSD_COLOR_MATRIX_24_RGB;
221                         break;
222                 case DRM_FORMAT_RGB565:
223                         priv->viu.osd1_blk0_cfg[0] |= OSD_BLK_MODE_16 |
224                                                 OSD_COLOR_MATRIX_16_RGB565;
225                         break;
226                 }
227         }
228
229         switch (fb->format->format) {
230         case DRM_FORMAT_XRGB8888:
231         case DRM_FORMAT_XBGR8888:
232                 /* For XRGB, replace the pixel's alpha by 0xFF */
233                 priv->viu.osd1_ctrl_stat2 |= OSD_REPLACE_EN;
234                 break;
235         case DRM_FORMAT_ARGB8888:
236         case DRM_FORMAT_ABGR8888:
237                 /* For ARGB, use the pixel's alpha */
238                 priv->viu.osd1_ctrl_stat2 &= ~OSD_REPLACE_EN;
239                 break;
240         }
241
242         /* Default scaler parameters */
243         vsc_bot_rcv_num = 0;
244         vsc_bot_rpt_p0_num = 0;
245         hf_bank_len = 4;
246         vf_bank_len = 4;
247
248         if (state->crtc->mode.flags & DRM_MODE_FLAG_INTERLACE) {
249                 vsc_bot_rcv_num = 6;
250                 vsc_bot_rpt_p0_num = 2;
251         }
252
253         hsc_ini_rcv_num = hf_bank_len;
254         vsc_ini_rcv_num = vf_bank_len;
255         hsc_ini_rpt_p0_num = (hf_bank_len / 2) - 1;
256         vsc_ini_rpt_p0_num = (vf_bank_len / 2) - 1;
257
258         src_w = fixed16_to_int(state->src_w);
259         src_h = fixed16_to_int(state->src_h);
260         dst_w = state->crtc_w;
261         dst_h = state->crtc_h;
262
263         /*
264          * When the output is interlaced, the OSD must switch between
265          * each field using the INTERLACE_SEL_ODD (0) of VIU_OSD1_BLK0_CFG_W0
266          * at each vsync.
267          * But the vertical scaler can provide such funtionnality if
268          * is configured for 2:1 scaling with interlace options enabled.
269          */
270         if (state->crtc->mode.flags & DRM_MODE_FLAG_INTERLACE) {
271                 dest.y1 /= 2;
272                 dest.y2 /= 2;
273                 dst_h /= 2;
274         }
275
276         hf_phase_step = ((src_w << 18) / dst_w) << 6;
277         vf_phase_step = (src_h << 20) / dst_h;
278
279         if (state->crtc->mode.flags & DRM_MODE_FLAG_INTERLACE)
280                 bot_ini_phase = ((vf_phase_step / 2) >> 4);
281         else
282                 bot_ini_phase = 0;
283
284         vf_phase_step = (vf_phase_step << 4);
285
286         /* In interlaced mode, scaler is always active */
287         if (src_h != dst_h || src_w != dst_w) {
288                 priv->viu.osd_sc_i_wh_m1 = SCI_WH_M1_W(src_w - 1) |
289                                            SCI_WH_M1_H(src_h - 1);
290                 priv->viu.osd_sc_o_h_start_end = SCO_HV_START(dest.x1) |
291                                                  SCO_HV_END(dest.x2 - 1);
292                 priv->viu.osd_sc_o_v_start_end = SCO_HV_START(dest.y1) |
293                                                  SCO_HV_END(dest.y2 - 1);
294                 /* Enable OSD Scaler */
295                 priv->viu.osd_sc_ctrl0 = SC_CTRL0_PATH_EN | SC_CTRL0_SEL_OSD1;
296         } else {
297                 priv->viu.osd_sc_i_wh_m1 = 0;
298                 priv->viu.osd_sc_o_h_start_end = 0;
299                 priv->viu.osd_sc_o_v_start_end = 0;
300                 priv->viu.osd_sc_ctrl0 = 0;
301         }
302
303         /* In interlaced mode, vertical scaler is always active */
304         if (src_h != dst_h) {
305                 priv->viu.osd_sc_v_ctrl0 =
306                                         VSC_BANK_LEN(vf_bank_len) |
307                                         VSC_TOP_INI_RCV_NUM(vsc_ini_rcv_num) |
308                                         VSC_TOP_RPT_L0_NUM(vsc_ini_rpt_p0_num) |
309                                         VSC_VERTICAL_SCALER_EN;
310
311                 if (state->crtc->mode.flags & DRM_MODE_FLAG_INTERLACE)
312                         priv->viu.osd_sc_v_ctrl0 |=
313                                         VSC_BOT_INI_RCV_NUM(vsc_bot_rcv_num) |
314                                         VSC_BOT_RPT_L0_NUM(vsc_bot_rpt_p0_num) |
315                                         VSC_PROG_INTERLACE;
316
317                 priv->viu.osd_sc_v_phase_step = SC_PHASE_STEP(vf_phase_step);
318                 priv->viu.osd_sc_v_ini_phase = VSC_INI_PHASE_BOT(bot_ini_phase);
319         } else {
320                 priv->viu.osd_sc_v_ctrl0 = 0;
321                 priv->viu.osd_sc_v_phase_step = 0;
322                 priv->viu.osd_sc_v_ini_phase = 0;
323         }
324
325         /* Horizontal scaler is only used if width does not match */
326         if (src_w != dst_w) {
327                 priv->viu.osd_sc_h_ctrl0 =
328                                         HSC_BANK_LENGTH(hf_bank_len) |
329                                         HSC_INI_RCV_NUM0(hsc_ini_rcv_num) |
330                                         HSC_RPT_P0_NUM0(hsc_ini_rpt_p0_num) |
331                                         HSC_HORIZ_SCALER_EN;
332                 priv->viu.osd_sc_h_phase_step = SC_PHASE_STEP(hf_phase_step);
333                 priv->viu.osd_sc_h_ini_phase = 0;
334         } else {
335                 priv->viu.osd_sc_h_ctrl0 = 0;
336                 priv->viu.osd_sc_h_phase_step = 0;
337                 priv->viu.osd_sc_h_ini_phase = 0;
338         }
339
340         /*
341          * The format of these registers is (x2 << 16 | x1),
342          * where x2 is exclusive.
343          * e.g. +30x1920 would be (1919 << 16) | 30
344          */
345         priv->viu.osd1_blk0_cfg[1] =
346                                 ((fixed16_to_int(state->src.x2) - 1) << 16) |
347                                 fixed16_to_int(state->src.x1);
348         priv->viu.osd1_blk0_cfg[2] =
349                                 ((fixed16_to_int(state->src.y2) - 1) << 16) |
350                                 fixed16_to_int(state->src.y1);
351         priv->viu.osd1_blk0_cfg[3] = ((dest.x2 - 1) << 16) | dest.x1;
352         priv->viu.osd1_blk0_cfg[4] = ((dest.y2 - 1) << 16) | dest.y1;
353
354         if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) {
355                 priv->viu.osd_blend_din0_scope_h = ((dest.x2 - 1) << 16) | dest.x1;
356                 priv->viu.osd_blend_din0_scope_v = ((dest.y2 - 1) << 16) | dest.y1;
357                 priv->viu.osb_blend0_size = dst_h << 16 | dst_w;
358                 priv->viu.osb_blend1_size = dst_h << 16 | dst_w;
359         }
360
361         /* Update Canvas with buffer address */
362         gem = drm_fb_cma_get_gem_obj(fb, 0);
363
364         priv->viu.osd1_addr = gem->paddr;
365         priv->viu.osd1_stride = fb->pitches[0];
366         priv->viu.osd1_height = fb->height;
367         priv->viu.osd1_width = fb->width;
368
369         if (priv->viu.osd1_afbcd) {
370                 priv->afbcd.modifier = fb->modifier;
371                 priv->afbcd.format = fb->format->format;
372
373                 /* Calculate decoder write stride */
374                 if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A))
375                         priv->viu.osd1_blk2_cfg4 =
376                                 meson_g12a_afbcd_line_stride(priv);
377         }
378
379         if (!meson_plane->enabled) {
380                 /* Reset OSD1 before enabling it on GXL+ SoCs */
381                 if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM) ||
382                     meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXL))
383                         meson_viu_osd1_reset(priv);
384
385                 meson_plane->enabled = true;
386         }
387
388         priv->viu.osd1_enabled = true;
389
390         spin_unlock_irqrestore(&priv->drm->event_lock, flags);
391 }
392
393 static void meson_plane_atomic_disable(struct drm_plane *plane,
394                                        struct drm_plane_state *old_state)
395 {
396         struct meson_plane *meson_plane = to_meson_plane(plane);
397         struct meson_drm *priv = meson_plane->priv;
398
399         if (priv->afbcd.ops) {
400                 priv->afbcd.ops->reset(priv);
401                 priv->afbcd.ops->disable(priv);
402         }
403
404         /* Disable OSD1 */
405         if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A))
406                 writel_bits_relaxed(VIU_OSD1_POSTBLD_SRC_OSD1, 0,
407                                     priv->io_base + _REG(OSD1_BLEND_SRC_CTRL));
408         else
409                 writel_bits_relaxed(VPP_OSD1_POSTBLEND, 0,
410                                     priv->io_base + _REG(VPP_MISC));
411
412         meson_plane->enabled = false;
413         priv->viu.osd1_enabled = false;
414 }
415
416 static const struct drm_plane_helper_funcs meson_plane_helper_funcs = {
417         .atomic_check   = meson_plane_atomic_check,
418         .atomic_disable = meson_plane_atomic_disable,
419         .atomic_update  = meson_plane_atomic_update,
420         .prepare_fb     = drm_gem_fb_prepare_fb,
421 };
422
423 static bool meson_plane_format_mod_supported(struct drm_plane *plane,
424                                              u32 format, u64 modifier)
425 {
426         struct meson_plane *meson_plane = to_meson_plane(plane);
427         struct meson_drm *priv = meson_plane->priv;
428         int i;
429
430         if (modifier == DRM_FORMAT_MOD_INVALID)
431                 return false;
432
433         if (modifier == DRM_FORMAT_MOD_LINEAR)
434                 return true;
435
436         if (!meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM) &&
437             !meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A))
438                 return false;
439
440         if (modifier & ~DRM_FORMAT_MOD_ARM_AFBC(MESON_MOD_AFBC_VALID_BITS))
441                 return false;
442
443         for (i = 0 ; i < plane->modifier_count ; ++i)
444                 if (plane->modifiers[i] == modifier)
445                         break;
446
447         if (i == plane->modifier_count) {
448                 DRM_DEBUG_KMS("Unsupported modifier\n");
449                 return false;
450         }
451
452         if (priv->afbcd.ops && priv->afbcd.ops->supported_fmt)
453                 return priv->afbcd.ops->supported_fmt(modifier, format);
454
455         DRM_DEBUG_KMS("AFBC Unsupported\n");
456         return false;
457 }
458
459 static const struct drm_plane_funcs meson_plane_funcs = {
460         .update_plane           = drm_atomic_helper_update_plane,
461         .disable_plane          = drm_atomic_helper_disable_plane,
462         .destroy                = drm_plane_cleanup,
463         .reset                  = drm_atomic_helper_plane_reset,
464         .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
465         .atomic_destroy_state   = drm_atomic_helper_plane_destroy_state,
466         .format_mod_supported   = meson_plane_format_mod_supported,
467 };
468
469 static const uint32_t supported_drm_formats[] = {
470         DRM_FORMAT_ARGB8888,
471         DRM_FORMAT_ABGR8888,
472         DRM_FORMAT_XRGB8888,
473         DRM_FORMAT_XBGR8888,
474         DRM_FORMAT_RGB888,
475         DRM_FORMAT_RGB565,
476 };
477
478 static const uint64_t format_modifiers_afbc_gxm[] = {
479         DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |
480                                 AFBC_FORMAT_MOD_SPARSE |
481                                 AFBC_FORMAT_MOD_YTR),
482         /* SPLIT mandates SPARSE, RGB modes mandates YTR */
483         DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |
484                                 AFBC_FORMAT_MOD_YTR |
485                                 AFBC_FORMAT_MOD_SPARSE |
486                                 AFBC_FORMAT_MOD_SPLIT),
487         DRM_FORMAT_MOD_LINEAR,
488         DRM_FORMAT_MOD_INVALID,
489 };
490
491 static const uint64_t format_modifiers_afbc_g12a[] = {
492         /*
493          * - TOFIX Support AFBC modifiers for YUV formats (16x16 + TILED)
494          * - SPLIT is mandatory for performances reasons when in 16x16
495          *   block size
496          * - 32x8 block size + SPLIT is mandatory with 4K frame size
497          *   for performances reasons
498          */
499         DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |
500                                 AFBC_FORMAT_MOD_SPARSE |
501                                 AFBC_FORMAT_MOD_SPLIT),
502         DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |
503                                 AFBC_FORMAT_MOD_YTR |
504                                 AFBC_FORMAT_MOD_SPARSE |
505                                 AFBC_FORMAT_MOD_SPLIT),
506         DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_32x8 |
507                                 AFBC_FORMAT_MOD_SPARSE),
508         DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_32x8 |
509                                 AFBC_FORMAT_MOD_YTR |
510                                 AFBC_FORMAT_MOD_SPARSE),
511         DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_32x8 |
512                                 AFBC_FORMAT_MOD_SPARSE |
513                                 AFBC_FORMAT_MOD_SPLIT),
514         DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_32x8 |
515                                 AFBC_FORMAT_MOD_YTR |
516                                 AFBC_FORMAT_MOD_SPARSE |
517                                 AFBC_FORMAT_MOD_SPLIT),
518         DRM_FORMAT_MOD_LINEAR,
519         DRM_FORMAT_MOD_INVALID,
520 };
521
522 static const uint64_t format_modifiers_default[] = {
523         DRM_FORMAT_MOD_LINEAR,
524         DRM_FORMAT_MOD_INVALID,
525 };
526
527 int meson_plane_create(struct meson_drm *priv)
528 {
529         struct meson_plane *meson_plane;
530         struct drm_plane *plane;
531         const uint64_t *format_modifiers = format_modifiers_default;
532
533         meson_plane = devm_kzalloc(priv->drm->dev, sizeof(*meson_plane),
534                                    GFP_KERNEL);
535         if (!meson_plane)
536                 return -ENOMEM;
537
538         meson_plane->priv = priv;
539         plane = &meson_plane->base;
540
541         if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM))
542                 format_modifiers = format_modifiers_afbc_gxm;
543         else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A))
544                 format_modifiers = format_modifiers_afbc_g12a;
545
546         drm_universal_plane_init(priv->drm, plane, 0xFF,
547                                  &meson_plane_funcs,
548                                  supported_drm_formats,
549                                  ARRAY_SIZE(supported_drm_formats),
550                                  format_modifiers,
551                                  DRM_PLANE_TYPE_PRIMARY, "meson_primary_plane");
552
553         drm_plane_helper_add(plane, &meson_plane_helper_funcs);
554
555         /* For now, OSD Primary plane is always on the front */
556         drm_plane_create_zpos_immutable_property(plane, 1);
557
558         priv->primary_plane = plane;
559
560         return 0;
561 }