0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #include <linux/bitfield.h>
0013
0014 #include <drm/drm_atomic.h>
0015 #include <drm/drm_atomic_helper.h>
0016 #include <drm/drm_blend.h>
0017 #include <drm/drm_device.h>
0018 #include <drm/drm_fb_cma_helper.h>
0019 #include <drm/drm_fourcc.h>
0020 #include <drm/drm_framebuffer.h>
0021 #include <drm/drm_gem_atomic_helper.h>
0022 #include <drm/drm_gem_cma_helper.h>
0023 #include <drm/drm_plane_helper.h>
0024
0025 #include "meson_plane.h"
0026 #include "meson_registers.h"
0027 #include "meson_viu.h"
0028 #include "meson_osd_afbcd.h"
0029
0030
0031 #define SCI_WH_M1_W(w) FIELD_PREP(GENMASK(28, 16), w)
0032 #define SCI_WH_M1_H(h) FIELD_PREP(GENMASK(12, 0), h)
0033
0034
0035
0036 #define SCO_HV_START(start) FIELD_PREP(GENMASK(27, 16), start)
0037 #define SCO_HV_END(end) FIELD_PREP(GENMASK(11, 0), end)
0038
0039
0040 #define SC_CTRL0_PATH_EN BIT(3)
0041 #define SC_CTRL0_SEL_OSD1 BIT(2)
0042
0043
0044 #define VSC_BANK_LEN(value) FIELD_PREP(GENMASK(2, 0), value)
0045 #define VSC_TOP_INI_RCV_NUM(value) FIELD_PREP(GENMASK(6, 3), value)
0046 #define VSC_TOP_RPT_L0_NUM(value) FIELD_PREP(GENMASK(9, 8), value)
0047 #define VSC_BOT_INI_RCV_NUM(value) FIELD_PREP(GENMASK(14, 11), value)
0048 #define VSC_BOT_RPT_L0_NUM(value) FIELD_PREP(GENMASK(17, 16), value)
0049 #define VSC_PROG_INTERLACE BIT(23)
0050 #define VSC_VERTICAL_SCALER_EN BIT(24)
0051
0052
0053 #define VSC_INI_PHASE_BOT(bottom) FIELD_PREP(GENMASK(31, 16), bottom)
0054 #define VSC_INI_PHASE_TOP(top) FIELD_PREP(GENMASK(15, 0), top)
0055
0056
0057 #define HSC_BANK_LENGTH(value) FIELD_PREP(GENMASK(2, 0), value)
0058 #define HSC_INI_RCV_NUM0(value) FIELD_PREP(GENMASK(6, 3), value)
0059 #define HSC_RPT_P0_NUM0(value) FIELD_PREP(GENMASK(9, 8), value)
0060 #define HSC_HORIZ_SCALER_EN BIT(22)
0061
0062
0063
0064 #define SC_PHASE_STEP(value) FIELD_PREP(GENMASK(27, 0), value)
0065
0066 struct meson_plane {
0067 struct drm_plane base;
0068 struct meson_drm *priv;
0069 bool enabled;
0070 };
0071 #define to_meson_plane(x) container_of(x, struct meson_plane, base)
0072
0073 #define FRAC_16_16(mult, div) (((mult) << 16) / (div))
0074
0075 static int meson_plane_atomic_check(struct drm_plane *plane,
0076 struct drm_atomic_state *state)
0077 {
0078 struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state,
0079 plane);
0080 struct drm_crtc_state *crtc_state;
0081
0082 if (!new_plane_state->crtc)
0083 return 0;
0084
0085 crtc_state = drm_atomic_get_crtc_state(state,
0086 new_plane_state->crtc);
0087 if (IS_ERR(crtc_state))
0088 return PTR_ERR(crtc_state);
0089
0090
0091
0092
0093
0094
0095 return drm_atomic_helper_check_plane_state(new_plane_state,
0096 crtc_state,
0097 FRAC_16_16(1, 5),
0098 DRM_PLANE_HELPER_NO_SCALING,
0099 false, true);
0100 }
0101
0102 #define MESON_MOD_AFBC_VALID_BITS (AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 | \
0103 AFBC_FORMAT_MOD_BLOCK_SIZE_32x8 | \
0104 AFBC_FORMAT_MOD_YTR | \
0105 AFBC_FORMAT_MOD_SPARSE | \
0106 AFBC_FORMAT_MOD_SPLIT)
0107
0108
0109 static inline int64_t fixed16_to_int(int64_t value)
0110 {
0111 return value >> 16;
0112 }
0113
0114 static u32 meson_g12a_afbcd_line_stride(struct meson_drm *priv)
0115 {
0116 u32 line_stride = 0;
0117
0118 switch (priv->afbcd.format) {
0119 case DRM_FORMAT_RGB565:
0120 line_stride = ((priv->viu.osd1_width << 4) + 127) >> 7;
0121 break;
0122 case DRM_FORMAT_RGB888:
0123 case DRM_FORMAT_XRGB8888:
0124 case DRM_FORMAT_ARGB8888:
0125 case DRM_FORMAT_XBGR8888:
0126 case DRM_FORMAT_ABGR8888:
0127 line_stride = ((priv->viu.osd1_width << 5) + 127) >> 7;
0128 break;
0129 }
0130
0131 return ((line_stride + 1) >> 1) << 1;
0132 }
0133
0134 static void meson_plane_atomic_update(struct drm_plane *plane,
0135 struct drm_atomic_state *state)
0136 {
0137 struct meson_plane *meson_plane = to_meson_plane(plane);
0138 struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state,
0139 plane);
0140 struct drm_rect dest = drm_plane_state_dest(new_state);
0141 struct meson_drm *priv = meson_plane->priv;
0142 struct drm_framebuffer *fb = new_state->fb;
0143 struct drm_gem_cma_object *gem;
0144 unsigned long flags;
0145 int vsc_ini_rcv_num, vsc_ini_rpt_p0_num;
0146 int vsc_bot_rcv_num, vsc_bot_rpt_p0_num;
0147 int hsc_ini_rcv_num, hsc_ini_rpt_p0_num;
0148 int hf_phase_step, vf_phase_step;
0149 int src_w, src_h, dst_w, dst_h;
0150 int bot_ini_phase;
0151 int hf_bank_len;
0152 int vf_bank_len;
0153 u8 canvas_id_osd1;
0154
0155
0156
0157
0158
0159
0160
0161 spin_lock_irqsave(&priv->drm->event_lock, flags);
0162
0163
0164 if ((meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM) ||
0165 meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) &&
0166 fb->modifier & DRM_FORMAT_MOD_ARM_AFBC(MESON_MOD_AFBC_VALID_BITS))
0167 priv->viu.osd1_afbcd = true;
0168 else
0169 priv->viu.osd1_afbcd = false;
0170
0171
0172 priv->viu.osd1_ctrl_stat = OSD_ENABLE |
0173 (0x100 << OSD_GLOBAL_ALPHA_SHIFT) |
0174 OSD_BLK0_ENABLE;
0175
0176 priv->viu.osd1_ctrl_stat2 = readl(priv->io_base +
0177 _REG(VIU_OSD1_CTRL_STAT2));
0178
0179 canvas_id_osd1 = priv->canvas_id_osd1;
0180
0181
0182 priv->viu.osd1_blk0_cfg[0] = canvas_id_osd1 << OSD_CANVAS_SEL;
0183
0184 if (priv->viu.osd1_afbcd) {
0185 if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) {
0186
0187 priv->viu.osd1_blk1_cfg4 = MESON_G12A_AFBCD_OUT_ADDR;
0188 priv->viu.osd1_blk0_cfg[0] |= OSD_ENDIANNESS_BE;
0189 priv->viu.osd1_ctrl_stat2 |= OSD_PENDING_STAT_CLEAN;
0190 priv->viu.osd1_ctrl_stat |= VIU_OSD1_CFG_SYN_EN;
0191 }
0192
0193 if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM)) {
0194 priv->viu.osd1_blk0_cfg[0] |= OSD_ENDIANNESS_LE;
0195 priv->viu.osd1_ctrl_stat2 |= OSD_DPATH_MALI_AFBCD;
0196 }
0197 } else {
0198 priv->viu.osd1_blk0_cfg[0] |= OSD_ENDIANNESS_LE;
0199
0200 if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM))
0201 priv->viu.osd1_ctrl_stat2 &= ~OSD_DPATH_MALI_AFBCD;
0202 }
0203
0204
0205 if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXBB))
0206 priv->viu.osd1_blk0_cfg[0] |= OSD_OUTPUT_COLOR_RGB;
0207
0208 if (priv->viu.osd1_afbcd &&
0209 meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) {
0210 priv->viu.osd1_blk0_cfg[0] |= OSD_MALI_SRC_EN |
0211 priv->afbcd.ops->fmt_to_blk_mode(fb->modifier,
0212 fb->format->format);
0213 } else {
0214 switch (fb->format->format) {
0215 case DRM_FORMAT_XRGB8888:
0216 case DRM_FORMAT_ARGB8888:
0217 priv->viu.osd1_blk0_cfg[0] |= OSD_BLK_MODE_32 |
0218 OSD_COLOR_MATRIX_32_ARGB;
0219 break;
0220 case DRM_FORMAT_XBGR8888:
0221 case DRM_FORMAT_ABGR8888:
0222 priv->viu.osd1_blk0_cfg[0] |= OSD_BLK_MODE_32 |
0223 OSD_COLOR_MATRIX_32_ABGR;
0224 break;
0225 case DRM_FORMAT_RGB888:
0226 priv->viu.osd1_blk0_cfg[0] |= OSD_BLK_MODE_24 |
0227 OSD_COLOR_MATRIX_24_RGB;
0228 break;
0229 case DRM_FORMAT_RGB565:
0230 priv->viu.osd1_blk0_cfg[0] |= OSD_BLK_MODE_16 |
0231 OSD_COLOR_MATRIX_16_RGB565;
0232 break;
0233 }
0234 }
0235
0236 switch (fb->format->format) {
0237 case DRM_FORMAT_XRGB8888:
0238 case DRM_FORMAT_XBGR8888:
0239
0240 priv->viu.osd1_ctrl_stat2 |= OSD_REPLACE_EN;
0241 break;
0242 case DRM_FORMAT_ARGB8888:
0243 case DRM_FORMAT_ABGR8888:
0244
0245 priv->viu.osd1_ctrl_stat2 &= ~OSD_REPLACE_EN;
0246 break;
0247 }
0248
0249
0250 vsc_bot_rcv_num = 0;
0251 vsc_bot_rpt_p0_num = 0;
0252 hf_bank_len = 4;
0253 vf_bank_len = 4;
0254
0255 if (new_state->crtc->mode.flags & DRM_MODE_FLAG_INTERLACE) {
0256 vsc_bot_rcv_num = 6;
0257 vsc_bot_rpt_p0_num = 2;
0258 }
0259
0260 hsc_ini_rcv_num = hf_bank_len;
0261 vsc_ini_rcv_num = vf_bank_len;
0262 hsc_ini_rpt_p0_num = (hf_bank_len / 2) - 1;
0263 vsc_ini_rpt_p0_num = (vf_bank_len / 2) - 1;
0264
0265 src_w = fixed16_to_int(new_state->src_w);
0266 src_h = fixed16_to_int(new_state->src_h);
0267 dst_w = new_state->crtc_w;
0268 dst_h = new_state->crtc_h;
0269
0270
0271
0272
0273
0274
0275
0276
0277 if (new_state->crtc->mode.flags & DRM_MODE_FLAG_INTERLACE) {
0278 dest.y1 /= 2;
0279 dest.y2 /= 2;
0280 dst_h /= 2;
0281 }
0282
0283 hf_phase_step = ((src_w << 18) / dst_w) << 6;
0284 vf_phase_step = (src_h << 20) / dst_h;
0285
0286 if (new_state->crtc->mode.flags & DRM_MODE_FLAG_INTERLACE)
0287 bot_ini_phase = ((vf_phase_step / 2) >> 4);
0288 else
0289 bot_ini_phase = 0;
0290
0291 vf_phase_step = (vf_phase_step << 4);
0292
0293
0294 if (src_h != dst_h || src_w != dst_w) {
0295 priv->viu.osd_sc_i_wh_m1 = SCI_WH_M1_W(src_w - 1) |
0296 SCI_WH_M1_H(src_h - 1);
0297 priv->viu.osd_sc_o_h_start_end = SCO_HV_START(dest.x1) |
0298 SCO_HV_END(dest.x2 - 1);
0299 priv->viu.osd_sc_o_v_start_end = SCO_HV_START(dest.y1) |
0300 SCO_HV_END(dest.y2 - 1);
0301
0302 priv->viu.osd_sc_ctrl0 = SC_CTRL0_PATH_EN | SC_CTRL0_SEL_OSD1;
0303 } else {
0304 priv->viu.osd_sc_i_wh_m1 = 0;
0305 priv->viu.osd_sc_o_h_start_end = 0;
0306 priv->viu.osd_sc_o_v_start_end = 0;
0307 priv->viu.osd_sc_ctrl0 = 0;
0308 }
0309
0310
0311 if (src_h != dst_h) {
0312 priv->viu.osd_sc_v_ctrl0 =
0313 VSC_BANK_LEN(vf_bank_len) |
0314 VSC_TOP_INI_RCV_NUM(vsc_ini_rcv_num) |
0315 VSC_TOP_RPT_L0_NUM(vsc_ini_rpt_p0_num) |
0316 VSC_VERTICAL_SCALER_EN;
0317
0318 if (new_state->crtc->mode.flags & DRM_MODE_FLAG_INTERLACE)
0319 priv->viu.osd_sc_v_ctrl0 |=
0320 VSC_BOT_INI_RCV_NUM(vsc_bot_rcv_num) |
0321 VSC_BOT_RPT_L0_NUM(vsc_bot_rpt_p0_num) |
0322 VSC_PROG_INTERLACE;
0323
0324 priv->viu.osd_sc_v_phase_step = SC_PHASE_STEP(vf_phase_step);
0325 priv->viu.osd_sc_v_ini_phase = VSC_INI_PHASE_BOT(bot_ini_phase);
0326 } else {
0327 priv->viu.osd_sc_v_ctrl0 = 0;
0328 priv->viu.osd_sc_v_phase_step = 0;
0329 priv->viu.osd_sc_v_ini_phase = 0;
0330 }
0331
0332
0333 if (src_w != dst_w) {
0334 priv->viu.osd_sc_h_ctrl0 =
0335 HSC_BANK_LENGTH(hf_bank_len) |
0336 HSC_INI_RCV_NUM0(hsc_ini_rcv_num) |
0337 HSC_RPT_P0_NUM0(hsc_ini_rpt_p0_num) |
0338 HSC_HORIZ_SCALER_EN;
0339 priv->viu.osd_sc_h_phase_step = SC_PHASE_STEP(hf_phase_step);
0340 priv->viu.osd_sc_h_ini_phase = 0;
0341 } else {
0342 priv->viu.osd_sc_h_ctrl0 = 0;
0343 priv->viu.osd_sc_h_phase_step = 0;
0344 priv->viu.osd_sc_h_ini_phase = 0;
0345 }
0346
0347
0348
0349
0350
0351
0352 priv->viu.osd1_blk0_cfg[1] =
0353 ((fixed16_to_int(new_state->src.x2) - 1) << 16) |
0354 fixed16_to_int(new_state->src.x1);
0355 priv->viu.osd1_blk0_cfg[2] =
0356 ((fixed16_to_int(new_state->src.y2) - 1) << 16) |
0357 fixed16_to_int(new_state->src.y1);
0358 priv->viu.osd1_blk0_cfg[3] = ((dest.x2 - 1) << 16) | dest.x1;
0359 priv->viu.osd1_blk0_cfg[4] = ((dest.y2 - 1) << 16) | dest.y1;
0360
0361 if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) {
0362 priv->viu.osd_blend_din0_scope_h = ((dest.x2 - 1) << 16) | dest.x1;
0363 priv->viu.osd_blend_din0_scope_v = ((dest.y2 - 1) << 16) | dest.y1;
0364 priv->viu.osb_blend0_size = dst_h << 16 | dst_w;
0365 priv->viu.osb_blend1_size = dst_h << 16 | dst_w;
0366 }
0367
0368
0369 gem = drm_fb_cma_get_gem_obj(fb, 0);
0370
0371 priv->viu.osd1_addr = gem->paddr;
0372 priv->viu.osd1_stride = fb->pitches[0];
0373 priv->viu.osd1_height = fb->height;
0374 priv->viu.osd1_width = fb->width;
0375
0376 if (priv->viu.osd1_afbcd) {
0377 priv->afbcd.modifier = fb->modifier;
0378 priv->afbcd.format = fb->format->format;
0379
0380
0381 if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A))
0382 priv->viu.osd1_blk2_cfg4 =
0383 meson_g12a_afbcd_line_stride(priv);
0384 }
0385
0386 if (!meson_plane->enabled) {
0387
0388 if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM) ||
0389 meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXL))
0390 meson_viu_osd1_reset(priv);
0391
0392 meson_plane->enabled = true;
0393 }
0394
0395 priv->viu.osd1_enabled = true;
0396
0397 spin_unlock_irqrestore(&priv->drm->event_lock, flags);
0398 }
0399
0400 static void meson_plane_atomic_disable(struct drm_plane *plane,
0401 struct drm_atomic_state *state)
0402 {
0403 struct meson_plane *meson_plane = to_meson_plane(plane);
0404 struct meson_drm *priv = meson_plane->priv;
0405
0406 if (priv->afbcd.ops) {
0407 priv->afbcd.ops->reset(priv);
0408 priv->afbcd.ops->disable(priv);
0409 }
0410
0411
0412 if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A))
0413 writel_bits_relaxed(VIU_OSD1_POSTBLD_SRC_OSD1, 0,
0414 priv->io_base + _REG(OSD1_BLEND_SRC_CTRL));
0415 else
0416 writel_bits_relaxed(VPP_OSD1_POSTBLEND, 0,
0417 priv->io_base + _REG(VPP_MISC));
0418
0419 meson_plane->enabled = false;
0420 priv->viu.osd1_enabled = false;
0421 }
0422
0423 static const struct drm_plane_helper_funcs meson_plane_helper_funcs = {
0424 .atomic_check = meson_plane_atomic_check,
0425 .atomic_disable = meson_plane_atomic_disable,
0426 .atomic_update = meson_plane_atomic_update,
0427 };
0428
0429 static bool meson_plane_format_mod_supported(struct drm_plane *plane,
0430 u32 format, u64 modifier)
0431 {
0432 struct meson_plane *meson_plane = to_meson_plane(plane);
0433 struct meson_drm *priv = meson_plane->priv;
0434 int i;
0435
0436 if (modifier == DRM_FORMAT_MOD_INVALID)
0437 return false;
0438
0439 if (modifier == DRM_FORMAT_MOD_LINEAR)
0440 return true;
0441
0442 if (!meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM) &&
0443 !meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A))
0444 return false;
0445
0446 if (modifier & ~DRM_FORMAT_MOD_ARM_AFBC(MESON_MOD_AFBC_VALID_BITS))
0447 return false;
0448
0449 for (i = 0 ; i < plane->modifier_count ; ++i)
0450 if (plane->modifiers[i] == modifier)
0451 break;
0452
0453 if (i == plane->modifier_count) {
0454 DRM_DEBUG_KMS("Unsupported modifier\n");
0455 return false;
0456 }
0457
0458 if (priv->afbcd.ops && priv->afbcd.ops->supported_fmt)
0459 return priv->afbcd.ops->supported_fmt(modifier, format);
0460
0461 DRM_DEBUG_KMS("AFBC Unsupported\n");
0462 return false;
0463 }
0464
0465 static const struct drm_plane_funcs meson_plane_funcs = {
0466 .update_plane = drm_atomic_helper_update_plane,
0467 .disable_plane = drm_atomic_helper_disable_plane,
0468 .destroy = drm_plane_cleanup,
0469 .reset = drm_atomic_helper_plane_reset,
0470 .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
0471 .atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
0472 .format_mod_supported = meson_plane_format_mod_supported,
0473 };
0474
0475 static const uint32_t supported_drm_formats[] = {
0476 DRM_FORMAT_ARGB8888,
0477 DRM_FORMAT_ABGR8888,
0478 DRM_FORMAT_XRGB8888,
0479 DRM_FORMAT_XBGR8888,
0480 DRM_FORMAT_RGB888,
0481 DRM_FORMAT_RGB565,
0482 };
0483
0484 static const uint64_t format_modifiers_afbc_gxm[] = {
0485 DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |
0486 AFBC_FORMAT_MOD_SPARSE |
0487 AFBC_FORMAT_MOD_YTR),
0488
0489 DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |
0490 AFBC_FORMAT_MOD_YTR |
0491 AFBC_FORMAT_MOD_SPARSE |
0492 AFBC_FORMAT_MOD_SPLIT),
0493 DRM_FORMAT_MOD_LINEAR,
0494 DRM_FORMAT_MOD_INVALID,
0495 };
0496
0497 static const uint64_t format_modifiers_afbc_g12a[] = {
0498
0499
0500
0501
0502
0503
0504
0505 DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |
0506 AFBC_FORMAT_MOD_SPARSE |
0507 AFBC_FORMAT_MOD_SPLIT),
0508 DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |
0509 AFBC_FORMAT_MOD_YTR |
0510 AFBC_FORMAT_MOD_SPARSE |
0511 AFBC_FORMAT_MOD_SPLIT),
0512 DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_32x8 |
0513 AFBC_FORMAT_MOD_SPARSE),
0514 DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_32x8 |
0515 AFBC_FORMAT_MOD_YTR |
0516 AFBC_FORMAT_MOD_SPARSE),
0517 DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_32x8 |
0518 AFBC_FORMAT_MOD_SPARSE |
0519 AFBC_FORMAT_MOD_SPLIT),
0520 DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_32x8 |
0521 AFBC_FORMAT_MOD_YTR |
0522 AFBC_FORMAT_MOD_SPARSE |
0523 AFBC_FORMAT_MOD_SPLIT),
0524 DRM_FORMAT_MOD_LINEAR,
0525 DRM_FORMAT_MOD_INVALID,
0526 };
0527
0528 static const uint64_t format_modifiers_default[] = {
0529 DRM_FORMAT_MOD_LINEAR,
0530 DRM_FORMAT_MOD_INVALID,
0531 };
0532
0533 int meson_plane_create(struct meson_drm *priv)
0534 {
0535 struct meson_plane *meson_plane;
0536 struct drm_plane *plane;
0537 const uint64_t *format_modifiers = format_modifiers_default;
0538
0539 meson_plane = devm_kzalloc(priv->drm->dev, sizeof(*meson_plane),
0540 GFP_KERNEL);
0541 if (!meson_plane)
0542 return -ENOMEM;
0543
0544 meson_plane->priv = priv;
0545 plane = &meson_plane->base;
0546
0547 if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM))
0548 format_modifiers = format_modifiers_afbc_gxm;
0549 else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A))
0550 format_modifiers = format_modifiers_afbc_g12a;
0551
0552 drm_universal_plane_init(priv->drm, plane, 0xFF,
0553 &meson_plane_funcs,
0554 supported_drm_formats,
0555 ARRAY_SIZE(supported_drm_formats),
0556 format_modifiers,
0557 DRM_PLANE_TYPE_PRIMARY, "meson_primary_plane");
0558
0559 drm_plane_helper_add(plane, &meson_plane_helper_funcs);
0560
0561
0562 drm_plane_create_zpos_immutable_property(plane, 1);
0563
0564 priv->primary_plane = plane;
0565
0566 return 0;
0567 }