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