forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-05-13 9d77db3c730780c8ef5ccd4b66403ff5675cfe4e
kernel/drivers/gpu/drm/meson/meson_viu.c
....@@ -1,31 +1,18 @@
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
6
- *
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/>.
197 */
208
21
-#include <linux/kernel.h>
22
-#include <linux/module.h>
23
-#include <drm/drmP.h>
9
+#include <linux/export.h>
10
+#include <linux/bitfield.h>
11
+
12
+#include <drm/drm_fourcc.h>
13
+
2414 #include "meson_drv.h"
2515 #include "meson_viu.h"
26
-#include "meson_vpp.h"
27
-#include "meson_venc.h"
28
-#include "meson_canvas.h"
2916 #include "meson_registers.h"
3017
3118 /**
....@@ -91,8 +78,36 @@
9178 EOTF_COEFF_RIGHTSHIFT /* right shift */
9279 };
9380
94
-void meson_viu_set_osd_matrix(struct meson_drm *priv,
95
- enum viu_matrix_sel_e m_select,
81
+static void meson_viu_set_g12a_osd1_matrix(struct meson_drm *priv,
82
+ int *m, bool csc_on)
83
+{
84
+ /* VPP WRAP OSD1 matrix */
85
+ writel(((m[0] & 0xfff) << 16) | (m[1] & 0xfff),
86
+ priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_PRE_OFFSET0_1));
87
+ writel(m[2] & 0xfff,
88
+ priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_PRE_OFFSET2));
89
+ writel(((m[3] & 0x1fff) << 16) | (m[4] & 0x1fff),
90
+ priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_COEF00_01));
91
+ writel(((m[5] & 0x1fff) << 16) | (m[6] & 0x1fff),
92
+ priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_COEF02_10));
93
+ writel(((m[7] & 0x1fff) << 16) | (m[8] & 0x1fff),
94
+ priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_COEF11_12));
95
+ writel(((m[9] & 0x1fff) << 16) | (m[10] & 0x1fff),
96
+ priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_COEF20_21));
97
+ writel((m[11] & 0x1fff),
98
+ priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_COEF22));
99
+
100
+ writel(((m[18] & 0xfff) << 16) | (m[19] & 0xfff),
101
+ priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_OFFSET0_1));
102
+ writel(m[20] & 0xfff,
103
+ priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_OFFSET2));
104
+
105
+ writel_bits_relaxed(BIT(0), csc_on ? BIT(0) : 0,
106
+ priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_EN_CTRL));
107
+}
108
+
109
+static void meson_viu_set_osd_matrix(struct meson_drm *priv,
110
+ enum viu_matrix_sel_e m_select,
96111 int *m, bool csc_on)
97112 {
98113 if (m_select == VIU_MATRIX_OSD) {
....@@ -160,10 +175,10 @@
160175 #define OSD_EOTF_LUT_SIZE 33
161176 #define OSD_OETF_LUT_SIZE 41
162177
163
-void meson_viu_set_osd_lut(struct meson_drm *priv, enum viu_lut_sel_e lut_sel,
164
- unsigned int *r_map, unsigned int *g_map,
165
- unsigned int *b_map,
166
- bool csc_on)
178
+static void
179
+meson_viu_set_osd_lut(struct meson_drm *priv, enum viu_lut_sel_e lut_sel,
180
+ unsigned int *r_map, unsigned int *g_map,
181
+ unsigned int *b_map, bool csc_on)
167182 {
168183 unsigned int addr_port;
169184 unsigned int data_port;
....@@ -296,28 +311,140 @@
296311 true);
297312 }
298313
314
+/* VIU OSD1 Reset as workaround for GXL+ Alpha OSD Bug */
315
+void meson_viu_osd1_reset(struct meson_drm *priv)
316
+{
317
+ uint32_t osd1_fifo_ctrl_stat, osd1_ctrl_stat2;
318
+
319
+ /* Save these 2 registers state */
320
+ osd1_fifo_ctrl_stat = readl_relaxed(
321
+ priv->io_base + _REG(VIU_OSD1_FIFO_CTRL_STAT));
322
+ osd1_ctrl_stat2 = readl_relaxed(
323
+ priv->io_base + _REG(VIU_OSD1_CTRL_STAT2));
324
+
325
+ /* Reset OSD1 */
326
+ writel_bits_relaxed(VIU_SW_RESET_OSD1, VIU_SW_RESET_OSD1,
327
+ priv->io_base + _REG(VIU_SW_RESET));
328
+ writel_bits_relaxed(VIU_SW_RESET_OSD1, 0,
329
+ priv->io_base + _REG(VIU_SW_RESET));
330
+
331
+ /* Rewrite these registers state lost in the reset */
332
+ writel_relaxed(osd1_fifo_ctrl_stat,
333
+ priv->io_base + _REG(VIU_OSD1_FIFO_CTRL_STAT));
334
+ writel_relaxed(osd1_ctrl_stat2,
335
+ priv->io_base + _REG(VIU_OSD1_CTRL_STAT2));
336
+
337
+ /* Reload the conversion matrix */
338
+ meson_viu_load_matrix(priv);
339
+}
340
+
341
+#define OSD1_MALI_ORDER_ABGR \
342
+ (FIELD_PREP(VIU_OSD1_MALI_AFBCD_A_REORDER, \
343
+ VIU_OSD1_MALI_REORDER_A) | \
344
+ FIELD_PREP(VIU_OSD1_MALI_AFBCD_B_REORDER, \
345
+ VIU_OSD1_MALI_REORDER_B) | \
346
+ FIELD_PREP(VIU_OSD1_MALI_AFBCD_G_REORDER, \
347
+ VIU_OSD1_MALI_REORDER_G) | \
348
+ FIELD_PREP(VIU_OSD1_MALI_AFBCD_R_REORDER, \
349
+ VIU_OSD1_MALI_REORDER_R))
350
+
351
+#define OSD1_MALI_ORDER_ARGB \
352
+ (FIELD_PREP(VIU_OSD1_MALI_AFBCD_A_REORDER, \
353
+ VIU_OSD1_MALI_REORDER_A) | \
354
+ FIELD_PREP(VIU_OSD1_MALI_AFBCD_B_REORDER, \
355
+ VIU_OSD1_MALI_REORDER_R) | \
356
+ FIELD_PREP(VIU_OSD1_MALI_AFBCD_G_REORDER, \
357
+ VIU_OSD1_MALI_REORDER_G) | \
358
+ FIELD_PREP(VIU_OSD1_MALI_AFBCD_R_REORDER, \
359
+ VIU_OSD1_MALI_REORDER_B))
360
+
361
+void meson_viu_g12a_enable_osd1_afbc(struct meson_drm *priv)
362
+{
363
+ u32 afbc_order = OSD1_MALI_ORDER_ARGB;
364
+
365
+ /* Enable Mali AFBC Unpack */
366
+ writel_bits_relaxed(VIU_OSD1_MALI_UNPACK_EN,
367
+ VIU_OSD1_MALI_UNPACK_EN,
368
+ priv->io_base + _REG(VIU_OSD1_MALI_UNPACK_CTRL));
369
+
370
+ switch (priv->afbcd.format) {
371
+ case DRM_FORMAT_XBGR8888:
372
+ case DRM_FORMAT_ABGR8888:
373
+ afbc_order = OSD1_MALI_ORDER_ABGR;
374
+ break;
375
+ }
376
+
377
+ /* Setup RGBA Reordering */
378
+ writel_bits_relaxed(VIU_OSD1_MALI_AFBCD_A_REORDER |
379
+ VIU_OSD1_MALI_AFBCD_B_REORDER |
380
+ VIU_OSD1_MALI_AFBCD_G_REORDER |
381
+ VIU_OSD1_MALI_AFBCD_R_REORDER,
382
+ afbc_order,
383
+ priv->io_base + _REG(VIU_OSD1_MALI_UNPACK_CTRL));
384
+
385
+ /* Select AFBCD path for OSD1 */
386
+ writel_bits_relaxed(OSD_PATH_OSD_AXI_SEL_OSD1_AFBCD,
387
+ OSD_PATH_OSD_AXI_SEL_OSD1_AFBCD,
388
+ priv->io_base + _REG(OSD_PATH_MISC_CTRL));
389
+}
390
+
391
+void meson_viu_g12a_disable_osd1_afbc(struct meson_drm *priv)
392
+{
393
+ /* Disable AFBCD path for OSD1 */
394
+ writel_bits_relaxed(OSD_PATH_OSD_AXI_SEL_OSD1_AFBCD, 0,
395
+ priv->io_base + _REG(OSD_PATH_MISC_CTRL));
396
+
397
+ /* Disable AFBCD unpack */
398
+ writel_bits_relaxed(VIU_OSD1_MALI_UNPACK_EN, 0,
399
+ priv->io_base + _REG(VIU_OSD1_MALI_UNPACK_CTRL));
400
+}
401
+
402
+void meson_viu_gxm_enable_osd1_afbc(struct meson_drm *priv)
403
+{
404
+ writel_bits_relaxed(MALI_AFBC_MISC, FIELD_PREP(MALI_AFBC_MISC, 0x90),
405
+ priv->io_base + _REG(VIU_MISC_CTRL1));
406
+}
407
+
408
+void meson_viu_gxm_disable_osd1_afbc(struct meson_drm *priv)
409
+{
410
+ writel_bits_relaxed(MALI_AFBC_MISC, FIELD_PREP(MALI_AFBC_MISC, 0x00),
411
+ priv->io_base + _REG(VIU_MISC_CTRL1));
412
+}
413
+
299414 void meson_viu_init(struct meson_drm *priv)
300415 {
301416 uint32_t reg;
302417
303418 /* Disable OSDs */
304
- writel_bits_relaxed(BIT(0) | BIT(21), 0,
305
- priv->io_base + _REG(VIU_OSD1_CTRL_STAT));
306
- writel_bits_relaxed(BIT(0) | BIT(21), 0,
307
- priv->io_base + _REG(VIU_OSD2_CTRL_STAT));
419
+ writel_bits_relaxed(VIU_OSD1_OSD_BLK_ENABLE | VIU_OSD1_OSD_ENABLE, 0,
420
+ priv->io_base + _REG(VIU_OSD1_CTRL_STAT));
421
+ writel_bits_relaxed(VIU_OSD1_OSD_BLK_ENABLE | VIU_OSD1_OSD_ENABLE, 0,
422
+ priv->io_base + _REG(VIU_OSD2_CTRL_STAT));
308423
309424 /* On GXL/GXM, Use the 10bit HDR conversion matrix */
310
- if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu") ||
311
- meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu"))
425
+ if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM) ||
426
+ meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXL))
312427 meson_viu_load_matrix(priv);
428
+ else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) {
429
+ meson_viu_set_g12a_osd1_matrix(priv, RGB709_to_YUV709l_coeff,
430
+ true);
431
+ /* fix green/pink color distortion from vendor u-boot */
432
+ writel_bits_relaxed(OSD1_HDR2_CTRL_REG_ONLY_MAT |
433
+ OSD1_HDR2_CTRL_VDIN0_HDR2_TOP_EN, 0,
434
+ priv->io_base + _REG(OSD1_HDR2_CTRL));
435
+ }
313436
314437 /* Initialize OSD1 fifo control register */
315
- reg = BIT(0) | /* Urgent DDR request priority */
316
- (4 << 5) | /* hold_fifo_lines */
317
- (3 << 10) | /* burst length 64 */
318
- (32 << 12) | /* fifo_depth_val: 32*8=256 */
319
- (2 << 22) | /* 4 words in 1 burst */
320
- (2 << 24);
438
+ reg = VIU_OSD_DDR_PRIORITY_URGENT |
439
+ VIU_OSD_FIFO_DEPTH_VAL(32) | /* fifo_depth_val: 32*8=256 */
440
+ VIU_OSD_WORDS_PER_BURST(4) | /* 4 words in 1 burst */
441
+ VIU_OSD_FIFO_LIMITS(2); /* fifo_lim: 2*16=32 */
442
+
443
+ if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A))
444
+ reg |= (VIU_OSD_BURST_LENGTH_32 | VIU_OSD_HOLD_FIFO_LINES(31));
445
+ else
446
+ reg |= (VIU_OSD_BURST_LENGTH_64 | VIU_OSD_HOLD_FIFO_LINES(4));
447
+
321448 writel_relaxed(reg, priv->io_base + _REG(VIU_OSD1_FIFO_CTRL_STAT));
322449 writel_relaxed(reg, priv->io_base + _REG(VIU_OSD2_FIFO_CTRL_STAT));
323450
....@@ -329,6 +456,50 @@
329456 0xff << OSD_REPLACE_SHIFT,
330457 priv->io_base + _REG(VIU_OSD2_CTRL_STAT2));
331458
459
+ /* Disable VD1 AFBC */
460
+ /* di_mif0_en=0 mif0_to_vpp_en=0 di_mad_en=0 and afbc vd1 set=0*/
461
+ writel_bits_relaxed(VIU_CTRL0_VD1_AFBC_MASK, 0,
462
+ priv->io_base + _REG(VIU_MISC_CTRL0));
463
+ writel_relaxed(0, priv->io_base + _REG(AFBC_ENABLE));
464
+
465
+ writel_relaxed(0x00FF00C0,
466
+ priv->io_base + _REG(VD1_IF0_LUMA_FIFO_SIZE));
467
+ writel_relaxed(0x00FF00C0,
468
+ priv->io_base + _REG(VD2_IF0_LUMA_FIFO_SIZE));
469
+
470
+ if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) {
471
+ u32 val = (u32)VIU_OSD_BLEND_REORDER(0, 1) |
472
+ (u32)VIU_OSD_BLEND_REORDER(1, 0) |
473
+ (u32)VIU_OSD_BLEND_REORDER(2, 0) |
474
+ (u32)VIU_OSD_BLEND_REORDER(3, 0) |
475
+ (u32)VIU_OSD_BLEND_DIN_EN(1) |
476
+ (u32)VIU_OSD_BLEND1_DIN3_BYPASS_TO_DOUT1 |
477
+ (u32)VIU_OSD_BLEND1_DOUT_BYPASS_TO_BLEND2 |
478
+ (u32)VIU_OSD_BLEND_DIN0_BYPASS_TO_DOUT0 |
479
+ (u32)VIU_OSD_BLEND_BLEN2_PREMULT_EN(1) |
480
+ (u32)VIU_OSD_BLEND_HOLD_LINES(4);
481
+ writel_relaxed(val, priv->io_base + _REG(VIU_OSD_BLEND_CTRL));
482
+
483
+ writel_relaxed(OSD_BLEND_PATH_SEL_ENABLE,
484
+ priv->io_base + _REG(OSD1_BLEND_SRC_CTRL));
485
+ writel_relaxed(OSD_BLEND_PATH_SEL_ENABLE,
486
+ priv->io_base + _REG(OSD2_BLEND_SRC_CTRL));
487
+ writel_relaxed(0, priv->io_base + _REG(VD1_BLEND_SRC_CTRL));
488
+ writel_relaxed(0, priv->io_base + _REG(VD2_BLEND_SRC_CTRL));
489
+ writel_relaxed(0,
490
+ priv->io_base + _REG(VIU_OSD_BLEND_DUMMY_DATA0));
491
+ writel_relaxed(0,
492
+ priv->io_base + _REG(VIU_OSD_BLEND_DUMMY_ALPHA));
493
+
494
+ writel_bits_relaxed(DOLBY_BYPASS_EN(0xc), DOLBY_BYPASS_EN(0xc),
495
+ priv->io_base + _REG(DOLBY_PATH_CTRL));
496
+
497
+ meson_viu_g12a_disable_osd1_afbc(priv);
498
+ }
499
+
500
+ if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM))
501
+ meson_viu_gxm_disable_osd1_afbc(priv);
502
+
332503 priv->viu.osd1_enabled = false;
333504 priv->viu.osd1_commit = false;
334505 priv->viu.osd1_interlace = false;