diff options
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 = <®_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 |