hc
2024-05-10 cde9070d9970eef1f7ec2360586c802a16230ad8
kernel/drivers/gpu/drm/meson/meson_vpp.c
....@@ -1,29 +1,16 @@
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
+
2411 #include "meson_drv.h"
25
-#include "meson_vpp.h"
2612 #include "meson_registers.h"
13
+#include "meson_vpp.h"
2714
2815 /**
2916 * DOC: Video Post Processing
....@@ -51,52 +38,6 @@
5138 writel(mux, priv->io_base + _REG(VPU_VIU_VENC_MUX_CTRL));
5239 }
5340
54
-/*
55
- * When the output is interlaced, the OSD must switch between
56
- * each field using the INTERLACE_SEL_ODD (0) of VIU_OSD1_BLK0_CFG_W0
57
- * at each vsync.
58
- * But the vertical scaler can provide such funtionnality if
59
- * is configured for 2:1 scaling with interlace options enabled.
60
- */
61
-void meson_vpp_setup_interlace_vscaler_osd1(struct meson_drm *priv,
62
- struct drm_rect *input)
63
-{
64
- writel_relaxed(BIT(3) /* Enable scaler */ |
65
- BIT(2), /* Select OSD1 */
66
- priv->io_base + _REG(VPP_OSD_SC_CTRL0));
67
-
68
- writel_relaxed(((drm_rect_width(input) - 1) << 16) |
69
- (drm_rect_height(input) - 1),
70
- priv->io_base + _REG(VPP_OSD_SCI_WH_M1));
71
- /* 2:1 scaling */
72
- writel_relaxed(((input->x1) << 16) | (input->x2),
73
- priv->io_base + _REG(VPP_OSD_SCO_H_START_END));
74
- writel_relaxed(((input->y1 >> 1) << 16) | (input->y2 >> 1),
75
- priv->io_base + _REG(VPP_OSD_SCO_V_START_END));
76
-
77
- /* 2:1 scaling values */
78
- writel_relaxed(BIT(16), priv->io_base + _REG(VPP_OSD_VSC_INI_PHASE));
79
- writel_relaxed(BIT(25), priv->io_base + _REG(VPP_OSD_VSC_PHASE_STEP));
80
-
81
- writel_relaxed(0, priv->io_base + _REG(VPP_OSD_HSC_CTRL0));
82
-
83
- writel_relaxed((4 << 0) /* osd_vsc_bank_length */ |
84
- (4 << 3) /* osd_vsc_top_ini_rcv_num0 */ |
85
- (1 << 8) /* osd_vsc_top_rpt_p0_num0 */ |
86
- (6 << 11) /* osd_vsc_bot_ini_rcv_num0 */ |
87
- (2 << 16) /* osd_vsc_bot_rpt_p0_num0 */ |
88
- BIT(23) /* osd_prog_interlace */ |
89
- BIT(24), /* Enable vertical scaler */
90
- priv->io_base + _REG(VPP_OSD_VSC_CTRL0));
91
-}
92
-
93
-void meson_vpp_disable_interlace_vscaler_osd1(struct meson_drm *priv)
94
-{
95
- writel_relaxed(0, priv->io_base + _REG(VPP_OSD_SC_CTRL0));
96
- writel_relaxed(0, priv->io_base + _REG(VPP_OSD_VSC_CTRL0));
97
- writel_relaxed(0, priv->io_base + _REG(VPP_OSD_HSC_CTRL0));
98
-}
99
-
10041 static unsigned int vpp_filter_coefs_4point_bspline[] = {
10142 0x15561500, 0x14561600, 0x13561700, 0x12561800,
10243 0x11551a00, 0x11541b00, 0x10541c00, 0x0f541d00,
....@@ -115,52 +56,110 @@
11556 {
11657 int i;
11758
118
- writel_relaxed(is_horizontal ? BIT(8) : 0,
59
+ writel_relaxed(is_horizontal ? VPP_SCALE_HORIZONTAL_COEF : 0,
11960 priv->io_base + _REG(VPP_OSD_SCALE_COEF_IDX));
12061 for (i = 0; i < 33; i++)
12162 writel_relaxed(coefs[i],
12263 priv->io_base + _REG(VPP_OSD_SCALE_COEF));
12364 }
12465
66
+static const uint32_t vpp_filter_coefs_bicubic[] = {
67
+ 0x00800000, 0x007f0100, 0xff7f0200, 0xfe7f0300,
68
+ 0xfd7e0500, 0xfc7e0600, 0xfb7d0800, 0xfb7c0900,
69
+ 0xfa7b0b00, 0xfa7a0dff, 0xf9790fff, 0xf97711ff,
70
+ 0xf87613ff, 0xf87416fe, 0xf87218fe, 0xf8701afe,
71
+ 0xf76f1dfd, 0xf76d1ffd, 0xf76b21fd, 0xf76824fd,
72
+ 0xf76627fc, 0xf76429fc, 0xf7612cfc, 0xf75f2ffb,
73
+ 0xf75d31fb, 0xf75a34fb, 0xf75837fa, 0xf7553afa,
74
+ 0xf8523cfa, 0xf8503ff9, 0xf84d42f9, 0xf84a45f9,
75
+ 0xf84848f8
76
+};
77
+
78
+static void meson_vpp_write_vd_scaling_filter_coefs(struct meson_drm *priv,
79
+ const unsigned int *coefs,
80
+ bool is_horizontal)
81
+{
82
+ int i;
83
+
84
+ writel_relaxed(is_horizontal ? VPP_SCALE_HORIZONTAL_COEF : 0,
85
+ priv->io_base + _REG(VPP_SCALE_COEF_IDX));
86
+ for (i = 0; i < 33; i++)
87
+ writel_relaxed(coefs[i],
88
+ priv->io_base + _REG(VPP_SCALE_COEF));
89
+}
90
+
12591 void meson_vpp_init(struct meson_drm *priv)
12692 {
12793 /* set dummy data default YUV black */
128
- if (meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu"))
94
+ if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXL))
12995 writel_relaxed(0x108080, priv->io_base + _REG(VPP_DUMMY_DATA1));
130
- else if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu")) {
96
+ else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM)) {
13197 writel_bits_relaxed(0xff << 16, 0xff << 16,
13298 priv->io_base + _REG(VIU_MISC_CTRL1));
133
- writel_relaxed(0x20000, priv->io_base + _REG(VPP_DOLBY_CTRL));
99
+ writel_relaxed(VPP_PPS_DUMMY_DATA_MODE,
100
+ priv->io_base + _REG(VPP_DOLBY_CTRL));
134101 writel_relaxed(0x1020080,
135102 priv->io_base + _REG(VPP_DUMMY_DATA1));
136
- }
103
+ writel_relaxed(0x42020,
104
+ priv->io_base + _REG(VPP_DUMMY_DATA));
105
+ } else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A))
106
+ writel_relaxed(0xf, priv->io_base + _REG(DOLBY_PATH_CTRL));
137107
138108 /* Initialize vpu fifo control registers */
139
- writel_relaxed(readl_relaxed(priv->io_base + _REG(VPP_OFIFO_SIZE)) |
140
- 0x77f, priv->io_base + _REG(VPP_OFIFO_SIZE));
141
- writel_relaxed(0x08080808, priv->io_base + _REG(VPP_HOLD_LINES));
109
+ if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A))
110
+ writel_relaxed(VPP_OFIFO_SIZE_DEFAULT,
111
+ priv->io_base + _REG(VPP_OFIFO_SIZE));
112
+ else
113
+ writel_bits_relaxed(VPP_OFIFO_SIZE_MASK, 0x77f,
114
+ priv->io_base + _REG(VPP_OFIFO_SIZE));
115
+ writel_relaxed(VPP_POSTBLEND_HOLD_LINES(4) | VPP_PREBLEND_HOLD_LINES(4),
116
+ priv->io_base + _REG(VPP_HOLD_LINES));
142117
143
- /* Turn off preblend */
144
- writel_bits_relaxed(VPP_PREBLEND_ENABLE, 0,
145
- priv->io_base + _REG(VPP_MISC));
118
+ if (!meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) {
119
+ /* Turn off preblend */
120
+ writel_bits_relaxed(VPP_PREBLEND_ENABLE, 0,
121
+ priv->io_base + _REG(VPP_MISC));
146122
147
- /* Turn off POSTBLEND */
148
- writel_bits_relaxed(VPP_POSTBLEND_ENABLE, 0,
149
- priv->io_base + _REG(VPP_MISC));
123
+ /* Turn off POSTBLEND */
124
+ writel_bits_relaxed(VPP_POSTBLEND_ENABLE, 0,
125
+ priv->io_base + _REG(VPP_MISC));
150126
151
- /* Force all planes off */
152
- writel_bits_relaxed(VPP_OSD1_POSTBLEND | VPP_OSD2_POSTBLEND |
153
- VPP_VD1_POSTBLEND | VPP_VD2_POSTBLEND, 0,
154
- priv->io_base + _REG(VPP_MISC));
127
+ /* Force all planes off */
128
+ writel_bits_relaxed(VPP_OSD1_POSTBLEND | VPP_OSD2_POSTBLEND |
129
+ VPP_VD1_POSTBLEND | VPP_VD2_POSTBLEND |
130
+ VPP_VD1_PREBLEND | VPP_VD2_PREBLEND, 0,
131
+ priv->io_base + _REG(VPP_MISC));
132
+
133
+ /* Setup default VD settings */
134
+ writel_relaxed(4096,
135
+ priv->io_base + _REG(VPP_PREBLEND_VD1_H_START_END));
136
+ writel_relaxed(4096,
137
+ priv->io_base + _REG(VPP_BLEND_VD2_H_START_END));
138
+ }
155139
156140 /* Disable Scalers */
157141 writel_relaxed(0, priv->io_base + _REG(VPP_OSD_SC_CTRL0));
158142 writel_relaxed(0, priv->io_base + _REG(VPP_OSD_VSC_CTRL0));
159143 writel_relaxed(0, priv->io_base + _REG(VPP_OSD_HSC_CTRL0));
160144
145
+ /* Set horizontal/vertical bank length and enable video scale out */
146
+ writel_relaxed(VPP_VSC_BANK_LENGTH(4) | VPP_HSC_BANK_LENGTH(4) |
147
+ VPP_SC_VD_EN_ENABLE,
148
+ priv->io_base + _REG(VPP_SC_MISC));
149
+
150
+ /* Enable minus black level for vadj1 */
151
+ writel_relaxed(VPP_MINUS_BLACK_LVL_VADJ1_ENABLE,
152
+ priv->io_base + _REG(VPP_VADJ_CTRL));
153
+
161154 /* Write in the proper filter coefficients. */
162155 meson_vpp_write_scaling_filter_coefs(priv,
163156 vpp_filter_coefs_4point_bspline, false);
164157 meson_vpp_write_scaling_filter_coefs(priv,
165158 vpp_filter_coefs_4point_bspline, true);
159
+
160
+ /* Write the VD proper filter coefficients. */
161
+ meson_vpp_write_vd_scaling_filter_coefs(priv, vpp_filter_coefs_bicubic,
162
+ false);
163
+ meson_vpp_write_vd_scaling_filter_coefs(priv, vpp_filter_coefs_bicubic,
164
+ true);
166165 }