forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-05-13 9d77db3c730780c8ef5ccd4b66403ff5675cfe4e
kernel/drivers/gpu/drm/meson/meson_plane.c
....@@ -1,49 +1,74 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * Copyright (C) 2016 BayLibre, SAS
34 * Author: Neil Armstrong <narmstrong@baylibre.com>
45 * Copyright (C) 2015 Amlogic, Inc. All rights reserved.
56 * Copyright (C) 2014 Endless Mobile
67 *
7
- * This program is free software; you can redistribute it and/or
8
- * modify it under the terms of the GNU General Public License as
9
- * published by the Free Software Foundation; either version 2 of the
10
- * License, or (at your option) any later version.
11
- *
12
- * This program is distributed in the hope that it will be useful, but
13
- * WITHOUT ANY WARRANTY; without even the implied warranty of
14
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15
- * General Public License for more details.
16
- *
17
- * You should have received a copy of the GNU General Public License
18
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
19
- *
208 * Written by:
219 * Jasper St. Pierre <jstpierre@mecheye.net>
2210 */
2311
24
-#include <linux/kernel.h>
25
-#include <linux/module.h>
26
-#include <linux/mutex.h>
27
-#include <linux/platform_device.h>
28
-#include <drm/drmP.h>
12
+#include <linux/bitfield.h>
13
+
2914 #include <drm/drm_atomic.h>
3015 #include <drm/drm_atomic_helper.h>
31
-#include <drm/drm_plane_helper.h>
32
-#include <drm/drm_gem_cma_helper.h>
16
+#include <drm/drm_device.h>
3317 #include <drm/drm_fb_cma_helper.h>
34
-#include <drm/drm_rect.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>
3522
3623 #include "meson_plane.h"
37
-#include "meson_vpp.h"
38
-#include "meson_viu.h"
39
-#include "meson_canvas.h"
4024 #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)
4163
4264 struct meson_plane {
4365 struct drm_plane base;
4466 struct meson_drm *priv;
67
+ bool enabled;
4568 };
4669 #define to_meson_plane(x) container_of(x, struct meson_plane, base)
70
+
71
+#define FRAC_16_16(mult, div) (((mult) << 16) / (div))
4772
4873 static int meson_plane_atomic_check(struct drm_plane *plane,
4974 struct drm_plane_state *state)
....@@ -57,11 +82,22 @@
5782 if (IS_ERR(crtc_state))
5883 return PTR_ERR(crtc_state);
5984
85
+ /*
86
+ * Only allow :
87
+ * - Upscaling up to 5x, vertical and horizontal
88
+ * - Final coordinates must match crtc size
89
+ */
6090 return drm_atomic_helper_check_plane_state(state, crtc_state,
91
+ FRAC_16_16(1, 5),
6192 DRM_PLANE_HELPER_NO_SCALING,
62
- DRM_PLANE_HELPER_NO_SCALING,
63
- true, true);
93
+ false, true);
6494 }
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)
65101
66102 /* Takes a fixed 16.16 number and converts it to integer. */
67103 static inline int64_t fixed16_to_int(int64_t value)
....@@ -69,27 +105,45 @@
69105 return value >> 16;
70106 }
71107
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
+
72128 static void meson_plane_atomic_update(struct drm_plane *plane,
73129 struct drm_plane_state *old_state)
74130 {
75131 struct meson_plane *meson_plane = to_meson_plane(plane);
76132 struct drm_plane_state *state = plane->state;
77
- struct drm_framebuffer *fb = state->fb;
133
+ struct drm_rect dest = drm_plane_state_dest(state);
78134 struct meson_drm *priv = meson_plane->priv;
135
+ struct drm_framebuffer *fb = state->fb;
79136 struct drm_gem_cma_object *gem;
80
- struct drm_rect src = {
81
- .x1 = (state->src_x),
82
- .y1 = (state->src_y),
83
- .x2 = (state->src_x + state->src_w),
84
- .y2 = (state->src_y + state->src_h),
85
- };
86
- struct drm_rect dest = {
87
- .x1 = state->crtc_x,
88
- .y1 = state->crtc_y,
89
- .x2 = state->crtc_x + state->crtc_w,
90
- .y2 = state->crtc_y + state->crtc_h,
91
- };
92137 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;
93147
94148 /*
95149 * Update Coordinates
....@@ -99,77 +153,210 @@
99153 */
100154 spin_lock_irqsave(&priv->drm->event_lock, flags);
101155
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
+
102164 /* Enable OSD and BLK0, set max global alpha */
103165 priv->viu.osd1_ctrl_stat = OSD_ENABLE |
104
- (0xFF << OSD_GLOBAL_ALPHA_SHIFT) |
166
+ (0x100 << OSD_GLOBAL_ALPHA_SHIFT) |
105167 OSD_BLK0_ENABLE;
106168
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
+
107174 /* Set up BLK0 to point to the right canvas */
108
- priv->viu.osd1_blk0_cfg[0] = ((MESON_CANVAS_ID_OSD1 << OSD_CANVAS_SEL) |
109
- OSD_ENDIANNESS_LE);
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
+ }
110196
111197 /* On GXBB, Use the old non-HDR RGB2YUV converter */
112
- if (meson_vpu_is_compatible(priv, "amlogic,meson-gxbb-vpu"))
198
+ if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXBB))
113199 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
+ }
114228
115229 switch (fb->format->format) {
116230 case DRM_FORMAT_XRGB8888:
117
- /* For XRGB, replace the pixel's alpha by 0xFF */
118
- writel_bits_relaxed(OSD_REPLACE_EN, OSD_REPLACE_EN,
119
- priv->io_base + _REG(VIU_OSD1_CTRL_STAT2));
120
- priv->viu.osd1_blk0_cfg[0] |= OSD_BLK_MODE_32 |
121
- OSD_COLOR_MATRIX_32_ARGB;
122
- break;
123231 case DRM_FORMAT_XBGR8888:
124232 /* For XRGB, replace the pixel's alpha by 0xFF */
125
- writel_bits_relaxed(OSD_REPLACE_EN, OSD_REPLACE_EN,
126
- priv->io_base + _REG(VIU_OSD1_CTRL_STAT2));
127
- priv->viu.osd1_blk0_cfg[0] |= OSD_BLK_MODE_32 |
128
- OSD_COLOR_MATRIX_32_ABGR;
233
+ priv->viu.osd1_ctrl_stat2 |= OSD_REPLACE_EN;
129234 break;
130235 case DRM_FORMAT_ARGB8888:
131
- /* For ARGB, use the pixel's alpha */
132
- writel_bits_relaxed(OSD_REPLACE_EN, 0,
133
- priv->io_base + _REG(VIU_OSD1_CTRL_STAT2));
134
- priv->viu.osd1_blk0_cfg[0] |= OSD_BLK_MODE_32 |
135
- OSD_COLOR_MATRIX_32_ARGB;
136
- break;
137236 case DRM_FORMAT_ABGR8888:
138237 /* For ARGB, use the pixel's alpha */
139
- writel_bits_relaxed(OSD_REPLACE_EN, 0,
140
- priv->io_base + _REG(VIU_OSD1_CTRL_STAT2));
141
- priv->viu.osd1_blk0_cfg[0] |= OSD_BLK_MODE_32 |
142
- OSD_COLOR_MATRIX_32_ABGR;
238
+ priv->viu.osd1_ctrl_stat2 &= ~OSD_REPLACE_EN;
143239 break;
144
- case DRM_FORMAT_RGB888:
145
- priv->viu.osd1_blk0_cfg[0] |= OSD_BLK_MODE_24 |
146
- OSD_COLOR_MATRIX_24_RGB;
147
- break;
148
- case DRM_FORMAT_RGB565:
149
- priv->viu.osd1_blk0_cfg[0] |= OSD_BLK_MODE_16 |
150
- OSD_COLOR_MATRIX_16_RGB565;
151
- break;
152
- };
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;
153247
154248 if (state->crtc->mode.flags & DRM_MODE_FLAG_INTERLACE) {
155
- priv->viu.osd1_interlace = true;
249
+ vsc_bot_rcv_num = 6;
250
+ vsc_bot_rpt_p0_num = 2;
251
+ }
156252
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) {
157271 dest.y1 /= 2;
158272 dest.y2 /= 2;
159
- } else
160
- priv->viu.osd1_interlace = false;
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
+ }
161339
162340 /*
163341 * The format of these registers is (x2 << 16 | x1),
164342 * where x2 is exclusive.
165343 * e.g. +30x1920 would be (1919 << 16) | 30
166344 */
167
- priv->viu.osd1_blk0_cfg[1] = ((fixed16_to_int(src.x2) - 1) << 16) |
168
- fixed16_to_int(src.x1);
169
- priv->viu.osd1_blk0_cfg[2] = ((fixed16_to_int(src.y2) - 1) << 16) |
170
- fixed16_to_int(src.y1);
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);
171351 priv->viu.osd1_blk0_cfg[3] = ((dest.x2 - 1) << 16) | dest.x1;
172352 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
+ }
173360
174361 /* Update Canvas with buffer address */
175362 gem = drm_fb_cma_get_gem_obj(fb, 0);
....@@ -177,6 +364,28 @@
177364 priv->viu.osd1_addr = gem->paddr;
178365 priv->viu.osd1_stride = fb->pitches[0];
179366 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;
180389
181390 spin_unlock_irqrestore(&priv->drm->event_lock, flags);
182391 }
....@@ -187,17 +396,65 @@
187396 struct meson_plane *meson_plane = to_meson_plane(plane);
188397 struct meson_drm *priv = meson_plane->priv;
189398
190
- /* Disable OSD1 */
191
- writel_bits_relaxed(VPP_OSD1_POSTBLEND, 0,
192
- priv->io_base + _REG(VPP_MISC));
399
+ if (priv->afbcd.ops) {
400
+ priv->afbcd.ops->reset(priv);
401
+ priv->afbcd.ops->disable(priv);
402
+ }
193403
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;
194414 }
195415
196416 static const struct drm_plane_helper_funcs meson_plane_helper_funcs = {
197417 .atomic_check = meson_plane_atomic_check,
198418 .atomic_disable = meson_plane_atomic_disable,
199419 .atomic_update = meson_plane_atomic_update,
420
+ .prepare_fb = drm_gem_fb_prepare_fb,
200421 };
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
+}
201458
202459 static const struct drm_plane_funcs meson_plane_funcs = {
203460 .update_plane = drm_atomic_helper_update_plane,
....@@ -206,6 +463,7 @@
206463 .reset = drm_atomic_helper_plane_reset,
207464 .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
208465 .atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
466
+ .format_mod_supported = meson_plane_format_mod_supported,
209467 };
210468
211469 static const uint32_t supported_drm_formats[] = {
....@@ -217,10 +475,60 @@
217475 DRM_FORMAT_RGB565,
218476 };
219477
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
+
220527 int meson_plane_create(struct meson_drm *priv)
221528 {
222529 struct meson_plane *meson_plane;
223530 struct drm_plane *plane;
531
+ const uint64_t *format_modifiers = format_modifiers_default;
224532
225533 meson_plane = devm_kzalloc(priv->drm->dev, sizeof(*meson_plane),
226534 GFP_KERNEL);
....@@ -230,15 +538,23 @@
230538 meson_plane->priv = priv;
231539 plane = &meson_plane->base;
232540
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
+
233546 drm_universal_plane_init(priv->drm, plane, 0xFF,
234547 &meson_plane_funcs,
235548 supported_drm_formats,
236549 ARRAY_SIZE(supported_drm_formats),
237
- NULL,
550
+ format_modifiers,
238551 DRM_PLANE_TYPE_PRIMARY, "meson_primary_plane");
239552
240553 drm_plane_helper_add(plane, &meson_plane_helper_funcs);
241554
555
+ /* For now, OSD Primary plane is always on the front */
556
+ drm_plane_create_zpos_immutable_property(plane, 1);
557
+
242558 priv->primary_plane = plane;
243559
244560 return 0;