summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/display/panel/armadeus,st0700-adapt.txt9
-rw-r--r--Documentation/devicetree/bindings/display/panel/koe,tx14d24vm1bpa.txt42
-rw-r--r--Documentation/gpu/drivers.rst1
-rw-r--r--Documentation/gpu/mcde.rst8
-rw-r--r--MAINTAINERS7
-rw-r--r--drivers/gpu/drm/Kconfig2
-rw-r--r--drivers/gpu/drm/Makefile1
-rw-r--r--drivers/gpu/drm/ati_pcigart.c5
-rw-r--r--drivers/gpu/drm/bridge/adv7511/adv7511_drv.c8
-rw-r--r--drivers/gpu/drm/bridge/analogix-anx78xx.c8
-rw-r--r--drivers/gpu/drm/bridge/analogix/analogix_dp_core.c18
-rw-r--r--drivers/gpu/drm/bridge/dumb-vga-dac.c2
-rw-r--r--drivers/gpu/drm/bridge/lvds-encoder.c10
-rw-r--r--drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c3
-rw-r--r--drivers/gpu/drm/bridge/nxp-ptn3460.c3
-rw-r--r--drivers/gpu/drm/bridge/panel.c2
-rw-r--r--drivers/gpu/drm/bridge/parade-ps8622.c3
-rw-r--r--drivers/gpu/drm/bridge/sii902x.c3
-rw-r--r--drivers/gpu/drm/bridge/synopsys/dw-hdmi.c27
-rw-r--r--drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c9
-rw-r--r--drivers/gpu/drm/bridge/tc358764.c14
-rw-r--r--drivers/gpu/drm/bridge/thc63lvd1024.c10
-rw-r--r--drivers/gpu/drm/bridge/ti-sn65dsi86.c18
-rw-r--r--drivers/gpu/drm/bridge/ti-tfp410.c4
-rw-r--r--drivers/gpu/drm/drm_agpsupport.c11
-rw-r--r--drivers/gpu/drm/drm_atomic.c9
-rw-r--r--drivers/gpu/drm/drm_atomic_helper.c11
-rw-r--r--drivers/gpu/drm/drm_atomic_state_helper.c7
-rw-r--r--drivers/gpu/drm/drm_auth.c10
-rw-r--r--drivers/gpu/drm/drm_blend.c9
-rw-r--r--drivers/gpu/drm/drm_bufs.c21
-rw-r--r--drivers/gpu/drm/drm_client.c2
-rw-r--r--drivers/gpu/drm/drm_color_mgmt.c8
-rw-r--r--drivers/gpu/drm/drm_context.c8
-rw-r--r--drivers/gpu/drm/drm_crtc_helper.c14
-rw-r--r--drivers/gpu/drm/drm_crtc_internal.h24
-rw-r--r--drivers/gpu/drm/drm_damage_helper.c2
-rw-r--r--drivers/gpu/drm/drm_debugfs.c13
-rw-r--r--drivers/gpu/drm/drm_debugfs_crc.c9
-rw-r--r--drivers/gpu/drm/drm_dma.c6
-rw-r--r--drivers/gpu/drm/drm_drv.c9
-rw-r--r--drivers/gpu/drm/drm_dumb_buffers.c4
-rw-r--r--drivers/gpu/drm/drm_edid_load.c2
-rw-r--r--drivers/gpu/drm/drm_encoder.c4
-rw-r--r--drivers/gpu/drm/drm_fb_helper.c19
-rw-r--r--drivers/gpu/drm/drm_file.c11
-rw-r--r--drivers/gpu/drm/drm_flip_work.c6
-rw-r--r--drivers/gpu/drm/drm_fourcc.c2
-rw-r--r--drivers/gpu/drm/drm_framebuffer.c13
-rw-r--r--drivers/gpu/drm/drm_gem.c8
-rw-r--r--drivers/gpu/drm/drm_gem_cma_helper.c11
-rw-r--r--drivers/gpu/drm/drm_gem_framebuffer_helper.c1
-rw-r--r--drivers/gpu/drm/drm_hashtab.c10
-rw-r--r--drivers/gpu/drm/drm_internal.h10
-rw-r--r--drivers/gpu/drm/drm_ioc32.c9
-rw-r--r--drivers/gpu/drm/drm_ioctl.c22
-rw-r--r--drivers/gpu/drm/drm_irq.c13
-rw-r--r--drivers/gpu/drm/drm_kms_helper_common.c3
-rw-r--r--drivers/gpu/drm/drm_lease.c15
-rw-r--r--drivers/gpu/drm/drm_legacy.h4
-rw-r--r--drivers/gpu/drm/drm_legacy_misc.c7
-rw-r--r--drivers/gpu/drm/drm_lock.c8
-rw-r--r--drivers/gpu/drm/drm_memory.c9
-rw-r--r--drivers/gpu/drm/drm_mm.c9
-rw-r--r--drivers/gpu/drm/drm_mode_config.c6
-rw-r--r--drivers/gpu/drm/drm_mode_object.c9
-rw-r--r--drivers/gpu/drm/drm_modes.c7
-rw-r--r--drivers/gpu/drm/drm_modeset_lock.c2
-rw-r--r--drivers/gpu/drm/drm_of.c5
-rw-r--r--drivers/gpu/drm/drm_pci.c11
-rw-r--r--drivers/gpu/drm/drm_plane_helper.c9
-rw-r--r--drivers/gpu/drm/drm_prime.c7
-rw-r--r--drivers/gpu/drm/drm_print.c7
-rw-r--r--drivers/gpu/drm/drm_probe_helper.c7
-rw-r--r--drivers/gpu/drm/drm_property.c7
-rw-r--r--drivers/gpu/drm/drm_rect.c4
-rw-r--r--drivers/gpu/drm/drm_scatter.c9
-rw-r--r--drivers/gpu/drm/drm_scdc_helper.c2
-rw-r--r--drivers/gpu/drm/drm_simple_kms_helper.c5
-rw-r--r--drivers/gpu/drm/drm_syncobj.c13
-rw-r--r--drivers/gpu/drm/drm_sysfs.c15
-rw-r--r--drivers/gpu/drm/drm_trace.h2
-rw-r--r--drivers/gpu/drm/drm_trace_points.c3
-rw-r--r--drivers/gpu/drm/drm_vblank.c12
-rw-r--r--drivers/gpu/drm/drm_vm.c14
-rw-r--r--drivers/gpu/drm/drm_vma_manager.c6
-rw-r--r--drivers/gpu/drm/drm_vram_mm_helper.c4
-rw-r--r--drivers/gpu/drm/drm_writeback.c6
-rw-r--r--drivers/gpu/drm/mcde/Kconfig18
-rw-r--r--drivers/gpu/drm/mcde/Makefile3
-rw-r--r--drivers/gpu/drm/mcde/mcde_display.c1142
-rw-r--r--drivers/gpu/drm/mcde/mcde_display_regs.h518
-rw-r--r--drivers/gpu/drm/mcde/mcde_drm.h44
-rw-r--r--drivers/gpu/drm/mcde/mcde_drv.c572
-rw-r--r--drivers/gpu/drm/mcde/mcde_dsi.c1044
-rw-r--r--drivers/gpu/drm/mcde/mcde_dsi_regs.h385
-rw-r--r--drivers/gpu/drm/meson/Kconfig1
-rw-r--r--drivers/gpu/drm/panel/panel-simple.c55
-rw-r--r--drivers/gpu/drm/panel/panel-sitronix-st7701.c6
-rw-r--r--drivers/gpu/drm/scheduler/sched_main.c17
-rw-r--r--drivers/gpu/drm/stm/dw_mipi_dsi-stm.c24
-rw-r--r--drivers/gpu/drm/stm/ltdc.c8
-rw-r--r--include/drm/bridge/dw_mipi_dsi.h8
-rw-r--r--include/drm/drm_auth.h11
-rw-r--r--include/drm/drm_legacy.h12
105 files changed, 4387 insertions, 243 deletions
diff --git a/Documentation/devicetree/bindings/display/panel/armadeus,st0700-adapt.txt b/Documentation/devicetree/bindings/display/panel/armadeus,st0700-adapt.txt
new file mode 100644
index 000000000000..a30d63db3c8f
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/panel/armadeus,st0700-adapt.txt
@@ -0,0 +1,9 @@
+Armadeus ST0700 Adapt. A Santek ST0700I5Y-RBSLW 7.0" WVGA (800x480) TFT with
+an adapter board.
+
+Required properties:
+- compatible: "armadeus,st0700-adapt"
+- power-supply: see panel-common.txt
+
+Optional properties:
+- backlight: see panel-common.txt
diff --git a/Documentation/devicetree/bindings/display/panel/koe,tx14d24vm1bpa.txt b/Documentation/devicetree/bindings/display/panel/koe,tx14d24vm1bpa.txt
new file mode 100644
index 000000000000..be7ac666807b
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/panel/koe,tx14d24vm1bpa.txt
@@ -0,0 +1,42 @@
+Kaohsiung Opto-Electronics Inc. 5.7" QVGA (320 x 240) TFT LCD panel
+
+Required properties:
+- compatible: should be "koe,tx14d24vm1bpa"
+- backlight: phandle of the backlight device attached to the panel
+- power-supply: single regulator to provide the supply voltage
+
+Required nodes:
+- port: Parallel port mapping to connect this display
+
+This panel needs single power supply voltage. Its backlight is conntrolled
+via PWM signal.
+
+Example:
+--------
+
+Example device-tree definition when connected to iMX53 based board
+
+ lcd_panel: lcd-panel {
+ compatible = "koe,tx14d24vm1bpa";
+ backlight = <&backlight_lcd>;
+ power-supply = <&reg_3v3>;
+
+ port {
+ lcd_panel_in: endpoint {
+ remote-endpoint = <&lcd_display_out>;
+ };
+ };
+ };
+
+Then one needs to extend the dispX node:
+
+ lcd_display: disp1 {
+
+ port@1 {
+ reg = <1>;
+
+ lcd_display_out: endpoint {
+ remote-endpoint = <&lcd_panel_in>;
+ };
+ };
+ };
diff --git a/Documentation/gpu/drivers.rst b/Documentation/gpu/drivers.rst
index 044a7025477c..4bfb7068e9f7 100644
--- a/Documentation/gpu/drivers.rst
+++ b/Documentation/gpu/drivers.rst
@@ -7,6 +7,7 @@ GPU Driver Documentation
amdgpu
amdgpu-dc
i915
+ mcde
meson
pl111
tegra
diff --git a/Documentation/gpu/mcde.rst b/Documentation/gpu/mcde.rst
new file mode 100644
index 000000000000..c69e977defda
--- /dev/null
+++ b/Documentation/gpu/mcde.rst
@@ -0,0 +1,8 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+=======================================================
+ drm/mcde ST-Ericsson MCDE Multi-channel display engine
+=======================================================
+
+.. kernel-doc:: drivers/gpu/drm/mcde/mcde_drv.c
+ :doc: ST-Ericsson MCDE DRM Driver
diff --git a/MAINTAINERS b/MAINTAINERS
index eb274ac5b834..7a2f487ea49a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5128,6 +5128,13 @@ S: Maintained
F: drivers/gpu/drm/tinydrm/st7735r.c
F: Documentation/devicetree/bindings/display/sitronix,st7735r.txt
+DRM DRIVER FOR ST-ERICSSON MCDE
+M: Linus Walleij <linus.walleij@linaro.org>
+T: git git://anongit.freedesktop.org/drm/drm-misc
+S: Maintained
+F: drivers/gpu/drm/mcde/
+F: Documentation/devicetree/bindings/display/ste,mcde.txt
+
DRM DRIVER FOR TDFX VIDEO CARDS
S: Orphan / Obsolete
F: drivers/gpu/drm/tdfx/
diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index b62f40cc9691..6b34949416b1 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -350,6 +350,8 @@ source "drivers/gpu/drm/panfrost/Kconfig"
source "drivers/gpu/drm/aspeed/Kconfig"
+source "drivers/gpu/drm/mcde/Kconfig"
+
# Keep legacy drivers last
menuconfig DRM_LEGACY
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index af37253a8ec4..4a63c1fcf389 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -118,3 +118,4 @@ obj-$(CONFIG_DRM_VBOXVIDEO) += vboxvideo/
obj-$(CONFIG_DRM_LIMA) += lima/
obj-$(CONFIG_DRM_PANFROST) += panfrost/
obj-$(CONFIG_DRM_ASPEED_GFX) += aspeed/
+obj-$(CONFIG_DRM_MCDE) += mcde/
diff --git a/drivers/gpu/drm/ati_pcigart.c b/drivers/gpu/drm/ati_pcigart.c
index 2362f07fe1fc..2a413e291a60 100644
--- a/drivers/gpu/drm/ati_pcigart.c
+++ b/drivers/gpu/drm/ati_pcigart.c
@@ -32,9 +32,12 @@
*/
#include <linux/export.h>
-#include <drm/drmP.h>
#include <drm/ati_pcigart.h>
+#include <drm/drm_device.h>
+#include <drm/drm_os_linux.h>
+#include <drm/drm_pci.h>
+#include <drm/drm_print.h>
# define ATI_PCIGART_PAGE_SIZE 4096 /**< PCI GART page size */
diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
index c532e9c9e491..562420d9d8d5 100644
--- a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
+++ b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
@@ -6,21 +6,21 @@
* Licensed under the GPL-2.
*/
+#include <linux/clk.h>
#include <linux/device.h>
#include <linux/gpio/consumer.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/slab.h>
-#include <linux/clk.h>
-#include <drm/drmP.h>
+#include <media/cec.h>
+
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_edid.h>
+#include <drm/drm_print.h>
#include <drm/drm_probe_helper.h>
-#include <media/cec.h>
-
#include "adv7511.h"
/* ADI recommended values for proper operation. */
diff --git a/drivers/gpu/drm/bridge/analogix-anx78xx.c b/drivers/gpu/drm/bridge/analogix-anx78xx.c
index c09aaf93ae1b..479ce3642a79 100644
--- a/drivers/gpu/drm/bridge/analogix-anx78xx.c
+++ b/drivers/gpu/drm/bridge/analogix-anx78xx.c
@@ -16,23 +16,23 @@
*/
#include <linux/delay.h>
#include <linux/err.h>
-#include <linux/interrupt.h>
+#include <linux/gpio/consumer.h>
#include <linux/i2c.h>
+#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of_gpio.h>
#include <linux/of_irq.h>
#include <linux/of_platform.h>
#include <linux/regmap.h>
-#include <linux/types.h>
-#include <linux/gpio/consumer.h>
#include <linux/regulator/consumer.h>
+#include <linux/types.h>
-#include <drm/drmP.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_crtc.h>
#include <drm/drm_dp_helper.h>
#include <drm/drm_edid.h>
+#include <drm/drm_print.h>
#include <drm/drm_probe_helper.h>
#include "analogix-anx78xx.h"
diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
index 257d69b21d99..d2de98d44184 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
@@ -10,27 +10,27 @@
* option) any later version.
*/
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/err.h>
#include <linux/clk.h>
+#include <linux/component.h>
+#include <linux/err.h>
+#include <linux/gpio.h>
+#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/iopoll.h>
-#include <linux/interrupt.h>
+#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
-#include <linux/gpio.h>
-#include <linux/component.h>
#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
-#include <drm/drmP.h>
+#include <drm/bridge/analogix_dp.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_crtc.h>
+#include <drm/drm_device.h>
#include <drm/drm_panel.h>
+#include <drm/drm_print.h>
#include <drm/drm_probe_helper.h>
-#include <drm/bridge/analogix_dp.h>
-
#include "analogix_dp_core.h"
#include "analogix_dp_reg.h"
diff --git a/drivers/gpu/drm/bridge/dumb-vga-dac.c b/drivers/gpu/drm/bridge/dumb-vga-dac.c
index e64736c39a9f..1a3800a58aaf 100644
--- a/drivers/gpu/drm/bridge/dumb-vga-dac.c
+++ b/drivers/gpu/drm/bridge/dumb-vga-dac.c
@@ -15,9 +15,9 @@
#include <linux/of_graph.h>
#include <linux/regulator/consumer.h>
-#include <drm/drmP.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_crtc.h>
+#include <drm/drm_print.h>
#include <drm/drm_probe_helper.h>
struct dumb_vga {
diff --git a/drivers/gpu/drm/bridge/lvds-encoder.c b/drivers/gpu/drm/bridge/lvds-encoder.c
index ae8fc597eb38..6eaaa76970b1 100644
--- a/drivers/gpu/drm/bridge/lvds-encoder.c
+++ b/drivers/gpu/drm/bridge/lvds-encoder.c
@@ -7,12 +7,14 @@
* the License, or (at your option) any later version.
*/
-#include <drm/drmP.h>
-#include <drm/drm_bridge.h>
-#include <drm/drm_panel.h>
-
#include <linux/gpio/consumer.h>
+#include <linux/module.h>
+#include <linux/of.h>
#include <linux/of_graph.h>
+#include <linux/platform_device.h>
+
+#include <drm/drm_bridge.h>
+#include <drm/drm_panel.h>
struct lvds_encoder {
struct drm_bridge bridge;
diff --git a/drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c b/drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c
index a01028ec4de6..1644d281558a 100644
--- a/drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c
+++ b/drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c
@@ -34,11 +34,12 @@
#include <linux/i2c.h>
#include <linux/module.h>
#include <linux/of.h>
+
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_edid.h>
+#include <drm/drm_print.h>
#include <drm/drm_probe_helper.h>
-#include <drm/drmP.h>
#define EDID_EXT_BLOCK_CNT 0x7E
diff --git a/drivers/gpu/drm/bridge/nxp-ptn3460.c b/drivers/gpu/drm/bridge/nxp-ptn3460.c
index fb335afea4cf..3f4d4aef19e1 100644
--- a/drivers/gpu/drm/bridge/nxp-ptn3460.c
+++ b/drivers/gpu/drm/bridge/nxp-ptn3460.c
@@ -20,13 +20,14 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
+
#include <drm/drm_atomic_helper.h>
#include <drm/drm_crtc.h>
#include <drm/drm_edid.h>
#include <drm/drm_of.h>
#include <drm/drm_panel.h>
+#include <drm/drm_print.h>
#include <drm/drm_probe_helper.h>
-#include <drm/drmP.h>
#define PTN3460_EDID_ADDR 0x0
#define PTN3460_EDID_EMULATION_ADDR 0x84
diff --git a/drivers/gpu/drm/bridge/panel.c b/drivers/gpu/drm/bridge/panel.c
index 000ba7ce1ba8..08517740e6a0 100644
--- a/drivers/gpu/drm/bridge/panel.c
+++ b/drivers/gpu/drm/bridge/panel.c
@@ -8,12 +8,12 @@
* the License, or (at your option) any later version.
*/
-#include <drm/drmP.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_connector.h>
#include <drm/drm_encoder.h>
#include <drm/drm_modeset_helper_vtables.h>
#include <drm/drm_panel.h>
+#include <drm/drm_print.h>
#include <drm/drm_probe_helper.h>
struct panel_bridge {
diff --git a/drivers/gpu/drm/bridge/parade-ps8622.c b/drivers/gpu/drm/bridge/parade-ps8622.c
index fda1395b7481..05b9da6284f0 100644
--- a/drivers/gpu/drm/bridge/parade-ps8622.c
+++ b/drivers/gpu/drm/bridge/parade-ps8622.c
@@ -24,12 +24,13 @@
#include <linux/of_device.h>
#include <linux/pm.h>
#include <linux/regulator/consumer.h>
+
#include <drm/drm_atomic_helper.h>
#include <drm/drm_crtc.h>
#include <drm/drm_of.h>
#include <drm/drm_panel.h>
+#include <drm/drm_print.h>
#include <drm/drm_probe_helper.h>
-#include <drm/drmP.h>
/* Brightness scale on the Parade chip */
#define PS8622_MAX_BRIGHTNESS 0xff
diff --git a/drivers/gpu/drm/bridge/sii902x.c b/drivers/gpu/drm/bridge/sii902x.c
index 08e12fef1349..cdb8dfdb2dff 100644
--- a/drivers/gpu/drm/bridge/sii902x.c
+++ b/drivers/gpu/drm/bridge/sii902x.c
@@ -28,9 +28,10 @@
#include <linux/module.h>
#include <linux/regmap.h>
-#include <drm/drmP.h>
#include <drm/drm_atomic_helper.h>
+#include <drm/drm_drv.h>
#include <drm/drm_edid.h>
+#include <drm/drm_print.h>
#include <drm/drm_probe_helper.h>
#define SII902X_TPI_VIDEO_DATA 0x0
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
index ab7968c8f6a2..66bd66bad44c 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
@@ -11,34 +11,35 @@
* (at your option) any later version.
*
*/
-#include <linux/module.h>
-#include <linux/irq.h>
+#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/err.h>
-#include <linux/clk.h>
#include <linux/hdmi.h>
+#include <linux/irq.h>
+#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/of_device.h>
#include <linux/regmap.h>
+#include <linux/dma-mapping.h>
#include <linux/spinlock.h>
-#include <drm/drm_of.h>
-#include <drm/drmP.h>
+#include <media/cec-notifier.h>
+
+#include <uapi/linux/media-bus-format.h>
+#include <uapi/linux/videodev2.h>
+
+#include <drm/bridge/dw_hdmi.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_edid.h>
#include <drm/drm_encoder_slave.h>
-#include <drm/drm_scdc_helper.h>
+#include <drm/drm_of.h>
+#include <drm/drm_print.h>
#include <drm/drm_probe_helper.h>
-#include <drm/bridge/dw_hdmi.h>
-
-#include <uapi/linux/media-bus-format.h>
-#include <uapi/linux/videodev2.h>
+#include <drm/drm_scdc_helper.h>
-#include "dw-hdmi.h"
#include "dw-hdmi-audio.h"
#include "dw-hdmi-cec.h"
-
-#include <media/cec-notifier.h>
+#include "dw-hdmi.h"
#define DDC_SEGMENT_ADDR 0x30
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
index e915ae8c9a92..a79c87bd0147 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
@@ -15,15 +15,18 @@
#include <linux/of_device.h>
#include <linux/pm_runtime.h>
#include <linux/reset.h>
-#include <drm/drmP.h>
+
+#include <video/mipi_display.h>
+
+#include <drm/bridge/dw_mipi_dsi.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_bridge.h>
#include <drm/drm_crtc.h>
#include <drm/drm_mipi_dsi.h>
+#include <drm/drm_modes.h>
#include <drm/drm_of.h>
+#include <drm/drm_print.h>
#include <drm/drm_probe_helper.h>
-#include <drm/bridge/dw_mipi_dsi.h>
-#include <video/mipi_display.h>
#define HWVER_131 0x31333100 /* IP version 1.31 */
diff --git a/drivers/gpu/drm/bridge/tc358764.c b/drivers/gpu/drm/bridge/tc358764.c
index a20e454ddd64..170f162ffa55 100644
--- a/drivers/gpu/drm/bridge/tc358764.c
+++ b/drivers/gpu/drm/bridge/tc358764.c
@@ -7,18 +7,22 @@
* Maciej Purski <m.purski@samsung.com>
*/
+#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
+#include <linux/module.h>
+#include <linux/of_graph.h>
+#include <linux/regulator/consumer.h>
+
+#include <video/mipi_display.h>
+
#include <drm/drm_atomic_helper.h>
#include <drm/drm_crtc.h>
#include <drm/drm_fb_helper.h>
#include <drm/drm_mipi_dsi.h>
#include <drm/drm_of.h>
#include <drm/drm_panel.h>
+#include <drm/drm_print.h>
#include <drm/drm_probe_helper.h>
-#include <drm/drmP.h>
-#include <linux/gpio/consumer.h>
-#include <linux/of_graph.h>
-#include <linux/regulator/consumer.h>
-#include <video/mipi_display.h>
#define FLD_MASK(start, end) (((1 << ((start) - (end) + 1)) - 1) << (end))
#define FLD_VAL(val, start, end) (((val) << (end)) & FLD_MASK(start, end))
diff --git a/drivers/gpu/drm/bridge/thc63lvd1024.c b/drivers/gpu/drm/bridge/thc63lvd1024.c
index b083a740565c..fd597f58f4e6 100644
--- a/drivers/gpu/drm/bridge/thc63lvd1024.c
+++ b/drivers/gpu/drm/bridge/thc63lvd1024.c
@@ -5,15 +5,17 @@
* Copyright (C) 2018 Jacopo Mondi <jacopo+renesas@jmondi.org>
*/
-#include <drm/drmP.h>
-#include <drm/drm_bridge.h>
-#include <drm/drm_panel.h>
-
#include <linux/gpio/consumer.h>
+#include <linux/module.h>
+#include <linux/of.h>
#include <linux/of_graph.h>
+#include <linux/platform_device.h>
#include <linux/regulator/consumer.h>
#include <linux/slab.h>
+#include <drm/drm_bridge.h>
+#include <drm/drm_panel.h>
+
enum thc63_ports {
THC63_LVDS_IN0,
THC63_LVDS_IN1,
diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi86.c b/drivers/gpu/drm/bridge/ti-sn65dsi86.c
index f72ee137e5f1..b77a52d05061 100644
--- a/drivers/gpu/drm/bridge/ti-sn65dsi86.c
+++ b/drivers/gpu/drm/bridge/ti-sn65dsi86.c
@@ -3,23 +3,25 @@
* Copyright (c) 2018, The Linux Foundation. All rights reserved.
*/
-#include <drm/drmP.h>
-#include <drm/drm_atomic.h>
-#include <drm/drm_atomic_helper.h>
-#include <drm/drm_dp_helper.h>
-#include <drm/drm_mipi_dsi.h>
-#include <drm/drm_of.h>
-#include <drm/drm_panel.h>
-#include <drm/drm_probe_helper.h>
#include <linux/clk.h>
#include <linux/gpio/consumer.h>
#include <linux/i2c.h>
#include <linux/iopoll.h>
+#include <linux/module.h>
#include <linux/of_graph.h>
#include <linux/pm_runtime.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
+#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_dp_helper.h>
+#include <drm/drm_mipi_dsi.h>
+#include <drm/drm_of.h>
+#include <drm/drm_panel.h>
+#include <drm/drm_print.h>
+#include <drm/drm_probe_helper.h>
+
#define SN_DEVICE_REV_REG 0x08
#define SN_DPPLL_SRC_REG 0x0A
#define DPPLL_CLK_SRC_DSICLK BIT(0)
diff --git a/drivers/gpu/drm/bridge/ti-tfp410.c b/drivers/gpu/drm/bridge/ti-tfp410.c
index 8b0e71bd3ca7..bfb21b5eefe1 100644
--- a/drivers/gpu/drm/bridge/ti-tfp410.c
+++ b/drivers/gpu/drm/bridge/ti-tfp410.c
@@ -11,15 +11,15 @@
#include <linux/delay.h>
#include <linux/fwnode.h>
#include <linux/gpio/consumer.h>
+#include <linux/i2c.h>
#include <linux/irq.h>
#include <linux/module.h>
#include <linux/of_graph.h>
#include <linux/platform_device.h>
-#include <linux/i2c.h>
-#include <drm/drmP.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_crtc.h>
+#include <drm/drm_print.h>
#include <drm/drm_probe_helper.h>
#define HOTPLUG_DEBOUNCE_MS 1100
diff --git a/drivers/gpu/drm/drm_agpsupport.c b/drivers/gpu/drm/drm_agpsupport.c
index 40fba1c04dfc..117b8ee98243 100644
--- a/drivers/gpu/drm/drm_agpsupport.c
+++ b/drivers/gpu/drm/drm_agpsupport.c
@@ -31,13 +31,20 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
-#include <drm/drmP.h>
#include <linux/module.h>
+#include <linux/pci.h>
#include <linux/slab.h>
-#include "drm_legacy.h"
#include <asm/agp.h>
+#include <drm/drm_agpsupport.h>
+#include <drm/drm_device.h>
+#include <drm/drm_drv.h>
+#include <drm/drm_file.h>
+#include <drm/drm_print.h>
+
+#include "drm_legacy.h"
+
/**
* Get AGP information.
*
diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
index f4924cb7f495..b640e77184e5 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -26,13 +26,18 @@
*/
-#include <drm/drmP.h>
+#include <linux/sync_file.h>
+
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_uapi.h>
+#include <drm/drm_debugfs.h>
+#include <drm/drm_device.h>
+#include <drm/drm_drv.h>
+#include <drm/drm_file.h>
+#include <drm/drm_fourcc.h>
#include <drm/drm_mode.h>
#include <drm/drm_print.h>
#include <drm/drm_writeback.h>
-#include <linux/sync_file.h>
#include "drm_crtc_internal.h"
#include "drm_internal.h"
diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
index 79dbeafb9a52..acf993cb8e52 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -25,14 +25,17 @@
* Daniel Vetter <daniel.vetter@ffwll.ch>
*/
-#include <drm/drmP.h>
+#include <linux/dma-fence.h>
+
#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
#include <drm/drm_atomic_uapi.h>
+#include <drm/drm_damage_helper.h>
+#include <drm/drm_device.h>
#include <drm/drm_plane_helper.h>
-#include <drm/drm_atomic_helper.h>
+#include <drm/drm_print.h>
+#include <drm/drm_vblank.h>
#include <drm/drm_writeback.h>
-#include <drm/drm_damage_helper.h>
-#include <linux/dma-fence.h>
#include "drm_crtc_helper_internal.h"
#include "drm_crtc_internal.h"
diff --git a/drivers/gpu/drm/drm_atomic_state_helper.c b/drivers/gpu/drm/drm_atomic_state_helper.c
index ec13823153a9..97ab26679b96 100644
--- a/drivers/gpu/drm/drm_atomic_state_helper.c
+++ b/drivers/gpu/drm/drm_atomic_state_helper.c
@@ -24,12 +24,13 @@
* Daniel Vetter <daniel.vetter@ffwll.ch>
*/
+#include <drm/drm_atomic.h>
#include <drm/drm_atomic_state_helper.h>
-#include <drm/drm_crtc.h>
-#include <drm/drm_plane.h>
#include <drm/drm_connector.h>
-#include <drm/drm_atomic.h>
+#include <drm/drm_crtc.h>
#include <drm/drm_device.h>
+#include <drm/drm_plane.h>
+#include <drm/drm_print.h>
#include <drm/drm_writeback.h>
#include <linux/slab.h>
diff --git a/drivers/gpu/drm/drm_auth.c b/drivers/gpu/drm/drm_auth.c
index bf98402f3210..cc9acd986c68 100644
--- a/drivers/gpu/drm/drm_auth.c
+++ b/drivers/gpu/drm/drm_auth.c
@@ -28,10 +28,16 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
-#include <drm/drmP.h>
+#include <linux/slab.h>
+
+#include <drm/drm_auth.h>
+#include <drm/drm_drv.h>
+#include <drm/drm_file.h>
+#include <drm/drm_lease.h>
+#include <drm/drm_print.h>
+
#include "drm_internal.h"
#include "drm_legacy.h"
-#include <drm/drm_lease.h>
/**
* DOC: master and authentication
diff --git a/drivers/gpu/drm/drm_blend.c b/drivers/gpu/drm/drm_blend.c
index 0c78ca386cbe..37ac168fcb60 100644
--- a/drivers/gpu/drm/drm_blend.c
+++ b/drivers/gpu/drm/drm_blend.c
@@ -23,13 +23,16 @@
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
* OF THIS SOFTWARE.
*/
-#include <drm/drmP.h>
-#include <drm/drm_atomic.h>
-#include <drm/drm_blend.h>
+
#include <linux/export.h>
#include <linux/slab.h>
#include <linux/sort.h>
+#include <drm/drm_atomic.h>
+#include <drm/drm_blend.h>
+#include <drm/drm_device.h>
+#include <drm/drm_print.h>
+
#include "drm_crtc_internal.h"
/**
diff --git a/drivers/gpu/drm/drm_bufs.c b/drivers/gpu/drm/drm_bufs.c
index bfc419ed9d6c..68dacf8422c6 100644
--- a/drivers/gpu/drm/drm_bufs.c
+++ b/drivers/gpu/drm/drm_bufs.c
@@ -28,15 +28,26 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
-#include <linux/vmalloc.h>
-#include <linux/slab.h>
-#include <linux/log2.h>
#include <linux/export.h>
+#include <linux/log2.h>
+#include <linux/mm.h>
+#include <linux/mman.h>
+#include <linux/nospec.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+#include <linux/vmalloc.h>
+
#include <asm/shmparam.h>
-#include <drm/drmP.h>
+
+#include <drm/drm_agpsupport.h>
+#include <drm/drm_device.h>
+#include <drm/drm_drv.h>
+#include <drm/drm_file.h>
+#include <drm/drm_pci.h>
+#include <drm/drm_print.h>
+
#include "drm_legacy.h"
-#include <linux/nospec.h>
static struct drm_map_list *drm_find_matching_map(struct drm_device *dev,
struct drm_local_map *map)
diff --git a/drivers/gpu/drm/drm_client.c b/drivers/gpu/drm/drm_client.c
index 5abcd83da6a6..e7870a54f498 100644
--- a/drivers/gpu/drm/drm_client.c
+++ b/drivers/gpu/drm/drm_client.c
@@ -15,10 +15,10 @@
#include <drm/drm_drv.h>
#include <drm/drm_file.h>
#include <drm/drm_fourcc.h>
+#include <drm/drm_framebuffer.h>
#include <drm/drm_gem.h>
#include <drm/drm_mode.h>
#include <drm/drm_print.h>
-#include <drm/drmP.h>
#include "drm_crtc_internal.h"
#include "drm_internal.h"
diff --git a/drivers/gpu/drm/drm_color_mgmt.c b/drivers/gpu/drm/drm_color_mgmt.c
index d5d34d0c79c7..4ce5c6d8de99 100644
--- a/drivers/gpu/drm/drm_color_mgmt.c
+++ b/drivers/gpu/drm/drm_color_mgmt.c
@@ -20,9 +20,13 @@
* OF THIS SOFTWARE.
*/
-#include <drm/drmP.h>
-#include <drm/drm_crtc.h>
+#include <linux/uaccess.h>
+
#include <drm/drm_color_mgmt.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_device.h>
+#include <drm/drm_drv.h>
+#include <drm/drm_print.h>
#include "drm_crtc_internal.h"
diff --git a/drivers/gpu/drm/drm_context.c b/drivers/gpu/drm/drm_context.c
index 6e8e1a9fcae3..1f802d8e5681 100644
--- a/drivers/gpu/drm/drm_context.c
+++ b/drivers/gpu/drm/drm_context.c
@@ -28,7 +28,13 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
-#include <drm/drmP.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+
+#include <drm/drm_drv.h>
+#include <drm/drm_file.h>
+#include <drm/drm_print.h>
+
#include "drm_legacy.h"
struct drm_ctx_list {
diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c
index 747661f63fbb..6dd49a60deac 100644
--- a/drivers/gpu/drm/drm_crtc_helper.c
+++ b/drivers/gpu/drm/drm_crtc_helper.c
@@ -29,21 +29,23 @@
* Jesse Barnes <jesse.barnes@intel.com>
*/
-#include <linux/kernel.h>
#include <linux/export.h>
+#include <linux/kernel.h>
#include <linux/moduleparam.h>
-#include <drm/drmP.h>
#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
#include <drm/drm_atomic_uapi.h>
#include <drm/drm_crtc.h>
-#include <drm/drm_encoder.h>
-#include <drm/drm_fourcc.h>
#include <drm/drm_crtc_helper.h>
+#include <drm/drm_drv.h>
+#include <drm/drm_edid.h>
+#include <drm/drm_encoder.h>
#include <drm/drm_fb_helper.h>
+#include <drm/drm_fourcc.h>
#include <drm/drm_plane_helper.h>
-#include <drm/drm_atomic_helper.h>
-#include <drm/drm_edid.h>
+#include <drm/drm_print.h>
+#include <drm/drm_vblank.h>
/**
* DOC: overview
diff --git a/drivers/gpu/drm/drm_crtc_internal.h b/drivers/gpu/drm/drm_crtc_internal.h
index 0719a235d6cc..c78a44fad13d 100644
--- a/drivers/gpu/drm/drm_crtc_internal.h
+++ b/drivers/gpu/drm/drm_crtc_internal.h
@@ -31,14 +31,30 @@
* and are not exported to drivers.
*/
-enum drm_mode_status;
+#include <linux/types.h>
+
+enum drm_color_encoding;
+enum drm_color_range;
enum drm_connector_force;
+enum drm_mode_status;
-struct drm_display_mode;
-struct work_struct;
-struct drm_connector;
+struct drm_atomic_state;
struct drm_bridge;
+struct drm_connector;
+struct drm_crtc;
+struct drm_device;
+struct drm_display_mode;
+struct drm_file;
+struct drm_framebuffer;
+struct drm_mode_create_dumb;
+struct drm_mode_fb_cmd2;
+struct drm_mode_fb_cmd;
+struct drm_mode_object;
+struct drm_plane;
+struct drm_property;
struct edid;
+struct kref;
+struct work_struct;
/* drm_crtc.c */
int drm_mode_crtc_set_obj_prop(struct drm_mode_object *obj,
diff --git a/drivers/gpu/drm/drm_damage_helper.c b/drivers/gpu/drm/drm_damage_helper.c
index ee67c96841fa..8230dac01a89 100644
--- a/drivers/gpu/drm/drm_damage_helper.c
+++ b/drivers/gpu/drm/drm_damage_helper.c
@@ -286,7 +286,7 @@ drm_atomic_helper_damage_iter_init(struct drm_atomic_helper_damage_iter *iter,
iter->plane_src.y2 = (state->src.y2 >> 16) + !!(state->src.y2 & 0xFFFF);
if (!iter->clips || !drm_rect_equals(&state->src, &old_state->src)) {
- iter->clips = 0;
+ iter->clips = NULL;
iter->num_clips = 0;
iter->full_update = true;
}
diff --git a/drivers/gpu/drm/drm_debugfs.c b/drivers/gpu/drm/drm_debugfs.c
index f8468eae0503..4b8e817d7420 100644
--- a/drivers/gpu/drm/drm_debugfs.c
+++ b/drivers/gpu/drm/drm_debugfs.c
@@ -24,20 +24,23 @@
*/
#include <linux/debugfs.h>
+#include <linux/export.h>
#include <linux/seq_file.h>
#include <linux/slab.h>
-#include <linux/export.h>
+#include <linux/uaccess.h>
+#include <drm/drm_atomic.h>
+#include <drm/drm_auth.h>
#include <drm/drm_client.h>
#include <drm/drm_debugfs.h>
+#include <drm/drm_device.h>
+#include <drm/drm_drv.h>
#include <drm/drm_edid.h>
-#include <drm/drm_atomic.h>
-#include <drm/drm_auth.h>
+#include <drm/drm_file.h>
#include <drm/drm_gem.h>
-#include <drm/drmP.h>
-#include "drm_internal.h"
#include "drm_crtc_internal.h"
+#include "drm_internal.h"
#if defined(CONFIG_DEBUG_FS)
diff --git a/drivers/gpu/drm/drm_debugfs_crc.c b/drivers/gpu/drm/drm_debugfs_crc.c
index 00e743153e94..585169f0dcc5 100644
--- a/drivers/gpu/drm/drm_debugfs_crc.c
+++ b/drivers/gpu/drm/drm_debugfs_crc.c
@@ -29,7 +29,14 @@
#include <linux/circ_buf.h>
#include <linux/ctype.h>
#include <linux/debugfs.h>
-#include <drm/drmP.h>
+#include <linux/poll.h>
+#include <linux/uaccess.h>
+
+#include <drm/drm_crtc.h>
+#include <drm/drm_debugfs_crc.h>
+#include <drm/drm_drv.h>
+#include <drm/drm_print.h>
+
#include "drm_internal.h"
/**
diff --git a/drivers/gpu/drm/drm_dma.c b/drivers/gpu/drm/drm_dma.c
index 3f83e2ca80ad..5ef0227eaa0e 100644
--- a/drivers/gpu/drm/drm_dma.c
+++ b/drivers/gpu/drm/drm_dma.c
@@ -34,7 +34,11 @@
*/
#include <linux/export.h>
-#include <drm/drmP.h>
+
+#include <drm/drm_drv.h>
+#include <drm/drm_pci.h>
+#include <drm/drm_print.h>
+
#include "drm_legacy.h"
/**
diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
index 862621494a93..95a55d98e152 100644
--- a/drivers/gpu/drm/drm_drv.c
+++ b/drivers/gpu/drm/drm_drv.c
@@ -35,16 +35,19 @@
#include <linux/srcu.h>
#include <drm/drm_client.h>
+#include <drm/drm_color_mgmt.h>
#include <drm/drm_drv.h>
-#include <drm/drmP.h>
+#include <drm/drm_file.h>
+#include <drm/drm_mode_object.h>
+#include <drm/drm_print.h>
#include "drm_crtc_internal.h"
-#include "drm_legacy.h"
#include "drm_internal.h"
+#include "drm_legacy.h"
/*
* drm_debug: Enable debug output.
- * Bitmask of DRM_UT_x. See include/drm/drmP.h for details.
+ * Bitmask of DRM_UT_x. See include/drm/drm_print.h for details.
*/
unsigned int drm_debug = 0;
EXPORT_SYMBOL(drm_debug);
diff --git a/drivers/gpu/drm/drm_dumb_buffers.c b/drivers/gpu/drm/drm_dumb_buffers.c
index 81dfdd33753a..d18a740fe0f1 100644
--- a/drivers/gpu/drm/drm_dumb_buffers.c
+++ b/drivers/gpu/drm/drm_dumb_buffers.c
@@ -23,8 +23,10 @@
* OF THIS SOFTWARE.
*/
-#include <drm/drmP.h>
+#include <drm/drm_device.h>
+#include <drm/drm_drv.h>
#include <drm/drm_gem.h>
+#include <drm/drm_mode.h>
#include "drm_crtc_internal.h"
diff --git a/drivers/gpu/drm/drm_edid_load.c b/drivers/gpu/drm/drm_edid_load.c
index feb1df935a9e..d38b3b255926 100644
--- a/drivers/gpu/drm/drm_edid_load.c
+++ b/drivers/gpu/drm/drm_edid_load.c
@@ -281,6 +281,8 @@ struct edid *drm_load_edid_firmware(struct drm_connector *connector)
* the last one found one as a fallback.
*/
fwstr = kstrdup(edid_firmware, GFP_KERNEL);
+ if (!fwstr)
+ return ERR_PTR(-ENOMEM);
edidstr = fwstr;
while ((edidname = strsep(&edidstr, ","))) {
diff --git a/drivers/gpu/drm/drm_encoder.c b/drivers/gpu/drm/drm_encoder.c
index b694fb57eaa4..7fb47b7b8b44 100644
--- a/drivers/gpu/drm/drm_encoder.c
+++ b/drivers/gpu/drm/drm_encoder.c
@@ -21,7 +21,9 @@
*/
#include <linux/export.h>
-#include <drm/drmP.h>
+
+#include <drm/drm_device.h>
+#include <drm/drm_drv.h>
#include <drm/drm_encoder.h>
#include "drm_crtc_internal.h"
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index 302cf5f8bcce..3f4cb66c7d65 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -32,18 +32,23 @@
#include <linux/console.h>
#include <linux/dma-buf.h>
#include <linux/kernel.h>
-#include <linux/sysrq.h>
-#include <linux/slab.h>
#include <linux/module.h>
-#include <drm/drmP.h>
-#include <drm/drm_crtc.h>
-#include <drm/drm_fb_helper.h>
-#include <drm/drm_crtc_helper.h>
+#include <linux/slab.h>
+#include <linux/sysrq.h>
+#include <linux/vmalloc.h>
+
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_drv.h>
+#include <drm/drm_fb_helper.h>
+#include <drm/drm_fourcc.h>
+#include <drm/drm_print.h>
+#include <drm/drm_vblank.h>
-#include "drm_crtc_internal.h"
#include "drm_crtc_helper_internal.h"
+#include "drm_crtc_internal.h"
#include "drm_internal.h"
static bool drm_fbdev_emulation = true;
diff --git a/drivers/gpu/drm/drm_file.c b/drivers/gpu/drm/drm_file.c
index 075a7766bb79..754af25fe255 100644
--- a/drivers/gpu/drm/drm_file.c
+++ b/drivers/gpu/drm/drm_file.c
@@ -31,17 +31,20 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
+#include <linux/dma-fence.h>
+#include <linux/module.h>
+#include <linux/pci.h>
#include <linux/poll.h>
#include <linux/slab.h>
-#include <linux/module.h>
#include <drm/drm_client.h>
+#include <drm/drm_drv.h>
#include <drm/drm_file.h>
-#include <drm/drmP.h>
+#include <drm/drm_print.h>
-#include "drm_legacy.h"
-#include "drm_internal.h"
#include "drm_crtc_internal.h"
+#include "drm_internal.h"
+#include "drm_legacy.h"
/* from BKL pushdown */
DEFINE_MUTEX(drm_global_mutex);
diff --git a/drivers/gpu/drm/drm_flip_work.c b/drivers/gpu/drm/drm_flip_work.c
index 3da3bf5af405..060b753881a2 100644
--- a/drivers/gpu/drm/drm_flip_work.c
+++ b/drivers/gpu/drm/drm_flip_work.c
@@ -21,9 +21,11 @@
* SOFTWARE.
*/
-#include <drm/drmP.h>
-#include <drm/drm_util.h>
+#include <linux/slab.h>
+
#include <drm/drm_flip_work.h>
+#include <drm/drm_print.h>
+#include <drm/drm_util.h>
/**
* drm_flip_work_allocate_task - allocate a flip-work task
diff --git a/drivers/gpu/drm/drm_fourcc.c b/drivers/gpu/drm/drm_fourcc.c
index 35b459d186c5..c630064ccf41 100644
--- a/drivers/gpu/drm/drm_fourcc.c
+++ b/drivers/gpu/drm/drm_fourcc.c
@@ -27,7 +27,7 @@
#include <linux/export.h>
#include <linux/kernel.h>
-#include <drm/drmP.h>
+#include <drm/drm_device.h>
#include <drm/drm_fourcc.h>
static char printable_char(int c)
diff --git a/drivers/gpu/drm/drm_framebuffer.c b/drivers/gpu/drm/drm_framebuffer.c
index d8d75e25f6fb..0b72468e8131 100644
--- a/drivers/gpu/drm/drm_framebuffer.c
+++ b/drivers/gpu/drm/drm_framebuffer.c
@@ -21,16 +21,21 @@
*/
#include <linux/export.h>
-#include <drm/drmP.h>
-#include <drm/drm_auth.h>
-#include <drm/drm_framebuffer.h>
+#include <linux/uaccess.h>
+
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_uapi.h>
+#include <drm/drm_auth.h>
+#include <drm/drm_debugfs.h>
+#include <drm/drm_drv.h>
+#include <drm/drm_file.h>
+#include <drm/drm_fourcc.h>
+#include <drm/drm_framebuffer.h>
#include <drm/drm_print.h>
#include <drm/drm_util.h>
-#include "drm_internal.h"
#include "drm_crtc_internal.h"
+#include "drm_internal.h"
/**
* DOC: overview
diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c
index 50de138c89e0..8a55f71325b1 100644
--- a/drivers/gpu/drm/drm_gem.c
+++ b/drivers/gpu/drm/drm_gem.c
@@ -38,10 +38,14 @@
#include <linux/dma-buf.h>
#include <linux/mem_encrypt.h>
#include <linux/pagevec.h>
-#include <drm/drmP.h>
-#include <drm/drm_vma_manager.h>
+
+#include <drm/drm_device.h>
+#include <drm/drm_drv.h>
+#include <drm/drm_file.h>
#include <drm/drm_gem.h>
#include <drm/drm_print.h>
+#include <drm/drm_vma_manager.h>
+
#include "drm_internal.h"
/** @file drm_gem.c
diff --git a/drivers/gpu/drm/drm_gem_cma_helper.c b/drivers/gpu/drm/drm_gem_cma_helper.c
index e01ceed09e67..0cb1bbed1f68 100644
--- a/drivers/gpu/drm/drm_gem_cma_helper.c
+++ b/drivers/gpu/drm/drm_gem_cma_helper.c
@@ -17,15 +17,16 @@
* GNU General Public License for more details.
*/
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/mutex.h>
-#include <linux/export.h>
#include <linux/dma-buf.h>
#include <linux/dma-mapping.h>
+#include <linux/export.h>
+#include <linux/mm.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
-#include <drm/drmP.h>
#include <drm/drm.h>
+#include <drm/drm_device.h>
+#include <drm/drm_drv.h>
#include <drm/drm_gem_cma_helper.h>
#include <drm/drm_vma_manager.h>
diff --git a/drivers/gpu/drm/drm_gem_framebuffer_helper.c b/drivers/gpu/drm/drm_gem_framebuffer_helper.c
index 65edb1ccb185..6fd48efe288c 100644
--- a/drivers/gpu/drm/drm_gem_framebuffer_helper.c
+++ b/drivers/gpu/drm/drm_gem_framebuffer_helper.c
@@ -14,7 +14,6 @@
#include <linux/reservation.h>
#include <linux/slab.h>
-#include <drm/drmP.h>
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_uapi.h>
#include <drm/drm_damage_helper.h>
diff --git a/drivers/gpu/drm/drm_hashtab.c b/drivers/gpu/drm/drm_hashtab.c
index c92b00d42ece..c50fa6f0709f 100644
--- a/drivers/gpu/drm/drm_hashtab.c
+++ b/drivers/gpu/drm/drm_hashtab.c
@@ -32,11 +32,15 @@
* Thomas Hellström <thomas-at-tungstengraphics-dot-com>
*/
-#include <drm/drmP.h>
-#include <drm/drm_hashtab.h>
+#include <linux/export.h>
#include <linux/hash.h>
+#include <linux/mm.h>
+#include <linux/rculist.h>
#include <linux/slab.h>
-#include <linux/export.h>
+#include <linux/vmalloc.h>
+
+#include <drm/drm_hashtab.h>
+#include <drm/drm_print.h>
int drm_ht_create(struct drm_open_hash *ht, unsigned int order)
{
diff --git a/drivers/gpu/drm/drm_internal.h b/drivers/gpu/drm/drm_internal.h
index e6a900c7c1fc..596e9f4ca7fc 100644
--- a/drivers/gpu/drm/drm_internal.h
+++ b/drivers/gpu/drm/drm_internal.h
@@ -28,8 +28,16 @@
#define DRM_IF_VERSION(maj, min) (maj << 16 | min)
-struct drm_prime_file_private;
+struct dentry;
struct dma_buf;
+struct drm_connector;
+struct drm_crtc;
+struct drm_framebuffer;
+struct drm_gem_object;
+struct drm_master;
+struct drm_minor;
+struct drm_prime_file_private;
+struct drm_printer;
/* drm_file.c */
extern struct mutex drm_global_mutex;
diff --git a/drivers/gpu/drm/drm_ioc32.c b/drivers/gpu/drm/drm_ioc32.c
index 374b372da58a..586aa28024c5 100644
--- a/drivers/gpu/drm/drm_ioc32.c
+++ b/drivers/gpu/drm/drm_ioc32.c
@@ -31,10 +31,13 @@
#include <linux/ratelimit.h>
#include <linux/export.h>
-#include <drm/drmP.h>
-#include "drm_legacy.h"
-#include "drm_internal.h"
+#include <drm/drm_agpsupport.h>
+#include <drm/drm_file.h>
+#include <drm/drm_print.h>
+
#include "drm_crtc_internal.h"
+#include "drm_internal.h"
+#include "drm_legacy.h"
#define DRM_IOCTL_VERSION32 DRM_IOWR(0x00, drm_version32_t)
#define DRM_IOCTL_GET_UNIQUE32 DRM_IOWR(0x01, drm_unique32_t)
diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c
index 2263e3ddd822..9441a36a2469 100644
--- a/drivers/gpu/drm/drm_ioctl.c
+++ b/drivers/gpu/drm/drm_ioctl.c
@@ -28,16 +28,22 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
-#include <drm/drm_ioctl.h>
-#include <drm/drmP.h>
-#include <drm/drm_auth.h>
-#include "drm_legacy.h"
-#include "drm_internal.h"
-#include "drm_crtc_internal.h"
-
-#include <linux/pci.h>
#include <linux/export.h>
#include <linux/nospec.h>
+#include <linux/pci.h>
+#include <linux/uaccess.h>
+
+#include <drm/drm_agpsupport.h>
+#include <drm/drm_auth.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_drv.h>
+#include <drm/drm_file.h>
+#include <drm/drm_ioctl.h>
+#include <drm/drm_print.h>
+
+#include "drm_crtc_internal.h"
+#include "drm_internal.h"
+#include "drm_legacy.h"
/**
* DOC: getunique and setversion story
diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c
index 02f38cc9f468..03bce566a8c3 100644
--- a/drivers/gpu/drm/drm_irq.c
+++ b/drivers/gpu/drm/drm_irq.c
@@ -51,13 +51,18 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
-#include <drm/drm_irq.h>
-#include <drm/drmP.h>
+#include <linux/export.h>
#include <linux/interrupt.h> /* For task queue support */
-
+#include <linux/pci.h>
#include <linux/vgaarb.h>
-#include <linux/export.h>
+
+#include <drm/drm.h>
+#include <drm/drm_device.h>
+#include <drm/drm_drv.h>
+#include <drm/drm_irq.h>
+#include <drm/drm_print.h>
+#include <drm/drm_vblank.h>
#include "drm_internal.h"
diff --git a/drivers/gpu/drm/drm_kms_helper_common.c b/drivers/gpu/drm/drm_kms_helper_common.c
index 9c5ae825c507..d9a5ac81949e 100644
--- a/drivers/gpu/drm/drm_kms_helper_common.c
+++ b/drivers/gpu/drm/drm_kms_helper_common.c
@@ -26,7 +26,8 @@
*/
#include <linux/module.h>
-#include <drm/drmP.h>
+
+#include <drm/drm_print.h>
#include "drm_crtc_helper_internal.h"
diff --git a/drivers/gpu/drm/drm_lease.c b/drivers/gpu/drm/drm_lease.c
index 694ff363a90b..849da9414450 100644
--- a/drivers/gpu/drm/drm_lease.c
+++ b/drivers/gpu/drm/drm_lease.c
@@ -11,14 +11,19 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*/
+#include <linux/file.h>
+#include <linux/uaccess.h>
-#include <drm/drmP.h>
-#include "drm_internal.h"
-#include "drm_legacy.h"
-#include "drm_crtc_internal.h"
-#include <drm/drm_lease.h>
#include <drm/drm_auth.h>
#include <drm/drm_crtc_helper.h>
+#include <drm/drm_drv.h>
+#include <drm/drm_file.h>
+#include <drm/drm_lease.h>
+#include <drm/drm_print.h>
+
+#include "drm_crtc_internal.h"
+#include "drm_internal.h"
+#include "drm_legacy.h"
#define drm_for_each_lessee(lessee, lessor) \
list_for_each_entry((lessee), &(lessor)->lessees, lessee_list)
diff --git a/drivers/gpu/drm/drm_legacy.h b/drivers/gpu/drm/drm_legacy.h
index 013ccdfd90be..1be3ea320474 100644
--- a/drivers/gpu/drm/drm_legacy.h
+++ b/drivers/gpu/drm/drm_legacy.h
@@ -29,11 +29,15 @@
* drivers use them, and removing them are API breaks.
*/
#include <linux/list.h>
+
+#include <drm/drm.h>
+#include <drm/drm_device.h>
#include <drm/drm_legacy.h>
struct agp_memory;
struct drm_device;
struct drm_file;
+struct drm_buf_desc;
/*
* Generic DRM Contexts
diff --git a/drivers/gpu/drm/drm_legacy_misc.c b/drivers/gpu/drm/drm_legacy_misc.c
index 18d05a6c12b3..4d3a11cfd979 100644
--- a/drivers/gpu/drm/drm_legacy_misc.c
+++ b/drivers/gpu/drm/drm_legacy_misc.c
@@ -33,7 +33,12 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
-#include <drm/drmP.h>
+#include <drm/drm_agpsupport.h>
+#include <drm/drm_device.h>
+#include <drm/drm_drv.h>
+#include <drm/drm_irq.h>
+#include <drm/drm_print.h>
+
#include "drm_internal.h"
#include "drm_legacy.h"
diff --git a/drivers/gpu/drm/drm_lock.c b/drivers/gpu/drm/drm_lock.c
index b70058e77a28..68b18b0e290c 100644
--- a/drivers/gpu/drm/drm_lock.c
+++ b/drivers/gpu/drm/drm_lock.c
@@ -36,9 +36,13 @@
#include <linux/export.h>
#include <linux/sched/signal.h>
-#include <drm/drmP.h>
-#include "drm_legacy.h"
+#include <drm/drm.h>
+#include <drm/drm_drv.h>
+#include <drm/drm_file.h>
+#include <drm/drm_print.h>
+
#include "drm_internal.h"
+#include "drm_legacy.h"
static int drm_lock_take(struct drm_lock_data *lock_data, unsigned int context);
diff --git a/drivers/gpu/drm/drm_memory.c b/drivers/gpu/drm/drm_memory.c
index 132fef8ff1b6..b634e1670190 100644
--- a/drivers/gpu/drm/drm_memory.c
+++ b/drivers/gpu/drm/drm_memory.c
@@ -33,10 +33,15 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
-#include <linux/highmem.h>
#include <linux/export.h>
+#include <linux/highmem.h>
+#include <linux/pci.h>
+#include <linux/vmalloc.h>
#include <xen/xen.h>
-#include <drm/drmP.h>
+
+#include <drm/drm_agpsupport.h>
+#include <drm/drm_device.h>
+
#include "drm_legacy.h"
#if IS_ENABLED(CONFIG_AGP)
diff --git a/drivers/gpu/drm/drm_mm.c b/drivers/gpu/drm/drm_mm.c
index 8b4cd31ce7bd..9a59865ce574 100644
--- a/drivers/gpu/drm/drm_mm.c
+++ b/drivers/gpu/drm/drm_mm.c
@@ -42,12 +42,13 @@
* Thomas Hellström <thomas-at-tungstengraphics-dot-com>
*/
-#include <drm/drmP.h>
-#include <drm/drm_mm.h>
-#include <linux/slab.h>
-#include <linux/seq_file.h>
#include <linux/export.h>
#include <linux/interval_tree_generic.h>
+#include <linux/seq_file.h>
+#include <linux/slab.h>
+#include <linux/stacktrace.h>
+
+#include <drm/drm_mm.h>
/**
* DOC: Overview
diff --git a/drivers/gpu/drm/drm_mode_config.c b/drivers/gpu/drm/drm_mode_config.c
index 1a346ae1599d..7bc03c3c154f 100644
--- a/drivers/gpu/drm/drm_mode_config.c
+++ b/drivers/gpu/drm/drm_mode_config.c
@@ -20,9 +20,13 @@
* OF THIS SOFTWARE.
*/
+#include <linux/uaccess.h>
+
+#include <drm/drm_drv.h>
#include <drm/drm_encoder.h>
+#include <drm/drm_file.h>
#include <drm/drm_mode_config.h>
-#include <drm/drmP.h>
+#include <drm/drm_print.h>
#include "drm_crtc_internal.h"
#include "drm_internal.h"
diff --git a/drivers/gpu/drm/drm_mode_object.c b/drivers/gpu/drm/drm_mode_object.c
index f32507e65b79..1c6e51135962 100644
--- a/drivers/gpu/drm/drm_mode_object.c
+++ b/drivers/gpu/drm/drm_mode_object.c
@@ -21,9 +21,14 @@
*/
#include <linux/export.h>
-#include <drm/drmP.h>
-#include <drm/drm_mode_object.h>
+#include <linux/uaccess.h>
+
#include <drm/drm_atomic.h>
+#include <drm/drm_drv.h>
+#include <drm/drm_device.h>
+#include <drm/drm_file.h>
+#include <drm/drm_mode_object.h>
+#include <drm/drm_print.h>
#include "drm_crtc_internal.h"
diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
index 56f92a0bba62..5a07a28fec6d 100644
--- a/drivers/gpu/drm/drm_modes.c
+++ b/drivers/gpu/drm/drm_modes.c
@@ -33,11 +33,14 @@
#include <linux/list.h>
#include <linux/list_sort.h>
#include <linux/export.h>
-#include <drm/drmP.h>
-#include <drm/drm_crtc.h>
+
#include <video/of_videomode.h>
#include <video/videomode.h>
+
+#include <drm/drm_crtc.h>
+#include <drm/drm_device.h>
#include <drm/drm_modes.h>
+#include <drm/drm_print.h>
#include "drm_crtc_internal.h"
diff --git a/drivers/gpu/drm/drm_modeset_lock.c b/drivers/gpu/drm/drm_modeset_lock.c
index 81dd11901ffd..53187821df01 100644
--- a/drivers/gpu/drm/drm_modeset_lock.c
+++ b/drivers/gpu/drm/drm_modeset_lock.c
@@ -21,9 +21,9 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
-#include <drm/drmP.h>
#include <drm/drm_atomic.h>
#include <drm/drm_crtc.h>
+#include <drm/drm_device.h>
#include <drm/drm_modeset_lock.h>
/**
diff --git a/drivers/gpu/drm/drm_of.c b/drivers/gpu/drm/drm_of.c
index 6becf63f9166..43d89dd59c6b 100644
--- a/drivers/gpu/drm/drm_of.c
+++ b/drivers/gpu/drm/drm_of.c
@@ -3,12 +3,13 @@
#include <linux/export.h>
#include <linux/list.h>
#include <linux/of_graph.h>
-#include <drm/drmP.h>
+
#include <drm/drm_bridge.h>
#include <drm/drm_crtc.h>
+#include <drm/drm_device.h>
#include <drm/drm_encoder.h>
-#include <drm/drm_panel.h>
#include <drm/drm_of.h>
+#include <drm/drm_panel.h>
/**
* DOC: overview
diff --git a/drivers/gpu/drm/drm_pci.c b/drivers/gpu/drm/drm_pci.c
index 693748ad8b88..a86a3ab2771c 100644
--- a/drivers/gpu/drm/drm_pci.c
+++ b/drivers/gpu/drm/drm_pci.c
@@ -22,12 +22,17 @@
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
-#include <linux/pci.h>
-#include <linux/slab.h>
#include <linux/dma-mapping.h>
#include <linux/export.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+
+#include <drm/drm.h>
+#include <drm/drm_agpsupport.h>
+#include <drm/drm_drv.h>
#include <drm/drm_pci.h>
-#include <drm/drmP.h>
+#include <drm/drm_print.h>
+
#include "drm_internal.h"
#include "drm_legacy.h"
diff --git a/drivers/gpu/drm/drm_plane_helper.c b/drivers/gpu/drm/drm_plane_helper.c
index 0fff72dcd06d..3aae7ea522f2 100644
--- a/drivers/gpu/drm/drm_plane_helper.c
+++ b/drivers/gpu/drm/drm_plane_helper.c
@@ -24,14 +24,15 @@
*/
#include <linux/list.h>
-#include <drm/drmP.h>
-#include <drm/drm_plane_helper.h>
-#include <drm/drm_rect.h>
+
#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
#include <drm/drm_atomic_uapi.h>
#include <drm/drm_crtc_helper.h>
+#include <drm/drm_device.h>
#include <drm/drm_encoder.h>
-#include <drm/drm_atomic_helper.h>
+#include <drm/drm_plane_helper.h>
+#include <drm/drm_rect.h>
#define SUBPIXEL_MASK 0xffff
diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c
index 706034fd403f..d0c01318076b 100644
--- a/drivers/gpu/drm/drm_prime.c
+++ b/drivers/gpu/drm/drm_prime.c
@@ -29,9 +29,12 @@
#include <linux/export.h>
#include <linux/dma-buf.h>
#include <linux/rbtree.h>
-#include <drm/drm_prime.h>
+
+#include <drm/drm_drv.h>
+#include <drm/drm_file.h>
+#include <drm/drm_framebuffer.h>
#include <drm/drm_gem.h>
-#include <drm/drmP.h>
+#include <drm/drm_prime.h>
#include "drm_internal.h"
diff --git a/drivers/gpu/drm/drm_print.c b/drivers/gpu/drm/drm_print.c
index f5cb0aabfe35..a17c8a14dba4 100644
--- a/drivers/gpu/drm/drm_print.c
+++ b/drivers/gpu/drm/drm_print.c
@@ -26,8 +26,13 @@
#define DEBUG /* for pr_debug() */
#include <stdarg.h>
+
+#include <linux/io.h>
#include <linux/seq_file.h>
-#include <drm/drmP.h>
+#include <linux/slab.h>
+
+#include <drm/drm.h>
+#include <drm/drm_drv.h>
#include <drm/drm_print.h>
void __drm_puts_coredump(struct drm_printer *p, const char *str)
diff --git a/drivers/gpu/drm/drm_probe_helper.c b/drivers/gpu/drm/drm_probe_helper.c
index 6fd08e04b323..43c85e1b467e 100644
--- a/drivers/gpu/drm/drm_probe_helper.c
+++ b/drivers/gpu/drm/drm_probe_helper.c
@@ -32,14 +32,15 @@
#include <linux/export.h>
#include <linux/moduleparam.h>
-#include <drm/drmP.h>
#include <drm/drm_client.h>
#include <drm/drm_crtc.h>
-#include <drm/drm_fourcc.h>
-#include <drm/drm_fb_helper.h>
#include <drm/drm_edid.h>
+#include <drm/drm_fb_helper.h>
+#include <drm/drm_fourcc.h>
#include <drm/drm_modeset_helper_vtables.h>
+#include <drm/drm_print.h>
#include <drm/drm_probe_helper.h>
+#include <drm/drm_sysfs.h>
#include "drm_crtc_helper_internal.h"
diff --git a/drivers/gpu/drm/drm_property.c b/drivers/gpu/drm/drm_property.c
index f8ec8f9c3e7a..892ce636ef72 100644
--- a/drivers/gpu/drm/drm_property.c
+++ b/drivers/gpu/drm/drm_property.c
@@ -21,7 +21,12 @@
*/
#include <linux/export.h>
-#include <drm/drmP.h>
+#include <linux/uaccess.h>
+
+#include <drm/drm_crtc.h>
+#include <drm/drm_drv.h>
+#include <drm/drm_file.h>
+#include <drm/drm_framebuffer.h>
#include <drm/drm_property.h>
#include "drm_crtc_internal.h"
diff --git a/drivers/gpu/drm/drm_rect.c b/drivers/gpu/drm/drm_rect.c
index 66c41b12719c..b8363aaa9032 100644
--- a/drivers/gpu/drm/drm_rect.c
+++ b/drivers/gpu/drm/drm_rect.c
@@ -24,7 +24,9 @@
#include <linux/errno.h>
#include <linux/export.h>
#include <linux/kernel.h>
-#include <drm/drmP.h>
+
+#include <drm/drm_mode.h>
+#include <drm/drm_print.h>
#include <drm/drm_rect.h>
/**
diff --git a/drivers/gpu/drm/drm_scatter.c b/drivers/gpu/drm/drm_scatter.c
index bb829a115fc6..2d7790f14b0c 100644
--- a/drivers/gpu/drm/drm_scatter.c
+++ b/drivers/gpu/drm/drm_scatter.c
@@ -31,9 +31,14 @@
* DEALINGS IN THE SOFTWARE.
*/
-#include <linux/vmalloc.h>
+#include <linux/mm.h>
#include <linux/slab.h>
-#include <drm/drmP.h>
+#include <linux/vmalloc.h>
+
+#include <drm/drm.h>
+#include <drm/drm_drv.h>
+#include <drm/drm_print.h>
+
#include "drm_legacy.h"
#define DEBUG_SCATTER 0
diff --git a/drivers/gpu/drm/drm_scdc_helper.c b/drivers/gpu/drm/drm_scdc_helper.c
index 870e25f1f788..311e71bbba5b 100644
--- a/drivers/gpu/drm/drm_scdc_helper.c
+++ b/drivers/gpu/drm/drm_scdc_helper.c
@@ -24,8 +24,8 @@
#include <linux/slab.h>
#include <linux/delay.h>
+#include <drm/drm_print.h>
#include <drm/drm_scdc_helper.h>
-#include <drm/drmP.h>
/**
* DOC: scdc helpers
diff --git a/drivers/gpu/drm/drm_simple_kms_helper.c b/drivers/gpu/drm/drm_simple_kms_helper.c
index a32f14cd7398..77c9645e17ed 100644
--- a/drivers/gpu/drm/drm_simple_kms_helper.c
+++ b/drivers/gpu/drm/drm_simple_kms_helper.c
@@ -7,13 +7,14 @@
* (at your option) any later version.
*/
-#include <drm/drmP.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_plane_helper.h>
#include <drm/drm_probe_helper.h>
#include <drm/drm_simple_kms_helper.h>
-#include <linux/slab.h>
/**
* DOC: overview
diff --git a/drivers/gpu/drm/drm_syncobj.c b/drivers/gpu/drm/drm_syncobj.c
index 3d400905100b..a199c8d56b95 100644
--- a/drivers/gpu/drm/drm_syncobj.c
+++ b/drivers/gpu/drm/drm_syncobj.c
@@ -46,16 +46,21 @@
* The file takes a reference on the kref.
*/
-#include <drm/drmP.h>
+#include <linux/anon_inodes.h>
#include <linux/file.h>
#include <linux/fs.h>
-#include <linux/anon_inodes.h>
-#include <linux/sync_file.h>
#include <linux/sched/signal.h>
+#include <linux/sync_file.h>
+#include <linux/uaccess.h>
-#include "drm_internal.h"
+#include <drm/drm_drv.h>
+#include <drm/drm_file.h>
+#include <drm/drm_gem.h>
+#include <drm/drm_print.h>
#include <drm/drm_syncobj.h>
+#include "drm_internal.h"
+
struct syncobj_wait_entry {
struct list_head node;
struct task_struct *task;
diff --git a/drivers/gpu/drm/drm_sysfs.c b/drivers/gpu/drm/drm_sysfs.c
index 18b1ac442997..acc44a55133d 100644
--- a/drivers/gpu/drm/drm_sysfs.c
+++ b/drivers/gpu/drm/drm_sysfs.c
@@ -13,13 +13,20 @@
*/
#include <linux/device.h>
-#include <linux/kdev_t.h>
-#include <linux/gfp.h>
#include <linux/err.h>
#include <linux/export.h>
-
+#include <linux/gfp.h>
+#include <linux/kdev_t.h>
+#include <linux/slab.h>
+
+#include <drm/drm_connector.h>
+#include <drm/drm_device.h>
+#include <drm/drm_file.h>
+#include <drm/drm_modes.h>
+#include <drm/drm_print.h>
+#include <drm/drm_property.h>
#include <drm/drm_sysfs.h>
-#include <drm/drmP.h>
+
#include "drm_internal.h"
#define to_drm_minor(d) dev_get_drvdata(d)
diff --git a/drivers/gpu/drm/drm_trace.h b/drivers/gpu/drm/drm_trace.h
index baccc63db106..471eb927474b 100644
--- a/drivers/gpu/drm/drm_trace.h
+++ b/drivers/gpu/drm/drm_trace.h
@@ -6,6 +6,8 @@
#include <linux/types.h>
#include <linux/tracepoint.h>
+struct drm_file;
+
#undef TRACE_SYSTEM
#define TRACE_SYSTEM drm
#define TRACE_INCLUDE_FILE drm_trace
diff --git a/drivers/gpu/drm/drm_trace_points.c b/drivers/gpu/drm/drm_trace_points.c
index 3bbc4deb4dbc..1e2065b403c9 100644
--- a/drivers/gpu/drm/drm_trace_points.c
+++ b/drivers/gpu/drm/drm_trace_points.c
@@ -1,4 +1,5 @@
-#include <drm/drmP.h>
+
+#include <drm/drm_file.h>
#define CREATE_TRACE_POINTS
#include "drm_trace.h"
diff --git a/drivers/gpu/drm/drm_vblank.c b/drivers/gpu/drm/drm_vblank.c
index a1b65d26d761..0d704bddb1a6 100644
--- a/drivers/gpu/drm/drm_vblank.c
+++ b/drivers/gpu/drm/drm_vblank.c
@@ -24,12 +24,18 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
-#include <drm/drm_vblank.h>
-#include <drm/drmP.h>
#include <linux/export.h>
+#include <linux/moduleparam.h>
+
+#include <drm/drm_crtc.h>
+#include <drm/drm_drv.h>
+#include <drm/drm_framebuffer.h>
+#include <drm/drm_print.h>
+#include <drm/drm_os_linux.h>
+#include <drm/drm_vblank.h>
-#include "drm_trace.h"
#include "drm_internal.h"
+#include "drm_trace.h"
/**
* DOC: vblank handling
diff --git a/drivers/gpu/drm/drm_vm.c b/drivers/gpu/drm/drm_vm.c
index 10cf83d569e1..2f24ee6c7a92 100644
--- a/drivers/gpu/drm/drm_vm.c
+++ b/drivers/gpu/drm/drm_vm.c
@@ -33,15 +33,27 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
-#include <drm/drmP.h>
#include <linux/export.h>
+#include <linux/pci.h>
#include <linux/seq_file.h>
+#include <linux/vmalloc.h>
+
#if defined(__ia64__)
#include <linux/efi.h>
#include <linux/slab.h>
#endif
#include <linux/mem_encrypt.h>
+
#include <asm/pgtable.h>
+
+#include <drm/drm_agpsupport.h>
+#include <drm/drm_device.h>
+#include <drm/drm_drv.h>
+#include <drm/drm_file.h>
+#include <drm/drm_framebuffer.h>
+#include <drm/drm_gem.h>
+#include <drm/drm_print.h>
+
#include "drm_internal.h"
#include "drm_legacy.h"
diff --git a/drivers/gpu/drm/drm_vma_manager.c b/drivers/gpu/drm/drm_vma_manager.c
index c5d0d2358301..4565319fa6b3 100644
--- a/drivers/gpu/drm/drm_vma_manager.c
+++ b/drivers/gpu/drm/drm_vma_manager.c
@@ -23,9 +23,6 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
-#include <drm/drmP.h>
-#include <drm/drm_mm.h>
-#include <drm/drm_vma_manager.h>
#include <linux/mm.h>
#include <linux/module.h>
#include <linux/rbtree.h>
@@ -33,6 +30,9 @@
#include <linux/spinlock.h>
#include <linux/types.h>
+#include <drm/drm_mm.h>
+#include <drm/drm_vma_manager.h>
+
/**
* DOC: vma offset manager
*
diff --git a/drivers/gpu/drm/drm_vram_mm_helper.c b/drivers/gpu/drm/drm_vram_mm_helper.c
index c94a6dc5ade7..c911781d6728 100644
--- a/drivers/gpu/drm/drm_vram_mm_helper.c
+++ b/drivers/gpu/drm/drm_vram_mm_helper.c
@@ -1,7 +1,9 @@
// SPDX-License-Identifier: GPL-2.0-or-later
+#include <drm/drm_device.h>
+#include <drm/drm_file.h>
#include <drm/drm_vram_mm_helper.h>
-#include <drm/drmP.h>
+
#include <drm/ttm/ttm_page_alloc.h>
/**
diff --git a/drivers/gpu/drm/drm_writeback.c b/drivers/gpu/drm/drm_writeback.c
index 79ac014701c8..ff138b6ec48b 100644
--- a/drivers/gpu/drm/drm_writeback.c
+++ b/drivers/gpu/drm/drm_writeback.c
@@ -9,12 +9,14 @@
* of such GNU licence.
*/
+#include <linux/dma-fence.h>
+
#include <drm/drm_crtc.h>
+#include <drm/drm_device.h>
+#include <drm/drm_drv.h>
#include <drm/drm_modeset_helper_vtables.h>
#include <drm/drm_property.h>
#include <drm/drm_writeback.h>
-#include <drm/drmP.h>
-#include <linux/dma-fence.h>
/**
* DOC: overview
diff --git a/drivers/gpu/drm/mcde/Kconfig b/drivers/gpu/drm/mcde/Kconfig
new file mode 100644
index 000000000000..b3990126562c
--- /dev/null
+++ b/drivers/gpu/drm/mcde/Kconfig
@@ -0,0 +1,18 @@
+config DRM_MCDE
+ tristate "DRM Support for ST-Ericsson MCDE (Multichannel Display Engine)"
+ depends on DRM
+ depends on CMA
+ depends on ARM || COMPILE_TEST
+ depends on OF
+ select MFD_SYSCON
+ select DRM_MIPI_DSI
+ select DRM_BRIDGE
+ select DRM_PANEL_BRIDGE
+ select DRM_KMS_HELPER
+ select DRM_KMS_CMA_HELPER
+ select DRM_GEM_CMA_HELPER
+ select VT_HW_CONSOLE_BINDING if FRAMEBUFFER_CONSOLE
+ help
+ Choose this option for DRM support for the ST-Ericsson MCDE
+ Multi-Channel Display Engine.
+ If M is selected the module will be called mcde_drm.
diff --git a/drivers/gpu/drm/mcde/Makefile b/drivers/gpu/drm/mcde/Makefile
new file mode 100644
index 000000000000..fe28f4e0fe46
--- /dev/null
+++ b/drivers/gpu/drm/mcde/Makefile
@@ -0,0 +1,3 @@
+mcde_drm-y += mcde_drv.o mcde_dsi.o mcde_display.o
+
+obj-$(CONFIG_DRM_MCDE) += mcde_drm.o
diff --git a/drivers/gpu/drm/mcde/mcde_display.c b/drivers/gpu/drm/mcde/mcde_display.c
new file mode 100644
index 000000000000..f3ef108a41d9
--- /dev/null
+++ b/drivers/gpu/drm/mcde/mcde_display.c
@@ -0,0 +1,1142 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2018 Linus Walleij <linus.walleij@linaro.org>
+ * Parts of this file were based on the MCDE driver by Marcus Lorentzon
+ * (C) ST-Ericsson SA 2013
+ */
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/dma-buf.h>
+
+#include <drm/drm_device.h>
+#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_fourcc.h>
+#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_gem_framebuffer_helper.h>
+#include <drm/drm_mipi_dsi.h>
+#include <drm/drm_simple_kms_helper.h>
+#include <drm/drm_vblank.h>
+#include <video/mipi_display.h>
+
+#include "mcde_drm.h"
+#include "mcde_display_regs.h"
+
+enum mcde_fifo {
+ MCDE_FIFO_A,
+ MCDE_FIFO_B,
+ /* TODO: implement FIFO C0 and FIFO C1 */
+};
+
+enum mcde_channel {
+ MCDE_CHANNEL_0 = 0,
+ MCDE_CHANNEL_1,
+ MCDE_CHANNEL_2,
+ MCDE_CHANNEL_3,
+};
+
+enum mcde_extsrc {
+ MCDE_EXTSRC_0 = 0,
+ MCDE_EXTSRC_1,
+ MCDE_EXTSRC_2,
+ MCDE_EXTSRC_3,
+ MCDE_EXTSRC_4,
+ MCDE_EXTSRC_5,
+ MCDE_EXTSRC_6,
+ MCDE_EXTSRC_7,
+ MCDE_EXTSRC_8,
+ MCDE_EXTSRC_9,
+};
+
+enum mcde_overlay {
+ MCDE_OVERLAY_0 = 0,
+ MCDE_OVERLAY_1,
+ MCDE_OVERLAY_2,
+ MCDE_OVERLAY_3,
+ MCDE_OVERLAY_4,
+ MCDE_OVERLAY_5,
+};
+
+enum mcde_dsi_formatter {
+ MCDE_DSI_FORMATTER_0 = 0,
+ MCDE_DSI_FORMATTER_1,
+ MCDE_DSI_FORMATTER_2,
+};
+
+void mcde_display_irq(struct mcde *mcde)
+{
+ u32 mispp, misovl, mischnl;
+ bool vblank;
+
+ /* Handle display IRQs */
+ mispp = readl(mcde->regs + MCDE_MISPP);
+ misovl = readl(mcde->regs + MCDE_MISOVL);
+ mischnl = readl(mcde->regs + MCDE_MISCHNL);
+
+ /*
+ * Handle IRQs from the DSI link. All IRQs from the DSI links
+ * are just latched onto the MCDE IRQ line, so we need to traverse
+ * any active DSI masters and check if an IRQ is originating from
+ * them.
+ *
+ * TODO: Currently only one DSI link is supported.
+ */
+ if (mcde_dsi_irq(mcde->mdsi)) {
+ u32 val;
+
+ /*
+ * In oneshot mode we do not send continuous updates
+ * to the display, instead we only push out updates when
+ * the update function is called, then we disable the
+ * flow on the channel once we get the TE IRQ.
+ */
+ if (mcde->oneshot_mode) {
+ spin_lock(&mcde->flow_lock);
+ if (--mcde->flow_active == 0) {
+ dev_dbg(mcde->dev, "TE0 IRQ\n");
+ /* Disable FIFO A flow */
+ val = readl(mcde->regs + MCDE_CRA0);
+ val &= ~MCDE_CRX0_FLOEN;
+ writel(val, mcde->regs + MCDE_CRA0);
+ }
+ spin_unlock(&mcde->flow_lock);
+ }
+ }
+
+ /* Vblank from one of the channels */
+ if (mispp & MCDE_PP_VCMPA) {
+ dev_dbg(mcde->dev, "chnl A vblank IRQ\n");
+ vblank = true;
+ }
+ if (mispp & MCDE_PP_VCMPB) {
+ dev_dbg(mcde->dev, "chnl B vblank IRQ\n");
+ vblank = true;
+ }
+ if (mispp & MCDE_PP_VCMPC0)
+ dev_dbg(mcde->dev, "chnl C0 vblank IRQ\n");
+ if (mispp & MCDE_PP_VCMPC1)
+ dev_dbg(mcde->dev, "chnl C1 vblank IRQ\n");
+ if (mispp & MCDE_PP_VSCC0)
+ dev_dbg(mcde->dev, "chnl C0 TE IRQ\n");
+ if (mispp & MCDE_PP_VSCC1)
+ dev_dbg(mcde->dev, "chnl C1 TE IRQ\n");
+ writel(mispp, mcde->regs + MCDE_RISPP);
+
+ if (vblank)
+ drm_crtc_handle_vblank(&mcde->pipe.crtc);
+
+ if (misovl)
+ dev_info(mcde->dev, "some stray overlay IRQ %08x\n", misovl);
+ writel(misovl, mcde->regs + MCDE_RISOVL);
+
+ if (mischnl)
+ dev_info(mcde->dev, "some stray channel error IRQ %08x\n",
+ mischnl);
+ writel(mischnl, mcde->regs + MCDE_RISCHNL);
+}
+
+void mcde_display_disable_irqs(struct mcde *mcde)
+{
+ /* Disable all IRQs */
+ writel(0, mcde->regs + MCDE_IMSCPP);
+ writel(0, mcde->regs + MCDE_IMSCOVL);
+ writel(0, mcde->regs + MCDE_IMSCCHNL);
+
+ /* Clear any pending IRQs */
+ writel(0xFFFFFFFF, mcde->regs + MCDE_RISPP);
+ writel(0xFFFFFFFF, mcde->regs + MCDE_RISOVL);
+ writel(0xFFFFFFFF, mcde->regs + MCDE_RISCHNL);
+}
+
+static int mcde_display_check(struct drm_simple_display_pipe *pipe,
+ struct drm_plane_state *pstate,
+ struct drm_crtc_state *cstate)
+{
+ const struct drm_display_mode *mode = &cstate->mode;
+ struct drm_framebuffer *old_fb = pipe->plane.state->fb;
+ struct drm_framebuffer *fb = pstate->fb;
+
+ if (fb) {
+ u32 offset = drm_fb_cma_get_gem_addr(fb, pstate, 0);
+
+ /* FB base address must be dword aligned. */
+ if (offset & 3) {
+ DRM_DEBUG_KMS("FB not 32-bit aligned\n");
+ return -EINVAL;
+ }
+
+ /*
+ * There's no pitch register, the mode's hdisplay
+ * controls this.
+ */
+ if (fb->pitches[0] != mode->hdisplay * fb->format->cpp[0]) {
+ DRM_DEBUG_KMS("can't handle pitches\n");
+ return -EINVAL;
+ }
+
+ /*
+ * We can't change the FB format in a flicker-free
+ * manner (and only update it during CRTC enable).
+ */
+ if (old_fb && old_fb->format != fb->format)
+ cstate->mode_changed = true;
+ }
+
+ return 0;
+}
+
+static int mcde_configure_extsrc(struct mcde *mcde, enum mcde_extsrc src,
+ u32 format)
+{
+ u32 val;
+ u32 conf;
+ u32 cr;
+
+ switch (src) {
+ case MCDE_EXTSRC_0:
+ conf = MCDE_EXTSRC0CONF;
+ cr = MCDE_EXTSRC0CR;
+ break;
+ case MCDE_EXTSRC_1:
+ conf = MCDE_EXTSRC1CONF;
+ cr = MCDE_EXTSRC1CR;
+ break;
+ case MCDE_EXTSRC_2:
+ conf = MCDE_EXTSRC2CONF;
+ cr = MCDE_EXTSRC2CR;
+ break;
+ case MCDE_EXTSRC_3:
+ conf = MCDE_EXTSRC3CONF;
+ cr = MCDE_EXTSRC3CR;
+ break;
+ case MCDE_EXTSRC_4:
+ conf = MCDE_EXTSRC4CONF;
+ cr = MCDE_EXTSRC4CR;
+ break;
+ case MCDE_EXTSRC_5:
+ conf = MCDE_EXTSRC5CONF;
+ cr = MCDE_EXTSRC5CR;
+ break;
+ case MCDE_EXTSRC_6:
+ conf = MCDE_EXTSRC6CONF;
+ cr = MCDE_EXTSRC6CR;
+ break;
+ case MCDE_EXTSRC_7:
+ conf = MCDE_EXTSRC7CONF;
+ cr = MCDE_EXTSRC7CR;
+ break;
+ case MCDE_EXTSRC_8:
+ conf = MCDE_EXTSRC8CONF;
+ cr = MCDE_EXTSRC8CR;
+ break;
+ case MCDE_EXTSRC_9:
+ conf = MCDE_EXTSRC9CONF;
+ cr = MCDE_EXTSRC9CR;
+ break;
+ }
+
+ /*
+ * Configure external source 0 one buffer (buffer 0)
+ * primary overlay ID 0.
+ * From mcde_hw.c ovly_update_registers() in the vendor tree
+ */
+ val = 0 << MCDE_EXTSRCXCONF_BUF_ID_SHIFT;
+ val |= 1 << MCDE_EXTSRCXCONF_BUF_NB_SHIFT;
+ val |= 0 << MCDE_EXTSRCXCONF_PRI_OVLID_SHIFT;
+ /*
+ * MCDE has inverse semantics from DRM on RBG/BGR which is why
+ * all the modes are inversed here.
+ */
+ switch (format) {
+ case DRM_FORMAT_ARGB8888:
+ val |= MCDE_EXTSRCXCONF_BPP_ARGB8888 <<
+ MCDE_EXTSRCXCONF_BPP_SHIFT;
+ val |= MCDE_EXTSRCXCONF_BGR;
+ break;
+ case DRM_FORMAT_ABGR8888:
+ val |= MCDE_EXTSRCXCONF_BPP_ARGB8888 <<
+ MCDE_EXTSRCXCONF_BPP_SHIFT;
+ break;
+ case DRM_FORMAT_XRGB8888:
+ val |= MCDE_EXTSRCXCONF_BPP_XRGB8888 <<
+ MCDE_EXTSRCXCONF_BPP_SHIFT;
+ val |= MCDE_EXTSRCXCONF_BGR;
+ break;
+ case DRM_FORMAT_XBGR8888:
+ val |= MCDE_EXTSRCXCONF_BPP_XRGB8888 <<
+ MCDE_EXTSRCXCONF_BPP_SHIFT;
+ break;
+ case DRM_FORMAT_RGB888:
+ val |= MCDE_EXTSRCXCONF_BPP_RGB888 <<
+ MCDE_EXTSRCXCONF_BPP_SHIFT;
+ val |= MCDE_EXTSRCXCONF_BGR;
+ break;
+ case DRM_FORMAT_BGR888:
+ val |= MCDE_EXTSRCXCONF_BPP_RGB888 <<
+ MCDE_EXTSRCXCONF_BPP_SHIFT;
+ break;
+ case DRM_FORMAT_ARGB4444:
+ val |= MCDE_EXTSRCXCONF_BPP_ARGB4444 <<
+ MCDE_EXTSRCXCONF_BPP_SHIFT;
+ val |= MCDE_EXTSRCXCONF_BGR;
+ break;
+ case DRM_FORMAT_ABGR4444:
+ val |= MCDE_EXTSRCXCONF_BPP_ARGB4444 <<
+ MCDE_EXTSRCXCONF_BPP_SHIFT;
+ break;
+ case DRM_FORMAT_XRGB4444:
+ val |= MCDE_EXTSRCXCONF_BPP_RGB444 <<
+ MCDE_EXTSRCXCONF_BPP_SHIFT;
+ val |= MCDE_EXTSRCXCONF_BGR;
+ break;
+ case DRM_FORMAT_XBGR4444:
+ val |= MCDE_EXTSRCXCONF_BPP_RGB444 <<
+ MCDE_EXTSRCXCONF_BPP_SHIFT;
+ break;
+ case DRM_FORMAT_XRGB1555:
+ val |= MCDE_EXTSRCXCONF_BPP_IRGB1555 <<
+ MCDE_EXTSRCXCONF_BPP_SHIFT;
+ val |= MCDE_EXTSRCXCONF_BGR;
+ break;
+ case DRM_FORMAT_XBGR1555:
+ val |= MCDE_EXTSRCXCONF_BPP_IRGB1555 <<
+ MCDE_EXTSRCXCONF_BPP_SHIFT;
+ break;
+ case DRM_FORMAT_RGB565:
+ val |= MCDE_EXTSRCXCONF_BPP_RGB565 <<
+ MCDE_EXTSRCXCONF_BPP_SHIFT;
+ val |= MCDE_EXTSRCXCONF_BGR;
+ break;
+ case DRM_FORMAT_BGR565:
+ val |= MCDE_EXTSRCXCONF_BPP_RGB565 <<
+ MCDE_EXTSRCXCONF_BPP_SHIFT;
+ break;
+ case DRM_FORMAT_YUV422:
+ val |= MCDE_EXTSRCXCONF_BPP_YCBCR422 <<
+ MCDE_EXTSRCXCONF_BPP_SHIFT;
+ break;
+ default:
+ dev_err(mcde->dev, "Unknown pixel format 0x%08x\n",
+ format);
+ return -EINVAL;
+ }
+ writel(val, mcde->regs + conf);
+
+ /* Software select, primary */
+ val = MCDE_EXTSRCXCR_SEL_MOD_SOFTWARE_SEL;
+ val |= MCDE_EXTSRCXCR_MULTIOVL_CTRL_PRIMARY;
+ writel(val, mcde->regs + cr);
+
+ return 0;
+}
+
+static void mcde_configure_overlay(struct mcde *mcde, enum mcde_overlay ovl,
+ enum mcde_extsrc src,
+ enum mcde_channel ch,
+ const struct drm_display_mode *mode,
+ u32 format)
+{
+ u32 val;
+ u32 conf1;
+ u32 conf2;
+ u32 crop;
+ u32 ljinc;
+ u32 cr;
+ u32 comp;
+
+ switch (ovl) {
+ case MCDE_OVERLAY_0:
+ conf1 = MCDE_OVL0CONF;
+ conf2 = MCDE_OVL0CONF2;
+ crop = MCDE_OVL0CROP;
+ ljinc = MCDE_OVL0LJINC;
+ cr = MCDE_OVL0CR;
+ comp = MCDE_OVL0COMP;
+ break;
+ case MCDE_OVERLAY_1:
+ conf1 = MCDE_OVL1CONF;
+ conf2 = MCDE_OVL1CONF2;
+ crop = MCDE_OVL1CROP;
+ ljinc = MCDE_OVL1LJINC;
+ cr = MCDE_OVL1CR;
+ comp = MCDE_OVL1COMP;
+ break;
+ case MCDE_OVERLAY_2:
+ conf1 = MCDE_OVL2CONF;
+ conf2 = MCDE_OVL2CONF2;
+ crop = MCDE_OVL2CROP;
+ ljinc = MCDE_OVL2LJINC;
+ cr = MCDE_OVL2CR;
+ comp = MCDE_OVL2COMP;
+ break;
+ case MCDE_OVERLAY_3:
+ conf1 = MCDE_OVL3CONF;
+ conf2 = MCDE_OVL3CONF2;
+ crop = MCDE_OVL3CROP;
+ ljinc = MCDE_OVL3LJINC;
+ cr = MCDE_OVL3CR;
+ comp = MCDE_OVL3COMP;
+ break;
+ case MCDE_OVERLAY_4:
+ conf1 = MCDE_OVL4CONF;
+ conf2 = MCDE_OVL4CONF2;
+ crop = MCDE_OVL4CROP;
+ ljinc = MCDE_OVL4LJINC;
+ cr = MCDE_OVL4CR;
+ comp = MCDE_OVL4COMP;
+ break;
+ case MCDE_OVERLAY_5:
+ conf1 = MCDE_OVL5CONF;
+ conf2 = MCDE_OVL5CONF2;
+ crop = MCDE_OVL5CROP;
+ ljinc = MCDE_OVL5LJINC;
+ cr = MCDE_OVL5CR;
+ comp = MCDE_OVL5COMP;
+ break;
+ }
+
+ val = mode->hdisplay << MCDE_OVLXCONF_PPL_SHIFT;
+ val |= mode->vdisplay << MCDE_OVLXCONF_LPF_SHIFT;
+ /* Use external source 0 that we just configured */
+ val |= src << MCDE_OVLXCONF_EXTSRC_ID_SHIFT;
+ writel(val, mcde->regs + conf1);
+
+ val = MCDE_OVLXCONF2_BP_PER_PIXEL_ALPHA;
+ val |= 0xff << MCDE_OVLXCONF2_ALPHAVALUE_SHIFT;
+ /* OPQ: overlay is opaque */
+ switch (format) {
+ case DRM_FORMAT_ARGB8888:
+ case DRM_FORMAT_ABGR8888:
+ case DRM_FORMAT_ARGB4444:
+ case DRM_FORMAT_ABGR4444:
+ case DRM_FORMAT_XRGB1555:
+ case DRM_FORMAT_XBGR1555:
+ /* No OPQ */
+ break;
+ case DRM_FORMAT_XRGB8888:
+ case DRM_FORMAT_XBGR8888:
+ case DRM_FORMAT_RGB888:
+ case DRM_FORMAT_BGR888:
+ case DRM_FORMAT_RGB565:
+ case DRM_FORMAT_BGR565:
+ case DRM_FORMAT_YUV422:
+ val |= MCDE_OVLXCONF2_OPQ;
+ break;
+ default:
+ dev_err(mcde->dev, "Unknown pixel format 0x%08x\n",
+ format);
+ break;
+ }
+ /* The default watermark level for overlay 0 is 48 */
+ val |= 48 << MCDE_OVLXCONF2_PIXELFETCHERWATERMARKLEVEL_SHIFT;
+ writel(val, mcde->regs + conf2);
+
+ /* Number of bytes to fetch per line */
+ writel(mcde->stride, mcde->regs + ljinc);
+ /* No cropping */
+ writel(0, mcde->regs + crop);
+
+ /* Set up overlay control register */
+ val = MCDE_OVLXCR_OVLEN;
+ val |= MCDE_OVLXCR_COLCCTRL_DISABLED;
+ val |= MCDE_OVLXCR_BURSTSIZE_8W <<
+ MCDE_OVLXCR_BURSTSIZE_SHIFT;
+ val |= MCDE_OVLXCR_MAXOUTSTANDING_8_REQ <<
+ MCDE_OVLXCR_MAXOUTSTANDING_SHIFT;
+ /* Not using rotation but set it up anyways */
+ val |= MCDE_OVLXCR_ROTBURSTSIZE_8W <<
+ MCDE_OVLXCR_ROTBURSTSIZE_SHIFT;
+ writel(val, mcde->regs + cr);
+
+ /*
+ * Set up the overlay compositor to route the overlay out to
+ * the desired channel
+ */
+ val = ch << MCDE_OVLXCOMP_CH_ID_SHIFT;
+ writel(val, mcde->regs + comp);
+}
+
+static void mcde_configure_channel(struct mcde *mcde, enum mcde_channel ch,
+ enum mcde_fifo fifo,
+ const struct drm_display_mode *mode)
+{
+ u32 val;
+ u32 conf;
+ u32 sync;
+ u32 stat;
+ u32 bgcol;
+ u32 mux;
+
+ switch (ch) {
+ case MCDE_CHANNEL_0:
+ conf = MCDE_CHNL0CONF;
+ sync = MCDE_CHNL0SYNCHMOD;
+ stat = MCDE_CHNL0STAT;
+ bgcol = MCDE_CHNL0BCKGNDCOL;
+ mux = MCDE_CHNL0MUXING;
+ break;
+ case MCDE_CHANNEL_1:
+ conf = MCDE_CHNL1CONF;
+ sync = MCDE_CHNL1SYNCHMOD;
+ stat = MCDE_CHNL1STAT;
+ bgcol = MCDE_CHNL1BCKGNDCOL;
+ mux = MCDE_CHNL1MUXING;
+ break;
+ case MCDE_CHANNEL_2:
+ conf = MCDE_CHNL2CONF;
+ sync = MCDE_CHNL2SYNCHMOD;
+ stat = MCDE_CHNL2STAT;
+ bgcol = MCDE_CHNL2BCKGNDCOL;
+ mux = MCDE_CHNL2MUXING;
+ break;
+ case MCDE_CHANNEL_3:
+ conf = MCDE_CHNL3CONF;
+ sync = MCDE_CHNL3SYNCHMOD;
+ stat = MCDE_CHNL3STAT;
+ bgcol = MCDE_CHNL3BCKGNDCOL;
+ mux = MCDE_CHNL3MUXING;
+ return;
+ }
+
+ /* Set up channel 0 sync (based on chnl_update_registers()) */
+ if (mcde->te_sync) {
+ /*
+ * Turn on hardware TE0 synchronization
+ */
+ val = MCDE_CHNLXSYNCHMOD_SRC_SYNCH_HARDWARE
+ << MCDE_CHNLXSYNCHMOD_SRC_SYNCH_SHIFT;
+ val |= MCDE_CHNLXSYNCHMOD_OUT_SYNCH_SRC_TE0
+ << MCDE_CHNLXSYNCHMOD_OUT_SYNCH_SRC_SHIFT;
+ } else {
+ /*
+ * Set up sync source to software, out sync formatter
+ * Code mostly from mcde_hw.c chnl_update_registers()
+ */
+ val = MCDE_CHNLXSYNCHMOD_SRC_SYNCH_SOFTWARE
+ << MCDE_CHNLXSYNCHMOD_SRC_SYNCH_SHIFT;
+ val |= MCDE_CHNLXSYNCHMOD_OUT_SYNCH_SRC_FORMATTER
+ << MCDE_CHNLXSYNCHMOD_OUT_SYNCH_SRC_SHIFT;
+ }
+ writel(val, mcde->regs + sync);
+
+ /* Set up pixels per line and lines per frame */
+ val = (mode->hdisplay - 1) << MCDE_CHNLXCONF_PPL_SHIFT;
+ val |= (mode->vdisplay - 1) << MCDE_CHNLXCONF_LPF_SHIFT;
+ writel(val, mcde->regs + conf);
+
+ /*
+ * Normalize color conversion:
+ * black background, OLED conversion disable on channel
+ */
+ val = MCDE_CHNLXSTAT_CHNLBLBCKGND_EN |
+ MCDE_CHNLXSTAT_CHNLRD;
+ writel(val, mcde->regs + stat);
+ writel(0, mcde->regs + bgcol);
+
+ /* Set up muxing: connect the channel to the desired FIFO */
+ switch (fifo) {
+ case MCDE_FIFO_A:
+ writel(MCDE_CHNLXMUXING_FIFO_ID_FIFO_A,
+ mcde->regs + mux);
+ break;
+ case MCDE_FIFO_B:
+ writel(MCDE_CHNLXMUXING_FIFO_ID_FIFO_B,
+ mcde->regs + mux);
+ break;
+ }
+}
+
+static void mcde_configure_fifo(struct mcde *mcde, enum mcde_fifo fifo,
+ enum mcde_dsi_formatter fmt,
+ int fifo_wtrmrk)
+{
+ u32 val;
+ u32 ctrl;
+ u32 cr0, cr1;
+
+ switch (fifo) {
+ case MCDE_FIFO_A:
+ ctrl = MCDE_CTRLA;
+ cr0 = MCDE_CRA0;
+ cr1 = MCDE_CRA1;
+ break;
+ case MCDE_FIFO_B:
+ ctrl = MCDE_CTRLB;
+ cr0 = MCDE_CRB0;
+ cr1 = MCDE_CRB1;
+ break;
+ }
+
+ val = fifo_wtrmrk << MCDE_CTRLX_FIFOWTRMRK_SHIFT;
+ /* We only support DSI formatting for now */
+ val |= MCDE_CTRLX_FORMTYPE_DSI <<
+ MCDE_CTRLX_FORMTYPE_SHIFT;
+
+ /* Select the formatter to use for this FIFO */
+ val |= fmt << MCDE_CTRLX_FORMID_SHIFT;
+ writel(val, mcde->regs + ctrl);
+
+ /* Blend source with Alpha 0xff on FIFO */
+ val = MCDE_CRX0_BLENDEN |
+ 0xff << MCDE_CRX0_ALPHABLEND_SHIFT;
+ writel(val, mcde->regs + cr0);
+
+ /* Set-up from mcde_fmtr_dsi.c, fmtr_dsi_enable_video() */
+
+ /* Use the MCDE clock for this FIFO */
+ val = MCDE_CRX1_CLKSEL_MCDECLK << MCDE_CRX1_CLKSEL_SHIFT;
+
+ /* TODO: when adding DPI support add OUTBPP etc here */
+ writel(val, mcde->regs + cr1);
+};
+
+static void mcde_configure_dsi_formatter(struct mcde *mcde,
+ enum mcde_dsi_formatter fmt,
+ u32 formatter_frame,
+ int pkt_size)
+{
+ u32 val;
+ u32 conf0;
+ u32 frame;
+ u32 pkt;
+ u32 sync;
+ u32 cmdw;
+ u32 delay0, delay1;
+
+ switch (fmt) {
+ case MCDE_DSI_FORMATTER_0:
+ conf0 = MCDE_DSIVID0CONF0;
+ frame = MCDE_DSIVID0FRAME;
+ pkt = MCDE_DSIVID0PKT;
+ sync = MCDE_DSIVID0SYNC;
+ cmdw = MCDE_DSIVID0CMDW;
+ delay0 = MCDE_DSIVID0DELAY0;
+ delay1 = MCDE_DSIVID0DELAY1;
+ break;
+ case MCDE_DSI_FORMATTER_1:
+ conf0 = MCDE_DSIVID1CONF0;
+ frame = MCDE_DSIVID1FRAME;
+ pkt = MCDE_DSIVID1PKT;
+ sync = MCDE_DSIVID1SYNC;
+ cmdw = MCDE_DSIVID1CMDW;
+ delay0 = MCDE_DSIVID1DELAY0;
+ delay1 = MCDE_DSIVID1DELAY1;
+ break;
+ case MCDE_DSI_FORMATTER_2:
+ conf0 = MCDE_DSIVID2CONF0;
+ frame = MCDE_DSIVID2FRAME;
+ pkt = MCDE_DSIVID2PKT;
+ sync = MCDE_DSIVID2SYNC;
+ cmdw = MCDE_DSIVID2CMDW;
+ delay0 = MCDE_DSIVID2DELAY0;
+ delay1 = MCDE_DSIVID2DELAY1;
+ break;
+ }
+
+ /*
+ * Enable formatter
+ * 8 bit commands and DCS commands (notgen = not generic)
+ */
+ val = MCDE_DSICONF0_CMD8 | MCDE_DSICONF0_DCSVID_NOTGEN;
+ if (mcde->mdsi->mode_flags & MIPI_DSI_MODE_VIDEO)
+ val |= MCDE_DSICONF0_VID_MODE_VID;
+ switch (mcde->mdsi->format) {
+ case MIPI_DSI_FMT_RGB888:
+ val |= MCDE_DSICONF0_PACKING_RGB888 <<
+ MCDE_DSICONF0_PACKING_SHIFT;
+ break;
+ case MIPI_DSI_FMT_RGB666:
+ val |= MCDE_DSICONF0_PACKING_RGB666 <<
+ MCDE_DSICONF0_PACKING_SHIFT;
+ break;
+ case MIPI_DSI_FMT_RGB666_PACKED:
+ val |= MCDE_DSICONF0_PACKING_RGB666_PACKED <<
+ MCDE_DSICONF0_PACKING_SHIFT;
+ break;
+ case MIPI_DSI_FMT_RGB565:
+ val |= MCDE_DSICONF0_PACKING_RGB565 <<
+ MCDE_DSICONF0_PACKING_SHIFT;
+ break;
+ default:
+ dev_err(mcde->dev, "unknown DSI format\n");
+ return;
+ }
+ writel(val, mcde->regs + conf0);
+
+ writel(formatter_frame, mcde->regs + frame);
+ writel(pkt_size, mcde->regs + pkt);
+ writel(0, mcde->regs + sync);
+ /* Define the MIPI command: we want to write into display memory */
+ val = MIPI_DCS_WRITE_MEMORY_CONTINUE <<
+ MCDE_DSIVIDXCMDW_CMDW_CONTINUE_SHIFT;
+ val |= MIPI_DCS_WRITE_MEMORY_START <<
+ MCDE_DSIVIDXCMDW_CMDW_START_SHIFT;
+ writel(val, mcde->regs + cmdw);
+
+ /*
+ * FIXME: the vendor driver has some hack around this value in
+ * CMD mode with autotrig.
+ */
+ writel(0, mcde->regs + delay0);
+ writel(0, mcde->regs + delay1);
+}
+
+static void mcde_enable_fifo(struct mcde *mcde, enum mcde_fifo fifo)
+{
+ u32 val;
+ u32 cr;
+
+ switch (fifo) {
+ case MCDE_FIFO_A:
+ cr = MCDE_CRA0;
+ break;
+ case MCDE_FIFO_B:
+ cr = MCDE_CRB0;
+ break;
+ default:
+ dev_err(mcde->dev, "cannot enable FIFO %c\n",
+ 'A' + fifo);
+ return;
+ }
+
+ spin_lock(&mcde->flow_lock);
+ val = readl(mcde->regs + cr);
+ val |= MCDE_CRX0_FLOEN;
+ writel(val, mcde->regs + cr);
+ mcde->flow_active++;
+ spin_unlock(&mcde->flow_lock);
+}
+
+static void mcde_disable_fifo(struct mcde *mcde, enum mcde_fifo fifo,
+ bool wait_for_drain)
+{
+ int timeout = 100;
+ u32 val;
+ u32 cr;
+
+ switch (fifo) {
+ case MCDE_FIFO_A:
+ cr = MCDE_CRA0;
+ break;
+ case MCDE_FIFO_B:
+ cr = MCDE_CRB0;
+ break;
+ default:
+ dev_err(mcde->dev, "cannot disable FIFO %c\n",
+ 'A' + fifo);
+ return;
+ }
+
+ spin_lock(&mcde->flow_lock);
+ val = readl(mcde->regs + cr);
+ val &= ~MCDE_CRX0_FLOEN;
+ writel(val, mcde->regs + cr);
+ mcde->flow_active = 0;
+ spin_unlock(&mcde->flow_lock);
+
+ if (!wait_for_drain)
+ return;
+
+ /* Check that we really drained and stopped the flow */
+ while (readl(mcde->regs + cr) & MCDE_CRX0_FLOEN) {
+ usleep_range(1000, 1500);
+ if (!--timeout) {
+ dev_err(mcde->dev,
+ "FIFO timeout while clearing FIFO %c\n",
+ 'A' + fifo);
+ return;
+ }
+ }
+}
+
+/*
+ * This drains a pipe i.e. a FIFO connected to a certain channel
+ */
+static void mcde_drain_pipe(struct mcde *mcde, enum mcde_fifo fifo,
+ enum mcde_channel ch)
+{
+ u32 val;
+ u32 ctrl;
+ u32 synsw;
+
+ switch (fifo) {
+ case MCDE_FIFO_A:
+ ctrl = MCDE_CTRLA;
+ break;
+ case MCDE_FIFO_B:
+ ctrl = MCDE_CTRLB;
+ break;
+ }
+
+ switch (ch) {
+ case MCDE_CHANNEL_0:
+ synsw = MCDE_CHNL0SYNCHSW;
+ break;
+ case MCDE_CHANNEL_1:
+ synsw = MCDE_CHNL1SYNCHSW;
+ break;
+ case MCDE_CHANNEL_2:
+ synsw = MCDE_CHNL2SYNCHSW;
+ break;
+ case MCDE_CHANNEL_3:
+ synsw = MCDE_CHNL3SYNCHSW;
+ return;
+ }
+
+ val = readl(mcde->regs + ctrl);
+ if (!(val & MCDE_CTRLX_FIFOEMPTY)) {
+ dev_err(mcde->dev, "Channel A FIFO not empty (handover)\n");
+ /* Attempt to clear the FIFO */
+ mcde_enable_fifo(mcde, fifo);
+ /* Trigger a software sync out on respective channel (0-3) */
+ writel(MCDE_CHNLXSYNCHSW_SW_TRIG, mcde->regs + synsw);
+ /* Disable FIFO A flow again */
+ mcde_disable_fifo(mcde, fifo, true);
+ }
+}
+
+static int mcde_dsi_get_pkt_div(int ppl, int fifo_size)
+{
+ /*
+ * DSI command mode line packets should be split into an even number of
+ * packets smaller than or equal to the fifo size.
+ */
+ int div;
+ const int max_div = DIV_ROUND_UP(MCDE_MAX_WIDTH, fifo_size);
+
+ for (div = 1; div < max_div; div++)
+ if (ppl % div == 0 && ppl / div <= fifo_size)
+ return div;
+ return 1;
+}
+
+static void mcde_display_enable(struct drm_simple_display_pipe *pipe,
+ struct drm_crtc_state *cstate,
+ struct drm_plane_state *plane_state)
+{
+ struct drm_crtc *crtc = &pipe->crtc;
+ struct drm_plane *plane = &pipe->plane;
+ struct drm_device *drm = crtc->dev;
+ struct mcde *mcde = drm->dev_private;
+ const struct drm_display_mode *mode = &cstate->mode;
+ struct drm_framebuffer *fb = plane->state->fb;
+ u32 format = fb->format->format;
+ u32 formatter_ppl = mode->hdisplay; /* pixels per line */
+ u32 formatter_lpf = mode->vdisplay; /* lines per frame */
+ int pkt_size, fifo_wtrmrk;
+ int cpp = fb->format->cpp[0];
+ int formatter_cpp;
+ struct drm_format_name_buf tmp;
+ u32 formatter_frame;
+ u32 pkt_div;
+ u32 val;
+
+ dev_info(drm->dev, "enable MCDE, %d x %d format %s\n",
+ mode->hdisplay, mode->vdisplay,
+ drm_get_format_name(format, &tmp));
+ if (!mcde->mdsi) {
+ /* TODO: deal with this for non-DSI output */
+ dev_err(drm->dev, "no DSI master attached!\n");
+ return;
+ }
+
+ dev_info(drm->dev, "output in %s mode, format %dbpp\n",
+ (mcde->mdsi->mode_flags & MIPI_DSI_MODE_VIDEO) ?
+ "VIDEO" : "CMD",
+ mipi_dsi_pixel_format_to_bpp(mcde->mdsi->format));
+ formatter_cpp =
+ mipi_dsi_pixel_format_to_bpp(mcde->mdsi->format) / 8;
+ dev_info(drm->dev, "overlay CPP %d bytes, DSI CPP %d bytes\n",
+ cpp,
+ formatter_cpp);
+
+ /* Calculations from mcde_fmtr_dsi.c, fmtr_dsi_enable_video() */
+
+ /*
+ * Set up FIFO A watermark level:
+ * 128 for LCD 32bpp video mode
+ * 48 for LCD 32bpp command mode
+ * 128 for LCD 16bpp video mode
+ * 64 for LCD 16bpp command mode
+ * 128 for HDMI 32bpp
+ * 192 for HDMI 16bpp
+ */
+ fifo_wtrmrk = mode->hdisplay;
+ if (mcde->mdsi->mode_flags & MIPI_DSI_MODE_VIDEO) {
+ fifo_wtrmrk = min(fifo_wtrmrk, 128);
+ pkt_div = 1;
+ } else {
+ fifo_wtrmrk = min(fifo_wtrmrk, 48);
+ /* The FIFO is 640 entries deep on this v3 hardware */
+ pkt_div = mcde_dsi_get_pkt_div(mode->hdisplay, 640);
+ }
+ dev_dbg(drm->dev, "FIFO watermark after flooring: %d bytes\n",
+ fifo_wtrmrk);
+ dev_dbg(drm->dev, "Packet divisor: %d bytes\n", pkt_div);
+
+ /* NOTE: pkt_div is 1 for video mode */
+ pkt_size = (formatter_ppl * formatter_cpp) / pkt_div;
+ /* Commands CMD8 need one extra byte */
+ if (!(mcde->mdsi->mode_flags & MIPI_DSI_MODE_VIDEO))
+ pkt_size++;
+
+ dev_dbg(drm->dev, "DSI packet size: %d * %d bytes per line\n",
+ pkt_size, pkt_div);
+ dev_dbg(drm->dev, "Overlay frame size: %u bytes\n",
+ mode->hdisplay * mode->vdisplay * cpp);
+ mcde->stride = mode->hdisplay * cpp;
+ dev_dbg(drm->dev, "Overlay line stride: %u bytes\n",
+ mcde->stride);
+ /* NOTE: pkt_div is 1 for video mode */
+ formatter_frame = pkt_size * pkt_div * formatter_lpf;
+ dev_dbg(drm->dev, "Formatter frame size: %u bytes\n", formatter_frame);
+
+ /* Drain the FIFO A + channel 0 pipe so we have a clean slate */
+ mcde_drain_pipe(mcde, MCDE_FIFO_A, MCDE_CHANNEL_0);
+
+ /*
+ * We set up our display pipeline:
+ * EXTSRC 0 -> OVERLAY 0 -> CHANNEL 0 -> FIFO A -> DSI FORMATTER 0
+ *
+ * First configure the external source (memory) on external source 0
+ * using the desired bitstream/bitmap format
+ */
+ mcde_configure_extsrc(mcde, MCDE_EXTSRC_0, format);
+
+ /*
+ * Configure overlay 0 according to format and mode and take input
+ * from external source 0 and route the output of this overlay to
+ * channel 0
+ */
+ mcde_configure_overlay(mcde, MCDE_OVERLAY_0, MCDE_EXTSRC_0,
+ MCDE_CHANNEL_0, mode, format);
+
+ /*
+ * Configure pixel-per-line and line-per-frame for channel 0 and then
+ * route channel 0 to FIFO A
+ */
+ mcde_configure_channel(mcde, MCDE_CHANNEL_0, MCDE_FIFO_A, mode);
+
+ /* Configure FIFO A to use DSI formatter 0 */
+ mcde_configure_fifo(mcde, MCDE_FIFO_A, MCDE_DSI_FORMATTER_0,
+ fifo_wtrmrk);
+
+ /* Configure the DSI formatter 0 for the DSI panel output */
+ mcde_configure_dsi_formatter(mcde, MCDE_DSI_FORMATTER_0,
+ formatter_frame, pkt_size);
+
+ if (mcde->te_sync) {
+ if (mode->flags & DRM_MODE_FLAG_NVSYNC)
+ val = MCDE_VSCRC_VSPOL;
+ else
+ val = 0;
+ writel(val, mcde->regs + MCDE_VSCRC0);
+ /* Enable VSYNC capture on TE0 */
+ val = readl(mcde->regs + MCDE_CRC);
+ val |= MCDE_CRC_SYCEN0;
+ writel(val, mcde->regs + MCDE_CRC);
+
+ drm_crtc_vblank_on(crtc);
+ }
+
+ dev_info(drm->dev, "MCDE display is enabled\n");
+}
+
+static void mcde_display_disable(struct drm_simple_display_pipe *pipe)
+{
+ struct drm_crtc *crtc = &pipe->crtc;
+ struct drm_device *drm = crtc->dev;
+ struct mcde *mcde = drm->dev_private;
+
+ if (mcde->te_sync)
+ drm_crtc_vblank_off(crtc);
+
+ /* Disable FIFO A flow */
+ mcde_disable_fifo(mcde, MCDE_FIFO_A, true);
+
+ dev_info(drm->dev, "MCDE display is disabled\n");
+}
+
+static void mcde_display_send_one_frame(struct mcde *mcde)
+{
+ /* Request a TE ACK */
+ if (mcde->te_sync)
+ mcde_dsi_te_request(mcde->mdsi);
+
+ /* Enable FIFO A flow */
+ mcde_enable_fifo(mcde, MCDE_FIFO_A);
+
+ if (mcde->te_sync) {
+ /*
+ * If oneshot mode is enabled, the flow will be disabled
+ * when the TE0 IRQ arrives in the interrupt handler. Otherwise
+ * updates are continuously streamed to the display after this
+ * point.
+ */
+ dev_dbg(mcde->dev, "sent TE0 framebuffer update\n");
+ return;
+ }
+
+ /* Trigger a software sync out on channel 0 */
+ writel(MCDE_CHNLXSYNCHSW_SW_TRIG,
+ mcde->regs + MCDE_CHNL0SYNCHSW);
+
+ /*
+ * Disable FIFO A flow again: since we are using TE sync we
+ * need to wait for the FIFO to drain before we continue
+ * so repeated calls to this function will not cause a mess
+ * in the hardware by pushing updates will updates are going
+ * on already.
+ */
+ mcde_disable_fifo(mcde, MCDE_FIFO_A, true);
+
+ dev_dbg(mcde->dev, "sent SW framebuffer update\n");
+}
+
+static void mcde_set_extsrc(struct mcde *mcde, u32 buffer_address)
+{
+ /* Write bitmap base address to register */
+ writel(buffer_address, mcde->regs + MCDE_EXTSRCXA0);
+ /*
+ * Base address for next line this is probably only used
+ * in interlace modes.
+ */
+ writel(buffer_address + mcde->stride, mcde->regs + MCDE_EXTSRCXA1);
+}
+
+static void mcde_display_update(struct drm_simple_display_pipe *pipe,
+ struct drm_plane_state *old_pstate)
+{
+ struct drm_crtc *crtc = &pipe->crtc;
+ struct drm_device *drm = crtc->dev;
+ struct mcde *mcde = drm->dev_private;
+ struct drm_pending_vblank_event *event = crtc->state->event;
+ struct drm_plane *plane = &pipe->plane;
+ struct drm_plane_state *pstate = plane->state;
+ struct drm_framebuffer *fb = pstate->fb;
+
+ /*
+ * Handle any pending event first, we need to arm the vblank
+ * interrupt before sending any update to the display so we don't
+ * miss the interrupt.
+ */
+ if (event) {
+ crtc->state->event = NULL;
+
+ spin_lock_irq(&crtc->dev->event_lock);
+ /*
+ * Hardware must be on before we can arm any vblank event,
+ * this is not a scanout controller where there is always
+ * some periodic update going on, it is completely frozen
+ * until we get an update. If MCDE output isn't yet enabled,
+ * we just send a vblank dummy event back.
+ */
+ if (crtc->state->active && drm_crtc_vblank_get(crtc) == 0) {
+ dev_dbg(mcde->dev, "arm vblank event\n");
+ drm_crtc_arm_vblank_event(crtc, event);
+ } else {
+ dev_dbg(mcde->dev, "insert fake vblank event\n");
+ drm_crtc_send_vblank_event(crtc, event);
+ }
+
+ spin_unlock_irq(&crtc->dev->event_lock);
+ }
+
+ /*
+ * We do not start sending framebuffer updates before the
+ * display is enabled. Update events will however be dispatched
+ * from the DRM core before the display is enabled.
+ */
+ if (fb) {
+ mcde_set_extsrc(mcde, drm_fb_cma_get_gem_addr(fb, pstate, 0));
+ /* Send a single frame using software sync */
+ mcde_display_send_one_frame(mcde);
+ dev_info_once(mcde->dev, "sent first display update\n");
+ } else {
+ /*
+ * If an update is receieved before the MCDE is enabled
+ * (before mcde_display_enable() is called) we can't really
+ * do much with that buffer.
+ */
+ dev_info(mcde->dev, "ignored a display update\n");
+ }
+}
+
+static int mcde_display_enable_vblank(struct drm_simple_display_pipe *pipe)
+{
+ struct drm_crtc *crtc = &pipe->crtc;
+ struct drm_device *drm = crtc->dev;
+ struct mcde *mcde = drm->dev_private;
+ u32 val;
+
+ /* Enable all VBLANK IRQs */
+ val = MCDE_PP_VCMPA |
+ MCDE_PP_VCMPB |
+ MCDE_PP_VSCC0 |
+ MCDE_PP_VSCC1 |
+ MCDE_PP_VCMPC0 |
+ MCDE_PP_VCMPC1;
+ writel(val, mcde->regs + MCDE_IMSCPP);
+
+ return 0;
+}
+
+static void mcde_display_disable_vblank(struct drm_simple_display_pipe *pipe)
+{
+ struct drm_crtc *crtc = &pipe->crtc;
+ struct drm_device *drm = crtc->dev;
+ struct mcde *mcde = drm->dev_private;
+
+ /* Disable all VBLANK IRQs */
+ writel(0, mcde->regs + MCDE_IMSCPP);
+ /* Clear any pending IRQs */
+ writel(0xFFFFFFFF, mcde->regs + MCDE_RISPP);
+}
+
+static struct drm_simple_display_pipe_funcs mcde_display_funcs = {
+ .check = mcde_display_check,
+ .enable = mcde_display_enable,
+ .disable = mcde_display_disable,
+ .update = mcde_display_update,
+ .prepare_fb = drm_gem_fb_simple_display_pipe_prepare_fb,
+};
+
+int mcde_display_init(struct drm_device *drm)
+{
+ struct mcde *mcde = drm->dev_private;
+ int ret;
+ static const u32 formats[] = {
+ DRM_FORMAT_ARGB8888,
+ DRM_FORMAT_ABGR8888,
+ DRM_FORMAT_XRGB8888,
+ DRM_FORMAT_XBGR8888,
+ DRM_FORMAT_RGB888,
+ DRM_FORMAT_BGR888,
+ DRM_FORMAT_ARGB4444,
+ DRM_FORMAT_ABGR4444,
+ DRM_FORMAT_XRGB4444,
+ DRM_FORMAT_XBGR4444,
+ /* These are actually IRGB1555 so intensity bit is lost */
+ DRM_FORMAT_XRGB1555,
+ DRM_FORMAT_XBGR1555,
+ DRM_FORMAT_RGB565,
+ DRM_FORMAT_BGR565,
+ DRM_FORMAT_YUV422,
+ };
+
+ /* Provide vblank only when we have TE enabled */
+ if (mcde->te_sync) {
+ mcde_display_funcs.enable_vblank = mcde_display_enable_vblank;
+ mcde_display_funcs.disable_vblank = mcde_display_disable_vblank;
+ }
+
+ ret = drm_simple_display_pipe_init(drm, &mcde->pipe,
+ &mcde_display_funcs,
+ formats, ARRAY_SIZE(formats),
+ NULL,
+ mcde->connector);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(mcde_display_init);
diff --git a/drivers/gpu/drm/mcde/mcde_display_regs.h b/drivers/gpu/drm/mcde/mcde_display_regs.h
new file mode 100644
index 000000000000..d3ac7ef5ff9a
--- /dev/null
+++ b/drivers/gpu/drm/mcde/mcde_display_regs.h
@@ -0,0 +1,518 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __DRM_MCDE_DISPLAY_REGS
+#define __DRM_MCDE_DISPLAY_REGS
+
+/* PP (pixel processor) interrupts */
+#define MCDE_IMSCPP 0x00000104
+#define MCDE_RISPP 0x00000114
+#define MCDE_MISPP 0x00000124
+#define MCDE_SISPP 0x00000134
+
+#define MCDE_PP_VCMPA BIT(0)
+#define MCDE_PP_VCMPB BIT(1)
+#define MCDE_PP_VSCC0 BIT(2)
+#define MCDE_PP_VSCC1 BIT(3)
+#define MCDE_PP_VCMPC0 BIT(4)
+#define MCDE_PP_VCMPC1 BIT(5)
+#define MCDE_PP_ROTFD_A BIT(6)
+#define MCDE_PP_ROTFD_B BIT(7)
+
+/* Overlay interrupts */
+#define MCDE_IMSCOVL 0x00000108
+#define MCDE_RISOVL 0x00000118
+#define MCDE_MISOVL 0x00000128
+#define MCDE_SISOVL 0x00000138
+
+/* Channel interrupts */
+#define MCDE_IMSCCHNL 0x0000010C
+#define MCDE_RISCHNL 0x0000011C
+#define MCDE_MISCHNL 0x0000012C
+#define MCDE_SISCHNL 0x0000013C
+
+/* X = 0..9 */
+#define MCDE_EXTSRCXA0 0x00000200
+#define MCDE_EXTSRCXA0_GROUPOFFSET 0x20
+#define MCDE_EXTSRCXA0_BASEADDRESS0_SHIFT 3
+#define MCDE_EXTSRCXA0_BASEADDRESS0_MASK 0xFFFFFFF8
+
+#define MCDE_EXTSRCXA1 0x00000204
+#define MCDE_EXTSRCXA1_GROUPOFFSET 0x20
+#define MCDE_EXTSRCXA1_BASEADDRESS1_SHIFT 3
+#define MCDE_EXTSRCXA1_BASEADDRESS1_MASK 0xFFFFFFF8
+
+/* External sources 0..9 */
+#define MCDE_EXTSRC0CONF 0x0000020C
+#define MCDE_EXTSRC1CONF 0x0000022C
+#define MCDE_EXTSRC2CONF 0x0000024C
+#define MCDE_EXTSRC3CONF 0x0000026C
+#define MCDE_EXTSRC4CONF 0x0000028C
+#define MCDE_EXTSRC5CONF 0x000002AC
+#define MCDE_EXTSRC6CONF 0x000002CC
+#define MCDE_EXTSRC7CONF 0x000002EC
+#define MCDE_EXTSRC8CONF 0x0000030C
+#define MCDE_EXTSRC9CONF 0x0000032C
+#define MCDE_EXTSRCXCONF_GROUPOFFSET 0x20
+#define MCDE_EXTSRCXCONF_BUF_ID_SHIFT 0
+#define MCDE_EXTSRCXCONF_BUF_ID_MASK 0x00000003
+#define MCDE_EXTSRCXCONF_BUF_NB_SHIFT 2
+#define MCDE_EXTSRCXCONF_BUF_NB_MASK 0x0000000C
+#define MCDE_EXTSRCXCONF_PRI_OVLID_SHIFT 4
+#define MCDE_EXTSRCXCONF_PRI_OVLID_MASK 0x000000F0
+#define MCDE_EXTSRCXCONF_BPP_SHIFT 8
+#define MCDE_EXTSRCXCONF_BPP_MASK 0x00000F00
+#define MCDE_EXTSRCXCONF_BPP_1BPP_PAL 0
+#define MCDE_EXTSRCXCONF_BPP_2BPP_PAL 1
+#define MCDE_EXTSRCXCONF_BPP_4BPP_PAL 2
+#define MCDE_EXTSRCXCONF_BPP_8BPP_PAL 3
+#define MCDE_EXTSRCXCONF_BPP_RGB444 4
+#define MCDE_EXTSRCXCONF_BPP_ARGB4444 5
+#define MCDE_EXTSRCXCONF_BPP_IRGB1555 6
+#define MCDE_EXTSRCXCONF_BPP_RGB565 7
+#define MCDE_EXTSRCXCONF_BPP_RGB888 8
+#define MCDE_EXTSRCXCONF_BPP_XRGB8888 9
+#define MCDE_EXTSRCXCONF_BPP_ARGB8888 10
+#define MCDE_EXTSRCXCONF_BPP_YCBCR422 11
+#define MCDE_EXTSRCXCONF_BGR BIT(12)
+#define MCDE_EXTSRCXCONF_BEBO BIT(13)
+#define MCDE_EXTSRCXCONF_BEPO BIT(14)
+#define MCDE_EXTSRCXCONF_TUNNELING_BUFFER_HEIGHT_SHIFT 16
+#define MCDE_EXTSRCXCONF_TUNNELING_BUFFER_HEIGHT_MASK 0x0FFF0000
+
+/* External sources 0..9 */
+#define MCDE_EXTSRC0CR 0x00000210
+#define MCDE_EXTSRC1CR 0x00000230
+#define MCDE_EXTSRC2CR 0x00000250
+#define MCDE_EXTSRC3CR 0x00000270
+#define MCDE_EXTSRC4CR 0x00000290
+#define MCDE_EXTSRC5CR 0x000002B0
+#define MCDE_EXTSRC6CR 0x000002D0
+#define MCDE_EXTSRC7CR 0x000002F0
+#define MCDE_EXTSRC8CR 0x00000310
+#define MCDE_EXTSRC9CR 0x00000330
+#define MCDE_EXTSRCXCR_SEL_MOD_SHIFT 0
+#define MCDE_EXTSRCXCR_SEL_MOD_MASK 0x00000003
+#define MCDE_EXTSRCXCR_SEL_MOD_EXTERNAL_SEL 0
+#define MCDE_EXTSRCXCR_SEL_MOD_AUTO_TOGGLE 1
+#define MCDE_EXTSRCXCR_SEL_MOD_SOFTWARE_SEL 2
+#define MCDE_EXTSRCXCR_MULTIOVL_CTRL_PRIMARY BIT(2) /* 0 = all */
+#define MCDE_EXTSRCXCR_FS_DIV_DISABLE BIT(3)
+#define MCDE_EXTSRCXCR_FORCE_FS_DIV BIT(4)
+
+/* Only external source 6 has a second address register */
+#define MCDE_EXTSRC6A2 0x000002C8
+
+/* 6 overlays */
+#define MCDE_OVL0CR 0x00000400
+#define MCDE_OVL1CR 0x00000420
+#define MCDE_OVL2CR 0x00000440
+#define MCDE_OVL3CR 0x00000460
+#define MCDE_OVL4CR 0x00000480
+#define MCDE_OVL5CR 0x000004A0
+#define MCDE_OVLXCR_OVLEN BIT(0)
+#define MCDE_OVLXCR_COLCCTRL_DISABLED 0
+#define MCDE_OVLXCR_COLCCTRL_ENABLED_NO_SAT (1 << 1)
+#define MCDE_OVLXCR_COLCCTRL_ENABLED_SAT (2 << 1)
+#define MCDE_OVLXCR_CKEYGEN BIT(3)
+#define MCDE_OVLXCR_ALPHAPMEN BIT(4)
+#define MCDE_OVLXCR_OVLF BIT(5)
+#define MCDE_OVLXCR_OVLR BIT(6)
+#define MCDE_OVLXCR_OVLB BIT(7)
+#define MCDE_OVLXCR_FETCH_ROPC_SHIFT 8
+#define MCDE_OVLXCR_FETCH_ROPC_MASK 0x0000FF00
+#define MCDE_OVLXCR_STBPRIO_SHIFT 16
+#define MCDE_OVLXCR_STBPRIO_MASK 0x000F0000
+#define MCDE_OVLXCR_BURSTSIZE_SHIFT 20
+#define MCDE_OVLXCR_BURSTSIZE_MASK 0x00F00000
+#define MCDE_OVLXCR_BURSTSIZE_1W 0
+#define MCDE_OVLXCR_BURSTSIZE_2W 1
+#define MCDE_OVLXCR_BURSTSIZE_4W 2
+#define MCDE_OVLXCR_BURSTSIZE_8W 3
+#define MCDE_OVLXCR_BURSTSIZE_16W 4
+#define MCDE_OVLXCR_BURSTSIZE_HW_1W 8
+#define MCDE_OVLXCR_BURSTSIZE_HW_2W 9
+#define MCDE_OVLXCR_BURSTSIZE_HW_4W 10
+#define MCDE_OVLXCR_BURSTSIZE_HW_8W 11
+#define MCDE_OVLXCR_BURSTSIZE_HW_16W 12
+#define MCDE_OVLXCR_MAXOUTSTANDING_SHIFT 24
+#define MCDE_OVLXCR_MAXOUTSTANDING_MASK 0x0F000000
+#define MCDE_OVLXCR_MAXOUTSTANDING_1_REQ 0
+#define MCDE_OVLXCR_MAXOUTSTANDING_2_REQ 1
+#define MCDE_OVLXCR_MAXOUTSTANDING_4_REQ 2
+#define MCDE_OVLXCR_MAXOUTSTANDING_8_REQ 3
+#define MCDE_OVLXCR_MAXOUTSTANDING_16_REQ 4
+#define MCDE_OVLXCR_ROTBURSTSIZE_SHIFT 28
+#define MCDE_OVLXCR_ROTBURSTSIZE_MASK 0xF0000000
+#define MCDE_OVLXCR_ROTBURSTSIZE_1W 0
+#define MCDE_OVLXCR_ROTBURSTSIZE_2W 1
+#define MCDE_OVLXCR_ROTBURSTSIZE_4W 2
+#define MCDE_OVLXCR_ROTBURSTSIZE_8W 3
+#define MCDE_OVLXCR_ROTBURSTSIZE_16W 4
+#define MCDE_OVLXCR_ROTBURSTSIZE_HW_1W 8
+#define MCDE_OVLXCR_ROTBURSTSIZE_HW_2W 9
+#define MCDE_OVLXCR_ROTBURSTSIZE_HW_4W 10
+#define MCDE_OVLXCR_ROTBURSTSIZE_HW_8W 11
+#define MCDE_OVLXCR_ROTBURSTSIZE_HW_16W 12
+
+#define MCDE_OVL0CONF 0x00000404
+#define MCDE_OVL1CONF 0x00000424
+#define MCDE_OVL2CONF 0x00000444
+#define MCDE_OVL3CONF 0x00000464
+#define MCDE_OVL4CONF 0x00000484
+#define MCDE_OVL5CONF 0x000004A4
+#define MCDE_OVLXCONF_PPL_SHIFT 0
+#define MCDE_OVLXCONF_PPL_MASK 0x000007FF
+#define MCDE_OVLXCONF_EXTSRC_ID_SHIFT 11
+#define MCDE_OVLXCONF_EXTSRC_ID_MASK 0x00007800
+#define MCDE_OVLXCONF_LPF_SHIFT 16
+#define MCDE_OVLXCONF_LPF_MASK 0x07FF0000
+
+#define MCDE_OVL0CONF2 0x00000408
+#define MCDE_OVL1CONF2 0x00000428
+#define MCDE_OVL2CONF2 0x00000448
+#define MCDE_OVL3CONF2 0x00000468
+#define MCDE_OVL4CONF2 0x00000488
+#define MCDE_OVL5CONF2 0x000004A8
+#define MCDE_OVLXCONF2_BP_PER_PIXEL_ALPHA 0
+#define MCDE_OVLXCONF2_BP_CONSTANT_ALPHA BIT(0)
+#define MCDE_OVLXCONF2_ALPHAVALUE_SHIFT 1
+#define MCDE_OVLXCONF2_ALPHAVALUE_MASK 0x000001FE
+#define MCDE_OVLXCONF2_OPQ BIT(9)
+#define MCDE_OVLXCONF2_PIXOFF_SHIFT 10
+#define MCDE_OVLXCONF2_PIXOFF_MASK 0x0000FC00
+#define MCDE_OVLXCONF2_PIXELFETCHERWATERMARKLEVEL_SHIFT 16
+#define MCDE_OVLXCONF2_PIXELFETCHERWATERMARKLEVEL_MASK 0x1FFF0000
+
+#define MCDE_OVL0LJINC 0x0000040C
+#define MCDE_OVL1LJINC 0x0000042C
+#define MCDE_OVL2LJINC 0x0000044C
+#define MCDE_OVL3LJINC 0x0000046C
+#define MCDE_OVL4LJINC 0x0000048C
+#define MCDE_OVL5LJINC 0x000004AC
+
+#define MCDE_OVL0CROP 0x00000410
+#define MCDE_OVL1CROP 0x00000430
+#define MCDE_OVL2CROP 0x00000450
+#define MCDE_OVL3CROP 0x00000470
+#define MCDE_OVL4CROP 0x00000490
+#define MCDE_OVL5CROP 0x000004B0
+#define MCDE_OVLXCROP_TMRGN_SHIFT 0
+#define MCDE_OVLXCROP_TMRGN_MASK 0x003FFFFF
+#define MCDE_OVLXCROP_LMRGN_SHIFT 22
+#define MCDE_OVLXCROP_LMRGN_MASK 0xFFC00000
+
+#define MCDE_OVL0COMP 0x00000414
+#define MCDE_OVL1COMP 0x00000434
+#define MCDE_OVL2COMP 0x00000454
+#define MCDE_OVL3COMP 0x00000474
+#define MCDE_OVL4COMP 0x00000494
+#define MCDE_OVL5COMP 0x000004B4
+#define MCDE_OVLXCOMP_XPOS_SHIFT 0
+#define MCDE_OVLXCOMP_XPOS_MASK 0x000007FF
+#define MCDE_OVLXCOMP_CH_ID_SHIFT 11
+#define MCDE_OVLXCOMP_CH_ID_MASK 0x00007800
+#define MCDE_OVLXCOMP_YPOS_SHIFT 16
+#define MCDE_OVLXCOMP_YPOS_MASK 0x07FF0000
+#define MCDE_OVLXCOMP_Z_SHIFT 27
+#define MCDE_OVLXCOMP_Z_MASK 0x78000000
+
+#define MCDE_CRC 0x00000C00
+#define MCDE_CRC_C1EN BIT(2)
+#define MCDE_CRC_C2EN BIT(3)
+#define MCDE_CRC_SYCEN0 BIT(7)
+#define MCDE_CRC_SYCEN1 BIT(8)
+#define MCDE_CRC_SIZE1 BIT(9)
+#define MCDE_CRC_SIZE2 BIT(10)
+#define MCDE_CRC_YUVCONVC1EN BIT(15)
+#define MCDE_CRC_CS1EN BIT(16)
+#define MCDE_CRC_CS2EN BIT(17)
+#define MCDE_CRC_CS1POL BIT(19)
+#define MCDE_CRC_CS2POL BIT(20)
+#define MCDE_CRC_CD1POL BIT(21)
+#define MCDE_CRC_CD2POL BIT(22)
+#define MCDE_CRC_WR1POL BIT(23)
+#define MCDE_CRC_WR2POL BIT(24)
+#define MCDE_CRC_RD1POL BIT(25)
+#define MCDE_CRC_RD2POL BIT(26)
+#define MCDE_CRC_SYNCCTRL_SHIFT 29
+#define MCDE_CRC_SYNCCTRL_MASK 0x60000000
+#define MCDE_CRC_SYNCCTRL_NO_SYNC 0
+#define MCDE_CRC_SYNCCTRL_DBI0 1
+#define MCDE_CRC_SYNCCTRL_DBI1 2
+#define MCDE_CRC_SYNCCTRL_PING_PONG 3
+#define MCDE_CRC_CLAMPC1EN BIT(31)
+
+#define MCDE_VSCRC0 0x00000C5C
+#define MCDE_VSCRC1 0x00000C60
+#define MCDE_VSCRC_VSPMIN_MASK 0x00000FFF
+#define MCDE_VSCRC_VSPMAX_SHIFT 12
+#define MCDE_VSCRC_VSPMAX_MASK 0x00FFF000
+#define MCDE_VSCRC_VSPDIV_SHIFT 24
+#define MCDE_VSCRC_VSPDIV_MASK 0x07000000
+#define MCDE_VSCRC_VSPDIV_MCDECLK_DIV_1 0
+#define MCDE_VSCRC_VSPDIV_MCDECLK_DIV_2 1
+#define MCDE_VSCRC_VSPDIV_MCDECLK_DIV_4 2
+#define MCDE_VSCRC_VSPDIV_MCDECLK_DIV_8 3
+#define MCDE_VSCRC_VSPDIV_MCDECLK_DIV_16 4
+#define MCDE_VSCRC_VSPDIV_MCDECLK_DIV_32 5
+#define MCDE_VSCRC_VSPDIV_MCDECLK_DIV_64 6
+#define MCDE_VSCRC_VSPDIV_MCDECLK_DIV_128 7
+#define MCDE_VSCRC_VSPOL BIT(27) /* 0 active high, 1 active low */
+#define MCDE_VSCRC_VSSEL BIT(28) /* 0 VSYNC0, 1 VSYNC1 */
+#define MCDE_VSCRC_VSDBL BIT(29)
+
+/* Channel config 0..3 */
+#define MCDE_CHNL0CONF 0x00000600
+#define MCDE_CHNL1CONF 0x00000620
+#define MCDE_CHNL2CONF 0x00000640
+#define MCDE_CHNL3CONF 0x00000660
+#define MCDE_CHNLXCONF_PPL_SHIFT 0
+#define MCDE_CHNLXCONF_PPL_MASK 0x000007FF
+#define MCDE_CHNLXCONF_LPF_SHIFT 16
+#define MCDE_CHNLXCONF_LPF_MASK 0x07FF0000
+#define MCDE_MAX_WIDTH 2048
+
+/* Channel status 0..3 */
+#define MCDE_CHNL0STAT 0x00000604
+#define MCDE_CHNL1STAT 0x00000624
+#define MCDE_CHNL2STAT 0x00000644
+#define MCDE_CHNL3STAT 0x00000664
+#define MCDE_CHNLXSTAT_CHNLRD BIT(0)
+#define MCDE_CHNLXSTAT_CHNLA BIT(1)
+#define MCDE_CHNLXSTAT_CHNLBLBCKGND_EN BIT(16)
+#define MCDE_CHNLXSTAT_PPLX2_V422 BIT(17)
+#define MCDE_CHNLXSTAT_LPFX2_V422 BIT(18)
+
+/* Sync settings for channel 0..3 */
+#define MCDE_CHNL0SYNCHMOD 0x00000608
+#define MCDE_CHNL1SYNCHMOD 0x00000628
+#define MCDE_CHNL2SYNCHMOD 0x00000648
+#define MCDE_CHNL3SYNCHMOD 0x00000668
+
+#define MCDE_CHNLXSYNCHMOD_SRC_SYNCH_SHIFT 0
+#define MCDE_CHNLXSYNCHMOD_SRC_SYNCH_MASK 0x00000003
+#define MCDE_CHNLXSYNCHMOD_SRC_SYNCH_HARDWARE 0
+#define MCDE_CHNLXSYNCHMOD_SRC_SYNCH_NO_SYNCH 1
+#define MCDE_CHNLXSYNCHMOD_SRC_SYNCH_SOFTWARE 2
+#define MCDE_CHNLXSYNCHMOD_OUT_SYNCH_SRC_SHIFT 2
+#define MCDE_CHNLXSYNCHMOD_OUT_SYNCH_SRC_MASK 0x0000001C
+#define MCDE_CHNLXSYNCHMOD_OUT_SYNCH_SRC_FORMATTER 0
+#define MCDE_CHNLXSYNCHMOD_OUT_SYNCH_SRC_TE0 1
+#define MCDE_CHNLXSYNCHMOD_OUT_SYNCH_SRC_TE1 2
+
+/* Software sync triggers for channel 0..3 */
+#define MCDE_CHNL0SYNCHSW 0x0000060C
+#define MCDE_CHNL1SYNCHSW 0x0000062C
+#define MCDE_CHNL2SYNCHSW 0x0000064C
+#define MCDE_CHNL3SYNCHSW 0x0000066C
+#define MCDE_CHNLXSYNCHSW_SW_TRIG BIT(0)
+
+#define MCDE_CHNL0BCKGNDCOL 0x00000610
+#define MCDE_CHNL1BCKGNDCOL 0x00000630
+#define MCDE_CHNL2BCKGNDCOL 0x00000650
+#define MCDE_CHNL3BCKGNDCOL 0x00000670
+#define MCDE_CHNLXBCKGNDCOL_B_SHIFT 0
+#define MCDE_CHNLXBCKGNDCOL_B_MASK 0x000000FF
+#define MCDE_CHNLXBCKGNDCOL_G_SHIFT 8
+#define MCDE_CHNLXBCKGNDCOL_G_MASK 0x0000FF00
+#define MCDE_CHNLXBCKGNDCOL_R_SHIFT 16
+#define MCDE_CHNLXBCKGNDCOL_R_MASK 0x00FF0000
+
+#define MCDE_CHNL0MUXING 0x00000614
+#define MCDE_CHNL1MUXING 0x00000634
+#define MCDE_CHNL2MUXING 0x00000654
+#define MCDE_CHNL3MUXING 0x00000674
+#define MCDE_CHNLXMUXING_FIFO_ID_FIFO_A 0
+#define MCDE_CHNLXMUXING_FIFO_ID_FIFO_B 1
+#define MCDE_CHNLXMUXING_FIFO_ID_FIFO_C0 2
+#define MCDE_CHNLXMUXING_FIFO_ID_FIFO_C1 3
+
+/* Pixel processing control registers for channel A B, */
+#define MCDE_CRA0 0x00000800
+#define MCDE_CRB0 0x00000A00
+#define MCDE_CRX0_FLOEN BIT(0)
+#define MCDE_CRX0_POWEREN BIT(1)
+#define MCDE_CRX0_BLENDEN BIT(2)
+#define MCDE_CRX0_AFLICKEN BIT(3)
+#define MCDE_CRX0_PALEN BIT(4)
+#define MCDE_CRX0_DITHEN BIT(5)
+#define MCDE_CRX0_GAMEN BIT(6)
+#define MCDE_CRX0_KEYCTRL_SHIFT 7
+#define MCDE_CRX0_KEYCTRL_MASK 0x00000380
+#define MCDE_CRX0_KEYCTRL_OFF 0
+#define MCDE_CRX0_KEYCTRL_ALPHA_RGB 1
+#define MCDE_CRX0_KEYCTRL_RGB 2
+#define MCDE_CRX0_KEYCTRL_FALPHA_FRGB 4
+#define MCDE_CRX0_KEYCTRL_FRGB 5
+#define MCDE_CRX0_BLENDCTRL BIT(10)
+#define MCDE_CRX0_FLICKMODE_SHIFT 11
+#define MCDE_CRX0_FLICKMODE_MASK 0x00001800
+#define MCDE_CRX0_FLICKMODE_FORCE_FILTER_0 0
+#define MCDE_CRX0_FLICKMODE_ADAPTIVE 1
+#define MCDE_CRX0_FLICKMODE_TEST_MODE 2
+#define MCDE_CRX0_FLOCKFORMAT_RGB BIT(13) /* 0 = YCVCR */
+#define MCDE_CRX0_PALMODE_GAMMA BIT(14) /* 0 = palette */
+#define MCDE_CRX0_OLEDEN BIT(15)
+#define MCDE_CRX0_ALPHABLEND_SHIFT 16
+#define MCDE_CRX0_ALPHABLEND_MASK 0x00FF0000
+#define MCDE_CRX0_ROTEN BIT(24)
+
+#define MCDE_CRA1 0x00000804
+#define MCDE_CRB1 0x00000A04
+#define MCDE_CRX1_PCD_SHIFT 0
+#define MCDE_CRX1_PCD_MASK 0x000003FF
+#define MCDE_CRX1_CLKSEL_SHIFT 10
+#define MCDE_CRX1_CLKSEL_MASK 0x00001C00
+#define MCDE_CRX1_CLKSEL_CLKPLL72 0
+#define MCDE_CRX1_CLKSEL_CLKPLL27 2
+#define MCDE_CRX1_CLKSEL_TV1CLK 3
+#define MCDE_CRX1_CLKSEL_TV2CLK 4
+#define MCDE_CRX1_CLKSEL_MCDECLK 5
+#define MCDE_CRX1_CDWIN_SHIFT 13
+#define MCDE_CRX1_CDWIN_MASK 0x0001E000
+#define MCDE_CRX1_CDWIN_8BPP_C1 0
+#define MCDE_CRX1_CDWIN_12BPP_C1 1
+#define MCDE_CRX1_CDWIN_12BPP_C2 2
+#define MCDE_CRX1_CDWIN_16BPP_C1 3
+#define MCDE_CRX1_CDWIN_16BPP_C2 4
+#define MCDE_CRX1_CDWIN_16BPP_C3 5
+#define MCDE_CRX1_CDWIN_18BPP_C1 6
+#define MCDE_CRX1_CDWIN_18BPP_C2 7
+#define MCDE_CRX1_CDWIN_24BPP 8
+#define MCDE_CRX1_OUTBPP_SHIFT 25
+#define MCDE_CRX1_OUTBPP_MASK 0x1E000000
+#define MCDE_CRX1_OUTBPP_MONO1 0
+#define MCDE_CRX1_OUTBPP_MONO2 1
+#define MCDE_CRX1_OUTBPP_MONO4 2
+#define MCDE_CRX1_OUTBPP_MONO8 3
+#define MCDE_CRX1_OUTBPP_8BPP 4
+#define MCDE_CRX1_OUTBPP_12BPP 5
+#define MCDE_CRX1_OUTBPP_15BPP 6
+#define MCDE_CRX1_OUTBPP_16BPP 7
+#define MCDE_CRX1_OUTBPP_18BPP 8
+#define MCDE_CRX1_OUTBPP_24BPP 9
+#define MCDE_CRX1_BCD BIT(29)
+#define MCDE_CRA1_CLKTYPE_TVXCLKSEL1 BIT(30) /* 0 = TVXCLKSEL1 */
+
+#define MCDE_COLKEYA 0x00000808
+#define MCDE_COLKEYB 0x00000A08
+
+#define MCDE_FCOLKEYA 0x0000080C
+#define MCDE_FCOLKEYB 0x00000A0C
+
+#define MCDE_RGBCONV1A 0x00000810
+#define MCDE_RGBCONV1B 0x00000A10
+
+#define MCDE_RGBCONV2A 0x00000814
+#define MCDE_RGBCONV2B 0x00000A14
+
+#define MCDE_RGBCONV3A 0x00000818
+#define MCDE_RGBCONV3B 0x00000A18
+
+#define MCDE_RGBCONV4A 0x0000081C
+#define MCDE_RGBCONV4B 0x00000A1C
+
+#define MCDE_RGBCONV5A 0x00000820
+#define MCDE_RGBCONV5B 0x00000A20
+
+#define MCDE_RGBCONV6A 0x00000824
+#define MCDE_RGBCONV6B 0x00000A24
+
+/* Rotation */
+#define MCDE_ROTACONF 0x0000087C
+#define MCDE_ROTBCONF 0x00000A7C
+
+#define MCDE_SYNCHCONFA 0x00000880
+#define MCDE_SYNCHCONFB 0x00000A80
+
+/* Channel A+B control registers */
+#define MCDE_CTRLA 0x00000884
+#define MCDE_CTRLB 0x00000A84
+#define MCDE_CTRLX_FIFOWTRMRK_SHIFT 0
+#define MCDE_CTRLX_FIFOWTRMRK_MASK 0x000003FF
+#define MCDE_CTRLX_FIFOEMPTY BIT(12)
+#define MCDE_CTRLX_FIFOFULL BIT(13)
+#define MCDE_CTRLX_FORMID_SHIFT 16
+#define MCDE_CTRLX_FORMID_MASK 0x00070000
+#define MCDE_CTRLX_FORMID_DSI0VID 0
+#define MCDE_CTRLX_FORMID_DSI0CMD 1
+#define MCDE_CTRLX_FORMID_DSI1VID 2
+#define MCDE_CTRLX_FORMID_DSI1CMD 3
+#define MCDE_CTRLX_FORMID_DSI2VID 4
+#define MCDE_CTRLX_FORMID_DSI2CMD 5
+#define MCDE_CTRLX_FORMID_DPIA 0
+#define MCDE_CTRLX_FORMID_DPIB 1
+#define MCDE_CTRLX_FORMTYPE_SHIFT 20
+#define MCDE_CTRLX_FORMTYPE_MASK 0x00700000
+#define MCDE_CTRLX_FORMTYPE_DPITV 0
+#define MCDE_CTRLX_FORMTYPE_DBI 1
+#define MCDE_CTRLX_FORMTYPE_DSI 2
+
+#define MCDE_DSIVID0CONF0 0x00000E00
+#define MCDE_DSICMD0CONF0 0x00000E20
+#define MCDE_DSIVID1CONF0 0x00000E40
+#define MCDE_DSICMD1CONF0 0x00000E60
+#define MCDE_DSIVID2CONF0 0x00000E80
+#define MCDE_DSICMD2CONF0 0x00000EA0
+#define MCDE_DSICONF0_BLANKING_SHIFT 0
+#define MCDE_DSICONF0_BLANKING_MASK 0x000000FF
+#define MCDE_DSICONF0_VID_MODE_CMD 0
+#define MCDE_DSICONF0_VID_MODE_VID BIT(12)
+#define MCDE_DSICONF0_CMD8 BIT(13)
+#define MCDE_DSICONF0_BIT_SWAP BIT(16)
+#define MCDE_DSICONF0_BYTE_SWAP BIT(17)
+#define MCDE_DSICONF0_DCSVID_NOTGEN BIT(18)
+#define MCDE_DSICONF0_PACKING_SHIFT 20
+#define MCDE_DSICONF0_PACKING_MASK 0x00700000
+#define MCDE_DSICONF0_PACKING_RGB565 0
+#define MCDE_DSICONF0_PACKING_RGB666 1
+#define MCDE_DSICONF0_PACKING_RGB666_PACKED 2
+#define MCDE_DSICONF0_PACKING_RGB888 3
+#define MCDE_DSICONF0_PACKING_HDTV 4
+
+#define MCDE_DSIVID0FRAME 0x00000E04
+#define MCDE_DSICMD0FRAME 0x00000E24
+#define MCDE_DSIVID1FRAME 0x00000E44
+#define MCDE_DSICMD1FRAME 0x00000E64
+#define MCDE_DSIVID2FRAME 0x00000E84
+#define MCDE_DSICMD2FRAME 0x00000EA4
+
+#define MCDE_DSIVID0PKT 0x00000E08
+#define MCDE_DSICMD0PKT 0x00000E28
+#define MCDE_DSIVID1PKT 0x00000E48
+#define MCDE_DSICMD1PKT 0x00000E68
+#define MCDE_DSIVID2PKT 0x00000E88
+#define MCDE_DSICMD2PKT 0x00000EA8
+
+#define MCDE_DSIVID0SYNC 0x00000E0C
+#define MCDE_DSICMD0SYNC 0x00000E2C
+#define MCDE_DSIVID1SYNC 0x00000E4C
+#define MCDE_DSICMD1SYNC 0x00000E6C
+#define MCDE_DSIVID2SYNC 0x00000E8C
+#define MCDE_DSICMD2SYNC 0x00000EAC
+
+#define MCDE_DSIVID0CMDW 0x00000E10
+#define MCDE_DSICMD0CMDW 0x00000E30
+#define MCDE_DSIVID1CMDW 0x00000E50
+#define MCDE_DSICMD1CMDW 0x00000E70
+#define MCDE_DSIVID2CMDW 0x00000E90
+#define MCDE_DSICMD2CMDW 0x00000EB0
+#define MCDE_DSIVIDXCMDW_CMDW_CONTINUE_SHIFT 0
+#define MCDE_DSIVIDXCMDW_CMDW_CONTINUE_MASK 0x0000FFFF
+#define MCDE_DSIVIDXCMDW_CMDW_START_SHIFT 16
+#define MCDE_DSIVIDXCMDW_CMDW_START_MASK 0xFFFF0000
+
+#define MCDE_DSIVID0DELAY0 0x00000E14
+#define MCDE_DSICMD0DELAY0 0x00000E34
+#define MCDE_DSIVID1DELAY0 0x00000E54
+#define MCDE_DSICMD1DELAY0 0x00000E74
+#define MCDE_DSIVID2DELAY0 0x00000E94
+#define MCDE_DSICMD2DELAY0 0x00000EB4
+
+#define MCDE_DSIVID0DELAY1 0x00000E18
+#define MCDE_DSICMD0DELAY1 0x00000E38
+#define MCDE_DSIVID1DELAY1 0x00000E58
+#define MCDE_DSICMD1DELAY1 0x00000E78
+#define MCDE_DSIVID2DELAY1 0x00000E98
+#define MCDE_DSICMD2DELAY1 0x00000EB8
+
+#endif /* __DRM_MCDE_DISPLAY_REGS */
diff --git a/drivers/gpu/drm/mcde/mcde_drm.h b/drivers/gpu/drm/mcde/mcde_drm.h
new file mode 100644
index 000000000000..dab4db021231
--- /dev/null
+++ b/drivers/gpu/drm/mcde/mcde_drm.h
@@ -0,0 +1,44 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2018 Linus Walleij <linus.walleij@linaro.org>
+ * Parts of this file were based on the MCDE driver by Marcus Lorentzon
+ * (C) ST-Ericsson SA 2013
+ */
+#include <drm/drm_simple_kms_helper.h>
+
+#ifndef _MCDE_DRM_H_
+#define _MCDE_DRM_H_
+
+struct mcde {
+ struct drm_device drm;
+ struct device *dev;
+ struct drm_panel *panel;
+ struct drm_bridge *bridge;
+ struct drm_connector *connector;
+ struct drm_simple_display_pipe pipe;
+ struct mipi_dsi_device *mdsi;
+ s16 stride;
+ bool te_sync;
+ bool oneshot_mode;
+ unsigned int flow_active;
+ spinlock_t flow_lock; /* Locks the channel flow control */
+
+ void __iomem *regs;
+
+ struct clk *mcde_clk;
+ struct clk *lcd_clk;
+ struct clk *hdmi_clk;
+
+ struct regulator *epod;
+ struct regulator *vana;
+};
+
+bool mcde_dsi_irq(struct mipi_dsi_device *mdsi);
+void mcde_dsi_te_request(struct mipi_dsi_device *mdsi);
+extern struct platform_driver mcde_dsi_driver;
+
+void mcde_display_irq(struct mcde *mcde);
+void mcde_display_disable_irqs(struct mcde *mcde);
+int mcde_display_init(struct drm_device *drm);
+
+#endif /* _MCDE_DRM_H_ */
diff --git a/drivers/gpu/drm/mcde/mcde_drv.c b/drivers/gpu/drm/mcde/mcde_drv.c
new file mode 100644
index 000000000000..baf63fb6850a
--- /dev/null
+++ b/drivers/gpu/drm/mcde/mcde_drv.c
@@ -0,0 +1,572 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2018 Linus Walleij <linus.walleij@linaro.org>
+ * Parts of this file were based on the MCDE driver by Marcus Lorentzon
+ * (C) ST-Ericsson SA 2013
+ */
+
+/**
+ * DOC: ST-Ericsson MCDE Driver
+ *
+ * The MCDE (short for multi-channel display engine) is a graphics
+ * controller found in the Ux500 chipsets, such as NovaThor U8500.
+ * It was initially conceptualized by ST Microelectronics for the
+ * successor of the Nomadik line, STn8500 but productified in the
+ * ST-Ericsson U8500 where is was used for mass-market deployments
+ * in Android phones from Samsung and Sony Ericsson.
+ *
+ * It can do 1080p30 on SDTV CCIR656, DPI-2, DBI-2 or DSI for
+ * panels with or without frame buffering and can convert most
+ * input formats including most variants of RGB and YUV.
+ *
+ * The hardware has four display pipes, and the layout is a little
+ * bit like this:
+ *
+ * Memory -> Overlay -> Channel -> FIFO -> 5 formatters -> DSI/DPI
+ * External 0..5 0..3 A,B, 3 x DSI bridge
+ * source 0..9 C0,C1 2 x DPI
+ *
+ * FIFOs A and B are for LCD and HDMI while FIFO CO/C1 are for
+ * panels with embedded buffer.
+ * 3 of the formatters are for DSI.
+ * 2 of the formatters are for DPI.
+ *
+ * Behind the formatters are the DSI or DPI ports that route to
+ * the external pins of the chip. As there are 3 DSI ports and one
+ * DPI port, it is possible to configure up to 4 display pipelines
+ * (effectively using channels 0..3) for concurrent use.
+ *
+ * In the current DRM/KMS setup, we use one external source, one overlay,
+ * one FIFO and one formatter which we connect to the simple CMA framebuffer
+ * helpers. We then provide a bridge to the DSI port, and on the DSI port
+ * bridge we connect hang a panel bridge or other bridge. This may be subject
+ * to change as we exploit more of the hardware capabilities.
+ *
+ * TODO:
+ * - Enabled damaged rectangles using drm_plane_enable_fb_damage_clips()
+ * so we can selectively just transmit the damaged area to a
+ * command-only display.
+ * - Enable mixing of more planes, possibly at the cost of moving away
+ * from using the simple framebuffer pipeline.
+ * - Enable output to bridges such as the AV8100 HDMI encoder from
+ * the DSI bridge.
+ */
+
+#include <linux/clk.h>
+#include <linux/component.h>
+#include <linux/dma-buf.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+#include <linux/slab.h>
+
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_bridge.h>
+#include <drm/drm_drv.h>
+#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_fb_helper.h>
+#include <drm/drm_gem.h>
+#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_gem_framebuffer_helper.h>
+#include <drm/drm_of.h>
+#include <drm/drm_probe_helper.h>
+#include <drm/drm_panel.h>
+#include <drm/drm_vblank.h>
+
+#include "mcde_drm.h"
+
+#define DRIVER_DESC "DRM module for MCDE"
+
+#define MCDE_CR 0x00000000
+#define MCDE_CR_IFIFOEMPTYLINECOUNT_V422_SHIFT 0
+#define MCDE_CR_IFIFOEMPTYLINECOUNT_V422_MASK 0x0000003F
+#define MCDE_CR_IFIFOCTRLEN BIT(15)
+#define MCDE_CR_UFRECOVERY_MODE_V422 BIT(16)
+#define MCDE_CR_WRAP_MODE_V422_SHIFT BIT(17)
+#define MCDE_CR_AUTOCLKG_EN BIT(30)
+#define MCDE_CR_MCDEEN BIT(31)
+
+#define MCDE_CONF0 0x00000004
+#define MCDE_CONF0_SYNCMUX0 BIT(0)
+#define MCDE_CONF0_SYNCMUX1 BIT(1)
+#define MCDE_CONF0_SYNCMUX2 BIT(2)
+#define MCDE_CONF0_SYNCMUX3 BIT(3)
+#define MCDE_CONF0_SYNCMUX4 BIT(4)
+#define MCDE_CONF0_SYNCMUX5 BIT(5)
+#define MCDE_CONF0_SYNCMUX6 BIT(6)
+#define MCDE_CONF0_SYNCMUX7 BIT(7)
+#define MCDE_CONF0_IFIFOCTRLWTRMRKLVL_SHIFT 12
+#define MCDE_CONF0_IFIFOCTRLWTRMRKLVL_MASK 0x00007000
+#define MCDE_CONF0_OUTMUX0_SHIFT 16
+#define MCDE_CONF0_OUTMUX0_MASK 0x00070000
+#define MCDE_CONF0_OUTMUX1_SHIFT 19
+#define MCDE_CONF0_OUTMUX1_MASK 0x00380000
+#define MCDE_CONF0_OUTMUX2_SHIFT 22
+#define MCDE_CONF0_OUTMUX2_MASK 0x01C00000
+#define MCDE_CONF0_OUTMUX3_SHIFT 25
+#define MCDE_CONF0_OUTMUX3_MASK 0x0E000000
+#define MCDE_CONF0_OUTMUX4_SHIFT 28
+#define MCDE_CONF0_OUTMUX4_MASK 0x70000000
+
+#define MCDE_SSP 0x00000008
+#define MCDE_AIS 0x00000100
+#define MCDE_IMSCERR 0x00000110
+#define MCDE_RISERR 0x00000120
+#define MCDE_MISERR 0x00000130
+#define MCDE_SISERR 0x00000140
+
+#define MCDE_PID 0x000001FC
+#define MCDE_PID_METALFIX_VERSION_SHIFT 0
+#define MCDE_PID_METALFIX_VERSION_MASK 0x000000FF
+#define MCDE_PID_DEVELOPMENT_VERSION_SHIFT 8
+#define MCDE_PID_DEVELOPMENT_VERSION_MASK 0x0000FF00
+#define MCDE_PID_MINOR_VERSION_SHIFT 16
+#define MCDE_PID_MINOR_VERSION_MASK 0x00FF0000
+#define MCDE_PID_MAJOR_VERSION_SHIFT 24
+#define MCDE_PID_MAJOR_VERSION_MASK 0xFF000000
+
+static const struct drm_mode_config_funcs mcde_mode_config_funcs = {
+ .fb_create = drm_gem_fb_create_with_dirty,
+ .atomic_check = drm_atomic_helper_check,
+ .atomic_commit = drm_atomic_helper_commit,
+};
+
+static const struct drm_mode_config_helper_funcs mcde_mode_config_helpers = {
+ /*
+ * Using this function is necessary to commit atomic updates
+ * that need the CRTC to be enabled before a commit, as is
+ * the case with e.g. DSI displays.
+ */
+ .atomic_commit_tail = drm_atomic_helper_commit_tail_rpm,
+};
+
+static irqreturn_t mcde_irq(int irq, void *data)
+{
+ struct mcde *mcde = data;
+ u32 val;
+
+ val = readl(mcde->regs + MCDE_MISERR);
+
+ mcde_display_irq(mcde);
+
+ if (val)
+ dev_info(mcde->dev, "some error IRQ\n");
+ writel(val, mcde->regs + MCDE_RISERR);
+
+ return IRQ_HANDLED;
+}
+
+static int mcde_modeset_init(struct drm_device *drm)
+{
+ struct drm_mode_config *mode_config;
+ struct mcde *mcde = drm->dev_private;
+ int ret;
+
+ if (!mcde->bridge) {
+ dev_err(drm->dev, "no display output bridge yet\n");
+ return -EPROBE_DEFER;
+ }
+
+ mode_config = &drm->mode_config;
+ mode_config->funcs = &mcde_mode_config_funcs;
+ mode_config->helper_private = &mcde_mode_config_helpers;
+ /* This hardware can do 1080p */
+ mode_config->min_width = 1;
+ mode_config->max_width = 1920;
+ mode_config->min_height = 1;
+ mode_config->max_height = 1080;
+
+ /*
+ * Currently we only support vblank handling on the DSI bridge, using
+ * TE synchronization. If TE sync is not set up, it is still possible
+ * to push out a single update on demand, but this is hard for DRM to
+ * exploit.
+ */
+ if (mcde->te_sync) {
+ ret = drm_vblank_init(drm, 1);
+ if (ret) {
+ dev_err(drm->dev, "failed to init vblank\n");
+ goto out_config;
+ }
+ }
+
+ ret = mcde_display_init(drm);
+ if (ret) {
+ dev_err(drm->dev, "failed to init display\n");
+ goto out_config;
+ }
+
+ /*
+ * Attach the DSI bridge
+ *
+ * TODO: when adding support for the DPI bridge or several DSI bridges,
+ * we selectively connect the bridge(s) here instead of this simple
+ * attachment.
+ */
+ ret = drm_simple_display_pipe_attach_bridge(&mcde->pipe,
+ mcde->bridge);
+ if (ret) {
+ dev_err(drm->dev, "failed to attach display output bridge\n");
+ goto out_config;
+ }
+
+ drm_mode_config_reset(drm);
+ drm_kms_helper_poll_init(drm);
+ drm_fbdev_generic_setup(drm, 32);
+
+ return 0;
+
+out_config:
+ drm_mode_config_cleanup(drm);
+ return ret;
+}
+
+static void mcde_release(struct drm_device *drm)
+{
+ struct mcde *mcde = drm->dev_private;
+
+ drm_mode_config_cleanup(drm);
+ drm_dev_fini(drm);
+ kfree(mcde);
+}
+
+DEFINE_DRM_GEM_CMA_FOPS(drm_fops);
+
+static struct drm_driver mcde_drm_driver = {
+ .driver_features =
+ DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME | DRIVER_ATOMIC,
+ .release = mcde_release,
+ .lastclose = drm_fb_helper_lastclose,
+ .ioctls = NULL,
+ .fops = &drm_fops,
+ .name = "mcde",
+ .desc = DRIVER_DESC,
+ .date = "20180529",
+ .major = 1,
+ .minor = 0,
+ .patchlevel = 0,
+ .dumb_create = drm_gem_cma_dumb_create,
+ .gem_free_object_unlocked = drm_gem_cma_free_object,
+ .gem_vm_ops = &drm_gem_cma_vm_ops,
+
+ .prime_handle_to_fd = drm_gem_prime_handle_to_fd,
+ .prime_fd_to_handle = drm_gem_prime_fd_to_handle,
+ .gem_prime_import = drm_gem_prime_import,
+ .gem_prime_export = drm_gem_prime_export,
+ .gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table,
+ .gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table,
+ .gem_prime_vmap = drm_gem_cma_prime_vmap,
+ .gem_prime_vunmap = drm_gem_cma_prime_vunmap,
+ .gem_prime_mmap = drm_gem_cma_prime_mmap,
+};
+
+static int mcde_drm_bind(struct device *dev)
+{
+ struct drm_device *drm = dev_get_drvdata(dev);
+ int ret;
+
+ drm_mode_config_init(drm);
+
+ ret = component_bind_all(drm->dev, drm);
+ if (ret) {
+ dev_err(dev, "can't bind component devices\n");
+ return ret;
+ }
+
+ ret = mcde_modeset_init(drm);
+ if (ret)
+ goto unbind;
+
+ ret = drm_dev_register(drm, 0);
+ if (ret < 0)
+ goto unbind;
+
+ return 0;
+
+unbind:
+ component_unbind_all(drm->dev, drm);
+ return ret;
+}
+
+static void mcde_drm_unbind(struct device *dev)
+{
+ struct drm_device *drm = dev_get_drvdata(dev);
+
+ drm_dev_unregister(drm);
+ drm_atomic_helper_shutdown(drm);
+ component_unbind_all(drm->dev, drm);
+}
+
+static const struct component_master_ops mcde_drm_comp_ops = {
+ .bind = mcde_drm_bind,
+ .unbind = mcde_drm_unbind,
+};
+
+static struct platform_driver *const mcde_component_drivers[] = {
+ &mcde_dsi_driver,
+};
+
+static int mcde_compare_dev(struct device *dev, void *data)
+{
+ return dev == data;
+}
+
+static int mcde_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct drm_device *drm;
+ struct mcde *mcde;
+ struct component_match *match;
+ struct resource *res;
+ u32 pid;
+ u32 val;
+ int irq;
+ int ret;
+ int i;
+
+ mcde = kzalloc(sizeof(*mcde), GFP_KERNEL);
+ if (!mcde)
+ return -ENOMEM;
+ mcde->dev = dev;
+
+ ret = drm_dev_init(&mcde->drm, &mcde_drm_driver, dev);
+ if (ret) {
+ kfree(mcde);
+ return ret;
+ }
+ drm = &mcde->drm;
+ drm->dev_private = mcde;
+ platform_set_drvdata(pdev, drm);
+
+ /* Enable use of the TE signal and interrupt */
+ mcde->te_sync = true;
+ /* Enable continuous updates: this is what Linux' framebuffer expects */
+ mcde->oneshot_mode = false;
+ drm->dev_private = mcde;
+
+ /* First obtain and turn on the main power */
+ mcde->epod = devm_regulator_get(dev, "epod");
+ if (IS_ERR(mcde->epod)) {
+ ret = PTR_ERR(mcde->epod);
+ dev_err(dev, "can't get EPOD regulator\n");
+ goto dev_unref;
+ }
+ ret = regulator_enable(mcde->epod);
+ if (ret) {
+ dev_err(dev, "can't enable EPOD regulator\n");
+ goto dev_unref;
+ }
+ mcde->vana = devm_regulator_get(dev, "vana");
+ if (IS_ERR(mcde->vana)) {
+ ret = PTR_ERR(mcde->vana);
+ dev_err(dev, "can't get VANA regulator\n");
+ goto regulator_epod_off;
+ }
+ ret = regulator_enable(mcde->vana);
+ if (ret) {
+ dev_err(dev, "can't enable VANA regulator\n");
+ goto regulator_epod_off;
+ }
+ /*
+ * The vendor code uses ESRAM (onchip RAM) and need to activate
+ * the v-esram34 regulator, but we don't use that yet
+ */
+
+ /* Clock the silicon so we can access the registers */
+ mcde->mcde_clk = devm_clk_get(dev, "mcde");
+ if (IS_ERR(mcde->mcde_clk)) {
+ dev_err(dev, "unable to get MCDE main clock\n");
+ ret = PTR_ERR(mcde->mcde_clk);
+ goto regulator_off;
+ }
+ ret = clk_prepare_enable(mcde->mcde_clk);
+ if (ret) {
+ dev_err(dev, "failed to enable MCDE main clock\n");
+ goto regulator_off;
+ }
+ dev_info(dev, "MCDE clk rate %lu Hz\n", clk_get_rate(mcde->mcde_clk));
+
+ mcde->lcd_clk = devm_clk_get(dev, "lcd");
+ if (IS_ERR(mcde->lcd_clk)) {
+ dev_err(dev, "unable to get LCD clock\n");
+ ret = PTR_ERR(mcde->lcd_clk);
+ goto clk_disable;
+ }
+ mcde->hdmi_clk = devm_clk_get(dev, "hdmi");
+ if (IS_ERR(mcde->hdmi_clk)) {
+ dev_err(dev, "unable to get HDMI clock\n");
+ ret = PTR_ERR(mcde->hdmi_clk);
+ goto clk_disable;
+ }
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ mcde->regs = devm_ioremap_resource(dev, res);
+ if (IS_ERR(mcde->regs)) {
+ dev_err(dev, "no MCDE regs\n");
+ ret = -EINVAL;
+ goto clk_disable;
+ }
+
+ irq = platform_get_irq(pdev, 0);
+ if (!irq) {
+ ret = -EINVAL;
+ goto clk_disable;
+ }
+
+ ret = devm_request_irq(dev, irq, mcde_irq, 0, "mcde", mcde);
+ if (ret) {
+ dev_err(dev, "failed to request irq %d\n", ret);
+ goto clk_disable;
+ }
+
+ /*
+ * Check hardware revision, we only support U8500v2 version
+ * as this was the only version used for mass market deployment,
+ * but surely you can add more versions if you have them and
+ * need them.
+ */
+ pid = readl(mcde->regs + MCDE_PID);
+ dev_info(dev, "found MCDE HW revision %d.%d (dev %d, metal fix %d)\n",
+ (pid & MCDE_PID_MAJOR_VERSION_MASK)
+ >> MCDE_PID_MAJOR_VERSION_SHIFT,
+ (pid & MCDE_PID_MINOR_VERSION_MASK)
+ >> MCDE_PID_MINOR_VERSION_SHIFT,
+ (pid & MCDE_PID_DEVELOPMENT_VERSION_MASK)
+ >> MCDE_PID_DEVELOPMENT_VERSION_SHIFT,
+ (pid & MCDE_PID_METALFIX_VERSION_MASK)
+ >> MCDE_PID_METALFIX_VERSION_SHIFT);
+ if (pid != 0x03000800) {
+ dev_err(dev, "unsupported hardware revision\n");
+ ret = -ENODEV;
+ goto clk_disable;
+ }
+
+ /* Set up the main control, watermark level at 7 */
+ val = 7 << MCDE_CONF0_IFIFOCTRLWTRMRKLVL_SHIFT;
+ /* 24 bits DPI: connect LSB Ch B to D[0:7] */
+ val |= 3 << MCDE_CONF0_OUTMUX0_SHIFT;
+ /* TV out: connect LSB Ch B to D[8:15] */
+ val |= 3 << MCDE_CONF0_OUTMUX1_SHIFT;
+ /* Don't care about this muxing */
+ val |= 0 << MCDE_CONF0_OUTMUX2_SHIFT;
+ /* 24 bits DPI: connect MID Ch B to D[24:31] */
+ val |= 4 << MCDE_CONF0_OUTMUX3_SHIFT;
+ /* 5: 24 bits DPI: connect MSB Ch B to D[32:39] */
+ val |= 5 << MCDE_CONF0_OUTMUX4_SHIFT;
+ /* Syncmux bits zero: DPI channel A and B on output pins A and B resp */
+ writel(val, mcde->regs + MCDE_CONF0);
+
+ /* Enable automatic clock gating */
+ val = readl(mcde->regs + MCDE_CR);
+ val |= MCDE_CR_MCDEEN | MCDE_CR_AUTOCLKG_EN;
+ writel(val, mcde->regs + MCDE_CR);
+
+ /* Clear any pending interrupts */
+ mcde_display_disable_irqs(mcde);
+ writel(0, mcde->regs + MCDE_IMSCERR);
+ writel(0xFFFFFFFF, mcde->regs + MCDE_RISERR);
+
+ /* Spawn child devices for the DSI ports */
+ devm_of_platform_populate(dev);
+
+ /* Create something that will match the subdrivers when we bind */
+ for (i = 0; i < ARRAY_SIZE(mcde_component_drivers); i++) {
+ struct device_driver *drv = &mcde_component_drivers[i]->driver;
+ struct device *p = NULL, *d;
+
+ while ((d = bus_find_device(&platform_bus_type, p, drv,
+ (void *)platform_bus_type.match))) {
+ put_device(p);
+ component_match_add(dev, &match, mcde_compare_dev, d);
+ p = d;
+ }
+ put_device(p);
+ }
+ if (IS_ERR(match)) {
+ dev_err(dev, "could not create component match\n");
+ ret = PTR_ERR(match);
+ goto clk_disable;
+ }
+ ret = component_master_add_with_match(&pdev->dev, &mcde_drm_comp_ops,
+ match);
+ if (ret) {
+ dev_err(dev, "failed to add component master\n");
+ goto clk_disable;
+ }
+ return 0;
+
+clk_disable:
+ clk_disable_unprepare(mcde->mcde_clk);
+regulator_off:
+ regulator_disable(mcde->vana);
+regulator_epod_off:
+ regulator_disable(mcde->epod);
+dev_unref:
+ drm_dev_put(drm);
+ return ret;
+
+}
+
+static int mcde_remove(struct platform_device *pdev)
+{
+ struct drm_device *drm = platform_get_drvdata(pdev);
+ struct mcde *mcde = drm->dev_private;
+
+ component_master_del(&pdev->dev, &mcde_drm_comp_ops);
+ clk_disable_unprepare(mcde->mcde_clk);
+ regulator_disable(mcde->vana);
+ regulator_disable(mcde->epod);
+ drm_dev_put(drm);
+
+ return 0;
+}
+
+static const struct of_device_id mcde_of_match[] = {
+ {
+ .compatible = "ste,mcde",
+ },
+ {},
+};
+
+static struct platform_driver mcde_driver = {
+ .driver = {
+ .name = "mcde",
+ .of_match_table = of_match_ptr(mcde_of_match),
+ },
+ .probe = mcde_probe,
+ .remove = mcde_remove,
+};
+
+static struct platform_driver *const component_drivers[] = {
+ &mcde_dsi_driver,
+};
+
+static int __init mcde_drm_register(void)
+{
+ int ret;
+
+ ret = platform_register_drivers(component_drivers,
+ ARRAY_SIZE(component_drivers));
+ if (ret)
+ return ret;
+
+ return platform_driver_register(&mcde_driver);
+}
+
+static void __exit mcde_drm_unregister(void)
+{
+ platform_unregister_drivers(component_drivers,
+ ARRAY_SIZE(component_drivers));
+ platform_driver_unregister(&mcde_driver);
+}
+
+module_init(mcde_drm_register);
+module_exit(mcde_drm_unregister);
+
+MODULE_ALIAS("platform:mcde-drm");
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/mcde/mcde_dsi.c b/drivers/gpu/drm/mcde/mcde_dsi.c
new file mode 100644
index 000000000000..07f7090d08b3
--- /dev/null
+++ b/drivers/gpu/drm/mcde/mcde_dsi.c
@@ -0,0 +1,1044 @@
+// SPDX-License-Identifier: GPL-2.0+
+#include <linux/clk.h>
+#include <linux/component.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
+#include <video/mipi_display.h>
+
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_bridge.h>
+#include <drm/drm_device.h>
+#include <drm/drm_drv.h>
+#include <drm/drm_encoder.h>
+#include <drm/drm_mipi_dsi.h>
+#include <drm/drm_modeset_helper_vtables.h>
+#include <drm/drm_of.h>
+#include <drm/drm_panel.h>
+#include <drm/drm_print.h>
+#include <drm/drm_probe_helper.h>
+
+#include "mcde_drm.h"
+#include "mcde_dsi_regs.h"
+
+#define DSI_DEFAULT_LP_FREQ_HZ 19200000
+#define DSI_DEFAULT_HS_FREQ_HZ 420160000
+
+/* PRCMU DSI reset registers */
+#define PRCM_DSI_SW_RESET 0x324
+#define PRCM_DSI_SW_RESET_DSI0_SW_RESETN BIT(0)
+#define PRCM_DSI_SW_RESET_DSI1_SW_RESETN BIT(1)
+#define PRCM_DSI_SW_RESET_DSI2_SW_RESETN BIT(2)
+
+struct mcde_dsi {
+ struct device *dev;
+ struct mcde *mcde;
+ struct drm_bridge bridge;
+ struct drm_connector connector;
+ struct drm_panel *panel;
+ struct drm_bridge *bridge_out;
+ struct mipi_dsi_host dsi_host;
+ struct mipi_dsi_device *mdsi;
+ struct clk *hs_clk;
+ struct clk *lp_clk;
+ unsigned long hs_freq;
+ unsigned long lp_freq;
+ bool unused;
+
+ void __iomem *regs;
+ struct regmap *prcmu;
+};
+
+static inline struct mcde_dsi *bridge_to_mcde_dsi(struct drm_bridge *bridge)
+{
+ return container_of(bridge, struct mcde_dsi, bridge);
+}
+
+static inline struct mcde_dsi *host_to_mcde_dsi(struct mipi_dsi_host *h)
+{
+ return container_of(h, struct mcde_dsi, dsi_host);
+}
+
+static inline struct mcde_dsi *connector_to_mcde_dsi(struct drm_connector *c)
+{
+ return container_of(c, struct mcde_dsi, connector);
+}
+
+bool mcde_dsi_irq(struct mipi_dsi_device *mdsi)
+{
+ struct mcde_dsi *d;
+ u32 val;
+ bool te_received = false;
+
+ d = host_to_mcde_dsi(mdsi->host);
+
+ dev_dbg(d->dev, "%s called\n", __func__);
+
+ val = readl(d->regs + DSI_DIRECT_CMD_STS_FLAG);
+ if (val)
+ dev_dbg(d->dev, "DSI_DIRECT_CMD_STS_FLAG = %08x\n", val);
+ if (val & DSI_DIRECT_CMD_STS_WRITE_COMPLETED)
+ dev_dbg(d->dev, "direct command write completed\n");
+ if (val & DSI_DIRECT_CMD_STS_TE_RECEIVED) {
+ te_received = true;
+ dev_dbg(d->dev, "direct command TE received\n");
+ }
+ if (val & DSI_DIRECT_CMD_STS_ACKNOWLEDGE_WITH_ERR_RECEIVED)
+ dev_err(d->dev, "direct command ACK ERR received\n");
+ if (val & DSI_DIRECT_CMD_STS_READ_COMPLETED_WITH_ERR)
+ dev_err(d->dev, "direct command read ERR received\n");
+ /* Mask off the ACK value and clear status */
+ writel(val, d->regs + DSI_DIRECT_CMD_STS_CLR);
+
+ val = readl(d->regs + DSI_CMD_MODE_STS_FLAG);
+ if (val)
+ dev_dbg(d->dev, "DSI_CMD_MODE_STS_FLAG = %08x\n", val);
+ if (val & DSI_CMD_MODE_STS_ERR_NO_TE)
+ /* This happens all the time (safe to ignore) */
+ dev_dbg(d->dev, "CMD mode no TE\n");
+ if (val & DSI_CMD_MODE_STS_ERR_TE_MISS)
+ /* This happens all the time (safe to ignore) */
+ dev_dbg(d->dev, "CMD mode TE miss\n");
+ if (val & DSI_CMD_MODE_STS_ERR_SDI1_UNDERRUN)
+ dev_err(d->dev, "CMD mode SD1 underrun\n");
+ if (val & DSI_CMD_MODE_STS_ERR_SDI2_UNDERRUN)
+ dev_err(d->dev, "CMD mode SD2 underrun\n");
+ if (val & DSI_CMD_MODE_STS_ERR_UNWANTED_RD)
+ dev_err(d->dev, "CMD mode unwanted RD\n");
+ writel(val, d->regs + DSI_CMD_MODE_STS_CLR);
+
+ val = readl(d->regs + DSI_DIRECT_CMD_RD_STS_FLAG);
+ if (val)
+ dev_dbg(d->dev, "DSI_DIRECT_CMD_RD_STS_FLAG = %08x\n", val);
+ writel(val, d->regs + DSI_DIRECT_CMD_RD_STS_CLR);
+
+ val = readl(d->regs + DSI_TG_STS_FLAG);
+ if (val)
+ dev_dbg(d->dev, "DSI_TG_STS_FLAG = %08x\n", val);
+ writel(val, d->regs + DSI_TG_STS_CLR);
+
+ val = readl(d->regs + DSI_VID_MODE_STS_FLAG);
+ if (val)
+ dev_err(d->dev, "some video mode error status\n");
+ writel(val, d->regs + DSI_VID_MODE_STS_CLR);
+
+ return te_received;
+}
+
+static int mcde_dsi_host_attach(struct mipi_dsi_host *host,
+ struct mipi_dsi_device *mdsi)
+{
+ struct mcde_dsi *d = host_to_mcde_dsi(host);
+
+ if (mdsi->lanes < 1 || mdsi->lanes > 2) {
+ DRM_ERROR("dsi device params invalid, 1 or 2 lanes supported\n");
+ return -EINVAL;
+ }
+
+ dev_info(d->dev, "attached DSI device with %d lanes\n", mdsi->lanes);
+ /* MIPI_DSI_FMT_RGB88 etc */
+ dev_info(d->dev, "format %08x, %dbpp\n", mdsi->format,
+ mipi_dsi_pixel_format_to_bpp(mdsi->format));
+ dev_info(d->dev, "mode flags: %08lx\n", mdsi->mode_flags);
+
+ d->mdsi = mdsi;
+ if (d->mcde)
+ d->mcde->mdsi = mdsi;
+
+ return 0;
+}
+
+static int mcde_dsi_host_detach(struct mipi_dsi_host *host,
+ struct mipi_dsi_device *mdsi)
+{
+ struct mcde_dsi *d = host_to_mcde_dsi(host);
+
+ d->mdsi = NULL;
+ if (d->mcde)
+ d->mcde->mdsi = NULL;
+
+ return 0;
+}
+
+#define MCDE_DSI_HOST_IS_READ(type) \
+ ((type == MIPI_DSI_GENERIC_READ_REQUEST_0_PARAM) || \
+ (type == MIPI_DSI_GENERIC_READ_REQUEST_1_PARAM) || \
+ (type == MIPI_DSI_GENERIC_READ_REQUEST_2_PARAM) || \
+ (type == MIPI_DSI_DCS_READ))
+
+static ssize_t mcde_dsi_host_transfer(struct mipi_dsi_host *host,
+ const struct mipi_dsi_msg *msg)
+{
+ struct mcde_dsi *d = host_to_mcde_dsi(host);
+ const u32 loop_delay_us = 10; /* us */
+ const u8 *tx = msg->tx_buf;
+ u32 loop_counter;
+ size_t txlen;
+ u32 val;
+ int ret;
+ int i;
+
+ txlen = msg->tx_len;
+ if (txlen > 12) {
+ dev_err(d->dev,
+ "dunno how to write more than 12 bytes yet\n");
+ return -EIO;
+ }
+
+ dev_dbg(d->dev,
+ "message to channel %d, %zd bytes",
+ msg->channel,
+ txlen);
+
+ /* Command "nature" */
+ if (MCDE_DSI_HOST_IS_READ(msg->type))
+ /* MCTL_MAIN_DATA_CTL already set up */
+ val = DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_NAT_READ;
+ else
+ val = DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_NAT_WRITE;
+ /*
+ * More than 2 bytes will not fit in a single packet, so it's
+ * time to set the "long not short" bit. One byte is used by
+ * the MIPI DCS command leaving just one byte for the payload
+ * in a short package.
+ */
+ if (mipi_dsi_packet_format_is_long(msg->type))
+ val |= DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_LONGNOTSHORT;
+ val |= 0 << DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_ID_SHIFT;
+ /* Add one to the length for the MIPI DCS command */
+ val |= txlen
+ << DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_SIZE_SHIFT;
+ val |= DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_LP_EN;
+ val |= msg->type << DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_HEAD_SHIFT;
+ writel(val, d->regs + DSI_DIRECT_CMD_MAIN_SETTINGS);
+
+ /* MIPI DCS command is part of the data */
+ if (txlen > 0) {
+ val = 0;
+ for (i = 0; i < 4 && i < txlen; i++)
+ val |= tx[i] << (i & 3) * 8;
+ }
+ writel(val, d->regs + DSI_DIRECT_CMD_WRDAT0);
+ if (txlen > 4) {
+ val = 0;
+ for (i = 0; i < 4 && (i + 4) < txlen; i++)
+ val |= tx[i + 4] << (i & 3) * 8;
+ writel(val, d->regs + DSI_DIRECT_CMD_WRDAT1);
+ }
+ if (txlen > 8) {
+ val = 0;
+ for (i = 0; i < 4 && (i + 8) < txlen; i++)
+ val |= tx[i + 8] << (i & 3) * 8;
+ writel(val, d->regs + DSI_DIRECT_CMD_WRDAT2);
+ }
+ if (txlen > 12) {
+ val = 0;
+ for (i = 0; i < 4 && (i + 12) < txlen; i++)
+ val |= tx[i + 12] << (i & 3) * 8;
+ writel(val, d->regs + DSI_DIRECT_CMD_WRDAT3);
+ }
+
+ writel(~0, d->regs + DSI_DIRECT_CMD_STS_CLR);
+ writel(~0, d->regs + DSI_CMD_MODE_STS_CLR);
+ /* Send command */
+ writel(1, d->regs + DSI_DIRECT_CMD_SEND);
+
+ loop_counter = 1000 * 1000 / loop_delay_us;
+ while (!(readl(d->regs + DSI_DIRECT_CMD_STS) &
+ DSI_DIRECT_CMD_STS_WRITE_COMPLETED)
+ && --loop_counter)
+ usleep_range(loop_delay_us, (loop_delay_us * 3) / 2);
+
+ if (!loop_counter) {
+ dev_err(d->dev, "DSI write timeout!\n");
+ return -ETIME;
+ }
+
+ val = readl(d->regs + DSI_DIRECT_CMD_STS);
+ if (val & DSI_DIRECT_CMD_STS_ACKNOWLEDGE_WITH_ERR_RECEIVED) {
+ val >>= DSI_DIRECT_CMD_STS_ACK_VAL_SHIFT;
+ dev_err(d->dev, "error during transmission: %04x\n",
+ val);
+ return -EIO;
+ }
+
+ if (!MCDE_DSI_HOST_IS_READ(msg->type)) {
+ /* Return number of bytes written */
+ if (mipi_dsi_packet_format_is_long(msg->type))
+ ret = 4 + txlen;
+ else
+ ret = 4;
+ } else {
+ /* OK this is a read command, get the response */
+ u32 rdsz;
+ u32 rddat;
+ u8 *rx = msg->rx_buf;
+
+ rdsz = readl(d->regs + DSI_DIRECT_CMD_RD_PROPERTY);
+ rdsz &= DSI_DIRECT_CMD_RD_PROPERTY_RD_SIZE_MASK;
+ rddat = readl(d->regs + DSI_DIRECT_CMD_RDDAT);
+ for (i = 0; i < 4 && i < rdsz; i++)
+ rx[i] = (rddat >> (i * 8)) & 0xff;
+ ret = rdsz;
+ }
+
+ writel(~0, d->regs + DSI_DIRECT_CMD_STS_CLR);
+ writel(~0, d->regs + DSI_CMD_MODE_STS_CLR);
+
+ return ret;
+}
+
+static const struct mipi_dsi_host_ops mcde_dsi_host_ops = {
+ .attach = mcde_dsi_host_attach,
+ .detach = mcde_dsi_host_detach,
+ .transfer = mcde_dsi_host_transfer,
+};
+
+/* This sends a direct (short) command to request TE */
+void mcde_dsi_te_request(struct mipi_dsi_device *mdsi)
+{
+ struct mcde_dsi *d;
+ u32 val;
+
+ d = host_to_mcde_dsi(mdsi->host);
+
+ /* Command "nature" TE request */
+ val = DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_NAT_TE_REQ;
+ val |= 0 << DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_ID_SHIFT;
+ val |= 2 << DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_SIZE_SHIFT;
+ val |= DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_LP_EN;
+ val |= DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_HEAD_DCS_SHORT_WRITE_1 <<
+ DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_HEAD_SHIFT;
+ writel(val, d->regs + DSI_DIRECT_CMD_MAIN_SETTINGS);
+
+ /* Clear TE reveived and error status bits and enables them */
+ writel(DSI_DIRECT_CMD_STS_CLR_TE_RECEIVED_CLR |
+ DSI_DIRECT_CMD_STS_CLR_ACKNOWLEDGE_WITH_ERR_RECEIVED_CLR,
+ d->regs + DSI_DIRECT_CMD_STS_CLR);
+ val = readl(d->regs + DSI_DIRECT_CMD_STS_CTL);
+ val |= DSI_DIRECT_CMD_STS_CTL_TE_RECEIVED_EN;
+ val |= DSI_DIRECT_CMD_STS_CTL_ACKNOWLEDGE_WITH_ERR_EN;
+ writel(val, d->regs + DSI_DIRECT_CMD_STS_CTL);
+
+ /* Clear and enable no TE or TE missing status */
+ writel(DSI_CMD_MODE_STS_CLR_ERR_NO_TE_CLR |
+ DSI_CMD_MODE_STS_CLR_ERR_TE_MISS_CLR,
+ d->regs + DSI_CMD_MODE_STS_CLR);
+ val = readl(d->regs + DSI_CMD_MODE_STS_CTL);
+ val |= DSI_CMD_MODE_STS_CTL_ERR_NO_TE_EN;
+ val |= DSI_CMD_MODE_STS_CTL_ERR_TE_MISS_EN;
+ writel(val, d->regs + DSI_CMD_MODE_STS_CTL);
+
+ /* Send this TE request command */
+ writel(1, d->regs + DSI_DIRECT_CMD_SEND);
+}
+
+static void mcde_dsi_setup_video_mode(struct mcde_dsi *d,
+ const struct drm_display_mode *mode)
+{
+ u8 bpp = mipi_dsi_pixel_format_to_bpp(d->mdsi->format);
+ u64 bpl;
+ u32 hfp;
+ u32 hbp;
+ u32 hsa;
+ u32 blkline_pck, line_duration;
+ u32 blkeol_pck, blkeol_duration;
+ u32 val;
+
+ val = 0;
+ if (d->mdsi->mode_flags & MIPI_DSI_MODE_VIDEO_BURST)
+ val |= DSI_VID_MAIN_CTL_BURST_MODE;
+ if (d->mdsi->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE) {
+ val |= DSI_VID_MAIN_CTL_SYNC_PULSE_ACTIVE;
+ val |= DSI_VID_MAIN_CTL_SYNC_PULSE_HORIZONTAL;
+ }
+ /* RGB header and pixel mode */
+ switch (d->mdsi->format) {
+ case MIPI_DSI_FMT_RGB565:
+ val |= MIPI_DSI_PACKED_PIXEL_STREAM_16 <<
+ DSI_VID_MAIN_CTL_HEADER_SHIFT;
+ val |= DSI_VID_MAIN_CTL_VID_PIXEL_MODE_16BITS;
+ break;
+ case MIPI_DSI_FMT_RGB666_PACKED:
+ val |= MIPI_DSI_PACKED_PIXEL_STREAM_18 <<
+ DSI_VID_MAIN_CTL_HEADER_SHIFT;
+ val |= DSI_VID_MAIN_CTL_VID_PIXEL_MODE_18BITS;
+ break;
+ case MIPI_DSI_FMT_RGB666:
+ val |= MIPI_DSI_PIXEL_STREAM_3BYTE_18
+ << DSI_VID_MAIN_CTL_HEADER_SHIFT;
+ val |= DSI_VID_MAIN_CTL_VID_PIXEL_MODE_18BITS_LOOSE;
+ break;
+ case MIPI_DSI_FMT_RGB888:
+ val |= MIPI_DSI_PACKED_PIXEL_STREAM_24 <<
+ DSI_VID_MAIN_CTL_HEADER_SHIFT;
+ val |= DSI_VID_MAIN_CTL_VID_PIXEL_MODE_24BITS;
+ break;
+ default:
+ dev_err(d->dev, "unknown pixel mode\n");
+ return;
+ }
+
+ /* TODO: TVG could be enabled here */
+
+ /* Send blanking packet */
+ val |= DSI_VID_MAIN_CTL_REG_BLKLINE_MODE_LP_0;
+ /* Send EOL packet */
+ val |= DSI_VID_MAIN_CTL_REG_BLKEOL_MODE_LP_0;
+ /* Recovery mode 1 */
+ val |= 1 << DSI_VID_MAIN_CTL_RECOVERY_MODE_SHIFT;
+ /* All other fields zero */
+ writel(val, d->regs + DSI_VID_MAIN_CTL);
+
+ /* Vertical frame parameters are pretty straight-forward */
+ val = mode->vdisplay << DSI_VID_VSIZE_VSA_LENGTH_SHIFT;
+ /* vertical front porch */
+ val |= (mode->vsync_start - mode->vdisplay)
+ << DSI_VID_VSIZE_VFP_LENGTH_SHIFT;
+ /* vertical sync active */
+ val |= (mode->vsync_end - mode->vsync_start)
+ << DSI_VID_VSIZE_VACT_LENGTH_SHIFT;
+ /* vertical back porch */
+ val |= (mode->vtotal - mode->vsync_end)
+ << DSI_VID_VSIZE_VBP_LENGTH_SHIFT;
+ writel(val, d->regs + DSI_VID_VSIZE);
+
+ /*
+ * Horizontal frame parameters:
+ * horizontal resolution is given in pixels and must be re-calculated
+ * into bytes since this is what the hardware expects.
+ *
+ * 6 + 2 is HFP header + checksum
+ */
+ hfp = (mode->hsync_start - mode->hdisplay) * bpp - 6 - 2;
+ if (d->mdsi->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE) {
+ /*
+ * 6 is HBP header + checksum
+ * 4 is RGB header + checksum
+ */
+ hbp = (mode->htotal - mode->hsync_end) * bpp - 4 - 6;
+ /*
+ * 6 is HBP header + checksum
+ * 4 is HSW packet bytes
+ * 4 is RGB header + checksum
+ */
+ hsa = (mode->hsync_end - mode->hsync_start) * bpp - 4 - 4 - 6;
+ } else {
+ /*
+ * HBP includes both back porch and sync
+ * 6 is HBP header + checksum
+ * 4 is HSW packet bytes
+ * 4 is RGB header + checksum
+ */
+ hbp = (mode->htotal - mode->hsync_start) * bpp - 4 - 4 - 6;
+ /* HSA is not considered in this mode and set to 0 */
+ hsa = 0;
+ }
+ dev_dbg(d->dev, "hfp: %u, hbp: %u, hsa: %u\n",
+ hfp, hbp, hsa);
+
+ /* Frame parameters: horizontal sync active */
+ val = hsa << DSI_VID_HSIZE1_HSA_LENGTH_SHIFT;
+ /* horizontal back porch */
+ val |= hbp << DSI_VID_HSIZE1_HBP_LENGTH_SHIFT;
+ /* horizontal front porch */
+ val |= hfp << DSI_VID_HSIZE1_HFP_LENGTH_SHIFT;
+ writel(val, d->regs + DSI_VID_HSIZE1);
+
+ /* RGB data length (bytes on one scanline) */
+ val = mode->hdisplay * (bpp / 8);
+ writel(val, d->regs + DSI_VID_HSIZE2);
+
+ /* TODO: further adjustments for TVG mode here */
+
+ /*
+ * EOL packet length from bits per line calculations: pixel clock
+ * is given in kHz, calculate the time between two pixels in
+ * picoseconds.
+ */
+ bpl = mode->clock * mode->htotal;
+ bpl *= (d->hs_freq / 8);
+ do_div(bpl, 1000000); /* microseconds */
+ do_div(bpl, 1000000); /* seconds */
+ bpl *= d->mdsi->lanes;
+ dev_dbg(d->dev, "calculated bytes per line: %llu\n", bpl);
+ /*
+ * 6 is header + checksum, header = 4 bytes, checksum = 2 bytes
+ * 4 is short packet for vsync/hsync
+ */
+ if (d->mdsi->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE) {
+ /* Fixme: isn't the hsync width in pixels? */
+ blkline_pck = bpl - (mode->hsync_end - mode->hsync_start) - 6;
+ val = blkline_pck << DSI_VID_BLKSIZE2_BLKLINE_PULSE_PCK_SHIFT;
+ writel(val, d->regs + DSI_VID_BLKSIZE2);
+ } else {
+ blkline_pck = bpl - 4 - 6;
+ val = blkline_pck << DSI_VID_BLKSIZE1_BLKLINE_EVENT_PCK_SHIFT;
+ writel(val, d->regs + DSI_VID_BLKSIZE1);
+ }
+
+ line_duration = (blkline_pck + 6) / d->mdsi->lanes;
+ dev_dbg(d->dev, "line duration %u\n", line_duration);
+ val = line_duration << DSI_VID_DPHY_TIME_REG_LINE_DURATION_SHIFT;
+ /*
+ * This is the time to perform LP->HS on D-PHY
+ * FIXME: nowhere to get this from: DT property on the DSI?
+ */
+ val |= 0 << DSI_VID_DPHY_TIME_REG_WAKEUP_TIME_SHIFT;
+ writel(val, d->regs + DSI_VID_DPHY_TIME);
+
+ /* Calculate block end of line */
+ blkeol_pck = bpl - mode->hdisplay * bpp - 6;
+ blkeol_duration = (blkeol_pck + 6) / d->mdsi->lanes;
+ dev_dbg(d->dev, "blkeol pck: %u, duration: %u\n",
+ blkeol_pck, blkeol_duration);
+
+ if (d->mdsi->mode_flags & MIPI_DSI_MODE_VIDEO_BURST) {
+ /* Set up EOL clock for burst mode */
+ val = readl(d->regs + DSI_VID_BLKSIZE1);
+ val |= blkeol_pck << DSI_VID_BLKSIZE1_BLKEOL_PCK_SHIFT;
+ writel(val, d->regs + DSI_VID_BLKSIZE1);
+ writel(blkeol_pck, d->regs + DSI_VID_VCA_SETTING2);
+
+ writel(blkeol_duration, d->regs + DSI_VID_PCK_TIME);
+ writel(blkeol_duration - 6, d->regs + DSI_VID_VCA_SETTING1);
+ }
+
+ /* Maximum line limit */
+ val = readl(d->regs + DSI_VID_VCA_SETTING2);
+ val |= blkline_pck <<
+ DSI_VID_VCA_SETTING2_EXACT_BURST_LIMIT_SHIFT;
+ writel(val, d->regs + DSI_VID_VCA_SETTING2);
+
+ /* Put IF1 into video mode */
+ val = readl(d->regs + DSI_MCTL_MAIN_DATA_CTL);
+ val |= DSI_MCTL_MAIN_DATA_CTL_IF1_MODE;
+ writel(val, d->regs + DSI_MCTL_MAIN_DATA_CTL);
+
+ /* Disable command mode on IF1 */
+ val = readl(d->regs + DSI_CMD_MODE_CTL);
+ val &= ~DSI_CMD_MODE_CTL_IF1_LP_EN;
+ writel(val, d->regs + DSI_CMD_MODE_CTL);
+
+ /* Enable some error interrupts */
+ val = readl(d->regs + DSI_VID_MODE_STS_CTL);
+ val |= DSI_VID_MODE_STS_CTL_ERR_MISSING_VSYNC;
+ val |= DSI_VID_MODE_STS_CTL_ERR_MISSING_DATA;
+ writel(val, d->regs + DSI_VID_MODE_STS_CTL);
+
+ /* Enable video mode */
+ val = readl(d->regs + DSI_MCTL_MAIN_DATA_CTL);
+ val |= DSI_MCTL_MAIN_DATA_CTL_VID_EN;
+ writel(val, d->regs + DSI_MCTL_MAIN_DATA_CTL);
+}
+
+static void mcde_dsi_start(struct mcde_dsi *d)
+{
+ unsigned long hs_freq;
+ u32 val;
+ int i;
+
+ /* No integration mode */
+ writel(0, d->regs + DSI_MCTL_INTEGRATION_MODE);
+
+ /* Enable the DSI port, from drivers/video/mcde/dsilink_v2.c */
+ val = DSI_MCTL_MAIN_DATA_CTL_LINK_EN |
+ DSI_MCTL_MAIN_DATA_CTL_BTA_EN |
+ DSI_MCTL_MAIN_DATA_CTL_READ_EN |
+ DSI_MCTL_MAIN_DATA_CTL_REG_TE_EN;
+ if (d->mdsi->mode_flags & MIPI_DSI_MODE_EOT_PACKET)
+ val |= DSI_MCTL_MAIN_DATA_CTL_HOST_EOT_GEN;
+ writel(val, d->regs + DSI_MCTL_MAIN_DATA_CTL);
+
+ /* Set a high command timeout, clear other fields */
+ val = 0x3ff << DSI_CMD_MODE_CTL_TE_TIMEOUT_SHIFT;
+ writel(val, d->regs + DSI_CMD_MODE_CTL);
+
+ /*
+ * UI_X4 is described as "unit interval times four"
+ * I guess since DSI packets are 4 bytes wide, one unit
+ * is one byte.
+ */
+ hs_freq = clk_get_rate(d->hs_clk);
+ hs_freq /= 1000000; /* MHz */
+ val = 4000 / hs_freq;
+ dev_dbg(d->dev, "UI value: %d\n", val);
+ val <<= DSI_MCTL_DPHY_STATIC_UI_X4_SHIFT;
+ val &= DSI_MCTL_DPHY_STATIC_UI_X4_MASK;
+ writel(val, d->regs + DSI_MCTL_DPHY_STATIC);
+
+ /*
+ * Enable clocking: 0x0f (something?) between each burst,
+ * enable the second lane if needed, enable continuous clock if
+ * needed, enable switch into ULPM (ultra-low power mode) on
+ * all the lines.
+ */
+ val = 0x0f << DSI_MCTL_MAIN_PHY_CTL_WAIT_BURST_TIME_SHIFT;
+ if (d->mdsi->lanes == 2)
+ val |= DSI_MCTL_MAIN_PHY_CTL_LANE2_EN;
+ if (!(d->mdsi->mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS))
+ val |= DSI_MCTL_MAIN_PHY_CTL_CLK_CONTINUOUS;
+ val |= DSI_MCTL_MAIN_PHY_CTL_CLK_ULPM_EN |
+ DSI_MCTL_MAIN_PHY_CTL_DAT1_ULPM_EN |
+ DSI_MCTL_MAIN_PHY_CTL_DAT2_ULPM_EN;
+ writel(val, d->regs + DSI_MCTL_MAIN_PHY_CTL);
+
+ val = (1 << DSI_MCTL_ULPOUT_TIME_CKLANE_ULPOUT_TIME_SHIFT) |
+ (1 << DSI_MCTL_ULPOUT_TIME_DATA_ULPOUT_TIME_SHIFT);
+ writel(val, d->regs + DSI_MCTL_ULPOUT_TIME);
+
+ writel(DSI_DPHY_LANES_TRIM_DPHY_SPECS_90_81B_0_90,
+ d->regs + DSI_DPHY_LANES_TRIM);
+
+ /* High PHY timeout */
+ val = (0x0f << DSI_MCTL_DPHY_TIMEOUT_CLK_DIV_SHIFT) |
+ (0x3fff << DSI_MCTL_DPHY_TIMEOUT_HSTX_TO_VAL_SHIFT) |
+ (0x3fff << DSI_MCTL_DPHY_TIMEOUT_LPRX_TO_VAL_SHIFT);
+ writel(val, d->regs + DSI_MCTL_DPHY_TIMEOUT);
+
+ val = DSI_MCTL_MAIN_EN_PLL_START |
+ DSI_MCTL_MAIN_EN_CKLANE_EN |
+ DSI_MCTL_MAIN_EN_DAT1_EN |
+ DSI_MCTL_MAIN_EN_IF1_EN;
+ if (d->mdsi->lanes == 2)
+ val |= DSI_MCTL_MAIN_EN_DAT2_EN;
+ writel(val, d->regs + DSI_MCTL_MAIN_EN);
+
+ /* Wait for the PLL to lock and the clock and data lines to come up */
+ i = 0;
+ val = DSI_MCTL_MAIN_STS_PLL_LOCK |
+ DSI_MCTL_MAIN_STS_CLKLANE_READY |
+ DSI_MCTL_MAIN_STS_DAT1_READY;
+ if (d->mdsi->lanes == 2)
+ val |= DSI_MCTL_MAIN_STS_DAT2_READY;
+ while ((readl(d->regs + DSI_MCTL_MAIN_STS) & val) != val) {
+ /* Sleep for a millisecond */
+ usleep_range(1000, 1500);
+ if (i++ == 100) {
+ dev_warn(d->dev, "DSI lanes did not start up\n");
+ return;
+ }
+ }
+
+ /* TODO needed? */
+
+ /* Command mode, clear IF1 ID */
+ val = readl(d->regs + DSI_CMD_MODE_CTL);
+ /*
+ * If we enable low-power mode here, with
+ * val |= DSI_CMD_MODE_CTL_IF1_LP_EN
+ * then display updates become really slow.
+ */
+ val &= ~DSI_CMD_MODE_CTL_IF1_ID_MASK;
+ writel(val, d->regs + DSI_CMD_MODE_CTL);
+
+ /* Wait for DSI PHY to initialize */
+ usleep_range(100, 200);
+ dev_info(d->dev, "DSI link enabled\n");
+}
+
+
+static void mcde_dsi_bridge_enable(struct drm_bridge *bridge)
+{
+ struct mcde_dsi *d = bridge_to_mcde_dsi(bridge);
+
+ dev_info(d->dev, "enable DSI master\n");
+};
+
+static void mcde_dsi_bridge_mode_set(struct drm_bridge *bridge,
+ const struct drm_display_mode *mode,
+ const struct drm_display_mode *adj)
+{
+ struct mcde_dsi *d = bridge_to_mcde_dsi(bridge);
+ unsigned long pixel_clock_hz = mode->clock * 1000;
+ unsigned long hs_freq, lp_freq;
+ u32 val;
+ int ret;
+
+ if (!d->mdsi) {
+ dev_err(d->dev, "no DSI device attached to encoder!\n");
+ return;
+ }
+
+ dev_info(d->dev, "set DSI master to %dx%d %lu Hz %s mode\n",
+ mode->hdisplay, mode->vdisplay, pixel_clock_hz,
+ (d->mdsi->mode_flags & MIPI_DSI_MODE_VIDEO) ? "VIDEO" : "CMD"
+ );
+
+ /* Copy maximum clock frequencies */
+ if (d->mdsi->lp_rate)
+ lp_freq = d->mdsi->lp_rate;
+ else
+ lp_freq = DSI_DEFAULT_LP_FREQ_HZ;
+ if (d->mdsi->hs_rate)
+ hs_freq = d->mdsi->hs_rate;
+ else
+ hs_freq = DSI_DEFAULT_HS_FREQ_HZ;
+
+ /* Enable LP (Low Power, Energy Save, ES) and HS (High Speed) clocks */
+ d->lp_freq = clk_round_rate(d->lp_clk, lp_freq);
+ ret = clk_set_rate(d->lp_clk, d->lp_freq);
+ if (ret)
+ dev_err(d->dev, "failed to set LP clock rate %lu Hz\n",
+ d->lp_freq);
+
+ d->hs_freq = clk_round_rate(d->hs_clk, hs_freq);
+ ret = clk_set_rate(d->hs_clk, d->hs_freq);
+ if (ret)
+ dev_err(d->dev, "failed to set HS clock rate %lu Hz\n",
+ d->hs_freq);
+
+ /* Start clocks */
+ ret = clk_prepare_enable(d->lp_clk);
+ if (ret)
+ dev_err(d->dev, "failed to enable LP clock\n");
+ else
+ dev_info(d->dev, "DSI LP clock rate %lu Hz\n",
+ d->lp_freq);
+ ret = clk_prepare_enable(d->hs_clk);
+ if (ret)
+ dev_err(d->dev, "failed to enable HS clock\n");
+ else
+ dev_info(d->dev, "DSI HS clock rate %lu Hz\n",
+ d->hs_freq);
+
+ if (d->mdsi->mode_flags & MIPI_DSI_MODE_VIDEO) {
+ mcde_dsi_setup_video_mode(d, mode);
+ } else {
+ /* Command mode, clear IF1 ID */
+ val = readl(d->regs + DSI_CMD_MODE_CTL);
+ /*
+ * If we enable low-power mode here with
+ * val |= DSI_CMD_MODE_CTL_IF1_LP_EN
+ * the display updates become really slow.
+ */
+ val &= ~DSI_CMD_MODE_CTL_IF1_ID_MASK;
+ writel(val, d->regs + DSI_CMD_MODE_CTL);
+ }
+}
+
+static void mcde_dsi_wait_for_command_mode_stop(struct mcde_dsi *d)
+{
+ u32 val;
+ int i;
+
+ /*
+ * Wait until we get out of command mode
+ * CSM = Command State Machine
+ */
+ i = 0;
+ val = DSI_CMD_MODE_STS_CSM_RUNNING;
+ while ((readl(d->regs + DSI_CMD_MODE_STS) & val) == val) {
+ /* Sleep for a millisecond */
+ usleep_range(1000, 2000);
+ if (i++ == 100) {
+ dev_warn(d->dev,
+ "could not get out of command mode\n");
+ return;
+ }
+ }
+}
+
+static void mcde_dsi_wait_for_video_mode_stop(struct mcde_dsi *d)
+{
+ u32 val;
+ int i;
+
+ /* Wait until we get out og video mode */
+ i = 0;
+ val = DSI_VID_MODE_STS_VSG_RUNNING;
+ while ((readl(d->regs + DSI_VID_MODE_STS) & val) == val) {
+ /* Sleep for a millisecond */
+ usleep_range(1000, 2000);
+ if (i++ == 100) {
+ dev_warn(d->dev,
+ "could not get out of video mode\n");
+ return;
+ }
+ }
+}
+
+static void mcde_dsi_bridge_disable(struct drm_bridge *bridge)
+{
+ struct mcde_dsi *d = bridge_to_mcde_dsi(bridge);
+ u32 val;
+
+ /* Disable all error interrupts */
+ writel(0, d->regs + DSI_VID_MODE_STS_CTL);
+
+ if (d->mdsi->mode_flags & MIPI_DSI_MODE_VIDEO) {
+ /* Stop video mode */
+ val = readl(d->regs + DSI_MCTL_MAIN_DATA_CTL);
+ val &= ~DSI_MCTL_MAIN_DATA_CTL_VID_EN;
+ writel(val, d->regs + DSI_MCTL_MAIN_DATA_CTL);
+ mcde_dsi_wait_for_video_mode_stop(d);
+ } else {
+ /* Stop command mode */
+ mcde_dsi_wait_for_command_mode_stop(d);
+ }
+
+ /* Stop clocks */
+ clk_disable_unprepare(d->hs_clk);
+ clk_disable_unprepare(d->lp_clk);
+}
+
+/*
+ * This connector needs no special handling, just use the default
+ * helpers for everything. It's pretty dummy.
+ */
+static const struct drm_connector_funcs mcde_dsi_connector_funcs = {
+ .reset = drm_atomic_helper_connector_reset,
+ .fill_modes = drm_helper_probe_single_connector_modes,
+ .destroy = drm_connector_cleanup,
+ .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+ .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
+};
+
+static int mcde_dsi_get_modes(struct drm_connector *connector)
+{
+ struct mcde_dsi *d = connector_to_mcde_dsi(connector);
+
+ /* Just pass the question to the panel */
+ if (d->panel)
+ return drm_panel_get_modes(d->panel);
+
+ /* TODO: deal with bridges */
+
+ return 0;
+}
+
+static const struct drm_connector_helper_funcs
+mcde_dsi_connector_helper_funcs = {
+ .get_modes = mcde_dsi_get_modes,
+};
+
+static int mcde_dsi_bridge_attach(struct drm_bridge *bridge)
+{
+ struct mcde_dsi *d = bridge_to_mcde_dsi(bridge);
+ struct drm_device *drm = bridge->dev;
+ int ret;
+
+ drm_connector_helper_add(&d->connector,
+ &mcde_dsi_connector_helper_funcs);
+
+ if (!drm_core_check_feature(drm, DRIVER_ATOMIC)) {
+ dev_err(d->dev, "we need atomic updates\n");
+ return -ENOTSUPP;
+ }
+
+ ret = drm_connector_init(drm, &d->connector,
+ &mcde_dsi_connector_funcs,
+ DRM_MODE_CONNECTOR_DSI);
+ if (ret) {
+ dev_err(d->dev, "failed to initialize DSI bridge connector\n");
+ return ret;
+ }
+ d->connector.polled = DRM_CONNECTOR_POLL_CONNECT;
+ /* The encoder in the bridge attached to the DSI bridge */
+ drm_connector_attach_encoder(&d->connector, bridge->encoder);
+ /* Then we attach the DSI bridge to the output (panel etc) bridge */
+ ret = drm_bridge_attach(bridge->encoder, d->bridge_out, bridge);
+ if (ret) {
+ dev_err(d->dev, "failed to attach the DSI bridge\n");
+ return ret;
+ }
+ d->connector.status = connector_status_connected;
+
+ return 0;
+}
+
+static const struct drm_bridge_funcs mcde_dsi_bridge_funcs = {
+ .attach = mcde_dsi_bridge_attach,
+ .mode_set = mcde_dsi_bridge_mode_set,
+ .disable = mcde_dsi_bridge_disable,
+ .enable = mcde_dsi_bridge_enable,
+};
+
+static int mcde_dsi_bind(struct device *dev, struct device *master,
+ void *data)
+{
+ struct drm_device *drm = data;
+ struct mcde *mcde = drm->dev_private;
+ struct mcde_dsi *d = dev_get_drvdata(dev);
+ struct device_node *child;
+ struct drm_panel *panel = NULL;
+ struct drm_bridge *bridge = NULL;
+
+ if (!of_get_available_child_count(dev->of_node)) {
+ dev_info(dev, "unused DSI interface\n");
+ d->unused = true;
+ return 0;
+ }
+ d->mcde = mcde;
+ /* If the display attached before binding, set this up */
+ if (d->mdsi)
+ d->mcde->mdsi = d->mdsi;
+
+ /* Obtain the clocks */
+ d->hs_clk = devm_clk_get(dev, "hs");
+ if (IS_ERR(d->hs_clk)) {
+ dev_err(dev, "unable to get HS clock\n");
+ return PTR_ERR(d->hs_clk);
+ }
+
+ d->lp_clk = devm_clk_get(dev, "lp");
+ if (IS_ERR(d->lp_clk)) {
+ dev_err(dev, "unable to get LP clock\n");
+ return PTR_ERR(d->lp_clk);
+ }
+
+ /* Assert RESET through the PRCMU, active low */
+ /* FIXME: which DSI block? */
+ regmap_update_bits(d->prcmu, PRCM_DSI_SW_RESET,
+ PRCM_DSI_SW_RESET_DSI0_SW_RESETN, 0);
+
+ usleep_range(100, 200);
+
+ /* De-assert RESET again */
+ regmap_update_bits(d->prcmu, PRCM_DSI_SW_RESET,
+ PRCM_DSI_SW_RESET_DSI0_SW_RESETN,
+ PRCM_DSI_SW_RESET_DSI0_SW_RESETN);
+
+ /* Start up the hardware */
+ mcde_dsi_start(d);
+
+ /* Look for a panel as a child to this node */
+ for_each_available_child_of_node(dev->of_node, child) {
+ panel = of_drm_find_panel(child);
+ if (IS_ERR(panel)) {
+ dev_err(dev, "failed to find panel try bridge (%lu)\n",
+ PTR_ERR(panel));
+ bridge = of_drm_find_bridge(child);
+ if (IS_ERR(bridge)) {
+ dev_err(dev, "failed to find bridge (%lu)\n",
+ PTR_ERR(bridge));
+ return PTR_ERR(bridge);
+ }
+ }
+ }
+ if (panel) {
+ bridge = drm_panel_bridge_add(panel,
+ DRM_MODE_CONNECTOR_DSI);
+ if (IS_ERR(bridge)) {
+ dev_err(dev, "error adding panel bridge\n");
+ return PTR_ERR(bridge);
+ }
+ dev_info(dev, "connected to panel\n");
+ d->panel = panel;
+ } else if (bridge) {
+ /* TODO: AV8100 HDMI encoder goes here for example */
+ dev_info(dev, "connected to non-panel bridge (unsupported)\n");
+ return -ENODEV;
+ } else {
+ dev_err(dev, "no panel or bridge\n");
+ return -ENODEV;
+ }
+
+ d->bridge_out = bridge;
+
+ /* Create a bridge for this DSI channel */
+ d->bridge.funcs = &mcde_dsi_bridge_funcs;
+ d->bridge.of_node = dev->of_node;
+ drm_bridge_add(&d->bridge);
+
+ /* TODO: first come first serve, use a list */
+ mcde->bridge = &d->bridge;
+
+ dev_info(dev, "initialized MCDE DSI bridge\n");
+
+ return 0;
+}
+
+static void mcde_dsi_unbind(struct device *dev, struct device *master,
+ void *data)
+{
+ struct mcde_dsi *d = dev_get_drvdata(dev);
+
+ if (d->panel)
+ drm_panel_bridge_remove(d->bridge_out);
+ regmap_update_bits(d->prcmu, PRCM_DSI_SW_RESET,
+ PRCM_DSI_SW_RESET_DSI0_SW_RESETN, 0);
+}
+
+static const struct component_ops mcde_dsi_component_ops = {
+ .bind = mcde_dsi_bind,
+ .unbind = mcde_dsi_unbind,
+};
+
+static int mcde_dsi_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct mcde_dsi *d;
+ struct mipi_dsi_host *host;
+ struct resource *res;
+ u32 dsi_id;
+ int ret;
+
+ d = devm_kzalloc(dev, sizeof(*d), GFP_KERNEL);
+ if (!d)
+ return -ENOMEM;
+ d->dev = dev;
+ platform_set_drvdata(pdev, d);
+
+ /* Get a handle on the PRCMU so we can do reset */
+ d->prcmu =
+ syscon_regmap_lookup_by_compatible("stericsson,db8500-prcmu");
+ if (IS_ERR(d->prcmu)) {
+ dev_err(dev, "no PRCMU regmap\n");
+ return PTR_ERR(d->prcmu);
+ }
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ d->regs = devm_ioremap_resource(dev, res);
+ if (IS_ERR(d->regs)) {
+ dev_err(dev, "no DSI regs\n");
+ return PTR_ERR(d->regs);
+ }
+
+ dsi_id = readl(d->regs + DSI_ID_REG);
+ dev_info(dev, "HW revision 0x%08x\n", dsi_id);
+
+ host = &d->dsi_host;
+ host->dev = dev;
+ host->ops = &mcde_dsi_host_ops;
+ ret = mipi_dsi_host_register(host);
+ if (ret < 0) {
+ dev_err(dev, "failed to register DSI host: %d\n", ret);
+ return ret;
+ }
+ dev_info(dev, "registered DSI host\n");
+
+ platform_set_drvdata(pdev, d);
+ return component_add(dev, &mcde_dsi_component_ops);
+}
+
+static int mcde_dsi_remove(struct platform_device *pdev)
+{
+ struct mcde_dsi *d = platform_get_drvdata(pdev);
+
+ component_del(&pdev->dev, &mcde_dsi_component_ops);
+ mipi_dsi_host_unregister(&d->dsi_host);
+
+ return 0;
+}
+
+static const struct of_device_id mcde_dsi_of_match[] = {
+ {
+ .compatible = "ste,mcde-dsi",
+ },
+ {},
+};
+
+struct platform_driver mcde_dsi_driver = {
+ .driver = {
+ .name = "mcde-dsi",
+ .of_match_table = of_match_ptr(mcde_dsi_of_match),
+ },
+ .probe = mcde_dsi_probe,
+ .remove = mcde_dsi_remove,
+};
diff --git a/drivers/gpu/drm/mcde/mcde_dsi_regs.h b/drivers/gpu/drm/mcde/mcde_dsi_regs.h
new file mode 100644
index 000000000000..c9253321a3be
--- /dev/null
+++ b/drivers/gpu/drm/mcde/mcde_dsi_regs.h
@@ -0,0 +1,385 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __DRM_MCDE_DSI_REGS
+#define __DRM_MCDE_DSI_REGS
+
+#define DSI_MCTL_INTEGRATION_MODE 0x00000000
+
+#define DSI_MCTL_MAIN_DATA_CTL 0x00000004
+#define DSI_MCTL_MAIN_DATA_CTL_LINK_EN BIT(0)
+#define DSI_MCTL_MAIN_DATA_CTL_IF1_MODE BIT(1)
+#define DSI_MCTL_MAIN_DATA_CTL_VID_EN BIT(2)
+#define DSI_MCTL_MAIN_DATA_CTL_TVG_SEL BIT(3)
+#define DSI_MCTL_MAIN_DATA_CTL_TBG_SEL BIT(4)
+#define DSI_MCTL_MAIN_DATA_CTL_IF1_TE_EN BIT(5)
+#define DSI_MCTL_MAIN_DATA_CTL_IF2_TE_EN BIT(6)
+#define DSI_MCTL_MAIN_DATA_CTL_REG_TE_EN BIT(7)
+#define DSI_MCTL_MAIN_DATA_CTL_READ_EN BIT(8)
+#define DSI_MCTL_MAIN_DATA_CTL_BTA_EN BIT(9)
+#define DSI_MCTL_MAIN_DATA_CTL_DISP_GEN_ECC BIT(10)
+#define DSI_MCTL_MAIN_DATA_CTL_DISP_GEN_CHECKSUM BIT(11)
+#define DSI_MCTL_MAIN_DATA_CTL_HOST_EOT_GEN BIT(12)
+#define DSI_MCTL_MAIN_DATA_CTL_DISP_EOT_GEN BIT(13)
+#define DSI_MCTL_MAIN_DATA_CTL_DLX_REMAP_EN BIT(14)
+#define DSI_MCTL_MAIN_DATA_CTL_TE_POLLING_EN BIT(15)
+
+#define DSI_MCTL_MAIN_PHY_CTL 0x00000008
+#define DSI_MCTL_MAIN_PHY_CTL_LANE2_EN BIT(0)
+#define DSI_MCTL_MAIN_PHY_CTL_FORCE_STOP_MODE BIT(1)
+#define DSI_MCTL_MAIN_PHY_CTL_CLK_CONTINUOUS BIT(2)
+#define DSI_MCTL_MAIN_PHY_CTL_CLK_ULPM_EN BIT(3)
+#define DSI_MCTL_MAIN_PHY_CTL_DAT1_ULPM_EN BIT(4)
+#define DSI_MCTL_MAIN_PHY_CTL_DAT2_ULPM_EN BIT(5)
+#define DSI_MCTL_MAIN_PHY_CTL_WAIT_BURST_TIME_SHIFT 6
+#define DSI_MCTL_MAIN_PHY_CTL_WAIT_BURST_TIME_MASK 0x000003C0
+#define DSI_MCTL_MAIN_PHY_CTL_CLOCK_FORCE_STOP_MODE BIT(10)
+
+#define DSI_MCTL_PLL_CTL 0x0000000C
+#define DSI_MCTL_LANE_STS 0x00000010
+
+#define DSI_MCTL_DPHY_TIMEOUT 0x00000014
+#define DSI_MCTL_DPHY_TIMEOUT_CLK_DIV_SHIFT 0
+#define DSI_MCTL_DPHY_TIMEOUT_CLK_DIV_MASK 0x0000000F
+#define DSI_MCTL_DPHY_TIMEOUT_HSTX_TO_VAL_SHIFT 4
+#define DSI_MCTL_DPHY_TIMEOUT_HSTX_TO_VAL_MASK 0x0003FFF0
+#define DSI_MCTL_DPHY_TIMEOUT_LPRX_TO_VAL_SHIFT 18
+#define DSI_MCTL_DPHY_TIMEOUT_LPRX_TO_VAL_MASK 0xFFFC0000
+
+#define DSI_MCTL_ULPOUT_TIME 0x00000018
+#define DSI_MCTL_ULPOUT_TIME_CKLANE_ULPOUT_TIME_SHIFT 0
+#define DSI_MCTL_ULPOUT_TIME_CKLANE_ULPOUT_TIME_MASK 0x000001FF
+#define DSI_MCTL_ULPOUT_TIME_DATA_ULPOUT_TIME_SHIFT 9
+#define DSI_MCTL_ULPOUT_TIME_DATA_ULPOUT_TIME_MASK 0x0003FE00
+
+#define DSI_MCTL_DPHY_STATIC 0x0000001C
+#define DSI_MCTL_DPHY_STATIC_SWAP_PINS_CLK BIT(0)
+#define DSI_MCTL_DPHY_STATIC_HS_INVERT_CLK BIT(1)
+#define DSI_MCTL_DPHY_STATIC_SWAP_PINS_DAT1 BIT(2)
+#define DSI_MCTL_DPHY_STATIC_HS_INVERT_DAT1 BIT(3)
+#define DSI_MCTL_DPHY_STATIC_SWAP_PINS_DAT2 BIT(4)
+#define DSI_MCTL_DPHY_STATIC_HS_INVERT_DAT2 BIT(5)
+#define DSI_MCTL_DPHY_STATIC_UI_X4_SHIFT 6
+#define DSI_MCTL_DPHY_STATIC_UI_X4_MASK 0x00000FC0
+
+#define DSI_MCTL_MAIN_EN 0x00000020
+#define DSI_MCTL_MAIN_EN_PLL_START BIT(0)
+#define DSI_MCTL_MAIN_EN_CKLANE_EN BIT(3)
+#define DSI_MCTL_MAIN_EN_DAT1_EN BIT(4)
+#define DSI_MCTL_MAIN_EN_DAT2_EN BIT(5)
+#define DSI_MCTL_MAIN_EN_CLKLANE_ULPM_REQ BIT(6)
+#define DSI_MCTL_MAIN_EN_DAT1_ULPM_REQ BIT(7)
+#define DSI_MCTL_MAIN_EN_DAT2_ULPM_REQ BIT(8)
+#define DSI_MCTL_MAIN_EN_IF1_EN BIT(9)
+#define DSI_MCTL_MAIN_EN_IF2_EN BIT(10)
+
+#define DSI_MCTL_MAIN_STS 0x00000024
+#define DSI_MCTL_MAIN_STS_PLL_LOCK BIT(0)
+#define DSI_MCTL_MAIN_STS_CLKLANE_READY BIT(1)
+#define DSI_MCTL_MAIN_STS_DAT1_READY BIT(2)
+#define DSI_MCTL_MAIN_STS_DAT2_READY BIT(3)
+#define DSI_MCTL_MAIN_STS_HSTX_TO_ERR BIT(4)
+#define DSI_MCTL_MAIN_STS_LPRX_TO_ERR BIT(5)
+#define DSI_MCTL_MAIN_STS_CRS_UNTERM_PCK BIT(6)
+#define DSI_MCTL_MAIN_STS_VRS_UNTERM_PCK BIT(7)
+
+#define DSI_MCTL_DPHY_ERR 0x00000028
+#define DSI_INT_VID_RDDATA 0x00000030
+#define DSI_INT_VID_GNT 0x00000034
+#define DSI_INT_CMD_RDDATA 0x00000038
+#define DSI_INT_CMD_GNT 0x0000003C
+#define DSI_INT_INTERRUPT_CTL 0x00000040
+
+#define DSI_CMD_MODE_CTL 0x00000050
+#define DSI_CMD_MODE_CTL_IF1_ID_SHIFT 0
+#define DSI_CMD_MODE_CTL_IF1_ID_MASK 0x00000003
+#define DSI_CMD_MODE_CTL_IF2_ID_SHIFT 2
+#define DSI_CMD_MODE_CTL_IF2_ID_MASK 0x0000000C
+#define DSI_CMD_MODE_CTL_IF1_LP_EN BIT(4)
+#define DSI_CMD_MODE_CTL_IF2_LP_EN BIT(5)
+#define DSI_CMD_MODE_CTL_ARB_MODE BIT(6)
+#define DSI_CMD_MODE_CTL_ARB_PRI BIT(7)
+#define DSI_CMD_MODE_CTL_FIL_VALUE_SHIFT 8
+#define DSI_CMD_MODE_CTL_FIL_VALUE_MASK 0x0000FF00
+#define DSI_CMD_MODE_CTL_TE_TIMEOUT_SHIFT 16
+#define DSI_CMD_MODE_CTL_TE_TIMEOUT_MASK 0x03FF0000
+
+#define DSI_CMD_MODE_STS 0x00000054
+#define DSI_CMD_MODE_STS_ERR_NO_TE BIT(0)
+#define DSI_CMD_MODE_STS_ERR_TE_MISS BIT(1)
+#define DSI_CMD_MODE_STS_ERR_SDI1_UNDERRUN BIT(2)
+#define DSI_CMD_MODE_STS_ERR_SDI2_UNDERRUN BIT(3)
+#define DSI_CMD_MODE_STS_ERR_UNWANTED_RD BIT(4)
+#define DSI_CMD_MODE_STS_CSM_RUNNING BIT(5)
+
+#define DSI_DIRECT_CMD_SEND 0x00000060
+
+#define DSI_DIRECT_CMD_MAIN_SETTINGS 0x00000064
+#define DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_NAT_SHIFT 0
+#define DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_NAT_MASK 0x00000007
+#define DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_NAT_WRITE 0
+#define DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_NAT_READ 1
+#define DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_NAT_TE_REQ 4
+#define DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_NAT_TRIG_REQ 5
+#define DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_NAT_BTA_REQ 6
+#define DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_LONGNOTSHORT BIT(3)
+#define DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_HEAD_SHIFT 8
+#define DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_HEAD_MASK 0x00003F00
+#define DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_HEAD_TURN_ON_PERIPHERAL 50
+#define DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_HEAD_SHUT_DOWN_PERIPHERAL 34
+#define DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_HEAD_GENERIC_SHORT_WRITE_0 3
+#define DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_HEAD_GENERIC_SHORT_WRITE_1 19
+#define DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_HEAD_GENERIC_SHORT_WRITE_2 35
+#define DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_HEAD_GENERIC_LONG_WRITE 41
+#define DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_HEAD_DCS_SHORT_WRITE_0 5
+#define DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_HEAD_DCS_SHORT_WRITE_1 21
+#define DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_HEAD_DCS_LONG_WRITE 57
+#define DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_HEAD_DCS_READ 6
+#define DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_HEAD_SET_MAX_PKT_SIZE 55
+#define DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_ID_SHIFT 14
+#define DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_SIZE_SHIFT 16
+#define DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_LP_EN BIT(21)
+#define DSI_DIRECT_CMD_MAIN_SETTINGS_TRIGGER_VAL_SHIFT 24
+#define DSI_DIRECT_CMD_MAIN_SETTINGS_TRIGGER_VAL_MASK 0x0F000000
+
+#define DSI_DIRECT_CMD_STS 0x00000068
+#define DSI_DIRECT_CMD_STS_CMD_TRANSMISSION BIT(0)
+#define DSI_DIRECT_CMD_STS_WRITE_COMPLETED BIT(1)
+#define DSI_DIRECT_CMD_STS_TRIGGER_COMPLETED BIT(2)
+#define DSI_DIRECT_CMD_STS_READ_COMPLETED BIT(3)
+#define DSI_DIRECT_CMD_STS_ACKNOWLEDGE_RECEIVED_SHIFT BIT(4)
+#define DSI_DIRECT_CMD_STS_ACKNOWLEDGE_WITH_ERR_RECEIVED BIT(5)
+#define DSI_DIRECT_CMD_STS_TRIGGER_RECEIVED BIT(6)
+#define DSI_DIRECT_CMD_STS_TE_RECEIVED BIT(7)
+#define DSI_DIRECT_CMD_STS_BTA_COMPLETED BIT(8)
+#define DSI_DIRECT_CMD_STS_BTA_FINISHED BIT(9)
+#define DSI_DIRECT_CMD_STS_READ_COMPLETED_WITH_ERR BIT(10)
+#define DSI_DIRECT_CMD_STS_TRIGGER_VAL_MASK 0x00007800
+#define DSI_DIRECT_CMD_STS_TRIGGER_VAL_SHIFT 11
+#define DSI_DIRECT_CMD_STS_ACK_VAL_SHIFT 16
+#define DSI_DIRECT_CMD_STS_ACK_VAL_MASK 0xFFFF0000
+
+#define DSI_DIRECT_CMD_RD_INIT 0x0000006C
+#define DSI_DIRECT_CMD_RD_INIT_RESET_SHIFT 0
+#define DSI_DIRECT_CMD_RD_INIT_RESET_MASK 0xFFFFFFFF
+
+#define DSI_DIRECT_CMD_WRDAT0 0x00000070
+#define DSI_DIRECT_CMD_WRDAT1 0x00000074
+#define DSI_DIRECT_CMD_WRDAT2 0x00000078
+#define DSI_DIRECT_CMD_WRDAT3 0x0000007C
+
+#define DSI_DIRECT_CMD_RDDAT 0x00000080
+
+#define DSI_DIRECT_CMD_RD_PROPERTY 0x00000084
+#define DSI_DIRECT_CMD_RD_PROPERTY_RD_SIZE_SHIFT 0
+#define DSI_DIRECT_CMD_RD_PROPERTY_RD_SIZE_MASK 0x0000FFFF
+#define DSI_DIRECT_CMD_RD_PROPERTY_RD_ID_SHIFT 16
+#define DSI_DIRECT_CMD_RD_PROPERTY_RD_ID_MASK 0x00030000
+#define DSI_DIRECT_CMD_RD_PROPERTY_RD_DCSNOTGENERIC_SHIFT 18
+#define DSI_DIRECT_CMD_RD_PROPERTY_RD_DCSNOTGENERIC_MASK 0x00040000
+
+#define DSI_DIRECT_CMD_RD_STS 0x00000088
+
+#define DSI_VID_MAIN_CTL 0x00000090
+#define DSI_VID_MAIN_CTL_START_MODE_SHIFT 0
+#define DSI_VID_MAIN_CTL_START_MODE_MASK 0x00000003
+#define DSI_VID_MAIN_CTL_STOP_MODE_SHIFT 2
+#define DSI_VID_MAIN_CTL_STOP_MODE_MASK 0x0000000C
+#define DSI_VID_MAIN_CTL_VID_ID_SHIFT 4
+#define DSI_VID_MAIN_CTL_VID_ID_MASK 0x00000030
+#define DSI_VID_MAIN_CTL_HEADER_SHIFT 6
+#define DSI_VID_MAIN_CTL_HEADER_MASK 0x00000FC0
+#define DSI_VID_MAIN_CTL_VID_PIXEL_MODE_16BITS 0
+#define DSI_VID_MAIN_CTL_VID_PIXEL_MODE_18BITS BIT(12)
+#define DSI_VID_MAIN_CTL_VID_PIXEL_MODE_18BITS_LOOSE BIT(13)
+#define DSI_VID_MAIN_CTL_VID_PIXEL_MODE_24BITS (BIT(12) | BIT(13))
+#define DSI_VID_MAIN_CTL_BURST_MODE BIT(14)
+#define DSI_VID_MAIN_CTL_SYNC_PULSE_ACTIVE BIT(15)
+#define DSI_VID_MAIN_CTL_SYNC_PULSE_HORIZONTAL BIT(16)
+#define DSI_VID_MAIN_CTL_REG_BLKLINE_MODE_NULL 0
+#define DSI_VID_MAIN_CTL_REG_BLKLINE_MODE_BLANKING BIT(17)
+#define DSI_VID_MAIN_CTL_REG_BLKLINE_MODE_LP_0 BIT(18)
+#define DSI_VID_MAIN_CTL_REG_BLKLINE_MODE_LP_1 (BIT(17) | BIT(18))
+#define DSI_VID_MAIN_CTL_REG_BLKEOL_MODE_NULL 0
+#define DSI_VID_MAIN_CTL_REG_BLKEOL_MODE_BLANKING BIT(19)
+#define DSI_VID_MAIN_CTL_REG_BLKEOL_MODE_LP_0 BIT(20)
+#define DSI_VID_MAIN_CTL_REG_BLKEOL_MODE_LP_1 (BIT(19) | BIT(20))
+#define DSI_VID_MAIN_CTL_RECOVERY_MODE_SHIFT 21
+#define DSI_VID_MAIN_CTL_RECOVERY_MODE_MASK 0x00600000
+
+#define DSI_VID_VSIZE 0x00000094
+#define DSI_VID_VSIZE_VSA_LENGTH_SHIFT 0
+#define DSI_VID_VSIZE_VSA_LENGTH_MASK 0x0000003F
+#define DSI_VID_VSIZE_VBP_LENGTH_SHIFT 6
+#define DSI_VID_VSIZE_VBP_LENGTH_MASK 0x00000FC0
+#define DSI_VID_VSIZE_VFP_LENGTH_SHIFT 12
+#define DSI_VID_VSIZE_VFP_LENGTH_MASK 0x000FF000
+#define DSI_VID_VSIZE_VACT_LENGTH_SHIFT 20
+#define DSI_VID_VSIZE_VACT_LENGTH_MASK 0x7FF00000
+
+#define DSI_VID_HSIZE1 0x00000098
+#define DSI_VID_HSIZE1_HSA_LENGTH_SHIFT 0
+#define DSI_VID_HSIZE1_HSA_LENGTH_MASK 0x000003FF
+#define DSI_VID_HSIZE1_HBP_LENGTH_SHIFT 10
+#define DSI_VID_HSIZE1_HBP_LENGTH_MASK 0x000FFC00
+#define DSI_VID_HSIZE1_HFP_LENGTH_SHIFT 20
+#define DSI_VID_HSIZE1_HFP_LENGTH_MASK 0x7FF00000
+
+#define DSI_VID_HSIZE2 0x0000009C
+#define DSI_VID_HSIZE2_RGB_SIZE_SHIFT 0
+#define DSI_VID_HSIZE2_RGB_SIZE_MASK 0x00001FFF
+
+#define DSI_VID_BLKSIZE1 0x000000A0
+#define DSI_VID_BLKSIZE1_BLKLINE_EVENT_PCK_SHIFT 0
+#define DSI_VID_BLKSIZE1_BLKLINE_EVENT_PCK_MASK 0x00001FFF
+#define DSI_VID_BLKSIZE1_BLKEOL_PCK_SHIFT 13
+#define DSI_VID_BLKSIZE1_BLKEOL_PCK_MASK 0x03FFE000
+
+#define DSI_VID_BLKSIZE2 0x000000A4
+#define DSI_VID_BLKSIZE2_BLKLINE_PULSE_PCK_SHIFT 0
+#define DSI_VID_BLKSIZE2_BLKLINE_PULSE_PCK_MASK 0x00001FFF
+
+#define DSI_VID_PCK_TIME 0x000000A8
+#define DSI_VID_PCK_TIME_BLKEOL_DURATION_SHIFT 0
+
+#define DSI_VID_DPHY_TIME 0x000000AC
+#define DSI_VID_DPHY_TIME_REG_LINE_DURATION_SHIFT 0
+#define DSI_VID_DPHY_TIME_REG_LINE_DURATION_MASK 0x00001FFF
+#define DSI_VID_DPHY_TIME_REG_WAKEUP_TIME_SHIFT 13
+#define DSI_VID_DPHY_TIME_REG_WAKEUP_TIME_MASK 0x00FFE000
+
+#define DSI_VID_MODE_STS 0x000000BC
+#define DSI_VID_MODE_STS_VSG_RUNNING BIT(0)
+
+#define DSI_VID_VCA_SETTING1 0x000000C0
+#define DSI_VID_VCA_SETTING1_MAX_BURST_LIMIT_SHIFT 0
+#define DSI_VID_VCA_SETTING1_MAX_BURST_LIMIT_MASK 0x0000FFFF
+#define DSI_VID_VCA_SETTING1_BURST_LP BIT(16)
+
+#define DSI_VID_VCA_SETTING2 0x000000C4
+#define DSI_VID_VCA_SETTING2_EXACT_BURST_LIMIT_SHIFT 0
+#define DSI_VID_VCA_SETTING2_EXACT_BURST_LIMIT_MASK 0x0000FFFF
+#define DSI_VID_VCA_SETTING2_MAX_LINE_LIMIT_SHIFT 16
+#define DSI_VID_VCA_SETTING2_MAX_LINE_LIMIT_MASK 0xFFFF0000
+
+#define DSI_CMD_MODE_STS_CTL 0x000000F4
+#define DSI_CMD_MODE_STS_CTL_ERR_NO_TE_EN BIT(0)
+#define DSI_CMD_MODE_STS_CTL_ERR_TE_MISS_EN BIT(1)
+#define DSI_CMD_MODE_STS_CTL_ERR_SDI1_UNDERRUN_EN BIT(2)
+#define DSI_CMD_MODE_STS_CTL_ERR_SDI2_UNDERRUN_EN BIT(3)
+#define DSI_CMD_MODE_STS_CTL_ERR_UNWANTED_RD_EN BIT(4)
+#define DSI_CMD_MODE_STS_CTL_CSM_RUNNING_EN BIT(5)
+#define DSI_CMD_MODE_STS_CTL_ERR_NO_TE_EDGE BIT(16)
+#define DSI_CMD_MODE_STS_CTL_ERR_TE_MISS_EDGE BIT(17)
+#define DSI_CMD_MODE_STS_CTL_ERR_SDI1_UNDERRUN_EDGE BIT(18)
+#define DSI_CMD_MODE_STS_CTL_ERR_SDI2_UNDERRUN_EDGE BIT(19)
+#define DSI_CMD_MODE_STS_CTL_ERR_UNWANTED_RD_EDGE BIT(20)
+#define DSI_CMD_MODE_STS_CTL_CSM_RUNNING_EDGE BIT(21)
+
+#define DSI_DIRECT_CMD_STS_CTL 0x000000F8
+#define DSI_DIRECT_CMD_STS_CTL_CMD_TRANSMISSION_EN BIT(0)
+#define DSI_DIRECT_CMD_STS_CTL_WRITE_COMPLETED_EN BIT(1)
+#define DSI_DIRECT_CMD_STS_CTL_TRIGGER_COMPLETED_EN BIT(2)
+#define DSI_DIRECT_CMD_STS_CTL_READ_COMPLETED_EN BIT(3)
+#define DSI_DIRECT_CMD_STS_CTL_ACKNOWLEDGE_RECEIVED_EN BIT(4)
+#define DSI_DIRECT_CMD_STS_CTL_ACKNOWLEDGE_WITH_ERR_EN BIT(5)
+#define DSI_DIRECT_CMD_STS_CTL_TRIGGER_RECEIVED_EN BIT(6)
+#define DSI_DIRECT_CMD_STS_CTL_TE_RECEIVED_EN BIT(7)
+#define DSI_DIRECT_CMD_STS_CTL_BTA_COMPLETED_EN BIT(8)
+#define DSI_DIRECT_CMD_STS_CTL_BTA_FINISHED_EN BIT(9)
+#define DSI_DIRECT_CMD_STS_CTL_READ_COMPLETED_WITH_ERR_EN BIT(10)
+#define DSI_DIRECT_CMD_STS_CTL_CMD_TRANSMISSION_EDGE BIT(16)
+#define DSI_DIRECT_CMD_STS_CTL_WRITE_COMPLETED_EDGE BIT(17)
+#define DSI_DIRECT_CMD_STS_CTL_TRIGGER_COMPLETED_EDGE BIT(18)
+#define DSI_DIRECT_CMD_STS_CTL_READ_COMPLETED_EDGE BIT(19)
+#define DSI_DIRECT_CMD_STS_CTL_ACKNOWLEDGE_RECEIVED_EDGE BIT(20)
+#define DSI_DIRECT_CMD_STS_CTL_ACKNOWLEDGE_WITH_ERR_EDGE BIT(21)
+#define DSI_DIRECT_CMD_STS_CTL_TRIGGER_RECEIVED_EDGE BIT(22)
+#define DSI_DIRECT_CMD_STS_CTL_TE_RECEIVED_EDGE BIT(23)
+#define DSI_DIRECT_CMD_STS_CTL_BTA_COMPLETED_EDGE BIT(24)
+#define DSI_DIRECT_CMD_STS_CTL_BTA_FINISHED_EDGE BIT(25)
+#define DSI_DIRECT_CMD_STS_CTL_READ_COMPLETED_WITH_ERR_EDGE BIT(26)
+
+#define DSI_VID_MODE_STS_CTL 0x00000100
+#define DSI_VID_MODE_STS_CTL_VSG_RUNNING BIT(0)
+#define DSI_VID_MODE_STS_CTL_ERR_MISSING_DATA BIT(1)
+#define DSI_VID_MODE_STS_CTL_ERR_MISSING_HSYNC BIT(2)
+#define DSI_VID_MODE_STS_CTL_ERR_MISSING_VSYNC BIT(3)
+#define DSI_VID_MODE_STS_CTL_REG_ERR_SMALL_LENGTH BIT(4)
+#define DSI_VID_MODE_STS_CTL_REG_ERR_SMALL_HEIGHT BIT(5)
+#define DSI_VID_MODE_STS_CTL_ERR_BURSTWRITE BIT(6)
+#define DSI_VID_MODE_STS_CTL_ERR_LONGWRITE BIT(7)
+#define DSI_VID_MODE_STS_CTL_ERR_LONGREAD BIT(8)
+#define DSI_VID_MODE_STS_CTL_ERR_VRS_WRONG_LENGTH BIT(9)
+#define DSI_VID_MODE_STS_CTL_VSG_RUNNING_EDGE BIT(16)
+#define DSI_VID_MODE_STS_CTL_ERR_MISSING_DATA_EDGE BIT(17)
+#define DSI_VID_MODE_STS_CTL_ERR_MISSING_HSYNC_EDGE BIT(18)
+#define DSI_VID_MODE_STS_CTL_ERR_MISSING_VSYNC_EDGE BIT(19)
+#define DSI_VID_MODE_STS_CTL_REG_ERR_SMALL_LENGTH_EDGE BIT(20)
+#define DSI_VID_MODE_STS_CTL_REG_ERR_SMALL_HEIGHT_EDGE BIT(21)
+#define DSI_VID_MODE_STS_CTL_ERR_BURSTWRITE_EDGE BIT(22)
+#define DSI_VID_MODE_STS_CTL_ERR_LONGWRITE_EDGE BIT(23)
+#define DSI_VID_MODE_STS_CTL_ERR_LONGREAD_EDGE BIT(24)
+#define DSI_VID_MODE_STS_CTL_ERR_VRS_WRONG_LENGTH_EDGE BIT(25)
+#define DSI_VID_MODE_STS_CTL_VSG_RECOVERY_EDGE BIT(26)
+
+#define DSI_TG_STS_CTL 0x00000104
+#define DSI_MCTL_DHPY_ERR_CTL 0x00000108
+#define DSI_MCTL_MAIN_STS_CLR 0x00000110
+
+#define DSI_CMD_MODE_STS_CLR 0x00000114
+#define DSI_CMD_MODE_STS_CLR_ERR_NO_TE_CLR BIT(0)
+#define DSI_CMD_MODE_STS_CLR_ERR_TE_MISS_CLR BIT(1)
+#define DSI_CMD_MODE_STS_CLR_ERR_SDI1_UNDERRUN_CLR BIT(2)
+#define DSI_CMD_MODE_STS_CLR_ERR_SDI2_UNDERRUN_CLR BIT(3)
+#define DSI_CMD_MODE_STS_CLR_ERR_UNWANTED_RD_CLR BIT(4)
+#define DSI_CMD_MODE_STS_CLR_CSM_RUNNING_CLR BIT(5)
+
+#define DSI_DIRECT_CMD_STS_CLR 0x00000118
+#define DSI_DIRECT_CMD_STS_CLR_CMD_TRANSMISSION_CLR BIT(0)
+#define DSI_DIRECT_CMD_STS_CLR_WRITE_COMPLETED_CLR BIT(1)
+#define DSI_DIRECT_CMD_STS_CLR_TRIGGER_COMPLETED_CLR BIT(2)
+#define DSI_DIRECT_CMD_STS_CLR_READ_COMPLETED_CLR BIT(3)
+#define DSI_DIRECT_CMD_STS_CLR_ACKNOWLEDGE_RECEIVED_CLR BIT(4)
+#define DSI_DIRECT_CMD_STS_CLR_ACKNOWLEDGE_WITH_ERR_RECEIVED_CLR BIT(5)
+#define DSI_DIRECT_CMD_STS_CLR_TRIGGER_RECEIVED_CLR BIT(6)
+#define DSI_DIRECT_CMD_STS_CLR_TE_RECEIVED_CLR BIT(7)
+#define DSI_DIRECT_CMD_STS_CLR_BTA_COMPLETED_CLR BIT(8)
+#define DSI_DIRECT_CMD_STS_CLR_BTA_FINISHED_CLR BIT(9)
+#define DSI_DIRECT_CMD_STS_CLR_READ_COMPLETED_WITH_ERR_CLR BIT(10)
+
+#define DSI_DIRECT_CMD_RD_STS_CLR 0x0000011C
+#define DSI_VID_MODE_STS_CLR 0x00000120
+#define DSI_TG_STS_CLR 0x00000124
+#define DSI_MCTL_DPHY_ERR_CLR 0x00000128
+#define DSI_MCTL_MAIN_STS_FLAG 0x00000130
+#define DSI_CMD_MODE_STS_FLAG 0x00000134
+#define DSI_DIRECT_CMD_STS_FLAG 0x00000138
+#define DSI_DIRECT_CMD_RD_STS_FLAG 0x0000013C
+#define DSI_VID_MODE_STS_FLAG 0x00000140
+#define DSI_TG_STS_FLAG 0x00000144
+
+#define DSI_DPHY_LANES_TRIM 0x00000150
+#define DSI_DPHY_LANES_TRIM_DPHY_SKEW_DAT1_SHIFT 0
+#define DSI_DPHY_LANES_TRIM_DPHY_SKEW_DAT1_MASK 0x00000003
+#define DSI_DPHY_LANES_TRIM_DPHY_CD_OFF_DAT1 BIT(2)
+#define DSI_DPHY_LANES_TRIM_DPHY_HSTX_SLEWRATE_UP_DAT1 BIT(3)
+#define DSI_DPHY_LANES_TRIM_DPHY_HSTX_SLEWRATE_DOWN_DAT1 BIT(4)
+#define DSI_DPHY_LANES_TRIM_DPHY_TEST_RESERVED_1_DAT1 BIT(5)
+#define DSI_DPHY_LANES_TRIM_DPHY_SKEW_CLK_SHIFT 6
+#define DSI_DPHY_LANES_TRIM_DPHY_SKEW_CLK_MASK 0x000000C0
+#define DSI_DPHY_LANES_TRIM_DPHY_LP_RX_VIL_CLK_SHIFT 8
+#define DSI_DPHY_LANES_TRIM_DPHY_LP_RX_VIL_CLK_MASK 0x00000300
+#define DSI_DPHY_LANES_TRIM_DPHY_LP_TX_SLEWRATE_CLK_SHIFT 10
+#define DSI_DPHY_LANES_TRIM_DPHY_LP_TX_SLEWRATE_CLK_MASK 0x00000C00
+#define DSI_DPHY_LANES_TRIM_DPHY_SPECS_90_81B_0_81 0
+#define DSI_DPHY_LANES_TRIM_DPHY_SPECS_90_81B_0_90 BIT(12)
+#define DSI_DPHY_LANES_TRIM_DPHY_HSTX_SLEWRATE_UP_CLK BIT(13)
+#define DSI_DPHY_LANES_TRIM_DPHY_HSTX_SLEWRATE_DOWN_CLK BIT(14)
+#define DSI_DPHY_LANES_TRIM_DPHY_TEST_RESERVED_1_CLK BIT(15)
+#define DSI_DPHY_LANES_TRIM_DPHY_SKEW_DAT2 BIT(16)
+#define DSI_DPHY_LANES_TRIM_DPHY_HSTX_SLEWRATE_UP_DAT2 BIT(18)
+#define DSI_DPHY_LANES_TRIM_DPHY_HSTX_SLEWRATE_DOWN_DAT2 BIT(19)
+#define DSI_DPHY_LANES_TRIM_DPHY_TEST_RESERVED_1_DAT2 BIT(20)
+
+#define DSI_ID_REG 0x00000FF0
+
+#endif /* __DRM_MCDE_DSI_REGS */
diff --git a/drivers/gpu/drm/meson/Kconfig b/drivers/gpu/drm/meson/Kconfig
index e450387d0eab..9f9281dd49f8 100644
--- a/drivers/gpu/drm/meson/Kconfig
+++ b/drivers/gpu/drm/meson/Kconfig
@@ -15,3 +15,4 @@ config DRM_MESON_DW_HDMI
depends on DRM_MESON
default y if DRM_MESON
select DRM_DW_HDMI
+ imply DRM_DW_HDMI_I2S_AUDIO
diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c
index c22c4719cd2c..ba653f6c3f5f 100644
--- a/drivers/gpu/drm/panel/panel-simple.c
+++ b/drivers/gpu/drm/panel/panel-simple.c
@@ -446,6 +446,32 @@ static const struct panel_desc ampire_am800480r3tmqwa1h = {
.bus_format = MEDIA_BUS_FMT_RGB666_1X18,
};
+static const struct display_timing santek_st0700i5y_rbslw_f_timing = {
+ .pixelclock = { 26400000, 33300000, 46800000 },
+ .hactive = { 800, 800, 800 },
+ .hfront_porch = { 16, 210, 354 },
+ .hback_porch = { 45, 36, 6 },
+ .hsync_len = { 1, 10, 40 },
+ .vactive = { 480, 480, 480 },
+ .vfront_porch = { 7, 22, 147 },
+ .vback_porch = { 22, 13, 3 },
+ .vsync_len = { 1, 10, 20 },
+ .flags = DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW |
+ DISPLAY_FLAGS_DE_HIGH | DISPLAY_FLAGS_PIXDATA_POSEDGE
+};
+
+static const struct panel_desc armadeus_st0700_adapt = {
+ .timings = &santek_st0700i5y_rbslw_f_timing,
+ .num_timings = 1,
+ .bpc = 6,
+ .size = {
+ .width = 154,
+ .height = 86,
+ },
+ .bus_format = MEDIA_BUS_FMT_RGB666_1X18,
+ .bus_flags = DRM_BUS_FLAG_DE_HIGH | DRM_BUS_FLAG_PIXDATA_POSEDGE,
+};
+
static const struct drm_display_mode auo_b101aw03_mode = {
.clock = 51450,
.hdisplay = 1024,
@@ -1649,6 +1675,29 @@ static const struct panel_desc innolux_zj070na_01p = {
},
};
+static const struct display_timing koe_tx14d24vm1bpa_timing = {
+ .pixelclock = { 5580000, 5850000, 6200000 },
+ .hactive = { 320, 320, 320 },
+ .hfront_porch = { 30, 30, 30 },
+ .hback_porch = { 30, 30, 30 },
+ .hsync_len = { 1, 5, 17 },
+ .vactive = { 240, 240, 240 },
+ .vfront_porch = { 6, 6, 6 },
+ .vback_porch = { 5, 5, 5 },
+ .vsync_len = { 1, 2, 11 },
+ .flags = DISPLAY_FLAGS_DE_HIGH,
+};
+
+static const struct panel_desc koe_tx14d24vm1bpa = {
+ .timings = &koe_tx14d24vm1bpa_timing,
+ .num_timings = 1,
+ .bpc = 6,
+ .size = {
+ .width = 115,
+ .height = 86,
+ },
+};
+
static const struct display_timing koe_tx31d200vm0baa_timing = {
.pixelclock = { 39600000, 43200000, 48000000 },
.hactive = { 1280, 1280, 1280 },
@@ -2722,6 +2771,9 @@ static const struct of_device_id platform_of_match[] = {
.compatible = "arm,rtsm-display",
.data = &arm_rtsm,
}, {
+ .compatible = "armadeus,st0700-adapt",
+ .data = &armadeus_st0700_adapt,
+ }, {
.compatible = "auo,b101aw03",
.data = &auo_b101aw03,
}, {
@@ -2869,6 +2921,9 @@ static const struct of_device_id platform_of_match[] = {
.compatible = "innolux,zj070na-01p",
.data = &innolux_zj070na_01p,
}, {
+ .compatible = "koe,tx14d24vm1bpa",
+ .data = &koe_tx14d24vm1bpa,
+ }, {
.compatible = "koe,tx31d200vm0baa",
.data = &koe_tx31d200vm0baa,
}, {
diff --git a/drivers/gpu/drm/panel/panel-sitronix-st7701.c b/drivers/gpu/drm/panel/panel-sitronix-st7701.c
index 63f9a1c7fb1b..09c5d9a6f9fa 100644
--- a/drivers/gpu/drm/panel/panel-sitronix-st7701.c
+++ b/drivers/gpu/drm/panel/panel-sitronix-st7701.c
@@ -305,9 +305,9 @@ static const struct drm_display_mode ts8550b_mode = {
.htotal = 480 + 38 + 12 + 12,
.vdisplay = 854,
- .vsync_start = 854 + 4,
- .vsync_end = 854 + 4 + 8,
- .vtotal = 854 + 4 + 8 + 18,
+ .vsync_start = 854 + 18,
+ .vsync_end = 854 + 18 + 8,
+ .vtotal = 854 + 18 + 8 + 4,
.width_mm = 69,
.height_mm = 139,
diff --git a/drivers/gpu/drm/scheduler/sched_main.c b/drivers/gpu/drm/scheduler/sched_main.c
index cf596fc0355b..49e7d0780414 100644
--- a/drivers/gpu/drm/scheduler/sched_main.c
+++ b/drivers/gpu/drm/scheduler/sched_main.c
@@ -286,16 +286,17 @@ static void drm_sched_job_timedout(struct work_struct *work)
job = list_first_entry_or_null(&sched->ring_mirror_list,
struct drm_sched_job, node);
- if (job)
+ if (job) {
job->sched->ops->timedout_job(job);
- /*
- * Guilty job did complete and hence needs to be manually removed
- * See drm_sched_stop doc.
- */
- if (sched->free_guilty) {
- job->sched->ops->free_job(job);
- sched->free_guilty = false;
+ /*
+ * Guilty job did complete and hence needs to be manually removed
+ * See drm_sched_stop doc.
+ */
+ if (sched->free_guilty) {
+ job->sched->ops->free_job(job);
+ sched->free_guilty = false;
+ }
}
spin_lock_irqsave(&sched->job_list_lock, flags);
diff --git a/drivers/gpu/drm/stm/dw_mipi_dsi-stm.c b/drivers/gpu/drm/stm/dw_mipi_dsi-stm.c
index d8e4a146b320..01db020c8953 100644
--- a/drivers/gpu/drm/stm/dw_mipi_dsi-stm.c
+++ b/drivers/gpu/drm/stm/dw_mipi_dsi-stm.c
@@ -227,7 +227,6 @@ dw_mipi_dsi_get_lane_mbps(void *priv_data, const struct drm_display_mode *mode,
u32 val;
/* Update lane capabilities according to hw version */
- dsi->hw_version = dsi_read(dsi, DSI_VERSION) & VERSION;
dsi->lane_min_kbps = LANE_MIN_KBPS;
dsi->lane_max_kbps = LANE_MAX_KBPS;
if (dsi->hw_version == HWVER_131) {
@@ -306,6 +305,7 @@ static int dw_mipi_dsi_stm_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct dw_mipi_dsi_stm *dsi;
+ struct clk *pclk;
struct resource *res;
int ret;
@@ -348,6 +348,28 @@ static int dw_mipi_dsi_stm_probe(struct platform_device *pdev)
goto err_clk_get;
}
+ pclk = devm_clk_get(dev, "pclk");
+ if (IS_ERR(pclk)) {
+ ret = PTR_ERR(pclk);
+ DRM_ERROR("Unable to get peripheral clock: %d\n", ret);
+ goto err_dsi_probe;
+ }
+
+ ret = clk_prepare_enable(pclk);
+ if (ret) {
+ DRM_ERROR("%s: Failed to enable peripheral clk\n", __func__);
+ goto err_dsi_probe;
+ }
+
+ dsi->hw_version = dsi_read(dsi, DSI_VERSION) & VERSION;
+ clk_disable_unprepare(pclk);
+
+ if (dsi->hw_version != HWVER_130 && dsi->hw_version != HWVER_131) {
+ ret = -ENODEV;
+ DRM_ERROR("bad dsi hardware version\n");
+ goto err_dsi_probe;
+ }
+
dw_mipi_dsi_stm_plat_data.base = dsi->base;
dw_mipi_dsi_stm_plat_data.priv_data = dsi;
diff --git a/drivers/gpu/drm/stm/ltdc.c b/drivers/gpu/drm/stm/ltdc.c
index 14eb8c40953b..ac29890edeb6 100644
--- a/drivers/gpu/drm/stm/ltdc.c
+++ b/drivers/gpu/drm/stm/ltdc.c
@@ -507,11 +507,6 @@ static bool ltdc_crtc_mode_fixup(struct drm_crtc *crtc,
struct ltdc_device *ldev = crtc_to_ltdc(crtc);
int rate = mode->clock * 1000;
- /*
- * TODO clk_round_rate() does not work yet. When ready, it can
- * be used instead of clk_set_rate() then clk_get_rate().
- */
-
clk_disable(ldev->pixel_clk);
if (clk_set_rate(ldev->pixel_clk, rate) < 0) {
DRM_ERROR("Cannot set rate (%dHz) for pixel clk\n", rate);
@@ -521,6 +516,9 @@ static bool ltdc_crtc_mode_fixup(struct drm_crtc *crtc,
adjusted_mode->clock = clk_get_rate(ldev->pixel_clk) / 1000;
+ DRM_DEBUG_DRIVER("requested clock %dkHz, adjusted clock %dkHz\n",
+ mode->clock, adjusted_mode->clock);
+
return true;
}
diff --git a/include/drm/bridge/dw_mipi_dsi.h b/include/drm/bridge/dw_mipi_dsi.h
index 7d3dd69a5caa..92cf9d1e1655 100644
--- a/include/drm/bridge/dw_mipi_dsi.h
+++ b/include/drm/bridge/dw_mipi_dsi.h
@@ -10,7 +10,15 @@
#ifndef __DW_MIPI_DSI__
#define __DW_MIPI_DSI__
+#include <linux/types.h>
+
+#include <drm/drm_modes.h>
+
+struct drm_display_mode;
+struct drm_encoder;
struct dw_mipi_dsi;
+struct mipi_dsi_device;
+struct platform_device;
struct dw_mipi_dsi_phy_ops {
int (*init)(void *priv_data);
diff --git a/include/drm/drm_auth.h b/include/drm/drm_auth.h
index 871008118bab..6bf8b2b78991 100644
--- a/include/drm/drm_auth.h
+++ b/include/drm/drm_auth.h
@@ -1,3 +1,6 @@
+#ifndef _DRM_AUTH_H_
+#define _DRM_AUTH_H_
+
/*
* Internal Header for the Direct Rendering Manager
*
@@ -25,8 +28,12 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
-#ifndef _DRM_AUTH_H_
-#define _DRM_AUTH_H_
+#include <linux/idr.h>
+#include <linux/kref.h>
+#include <linux/wait.h>
+
+struct drm_file;
+struct drm_hw_lock;
/*
* Legacy DRI1 locking data structure. Only here instead of in drm_legacy.h for
diff --git a/include/drm/drm_legacy.h b/include/drm/drm_legacy.h
index 2182a56ac421..58dc0c04bf99 100644
--- a/include/drm/drm_legacy.h
+++ b/include/drm/drm_legacy.h
@@ -1,11 +1,5 @@
#ifndef __DRM_DRM_LEGACY_H__
#define __DRM_DRM_LEGACY_H__
-
-#include <drm/drm_auth.h>
-#include <drm/drm_hashtab.h>
-
-struct drm_device;
-
/*
* Legacy driver interfaces for the Direct Rendering Manager
*
@@ -39,6 +33,12 @@ struct drm_device;
* OTHER DEALINGS IN THE SOFTWARE.
*/
+#include <drm/drm.h>
+#include <drm/drm_auth.h>
+#include <drm/drm_hashtab.h>
+
+struct drm_device;
+struct file;
/*
* Legacy Support for palateontologic DRM drivers