Merge drm/drm-next into drm-misc-next
authorMaxime Ripard <mripard@kernel.org>
Thu, 3 Oct 2019 14:38:50 +0000 (16:38 +0200)
committerMaxime Ripard <mripard@kernel.org>
Thu, 3 Oct 2019 14:38:50 +0000 (16:38 +0200)
We haven't done any backmerge for a while due to the merge window, and it
starts to become an issue for komeda. Let's bring 5.4-rc1 in.

Signed-off-by: Maxime Ripard <mripard@kernel.org>
266 files changed:
Documentation/devicetree/bindings/display/allwinner,sun6i-a31-mipi-dsi.yaml
Documentation/devicetree/bindings/display/bridge/anx7814.txt
Documentation/gpu/drm-mm.rst
Documentation/gpu/todo.rst
MAINTAINERS
drivers/dma-buf/dma-resv.c
drivers/gpu/drm/Kconfig
drivers/gpu/drm/Makefile
drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c
drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
drivers/gpu/drm/amd/amdgpu/dce_virtual.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
drivers/gpu/drm/arc/arcpgu_hdmi.c
drivers/gpu/drm/arm/display/Kconfig
drivers/gpu/drm/arm/display/komeda/Makefile
drivers/gpu/drm/arm/display/komeda/d71/d71_component.c
drivers/gpu/drm/arm/display/komeda/d71/d71_dev.c
drivers/gpu/drm/arm/display/komeda/d71/d71_dev.h
drivers/gpu/drm/arm/display/komeda/komeda_crtc.c
drivers/gpu/drm/arm/display/komeda/komeda_dev.c
drivers/gpu/drm/arm/display/komeda/komeda_dev.h
drivers/gpu/drm/arm/display/komeda/komeda_drv.c
drivers/gpu/drm/arm/display/komeda/komeda_event.c [new file with mode: 0644]
drivers/gpu/drm/arm/display/komeda/komeda_kms.c
drivers/gpu/drm/arm/display/komeda/komeda_pipeline.h
drivers/gpu/drm/arm/display/komeda/komeda_pipeline_state.c
drivers/gpu/drm/ast/Kconfig
drivers/gpu/drm/ast/ast_drv.c
drivers/gpu/drm/ast/ast_main.c
drivers/gpu/drm/ast/ast_mode.c
drivers/gpu/drm/ast/ast_ttm.c
drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c
drivers/gpu/drm/bochs/Kconfig
drivers/gpu/drm/bochs/bochs.h
drivers/gpu/drm/bochs/bochs_drv.c
drivers/gpu/drm/bochs/bochs_mm.c
drivers/gpu/drm/bridge/analogix-anx78xx.c
drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
drivers/gpu/drm/bridge/cdns-dsi.c
drivers/gpu/drm/bridge/dumb-vga-dac.c
drivers/gpu/drm/bridge/lvds-encoder.c
drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c
drivers/gpu/drm/bridge/nxp-ptn3460.c
drivers/gpu/drm/bridge/panel.c
drivers/gpu/drm/bridge/parade-ps8622.c
drivers/gpu/drm/bridge/sii902x.c
drivers/gpu/drm/bridge/sii9234.c
drivers/gpu/drm/bridge/sil-sii8620.c
drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c
drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
drivers/gpu/drm/bridge/synopsys/dw-hdmi.h
drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
drivers/gpu/drm/bridge/tc358764.c
drivers/gpu/drm/bridge/tc358767.c
drivers/gpu/drm/bridge/ti-sn65dsi86.c
drivers/gpu/drm/bridge/ti-tfp410.c
drivers/gpu/drm/cirrus/cirrus.c
drivers/gpu/drm/drm_atomic_helper.c
drivers/gpu/drm/drm_atomic_uapi.c
drivers/gpu/drm/drm_blend.c
drivers/gpu/drm/drm_client_modeset.c
drivers/gpu/drm/drm_connector.c
drivers/gpu/drm/drm_crtc_helper.c
drivers/gpu/drm/drm_crtc_helper_internal.h
drivers/gpu/drm/drm_debugfs_crc.c
drivers/gpu/drm/drm_dp_cec.c
drivers/gpu/drm/drm_dp_helper.c
drivers/gpu/drm/drm_dp_mst_topology.c
drivers/gpu/drm/drm_dp_mst_topology_internal.h [new file with mode: 0644]
drivers/gpu/drm/drm_drv.c
drivers/gpu/drm/drm_dsc.c
drivers/gpu/drm/drm_edid.c
drivers/gpu/drm/drm_edid_load.c
drivers/gpu/drm/drm_encoder.c
drivers/gpu/drm/drm_fb_helper.c
drivers/gpu/drm/drm_gem_ttm_helper.c [new file with mode: 0644]
drivers/gpu/drm/drm_gem_vram_helper.c
drivers/gpu/drm/drm_memory.c
drivers/gpu/drm/drm_mipi_dbi.c
drivers/gpu/drm/drm_of.c
drivers/gpu/drm/drm_panel.c
drivers/gpu/drm/drm_print.c
drivers/gpu/drm/drm_probe_helper.c
drivers/gpu/drm/drm_simple_kms_helper.c
drivers/gpu/drm/drm_syncobj.c
drivers/gpu/drm/drm_trace.h
drivers/gpu/drm/drm_vblank.c
drivers/gpu/drm/drm_vram_helper_common.c
drivers/gpu/drm/drm_vram_mm_helper.c [deleted file]
drivers/gpu/drm/etnaviv/etnaviv_buffer.c
drivers/gpu/drm/exynos/exynos_dp.c
drivers/gpu/drm/exynos/exynos_drm_dsi.c
drivers/gpu/drm/exynos/exynos_drm_mic.c
drivers/gpu/drm/exynos/exynos_hdmi.c
drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c
drivers/gpu/drm/hisilicon/hibmc/Kconfig
drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
drivers/gpu/drm/hisilicon/hibmc/hibmc_ttm.c
drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
drivers/gpu/drm/i2c/sil164_drv.c
drivers/gpu/drm/i2c/tda9950.c
drivers/gpu/drm/i2c/tda998x_drv.c
drivers/gpu/drm/i915/display/intel_connector.c
drivers/gpu/drm/i915/display/intel_dp.c
drivers/gpu/drm/i915/display/intel_hdmi.c
drivers/gpu/drm/i915/i915_drv.c
drivers/gpu/drm/imx/imx-ldb.c
drivers/gpu/drm/imx/parallel-display.c
drivers/gpu/drm/ingenic/ingenic-drm.c
drivers/gpu/drm/mcde/mcde_drv.c
drivers/gpu/drm/mcde/mcde_dsi.c
drivers/gpu/drm/mediatek/mtk_dpi.c
drivers/gpu/drm/mediatek/mtk_dsi.c
drivers/gpu/drm/mediatek/mtk_hdmi.c
drivers/gpu/drm/meson/meson_drv.c
drivers/gpu/drm/meson/meson_dw_hdmi.c
drivers/gpu/drm/meson/meson_vclk.c
drivers/gpu/drm/mgag200/Kconfig
drivers/gpu/drm/mgag200/mgag200_cursor.c
drivers/gpu/drm/mgag200/mgag200_drv.c
drivers/gpu/drm/mgag200/mgag200_drv.h
drivers/gpu/drm/mgag200/mgag200_mode.c
drivers/gpu/drm/mgag200/mgag200_ttm.c
drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
drivers/gpu/drm/msm/dsi/dsi.h
drivers/gpu/drm/msm/edp/edp.c
drivers/gpu/drm/msm/edp/edp.h
drivers/gpu/drm/msm/hdmi/hdmi.c
drivers/gpu/drm/msm/hdmi/hdmi.h
drivers/gpu/drm/nouveau/dispnv04/disp.c
drivers/gpu/drm/nouveau/dispnv50/disp.c
drivers/gpu/drm/nouveau/nouveau_connector.c
drivers/gpu/drm/nouveau/nouveau_ttm.c
drivers/gpu/drm/omapdrm/dss/output.c
drivers/gpu/drm/omapdrm/omap_drv.c
drivers/gpu/drm/omapdrm/omap_encoder.c
drivers/gpu/drm/panel/panel-arm-versatile.c
drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c
drivers/gpu/drm/panel/panel-ilitek-ili9322.c
drivers/gpu/drm/panel/panel-ilitek-ili9881c.c
drivers/gpu/drm/panel/panel-innolux-p079zca.c
drivers/gpu/drm/panel/panel-jdi-lt070me05000.c
drivers/gpu/drm/panel/panel-kingdisplay-kd097d04.c
drivers/gpu/drm/panel/panel-lg-lb035q02.c
drivers/gpu/drm/panel/panel-lg-lg4573.c
drivers/gpu/drm/panel/panel-lvds.c
drivers/gpu/drm/panel/panel-nec-nl8048hl11.c
drivers/gpu/drm/panel/panel-novatek-nt39016.c
drivers/gpu/drm/panel/panel-olimex-lcd-olinuxino.c
drivers/gpu/drm/panel/panel-orisetech-otm8009a.c
drivers/gpu/drm/panel/panel-osd-osd101t2587-53ts.c
drivers/gpu/drm/panel/panel-panasonic-vvx10f034n00.c
drivers/gpu/drm/panel/panel-raspberrypi-touchscreen.c
drivers/gpu/drm/panel/panel-raydium-rm67191.c
drivers/gpu/drm/panel/panel-raydium-rm68200.c
drivers/gpu/drm/panel/panel-rocktech-jh057n00900.c
drivers/gpu/drm/panel/panel-ronbo-rb070d30.c
drivers/gpu/drm/panel/panel-samsung-ld9040.c
drivers/gpu/drm/panel/panel-samsung-s6d16d0.c
drivers/gpu/drm/panel/panel-samsung-s6e3ha2.c
drivers/gpu/drm/panel/panel-samsung-s6e63j0x03.c
drivers/gpu/drm/panel/panel-samsung-s6e63m0.c
drivers/gpu/drm/panel/panel-samsung-s6e8aa0.c
drivers/gpu/drm/panel/panel-seiko-43wvf1g.c
drivers/gpu/drm/panel/panel-sharp-lq101r1sx01.c
drivers/gpu/drm/panel/panel-sharp-ls037v7dw01.c
drivers/gpu/drm/panel/panel-sharp-ls043t1le01.c
drivers/gpu/drm/panel/panel-simple.c
drivers/gpu/drm/panel/panel-sitronix-st7701.c
drivers/gpu/drm/panel/panel-sitronix-st7789v.c
drivers/gpu/drm/panel/panel-sony-acx565akm.c
drivers/gpu/drm/panel/panel-tpo-td028ttec1.c
drivers/gpu/drm/panel/panel-tpo-td043mtea1.c
drivers/gpu/drm/panel/panel-tpo-tpg110.c
drivers/gpu/drm/panel/panel-truly-nt35597.c
drivers/gpu/drm/panfrost/panfrost_devfreq.c
drivers/gpu/drm/panfrost/panfrost_issues.h
drivers/gpu/drm/pl111/pl111_drv.c
drivers/gpu/drm/qxl/qxl_drv.c
drivers/gpu/drm/qxl/qxl_drv.h
drivers/gpu/drm/qxl/qxl_object.c
drivers/gpu/drm/qxl/qxl_ttm.c
drivers/gpu/drm/radeon/radeon_connectors.c
drivers/gpu/drm/radeon/radeon_drv.c
drivers/gpu/drm/radeon/radeon_ttm.c
drivers/gpu/drm/rcar-du/rcar_du_encoder.c
drivers/gpu/drm/rockchip/rockchip_lvds.c
drivers/gpu/drm/rockchip/rockchip_rgb.c
drivers/gpu/drm/selftests/Makefile
drivers/gpu/drm/selftests/drm_modeset_selftests.h
drivers/gpu/drm/selftests/test-drm_dp_mst_helper.c [new file with mode: 0644]
drivers/gpu/drm/selftests/test-drm_framebuffer.c
drivers/gpu/drm/selftests/test-drm_modeset_common.h
drivers/gpu/drm/sti/sti_cursor.c
drivers/gpu/drm/sti/sti_dvo.c
drivers/gpu/drm/sti/sti_gdp.c
drivers/gpu/drm/sti/sti_hda.c
drivers/gpu/drm/sti/sti_hdmi.c
drivers/gpu/drm/sti/sti_tvout.c
drivers/gpu/drm/sti/sti_vtg.c
drivers/gpu/drm/stm/dw_mipi_dsi-stm.c
drivers/gpu/drm/stm/ltdc.c
drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
drivers/gpu/drm/sun4i/sun4i_lvds.c
drivers/gpu/drm/sun4i/sun4i_rgb.c
drivers/gpu/drm/sun4i/sun4i_tcon.c
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h
drivers/gpu/drm/tilcdc/tilcdc_external.c
drivers/gpu/drm/tiny/Kconfig
drivers/gpu/drm/ttm/ttm_bo.c
drivers/gpu/drm/ttm/ttm_bo_vm.c
drivers/gpu/drm/tve200/tve200_drv.c
drivers/gpu/drm/udl/udl_connector.c
drivers/gpu/drm/v3d/v3d_drv.c
drivers/gpu/drm/v3d/v3d_gem.c
drivers/gpu/drm/vboxvideo/Kconfig
drivers/gpu/drm/vboxvideo/vbox_drv.h
drivers/gpu/drm/vboxvideo/vbox_ttm.c
drivers/gpu/drm/vc4/vc4_dpi.c
drivers/gpu/drm/vc4/vc4_dsi.c
drivers/gpu/drm/vc4/vc4_hdmi.c
drivers/gpu/drm/virtio/Kconfig
drivers/gpu/drm/virtio/Makefile
drivers/gpu/drm/virtio/virtgpu_drv.c
drivers/gpu/drm/virtio/virtgpu_drv.h
drivers/gpu/drm/virtio/virtgpu_fence.c
drivers/gpu/drm/virtio/virtgpu_gem.c
drivers/gpu/drm/virtio/virtgpu_ioctl.c
drivers/gpu/drm/virtio/virtgpu_kms.c
drivers/gpu/drm/virtio/virtgpu_object.c
drivers/gpu/drm/virtio/virtgpu_plane.c
drivers/gpu/drm/virtio/virtgpu_prime.c
drivers/gpu/drm/virtio/virtgpu_ttm.c [deleted file]
drivers/gpu/drm/virtio/virtgpu_vq.c
drivers/gpu/drm/vkms/vkms_crtc.c
drivers/gpu/drm/vkms/vkms_drv.c
drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
drivers/video/fbdev/core/fbmem.c
drivers/video/fbdev/sa1100fb.c
drivers/video/hdmi.c
include/drm/bridge/dw_hdmi.h
include/drm/drm_bridge.h
include/drm/drm_connector.h
include/drm/drm_crtc.h
include/drm/drm_dp_helper.h
include/drm/drm_dp_mst_helper.h
include/drm/drm_drv.h
include/drm/drm_encoder.h
include/drm/drm_fb_helper.h
include/drm/drm_gem_ttm_helper.h [new file with mode: 0644]
include/drm/drm_gem_vram_helper.h
include/drm/drm_modeset_helper_vtables.h
include/drm/drm_modeset_lock.h
include/drm/drm_panel.h
include/drm/drm_prime.h
include/drm/drm_print.h
include/drm/drm_rect.h
include/drm/drm_vblank.h
include/drm/drm_vram_mm_helper.h [deleted file]
include/drm/ttm/ttm_bo_driver.h
include/linux/fb.h
include/uapi/drm/v3d_drm.h

index 47950fced28d85ef079308ab750f733fd3d06ab7..dafc0980c4fa7a241722430c6df62f4f331d1601 100644 (file)
@@ -36,6 +36,9 @@ properties:
   resets:
     maxItems: 1
 
+  vcc-dsi-supply:
+    description: VCC-DSI power supply of the DSI encoder
+
   phys:
     maxItems: 1
 
@@ -64,6 +67,7 @@ required:
   - phys
   - phy-names
   - resets
+  - vcc-dsi-supply
   - port
 
 additionalProperties: false
@@ -79,6 +83,7 @@ examples:
         resets = <&ccu 4>;
         phys = <&dphy0>;
         phy-names = "dphy";
+        vcc-dsi-supply = <&reg_dcdc1>;
         #address-cells = <1>;
         #size-cells = <0>;
 
index dbd7c84ee58495f4adc88246115671ed905a11d9..17258747fff622d81480649eaa765d0db546be3c 100644 (file)
@@ -6,7 +6,11 @@ designed for portable devices.
 
 Required properties:
 
- - compatible          : "analogix,anx7814"
+ - compatible          : Must be one of:
+                         "analogix,anx7808"
+                         "analogix,anx7812"
+                         "analogix,anx7814"
+                         "analogix,anx7818"
  - reg                 : I2C address of the device
  - interrupts          : Should contain the INTP interrupt
  - hpd-gpios           : Which GPIO to use for hpd
index b664f054c259aa48810d27a8fc74482847e4c050..59619296c84bff029456bb6f9538bcf2d24aca12 100644 (file)
@@ -400,16 +400,13 @@ GEM VRAM Helper Functions Reference
 .. kernel-doc:: drivers/gpu/drm/drm_gem_vram_helper.c
    :export:
 
-VRAM MM Helper Functions Reference
-----------------------------------
+GEM TTM Helper Functions Reference
+-----------------------------------
 
-.. kernel-doc:: drivers/gpu/drm/drm_vram_mm_helper.c
+.. kernel-doc:: drivers/gpu/drm/drm_gem_ttm_helper.c
    :doc: overview
 
-.. kernel-doc:: include/drm/drm_vram_mm_helper.h
-   :internal:
-
-.. kernel-doc:: drivers/gpu/drm/drm_vram_mm_helper.c
+.. kernel-doc:: drivers/gpu/drm/drm_gem_ttm_helper.c
    :export:
 
 VMA Offset Manager
index 32787acff0a861115bfe52730b26a76368d4c408..8dc147c93c9cf34382ad766d9e3c66b8feeff2fb 100644 (file)
@@ -284,6 +284,18 @@ drm_fb_helper tasks
   removed: drm_fb_helper_single_add_all_connectors(),
   drm_fb_helper_add_one_connector() and drm_fb_helper_remove_one_connector().
 
+connector register/unregister fixes
+-----------------------------------
+
+- For most connectors it's a no-op to call drm_connector_register/unregister
+  directly from driver code, drm_dev_register/unregister take care of this
+  already. We can remove all of them.
+
+- For dp drivers it's a bit more a mess, since we need the connector to be
+  registered when calling drm_dp_aux_register. Fix this by instead calling
+  drm_dp_aux_init, and moving the actual registering into a late_register
+  callback as recommended in the kerneldoc.
+
 Core refactorings
 =================
 
index 296de2b51c832ecc1869a77624c964ce398a5236..94fb077c0817715e2891ee91f365cde48416e44a 100644 (file)
@@ -1272,6 +1272,8 @@ F:        Documentation/gpu/afbc.rst
 ARM MALI PANFROST DRM DRIVER
 M:     Rob Herring <robh@kernel.org>
 M:     Tomeu Vizoso <tomeu.vizoso@collabora.com>
+R:     Steven Price <steven.price@arm.com>
+R:     Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
 L:     dri-devel@lists.freedesktop.org
 S:     Supported
 T:     git git://anongit.freedesktop.org/drm/drm-misc
@@ -5376,12 +5378,22 @@ F:      include/linux/vga*
 
 DRM DRIVERS FOR ALLWINNER A10
 M:     Maxime Ripard <mripard@kernel.org>
+M:     Chen-Yu Tsai <wens@csie.org>
 L:     dri-devel@lists.freedesktop.org
 S:     Supported
 F:     drivers/gpu/drm/sun4i/
 F:     Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
 T:     git git://anongit.freedesktop.org/drm/drm-misc
 
+DRM DRIVER FOR ALLWINNER DE2 AND DE3 ENGINE
+M:     Maxime Ripard <mripard@kernel.org>
+M:     Chen-Yu Tsai <wens@csie.org>
+R:     Jernej Skrabec <jernej.skrabec@siol.net>
+L:     dri-devel@lists.freedesktop.org
+S:     Supported
+F:     drivers/gpu/drm/sun4i/sun8i*
+T:     git git://anongit.freedesktop.org/drm/drm-misc
+
 DRM DRIVERS FOR AMLOGIC SOCS
 M:     Neil Armstrong <narmstrong@baylibre.com>
 L:     dri-devel@lists.freedesktop.org
index 42a8f3f1168133424091f35e011f58c2e757b890..709002515550cd2e6ff989a4c2bdd11b5b0cdf9c 100644 (file)
@@ -471,7 +471,7 @@ unlock:
        if (pfence_excl)
                *pfence_excl = fence_excl;
        else if (fence_excl)
-               shared[++shared_count] = fence_excl;
+               shared[shared_count++] = fence_excl;
 
        if (!shared_count) {
                kfree(shared);
index e67c194c2acad020c2d7bf03137d8fdaa35e612f..caeef11976e84bc475e5cce963ed864075378e4b 100644 (file)
@@ -168,10 +168,16 @@ config DRM_TTM
 config DRM_VRAM_HELPER
        tristate
        depends on DRM
-       select DRM_TTM
        help
          Helpers for VRAM memory management
 
+config DRM_TTM_HELPER
+       tristate
+       depends on DRM
+       select DRM_TTM
+       help
+         Helpers for ttm-based gem objects
+
 config DRM_GEM_CMA_HELPER
        bool
        depends on DRM
index 82ff826b33ccd13f40680d1a9a35d2dcc111068e..9f1c7c486f88b500e0eae0f28e31f83d1bba7f3b 100644 (file)
@@ -33,10 +33,12 @@ drm-$(CONFIG_DEBUG_FS) += drm_debugfs.o drm_debugfs_crc.o
 drm-$(CONFIG_DRM_LOAD_EDID_FIRMWARE) += drm_edid_load.o
 
 drm_vram_helper-y := drm_gem_vram_helper.o \
-                    drm_vram_helper_common.o \
-                    drm_vram_mm_helper.o
+                    drm_vram_helper_common.o
 obj-$(CONFIG_DRM_VRAM_HELPER) += drm_vram_helper.o
 
+drm_ttm_helper-y := drm_gem_ttm_helper.o
+obj-$(CONFIG_DRM_TTM_HELPER) += drm_ttm_helper.o
+
 drm_kms_helper-y := drm_crtc_helper.o drm_dp_helper.o drm_dsc.o drm_probe_helper.o \
                drm_plane_helper.o drm_dp_mst_topology.o drm_atomic_helper.o \
                drm_kms_helper_common.o drm_dp_dual_mode_helper.o \
index ece55c8fa67333267f75dd41baaa70a3906e287b..d8729285f7310f510858a971559388b21f65a6a7 100644 (file)
@@ -217,11 +217,10 @@ amdgpu_connector_update_scratch_regs(struct drm_connector *connector,
        struct drm_encoder *encoder;
        const struct drm_connector_helper_funcs *connector_funcs = connector->helper_private;
        bool connected;
-       int i;
 
        best_encoder = connector_funcs->best_encoder(connector);
 
-       drm_connector_for_each_possible_encoder(connector, encoder, i) {
+       drm_connector_for_each_possible_encoder(connector, encoder) {
                if ((encoder == best_encoder) && (status == connector_status_connected))
                        connected = true;
                else
@@ -236,9 +235,8 @@ amdgpu_connector_find_encoder(struct drm_connector *connector,
                               int encoder_type)
 {
        struct drm_encoder *encoder;
-       int i;
 
-       drm_connector_for_each_possible_encoder(connector, encoder, i) {
+       drm_connector_for_each_possible_encoder(connector, encoder) {
                if (encoder->encoder_type == encoder_type)
                        return encoder;
        }
@@ -347,10 +345,9 @@ static struct drm_encoder *
 amdgpu_connector_best_single_encoder(struct drm_connector *connector)
 {
        struct drm_encoder *encoder;
-       int i;
 
        /* pick the first one */
-       drm_connector_for_each_possible_encoder(connector, encoder, i)
+       drm_connector_for_each_possible_encoder(connector, encoder)
                return encoder;
 
        return NULL;
@@ -1065,9 +1062,8 @@ amdgpu_connector_dvi_detect(struct drm_connector *connector, bool force)
        /* find analog encoder */
        if (amdgpu_connector->dac_load_detect) {
                struct drm_encoder *encoder;
-               int i;
 
-               drm_connector_for_each_possible_encoder(connector, encoder, i) {
+               drm_connector_for_each_possible_encoder(connector, encoder) {
                        if (encoder->encoder_type != DRM_MODE_ENCODER_DAC &&
                            encoder->encoder_type != DRM_MODE_ENCODER_TVDAC)
                                continue;
@@ -1117,9 +1113,8 @@ amdgpu_connector_dvi_encoder(struct drm_connector *connector)
 {
        struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector);
        struct drm_encoder *encoder;
-       int i;
 
-       drm_connector_for_each_possible_encoder(connector, encoder, i) {
+       drm_connector_for_each_possible_encoder(connector, encoder) {
                if (amdgpu_connector->use_digital == true) {
                        if (encoder->encoder_type == DRM_MODE_ENCODER_TMDS)
                                return encoder;
@@ -1134,7 +1129,7 @@ amdgpu_connector_dvi_encoder(struct drm_connector *connector)
 
        /* then check use digitial */
        /* pick the first one */
-       drm_connector_for_each_possible_encoder(connector, encoder, i)
+       drm_connector_for_each_possible_encoder(connector, encoder)
                return encoder;
 
        return NULL;
@@ -1271,9 +1266,8 @@ u16 amdgpu_connector_encoder_get_dp_bridge_encoder_id(struct drm_connector *conn
 {
        struct drm_encoder *encoder;
        struct amdgpu_encoder *amdgpu_encoder;
-       int i;
 
-       drm_connector_for_each_possible_encoder(connector, encoder, i) {
+       drm_connector_for_each_possible_encoder(connector, encoder) {
                amdgpu_encoder = to_amdgpu_encoder(encoder);
 
                switch (amdgpu_encoder->encoder_id) {
@@ -1292,10 +1286,9 @@ static bool amdgpu_connector_encoder_is_hbr2(struct drm_connector *connector)
 {
        struct drm_encoder *encoder;
        struct amdgpu_encoder *amdgpu_encoder;
-       int i;
        bool found = false;
 
-       drm_connector_for_each_possible_encoder(connector, encoder, i) {
+       drm_connector_for_each_possible_encoder(connector, encoder) {
                amdgpu_encoder = to_amdgpu_encoder(encoder);
                if (amdgpu_encoder->caps & ATOM_ENCODER_CAP_RECORD_HBR2)
                        found = true;
index 264677ab248a1af2d3a816132b64aca4d4ffd567..3fae1007143e398b5dd1261be472741ffe20f957 100644 (file)
@@ -1048,7 +1048,7 @@ static int amdgpu_pci_probe(struct pci_dev *pdev,
        }
 
        /* Get rid of things like offb */
-       ret = drm_fb_helper_remove_conflicting_pci_framebuffers(pdev, 0, "amdgpudrmfb");
+       ret = drm_fb_helper_remove_conflicting_pci_framebuffers(pdev, "amdgpudrmfb");
        if (ret)
                return ret;
 
index dff41d0a85fe969b7bc96323ba66d235d210fed3..8e867b8b432f3f0f0cc985579f7af70e8cfd0778 100644 (file)
@@ -1731,6 +1731,7 @@ int amdgpu_ttm_init(struct amdgpu_device *adev)
        r = ttm_bo_device_init(&adev->mman.bdev,
                               &amdgpu_bo_driver,
                               adev->ddev->anon_inode->i_mapping,
+                              adev->ddev->vma_offset_manager,
                               dma_addressing_limited(adev->dev));
        if (r) {
                DRM_ERROR("failed initializing buffer object driver(%d).\n", r);
index c9608ae8643b64b0a7eb5ba585b683a1a5a189c8..e4f94863332c1caf47f97d80c7b68198cea0b954 100644 (file)
@@ -260,15 +260,14 @@ static struct drm_encoder *
 dce_virtual_encoder(struct drm_connector *connector)
 {
        struct drm_encoder *encoder;
-       int i;
 
-       drm_connector_for_each_possible_encoder(connector, encoder, i) {
+       drm_connector_for_each_possible_encoder(connector, encoder) {
                if (encoder->encoder_type == DRM_MODE_ENCODER_VIRTUAL)
                        return encoder;
        }
 
        /* pick the first one */
-       drm_connector_for_each_possible_encoder(connector, encoder, i)
+       drm_connector_for_each_possible_encoder(connector, encoder)
                return encoder;
 
        return NULL;
index 8cab6da512a065b5c1f9c0bd5a0c86cce8238fd2..f4e0f27a76de4ebc970849b620f47c7069eb2ea7 100644 (file)
@@ -4839,7 +4839,13 @@ static int to_drm_connector_type(enum signal_type st)
 
 static struct drm_encoder *amdgpu_dm_connector_to_encoder(struct drm_connector *connector)
 {
-       return drm_encoder_find(connector->dev, NULL, connector->encoder_ids[0]);
+       struct drm_encoder *encoder;
+
+       /* There is only one encoder per connector */
+       drm_connector_for_each_possible_encoder(connector, encoder)
+               return encoder;
+
+       return NULL;
 }
 
 static void amdgpu_dm_get_native_mode(struct drm_connector *connector)
index 16218a202b591c022b79191e8f79a91e952ef163..5ec14efd4d8cb5cdb774a675c7d6bf2481ae89e3 100644 (file)
@@ -416,7 +416,7 @@ void amdgpu_dm_initialize_dp_connector(struct amdgpu_display_manager *dm,
 
        drm_dp_aux_register(&aconnector->dm_dp_aux.aux);
        drm_dp_cec_register_connector(&aconnector->dm_dp_aux.aux,
-                                     aconnector->base.name, dm->adev->dev);
+                                     &aconnector->base);
        aconnector->mst_mgr.cbs = &dm_mst_cbs;
        drm_dp_mst_topology_mgr_init(
                &aconnector->mst_mgr,
index 98aac743cc26200ff46aec1e8c283a02075512aa..8fd7094beecef24efed1ccbe219a329330292057 100644 (file)
@@ -5,6 +5,7 @@
  * Copyright (C) 2016 Synopsys, Inc. (www.synopsys.com)
  */
 
+#include <drm/drm_bridge.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_encoder.h>
 #include <drm/drm_device.h>
index cec0639e3aa1fc8cdd6c846759bb9212444133c9..e87ff8623076c8e69b846fb98879ebb7127273ad 100644 (file)
@@ -12,3 +12,9 @@ config DRM_KOMEDA
          Processor driver. It supports the D71 variants of the hardware.
 
          If compiled as a module it will be called komeda.
+
+config DRM_KOMEDA_ERROR_PRINT
+       bool "Enable komeda error print"
+       depends on DRM_KOMEDA
+       help
+         Choose this option to enable error printing.
index 5c3900c2e764feac9a6ea5d932a0af2f0821c00d..f095a1c68ac7b1859bcacbd408ba8ef268a38663 100644 (file)
@@ -22,4 +22,6 @@ komeda-y += \
        d71/d71_dev.o \
        d71/d71_component.o
 
+komeda-$(CONFIG_DRM_KOMEDA_ERROR_PRINT) += komeda_event.o
+
 obj-$(CONFIG_DRM_KOMEDA) += komeda.o
index 55a8cc94808a1ac36ff81765e765c24e38882353..c3d29c0b051bd44a8002eadba417bbd94c08fca8 100644 (file)
@@ -1218,6 +1218,90 @@ int d71_probe_block(struct d71_dev *d71,
        return err;
 }
 
+static void d71_gcu_dump(struct d71_dev *d71, struct seq_file *sf)
+{
+       u32 v[5];
+
+       seq_puts(sf, "\n------ GCU ------\n");
+
+       get_values_from_reg(d71->gcu_addr, 0, 3, v);
+       seq_printf(sf, "GLB_ARCH_ID:\t\t0x%X\n", v[0]);
+       seq_printf(sf, "GLB_CORE_ID:\t\t0x%X\n", v[1]);
+       seq_printf(sf, "GLB_CORE_INFO:\t\t0x%X\n", v[2]);
+
+       get_values_from_reg(d71->gcu_addr, 0x10, 1, v);
+       seq_printf(sf, "GLB_IRQ_STATUS:\t\t0x%X\n", v[0]);
+
+       get_values_from_reg(d71->gcu_addr, 0xA0, 5, v);
+       seq_printf(sf, "GCU_IRQ_RAW_STATUS:\t0x%X\n", v[0]);
+       seq_printf(sf, "GCU_IRQ_CLEAR:\t\t0x%X\n", v[1]);
+       seq_printf(sf, "GCU_IRQ_MASK:\t\t0x%X\n", v[2]);
+       seq_printf(sf, "GCU_IRQ_STATUS:\t\t0x%X\n", v[3]);
+       seq_printf(sf, "GCU_STATUS:\t\t0x%X\n", v[4]);
+
+       get_values_from_reg(d71->gcu_addr, 0xD0, 3, v);
+       seq_printf(sf, "GCU_CONTROL:\t\t0x%X\n", v[0]);
+       seq_printf(sf, "GCU_CONFIG_VALID0:\t0x%X\n", v[1]);
+       seq_printf(sf, "GCU_CONFIG_VALID1:\t0x%X\n", v[2]);
+}
+
+static void d71_lpu_dump(struct d71_pipeline *pipe, struct seq_file *sf)
+{
+       u32 v[6];
+
+       seq_printf(sf, "\n------ LPU%d ------\n", pipe->base.id);
+
+       dump_block_header(sf, pipe->lpu_addr);
+
+       get_values_from_reg(pipe->lpu_addr, 0xA0, 6, v);
+       seq_printf(sf, "LPU_IRQ_RAW_STATUS:\t0x%X\n", v[0]);
+       seq_printf(sf, "LPU_IRQ_CLEAR:\t\t0x%X\n", v[1]);
+       seq_printf(sf, "LPU_IRQ_MASK:\t\t0x%X\n", v[2]);
+       seq_printf(sf, "LPU_IRQ_STATUS:\t\t0x%X\n", v[3]);
+       seq_printf(sf, "LPU_STATUS:\t\t0x%X\n", v[4]);
+       seq_printf(sf, "LPU_TBU_STATUS:\t\t0x%X\n", v[5]);
+
+       get_values_from_reg(pipe->lpu_addr, 0xC0, 1, v);
+       seq_printf(sf, "LPU_INFO:\t\t0x%X\n", v[0]);
+
+       get_values_from_reg(pipe->lpu_addr, 0xD0, 3, v);
+       seq_printf(sf, "LPU_RAXI_CONTROL:\t0x%X\n", v[0]);
+       seq_printf(sf, "LPU_WAXI_CONTROL:\t0x%X\n", v[1]);
+       seq_printf(sf, "LPU_TBU_CONTROL:\t0x%X\n", v[2]);
+}
+
+static void d71_dou_dump(struct d71_pipeline *pipe, struct seq_file *sf)
+{
+       u32 v[5];
+
+       seq_printf(sf, "\n------ DOU%d ------\n", pipe->base.id);
+
+       dump_block_header(sf, pipe->dou_addr);
+
+       get_values_from_reg(pipe->dou_addr, 0xA0, 5, v);
+       seq_printf(sf, "DOU_IRQ_RAW_STATUS:\t0x%X\n", v[0]);
+       seq_printf(sf, "DOU_IRQ_CLEAR:\t\t0x%X\n", v[1]);
+       seq_printf(sf, "DOU_IRQ_MASK:\t\t0x%X\n", v[2]);
+       seq_printf(sf, "DOU_IRQ_STATUS:\t\t0x%X\n", v[3]);
+       seq_printf(sf, "DOU_STATUS:\t\t0x%X\n", v[4]);
+}
+
+static void d71_pipeline_dump(struct komeda_pipeline *pipe, struct seq_file *sf)
+{
+       struct d71_pipeline *d71_pipe = to_d71_pipeline(pipe);
+
+       d71_lpu_dump(d71_pipe, sf);
+       d71_dou_dump(d71_pipe, sf);
+}
+
 const struct komeda_pipeline_funcs d71_pipeline_funcs = {
-       .downscaling_clk_check = d71_downscaling_clk_check,
+       .downscaling_clk_check  = d71_downscaling_clk_check,
+       .dump_register          = d71_pipeline_dump,
 };
+
+void d71_dump(struct komeda_dev *mdev, struct seq_file *sf)
+{
+       struct d71_dev *d71 = mdev->chip_data;
+
+       d71_gcu_dump(d71, sf);
+}
index d567ab7ed314e28d029184cf4b5e3752bed0f336..822b23a1ce75a826a4c3d58a69175faea039a922 100644 (file)
@@ -195,7 +195,7 @@ d71_irq_handler(struct komeda_dev *mdev, struct komeda_events *evts)
        if (gcu_status & GLB_IRQ_STATUS_PIPE1)
                evts->pipes[1] |= get_pipeline_event(d71->pipes[1], gcu_status);
 
-       return gcu_status ? IRQ_HANDLED : IRQ_NONE;
+       return IRQ_RETVAL(gcu_status);
 }
 
 #define ENABLED_GCU_IRQS       (GCU_IRQ_CVAL0 | GCU_IRQ_CVAL1 | \
@@ -395,6 +395,22 @@ static int d71_enum_resources(struct komeda_dev *mdev)
                        err = PTR_ERR(pipe);
                        goto err_cleanup;
                }
+
+               /* D71 HW doesn't update shadow registers when display output
+                * is turning off, so when we disable all pipeline components
+                * together with display output disable by one flush or one
+                * operation, the disable operation updated registers will not
+                * be flush to or valid in HW, which may leads problem.
+                * To workaround this problem, introduce a two phase disable.
+                * Phase1: Disabling components with display is on to make sure
+                *         the disable can be flushed to HW.
+                * Phase2: Only turn-off display output.
+                */
+               value = KOMEDA_PIPELINE_IMPROCS |
+                       BIT(KOMEDA_COMPONENT_TIMING_CTRLR);
+
+               pipe->standalone_disabled_comps = value;
+
                d71->pipes[i] = to_d71_pipeline(pipe);
        }
 
@@ -561,17 +577,18 @@ static int d71_disconnect_iommu(struct komeda_dev *mdev)
 }
 
 static const struct komeda_dev_funcs d71_chip_funcs = {
-       .init_format_table = d71_init_fmt_tbl,
-       .enum_resources = d71_enum_resources,
-       .cleanup        = d71_cleanup,
-       .irq_handler    = d71_irq_handler,
-       .enable_irq     = d71_enable_irq,
-       .disable_irq    = d71_disable_irq,
-       .on_off_vblank  = d71_on_off_vblank,
-       .change_opmode  = d71_change_opmode,
-       .flush          = d71_flush,
-       .connect_iommu  = d71_connect_iommu,
-       .disconnect_iommu = d71_disconnect_iommu,
+       .init_format_table      = d71_init_fmt_tbl,
+       .enum_resources         = d71_enum_resources,
+       .cleanup                = d71_cleanup,
+       .irq_handler            = d71_irq_handler,
+       .enable_irq             = d71_enable_irq,
+       .disable_irq            = d71_disable_irq,
+       .on_off_vblank          = d71_on_off_vblank,
+       .change_opmode          = d71_change_opmode,
+       .flush                  = d71_flush,
+       .connect_iommu          = d71_connect_iommu,
+       .disconnect_iommu       = d71_disconnect_iommu,
+       .dump_register          = d71_dump,
 };
 
 const struct komeda_dev_funcs *
index 84f1878b647d6f4d4683f7020da9f84f57fa0ef8..c7357c2b9e6246c899a9686f7e47e9a91828ec49 100644 (file)
@@ -49,4 +49,6 @@ int d71_probe_block(struct d71_dev *d71,
                    struct block_header *blk, u32 __iomem *reg);
 void d71_read_block_header(u32 __iomem *reg, struct block_header *blk);
 
+void d71_dump(struct komeda_dev *mdev, struct seq_file *sf);
+
 #endif /* !_D71_DEV_H_ */
index 624d257da20f8124dce0b0ee699460651a88201d..75263d8cd0bdea114fb72695a4442242c671bd70 100644 (file)
@@ -5,7 +5,6 @@
  *
  */
 #include <linux/clk.h>
-#include <linux/pm_runtime.h>
 #include <linux/spinlock.h>
 
 #include <drm/drm_atomic.h>
@@ -250,23 +249,57 @@ komeda_crtc_atomic_enable(struct drm_crtc *crtc,
 {
        komeda_crtc_prepare(to_kcrtc(crtc));
        drm_crtc_vblank_on(crtc);
+       WARN_ON(drm_crtc_vblank_get(crtc));
        komeda_crtc_do_flush(crtc, old);
 }
 
+static void
+komeda_crtc_flush_and_wait_for_flip_done(struct komeda_crtc *kcrtc,
+                                        struct completion *input_flip_done)
+{
+       struct drm_device *drm = kcrtc->base.dev;
+       struct komeda_dev *mdev = kcrtc->master->mdev;
+       struct completion *flip_done;
+       struct completion temp;
+       int timeout;
+
+       /* if caller doesn't send a flip_done, use a private flip_done */
+       if (input_flip_done) {
+               flip_done = input_flip_done;
+       } else {
+               init_completion(&temp);
+               kcrtc->disable_done = &temp;
+               flip_done = &temp;
+       }
+
+       mdev->funcs->flush(mdev, kcrtc->master->id, 0);
+
+       /* wait the flip take affect.*/
+       timeout = wait_for_completion_timeout(flip_done, HZ);
+       if (timeout == 0) {
+               DRM_ERROR("wait pipe%d flip done timeout\n", kcrtc->master->id);
+               if (!input_flip_done) {
+                       unsigned long flags;
+
+                       spin_lock_irqsave(&drm->event_lock, flags);
+                       kcrtc->disable_done = NULL;
+                       spin_unlock_irqrestore(&drm->event_lock, flags);
+               }
+       }
+}
+
 static void
 komeda_crtc_atomic_disable(struct drm_crtc *crtc,
                           struct drm_crtc_state *old)
 {
        struct komeda_crtc *kcrtc = to_kcrtc(crtc);
        struct komeda_crtc_state *old_st = to_kcrtc_st(old);
-       struct komeda_dev *mdev = crtc->dev->dev_private;
        struct komeda_pipeline *master = kcrtc->master;
        struct komeda_pipeline *slave  = kcrtc->slave;
        struct completion *disable_done = &crtc->state->commit->flip_done;
-       struct completion temp;
-       int timeout;
+       bool needs_phase2 = false;
 
-       DRM_DEBUG_ATOMIC("CRTC%d_DISABLE: active_pipes: 0x%x, affected: 0x%x.\n",
+       DRM_DEBUG_ATOMIC("CRTC%d_DISABLE: active_pipes: 0x%x, affected: 0x%x\n",
                         drm_crtc_index(crtc),
                         old_st->active_pipes, old_st->affected_pipes);
 
@@ -274,7 +307,7 @@ komeda_crtc_atomic_disable(struct drm_crtc *crtc,
                komeda_pipeline_disable(slave, old->state);
 
        if (has_bit(master->id, old_st->active_pipes))
-               komeda_pipeline_disable(master, old->state);
+               needs_phase2 = komeda_pipeline_disable(master, old->state);
 
        /* crtc_disable has two scenarios according to the state->active switch.
         * 1. active -> inactive
@@ -293,32 +326,23 @@ komeda_crtc_atomic_disable(struct drm_crtc *crtc,
         *    That's also the reason why skip modeset commit in
         *    komeda_crtc_atomic_flush()
         */
-       if (crtc->state->active) {
-               struct komeda_pipeline_state *pipe_st;
-               /* clear the old active_comps to zero */
-               pipe_st = komeda_pipeline_get_old_state(master, old->state);
-               pipe_st->active_comps = 0;
+       disable_done = (needs_phase2 || crtc->state->active) ?
+                      NULL : &crtc->state->commit->flip_done;
 
-               init_completion(&temp);
-               kcrtc->disable_done = &temp;
-               disable_done = &temp;
-       }
+       /* wait phase 1 disable done */
+       komeda_crtc_flush_and_wait_for_flip_done(kcrtc, disable_done);
 
-       mdev->funcs->flush(mdev, master->id, 0);
+       /* phase 2 */
+       if (needs_phase2) {
+               komeda_pipeline_disable(kcrtc->master, old->state);
 
-       /* wait the disable take affect.*/
-       timeout = wait_for_completion_timeout(disable_done, HZ);
-       if (timeout == 0) {
-               DRM_ERROR("disable pipeline%d timeout.\n", kcrtc->master->id);
-               if (crtc->state->active) {
-                       unsigned long flags;
+               disable_done = crtc->state->active ?
+                              NULL : &crtc->state->commit->flip_done;
 
-                       spin_lock_irqsave(&crtc->dev->event_lock, flags);
-                       kcrtc->disable_done = NULL;
-                       spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
-               }
+               komeda_crtc_flush_and_wait_for_flip_done(kcrtc, disable_done);
        }
 
+       drm_crtc_vblank_put(crtc);
        drm_crtc_vblank_off(crtc);
        komeda_crtc_unprepare(kcrtc);
 }
index ca64a129c594ecc31f951cbc6ce5b903290501e0..937a6d4c486571d06ca61a343d656f857caf5ed6 100644 (file)
@@ -25,6 +25,8 @@ static int komeda_register_show(struct seq_file *sf, void *x)
        struct komeda_dev *mdev = sf->private;
        int i;
 
+       seq_puts(sf, "\n====== Komeda register dump =========\n");
+
        if (mdev->funcs->dump_register)
                mdev->funcs->dump_register(mdev, sf);
 
@@ -91,9 +93,19 @@ config_id_show(struct device *dev, struct device_attribute *attr, char *buf)
 }
 static DEVICE_ATTR_RO(config_id);
 
+static ssize_t
+aclk_hz_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       struct komeda_dev *mdev = dev_to_mdev(dev);
+
+       return snprintf(buf, PAGE_SIZE, "%lu\n", clk_get_rate(mdev->aclk));
+}
+static DEVICE_ATTR_RO(aclk_hz);
+
 static struct attribute *komeda_sysfs_entries[] = {
        &dev_attr_core_id.attr,
        &dev_attr_config_id.attr,
+       &dev_attr_aclk_hz.attr,
        NULL,
 };
 
@@ -216,7 +228,7 @@ struct komeda_dev *komeda_dev_create(struct device *dev)
                          product->product_id,
                          MALIDP_CORE_ID_PRODUCT_ID(mdev->chip.core_id));
                err = -ENODEV;
-               goto err_cleanup;
+               goto disable_clk;
        }
 
        DRM_INFO("Found ARM Mali-D%x version r%dp%d\n",
@@ -229,19 +241,19 @@ struct komeda_dev *komeda_dev_create(struct device *dev)
        err = mdev->funcs->enum_resources(mdev);
        if (err) {
                DRM_ERROR("enumerate display resource failed.\n");
-               goto err_cleanup;
+               goto disable_clk;
        }
 
        err = komeda_parse_dt(dev, mdev);
        if (err) {
                DRM_ERROR("parse device tree failed.\n");
-               goto err_cleanup;
+               goto disable_clk;
        }
 
        err = komeda_assemble_pipelines(mdev);
        if (err) {
                DRM_ERROR("assemble display pipelines failed.\n");
-               goto err_cleanup;
+               goto disable_clk;
        }
 
        dev->dma_parms = &mdev->dma_parms;
@@ -254,11 +266,14 @@ struct komeda_dev *komeda_dev_create(struct device *dev)
        if (mdev->iommu && mdev->funcs->connect_iommu) {
                err = mdev->funcs->connect_iommu(mdev);
                if (err) {
+                       DRM_ERROR("connect iommu failed.\n");
                        mdev->iommu = NULL;
-                       goto err_cleanup;
+                       goto disable_clk;
                }
        }
 
+       clk_disable_unprepare(mdev->aclk);
+
        err = sysfs_create_group(&dev->kobj, &komeda_sysfs_attr_group);
        if (err) {
                DRM_ERROR("create sysfs group failed.\n");
@@ -271,6 +286,8 @@ struct komeda_dev *komeda_dev_create(struct device *dev)
 
        return mdev;
 
+disable_clk:
+       clk_disable_unprepare(mdev->aclk);
 err_cleanup:
        komeda_dev_destroy(mdev);
        return ERR_PTR(err);
@@ -288,8 +305,12 @@ void komeda_dev_destroy(struct komeda_dev *mdev)
        debugfs_remove_recursive(mdev->debugfs_root);
 #endif
 
+       if (mdev->aclk)
+               clk_prepare_enable(mdev->aclk);
+
        if (mdev->iommu && mdev->funcs->disconnect_iommu)
-               mdev->funcs->disconnect_iommu(mdev);
+               if (mdev->funcs->disconnect_iommu(mdev))
+                       DRM_ERROR("disconnect iommu failed.\n");
        mdev->iommu = NULL;
 
        for (i = 0; i < mdev->n_pipelines; i++) {
@@ -317,3 +338,47 @@ void komeda_dev_destroy(struct komeda_dev *mdev)
 
        devm_kfree(dev, mdev);
 }
+
+int komeda_dev_resume(struct komeda_dev *mdev)
+{
+       int ret = 0;
+
+       clk_prepare_enable(mdev->aclk);
+
+       if (mdev->iommu && mdev->funcs->connect_iommu) {
+               ret = mdev->funcs->connect_iommu(mdev);
+               if (ret < 0) {
+                       DRM_ERROR("connect iommu failed.\n");
+                       goto disable_clk;
+               }
+       }
+
+       ret = mdev->funcs->enable_irq(mdev);
+
+disable_clk:
+       clk_disable_unprepare(mdev->aclk);
+
+       return ret;
+}
+
+int komeda_dev_suspend(struct komeda_dev *mdev)
+{
+       int ret = 0;
+
+       clk_prepare_enable(mdev->aclk);
+
+       if (mdev->iommu && mdev->funcs->disconnect_iommu) {
+               ret = mdev->funcs->disconnect_iommu(mdev);
+               if (ret < 0) {
+                       DRM_ERROR("disconnect iommu failed.\n");
+                       goto disable_clk;
+               }
+       }
+
+       ret = mdev->funcs->disable_irq(mdev);
+
+disable_clk:
+       clk_disable_unprepare(mdev->aclk);
+
+       return ret;
+}
index d1c86b6174c808a109b9718e79575d9f6096fb92..414200233b64b4441dfa38d9cf58313ac7a1e374 100644 (file)
 #define KOMEDA_ERR_TTNG                        BIT_ULL(30)
 #define KOMEDA_ERR_TTF                 BIT_ULL(31)
 
+#define KOMEDA_ERR_EVENTS      \
+       (KOMEDA_EVENT_URUN      | KOMEDA_EVENT_IBSY     | KOMEDA_EVENT_OVR |\
+       KOMEDA_ERR_TETO         | KOMEDA_ERR_TEMR       | KOMEDA_ERR_TITR |\
+       KOMEDA_ERR_CPE          | KOMEDA_ERR_CFGE       | KOMEDA_ERR_AXIE |\
+       KOMEDA_ERR_ACE0         | KOMEDA_ERR_ACE1       | KOMEDA_ERR_ACE2 |\
+       KOMEDA_ERR_ACE3         | KOMEDA_ERR_DRIFTTO    | KOMEDA_ERR_FRAMETO |\
+       KOMEDA_ERR_ZME          | KOMEDA_ERR_MERR       | KOMEDA_ERR_TCF |\
+       KOMEDA_ERR_TTNG         | KOMEDA_ERR_TTF)
+
+#define KOMEDA_WARN_EVENTS     KOMEDA_ERR_CSCE
+
 /* malidp device id */
 enum {
        MALI_D71 = 0,
@@ -207,4 +218,13 @@ void komeda_dev_destroy(struct komeda_dev *mdev);
 
 struct komeda_dev *dev_to_mdev(struct device *dev);
 
+#ifdef CONFIG_DRM_KOMEDA_ERROR_PRINT
+void komeda_print_events(struct komeda_events *evts);
+#else
+static inline void komeda_print_events(struct komeda_events *evts) {}
+#endif
+
+int komeda_dev_resume(struct komeda_dev *mdev);
+int komeda_dev_suspend(struct komeda_dev *mdev);
+
 #endif /*_KOMEDA_DEV_H_*/
index 69ace6f9055d3c9c0e3399d776e4222510992c89..d6c2222c5d3305928cd806078bcdbdacccef203c 100644 (file)
@@ -8,6 +8,7 @@
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
 #include <linux/component.h>
+#include <linux/pm_runtime.h>
 #include <drm/drm_of.h>
 #include "komeda_dev.h"
 #include "komeda_kms.h"
@@ -136,13 +137,40 @@ static const struct of_device_id komeda_of_match[] = {
 
 MODULE_DEVICE_TABLE(of, komeda_of_match);
 
+static int __maybe_unused komeda_pm_suspend(struct device *dev)
+{
+       struct komeda_drv *mdrv = dev_get_drvdata(dev);
+       struct drm_device *drm = &mdrv->kms->base;
+       int res;
+
+       res = drm_mode_config_helper_suspend(drm);
+
+       komeda_dev_suspend(mdrv->mdev);
+
+       return res;
+}
+
+static int __maybe_unused komeda_pm_resume(struct device *dev)
+{
+       struct komeda_drv *mdrv = dev_get_drvdata(dev);
+       struct drm_device *drm = &mdrv->kms->base;
+
+       komeda_dev_resume(mdrv->mdev);
+
+       return drm_mode_config_helper_resume(drm);
+}
+
+static const struct dev_pm_ops komeda_pm_ops = {
+       SET_SYSTEM_SLEEP_PM_OPS(komeda_pm_suspend, komeda_pm_resume)
+};
+
 static struct platform_driver komeda_platform_driver = {
        .probe  = komeda_platform_probe,
        .remove = komeda_platform_remove,
        .driver = {
                .name = "komeda",
                .of_match_table = komeda_of_match,
-               .pm = NULL,
+               .pm = &komeda_pm_ops,
        },
 };
 
diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_event.c b/drivers/gpu/drm/arm/display/komeda/komeda_event.c
new file mode 100644 (file)
index 0000000..a36fb86
--- /dev/null
@@ -0,0 +1,140 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * (C) COPYRIGHT 2019 ARM Limited. All rights reserved.
+ * Author: James.Qian.Wang <james.qian.wang@arm.com>
+ *
+ */
+#include <drm/drm_print.h>
+
+#include "komeda_dev.h"
+
+struct komeda_str {
+       char *str;
+       u32 sz;
+       u32 len;
+};
+
+/* return 0 on success,  < 0 on no space.
+ */
+static int komeda_sprintf(struct komeda_str *str, const char *fmt, ...)
+{
+       va_list args;
+       int num, free_sz;
+       int err;
+
+       free_sz = str->sz - str->len - 1;
+       if (free_sz <= 0)
+               return -ENOSPC;
+
+       va_start(args, fmt);
+
+       num = vsnprintf(str->str + str->len, free_sz, fmt, args);
+
+       va_end(args);
+
+       if (num < free_sz) {
+               str->len += num;
+               err = 0;
+       } else {
+               str->len = str->sz - 1;
+               err = -ENOSPC;
+       }
+
+       return err;
+}
+
+static void evt_sprintf(struct komeda_str *str, u64 evt, const char *msg)
+{
+       if (evt)
+               komeda_sprintf(str, msg);
+}
+
+static void evt_str(struct komeda_str *str, u64 events)
+{
+       if (events == 0ULL) {
+               komeda_sprintf(str, "None");
+               return;
+       }
+
+       evt_sprintf(str, events & KOMEDA_EVENT_VSYNC, "VSYNC|");
+       evt_sprintf(str, events & KOMEDA_EVENT_FLIP, "FLIP|");
+       evt_sprintf(str, events & KOMEDA_EVENT_EOW, "EOW|");
+       evt_sprintf(str, events & KOMEDA_EVENT_MODE, "OP-MODE|");
+
+       evt_sprintf(str, events & KOMEDA_EVENT_URUN, "UNDERRUN|");
+       evt_sprintf(str, events & KOMEDA_EVENT_OVR, "OVERRUN|");
+
+       /* GLB error */
+       evt_sprintf(str, events & KOMEDA_ERR_MERR, "MERR|");
+       evt_sprintf(str, events & KOMEDA_ERR_FRAMETO, "FRAMETO|");
+
+       /* DOU error */
+       evt_sprintf(str, events & KOMEDA_ERR_DRIFTTO, "DRIFTTO|");
+       evt_sprintf(str, events & KOMEDA_ERR_FRAMETO, "FRAMETO|");
+       evt_sprintf(str, events & KOMEDA_ERR_TETO, "TETO|");
+       evt_sprintf(str, events & KOMEDA_ERR_CSCE, "CSCE|");
+
+       /* LPU errors or events */
+       evt_sprintf(str, events & KOMEDA_EVENT_IBSY, "IBSY|");
+       evt_sprintf(str, events & KOMEDA_ERR_AXIE, "AXIE|");
+       evt_sprintf(str, events & KOMEDA_ERR_ACE0, "ACE0|");
+       evt_sprintf(str, events & KOMEDA_ERR_ACE1, "ACE1|");
+       evt_sprintf(str, events & KOMEDA_ERR_ACE2, "ACE2|");
+       evt_sprintf(str, events & KOMEDA_ERR_ACE3, "ACE3|");
+
+       /* LPU TBU errors*/
+       evt_sprintf(str, events & KOMEDA_ERR_TCF, "TCF|");
+       evt_sprintf(str, events & KOMEDA_ERR_TTNG, "TTNG|");
+       evt_sprintf(str, events & KOMEDA_ERR_TITR, "TITR|");
+       evt_sprintf(str, events & KOMEDA_ERR_TEMR, "TEMR|");
+       evt_sprintf(str, events & KOMEDA_ERR_TTF, "TTF|");
+
+       /* CU errors*/
+       evt_sprintf(str, events & KOMEDA_ERR_CPE, "COPROC|");
+       evt_sprintf(str, events & KOMEDA_ERR_ZME, "ZME|");
+       evt_sprintf(str, events & KOMEDA_ERR_CFGE, "CFGE|");
+       evt_sprintf(str, events & KOMEDA_ERR_TEMR, "TEMR|");
+
+       if (str->len > 0 && (str->str[str->len - 1] == '|')) {
+               str->str[str->len - 1] = 0;
+               str->len--;
+       }
+}
+
+static bool is_new_frame(struct komeda_events *a)
+{
+       return (a->pipes[0] | a->pipes[1]) &
+              (KOMEDA_EVENT_FLIP | KOMEDA_EVENT_EOW);
+}
+
+void komeda_print_events(struct komeda_events *evts)
+{
+       u64 print_evts = KOMEDA_ERR_EVENTS;
+       static bool en_print = true;
+
+       /* reduce the same msg print, only print the first evt for one frame */
+       if (evts->global || is_new_frame(evts))
+               en_print = true;
+       if (!en_print)
+               return;
+
+       if ((evts->global | evts->pipes[0] | evts->pipes[1]) & print_evts) {
+               char msg[256];
+               struct komeda_str str;
+
+               str.str = msg;
+               str.sz  = sizeof(msg);
+               str.len = 0;
+
+               komeda_sprintf(&str, "gcu: ");
+               evt_str(&str, evts->global);
+               komeda_sprintf(&str, ", pipes[0]: ");
+               evt_str(&str, evts->pipes[0]);
+               komeda_sprintf(&str, ", pipes[1]: ");
+               evt_str(&str, evts->pipes[1]);
+
+               DRM_ERROR("err detect: %s\n", msg);
+
+               en_print = false;
+       }
+}
index 8820ce15ce375df111338db44d59821018cfc51c..d49772de93e09207d844a1499a863118d9b0852e 100644 (file)
@@ -48,6 +48,8 @@ static irqreturn_t komeda_kms_irq_handler(int irq, void *data)
        memset(&evts, 0, sizeof(evts));
        status = mdev->funcs->irq_handler(mdev, &evts);
 
+       komeda_print_events(&evts);
+
        /* Notify the crtc to handle the events */
        for (i = 0; i < kms->n_crtcs; i++)
                komeda_crtc_handle_event(&kms->crtcs[i], &evts);
index cf5bea578ad924e054bd66a270165b1ecbd09dd7..b322f52ba8f2956030377b82d2884a2212349036 100644 (file)
@@ -389,6 +389,18 @@ struct komeda_pipeline {
        int id;
        /** @avail_comps: available components mask of pipeline */
        u32 avail_comps;
+       /**
+        * @standalone_disabled_comps:
+        *
+        * When disable the pipeline, some components can not be disabled
+        * together with others, but need a sparated and standalone disable.
+        * The standalone_disabled_comps are the components which need to be
+        * disabled standalone, and this concept also introduce concept of
+        * two phase.
+        * phase 1: for disabling the common components.
+        * phase 2: for disabling the standalong_disabled_comps.
+        */
+       u32 standalone_disabled_comps;
        /** @n_layers: the number of layer on @layers */
        int n_layers;
        /** @layers: the pipeline layers */
@@ -535,7 +547,7 @@ int komeda_release_unclaimed_resources(struct komeda_pipeline *pipe,
 struct komeda_pipeline_state *
 komeda_pipeline_get_old_state(struct komeda_pipeline *pipe,
                              struct drm_atomic_state *state);
-void komeda_pipeline_disable(struct komeda_pipeline *pipe,
+bool komeda_pipeline_disable(struct komeda_pipeline *pipe,
                             struct drm_atomic_state *old_state);
 void komeda_pipeline_update(struct komeda_pipeline *pipe,
                            struct drm_atomic_state *old_state);
index ea26bc9c2d0012e7c4703227464f462b70f1fd4b..0ba9c6aa37085bab142a3715c416ea20b2e496d8 100644 (file)
@@ -1218,7 +1218,17 @@ int komeda_release_unclaimed_resources(struct komeda_pipeline *pipe,
        return 0;
 }
 
-void komeda_pipeline_disable(struct komeda_pipeline *pipe,
+/* Since standalong disabled components must be disabled separately and in the
+ * last, So a complete disable operation may needs to call pipeline_disable
+ * twice (two phase disabling).
+ * Phase 1: disable the common components, flush it.
+ * Phase 2: disable the standalone disabled components, flush it.
+ *
+ * RETURNS:
+ * true: disable is not complete, needs a phase 2 disable.
+ * false: disable is complete.
+ */
+bool komeda_pipeline_disable(struct komeda_pipeline *pipe,
                             struct drm_atomic_state *old_state)
 {
        struct komeda_pipeline_state *old;
@@ -1228,9 +1238,14 @@ void komeda_pipeline_disable(struct komeda_pipeline *pipe,
 
        old = komeda_pipeline_get_old_state(pipe, old_state);
 
-       disabling_comps = old->active_comps;
-       DRM_DEBUG_ATOMIC("PIPE%d: disabling_comps: 0x%x.\n",
-                        pipe->id, disabling_comps);
+       disabling_comps = old->active_comps &
+                         (~pipe->standalone_disabled_comps);
+       if (!disabling_comps)
+               disabling_comps = old->active_comps &
+                                 pipe->standalone_disabled_comps;
+
+       DRM_DEBUG_ATOMIC("PIPE%d: active_comps: 0x%x, disabling_comps: 0x%x.\n",
+                        pipe->id, old->active_comps, disabling_comps);
 
        dp_for_each_set_bit(id, disabling_comps) {
                c = komeda_pipeline_get_component(pipe, id);
@@ -1248,6 +1263,13 @@ void komeda_pipeline_disable(struct komeda_pipeline *pipe,
 
                c->funcs->disable(c);
        }
+
+       /* Update the pipeline state, if there are components that are still
+        * active, return true for calling the phase 2 disable.
+        */
+       old->active_comps &= ~disabling_comps;
+
+       return old->active_comps ? true : false;
 }
 
 void komeda_pipeline_update(struct komeda_pipeline *pipe,
index 829620d5326cce6e25e2254d13dbf48dc7eb0841..fbcf2f45cef51d80df099f4c376b4352cfe03b64 100644 (file)
@@ -4,6 +4,8 @@ config DRM_AST
        depends on DRM && PCI && MMU
        select DRM_KMS_HELPER
        select DRM_VRAM_HELPER
+       select DRM_TTM
+       select DRM_TTM_HELPER
        help
         Say yes for experimental AST GPU driver. Do not enable
         this driver without having a working -modesetting,
index 6ed6ff49efc0707fbaa607468c1038f86159ac56..e0e8770462bc3ed8f26d4a11fc62e500e975a9e4 100644 (file)
@@ -35,7 +35,6 @@
 #include <drm/drm_gem_vram_helper.h>
 #include <drm/drm_pci.h>
 #include <drm/drm_probe_helper.h>
-#include <drm/drm_vram_mm_helper.h>
 
 #include "ast_drv.h"
 
index 50de8e47659c7f62c272b068adf2d0bad9138956..21715d6a9b56027e704ec380964fccdbb374816e 100644 (file)
@@ -33,7 +33,6 @@
 #include <drm/drm_gem.h>
 #include <drm/drm_gem_framebuffer_helper.h>
 #include <drm/drm_gem_vram_helper.h>
-#include <drm/drm_vram_mm_helper.h>
 
 #include "ast_drv.h"
 
index d349c721501c6cb5ee890b5c2906479e0b865daf..6caa6ebfeaa8d96c6f3947c2de406065c9f247ca 100644 (file)
@@ -687,17 +687,6 @@ static void ast_encoder_destroy(struct drm_encoder *encoder)
        kfree(encoder);
 }
 
-
-static struct drm_encoder *ast_best_single_encoder(struct drm_connector *connector)
-{
-       int enc_id = connector->encoder_ids[0];
-       /* pick the encoder ids */
-       if (enc_id)
-               return drm_encoder_find(connector->dev, NULL, enc_id);
-       return NULL;
-}
-
-
 static const struct drm_encoder_funcs ast_enc_funcs = {
        .destroy = ast_encoder_destroy,
 };
@@ -847,7 +836,6 @@ static void ast_connector_destroy(struct drm_connector *connector)
 static const struct drm_connector_helper_funcs ast_connector_helper_funcs = {
        .mode_valid = ast_mode_valid,
        .get_modes = ast_get_modes,
-       .best_encoder = ast_best_single_encoder,
 };
 
 static const struct drm_connector_funcs ast_connector_funcs = {
@@ -1179,26 +1167,22 @@ static int ast_cursor_set(struct drm_crtc *crtc,
                return -ENOENT;
        }
        gbo = drm_gem_vram_of_gem(obj);
-
-       ret = drm_gem_vram_pin(gbo, 0);
-       if (ret)
-               goto err_drm_gem_object_put_unlocked;
-       src = drm_gem_vram_kmap(gbo, true, NULL);
+       src = drm_gem_vram_vmap(gbo);
        if (IS_ERR(src)) {
                ret = PTR_ERR(src);
-               goto err_drm_gem_vram_unpin;
+               goto err_drm_gem_object_put_unlocked;
        }
 
        dst = drm_gem_vram_kmap(drm_gem_vram_of_gem(ast->cursor_cache),
                                false, NULL);
        if (IS_ERR(dst)) {
                ret = PTR_ERR(dst);
-               goto err_drm_gem_vram_kunmap;
+               goto err_drm_gem_vram_vunmap;
        }
        dst_gpu = drm_gem_vram_offset(drm_gem_vram_of_gem(ast->cursor_cache));
        if (dst_gpu < 0) {
                ret = (int)dst_gpu;
-               goto err_drm_gem_vram_kunmap;
+               goto err_drm_gem_vram_vunmap;
        }
 
        dst += (AST_HWC_SIZE + AST_HWC_SIGNATURE_SIZE)*ast->next_cursor;
@@ -1233,16 +1217,13 @@ static int ast_cursor_set(struct drm_crtc *crtc,
 
        ast_show_cursor(crtc);
 
-       drm_gem_vram_kunmap(gbo);
-       drm_gem_vram_unpin(gbo);
+       drm_gem_vram_vunmap(gbo, src);
        drm_gem_object_put_unlocked(obj);
 
        return 0;
 
-err_drm_gem_vram_kunmap:
-       drm_gem_vram_kunmap(gbo);
-err_drm_gem_vram_unpin:
-       drm_gem_vram_unpin(gbo);
+err_drm_gem_vram_vunmap:
+       drm_gem_vram_vunmap(gbo, src);
 err_drm_gem_object_put_unlocked:
        drm_gem_object_put_unlocked(obj);
        return ret;
index c52d9229417158d5b2d4c1846b41b94754f4f237..fad34106083a88c7297df95a034d743b5a9810f0 100644 (file)
@@ -30,7 +30,6 @@
 
 #include <drm/drm_print.h>
 #include <drm/drm_gem_vram_helper.h>
-#include <drm/drm_vram_mm_helper.h>
 
 #include "ast_drv.h"
 
@@ -42,7 +41,7 @@ int ast_mm_init(struct ast_private *ast)
 
        vmm = drm_vram_helper_alloc_mm(
                dev, pci_resource_start(dev->pdev, 0),
-               ast->vram_size, &drm_gem_vram_mm_funcs);
+               ast->vram_size);
        if (IS_ERR(vmm)) {
                ret = PTR_ERR(vmm);
                DRM_ERROR("Error initializing VRAM MM; %d\n", ret);
index 375fa84c548b7c8fffbde5b30da2929b9cde3aab..121b62682d8030366a8528a7d25a4dd3df3f8301 100644 (file)
@@ -107,7 +107,8 @@ static int atmel_hlcdc_attach_endpoint(struct drm_device *dev, int endpoint)
        output->encoder.possible_crtcs = 0x1;
 
        if (panel) {
-               bridge = drm_panel_bridge_add(panel, DRM_MODE_CONNECTOR_Unknown);
+               bridge = drm_panel_bridge_add_typed(panel,
+                                                   DRM_MODE_CONNECTOR_Unknown);
                if (IS_ERR(bridge))
                        return PTR_ERR(bridge);
        }
index 32b043abb668d8c51dae70041cd6d5a0e5b59065..7bcdf294fed8344e5e5387f4550ceaf834e54b9c 100644 (file)
@@ -4,6 +4,8 @@ config DRM_BOCHS
        depends on DRM && PCI && MMU
        select DRM_KMS_HELPER
        select DRM_VRAM_HELPER
+       select DRM_TTM
+       select DRM_TTM_HELPER
        help
          Choose this option for qemu.
          If M is selected the module will be called bochs-drm.
index 68483a2fc12c660907a01c3fbce1868e066e8b4a..917767173ee6836deea7b5e2bfa704c0aa77ea2d 100644 (file)
@@ -10,7 +10,6 @@
 #include <drm/drm_gem.h>
 #include <drm/drm_gem_vram_helper.h>
 #include <drm/drm_simple_kms_helper.h>
-#include <drm/drm_vram_mm_helper.h>
 
 /* ---------------------------------------------------------------------- */
 
index 770e1625d05ef5d1d4cd3272c9f8184d13ddb532..3b9b0d9bbc1417406b94ac36cfb328c269b12929 100644 (file)
@@ -114,7 +114,7 @@ static int bochs_pci_probe(struct pci_dev *pdev,
                return -ENOMEM;
        }
 
-       ret = drm_fb_helper_remove_conflicting_pci_framebuffers(pdev, 0, "bochsdrmfb");
+       ret = drm_fb_helper_remove_conflicting_pci_framebuffers(pdev, "bochsdrmfb");
        if (ret)
                return ret;
 
index 8f9bb886f7add4cafb17db3313c37dbacfedd8e0..1b74f530b07c4e90e2a3f5ca6e1dc2834b509ff9 100644 (file)
@@ -11,8 +11,7 @@ int bochs_mm_init(struct bochs_device *bochs)
        struct drm_vram_mm *vmm;
 
        vmm = drm_vram_helper_alloc_mm(bochs->dev, bochs->fb_base,
-                                      bochs->fb_size,
-                                      &drm_gem_vram_mm_funcs);
+                                      bochs->fb_size);
        return PTR_ERR_OR_ZERO(vmm);
 }
 
index 3c7cc5af735ce3f7a5f22acc7516ce8480c5e161..31118d38558022bcbb99970f9f460e4b731868fc 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/types.h>
 
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_bridge.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_dp_helper.h>
 #include <drm/drm_edid.h>
@@ -715,7 +716,9 @@ static int anx78xx_init_pdata(struct anx78xx *anx78xx)
        /* 1.0V digital core power regulator  */
        pdata->dvdd10 = devm_regulator_get(dev, "dvdd10");
        if (IS_ERR(pdata->dvdd10)) {
-               DRM_ERROR("DVDD10 regulator not found\n");
+               if (PTR_ERR(pdata->dvdd10) != -EPROBE_DEFER)
+                       DRM_ERROR("DVDD10 regulator not found\n");
+
                return PTR_ERR(pdata->dvdd10);
        }
 
@@ -1301,6 +1304,7 @@ static const struct regmap_config anx78xx_regmap_config = {
 };
 
 static const u16 anx78xx_chipid_list[] = {
+       0x7808,
        0x7812,
        0x7814,
        0x7818,
@@ -1332,7 +1336,9 @@ static int anx78xx_i2c_probe(struct i2c_client *client,
 
        err = anx78xx_init_pdata(anx78xx);
        if (err) {
-               DRM_ERROR("Failed to initialize pdata: %d\n", err);
+               if (err != -EPROBE_DEFER)
+                       DRM_ERROR("Failed to initialize pdata: %d\n", err);
+
                return err;
        }
 
@@ -1350,15 +1356,18 @@ static int anx78xx_i2c_probe(struct i2c_client *client,
 
        /* Map slave addresses of ANX7814 */
        for (i = 0; i < I2C_NUM_ADDRESSES; i++) {
-               anx78xx->i2c_dummy[i] = i2c_new_dummy(client->adapter,
-                                               anx78xx_i2c_addresses[i] >> 1);
-               if (!anx78xx->i2c_dummy[i]) {
-                       err = -ENOMEM;
-                       DRM_ERROR("Failed to reserve I2C bus %02x\n",
-                                 anx78xx_i2c_addresses[i]);
+               struct i2c_client *i2c_dummy;
+
+               i2c_dummy = i2c_new_dummy_device(client->adapter,
+                                                anx78xx_i2c_addresses[i] >> 1);
+               if (IS_ERR(i2c_dummy)) {
+                       err = PTR_ERR(i2c_dummy);
+                       DRM_ERROR("Failed to reserve I2C bus %02x: %d\n",
+                                 anx78xx_i2c_addresses[i], err);
                        goto err_unregister_i2c;
                }
 
+               anx78xx->i2c_dummy[i] = i2c_dummy;
                anx78xx->map[i] = devm_regmap_init_i2c(anx78xx->i2c_dummy[i],
                                                       &anx78xx_regmap_config);
                if (IS_ERR(anx78xx->map[i])) {
@@ -1463,7 +1472,10 @@ MODULE_DEVICE_TABLE(i2c, anx78xx_id);
 
 #if IS_ENABLED(CONFIG_OF)
 static const struct of_device_id anx78xx_match_table[] = {
+       { .compatible = "analogix,anx7808", },
+       { .compatible = "analogix,anx7812", },
        { .compatible = "analogix,anx7814", },
+       { .compatible = "analogix,anx7818", },
        { /* sentinel */ },
 };
 MODULE_DEVICE_TABLE(of, anx78xx_match_table);
index 22885dceaa177e1e608ae9246b225699b9fafa76..bb411fe52ae83d673b069b004acd6f1071334acf 100644 (file)
@@ -21,6 +21,7 @@
 #include <drm/bridge/analogix_dp.h>
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_bridge.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_device.h>
 #include <drm/drm_panel.h>
index 6166dca6be813ebc8ca3629d94108f4e76168cb7..3a5bd4e7fd1e3b8ce257cb05ca52591f884fdfff 100644 (file)
@@ -956,7 +956,8 @@ static int cdns_dsi_attach(struct mipi_dsi_host *host,
 
        panel = of_drm_find_panel(np);
        if (!IS_ERR(panel)) {
-               bridge = drm_panel_bridge_add(panel, DRM_MODE_CONNECTOR_DSI);
+               bridge = drm_panel_bridge_add_typed(panel,
+                                                   DRM_MODE_CONNECTOR_DSI);
        } else {
                bridge = of_drm_find_bridge(dev->dev.of_node);
                if (!bridge)
index 7aa789c358829b05a32e9d8dfe2961cfc7efe6a5..cc33dc411b9e8526992b6760d0868ecf5b2266e0 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/regulator/consumer.h>
 
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_bridge.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_print.h>
 #include <drm/drm_probe_helper.h>
index 2ab2c234f26c2b0e770fd661e49475c0b751f4da..e2132a8d5106c29a14806b9d504d40271e5b8952 100644 (file)
@@ -106,7 +106,8 @@ static int lvds_encoder_probe(struct platform_device *pdev)
        }
 
        lvds_encoder->panel_bridge =
-               devm_drm_panel_bridge_add(dev, panel, DRM_MODE_CONNECTOR_LVDS);
+               devm_drm_panel_bridge_add_typed(dev, panel,
+                                               DRM_MODE_CONNECTOR_LVDS);
        if (IS_ERR(lvds_encoder->panel_bridge))
                return PTR_ERR(lvds_encoder->panel_bridge);
 
index 6e81e5db57f2506062baada398732040072f950f..e8a49f6146c61fea646f4e88bbfbb940cfe4f196 100644 (file)
@@ -25,6 +25,7 @@
 
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_bridge.h>
 #include <drm/drm_edid.h>
 #include <drm/drm_print.h>
 #include <drm/drm_probe_helper.h>
index d4a1cc5052c32921d0893052789f44144eb2801d..57ff01339559768487a2830a835156ec01020902 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/module.h>
 #include <linux/of.h>
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_bridge.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_edid.h>
 #include <drm/drm_of.h>
index b12ae3a4c5f11b243e8440f1ffd6e6ed0c1f0633..f4e293e7cf64268db54339a5f5ae1a5eb3ee8a53 100644 (file)
@@ -5,6 +5,7 @@
  */
 
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_bridge.h>
 #include <drm/drm_connector.h>
 #include <drm/drm_encoder.h>
 #include <drm/drm_modeset_helper_vtables.h>
@@ -133,8 +134,6 @@ static const struct drm_bridge_funcs panel_bridge_bridge_funcs = {
  * just calls the appropriate functions from &drm_panel.
  *
  * @panel: The drm_panel being wrapped.  Must be non-NULL.
- * @connector_type: The DRM_MODE_CONNECTOR_* for the connector to be
- * created.
  *
  * For drivers converting from directly using drm_panel: The expected
  * usage pattern is that during either encoder module probe or DSI
@@ -148,11 +147,37 @@ static const struct drm_bridge_funcs panel_bridge_bridge_funcs = {
  * drm_mode_config_cleanup() if the bridge has already been attached), then
  * drm_panel_bridge_remove() to free it.
  *
+ * The connector type is set to @panel->connector_type, which must be set to a
+ * known type. Calling this function with a panel whose connector type is
+ * DRM_MODE_CONNECTOR_Unknown will return NULL.
+ *
  * See devm_drm_panel_bridge_add() for an automatically manged version of this
  * function.
  */
-struct drm_bridge *drm_panel_bridge_add(struct drm_panel *panel,
-                                       u32 connector_type)
+struct drm_bridge *drm_panel_bridge_add(struct drm_panel *panel)
+{
+       if (WARN_ON(panel->connector_type == DRM_MODE_CONNECTOR_Unknown))
+               return NULL;
+
+       return drm_panel_bridge_add_typed(panel, panel->connector_type);
+}
+EXPORT_SYMBOL(drm_panel_bridge_add);
+
+/**
+ * drm_panel_bridge_add_typed - Creates a &drm_bridge and &drm_connector with
+ * an explicit connector type.
+ * @panel: The drm_panel being wrapped.  Must be non-NULL.
+ * @connector_type: The connector type (DRM_MODE_CONNECTOR_*)
+ *
+ * This is just like drm_panel_bridge_add(), but forces the connector type to
+ * @connector_type instead of infering it from the panel.
+ *
+ * This function is deprecated and should not be used in new drivers. Use
+ * drm_panel_bridge_add() instead, and fix panel drivers as necessary if they
+ * don't report a connector type.
+ */
+struct drm_bridge *drm_panel_bridge_add_typed(struct drm_panel *panel,
+                                             u32 connector_type)
 {
        struct panel_bridge *panel_bridge;
 
@@ -176,7 +201,7 @@ struct drm_bridge *drm_panel_bridge_add(struct drm_panel *panel,
 
        return &panel_bridge->bridge;
 }
-EXPORT_SYMBOL(drm_panel_bridge_add);
+EXPORT_SYMBOL(drm_panel_bridge_add_typed);
 
 /**
  * drm_panel_bridge_remove - Unregisters and frees a drm_bridge
@@ -213,15 +238,38 @@ static void devm_drm_panel_bridge_release(struct device *dev, void *res)
  * that just calls the appropriate functions from &drm_panel.
  * @dev: device to tie the bridge lifetime to
  * @panel: The drm_panel being wrapped.  Must be non-NULL.
- * @connector_type: The DRM_MODE_CONNECTOR_* for the connector to be
- * created.
  *
  * This is the managed version of drm_panel_bridge_add() which automatically
  * calls drm_panel_bridge_remove() when @dev is unbound.
  */
 struct drm_bridge *devm_drm_panel_bridge_add(struct device *dev,
-                                            struct drm_panel *panel,
-                                            u32 connector_type)
+                                            struct drm_panel *panel)
+{
+       if (WARN_ON(panel->connector_type == DRM_MODE_CONNECTOR_Unknown))
+               return NULL;
+
+       return devm_drm_panel_bridge_add_typed(dev, panel,
+                                              panel->connector_type);
+}
+EXPORT_SYMBOL(devm_drm_panel_bridge_add);
+
+/**
+ * devm_drm_panel_bridge_add_typed - Creates a managed &drm_bridge and
+ * &drm_connector with an explicit connector type.
+ * @dev: device to tie the bridge lifetime to
+ * @panel: The drm_panel being wrapped.  Must be non-NULL.
+ * @connector_type: The connector type (DRM_MODE_CONNECTOR_*)
+ *
+ * This is just like devm_drm_panel_bridge_add(), but forces the connector type
+ * to @connector_type instead of infering it from the panel.
+ *
+ * This function is deprecated and should not be used in new drivers. Use
+ * devm_drm_panel_bridge_add() instead, and fix panel drivers as necessary if
+ * they don't report a connector type.
+ */
+struct drm_bridge *devm_drm_panel_bridge_add_typed(struct device *dev,
+                                                  struct drm_panel *panel,
+                                                  u32 connector_type)
 {
        struct drm_bridge **ptr, *bridge;
 
@@ -230,7 +278,7 @@ struct drm_bridge *devm_drm_panel_bridge_add(struct device *dev,
        if (!ptr)
                return ERR_PTR(-ENOMEM);
 
-       bridge = drm_panel_bridge_add(panel, connector_type);
+       bridge = drm_panel_bridge_add_typed(panel, connector_type);
        if (!IS_ERR(bridge)) {
                *ptr = bridge;
                devres_add(dev, ptr);
@@ -240,4 +288,4 @@ struct drm_bridge *devm_drm_panel_bridge_add(struct device *dev,
 
        return bridge;
 }
-EXPORT_SYMBOL(devm_drm_panel_bridge_add);
+EXPORT_SYMBOL(devm_drm_panel_bridge_add_typed);
index 93c68e2e9484fd9f9553ccf5fce11b0ae0f8dada..b7a72dfdcac3c77d04c29576a3d1c0b20facacb3 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/regulator/consumer.h>
 
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_bridge.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_of.h>
 #include <drm/drm_panel.h>
index 38f75ac580df48ad47deff264eb4467b6d06b1ba..b70e8c5cf2e13806f8361c1ccb4441cc5193be14 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/clk.h>
 
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_bridge.h>
 #include <drm/drm_drv.h>
 #include <drm/drm_edid.h>
 #include <drm/drm_print.h>
index 25d4ad8c7ad65d23ee36a7a245e04ee155b504f1..ad00d841ed9ebf3922eea73bda0d9f2010e233b7 100644 (file)
@@ -13,6 +13,7 @@
  *    Dharam Kumar <dharam.kr@samsung.com>
  */
 #include <drm/bridge/mhl.h>
+#include <drm/drm_bridge.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_edid.h>
 
index bd3165ee53541384505c2cae92816c536eb4b6d5..14643923a7217bf236757260407eb2ee24eebf3f 100644 (file)
@@ -9,6 +9,7 @@
 #include <asm/unaligned.h>
 
 #include <drm/bridge/mhl.h>
+#include <drm/drm_bridge.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_edid.h>
 #include <drm/drm_encoder.h>
index 1d15cf9b6821e99d277bd79a41757c1161db77c4..20f4f92dd866fe16150da42b655bb332338d9022 100644 (file)
@@ -102,6 +102,7 @@ static int dw_hdmi_i2s_hw_params(struct device *dev, void *data,
        }
 
        dw_hdmi_set_sample_rate(hdmi, hparms->sample_rate);
+       dw_hdmi_set_channel_status(hdmi, hparms->iec.status);
        dw_hdmi_set_channel_count(hdmi, hparms->channels);
        dw_hdmi_set_channel_allocation(hdmi, hparms->cea.channel_allocation);
 
@@ -109,6 +110,14 @@ static int dw_hdmi_i2s_hw_params(struct device *dev, void *data,
        hdmi_write(audio, conf0, HDMI_AUD_CONF0);
        hdmi_write(audio, conf1, HDMI_AUD_CONF1);
 
+       return 0;
+}
+
+static int dw_hdmi_i2s_audio_startup(struct device *dev, void *data)
+{
+       struct dw_hdmi_i2s_audio_data *audio = data;
+       struct dw_hdmi *hdmi = audio->hdmi;
+
        dw_hdmi_audio_enable(hdmi);
 
        return 0;
@@ -153,6 +162,7 @@ static int dw_hdmi_i2s_get_dai_id(struct snd_soc_component *component,
 
 static struct hdmi_codec_ops dw_hdmi_i2s_ops = {
        .hw_params      = dw_hdmi_i2s_hw_params,
+       .audio_startup  = dw_hdmi_i2s_audio_startup,
        .audio_shutdown = dw_hdmi_i2s_audio_shutdown,
        .get_eld        = dw_hdmi_i2s_get_eld,
        .get_dai_id     = dw_hdmi_i2s_get_dai_id,
index 521d689413c8c4b979794b11a7a0a6e2468037d6..d77fb8af61b8a82f78e7d2602b10300c2591ddef 100644 (file)
@@ -26,6 +26,7 @@
 
 #include <drm/bridge/dw_hdmi.h>
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_bridge.h>
 #include <drm/drm_edid.h>
 #include <drm/drm_of.h>
 #include <drm/drm_print.h>
@@ -580,6 +581,26 @@ static unsigned int hdmi_compute_n(unsigned int freq, unsigned long pixel_clk)
        return n;
 }
 
+/*
+ * When transmitting IEC60958 linear PCM audio, these registers allow to
+ * configure the channel status information of all the channel status
+ * bits in the IEC60958 frame. For the moment this configuration is only
+ * used when the I2S audio interface, General Purpose Audio (GPA),
+ * or AHB audio DMA (AHBAUDDMA) interface is active
+ * (for S/PDIF interface this information comes from the stream).
+ */
+void dw_hdmi_set_channel_status(struct dw_hdmi *hdmi,
+                               u8 *channel_status)
+{
+       /*
+        * Set channel status register for frequency and word length.
+        * Use default values for other registers.
+        */
+       hdmi_writeb(hdmi, channel_status[3], HDMI_FC_AUDSCHNLS7);
+       hdmi_writeb(hdmi, channel_status[4], HDMI_FC_AUDSCHNLS8);
+}
+EXPORT_SYMBOL_GPL(dw_hdmi_set_channel_status);
+
 static void hdmi_set_clk_regenerator(struct dw_hdmi *hdmi,
        unsigned long pixel_clk, unsigned int sample_rate)
 {
index 6988f12d89d9bc1075510a39eb09453b1cf28bd3..fcff5059db249da0c66326fce04b680df93b78c0 100644 (file)
 #define HDMI_FC_SPDDEVICEINF                    0x1062
 #define HDMI_FC_AUDSCONF                        0x1063
 #define HDMI_FC_AUDSSTAT                        0x1064
+#define HDMI_FC_AUDSCHNLS7                      0x106e
+#define HDMI_FC_AUDSCHNLS8                      0x106f
 #define HDMI_FC_DATACH0FILL                     0x1070
 #define HDMI_FC_DATACH1FILL                     0x1071
 #define HDMI_FC_DATACH2FILL                     0x1072
index 675442bfc1bd77070cea0f7ed1305647fc3178f6..b6e793bb653c4dbabf32230638b96d7ef732fe74 100644 (file)
@@ -316,7 +316,8 @@ static int dw_mipi_dsi_host_attach(struct mipi_dsi_host *host,
                return ret;
 
        if (panel) {
-               bridge = drm_panel_bridge_add(panel, DRM_MODE_CONNECTOR_DSI);
+               bridge = drm_panel_bridge_add_typed(panel,
+                                                   DRM_MODE_CONNECTOR_DSI);
                if (IS_ERR(bridge))
                        return PTR_ERR(bridge);
        }
@@ -981,7 +982,6 @@ __dw_mipi_dsi_probe(struct platform_device *pdev,
        struct device *dev = &pdev->dev;
        struct reset_control *apb_rst;
        struct dw_mipi_dsi *dsi;
-       struct resource *res;
        int ret;
 
        dsi = devm_kzalloc(dev, sizeof(*dsi), GFP_KERNEL);
@@ -997,11 +997,7 @@ __dw_mipi_dsi_probe(struct platform_device *pdev,
        }
 
        if (!plat_data->base) {
-               res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-               if (!res)
-                       return ERR_PTR(-ENODEV);
-
-               dsi->base = devm_ioremap_resource(dev, res);
+               dsi->base = devm_platform_ioremap_resource(pdev, 0);
                if (IS_ERR(dsi->base))
                        return ERR_PTR(-ENODEV);
 
index 170f162ffa5586599079e9766db1e2cf0b2a4af6..db298f550a5adfc7d7317c67ae7d7a2b77c5d425 100644 (file)
@@ -16,6 +16,7 @@
 #include <video/mipi_display.h>
 
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_bridge.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_mipi_dsi.h>
index cebc8e6208208815b9334671ee13b958516d54d9..51664a2df73133dec35bb9339079d96f06b3461e 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/slab.h>
 
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_bridge.h>
 #include <drm/drm_dp_helper.h>
 #include <drm/drm_edid.h>
 #include <drm/drm_of.h>
index 0a580957c8cf12e9ba7a2dfc3e1ad0abb3113e73..43abf01ebd4ca00272f3ea781f96597e802a093a 100644 (file)
@@ -17,6 +17,7 @@
 
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_bridge.h>
 #include <drm/drm_dp_helper.h>
 #include <drm/drm_mipi_dsi.h>
 #include <drm/drm_of.h>
index 61cc2354ef1bfe7eb09a6d93b9d7c22b3ed4c713..aa3198dc9903cefb70f74ce815352752434a91f9 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/platform_device.h>
 
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_bridge.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_print.h>
 #include <drm/drm_probe_helper.h>
index 36a69aec8a4ba5fe94f38ce1c79d711336f0e1f4..89d9e6fdeb8c5130316ef80e5529cbf2919d9620 100644 (file)
@@ -532,7 +532,7 @@ static int cirrus_pci_probe(struct pci_dev *pdev,
        struct cirrus_device *cirrus;
        int ret;
 
-       ret = drm_fb_helper_remove_conflicting_pci_framebuffers(pdev, 0, "cirrusdrmfb");
+       ret = drm_fb_helper_remove_conflicting_pci_framebuffers(pdev, "cirrusdrmfb");
        if (ret)
                return ret;
 
index 3ef2ac52ce942c303fbec865587fa7b95933ad15..587052751b481e8f754962d92f2c8c69d3c616ed 100644 (file)
@@ -31,6 +31,7 @@
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_atomic_uapi.h>
+#include <drm/drm_bridge.h>
 #include <drm/drm_damage_helper.h>
 #include <drm/drm_device.h>
 #include <drm/drm_plane_helper.h>
@@ -97,17 +98,6 @@ drm_atomic_helper_plane_changed(struct drm_atomic_state *state,
        }
 }
 
-/*
- * For connectors that support multiple encoders, either the
- * .atomic_best_encoder() or .best_encoder() operation must be implemented.
- */
-static struct drm_encoder *
-pick_single_encoder_for_connector(struct drm_connector *connector)
-{
-       WARN_ON(connector->encoder_ids[1]);
-       return drm_encoder_find(connector->dev, NULL, connector->encoder_ids[0]);
-}
-
 static int handle_conflicting_encoders(struct drm_atomic_state *state,
                                       bool disable_conflicting_encoders)
 {
@@ -135,7 +125,7 @@ static int handle_conflicting_encoders(struct drm_atomic_state *state,
                else if (funcs->best_encoder)
                        new_encoder = funcs->best_encoder(connector);
                else
-                       new_encoder = pick_single_encoder_for_connector(connector);
+                       new_encoder = drm_connector_get_single_encoder(connector);
 
                if (new_encoder) {
                        if (encoder_mask & drm_encoder_mask(new_encoder)) {
@@ -359,7 +349,7 @@ update_connector_routing(struct drm_atomic_state *state,
        else if (funcs->best_encoder)
                new_encoder = funcs->best_encoder(connector);
        else
-               new_encoder = pick_single_encoder_for_connector(connector);
+               new_encoder = drm_connector_get_single_encoder(connector);
 
        if (!new_encoder) {
                DRM_DEBUG_ATOMIC("No suitable encoder found for [CONNECTOR:%d:%s]\n",
@@ -482,7 +472,7 @@ mode_fixup(struct drm_atomic_state *state)
                        continue;
 
                funcs = crtc->helper_private;
-               if (!funcs->mode_fixup)
+               if (!funcs || !funcs->mode_fixup)
                        continue;
 
                ret = funcs->mode_fixup(crtc, &new_crtc_state->mode,
index 7a26bfb5329cd255f1def9675f074b456b70dbbe..0d466d3b08090d756b7bb31343c606cf20b0ac90 100644 (file)
@@ -1405,7 +1405,7 @@ retry:
        } else if (arg->flags & DRM_MODE_ATOMIC_NONBLOCK) {
                ret = drm_atomic_nonblocking_commit(state);
        } else {
-               if (unlikely(drm_debug & DRM_UT_STATE))
+               if (drm_debug_enabled(DRM_UT_STATE))
                        drm_atomic_print_state(state);
 
                ret = drm_atomic_commit(state);
index 37ac168fcb60ff46faadf4b59ce9bc53c7d1bf9a..d02709dd2d4a38cb89f08f25912146cc9a7fca42 100644 (file)
  *     Z position is set up with drm_plane_create_zpos_immutable_property() and
  *     drm_plane_create_zpos_property(). It controls the visibility of overlapping
  *     planes. Without this property the primary plane is always below the cursor
- *     plane, and ordering between all other planes is undefined.
+ *     plane, and ordering between all other planes is undefined. The positive
+ *     Z axis points towards the user, i.e. planes with lower Z position values
+ *     are underneath planes with higher Z position values. Note that the Z
+ *     position value can also be immutable, to inform userspace about the
+ *     hard-coded stacking of overlay planes, see
+ *     drm_plane_create_zpos_immutable_property().
  *
  * pixel blend mode:
  *     Pixel blend mode is set up with drm_plane_create_blend_mode_property().
index c8922b7cac091de342253ac5938acf690c82a4b5..895b73f23079a7838cc926ab1e1728d88de13f71 100644 (file)
@@ -415,9 +415,8 @@ static bool connector_has_possible_crtc(struct drm_connector *connector,
                                        struct drm_crtc *crtc)
 {
        struct drm_encoder *encoder;
-       int i;
 
-       drm_connector_for_each_possible_encoder(connector, encoder, i) {
+       drm_connector_for_each_possible_encoder(connector, encoder) {
                if (encoder->possible_crtcs & drm_crtc_mask(crtc))
                        return true;
        }
index 4c766624b20d31e8b827313b887728cc797c8051..0965632008a993b09c15c74deba3e01692f5082c 100644 (file)
@@ -365,8 +365,6 @@ EXPORT_SYMBOL(drm_connector_attach_edid_property);
 int drm_connector_attach_encoder(struct drm_connector *connector,
                                 struct drm_encoder *encoder)
 {
-       int i;
-
        /*
         * In the past, drivers have attempted to model the static association
         * of connector to encoder in simple connector/encoder devices using a
@@ -381,18 +379,15 @@ int drm_connector_attach_encoder(struct drm_connector *connector,
        if (WARN_ON(connector->encoder))
                return -EINVAL;
 
-       for (i = 0; i < ARRAY_SIZE(connector->encoder_ids); i++) {
-               if (connector->encoder_ids[i] == 0) {
-                       connector->encoder_ids[i] = encoder->base.id;
-                       return 0;
-               }
-       }
-       return -ENOMEM;
+       connector->possible_encoders |= drm_encoder_mask(encoder);
+
+       return 0;
 }
 EXPORT_SYMBOL(drm_connector_attach_encoder);
 
 /**
- * drm_connector_has_possible_encoder - check if the connector and encoder are assosicated with each other
+ * drm_connector_has_possible_encoder - check if the connector and encoder are
+ * associated with each other
  * @connector: the connector
  * @encoder: the encoder
  *
@@ -402,15 +397,7 @@ EXPORT_SYMBOL(drm_connector_attach_encoder);
 bool drm_connector_has_possible_encoder(struct drm_connector *connector,
                                        struct drm_encoder *encoder)
 {
-       struct drm_encoder *enc;
-       int i;
-
-       drm_connector_for_each_possible_encoder(connector, enc, i) {
-               if (enc == encoder)
-                       return true;
-       }
-
-       return false;
+       return connector->possible_encoders & drm_encoder_mask(encoder);
 }
 EXPORT_SYMBOL(drm_connector_has_possible_encoder);
 
@@ -480,7 +467,10 @@ EXPORT_SYMBOL(drm_connector_cleanup);
  * drm_connector_register - register a connector
  * @connector: the connector to register
  *
- * Register userspace interfaces for a connector
+ * Register userspace interfaces for a connector. Only call this for connectors
+ * which can be hotplugged after drm_dev_register() has been called already,
+ * e.g. DP MST connectors. All other connectors will be registered automatically
+ * when calling drm_dev_register().
  *
  * Returns:
  * Zero on success, error code on failure.
@@ -526,7 +516,10 @@ EXPORT_SYMBOL(drm_connector_register);
  * drm_connector_unregister - unregister a connector
  * @connector: the connector to unregister
  *
- * Unregister userspace interfaces for a connector
+ * Unregister userspace interfaces for a connector. Only call this for
+ * connectors which have registered explicitly by calling drm_dev_register(),
+ * since connectors are unregistered automatically when drm_dev_unregister() is
+ * called.
  */
 void drm_connector_unregister(struct drm_connector *connector)
 {
@@ -882,6 +875,38 @@ static const struct drm_prop_enum_list hdmi_colorspaces[] = {
        { DRM_MODE_COLORIMETRY_DCI_P3_RGB_THEATER, "DCI-P3_RGB_Theater" },
 };
 
+/*
+ * As per DP 1.4a spec, 2.2.5.7.5 VSC SDP Payload for Pixel Encoding/Colorimetry
+ * Format Table 2-120
+ */
+static const struct drm_prop_enum_list dp_colorspaces[] = {
+       /* For Default case, driver will set the colorspace */
+       { DRM_MODE_COLORIMETRY_DEFAULT, "Default" },
+       { DRM_MODE_COLORIMETRY_RGB_WIDE_FIXED, "RGB_Wide_Gamut_Fixed_Point" },
+       /* Colorimetry based on scRGB (IEC 61966-2-2) */
+       { DRM_MODE_COLORIMETRY_RGB_WIDE_FLOAT, "RGB_Wide_Gamut_Floating_Point" },
+       /* Colorimetry based on IEC 61966-2-5 */
+       { DRM_MODE_COLORIMETRY_OPRGB, "opRGB" },
+       /* Colorimetry based on SMPTE RP 431-2 */
+       { DRM_MODE_COLORIMETRY_DCI_P3_RGB_D65, "DCI-P3_RGB_D65" },
+       /* Colorimetry based on ITU-R BT.2020 */
+       { DRM_MODE_COLORIMETRY_BT2020_RGB, "BT2020_RGB" },
+       { DRM_MODE_COLORIMETRY_BT601_YCC, "BT601_YCC" },
+       { DRM_MODE_COLORIMETRY_BT709_YCC, "BT709_YCC" },
+       /* Standard Definition Colorimetry based on IEC 61966-2-4 */
+       { DRM_MODE_COLORIMETRY_XVYCC_601, "XVYCC_601" },
+       /* High Definition Colorimetry based on IEC 61966-2-4 */
+       { DRM_MODE_COLORIMETRY_XVYCC_709, "XVYCC_709" },
+       /* Colorimetry based on IEC 61966-2-1/Amendment 1 */
+       { DRM_MODE_COLORIMETRY_SYCC_601, "SYCC_601" },
+       /* Colorimetry based on IEC 61966-2-5 [33] */
+       { DRM_MODE_COLORIMETRY_OPYCC_601, "opYCC_601" },
+       /* Colorimetry based on ITU-R BT.2020 */
+       { DRM_MODE_COLORIMETRY_BT2020_CYCC, "BT2020_CYCC" },
+       /* Colorimetry based on ITU-R BT.2020 */
+       { DRM_MODE_COLORIMETRY_BT2020_YCC, "BT2020_YCC" },
+};
+
 /**
  * DOC: standard connector properties
  *
@@ -1674,7 +1699,6 @@ EXPORT_SYMBOL(drm_mode_create_aspect_ratio_property);
  * DOC: standard connector properties
  *
  * Colorspace:
- *     drm_mode_create_colorspace_property - create colorspace property
  *     This property helps select a suitable colorspace based on the sink
  *     capability. Modern sink devices support wider gamut like BT2020.
  *     This helps switch to BT2020 mode if the BT2020 encoded video stream
@@ -1694,32 +1718,68 @@ EXPORT_SYMBOL(drm_mode_create_aspect_ratio_property);
  *      - This property is just to inform sink what colorspace
  *        source is trying to drive.
  *
+ * Because between HDMI and DP have different colorspaces,
+ * drm_mode_create_hdmi_colorspace_property() is used for HDMI connector and
+ * drm_mode_create_dp_colorspace_property() is used for DP connector.
+ */
+
+/**
+ * drm_mode_create_hdmi_colorspace_property - create hdmi colorspace property
+ * @connector: connector to create the Colorspace property on.
+ *
  * Called by a driver the first time it's needed, must be attached to desired
- * connectors.
+ * HDMI connectors.
+ *
+ * Returns:
+ * Zero on success, negative errono on failure.
  */
-int drm_mode_create_colorspace_property(struct drm_connector *connector)
+int drm_mode_create_hdmi_colorspace_property(struct drm_connector *connector)
 {
        struct drm_device *dev = connector->dev;
-       struct drm_property *prop;
 
-       if (connector->connector_type == DRM_MODE_CONNECTOR_HDMIA ||
-           connector->connector_type == DRM_MODE_CONNECTOR_HDMIB) {
-               prop = drm_property_create_enum(dev, DRM_MODE_PROP_ENUM,
-                                               "Colorspace",
-                                               hdmi_colorspaces,
-                                               ARRAY_SIZE(hdmi_colorspaces));
-               if (!prop)
-                       return -ENOMEM;
-       } else {
-               DRM_DEBUG_KMS("Colorspace property not supported\n");
+       if (connector->colorspace_property)
                return 0;
-       }
 
-       connector->colorspace_property = prop;
+       connector->colorspace_property =
+               drm_property_create_enum(dev, DRM_MODE_PROP_ENUM, "Colorspace",
+                                        hdmi_colorspaces,
+                                        ARRAY_SIZE(hdmi_colorspaces));
+
+       if (!connector->colorspace_property)
+               return -ENOMEM;
+
+       return 0;
+}
+EXPORT_SYMBOL(drm_mode_create_hdmi_colorspace_property);
+
+/**
+ * drm_mode_create_dp_colorspace_property - create dp colorspace property
+ * @connector: connector to create the Colorspace property on.
+ *
+ * Called by a driver the first time it's needed, must be attached to desired
+ * DP connectors.
+ *
+ * Returns:
+ * Zero on success, negative errono on failure.
+ */
+int drm_mode_create_dp_colorspace_property(struct drm_connector *connector)
+{
+       struct drm_device *dev = connector->dev;
+
+       if (connector->colorspace_property)
+               return 0;
+
+       connector->colorspace_property =
+               drm_property_create_enum(dev, DRM_MODE_PROP_ENUM, "Colorspace",
+                                        dp_colorspaces,
+                                        ARRAY_SIZE(dp_colorspaces));
+
+       if (!connector->colorspace_property)
+               return -ENOMEM;
 
        return 0;
 }
-EXPORT_SYMBOL(drm_mode_create_colorspace_property);
+EXPORT_SYMBOL(drm_mode_create_dp_colorspace_property);
 
 /**
  * drm_mode_create_content_type_property - create content type property
@@ -2121,7 +2181,6 @@ int drm_mode_getconnector(struct drm_device *dev, void *data,
        int encoders_count = 0;
        int ret = 0;
        int copied = 0;
-       int i;
        struct drm_mode_modeinfo u_mode;
        struct drm_mode_modeinfo __user *mode_ptr;
        uint32_t __user *encoder_ptr;
@@ -2136,14 +2195,13 @@ int drm_mode_getconnector(struct drm_device *dev, void *data,
        if (!connector)
                return -ENOENT;
 
-       drm_connector_for_each_possible_encoder(connector, encoder, i)
-               encoders_count++;
+       encoders_count = hweight32(connector->possible_encoders);
 
        if ((out_resp->count_encoders >= encoders_count) && encoders_count) {
                copied = 0;
                encoder_ptr = (uint32_t __user *)(unsigned long)(out_resp->encoders_ptr);
 
-               drm_connector_for_each_possible_encoder(connector, encoder, i) {
+               drm_connector_for_each_possible_encoder(connector, encoder) {
                        if (put_user(encoder->base.id, encoder_ptr + copied)) {
                                ret = -EFAULT;
                                goto out;
index 80ddf13ad99612056ca44bd49e2669d201920399..499b05aaccfc2d5536ac2a44bf915c7486a357f7 100644 (file)
@@ -36,6 +36,7 @@
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_atomic_uapi.h>
+#include <drm/drm_bridge.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_crtc_helper.h>
 #include <drm/drm_drv.h>
@@ -459,6 +460,22 @@ drm_crtc_helper_disable(struct drm_crtc *crtc)
        __drm_helper_disable_unused_functions(dev);
 }
 
+/*
+ * For connectors that support multiple encoders, either the
+ * .atomic_best_encoder() or .best_encoder() operation must be implemented.
+ */
+struct drm_encoder *
+drm_connector_get_single_encoder(struct drm_connector *connector)
+{
+       struct drm_encoder *encoder;
+
+       WARN_ON(hweight32(connector->possible_encoders) > 1);
+       drm_connector_for_each_possible_encoder(connector, encoder)
+               return encoder;
+
+       return NULL;
+}
+
 /**
  * drm_crtc_helper_set_config - set a new config from userspace
  * @set: mode set configuration
@@ -624,7 +641,11 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set,
                new_encoder = connector->encoder;
                for (ro = 0; ro < set->num_connectors; ro++) {
                        if (set->connectors[ro] == connector) {
-                               new_encoder = connector_funcs->best_encoder(connector);
+                               if (connector_funcs->best_encoder)
+                                       new_encoder = connector_funcs->best_encoder(connector);
+                               else
+                                       new_encoder = drm_connector_get_single_encoder(connector);
+
                                /* if we can't get an encoder for a connector
                                   we are setting now - then fail */
                                if (new_encoder == NULL)
index b5ac1581e6231dce42bd3c12756d4830fb6b5556..f0a66ef47e5ad1b29b53724e344256287242e492 100644 (file)
@@ -75,3 +75,6 @@ enum drm_mode_status drm_encoder_mode_valid(struct drm_encoder *encoder,
                                            const struct drm_display_mode *mode);
 enum drm_mode_status drm_connector_mode_valid(struct drm_connector *connector,
                                              struct drm_display_mode *mode);
+
+struct drm_encoder *
+drm_connector_get_single_encoder(struct drm_connector *connector);
index be1b7ba92ffe1e5e041c4d794edc0c0972da5ae4..ca3c55c6b81550270c4953ecac2d3005f7741ad7 100644 (file)
@@ -334,19 +334,17 @@ static ssize_t crtc_crc_read(struct file *filep, char __user *user_buf,
        return LINE_LEN(crc->values_cnt);
 }
 
-static unsigned int crtc_crc_poll(struct file *file, poll_table *wait)
+static __poll_t crtc_crc_poll(struct file *file, poll_table *wait)
 {
        struct drm_crtc *crtc = file->f_inode->i_private;
        struct drm_crtc_crc *crc = &crtc->crc;
-       unsigned ret;
+       __poll_t ret = 0;
 
        poll_wait(file, &crc->wq, wait);
 
        spin_lock_irq(&crc->lock);
        if (crc->source && crtc_crc_data_count(crc))
-               ret = POLLIN | POLLRDNORM;
-       else
-               ret = 0;
+               ret |= EPOLLIN | EPOLLRDNORM;
        spin_unlock_irq(&crc->lock);
 
        return ret;
index b15cee85b702b257f0ebdd19c3d2f6e4995207fc..b457c16c3a8bb546ce6dfc49150919efdd24a261 100644 (file)
@@ -8,7 +8,9 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/slab.h>
+#include <drm/drm_connector.h>
 #include <drm/drm_dp_helper.h>
+#include <drm/drmP.h>
 #include <media/cec.h>
 
 /*
@@ -295,7 +297,10 @@ static void drm_dp_cec_unregister_work(struct work_struct *work)
  */
 void drm_dp_cec_set_edid(struct drm_dp_aux *aux, const struct edid *edid)
 {
-       u32 cec_caps = CEC_CAP_DEFAULTS | CEC_CAP_NEEDS_HPD;
+       struct drm_connector *connector = aux->cec.connector;
+       u32 cec_caps = CEC_CAP_DEFAULTS | CEC_CAP_NEEDS_HPD |
+                      CEC_CAP_CONNECTOR_INFO;
+       struct cec_connector_info conn_info;
        unsigned int num_las = 1;
        u8 cap;
 
@@ -344,13 +349,17 @@ void drm_dp_cec_set_edid(struct drm_dp_aux *aux, const struct edid *edid)
 
        /* Create a new adapter */
        aux->cec.adap = cec_allocate_adapter(&drm_dp_cec_adap_ops,
-                                            aux, aux->cec.name, cec_caps,
+                                            aux, connector->name, cec_caps,
                                             num_las);
        if (IS_ERR(aux->cec.adap)) {
                aux->cec.adap = NULL;
                goto unlock;
        }
-       if (cec_register_adapter(aux->cec.adap, aux->cec.parent)) {
+
+       cec_fill_conn_info_from_drm(&conn_info, connector);
+       cec_s_conn_info(aux->cec.adap, &conn_info);
+
+       if (cec_register_adapter(aux->cec.adap, connector->dev->dev)) {
                cec_delete_adapter(aux->cec.adap);
                aux->cec.adap = NULL;
        } else {
@@ -406,22 +415,20 @@ EXPORT_SYMBOL(drm_dp_cec_unset_edid);
 /**
  * drm_dp_cec_register_connector() - register a new connector
  * @aux: DisplayPort AUX channel
- * @name: name of the CEC device
- * @parent: parent device
+ * @connector: drm connector
  *
  * A new connector was registered with associated CEC adapter name and
  * CEC adapter parent device. After registering the name and parent
  * drm_dp_cec_set_edid() is called to check if the connector supports
  * CEC and to register a CEC adapter if that is the case.
  */
-void drm_dp_cec_register_connector(struct drm_dp_aux *aux, const char *name,
-                                  struct device *parent)
+void drm_dp_cec_register_connector(struct drm_dp_aux *aux,
+                                  struct drm_connector *connector)
 {
        WARN_ON(aux->cec.adap);
        if (WARN_ON(!aux->transfer))
                return;
-       aux->cec.name = name;
-       aux->cec.parent = parent;
+       aux->cec.connector = connector;
        INIT_DELAYED_WORK(&aux->cec.unregister_work,
                          drm_dp_cec_unregister_work);
 }
index ffc68d305afe434c01cdaad5cad87969ac49b07c..f373798d82f62118a38bc1401935bfdb9a843b56 100644 (file)
@@ -1109,6 +1109,14 @@ EXPORT_SYMBOL(drm_dp_aux_init);
  * @aux: DisplayPort AUX channel
  *
  * Automatically calls drm_dp_aux_init() if this hasn't been done yet.
+ * This should only be called when the underlying &struct drm_connector is
+ * initialiazed already. Therefore the best place to call this is from
+ * &drm_connector_funcs.late_register. Not that drivers which don't follow this
+ * will Oops when CONFIG_DRM_DP_AUX_CHARDEV is enabled.
+ *
+ * Drivers which need to use the aux channel before that point (e.g. at driver
+ * load time, before drm_dev_register() has been called) need to call
+ * drm_dp_aux_init().
  *
  * Returns 0 on success or a negative error code on failure.
  */
index 82add736e17d52cba97b494f34b83f63f7fa82a7..6b14b63b8d623836b532e74d46e16c00eb7accfc 100644 (file)
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_dp_mst_helper.h>
 #include <drm/drm_drv.h>
-#include <drm/drm_fixed.h>
 #include <drm/drm_print.h>
 #include <drm/drm_probe_helper.h>
 
 #include "drm_crtc_helper_internal.h"
+#include "drm_dp_mst_topology_internal.h"
 
 /**
  * DOC: dp mst helper
@@ -47,7 +47,6 @@
  */
 static bool dump_dp_payload_table(struct drm_dp_mst_topology_mgr *mgr,
                                  char *buf);
-static int test_calc_pbn_mode(void);
 
 static void drm_dp_mst_topology_put_port(struct drm_dp_mst_port *port);
 
@@ -74,6 +73,8 @@ static int drm_dp_mst_register_i2c_bus(struct drm_dp_aux *aux);
 static void drm_dp_mst_unregister_i2c_bus(struct drm_dp_aux *aux);
 static void drm_dp_mst_kick_tx(struct drm_dp_mst_topology_mgr *mgr);
 
+#define DBG_PREFIX "[dp_mst]"
+
 #define DP_STR(x) [DP_ ## x] = #x
 
 static const char *drm_dp_mst_req_type_str(u8 req_type)
@@ -130,6 +131,43 @@ static const char *drm_dp_mst_nak_reason_str(u8 nak_reason)
 }
 
 #undef DP_STR
+#define DP_STR(x) [DRM_DP_SIDEBAND_TX_ ## x] = #x
+
+static const char *drm_dp_mst_sideband_tx_state_str(int state)
+{
+       static const char * const sideband_reason_str[] = {
+               DP_STR(QUEUED),
+               DP_STR(START_SEND),
+               DP_STR(SENT),
+               DP_STR(RX),
+               DP_STR(TIMEOUT),
+       };
+
+       if (state >= ARRAY_SIZE(sideband_reason_str) ||
+           !sideband_reason_str[state])
+               return "unknown";
+
+       return sideband_reason_str[state];
+}
+
+static int
+drm_dp_mst_rad_to_str(const u8 rad[8], u8 lct, char *out, size_t len)
+{
+       int i;
+       u8 unpacked_rad[16];
+
+       for (i = 0; i < lct; i++) {
+               if (i % 2)
+                       unpacked_rad[i] = rad[i / 2] >> 4;
+               else
+                       unpacked_rad[i] = rad[i / 2] & BIT_MASK(4);
+       }
+
+       /* TODO: Eventually add something to printk so we can format the rad
+        * like this: 1.2.3
+        */
+       return snprintf(out, len, "%*phC", lct, unpacked_rad);
+}
 
 /* sideband msg handling */
 static u8 drm_dp_msg_header_crc4(const uint8_t *data, size_t num_nibbles)
@@ -262,8 +300,9 @@ static bool drm_dp_decode_sideband_msg_hdr(struct drm_dp_sideband_msg_hdr *hdr,
        return true;
 }
 
-static void drm_dp_encode_sideband_req(struct drm_dp_sideband_msg_req_body *req,
-                                      struct drm_dp_sideband_msg_tx *raw)
+void
+drm_dp_encode_sideband_req(const struct drm_dp_sideband_msg_req_body *req,
+                          struct drm_dp_sideband_msg_tx *raw)
 {
        int idx = 0;
        int i;
@@ -272,6 +311,8 @@ static void drm_dp_encode_sideband_req(struct drm_dp_sideband_msg_req_body *req,
 
        switch (req->req_type) {
        case DP_ENUM_PATH_RESOURCES:
+       case DP_POWER_DOWN_PHY:
+       case DP_POWER_UP_PHY:
                buf[idx] = (req->u.port_num.port_number & 0xf) << 4;
                idx++;
                break;
@@ -359,14 +400,253 @@ static void drm_dp_encode_sideband_req(struct drm_dp_sideband_msg_req_body *req,
                memcpy(&buf[idx], req->u.i2c_write.bytes, req->u.i2c_write.num_bytes);
                idx += req->u.i2c_write.num_bytes;
                break;
+       }
+       raw->cur_len = idx;
+}
+EXPORT_SYMBOL_FOR_TESTS_ONLY(drm_dp_encode_sideband_req);
+
+/* Decode a sideband request we've encoded, mainly used for debugging */
+int
+drm_dp_decode_sideband_req(const struct drm_dp_sideband_msg_tx *raw,
+                          struct drm_dp_sideband_msg_req_body *req)
+{
+       const u8 *buf = raw->msg;
+       int i, idx = 0;
 
+       req->req_type = buf[idx++] & 0x7f;
+       switch (req->req_type) {
+       case DP_ENUM_PATH_RESOURCES:
        case DP_POWER_DOWN_PHY:
        case DP_POWER_UP_PHY:
-               buf[idx] = (req->u.port_num.port_number & 0xf) << 4;
-               idx++;
+               req->u.port_num.port_number = (buf[idx] >> 4) & 0xf;
+               break;
+       case DP_ALLOCATE_PAYLOAD:
+               {
+                       struct drm_dp_allocate_payload *a =
+                               &req->u.allocate_payload;
+
+                       a->number_sdp_streams = buf[idx] & 0xf;
+                       a->port_number = (buf[idx] >> 4) & 0xf;
+
+                       WARN_ON(buf[++idx] & 0x80);
+                       a->vcpi = buf[idx] & 0x7f;
+
+                       a->pbn = buf[++idx] << 8;
+                       a->pbn |= buf[++idx];
+
+                       idx++;
+                       for (i = 0; i < a->number_sdp_streams; i++) {
+                               a->sdp_stream_sink[i] =
+                                       (buf[idx + (i / 2)] >> ((i % 2) ? 0 : 4)) & 0xf;
+                       }
+               }
+               break;
+       case DP_QUERY_PAYLOAD:
+               req->u.query_payload.port_number = (buf[idx] >> 4) & 0xf;
+               WARN_ON(buf[++idx] & 0x80);
+               req->u.query_payload.vcpi = buf[idx] & 0x7f;
+               break;
+       case DP_REMOTE_DPCD_READ:
+               {
+                       struct drm_dp_remote_dpcd_read *r = &req->u.dpcd_read;
+
+                       r->port_number = (buf[idx] >> 4) & 0xf;
+
+                       r->dpcd_address = (buf[idx] << 16) & 0xf0000;
+                       r->dpcd_address |= (buf[++idx] << 8) & 0xff00;
+                       r->dpcd_address |= buf[++idx] & 0xff;
+
+                       r->num_bytes = buf[++idx];
+               }
+               break;
+       case DP_REMOTE_DPCD_WRITE:
+               {
+                       struct drm_dp_remote_dpcd_write *w =
+                               &req->u.dpcd_write;
+
+                       w->port_number = (buf[idx] >> 4) & 0xf;
+
+                       w->dpcd_address = (buf[idx] << 16) & 0xf0000;
+                       w->dpcd_address |= (buf[++idx] << 8) & 0xff00;
+                       w->dpcd_address |= buf[++idx] & 0xff;
+
+                       w->num_bytes = buf[++idx];
+
+                       w->bytes = kmemdup(&buf[++idx], w->num_bytes,
+                                          GFP_KERNEL);
+                       if (!w->bytes)
+                               return -ENOMEM;
+               }
+               break;
+       case DP_REMOTE_I2C_READ:
+               {
+                       struct drm_dp_remote_i2c_read *r = &req->u.i2c_read;
+                       struct drm_dp_remote_i2c_read_tx *tx;
+                       bool failed = false;
+
+                       r->num_transactions = buf[idx] & 0x3;
+                       r->port_number = (buf[idx] >> 4) & 0xf;
+                       for (i = 0; i < r->num_transactions; i++) {
+                               tx = &r->transactions[i];
+
+                               tx->i2c_dev_id = buf[++idx] & 0x7f;
+                               tx->num_bytes = buf[++idx];
+                               tx->bytes = kmemdup(&buf[++idx],
+                                                   tx->num_bytes,
+                                                   GFP_KERNEL);
+                               if (!tx->bytes) {
+                                       failed = true;
+                                       break;
+                               }
+                               idx += tx->num_bytes;
+                               tx->no_stop_bit = (buf[idx] >> 5) & 0x1;
+                               tx->i2c_transaction_delay = buf[idx] & 0xf;
+                       }
+
+                       if (failed) {
+                               for (i = 0; i < r->num_transactions; i++)
+                                       kfree(tx->bytes);
+                               return -ENOMEM;
+                       }
+
+                       r->read_i2c_device_id = buf[++idx] & 0x7f;
+                       r->num_bytes_read = buf[++idx];
+               }
+               break;
+       case DP_REMOTE_I2C_WRITE:
+               {
+                       struct drm_dp_remote_i2c_write *w = &req->u.i2c_write;
+
+                       w->port_number = (buf[idx] >> 4) & 0xf;
+                       w->write_i2c_device_id = buf[++idx] & 0x7f;
+                       w->num_bytes = buf[++idx];
+                       w->bytes = kmemdup(&buf[++idx], w->num_bytes,
+                                          GFP_KERNEL);
+                       if (!w->bytes)
+                               return -ENOMEM;
+               }
+               break;
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL_FOR_TESTS_ONLY(drm_dp_decode_sideband_req);
+
+void
+drm_dp_dump_sideband_msg_req_body(const struct drm_dp_sideband_msg_req_body *req,
+                                 int indent, struct drm_printer *printer)
+{
+       int i;
+
+#define P(f, ...) drm_printf_indent(printer, indent, f, ##__VA_ARGS__)
+       if (req->req_type == DP_LINK_ADDRESS) {
+               /* No contents to print */
+               P("type=%s\n", drm_dp_mst_req_type_str(req->req_type));
+               return;
+       }
+
+       P("type=%s contents:\n", drm_dp_mst_req_type_str(req->req_type));
+       indent++;
+
+       switch (req->req_type) {
+       case DP_ENUM_PATH_RESOURCES:
+       case DP_POWER_DOWN_PHY:
+       case DP_POWER_UP_PHY:
+               P("port=%d\n", req->u.port_num.port_number);
+               break;
+       case DP_ALLOCATE_PAYLOAD:
+               P("port=%d vcpi=%d pbn=%d sdp_streams=%d %*ph\n",
+                 req->u.allocate_payload.port_number,
+                 req->u.allocate_payload.vcpi, req->u.allocate_payload.pbn,
+                 req->u.allocate_payload.number_sdp_streams,
+                 req->u.allocate_payload.number_sdp_streams,
+                 req->u.allocate_payload.sdp_stream_sink);
+               break;
+       case DP_QUERY_PAYLOAD:
+               P("port=%d vcpi=%d\n",
+                 req->u.query_payload.port_number,
+                 req->u.query_payload.vcpi);
+               break;
+       case DP_REMOTE_DPCD_READ:
+               P("port=%d dpcd_addr=%05x len=%d\n",
+                 req->u.dpcd_read.port_number, req->u.dpcd_read.dpcd_address,
+                 req->u.dpcd_read.num_bytes);
+               break;
+       case DP_REMOTE_DPCD_WRITE:
+               P("port=%d addr=%05x len=%d: %*ph\n",
+                 req->u.dpcd_write.port_number,
+                 req->u.dpcd_write.dpcd_address,
+                 req->u.dpcd_write.num_bytes, req->u.dpcd_write.num_bytes,
+                 req->u.dpcd_write.bytes);
+               break;
+       case DP_REMOTE_I2C_READ:
+               P("port=%d num_tx=%d id=%d size=%d:\n",
+                 req->u.i2c_read.port_number,
+                 req->u.i2c_read.num_transactions,
+                 req->u.i2c_read.read_i2c_device_id,
+                 req->u.i2c_read.num_bytes_read);
+
+               indent++;
+               for (i = 0; i < req->u.i2c_read.num_transactions; i++) {
+                       const struct drm_dp_remote_i2c_read_tx *rtx =
+                               &req->u.i2c_read.transactions[i];
+
+                       P("%d: id=%03d size=%03d no_stop_bit=%d tx_delay=%03d: %*ph\n",
+                         i, rtx->i2c_dev_id, rtx->num_bytes,
+                         rtx->no_stop_bit, rtx->i2c_transaction_delay,
+                         rtx->num_bytes, rtx->bytes);
+               }
+               break;
+       case DP_REMOTE_I2C_WRITE:
+               P("port=%d id=%d size=%d: %*ph\n",
+                 req->u.i2c_write.port_number,
+                 req->u.i2c_write.write_i2c_device_id,
+                 req->u.i2c_write.num_bytes, req->u.i2c_write.num_bytes,
+                 req->u.i2c_write.bytes);
+               break;
+       default:
+               P("???\n");
+               break;
+       }
+#undef P
+}
+EXPORT_SYMBOL_FOR_TESTS_ONLY(drm_dp_dump_sideband_msg_req_body);
+
+static inline void
+drm_dp_mst_dump_sideband_msg_tx(struct drm_printer *p,
+                               const struct drm_dp_sideband_msg_tx *txmsg)
+{
+       struct drm_dp_sideband_msg_req_body req;
+       char buf[64];
+       int ret;
+       int i;
+
+       drm_dp_mst_rad_to_str(txmsg->dst->rad, txmsg->dst->lct, buf,
+                             sizeof(buf));
+       drm_printf(p, "txmsg cur_offset=%x cur_len=%x seqno=%x state=%s path_msg=%d dst=%s\n",
+                  txmsg->cur_offset, txmsg->cur_len, txmsg->seqno,
+                  drm_dp_mst_sideband_tx_state_str(txmsg->state),
+                  txmsg->path_msg, buf);
+
+       ret = drm_dp_decode_sideband_req(txmsg, &req);
+       if (ret) {
+               drm_printf(p, "<failed to decode sideband req: %d>\n", ret);
+               return;
+       }
+       drm_dp_dump_sideband_msg_req_body(&req, 1, p);
+
+       switch (req.req_type) {
+       case DP_REMOTE_DPCD_WRITE:
+               kfree(req.u.dpcd_write.bytes);
+               break;
+       case DP_REMOTE_I2C_READ:
+               for (i = 0; i < req.u.i2c_read.num_transactions; i++)
+                       kfree(req.u.i2c_read.transactions[i].bytes);
+               break;
+       case DP_REMOTE_I2C_WRITE:
+               kfree(req.u.i2c_write.bytes);
                break;
        }
-       raw->cur_len = idx;
 }
 
 static void drm_dp_crc_sideband_chunk_req(u8 *msg, u8 len)
@@ -842,11 +1122,11 @@ static void drm_dp_mst_put_payload_id(struct drm_dp_mst_topology_mgr *mgr,
        clear_bit(vcpi - 1, &mgr->vcpi_mask);
 
        for (i = 0; i < mgr->max_payloads; i++) {
-               if (mgr->proposed_vcpis[i])
-                       if (mgr->proposed_vcpis[i]->vcpi == vcpi) {
-                               mgr->proposed_vcpis[i] = NULL;
-                               clear_bit(i + 1, &mgr->payload_mask);
-                       }
+               if (mgr->proposed_vcpis[i] &&
+                   mgr->proposed_vcpis[i]->vcpi == vcpi) {
+                       mgr->proposed_vcpis[i] = NULL;
+                       clear_bit(i + 1, &mgr->payload_mask);
+               }
        }
        mutex_unlock(&mgr->payload_lock);
 }
@@ -899,6 +1179,11 @@ static int drm_dp_mst_wait_tx_reply(struct drm_dp_mst_branch *mstb,
                }
        }
 out:
+       if (unlikely(ret == -EIO) && drm_debug_enabled(DRM_UT_DP)) {
+               struct drm_printer p = drm_debug_printer(DBG_PREFIX);
+
+               drm_dp_mst_dump_sideband_msg_tx(&p, txmsg);
+       }
        mutex_unlock(&mgr->qlock);
 
        return ret;
@@ -1617,9 +1902,10 @@ void drm_dp_mst_connector_early_unregister(struct drm_connector *connector,
 }
 EXPORT_SYMBOL(drm_dp_mst_connector_early_unregister);
 
-static void drm_dp_add_port(struct drm_dp_mst_branch *mstb,
-                           struct drm_device *dev,
-                           struct drm_dp_link_addr_reply_port *port_msg)
+static void
+drm_dp_mst_handle_link_address_port(struct drm_dp_mst_branch *mstb,
+                                   struct drm_device *dev,
+                                   struct drm_dp_link_addr_reply_port *port_msg)
 {
        struct drm_dp_mst_port *port;
        bool ret;
@@ -1722,8 +2008,9 @@ out:
        drm_dp_mst_topology_put_port(port);
 }
 
-static void drm_dp_update_port(struct drm_dp_mst_branch *mstb,
-                              struct drm_dp_connection_status_notify *conn_stat)
+static void
+drm_dp_mst_handle_conn_stat(struct drm_dp_mst_branch *mstb,
+                           struct drm_dp_connection_status_notify *conn_stat)
 {
        struct drm_dp_mst_port *port;
        int old_pdt;
@@ -1800,7 +2087,7 @@ out:
 
 static struct drm_dp_mst_branch *get_mst_branch_device_by_guid_helper(
        struct drm_dp_mst_branch *mstb,
-       uint8_t *guid)
+       const uint8_t *guid)
 {
        struct drm_dp_mst_branch *found_mstb;
        struct drm_dp_mst_port *port;
@@ -1824,7 +2111,7 @@ static struct drm_dp_mst_branch *get_mst_branch_device_by_guid_helper(
 
 static struct drm_dp_mst_branch *
 drm_dp_get_mst_branch_device_by_guid(struct drm_dp_mst_topology_mgr *mgr,
-                                    uint8_t *guid)
+                                    const uint8_t *guid)
 {
        struct drm_dp_mst_branch *mstb;
        int ret;
@@ -2035,8 +2322,11 @@ static int process_single_tx_qlock(struct drm_dp_mst_topology_mgr *mgr,
        idx += tosend + 1;
 
        ret = drm_dp_send_sideband_msg(mgr, up, chunk, idx);
-       if (ret) {
-               DRM_DEBUG_KMS("sideband msg failed to send\n");
+       if (unlikely(ret) && drm_debug_enabled(DRM_UT_DP)) {
+               struct drm_printer p = drm_debug_printer(DBG_PREFIX);
+
+               drm_printf(&p, "sideband msg failed to send\n");
+               drm_dp_mst_dump_sideband_msg_tx(&p, txmsg);
                return ret;
        }
 
@@ -2098,17 +2388,46 @@ static void drm_dp_queue_down_tx(struct drm_dp_mst_topology_mgr *mgr,
 {
        mutex_lock(&mgr->qlock);
        list_add_tail(&txmsg->next, &mgr->tx_msg_downq);
+
+       if (drm_debug_enabled(DRM_UT_DP)) {
+               struct drm_printer p = drm_debug_printer(DBG_PREFIX);
+
+               drm_dp_mst_dump_sideband_msg_tx(&p, txmsg);
+       }
+
        if (list_is_singular(&mgr->tx_msg_downq))
                process_single_down_tx_qlock(mgr);
        mutex_unlock(&mgr->qlock);
 }
 
+static void
+drm_dp_dump_link_address(struct drm_dp_link_address_ack_reply *reply)
+{
+       struct drm_dp_link_addr_reply_port *port_reply;
+       int i;
+
+       for (i = 0; i < reply->nports; i++) {
+               port_reply = &reply->ports[i];
+               DRM_DEBUG_KMS("port %d: input %d, pdt: %d, pn: %d, dpcd_rev: %02x, mcs: %d, ddps: %d, ldps %d, sdp %d/%d\n",
+                             i,
+                             port_reply->input_port,
+                             port_reply->peer_device_type,
+                             port_reply->port_number,
+                             port_reply->dpcd_revision,
+                             port_reply->mcs,
+                             port_reply->ddps,
+                             port_reply->legacy_device_plug_status,
+                             port_reply->num_sdp_streams,
+                             port_reply->num_sdp_stream_sinks);
+       }
+}
+
 static void drm_dp_send_link_address(struct drm_dp_mst_topology_mgr *mgr,
                                     struct drm_dp_mst_branch *mstb)
 {
-       int len;
        struct drm_dp_sideband_msg_tx *txmsg;
-       int ret;
+       struct drm_dp_link_address_ack_reply *reply;
+       int i, len, ret;
 
        txmsg = kzalloc(sizeof(*txmsg), GFP_KERNEL);
        if (!txmsg)
@@ -2120,48 +2439,44 @@ static void drm_dp_send_link_address(struct drm_dp_mst_topology_mgr *mgr,
        mstb->link_address_sent = true;
        drm_dp_queue_down_tx(mgr, txmsg);
 
+       /* FIXME: Actually do some real error handling here */
        ret = drm_dp_mst_wait_tx_reply(mstb, txmsg);
-       if (ret > 0) {
-               int i;
+       if (ret <= 0) {
+               DRM_ERROR("Sending link address failed with %d\n", ret);
+               goto out;
+       }
+       if (txmsg->reply.reply_type == DP_SIDEBAND_REPLY_NAK) {
+               DRM_ERROR("link address NAK received\n");
+               ret = -EIO;
+               goto out;
+       }
 
-               if (txmsg->reply.reply_type == DP_SIDEBAND_REPLY_NAK) {
-                       DRM_DEBUG_KMS("link address nak received\n");
-               } else {
-                       DRM_DEBUG_KMS("link address reply: %d\n", txmsg->reply.u.link_addr.nports);
-                       for (i = 0; i < txmsg->reply.u.link_addr.nports; i++) {
-                               DRM_DEBUG_KMS("port %d: input %d, pdt: %d, pn: %d, dpcd_rev: %02x, mcs: %d, ddps: %d, ldps %d, sdp %d/%d\n", i,
-                                      txmsg->reply.u.link_addr.ports[i].input_port,
-                                      txmsg->reply.u.link_addr.ports[i].peer_device_type,
-                                      txmsg->reply.u.link_addr.ports[i].port_number,
-                                      txmsg->reply.u.link_addr.ports[i].dpcd_revision,
-                                      txmsg->reply.u.link_addr.ports[i].mcs,
-                                      txmsg->reply.u.link_addr.ports[i].ddps,
-                                      txmsg->reply.u.link_addr.ports[i].legacy_device_plug_status,
-                                      txmsg->reply.u.link_addr.ports[i].num_sdp_streams,
-                                      txmsg->reply.u.link_addr.ports[i].num_sdp_stream_sinks);
-                       }
+       reply = &txmsg->reply.u.link_addr;
+       DRM_DEBUG_KMS("link address reply: %d\n", reply->nports);
+       drm_dp_dump_link_address(reply);
 
-                       drm_dp_check_mstb_guid(mstb, txmsg->reply.u.link_addr.guid);
+       drm_dp_check_mstb_guid(mstb, reply->guid);
 
-                       for (i = 0; i < txmsg->reply.u.link_addr.nports; i++) {
-                               drm_dp_add_port(mstb, mgr->dev, &txmsg->reply.u.link_addr.ports[i]);
-                       }
-                       drm_kms_helper_hotplug_event(mgr->dev);
-               }
-       } else {
-               mstb->link_address_sent = false;
-               DRM_DEBUG_KMS("link address failed %d\n", ret);
-       }
+       for (i = 0; i < reply->nports; i++)
+               drm_dp_mst_handle_link_address_port(mstb, mgr->dev,
+                                                   &reply->ports[i]);
+
+       drm_kms_helper_hotplug_event(mgr->dev);
 
+out:
+       if (ret <= 0)
+               mstb->link_address_sent = false;
        kfree(txmsg);
 }
 
-static int drm_dp_send_enum_path_resources(struct drm_dp_mst_topology_mgr *mgr,
-                                          struct drm_dp_mst_branch *mstb,
-                                          struct drm_dp_mst_port *port)
+static int
+drm_dp_send_enum_path_resources(struct drm_dp_mst_topology_mgr *mgr,
+                               struct drm_dp_mst_branch *mstb,
+                               struct drm_dp_mst_port *port)
 {
-       int len;
+       struct drm_dp_enum_path_resources_ack_reply *path_res;
        struct drm_dp_sideband_msg_tx *txmsg;
+       int len;
        int ret;
 
        txmsg = kzalloc(sizeof(*txmsg), GFP_KERNEL);
@@ -2175,14 +2490,20 @@ static int drm_dp_send_enum_path_resources(struct drm_dp_mst_topology_mgr *mgr,
 
        ret = drm_dp_mst_wait_tx_reply(mstb, txmsg);
        if (ret > 0) {
+               path_res = &txmsg->reply.u.path_resources;
+
                if (txmsg->reply.reply_type == DP_SIDEBAND_REPLY_NAK) {
                        DRM_DEBUG_KMS("enum path resources nak received\n");
                } else {
-                       if (port->port_num != txmsg->reply.u.path_resources.port_number)
+                       if (port->port_num != path_res->port_number)
                                DRM_ERROR("got incorrect port in response\n");
-                       DRM_DEBUG_KMS("enum path resources %d: %d %d\n", txmsg->reply.u.path_resources.port_number, txmsg->reply.u.path_resources.full_payload_bw_number,
-                              txmsg->reply.u.path_resources.avail_payload_bw_number);
-                       port->available_pbn = txmsg->reply.u.path_resources.avail_payload_bw_number;
+
+                       DRM_DEBUG_KMS("enum path resources %d: %d %d\n",
+                                     path_res->port_number,
+                                     path_res->full_payload_bw_number,
+                                     path_res->avail_payload_bw_number);
+                       port->available_pbn =
+                               path_res->avail_payload_bw_number;
                }
        }
 
@@ -2655,30 +2976,13 @@ static int drm_dp_send_up_ack_reply(struct drm_dp_mst_topology_mgr *mgr,
        return 0;
 }
 
-static bool drm_dp_get_vc_payload_bw(int dp_link_bw,
-                                    int dp_link_count,
-                                    int *out)
+static int drm_dp_get_vc_payload_bw(u8 dp_link_bw, u8  dp_link_count)
 {
-       switch (dp_link_bw) {
-       default:
+       if (dp_link_bw == 0 || dp_link_count == 0)
                DRM_DEBUG_KMS("invalid link bandwidth in DPCD: %x (link count: %d)\n",
                              dp_link_bw, dp_link_count);
-               return false;
 
-       case DP_LINK_BW_1_62:
-               *out = 3 * dp_link_count;
-               break;
-       case DP_LINK_BW_2_7:
-               *out = 5 * dp_link_count;
-               break;
-       case DP_LINK_BW_5_4:
-               *out = 10 * dp_link_count;
-               break;
-       case DP_LINK_BW_8_1:
-               *out = 15 * dp_link_count;
-               break;
-       }
-       return true;
+       return dp_link_bw * dp_link_count / 2;
 }
 
 /**
@@ -2710,9 +3014,9 @@ int drm_dp_mst_topology_mgr_set_mst(struct drm_dp_mst_topology_mgr *mgr, bool ms
                        goto out_unlock;
                }
 
-               if (!drm_dp_get_vc_payload_bw(mgr->dpcd[1],
-                                             mgr->dpcd[2] & DP_MAX_LANE_COUNT_MASK,
-                                             &mgr->pbn_div)) {
+               mgr->pbn_div = drm_dp_get_vc_payload_bw(mgr->dpcd[1],
+                                                       mgr->dpcd[2] & DP_MAX_LANE_COUNT_MASK);
+               if (mgr->pbn_div == 0) {
                        ret = -EINVAL;
                        goto out_unlock;
                }
@@ -2890,136 +3194,135 @@ static bool drm_dp_get_one_sb_msg(struct drm_dp_mst_topology_mgr *mgr, bool up)
 
 static int drm_dp_mst_handle_down_rep(struct drm_dp_mst_topology_mgr *mgr)
 {
-       int ret = 0;
+       struct drm_dp_sideband_msg_tx *txmsg;
+       struct drm_dp_mst_branch *mstb;
+       struct drm_dp_sideband_msg_hdr *hdr = &mgr->down_rep_recv.initial_hdr;
+       int slot = -1;
+
+       if (!drm_dp_get_one_sb_msg(mgr, false))
+               goto clear_down_rep_recv;
 
-       if (!drm_dp_get_one_sb_msg(mgr, false)) {
-               memset(&mgr->down_rep_recv, 0,
-                      sizeof(struct drm_dp_sideband_msg_rx));
+       if (!mgr->down_rep_recv.have_eomt)
                return 0;
+
+       mstb = drm_dp_get_mst_branch_device(mgr, hdr->lct, hdr->rad);
+       if (!mstb) {
+               DRM_DEBUG_KMS("Got MST reply from unknown device %d\n",
+                             hdr->lct);
+               goto clear_down_rep_recv;
        }
 
-       if (mgr->down_rep_recv.have_eomt) {
-               struct drm_dp_sideband_msg_tx *txmsg;
-               struct drm_dp_mst_branch *mstb;
-               int slot = -1;
-               mstb = drm_dp_get_mst_branch_device(mgr,
-                                                   mgr->down_rep_recv.initial_hdr.lct,
-                                                   mgr->down_rep_recv.initial_hdr.rad);
+       /* find the message */
+       slot = hdr->seqno;
+       mutex_lock(&mgr->qlock);
+       txmsg = mstb->tx_slots[slot];
+       /* remove from slots */
+       mutex_unlock(&mgr->qlock);
 
-               if (!mstb) {
-                       DRM_DEBUG_KMS("Got MST reply from unknown device %d\n", mgr->down_rep_recv.initial_hdr.lct);
-                       memset(&mgr->down_rep_recv, 0, sizeof(struct drm_dp_sideband_msg_rx));
-                       return 0;
-               }
+       if (!txmsg) {
+               DRM_DEBUG_KMS("Got MST reply with no msg %p %d %d %02x %02x\n",
+                             mstb, hdr->seqno, hdr->lct, hdr->rad[0],
+                             mgr->down_rep_recv.msg[0]);
+               goto no_msg;
+       }
 
-               /* find the message */
-               slot = mgr->down_rep_recv.initial_hdr.seqno;
-               mutex_lock(&mgr->qlock);
-               txmsg = mstb->tx_slots[slot];
-               /* remove from slots */
-               mutex_unlock(&mgr->qlock);
-
-               if (!txmsg) {
-                       DRM_DEBUG_KMS("Got MST reply with no msg %p %d %d %02x %02x\n",
-                              mstb,
-                              mgr->down_rep_recv.initial_hdr.seqno,
-                              mgr->down_rep_recv.initial_hdr.lct,
-                                     mgr->down_rep_recv.initial_hdr.rad[0],
-                                     mgr->down_rep_recv.msg[0]);
-                       drm_dp_mst_topology_put_mstb(mstb);
-                       memset(&mgr->down_rep_recv, 0, sizeof(struct drm_dp_sideband_msg_rx));
-                       return 0;
-               }
+       drm_dp_sideband_parse_reply(&mgr->down_rep_recv, &txmsg->reply);
 
-               drm_dp_sideband_parse_reply(&mgr->down_rep_recv, &txmsg->reply);
+       if (txmsg->reply.reply_type == DP_SIDEBAND_REPLY_NAK)
+               DRM_DEBUG_KMS("Got NAK reply: req 0x%02x (%s), reason 0x%02x (%s), nak data 0x%02x\n",
+                             txmsg->reply.req_type,
+                             drm_dp_mst_req_type_str(txmsg->reply.req_type),
+                             txmsg->reply.u.nak.reason,
+                             drm_dp_mst_nak_reason_str(txmsg->reply.u.nak.reason),
+                             txmsg->reply.u.nak.nak_data);
 
-               if (txmsg->reply.reply_type == DP_SIDEBAND_REPLY_NAK)
-                       DRM_DEBUG_KMS("Got NAK reply: req 0x%02x (%s), reason 0x%02x (%s), nak data 0x%02x\n",
-                                     txmsg->reply.req_type,
-                                     drm_dp_mst_req_type_str(txmsg->reply.req_type),
-                                     txmsg->reply.u.nak.reason,
-                                     drm_dp_mst_nak_reason_str(txmsg->reply.u.nak.reason),
-                                     txmsg->reply.u.nak.nak_data);
-
-               memset(&mgr->down_rep_recv, 0, sizeof(struct drm_dp_sideband_msg_rx));
-               drm_dp_mst_topology_put_mstb(mstb);
+       memset(&mgr->down_rep_recv, 0, sizeof(struct drm_dp_sideband_msg_rx));
+       drm_dp_mst_topology_put_mstb(mstb);
 
-               mutex_lock(&mgr->qlock);
-               txmsg->state = DRM_DP_SIDEBAND_TX_RX;
-               mstb->tx_slots[slot] = NULL;
-               mutex_unlock(&mgr->qlock);
+       mutex_lock(&mgr->qlock);
+       txmsg->state = DRM_DP_SIDEBAND_TX_RX;
+       mstb->tx_slots[slot] = NULL;
+       mutex_unlock(&mgr->qlock);
 
-               wake_up_all(&mgr->tx_waitq);
-       }
-       return ret;
+       wake_up_all(&mgr->tx_waitq);
+
+       return 0;
+
+no_msg:
+       drm_dp_mst_topology_put_mstb(mstb);
+clear_down_rep_recv:
+       memset(&mgr->down_rep_recv, 0, sizeof(struct drm_dp_sideband_msg_rx));
+
+       return 0;
 }
 
 static int drm_dp_mst_handle_up_req(struct drm_dp_mst_topology_mgr *mgr)
 {
-       int ret = 0;
+       struct drm_dp_sideband_msg_req_body msg;
+       struct drm_dp_sideband_msg_hdr *hdr = &mgr->up_req_recv.initial_hdr;
+       struct drm_dp_mst_branch *mstb = NULL;
+       const u8 *guid;
+       bool seqno;
+
+       if (!drm_dp_get_one_sb_msg(mgr, true))
+               goto out;
 
-       if (!drm_dp_get_one_sb_msg(mgr, true)) {
-               memset(&mgr->up_req_recv, 0,
-                      sizeof(struct drm_dp_sideband_msg_rx));
+       if (!mgr->up_req_recv.have_eomt)
                return 0;
-       }
 
-       if (mgr->up_req_recv.have_eomt) {
-               struct drm_dp_sideband_msg_req_body msg;
-               struct drm_dp_mst_branch *mstb = NULL;
-               bool seqno;
-
-               if (!mgr->up_req_recv.initial_hdr.broadcast) {
-                       mstb = drm_dp_get_mst_branch_device(mgr,
-                                                           mgr->up_req_recv.initial_hdr.lct,
-                                                           mgr->up_req_recv.initial_hdr.rad);
-                       if (!mstb) {
-                               DRM_DEBUG_KMS("Got MST reply from unknown device %d\n", mgr->up_req_recv.initial_hdr.lct);
-                               memset(&mgr->up_req_recv, 0, sizeof(struct drm_dp_sideband_msg_rx));
-                               return 0;
-                       }
+       if (!hdr->broadcast) {
+               mstb = drm_dp_get_mst_branch_device(mgr, hdr->lct, hdr->rad);
+               if (!mstb) {
+                       DRM_DEBUG_KMS("Got MST reply from unknown device %d\n",
+                                     hdr->lct);
+                       goto out;
                }
+       }
 
-               seqno = mgr->up_req_recv.initial_hdr.seqno;
-               drm_dp_sideband_parse_req(&mgr->up_req_recv, &msg);
-
-               if (msg.req_type == DP_CONNECTION_STATUS_NOTIFY) {
-                       drm_dp_send_up_ack_reply(mgr, mgr->mst_primary, msg.req_type, seqno, false);
-
-                       if (!mstb)
-                               mstb = drm_dp_get_mst_branch_device_by_guid(mgr, msg.u.conn_stat.guid);
-
-                       if (!mstb) {
-                               DRM_DEBUG_KMS("Got MST reply from unknown device %d\n", mgr->up_req_recv.initial_hdr.lct);
-                               memset(&mgr->up_req_recv, 0, sizeof(struct drm_dp_sideband_msg_rx));
-                               return 0;
-                       }
-
-                       drm_dp_update_port(mstb, &msg.u.conn_stat);
-
-                       DRM_DEBUG_KMS("Got CSN: pn: %d ldps:%d ddps: %d mcs: %d ip: %d pdt: %d\n", msg.u.conn_stat.port_number, msg.u.conn_stat.legacy_device_plug_status, msg.u.conn_stat.displayport_device_plug_status, msg.u.conn_stat.message_capability_status, msg.u.conn_stat.input_port, msg.u.conn_stat.peer_device_type);
-                       drm_kms_helper_hotplug_event(mgr->dev);
+       seqno = hdr->seqno;
+       drm_dp_sideband_parse_req(&mgr->up_req_recv, &msg);
 
-               } else if (msg.req_type == DP_RESOURCE_STATUS_NOTIFY) {
-                       drm_dp_send_up_ack_reply(mgr, mgr->mst_primary, msg.req_type, seqno, false);
-                       if (!mstb)
-                               mstb = drm_dp_get_mst_branch_device_by_guid(mgr, msg.u.resource_stat.guid);
+       if (msg.req_type == DP_CONNECTION_STATUS_NOTIFY)
+               guid = msg.u.conn_stat.guid;
+       else if (msg.req_type == DP_RESOURCE_STATUS_NOTIFY)
+               guid = msg.u.resource_stat.guid;
+       else
+               goto out;
 
-                       if (!mstb) {
-                               DRM_DEBUG_KMS("Got MST reply from unknown device %d\n", mgr->up_req_recv.initial_hdr.lct);
-                               memset(&mgr->up_req_recv, 0, sizeof(struct drm_dp_sideband_msg_rx));
-                               return 0;
-                       }
+       drm_dp_send_up_ack_reply(mgr, mgr->mst_primary, msg.req_type, seqno,
+                                false);
 
-                       DRM_DEBUG_KMS("Got RSN: pn: %d avail_pbn %d\n", msg.u.resource_stat.port_number, msg.u.resource_stat.available_pbn);
+       if (!mstb) {
+               mstb = drm_dp_get_mst_branch_device_by_guid(mgr, guid);
+               if (!mstb) {
+                       DRM_DEBUG_KMS("Got MST reply from unknown device %d\n",
+                                     hdr->lct);
+                       goto out;
                }
+       }
 
-               if (mstb)
-                       drm_dp_mst_topology_put_mstb(mstb);
+       if (msg.req_type == DP_CONNECTION_STATUS_NOTIFY) {
+               drm_dp_mst_handle_conn_stat(mstb, &msg.u.conn_stat);
 
-               memset(&mgr->up_req_recv, 0, sizeof(struct drm_dp_sideband_msg_rx));
+               DRM_DEBUG_KMS("Got CSN: pn: %d ldps:%d ddps: %d mcs: %d ip: %d pdt: %d\n",
+                             msg.u.conn_stat.port_number,
+                             msg.u.conn_stat.legacy_device_plug_status,
+                             msg.u.conn_stat.displayport_device_plug_status,
+                             msg.u.conn_stat.message_capability_status,
+                             msg.u.conn_stat.input_port,
+                             msg.u.conn_stat.peer_device_type);
+
+               drm_kms_helper_hotplug_event(mgr->dev);
+       } else if (msg.req_type == DP_RESOURCE_STATUS_NOTIFY) {
+               DRM_DEBUG_KMS("Got RSN: pn: %d avail_pbn %d\n",
+                             msg.u.resource_stat.port_number,
+                             msg.u.resource_stat.available_pbn);
        }
-       return ret;
+
+       drm_dp_mst_topology_put_mstb(mstb);
+out:
+       memset(&mgr->up_req_recv, 0, sizeof(struct drm_dp_sideband_msg_rx));
+       return 0;
 }
 
 /**
@@ -3539,13 +3842,6 @@ EXPORT_SYMBOL(drm_dp_check_act_status);
  */
 int drm_dp_calc_pbn_mode(int clock, int bpp)
 {
-       u64 kbps;
-       s64 peak_kbps;
-       u32 numerator;
-       u32 denominator;
-
-       kbps = clock * bpp;
-
        /*
         * margin 5300ppm + 300ppm ~ 0.6% as per spec, factor is 1.006
         * The unit of 54/64Mbytes/sec is an arbitrary unit chosen based on
@@ -3556,41 +3852,11 @@ int drm_dp_calc_pbn_mode(int clock, int bpp)
         * peak_kbps *= (64/54)
         * peak_kbps *= 8    convert to bytes
         */
-
-       numerator = 64 * 1006;
-       denominator = 54 * 8 * 1000 * 1000;
-
-       kbps *= numerator;
-       peak_kbps = drm_fixp_from_fraction(kbps, denominator);
-
-       return drm_fixp2int_ceil(peak_kbps);
+       return DIV_ROUND_UP_ULL(mul_u32_u32(clock * bpp, 64 * 1006),
+                               8 * 54 * 1000 * 1000);
 }
 EXPORT_SYMBOL(drm_dp_calc_pbn_mode);
 
-static int test_calc_pbn_mode(void)
-{
-       int ret;
-       ret = drm_dp_calc_pbn_mode(154000, 30);
-       if (ret != 689) {
-               DRM_ERROR("PBN calculation test failed - clock %d, bpp %d, expected PBN %d, actual PBN %d.\n",
-                               154000, 30, 689, ret);
-               return -EINVAL;
-       }
-       ret = drm_dp_calc_pbn_mode(234000, 30);
-       if (ret != 1047) {
-               DRM_ERROR("PBN calculation test failed - clock %d, bpp %d, expected PBN %d, actual PBN %d.\n",
-                               234000, 30, 1047, ret);
-               return -EINVAL;
-       }
-       ret = drm_dp_calc_pbn_mode(297000, 24);
-       if (ret != 1063) {
-               DRM_ERROR("PBN calculation test failed - clock %d, bpp %d, expected PBN %d, actual PBN %d.\n",
-                               297000, 24, 1063, ret);
-               return -EINVAL;
-       }
-       return 0;
-}
-
 /* we want to kick the TX after we've ack the up/down IRQs. */
 static void drm_dp_mst_kick_tx(struct drm_dp_mst_topology_mgr *mgr)
 {
@@ -3749,8 +4015,6 @@ static void drm_dp_destroy_connector_work(struct work_struct *work)
                list_del(&port->next);
                mutex_unlock(&mgr->destroy_connector_lock);
 
-               INIT_LIST_HEAD(&port->next);
-
                mgr->cbs->destroy_connector(mgr, port->connector);
 
                drm_dp_port_teardown_pdt(port, port->pdt);
@@ -3970,8 +4234,6 @@ int drm_dp_mst_topology_mgr_init(struct drm_dp_mst_topology_mgr *mgr,
        if (!mgr->proposed_vcpis)
                return -ENOMEM;
        set_bit(0, &mgr->payload_mask);
-       if (test_calc_pbn_mode() < 0)
-               DRM_ERROR("MST PBN self-test failed\n");
 
        mst_state = kzalloc(sizeof(*mst_state), GFP_KERNEL);
        if (mst_state == NULL)
@@ -4007,6 +4269,11 @@ void drm_dp_mst_topology_mgr_destroy(struct drm_dp_mst_topology_mgr *mgr)
        mgr->aux = NULL;
        drm_atomic_private_obj_fini(&mgr->base);
        mgr->funcs = NULL;
+
+       mutex_destroy(&mgr->destroy_connector_lock);
+       mutex_destroy(&mgr->payload_lock);
+       mutex_destroy(&mgr->qlock);
+       mutex_destroy(&mgr->lock);
 }
 EXPORT_SYMBOL(drm_dp_mst_topology_mgr_destroy);
 
diff --git a/drivers/gpu/drm/drm_dp_mst_topology_internal.h b/drivers/gpu/drm/drm_dp_mst_topology_internal.h
new file mode 100644 (file)
index 0000000..eeda9a6
--- /dev/null
@@ -0,0 +1,24 @@
+/* SPDX-License-Identifier: GPL-2.0-only
+ *
+ * Declarations for DP MST related functions which are only used in selftests
+ *
+ * Copyright Â© 2018 Red Hat
+ * Authors:
+ *     Lyude Paul <lyude@redhat.com>
+ */
+
+#ifndef _DRM_DP_MST_HELPER_INTERNAL_H_
+#define _DRM_DP_MST_HELPER_INTERNAL_H_
+
+#include <drm/drm_dp_mst_helper.h>
+
+void
+drm_dp_encode_sideband_req(const struct drm_dp_sideband_msg_req_body *req,
+                          struct drm_dp_sideband_msg_tx *raw);
+int drm_dp_decode_sideband_req(const struct drm_dp_sideband_msg_tx *raw,
+                              struct drm_dp_sideband_msg_req_body *req);
+void
+drm_dp_dump_sideband_msg_req_body(const struct drm_dp_sideband_msg_req_body *req,
+                                 int indent, struct drm_printer *printer);
+
+#endif /* !_DRM_DP_MST_HELPER_INTERNAL_H_ */
index 769feefeeeefbed02d7a257c249ddc90b64b9644..1b9b40a1c7c98659f1dbb23163a809be9438e745 100644 (file)
 #include "drm_internal.h"
 #include "drm_legacy.h"
 
-/*
- * drm_debug: Enable debug output.
- * Bitmask of DRM_UT_x. See include/drm/drm_print.h for details.
- */
-unsigned int drm_debug = 0;
-EXPORT_SYMBOL(drm_debug);
-
 MODULE_AUTHOR("Gareth Hughes, Leif Delgass, José Fonseca, Jon Smirl");
 MODULE_DESCRIPTION("DRM shared core routines");
 MODULE_LICENSE("GPL and additional rights");
-MODULE_PARM_DESC(debug, "Enable debug output, where each bit enables a debug category.\n"
-"\t\tBit 0 (0x01)  will enable CORE messages (drm core code)\n"
-"\t\tBit 1 (0x02)  will enable DRIVER messages (drm controller code)\n"
-"\t\tBit 2 (0x04)  will enable KMS messages (modesetting code)\n"
-"\t\tBit 3 (0x08)  will enable PRIME messages (prime code)\n"
-"\t\tBit 4 (0x10)  will enable ATOMIC messages (atomic code)\n"
-"\t\tBit 5 (0x20)  will enable VBL messages (vblank code)\n"
-"\t\tBit 7 (0x80)  will enable LEASE messages (leasing code)\n"
-"\t\tBit 8 (0x100) will enable DP messages (displayport code)");
-module_param_named(debug, drm_debug, int, 0600);
 
 static DEFINE_SPINLOCK(drm_minor_lock);
 static struct idr drm_minors_idr;
index 77f4e5ae4197259d78082bb9daf6cc6fcd922410..4a475d9696ff39dae1ace772c0af1f27897a07cc 100644 (file)
@@ -216,13 +216,11 @@ void drm_dsc_pps_payload_pack(struct drm_dsc_picture_parameter_set *pps_payload,
         */
        for (i = 0; i < DSC_NUM_BUF_RANGES; i++) {
                pps_payload->rc_range_parameters[i] =
-                       ((dsc_cfg->rc_range_params[i].range_min_qp <<
-                         DSC_PPS_RC_RANGE_MINQP_SHIFT) |
-                        (dsc_cfg->rc_range_params[i].range_max_qp <<
-                         DSC_PPS_RC_RANGE_MAXQP_SHIFT) |
-                        (dsc_cfg->rc_range_params[i].range_bpg_offset));
-               pps_payload->rc_range_parameters[i] =
-                       cpu_to_be16(pps_payload->rc_range_parameters[i]);
+                       cpu_to_be16((dsc_cfg->rc_range_params[i].range_min_qp <<
+                                    DSC_PPS_RC_RANGE_MINQP_SHIFT) |
+                                   (dsc_cfg->rc_range_params[i].range_max_qp <<
+                                    DSC_PPS_RC_RANGE_MAXQP_SHIFT) |
+                                   (dsc_cfg->rc_range_params[i].range_bpg_offset));
        }
 
        /* PPS 88 */
@@ -336,12 +334,6 @@ int drm_dsc_compute_rc_parameters(struct drm_dsc_config *vdsc_cfg)
        else
                vdsc_cfg->nfl_bpg_offset = 0;
 
-       /* 2^16 - 1 */
-       if (vdsc_cfg->nfl_bpg_offset > 65535) {
-               DRM_DEBUG_KMS("NflBpgOffset is too large for this slice height\n");
-               return -ERANGE;
-       }
-
        /* Number of groups used to code the entire slice */
        groups_total = groups_per_line * vdsc_cfg->slice_height;
 
@@ -371,11 +363,6 @@ int drm_dsc_compute_rc_parameters(struct drm_dsc_config *vdsc_cfg)
                vdsc_cfg->scale_increment_interval = 0;
        }
 
-       if (vdsc_cfg->scale_increment_interval > 65535) {
-               DRM_DEBUG_KMS("ScaleIncrementInterval is large for slice height\n");
-               return -ERANGE;
-       }
-
        /*
         * DSC spec mentions that bits_per_pixel specifies the target
         * bits/pixel (bpp) rate that is used by the encoder,
index 82a4ceed3fcf5a77bbb87b667b7c8375e9a19863..0552175313cbf1ccc3a97ef6de4d40fbf7472758 100644 (file)
@@ -1275,6 +1275,106 @@ static const struct drm_display_mode edid_cea_modes[] = {
                   4104, 4400, 0, 2160, 2168, 2178, 2250, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
          .vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
+       /* 108 - 1280x720@48Hz 16:9 */
+       { DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 90000, 1280, 2240,
+                  2280, 2500, 0, 720, 725, 730, 750, 0,
+                  DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+         .vrefresh = 48, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
+       /* 109 - 1280x720@48Hz 64:27 */
+       { DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 90000, 1280, 2240,
+                  2280, 2500, 0, 720, 725, 730, 750, 0,
+                  DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+         .vrefresh = 48, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
+       /* 110 - 1680x720@48Hz 64:27 */
+       { DRM_MODE("1680x720", DRM_MODE_TYPE_DRIVER, 99000, 1680, 2490,
+                  2530, 2750, 0, 720, 725, 730, 750, 0,
+                  DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+         .vrefresh = 48, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
+       /* 111 - 1920x1080@48Hz 16:9 */
+       { DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 148500, 1920, 2558,
+                  2602, 2750, 0, 1080, 1084, 1089, 1125, 0,
+                  DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+         .vrefresh = 48, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
+       /* 112 - 1920x1080@48Hz 64:27 */
+       { DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 148500, 1920, 2558,
+                  2602, 2750, 0, 1080, 1084, 1089, 1125, 0,
+                  DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+         .vrefresh = 48, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
+       /* 113 - 2560x1080@48Hz 64:27 */
+       { DRM_MODE("2560x1080", DRM_MODE_TYPE_DRIVER, 198000, 2560, 3558,
+                  3602, 3750, 0, 1080, 1084, 1089, 1100, 0,
+                  DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+         .vrefresh = 48, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
+       /* 114 - 3840x2160@48Hz 16:9 */
+       { DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 594000, 3840, 5116,
+                  5204, 5500, 0, 2160, 2168, 2178, 2250, 0,
+                  DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+         .vrefresh = 48, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
+       /* 115 - 4096x2160@48Hz 256:135 */
+       { DRM_MODE("4096x2160", DRM_MODE_TYPE_DRIVER, 594000, 4096, 5116,
+                  5204, 5500, 0, 2160, 2168, 2178, 2250, 0,
+                  DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+         .vrefresh = 48, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_256_135, },
+       /* 116 - 3840x2160@48Hz 64:27 */
+       { DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 594000, 3840, 5116,
+                  5204, 5500, 0, 2160, 2168, 2178, 2250, 0,
+                  DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+         .vrefresh = 48, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
+       /* 117 - 3840x2160@100Hz 16:9 */
+       { DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 1188000, 3840, 4896,
+                  4984, 5280, 0, 2160, 2168, 2178, 2250, 0,
+                  DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+         .vrefresh = 100, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
+       /* 118 - 3840x2160@120Hz 16:9 */
+       { DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 1188000, 3840, 4016,
+                  4104, 4400, 0, 2160, 2168, 2178, 2250, 0,
+                  DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+         .vrefresh = 120, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
+       /* 119 - 3840x2160@100Hz 64:27 */
+       { DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 1188000, 3840, 4896,
+                  4984, 5280, 0, 2160, 2168, 2178, 2250, 0,
+                  DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+         .vrefresh = 100, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
+       /* 120 - 3840x2160@120Hz 64:27 */
+       { DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 1188000, 3840, 4016,
+                  4104, 4400, 0, 2160, 2168, 2178, 2250, 0,
+                  DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+         .vrefresh = 120, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
+       /* 121 - 5120x2160@24Hz 64:27 */
+       { DRM_MODE("5120x2160", DRM_MODE_TYPE_DRIVER, 396000, 5120, 7116,
+                  7204, 7500, 0, 2160, 2168, 2178, 2200, 0,
+                  DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+         .vrefresh = 24, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
+       /* 122 - 5120x2160@25Hz 64:27 */
+       { DRM_MODE("5120x2160", DRM_MODE_TYPE_DRIVER, 396000, 5120, 6816,
+                  6904, 7200, 0, 2160, 2168, 2178, 2200, 0,
+                  DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+         .vrefresh = 25, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
+       /* 123 - 5120x2160@30Hz 64:27 */
+       { DRM_MODE("5120x2160", DRM_MODE_TYPE_DRIVER, 396000, 5120, 5784,
+                  5872, 6000, 0, 2160, 2168, 2178, 2200, 0,
+                  DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+         .vrefresh = 30, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
+       /* 124 - 5120x2160@48Hz 64:27 */
+       { DRM_MODE("5120x2160", DRM_MODE_TYPE_DRIVER, 742500, 5120, 5866,
+                  5954, 6250, 0, 2160, 2168, 2178, 2475, 0,
+                  DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+         .vrefresh = 48, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
+       /* 125 - 5120x2160@50Hz 64:27 */
+       { DRM_MODE("5120x2160", DRM_MODE_TYPE_DRIVER, 742500, 5120, 6216,
+                  6304, 6600, 0, 2160, 2168, 2178, 2250, 0,
+                  DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+         .vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
+       /* 126 - 5120x2160@60Hz 64:27 */
+       { DRM_MODE("5120x2160", DRM_MODE_TYPE_DRIVER, 742500, 5120, 5284,
+                  5372, 5500, 0, 2160, 2168, 2178, 2250, 0,
+                  DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+         .vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
+       /* 127 - 5120x2160@100Hz 64:27 */
+       { DRM_MODE("5120x2160", DRM_MODE_TYPE_DRIVER, 1485000, 5120, 6216,
+                  6304, 6600, 0, 2160, 2168, 2178, 2250, 0,
+                  DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+         .vrefresh = 100, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
 };
 
 /*
@@ -1551,7 +1651,7 @@ static void connector_bad_edid(struct drm_connector *connector,
 {
        int i;
 
-       if (connector->bad_edid_counter++ && !(drm_debug & DRM_UT_KMS))
+       if (connector->bad_edid_counter++ && !drm_debug_enabled(DRM_UT_KMS))
                return;
 
        dev_warn(connector->dev->dev,
@@ -3719,7 +3819,7 @@ cea_db_offsets(const u8 *cea, int *start, int *end)
                if (*end < 4 || *end > 127)
                        return -ERANGE;
        } else {
-               return -ENOTSUPP;
+               return -EOPNOTSUPP;
        }
 
        return 0;
@@ -4188,7 +4288,7 @@ int drm_edid_to_sad(struct edid *edid, struct cea_sad **sads)
 
        if (cea_revision(cea) < 3) {
                DRM_DEBUG_KMS("SAD: wrong CEA revision\n");
-               return -ENOTSUPP;
+               return -EOPNOTSUPP;
        }
 
        if (cea_db_offsets(cea, &start, &end)) {
@@ -4249,7 +4349,7 @@ int drm_edid_to_speaker_allocation(struct edid *edid, u8 **sadb)
 
        if (cea_revision(cea) < 3) {
                DRM_DEBUG_KMS("SAD: wrong CEA revision\n");
-               return -ENOTSUPP;
+               return -EOPNOTSUPP;
        }
 
        if (cea_db_offsets(cea, &start, &end)) {
index d38b3b255926e3783c66c86c09d55a1a478c2991..37d8ba3ddb46af97536f1950ae4ba44dee148be6 100644 (file)
@@ -175,7 +175,7 @@ static void *edid_load(struct drm_connector *connector, const char *name,
        u8 *edid;
        int fwsize, builtin;
        int i, valid_extensions = 0;
-       bool print_bad_edid = !connector->bad_edid_counter || (drm_debug & DRM_UT_KMS);
+       bool print_bad_edid = !connector->bad_edid_counter || drm_debug_enabled(DRM_UT_KMS);
 
        builtin = match_string(generic_edid_name, GENERIC_EDIDS, name);
        if (builtin >= 0) {
index 7fb47b7b8b44a5288e59023fb97644953edfa603..80d88a55302eca62ebc076785a33ff541754fc49 100644 (file)
@@ -22,6 +22,7 @@
 
 #include <linux/export.h>
 
+#include <drm/drm_bridge.h>
 #include <drm/drm_device.h>
 #include <drm/drm_drv.h>
 #include <drm/drm_encoder.h>
index a7ba5b4902d664fb72917b9f999b683c3fcaec58..b75ae8555baf91d5214d55b516eb5c0de20cadaf 100644 (file)
@@ -46,6 +46,7 @@
 #include <drm/drm_print.h>
 #include <drm/drm_vblank.h>
 
+#include "drm_crtc_helper_internal.h"
 #include "drm_internal.h"
 
 static bool drm_fbdev_emulation = true;
diff --git a/drivers/gpu/drm/drm_gem_ttm_helper.c b/drivers/gpu/drm/drm_gem_ttm_helper.c
new file mode 100644 (file)
index 0000000..a534104
--- /dev/null
@@ -0,0 +1,56 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include <linux/module.h>
+
+#include <drm/drm_gem_ttm_helper.h>
+
+/**
+ * DOC: overview
+ *
+ * This library provides helper functions for gem objects backed by
+ * ttm.
+ */
+
+/**
+ * drm_gem_ttm_print_info() - Print &ttm_buffer_object info for debugfs
+ * @p: DRM printer
+ * @indent: Tab indentation level
+ * @gem: GEM object
+ *
+ * This function can be used as &drm_gem_object_funcs.print_info
+ * callback.
+ */
+void drm_gem_ttm_print_info(struct drm_printer *p, unsigned int indent,
+                           const struct drm_gem_object *gem)
+{
+       static const char * const plname[] = {
+               [ TTM_PL_SYSTEM ] = "system",
+               [ TTM_PL_TT     ] = "tt",
+               [ TTM_PL_VRAM   ] = "vram",
+               [ TTM_PL_PRIV   ] = "priv",
+
+               [ 16 ]            = "cached",
+               [ 17 ]            = "uncached",
+               [ 18 ]            = "wc",
+               [ 19 ]            = "contig",
+
+               [ 21 ]            = "pinned", /* NO_EVICT */
+               [ 22 ]            = "topdown",
+       };
+       const struct ttm_buffer_object *bo = drm_gem_ttm_of_gem(gem);
+
+       drm_printf_indent(p, indent, "placement=");
+       drm_print_bits(p, bo->mem.placement, plname, ARRAY_SIZE(plname));
+       drm_printf(p, "\n");
+
+       if (bo->mem.bus.is_iomem) {
+               drm_printf_indent(p, indent, "bus.base=%lx\n",
+                                 (unsigned long)bo->mem.bus.base);
+               drm_printf_indent(p, indent, "bus.offset=%lx\n",
+                                 (unsigned long)bo->mem.bus.offset);
+       }
+}
+EXPORT_SYMBOL(drm_gem_ttm_print_info);
+
+MODULE_DESCRIPTION("DRM gem ttm helpers");
+MODULE_LICENSE("GPL");
index fd751078bae1de66877f88482efcccd4354ea5c0..dc7942981f4a15a315573beff79d484895203087 100644 (file)
@@ -1,10 +1,12 @@
 // SPDX-License-Identifier: GPL-2.0-or-later
 
-#include <drm/drm_gem_vram_helper.h>
+#include <drm/drm_debugfs.h>
 #include <drm/drm_device.h>
+#include <drm/drm_file.h>
+#include <drm/drm_gem_ttm_helper.h>
+#include <drm/drm_gem_vram_helper.h>
 #include <drm/drm_mode.h>
 #include <drm/drm_prime.h>
-#include <drm/drm_vram_mm_helper.h>
 #include <drm/ttm/ttm_page_alloc.h>
 
 static const struct drm_gem_object_funcs drm_gem_vram_object_funcs;
@@ -14,6 +16,11 @@ static const struct drm_gem_object_funcs drm_gem_vram_object_funcs;
  *
  * This library provides a GEM buffer object that is backed by video RAM
  * (VRAM). It can be used for framebuffer devices with dedicated memory.
+ *
+ * The data structure &struct drm_vram_mm and its helpers implement a memory
+ * manager for simple framebuffer devices with dedicated video memory. Buffer
+ * objects are either placed in video RAM or evicted to system memory. The rsp.
+ * buffer object is provided by &struct drm_gem_vram_object.
  */
 
 /*
@@ -26,6 +33,10 @@ static void drm_gem_vram_cleanup(struct drm_gem_vram_object *gbo)
         * TTM buffer object in 'bo' has already been cleaned
         * up; only release the GEM object.
         */
+
+       WARN_ON(gbo->kmap_use_count);
+       WARN_ON(gbo->kmap.virtual);
+
        drm_gem_object_release(&gbo->bo.base);
 }
 
@@ -47,6 +58,7 @@ static void drm_gem_vram_placement(struct drm_gem_vram_object *gbo,
 {
        unsigned int i;
        unsigned int c = 0;
+       u32 invariant_flags = pl_flag & TTM_PL_FLAG_TOPDOWN;
 
        gbo->placement.placement = gbo->placements;
        gbo->placement.busy_placement = gbo->placements;
@@ -54,15 +66,18 @@ static void drm_gem_vram_placement(struct drm_gem_vram_object *gbo,
        if (pl_flag & TTM_PL_FLAG_VRAM)
                gbo->placements[c++].flags = TTM_PL_FLAG_WC |
                                             TTM_PL_FLAG_UNCACHED |
-                                            TTM_PL_FLAG_VRAM;
+                                            TTM_PL_FLAG_VRAM |
+                                            invariant_flags;
 
        if (pl_flag & TTM_PL_FLAG_SYSTEM)
                gbo->placements[c++].flags = TTM_PL_MASK_CACHING |
-                                            TTM_PL_FLAG_SYSTEM;
+                                            TTM_PL_FLAG_SYSTEM |
+                                            invariant_flags;
 
        if (!c)
                gbo->placements[c++].flags = TTM_PL_MASK_CACHING |
-                                            TTM_PL_FLAG_SYSTEM;
+                                            TTM_PL_FLAG_SYSTEM |
+                                            invariant_flags;
 
        gbo->placement.num_placement = c;
        gbo->placement.num_busy_placement = c;
@@ -82,8 +97,7 @@ static int drm_gem_vram_init(struct drm_device *dev,
        int ret;
        size_t acc_size;
 
-       if (!gbo->bo.base.funcs)
-               gbo->bo.base.funcs = &drm_gem_vram_object_funcs;
+       gbo->bo.base.funcs = &drm_gem_vram_object_funcs;
 
        ret = drm_gem_object_init(dev, &gbo->bo.base, size);
        if (ret)
@@ -192,30 +206,12 @@ s64 drm_gem_vram_offset(struct drm_gem_vram_object *gbo)
 }
 EXPORT_SYMBOL(drm_gem_vram_offset);
 
-/**
- * drm_gem_vram_pin() - Pins a GEM VRAM object in a region.
- * @gbo:       the GEM VRAM object
- * @pl_flag:   a bitmask of possible memory regions
- *
- * Pinning a buffer object ensures that it is not evicted from
- * a memory region. A pinned buffer object has to be unpinned before
- * it can be pinned to another region. If the pl_flag argument is 0,
- * the buffer is pinned at its current location (video RAM or system
- * memory).
- *
- * Returns:
- * 0 on success, or
- * a negative error code otherwise.
- */
-int drm_gem_vram_pin(struct drm_gem_vram_object *gbo, unsigned long pl_flag)
+static int drm_gem_vram_pin_locked(struct drm_gem_vram_object *gbo,
+                                  unsigned long pl_flag)
 {
        int i, ret;
        struct ttm_operation_ctx ctx = { false, false };
 
-       ret = ttm_bo_reserve(&gbo->bo, true, false, NULL);
-       if (ret < 0)
-               return ret;
-
        if (gbo->pin_count)
                goto out;
 
@@ -227,62 +223,123 @@ int drm_gem_vram_pin(struct drm_gem_vram_object *gbo, unsigned long pl_flag)
 
        ret = ttm_bo_validate(&gbo->bo, &gbo->placement, &ctx);
        if (ret < 0)
-               goto err_ttm_bo_unreserve;
+               return ret;
 
 out:
        ++gbo->pin_count;
-       ttm_bo_unreserve(&gbo->bo);
 
        return 0;
-
-err_ttm_bo_unreserve:
-       ttm_bo_unreserve(&gbo->bo);
-       return ret;
 }
-EXPORT_SYMBOL(drm_gem_vram_pin);
 
 /**
- * drm_gem_vram_unpin() - Unpins a GEM VRAM object
+ * drm_gem_vram_pin() - Pins a GEM VRAM object in a region.
  * @gbo:       the GEM VRAM object
+ * @pl_flag:   a bitmask of possible memory regions
+ *
+ * Pinning a buffer object ensures that it is not evicted from
+ * a memory region. A pinned buffer object has to be unpinned before
+ * it can be pinned to another region. If the pl_flag argument is 0,
+ * the buffer is pinned at its current location (video RAM or system
+ * memory).
+ *
+ * Small buffer objects, such as cursor images, can lead to memory
+ * fragmentation if they are pinned in the middle of video RAM. This
+ * is especially a problem on devices with only a small amount of
+ * video RAM. Fragmentation can prevent the primary framebuffer from
+ * fitting in, even though there's enough memory overall. The modifier
+ * DRM_GEM_VRAM_PL_FLAG_TOPDOWN marks the buffer object to be pinned
+ * at the high end of the memory region to avoid fragmentation.
  *
  * Returns:
  * 0 on success, or
  * a negative error code otherwise.
  */
-int drm_gem_vram_unpin(struct drm_gem_vram_object *gbo)
+int drm_gem_vram_pin(struct drm_gem_vram_object *gbo, unsigned long pl_flag)
 {
-       int i, ret;
-       struct ttm_operation_ctx ctx = { false, false };
+       int ret;
 
        ret = ttm_bo_reserve(&gbo->bo, true, false, NULL);
-       if (ret < 0)
+       if (ret)
                return ret;
+       ret = drm_gem_vram_pin_locked(gbo, pl_flag);
+       ttm_bo_unreserve(&gbo->bo);
+
+       return ret;
+}
+EXPORT_SYMBOL(drm_gem_vram_pin);
+
+static int drm_gem_vram_unpin_locked(struct drm_gem_vram_object *gbo)
+{
+       int i, ret;
+       struct ttm_operation_ctx ctx = { false, false };
 
        if (WARN_ON_ONCE(!gbo->pin_count))
-               goto out;
+               return 0;
 
        --gbo->pin_count;
        if (gbo->pin_count)
-               goto out;
+               return 0;
 
        for (i = 0; i < gbo->placement.num_placement ; ++i)
                gbo->placements[i].flags &= ~TTM_PL_FLAG_NO_EVICT;
 
        ret = ttm_bo_validate(&gbo->bo, &gbo->placement, &ctx);
        if (ret < 0)
-               goto err_ttm_bo_unreserve;
-
-out:
-       ttm_bo_unreserve(&gbo->bo);
+               return ret;
 
        return 0;
+}
 
-err_ttm_bo_unreserve:
+/**
+ * drm_gem_vram_unpin() - Unpins a GEM VRAM object
+ * @gbo:       the GEM VRAM object
+ *
+ * Returns:
+ * 0 on success, or
+ * a negative error code otherwise.
+ */
+int drm_gem_vram_unpin(struct drm_gem_vram_object *gbo)
+{
+       int ret;
+
+       ret = ttm_bo_reserve(&gbo->bo, true, false, NULL);
+       if (ret)
+               return ret;
+       ret = drm_gem_vram_unpin_locked(gbo);
        ttm_bo_unreserve(&gbo->bo);
+
        return ret;
 }
 EXPORT_SYMBOL(drm_gem_vram_unpin);
 
+static void *drm_gem_vram_kmap_locked(struct drm_gem_vram_object *gbo,
+                                     bool map, bool *is_iomem)
+{
+       int ret;
+       struct ttm_bo_kmap_obj *kmap = &gbo->kmap;
+
+       if (gbo->kmap_use_count > 0)
+               goto out;
+
+       if (kmap->virtual || !map)
+               goto out;
+
+       ret = ttm_bo_kmap(&gbo->bo, 0, gbo->bo.num_pages, kmap);
+       if (ret)
+               return ERR_PTR(ret);
+
+out:
+       if (!kmap->virtual) {
+               if (is_iomem)
+                       *is_iomem = false;
+               return NULL; /* not mapped; don't increment ref */
+       }
+       ++gbo->kmap_use_count;
+       if (is_iomem)
+               return ttm_kmap_obj_virtual(kmap, is_iomem);
+       return kmap->virtual;
+}
+
 /**
  * drm_gem_vram_kmap() - Maps a GEM VRAM object into kernel address space
  * @gbo:       the GEM VRAM object
@@ -304,42 +361,120 @@ void *drm_gem_vram_kmap(struct drm_gem_vram_object *gbo, bool map,
                        bool *is_iomem)
 {
        int ret;
-       struct ttm_bo_kmap_obj *kmap = &gbo->kmap;
+       void *virtual;
 
-       if (kmap->virtual || !map)
-               goto out;
-
-       ret = ttm_bo_kmap(&gbo->bo, 0, gbo->bo.num_pages, kmap);
+       ret = ttm_bo_reserve(&gbo->bo, true, false, NULL);
        if (ret)
                return ERR_PTR(ret);
+       virtual = drm_gem_vram_kmap_locked(gbo, map, is_iomem);
+       ttm_bo_unreserve(&gbo->bo);
 
-out:
-       if (!is_iomem)
-               return kmap->virtual;
-       if (!kmap->virtual) {
-               *is_iomem = false;
-               return NULL;
-       }
-       return ttm_kmap_obj_virtual(kmap, is_iomem);
+       return virtual;
 }
 EXPORT_SYMBOL(drm_gem_vram_kmap);
 
+static void drm_gem_vram_kunmap_locked(struct drm_gem_vram_object *gbo)
+{
+       if (WARN_ON_ONCE(!gbo->kmap_use_count))
+               return;
+       if (--gbo->kmap_use_count > 0)
+               return;
+
+       /*
+        * Permanently mapping and unmapping buffers adds overhead from
+        * updating the page tables and creates debugging output. Therefore,
+        * we delay the actual unmap operation until the BO gets evicted
+        * from memory. See drm_gem_vram_bo_driver_move_notify().
+        */
+}
+
 /**
  * drm_gem_vram_kunmap() - Unmaps a GEM VRAM object
  * @gbo:       the GEM VRAM object
  */
 void drm_gem_vram_kunmap(struct drm_gem_vram_object *gbo)
 {
-       struct ttm_bo_kmap_obj *kmap = &gbo->kmap;
+       int ret;
 
-       if (!kmap->virtual)
+       ret = ttm_bo_reserve(&gbo->bo, false, false, NULL);
+       if (WARN_ONCE(ret, "ttm_bo_reserve_failed(): ret=%d\n", ret))
                return;
-
-       ttm_bo_kunmap(kmap);
-       kmap->virtual = NULL;
+       drm_gem_vram_kunmap_locked(gbo);
+       ttm_bo_unreserve(&gbo->bo);
 }
 EXPORT_SYMBOL(drm_gem_vram_kunmap);
 
+/**
+ * drm_gem_vram_vmap() - Pins and maps a GEM VRAM object into kernel address
+ *                       space
+ * @gbo:       The GEM VRAM object to map
+ *
+ * The vmap function pins a GEM VRAM object to its current location, either
+ * system or video memory, and maps its buffer into kernel address space.
+ * As pinned object cannot be relocated, you should avoid pinning objects
+ * permanently. Call drm_gem_vram_vunmap() with the returned address to
+ * unmap and unpin the GEM VRAM object.
+ *
+ * If you have special requirements for the pinning or mapping operations,
+ * call drm_gem_vram_pin() and drm_gem_vram_kmap() directly.
+ *
+ * Returns:
+ * The buffer's virtual address on success, or
+ * an ERR_PTR()-encoded error code otherwise.
+ */
+void *drm_gem_vram_vmap(struct drm_gem_vram_object *gbo)
+{
+       int ret;
+       void *base;
+
+       ret = ttm_bo_reserve(&gbo->bo, true, false, NULL);
+       if (ret)
+               return ERR_PTR(ret);
+
+       ret = drm_gem_vram_pin_locked(gbo, 0);
+       if (ret)
+               goto err_ttm_bo_unreserve;
+       base = drm_gem_vram_kmap_locked(gbo, true, NULL);
+       if (IS_ERR(base)) {
+               ret = PTR_ERR(base);
+               goto err_drm_gem_vram_unpin_locked;
+       }
+
+       ttm_bo_unreserve(&gbo->bo);
+
+       return base;
+
+err_drm_gem_vram_unpin_locked:
+       drm_gem_vram_unpin_locked(gbo);
+err_ttm_bo_unreserve:
+       ttm_bo_unreserve(&gbo->bo);
+       return ERR_PTR(ret);
+}
+EXPORT_SYMBOL(drm_gem_vram_vmap);
+
+/**
+ * drm_gem_vram_vunmap() - Unmaps and unpins a GEM VRAM object
+ * @gbo:       The GEM VRAM object to unmap
+ * @vaddr:     The mapping's base address as returned by drm_gem_vram_vmap()
+ *
+ * A call to drm_gem_vram_vunmap() unmaps and unpins a GEM VRAM buffer. See
+ * the documentation for drm_gem_vram_vmap() for more information.
+ */
+void drm_gem_vram_vunmap(struct drm_gem_vram_object *gbo, void *vaddr)
+{
+       int ret;
+
+       ret = ttm_bo_reserve(&gbo->bo, false, false, NULL);
+       if (WARN_ONCE(ret, "ttm_bo_reserve_failed(): ret=%d\n", ret))
+               return;
+
+       drm_gem_vram_kunmap_locked(gbo);
+       drm_gem_vram_unpin_locked(gbo);
+
+       ttm_bo_unreserve(&gbo->bo);
+}
+EXPORT_SYMBOL(drm_gem_vram_vunmap);
+
 /**
  * drm_gem_vram_fill_create_dumb() - \
        Helper for implementing &struct drm_driver.dumb_create
@@ -410,59 +545,34 @@ static bool drm_is_gem_vram(struct ttm_buffer_object *bo)
        return (bo->destroy == ttm_buffer_object_destroy);
 }
 
-/**
- * drm_gem_vram_bo_driver_evict_flags() - \
-       Implements &struct ttm_bo_driver.evict_flags
- * @bo:        TTM buffer object. Refers to &struct drm_gem_vram_object.bo
- * @pl:        TTM placement information.
- */
-void drm_gem_vram_bo_driver_evict_flags(struct ttm_buffer_object *bo,
-                                       struct ttm_placement *pl)
+static void drm_gem_vram_bo_driver_evict_flags(struct drm_gem_vram_object *gbo,
+                                              struct ttm_placement *pl)
 {
-       struct drm_gem_vram_object *gbo;
-
-       /* TTM may pass BOs that are not GEM VRAM BOs. */
-       if (!drm_is_gem_vram(bo))
-               return;
-
-       gbo = drm_gem_vram_of_bo(bo);
        drm_gem_vram_placement(gbo, TTM_PL_FLAG_SYSTEM);
        *pl = gbo->placement;
 }
-EXPORT_SYMBOL(drm_gem_vram_bo_driver_evict_flags);
 
-/**
- * drm_gem_vram_bo_driver_verify_access() - \
-       Implements &struct ttm_bo_driver.verify_access
- * @bo:                TTM buffer object. Refers to &struct drm_gem_vram_object.bo
- * @filp:      File pointer.
- *
- * Returns:
- * 0 on success, or
- * a negative errno code otherwise.
- */
-int drm_gem_vram_bo_driver_verify_access(struct ttm_buffer_object *bo,
-                                        struct file *filp)
+static int drm_gem_vram_bo_driver_verify_access(struct drm_gem_vram_object *gbo,
+                                               struct file *filp)
 {
-       struct drm_gem_vram_object *gbo = drm_gem_vram_of_bo(bo);
-
        return drm_vma_node_verify_access(&gbo->bo.base.vma_node,
                                          filp->private_data);
 }
-EXPORT_SYMBOL(drm_gem_vram_bo_driver_verify_access);
 
-/*
- * drm_gem_vram_mm_funcs - Functions for &struct drm_vram_mm
- *
- * Most users of @struct drm_gem_vram_object will also use
- * @struct drm_vram_mm. This instance of &struct drm_vram_mm_funcs
- * can be used to connect both.
- */
-const struct drm_vram_mm_funcs drm_gem_vram_mm_funcs = {
-       .evict_flags = drm_gem_vram_bo_driver_evict_flags,
-       .verify_access = drm_gem_vram_bo_driver_verify_access
-};
-EXPORT_SYMBOL(drm_gem_vram_mm_funcs);
+static void drm_gem_vram_bo_driver_move_notify(struct drm_gem_vram_object *gbo,
+                                              bool evict,
+                                              struct ttm_mem_reg *new_mem)
+{
+       struct ttm_bo_kmap_obj *kmap = &gbo->kmap;
+
+       if (WARN_ON_ONCE(gbo->kmap_use_count))
+               return;
+
+       if (!kmap->virtual)
+               return;
+       ttm_bo_kunmap(kmap);
+       kmap->virtual = NULL;
+}
 
 /*
  * Helpers for struct drm_gem_object_funcs
@@ -595,17 +705,11 @@ static void drm_gem_vram_object_unpin(struct drm_gem_object *gem)
 static void *drm_gem_vram_object_vmap(struct drm_gem_object *gem)
 {
        struct drm_gem_vram_object *gbo = drm_gem_vram_of_gem(gem);
-       int ret;
        void *base;
 
-       ret = drm_gem_vram_pin(gbo, 0);
-       if (ret)
-               return NULL;
-       base = drm_gem_vram_kmap(gbo, true, NULL);
-       if (IS_ERR(base)) {
-               drm_gem_vram_unpin(gbo);
+       base = drm_gem_vram_vmap(gbo);
+       if (IS_ERR(base))
                return NULL;
-       }
        return base;
 }
 
@@ -620,8 +724,7 @@ static void drm_gem_vram_object_vunmap(struct drm_gem_object *gem,
 {
        struct drm_gem_vram_object *gbo = drm_gem_vram_of_gem(gem);
 
-       drm_gem_vram_kunmap(gbo);
-       drm_gem_vram_unpin(gbo);
+       drm_gem_vram_vunmap(gbo, vaddr);
 }
 
 /*
@@ -633,5 +736,326 @@ static const struct drm_gem_object_funcs drm_gem_vram_object_funcs = {
        .pin    = drm_gem_vram_object_pin,
        .unpin  = drm_gem_vram_object_unpin,
        .vmap   = drm_gem_vram_object_vmap,
-       .vunmap = drm_gem_vram_object_vunmap
+       .vunmap = drm_gem_vram_object_vunmap,
+       .print_info = drm_gem_ttm_print_info,
 };
+
+/*
+ * VRAM memory manager
+ */
+
+/*
+ * TTM TT
+ */
+
+static void backend_func_destroy(struct ttm_tt *tt)
+{
+       ttm_tt_fini(tt);
+       kfree(tt);
+}
+
+static struct ttm_backend_func backend_func = {
+       .destroy = backend_func_destroy
+};
+
+/*
+ * TTM BO device
+ */
+
+static struct ttm_tt *bo_driver_ttm_tt_create(struct ttm_buffer_object *bo,
+                                             uint32_t page_flags)
+{
+       struct ttm_tt *tt;
+       int ret;
+
+       tt = kzalloc(sizeof(*tt), GFP_KERNEL);
+       if (!tt)
+               return NULL;
+
+       tt->func = &backend_func;
+
+       ret = ttm_tt_init(tt, bo, page_flags);
+       if (ret < 0)
+               goto err_ttm_tt_init;
+
+       return tt;
+
+err_ttm_tt_init:
+       kfree(tt);
+       return NULL;
+}
+
+static int bo_driver_init_mem_type(struct ttm_bo_device *bdev, uint32_t type,
+                                  struct ttm_mem_type_manager *man)
+{
+       switch (type) {
+       case TTM_PL_SYSTEM:
+               man->flags = TTM_MEMTYPE_FLAG_MAPPABLE;
+               man->available_caching = TTM_PL_MASK_CACHING;
+               man->default_caching = TTM_PL_FLAG_CACHED;
+               break;
+       case TTM_PL_VRAM:
+               man->func = &ttm_bo_manager_func;
+               man->flags = TTM_MEMTYPE_FLAG_FIXED |
+                            TTM_MEMTYPE_FLAG_MAPPABLE;
+               man->available_caching = TTM_PL_FLAG_UNCACHED |
+                                        TTM_PL_FLAG_WC;
+               man->default_caching = TTM_PL_FLAG_WC;
+               break;
+       default:
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static void bo_driver_evict_flags(struct ttm_buffer_object *bo,
+                                 struct ttm_placement *placement)
+{
+       struct drm_gem_vram_object *gbo;
+
+       /* TTM may pass BOs that are not GEM VRAM BOs. */
+       if (!drm_is_gem_vram(bo))
+               return;
+
+       gbo = drm_gem_vram_of_bo(bo);
+
+       drm_gem_vram_bo_driver_evict_flags(gbo, placement);
+}
+
+static int bo_driver_verify_access(struct ttm_buffer_object *bo,
+                                  struct file *filp)
+{
+       struct drm_gem_vram_object *gbo;
+
+       /* TTM may pass BOs that are not GEM VRAM BOs. */
+       if (!drm_is_gem_vram(bo))
+               return -EINVAL;
+
+       gbo = drm_gem_vram_of_bo(bo);
+
+       return drm_gem_vram_bo_driver_verify_access(gbo, filp);
+}
+
+static void bo_driver_move_notify(struct ttm_buffer_object *bo,
+                                 bool evict,
+                                 struct ttm_mem_reg *new_mem)
+{
+       struct drm_gem_vram_object *gbo;
+
+       /* TTM may pass BOs that are not GEM VRAM BOs. */
+       if (!drm_is_gem_vram(bo))
+               return;
+
+       gbo = drm_gem_vram_of_bo(bo);
+
+       drm_gem_vram_bo_driver_move_notify(gbo, evict, new_mem);
+}
+
+static int bo_driver_io_mem_reserve(struct ttm_bo_device *bdev,
+                                   struct ttm_mem_reg *mem)
+{
+       struct ttm_mem_type_manager *man = bdev->man + mem->mem_type;
+       struct drm_vram_mm *vmm = drm_vram_mm_of_bdev(bdev);
+
+       if (!(man->flags & TTM_MEMTYPE_FLAG_MAPPABLE))
+               return -EINVAL;
+
+       mem->bus.addr = NULL;
+       mem->bus.size = mem->num_pages << PAGE_SHIFT;
+
+       switch (mem->mem_type) {
+       case TTM_PL_SYSTEM:     /* nothing to do */
+               mem->bus.offset = 0;
+               mem->bus.base = 0;
+               mem->bus.is_iomem = false;
+               break;
+       case TTM_PL_VRAM:
+               mem->bus.offset = mem->start << PAGE_SHIFT;
+               mem->bus.base = vmm->vram_base;
+               mem->bus.is_iomem = true;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static void bo_driver_io_mem_free(struct ttm_bo_device *bdev,
+                                 struct ttm_mem_reg *mem)
+{ }
+
+static struct ttm_bo_driver bo_driver = {
+       .ttm_tt_create = bo_driver_ttm_tt_create,
+       .ttm_tt_populate = ttm_pool_populate,
+       .ttm_tt_unpopulate = ttm_pool_unpopulate,
+       .init_mem_type = bo_driver_init_mem_type,
+       .eviction_valuable = ttm_bo_eviction_valuable,
+       .evict_flags = bo_driver_evict_flags,
+       .verify_access = bo_driver_verify_access,
+       .move_notify = bo_driver_move_notify,
+       .io_mem_reserve = bo_driver_io_mem_reserve,
+       .io_mem_free = bo_driver_io_mem_free,
+};
+
+/*
+ * struct drm_vram_mm
+ */
+
+#if defined(CONFIG_DEBUG_FS)
+static int drm_vram_mm_debugfs(struct seq_file *m, void *data)
+{
+       struct drm_info_node *node = (struct drm_info_node *) m->private;
+       struct drm_vram_mm *vmm = node->minor->dev->vram_mm;
+       struct drm_mm *mm = vmm->bdev.man[TTM_PL_VRAM].priv;
+       struct ttm_bo_global *glob = vmm->bdev.glob;
+       struct drm_printer p = drm_seq_file_printer(m);
+
+       spin_lock(&glob->lru_lock);
+       drm_mm_print(mm, &p);
+       spin_unlock(&glob->lru_lock);
+       return 0;
+}
+
+static const struct drm_info_list drm_vram_mm_debugfs_list[] = {
+       { "vram-mm", drm_vram_mm_debugfs, 0, NULL },
+};
+#endif
+
+/**
+ * drm_vram_mm_debugfs_init() - Register VRAM MM debugfs file.
+ *
+ * @minor: drm minor device.
+ *
+ * Returns:
+ * 0 on success, or
+ * a negative error code otherwise.
+ */
+int drm_vram_mm_debugfs_init(struct drm_minor *minor)
+{
+       int ret = 0;
+
+#if defined(CONFIG_DEBUG_FS)
+       ret = drm_debugfs_create_files(drm_vram_mm_debugfs_list,
+                                      ARRAY_SIZE(drm_vram_mm_debugfs_list),
+                                      minor->debugfs_root, minor);
+#endif
+       return ret;
+}
+EXPORT_SYMBOL(drm_vram_mm_debugfs_init);
+
+static int drm_vram_mm_init(struct drm_vram_mm *vmm, struct drm_device *dev,
+                           uint64_t vram_base, size_t vram_size)
+{
+       int ret;
+
+       vmm->vram_base = vram_base;
+       vmm->vram_size = vram_size;
+
+       ret = ttm_bo_device_init(&vmm->bdev, &bo_driver,
+                                dev->anon_inode->i_mapping,
+                                dev->vma_offset_manager,
+                                true);
+       if (ret)
+               return ret;
+
+       ret = ttm_bo_init_mm(&vmm->bdev, TTM_PL_VRAM, vram_size >> PAGE_SHIFT);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
+static void drm_vram_mm_cleanup(struct drm_vram_mm *vmm)
+{
+       ttm_bo_device_release(&vmm->bdev);
+}
+
+static int drm_vram_mm_mmap(struct file *filp, struct vm_area_struct *vma,
+                           struct drm_vram_mm *vmm)
+{
+       return ttm_bo_mmap(filp, vma, &vmm->bdev);
+}
+
+/*
+ * Helpers for integration with struct drm_device
+ */
+
+/**
+ * drm_vram_helper_alloc_mm - Allocates a device's instance of \
+       &struct drm_vram_mm
+ * @dev:       the DRM device
+ * @vram_base: the base address of the video memory
+ * @vram_size: the size of the video memory in bytes
+ *
+ * Returns:
+ * The new instance of &struct drm_vram_mm on success, or
+ * an ERR_PTR()-encoded errno code otherwise.
+ */
+struct drm_vram_mm *drm_vram_helper_alloc_mm(
+       struct drm_device *dev, uint64_t vram_base, size_t vram_size)
+{
+       int ret;
+
+       if (WARN_ON(dev->vram_mm))
+               return dev->vram_mm;
+
+       dev->vram_mm = kzalloc(sizeof(*dev->vram_mm), GFP_KERNEL);
+       if (!dev->vram_mm)
+               return ERR_PTR(-ENOMEM);
+
+       ret = drm_vram_mm_init(dev->vram_mm, dev, vram_base, vram_size);
+       if (ret)
+               goto err_kfree;
+
+       return dev->vram_mm;
+
+err_kfree:
+       kfree(dev->vram_mm);
+       dev->vram_mm = NULL;
+       return ERR_PTR(ret);
+}
+EXPORT_SYMBOL(drm_vram_helper_alloc_mm);
+
+/**
+ * drm_vram_helper_release_mm - Releases a device's instance of \
+       &struct drm_vram_mm
+ * @dev:       the DRM device
+ */
+void drm_vram_helper_release_mm(struct drm_device *dev)
+{
+       if (!dev->vram_mm)
+               return;
+
+       drm_vram_mm_cleanup(dev->vram_mm);
+       kfree(dev->vram_mm);
+       dev->vram_mm = NULL;
+}
+EXPORT_SYMBOL(drm_vram_helper_release_mm);
+
+/*
+ * Helpers for &struct file_operations
+ */
+
+/**
+ * drm_vram_mm_file_operations_mmap() - \
+       Implements &struct file_operations.mmap()
+ * @filp:      the mapping's file structure
+ * @vma:       the mapping's memory area
+ *
+ * Returns:
+ * 0 on success, or
+ * a negative error code otherwise.
+ */
+int drm_vram_mm_file_operations_mmap(
+       struct file *filp, struct vm_area_struct *vma)
+{
+       struct drm_file *file_priv = filp->private_data;
+       struct drm_device *dev = file_priv->minor->dev;
+
+       if (WARN_ONCE(!dev->vram_mm, "VRAM MM not initialized"))
+               return -EINVAL;
+
+       return drm_vram_mm_mmap(filp, vma, dev->vram_mm);
+}
+EXPORT_SYMBOL(drm_vram_mm_file_operations_mmap);
index 0bec6dbb01421e0856271a2400f2b962411ce76f..fbea69d6f90902d93f910a4d93e50ba1ed9e3c61 100644 (file)
@@ -40,6 +40,7 @@
 #include <xen/xen.h>
 
 #include <drm/drm_agpsupport.h>
+#include <drm/drm_cache.h>
 #include <drm/drm_device.h>
 
 #include "drm_legacy.h"
index 1961f713aaab427857c062aad5610b0c8a32a297..ccfb5b33c5e3f2552cf873fb8839c6804331a95b 100644 (file)
@@ -783,7 +783,7 @@ static int mipi_dbi_spi1e_transfer(struct mipi_dbi *dbi, int dc,
        int i, ret;
        u8 *dst;
 
-       if (drm_debug & DRM_UT_DRIVER)
+       if (drm_debug_enabled(DRM_UT_DRIVER))
                pr_debug("[drm:%s] dc=%d, max_chunk=%zu, transfers:\n",
                         __func__, dc, max_chunk);
 
@@ -907,7 +907,7 @@ static int mipi_dbi_spi1_transfer(struct mipi_dbi *dbi, int dc,
        max_chunk = dbi->tx_buf9_len;
        dst16 = dbi->tx_buf9;
 
-       if (drm_debug & DRM_UT_DRIVER)
+       if (drm_debug_enabled(DRM_UT_DRIVER))
                pr_debug("[drm:%s] dc=%d, max_chunk=%zu, transfers:\n",
                         __func__, dc, max_chunk);
 
@@ -955,7 +955,7 @@ static int mipi_dbi_typec1_command(struct mipi_dbi *dbi, u8 *cmd,
        int ret;
 
        if (mipi_dbi_command_is_read(dbi, *cmd))
-               return -ENOTSUPP;
+               return -EOPNOTSUPP;
 
        MIPI_DBI_DEBUG_COMMAND(*cmd, parameters, num);
 
@@ -1187,8 +1187,7 @@ static ssize_t mipi_dbi_debugfs_command_write(struct file *file,
        struct mipi_dbi_dev *dbidev = m->private;
        u8 val, cmd = 0, parameters[64];
        char *buf, *pos, *token;
-       unsigned int i;
-       int ret, idx;
+       int i, ret, idx;
 
        if (!drm_dev_enter(&dbidev->drm, &idx))
                return -ENODEV;
index 43d89dd59c6b14501a0060a2963dc6a86b06004d..0ca58803ba46f207e4227af8eb4c07a7c07b8654 100644 (file)
@@ -250,11 +250,6 @@ int drm_of_find_panel_or_bridge(const struct device_node *np,
        if (!remote)
                return -ENODEV;
 
-       if (!of_device_is_available(remote)) {
-               of_node_put(remote);
-               return -ENODEV;
-       }
-
        if (panel) {
                *panel = of_drm_find_panel(remote);
                if (!IS_ERR(*panel))
index 6b0bf42039cfa9449e6e1ad055c36e6ee08d44a1..ed7985c0535a2dae5311fde445726655bd188a28 100644 (file)
@@ -44,13 +44,21 @@ static LIST_HEAD(panel_list);
 /**
  * drm_panel_init - initialize a panel
  * @panel: DRM panel
+ * @dev: parent device of the panel
+ * @funcs: panel operations
+ * @connector_type: the connector type (DRM_MODE_CONNECTOR_*) corresponding to
+ *     the panel interface
  *
- * Sets up internal fields of the panel so that it can subsequently be added
- * to the registry.
+ * Initialize the panel structure for subsequent registration with
+ * drm_panel_add().
  */
-void drm_panel_init(struct drm_panel *panel)
+void drm_panel_init(struct drm_panel *panel, struct device *dev,
+                   const struct drm_panel_funcs *funcs, int connector_type)
 {
        INIT_LIST_HEAD(&panel->list);
+       panel->dev = dev;
+       panel->funcs = funcs;
+       panel->connector_type = connector_type;
 }
 EXPORT_SYMBOL(drm_panel_init);
 
index a17c8a14dba4f9401c7ffbfed8d1eda4d0e2153a..9a25d73c155c96757d24a5216254e123431f7c07 100644 (file)
@@ -28,6 +28,7 @@
 #include <stdarg.h>
 
 #include <linux/io.h>
+#include <linux/moduleparam.h>
 #include <linux/seq_file.h>
 #include <linux/slab.h>
 
 #include <drm/drm_drv.h>
 #include <drm/drm_print.h>
 
+/*
+ * drm_debug: Enable debug output.
+ * Bitmask of DRM_UT_x. See include/drm/drm_print.h for details.
+ */
+unsigned int drm_debug;
+EXPORT_SYMBOL(drm_debug);
+
+MODULE_PARM_DESC(debug, "Enable debug output, where each bit enables a debug category.\n"
+"\t\tBit 0 (0x01)  will enable CORE messages (drm core code)\n"
+"\t\tBit 1 (0x02)  will enable DRIVER messages (drm controller code)\n"
+"\t\tBit 2 (0x04)  will enable KMS messages (modesetting code)\n"
+"\t\tBit 3 (0x08)  will enable PRIME messages (prime code)\n"
+"\t\tBit 4 (0x10)  will enable ATOMIC messages (atomic code)\n"
+"\t\tBit 5 (0x20)  will enable VBL messages (vblank code)\n"
+"\t\tBit 7 (0x80)  will enable LEASE messages (leasing code)\n"
+"\t\tBit 8 (0x100) will enable DP messages (displayport code)");
+module_param_named(debug, drm_debug, int, 0600);
+
 void __drm_puts_coredump(struct drm_printer *p, const char *str)
 {
        struct drm_print_iterator *iterator = p->arg;
@@ -147,6 +166,12 @@ void __drm_printfn_debug(struct drm_printer *p, struct va_format *vaf)
 }
 EXPORT_SYMBOL(__drm_printfn_debug);
 
+void __drm_printfn_err(struct drm_printer *p, struct va_format *vaf)
+{
+       pr_err("*ERROR* %s %pV", p->prefix, vaf);
+}
+EXPORT_SYMBOL(__drm_printfn_err);
+
 /**
  * drm_puts - print a const string to a &drm_printer stream
  * @p: the &drm printer
@@ -179,6 +204,37 @@ void drm_printf(struct drm_printer *p, const char *f, ...)
 }
 EXPORT_SYMBOL(drm_printf);
 
+/**
+ * drm_print_bits - print bits to a &drm_printer stream
+ *
+ * Print bits (in flag fields for example) in human readable form.
+ *
+ * @p: the &drm_printer
+ * @value: field value.
+ * @bits: Array with bit names.
+ * @nbits: Size of bit names array.
+ */
+void drm_print_bits(struct drm_printer *p, unsigned long value,
+                   const char * const bits[], unsigned int nbits)
+{
+       bool first = true;
+       unsigned int i;
+
+       if (WARN_ON_ONCE(nbits > BITS_PER_TYPE(value)))
+               nbits = BITS_PER_TYPE(value);
+
+       for_each_set_bit(i, &value, nbits) {
+               if (WARN_ON_ONCE(!bits[i]))
+                       continue;
+               drm_printf(p, "%s%s", first ? "" : ",",
+                          bits[i]);
+               first = false;
+       }
+       if (first)
+               drm_printf(p, "(none)");
+}
+EXPORT_SYMBOL(drm_print_bits);
+
 void drm_dev_printk(const struct device *dev, const char *level,
                    const char *format, ...)
 {
@@ -206,7 +262,7 @@ void drm_dev_dbg(const struct device *dev, unsigned int category,
        struct va_format vaf;
        va_list args;
 
-       if (!(drm_debug & category))
+       if (!drm_debug_enabled(category))
                return;
 
        va_start(args, format);
@@ -229,7 +285,7 @@ void drm_dbg(unsigned int category, const char *format, ...)
        struct va_format vaf;
        va_list args;
 
-       if (!(drm_debug & category))
+       if (!drm_debug_enabled(category))
                return;
 
        va_start(args, format);
index ef2c468205a2015942a98d02dd91756a9f470c79..a7c87abe88d0b2230efba8b6972271cbf44c4838 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/export.h>
 #include <linux/moduleparam.h>
 
+#include <drm/drm_bridge.h>
 #include <drm/drm_client.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_edid.h>
@@ -92,7 +93,6 @@ drm_mode_validate_pipeline(struct drm_display_mode *mode,
        struct drm_device *dev = connector->dev;
        enum drm_mode_status ret = MODE_OK;
        struct drm_encoder *encoder;
-       int i;
 
        /* Step 1: Validate against connector */
        ret = drm_connector_mode_valid(connector, mode);
@@ -100,7 +100,7 @@ drm_mode_validate_pipeline(struct drm_display_mode *mode,
                return ret;
 
        /* Step 2: Validate against encoders and crtcs */
-       drm_connector_for_each_possible_encoder(connector, encoder, i) {
+       drm_connector_for_each_possible_encoder(connector, encoder) {
                struct drm_crtc *crtc;
 
                ret = drm_encoder_mode_valid(encoder, mode);
index b11910f14c46b9eca4bbd0495fc785884494230e..046055719245a2861583f061b8ac0752ecc902ff 100644 (file)
@@ -8,6 +8,7 @@
 
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_bridge.h>
 #include <drm/drm_plane_helper.h>
 #include <drm/drm_probe_helper.h>
 #include <drm/drm_simple_kms_helper.h>
index 4b5c7b0ed714831a22a0a30e95af9b3929f8154e..9ec334663c2db56d4abc926b53611211304030c1 100644 (file)
 #include <drm/drm_gem.h>
 #include <drm/drm_print.h>
 #include <drm/drm_syncobj.h>
+#include <drm/drm_utils.h>
 
 #include "drm_internal.h"
 
index 471eb927474b8ac48bbb5b34769f1d3dd39bcb14..11c6dd577e8ed2c01c585893972d8be201401aa0 100644 (file)
@@ -13,17 +13,23 @@ struct drm_file;
 #define TRACE_INCLUDE_FILE drm_trace
 
 TRACE_EVENT(drm_vblank_event,
-           TP_PROTO(int crtc, unsigned int seq),
-           TP_ARGS(crtc, seq),
+           TP_PROTO(int crtc, unsigned int seq, ktime_t time, bool high_prec),
+           TP_ARGS(crtc, seq, time, high_prec),
            TP_STRUCT__entry(
                    __field(int, crtc)
                    __field(unsigned int, seq)
+                   __field(ktime_t, time)
+                   __field(bool, high_prec)
                    ),
            TP_fast_assign(
                    __entry->crtc = crtc;
                    __entry->seq = seq;
-                   ),
-           TP_printk("crtc=%d, seq=%u", __entry->crtc, __entry->seq)
+                   __entry->time = time;
+                   __entry->high_prec = high_prec;
+                       ),
+           TP_printk("crtc=%d, seq=%u, time=%lld, high-prec=%s",
+                       __entry->crtc, __entry->seq, __entry->time,
+                       __entry->high_prec ? "true" : "false")
 );
 
 TRACE_EVENT(drm_vblank_event_queued,
index fd1fbc77871f1eefce920f49e6e2939cb96cdf18..4f7962b6427b362cc3b5f764b07bacb345e24278 100644 (file)
@@ -106,7 +106,7 @@ static void store_vblank(struct drm_device *dev, unsigned int pipe,
 
        write_seqlock(&vblank->seqlock);
        vblank->time = t_vblank;
-       vblank->count += vblank_count_inc;
+       atomic64_add(vblank_count_inc, &vblank->count);
        write_sequnlock(&vblank->seqlock);
 }
 
@@ -272,7 +272,8 @@ static void drm_update_vblank_count(struct drm_device *dev, unsigned int pipe,
 
        DRM_DEBUG_VBL("updating vblank count on crtc %u:"
                      " current=%llu, diff=%u, hw=%u hw_last=%u\n",
-                     pipe, vblank->count, diff, cur_vblank, vblank->last);
+                     pipe, atomic64_read(&vblank->count), diff,
+                     cur_vblank, vblank->last);
 
        if (diff == 0) {
                WARN_ON_ONCE(cur_vblank != vblank->last);
@@ -294,11 +295,23 @@ static void drm_update_vblank_count(struct drm_device *dev, unsigned int pipe,
 static u64 drm_vblank_count(struct drm_device *dev, unsigned int pipe)
 {
        struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
+       u64 count;
 
        if (WARN_ON(pipe >= dev->num_crtcs))
                return 0;
 
-       return vblank->count;
+       count = atomic64_read(&vblank->count);
+
+       /*
+        * This read barrier corresponds to the implicit write barrier of the
+        * write seqlock in store_vblank(). Note that this is the only place
+        * where we need an explicit barrier, since all other access goes
+        * through drm_vblank_count_and_time(), which already has the required
+        * read barrier curtesy of the read seqlock.
+        */
+       smp_rmb();
+
+       return count;
 }
 
 /**
@@ -319,7 +332,7 @@ u64 drm_crtc_accurate_vblank_count(struct drm_crtc *crtc)
        u64 vblank;
        unsigned long flags;
 
-       WARN_ONCE(drm_debug & DRM_UT_VBL && !dev->driver->get_vblank_timestamp,
+       WARN_ONCE(drm_debug_enabled(DRM_UT_VBL) && !dev->driver->get_vblank_timestamp,
                  "This function requires support for accurate vblank timestamps.");
 
        spin_lock_irqsave(&dev->vblank_time_lock, flags);
@@ -693,7 +706,7 @@ bool drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev,
         */
        *vblank_time = ktime_sub_ns(etime, delta_ns);
 
-       if ((drm_debug & DRM_UT_VBL) == 0)
+       if (!drm_debug_enabled(DRM_UT_VBL))
                return true;
 
        ts_etime = ktime_to_timespec64(etime);
@@ -763,6 +776,14 @@ drm_get_last_vbltimestamp(struct drm_device *dev, unsigned int pipe,
  * vblank interrupt (since it only reports the software vblank counter), see
  * drm_crtc_accurate_vblank_count() for such use-cases.
  *
+ * Note that for a given vblank counter value drm_crtc_handle_vblank()
+ * and drm_crtc_vblank_count() or drm_crtc_vblank_count_and_time()
+ * provide a barrier: Any writes done before calling
+ * drm_crtc_handle_vblank() will be visible to callers of the later
+ * functions, iff the vblank count is the same or a later one.
+ *
+ * See also &drm_vblank_crtc.count.
+ *
  * Returns:
  * The software vblank counter.
  */
@@ -800,7 +821,7 @@ static u64 drm_vblank_count_and_time(struct drm_device *dev, unsigned int pipe,
 
        do {
                seq = read_seqbegin(&vblank->seqlock);
-               vblank_count = vblank->count;
+               vblank_count = atomic64_read(&vblank->count);
                *vblanktime = vblank->time;
        } while (read_seqretry(&vblank->seqlock, seq));
 
@@ -817,6 +838,14 @@ static u64 drm_vblank_count_and_time(struct drm_device *dev, unsigned int pipe,
  * vblank events since the system was booted, including lost events due to
  * modesetting activity. Returns corresponding system timestamp of the time
  * of the vblank interval that corresponds to the current vblank counter value.
+ *
+ * Note that for a given vblank counter value drm_crtc_handle_vblank()
+ * and drm_crtc_vblank_count() or drm_crtc_vblank_count_and_time()
+ * provide a barrier: Any writes done before calling
+ * drm_crtc_handle_vblank() will be visible to callers of the later
+ * functions, iff the vblank count is the same or a later one.
+ *
+ * See also &drm_vblank_crtc.count.
  */
 u64 drm_crtc_vblank_count_and_time(struct drm_crtc *crtc,
                                   ktime_t *vblanktime)
@@ -1323,7 +1352,7 @@ void drm_vblank_restore(struct drm_device *dev, unsigned int pipe)
        assert_spin_locked(&dev->vblank_time_lock);
 
        vblank = &dev->vblank[pipe];
-       WARN_ONCE((drm_debug & DRM_UT_VBL) && !vblank->framedur_ns,
+       WARN_ONCE(drm_debug_enabled(DRM_UT_VBL) && !vblank->framedur_ns,
                  "Cannot compute missed vblanks without frame duration\n");
        framedur_ns = vblank->framedur_ns;
 
@@ -1731,7 +1760,8 @@ static void drm_handle_vblank_events(struct drm_device *dev, unsigned int pipe)
                send_vblank_event(dev, e, seq, now);
        }
 
-       trace_drm_vblank_event(pipe, seq);
+       trace_drm_vblank_event(pipe, seq, now,
+                       dev->driver->get_vblank_timestamp != NULL);
 }
 
 /**
@@ -1806,6 +1836,14 @@ EXPORT_SYMBOL(drm_handle_vblank);
  *
  * This is the native KMS version of drm_handle_vblank().
  *
+ * Note that for a given vblank counter value drm_crtc_handle_vblank()
+ * and drm_crtc_vblank_count() or drm_crtc_vblank_count_and_time()
+ * provide a barrier: Any writes done before calling
+ * drm_crtc_handle_vblank() will be visible to callers of the later
+ * functions, iff the vblank count is the same or a later one.
+ *
+ * See also &drm_vblank_crtc.count.
+ *
  * Returns:
  * True if the event was successfully handled, false on failure.
  */
index e9c9f9a80ba396c46c053cbb79e6fa43e183b53e..2000d9b33fd52c75d084b599ef98d8a3601208ab 100644 (file)
@@ -7,9 +7,8 @@
  *
  * This library provides &struct drm_gem_vram_object (GEM VRAM), a GEM
  * buffer object that is backed by video RAM. It can be used for
- * framebuffer devices with dedicated memory. The video RAM can be
- * managed with &struct drm_vram_mm (VRAM MM). Both data structures are
- * supposed to be used together, but can also be used individually.
+ * framebuffer devices with dedicated memory. The video RAM is managed
+ * by &struct drm_vram_mm (VRAM MM).
  *
  * With the GEM interface userspace applications create, manage and destroy
  * graphics buffers, such as an on-screen framebuffer. GEM does not provide
@@ -50,8 +49,7 @@
  *             // setup device, vram base and size
  *             // ...
  *
- *             ret = drm_vram_helper_alloc_mm(dev, vram_base, vram_size,
- *                                            &drm_gem_vram_mm_funcs);
+ *             ret = drm_vram_helper_alloc_mm(dev, vram_base, vram_size);
  *             if (ret)
  *                     return ret;
  *             return 0;
diff --git a/drivers/gpu/drm/drm_vram_mm_helper.c b/drivers/gpu/drm/drm_vram_mm_helper.c
deleted file mode 100644 (file)
index c911781..0000000
+++ /dev/null
@@ -1,297 +0,0 @@
-// 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/ttm/ttm_page_alloc.h>
-
-/**
- * DOC: overview
- *
- * The data structure &struct drm_vram_mm and its helpers implement a memory
- * manager for simple framebuffer devices with dedicated video memory. Buffer
- * objects are either placed in video RAM or evicted to system memory. These
- * helper functions work well with &struct drm_gem_vram_object.
- */
-
-/*
- * TTM TT
- */
-
-static void backend_func_destroy(struct ttm_tt *tt)
-{
-       ttm_tt_fini(tt);
-       kfree(tt);
-}
-
-static struct ttm_backend_func backend_func = {
-       .destroy = backend_func_destroy
-};
-
-/*
- * TTM BO device
- */
-
-static struct ttm_tt *bo_driver_ttm_tt_create(struct ttm_buffer_object *bo,
-                                             uint32_t page_flags)
-{
-       struct ttm_tt *tt;
-       int ret;
-
-       tt = kzalloc(sizeof(*tt), GFP_KERNEL);
-       if (!tt)
-               return NULL;
-
-       tt->func = &backend_func;
-
-       ret = ttm_tt_init(tt, bo, page_flags);
-       if (ret < 0)
-               goto err_ttm_tt_init;
-
-       return tt;
-
-err_ttm_tt_init:
-       kfree(tt);
-       return NULL;
-}
-
-static int bo_driver_init_mem_type(struct ttm_bo_device *bdev, uint32_t type,
-                                  struct ttm_mem_type_manager *man)
-{
-       switch (type) {
-       case TTM_PL_SYSTEM:
-               man->flags = TTM_MEMTYPE_FLAG_MAPPABLE;
-               man->available_caching = TTM_PL_MASK_CACHING;
-               man->default_caching = TTM_PL_FLAG_CACHED;
-               break;
-       case TTM_PL_VRAM:
-               man->func = &ttm_bo_manager_func;
-               man->flags = TTM_MEMTYPE_FLAG_FIXED |
-                            TTM_MEMTYPE_FLAG_MAPPABLE;
-               man->available_caching = TTM_PL_FLAG_UNCACHED |
-                                        TTM_PL_FLAG_WC;
-               man->default_caching = TTM_PL_FLAG_WC;
-               break;
-       default:
-               return -EINVAL;
-       }
-       return 0;
-}
-
-static void bo_driver_evict_flags(struct ttm_buffer_object *bo,
-                                 struct ttm_placement *placement)
-{
-       struct drm_vram_mm *vmm = drm_vram_mm_of_bdev(bo->bdev);
-
-       if (vmm->funcs && vmm->funcs->evict_flags)
-               vmm->funcs->evict_flags(bo, placement);
-}
-
-static int bo_driver_verify_access(struct ttm_buffer_object *bo,
-                                  struct file *filp)
-{
-       struct drm_vram_mm *vmm = drm_vram_mm_of_bdev(bo->bdev);
-
-       if (!vmm->funcs || !vmm->funcs->verify_access)
-               return 0;
-       return vmm->funcs->verify_access(bo, filp);
-}
-
-static int bo_driver_io_mem_reserve(struct ttm_bo_device *bdev,
-                                   struct ttm_mem_reg *mem)
-{
-       struct ttm_mem_type_manager *man = bdev->man + mem->mem_type;
-       struct drm_vram_mm *vmm = drm_vram_mm_of_bdev(bdev);
-
-       if (!(man->flags & TTM_MEMTYPE_FLAG_MAPPABLE))
-               return -EINVAL;
-
-       mem->bus.addr = NULL;
-       mem->bus.size = mem->num_pages << PAGE_SHIFT;
-
-       switch (mem->mem_type) {
-       case TTM_PL_SYSTEM:     /* nothing to do */
-               mem->bus.offset = 0;
-               mem->bus.base = 0;
-               mem->bus.is_iomem = false;
-               break;
-       case TTM_PL_VRAM:
-               mem->bus.offset = mem->start << PAGE_SHIFT;
-               mem->bus.base = vmm->vram_base;
-               mem->bus.is_iomem = true;
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
-static void bo_driver_io_mem_free(struct ttm_bo_device *bdev,
-                                 struct ttm_mem_reg *mem)
-{ }
-
-static struct ttm_bo_driver bo_driver = {
-       .ttm_tt_create = bo_driver_ttm_tt_create,
-       .ttm_tt_populate = ttm_pool_populate,
-       .ttm_tt_unpopulate = ttm_pool_unpopulate,
-       .init_mem_type = bo_driver_init_mem_type,
-       .eviction_valuable = ttm_bo_eviction_valuable,
-       .evict_flags = bo_driver_evict_flags,
-       .verify_access = bo_driver_verify_access,
-       .io_mem_reserve = bo_driver_io_mem_reserve,
-       .io_mem_free = bo_driver_io_mem_free,
-};
-
-/*
- * struct drm_vram_mm
- */
-
-/**
- * drm_vram_mm_init() - Initialize an instance of VRAM MM.
- * @vmm:       the VRAM MM instance to initialize
- * @dev:       the DRM device
- * @vram_base: the base address of the video memory
- * @vram_size: the size of the video memory in bytes
- * @funcs:     callback functions for buffer objects
- *
- * Returns:
- * 0 on success, or
- * a negative error code otherwise.
- */
-int drm_vram_mm_init(struct drm_vram_mm *vmm, struct drm_device *dev,
-                    uint64_t vram_base, size_t vram_size,
-                    const struct drm_vram_mm_funcs *funcs)
-{
-       int ret;
-
-       vmm->vram_base = vram_base;
-       vmm->vram_size = vram_size;
-       vmm->funcs = funcs;
-
-       ret = ttm_bo_device_init(&vmm->bdev, &bo_driver,
-                                dev->anon_inode->i_mapping,
-                                true);
-       if (ret)
-               return ret;
-
-       ret = ttm_bo_init_mm(&vmm->bdev, TTM_PL_VRAM, vram_size >> PAGE_SHIFT);
-       if (ret)
-               return ret;
-
-       return 0;
-}
-EXPORT_SYMBOL(drm_vram_mm_init);
-
-/**
- * drm_vram_mm_cleanup() - Cleans up an initialized instance of VRAM MM.
- * @vmm:       the VRAM MM instance to clean up
- */
-void drm_vram_mm_cleanup(struct drm_vram_mm *vmm)
-{
-       ttm_bo_device_release(&vmm->bdev);
-}
-EXPORT_SYMBOL(drm_vram_mm_cleanup);
-
-/**
- * drm_vram_mm_mmap() - Helper for implementing &struct file_operations.mmap()
- * @filp:      the mapping's file structure
- * @vma:       the mapping's memory area
- * @vmm:       the VRAM MM instance
- *
- * Returns:
- * 0 on success, or
- * a negative error code otherwise.
- */
-int drm_vram_mm_mmap(struct file *filp, struct vm_area_struct *vma,
-                    struct drm_vram_mm *vmm)
-{
-       return ttm_bo_mmap(filp, vma, &vmm->bdev);
-}
-EXPORT_SYMBOL(drm_vram_mm_mmap);
-
-/*
- * Helpers for integration with struct drm_device
- */
-
-/**
- * drm_vram_helper_alloc_mm - Allocates a device's instance of \
-       &struct drm_vram_mm
- * @dev:       the DRM device
- * @vram_base: the base address of the video memory
- * @vram_size: the size of the video memory in bytes
- * @funcs:     callback functions for buffer objects
- *
- * Returns:
- * The new instance of &struct drm_vram_mm on success, or
- * an ERR_PTR()-encoded errno code otherwise.
- */
-struct drm_vram_mm *drm_vram_helper_alloc_mm(
-       struct drm_device *dev, uint64_t vram_base, size_t vram_size,
-       const struct drm_vram_mm_funcs *funcs)
-{
-       int ret;
-
-       if (WARN_ON(dev->vram_mm))
-               return dev->vram_mm;
-
-       dev->vram_mm = kzalloc(sizeof(*dev->vram_mm), GFP_KERNEL);
-       if (!dev->vram_mm)
-               return ERR_PTR(-ENOMEM);
-
-       ret = drm_vram_mm_init(dev->vram_mm, dev, vram_base, vram_size, funcs);
-       if (ret)
-               goto err_kfree;
-
-       return dev->vram_mm;
-
-err_kfree:
-       kfree(dev->vram_mm);
-       dev->vram_mm = NULL;
-       return ERR_PTR(ret);
-}
-EXPORT_SYMBOL(drm_vram_helper_alloc_mm);
-
-/**
- * drm_vram_helper_release_mm - Releases a device's instance of \
-       &struct drm_vram_mm
- * @dev:       the DRM device
- */
-void drm_vram_helper_release_mm(struct drm_device *dev)
-{
-       if (!dev->vram_mm)
-               return;
-
-       drm_vram_mm_cleanup(dev->vram_mm);
-       kfree(dev->vram_mm);
-       dev->vram_mm = NULL;
-}
-EXPORT_SYMBOL(drm_vram_helper_release_mm);
-
-/*
- * Helpers for &struct file_operations
- */
-
-/**
- * drm_vram_mm_file_operations_mmap() - \
-       Implements &struct file_operations.mmap()
- * @filp:      the mapping's file structure
- * @vma:       the mapping's memory area
- *
- * Returns:
- * 0 on success, or
- * a negative error code otherwise.
- */
-int drm_vram_mm_file_operations_mmap(
-       struct file *filp, struct vm_area_struct *vma)
-{
-       struct drm_file *file_priv = filp->private_data;
-       struct drm_device *dev = file_priv->minor->dev;
-
-       if (WARN_ONCE(!dev->vram_mm, "VRAM MM not initialized"))
-               return -EINVAL;
-
-       return drm_vram_mm_mmap(filp, vma, dev->vram_mm);
-}
-EXPORT_SYMBOL(drm_vram_mm_file_operations_mmap);
index 7e4e2959bf4f723d6706f9c1a960669e03017894..32d9fac587f9a2157d28ab3cfaee92c4505e4c68 100644 (file)
@@ -326,7 +326,7 @@ void etnaviv_buffer_queue(struct etnaviv_gpu *gpu, u32 exec_state,
 
        lockdep_assert_held(&gpu->lock);
 
-       if (drm_debug & DRM_UT_DRIVER)
+       if (drm_debug_enabled(DRM_UT_DRIVER))
                etnaviv_buffer_dump(gpu, buffer, 0, 0x50);
 
        link_target = etnaviv_cmdbuf_get_va(cmdbuf,
@@ -459,13 +459,13 @@ void etnaviv_buffer_queue(struct etnaviv_gpu *gpu, u32 exec_state,
                 etnaviv_cmdbuf_get_va(buffer, &gpu->mmu_context->cmdbuf_mapping)
                 + buffer->user_size - 4);
 
-       if (drm_debug & DRM_UT_DRIVER)
+       if (drm_debug_enabled(DRM_UT_DRIVER))
                pr_info("stream link to 0x%08x @ 0x%08x %p\n",
                        return_target,
                        etnaviv_cmdbuf_get_va(cmdbuf, &gpu->mmu_context->cmdbuf_mapping),
                        cmdbuf->vaddr);
 
-       if (drm_debug & DRM_UT_DRIVER) {
+       if (drm_debug_enabled(DRM_UT_DRIVER)) {
                print_hex_dump(KERN_INFO, "cmd ", DUMP_PREFIX_OFFSET, 16, 4,
                               cmdbuf->vaddr, cmdbuf->size, 0);
 
@@ -484,6 +484,6 @@ void etnaviv_buffer_queue(struct etnaviv_gpu *gpu, u32 exec_state,
                                    VIV_FE_LINK_HEADER_PREFETCH(link_dwords),
                                    link_target);
 
-       if (drm_debug & DRM_UT_DRIVER)
+       if (drm_debug_enabled(DRM_UT_DRIVER))
                etnaviv_buffer_dump(gpu, buffer, 0, 0x50);
 }
index 3a0f0ba8c63a0defb90e8f1eb64dab432fc96dbd..1e6aa24bf45eed9f8be1e53ae16fef6a4e5b0426 100644 (file)
@@ -19,6 +19,7 @@
 
 #include <drm/bridge/analogix_dp.h>
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_bridge.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_of.h>
 #include <drm/drm_panel.h>
index 6926cee91b367963ba1571e33efc659093fa6bb6..72726f2c7a9fb035631d9df9bee2f42a8ee05902 100644 (file)
@@ -24,6 +24,7 @@
 #include <video/videomode.h>
 
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_bridge.h>
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_mipi_dsi.h>
 #include <drm/drm_panel.h>
index b78e8c5ba553b215f590a38ec6bf97dce02b9e7d..f41d75923557a23a0e1fcfc103aac0c76abb7277 100644 (file)
@@ -21,6 +21,7 @@
 #include <video/of_videomode.h>
 #include <video/videomode.h>
 
+#include <drm/drm_bridge.h>
 #include <drm/drm_encoder.h>
 #include <drm/drm_print.h>
 
index bc1565f1822ab096a86b949024a625519be040c9..48159d5d22144457d38a1792f7a2c546acdef40b 100644 (file)
@@ -34,6 +34,7 @@
 #include <media/cec-notifier.h>
 
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_bridge.h>
 #include <drm/drm_edid.h>
 #include <drm/drm_print.h>
 #include <drm/drm_probe_helper.h>
@@ -852,6 +853,10 @@ static enum drm_connector_status hdmi_detect(struct drm_connector *connector,
 
 static void hdmi_connector_destroy(struct drm_connector *connector)
 {
+       struct hdmi_context *hdata = connector_to_hdmi(connector);
+
+       cec_notifier_conn_unregister(hdata->notifier);
+
        drm_connector_unregister(connector);
        drm_connector_cleanup(connector);
 }
@@ -935,6 +940,7 @@ static int hdmi_create_connector(struct drm_encoder *encoder)
 {
        struct hdmi_context *hdata = encoder_to_hdmi(encoder);
        struct drm_connector *connector = &hdata->connector;
+       struct cec_connector_info conn_info;
        int ret;
 
        connector->interlace_allowed = true;
@@ -957,6 +963,15 @@ static int hdmi_create_connector(struct drm_encoder *encoder)
                        DRM_DEV_ERROR(hdata->dev, "Failed to attach bridge\n");
        }
 
+       cec_fill_conn_info_from_drm(&conn_info, connector);
+
+       hdata->notifier = cec_notifier_conn_register(hdata->dev, NULL,
+                                                    &conn_info);
+       if (!hdata->notifier) {
+               ret = -ENOMEM;
+               DRM_DEV_ERROR(hdata->dev, "Failed to allocate CEC notifier\n");
+       }
+
        return ret;
 }
 
@@ -1528,8 +1543,8 @@ static void hdmi_disable(struct drm_encoder *encoder)
                 */
                mutex_unlock(&hdata->mutex);
                cancel_delayed_work(&hdata->hotplug_work);
-               cec_notifier_set_phys_addr(hdata->notifier,
-                                          CEC_PHYS_ADDR_INVALID);
+               if (hdata->notifier)
+                       cec_notifier_phys_addr_invalidate(hdata->notifier);
                return;
        }
 
@@ -2006,12 +2021,6 @@ static int hdmi_probe(struct platform_device *pdev)
                }
        }
 
-       hdata->notifier = cec_notifier_get(&pdev->dev);
-       if (hdata->notifier == NULL) {
-               ret = -ENOMEM;
-               goto err_hdmiphy;
-       }
-
        pm_runtime_enable(dev);
 
        audio_infoframe = &hdata->audio.infoframe;
@@ -2023,7 +2032,7 @@ static int hdmi_probe(struct platform_device *pdev)
 
        ret = hdmi_register_audio_device(hdata);
        if (ret)
-               goto err_notifier_put;
+               goto err_rpm_disable;
 
        ret = component_add(&pdev->dev, &hdmi_component_ops);
        if (ret)
@@ -2034,8 +2043,7 @@ static int hdmi_probe(struct platform_device *pdev)
 err_unregister_audio:
        platform_device_unregister(hdata->audio.pdev);
 
-err_notifier_put:
-       cec_notifier_put(hdata->notifier);
+err_rpm_disable:
        pm_runtime_disable(dev);
 
 err_hdmiphy:
@@ -2054,12 +2062,10 @@ static int hdmi_remove(struct platform_device *pdev)
        struct hdmi_context *hdata = platform_get_drvdata(pdev);
 
        cancel_delayed_work_sync(&hdata->hotplug_work);
-       cec_notifier_set_phys_addr(hdata->notifier, CEC_PHYS_ADDR_INVALID);
 
        component_del(&pdev->dev, &hdmi_component_ops);
        platform_device_unregister(hdata->audio.pdev);
 
-       cec_notifier_put(hdata->notifier);
        pm_runtime_disable(&pdev->dev);
 
        if (!IS_ERR(hdata->reg_hdmi_en))
index a92fd6c70b09e8b298229e65921b6678015533f6..82c972e9c02461b47603b9709071e7ccd335cd2b 100644 (file)
@@ -9,6 +9,7 @@
 #include <linux/of_graph.h>
 
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_bridge.h>
 #include <drm/drm_of.h>
 #include <drm/drm_panel.h>
 #include <drm/drm_probe_helper.h>
index 35a3c5f0c38cc1cb38e755244e7f5334c10af5c6..dfc5aef62f7ba2b3d4a8c9c780ea6cb16128ca20 100644 (file)
@@ -4,7 +4,8 @@ config DRM_HISI_HIBMC
        depends on DRM && PCI && MMU && ARM64
        select DRM_KMS_HELPER
        select DRM_VRAM_HELPER
-
+       select DRM_TTM
+       select DRM_TTM_HELPER
        help
          Choose this option if you have a Hisilicon Hibmc soc chipset.
          If M is selected the module will be called hibmc-drm.
index c103005b0a33e440592766e2fdd298ad6a7431c1..4f52c83b9b4c026f6b67668dd928c6f824acea36 100644 (file)
@@ -22,7 +22,6 @@
 #include <drm/drm_print.h>
 #include <drm/drm_probe_helper.h>
 #include <drm/drm_vblank.h>
-#include <drm/drm_vram_mm_helper.h>
 
 #include "hibmc_drm_drv.h"
 #include "hibmc_drm_regs.h"
index 9f6e473e629578f694c2fce5091ef78d6e459cc0..21b684eab5c9c6785550774a37dd19b8242a4997 100644 (file)
@@ -17,7 +17,6 @@
 #include <drm/drm_gem.h>
 #include <drm/drm_gem_vram_helper.h>
 #include <drm/drm_print.h>
-#include <drm/drm_vram_mm_helper.h>
 
 #include "hibmc_drm_drv.h"
 
@@ -29,7 +28,7 @@ int hibmc_mm_init(struct hibmc_drm_private *hibmc)
 
        vmm = drm_vram_helper_alloc_mm(dev,
                                       pci_resource_start(dev->pdev, 0),
-                                      hibmc->fb_size, &drm_gem_vram_mm_funcs);
+                                      hibmc->fb_size);
        if (IS_ERR(vmm)) {
                ret = PTR_ERR(vmm);
                DRM_ERROR("Error initializing VRAM MM; %d\n", ret);
index 5bf8138941ded16c498c50df53c31c058fc77987..bdcf9c6ae9e9ec07e63c6e9aadf9e19c467ba6dd 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/platform_device.h>
 
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_bridge.h>
 #include <drm/drm_device.h>
 #include <drm/drm_encoder_slave.h>
 #include <drm/drm_mipi_dsi.h>
index 8bcf0d1991451a797e9fe14bb075b228648bc1a2..a839f78a4c8a3037d8335330bfb86f033bc740a0 100644 (file)
@@ -44,7 +44,7 @@ struct sil164_priv {
        ((struct sil164_priv *)to_encoder_slave(x)->slave_priv)
 
 #define sil164_dbg(client, format, ...) do {                           \
-               if (drm_debug & DRM_UT_KMS)                             \
+               if (drm_debug_enabled(DRM_UT_KMS))                      \
                        dev_printk(KERN_DEBUG, &client->dev,            \
                                   "%s: " format, __func__, ## __VA_ARGS__); \
        } while (0)
index 8039fc0d83db44188de1a9515a1c2f93048291c7..a5a75bdeb7a5fa4462993829a88a753eb6cdc6a4 100644 (file)
@@ -420,7 +420,8 @@ static int tda9950_probe(struct i2c_client *client,
                priv->hdmi = glue->parent;
 
        priv->adap = cec_allocate_adapter(&tda9950_cec_ops, priv, "tda9950",
-                                         CEC_CAP_DEFAULTS,
+                                         CEC_CAP_DEFAULTS |
+                                         CEC_CAP_CONNECTOR_INFO,
                                          CEC_MAX_LOG_ADDRS);
        if (IS_ERR(priv->adap))
                return PTR_ERR(priv->adap);
@@ -457,13 +458,14 @@ static int tda9950_probe(struct i2c_client *client,
        if (ret < 0)
                return ret;
 
-       priv->notify = cec_notifier_get(priv->hdmi);
+       priv->notify = cec_notifier_cec_adap_register(priv->hdmi, NULL,
+                                                     priv->adap);
        if (!priv->notify)
                return -ENOMEM;
 
        ret = cec_register_adapter(priv->adap, priv->hdmi);
        if (ret < 0) {
-               cec_notifier_put(priv->notify);
+               cec_notifier_cec_adap_unregister(priv->notify);
                return ret;
        }
 
@@ -473,8 +475,6 @@ static int tda9950_probe(struct i2c_client *client,
         */
        devm_remove_action(dev, tda9950_cec_del, priv);
 
-       cec_register_cec_notifier(priv->adap, priv->notify);
-
        return 0;
 }
 
@@ -482,8 +482,8 @@ static int tda9950_remove(struct i2c_client *client)
 {
        struct tda9950_priv *priv = i2c_get_clientdata(client);
 
+       cec_notifier_cec_adap_unregister(priv->notify);
        cec_unregister_adapter(priv->adap);
-       cec_notifier_put(priv->notify);
 
        return 0;
 }
index 84c6d4c91c658cb777817c64f86331ec97728414..6c218bace2ce78c77744d69fa859a8f495522556 100644 (file)
@@ -14,6 +14,7 @@
 #include <sound/hdmi-codec.h>
 
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_bridge.h>
 #include <drm/drm_edid.h>
 #include <drm/drm_of.h>
 #include <drm/drm_print.h>
index 308ec63207ee272cf894e8a7ac15517f2396bf3a..ba2ef165a01ae59c9a7857c293b2e27dc601657d 100644 (file)
@@ -277,7 +277,7 @@ intel_attach_aspect_ratio_property(struct drm_connector *connector)
 void
 intel_attach_colorspace_property(struct drm_connector *connector)
 {
-       if (!drm_mode_create_colorspace_property(connector))
+       if (!drm_mode_create_hdmi_colorspace_property(connector))
                drm_object_attach_property(&connector->base,
                                           connector->colorspace_property, 0);
 }
index 921ad0a2f7ba7c743bea90622216d019846a6f22..2950e9308a4f77239dae51096a4c37772f15e3fd 100644 (file)
@@ -5490,7 +5490,6 @@ static int
 intel_dp_connector_register(struct drm_connector *connector)
 {
        struct intel_dp *intel_dp = intel_attached_dp(connector);
-       struct drm_device *dev = connector->dev;
        int ret;
 
        ret = intel_connector_register(connector);
@@ -5505,8 +5504,7 @@ intel_dp_connector_register(struct drm_connector *connector)
        intel_dp->aux.dev = connector->kdev;
        ret = drm_dp_aux_register(&intel_dp->aux);
        if (!ret)
-               drm_dp_cec_register_connector(&intel_dp->aux,
-                                             connector->name, dev->dev);
+               drm_dp_cec_register_connector(&intel_dp->aux, connector);
        return ret;
 }
 
index e02f0faecf02806235df03dbe870ec88dd9b5a73..0f5a0c618e461595a6d008c7e207b04ad18b363d 100644 (file)
@@ -2751,8 +2751,9 @@ intel_hdmi_connector_register(struct drm_connector *connector)
 
 static void intel_hdmi_destroy(struct drm_connector *connector)
 {
-       if (intel_attached_hdmi(connector)->cec_notifier)
-               cec_notifier_put(intel_attached_hdmi(connector)->cec_notifier);
+       struct cec_notifier *n = intel_attached_hdmi(connector)->cec_notifier;
+
+       cec_notifier_conn_unregister(n);
 
        intel_connector_destroy(connector);
 }
@@ -3067,6 +3068,7 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port,
        struct drm_device *dev = intel_encoder->base.dev;
        struct drm_i915_private *dev_priv = to_i915(dev);
        enum port port = intel_encoder->port;
+       struct cec_connector_info conn_info;
 
        DRM_DEBUG_KMS("Adding HDMI connector on port %c\n",
                      port_name(port));
@@ -3119,8 +3121,11 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port,
                I915_WRITE(PEG_BAND_GAP_DATA, (temp & ~0xf) | 0xd);
        }
 
-       intel_hdmi->cec_notifier = cec_notifier_get_conn(dev->dev,
-                                                        port_identifier(port));
+       cec_fill_conn_info_from_drm(&conn_info, connector);
+
+       intel_hdmi->cec_notifier =
+               cec_notifier_conn_register(dev->dev, port_identifier(port),
+                                          &conn_info);
        if (!intel_hdmi->cec_notifier)
                DRM_DEBUG_KMS("CEC notifier get failed\n");
 }
index 020696726f9e63703e665b614fb83cf1a8c54a17..1c4ff8b5b0a2d359c94f59d26ac52b7845052e4b 100644 (file)
@@ -422,31 +422,6 @@ out:
        return ret;
 }
 
-static int i915_kick_out_firmware_fb(struct drm_i915_private *dev_priv)
-{
-       struct apertures_struct *ap;
-       struct pci_dev *pdev = dev_priv->drm.pdev;
-       struct i915_ggtt *ggtt = &dev_priv->ggtt;
-       bool primary;
-       int ret;
-
-       ap = alloc_apertures(1);
-       if (!ap)
-               return -ENOMEM;
-
-       ap->ranges[0].base = ggtt->gmadr.start;
-       ap->ranges[0].size = ggtt->mappable_end;
-
-       primary =
-               pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW;
-
-       ret = drm_fb_helper_remove_conflicting_framebuffers(ap, "inteldrmfb", primary);
-
-       kfree(ap);
-
-       return ret;
-}
-
 static void intel_init_dpio(struct drm_i915_private *dev_priv)
 {
        /*
@@ -1249,21 +1224,9 @@ static int i915_driver_hw_probe(struct drm_i915_private *dev_priv)
        if (ret)
                goto err_perf;
 
-       /*
-        * WARNING: Apparently we must kick fbdev drivers before vgacon,
-        * otherwise the vga fbdev driver falls over.
-        */
-       ret = i915_kick_out_firmware_fb(dev_priv);
-       if (ret) {
-               DRM_ERROR("failed to remove conflicting framebuffer drivers\n");
-               goto err_ggtt;
-       }
-
-       ret = vga_remove_vgacon(pdev);
-       if (ret) {
-               DRM_ERROR("failed to remove conflicting VGA console\n");
+       ret = drm_fb_helper_remove_conflicting_pci_framebuffers(pdev, "inteldrmfb");
+       if (ret)
                goto err_ggtt;
-       }
 
        ret = i915_ggtt_init_hw(dev_priv);
        if (ret)
index 695f307f36b2862c2a9f46f816644e9a2e1ae842..208069faf183dd46622f0f6789ab6992bb07ccce 100644 (file)
@@ -20,6 +20,7 @@
 
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_bridge.h>
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_of.h>
 #include <drm/drm_panel.h>
index e7ce17503ae1774d8b44b23ebf565519ab321f0c..35518e5de356d7b0adb16a01266db15cf4307979 100644 (file)
@@ -13,6 +13,7 @@
 #include <video/of_display_timing.h>
 
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_bridge.h>
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_of.h>
 #include <drm/drm_panel.h>
index 2e2ed653e9c6b452e281ea4625fe56863ee7f7d1..ec32e1c673350cd6ad1b628cf7aba1c7a03c87c7 100644 (file)
@@ -13,6 +13,7 @@
 
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_bridge.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_crtc_helper.h>
 #include <drm/drm_drv.h>
@@ -676,8 +677,8 @@ static int ingenic_drm_probe(struct platform_device *pdev)
        }
 
        if (panel)
-               bridge = devm_drm_panel_bridge_add(dev, panel,
-                                                  DRM_MODE_CONNECTOR_DPI);
+               bridge = devm_drm_panel_bridge_add_typed(dev, panel,
+                                                        DRM_MODE_CONNECTOR_DPI);
 
        priv->dma_hwdesc = dma_alloc_coherent(dev, sizeof(*priv->dma_hwdesc),
                                              &priv->dma_hwdesc_phys,
index 9a09eba5318273611fb7a6f0f63bd5b0ae190f66..5649887d2b90126d17ea37c89fd699ab1b3d6777 100644 (file)
@@ -484,7 +484,8 @@ static int mcde_probe(struct platform_device *pdev)
        }
        if (!match) {
                dev_err(dev, "no matching components\n");
-               return -ENODEV;
+               ret = -ENODEV;
+               goto clk_disable;
        }
        if (IS_ERR(match)) {
                dev_err(dev, "could not create component match\n");
index f9c9e32b299c9a60c2f530adad3147b93c862c25..d6214d3c8b337b5b6ab4c1f19fb17fbca003f41c 100644 (file)
@@ -946,8 +946,8 @@ static int mcde_dsi_bind(struct device *dev, struct device *master,
                }
        }
        if (panel) {
-               bridge = drm_panel_bridge_add(panel,
-                                             DRM_MODE_CONNECTOR_DSI);
+               bridge = drm_panel_bridge_add_typed(panel,
+                                                   DRM_MODE_CONNECTOR_DSI);
                if (IS_ERR(bridge)) {
                        dev_err(dev, "error adding panel bridge\n");
                        return PTR_ERR(bridge);
index be6d95c5ff253388fc89e5b673574febe03e1f31..01fa8b8d763d182ac9b33dfe3a8f81e11702fb2a 100644 (file)
@@ -17,6 +17,7 @@
 #include <video/videomode.h>
 
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_bridge.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_of.h>
 
index 224afb666881c496e11343c8c9264917d3291154..a413f5ff442da04f7c38d18757e8a705f2b188b2 100644 (file)
@@ -16,6 +16,7 @@
 #include <video/videomode.h>
 
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_bridge.h>
 #include <drm/drm_mipi_dsi.h>
 #include <drm/drm_of.h>
 #include <drm/drm_panel.h>
index ce91b61364eb6a86b70f2646721681d78c7391f5..c79b1f855d89559584e0ee5ff6c1d30091c1482f 100644 (file)
@@ -23,6 +23,7 @@
 #include <sound/hdmi-codec.h>
 
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_bridge.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_edid.h>
 #include <drm/drm_print.h>
index a24f8dec5adc9ed725456b8e28f365c7d5831a6d..397c33182f4f83325d066bf5454d0ebd1cc5b14c 100644 (file)
@@ -372,6 +372,33 @@ static const struct component_master_ops meson_drv_master_ops = {
        .unbind = meson_drv_unbind,
 };
 
+static int __maybe_unused meson_drv_pm_suspend(struct device *dev)
+{
+       struct meson_drm *priv = dev_get_drvdata(dev);
+
+       if (!priv)
+               return 0;
+
+       return drm_mode_config_helper_suspend(priv->drm);
+}
+
+static int __maybe_unused meson_drv_pm_resume(struct device *dev)
+{
+       struct meson_drm *priv = dev_get_drvdata(dev);
+
+       if (!priv)
+               return 0;
+
+       meson_vpu_init(priv);
+       meson_venc_init(priv);
+       meson_vpp_init(priv);
+       meson_viu_init(priv);
+
+       drm_mode_config_helper_resume(priv->drm);
+
+       return 0;
+}
+
 static int compare_of(struct device *dev, void *data)
 {
        DRM_DEBUG_DRIVER("Comparing of node %pOF with %pOF\n",
@@ -467,11 +494,16 @@ static const struct of_device_id dt_match[] = {
 };
 MODULE_DEVICE_TABLE(of, dt_match);
 
+static const struct dev_pm_ops meson_drv_pm_ops = {
+       SET_SYSTEM_SLEEP_PM_OPS(meson_drv_pm_suspend, meson_drv_pm_resume)
+};
+
 static struct platform_driver meson_drm_platform_driver = {
        .probe      = meson_drv_probe,
        .driver     = {
                .name   = "meson-drm",
                .of_match_table = dt_match,
+               .pm = &meson_drv_pm_ops,
        },
 };
 
index 68bbd987147b0257328b3fa57cca545f000fa9c9..022286dc6ab24960b921522e3f9163e993640a6d 100644 (file)
@@ -802,6 +802,47 @@ static bool meson_hdmi_connector_is_available(struct device *dev)
        return false;
 }
 
+static void meson_dw_hdmi_init(struct meson_dw_hdmi *meson_dw_hdmi)
+{
+       struct meson_drm *priv = meson_dw_hdmi->priv;
+
+       /* Enable clocks */
+       regmap_update_bits(priv->hhi, HHI_HDMI_CLK_CNTL, 0xffff, 0x100);
+
+       /* Bring HDMITX MEM output of power down */
+       regmap_update_bits(priv->hhi, HHI_MEM_PD_REG0, 0xff << 8, 0);
+
+       /* Reset HDMITX APB & TX & PHY */
+       reset_control_reset(meson_dw_hdmi->hdmitx_apb);
+       reset_control_reset(meson_dw_hdmi->hdmitx_ctrl);
+       reset_control_reset(meson_dw_hdmi->hdmitx_phy);
+
+       /* Enable APB3 fail on error */
+       if (!meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) {
+               writel_bits_relaxed(BIT(15), BIT(15),
+                                   meson_dw_hdmi->hdmitx + HDMITX_TOP_CTRL_REG);
+               writel_bits_relaxed(BIT(15), BIT(15),
+                                   meson_dw_hdmi->hdmitx + HDMITX_DWC_CTRL_REG);
+       }
+
+       /* Bring out of reset */
+       meson_dw_hdmi->data->top_write(meson_dw_hdmi,
+                                      HDMITX_TOP_SW_RESET,  0);
+
+       msleep(20);
+
+       meson_dw_hdmi->data->top_write(meson_dw_hdmi,
+                                      HDMITX_TOP_CLK_CNTL, 0xff);
+
+       /* Enable HDMI-TX Interrupt */
+       meson_dw_hdmi->data->top_write(meson_dw_hdmi, HDMITX_TOP_INTR_STAT_CLR,
+                                      HDMITX_TOP_INTR_CORE);
+
+       meson_dw_hdmi->data->top_write(meson_dw_hdmi, HDMITX_TOP_INTR_MASKN,
+                                      HDMITX_TOP_INTR_CORE);
+
+}
+
 static int meson_dw_hdmi_bind(struct device *dev, struct device *master,
                                void *data)
 {
@@ -925,40 +966,7 @@ static int meson_dw_hdmi_bind(struct device *dev, struct device *master,
 
        DRM_DEBUG_DRIVER("encoder initialized\n");
 
-       /* Enable clocks */
-       regmap_update_bits(priv->hhi, HHI_HDMI_CLK_CNTL, 0xffff, 0x100);
-
-       /* Bring HDMITX MEM output of power down */
-       regmap_update_bits(priv->hhi, HHI_MEM_PD_REG0, 0xff << 8, 0);
-
-       /* Reset HDMITX APB & TX & PHY */
-       reset_control_reset(meson_dw_hdmi->hdmitx_apb);
-       reset_control_reset(meson_dw_hdmi->hdmitx_ctrl);
-       reset_control_reset(meson_dw_hdmi->hdmitx_phy);
-
-       /* Enable APB3 fail on error */
-       if (!meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) {
-               writel_bits_relaxed(BIT(15), BIT(15),
-                                   meson_dw_hdmi->hdmitx + HDMITX_TOP_CTRL_REG);
-               writel_bits_relaxed(BIT(15), BIT(15),
-                                   meson_dw_hdmi->hdmitx + HDMITX_DWC_CTRL_REG);
-       }
-
-       /* Bring out of reset */
-       meson_dw_hdmi->data->top_write(meson_dw_hdmi,
-                                      HDMITX_TOP_SW_RESET,  0);
-
-       msleep(20);
-
-       meson_dw_hdmi->data->top_write(meson_dw_hdmi,
-                                      HDMITX_TOP_CLK_CNTL, 0xff);
-
-       /* Enable HDMI-TX Interrupt */
-       meson_dw_hdmi->data->top_write(meson_dw_hdmi, HDMITX_TOP_INTR_STAT_CLR,
-                                      HDMITX_TOP_INTR_CORE);
-
-       meson_dw_hdmi->data->top_write(meson_dw_hdmi, HDMITX_TOP_INTR_MASKN,
-                                      HDMITX_TOP_INTR_CORE);
+       meson_dw_hdmi_init(meson_dw_hdmi);
 
        /* Bridge / Connector */
 
@@ -994,6 +1002,34 @@ static const struct component_ops meson_dw_hdmi_ops = {
        .unbind = meson_dw_hdmi_unbind,
 };
 
+static int __maybe_unused meson_dw_hdmi_pm_suspend(struct device *dev)
+{
+       struct meson_dw_hdmi *meson_dw_hdmi = dev_get_drvdata(dev);
+
+       if (!meson_dw_hdmi)
+               return 0;
+
+       /* Reset TOP */
+       meson_dw_hdmi->data->top_write(meson_dw_hdmi,
+                                      HDMITX_TOP_SW_RESET, 0);
+
+       return 0;
+}
+
+static int __maybe_unused meson_dw_hdmi_pm_resume(struct device *dev)
+{
+       struct meson_dw_hdmi *meson_dw_hdmi = dev_get_drvdata(dev);
+
+       if (!meson_dw_hdmi)
+               return 0;
+
+       meson_dw_hdmi_init(meson_dw_hdmi);
+
+       dw_hdmi_resume(meson_dw_hdmi->hdmi);
+
+       return 0;
+}
+
 static int meson_dw_hdmi_probe(struct platform_device *pdev)
 {
        return component_add(&pdev->dev, &meson_dw_hdmi_ops);
@@ -1006,6 +1042,11 @@ static int meson_dw_hdmi_remove(struct platform_device *pdev)
        return 0;
 }
 
+static const struct dev_pm_ops meson_dw_hdmi_pm_ops = {
+       SET_SYSTEM_SLEEP_PM_OPS(meson_dw_hdmi_pm_suspend,
+                               meson_dw_hdmi_pm_resume)
+};
+
 static const struct of_device_id meson_dw_hdmi_of_table[] = {
        { .compatible = "amlogic,meson-gxbb-dw-hdmi",
          .data = &meson_dw_hdmi_gx_data },
@@ -1025,6 +1066,7 @@ static struct platform_driver meson_dw_hdmi_platform_driver = {
        .driver         = {
                .name           = DRIVER_NAME,
                .of_match_table = meson_dw_hdmi_of_table,
+               .pm = &meson_dw_hdmi_pm_ops,
        },
 };
 module_platform_driver(meson_dw_hdmi_platform_driver);
index ac491a7819527643dbe62b120dc56b0776b3d788..f690793ae2d573f8cd01dfe54fa02bf6867e34f8 100644 (file)
@@ -638,13 +638,18 @@ static bool meson_hdmi_pll_validate_params(struct meson_drm *priv,
                if (frac >= HDMI_FRAC_MAX_GXBB)
                        return false;
        } else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM) ||
-                  meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXL) ||
-                  meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) {
+                  meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXL)) {
                /* Empiric supported min/max dividers */
                if (m < 106 || m > 247)
                        return false;
                if (frac >= HDMI_FRAC_MAX_GXL)
                        return false;
+       } else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) {
+               /* Empiric supported min/max dividers */
+               if (m < 106 || m > 247)
+                       return false;
+               if (frac >= HDMI_FRAC_MAX_G12A)
+                       return false;
        }
 
        return true;
index 76fee0fbdcae81a13741a752a10be2fa819cde79..aed11f4f4c55e84c4d769f7ae1a62c1dd6ba40b4 100644 (file)
@@ -4,6 +4,8 @@ config DRM_MGAG200
        depends on DRM && PCI && MMU
        select DRM_KMS_HELPER
        select DRM_VRAM_HELPER
+       select DRM_TTM
+       select DRM_TTM_HELPER
        help
         This is a KMS driver for the MGA G200 server chips, it
          does not support the original MGA G200 or any of the desktop
index 289ce3e29032766d887f428d9bf30ad50d32e098..89f61573a497a11b817ec3cb728b3da6edba1cc5 100644 (file)
@@ -85,17 +85,12 @@ int mga_crtc_cursor_set(struct drm_crtc *crtc,
        if (!obj)
                return -ENOENT;
        gbo = drm_gem_vram_of_gem(obj);
-       ret = drm_gem_vram_pin(gbo, 0);
-       if (ret) {
-               dev_err(&dev->pdev->dev, "failed to lock user bo\n");
-               goto err_drm_gem_object_put_unlocked;
-       }
-       src = drm_gem_vram_kmap(gbo, true, NULL);
+       src = drm_gem_vram_vmap(gbo);
        if (IS_ERR(src)) {
                ret = PTR_ERR(src);
                dev_err(&dev->pdev->dev,
-                       "failed to kmap user buffer updates\n");
-               goto err_drm_gem_vram_unpin_src;
+                       "failed to map user buffer updates\n");
+               goto err_drm_gem_object_put_unlocked;
        }
 
        /* Pin and map up-coming buffer to write colour indices */
@@ -103,7 +98,7 @@ int mga_crtc_cursor_set(struct drm_crtc *crtc,
        if (ret) {
                dev_err(&dev->pdev->dev,
                        "failed to pin cursor buffer: %d\n", ret);
-               goto err_drm_gem_vram_kunmap_src;
+               goto err_drm_gem_vram_vunmap;
        }
        dst = drm_gem_vram_kmap(pixels_next, true, NULL);
        if (IS_ERR(dst)) {
@@ -213,8 +208,7 @@ int mga_crtc_cursor_set(struct drm_crtc *crtc,
        mdev->cursor.pixels_current = pixels_next;
 
        drm_gem_vram_kunmap(pixels_next);
-       drm_gem_vram_kunmap(gbo);
-       drm_gem_vram_unpin(gbo);
+       drm_gem_vram_vunmap(gbo, src);
        drm_gem_object_put_unlocked(obj);
 
        return 0;
@@ -223,10 +217,8 @@ err_drm_gem_vram_kunmap_dst:
        drm_gem_vram_kunmap(pixels_next);
 err_drm_gem_vram_unpin_dst:
        drm_gem_vram_unpin(pixels_next);
-err_drm_gem_vram_kunmap_src:
-       drm_gem_vram_kunmap(gbo);
-err_drm_gem_vram_unpin_src:
-       drm_gem_vram_unpin(gbo);
+err_drm_gem_vram_vunmap:
+       drm_gem_vram_vunmap(gbo, src);
 err_drm_gem_object_put_unlocked:
        drm_gem_object_put_unlocked(obj);
        return ret;
index afd9119b6cf1bed4a8b143387f160ddfa0078215..4f9df3b93598a215d5e6d1701796f7b33f82d192 100644 (file)
@@ -46,7 +46,7 @@ MODULE_DEVICE_TABLE(pci, pciidlist);
 
 static int mga_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
-       drm_fb_helper_remove_conflicting_pci_framebuffers(pdev, 0, "mgag200drmfb");
+       drm_fb_helper_remove_conflicting_pci_framebuffers(pdev, "mgag200drmfb");
 
        return drm_get_pci_dev(pdev, ent, &driver);
 }
index 1c93f8dc08c7720512cdfe5b137d9d185a764463..37c003ed57c057c6c6c11e95e1832ded7302cadc 100644 (file)
@@ -19,7 +19,6 @@
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_gem.h>
 #include <drm/drm_gem_vram_helper.h>
-#include <drm/drm_vram_mm_helper.h>
 
 #include "mgag200_reg.h"
 
index 5e778b5f1a10a7f97e95c46ac2ba58f5278d5662..68226556044b9272d5c0fd27b476b1da1dfbcb88 100644 (file)
@@ -1638,16 +1638,6 @@ static enum drm_mode_status mga_vga_mode_valid(struct drm_connector *connector,
        return MODE_OK;
 }
 
-static struct drm_encoder *mga_connector_best_encoder(struct drm_connector
-                                                 *connector)
-{
-       int enc_id = connector->encoder_ids[0];
-       /* pick the encoder ids */
-       if (enc_id)
-               return drm_encoder_find(connector->dev, NULL, enc_id);
-       return NULL;
-}
-
 static void mga_connector_destroy(struct drm_connector *connector)
 {
        struct mga_connector *mga_connector = to_mga_connector(connector);
@@ -1659,7 +1649,6 @@ static void mga_connector_destroy(struct drm_connector *connector)
 static const struct drm_connector_helper_funcs mga_vga_connector_helper_funcs = {
        .get_modes = mga_vga_get_modes,
        .mode_valid = mga_vga_mode_valid,
-       .best_encoder = mga_connector_best_encoder,
 };
 
 static const struct drm_connector_funcs mga_vga_connector_funcs = {
index 73a6b848601cd405c77aa6f5a2f1610de08c73df..69c81ebf37456445e82eed09969912f0fbbab7da 100644 (file)
@@ -37,8 +37,7 @@ int mgag200_mm_init(struct mga_device *mdev)
        struct drm_device *dev = mdev->dev;
 
        vmm = drm_vram_helper_alloc_mm(dev, pci_resource_start(dev->pdev, 0),
-                                      mdev->mc.vram_size,
-                                      &drm_gem_vram_mm_funcs);
+                                      mdev->mc.vram_size);
        if (IS_ERR(vmm)) {
                ret = PTR_ERR(vmm);
                DRM_ERROR("Error initializing VRAM MM; %d\n", ret);
index 4c889aabdaf98c276d1d04e6d6d96cde7dc507f0..959d03e007fa76480f09869ad535ce0a4a0a74e4 100644 (file)
@@ -31,7 +31,7 @@
  */
 #define DPU_DEBUG(fmt, ...)                                                \
        do {                                                               \
-               if (unlikely(drm_debug & DRM_UT_KMS))                      \
+               if (drm_debug_enabled(DRM_UT_KMS))                         \
                        DRM_DEBUG(fmt, ##__VA_ARGS__); \
                else                                                       \
                        pr_debug(fmt, ##__VA_ARGS__);                      \
@@ -43,7 +43,7 @@
  */
 #define DPU_DEBUG_DRIVER(fmt, ...)                                         \
        do {                                                               \
-               if (unlikely(drm_debug & DRM_UT_DRIVER))                   \
+               if (drm_debug_enabled(DRM_UT_DRIVER))                      \
                        DRM_ERROR(fmt, ##__VA_ARGS__); \
                else                                                       \
                        pr_debug(fmt, ##__VA_ARGS__);                      \
index 0da8a4e428ad236319aacb4bbbae4a578da02b3e..eff1a4c612584b10f36f9e43b1a0b8d458e7ae97 100644 (file)
@@ -9,6 +9,7 @@
 #include <linux/of_platform.h>
 #include <linux/platform_device.h>
 
+#include <drm/drm_bridge.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_mipi_dsi.h>
 #include <drm/drm_panel.h>
index 0f312ac5b6240930a67c400517c08d798fda2e19..ad4e963ccd9b04aa324485e77adcf86d07e8e6d2 100644 (file)
@@ -178,7 +178,9 @@ int msm_edp_modeset_init(struct msm_edp *edp, struct drm_device *dev,
                goto fail;
        }
 
-       encoder->bridge = edp->bridge;
+       ret = drm_bridge_attach(encoder, edp->bridge, NULL);
+       if (ret)
+               goto fail;
 
        priv->bridges[priv->num_bridges++]       = edp->bridge;
        priv->connectors[priv->num_connectors++] = edp->connector;
index f2c17858a703ff27371a3941f30116b2eef32f9b..eb34243dad530ea382d07b57f452976b644fffcc 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/interrupt.h>
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
+#include <drm/drm_bridge.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_dp_helper.h>
 
index 355afb936401a040012cfeabb2b47009930c2f1e..1a9b6289637da220015d4a67f2aac4463c2c2f2a 100644 (file)
@@ -327,7 +327,9 @@ int msm_hdmi_modeset_init(struct hdmi *hdmi,
                goto fail;
        }
 
-       encoder->bridge = hdmi->bridge;
+       ret = drm_bridge_attach(encoder, hdmi->bridge, NULL);
+       if (ret)
+               goto fail;
 
        priv->bridges[priv->num_bridges++]       = hdmi->bridge;
        priv->connectors[priv->num_connectors++] = hdmi->connector;
index bdac452b00fb324ce661b47b731fc7872250e20b..d0b84f0abee17146deeed623cd3da8aad355d951 100644 (file)
@@ -14,6 +14,8 @@
 #include <linux/gpio/consumer.h>
 #include <linux/hdmi.h>
 
+#include <drm/drm_bridge.h>
+
 #include "msm_drv.h"
 #include "hdmi.xml.h"
 
index dc64863b5fd88a8bcf30aea2c6212e87ac1d3cf0..44ee82d0c9b6a6af7b9e00ad272a3d70814c5744 100644 (file)
@@ -256,7 +256,7 @@ nv04_display_create(struct drm_device *dev)
 
        list_for_each_entry_safe(connector, ct,
                                 &dev->mode_config.connector_list, head) {
-               if (!connector->encoder_ids[0]) {
+               if (!connector->possible_encoders) {
                        NV_WARN(drm, "%s has no encoders, removing\n",
                                connector->name);
                        connector->funcs->destroy(connector);
index b46be8a091e99cfc77009bc850bea8ecceaa993c..a13924ae1992a438820de61acbf860d0362f6423 100644 (file)
@@ -2392,7 +2392,7 @@ nv50_display_create(struct drm_device *dev)
 
        /* cull any connectors we created that don't have an encoder */
        list_for_each_entry_safe(connector, tmp, &dev->mode_config.connector_list, head) {
-               if (connector->encoder_ids[0])
+               if (connector->possible_encoders)
                        continue;
 
                NV_WARN(drm, "%s has no encoders, removing\n",
index 94dfa2e5a9abed6c8e4a16410c22b11c44b40447..3a5db17bc5c7ad56c3c1ea06f4bfd93d0518bab7 100644 (file)
@@ -365,9 +365,8 @@ find_encoder(struct drm_connector *connector, int type)
 {
        struct nouveau_encoder *nv_encoder;
        struct drm_encoder *enc;
-       int i;
 
-       drm_connector_for_each_possible_encoder(connector, enc, i) {
+       drm_connector_for_each_possible_encoder(connector, enc) {
                nv_encoder = nouveau_encoder(enc);
 
                if (type == DCB_OUTPUT_ANY ||
@@ -414,10 +413,10 @@ nouveau_connector_ddc_detect(struct drm_connector *connector)
        struct drm_device *dev = connector->dev;
        struct nouveau_encoder *nv_encoder = NULL, *found = NULL;
        struct drm_encoder *encoder;
-       int i, ret;
+       int ret;
        bool switcheroo_ddc = false;
 
-       drm_connector_for_each_possible_encoder(connector, encoder, i) {
+       drm_connector_for_each_possible_encoder(connector, encoder) {
                nv_encoder = nouveau_encoder(encoder);
 
                switch (nv_encoder->dcb->type) {
@@ -1415,8 +1414,7 @@ nouveau_connector_create(struct drm_device *dev,
        switch (type) {
        case DRM_MODE_CONNECTOR_DisplayPort:
        case DRM_MODE_CONNECTOR_eDP:
-               drm_dp_cec_register_connector(&nv_connector->aux,
-                                             connector->name, dev->dev);
+               drm_dp_cec_register_connector(&nv_connector->aux, connector);
                break;
        }
 
index f0daf958e03a2c810664874f7028205c2af73e94..77a0c6ad3cef55e12c04fb88499af5d6899ce506 100644 (file)
@@ -236,6 +236,7 @@ nouveau_ttm_init(struct nouveau_drm *drm)
        ret = ttm_bo_device_init(&drm->ttm.bdev,
                                  &nouveau_bo_driver,
                                  dev->anon_inode->i_mapping,
+                                 dev->vma_offset_manager,
                                  drm->client.mmu.dmabits <= 32 ? true : false);
        if (ret) {
                NV_ERROR(drm, "error initialising bo driver, %d\n", ret);
index 14b41de44ebcda9a6c6ebda7de21817b22de2a90..0693d34fca1b9c89ea803137d5e5f25d581cd467 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/of.h>
 #include <linux/of_graph.h>
 
+#include <drm/drm_bridge.h>
 #include <drm/drm_panel.h>
 
 #include "dss.h"
index 2983c003698ec9b59d6fb772ad2264b21c55b951..b3e22c890c51d97eb855acdcd8a1678cf92fdcca 100644 (file)
@@ -11,6 +11,7 @@
 
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_bridge.h>
 #include <drm/drm_drv.h>
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_file.h>
index 6fe14111cd95603991a57da84d89fe36529f67a5..24bbe9f2a32ec696fcd2ec6cae339c51371d5068 100644 (file)
@@ -6,6 +6,7 @@
 
 #include <linux/list.h>
 
+#include <drm/drm_bridge.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_modeset_helper_vtables.h>
 #include <drm/drm_edid.h>
index 5f72c922a04b19f5a3dde6c0b6d4f759a56c91af..a0574dc03e16fd9275ca64fbfbc1be861082170e 100644 (file)
@@ -350,9 +350,8 @@ static int versatile_panel_probe(struct platform_device *pdev)
                        dev_info(dev, "panel mounted on IB2 daughterboard\n");
        }
 
-       drm_panel_init(&vpanel->panel);
-       vpanel->panel.dev = dev;
-       vpanel->panel.funcs = &versatile_panel_drm_funcs;
+       drm_panel_init(&vpanel->panel, dev, &versatile_panel_drm_funcs,
+                      DRM_MODE_CONNECTOR_DPI);
 
        return drm_panel_add(&vpanel->panel);
 }
index dabf59e0f56facafa8e1e991069ec099496ae4ea..98f184b811873429e880b7d29660e58356b0a9ab 100644 (file)
@@ -204,9 +204,8 @@ static int feiyang_dsi_probe(struct mipi_dsi_device *dsi)
        mipi_dsi_set_drvdata(dsi, ctx);
        ctx->dsi = dsi;
 
-       drm_panel_init(&ctx->panel);
-       ctx->panel.dev = &dsi->dev;
-       ctx->panel.funcs = &feiyang_funcs;
+       drm_panel_init(&ctx->panel, &dsi->dev, &feiyang_funcs,
+                      DRM_MODE_CONNECTOR_DSI);
 
        ctx->dvdd = devm_regulator_get(&dsi->dev, "dvdd");
        if (IS_ERR(ctx->dvdd)) {
index 3c58f63adbf7e727851ef98f9587c9567b65fe00..24955bec1958bd64b10f03a5a1e42d38cc81f19f 100644 (file)
@@ -895,9 +895,8 @@ static int ili9322_probe(struct spi_device *spi)
                ili->input = ili->conf->input;
        }
 
-       drm_panel_init(&ili->panel);
-       ili->panel.dev = dev;
-       ili->panel.funcs = &ili9322_drm_funcs;
+       drm_panel_init(&ili->panel, dev, &ili9322_drm_funcs,
+                      DRM_MODE_CONNECTOR_DPI);
 
        return drm_panel_add(&ili->panel);
 }
index 3ad4a46c4e945d2b49785c8d7298cb1d7d26bb30..e8789e460a169e3e206245a5c35e5a34fd406bb0 100644 (file)
@@ -433,9 +433,8 @@ static int ili9881c_dsi_probe(struct mipi_dsi_device *dsi)
        mipi_dsi_set_drvdata(dsi, ctx);
        ctx->dsi = dsi;
 
-       drm_panel_init(&ctx->panel);
-       ctx->panel.dev = &dsi->dev;
-       ctx->panel.funcs = &ili9881c_funcs;
+       drm_panel_init(&ctx->panel, &dsi->dev, &ili9881c_funcs,
+                      DRM_MODE_CONNECTOR_DSI);
 
        ctx->power = devm_regulator_get(&dsi->dev, "power");
        if (IS_ERR(ctx->power)) {
index d92d1c98878c12f8bffecfd0d955d84140033ac1..83df1ac4211f202fe1db4f2cf021cdf6c683b148 100644 (file)
@@ -487,9 +487,8 @@ static int innolux_panel_add(struct mipi_dsi_device *dsi,
        if (IS_ERR(innolux->backlight))
                return PTR_ERR(innolux->backlight);
 
-       drm_panel_init(&innolux->base);
-       innolux->base.funcs = &innolux_panel_funcs;
-       innolux->base.dev = dev;
+       drm_panel_init(&innolux->base, dev, &innolux_panel_funcs,
+                      DRM_MODE_CONNECTOR_DSI);
 
        err = drm_panel_add(&innolux->base);
        if (err < 0)
index ff3e89e61e3fc44c101b52dfbf8512b785e422d2..56364a93f0b81950a7e37df9bbc736205dd0d5ad 100644 (file)
@@ -437,9 +437,8 @@ static int jdi_panel_add(struct jdi_panel *jdi)
                return ret;
        }
 
-       drm_panel_init(&jdi->base);
-       jdi->base.funcs = &jdi_panel_funcs;
-       jdi->base.dev = &jdi->dsi->dev;
+       drm_panel_init(&jdi->base, &jdi->dsi->dev, &jdi_panel_funcs,
+                      DRM_MODE_CONNECTOR_DSI);
 
        ret = drm_panel_add(&jdi->base);
 
index 3ac04eb8d0fe59c1a2f44362bf2497b2c09c5116..45f96556ec8c91028a313b0638e2d10cc2404ab9 100644 (file)
@@ -391,9 +391,8 @@ static int kingdisplay_panel_add(struct kingdisplay_panel *kingdisplay)
        if (IS_ERR(kingdisplay->backlight))
                return PTR_ERR(kingdisplay->backlight);
 
-       drm_panel_init(&kingdisplay->base);
-       kingdisplay->base.funcs = &kingdisplay_panel_funcs;
-       kingdisplay->base.dev = &kingdisplay->link->dev;
+       drm_panel_init(&kingdisplay->base, &kingdisplay->link->dev,
+                      &kingdisplay_panel_funcs, DRM_MODE_CONNECTOR_DSI);
 
        return drm_panel_add(&kingdisplay->base);
 }
index fc82a525b071bc3bc9f8e9ac0d3cedbca849bb3d..f984a5189fbfe732564845cb442b36d1aae73b64 100644 (file)
@@ -196,9 +196,8 @@ static int lb035q02_probe(struct spi_device *spi)
        if (ret < 0)
                return ret;
 
-       drm_panel_init(&lcd->panel);
-       lcd->panel.dev = &lcd->spi->dev;
-       lcd->panel.funcs = &lb035q02_funcs;
+       drm_panel_init(&lcd->panel, &lcd->spi->dev, &lb035q02_funcs,
+                      DRM_MODE_CONNECTOR_DPI);
 
        return drm_panel_add(&lcd->panel);
 }
index 41bf02d122a1f581e2cc6c3431a0e13d4529eed4..db4865a4c2b98928ea6a4b573da32c96f35c7485 100644 (file)
@@ -259,9 +259,8 @@ static int lg4573_probe(struct spi_device *spi)
                return ret;
        }
 
-       drm_panel_init(&ctx->panel);
-       ctx->panel.dev = &spi->dev;
-       ctx->panel.funcs = &lg4573_drm_funcs;
+       drm_panel_init(&ctx->panel, &spi->dev, &lg4573_drm_funcs,
+                      DRM_MODE_CONNECTOR_DPI);
 
        return drm_panel_add(&ctx->panel);
 }
index ad47cc95459ebb1b248f8c33bdcac1a7189cd1d0..2405f26e5d31f2ee8f9702e6c6780a3db61b00b7 100644 (file)
@@ -197,7 +197,6 @@ static int panel_lvds_parse_dt(struct panel_lvds *lvds)
 static int panel_lvds_probe(struct platform_device *pdev)
 {
        struct panel_lvds *lvds;
-       struct device_node *np;
        int ret;
 
        lvds = devm_kzalloc(&pdev->dev, sizeof(*lvds), GFP_KERNEL);
@@ -243,14 +242,9 @@ static int panel_lvds_probe(struct platform_device *pdev)
                return ret;
        }
 
-       np = of_parse_phandle(lvds->dev->of_node, "backlight", 0);
-       if (np) {
-               lvds->backlight = of_find_backlight_by_node(np);
-               of_node_put(np);
-
-               if (!lvds->backlight)
-                       return -EPROBE_DEFER;
-       }
+       lvds->backlight = devm_of_find_backlight(lvds->dev);
+       if (IS_ERR(lvds->backlight))
+               return PTR_ERR(lvds->backlight);
 
        /*
         * TODO: Handle all power supplies specified in the DT node in a generic
@@ -260,20 +254,15 @@ static int panel_lvds_probe(struct platform_device *pdev)
         */
 
        /* Register the panel. */
-       drm_panel_init(&lvds->panel);
-       lvds->panel.dev = lvds->dev;
-       lvds->panel.funcs = &panel_lvds_funcs;
+       drm_panel_init(&lvds->panel, lvds->dev, &panel_lvds_funcs,
+                      DRM_MODE_CONNECTOR_LVDS);
 
        ret = drm_panel_add(&lvds->panel);
        if (ret < 0)
-               goto error;
+               return ret;
 
        dev_set_drvdata(lvds->dev, lvds);
        return 0;
-
-error:
-       put_device(&lvds->backlight->dev);
-       return ret;
 }
 
 static int panel_lvds_remove(struct platform_device *pdev)
@@ -284,9 +273,6 @@ static int panel_lvds_remove(struct platform_device *pdev)
 
        panel_lvds_disable(&lvds->panel);
 
-       if (lvds->backlight)
-               put_device(&lvds->backlight->dev);
-
        return 0;
 }
 
index 299b217c83e186493e20466b5ebfae0f6caa916f..c4bc7fa85fadb9c5fd2d7e262b5b82d36059e440 100644 (file)
@@ -205,9 +205,8 @@ static int nl8048_probe(struct spi_device *spi)
        if (ret < 0)
                return ret;
 
-       drm_panel_init(&lcd->panel);
-       lcd->panel.dev = &lcd->spi->dev;
-       lcd->panel.funcs = &nl8048_funcs;
+       drm_panel_init(&lcd->panel, &lcd->spi->dev, &nl8048_funcs,
+                      DRM_MODE_CONNECTOR_DPI);
 
        return drm_panel_add(&lcd->panel);
 }
index 2ad1063b068d549c952b8af18190434b72ad00e6..60ccedce530c29a6e84a62159c3104cec4e83aaf 100644 (file)
@@ -292,9 +292,8 @@ static int nt39016_probe(struct spi_device *spi)
                return err;
        }
 
-       drm_panel_init(&panel->drm_panel);
-       panel->drm_panel.dev = dev;
-       panel->drm_panel.funcs = &nt39016_funcs;
+       drm_panel_init(&panel->drm_panel, dev, &nt39016_funcs,
+                      DRM_MODE_CONNECTOR_DPI);
 
        err = drm_panel_add(&panel->drm_panel);
        if (err < 0) {
index 2bae1db3ff344ba491be710edf0681d73090b531..f2a72ee6ee07dd5d135c58997a7a7773c593520a 100644 (file)
@@ -288,9 +288,8 @@ static int lcd_olinuxino_probe(struct i2c_client *client,
        if (IS_ERR(lcd->backlight))
                return PTR_ERR(lcd->backlight);
 
-       drm_panel_init(&lcd->panel);
-       lcd->panel.dev = dev;
-       lcd->panel.funcs = &lcd_olinuxino_funcs;
+       drm_panel_init(&lcd->panel, dev, &lcd_olinuxino_funcs,
+                      DRM_MODE_CONNECTOR_DPI);
 
        return drm_panel_add(&lcd->panel);
 }
index c7b48df8869a1d6e28a9e174076af0f709525934..bf1f928b215fc36855b2b8c3eafca2988a31debc 100644 (file)
@@ -455,9 +455,8 @@ static int otm8009a_probe(struct mipi_dsi_device *dsi)
        dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST |
                          MIPI_DSI_MODE_LPM;
 
-       drm_panel_init(&ctx->panel);
-       ctx->panel.dev = dev;
-       ctx->panel.funcs = &otm8009a_drm_funcs;
+       drm_panel_init(&ctx->panel, dev, &otm8009a_drm_funcs,
+                      DRM_MODE_CONNECTOR_DSI);
 
        ctx->bl_dev = devm_backlight_device_register(dev, dev_name(dev),
                                                     dsi->host->dev, ctx,
index e0e20ecff916db58f3e86a18f440fb75f74e1dd1..2b40913899d88fb4202eafa13c68d1f04fb6eeff 100644 (file)
@@ -166,9 +166,8 @@ static int osd101t2587_panel_add(struct osd101t2587_panel *osd101t2587)
        if (IS_ERR(osd101t2587->backlight))
                return PTR_ERR(osd101t2587->backlight);
 
-       drm_panel_init(&osd101t2587->base);
-       osd101t2587->base.funcs = &osd101t2587_panel_funcs;
-       osd101t2587->base.dev = &osd101t2587->dsi->dev;
+       drm_panel_init(&osd101t2587->base, &osd101t2587->dsi->dev,
+                      &osd101t2587_panel_funcs, DRM_MODE_CONNECTOR_DSI);
 
        return drm_panel_add(&osd101t2587->base);
 }
index 3dff0b3f73c233311ab5606ab73c63f5620eed3d..664605071d34270999507260fc6eaa559f4d23e7 100644 (file)
@@ -223,9 +223,8 @@ static int wuxga_nt_panel_add(struct wuxga_nt_panel *wuxga_nt)
                        return -EPROBE_DEFER;
        }
 
-       drm_panel_init(&wuxga_nt->base);
-       wuxga_nt->base.funcs = &wuxga_nt_panel_funcs;
-       wuxga_nt->base.dev = &wuxga_nt->dsi->dev;
+       drm_panel_init(&wuxga_nt->base, &wuxga_nt->dsi->dev,
+                      &wuxga_nt_panel_funcs, DRM_MODE_CONNECTOR_DSI);
 
        ret = drm_panel_add(&wuxga_nt->base);
        if (ret < 0)
index b5b14aa059ea722195aa4e55dab8c969475e4f7b..09824e92fc781cc905d0cfe3da6e0ceffa399938 100644 (file)
@@ -426,8 +426,8 @@ static int rpi_touchscreen_probe(struct i2c_client *i2c,
                return PTR_ERR(ts->dsi);
        }
 
-       ts->base.dev = dev;
-       ts->base.funcs = &rpi_touchscreen_funcs;
+       drm_panel_init(&ts->base, dev, &rpi_touchscreen_funcs,
+                      DRM_MODE_CONNECTOR_DSI);
 
        /* This appears last, as it's what will unblock the DSI host
         * driver's component bind function.
index 6a5d37006103e53ed12273ed2f49665a913266df..fd67fc6185c4ff654a0529877ab9a7cca0e27561 100644 (file)
@@ -606,9 +606,8 @@ static int rad_panel_probe(struct mipi_dsi_device *dsi)
        if (ret)
                return ret;
 
-       drm_panel_init(&panel->panel);
-       panel->panel.funcs = &rad_panel_funcs;
-       panel->panel.dev = dev;
+       drm_panel_init(&panel->panel, dev, &rad_panel_funcs,
+                      DRM_MODE_CONNECTOR_DSI);
        dev_set_drvdata(dev, panel);
 
        ret = drm_panel_add(&panel->panel);
index ba889625ad4353f1dd6b18fa15b6fde159bc0c93..994e855721f4b4a80cb367a0e38b17664903b533 100644 (file)
@@ -404,9 +404,8 @@ static int rm68200_probe(struct mipi_dsi_device *dsi)
        dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST |
                          MIPI_DSI_MODE_LPM;
 
-       drm_panel_init(&ctx->panel);
-       ctx->panel.dev = dev;
-       ctx->panel.funcs = &rm68200_drm_funcs;
+       drm_panel_init(&ctx->panel, dev, &rm68200_drm_funcs,
+                      DRM_MODE_CONNECTOR_DSI);
 
        drm_panel_add(&ctx->panel);
 
index b9109922397ff6e2a9fdf479f4600ff3696be1cf..31234b79d3b1ab2b617b5c49f5196e76c8dd8bab 100644 (file)
@@ -343,9 +343,8 @@ static int jh057n_probe(struct mipi_dsi_device *dsi)
                return ret;
        }
 
-       drm_panel_init(&ctx->panel);
-       ctx->panel.dev = dev;
-       ctx->panel.funcs = &jh057n_drm_funcs;
+       drm_panel_init(&ctx->panel, dev, &jh057n_drm_funcs,
+                      DRM_MODE_CONNECTOR_DSI);
 
        drm_panel_add(&ctx->panel);
 
index 3c15764f0c039c8261820a881e66a817ab94d71d..170a5cda21b931c1de60c8719f7f12aa8060db72 100644 (file)
@@ -173,9 +173,8 @@ static int rb070d30_panel_dsi_probe(struct mipi_dsi_device *dsi)
        mipi_dsi_set_drvdata(dsi, ctx);
        ctx->dsi = dsi;
 
-       drm_panel_init(&ctx->panel);
-       ctx->panel.dev = &dsi->dev;
-       ctx->panel.funcs = &rb070d30_panel_funcs;
+       drm_panel_init(&ctx->panel, &dsi->dev, &rb070d30_panel_funcs,
+                      DRM_MODE_CONNECTOR_DSI);
 
        ctx->gpios.reset = devm_gpiod_get(&dsi->dev, "reset", GPIOD_OUT_LOW);
        if (IS_ERR(ctx->gpios.reset)) {
index 3be902dcedc02254788c2060cf3c2515a5c2ee87..250809ba37c7ea51e58b29c545b76bf493a87ae8 100644 (file)
@@ -351,9 +351,8 @@ static int ld9040_probe(struct spi_device *spi)
                return ret;
        }
 
-       drm_panel_init(&ctx->panel);
-       ctx->panel.dev = dev;
-       ctx->panel.funcs = &ld9040_drm_funcs;
+       drm_panel_init(&ctx->panel, dev, &ld9040_drm_funcs,
+                      DRM_MODE_CONNECTOR_DPI);
 
        return drm_panel_add(&ctx->panel);
 }
index f75bef24e0504664c96b9c0d2534b94554baad4d..e3a0397e953ee6715c972fec61404c17e9f9e07c 100644 (file)
@@ -215,9 +215,8 @@ static int s6d16d0_probe(struct mipi_dsi_device *dsi)
                return ret;
        }
 
-       drm_panel_init(&s6->panel);
-       s6->panel.dev = dev;
-       s6->panel.funcs = &s6d16d0_drm_funcs;
+       drm_panel_init(&s6->panel, dev, &s6d16d0_drm_funcs,
+                      DRM_MODE_CONNECTOR_DSI);
 
        ret = drm_panel_add(&s6->panel);
        if (ret < 0)
index b923de23ed654fe7c6ce9d09fd96557f7366836b..938ab72c55404de610eb037109659f9c44041261 100644 (file)
@@ -732,9 +732,8 @@ static int s6e3ha2_probe(struct mipi_dsi_device *dsi)
        ctx->bl_dev->props.brightness = S6E3HA2_DEFAULT_BRIGHTNESS;
        ctx->bl_dev->props.power = FB_BLANK_POWERDOWN;
 
-       drm_panel_init(&ctx->panel);
-       ctx->panel.dev = dev;
-       ctx->panel.funcs = &s6e3ha2_drm_funcs;
+       drm_panel_init(&ctx->panel, dev, &s6e3ha2_drm_funcs,
+                      DRM_MODE_CONNECTOR_DSI);
 
        ret = drm_panel_add(&ctx->panel);
        if (ret < 0)
index cd90fa700c49331e7201cb1c8042d48599a75d6f..a60635e9226da89ec51498c092b6ccfe8c6c86c2 100644 (file)
@@ -466,9 +466,8 @@ static int s6e63j0x03_probe(struct mipi_dsi_device *dsi)
                return PTR_ERR(ctx->reset_gpio);
        }
 
-       drm_panel_init(&ctx->panel);
-       ctx->panel.dev = dev;
-       ctx->panel.funcs = &s6e63j0x03_funcs;
+       drm_panel_init(&ctx->panel, dev, &s6e63j0x03_funcs,
+                      DRM_MODE_CONNECTOR_DSI);
 
        ctx->bl_dev = backlight_device_register("s6e63j0x03", dev, ctx,
                                                &s6e63j0x03_bl_ops, NULL);
index 142d395ea51295c40a1e4b77087894e84c92e822..ba01af0b14fd3ff3345ba57ae5d9d0fd4e7e4422 100644 (file)
@@ -473,9 +473,8 @@ static int s6e63m0_probe(struct spi_device *spi)
                return ret;
        }
 
-       drm_panel_init(&ctx->panel);
-       ctx->panel.dev = dev;
-       ctx->panel.funcs = &s6e63m0_drm_funcs;
+       drm_panel_init(&ctx->panel, dev, &s6e63m0_drm_funcs,
+                      DRM_MODE_CONNECTOR_DPI);
 
        ret = s6e63m0_backlight_register(ctx);
        if (ret < 0)
index 81858267723ad0ce5888ebb90f7f50958ebe03c5..dbced650120456749734140350b20ccc7cb4e0c0 100644 (file)
@@ -1017,9 +1017,8 @@ static int s6e8aa0_probe(struct mipi_dsi_device *dsi)
 
        ctx->brightness = GAMMA_LEVEL_NUM - 1;
 
-       drm_panel_init(&ctx->panel);
-       ctx->panel.dev = dev;
-       ctx->panel.funcs = &s6e8aa0_drm_funcs;
+       drm_panel_init(&ctx->panel, dev, &s6e8aa0_drm_funcs,
+                      DRM_MODE_CONNECTOR_DSI);
 
        ret = drm_panel_add(&ctx->panel);
        if (ret < 0)
index 18b22b1294fbc582f47483029022f71df2078c5f..b3619ba443bd2576056215c089b766dd89d8678d 100644 (file)
@@ -274,9 +274,8 @@ static int seiko_panel_probe(struct device *dev,
                        return -EPROBE_DEFER;
        }
 
-       drm_panel_init(&panel->base);
-       panel->base.dev = dev;
-       panel->base.funcs = &seiko_panel_funcs;
+       drm_panel_init(&panel->base, dev, &seiko_panel_funcs,
+                      DRM_MODE_CONNECTOR_DPI);
 
        err = drm_panel_add(&panel->base);
        if (err < 0)
index e910b4ad13104cc00f086fdeed0e7aeb8a99d88d..5e136c3ba18500571433ac37754e72b051d75629 100644 (file)
@@ -329,9 +329,8 @@ static int sharp_panel_add(struct sharp_panel *sharp)
        if (IS_ERR(sharp->backlight))
                return PTR_ERR(sharp->backlight);
 
-       drm_panel_init(&sharp->base);
-       sharp->base.funcs = &sharp_panel_funcs;
-       sharp->base.dev = &sharp->link1->dev;
+       drm_panel_init(&sharp->base, &sharp->link1->dev, &sharp_panel_funcs,
+                      DRM_MODE_CONNECTOR_DSI);
 
        return drm_panel_add(&sharp->base);
 }
index 46cd9a2501298222edaf9dac935e7c9e6a6aed1d..eeab7998c7de4ff62d2253b0885a1dd9846d9c18 100644 (file)
@@ -185,9 +185,8 @@ static int ls037v7dw01_probe(struct platform_device *pdev)
                return PTR_ERR(lcd->ud_gpio);
        }
 
-       drm_panel_init(&lcd->panel);
-       lcd->panel.dev = &pdev->dev;
-       lcd->panel.funcs = &ls037v7dw01_funcs;
+       drm_panel_init(&lcd->panel, &pdev->dev, &ls037v7dw01_funcs,
+                      DRM_MODE_CONNECTOR_DPI);
 
        return drm_panel_add(&lcd->panel);
 }
index c39abde9f9f10cae1df13b33a1c84a339408c128..b963ba4ab5898f3c423744f2a3889b91a1d8392d 100644 (file)
@@ -264,9 +264,8 @@ static int sharp_nt_panel_add(struct sharp_nt_panel *sharp_nt)
        if (IS_ERR(sharp_nt->backlight))
                return PTR_ERR(sharp_nt->backlight);
 
-       drm_panel_init(&sharp_nt->base);
-       sharp_nt->base.funcs = &sharp_nt_panel_funcs;
-       sharp_nt->base.dev = &sharp_nt->dsi->dev;
+       drm_panel_init(&sharp_nt->base, &sharp_nt->dsi->dev,
+                      &sharp_nt_panel_funcs, DRM_MODE_CONNECTOR_DSI);
 
        return drm_panel_add(&sharp_nt->base);
 }
index 28fa6ba7b767394d2fd918079f164fca08941ff8..5d487686d25c510cb55fede3eb624b284e273b90 100644 (file)
@@ -94,6 +94,7 @@ struct panel_desc {
 
        u32 bus_format;
        u32 bus_flags;
+       int connector_type;
 };
 
 struct panel_simple {
@@ -464,9 +465,8 @@ static int panel_simple_probe(struct device *dev, const struct panel_desc *desc)
        if (!of_get_display_timing(dev->of_node, "panel-timing", &dt))
                panel_simple_parse_panel_timing_node(dev, panel, &dt);
 
-       drm_panel_init(&panel->base);
-       panel->base.dev = dev;
-       panel->base.funcs = &panel_simple_funcs;
+       drm_panel_init(&panel->base, dev, &panel_simple_funcs,
+                      desc->connector_type);
 
        err = drm_panel_add(&panel->base);
        if (err < 0)
@@ -833,6 +833,7 @@ static const struct panel_desc auo_g133han01 = {
                .unprepare = 1000,
        },
        .bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA,
+       .connector_type = DRM_MODE_CONNECTOR_LVDS,
 };
 
 static const struct display_timing auo_g185han01_timings = {
@@ -862,6 +863,7 @@ static const struct panel_desc auo_g185han01 = {
                .unprepare = 1000,
        },
        .bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG,
+       .connector_type = DRM_MODE_CONNECTOR_LVDS,
 };
 
 static const struct display_timing auo_p320hvn03_timings = {
@@ -890,6 +892,7 @@ static const struct panel_desc auo_p320hvn03 = {
                .unprepare = 500,
        },
        .bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG,
+       .connector_type = DRM_MODE_CONNECTOR_LVDS,
 };
 
 static const struct drm_display_mode auo_t215hvn01_mode = {
@@ -1205,6 +1208,7 @@ static const struct panel_desc dlc_dlc0700yzg_1 = {
                .disable = 200,
        },
        .bus_format = MEDIA_BUS_FMT_RGB666_1X7X3_SPWG,
+       .connector_type = DRM_MODE_CONNECTOR_LVDS,
 };
 
 static const struct display_timing dlc_dlc1010gig_timing = {
@@ -1235,6 +1239,7 @@ static const struct panel_desc dlc_dlc1010gig = {
                .unprepare = 60,
        },
        .bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG,
+       .connector_type = DRM_MODE_CONNECTOR_LVDS,
 };
 
 static const struct drm_display_mode edt_et035012dm6_mode = {
@@ -1501,6 +1506,7 @@ static const struct panel_desc hannstar_hsd070pww1 = {
                .height = 94,
        },
        .bus_format = MEDIA_BUS_FMT_RGB666_1X7X3_SPWG,
+       .connector_type = DRM_MODE_CONNECTOR_LVDS,
 };
 
 static const struct display_timing hannstar_hsd100pxn1_timing = {
@@ -1525,6 +1531,7 @@ static const struct panel_desc hannstar_hsd100pxn1 = {
                .height = 152,
        },
        .bus_format = MEDIA_BUS_FMT_RGB666_1X7X3_SPWG,
+       .connector_type = DRM_MODE_CONNECTOR_LVDS,
 };
 
 static const struct drm_display_mode hitachi_tx23d38vm0caa_mode = {
@@ -1631,6 +1638,7 @@ static const struct panel_desc innolux_g070y2_l01 = {
                .unprepare = 800,
        },
        .bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG,
+       .connector_type = DRM_MODE_CONNECTOR_LVDS,
 };
 
 static const struct display_timing innolux_g101ice_l01_timing = {
@@ -1659,6 +1667,7 @@ static const struct panel_desc innolux_g101ice_l01 = {
                .disable = 200,
        },
        .bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG,
+       .connector_type = DRM_MODE_CONNECTOR_LVDS,
 };
 
 static const struct display_timing innolux_g121i1_l01_timing = {
@@ -1686,6 +1695,7 @@ static const struct panel_desc innolux_g121i1_l01 = {
                .disable = 20,
        },
        .bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG,
+       .connector_type = DRM_MODE_CONNECTOR_LVDS,
 };
 
 static const struct drm_display_mode innolux_g121x1_l03_mode = {
@@ -1869,6 +1879,7 @@ static const struct panel_desc koe_tx31d200vm0baa = {
                .height = 109,
        },
        .bus_format = MEDIA_BUS_FMT_RGB666_1X7X3_SPWG,
+       .connector_type = DRM_MODE_CONNECTOR_LVDS,
 };
 
 static const struct display_timing kyo_tcg121xglp_timing = {
@@ -1893,6 +1904,7 @@ static const struct panel_desc kyo_tcg121xglp = {
                .height = 184,
        },
        .bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG,
+       .connector_type = DRM_MODE_CONNECTOR_LVDS,
 };
 
 static const struct drm_display_mode lemaker_bl035_rgb_002_mode = {
@@ -1941,6 +1953,7 @@ static const struct panel_desc lg_lb070wv8 = {
                .height = 91,
        },
        .bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG,
+       .connector_type = DRM_MODE_CONNECTOR_LVDS,
 };
 
 static const struct drm_display_mode lg_lp079qx1_sp0v_mode = {
@@ -2063,6 +2076,7 @@ static const struct panel_desc mitsubishi_aa070mc01 = {
                .disable = 400,
        },
        .bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG,
+       .connector_type = DRM_MODE_CONNECTOR_LVDS,
        .bus_flags = DRM_BUS_FLAG_DE_HIGH,
 };
 
@@ -2091,6 +2105,7 @@ static const struct panel_desc nec_nl12880bc20_05 = {
                .disable = 50,
        },
        .bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG,
+       .connector_type = DRM_MODE_CONNECTOR_LVDS,
 };
 
 static const struct drm_display_mode nec_nl4827hc19_05b_mode = {
@@ -2193,6 +2208,7 @@ static const struct panel_desc nlt_nl192108ac18_02d = {
                .unprepare = 500,
        },
        .bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG,
+       .connector_type = DRM_MODE_CONNECTOR_LVDS,
 };
 
 static const struct drm_display_mode nvd_9128_mode = {
@@ -2216,6 +2232,7 @@ static const struct panel_desc nvd_9128 = {
                .height = 88,
        },
        .bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG,
+       .connector_type = DRM_MODE_CONNECTOR_LVDS,
 };
 
 static const struct display_timing okaya_rs800480t_7x0gp_timing = {
@@ -2381,6 +2398,7 @@ static const struct panel_desc osddisplays_osd070t1718_19ts = {
        },
        .bus_format = MEDIA_BUS_FMT_RGB888_1X24,
        .bus_flags = DRM_BUS_FLAG_DE_HIGH | DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE,
+       .connector_type = DRM_MODE_CONNECTOR_DPI,
 };
 
 static const struct drm_display_mode pda_91_00156_a0_mode = {
@@ -2628,6 +2646,7 @@ static const struct panel_desc sharp_lq101k1ly04 = {
                .height = 136,
        },
        .bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA,
+       .connector_type = DRM_MODE_CONNECTOR_LVDS,
 };
 
 static const struct display_timing sharp_lq123p1jx31_timing = {
@@ -2807,6 +2826,7 @@ static const struct panel_desc tianma_tm070jdhg30 = {
                .height = 95,
        },
        .bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG,
+       .connector_type = DRM_MODE_CONNECTOR_LVDS,
 };
 
 static const struct display_timing tianma_tm070rvhg71_timing = {
@@ -2831,6 +2851,7 @@ static const struct panel_desc tianma_tm070rvhg71 = {
                .height = 86,
        },
        .bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG,
+       .connector_type = DRM_MODE_CONNECTOR_LVDS,
 };
 
 static const struct drm_display_mode ti_nspire_cx_lcd_mode[] = {
@@ -2913,6 +2934,7 @@ static const struct panel_desc toshiba_lt089ac29000 = {
        },
        .bus_format = MEDIA_BUS_FMT_RGB888_1X24,
        .bus_flags = DRM_BUS_FLAG_DE_HIGH | DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE,
+       .connector_type = DRM_MODE_CONNECTOR_LVDS,
 };
 
 static const struct drm_display_mode tpk_f07a_0102_mode = {
@@ -2983,6 +3005,7 @@ static const struct panel_desc urt_umsh_8596md_lvds = {
                .height = 91,
        },
        .bus_format = MEDIA_BUS_FMT_RGB666_1X7X3_SPWG,
+       .connector_type = DRM_MODE_CONNECTOR_LVDS,
 };
 
 static const struct panel_desc urt_umsh_8596md_parallel = {
index 09c5d9a6f9fa8a169e5e16f54b68fb757eeecf8c..ee3f23f45755f090709c97f8acdf74ce8be4cfb8 100644 (file)
@@ -369,7 +369,8 @@ static int st7701_dsi_probe(struct mipi_dsi_device *dsi)
        if (IS_ERR(st7701->backlight))
                return PTR_ERR(st7701->backlight);
 
-       drm_panel_init(&st7701->panel);
+       drm_panel_init(&st7701->panel, &dsi->dev, &st7701_funcs,
+                      DRM_MODE_CONNECTOR_DSI);
 
        /**
         * Once sleep out has been issued, ST7701 IC required to wait 120ms
@@ -381,8 +382,6 @@ static int st7701_dsi_probe(struct mipi_dsi_device *dsi)
         * ts8550b and there is no valid documentation for that.
         */
        st7701->sleep_delay = 120 + desc->panel_sleep_delay;
-       st7701->panel.funcs = &st7701_funcs;
-       st7701->panel.dev = &dsi->dev;
 
        ret = drm_panel_add(&st7701->panel);
        if (ret < 0)
index 5e3e92ea9ea6988595445c806d427414a53ffcbb..108a85bb6667238d0e5c0448e855f532b75b3dd0 100644 (file)
@@ -381,8 +381,8 @@ static int st7789v_probe(struct spi_device *spi)
        spi_set_drvdata(spi, ctx);
        ctx->spi = spi;
 
-       ctx->panel.dev = &spi->dev;
-       ctx->panel.funcs = &st7789v_drm_funcs;
+       drm_panel_init(&ctx->panel, &spi->dev, &st7789v_drm_funcs,
+                      DRM_MODE_CONNECTOR_DPI);
 
        ctx->power = devm_regulator_get(&spi->dev, "power");
        if (IS_ERR(ctx->power))
index 305259b5876701dc9db0aab4e472e16306ec3a02..6f5ce5867ff9606131b3752ec467dc81c95d106f 100644 (file)
@@ -648,9 +648,8 @@ static int acx565akm_probe(struct spi_device *spi)
                        return ret;
        }
 
-       drm_panel_init(&lcd->panel);
-       lcd->panel.dev = &lcd->spi->dev;
-       lcd->panel.funcs = &acx565akm_funcs;
+       drm_panel_init(&lcd->panel, &lcd->spi->dev, &acx565akm_funcs,
+                      DRM_MODE_CONNECTOR_DPI);
 
        ret = drm_panel_add(&lcd->panel);
        if (ret < 0) {
index d7b2e34626efe81435a632711fb8b5dc2e1b3d01..1d08d03f509d51cf4e411d7f1ea012ea99fde4d3 100644 (file)
@@ -347,9 +347,8 @@ static int td028ttec1_probe(struct spi_device *spi)
                return ret;
        }
 
-       drm_panel_init(&lcd->panel);
-       lcd->panel.dev = &lcd->spi->dev;
-       lcd->panel.funcs = &td028ttec1_funcs;
+       drm_panel_init(&lcd->panel, &lcd->spi->dev, &td028ttec1_funcs,
+                      DRM_MODE_CONNECTOR_DPI);
 
        return drm_panel_add(&lcd->panel);
 }
index 84370562910ff5dfcd52dd1896d227464db2d9bb..416aebd23b6ab468d8f83aa83ef6eff326a4e92e 100644 (file)
@@ -458,9 +458,8 @@ static int td043mtea1_probe(struct spi_device *spi)
                return ret;
        }
 
-       drm_panel_init(&lcd->panel);
-       lcd->panel.dev = &lcd->spi->dev;
-       lcd->panel.funcs = &td043mtea1_funcs;
+       drm_panel_init(&lcd->panel, &lcd->spi->dev, &td043mtea1_funcs,
+                      DRM_MODE_CONNECTOR_DPI);
 
        ret = drm_panel_add(&lcd->panel);
        if (ret < 0) {
index 71591e5f59383f9c1ae9e3bddec78c2f234314bc..1a5418ae2ccf30ba40fb4716d65c4fe4a03faae2 100644 (file)
@@ -457,9 +457,8 @@ static int tpg110_probe(struct spi_device *spi)
        if (ret)
                return ret;
 
-       drm_panel_init(&tpg->panel);
-       tpg->panel.dev = dev;
-       tpg->panel.funcs = &tpg110_drm_funcs;
+       drm_panel_init(&tpg->panel, dev, &tpg110_drm_funcs,
+                      DRM_MODE_CONNECTOR_DPI);
        spi_set_drvdata(spi, tpg);
 
        return drm_panel_add(&tpg->panel);
index 77e1311b7c6921a51596c982a28c870895a34976..0feea2456e14b66bf0370e6e0edd9140528a6b43 100644 (file)
@@ -518,9 +518,8 @@ static int truly_nt35597_panel_add(struct truly_nt35597 *ctx)
        /* dual port */
        gpiod_set_value(ctx->mode_gpio, 0);
 
-       drm_panel_init(&ctx->panel);
-       ctx->panel.dev = dev;
-       ctx->panel.funcs = &truly_nt35597_drm_funcs;
+       drm_panel_init(&ctx->panel, dev, &truly_nt35597_drm_funcs,
+                      DRM_MODE_CONNECTOR_DSI);
        drm_panel_add(&ctx->panel);
 
        return 0;
index 12ff77dacc9541fb3d7a1af3d9d3f0876f59d8b8..c1eb8cfe6aeb396c9e2176a81869724577bea2df 100644 (file)
@@ -53,8 +53,10 @@ static int panfrost_devfreq_target(struct device *dev, unsigned long *freq,
        if (err) {
                dev_err(dev, "Cannot set frequency %lu (%d)\n", target_rate,
                        err);
-               regulator_set_voltage(pfdev->regulator, pfdev->devfreq.cur_volt,
-                                     pfdev->devfreq.cur_volt);
+               if (pfdev->regulator)
+                       regulator_set_voltage(pfdev->regulator,
+                                             pfdev->devfreq.cur_volt,
+                                             pfdev->devfreq.cur_volt);
                return err;
        }
 
index cec6dcdadb5c3129c14254f93ad5187bc48c84db..8e59d765bf19f1bd71af569ce5811c17cafc49a2 100644 (file)
  * to care about.
  */
 enum panfrost_hw_issue {
+       /* Need way to guarantee that all previously-translated memory accesses
+        * are commited */
        HW_ISSUE_6367,
+
+       /* On job complete with non-done the cache is not flushed */
        HW_ISSUE_6787,
+
+       /* Write of PRFCNT_CONFIG_MODE_MANUAL to PRFCNT_CONFIG causes a
+        * instrumentation dump if PRFCNT_TILER_EN is enabled */
        HW_ISSUE_8186,
+
+       /* TIB: Reports faults from a vtile which has not yet been allocated */
        HW_ISSUE_8245,
+
+       /* uTLB deadlock could occur when writing to an invalid page at the
+        * same time as access to a valid page in the same uTLB cache line ( ==
+        * 4 PTEs == 16K block of mapping) */
        HW_ISSUE_8316,
+
+       /* HT: TERMINATE for RUN command ignored if previous LOAD_DESCRIPTOR is
+        * still executing */
        HW_ISSUE_8394,
+
+       /* CSE: Sends a TERMINATED response for a task that should not be
+        * terminated */
        HW_ISSUE_8401,
+
+       /* Repeatedly Soft-stopping a job chain consisting of (Vertex Shader,
+        * Cache Flush, Tiler) jobs causes DATA_INVALID_FAULT on tiler job. */
        HW_ISSUE_8408,
+
+       /* Disable the Pause Buffer in the LS pipe. */
        HW_ISSUE_8443,
+
+       /* Change in RMUs in use causes problems related with the core's SDC */
        HW_ISSUE_8987,
+
+       /* Compute endpoint has a 4-deep queue of tasks, meaning a soft stop
+        * won't complete until all 4 tasks have completed */
        HW_ISSUE_9435,
+
+       /* HT: Tiler returns TERMINATED for non-terminated command */
        HW_ISSUE_9510,
+
+       /* Occasionally the GPU will issue multiple page faults for the same
+        * address before the MMU page table has been read by the GPU */
        HW_ISSUE_9630,
+
+       /* RA DCD load request to SDC returns invalid load ignore causing
+        * colour buffer mismatch */
        HW_ISSUE_10327,
+
+       /* MMU TLB invalidation hazards */
        HW_ISSUE_10649,
+
+       /* Missing cache flush in multi core-group configuration */
        HW_ISSUE_10676,
+
+       /* Chicken bit on T72X for a hardware workaround in compiler */
        HW_ISSUE_10797,
+
+       /* Soft-stopping fragment jobs might fail with TILE_RANGE_FAULT */
        HW_ISSUE_10817,
+
+       /* Intermittent missing interrupt on job completion */
        HW_ISSUE_10883,
+
+       /* Soft-stopping fragment jobs might fail with TILE_RANGE_ERROR
+        * (similar to issue 10817) and can use #10817 workaround */
        HW_ISSUE_10959,
+
+       /* Soft-stopped fragment shader job can restart with out-of-bound
+        * restart index */
        HW_ISSUE_10969,
+
+       /* Race condition can cause tile list corruption */
        HW_ISSUE_11020,
+
+       /* Write buffer can cause tile list corruption */
        HW_ISSUE_11024,
+
+       /* Pause buffer can cause a fragment job hang */
        HW_ISSUE_11035,
+
+       /* Dynamic Core Scaling not supported due to errata */
        HW_ISSUE_11056,
+
+       /* Clear encoder state for a hard stopped fragment job which is AFBC
+        * encoded by soft resetting the GPU. Only for T76X r0p0, r0p1 and
+        * r0p1_50rel0 */
        HW_ISSUE_T76X_3542,
+
+       /* Keep tiler module clock on to prevent GPU stall */
        HW_ISSUE_T76X_3953,
+
+       /* Must ensure L2 is not transitioning when we reset. Workaround with a
+        * busy wait until L2 completes transition; ensure there is a maximum
+        * loop count as she may never complete her transition. (On chips
+        * without this errata, it's totally okay if L2 transitions.) */
        HW_ISSUE_TMIX_8463,
+
+       /* Don't set SC_LS_ATTR_CHECK_DISABLE/SC_LS_ALLOW_ATTR_TYPES */
        GPUCORE_1619,
+
+       /* When a hard-stop follows close after a soft-stop, the completion
+        * code for the terminated job may be incorrectly set to STOPPED */
        HW_ISSUE_TMIX_8438,
+
+       /* "Protected mode" is buggy on Mali-G31 some Bifrost chips, so the
+        * kernel must fiddle with L2 caches to prevent data leakage */
        HW_ISSUE_TGOX_R1_1234,
+
        HW_ISSUE_END
 };
 
index 276b53473a84eb8c6f2e3c33fae00a5deb307196..63dfcda041474704ea2e950052c7733f999fb754 100644 (file)
@@ -150,8 +150,8 @@ static int pl111_modeset_init(struct drm_device *dev)
                return -EPROBE_DEFER;
 
        if (panel) {
-               bridge = drm_panel_bridge_add(panel,
-                                             DRM_MODE_CONNECTOR_Unknown);
+               bridge = drm_panel_bridge_add_typed(panel,
+                                                   DRM_MODE_CONNECTOR_Unknown);
                if (IS_ERR(bridge)) {
                        ret = PTR_ERR(bridge);
                        goto out_config;
index 265bfe9f8016f78d1ac928d1ec9081f135306d7e..483b4c57554a6155ffd5f0e82cc16d685b69b94c 100644 (file)
@@ -88,7 +88,7 @@ qxl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        if (ret)
                goto free_dev;
 
-       ret = drm_fb_helper_remove_conflicting_pci_framebuffers(pdev, 0, "qxl");
+       ret = drm_fb_helper_remove_conflicting_pci_framebuffers(pdev, "qxl");
        if (ret)
                goto disable_pci;
 
@@ -276,16 +276,8 @@ static struct drm_driver qxl_driver = {
 #endif
        .prime_handle_to_fd = drm_gem_prime_handle_to_fd,
        .prime_fd_to_handle = drm_gem_prime_fd_to_handle,
-       .gem_prime_pin = qxl_gem_prime_pin,
-       .gem_prime_unpin = qxl_gem_prime_unpin,
-       .gem_prime_get_sg_table = qxl_gem_prime_get_sg_table,
        .gem_prime_import_sg_table = qxl_gem_prime_import_sg_table,
-       .gem_prime_vmap = qxl_gem_prime_vmap,
-       .gem_prime_vunmap = qxl_gem_prime_vunmap,
        .gem_prime_mmap = qxl_gem_prime_mmap,
-       .gem_free_object_unlocked = qxl_gem_object_free,
-       .gem_open_object = qxl_gem_object_open,
-       .gem_close_object = qxl_gem_object_close,
        .fops = &qxl_fops,
        .ioctls = qxl_ioctls,
        .irq_handler = qxl_irq_handler,
index 9e034c5fa87dc6a8773b82cab79b032fce40c514..d4051409ce64f54fe166a03681a5e51a5df172ea 100644 (file)
@@ -38,6 +38,7 @@
 #include <drm/drm_crtc.h>
 #include <drm/drm_encoder.h>
 #include <drm/drm_fb_helper.h>
+#include <drm/drm_gem_ttm_helper.h>
 #include <drm/drm_ioctl.h>
 #include <drm/drm_gem.h>
 #include <drm/qxl_drm.h>
index 548dfe6f3b2685028054ca576971b78ce0ec929f..c013c516f5619cb4da90a0302f31c3d3a4076739 100644 (file)
@@ -77,6 +77,18 @@ void qxl_ttm_placement_from_domain(struct qxl_bo *qbo, u32 domain, bool pinned)
        }
 }
 
+static const struct drm_gem_object_funcs qxl_object_funcs = {
+       .free = qxl_gem_object_free,
+       .open = qxl_gem_object_open,
+       .close = qxl_gem_object_close,
+       .pin = qxl_gem_prime_pin,
+       .unpin = qxl_gem_prime_unpin,
+       .get_sg_table = qxl_gem_prime_get_sg_table,
+       .vmap = qxl_gem_prime_vmap,
+       .vunmap = qxl_gem_prime_vunmap,
+       .print_info = drm_gem_ttm_print_info,
+};
+
 int qxl_bo_create(struct qxl_device *qdev,
                  unsigned long size, bool kernel, bool pinned, u32 domain,
                  struct qxl_surface *surf,
@@ -100,6 +112,7 @@ int qxl_bo_create(struct qxl_device *qdev,
                kfree(bo);
                return r;
        }
+       bo->tbo.base.funcs = &qxl_object_funcs;
        bo->type = domain;
        bo->pin_count = pinned ? 1 : 0;
        bo->surface_id = 0;
index 9b24514c75aad35e871cd03aa95c8ee5a4b39215..cbc6c2ba8630fd1f02212695575c9c79b39e40a1 100644 (file)
@@ -325,6 +325,7 @@ int qxl_ttm_init(struct qxl_device *qdev)
        r = ttm_bo_device_init(&qdev->mman.bdev,
                               &qxl_bo_driver,
                               qdev->ddev.anon_inode->i_mapping,
+                              qdev->ddev.vma_offset_manager,
                               false);
        if (r) {
                DRM_ERROR("failed initializing buffer object driver(%d).\n", r);
index b684cd719612b41bb90b39f842150d66e42bf453..c07427d3c19995f76dbd153a65e6b8283ab111de 100644 (file)
@@ -249,11 +249,10 @@ radeon_connector_update_scratch_regs(struct drm_connector *connector, enum drm_c
        struct drm_encoder *encoder;
        const struct drm_connector_helper_funcs *connector_funcs = connector->helper_private;
        bool connected;
-       int i;
 
        best_encoder = connector_funcs->best_encoder(connector);
 
-       drm_connector_for_each_possible_encoder(connector, encoder, i) {
+       drm_connector_for_each_possible_encoder(connector, encoder) {
                if ((encoder == best_encoder) && (status == connector_status_connected))
                        connected = true;
                else
@@ -269,9 +268,8 @@ radeon_connector_update_scratch_regs(struct drm_connector *connector, enum drm_c
 static struct drm_encoder *radeon_find_encoder(struct drm_connector *connector, int encoder_type)
 {
        struct drm_encoder *encoder;
-       int i;
 
-       drm_connector_for_each_possible_encoder(connector, encoder, i) {
+       drm_connector_for_each_possible_encoder(connector, encoder) {
                if (encoder->encoder_type == encoder_type)
                        return encoder;
        }
@@ -380,10 +378,9 @@ static int radeon_ddc_get_modes(struct drm_connector *connector)
 static struct drm_encoder *radeon_best_single_encoder(struct drm_connector *connector)
 {
        struct drm_encoder *encoder;
-       int i;
 
        /* pick the first one */
-       drm_connector_for_each_possible_encoder(connector, encoder, i)
+       drm_connector_for_each_possible_encoder(connector, encoder)
                return encoder;
 
        return NULL;
@@ -428,14 +425,13 @@ radeon_connector_analog_encoder_conflict_solve(struct drm_connector *connector,
 
        list_for_each_entry(conflict, &dev->mode_config.connector_list, head) {
                struct drm_encoder *enc;
-               int i;
 
                if (conflict == connector)
                        continue;
 
                radeon_conflict = to_radeon_connector(conflict);
 
-               drm_connector_for_each_possible_encoder(conflict, enc, i) {
+               drm_connector_for_each_possible_encoder(conflict, enc) {
                        /* if the IDs match */
                        if (enc == encoder) {
                                if (conflict->status != connector_status_connected)
@@ -1363,9 +1359,7 @@ radeon_dvi_detect(struct drm_connector *connector, bool force)
 
        /* find analog encoder */
        if (radeon_connector->dac_load_detect) {
-               int i;
-
-               drm_connector_for_each_possible_encoder(connector, encoder, i) {
+               drm_connector_for_each_possible_encoder(connector, encoder) {
                        if (encoder->encoder_type != DRM_MODE_ENCODER_DAC &&
                            encoder->encoder_type != DRM_MODE_ENCODER_TVDAC)
                                continue;
@@ -1443,9 +1437,8 @@ static struct drm_encoder *radeon_dvi_encoder(struct drm_connector *connector)
 {
        struct radeon_connector *radeon_connector = to_radeon_connector(connector);
        struct drm_encoder *encoder;
-       int i;
 
-       drm_connector_for_each_possible_encoder(connector, encoder, i) {
+       drm_connector_for_each_possible_encoder(connector, encoder) {
                if (radeon_connector->use_digital == true) {
                        if (encoder->encoder_type == DRM_MODE_ENCODER_TMDS)
                                return encoder;
@@ -1460,7 +1453,7 @@ static struct drm_encoder *radeon_dvi_encoder(struct drm_connector *connector)
 
        /* then check use digitial */
        /* pick the first one */
-       drm_connector_for_each_possible_encoder(connector, encoder, i)
+       drm_connector_for_each_possible_encoder(connector, encoder)
                return encoder;
 
        return NULL;
@@ -1603,9 +1596,8 @@ u16 radeon_connector_encoder_get_dp_bridge_encoder_id(struct drm_connector *conn
 {
        struct drm_encoder *encoder;
        struct radeon_encoder *radeon_encoder;
-       int i;
 
-       drm_connector_for_each_possible_encoder(connector, encoder, i) {
+       drm_connector_for_each_possible_encoder(connector, encoder) {
                radeon_encoder = to_radeon_encoder(encoder);
 
                switch (radeon_encoder->encoder_id) {
@@ -1624,10 +1616,9 @@ static bool radeon_connector_encoder_is_hbr2(struct drm_connector *connector)
 {
        struct drm_encoder *encoder;
        struct radeon_encoder *radeon_encoder;
-       int i;
        bool found = false;
 
-       drm_connector_for_each_possible_encoder(connector, encoder, i) {
+       drm_connector_for_each_possible_encoder(connector, encoder) {
                radeon_encoder = to_radeon_encoder(encoder);
                if (radeon_encoder->caps & ATOM_ENCODER_CAP_RECORD_HBR2)
                        found = true;
index d0bc91ed7c90a73b898e57a6a77a4786c11ed169..19590fff135c3139a98bcf4f6f5ed739f4d7b2e7 100644 (file)
@@ -361,7 +361,7 @@ static int radeon_pci_probe(struct pci_dev *pdev,
                return -EPROBE_DEFER;
 
        /* Get rid of things like offb */
-       ret = drm_fb_helper_remove_conflicting_pci_framebuffers(pdev, 0, "radeondrmfb");
+       ret = drm_fb_helper_remove_conflicting_pci_framebuffers(pdev, "radeondrmfb");
        if (ret)
                return ret;
 
index a05e10724d465f5478d86153ee41de0dfad6aef3..098bc9f40b983300a5bfbf28851cee016e929732 100644 (file)
@@ -794,6 +794,7 @@ int radeon_ttm_init(struct radeon_device *rdev)
        r = ttm_bo_device_init(&rdev->mman.bdev,
                               &radeon_bo_driver,
                               rdev->ddev->anon_inode->i_mapping,
+                              rdev->ddev->vma_offset_manager,
                               dma_addressing_limited(&rdev->pdev->dev));
        if (r) {
                DRM_ERROR("failed initializing buffer object driver(%d).\n", r);
index 0f00bdfe2366a5a0cb689fe9741f4447334e3f8f..3cd83a030a04fb27e3b44a5d3bafae205907b4b6 100644 (file)
@@ -9,6 +9,7 @@
 
 #include <linux/export.h>
 
+#include <drm/drm_bridge.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_modeset_helper_vtables.h>
 #include <drm/drm_panel.h>
@@ -84,8 +85,8 @@ int rcar_du_encoder_init(struct rcar_du_device *rcdu,
                        goto done;
                }
 
-               bridge = devm_drm_panel_bridge_add(rcdu->dev, panel,
-                                                  DRM_MODE_CONNECTOR_DPI);
+               bridge = devm_drm_panel_bridge_add_typed(rcdu->dev, panel,
+                                                        DRM_MODE_CONNECTOR_DPI);
                if (IS_ERR(bridge)) {
                        ret = PTR_ERR(bridge);
                        goto done;
index 64aefa856896376a10ce8ad51023e78bc79df4a0..8a4c9af0ba73c08b24fd55fc3eb1779f15384990 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/regmap.h>
 #include <linux/reset.h>
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_bridge.h>
 
 #include <drm/drm_dp_helper.h>
 #include <drm/drm_of.h>
index 89e0bb0fe0ab942ceb78db41ad3659f07615d1f8..ae730275a34f83bb2734c913fa929051790a77cb 100644 (file)
@@ -9,6 +9,7 @@
 #include <linux/of_graph.h>
 
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_bridge.h>
 #include <drm/drm_dp_helper.h>
 #include <drm/drm_of.h>
 #include <drm/drm_panel.h>
@@ -135,7 +136,8 @@ struct rockchip_rgb *rockchip_rgb_init(struct device *dev,
        drm_encoder_helper_add(encoder, &rockchip_rgb_encoder_helper_funcs);
 
        if (panel) {
-               bridge = drm_panel_bridge_add(panel, DRM_MODE_CONNECTOR_LVDS);
+               bridge = drm_panel_bridge_add_typed(panel,
+                                                   DRM_MODE_CONNECTOR_LVDS);
                if (IS_ERR(bridge))
                        return ERR_CAST(bridge);
        }
index aae88f8a016c20bc21ac6e30ef8d861a78e7f182..d2137342b3710bd53a890eb3dea8b8c99ed7162b 100644 (file)
@@ -1,6 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0-only
 test-drm_modeset-y := test-drm_modeset_common.o test-drm_plane_helper.o \
                       test-drm_format.o test-drm_framebuffer.o \
-                     test-drm_damage_helper.o
+                     test-drm_damage_helper.o test-drm_dp_mst_helper.o
 
 obj-$(CONFIG_DRM_DEBUG_SELFTEST) += test-drm_mm.o test-drm_modeset.o test-drm_cmdline_parser.o
index 46475374601333609c633cc6ef67daf73ae204f7..1898de0b4a4d78824b9d2311df5a8b535888b313 100644 (file)
@@ -32,3 +32,5 @@ selftest(damage_iter_damage_one_intersect, igt_damage_iter_damage_one_intersect)
 selftest(damage_iter_damage_one_outside, igt_damage_iter_damage_one_outside)
 selftest(damage_iter_damage_src_moved, igt_damage_iter_damage_src_moved)
 selftest(damage_iter_damage_not_visible, igt_damage_iter_damage_not_visible)
+selftest(dp_mst_calc_pbn_mode, igt_dp_mst_calc_pbn_mode)
+selftest(dp_mst_sideband_msg_req_decode, igt_dp_mst_sideband_msg_req_decode)
diff --git a/drivers/gpu/drm/selftests/test-drm_dp_mst_helper.c b/drivers/gpu/drm/selftests/test-drm_dp_mst_helper.c
new file mode 100644 (file)
index 0000000..af2b2de
--- /dev/null
@@ -0,0 +1,238 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Test cases for for the DRM DP MST helpers
+ */
+
+#define PREFIX_STR "[drm_dp_mst_helper]"
+
+#include <drm/drm_dp_mst_helper.h>
+#include <drm/drm_print.h>
+
+#include "../drm_dp_mst_topology_internal.h"
+#include "test-drm_modeset_common.h"
+
+int igt_dp_mst_calc_pbn_mode(void *ignored)
+{
+       int pbn, i;
+       const struct {
+               int rate;
+               int bpp;
+               int expected;
+       } test_params[] = {
+               { 154000, 30, 689 },
+               { 234000, 30, 1047 },
+               { 297000, 24, 1063 },
+       };
+
+       for (i = 0; i < ARRAY_SIZE(test_params); i++) {
+               pbn = drm_dp_calc_pbn_mode(test_params[i].rate,
+                                          test_params[i].bpp);
+               FAIL(pbn != test_params[i].expected,
+                    "Expected PBN %d for clock %d bpp %d, got %d\n",
+                    test_params[i].expected, test_params[i].rate,
+                    test_params[i].bpp, pbn);
+       }
+
+       return 0;
+}
+
+static bool
+sideband_msg_req_equal(const struct drm_dp_sideband_msg_req_body *in,
+                      const struct drm_dp_sideband_msg_req_body *out)
+{
+       const struct drm_dp_remote_i2c_read_tx *txin, *txout;
+       int i;
+
+       if (in->req_type != out->req_type)
+               return false;
+
+       switch (in->req_type) {
+       /*
+        * Compare struct members manually for request types which can't be
+        * compared simply using memcmp(). This is because said request types
+        * contain pointers to other allocated structs
+        */
+       case DP_REMOTE_I2C_READ:
+#define IN in->u.i2c_read
+#define OUT out->u.i2c_read
+               if (IN.num_bytes_read != OUT.num_bytes_read ||
+                   IN.num_transactions != OUT.num_transactions ||
+                   IN.port_number != OUT.port_number ||
+                   IN.read_i2c_device_id != OUT.read_i2c_device_id)
+                       return false;
+
+               for (i = 0; i < IN.num_transactions; i++) {
+                       txin = &IN.transactions[i];
+                       txout = &OUT.transactions[i];
+
+                       if (txin->i2c_dev_id != txout->i2c_dev_id ||
+                           txin->no_stop_bit != txout->no_stop_bit ||
+                           txin->num_bytes != txout->num_bytes ||
+                           txin->i2c_transaction_delay !=
+                           txout->i2c_transaction_delay)
+                               return false;
+
+                       if (memcmp(txin->bytes, txout->bytes,
+                                  txin->num_bytes) != 0)
+                               return false;
+               }
+               break;
+#undef IN
+#undef OUT
+
+       case DP_REMOTE_DPCD_WRITE:
+#define IN in->u.dpcd_write
+#define OUT out->u.dpcd_write
+               if (IN.dpcd_address != OUT.dpcd_address ||
+                   IN.num_bytes != OUT.num_bytes ||
+                   IN.port_number != OUT.port_number)
+                       return false;
+
+               return memcmp(IN.bytes, OUT.bytes, IN.num_bytes) == 0;
+#undef IN
+#undef OUT
+
+       case DP_REMOTE_I2C_WRITE:
+#define IN in->u.i2c_write
+#define OUT out->u.i2c_write
+               if (IN.port_number != OUT.port_number ||
+                   IN.write_i2c_device_id != OUT.write_i2c_device_id ||
+                   IN.num_bytes != OUT.num_bytes)
+                       return false;
+
+               return memcmp(IN.bytes, OUT.bytes, IN.num_bytes) == 0;
+#undef IN
+#undef OUT
+
+       default:
+               return memcmp(in, out, sizeof(*in)) == 0;
+       }
+
+       return true;
+}
+
+static bool
+sideband_msg_req_encode_decode(struct drm_dp_sideband_msg_req_body *in)
+{
+       struct drm_dp_sideband_msg_req_body out = {0};
+       struct drm_printer p = drm_err_printer(PREFIX_STR);
+       struct drm_dp_sideband_msg_tx txmsg;
+       int i, ret;
+
+       drm_dp_encode_sideband_req(in, &txmsg);
+       ret = drm_dp_decode_sideband_req(&txmsg, &out);
+       if (ret < 0) {
+               drm_printf(&p, "Failed to decode sideband request: %d\n",
+                          ret);
+               return false;
+       }
+
+       if (!sideband_msg_req_equal(in, &out)) {
+               drm_printf(&p, "Encode/decode failed, expected:\n");
+               drm_dp_dump_sideband_msg_req_body(in, 1, &p);
+               drm_printf(&p, "Got:\n");
+               drm_dp_dump_sideband_msg_req_body(&out, 1, &p);
+               return false;
+       }
+
+       switch (in->req_type) {
+       case DP_REMOTE_DPCD_WRITE:
+               kfree(out.u.dpcd_write.bytes);
+               break;
+       case DP_REMOTE_I2C_READ:
+               for (i = 0; i < out.u.i2c_read.num_transactions; i++)
+                       kfree(out.u.i2c_read.transactions[i].bytes);
+               break;
+       case DP_REMOTE_I2C_WRITE:
+               kfree(out.u.i2c_write.bytes);
+               break;
+       }
+
+       /* Clear everything but the req_type for the input */
+       memset(&in->u, 0, sizeof(in->u));
+
+       return true;
+}
+
+int igt_dp_mst_sideband_msg_req_decode(void *unused)
+{
+       struct drm_dp_sideband_msg_req_body in = { 0 };
+       u8 data[] = { 0xff, 0x0, 0xdd };
+       int i;
+
+#define DO_TEST() FAIL_ON(!sideband_msg_req_encode_decode(&in))
+
+       in.req_type = DP_ENUM_PATH_RESOURCES;
+       in.u.port_num.port_number = 5;
+       DO_TEST();
+
+       in.req_type = DP_POWER_UP_PHY;
+       in.u.port_num.port_number = 5;
+       DO_TEST();
+
+       in.req_type = DP_POWER_DOWN_PHY;
+       in.u.port_num.port_number = 5;
+       DO_TEST();
+
+       in.req_type = DP_ALLOCATE_PAYLOAD;
+       in.u.allocate_payload.number_sdp_streams = 3;
+       for (i = 0; i < in.u.allocate_payload.number_sdp_streams; i++)
+               in.u.allocate_payload.sdp_stream_sink[i] = i + 1;
+       DO_TEST();
+       in.u.allocate_payload.port_number = 0xf;
+       DO_TEST();
+       in.u.allocate_payload.vcpi = 0x7f;
+       DO_TEST();
+       in.u.allocate_payload.pbn = U16_MAX;
+       DO_TEST();
+
+       in.req_type = DP_QUERY_PAYLOAD;
+       in.u.query_payload.port_number = 0xf;
+       DO_TEST();
+       in.u.query_payload.vcpi = 0x7f;
+       DO_TEST();
+
+       in.req_type = DP_REMOTE_DPCD_READ;
+       in.u.dpcd_read.port_number = 0xf;
+       DO_TEST();
+       in.u.dpcd_read.dpcd_address = 0xfedcb;
+       DO_TEST();
+       in.u.dpcd_read.num_bytes = U8_MAX;
+       DO_TEST();
+
+       in.req_type = DP_REMOTE_DPCD_WRITE;
+       in.u.dpcd_write.port_number = 0xf;
+       DO_TEST();
+       in.u.dpcd_write.dpcd_address = 0xfedcb;
+       DO_TEST();
+       in.u.dpcd_write.num_bytes = ARRAY_SIZE(data);
+       in.u.dpcd_write.bytes = data;
+       DO_TEST();
+
+       in.req_type = DP_REMOTE_I2C_READ;
+       in.u.i2c_read.port_number = 0xf;
+       DO_TEST();
+       in.u.i2c_read.read_i2c_device_id = 0x7f;
+       DO_TEST();
+       in.u.i2c_read.num_transactions = 3;
+       in.u.i2c_read.num_bytes_read = ARRAY_SIZE(data) * 3;
+       for (i = 0; i < in.u.i2c_read.num_transactions; i++) {
+               in.u.i2c_read.transactions[i].bytes = data;
+               in.u.i2c_read.transactions[i].num_bytes = ARRAY_SIZE(data);
+               in.u.i2c_read.transactions[i].i2c_dev_id = 0x7f & ~i;
+               in.u.i2c_read.transactions[i].i2c_transaction_delay = 0xf & ~i;
+       }
+       DO_TEST();
+
+       in.req_type = DP_REMOTE_I2C_WRITE;
+       in.u.i2c_write.port_number = 0xf;
+       DO_TEST();
+       in.u.i2c_write.write_i2c_device_id = 0x7f;
+       DO_TEST();
+       in.u.i2c_write.num_bytes = ARRAY_SIZE(data);
+       in.u.i2c_write.bytes = data;
+       DO_TEST();
+
+#undef DO_TEST
+       return 0;
+}
index 74d5561a862be433f869d192a48857ddb61e9e86..2d29ea6f92e2a9ce2fff0c9b4e2cddb5c270c186 100644 (file)
@@ -126,7 +126,7 @@ static struct drm_framebuffer_test createbuffer_tests[] = {
                 .handles = { 1, 1, 0 }, .pitches = { MAX_WIDTH, MAX_WIDTH - 1, 0 },
        }
 },
-{ .buffer_created = 0, .name = "NV12 Invalid modifier/misssing DRM_MODE_FB_MODIFIERS flag",
+{ .buffer_created = 0, .name = "NV12 Invalid modifier/missing DRM_MODE_FB_MODIFIERS flag",
        .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_NV12,
                 .handles = { 1, 1, 0 }, .modifier = { DRM_FORMAT_MOD_SAMSUNG_64_32_TILE, 0, 0 },
                 .pitches = { MAX_WIDTH, MAX_WIDTH, 0 },
index 8c76f09c12d1108a2d36296ac6ec49761c529697..0fcb8bbc6a1b9f7e7150153dc44249d06f79e863 100644 (file)
@@ -39,5 +39,7 @@ int igt_damage_iter_damage_one_intersect(void *ignored);
 int igt_damage_iter_damage_one_outside(void *ignored);
 int igt_damage_iter_damage_src_moved(void *ignored);
 int igt_damage_iter_damage_not_visible(void *ignored);
+int igt_dp_mst_calc_pbn_mode(void *ignored);
+int igt_dp_mst_sideband_msg_req_decode(void *ignored);
 
 #endif
index 0bf7c332cf0b56b36c82112cecef1b24fbf6fe9c..ea64c1dcaf634042a41e3bef1162eda03630c521 100644 (file)
@@ -47,7 +47,7 @@ struct dma_pixmap {
        void *base;
 };
 
-/**
+/*
  * STI Cursor structure
  *
  * @sti_plane:    sti_plane structure
index e55870190bf5c5f711849c03ce582fb9bcaee028..68289b0b063a7a06c06e8d54e603fd4047fc05e9 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/platform_device.h>
 
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_bridge.h>
 #include <drm/drm_device.h>
 #include <drm/drm_panel.h>
 #include <drm/drm_print.h>
@@ -65,7 +66,7 @@ static struct dvo_config rgb_24bit_de_cfg = {
        .awg_fwgen_fct = sti_awg_generate_code_data_enable_mode,
 };
 
-/**
+/*
  * STI digital video output structure
  *
  * @dev: driver device
index 8e926cd6a1c8e11e481905c6a124057ece70d27b..11595c748844f6f0a088f698b4c4cf0011142bf7 100644 (file)
@@ -103,7 +103,7 @@ struct sti_gdp_node_list {
        dma_addr_t btm_field_paddr;
 };
 
-/**
+/*
  * STI GDP structure
  *
  * @sti_plane:          sti_plane structure
index 94e404f132342b5a4ba3f3783cb6053cfe4ff431..8f7bf33815fd18f6e0b3f11eb078b98282a57e8c 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/seq_file.h>
 
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_bridge.h>
 #include <drm/drm_debugfs.h>
 #include <drm/drm_device.h>
 #include <drm/drm_file.h>
@@ -230,7 +231,7 @@ static const struct sti_hda_video_config hda_supported_modes[] = {
         AWGi_720x480p_60, NN_720x480p_60, VID_ED}
 };
 
-/**
+/*
  * STI hd analog structure
  *
  * @dev: driver device
index 9862c322f0c4a8a677bd5c3bd443d6f7d5ab8f90..814560ead4e184063a9fc7b33ac4bdb7e9795b08 100644 (file)
@@ -9,11 +9,12 @@
 #include <linux/debugfs.h>
 #include <linux/hdmi.h>
 #include <linux/module.h>
-#include <linux/of_gpio.h>
+#include <linux/io.h>
 #include <linux/platform_device.h>
 #include <linux/reset.h>
 
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_bridge.h>
 #include <drm/drm_debugfs.h>
 #include <drm/drm_drv.h>
 #include <drm/drm_edid.h>
@@ -333,7 +334,6 @@ static void hdmi_infoframe_reset(struct sti_hdmi *hdmi,
  * Helper to concatenate infoframe in 32 bits word
  *
  * @ptr: pointer on the hdmi internal structure
- * @data: infoframe to write
  * @size: size to write
  */
 static inline unsigned int hdmi_infoframe_subpack(const u8 *ptr, size_t size)
@@ -543,13 +543,14 @@ static int hdmi_vendor_infoframe_config(struct sti_hdmi *hdmi)
        return 0;
 }
 
+#define HDMI_TIMEOUT_SWRESET  100   /*milliseconds */
+
 /**
  * Software reset of the hdmi subsystem
  *
  * @hdmi: pointer on the hdmi internal structure
  *
  */
-#define HDMI_TIMEOUT_SWRESET  100   /*milliseconds */
 static void hdmi_swreset(struct sti_hdmi *hdmi)
 {
        u32 val;
@@ -1256,6 +1257,7 @@ static int sti_hdmi_bind(struct device *dev, struct device *master, void *data)
        struct drm_device *drm_dev = data;
        struct drm_encoder *encoder;
        struct sti_hdmi_connector *connector;
+       struct cec_connector_info conn_info;
        struct drm_connector *drm_connector;
        struct drm_bridge *bridge;
        int err;
@@ -1318,6 +1320,14 @@ static int sti_hdmi_bind(struct device *dev, struct device *master, void *data)
                goto err_sysfs;
        }
 
+       cec_fill_conn_info_from_drm(&conn_info, drm_connector);
+       hdmi->notifier = cec_notifier_conn_register(&hdmi->dev, NULL,
+                                                   &conn_info);
+       if (!hdmi->notifier) {
+               hdmi->drm_connector = NULL;
+               return -ENOMEM;
+       }
+
        /* Enable default interrupts */
        hdmi_write(hdmi, HDMI_DEFAULT_INT, HDMI_INT_EN);
 
@@ -1331,6 +1341,9 @@ err_sysfs:
 static void sti_hdmi_unbind(struct device *dev,
                struct device *master, void *data)
 {
+       struct sti_hdmi *hdmi = dev_get_drvdata(dev);
+
+       cec_notifier_conn_unregister(hdmi->notifier);
 }
 
 static const struct component_ops sti_hdmi_ops = {
@@ -1436,10 +1449,6 @@ static int sti_hdmi_probe(struct platform_device *pdev)
                goto release_adapter;
        }
 
-       hdmi->notifier = cec_notifier_get(&pdev->dev);
-       if (!hdmi->notifier)
-               goto release_adapter;
-
        hdmi->reset = devm_reset_control_get(dev, "hdmi");
        /* Take hdmi out of reset */
        if (!IS_ERR(hdmi->reset))
@@ -1459,14 +1468,11 @@ static int sti_hdmi_remove(struct platform_device *pdev)
 {
        struct sti_hdmi *hdmi = dev_get_drvdata(&pdev->dev);
 
-       cec_notifier_set_phys_addr(hdmi->notifier, CEC_PHYS_ADDR_INVALID);
-
        i2c_put_adapter(hdmi->ddc_adapt);
        if (hdmi->audio_pdev)
                platform_device_unregister(hdmi->audio_pdev);
        component_del(&pdev->dev, &sti_hdmi_ops);
 
-       cec_notifier_put(hdmi->notifier);
        return 0;
 }
 
index aba79c17251222f77d386a68f5d24a0393cbc15a..5767e93dd1cdc034c520adac8b774f745c1f185a 100644 (file)
@@ -157,9 +157,9 @@ static void tvout_write(struct sti_tvout *tvout, u32 val, int offset)
  *
  * @tvout: tvout structure
  * @reg: register to set
- * @cr_r:
- * @y_g:
- * @cb_b:
+ * @cr_r: red chroma or red order
+ * @y_g: y or green order
+ * @cb_b: blue chroma or blue order
  */
 static void tvout_vip_set_color_order(struct sti_tvout *tvout, int reg,
                                      u32 cr_r, u32 y_g, u32 cb_b)
@@ -214,7 +214,7 @@ static void tvout_vip_set_rnd(struct sti_tvout *tvout, int reg, u32 rnd)
  * @tvout: tvout structure
  * @reg: register to set
  * @main_path: main or auxiliary path
- * @sel_input: selected_input (main/aux + conv)
+ * @video_out: selected_input (main/aux + conv)
  */
 static void tvout_vip_set_sel_input(struct sti_tvout *tvout,
                                    int reg,
@@ -251,7 +251,7 @@ static void tvout_vip_set_sel_input(struct sti_tvout *tvout,
  *
  * @tvout: tvout structure
  * @reg: register to set
- * @in_vid_signed: used video input format
+ * @in_vid_fmt: used video input format
  */
 static void tvout_vip_set_in_vid_fmt(struct sti_tvout *tvout,
                int reg, u32 in_vid_fmt)
index ef4009f11396a0b20c3a95425ce3942a9eddc0e4..0b17ac8a3faaa840095a8665083143060c15b4c4 100644 (file)
@@ -121,7 +121,7 @@ struct sti_vtg_sync_params {
        u32 vsync_off_bot;
 };
 
-/**
+/*
  * STI VTG structure
  *
  * @regs: register mapping
index a03a642c147cc58cb1c0d4454113c9157aebc247..514efefb0016df80d29d6243b05f06ce635a6b22 100644 (file)
@@ -260,8 +260,11 @@ dw_mipi_dsi_get_lane_mbps(void *priv_data, const struct drm_display_mode *mode,
        /* Compute requested pll out */
        bpp = mipi_dsi_pixel_format_to_bpp(format);
        pll_out_khz = mode->clock * bpp / lanes;
+
        /* Add 20% to pll out to be higher than pixel bw (burst mode only) */
-       pll_out_khz = (pll_out_khz * 12) / 10;
+       if (mode_flags & MIPI_DSI_MODE_VIDEO_BURST)
+               pll_out_khz = (pll_out_khz * 12) / 10;
+
        if (pll_out_khz > dsi->lane_max_kbps) {
                pll_out_khz = dsi->lane_max_kbps;
                DRM_WARN("Warning max phy mbps is used\n");
index 3ab4fbf8eb0d1e290280301c67b003ef107b5960..5b51298921cf18675c70f7a624fba8921719001b 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/module.h>
 #include <linux/of_address.h>
 #include <linux/of_graph.h>
+#include <linux/pinctrl/consumer.h>
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
 #include <linux/reset.h>
@@ -1040,6 +1041,36 @@ static const struct drm_encoder_funcs ltdc_encoder_funcs = {
        .destroy = drm_encoder_cleanup,
 };
 
+static void ltdc_encoder_disable(struct drm_encoder *encoder)
+{
+       struct drm_device *ddev = encoder->dev;
+
+       DRM_DEBUG_DRIVER("\n");
+
+       /* Set to sleep state the pinctrl whatever type of encoder */
+       pinctrl_pm_select_sleep_state(ddev->dev);
+}
+
+static void ltdc_encoder_enable(struct drm_encoder *encoder)
+{
+       struct drm_device *ddev = encoder->dev;
+
+       DRM_DEBUG_DRIVER("\n");
+
+       /*
+        * Set to default state the pinctrl only with DPI type.
+        * Others types like DSI, don't need pinctrl due to
+        * internal bridge (the signals do not come out of the chipset).
+        */
+       if (encoder->encoder_type == DRM_MODE_ENCODER_DPI)
+               pinctrl_pm_select_default_state(ddev->dev);
+}
+
+static const struct drm_encoder_helper_funcs ltdc_encoder_helper_funcs = {
+       .disable = ltdc_encoder_disable,
+       .enable = ltdc_encoder_enable,
+};
+
 static int ltdc_encoder_init(struct drm_device *ddev, struct drm_bridge *bridge)
 {
        struct drm_encoder *encoder;
@@ -1055,6 +1086,8 @@ static int ltdc_encoder_init(struct drm_device *ddev, struct drm_bridge *bridge)
        drm_encoder_init(ddev, encoder, &ltdc_encoder_funcs,
                         DRM_MODE_ENCODER_DPI, NULL);
 
+       drm_encoder_helper_add(encoder, &ltdc_encoder_helper_funcs);
+
        ret = drm_bridge_attach(encoder, bridge, NULL);
        if (ret) {
                drm_encoder_cleanup(encoder);
@@ -1236,8 +1269,8 @@ int ltdc_load(struct drm_device *ddev)
        /* Add endpoints panels or bridges if any */
        for (i = 0; i < MAX_ENDPOINTS; i++) {
                if (panel[i]) {
-                       bridge[i] = drm_panel_bridge_add(panel[i],
-                                                       DRM_MODE_CONNECTOR_DPI);
+                       bridge[i] = drm_panel_bridge_add_typed(panel[i],
+                                                              DRM_MODE_CONNECTOR_DPI);
                        if (IS_ERR(bridge[i])) {
                                DRM_ERROR("panel-bridge endpoint %d\n", i);
                                ret = PTR_ERR(bridge[i]);
@@ -1280,6 +1313,8 @@ int ltdc_load(struct drm_device *ddev)
 
        clk_disable_unprepare(ldev->pixel_clk);
 
+       pinctrl_pm_select_sleep_state(ddev->dev);
+
        pm_runtime_enable(ddev->dev);
 
        return 0;
index eb8071a4d6d002154d3a93caa80b2eb110996c40..a7c4654445c75b652a8b3d8462f2d52023994ed9 100644 (file)
@@ -490,6 +490,7 @@ static int sun4i_hdmi_bind(struct device *dev, struct device *master,
 {
        struct platform_device *pdev = to_platform_device(dev);
        struct drm_device *drm = data;
+       struct cec_connector_info conn_info;
        struct sun4i_drv *drv = drm->dev_private;
        struct sun4i_hdmi *hdmi;
        struct resource *res;
@@ -629,8 +630,7 @@ static int sun4i_hdmi_bind(struct device *dev, struct device *master,
 
 #ifdef CONFIG_DRM_SUN4I_HDMI_CEC
        hdmi->cec_adap = cec_pin_allocate_adapter(&sun4i_hdmi_cec_pin_ops,
-               hdmi, "sun4i", CEC_CAP_TRANSMIT | CEC_CAP_LOG_ADDRS |
-               CEC_CAP_PASSTHROUGH | CEC_CAP_RC);
+               hdmi, "sun4i", CEC_CAP_DEFAULTS | CEC_CAP_CONNECTOR_INFO);
        ret = PTR_ERR_OR_ZERO(hdmi->cec_adap);
        if (ret < 0)
                goto err_cleanup_connector;
@@ -649,6 +649,8 @@ static int sun4i_hdmi_bind(struct device *dev, struct device *master,
                        "Couldn't initialise the HDMI connector\n");
                goto err_cleanup_connector;
        }
+       cec_fill_conn_info_from_drm(&conn_info, &hdmi->connector);
+       cec_s_conn_info(hdmi->cec_adap, &conn_info);
 
        /* There is no HPD interrupt, so we need to poll the controller */
        hdmi->connector.polled = DRM_CONNECTOR_POLL_CONNECT |
index 7fbf425acb55004424231d4d2dd2b69c500e9fba..25ab2ef6d5454fb427fb9439ddffdcca35a672c2 100644 (file)
@@ -7,6 +7,7 @@
 #include <linux/clk.h>
 
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_bridge.h>
 #include <drm/drm_of.h>
 #include <drm/drm_panel.h>
 #include <drm/drm_print.h>
index aac56983f2081ee450f08ccf86e58abbecbb09e4..e74b9eddca0133973457f4de80dc9cbf0c8db4c2 100644 (file)
@@ -9,6 +9,7 @@
 #include <linux/clk.h>
 
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_bridge.h>
 #include <drm/drm_of.h>
 #include <drm/drm_panel.h>
 #include <drm/drm_print.h>
index 04c721d0d3b981964145b3bc9cf80e17545008a5..fad72799b8df17801e50df209d48bb0365843630 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/reset.h>
 
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_bridge.h>
 #include <drm/drm_connector.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_encoder.h>
index 1636344ba9ec2ecebe44aa38a382fb81f29fe007..082d196e43da79818d38c4d39388e7bae46d7cfd 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
 #include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
 #include <linux/reset.h>
 #include <linux/slab.h>
 
@@ -365,8 +366,7 @@ static void sun6i_dsi_inst_init(struct sun6i_dsi *dsi,
 static u16 sun6i_dsi_get_video_start_delay(struct sun6i_dsi *dsi,
                                           struct drm_display_mode *mode)
 {
-       u16 start = clamp(mode->vtotal - mode->vdisplay - 10, 8, 100);
-       u16 delay = mode->vtotal - (mode->vsync_end - mode->vdisplay) + start;
+       u16 delay = mode->vtotal - (mode->vsync_end - mode->vdisplay) + 1;
 
        if (delay > mode->vtotal)
                delay = delay % mode->vtotal;
@@ -437,9 +437,9 @@ static void sun6i_dsi_setup_burst(struct sun6i_dsi *dsi,
                             SUN6I_DSI_BURST_LINE_SYNC_POINT(SUN6I_DSI_SYNC_POINT));
 
                val = SUN6I_DSI_TCON_DRQ_ENABLE_MODE;
-       } else if ((mode->hsync_end - mode->hdisplay) > 20) {
+       } else if ((mode->hsync_start - mode->hdisplay) > 20) {
                /* Maaaaaagic */
-               u16 drq = (mode->hsync_end - mode->hdisplay) - 20;
+               u16 drq = (mode->hsync_start - mode->hdisplay) - 20;
 
                drq *= mipi_dsi_pixel_format_to_bpp(device->format);
                drq /= 32;
@@ -1100,6 +1100,12 @@ static int sun6i_dsi_probe(struct platform_device *pdev)
                return PTR_ERR(base);
        }
 
+       dsi->regulator = devm_regulator_get(dev, "vcc-dsi");
+       if (IS_ERR(dsi->regulator)) {
+               dev_err(dev, "Couldn't get VCC-DSI supply\n");
+               return PTR_ERR(dsi->regulator);
+       }
+
        dsi->regs = devm_regmap_init_mmio_clk(dev, "bus", base,
                                              &sun6i_dsi_regmap_config);
        if (IS_ERR(dsi->regs)) {
@@ -1173,6 +1179,13 @@ static int sun6i_dsi_remove(struct platform_device *pdev)
 static int __maybe_unused sun6i_dsi_runtime_resume(struct device *dev)
 {
        struct sun6i_dsi *dsi = dev_get_drvdata(dev);
+       int err;
+
+       err = regulator_enable(dsi->regulator);
+       if (err) {
+               dev_err(dsi->dev, "failed to enable VCC-DSI supply: %d\n", err);
+               return err;
+       }
 
        reset_control_deassert(dsi->reset);
        clk_prepare_enable(dsi->mod_clk);
@@ -1205,6 +1218,7 @@ static int __maybe_unused sun6i_dsi_runtime_suspend(struct device *dev)
 
        clk_disable_unprepare(dsi->mod_clk);
        reset_control_assert(dsi->reset);
+       regulator_disable(dsi->regulator);
 
        return 0;
 }
index 5c3ad5be06901bc83179695f8ece7da02f9bf70c..3f4846f581ef929948b980609dd1bffc6621646a 100644 (file)
@@ -23,6 +23,7 @@ struct sun6i_dsi {
        struct clk              *bus_clk;
        struct clk              *mod_clk;
        struct regmap           *regs;
+       struct regulator        *regulator;
        struct reset_control    *reset;
        struct phy              *dphy;
 
index 43d756b7810ee619ede16400e6d79448f7147cba..51d034e095f4dfd811358d2bfc44641a18789409 100644 (file)
@@ -8,6 +8,7 @@
 #include <linux/of_graph.h>
 
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_bridge.h>
 #include <drm/drm_of.h>
 
 #include "tilcdc_drv.h"
@@ -139,8 +140,8 @@ int tilcdc_attach_external_device(struct drm_device *ddev)
        }
 
        if (panel) {
-               bridge = devm_drm_panel_bridge_add(ddev->dev, panel,
-                                                  DRM_MODE_CONNECTOR_DPI);
+               bridge = devm_drm_panel_bridge_add_typed(ddev->dev, panel,
+                                                        DRM_MODE_CONNECTOR_DPI);
                if (IS_ERR(bridge)) {
                        ret = PTR_ERR(bridge);
                        goto err_encoder_cleanup;
index 504763423d463a69122e3fe92870c8bec8b63aad..a46ac284dd5e9211070dcf1ecea877bdde90a760 100644 (file)
@@ -63,7 +63,6 @@ config TINYDRM_REPAPER
        depends on DRM && SPI
        select DRM_KMS_HELPER
        select DRM_KMS_CMA_HELPER
-       depends on THERMAL || !THERMAL
        help
          DRM driver for the following Pervasive Displays panels:
          1.44" TFT EPD Panel (E1144CS021)
index 20ff56f27aa4a988471ce390fd4149a6ec54343d..c7f86499165f926e0b37c415667bc12ecd92bae7 100644 (file)
@@ -675,7 +675,7 @@ static void ttm_bo_release(struct kref *kref)
        if (bo->bdev->driver->release_notify)
                bo->bdev->driver->release_notify(bo);
 
-       drm_vma_offset_remove(&bdev->vma_manager, &bo->base.vma_node);
+       drm_vma_offset_remove(bdev->vma_manager, &bo->base.vma_node);
        ttm_mem_io_lock(man, false);
        ttm_mem_io_free_vm(bo);
        ttm_mem_io_unlock(man);
@@ -1356,7 +1356,7 @@ int ttm_bo_init_reserved(struct ttm_bo_device *bdev,
         */
        if (bo->type == ttm_bo_type_device ||
            bo->type == ttm_bo_type_sg)
-               ret = drm_vma_offset_add(&bdev->vma_manager, &bo->base.vma_node,
+               ret = drm_vma_offset_add(bdev->vma_manager, &bo->base.vma_node,
                                         bo->mem.num_pages);
 
        /* passed reservation objects should already be locked,
@@ -1707,8 +1707,6 @@ int ttm_bo_device_release(struct ttm_bo_device *bdev)
                        pr_debug("Swap list %d was clean\n", i);
        spin_unlock(&glob->lru_lock);
 
-       drm_vma_offset_manager_destroy(&bdev->vma_manager);
-
        if (!ret)
                ttm_bo_global_release();
 
@@ -1719,11 +1717,15 @@ EXPORT_SYMBOL(ttm_bo_device_release);
 int ttm_bo_device_init(struct ttm_bo_device *bdev,
                       struct ttm_bo_driver *driver,
                       struct address_space *mapping,
+                      struct drm_vma_offset_manager *vma_manager,
                       bool need_dma32)
 {
        struct ttm_bo_global *glob = &ttm_bo_glob;
        int ret;
 
+       if (WARN_ON(vma_manager == NULL))
+               return -EINVAL;
+
        ret = ttm_bo_global_init();
        if (ret)
                return ret;
@@ -1740,9 +1742,7 @@ int ttm_bo_device_init(struct ttm_bo_device *bdev,
        if (unlikely(ret != 0))
                goto out_no_sys;
 
-       drm_vma_offset_manager_init(&bdev->vma_manager,
-                                   DRM_FILE_PAGE_OFFSET_START,
-                                   DRM_FILE_PAGE_OFFSET_SIZE);
+       bdev->vma_manager = vma_manager;
        INIT_DELAYED_WORK(&bdev->wq, ttm_bo_delayed_workqueue);
        INIT_LIST_HEAD(&bdev->ddestroy);
        bdev->dev_mapping = mapping;
index 76eedb9636931da799fe0954b6ef564ed7219621..4aa007edffb09b1b05e28f4873342552c9e170b5 100644 (file)
@@ -409,16 +409,16 @@ static struct ttm_buffer_object *ttm_bo_vm_lookup(struct ttm_bo_device *bdev,
        struct drm_vma_offset_node *node;
        struct ttm_buffer_object *bo = NULL;
 
-       drm_vma_offset_lock_lookup(&bdev->vma_manager);
+       drm_vma_offset_lock_lookup(bdev->vma_manager);
 
-       node = drm_vma_offset_lookup_locked(&bdev->vma_manager, offset, pages);
+       node = drm_vma_offset_lookup_locked(bdev->vma_manager, offset, pages);
        if (likely(node)) {
                bo = container_of(node, struct ttm_buffer_object,
                                  base.vma_node);
                bo = ttm_bo_get_unless_zero(bo);
        }
 
-       drm_vma_offset_unlock_lookup(&bdev->vma_manager);
+       drm_vma_offset_unlock_lookup(bdev->vma_manager);
 
        if (!bo)
                pr_err("Could not find buffer object to map\n");
index 416f24823c0aa5a9f623b5669c132b3ae491a5e5..954b09c948ebe3b1089bb603d839d542c01939db 100644 (file)
@@ -80,8 +80,8 @@ static int tve200_modeset_init(struct drm_device *dev)
        if (ret && ret != -ENODEV)
                return ret;
        if (panel) {
-               bridge = drm_panel_bridge_add(panel,
-                                             DRM_MODE_CONNECTOR_Unknown);
+               bridge = drm_panel_bridge_add_typed(panel,
+                                                   DRM_MODE_CONNECTOR_Unknown);
                if (IS_ERR(bridge)) {
                        ret = PTR_ERR(bridge);
                        goto out_bridge;
index ddb61a60c61049f787bd580d6f58c8082df172de..b4ae3e89a7b43f6e7117ee30f59727852b1a910a 100644 (file)
@@ -90,13 +90,6 @@ udl_detect(struct drm_connector *connector, bool force)
        return connector_status_connected;
 }
 
-static struct drm_encoder*
-udl_best_single_encoder(struct drm_connector *connector)
-{
-       int enc_id = connector->encoder_ids[0];
-       return drm_encoder_find(connector->dev, NULL, enc_id);
-}
-
 static int udl_connector_set_property(struct drm_connector *connector,
                                      struct drm_property *property,
                                      uint64_t val)
@@ -120,7 +113,6 @@ static void udl_connector_destroy(struct drm_connector *connector)
 static const struct drm_connector_helper_funcs udl_connector_helper_funcs = {
        .get_modes = udl_get_modes,
        .mode_valid = udl_mode_valid,
-       .best_encoder = udl_best_single_encoder,
 };
 
 static const struct drm_connector_funcs udl_connector_funcs = {
index 3506ae2723ae156b9ad0f9de9a0c037855529c0c..e94bf75368bef387927d8f64616c00aed070dfa2 100644 (file)
@@ -126,6 +126,9 @@ static int v3d_get_param_ioctl(struct drm_device *dev, void *data,
        case DRM_V3D_PARAM_SUPPORTS_CSD:
                args->value = v3d_has_csd(v3d);
                return 0;
+       case DRM_V3D_PARAM_SUPPORTS_CACHE_FLUSH:
+               args->value = 1;
+               return 0;
        default:
                DRM_DEBUG("Unknown parameter %d\n", args->param);
                return -EINVAL;
index 5d80507b539bd01a28619629c7dd6cf9d4ddf42c..4c4b59ae2c81067dd39b5113a8edea29dff3a40f 100644 (file)
@@ -530,13 +530,16 @@ v3d_submit_cl_ioctl(struct drm_device *dev, void *data,
        struct drm_v3d_submit_cl *args = data;
        struct v3d_bin_job *bin = NULL;
        struct v3d_render_job *render;
+       struct v3d_job *clean_job = NULL;
+       struct v3d_job *last_job;
        struct ww_acquire_ctx acquire_ctx;
        int ret = 0;
 
        trace_v3d_submit_cl_ioctl(&v3d->drm, args->rcl_start, args->rcl_end);
 
-       if (args->pad != 0) {
-               DRM_INFO("pad must be zero: %d\n", args->pad);
+       if (args->flags != 0 &&
+           args->flags != DRM_V3D_SUBMIT_CL_FLUSH_CACHE) {
+               DRM_INFO("invalid flags: %d\n", args->flags);
                return -EINVAL;
        }
 
@@ -563,6 +566,7 @@ v3d_submit_cl_ioctl(struct drm_device *dev, void *data,
                ret = v3d_job_init(v3d, file_priv, &bin->base,
                                   v3d_job_free, args->in_sync_bcl);
                if (ret) {
+                       kfree(bin);
                        v3d_job_put(&render->base);
                        return ret;
                }
@@ -575,12 +579,31 @@ v3d_submit_cl_ioctl(struct drm_device *dev, void *data,
                bin->render = render;
        }
 
-       ret = v3d_lookup_bos(dev, file_priv, &render->base,
+       if (args->flags & DRM_V3D_SUBMIT_CL_FLUSH_CACHE) {
+               clean_job = kcalloc(1, sizeof(*clean_job), GFP_KERNEL);
+               if (!clean_job) {
+                       ret = -ENOMEM;
+                       goto fail;
+               }
+
+               ret = v3d_job_init(v3d, file_priv, clean_job, v3d_job_free, 0);
+               if (ret) {
+                       kfree(clean_job);
+                       clean_job = NULL;
+                       goto fail;
+               }
+
+               last_job = clean_job;
+       } else {
+               last_job = &render->base;
+       }
+
+       ret = v3d_lookup_bos(dev, file_priv, last_job,
                             args->bo_handles, args->bo_handle_count);
        if (ret)
                goto fail;
 
-       ret = v3d_lock_bo_reservations(&render->base, &acquire_ctx);
+       ret = v3d_lock_bo_reservations(last_job, &acquire_ctx);
        if (ret)
                goto fail;
 
@@ -599,28 +622,44 @@ v3d_submit_cl_ioctl(struct drm_device *dev, void *data,
        ret = v3d_push_job(v3d_priv, &render->base, V3D_RENDER);
        if (ret)
                goto fail_unreserve;
+
+       if (clean_job) {
+               struct dma_fence *render_fence =
+                       dma_fence_get(render->base.done_fence);
+               ret = drm_gem_fence_array_add(&clean_job->deps, render_fence);
+               if (ret)
+                       goto fail_unreserve;
+               ret = v3d_push_job(v3d_priv, clean_job, V3D_CACHE_CLEAN);
+               if (ret)
+                       goto fail_unreserve;
+       }
+
        mutex_unlock(&v3d->sched_lock);
 
        v3d_attach_fences_and_unlock_reservation(file_priv,
-                                                &render->base,
+                                                last_job,
                                                 &acquire_ctx,
                                                 args->out_sync,
-                                                render->base.done_fence);
+                                                last_job->done_fence);
 
        if (bin)
                v3d_job_put(&bin->base);
        v3d_job_put(&render->base);
+       if (clean_job)
+               v3d_job_put(clean_job);
 
        return 0;
 
 fail_unreserve:
        mutex_unlock(&v3d->sched_lock);
-       drm_gem_unlock_reservations(render->base.bo,
-                                   render->base.bo_count, &acquire_ctx);
+       drm_gem_unlock_reservations(last_job->bo,
+                                   last_job->bo_count, &acquire_ctx);
 fail:
        if (bin)
                v3d_job_put(&bin->base);
        v3d_job_put(&render->base);
+       if (clean_job)
+               v3d_job_put(clean_job);
 
        return ret;
 }
index 56ba510f21a2d84717baf4f683b9fe18597df6b7..45fe135d6e436e83606a4f99fb55df29f3733738 100644 (file)
@@ -4,6 +4,8 @@ config DRM_VBOXVIDEO
        depends on DRM && X86 && PCI
        select DRM_KMS_HELPER
        select DRM_VRAM_HELPER
+       select DRM_TTM
+       select DRM_TTM_HELPER
        select GENERIC_ALLOCATOR
        help
          This is a KMS driver for the virtual Graphics Card used in
index e8cb9efc6088961f6cb28ef2a49d21b4baf1e505..fb436ec760ead525b54a8069f458be48e52242f5 100644 (file)
@@ -20,8 +20,6 @@
 #include <drm/drm_gem.h>
 #include <drm/drm_gem_vram_helper.h>
 
-#include <drm/drm_vram_mm_helper.h>
-
 #include "vboxvideo_guest.h"
 #include "vboxvideo_vbe.h"
 #include "hgsmi_ch_setup.h"
index b82595a9ed0fd337e1447f4707d83f4f378864aa..976423d0c3ccacc588fcf1e6a2a43e7b679b8736 100644 (file)
@@ -17,8 +17,7 @@ int vbox_mm_init(struct vbox_private *vbox)
        struct drm_device *dev = &vbox->ddev;
 
        vmm = drm_vram_helper_alloc_mm(dev, pci_resource_start(dev->pdev, 0),
-                                      vbox->available_vram_size,
-                                      &drm_gem_vram_mm_funcs);
+                                      vbox->available_vram_size);
        if (IS_ERR(vmm)) {
                ret = PTR_ERR(vmm);
                DRM_ERROR("Error initializing VRAM MM; %d\n", ret);
index 8a27a6acee61cb965a8d2287c721dee5f3cdec33..c586325de2a5bd09589eb28cdb636b7aed68fbfd 100644 (file)
@@ -249,7 +249,8 @@ static int vc4_dpi_init_bridge(struct vc4_dpi *dpi)
        }
 
        if (panel)
-               bridge = drm_panel_bridge_add(panel, DRM_MODE_CONNECTOR_DPI);
+               bridge = drm_panel_bridge_add_typed(panel,
+                                                   DRM_MODE_CONNECTOR_DPI);
 
        return drm_bridge_attach(dpi->encoder, bridge, NULL);
 }
index c78fa8144776e7cf9abade9a81791c2c24ae5e62..c9ba83ed49b9bdd25345701fa464466a19ffd433 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/pm_runtime.h>
 
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_bridge.h>
 #include <drm/drm_edid.h>
 #include <drm/drm_mipi_dsi.h>
 #include <drm/drm_of.h>
@@ -1575,8 +1576,8 @@ static int vc4_dsi_bind(struct device *dev, struct device *master, void *data)
        }
 
        if (panel) {
-               dsi->bridge = devm_drm_panel_bridge_add(dev, panel,
-                                                       DRM_MODE_CONNECTOR_DSI);
+               dsi->bridge = devm_drm_panel_bridge_add_typed(dev, panel,
+                                                             DRM_MODE_CONNECTOR_DSI);
                if (IS_ERR(dsi->bridge))
                        return PTR_ERR(dsi->bridge);
        }
index ee7d4e7b0ee33ca2ae75f5b1e322487d8dc887eb..0853b980bcb314bf65b8a4955476d66695f5457e 100644 (file)
@@ -1285,6 +1285,9 @@ static const struct cec_adap_ops vc4_hdmi_cec_adap_ops = {
 
 static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 {
+#ifdef CONFIG_DRM_VC4_HDMI_CEC
+       struct cec_connector_info conn_info;
+#endif
        struct platform_device *pdev = to_platform_device(dev);
        struct drm_device *drm = dev_get_drvdata(master);
        struct vc4_dev *vc4 = drm->dev_private;
@@ -1403,13 +1406,15 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 #ifdef CONFIG_DRM_VC4_HDMI_CEC
        hdmi->cec_adap = cec_allocate_adapter(&vc4_hdmi_cec_adap_ops,
                                              vc4, "vc4",
-                                             CEC_CAP_TRANSMIT |
-                                             CEC_CAP_LOG_ADDRS |
-                                             CEC_CAP_PASSTHROUGH |
-                                             CEC_CAP_RC, 1);
+                                             CEC_CAP_DEFAULTS |
+                                             CEC_CAP_CONNECTOR_INFO, 1);
        ret = PTR_ERR_OR_ZERO(hdmi->cec_adap);
        if (ret < 0)
                goto err_destroy_conn;
+
+       cec_fill_conn_info_from_drm(&conn_info, hdmi->connector);
+       cec_s_conn_info(hdmi->cec_adap, &conn_info);
+
        HDMI_WRITE(VC4_HDMI_CPU_MASK_SET, 0xffffffff);
        value = HDMI_READ(VC4_HDMI_CEC_CNTRL_1);
        value &= ~VC4_HDMI_CEC_DIV_CLK_CNT_MASK;
index ba36e933bb490ceeaf5d9b9f1b10286a72e8f416..eff3047052d4818d9bbede7c4b7b115fe7d1d62a 100644 (file)
@@ -3,7 +3,7 @@ config DRM_VIRTIO_GPU
        tristate "Virtio GPU driver"
        depends on DRM && VIRTIO && MMU
        select DRM_KMS_HELPER
-       select DRM_TTM
+       select DRM_GEM_SHMEM_HELPER
        help
           This is the virtual GPU driver for virtio.  It can be used with
           QEMU based VMMs (like KVM or Xen).
index 458e606a936f4a877abd21040c994b128a06e683..92aa2b3d349d99235035476cacb921f67e1d2a24 100644 (file)
@@ -4,7 +4,7 @@
 # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
 
 virtio-gpu-y := virtgpu_drv.o virtgpu_kms.o virtgpu_gem.o \
-       virtgpu_display.o virtgpu_vq.o virtgpu_ttm.o \
+       virtgpu_display.o virtgpu_vq.o \
        virtgpu_fence.o virtgpu_object.o virtgpu_debugfs.o virtgpu_plane.o \
        virtgpu_ioctl.o virtgpu_prime.o virtgpu_trace_points.o
 
index 0fc32fa0b3c0fc818f2f4584064707bf3dadbe01..a5cb58754f7d7b249dd62fe2e84101fc222fe09d 100644 (file)
@@ -56,7 +56,6 @@ static int virtio_gpu_pci_quirk(struct drm_device *dev, struct virtio_device *vd
        dev->pdev = pdev;
        if (vga)
                drm_fb_helper_remove_conflicting_pci_framebuffers(pdev,
-                                                                 0,
                                                                  "virtiodrmfb");
 
        /*
@@ -185,17 +184,7 @@ MODULE_AUTHOR("Dave Airlie <airlied@redhat.com>");
 MODULE_AUTHOR("Gerd Hoffmann <kraxel@redhat.com>");
 MODULE_AUTHOR("Alon Levy");
 
-static const struct file_operations virtio_gpu_driver_fops = {
-       .owner = THIS_MODULE,
-       .open = drm_open,
-       .mmap = virtio_gpu_mmap,
-       .poll = drm_poll,
-       .read = drm_read,
-       .unlocked_ioctl = drm_ioctl,
-       .release = drm_release,
-       .compat_ioctl = drm_compat_ioctl,
-       .llseek = noop_llseek,
-};
+DEFINE_DRM_GEM_SHMEM_FOPS(virtio_gpu_driver_fops);
 
 static struct drm_driver driver = {
        .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_RENDER | DRIVER_ATOMIC,
@@ -210,15 +199,10 @@ static struct drm_driver driver = {
 #endif
        .prime_handle_to_fd = drm_gem_prime_handle_to_fd,
        .prime_fd_to_handle = drm_gem_prime_fd_to_handle,
-       .gem_prime_get_sg_table = virtgpu_gem_prime_get_sg_table,
+       .gem_prime_mmap = drm_gem_prime_mmap,
        .gem_prime_import_sg_table = virtgpu_gem_prime_import_sg_table,
-       .gem_prime_vmap = virtgpu_gem_prime_vmap,
-       .gem_prime_vunmap = virtgpu_gem_prime_vunmap,
-       .gem_prime_mmap = virtgpu_gem_prime_mmap,
 
-       .gem_free_object_unlocked = virtio_gpu_gem_free_object,
-       .gem_open_object = virtio_gpu_gem_object_open,
-       .gem_close_object = virtio_gpu_gem_object_close,
+       .gem_create_object = virtio_gpu_create_object,
        .fops = &virtio_gpu_driver_fops,
 
        .ioctls = virtio_gpu_ioctls,
index e28829661724f33640732ade1189a04543e69e61..314e02f94d9c4216edb1904c3be458404c26307e 100644 (file)
 #include <drm/drm_encoder.h>
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_gem.h>
+#include <drm/drm_gem_shmem_helper.h>
 #include <drm/drm_ioctl.h>
 #include <drm/drm_probe_helper.h>
-#include <drm/ttm/ttm_bo_api.h>
-#include <drm/ttm/ttm_bo_driver.h>
-#include <drm/ttm/ttm_module.h>
-#include <drm/ttm/ttm_placement.h>
 
 #define DRIVER_NAME "virtio_gpu"
 #define DRIVER_DESC "virtio GPU"
@@ -68,21 +65,23 @@ struct virtio_gpu_object_params {
 };
 
 struct virtio_gpu_object {
-       struct drm_gem_object gem_base;
+       struct drm_gem_shmem_object base;
        uint32_t hw_res_handle;
 
        struct sg_table *pages;
        uint32_t mapped;
-       void *vmap;
        bool dumb;
-       struct ttm_place                placement_code;
-       struct ttm_placement            placement;
-       struct ttm_buffer_object        tbo;
-       struct ttm_bo_kmap_obj          kmap;
        bool created;
 };
 #define gem_to_virtio_gpu_obj(gobj) \
-       container_of((gobj), struct virtio_gpu_object, gem_base)
+       container_of((gobj), struct virtio_gpu_object, base.base)
+
+struct virtio_gpu_object_array {
+       struct ww_acquire_ctx ticket;
+       struct list_head next;
+       u32 nents, total;
+       struct drm_gem_object *objs[];
+};
 
 struct virtio_gpu_vbuffer;
 struct virtio_gpu_device;
@@ -115,9 +114,9 @@ struct virtio_gpu_vbuffer {
 
        char *resp_buf;
        int resp_size;
-
        virtio_gpu_resp_cb resp_cb;
 
+       struct virtio_gpu_object_array *objs;
        struct list_head list;
 };
 
@@ -147,10 +146,6 @@ struct virtio_gpu_framebuffer {
 #define to_virtio_gpu_framebuffer(x) \
        container_of(x, struct virtio_gpu_framebuffer, base)
 
-struct virtio_gpu_mman {
-       struct ttm_bo_device            bdev;
-};
-
 struct virtio_gpu_queue {
        struct virtqueue *vq;
        spinlock_t qlock;
@@ -179,8 +174,6 @@ struct virtio_gpu_device {
 
        struct virtio_device *vdev;
 
-       struct virtio_gpu_mman mman;
-
        struct virtio_gpu_output outputs[VIRTIO_GPU_MAX_SCANOUTS];
        uint32_t num_scanouts;
 
@@ -205,6 +198,10 @@ struct virtio_gpu_device {
 
        struct work_struct config_changed_work;
 
+       struct work_struct obj_free_work;
+       spinlock_t obj_free_lock;
+       struct list_head obj_free_list;
+
        struct virtio_gpu_drv_capset *capsets;
        uint32_t num_capsets;
        struct list_head cap_cache;
@@ -217,9 +214,6 @@ struct virtio_gpu_fpriv {
 /* virtio_ioctl.c */
 #define DRM_VIRTIO_NUM_IOCTLS 10
 extern struct drm_ioctl_desc virtio_gpu_ioctls[DRM_VIRTIO_NUM_IOCTLS];
-int virtio_gpu_object_list_validate(struct ww_acquire_ctx *ticket,
-                                   struct list_head *head);
-void virtio_gpu_unref_list(struct list_head *head);
 
 /* virtio_kms.c */
 int virtio_gpu_init(struct drm_device *dev);
@@ -240,10 +234,6 @@ int virtio_gpu_gem_object_open(struct drm_gem_object *obj,
                               struct drm_file *file);
 void virtio_gpu_gem_object_close(struct drm_gem_object *obj,
                                 struct drm_file *file);
-struct virtio_gpu_object*
-virtio_gpu_alloc_object(struct drm_device *dev,
-                       struct virtio_gpu_object_params *params,
-                       struct virtio_gpu_fence *fence);
 int virtio_gpu_mode_dumb_create(struct drm_file *file_priv,
                                struct drm_device *dev,
                                struct drm_mode_create_dumb *args);
@@ -251,20 +241,35 @@ int virtio_gpu_mode_dumb_mmap(struct drm_file *file_priv,
                              struct drm_device *dev,
                              uint32_t handle, uint64_t *offset_p);
 
+struct virtio_gpu_object_array *virtio_gpu_array_alloc(u32 nents);
+struct virtio_gpu_object_array*
+virtio_gpu_array_from_handles(struct drm_file *drm_file, u32 *handles, u32 nents);
+void virtio_gpu_array_add_obj(struct virtio_gpu_object_array *objs,
+                             struct drm_gem_object *obj);
+int virtio_gpu_array_lock_resv(struct virtio_gpu_object_array *objs);
+void virtio_gpu_array_unlock_resv(struct virtio_gpu_object_array *objs);
+void virtio_gpu_array_add_fence(struct virtio_gpu_object_array *objs,
+                               struct dma_fence *fence);
+void virtio_gpu_array_put_free(struct virtio_gpu_object_array *objs);
+void virtio_gpu_array_put_free_delayed(struct virtio_gpu_device *vgdev,
+                                      struct virtio_gpu_object_array *objs);
+void virtio_gpu_array_put_free_work(struct work_struct *work);
+
 /* virtio vg */
 int virtio_gpu_alloc_vbufs(struct virtio_gpu_device *vgdev);
 void virtio_gpu_free_vbufs(struct virtio_gpu_device *vgdev);
 void virtio_gpu_cmd_create_resource(struct virtio_gpu_device *vgdev,
                                    struct virtio_gpu_object *bo,
                                    struct virtio_gpu_object_params *params,
+                                   struct virtio_gpu_object_array *objs,
                                    struct virtio_gpu_fence *fence);
 void virtio_gpu_cmd_unref_resource(struct virtio_gpu_device *vgdev,
                                   uint32_t resource_id);
 void virtio_gpu_cmd_transfer_to_host_2d(struct virtio_gpu_device *vgdev,
-                                       struct virtio_gpu_object *bo,
                                        uint64_t offset,
                                        __le32 width, __le32 height,
                                        __le32 x, __le32 y,
+                                       struct virtio_gpu_object_array *objs,
                                        struct virtio_gpu_fence *fence);
 void virtio_gpu_cmd_resource_flush(struct virtio_gpu_device *vgdev,
                                   uint32_t resource_id,
@@ -295,28 +300,32 @@ void virtio_gpu_cmd_context_destroy(struct virtio_gpu_device *vgdev,
                                    uint32_t id);
 void virtio_gpu_cmd_context_attach_resource(struct virtio_gpu_device *vgdev,
                                            uint32_t ctx_id,
-                                           uint32_t resource_id);
+                                           struct virtio_gpu_object_array *objs);
 void virtio_gpu_cmd_context_detach_resource(struct virtio_gpu_device *vgdev,
                                            uint32_t ctx_id,
-                                           uint32_t resource_id);
+                                           struct virtio_gpu_object_array *objs);
 void virtio_gpu_cmd_submit(struct virtio_gpu_device *vgdev,
                           void *data, uint32_t data_size,
-                          uint32_t ctx_id, struct virtio_gpu_fence *fence);
+                          uint32_t ctx_id,
+                          struct virtio_gpu_object_array *objs,
+                          struct virtio_gpu_fence *fence);
 void virtio_gpu_cmd_transfer_from_host_3d(struct virtio_gpu_device *vgdev,
-                                         uint32_t resource_id, uint32_t ctx_id,
+                                         uint32_t ctx_id,
                                          uint64_t offset, uint32_t level,
                                          struct virtio_gpu_box *box,
+                                         struct virtio_gpu_object_array *objs,
                                          struct virtio_gpu_fence *fence);
 void virtio_gpu_cmd_transfer_to_host_3d(struct virtio_gpu_device *vgdev,
-                                       struct virtio_gpu_object *bo,
                                        uint32_t ctx_id,
                                        uint64_t offset, uint32_t level,
                                        struct virtio_gpu_box *box,
+                                       struct virtio_gpu_object_array *objs,
                                        struct virtio_gpu_fence *fence);
 void
 virtio_gpu_cmd_resource_create_3d(struct virtio_gpu_device *vgdev,
                                  struct virtio_gpu_object *bo,
                                  struct virtio_gpu_object_params *params,
+                                 struct virtio_gpu_object_array *objs,
                                  struct virtio_gpu_fence *fence);
 void virtio_gpu_ctrl_ack(struct virtqueue *vq);
 void virtio_gpu_cursor_ack(struct virtqueue *vq);
@@ -339,11 +348,6 @@ struct drm_plane *virtio_gpu_plane_init(struct virtio_gpu_device *vgdev,
                                        enum drm_plane_type type,
                                        int index);
 
-/* virtio_gpu_ttm.c */
-int virtio_gpu_ttm_init(struct virtio_gpu_device *vgdev);
-void virtio_gpu_ttm_fini(struct virtio_gpu_device *vgdev);
-int virtio_gpu_mmap(struct file *filp, struct vm_area_struct *vma);
-
 /* virtio_gpu_fence.c */
 bool virtio_fence_signaled(struct dma_fence *f);
 struct virtio_gpu_fence *virtio_gpu_fence_alloc(
@@ -355,70 +359,21 @@ void virtio_gpu_fence_event_process(struct virtio_gpu_device *vdev,
                                    u64 last_seq);
 
 /* virtio_gpu_object */
+struct drm_gem_object *virtio_gpu_create_object(struct drm_device *dev,
+                                               size_t size);
 int virtio_gpu_object_create(struct virtio_gpu_device *vgdev,
                             struct virtio_gpu_object_params *params,
                             struct virtio_gpu_object **bo_ptr,
                             struct virtio_gpu_fence *fence);
-void virtio_gpu_object_kunmap(struct virtio_gpu_object *bo);
-int virtio_gpu_object_kmap(struct virtio_gpu_object *bo);
-int virtio_gpu_object_get_sg_table(struct virtio_gpu_device *qdev,
-                                  struct virtio_gpu_object *bo);
-void virtio_gpu_object_free_sg_table(struct virtio_gpu_object *bo);
-int virtio_gpu_object_wait(struct virtio_gpu_object *bo, bool no_wait);
 
 /* virtgpu_prime.c */
-struct sg_table *virtgpu_gem_prime_get_sg_table(struct drm_gem_object *obj);
 struct drm_gem_object *virtgpu_gem_prime_import_sg_table(
        struct drm_device *dev, struct dma_buf_attachment *attach,
        struct sg_table *sgt);
-void *virtgpu_gem_prime_vmap(struct drm_gem_object *obj);
-void virtgpu_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr);
-int virtgpu_gem_prime_mmap(struct drm_gem_object *obj,
-                          struct vm_area_struct *vma);
-
-static inline struct virtio_gpu_object*
-virtio_gpu_object_ref(struct virtio_gpu_object *bo)
-{
-       ttm_bo_get(&bo->tbo);
-       return bo;
-}
-
-static inline void virtio_gpu_object_unref(struct virtio_gpu_object **bo)
-{
-       struct ttm_buffer_object *tbo;
-
-       if ((*bo) == NULL)
-               return;
-       tbo = &((*bo)->tbo);
-       ttm_bo_put(tbo);
-       *bo = NULL;
-}
 
 static inline u64 virtio_gpu_object_mmap_offset(struct virtio_gpu_object *bo)
 {
-       return drm_vma_node_offset_addr(&bo->tbo.base.vma_node);
-}
-
-static inline int virtio_gpu_object_reserve(struct virtio_gpu_object *bo,
-                                        bool no_wait)
-{
-       int r;
-
-       r = ttm_bo_reserve(&bo->tbo, true, no_wait, NULL);
-       if (unlikely(r != 0)) {
-               if (r != -ERESTARTSYS) {
-                       struct virtio_gpu_device *qdev =
-                               bo->gem_base.dev->dev_private;
-                       dev_err(qdev->dev, "%p reserve failed\n", bo);
-               }
-               return r;
-       }
-       return 0;
-}
-
-static inline void virtio_gpu_object_unreserve(struct virtio_gpu_object *bo)
-{
-       ttm_bo_unreserve(&bo->tbo);
+       return drm_vma_node_offset_addr(&bo->base.base.vma_node);
 }
 
 /* virgl debufs */
index a0514f5bd0065a3ff293e0fd6994497cb49970e9..a4b9881ca1d399172135fd4c99726a1c9dd278ce 100644 (file)
@@ -41,6 +41,10 @@ bool virtio_fence_signaled(struct dma_fence *f)
 {
        struct virtio_gpu_fence *fence = to_virtio_fence(f);
 
+       if (WARN_ON_ONCE(fence->f.seqno == 0))
+               /* leaked fence outside driver before completing
+                * initialization with virtio_gpu_fence_emit */
+               return false;
        if (atomic64_read(&fence->drv->last_seq) >= fence->f.seqno)
                return true;
        return false;
index 292566146814b846f0574874071120dbb7274014..4c1f579edfb393daa43420a344587d357ac262c2 100644 (file)
 
 #include "virtgpu_drv.h"
 
-void virtio_gpu_gem_free_object(struct drm_gem_object *gem_obj)
-{
-       struct virtio_gpu_object *obj = gem_to_virtio_gpu_obj(gem_obj);
-
-       if (obj)
-               virtio_gpu_object_unref(&obj);
-}
-
-struct virtio_gpu_object*
-virtio_gpu_alloc_object(struct drm_device *dev,
-                       struct virtio_gpu_object_params *params,
-                       struct virtio_gpu_fence *fence)
-{
-       struct virtio_gpu_device *vgdev = dev->dev_private;
-       struct virtio_gpu_object *obj;
-       int ret;
-
-       ret = virtio_gpu_object_create(vgdev, params, &obj, fence);
-       if (ret)
-               return ERR_PTR(ret);
-
-       return obj;
-}
-
 int virtio_gpu_gem_create(struct drm_file *file,
                          struct drm_device *dev,
                          struct virtio_gpu_object_params *params,
                          struct drm_gem_object **obj_p,
                          uint32_t *handle_p)
 {
+       struct virtio_gpu_device *vgdev = dev->dev_private;
        struct virtio_gpu_object *obj;
        int ret;
        u32 handle;
 
-       obj = virtio_gpu_alloc_object(dev, params, NULL);
-       if (IS_ERR(obj))
-               return PTR_ERR(obj);
+       ret = virtio_gpu_object_create(vgdev, params, &obj, NULL);
+       if (ret < 0)
+               return ret;
 
-       ret = drm_gem_handle_create(file, &obj->gem_base, &handle);
+       ret = drm_gem_handle_create(file, &obj->base.base, &handle);
        if (ret) {
-               drm_gem_object_release(&obj->gem_base);
+               drm_gem_object_release(&obj->base.base);
                return ret;
        }
 
-       *obj_p = &obj->gem_base;
+       *obj_p = &obj->base.base;
 
        /* drop reference from allocate - handle holds it now */
-       drm_gem_object_put_unlocked(&obj->gem_base);
+       drm_gem_object_put_unlocked(&obj->base.base);
 
        *handle_p = handle;
        return 0;
@@ -136,19 +113,18 @@ int virtio_gpu_gem_object_open(struct drm_gem_object *obj,
 {
        struct virtio_gpu_device *vgdev = obj->dev->dev_private;
        struct virtio_gpu_fpriv *vfpriv = file->driver_priv;
-       struct virtio_gpu_object *qobj = gem_to_virtio_gpu_obj(obj);
-       int r;
+       struct virtio_gpu_object_array *objs;
 
        if (!vgdev->has_virgl_3d)
                return 0;
 
-       r = virtio_gpu_object_reserve(qobj, false);
-       if (r)
-               return r;
+       objs = virtio_gpu_array_alloc(1);
+       if (!objs)
+               return -ENOMEM;
+       virtio_gpu_array_add_obj(objs, obj);
 
        virtio_gpu_cmd_context_attach_resource(vgdev, vfpriv->ctx_id,
-                                              qobj->hw_res_handle);
-       virtio_gpu_object_unreserve(qobj);
+                                              objs);
        return 0;
 }
 
@@ -157,17 +133,136 @@ void virtio_gpu_gem_object_close(struct drm_gem_object *obj,
 {
        struct virtio_gpu_device *vgdev = obj->dev->dev_private;
        struct virtio_gpu_fpriv *vfpriv = file->driver_priv;
-       struct virtio_gpu_object *qobj = gem_to_virtio_gpu_obj(obj);
-       int r;
+       struct virtio_gpu_object_array *objs;
 
        if (!vgdev->has_virgl_3d)
                return;
 
-       r = virtio_gpu_object_reserve(qobj, false);
-       if (r)
+       objs = virtio_gpu_array_alloc(1);
+       if (!objs)
                return;
+       virtio_gpu_array_add_obj(objs, obj);
 
        virtio_gpu_cmd_context_detach_resource(vgdev, vfpriv->ctx_id,
-                                               qobj->hw_res_handle);
-       virtio_gpu_object_unreserve(qobj);
+                                              objs);
+}
+
+struct virtio_gpu_object_array *virtio_gpu_array_alloc(u32 nents)
+{
+       struct virtio_gpu_object_array *objs;
+       size_t size = sizeof(*objs) + sizeof(objs->objs[0]) * nents;
+
+       objs = kmalloc(size, GFP_KERNEL);
+       if (!objs)
+               return NULL;
+
+       objs->nents = 0;
+       objs->total = nents;
+       return objs;
+}
+
+static void virtio_gpu_array_free(struct virtio_gpu_object_array *objs)
+{
+       kfree(objs);
+}
+
+struct virtio_gpu_object_array*
+virtio_gpu_array_from_handles(struct drm_file *drm_file, u32 *handles, u32 nents)
+{
+       struct virtio_gpu_object_array *objs;
+       u32 i;
+
+       objs = virtio_gpu_array_alloc(nents);
+       if (!objs)
+               return NULL;
+
+       for (i = 0; i < nents; i++) {
+               objs->objs[i] = drm_gem_object_lookup(drm_file, handles[i]);
+               if (!objs->objs[i]) {
+                       objs->nents = i;
+                       virtio_gpu_array_put_free(objs);
+                       return NULL;
+               }
+       }
+       objs->nents = i;
+       return objs;
+}
+
+void virtio_gpu_array_add_obj(struct virtio_gpu_object_array *objs,
+                             struct drm_gem_object *obj)
+{
+       if (WARN_ON_ONCE(objs->nents == objs->total))
+               return;
+
+       drm_gem_object_get(obj);
+       objs->objs[objs->nents] = obj;
+       objs->nents++;
+}
+
+int virtio_gpu_array_lock_resv(struct virtio_gpu_object_array *objs)
+{
+       int ret;
+
+       if (objs->nents == 1) {
+               ret = dma_resv_lock_interruptible(objs->objs[0]->resv, NULL);
+       } else {
+               ret = drm_gem_lock_reservations(objs->objs, objs->nents,
+                                               &objs->ticket);
+       }
+       return ret;
+}
+
+void virtio_gpu_array_unlock_resv(struct virtio_gpu_object_array *objs)
+{
+       if (objs->nents == 1) {
+               dma_resv_unlock(objs->objs[0]->resv);
+       } else {
+               drm_gem_unlock_reservations(objs->objs, objs->nents,
+                                           &objs->ticket);
+       }
+}
+
+void virtio_gpu_array_add_fence(struct virtio_gpu_object_array *objs,
+                               struct dma_fence *fence)
+{
+       int i;
+
+       for (i = 0; i < objs->nents; i++)
+               dma_resv_add_excl_fence(objs->objs[i]->resv, fence);
+}
+
+void virtio_gpu_array_put_free(struct virtio_gpu_object_array *objs)
+{
+       u32 i;
+
+       for (i = 0; i < objs->nents; i++)
+               drm_gem_object_put_unlocked(objs->objs[i]);
+       virtio_gpu_array_free(objs);
+}
+
+void virtio_gpu_array_put_free_delayed(struct virtio_gpu_device *vgdev,
+                                      struct virtio_gpu_object_array *objs)
+{
+       spin_lock(&vgdev->obj_free_lock);
+       list_add_tail(&objs->next, &vgdev->obj_free_list);
+       spin_unlock(&vgdev->obj_free_lock);
+       schedule_work(&vgdev->obj_free_work);
+}
+
+void virtio_gpu_array_put_free_work(struct work_struct *work)
+{
+       struct virtio_gpu_device *vgdev =
+               container_of(work, struct virtio_gpu_device, obj_free_work);
+       struct virtio_gpu_object_array *objs;
+
+       spin_lock(&vgdev->obj_free_lock);
+       while (!list_empty(&vgdev->obj_free_list)) {
+               objs = list_first_entry(&vgdev->obj_free_list,
+                                       struct virtio_gpu_object_array, next);
+               list_del(&objs->next);
+               spin_unlock(&vgdev->obj_free_lock);
+               virtio_gpu_array_put_free(objs);
+               spin_lock(&vgdev->obj_free_lock);
+       }
+       spin_unlock(&vgdev->obj_free_lock);
 }
index 0a88ef11b9d3fd1218c15f3cf9f8a44c4894f4bc..9af1ec62434f2fce430308b30c68e094108cba98 100644 (file)
@@ -29,7 +29,6 @@
 #include <linux/sync_file.h>
 
 #include <drm/drm_file.h>
-#include <drm/ttm/ttm_execbuf_util.h>
 #include <drm/virtgpu_drm.h>
 
 #include "virtgpu_drv.h"
@@ -56,45 +55,6 @@ static int virtio_gpu_map_ioctl(struct drm_device *dev, void *data,
                                         &virtio_gpu_map->offset);
 }
 
-int virtio_gpu_object_list_validate(struct ww_acquire_ctx *ticket,
-                                   struct list_head *head)
-{
-       struct ttm_operation_ctx ctx = { false, false };
-       struct ttm_validate_buffer *buf;
-       struct ttm_buffer_object *bo;
-       struct virtio_gpu_object *qobj;
-       int ret;
-
-       ret = ttm_eu_reserve_buffers(ticket, head, true, NULL, true);
-       if (ret != 0)
-               return ret;
-
-       list_for_each_entry(buf, head, head) {
-               bo = buf->bo;
-               qobj = container_of(bo, struct virtio_gpu_object, tbo);
-               ret = ttm_bo_validate(bo, &qobj->placement, &ctx);
-               if (ret) {
-                       ttm_eu_backoff_reservation(ticket, head);
-                       return ret;
-               }
-       }
-       return 0;
-}
-
-void virtio_gpu_unref_list(struct list_head *head)
-{
-       struct ttm_validate_buffer *buf;
-       struct ttm_buffer_object *bo;
-       struct virtio_gpu_object *qobj;
-
-       list_for_each_entry(buf, head, head) {
-               bo = buf->bo;
-               qobj = container_of(bo, struct virtio_gpu_object, tbo);
-
-               drm_gem_object_put_unlocked(&qobj->gem_base);
-       }
-}
-
 /*
  * Usage of execbuffer:
  * Relocations need to take into account the full VIRTIO_GPUDrawable size.
@@ -107,16 +67,11 @@ static int virtio_gpu_execbuffer_ioctl(struct drm_device *dev, void *data,
        struct drm_virtgpu_execbuffer *exbuf = data;
        struct virtio_gpu_device *vgdev = dev->dev_private;
        struct virtio_gpu_fpriv *vfpriv = drm_file->driver_priv;
-       struct drm_gem_object *gobj;
        struct virtio_gpu_fence *out_fence;
-       struct virtio_gpu_object *qobj;
        int ret;
        uint32_t *bo_handles = NULL;
        void __user *user_bo_handles = NULL;
-       struct list_head validate_list;
-       struct ttm_validate_buffer *buflist = NULL;
-       int i;
-       struct ww_acquire_ctx ticket;
+       struct virtio_gpu_object_array *buflist = NULL;
        struct sync_file *sync_file;
        int in_fence_fd = exbuf->fence_fd;
        int out_fence_fd = -1;
@@ -157,15 +112,10 @@ static int virtio_gpu_execbuffer_ioctl(struct drm_device *dev, void *data,
                        return out_fence_fd;
        }
 
-       INIT_LIST_HEAD(&validate_list);
        if (exbuf->num_bo_handles) {
-
                bo_handles = kvmalloc_array(exbuf->num_bo_handles,
-                                          sizeof(uint32_t), GFP_KERNEL);
-               buflist = kvmalloc_array(exbuf->num_bo_handles,
-                                          sizeof(struct ttm_validate_buffer),
-                                          GFP_KERNEL | __GFP_ZERO);
-               if (!bo_handles || !buflist) {
+                                           sizeof(uint32_t), GFP_KERNEL);
+               if (!bo_handles) {
                        ret = -ENOMEM;
                        goto out_unused_fd;
                }
@@ -177,27 +127,23 @@ static int virtio_gpu_execbuffer_ioctl(struct drm_device *dev, void *data,
                        goto out_unused_fd;
                }
 
-               for (i = 0; i < exbuf->num_bo_handles; i++) {
-                       gobj = drm_gem_object_lookup(drm_file, bo_handles[i]);
-                       if (!gobj) {
-                               ret = -ENOENT;
-                               goto out_unused_fd;
-                       }
-
-                       qobj = gem_to_virtio_gpu_obj(gobj);
-                       buflist[i].bo = &qobj->tbo;
-
-                       list_add(&buflist[i].head, &validate_list);
+               buflist = virtio_gpu_array_from_handles(drm_file, bo_handles,
+                                                       exbuf->num_bo_handles);
+               if (!buflist) {
+                       ret = -ENOENT;
+                       goto out_unused_fd;
                }
                kvfree(bo_handles);
                bo_handles = NULL;
        }
 
-       ret = virtio_gpu_object_list_validate(&ticket, &validate_list);
-       if (ret)
-               goto out_free;
+       if (buflist) {
+               ret = virtio_gpu_array_lock_resv(buflist);
+               if (ret)
+                       goto out_unused_fd;
+       }
 
-       buf = memdup_user(u64_to_user_ptr(exbuf->command), exbuf->size);
+       buf = vmemdup_user(u64_to_user_ptr(exbuf->command), exbuf->size);
        if (IS_ERR(buf)) {
                ret = PTR_ERR(buf);
                goto out_unresv;
@@ -222,24 +168,18 @@ static int virtio_gpu_execbuffer_ioctl(struct drm_device *dev, void *data,
        }
 
        virtio_gpu_cmd_submit(vgdev, buf, exbuf->size,
-                             vfpriv->ctx_id, out_fence);
-
-       ttm_eu_fence_buffer_objects(&ticket, &validate_list, &out_fence->f);
-
-       /* fence the command bo */
-       virtio_gpu_unref_list(&validate_list);
-       kvfree(buflist);
+                             vfpriv->ctx_id, buflist, out_fence);
        return 0;
 
 out_memdup:
-       kfree(buf);
+       kvfree(buf);
 out_unresv:
-       ttm_eu_backoff_reservation(&ticket, &validate_list);
-out_free:
-       virtio_gpu_unref_list(&validate_list);
+       if (buflist)
+               virtio_gpu_array_unlock_resv(buflist);
 out_unused_fd:
        kvfree(bo_handles);
-       kvfree(buflist);
+       if (buflist)
+               virtio_gpu_array_put_free(buflist);
 
        if (out_fence_fd >= 0)
                put_unused_fd(out_fence_fd);
@@ -316,11 +256,11 @@ static int virtio_gpu_resource_create_ioctl(struct drm_device *dev, void *data,
        fence = virtio_gpu_fence_alloc(vgdev);
        if (!fence)
                return -ENOMEM;
-       qobj = virtio_gpu_alloc_object(dev, &params, fence);
+       ret = virtio_gpu_object_create(vgdev, &params, &qobj, fence);
        dma_fence_put(&fence->f);
-       if (IS_ERR(qobj))
-               return PTR_ERR(qobj);
-       obj = &qobj->gem_base;
+       if (ret < 0)
+               return ret;
+       obj = &qobj->base.base;
 
        ret = drm_gem_handle_create(file_priv, obj, &handle);
        if (ret) {
@@ -347,7 +287,7 @@ static int virtio_gpu_resource_info_ioctl(struct drm_device *dev, void *data,
 
        qobj = gem_to_virtio_gpu_obj(gobj);
 
-       ri->size = qobj->gem_base.size;
+       ri->size = qobj->base.base.size;
        ri->res_handle = qobj->hw_res_handle;
        drm_gem_object_put_unlocked(gobj);
        return 0;
@@ -360,9 +300,7 @@ static int virtio_gpu_transfer_from_host_ioctl(struct drm_device *dev,
        struct virtio_gpu_device *vgdev = dev->dev_private;
        struct virtio_gpu_fpriv *vfpriv = file->driver_priv;
        struct drm_virtgpu_3d_transfer_from_host *args = data;
-       struct ttm_operation_ctx ctx = { true, false };
-       struct drm_gem_object *gobj = NULL;
-       struct virtio_gpu_object *qobj = NULL;
+       struct virtio_gpu_object_array *objs;
        struct virtio_gpu_fence *fence;
        int ret;
        u32 offset = args->offset;
@@ -371,39 +309,31 @@ static int virtio_gpu_transfer_from_host_ioctl(struct drm_device *dev,
        if (vgdev->has_virgl_3d == false)
                return -ENOSYS;
 
-       gobj = drm_gem_object_lookup(file, args->bo_handle);
-       if (gobj == NULL)
+       objs = virtio_gpu_array_from_handles(file, &args->bo_handle, 1);
+       if (objs == NULL)
                return -ENOENT;
 
-       qobj = gem_to_virtio_gpu_obj(gobj);
-
-       ret = virtio_gpu_object_reserve(qobj, false);
-       if (ret)
-               goto out;
-
-       ret = ttm_bo_validate(&qobj->tbo, &qobj->placement, &ctx);
-       if (unlikely(ret))
-               goto out_unres;
+       ret = virtio_gpu_array_lock_resv(objs);
+       if (ret != 0)
+               goto err_put_free;
 
        convert_to_hw_box(&box, &args->box);
 
        fence = virtio_gpu_fence_alloc(vgdev);
        if (!fence) {
                ret = -ENOMEM;
-               goto out_unres;
+               goto err_unlock;
        }
        virtio_gpu_cmd_transfer_from_host_3d
-               (vgdev, qobj->hw_res_handle,
-                vfpriv->ctx_id, offset, args->level,
-                &box, fence);
-       dma_resv_add_excl_fence(qobj->tbo.base.resv,
-                                         &fence->f);
-
+               (vgdev, vfpriv->ctx_id, offset, args->level,
+                &box, objs, fence);
        dma_fence_put(&fence->f);
-out_unres:
-       virtio_gpu_object_unreserve(qobj);
-out:
-       drm_gem_object_put_unlocked(gobj);
+       return 0;
+
+err_unlock:
+       virtio_gpu_array_unlock_resv(objs);
+err_put_free:
+       virtio_gpu_array_put_free(objs);
        return ret;
 }
 
@@ -413,75 +343,71 @@ static int virtio_gpu_transfer_to_host_ioctl(struct drm_device *dev, void *data,
        struct virtio_gpu_device *vgdev = dev->dev_private;
        struct virtio_gpu_fpriv *vfpriv = file->driver_priv;
        struct drm_virtgpu_3d_transfer_to_host *args = data;
-       struct ttm_operation_ctx ctx = { true, false };
-       struct drm_gem_object *gobj = NULL;
-       struct virtio_gpu_object *qobj = NULL;
+       struct virtio_gpu_object_array *objs;
        struct virtio_gpu_fence *fence;
        struct virtio_gpu_box box;
        int ret;
        u32 offset = args->offset;
 
-       gobj = drm_gem_object_lookup(file, args->bo_handle);
-       if (gobj == NULL)
+       objs = virtio_gpu_array_from_handles(file, &args->bo_handle, 1);
+       if (objs == NULL)
                return -ENOENT;
 
-       qobj = gem_to_virtio_gpu_obj(gobj);
-
-       ret = virtio_gpu_object_reserve(qobj, false);
-       if (ret)
-               goto out;
-
-       ret = ttm_bo_validate(&qobj->tbo, &qobj->placement, &ctx);
-       if (unlikely(ret))
-               goto out_unres;
-
        convert_to_hw_box(&box, &args->box);
        if (!vgdev->has_virgl_3d) {
                virtio_gpu_cmd_transfer_to_host_2d
-                       (vgdev, qobj, offset,
-                        box.w, box.h, box.x, box.y, NULL);
+                       (vgdev, offset,
+                        box.w, box.h, box.x, box.y,
+                        objs, NULL);
        } else {
+               ret = virtio_gpu_array_lock_resv(objs);
+               if (ret != 0)
+                       goto err_put_free;
+
+               ret = -ENOMEM;
                fence = virtio_gpu_fence_alloc(vgdev);
-               if (!fence) {
-                       ret = -ENOMEM;
-                       goto out_unres;
-               }
+               if (!fence)
+                       goto err_unlock;
+
                virtio_gpu_cmd_transfer_to_host_3d
-                       (vgdev, qobj,
+                       (vgdev,
                         vfpriv ? vfpriv->ctx_id : 0, offset,
-                        args->level, &box, fence);
-               dma_resv_add_excl_fence(qobj->tbo.base.resv,
-                                                 &fence->f);
+                        args->level, &box, objs, fence);
                dma_fence_put(&fence->f);
        }
+       return 0;
 
-out_unres:
-       virtio_gpu_object_unreserve(qobj);
-out:
-       drm_gem_object_put_unlocked(gobj);
+err_unlock:
+       virtio_gpu_array_unlock_resv(objs);
+err_put_free:
+       virtio_gpu_array_put_free(objs);
        return ret;
 }
 
 static int virtio_gpu_wait_ioctl(struct drm_device *dev, void *data,
-                           struct drm_file *file)
+                                struct drm_file *file)
 {
        struct drm_virtgpu_3d_wait *args = data;
-       struct drm_gem_object *gobj = NULL;
-       struct virtio_gpu_object *qobj = NULL;
+       struct drm_gem_object *obj;
+       long timeout = 15 * HZ;
        int ret;
-       bool nowait = false;
 
-       gobj = drm_gem_object_lookup(file, args->handle);
-       if (gobj == NULL)
+       obj = drm_gem_object_lookup(file, args->handle);
+       if (obj == NULL)
                return -ENOENT;
 
-       qobj = gem_to_virtio_gpu_obj(gobj);
-
-       if (args->flags & VIRTGPU_WAIT_NOWAIT)
-               nowait = true;
-       ret = virtio_gpu_object_wait(qobj, nowait);
+       if (args->flags & VIRTGPU_WAIT_NOWAIT) {
+               ret = dma_resv_test_signaled_rcu(obj->resv, true);
+       } else {
+               ret = dma_resv_wait_timeout_rcu(obj->resv, true, true,
+                                               timeout);
+       }
+       if (ret == 0)
+               ret = -EBUSY;
+       else if (ret > 0)
+               ret = 0;
 
-       drm_gem_object_put_unlocked(gobj);
+       drm_gem_object_put_unlocked(obj);
        return ret;
 }
 
index c190702fab72642de0af57e9f1a257445c90cbef..0b3cdb0d83b0da22600e71dc6a46617bbfea7150 100644 (file)
@@ -147,6 +147,11 @@ int virtio_gpu_init(struct drm_device *dev)
        INIT_WORK(&vgdev->config_changed_work,
                  virtio_gpu_config_changed_work_func);
 
+       INIT_WORK(&vgdev->obj_free_work,
+                 virtio_gpu_array_put_free_work);
+       INIT_LIST_HEAD(&vgdev->obj_free_list);
+       spin_lock_init(&vgdev->obj_free_lock);
+
 #ifdef __LITTLE_ENDIAN
        if (virtio_has_feature(vgdev->vdev, VIRTIO_GPU_F_VIRGL))
                vgdev->has_virgl_3d = true;
@@ -173,12 +178,6 @@ int virtio_gpu_init(struct drm_device *dev)
                goto err_vbufs;
        }
 
-       ret = virtio_gpu_ttm_init(vgdev);
-       if (ret) {
-               DRM_ERROR("failed to init ttm %d\n", ret);
-               goto err_ttm;
-       }
-
        /* get display info */
        virtio_cread(vgdev->vdev, struct virtio_gpu_config,
                     num_scanouts, &num_scanouts);
@@ -210,8 +209,6 @@ int virtio_gpu_init(struct drm_device *dev)
        return 0;
 
 err_scanouts:
-       virtio_gpu_ttm_fini(vgdev);
-err_ttm:
        virtio_gpu_free_vbufs(vgdev);
 err_vbufs:
        vgdev->vdev->config->del_vqs(vgdev->vdev);
@@ -234,6 +231,7 @@ void virtio_gpu_deinit(struct drm_device *dev)
 {
        struct virtio_gpu_device *vgdev = dev->dev_private;
 
+       flush_work(&vgdev->obj_free_work);
        vgdev->vqs_ready = false;
        flush_work(&vgdev->ctrlq.dequeue_work);
        flush_work(&vgdev->cursorq.dequeue_work);
@@ -242,7 +240,6 @@ void virtio_gpu_deinit(struct drm_device *dev)
        vgdev->vdev->config->del_vqs(vgdev->vdev);
 
        virtio_gpu_modeset_fini(vgdev);
-       virtio_gpu_ttm_fini(vgdev);
        virtio_gpu_free_vbufs(vgdev);
        virtio_gpu_cleanup_cap_cache(vgdev);
        kfree(vgdev->capsets);
index 09b526518f5a64b75288cc5738ae9ad7e6d0ff12..69a3d310ff702448710ae6404c540da431513f0c 100644 (file)
  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  */
 
-#include <drm/ttm/ttm_execbuf_util.h>
+#include <linux/moduleparam.h>
 
 #include "virtgpu_drv.h"
 
+static int virtio_gpu_virglrenderer_workaround = 1;
+module_param_named(virglhack, virtio_gpu_virglrenderer_workaround, int, 0400);
+
 static int virtio_gpu_resource_id_get(struct virtio_gpu_device *vgdev,
                                       uint32_t *resid)
 {
-#if 0
-       int handle = ida_alloc(&vgdev->resource_ida, GFP_KERNEL);
-
-       if (handle < 0)
-               return handle;
-#else
-       static int handle;
-
-       /*
-        * FIXME: dirty hack to avoid re-using IDs, virglrenderer
-        * can't deal with that.  Needs fixing in virglrenderer, also
-        * should figure a better way to handle that in the guest.
-        */
-       handle++;
-#endif
-
-       *resid = handle + 1;
+       if (virtio_gpu_virglrenderer_workaround) {
+               /*
+                * Hack to avoid re-using resource IDs.
+                *
+                * virglrenderer versions up to (and including) 0.7.0
+                * can't deal with that.  virglrenderer commit
+                * "f91a9dd35715 Fix unlinking resources from hash
+                * table." (Feb 2019) fixes the bug.
+                */
+               static int handle;
+               handle++;
+               *resid = handle + 1;
+       } else {
+               int handle = ida_alloc(&vgdev->resource_ida, GFP_KERNEL);
+               if (handle < 0)
+                       return handle;
+               *resid = handle + 1;
+       }
        return 0;
 }
 
 static void virtio_gpu_resource_id_put(struct virtio_gpu_device *vgdev, uint32_t id)
 {
-#if 0
-       ida_free(&vgdev->resource_ida, id - 1);
-#endif
+       if (!virtio_gpu_virglrenderer_workaround) {
+               ida_free(&vgdev->resource_ida, id - 1);
+       }
 }
 
-static void virtio_gpu_ttm_bo_destroy(struct ttm_buffer_object *tbo)
+static void virtio_gpu_free_object(struct drm_gem_object *obj)
 {
-       struct virtio_gpu_object *bo;
-       struct virtio_gpu_device *vgdev;
-
-       bo = container_of(tbo, struct virtio_gpu_object, tbo);
-       vgdev = (struct virtio_gpu_device *)bo->gem_base.dev->dev_private;
+       struct virtio_gpu_object *bo = gem_to_virtio_gpu_obj(obj);
+       struct virtio_gpu_device *vgdev = bo->base.base.dev->dev_private;
 
+       if (bo->pages)
+               virtio_gpu_object_detach(vgdev, bo);
        if (bo->created)
                virtio_gpu_cmd_unref_resource(vgdev, bo->hw_res_handle);
-       if (bo->pages)
-               virtio_gpu_object_free_sg_table(bo);
-       if (bo->vmap)
-               virtio_gpu_object_kunmap(bo);
-       drm_gem_object_release(&bo->gem_base);
        virtio_gpu_resource_id_put(vgdev, bo->hw_res_handle);
-       kfree(bo);
+
+       drm_gem_shmem_free_object(obj);
 }
 
-static void virtio_gpu_init_ttm_placement(struct virtio_gpu_object *vgbo)
+static const struct drm_gem_object_funcs virtio_gpu_gem_funcs = {
+       .free = virtio_gpu_free_object,
+       .open = virtio_gpu_gem_object_open,
+       .close = virtio_gpu_gem_object_close,
+
+       .print_info = drm_gem_shmem_print_info,
+       .pin = drm_gem_shmem_pin,
+       .unpin = drm_gem_shmem_unpin,
+       .get_sg_table = drm_gem_shmem_get_sg_table,
+       .vmap = drm_gem_shmem_vmap,
+       .vunmap = drm_gem_shmem_vunmap,
+       .vm_ops = &drm_gem_shmem_vm_ops,
+};
+
+struct drm_gem_object *virtio_gpu_create_object(struct drm_device *dev,
+                                               size_t size)
 {
-       u32 c = 1;
-
-       vgbo->placement.placement = &vgbo->placement_code;
-       vgbo->placement.busy_placement = &vgbo->placement_code;
-       vgbo->placement_code.fpfn = 0;
-       vgbo->placement_code.lpfn = 0;
-       vgbo->placement_code.flags =
-               TTM_PL_MASK_CACHING | TTM_PL_FLAG_TT |
-               TTM_PL_FLAG_NO_EVICT;
-       vgbo->placement.num_placement = c;
-       vgbo->placement.num_busy_placement = c;
+       struct virtio_gpu_object *bo;
+
+       bo = kzalloc(sizeof(*bo), GFP_KERNEL);
+       if (!bo)
+               return NULL;
 
+       bo->base.base.funcs = &virtio_gpu_gem_funcs;
+       return &bo->base.base;
 }
 
 int virtio_gpu_object_create(struct virtio_gpu_device *vgdev,
@@ -97,157 +107,59 @@ int virtio_gpu_object_create(struct virtio_gpu_device *vgdev,
                             struct virtio_gpu_object **bo_ptr,
                             struct virtio_gpu_fence *fence)
 {
+       struct virtio_gpu_object_array *objs = NULL;
+       struct drm_gem_shmem_object *shmem_obj;
        struct virtio_gpu_object *bo;
-       size_t acc_size;
        int ret;
 
        *bo_ptr = NULL;
 
-       acc_size = ttm_bo_dma_acc_size(&vgdev->mman.bdev, params->size,
-                                      sizeof(struct virtio_gpu_object));
+       params->size = roundup(params->size, PAGE_SIZE);
+       shmem_obj = drm_gem_shmem_create(vgdev->ddev, params->size);
+       if (IS_ERR(shmem_obj))
+               return PTR_ERR(shmem_obj);
+       bo = gem_to_virtio_gpu_obj(&shmem_obj->base);
 
-       bo = kzalloc(sizeof(struct virtio_gpu_object), GFP_KERNEL);
-       if (bo == NULL)
-               return -ENOMEM;
        ret = virtio_gpu_resource_id_get(vgdev, &bo->hw_res_handle);
-       if (ret < 0) {
-               kfree(bo);
-               return ret;
-       }
-       params->size = roundup(params->size, PAGE_SIZE);
-       ret = drm_gem_object_init(vgdev->ddev, &bo->gem_base, params->size);
-       if (ret != 0) {
-               virtio_gpu_resource_id_put(vgdev, bo->hw_res_handle);
-               kfree(bo);
-               return ret;
-       }
+       if (ret < 0)
+               goto err_free_gem;
+
        bo->dumb = params->dumb;
 
+       if (fence) {
+               ret = -ENOMEM;
+               objs = virtio_gpu_array_alloc(1);
+               if (!objs)
+                       goto err_put_id;
+               virtio_gpu_array_add_obj(objs, &bo->base.base);
+
+               ret = virtio_gpu_array_lock_resv(objs);
+               if (ret != 0)
+                       goto err_put_objs;
+       }
+
        if (params->virgl) {
-               virtio_gpu_cmd_resource_create_3d(vgdev, bo, params, fence);
+               virtio_gpu_cmd_resource_create_3d(vgdev, bo, params,
+                                                 objs, fence);
        } else {
-               virtio_gpu_cmd_create_resource(vgdev, bo, params, fence);
+               virtio_gpu_cmd_create_resource(vgdev, bo, params,
+                                              objs, fence);
        }
 
-       virtio_gpu_init_ttm_placement(bo);
-       ret = ttm_bo_init(&vgdev->mman.bdev, &bo->tbo, params->size,
-                         ttm_bo_type_device, &bo->placement, 0,
-                         true, acc_size, NULL, NULL,
-                         &virtio_gpu_ttm_bo_destroy);
-       /* ttm_bo_init failure will call the destroy */
-       if (ret != 0)
+       ret = virtio_gpu_object_attach(vgdev, bo, NULL);
+       if (ret != 0) {
+               virtio_gpu_free_object(&shmem_obj->base);
                return ret;
-
-       if (fence) {
-               struct virtio_gpu_fence_driver *drv = &vgdev->fence_drv;
-               struct list_head validate_list;
-               struct ttm_validate_buffer mainbuf;
-               struct ww_acquire_ctx ticket;
-               unsigned long irq_flags;
-               bool signaled;
-
-               INIT_LIST_HEAD(&validate_list);
-               memset(&mainbuf, 0, sizeof(struct ttm_validate_buffer));
-
-               /* use a gem reference since unref list undoes them */
-               drm_gem_object_get(&bo->gem_base);
-               mainbuf.bo = &bo->tbo;
-               list_add(&mainbuf.head, &validate_list);
-
-               ret = virtio_gpu_object_list_validate(&ticket, &validate_list);
-               if (ret == 0) {
-                       spin_lock_irqsave(&drv->lock, irq_flags);
-                       signaled = virtio_fence_signaled(&fence->f);
-                       if (!signaled)
-                               /* virtio create command still in flight */
-                               ttm_eu_fence_buffer_objects(&ticket, &validate_list,
-                                                           &fence->f);
-                       spin_unlock_irqrestore(&drv->lock, irq_flags);
-                       if (signaled)
-                               /* virtio create command finished */
-                               ttm_eu_backoff_reservation(&ticket, &validate_list);
-               }
-               virtio_gpu_unref_list(&validate_list);
        }
 
        *bo_ptr = bo;
        return 0;
-}
-
-void virtio_gpu_object_kunmap(struct virtio_gpu_object *bo)
-{
-       bo->vmap = NULL;
-       ttm_bo_kunmap(&bo->kmap);
-}
-
-int virtio_gpu_object_kmap(struct virtio_gpu_object *bo)
-{
-       bool is_iomem;
-       int r;
-
-       WARN_ON(bo->vmap);
-
-       r = ttm_bo_kmap(&bo->tbo, 0, bo->tbo.num_pages, &bo->kmap);
-       if (r)
-               return r;
-       bo->vmap = ttm_kmap_obj_virtual(&bo->kmap, &is_iomem);
-       return 0;
-}
 
-int virtio_gpu_object_get_sg_table(struct virtio_gpu_device *qdev,
-                                  struct virtio_gpu_object *bo)
-{
-       int ret;
-       struct page **pages = bo->tbo.ttm->pages;
-       int nr_pages = bo->tbo.num_pages;
-       struct ttm_operation_ctx ctx = {
-               .interruptible = false,
-               .no_wait_gpu = false
-       };
-       size_t max_segment;
-
-       /* wtf swapping */
-       if (bo->pages)
-               return 0;
-
-       if (bo->tbo.ttm->state == tt_unpopulated)
-               bo->tbo.ttm->bdev->driver->ttm_tt_populate(bo->tbo.ttm, &ctx);
-       bo->pages = kmalloc(sizeof(struct sg_table), GFP_KERNEL);
-       if (!bo->pages)
-               goto out;
-
-       max_segment = virtio_max_dma_size(qdev->vdev);
-       max_segment &= PAGE_MASK;
-       if (max_segment > SCATTERLIST_MAX_SEGMENT)
-               max_segment = SCATTERLIST_MAX_SEGMENT;
-       ret = __sg_alloc_table_from_pages(bo->pages, pages, nr_pages, 0,
-                                         nr_pages << PAGE_SHIFT,
-                                         max_segment, GFP_KERNEL);
-       if (ret)
-               goto out;
-       return 0;
-out:
-       kfree(bo->pages);
-       bo->pages = NULL;
-       return -ENOMEM;
-}
-
-void virtio_gpu_object_free_sg_table(struct virtio_gpu_object *bo)
-{
-       sg_free_table(bo->pages);
-       kfree(bo->pages);
-       bo->pages = NULL;
-}
-
-int virtio_gpu_object_wait(struct virtio_gpu_object *bo, bool no_wait)
-{
-       int r;
-
-       r = ttm_bo_reserve(&bo->tbo, true, no_wait, NULL);
-       if (unlikely(r != 0))
-               return r;
-       r = ttm_bo_wait(&bo->tbo, true, no_wait);
-       ttm_bo_unreserve(&bo->tbo);
-       return r;
+err_put_objs:
+       virtio_gpu_array_put_free(objs);
+err_put_id:
+       virtio_gpu_resource_id_put(vgdev, bo->hw_res_handle);
+err_free_gem:
+       drm_gem_shmem_free_object(&shmem_obj->base);
+       return ret;
 }
-
index a492ac3f4a7e14d8c7460af836ebd9ddf27e74cc..f4b7360282ce91d589198234df968d7bb237ae51 100644 (file)
@@ -84,7 +84,22 @@ static const struct drm_plane_funcs virtio_gpu_plane_funcs = {
 static int virtio_gpu_plane_atomic_check(struct drm_plane *plane,
                                         struct drm_plane_state *state)
 {
-       return 0;
+       bool is_cursor = plane->type == DRM_PLANE_TYPE_CURSOR;
+       struct drm_crtc_state *crtc_state;
+       int ret;
+
+       if (!state->fb || !state->crtc)
+               return 0;
+
+       crtc_state = drm_atomic_get_crtc_state(state->state, state->crtc);
+       if (IS_ERR(crtc_state))
+                return PTR_ERR(crtc_state);
+
+       ret = drm_atomic_helper_check_plane_state(state, crtc_state,
+                                                 DRM_PLANE_HELPER_NO_SCALING,
+                                                 DRM_PLANE_HELPER_NO_SCALING,
+                                                 is_cursor, true);
+       return ret;
 }
 
 static void virtio_gpu_primary_plane_update(struct drm_plane *plane,
@@ -109,12 +124,19 @@ static void virtio_gpu_primary_plane_update(struct drm_plane *plane,
                bo = gem_to_virtio_gpu_obj(vgfb->base.obj[0]);
                handle = bo->hw_res_handle;
                if (bo->dumb) {
+                       struct virtio_gpu_object_array *objs;
+
+                       objs = virtio_gpu_array_alloc(1);
+                       if (!objs)
+                               return;
+                       virtio_gpu_array_add_obj(objs, vgfb->base.obj[0]);
                        virtio_gpu_cmd_transfer_to_host_2d
-                               (vgdev, bo, 0,
+                               (vgdev, 0,
                                 cpu_to_le32(plane->state->src_w >> 16),
                                 cpu_to_le32(plane->state->src_h >> 16),
                                 cpu_to_le32(plane->state->src_x >> 16),
-                                cpu_to_le32(plane->state->src_y >> 16), NULL);
+                                cpu_to_le32(plane->state->src_y >> 16),
+                                objs, NULL);
                }
        } else {
                handle = 0;
@@ -186,7 +208,6 @@ static void virtio_gpu_cursor_plane_update(struct drm_plane *plane,
        struct virtio_gpu_framebuffer *vgfb;
        struct virtio_gpu_object *bo = NULL;
        uint32_t handle;
-       int ret = 0;
 
        if (plane->state->crtc)
                output = drm_crtc_to_virtio_gpu_output(plane->state->crtc);
@@ -205,20 +226,20 @@ static void virtio_gpu_cursor_plane_update(struct drm_plane *plane,
 
        if (bo && bo->dumb && (plane->state->fb != old_state->fb)) {
                /* new cursor -- update & wait */
+               struct virtio_gpu_object_array *objs;
+
+               objs = virtio_gpu_array_alloc(1);
+               if (!objs)
+                       return;
+               virtio_gpu_array_add_obj(objs, vgfb->base.obj[0]);
                virtio_gpu_cmd_transfer_to_host_2d
-                       (vgdev, bo, 0,
+                       (vgdev, 0,
                         cpu_to_le32(plane->state->crtc_w),
                         cpu_to_le32(plane->state->crtc_h),
-                        0, 0, vgfb->fence);
-               ret = virtio_gpu_object_reserve(bo, false);
-               if (!ret) {
-                       dma_resv_add_excl_fence(bo->tbo.base.resv,
-                                                         &vgfb->fence->f);
-                       dma_fence_put(&vgfb->fence->f);
-                       vgfb->fence = NULL;
-                       virtio_gpu_object_unreserve(bo);
-                       virtio_gpu_object_wait(bo, false);
-               }
+                        0, 0, objs, vgfb->fence);
+               dma_fence_wait(&vgfb->fence->f, true);
+               dma_fence_put(&vgfb->fence->f);
+               vgfb->fence = NULL;
        }
 
        if (plane->state->fb != old_state->fb) {
index dc642a884b882ba8463d0645ccfa11037938818e..050d24c39a8f66fd98a27ffe3aafa5075ed64516 100644 (file)
  * device that might share buffers with virtgpu
  */
 
-struct sg_table *virtgpu_gem_prime_get_sg_table(struct drm_gem_object *obj)
-{
-       struct virtio_gpu_object *bo = gem_to_virtio_gpu_obj(obj);
-
-       if (!bo->tbo.ttm->pages || !bo->tbo.ttm->num_pages)
-               /* should not happen */
-               return ERR_PTR(-EINVAL);
-
-       return drm_prime_pages_to_sg(bo->tbo.ttm->pages,
-                                    bo->tbo.ttm->num_pages);
-}
-
 struct drm_gem_object *virtgpu_gem_prime_import_sg_table(
        struct drm_device *dev, struct dma_buf_attachment *attach,
        struct sg_table *table)
 {
        return ERR_PTR(-ENODEV);
 }
-
-void *virtgpu_gem_prime_vmap(struct drm_gem_object *obj)
-{
-       struct virtio_gpu_object *bo = gem_to_virtio_gpu_obj(obj);
-       int ret;
-
-       ret = virtio_gpu_object_kmap(bo);
-       if (ret)
-               return NULL;
-       return bo->vmap;
-}
-
-void virtgpu_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr)
-{
-       virtio_gpu_object_kunmap(gem_to_virtio_gpu_obj(obj));
-}
-
-int virtgpu_gem_prime_mmap(struct drm_gem_object *obj,
-                          struct vm_area_struct *vma)
-{
-       return drm_gem_prime_mmap(obj, vma);
-}
diff --git a/drivers/gpu/drm/virtio/virtgpu_ttm.c b/drivers/gpu/drm/virtio/virtgpu_ttm.c
deleted file mode 100644 (file)
index f879036..0000000
+++ /dev/null
@@ -1,305 +0,0 @@
-/*
- * Copyright (C) 2015 Red Hat, Inc.
- * All Rights Reserved.
- *
- * Authors:
- *    Dave Airlie
- *    Alon Levy
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include <linux/delay.h>
-
-#include <drm/drm.h>
-#include <drm/drm_file.h>
-#include <drm/ttm/ttm_bo_api.h>
-#include <drm/ttm/ttm_bo_driver.h>
-#include <drm/ttm/ttm_module.h>
-#include <drm/ttm/ttm_page_alloc.h>
-#include <drm/ttm/ttm_placement.h>
-#include <drm/virtgpu_drm.h>
-
-#include "virtgpu_drv.h"
-
-static struct
-virtio_gpu_device *virtio_gpu_get_vgdev(struct ttm_bo_device *bdev)
-{
-       struct virtio_gpu_mman *mman;
-       struct virtio_gpu_device *vgdev;
-
-       mman = container_of(bdev, struct virtio_gpu_mman, bdev);
-       vgdev = container_of(mman, struct virtio_gpu_device, mman);
-       return vgdev;
-}
-
-int virtio_gpu_mmap(struct file *filp, struct vm_area_struct *vma)
-{
-       struct drm_file *file_priv;
-       struct virtio_gpu_device *vgdev;
-       int r;
-
-       file_priv = filp->private_data;
-       vgdev = file_priv->minor->dev->dev_private;
-       if (vgdev == NULL) {
-               DRM_ERROR(
-                "filp->private_data->minor->dev->dev_private == NULL\n");
-               return -EINVAL;
-       }
-       r = ttm_bo_mmap(filp, vma, &vgdev->mman.bdev);
-
-       return r;
-}
-
-static int virtio_gpu_invalidate_caches(struct ttm_bo_device *bdev,
-                                       uint32_t flags)
-{
-       return 0;
-}
-
-static int ttm_bo_man_get_node(struct ttm_mem_type_manager *man,
-                              struct ttm_buffer_object *bo,
-                              const struct ttm_place *place,
-                              struct ttm_mem_reg *mem)
-{
-       mem->mm_node = (void *)1;
-       return 0;
-}
-
-static void ttm_bo_man_put_node(struct ttm_mem_type_manager *man,
-                               struct ttm_mem_reg *mem)
-{
-       mem->mm_node = (void *)NULL;
-}
-
-static int ttm_bo_man_init(struct ttm_mem_type_manager *man,
-                          unsigned long p_size)
-{
-       return 0;
-}
-
-static int ttm_bo_man_takedown(struct ttm_mem_type_manager *man)
-{
-       return 0;
-}
-
-static void ttm_bo_man_debug(struct ttm_mem_type_manager *man,
-                            struct drm_printer *printer)
-{
-}
-
-static const struct ttm_mem_type_manager_func virtio_gpu_bo_manager_func = {
-       .init = ttm_bo_man_init,
-       .takedown = ttm_bo_man_takedown,
-       .get_node = ttm_bo_man_get_node,
-       .put_node = ttm_bo_man_put_node,
-       .debug = ttm_bo_man_debug
-};
-
-static int virtio_gpu_init_mem_type(struct ttm_bo_device *bdev, uint32_t type,
-                                   struct ttm_mem_type_manager *man)
-{
-       switch (type) {
-       case TTM_PL_SYSTEM:
-               /* System memory */
-               man->flags = TTM_MEMTYPE_FLAG_MAPPABLE;
-               man->available_caching = TTM_PL_MASK_CACHING;
-               man->default_caching = TTM_PL_FLAG_CACHED;
-               break;
-       case TTM_PL_TT:
-               man->func = &virtio_gpu_bo_manager_func;
-               man->flags = TTM_MEMTYPE_FLAG_MAPPABLE;
-               man->available_caching = TTM_PL_MASK_CACHING;
-               man->default_caching = TTM_PL_FLAG_CACHED;
-               break;
-       default:
-               DRM_ERROR("Unsupported memory type %u\n", (unsigned int)type);
-               return -EINVAL;
-       }
-       return 0;
-}
-
-static void virtio_gpu_evict_flags(struct ttm_buffer_object *bo,
-                               struct ttm_placement *placement)
-{
-       static const struct ttm_place placements = {
-               .fpfn  = 0,
-               .lpfn  = 0,
-               .flags = TTM_PL_MASK_CACHING | TTM_PL_FLAG_SYSTEM,
-       };
-
-       placement->placement = &placements;
-       placement->busy_placement = &placements;
-       placement->num_placement = 1;
-       placement->num_busy_placement = 1;
-}
-
-static int virtio_gpu_verify_access(struct ttm_buffer_object *bo,
-                                   struct file *filp)
-{
-       return 0;
-}
-
-static int virtio_gpu_ttm_io_mem_reserve(struct ttm_bo_device *bdev,
-                                        struct ttm_mem_reg *mem)
-{
-       struct ttm_mem_type_manager *man = &bdev->man[mem->mem_type];
-
-       mem->bus.addr = NULL;
-       mem->bus.offset = 0;
-       mem->bus.size = mem->num_pages << PAGE_SHIFT;
-       mem->bus.base = 0;
-       mem->bus.is_iomem = false;
-       if (!(man->flags & TTM_MEMTYPE_FLAG_MAPPABLE))
-               return -EINVAL;
-       switch (mem->mem_type) {
-       case TTM_PL_SYSTEM:
-       case TTM_PL_TT:
-               /* system memory */
-               return 0;
-       default:
-               return -EINVAL;
-       }
-       return 0;
-}
-
-static void virtio_gpu_ttm_io_mem_free(struct ttm_bo_device *bdev,
-                                      struct ttm_mem_reg *mem)
-{
-}
-
-/*
- * TTM backend functions.
- */
-struct virtio_gpu_ttm_tt {
-       struct ttm_dma_tt               ttm;
-       struct virtio_gpu_object        *obj;
-};
-
-static int virtio_gpu_ttm_tt_bind(struct ttm_tt *ttm,
-                                 struct ttm_mem_reg *bo_mem)
-{
-       struct virtio_gpu_ttm_tt *gtt =
-               container_of(ttm, struct virtio_gpu_ttm_tt, ttm.ttm);
-       struct virtio_gpu_device *vgdev =
-               virtio_gpu_get_vgdev(gtt->obj->tbo.bdev);
-
-       virtio_gpu_object_attach(vgdev, gtt->obj, NULL);
-       return 0;
-}
-
-static int virtio_gpu_ttm_tt_unbind(struct ttm_tt *ttm)
-{
-       struct virtio_gpu_ttm_tt *gtt =
-               container_of(ttm, struct virtio_gpu_ttm_tt, ttm.ttm);
-       struct virtio_gpu_device *vgdev =
-               virtio_gpu_get_vgdev(gtt->obj->tbo.bdev);
-
-       virtio_gpu_object_detach(vgdev, gtt->obj);
-       return 0;
-}
-
-static void virtio_gpu_ttm_tt_destroy(struct ttm_tt *ttm)
-{
-       struct virtio_gpu_ttm_tt *gtt =
-               container_of(ttm, struct virtio_gpu_ttm_tt, ttm.ttm);
-
-       ttm_dma_tt_fini(&gtt->ttm);
-       kfree(gtt);
-}
-
-static struct ttm_backend_func virtio_gpu_tt_func = {
-       .bind = &virtio_gpu_ttm_tt_bind,
-       .unbind = &virtio_gpu_ttm_tt_unbind,
-       .destroy = &virtio_gpu_ttm_tt_destroy,
-};
-
-static struct ttm_tt *virtio_gpu_ttm_tt_create(struct ttm_buffer_object *bo,
-                                              uint32_t page_flags)
-{
-       struct virtio_gpu_device *vgdev;
-       struct virtio_gpu_ttm_tt *gtt;
-
-       vgdev = virtio_gpu_get_vgdev(bo->bdev);
-       gtt = kzalloc(sizeof(struct virtio_gpu_ttm_tt), GFP_KERNEL);
-       if (gtt == NULL)
-               return NULL;
-       gtt->ttm.ttm.func = &virtio_gpu_tt_func;
-       gtt->obj = container_of(bo, struct virtio_gpu_object, tbo);
-       if (ttm_dma_tt_init(&gtt->ttm, bo, page_flags)) {
-               kfree(gtt);
-               return NULL;
-       }
-       return &gtt->ttm.ttm;
-}
-
-static void virtio_gpu_bo_swap_notify(struct ttm_buffer_object *tbo)
-{
-       struct virtio_gpu_object *bo;
-
-       bo = container_of(tbo, struct virtio_gpu_object, tbo);
-
-       if (bo->pages)
-               virtio_gpu_object_free_sg_table(bo);
-}
-
-static struct ttm_bo_driver virtio_gpu_bo_driver = {
-       .ttm_tt_create = &virtio_gpu_ttm_tt_create,
-       .invalidate_caches = &virtio_gpu_invalidate_caches,
-       .init_mem_type = &virtio_gpu_init_mem_type,
-       .eviction_valuable = ttm_bo_eviction_valuable,
-       .evict_flags = &virtio_gpu_evict_flags,
-       .verify_access = &virtio_gpu_verify_access,
-       .io_mem_reserve = &virtio_gpu_ttm_io_mem_reserve,
-       .io_mem_free = &virtio_gpu_ttm_io_mem_free,
-       .swap_notify = &virtio_gpu_bo_swap_notify,
-};
-
-int virtio_gpu_ttm_init(struct virtio_gpu_device *vgdev)
-{
-       int r;
-
-       /* No others user of address space so set it to 0 */
-       r = ttm_bo_device_init(&vgdev->mman.bdev,
-                              &virtio_gpu_bo_driver,
-                              vgdev->ddev->anon_inode->i_mapping,
-                              false);
-       if (r) {
-               DRM_ERROR("failed initializing buffer object driver(%d).\n", r);
-               goto err_dev_init;
-       }
-
-       r = ttm_bo_init_mm(&vgdev->mman.bdev, TTM_PL_TT, 0);
-       if (r) {
-               DRM_ERROR("Failed initializing GTT heap.\n");
-               goto err_mm_init;
-       }
-       return 0;
-
-err_mm_init:
-       ttm_bo_device_release(&vgdev->mman.bdev);
-err_dev_init:
-       return r;
-}
-
-void virtio_gpu_ttm_fini(struct virtio_gpu_device *vgdev)
-{
-       ttm_bo_device_release(&vgdev->mman.bdev);
-       DRM_INFO("virtio_gpu: ttm finalized\n");
-}
index 7ac20490e1b4c779fe34a3bbda9008e7307ae811..80176f379ad5115a8fcacaf304afa76f82f36617 100644 (file)
@@ -155,7 +155,7 @@ static void free_vbuf(struct virtio_gpu_device *vgdev,
 {
        if (vbuf->resp_size > MAX_INLINE_RESP_SIZE)
                kfree(vbuf->resp_buf);
-       kfree(vbuf->data_buf);
+       kvfree(vbuf->data_buf);
        kmem_cache_free(vgdev->vbufs, vbuf);
 }
 
@@ -192,7 +192,7 @@ void virtio_gpu_dequeue_ctrl_func(struct work_struct *work)
        } while (!virtqueue_enable_cb(vgdev->ctrlq.vq));
        spin_unlock(&vgdev->ctrlq.qlock);
 
-       list_for_each_entry_safe(entry, tmp, &reclaim_list, list) {
+       list_for_each_entry(entry, &reclaim_list, list) {
                resp = (struct virtio_gpu_ctrl_hdr *)entry->resp_buf;
 
                trace_virtio_gpu_cmd_response(vgdev->ctrlq.vq, resp);
@@ -219,14 +219,18 @@ void virtio_gpu_dequeue_ctrl_func(struct work_struct *work)
                }
                if (entry->resp_cb)
                        entry->resp_cb(vgdev, entry);
-
-               list_del(&entry->list);
-               free_vbuf(vgdev, entry);
        }
        wake_up(&vgdev->ctrlq.ack_queue);
 
        if (fence_id)
                virtio_gpu_fence_event_process(vgdev, fence_id);
+
+       list_for_each_entry_safe(entry, tmp, &reclaim_list, list) {
+               if (entry->objs)
+                       virtio_gpu_array_put_free_delayed(vgdev, entry->objs);
+               list_del(&entry->list);
+               free_vbuf(vgdev, entry);
+       }
 }
 
 void virtio_gpu_dequeue_cursor_func(struct work_struct *work)
@@ -252,26 +256,67 @@ void virtio_gpu_dequeue_cursor_func(struct work_struct *work)
        wake_up(&vgdev->cursorq.ack_queue);
 }
 
-static int virtio_gpu_queue_ctrl_buffer_locked(struct virtio_gpu_device *vgdev,
-                                              struct virtio_gpu_vbuffer *vbuf)
+/* Create sg_table from a vmalloc'd buffer. */
+static struct sg_table *vmalloc_to_sgt(char *data, uint32_t size, int *sg_ents)
+{
+       int ret, s, i;
+       struct sg_table *sgt;
+       struct scatterlist *sg;
+       struct page *pg;
+
+       if (WARN_ON(!PAGE_ALIGNED(data)))
+               return NULL;
+
+       sgt = kmalloc(sizeof(*sgt), GFP_KERNEL);
+       if (!sgt)
+               return NULL;
+
+       *sg_ents = DIV_ROUND_UP(size, PAGE_SIZE);
+       ret = sg_alloc_table(sgt, *sg_ents, GFP_KERNEL);
+       if (ret) {
+               kfree(sgt);
+               return NULL;
+       }
+
+       for_each_sg(sgt->sgl, sg, *sg_ents, i) {
+               pg = vmalloc_to_page(data);
+               if (!pg) {
+                       sg_free_table(sgt);
+                       kfree(sgt);
+                       return NULL;
+               }
+
+               s = min_t(int, PAGE_SIZE, size);
+               sg_set_page(sg, pg, s, 0);
+
+               size -= s;
+               data += s;
+       }
+
+       return sgt;
+}
+
+static bool virtio_gpu_queue_ctrl_buffer_locked(struct virtio_gpu_device *vgdev,
+                                               struct virtio_gpu_vbuffer *vbuf,
+                                               struct scatterlist *vout)
                __releases(&vgdev->ctrlq.qlock)
                __acquires(&vgdev->ctrlq.qlock)
 {
        struct virtqueue *vq = vgdev->ctrlq.vq;
-       struct scatterlist *sgs[3], vcmd, vout, vresp;
+       struct scatterlist *sgs[3], vcmd, vresp;
        int outcnt = 0, incnt = 0;
+       bool notify = false;
        int ret;
 
        if (!vgdev->vqs_ready)
-               return -ENODEV;
+               return notify;
 
        sg_init_one(&vcmd, vbuf->buf, vbuf->size);
        sgs[outcnt + incnt] = &vcmd;
        outcnt++;
 
-       if (vbuf->data_size) {
-               sg_init_one(&vout, vbuf->data_buf, vbuf->data_size);
-               sgs[outcnt + incnt] = &vout;
+       if (vout) {
+               sgs[outcnt + incnt] = vout;
                outcnt++;
        }
 
@@ -292,32 +337,35 @@ retry:
                trace_virtio_gpu_cmd_queue(vq,
                        (struct virtio_gpu_ctrl_hdr *)vbuf->buf);
 
-               virtqueue_kick(vq);
+               notify = virtqueue_kick_prepare(vq);
        }
-
-       if (!ret)
-               ret = vq->num_free;
-       return ret;
-}
-
-static int virtio_gpu_queue_ctrl_buffer(struct virtio_gpu_device *vgdev,
-                                       struct virtio_gpu_vbuffer *vbuf)
-{
-       int rc;
-
-       spin_lock(&vgdev->ctrlq.qlock);
-       rc = virtio_gpu_queue_ctrl_buffer_locked(vgdev, vbuf);
-       spin_unlock(&vgdev->ctrlq.qlock);
-       return rc;
+       return notify;
 }
 
-static int virtio_gpu_queue_fenced_ctrl_buffer(struct virtio_gpu_device *vgdev,
-                                              struct virtio_gpu_vbuffer *vbuf,
-                                              struct virtio_gpu_ctrl_hdr *hdr,
-                                              struct virtio_gpu_fence *fence)
+static void virtio_gpu_queue_fenced_ctrl_buffer(struct virtio_gpu_device *vgdev,
+                                               struct virtio_gpu_vbuffer *vbuf,
+                                               struct virtio_gpu_ctrl_hdr *hdr,
+                                               struct virtio_gpu_fence *fence)
 {
        struct virtqueue *vq = vgdev->ctrlq.vq;
-       int rc;
+       struct scatterlist *vout = NULL, sg;
+       struct sg_table *sgt = NULL;
+       bool notify;
+       int outcnt = 0;
+
+       if (vbuf->data_size) {
+               if (is_vmalloc_addr(vbuf->data_buf)) {
+                       sgt = vmalloc_to_sgt(vbuf->data_buf, vbuf->data_size,
+                                            &outcnt);
+                       if (!sgt)
+                               return;
+                       vout = sgt->sgl;
+               } else {
+                       sg_init_one(&sg, vbuf->data_buf, vbuf->data_size);
+                       vout = &sg;
+                       outcnt = 1;
+               }
+       }
 
 again:
        spin_lock(&vgdev->ctrlq.qlock);
@@ -330,29 +378,47 @@ again:
         * to wait for free space, which can result in fence ids being
         * submitted out-of-order.
         */
-       if (vq->num_free < 3) {
+       if (vq->num_free < 2 + outcnt) {
                spin_unlock(&vgdev->ctrlq.qlock);
                wait_event(vgdev->ctrlq.ack_queue, vq->num_free >= 3);
                goto again;
        }
 
-       if (fence)
+       if (hdr && fence) {
                virtio_gpu_fence_emit(vgdev, hdr, fence);
-       rc = virtio_gpu_queue_ctrl_buffer_locked(vgdev, vbuf);
+               if (vbuf->objs) {
+                       virtio_gpu_array_add_fence(vbuf->objs, &fence->f);
+                       virtio_gpu_array_unlock_resv(vbuf->objs);
+               }
+       }
+       notify = virtio_gpu_queue_ctrl_buffer_locked(vgdev, vbuf, vout);
        spin_unlock(&vgdev->ctrlq.qlock);
-       return rc;
+       if (notify)
+               virtqueue_notify(vgdev->ctrlq.vq);
+
+       if (sgt) {
+               sg_free_table(sgt);
+               kfree(sgt);
+       }
 }
 
-static int virtio_gpu_queue_cursor(struct virtio_gpu_device *vgdev,
-                                  struct virtio_gpu_vbuffer *vbuf)
+static void virtio_gpu_queue_ctrl_buffer(struct virtio_gpu_device *vgdev,
+                                        struct virtio_gpu_vbuffer *vbuf)
+{
+       virtio_gpu_queue_fenced_ctrl_buffer(vgdev, vbuf, NULL, NULL);
+}
+
+static void virtio_gpu_queue_cursor(struct virtio_gpu_device *vgdev,
+                                   struct virtio_gpu_vbuffer *vbuf)
 {
        struct virtqueue *vq = vgdev->cursorq.vq;
        struct scatterlist *sgs[1], ccmd;
+       bool notify;
        int ret;
        int outcnt;
 
        if (!vgdev->vqs_ready)
-               return -ENODEV;
+               return;
 
        sg_init_one(&ccmd, vbuf->buf, vbuf->size);
        sgs[0] = &ccmd;
@@ -370,14 +436,13 @@ retry:
                trace_virtio_gpu_cmd_queue(vq,
                        (struct virtio_gpu_ctrl_hdr *)vbuf->buf);
 
-               virtqueue_kick(vq);
+               notify = virtqueue_kick_prepare(vq);
        }
 
        spin_unlock(&vgdev->cursorq.qlock);
 
-       if (!ret)
-               ret = vq->num_free;
-       return ret;
+       if (notify)
+               virtqueue_notify(vq);
 }
 
 /* just create gem objects for userspace and long lived objects,
@@ -388,6 +453,7 @@ retry:
 void virtio_gpu_cmd_create_resource(struct virtio_gpu_device *vgdev,
                                    struct virtio_gpu_object *bo,
                                    struct virtio_gpu_object_params *params,
+                                   struct virtio_gpu_object_array *objs,
                                    struct virtio_gpu_fence *fence)
 {
        struct virtio_gpu_resource_create_2d *cmd_p;
@@ -395,6 +461,7 @@ void virtio_gpu_cmd_create_resource(struct virtio_gpu_device *vgdev,
 
        cmd_p = virtio_gpu_alloc_cmd(vgdev, &vbuf, sizeof(*cmd_p));
        memset(cmd_p, 0, sizeof(*cmd_p));
+       vbuf->objs = objs;
 
        cmd_p->hdr.type = cpu_to_le32(VIRTIO_GPU_CMD_RESOURCE_CREATE_2D);
        cmd_p->resource_id = cpu_to_le32(bo->hw_res_handle);
@@ -481,12 +548,13 @@ void virtio_gpu_cmd_resource_flush(struct virtio_gpu_device *vgdev,
 }
 
 void virtio_gpu_cmd_transfer_to_host_2d(struct virtio_gpu_device *vgdev,
-                                       struct virtio_gpu_object *bo,
                                        uint64_t offset,
                                        __le32 width, __le32 height,
                                        __le32 x, __le32 y,
+                                       struct virtio_gpu_object_array *objs,
                                        struct virtio_gpu_fence *fence)
 {
+       struct virtio_gpu_object *bo = gem_to_virtio_gpu_obj(objs->objs[0]);
        struct virtio_gpu_transfer_to_host_2d *cmd_p;
        struct virtio_gpu_vbuffer *vbuf;
        bool use_dma_api = !virtio_has_iommu_quirk(vgdev->vdev);
@@ -498,6 +566,7 @@ void virtio_gpu_cmd_transfer_to_host_2d(struct virtio_gpu_device *vgdev,
 
        cmd_p = virtio_gpu_alloc_cmd(vgdev, &vbuf, sizeof(*cmd_p));
        memset(cmd_p, 0, sizeof(*cmd_p));
+       vbuf->objs = objs;
 
        cmd_p->hdr.type = cpu_to_le32(VIRTIO_GPU_CMD_TRANSFER_TO_HOST_2D);
        cmd_p->resource_id = cpu_to_le32(bo->hw_res_handle);
@@ -826,34 +895,38 @@ void virtio_gpu_cmd_context_destroy(struct virtio_gpu_device *vgdev,
 
 void virtio_gpu_cmd_context_attach_resource(struct virtio_gpu_device *vgdev,
                                            uint32_t ctx_id,
-                                           uint32_t resource_id)
+                                           struct virtio_gpu_object_array *objs)
 {
+       struct virtio_gpu_object *bo = gem_to_virtio_gpu_obj(objs->objs[0]);
        struct virtio_gpu_ctx_resource *cmd_p;
        struct virtio_gpu_vbuffer *vbuf;
 
        cmd_p = virtio_gpu_alloc_cmd(vgdev, &vbuf, sizeof(*cmd_p));
        memset(cmd_p, 0, sizeof(*cmd_p));
+       vbuf->objs = objs;
 
        cmd_p->hdr.type = cpu_to_le32(VIRTIO_GPU_CMD_CTX_ATTACH_RESOURCE);
        cmd_p->hdr.ctx_id = cpu_to_le32(ctx_id);
-       cmd_p->resource_id = cpu_to_le32(resource_id);
+       cmd_p->resource_id = cpu_to_le32(bo->hw_res_handle);
        virtio_gpu_queue_ctrl_buffer(vgdev, vbuf);
 
 }
 
 void virtio_gpu_cmd_context_detach_resource(struct virtio_gpu_device *vgdev,
                                            uint32_t ctx_id,
-                                           uint32_t resource_id)
+                                           struct virtio_gpu_object_array *objs)
 {
+       struct virtio_gpu_object *bo = gem_to_virtio_gpu_obj(objs->objs[0]);
        struct virtio_gpu_ctx_resource *cmd_p;
        struct virtio_gpu_vbuffer *vbuf;
 
        cmd_p = virtio_gpu_alloc_cmd(vgdev, &vbuf, sizeof(*cmd_p));
        memset(cmd_p, 0, sizeof(*cmd_p));
+       vbuf->objs = objs;
 
        cmd_p->hdr.type = cpu_to_le32(VIRTIO_GPU_CMD_CTX_DETACH_RESOURCE);
        cmd_p->hdr.ctx_id = cpu_to_le32(ctx_id);
-       cmd_p->resource_id = cpu_to_le32(resource_id);
+       cmd_p->resource_id = cpu_to_le32(bo->hw_res_handle);
        virtio_gpu_queue_ctrl_buffer(vgdev, vbuf);
 }
 
@@ -861,6 +934,7 @@ void
 virtio_gpu_cmd_resource_create_3d(struct virtio_gpu_device *vgdev,
                                  struct virtio_gpu_object *bo,
                                  struct virtio_gpu_object_params *params,
+                                 struct virtio_gpu_object_array *objs,
                                  struct virtio_gpu_fence *fence)
 {
        struct virtio_gpu_resource_create_3d *cmd_p;
@@ -868,6 +942,7 @@ virtio_gpu_cmd_resource_create_3d(struct virtio_gpu_device *vgdev,
 
        cmd_p = virtio_gpu_alloc_cmd(vgdev, &vbuf, sizeof(*cmd_p));
        memset(cmd_p, 0, sizeof(*cmd_p));
+       vbuf->objs = objs;
 
        cmd_p->hdr.type = cpu_to_le32(VIRTIO_GPU_CMD_RESOURCE_CREATE_3D);
        cmd_p->resource_id = cpu_to_le32(bo->hw_res_handle);
@@ -888,12 +963,13 @@ virtio_gpu_cmd_resource_create_3d(struct virtio_gpu_device *vgdev,
 }
 
 void virtio_gpu_cmd_transfer_to_host_3d(struct virtio_gpu_device *vgdev,
-                                       struct virtio_gpu_object *bo,
                                        uint32_t ctx_id,
                                        uint64_t offset, uint32_t level,
                                        struct virtio_gpu_box *box,
+                                       struct virtio_gpu_object_array *objs,
                                        struct virtio_gpu_fence *fence)
 {
+       struct virtio_gpu_object *bo = gem_to_virtio_gpu_obj(objs->objs[0]);
        struct virtio_gpu_transfer_host_3d *cmd_p;
        struct virtio_gpu_vbuffer *vbuf;
        bool use_dma_api = !virtio_has_iommu_quirk(vgdev->vdev);
@@ -906,6 +982,8 @@ void virtio_gpu_cmd_transfer_to_host_3d(struct virtio_gpu_device *vgdev,
        cmd_p = virtio_gpu_alloc_cmd(vgdev, &vbuf, sizeof(*cmd_p));
        memset(cmd_p, 0, sizeof(*cmd_p));
 
+       vbuf->objs = objs;
+
        cmd_p->hdr.type = cpu_to_le32(VIRTIO_GPU_CMD_TRANSFER_TO_HOST_3D);
        cmd_p->hdr.ctx_id = cpu_to_le32(ctx_id);
        cmd_p->resource_id = cpu_to_le32(bo->hw_res_handle);
@@ -917,20 +995,24 @@ void virtio_gpu_cmd_transfer_to_host_3d(struct virtio_gpu_device *vgdev,
 }
 
 void virtio_gpu_cmd_transfer_from_host_3d(struct virtio_gpu_device *vgdev,
-                                         uint32_t resource_id, uint32_t ctx_id,
+                                         uint32_t ctx_id,
                                          uint64_t offset, uint32_t level,
                                          struct virtio_gpu_box *box,
+                                         struct virtio_gpu_object_array *objs,
                                          struct virtio_gpu_fence *fence)
 {
+       struct virtio_gpu_object *bo = gem_to_virtio_gpu_obj(objs->objs[0]);
        struct virtio_gpu_transfer_host_3d *cmd_p;
        struct virtio_gpu_vbuffer *vbuf;
 
        cmd_p = virtio_gpu_alloc_cmd(vgdev, &vbuf, sizeof(*cmd_p));
        memset(cmd_p, 0, sizeof(*cmd_p));
 
+       vbuf->objs = objs;
+
        cmd_p->hdr.type = cpu_to_le32(VIRTIO_GPU_CMD_TRANSFER_FROM_HOST_3D);
        cmd_p->hdr.ctx_id = cpu_to_le32(ctx_id);
-       cmd_p->resource_id = cpu_to_le32(resource_id);
+       cmd_p->resource_id = cpu_to_le32(bo->hw_res_handle);
        cmd_p->box = *box;
        cmd_p->offset = cpu_to_le64(offset);
        cmd_p->level = cpu_to_le32(level);
@@ -940,7 +1022,9 @@ void virtio_gpu_cmd_transfer_from_host_3d(struct virtio_gpu_device *vgdev,
 
 void virtio_gpu_cmd_submit(struct virtio_gpu_device *vgdev,
                           void *data, uint32_t data_size,
-                          uint32_t ctx_id, struct virtio_gpu_fence *fence)
+                          uint32_t ctx_id,
+                          struct virtio_gpu_object_array *objs,
+                          struct virtio_gpu_fence *fence)
 {
        struct virtio_gpu_cmd_submit *cmd_p;
        struct virtio_gpu_vbuffer *vbuf;
@@ -950,6 +1034,7 @@ void virtio_gpu_cmd_submit(struct virtio_gpu_device *vgdev,
 
        vbuf->data_buf = data;
        vbuf->data_size = data_size;
+       vbuf->objs = objs;
 
        cmd_p->hdr.type = cpu_to_le32(VIRTIO_GPU_CMD_SUBMIT_3D);
        cmd_p->hdr.ctx_id = cpu_to_le32(ctx_id);
@@ -965,17 +1050,21 @@ int virtio_gpu_object_attach(struct virtio_gpu_device *vgdev,
        bool use_dma_api = !virtio_has_iommu_quirk(vgdev->vdev);
        struct virtio_gpu_mem_entry *ents;
        struct scatterlist *sg;
-       int si, nents;
+       int si, nents, ret;
 
        if (WARN_ON_ONCE(!obj->created))
                return -EINVAL;
+       if (WARN_ON_ONCE(obj->pages))
+               return -EINVAL;
 
-       if (!obj->pages) {
-               int ret;
+       ret = drm_gem_shmem_pin(&obj->base.base);
+       if (ret < 0)
+               return -EINVAL;
 
-               ret = virtio_gpu_object_get_sg_table(vgdev, obj);
-               if (ret)
-                       return ret;
+       obj->pages = drm_gem_shmem_get_sg_table(&obj->base.base);
+       if (obj->pages == NULL) {
+               drm_gem_shmem_unpin(&obj->base.base);
+               return -EINVAL;
        }
 
        if (use_dma_api) {
@@ -1014,6 +1103,9 @@ void virtio_gpu_object_detach(struct virtio_gpu_device *vgdev,
 {
        bool use_dma_api = !virtio_has_iommu_quirk(vgdev->vdev);
 
+       if (WARN_ON_ONCE(!obj->pages))
+               return;
+
        if (use_dma_api && obj->mapped) {
                struct virtio_gpu_fence *fence = virtio_gpu_fence_alloc(vgdev);
                /* detach backing and wait for the host process it ... */
@@ -1029,6 +1121,11 @@ void virtio_gpu_object_detach(struct virtio_gpu_device *vgdev,
        } else {
                virtio_gpu_cmd_resource_inval_backing(vgdev, obj->hw_res_handle, NULL);
        }
+
+       sg_free_table(obj->pages);
+       obj->pages = NULL;
+
+       drm_gem_shmem_unpin(&obj->base.base);
 }
 
 void virtio_gpu_cursor_ping(struct virtio_gpu_device *vgdev,
index 927dafaebc766c0f1eba4cb924e2f3575040522b..74f703b8d22a511674a8001eba16b07c5402ed1b 100644 (file)
@@ -16,17 +16,18 @@ static enum hrtimer_restart vkms_vblank_simulate(struct hrtimer *timer)
        u64 ret_overrun;
        bool ret;
 
-       spin_lock(&output->lock);
-
        ret_overrun = hrtimer_forward_now(&output->vblank_hrtimer,
                                          output->period_ns);
        WARN_ON(ret_overrun != 1);
 
+       spin_lock(&output->lock);
        ret = drm_crtc_handle_vblank(crtc);
        if (!ret)
                DRM_ERROR("vkms failure on handling vblank");
 
        state = output->composer_state;
+       spin_unlock(&output->lock);
+
        if (state && output->composer_enabled) {
                u64 frame = drm_crtc_accurate_vblank_count(crtc);
 
@@ -48,8 +49,6 @@ static enum hrtimer_restart vkms_vblank_simulate(struct hrtimer *timer)
                        DRM_DEBUG_DRIVER("Composer worker already queued\n");
        }
 
-       spin_unlock(&output->lock);
-
        return HRTIMER_RESTART;
 }
 
@@ -85,7 +84,7 @@ bool vkms_get_vblank_timestamp(struct drm_device *dev, unsigned int pipe,
        struct vkms_output *output = &vkmsdev->output;
        struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
 
-       *vblank_time = output->vblank_hrtimer.node.expires;
+       *vblank_time = READ_ONCE(output->vblank_hrtimer.node.expires);
 
        if (WARN_ON(*vblank_time == vblank->time))
                return true;
index 44ab9f8ef8be6fc94cc9ebca80054581bb1d38e6..80524a22412a6137d0b150781963b5633d75079e 100644 (file)
@@ -83,7 +83,7 @@ static void vkms_atomic_commit_tail(struct drm_atomic_state *old_state)
 
        drm_atomic_helper_commit_hw_done(old_state);
 
-       drm_atomic_helper_wait_for_vblanks(dev, old_state);
+       drm_atomic_helper_wait_for_flip_done(dev, old_state);
 
        for_each_old_crtc_in_state(old_state, crtc, old_crtc_state, i) {
                struct vkms_crtc_state *vkms_state =
index b38bcb032c991ec75f3cd8742be1ecd37c2f98b7..81a95651643f2c58b3abd61f6c104c82c322d85e 100644 (file)
@@ -827,9 +827,13 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
                goto out_no_fman;
        }
 
+       drm_vma_offset_manager_init(&dev_priv->vma_manager,
+                                   DRM_FILE_PAGE_OFFSET_START,
+                                   DRM_FILE_PAGE_OFFSET_SIZE);
        ret = ttm_bo_device_init(&dev_priv->bdev,
                                 &vmw_bo_driver,
                                 dev->anon_inode->i_mapping,
+                                &dev_priv->vma_manager,
                                 false);
        if (unlikely(ret != 0)) {
                DRM_ERROR("Failed initializing TTM buffer object driver.\n");
@@ -986,6 +990,7 @@ static void vmw_driver_unload(struct drm_device *dev)
        if (dev_priv->has_mob)
                (void) ttm_bo_clean_mm(&dev_priv->bdev, VMW_PL_MOB);
        (void) ttm_bo_device_release(&dev_priv->bdev);
+       drm_vma_offset_manager_destroy(&dev_priv->vma_manager);
        vmw_release_device_late(dev_priv);
        vmw_fence_manager_takedown(dev_priv->fman);
        if (dev_priv->capabilities & SVGA_CAP_IRQMASK)
index 5eb73ded8e07a2f46706b21ac8390e43e4622498..29f60e027a38290e6a348bd0ed91698993b672dc 100644 (file)
@@ -438,6 +438,7 @@ struct vmw_private {
        struct vmw_fifo_state fifo;
 
        struct drm_device *dev;
+       struct drm_vma_offset_manager vma_manager;
        unsigned long vmw_chipset;
        unsigned int io_start;
        uint32_t vram_start;
index e6a1c805064f07c8ae2499c3a2f9e0a069546999..95c32952fa8a5702c1d744402bf2dc67b7f7f2b8 100644 (file)
@@ -1758,21 +1758,19 @@ EXPORT_SYMBOL(remove_conflicting_framebuffers);
 /**
  * remove_conflicting_pci_framebuffers - remove firmware-configured framebuffers for PCI devices
  * @pdev: PCI device
- * @res_id: index of PCI BAR configuring framebuffer memory
  * @name: requesting driver name
  *
  * This function removes framebuffer devices (eg. initialized by firmware)
- * using memory range configured for @pdev's BAR @res_id.
+ * using memory range configured for any of @pdev's memory bars.
  *
  * The function assumes that PCI device with shadowed ROM drives a primary
  * display and so kicks out vga16fb.
  */
-int remove_conflicting_pci_framebuffers(struct pci_dev *pdev, int res_id, const char *name)
+int remove_conflicting_pci_framebuffers(struct pci_dev *pdev, const char *name)
 {
        struct apertures_struct *ap;
        bool primary = false;
        int err, idx, bar;
-       bool res_id_found = false;
 
        for (idx = 0, bar = 0; bar < PCI_ROM_RESOURCE; bar++) {
                if (!(pci_resource_flags(pdev, bar) & IORESOURCE_MEM))
@@ -1789,16 +1787,11 @@ int remove_conflicting_pci_framebuffers(struct pci_dev *pdev, int res_id, const
                        continue;
                ap->ranges[idx].base = pci_resource_start(pdev, bar);
                ap->ranges[idx].size = pci_resource_len(pdev, bar);
-               pci_info(pdev, "%s: bar %d: 0x%lx -> 0x%lx\n", __func__, bar,
-                        (unsigned long)pci_resource_start(pdev, bar),
-                        (unsigned long)pci_resource_end(pdev, bar));
+               pci_dbg(pdev, "%s: bar %d: 0x%lx -> 0x%lx\n", __func__, bar,
+                       (unsigned long)pci_resource_start(pdev, bar),
+                       (unsigned long)pci_resource_end(pdev, bar));
                idx++;
-               if (res_id == bar)
-                       res_id_found = true;
        }
-       if (!res_id_found)
-               pci_warn(pdev, "%s: passed res_id (%d) is not a memory bar\n",
-                        __func__, res_id);
 
 #ifdef CONFIG_X86
        primary = pdev->resource[PCI_ROM_RESOURCE].flags &
index ae2bcfee338a29031bfe1b78f13c80ba47a51eca..81ad3aa1ca06a46352412dc7722d9eab8bab1658 100644 (file)
@@ -967,19 +967,6 @@ static void sa1100fb_task(struct work_struct *w)
 }
 
 #ifdef CONFIG_CPU_FREQ
-/*
- * Calculate the minimum DMA period over all displays that we own.
- * This, together with the SDRAM bandwidth defines the slowest CPU
- * frequency that can be selected.
- */
-static unsigned int sa1100fb_min_dma_period(struct sa1100fb_info *fbi)
-{
-       /*
-        * FIXME: we need to verify _all_ consoles.
-        */
-       return sa1100fb_display_dma_period(&fbi->fb.var);
-}
-
 /*
  * CPU clock speed change handler.  We need to adjust the LCD timing
  * parameters when the CPU clock is adjusted by the power management
index b939bc28d886fc2f8b3d8ed85e23e2816982b1c3..9c82e2a0a41117aab8b1051dfae76f1917b0aaa9 100644 (file)
@@ -1576,12 +1576,12 @@ static int hdmi_avi_infoframe_unpack(struct hdmi_avi_infoframe *frame,
        if (ptr[0] & 0x10)
                frame->active_aspect = ptr[1] & 0xf;
        if (ptr[0] & 0x8) {
-               frame->top_bar = (ptr[5] << 8) + ptr[6];
-               frame->bottom_bar = (ptr[7] << 8) + ptr[8];
+               frame->top_bar = (ptr[6] << 8) | ptr[5];
+               frame->bottom_bar = (ptr[8] << 8) | ptr[7];
        }
        if (ptr[0] & 0x4) {
-               frame->left_bar = (ptr[9] << 8) + ptr[10];
-               frame->right_bar = (ptr[11] << 8) + ptr[12];
+               frame->left_bar = (ptr[10] << 8) | ptr[9];
+               frame->right_bar = (ptr[12] << 8) | ptr[11];
        }
        frame->scan_mode = ptr[0] & 0x3;
 
index cf528c2898570d72d38eedb233505b63f6d548fd..4b3e863c4f8af2e7fa72a85f536f4338b504a917 100644 (file)
@@ -156,6 +156,7 @@ void dw_hdmi_setup_rx_sense(struct dw_hdmi *hdmi, bool hpd, bool rx_sense);
 
 void dw_hdmi_set_sample_rate(struct dw_hdmi *hdmi, unsigned int rate);
 void dw_hdmi_set_channel_count(struct dw_hdmi *hdmi, unsigned int cnt);
+void dw_hdmi_set_channel_status(struct dw_hdmi *hdmi, u8 *channel_status);
 void dw_hdmi_set_channel_allocation(struct dw_hdmi *hdmi, unsigned int ca);
 void dw_hdmi_audio_enable(struct dw_hdmi *hdmi);
 void dw_hdmi_audio_disable(struct dw_hdmi *hdmi);
index 7616f6562fe488e47312e0b7e77da5977cffd902..c0a2286a81e986565e9cd0271bfa0e5db1bda4d7 100644 (file)
@@ -42,7 +42,7 @@ struct drm_bridge_funcs {
         * This callback is invoked whenever our bridge is being attached to a
         * &drm_encoder.
         *
-        * The attach callback is optional.
+        * The @attach callback is optional.
         *
         * RETURNS:
         *
@@ -56,7 +56,7 @@ struct drm_bridge_funcs {
         * This callback is invoked whenever our bridge is being detached from a
         * &drm_encoder.
         *
-        * The detach callback is optional.
+        * The @detach callback is optional.
         */
        void (*detach)(struct drm_bridge *bridge);
 
@@ -76,7 +76,7 @@ struct drm_bridge_funcs {
         * atomic helpers to validate modes supplied by userspace in
         * drm_atomic_helper_check_modeset().
         *
-        * This function is optional.
+        * The @mode_valid callback is optional.
         *
         * NOTE:
         *
@@ -108,7 +108,7 @@ struct drm_bridge_funcs {
         * this function passes all other callbacks must succeed for this
         * configuration.
         *
-        * The mode_fixup callback is optional.
+        * The @mode_fixup callback is optional.
         *
         * NOTE:
         *
@@ -146,7 +146,7 @@ struct drm_bridge_funcs {
         * The bridge can assume that the display pipe (i.e. clocks and timing
         * signals) feeding it is still running when this callback is called.
         *
-        * The disable callback is optional.
+        * The @disable callback is optional.
         */
        void (*disable)(struct drm_bridge *bridge);
 
@@ -165,7 +165,7 @@ struct drm_bridge_funcs {
         * singals) feeding it is no longer running when this callback is
         * called.
         *
-        * The post_disable callback is optional.
+        * The @post_disable callback is optional.
         */
        void (*post_disable)(struct drm_bridge *bridge);
 
@@ -214,7 +214,7 @@ struct drm_bridge_funcs {
         * not enable the display link feeding the next bridge in the chain (if
         * there is one) when this callback is called.
         *
-        * The pre_enable callback is optional.
+        * The @pre_enable callback is optional.
         */
        void (*pre_enable)(struct drm_bridge *bridge);
 
@@ -234,7 +234,7 @@ struct drm_bridge_funcs {
         * callback must enable the display link feeding the next bridge in the
         * chain if there is one.
         *
-        * The enable callback is optional.
+        * The @enable callback is optional.
         */
        void (*enable)(struct drm_bridge *bridge);
 
@@ -283,7 +283,7 @@ struct drm_bridge_funcs {
         * would be prudent to also provide an implementation of @enable if
         * you are expecting driver calls into &drm_bridge_enable.
         *
-        * The enable callback is optional.
+        * The @atomic_enable callback is optional.
         */
        void (*atomic_enable)(struct drm_bridge *bridge,
                              struct drm_atomic_state *state);
@@ -305,7 +305,7 @@ struct drm_bridge_funcs {
         * would be prudent to also provide an implementation of @disable if
         * you are expecting driver calls into &drm_bridge_disable.
         *
-        * The disable callback is optional.
+        * The @atomic_disable callback is optional.
         */
        void (*atomic_disable)(struct drm_bridge *bridge,
                               struct drm_atomic_state *state);
@@ -330,7 +330,7 @@ struct drm_bridge_funcs {
         * @post_disable if you are expecting driver calls into
         * &drm_bridge_post_disable.
         *
-        * The post_disable callback is optional.
+        * The @atomic_post_disable callback is optional.
         */
        void (*atomic_post_disable)(struct drm_bridge *bridge,
                                    struct drm_atomic_state *state);
@@ -429,12 +429,15 @@ void drm_atomic_bridge_enable(struct drm_bridge *bridge,
                              struct drm_atomic_state *state);
 
 #ifdef CONFIG_DRM_PANEL_BRIDGE
-struct drm_bridge *drm_panel_bridge_add(struct drm_panel *panel,
-                                       u32 connector_type);
+struct drm_bridge *drm_panel_bridge_add(struct drm_panel *panel);
+struct drm_bridge *drm_panel_bridge_add_typed(struct drm_panel *panel,
+                                             u32 connector_type);
 void drm_panel_bridge_remove(struct drm_bridge *bridge);
 struct drm_bridge *devm_drm_panel_bridge_add(struct device *dev,
-                                            struct drm_panel *panel,
-                                            u32 connector_type);
+                                            struct drm_panel *panel);
+struct drm_bridge *devm_drm_panel_bridge_add_typed(struct device *dev,
+                                                  struct drm_panel *panel,
+                                                  u32 connector_type);
 #endif
 
 #endif
index 681cb590f95211d3a3209f3f978561992ee75e00..5f8c3389d46f79b4fad89979e60bcd93c4d81b45 100644 (file)
@@ -281,6 +281,10 @@ enum drm_panel_orientation {
 /* Additional Colorimetry extension added as part of CTA 861.G */
 #define DRM_MODE_COLORIMETRY_DCI_P3_RGB_D65            11
 #define DRM_MODE_COLORIMETRY_DCI_P3_RGB_THEATER                12
+/* Additional Colorimetry Options added for DP 1.4a VSC Colorimetry Format */
+#define DRM_MODE_COLORIMETRY_RGB_WIDE_FIXED            13
+#define DRM_MODE_COLORIMETRY_RGB_WIDE_FLOAT            14
+#define DRM_MODE_COLORIMETRY_BT601_YCC                 15
 
 /**
  * enum drm_bus_flags - bus_flags info for &drm_display_info
@@ -1288,12 +1292,12 @@ struct drm_connector {
        /** @override_edid: has the EDID been overwritten through debugfs for testing? */
        bool override_edid;
 
-#define DRM_CONNECTOR_MAX_ENCODER 3
        /**
-        * @encoder_ids: Valid encoders for this connector. Please only use
-        * drm_connector_for_each_possible_encoder() to enumerate these.
+        * @possible_encoders: Bit mask of encoders that can drive this
+        * connector, drm_encoder_index() determines the index into the bitfield
+        * and the bits are set with drm_connector_attach_encoder().
         */
-       uint32_t encoder_ids[DRM_CONNECTOR_MAX_ENCODER];
+       u32 possible_encoders;
 
        /**
         * @encoder: Currently bound encoder driving this connector, if any.
@@ -1523,7 +1527,8 @@ int drm_connector_attach_scaling_mode_property(struct drm_connector *connector,
 int drm_connector_attach_vrr_capable_property(
                struct drm_connector *connector);
 int drm_mode_create_aspect_ratio_property(struct drm_device *dev);
-int drm_mode_create_colorspace_property(struct drm_connector *connector);
+int drm_mode_create_hdmi_colorspace_property(struct drm_connector *connector);
+int drm_mode_create_dp_colorspace_property(struct drm_connector *connector);
 int drm_mode_create_content_type_property(struct drm_device *dev);
 void drm_hdmi_avi_infoframe_content_type(struct hdmi_avi_infoframe *frame,
                                         const struct drm_connector_state *conn_state);
@@ -1608,13 +1613,9 @@ bool drm_connector_has_possible_encoder(struct drm_connector *connector,
  * drm_connector_for_each_possible_encoder - iterate connector's possible encoders
  * @connector: &struct drm_connector pointer
  * @encoder: &struct drm_encoder pointer used as cursor
- * @__i: int iteration cursor, for macro-internal use
  */
-#define drm_connector_for_each_possible_encoder(connector, encoder, __i) \
-       for ((__i) = 0; (__i) < ARRAY_SIZE((connector)->encoder_ids) && \
-                    (connector)->encoder_ids[(__i)] != 0; (__i)++) \
-               for_each_if((encoder) = \
-                           drm_encoder_find((connector)->dev, NULL, \
-                                            (connector)->encoder_ids[(__i)])) \
+#define drm_connector_for_each_possible_encoder(connector, encoder) \
+       drm_for_each_encoder_mask(encoder, (connector)->dev, \
+                                 (connector)->possible_encoders)
 
 #endif
index 408b6f4e63c0c15ed3cc48ba0c08e7317de878af..5e9b15a0e8c5c1304ba93e4e3d206c4439c8b56b 100644 (file)
@@ -41,7 +41,6 @@
 #include <drm/drm_connector.h>
 #include <drm/drm_device.h>
 #include <drm/drm_property.h>
-#include <drm/drm_bridge.h>
 #include <drm/drm_edid.h>
 #include <drm/drm_plane.h>
 #include <drm/drm_blend.h>
index 8364502f92cfe4545ea94cef2e9568b3afbd06e7..ed1a985745ba8c8d33c3b1623ba9c9ad4a20da9a 100644 (file)
  * 1.2 formally includes both eDP and DPI definitions.
  */
 
+/* MSA (Main Stream Attribute) MISC bits (as MISC1<<8|MISC0) */
+#define DP_MSA_MISC_SYNC_CLOCK                 (1 << 0)
+#define DP_MSA_MISC_INTERLACE_VTOTAL_EVEN      (1 << 8)
+#define DP_MSA_MISC_STEREO_NO_3D               (0 << 9)
+#define DP_MSA_MISC_STEREO_PROG_RIGHT_EYE      (1 << 9)
+#define DP_MSA_MISC_STEREO_PROG_LEFT_EYE       (3 << 9)
+/* bits per component for non-RAW */
+#define DP_MSA_MISC_6_BPC                      (0 << 5)
+#define DP_MSA_MISC_8_BPC                      (1 << 5)
+#define DP_MSA_MISC_10_BPC                     (2 << 5)
+#define DP_MSA_MISC_12_BPC                     (3 << 5)
+#define DP_MSA_MISC_16_BPC                     (4 << 5)
+/* bits per component for RAW */
+#define DP_MSA_MISC_RAW_6_BPC                  (1 << 5)
+#define DP_MSA_MISC_RAW_7_BPC                  (2 << 5)
+#define DP_MSA_MISC_RAW_8_BPC                  (3 << 5)
+#define DP_MSA_MISC_RAW_10_BPC                 (4 << 5)
+#define DP_MSA_MISC_RAW_12_BPC                 (5 << 5)
+#define DP_MSA_MISC_RAW_14_BPC                 (6 << 5)
+#define DP_MSA_MISC_RAW_16_BPC                 (7 << 5)
+/* pixel encoding/colorimetry format */
+#define _DP_MSA_MISC_COLOR(misc1_7, misc0_21, misc0_3, misc0_4) \
+       ((misc1_7) << 15 | (misc0_4) << 4 | (misc0_3) << 3 | ((misc0_21) << 1))
+#define DP_MSA_MISC_COLOR_RGB                  _DP_MSA_MISC_COLOR(0, 0, 0, 0)
+#define DP_MSA_MISC_COLOR_CEA_RGB              _DP_MSA_MISC_COLOR(0, 0, 1, 0)
+#define DP_MSA_MISC_COLOR_RGB_WIDE_FIXED       _DP_MSA_MISC_COLOR(0, 3, 0, 0)
+#define DP_MSA_MISC_COLOR_RGB_WIDE_FLOAT       _DP_MSA_MISC_COLOR(0, 3, 0, 1)
+#define DP_MSA_MISC_COLOR_Y_ONLY               _DP_MSA_MISC_COLOR(1, 0, 0, 0)
+#define DP_MSA_MISC_COLOR_RAW                  _DP_MSA_MISC_COLOR(1, 1, 0, 0)
+#define DP_MSA_MISC_COLOR_YCBCR_422_BT601      _DP_MSA_MISC_COLOR(0, 1, 1, 0)
+#define DP_MSA_MISC_COLOR_YCBCR_422_BT709      _DP_MSA_MISC_COLOR(0, 1, 1, 1)
+#define DP_MSA_MISC_COLOR_YCBCR_444_BT601      _DP_MSA_MISC_COLOR(0, 2, 1, 0)
+#define DP_MSA_MISC_COLOR_YCBCR_444_BT709      _DP_MSA_MISC_COLOR(0, 2, 1, 1)
+#define DP_MSA_MISC_COLOR_XVYCC_422_BT601      _DP_MSA_MISC_COLOR(0, 1, 0, 0)
+#define DP_MSA_MISC_COLOR_XVYCC_422_BT709      _DP_MSA_MISC_COLOR(0, 1, 0, 1)
+#define DP_MSA_MISC_COLOR_XVYCC_444_BT601      _DP_MSA_MISC_COLOR(0, 2, 0, 0)
+#define DP_MSA_MISC_COLOR_XVYCC_444_BT709      _DP_MSA_MISC_COLOR(0, 2, 0, 1)
+#define DP_MSA_MISC_COLOR_OPRGB                        _DP_MSA_MISC_COLOR(0, 0, 1, 1)
+#define DP_MSA_MISC_COLOR_DCI_P3               _DP_MSA_MISC_COLOR(0, 3, 1, 0)
+#define DP_MSA_MISC_COLOR_COLOR_PROFILE                _DP_MSA_MISC_COLOR(0, 3, 1, 1)
+#define DP_MSA_MISC_COLOR_VSC_SDP              (1 << 14)
+
 #define DP_AUX_MAX_PAYLOAD_BYTES       16
 
 #define DP_AUX_I2C_WRITE               0x0
@@ -1230,20 +1272,19 @@ struct drm_dp_aux_msg {
 
 struct cec_adapter;
 struct edid;
+struct drm_connector;
 
 /**
  * struct drm_dp_aux_cec - DisplayPort CEC-Tunneling-over-AUX
  * @lock: mutex protecting this struct
  * @adap: the CEC adapter for CEC-Tunneling-over-AUX support.
- * @name: name of the CEC adapter
- * @parent: parent device of the CEC adapter
+ * @connector: the connector this CEC adapter is associated with
  * @unregister_work: unregister the CEC adapter
  */
 struct drm_dp_aux_cec {
        struct mutex lock;
        struct cec_adapter *adap;
-       const char *name;
-       struct device *parent;
+       struct drm_connector *connector;
        struct delayed_work unregister_work;
 };
 
@@ -1451,8 +1492,8 @@ drm_dp_has_quirk(const struct drm_dp_desc *desc, enum drm_dp_quirk quirk)
 
 #ifdef CONFIG_DRM_DP_CEC
 void drm_dp_cec_irq(struct drm_dp_aux *aux);
-void drm_dp_cec_register_connector(struct drm_dp_aux *aux, const char *name,
-                                  struct device *parent);
+void drm_dp_cec_register_connector(struct drm_dp_aux *aux,
+                                  struct drm_connector *connector);
 void drm_dp_cec_unregister_connector(struct drm_dp_aux *aux);
 void drm_dp_cec_set_edid(struct drm_dp_aux *aux, const struct edid *edid);
 void drm_dp_cec_unset_edid(struct drm_dp_aux *aux);
@@ -1461,9 +1502,9 @@ static inline void drm_dp_cec_irq(struct drm_dp_aux *aux)
 {
 }
 
-static inline void drm_dp_cec_register_connector(struct drm_dp_aux *aux,
-                                                const char *name,
-                                                struct device *parent)
+static inline void
+drm_dp_cec_register_connector(struct drm_dp_aux *aux,
+                             struct drm_connector *connector)
 {
 }
 
index 2ba6253ea6d3fa3a005fb99c9c687d04990cd060..4a25e0577ae0311bcfc4db0ac4e4af27bf66f1c9 100644 (file)
@@ -287,7 +287,7 @@ struct drm_dp_remote_dpcd_write {
 struct drm_dp_remote_i2c_read {
        u8 num_transactions;
        u8 port_number;
-       struct {
+       struct drm_dp_remote_i2c_read_tx {
                u8 i2c_dev_id;
                u8 num_bytes;
                u8 *bytes;
@@ -334,7 +334,7 @@ struct drm_dp_resource_status_notify {
 
 struct drm_dp_query_payload_ack_reply {
        u8 port_number;
-       u8 allocated_pbn;
+       u16 allocated_pbn;
 };
 
 struct drm_dp_sideband_msg_req_body {
@@ -481,15 +481,11 @@ struct drm_dp_mst_topology_mgr {
        int conn_base_id;
 
        /**
-        * @down_rep_recv: Message receiver state for down replies. This and
-        * @up_req_recv are only ever access from the work item, which is
-        * serialised.
+        * @down_rep_recv: Message receiver state for down replies.
         */
        struct drm_dp_sideband_msg_rx down_rep_recv;
        /**
-        * @up_req_recv: Message receiver state for up requests. This and
-        * @down_rep_recv are only ever access from the work item, which is
-        * serialised.
+        * @up_req_recv: Message receiver state for up requests.
         */
        struct drm_dp_sideband_msg_rx up_req_recv;
 
index 8976afe48c1c4237efb4bbd924a5d6f4041266d5..cf13470810a5e036d27ba26f258817b4486bd2c2 100644 (file)
@@ -778,8 +778,6 @@ struct drm_driver {
        int dev_priv_size;
 };
 
-extern unsigned int drm_debug;
-
 int drm_dev_init(struct drm_device *dev,
                 struct drm_driver *driver,
                 struct device *parent);
index 70cfca03d812e4a751fdbe122f632d06235d0b36..f06164f44efea7a5b7aca33ad89414a0b49ca8f0 100644 (file)
@@ -140,7 +140,7 @@ struct drm_encoder {
         * @possible_crtcs: Bitmask of potential CRTC bindings, using
         * drm_crtc_index() as the index into the bitfield. The driver must set
         * the bits for all &drm_crtc objects this encoder can be connected to
-        * before calling drm_encoder_init().
+        * before calling drm_dev_register().
         *
         * In reality almost every driver gets this wrong.
         *
@@ -154,7 +154,7 @@ struct drm_encoder {
         * using drm_encoder_index() as the index into the bitfield. The driver
         * must set the bits for all &drm_encoder objects which can clone a
         * &drm_crtc together with this encoder before calling
-        * drm_encoder_init(). Drivers should set the bit representing the
+        * drm_dev_register(). Drivers should set the bit representing the
         * encoder itself, too. Cloning bits should be set such that when two
         * encoders can be used in a cloned configuration, they both should have
         * each another bits set.
@@ -198,7 +198,7 @@ static inline unsigned int drm_encoder_index(const struct drm_encoder *encoder)
 }
 
 /**
- * drm_encoder_mask - find the mask of a registered ENCODER
+ * drm_encoder_mask - find the mask of a registered encoder
  * @encoder: encoder to find mask for
  *
  * Given a registered encoder, return the mask bit of that encoder for an
index c8a8ae2a678a7eb5dbbf2ef5a039d06d51186aee..8dcc012ccbc853922fac6f08030f65bbe1541e1e 100644 (file)
@@ -539,18 +539,16 @@ drm_fb_helper_remove_conflicting_framebuffers(struct apertures_struct *a,
 /**
  * drm_fb_helper_remove_conflicting_pci_framebuffers - remove firmware-configured framebuffers for PCI devices
  * @pdev: PCI device
- * @resource_id: index of PCI BAR configuring framebuffer memory
  * @name: requesting driver name
  *
  * This function removes framebuffer devices (eg. initialized by firmware)
- * using memory range configured for @pdev's BAR @resource_id.
+ * using memory range configured for any of @pdev's memory bars.
  *
  * The function assumes that PCI device with shadowed ROM drives a primary
  * display and so kicks out vga16fb.
  */
 static inline int
 drm_fb_helper_remove_conflicting_pci_framebuffers(struct pci_dev *pdev,
-                                                 int resource_id,
                                                  const char *name)
 {
        int ret = 0;
@@ -560,7 +558,7 @@ drm_fb_helper_remove_conflicting_pci_framebuffers(struct pci_dev *pdev,
         * otherwise the vga fbdev driver falls over.
         */
 #if IS_REACHABLE(CONFIG_FB)
-       ret = remove_conflicting_pci_framebuffers(pdev, resource_id, name);
+       ret = remove_conflicting_pci_framebuffers(pdev, name);
 #endif
        if (ret == 0)
                ret = vga_remove_vgacon(pdev);
diff --git a/include/drm/drm_gem_ttm_helper.h b/include/drm/drm_gem_ttm_helper.h
new file mode 100644 (file)
index 0000000..6268f89
--- /dev/null
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#ifndef DRM_GEM_TTM_HELPER_H
+#define DRM_GEM_TTM_HELPER_H
+
+#include <linux/kernel.h>
+
+#include <drm/drm_gem.h>
+#include <drm/drm_device.h>
+#include <drm/ttm/ttm_bo_api.h>
+#include <drm/ttm/ttm_bo_driver.h>
+
+#define drm_gem_ttm_of_gem(gem_obj) \
+       container_of(gem_obj, struct ttm_buffer_object, base)
+
+void drm_gem_ttm_print_info(struct drm_printer *p, unsigned int indent,
+                           const struct drm_gem_object *gem);
+
+#endif
index ac217d7684566b5afaf4d7846d99c1a5b72d5e9f..354a9cd358a37cd01f496c4afae1eb3ea05ca801 100644 (file)
@@ -3,9 +3,13 @@
 #ifndef DRM_GEM_VRAM_HELPER_H
 #define DRM_GEM_VRAM_HELPER_H
 
+#include <drm/drm_file.h>
 #include <drm/drm_gem.h>
+#include <drm/drm_ioctl.h>
 #include <drm/ttm/ttm_bo_api.h>
+#include <drm/ttm/ttm_bo_driver.h>
 #include <drm/ttm/ttm_placement.h>
+
 #include <linux/kernel.h> /* for container_of() */
 
 struct drm_mode_create_dumb;
@@ -15,6 +19,7 @@ struct vm_area_struct;
 
 #define DRM_GEM_VRAM_PL_FLAG_VRAM      TTM_PL_FLAG_VRAM
 #define DRM_GEM_VRAM_PL_FLAG_SYSTEM    TTM_PL_FLAG_SYSTEM
+#define DRM_GEM_VRAM_PL_FLAG_TOPDOWN   TTM_PL_FLAG_TOPDOWN
 
 /*
  * Buffer-object helpers
@@ -34,11 +39,26 @@ struct vm_area_struct;
  * backed by VRAM. It can be used for simple framebuffer devices with
  * dedicated memory. The buffer object can be evicted to system memory if
  * video memory becomes scarce.
+ *
+ * GEM VRAM objects perform reference counting for pin and mapping
+ * operations. So a buffer object that has been pinned N times with
+ * drm_gem_vram_pin() must be unpinned N times with
+ * drm_gem_vram_unpin(). The same applies to pairs of
+ * drm_gem_vram_kmap() and drm_gem_vram_kunmap(), as well as pairs of
+ * drm_gem_vram_vmap() and drm_gem_vram_vunmap().
  */
 struct drm_gem_vram_object {
        struct ttm_buffer_object bo;
        struct ttm_bo_kmap_obj kmap;
 
+       /**
+        * @kmap_use_count:
+        *
+        * Reference count on the virtual address.
+        * The address are un-mapped when the count reaches zero.
+        */
+       unsigned int kmap_use_count;
+
        /* Supported placements are %TTM_PL_VRAM and %TTM_PL_SYSTEM */
        struct ttm_placement placement;
        struct ttm_place placements[2];
@@ -83,6 +103,8 @@ int drm_gem_vram_unpin(struct drm_gem_vram_object *gbo);
 void *drm_gem_vram_kmap(struct drm_gem_vram_object *gbo, bool map,
                        bool *is_iomem);
 void drm_gem_vram_kunmap(struct drm_gem_vram_object *gbo);
+void *drm_gem_vram_vmap(struct drm_gem_vram_object *gbo);
+void drm_gem_vram_vunmap(struct drm_gem_vram_object *gbo, void *vaddr);
 
 int drm_gem_vram_fill_create_dumb(struct drm_file *file,
                                  struct drm_device *dev,
@@ -91,18 +113,6 @@ int drm_gem_vram_fill_create_dumb(struct drm_file *file,
                                  bool interruptible,
                                  struct drm_mode_create_dumb *args);
 
-/*
- * Helpers for struct ttm_bo_driver
- */
-
-void drm_gem_vram_bo_driver_evict_flags(struct ttm_buffer_object *bo,
-                                       struct ttm_placement *pl);
-
-int drm_gem_vram_bo_driver_verify_access(struct ttm_buffer_object *bo,
-                                        struct file *filp);
-
-extern const struct drm_vram_mm_funcs drm_gem_vram_mm_funcs;
-
 /*
  * Helpers for struct drm_driver
  */
@@ -122,8 +132,81 @@ int drm_gem_vram_driver_dumb_mmap_offset(struct drm_file *file,
  * &struct drm_driver with default functions.
  */
 #define DRM_GEM_VRAM_DRIVER \
+       .debugfs_init             = drm_vram_mm_debugfs_init, \
        .dumb_create              = drm_gem_vram_driver_dumb_create, \
        .dumb_map_offset          = drm_gem_vram_driver_dumb_mmap_offset, \
        .gem_prime_mmap           = drm_gem_prime_mmap
 
+/*
+ *  VRAM memory manager
+ */
+
+/**
+ * struct drm_vram_mm - An instance of VRAM MM
+ * @vram_base: Base address of the managed video memory
+ * @vram_size: Size of the managed video memory in bytes
+ * @bdev:      The TTM BO device.
+ * @funcs:     TTM BO functions
+ *
+ * The fields &struct drm_vram_mm.vram_base and
+ * &struct drm_vram_mm.vrm_size are managed by VRAM MM, but are
+ * available for public read access. Use the field
+ * &struct drm_vram_mm.bdev to access the TTM BO device.
+ */
+struct drm_vram_mm {
+       uint64_t vram_base;
+       size_t vram_size;
+
+       struct ttm_bo_device bdev;
+};
+
+/**
+ * drm_vram_mm_of_bdev() - \
+       Returns the container of type &struct ttm_bo_device for field bdev.
+ * @bdev:      the TTM BO device
+ *
+ * Returns:
+ * The containing instance of &struct drm_vram_mm
+ */
+static inline struct drm_vram_mm *drm_vram_mm_of_bdev(
+       struct ttm_bo_device *bdev)
+{
+       return container_of(bdev, struct drm_vram_mm, bdev);
+}
+
+int drm_vram_mm_debugfs_init(struct drm_minor *minor);
+
+/*
+ * Helpers for integration with struct drm_device
+ */
+
+struct drm_vram_mm *drm_vram_helper_alloc_mm(
+       struct drm_device *dev, uint64_t vram_base, size_t vram_size);
+void drm_vram_helper_release_mm(struct drm_device *dev);
+
+/*
+ * Helpers for &struct file_operations
+ */
+
+int drm_vram_mm_file_operations_mmap(
+       struct file *filp, struct vm_area_struct *vma);
+
+/**
+ * define DRM_VRAM_MM_FILE_OPERATIONS - default callback functions for \
+       &struct file_operations
+ *
+ * Drivers that use VRAM MM can use this macro to initialize
+ * &struct file_operations with default functions.
+ */
+#define DRM_VRAM_MM_FILE_OPERATIONS \
+       .llseek         = no_llseek, \
+       .read           = drm_read, \
+       .poll           = drm_poll, \
+       .unlocked_ioctl = drm_ioctl, \
+       .compat_ioctl   = drm_compat_ioctl, \
+       .mmap           = drm_vram_mm_file_operations_mmap, \
+       .open           = drm_open, \
+       .release        = drm_release \
+
+
 #endif
index 6b18c8adfe9dcb5e8282fa07e13d9cbcf2e4402b..5a87f1bd7a3f320b9e7f4f878535fe7764ad81b2 100644 (file)
@@ -955,9 +955,8 @@ struct drm_connector_helper_funcs {
         * @atomic_best_encoder.
         *
         * You can leave this function to NULL if the connector is only
-        * attached to a single encoder and you are using the atomic helpers.
-        * In this case, the core will call drm_atomic_helper_best_encoder()
-        * for you.
+        * attached to a single encoder. In this case, the core will call
+        * drm_connector_get_single_encoder() for you.
         *
         * RETURNS:
         *
@@ -977,7 +976,7 @@ struct drm_connector_helper_funcs {
         *
         * This function is used by drm_atomic_helper_check_modeset().
         * If it is not implemented, the core will fallback to @best_encoder
-        * (or drm_atomic_helper_best_encoder() if @best_encoder is NULL).
+        * (or drm_connector_get_single_encoder() if @best_encoder is NULL).
         *
         * NOTE:
         *
index 7b8841065b11876faea882b4122100d3b5c82f57..4fc9a43ac45a8f3c61b5542ae423747adb21056a 100644 (file)
@@ -114,6 +114,15 @@ static inline bool drm_modeset_is_locked(struct drm_modeset_lock *lock)
        return ww_mutex_is_locked(&lock->mutex);
 }
 
+/**
+ * drm_modeset_lock_assert_held - equivalent to lockdep_assert_held()
+ * @lock: lock to check
+ */
+static inline void drm_modeset_lock_assert_held(struct drm_modeset_lock *lock)
+{
+       lockdep_assert_held(&lock->mutex.base);
+}
+
 int drm_modeset_lock(struct drm_modeset_lock *lock,
                struct drm_modeset_acquire_ctx *ctx);
 int __must_check drm_modeset_lock_single_interruptible(struct drm_modeset_lock *lock);
index 624bd15ecfab61869a9132a10bf208d516084838..ce8da64022b43e7323a49b0a3be5a7ecf86a3691 100644 (file)
@@ -139,6 +139,15 @@ struct drm_panel {
         */
        const struct drm_panel_funcs *funcs;
 
+       /**
+        * @connector_type:
+        *
+        * Type of the panel as a DRM_MODE_CONNECTOR_* value. This is used to
+        * initialise the drm_connector corresponding to the panel with the
+        * correct connector type.
+        */
+       int connector_type;
+
        /**
         * @list:
         *
@@ -147,7 +156,9 @@ struct drm_panel {
        struct list_head list;
 };
 
-void drm_panel_init(struct drm_panel *panel);
+void drm_panel_init(struct drm_panel *panel, struct device *dev,
+                   const struct drm_panel_funcs *funcs,
+                   int connector_type);
 
 int drm_panel_add(struct drm_panel *panel);
 void drm_panel_remove(struct drm_panel *panel);
index d89311b822d508c7305fa20d5dbc37cf4678d53d..9af7422b44cf0fb712223c3b24330a737b85a9dd 100644 (file)
@@ -61,8 +61,6 @@ struct drm_device;
 struct drm_gem_object;
 struct drm_file;
 
-struct device;
-
 /* core prime functions */
 struct dma_buf *drm_gem_dmabuf_export(struct drm_device *dev,
                                      struct dma_buf_export_info *exp_info);
index a5d6f2f3e430fa85df646eaf1fcfa0a4fccfdd03..5b8049992c2400f38f220d2db00b3b1e981d5ec4 100644 (file)
@@ -34,6 +34,8 @@
 
 #include <drm/drm.h>
 
+extern unsigned int drm_debug;
+
 /**
  * DOC: print
  *
@@ -83,11 +85,14 @@ void __drm_printfn_seq_file(struct drm_printer *p, struct va_format *vaf);
 void __drm_puts_seq_file(struct drm_printer *p, const char *str);
 void __drm_printfn_info(struct drm_printer *p, struct va_format *vaf);
 void __drm_printfn_debug(struct drm_printer *p, struct va_format *vaf);
+void __drm_printfn_err(struct drm_printer *p, struct va_format *vaf);
 
 __printf(2, 3)
 void drm_printf(struct drm_printer *p, const char *f, ...);
 void drm_puts(struct drm_printer *p, const char *str);
 void drm_print_regset32(struct drm_printer *p, struct debugfs_regset32 *regset);
+void drm_print_bits(struct drm_printer *p, unsigned long value,
+                   const char * const bits[], unsigned int nbits);
 
 __printf(2, 0)
 /**
@@ -227,6 +232,22 @@ static inline struct drm_printer drm_debug_printer(const char *prefix)
        return p;
 }
 
+/**
+ * drm_err_printer - construct a &drm_printer that outputs to pr_err()
+ * @prefix: debug output prefix
+ *
+ * RETURNS:
+ * The &drm_printer object
+ */
+static inline struct drm_printer drm_err_printer(const char *prefix)
+{
+       struct drm_printer p = {
+               .printfn = __drm_printfn_err,
+               .prefix = prefix
+       };
+       return p;
+}
+
 /*
  * The following categories are defined:
  *
@@ -272,6 +293,11 @@ static inline struct drm_printer drm_debug_printer(const char *prefix)
 #define DRM_UT_LEASE           0x80
 #define DRM_UT_DP              0x100
 
+static inline bool drm_debug_enabled(unsigned int category)
+{
+       return unlikely(drm_debug & category);
+}
+
 __printf(3, 4)
 void drm_dev_printk(const struct device *dev, const char *level,
                    const char *format, ...);
index 6195820aa5c5f539946532d38578cefa47e5f341..cd0106135b6ad5131c74c72c36f608686d64e277 100644 (file)
@@ -69,6 +69,23 @@ struct drm_rect {
                (r)->x1 >> 16, (((r)->x1 & 0xffff) * 15625) >> 10, \
                (r)->y1 >> 16, (((r)->y1 & 0xffff) * 15625) >> 10
 
+/**
+ * drm_rect_init - initialize the rectangle from x/y/w/h
+ * @r: rectangle
+ * @x: x coordinate
+ * @y: y coordinate
+ * @width: width
+ * @height: height
+ */
+static inline void drm_rect_init(struct drm_rect *r, int x, int y,
+                                int width, int height)
+{
+       r->x1 = x;
+       r->y1 = y;
+       r->x2 = x + width;
+       r->y2 = y + height;
+}
+
 /**
  * drm_rect_adjust_size - adjust the size of the rectangle
  * @r: rectangle to be adjusted
@@ -106,6 +123,20 @@ static inline void drm_rect_translate(struct drm_rect *r, int dx, int dy)
        r->y2 += dy;
 }
 
+/**
+ * drm_rect_translate_to - translate the rectangle to an absolute position
+ * @r: rectangle to be tranlated
+ * @x: horizontal position
+ * @y: vertical position
+ *
+ * Move rectangle @r to @x in the horizontal direction,
+ * and to @y in the vertical direction.
+ */
+static inline void drm_rect_translate_to(struct drm_rect *r, int x, int y)
+{
+       drm_rect_translate(r, x - r->x1, y - r->y1);
+}
+
 /**
  * drm_rect_downscale - downscale a rectangle
  * @r: rectangle to be downscaled
index 9fe4ba8bc622cdf18f0da9a983f094fa066d9c68..c16c44052b3dc1b69d82a7364756507b5a2f6a67 100644 (file)
@@ -109,9 +109,20 @@ struct drm_vblank_crtc {
        seqlock_t seqlock;
 
        /**
-        * @count: Current software vblank counter.
+        * @count:
+        *
+        * Current software vblank counter.
+        *
+        * Note that for a given vblank counter value drm_crtc_handle_vblank()
+        * and drm_crtc_vblank_count() or drm_crtc_vblank_count_and_time()
+        * provide a barrier: Any writes done before calling
+        * drm_crtc_handle_vblank() will be visible to callers of the later
+        * functions, iff the vblank count is the same or a later one.
+        *
+        * IMPORTANT: This guarantee requires barriers, therefor never access
+        * this field directly. Use drm_crtc_vblank_count() instead.
         */
-       u64 count;
+       atomic64_t count;
        /**
         * @time: Vblank timestamp corresponding to @count.
         */
diff --git a/include/drm/drm_vram_mm_helper.h b/include/drm/drm_vram_mm_helper.h
deleted file mode 100644 (file)
index 2aacfb1..0000000
+++ /dev/null
@@ -1,104 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-
-#ifndef DRM_VRAM_MM_HELPER_H
-#define DRM_VRAM_MM_HELPER_H
-
-#include <drm/drm_file.h>
-#include <drm/drm_ioctl.h>
-#include <drm/ttm/ttm_bo_driver.h>
-
-struct drm_device;
-
-/**
- * struct drm_vram_mm_funcs - Callback functions for &struct drm_vram_mm
- * @evict_flags:       Provides an implementation for struct \
-       &ttm_bo_driver.evict_flags
- * @verify_access:     Provides an implementation for \
-       struct &ttm_bo_driver.verify_access
- *
- * These callback function integrate VRAM MM with TTM buffer objects. New
- * functions can be added if necessary.
- */
-struct drm_vram_mm_funcs {
-       void (*evict_flags)(struct ttm_buffer_object *bo,
-                           struct ttm_placement *placement);
-       int (*verify_access)(struct ttm_buffer_object *bo, struct file *filp);
-};
-
-/**
- * struct drm_vram_mm - An instance of VRAM MM
- * @vram_base: Base address of the managed video memory
- * @vram_size: Size of the managed video memory in bytes
- * @bdev:      The TTM BO device.
- * @funcs:     TTM BO functions
- *
- * The fields &struct drm_vram_mm.vram_base and
- * &struct drm_vram_mm.vrm_size are managed by VRAM MM, but are
- * available for public read access. Use the field
- * &struct drm_vram_mm.bdev to access the TTM BO device.
- */
-struct drm_vram_mm {
-       uint64_t vram_base;
-       size_t vram_size;
-
-       struct ttm_bo_device bdev;
-
-       const struct drm_vram_mm_funcs *funcs;
-};
-
-/**
- * drm_vram_mm_of_bdev() - \
-       Returns the container of type &struct ttm_bo_device for field bdev.
- * @bdev:      the TTM BO device
- *
- * Returns:
- * The containing instance of &struct drm_vram_mm
- */
-static inline struct drm_vram_mm *drm_vram_mm_of_bdev(
-       struct ttm_bo_device *bdev)
-{
-       return container_of(bdev, struct drm_vram_mm, bdev);
-}
-
-int drm_vram_mm_init(struct drm_vram_mm *vmm, struct drm_device *dev,
-                    uint64_t vram_base, size_t vram_size,
-                    const struct drm_vram_mm_funcs *funcs);
-void drm_vram_mm_cleanup(struct drm_vram_mm *vmm);
-
-int drm_vram_mm_mmap(struct file *filp, struct vm_area_struct *vma,
-                    struct drm_vram_mm *vmm);
-
-/*
- * Helpers for integration with struct drm_device
- */
-
-struct drm_vram_mm *drm_vram_helper_alloc_mm(
-       struct drm_device *dev, uint64_t vram_base, size_t vram_size,
-       const struct drm_vram_mm_funcs *funcs);
-void drm_vram_helper_release_mm(struct drm_device *dev);
-
-/*
- * Helpers for &struct file_operations
- */
-
-int drm_vram_mm_file_operations_mmap(
-       struct file *filp, struct vm_area_struct *vma);
-
-/**
- * define DRM_VRAM_MM_FILE_OPERATIONS - default callback functions for \
-       &struct file_operations
- *
- * Drivers that use VRAM MM can use this macro to initialize
- * &struct file_operations with default functions.
- */
-#define DRM_VRAM_MM_FILE_OPERATIONS \
-       .llseek         = no_llseek, \
-       .read           = drm_read, \
-       .poll           = drm_poll, \
-       .unlocked_ioctl = drm_ioctl, \
-       .compat_ioctl   = drm_compat_ioctl, \
-       .mmap           = drm_vram_mm_file_operations_mmap, \
-       .open           = drm_open, \
-       .release        = drm_release \
-
-#endif
index 6f536caea368ba7fe60e12ead27941e17aa42d95..27b9d5be197f22cd88de4a62630985287ad9a468 100644 (file)
@@ -451,7 +451,7 @@ extern struct ttm_bo_global {
  *
  * @driver: Pointer to a struct ttm_bo_driver struct setup by the driver.
  * @man: An array of mem_type_managers.
- * @vma_manager: Address space manager
+ * @vma_manager: Address space manager (pointer)
  * lru_lock: Spinlock that protects the buffer+device lru lists and
  * ddestroy lists.
  * @dev_mapping: A pointer to the struct address_space representing the
@@ -474,7 +474,7 @@ struct ttm_bo_device {
        /*
         * Protected by internal locks.
         */
-       struct drm_vma_offset_manager vma_manager;
+       struct drm_vma_offset_manager *vma_manager;
 
        /*
         * Protected by the global:lru lock.
@@ -595,6 +595,7 @@ int ttm_bo_device_release(struct ttm_bo_device *bdev);
  * @glob: A pointer to an initialized struct ttm_bo_global.
  * @driver: A pointer to a struct ttm_bo_driver set up by the caller.
  * @mapping: The address space to use for this bo.
+ * @vma_manager: A pointer to a vma manager.
  * @file_page_offset: Offset into the device address space that is available
  * for buffer data. This ensures compatibility with other users of the
  * address space.
@@ -606,6 +607,7 @@ int ttm_bo_device_release(struct ttm_bo_device *bdev);
 int ttm_bo_device_init(struct ttm_bo_device *bdev,
                       struct ttm_bo_driver *driver,
                       struct address_space *mapping,
+                      struct drm_vma_offset_manager *vma_manager,
                       bool need_dma32);
 
 /**
index 756706b666a109fa8718df5f75fb2dc3b58bc0b8..41e0069eca0a2fc8e388f48e0fff5de4b800af4b 100644 (file)
@@ -607,7 +607,7 @@ extern ssize_t fb_sys_write(struct fb_info *info, const char __user *buf,
 extern int register_framebuffer(struct fb_info *fb_info);
 extern void unregister_framebuffer(struct fb_info *fb_info);
 extern void unlink_framebuffer(struct fb_info *fb_info);
-extern int remove_conflicting_pci_framebuffers(struct pci_dev *pdev, int res_id,
+extern int remove_conflicting_pci_framebuffers(struct pci_dev *pdev,
                                               const char *name);
 extern int remove_conflicting_framebuffers(struct apertures_struct *a,
                                           const char *name, bool primary);
index 58fbe48c91e905af2af35a888ea170fa411e3b81..1ce746e228d99bc7c3569c48692a0dcc490c17fa 100644 (file)
@@ -48,6 +48,8 @@ extern "C" {
 #define DRM_IOCTL_V3D_SUBMIT_TFU          DRM_IOW(DRM_COMMAND_BASE + DRM_V3D_SUBMIT_TFU, struct drm_v3d_submit_tfu)
 #define DRM_IOCTL_V3D_SUBMIT_CSD          DRM_IOW(DRM_COMMAND_BASE + DRM_V3D_SUBMIT_CSD, struct drm_v3d_submit_csd)
 
+#define DRM_V3D_SUBMIT_CL_FLUSH_CACHE             0x01
+
 /**
  * struct drm_v3d_submit_cl - ioctl argument for submitting commands to the 3D
  * engine.
@@ -61,7 +63,7 @@ extern "C" {
  * flushed by the time the render done IRQ happens, which is the
  * trigger for out_sync.  Any dirtying of cachelines by the job (only
  * possible using TMU writes) must be flushed by the caller using the
- * CL's cache flush commands.
+ * DRM_V3D_SUBMIT_CL_FLUSH_CACHE_FLAG flag.
  */
 struct drm_v3d_submit_cl {
        /* Pointer to the binner command list.
@@ -124,8 +126,7 @@ struct drm_v3d_submit_cl {
        /* Number of BO handles passed in (size is that times 4). */
        __u32 bo_handle_count;
 
-       /* Pad, must be zero-filled. */
-       __u32 pad;
+       __u32 flags;
 };
 
 /**
@@ -193,6 +194,7 @@ enum drm_v3d_param {
        DRM_V3D_PARAM_V3D_CORE0_IDENT2,
        DRM_V3D_PARAM_SUPPORTS_TFU,
        DRM_V3D_PARAM_SUPPORTS_CSD,
+       DRM_V3D_PARAM_SUPPORTS_CACHE_FLUSH,
 };
 
 struct drm_v3d_get_param {