aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/display/amlogic,meson-dw-hdmi.txt4
-rw-r--r--Documentation/devicetree/bindings/display/amlogic,meson-vpu.txt4
-rw-r--r--Documentation/devicetree/bindings/gpu/arm,mali-bifrost.txt92
-rw-r--r--Documentation/gpu/meson.rst6
-rw-r--r--MAINTAINERS2
-rw-r--r--drivers/gpu/drm/Makefile3
-rw-r--r--drivers/gpu/drm/cirrus/Kconfig2
-rw-r--r--drivers/gpu/drm/cirrus/Makefile3
-rw-r--r--drivers/gpu/drm/cirrus/cirrus.c657
-rw-r--r--drivers/gpu/drm/cirrus/cirrus_drv.c161
-rw-r--r--drivers/gpu/drm/cirrus/cirrus_fbdev.c309
-rw-r--r--drivers/gpu/drm/cirrus/cirrus_main.c328
-rw-r--r--drivers/gpu/drm/cirrus/cirrus_mode.c617
-rw-r--r--drivers/gpu/drm/drm_format_helper.c326
-rw-r--r--drivers/gpu/drm/lima/Kconfig3
-rw-r--r--drivers/gpu/drm/lima/lima_gem.c1
-rw-r--r--drivers/gpu/drm/meson/meson_crtc.c269
-rw-r--r--drivers/gpu/drm/meson/meson_drv.c1
-rw-r--r--drivers/gpu/drm/meson/meson_drv.h4
-rw-r--r--drivers/gpu/drm/meson/meson_dw_hdmi.c163
-rw-r--r--drivers/gpu/drm/meson/meson_dw_hdmi.h32
-rw-r--r--drivers/gpu/drm/meson/meson_overlay.c10
-rw-r--r--drivers/gpu/drm/meson/meson_plane.c15
-rw-r--r--drivers/gpu/drm/meson/meson_registers.h247
-rw-r--r--drivers/gpu/drm/meson/meson_vclk.c123
-rw-r--r--drivers/gpu/drm/meson/meson_venc.c11
-rw-r--r--drivers/gpu/drm/meson/meson_venc_cvbs.c25
-rw-r--r--drivers/gpu/drm/meson/meson_viu.c72
-rw-r--r--drivers/gpu/drm/meson/meson_vpp.c51
-rw-r--r--drivers/gpu/drm/panel/panel-rocktech-jh057n00900.c19
-rw-r--r--drivers/gpu/drm/pl111/pl111_versatile.c4
-rw-r--r--drivers/gpu/drm/tinydrm/core/tinydrm-helpers.c158
-rw-r--r--drivers/gpu/drm/tinydrm/mipi-dbi.c7
-rw-r--r--drivers/gpu/drm/tinydrm/repaper.c3
-rw-r--r--drivers/gpu/drm/tinydrm/st7586.c3
-rw-r--r--drivers/gpu/drm/vc4/vc4_debugfs.c2
-rw-r--r--include/drm/drm_format_helper.h34
-rw-r--r--include/drm/tinydrm/tinydrm-helpers.h10
38 files changed, 2028 insertions, 1753 deletions
diff --git a/Documentation/devicetree/bindings/display/amlogic,meson-dw-hdmi.txt b/Documentation/devicetree/bindings/display/amlogic,meson-dw-hdmi.txt
index bf4a18047309..3a50a7862cf3 100644
--- a/Documentation/devicetree/bindings/display/amlogic,meson-dw-hdmi.txt
+++ b/Documentation/devicetree/bindings/display/amlogic,meson-dw-hdmi.txt
@@ -37,6 +37,7 @@ Required properties:
37 - GXL (S905X, S905D) : "amlogic,meson-gxl-dw-hdmi" 37 - GXL (S905X, S905D) : "amlogic,meson-gxl-dw-hdmi"
38 - GXM (S912) : "amlogic,meson-gxm-dw-hdmi" 38 - GXM (S912) : "amlogic,meson-gxm-dw-hdmi"
39 followed by the common "amlogic,meson-gx-dw-hdmi" 39 followed by the common "amlogic,meson-gx-dw-hdmi"
40 - G12A (S905X2, S905Y2, S905D2) : "amlogic,meson-g12a-dw-hdmi"
40- reg: Physical base address and length of the controller's registers. 41- reg: Physical base address and length of the controller's registers.
41- interrupts: The HDMI interrupt number 42- interrupts: The HDMI interrupt number
42- clocks, clock-names : must have the phandles to the HDMI iahb and isfr clocks, 43- clocks, clock-names : must have the phandles to the HDMI iahb and isfr clocks,
@@ -66,6 +67,9 @@ corresponding to each HDMI output and input.
66 S905X (GXL) VENC Input TMDS Output 67 S905X (GXL) VENC Input TMDS Output
67 S905D (GXL) VENC Input TMDS Output 68 S905D (GXL) VENC Input TMDS Output
68 S912 (GXM) VENC Input TMDS Output 69 S912 (GXM) VENC Input TMDS Output
70 S905X2 (G12A) VENC Input TMDS Output
71 S905Y2 (G12A) VENC Input TMDS Output
72 S905D2 (G12A) VENC Input TMDS Output
69 73
70Example: 74Example:
71 75
diff --git a/Documentation/devicetree/bindings/display/amlogic,meson-vpu.txt b/Documentation/devicetree/bindings/display/amlogic,meson-vpu.txt
index 419444e2b4d3..be40a780501c 100644
--- a/Documentation/devicetree/bindings/display/amlogic,meson-vpu.txt
+++ b/Documentation/devicetree/bindings/display/amlogic,meson-vpu.txt
@@ -57,6 +57,7 @@ Required properties:
57 - GXL (S905X, S905D) : "amlogic,meson-gxl-vpu" 57 - GXL (S905X, S905D) : "amlogic,meson-gxl-vpu"
58 - GXM (S912) : "amlogic,meson-gxm-vpu" 58 - GXM (S912) : "amlogic,meson-gxm-vpu"
59 followed by the common "amlogic,meson-gx-vpu" 59 followed by the common "amlogic,meson-gx-vpu"
60 - G12A (S905X2, S905Y2, S905D2) : "amlogic,meson-g12a-vpu"
60- reg: base address and size of he following memory-mapped regions : 61- reg: base address and size of he following memory-mapped regions :
61 - vpu 62 - vpu
62 - hhi 63 - hhi
@@ -83,6 +84,9 @@ corresponding to each VPU output.
83 S905X (GXL) CVBS VDAC HDMI-TX 84 S905X (GXL) CVBS VDAC HDMI-TX
84 S905D (GXL) CVBS VDAC HDMI-TX 85 S905D (GXL) CVBS VDAC HDMI-TX
85 S912 (GXM) CVBS VDAC HDMI-TX 86 S912 (GXM) CVBS VDAC HDMI-TX
87 S905X2 (G12A) CVBS VDAC HDMI-TX
88 S905Y2 (G12A) CVBS VDAC HDMI-TX
89 S905D2 (G12A) CVBS VDAC HDMI-TX
86 90
87Example: 91Example:
88 92
diff --git a/Documentation/devicetree/bindings/gpu/arm,mali-bifrost.txt b/Documentation/devicetree/bindings/gpu/arm,mali-bifrost.txt
new file mode 100644
index 000000000000..b8be9dbc68b4
--- /dev/null
+++ b/Documentation/devicetree/bindings/gpu/arm,mali-bifrost.txt
@@ -0,0 +1,92 @@
1ARM Mali Bifrost GPU
2====================
3
4Required properties:
5
6- compatible :
7 * Since Mali Bifrost GPU model/revision is fully discoverable by reading
8 some determined registers, must contain the following:
9 + "arm,mali-bifrost"
10 * which must be preceded by one of the following vendor specifics:
11 + "amlogic,meson-g12a-mali"
12
13- reg : Physical base address of the device and length of the register area.
14
15- interrupts : Contains the three IRQ lines required by Mali Bifrost devices,
16 in the following defined order.
17
18- interrupt-names : Contains the names of IRQ resources in this exact defined
19 order: "job", "mmu", "gpu".
20
21Optional properties:
22
23- clocks : Phandle to clock for the Mali Bifrost device.
24
25- mali-supply : Phandle to regulator for the Mali device. Refer to
26 Documentation/devicetree/bindings/regulator/regulator.txt for details.
27
28- operating-points-v2 : Refer to Documentation/devicetree/bindings/opp/opp.txt
29 for details.
30
31- resets : Phandle of the GPU reset line.
32
33Vendor-specific bindings
34------------------------
35
36The Mali GPU is integrated very differently from one SoC to
37another. In order to accommodate those differences, you have the option
38to specify one more vendor-specific compatible, among:
39
40- "amlogic,meson-g12a-mali"
41 Required properties:
42 - resets : Should contain phandles of :
43 + GPU reset line
44 + GPU APB glue reset line
45
46Example for a Mali-G31:
47
48gpu@ffa30000 {
49 compatible = "amlogic,meson-g12a-mali", "arm,mali-bifrost";
50 reg = <0xffe40000 0x10000>;
51 interrupts = <GIC_SPI 160 IRQ_TYPE_LEVEL_HIGH>,
52 <GIC_SPI 161 IRQ_TYPE_LEVEL_HIGH>,
53 <GIC_SPI 162 IRQ_TYPE_LEVEL_HIGH>;
54 interrupt-names = "job", "mmu", "gpu";
55 clocks = <&clk CLKID_MALI>;
56 mali-supply = <&vdd_gpu>;
57 operating-points-v2 = <&gpu_opp_table>;
58 resets = <&reset RESET_DVALIN_CAPB3>, <&reset RESET_DVALIN>;
59};
60
61gpu_opp_table: opp_table0 {
62 compatible = "operating-points-v2";
63
64 opp@533000000 {
65 opp-hz = /bits/ 64 <533000000>;
66 opp-microvolt = <1250000>;
67 };
68 opp@450000000 {
69 opp-hz = /bits/ 64 <450000000>;
70 opp-microvolt = <1150000>;
71 };
72 opp@400000000 {
73 opp-hz = /bits/ 64 <400000000>;
74 opp-microvolt = <1125000>;
75 };
76 opp@350000000 {
77 opp-hz = /bits/ 64 <350000000>;
78 opp-microvolt = <1075000>;
79 };
80 opp@266000000 {
81 opp-hz = /bits/ 64 <266000000>;
82 opp-microvolt = <1025000>;
83 };
84 opp@160000000 {
85 opp-hz = /bits/ 64 <160000000>;
86 opp-microvolt = <925000>;
87 };
88 opp@100000000 {
89 opp-hz = /bits/ 64 <100000000>;
90 opp-microvolt = <912500>;
91 };
92};
diff --git a/Documentation/gpu/meson.rst b/Documentation/gpu/meson.rst
index 479f6f51a13b..b9e2f9aa3bd8 100644
--- a/Documentation/gpu/meson.rst
+++ b/Documentation/gpu/meson.rst
@@ -42,12 +42,6 @@ Video Encoder
42.. kernel-doc:: drivers/gpu/drm/meson/meson_venc.c 42.. kernel-doc:: drivers/gpu/drm/meson/meson_venc.c
43 :doc: Video Encoder 43 :doc: Video Encoder
44 44
45Video Canvas Management
46=======================
47
48.. kernel-doc:: drivers/gpu/drm/meson/meson_canvas.c
49 :doc: Canvas
50
51Video Clocks 45Video Clocks
52============ 46============
53 47
diff --git a/MAINTAINERS b/MAINTAINERS
index 4b69b6b48b3b..8825dffebb4c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5209,7 +5209,7 @@ F: Documentation/devicetree/bindings/display/hisilicon/
5209DRM DRIVERS FOR LIMA 5209DRM DRIVERS FOR LIMA
5210M: Qiang Yu <yuq825@gmail.com> 5210M: Qiang Yu <yuq825@gmail.com>
5211L: dri-devel@lists.freedesktop.org 5211L: dri-devel@lists.freedesktop.org
5212L: lima@lists.freedesktop.org 5212L: lima@lists.freedesktop.org (moderated for non-subscribers)
5213S: Maintained 5213S: Maintained
5214F: drivers/gpu/drm/lima/ 5214F: drivers/gpu/drm/lima/
5215F: include/uapi/drm/lima_drm.h 5215F: include/uapi/drm/lima_drm.h
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index d97c0a3a8cfc..7ebae3d45505 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -38,7 +38,8 @@ drm_kms_helper-y := drm_crtc_helper.o drm_dp_helper.o drm_dsc.o drm_probe_helper
38 drm_kms_helper_common.o drm_dp_dual_mode_helper.o \ 38 drm_kms_helper_common.o drm_dp_dual_mode_helper.o \
39 drm_simple_kms_helper.o drm_modeset_helper.o \ 39 drm_simple_kms_helper.o drm_modeset_helper.o \
40 drm_scdc_helper.o drm_gem_framebuffer_helper.o \ 40 drm_scdc_helper.o drm_gem_framebuffer_helper.o \
41 drm_atomic_state_helper.o drm_damage_helper.o 41 drm_atomic_state_helper.o drm_damage_helper.o \
42 drm_format_helper.o
42 43
43drm_kms_helper-$(CONFIG_DRM_PANEL_BRIDGE) += bridge/panel.o 44drm_kms_helper-$(CONFIG_DRM_PANEL_BRIDGE) += bridge/panel.o
44drm_kms_helper-$(CONFIG_DRM_FBDEV_EMULATION) += drm_fb_helper.o 45drm_kms_helper-$(CONFIG_DRM_FBDEV_EMULATION) += drm_fb_helper.o
diff --git a/drivers/gpu/drm/cirrus/Kconfig b/drivers/gpu/drm/cirrus/Kconfig
index fc78c90ee931..dd4f52a0bc1c 100644
--- a/drivers/gpu/drm/cirrus/Kconfig
+++ b/drivers/gpu/drm/cirrus/Kconfig
@@ -2,7 +2,7 @@ config DRM_CIRRUS_QEMU
2 tristate "Cirrus driver for QEMU emulated device" 2 tristate "Cirrus driver for QEMU emulated device"
3 depends on DRM && PCI && MMU 3 depends on DRM && PCI && MMU
4 select DRM_KMS_HELPER 4 select DRM_KMS_HELPER
5 select DRM_TTM 5 select DRM_GEM_SHMEM_HELPER
6 help 6 help
7 This is a KMS driver for emulated cirrus device in qemu. 7 This is a KMS driver for emulated cirrus device in qemu.
8 It is *NOT* intended for real cirrus devices. This requires 8 It is *NOT* intended for real cirrus devices. This requires
diff --git a/drivers/gpu/drm/cirrus/Makefile b/drivers/gpu/drm/cirrus/Makefile
index 919c0a336c97..acf8971d37a1 100644
--- a/drivers/gpu/drm/cirrus/Makefile
+++ b/drivers/gpu/drm/cirrus/Makefile
@@ -1,4 +1 @@
1cirrus-y := cirrus_main.o cirrus_mode.o \
2 cirrus_drv.o cirrus_fbdev.o cirrus_ttm.o
3
4obj-$(CONFIG_DRM_CIRRUS_QEMU) += cirrus.o obj-$(CONFIG_DRM_CIRRUS_QEMU) += cirrus.o
diff --git a/drivers/gpu/drm/cirrus/cirrus.c b/drivers/gpu/drm/cirrus/cirrus.c
new file mode 100644
index 000000000000..5095b8ce52c2
--- /dev/null
+++ b/drivers/gpu/drm/cirrus/cirrus.c
@@ -0,0 +1,657 @@
1/* SPDX-License-Identifier: GPL-2.0 */
2/*
3 * Copyright 2012-2019 Red Hat
4 *
5 * This file is subject to the terms and conditions of the GNU General
6 * Public License version 2. See the file COPYING in the main
7 * directory of this archive for more details.
8 *
9 * Authors: Matthew Garrett
10 * Dave Airlie
11 * Gerd Hoffmann
12 *
13 * Portions of this code derived from cirrusfb.c:
14 * drivers/video/cirrusfb.c - driver for Cirrus Logic chipsets
15 *
16 * Copyright 1999-2001 Jeff Garzik <jgarzik@pobox.com>
17 */
18
19#include <linux/console.h>
20#include <linux/module.h>
21#include <linux/pci.h>
22
23#include <video/cirrus.h>
24#include <video/vga.h>
25
26#include <drm/drm_atomic_helper.h>
27#include <drm/drm_atomic_state_helper.h>
28#include <drm/drm_connector.h>
29#include <drm/drm_damage_helper.h>
30#include <drm/drm_drv.h>
31#include <drm/drm_fb_helper.h>
32#include <drm/drm_file.h>
33#include <drm/drm_format_helper.h>
34#include <drm/drm_fourcc.h>
35#include <drm/drm_gem_shmem_helper.h>
36#include <drm/drm_gem_framebuffer_helper.h>
37#include <drm/drm_ioctl.h>
38#include <drm/drm_modeset_helper_vtables.h>
39#include <drm/drm_probe_helper.h>
40#include <drm/drm_simple_kms_helper.h>
41#include <drm/drm_vblank.h>
42
43#define DRIVER_NAME "cirrus"
44#define DRIVER_DESC "qemu cirrus vga"
45#define DRIVER_DATE "2019"
46#define DRIVER_MAJOR 2
47#define DRIVER_MINOR 0
48
49#define CIRRUS_MAX_PITCH (0x1FF << 3) /* (4096 - 1) & ~111b bytes */
50#define CIRRUS_VRAM_SIZE (4 * 1024 * 1024) /* 4 MB */
51
52struct cirrus_device {
53 struct drm_device dev;
54 struct drm_simple_display_pipe pipe;
55 struct drm_connector conn;
56 unsigned int cpp;
57 unsigned int pitch;
58 void __iomem *vram;
59 void __iomem *mmio;
60};
61
62/* ------------------------------------------------------------------ */
63/*
64 * The meat of this driver. The core passes us a mode and we have to program
65 * it. The modesetting here is the bare minimum required to satisfy the qemu
66 * emulation of this hardware, and running this against a real device is
67 * likely to result in an inadequately programmed mode. We've already had
68 * the opportunity to modify the mode, so whatever we receive here should
69 * be something that can be correctly programmed and displayed
70 */
71
72#define SEQ_INDEX 4
73#define SEQ_DATA 5
74
75static u8 rreg_seq(struct cirrus_device *cirrus, u8 reg)
76{
77 iowrite8(reg, cirrus->mmio + SEQ_INDEX);
78 return ioread8(cirrus->mmio + SEQ_DATA);
79}
80
81static void wreg_seq(struct cirrus_device *cirrus, u8 reg, u8 val)
82{
83 iowrite8(reg, cirrus->mmio + SEQ_INDEX);
84 iowrite8(val, cirrus->mmio + SEQ_DATA);
85}
86
87#define CRT_INDEX 0x14
88#define CRT_DATA 0x15
89
90static u8 rreg_crt(struct cirrus_device *cirrus, u8 reg)
91{
92 iowrite8(reg, cirrus->mmio + CRT_INDEX);
93 return ioread8(cirrus->mmio + CRT_DATA);
94}
95
96static void wreg_crt(struct cirrus_device *cirrus, u8 reg, u8 val)
97{
98 iowrite8(reg, cirrus->mmio + CRT_INDEX);
99 iowrite8(val, cirrus->mmio + CRT_DATA);
100}
101
102#define GFX_INDEX 0xe
103#define GFX_DATA 0xf
104
105static void wreg_gfx(struct cirrus_device *cirrus, u8 reg, u8 val)
106{
107 iowrite8(reg, cirrus->mmio + GFX_INDEX);
108 iowrite8(val, cirrus->mmio + GFX_DATA);
109}
110
111#define VGA_DAC_MASK 0x06
112
113static void wreg_hdr(struct cirrus_device *cirrus, u8 val)
114{
115 ioread8(cirrus->mmio + VGA_DAC_MASK);
116 ioread8(cirrus->mmio + VGA_DAC_MASK);
117 ioread8(cirrus->mmio + VGA_DAC_MASK);
118 ioread8(cirrus->mmio + VGA_DAC_MASK);
119 iowrite8(val, cirrus->mmio + VGA_DAC_MASK);
120}
121
122static int cirrus_convert_to(struct drm_framebuffer *fb)
123{
124 if (fb->format->cpp[0] == 4 && fb->pitches[0] > CIRRUS_MAX_PITCH) {
125 if (fb->width * 3 <= CIRRUS_MAX_PITCH)
126 /* convert from XR24 to RG24 */
127 return 3;
128 else
129 /* convert from XR24 to RG16 */
130 return 2;
131 }
132 return 0;
133}
134
135static int cirrus_cpp(struct drm_framebuffer *fb)
136{
137 int convert_cpp = cirrus_convert_to(fb);
138
139 if (convert_cpp)
140 return convert_cpp;
141 return fb->format->cpp[0];
142}
143
144static int cirrus_pitch(struct drm_framebuffer *fb)
145{
146 int convert_cpp = cirrus_convert_to(fb);
147
148 if (convert_cpp)
149 return convert_cpp * fb->width;
150 return fb->pitches[0];
151}
152
153static void cirrus_set_start_address(struct cirrus_device *cirrus, u32 offset)
154{
155 u32 addr;
156 u8 tmp;
157
158 addr = offset >> 2;
159 wreg_crt(cirrus, 0x0c, (u8)((addr >> 8) & 0xff));
160 wreg_crt(cirrus, 0x0d, (u8)(addr & 0xff));
161
162 tmp = rreg_crt(cirrus, 0x1b);
163 tmp &= 0xf2;
164 tmp |= (addr >> 16) & 0x01;
165 tmp |= (addr >> 15) & 0x0c;
166 wreg_crt(cirrus, 0x1b, tmp);
167
168 tmp = rreg_crt(cirrus, 0x1d);
169 tmp &= 0x7f;
170 tmp |= (addr >> 12) & 0x80;
171 wreg_crt(cirrus, 0x1d, tmp);
172}
173
174static int cirrus_mode_set(struct cirrus_device *cirrus,
175 struct drm_display_mode *mode,
176 struct drm_framebuffer *fb)
177{
178 int hsyncstart, hsyncend, htotal, hdispend;
179 int vtotal, vdispend;
180 int tmp;
181 int sr07 = 0, hdr = 0;
182
183 htotal = mode->htotal / 8;
184 hsyncend = mode->hsync_end / 8;
185 hsyncstart = mode->hsync_start / 8;
186 hdispend = mode->hdisplay / 8;
187
188 vtotal = mode->vtotal;
189 vdispend = mode->vdisplay;
190
191 vdispend -= 1;
192 vtotal -= 2;
193
194 htotal -= 5;
195 hdispend -= 1;
196 hsyncstart += 1;
197 hsyncend += 1;
198
199 wreg_crt(cirrus, VGA_CRTC_V_SYNC_END, 0x20);
200 wreg_crt(cirrus, VGA_CRTC_H_TOTAL, htotal);
201 wreg_crt(cirrus, VGA_CRTC_H_DISP, hdispend);
202 wreg_crt(cirrus, VGA_CRTC_H_SYNC_START, hsyncstart);
203 wreg_crt(cirrus, VGA_CRTC_H_SYNC_END, hsyncend);
204 wreg_crt(cirrus, VGA_CRTC_V_TOTAL, vtotal & 0xff);
205 wreg_crt(cirrus, VGA_CRTC_V_DISP_END, vdispend & 0xff);
206
207 tmp = 0x40;
208 if ((vdispend + 1) & 512)
209 tmp |= 0x20;
210 wreg_crt(cirrus, VGA_CRTC_MAX_SCAN, tmp);
211
212 /*
213 * Overflow bits for values that don't fit in the standard registers
214 */
215 tmp = 0x10;
216 if (vtotal & 0x100)
217 tmp |= 0x01;
218 if (vdispend & 0x100)
219 tmp |= 0x02;
220 if ((vdispend + 1) & 0x100)
221 tmp |= 0x08;
222 if (vtotal & 0x200)
223 tmp |= 0x20;
224 if (vdispend & 0x200)
225 tmp |= 0x40;
226 wreg_crt(cirrus, VGA_CRTC_OVERFLOW, tmp);
227
228 tmp = 0;
229
230 /* More overflow bits */
231
232 if ((htotal + 5) & 0x40)
233 tmp |= 0x10;
234 if ((htotal + 5) & 0x80)
235 tmp |= 0x20;
236 if (vtotal & 0x100)
237 tmp |= 0x40;
238 if (vtotal & 0x200)
239 tmp |= 0x80;
240
241 wreg_crt(cirrus, CL_CRT1A, tmp);
242
243 /* Disable Hercules/CGA compatibility */
244 wreg_crt(cirrus, VGA_CRTC_MODE, 0x03);
245
246 sr07 = rreg_seq(cirrus, 0x07);
247 sr07 &= 0xe0;
248 hdr = 0;
249
250 cirrus->cpp = cirrus_cpp(fb);
251 switch (cirrus->cpp * 8) {
252 case 8:
253 sr07 |= 0x11;
254 break;
255 case 16:
256 sr07 |= 0x17;
257 hdr = 0xc1;
258 break;
259 case 24:
260 sr07 |= 0x15;
261 hdr = 0xc5;
262 break;
263 case 32:
264 sr07 |= 0x19;
265 hdr = 0xc5;
266 break;
267 default:
268 return -1;
269 }
270
271 wreg_seq(cirrus, 0x7, sr07);
272
273 /* Program the pitch */
274 cirrus->pitch = cirrus_pitch(fb);
275 tmp = cirrus->pitch / 8;
276 wreg_crt(cirrus, VGA_CRTC_OFFSET, tmp);
277
278 /* Enable extended blanking and pitch bits, and enable full memory */
279 tmp = 0x22;
280 tmp |= (cirrus->pitch >> 7) & 0x10;
281 tmp |= (cirrus->pitch >> 6) & 0x40;
282 wreg_crt(cirrus, 0x1b, tmp);
283
284 /* Enable high-colour modes */
285 wreg_gfx(cirrus, VGA_GFX_MODE, 0x40);
286
287 /* And set graphics mode */
288 wreg_gfx(cirrus, VGA_GFX_MISC, 0x01);
289
290 wreg_hdr(cirrus, hdr);
291
292 cirrus_set_start_address(cirrus, 0);
293
294 /* Unblank (needed on S3 resume, vgabios doesn't do it then) */
295 outb(0x20, 0x3c0);
296 return 0;
297}
298
299static int cirrus_fb_blit_rect(struct drm_framebuffer *fb,
300 struct drm_rect *rect)
301{
302 struct cirrus_device *cirrus = fb->dev->dev_private;
303 void *vmap;
304
305 vmap = drm_gem_shmem_vmap(fb->obj[0]);
306 if (!vmap)
307 return -ENOMEM;
308
309 if (cirrus->cpp == fb->format->cpp[0])
310 drm_fb_memcpy_dstclip(__io_virt(cirrus->vram),
311 vmap, fb, rect);
312
313 else if (fb->format->cpp[0] == 4 && cirrus->cpp == 2)
314 drm_fb_xrgb8888_to_rgb565_dstclip(__io_virt(cirrus->vram),
315 cirrus->pitch,
316 vmap, fb, rect, false);
317
318 else if (fb->format->cpp[0] == 4 && cirrus->cpp == 3)
319 drm_fb_xrgb8888_to_rgb888_dstclip(__io_virt(cirrus->vram),
320 cirrus->pitch,
321 vmap, fb, rect);
322
323 else
324 WARN_ON_ONCE("cpp mismatch");
325
326 drm_gem_shmem_vunmap(fb->obj[0], vmap);
327 return 0;
328}
329
330static int cirrus_fb_blit_fullscreen(struct drm_framebuffer *fb)
331{
332 struct drm_rect fullscreen = {
333 .x1 = 0,
334 .x2 = fb->width,
335 .y1 = 0,
336 .y2 = fb->height,
337 };
338 return cirrus_fb_blit_rect(fb, &fullscreen);
339}
340
341static int cirrus_check_size(int width, int height,
342 struct drm_framebuffer *fb)
343{
344 int pitch = width * 2;
345
346 if (fb)
347 pitch = cirrus_pitch(fb);
348
349 if (pitch > CIRRUS_MAX_PITCH)
350 return -EINVAL;
351 if (pitch * height > CIRRUS_VRAM_SIZE)
352 return -EINVAL;
353 return 0;
354}
355
356/* ------------------------------------------------------------------ */
357/* cirrus connector */
358
359static int cirrus_conn_get_modes(struct drm_connector *conn)
360{
361 int count;
362
363 count = drm_add_modes_noedid(conn,
364 conn->dev->mode_config.max_width,
365 conn->dev->mode_config.max_height);
366 drm_set_preferred_mode(conn, 1024, 768);
367 return count;
368}
369
370static const struct drm_connector_helper_funcs cirrus_conn_helper_funcs = {
371 .get_modes = cirrus_conn_get_modes,
372};
373
374static const struct drm_connector_funcs cirrus_conn_funcs = {
375 .fill_modes = drm_helper_probe_single_connector_modes,
376 .destroy = drm_connector_cleanup,
377 .reset = drm_atomic_helper_connector_reset,
378 .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
379 .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
380};
381
382static int cirrus_conn_init(struct cirrus_device *cirrus)
383{
384 drm_connector_helper_add(&cirrus->conn, &cirrus_conn_helper_funcs);
385 return drm_connector_init(&cirrus->dev, &cirrus->conn,
386 &cirrus_conn_funcs, DRM_MODE_CONNECTOR_VGA);
387
388}
389
390/* ------------------------------------------------------------------ */
391/* cirrus (simple) display pipe */
392
393static enum drm_mode_status cirrus_pipe_mode_valid(struct drm_crtc *crtc,
394 const struct drm_display_mode *mode)
395{
396 if (cirrus_check_size(mode->hdisplay, mode->vdisplay, NULL) < 0)
397 return MODE_BAD;
398 return MODE_OK;
399}
400
401static int cirrus_pipe_check(struct drm_simple_display_pipe *pipe,
402 struct drm_plane_state *plane_state,
403 struct drm_crtc_state *crtc_state)
404{
405 struct drm_framebuffer *fb = plane_state->fb;
406
407 if (!fb)
408 return 0;
409 return cirrus_check_size(fb->width, fb->height, fb);
410}
411
412static void cirrus_pipe_enable(struct drm_simple_display_pipe *pipe,
413 struct drm_crtc_state *crtc_state,
414 struct drm_plane_state *plane_state)
415{
416 struct cirrus_device *cirrus = pipe->crtc.dev->dev_private;
417
418 cirrus_mode_set(cirrus, &crtc_state->mode, plane_state->fb);
419 cirrus_fb_blit_fullscreen(plane_state->fb);
420}
421
422static void cirrus_pipe_update(struct drm_simple_display_pipe *pipe,
423 struct drm_plane_state *old_state)
424{
425 struct cirrus_device *cirrus = pipe->crtc.dev->dev_private;
426 struct drm_plane_state *state = pipe->plane.state;
427 struct drm_crtc *crtc = &pipe->crtc;
428 struct drm_rect rect;
429
430 if (pipe->plane.state->fb &&
431 cirrus->cpp != cirrus_cpp(pipe->plane.state->fb))
432 cirrus_mode_set(cirrus, &crtc->mode,
433 pipe->plane.state->fb);
434
435 if (drm_atomic_helper_damage_merged(old_state, state, &rect))
436 cirrus_fb_blit_rect(pipe->plane.state->fb, &rect);
437
438 if (crtc->state->event) {
439 spin_lock_irq(&crtc->dev->event_lock);
440 drm_crtc_send_vblank_event(crtc, crtc->state->event);
441 crtc->state->event = NULL;
442 spin_unlock_irq(&crtc->dev->event_lock);
443 }
444}
445
446static const struct drm_simple_display_pipe_funcs cirrus_pipe_funcs = {
447 .mode_valid = cirrus_pipe_mode_valid,
448 .check = cirrus_pipe_check,
449 .enable = cirrus_pipe_enable,
450 .update = cirrus_pipe_update,
451};
452
453static const uint32_t cirrus_formats[] = {
454 DRM_FORMAT_RGB565,
455 DRM_FORMAT_RGB888,
456 DRM_FORMAT_XRGB8888,
457};
458
459static const uint64_t cirrus_modifiers[] = {
460 DRM_FORMAT_MOD_LINEAR,
461 DRM_FORMAT_MOD_INVALID
462};
463
464static int cirrus_pipe_init(struct cirrus_device *cirrus)
465{
466 return drm_simple_display_pipe_init(&cirrus->dev,
467 &cirrus->pipe,
468 &cirrus_pipe_funcs,
469 cirrus_formats,
470 ARRAY_SIZE(cirrus_formats),
471 cirrus_modifiers,
472 &cirrus->conn);
473}
474
475/* ------------------------------------------------------------------ */
476/* cirrus framebuffers & mode config */
477
478static struct drm_framebuffer*
479cirrus_fb_create(struct drm_device *dev, struct drm_file *file_priv,
480 const struct drm_mode_fb_cmd2 *mode_cmd)
481{
482 if (mode_cmd->pixel_format != DRM_FORMAT_RGB565 &&
483 mode_cmd->pixel_format != DRM_FORMAT_RGB888 &&
484 mode_cmd->pixel_format != DRM_FORMAT_XRGB8888)
485 return ERR_PTR(-EINVAL);
486 if (cirrus_check_size(mode_cmd->width, mode_cmd->height, NULL) < 0)
487 return ERR_PTR(-EINVAL);
488 return drm_gem_fb_create_with_dirty(dev, file_priv, mode_cmd);
489}
490
491static const struct drm_mode_config_funcs cirrus_mode_config_funcs = {
492 .fb_create = cirrus_fb_create,
493 .atomic_check = drm_atomic_helper_check,
494 .atomic_commit = drm_atomic_helper_commit,
495};
496
497static void cirrus_mode_config_init(struct cirrus_device *cirrus)
498{
499 struct drm_device *dev = &cirrus->dev;
500
501 drm_mode_config_init(dev);
502 dev->mode_config.min_width = 0;
503 dev->mode_config.min_height = 0;
504 dev->mode_config.max_width = CIRRUS_MAX_PITCH / 2;
505 dev->mode_config.max_height = 1024;
506 dev->mode_config.preferred_depth = 16;
507 dev->mode_config.prefer_shadow = 0;
508 dev->mode_config.funcs = &cirrus_mode_config_funcs;
509}
510
511/* ------------------------------------------------------------------ */
512
513DEFINE_DRM_GEM_SHMEM_FOPS(cirrus_fops);
514
515static struct drm_driver cirrus_driver = {
516 .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC | DRIVER_PRIME,
517
518 .name = DRIVER_NAME,
519 .desc = DRIVER_DESC,
520 .date = DRIVER_DATE,
521 .major = DRIVER_MAJOR,
522 .minor = DRIVER_MINOR,
523
524 .fops = &cirrus_fops,
525 DRM_GEM_SHMEM_DRIVER_OPS,
526};
527
528static int cirrus_pci_probe(struct pci_dev *pdev,
529 const struct pci_device_id *ent)
530{
531 struct drm_device *dev;
532 struct cirrus_device *cirrus;
533 int ret;
534
535 ret = drm_fb_helper_remove_conflicting_pci_framebuffers(pdev, 0, "cirrusdrmfb");
536 if (ret)
537 return ret;
538
539 ret = pci_enable_device(pdev);
540 if (ret)
541 return ret;
542
543 ret = pci_request_regions(pdev, DRIVER_NAME);
544 if (ret)
545 return ret;
546
547 ret = -ENOMEM;
548 cirrus = kzalloc(sizeof(*cirrus), GFP_KERNEL);
549 if (cirrus == NULL)
550 goto err_pci_release;
551
552 dev = &cirrus->dev;
553 ret = drm_dev_init(dev, &cirrus_driver, &pdev->dev);
554 if (ret)
555 goto err_free_cirrus;
556 dev->dev_private = cirrus;
557
558 ret = -ENOMEM;
559 cirrus->vram = ioremap(pci_resource_start(pdev, 0),
560 pci_resource_len(pdev, 0));
561 if (cirrus->vram == NULL)
562 goto err_dev_put;
563
564 cirrus->mmio = ioremap(pci_resource_start(pdev, 1),
565 pci_resource_len(pdev, 1));
566 if (cirrus->mmio == NULL)
567 goto err_unmap_vram;
568
569 cirrus_mode_config_init(cirrus);
570
571 ret = cirrus_conn_init(cirrus);
572 if (ret < 0)
573 goto err_cleanup;
574
575 ret = cirrus_pipe_init(cirrus);
576 if (ret < 0)
577 goto err_cleanup;
578
579 drm_mode_config_reset(dev);
580
581 dev->pdev = pdev;
582 pci_set_drvdata(pdev, dev);
583 ret = drm_dev_register(dev, 0);
584 if (ret)
585 goto err_cleanup;
586
587 drm_fbdev_generic_setup(dev, dev->mode_config.preferred_depth);
588 return 0;
589
590err_cleanup:
591 drm_mode_config_cleanup(dev);
592 iounmap(cirrus->mmio);
593err_unmap_vram:
594 iounmap(cirrus->vram);
595err_dev_put:
596 drm_dev_put(dev);
597err_free_cirrus:
598 kfree(cirrus);
599err_pci_release:
600 pci_release_regions(pdev);
601 return ret;
602}
603
604static void cirrus_pci_remove(struct pci_dev *pdev)
605{
606 struct drm_device *dev = pci_get_drvdata(pdev);
607 struct cirrus_device *cirrus = dev->dev_private;
608
609 drm_dev_unregister(dev);
610 drm_mode_config_cleanup(dev);
611 iounmap(cirrus->mmio);
612 iounmap(cirrus->vram);
613 drm_dev_put(dev);
614 kfree(cirrus);
615 pci_release_regions(pdev);
616}
617
618static const struct pci_device_id pciidlist[] = {
619 {
620 .vendor = PCI_VENDOR_ID_CIRRUS,
621 .device = PCI_DEVICE_ID_CIRRUS_5446,
622 /* only bind to the cirrus chip in qemu */
623 .subvendor = PCI_SUBVENDOR_ID_REDHAT_QUMRANET,
624 .subdevice = PCI_SUBDEVICE_ID_QEMU,
625 }, {
626 .vendor = PCI_VENDOR_ID_CIRRUS,
627 .device = PCI_DEVICE_ID_CIRRUS_5446,
628 .subvendor = PCI_VENDOR_ID_XEN,
629 .subdevice = 0x0001,
630 },
631 { /* end if list */ }
632};
633
634static struct pci_driver cirrus_pci_driver = {
635 .name = DRIVER_NAME,
636 .id_table = pciidlist,
637 .probe = cirrus_pci_probe,
638 .remove = cirrus_pci_remove,
639};
640
641static int __init cirrus_init(void)
642{
643 if (vgacon_text_force())
644 return -EINVAL;
645 return pci_register_driver(&cirrus_pci_driver);
646}
647
648static void __exit cirrus_exit(void)
649{
650 pci_unregister_driver(&cirrus_pci_driver);
651}
652
653module_init(cirrus_init);
654module_exit(cirrus_exit);
655
656MODULE_DEVICE_TABLE(pci, pciidlist);
657MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/cirrus/cirrus_drv.c b/drivers/gpu/drm/cirrus/cirrus_drv.c
deleted file mode 100644
index 8ec880f3a322..000000000000
--- a/drivers/gpu/drm/cirrus/cirrus_drv.c
+++ /dev/null
@@ -1,161 +0,0 @@
1/*
2 * Copyright 2012 Red Hat <mjg@redhat.com>
3 *
4 * This file is subject to the terms and conditions of the GNU General
5 * Public License version 2. See the file COPYING in the main
6 * directory of this archive for more details.
7 *
8 * Authors: Matthew Garrett
9 * Dave Airlie
10 */
11#include <linux/module.h>
12#include <linux/console.h>
13#include <drm/drmP.h>
14#include <drm/drm_crtc_helper.h>
15#include <drm/drm_probe_helper.h>
16
17#include "cirrus_drv.h"
18
19int cirrus_modeset = -1;
20int cirrus_bpp = 16;
21
22MODULE_PARM_DESC(modeset, "Disable/Enable modesetting");
23module_param_named(modeset, cirrus_modeset, int, 0400);
24MODULE_PARM_DESC(bpp, "Max bits-per-pixel (default:16)");
25module_param_named(bpp, cirrus_bpp, int, 0400);
26
27/*
28 * This is the generic driver code. This binds the driver to the drm core,
29 * which then performs further device association and calls our graphics init
30 * functions
31 */
32
33static struct drm_driver driver;
34
35/* only bind to the cirrus chip in qemu */
36static const struct pci_device_id pciidlist[] = {
37 { PCI_VENDOR_ID_CIRRUS, PCI_DEVICE_ID_CIRRUS_5446,
38 PCI_SUBVENDOR_ID_REDHAT_QUMRANET, PCI_SUBDEVICE_ID_QEMU,
39 0, 0, 0 },
40 { PCI_VENDOR_ID_CIRRUS, PCI_DEVICE_ID_CIRRUS_5446, PCI_VENDOR_ID_XEN,
41 0x0001, 0, 0, 0 },
42 {0,}
43};
44
45
46static int cirrus_pci_probe(struct pci_dev *pdev,
47 const struct pci_device_id *ent)
48{
49 int ret;
50
51 ret = drm_fb_helper_remove_conflicting_pci_framebuffers(pdev, 0, "cirrusdrmfb");
52 if (ret)
53 return ret;
54
55 return drm_get_pci_dev(pdev, ent, &driver);
56}
57
58static void cirrus_pci_remove(struct pci_dev *pdev)
59{
60 struct drm_device *dev = pci_get_drvdata(pdev);
61
62 drm_put_dev(dev);
63}
64
65#ifdef CONFIG_PM_SLEEP
66static int cirrus_pm_suspend(struct device *dev)
67{
68 struct pci_dev *pdev = to_pci_dev(dev);
69 struct drm_device *drm_dev = pci_get_drvdata(pdev);
70 struct cirrus_device *cdev = drm_dev->dev_private;
71
72 drm_kms_helper_poll_disable(drm_dev);
73
74 if (cdev->mode_info.gfbdev) {
75 console_lock();
76 drm_fb_helper_set_suspend(&cdev->mode_info.gfbdev->helper, 1);
77 console_unlock();
78 }
79
80 return 0;
81}
82
83static int cirrus_pm_resume(struct device *dev)
84{
85 struct pci_dev *pdev = to_pci_dev(dev);
86 struct drm_device *drm_dev = pci_get_drvdata(pdev);
87 struct cirrus_device *cdev = drm_dev->dev_private;
88
89 drm_helper_resume_force_mode(drm_dev);
90
91 if (cdev->mode_info.gfbdev) {
92 console_lock();
93 drm_fb_helper_set_suspend(&cdev->mode_info.gfbdev->helper, 0);
94 console_unlock();
95 }
96
97 drm_kms_helper_poll_enable(drm_dev);
98 return 0;
99}
100#endif
101
102static const struct file_operations cirrus_driver_fops = {
103 .owner = THIS_MODULE,
104 .open = drm_open,
105 .release = drm_release,
106 .unlocked_ioctl = drm_ioctl,
107 .mmap = cirrus_mmap,
108 .poll = drm_poll,
109 .compat_ioctl = drm_compat_ioctl,
110};
111static struct drm_driver driver = {
112 .driver_features = DRIVER_MODESET | DRIVER_GEM,
113 .load = cirrus_driver_load,
114 .unload = cirrus_driver_unload,
115 .fops = &cirrus_driver_fops,
116 .name = DRIVER_NAME,
117 .desc = DRIVER_DESC,
118 .date = DRIVER_DATE,
119 .major = DRIVER_MAJOR,
120 .minor = DRIVER_MINOR,
121 .patchlevel = DRIVER_PATCHLEVEL,
122 .gem_free_object_unlocked = cirrus_gem_free_object,
123 .dumb_create = cirrus_dumb_create,
124 .dumb_map_offset = cirrus_dumb_mmap_offset,
125};
126
127static const struct dev_pm_ops cirrus_pm_ops = {
128 SET_SYSTEM_SLEEP_PM_OPS(cirrus_pm_suspend,
129 cirrus_pm_resume)
130};
131
132static struct pci_driver cirrus_pci_driver = {
133 .name = DRIVER_NAME,
134 .id_table = pciidlist,
135 .probe = cirrus_pci_probe,
136 .remove = cirrus_pci_remove,
137 .driver.pm = &cirrus_pm_ops,
138};
139
140static int __init cirrus_init(void)
141{
142 if (vgacon_text_force() && cirrus_modeset == -1)
143 return -EINVAL;
144
145 if (cirrus_modeset == 0)
146 return -EINVAL;
147 return pci_register_driver(&cirrus_pci_driver);
148}
149
150static void __exit cirrus_exit(void)
151{
152 pci_unregister_driver(&cirrus_pci_driver);
153}
154
155module_init(cirrus_init);
156module_exit(cirrus_exit);
157
158MODULE_DEVICE_TABLE(pci, pciidlist);
159MODULE_AUTHOR(DRIVER_AUTHOR);
160MODULE_DESCRIPTION(DRIVER_DESC);
161MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/cirrus/cirrus_fbdev.c b/drivers/gpu/drm/cirrus/cirrus_fbdev.c
deleted file mode 100644
index 2e6128069fc3..000000000000
--- a/drivers/gpu/drm/cirrus/cirrus_fbdev.c
+++ /dev/null
@@ -1,309 +0,0 @@
1/*
2 * Copyright 2012 Red Hat
3 *
4 * This file is subject to the terms and conditions of the GNU General
5 * Public License version 2. See the file COPYING in the main
6 * directory of this archive for more details.
7 *
8 * Authors: Matthew Garrett
9 * Dave Airlie
10 */
11#include <linux/module.h>
12#include <drm/drmP.h>
13#include <drm/drm_util.h>
14#include <drm/drm_fb_helper.h>
15#include <drm/drm_crtc_helper.h>
16
17#include "cirrus_drv.h"
18
19static void cirrus_dirty_update(struct cirrus_fbdev *afbdev,
20 int x, int y, int width, int height)
21{
22 int i;
23 struct drm_gem_object *obj;
24 struct cirrus_bo *bo;
25 int src_offset, dst_offset;
26 int bpp = afbdev->gfb->format->cpp[0];
27 int ret = -EBUSY;
28 bool unmap = false;
29 bool store_for_later = false;
30 int x2, y2;
31 unsigned long flags;
32
33 obj = afbdev->gfb->obj[0];
34 bo = gem_to_cirrus_bo(obj);
35
36 /*
37 * try and reserve the BO, if we fail with busy
38 * then the BO is being moved and we should
39 * store up the damage until later.
40 */
41 if (drm_can_sleep())
42 ret = cirrus_bo_reserve(bo, true);
43 if (ret) {
44 if (ret != -EBUSY)
45 return;
46 store_for_later = true;
47 }
48
49 x2 = x + width - 1;
50 y2 = y + height - 1;
51 spin_lock_irqsave(&afbdev->dirty_lock, flags);
52
53 if (afbdev->y1 < y)
54 y = afbdev->y1;
55 if (afbdev->y2 > y2)
56 y2 = afbdev->y2;
57 if (afbdev->x1 < x)
58 x = afbdev->x1;
59 if (afbdev->x2 > x2)
60 x2 = afbdev->x2;
61
62 if (store_for_later) {
63 afbdev->x1 = x;
64 afbdev->x2 = x2;
65 afbdev->y1 = y;
66 afbdev->y2 = y2;
67 spin_unlock_irqrestore(&afbdev->dirty_lock, flags);
68 return;
69 }
70
71 afbdev->x1 = afbdev->y1 = INT_MAX;
72 afbdev->x2 = afbdev->y2 = 0;
73 spin_unlock_irqrestore(&afbdev->dirty_lock, flags);
74
75 if (!bo->kmap.virtual) {
76 ret = ttm_bo_kmap(&bo->bo, 0, bo->bo.num_pages, &bo->kmap);
77 if (ret) {
78 DRM_ERROR("failed to kmap fb updates\n");
79 cirrus_bo_unreserve(bo);
80 return;
81 }
82 unmap = true;
83 }
84 for (i = y; i < y + height; i++) {
85 /* assume equal stride for now */
86 src_offset = dst_offset = i * afbdev->gfb->pitches[0] + (x * bpp);
87 memcpy_toio(bo->kmap.virtual + src_offset, afbdev->sysram + src_offset, width * bpp);
88
89 }
90 if (unmap)
91 ttm_bo_kunmap(&bo->kmap);
92
93 cirrus_bo_unreserve(bo);
94}
95
96static void cirrus_fillrect(struct fb_info *info,
97 const struct fb_fillrect *rect)
98{
99 struct cirrus_fbdev *afbdev = info->par;
100 drm_fb_helper_sys_fillrect(info, rect);
101 cirrus_dirty_update(afbdev, rect->dx, rect->dy, rect->width,
102 rect->height);
103}
104
105static void cirrus_copyarea(struct fb_info *info,
106 const struct fb_copyarea *area)
107{
108 struct cirrus_fbdev *afbdev = info->par;
109 drm_fb_helper_sys_copyarea(info, area);
110 cirrus_dirty_update(afbdev, area->dx, area->dy, area->width,
111 area->height);
112}
113
114static void cirrus_imageblit(struct fb_info *info,
115 const struct fb_image *image)
116{
117 struct cirrus_fbdev *afbdev = info->par;
118 drm_fb_helper_sys_imageblit(info, image);
119 cirrus_dirty_update(afbdev, image->dx, image->dy, image->width,
120 image->height);
121}
122
123
124static struct fb_ops cirrusfb_ops = {
125 .owner = THIS_MODULE,
126 .fb_check_var = drm_fb_helper_check_var,
127 .fb_set_par = drm_fb_helper_set_par,
128 .fb_fillrect = cirrus_fillrect,
129 .fb_copyarea = cirrus_copyarea,
130 .fb_imageblit = cirrus_imageblit,
131 .fb_pan_display = drm_fb_helper_pan_display,
132 .fb_blank = drm_fb_helper_blank,
133 .fb_setcmap = drm_fb_helper_setcmap,
134};
135
136static int cirrusfb_create_object(struct cirrus_fbdev *afbdev,
137 const struct drm_mode_fb_cmd2 *mode_cmd,
138 struct drm_gem_object **gobj_p)
139{
140 struct drm_device *dev = afbdev->helper.dev;
141 struct cirrus_device *cdev = dev->dev_private;
142 u32 bpp;
143 u32 size;
144 struct drm_gem_object *gobj;
145 int ret = 0;
146
147 bpp = drm_format_plane_cpp(mode_cmd->pixel_format, 0) * 8;
148
149 if (!cirrus_check_framebuffer(cdev, mode_cmd->width, mode_cmd->height,
150 bpp, mode_cmd->pitches[0]))
151 return -EINVAL;
152
153 size = mode_cmd->pitches[0] * mode_cmd->height;
154 ret = cirrus_gem_create(dev, size, true, &gobj);
155 if (ret)
156 return ret;
157
158 *gobj_p = gobj;
159 return ret;
160}
161
162static int cirrusfb_create(struct drm_fb_helper *helper,
163 struct drm_fb_helper_surface_size *sizes)
164{
165 struct cirrus_fbdev *gfbdev =
166 container_of(helper, struct cirrus_fbdev, helper);
167 struct cirrus_device *cdev = gfbdev->helper.dev->dev_private;
168 struct fb_info *info;
169 struct drm_framebuffer *fb;
170 struct drm_mode_fb_cmd2 mode_cmd;
171 void *sysram;
172 struct drm_gem_object *gobj = NULL;
173 int size, ret;
174
175 mode_cmd.width = sizes->surface_width;
176 mode_cmd.height = sizes->surface_height;
177 mode_cmd.pitches[0] = mode_cmd.width * ((sizes->surface_bpp + 7) / 8);
178 mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp,
179 sizes->surface_depth);
180 size = mode_cmd.pitches[0] * mode_cmd.height;
181
182 ret = cirrusfb_create_object(gfbdev, &mode_cmd, &gobj);
183 if (ret) {
184 DRM_ERROR("failed to create fbcon backing object %d\n", ret);
185 return ret;
186 }
187
188 sysram = vmalloc(size);
189 if (!sysram)
190 return -ENOMEM;
191
192 info = drm_fb_helper_alloc_fbi(helper);
193 if (IS_ERR(info)) {
194 ret = PTR_ERR(info);
195 goto err_vfree;
196 }
197
198 fb = kzalloc(sizeof(*fb), GFP_KERNEL);
199 if (!fb) {
200 ret = -ENOMEM;
201 goto err_drm_gem_object_put_unlocked;
202 }
203
204 ret = cirrus_framebuffer_init(cdev->dev, fb, &mode_cmd, gobj);
205 if (ret)
206 goto err_kfree;
207
208 gfbdev->sysram = sysram;
209 gfbdev->size = size;
210 gfbdev->gfb = fb;
211
212 /* setup helper */
213 gfbdev->helper.fb = fb;
214
215 info->fbops = &cirrusfb_ops;
216
217 drm_fb_helper_fill_info(info, &gfbdev->helper, sizes);
218
219 /* setup aperture base/size for vesafb takeover */
220 info->apertures->ranges[0].base = cdev->dev->mode_config.fb_base;
221 info->apertures->ranges[0].size = cdev->mc.vram_size;
222
223 info->fix.smem_start = cdev->dev->mode_config.fb_base;
224 info->fix.smem_len = cdev->mc.vram_size;
225
226 info->screen_base = sysram;
227 info->screen_size = size;
228
229 info->fix.mmio_start = 0;
230 info->fix.mmio_len = 0;
231
232 DRM_INFO("fb mappable at 0x%lX\n", info->fix.smem_start);
233 DRM_INFO("vram aper at 0x%lX\n", (unsigned long)info->fix.smem_start);
234 DRM_INFO("size %lu\n", (unsigned long)info->fix.smem_len);
235 DRM_INFO("fb depth is %d\n", fb->format->depth);
236 DRM_INFO(" pitch is %d\n", fb->pitches[0]);
237
238 return 0;
239
240err_kfree:
241 kfree(fb);
242err_drm_gem_object_put_unlocked:
243 drm_gem_object_put_unlocked(gobj);
244err_vfree:
245 vfree(sysram);
246 return ret;
247}
248
249static int cirrus_fbdev_destroy(struct drm_device *dev,
250 struct cirrus_fbdev *gfbdev)
251{
252 struct drm_framebuffer *gfb = gfbdev->gfb;
253
254 drm_helper_force_disable_all(dev);
255
256 drm_fb_helper_unregister_fbi(&gfbdev->helper);
257
258 vfree(gfbdev->sysram);
259 drm_fb_helper_fini(&gfbdev->helper);
260 if (gfb)
261 drm_framebuffer_put(gfb);
262
263 return 0;
264}
265
266static const struct drm_fb_helper_funcs cirrus_fb_helper_funcs = {
267 .fb_probe = cirrusfb_create,
268};
269
270int cirrus_fbdev_init(struct cirrus_device *cdev)
271{
272 struct cirrus_fbdev *gfbdev;
273 int ret;
274
275 /*bpp_sel = 8;*/
276 gfbdev = kzalloc(sizeof(struct cirrus_fbdev), GFP_KERNEL);
277 if (!gfbdev)
278 return -ENOMEM;
279
280 cdev->mode_info.gfbdev = gfbdev;
281 spin_lock_init(&gfbdev->dirty_lock);
282
283 drm_fb_helper_prepare(cdev->dev, &gfbdev->helper,
284 &cirrus_fb_helper_funcs);
285
286 ret = drm_fb_helper_init(cdev->dev, &gfbdev->helper,
287 CIRRUSFB_CONN_LIMIT);
288 if (ret)
289 return ret;
290
291 ret = drm_fb_helper_single_add_all_connectors(&gfbdev->helper);
292 if (ret)
293 return ret;
294
295 /* disable all the possible outputs/crtcs before entering KMS mode */
296 drm_helper_disable_unused_functions(cdev->dev);
297
298 return drm_fb_helper_initial_config(&gfbdev->helper, cirrus_bpp);
299}
300
301void cirrus_fbdev_fini(struct cirrus_device *cdev)
302{
303 if (!cdev->mode_info.gfbdev)
304 return;
305
306 cirrus_fbdev_destroy(cdev->dev, cdev->mode_info.gfbdev);
307 kfree(cdev->mode_info.gfbdev);
308 cdev->mode_info.gfbdev = NULL;
309}
diff --git a/drivers/gpu/drm/cirrus/cirrus_main.c b/drivers/gpu/drm/cirrus/cirrus_main.c
deleted file mode 100644
index 57f8fe6d020b..000000000000
--- a/drivers/gpu/drm/cirrus/cirrus_main.c
+++ /dev/null
@@ -1,328 +0,0 @@
1/*
2 * Copyright 2012 Red Hat
3 *
4 * This file is subject to the terms and conditions of the GNU General
5 * Public License version 2. See the file COPYING in the main
6 * directory of this archive for more details.
7 *
8 * Authors: Matthew Garrett
9 * Dave Airlie
10 */
11#include <drm/drmP.h>
12#include <drm/drm_crtc_helper.h>
13#include <drm/drm_gem_framebuffer_helper.h>
14
15#include "cirrus_drv.h"
16
17static const struct drm_framebuffer_funcs cirrus_fb_funcs = {
18 .create_handle = drm_gem_fb_create_handle,
19 .destroy = drm_gem_fb_destroy,
20};
21
22int cirrus_framebuffer_init(struct drm_device *dev,
23 struct drm_framebuffer *gfb,
24 const struct drm_mode_fb_cmd2 *mode_cmd,
25 struct drm_gem_object *obj)
26{
27 int ret;
28
29 drm_helper_mode_fill_fb_struct(dev, gfb, mode_cmd);
30 gfb->obj[0] = obj;
31 ret = drm_framebuffer_init(dev, gfb, &cirrus_fb_funcs);
32 if (ret) {
33 DRM_ERROR("drm_framebuffer_init failed: %d\n", ret);
34 return ret;
35 }
36 return 0;
37}
38
39static struct drm_framebuffer *
40cirrus_user_framebuffer_create(struct drm_device *dev,
41 struct drm_file *filp,
42 const struct drm_mode_fb_cmd2 *mode_cmd)
43{
44 struct cirrus_device *cdev = dev->dev_private;
45 struct drm_gem_object *obj;
46 struct drm_framebuffer *fb;
47 u32 bpp;
48 int ret;
49
50 bpp = drm_format_plane_cpp(mode_cmd->pixel_format, 0) * 8;
51
52 if (!cirrus_check_framebuffer(cdev, mode_cmd->width, mode_cmd->height,
53 bpp, mode_cmd->pitches[0]))
54 return ERR_PTR(-EINVAL);
55
56 obj = drm_gem_object_lookup(filp, mode_cmd->handles[0]);
57 if (obj == NULL)
58 return ERR_PTR(-ENOENT);
59
60 fb = kzalloc(sizeof(*fb), GFP_KERNEL);
61 if (!fb) {
62 drm_gem_object_put_unlocked(obj);
63 return ERR_PTR(-ENOMEM);
64 }
65
66 ret = cirrus_framebuffer_init(dev, fb, mode_cmd, obj);
67 if (ret) {
68 drm_gem_object_put_unlocked(obj);
69 kfree(fb);
70 return ERR_PTR(ret);
71 }
72 return fb;
73}
74
75static const struct drm_mode_config_funcs cirrus_mode_funcs = {
76 .fb_create = cirrus_user_framebuffer_create,
77};
78
79/* Unmap the framebuffer from the core and release the memory */
80static void cirrus_vram_fini(struct cirrus_device *cdev)
81{
82 iounmap(cdev->rmmio);
83 cdev->rmmio = NULL;
84 if (cdev->mc.vram_base)
85 release_mem_region(cdev->mc.vram_base, cdev->mc.vram_size);
86}
87
88/* Map the framebuffer from the card and configure the core */
89static int cirrus_vram_init(struct cirrus_device *cdev)
90{
91 /* BAR 0 is VRAM */
92 cdev->mc.vram_base = pci_resource_start(cdev->dev->pdev, 0);
93 cdev->mc.vram_size = pci_resource_len(cdev->dev->pdev, 0);
94
95 if (!request_mem_region(cdev->mc.vram_base, cdev->mc.vram_size,
96 "cirrusdrmfb_vram")) {
97 DRM_ERROR("can't reserve VRAM\n");
98 return -ENXIO;
99 }
100
101 return 0;
102}
103
104/*
105 * Our emulated hardware has two sets of memory. One is video RAM and can
106 * simply be used as a linear framebuffer - the other provides mmio access
107 * to the display registers. The latter can also be accessed via IO port
108 * access, but we map the range and use mmio to program them instead
109 */
110
111int cirrus_device_init(struct cirrus_device *cdev,
112 struct drm_device *ddev,
113 struct pci_dev *pdev, uint32_t flags)
114{
115 int ret;
116
117 cdev->dev = ddev;
118 cdev->flags = flags;
119
120 /* Hardcode the number of CRTCs to 1 */
121 cdev->num_crtc = 1;
122
123 /* BAR 0 is the framebuffer, BAR 1 contains registers */
124 cdev->rmmio_base = pci_resource_start(cdev->dev->pdev, 1);
125 cdev->rmmio_size = pci_resource_len(cdev->dev->pdev, 1);
126
127 if (!request_mem_region(cdev->rmmio_base, cdev->rmmio_size,
128 "cirrusdrmfb_mmio")) {
129 DRM_ERROR("can't reserve mmio registers\n");
130 return -ENOMEM;
131 }
132
133 cdev->rmmio = ioremap(cdev->rmmio_base, cdev->rmmio_size);
134
135 if (cdev->rmmio == NULL)
136 return -ENOMEM;
137
138 ret = cirrus_vram_init(cdev);
139 if (ret) {
140 release_mem_region(cdev->rmmio_base, cdev->rmmio_size);
141 return ret;
142 }
143
144 return 0;
145}
146
147void cirrus_device_fini(struct cirrus_device *cdev)
148{
149 release_mem_region(cdev->rmmio_base, cdev->rmmio_size);
150 cirrus_vram_fini(cdev);
151}
152
153/*
154 * Functions here will be called by the core once it's bound the driver to
155 * a PCI device
156 */
157
158int cirrus_driver_load(struct drm_device *dev, unsigned long flags)
159{
160 struct cirrus_device *cdev;
161 int r;
162
163 cdev = kzalloc(sizeof(struct cirrus_device), GFP_KERNEL);
164 if (cdev == NULL)
165 return -ENOMEM;
166 dev->dev_private = (void *)cdev;
167
168 r = cirrus_device_init(cdev, dev, dev->pdev, flags);
169 if (r) {
170 dev_err(&dev->pdev->dev, "Fatal error during GPU init: %d\n", r);
171 goto out;
172 }
173
174 r = cirrus_mm_init(cdev);
175 if (r) {
176 dev_err(&dev->pdev->dev, "fatal err on mm init\n");
177 goto out;
178 }
179
180 /*
181 * cirrus_modeset_init() is initializing/registering the emulated fbdev
182 * and DRM internals can access/test some of the fields in
183 * mode_config->funcs as part of the fbdev registration process.
184 * Make sure dev->mode_config.funcs is properly set to avoid
185 * dereferencing a NULL pointer.
186 * FIXME: mode_config.funcs assignment should probably be done in
187 * cirrus_modeset_init() (that's a common pattern seen in other DRM
188 * drivers).
189 */
190 dev->mode_config.funcs = &cirrus_mode_funcs;
191 r = cirrus_modeset_init(cdev);
192 if (r) {
193 dev_err(&dev->pdev->dev, "Fatal error during modeset init: %d\n", r);
194 goto out;
195 }
196
197 return 0;
198out:
199 cirrus_driver_unload(dev);
200 return r;
201}
202
203void cirrus_driver_unload(struct drm_device *dev)
204{
205 struct cirrus_device *cdev = dev->dev_private;
206
207 if (cdev == NULL)
208 return;
209 cirrus_modeset_fini(cdev);
210 cirrus_mm_fini(cdev);
211 cirrus_device_fini(cdev);
212 kfree(cdev);
213 dev->dev_private = NULL;
214}
215
216int cirrus_gem_create(struct drm_device *dev,
217 u32 size, bool iskernel,
218 struct drm_gem_object **obj)
219{
220 struct cirrus_bo *cirrusbo;
221 int ret;
222
223 *obj = NULL;
224
225 size = roundup(size, PAGE_SIZE);
226 if (size == 0)
227 return -EINVAL;
228
229 ret = cirrus_bo_create(dev, size, 0, 0, &cirrusbo);
230 if (ret) {
231 if (ret != -ERESTARTSYS)
232 DRM_ERROR("failed to allocate GEM object\n");
233 return ret;
234 }
235 *obj = &cirrusbo->gem;
236 return 0;
237}
238
239int cirrus_dumb_create(struct drm_file *file,
240 struct drm_device *dev,
241 struct drm_mode_create_dumb *args)
242{
243 int ret;
244 struct drm_gem_object *gobj;
245 u32 handle;
246
247 args->pitch = args->width * ((args->bpp + 7) / 8);
248 args->size = args->pitch * args->height;
249
250 ret = cirrus_gem_create(dev, args->size, false,
251 &gobj);
252 if (ret)
253 return ret;
254
255 ret = drm_gem_handle_create(file, gobj, &handle);
256 drm_gem_object_put_unlocked(gobj);
257 if (ret)
258 return ret;
259
260 args->handle = handle;
261 return 0;
262}
263
264static void cirrus_bo_unref(struct cirrus_bo **bo)
265{
266 struct ttm_buffer_object *tbo;
267
268 if ((*bo) == NULL)
269 return;
270
271 tbo = &((*bo)->bo);
272 ttm_bo_put(tbo);
273 *bo = NULL;
274}
275
276void cirrus_gem_free_object(struct drm_gem_object *obj)
277{
278 struct cirrus_bo *cirrus_bo = gem_to_cirrus_bo(obj);
279
280 cirrus_bo_unref(&cirrus_bo);
281}
282
283
284static inline u64 cirrus_bo_mmap_offset(struct cirrus_bo *bo)
285{
286 return drm_vma_node_offset_addr(&bo->bo.vma_node);
287}
288
289int
290cirrus_dumb_mmap_offset(struct drm_file *file,
291 struct drm_device *dev,
292 uint32_t handle,
293 uint64_t *offset)
294{
295 struct drm_gem_object *obj;
296 struct cirrus_bo *bo;
297
298 obj = drm_gem_object_lookup(file, handle);
299 if (obj == NULL)
300 return -ENOENT;
301
302 bo = gem_to_cirrus_bo(obj);
303 *offset = cirrus_bo_mmap_offset(bo);
304
305 drm_gem_object_put_unlocked(obj);
306
307 return 0;
308}
309
310bool cirrus_check_framebuffer(struct cirrus_device *cdev, int width, int height,
311 int bpp, int pitch)
312{
313 const int max_pitch = 0x1FF << 3; /* (4096 - 1) & ~111b bytes */
314 const int max_size = cdev->mc.vram_size;
315
316 if (bpp > cirrus_bpp)
317 return false;
318 if (bpp > 32)
319 return false;
320
321 if (pitch > max_pitch)
322 return false;
323
324 if (pitch * height > max_size)
325 return false;
326
327 return true;
328}
diff --git a/drivers/gpu/drm/cirrus/cirrus_mode.c b/drivers/gpu/drm/cirrus/cirrus_mode.c
deleted file mode 100644
index b109cd71426f..000000000000
--- a/drivers/gpu/drm/cirrus/cirrus_mode.c
+++ /dev/null
@@ -1,617 +0,0 @@
1
2/*
3 * Copyright 2012 Red Hat
4 *
5 * This file is subject to the terms and conditions of the GNU General
6 * Public License version 2. See the file COPYING in the main
7 * directory of this archive for more details.
8 *
9 * Authors: Matthew Garrett
10 * Dave Airlie
11 *
12 * Portions of this code derived from cirrusfb.c:
13 * drivers/video/cirrusfb.c - driver for Cirrus Logic chipsets
14 *
15 * Copyright 1999-2001 Jeff Garzik <jgarzik@pobox.com>
16 */
17#include <drm/drmP.h>
18#include <drm/drm_crtc_helper.h>
19#include <drm/drm_plane_helper.h>
20#include <drm/drm_probe_helper.h>
21
22#include <video/cirrus.h>
23
24#include "cirrus_drv.h"
25
26#define CIRRUS_LUT_SIZE 256
27
28#define PALETTE_INDEX 0x8
29#define PALETTE_DATA 0x9
30
31/*
32 * This file contains setup code for the CRTC.
33 */
34
35/*
36 * The DRM core requires DPMS functions, but they make little sense in our
37 * case and so are just stubs
38 */
39
40static void cirrus_crtc_dpms(struct drm_crtc *crtc, int mode)
41{
42 struct drm_device *dev = crtc->dev;
43 struct cirrus_device *cdev = dev->dev_private;
44 u8 sr01, gr0e;
45
46 switch (mode) {
47 case DRM_MODE_DPMS_ON:
48 sr01 = 0x00;
49 gr0e = 0x00;
50 break;
51 case DRM_MODE_DPMS_STANDBY:
52 sr01 = 0x20;
53 gr0e = 0x02;
54 break;
55 case DRM_MODE_DPMS_SUSPEND:
56 sr01 = 0x20;
57 gr0e = 0x04;
58 break;
59 case DRM_MODE_DPMS_OFF:
60 sr01 = 0x20;
61 gr0e = 0x06;
62 break;
63 default:
64 return;
65 }
66
67 WREG8(SEQ_INDEX, 0x1);
68 sr01 |= RREG8(SEQ_DATA) & ~0x20;
69 WREG_SEQ(0x1, sr01);
70
71 WREG8(GFX_INDEX, 0xe);
72 gr0e |= RREG8(GFX_DATA) & ~0x06;
73 WREG_GFX(0xe, gr0e);
74}
75
76static void cirrus_set_start_address(struct drm_crtc *crtc, unsigned offset)
77{
78 struct cirrus_device *cdev = crtc->dev->dev_private;
79 u32 addr;
80 u8 tmp;
81
82 addr = offset >> 2;
83 WREG_CRT(0x0c, (u8)((addr >> 8) & 0xff));
84 WREG_CRT(0x0d, (u8)(addr & 0xff));
85
86 WREG8(CRT_INDEX, 0x1b);
87 tmp = RREG8(CRT_DATA);
88 tmp &= 0xf2;
89 tmp |= (addr >> 16) & 0x01;
90 tmp |= (addr >> 15) & 0x0c;
91 WREG_CRT(0x1b, tmp);
92 WREG8(CRT_INDEX, 0x1d);
93 tmp = RREG8(CRT_DATA);
94 tmp &= 0x7f;
95 tmp |= (addr >> 12) & 0x80;
96 WREG_CRT(0x1d, tmp);
97}
98
99/* cirrus is different - we will force move buffers out of VRAM */
100static int cirrus_crtc_do_set_base(struct drm_crtc *crtc,
101 struct drm_framebuffer *fb,
102 int x, int y, int atomic)
103{
104 struct cirrus_device *cdev = crtc->dev->dev_private;
105 struct cirrus_bo *bo;
106 int ret;
107 u64 gpu_addr;
108
109 /* push the previous fb to system ram */
110 if (!atomic && fb) {
111 bo = gem_to_cirrus_bo(fb->obj[0]);
112 ret = cirrus_bo_reserve(bo, false);
113 if (ret)
114 return ret;
115 cirrus_bo_push_sysram(bo);
116 cirrus_bo_unreserve(bo);
117 }
118
119 bo = gem_to_cirrus_bo(crtc->primary->fb->obj[0]);
120
121 ret = cirrus_bo_reserve(bo, false);
122 if (ret)
123 return ret;
124
125 ret = cirrus_bo_pin(bo, TTM_PL_FLAG_VRAM, &gpu_addr);
126 if (ret) {
127 cirrus_bo_unreserve(bo);
128 return ret;
129 }
130
131 if (cdev->mode_info.gfbdev->gfb == crtc->primary->fb) {
132 /* if pushing console in kmap it */
133 ret = ttm_bo_kmap(&bo->bo, 0, bo->bo.num_pages, &bo->kmap);
134 if (ret)
135 DRM_ERROR("failed to kmap fbcon\n");
136 }
137 cirrus_bo_unreserve(bo);
138
139 cirrus_set_start_address(crtc, (u32)gpu_addr);
140 return 0;
141}
142
143static int cirrus_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
144 struct drm_framebuffer *old_fb)
145{
146 return cirrus_crtc_do_set_base(crtc, old_fb, x, y, 0);
147}
148
149/*
150 * The meat of this driver. The core passes us a mode and we have to program
151 * it. The modesetting here is the bare minimum required to satisfy the qemu
152 * emulation of this hardware, and running this against a real device is
153 * likely to result in an inadequately programmed mode. We've already had
154 * the opportunity to modify the mode, so whatever we receive here should
155 * be something that can be correctly programmed and displayed
156 */
157static int cirrus_crtc_mode_set(struct drm_crtc *crtc,
158 struct drm_display_mode *mode,
159 struct drm_display_mode *adjusted_mode,
160 int x, int y, struct drm_framebuffer *old_fb)
161{
162 struct drm_device *dev = crtc->dev;
163 struct cirrus_device *cdev = dev->dev_private;
164 const struct drm_framebuffer *fb = crtc->primary->fb;
165 int hsyncstart, hsyncend, htotal, hdispend;
166 int vtotal, vdispend;
167 int tmp;
168 int sr07 = 0, hdr = 0;
169
170 htotal = mode->htotal / 8;
171 hsyncend = mode->hsync_end / 8;
172 hsyncstart = mode->hsync_start / 8;
173 hdispend = mode->hdisplay / 8;
174
175 vtotal = mode->vtotal;
176 vdispend = mode->vdisplay;
177
178 vdispend -= 1;
179 vtotal -= 2;
180
181 htotal -= 5;
182 hdispend -= 1;
183 hsyncstart += 1;
184 hsyncend += 1;
185
186 WREG_CRT(VGA_CRTC_V_SYNC_END, 0x20);
187 WREG_CRT(VGA_CRTC_H_TOTAL, htotal);
188 WREG_CRT(VGA_CRTC_H_DISP, hdispend);
189 WREG_CRT(VGA_CRTC_H_SYNC_START, hsyncstart);
190 WREG_CRT(VGA_CRTC_H_SYNC_END, hsyncend);
191 WREG_CRT(VGA_CRTC_V_TOTAL, vtotal & 0xff);
192 WREG_CRT(VGA_CRTC_V_DISP_END, vdispend & 0xff);
193
194 tmp = 0x40;
195 if ((vdispend + 1) & 512)
196 tmp |= 0x20;
197 WREG_CRT(VGA_CRTC_MAX_SCAN, tmp);
198
199 /*
200 * Overflow bits for values that don't fit in the standard registers
201 */
202 tmp = 16;
203 if (vtotal & 256)
204 tmp |= 1;
205 if (vdispend & 256)
206 tmp |= 2;
207 if ((vdispend + 1) & 256)
208 tmp |= 8;
209 if (vtotal & 512)
210 tmp |= 32;
211 if (vdispend & 512)
212 tmp |= 64;
213 WREG_CRT(VGA_CRTC_OVERFLOW, tmp);
214
215 tmp = 0;
216
217 /* More overflow bits */
218
219 if ((htotal + 5) & 64)
220 tmp |= 16;
221 if ((htotal + 5) & 128)
222 tmp |= 32;
223 if (vtotal & 256)
224 tmp |= 64;
225 if (vtotal & 512)
226 tmp |= 128;
227
228 WREG_CRT(CL_CRT1A, tmp);
229
230 /* Disable Hercules/CGA compatibility */
231 WREG_CRT(VGA_CRTC_MODE, 0x03);
232
233 WREG8(SEQ_INDEX, 0x7);
234 sr07 = RREG8(SEQ_DATA);
235 sr07 &= 0xe0;
236 hdr = 0;
237 switch (fb->format->cpp[0] * 8) {
238 case 8:
239 sr07 |= 0x11;
240 break;
241 case 16:
242 sr07 |= 0x17;
243 hdr = 0xc1;
244 break;
245 case 24:
246 sr07 |= 0x15;
247 hdr = 0xc5;
248 break;
249 case 32:
250 sr07 |= 0x19;
251 hdr = 0xc5;
252 break;
253 default:
254 return -1;
255 }
256
257 WREG_SEQ(0x7, sr07);
258
259 /* Program the pitch */
260 tmp = fb->pitches[0] / 8;
261 WREG_CRT(VGA_CRTC_OFFSET, tmp);
262
263 /* Enable extended blanking and pitch bits, and enable full memory */
264 tmp = 0x22;
265 tmp |= (fb->pitches[0] >> 7) & 0x10;
266 tmp |= (fb->pitches[0] >> 6) & 0x40;
267 WREG_CRT(0x1b, tmp);
268
269 /* Enable high-colour modes */
270 WREG_GFX(VGA_GFX_MODE, 0x40);
271
272 /* And set graphics mode */
273 WREG_GFX(VGA_GFX_MISC, 0x01);
274
275 WREG_HDR(hdr);
276 cirrus_crtc_do_set_base(crtc, old_fb, x, y, 0);
277
278 /* Unblank (needed on S3 resume, vgabios doesn't do it then) */
279 outb(0x20, 0x3c0);
280 return 0;
281}
282
283/*
284 * This is called before a mode is programmed. A typical use might be to
285 * enable DPMS during the programming to avoid seeing intermediate stages,
286 * but that's not relevant to us
287 */
288static void cirrus_crtc_prepare(struct drm_crtc *crtc)
289{
290}
291
292static void cirrus_crtc_load_lut(struct drm_crtc *crtc)
293{
294 struct drm_device *dev = crtc->dev;
295 struct cirrus_device *cdev = dev->dev_private;
296 u16 *r, *g, *b;
297 int i;
298
299 if (!crtc->enabled)
300 return;
301
302 r = crtc->gamma_store;
303 g = r + crtc->gamma_size;
304 b = g + crtc->gamma_size;
305
306 for (i = 0; i < CIRRUS_LUT_SIZE; i++) {
307 /* VGA registers */
308 WREG8(PALETTE_INDEX, i);
309 WREG8(PALETTE_DATA, *r++ >> 8);
310 WREG8(PALETTE_DATA, *g++ >> 8);
311 WREG8(PALETTE_DATA, *b++ >> 8);
312 }
313}
314
315/*
316 * This is called after a mode is programmed. It should reverse anything done
317 * by the prepare function
318 */
319static void cirrus_crtc_commit(struct drm_crtc *crtc)
320{
321 cirrus_crtc_load_lut(crtc);
322}
323
324/*
325 * The core can pass us a set of gamma values to program. We actually only
326 * use this for 8-bit mode so can't perform smooth fades on deeper modes,
327 * but it's a requirement that we provide the function
328 */
329static int cirrus_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green,
330 u16 *blue, uint32_t size,
331 struct drm_modeset_acquire_ctx *ctx)
332{
333 cirrus_crtc_load_lut(crtc);
334
335 return 0;
336}
337
338/* Simple cleanup function */
339static void cirrus_crtc_destroy(struct drm_crtc *crtc)
340{
341 struct cirrus_crtc *cirrus_crtc = to_cirrus_crtc(crtc);
342
343 drm_crtc_cleanup(crtc);
344 kfree(cirrus_crtc);
345}
346
347/* These provide the minimum set of functions required to handle a CRTC */
348static const struct drm_crtc_funcs cirrus_crtc_funcs = {
349 .gamma_set = cirrus_crtc_gamma_set,
350 .set_config = drm_crtc_helper_set_config,
351 .destroy = cirrus_crtc_destroy,
352};
353
354static const struct drm_crtc_helper_funcs cirrus_helper_funcs = {
355 .dpms = cirrus_crtc_dpms,
356 .mode_set = cirrus_crtc_mode_set,
357 .mode_set_base = cirrus_crtc_mode_set_base,
358 .prepare = cirrus_crtc_prepare,
359 .commit = cirrus_crtc_commit,
360};
361
362/* CRTC setup */
363static const uint32_t cirrus_formats_16[] = {
364 DRM_FORMAT_RGB565,
365};
366
367static const uint32_t cirrus_formats_24[] = {
368 DRM_FORMAT_RGB888,
369 DRM_FORMAT_RGB565,
370};
371
372static const uint32_t cirrus_formats_32[] = {
373 DRM_FORMAT_XRGB8888,
374 DRM_FORMAT_ARGB8888,
375 DRM_FORMAT_RGB888,
376 DRM_FORMAT_RGB565,
377};
378
379static struct drm_plane *cirrus_primary_plane(struct drm_device *dev)
380{
381 const uint32_t *formats;
382 uint32_t nformats;
383 struct drm_plane *primary;
384 int ret;
385
386 switch (cirrus_bpp) {
387 case 16:
388 formats = cirrus_formats_16;
389 nformats = ARRAY_SIZE(cirrus_formats_16);
390 break;
391 case 24:
392 formats = cirrus_formats_24;
393 nformats = ARRAY_SIZE(cirrus_formats_24);
394 break;
395 case 32:
396 formats = cirrus_formats_32;
397 nformats = ARRAY_SIZE(cirrus_formats_32);
398 break;
399 default:
400 return NULL;
401 }
402
403 primary = kzalloc(sizeof(*primary), GFP_KERNEL);
404 if (primary == NULL) {
405 DRM_DEBUG_KMS("Failed to allocate primary plane\n");
406 return NULL;
407 }
408
409 ret = drm_universal_plane_init(dev, primary, 0,
410 &drm_primary_helper_funcs,
411 formats, nformats,
412 NULL,
413 DRM_PLANE_TYPE_PRIMARY, NULL);
414 if (ret) {
415 kfree(primary);
416 primary = NULL;
417 }
418
419 return primary;
420}
421
422static void cirrus_crtc_init(struct drm_device *dev)
423{
424 struct cirrus_device *cdev = dev->dev_private;
425 struct cirrus_crtc *cirrus_crtc;
426 struct drm_plane *primary;
427
428 cirrus_crtc = kzalloc(sizeof(struct cirrus_crtc) +
429 (CIRRUSFB_CONN_LIMIT * sizeof(struct drm_connector *)),
430 GFP_KERNEL);
431
432 if (cirrus_crtc == NULL)
433 return;
434
435 primary = cirrus_primary_plane(dev);
436 if (primary == NULL) {
437 kfree(cirrus_crtc);
438 return;
439 }
440
441 drm_crtc_init_with_planes(dev, &cirrus_crtc->base,
442 primary, NULL,
443 &cirrus_crtc_funcs, NULL);
444
445 drm_mode_crtc_set_gamma_size(&cirrus_crtc->base, CIRRUS_LUT_SIZE);
446 cdev->mode_info.crtc = cirrus_crtc;
447
448 drm_crtc_helper_add(&cirrus_crtc->base, &cirrus_helper_funcs);
449}
450
451static void cirrus_encoder_mode_set(struct drm_encoder *encoder,
452 struct drm_display_mode *mode,
453 struct drm_display_mode *adjusted_mode)
454{
455}
456
457static void cirrus_encoder_dpms(struct drm_encoder *encoder, int state)
458{
459 return;
460}
461
462static void cirrus_encoder_prepare(struct drm_encoder *encoder)
463{
464}
465
466static void cirrus_encoder_commit(struct drm_encoder *encoder)
467{
468}
469
470static void cirrus_encoder_destroy(struct drm_encoder *encoder)
471{
472 struct cirrus_encoder *cirrus_encoder = to_cirrus_encoder(encoder);
473 drm_encoder_cleanup(encoder);
474 kfree(cirrus_encoder);
475}
476
477static const struct drm_encoder_helper_funcs cirrus_encoder_helper_funcs = {
478 .dpms = cirrus_encoder_dpms,
479 .mode_set = cirrus_encoder_mode_set,
480 .prepare = cirrus_encoder_prepare,
481 .commit = cirrus_encoder_commit,
482};
483
484static const struct drm_encoder_funcs cirrus_encoder_encoder_funcs = {
485 .destroy = cirrus_encoder_destroy,
486};
487
488static struct drm_encoder *cirrus_encoder_init(struct drm_device *dev)
489{
490 struct drm_encoder *encoder;
491 struct cirrus_encoder *cirrus_encoder;
492
493 cirrus_encoder = kzalloc(sizeof(struct cirrus_encoder), GFP_KERNEL);
494 if (!cirrus_encoder)
495 return NULL;
496
497 encoder = &cirrus_encoder->base;
498 encoder->possible_crtcs = 0x1;
499
500 drm_encoder_init(dev, encoder, &cirrus_encoder_encoder_funcs,
501 DRM_MODE_ENCODER_DAC, NULL);
502 drm_encoder_helper_add(encoder, &cirrus_encoder_helper_funcs);
503
504 return encoder;
505}
506
507
508static int cirrus_vga_get_modes(struct drm_connector *connector)
509{
510 int count;
511
512 /* Just add a static list of modes */
513 if (cirrus_bpp <= 24) {
514 count = drm_add_modes_noedid(connector, 1280, 1024);
515 drm_set_preferred_mode(connector, 1024, 768);
516 } else {
517 count = drm_add_modes_noedid(connector, 800, 600);
518 drm_set_preferred_mode(connector, 800, 600);
519 }
520 return count;
521}
522
523static struct drm_encoder *cirrus_connector_best_encoder(struct drm_connector
524 *connector)
525{
526 int enc_id = connector->encoder_ids[0];
527 /* pick the encoder ids */
528 if (enc_id)
529 return drm_encoder_find(connector->dev, NULL, enc_id);
530 return NULL;
531}
532
533static void cirrus_connector_destroy(struct drm_connector *connector)
534{
535 drm_connector_cleanup(connector);
536 kfree(connector);
537}
538
539static const struct drm_connector_helper_funcs cirrus_vga_connector_helper_funcs = {
540 .get_modes = cirrus_vga_get_modes,
541 .best_encoder = cirrus_connector_best_encoder,
542};
543
544static const struct drm_connector_funcs cirrus_vga_connector_funcs = {
545 .dpms = drm_helper_connector_dpms,
546 .fill_modes = drm_helper_probe_single_connector_modes,
547 .destroy = cirrus_connector_destroy,
548};
549
550static struct drm_connector *cirrus_vga_init(struct drm_device *dev)
551{
552 struct drm_connector *connector;
553 struct cirrus_connector *cirrus_connector;
554
555 cirrus_connector = kzalloc(sizeof(struct cirrus_connector), GFP_KERNEL);
556 if (!cirrus_connector)
557 return NULL;
558
559 connector = &cirrus_connector->base;
560
561 drm_connector_init(dev, connector,
562 &cirrus_vga_connector_funcs, DRM_MODE_CONNECTOR_VGA);
563
564 drm_connector_helper_add(connector, &cirrus_vga_connector_helper_funcs);
565
566 drm_connector_register(connector);
567 return connector;
568}
569
570
571int cirrus_modeset_init(struct cirrus_device *cdev)
572{
573 struct drm_encoder *encoder;
574 struct drm_connector *connector;
575 int ret;
576
577 drm_mode_config_init(cdev->dev);
578
579 cdev->dev->mode_config.max_width = CIRRUS_MAX_FB_WIDTH;
580 cdev->dev->mode_config.max_height = CIRRUS_MAX_FB_HEIGHT;
581
582 cdev->dev->mode_config.fb_base = cdev->mc.vram_base;
583 cdev->dev->mode_config.preferred_depth = cirrus_bpp;
584 /* don't prefer a shadow on virt GPU */
585 cdev->dev->mode_config.prefer_shadow = 0;
586
587 cirrus_crtc_init(cdev->dev);
588
589 encoder = cirrus_encoder_init(cdev->dev);
590 if (!encoder) {
591 DRM_ERROR("cirrus_encoder_init failed\n");
592 return -1;
593 }
594
595 connector = cirrus_vga_init(cdev->dev);
596 if (!connector) {
597 DRM_ERROR("cirrus_vga_init failed\n");
598 return -1;
599 }
600
601 drm_connector_attach_encoder(connector, encoder);
602
603 ret = cirrus_fbdev_init(cdev);
604 if (ret) {
605 DRM_ERROR("cirrus_fbdev_init failed\n");
606 return ret;
607 }
608
609 return 0;
610}
611
612void cirrus_modeset_fini(struct cirrus_device *cdev)
613{
614 cirrus_fbdev_fini(cdev);
615 drm_helper_force_disable_all(cdev->dev);
616 drm_mode_config_cleanup(cdev->dev);
617}
diff --git a/drivers/gpu/drm/drm_format_helper.c b/drivers/gpu/drm/drm_format_helper.c
new file mode 100644
index 000000000000..00d716f14173
--- /dev/null
+++ b/drivers/gpu/drm/drm_format_helper.c
@@ -0,0 +1,326 @@
1/* SPDX-License-Identifier: GPL-2.0 */
2/*
3 * Copyright (C) 2016 Noralf Trønnes
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 */
10
11#include <linux/module.h>
12#include <linux/slab.h>
13
14#include <drm/drm_format_helper.h>
15#include <drm/drm_framebuffer.h>
16#include <drm/drm_fourcc.h>
17#include <drm/drm_rect.h>
18
19static void drm_fb_memcpy_lines(void *dst, unsigned int dst_pitch,
20 void *src, unsigned int src_pitch,
21 unsigned int linelength, unsigned int lines)
22{
23 int line;
24
25 for (line = 0; line < lines; line++) {
26 memcpy(dst, src, linelength);
27 src += src_pitch;
28 dst += dst_pitch;
29 }
30}
31
32/**
33 * drm_fb_memcpy - Copy clip buffer
34 * @dst: Destination buffer
35 * @vaddr: Source buffer
36 * @fb: DRM framebuffer
37 * @clip: Clip rectangle area to copy
38 *
39 * This function does not apply clipping on dst, i.e. the destination
40 * is a small buffer containing the clip rect only.
41 */
42void drm_fb_memcpy(void *dst, void *vaddr, struct drm_framebuffer *fb,
43 struct drm_rect *clip)
44{
45 unsigned int cpp = drm_format_plane_cpp(fb->format->format, 0);
46 unsigned int offset = (clip->y1 * fb->pitches[0]) + (clip->x1 * cpp);
47 size_t len = (clip->x2 - clip->x1) * cpp;
48
49 drm_fb_memcpy_lines(dst, len,
50 vaddr + offset, fb->pitches[0],
51 len, clip->y2 - clip->y1);
52}
53EXPORT_SYMBOL(drm_fb_memcpy);
54
55/**
56 * drm_fb_memcpy_dstclip - Copy clip buffer
57 * @dst: Destination buffer
58 * @vaddr: Source buffer
59 * @fb: DRM framebuffer
60 * @clip: Clip rectangle area to copy
61 *
62 * This function applies clipping on dst, i.e. the destination is a
63 * full framebuffer but only the clip rect content is copied over.
64 */
65void drm_fb_memcpy_dstclip(void *dst, void *vaddr, struct drm_framebuffer *fb,
66 struct drm_rect *clip)
67{
68 unsigned int cpp = drm_format_plane_cpp(fb->format->format, 0);
69 unsigned int offset = (clip->y1 * fb->pitches[0]) + (clip->x1 * cpp);
70 size_t len = (clip->x2 - clip->x1) * cpp;
71
72 drm_fb_memcpy_lines(dst + offset, fb->pitches[0],
73 vaddr + offset, fb->pitches[0],
74 len, clip->y2 - clip->y1);
75}
76EXPORT_SYMBOL(drm_fb_memcpy_dstclip);
77
78/**
79 * drm_fb_swab16 - Swap bytes into clip buffer
80 * @dst: RGB565 destination buffer
81 * @vaddr: RGB565 source buffer
82 * @fb: DRM framebuffer
83 * @clip: Clip rectangle area to copy
84 */
85void drm_fb_swab16(u16 *dst, void *vaddr, struct drm_framebuffer *fb,
86 struct drm_rect *clip)
87{
88 size_t len = (clip->x2 - clip->x1) * sizeof(u16);
89 unsigned int x, y;
90 u16 *src, *buf;
91
92 /*
93 * The cma memory is write-combined so reads are uncached.
94 * Speed up by fetching one line at a time.
95 */
96 buf = kmalloc(len, GFP_KERNEL);
97 if (!buf)
98 return;
99
100 for (y = clip->y1; y < clip->y2; y++) {
101 src = vaddr + (y * fb->pitches[0]);
102 src += clip->x1;
103 memcpy(buf, src, len);
104 src = buf;
105 for (x = clip->x1; x < clip->x2; x++)
106 *dst++ = swab16(*src++);
107 }
108
109 kfree(buf);
110}
111EXPORT_SYMBOL(drm_fb_swab16);
112
113static void drm_fb_xrgb8888_to_rgb565_lines(void *dst, unsigned int dst_pitch,
114 void *src, unsigned int src_pitch,
115 unsigned int src_linelength,
116 unsigned int lines,
117 bool swap)
118{
119 unsigned int linepixels = src_linelength / sizeof(u32);
120 unsigned int x, y;
121 u32 *sbuf;
122 u16 *dbuf, val16;
123
124 /*
125 * The cma memory is write-combined so reads are uncached.
126 * Speed up by fetching one line at a time.
127 */
128 sbuf = kmalloc(src_linelength, GFP_KERNEL);
129 if (!sbuf)
130 return;
131
132 for (y = 0; y < lines; y++) {
133 memcpy(sbuf, src, src_linelength);
134 dbuf = dst;
135 for (x = 0; x < linepixels; x++) {
136 val16 = ((sbuf[x] & 0x00F80000) >> 8) |
137 ((sbuf[x] & 0x0000FC00) >> 5) |
138 ((sbuf[x] & 0x000000F8) >> 3);
139 if (swap)
140 *dbuf++ = swab16(val16);
141 else
142 *dbuf++ = val16;
143 }
144 src += src_pitch;
145 dst += dst_pitch;
146 }
147
148 kfree(sbuf);
149}
150
151/**
152 * drm_fb_xrgb8888_to_rgb565 - Convert XRGB8888 to RGB565 clip buffer
153 * @dst: RGB565 destination buffer
154 * @vaddr: XRGB8888 source buffer
155 * @fb: DRM framebuffer
156 * @clip: Clip rectangle area to copy
157 * @swap: Swap bytes
158 *
159 * Drivers can use this function for RGB565 devices that don't natively
160 * support XRGB8888.
161 *
162 * This function does not apply clipping on dst, i.e. the destination
163 * is a small buffer containing the clip rect only.
164 */
165void drm_fb_xrgb8888_to_rgb565(void *dst, void *vaddr,
166 struct drm_framebuffer *fb,
167 struct drm_rect *clip, bool swap)
168{
169 unsigned int src_offset = (clip->y1 * fb->pitches[0])
170 + (clip->x1 * sizeof(u32));
171 size_t src_len = (clip->x2 - clip->x1) * sizeof(u32);
172 size_t dst_len = (clip->x2 - clip->x1) * sizeof(u16);
173
174 drm_fb_xrgb8888_to_rgb565_lines(dst, dst_len,
175 vaddr + src_offset, fb->pitches[0],
176 src_len, clip->y2 - clip->y1,
177 swap);
178}
179EXPORT_SYMBOL(drm_fb_xrgb8888_to_rgb565);
180
181/**
182 * drm_fb_xrgb8888_to_rgb565_dstclip - Convert XRGB8888 to RGB565 clip buffer
183 * @dst: RGB565 destination buffer
184 * @dst_pitch: destination buffer pitch
185 * @vaddr: XRGB8888 source buffer
186 * @fb: DRM framebuffer
187 * @clip: Clip rectangle area to copy
188 * @swap: Swap bytes
189 *
190 * Drivers can use this function for RGB565 devices that don't natively
191 * support XRGB8888.
192 *
193 * This function applies clipping on dst, i.e. the destination is a
194 * full framebuffer but only the clip rect content is copied over.
195 */
196void drm_fb_xrgb8888_to_rgb565_dstclip(void *dst, unsigned int dst_pitch,
197 void *vaddr, struct drm_framebuffer *fb,
198 struct drm_rect *clip, bool swap)
199{
200 unsigned int src_offset = (clip->y1 * fb->pitches[0])
201 + (clip->x1 * sizeof(u32));
202 unsigned int dst_offset = (clip->y1 * dst_pitch)
203 + (clip->x1 * sizeof(u16));
204 size_t src_len = (clip->x2 - clip->x1) * sizeof(u32);
205
206 drm_fb_xrgb8888_to_rgb565_lines(dst + dst_offset, dst_pitch,
207 vaddr + src_offset, fb->pitches[0],
208 src_len, clip->y2 - clip->y1,
209 swap);
210}
211EXPORT_SYMBOL(drm_fb_xrgb8888_to_rgb565_dstclip);
212
213static void drm_fb_xrgb8888_to_rgb888_lines(void *dst, unsigned int dst_pitch,
214 void *src, unsigned int src_pitch,
215 unsigned int src_linelength,
216 unsigned int lines)
217{
218 unsigned int linepixels = src_linelength / 3;
219 unsigned int x, y;
220 u32 *sbuf;
221 u8 *dbuf;
222
223 sbuf = kmalloc(src_linelength, GFP_KERNEL);
224 if (!sbuf)
225 return;
226
227 for (y = 0; y < lines; y++) {
228 memcpy(sbuf, src, src_linelength);
229 dbuf = dst;
230 for (x = 0; x < linepixels; x++) {
231 *dbuf++ = (sbuf[x] & 0x000000FF) >> 0;
232 *dbuf++ = (sbuf[x] & 0x0000FF00) >> 8;
233 *dbuf++ = (sbuf[x] & 0x00FF0000) >> 16;
234 }
235 src += src_pitch;
236 dst += dst_pitch;
237 }
238
239 kfree(sbuf);
240}
241
242/**
243 * drm_fb_xrgb8888_to_rgb888_dstclip - Convert XRGB8888 to RGB888 clip buffer
244 * @dst: RGB565 destination buffer
245 * @dst_pitch: destination buffer pitch
246 * @vaddr: XRGB8888 source buffer
247 * @fb: DRM framebuffer
248 * @clip: Clip rectangle area to copy
249 * @dstclip: Clip destination too.
250 *
251 * Drivers can use this function for RGB888 devices that don't natively
252 * support XRGB8888.
253 *
254 * This function applies clipping on dst, i.e. the destination is a
255 * full framebuffer but only the clip rect content is copied over.
256 */
257void drm_fb_xrgb8888_to_rgb888_dstclip(void *dst, unsigned int dst_pitch,
258 void *vaddr, struct drm_framebuffer *fb,
259 struct drm_rect *clip)
260{
261 unsigned int src_offset = (clip->y1 * fb->pitches[0])
262 + (clip->x1 * sizeof(u32));
263 unsigned int dst_offset = (clip->y1 * dst_pitch)
264 + (clip->x1 * 3);
265 size_t src_len = (clip->x2 - clip->x1) * sizeof(u32);
266
267 drm_fb_xrgb8888_to_rgb888_lines(dst + dst_offset, dst_pitch,
268 vaddr + src_offset, fb->pitches[0],
269 src_len, clip->y2 - clip->y1);
270}
271EXPORT_SYMBOL(drm_fb_xrgb8888_to_rgb888_dstclip);
272
273/**
274 * drm_fb_xrgb8888_to_gray8 - Convert XRGB8888 to grayscale
275 * @dst: 8-bit grayscale destination buffer
276 * @vaddr: XRGB8888 source buffer
277 * @fb: DRM framebuffer
278 * @clip: Clip rectangle area to copy
279 *
280 * Drm doesn't have native monochrome or grayscale support.
281 * Such drivers can announce the commonly supported XR24 format to userspace
282 * and use this function to convert to the native format.
283 *
284 * Monochrome drivers will use the most significant bit,
285 * where 1 means foreground color and 0 background color.
286 *
287 * ITU BT.601 is used for the RGB -> luma (brightness) conversion.
288 */
289void drm_fb_xrgb8888_to_gray8(u8 *dst, void *vaddr, struct drm_framebuffer *fb,
290 struct drm_rect *clip)
291{
292 unsigned int len = (clip->x2 - clip->x1) * sizeof(u32);
293 unsigned int x, y;
294 void *buf;
295 u32 *src;
296
297 if (WARN_ON(fb->format->format != DRM_FORMAT_XRGB8888))
298 return;
299 /*
300 * The cma memory is write-combined so reads are uncached.
301 * Speed up by fetching one line at a time.
302 */
303 buf = kmalloc(len, GFP_KERNEL);
304 if (!buf)
305 return;
306
307 for (y = clip->y1; y < clip->y2; y++) {
308 src = vaddr + (y * fb->pitches[0]);
309 src += clip->x1;
310 memcpy(buf, src, len);
311 src = buf;
312 for (x = clip->x1; x < clip->x2; x++) {
313 u8 r = (*src & 0x00ff0000) >> 16;
314 u8 g = (*src & 0x0000ff00) >> 8;
315 u8 b = *src & 0x000000ff;
316
317 /* ITU BT.601: Y = 0.299 R + 0.587 G + 0.114 B */
318 *dst++ = (3 * r + 6 * g + b) / 10;
319 src++;
320 }
321 }
322
323 kfree(buf);
324}
325EXPORT_SYMBOL(drm_fb_xrgb8888_to_gray8);
326
diff --git a/drivers/gpu/drm/lima/Kconfig b/drivers/gpu/drm/lima/Kconfig
index f11314448093..bb4ddc6bb0a6 100644
--- a/drivers/gpu/drm/lima/Kconfig
+++ b/drivers/gpu/drm/lima/Kconfig
@@ -5,6 +5,9 @@ config DRM_LIMA
5 tristate "LIMA (DRM support for ARM Mali 400/450 GPU)" 5 tristate "LIMA (DRM support for ARM Mali 400/450 GPU)"
6 depends on DRM 6 depends on DRM
7 depends on ARM || ARM64 || COMPILE_TEST 7 depends on ARM || ARM64 || COMPILE_TEST
8 depends on MMU
9 depends on COMMON_CLK
10 depends on OF
8 select DRM_SCHED 11 select DRM_SCHED
9 help 12 help
10 DRM driver for ARM Mali 400/450 GPUs. 13 DRM driver for ARM Mali 400/450 GPUs.
diff --git a/drivers/gpu/drm/lima/lima_gem.c b/drivers/gpu/drm/lima/lima_gem.c
index 2d3cf96f6c58..1d69498bc17e 100644
--- a/drivers/gpu/drm/lima/lima_gem.c
+++ b/drivers/gpu/drm/lima/lima_gem.c
@@ -1,6 +1,7 @@
1// SPDX-License-Identifier: GPL-2.0 OR MIT 1// SPDX-License-Identifier: GPL-2.0 OR MIT
2/* Copyright 2017-2019 Qiang Yu <yuq825@gmail.com> */ 2/* Copyright 2017-2019 Qiang Yu <yuq825@gmail.com> */
3 3
4#include <linux/mm.h>
4#include <linux/sync_file.h> 5#include <linux/sync_file.h>
5#include <linux/pfn_t.h> 6#include <linux/pfn_t.h>
6 7
diff --git a/drivers/gpu/drm/meson/meson_crtc.c b/drivers/gpu/drm/meson/meson_crtc.c
index 6d9311e254ef..5579f8ac3e3f 100644
--- a/drivers/gpu/drm/meson/meson_crtc.c
+++ b/drivers/gpu/drm/meson/meson_crtc.c
@@ -39,12 +39,17 @@
39#include "meson_viu.h" 39#include "meson_viu.h"
40#include "meson_registers.h" 40#include "meson_registers.h"
41 41
42#define MESON_G12A_VIU_OFFSET 0x5ec0
43
42/* CRTC definition */ 44/* CRTC definition */
43 45
44struct meson_crtc { 46struct meson_crtc {
45 struct drm_crtc base; 47 struct drm_crtc base;
46 struct drm_pending_vblank_event *event; 48 struct drm_pending_vblank_event *event;
47 struct meson_drm *priv; 49 struct meson_drm *priv;
50 void (*enable_osd1)(struct meson_drm *priv);
51 void (*enable_vd1)(struct meson_drm *priv);
52 unsigned int viu_offset;
48}; 53};
49#define to_meson_crtc(x) container_of(x, struct meson_crtc, base) 54#define to_meson_crtc(x) container_of(x, struct meson_crtc, base)
50 55
@@ -80,6 +85,44 @@ static const struct drm_crtc_funcs meson_crtc_funcs = {
80 85
81}; 86};
82 87
88static void meson_g12a_crtc_atomic_enable(struct drm_crtc *crtc,
89 struct drm_crtc_state *old_state)
90{
91 struct meson_crtc *meson_crtc = to_meson_crtc(crtc);
92 struct drm_crtc_state *crtc_state = crtc->state;
93 struct meson_drm *priv = meson_crtc->priv;
94
95 DRM_DEBUG_DRIVER("\n");
96
97 if (!crtc_state) {
98 DRM_ERROR("Invalid crtc_state\n");
99 return;
100 }
101
102 /* VD1 Preblend vertical start/end */
103 writel(FIELD_PREP(GENMASK(11, 0), 2303),
104 priv->io_base + _REG(VPP_PREBLEND_VD1_V_START_END));
105
106 /* Setup Blender */
107 writel(crtc_state->mode.hdisplay |
108 crtc_state->mode.vdisplay << 16,
109 priv->io_base + _REG(VPP_POSTBLEND_H_SIZE));
110
111 writel_relaxed(0 << 16 |
112 (crtc_state->mode.hdisplay - 1),
113 priv->io_base + _REG(VPP_OSD1_BLD_H_SCOPE));
114 writel_relaxed(0 << 16 |
115 (crtc_state->mode.vdisplay - 1),
116 priv->io_base + _REG(VPP_OSD1_BLD_V_SCOPE));
117 writel_relaxed(crtc_state->mode.hdisplay << 16 |
118 crtc_state->mode.vdisplay,
119 priv->io_base + _REG(VPP_OUT_H_V_SIZE));
120
121 drm_crtc_vblank_on(crtc);
122
123 priv->viu.osd1_enabled = true;
124}
125
83static void meson_crtc_atomic_enable(struct drm_crtc *crtc, 126static void meson_crtc_atomic_enable(struct drm_crtc *crtc,
84 struct drm_crtc_state *old_state) 127 struct drm_crtc_state *old_state)
85{ 128{
@@ -110,6 +153,31 @@ static void meson_crtc_atomic_enable(struct drm_crtc *crtc,
110 priv->viu.osd1_enabled = true; 153 priv->viu.osd1_enabled = true;
111} 154}
112 155
156static void meson_g12a_crtc_atomic_disable(struct drm_crtc *crtc,
157 struct drm_crtc_state *old_state)
158{
159 struct meson_crtc *meson_crtc = to_meson_crtc(crtc);
160 struct meson_drm *priv = meson_crtc->priv;
161
162 DRM_DEBUG_DRIVER("\n");
163
164 drm_crtc_vblank_off(crtc);
165
166 priv->viu.osd1_enabled = false;
167 priv->viu.osd1_commit = false;
168
169 priv->viu.vd1_enabled = false;
170 priv->viu.vd1_commit = false;
171
172 if (crtc->state->event && !crtc->state->active) {
173 spin_lock_irq(&crtc->dev->event_lock);
174 drm_crtc_send_vblank_event(crtc, crtc->state->event);
175 spin_unlock_irq(&crtc->dev->event_lock);
176
177 crtc->state->event = NULL;
178 }
179}
180
113static void meson_crtc_atomic_disable(struct drm_crtc *crtc, 181static void meson_crtc_atomic_disable(struct drm_crtc *crtc,
114 struct drm_crtc_state *old_state) 182 struct drm_crtc_state *old_state)
115{ 183{
@@ -173,6 +241,53 @@ static const struct drm_crtc_helper_funcs meson_crtc_helper_funcs = {
173 .atomic_disable = meson_crtc_atomic_disable, 241 .atomic_disable = meson_crtc_atomic_disable,
174}; 242};
175 243
244static const struct drm_crtc_helper_funcs meson_g12a_crtc_helper_funcs = {
245 .atomic_begin = meson_crtc_atomic_begin,
246 .atomic_flush = meson_crtc_atomic_flush,
247 .atomic_enable = meson_g12a_crtc_atomic_enable,
248 .atomic_disable = meson_g12a_crtc_atomic_disable,
249};
250
251static void meson_crtc_enable_osd1(struct meson_drm *priv)
252{
253 writel_bits_relaxed(VPP_OSD1_POSTBLEND, VPP_OSD1_POSTBLEND,
254 priv->io_base + _REG(VPP_MISC));
255}
256
257static void meson_g12a_crtc_enable_osd1(struct meson_drm *priv)
258{
259 writel_relaxed(priv->viu.osd_blend_din0_scope_h,
260 priv->io_base +
261 _REG(VIU_OSD_BLEND_DIN0_SCOPE_H));
262 writel_relaxed(priv->viu.osd_blend_din0_scope_v,
263 priv->io_base +
264 _REG(VIU_OSD_BLEND_DIN0_SCOPE_V));
265 writel_relaxed(priv->viu.osb_blend0_size,
266 priv->io_base +
267 _REG(VIU_OSD_BLEND_BLEND0_SIZE));
268 writel_relaxed(priv->viu.osb_blend1_size,
269 priv->io_base +
270 _REG(VIU_OSD_BLEND_BLEND1_SIZE));
271}
272
273static void meson_crtc_enable_vd1(struct meson_drm *priv)
274{
275 writel_bits_relaxed(VPP_VD1_PREBLEND | VPP_VD1_POSTBLEND |
276 VPP_COLOR_MNG_ENABLE,
277 VPP_VD1_PREBLEND | VPP_VD1_POSTBLEND |
278 VPP_COLOR_MNG_ENABLE,
279 priv->io_base + _REG(VPP_MISC));
280}
281
282static void meson_g12a_crtc_enable_vd1(struct meson_drm *priv)
283{
284 writel_relaxed(((1 << 16) | /* post bld premult*/
285 (1 << 8) | /* post src */
286 (1 << 4) | /* pre bld premult*/
287 (1 << 0)),
288 priv->io_base + _REG(VD1_BLEND_SRC_CTRL));
289}
290
176void meson_crtc_irq(struct meson_drm *priv) 291void meson_crtc_irq(struct meson_drm *priv)
177{ 292{
178 struct meson_crtc *meson_crtc = to_meson_crtc(priv->crtc); 293 struct meson_crtc *meson_crtc = to_meson_crtc(priv->crtc);
@@ -219,8 +334,8 @@ void meson_crtc_irq(struct meson_drm *priv)
219 MESON_CANVAS_BLKMODE_LINEAR, 0); 334 MESON_CANVAS_BLKMODE_LINEAR, 0);
220 335
221 /* Enable OSD1 */ 336 /* Enable OSD1 */
222 writel_bits_relaxed(VPP_OSD1_POSTBLEND, VPP_OSD1_POSTBLEND, 337 if (meson_crtc->enable_osd1)
223 priv->io_base + _REG(VPP_MISC)); 338 meson_crtc->enable_osd1(priv);
224 339
225 priv->viu.osd1_commit = false; 340 priv->viu.osd1_commit = false;
226 } 341 }
@@ -261,89 +376,133 @@ void meson_crtc_irq(struct meson_drm *priv)
261 }; 376 };
262 377
263 writel_relaxed(priv->viu.vd1_if0_gen_reg, 378 writel_relaxed(priv->viu.vd1_if0_gen_reg,
264 priv->io_base + _REG(VD1_IF0_GEN_REG)); 379 priv->io_base + meson_crtc->viu_offset +
380 _REG(VD1_IF0_GEN_REG));
265 writel_relaxed(priv->viu.vd1_if0_gen_reg, 381 writel_relaxed(priv->viu.vd1_if0_gen_reg,
266 priv->io_base + _REG(VD2_IF0_GEN_REG)); 382 priv->io_base + meson_crtc->viu_offset +
383 _REG(VD2_IF0_GEN_REG));
267 writel_relaxed(priv->viu.vd1_if0_gen_reg2, 384 writel_relaxed(priv->viu.vd1_if0_gen_reg2,
268 priv->io_base + _REG(VD1_IF0_GEN_REG2)); 385 priv->io_base + meson_crtc->viu_offset +
386 _REG(VD1_IF0_GEN_REG2));
269 writel_relaxed(priv->viu.viu_vd1_fmt_ctrl, 387 writel_relaxed(priv->viu.viu_vd1_fmt_ctrl,
270 priv->io_base + _REG(VIU_VD1_FMT_CTRL)); 388 priv->io_base + meson_crtc->viu_offset +
389 _REG(VIU_VD1_FMT_CTRL));
271 writel_relaxed(priv->viu.viu_vd1_fmt_ctrl, 390 writel_relaxed(priv->viu.viu_vd1_fmt_ctrl,
272 priv->io_base + _REG(VIU_VD2_FMT_CTRL)); 391 priv->io_base + meson_crtc->viu_offset +
392 _REG(VIU_VD2_FMT_CTRL));
273 writel_relaxed(priv->viu.viu_vd1_fmt_w, 393 writel_relaxed(priv->viu.viu_vd1_fmt_w,
274 priv->io_base + _REG(VIU_VD1_FMT_W)); 394 priv->io_base + meson_crtc->viu_offset +
395 _REG(VIU_VD1_FMT_W));
275 writel_relaxed(priv->viu.viu_vd1_fmt_w, 396 writel_relaxed(priv->viu.viu_vd1_fmt_w,
276 priv->io_base + _REG(VIU_VD2_FMT_W)); 397 priv->io_base + meson_crtc->viu_offset +
398 _REG(VIU_VD2_FMT_W));
277 writel_relaxed(priv->viu.vd1_if0_canvas0, 399 writel_relaxed(priv->viu.vd1_if0_canvas0,
278 priv->io_base + _REG(VD1_IF0_CANVAS0)); 400 priv->io_base + meson_crtc->viu_offset +
401 _REG(VD1_IF0_CANVAS0));
279 writel_relaxed(priv->viu.vd1_if0_canvas0, 402 writel_relaxed(priv->viu.vd1_if0_canvas0,
280 priv->io_base + _REG(VD1_IF0_CANVAS1)); 403 priv->io_base + meson_crtc->viu_offset +
404 _REG(VD1_IF0_CANVAS1));
281 writel_relaxed(priv->viu.vd1_if0_canvas0, 405 writel_relaxed(priv->viu.vd1_if0_canvas0,
282 priv->io_base + _REG(VD2_IF0_CANVAS0)); 406 priv->io_base + meson_crtc->viu_offset +
407 _REG(VD2_IF0_CANVAS0));
283 writel_relaxed(priv->viu.vd1_if0_canvas0, 408 writel_relaxed(priv->viu.vd1_if0_canvas0,
284 priv->io_base + _REG(VD2_IF0_CANVAS1)); 409 priv->io_base + meson_crtc->viu_offset +
410 _REG(VD2_IF0_CANVAS1));
285 writel_relaxed(priv->viu.vd1_if0_luma_x0, 411 writel_relaxed(priv->viu.vd1_if0_luma_x0,
286 priv->io_base + _REG(VD1_IF0_LUMA_X0)); 412 priv->io_base + meson_crtc->viu_offset +
413 _REG(VD1_IF0_LUMA_X0));
287 writel_relaxed(priv->viu.vd1_if0_luma_x0, 414 writel_relaxed(priv->viu.vd1_if0_luma_x0,
288 priv->io_base + _REG(VD1_IF0_LUMA_X1)); 415 priv->io_base + meson_crtc->viu_offset +
416 _REG(VD1_IF0_LUMA_X1));
289 writel_relaxed(priv->viu.vd1_if0_luma_x0, 417 writel_relaxed(priv->viu.vd1_if0_luma_x0,
290 priv->io_base + _REG(VD2_IF0_LUMA_X0)); 418 priv->io_base + meson_crtc->viu_offset +
419 _REG(VD2_IF0_LUMA_X0));
291 writel_relaxed(priv->viu.vd1_if0_luma_x0, 420 writel_relaxed(priv->viu.vd1_if0_luma_x0,
292 priv->io_base + _REG(VD2_IF0_LUMA_X1)); 421 priv->io_base + meson_crtc->viu_offset +
422 _REG(VD2_IF0_LUMA_X1));
293 writel_relaxed(priv->viu.vd1_if0_luma_y0, 423 writel_relaxed(priv->viu.vd1_if0_luma_y0,
294 priv->io_base + _REG(VD1_IF0_LUMA_Y0)); 424 priv->io_base + meson_crtc->viu_offset +
425 _REG(VD1_IF0_LUMA_Y0));
295 writel_relaxed(priv->viu.vd1_if0_luma_y0, 426 writel_relaxed(priv->viu.vd1_if0_luma_y0,
296 priv->io_base + _REG(VD1_IF0_LUMA_Y1)); 427 priv->io_base + meson_crtc->viu_offset +
428 _REG(VD1_IF0_LUMA_Y1));
297 writel_relaxed(priv->viu.vd1_if0_luma_y0, 429 writel_relaxed(priv->viu.vd1_if0_luma_y0,
298 priv->io_base + _REG(VD2_IF0_LUMA_Y0)); 430 priv->io_base + meson_crtc->viu_offset +
431 _REG(VD2_IF0_LUMA_Y0));
299 writel_relaxed(priv->viu.vd1_if0_luma_y0, 432 writel_relaxed(priv->viu.vd1_if0_luma_y0,
300 priv->io_base + _REG(VD2_IF0_LUMA_Y1)); 433 priv->io_base + meson_crtc->viu_offset +
434 _REG(VD2_IF0_LUMA_Y1));
301 writel_relaxed(priv->viu.vd1_if0_chroma_x0, 435 writel_relaxed(priv->viu.vd1_if0_chroma_x0,
302 priv->io_base + _REG(VD1_IF0_CHROMA_X0)); 436 priv->io_base + meson_crtc->viu_offset +
437 _REG(VD1_IF0_CHROMA_X0));
303 writel_relaxed(priv->viu.vd1_if0_chroma_x0, 438 writel_relaxed(priv->viu.vd1_if0_chroma_x0,
304 priv->io_base + _REG(VD1_IF0_CHROMA_X1)); 439 priv->io_base + meson_crtc->viu_offset +
440 _REG(VD1_IF0_CHROMA_X1));
305 writel_relaxed(priv->viu.vd1_if0_chroma_x0, 441 writel_relaxed(priv->viu.vd1_if0_chroma_x0,
306 priv->io_base + _REG(VD2_IF0_CHROMA_X0)); 442 priv->io_base + meson_crtc->viu_offset +
443 _REG(VD2_IF0_CHROMA_X0));
307 writel_relaxed(priv->viu.vd1_if0_chroma_x0, 444 writel_relaxed(priv->viu.vd1_if0_chroma_x0,
308 priv->io_base + _REG(VD2_IF0_CHROMA_X1)); 445 priv->io_base + meson_crtc->viu_offset +
446 _REG(VD2_IF0_CHROMA_X1));
309 writel_relaxed(priv->viu.vd1_if0_chroma_y0, 447 writel_relaxed(priv->viu.vd1_if0_chroma_y0,
310 priv->io_base + _REG(VD1_IF0_CHROMA_Y0)); 448 priv->io_base + meson_crtc->viu_offset +
449 _REG(VD1_IF0_CHROMA_Y0));
311 writel_relaxed(priv->viu.vd1_if0_chroma_y0, 450 writel_relaxed(priv->viu.vd1_if0_chroma_y0,
312 priv->io_base + _REG(VD1_IF0_CHROMA_Y1)); 451 priv->io_base + meson_crtc->viu_offset +
452 _REG(VD1_IF0_CHROMA_Y1));
313 writel_relaxed(priv->viu.vd1_if0_chroma_y0, 453 writel_relaxed(priv->viu.vd1_if0_chroma_y0,
314 priv->io_base + _REG(VD2_IF0_CHROMA_Y0)); 454 priv->io_base + meson_crtc->viu_offset +
455 _REG(VD2_IF0_CHROMA_Y0));
315 writel_relaxed(priv->viu.vd1_if0_chroma_y0, 456 writel_relaxed(priv->viu.vd1_if0_chroma_y0,
316 priv->io_base + _REG(VD2_IF0_CHROMA_Y1)); 457 priv->io_base + meson_crtc->viu_offset +
458 _REG(VD2_IF0_CHROMA_Y1));
317 writel_relaxed(priv->viu.vd1_if0_repeat_loop, 459 writel_relaxed(priv->viu.vd1_if0_repeat_loop,
318 priv->io_base + _REG(VD1_IF0_RPT_LOOP)); 460 priv->io_base + meson_crtc->viu_offset +
461 _REG(VD1_IF0_RPT_LOOP));
319 writel_relaxed(priv->viu.vd1_if0_repeat_loop, 462 writel_relaxed(priv->viu.vd1_if0_repeat_loop,
320 priv->io_base + _REG(VD2_IF0_RPT_LOOP)); 463 priv->io_base + meson_crtc->viu_offset +
464 _REG(VD2_IF0_RPT_LOOP));
321 writel_relaxed(priv->viu.vd1_if0_luma0_rpt_pat, 465 writel_relaxed(priv->viu.vd1_if0_luma0_rpt_pat,
322 priv->io_base + _REG(VD1_IF0_LUMA0_RPT_PAT)); 466 priv->io_base + meson_crtc->viu_offset +
467 _REG(VD1_IF0_LUMA0_RPT_PAT));
323 writel_relaxed(priv->viu.vd1_if0_luma0_rpt_pat, 468 writel_relaxed(priv->viu.vd1_if0_luma0_rpt_pat,
324 priv->io_base + _REG(VD2_IF0_LUMA0_RPT_PAT)); 469 priv->io_base + meson_crtc->viu_offset +
470 _REG(VD2_IF0_LUMA0_RPT_PAT));
325 writel_relaxed(priv->viu.vd1_if0_luma0_rpt_pat, 471 writel_relaxed(priv->viu.vd1_if0_luma0_rpt_pat,
326 priv->io_base + _REG(VD1_IF0_LUMA1_RPT_PAT)); 472 priv->io_base + meson_crtc->viu_offset +
473 _REG(VD1_IF0_LUMA1_RPT_PAT));
327 writel_relaxed(priv->viu.vd1_if0_luma0_rpt_pat, 474 writel_relaxed(priv->viu.vd1_if0_luma0_rpt_pat,
328 priv->io_base + _REG(VD2_IF0_LUMA1_RPT_PAT)); 475 priv->io_base + meson_crtc->viu_offset +
476 _REG(VD2_IF0_LUMA1_RPT_PAT));
329 writel_relaxed(priv->viu.vd1_if0_chroma0_rpt_pat, 477 writel_relaxed(priv->viu.vd1_if0_chroma0_rpt_pat,
330 priv->io_base + _REG(VD1_IF0_CHROMA0_RPT_PAT)); 478 priv->io_base + meson_crtc->viu_offset +
479 _REG(VD1_IF0_CHROMA0_RPT_PAT));
331 writel_relaxed(priv->viu.vd1_if0_chroma0_rpt_pat, 480 writel_relaxed(priv->viu.vd1_if0_chroma0_rpt_pat,
332 priv->io_base + _REG(VD2_IF0_CHROMA0_RPT_PAT)); 481 priv->io_base + meson_crtc->viu_offset +
482 _REG(VD2_IF0_CHROMA0_RPT_PAT));
333 writel_relaxed(priv->viu.vd1_if0_chroma0_rpt_pat, 483 writel_relaxed(priv->viu.vd1_if0_chroma0_rpt_pat,
334 priv->io_base + _REG(VD1_IF0_CHROMA1_RPT_PAT)); 484 priv->io_base + meson_crtc->viu_offset +
485 _REG(VD1_IF0_CHROMA1_RPT_PAT));
335 writel_relaxed(priv->viu.vd1_if0_chroma0_rpt_pat, 486 writel_relaxed(priv->viu.vd1_if0_chroma0_rpt_pat,
336 priv->io_base + _REG(VD2_IF0_CHROMA1_RPT_PAT)); 487 priv->io_base + meson_crtc->viu_offset +
337 writel_relaxed(0, priv->io_base + _REG(VD1_IF0_LUMA_PSEL)); 488 _REG(VD2_IF0_CHROMA1_RPT_PAT));
338 writel_relaxed(0, priv->io_base + _REG(VD1_IF0_CHROMA_PSEL)); 489 writel_relaxed(0, priv->io_base + meson_crtc->viu_offset +
339 writel_relaxed(0, priv->io_base + _REG(VD2_IF0_LUMA_PSEL)); 490 _REG(VD1_IF0_LUMA_PSEL));
340 writel_relaxed(0, priv->io_base + _REG(VD2_IF0_CHROMA_PSEL)); 491 writel_relaxed(0, priv->io_base + meson_crtc->viu_offset +
492 _REG(VD1_IF0_CHROMA_PSEL));
493 writel_relaxed(0, priv->io_base + meson_crtc->viu_offset +
494 _REG(VD2_IF0_LUMA_PSEL));
495 writel_relaxed(0, priv->io_base + meson_crtc->viu_offset +
496 _REG(VD2_IF0_CHROMA_PSEL));
341 writel_relaxed(priv->viu.vd1_range_map_y, 497 writel_relaxed(priv->viu.vd1_range_map_y,
342 priv->io_base + _REG(VD1_IF0_RANGE_MAP_Y)); 498 priv->io_base + meson_crtc->viu_offset +
499 _REG(VD1_IF0_RANGE_MAP_Y));
343 writel_relaxed(priv->viu.vd1_range_map_cb, 500 writel_relaxed(priv->viu.vd1_range_map_cb,
344 priv->io_base + _REG(VD1_IF0_RANGE_MAP_CB)); 501 priv->io_base + meson_crtc->viu_offset +
502 _REG(VD1_IF0_RANGE_MAP_CB));
345 writel_relaxed(priv->viu.vd1_range_map_cr, 503 writel_relaxed(priv->viu.vd1_range_map_cr,
346 priv->io_base + _REG(VD1_IF0_RANGE_MAP_CR)); 504 priv->io_base + meson_crtc->viu_offset +
505 _REG(VD1_IF0_RANGE_MAP_CR));
347 writel_relaxed(0x78404, 506 writel_relaxed(0x78404,
348 priv->io_base + _REG(VPP_SC_MISC)); 507 priv->io_base + _REG(VPP_SC_MISC));
349 writel_relaxed(priv->viu.vpp_pic_in_height, 508 writel_relaxed(priv->viu.vpp_pic_in_height,
@@ -389,11 +548,8 @@ void meson_crtc_irq(struct meson_drm *priv)
389 writel_relaxed(0x42, priv->io_base + _REG(VPP_SCALE_COEF_IDX)); 548 writel_relaxed(0x42, priv->io_base + _REG(VPP_SCALE_COEF_IDX));
390 549
391 /* Enable VD1 */ 550 /* Enable VD1 */
392 writel_bits_relaxed(VPP_VD1_PREBLEND | VPP_VD1_POSTBLEND | 551 if (meson_crtc->enable_vd1)
393 VPP_COLOR_MNG_ENABLE, 552 meson_crtc->enable_vd1(priv);
394 VPP_VD1_PREBLEND | VPP_VD1_POSTBLEND |
395 VPP_COLOR_MNG_ENABLE,
396 priv->io_base + _REG(VPP_MISC));
397 553
398 priv->viu.vd1_commit = false; 554 priv->viu.vd1_commit = false;
399 } 555 }
@@ -430,7 +586,16 @@ int meson_crtc_create(struct meson_drm *priv)
430 return ret; 586 return ret;
431 } 587 }
432 588
433 drm_crtc_helper_add(crtc, &meson_crtc_helper_funcs); 589 if (meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu")) {
590 meson_crtc->enable_osd1 = meson_g12a_crtc_enable_osd1;
591 meson_crtc->enable_vd1 = meson_g12a_crtc_enable_vd1;
592 meson_crtc->viu_offset = MESON_G12A_VIU_OFFSET;
593 drm_crtc_helper_add(crtc, &meson_g12a_crtc_helper_funcs);
594 } else {
595 meson_crtc->enable_osd1 = meson_crtc_enable_osd1;
596 meson_crtc->enable_vd1 = meson_crtc_enable_vd1;
597 drm_crtc_helper_add(crtc, &meson_crtc_helper_funcs);
598 }
434 599
435 priv->crtc = crtc; 600 priv->crtc = crtc;
436 601
diff --git a/drivers/gpu/drm/meson/meson_drv.c b/drivers/gpu/drm/meson/meson_drv.c
index 70f9d7b85e8e..937cfabb95df 100644
--- a/drivers/gpu/drm/meson/meson_drv.c
+++ b/drivers/gpu/drm/meson/meson_drv.c
@@ -444,6 +444,7 @@ static const struct of_device_id dt_match[] = {
444 { .compatible = "amlogic,meson-gxbb-vpu" }, 444 { .compatible = "amlogic,meson-gxbb-vpu" },
445 { .compatible = "amlogic,meson-gxl-vpu" }, 445 { .compatible = "amlogic,meson-gxl-vpu" },
446 { .compatible = "amlogic,meson-gxm-vpu" }, 446 { .compatible = "amlogic,meson-gxm-vpu" },
447 { .compatible = "amlogic,meson-g12a-vpu" },
447 {} 448 {}
448}; 449};
449MODULE_DEVICE_TABLE(of, dt_match); 450MODULE_DEVICE_TABLE(of, dt_match);
diff --git a/drivers/gpu/drm/meson/meson_drv.h b/drivers/gpu/drm/meson/meson_drv.h
index 214a7cb18ce2..9614baa836b9 100644
--- a/drivers/gpu/drm/meson/meson_drv.h
+++ b/drivers/gpu/drm/meson/meson_drv.h
@@ -62,6 +62,10 @@ struct meson_drm {
62 uint32_t osd_sc_h_phase_step; 62 uint32_t osd_sc_h_phase_step;
63 uint32_t osd_sc_h_ctrl0; 63 uint32_t osd_sc_h_ctrl0;
64 uint32_t osd_sc_v_ctrl0; 64 uint32_t osd_sc_v_ctrl0;
65 uint32_t osd_blend_din0_scope_h;
66 uint32_t osd_blend_din0_scope_v;
67 uint32_t osb_blend0_size;
68 uint32_t osb_blend1_size;
65 69
66 bool vd1_enabled; 70 bool vd1_enabled;
67 bool vd1_commit; 71 bool vd1_commit;
diff --git a/drivers/gpu/drm/meson/meson_dw_hdmi.c b/drivers/gpu/drm/meson/meson_dw_hdmi.c
index e28814f4ea6c..2a860d158f4f 100644
--- a/drivers/gpu/drm/meson/meson_dw_hdmi.c
+++ b/drivers/gpu/drm/meson/meson_dw_hdmi.c
@@ -20,6 +20,7 @@
20#include <linux/kernel.h> 20#include <linux/kernel.h>
21#include <linux/module.h> 21#include <linux/module.h>
22#include <linux/component.h> 22#include <linux/component.h>
23#include <linux/of_device.h>
23#include <linux/of_graph.h> 24#include <linux/of_graph.h>
24#include <linux/reset.h> 25#include <linux/reset.h>
25#include <linux/clk.h> 26#include <linux/clk.h>
@@ -105,6 +106,7 @@
105#define HDMITX_TOP_ADDR_REG 0x0 106#define HDMITX_TOP_ADDR_REG 0x0
106#define HDMITX_TOP_DATA_REG 0x4 107#define HDMITX_TOP_DATA_REG 0x4
107#define HDMITX_TOP_CTRL_REG 0x8 108#define HDMITX_TOP_CTRL_REG 0x8
109#define HDMITX_TOP_G12A_OFFSET 0x8000
108 110
109/* Controller Communication Channel */ 111/* Controller Communication Channel */
110#define HDMITX_DWC_ADDR_REG 0x10 112#define HDMITX_DWC_ADDR_REG 0x10
@@ -118,6 +120,8 @@
118#define HHI_HDMI_PHY_CNTL1 0x3a4 /* 0xe9 */ 120#define HHI_HDMI_PHY_CNTL1 0x3a4 /* 0xe9 */
119#define HHI_HDMI_PHY_CNTL2 0x3a8 /* 0xea */ 121#define HHI_HDMI_PHY_CNTL2 0x3a8 /* 0xea */
120#define HHI_HDMI_PHY_CNTL3 0x3ac /* 0xeb */ 122#define HHI_HDMI_PHY_CNTL3 0x3ac /* 0xeb */
123#define HHI_HDMI_PHY_CNTL4 0x3b0 /* 0xec */
124#define HHI_HDMI_PHY_CNTL5 0x3b4 /* 0xed */
121 125
122static DEFINE_SPINLOCK(reg_lock); 126static DEFINE_SPINLOCK(reg_lock);
123 127
@@ -127,12 +131,26 @@ enum meson_venc_source {
127 MESON_VENC_SOURCE_ENCP = 2, 131 MESON_VENC_SOURCE_ENCP = 2,
128}; 132};
129 133
134struct meson_dw_hdmi;
135
136struct meson_dw_hdmi_data {
137 unsigned int (*top_read)(struct meson_dw_hdmi *dw_hdmi,
138 unsigned int addr);
139 void (*top_write)(struct meson_dw_hdmi *dw_hdmi,
140 unsigned int addr, unsigned int data);
141 unsigned int (*dwc_read)(struct meson_dw_hdmi *dw_hdmi,
142 unsigned int addr);
143 void (*dwc_write)(struct meson_dw_hdmi *dw_hdmi,
144 unsigned int addr, unsigned int data);
145};
146
130struct meson_dw_hdmi { 147struct meson_dw_hdmi {
131 struct drm_encoder encoder; 148 struct drm_encoder encoder;
132 struct dw_hdmi_plat_data dw_plat_data; 149 struct dw_hdmi_plat_data dw_plat_data;
133 struct meson_drm *priv; 150 struct meson_drm *priv;
134 struct device *dev; 151 struct device *dev;
135 void __iomem *hdmitx; 152 void __iomem *hdmitx;
153 const struct meson_dw_hdmi_data *data;
136 struct reset_control *hdmitx_apb; 154 struct reset_control *hdmitx_apb;
137 struct reset_control *hdmitx_ctrl; 155 struct reset_control *hdmitx_ctrl;
138 struct reset_control *hdmitx_phy; 156 struct reset_control *hdmitx_phy;
@@ -174,6 +192,12 @@ static unsigned int dw_hdmi_top_read(struct meson_dw_hdmi *dw_hdmi,
174 return data; 192 return data;
175} 193}
176 194
195static unsigned int dw_hdmi_g12a_top_read(struct meson_dw_hdmi *dw_hdmi,
196 unsigned int addr)
197{
198 return readl(dw_hdmi->hdmitx + HDMITX_TOP_G12A_OFFSET + (addr << 2));
199}
200
177static inline void dw_hdmi_top_write(struct meson_dw_hdmi *dw_hdmi, 201static inline void dw_hdmi_top_write(struct meson_dw_hdmi *dw_hdmi,
178 unsigned int addr, unsigned int data) 202 unsigned int addr, unsigned int data)
179{ 203{
@@ -191,18 +215,24 @@ static inline void dw_hdmi_top_write(struct meson_dw_hdmi *dw_hdmi,
191 spin_unlock_irqrestore(&reg_lock, flags); 215 spin_unlock_irqrestore(&reg_lock, flags);
192} 216}
193 217
218static inline void dw_hdmi_g12a_top_write(struct meson_dw_hdmi *dw_hdmi,
219 unsigned int addr, unsigned int data)
220{
221 writel(data, dw_hdmi->hdmitx + HDMITX_TOP_G12A_OFFSET + (addr << 2));
222}
223
194/* Helper to change specific bits in PHY registers */ 224/* Helper to change specific bits in PHY registers */
195static inline void dw_hdmi_top_write_bits(struct meson_dw_hdmi *dw_hdmi, 225static inline void dw_hdmi_top_write_bits(struct meson_dw_hdmi *dw_hdmi,
196 unsigned int addr, 226 unsigned int addr,
197 unsigned int mask, 227 unsigned int mask,
198 unsigned int val) 228 unsigned int val)
199{ 229{
200 unsigned int data = dw_hdmi_top_read(dw_hdmi, addr); 230 unsigned int data = dw_hdmi->data->top_read(dw_hdmi, addr);
201 231
202 data &= ~mask; 232 data &= ~mask;
203 data |= val; 233 data |= val;
204 234
205 dw_hdmi_top_write(dw_hdmi, addr, data); 235 dw_hdmi->data->top_write(dw_hdmi, addr, data);
206} 236}
207 237
208static unsigned int dw_hdmi_dwc_read(struct meson_dw_hdmi *dw_hdmi, 238static unsigned int dw_hdmi_dwc_read(struct meson_dw_hdmi *dw_hdmi,
@@ -226,6 +256,12 @@ static unsigned int dw_hdmi_dwc_read(struct meson_dw_hdmi *dw_hdmi,
226 return data; 256 return data;
227} 257}
228 258
259static unsigned int dw_hdmi_g12a_dwc_read(struct meson_dw_hdmi *dw_hdmi,
260 unsigned int addr)
261{
262 return readb(dw_hdmi->hdmitx + addr);
263}
264
229static inline void dw_hdmi_dwc_write(struct meson_dw_hdmi *dw_hdmi, 265static inline void dw_hdmi_dwc_write(struct meson_dw_hdmi *dw_hdmi,
230 unsigned int addr, unsigned int data) 266 unsigned int addr, unsigned int data)
231{ 267{
@@ -243,18 +279,24 @@ static inline void dw_hdmi_dwc_write(struct meson_dw_hdmi *dw_hdmi,
243 spin_unlock_irqrestore(&reg_lock, flags); 279 spin_unlock_irqrestore(&reg_lock, flags);
244} 280}
245 281
282static inline void dw_hdmi_g12a_dwc_write(struct meson_dw_hdmi *dw_hdmi,
283 unsigned int addr, unsigned int data)
284{
285 writeb(data, dw_hdmi->hdmitx + addr);
286}
287
246/* Helper to change specific bits in controller registers */ 288/* Helper to change specific bits in controller registers */
247static inline void dw_hdmi_dwc_write_bits(struct meson_dw_hdmi *dw_hdmi, 289static inline void dw_hdmi_dwc_write_bits(struct meson_dw_hdmi *dw_hdmi,
248 unsigned int addr, 290 unsigned int addr,
249 unsigned int mask, 291 unsigned int mask,
250 unsigned int val) 292 unsigned int val)
251{ 293{
252 unsigned int data = dw_hdmi_dwc_read(dw_hdmi, addr); 294 unsigned int data = dw_hdmi->data->dwc_read(dw_hdmi, addr);
253 295
254 data &= ~mask; 296 data &= ~mask;
255 data |= val; 297 data |= val;
256 298
257 dw_hdmi_dwc_write(dw_hdmi, addr, data); 299 dw_hdmi->data->dwc_write(dw_hdmi, addr, data);
258} 300}
259 301
260/* Bridge */ 302/* Bridge */
@@ -300,6 +342,24 @@ static void meson_hdmi_phy_setup_mode(struct meson_dw_hdmi *dw_hdmi,
300 regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, 0x33632122); 342 regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, 0x33632122);
301 regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL3, 0x2000115b); 343 regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL3, 0x2000115b);
302 } 344 }
345 } else if (dw_hdmi_is_compatible(dw_hdmi,
346 "amlogic,meson-g12a-dw-hdmi")) {
347 if (pixel_clock >= 371250) {
348 /* 5.94Gbps, 3.7125Gbps */
349 regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, 0x37eb65c4);
350 regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL3, 0x2ab0ff3b);
351 regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL5, 0x0000080b);
352 } else if (pixel_clock >= 297000) {
353 /* 2.97Gbps */
354 regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, 0x33eb6262);
355 regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL3, 0x2ab0ff3b);
356 regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL5, 0x00000003);
357 } else {
358 /* 1.485Gbps, and below */
359 regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, 0x33eb4242);
360 regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL3, 0x2ab0ff3b);
361 regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL5, 0x00000003);
362 }
303 } 363 }
304} 364}
305 365
@@ -375,7 +435,7 @@ static int dw_hdmi_phy_init(struct dw_hdmi *hdmi, void *data,
375 regmap_update_bits(priv->hhi, HHI_MEM_PD_REG0, 0xff << 8, 0); 435 regmap_update_bits(priv->hhi, HHI_MEM_PD_REG0, 0xff << 8, 0);
376 436
377 /* Bring out of reset */ 437 /* Bring out of reset */
378 dw_hdmi_top_write(dw_hdmi, HDMITX_TOP_SW_RESET, 0); 438 dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_SW_RESET, 0);
379 439
380 /* Enable internal pixclk, tmds_clk, spdif_clk, i2s_clk, cecclk */ 440 /* Enable internal pixclk, tmds_clk, spdif_clk, i2s_clk, cecclk */
381 dw_hdmi_top_write_bits(dw_hdmi, HDMITX_TOP_CLK_CNTL, 441 dw_hdmi_top_write_bits(dw_hdmi, HDMITX_TOP_CLK_CNTL,
@@ -384,24 +444,25 @@ static int dw_hdmi_phy_init(struct dw_hdmi *hdmi, void *data,
384 0x3 << 4, 0x3 << 4); 444 0x3 << 4, 0x3 << 4);
385 445
386 /* Enable normal output to PHY */ 446 /* Enable normal output to PHY */
387 dw_hdmi_top_write(dw_hdmi, HDMITX_TOP_BIST_CNTL, BIT(12)); 447 dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_BIST_CNTL, BIT(12));
388 448
389 /* TMDS pattern setup (TOFIX Handle the YUV420 case) */ 449 /* TMDS pattern setup (TOFIX Handle the YUV420 case) */
390 if (mode->clock > 340000) { 450 if (mode->clock > 340000) {
391 dw_hdmi_top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_01, 0); 451 dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_01,
392 dw_hdmi_top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_23, 452 0);
453 dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_23,
393 0x03ff03ff); 454 0x03ff03ff);
394 } else { 455 } else {
395 dw_hdmi_top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_01, 456 dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_01,
396 0x001f001f); 457 0x001f001f);
397 dw_hdmi_top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_23, 458 dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_23,
398 0x001f001f); 459 0x001f001f);
399 } 460 }
400 461
401 /* Load TMDS pattern */ 462 /* Load TMDS pattern */
402 dw_hdmi_top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_CNTL, 0x1); 463 dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_CNTL, 0x1);
403 msleep(20); 464 msleep(20);
404 dw_hdmi_top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_CNTL, 0x2); 465 dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_CNTL, 0x2);
405 466
406 /* Setup PHY parameters */ 467 /* Setup PHY parameters */
407 meson_hdmi_phy_setup_mode(dw_hdmi, mode); 468 meson_hdmi_phy_setup_mode(dw_hdmi, mode);
@@ -412,7 +473,8 @@ static int dw_hdmi_phy_init(struct dw_hdmi *hdmi, void *data,
412 473
413 /* BIT_INVERT */ 474 /* BIT_INVERT */
414 if (dw_hdmi_is_compatible(dw_hdmi, "amlogic,meson-gxl-dw-hdmi") || 475 if (dw_hdmi_is_compatible(dw_hdmi, "amlogic,meson-gxl-dw-hdmi") ||
415 dw_hdmi_is_compatible(dw_hdmi, "amlogic,meson-gxm-dw-hdmi")) 476 dw_hdmi_is_compatible(dw_hdmi, "amlogic,meson-gxm-dw-hdmi") ||
477 dw_hdmi_is_compatible(dw_hdmi, "amlogic,meson-g12a-dw-hdmi"))
416 regmap_update_bits(priv->hhi, HHI_HDMI_PHY_CNTL1, 478 regmap_update_bits(priv->hhi, HHI_HDMI_PHY_CNTL1,
417 BIT(17), 0); 479 BIT(17), 0);
418 else 480 else
@@ -480,7 +542,7 @@ static enum drm_connector_status dw_hdmi_read_hpd(struct dw_hdmi *hdmi,
480{ 542{
481 struct meson_dw_hdmi *dw_hdmi = (struct meson_dw_hdmi *)data; 543 struct meson_dw_hdmi *dw_hdmi = (struct meson_dw_hdmi *)data;
482 544
483 return !!dw_hdmi_top_read(dw_hdmi, HDMITX_TOP_STAT0) ? 545 return !!dw_hdmi->data->top_read(dw_hdmi, HDMITX_TOP_STAT0) ?
484 connector_status_connected : connector_status_disconnected; 546 connector_status_connected : connector_status_disconnected;
485} 547}
486 548
@@ -490,11 +552,11 @@ static void dw_hdmi_setup_hpd(struct dw_hdmi *hdmi,
490 struct meson_dw_hdmi *dw_hdmi = (struct meson_dw_hdmi *)data; 552 struct meson_dw_hdmi *dw_hdmi = (struct meson_dw_hdmi *)data;
491 553
492 /* Setup HPD Filter */ 554 /* Setup HPD Filter */
493 dw_hdmi_top_write(dw_hdmi, HDMITX_TOP_HPD_FILTER, 555 dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_HPD_FILTER,
494 (0xa << 12) | 0xa0); 556 (0xa << 12) | 0xa0);
495 557
496 /* Clear interrupts */ 558 /* Clear interrupts */
497 dw_hdmi_top_write(dw_hdmi, HDMITX_TOP_INTR_STAT_CLR, 559 dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_INTR_STAT_CLR,
498 HDMITX_TOP_INTR_HPD_RISE | HDMITX_TOP_INTR_HPD_FALL); 560 HDMITX_TOP_INTR_HPD_RISE | HDMITX_TOP_INTR_HPD_FALL);
499 561
500 /* Unmask interrupts */ 562 /* Unmask interrupts */
@@ -515,8 +577,8 @@ static irqreturn_t dw_hdmi_top_irq(int irq, void *dev_id)
515 struct meson_dw_hdmi *dw_hdmi = dev_id; 577 struct meson_dw_hdmi *dw_hdmi = dev_id;
516 u32 stat; 578 u32 stat;
517 579
518 stat = dw_hdmi_top_read(dw_hdmi, HDMITX_TOP_INTR_STAT); 580 stat = dw_hdmi->data->top_read(dw_hdmi, HDMITX_TOP_INTR_STAT);
519 dw_hdmi_top_write(dw_hdmi, HDMITX_TOP_INTR_STAT_CLR, stat); 581 dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_INTR_STAT_CLR, stat);
520 582
521 /* HPD Events, handle in the threaded interrupt handler */ 583 /* HPD Events, handle in the threaded interrupt handler */
522 if (stat & (HDMITX_TOP_INTR_HPD_RISE | HDMITX_TOP_INTR_HPD_FALL)) { 584 if (stat & (HDMITX_TOP_INTR_HPD_RISE | HDMITX_TOP_INTR_HPD_FALL)) {
@@ -685,7 +747,9 @@ static const struct drm_encoder_helper_funcs
685static int meson_dw_hdmi_reg_read(void *context, unsigned int reg, 747static int meson_dw_hdmi_reg_read(void *context, unsigned int reg,
686 unsigned int *result) 748 unsigned int *result)
687{ 749{
688 *result = dw_hdmi_dwc_read(context, reg); 750 struct meson_dw_hdmi *dw_hdmi = context;
751
752 *result = dw_hdmi->data->dwc_read(dw_hdmi, reg);
689 753
690 return 0; 754 return 0;
691 755
@@ -694,7 +758,9 @@ static int meson_dw_hdmi_reg_read(void *context, unsigned int reg,
694static int meson_dw_hdmi_reg_write(void *context, unsigned int reg, 758static int meson_dw_hdmi_reg_write(void *context, unsigned int reg,
695 unsigned int val) 759 unsigned int val)
696{ 760{
697 dw_hdmi_dwc_write(context, reg, val); 761 struct meson_dw_hdmi *dw_hdmi = context;
762
763 dw_hdmi->data->dwc_write(dw_hdmi, reg, val);
698 764
699 return 0; 765 return 0;
700} 766}
@@ -708,6 +774,20 @@ static const struct regmap_config meson_dw_hdmi_regmap_config = {
708 .fast_io = true, 774 .fast_io = true,
709}; 775};
710 776
777static const struct meson_dw_hdmi_data meson_dw_hdmi_gx_data = {
778 .top_read = dw_hdmi_top_read,
779 .top_write = dw_hdmi_top_write,
780 .dwc_read = dw_hdmi_dwc_read,
781 .dwc_write = dw_hdmi_dwc_write,
782};
783
784static const struct meson_dw_hdmi_data meson_dw_hdmi_g12a_data = {
785 .top_read = dw_hdmi_g12a_top_read,
786 .top_write = dw_hdmi_g12a_top_write,
787 .dwc_read = dw_hdmi_g12a_dwc_read,
788 .dwc_write = dw_hdmi_g12a_dwc_write,
789};
790
711static bool meson_hdmi_connector_is_available(struct device *dev) 791static bool meson_hdmi_connector_is_available(struct device *dev)
712{ 792{
713 struct device_node *ep, *remote; 793 struct device_node *ep, *remote;
@@ -734,6 +814,7 @@ static int meson_dw_hdmi_bind(struct device *dev, struct device *master,
734 void *data) 814 void *data)
735{ 815{
736 struct platform_device *pdev = to_platform_device(dev); 816 struct platform_device *pdev = to_platform_device(dev);
817 const struct meson_dw_hdmi_data *match;
737 struct meson_dw_hdmi *meson_dw_hdmi; 818 struct meson_dw_hdmi *meson_dw_hdmi;
738 struct drm_device *drm = data; 819 struct drm_device *drm = data;
739 struct meson_drm *priv = drm->dev_private; 820 struct meson_drm *priv = drm->dev_private;
@@ -750,6 +831,12 @@ static int meson_dw_hdmi_bind(struct device *dev, struct device *master,
750 return -ENODEV; 831 return -ENODEV;
751 } 832 }
752 833
834 match = of_device_get_match_data(&pdev->dev);
835 if (!match) {
836 dev_err(&pdev->dev, "failed to get match data\n");
837 return -ENODEV;
838 }
839
753 meson_dw_hdmi = devm_kzalloc(dev, sizeof(*meson_dw_hdmi), 840 meson_dw_hdmi = devm_kzalloc(dev, sizeof(*meson_dw_hdmi),
754 GFP_KERNEL); 841 GFP_KERNEL);
755 if (!meson_dw_hdmi) 842 if (!meson_dw_hdmi)
@@ -757,6 +844,7 @@ static int meson_dw_hdmi_bind(struct device *dev, struct device *master,
757 844
758 meson_dw_hdmi->priv = priv; 845 meson_dw_hdmi->priv = priv;
759 meson_dw_hdmi->dev = dev; 846 meson_dw_hdmi->dev = dev;
847 meson_dw_hdmi->data = match;
760 dw_plat_data = &meson_dw_hdmi->dw_plat_data; 848 dw_plat_data = &meson_dw_hdmi->dw_plat_data;
761 encoder = &meson_dw_hdmi->encoder; 849 encoder = &meson_dw_hdmi->encoder;
762 850
@@ -857,24 +945,28 @@ static int meson_dw_hdmi_bind(struct device *dev, struct device *master,
857 reset_control_reset(meson_dw_hdmi->hdmitx_phy); 945 reset_control_reset(meson_dw_hdmi->hdmitx_phy);
858 946
859 /* Enable APB3 fail on error */ 947 /* Enable APB3 fail on error */
860 writel_bits_relaxed(BIT(15), BIT(15), 948 if (!meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu")) {
861 meson_dw_hdmi->hdmitx + HDMITX_TOP_CTRL_REG); 949 writel_bits_relaxed(BIT(15), BIT(15),
862 writel_bits_relaxed(BIT(15), BIT(15), 950 meson_dw_hdmi->hdmitx + HDMITX_TOP_CTRL_REG);
863 meson_dw_hdmi->hdmitx + HDMITX_DWC_CTRL_REG); 951 writel_bits_relaxed(BIT(15), BIT(15),
952 meson_dw_hdmi->hdmitx + HDMITX_DWC_CTRL_REG);
953 }
864 954
865 /* Bring out of reset */ 955 /* Bring out of reset */
866 dw_hdmi_top_write(meson_dw_hdmi, HDMITX_TOP_SW_RESET, 0); 956 meson_dw_hdmi->data->top_write(meson_dw_hdmi,
957 HDMITX_TOP_SW_RESET, 0);
867 958
868 msleep(20); 959 msleep(20);
869 960
870 dw_hdmi_top_write(meson_dw_hdmi, HDMITX_TOP_CLK_CNTL, 0xff); 961 meson_dw_hdmi->data->top_write(meson_dw_hdmi,
962 HDMITX_TOP_CLK_CNTL, 0xff);
871 963
872 /* Enable HDMI-TX Interrupt */ 964 /* Enable HDMI-TX Interrupt */
873 dw_hdmi_top_write(meson_dw_hdmi, HDMITX_TOP_INTR_STAT_CLR, 965 meson_dw_hdmi->data->top_write(meson_dw_hdmi, HDMITX_TOP_INTR_STAT_CLR,
874 HDMITX_TOP_INTR_CORE); 966 HDMITX_TOP_INTR_CORE);
875 967
876 dw_hdmi_top_write(meson_dw_hdmi, HDMITX_TOP_INTR_MASKN, 968 meson_dw_hdmi->data->top_write(meson_dw_hdmi, HDMITX_TOP_INTR_MASKN,
877 HDMITX_TOP_INTR_CORE); 969 HDMITX_TOP_INTR_CORE);
878 970
879 /* Bridge / Connector */ 971 /* Bridge / Connector */
880 972
@@ -923,9 +1015,14 @@ static int meson_dw_hdmi_remove(struct platform_device *pdev)
923} 1015}
924 1016
925static const struct of_device_id meson_dw_hdmi_of_table[] = { 1017static const struct of_device_id meson_dw_hdmi_of_table[] = {
926 { .compatible = "amlogic,meson-gxbb-dw-hdmi" }, 1018 { .compatible = "amlogic,meson-gxbb-dw-hdmi",
927 { .compatible = "amlogic,meson-gxl-dw-hdmi" }, 1019 .data = &meson_dw_hdmi_gx_data },
928 { .compatible = "amlogic,meson-gxm-dw-hdmi" }, 1020 { .compatible = "amlogic,meson-gxl-dw-hdmi",
1021 .data = &meson_dw_hdmi_gx_data },
1022 { .compatible = "amlogic,meson-gxm-dw-hdmi",
1023 .data = &meson_dw_hdmi_gx_data },
1024 { .compatible = "amlogic,meson-g12a-dw-hdmi",
1025 .data = &meson_dw_hdmi_g12a_data },
929 { } 1026 { }
930}; 1027};
931MODULE_DEVICE_TABLE(of, meson_dw_hdmi_of_table); 1028MODULE_DEVICE_TABLE(of, meson_dw_hdmi_of_table);
diff --git a/drivers/gpu/drm/meson/meson_dw_hdmi.h b/drivers/gpu/drm/meson/meson_dw_hdmi.h
index 0b81183125e3..03e2f0c1a2d5 100644
--- a/drivers/gpu/drm/meson/meson_dw_hdmi.h
+++ b/drivers/gpu/drm/meson/meson_dw_hdmi.h
@@ -21,9 +21,12 @@
21#define __MESON_DW_HDMI_H 21#define __MESON_DW_HDMI_H
22 22
23/* 23/*
24 * Bit 7 RW Reserved. Default 1. 24 * Bit 15-10: RW Reserved. Default 1 starting from G12A
25 * Bit 6 RW Reserved. Default 1. 25 * Bit 9 RW sw_reset_i2c starting from G12A
26 * Bit 5 RW Reserved. Default 1. 26 * Bit 8 RW sw_reset_axiarb starting from G12A
27 * Bit 7 RW Reserved. Default 1, sw_reset_emp starting from G12A
28 * Bit 6 RW Reserved. Default 1, sw_reset_flt starting from G12A
29 * Bit 5 RW Reserved. Default 1, sw_reset_hdcp22 starting from G12A
27 * Bit 4 RW sw_reset_phyif: PHY interface. 1=Apply reset; 0=Release from reset. 30 * Bit 4 RW sw_reset_phyif: PHY interface. 1=Apply reset; 0=Release from reset.
28 * Default 1. 31 * Default 1.
29 * Bit 3 RW sw_reset_intr: interrupt module. 1=Apply reset; 32 * Bit 3 RW sw_reset_intr: interrupt module. 1=Apply reset;
@@ -39,12 +42,16 @@
39#define HDMITX_TOP_SW_RESET (0x000) 42#define HDMITX_TOP_SW_RESET (0x000)
40 43
41/* 44/*
45 * Bit 31 RW free_clk_en: 0=Enable clock gating for power saving; 1= Disable
42 * Bit 12 RW i2s_ws_inv:1=Invert i2s_ws; 0=No invert. Default 0. 46 * Bit 12 RW i2s_ws_inv:1=Invert i2s_ws; 0=No invert. Default 0.
43 * Bit 11 RW i2s_clk_inv: 1=Invert i2s_clk; 0=No invert. Default 0. 47 * Bit 11 RW i2s_clk_inv: 1=Invert i2s_clk; 0=No invert. Default 0.
44 * Bit 10 RW spdif_clk_inv: 1=Invert spdif_clk; 0=No invert. Default 0. 48 * Bit 10 RW spdif_clk_inv: 1=Invert spdif_clk; 0=No invert. Default 0.
45 * Bit 9 RW tmds_clk_inv: 1=Invert tmds_clk; 0=No invert. Default 0. 49 * Bit 9 RW tmds_clk_inv: 1=Invert tmds_clk; 0=No invert. Default 0.
46 * Bit 8 RW pixel_clk_inv: 1=Invert pixel_clk; 0=No invert. Default 0. 50 * Bit 8 RW pixel_clk_inv: 1=Invert pixel_clk; 0=No invert. Default 0.
47 * Bit 4 RW cec_clk_en: 1=enable cec_clk; 0=disable. Default 0. 51 * Bit 7 RW hdcp22_skpclk_en: starting from G12A, 1=enable; 0=disable
52 * Bit 6 RW hdcp22_esmclk_en: starting from G12A, 1=enable; 0=disable
53 * Bit 5 RW hdcp22_tmdsclk_en: starting from G12A, 1=enable; 0=disable
54 * Bit 4 RW cec_clk_en: 1=enable cec_clk; 0=disable. Default 0. Reserved for G12A
48 * Bit 3 RW i2s_clk_en: 1=enable i2s_clk; 0=disable. Default 0. 55 * Bit 3 RW i2s_clk_en: 1=enable i2s_clk; 0=disable. Default 0.
49 * Bit 2 RW spdif_clk_en: 1=enable spdif_clk; 0=disable. Default 0. 56 * Bit 2 RW spdif_clk_en: 1=enable spdif_clk; 0=disable. Default 0.
50 * Bit 1 RW tmds_clk_en: 1=enable tmds_clk; 0=disable. Default 0. 57 * Bit 1 RW tmds_clk_en: 1=enable tmds_clk; 0=disable. Default 0.
@@ -53,6 +60,8 @@
53#define HDMITX_TOP_CLK_CNTL (0x001) 60#define HDMITX_TOP_CLK_CNTL (0x001)
54 61
55/* 62/*
63 * Bit 31:28 RW rxsense_glitch_width: starting from G12A
64 * Bit 27:16 RW rxsense_valid_width: starting from G12A
56 * Bit 11: 0 RW hpd_valid_width: filter out width <= M*1024. Default 0. 65 * Bit 11: 0 RW hpd_valid_width: filter out width <= M*1024. Default 0.
57 * Bit 15:12 RW hpd_glitch_width: filter out glitch <= N. Default 0. 66 * Bit 15:12 RW hpd_glitch_width: filter out glitch <= N. Default 0.
58 */ 67 */
@@ -61,6 +70,9 @@
61/* 70/*
62 * intr_maskn: MASK_N, one bit per interrupt source. 71 * intr_maskn: MASK_N, one bit per interrupt source.
63 * 1=Enable interrupt source; 0=Disable interrupt source. Default 0. 72 * 1=Enable interrupt source; 0=Disable interrupt source. Default 0.
73 * [ 7] rxsense_fall starting from G12A
74 * [ 6] rxsense_rise starting from G12A
75 * [ 5] err_i2c_timeout starting from G12A
64 * [ 4] hdcp22_rndnum_err 76 * [ 4] hdcp22_rndnum_err
65 * [ 3] nonce_rfrsh_rise 77 * [ 3] nonce_rfrsh_rise
66 * [ 2] hpd_fall_intr 78 * [ 2] hpd_fall_intr
@@ -73,6 +85,9 @@
73 * Bit 30: 0 RW intr_stat: For each bit, write 1 to manually set the interrupt 85 * Bit 30: 0 RW intr_stat: For each bit, write 1 to manually set the interrupt
74 * bit, read back the interrupt status. 86 * bit, read back the interrupt status.
75 * Bit 31 R IP interrupt status 87 * Bit 31 R IP interrupt status
88 * Bit 7 RW rxsense_fall starting from G12A
89 * Bit 6 RW rxsense_rise starting from G12A
90 * Bit 5 RW err_i2c_timeout starting from G12A
76 * Bit 2 RW hpd_fall 91 * Bit 2 RW hpd_fall
77 * Bit 1 RW hpd_rise 92 * Bit 1 RW hpd_rise
78 * Bit 0 RW IP interrupt 93 * Bit 0 RW IP interrupt
@@ -80,6 +95,9 @@
80#define HDMITX_TOP_INTR_STAT (0x004) 95#define HDMITX_TOP_INTR_STAT (0x004)
81 96
82/* 97/*
98 * [7] rxsense_fall starting from G12A
99 * [6] rxsense_rise starting from G12A
100 * [5] err_i2c_timeout starting from G12A
83 * [4] hdcp22_rndnum_err 101 * [4] hdcp22_rndnum_err
84 * [3] nonce_rfrsh_rise 102 * [3] nonce_rfrsh_rise
85 * [2] hpd_fall 103 * [2] hpd_fall
@@ -91,6 +109,8 @@
91#define HDMITX_TOP_INTR_CORE BIT(0) 109#define HDMITX_TOP_INTR_CORE BIT(0)
92#define HDMITX_TOP_INTR_HPD_RISE BIT(1) 110#define HDMITX_TOP_INTR_HPD_RISE BIT(1)
93#define HDMITX_TOP_INTR_HPD_FALL BIT(2) 111#define HDMITX_TOP_INTR_HPD_FALL BIT(2)
112#define HDMITX_TOP_INTR_RXSENSE_RISE BIT(6)
113#define HDMITX_TOP_INTR_RXSENSE_FALL BIT(7)
94 114
95/* Bit 14:12 RW tmds_sel: 3'b000=Output zero; 3'b001=Output normal TMDS data; 115/* Bit 14:12 RW tmds_sel: 3'b000=Output zero; 3'b001=Output normal TMDS data;
96 * 3'b010=Output PRBS data; 3'b100=Output shift pattern. Default 0. 116 * 3'b010=Output PRBS data; 3'b100=Output shift pattern. Default 0.
@@ -140,7 +160,9 @@
140 */ 160 */
141#define HDMITX_TOP_REVOCMEM_STAT (0x00D) 161#define HDMITX_TOP_REVOCMEM_STAT (0x00D)
142 162
143/* Bit 0 R filtered HPD status. */ 163/* Bit 1 R filtered RxSense status
164 * Bit 0 R filtered HPD status.
165 */
144#define HDMITX_TOP_STAT0 (0x00E) 166#define HDMITX_TOP_STAT0 (0x00E)
145 167
146#endif /* __MESON_DW_HDMI_H */ 168#endif /* __MESON_DW_HDMI_H */
diff --git a/drivers/gpu/drm/meson/meson_overlay.c b/drivers/gpu/drm/meson/meson_overlay.c
index b54a22e483b9..bdbf925ff3e8 100644
--- a/drivers/gpu/drm/meson/meson_overlay.c
+++ b/drivers/gpu/drm/meson/meson_overlay.c
@@ -516,8 +516,14 @@ static void meson_overlay_atomic_disable(struct drm_plane *plane,
516 priv->viu.vd1_enabled = false; 516 priv->viu.vd1_enabled = false;
517 517
518 /* Disable VD1 */ 518 /* Disable VD1 */
519 writel_bits_relaxed(VPP_VD1_POSTBLEND | VPP_VD1_PREBLEND, 0, 519 if (meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu")) {
520 priv->io_base + _REG(VPP_MISC)); 520 writel_relaxed(0, priv->io_base + _REG(VD1_BLEND_SRC_CTRL));
521 writel_relaxed(0, priv->io_base + _REG(VD2_BLEND_SRC_CTRL));
522 writel_relaxed(0, priv->io_base + _REG(VD1_IF0_GEN_REG + 0x17b0));
523 writel_relaxed(0, priv->io_base + _REG(VD2_IF0_GEN_REG + 0x17b0));
524 } else
525 writel_bits_relaxed(VPP_VD1_POSTBLEND | VPP_VD1_PREBLEND, 0,
526 priv->io_base + _REG(VPP_MISC));
521 527
522} 528}
523 529
diff --git a/drivers/gpu/drm/meson/meson_plane.c b/drivers/gpu/drm/meson/meson_plane.c
index b7786218cb10..bf8f1fab63aa 100644
--- a/drivers/gpu/drm/meson/meson_plane.c
+++ b/drivers/gpu/drm/meson/meson_plane.c
@@ -294,6 +294,13 @@ static void meson_plane_atomic_update(struct drm_plane *plane,
294 priv->viu.osd1_blk0_cfg[3] = ((dest.x2 - 1) << 16) | dest.x1; 294 priv->viu.osd1_blk0_cfg[3] = ((dest.x2 - 1) << 16) | dest.x1;
295 priv->viu.osd1_blk0_cfg[4] = ((dest.y2 - 1) << 16) | dest.y1; 295 priv->viu.osd1_blk0_cfg[4] = ((dest.y2 - 1) << 16) | dest.y1;
296 296
297 if (meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu")) {
298 priv->viu.osd_blend_din0_scope_h = ((dest.x2 - 1) << 16) | dest.x1;
299 priv->viu.osd_blend_din0_scope_v = ((dest.y2 - 1) << 16) | dest.y1;
300 priv->viu.osb_blend0_size = dst_h << 16 | dst_w;
301 priv->viu.osb_blend1_size = dst_h << 16 | dst_w;
302 }
303
297 /* Update Canvas with buffer address */ 304 /* Update Canvas with buffer address */
298 gem = drm_fb_cma_get_gem_obj(fb, 0); 305 gem = drm_fb_cma_get_gem_obj(fb, 0);
299 306
@@ -320,8 +327,12 @@ static void meson_plane_atomic_disable(struct drm_plane *plane,
320 struct meson_drm *priv = meson_plane->priv; 327 struct meson_drm *priv = meson_plane->priv;
321 328
322 /* Disable OSD1 */ 329 /* Disable OSD1 */
323 writel_bits_relaxed(VPP_OSD1_POSTBLEND, 0, 330 if (meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu"))
324 priv->io_base + _REG(VPP_MISC)); 331 writel_bits_relaxed(BIT(0) | BIT(21), 0,
332 priv->io_base + _REG(VIU_OSD1_CTRL_STAT));
333 else
334 writel_bits_relaxed(VPP_OSD1_POSTBLEND, 0,
335 priv->io_base + _REG(VPP_MISC));
325 336
326 meson_plane->enabled = false; 337 meson_plane->enabled = false;
327 338
diff --git a/drivers/gpu/drm/meson/meson_registers.h b/drivers/gpu/drm/meson/meson_registers.h
index 5c7e02c703bc..cfaf90501bb1 100644
--- a/drivers/gpu/drm/meson/meson_registers.h
+++ b/drivers/gpu/drm/meson/meson_registers.h
@@ -216,6 +216,29 @@
216#define VIU_OSD2_FIFO_CTRL_STAT 0x1a4b 216#define VIU_OSD2_FIFO_CTRL_STAT 0x1a4b
217#define VIU_OSD2_TEST_RDDATA 0x1a4c 217#define VIU_OSD2_TEST_RDDATA 0x1a4c
218#define VIU_OSD2_PROT_CTRL 0x1a4e 218#define VIU_OSD2_PROT_CTRL 0x1a4e
219#define VIU_OSD2_MALI_UNPACK_CTRL 0x1abd
220#define VIU_OSD2_DIMM_CTRL 0x1acf
221
222#define VIU_OSD3_CTRL_STAT 0x3d80
223#define VIU_OSD3_CTRL_STAT2 0x3d81
224#define VIU_OSD3_COLOR_ADDR 0x3d82
225#define VIU_OSD3_COLOR 0x3d83
226#define VIU_OSD3_TCOLOR_AG0 0x3d84
227#define VIU_OSD3_TCOLOR_AG1 0x3d85
228#define VIU_OSD3_TCOLOR_AG2 0x3d86
229#define VIU_OSD3_TCOLOR_AG3 0x3d87
230#define VIU_OSD3_BLK0_CFG_W0 0x3d88
231#define VIU_OSD3_BLK0_CFG_W1 0x3d8c
232#define VIU_OSD3_BLK0_CFG_W2 0x3d90
233#define VIU_OSD3_BLK0_CFG_W3 0x3d94
234#define VIU_OSD3_BLK0_CFG_W4 0x3d98
235#define VIU_OSD3_BLK1_CFG_W4 0x3d99
236#define VIU_OSD3_BLK2_CFG_W4 0x3d9a
237#define VIU_OSD3_FIFO_CTRL_STAT 0x3d9c
238#define VIU_OSD3_TEST_RDDATA 0x3d9d
239#define VIU_OSD3_PROT_CTRL 0x3d9e
240#define VIU_OSD3_MALI_UNPACK_CTRL 0x3d9f
241#define VIU_OSD3_DIMM_CTRL 0x3da0
219 242
220#define VD1_IF0_GEN_REG 0x1a50 243#define VD1_IF0_GEN_REG 0x1a50
221#define VD1_IF0_CANVAS0 0x1a51 244#define VD1_IF0_CANVAS0 0x1a51
@@ -287,6 +310,27 @@
287#define VIU_OSD1_MATRIX_COEF31_32 0x1a9e 310#define VIU_OSD1_MATRIX_COEF31_32 0x1a9e
288#define VIU_OSD1_MATRIX_COEF40_41 0x1a9f 311#define VIU_OSD1_MATRIX_COEF40_41 0x1a9f
289#define VD1_IF0_GEN_REG3 0x1aa7 312#define VD1_IF0_GEN_REG3 0x1aa7
313
314#define VIU_OSD_BLENDO_H_START_END 0x1aa9
315#define VIU_OSD_BLENDO_V_START_END 0x1aaa
316#define VIU_OSD_BLEND_GEN_CTRL0 0x1aab
317#define VIU_OSD_BLEND_GEN_CTRL1 0x1aac
318#define VIU_OSD_BLEND_DUMMY_DATA 0x1aad
319#define VIU_OSD_BLEND_CURRENT_XY 0x1aae
320
321#define VIU_OSD2_MATRIX_CTRL 0x1ab0
322#define VIU_OSD2_MATRIX_COEF00_01 0x1ab1
323#define VIU_OSD2_MATRIX_COEF02_10 0x1ab2
324#define VIU_OSD2_MATRIX_COEF11_12 0x1ab3
325#define VIU_OSD2_MATRIX_COEF20_21 0x1ab4
326#define VIU_OSD2_MATRIX_COEF22 0x1ab5
327#define VIU_OSD2_MATRIX_OFFSET0_1 0x1ab6
328#define VIU_OSD2_MATRIX_OFFSET2 0x1ab7
329#define VIU_OSD2_MATRIX_PRE_OFFSET0_1 0x1ab8
330#define VIU_OSD2_MATRIX_PRE_OFFSET2 0x1ab9
331#define VIU_OSD2_MATRIX_PROBE_COLOR 0x1aba
332#define VIU_OSD2_MATRIX_HL_COLOR 0x1abb
333#define VIU_OSD2_MATRIX_PROBE_POS 0x1abc
290#define VIU_OSD1_EOTF_CTL 0x1ad4 334#define VIU_OSD1_EOTF_CTL 0x1ad4
291#define VIU_OSD1_EOTF_COEF00_01 0x1ad5 335#define VIU_OSD1_EOTF_COEF00_01 0x1ad5
292#define VIU_OSD1_EOTF_COEF02_10 0x1ad6 336#define VIU_OSD1_EOTF_COEF02_10 0x1ad6
@@ -481,6 +525,82 @@
481#define VPP_OSD_SCALE_COEF 0x1dcd 525#define VPP_OSD_SCALE_COEF 0x1dcd
482#define VPP_INT_LINE_NUM 0x1dce 526#define VPP_INT_LINE_NUM 0x1dce
483 527
528#define VPP_WRAP_OSD1_MATRIX_COEF00_01 0x3d60
529#define VPP_WRAP_OSD1_MATRIX_COEF02_10 0x3d61
530#define VPP_WRAP_OSD1_MATRIX_COEF11_12 0x3d62
531#define VPP_WRAP_OSD1_MATRIX_COEF20_21 0x3d63
532#define VPP_WRAP_OSD1_MATRIX_COEF22 0x3d64
533#define VPP_WRAP_OSD1_MATRIX_COEF13_14 0x3d65
534#define VPP_WRAP_OSD1_MATRIX_COEF23_24 0x3d66
535#define VPP_WRAP_OSD1_MATRIX_COEF15_25 0x3d67
536#define VPP_WRAP_OSD1_MATRIX_CLIP 0x3d68
537#define VPP_WRAP_OSD1_MATRIX_OFFSET0_1 0x3d69
538#define VPP_WRAP_OSD1_MATRIX_OFFSET2 0x3d6a
539#define VPP_WRAP_OSD1_MATRIX_PRE_OFFSET0_1 0x3d6b
540#define VPP_WRAP_OSD1_MATRIX_PRE_OFFSET2 0x3d6c
541#define VPP_WRAP_OSD1_MATRIX_EN_CTRL 0x3d6d
542
543#define VPP_WRAP_OSD2_MATRIX_COEF00_01 0x3d70
544#define VPP_WRAP_OSD2_MATRIX_COEF02_10 0x3d71
545#define VPP_WRAP_OSD2_MATRIX_COEF11_12 0x3d72
546#define VPP_WRAP_OSD2_MATRIX_COEF20_21 0x3d73
547#define VPP_WRAP_OSD2_MATRIX_COEF22 0x3d74
548#define VPP_WRAP_OSD2_MATRIX_COEF13_14 0x3d75
549#define VPP_WRAP_OSD2_MATRIX_COEF23_24 0x3d76
550#define VPP_WRAP_OSD2_MATRIX_COEF15_25 0x3d77
551#define VPP_WRAP_OSD2_MATRIX_CLIP 0x3d78
552#define VPP_WRAP_OSD2_MATRIX_OFFSET0_1 0x3d79
553#define VPP_WRAP_OSD2_MATRIX_OFFSET2 0x3d7a
554#define VPP_WRAP_OSD2_MATRIX_PRE_OFFSET0_1 0x3d7b
555#define VPP_WRAP_OSD2_MATRIX_PRE_OFFSET2 0x3d7c
556#define VPP_WRAP_OSD2_MATRIX_EN_CTRL 0x3d7d
557
558#define VPP_WRAP_OSD3_MATRIX_COEF00_01 0x3db0
559#define VPP_WRAP_OSD3_MATRIX_COEF02_10 0x3db1
560#define VPP_WRAP_OSD3_MATRIX_COEF11_12 0x3db2
561#define VPP_WRAP_OSD3_MATRIX_COEF20_21 0x3db3
562#define VPP_WRAP_OSD3_MATRIX_COEF22 0x3db4
563#define VPP_WRAP_OSD3_MATRIX_COEF13_14 0x3db5
564#define VPP_WRAP_OSD3_MATRIX_COEF23_24 0x3db6
565#define VPP_WRAP_OSD3_MATRIX_COEF15_25 0x3db7
566#define VPP_WRAP_OSD3_MATRIX_CLIP 0x3db8
567#define VPP_WRAP_OSD3_MATRIX_OFFSET0_1 0x3db9
568#define VPP_WRAP_OSD3_MATRIX_OFFSET2 0x3dba
569#define VPP_WRAP_OSD3_MATRIX_PRE_OFFSET0_1 0x3dbb
570#define VPP_WRAP_OSD3_MATRIX_PRE_OFFSET2 0x3dbc
571#define VPP_WRAP_OSD3_MATRIX_EN_CTRL 0x3dbd
572
573/* osd2 scaler */
574#define OSD2_VSC_PHASE_STEP 0x3d00
575#define OSD2_VSC_INI_PHASE 0x3d01
576#define OSD2_VSC_CTRL0 0x3d02
577#define OSD2_HSC_PHASE_STEP 0x3d03
578#define OSD2_HSC_INI_PHASE 0x3d04
579#define OSD2_HSC_CTRL0 0x3d05
580#define OSD2_HSC_INI_PAT_CTRL 0x3d06
581#define OSD2_SC_DUMMY_DATA 0x3d07
582#define OSD2_SC_CTRL0 0x3d08
583#define OSD2_SCI_WH_M1 0x3d09
584#define OSD2_SCO_H_START_END 0x3d0a
585#define OSD2_SCO_V_START_END 0x3d0b
586#define OSD2_SCALE_COEF_IDX 0x3d18
587#define OSD2_SCALE_COEF 0x3d19
588
589/* osd34 scaler */
590#define OSD34_SCALE_COEF_IDX 0x3d1e
591#define OSD34_SCALE_COEF 0x3d1f
592#define OSD34_VSC_PHASE_STEP 0x3d20
593#define OSD34_VSC_INI_PHASE 0x3d21
594#define OSD34_VSC_CTRL0 0x3d22
595#define OSD34_HSC_PHASE_STEP 0x3d23
596#define OSD34_HSC_INI_PHASE 0x3d24
597#define OSD34_HSC_CTRL0 0x3d25
598#define OSD34_HSC_INI_PAT_CTRL 0x3d26
599#define OSD34_SC_DUMMY_DATA 0x3d27
600#define OSD34_SC_CTRL0 0x3d28
601#define OSD34_SCI_WH_M1 0x3d29
602#define OSD34_SCO_H_START_END 0x3d2a
603#define OSD34_SCO_V_START_END 0x3d2b
484/* viu2 */ 604/* viu2 */
485#define VIU2_ADDR_START 0x1e00 605#define VIU2_ADDR_START 0x1e00
486#define VIU2_ADDR_END 0x1eff 606#define VIU2_ADDR_END 0x1eff
@@ -1400,4 +1520,131 @@
1400#define OSDSR_YBIC_VCOEF0 0x3149 1520#define OSDSR_YBIC_VCOEF0 0x3149
1401#define OSDSR_CBIC_VCOEF0 0x314a 1521#define OSDSR_CBIC_VCOEF0 0x314a
1402 1522
1523/* osd afbcd on gxtvbb */
1524#define OSD1_AFBCD_ENABLE 0x31a0
1525#define OSD1_AFBCD_MODE 0x31a1
1526#define OSD1_AFBCD_SIZE_IN 0x31a2
1527#define OSD1_AFBCD_HDR_PTR 0x31a3
1528#define OSD1_AFBCD_FRAME_PTR 0x31a4
1529#define OSD1_AFBCD_CHROMA_PTR 0x31a5
1530#define OSD1_AFBCD_CONV_CTRL 0x31a6
1531#define OSD1_AFBCD_STATUS 0x31a8
1532#define OSD1_AFBCD_PIXEL_HSCOPE 0x31a9
1533#define OSD1_AFBCD_PIXEL_VSCOPE 0x31aa
1534#define VIU_MISC_CTRL1 0x1a07
1535
1536/* add for gxm and 962e dv core2 */
1537#define DOLBY_CORE2A_SWAP_CTRL1 0x3434
1538#define DOLBY_CORE2A_SWAP_CTRL2 0x3435
1539
1540/* osd afbc on g12a */
1541#define VPU_MAFBC_BLOCK_ID 0x3a00
1542#define VPU_MAFBC_IRQ_RAW_STATUS 0x3a01
1543#define VPU_MAFBC_IRQ_CLEAR 0x3a02
1544#define VPU_MAFBC_IRQ_MASK 0x3a03
1545#define VPU_MAFBC_IRQ_STATUS 0x3a04
1546#define VPU_MAFBC_COMMAND 0x3a05
1547#define VPU_MAFBC_STATUS 0x3a06
1548#define VPU_MAFBC_SURFACE_CFG 0x3a07
1549
1550/* osd afbc on g12a */
1551#define VPU_MAFBC_HEADER_BUF_ADDR_LOW_S0 0x3a10
1552#define VPU_MAFBC_HEADER_BUF_ADDR_HIGH_S0 0x3a11
1553#define VPU_MAFBC_FORMAT_SPECIFIER_S0 0x3a12
1554#define VPU_MAFBC_BUFFER_WIDTH_S0 0x3a13
1555#define VPU_MAFBC_BUFFER_HEIGHT_S0 0x3a14
1556#define VPU_MAFBC_BOUNDING_BOX_X_START_S0 0x3a15
1557#define VPU_MAFBC_BOUNDING_BOX_X_END_S0 0x3a16
1558#define VPU_MAFBC_BOUNDING_BOX_Y_START_S0 0x3a17
1559#define VPU_MAFBC_BOUNDING_BOX_Y_END_S0 0x3a18
1560#define VPU_MAFBC_OUTPUT_BUF_ADDR_LOW_S0 0x3a19
1561#define VPU_MAFBC_OUTPUT_BUF_ADDR_HIGH_S0 0x3a1a
1562#define VPU_MAFBC_OUTPUT_BUF_STRIDE_S0 0x3a1b
1563#define VPU_MAFBC_PREFETCH_CFG_S0 0x3a1c
1564
1565#define VPU_MAFBC_HEADER_BUF_ADDR_LOW_S1 0x3a30
1566#define VPU_MAFBC_HEADER_BUF_ADDR_HIGH_S1 0x3a31
1567#define VPU_MAFBC_FORMAT_SPECIFIER_S1 0x3a32
1568#define VPU_MAFBC_BUFFER_WIDTH_S1 0x3a33
1569#define VPU_MAFBC_BUFFER_HEIGHT_S1 0x3a34
1570#define VPU_MAFBC_BOUNDING_BOX_X_START_S1 0x3a35
1571#define VPU_MAFBC_BOUNDING_BOX_X_END_S1 0x3a36
1572#define VPU_MAFBC_BOUNDING_BOX_Y_START_S1 0x3a37
1573#define VPU_MAFBC_BOUNDING_BOX_Y_END_S1 0x3a38
1574#define VPU_MAFBC_OUTPUT_BUF_ADDR_LOW_S1 0x3a39
1575#define VPU_MAFBC_OUTPUT_BUF_ADDR_HIGH_S1 0x3a3a
1576#define VPU_MAFBC_OUTPUT_BUF_STRIDE_S1 0x3a3b
1577#define VPU_MAFBC_PREFETCH_CFG_S1 0x3a3c
1578
1579#define VPU_MAFBC_HEADER_BUF_ADDR_LOW_S2 0x3a50
1580#define VPU_MAFBC_HEADER_BUF_ADDR_HIGH_S2 0x3a51
1581#define VPU_MAFBC_FORMAT_SPECIFIER_S2 0x3a52
1582#define VPU_MAFBC_BUFFER_WIDTH_S2 0x3a53
1583#define VPU_MAFBC_BUFFER_HEIGHT_S2 0x3a54
1584#define VPU_MAFBC_BOUNDING_BOX_X_START_S2 0x3a55
1585#define VPU_MAFBC_BOUNDING_BOX_X_END_S2 0x3a56
1586#define VPU_MAFBC_BOUNDING_BOX_Y_START_S2 0x3a57
1587#define VPU_MAFBC_BOUNDING_BOX_Y_END_S2 0x3a58
1588#define VPU_MAFBC_OUTPUT_BUF_ADDR_LOW_S2 0x3a59
1589#define VPU_MAFBC_OUTPUT_BUF_ADDR_HIGH_S2 0x3a5a
1590#define VPU_MAFBC_OUTPUT_BUF_STRIDE_S2 0x3a5b
1591#define VPU_MAFBC_PREFETCH_CFG_S2 0x3a5c
1592
1593#define VPU_MAFBC_HEADER_BUF_ADDR_LOW_S3 0x3a70
1594#define VPU_MAFBC_HEADER_BUF_ADDR_HIGH_S3 0x3a71
1595#define VPU_MAFBC_FORMAT_SPECIFIER_S3 0x3a72
1596#define VPU_MAFBC_BUFFER_WIDTH_S3 0x3a73
1597#define VPU_MAFBC_BUFFER_HEIGHT_S3 0x3a74
1598#define VPU_MAFBC_BOUNDING_BOX_X_START_S3 0x3a75
1599#define VPU_MAFBC_BOUNDING_BOX_X_END_S3 0x3a76
1600#define VPU_MAFBC_BOUNDING_BOX_Y_START_S3 0x3a77
1601#define VPU_MAFBC_BOUNDING_BOX_Y_END_S3 0x3a78
1602#define VPU_MAFBC_OUTPUT_BUF_ADDR_LOW_S3 0x3a79
1603#define VPU_MAFBC_OUTPUT_BUF_ADDR_HIGH_S3 0x3a7a
1604#define VPU_MAFBC_OUTPUT_BUF_STRIDE_S3 0x3a7b
1605#define VPU_MAFBC_PREFETCH_CFG_S3 0x3a7c
1606
1607#define DOLBY_PATH_CTRL 0x1a0c
1608#define OSD_PATH_MISC_CTRL 0x1a0e
1609#define MALI_AFBCD_TOP_CTRL 0x1a0f
1610
1611#define VIU_OSD_BLEND_CTRL 0x39b0
1612#define VIU_OSD_BLEND_CTRL1 0x39c0
1613#define VIU_OSD_BLEND_DIN0_SCOPE_H 0x39b1
1614#define VIU_OSD_BLEND_DIN0_SCOPE_V 0x39b2
1615#define VIU_OSD_BLEND_DIN1_SCOPE_H 0x39b3
1616#define VIU_OSD_BLEND_DIN1_SCOPE_V 0x39b4
1617#define VIU_OSD_BLEND_DIN2_SCOPE_H 0x39b5
1618#define VIU_OSD_BLEND_DIN2_SCOPE_V 0x39b6
1619#define VIU_OSD_BLEND_DIN3_SCOPE_H 0x39b7
1620#define VIU_OSD_BLEND_DIN3_SCOPE_V 0x39b8
1621#define VIU_OSD_BLEND_DUMMY_DATA0 0x39b9
1622#define VIU_OSD_BLEND_DUMMY_ALPHA 0x39ba
1623#define VIU_OSD_BLEND_BLEND0_SIZE 0x39bb
1624#define VIU_OSD_BLEND_BLEND1_SIZE 0x39bc
1625#define VIU_OSD_BLEND_RO_CURRENT_XY 0x39bf
1626
1627#define VPP_OUT_H_V_SIZE 0x1da5
1628
1629#define VPP_VD2_HDR_IN_SIZE 0x1df0
1630#define VPP_OSD1_IN_SIZE 0x1df1
1631#define VPP_GCLK_CTRL2 0x1df2
1632#define VD2_PPS_DUMMY_DATA 0x1df4
1633#define VPP_OSD1_BLD_H_SCOPE 0x1df5
1634#define VPP_OSD1_BLD_V_SCOPE 0x1df6
1635#define VPP_OSD2_BLD_H_SCOPE 0x1df7
1636#define VPP_OSD2_BLD_V_SCOPE 0x1df8
1637#define VPP_WRBAK_CTRL 0x1df9
1638#define VPP_SLEEP_CTRL 0x1dfa
1639#define VD1_BLEND_SRC_CTRL 0x1dfb
1640#define VD2_BLEND_SRC_CTRL 0x1dfc
1641#define OSD1_BLEND_SRC_CTRL 0x1dfd
1642#define OSD2_BLEND_SRC_CTRL 0x1dfe
1643
1644#define VPP_POST_BLEND_BLEND_DUMMY_DATA 0x3968
1645#define VPP_POST_BLEND_DUMMY_ALPHA 0x3969
1646#define VPP_RDARB_MODE 0x3978
1647#define VPP_RDARB_REQEN_SLV 0x3979
1648#define VPU_RDARB_MODE_L2C1 0x279d
1649
1403#endif /* __MESON_REGISTERS_H */ 1650#endif /* __MESON_REGISTERS_H */
diff --git a/drivers/gpu/drm/meson/meson_vclk.c b/drivers/gpu/drm/meson/meson_vclk.c
index f6ba35a405f8..b39034745444 100644
--- a/drivers/gpu/drm/meson/meson_vclk.c
+++ b/drivers/gpu/drm/meson/meson_vclk.c
@@ -113,9 +113,12 @@
113#define HHI_HDMI_PLL_CNTL4 0x32C /* 0xcb offset in data sheet */ 113#define HHI_HDMI_PLL_CNTL4 0x32C /* 0xcb offset in data sheet */
114#define HHI_HDMI_PLL_CNTL5 0x330 /* 0xcc offset in data sheet */ 114#define HHI_HDMI_PLL_CNTL5 0x330 /* 0xcc offset in data sheet */
115#define HHI_HDMI_PLL_CNTL6 0x334 /* 0xcd offset in data sheet */ 115#define HHI_HDMI_PLL_CNTL6 0x334 /* 0xcd offset in data sheet */
116#define HHI_HDMI_PLL_CNTL7 0x338 /* 0xce offset in data sheet */
116 117
117#define HDMI_PLL_RESET BIT(28) 118#define HDMI_PLL_RESET BIT(28)
119#define HDMI_PLL_RESET_G12A BIT(29)
118#define HDMI_PLL_LOCK BIT(31) 120#define HDMI_PLL_LOCK BIT(31)
121#define HDMI_PLL_LOCK_G12A (3 << 30)
119 122
120#define FREQ_1000_1001(_freq) DIV_ROUND_CLOSEST(_freq * 1000, 1001) 123#define FREQ_1000_1001(_freq) DIV_ROUND_CLOSEST(_freq * 1000, 1001)
121 124
@@ -257,6 +260,10 @@ static void meson_venci_cvbs_clock_config(struct meson_drm *priv)
257 regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x71486980); 260 regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x71486980);
258 regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x00000e55); 261 regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x00000e55);
259 regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x4800023d); 262 regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x4800023d);
263
264 /* Poll for lock bit */
265 regmap_read_poll_timeout(priv->hhi, HHI_HDMI_PLL_CNTL, val,
266 (val & HDMI_PLL_LOCK), 10, 0);
260 } else if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu") || 267 } else if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu") ||
261 meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu")) { 268 meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu")) {
262 regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x4000027b); 269 regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x4000027b);
@@ -271,11 +278,26 @@ static void meson_venci_cvbs_clock_config(struct meson_drm *priv)
271 HDMI_PLL_RESET, HDMI_PLL_RESET); 278 HDMI_PLL_RESET, HDMI_PLL_RESET);
272 regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL, 279 regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
273 HDMI_PLL_RESET, 0); 280 HDMI_PLL_RESET, 0);
274 }
275 281
276 /* Poll for lock bit */ 282 /* Poll for lock bit */
277 regmap_read_poll_timeout(priv->hhi, HHI_HDMI_PLL_CNTL, val, 283 regmap_read_poll_timeout(priv->hhi, HHI_HDMI_PLL_CNTL, val,
278 (val & HDMI_PLL_LOCK), 10, 0); 284 (val & HDMI_PLL_LOCK), 10, 0);
285 } else if (meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu")) {
286 regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x1a0504f7);
287 regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2, 0x00010000);
288 regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL3, 0x00000000);
289 regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0x6a28dc00);
290 regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x65771290);
291 regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x39272000);
292 regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL7, 0x56540000);
293 regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x3a0504f7);
294 regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x1a0504f7);
295
296 /* Poll for lock bit */
297 regmap_read_poll_timeout(priv->hhi, HHI_HDMI_PLL_CNTL, val,
298 ((val & HDMI_PLL_LOCK_G12A) == HDMI_PLL_LOCK_G12A),
299 10, 0);
300 }
279 301
280 /* Disable VCLK2 */ 302 /* Disable VCLK2 */
281 regmap_update_bits(priv->hhi, HHI_VIID_CLK_CNTL, VCLK2_EN, 0); 303 regmap_update_bits(priv->hhi, HHI_VIID_CLK_CNTL, VCLK2_EN, 0);
@@ -288,8 +310,13 @@ static void meson_venci_cvbs_clock_config(struct meson_drm *priv)
288 VCLK2_DIV_MASK, (55 - 1)); 310 VCLK2_DIV_MASK, (55 - 1));
289 311
290 /* select vid_pll for vclk2 */ 312 /* select vid_pll for vclk2 */
291 regmap_update_bits(priv->hhi, HHI_VIID_CLK_CNTL, 313 if (meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu"))
292 VCLK2_SEL_MASK, (4 << VCLK2_SEL_SHIFT)); 314 regmap_update_bits(priv->hhi, HHI_VIID_CLK_CNTL,
315 VCLK2_SEL_MASK, (0 << VCLK2_SEL_SHIFT));
316 else
317 regmap_update_bits(priv->hhi, HHI_VIID_CLK_CNTL,
318 VCLK2_SEL_MASK, (4 << VCLK2_SEL_SHIFT));
319
293 /* enable vclk2 gate */ 320 /* enable vclk2 gate */
294 regmap_update_bits(priv->hhi, HHI_VIID_CLK_CNTL, VCLK2_EN, VCLK2_EN); 321 regmap_update_bits(priv->hhi, HHI_VIID_CLK_CNTL, VCLK2_EN, VCLK2_EN);
295 322
@@ -396,8 +423,8 @@ struct meson_vclk_params {
396 }, 423 },
397 [MESON_VCLK_HDMI_297000] = { 424 [MESON_VCLK_HDMI_297000] = {
398 .pixel_freq = 297000, 425 .pixel_freq = 297000,
399 .pll_base_freq = 2970000, 426 .pll_base_freq = 5940000,
400 .pll_od1 = 1, 427 .pll_od1 = 2,
401 .pll_od2 = 1, 428 .pll_od2 = 1,
402 .pll_od3 = 1, 429 .pll_od3 = 1,
403 .vid_pll_div = VID_PLL_DIV_5, 430 .vid_pll_div = VID_PLL_DIV_5,
@@ -476,32 +503,80 @@ void meson_hdmi_pll_set_params(struct meson_drm *priv, unsigned int m,
476 /* Poll for lock bit */ 503 /* Poll for lock bit */
477 regmap_read_poll_timeout(priv->hhi, HHI_HDMI_PLL_CNTL, val, 504 regmap_read_poll_timeout(priv->hhi, HHI_HDMI_PLL_CNTL, val,
478 (val & HDMI_PLL_LOCK), 10, 0); 505 (val & HDMI_PLL_LOCK), 10, 0);
506 } else if (meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu")) {
507 regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x0b3a0400 | m);
508
509 /* Enable and reset */
510 regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
511 0x3 << 28, 0x3 << 28);
512
513 regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2, frac);
514 regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL3, 0x00000000);
515
516 /* G12A HDMI PLL Needs specific parameters for 5.4GHz */
517 if (m >= 0xf7) {
518 regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0xea68dc00);
519 regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x65771290);
520 regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x39272000);
521 regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL7, 0x55540000);
522 } else {
523 regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0x0a691c00);
524 regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x33771290);
525 regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x39270000);
526 regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL7, 0x50540000);
527 }
528
529 do {
530 /* Reset PLL */
531 regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
532 HDMI_PLL_RESET_G12A, HDMI_PLL_RESET_G12A);
533
534 /* UN-Reset PLL */
535 regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
536 HDMI_PLL_RESET_G12A, 0);
537
538 /* Poll for lock bits */
539 if (!regmap_read_poll_timeout(priv->hhi,
540 HHI_HDMI_PLL_CNTL, val,
541 ((val & HDMI_PLL_LOCK_G12A)
542 == HDMI_PLL_LOCK_G12A),
543 10, 100))
544 break;
545 } while(1);
479 } 546 }
480 547
481 if (meson_vpu_is_compatible(priv, "amlogic,meson-gxbb-vpu")) 548 if (meson_vpu_is_compatible(priv, "amlogic,meson-gxbb-vpu"))
482 regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL2, 549 regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL2,
483 3 << 16, pll_od_to_reg(od1) << 16); 550 3 << 16, pll_od_to_reg(od1) << 16);
484 else if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu") || 551 else if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu") ||
485 meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu")) 552 meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu"))
486 regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL3, 553 regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL3,
487 3 << 21, pll_od_to_reg(od1) << 21); 554 3 << 21, pll_od_to_reg(od1) << 21);
555 else if (meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu"))
556 regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
557 3 << 16, pll_od_to_reg(od1) << 16);
488 558
489 if (meson_vpu_is_compatible(priv, "amlogic,meson-gxbb-vpu")) 559 if (meson_vpu_is_compatible(priv, "amlogic,meson-gxbb-vpu"))
490 regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL2, 560 regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL2,
491 3 << 22, pll_od_to_reg(od2) << 22); 561 3 << 22, pll_od_to_reg(od2) << 22);
492 else if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu") || 562 else if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu") ||
493 meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu")) 563 meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu"))
494 regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL3, 564 regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL3,
495 3 << 23, pll_od_to_reg(od2) << 23); 565 3 << 23, pll_od_to_reg(od2) << 23);
566 else if (meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu"))
567 regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
568 3 << 18, pll_od_to_reg(od2) << 18);
496 569
497 if (meson_vpu_is_compatible(priv, "amlogic,meson-gxbb-vpu")) 570 if (meson_vpu_is_compatible(priv, "amlogic,meson-gxbb-vpu"))
498 regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL2, 571 regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL2,
499 3 << 18, pll_od_to_reg(od3) << 18); 572 3 << 18, pll_od_to_reg(od3) << 18);
500 else if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu") || 573 else if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu") ||
501 meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu")) 574 meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu"))
502 regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL3, 575 regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL3,
503 3 << 19, pll_od_to_reg(od3) << 19); 576 3 << 19, pll_od_to_reg(od3) << 19);
504 577 else if (meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu"))
578 regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
579 3 << 20, pll_od_to_reg(od3) << 20);
505} 580}
506 581
507#define XTAL_FREQ 24000 582#define XTAL_FREQ 24000
@@ -518,6 +593,7 @@ static unsigned int meson_hdmi_pll_get_m(struct meson_drm *priv,
518 593
519#define HDMI_FRAC_MAX_GXBB 4096 594#define HDMI_FRAC_MAX_GXBB 4096
520#define HDMI_FRAC_MAX_GXL 1024 595#define HDMI_FRAC_MAX_GXL 1024
596#define HDMI_FRAC_MAX_G12A 131072
521 597
522static unsigned int meson_hdmi_pll_get_frac(struct meson_drm *priv, 598static unsigned int meson_hdmi_pll_get_frac(struct meson_drm *priv,
523 unsigned int m, 599 unsigned int m,
@@ -534,6 +610,9 @@ static unsigned int meson_hdmi_pll_get_frac(struct meson_drm *priv,
534 parent_freq *= 2; 610 parent_freq *= 2;
535 } 611 }
536 612
613 if (meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu"))
614 frac_max = HDMI_FRAC_MAX_G12A;
615
537 /* We can have a perfect match !*/ 616 /* We can have a perfect match !*/
538 if (pll_freq / m == parent_freq && 617 if (pll_freq / m == parent_freq &&
539 pll_freq % m == 0) 618 pll_freq % m == 0)
@@ -559,7 +638,8 @@ static bool meson_hdmi_pll_validate_params(struct meson_drm *priv,
559 if (frac >= HDMI_FRAC_MAX_GXBB) 638 if (frac >= HDMI_FRAC_MAX_GXBB)
560 return false; 639 return false;
561 } else if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu") || 640 } else if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu") ||
562 meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu")) { 641 meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu") ||
642 meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu")) {
563 /* Empiric supported min/max dividers */ 643 /* Empiric supported min/max dividers */
564 if (m < 106 || m > 247) 644 if (m < 106 || m > 247)
565 return false; 645 return false;
@@ -714,6 +794,23 @@ static void meson_vclk_set(struct meson_drm *priv, unsigned int pll_base_freq,
714 } 794 }
715 795
716 meson_hdmi_pll_set_params(priv, m, frac, od1, od2, od3); 796 meson_hdmi_pll_set_params(priv, m, frac, od1, od2, od3);
797 } else if (meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu")) {
798 switch (pll_base_freq) {
799 case 2970000:
800 m = 0x7b;
801 frac = vic_alternate_clock ? 0x140b4 : 0x18000;
802 break;
803 case 4320000:
804 m = vic_alternate_clock ? 0xb3 : 0xb4;
805 frac = vic_alternate_clock ? 0x1a3ee : 0;
806 break;
807 case 5940000:
808 m = 0xf7;
809 frac = vic_alternate_clock ? 0x8148 : 0x10000;
810 break;
811 }
812
813 meson_hdmi_pll_set_params(priv, m, frac, od1, od2, od3);
717 } 814 }
718 815
719 /* Setup vid_pll divider */ 816 /* Setup vid_pll divider */
diff --git a/drivers/gpu/drm/meson/meson_venc.c b/drivers/gpu/drm/meson/meson_venc.c
index 66d73a932d19..6faca7313339 100644
--- a/drivers/gpu/drm/meson/meson_venc.c
+++ b/drivers/gpu/drm/meson/meson_venc.c
@@ -73,7 +73,9 @@
73/* HHI Registers */ 73/* HHI Registers */
74#define HHI_GCLK_MPEG2 0x148 /* 0x52 offset in data sheet */ 74#define HHI_GCLK_MPEG2 0x148 /* 0x52 offset in data sheet */
75#define HHI_VDAC_CNTL0 0x2F4 /* 0xbd offset in data sheet */ 75#define HHI_VDAC_CNTL0 0x2F4 /* 0xbd offset in data sheet */
76#define HHI_VDAC_CNTL0_G12A 0x2EC /* 0xbd offset in data sheet */
76#define HHI_VDAC_CNTL1 0x2F8 /* 0xbe offset in data sheet */ 77#define HHI_VDAC_CNTL1 0x2F8 /* 0xbe offset in data sheet */
78#define HHI_VDAC_CNTL1_G12A 0x2F0 /* 0xbe offset in data sheet */
77#define HHI_HDMI_PHY_CNTL0 0x3a0 /* 0xe8 offset in data sheet */ 79#define HHI_HDMI_PHY_CNTL0 0x3a0 /* 0xe8 offset in data sheet */
78 80
79struct meson_cvbs_enci_mode meson_cvbs_enci_pal = { 81struct meson_cvbs_enci_mode meson_cvbs_enci_pal = {
@@ -1675,8 +1677,13 @@ void meson_venc_disable_vsync(struct meson_drm *priv)
1675void meson_venc_init(struct meson_drm *priv) 1677void meson_venc_init(struct meson_drm *priv)
1676{ 1678{
1677 /* Disable CVBS VDAC */ 1679 /* Disable CVBS VDAC */
1678 regmap_write(priv->hhi, HHI_VDAC_CNTL0, 0); 1680 if (meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu")) {
1679 regmap_write(priv->hhi, HHI_VDAC_CNTL1, 8); 1681 regmap_write(priv->hhi, HHI_VDAC_CNTL0_G12A, 0);
1682 regmap_write(priv->hhi, HHI_VDAC_CNTL1_G12A, 8);
1683 } else {
1684 regmap_write(priv->hhi, HHI_VDAC_CNTL0, 0);
1685 regmap_write(priv->hhi, HHI_VDAC_CNTL1, 8);
1686 }
1680 1687
1681 /* Power Down Dacs */ 1688 /* Power Down Dacs */
1682 writel_relaxed(0xff, priv->io_base + _REG(VENC_VDAC_SETTING)); 1689 writel_relaxed(0xff, priv->io_base + _REG(VENC_VDAC_SETTING));
diff --git a/drivers/gpu/drm/meson/meson_venc_cvbs.c b/drivers/gpu/drm/meson/meson_venc_cvbs.c
index d622d817b6df..2c5341c881c4 100644
--- a/drivers/gpu/drm/meson/meson_venc_cvbs.c
+++ b/drivers/gpu/drm/meson/meson_venc_cvbs.c
@@ -37,7 +37,9 @@
37 37
38/* HHI VDAC Registers */ 38/* HHI VDAC Registers */
39#define HHI_VDAC_CNTL0 0x2F4 /* 0xbd offset in data sheet */ 39#define HHI_VDAC_CNTL0 0x2F4 /* 0xbd offset in data sheet */
40#define HHI_VDAC_CNTL0_G12A 0x2EC /* 0xbd offset in data sheet */
40#define HHI_VDAC_CNTL1 0x2F8 /* 0xbe offset in data sheet */ 41#define HHI_VDAC_CNTL1 0x2F8 /* 0xbe offset in data sheet */
42#define HHI_VDAC_CNTL1_G12A 0x2F0 /* 0xbe offset in data sheet */
41 43
42struct meson_venc_cvbs { 44struct meson_venc_cvbs {
43 struct drm_encoder encoder; 45 struct drm_encoder encoder;
@@ -166,8 +168,13 @@ static void meson_venc_cvbs_encoder_disable(struct drm_encoder *encoder)
166 struct meson_drm *priv = meson_venc_cvbs->priv; 168 struct meson_drm *priv = meson_venc_cvbs->priv;
167 169
168 /* Disable CVBS VDAC */ 170 /* Disable CVBS VDAC */
169 regmap_write(priv->hhi, HHI_VDAC_CNTL0, 0); 171 if (meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu")) {
170 regmap_write(priv->hhi, HHI_VDAC_CNTL1, 8); 172 regmap_write(priv->hhi, HHI_VDAC_CNTL0_G12A, 0);
173 regmap_write(priv->hhi, HHI_VDAC_CNTL1_G12A, 0);
174 } else {
175 regmap_write(priv->hhi, HHI_VDAC_CNTL0, 0);
176 regmap_write(priv->hhi, HHI_VDAC_CNTL1, 8);
177 }
171} 178}
172 179
173static void meson_venc_cvbs_encoder_enable(struct drm_encoder *encoder) 180static void meson_venc_cvbs_encoder_enable(struct drm_encoder *encoder)
@@ -179,13 +186,17 @@ static void meson_venc_cvbs_encoder_enable(struct drm_encoder *encoder)
179 /* VDAC0 source is not from ATV */ 186 /* VDAC0 source is not from ATV */
180 writel_bits_relaxed(BIT(5), 0, priv->io_base + _REG(VENC_VDAC_DACSEL0)); 187 writel_bits_relaxed(BIT(5), 0, priv->io_base + _REG(VENC_VDAC_DACSEL0));
181 188
182 if (meson_vpu_is_compatible(priv, "amlogic,meson-gxbb-vpu")) 189 if (meson_vpu_is_compatible(priv, "amlogic,meson-gxbb-vpu")) {
183 regmap_write(priv->hhi, HHI_VDAC_CNTL0, 1); 190 regmap_write(priv->hhi, HHI_VDAC_CNTL0, 1);
184 else if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu") || 191 regmap_write(priv->hhi, HHI_VDAC_CNTL1, 0);
185 meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu")) 192 } else if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu") ||
193 meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu")) {
186 regmap_write(priv->hhi, HHI_VDAC_CNTL0, 0xf0001); 194 regmap_write(priv->hhi, HHI_VDAC_CNTL0, 0xf0001);
187 195 regmap_write(priv->hhi, HHI_VDAC_CNTL1, 0);
188 regmap_write(priv->hhi, HHI_VDAC_CNTL1, 0); 196 } else if (meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu")) {
197 regmap_write(priv->hhi, HHI_VDAC_CNTL0_G12A, 0x906001);
198 regmap_write(priv->hhi, HHI_VDAC_CNTL1_G12A, 0);
199 }
189} 200}
190 201
191static void meson_venc_cvbs_encoder_mode_set(struct drm_encoder *encoder, 202static void meson_venc_cvbs_encoder_mode_set(struct drm_encoder *encoder,
diff --git a/drivers/gpu/drm/meson/meson_viu.c b/drivers/gpu/drm/meson/meson_viu.c
index ac0f3687e09a..0169c98b01c9 100644
--- a/drivers/gpu/drm/meson/meson_viu.c
+++ b/drivers/gpu/drm/meson/meson_viu.c
@@ -90,6 +90,34 @@ static int eotf_bypass_coeff[EOTF_COEFF_SIZE] = {
90 EOTF_COEFF_RIGHTSHIFT /* right shift */ 90 EOTF_COEFF_RIGHTSHIFT /* right shift */
91}; 91};
92 92
93void meson_viu_set_g12a_osd1_matrix(struct meson_drm *priv, int *m,
94 bool csc_on)
95{
96 /* VPP WRAP OSD1 matrix */
97 writel(((m[0] & 0xfff) << 16) | (m[1] & 0xfff),
98 priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_PRE_OFFSET0_1));
99 writel(m[2] & 0xfff,
100 priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_PRE_OFFSET2));
101 writel(((m[3] & 0x1fff) << 16) | (m[4] & 0x1fff),
102 priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_COEF00_01));
103 writel(((m[5] & 0x1fff) << 16) | (m[6] & 0x1fff),
104 priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_COEF02_10));
105 writel(((m[7] & 0x1fff) << 16) | (m[8] & 0x1fff),
106 priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_COEF11_12));
107 writel(((m[9] & 0x1fff) << 16) | (m[10] & 0x1fff),
108 priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_COEF20_21));
109 writel((m[11] & 0x1fff) << 16,
110 priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_COEF22));
111
112 writel(((m[18] & 0xfff) << 16) | (m[19] & 0xfff),
113 priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_OFFSET0_1));
114 writel(m[20] & 0xfff,
115 priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_OFFSET2));
116
117 writel_bits_relaxed(BIT(0), csc_on ? BIT(0) : 0,
118 priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_EN_CTRL));
119}
120
93void meson_viu_set_osd_matrix(struct meson_drm *priv, 121void meson_viu_set_osd_matrix(struct meson_drm *priv,
94 enum viu_matrix_sel_e m_select, 122 enum viu_matrix_sel_e m_select,
95 int *m, bool csc_on) 123 int *m, bool csc_on)
@@ -336,14 +364,24 @@ void meson_viu_init(struct meson_drm *priv)
336 if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu") || 364 if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu") ||
337 meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu")) 365 meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu"))
338 meson_viu_load_matrix(priv); 366 meson_viu_load_matrix(priv);
367 else if (meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu"))
368 meson_viu_set_g12a_osd1_matrix(priv, RGB709_to_YUV709l_coeff,
369 true);
339 370
340 /* Initialize OSD1 fifo control register */ 371 /* Initialize OSD1 fifo control register */
341 reg = BIT(0) | /* Urgent DDR request priority */ 372 reg = BIT(0) | /* Urgent DDR request priority */
342 (4 << 5) | /* hold_fifo_lines */ 373 (4 << 5); /* hold_fifo_lines */
343 (3 << 10) | /* burst length 64 */ 374 if (meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu"))
344 (32 << 12) | /* fifo_depth_val: 32*8=256 */ 375 reg |= (1 << 10) | /* burst length 32 */
345 (2 << 22) | /* 4 words in 1 burst */ 376 (32 << 12) | /* fifo_depth_val: 32*8=256 */
346 (2 << 24); 377 (2 << 22) | /* 4 words in 1 burst */
378 (2 << 24) |
379 (1 << 31);
380 else
381 reg |= (3 << 10) | /* burst length 64 */
382 (32 << 12) | /* fifo_depth_val: 32*8=256 */
383 (2 << 22) | /* 4 words in 1 burst */
384 (2 << 24);
347 writel_relaxed(reg, priv->io_base + _REG(VIU_OSD1_FIFO_CTRL_STAT)); 385 writel_relaxed(reg, priv->io_base + _REG(VIU_OSD1_FIFO_CTRL_STAT));
348 writel_relaxed(reg, priv->io_base + _REG(VIU_OSD2_FIFO_CTRL_STAT)); 386 writel_relaxed(reg, priv->io_base + _REG(VIU_OSD2_FIFO_CTRL_STAT));
349 387
@@ -369,6 +407,30 @@ void meson_viu_init(struct meson_drm *priv)
369 writel_relaxed(0x00FF00C0, 407 writel_relaxed(0x00FF00C0,
370 priv->io_base + _REG(VD2_IF0_LUMA_FIFO_SIZE)); 408 priv->io_base + _REG(VD2_IF0_LUMA_FIFO_SIZE));
371 409
410 if (meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu")) {
411 writel_relaxed(4 << 29 |
412 1 << 27 |
413 1 << 26 | /* blend_din0 input to blend0 */
414 1 << 25 | /* blend1_dout to blend2 */
415 1 << 24 | /* blend1_din3 input to blend1 */
416 1 << 20 |
417 0 << 16 |
418 1,
419 priv->io_base + _REG(VIU_OSD_BLEND_CTRL));
420 writel_relaxed(3 << 8 |
421 1 << 20,
422 priv->io_base + _REG(OSD1_BLEND_SRC_CTRL));
423 writel_relaxed(1 << 20,
424 priv->io_base + _REG(OSD2_BLEND_SRC_CTRL));
425 writel_relaxed(0, priv->io_base + _REG(VD1_BLEND_SRC_CTRL));
426 writel_relaxed(0, priv->io_base + _REG(VD2_BLEND_SRC_CTRL));
427 writel_relaxed(0,
428 priv->io_base + _REG(VIU_OSD_BLEND_DUMMY_DATA0));
429 writel_relaxed(0,
430 priv->io_base + _REG(VIU_OSD_BLEND_DUMMY_ALPHA));
431 writel_bits_relaxed(0x3 << 2, 0x3 << 2,
432 priv->io_base + _REG(DOLBY_PATH_CTRL));
433 }
372 434
373 priv->viu.osd1_enabled = false; 435 priv->viu.osd1_enabled = false;
374 priv->viu.osd1_commit = false; 436 priv->viu.osd1_commit = false;
diff --git a/drivers/gpu/drm/meson/meson_vpp.c b/drivers/gpu/drm/meson/meson_vpp.c
index f9efb431e953..8c52a3455ef4 100644
--- a/drivers/gpu/drm/meson/meson_vpp.c
+++ b/drivers/gpu/drm/meson/meson_vpp.c
@@ -112,32 +112,39 @@ void meson_vpp_init(struct meson_drm *priv)
112 writel_relaxed(0x20000, priv->io_base + _REG(VPP_DOLBY_CTRL)); 112 writel_relaxed(0x20000, priv->io_base + _REG(VPP_DOLBY_CTRL));
113 writel_relaxed(0x1020080, 113 writel_relaxed(0x1020080,
114 priv->io_base + _REG(VPP_DUMMY_DATA1)); 114 priv->io_base + _REG(VPP_DUMMY_DATA1));
115 } 115 } else if (meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu"))
116 writel_relaxed(0xf, priv->io_base + _REG(DOLBY_PATH_CTRL));
116 117
117 /* Initialize vpu fifo control registers */ 118 /* Initialize vpu fifo control registers */
118 writel_relaxed(readl_relaxed(priv->io_base + _REG(VPP_OFIFO_SIZE)) | 119 if (meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu"))
119 0x77f, priv->io_base + _REG(VPP_OFIFO_SIZE)); 120 writel_relaxed(0xfff << 20 | 0x1000,
121 priv->io_base + _REG(VPP_OFIFO_SIZE));
122 else
123 writel_relaxed(readl_relaxed(priv->io_base + _REG(VPP_OFIFO_SIZE)) |
124 0x77f, priv->io_base + _REG(VPP_OFIFO_SIZE));
120 writel_relaxed(0x08080808, priv->io_base + _REG(VPP_HOLD_LINES)); 125 writel_relaxed(0x08080808, priv->io_base + _REG(VPP_HOLD_LINES));
121 126
122 /* Turn off preblend */ 127 if (!meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu")) {
123 writel_bits_relaxed(VPP_PREBLEND_ENABLE, 0, 128 /* Turn off preblend */
124 priv->io_base + _REG(VPP_MISC)); 129 writel_bits_relaxed(VPP_PREBLEND_ENABLE, 0,
125 130 priv->io_base + _REG(VPP_MISC));
126 /* Turn off POSTBLEND */ 131
127 writel_bits_relaxed(VPP_POSTBLEND_ENABLE, 0, 132 /* Turn off POSTBLEND */
128 priv->io_base + _REG(VPP_MISC)); 133 writel_bits_relaxed(VPP_POSTBLEND_ENABLE, 0,
129 134 priv->io_base + _REG(VPP_MISC));
130 /* Force all planes off */ 135
131 writel_bits_relaxed(VPP_OSD1_POSTBLEND | VPP_OSD2_POSTBLEND | 136 /* Force all planes off */
132 VPP_VD1_POSTBLEND | VPP_VD2_POSTBLEND | 137 writel_bits_relaxed(VPP_OSD1_POSTBLEND | VPP_OSD2_POSTBLEND |
133 VPP_VD1_PREBLEND | VPP_VD2_PREBLEND, 0, 138 VPP_VD1_POSTBLEND | VPP_VD2_POSTBLEND |
134 priv->io_base + _REG(VPP_MISC)); 139 VPP_VD1_PREBLEND | VPP_VD2_PREBLEND, 0,
135 140 priv->io_base + _REG(VPP_MISC));
136 /* Setup default VD settings */ 141
137 writel_relaxed(4096, 142 /* Setup default VD settings */
138 priv->io_base + _REG(VPP_PREBLEND_VD1_H_START_END)); 143 writel_relaxed(4096,
139 writel_relaxed(4096, 144 priv->io_base + _REG(VPP_PREBLEND_VD1_H_START_END));
140 priv->io_base + _REG(VPP_BLEND_VD2_H_START_END)); 145 writel_relaxed(4096,
146 priv->io_base + _REG(VPP_BLEND_VD2_H_START_END));
147 }
141 148
142 /* Disable Scalers */ 149 /* Disable Scalers */
143 writel_relaxed(0, priv->io_base + _REG(VPP_OSD_SC_CTRL0)); 150 writel_relaxed(0, priv->io_base + _REG(VPP_OSD_SC_CTRL0));
diff --git a/drivers/gpu/drm/panel/panel-rocktech-jh057n00900.c b/drivers/gpu/drm/panel/panel-rocktech-jh057n00900.c
index 158a6d548068..d88ea8da2ec2 100644
--- a/drivers/gpu/drm/panel/panel-rocktech-jh057n00900.c
+++ b/drivers/gpu/drm/panel/panel-rocktech-jh057n00900.c
@@ -123,7 +123,7 @@ static int jh057n_init_sequence(struct jh057n *ctx)
123 123
124 ret = mipi_dsi_dcs_exit_sleep_mode(dsi); 124 ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
125 if (ret < 0) { 125 if (ret < 0) {
126 DRM_DEV_ERROR(dev, "Failed to exit sleep mode"); 126 DRM_DEV_ERROR(dev, "Failed to exit sleep mode\n");
127 return ret; 127 return ret;
128 } 128 }
129 /* Panel is operational 120 msec after reset */ 129 /* Panel is operational 120 msec after reset */
@@ -132,7 +132,7 @@ static int jh057n_init_sequence(struct jh057n *ctx)
132 if (ret) 132 if (ret)
133 return ret; 133 return ret;
134 134
135 DRM_DEV_DEBUG_DRIVER(dev, "Panel init sequence done"); 135 DRM_DEV_DEBUG_DRIVER(dev, "Panel init sequence done\n");
136 return 0; 136 return 0;
137} 137}
138 138
@@ -172,7 +172,7 @@ static int jh057n_prepare(struct drm_panel *panel)
172 if (ctx->prepared) 172 if (ctx->prepared)
173 return 0; 173 return 0;
174 174
175 DRM_DEV_DEBUG_DRIVER(ctx->dev, "Resetting the panel."); 175 DRM_DEV_DEBUG_DRIVER(ctx->dev, "Resetting the panel\n");
176 gpiod_set_value_cansleep(ctx->reset_gpio, 1); 176 gpiod_set_value_cansleep(ctx->reset_gpio, 1);
177 usleep_range(20, 40); 177 usleep_range(20, 40);
178 gpiod_set_value_cansleep(ctx->reset_gpio, 0); 178 gpiod_set_value_cansleep(ctx->reset_gpio, 0);
@@ -180,7 +180,8 @@ static int jh057n_prepare(struct drm_panel *panel)
180 180
181 ret = jh057n_init_sequence(ctx); 181 ret = jh057n_init_sequence(ctx);
182 if (ret < 0) { 182 if (ret < 0) {
183 DRM_DEV_ERROR(ctx->dev, "Panel init sequence failed: %d", ret); 183 DRM_DEV_ERROR(ctx->dev, "Panel init sequence failed: %d\n",
184 ret);
184 return ret; 185 return ret;
185 } 186 }
186 187
@@ -212,7 +213,7 @@ static int jh057n_get_modes(struct drm_panel *panel)
212 213
213 mode = drm_mode_duplicate(panel->drm, &default_mode); 214 mode = drm_mode_duplicate(panel->drm, &default_mode);
214 if (!mode) { 215 if (!mode) {
215 DRM_DEV_ERROR(ctx->dev, "Failed to add mode %ux%u@%u", 216 DRM_DEV_ERROR(ctx->dev, "Failed to add mode %ux%u@%u\n",
216 default_mode.hdisplay, default_mode.vdisplay, 217 default_mode.hdisplay, default_mode.vdisplay,
217 default_mode.vrefresh); 218 default_mode.vrefresh);
218 return -ENOMEM; 219 return -ENOMEM;
@@ -241,7 +242,7 @@ static int allpixelson_set(void *data, u64 val)
241 struct jh057n *ctx = data; 242 struct jh057n *ctx = data;
242 struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev); 243 struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
243 244
244 DRM_DEV_DEBUG_DRIVER(ctx->dev, "Setting all pixels on"); 245 DRM_DEV_DEBUG_DRIVER(ctx->dev, "Setting all pixels on\n");
245 dsi_generic_write_seq(dsi, ST7703_CMD_ALL_PIXEL_ON); 246 dsi_generic_write_seq(dsi, ST7703_CMD_ALL_PIXEL_ON);
246 msleep(val * 1000); 247 msleep(val * 1000);
247 /* Reset the panel to get video back */ 248 /* Reset the panel to get video back */
@@ -290,7 +291,7 @@ static int jh057n_probe(struct mipi_dsi_device *dsi)
290 291
291 ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW); 292 ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
292 if (IS_ERR(ctx->reset_gpio)) { 293 if (IS_ERR(ctx->reset_gpio)) {
293 DRM_DEV_ERROR(dev, "cannot get reset gpio"); 294 DRM_DEV_ERROR(dev, "cannot get reset gpio\n");
294 return PTR_ERR(ctx->reset_gpio); 295 return PTR_ERR(ctx->reset_gpio);
295 } 296 }
296 297
@@ -315,12 +316,12 @@ static int jh057n_probe(struct mipi_dsi_device *dsi)
315 316
316 ret = mipi_dsi_attach(dsi); 317 ret = mipi_dsi_attach(dsi);
317 if (ret < 0) { 318 if (ret < 0) {
318 DRM_DEV_ERROR(dev, "mipi_dsi_attach failed. Is host ready?"); 319 DRM_DEV_ERROR(dev, "mipi_dsi_attach failed. Is host ready?\n");
319 drm_panel_remove(&ctx->panel); 320 drm_panel_remove(&ctx->panel);
320 return ret; 321 return ret;
321 } 322 }
322 323
323 DRM_DEV_INFO(dev, "%ux%u@%u %ubpp dsi %udl - ready", 324 DRM_DEV_INFO(dev, "%ux%u@%u %ubpp dsi %udl - ready\n",
324 default_mode.hdisplay, default_mode.vdisplay, 325 default_mode.hdisplay, default_mode.vdisplay,
325 default_mode.vrefresh, 326 default_mode.vrefresh,
326 mipi_dsi_pixel_format_to_bpp(dsi->format), dsi->lanes); 327 mipi_dsi_pixel_format_to_bpp(dsi->format), dsi->lanes);
diff --git a/drivers/gpu/drm/pl111/pl111_versatile.c b/drivers/gpu/drm/pl111/pl111_versatile.c
index b9baefdba38a..1c318ad32a8c 100644
--- a/drivers/gpu/drm/pl111/pl111_versatile.c
+++ b/drivers/gpu/drm/pl111/pl111_versatile.c
@@ -330,6 +330,7 @@ int pl111_versatile_init(struct device *dev, struct pl111_drm_dev_private *priv)
330 ret = vexpress_muxfpga_init(); 330 ret = vexpress_muxfpga_init();
331 if (ret) { 331 if (ret) {
332 dev_err(dev, "unable to initialize muxfpga driver\n"); 332 dev_err(dev, "unable to initialize muxfpga driver\n");
333 of_node_put(np);
333 return ret; 334 return ret;
334 } 335 }
335 336
@@ -337,17 +338,20 @@ int pl111_versatile_init(struct device *dev, struct pl111_drm_dev_private *priv)
337 pdev = of_find_device_by_node(np); 338 pdev = of_find_device_by_node(np);
338 if (!pdev) { 339 if (!pdev) {
339 dev_err(dev, "can't find the sysreg device, deferring\n"); 340 dev_err(dev, "can't find the sysreg device, deferring\n");
341 of_node_put(np);
340 return -EPROBE_DEFER; 342 return -EPROBE_DEFER;
341 } 343 }
342 map = dev_get_drvdata(&pdev->dev); 344 map = dev_get_drvdata(&pdev->dev);
343 if (!map) { 345 if (!map) {
344 dev_err(dev, "sysreg has not yet probed\n"); 346 dev_err(dev, "sysreg has not yet probed\n");
345 platform_device_put(pdev); 347 platform_device_put(pdev);
348 of_node_put(np);
346 return -EPROBE_DEFER; 349 return -EPROBE_DEFER;
347 } 350 }
348 } else { 351 } else {
349 map = syscon_node_to_regmap(np); 352 map = syscon_node_to_regmap(np);
350 } 353 }
354 of_node_put(np);
351 355
352 if (IS_ERR(map)) { 356 if (IS_ERR(map)) {
353 dev_err(dev, "no Versatile syscon regmap\n"); 357 dev_err(dev, "no Versatile syscon regmap\n");
diff --git a/drivers/gpu/drm/tinydrm/core/tinydrm-helpers.c b/drivers/gpu/drm/tinydrm/core/tinydrm-helpers.c
index d7b38dfb6438..6d540d93758f 100644
--- a/drivers/gpu/drm/tinydrm/core/tinydrm-helpers.c
+++ b/drivers/gpu/drm/tinydrm/core/tinydrm-helpers.c
@@ -26,164 +26,6 @@ static unsigned int spi_max;
26module_param(spi_max, uint, 0400); 26module_param(spi_max, uint, 0400);
27MODULE_PARM_DESC(spi_max, "Set a lower SPI max transfer size"); 27MODULE_PARM_DESC(spi_max, "Set a lower SPI max transfer size");
28 28
29/**
30 * tinydrm_memcpy - Copy clip buffer
31 * @dst: Destination buffer
32 * @vaddr: Source buffer
33 * @fb: DRM framebuffer
34 * @clip: Clip rectangle area to copy
35 */
36void tinydrm_memcpy(void *dst, void *vaddr, struct drm_framebuffer *fb,
37 struct drm_rect *clip)
38{
39 unsigned int cpp = drm_format_plane_cpp(fb->format->format, 0);
40 unsigned int pitch = fb->pitches[0];
41 void *src = vaddr + (clip->y1 * pitch) + (clip->x1 * cpp);
42 size_t len = (clip->x2 - clip->x1) * cpp;
43 unsigned int y;
44
45 for (y = clip->y1; y < clip->y2; y++) {
46 memcpy(dst, src, len);
47 src += pitch;
48 dst += len;
49 }
50}
51EXPORT_SYMBOL(tinydrm_memcpy);
52
53/**
54 * tinydrm_swab16 - Swap bytes into clip buffer
55 * @dst: RGB565 destination buffer
56 * @vaddr: RGB565 source buffer
57 * @fb: DRM framebuffer
58 * @clip: Clip rectangle area to copy
59 */
60void tinydrm_swab16(u16 *dst, void *vaddr, struct drm_framebuffer *fb,
61 struct drm_rect *clip)
62{
63 size_t len = (clip->x2 - clip->x1) * sizeof(u16);
64 unsigned int x, y;
65 u16 *src, *buf;
66
67 /*
68 * The cma memory is write-combined so reads are uncached.
69 * Speed up by fetching one line at a time.
70 */
71 buf = kmalloc(len, GFP_KERNEL);
72 if (!buf)
73 return;
74
75 for (y = clip->y1; y < clip->y2; y++) {
76 src = vaddr + (y * fb->pitches[0]);
77 src += clip->x1;
78 memcpy(buf, src, len);
79 src = buf;
80 for (x = clip->x1; x < clip->x2; x++)
81 *dst++ = swab16(*src++);
82 }
83
84 kfree(buf);
85}
86EXPORT_SYMBOL(tinydrm_swab16);
87
88/**
89 * tinydrm_xrgb8888_to_rgb565 - Convert XRGB8888 to RGB565 clip buffer
90 * @dst: RGB565 destination buffer
91 * @vaddr: XRGB8888 source buffer
92 * @fb: DRM framebuffer
93 * @clip: Clip rectangle area to copy
94 * @swap: Swap bytes
95 *
96 * Drivers can use this function for RGB565 devices that don't natively
97 * support XRGB8888.
98 */
99void tinydrm_xrgb8888_to_rgb565(u16 *dst, void *vaddr,
100 struct drm_framebuffer *fb,
101 struct drm_rect *clip, bool swap)
102{
103 size_t len = (clip->x2 - clip->x1) * sizeof(u32);
104 unsigned int x, y;
105 u32 *src, *buf;
106 u16 val16;
107
108 buf = kmalloc(len, GFP_KERNEL);
109 if (!buf)
110 return;
111
112 for (y = clip->y1; y < clip->y2; y++) {
113 src = vaddr + (y * fb->pitches[0]);
114 src += clip->x1;
115 memcpy(buf, src, len);
116 src = buf;
117 for (x = clip->x1; x < clip->x2; x++) {
118 val16 = ((*src & 0x00F80000) >> 8) |
119 ((*src & 0x0000FC00) >> 5) |
120 ((*src & 0x000000F8) >> 3);
121 src++;
122 if (swap)
123 *dst++ = swab16(val16);
124 else
125 *dst++ = val16;
126 }
127 }
128
129 kfree(buf);
130}
131EXPORT_SYMBOL(tinydrm_xrgb8888_to_rgb565);
132
133/**
134 * tinydrm_xrgb8888_to_gray8 - Convert XRGB8888 to grayscale
135 * @dst: 8-bit grayscale destination buffer
136 * @vaddr: XRGB8888 source buffer
137 * @fb: DRM framebuffer
138 * @clip: Clip rectangle area to copy
139 *
140 * Drm doesn't have native monochrome or grayscale support.
141 * Such drivers can announce the commonly supported XR24 format to userspace
142 * and use this function to convert to the native format.
143 *
144 * Monochrome drivers will use the most significant bit,
145 * where 1 means foreground color and 0 background color.
146 *
147 * ITU BT.601 is used for the RGB -> luma (brightness) conversion.
148 */
149void tinydrm_xrgb8888_to_gray8(u8 *dst, void *vaddr, struct drm_framebuffer *fb,
150 struct drm_rect *clip)
151{
152 unsigned int len = (clip->x2 - clip->x1) * sizeof(u32);
153 unsigned int x, y;
154 void *buf;
155 u32 *src;
156
157 if (WARN_ON(fb->format->format != DRM_FORMAT_XRGB8888))
158 return;
159 /*
160 * The cma memory is write-combined so reads are uncached.
161 * Speed up by fetching one line at a time.
162 */
163 buf = kmalloc(len, GFP_KERNEL);
164 if (!buf)
165 return;
166
167 for (y = clip->y1; y < clip->y2; y++) {
168 src = vaddr + (y * fb->pitches[0]);
169 src += clip->x1;
170 memcpy(buf, src, len);
171 src = buf;
172 for (x = clip->x1; x < clip->x2; x++) {
173 u8 r = (*src & 0x00ff0000) >> 16;
174 u8 g = (*src & 0x0000ff00) >> 8;
175 u8 b = *src & 0x000000ff;
176
177 /* ITU BT.601: Y = 0.299 R + 0.587 G + 0.114 B */
178 *dst++ = (3 * r + 6 * g + b) / 10;
179 src++;
180 }
181 }
182
183 kfree(buf);
184}
185EXPORT_SYMBOL(tinydrm_xrgb8888_to_gray8);
186
187#if IS_ENABLED(CONFIG_SPI) 29#if IS_ENABLED(CONFIG_SPI)
188 30
189/** 31/**
diff --git a/drivers/gpu/drm/tinydrm/mipi-dbi.c b/drivers/gpu/drm/tinydrm/mipi-dbi.c
index 869c8f56da3b..85761b4abb83 100644
--- a/drivers/gpu/drm/tinydrm/mipi-dbi.c
+++ b/drivers/gpu/drm/tinydrm/mipi-dbi.c
@@ -21,6 +21,7 @@
21#include <drm/drm_drv.h> 21#include <drm/drm_drv.h>
22#include <drm/drm_fb_cma_helper.h> 22#include <drm/drm_fb_cma_helper.h>
23#include <drm/drm_gem_cma_helper.h> 23#include <drm/drm_gem_cma_helper.h>
24#include <drm/drm_format_helper.h>
24#include <drm/drm_fourcc.h> 25#include <drm/drm_fourcc.h>
25#include <drm/drm_gem_framebuffer_helper.h> 26#include <drm/drm_gem_framebuffer_helper.h>
26#include <drm/drm_vblank.h> 27#include <drm/drm_vblank.h>
@@ -218,12 +219,12 @@ int mipi_dbi_buf_copy(void *dst, struct drm_framebuffer *fb,
218 switch (fb->format->format) { 219 switch (fb->format->format) {
219 case DRM_FORMAT_RGB565: 220 case DRM_FORMAT_RGB565:
220 if (swap) 221 if (swap)
221 tinydrm_swab16(dst, src, fb, clip); 222 drm_fb_swab16(dst, src, fb, clip);
222 else 223 else
223 tinydrm_memcpy(dst, src, fb, clip); 224 drm_fb_memcpy(dst, src, fb, clip);
224 break; 225 break;
225 case DRM_FORMAT_XRGB8888: 226 case DRM_FORMAT_XRGB8888:
226 tinydrm_xrgb8888_to_rgb565(dst, src, fb, clip, swap); 227 drm_fb_xrgb8888_to_rgb565(dst, src, fb, clip, swap);
227 break; 228 break;
228 default: 229 default:
229 dev_err_once(fb->dev->dev, "Format is not supported: %s\n", 230 dev_err_once(fb->dev->dev, "Format is not supported: %s\n",
diff --git a/drivers/gpu/drm/tinydrm/repaper.c b/drivers/gpu/drm/tinydrm/repaper.c
index 3f3632457079..a29b8278324b 100644
--- a/drivers/gpu/drm/tinydrm/repaper.c
+++ b/drivers/gpu/drm/tinydrm/repaper.c
@@ -31,6 +31,7 @@
31#include <drm/drm_drv.h> 31#include <drm/drm_drv.h>
32#include <drm/drm_fb_cma_helper.h> 32#include <drm/drm_fb_cma_helper.h>
33#include <drm/drm_fb_helper.h> 33#include <drm/drm_fb_helper.h>
34#include <drm/drm_format_helper.h>
34#include <drm/drm_gem_cma_helper.h> 35#include <drm/drm_gem_cma_helper.h>
35#include <drm/drm_gem_framebuffer_helper.h> 36#include <drm/drm_gem_framebuffer_helper.h>
36#include <drm/drm_rect.h> 37#include <drm/drm_rect.h>
@@ -566,7 +567,7 @@ static int repaper_fb_dirty(struct drm_framebuffer *fb)
566 goto out_free; 567 goto out_free;
567 } 568 }
568 569
569 tinydrm_xrgb8888_to_gray8(buf, cma_obj->vaddr, fb, &clip); 570 drm_fb_xrgb8888_to_gray8(buf, cma_obj->vaddr, fb, &clip);
570 571
571 if (import_attach) { 572 if (import_attach) {
572 ret = dma_buf_end_cpu_access(import_attach->dmabuf, 573 ret = dma_buf_end_cpu_access(import_attach->dmabuf,
diff --git a/drivers/gpu/drm/tinydrm/st7586.c b/drivers/gpu/drm/tinydrm/st7586.c
index d99957bac532..560d7ac0cadc 100644
--- a/drivers/gpu/drm/tinydrm/st7586.c
+++ b/drivers/gpu/drm/tinydrm/st7586.c
@@ -22,6 +22,7 @@
22#include <drm/drm_drv.h> 22#include <drm/drm_drv.h>
23#include <drm/drm_fb_cma_helper.h> 23#include <drm/drm_fb_cma_helper.h>
24#include <drm/drm_fb_helper.h> 24#include <drm/drm_fb_helper.h>
25#include <drm/drm_format_helper.h>
25#include <drm/drm_gem_cma_helper.h> 26#include <drm/drm_gem_cma_helper.h>
26#include <drm/drm_gem_framebuffer_helper.h> 27#include <drm/drm_gem_framebuffer_helper.h>
27#include <drm/drm_rect.h> 28#include <drm/drm_rect.h>
@@ -77,7 +78,7 @@ static void st7586_xrgb8888_to_gray332(u8 *dst, void *vaddr,
77 if (!buf) 78 if (!buf)
78 return; 79 return;
79 80
80 tinydrm_xrgb8888_to_gray8(buf, vaddr, fb, clip); 81 drm_fb_xrgb8888_to_gray8(buf, vaddr, fb, clip);
81 src = buf; 82 src = buf;
82 83
83 for (y = clip->y1; y < clip->y2; y++) { 84 for (y = clip->y1; y < clip->y2; y++) {
diff --git a/drivers/gpu/drm/vc4/vc4_debugfs.c b/drivers/gpu/drm/vc4/vc4_debugfs.c
index 69df84bdf904..f9dec08267dc 100644
--- a/drivers/gpu/drm/vc4/vc4_debugfs.c
+++ b/drivers/gpu/drm/vc4/vc4_debugfs.c
@@ -48,7 +48,7 @@ vc4_debugfs_init(struct drm_minor *minor)
48 return 0; 48 return 0;
49} 49}
50 50
51int vc4_debugfs_regset32(struct seq_file *m, void *unused) 51static int vc4_debugfs_regset32(struct seq_file *m, void *unused)
52{ 52{
53 struct drm_info_node *node = (struct drm_info_node *)m->private; 53 struct drm_info_node *node = (struct drm_info_node *)m->private;
54 struct debugfs_regset32 *regset = node->info_ent->data; 54 struct debugfs_regset32 *regset = node->info_ent->data;
diff --git a/include/drm/drm_format_helper.h b/include/drm/drm_format_helper.h
new file mode 100644
index 000000000000..6f84380757ee
--- /dev/null
+++ b/include/drm/drm_format_helper.h
@@ -0,0 +1,34 @@
1/*
2 * Copyright (C) 2016 Noralf Trønnes
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 */
9
10#ifndef __LINUX_DRM_FORMAT_HELPER_H
11#define __LINUX_DRM_FORMAT_HELPER_H
12
13struct drm_framebuffer;
14struct drm_rect;
15
16void drm_fb_memcpy(void *dst, void *vaddr, struct drm_framebuffer *fb,
17 struct drm_rect *clip);
18void drm_fb_memcpy_dstclip(void *dst, void *vaddr, struct drm_framebuffer *fb,
19 struct drm_rect *clip);
20void drm_fb_swab16(u16 *dst, void *vaddr, struct drm_framebuffer *fb,
21 struct drm_rect *clip);
22void drm_fb_xrgb8888_to_rgb565(void *dst, void *vaddr,
23 struct drm_framebuffer *fb,
24 struct drm_rect *clip, bool swap);
25void drm_fb_xrgb8888_to_rgb565_dstclip(void *dst, unsigned int dst_pitch,
26 void *vaddr, struct drm_framebuffer *fb,
27 struct drm_rect *clip, bool swap);
28void drm_fb_xrgb8888_to_rgb888_dstclip(void *dst, unsigned int dst_pitch,
29 void *vaddr, struct drm_framebuffer *fb,
30 struct drm_rect *clip);
31void drm_fb_xrgb8888_to_gray8(u8 *dst, void *vaddr, struct drm_framebuffer *fb,
32 struct drm_rect *clip);
33
34#endif /* __LINUX_DRM_FORMAT_HELPER_H */
diff --git a/include/drm/tinydrm/tinydrm-helpers.h b/include/drm/tinydrm/tinydrm-helpers.h
index ae4a6abc43b5..7d259acb8826 100644
--- a/include/drm/tinydrm/tinydrm-helpers.h
+++ b/include/drm/tinydrm/tinydrm-helpers.h
@@ -46,16 +46,6 @@ int tinydrm_display_pipe_init(struct drm_device *drm,
46 const struct drm_display_mode *mode, 46 const struct drm_display_mode *mode,
47 unsigned int rotation); 47 unsigned int rotation);
48 48
49void tinydrm_memcpy(void *dst, void *vaddr, struct drm_framebuffer *fb,
50 struct drm_rect *clip);
51void tinydrm_swab16(u16 *dst, void *vaddr, struct drm_framebuffer *fb,
52 struct drm_rect *clip);
53void tinydrm_xrgb8888_to_rgb565(u16 *dst, void *vaddr,
54 struct drm_framebuffer *fb,
55 struct drm_rect *clip, bool swap);
56void tinydrm_xrgb8888_to_gray8(u8 *dst, void *vaddr, struct drm_framebuffer *fb,
57 struct drm_rect *clip);
58
59size_t tinydrm_spi_max_transfer_size(struct spi_device *spi, size_t max_len); 49size_t tinydrm_spi_max_transfer_size(struct spi_device *spi, size_t max_len);
60bool tinydrm_spi_bpw_supported(struct spi_device *spi, u8 bpw); 50bool tinydrm_spi_bpw_supported(struct spi_device *spi, u8 bpw);
61int tinydrm_spi_transfer(struct spi_device *spi, u32 speed_hz, 51int tinydrm_spi_transfer(struct spi_device *spi, u32 speed_hz,