Merge drm/drm-next into drm-misc-next
authorMaxime Ripard <mripard@kernel.org>
Mon, 29 Jan 2024 13:20:23 +0000 (14:20 +0100)
committerMaxime Ripard <mripard@kernel.org>
Mon, 29 Jan 2024 13:20:23 +0000 (14:20 +0100)
Kickstart 6.9 development cycle.

Signed-off-by: Maxime Ripard <mripard@kernel.org>
163 files changed:
Documentation/devicetree/bindings/display/panel/boe,th101mb31ig002-28a.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/display/panel/novatek,nt35510.yaml
Documentation/devicetree/bindings/display/panel/novatek,nt36672e.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/display/panel/panel-lvds.yaml
Documentation/devicetree/bindings/display/panel/panel-simple.yaml
Documentation/devicetree/bindings/display/solomon,ssd1307fb.yaml
Documentation/devicetree/bindings/display/solomon,ssd132x.yaml
Documentation/devicetree/bindings/display/solomon,ssd133x.yaml [new file with mode: 0644]
Documentation/gpu/drm-internals.rst
Documentation/gpu/introduction.rst
Documentation/gpu/rfc/index.rst
Documentation/gpu/rfc/xe.rst [deleted file]
Documentation/gpu/todo.rst
MAINTAINERS
drivers/accel/qaic/mhi_controller.c
drivers/accel/qaic/qaic.h
drivers/accel/qaic/qaic_data.c
drivers/accel/qaic/qaic_drv.c
drivers/dma-buf/dma-fence.c
drivers/dma-buf/dma-resv.c
drivers/gpu/drm/Kconfig
drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
drivers/gpu/drm/bridge/ite-it6505.c
drivers/gpu/drm/bridge/lontium-lt9611.c
drivers/gpu/drm/bridge/lontium-lt9611uxc.c
drivers/gpu/drm/bridge/samsung-dsim.c
drivers/gpu/drm/bridge/sii902x.c
drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
drivers/gpu/drm/bridge/tc358767.c
drivers/gpu/drm/ci/build.sh
drivers/gpu/drm/ci/gitlab-ci.yml
drivers/gpu/drm/ci/test.yml
drivers/gpu/drm/ci/testlist.txt
drivers/gpu/drm/ci/xfails/msm-apq8016-fails.txt
drivers/gpu/drm/ci/xfails/msm-sc7180-fails.txt [deleted file]
drivers/gpu/drm/ci/xfails/msm-sc7180-flakes.txt [deleted file]
drivers/gpu/drm/ci/xfails/msm-sc7180-skips.txt [deleted file]
drivers/gpu/drm/ci/xfails/msm-sc7180-trogdor-kingoftown-fails.txt [new file with mode: 0644]
drivers/gpu/drm/ci/xfails/msm-sc7180-trogdor-lazor-limozeen-fails.txt [new file with mode: 0644]
drivers/gpu/drm/ci/xfails/msm-sdm845-fails.txt
drivers/gpu/drm/ci/xfails/msm-sdm845-flakes.txt
drivers/gpu/drm/ci/xfails/msm-sdm845-skips.txt
drivers/gpu/drm/drm_debugfs.c
drivers/gpu/drm/drm_edid.c
drivers/gpu/drm/drm_exec.c
drivers/gpu/drm/drm_gem_vram_helper.c
drivers/gpu/drm/drm_ioc32.c
drivers/gpu/drm/drm_managed.c
drivers/gpu/drm/drm_modes.c
drivers/gpu/drm/drm_panel_orientation_quirks.c
drivers/gpu/drm/drm_probe_helper.c
drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c
drivers/gpu/drm/i915/gem/i915_gem_ttm.c
drivers/gpu/drm/ingenic/Kconfig
drivers/gpu/drm/lima/lima_gem.c
drivers/gpu/drm/loongson/lsdc_drv.c
drivers/gpu/drm/loongson/lsdc_ttm.c
drivers/gpu/drm/mcde/Kconfig
drivers/gpu/drm/mgag200/mgag200_drv.c
drivers/gpu/drm/mgag200/mgag200_mode.c
drivers/gpu/drm/msm/dp/dp_display.c
drivers/gpu/drm/nouveau/dispnv04/crtc.c
drivers/gpu/drm/nouveau/dispnv50/head.c
drivers/gpu/drm/nouveau/nouveau_bo.c
drivers/gpu/drm/nouveau/nouveau_bo.h
drivers/gpu/drm/nouveau/nouveau_connector.h
drivers/gpu/drm/nouveau/nouveau_ioc32.c
drivers/gpu/drm/nouveau/nvif/outp.c
drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c
drivers/gpu/drm/nouveau/nvkm/subdev/bios/init.c
drivers/gpu/drm/nouveau/nvkm/subdev/volt/gk20a.c
drivers/gpu/drm/panel/Kconfig
drivers/gpu/drm/panel/Makefile
drivers/gpu/drm/panel/panel-boe-himax8279d.c
drivers/gpu/drm/panel/panel-boe-th101mb31ig002-28a.c [new file with mode: 0644]
drivers/gpu/drm/panel/panel-edp.c
drivers/gpu/drm/panel/panel-leadtek-ltk050h3146w.c
drivers/gpu/drm/panel/panel-novatek-nt35510.c
drivers/gpu/drm/panel/panel-novatek-nt36523.c
drivers/gpu/drm/panel/panel-novatek-nt36672e.c [new file with mode: 0644]
drivers/gpu/drm/panel/panel-simple.c
drivers/gpu/drm/pl111/Kconfig
drivers/gpu/drm/qxl/qxl_object.c
drivers/gpu/drm/qxl/qxl_ttm.c
drivers/gpu/drm/radeon/radeon_object.c
drivers/gpu/drm/radeon/radeon_ttm.c
drivers/gpu/drm/radeon/radeon_uvd.c
drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
drivers/gpu/drm/rockchip/inno_hdmi.c
drivers/gpu/drm/rockchip/inno_hdmi.h
drivers/gpu/drm/rockchip/rockchip_lvds.c
drivers/gpu/drm/rockchip/rockchip_vop_reg.c
drivers/gpu/drm/rockchip/rockchip_vop_reg.h
drivers/gpu/drm/scheduler/sched_main.c
drivers/gpu/drm/solomon/ssd130x-spi.c
drivers/gpu/drm/solomon/ssd130x.c
drivers/gpu/drm/solomon/ssd130x.h
drivers/gpu/drm/tegra/dpaux.c
drivers/gpu/drm/tegra/drm.h
drivers/gpu/drm/tegra/dsi.c
drivers/gpu/drm/tegra/hdmi.c
drivers/gpu/drm/tegra/output.c
drivers/gpu/drm/tegra/rgb.c
drivers/gpu/drm/tegra/sor.c
drivers/gpu/drm/tests/drm_managed_test.c
drivers/gpu/drm/tilcdc/tilcdc_drv.c
drivers/gpu/drm/ttm/tests/Makefile
drivers/gpu/drm/ttm/tests/ttm_bo_test.c [new file with mode: 0644]
drivers/gpu/drm/ttm/tests/ttm_kunit_helpers.c
drivers/gpu/drm/ttm/tests/ttm_kunit_helpers.h
drivers/gpu/drm/ttm/tests/ttm_pool_test.c
drivers/gpu/drm/ttm/tests/ttm_resource_test.c [new file with mode: 0644]
drivers/gpu/drm/ttm/tests/ttm_tt_test.c [new file with mode: 0644]
drivers/gpu/drm/ttm/ttm_bo.c
drivers/gpu/drm/ttm/ttm_bo_util.c
drivers/gpu/drm/ttm/ttm_resource.c
drivers/gpu/drm/ttm/ttm_tt.c
drivers/gpu/drm/tve200/Kconfig
drivers/gpu/drm/v3d/v3d_debugfs.c
drivers/gpu/drm/vc4/vc4_hdmi.c
drivers/gpu/drm/vc4/vc4_plane.c
drivers/gpu/drm/virtio/virtgpu_submit.c
drivers/gpu/drm/vkms/Kconfig [new file with mode: 0644]
drivers/gpu/drm/vkms/vkms_composer.c
drivers/gpu/drm/vmwgfx/vmwgfx_bo.c
drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c
drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
drivers/gpu/drm/vmwgfx/vmwgfx_surface.c
drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c
drivers/media/i2c/tc358743.c
drivers/staging/sm750fb/Kconfig
drivers/video/Kconfig
drivers/video/Makefile
drivers/video/cmdline.c
drivers/video/fbdev/Kconfig
drivers/video/fbdev/core/Kconfig
drivers/video/fbdev/core/fbmem.c
drivers/video/fbdev/efifb.c
drivers/video/fbdev/geode/Kconfig
drivers/video/fbdev/simplefb.c
drivers/video/fbdev/vesafb.c
include/drm/drm_atomic.h
include/drm/drm_edid.h
include/drm/drm_exec.h
include/drm/drm_fixed.h
include/drm/drm_gpuvm.h
include/drm/drm_managed.h
include/drm/drm_modes.h
include/drm/drm_probe_helper.h
include/drm/ttm/ttm_placement.h
include/drm/ttm/ttm_resource.h
include/drm/ttm/ttm_tt.h
include/linux/fb.h
include/sound/hdmi-codec.h
include/uapi/drm/nouveau_drm.h
include/uapi/drm/qaic_accel.h
include/uapi/linux/virtio_gpu.h
include/video/cmdline.h

diff --git a/Documentation/devicetree/bindings/display/panel/boe,th101mb31ig002-28a.yaml b/Documentation/devicetree/bindings/display/panel/boe,th101mb31ig002-28a.yaml
new file mode 100644 (file)
index 0000000..32df26c
--- /dev/null
@@ -0,0 +1,58 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/panel/boe,th101mb31ig002-28a.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: BOE TH101MB31IG002-28A WXGA DSI Display Panel
+
+maintainers:
+  - Manuel Traut <manut@mecka.net>
+
+allOf:
+  - $ref: panel-common.yaml#
+
+properties:
+  compatible:
+    enum:
+        # BOE TH101MB31IG002-28A 10.1" WXGA TFT LCD panel
+      - boe,th101mb31ig002-28a
+
+  reg: true
+  backlight: true
+  enable-gpios: true
+  power-supply: true
+  port: true
+  rotation: true
+
+required:
+  - compatible
+  - reg
+  - enable-gpios
+  - power-supply
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/gpio/gpio.h>
+
+    dsi {
+        #address-cells = <1>;
+        #size-cells = <0>;
+        panel@0 {
+            compatible = "boe,th101mb31ig002-28a";
+            reg = <0>;
+            backlight = <&backlight_lcd0>;
+            enable-gpios = <&gpio 45 GPIO_ACTIVE_HIGH>;
+            rotation = <90>;
+            power-supply = <&vcc_3v3>;
+            port {
+                panel_in_dsi: endpoint {
+                    remote-endpoint = <&dsi_out_con>;
+                };
+            };
+        };
+    };
+
+...
index bc92928c805b9a10900552fce47c06a4d26c5a54..a4afaff483b73f510f265d739f0b1ed84b777b5d 100644 (file)
@@ -15,7 +15,9 @@ allOf:
 properties:
   compatible:
     items:
-      - const: hydis,hva40wv1
+      - enum:
+          - frida,frd400b25025
+          - hydis,hva40wv1
       - const: novatek,nt35510
     description: This indicates the panel manufacturer of the panel
       that is in turn using the NT35510 panel driver. The compatible
diff --git a/Documentation/devicetree/bindings/display/panel/novatek,nt36672e.yaml b/Documentation/devicetree/bindings/display/panel/novatek,nt36672e.yaml
new file mode 100644 (file)
index 0000000..dc4672f
--- /dev/null
@@ -0,0 +1,66 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/panel/novatek,nt36672e.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Novatek NT36672E LCD DSI Panel
+
+maintainers:
+  - Ritesh Kumar <quic_riteshk@quicinc.com>
+
+allOf:
+  - $ref: panel-common.yaml#
+
+properties:
+  compatible:
+    const: novatek,nt36672e
+
+  reg:
+    maxItems: 1
+    description: DSI virtual channel
+
+  vddi-supply: true
+  avdd-supply: true
+  avee-supply: true
+  port: true
+  reset-gpios: true
+  backlight: true
+
+required:
+  - compatible
+  - reg
+  - vddi-supply
+  - avdd-supply
+  - avee-supply
+  - reset-gpios
+  - port
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/gpio/gpio.h>
+    dsi {
+        #address-cells = <1>;
+        #size-cells = <0>;
+        panel@0 {
+            compatible = "novatek,nt36672e";
+            reg = <0>;
+
+            reset-gpios = <&tlmm 44 GPIO_ACTIVE_HIGH>;
+
+            vddi-supply = <&vreg_l8c_1p8>;
+            avdd-supply = <&disp_avdd>;
+            avee-supply = <&disp_avee>;
+
+            backlight = <&pwm_backlight>;
+
+            port {
+                panel0_in: endpoint {
+                    remote-endpoint = <&dsi0_out>;
+                };
+            };
+        };
+    };
+...
index 9f1016551e0b27e4518277ccc9b314b3245bb18f..3fb24393529cddf18495b363ed25fcf2bafa908e 100644 (file)
@@ -42,6 +42,8 @@ properties:
           - auo,b101ew05
           # Chunghwa Picture Tubes Ltd. 7" WXGA (800x1280) TFT LCD LVDS panel
           - chunghwa,claa070wp03xg
+          # EDT ETML0700Z9NDHA 7.0" WSVGA (1024x600) color TFT LCD LVDS panel
+          - edt,etml0700z9ndha
           # HannStar Display Corp. HSD101PWW2 10.1" WXGA (1280x800) LVDS panel
           - hannstar,hsd101pww2
           # Hydis Technologies 7" WXGA (800x1280) TFT LCD LVDS panel
index 634a10c6f2ddddb125e72cf6929410c8481b4671..233c620722ddc01511e931b8bac0d4431de04a6e 100644 (file)
@@ -141,6 +141,8 @@ properties:
       - edt,etm0700g0edh6
         # Emerging Display Technology Corp. LVDS WSVGA TFT Display with capacitive touch
       - edt,etml0700y5dha
+        # Emerging Display Technology Corp. 10.1" LVDS WXGA TFT Display with capacitive touch
+      - edt,etml1010g3dra
         # Emerging Display Technology Corp. 5.7" VGA TFT LCD panel with
         # capacitive touch
       - edt,etmv570g2dhu
index 3afbb52d1b7fe589bdd4ae4f0b66f287ce282f40..153ff86fb40590dd926483b299896b39744dee5d 100644 (file)
@@ -131,9 +131,9 @@ allOf:
             const: sinowealth,sh1106
     then:
       properties:
-        width:
+        solomon,width:
           default: 132
-        height:
+        solomon,height:
           default: 64
         solomon,dclk-div:
           default: 1
@@ -149,9 +149,9 @@ allOf:
               - solomon,ssd1305
     then:
       properties:
-        width:
+        solomon,width:
           default: 132
-        height:
+        solomon,height:
           default: 64
         solomon,dclk-div:
           default: 1
@@ -167,9 +167,9 @@ allOf:
               - solomon,ssd1306
     then:
       properties:
-        width:
+        solomon,width:
           default: 128
-        height:
+        solomon,height:
           default: 64
         solomon,dclk-div:
           default: 1
@@ -185,9 +185,9 @@ allOf:
               - solomon,ssd1307
     then:
       properties:
-        width:
+        solomon,width:
           default: 128
-        height:
+        solomon,height:
           default: 39
         solomon,dclk-div:
           default: 2
@@ -205,9 +205,9 @@ allOf:
               - solomon,ssd1309
     then:
       properties:
-        width:
+        solomon,width:
           default: 128
-        height:
+        solomon,height:
           default: 64
         solomon,dclk-div:
           default: 1
index 37975ee61c5ad48e822792ec4e37bad6f331a91c..dd7939989cf4f1c2469fc30f1e74aa26b32f3a32 100644 (file)
@@ -30,9 +30,9 @@ allOf:
             const: solomon,ssd1322
     then:
       properties:
-        width:
+        solomon,width:
           default: 480
-        height:
+        solomon,height:
           default: 128
 
   - if:
@@ -42,9 +42,9 @@ allOf:
             const: solomon,ssd1325
     then:
       properties:
-        width:
+        solomon,width:
           default: 128
-        height:
+        solomon,height:
           default: 80
 
   - if:
@@ -54,9 +54,9 @@ allOf:
             const: solomon,ssd1327
     then:
       properties:
-        width:
+        solomon,width:
           default: 128
-        height:
+        solomon,height:
           default: 128
 
 unevaluatedProperties: false
diff --git a/Documentation/devicetree/bindings/display/solomon,ssd133x.yaml b/Documentation/devicetree/bindings/display/solomon,ssd133x.yaml
new file mode 100644 (file)
index 0000000..b778003
--- /dev/null
@@ -0,0 +1,45 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/solomon,ssd133x.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Solomon SSD133x OLED Display Controllers
+
+maintainers:
+  - Javier Martinez Canillas <javierm@redhat.com>
+
+allOf:
+  - $ref: solomon,ssd-common.yaml#
+
+properties:
+  compatible:
+    enum:
+      - solomon,ssd1331
+
+  solomon,width:
+    default: 96
+
+  solomon,height:
+    default: 64
+
+required:
+  - compatible
+  - reg
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    spi {
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        oled@0 {
+            compatible = "solomon,ssd1331";
+            reg = <0x0>;
+            reset-gpios = <&gpio2 7>;
+            dc-gpios = <&gpio2 8>;
+            spi-max-frequency = <10000000>;
+        };
+    };
index 5fd20a306718cde46926c91b8fef23d6ee9814b9..335de7fcddeecc0fbe94f376a8107ed94476b986 100644 (file)
@@ -153,18 +153,6 @@ Managed Resources
 .. kernel-doc:: include/drm/drm_managed.h
    :internal:
 
-Bus-specific Device Registration and PCI Support
-------------------------------------------------
-
-A number of functions are provided to help with device registration. The
-functions deal with PCI and platform devices respectively and are only
-provided for historical reasons. These are all deprecated and shouldn't
-be used in new drivers. Besides that there's a few helpers for pci
-drivers.
-
-.. kernel-doc:: drivers/gpu/drm/drm_pci.c
-   :export:
-
 Open/Close, File Operations and IOCTLs
 ======================================
 
index f05eccd2c07c8acfe0f4f342c971861df86cd842..b7c0baf97dbee223eb541cc143cf910553e0b63f 100644 (file)
@@ -164,6 +164,8 @@ Conference talks
 Slides and articles
 -------------------
 
+* `The Linux graphics stack in a nutshell, part 1 <https://lwn.net/Articles/955376/>`_ - Thomas Zimmermann (2023)
+* `The Linux graphics stack in a nutshell, part 2 <https://lwn.net/Articles/955708/>`_ - Thomas Zimmermann (2023)
 * `Understanding the Linux Graphics Stack <https://bootlin.com/doc/training/graphics/graphics-slides.pdf>`_ - Bootlin (2022)
 * `DRM KMS overview <https://wiki.st.com/stm32mpu/wiki/DRM_KMS_overview>`_ - STMicroelectronics (2021)
 * `Linux graphic stack <https://studiopixl.com/2017-05-13/linux-graphic-stack-an-overview>`_ - Nathan Gauër (2017)
index e4f7b005138d0698773d0a1432681ca5ed7dddd1..476719771eef388d575bc5c753ff248c60dfd4d5 100644 (file)
@@ -31,7 +31,3 @@ host such documentation:
 .. toctree::
 
     i915_vm_bind.rst
-
-.. toctree::
-
-   xe.rst
diff --git a/Documentation/gpu/rfc/xe.rst b/Documentation/gpu/rfc/xe.rst
deleted file mode 100644 (file)
index 97cf875..0000000
+++ /dev/null
@@ -1,234 +0,0 @@
-==========================
-Xe â€“ Merge Acceptance Plan
-==========================
-Xe is a new driver for Intel GPUs that supports both integrated and
-discrete platforms starting with Tiger Lake (first Intel Xe Architecture).
-
-This document aims to establish a merge plan for the Xe, by writing down clear
-pre-merge goals, in order to avoid unnecessary delays.
-
-Xe â€“ Overview
-=============
-The main motivation of Xe is to have a fresh base to work from that is
-unencumbered by older platforms, whilst also taking the opportunity to
-rearchitect our driver to increase sharing across the drm subsystem, both
-leveraging and allowing us to contribute more towards other shared components
-like TTM and drm/scheduler.
-
-This is also an opportunity to start from the beginning with a clean uAPI that is
-extensible by design and already aligned with the modern userspace needs. For
-this reason, the memory model is solely based on GPU Virtual Address space
-bind/unbind (‘VM_BIND’) of GEM buffer objects (BOs) and execution only supporting
-explicit synchronization. With persistent mapping across the execution, the
-userspace does not need to provide a list of all required mappings during each
-submission.
-
-The new driver leverages a lot from i915. As for display, the intent is to share
-the display code with the i915 driver so that there is maximum reuse there.
-
-As for the power management area, the goal is to have a much-simplified support
-for the system suspend states (S-states), PCI device suspend states (D-states),
-GPU/Render suspend states (R-states) and frequency management. It should leverage
-as much as possible all the existent PCI-subsystem infrastructure (pm and
-runtime_pm) and underlying firmware components such PCODE and GuC for the power
-states and frequency decisions.
-
-Repository:
-
-https://gitlab.freedesktop.org/drm/xe/kernel (branch drm-xe-next)
-
-Xe â€“ Platforms
-==============
-Currently, Xe is already functional and has experimental support for multiple
-platforms starting from Tiger Lake, with initial support in userspace implemented
-in Mesa (for Iris and Anv, our OpenGL and Vulkan drivers), as well as in NEO
-(for OpenCL and Level0).
-
-During a transition period, platforms will be supported by both Xe and i915.
-However, the force_probe mechanism existent in both drivers will allow only one
-official and by-default probe at a given time.
-
-For instance, in order to probe a DG2 which PCI ID is 0x5690 by Xe instead of
-i915, the following set of parameters need to be used:
-
-```
-i915.force_probe=!5690 xe.force_probe=5690
-```
-
-In both drivers, the â€˜.require_force_probe’ protection forces the user to use the
-force_probe parameter while the driver is under development. This protection is
-only removed when the support for the platform and the uAPI are stable. Stability
-which needs to be demonstrated by CI results.
-
-In order to avoid user space regressions, i915 will continue to support all the
-current platforms that are already out of this protection. Xe support will be
-forever experimental and dependent on the usage of force_probe for these
-platforms.
-
-When the time comes for Xe, the protection will be lifted on Xe and kept in i915.
-
-Xe â€“ Pre-Merge Goals - Work-in-Progress
-=======================================
-
-Display integration with i915
------------------------------
-In order to share the display code with the i915 driver so that there is maximum
-reuse, the i915/display/ code is built twice, once for i915.ko and then for
-xe.ko. Currently, the i915/display code in Xe tree is polluted with many 'ifdefs'
-depending on the build target. The goal is to refactor both Xe and i915/display
-code simultaneously in order to get a clean result before they land upstream, so
-that display can already be part of the initial pull request towards drm-next.
-
-However, display code should not gate the acceptance of Xe in upstream. Xe
-patches will be refactored in a way that display code can be removed, if needed,
-from the first pull request of Xe towards drm-next. The expectation is that when
-both drivers are part of the drm-tip, the introduction of cleaner patches will be
-easier and speed up.
-
-Xe â€“ uAPI high level overview
-=============================
-
-...Warning: To be done in follow up patches after/when/where the main consensus in various items are individually reached.
-
-Xe â€“ Pre-Merge Goals - Completed
-================================
-
-Drm_exec
---------
-Helper to make dma_resv locking for a big number of buffers is getting removed in
-the drm_exec series proposed in https://patchwork.freedesktop.org/patch/524376/
-If that happens, Xe needs to change and incorporate the changes in the driver.
-The goal is to engage with the Community to understand if the best approach is to
-move that to the drivers that are using it or if we should keep the helpers in
-place waiting for Xe to get merged.
-
-This item ties into the GPUVA, VM_BIND, and even long-running compute support.
-
-As a key measurable result, we need to have a community consensus documented in
-this document and the Xe driver prepared for the changes, if necessary.
-
-Userptr integration and vm_bind
--------------------------------
-Different drivers implement different ways of dealing with execution of userptr.
-With multiple drivers currently introducing support to VM_BIND, the goal is to
-aim for a DRM consensus on what’s the best way to have that support. To some
-extent this is already getting addressed itself with the GPUVA where likely the
-userptr will be a GPUVA with a NULL GEM call VM bind directly on the userptr.
-However, there are more aspects around the rules for that and the usage of
-mmu_notifiers, locking and other aspects.
-
-This task here has the goal of introducing a documentation of the basic rules.
-
-The documentation *needs* to first live in this document (API session below) and
-then moved to another more specific document or at Xe level or at DRM level.
-
-Documentation should include:
-
- * The userptr part of the VM_BIND api.
-
- * Locking, including the page-faulting case.
-
- * O(1) complexity under VM_BIND.
-
-The document is now included in the drm documentation :doc:`here </gpu/drm-vm-bind-async>`.
-
-Some parts of userptr like mmu_notifiers should become GPUVA or DRM helpers when
-the second driver supporting VM_BIND+userptr appears. Details to be defined when
-the time comes.
-
-The DRM GPUVM helpers do not yet include the userptr parts, but discussions
-about implementing them are ongoing.
-
-ASYNC VM_BIND
--------------
-Although having a common DRM level IOCTL for VM_BIND is not a requirement to get
-Xe merged, it is mandatory to have a consensus with other drivers and Mesa.
-It needs to be clear how to handle async VM_BIND and interactions with userspace
-memory fences. Ideally with helper support so people don't get it wrong in all
-possible ways.
-
-As a key measurable result, the benefits of ASYNC VM_BIND and a discussion of
-various flavors, error handling and sample API suggestions are documented in
-:doc:`The ASYNC VM_BIND document </gpu/drm-vm-bind-async>`.
-
-Drm_scheduler
--------------
-Xe primarily uses Firmware based scheduling (GuC FW). However, it will use
-drm_scheduler as the scheduler â€˜frontend’ for userspace submission in order to
-resolve syncobj and dma-buf implicit sync dependencies. However, drm_scheduler is
-not yet prepared to handle the 1-to-1 relationship between drm_gpu_scheduler and
-drm_sched_entity.
-
-Deeper changes to drm_scheduler should *not* be required to get Xe accepted, but
-some consensus needs to be reached between Xe and other community drivers that
-could also benefit from this work, for coupling FW based/assisted submission such
-as the ARM’s new Mali GPU driver, and others.
-
-As a key measurable result, the patch series introducing Xe itself shall not
-depend on any other patch touching drm_scheduler itself that was not yet merged
-through drm-misc. This, by itself, already includes the reach of an agreement for
-uniform 1 to 1 relationship implementation / usage across drivers.
-
-Long running compute: minimal data structure/scaffolding
---------------------------------------------------------
-The generic scheduler code needs to include the handling of endless compute
-contexts, with the minimal scaffolding for preempt-ctx fences (probably on the
-drm_sched_entity) and making sure drm_scheduler can cope with the lack of job
-completion fence.
-
-The goal is to achieve a consensus ahead of Xe initial pull-request, ideally with
-this minimal drm/scheduler work, if needed, merged to drm-misc in a way that any
-drm driver, including Xe, could re-use and add their own individual needs on top
-in a next stage. However, this should not block the initial merge.
-
-Dev_coredump
-------------
-
-Xe needs to align with other drivers on the way that the error states are
-dumped, avoiding a Xe only error_state solution. The goal is to use devcoredump
-infrastructure to report error states, since it produces a standardized way
-by exposing a virtual and temporary /sys/class/devcoredump device.
-
-As the key measurable result, Xe driver needs to provide GPU snapshots captured
-at hang time through devcoredump, but without depending on any core modification
-of devcoredump infrastructure itself.
-
-Later, when we are in-tree, the goal is to collaborate with devcoredump
-infrastructure with overall possible improvements, like multiple file support
-for better organization of the dumps, snapshot support, dmesg extra print,
-and whatever may make sense and help the overall infrastructure.
-
-DRM_VM_BIND
------------
-Nouveau, and Xe are all implementing â€˜VM_BIND’ and new â€˜Exec’ uAPIs in order to
-fulfill the needs of the modern uAPI. Xe merge should *not* be blocked on the
-development of a common new drm_infrastructure. However, the Xe team needs to
-engage with the community to explore the options of a common API.
-
-As a key measurable result, the DRM_VM_BIND needs to be documented in this file
-below, or this entire block deleted if the consensus is for independent drivers
-vm_bind ioctls.
-
-Although having a common DRM level IOCTL for VM_BIND is not a requirement to get
-Xe merged, it is mandatory to enforce the overall locking scheme for all major
-structs and list (so vm and vma). So, a consensus is needed, and possibly some
-common helpers. If helpers are needed, they should be also documented in this
-document.
-
-GPU VA
-------
-Two main goals of Xe are meeting together here:
-
-1) Have an uAPI that aligns with modern UMD needs.
-
-2) Early upstream engagement.
-
-RedHat engineers working on Nouveau proposed a new DRM feature to handle keeping
-track of GPU virtual address mappings. This is still not merged upstream, but
-this aligns very well with our goals and with our VM_BIND. The engagement with
-upstream and the port of Xe towards GPUVA is already ongoing.
-
-As a key measurable result, Xe needs to be aligned with the GPU VA and working in
-our tree. Missing Nouveau patches should *not* block Xe and any needed GPUVA
-related patch should be independent and present on dri-devel or acked by
-maintainers to go along with the first Xe pull request towards drm-next.
index 41a264bf84ce02127ee00ac646b216ed532a9963..fb9ad120b141478a657012f752a5207e98984c73 100644 (file)
@@ -120,6 +120,29 @@ Contact: Daniel Vetter, respective driver maintainers
 
 Level: Advanced
 
+Rename drm_atomic_state
+-----------------------
+
+The KMS framework uses two slightly different definitions for the ``state``
+concept. For a given object (plane, CRTC, encoder, etc., so
+``drm_$OBJECT_state``), the state is the entire state of that object. However,
+at the device level, ``drm_atomic_state`` refers to a state update for a
+limited number of objects.
+
+The state isn't the entire device state, but only the full state of some
+objects in that device. This is confusing to newcomers, and
+``drm_atomic_state`` should be renamed to something clearer like
+``drm_atomic_commit``.
+
+In addition to renaming the structure itself, it would also imply renaming some
+related functions (``drm_atomic_state_alloc``, ``drm_atomic_state_get``,
+``drm_atomic_state_put``, ``drm_atomic_state_init``,
+``__drm_atomic_state_free``, etc.).
+
+Contact: Maxime Ripard <mripard@kernel.org>
+
+Level: Advanced
+
 Fallout from atomic KMS
 -----------------------
 
index 8d1052fa6a6924d17a4d2681fa7907c544e35186..59b3da17debc4796c13f18d25dd58b3eee49e1c1 100644 (file)
@@ -10466,7 +10466,6 @@ F:      drivers/media/rc/img-ir/
 
 IMGTEC POWERVR DRM DRIVER
 M:     Frank Binns <frank.binns@imgtec.com>
-M:     Donald Robson <donald.robson@imgtec.com>
 M:     Matt Coster <matt.coster@imgtec.com>
 S:     Supported
 T:     git git://anongit.freedesktop.org/drm/drm-misc
index cb77d048ed54b72c51123d2328ab1a60634adeb9..51cb85d0387b2c71ed3bc7fc4bedc75fd83ec01c 100644 (file)
@@ -358,8 +358,8 @@ static struct mhi_channel_config aic100_channels[] = {
                .wake_capable = false,
        },
        {
-               .num = 21,
                .name = "QAIC_TIMESYNC",
+               .num = 21,
                .num_elements = 32,
                .local_elements = 0,
                .event_ring = 0,
@@ -390,8 +390,8 @@ static struct mhi_channel_config aic100_channels[] = {
                .wake_capable = false,
        },
        {
-               .num = 23,
                .name = "QAIC_TIMESYNC_PERIODIC",
+               .num = 23,
                .num_elements = 32,
                .local_elements = 0,
                .event_ring = 0,
index 582836f9538f958b4c4cebf3857d85610cb01c34..9256653b30362ecea39e92d54bc3568380cae2cd 100644 (file)
@@ -30,6 +30,7 @@
 #define to_qaic_drm_device(dev) container_of(dev, struct qaic_drm_device, drm)
 #define to_drm(qddev) (&(qddev)->drm)
 #define to_accel_kdev(qddev) (to_drm(qddev)->accel->kdev) /* Return Linux device of accel node */
+#define to_qaic_device(dev) (to_qaic_drm_device((dev))->qdev)
 
 enum __packed dev_states {
        /* Device is offline or will be very soon */
@@ -191,8 +192,6 @@ struct qaic_bo {
        u32                     nr_slice;
        /* Number of slice that have been transferred by DMA engine */
        u32                     nr_slice_xfer_done;
-       /* true = BO is queued for execution, true = BO is not queued */
-       bool                    queued;
        /*
         * If true then user has attached slicing information to this BO by
         * calling DRM_IOCTL_QAIC_ATTACH_SLICE_BO ioctl.
index 03c9a793da35ad081a2224250d424abb751e921c..2459fe4a3f95a7c596de929bf6297cac89f01a38 100644 (file)
@@ -141,6 +141,11 @@ struct dbc_rsp {
        __le16  status;
 } __packed;
 
+static inline bool bo_queued(struct qaic_bo *bo)
+{
+       return !list_empty(&bo->xfer_list);
+}
+
 inline int get_dbc_req_elem_size(void)
 {
        return sizeof(struct dbc_req);
@@ -569,6 +574,9 @@ static void qaic_free_sgt(struct sg_table *sgt)
 {
        struct scatterlist *sg;
 
+       if (!sgt)
+               return;
+
        for (sg = sgt->sgl; sg; sg = sg_next(sg))
                if (sg_page(sg))
                        __free_pages(sg_page(sg), get_order(sg->length));
@@ -648,6 +656,7 @@ static void qaic_init_bo(struct qaic_bo *bo, bool reinit)
        }
        complete_all(&bo->xfer_done);
        INIT_LIST_HEAD(&bo->slices);
+       INIT_LIST_HEAD(&bo->xfer_list);
 }
 
 static struct qaic_bo *qaic_alloc_init_bo(void)
@@ -709,9 +718,13 @@ int qaic_create_bo_ioctl(struct drm_device *dev, void *data, struct drm_file *fi
        if (ret)
                goto free_bo;
 
+       ret = drm_gem_create_mmap_offset(obj);
+       if (ret)
+               goto free_bo;
+
        ret = drm_gem_handle_create(file_priv, obj, &args->handle);
        if (ret)
-               goto free_sgt;
+               goto free_bo;
 
        bo->handle = args->handle;
        drm_gem_object_put(obj);
@@ -720,10 +733,8 @@ int qaic_create_bo_ioctl(struct drm_device *dev, void *data, struct drm_file *fi
 
        return 0;
 
-free_sgt:
-       qaic_free_sgt(bo->sgt);
 free_bo:
-       kfree(bo);
+       drm_gem_object_put(obj);
 unlock_dev_srcu:
        srcu_read_unlock(&qdev->dev_lock, qdev_rcu_id);
 unlock_usr_srcu:
@@ -738,7 +749,7 @@ int qaic_mmap_bo_ioctl(struct drm_device *dev, void *data, struct drm_file *file
        struct drm_gem_object *obj;
        struct qaic_device *qdev;
        struct qaic_user *usr;
-       int ret;
+       int ret = 0;
 
        usr = file_priv->driver_priv;
        usr_rcu_id = srcu_read_lock(&usr->qddev_lock);
@@ -760,9 +771,7 @@ int qaic_mmap_bo_ioctl(struct drm_device *dev, void *data, struct drm_file *file
                goto unlock_dev_srcu;
        }
 
-       ret = drm_gem_create_mmap_offset(obj);
-       if (ret == 0)
-               args->offset = drm_vma_node_offset_addr(&obj->vma_node);
+       args->offset = drm_vma_node_offset_addr(&obj->vma_node);
 
        drm_gem_object_put(obj);
 
@@ -828,9 +837,6 @@ static int qaic_prepare_import_bo(struct qaic_bo *bo, struct qaic_attach_slice_h
        struct sg_table *sgt;
        int ret;
 
-       if (obj->import_attach->dmabuf->size < hdr->size)
-               return -EINVAL;
-
        sgt = dma_buf_map_attachment(obj->import_attach, hdr->dir);
        if (IS_ERR(sgt)) {
                ret = PTR_ERR(sgt);
@@ -847,9 +853,6 @@ static int qaic_prepare_export_bo(struct qaic_device *qdev, struct qaic_bo *bo,
 {
        int ret;
 
-       if (bo->base.size < hdr->size)
-               return -EINVAL;
-
        ret = dma_map_sgtable(&qdev->pdev->dev, bo->sgt, hdr->dir, 0);
        if (ret)
                return -EFAULT;
@@ -950,9 +953,6 @@ int qaic_attach_slice_bo_ioctl(struct drm_device *dev, void *data, struct drm_fi
        if (arg_size / args->hdr.count != sizeof(*slice_ent))
                return -EINVAL;
 
-       if (args->hdr.size == 0)
-               return -EINVAL;
-
        if (!(args->hdr.dir == DMA_TO_DEVICE || args->hdr.dir == DMA_FROM_DEVICE))
                return -EINVAL;
 
@@ -992,16 +992,16 @@ int qaic_attach_slice_bo_ioctl(struct drm_device *dev, void *data, struct drm_fi
                goto free_slice_ent;
        }
 
-       ret = qaic_validate_req(qdev, slice_ent, args->hdr.count, args->hdr.size);
-       if (ret)
-               goto free_slice_ent;
-
        obj = drm_gem_object_lookup(file_priv, args->hdr.handle);
        if (!obj) {
                ret = -ENOENT;
                goto free_slice_ent;
        }
 
+       ret = qaic_validate_req(qdev, slice_ent, args->hdr.count, obj->size);
+       if (ret)
+               goto put_bo;
+
        bo = to_qaic_bo(obj);
        ret = mutex_lock_interruptible(&bo->lock);
        if (ret)
@@ -1173,7 +1173,6 @@ static int send_bo_list_to_device(struct qaic_device *qdev, struct drm_file *fil
        struct bo_slice *slice;
        unsigned long flags;
        struct qaic_bo *bo;
-       bool queued;
        int i, j;
        int ret;
 
@@ -1205,9 +1204,7 @@ static int send_bo_list_to_device(struct qaic_device *qdev, struct drm_file *fil
                }
 
                spin_lock_irqsave(&dbc->xfer_lock, flags);
-               queued = bo->queued;
-               bo->queued = true;
-               if (queued) {
+               if (bo_queued(bo)) {
                        spin_unlock_irqrestore(&dbc->xfer_lock, flags);
                        ret = -EINVAL;
                        goto unlock_bo;
@@ -1230,7 +1227,6 @@ static int send_bo_list_to_device(struct qaic_device *qdev, struct drm_file *fil
                        else
                                ret = copy_exec_reqs(qdev, slice, dbc->id, head, tail);
                        if (ret) {
-                               bo->queued = false;
                                spin_unlock_irqrestore(&dbc->xfer_lock, flags);
                                goto unlock_bo;
                        }
@@ -1253,8 +1249,7 @@ failed_to_send_bo:
                spin_lock_irqsave(&dbc->xfer_lock, flags);
                bo = list_last_entry(&dbc->xfer_list, struct qaic_bo, xfer_list);
                obj = &bo->base;
-               bo->queued = false;
-               list_del(&bo->xfer_list);
+               list_del_init(&bo->xfer_list);
                spin_unlock_irqrestore(&dbc->xfer_lock, flags);
                dma_sync_sgtable_for_cpu(&qdev->pdev->dev, bo->sgt, bo->dir);
                drm_gem_object_put(obj);
@@ -1615,8 +1610,7 @@ read_fifo:
                         */
                        dma_sync_sgtable_for_cpu(&qdev->pdev->dev, bo->sgt, bo->dir);
                        bo->nr_slice_xfer_done = 0;
-                       bo->queued = false;
-                       list_del(&bo->xfer_list);
+                       list_del_init(&bo->xfer_list);
                        bo->perf_stats.req_processed_ts = ktime_get_ns();
                        complete_all(&bo->xfer_done);
                        drm_gem_object_put(&bo->base);
@@ -1875,7 +1869,7 @@ int qaic_detach_slice_bo_ioctl(struct drm_device *dev, void *data, struct drm_fi
 
        /* Check if BO is committed to H/W for DMA */
        spin_lock_irqsave(&dbc->xfer_lock, flags);
-       if (bo->queued) {
+       if (bo_queued(bo)) {
                spin_unlock_irqrestore(&dbc->xfer_lock, flags);
                ret = -EBUSY;
                goto unlock_ch_srcu;
@@ -1905,8 +1899,7 @@ static void empty_xfer_list(struct qaic_device *qdev, struct dma_bridge_chan *db
        spin_lock_irqsave(&dbc->xfer_lock, flags);
        while (!list_empty(&dbc->xfer_list)) {
                bo = list_first_entry(&dbc->xfer_list, typeof(*bo), xfer_list);
-               bo->queued = false;
-               list_del(&bo->xfer_list);
+               list_del_init(&bo->xfer_list);
                spin_unlock_irqrestore(&dbc->xfer_lock, flags);
                bo->nr_slice_xfer_done = 0;
                bo->req_id = 0;
index 2a313eb69b1219b5b985dc39b9b9742690c97ccf..d1a632dbaec6e17a8d44120dd2b7e3dd02aed835 100644 (file)
@@ -44,6 +44,53 @@ MODULE_PARM_DESC(datapath_polling, "Operate the datapath in polling mode");
 static bool link_up;
 static DEFINE_IDA(qaic_usrs);
 
+static void qaicm_wq_release(struct drm_device *dev, void *res)
+{
+       struct workqueue_struct *wq = res;
+
+       destroy_workqueue(wq);
+}
+
+static struct workqueue_struct *qaicm_wq_init(struct drm_device *dev, const char *fmt)
+{
+       struct workqueue_struct *wq;
+       int ret;
+
+       wq = alloc_workqueue(fmt, WQ_UNBOUND, 0);
+       if (!wq)
+               return ERR_PTR(-ENOMEM);
+       ret = drmm_add_action_or_reset(dev, qaicm_wq_release, wq);
+       if (ret)
+               return ERR_PTR(ret);
+
+       return wq;
+}
+
+static void qaicm_srcu_release(struct drm_device *dev, void *res)
+{
+       struct srcu_struct *lock = res;
+
+       cleanup_srcu_struct(lock);
+}
+
+static int qaicm_srcu_init(struct drm_device *dev, struct srcu_struct *lock)
+{
+       int ret;
+
+       ret = init_srcu_struct(lock);
+       if (ret)
+               return ret;
+
+       return drmm_add_action_or_reset(dev, qaicm_srcu_release, lock);
+}
+
+static void qaicm_pci_release(struct drm_device *dev, void *res)
+{
+       struct qaic_device *qdev = to_qaic_device(dev);
+
+       pci_set_drvdata(qdev->pdev, NULL);
+}
+
 static void free_usr(struct kref *kref)
 {
        struct qaic_user *usr = container_of(kref, struct qaic_user, ref_count);
@@ -299,74 +346,73 @@ void qaic_dev_reset_clean_local_state(struct qaic_device *qdev)
                release_dbc(qdev, i);
 }
 
-static void cleanup_qdev(struct qaic_device *qdev)
-{
-       int i;
-
-       for (i = 0; i < qdev->num_dbc; ++i)
-               cleanup_srcu_struct(&qdev->dbc[i].ch_lock);
-       cleanup_srcu_struct(&qdev->dev_lock);
-       pci_set_drvdata(qdev->pdev, NULL);
-       destroy_workqueue(qdev->cntl_wq);
-       destroy_workqueue(qdev->qts_wq);
-}
-
 static struct qaic_device *create_qdev(struct pci_dev *pdev, const struct pci_device_id *id)
 {
+       struct device *dev = &pdev->dev;
        struct qaic_drm_device *qddev;
        struct qaic_device *qdev;
-       int i;
+       struct drm_device *drm;
+       int i, ret;
 
-       qdev = devm_kzalloc(&pdev->dev, sizeof(*qdev), GFP_KERNEL);
+       qdev = devm_kzalloc(dev, sizeof(*qdev), GFP_KERNEL);
        if (!qdev)
                return NULL;
 
        qdev->dev_state = QAIC_OFFLINE;
        if (id->device == PCI_DEV_AIC100) {
                qdev->num_dbc = 16;
-               qdev->dbc = devm_kcalloc(&pdev->dev, qdev->num_dbc, sizeof(*qdev->dbc), GFP_KERNEL);
+               qdev->dbc = devm_kcalloc(dev, qdev->num_dbc, sizeof(*qdev->dbc), GFP_KERNEL);
                if (!qdev->dbc)
                        return NULL;
        }
 
-       qdev->cntl_wq = alloc_workqueue("qaic_cntl", WQ_UNBOUND, 0);
-       if (!qdev->cntl_wq)
+       qddev = devm_drm_dev_alloc(&pdev->dev, &qaic_accel_driver, struct qaic_drm_device, drm);
+       if (IS_ERR(qddev))
+               return NULL;
+
+       drm = to_drm(qddev);
+       pci_set_drvdata(pdev, qdev);
+
+       ret = drmm_mutex_init(drm, &qddev->users_mutex);
+       if (ret)
+               return NULL;
+       ret = drmm_add_action_or_reset(drm, qaicm_pci_release, NULL);
+       if (ret)
+               return NULL;
+       ret = drmm_mutex_init(drm, &qdev->cntl_mutex);
+       if (ret)
                return NULL;
 
-       qdev->qts_wq = alloc_workqueue("qaic_ts", WQ_UNBOUND, 0);
-       if (!qdev->qts_wq) {
-               destroy_workqueue(qdev->cntl_wq);
+       qdev->cntl_wq = qaicm_wq_init(drm, "qaic_cntl");
+       if (IS_ERR(qdev->cntl_wq))
+               return NULL;
+       qdev->qts_wq = qaicm_wq_init(drm, "qaic_ts");
+       if (IS_ERR(qdev->qts_wq))
                return NULL;
-       }
 
-       pci_set_drvdata(pdev, qdev);
+       ret = qaicm_srcu_init(drm, &qdev->dev_lock);
+       if (ret)
+               return NULL;
+
+       qdev->qddev = qddev;
        qdev->pdev = pdev;
+       qddev->qdev = qdev;
 
-       mutex_init(&qdev->cntl_mutex);
        INIT_LIST_HEAD(&qdev->cntl_xfer_list);
-       init_srcu_struct(&qdev->dev_lock);
+       INIT_LIST_HEAD(&qddev->users);
 
        for (i = 0; i < qdev->num_dbc; ++i) {
                spin_lock_init(&qdev->dbc[i].xfer_lock);
                qdev->dbc[i].qdev = qdev;
                qdev->dbc[i].id = i;
                INIT_LIST_HEAD(&qdev->dbc[i].xfer_list);
-               init_srcu_struct(&qdev->dbc[i].ch_lock);
+               ret = qaicm_srcu_init(drm, &qdev->dbc[i].ch_lock);
+               if (ret)
+                       return NULL;
                init_waitqueue_head(&qdev->dbc[i].dbc_release);
                INIT_LIST_HEAD(&qdev->dbc[i].bo_lists);
        }
 
-       qddev = devm_drm_dev_alloc(&pdev->dev, &qaic_accel_driver, struct qaic_drm_device, drm);
-       if (IS_ERR(qddev)) {
-               cleanup_qdev(qdev);
-               return NULL;
-       }
-
-       drmm_mutex_init(to_drm(qddev), &qddev->users_mutex);
-       INIT_LIST_HEAD(&qddev->users);
-       qddev->qdev = qdev;
-       qdev->qddev = qddev;
-
        return qdev;
 }
 
@@ -472,35 +518,28 @@ static int qaic_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 
        ret = init_pci(qdev, pdev);
        if (ret)
-               goto cleanup_qdev;
+               return ret;
 
        for (i = 0; i < qdev->num_dbc; ++i)
                qdev->dbc[i].dbc_base = qdev->bar_2 + QAIC_DBC_OFF(i);
 
        mhi_irq = init_msi(qdev, pdev);
-       if (mhi_irq < 0) {
-               ret = mhi_irq;
-               goto cleanup_qdev;
-       }
+       if (mhi_irq < 0)
+               return mhi_irq;
 
        ret = qaic_create_drm_device(qdev, QAIC_NO_PARTITION);
        if (ret)
-               goto cleanup_qdev;
+               return ret;
 
        qdev->mhi_cntrl = qaic_mhi_register_controller(pdev, qdev->bar_0, mhi_irq,
                                                       qdev->single_msi);
        if (IS_ERR(qdev->mhi_cntrl)) {
                ret = PTR_ERR(qdev->mhi_cntrl);
-               goto cleanup_drm_dev;
+               qaic_destroy_drm_device(qdev, QAIC_NO_PARTITION);
+               return ret;
        }
 
        return 0;
-
-cleanup_drm_dev:
-       qaic_destroy_drm_device(qdev, QAIC_NO_PARTITION);
-cleanup_qdev:
-       cleanup_qdev(qdev);
-       return ret;
 }
 
 static void qaic_pci_remove(struct pci_dev *pdev)
@@ -511,9 +550,8 @@ static void qaic_pci_remove(struct pci_dev *pdev)
                return;
 
        qaic_dev_reset_clean_local_state(qdev);
-       qaic_destroy_drm_device(qdev, QAIC_NO_PARTITION);
        qaic_mhi_free_controller(qdev->mhi_cntrl, link_up);
-       cleanup_qdev(qdev);
+       qaic_destroy_drm_device(qdev, QAIC_NO_PARTITION);
 }
 
 static void qaic_pci_shutdown(struct pci_dev *pdev)
index e0fd99e61a2d4fcc0f8ea3c671fb0fb2238fa332..0393a9bba3a8a9b9977b6f7e00e0d20c6d890a33 100644 (file)
@@ -102,7 +102,7 @@ static atomic64_t dma_fence_context_counter = ATOMIC64_INIT(1);
  *
  * * Drivers are allowed to call dma_fence_wait() from their &mmu_notifier
  *   respectively &mmu_interval_notifier callbacks. This means any code required
- *   for fence completeion cannot allocate memory with GFP_NOFS or GFP_NOIO.
+ *   for fence completion cannot allocate memory with GFP_NOFS or GFP_NOIO.
  *   Only GFP_ATOMIC is permissible, which might fail.
  *
  * Note that only GPU drivers have a reasonable excuse for both requiring
@@ -522,7 +522,7 @@ dma_fence_wait_timeout(struct dma_fence *fence, bool intr, signed long timeout)
 EXPORT_SYMBOL(dma_fence_wait_timeout);
 
 /**
- * dma_fence_release - default relese function for fences
+ * dma_fence_release - default release function for fences
  * @kref: &dma_fence.recfount
  *
  * This is the default release functions for &dma_fence. Drivers shouldn't call
@@ -974,8 +974,8 @@ void dma_fence_set_deadline(struct dma_fence *fence, ktime_t deadline)
 EXPORT_SYMBOL(dma_fence_set_deadline);
 
 /**
- * dma_fence_describe - Dump fence describtion into seq_file
- * @fence: the 6fence to describe
+ * dma_fence_describe - Dump fence description into seq_file
+ * @fence: the fence to describe
  * @seq: the seq_file to put the textual description into
  *
  * Dump a textual description of the fence and it's state into the seq_file.
index eb8b733065b24d64de661fd5f0781766f1a6bfa2..e2869fb311403964b492d2e5d9f0d37993c8bff5 100644 (file)
@@ -405,7 +405,7 @@ static void dma_resv_iter_walk_unlocked(struct dma_resv_iter *cursor)
  *
  * Beware that the iterator can be restarted.  Code which accumulates statistics
  * or similar needs to check for this with dma_resv_iter_is_restarted(). For
- * this reason prefer the locked dma_resv_iter_first() whenver possible.
+ * this reason prefer the locked dma_resv_iter_first() whenever possible.
  *
  * Returns the first fence from an unlocked dma_resv obj.
  */
@@ -428,7 +428,7 @@ EXPORT_SYMBOL(dma_resv_iter_first_unlocked);
  *
  * Beware that the iterator can be restarted.  Code which accumulates statistics
  * or similar needs to check for this with dma_resv_iter_is_restarted(). For
- * this reason prefer the locked dma_resv_iter_next() whenver possible.
+ * this reason prefer the locked dma_resv_iter_next() whenever possible.
  *
  * Returns the next fence from an unlocked dma_resv obj.
  */
index 2520db0b776e1bccf213fd541baf6275dbb192eb..872edb47bb53236b6296a7f1e02b187a73e30b48 100644 (file)
@@ -19,8 +19,7 @@ menuconfig DRM
 # gallium uses SYS_kcmp for os_same_file_description() to de-duplicate
 # device and dmabuf fd. Let's make sure that is available for our userspace.
        select KCMP
-       select VIDEO_CMDLINE
-       select VIDEO_NOMODESET
+       select VIDEO
        help
          Kernel-level support for the Direct Rendering Infrastructure (DRI)
          introduced in XFree86 4.0. If you say Y here, you need to select
@@ -42,7 +41,7 @@ config DRM_MIPI_DSI
 config DRM_DEBUG_MM
        bool "Insert extra checks and debug info into the DRM range managers"
        default n
-       depends on DRM=y
+       depends on DRM
        depends on STACKTRACE_SUPPORT
        select STACKDEPOT
        help
@@ -289,19 +288,7 @@ config DRM_VGEM
          as used by Mesa's software renderer for enhanced performance.
          If M is selected the module will be called vgem.
 
-config DRM_VKMS
-       tristate "Virtual KMS (EXPERIMENTAL)"
-       depends on DRM && MMU
-       select DRM_KMS_HELPER
-       select DRM_GEM_SHMEM_HELPER
-       select CRC32
-       default n
-       help
-         Virtual Kernel Mode-Setting (VKMS) is used for testing or for
-         running GPU in a headless machines. Choose this option to get
-         a VKMS.
-
-         If M is selected the module will be called vkms.
+source "drivers/gpu/drm/vkms/Kconfig"
 
 source "drivers/gpu/drm/exynos/Kconfig"
 
index 425cebcc5cbff76d154ccb0d5a571573cbcd4955..b671b06654923d7a1cdfe4d528bc75a91c661240 100644 (file)
@@ -220,9 +220,6 @@ void amdgpu_bo_placement_from_domain(struct amdgpu_bo *abo, u32 domain)
 
        placement->num_placement = c;
        placement->placement = places;
-
-       placement->num_busy_placement = c;
-       placement->busy_placement = places;
 }
 
 /**
@@ -1397,8 +1394,7 @@ vm_fault_t amdgpu_bo_fault_reserve_notify(struct ttm_buffer_object *bo)
                                        AMDGPU_GEM_DOMAIN_GTT);
 
        /* Avoid costly evictions; only set GTT as a busy placement */
-       abo->placement.num_busy_placement = 1;
-       abo->placement.busy_placement = &abo->placements[1];
+       abo->placements[0].flags |= TTM_PL_FLAG_DESIRED;
 
        r = ttm_bo_validate(bo, &abo->placement, &ctx);
        if (unlikely(r == -EBUSY || r == -ERESTARTSYS))
index 75c9fd2c6c2a1cb4cc39689668f2f65f036e55c5..8722beba494e563fd45c3e2f3cfba05a7f9d38e8 100644 (file)
@@ -102,23 +102,19 @@ static void amdgpu_evict_flags(struct ttm_buffer_object *bo,
        /* Don't handle scatter gather BOs */
        if (bo->type == ttm_bo_type_sg) {
                placement->num_placement = 0;
-               placement->num_busy_placement = 0;
                return;
        }
 
        /* Object isn't an AMDGPU object so ignore */
        if (!amdgpu_bo_is_amdgpu_bo(bo)) {
                placement->placement = &placements;
-               placement->busy_placement = &placements;
                placement->num_placement = 1;
-               placement->num_busy_placement = 1;
                return;
        }
 
        abo = ttm_to_amdgpu_bo(bo);
        if (abo->flags & AMDGPU_GEM_CREATE_DISCARDABLE) {
                placement->num_placement = 0;
-               placement->num_busy_placement = 0;
                return;
        }
 
@@ -128,13 +124,13 @@ static void amdgpu_evict_flags(struct ttm_buffer_object *bo,
        case AMDGPU_PL_OA:
        case AMDGPU_PL_DOORBELL:
                placement->num_placement = 0;
-               placement->num_busy_placement = 0;
                return;
 
        case TTM_PL_VRAM:
                if (!adev->mman.buffer_funcs_enabled) {
                        /* Move to system memory */
                        amdgpu_bo_placement_from_domain(abo, AMDGPU_GEM_DOMAIN_CPU);
+
                } else if (!amdgpu_gmc_vram_full_visible(&adev->gmc) &&
                           !(abo->flags & AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED) &&
                           amdgpu_bo_in_cpu_visible_vram(abo)) {
@@ -149,8 +145,7 @@ static void amdgpu_evict_flags(struct ttm_buffer_object *bo,
                                                        AMDGPU_GEM_DOMAIN_CPU);
                        abo->placements[0].fpfn = adev->gmc.visible_vram_size >> PAGE_SHIFT;
                        abo->placements[0].lpfn = 0;
-                       abo->placement.busy_placement = &abo->placements[1];
-                       abo->placement.num_busy_placement = 1;
+                       abo->placements[0].flags |= TTM_PL_FLAG_DESIRED;
                } else {
                        /* Move to GTT memory */
                        amdgpu_bo_placement_from_domain(abo, AMDGPU_GEM_DOMAIN_GTT |
@@ -966,8 +961,6 @@ int amdgpu_ttm_alloc_gart(struct ttm_buffer_object *bo)
        /* allocate GART space */
        placement.num_placement = 1;
        placement.placement = &placements;
-       placement.num_busy_placement = 1;
-       placement.busy_placement = &placements;
        placements.fpfn = 0;
        placements.lpfn = adev->gmc.gart_size >> PAGE_SHIFT;
        placements.mem_type = TTM_PL_TT;
index 2f300f5ca051cc17426aa7d6ad63420d787007ca..b589136ca6da9f5d9f397ac2931f5991ab51e5bb 100644 (file)
@@ -2240,11 +2240,13 @@ static void it6505_link_training_work(struct work_struct *work)
        ret = it6505_link_start_auto_train(it6505);
        DRM_DEV_DEBUG_DRIVER(dev, "auto train %s, auto_train_retry: %d",
                             ret ? "pass" : "failed", it6505->auto_train_retry);
-       it6505->auto_train_retry--;
 
        if (ret) {
+               it6505->auto_train_retry = AUTO_TRAIN_RETRY;
                it6505_link_train_ok(it6505);
                return;
+       } else {
+               it6505->auto_train_retry--;
        }
 
        it6505_dump(it6505);
index 9663601ce0981803e0a4e0d3cecba8261097b663..b9205d14d943356a135943ef7a329cb41df9bb21 100644 (file)
@@ -18,6 +18,7 @@
 
 #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>
 #include <drm/drm_print.h>
index e971b75e90ad01d2097773226e24a15d09245750..f3f130c1ef0ae4a106a5f5a4abffa54baab1024e 100644 (file)
@@ -21,6 +21,7 @@
 
 #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_print.h>
 #include <drm/drm_probe_helper.h>
index be5914caa17d546601d11719976161624c1a420f..f9d85fe1df7ec6bbf1d6724cd7abb668ba9b64d2 100644 (file)
@@ -96,6 +96,7 @@
 #define DSIM_MFLUSH_VS                 BIT(29)
 /* This flag is valid only for exynos3250/3472/5260/5430 */
 #define DSIM_CLKLANE_STOP              BIT(30)
+#define DSIM_NON_CONTINUOUS_CLKLANE    BIT(31)
 
 /* DSIM_ESCMODE */
 #define DSIM_TX_TRIGGER_RST            BIT(4)
@@ -945,8 +946,12 @@ static int samsung_dsim_init_link(struct samsung_dsim *dsi)
         * power consumption.
         */
        if (driver_data->has_clklane_stop &&
-           dsi->mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS)
+           dsi->mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS) {
+               if (!samsung_dsim_hw_is_exynos(dsi->plat_data->hw_type))
+                       reg |= DSIM_NON_CONTINUOUS_CLKLANE;
+
                reg |= DSIM_CLKLANE_STOP;
+       }
        samsung_dsim_write(dsi, DSIM_CONFIG_REG, reg);
 
        lanes_mask = BIT(dsi->lanes) - 1;
@@ -1494,7 +1499,6 @@ static void samsung_dsim_atomic_pre_enable(struct drm_bridge *bridge,
                        return;
 
                samsung_dsim_set_display_mode(dsi);
-               samsung_dsim_set_display_enable(dsi, true);
        }
 }
 
@@ -1507,6 +1511,7 @@ static void samsung_dsim_atomic_enable(struct drm_bridge *bridge,
                samsung_dsim_set_display_mode(dsi);
                samsung_dsim_set_display_enable(dsi, true);
        } else {
+               samsung_dsim_set_display_enable(dsi, true);
                samsung_dsim_set_stop_state(dsi, false);
        }
 
@@ -1524,6 +1529,8 @@ static void samsung_dsim_atomic_disable(struct drm_bridge *bridge,
        if (!samsung_dsim_hw_is_exynos(dsi->plat_data->hw_type))
                samsung_dsim_set_stop_state(dsi, true);
 
+       samsung_dsim_set_display_enable(dsi, false);
+
        dsi->state &= ~DSIM_STATE_VIDOUT_AVAILABLE;
 }
 
@@ -1532,7 +1539,8 @@ static void samsung_dsim_atomic_post_disable(struct drm_bridge *bridge,
 {
        struct samsung_dsim *dsi = bridge_to_dsi(bridge);
 
-       samsung_dsim_set_display_enable(dsi, false);
+       if (!samsung_dsim_hw_is_exynos(dsi->plat_data->hw_type))
+               samsung_dsim_set_stop_state(dsi, true);
 
        dsi->state &= ~DSIM_STATE_ENABLED;
        pm_runtime_put_sync(dsi->dev);
@@ -2020,11 +2028,11 @@ int samsung_dsim_probe(struct platform_device *pdev)
        else
                dsi->bridge.timings = &samsung_dsim_bridge_timings_de_high;
 
-       if (dsi->plat_data->host_ops && dsi->plat_data->host_ops->register_host)
+       if (dsi->plat_data->host_ops && dsi->plat_data->host_ops->register_host) {
                ret = dsi->plat_data->host_ops->register_host(dsi);
-
-       if (ret)
-               goto err_disable_runtime;
+               if (ret)
+                       goto err_disable_runtime;
+       }
 
        return 0;
 
index 2bdc5b439bebd56407af3b5b04892b3ac90678d4..4560ae9cbce15095eddaf6296396960a7887ab06 100644 (file)
@@ -1080,6 +1080,26 @@ static int sii902x_init(struct sii902x *sii902x)
                        return ret;
        }
 
+       ret = sii902x_audio_codec_init(sii902x, dev);
+       if (ret)
+               return ret;
+
+       i2c_set_clientdata(sii902x->i2c, sii902x);
+
+       sii902x->i2cmux = i2c_mux_alloc(sii902x->i2c->adapter, dev,
+                                       1, 0, I2C_MUX_GATE,
+                                       sii902x_i2c_bypass_select,
+                                       sii902x_i2c_bypass_deselect);
+       if (!sii902x->i2cmux) {
+               ret = -ENOMEM;
+               goto err_unreg_audio;
+       }
+
+       sii902x->i2cmux->priv = sii902x;
+       ret = i2c_mux_add_adapter(sii902x->i2cmux, 0, 0, 0);
+       if (ret)
+               goto err_unreg_audio;
+
        sii902x->bridge.funcs = &sii902x_bridge_funcs;
        sii902x->bridge.of_node = dev->of_node;
        sii902x->bridge.timings = &default_sii902x_timings;
@@ -1090,19 +1110,13 @@ static int sii902x_init(struct sii902x *sii902x)
 
        drm_bridge_add(&sii902x->bridge);
 
-       sii902x_audio_codec_init(sii902x, dev);
-
-       i2c_set_clientdata(sii902x->i2c, sii902x);
+       return 0;
 
-       sii902x->i2cmux = i2c_mux_alloc(sii902x->i2c->adapter, dev,
-                                       1, 0, I2C_MUX_GATE,
-                                       sii902x_i2c_bypass_select,
-                                       sii902x_i2c_bypass_deselect);
-       if (!sii902x->i2cmux)
-               return -ENOMEM;
+err_unreg_audio:
+       if (!PTR_ERR_OR_ZERO(sii902x->audio.pdev))
+               platform_device_unregister(sii902x->audio.pdev);
 
-       sii902x->i2cmux->priv = sii902x;
-       return i2c_mux_add_adapter(sii902x->i2cmux, 0, 0, 0);
+       return ret;
 }
 
 static int sii902x_probe(struct i2c_client *client)
@@ -1170,12 +1184,14 @@ static int sii902x_probe(struct i2c_client *client)
 }
 
 static void sii902x_remove(struct i2c_client *client)
-
 {
        struct sii902x *sii902x = i2c_get_clientdata(client);
 
-       i2c_mux_del_adapters(sii902x->i2cmux);
        drm_bridge_remove(&sii902x->bridge);
+       i2c_mux_del_adapters(sii902x->i2cmux);
+
+       if (!PTR_ERR_OR_ZERO(sii902x->audio.pdev))
+               platform_device_unregister(sii902x->audio.pdev);
 }
 
 static const struct of_device_id sii902x_dt_ids[] = {
index aca5bb0866f886c05f5914ec647242ee1326509a..ca74a20015b3dc8a6733d0aad846c14f88a0895f 100644 (file)
@@ -31,6 +31,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_of.h>
 #include <drm/drm_print.h>
 #include <drm/drm_probe_helper.h>
index 615cc8f950d7b3e11d174f61559a13088af91179..f10ba91dc252dd65011e0cfc6df0735df4b7ebce 100644 (file)
 
 /* Registers */
 
+/* DSI D-PHY Layer registers */
+#define D0W_DPHYCONTTX         0x0004
+#define CLW_DPHYCONTTX         0x0020
+#define D0W_DPHYCONTRX         0x0024
+#define D1W_DPHYCONTRX         0x0028
+#define D2W_DPHYCONTRX         0x002c
+#define D3W_DPHYCONTRX         0x0030
+#define COM_DPHYCONTRX         0x0038
+#define CLW_CNTRL              0x0040
+#define D0W_CNTRL              0x0044
+#define D1W_CNTRL              0x0048
+#define D2W_CNTRL              0x004c
+#define D3W_CNTRL              0x0050
+#define TESTMODE_CNTRL         0x0054
+
 /* PPI layer registers */
 #define PPI_STARTPPI           0x0104 /* START control bit */
+#define PPI_BUSYPPI            0x0108 /* PPI busy status */
 #define PPI_LPTXTIMECNT                0x0114 /* LPTX timing signal */
 #define LPX_PERIOD                     3
 #define PPI_LANEENABLE         0x0134
@@ -59,6 +75,7 @@
 
 /* DSI layer registers */
 #define DSI_STARTDSI           0x0204 /* START control bit of DSI-TX */
+#define DSI_BUSYDSI            0x0208 /* DSI busy status */
 #define DSI_LANEENABLE         0x0210 /* Enables each lane */
 #define DSI_RX_START                   BIT(0)
 
 #define LANEENABLE_L2EN                BIT(1)
 #define LANEENABLE_L3EN                BIT(2)
 
+#define DSI_LANESTATUS0                0x0214  /* DSI lane status 0 */
+#define DSI_LANESTATUS1                0x0218  /* DSI lane status 1 */
+#define DSI_INTSTATUS          0x0220  /* Interrupt Status */
+#define DSI_INTMASK            0x0224  /* Interrupt Mask */
+#define DSI_INTCLR             0x0228  /* Interrupt Clear */
+#define DSI_LPTXTO             0x0230  /* LPTX Time Out Counter */
+
+/* DSI General Registers */
+#define DSIERRCNT              0x0300  /* DSI Error Count Register */
+
+/* DSI Application Layer Registers */
+#define APLCTRL                        0x0400  /* Application layer Control Register */
+#define RDPKTLN                        0x0404  /* DSI Read packet Length Register */
+
 /* Display Parallel Input Interface */
 #define DPIPXLFMT              0x0440
 #define VS_POL_ACTIVE_LOW              (1 << 10)
 #define VFUEN                          BIT(0)   /* Video Frame Timing Upload */
 
 /* System */
-#define TC_IDREG               0x0500
-#define SYSSTAT                        0x0508
-#define SYSCTRL                        0x0510
-#define DP0_AUDSRC_NO_INPUT            (0 << 3)
-#define DP0_AUDSRC_I2S_RX              (1 << 3)
-#define DP0_VIDSRC_NO_INPUT            (0 << 0)
-#define DP0_VIDSRC_DSI_RX              (1 << 0)
-#define DP0_VIDSRC_DPI_RX              (2 << 0)
-#define DP0_VIDSRC_COLOR_BAR           (3 << 0)
-#define SYSRSTENB              0x050c
+#define TC_IDREG               0x0500  /* Chip ID and Revision ID */
+#define SYSBOOT                        0x0504  /* System BootStrap Status Register */
+#define SYSSTAT                        0x0508  /* System Status Register */
+#define SYSRSTENB              0x050c /* System Reset/Enable Register */
 #define ENBI2C                         (1 << 0)
 #define ENBLCD0                                (1 << 2)
 #define ENBBM                          (1 << 3)
 #define ENBDSIRX                       (1 << 4)
 #define ENBREG                         (1 << 5)
 #define ENBHDCP                                (1 << 8)
-#define GPIOM                  0x0540
-#define GPIOC                  0x0544
-#define GPIOO                  0x0548
-#define GPIOI                  0x054c
-#define INTCTL_G               0x0560
-#define INTSTS_G               0x0564
+#define SYSCTRL                        0x0510  /* System Control Register */
+#define DP0_AUDSRC_NO_INPUT            (0 << 3)
+#define DP0_AUDSRC_I2S_RX              (1 << 3)
+#define DP0_VIDSRC_NO_INPUT            (0 << 0)
+#define DP0_VIDSRC_DSI_RX              (1 << 0)
+#define DP0_VIDSRC_DPI_RX              (2 << 0)
+#define DP0_VIDSRC_COLOR_BAR           (3 << 0)
+#define GPIOM                  0x0540  /* GPIO Mode Control Register */
+#define GPIOC                  0x0544  /* GPIO Direction Control Register */
+#define GPIOO                  0x0548  /* GPIO Output Register */
+#define GPIOI                  0x054c  /* GPIO Input Register */
+#define INTCTL_G               0x0560  /* General Interrupts Control Register */
+#define INTSTS_G               0x0564  /* General Interrupts Status Register */
 
 #define INT_SYSERR             BIT(16)
 #define INT_GPIO_H(x)          (1 << (x == 0 ? 2 : 10))
 #define INT_GPIO_LC(x)         (1 << (x == 0 ? 3 : 11))
 
-#define INT_GP0_LCNT           0x0584
-#define INT_GP1_LCNT           0x0588
+#define TEST_INT_C             0x0570  /* Test Interrupts Control Register */
+#define TEST_INT_S             0x0574  /* Test Interrupts Status Register */
+
+#define INT_GP0_LCNT           0x0584  /* Interrupt GPIO0 Low Count Value Register */
+#define INT_GP1_LCNT           0x0588  /* Interrupt GPIO1 Low Count Value Register */
 
 /* Control */
 #define DP0CTL                 0x0600
 #define DP_EN                          BIT(0)   /* Enable DPTX function */
 
 /* Clocks */
-#define DP0_VIDMNGEN0          0x0610
-#define DP0_VIDMNGEN1          0x0614
-#define DP0_VMNGENSTATUS       0x0618
+#define DP0_VIDMNGEN0          0x0610  /* DP0 Video Force M Value Register */
+#define DP0_VIDMNGEN1          0x0614  /* DP0 Video Force N Value Register */
+#define DP0_VMNGENSTATUS       0x0618  /* DP0 Video Current M Value Register */
+#define DP0_AUDMNGEN0          0x0628  /* DP0 Audio Force M Value Register */
+#define DP0_AUDMNGEN1          0x062c  /* DP0 Audio Force N Value Register */
+#define DP0_AMNGENSTATUS       0x0630  /* DP0 Audio Current M Value Register */
 
 /* Main Channel */
 #define DP0_SECSAMPLE          0x0640
 #define DP0_SNKLTCHGREQ                0x06d4
 #define DP0_LTLOOPCTRL         0x06d8
 #define DP0_SNKLTCTRL          0x06e4
-
-#define DP1_SRCCTRL            0x07a0
+#define DP0_TPATDAT0           0x06e8  /* DP0 Test Pattern bits 29 to 0 */
+#define DP0_TPATDAT1           0x06ec  /* DP0 Test Pattern bits 59 to 30 */
+#define DP0_TPATDAT2           0x06f0  /* DP0 Test Pattern bits 89 to 60 */
+#define DP0_TPATDAT3           0x06f4  /* DP0 Test Pattern bits 119 to 90 */
+
+#define AUDCFG0                        0x0700  /* DP0 Audio Config0 Register */
+#define AUDCFG1                        0x0704  /* DP0 Audio Config1 Register */
+#define AUDIFDATA0             0x0708  /* DP0 Audio Info Frame Bytes 3 to 0 */
+#define AUDIFDATA1             0x070c  /* DP0 Audio Info Frame Bytes 7 to 4 */
+#define AUDIFDATA2             0x0710  /* DP0 Audio Info Frame Bytes 11 to 8 */
+#define AUDIFDATA3             0x0714  /* DP0 Audio Info Frame Bytes 15 to 12 */
+#define AUDIFDATA4             0x0718  /* DP0 Audio Info Frame Bytes 19 to 16 */
+#define AUDIFDATA5             0x071c  /* DP0 Audio Info Frame Bytes 23 to 20 */
+#define AUDIFDATA6             0x0720  /* DP0 Audio Info Frame Bytes 27 to 24 */
+
+#define DP1_SRCCTRL            0x07a0  /* DP1 Control Register */
 
 /* PHY */
 #define DP_PHY_CTRL            0x0800
 #define PHY_2LANE                      BIT(2)   /* PHY Enable 2 lanes */
 #define PHY_A0_EN                      BIT(1)   /* PHY Aux Channel0 Enable */
 #define PHY_M0_EN                      BIT(0)   /* PHY Main Channel0 Enable */
+#define DP_PHY_CFG_WR          0x0810  /* DP PHY Configuration Test Write Register */
+#define DP_PHY_CFG_RD          0x0814  /* DP PHY Configuration Test Read Register */
+#define DP0_AUX_PHY_CTRL       0x0820  /* DP0 AUX PHY Control Register */
+#define DP0_MAIN_PHY_DBG       0x0840  /* DP0 Main PHY Test Debug Register */
+
+/* I2S */
+#define I2SCFG                 0x0880  /* I2S Audio Config 0 Register */
+#define I2SCH0STAT0            0x0888  /* I2S Audio Channel 0 Status Bytes 3 to 0 */
+#define I2SCH0STAT1            0x088c  /* I2S Audio Channel 0 Status Bytes 7 to 4 */
+#define I2SCH0STAT2            0x0890  /* I2S Audio Channel 0 Status Bytes 11 to 8 */
+#define I2SCH0STAT3            0x0894  /* I2S Audio Channel 0 Status Bytes 15 to 12 */
+#define I2SCH0STAT4            0x0898  /* I2S Audio Channel 0 Status Bytes 19 to 16 */
+#define I2SCH0STAT5            0x089c  /* I2S Audio Channel 0 Status Bytes 23 to 20 */
+#define I2SCH1STAT0            0x08a0  /* I2S Audio Channel 1 Status Bytes 3 to 0 */
+#define I2SCH1STAT1            0x08a4  /* I2S Audio Channel 1 Status Bytes 7 to 4 */
+#define I2SCH1STAT2            0x08a8  /* I2S Audio Channel 1 Status Bytes 11 to 8 */
+#define I2SCH1STAT3            0x08ac  /* I2S Audio Channel 1 Status Bytes 15 to 12 */
+#define I2SCH1STAT4            0x08b0  /* I2S Audio Channel 1 Status Bytes 19 to 16 */
+#define I2SCH1STAT5            0x08b4  /* I2S Audio Channel 1 Status Bytes 23 to 20 */
 
 /* PLL */
 #define DP0_PLLCTRL            0x0900
@@ -546,9 +617,14 @@ static int tc_pxl_pll_en(struct tc_data *tc, u32 refclk, u32 pixelclock)
                        continue;
                for (i_post = 0; i_post < ARRAY_SIZE(ext_div); i_post++) {
                        for (div = 1; div <= 16; div++) {
-                               u32 clk;
+                               u32 clk, iclk;
                                u64 tmp;
 
+                               /* PCLK PLL input unit clock ... 6..40 MHz */
+                               iclk = refclk / (div * ext_div[i_pre]);
+                               if (iclk < 6000000 || iclk > 40000000)
+                                       continue;
+
                                tmp = pixelclock * ext_div[i_pre] *
                                      ext_div[i_post] * div;
                                do_div(tmp, refclk);
@@ -1833,16 +1909,16 @@ static bool tc_readable_reg(struct device *dev, unsigned int reg)
        case 0x1f4:
        /* DSI Protocol Layer */
        case DSI_STARTDSI:
-       case 0x208:
+       case DSI_BUSYDSI:
        case DSI_LANEENABLE:
-       case 0x214:
-       case 0x218:
-       case 0x220:
+       case DSI_LANESTATUS0:
+       case DSI_LANESTATUS1:
+       case DSI_INTSTATUS:
        case 0x224:
        case 0x228:
        case 0x230:
        /* DSI General */
-       case 0x300:
+       case DSIERRCNT:
        /* DSI Application Layer */
        case 0x400:
        case 0x404:
@@ -1978,13 +2054,20 @@ static bool tc_readable_reg(struct device *dev, unsigned int reg)
 }
 
 static const struct regmap_range tc_volatile_ranges[] = {
+       regmap_reg_range(PPI_BUSYPPI, PPI_BUSYPPI),
+       regmap_reg_range(DSI_BUSYDSI, DSI_BUSYDSI),
+       regmap_reg_range(DSI_LANESTATUS0, DSI_INTSTATUS),
+       regmap_reg_range(DSIERRCNT, DSIERRCNT),
+       regmap_reg_range(VFUEN0, VFUEN0),
+       regmap_reg_range(SYSSTAT, SYSSTAT),
+       regmap_reg_range(GPIOI, GPIOI),
+       regmap_reg_range(INTSTS_G, INTSTS_G),
+       regmap_reg_range(DP0_VMNGENSTATUS, DP0_VMNGENSTATUS),
+       regmap_reg_range(DP0_AMNGENSTATUS, DP0_AMNGENSTATUS),
        regmap_reg_range(DP0_AUXWDATA(0), DP0_AUXSTATUS),
        regmap_reg_range(DP0_LTSTAT, DP0_SNKLTCHGREQ),
        regmap_reg_range(DP_PHY_CTRL, DP_PHY_CTRL),
        regmap_reg_range(DP0_PLLCTRL, PXL_PLLCTRL),
-       regmap_reg_range(VFUEN0, VFUEN0),
-       regmap_reg_range(INTSTS_G, INTSTS_G),
-       regmap_reg_range(GPIOI, GPIOI),
 };
 
 static const struct regmap_access_table tc_volatile_table = {
@@ -1992,12 +2075,28 @@ static const struct regmap_access_table tc_volatile_table = {
        .n_yes_ranges = ARRAY_SIZE(tc_volatile_ranges),
 };
 
-static bool tc_writeable_reg(struct device *dev, unsigned int reg)
-{
-       return (reg != TC_IDREG) &&
-              (reg != DP0_LTSTAT) &&
-              (reg != DP0_SNKLTCHGREQ);
-}
+static const struct regmap_range tc_precious_ranges[] = {
+       regmap_reg_range(SYSSTAT, SYSSTAT),
+};
+
+static const struct regmap_access_table tc_precious_table = {
+       .yes_ranges = tc_precious_ranges,
+       .n_yes_ranges = ARRAY_SIZE(tc_precious_ranges),
+};
+
+static const struct regmap_range tc_non_writeable_ranges[] = {
+       regmap_reg_range(PPI_BUSYPPI, PPI_BUSYPPI),
+       regmap_reg_range(DSI_BUSYDSI, DSI_BUSYDSI),
+       regmap_reg_range(DSI_LANESTATUS0, DSI_INTSTATUS),
+       regmap_reg_range(TC_IDREG, SYSSTAT),
+       regmap_reg_range(GPIOI, GPIOI),
+       regmap_reg_range(DP0_LTSTAT, DP0_SNKLTCHGREQ),
+};
+
+static const struct regmap_access_table tc_writeable_table = {
+       .no_ranges = tc_non_writeable_ranges,
+       .n_no_ranges = ARRAY_SIZE(tc_non_writeable_ranges),
+};
 
 static const struct regmap_config tc_regmap_config = {
        .name = "tc358767",
@@ -2008,7 +2107,8 @@ static const struct regmap_config tc_regmap_config = {
        .cache_type = REGCACHE_MAPLE,
        .readable_reg = tc_readable_reg,
        .volatile_table = &tc_volatile_table,
-       .writeable_reg = tc_writeable_reg,
+       .precious_table = &tc_precious_table,
+       .wr_table = &tc_writeable_table,
        .reg_format_endian = REGMAP_ENDIAN_BIG,
        .val_format_endian = REGMAP_ENDIAN_LITTLE,
 };
index f73f3471e94e82e184004cc38c5318bd402dc7c6..106f2d40d222fe2d3af7d22186e6aaff35e3c5e1 100644 (file)
@@ -26,6 +26,7 @@ if [[ "$KERNEL_ARCH" = "arm64" ]]; then
     DEVICE_TREES+=" arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-juniper-sku16.dtb"
     DEVICE_TREES+=" arch/arm64/boot/dts/mediatek/mt8192-asurada-spherion-r0.dtb"
     DEVICE_TREES+=" arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-limozeen-nots-r5.dtb"
+    DEVICE_TREES+=" arch/arm64/boot/dts/qcom/sc7180-trogdor-kingoftown.dtb"
 elif [[ "$KERNEL_ARCH" = "arm" ]]; then
     GCC_ARCH="arm-linux-gnueabihf"
     DEBIAN_ARCH="armhf"
index dac92cc2777cc3a91a5e8e5a2aa073faeb71f360..084e3ff8e3f42df368537358e984f22c9ec5f0e0 100644 (file)
@@ -1,6 +1,6 @@
 variables:
   DRM_CI_PROJECT_PATH: &drm-ci-project-path mesa/mesa
-  DRM_CI_COMMIT_SHA: &drm-ci-commit-sha edfbf74df1d4d6ce54ffe24566108be0e1a98c3d
+  DRM_CI_COMMIT_SHA: &drm-ci-commit-sha 9d162de9a05155e1c4041857a5848842749164cf
 
   UPSTREAM_REPO: git://anongit.freedesktop.org/drm/drm
   TARGET_BRANCH: drm-next
@@ -25,7 +25,9 @@ variables:
   # per-job artifact storage on MinIO
   JOB_ARTIFACTS_BASE: ${PIPELINE_ARTIFACTS_BASE}/${CI_JOB_ID}
   # default kernel for rootfs before injecting the current kernel tree
-  KERNEL_IMAGE_BASE: https://${S3_HOST}/mesa-lava/gfx-ci/linux/v6.4.12-for-mesa-ci-f6b4ad45f48d
+  KERNEL_REPO: "gfx-ci/linux"
+  KERNEL_TAG: "v6.6.4-for-mesa-ci-e4f4c500f7fb"
+  KERNEL_IMAGE_BASE: https://${S3_HOST}/mesa-lava/${KERNEL_REPO}/${KERNEL_TAG}
   LAVA_TAGS: subset-1-gfx
   LAVA_JOB_PRIORITY: 30
 
@@ -133,6 +135,11 @@ stages:
     - if: &is-pre-merge-for-marge '$GITLAB_USER_LOGIN == "marge-bot" && $CI_PIPELINE_SOURCE == "merge_request_event"'
       when: on_success
 
+.never-post-merge-rules:
+  rules:
+    - if: *is-post-merge
+      when: never
+
 # Rule to filter for only scheduled pipelines.
 .scheduled_pipeline-rules:
   rules:
@@ -150,6 +157,7 @@ stages:
 .build-rules:
   rules:
     - !reference [.no_scheduled_pipelines-rules, rules]
+    - !reference [.never-post-merge-rules, rules]
     # Run automatically once all dependency jobs have passed
     - when: on_success
 
@@ -157,6 +165,7 @@ stages:
 .container+build-rules:
   rules:
     - !reference [.no_scheduled_pipelines-rules, rules]
+    - !reference [.never-post-merge-rules, rules]
     - when: manual
 
 .ci-deqp-artifacts:
@@ -175,6 +184,7 @@ stages:
 .container-rules:
   rules:
     - !reference [.no_scheduled_pipelines-rules, rules]
+    - !reference [.never-post-merge-rules, rules]
     # Run pipeline by default in the main project if any CI pipeline
     # configuration files were changed, to ensure docker images are up to date
     - if: *is-post-merge
index 2c9a1838e7284c93c43296f52a6c9157c749a840..355b794ef2b1bbd8bd3b339e1f55833b50b1be50 100644 (file)
   tags:
     - $RUNNER_TAG
 
-msm:sc7180:
+.msm-sc7180:
   extends:
     - .lava-igt:arm64
   stage: msm
-  parallel: 4
   variables:
     DRIVER_NAME: msm
-    DEVICE_TYPE: sc7180-trogdor-lazor-limozeen
-    DTB: sc7180-trogdor-lazor-limozeen-nots-r5
     BOOT_METHOD: depthcharge
     KERNEL_IMAGE_TYPE: ""
-    GPU_VERSION: sc7180
+
+msm:sc7180-trogdor-lazor-limozeen:
+  extends:
+    - .msm-sc7180
+  parallel: 4
+  variables:
+    DEVICE_TYPE: sc7180-trogdor-lazor-limozeen
+    DTB: sc7180-trogdor-lazor-limozeen-nots-r5
+    GPU_VERSION: ${DEVICE_TYPE}
     RUNNER_TAG: mesa-ci-x86-64-lava-sc7180-trogdor-lazor-limozeen
 
+msm:sc7180-trogdor-kingoftown:
+  extends:
+    - .msm-sc7180
+  parallel: 6
+  variables:
+    DEVICE_TYPE: sc7180-trogdor-kingoftown
+    DTB: sc7180-trogdor-kingoftown
+    GPU_VERSION: ${DEVICE_TYPE}
+    RUNNER_TAG: mesa-ci-x86-64-lava-sc7180-trogdor-kingoftown
+
 msm:apq8016:
   extends:
     - .baremetal-igt-arm64
@@ -324,6 +339,7 @@ virtio_gpu:none:
     GPU_VERSION: none
   extends:
     - .test-gl
+    - .test-rules
   tags:
     - kvm
   script:
index f82cd90372f4a4e6f82bd18f5e64a42e4585bad4..eaeb751bb0ad61da172ca4e4601cbfd0027d1340 100644 (file)
@@ -2910,3 +2910,52 @@ kms_writeback@writeback-invalid-parameters
 kms_writeback@writeback-fb-id
 kms_writeback@writeback-check-output
 prime_mmap_kms@buffer-sharing
+msm_shrink@copy-gpu-sanitycheck-8
+msm_shrink@copy-gpu-sanitycheck-32
+msm_shrink@copy-gpu-8
+msm_shrink@copy-gpu-32
+msm_shrink@copy-gpu-madvise-8
+msm_shrink@copy-gpu-madvise-32
+msm_shrink@copy-gpu-oom-8
+msm_shrink@copy-gpu-oom-32
+msm_shrink@copy-mmap-sanitycheck-8
+msm_shrink@copy-mmap-sanitycheck-32
+msm_shrink@copy-mmap-8
+msm_shrink@copy-mmap-32
+msm_shrink@copy-mmap-madvise-8
+msm_shrink@copy-mmap-madvise-32
+msm_shrink@copy-mmap-oom-8
+msm_shrink@copy-mmap-oom-32
+msm_shrink@copy-mmap-dmabuf-sanitycheck-8
+msm_shrink@copy-mmap-dmabuf-sanitycheck-32
+msm_shrink@copy-mmap-dmabuf-8
+msm_shrink@copy-mmap-dmabuf-32
+msm_shrink@copy-mmap-dmabuf-madvise-8
+msm_shrink@copy-mmap-dmabuf-madvise-32
+msm_shrink@copy-mmap-dmabuf-oom-8
+msm_shrink@copy-mmap-dmabuf-oom-32
+msm_mapping@ring
+msm_mapping@sqefw
+msm_mapping@shadow
+msm_submitoverhead@submitbench-10-bos
+msm_submitoverhead@submitbench-10-bos-no-implicit-sync
+msm_submitoverhead@submitbench-100-bos
+msm_submitoverhead@submitbench-100-bos-no-implicit-sync
+msm_submitoverhead@submitbench-250-bos
+msm_submitoverhead@submitbench-250-bos-no-implicit-sync
+msm_submitoverhead@submitbench-500-bos
+msm_submitoverhead@submitbench-500-bos-no-implicit-sync
+msm_submitoverhead@submitbench-1000-bos
+msm_submitoverhead@submitbench-1000-bos-no-implicit-sync
+msm_recovery@hangcheck
+msm_recovery@gpu-fault
+msm_recovery@gpu-fault-parallel
+msm_recovery@iova-fault
+msm_submit@empty-submit
+msm_submit@invalid-queue-submit
+msm_submit@invalid-flags-submit
+msm_submit@invalid-in-fence-submit
+msm_submit@invalid-duplicate-bo-submit
+msm_submit@invalid-cmd-idx-submit
+msm_submit@invalid-cmd-type-submit
+msm_submit@valid-submit
index d39d254c935e9ac56f69de73b03d6259908d84cb..44a5c62dedad98c12cf8d2a194eeba811af4bb7e 100644 (file)
@@ -6,8 +6,6 @@ kms_cursor_legacy@all-pipes-single-bo,Fail
 kms_cursor_legacy@all-pipes-single-move,Fail
 kms_cursor_legacy@all-pipes-torture-bo,Fail
 kms_cursor_legacy@all-pipes-torture-move,Fail
-kms_cursor_legacy@forked-bo,Fail
-kms_cursor_legacy@forked-move,Fail
 kms_cursor_legacy@pipe-A-forked-bo,Fail
 kms_cursor_legacy@pipe-A-forked-move,Fail
 kms_cursor_legacy@pipe-A-single-bo,Fail
@@ -18,3 +16,4 @@ kms_force_connector_basic@force-edid,Fail
 kms_hdmi_inject@inject-4k,Fail
 kms_selftest@drm_format,Timeout
 kms_selftest@drm_format_helper,Timeout
+msm_mapping@ring,Fail
diff --git a/drivers/gpu/drm/ci/xfails/msm-sc7180-fails.txt b/drivers/gpu/drm/ci/xfails/msm-sc7180-fails.txt
deleted file mode 100644 (file)
index f71166a..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-kms_color@ctm-0-25,Fail
-kms_color@ctm-0-50,Fail
-kms_color@ctm-0-75,Fail
-kms_color@ctm-blue-to-red,Fail
-kms_color@ctm-green-to-red,Fail
-kms_color@ctm-negative,Fail
-kms_color@ctm-red-to-blue,Fail
-kms_color@ctm-signed,Fail
-kms_cursor_legacy@cursor-vs-flip-toggle,Fail
-kms_cursor_legacy@cursor-vs-flip-varying-size,Fail
-kms_cursor_legacy@cursorA-vs-flipA-atomic-transitions,Crash
-kms_flip@flip-vs-modeset-vs-hang,Fail
-kms_flip@flip-vs-panning-vs-hang,Fail
-kms_pipe_crc_basic@compare-crc-sanitycheck-nv12,Fail
-kms_plane_alpha_blend@alpha-7efc,Fail
-kms_plane_alpha_blend@coverage-7efc,Fail
-kms_plane_alpha_blend@coverage-vs-premult-vs-constant,Fail
-kms_plane_alpha_blend@pipe-A-alpha-7efc,Fail
-kms_plane_alpha_blend@pipe-A-coverage-7efc,Fail
-kms_plane_alpha_blend@pipe-A-coverage-vs-premult-vs-constant,Fail
-kms_plane_alpha_blend@pipe-B-alpha-7efc,Fail
-kms_plane_alpha_blend@pipe-B-alpha-basic,Fail
-kms_plane_alpha_blend@pipe-B-alpha-opaque-fb,Fail
-kms_plane_alpha_blend@pipe-B-constant-alpha-max,Fail
-kms_plane_alpha_blend@pipe-B-constant-alpha-mid,Fail
-kms_plane_alpha_blend@pipe-B-coverage-7efc,Fail
-kms_plane_alpha_blend@pipe-B-coverage-vs-premult-vs-constant,Fail
-kms_rmfb@close-fd,Fail
-kms_universal_plane@disable-primary-vs-flip-pipe-b,Fail
-kms_universal_plane@universal-plane-pipe-B-sanity,Fail
diff --git a/drivers/gpu/drm/ci/xfails/msm-sc7180-flakes.txt b/drivers/gpu/drm/ci/xfails/msm-sc7180-flakes.txt
deleted file mode 100644 (file)
index 0473004..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-kms_color@ctm-0-25
-kms_color@ctm-0-50
-kms_color@ctm-0-75
-kms_color@ctm-blue-to-red
-kms_color@ctm-green-to-red
-kms_color@ctm-negative
-kms_color@ctm-red-to-blue
-kms_color@ctm-signed
-kms_flip@flip-vs-modeset-vs-hang
-kms_flip@flip-vs-panning-vs-hang
-kms_plane@pixel-format
-kms_plane@pixel-format-source-clamping
-kms_plane@plane-position-covered
-kms_plane@plane-position-hole
-kms_plane@plane-position-hole-dpms
-kms_writeback@writeback-fb-id
-kms_writeback@writeback-invalid-parameters
diff --git a/drivers/gpu/drm/ci/xfails/msm-sc7180-skips.txt b/drivers/gpu/drm/ci/xfails/msm-sc7180-skips.txt
deleted file mode 100644 (file)
index e59a2fd..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-# Suspend to RAM seems to be broken on this machine
-.*suspend.*
-
-# Test incorrectly assumes that CTM support implies gamma/degamma
-# LUT support.  None of the subtests handle the case of only having
-# CTM support
-#kms_color.*
diff --git a/drivers/gpu/drm/ci/xfails/msm-sc7180-trogdor-kingoftown-fails.txt b/drivers/gpu/drm/ci/xfails/msm-sc7180-trogdor-kingoftown-fails.txt
new file mode 100644 (file)
index 0000000..7e4d874
--- /dev/null
@@ -0,0 +1,17 @@
+kms_color@ctm-0-25,Fail
+kms_color@ctm-0-50,Fail
+kms_color@ctm-0-75,Fail
+kms_color@ctm-blue-to-red,Fail
+kms_color@ctm-green-to-red,Fail
+kms_color@ctm-negative,Fail
+kms_color@ctm-red-to-blue,Fail
+kms_color@ctm-signed,Fail
+kms_cursor_legacy@cursor-vs-flip-toggle,Fail
+kms_cursor_legacy@cursor-vs-flip-varying-size,Fail
+kms_flip@flip-vs-modeset-vs-hang,Fail
+kms_flip@flip-vs-panning-vs-hang,Fail
+kms_pipe_crc_basic@compare-crc-sanitycheck-nv12,Fail
+kms_plane_alpha_blend@alpha-7efc,Fail
+kms_plane_alpha_blend@coverage-7efc,Fail
+kms_plane_alpha_blend@coverage-vs-premult-vs-constant,Fail
+kms_rmfb@close-fd,Fail
diff --git a/drivers/gpu/drm/ci/xfails/msm-sc7180-trogdor-lazor-limozeen-fails.txt b/drivers/gpu/drm/ci/xfails/msm-sc7180-trogdor-lazor-limozeen-fails.txt
new file mode 100644 (file)
index 0000000..7e4d874
--- /dev/null
@@ -0,0 +1,17 @@
+kms_color@ctm-0-25,Fail
+kms_color@ctm-0-50,Fail
+kms_color@ctm-0-75,Fail
+kms_color@ctm-blue-to-red,Fail
+kms_color@ctm-green-to-red,Fail
+kms_color@ctm-negative,Fail
+kms_color@ctm-red-to-blue,Fail
+kms_color@ctm-signed,Fail
+kms_cursor_legacy@cursor-vs-flip-toggle,Fail
+kms_cursor_legacy@cursor-vs-flip-varying-size,Fail
+kms_flip@flip-vs-modeset-vs-hang,Fail
+kms_flip@flip-vs-panning-vs-hang,Fail
+kms_pipe_crc_basic@compare-crc-sanitycheck-nv12,Fail
+kms_plane_alpha_blend@alpha-7efc,Fail
+kms_plane_alpha_blend@coverage-7efc,Fail
+kms_plane_alpha_blend@coverage-vs-premult-vs-constant,Fail
+kms_rmfb@close-fd,Fail
index c55baa2d18c1b1a4bf4e2c0b860519921320c30f..e9043a00383efc03ce23bd485bda744681edf046 100644 (file)
@@ -15,7 +15,7 @@ kms_color@pipe-A-ctm-max,Fail
 kms_color@pipe-A-ctm-negative,Fail
 kms_color@pipe-A-ctm-red-to-blue,Fail
 kms_color@pipe-A-legacy-gamma,Fail
-kms_cursor_legacy@basic-flip-after-cursor-legacy,Fail
+kms_cursor_legacy@basic-flip-after-cursor-atomic,Fail
 kms_cursor_legacy@basic-flip-after-cursor-varying-size,Fail
 kms_cursor_legacy@basic-flip-before-cursor-atomic,Fail
 kms_cursor_legacy@basic-flip-before-cursor-legacy,Fail
@@ -29,9 +29,6 @@ kms_cursor_legacy@flip-vs-cursor-atomic,Fail
 kms_cursor_legacy@flip-vs-cursor-crc-atomic,Fail
 kms_cursor_legacy@flip-vs-cursor-crc-legacy,Fail
 kms_cursor_legacy@flip-vs-cursor-legacy,Fail
-kms_cursor_legacy@short-flip-after-cursor-atomic-transitions,Fail
-kms_cursor_legacy@short-flip-after-cursor-atomic-transitions-varying-size,Fail
-kms_cursor_legacy@short-flip-after-cursor-toggle,Fail
 kms_flip@flip-vs-modeset-vs-hang,Fail
 kms_flip@flip-vs-panning-vs-hang,Fail
 kms_pipe_crc_basic@compare-crc-sanitycheck-nv12,Fail
index 16d205c04cbbf186e8be3aef10c1edccb1a5bb80..8a492f01eaa4ac3189aaaeaa620203a796557583 100644 (file)
@@ -1,12 +1,22 @@
-kms_cursor_legacy@basic-flip-after-cursor-atomic
-kms_cursor_legacy@basic-flip-before-cursor-varying-size
-kms_cursor_legacy@cursorA-vs-flipA-toggle
-kms_cursor_legacy@flip-vs-cursor-atomic-transitions
+# Board Name: msm:sdm845
+# Bug Report: https://lore.kernel.org/dri-devel/46287831-edfa-78e8-6055-d7a08831c445@collabora.com/T/#u
+# Failure Rate: 50
+# IGT Version: 1.28-gd2af13d9f
+# Linux Version: 6.7.0-rc3
+
+# Reported by deqp-runner
+kms_cursor_legacy@basic-flip-after-cursor-legacy
 kms_cursor_legacy@flip-vs-cursor-toggle
 kms_cursor_legacy@flip-vs-cursor-varying-size
+kms_cursor_legacy@short-flip-after-cursor-toggle
 kms_cursor_legacy@short-flip-before-cursor-atomic-transitions
-kms_cursor_legacy@short-flip-before-cursor-toggle
-kms_flip@flip-vs-modeset-vs-hang
-kms_flip@flip-vs-panning-vs-hang
-kms_plane@pixel-format
-kms_plane@pixel-format-source-clamping
+kms_cursor_legacy@short-flip-before-cursor-atomic-transitions-varying-size
+msm_shrink@copy-gpu-32
+msm_shrink@copy-gpu-oom-32
+
+# The below test shows inconsistency across multiple runs, giving
+# results of Pass and Fail alternately.
+kms_cursor_legacy@basic-flip-before-cursor-varying-size
+kms_cursor_legacy@flip-vs-cursor-atomic-transitions
+kms_cursor_legacy@short-flip-after-cursor-atomic-transitions
+kms_cursor_legacy@short-flip-after-cursor-atomic-transitions-varying-size
index 42675f1c6d762c819390744c9c0dfec92cb3e203..618e3a3a7277721d91abbfbf9ef30092fbb7e6c4 100644 (file)
@@ -1,2 +1,7 @@
 # Hangs machine
-kms_bw.*
\ No newline at end of file
+kms_bw.*
+
+# Failing due to a bootloader/fw issue. The workaround in mesa CI involves these two patches
+# https://gitlab.freedesktop.org/gfx-ci/linux/-/commit/4b49f902ec6f2bb382cbbf489870573f4b43371e
+# https://gitlab.freedesktop.org/gfx-ci/linux/-/commit/38cdf4c5559771e2474ae0fecef8469f65147bc1
+msm_mapping@*
index f4715a67e340d3f5fdd9ee8f8801af677040d25c..08fcefd804bc09a730e760f9074efffba8685e13 100644 (file)
@@ -45,8 +45,6 @@
 #include "drm_crtc_internal.h"
 #include "drm_internal.h"
 
-#if defined(CONFIG_DEBUG_FS)
-
 /***************************************************
  * Initialization, etc.
  **************************************************/
@@ -647,5 +645,3 @@ void drm_debugfs_encoder_remove(struct drm_encoder *encoder)
        debugfs_remove_recursive(encoder->debugfs_entry);
        encoder->debugfs_entry = NULL;
 }
-
-#endif /* CONFIG_DEBUG_FS */
index 69c68804023ff9a959e482d8c7ac5176f1ab34e1..923c4423151c1eb2c8ce635940898fc01db63825 100644 (file)
@@ -3611,7 +3611,8 @@ static bool mode_in_range(const struct drm_display_mode *mode,
        if (!mode_in_vsync_range(mode, edid, t))
                return false;
 
-       if ((max_clock = range_pixel_clock(edid, t)))
+       max_clock = range_pixel_clock(edid, t);
+       if (max_clock)
                if (mode->clock > max_clock)
                        return false;
 
@@ -6990,28 +6991,6 @@ int drm_add_modes_noedid(struct drm_connector *connector,
 }
 EXPORT_SYMBOL(drm_add_modes_noedid);
 
-/**
- * drm_set_preferred_mode - Sets the preferred mode of a connector
- * @connector: connector whose mode list should be processed
- * @hpref: horizontal resolution of preferred mode
- * @vpref: vertical resolution of preferred mode
- *
- * Marks a mode as preferred if it matches the resolution specified by @hpref
- * and @vpref.
- */
-void drm_set_preferred_mode(struct drm_connector *connector,
-                          int hpref, int vpref)
-{
-       struct drm_display_mode *mode;
-
-       list_for_each_entry(mode, &connector->probed_modes, head) {
-               if (mode->hdisplay == hpref &&
-                   mode->vdisplay == vpref)
-                       mode->type |= DRM_MODE_TYPE_PREFERRED;
-       }
-}
-EXPORT_SYMBOL(drm_set_preferred_mode);
-
 static bool is_hdmi2_sink(const struct drm_connector *connector)
 {
        /*
index 48ee851b61d904b7661095f8e0393e4fc0973035..2da094bdf8a4d282742943500ab84b785fa8e334 100644 (file)
@@ -76,7 +76,7 @@ static void drm_exec_unlock_all(struct drm_exec *exec)
  * If nr is non-zero then it is used as the initial objects table size.
  * In either case, the table will grow (be re-allocated) on demand.
  */
-void drm_exec_init(struct drm_exec *exec, uint32_t flags, unsigned nr)
+void drm_exec_init(struct drm_exec *exec, u32 flags, unsigned nr)
 {
        if (!nr)
                nr = PAGE_SIZE / sizeof(void *);
index b67eafa557159eb59d0142d7ef3062cff3488a98..75f2eaf0d5b610c2f9eb0b85b911676ba7e47b63 100644 (file)
@@ -147,7 +147,6 @@ static void drm_gem_vram_placement(struct drm_gem_vram_object *gbo,
                invariant_flags = TTM_PL_FLAG_TOPDOWN;
 
        gbo->placement.placement = gbo->placements;
-       gbo->placement.busy_placement = gbo->placements;
 
        if (pl_flag & DRM_GEM_VRAM_PL_FLAG_VRAM) {
                gbo->placements[c].mem_type = TTM_PL_VRAM;
@@ -160,7 +159,6 @@ static void drm_gem_vram_placement(struct drm_gem_vram_object *gbo,
        }
 
        gbo->placement.num_placement = c;
-       gbo->placement.num_busy_placement = c;
 
        for (i = 0; i < c; ++i) {
                gbo->placements[i].fpfn = 0;
index 129e2b91dbfe7f785a821c165db0c0b88ff4b1c9..e6b5b06de1487be0f9b0a08892e341a49750534b 100644 (file)
@@ -229,7 +229,7 @@ typedef struct drm_update_draw32 {
        unsigned int num;
        /* 64-bit version has a 32-bit pad here */
        u64 data;       /**< Pointer */
-} __attribute__((packed)) drm_update_draw32_t;
+} __packed drm_update_draw32_t;
 
 static int compat_drm_update_draw(struct file *file, unsigned int cmd,
                                  unsigned long arg)
@@ -296,7 +296,7 @@ typedef struct drm_mode_fb_cmd232 {
        u32 pitches[4];
        u32 offsets[4];
        u64 modifier[4];
-} __attribute__((packed)) drm_mode_fb_cmd232_t;
+} __packed drm_mode_fb_cmd232_t;
 
 static int compat_drm_mode_addfb2(struct file *file, unsigned int cmd,
                                  unsigned long arg)
index bcd111404b128aacb5081cfb4a489dab636923e2..7646f67bda4e47bf9f1a233e107d080f3e25770f 100644 (file)
@@ -176,6 +176,45 @@ int __drmm_add_action_or_reset(struct drm_device *dev,
 }
 EXPORT_SYMBOL(__drmm_add_action_or_reset);
 
+/**
+ * drmm_release_action - release a managed action from a &drm_device
+ * @dev: DRM device
+ * @action: function which would be called when @dev is released
+ * @data: opaque pointer, passed to @action
+ *
+ * This function calls the @action previously added by drmm_add_action()
+ * immediately.
+ * The @action is removed from the list of cleanup actions for @dev,
+ * which means that it won't be called in the final drm_dev_put().
+ */
+void drmm_release_action(struct drm_device *dev,
+                        drmres_release_t action,
+                        void *data)
+{
+       struct drmres *dr_match = NULL, *dr;
+       unsigned long flags;
+
+       spin_lock_irqsave(&dev->managed.lock, flags);
+       list_for_each_entry_reverse(dr, &dev->managed.resources, node.entry) {
+               if (dr->node.release == action) {
+                       if (!data || (data && *(void **)dr->data == data)) {
+                               dr_match = dr;
+                               del_dr(dev, dr_match);
+                               break;
+                       }
+               }
+       }
+       spin_unlock_irqrestore(&dev->managed.lock, flags);
+
+       if (WARN_ON(!dr_match))
+               return;
+
+       action(dev, data);
+
+       free_dr(dr_match);
+}
+EXPORT_SYMBOL(drmm_release_action);
+
 /**
  * drmm_kmalloc - &drm_device managed kmalloc()
  * @dev: DRM device
index 893f52ee492610e11ebb5ded63d1cc7683e81b31..c4f88c3a93b7a98baac9b7deed397b08a8f6dfca 100644 (file)
@@ -2752,3 +2752,25 @@ bool drm_mode_is_420(const struct drm_display_info *display,
                drm_mode_is_420_also(display, mode);
 }
 EXPORT_SYMBOL(drm_mode_is_420);
+
+/**
+ * drm_set_preferred_mode - Sets the preferred mode of a connector
+ * @connector: connector whose mode list should be processed
+ * @hpref: horizontal resolution of preferred mode
+ * @vpref: vertical resolution of preferred mode
+ *
+ * Marks a mode as preferred if it matches the resolution specified by @hpref
+ * and @vpref.
+ */
+void drm_set_preferred_mode(struct drm_connector *connector,
+                           int hpref, int vpref)
+{
+       struct drm_display_mode *mode;
+
+       list_for_each_entry(mode, &connector->probed_modes, head) {
+               if (mode->hdisplay == hpref &&
+                   mode->vdisplay == vpref)
+                       mode->type |= DRM_MODE_TYPE_PREFERRED;
+       }
+}
+EXPORT_SYMBOL(drm_set_preferred_mode);
index 3d92f66e550c3885d1639c9450487228758afd76..aa93129c3397e40c67027d2098d8e6dd1a875932 100644 (file)
@@ -117,6 +117,12 @@ static const struct drm_dmi_panel_orientation_data lcd1080x1920_leftside_up = {
        .orientation = DRM_MODE_PANEL_ORIENTATION_LEFT_UP,
 };
 
+static const struct drm_dmi_panel_orientation_data lcd1080x1920_rightside_up = {
+       .width = 1080,
+       .height = 1920,
+       .orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP,
+};
+
 static const struct drm_dmi_panel_orientation_data lcd1200x1920_rightside_up = {
        .width = 1200,
        .height = 1920,
@@ -279,6 +285,12 @@ static const struct dmi_system_id orientation_data[] = {
                  DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "G1618-03")
                },
                .driver_data = (void *)&lcd720x1280_rightside_up,
+       }, {    /* GPD Win Mini */
+               .matches = {
+                 DMI_EXACT_MATCH(DMI_SYS_VENDOR, "GPD"),
+                 DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "G1617-01")
+               },
+               .driver_data = (void *)&lcd1080x1920_rightside_up,
        }, {    /* I.T.Works TW891 */
                .matches = {
                  DMI_EXACT_MATCH(DMI_SYS_VENDOR, "To be filled by O.E.M."),
index 3f479483d7d80f21febcda087570bcc6af2fd34c..d1e1ade66f81cb3bd90e91a3dbcd8d0d9acd60de 100644 (file)
@@ -1100,42 +1100,6 @@ enum drm_mode_status drm_crtc_helper_mode_valid_fixed(struct drm_crtc *crtc,
 }
 EXPORT_SYMBOL(drm_crtc_helper_mode_valid_fixed);
 
-/**
- * drm_connector_helper_get_modes_from_ddc - Updates the connector's EDID
- *                                           property from the connector's
- *                                           DDC channel
- * @connector: The connector
- *
- * Returns:
- * The number of detected display modes.
- *
- * Uses a connector's DDC channel to retrieve EDID data and update the
- * connector's EDID property and display modes. Drivers can use this
- * function to implement struct &drm_connector_helper_funcs.get_modes
- * for connectors with a DDC channel.
- */
-int drm_connector_helper_get_modes_from_ddc(struct drm_connector *connector)
-{
-       struct edid *edid;
-       int count = 0;
-
-       if (!connector->ddc)
-               return 0;
-
-       edid = drm_get_edid(connector, connector->ddc);
-
-       // clears property if EDID is NULL
-       drm_connector_update_edid_property(connector, edid);
-
-       if (edid) {
-               count = drm_add_edid_modes(connector, edid);
-               kfree(edid);
-       }
-
-       return count;
-}
-EXPORT_SYMBOL(drm_connector_helper_get_modes_from_ddc);
-
 /**
  * drm_connector_helper_get_modes_fixed - Duplicates a display mode for a connector
  * @connector: the connector
index f957552c6c50785734521a38a79c95858fb0ef3f..207aa3f660b030870b722317fe24f575493c2cc7 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/i2c-algo-bit.h>
 #include <linux/i2c.h>
 
-#include <drm/drm_edid.h>
 #include <drm/drm_framebuffer.h>
 
 struct hibmc_connector {
index 8c6d2ea2a4729f4c36ffcb34f073b6c03d260901..94e2c573a7aff35f3f19597d92c26e23d43ae631 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/io.h>
 
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_edid.h>
 #include <drm/drm_probe_helper.h>
 #include <drm/drm_print.h>
 #include <drm/drm_simple_kms_helper.h>
index 9227f8146a583fc45a5a391ac4a9be48bb3b8a60..a6b0aaf30cbe5fa2cb61d506c8deb95b8b2f4416 100644 (file)
@@ -65,8 +65,6 @@ static const struct ttm_place sys_placement_flags = {
 static struct ttm_placement i915_sys_placement = {
        .num_placement = 1,
        .placement = &sys_placement_flags,
-       .num_busy_placement = 1,
-       .busy_placement = &sys_placement_flags,
 };
 
 /**
@@ -157,32 +155,28 @@ i915_ttm_place_from_region(const struct intel_memory_region *mr,
 
 static void
 i915_ttm_placement_from_obj(const struct drm_i915_gem_object *obj,
-                           struct ttm_place *requested,
-                           struct ttm_place *busy,
+                           struct ttm_place *places,
                            struct ttm_placement *placement)
 {
        unsigned int num_allowed = obj->mm.n_placements;
        unsigned int flags = obj->flags;
        unsigned int i;
 
-       placement->num_placement = 1;
+       places[0].flags |= TTM_PL_FLAG_DESIRED;
        i915_ttm_place_from_region(num_allowed ? obj->mm.placements[0] :
-                                  obj->mm.region, requested, obj->bo_offset,
+                                  obj->mm.region, &places[0], obj->bo_offset,
                                   obj->base.size, flags);
 
        /* Cache this on object? */
-       placement->num_busy_placement = num_allowed;
-       for (i = 0; i < placement->num_busy_placement; ++i)
-               i915_ttm_place_from_region(obj->mm.placements[i], busy + i,
-                                          obj->bo_offset, obj->base.size, flags);
-
-       if (num_allowed == 0) {
-               *busy = *requested;
-               placement->num_busy_placement = 1;
+       for (i = 0; i < num_allowed; ++i) {
+               i915_ttm_place_from_region(obj->mm.placements[i],
+                                          &places[i + 1], obj->bo_offset,
+                                          obj->base.size, flags);
+               places[i + 1].flags |= TTM_PL_FLAG_FALLBACK;
        }
 
-       placement->placement = requested;
-       placement->busy_placement = busy;
+       placement->num_placement = num_allowed + 1;
+       placement->placement = places;
 }
 
 static int i915_ttm_tt_shmem_populate(struct ttm_device *bdev,
@@ -789,7 +783,8 @@ static int __i915_ttm_get_pages(struct drm_i915_gem_object *obj,
        int ret;
 
        /* First try only the requested placement. No eviction. */
-       real_num_busy = fetch_and_zero(&placement->num_busy_placement);
+       real_num_busy = placement->num_placement;
+       placement->num_placement = 1;
        ret = ttm_bo_validate(bo, placement, &ctx);
        if (ret) {
                ret = i915_ttm_err_to_gem(ret);
@@ -805,7 +800,7 @@ static int __i915_ttm_get_pages(struct drm_i915_gem_object *obj,
                 * If the initial attempt fails, allow all accepted placements,
                 * evicting if necessary.
                 */
-               placement->num_busy_placement = real_num_busy;
+               placement->num_placement = real_num_busy;
                ret = ttm_bo_validate(bo, placement, &ctx);
                if (ret)
                        return i915_ttm_err_to_gem(ret);
@@ -839,7 +834,7 @@ static int __i915_ttm_get_pages(struct drm_i915_gem_object *obj,
 
 static int i915_ttm_get_pages(struct drm_i915_gem_object *obj)
 {
-       struct ttm_place requested, busy[I915_TTM_MAX_PLACEMENTS];
+       struct ttm_place places[I915_TTM_MAX_PLACEMENTS + 1];
        struct ttm_placement placement;
 
        /* restricted by sg_alloc_table */
@@ -849,7 +844,7 @@ static int i915_ttm_get_pages(struct drm_i915_gem_object *obj)
        GEM_BUG_ON(obj->mm.n_placements > I915_TTM_MAX_PLACEMENTS);
 
        /* Move to the requested placement. */
-       i915_ttm_placement_from_obj(obj, &requested, busy, &placement);
+       i915_ttm_placement_from_obj(obj, places, &placement);
 
        return __i915_ttm_get_pages(obj, &placement);
 }
@@ -879,9 +874,7 @@ static int __i915_ttm_migrate(struct drm_i915_gem_object *obj,
        i915_ttm_place_from_region(mr, &requested, obj->bo_offset,
                                   obj->base.size, flags);
        placement.num_placement = 1;
-       placement.num_busy_placement = 1;
        placement.placement = &requested;
-       placement.busy_placement = &requested;
 
        ret = __i915_ttm_get_pages(obj, &placement);
        if (ret)
index b440e0cdc05794f566ea2cecc25d8834be45ff2b..3db117c5edd9161b83d85dd1d195856902de2648 100644 (file)
@@ -11,7 +11,6 @@ config DRM_INGENIC
        select DRM_GEM_DMA_HELPER
        select REGMAP
        select REGMAP_MMIO
-       select VT_HW_CONSOLE_BINDING if FRAMEBUFFER_CONSOLE
        help
          Choose this option for DRM support for the Ingenic SoCs.
 
index 4f9736e5f929beecb84d2abee435ff64baa1bb25..7ea244d876ca63ccd1a91ba934d6f8871a3ac6ad 100644 (file)
@@ -75,29 +75,34 @@ int lima_heap_alloc(struct lima_bo *bo, struct lima_vm *vm)
        } else {
                bo->base.sgt = kmalloc(sizeof(*bo->base.sgt), GFP_KERNEL);
                if (!bo->base.sgt) {
-                       sg_free_table(&sgt);
-                       return -ENOMEM;
+                       ret = -ENOMEM;
+                       goto err_out0;
                }
        }
 
        ret = dma_map_sgtable(dev, &sgt, DMA_BIDIRECTIONAL, 0);
-       if (ret) {
-               sg_free_table(&sgt);
-               kfree(bo->base.sgt);
-               bo->base.sgt = NULL;
-               return ret;
-       }
+       if (ret)
+               goto err_out1;
 
        *bo->base.sgt = sgt;
 
        if (vm) {
                ret = lima_vm_map_bo(vm, bo, old_size >> PAGE_SHIFT);
                if (ret)
-                       return ret;
+                       goto err_out2;
        }
 
        bo->heap_size = new_size;
        return 0;
+
+err_out2:
+       dma_unmap_sgtable(dev, &sgt, DMA_BIDIRECTIONAL, 0);
+err_out1:
+       kfree(bo->base.sgt);
+       bo->base.sgt = NULL;
+err_out0:
+       sg_free_table(&sgt);
+       return ret;
 }
 
 int lima_gem_create_handle(struct drm_device *dev, struct drm_file *file,
index 89ccc0c431690f7d458e999b464924b0af1b8107..d8ff60b46abe6e6f46d2b04935c2fc11ced6beb0 100644 (file)
@@ -184,7 +184,7 @@ static int lsdc_get_dedicated_vram(struct lsdc_device *ldev,
        drm_info(ddev, "Dedicated vram start: 0x%llx, size: %uMiB\n",
                 (u64)base, (u32)(size >> 20));
 
-       return 0;
+       return (size > SZ_1M) ? 0 : -ENODEV;
 }
 
 static struct lsdc_device *
index bf79dc55afa49c1dc1dbfe70fa35936895921cbb..465f622ac05db72731dd9d33ead7d3fc414d17ff 100644 (file)
@@ -54,7 +54,6 @@ static void lsdc_bo_set_placement(struct lsdc_bo *lbo, u32 domain)
                pflags |= TTM_PL_FLAG_TOPDOWN;
 
        lbo->placement.placement = lbo->placements;
-       lbo->placement.busy_placement = lbo->placements;
 
        if (domain & LSDC_GEM_DOMAIN_VRAM) {
                lbo->placements[c].mem_type = TTM_PL_VRAM;
@@ -77,7 +76,6 @@ static void lsdc_bo_set_placement(struct lsdc_bo *lbo, u32 domain)
        }
 
        lbo->placement.num_placement = c;
-       lbo->placement.num_busy_placement = c;
 
        for (i = 0; i < c; ++i) {
                lbo->placements[i].fpfn = 0;
index 4f3d68e11bc123a1bf35661446ea8ba974b9a159..907460b69d4f527481de1ec3dfc277b233a811f7 100644 (file)
@@ -11,7 +11,6 @@ config DRM_MCDE
        select DRM_PANEL_BRIDGE
        select DRM_KMS_HELPER
        select DRM_GEM_DMA_HELPER
-       select VT_HW_CONSOLE_BINDING if FRAMEBUFFER_CONSOLE
        help
          Choose this option for DRM support for the ST-Ericsson MCDE
          Multi-Channel Display Engine.
index 2fb18b782b05366fd549ac3fc6d9ede24364ed22..54fce00e2136e08de31680ac8d2f416ca1b4b281 100644 (file)
@@ -146,14 +146,13 @@ int mgag200_device_preinit(struct mga_device *mdev)
        }
        mdev->vram_res = res;
 
-       /* Don't fail on errors, but performance might be reduced. */
-       devm_arch_io_reserve_memtype_wc(dev->dev, res->start, resource_size(res));
-       devm_arch_phys_wc_add(dev->dev, res->start, resource_size(res));
-
-       mdev->vram = devm_ioremap(dev->dev, res->start, resource_size(res));
+       mdev->vram = devm_ioremap_wc(dev->dev, res->start, resource_size(res));
        if (!mdev->vram)
                return -ENOMEM;
 
+       /* Don't fail on errors, but performance might be reduced. */
+       devm_arch_phys_wc_add(dev->dev, res->start, resource_size(res));
+
        return 0;
 }
 
index 0f0d59938c3a07912c3f1cb2a0c3b78f393617aa..0eb769dd76ce0a3019a5b0ae75618b61ba0bb4c5 100644 (file)
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_damage_helper.h>
+#include <drm/drm_edid.h>
 #include <drm/drm_format_helper.h>
 #include <drm/drm_fourcc.h>
 #include <drm/drm_framebuffer.h>
 #include <drm/drm_gem_atomic_helper.h>
 #include <drm/drm_gem_framebuffer_helper.h>
 #include <drm/drm_print.h>
-#include <drm/drm_probe_helper.h>
 
 #include "mgag200_drv.h"
 
@@ -717,17 +717,23 @@ void mgag200_crtc_atomic_destroy_state(struct drm_crtc *crtc, struct drm_crtc_st
 int mgag200_vga_connector_helper_get_modes(struct drm_connector *connector)
 {
        struct mga_device *mdev = to_mga_device(connector->dev);
-       int ret;
+       const struct drm_edid *drm_edid;
+       int count;
 
        /*
         * Protect access to I/O registers from concurrent modesetting
         * by acquiring the I/O-register lock.
         */
        mutex_lock(&mdev->rmmio_lock);
-       ret = drm_connector_helper_get_modes_from_ddc(connector);
+
+       drm_edid = drm_edid_read(connector);
+       drm_edid_connector_update(connector, drm_edid);
+       count = drm_edid_connector_add_modes(connector);
+       drm_edid_free(drm_edid);
+
        mutex_unlock(&mdev->rmmio_lock);
 
-       return ret;
+       return count;
 }
 
 /*
index d37d599aec273b41b7ec54eb04b55ee86770d1a5..c8e1bbebdffe24934c1feaf4bdd3473cd278479e 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/of_irq.h>
 #include <linux/delay.h>
 #include <drm/display/drm_dp_aux_bus.h>
+#include <drm/drm_edid.h>
 
 #include "msm_drv.h"
 #include "msm_kms.h"
index a34917b048f96f4c755c6fe605ab7e92c674e28a..4310ad71870b109697cc07047cbc29f4a631272f 100644 (file)
@@ -449,7 +449,7 @@ nv_crtc_mode_set_vga(struct drm_crtc *crtc, struct drm_display_mode *mode)
        regp->Attribute[NV_CIO_AR_CSEL_INDEX] = 0x00;
 }
 
-/**
+/*
  * Sets up registers for the given mode/adjusted_mode pair.
  *
  * The clocks, CRTCs and outputs attached to this CRTC must be off.
@@ -625,7 +625,7 @@ nv_crtc_swap_fbs(struct drm_crtc *crtc, struct drm_framebuffer *old_fb)
        return ret;
 }
 
-/**
+/*
  * Sets up registers for the given mode/adjusted_mode pair.
  *
  * The clocks, CRTCs and outputs attached to this CRTC must be off.
index 5f490fbf18772137c8048ce03604a8849dd06759..83355dbc15eeb3fe8633bf72114db77cc97f3a27 100644 (file)
@@ -32,6 +32,7 @@
 
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_edid.h>
 #include <drm/drm_vblank.h>
 #include "nouveau_connector.h"
 
index 00cc7d1abaa39b7330f4ade2551d881f649cd255..56dcd25db1ce2c79b8a6be7c0ea684838e74e655 100644 (file)
@@ -404,27 +404,6 @@ nouveau_bo_new(struct nouveau_cli *cli, u64 size, int align,
        return 0;
 }
 
-static void
-set_placement_list(struct ttm_place *pl, unsigned *n, uint32_t domain)
-{
-       *n = 0;
-
-       if (domain & NOUVEAU_GEM_DOMAIN_VRAM) {
-               pl[*n].mem_type = TTM_PL_VRAM;
-               pl[*n].flags = 0;
-               (*n)++;
-       }
-       if (domain & NOUVEAU_GEM_DOMAIN_GART) {
-               pl[*n].mem_type = TTM_PL_TT;
-               pl[*n].flags = 0;
-               (*n)++;
-       }
-       if (domain & NOUVEAU_GEM_DOMAIN_CPU) {
-               pl[*n].mem_type = TTM_PL_SYSTEM;
-               pl[(*n)++].flags = 0;
-       }
-}
-
 static void
 set_placement_range(struct nouveau_bo *nvbo, uint32_t domain)
 {
@@ -452,10 +431,6 @@ set_placement_range(struct nouveau_bo *nvbo, uint32_t domain)
                        nvbo->placements[i].fpfn = fpfn;
                        nvbo->placements[i].lpfn = lpfn;
                }
-               for (i = 0; i < nvbo->placement.num_busy_placement; ++i) {
-                       nvbo->busy_placements[i].fpfn = fpfn;
-                       nvbo->busy_placements[i].lpfn = lpfn;
-               }
        }
 }
 
@@ -463,15 +438,32 @@ void
 nouveau_bo_placement_set(struct nouveau_bo *nvbo, uint32_t domain,
                         uint32_t busy)
 {
-       struct ttm_placement *pl = &nvbo->placement;
+       unsigned int *n = &nvbo->placement.num_placement;
+       struct ttm_place *pl = nvbo->placements;
 
-       pl->placement = nvbo->placements;
-       set_placement_list(nvbo->placements, &pl->num_placement, domain);
+       domain |= busy;
 
-       pl->busy_placement = nvbo->busy_placements;
-       set_placement_list(nvbo->busy_placements, &pl->num_busy_placement,
-                          domain | busy);
+       *n = 0;
+       if (domain & NOUVEAU_GEM_DOMAIN_VRAM) {
+               pl[*n].mem_type = TTM_PL_VRAM;
+               pl[*n].flags = busy & NOUVEAU_GEM_DOMAIN_VRAM ?
+                       TTM_PL_FLAG_FALLBACK : 0;
+               (*n)++;
+       }
+       if (domain & NOUVEAU_GEM_DOMAIN_GART) {
+               pl[*n].mem_type = TTM_PL_TT;
+               pl[*n].flags = busy & NOUVEAU_GEM_DOMAIN_GART ?
+                       TTM_PL_FLAG_FALLBACK : 0;
+               (*n)++;
+       }
+       if (domain & NOUVEAU_GEM_DOMAIN_CPU) {
+               pl[*n].mem_type = TTM_PL_SYSTEM;
+               pl[*n].flags = busy & NOUVEAU_GEM_DOMAIN_CPU ?
+                       TTM_PL_FLAG_FALLBACK : 0;
+               (*n)++;
+       }
 
+       nvbo->placement.placement = nvbo->placements;
        set_placement_range(nvbo, domain);
 }
 
@@ -1314,11 +1306,6 @@ vm_fault_t nouveau_ttm_fault_reserve_notify(struct ttm_buffer_object *bo)
                        nvbo->placements[i].lpfn = mappable;
                }
 
-               for (i = 0; i < nvbo->placement.num_busy_placement; ++i) {
-                       nvbo->busy_placements[i].fpfn = 0;
-                       nvbo->busy_placements[i].lpfn = mappable;
-               }
-
                nouveau_bo_placement_set(nvbo, NOUVEAU_GEM_DOMAIN_VRAM, 0);
        }
 
index 70c551921a9ee917ffda2633f2b300c9ada2c4e3..e9dfab6a81560e5f68371363ce676008f1b8b901 100644 (file)
@@ -15,7 +15,6 @@ struct nouveau_bo {
        struct ttm_placement placement;
        u32 valid_domains;
        struct ttm_place placements[3];
-       struct ttm_place busy_placements[3];
        bool force_coherent;
        struct ttm_bo_kmap_obj kmap;
        struct list_head head;
index a2df4918340cb8b4653554bd8e3050782de17763..0608cabed058e3e43f6d344c21609ef79f30b15c 100644 (file)
@@ -35,7 +35,6 @@
 
 #include <drm/display/drm_dp_helper.h>
 #include <drm/drm_crtc.h>
-#include <drm/drm_edid.h>
 #include <drm/drm_encoder.h>
 #include <drm/drm_util.h>
 
@@ -44,6 +43,7 @@
 
 struct nvkm_i2c_port;
 struct dcb_output;
+struct edid;
 
 #ifdef CONFIG_DRM_NOUVEAU_BACKLIGHT
 struct nouveau_backlight {
index adf01ca9e035d50cea5537dac985dbdd42324224..2af3615c5205cd58b6afcaf91eb2263a4cca1e61 100644 (file)
@@ -1,4 +1,4 @@
-/**
+/*
  * \file mga_ioc32.c
  *
  * 32-bit ioctl compatibility routines for the MGA DRM.
@@ -38,7 +38,7 @@
 
 #include "nouveau_ioctl.h"
 
-/**
+/*
  * Called whenever a 32-bit process running under a 64-bit kernel
  * performs an ioctl on /dev/dri/card<n>.
  *
index 5d3190c05250a959019ee43e919a666e4082a753..6daeb7f0b09b63fcd8d6f0149c18b4dfd624672f 100644 (file)
@@ -452,13 +452,12 @@ nvif_outp_edid_get(struct nvif_outp *outp, u8 **pedid)
        if (ret)
                goto done;
 
-       *pedid = kmalloc(args->size, GFP_KERNEL);
+       *pedid = kmemdup(args->data, args->size, GFP_KERNEL);
        if (!*pedid) {
                ret = -ENOMEM;
                goto done;
        }
 
-       memcpy(*pedid, args->data, args->size);
        ret = args->size;
 done:
        kfree(args);
index c494a1ff2d5727cef5ce01131379462be4c4a16e..986e8d547c94246a5f7bd058e6ddf555ffc651a4 100644 (file)
@@ -1040,7 +1040,7 @@ gf100_gr_zbc_init(struct gf100_gr *gr)
        }
 }
 
-/**
+/*
  * Wait until GR goes idle. GR is considered idle if it is disabled by the
  * MC (0x200) register, or GR is not busy and a context switch is not in
  * progress.
index 1420794038642549363453d1649816fce16f6e34..b54f044c4483b1f1cd9e19fd285f0c47809bb581 100644 (file)
@@ -575,7 +575,7 @@ init_tmds_reg(struct nvbios_init *init, u8 tmds)
  * init opcode handlers
  *****************************************************************************/
 
-/**
+/*
  * init_reserved - stub for various unknown/unused single-byte opcodes
  *
  */
@@ -602,7 +602,7 @@ init_reserved(struct nvbios_init *init)
        init->offset += length;
 }
 
-/**
+/*
  * INIT_DONE - opcode 0x71
  *
  */
@@ -613,7 +613,7 @@ init_done(struct nvbios_init *init)
        init->offset = 0x0000;
 }
 
-/**
+/*
  * INIT_IO_RESTRICT_PROG - opcode 0x32
  *
  */
@@ -650,7 +650,7 @@ init_io_restrict_prog(struct nvbios_init *init)
        trace("}]\n");
 }
 
-/**
+/*
  * INIT_REPEAT - opcode 0x33
  *
  */
@@ -676,7 +676,7 @@ init_repeat(struct nvbios_init *init)
        init->repeat = repeat;
 }
 
-/**
+/*
  * INIT_IO_RESTRICT_PLL - opcode 0x34
  *
  */
@@ -716,7 +716,7 @@ init_io_restrict_pll(struct nvbios_init *init)
        trace("}]\n");
 }
 
-/**
+/*
  * INIT_END_REPEAT - opcode 0x36
  *
  */
@@ -732,7 +732,7 @@ init_end_repeat(struct nvbios_init *init)
        }
 }
 
-/**
+/*
  * INIT_COPY - opcode 0x37
  *
  */
@@ -759,7 +759,7 @@ init_copy(struct nvbios_init *init)
        init_wrvgai(init, port, index, data);
 }
 
-/**
+/*
  * INIT_NOT - opcode 0x38
  *
  */
@@ -771,7 +771,7 @@ init_not(struct nvbios_init *init)
        init_exec_inv(init);
 }
 
-/**
+/*
  * INIT_IO_FLAG_CONDITION - opcode 0x39
  *
  */
@@ -788,7 +788,7 @@ init_io_flag_condition(struct nvbios_init *init)
                init_exec_set(init, false);
 }
 
-/**
+/*
  * INIT_GENERIC_CONDITION - opcode 0x3a
  *
  */
@@ -840,7 +840,7 @@ init_generic_condition(struct nvbios_init *init)
        }
 }
 
-/**
+/*
  * INIT_IO_MASK_OR - opcode 0x3b
  *
  */
@@ -859,7 +859,7 @@ init_io_mask_or(struct nvbios_init *init)
        init_wrvgai(init, 0x03d4, index, data &= ~(1 << or));
 }
 
-/**
+/*
  * INIT_IO_OR - opcode 0x3c
  *
  */
@@ -878,7 +878,7 @@ init_io_or(struct nvbios_init *init)
        init_wrvgai(init, 0x03d4, index, data | (1 << or));
 }
 
-/**
+/*
  * INIT_ANDN_REG - opcode 0x47
  *
  */
@@ -895,7 +895,7 @@ init_andn_reg(struct nvbios_init *init)
        init_mask(init, reg, mask, 0);
 }
 
-/**
+/*
  * INIT_OR_REG - opcode 0x48
  *
  */
@@ -912,7 +912,7 @@ init_or_reg(struct nvbios_init *init)
        init_mask(init, reg, 0, mask);
 }
 
-/**
+/*
  * INIT_INDEX_ADDRESS_LATCHED - opcode 0x49
  *
  */
@@ -942,7 +942,7 @@ init_idx_addr_latched(struct nvbios_init *init)
        }
 }
 
-/**
+/*
  * INIT_IO_RESTRICT_PLL2 - opcode 0x4a
  *
  */
@@ -977,7 +977,7 @@ init_io_restrict_pll2(struct nvbios_init *init)
        trace("}]\n");
 }
 
-/**
+/*
  * INIT_PLL2 - opcode 0x4b
  *
  */
@@ -994,7 +994,7 @@ init_pll2(struct nvbios_init *init)
        init_prog_pll(init, reg, freq);
 }
 
-/**
+/*
  * INIT_I2C_BYTE - opcode 0x4c
  *
  */
@@ -1025,7 +1025,7 @@ init_i2c_byte(struct nvbios_init *init)
        }
 }
 
-/**
+/*
  * INIT_ZM_I2C_BYTE - opcode 0x4d
  *
  */
@@ -1051,7 +1051,7 @@ init_zm_i2c_byte(struct nvbios_init *init)
        }
 }
 
-/**
+/*
  * INIT_ZM_I2C - opcode 0x4e
  *
  */
@@ -1085,7 +1085,7 @@ init_zm_i2c(struct nvbios_init *init)
        }
 }
 
-/**
+/*
  * INIT_TMDS - opcode 0x4f
  *
  */
@@ -1111,7 +1111,7 @@ init_tmds(struct nvbios_init *init)
        init_wr32(init, reg + 0, addr);
 }
 
-/**
+/*
  * INIT_ZM_TMDS_GROUP - opcode 0x50
  *
  */
@@ -1138,7 +1138,7 @@ init_zm_tmds_group(struct nvbios_init *init)
        }
 }
 
-/**
+/*
  * INIT_CR_INDEX_ADDRESS_LATCHED - opcode 0x51
  *
  */
@@ -1168,7 +1168,7 @@ init_cr_idx_adr_latch(struct nvbios_init *init)
        init_wrvgai(init, 0x03d4, addr0, save0);
 }
 
-/**
+/*
  * INIT_CR - opcode 0x52
  *
  */
@@ -1188,7 +1188,7 @@ init_cr(struct nvbios_init *init)
        init_wrvgai(init, 0x03d4, addr, val | data);
 }
 
-/**
+/*
  * INIT_ZM_CR - opcode 0x53
  *
  */
@@ -1205,7 +1205,7 @@ init_zm_cr(struct nvbios_init *init)
        init_wrvgai(init, 0x03d4, addr, data);
 }
 
-/**
+/*
  * INIT_ZM_CR_GROUP - opcode 0x54
  *
  */
@@ -1229,7 +1229,7 @@ init_zm_cr_group(struct nvbios_init *init)
        }
 }
 
-/**
+/*
  * INIT_CONDITION_TIME - opcode 0x56
  *
  */
@@ -1256,7 +1256,7 @@ init_condition_time(struct nvbios_init *init)
        init_exec_set(init, false);
 }
 
-/**
+/*
  * INIT_LTIME - opcode 0x57
  *
  */
@@ -1273,7 +1273,7 @@ init_ltime(struct nvbios_init *init)
                mdelay(msec);
 }
 
-/**
+/*
  * INIT_ZM_REG_SEQUENCE - opcode 0x58
  *
  */
@@ -1298,7 +1298,7 @@ init_zm_reg_sequence(struct nvbios_init *init)
        }
 }
 
-/**
+/*
  * INIT_PLL_INDIRECT - opcode 0x59
  *
  */
@@ -1317,7 +1317,7 @@ init_pll_indirect(struct nvbios_init *init)
        init_prog_pll(init, reg, freq);
 }
 
-/**
+/*
  * INIT_ZM_REG_INDIRECT - opcode 0x5a
  *
  */
@@ -1336,7 +1336,7 @@ init_zm_reg_indirect(struct nvbios_init *init)
        init_wr32(init, addr, data);
 }
 
-/**
+/*
  * INIT_SUB_DIRECT - opcode 0x5b
  *
  */
@@ -1362,7 +1362,7 @@ init_sub_direct(struct nvbios_init *init)
        init->offset += 3;
 }
 
-/**
+/*
  * INIT_JUMP - opcode 0x5c
  *
  */
@@ -1380,7 +1380,7 @@ init_jump(struct nvbios_init *init)
                init->offset += 3;
 }
 
-/**
+/*
  * INIT_I2C_IF - opcode 0x5e
  *
  */
@@ -1407,7 +1407,7 @@ init_i2c_if(struct nvbios_init *init)
        init_exec_force(init, false);
 }
 
-/**
+/*
  * INIT_COPY_NV_REG - opcode 0x5f
  *
  */
@@ -1433,7 +1433,7 @@ init_copy_nv_reg(struct nvbios_init *init)
        init_mask(init, dreg, ~dmask, (data & smask) ^ sxor);
 }
 
-/**
+/*
  * INIT_ZM_INDEX_IO - opcode 0x62
  *
  */
@@ -1451,7 +1451,7 @@ init_zm_index_io(struct nvbios_init *init)
        init_wrvgai(init, port, index, data);
 }
 
-/**
+/*
  * INIT_COMPUTE_MEM - opcode 0x63
  *
  */
@@ -1469,7 +1469,7 @@ init_compute_mem(struct nvbios_init *init)
        init_exec_force(init, false);
 }
 
-/**
+/*
  * INIT_RESET - opcode 0x65
  *
  */
@@ -1496,7 +1496,7 @@ init_reset(struct nvbios_init *init)
        init_exec_force(init, false);
 }
 
-/**
+/*
  * INIT_CONFIGURE_MEM - opcode 0x66
  *
  */
@@ -1555,7 +1555,7 @@ init_configure_mem(struct nvbios_init *init)
        init_exec_force(init, false);
 }
 
-/**
+/*
  * INIT_CONFIGURE_CLK - opcode 0x67
  *
  */
@@ -1589,7 +1589,7 @@ init_configure_clk(struct nvbios_init *init)
        init_exec_force(init, false);
 }
 
-/**
+/*
  * INIT_CONFIGURE_PREINIT - opcode 0x68
  *
  */
@@ -1615,7 +1615,7 @@ init_configure_preinit(struct nvbios_init *init)
        init_exec_force(init, false);
 }
 
-/**
+/*
  * INIT_IO - opcode 0x69
  *
  */
@@ -1655,7 +1655,7 @@ init_io(struct nvbios_init *init)
        init_wrport(init, port, data | value);
 }
 
-/**
+/*
  * INIT_SUB - opcode 0x6b
  *
  */
@@ -1682,7 +1682,7 @@ init_sub(struct nvbios_init *init)
        init->offset += 2;
 }
 
-/**
+/*
  * INIT_RAM_CONDITION - opcode 0x6d
  *
  */
@@ -1701,7 +1701,7 @@ init_ram_condition(struct nvbios_init *init)
                init_exec_set(init, false);
 }
 
-/**
+/*
  * INIT_NV_REG - opcode 0x6e
  *
  */
@@ -1719,7 +1719,7 @@ init_nv_reg(struct nvbios_init *init)
        init_mask(init, reg, ~mask, data);
 }
 
-/**
+/*
  * INIT_MACRO - opcode 0x6f
  *
  */
@@ -1743,7 +1743,7 @@ init_macro(struct nvbios_init *init)
        init->offset += 2;
 }
 
-/**
+/*
  * INIT_RESUME - opcode 0x72
  *
  */
@@ -1755,7 +1755,7 @@ init_resume(struct nvbios_init *init)
        init_exec_set(init, true);
 }
 
-/**
+/*
  * INIT_STRAP_CONDITION - opcode 0x73
  *
  */
@@ -1773,7 +1773,7 @@ init_strap_condition(struct nvbios_init *init)
                init_exec_set(init, false);
 }
 
-/**
+/*
  * INIT_TIME - opcode 0x74
  *
  */
@@ -1794,7 +1794,7 @@ init_time(struct nvbios_init *init)
        }
 }
 
-/**
+/*
  * INIT_CONDITION - opcode 0x75
  *
  */
@@ -1811,7 +1811,7 @@ init_condition(struct nvbios_init *init)
                init_exec_set(init, false);
 }
 
-/**
+/*
  * INIT_IO_CONDITION - opcode 0x76
  *
  */
@@ -1828,7 +1828,7 @@ init_io_condition(struct nvbios_init *init)
                init_exec_set(init, false);
 }
 
-/**
+/*
  * INIT_ZM_REG16 - opcode 0x77
  *
  */
@@ -1845,7 +1845,7 @@ init_zm_reg16(struct nvbios_init *init)
        init_wr32(init, addr, data);
 }
 
-/**
+/*
  * INIT_INDEX_IO - opcode 0x78
  *
  */
@@ -1867,7 +1867,7 @@ init_index_io(struct nvbios_init *init)
        init_wrvgai(init, port, index, data | value);
 }
 
-/**
+/*
  * INIT_PLL - opcode 0x79
  *
  */
@@ -1884,7 +1884,7 @@ init_pll(struct nvbios_init *init)
        init_prog_pll(init, reg, freq);
 }
 
-/**
+/*
  * INIT_ZM_REG - opcode 0x7a
  *
  */
@@ -1904,7 +1904,7 @@ init_zm_reg(struct nvbios_init *init)
        init_wr32(init, addr, data);
 }
 
-/**
+/*
  * INIT_RAM_RESTRICT_PLL - opcde 0x87
  *
  */
@@ -1934,7 +1934,7 @@ init_ram_restrict_pll(struct nvbios_init *init)
        }
 }
 
-/**
+/*
  * INIT_RESET_BEGUN - opcode 0x8c
  *
  */
@@ -1945,7 +1945,7 @@ init_reset_begun(struct nvbios_init *init)
        init->offset += 1;
 }
 
-/**
+/*
  * INIT_RESET_END - opcode 0x8d
  *
  */
@@ -1956,7 +1956,7 @@ init_reset_end(struct nvbios_init *init)
        init->offset += 1;
 }
 
-/**
+/*
  * INIT_GPIO - opcode 0x8e
  *
  */
@@ -1972,7 +1972,7 @@ init_gpio(struct nvbios_init *init)
                nvkm_gpio_reset(gpio, DCB_GPIO_UNUSED);
 }
 
-/**
+/*
  * INIT_RAM_RESTRICT_ZM_GROUP - opcode 0x8f
  *
  */
@@ -2010,7 +2010,7 @@ init_ram_restrict_zm_reg_group(struct nvbios_init *init)
        }
 }
 
-/**
+/*
  * INIT_COPY_ZM_REG - opcode 0x90
  *
  */
@@ -2027,7 +2027,7 @@ init_copy_zm_reg(struct nvbios_init *init)
        init_wr32(init, dreg, init_rd32(init, sreg));
 }
 
-/**
+/*
  * INIT_ZM_REG_GROUP - opcode 0x91
  *
  */
@@ -2049,7 +2049,7 @@ init_zm_reg_group(struct nvbios_init *init)
        }
 }
 
-/**
+/*
  * INIT_XLAT - opcode 0x96
  *
  */
@@ -2077,7 +2077,7 @@ init_xlat(struct nvbios_init *init)
        init_mask(init, daddr, ~dmask, data);
 }
 
-/**
+/*
  * INIT_ZM_MASK_ADD - opcode 0x97
  *
  */
@@ -2098,7 +2098,7 @@ init_zm_mask_add(struct nvbios_init *init)
        init_wr32(init, addr, data);
 }
 
-/**
+/*
  * INIT_AUXCH - opcode 0x98
  *
  */
@@ -2122,7 +2122,7 @@ init_auxch(struct nvbios_init *init)
        }
 }
 
-/**
+/*
  * INIT_AUXCH - opcode 0x99
  *
  */
@@ -2144,7 +2144,7 @@ init_zm_auxch(struct nvbios_init *init)
        }
 }
 
-/**
+/*
  * INIT_I2C_LONG_IF - opcode 0x9a
  *
  */
@@ -2183,7 +2183,7 @@ init_i2c_long_if(struct nvbios_init *init)
        init_exec_set(init, false);
 }
 
-/**
+/*
  * INIT_GPIO_NE - opcode 0xa9
  *
  */
index 8c2faa9645111932c6920befc021d71363d7869c..ccac88da8864849911b14625abbf375ca3a097b8 100644 (file)
@@ -45,7 +45,7 @@ static const struct cvb_coef gk20a_cvb_coef[] = {
        /* 852 */ { 1608418, -21643, -269,     0,    763,  -48},
 };
 
-/**
+/*
  * cvb_mv = ((c2 * speedo / s_scale + c1) * speedo / s_scale + c0)
  */
 static inline int
@@ -58,7 +58,7 @@ gk20a_volt_get_cvb_voltage(int speedo, int s_scale, const struct cvb_coef *coef)
        return mv;
 }
 
-/**
+/*
  * cvb_t_mv =
  * ((c2 * speedo / s_scale + c1) * speedo / s_scale + c0) +
  * ((c3 * speedo / s_scale + c4 + c5 * T / t_scale) * T / t_scale)
index dad938cf6decfb0658a73439a6ca602c78fce2fb..23b089a2103de37125d687396bd6eaa4c91b9ed9 100644 (file)
@@ -67,6 +67,17 @@ config DRM_PANEL_BOE_HIMAX8279D
          24 bit RGB per pixel. It provides a MIPI DSI interface to
          the host and has a built-in LED backlight.
 
+config DRM_PANEL_BOE_TH101MB31UIG002_28A
+       tristate "Boe TH101MB31UIG002-28A panel"
+       depends on OF
+       depends on DRM_MIPI_DSI
+       depends on BACKLIGHT_CLASS_DEVICE
+       help
+         Say Y here if you want to enable support for Boe
+         TH101MB31UIG002-28A TFT-LCD modules. The panel has a 800x1280
+         resolution and uses 24 bit RGB per pixel. It provides a MIPI DSI
+         interface to the host and has a built-in LED backlight.
+
 config DRM_PANEL_BOE_TV101WUM_NL6
        tristate "BOE TV101WUM and AUO KD101N80 45NA 1200x1920 panel"
        depends on OF
@@ -438,6 +449,16 @@ config DRM_PANEL_NOVATEK_NT36672A
          around the Novatek NT36672A display controller, such as some
          Tianma panels used in a few Xiaomi Poco F1 mobile phones.
 
+config DRM_PANEL_NOVATEK_NT36672E
+       tristate "Novatek NT36672E DSI panel"
+       depends on OF
+       depends on DRM_MIPI_DSI
+       depends on BACKLIGHT_CLASS_DEVICE
+       help
+         Say Y here if you want to enable support for Novatek NT36672E DSI Video Mode
+         LCD panel module. The panel has a resolution of 1080x2408 and uses 24 bit
+         RGB per pixel.
+
 config DRM_PANEL_NOVATEK_NT39016
        tristate "Novatek NT39016 RGB/SPI panel"
        depends on OF && SPI
index d94a644d0a6cea274f1748f11d8558b809cc91fc..1c4f4e7f25bb86f2dfb6e01bdea80106baedd988 100644 (file)
@@ -5,6 +5,7 @@ obj-$(CONFIG_DRM_PANEL_ASUS_Z00T_TM5P5_NT35596) += panel-asus-z00t-tm5p5-n35596.
 obj-$(CONFIG_DRM_PANEL_AUO_A030JTN01) += panel-auo-a030jtn01.o
 obj-$(CONFIG_DRM_PANEL_BOE_BF060Y8M_AJ0) += panel-boe-bf060y8m-aj0.o
 obj-$(CONFIG_DRM_PANEL_BOE_HIMAX8279D) += panel-boe-himax8279d.o
+obj-$(CONFIG_DRM_PANEL_BOE_TH101MB31UIG002_28A) += panel-boe-th101mb31ig002-28a.o
 obj-$(CONFIG_DRM_PANEL_BOE_TV101WUM_NL6) += panel-boe-tv101wum-nl6.o
 obj-$(CONFIG_DRM_PANEL_DSI_CM) += panel-dsi-cm.o
 obj-$(CONFIG_DRM_PANEL_LVDS) += panel-lvds.o
@@ -41,6 +42,7 @@ obj-$(CONFIG_DRM_PANEL_NOVATEK_NT35560) += panel-novatek-nt35560.o
 obj-$(CONFIG_DRM_PANEL_NOVATEK_NT35950) += panel-novatek-nt35950.o
 obj-$(CONFIG_DRM_PANEL_NOVATEK_NT36523) += panel-novatek-nt36523.o
 obj-$(CONFIG_DRM_PANEL_NOVATEK_NT36672A) += panel-novatek-nt36672a.o
+obj-$(CONFIG_DRM_PANEL_NOVATEK_NT36672E) += panel-novatek-nt36672e.o
 obj-$(CONFIG_DRM_PANEL_NOVATEK_NT39016) += panel-novatek-nt39016.o
 obj-$(CONFIG_DRM_PANEL_MANTIX_MLAF057WE51) += panel-mantix-mlaf057we51.o
 obj-$(CONFIG_DRM_PANEL_OLIMEX_LCD_OLINUXINO) += panel-olimex-lcd-olinuxino.o
index 11b64acbe8a9f23107b6c5118b4d114c446c4957..e225840b0d67bf0ff2d07902e9c3d7d4cfa32b47 100644 (file)
@@ -854,26 +854,20 @@ static int panel_add(struct panel_info *pinfo)
 
        pinfo->pp18_gpio = devm_gpiod_get(dev, "pp18", GPIOD_OUT_HIGH);
        if (IS_ERR(pinfo->pp18_gpio)) {
-               ret = PTR_ERR(pinfo->pp18_gpio);
-               if (ret != -EPROBE_DEFER)
-                       dev_err(dev, "failed to get pp18 gpio: %d\n", ret);
-               return ret;
+               return dev_err_probe(dev, PTR_ERR(pinfo->pp18_gpio),
+                                                        "failed to get pp18 gpio\n");
        }
 
        pinfo->pp33_gpio = devm_gpiod_get(dev, "pp33", GPIOD_OUT_HIGH);
        if (IS_ERR(pinfo->pp33_gpio)) {
-               ret = PTR_ERR(pinfo->pp33_gpio);
-               if (ret != -EPROBE_DEFER)
-                       dev_err(dev, "failed to get pp33 gpio: %d\n", ret);
-               return ret;
+               return  dev_err_probe(dev, PTR_ERR(pinfo->pp33_gpio),
+                                                        "failed to get pp33 gpio\n");
        }
 
        pinfo->enable_gpio = devm_gpiod_get(dev, "enable", GPIOD_OUT_HIGH);
        if (IS_ERR(pinfo->enable_gpio)) {
-               ret = PTR_ERR(pinfo->enable_gpio);
-               if (ret != -EPROBE_DEFER)
-                       dev_err(dev, "failed to get enable gpio: %d\n", ret);
-               return ret;
+               return  dev_err_probe(dev, PTR_ERR(pinfo->enable_gpio),
+                                                "failed to get enable gpio\n");
        }
 
        drm_panel_init(&pinfo->base, dev, &panel_funcs,
diff --git a/drivers/gpu/drm/panel/panel-boe-th101mb31ig002-28a.c b/drivers/gpu/drm/panel/panel-boe-th101mb31ig002-28a.c
new file mode 100644 (file)
index 0000000..763e9f8
--- /dev/null
@@ -0,0 +1,322 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2023 Alexander Warnecke <awarnecke002@hotmail.com>
+ * Copyright (c) 2023 Manuel Traut <manut@mecka.net>
+ * Copyright (c) 2023 Dang Huynh <danct12@riseup.net>
+ */
+
+#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/regulator/consumer.h>
+
+#include <drm/drm_connector.h>
+#include <drm/drm_mipi_dsi.h>
+#include <drm/drm_modes.h>
+#include <drm/drm_panel.h>
+
+struct boe_th101mb31ig002 {
+       struct drm_panel panel;
+
+       struct mipi_dsi_device *dsi;
+
+       struct regulator *power;
+       struct gpio_desc *enable;
+       struct gpio_desc *reset;
+
+       enum drm_panel_orientation orientation;
+};
+
+static void boe_th101mb31ig002_reset(struct boe_th101mb31ig002 *ctx)
+{
+       gpiod_direction_output(ctx->reset, 0);
+       usleep_range(10, 100);
+       gpiod_direction_output(ctx->reset, 1);
+       usleep_range(10, 100);
+       gpiod_direction_output(ctx->reset, 0);
+       usleep_range(5000, 6000);
+}
+
+static int boe_th101mb31ig002_enable(struct drm_panel *panel)
+{
+       struct boe_th101mb31ig002 *ctx = container_of(panel,
+                                                     struct boe_th101mb31ig002,
+                                                     panel);
+       struct mipi_dsi_device *dsi = ctx->dsi;
+       struct device *dev = &dsi->dev;
+       int ret;
+
+       mipi_dsi_dcs_write_seq(dsi, 0xE0, 0xAB, 0xBA);
+       mipi_dsi_dcs_write_seq(dsi, 0xE1, 0xBA, 0xAB);
+       mipi_dsi_dcs_write_seq(dsi, 0xB1, 0x10, 0x01, 0x47, 0xFF);
+       mipi_dsi_dcs_write_seq(dsi, 0xB2, 0x0C, 0x14, 0x04, 0x50, 0x50, 0x14);
+       mipi_dsi_dcs_write_seq(dsi, 0xB3, 0x56, 0x53, 0x00);
+       mipi_dsi_dcs_write_seq(dsi, 0xB4, 0x33, 0x30, 0x04);
+       mipi_dsi_dcs_write_seq(dsi, 0xB6, 0xB0, 0x00, 0x00, 0x10, 0x00, 0x10,
+                                   0x00);
+       mipi_dsi_dcs_write_seq(dsi, 0xB8, 0x05, 0x12, 0x29, 0x49, 0x48, 0x00,
+                                   0x00);
+       mipi_dsi_dcs_write_seq(dsi, 0xB9, 0x7C, 0x65, 0x55, 0x49, 0x46, 0x36,
+                                   0x3B, 0x24, 0x3D, 0x3C, 0x3D, 0x5C, 0x4C,
+                                   0x55, 0x47, 0x46, 0x39, 0x26, 0x06, 0x7C,
+                                   0x65, 0x55, 0x49, 0x46, 0x36, 0x3B, 0x24,
+                                   0x3D, 0x3C, 0x3D, 0x5C, 0x4C, 0x55, 0x47,
+                                   0x46, 0x39, 0x26, 0x06);
+       mipi_dsi_dcs_write_seq(dsi, 0x00, 0xFF, 0x87, 0x12, 0x34, 0x44, 0x44,
+                                   0x44, 0x44, 0x98, 0x04, 0x98, 0x04, 0x0F,
+                                   0x00, 0x00, 0xC1);
+       mipi_dsi_dcs_write_seq(dsi, 0xC1, 0x54, 0x94, 0x02, 0x85, 0x9F, 0x00,
+                                   0x7F, 0x00, 0x54, 0x00);
+       mipi_dsi_dcs_write_seq(dsi, 0xC2, 0x17, 0x09, 0x08, 0x89, 0x08, 0x11,
+                                   0x22, 0x20, 0x44, 0xFF, 0x18, 0x00);
+       mipi_dsi_dcs_write_seq(dsi, 0xC3, 0x86, 0x46, 0x05, 0x05, 0x1C, 0x1C,
+                                   0x1D, 0x1D, 0x02, 0x1F, 0x1F, 0x1E, 0x1E,
+                                   0x0F, 0x0F, 0x0D, 0x0D, 0x13, 0x13, 0x11,
+                                   0x11, 0x00);
+       mipi_dsi_dcs_write_seq(dsi, 0xC4, 0x07, 0x07, 0x04, 0x04, 0x1C, 0x1C,
+                                   0x1D, 0x1D, 0x02, 0x1F, 0x1F, 0x1E, 0x1E,
+                                   0x0E, 0x0E, 0x0C, 0x0C, 0x12, 0x12, 0x10,
+                                   0x10, 0x00);
+       mipi_dsi_dcs_write_seq(dsi, 0xC6, 0x2A, 0x2A);
+       mipi_dsi_dcs_write_seq(dsi, 0xC8, 0x21, 0x00, 0x31, 0x42, 0x34, 0x16);
+       mipi_dsi_dcs_write_seq(dsi, 0xCA, 0xCB, 0x43);
+       mipi_dsi_dcs_write_seq(dsi, 0xCD, 0x0E, 0x4B, 0x4B, 0x20, 0x19, 0x6B,
+                                   0x06, 0xB3);
+       mipi_dsi_dcs_write_seq(dsi, 0xD2, 0xE3, 0x2B, 0x38, 0x00);
+       mipi_dsi_dcs_write_seq(dsi, 0xD4, 0x00, 0x01, 0x00, 0x0E, 0x04, 0x44,
+                                   0x08, 0x10, 0x00, 0x00, 0x00);
+       mipi_dsi_dcs_write_seq(dsi, 0xE6, 0x80, 0x01, 0xFF, 0xFF, 0xFF, 0xFF,
+                                   0xFF, 0xFF);
+       mipi_dsi_dcs_write_seq(dsi, 0xF0, 0x12, 0x03, 0x20, 0x00, 0xFF);
+       mipi_dsi_dcs_write_seq(dsi, 0xF3, 0x00);
+
+       ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
+       if (ret < 0) {
+               dev_err(dev, "Failed to exit sleep mode: %d\n", ret);
+               return ret;
+       }
+
+       msleep(120);
+
+       ret = mipi_dsi_dcs_set_display_on(dsi);
+       if (ret < 0) {
+               dev_err(dev, "Failed to set panel on: %d\n", ret);
+               return ret;
+       }
+
+       return 0;
+}
+
+static int boe_th101mb31ig002_disable(struct drm_panel *panel)
+{
+       struct boe_th101mb31ig002 *ctx = container_of(panel,
+                                                     struct boe_th101mb31ig002,
+                                                     panel);
+       struct mipi_dsi_device *dsi = ctx->dsi;
+       struct device *dev = &dsi->dev;
+       int ret;
+
+       ret = mipi_dsi_dcs_set_display_off(dsi);
+       if (ret < 0)
+               dev_err(dev, "Failed to set panel off: %d\n", ret);
+
+       msleep(120);
+
+       ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
+       if (ret < 0)
+               dev_err(dev, "Failed to enter sleep mode: %d\n", ret);
+
+       return 0;
+}
+
+static int boe_th101mb31ig002_unprepare(struct drm_panel *panel)
+{
+       struct boe_th101mb31ig002 *ctx = container_of(panel,
+                                                     struct boe_th101mb31ig002,
+                                                     panel);
+
+       gpiod_set_value_cansleep(ctx->reset, 1);
+       gpiod_set_value_cansleep(ctx->enable, 0);
+       regulator_disable(ctx->power);
+
+       return 0;
+}
+
+static int boe_th101mb31ig002_prepare(struct drm_panel *panel)
+{
+       struct boe_th101mb31ig002 *ctx = container_of(panel,
+                                                     struct boe_th101mb31ig002,
+                                                     panel);
+       struct device *dev = &ctx->dsi->dev;
+       int ret;
+
+       ret = regulator_enable(ctx->power);
+       if (ret) {
+               dev_err(dev, "Failed to enable power supply: %d\n", ret);
+               return ret;
+       }
+
+       gpiod_set_value_cansleep(ctx->enable, 1);
+       msleep(50);
+       boe_th101mb31ig002_reset(ctx);
+       boe_th101mb31ig002_enable(panel);
+
+       return 0;
+}
+
+static const struct drm_display_mode boe_th101mb31ig002_default_mode = {
+       .clock          = 73500,
+       .hdisplay       = 800,
+       .hsync_start    = 800 + 64,
+       .hsync_end      = 800 + 64 + 16,
+       .htotal         = 800 + 64 + 16 + 64,
+       .vdisplay       = 1280,
+       .vsync_start    = 1280 + 2,
+       .vsync_end      = 1280 + 2 + 4,
+       .vtotal         = 1280 + 2 + 4 + 12,
+       .width_mm       = 135,
+       .height_mm      = 216,
+       .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
+};
+
+static int boe_th101mb31ig002_get_modes(struct drm_panel *panel,
+                                       struct drm_connector *connector)
+{
+       struct boe_th101mb31ig002 *ctx = container_of(panel,
+                                                     struct boe_th101mb31ig002,
+                                                     panel);
+       struct drm_display_mode *mode;
+
+       mode = drm_mode_duplicate(connector->dev,
+                                 &boe_th101mb31ig002_default_mode);
+       if (!mode) {
+               dev_err(panel->dev, "Failed to add mode %ux%u@%u\n",
+                       boe_th101mb31ig002_default_mode.hdisplay,
+                       boe_th101mb31ig002_default_mode.vdisplay,
+                       drm_mode_vrefresh(&boe_th101mb31ig002_default_mode));
+               return -ENOMEM;
+       }
+
+       drm_mode_set_name(mode);
+
+       connector->display_info.bpc = 8;
+       connector->display_info.width_mm = mode->width_mm;
+       connector->display_info.height_mm = mode->height_mm;
+
+       /*
+        * TODO: Remove once all drm drivers call
+        * drm_connector_set_orientation_from_panel()
+        */
+       drm_connector_set_panel_orientation(connector, ctx->orientation);
+
+       drm_mode_probed_add(connector, mode);
+
+       return 1;
+}
+
+static enum drm_panel_orientation
+boe_th101mb31ig002_get_orientation(struct drm_panel *panel)
+{
+       struct boe_th101mb31ig002 *ctx = container_of(panel,
+                                                     struct boe_th101mb31ig002,
+                                                     panel);
+
+       return ctx->orientation;
+}
+
+static const struct drm_panel_funcs boe_th101mb31ig002_funcs = {
+       .prepare = boe_th101mb31ig002_prepare,
+       .unprepare = boe_th101mb31ig002_unprepare,
+       .disable = boe_th101mb31ig002_disable,
+       .get_modes = boe_th101mb31ig002_get_modes,
+       .get_orientation = boe_th101mb31ig002_get_orientation,
+};
+
+static int boe_th101mb31ig002_dsi_probe(struct mipi_dsi_device *dsi)
+{
+       struct boe_th101mb31ig002 *ctx;
+       int ret;
+
+       ctx = devm_kzalloc(&dsi->dev, sizeof(*ctx), GFP_KERNEL);
+       if (!ctx)
+               return -ENOMEM;
+
+       mipi_dsi_set_drvdata(dsi, ctx);
+       ctx->dsi = dsi;
+
+       dsi->lanes = 4;
+       dsi->format = MIPI_DSI_FMT_RGB888;
+       dsi->mode_flags = MIPI_DSI_MODE_VIDEO_BURST |
+                         MIPI_DSI_MODE_NO_EOT_PACKET |
+                         MIPI_DSI_MODE_LPM;
+
+       ctx->power = devm_regulator_get(&dsi->dev, "power");
+       if (IS_ERR(ctx->power))
+               return dev_err_probe(&dsi->dev, PTR_ERR(ctx->power),
+                                    "Failed to get power regulator\n");
+
+       ctx->enable = devm_gpiod_get(&dsi->dev, "enable", GPIOD_OUT_LOW);
+       if (IS_ERR(ctx->enable))
+               return dev_err_probe(&dsi->dev, PTR_ERR(ctx->enable),
+                                    "Failed to get enable GPIO\n");
+
+       ctx->reset = devm_gpiod_get(&dsi->dev, "reset", GPIOD_OUT_HIGH);
+       if (IS_ERR(ctx->reset))
+               return dev_err_probe(&dsi->dev, PTR_ERR(ctx->reset),
+                                    "Failed to get reset GPIO\n");
+
+       ret = of_drm_get_panel_orientation(dsi->dev.of_node,
+                                          &ctx->orientation);
+       if (ret)
+               return dev_err_probe(&dsi->dev, ret,
+                                    "Failed to get orientation\n");
+
+       drm_panel_init(&ctx->panel, &dsi->dev, &boe_th101mb31ig002_funcs,
+                      DRM_MODE_CONNECTOR_DSI);
+
+       ret = drm_panel_of_backlight(&ctx->panel);
+       if (ret)
+               return ret;
+
+       drm_panel_add(&ctx->panel);
+
+       ret = mipi_dsi_attach(dsi);
+       if (ret < 0) {
+               dev_err_probe(&dsi->dev, ret,
+                             "Failed to attach panel to DSI host\n");
+               drm_panel_remove(&ctx->panel);
+               return ret;
+       }
+
+       return 0;
+}
+
+static void boe_th101mb31ig002_dsi_remove(struct mipi_dsi_device *dsi)
+{
+       struct boe_th101mb31ig002 *ctx = mipi_dsi_get_drvdata(dsi);
+
+       mipi_dsi_detach(dsi);
+       drm_panel_remove(&ctx->panel);
+}
+
+static const struct of_device_id boe_th101mb31ig002_of_match[] = {
+       { .compatible = "boe,th101mb31ig002-28a", },
+       { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, boe_th101mb31ig002_of_match);
+
+static struct mipi_dsi_driver boe_th101mb31ig002_driver = {
+       .driver = {
+               .name = "boe-th101mb31ig002-28a",
+               .of_match_table = boe_th101mb31ig002_of_match,
+       },
+       .probe = boe_th101mb31ig002_dsi_probe,
+       .remove = boe_th101mb31ig002_dsi_remove,
+};
+module_mipi_dsi_driver(boe_th101mb31ig002_driver);
+
+MODULE_AUTHOR("Alexander Warnecke <awarnecke002@hotmail.com>");
+MODULE_DESCRIPTION("BOE TH101MB31IG002-28A MIPI-DSI LCD panel");
+MODULE_LICENSE("GPL");
index a0b6f69b916f92511e81944246448db4401386fd..7d556b1bfa82c2d4bfd5de1cef26d54b8e2af12f 100644 (file)
@@ -70,6 +70,21 @@ struct panel_delay {
         */
        unsigned int hpd_absent;
 
+       /**
+        * @powered_on_to_enable: Time between panel powered on and enable.
+        *
+        * The minimum time, in milliseconds, that needs to have passed
+        * between when panel powered on and enable may begin.
+        *
+        * This is (T3+T4+T5+T6+T8)-min on eDP timing diagrams or after the
+        * power supply enabled until we can turn the backlight on and see
+        * valid data.
+        *
+        * This doesn't normally need to be set if timings are already met by
+        * prepare_to_enable or enable.
+        */
+       unsigned int powered_on_to_enable;
+
        /**
         * @prepare_to_enable: Time between prepare and enable.
         *
@@ -216,6 +231,7 @@ struct panel_edp {
        bool prepared;
 
        ktime_t prepared_time;
+       ktime_t powered_on_time;
        ktime_t unprepared_time;
 
        const struct panel_desc *desc;
@@ -413,8 +429,7 @@ static int panel_edp_unprepare(struct drm_panel *panel)
        if (!p->prepared)
                return 0;
 
-       pm_runtime_mark_last_busy(panel->dev);
-       ret = pm_runtime_put_autosuspend(panel->dev);
+       ret = pm_runtime_put_sync_suspend(panel->dev);
        if (ret < 0)
                return ret;
        p->prepared = false;
@@ -455,6 +470,8 @@ static int panel_edp_prepare_once(struct panel_edp *p)
 
        gpiod_set_value_cansleep(p->enable_gpio, 1);
 
+       p->powered_on_time = ktime_get_boottime();
+
        delay = p->desc->delay.hpd_reliable;
        if (p->no_hpd)
                delay = max(delay, p->desc->delay.hpd_absent);
@@ -579,6 +596,8 @@ static int panel_edp_enable(struct drm_panel *panel)
 
        panel_edp_wait(p->prepared_time, p->desc->delay.prepare_to_enable);
 
+       panel_edp_wait(p->powered_on_time, p->desc->delay.powered_on_to_enable);
+
        p->enabled = true;
 
        return 0;
@@ -1837,6 +1856,13 @@ static const struct panel_delay delay_200_500_p2e80 = {
        .prepare_to_enable = 80,
 };
 
+static const struct panel_delay delay_200_500_e50_p2e80 = {
+       .hpd_absent = 200,
+       .unprepare = 500,
+       .enable = 50,
+       .prepare_to_enable = 80,
+};
+
 static const struct panel_delay delay_200_500_p2e100 = {
        .hpd_absent = 200,
        .unprepare = 500,
@@ -1874,6 +1900,13 @@ static const struct panel_delay delay_200_500_e200 = {
        .enable = 200,
 };
 
+static const struct panel_delay delay_200_500_e200_d200 = {
+       .hpd_absent = 200,
+       .unprepare = 500,
+       .enable = 200,
+       .disable = 200,
+};
+
 static const struct panel_delay delay_200_500_e200_d10 = {
        .hpd_absent = 200,
        .unprepare = 500,
@@ -1887,6 +1920,13 @@ static const struct panel_delay delay_200_150_e200 = {
        .enable = 200,
 };
 
+static const struct panel_delay delay_200_500_e50_po2e200 = {
+       .hpd_absent = 200,
+       .unprepare = 500,
+       .enable = 50,
+       .powered_on_to_enable = 200,
+};
+
 #define EDP_PANEL_ENTRY(vend_chr_0, vend_chr_1, vend_chr_2, product_id, _delay, _name) \
 { \
        .name = _name, \
@@ -1912,7 +1952,9 @@ static const struct panel_delay delay_200_150_e200 = {
  * Sort first by vendor, then by product ID.
  */
 static const struct edp_panel_entry edp_panels[] = {
+       EDP_PANEL_ENTRY('A', 'U', 'O', 0x105c, &delay_200_500_e50, "B116XTN01.0"),
        EDP_PANEL_ENTRY('A', 'U', 'O', 0x1062, &delay_200_500_e50, "B120XAN01.0"),
+       EDP_PANEL_ENTRY('A', 'U', 'O', 0x125c, &delay_200_500_e50, "Unknown"),
        EDP_PANEL_ENTRY('A', 'U', 'O', 0x145c, &delay_200_500_e50, "B116XAB01.4"),
        EDP_PANEL_ENTRY('A', 'U', 'O', 0x1e9b, &delay_200_500_e50, "B133UAN02.1"),
        EDP_PANEL_ENTRY('A', 'U', 'O', 0x1ea5, &delay_200_500_e50, "B116XAK01.6"),
@@ -1923,54 +1965,91 @@ static const struct edp_panel_entry edp_panels[] = {
        EDP_PANEL_ENTRY('A', 'U', 'O', 0x403d, &delay_200_500_e50, "B140HAN04.0"),
        EDP_PANEL_ENTRY2('A', 'U', 'O', 0x405c, &auo_b116xak01.delay, "B116XAK01.0",
                         &auo_b116xa3_mode),
+       EDP_PANEL_ENTRY('A', 'U', 'O', 0x435c, &delay_200_500_e50, "Unknown"),
        EDP_PANEL_ENTRY('A', 'U', 'O', 0x582d, &delay_200_500_e50, "B133UAN01.0"),
        EDP_PANEL_ENTRY2('A', 'U', 'O', 0x615c, &delay_200_500_e50, "B116XAN06.1",
                         &auo_b116xa3_mode),
        EDP_PANEL_ENTRY('A', 'U', 'O', 0x635c, &delay_200_500_e50, "B116XAN06.3"),
        EDP_PANEL_ENTRY('A', 'U', 'O', 0x639c, &delay_200_500_e50, "B140HAK02.7"),
+       EDP_PANEL_ENTRY('A', 'U', 'O', 0x723c, &delay_200_500_e50, "B140XTN07.2"),
        EDP_PANEL_ENTRY('A', 'U', 'O', 0x8594, &delay_200_500_e50, "B133UAN01.0"),
        EDP_PANEL_ENTRY('A', 'U', 'O', 0xf390, &delay_200_500_e50, "B140XTN07.7"),
 
+       EDP_PANEL_ENTRY('B', 'O', 'E', 0x0607, &delay_200_500_e200, "Unknown"),
+       EDP_PANEL_ENTRY('B', 'O', 'E', 0x0608, &delay_200_500_e50, "NT116WHM-N11"),
+       EDP_PANEL_ENTRY('B', 'O', 'E', 0x0668, &delay_200_500_e200, "Unknown"),
+       EDP_PANEL_ENTRY('B', 'O', 'E', 0x068f, &delay_200_500_e200, "Unknown"),
+       EDP_PANEL_ENTRY('B', 'O', 'E', 0x06e5, &delay_200_500_e200, "Unknown"),
+       EDP_PANEL_ENTRY('B', 'O', 'E', 0x0705, &delay_200_500_e200, "Unknown"),
        EDP_PANEL_ENTRY('B', 'O', 'E', 0x0715, &delay_200_150_e200, "NT116WHM-N21"),
+       EDP_PANEL_ENTRY('B', 'O', 'E', 0x0717, &delay_200_500_e50_po2e200, "NV133FHM-N42"),
        EDP_PANEL_ENTRY('B', 'O', 'E', 0x0731, &delay_200_500_e80, "NT116WHM-N42"),
        EDP_PANEL_ENTRY('B', 'O', 'E', 0x0741, &delay_200_500_e200, "NT116WHM-N44"),
+       EDP_PANEL_ENTRY('B', 'O', 'E', 0x0744, &delay_200_500_e200, "Unknown"),
+       EDP_PANEL_ENTRY('B', 'O', 'E', 0x074c, &delay_200_500_e200, "Unknown"),
+       EDP_PANEL_ENTRY('B', 'O', 'E', 0x0751, &delay_200_500_e200, "Unknown"),
+       EDP_PANEL_ENTRY('B', 'O', 'E', 0x0754, &delay_200_500_e50_po2e200, "NV116WHM-N45"),
+       EDP_PANEL_ENTRY('B', 'O', 'E', 0x0771, &delay_200_500_e200, "Unknown"),
        EDP_PANEL_ENTRY('B', 'O', 'E', 0x0786, &delay_200_500_p2e80, "NV116WHM-T01"),
+       EDP_PANEL_ENTRY('B', 'O', 'E', 0x0797, &delay_200_500_e200, "Unknown"),
        EDP_PANEL_ENTRY('B', 'O', 'E', 0x07d1, &boe_nv133fhm_n61.delay, "NV133FHM-N61"),
+       EDP_PANEL_ENTRY('B', 'O', 'E', 0x07d3, &delay_200_500_e200, "Unknown"),
        EDP_PANEL_ENTRY('B', 'O', 'E', 0x07f6, &delay_200_500_e200, "NT140FHM-N44"),
+       EDP_PANEL_ENTRY('B', 'O', 'E', 0x07f8, &delay_200_500_e200, "Unknown"),
+       EDP_PANEL_ENTRY('B', 'O', 'E', 0x0813, &delay_200_500_e200, "Unknown"),
+       EDP_PANEL_ENTRY('B', 'O', 'E', 0x0827, &delay_200_500_e50_p2e80, "NT140WHM-N44 V8.0"),
        EDP_PANEL_ENTRY('B', 'O', 'E', 0x082d, &boe_nv133fhm_n61.delay, "NV133FHM-N62"),
+       EDP_PANEL_ENTRY('B', 'O', 'E', 0x0843, &delay_200_500_e200, "Unknown"),
        EDP_PANEL_ENTRY('B', 'O', 'E', 0x08b2, &delay_200_500_e200, "NT140WHM-N49"),
+       EDP_PANEL_ENTRY('B', 'O', 'E', 0x0848, &delay_200_500_e200, "Unknown"),
+       EDP_PANEL_ENTRY('B', 'O', 'E', 0x0849, &delay_200_500_e200, "Unknown"),
        EDP_PANEL_ENTRY('B', 'O', 'E', 0x09c3, &delay_200_500_e50, "NT116WHM-N21,836X2"),
        EDP_PANEL_ENTRY('B', 'O', 'E', 0x094b, &delay_200_500_e50, "NT116WHM-N21"),
        EDP_PANEL_ENTRY('B', 'O', 'E', 0x0951, &delay_200_500_e80, "NV116WHM-N47"),
        EDP_PANEL_ENTRY('B', 'O', 'E', 0x095f, &delay_200_500_e50, "NE135FBM-N41 v8.1"),
+       EDP_PANEL_ENTRY('B', 'O', 'E', 0x096e, &delay_200_500_e50_po2e200, "NV116WHM-T07 V8.0"),
        EDP_PANEL_ENTRY('B', 'O', 'E', 0x0979, &delay_200_500_e50, "NV116WHM-N49 V8.0"),
        EDP_PANEL_ENTRY('B', 'O', 'E', 0x098d, &boe_nv110wtm_n61.delay, "NV110WTM-N61"),
+       EDP_PANEL_ENTRY('B', 'O', 'E', 0x0993, &delay_200_500_e80, "NV116WHM-T14 V8.0"),
+       EDP_PANEL_ENTRY('B', 'O', 'E', 0x09ad, &delay_200_500_e80, "NV116WHM-N47"),
        EDP_PANEL_ENTRY('B', 'O', 'E', 0x09ae, &delay_200_500_e200, "NT140FHM-N45"),
        EDP_PANEL_ENTRY('B', 'O', 'E', 0x09dd, &delay_200_500_e50, "NT116WHM-N21"),
+       EDP_PANEL_ENTRY('B', 'O', 'E', 0x0a36, &delay_200_500_e200, "Unknown"),
+       EDP_PANEL_ENTRY('B', 'O', 'E', 0x0a3e, &delay_200_500_e80, "NV116WHM-N49"),
        EDP_PANEL_ENTRY('B', 'O', 'E', 0x0a5d, &delay_200_500_e50, "NV116WHM-N45"),
        EDP_PANEL_ENTRY('B', 'O', 'E', 0x0ac5, &delay_200_500_e50, "NV116WHM-N4C"),
+       EDP_PANEL_ENTRY('B', 'O', 'E', 0x0b34, &delay_200_500_e80, "NV122WUM-N41"),
        EDP_PANEL_ENTRY('B', 'O', 'E', 0x0b43, &delay_200_500_e200, "NV140FHM-T09"),
        EDP_PANEL_ENTRY('B', 'O', 'E', 0x0b56, &delay_200_500_e80, "NT140FHM-N47"),
        EDP_PANEL_ENTRY('B', 'O', 'E', 0x0c20, &delay_200_500_e80, "NT140FHM-N47"),
 
+       EDP_PANEL_ENTRY('C', 'M', 'N', 0x1130, &delay_200_500_e50, "N116BGE-EB2"),
        EDP_PANEL_ENTRY('C', 'M', 'N', 0x1132, &delay_200_500_e80_d50, "N116BGE-EA2"),
        EDP_PANEL_ENTRY('C', 'M', 'N', 0x1138, &innolux_n116bca_ea1.delay, "N116BCA-EA1-RC4"),
        EDP_PANEL_ENTRY('C', 'M', 'N', 0x1139, &delay_200_500_e80_d50, "N116BGE-EA2"),
+       EDP_PANEL_ENTRY('C', 'M', 'N', 0x1141, &delay_200_500_e80_d50, "Unknown"),
        EDP_PANEL_ENTRY('C', 'M', 'N', 0x1145, &delay_200_500_e80_d50, "N116BCN-EB1"),
+       EDP_PANEL_ENTRY('C', 'M', 'N', 0x114a, &delay_200_500_e80_d50, "Unknown"),
        EDP_PANEL_ENTRY('C', 'M', 'N', 0x114c, &innolux_n116bca_ea1.delay, "N116BCA-EA1"),
        EDP_PANEL_ENTRY('C', 'M', 'N', 0x1152, &delay_200_500_e80_d50, "N116BCN-EA1"),
        EDP_PANEL_ENTRY('C', 'M', 'N', 0x1153, &delay_200_500_e80_d50, "N116BGE-EA2"),
        EDP_PANEL_ENTRY('C', 'M', 'N', 0x1154, &delay_200_500_e80_d50, "N116BCA-EA2"),
+       EDP_PANEL_ENTRY('C', 'M', 'N', 0x1156, &delay_200_500_e80_d50, "Unknown"),
        EDP_PANEL_ENTRY('C', 'M', 'N', 0x1157, &delay_200_500_e80_d50, "N116BGE-EA2"),
        EDP_PANEL_ENTRY('C', 'M', 'N', 0x115b, &delay_200_500_e80_d50, "N116BCN-EB1"),
        EDP_PANEL_ENTRY('C', 'M', 'N', 0x1247, &delay_200_500_e80_d50, "N120ACA-EA1"),
        EDP_PANEL_ENTRY('C', 'M', 'N', 0x142b, &delay_200_500_e80_d50, "N140HCA-EAC"),
+       EDP_PANEL_ENTRY('C', 'M', 'N', 0x142e, &delay_200_500_e80_d50, "N140BGA-EA4"),
        EDP_PANEL_ENTRY('C', 'M', 'N', 0x144f, &delay_200_500_e80_d50, "N140HGA-EA1"),
        EDP_PANEL_ENTRY('C', 'M', 'N', 0x1468, &delay_200_500_e80, "N140HGA-EA1"),
        EDP_PANEL_ENTRY('C', 'M', 'N', 0x14d4, &delay_200_500_e80_d50, "N140HCA-EAC"),
        EDP_PANEL_ENTRY('C', 'M', 'N', 0x14d6, &delay_200_500_e80_d50, "N140BGA-EA4"),
        EDP_PANEL_ENTRY('C', 'M', 'N', 0x14e5, &delay_200_500_e80_d50, "N140HGA-EA1"),
 
+       EDP_PANEL_ENTRY('C', 'S', 'O', 0x1200, &delay_200_500_e50, "MNC207QS1-1"),
+
+       EDP_PANEL_ENTRY('H', 'K', 'C', 0x2d51, &delay_200_500_e200, "Unknown"),
+       EDP_PANEL_ENTRY('H', 'K', 'C', 0x2d5b, &delay_200_500_e200, "Unknown"),
        EDP_PANEL_ENTRY('H', 'K', 'C', 0x2d5c, &delay_200_500_e200, "MB116AN01-2"),
 
        EDP_PANEL_ENTRY('I', 'V', 'O', 0x048e, &delay_200_500_e200_d10, "M116NWR6 R5"),
@@ -1979,11 +2058,25 @@ static const struct edp_panel_entry edp_panels[] = {
        EDP_PANEL_ENTRY('I', 'V', 'O', 0x854b, &delay_200_500_p2e100, "R133NW4K-R0"),
        EDP_PANEL_ENTRY('I', 'V', 'O', 0x8c4d, &delay_200_150_e200, "R140NWFM R1"),
 
+       EDP_PANEL_ENTRY('K', 'D', 'B', 0x044f, &delay_200_500_e80_d50, "Unknown"),
        EDP_PANEL_ENTRY('K', 'D', 'B', 0x0624, &kingdisplay_kd116n21_30nv_a010.delay, "116N21-30NV-A010"),
+       EDP_PANEL_ENTRY('K', 'D', 'B', 0x1118, &delay_200_500_e50, "KD116N29-30NK-A005"),
        EDP_PANEL_ENTRY('K', 'D', 'B', 0x1120, &delay_200_500_e80_d50, "116N29-30NK-C007"),
 
+       EDP_PANEL_ENTRY('K', 'D', 'C', 0x044f, &delay_200_500_e50, "KD116N9-30NH-F3"),
+       EDP_PANEL_ENTRY('K', 'D', 'C', 0x05f1, &delay_200_500_e80_d50, "KD116N5-30NV-G7"),
        EDP_PANEL_ENTRY('K', 'D', 'C', 0x0809, &delay_200_500_e50, "KD116N2930A15"),
 
+       EDP_PANEL_ENTRY('L', 'G', 'D', 0x0000, &delay_200_500_e200_d200, "Unknown"),
+       EDP_PANEL_ENTRY('L', 'G', 'D', 0x048d, &delay_200_500_e200_d200, "Unknown"),
+       EDP_PANEL_ENTRY('L', 'G', 'D', 0x0497, &delay_200_500_e200_d200, "LP116WH7-SPB1"),
+       EDP_PANEL_ENTRY('L', 'G', 'D', 0x052c, &delay_200_500_e200_d200, "LP133WF2-SPL7"),
+       EDP_PANEL_ENTRY('L', 'G', 'D', 0x0537, &delay_200_500_e200_d200, "Unknown"),
+       EDP_PANEL_ENTRY('L', 'G', 'D', 0x054a, &delay_200_500_e200_d200, "LP116WH8-SPC1"),
+       EDP_PANEL_ENTRY('L', 'G', 'D', 0x0567, &delay_200_500_e200_d200, "Unknown"),
+       EDP_PANEL_ENTRY('L', 'G', 'D', 0x05af, &delay_200_500_e200_d200, "Unknown"),
+       EDP_PANEL_ENTRY('L', 'G', 'D', 0x05f1, &delay_200_500_e200_d200, "Unknown"),
+
        EDP_PANEL_ENTRY('S', 'D', 'C', 0x416d, &delay_100_500_e200, "ATNA45AF01"),
 
        EDP_PANEL_ENTRY('S', 'H', 'P', 0x1511, &delay_200_500_e50, "LQ140M1JW48"),
index 30919c872ac8d50fc638c468cd968e52bc61855e..9d87cc1a357e3853979ce2b0b4c7f7e45018adda 100644 (file)
@@ -646,26 +646,17 @@ static int ltk050h3146w_probe(struct mipi_dsi_device *dsi)
                return -EINVAL;
 
        ctx->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
-       if (IS_ERR(ctx->reset_gpio)) {
-               dev_err(dev, "cannot get reset gpio\n");
-               return PTR_ERR(ctx->reset_gpio);
-       }
+       if (IS_ERR(ctx->reset_gpio))
+               return dev_err_probe(dev, PTR_ERR(ctx->reset_gpio), "cannot get reset gpio\n");
 
        ctx->vci = devm_regulator_get(dev, "vci");
-       if (IS_ERR(ctx->vci)) {
-               ret = PTR_ERR(ctx->vci);
-               if (ret != -EPROBE_DEFER)
-                       dev_err(dev, "Failed to request vci regulator: %d\n", ret);
-               return ret;
-       }
+       if (IS_ERR(ctx->vci))
+               return dev_err_probe(dev, PTR_ERR(ctx->vci), "Failed to request vci regulator\n");
 
        ctx->iovcc = devm_regulator_get(dev, "iovcc");
-       if (IS_ERR(ctx->iovcc)) {
-               ret = PTR_ERR(ctx->iovcc);
-               if (ret != -EPROBE_DEFER)
-                       dev_err(dev, "Failed to request iovcc regulator: %d\n", ret);
-               return ret;
-       }
+       if (IS_ERR(ctx->iovcc))
+               return dev_err_probe(dev, PTR_ERR(ctx->iovcc),
+                                    "Failed to request iovcc regulator\n");
 
        mipi_dsi_set_drvdata(dsi, ctx);
 
index 83a9cf53d2690defbf8a07fd428e4f5853fac09e..d3bfdfc9cff641635a7a292e1c76383cb6259f7e 100644 (file)
@@ -36,6 +36,9 @@
 #include <drm/drm_modes.h>
 #include <drm/drm_panel.h>
 
+#define NT35510_CMD_CORRECT_GAMMA BIT(0)
+#define NT35510_CMD_CONTROL_DISPLAY BIT(1)
+
 #define MCS_CMD_MAUCCTR                0xF0 /* Manufacturer command enable */
 #define MCS_CMD_READ_ID1       0xDA
 #define MCS_CMD_READ_ID2       0xDB
 /* AVDD and AVEE setting 3 bytes */
 #define NT35510_P1_AVDD_LEN 3
 #define NT35510_P1_AVEE_LEN 3
+#define NT35510_P1_VCL_LEN 3
 #define NT35510_P1_VGH_LEN 3
 #define NT35510_P1_VGL_LEN 3
 #define NT35510_P1_VGP_LEN 3
 #define NT35510_P1_VGN_LEN 3
+#define NT35510_P1_VCMOFF_LEN 2
 /* BT1CTR thru BT5CTR setting 3 bytes */
 #define NT35510_P1_BT1CTR_LEN 3
 #define NT35510_P1_BT2CTR_LEN 3
+#define NT35510_P1_BT3CTR_LEN 3
 #define NT35510_P1_BT4CTR_LEN 3
 #define NT35510_P1_BT5CTR_LEN 3
 /* 52 gamma parameters times two per color: positive and negative */
 #define NT35510_P1_GAMMA_LEN 52
 
+#define NT35510_WRCTRLD_BCTRL BIT(5)
+#define NT35510_WRCTRLD_A BIT(4)
+#define NT35510_WRCTRLD_DD BIT(3)
+#define NT35510_WRCTRLD_BL BIT(2)
+#define NT35510_WRCTRLD_DB BIT(1)
+#define NT35510_WRCTRLD_G BIT(0)
+
+#define NT35510_WRCABC_OFF 0
+#define NT35510_WRCABC_UI_MODE 1
+#define NT35510_WRCABC_STILL_MODE 2
+#define NT35510_WRCABC_MOVING_MODE 3
+
 /**
  * struct nt35510_config - the display-specific NT35510 configuration
  *
@@ -171,6 +189,14 @@ struct nt35510_config {
         * timing in the display controller.
         */
        const struct drm_display_mode mode;
+       /**
+        * @mode_flags: DSI operation mode related flags
+        */
+       unsigned long mode_flags;
+       /**
+        * @cmds: enable DSI commands
+        */
+       u32 cmds;
        /**
         * @avdd: setting for AVDD ranging from 0x00 = 6.5V to 0x14 = 4.5V
         * in 0.1V steps the default is 0x05 which means 6.0V
@@ -220,6 +246,25 @@ struct nt35510_config {
         * The defaults are 4 and 3 yielding 0x34
         */
        u8 bt2ctr[NT35510_P1_BT2CTR_LEN];
+       /**
+        * @vcl: setting for VCL ranging from 0x00 = -2.5V to 0x11 = -4.0V
+        * in 1V steps, the default is 0x00 which means -2.5V
+        */
+       u8 vcl[NT35510_P1_VCL_LEN];
+       /**
+        * @bt3ctr: setting for boost power control for the VCL step-up
+        * circuit (3)
+        * bits 0..2 in the lower nibble controls CLCK, the booster clock
+        * frequency, the values are the same as for PCK in @bt1ctr.
+        * bits 4..5 in the upper nibble controls BTCL, the boosting
+        * amplification for the step-up circuit.
+        * 0 = Disable
+        * 1 = -0.5 x VDDB
+        * 2 = -1 x VDDB
+        * 3 = -2 x VDDB
+        * The defaults are 4 and 2 yielding 0x24
+        */
+       u8 bt3ctr[NT35510_P1_BT3CTR_LEN];
        /**
         * @vgh: setting for VGH ranging from 0x00 = 7.0V to 0x0B = 18.0V
         * in 1V steps, the default is 0x08 which means 15V
@@ -273,6 +318,113 @@ struct nt35510_config {
         * same layout of bytes as @vgp.
         */
        u8 vgn[NT35510_P1_VGN_LEN];
+       /**
+        * @vcmoff: setting the DC VCOM offset voltage
+        * The first byte contains bit 8 of VCM in bit 0 and VCMOFFSEL in bit 4.
+        * The second byte contains bits 0..7 of VCM.
+        * VCMOFFSEL the common voltage offset mode.
+        * VCMOFFSEL 0x00 = VCOM .. 0x01 Gamma.
+        * The default is 0x00.
+        * VCM the VCOM output voltage (VCMOFFSEL = 0) or the internal register
+        * offset for gamma voltage (VCMOFFSEL = 1).
+        * VCM 0x00 = 0V/0 .. 0x118 = 3.5V/280 in steps of 12.5mV/1step
+        * The default is 0x00 = 0V/0.
+        */
+       u8 vcmoff[NT35510_P1_VCMOFF_LEN];
+       /**
+        * @dopctr: setting optional control for display
+        * ERR bits 0..1 in the first byte is the ERR pin output signal setting.
+        * 0 = Disable, ERR pin output low
+        * 1 = ERR pin output CRC error only
+        * 2 = ERR pin output ECC error only
+        * 3 = ERR pin output CRC and ECC error
+        * The default is 0.
+        * N565 bit 2 in the first byte is the 16-bit/pixel format selection.
+        * 0 = R[4:0] + G[5:3] & G[2:0] + B[4:0]
+        * 1 = G[2:0] + R[4:0] & B[4:0] + G[5:3]
+        * The default is 0.
+        * DIS_EoTP_HS bit 3 in the first byte is "DSI protocol violation" error
+        * reporting.
+        * 0 = reporting when error
+        * 1 = not reporting when error
+        * DSIM bit 4 in the first byte is the video mode data type enable
+        * 0 = Video mode data type disable
+        * 1 = Video mode data type enable
+        * The default is 0.
+        * DSIG bit 5 int the first byte is the generic r/w data type enable
+        * 0 = Generic r/w disable
+        * 1 = Generic r/w enable
+        * The default is 0.
+        * DSITE bit 6 in the first byte is TE line enable
+        * 0 = TE line is disabled
+        * 1 = TE line is enabled
+        * The default is 0.
+        * RAMKP bit 7 in the first byte is the frame memory keep/loss in
+        * sleep-in mode
+        * 0 = contents loss in sleep-in
+        * 1 = contents keep in sleep-in
+        * The default is 0.
+        * CRL bit 1 in the second byte is the source driver data shift
+        * direction selection. This bit is XOR operation with bit RSMX
+        * of 3600h command.
+        * 0 (RMSX = 0) = S1 -> S1440
+        * 0 (RMSX = 1) = S1440 -> S1
+        * 1 (RMSX = 0) = S1440 -> S1
+        * 1 (RMSX = 1) = S1 -> S1440
+        * The default is 0.
+        * CTB bit 2 in the second byte is the vertical scanning direction
+        * selection for gate control signals. This bit is XOR operation
+        * with bit ML of 3600h command.
+        * 0 (ML = 0) = Forward (top -> bottom)
+        * 0 (ML = 1) = Reverse (bottom -> top)
+        * 1 (ML = 0) = Reverse (bottom -> top)
+        * 1 (ML = 1) = Forward (top -> bottom)
+        * The default is 0.
+        * CRGB bit 3 in the second byte is RGB-BGR order selection. This
+        * bit is XOR operation with bit RGB of 3600h command.
+        * 0 (RGB = 0) = RGB/Normal
+        * 0 (RGB = 1) = BGR/RB swap
+        * 1 (RGB = 0) = BGR/RB swap
+        * 1 (RGB = 1) = RGB/Normal
+        * The default is 0.
+        * TE_PWR_SEL bit 4 in the second byte is the TE output voltage
+        * level selection (only valid when DSTB_SEL = 0 or DSTB_SEL = 1,
+        * VSEL = High and VDDI = 1.665~3.3V).
+        * 0 = TE output voltage level is VDDI
+        * 1 = TE output voltage level is VDDA
+        * The default is 0.
+        */
+       u8 dopctr[NT35510_P0_DOPCTR_LEN];
+       /**
+        * @madctl: Memory data access control
+        * RSMY bit 0 is flip vertical. Flips the display image top to down.
+        * RSMX bit 1 is flip horizontal. Flips the display image left to right.
+        * MH bit 2 is the horizontal refresh order.
+        * RGB bit 3 is the RGB-BGR order.
+        * 0 = RGB color sequence
+        * 1 = BGR color sequence
+        * ML bit 4 is the vertical refresh order.
+        * MV bit 5 is the row/column exchange.
+        * MX bit 6 is the column address order.
+        * MY bit 7 is the row address order.
+        */
+       u8 madctl;
+       /**
+        * @sdhdtctr: source output data hold time
+        * 0x00..0x3F = 0..31.5us in steps of 0.5us
+        * The default is 0x05 = 2.5us.
+        */
+       u8 sdhdtctr;
+       /**
+        * @gseqctr: EQ control for gate signals
+        * GFEQ_XX[3:0]: time setting of EQ step for falling edge in steps
+        * of 0.5us.
+        * The default is 0x07 = 3.5us
+        * GREQ_XX[7:4]: time setting of EQ step for rising edge in steps
+        * of 0.5us.
+        * The default is 0x07 = 3.5us
+        */
+       u8 gseqctr[NT35510_P0_GSEQCTR_LEN];
        /**
         * @sdeqctr: Source driver control settings, first byte is
         * 0 for mode 1 and 1 for mode 2. Mode 1 uses two steps and
@@ -343,6 +495,43 @@ struct nt35510_config {
         * @gamma_corr_neg_b: Blue gamma correction parameters, negative
         */
        u8 gamma_corr_neg_b[NT35510_P1_GAMMA_LEN];
+       /**
+        * @wrdisbv: write display brightness
+        * 0x00 value means the lowest brightness and 0xff value means
+        * the highest brightness.
+        * The default is 0x00.
+        */
+       u8 wrdisbv;
+       /**
+        * @wrctrld: write control display
+        * G bit 0 selects gamma curve: 0 = Manual, 1 = Automatic
+        * DB bit 1 selects display brightness: 0 = Manual, 1 = Automatic
+        * BL bit 2 controls backlight control: 0 = Off, 1 = On
+        * DD bit 3 controls display dimming: 0 = Off, 1 = On
+        * A bit 4 controls LABC block: 0 = Off, 1 = On
+        * BCTRL bit 5 controls brightness block: 0 = Off, 1 = On
+        */
+       u8 wrctrld;
+       /**
+        * @wrcabc: write content adaptive brightness control
+        * There is possible to use 4 different modes for content adaptive
+        * image functionality:
+        * 0: Off
+        * 1: User Interface Image (UI-Mode)
+        * 2: Still Picture Image (Still-Mode)
+        * 3: Moving Picture Image (Moving-Mode)
+        * The default is 0
+        */
+       u8 wrcabc;
+       /**
+        * @wrcabcmb: write CABC minimum brightness
+        * Set the minimum brightness value of the display for CABC
+        * function.
+        * 0x00 value means the lowest brightness for CABC and 0xff
+        * value means the highest brightness for CABC.
+        * The default is 0x00.
+        */
+       u8 wrcabcmb;
 };
 
 /**
@@ -486,6 +675,16 @@ static int nt35510_setup_power(struct nt35510 *nt)
                                nt->conf->bt2ctr);
        if (ret)
                return ret;
+       ret = nt35510_send_long(nt, dsi, NT35510_P1_SETVCL,
+                               NT35510_P1_VCL_LEN,
+                               nt->conf->vcl);
+       if (ret)
+               return ret;
+       ret = nt35510_send_long(nt, dsi, NT35510_P1_BT3CTR,
+                               NT35510_P1_BT3CTR_LEN,
+                               nt->conf->bt3ctr);
+       if (ret)
+               return ret;
        ret = nt35510_send_long(nt, dsi, NT35510_P1_SETVGH,
                                NT35510_P1_VGH_LEN,
                                nt->conf->vgh);
@@ -522,6 +721,12 @@ static int nt35510_setup_power(struct nt35510 *nt)
        if (ret)
                return ret;
 
+       ret = nt35510_send_long(nt, dsi, NT35510_P1_SETVCMOFF,
+                               NT35510_P1_VCMOFF_LEN,
+                               nt->conf->vcmoff);
+       if (ret)
+               return ret;
+
        /* Typically 10 ms */
        usleep_range(10000, 20000);
 
@@ -536,46 +741,28 @@ static int nt35510_setup_display(struct nt35510 *nt)
 {
        struct mipi_dsi_device *dsi = to_mipi_dsi_device(nt->dev);
        const struct nt35510_config *conf = nt->conf;
-       u8 dopctr[NT35510_P0_DOPCTR_LEN];
-       u8 gseqctr[NT35510_P0_GSEQCTR_LEN];
        u8 dpfrctr[NT35510_P0_DPFRCTR1_LEN];
-       /* FIXME: set up any rotation (assume none for now) */
-       u8 addr_mode = NT35510_ROTATE_0_SETTING;
-       u8 val;
        int ret;
 
-       /* Enable TE, EoTP and RGB pixel format */
-       dopctr[0] = NT35510_DOPCTR_0_DSITE | NT35510_DOPCTR_0_EOTP |
-               NT35510_DOPCTR_0_N565;
-       dopctr[1] = NT35510_DOPCTR_1_CTB;
        ret = nt35510_send_long(nt, dsi, NT35510_P0_DOPCTR,
                                NT35510_P0_DOPCTR_LEN,
-                               dopctr);
+                               conf->dopctr);
        if (ret)
                return ret;
 
-       ret = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_ADDRESS_MODE, &addr_mode,
-                                sizeof(addr_mode));
+       ret = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_ADDRESS_MODE, &conf->madctl,
+                                sizeof(conf->madctl));
        if (ret < 0)
                return ret;
 
-       /*
-        * Source data hold time, default 0x05 = 2.5us
-        * 0x00..0x3F = 0 .. 31.5us in steps of 0.5us
-        * 0x0A = 5us
-        */
-       val = 0x0A;
-       ret = mipi_dsi_dcs_write(dsi, NT35510_P0_SDHDTCTR, &val,
-                                sizeof(val));
+       ret = mipi_dsi_dcs_write(dsi, NT35510_P0_SDHDTCTR, &conf->sdhdtctr,
+                                sizeof(conf->sdhdtctr));
        if (ret < 0)
                return ret;
 
-       /* EQ control for gate signals, 0x00 = 0 us */
-       gseqctr[0] = 0x00;
-       gseqctr[1] = 0x00;
        ret = nt35510_send_long(nt, dsi, NT35510_P0_GSEQCTR,
                                NT35510_P0_GSEQCTR_LEN,
-                               gseqctr);
+                               conf->gseqctr);
        if (ret)
                return ret;
 
@@ -719,36 +906,38 @@ static int nt35510_power_on(struct nt35510 *nt)
        if (ret)
                return ret;
 
-       ret = nt35510_send_long(nt, dsi, NT35510_P1_SET_GAMMA_RED_POS,
-                               NT35510_P1_GAMMA_LEN,
-                               nt->conf->gamma_corr_pos_r);
-       if (ret)
-               return ret;
-       ret = nt35510_send_long(nt, dsi, NT35510_P1_SET_GAMMA_GREEN_POS,
-                               NT35510_P1_GAMMA_LEN,
-                               nt->conf->gamma_corr_pos_g);
-       if (ret)
-               return ret;
-       ret = nt35510_send_long(nt, dsi, NT35510_P1_SET_GAMMA_BLUE_POS,
-                               NT35510_P1_GAMMA_LEN,
-                               nt->conf->gamma_corr_pos_b);
-       if (ret)
-               return ret;
-       ret = nt35510_send_long(nt, dsi, NT35510_P1_SET_GAMMA_RED_NEG,
-                               NT35510_P1_GAMMA_LEN,
-                               nt->conf->gamma_corr_neg_r);
-       if (ret)
-               return ret;
-       ret = nt35510_send_long(nt, dsi, NT35510_P1_SET_GAMMA_GREEN_NEG,
-                               NT35510_P1_GAMMA_LEN,
-                               nt->conf->gamma_corr_neg_g);
-       if (ret)
-               return ret;
-       ret = nt35510_send_long(nt, dsi, NT35510_P1_SET_GAMMA_BLUE_NEG,
-                               NT35510_P1_GAMMA_LEN,
-                               nt->conf->gamma_corr_neg_b);
-       if (ret)
-               return ret;
+       if (nt->conf->cmds & NT35510_CMD_CORRECT_GAMMA) {
+               ret = nt35510_send_long(nt, dsi, NT35510_P1_SET_GAMMA_RED_POS,
+                                       NT35510_P1_GAMMA_LEN,
+                                       nt->conf->gamma_corr_pos_r);
+               if (ret)
+                       return ret;
+               ret = nt35510_send_long(nt, dsi, NT35510_P1_SET_GAMMA_GREEN_POS,
+                                       NT35510_P1_GAMMA_LEN,
+                                       nt->conf->gamma_corr_pos_g);
+               if (ret)
+                       return ret;
+               ret = nt35510_send_long(nt, dsi, NT35510_P1_SET_GAMMA_BLUE_POS,
+                                       NT35510_P1_GAMMA_LEN,
+                                       nt->conf->gamma_corr_pos_b);
+               if (ret)
+                       return ret;
+               ret = nt35510_send_long(nt, dsi, NT35510_P1_SET_GAMMA_RED_NEG,
+                                       NT35510_P1_GAMMA_LEN,
+                                       nt->conf->gamma_corr_neg_r);
+               if (ret)
+                       return ret;
+               ret = nt35510_send_long(nt, dsi, NT35510_P1_SET_GAMMA_GREEN_NEG,
+                                       NT35510_P1_GAMMA_LEN,
+                                       nt->conf->gamma_corr_neg_g);
+               if (ret)
+                       return ret;
+               ret = nt35510_send_long(nt, dsi, NT35510_P1_SET_GAMMA_BLUE_NEG,
+                                       NT35510_P1_GAMMA_LEN,
+                                       nt->conf->gamma_corr_neg_b);
+               if (ret)
+                       return ret;
+       }
 
        /* Set up stuff in  manufacturer control, page 0 */
        ret = nt35510_send_long(nt, dsi, MCS_CMD_MAUCCTR,
@@ -827,6 +1016,26 @@ static int nt35510_prepare(struct drm_panel *panel)
        /* Up to 120 ms */
        usleep_range(120000, 150000);
 
+       if (nt->conf->cmds & NT35510_CMD_CONTROL_DISPLAY) {
+               ret = mipi_dsi_dcs_write(dsi, MIPI_DCS_WRITE_CONTROL_DISPLAY,
+                                        &nt->conf->wrctrld,
+                                        sizeof(nt->conf->wrctrld));
+               if (ret < 0)
+                       return ret;
+
+               ret = mipi_dsi_dcs_write(dsi, MIPI_DCS_WRITE_POWER_SAVE,
+                                        &nt->conf->wrcabc,
+                                        sizeof(nt->conf->wrcabc));
+               if (ret < 0)
+                       return ret;
+
+               ret = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_CABC_MIN_BRIGHTNESS,
+                                        &nt->conf->wrcabcmb,
+                                        sizeof(nt->conf->wrcabcmb));
+               if (ret < 0)
+                       return ret;
+       }
+
        ret = mipi_dsi_dcs_set_display_on(dsi);
        if (ret) {
                dev_err(nt->dev, "failed to turn display on (%d)\n", ret);
@@ -896,7 +1105,6 @@ static int nt35510_probe(struct mipi_dsi_device *dsi)
         */
        dsi->hs_rate = 349440000;
        dsi->lp_rate = 9600000;
-       dsi->mode_flags = MIPI_DSI_CLOCK_NON_CONTINUOUS;
 
        /*
         * Every new incarnation of this display must have a unique
@@ -908,6 +1116,8 @@ static int nt35510_probe(struct mipi_dsi_device *dsi)
                return -ENODEV;
        }
 
+       dsi->mode_flags = nt->conf->mode_flags;
+
        nt->supplies[0].supply = "vdd"; /* 2.3-4.8 V */
        nt->supplies[1].supply = "vddi"; /* 1.65-3.3V */
        ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(nt->supplies),
@@ -923,7 +1133,7 @@ static int nt35510_probe(struct mipi_dsi_device *dsi)
        if (ret)
                return ret;
 
-       nt->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_ASIS);
+       nt->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
        if (IS_ERR(nt->reset_gpio)) {
                dev_err(dev, "error getting RESET GPIO\n");
                return PTR_ERR(nt->reset_gpio);
@@ -952,7 +1162,10 @@ static int nt35510_probe(struct mipi_dsi_device *dsi)
                        return PTR_ERR(bl);
                }
                bl->props.max_brightness = 255;
-               bl->props.brightness = 255;
+               if (nt->conf->cmds & NT35510_CMD_CONTROL_DISPLAY)
+                       bl->props.brightness = nt->conf->wrdisbv;
+               else
+                       bl->props.brightness = 255;
                bl->props.power = FB_BLANK_POWERDOWN;
                nt->panel.backlight = bl;
        }
@@ -1030,6 +1243,8 @@ static const struct nt35510_config nt35510_hydis_hva40wv1 = {
                .vtotal = 800 + 2 + 0 + 5, /* VBP = 5 */
                .flags = 0,
        },
+       .mode_flags = MIPI_DSI_CLOCK_NON_CONTINUOUS,
+       .cmds = NT35510_CMD_CORRECT_GAMMA,
        /* 0x09: AVDD = 5.6V */
        .avdd = { 0x09, 0x09, 0x09 },
        /* 0x34: PCK = Hsync/2, BTP = 2 x VDDB */
@@ -1038,6 +1253,10 @@ static const struct nt35510_config nt35510_hydis_hva40wv1 = {
        .avee = { 0x09, 0x09, 0x09 },
        /* 0x24: NCK = Hsync/2, BTN =  -2 x VDDB */
        .bt2ctr = { 0x24, 0x24, 0x24 },
+       /* VBCLA: -2.5V, VBCLB: -2.5V, VBCLC: -2.5V */
+       .vcl = { 0x00, 0x00, 0x00 },
+       /* 0x24: CLCK = Hsync/2, BTN =  -1 x VDDB */
+       .bt3ctr = { 0x24, 0x24, 0x24 },
        /* 0x05 = 12V */
        .vgh = { 0x05, 0x05, 0x05 },
        /* 0x24: NCKA = Hsync/2, VGH = 2 x AVDD - AVEE */
@@ -1050,6 +1269,16 @@ static const struct nt35510_config nt35510_hydis_hva40wv1 = {
        .vgp = { 0x00, 0xA3, 0x00 },
        /* VGMP: 0x0A3 = 5.0375V, VGSP = 0V */
        .vgn = { 0x00, 0xA3, 0x00 },
+       /* VCMOFFSEL = VCOM voltage offset mode, VCM = 0V */
+       .vcmoff = { 0x00, 0x00 },
+       /* Enable TE, EoTP and RGB pixel format */
+       .dopctr = { NT35510_DOPCTR_0_DSITE | NT35510_DOPCTR_0_EOTP |
+                   NT35510_DOPCTR_0_N565, NT35510_DOPCTR_1_CTB },
+       .madctl = NT35510_ROTATE_0_SETTING,
+       /* 0x0A: SDT = 5 us */
+       .sdhdtctr = 0x0A,
+       /* EQ control for gate signals, 0x00 = 0 us */
+       .gseqctr = { 0x00, 0x00 },
        /* SDEQCTR: source driver EQ mode 2, 2.5 us rise time on each step */
        .sdeqctr = { 0x01, 0x05, 0x05, 0x05 },
        /* SDVPCTR: Normal operation off color during v porch */
@@ -1073,7 +1302,88 @@ static const struct nt35510_config nt35510_hydis_hva40wv1 = {
        .gamma_corr_neg_b = { NT35510_GAMMA_NEG_DEFAULT },
 };
 
+static const struct nt35510_config nt35510_frida_frd400b25025 = {
+       .width_mm = 52,
+       .height_mm = 86,
+       .mode = {
+               .clock = 23000,
+               .hdisplay = 480,
+               .hsync_start = 480 + 34, /* HFP = 34 */
+               .hsync_end = 480 + 34 + 2, /* HSync = 2 */
+               .htotal = 480 + 34 + 2 + 34, /* HBP = 34 */
+               .vdisplay = 800,
+               .vsync_start = 800 + 15, /* VFP = 15 */
+               .vsync_end = 800 + 15 + 12, /* VSync = 12 */
+               .vtotal = 800 + 15 + 12 + 15, /* VBP = 15 */
+               .flags = 0,
+       },
+       .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST |
+                       MIPI_DSI_MODE_LPM,
+       .cmds = NT35510_CMD_CONTROL_DISPLAY,
+       /* 0x03: AVDD = 6.2V */
+       .avdd = { 0x03, 0x03, 0x03 },
+       /* 0x46: PCK = 2 x Hsync, BTP = 2.5 x VDDB */
+       .bt1ctr = { 0x46, 0x46, 0x46 },
+       /* 0x03: AVEE = -6.2V */
+       .avee = { 0x03, 0x03, 0x03 },
+       /* 0x36: PCK = 2 x Hsync, BTP =  2 x VDDB */
+       .bt2ctr = { 0x36, 0x36, 0x36 },
+       /* VBCLA: -2.5V, VBCLB: -2.5V, VBCLC: -3.5V */
+       .vcl = { 0x00, 0x00, 0x02 },
+       /* 0x26: CLCK = 2 x Hsync, BTN =  -1 x VDDB */
+       .bt3ctr = { 0x26, 0x26, 0x26 },
+       /* 0x09 = 16V */
+       .vgh = { 0x09, 0x09, 0x09 },
+       /* 0x36: HCK = 2 x Hsync, VGH = 2 x AVDD - AVEE */
+       .bt4ctr = { 0x36, 0x36, 0x36 },
+       /* 0x08 = -10V */
+       .vgl = { 0x08, 0x08, 0x08 },
+       /* 0x26: LCK = 2 x Hsync, VGL = AVDD + VCL - AVDD */
+       .bt5ctr = { 0x26, 0x26, 0x26 },
+       /* VGMP: 0x080 = 4.6V, VGSP = 0V */
+       .vgp = { 0x00, 0x80, 0x00 },
+       /* VGMP: 0x080 = 4.6V, VGSP = 0V */
+       .vgn = { 0x00, 0x80, 0x00 },
+       /* VCMOFFSEL = VCOM voltage offset mode, VCM = -1V */
+       .vcmoff = { 0x00, 0x50 },
+       .dopctr = { NT35510_DOPCTR_0_RAMKP | NT35510_DOPCTR_0_DSITE |
+               NT35510_DOPCTR_0_DSIG | NT35510_DOPCTR_0_DSIM |
+               NT35510_DOPCTR_0_EOTP | NT35510_DOPCTR_0_N565, 0 },
+       .madctl = NT35510_ROTATE_180_SETTING,
+       /* 0x03: SDT = 1.5 us */
+       .sdhdtctr = 0x03,
+       /* EQ control for gate signals, 0x00 = 0 us */
+       .gseqctr = { 0x00, 0x00 },
+       /* SDEQCTR: source driver EQ mode 2, 1 us rise time on each step */
+       .sdeqctr = { 0x01, 0x02, 0x02, 0x02 },
+       /* SDVPCTR: Normal operation off color during v porch */
+       .sdvpctr = 0x01,
+       /* T1: number of pixel clocks on one scanline: 0x184 = 389 clocks */
+       .t1 = 0x0184,
+       /* VBP: vertical back porch toward the panel */
+       .vbp = 0x1C,
+       /* VFP: vertical front porch toward the panel */
+       .vfp = 0x1C,
+       /* PSEL: divide pixel clock 23MHz with 1 (no clock downscaling) */
+       .psel = 0,
+       /* DPTMCTR12: 0x03: LVGL = VGLX, overlap mode, swap R->L O->E */
+       .dpmctr12 = { 0x03, 0x00, 0x00, },
+       /* write display brightness */
+       .wrdisbv = 0x7f,
+       /* write control display */
+       .wrctrld = NT35510_WRCTRLD_BCTRL | NT35510_WRCTRLD_DD |
+                       NT35510_WRCTRLD_BL,
+       /* write content adaptive brightness control */
+       .wrcabc = NT35510_WRCABC_STILL_MODE,
+       /* write CABC minimum brightness */
+       .wrcabcmb = 0xff,
+};
+
 static const struct of_device_id nt35510_of_match[] = {
+       {
+               .compatible = "frida,frd400b25025",
+               .data = &nt35510_frida_frd400b25025,
+       },
        {
                .compatible = "hydis,hva40wv1",
                .data = &nt35510_hydis_hva40wv1,
index a189ce23632856a0492446bcc2759101fee8407c..d6fa76dbf94817100668931ffa55ccece456b9be 100644 (file)
@@ -933,8 +933,7 @@ static int j606f_boe_init_sequence(struct panel_info *pinfo)
 
 static const struct drm_display_mode elish_boe_modes[] = {
        {
-               /* There is only one 120 Hz timing, but it doesn't work perfectly, 104 Hz preferred */
-               .clock = (1600 + 60 + 8 + 60) * (2560 + 26 + 4 + 168) * 104 / 1000,
+               .clock = (1600 + 60 + 8 + 60) * (2560 + 26 + 4 + 168) * 120 / 1000,
                .hdisplay = 1600,
                .hsync_start = 1600 + 60,
                .hsync_end = 1600 + 60 + 8,
@@ -948,8 +947,7 @@ static const struct drm_display_mode elish_boe_modes[] = {
 
 static const struct drm_display_mode elish_csot_modes[] = {
        {
-               /* There is only one 120 Hz timing, but it doesn't work perfectly, 104 Hz preferred */
-               .clock = (1600 + 200 + 40 + 52) * (2560 + 26 + 4 + 168) * 104 / 1000,
+               .clock = (1600 + 200 + 40 + 52) * (2560 + 26 + 4 + 168) * 120 / 1000,
                .hdisplay = 1600,
                .hsync_start = 1600 + 200,
                .hsync_end = 1600 + 200 + 40,
diff --git a/drivers/gpu/drm/panel/panel-novatek-nt36672e.c b/drivers/gpu/drm/panel/panel-novatek-nt36672e.c
new file mode 100644 (file)
index 0000000..cb7406d
--- /dev/null
@@ -0,0 +1,643 @@
+// SPDX-License-Identifier: GPL-2.0-only
+// Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
+
+#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/regulator/consumer.h>
+
+#include <drm/drm_mipi_dsi.h>
+#include <drm/drm_modes.h>
+#include <drm/drm_panel.h>
+
+#include <video/mipi_display.h>
+
+static const char * const regulator_names[] = {
+       "vddi",
+       "avdd",
+       "avee",
+};
+
+static const unsigned long regulator_enable_loads[] = {
+       62000,
+       100000,
+       100000,
+};
+
+static const unsigned long regulator_disable_loads[] = {
+       80,
+       100,
+       100,
+};
+
+struct panel_desc {
+       const struct drm_display_mode *display_mode;
+       u32 width_mm;
+       u32 height_mm;
+       unsigned long mode_flags;
+       enum mipi_dsi_pixel_format format;
+       unsigned int lanes;
+       const char *panel_name;
+       int (*init_sequence)(struct mipi_dsi_device *dsi);
+};
+
+struct nt36672e_panel {
+       struct drm_panel panel;
+       struct mipi_dsi_device *dsi;
+       struct gpio_desc *reset_gpio;
+       struct regulator_bulk_data supplies[3];
+       const struct panel_desc *desc;
+};
+
+static inline struct nt36672e_panel *to_nt36672e_panel(struct drm_panel *panel)
+{
+       return container_of(panel, struct nt36672e_panel, panel);
+}
+
+static int nt36672e_1080x2408_60hz_init(struct mipi_dsi_device *dsi)
+{
+       mipi_dsi_dcs_write_seq(dsi, 0xff, 0x10);
+       mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01);
+       mipi_dsi_dcs_write_seq(dsi, 0xb0, 0x00);
+       mipi_dsi_dcs_write_seq(dsi, 0xc0, 0x00);
+       mipi_dsi_dcs_write_seq(dsi, 0xc1, 0x89, 0x28, 0x00, 0x08, 0x00, 0xaa, 0x02,
+                               0x0e, 0x00, 0x2b, 0x00, 0x07, 0x0d, 0xb7, 0x0c, 0xb7);
+
+       mipi_dsi_dcs_write_seq(dsi, 0xc2, 0x1b, 0xa0);
+       mipi_dsi_dcs_write_seq(dsi, 0xff, 0x20);
+       mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01);
+       mipi_dsi_dcs_write_seq(dsi, 0x01, 0x66);
+       mipi_dsi_dcs_write_seq(dsi, 0x06, 0x40);
+       mipi_dsi_dcs_write_seq(dsi, 0x07, 0x38);
+       mipi_dsi_dcs_write_seq(dsi, 0x2f, 0x83);
+       mipi_dsi_dcs_write_seq(dsi, 0x69, 0x91);
+       mipi_dsi_dcs_write_seq(dsi, 0x95, 0xd1);
+       mipi_dsi_dcs_write_seq(dsi, 0x96, 0xd1);
+       mipi_dsi_dcs_write_seq(dsi, 0xf2, 0x64);
+       mipi_dsi_dcs_write_seq(dsi, 0xf3, 0x54);
+       mipi_dsi_dcs_write_seq(dsi, 0xf4, 0x64);
+       mipi_dsi_dcs_write_seq(dsi, 0xf5, 0x54);
+       mipi_dsi_dcs_write_seq(dsi, 0xf6, 0x64);
+       mipi_dsi_dcs_write_seq(dsi, 0xf7, 0x54);
+       mipi_dsi_dcs_write_seq(dsi, 0xf8, 0x64);
+       mipi_dsi_dcs_write_seq(dsi, 0xf9, 0x54);
+       mipi_dsi_dcs_write_seq(dsi, 0xff, 0x24);
+       mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01);
+       mipi_dsi_dcs_write_seq(dsi, 0x01, 0x0f);
+       mipi_dsi_dcs_write_seq(dsi, 0x03, 0x0c);
+       mipi_dsi_dcs_write_seq(dsi, 0x05, 0x1d);
+       mipi_dsi_dcs_write_seq(dsi, 0x08, 0x2f);
+       mipi_dsi_dcs_write_seq(dsi, 0x09, 0x2e);
+       mipi_dsi_dcs_write_seq(dsi, 0x0a, 0x2d);
+       mipi_dsi_dcs_write_seq(dsi, 0x0b, 0x2c);
+       mipi_dsi_dcs_write_seq(dsi, 0x11, 0x17);
+       mipi_dsi_dcs_write_seq(dsi, 0x12, 0x13);
+       mipi_dsi_dcs_write_seq(dsi, 0x13, 0x15);
+       mipi_dsi_dcs_write_seq(dsi, 0x15, 0x14);
+       mipi_dsi_dcs_write_seq(dsi, 0x16, 0x16);
+       mipi_dsi_dcs_write_seq(dsi, 0x17, 0x18);
+       mipi_dsi_dcs_write_seq(dsi, 0x1b, 0x01);
+       mipi_dsi_dcs_write_seq(dsi, 0x1d, 0x1d);
+       mipi_dsi_dcs_write_seq(dsi, 0x20, 0x2f);
+       mipi_dsi_dcs_write_seq(dsi, 0x21, 0x2e);
+       mipi_dsi_dcs_write_seq(dsi, 0x22, 0x2d);
+       mipi_dsi_dcs_write_seq(dsi, 0x23, 0x2c);
+       mipi_dsi_dcs_write_seq(dsi, 0x29, 0x17);
+       mipi_dsi_dcs_write_seq(dsi, 0x2a, 0x13);
+       mipi_dsi_dcs_write_seq(dsi, 0x2b, 0x15);
+       mipi_dsi_dcs_write_seq(dsi, 0x2f, 0x14);
+       mipi_dsi_dcs_write_seq(dsi, 0x30, 0x16);
+       mipi_dsi_dcs_write_seq(dsi, 0x31, 0x18);
+       mipi_dsi_dcs_write_seq(dsi, 0x32, 0x04);
+       mipi_dsi_dcs_write_seq(dsi, 0x34, 0x10);
+       mipi_dsi_dcs_write_seq(dsi, 0x35, 0x1f);
+       mipi_dsi_dcs_write_seq(dsi, 0x36, 0x1f);
+       mipi_dsi_dcs_write_seq(dsi, 0x4d, 0x14);
+       mipi_dsi_dcs_write_seq(dsi, 0x4e, 0x36);
+       mipi_dsi_dcs_write_seq(dsi, 0x4f, 0x36);
+       mipi_dsi_dcs_write_seq(dsi, 0x53, 0x36);
+       mipi_dsi_dcs_write_seq(dsi, 0x71, 0x30);
+       mipi_dsi_dcs_write_seq(dsi, 0x79, 0x11);
+       mipi_dsi_dcs_write_seq(dsi, 0x7a, 0x82);
+       mipi_dsi_dcs_write_seq(dsi, 0x7b, 0x8f);
+       mipi_dsi_dcs_write_seq(dsi, 0x7d, 0x04);
+       mipi_dsi_dcs_write_seq(dsi, 0x80, 0x04);
+       mipi_dsi_dcs_write_seq(dsi, 0x81, 0x04);
+       mipi_dsi_dcs_write_seq(dsi, 0x82, 0x13);
+       mipi_dsi_dcs_write_seq(dsi, 0x84, 0x31);
+       mipi_dsi_dcs_write_seq(dsi, 0x85, 0x00);
+       mipi_dsi_dcs_write_seq(dsi, 0x86, 0x00);
+       mipi_dsi_dcs_write_seq(dsi, 0x87, 0x00);
+       mipi_dsi_dcs_write_seq(dsi, 0x90, 0x13);
+       mipi_dsi_dcs_write_seq(dsi, 0x92, 0x31);
+       mipi_dsi_dcs_write_seq(dsi, 0x93, 0x00);
+       mipi_dsi_dcs_write_seq(dsi, 0x94, 0x00);
+       mipi_dsi_dcs_write_seq(dsi, 0x95, 0x00);
+       mipi_dsi_dcs_write_seq(dsi, 0x9c, 0xf4);
+       mipi_dsi_dcs_write_seq(dsi, 0x9d, 0x01);
+       mipi_dsi_dcs_write_seq(dsi, 0xa0, 0x0f);
+       mipi_dsi_dcs_write_seq(dsi, 0xa2, 0x0f);
+       mipi_dsi_dcs_write_seq(dsi, 0xa3, 0x02);
+       mipi_dsi_dcs_write_seq(dsi, 0xa4, 0x04);
+       mipi_dsi_dcs_write_seq(dsi, 0xa5, 0x04);
+       mipi_dsi_dcs_write_seq(dsi, 0xc6, 0xc0);
+       mipi_dsi_dcs_write_seq(dsi, 0xc9, 0x00);
+       mipi_dsi_dcs_write_seq(dsi, 0xd9, 0x80);
+       mipi_dsi_dcs_write_seq(dsi, 0xe9, 0x02);
+       mipi_dsi_dcs_write_seq(dsi, 0xff, 0x25);
+       mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01);
+       mipi_dsi_dcs_write_seq(dsi, 0x18, 0x22);
+       mipi_dsi_dcs_write_seq(dsi, 0x19, 0xe4);
+       mipi_dsi_dcs_write_seq(dsi, 0x21, 0x40);
+       mipi_dsi_dcs_write_seq(dsi, 0x66, 0xd8);
+       mipi_dsi_dcs_write_seq(dsi, 0x68, 0x50);
+       mipi_dsi_dcs_write_seq(dsi, 0x69, 0x10);
+       mipi_dsi_dcs_write_seq(dsi, 0x6b, 0x00);
+       mipi_dsi_dcs_write_seq(dsi, 0x6d, 0x0d);
+       mipi_dsi_dcs_write_seq(dsi, 0x6e, 0x48);
+       mipi_dsi_dcs_write_seq(dsi, 0x72, 0x41);
+       mipi_dsi_dcs_write_seq(dsi, 0x73, 0x4a);
+       mipi_dsi_dcs_write_seq(dsi, 0x74, 0xd0);
+       mipi_dsi_dcs_write_seq(dsi, 0x77, 0x62);
+       mipi_dsi_dcs_write_seq(dsi, 0x79, 0x7e);
+       mipi_dsi_dcs_write_seq(dsi, 0x7d, 0x03);
+       mipi_dsi_dcs_write_seq(dsi, 0x7e, 0x15);
+       mipi_dsi_dcs_write_seq(dsi, 0x7f, 0x00);
+       mipi_dsi_dcs_write_seq(dsi, 0x84, 0x4d);
+       mipi_dsi_dcs_write_seq(dsi, 0xcf, 0x80);
+       mipi_dsi_dcs_write_seq(dsi, 0xd6, 0x80);
+       mipi_dsi_dcs_write_seq(dsi, 0xd7, 0x80);
+       mipi_dsi_dcs_write_seq(dsi, 0xef, 0x20);
+       mipi_dsi_dcs_write_seq(dsi, 0xf0, 0x84);
+       mipi_dsi_dcs_write_seq(dsi, 0xff, 0x26);
+       mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01);
+       mipi_dsi_dcs_write_seq(dsi, 0x81, 0x0f);
+       mipi_dsi_dcs_write_seq(dsi, 0x83, 0x01);
+       mipi_dsi_dcs_write_seq(dsi, 0x84, 0x03);
+       mipi_dsi_dcs_write_seq(dsi, 0x85, 0x01);
+       mipi_dsi_dcs_write_seq(dsi, 0x86, 0x03);
+       mipi_dsi_dcs_write_seq(dsi, 0x87, 0x01);
+       mipi_dsi_dcs_write_seq(dsi, 0x88, 0x05);
+       mipi_dsi_dcs_write_seq(dsi, 0x8a, 0x1a);
+       mipi_dsi_dcs_write_seq(dsi, 0x8b, 0x11);
+       mipi_dsi_dcs_write_seq(dsi, 0x8c, 0x24);
+       mipi_dsi_dcs_write_seq(dsi, 0x8e, 0x42);
+       mipi_dsi_dcs_write_seq(dsi, 0x8f, 0x11);
+       mipi_dsi_dcs_write_seq(dsi, 0x90, 0x11);
+       mipi_dsi_dcs_write_seq(dsi, 0x91, 0x11);
+       mipi_dsi_dcs_write_seq(dsi, 0x9a, 0x80);
+       mipi_dsi_dcs_write_seq(dsi, 0x9b, 0x04);
+       mipi_dsi_dcs_write_seq(dsi, 0x9c, 0x00);
+       mipi_dsi_dcs_write_seq(dsi, 0x9d, 0x00);
+       mipi_dsi_dcs_write_seq(dsi, 0x9e, 0x00);
+       mipi_dsi_dcs_write_seq(dsi, 0xff, 0x27);
+       mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01);
+       mipi_dsi_dcs_write_seq(dsi, 0x01, 0x68);
+       mipi_dsi_dcs_write_seq(dsi, 0x20, 0x81);
+       mipi_dsi_dcs_write_seq(dsi, 0x21, 0x6a);
+       mipi_dsi_dcs_write_seq(dsi, 0x25, 0x81);
+       mipi_dsi_dcs_write_seq(dsi, 0x26, 0x94);
+       mipi_dsi_dcs_write_seq(dsi, 0x6e, 0x00);
+       mipi_dsi_dcs_write_seq(dsi, 0x6f, 0x00);
+       mipi_dsi_dcs_write_seq(dsi, 0x70, 0x00);
+       mipi_dsi_dcs_write_seq(dsi, 0x71, 0x00);
+       mipi_dsi_dcs_write_seq(dsi, 0x72, 0x00);
+       mipi_dsi_dcs_write_seq(dsi, 0x75, 0x00);
+       mipi_dsi_dcs_write_seq(dsi, 0x76, 0x00);
+       mipi_dsi_dcs_write_seq(dsi, 0x77, 0x00);
+       mipi_dsi_dcs_write_seq(dsi, 0x7d, 0x09);
+       mipi_dsi_dcs_write_seq(dsi, 0x7e, 0x67);
+       mipi_dsi_dcs_write_seq(dsi, 0x80, 0x23);
+       mipi_dsi_dcs_write_seq(dsi, 0x82, 0x09);
+       mipi_dsi_dcs_write_seq(dsi, 0x83, 0x67);
+       mipi_dsi_dcs_write_seq(dsi, 0x88, 0x01);
+       mipi_dsi_dcs_write_seq(dsi, 0x89, 0x10);
+       mipi_dsi_dcs_write_seq(dsi, 0xa5, 0x10);
+       mipi_dsi_dcs_write_seq(dsi, 0xa6, 0x23);
+       mipi_dsi_dcs_write_seq(dsi, 0xa7, 0x01);
+       mipi_dsi_dcs_write_seq(dsi, 0xb6, 0x40);
+       mipi_dsi_dcs_write_seq(dsi, 0xe5, 0x02);
+       mipi_dsi_dcs_write_seq(dsi, 0xe6, 0xd3);
+       mipi_dsi_dcs_write_seq(dsi, 0xeb, 0x03);
+       mipi_dsi_dcs_write_seq(dsi, 0xec, 0x28);
+       mipi_dsi_dcs_write_seq(dsi, 0xff, 0x2a);
+       mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01);
+       mipi_dsi_dcs_write_seq(dsi, 0x00, 0x91);
+       mipi_dsi_dcs_write_seq(dsi, 0x03, 0x20);
+       mipi_dsi_dcs_write_seq(dsi, 0x07, 0x50);
+       mipi_dsi_dcs_write_seq(dsi, 0x0a, 0x70);
+       mipi_dsi_dcs_write_seq(dsi, 0x0c, 0x04);
+       mipi_dsi_dcs_write_seq(dsi, 0x0d, 0x40);
+       mipi_dsi_dcs_write_seq(dsi, 0x0f, 0x01);
+       mipi_dsi_dcs_write_seq(dsi, 0x11, 0xe0);
+       mipi_dsi_dcs_write_seq(dsi, 0x15, 0x0f);
+       mipi_dsi_dcs_write_seq(dsi, 0x16, 0xa4);
+       mipi_dsi_dcs_write_seq(dsi, 0x19, 0x0f);
+       mipi_dsi_dcs_write_seq(dsi, 0x1a, 0x78);
+       mipi_dsi_dcs_write_seq(dsi, 0x1b, 0x23);
+       mipi_dsi_dcs_write_seq(dsi, 0x1d, 0x36);
+       mipi_dsi_dcs_write_seq(dsi, 0x1e, 0x3e);
+       mipi_dsi_dcs_write_seq(dsi, 0x1f, 0x3e);
+       mipi_dsi_dcs_write_seq(dsi, 0x20, 0x3e);
+       mipi_dsi_dcs_write_seq(dsi, 0x28, 0xfd);
+       mipi_dsi_dcs_write_seq(dsi, 0x29, 0x12);
+       mipi_dsi_dcs_write_seq(dsi, 0x2a, 0xe1);
+       mipi_dsi_dcs_write_seq(dsi, 0x2d, 0x0a);
+       mipi_dsi_dcs_write_seq(dsi, 0x30, 0x49);
+       mipi_dsi_dcs_write_seq(dsi, 0x33, 0x96);
+       mipi_dsi_dcs_write_seq(dsi, 0x34, 0xff);
+       mipi_dsi_dcs_write_seq(dsi, 0x35, 0x40);
+       mipi_dsi_dcs_write_seq(dsi, 0x36, 0xde);
+       mipi_dsi_dcs_write_seq(dsi, 0x37, 0xf9);
+       mipi_dsi_dcs_write_seq(dsi, 0x38, 0x45);
+       mipi_dsi_dcs_write_seq(dsi, 0x39, 0xd9);
+       mipi_dsi_dcs_write_seq(dsi, 0x3a, 0x49);
+       mipi_dsi_dcs_write_seq(dsi, 0x4a, 0xf0);
+       mipi_dsi_dcs_write_seq(dsi, 0x7a, 0x09);
+       mipi_dsi_dcs_write_seq(dsi, 0x7b, 0x40);
+       mipi_dsi_dcs_write_seq(dsi, 0x7f, 0xf0);
+       mipi_dsi_dcs_write_seq(dsi, 0x83, 0x0f);
+       mipi_dsi_dcs_write_seq(dsi, 0x84, 0xa4);
+       mipi_dsi_dcs_write_seq(dsi, 0x87, 0x0f);
+       mipi_dsi_dcs_write_seq(dsi, 0x88, 0x78);
+       mipi_dsi_dcs_write_seq(dsi, 0x89, 0x23);
+       mipi_dsi_dcs_write_seq(dsi, 0x8b, 0x36);
+       mipi_dsi_dcs_write_seq(dsi, 0x8c, 0x7d);
+       mipi_dsi_dcs_write_seq(dsi, 0x8d, 0x7d);
+       mipi_dsi_dcs_write_seq(dsi, 0x8e, 0x7d);
+       mipi_dsi_dcs_write_seq(dsi, 0xff, 0x20);
+       mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01);
+       mipi_dsi_dcs_write_seq(dsi, 0xb0, 0x00, 0x00, 0x00, 0x17, 0x00, 0x49, 0x00,
+                               0x6a, 0x00, 0x89, 0x00, 0x9f, 0x00, 0xb6, 0x00, 0xc8);
+       mipi_dsi_dcs_write_seq(dsi, 0xb1, 0x00, 0xd9, 0x01, 0x10, 0x01, 0x3a, 0x01,
+                               0x7a, 0x01, 0xa9, 0x01, 0xf2, 0x02, 0x2d, 0x02, 0x2e);
+       mipi_dsi_dcs_write_seq(dsi, 0xb2, 0x02, 0x64, 0x02, 0xa3, 0x02, 0xca, 0x03,
+                               0x00, 0x03, 0x1e, 0x03, 0x4a, 0x03, 0x59, 0x03, 0x6a);
+       mipi_dsi_dcs_write_seq(dsi, 0xb3, 0x03, 0x7d, 0x03, 0x93, 0x03, 0xab, 0x03,
+                               0xc8, 0x03, 0xec, 0x03, 0xfe, 0x00, 0x00);
+       mipi_dsi_dcs_write_seq(dsi, 0xb4, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x51, 0x00,
+                               0x71, 0x00, 0x90, 0x00, 0xa7, 0x00, 0xbf, 0x00, 0xd1);
+       mipi_dsi_dcs_write_seq(dsi, 0xb5, 0x00, 0xe2, 0x01, 0x1a, 0x01, 0x43, 0x01,
+                               0x83, 0x01, 0xb2, 0x01, 0xfa, 0x02, 0x34, 0x02, 0x36);
+       mipi_dsi_dcs_write_seq(dsi, 0xb6, 0x02, 0x6b, 0x02, 0xa8, 0x02, 0xd0, 0x03,
+                               0x03, 0x03, 0x21, 0x03, 0x4d, 0x03, 0x5b, 0x03, 0x6b);
+       mipi_dsi_dcs_write_seq(dsi, 0xb7, 0x03, 0x7e, 0x03, 0x94, 0x03, 0xac, 0x03,
+                               0xc8, 0x03, 0xec, 0x03, 0xfe, 0x00, 0x00);
+       mipi_dsi_dcs_write_seq(dsi, 0xb8, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x51, 0x00,
+                               0x72, 0x00, 0x92, 0x00, 0xa8, 0x00, 0xbf, 0x00, 0xd1);
+       mipi_dsi_dcs_write_seq(dsi, 0xb9, 0x00, 0xe2, 0x01, 0x18, 0x01, 0x42, 0x01,
+                               0x81, 0x01, 0xaf, 0x01, 0xf5, 0x02, 0x2f, 0x02, 0x31);
+       mipi_dsi_dcs_write_seq(dsi, 0xba, 0x02, 0x68, 0x02, 0xa6, 0x02, 0xcd, 0x03,
+                               0x01, 0x03, 0x1f, 0x03, 0x4a, 0x03, 0x59, 0x03, 0x6a);
+       mipi_dsi_dcs_write_seq(dsi, 0xbb, 0x03, 0x7d, 0x03, 0x93, 0x03, 0xab, 0x03,
+                               0xc8, 0x03, 0xec, 0x03, 0xfe, 0x00, 0x00);
+       mipi_dsi_dcs_write_seq(dsi, 0xff, 0x21);
+       mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01);
+       mipi_dsi_dcs_write_seq(dsi, 0xb0, 0x00, 0x00, 0x00, 0x17, 0x00, 0x49, 0x00,
+                               0x6a, 0x00, 0x89, 0x00, 0x9f, 0x00, 0xb6, 0x00, 0xc8);
+       mipi_dsi_dcs_write_seq(dsi, 0xb1, 0x00, 0xd9, 0x01, 0x10, 0x01, 0x3a, 0x01,
+                               0x7a, 0x01, 0xa9, 0x01, 0xf2, 0x02, 0x2d, 0x02, 0x2e);
+       mipi_dsi_dcs_write_seq(dsi, 0xb2, 0x02, 0x64, 0x02, 0xa3, 0x02, 0xca, 0x03,
+                               0x00, 0x03, 0x1e, 0x03, 0x4a, 0x03, 0x59, 0x03, 0x6a);
+       mipi_dsi_dcs_write_seq(dsi, 0xb3, 0x03, 0x7d, 0x03, 0x93, 0x03, 0xab, 0x03,
+                               0xc8, 0x03, 0xec, 0x03, 0xfe, 0x00, 0x00);
+       mipi_dsi_dcs_write_seq(dsi, 0xb4, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x51, 0x00,
+                               0x71, 0x00, 0x90, 0x00, 0xa7, 0x00, 0xbf, 0x00, 0xd1);
+       mipi_dsi_dcs_write_seq(dsi, 0xb5, 0x00, 0xe2, 0x01, 0x1a, 0x01, 0x43, 0x01,
+                               0x83, 0x01, 0xb2, 0x01, 0xfa, 0x02, 0x34, 0x02, 0x36);
+       mipi_dsi_dcs_write_seq(dsi, 0xb6, 0x02, 0x6b, 0x02, 0xa8, 0x02, 0xd0, 0x03,
+                               0x03, 0x03, 0x21, 0x03, 0x4d, 0x03, 0x5b, 0x03, 0x6b);
+       mipi_dsi_dcs_write_seq(dsi, 0xb7, 0x03, 0x7e, 0x03, 0x94, 0x03, 0xac, 0x03,
+                               0xc8, 0x03, 0xec, 0x03, 0xfe, 0x00, 0x00);
+       mipi_dsi_dcs_write_seq(dsi, 0xb8, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x51, 0x00,
+                               0x72, 0x00, 0x92, 0x00, 0xa8, 0x00, 0xbf, 0x00, 0xd1);
+       mipi_dsi_dcs_write_seq(dsi, 0xb9, 0x00, 0xe2, 0x01, 0x18, 0x01, 0x42, 0x01,
+                               0x81, 0x01, 0xaf, 0x01, 0xf5, 0x02, 0x2f, 0x02, 0x31);
+       mipi_dsi_dcs_write_seq(dsi, 0xba, 0x02, 0x68, 0x02, 0xa6, 0x02, 0xcd, 0x03,
+                               0x01, 0x03, 0x1f, 0x03, 0x4a, 0x03, 0x59, 0x03, 0x6a);
+       mipi_dsi_dcs_write_seq(dsi, 0xbb, 0x03, 0x7d, 0x03, 0x93, 0x03, 0xab, 0x03,
+                               0xc8, 0x03, 0xec, 0x03, 0xfe, 0x00, 0x00);
+       mipi_dsi_dcs_write_seq(dsi, 0xff, 0x2c);
+       mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01);
+       mipi_dsi_dcs_write_seq(dsi, 0x61, 0x1f);
+       mipi_dsi_dcs_write_seq(dsi, 0x62, 0x1f);
+       mipi_dsi_dcs_write_seq(dsi, 0x7e, 0x03);
+       mipi_dsi_dcs_write_seq(dsi, 0x6a, 0x14);
+       mipi_dsi_dcs_write_seq(dsi, 0x6b, 0x36);
+       mipi_dsi_dcs_write_seq(dsi, 0x6c, 0x36);
+       mipi_dsi_dcs_write_seq(dsi, 0x6d, 0x36);
+       mipi_dsi_dcs_write_seq(dsi, 0x53, 0x04);
+       mipi_dsi_dcs_write_seq(dsi, 0x54, 0x04);
+       mipi_dsi_dcs_write_seq(dsi, 0x55, 0x04);
+       mipi_dsi_dcs_write_seq(dsi, 0x56, 0x0f);
+       mipi_dsi_dcs_write_seq(dsi, 0x58, 0x0f);
+       mipi_dsi_dcs_write_seq(dsi, 0x59, 0x0f);
+       mipi_dsi_dcs_write_seq(dsi, 0xff, 0xf0);
+       mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01);
+       mipi_dsi_dcs_write_seq(dsi, 0x5a, 0x00);
+
+       mipi_dsi_dcs_write_seq(dsi, 0xff, 0x10);
+       mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01);
+       mipi_dsi_dcs_write_seq(dsi, 0x51, 0xff);
+       mipi_dsi_dcs_write_seq(dsi, 0x53, 0x24);
+       mipi_dsi_dcs_write_seq(dsi, 0x55, 0x01);
+
+       return 0;
+}
+
+static int nt36672e_power_on(struct nt36672e_panel *ctx)
+{
+       struct mipi_dsi_device *dsi = ctx->dsi;
+       int ret, i;
+
+       for (i = 0; i < ARRAY_SIZE(ctx->supplies); i++) {
+               ret = regulator_set_load(ctx->supplies[i].consumer,
+                               regulator_enable_loads[i]);
+               if (ret) {
+                       dev_err(&dsi->dev, "regulator set load failed for supply %s: %d\n",
+                               ctx->supplies[i].supply, ret);
+                       return ret;
+               }
+       }
+
+       ret = regulator_bulk_enable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
+       if (ret < 0) {
+               dev_err(&dsi->dev, "regulator bulk enable failed: %d\n", ret);
+               return ret;
+       }
+
+       /*
+        * Reset sequence of nt36672e panel requires the panel to be out of reset
+        * for 10ms, followed by being held in reset for 10ms and then out again.
+        */
+       gpiod_set_value(ctx->reset_gpio, 1);
+       usleep_range(10000, 20000);
+       gpiod_set_value(ctx->reset_gpio, 0);
+       usleep_range(10000, 20000);
+       gpiod_set_value(ctx->reset_gpio, 1);
+       usleep_range(10000, 20000);
+
+       return 0;
+}
+
+static int nt36672e_power_off(struct nt36672e_panel *ctx)
+{
+       struct mipi_dsi_device *dsi = ctx->dsi;
+       int ret = 0;
+       int i;
+
+       gpiod_set_value(ctx->reset_gpio, 0);
+
+       for (i = 0; i < ARRAY_SIZE(ctx->supplies); i++) {
+               ret = regulator_set_load(ctx->supplies[i].consumer,
+                               regulator_disable_loads[i]);
+               if (ret) {
+                       dev_err(&dsi->dev, "regulator set load failed for supply %s: %d\n",
+                               ctx->supplies[i].supply, ret);
+                       return ret;
+               }
+       }
+
+       ret = regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
+       if (ret)
+               dev_err(&dsi->dev, "regulator bulk disable failed: %d\n", ret);
+
+       return ret;
+}
+
+static int nt36672e_on(struct nt36672e_panel *ctx)
+{
+       struct mipi_dsi_device *dsi = ctx->dsi;
+       const struct panel_desc *desc = ctx->desc;
+       int ret = 0;
+
+       dsi->mode_flags |= MIPI_DSI_MODE_LPM;
+
+       if (desc->init_sequence) {
+               ret = desc->init_sequence(dsi);
+               if (ret < 0) {
+                       dev_err(&dsi->dev, "panel init sequence failed: %d\n", ret);
+                       return ret;
+               }
+       }
+
+       ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
+       if (ret < 0) {
+               dev_err(&dsi->dev, "Failed to exit sleep mode: %d\n", ret);
+               return ret;
+       }
+       msleep(120);
+
+       ret = mipi_dsi_dcs_set_display_on(dsi);
+       if (ret < 0) {
+               dev_err(&dsi->dev, "Failed to set display on: %d\n", ret);
+               return ret;
+       }
+       msleep(100);
+
+       return 0;
+}
+
+static int nt36672e_off(struct nt36672e_panel *ctx)
+{
+       struct mipi_dsi_device *dsi = ctx->dsi;
+       int ret = 0;
+
+       dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
+
+       ret = mipi_dsi_dcs_set_display_off(dsi);
+       if (ret < 0) {
+               dev_err(&dsi->dev, "Failed to set display off: %d\n", ret);
+               return ret;
+       }
+       msleep(20);
+
+       ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
+       if (ret < 0) {
+               dev_err(&dsi->dev, "Failed to enter sleep mode: %d\n", ret);
+               return ret;
+       }
+       msleep(60);
+
+       return 0;
+}
+
+static int nt36672e_panel_prepare(struct drm_panel *panel)
+{
+       struct nt36672e_panel *ctx = to_nt36672e_panel(panel);
+       struct mipi_dsi_device *dsi = ctx->dsi;
+       int ret = 0;
+
+       ret = nt36672e_power_on(ctx);
+       if (ret < 0)
+               return ret;
+
+       ret = nt36672e_on(ctx);
+       if (ret < 0) {
+               dev_err(&dsi->dev, "Failed to initialize panel: %d\n", ret);
+               if (nt36672e_power_off(ctx))
+                       dev_err(&dsi->dev, "power off failed\n");
+               return ret;
+       }
+
+       return 0;
+}
+
+static int nt36672e_panel_unprepare(struct drm_panel *panel)
+{
+       struct nt36672e_panel *ctx = to_nt36672e_panel(panel);
+       struct mipi_dsi_device *dsi = ctx->dsi;
+       int ret = 0;
+
+       ret = nt36672e_off(ctx);
+       if (ret < 0)
+               dev_err(&dsi->dev, "Failed to un-initialize panel: %d\n", ret);
+
+       ret = nt36672e_power_off(ctx);
+       if (ret < 0)
+               dev_err(&dsi->dev, "power off failed: %d\n", ret);
+
+       return 0;
+}
+
+static const struct drm_display_mode nt36672e_1080x2408_60hz = {
+       .name = "1080x2408",
+       .clock = 181690,
+       .hdisplay = 1080,
+       .hsync_start = 1080 + 76,
+       .hsync_end = 1080 + 76 + 12,
+       .htotal = 1080 + 76 + 12 + 56,
+       .vdisplay = 2408,
+       .vsync_start = 2408 + 46,
+       .vsync_end = 2408 + 46 + 10,
+       .vtotal = 2408 + 46 + 10 + 10,
+       .flags = 0,
+};
+
+static const struct panel_desc nt36672e_panel_desc = {
+       .display_mode = &nt36672e_1080x2408_60hz,
+       .width_mm = 74,
+       .height_mm = 131,
+       .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_LPM | MIPI_DSI_CLOCK_NON_CONTINUOUS,
+       .format = MIPI_DSI_FMT_RGB888,
+       .lanes = 4,
+       .panel_name = "nt36672e fhd plus panel",
+       .init_sequence = nt36672e_1080x2408_60hz_init,
+};
+
+static int nt36672e_panel_get_modes(struct drm_panel *panel, struct drm_connector *connector)
+{
+       struct nt36672e_panel *ctx = to_nt36672e_panel(panel);
+       struct drm_display_mode *mode;
+
+       mode = drm_mode_duplicate(connector->dev, ctx->desc->display_mode);
+       if (!mode)
+               return -ENOMEM;
+
+       drm_mode_set_name(mode);
+
+       mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
+       connector->display_info.width_mm = ctx->desc->width_mm;
+       connector->display_info.height_mm = ctx->desc->height_mm;
+       drm_mode_probed_add(connector, mode);
+
+       return 1;
+}
+
+static const struct drm_panel_funcs nt36672e_drm_funcs = {
+       .prepare = nt36672e_panel_prepare,
+       .unprepare = nt36672e_panel_unprepare,
+       .get_modes = nt36672e_panel_get_modes,
+};
+
+static int nt36672e_panel_probe(struct mipi_dsi_device *dsi)
+{
+       struct device *dev = &dsi->dev;
+       struct nt36672e_panel *ctx;
+       int i, ret = 0;
+
+       ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
+       if (!ctx)
+               return -ENOMEM;
+
+       ctx->desc = of_device_get_match_data(dev);
+       if (!ctx->desc) {
+               dev_err(dev, "missing device configuration\n");
+               return -ENODEV;
+       }
+
+       for (i = 0; i < ARRAY_SIZE(ctx->supplies); i++)
+               ctx->supplies[i].supply = regulator_names[i];
+
+       ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(ctx->supplies),
+                       ctx->supplies);
+       if (ret < 0)
+               return ret;
+
+       ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
+       if (IS_ERR(ctx->reset_gpio))
+               return dev_err_probe(dev, PTR_ERR(ctx->reset_gpio), "Failed to get reset-gpios\n");
+
+       ctx->dsi = dsi;
+       mipi_dsi_set_drvdata(dsi, ctx);
+
+       dsi->lanes = ctx->desc->lanes;
+       dsi->format = ctx->desc->format;
+       dsi->mode_flags = ctx->desc->mode_flags;
+
+       drm_panel_init(&ctx->panel, dev, &nt36672e_drm_funcs, DRM_MODE_CONNECTOR_DSI);
+
+       ret = drm_panel_of_backlight(&ctx->panel);
+       if (ret)
+               return dev_err_probe(dev, ret, "Failed to get backlight\n");
+
+       ctx->panel.prepare_prev_first = true;
+
+       drm_panel_add(&ctx->panel);
+
+       ret = mipi_dsi_attach(dsi);
+       if (ret < 0) {
+               dev_err(dev, "Failed to attach to DSI host: %d\n", ret);
+               goto err_dsi_attach;
+       }
+
+       return 0;
+
+err_dsi_attach:
+       drm_panel_remove(&ctx->panel);
+       return ret;
+}
+
+static void nt36672e_panel_remove(struct mipi_dsi_device *dsi)
+{
+       struct nt36672e_panel *ctx = mipi_dsi_get_drvdata(dsi);
+
+       mipi_dsi_detach(ctx->dsi);
+       mipi_dsi_device_unregister(ctx->dsi);
+
+       drm_panel_remove(&ctx->panel);
+}
+
+static const struct of_device_id nt36672e_of_match[] = {
+       {
+               .compatible = "novatek,nt36672e",
+               .data = &nt36672e_panel_desc,
+       },
+       { }
+};
+MODULE_DEVICE_TABLE(of, nt36672e_of_match);
+
+static struct mipi_dsi_driver nt36672e_panel_driver = {
+       .driver = {
+               .name = "panel-novatek-nt36672e",
+               .of_match_table = nt36672e_of_match,
+       },
+       .probe = nt36672e_panel_probe,
+       .remove = nt36672e_panel_remove,
+};
+module_mipi_dsi_driver(nt36672e_panel_driver);
+
+MODULE_AUTHOR("Ritesh Kumar <quic_riteshk@quicinc.com>");
+MODULE_DESCRIPTION("Novatek NT36672E DSI Panel Driver");
+MODULE_LICENSE("GPL");
index 2214cb09678cd6a234359c2cb7972c9beb3f5851..c62281c0258c5d7d0fa24783f9cf55a9e3306d0c 100644 (file)
@@ -1980,6 +1980,33 @@ static const struct panel_desc edt_etml0700y5dha = {
        .connector_type = DRM_MODE_CONNECTOR_LVDS,
 };
 
+static const struct display_timing edt_etml1010g3dra_timing = {
+       .pixelclock = { 66300000, 72400000, 78900000 },
+       .hactive = { 1280, 1280, 1280 },
+       .hfront_porch = { 12, 72, 132 },
+       .hback_porch = { 86, 86, 86 },
+       .hsync_len = { 2, 2, 2 },
+       .vactive = { 800, 800, 800 },
+       .vfront_porch = { 1, 15, 49 },
+       .vback_porch = { 21, 21, 21 },
+       .vsync_len = { 2, 2, 2 },
+       .flags = DISPLAY_FLAGS_VSYNC_LOW | DISPLAY_FLAGS_HSYNC_LOW |
+                DISPLAY_FLAGS_DE_HIGH,
+};
+
+static const struct panel_desc edt_etml1010g3dra = {
+       .timings = &edt_etml1010g3dra_timing,
+       .num_timings = 1,
+       .bpc = 8,
+       .size = {
+               .width = 216,
+               .height = 135,
+       },
+       .bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG,
+       .bus_flags = DRM_BUS_FLAG_DE_HIGH,
+       .connector_type = DRM_MODE_CONNECTOR_LVDS,
+};
+
 static const struct drm_display_mode edt_etmv570g2dhu_mode = {
        .clock = 25175,
        .hdisplay = 640,
@@ -2754,21 +2781,21 @@ static const struct panel_desc lemaker_bl035_rgb_002 = {
        .bus_flags = DRM_BUS_FLAG_DE_LOW,
 };
 
-static const struct drm_display_mode lg_lb070wv8_mode = {
-       .clock = 33246,
-       .hdisplay = 800,
-       .hsync_start = 800 + 88,
-       .hsync_end = 800 + 88 + 80,
-       .htotal = 800 + 88 + 80 + 88,
-       .vdisplay = 480,
-       .vsync_start = 480 + 10,
-       .vsync_end = 480 + 10 + 25,
-       .vtotal = 480 + 10 + 25 + 10,
+static const struct display_timing lg_lb070wv8_timing = {
+       .pixelclock = { 31950000, 33260000, 34600000 },
+       .hactive = { 800, 800, 800 },
+       .hfront_porch = { 88, 88, 88 },
+       .hback_porch = { 88, 88, 88 },
+       .hsync_len = { 80, 80, 80 },
+       .vactive = { 480, 480, 480 },
+       .vfront_porch = { 10, 10, 10 },
+       .vback_porch = { 10, 10, 10 },
+       .vsync_len = { 25, 25, 25 },
 };
 
 static const struct panel_desc lg_lb070wv8 = {
-       .modes = &lg_lb070wv8_mode,
-       .num_modes = 1,
+       .timings = &lg_lb070wv8_timing,
+       .num_timings = 1,
        .bpc = 8,
        .size = {
                .width = 151,
@@ -4421,6 +4448,9 @@ static const struct of_device_id platform_of_match[] = {
        }, {
                .compatible = "edt,etml0700y5dha",
                .data = &edt_etml0700y5dha,
+       }, {
+               .compatible = "edt,etml1010g3dra",
+               .data = &edt_etml1010g3dra,
        }, {
                .compatible = "edt,etmv570g2dhu",
                .data = &edt_etmv570g2dhu,
index ad24cdf1d99280757356f460e8b3417f1dd6c183..20fe1d2c0aaff4527a59f742657d9dbe5d5965a3 100644 (file)
@@ -9,7 +9,6 @@ config DRM_PL111
        select DRM_GEM_DMA_HELPER
        select DRM_BRIDGE
        select DRM_PANEL_BRIDGE
-       select VT_HW_CONSOLE_BINDING if FRAMEBUFFER_CONSOLE
        help
          Choose this option for DRM support for the PL111 CLCD controller.
          If M is selected the module will be called pl111_drm.
index 06a58dad5f5cf4e8b78f5aa2955e801470388c34..1e46b0a6e47871465dd6fbb4a9f97970ead95dc5 100644 (file)
@@ -66,7 +66,6 @@ void qxl_ttm_placement_from_domain(struct qxl_bo *qbo, u32 domain)
                pflag |= TTM_PL_FLAG_TOPDOWN;
 
        qbo->placement.placement = qbo->placements;
-       qbo->placement.busy_placement = qbo->placements;
        if (domain == QXL_GEM_DOMAIN_VRAM) {
                qbo->placements[c].mem_type = TTM_PL_VRAM;
                qbo->placements[c++].flags = pflag;
@@ -86,7 +85,6 @@ void qxl_ttm_placement_from_domain(struct qxl_bo *qbo, u32 domain)
                qbo->placements[c++].flags = 0;
        }
        qbo->placement.num_placement = c;
-       qbo->placement.num_busy_placement = c;
        for (i = 0; i < c; ++i) {
                qbo->placements[i].fpfn = 0;
                qbo->placements[i].lpfn = 0;
index 1a82629bce3f63323c91c89a06fca3042cd566b3..765a144cea14dc1afe76a42c90677ae954ca4950 100644 (file)
@@ -60,9 +60,7 @@ static void qxl_evict_flags(struct ttm_buffer_object *bo,
 
        if (!qxl_ttm_bo_is_qxl_bo(bo)) {
                placement->placement = &placements;
-               placement->busy_placement = &placements;
                placement->num_placement = 1;
-               placement->num_busy_placement = 1;
                return;
        }
        qbo = to_qxl_bo(bo);
index 10c0fbd9d2b441cad7d8d0e66bfb5b90bc2ff2fb..a955f8a2f7feec2460dd611edbeef7ad9e27a334 100644 (file)
@@ -78,7 +78,6 @@ void radeon_ttm_placement_from_domain(struct radeon_bo *rbo, u32 domain)
        u32 c = 0, i;
 
        rbo->placement.placement = rbo->placements;
-       rbo->placement.busy_placement = rbo->placements;
        if (domain & RADEON_GEM_DOMAIN_VRAM) {
                /* Try placing BOs which don't need CPU access outside of the
                 * CPU accessible part of VRAM
@@ -114,7 +113,6 @@ void radeon_ttm_placement_from_domain(struct radeon_bo *rbo, u32 domain)
        }
 
        rbo->placement.num_placement = c;
-       rbo->placement.num_busy_placement = c;
 
        for (i = 0; i < c; ++i) {
                if ((rbo->flags & RADEON_GEM_CPU_ACCESS) &&
index de4e6d78f1e1219f7f3e1ae402872bad52b47ed5..2078b0000e228bf17dab13cd1e6f045936fb5352 100644 (file)
@@ -92,9 +92,7 @@ static void radeon_evict_flags(struct ttm_buffer_object *bo,
 
        if (!radeon_ttm_bo_is_radeon_bo(bo)) {
                placement->placement = &placements;
-               placement->busy_placement = &placements;
                placement->num_placement = 1;
-               placement->num_busy_placement = 1;
                return;
        }
        rbo = container_of(bo, struct radeon_bo, tbo);
@@ -114,15 +112,11 @@ static void radeon_evict_flags(struct ttm_buffer_object *bo,
                         */
                        radeon_ttm_placement_from_domain(rbo, RADEON_GEM_DOMAIN_VRAM |
                                                         RADEON_GEM_DOMAIN_GTT);
-                       rbo->placement.num_busy_placement = 0;
                        for (i = 0; i < rbo->placement.num_placement; i++) {
                                if (rbo->placements[i].mem_type == TTM_PL_VRAM) {
                                        if (rbo->placements[i].fpfn < fpfn)
                                                rbo->placements[i].fpfn = fpfn;
-                               } else {
-                                       rbo->placement.busy_placement =
-                                               &rbo->placements[i];
-                                       rbo->placement.num_busy_placement = 1;
+                                       rbo->placements[0].flags |= TTM_PL_FLAG_DESIRED;
                                }
                        }
                } else
index a2cda184b2b25ccb80445cf17057c0047d775c06..058a1c8451b2d946b4a6a6ce7790d7f84815c843 100644 (file)
@@ -324,7 +324,6 @@ void radeon_uvd_force_into_uvd_segment(struct radeon_bo *rbo,
        rbo->placements[1].fpfn += (256 * 1024 * 1024) >> PAGE_SHIFT;
        rbo->placements[1].lpfn += (256 * 1024 * 1024) >> PAGE_SHIFT;
        rbo->placement.num_placement++;
-       rbo->placement.num_busy_placement++;
 }
 
 void radeon_uvd_free_handles(struct radeon_device *rdev, struct drm_file *filp)
index bd08d57486fef4b2993c8266ba844e29f3d2cb15..7069a3d4d58119254a8060c26c37e7eaf2fc82b2 100644 (file)
@@ -343,6 +343,9 @@ static int rockchip_dp_bind(struct device *dev, struct device *master,
                return ret;
        }
 
+       rockchip_drm_encoder_set_crtc_endpoint_id(&dp->encoder,
+                                                 dev->of_node, 0, 0);
+
        dp->plat_data.encoder = &dp->encoder.encoder;
 
        ret = analogix_dp_bind(dp->adp, drm_dev);
index e6fbe040ccf6a9af8f54b6220dfa6c96d4cd0ee8..1d2261643743d85d583e433b1230caeb4eb70714 100644 (file)
 #include <linux/delay.h>
 #include <linux/err.h>
 #include <linux/hdmi.h>
-#include <linux/mfd/syscon.h>
 #include <linux/mod_devicetable.h>
 #include <linux/module.h>
 #include <linux/mutex.h>
 #include <linux/platform_device.h>
 
+#include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_edid.h>
 #include <drm/drm_of.h>
 
 #include "inno_hdmi.h"
 
-struct hdmi_data_info {
-       int vic;
-       bool sink_has_audio;
-       unsigned int enc_in_format;
-       unsigned int enc_out_format;
-       unsigned int colorimetry;
+#define INNO_HDMI_MIN_TMDS_CLOCK  25000000U
+
+struct inno_hdmi_phy_config {
+       unsigned long pixelclock;
+       u8 pre_emphasis;
+       u8 voltage_level_control;
+};
+
+struct inno_hdmi_variant {
+       struct inno_hdmi_phy_config *phy_configs;
+       struct inno_hdmi_phy_config *default_phy_config;
 };
 
 struct inno_hdmi_i2c {
@@ -46,10 +51,9 @@ struct inno_hdmi_i2c {
 
 struct inno_hdmi {
        struct device *dev;
-       struct drm_device *drm_dev;
 
-       int irq;
        struct clk *pclk;
+       struct clk *refclk;
        void __iomem *regs;
 
        struct drm_connector    connector;
@@ -58,10 +62,14 @@ struct inno_hdmi {
        struct inno_hdmi_i2c *i2c;
        struct i2c_adapter *ddc;
 
-       unsigned int tmds_rate;
+       const struct inno_hdmi_variant *variant;
+};
 
-       struct hdmi_data_info   hdmi_data;
-       struct drm_display_mode previous_mode;
+struct inno_hdmi_connector_state {
+       struct drm_connector_state      base;
+       unsigned int                    enc_out_format;
+       unsigned int                    colorimetry;
+       bool                            rgb_limited_range;
 };
 
 static struct inno_hdmi *encoder_to_inno_hdmi(struct drm_encoder *encoder)
@@ -76,50 +84,16 @@ static struct inno_hdmi *connector_to_inno_hdmi(struct drm_connector *connector)
        return container_of(connector, struct inno_hdmi, connector);
 }
 
+#define to_inno_hdmi_conn_state(conn_state) \
+       container_of_const(conn_state, struct inno_hdmi_connector_state, base)
+
 enum {
-       CSC_ITU601_16_235_TO_RGB_0_255_8BIT,
-       CSC_ITU601_0_255_TO_RGB_0_255_8BIT,
-       CSC_ITU709_16_235_TO_RGB_0_255_8BIT,
        CSC_RGB_0_255_TO_ITU601_16_235_8BIT,
        CSC_RGB_0_255_TO_ITU709_16_235_8BIT,
        CSC_RGB_0_255_TO_RGB_16_235_8BIT,
 };
 
 static const char coeff_csc[][24] = {
-       /*
-        * YUV2RGB:601 SD mode(Y[16:235], UV[16:240], RGB[0:255]):
-        *   R = 1.164*Y + 1.596*V - 204
-        *   G = 1.164*Y - 0.391*U - 0.813*V + 154
-        *   B = 1.164*Y + 2.018*U - 258
-        */
-       {
-               0x04, 0xa7, 0x00, 0x00, 0x06, 0x62, 0x02, 0xcc,
-               0x04, 0xa7, 0x11, 0x90, 0x13, 0x40, 0x00, 0x9a,
-               0x04, 0xa7, 0x08, 0x12, 0x00, 0x00, 0x03, 0x02
-       },
-       /*
-        * YUV2RGB:601 SD mode(YUV[0:255],RGB[0:255]):
-        *   R = Y + 1.402*V - 248
-        *   G = Y - 0.344*U - 0.714*V + 135
-        *   B = Y + 1.772*U - 227
-        */
-       {
-               0x04, 0x00, 0x00, 0x00, 0x05, 0x9b, 0x02, 0xf8,
-               0x04, 0x00, 0x11, 0x60, 0x12, 0xdb, 0x00, 0x87,
-               0x04, 0x00, 0x07, 0x16, 0x00, 0x00, 0x02, 0xe3
-       },
-       /*
-        * YUV2RGB:709 HD mode(Y[16:235],UV[16:240],RGB[0:255]):
-        *   R = 1.164*Y + 1.793*V - 248
-        *   G = 1.164*Y - 0.213*U - 0.534*V + 77
-        *   B = 1.164*Y + 2.115*U - 289
-        */
-       {
-               0x04, 0xa7, 0x00, 0x00, 0x07, 0x2c, 0x02, 0xf8,
-               0x04, 0xa7, 0x10, 0xda, 0x12, 0x22, 0x00, 0x4d,
-               0x04, 0xa7, 0x08, 0x74, 0x00, 0x00, 0x03, 0x21
-       },
-
        /*
         * RGB2YUV:601 SD mode:
         *   Cb = -0.291G - 0.148R + 0.439B + 128
@@ -155,6 +129,36 @@ static const char coeff_csc[][24] = {
        },
 };
 
+static struct inno_hdmi_phy_config rk3036_hdmi_phy_configs[] = {
+       {  74250000, 0x3f, 0xbb },
+       { 165000000, 0x6f, 0xbb },
+       {      ~0UL, 0x00, 0x00 }
+};
+
+static struct inno_hdmi_phy_config rk3128_hdmi_phy_configs[] = {
+       {  74250000, 0x3f, 0xaa },
+       { 165000000, 0x5f, 0xaa },
+       {      ~0UL, 0x00, 0x00 }
+};
+
+static int inno_hdmi_find_phy_config(struct inno_hdmi *hdmi,
+                                    unsigned long pixelclk)
+{
+       const struct inno_hdmi_phy_config *phy_configs =
+                                               hdmi->variant->phy_configs;
+       int i;
+
+       for (i = 0; phy_configs[i].pixelclock != ~0UL; i++) {
+               if (pixelclk <= phy_configs[i].pixelclock)
+                       return i;
+       }
+
+       DRM_DEV_DEBUG(hdmi->dev, "No phy configuration for pixelclock %lu\n",
+                     pixelclk);
+
+       return -EINVAL;
+}
+
 static inline u8 hdmi_readb(struct inno_hdmi *hdmi, u16 offset)
 {
        return readl_relaxed(hdmi->regs + (offset) * 0x04);
@@ -174,11 +178,11 @@ static inline void hdmi_modb(struct inno_hdmi *hdmi, u16 offset,
        hdmi_writeb(hdmi, offset, temp);
 }
 
-static void inno_hdmi_i2c_init(struct inno_hdmi *hdmi)
+static void inno_hdmi_i2c_init(struct inno_hdmi *hdmi, unsigned long long rate)
 {
-       int ddc_bus_freq;
+       unsigned long long ddc_bus_freq = rate >> 2;
 
-       ddc_bus_freq = (hdmi->tmds_rate >> 2) / HDMI_SCL_RATE;
+       do_div(ddc_bus_freq, HDMI_SCL_RATE);
 
        hdmi_writeb(hdmi, DDC_BUS_FREQ_L, ddc_bus_freq & 0xFF);
        hdmi_writeb(hdmi, DDC_BUS_FREQ_H, (ddc_bus_freq >> 8) & 0xFF);
@@ -196,38 +200,44 @@ static void inno_hdmi_sys_power(struct inno_hdmi *hdmi, bool enable)
                hdmi_modb(hdmi, HDMI_SYS_CTRL, m_POWER, v_PWR_OFF);
 }
 
-static void inno_hdmi_set_pwr_mode(struct inno_hdmi *hdmi, int mode)
+static void inno_hdmi_standby(struct inno_hdmi *hdmi)
 {
-       switch (mode) {
-       case NORMAL:
-               inno_hdmi_sys_power(hdmi, false);
+       inno_hdmi_sys_power(hdmi, false);
 
-               hdmi_writeb(hdmi, HDMI_PHY_PRE_EMPHASIS, 0x6f);
-               hdmi_writeb(hdmi, HDMI_PHY_DRIVER, 0xbb);
+       hdmi_writeb(hdmi, HDMI_PHY_DRIVER, 0x00);
+       hdmi_writeb(hdmi, HDMI_PHY_PRE_EMPHASIS, 0x00);
+       hdmi_writeb(hdmi, HDMI_PHY_CHG_PWR, 0x00);
+       hdmi_writeb(hdmi, HDMI_PHY_SYS_CTL, 0x15);
+};
 
-               hdmi_writeb(hdmi, HDMI_PHY_SYS_CTL, 0x15);
-               hdmi_writeb(hdmi, HDMI_PHY_SYS_CTL, 0x14);
-               hdmi_writeb(hdmi, HDMI_PHY_SYS_CTL, 0x10);
-               hdmi_writeb(hdmi, HDMI_PHY_CHG_PWR, 0x0f);
-               hdmi_writeb(hdmi, HDMI_PHY_SYNC, 0x00);
-               hdmi_writeb(hdmi, HDMI_PHY_SYNC, 0x01);
+static void inno_hdmi_power_up(struct inno_hdmi *hdmi,
+                              unsigned long mpixelclock)
+{
+       struct inno_hdmi_phy_config *phy_config;
+       int ret = inno_hdmi_find_phy_config(hdmi, mpixelclock);
 
-               inno_hdmi_sys_power(hdmi, true);
-               break;
+       if (ret < 0) {
+               phy_config = hdmi->variant->default_phy_config;
+               DRM_DEV_ERROR(hdmi->dev,
+                             "Using default phy configuration for TMDS rate %lu",
+                             mpixelclock);
+       } else {
+               phy_config = &hdmi->variant->phy_configs[ret];
+       }
 
-       case LOWER_PWR:
-               inno_hdmi_sys_power(hdmi, false);
-               hdmi_writeb(hdmi, HDMI_PHY_DRIVER, 0x00);
-               hdmi_writeb(hdmi, HDMI_PHY_PRE_EMPHASIS, 0x00);
-               hdmi_writeb(hdmi, HDMI_PHY_CHG_PWR, 0x00);
-               hdmi_writeb(hdmi, HDMI_PHY_SYS_CTL, 0x15);
+       inno_hdmi_sys_power(hdmi, false);
 
-               break;
+       hdmi_writeb(hdmi, HDMI_PHY_PRE_EMPHASIS, phy_config->pre_emphasis);
+       hdmi_writeb(hdmi, HDMI_PHY_DRIVER, phy_config->voltage_level_control);
+       hdmi_writeb(hdmi, HDMI_PHY_SYS_CTL, 0x15);
+       hdmi_writeb(hdmi, HDMI_PHY_SYS_CTL, 0x14);
+       hdmi_writeb(hdmi, HDMI_PHY_SYS_CTL, 0x10);
+       hdmi_writeb(hdmi, HDMI_PHY_CHG_PWR, 0x0f);
+       hdmi_writeb(hdmi, HDMI_PHY_SYNC, 0x00);
+       hdmi_writeb(hdmi, HDMI_PHY_SYNC, 0x01);
 
-       default:
-               DRM_DEV_ERROR(hdmi->dev, "Unknown power mode %d\n", mode);
-       }
-}
+       inno_hdmi_sys_power(hdmi, true);
+};
 
 static void inno_hdmi_reset(struct inno_hdmi *hdmi)
 {
@@ -244,75 +254,96 @@ static void inno_hdmi_reset(struct inno_hdmi *hdmi)
        val = v_REG_CLK_INV | v_REG_CLK_SOURCE_SYS | v_PWR_ON | v_INT_POL_HIGH;
        hdmi_modb(hdmi, HDMI_SYS_CTRL, msk, val);
 
-       inno_hdmi_set_pwr_mode(hdmi, NORMAL);
+       inno_hdmi_standby(hdmi);
 }
 
-static int inno_hdmi_upload_frame(struct inno_hdmi *hdmi, int setup_rc,
-                                 union hdmi_infoframe *frame, u32 frame_index,
-                                 u32 mask, u32 disable, u32 enable)
+static void inno_hdmi_disable_frame(struct inno_hdmi *hdmi,
+                                   enum hdmi_infoframe_type type)
 {
-       if (mask)
-               hdmi_modb(hdmi, HDMI_PACKET_SEND_AUTO, mask, disable);
+       struct drm_connector *connector = &hdmi->connector;
 
-       hdmi_writeb(hdmi, HDMI_CONTROL_PACKET_BUF_INDEX, frame_index);
-
-       if (setup_rc >= 0) {
-               u8 packed_frame[HDMI_MAXIMUM_INFO_FRAME_SIZE];
-               ssize_t rc, i;
+       if (type != HDMI_INFOFRAME_TYPE_AVI) {
+               drm_err(connector->dev,
+                       "Unsupported infoframe type: %u\n", type);
+               return;
+       }
 
-               rc = hdmi_infoframe_pack(frame, packed_frame,
-                                        sizeof(packed_frame));
-               if (rc < 0)
-                       return rc;
+       hdmi_writeb(hdmi, HDMI_CONTROL_PACKET_BUF_INDEX, INFOFRAME_AVI);
+}
 
-               for (i = 0; i < rc; i++)
-                       hdmi_writeb(hdmi, HDMI_CONTROL_PACKET_ADDR + i,
-                                   packed_frame[i]);
+static int inno_hdmi_upload_frame(struct inno_hdmi *hdmi,
+                                 union hdmi_infoframe *frame, enum hdmi_infoframe_type type)
+{
+       struct drm_connector *connector = &hdmi->connector;
+       u8 packed_frame[HDMI_MAXIMUM_INFO_FRAME_SIZE];
+       ssize_t rc, i;
 
-               if (mask)
-                       hdmi_modb(hdmi, HDMI_PACKET_SEND_AUTO, mask, enable);
+       if (type != HDMI_INFOFRAME_TYPE_AVI) {
+               drm_err(connector->dev,
+                       "Unsupported infoframe type: %u\n", type);
+               return 0;
        }
 
-       return setup_rc;
-}
+       inno_hdmi_disable_frame(hdmi, type);
 
-static int inno_hdmi_config_video_vsi(struct inno_hdmi *hdmi,
-                                     struct drm_display_mode *mode)
-{
-       union hdmi_infoframe frame;
-       int rc;
+       rc = hdmi_infoframe_pack(frame, packed_frame,
+                                sizeof(packed_frame));
+       if (rc < 0)
+               return rc;
 
-       rc = drm_hdmi_vendor_infoframe_from_display_mode(&frame.vendor.hdmi,
-                                                        &hdmi->connector,
-                                                        mode);
+       for (i = 0; i < rc; i++)
+               hdmi_writeb(hdmi, HDMI_CONTROL_PACKET_ADDR + i,
+                           packed_frame[i]);
 
-       return inno_hdmi_upload_frame(hdmi, rc, &frame, INFOFRAME_VSI,
-               m_PACKET_VSI_EN, v_PACKET_VSI_EN(0), v_PACKET_VSI_EN(1));
+       return 0;
 }
 
 static int inno_hdmi_config_video_avi(struct inno_hdmi *hdmi,
                                      struct drm_display_mode *mode)
 {
+       struct drm_connector *connector = &hdmi->connector;
+       struct drm_connector_state *conn_state = connector->state;
+       struct inno_hdmi_connector_state *inno_conn_state =
+                                       to_inno_hdmi_conn_state(conn_state);
        union hdmi_infoframe frame;
        int rc;
 
        rc = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi,
                                                      &hdmi->connector,
                                                      mode);
+       if (rc) {
+               inno_hdmi_disable_frame(hdmi, HDMI_INFOFRAME_TYPE_AVI);
+               return rc;
+       }
 
-       if (hdmi->hdmi_data.enc_out_format == HDMI_COLORSPACE_YUV444)
+       if (inno_conn_state->enc_out_format == HDMI_COLORSPACE_YUV444)
                frame.avi.colorspace = HDMI_COLORSPACE_YUV444;
-       else if (hdmi->hdmi_data.enc_out_format == HDMI_COLORSPACE_YUV422)
+       else if (inno_conn_state->enc_out_format == HDMI_COLORSPACE_YUV422)
                frame.avi.colorspace = HDMI_COLORSPACE_YUV422;
        else
                frame.avi.colorspace = HDMI_COLORSPACE_RGB;
 
-       return inno_hdmi_upload_frame(hdmi, rc, &frame, INFOFRAME_AVI, 0, 0, 0);
+       if (inno_conn_state->enc_out_format == HDMI_COLORSPACE_RGB) {
+               drm_hdmi_avi_infoframe_quant_range(&frame.avi,
+                                                  connector, mode,
+                                                  inno_conn_state->rgb_limited_range ?
+                                                  HDMI_QUANTIZATION_RANGE_LIMITED :
+                                                  HDMI_QUANTIZATION_RANGE_FULL);
+       } else {
+               frame.avi.quantization_range = HDMI_QUANTIZATION_RANGE_DEFAULT;
+               frame.avi.ycc_quantization_range =
+                       HDMI_YCC_QUANTIZATION_RANGE_LIMITED;
+       }
+
+       return inno_hdmi_upload_frame(hdmi, &frame, HDMI_INFOFRAME_TYPE_AVI);
 }
 
 static int inno_hdmi_config_video_csc(struct inno_hdmi *hdmi)
 {
-       struct hdmi_data_info *data = &hdmi->hdmi_data;
+       struct drm_connector *connector = &hdmi->connector;
+       struct drm_connector_state *conn_state = connector->state;
+       struct inno_hdmi_connector_state *inno_conn_state =
+                                       to_inno_hdmi_conn_state(conn_state);
        int c0_c2_change = 0;
        int csc_enable = 0;
        int csc_mode = 0;
@@ -330,9 +361,14 @@ static int inno_hdmi_config_video_csc(struct inno_hdmi *hdmi)
                v_VIDEO_INPUT_CSP(0);
        hdmi_writeb(hdmi, HDMI_VIDEO_CONTRL2, value);
 
-       if (data->enc_in_format == data->enc_out_format) {
-               if ((data->enc_in_format == HDMI_COLORSPACE_RGB) ||
-                   (data->enc_in_format >= HDMI_COLORSPACE_YUV444)) {
+       if (inno_conn_state->enc_out_format == HDMI_COLORSPACE_RGB) {
+               if (inno_conn_state->rgb_limited_range) {
+                       csc_mode = CSC_RGB_0_255_TO_RGB_16_235_8BIT;
+                       auto_csc = AUTO_CSC_DISABLE;
+                       c0_c2_change = C0_C2_CHANGE_DISABLE;
+                       csc_enable = v_CSC_ENABLE;
+
+               } else {
                        value = v_SOF_DISABLE | v_COLOR_DEPTH_NOT_INDICATED(1);
                        hdmi_writeb(hdmi, HDMI_VIDEO_CONTRL3, value);
 
@@ -342,35 +378,21 @@ static int inno_hdmi_config_video_csc(struct inno_hdmi *hdmi)
                                  v_VIDEO_C0_C2_SWAP(C0_C2_CHANGE_DISABLE));
                        return 0;
                }
-       }
-
-       if (data->colorimetry == HDMI_COLORIMETRY_ITU_601) {
-               if ((data->enc_in_format == HDMI_COLORSPACE_RGB) &&
-                   (data->enc_out_format == HDMI_COLORSPACE_YUV444)) {
-                       csc_mode = CSC_RGB_0_255_TO_ITU601_16_235_8BIT;
-                       auto_csc = AUTO_CSC_DISABLE;
-                       c0_c2_change = C0_C2_CHANGE_DISABLE;
-                       csc_enable = v_CSC_ENABLE;
-               } else if ((data->enc_in_format == HDMI_COLORSPACE_YUV444) &&
-                          (data->enc_out_format == HDMI_COLORSPACE_RGB)) {
-                       csc_mode = CSC_ITU601_16_235_TO_RGB_0_255_8BIT;
-                       auto_csc = AUTO_CSC_ENABLE;
-                       c0_c2_change = C0_C2_CHANGE_DISABLE;
-                       csc_enable = v_CSC_DISABLE;
-               }
        } else {
-               if ((data->enc_in_format == HDMI_COLORSPACE_RGB) &&
-                   (data->enc_out_format == HDMI_COLORSPACE_YUV444)) {
-                       csc_mode = CSC_RGB_0_255_TO_ITU709_16_235_8BIT;
-                       auto_csc = AUTO_CSC_DISABLE;
-                       c0_c2_change = C0_C2_CHANGE_DISABLE;
-                       csc_enable = v_CSC_ENABLE;
-               } else if ((data->enc_in_format == HDMI_COLORSPACE_YUV444) &&
-                          (data->enc_out_format == HDMI_COLORSPACE_RGB)) {
-                       csc_mode = CSC_ITU709_16_235_TO_RGB_0_255_8BIT;
-                       auto_csc = AUTO_CSC_ENABLE;
-                       c0_c2_change = C0_C2_CHANGE_DISABLE;
-                       csc_enable = v_CSC_DISABLE;
+               if (inno_conn_state->colorimetry == HDMI_COLORIMETRY_ITU_601) {
+                       if (inno_conn_state->enc_out_format == HDMI_COLORSPACE_YUV444) {
+                               csc_mode = CSC_RGB_0_255_TO_ITU601_16_235_8BIT;
+                               auto_csc = AUTO_CSC_DISABLE;
+                               c0_c2_change = C0_C2_CHANGE_DISABLE;
+                               csc_enable = v_CSC_ENABLE;
+                       }
+               } else {
+                       if (inno_conn_state->enc_out_format == HDMI_COLORSPACE_YUV444) {
+                               csc_mode = CSC_RGB_0_255_TO_ITU709_16_235_8BIT;
+                               auto_csc = AUTO_CSC_DISABLE;
+                               c0_c2_change = C0_C2_CHANGE_DISABLE;
+                               csc_enable = v_CSC_ENABLE;
+                       }
                }
        }
 
@@ -411,7 +433,7 @@ static int inno_hdmi_config_video_timing(struct inno_hdmi *hdmi,
        hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HBLANK_L, value & 0xFF);
        hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HBLANK_H, (value >> 8) & 0xFF);
 
-       value = mode->hsync_start - mode->hdisplay;
+       value = mode->htotal - mode->hsync_start;
        hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HDELAY_L, value & 0xFF);
        hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HDELAY_H, (value >> 8) & 0xFF);
 
@@ -426,7 +448,7 @@ static int inno_hdmi_config_video_timing(struct inno_hdmi *hdmi,
        value = mode->vtotal - mode->vdisplay;
        hdmi_writeb(hdmi, HDMI_VIDEO_EXT_VBLANK, value & 0xFF);
 
-       value = mode->vsync_start - mode->vdisplay;
+       value = mode->vtotal - mode->vsync_start;
        hdmi_writeb(hdmi, HDMI_VIDEO_EXT_VDELAY, value & 0xFF);
 
        value = mode->vsync_end - mode->vsync_start;
@@ -443,19 +465,7 @@ static int inno_hdmi_setup(struct inno_hdmi *hdmi,
                           struct drm_display_mode *mode)
 {
        struct drm_display_info *display = &hdmi->connector.display_info;
-
-       hdmi->hdmi_data.vic = drm_match_cea_mode(mode);
-
-       hdmi->hdmi_data.enc_in_format = HDMI_COLORSPACE_RGB;
-       hdmi->hdmi_data.enc_out_format = HDMI_COLORSPACE_RGB;
-
-       if ((hdmi->hdmi_data.vic == 6) || (hdmi->hdmi_data.vic == 7) ||
-           (hdmi->hdmi_data.vic == 21) || (hdmi->hdmi_data.vic == 22) ||
-           (hdmi->hdmi_data.vic == 2) || (hdmi->hdmi_data.vic == 3) ||
-           (hdmi->hdmi_data.vic == 17) || (hdmi->hdmi_data.vic == 18))
-               hdmi->hdmi_data.colorimetry = HDMI_COLORIMETRY_ITU_601;
-       else
-               hdmi->hdmi_data.colorimetry = HDMI_COLORIMETRY_ITU_709;
+       unsigned long mpixelclock = mode->clock * 1000;
 
        /* Mute video and audio output */
        hdmi_modb(hdmi, HDMI_AV_MUTE, m_AUDIO_MUTE | m_VIDEO_BLACK,
@@ -469,10 +479,8 @@ static int inno_hdmi_setup(struct inno_hdmi *hdmi,
 
        inno_hdmi_config_video_csc(hdmi);
 
-       if (display->is_hdmi) {
+       if (display->is_hdmi)
                inno_hdmi_config_video_avi(hdmi, mode);
-               inno_hdmi_config_video_vsi(hdmi, mode);
-       }
 
        /*
         * When IP controller have configured to an accurate video
@@ -480,47 +488,73 @@ static int inno_hdmi_setup(struct inno_hdmi *hdmi,
         * DCLK_LCDC, so we need to init the TMDS rate to mode pixel
         * clock rate, and reconfigure the DDC clock.
         */
-       hdmi->tmds_rate = mode->clock * 1000;
-       inno_hdmi_i2c_init(hdmi);
+       inno_hdmi_i2c_init(hdmi, mpixelclock);
 
        /* Unmute video and audio output */
        hdmi_modb(hdmi, HDMI_AV_MUTE, m_AUDIO_MUTE | m_VIDEO_BLACK,
                  v_AUDIO_MUTE(0) | v_VIDEO_MUTE(0));
 
+       inno_hdmi_power_up(hdmi, mpixelclock);
+
        return 0;
 }
 
-static void inno_hdmi_encoder_mode_set(struct drm_encoder *encoder,
-                                      struct drm_display_mode *mode,
-                                      struct drm_display_mode *adj_mode)
+static enum drm_mode_status inno_hdmi_display_mode_valid(struct inno_hdmi *hdmi,
+                                                        struct drm_display_mode *mode)
 {
-       struct inno_hdmi *hdmi = encoder_to_inno_hdmi(encoder);
+       unsigned long mpixelclk, max_tolerance;
+       long rounded_refclk;
 
-       inno_hdmi_setup(hdmi, adj_mode);
+       /* No support for double-clock modes */
+       if (mode->flags & DRM_MODE_FLAG_DBLCLK)
+               return MODE_BAD;
 
-       /* Store the display mode for plugin/DPMS poweron events */
-       drm_mode_copy(&hdmi->previous_mode, adj_mode);
-}
+       mpixelclk = mode->clock * 1000;
 
-static void inno_hdmi_encoder_enable(struct drm_encoder *encoder)
-{
-       struct inno_hdmi *hdmi = encoder_to_inno_hdmi(encoder);
+       if (mpixelclk < INNO_HDMI_MIN_TMDS_CLOCK)
+               return MODE_CLOCK_LOW;
+
+       if (inno_hdmi_find_phy_config(hdmi, mpixelclk) < 0)
+               return MODE_CLOCK_HIGH;
 
-       inno_hdmi_set_pwr_mode(hdmi, NORMAL);
+       if (hdmi->refclk) {
+               rounded_refclk = clk_round_rate(hdmi->refclk, mpixelclk);
+               if (rounded_refclk < 0)
+                       return MODE_BAD;
+
+               /* Vesa DMT standard mentions +/- 0.5% max tolerance */
+               max_tolerance = mpixelclk / 200;
+               if (abs_diff((unsigned long)rounded_refclk, mpixelclk) > max_tolerance)
+                       return MODE_NOCLOCK;
+       }
+
+       return MODE_OK;
 }
 
-static void inno_hdmi_encoder_disable(struct drm_encoder *encoder)
+static void inno_hdmi_encoder_enable(struct drm_encoder *encoder,
+                                    struct drm_atomic_state *state)
 {
        struct inno_hdmi *hdmi = encoder_to_inno_hdmi(encoder);
+       struct drm_connector_state *conn_state;
+       struct drm_crtc_state *crtc_state;
 
-       inno_hdmi_set_pwr_mode(hdmi, LOWER_PWR);
+       conn_state = drm_atomic_get_new_connector_state(state, &hdmi->connector);
+       if (WARN_ON(!conn_state))
+               return;
+
+       crtc_state = drm_atomic_get_new_crtc_state(state, conn_state->crtc);
+       if (WARN_ON(!crtc_state))
+               return;
+
+       inno_hdmi_setup(hdmi, &crtc_state->adjusted_mode);
 }
 
-static bool inno_hdmi_encoder_mode_fixup(struct drm_encoder *encoder,
-                                        const struct drm_display_mode *mode,
-                                        struct drm_display_mode *adj_mode)
+static void inno_hdmi_encoder_disable(struct drm_encoder *encoder,
+                                     struct drm_atomic_state *state)
 {
-       return true;
+       struct inno_hdmi *hdmi = encoder_to_inno_hdmi(encoder);
+
+       inno_hdmi_standby(hdmi);
 }
 
 static int
@@ -529,19 +563,35 @@ inno_hdmi_encoder_atomic_check(struct drm_encoder *encoder,
                               struct drm_connector_state *conn_state)
 {
        struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc_state);
+       struct inno_hdmi *hdmi = encoder_to_inno_hdmi(encoder);
+       struct drm_display_mode *mode = &crtc_state->adjusted_mode;
+       u8 vic = drm_match_cea_mode(mode);
+       struct inno_hdmi_connector_state *inno_conn_state =
+                                       to_inno_hdmi_conn_state(conn_state);
 
        s->output_mode = ROCKCHIP_OUT_MODE_P888;
        s->output_type = DRM_MODE_CONNECTOR_HDMIA;
 
-       return 0;
+       if (vic == 6 || vic == 7 ||
+           vic == 21 || vic == 22 ||
+           vic == 2 || vic == 3 ||
+           vic == 17 || vic == 18)
+               inno_conn_state->colorimetry = HDMI_COLORIMETRY_ITU_601;
+       else
+               inno_conn_state->colorimetry = HDMI_COLORIMETRY_ITU_709;
+
+       inno_conn_state->enc_out_format = HDMI_COLORSPACE_RGB;
+       inno_conn_state->rgb_limited_range =
+               drm_default_rgb_quant_range(mode) == HDMI_QUANTIZATION_RANGE_LIMITED;
+
+       return  inno_hdmi_display_mode_valid(hdmi,
+                               &crtc_state->adjusted_mode) == MODE_OK ? 0 : -EINVAL;
 }
 
 static struct drm_encoder_helper_funcs inno_hdmi_encoder_helper_funcs = {
-       .enable     = inno_hdmi_encoder_enable,
-       .disable    = inno_hdmi_encoder_disable,
-       .mode_fixup = inno_hdmi_encoder_mode_fixup,
-       .mode_set   = inno_hdmi_encoder_mode_set,
-       .atomic_check = inno_hdmi_encoder_atomic_check,
+       .atomic_check   = inno_hdmi_encoder_atomic_check,
+       .atomic_enable  = inno_hdmi_encoder_enable,
+       .atomic_disable = inno_hdmi_encoder_disable,
 };
 
 static enum drm_connector_status
@@ -564,7 +614,6 @@ static int inno_hdmi_connector_get_modes(struct drm_connector *connector)
 
        edid = drm_get_edid(connector, hdmi->ddc);
        if (edid) {
-               hdmi->hdmi_data.sink_has_audio = drm_detect_monitor_audio(edid);
                drm_connector_update_edid_property(connector, edid);
                ret = drm_add_edid_modes(connector, edid);
                kfree(edid);
@@ -577,14 +626,9 @@ static enum drm_mode_status
 inno_hdmi_connector_mode_valid(struct drm_connector *connector,
                               struct drm_display_mode *mode)
 {
-       return MODE_OK;
-}
+       struct inno_hdmi *hdmi = connector_to_inno_hdmi(connector);
 
-static int
-inno_hdmi_probe_single_connector_modes(struct drm_connector *connector,
-                                      uint32_t maxX, uint32_t maxY)
-{
-       return drm_helper_probe_single_connector_modes(connector, 1920, 1080);
+       return  inno_hdmi_display_mode_valid(hdmi, mode);
 }
 
 static void inno_hdmi_connector_destroy(struct drm_connector *connector)
@@ -593,13 +637,64 @@ static void inno_hdmi_connector_destroy(struct drm_connector *connector)
        drm_connector_cleanup(connector);
 }
 
+static void
+inno_hdmi_connector_destroy_state(struct drm_connector *connector,
+                                 struct drm_connector_state *state)
+{
+       struct inno_hdmi_connector_state *inno_conn_state =
+                                               to_inno_hdmi_conn_state(state);
+
+       __drm_atomic_helper_connector_destroy_state(&inno_conn_state->base);
+       kfree(inno_conn_state);
+}
+
+static void inno_hdmi_connector_reset(struct drm_connector *connector)
+{
+       struct inno_hdmi_connector_state *inno_conn_state;
+
+       if (connector->state) {
+               inno_hdmi_connector_destroy_state(connector, connector->state);
+               connector->state = NULL;
+       }
+
+       inno_conn_state = kzalloc(sizeof(*inno_conn_state), GFP_KERNEL);
+       if (!inno_conn_state)
+               return;
+
+       __drm_atomic_helper_connector_reset(connector, &inno_conn_state->base);
+
+       inno_conn_state->colorimetry = HDMI_COLORIMETRY_ITU_709;
+       inno_conn_state->enc_out_format = HDMI_COLORSPACE_RGB;
+       inno_conn_state->rgb_limited_range = false;
+}
+
+static struct drm_connector_state *
+inno_hdmi_connector_duplicate_state(struct drm_connector *connector)
+{
+       struct inno_hdmi_connector_state *inno_conn_state;
+
+       if (WARN_ON(!connector->state))
+               return NULL;
+
+       inno_conn_state = kmemdup(to_inno_hdmi_conn_state(connector->state),
+                                 sizeof(*inno_conn_state), GFP_KERNEL);
+
+       if (!inno_conn_state)
+               return NULL;
+
+       __drm_atomic_helper_connector_duplicate_state(connector,
+                                                     &inno_conn_state->base);
+
+       return &inno_conn_state->base;
+}
+
 static const struct drm_connector_funcs inno_hdmi_connector_funcs = {
-       .fill_modes = inno_hdmi_probe_single_connector_modes,
+       .fill_modes = drm_helper_probe_single_connector_modes,
        .detect = inno_hdmi_connector_detect,
        .destroy = inno_hdmi_connector_destroy,
-       .reset = drm_atomic_helper_connector_reset,
-       .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
-       .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
+       .reset = inno_hdmi_connector_reset,
+       .atomic_duplicate_state = inno_hdmi_connector_duplicate_state,
+       .atomic_destroy_state = inno_hdmi_connector_destroy_state,
 };
 
 static struct drm_connector_helper_funcs inno_hdmi_connector_helper_funcs = {
@@ -819,6 +914,7 @@ static int inno_hdmi_bind(struct device *dev, struct device *master,
        struct platform_device *pdev = to_platform_device(dev);
        struct drm_device *drm = data;
        struct inno_hdmi *hdmi;
+       const struct inno_hdmi_variant *variant;
        int irq;
        int ret;
 
@@ -827,7 +923,12 @@ static int inno_hdmi_bind(struct device *dev, struct device *master,
                return -ENOMEM;
 
        hdmi->dev = dev;
-       hdmi->drm_dev = drm;
+
+       variant = of_device_get_match_data(hdmi->dev);
+       if (!variant)
+               return -EINVAL;
+
+       hdmi->variant = variant;
 
        hdmi->regs = devm_platform_ioremap_resource(pdev, 0);
        if (IS_ERR(hdmi->regs))
@@ -846,6 +947,20 @@ static int inno_hdmi_bind(struct device *dev, struct device *master,
                return ret;
        }
 
+       hdmi->refclk = devm_clk_get_optional(hdmi->dev, "ref");
+       if (IS_ERR(hdmi->refclk)) {
+               DRM_DEV_ERROR(hdmi->dev, "Unable to get HDMI reference clock\n");
+               ret = PTR_ERR(hdmi->refclk);
+               goto err_disable_pclk;
+       }
+
+       ret = clk_prepare_enable(hdmi->refclk);
+       if (ret) {
+               DRM_DEV_ERROR(hdmi->dev,
+                             "Cannot enable HDMI reference clock: %d\n", ret);
+               goto err_disable_pclk;
+       }
+
        irq = platform_get_irq(pdev, 0);
        if (irq < 0) {
                ret = irq;
@@ -862,13 +977,16 @@ static int inno_hdmi_bind(struct device *dev, struct device *master,
        }
 
        /*
-        * When IP controller haven't configured to an accurate video
-        * timing, then the TMDS clock source would be switched to
-        * PCLK_HDMI, so we need to init the TMDS rate to PCLK rate,
-        * and reconfigure the DDC clock.
+        * When the controller isn't configured to an accurate
+        * video timing and there is no reference clock available,
+        * then the TMDS clock source would be switched to PCLK_HDMI,
+        * so we need to init the TMDS rate to PCLK rate, and
+        * reconfigure the DDC clock.
         */
-       hdmi->tmds_rate = clk_get_rate(hdmi->pclk);
-       inno_hdmi_i2c_init(hdmi);
+       if (hdmi->refclk)
+               inno_hdmi_i2c_init(hdmi, clk_get_rate(hdmi->refclk));
+       else
+               inno_hdmi_i2c_init(hdmi, clk_get_rate(hdmi->pclk));
 
        ret = inno_hdmi_register(drm, hdmi);
        if (ret)
@@ -892,6 +1010,8 @@ err_cleanup_hdmi:
 err_put_adapter:
        i2c_put_adapter(hdmi->ddc);
 err_disable_clk:
+       clk_disable_unprepare(hdmi->refclk);
+err_disable_pclk:
        clk_disable_unprepare(hdmi->pclk);
        return ret;
 }
@@ -905,6 +1025,7 @@ static void inno_hdmi_unbind(struct device *dev, struct device *master,
        hdmi->encoder.encoder.funcs->destroy(&hdmi->encoder.encoder);
 
        i2c_put_adapter(hdmi->ddc);
+       clk_disable_unprepare(hdmi->refclk);
        clk_disable_unprepare(hdmi->pclk);
 }
 
@@ -923,8 +1044,22 @@ static void inno_hdmi_remove(struct platform_device *pdev)
        component_del(&pdev->dev, &inno_hdmi_ops);
 }
 
+static const struct inno_hdmi_variant rk3036_inno_hdmi_variant = {
+       .phy_configs = rk3036_hdmi_phy_configs,
+       .default_phy_config = &rk3036_hdmi_phy_configs[1],
+};
+
+static const struct inno_hdmi_variant rk3128_inno_hdmi_variant = {
+       .phy_configs = rk3128_hdmi_phy_configs,
+       .default_phy_config = &rk3128_hdmi_phy_configs[1],
+};
+
 static const struct of_device_id inno_hdmi_dt_ids[] = {
        { .compatible = "rockchip,rk3036-inno-hdmi",
+         .data = &rk3036_inno_hdmi_variant,
+       },
+       { .compatible = "rockchip,rk3128-inno-hdmi",
+         .data = &rk3128_inno_hdmi_variant,
        },
        {},
 };
index 93245b55f967009acf6256f74819b3afb413a214..a7edf3559e606f7a219abcd2044ff729e6978b41 100644 (file)
 
 #define DDC_SEGMENT_ADDR               0x30
 
-enum PWR_MODE {
-       NORMAL,
-       LOWER_PWR,
-};
-
 #define HDMI_SCL_RATE                  (100*1000)
 #define DDC_BUS_FREQ_L                 0x4b
 #define DDC_BUS_FREQ_H                 0x4c
index 59341654ec32b83e7d1a4766a0a90663df017006..77b76cff1adb9dc8701b647dbfda45eaa0829558 100644 (file)
@@ -576,8 +576,7 @@ static int rockchip_lvds_bind(struct device *dev, struct device *master,
                ret = -EINVAL;
                goto err_put_port;
        } else if (ret) {
-               DRM_DEV_ERROR(dev, "failed to find panel and bridge node\n");
-               ret = -EPROBE_DEFER;
+               dev_err_probe(dev, ret, "failed to find panel and bridge node\n");
                goto err_put_port;
        }
        if (lvds->panel)
index c51ca82320cb0c09d2fea4909ea560b706ec191b..b9ee02061d5bf377b167b03f3d9605ca6a1aa189 100644 (file)
@@ -227,11 +227,22 @@ static const struct vop_win_data rk3126_vop_win_data[] = {
          .type = DRM_PLANE_TYPE_CURSOR },
 };
 
+static const struct vop_output rk3126_output = {
+       .pin_pol = VOP_REG(RK3036_DSP_CTRL0, 0xf, 4),
+       .hdmi_pin_pol = VOP_REG(RK3126_INT_SCALER, 0x7, 4),
+       .hdmi_en = VOP_REG(RK3036_AXI_BUS_CTRL, 0x1, 22),
+       .hdmi_dclk_pol = VOP_REG(RK3036_AXI_BUS_CTRL, 0x1, 23),
+       .rgb_en = VOP_REG(RK3036_AXI_BUS_CTRL, 0x1, 24),
+       .rgb_dclk_pol = VOP_REG(RK3036_AXI_BUS_CTRL, 0x1, 25),
+       .mipi_en = VOP_REG(RK3036_AXI_BUS_CTRL, 0x1, 28),
+       .mipi_dclk_pol = VOP_REG(RK3036_AXI_BUS_CTRL, 0x1, 29),
+};
+
 static const struct vop_data rk3126_vop = {
        .intr = &rk3036_intr,
        .common = &rk3036_common,
        .modeset = &rk3036_modeset,
-       .output = &rk3036_output,
+       .output = &rk3126_output,
        .win = rk3126_vop_win_data,
        .win_size = ARRAY_SIZE(rk3126_vop_win_data),
        .max_output = { 1920, 1080 },
index 406e981c75bd73df2f2350e1704030abd1b585f3..fbf1bcc686250ea3d0388e0922dcf6bc8a03d3ec 100644 (file)
 /* rk3036 register definition end */
 
 /* rk3126 register definition */
+#define RK3126_INT_SCALER              0x0c
+
+/* win1 register */
 #define RK3126_WIN1_MST                        0x4c
 #define RK3126_WIN1_DSP_INFO           0x50
 #define RK3126_WIN1_DSP_ST             0x54
index 550492a7a031d7827b2e167098c495908bee82aa..1abbcdf38430e8e3ab226ec094a0a7ea1ecb8c16 100644 (file)
@@ -1249,7 +1249,7 @@ int drm_sched_init(struct drm_gpu_scheduler *sched,
                   long timeout, struct workqueue_struct *timeout_wq,
                   atomic_t *score, const char *name, struct device *dev)
 {
-       int i, ret;
+       int i;
 
        sched->ops = ops;
        sched->credit_limit = credit_limit;
@@ -1285,11 +1285,11 @@ int drm_sched_init(struct drm_gpu_scheduler *sched,
 
                sched->own_submit_wq = true;
        }
-       ret = -ENOMEM;
+
        sched->sched_rq = kmalloc_array(num_rqs, sizeof(*sched->sched_rq),
                                        GFP_KERNEL | __GFP_ZERO);
        if (!sched->sched_rq)
-               goto Out_free;
+               goto Out_check_own;
        sched->num_rqs = num_rqs;
        for (i = DRM_SCHED_PRIORITY_KERNEL; i < sched->num_rqs; i++) {
                sched->sched_rq[i] = kzalloc(sizeof(*sched->sched_rq[i]), GFP_KERNEL);
@@ -1314,13 +1314,14 @@ int drm_sched_init(struct drm_gpu_scheduler *sched,
 Out_unroll:
        for (--i ; i >= DRM_SCHED_PRIORITY_KERNEL; i--)
                kfree(sched->sched_rq[i]);
-Out_free:
+
        kfree(sched->sched_rq);
        sched->sched_rq = NULL;
+Out_check_own:
        if (sched->own_submit_wq)
                destroy_workqueue(sched->submit_wq);
        drm_err(sched, "%s: Failed to setup GPU scheduler--out of memory\n", __func__);
-       return ret;
+       return -ENOMEM;
 }
 EXPORT_SYMBOL(drm_sched_init);
 
index 84e035a7ab3f50396cdf9db2597e0b3e1968c268..84bfde31d1724a2c7e2cb52e847fe934813fda3b 100644 (file)
@@ -142,6 +142,11 @@ static const struct of_device_id ssd130x_of_match[] = {
                .compatible = "solomon,ssd1327",
                .data = &ssd130x_variants[SSD1327_ID],
        },
+       /* ssd133x family */
+       {
+               .compatible = "solomon,ssd1331",
+               .data = &ssd130x_variants[SSD1331_ID],
+       },
        { /* sentinel */ }
 };
 MODULE_DEVICE_TABLE(of, ssd130x_of_match);
@@ -166,6 +171,8 @@ static const struct spi_device_id ssd130x_spi_table[] = {
        { "ssd1322", SSD1322_ID },
        { "ssd1325", SSD1325_ID },
        { "ssd1327", SSD1327_ID },
+       /* ssd133x family */
+       { "ssd1331", SSD1331_ID },
        { /* sentinel */ }
 };
 MODULE_DEVICE_TABLE(spi, ssd130x_spi_table);
index 3d0e093a7e6ed74de7c5b7484323c4465e49b89a..ebd943b9e357b539ebd82b4c845ddbc4b3ac9624 100644 (file)
 #define SSD130X_SET_VCOMH_VOLTAGE              0xbe
 #define SSD132X_SET_FUNCTION_SELECT_B          0xd5
 
+/* ssd133x commands */
+#define SSD133X_SET_COL_RANGE                  0x15
+#define SSD133X_SET_ROW_RANGE                  0x75
+#define SSD133X_CONTRAST_A                     0x81
+#define SSD133X_CONTRAST_B                     0x82
+#define SSD133X_CONTRAST_C                     0x83
+#define SSD133X_SET_MASTER_CURRENT             0x87
+#define SSD132X_SET_PRECHARGE_A                        0x8a
+#define SSD132X_SET_PRECHARGE_B                        0x8b
+#define SSD132X_SET_PRECHARGE_C                        0x8c
+#define SSD133X_SET_DISPLAY_START              0xa1
+#define SSD133X_SET_DISPLAY_OFFSET             0xa2
+#define SSD133X_SET_DISPLAY_NORMAL             0xa4
+#define SSD133X_SET_MASTER_CONFIG              0xad
+#define SSD133X_POWER_SAVE_MODE                        0xb0
+#define SSD133X_PHASES_PERIOD                  0xb1
+#define SSD133X_SET_CLOCK_FREQ                 0xb3
+#define SSD133X_SET_PRECHARGE_VOLTAGE          0xbb
+#define SSD133X_SET_VCOMH_VOLTAGE              0xbe
+
 #define MAX_CONTRAST 255
 
 const struct ssd130x_deviceinfo ssd130x_variants[] = {
@@ -180,6 +200,12 @@ const struct ssd130x_deviceinfo ssd130x_variants[] = {
                .default_width = 128,
                .default_height = 128,
                .family_id = SSD132X_FAMILY,
+       },
+       /* ssd133x family */
+       [SSD1331_ID] = {
+               .default_width = 96,
+               .default_height = 64,
+               .family_id = SSD133X_FAMILY,
        }
 };
 EXPORT_SYMBOL_NS_GPL(ssd130x_variants, DRM_SSD130X);
@@ -589,6 +615,117 @@ static int ssd132x_init(struct ssd130x_device *ssd130x)
        return 0;
 }
 
+static int ssd133x_init(struct ssd130x_device *ssd130x)
+{
+       int ret;
+
+       /* Set color A contrast */
+       ret = ssd130x_write_cmd(ssd130x, 2, SSD133X_CONTRAST_A, 0x91);
+       if (ret < 0)
+               return ret;
+
+       /* Set color B contrast */
+       ret = ssd130x_write_cmd(ssd130x, 2, SSD133X_CONTRAST_B, 0x50);
+       if (ret < 0)
+               return ret;
+
+       /* Set color C contrast */
+       ret = ssd130x_write_cmd(ssd130x, 2, SSD133X_CONTRAST_C, 0x7d);
+       if (ret < 0)
+               return ret;
+
+       /* Set master current */
+       ret = ssd130x_write_cmd(ssd130x, 2, SSD133X_SET_MASTER_CURRENT, 0x06);
+       if (ret < 0)
+               return ret;
+
+       /* Set column start and end */
+       ret = ssd130x_write_cmd(ssd130x, 3, SSD133X_SET_COL_RANGE, 0x00, ssd130x->width - 1);
+       if (ret < 0)
+               return ret;
+
+       /* Set row start and end */
+       ret = ssd130x_write_cmd(ssd130x, 3, SSD133X_SET_ROW_RANGE, 0x00, ssd130x->height - 1);
+       if (ret < 0)
+               return ret;
+
+       /*
+        * Horizontal Address Increment
+        * Normal order SA,SB,SC (e.g. RGB)
+        * COM Split Odd Even
+        * 256 color format
+        */
+       ret = ssd130x_write_cmd(ssd130x, 2, SSD13XX_SET_SEG_REMAP, 0x20);
+       if (ret < 0)
+               return ret;
+
+       /* Set display start and offset */
+       ret = ssd130x_write_cmd(ssd130x, 2, SSD133X_SET_DISPLAY_START, 0x00);
+       if (ret < 0)
+               return ret;
+
+       ret = ssd130x_write_cmd(ssd130x, 2, SSD133X_SET_DISPLAY_OFFSET, 0x00);
+       if (ret < 0)
+               return ret;
+
+       /* Set display mode normal */
+       ret = ssd130x_write_cmd(ssd130x, 1, SSD133X_SET_DISPLAY_NORMAL);
+       if (ret < 0)
+               return ret;
+
+       /* Set multiplex ratio value */
+       ret = ssd130x_write_cmd(ssd130x, 2, SSD13XX_SET_MULTIPLEX_RATIO, ssd130x->height - 1);
+       if (ret < 0)
+               return ret;
+
+       /* Set master configuration */
+       ret = ssd130x_write_cmd(ssd130x, 2, SSD133X_SET_MASTER_CONFIG, 0x8e);
+       if (ret < 0)
+               return ret;
+
+       /* Set power mode */
+       ret = ssd130x_write_cmd(ssd130x, 2, SSD133X_POWER_SAVE_MODE, 0x0b);
+       if (ret < 0)
+               return ret;
+
+       /* Set Phase 1 and 2 period */
+       ret = ssd130x_write_cmd(ssd130x, 2, SSD133X_PHASES_PERIOD, 0x31);
+       if (ret < 0)
+               return ret;
+
+       /* Set clock divider */
+       ret = ssd130x_write_cmd(ssd130x, 2, SSD133X_SET_CLOCK_FREQ, 0xf0);
+       if (ret < 0)
+               return ret;
+
+       /* Set pre-charge A */
+       ret = ssd130x_write_cmd(ssd130x, 2, SSD132X_SET_PRECHARGE_A, 0x64);
+       if (ret < 0)
+               return ret;
+
+       /* Set pre-charge B */
+       ret = ssd130x_write_cmd(ssd130x, 2, SSD132X_SET_PRECHARGE_B, 0x78);
+       if (ret < 0)
+               return ret;
+
+       /* Set pre-charge C */
+       ret = ssd130x_write_cmd(ssd130x, 2, SSD132X_SET_PRECHARGE_C, 0x64);
+       if (ret < 0)
+               return ret;
+
+       /* Set pre-charge level */
+       ret = ssd130x_write_cmd(ssd130x, 2, SSD133X_SET_PRECHARGE_VOLTAGE, 0x3a);
+       if (ret < 0)
+               return ret;
+
+       /* Set VCOMH voltage */
+       ret = ssd130x_write_cmd(ssd130x, 2, SSD133X_SET_VCOMH_VOLTAGE, 0x3e);
+       if (ret < 0)
+               return ret;
+
+       return 0;
+}
+
 static int ssd130x_update_rect(struct ssd130x_device *ssd130x,
                               struct drm_rect *rect, u8 *buf,
                               u8 *data_array)
@@ -753,6 +890,47 @@ static int ssd132x_update_rect(struct ssd130x_device *ssd130x,
        return ret;
 }
 
+static int ssd133x_update_rect(struct ssd130x_device *ssd130x,
+                              struct drm_rect *rect, u8 *data_array,
+                              unsigned int pitch)
+{
+       unsigned int x = rect->x1;
+       unsigned int y = rect->y1;
+       unsigned int columns = drm_rect_width(rect);
+       unsigned int rows = drm_rect_height(rect);
+       int ret;
+
+       /*
+        * The screen is divided in Segment and Common outputs, where
+        * COM0 to COM[N - 1] are the rows and SEG0 to SEG[M - 1] are
+        * the columns.
+        *
+        * Each Segment has a 8-bit pixel and each Common output has a
+        * row of pixels. When using the (default) horizontal address
+        * increment mode, each byte of data sent to the controller has
+        * a Segment (e.g: SEG0).
+        *
+        * When using the 256 color depth format, each pixel contains 3
+        * sub-pixels for color A, B and C. These have 3 bit, 3 bit and
+        * 2 bits respectively.
+        */
+
+       /* Set column start and end */
+       ret = ssd130x_write_cmd(ssd130x, 3, SSD133X_SET_COL_RANGE, x, columns - 1);
+       if (ret < 0)
+               return ret;
+
+       /* Set row start and end */
+       ret = ssd130x_write_cmd(ssd130x, 3, SSD133X_SET_ROW_RANGE, y, rows - 1);
+       if (ret < 0)
+               return ret;
+
+       /* Write out update in one go since horizontal addressing mode is used */
+       ret = ssd130x_write_data(ssd130x, data_array, pitch * rows);
+
+       return ret;
+}
+
 static void ssd130x_clear_screen(struct ssd130x_device *ssd130x, u8 *data_array)
 {
        unsigned int pages = DIV_ROUND_UP(ssd130x->height, SSD130X_PAGE_HEIGHT);
@@ -805,6 +983,22 @@ static void ssd132x_clear_screen(struct ssd130x_device *ssd130x, u8 *data_array)
        ssd130x_write_data(ssd130x, data_array, columns * height);
 }
 
+static void ssd133x_clear_screen(struct ssd130x_device *ssd130x, u8 *data_array)
+{
+       const struct drm_format_info *fi = drm_format_info(DRM_FORMAT_RGB332);
+       unsigned int pitch;
+
+       if (!fi)
+               return;
+
+       pitch = drm_format_info_min_pitch(fi, 0, ssd130x->width);
+
+       memset(data_array, 0, pitch * ssd130x->height);
+
+       /* Write out update in one go since horizontal addressing mode is used */
+       ssd130x_write_data(ssd130x, data_array, pitch * ssd130x->height);
+}
+
 static int ssd130x_fb_blit_rect(struct drm_framebuffer *fb,
                                const struct iosys_map *vmap,
                                struct drm_rect *rect,
@@ -866,6 +1060,36 @@ static int ssd132x_fb_blit_rect(struct drm_framebuffer *fb,
        return ret;
 }
 
+static int ssd133x_fb_blit_rect(struct drm_framebuffer *fb,
+                               const struct iosys_map *vmap,
+                               struct drm_rect *rect, u8 *data_array,
+                               struct drm_format_conv_state *fmtcnv_state)
+{
+       struct ssd130x_device *ssd130x = drm_to_ssd130x(fb->dev);
+       const struct drm_format_info *fi = drm_format_info(DRM_FORMAT_RGB332);
+       unsigned int dst_pitch;
+       struct iosys_map dst;
+       int ret = 0;
+
+       if (!fi)
+               return -EINVAL;
+
+       dst_pitch = drm_format_info_min_pitch(fi, 0, drm_rect_width(rect));
+
+       ret = drm_gem_fb_begin_cpu_access(fb, DMA_FROM_DEVICE);
+       if (ret)
+               return ret;
+
+       iosys_map_set_vaddr(&dst, data_array);
+       drm_fb_xrgb8888_to_rgb332(&dst, &dst_pitch, vmap, fb, rect, fmtcnv_state);
+
+       drm_gem_fb_end_cpu_access(fb, DMA_FROM_DEVICE);
+
+       ssd133x_update_rect(ssd130x, rect, data_array, dst_pitch);
+
+       return ret;
+}
+
 static int ssd130x_primary_plane_atomic_check(struct drm_plane *plane,
                                              struct drm_atomic_state *state)
 {
@@ -964,6 +1188,29 @@ static int ssd132x_primary_plane_atomic_check(struct drm_plane *plane,
        return 0;
 }
 
+static int ssd133x_primary_plane_atomic_check(struct drm_plane *plane,
+                                             struct drm_atomic_state *state)
+{
+       struct drm_plane_state *plane_state = drm_atomic_get_new_plane_state(state, plane);
+       struct drm_crtc *crtc = plane_state->crtc;
+       struct drm_crtc_state *crtc_state = NULL;
+       int ret;
+
+       if (crtc)
+               crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
+
+       ret = drm_atomic_helper_check_plane_state(plane_state, crtc_state,
+                                                 DRM_PLANE_NO_SCALING,
+                                                 DRM_PLANE_NO_SCALING,
+                                                 false, false);
+       if (ret)
+               return ret;
+       else if (!plane_state->visible)
+               return 0;
+
+       return 0;
+}
+
 static void ssd130x_primary_plane_atomic_update(struct drm_plane *plane,
                                                struct drm_atomic_state *state)
 {
@@ -1034,6 +1281,39 @@ static void ssd132x_primary_plane_atomic_update(struct drm_plane *plane,
        drm_dev_exit(idx);
 }
 
+static void ssd133x_primary_plane_atomic_update(struct drm_plane *plane,
+                                               struct drm_atomic_state *state)
+{
+       struct drm_plane_state *plane_state = drm_atomic_get_new_plane_state(state, plane);
+       struct drm_plane_state *old_plane_state = drm_atomic_get_old_plane_state(state, plane);
+       struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
+       struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, plane_state->crtc);
+       struct ssd130x_crtc_state *ssd130x_crtc_state =  to_ssd130x_crtc_state(crtc_state);
+       struct drm_framebuffer *fb = plane_state->fb;
+       struct drm_atomic_helper_damage_iter iter;
+       struct drm_device *drm = plane->dev;
+       struct drm_rect dst_clip;
+       struct drm_rect damage;
+       int idx;
+
+       if (!drm_dev_enter(drm, &idx))
+               return;
+
+       drm_atomic_helper_damage_iter_init(&iter, old_plane_state, plane_state);
+       drm_atomic_for_each_plane_damage(&iter, &damage) {
+               dst_clip = plane_state->dst;
+
+               if (!drm_rect_intersect(&dst_clip, &damage))
+                       continue;
+
+               ssd133x_fb_blit_rect(fb, &shadow_plane_state->data[0], &dst_clip,
+                                    ssd130x_crtc_state->data_array,
+                                    &shadow_plane_state->fmtcnv_state);
+       }
+
+       drm_dev_exit(idx);
+}
+
 static void ssd130x_primary_plane_atomic_disable(struct drm_plane *plane,
                                                 struct drm_atomic_state *state)
 {
@@ -1082,6 +1362,30 @@ static void ssd132x_primary_plane_atomic_disable(struct drm_plane *plane,
        drm_dev_exit(idx);
 }
 
+static void ssd133x_primary_plane_atomic_disable(struct drm_plane *plane,
+                                                struct drm_atomic_state *state)
+{
+       struct drm_device *drm = plane->dev;
+       struct ssd130x_device *ssd130x = drm_to_ssd130x(drm);
+       struct drm_plane_state *plane_state = drm_atomic_get_new_plane_state(state, plane);
+       struct drm_crtc_state *crtc_state;
+       struct ssd130x_crtc_state *ssd130x_crtc_state;
+       int idx;
+
+       if (!plane_state->crtc)
+               return;
+
+       crtc_state = drm_atomic_get_new_crtc_state(state, plane_state->crtc);
+       ssd130x_crtc_state = to_ssd130x_crtc_state(crtc_state);
+
+       if (!drm_dev_enter(drm, &idx))
+               return;
+
+       ssd133x_clear_screen(ssd130x, ssd130x_crtc_state->data_array);
+
+       drm_dev_exit(idx);
+}
+
 /* Called during init to allocate the plane's atomic state. */
 static void ssd130x_primary_plane_reset(struct drm_plane *plane)
 {
@@ -1144,6 +1448,12 @@ static const struct drm_plane_helper_funcs ssd130x_primary_plane_helper_funcs[]
                .atomic_check = ssd132x_primary_plane_atomic_check,
                .atomic_update = ssd132x_primary_plane_atomic_update,
                .atomic_disable = ssd132x_primary_plane_atomic_disable,
+       },
+       [SSD133X_FAMILY] = {
+               DRM_GEM_SHADOW_PLANE_HELPER_FUNCS,
+               .atomic_check = ssd133x_primary_plane_atomic_check,
+               .atomic_update = ssd133x_primary_plane_atomic_update,
+               .atomic_disable = ssd133x_primary_plane_atomic_disable,
        }
 };
 
@@ -1214,6 +1524,33 @@ static int ssd132x_crtc_atomic_check(struct drm_crtc *crtc,
        return 0;
 }
 
+static int ssd133x_crtc_atomic_check(struct drm_crtc *crtc,
+                                    struct drm_atomic_state *state)
+{
+       struct drm_device *drm = crtc->dev;
+       struct ssd130x_device *ssd130x = drm_to_ssd130x(drm);
+       struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
+       struct ssd130x_crtc_state *ssd130x_state = to_ssd130x_crtc_state(crtc_state);
+       const struct drm_format_info *fi = drm_format_info(DRM_FORMAT_RGB332);
+       unsigned int pitch;
+       int ret;
+
+       if (!fi)
+               return -EINVAL;
+
+       ret = drm_crtc_helper_atomic_check(crtc, state);
+       if (ret)
+               return ret;
+
+       pitch = drm_format_info_min_pitch(fi, 0, ssd130x->width);
+
+       ssd130x_state->data_array = kmalloc(pitch * ssd130x->height, GFP_KERNEL);
+       if (!ssd130x_state->data_array)
+               return -ENOMEM;
+
+       return 0;
+}
+
 /* Called during init to allocate the CRTC's atomic state. */
 static void ssd130x_crtc_reset(struct drm_crtc *crtc)
 {
@@ -1275,6 +1612,10 @@ static const struct drm_crtc_helper_funcs ssd130x_crtc_helper_funcs[] = {
                .mode_valid = ssd130x_crtc_mode_valid,
                .atomic_check = ssd132x_crtc_atomic_check,
        },
+       [SSD133X_FAMILY] = {
+               .mode_valid = ssd130x_crtc_mode_valid,
+               .atomic_check = ssd133x_crtc_atomic_check,
+       },
 };
 
 static const struct drm_crtc_funcs ssd130x_crtc_funcs = {
@@ -1337,6 +1678,31 @@ power_off:
        ssd130x_power_off(ssd130x);
 }
 
+static void ssd133x_encoder_atomic_enable(struct drm_encoder *encoder,
+                                         struct drm_atomic_state *state)
+{
+       struct drm_device *drm = encoder->dev;
+       struct ssd130x_device *ssd130x = drm_to_ssd130x(drm);
+       int ret;
+
+       ret = ssd130x_power_on(ssd130x);
+       if (ret)
+               return;
+
+       ret = ssd133x_init(ssd130x);
+       if (ret)
+               goto power_off;
+
+       ssd130x_write_cmd(ssd130x, 1, SSD13XX_DISPLAY_ON);
+
+       backlight_enable(ssd130x->bl_dev);
+
+       return;
+
+power_off:
+       ssd130x_power_off(ssd130x);
+}
+
 static void ssd130x_encoder_atomic_disable(struct drm_encoder *encoder,
                                           struct drm_atomic_state *state)
 {
@@ -1358,6 +1724,10 @@ static const struct drm_encoder_helper_funcs ssd130x_encoder_helper_funcs[] = {
        [SSD132X_FAMILY] = {
                .atomic_enable = ssd132x_encoder_atomic_enable,
                .atomic_disable = ssd130x_encoder_atomic_disable,
+       },
+       [SSD133X_FAMILY] = {
+               .atomic_enable = ssd133x_encoder_atomic_enable,
+               .atomic_disable = ssd130x_encoder_atomic_disable,
        }
 };
 
index 075c5c3ee75ac195340cff5b465da8a18d446b69..a4554018bb2a49513cf49561ea0e2721f4df05f7 100644 (file)
@@ -25,7 +25,8 @@
 
 enum ssd130x_family_ids {
        SSD130X_FAMILY,
-       SSD132X_FAMILY
+       SSD132X_FAMILY,
+       SSD133X_FAMILY
 };
 
 enum ssd130x_variants {
@@ -39,6 +40,8 @@ enum ssd130x_variants {
        SSD1322_ID,
        SSD1325_ID,
        SSD1327_ID,
+       /* ssd133x family */
+       SSD1331_ID,
        NR_SSD130X_VARIANTS
 };
 
index ef02d530f78d751a51b6c1a7681ee8e6246287e6..ae12d001a04bfbe98504b6435dc9b9d964f7f4aa 100644 (file)
@@ -522,7 +522,7 @@ static int tegra_dpaux_probe(struct platform_device *pdev)
        if (err < 0) {
                dev_err(dpaux->dev, "failed to request IRQ#%u: %d\n",
                        dpaux->irq, err);
-               return err;
+               goto err_pm_disable;
        }
 
        disable_irq(dpaux->irq);
@@ -542,7 +542,7 @@ static int tegra_dpaux_probe(struct platform_device *pdev)
         */
        err = tegra_dpaux_pad_config(dpaux, DPAUX_PADCTL_FUNC_I2C);
        if (err < 0)
-               return err;
+               goto err_pm_disable;
 
 #ifdef CONFIG_GENERIC_PINCONF
        dpaux->desc.name = dev_name(&pdev->dev);
@@ -555,7 +555,8 @@ static int tegra_dpaux_probe(struct platform_device *pdev)
        dpaux->pinctrl = devm_pinctrl_register(&pdev->dev, &dpaux->desc, dpaux);
        if (IS_ERR(dpaux->pinctrl)) {
                dev_err(&pdev->dev, "failed to register pincontrol\n");
-               return PTR_ERR(dpaux->pinctrl);
+               err = PTR_ERR(dpaux->pinctrl);
+               goto err_pm_disable;
        }
 #endif
        /* enable and clear all interrupts */
@@ -571,10 +572,15 @@ static int tegra_dpaux_probe(struct platform_device *pdev)
        err = devm_of_dp_aux_populate_ep_devices(&dpaux->aux);
        if (err < 0) {
                dev_err(dpaux->dev, "failed to populate AUX bus: %d\n", err);
-               return err;
+               goto err_pm_disable;
        }
 
        return 0;
+
+err_pm_disable:
+       pm_runtime_put_sync(&pdev->dev);
+       pm_runtime_disable(&pdev->dev);
+       return err;
 }
 
 static void tegra_dpaux_remove(struct platform_device *pdev)
index ccb5d74fa227076e978fcca1f4245cff7ba29b37..682011166a8f67caf43b8edb56b7b91c481e2933 100644 (file)
@@ -13,7 +13,6 @@
 
 #include <drm/drm_atomic.h>
 #include <drm/drm_bridge.h>
-#include <drm/drm_edid.h>
 #include <drm/drm_encoder.h>
 #include <drm/drm_fixed.h>
 #include <drm/drm_probe_helper.h>
@@ -26,6 +25,7 @@
 /* XXX move to include/uapi/drm/drm_fourcc.h? */
 #define DRM_FORMAT_MOD_NVIDIA_SECTOR_LAYOUT BIT_ULL(22)
 
+struct edid;
 struct reset_control;
 
 struct tegra_drm {
index fbfe92a816d4bcb460fdb25deef35bcb1ddf88dc..db606e151afc81e26eaacb36a90389acc3b5a1aa 100644 (file)
@@ -1544,9 +1544,11 @@ static int tegra_dsi_ganged_probe(struct tegra_dsi *dsi)
        np = of_parse_phandle(dsi->dev->of_node, "nvidia,ganged-mode", 0);
        if (np) {
                struct platform_device *gangster = of_find_device_by_node(np);
+               of_node_put(np);
+               if (!gangster)
+                       return -EPROBE_DEFER;
 
                dsi->slave = platform_get_drvdata(gangster);
-               of_node_put(np);
 
                if (!dsi->slave) {
                        put_device(&gangster->dev);
@@ -1594,44 +1596,58 @@ static int tegra_dsi_probe(struct platform_device *pdev)
 
        if (!pdev->dev.pm_domain) {
                dsi->rst = devm_reset_control_get(&pdev->dev, "dsi");
-               if (IS_ERR(dsi->rst))
-                       return PTR_ERR(dsi->rst);
+               if (IS_ERR(dsi->rst)) {
+                       err = PTR_ERR(dsi->rst);
+                       goto remove;
+               }
        }
 
        dsi->clk = devm_clk_get(&pdev->dev, NULL);
-       if (IS_ERR(dsi->clk))
-               return dev_err_probe(&pdev->dev, PTR_ERR(dsi->clk),
-                                    "cannot get DSI clock\n");
+       if (IS_ERR(dsi->clk)) {
+               err = dev_err_probe(&pdev->dev, PTR_ERR(dsi->clk),
+                                   "cannot get DSI clock\n");
+               goto remove;
+       }
 
        dsi->clk_lp = devm_clk_get(&pdev->dev, "lp");
-       if (IS_ERR(dsi->clk_lp))
-               return dev_err_probe(&pdev->dev, PTR_ERR(dsi->clk_lp),
-                                    "cannot get low-power clock\n");
+       if (IS_ERR(dsi->clk_lp)) {
+               err = dev_err_probe(&pdev->dev, PTR_ERR(dsi->clk_lp),
+                                   "cannot get low-power clock\n");
+               goto remove;
+       }
 
        dsi->clk_parent = devm_clk_get(&pdev->dev, "parent");
-       if (IS_ERR(dsi->clk_parent))
-               return dev_err_probe(&pdev->dev, PTR_ERR(dsi->clk_parent),
-                                    "cannot get parent clock\n");
+       if (IS_ERR(dsi->clk_parent)) {
+               err = dev_err_probe(&pdev->dev, PTR_ERR(dsi->clk_parent),
+                                   "cannot get parent clock\n");
+               goto remove;
+       }
 
        dsi->vdd = devm_regulator_get(&pdev->dev, "avdd-dsi-csi");
-       if (IS_ERR(dsi->vdd))
-               return dev_err_probe(&pdev->dev, PTR_ERR(dsi->vdd),
-                                    "cannot get VDD supply\n");
+       if (IS_ERR(dsi->vdd)) {
+               err = dev_err_probe(&pdev->dev, PTR_ERR(dsi->vdd),
+                                   "cannot get VDD supply\n");
+               goto remove;
+       }
 
        err = tegra_dsi_setup_clocks(dsi);
        if (err < 0) {
                dev_err(&pdev->dev, "cannot setup clocks\n");
-               return err;
+               goto remove;
        }
 
        regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        dsi->regs = devm_ioremap_resource(&pdev->dev, regs);
-       if (IS_ERR(dsi->regs))
-               return PTR_ERR(dsi->regs);
+       if (IS_ERR(dsi->regs)) {
+               err = PTR_ERR(dsi->regs);
+               goto remove;
+       }
 
        dsi->mipi = tegra_mipi_request(&pdev->dev, pdev->dev.of_node);
-       if (IS_ERR(dsi->mipi))
-               return PTR_ERR(dsi->mipi);
+       if (IS_ERR(dsi->mipi)) {
+               err = PTR_ERR(dsi->mipi);
+               goto remove;
+       }
 
        dsi->host.ops = &tegra_dsi_host_ops;
        dsi->host.dev = &pdev->dev;
@@ -1659,9 +1675,12 @@ static int tegra_dsi_probe(struct platform_device *pdev)
        return 0;
 
 unregister:
+       pm_runtime_disable(&pdev->dev);
        mipi_dsi_host_unregister(&dsi->host);
 mipi_free:
        tegra_mipi_free(dsi->mipi);
+remove:
+       tegra_output_remove(&dsi->output);
        return err;
 }
 
index a1fcee665023b387ddaf7d0ace08d0262b4e58f8..09987e372e3ef77139575f3efdcd495f996297b6 100644 (file)
@@ -24,6 +24,7 @@
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_debugfs.h>
+#include <drm/drm_edid.h>
 #include <drm/drm_eld.h>
 #include <drm/drm_file.h>
 #include <drm/drm_fourcc.h>
@@ -1856,12 +1857,14 @@ static int tegra_hdmi_probe(struct platform_device *pdev)
                return err;
 
        hdmi->regs = devm_platform_ioremap_resource(pdev, 0);
-       if (IS_ERR(hdmi->regs))
-               return PTR_ERR(hdmi->regs);
+       if (IS_ERR(hdmi->regs)) {
+               err = PTR_ERR(hdmi->regs);
+               goto remove;
+       }
 
        err = platform_get_irq(pdev, 0);
        if (err < 0)
-               return err;
+               goto remove;
 
        hdmi->irq = err;
 
@@ -1870,18 +1873,18 @@ static int tegra_hdmi_probe(struct platform_device *pdev)
        if (err < 0) {
                dev_err(&pdev->dev, "failed to request IRQ#%u: %d\n",
                        hdmi->irq, err);
-               return err;
+               goto remove;
        }
 
        platform_set_drvdata(pdev, hdmi);
 
        err = devm_pm_runtime_enable(&pdev->dev);
        if (err)
-               return err;
+               goto remove;
 
        err = devm_tegra_core_dev_init_opp_table_common(&pdev->dev);
        if (err)
-               return err;
+               goto remove;
 
        INIT_LIST_HEAD(&hdmi->client.list);
        hdmi->client.ops = &hdmi_client_ops;
@@ -1891,10 +1894,14 @@ static int tegra_hdmi_probe(struct platform_device *pdev)
        if (err < 0) {
                dev_err(&pdev->dev, "failed to register host1x client: %d\n",
                        err);
-               return err;
+               goto remove;
        }
 
        return 0;
+
+remove:
+       tegra_output_remove(&hdmi->output);
+       return err;
 }
 
 static void tegra_hdmi_remove(struct platform_device *pdev)
index dc2dcb5ca1c894ce384eec832c917196ba5c7aed..4da3c3d1abbc7f53f2c4db6dd6eca63db1be1a54 100644 (file)
@@ -8,6 +8,7 @@
 #include <linux/of.h>
 
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_edid.h>
 #include <drm/drm_of.h>
 #include <drm/drm_panel.h>
 #include <drm/drm_simple_kms_helper.h>
@@ -142,8 +143,10 @@ int tegra_output_probe(struct tegra_output *output)
                                        GPIOD_IN,
                                        "HDMI hotplug detect");
        if (IS_ERR(output->hpd_gpio)) {
-               if (PTR_ERR(output->hpd_gpio) != -ENOENT)
-                       return PTR_ERR(output->hpd_gpio);
+               if (PTR_ERR(output->hpd_gpio) != -ENOENT) {
+                       err = PTR_ERR(output->hpd_gpio);
+                       goto put_i2c;
+               }
 
                output->hpd_gpio = NULL;
        }
@@ -152,7 +155,7 @@ int tegra_output_probe(struct tegra_output *output)
                err = gpiod_to_irq(output->hpd_gpio);
                if (err < 0) {
                        dev_err(output->dev, "gpiod_to_irq(): %d\n", err);
-                       return err;
+                       goto put_i2c;
                }
 
                output->hpd_irq = err;
@@ -165,7 +168,7 @@ int tegra_output_probe(struct tegra_output *output)
                if (err < 0) {
                        dev_err(output->dev, "failed to request IRQ#%u: %d\n",
                                output->hpd_irq, err);
-                       return err;
+                       goto put_i2c;
                }
 
                output->connector.polled = DRM_CONNECTOR_POLL_HPD;
@@ -179,6 +182,12 @@ int tegra_output_probe(struct tegra_output *output)
        }
 
        return 0;
+
+put_i2c:
+       if (output->ddc)
+               i2c_put_adapter(output->ddc);
+
+       return err;
 }
 
 void tegra_output_remove(struct tegra_output *output)
index fc66bbd913b24881612fec3f53d5fdf1c34669d1..1e8ec50b759e467ed608a444f25059b7b03bac55 100644 (file)
@@ -225,26 +225,28 @@ int tegra_dc_rgb_probe(struct tegra_dc *dc)
        rgb->clk = devm_clk_get(dc->dev, NULL);
        if (IS_ERR(rgb->clk)) {
                dev_err(dc->dev, "failed to get clock\n");
-               return PTR_ERR(rgb->clk);
+               err = PTR_ERR(rgb->clk);
+               goto remove;
        }
 
        rgb->clk_parent = devm_clk_get(dc->dev, "parent");
        if (IS_ERR(rgb->clk_parent)) {
                dev_err(dc->dev, "failed to get parent clock\n");
-               return PTR_ERR(rgb->clk_parent);
+               err = PTR_ERR(rgb->clk_parent);
+               goto remove;
        }
 
        err = clk_set_parent(rgb->clk, rgb->clk_parent);
        if (err < 0) {
                dev_err(dc->dev, "failed to set parent clock: %d\n", err);
-               return err;
+               goto remove;
        }
 
        rgb->pll_d_out0 = clk_get_sys(NULL, "pll_d_out0");
        if (IS_ERR(rgb->pll_d_out0)) {
                err = PTR_ERR(rgb->pll_d_out0);
                dev_err(dc->dev, "failed to get pll_d_out0: %d\n", err);
-               return err;
+               goto remove;
        }
 
        if (dc->soc->has_pll_d2_out0) {
@@ -252,13 +254,19 @@ int tegra_dc_rgb_probe(struct tegra_dc *dc)
                if (IS_ERR(rgb->pll_d2_out0)) {
                        err = PTR_ERR(rgb->pll_d2_out0);
                        dev_err(dc->dev, "failed to get pll_d2_out0: %d\n", err);
-                       return err;
+                       goto put_pll;
                }
        }
 
        dc->rgb = &rgb->output;
 
        return 0;
+
+put_pll:
+       clk_put(rgb->pll_d_out0);
+remove:
+       tegra_output_remove(&rgb->output);
+       return err;
 }
 
 void tegra_dc_rgb_remove(struct tegra_dc *dc)
index 83341576630d8fc0de45ab5bd8f6031719aba8a4..bad3b8fcc72692eaf89fe82e1a0c70abc00a6b79 100644 (file)
@@ -20,6 +20,7 @@
 #include <drm/display/drm_scdc_helper.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_debugfs.h>
+#include <drm/drm_edid.h>
 #include <drm/drm_eld.h>
 #include <drm/drm_file.h>
 #include <drm/drm_panel.h>
index 1652dca11d30c7d57b81789062ad21a44ae588bf..76eb273c9b3648a87da6255c04f672e92cb2e41f 100644 (file)
@@ -12,6 +12,7 @@
 #define TEST_TIMEOUT_MS        100
 
 struct managed_test_priv {
+       struct drm_device *drm;
        bool action_done;
        wait_queue_head_t action_wq;
 };
@@ -24,44 +25,88 @@ static void drm_action(struct drm_device *drm, void *ptr)
        wake_up_interruptible(&priv->action_wq);
 }
 
-static void drm_test_managed_run_action(struct kunit *test)
+/*
+ * The test verifies that the release action is called when
+ * drmm_release_action is called.
+ */
+static void drm_test_managed_release_action(struct kunit *test)
 {
-       struct managed_test_priv *priv;
-       struct drm_device *drm;
-       struct device *dev;
+       struct managed_test_priv *priv = test->priv;
        int ret;
 
-       priv = kunit_kzalloc(test, sizeof(*priv), GFP_KERNEL);
-       KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv);
-       init_waitqueue_head(&priv->action_wq);
+       ret = drmm_add_action_or_reset(priv->drm, drm_action, priv);
+       KUNIT_EXPECT_EQ(test, ret, 0);
 
-       dev = drm_kunit_helper_alloc_device(test);
-       KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev);
+       ret = drm_dev_register(priv->drm, 0);
+       KUNIT_ASSERT_EQ(test, ret, 0);
+
+       drmm_release_action(priv->drm, drm_action, priv);
+       ret = wait_event_interruptible_timeout(priv->action_wq, priv->action_done,
+                                              msecs_to_jiffies(TEST_TIMEOUT_MS));
+       KUNIT_EXPECT_GT(test, ret, 0);
+
+       drm_dev_unregister(priv->drm);
+       drm_kunit_helper_free_device(test, priv->drm->dev);
+}
 
-       drm = __drm_kunit_helper_alloc_drm_device(test, dev, sizeof(*drm), 0, DRIVER_MODESET);
-       KUNIT_ASSERT_NOT_ERR_OR_NULL(test, drm);
+/*
+ * The test verifies that the release action is called automatically when the
+ * device is released.
+ */
+static void drm_test_managed_run_action(struct kunit *test)
+{
+       struct managed_test_priv *priv = test->priv;
+       int ret;
 
-       ret = drmm_add_action_or_reset(drm, drm_action, priv);
+       ret = drmm_add_action_or_reset(priv->drm, drm_action, priv);
        KUNIT_EXPECT_EQ(test, ret, 0);
 
-       ret = drm_dev_register(drm, 0);
+       ret = drm_dev_register(priv->drm, 0);
        KUNIT_ASSERT_EQ(test, ret, 0);
 
-       drm_dev_unregister(drm);
-       drm_kunit_helper_free_device(test, dev);
+       drm_dev_unregister(priv->drm);
+       drm_kunit_helper_free_device(test, priv->drm->dev);
 
        ret = wait_event_interruptible_timeout(priv->action_wq, priv->action_done,
                                               msecs_to_jiffies(TEST_TIMEOUT_MS));
        KUNIT_EXPECT_GT(test, ret, 0);
 }
 
+static int drm_managed_test_init(struct kunit *test)
+{
+       struct managed_test_priv *priv;
+       struct device *dev;
+
+       priv = kunit_kzalloc(test, sizeof(*priv), GFP_KERNEL);
+       KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv);
+       init_waitqueue_head(&priv->action_wq);
+
+       dev = drm_kunit_helper_alloc_device(test);
+       KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev);
+
+       /*
+        * DRM device can't be embedded in priv, since priv->action_done needs
+        * to remain allocated beyond both parent device and drm_device
+        * lifetime.
+        */
+       priv->drm = __drm_kunit_helper_alloc_drm_device(test, dev, sizeof(*priv->drm), 0,
+                                                       DRIVER_MODESET);
+       KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv->drm);
+
+       test->priv = priv;
+
+       return 0;
+}
+
 static struct kunit_case drm_managed_tests[] = {
+       KUNIT_CASE(drm_test_managed_release_action),
        KUNIT_CASE(drm_test_managed_run_action),
        {}
 };
 
 static struct kunit_suite drm_managed_test_suite = {
-       .name = "drm-test-managed",
+       .name = "drm_managed",
+       .init = drm_managed_test_init,
        .test_cases = drm_managed_tests
 };
 
index 23bf16f596f617631985c5a039b5c203b67747ca..cd5eefa06060df44343e926ec0035f6a28b85675 100644 (file)
@@ -182,9 +182,6 @@ static void tilcdc_fini(struct drm_device *dev)
        if (priv->clk)
                clk_put(priv->clk);
 
-       if (priv->mmio)
-               iounmap(priv->mmio);
-
        if (priv->wq)
                destroy_workqueue(priv->wq);
 
@@ -201,7 +198,6 @@ static int tilcdc_init(const struct drm_driver *ddrv, struct device *dev)
        struct platform_device *pdev = to_platform_device(dev);
        struct device_node *node = dev->of_node;
        struct tilcdc_drm_private *priv;
-       struct resource *res;
        u32 bpp = 0;
        int ret;
 
@@ -226,17 +222,10 @@ static int tilcdc_init(const struct drm_driver *ddrv, struct device *dev)
                goto init_failed;
        }
 
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res) {
-               dev_err(dev, "failed to get memory resource\n");
-               ret = -EINVAL;
-               goto init_failed;
-       }
-
-       priv->mmio = ioremap(res->start, resource_size(res));
-       if (!priv->mmio) {
-               dev_err(dev, "failed to ioremap\n");
-               ret = -ENOMEM;
+       priv->mmio = devm_platform_ioremap_resource(pdev, 0);
+       if (IS_ERR(priv->mmio)) {
+               dev_err(dev, "failed to request / ioremap\n");
+               ret = PTR_ERR(priv->mmio);
                goto init_failed;
        }
 
index ec87c4fc1ad5517e76405116650a66d89940f479..468535f7eed28da86f0d2226baa2e2bcb5a95bdb 100644 (file)
@@ -3,4 +3,7 @@
 obj-$(CONFIG_DRM_TTM_KUNIT_TEST) += \
         ttm_device_test.o \
         ttm_pool_test.o \
+        ttm_resource_test.o \
+        ttm_tt_test.o \
+        ttm_bo_test.o \
         ttm_kunit_helpers.o
diff --git a/drivers/gpu/drm/ttm/tests/ttm_bo_test.c b/drivers/gpu/drm/ttm/tests/ttm_bo_test.c
new file mode 100644 (file)
index 0000000..1f8a4f8
--- /dev/null
@@ -0,0 +1,622 @@
+// SPDX-License-Identifier: GPL-2.0 AND MIT
+/*
+ * Copyright Â© 2023 Intel Corporation
+ */
+#include <linux/dma-resv.h>
+#include <linux/kthread.h>
+#include <linux/delay.h>
+#include <linux/timer.h>
+#include <linux/jiffies.h>
+#include <linux/mutex.h>
+#include <linux/ww_mutex.h>
+
+#include <drm/ttm/ttm_resource.h>
+#include <drm/ttm/ttm_placement.h>
+#include <drm/ttm/ttm_tt.h>
+
+#include "ttm_kunit_helpers.h"
+
+#define BO_SIZE                SZ_8K
+
+struct ttm_bo_test_case {
+       const char *description;
+       bool interruptible;
+       bool no_wait;
+};
+
+static const struct ttm_bo_test_case ttm_bo_reserved_cases[] = {
+       {
+               .description = "Cannot be interrupted and sleeps",
+               .interruptible = false,
+               .no_wait = false,
+       },
+       {
+               .description = "Cannot be interrupted, locks straight away",
+               .interruptible = false,
+               .no_wait = true,
+       },
+       {
+               .description = "Can be interrupted, sleeps",
+               .interruptible = true,
+               .no_wait = false,
+       },
+};
+
+static void ttm_bo_init_case_desc(const struct ttm_bo_test_case *t,
+                                 char *desc)
+{
+       strscpy(desc, t->description, KUNIT_PARAM_DESC_SIZE);
+}
+
+KUNIT_ARRAY_PARAM(ttm_bo_reserve, ttm_bo_reserved_cases, ttm_bo_init_case_desc);
+
+static void ttm_bo_reserve_optimistic_no_ticket(struct kunit *test)
+{
+       const struct ttm_bo_test_case *params = test->param_value;
+       struct ttm_buffer_object *bo;
+       int err;
+
+       bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE);
+
+       err = ttm_bo_reserve(bo, params->interruptible, params->no_wait, NULL);
+       KUNIT_ASSERT_EQ(test, err, 0);
+
+       dma_resv_unlock(bo->base.resv);
+}
+
+static void ttm_bo_reserve_locked_no_sleep(struct kunit *test)
+{
+       struct ttm_buffer_object *bo;
+       bool interruptible = false;
+       bool no_wait = true;
+       int err;
+
+       bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE);
+
+       /* Let's lock it beforehand */
+       dma_resv_lock(bo->base.resv, NULL);
+
+       err = ttm_bo_reserve(bo, interruptible, no_wait, NULL);
+       dma_resv_unlock(bo->base.resv);
+
+       KUNIT_ASSERT_EQ(test, err, -EBUSY);
+}
+
+static void ttm_bo_reserve_no_wait_ticket(struct kunit *test)
+{
+       struct ttm_buffer_object *bo;
+       struct ww_acquire_ctx ctx;
+       bool interruptible = false;
+       bool no_wait = true;
+       int err;
+
+       ww_acquire_init(&ctx, &reservation_ww_class);
+
+       bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE);
+
+       err = ttm_bo_reserve(bo, interruptible, no_wait, &ctx);
+       KUNIT_ASSERT_EQ(test, err, -EBUSY);
+
+       ww_acquire_fini(&ctx);
+}
+
+static void ttm_bo_reserve_double_resv(struct kunit *test)
+{
+       struct ttm_buffer_object *bo;
+       struct ww_acquire_ctx ctx;
+       bool interruptible = false;
+       bool no_wait = false;
+       int err;
+
+       ww_acquire_init(&ctx, &reservation_ww_class);
+
+       bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE);
+
+       err = ttm_bo_reserve(bo, interruptible, no_wait, &ctx);
+       KUNIT_ASSERT_EQ(test, err, 0);
+
+       err = ttm_bo_reserve(bo, interruptible, no_wait, &ctx);
+
+       dma_resv_unlock(bo->base.resv);
+       ww_acquire_fini(&ctx);
+
+       KUNIT_ASSERT_EQ(test, err, -EALREADY);
+}
+
+/*
+ * A test case heavily inspired by ww_test_edeadlk_normal(). It injects
+ * a deadlock by manipulating the sequence number of the context that holds
+ * dma_resv lock of bo2 so the other context is "wounded" and has to back off
+ * (indicated by -EDEADLK). The subtest checks if ttm_bo_reserve() properly
+ * propagates that error.
+ */
+static void ttm_bo_reserve_deadlock(struct kunit *test)
+{
+       struct ttm_buffer_object *bo1, *bo2;
+       struct ww_acquire_ctx ctx1, ctx2;
+       bool interruptible = false;
+       bool no_wait = false;
+       int err;
+
+       bo1 = ttm_bo_kunit_init(test, test->priv, BO_SIZE);
+       bo2 = ttm_bo_kunit_init(test, test->priv, BO_SIZE);
+
+       ww_acquire_init(&ctx1, &reservation_ww_class);
+       mutex_lock(&bo2->base.resv->lock.base);
+
+       /* The deadlock will be caught by WW mutex, don't warn about it */
+       lock_release(&bo2->base.resv->lock.base.dep_map, 1);
+
+       bo2->base.resv->lock.ctx = &ctx2;
+       ctx2 = ctx1;
+       ctx2.stamp--; /* Make the context holding the lock younger */
+
+       err = ttm_bo_reserve(bo1, interruptible, no_wait, &ctx1);
+       KUNIT_ASSERT_EQ(test, err, 0);
+
+       err = ttm_bo_reserve(bo2, interruptible, no_wait, &ctx1);
+       KUNIT_ASSERT_EQ(test, err, -EDEADLK);
+
+       dma_resv_unlock(bo1->base.resv);
+       ww_acquire_fini(&ctx1);
+}
+
+#if IS_BUILTIN(CONFIG_DRM_TTM_KUNIT_TEST)
+struct signal_timer {
+       struct timer_list timer;
+       struct ww_acquire_ctx *ctx;
+};
+
+static void signal_for_ttm_bo_reserve(struct timer_list *t)
+{
+       struct signal_timer *s_timer = from_timer(s_timer, t, timer);
+       struct task_struct *task = s_timer->ctx->task;
+
+       do_send_sig_info(SIGTERM, SEND_SIG_PRIV, task, PIDTYPE_PID);
+}
+
+static int threaded_ttm_bo_reserve(void *arg)
+{
+       struct ttm_buffer_object *bo = arg;
+       struct signal_timer s_timer;
+       struct ww_acquire_ctx ctx;
+       bool interruptible = true;
+       bool no_wait = false;
+       int err;
+
+       ww_acquire_init(&ctx, &reservation_ww_class);
+
+       /* Prepare a signal that will interrupt the reservation attempt */
+       timer_setup_on_stack(&s_timer.timer, &signal_for_ttm_bo_reserve, 0);
+       s_timer.ctx = &ctx;
+
+       mod_timer(&s_timer.timer, msecs_to_jiffies(100));
+
+       err = ttm_bo_reserve(bo, interruptible, no_wait, &ctx);
+
+       timer_delete_sync(&s_timer.timer);
+       destroy_timer_on_stack(&s_timer.timer);
+
+       ww_acquire_fini(&ctx);
+
+       return err;
+}
+
+static void ttm_bo_reserve_interrupted(struct kunit *test)
+{
+       struct ttm_buffer_object *bo;
+       struct task_struct *task;
+       int err;
+
+       bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE);
+
+       task = kthread_create(threaded_ttm_bo_reserve, bo, "ttm-bo-reserve");
+
+       if (IS_ERR(task))
+               KUNIT_FAIL(test, "Couldn't create ttm bo reserve task\n");
+
+       /* Take a lock so the threaded reserve has to wait */
+       mutex_lock(&bo->base.resv->lock.base);
+
+       wake_up_process(task);
+       msleep(20);
+       err = kthread_stop(task);
+
+       mutex_unlock(&bo->base.resv->lock.base);
+
+       KUNIT_ASSERT_EQ(test, err, -ERESTARTSYS);
+}
+#endif /* IS_BUILTIN(CONFIG_DRM_TTM_KUNIT_TEST) */
+
+static void ttm_bo_unreserve_basic(struct kunit *test)
+{
+       struct ttm_test_devices *priv = test->priv;
+       struct ttm_buffer_object *bo;
+       struct ttm_device *ttm_dev;
+       struct ttm_resource *res1, *res2;
+       struct ttm_place *place;
+       struct ttm_resource_manager *man;
+       unsigned int bo_prio = TTM_MAX_BO_PRIORITY - 1;
+       uint32_t mem_type = TTM_PL_SYSTEM;
+       int err;
+
+       place = ttm_place_kunit_init(test, mem_type, 0);
+
+       ttm_dev = kunit_kzalloc(test, sizeof(*ttm_dev), GFP_KERNEL);
+       KUNIT_ASSERT_NOT_NULL(test, ttm_dev);
+
+       err = ttm_device_kunit_init(priv, ttm_dev, false, false);
+       KUNIT_ASSERT_EQ(test, err, 0);
+       priv->ttm_dev = ttm_dev;
+
+       bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE);
+       bo->priority = bo_prio;
+
+       err = ttm_resource_alloc(bo, place, &res1);
+       KUNIT_ASSERT_EQ(test, err, 0);
+
+       bo->resource = res1;
+
+       /* Add a dummy resource to populate LRU */
+       ttm_resource_alloc(bo, place, &res2);
+
+       dma_resv_lock(bo->base.resv, NULL);
+       ttm_bo_unreserve(bo);
+
+       man = ttm_manager_type(priv->ttm_dev, mem_type);
+       KUNIT_ASSERT_EQ(test,
+                       list_is_last(&res1->lru, &man->lru[bo->priority]), 1);
+
+       ttm_resource_free(bo, &res2);
+       ttm_resource_free(bo, &res1);
+}
+
+static void ttm_bo_unreserve_pinned(struct kunit *test)
+{
+       struct ttm_test_devices *priv = test->priv;
+       struct ttm_buffer_object *bo;
+       struct ttm_device *ttm_dev;
+       struct ttm_resource *res1, *res2;
+       struct ttm_place *place;
+       uint32_t mem_type = TTM_PL_SYSTEM;
+       int err;
+
+       ttm_dev = kunit_kzalloc(test, sizeof(*ttm_dev), GFP_KERNEL);
+       KUNIT_ASSERT_NOT_NULL(test, ttm_dev);
+
+       err = ttm_device_kunit_init(priv, ttm_dev, false, false);
+       KUNIT_ASSERT_EQ(test, err, 0);
+       priv->ttm_dev = ttm_dev;
+
+       bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE);
+       place = ttm_place_kunit_init(test, mem_type, 0);
+
+       dma_resv_lock(bo->base.resv, NULL);
+       ttm_bo_pin(bo);
+
+       err = ttm_resource_alloc(bo, place, &res1);
+       KUNIT_ASSERT_EQ(test, err, 0);
+       bo->resource = res1;
+
+       /* Add a dummy resource to the pinned list */
+       err = ttm_resource_alloc(bo, place, &res2);
+       KUNIT_ASSERT_EQ(test, err, 0);
+       KUNIT_ASSERT_EQ(test,
+                       list_is_last(&res2->lru, &priv->ttm_dev->pinned), 1);
+
+       ttm_bo_unreserve(bo);
+       KUNIT_ASSERT_EQ(test,
+                       list_is_last(&res1->lru, &priv->ttm_dev->pinned), 1);
+
+       ttm_resource_free(bo, &res1);
+       ttm_resource_free(bo, &res2);
+}
+
+static void ttm_bo_unreserve_bulk(struct kunit *test)
+{
+       struct ttm_test_devices *priv = test->priv;
+       struct ttm_lru_bulk_move lru_bulk_move;
+       struct ttm_lru_bulk_move_pos *pos;
+       struct ttm_buffer_object *bo1, *bo2;
+       struct ttm_resource *res1, *res2;
+       struct ttm_device *ttm_dev;
+       struct ttm_place *place;
+       uint32_t mem_type = TTM_PL_SYSTEM;
+       unsigned int bo_priority = 0;
+       int err;
+
+       ttm_lru_bulk_move_init(&lru_bulk_move);
+
+       place = ttm_place_kunit_init(test, mem_type, 0);
+
+       ttm_dev = kunit_kzalloc(test, sizeof(*ttm_dev), GFP_KERNEL);
+       KUNIT_ASSERT_NOT_NULL(test, ttm_dev);
+
+       err = ttm_device_kunit_init(priv, ttm_dev, false, false);
+       KUNIT_ASSERT_EQ(test, err, 0);
+       priv->ttm_dev = ttm_dev;
+
+       bo1 = ttm_bo_kunit_init(test, test->priv, BO_SIZE);
+       bo2 = ttm_bo_kunit_init(test, test->priv, BO_SIZE);
+
+       dma_resv_lock(bo1->base.resv, NULL);
+       ttm_bo_set_bulk_move(bo1, &lru_bulk_move);
+       dma_resv_unlock(bo1->base.resv);
+
+       err = ttm_resource_alloc(bo1, place, &res1);
+       KUNIT_ASSERT_EQ(test, err, 0);
+       bo1->resource = res1;
+
+       dma_resv_lock(bo2->base.resv, NULL);
+       ttm_bo_set_bulk_move(bo2, &lru_bulk_move);
+       dma_resv_unlock(bo2->base.resv);
+
+       err = ttm_resource_alloc(bo2, place, &res2);
+       KUNIT_ASSERT_EQ(test, err, 0);
+       bo2->resource = res2;
+
+       ttm_bo_reserve(bo1, false, false, NULL);
+       ttm_bo_unreserve(bo1);
+
+       pos = &lru_bulk_move.pos[mem_type][bo_priority];
+       KUNIT_ASSERT_PTR_EQ(test, res1, pos->last);
+
+       ttm_resource_free(bo1, &res1);
+       ttm_resource_free(bo2, &res2);
+}
+
+static void ttm_bo_put_basic(struct kunit *test)
+{
+       struct ttm_test_devices *priv = test->priv;
+       struct ttm_buffer_object *bo;
+       struct ttm_resource *res;
+       struct ttm_device *ttm_dev;
+       struct ttm_place *place;
+       uint32_t mem_type = TTM_PL_SYSTEM;
+       int err;
+
+       place = ttm_place_kunit_init(test, mem_type, 0);
+
+       ttm_dev = kunit_kzalloc(test, sizeof(*ttm_dev), GFP_KERNEL);
+       KUNIT_ASSERT_NOT_NULL(test, ttm_dev);
+
+       err = ttm_device_kunit_init(priv, ttm_dev, false, false);
+       KUNIT_ASSERT_EQ(test, err, 0);
+       priv->ttm_dev = ttm_dev;
+
+       bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE);
+       bo->type = ttm_bo_type_device;
+
+       err = ttm_resource_alloc(bo, place, &res);
+       KUNIT_ASSERT_EQ(test, err, 0);
+       bo->resource = res;
+
+       dma_resv_lock(bo->base.resv, NULL);
+       err = ttm_tt_create(bo, false);
+       dma_resv_unlock(bo->base.resv);
+       KUNIT_EXPECT_EQ(test, err, 0);
+
+       ttm_bo_put(bo);
+}
+
+static const char *mock_name(struct dma_fence *f)
+{
+       return "kunit-ttm-bo-put";
+}
+
+static const struct dma_fence_ops mock_fence_ops = {
+       .get_driver_name = mock_name,
+       .get_timeline_name = mock_name,
+};
+
+static void ttm_bo_put_shared_resv(struct kunit *test)
+{
+       struct ttm_test_devices *priv = test->priv;
+       struct ttm_buffer_object *bo;
+       struct dma_resv *external_resv;
+       struct dma_fence *fence;
+       /* A dummy DMA fence lock */
+       spinlock_t fence_lock;
+       struct ttm_device *ttm_dev;
+       int err;
+
+       ttm_dev = kunit_kzalloc(test, sizeof(*ttm_dev), GFP_KERNEL);
+       KUNIT_ASSERT_NOT_NULL(test, ttm_dev);
+
+       err = ttm_device_kunit_init(priv, ttm_dev, false, false);
+       KUNIT_ASSERT_EQ(test, err, 0);
+       priv->ttm_dev = ttm_dev;
+
+       external_resv = kunit_kzalloc(test, sizeof(*ttm_dev), GFP_KERNEL);
+       KUNIT_ASSERT_NOT_NULL(test, external_resv);
+
+       dma_resv_init(external_resv);
+
+       fence = kunit_kzalloc(test, sizeof(*fence), GFP_KERNEL);
+       KUNIT_ASSERT_NOT_NULL(test, fence);
+
+       spin_lock_init(&fence_lock);
+       dma_fence_init(fence, &mock_fence_ops, &fence_lock, 0, 0);
+
+       dma_resv_lock(external_resv, NULL);
+       dma_resv_reserve_fences(external_resv, 1);
+       dma_resv_add_fence(external_resv, fence, DMA_RESV_USAGE_BOOKKEEP);
+       dma_resv_unlock(external_resv);
+
+       dma_fence_signal(fence);
+
+       bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE);
+       bo->type = ttm_bo_type_device;
+       bo->base.resv = external_resv;
+
+       ttm_bo_put(bo);
+}
+
+static void ttm_bo_pin_basic(struct kunit *test)
+{
+       struct ttm_test_devices *priv = test->priv;
+       struct ttm_buffer_object *bo;
+       struct ttm_device *ttm_dev;
+       unsigned int no_pins = 3;
+       int err;
+
+       ttm_dev = kunit_kzalloc(test, sizeof(*ttm_dev), GFP_KERNEL);
+       KUNIT_ASSERT_NOT_NULL(test, ttm_dev);
+
+       err = ttm_device_kunit_init(priv, ttm_dev, false, false);
+       KUNIT_ASSERT_EQ(test, err, 0);
+       priv->ttm_dev = ttm_dev;
+
+       bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE);
+
+       for (int i = 0; i < no_pins; i++) {
+               dma_resv_lock(bo->base.resv, NULL);
+               ttm_bo_pin(bo);
+               dma_resv_unlock(bo->base.resv);
+       }
+
+       KUNIT_ASSERT_EQ(test, bo->pin_count, no_pins);
+}
+
+static void ttm_bo_pin_unpin_resource(struct kunit *test)
+{
+       struct ttm_test_devices *priv = test->priv;
+       struct ttm_lru_bulk_move lru_bulk_move;
+       struct ttm_lru_bulk_move_pos *pos;
+       struct ttm_buffer_object *bo;
+       struct ttm_resource *res;
+       struct ttm_device *ttm_dev;
+       struct ttm_place *place;
+       uint32_t mem_type = TTM_PL_SYSTEM;
+       unsigned int bo_priority = 0;
+       int err;
+
+       ttm_lru_bulk_move_init(&lru_bulk_move);
+
+       place = ttm_place_kunit_init(test, mem_type, 0);
+
+       ttm_dev = kunit_kzalloc(test, sizeof(*ttm_dev), GFP_KERNEL);
+       KUNIT_ASSERT_NOT_NULL(test, ttm_dev);
+
+       err = ttm_device_kunit_init(priv, ttm_dev, false, false);
+       KUNIT_ASSERT_EQ(test, err, 0);
+       priv->ttm_dev = ttm_dev;
+
+       bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE);
+
+       err = ttm_resource_alloc(bo, place, &res);
+       KUNIT_ASSERT_EQ(test, err, 0);
+       bo->resource = res;
+
+       dma_resv_lock(bo->base.resv, NULL);
+       ttm_bo_set_bulk_move(bo, &lru_bulk_move);
+       ttm_bo_pin(bo);
+       dma_resv_unlock(bo->base.resv);
+
+       pos = &lru_bulk_move.pos[mem_type][bo_priority];
+
+       KUNIT_ASSERT_EQ(test, bo->pin_count, 1);
+       KUNIT_ASSERT_NULL(test, pos->first);
+       KUNIT_ASSERT_NULL(test, pos->last);
+
+       dma_resv_lock(bo->base.resv, NULL);
+       ttm_bo_unpin(bo);
+       dma_resv_unlock(bo->base.resv);
+
+       KUNIT_ASSERT_PTR_EQ(test, res, pos->last);
+       KUNIT_ASSERT_EQ(test, bo->pin_count, 0);
+
+       ttm_resource_free(bo, &res);
+}
+
+static void ttm_bo_multiple_pin_one_unpin(struct kunit *test)
+{
+       struct ttm_test_devices *priv = test->priv;
+       struct ttm_lru_bulk_move lru_bulk_move;
+       struct ttm_lru_bulk_move_pos *pos;
+       struct ttm_buffer_object *bo;
+       struct ttm_resource *res;
+       struct ttm_device *ttm_dev;
+       struct ttm_place *place;
+       uint32_t mem_type = TTM_PL_SYSTEM;
+       unsigned int bo_priority = 0;
+       int err;
+
+       ttm_lru_bulk_move_init(&lru_bulk_move);
+
+       place = ttm_place_kunit_init(test, mem_type, 0);
+
+       ttm_dev = kunit_kzalloc(test, sizeof(*ttm_dev), GFP_KERNEL);
+       KUNIT_ASSERT_NOT_NULL(test, ttm_dev);
+
+       err = ttm_device_kunit_init(priv, ttm_dev, false, false);
+       KUNIT_ASSERT_EQ(test, err, 0);
+       priv->ttm_dev = ttm_dev;
+
+       bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE);
+
+       err = ttm_resource_alloc(bo, place, &res);
+       KUNIT_ASSERT_EQ(test, err, 0);
+       bo->resource = res;
+
+       dma_resv_lock(bo->base.resv, NULL);
+       ttm_bo_set_bulk_move(bo, &lru_bulk_move);
+
+       /* Multiple pins */
+       ttm_bo_pin(bo);
+       ttm_bo_pin(bo);
+
+       dma_resv_unlock(bo->base.resv);
+
+       pos = &lru_bulk_move.pos[mem_type][bo_priority];
+
+       KUNIT_ASSERT_EQ(test, bo->pin_count, 2);
+       KUNIT_ASSERT_NULL(test, pos->first);
+       KUNIT_ASSERT_NULL(test, pos->last);
+
+       dma_resv_lock(bo->base.resv, NULL);
+       ttm_bo_unpin(bo);
+       dma_resv_unlock(bo->base.resv);
+
+       KUNIT_ASSERT_EQ(test, bo->pin_count, 1);
+       KUNIT_ASSERT_NULL(test, pos->first);
+       KUNIT_ASSERT_NULL(test, pos->last);
+
+       dma_resv_lock(bo->base.resv, NULL);
+       ttm_bo_unpin(bo);
+       dma_resv_unlock(bo->base.resv);
+
+       ttm_resource_free(bo, &res);
+}
+
+static struct kunit_case ttm_bo_test_cases[] = {
+       KUNIT_CASE_PARAM(ttm_bo_reserve_optimistic_no_ticket,
+                        ttm_bo_reserve_gen_params),
+       KUNIT_CASE(ttm_bo_reserve_locked_no_sleep),
+       KUNIT_CASE(ttm_bo_reserve_no_wait_ticket),
+       KUNIT_CASE(ttm_bo_reserve_double_resv),
+#if IS_BUILTIN(CONFIG_DRM_TTM_KUNIT_TEST)
+       KUNIT_CASE(ttm_bo_reserve_interrupted),
+#endif
+       KUNIT_CASE(ttm_bo_reserve_deadlock),
+       KUNIT_CASE(ttm_bo_unreserve_basic),
+       KUNIT_CASE(ttm_bo_unreserve_pinned),
+       KUNIT_CASE(ttm_bo_unreserve_bulk),
+       KUNIT_CASE(ttm_bo_put_basic),
+       KUNIT_CASE(ttm_bo_put_shared_resv),
+       KUNIT_CASE(ttm_bo_pin_basic),
+       KUNIT_CASE(ttm_bo_pin_unpin_resource),
+       KUNIT_CASE(ttm_bo_multiple_pin_one_unpin),
+       {}
+};
+
+static struct kunit_suite ttm_bo_test_suite = {
+       .name = "ttm_bo",
+       .init = ttm_test_devices_init,
+       .exit = ttm_test_devices_fini,
+       .test_cases = ttm_bo_test_cases,
+};
+
+kunit_test_suites(&ttm_bo_test_suite);
+
+MODULE_LICENSE("GPL");
index 81661d8827aa25263729af9da5c4e9e8b9d71b0a..7b7c1fa805fcb093fd583cd51b34272f1b347b70 100644 (file)
@@ -2,9 +2,33 @@
 /*
  * Copyright Â© 2023 Intel Corporation
  */
+#include <drm/ttm/ttm_tt.h>
+
 #include "ttm_kunit_helpers.h"
 
+static struct ttm_tt *ttm_tt_simple_create(struct ttm_buffer_object *bo,
+                                          uint32_t page_flags)
+{
+       struct ttm_tt *tt;
+
+       tt = kzalloc(sizeof(*tt), GFP_KERNEL);
+       ttm_tt_init(tt, bo, page_flags, ttm_cached, 0);
+
+       return tt;
+}
+
+static void ttm_tt_simple_destroy(struct ttm_device *bdev, struct ttm_tt *ttm)
+{
+       kfree(ttm);
+}
+
+static void dummy_ttm_bo_destroy(struct ttm_buffer_object *bo)
+{
+}
+
 struct ttm_device_funcs ttm_dev_funcs = {
+       .ttm_tt_create = ttm_tt_simple_create,
+       .ttm_tt_destroy = ttm_tt_simple_destroy,
 };
 EXPORT_SYMBOL_GPL(ttm_dev_funcs);
 
@@ -29,19 +53,41 @@ struct ttm_buffer_object *ttm_bo_kunit_init(struct kunit *test,
                                            struct ttm_test_devices *devs,
                                            size_t size)
 {
-       struct drm_gem_object gem_obj = { .size = size };
+       struct drm_gem_object gem_obj = { };
        struct ttm_buffer_object *bo;
+       int err;
 
        bo = kunit_kzalloc(test, sizeof(*bo), GFP_KERNEL);
        KUNIT_ASSERT_NOT_NULL(test, bo);
 
        bo->base = gem_obj;
+       err = drm_gem_object_init(devs->drm, &bo->base, size);
+       KUNIT_ASSERT_EQ(test, err, 0);
+
        bo->bdev = devs->ttm_dev;
+       bo->destroy = dummy_ttm_bo_destroy;
+
+       kref_init(&bo->kref);
 
        return bo;
 }
 EXPORT_SYMBOL_GPL(ttm_bo_kunit_init);
 
+struct ttm_place *ttm_place_kunit_init(struct kunit *test,
+                                      uint32_t mem_type, uint32_t flags)
+{
+       struct ttm_place *place;
+
+       place = kunit_kzalloc(test, sizeof(*place), GFP_KERNEL);
+       KUNIT_ASSERT_NOT_NULL(test, place);
+
+       place->mem_type = mem_type;
+       place->flags = flags;
+
+       return place;
+}
+EXPORT_SYMBOL_GPL(ttm_place_kunit_init);
+
 struct ttm_test_devices *ttm_test_devices_basic(struct kunit *test)
 {
        struct ttm_test_devices *devs;
index e261e3660d0b3d368d8f90d7a1fcd0916f8654e9..2f51c833a536745de740e42129fb031bc48ba9ed 100644 (file)
@@ -8,6 +8,7 @@
 #include <drm/drm_drv.h>
 #include <drm/ttm/ttm_device.h>
 #include <drm/ttm/ttm_bo.h>
+#include <drm/ttm/ttm_placement.h>
 
 #include <drm/drm_kunit_helpers.h>
 #include <kunit/test.h>
@@ -28,6 +29,8 @@ int ttm_device_kunit_init(struct ttm_test_devices *priv,
 struct ttm_buffer_object *ttm_bo_kunit_init(struct kunit *test,
                                            struct ttm_test_devices *devs,
                                            size_t size);
+struct ttm_place *ttm_place_kunit_init(struct kunit *test,
+                                      uint32_t mem_type, uint32_t flags);
 
 struct ttm_test_devices *ttm_test_devices_basic(struct kunit *test);
 struct ttm_test_devices *ttm_test_devices_all(struct kunit *test);
index cceaa18d4e46bb74882fa4f1d7e674aa75d83f9c..0a3fede84da92e46e7dca23e6404b45c361659ab 100644 (file)
@@ -78,10 +78,9 @@ static struct ttm_pool *ttm_pool_pre_populated(struct kunit *test,
        struct ttm_test_devices *devs = priv->devs;
        struct ttm_pool *pool;
        struct ttm_tt *tt;
-       unsigned long order = __fls(size / PAGE_SIZE);
        int err;
 
-       tt = ttm_tt_kunit_init(test, order, caching, size);
+       tt = ttm_tt_kunit_init(test, 0, caching, size);
        KUNIT_ASSERT_NOT_NULL(test, tt);
 
        pool = kunit_kzalloc(test, sizeof(*pool), GFP_KERNEL);
diff --git a/drivers/gpu/drm/ttm/tests/ttm_resource_test.c b/drivers/gpu/drm/ttm/tests/ttm_resource_test.c
new file mode 100644 (file)
index 0000000..029e1f0
--- /dev/null
@@ -0,0 +1,335 @@
+// SPDX-License-Identifier: GPL-2.0 AND MIT
+/*
+ * Copyright Â© 2023 Intel Corporation
+ */
+#include <drm/ttm/ttm_resource.h>
+
+#include "ttm_kunit_helpers.h"
+
+#define RES_SIZE               SZ_4K
+#define TTM_PRIV_DUMMY_REG     (TTM_NUM_MEM_TYPES - 1)
+
+struct ttm_resource_test_case {
+       const char *description;
+       uint32_t mem_type;
+       uint32_t flags;
+};
+
+struct ttm_resource_test_priv {
+       struct ttm_test_devices *devs;
+       struct ttm_buffer_object *bo;
+       struct ttm_place *place;
+};
+
+static const struct ttm_resource_manager_func ttm_resource_manager_mock_funcs = { };
+
+static int ttm_resource_test_init(struct kunit *test)
+{
+       struct ttm_resource_test_priv *priv;
+
+       priv = kunit_kzalloc(test, sizeof(*priv), GFP_KERNEL);
+       KUNIT_ASSERT_NOT_NULL(test, priv);
+
+       priv->devs = ttm_test_devices_all(test);
+       KUNIT_ASSERT_NOT_NULL(test, priv->devs);
+
+       test->priv = priv;
+
+       return 0;
+}
+
+static void ttm_resource_test_fini(struct kunit *test)
+{
+       struct ttm_resource_test_priv *priv = test->priv;
+
+       ttm_test_devices_put(test, priv->devs);
+}
+
+static void ttm_init_test_mocks(struct kunit *test,
+                               struct ttm_resource_test_priv *priv,
+                               uint32_t mem_type, uint32_t flags)
+{
+       size_t size = RES_SIZE;
+
+       /* Make sure we have what we need for a good BO mock */
+       KUNIT_ASSERT_NOT_NULL(test, priv->devs->ttm_dev);
+
+       priv->bo = ttm_bo_kunit_init(test, priv->devs, size);
+       priv->place = ttm_place_kunit_init(test, mem_type, flags);
+}
+
+static void ttm_init_test_manager(struct kunit *test,
+                                 struct ttm_resource_test_priv *priv,
+                                 uint32_t mem_type)
+{
+       struct ttm_device *ttm_dev = priv->devs->ttm_dev;
+       struct ttm_resource_manager *man;
+       size_t size = SZ_16K;
+
+       man = kunit_kzalloc(test, sizeof(*man), GFP_KERNEL);
+       KUNIT_ASSERT_NOT_NULL(test, man);
+
+       man->use_tt = false;
+       man->func = &ttm_resource_manager_mock_funcs;
+
+       ttm_resource_manager_init(man, ttm_dev, size);
+       ttm_set_driver_manager(ttm_dev, mem_type, man);
+       ttm_resource_manager_set_used(man, true);
+}
+
+static const struct ttm_resource_test_case ttm_resource_cases[] = {
+       {
+               .description = "Init resource in TTM_PL_SYSTEM",
+               .mem_type = TTM_PL_SYSTEM,
+       },
+       {
+               .description = "Init resource in TTM_PL_VRAM",
+               .mem_type = TTM_PL_VRAM,
+       },
+       {
+               .description = "Init resource in a private placement",
+               .mem_type = TTM_PRIV_DUMMY_REG,
+       },
+       {
+               .description = "Init resource in TTM_PL_SYSTEM, set placement flags",
+               .mem_type = TTM_PL_SYSTEM,
+               .flags = TTM_PL_FLAG_TOPDOWN,
+       },
+};
+
+static void ttm_resource_case_desc(const struct ttm_resource_test_case *t, char *desc)
+{
+       strscpy(desc, t->description, KUNIT_PARAM_DESC_SIZE);
+}
+
+KUNIT_ARRAY_PARAM(ttm_resource, ttm_resource_cases, ttm_resource_case_desc);
+
+static void ttm_resource_init_basic(struct kunit *test)
+{
+       const struct ttm_resource_test_case *params = test->param_value;
+       struct ttm_resource_test_priv *priv = test->priv;
+       struct ttm_resource *res;
+       struct ttm_buffer_object *bo;
+       struct ttm_place *place;
+       struct ttm_resource_manager *man;
+       uint64_t expected_usage;
+
+       ttm_init_test_mocks(test, priv, params->mem_type, params->flags);
+       bo = priv->bo;
+       place = priv->place;
+
+       if (params->mem_type > TTM_PL_SYSTEM)
+               ttm_init_test_manager(test, priv, params->mem_type);
+
+       res = kunit_kzalloc(test, sizeof(*res), GFP_KERNEL);
+       KUNIT_ASSERT_NOT_NULL(test, res);
+
+       man = ttm_manager_type(priv->devs->ttm_dev, place->mem_type);
+       expected_usage = man->usage + RES_SIZE;
+
+       KUNIT_ASSERT_TRUE(test, list_empty(&man->lru[bo->priority]));
+
+       ttm_resource_init(bo, place, res);
+
+       KUNIT_ASSERT_EQ(test, res->start, 0);
+       KUNIT_ASSERT_EQ(test, res->size, RES_SIZE);
+       KUNIT_ASSERT_EQ(test, res->mem_type, place->mem_type);
+       KUNIT_ASSERT_EQ(test, res->placement, place->flags);
+       KUNIT_ASSERT_PTR_EQ(test, res->bo, bo);
+
+       KUNIT_ASSERT_NULL(test, res->bus.addr);
+       KUNIT_ASSERT_EQ(test, res->bus.offset, 0);
+       KUNIT_ASSERT_FALSE(test, res->bus.is_iomem);
+       KUNIT_ASSERT_EQ(test, res->bus.caching, ttm_cached);
+       KUNIT_ASSERT_EQ(test, man->usage, expected_usage);
+
+       KUNIT_ASSERT_TRUE(test, list_is_singular(&man->lru[bo->priority]));
+
+       ttm_resource_fini(man, res);
+}
+
+static void ttm_resource_init_pinned(struct kunit *test)
+{
+       struct ttm_resource_test_priv *priv = test->priv;
+       struct ttm_resource *res;
+       struct ttm_buffer_object *bo;
+       struct ttm_place *place;
+       struct ttm_resource_manager *man;
+
+       ttm_init_test_mocks(test, priv, TTM_PL_SYSTEM, 0);
+       bo = priv->bo;
+       place = priv->place;
+
+       man = ttm_manager_type(priv->devs->ttm_dev, place->mem_type);
+
+       res = kunit_kzalloc(test, sizeof(*res), GFP_KERNEL);
+       KUNIT_ASSERT_NOT_NULL(test, res);
+       KUNIT_ASSERT_TRUE(test, list_empty(&bo->bdev->pinned));
+
+       dma_resv_lock(bo->base.resv, NULL);
+       ttm_bo_pin(bo);
+       ttm_resource_init(bo, place, res);
+       KUNIT_ASSERT_TRUE(test, list_is_singular(&bo->bdev->pinned));
+
+       ttm_bo_unpin(bo);
+       ttm_resource_fini(man, res);
+       dma_resv_unlock(bo->base.resv);
+
+       KUNIT_ASSERT_TRUE(test, list_empty(&bo->bdev->pinned));
+}
+
+static void ttm_resource_fini_basic(struct kunit *test)
+{
+       struct ttm_resource_test_priv *priv = test->priv;
+       struct ttm_resource *res;
+       struct ttm_buffer_object *bo;
+       struct ttm_place *place;
+       struct ttm_resource_manager *man;
+
+       ttm_init_test_mocks(test, priv, TTM_PL_SYSTEM, 0);
+       bo = priv->bo;
+       place = priv->place;
+
+       man = ttm_manager_type(priv->devs->ttm_dev, place->mem_type);
+
+       res = kunit_kzalloc(test, sizeof(*res), GFP_KERNEL);
+       KUNIT_ASSERT_NOT_NULL(test, res);
+
+       ttm_resource_init(bo, place, res);
+       ttm_resource_fini(man, res);
+
+       KUNIT_ASSERT_TRUE(test, list_empty(&res->lru));
+       KUNIT_ASSERT_EQ(test, man->usage, 0);
+}
+
+static void ttm_resource_manager_init_basic(struct kunit *test)
+{
+       struct ttm_resource_test_priv *priv = test->priv;
+       struct ttm_resource_manager *man;
+       size_t size = SZ_16K;
+
+       man = kunit_kzalloc(test, sizeof(*man), GFP_KERNEL);
+       KUNIT_ASSERT_NOT_NULL(test, man);
+
+       ttm_resource_manager_init(man, priv->devs->ttm_dev, size);
+
+       KUNIT_ASSERT_PTR_EQ(test, man->bdev, priv->devs->ttm_dev);
+       KUNIT_ASSERT_EQ(test, man->size, size);
+       KUNIT_ASSERT_EQ(test, man->usage, 0);
+       KUNIT_ASSERT_NULL(test, man->move);
+       KUNIT_ASSERT_NOT_NULL(test, &man->move_lock);
+
+       for (int i = 0; i < TTM_MAX_BO_PRIORITY; ++i)
+               KUNIT_ASSERT_TRUE(test, list_empty(&man->lru[i]));
+}
+
+static void ttm_resource_manager_usage_basic(struct kunit *test)
+{
+       struct ttm_resource_test_priv *priv = test->priv;
+       struct ttm_resource *res;
+       struct ttm_buffer_object *bo;
+       struct ttm_place *place;
+       struct ttm_resource_manager *man;
+       uint64_t actual_usage;
+
+       ttm_init_test_mocks(test, priv, TTM_PL_SYSTEM, TTM_PL_FLAG_TOPDOWN);
+       bo = priv->bo;
+       place = priv->place;
+
+       res = kunit_kzalloc(test, sizeof(*res), GFP_KERNEL);
+       KUNIT_ASSERT_NOT_NULL(test, res);
+
+       man = ttm_manager_type(priv->devs->ttm_dev, place->mem_type);
+
+       ttm_resource_init(bo, place, res);
+       actual_usage = ttm_resource_manager_usage(man);
+
+       KUNIT_ASSERT_EQ(test, actual_usage, RES_SIZE);
+
+       ttm_resource_fini(man, res);
+}
+
+static void ttm_resource_manager_set_used_basic(struct kunit *test)
+{
+       struct ttm_resource_test_priv *priv = test->priv;
+       struct ttm_resource_manager *man;
+
+       man = ttm_manager_type(priv->devs->ttm_dev, TTM_PL_SYSTEM);
+       KUNIT_ASSERT_TRUE(test, man->use_type);
+
+       ttm_resource_manager_set_used(man, false);
+       KUNIT_ASSERT_FALSE(test, man->use_type);
+}
+
+static void ttm_sys_man_alloc_basic(struct kunit *test)
+{
+       struct ttm_resource_test_priv *priv = test->priv;
+       struct ttm_resource_manager *man;
+       struct ttm_buffer_object *bo;
+       struct ttm_place *place;
+       struct ttm_resource *res;
+       uint32_t mem_type = TTM_PL_SYSTEM;
+       int ret;
+
+       ttm_init_test_mocks(test, priv, mem_type, 0);
+       bo = priv->bo;
+       place = priv->place;
+
+       man = ttm_manager_type(priv->devs->ttm_dev, mem_type);
+       ret = man->func->alloc(man, bo, place, &res);
+
+       KUNIT_ASSERT_EQ(test, ret, 0);
+       KUNIT_ASSERT_EQ(test, res->size, RES_SIZE);
+       KUNIT_ASSERT_EQ(test, res->mem_type, mem_type);
+       KUNIT_ASSERT_PTR_EQ(test, res->bo, bo);
+
+       ttm_resource_fini(man, res);
+}
+
+static void ttm_sys_man_free_basic(struct kunit *test)
+{
+       struct ttm_resource_test_priv *priv = test->priv;
+       struct ttm_resource_manager *man;
+       struct ttm_buffer_object *bo;
+       struct ttm_place *place;
+       struct ttm_resource *res;
+       uint32_t mem_type = TTM_PL_SYSTEM;
+
+       ttm_init_test_mocks(test, priv, mem_type, 0);
+       bo = priv->bo;
+       place = priv->place;
+
+       res = kunit_kzalloc(test, sizeof(*res), GFP_KERNEL);
+       KUNIT_ASSERT_NOT_NULL(test, res);
+
+       ttm_resource_alloc(bo, place, &res);
+
+       man = ttm_manager_type(priv->devs->ttm_dev, mem_type);
+       man->func->free(man, res);
+
+       KUNIT_ASSERT_TRUE(test, list_empty(&man->lru[bo->priority]));
+       KUNIT_ASSERT_EQ(test, man->usage, 0);
+}
+
+static struct kunit_case ttm_resource_test_cases[] = {
+       KUNIT_CASE_PARAM(ttm_resource_init_basic, ttm_resource_gen_params),
+       KUNIT_CASE(ttm_resource_init_pinned),
+       KUNIT_CASE(ttm_resource_fini_basic),
+       KUNIT_CASE(ttm_resource_manager_init_basic),
+       KUNIT_CASE(ttm_resource_manager_usage_basic),
+       KUNIT_CASE(ttm_resource_manager_set_used_basic),
+       KUNIT_CASE(ttm_sys_man_alloc_basic),
+       KUNIT_CASE(ttm_sys_man_free_basic),
+       {}
+};
+
+static struct kunit_suite ttm_resource_test_suite = {
+       .name = "ttm_resource",
+       .init = ttm_resource_test_init,
+       .exit = ttm_resource_test_fini,
+       .test_cases = ttm_resource_test_cases,
+};
+
+kunit_test_suites(&ttm_resource_test_suite);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/ttm/tests/ttm_tt_test.c b/drivers/gpu/drm/ttm/tests/ttm_tt_test.c
new file mode 100644 (file)
index 0000000..fd4502c
--- /dev/null
@@ -0,0 +1,295 @@
+// SPDX-License-Identifier: GPL-2.0 AND MIT
+/*
+ * Copyright Â© 2023 Intel Corporation
+ */
+#include <linux/shmem_fs.h>
+#include <drm/ttm/ttm_tt.h>
+
+#include "ttm_kunit_helpers.h"
+
+#define BO_SIZE                SZ_4K
+
+struct ttm_tt_test_case {
+       const char *description;
+       uint32_t size;
+       uint32_t extra_pages_num;
+};
+
+static int ttm_tt_test_init(struct kunit *test)
+{
+       struct ttm_test_devices *priv;
+
+       priv = kunit_kzalloc(test, sizeof(*priv), GFP_KERNEL);
+       KUNIT_ASSERT_NOT_NULL(test, priv);
+
+       priv = ttm_test_devices_all(test);
+       test->priv = priv;
+
+       return 0;
+}
+
+static const struct ttm_tt_test_case ttm_tt_init_basic_cases[] = {
+       {
+               .description = "Page-aligned size",
+               .size = SZ_4K,
+       },
+       {
+               .description = "Extra pages requested",
+               .size = SZ_4K,
+               .extra_pages_num = 1,
+       },
+};
+
+static void ttm_tt_init_case_desc(const struct ttm_tt_test_case *t,
+                                 char *desc)
+{
+       strscpy(desc, t->description, KUNIT_PARAM_DESC_SIZE);
+}
+
+KUNIT_ARRAY_PARAM(ttm_tt_init_basic, ttm_tt_init_basic_cases,
+                 ttm_tt_init_case_desc);
+
+static void ttm_tt_init_basic(struct kunit *test)
+{
+       const struct ttm_tt_test_case *params = test->param_value;
+       struct ttm_buffer_object *bo;
+       struct ttm_tt *tt;
+       uint32_t page_flags = TTM_TT_FLAG_ZERO_ALLOC;
+       enum ttm_caching caching = ttm_cached;
+       uint32_t extra_pages = params->extra_pages_num;
+       int num_pages = params->size >> PAGE_SHIFT;
+       int err;
+
+       tt = kunit_kzalloc(test, sizeof(*tt), GFP_KERNEL);
+       KUNIT_ASSERT_NOT_NULL(test, tt);
+
+       bo = ttm_bo_kunit_init(test, test->priv, params->size);
+
+       err = ttm_tt_init(tt, bo, page_flags, caching, extra_pages);
+       KUNIT_ASSERT_EQ(test, err, 0);
+
+       KUNIT_ASSERT_EQ(test, tt->num_pages, num_pages + extra_pages);
+
+       KUNIT_ASSERT_EQ(test, tt->page_flags, page_flags);
+       KUNIT_ASSERT_EQ(test, tt->caching, caching);
+
+       KUNIT_ASSERT_NULL(test, tt->dma_address);
+       KUNIT_ASSERT_NULL(test, tt->swap_storage);
+}
+
+static void ttm_tt_init_misaligned(struct kunit *test)
+{
+       struct ttm_buffer_object *bo;
+       struct ttm_tt *tt;
+       enum ttm_caching caching = ttm_cached;
+       uint32_t size = SZ_8K;
+       int num_pages = (size + SZ_4K) >> PAGE_SHIFT;
+       int err;
+
+       tt = kunit_kzalloc(test, sizeof(*tt), GFP_KERNEL);
+       KUNIT_ASSERT_NOT_NULL(test, tt);
+
+       bo = ttm_bo_kunit_init(test, test->priv, size);
+
+       /* Make the object size misaligned */
+       bo->base.size += 1;
+
+       err = ttm_tt_init(tt, bo, 0, caching, 0);
+       KUNIT_ASSERT_EQ(test, err, 0);
+
+       KUNIT_ASSERT_EQ(test, tt->num_pages, num_pages);
+}
+
+static void ttm_tt_fini_basic(struct kunit *test)
+{
+       struct ttm_buffer_object *bo;
+       struct ttm_tt *tt;
+       enum ttm_caching caching = ttm_cached;
+       int err;
+
+       tt = kunit_kzalloc(test, sizeof(*tt), GFP_KERNEL);
+       KUNIT_ASSERT_NOT_NULL(test, tt);
+
+       bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE);
+
+       err = ttm_tt_init(tt, bo, 0, caching, 0);
+       KUNIT_ASSERT_EQ(test, err, 0);
+       KUNIT_ASSERT_NOT_NULL(test, tt->pages);
+
+       ttm_tt_fini(tt);
+       KUNIT_ASSERT_NULL(test, tt->pages);
+}
+
+static void ttm_tt_fini_sg(struct kunit *test)
+{
+       struct ttm_buffer_object *bo;
+       struct ttm_tt *tt;
+       enum ttm_caching caching = ttm_cached;
+       int err;
+
+       tt = kunit_kzalloc(test, sizeof(*tt), GFP_KERNEL);
+       KUNIT_ASSERT_NOT_NULL(test, tt);
+
+       bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE);
+
+       err = ttm_sg_tt_init(tt, bo, 0, caching);
+       KUNIT_ASSERT_EQ(test, err, 0);
+       KUNIT_ASSERT_NOT_NULL(test, tt->dma_address);
+
+       ttm_tt_fini(tt);
+       KUNIT_ASSERT_NULL(test, tt->dma_address);
+}
+
+static void ttm_tt_fini_shmem(struct kunit *test)
+{
+       struct ttm_buffer_object *bo;
+       struct ttm_tt *tt;
+       struct file *shmem;
+       enum ttm_caching caching = ttm_cached;
+       int err;
+
+       tt = kunit_kzalloc(test, sizeof(*tt), GFP_KERNEL);
+       KUNIT_ASSERT_NOT_NULL(test, tt);
+
+       bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE);
+
+       err = ttm_tt_init(tt, bo, 0, caching, 0);
+       KUNIT_ASSERT_EQ(test, err, 0);
+
+       shmem = shmem_file_setup("ttm swap", BO_SIZE, 0);
+       tt->swap_storage = shmem;
+
+       ttm_tt_fini(tt);
+       KUNIT_ASSERT_NULL(test, tt->swap_storage);
+}
+
+static void ttm_tt_create_basic(struct kunit *test)
+{
+       struct ttm_buffer_object *bo;
+       int err;
+
+       bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE);
+       bo->type = ttm_bo_type_device;
+
+       dma_resv_lock(bo->base.resv, NULL);
+       err = ttm_tt_create(bo, false);
+       dma_resv_unlock(bo->base.resv);
+
+       KUNIT_EXPECT_EQ(test, err, 0);
+       KUNIT_EXPECT_NOT_NULL(test, bo->ttm);
+
+       /* Free manually, as it was allocated outside of KUnit */
+       kfree(bo->ttm);
+}
+
+static void ttm_tt_create_invalid_bo_type(struct kunit *test)
+{
+       struct ttm_buffer_object *bo;
+       int err;
+
+       bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE);
+       bo->type = ttm_bo_type_sg + 1;
+
+       dma_resv_lock(bo->base.resv, NULL);
+       err = ttm_tt_create(bo, false);
+       dma_resv_unlock(bo->base.resv);
+
+       KUNIT_EXPECT_EQ(test, err, -EINVAL);
+       KUNIT_EXPECT_NULL(test, bo->ttm);
+}
+
+static void ttm_tt_create_ttm_exists(struct kunit *test)
+{
+       struct ttm_buffer_object *bo;
+       struct ttm_tt *tt;
+       enum ttm_caching caching = ttm_cached;
+       int err;
+
+       tt = kunit_kzalloc(test, sizeof(*tt), GFP_KERNEL);
+       KUNIT_ASSERT_NOT_NULL(test, tt);
+
+       bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE);
+
+       err = ttm_tt_init(tt, bo, 0, caching, 0);
+       KUNIT_ASSERT_EQ(test, err, 0);
+       bo->ttm = tt;
+
+       dma_resv_lock(bo->base.resv, NULL);
+       err = ttm_tt_create(bo, false);
+       dma_resv_unlock(bo->base.resv);
+
+       /* Expect to keep the previous TTM */
+       KUNIT_ASSERT_EQ(test, err, 0);
+       KUNIT_ASSERT_PTR_EQ(test, tt, bo->ttm);
+}
+
+static struct ttm_tt *ttm_tt_null_create(struct ttm_buffer_object *bo,
+                                        uint32_t page_flags)
+{
+       return NULL;
+}
+
+static struct ttm_device_funcs ttm_dev_empty_funcs = {
+       .ttm_tt_create = ttm_tt_null_create,
+};
+
+static void ttm_tt_create_failed(struct kunit *test)
+{
+       const struct ttm_test_devices *devs = test->priv;
+       struct ttm_buffer_object *bo;
+       int err;
+
+       bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE);
+
+       /* Update ttm_device_funcs so we don't alloc ttm_tt */
+       devs->ttm_dev->funcs = &ttm_dev_empty_funcs;
+
+       dma_resv_lock(bo->base.resv, NULL);
+       err = ttm_tt_create(bo, false);
+       dma_resv_unlock(bo->base.resv);
+
+       KUNIT_ASSERT_EQ(test, err, -ENOMEM);
+}
+
+static void ttm_tt_destroy_basic(struct kunit *test)
+{
+       const struct ttm_test_devices *devs = test->priv;
+       struct ttm_buffer_object *bo;
+       int err;
+
+       bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE);
+
+       dma_resv_lock(bo->base.resv, NULL);
+       err = ttm_tt_create(bo, false);
+       dma_resv_unlock(bo->base.resv);
+
+       KUNIT_ASSERT_EQ(test, err, 0);
+       KUNIT_ASSERT_NOT_NULL(test, bo->ttm);
+
+       ttm_tt_destroy(devs->ttm_dev, bo->ttm);
+}
+
+static struct kunit_case ttm_tt_test_cases[] = {
+       KUNIT_CASE_PARAM(ttm_tt_init_basic, ttm_tt_init_basic_gen_params),
+       KUNIT_CASE(ttm_tt_init_misaligned),
+       KUNIT_CASE(ttm_tt_fini_basic),
+       KUNIT_CASE(ttm_tt_fini_sg),
+       KUNIT_CASE(ttm_tt_fini_shmem),
+       KUNIT_CASE(ttm_tt_create_basic),
+       KUNIT_CASE(ttm_tt_create_invalid_bo_type),
+       KUNIT_CASE(ttm_tt_create_ttm_exists),
+       KUNIT_CASE(ttm_tt_create_failed),
+       KUNIT_CASE(ttm_tt_destroy_basic),
+       {}
+};
+
+static struct kunit_suite ttm_tt_test_suite = {
+       .name = "ttm_tt",
+       .init = ttm_tt_test_init,
+       .exit = ttm_test_devices_fini,
+       .test_cases = ttm_tt_test_cases,
+};
+
+kunit_test_suites(&ttm_tt_test_suite);
+
+MODULE_LICENSE("GPL");
index edf10618fe2b22f70d88d18548bb0475643afee2..ba3f09e2d7e678f7caa0577fb7ba3e979136c5c1 100644 (file)
@@ -410,8 +410,8 @@ static int ttm_bo_bounce_temp_buffer(struct ttm_buffer_object *bo,
        struct ttm_resource *hop_mem;
        int ret;
 
-       hop_placement.num_placement = hop_placement.num_busy_placement = 1;
-       hop_placement.placement = hop_placement.busy_placement = hop;
+       hop_placement.num_placement = 1;
+       hop_placement.placement = hop;
 
        /* find space in the bounce domain */
        ret = ttm_bo_mem_space(bo, &hop_placement, &hop_mem, ctx);
@@ -440,10 +440,9 @@ static int ttm_bo_evict(struct ttm_buffer_object *bo,
        dma_resv_assert_held(bo->base.resv);
 
        placement.num_placement = 0;
-       placement.num_busy_placement = 0;
        bdev->funcs->evict_flags(bo, &placement);
 
-       if (!placement.num_placement && !placement.num_busy_placement) {
+       if (!placement.num_placement) {
                ret = ttm_bo_wait_ctx(bo, ctx);
                if (ret)
                        return ret;
@@ -770,7 +769,7 @@ static int ttm_bo_mem_force_space(struct ttm_buffer_object *bo,
  * This function may sleep while waiting for space to become available.
  * Returns:
  * -EBUSY: No space available (only if no_wait == 1).
- * -ENOMEM: Could not allocate memory for the buffer object, either due to
+ * -ENOSPC: Could not allocate space for the buffer object, either due to
  * fragmentation or concurrent allocators.
  * -ERESTARTSYS: An interruptible sleep was interrupted by a signal.
  */
@@ -791,6 +790,9 @@ int ttm_bo_mem_space(struct ttm_buffer_object *bo,
                const struct ttm_place *place = &placement->placement[i];
                struct ttm_resource_manager *man;
 
+               if (place->flags & TTM_PL_FLAG_FALLBACK)
+                       continue;
+
                man = ttm_manager_type(bdev, place->mem_type);
                if (!man || !ttm_resource_manager_used(man))
                        continue;
@@ -813,10 +815,13 @@ int ttm_bo_mem_space(struct ttm_buffer_object *bo,
                return 0;
        }
 
-       for (i = 0; i < placement->num_busy_placement; ++i) {
-               const struct ttm_place *place = &placement->busy_placement[i];
+       for (i = 0; i < placement->num_placement; ++i) {
+               const struct ttm_place *place = &placement->placement[i];
                struct ttm_resource_manager *man;
 
+               if (place->flags & TTM_PL_FLAG_DESIRED)
+                       continue;
+
                man = ttm_manager_type(bdev, place->mem_type);
                if (!man || !ttm_resource_manager_used(man))
                        continue;
@@ -830,7 +835,7 @@ int ttm_bo_mem_space(struct ttm_buffer_object *bo,
                        goto error;
        }
 
-       ret = -ENOMEM;
+       ret = -ENOSPC;
        if (!type_found) {
                pr_err(TTM_PFX "No compatible memory type found\n");
                ret = -EINVAL;
@@ -904,11 +909,11 @@ int ttm_bo_validate(struct ttm_buffer_object *bo,
        /*
         * Remove the backing store if no placement is given.
         */
-       if (!placement->num_placement && !placement->num_busy_placement)
+       if (!placement->num_placement)
                return ttm_bo_pipeline_gutting(bo);
 
        /* Check whether we need to move buffer. */
-       if (bo->resource && ttm_resource_compat(bo->resource, placement))
+       if (bo->resource && ttm_resource_compatible(bo->resource, placement))
                return 0;
 
        /* Moving of pinned BOs is forbidden */
@@ -916,6 +921,9 @@ int ttm_bo_validate(struct ttm_buffer_object *bo,
                return -EINVAL;
 
        ret = ttm_bo_move_buffer(bo, placement, ctx);
+       /* For backward compatibility with userspace */
+       if (ret == -ENOSPC)
+               return -ENOMEM;
        if (ret)
                return ret;
 
index fd9fd3d15101c873758c6365eb4924214e23fe7b..0b3f4267130c4569fa04ae8eba4a5b5eefe6a176 100644 (file)
@@ -294,7 +294,13 @@ pgprot_t ttm_io_prot(struct ttm_buffer_object *bo, struct ttm_resource *res,
        enum ttm_caching caching;
 
        man = ttm_manager_type(bo->bdev, res->mem_type);
-       caching = man->use_tt ? bo->ttm->caching : res->bus.caching;
+       if (man->use_tt) {
+               caching = bo->ttm->caching;
+               if (bo->ttm->page_flags & TTM_TT_FLAG_DECRYPTED)
+                       tmp = pgprot_decrypted(tmp);
+       } else  {
+               caching = res->bus.caching;
+       }
 
        return ttm_prot_from_caching(caching, tmp);
 }
@@ -337,6 +343,8 @@ static int ttm_bo_kmap_ttm(struct ttm_buffer_object *bo,
                .no_wait_gpu = false
        };
        struct ttm_tt *ttm = bo->ttm;
+       struct ttm_resource_manager *man =
+                       ttm_manager_type(bo->bdev, bo->resource->mem_type);
        pgprot_t prot;
        int ret;
 
@@ -346,7 +354,8 @@ static int ttm_bo_kmap_ttm(struct ttm_buffer_object *bo,
        if (ret)
                return ret;
 
-       if (num_pages == 1 && ttm->caching == ttm_cached) {
+       if (num_pages == 1 && ttm->caching == ttm_cached &&
+           !(man->use_tt && (ttm->page_flags & TTM_TT_FLAG_DECRYPTED))) {
                /*
                 * We're mapping a single page, and the desired
                 * page protection is consistent with the bo.
index 46ff9c75bb124ae73cc45439ddd33cf9e02e305f..fb14f7716cf8241a8e32414fb51063c71d95d846 100644 (file)
@@ -30,6 +30,8 @@
 #include <drm/ttm/ttm_placement.h>
 #include <drm/ttm/ttm_resource.h>
 
+#include <drm/drm_util.h>
+
 /**
  * ttm_lru_bulk_move_init - initialize a bulk move structure
  * @bulk: the structure to init
@@ -240,6 +242,7 @@ int ttm_resource_alloc(struct ttm_buffer_object *bo,
        spin_unlock(&bo->bdev->lru_lock);
        return 0;
 }
+EXPORT_SYMBOL_FOR_TESTS_ONLY(ttm_resource_alloc);
 
 void ttm_resource_free(struct ttm_buffer_object *bo, struct ttm_resource **res)
 {
@@ -288,37 +291,15 @@ bool ttm_resource_intersects(struct ttm_device *bdev,
 }
 
 /**
- * ttm_resource_compatible - test for compatibility
- *
- * @bdev: TTM device structure
- * @res: The resource to test
- * @place: The placement to test
- * @size: How many bytes the new allocation needs.
+ * ttm_resource_compatible - check if resource is compatible with placement
  *
- * Test if @res compatible with @place and @size.
+ * @res: the resource to check
+ * @placement: the placement to check against
  *
- * Returns true if the res placement compatible with @place and @size.
+ * Returns true if the placement is compatible.
  */
-bool ttm_resource_compatible(struct ttm_device *bdev,
-                            struct ttm_resource *res,
-                            const struct ttm_place *place,
-                            size_t size)
-{
-       struct ttm_resource_manager *man;
-
-       if (!res || !place)
-               return false;
-
-       man = ttm_manager_type(bdev, res->mem_type);
-       if (!man->func->compatible)
-               return true;
-
-       return man->func->compatible(man, res, place, size);
-}
-
-static bool ttm_resource_places_compat(struct ttm_resource *res,
-                                      const struct ttm_place *places,
-                                      unsigned num_placement)
+bool ttm_resource_compatible(struct ttm_resource *res,
+                            struct ttm_placement *placement)
 {
        struct ttm_buffer_object *bo = res->bo;
        struct ttm_device *bdev = bo->bdev;
@@ -327,44 +308,25 @@ static bool ttm_resource_places_compat(struct ttm_resource *res,
        if (res->placement & TTM_PL_FLAG_TEMPORARY)
                return false;
 
-       for (i = 0; i < num_placement; i++) {
-               const struct ttm_place *heap = &places[i];
+       for (i = 0; i < placement->num_placement; i++) {
+               const struct ttm_place *place = &placement->placement[i];
+               struct ttm_resource_manager *man;
 
-               if (!ttm_resource_compatible(bdev, res, heap, bo->base.size))
+               if (res->mem_type != place->mem_type)
+                       continue;
+
+               man = ttm_manager_type(bdev, res->mem_type);
+               if (man->func->compatible &&
+                   !man->func->compatible(man, res, place, bo->base.size))
                        continue;
 
-               if ((res->mem_type == heap->mem_type) &&
-                   (!(heap->flags & TTM_PL_FLAG_CONTIGUOUS) ||
+               if ((!(place->flags & TTM_PL_FLAG_CONTIGUOUS) ||
                     (res->placement & TTM_PL_FLAG_CONTIGUOUS)))
                        return true;
        }
        return false;
 }
 
-/**
- * ttm_resource_compat - check if resource is compatible with placement
- *
- * @res: the resource to check
- * @placement: the placement to check against
- *
- * Returns true if the placement is compatible.
- */
-bool ttm_resource_compat(struct ttm_resource *res,
-                        struct ttm_placement *placement)
-{
-       if (ttm_resource_places_compat(res, placement->placement,
-                                      placement->num_placement))
-               return true;
-
-       if ((placement->busy_placement != placement->placement ||
-            placement->num_busy_placement > placement->num_placement) &&
-           ttm_resource_places_compat(res, placement->busy_placement,
-                                      placement->num_busy_placement))
-               return true;
-
-       return false;
-}
-
 void ttm_resource_set_bo(struct ttm_resource *res,
                         struct ttm_buffer_object *bo)
 {
index e0a77671edd6c155329119e498e271a520a4eaab..578a7c37f00bd7a3c8a5f1d5e93d4cd80fdc6cc9 100644 (file)
 
 #define pr_fmt(fmt) "[TTM] " fmt
 
+#include <linux/cc_platform.h>
 #include <linux/sched.h>
 #include <linux/shmem_fs.h>
 #include <linux/file.h>
 #include <linux/module.h>
 #include <drm/drm_cache.h>
+#include <drm/drm_device.h>
+#include <drm/drm_util.h>
 #include <drm/ttm/ttm_bo.h>
 #include <drm/ttm/ttm_tt.h>
 
@@ -60,6 +63,7 @@ static atomic_long_t ttm_dma32_pages_allocated;
 int ttm_tt_create(struct ttm_buffer_object *bo, bool zero_alloc)
 {
        struct ttm_device *bdev = bo->bdev;
+       struct drm_device *ddev = bo->base.dev;
        uint32_t page_flags = 0;
 
        dma_resv_assert_held(bo->base.resv);
@@ -81,6 +85,15 @@ int ttm_tt_create(struct ttm_buffer_object *bo, bool zero_alloc)
                pr_err("Illegal buffer object type\n");
                return -EINVAL;
        }
+       /*
+        * When using dma_alloc_coherent with memory encryption the
+        * mapped TT pages need to be decrypted or otherwise the drivers
+        * will end up sending encrypted mem to the gpu.
+        */
+       if (bdev->pool.use_dma_alloc && cc_platform_has(CC_ATTR_GUEST_MEM_ENCRYPT)) {
+               page_flags |= TTM_TT_FLAG_DECRYPTED;
+               drm_info(ddev, "TT memory decryption enabled.");
+       }
 
        bo->ttm = bdev->funcs->ttm_tt_create(bo, page_flags);
        if (unlikely(bo->ttm == NULL))
@@ -91,6 +104,7 @@ int ttm_tt_create(struct ttm_buffer_object *bo, bool zero_alloc)
 
        return 0;
 }
+EXPORT_SYMBOL_FOR_TESTS_ONLY(ttm_tt_create);
 
 /*
  * Allocates storage for pointers to the pages that back the ttm.
@@ -129,6 +143,7 @@ void ttm_tt_destroy(struct ttm_device *bdev, struct ttm_tt *ttm)
 {
        bdev->funcs->ttm_tt_destroy(bdev, ttm);
 }
+EXPORT_SYMBOL_FOR_TESTS_ONLY(ttm_tt_destroy);
 
 static void ttm_tt_init_fields(struct ttm_tt *ttm,
                               struct ttm_buffer_object *bo,
index 11e865be81c6d0416c3622060c52bcff06ca50e0..5121fed571a5359883aea030c9b754e00da94d49 100644 (file)
@@ -9,7 +9,6 @@ config DRM_TVE200
        select DRM_PANEL_BRIDGE
        select DRM_KMS_HELPER
        select DRM_GEM_DMA_HELPER
-       select VT_HW_CONSOLE_BINDING if FRAMEBUFFER_CONSOLE
        help
          Choose this option for DRM support for the Faraday TV Encoder
          TVE200 Controller.
index 94eafcecc65b0c878e20e7a3f4a528f8a56e60c1..dc3cf708d02e05069eb38947ebe4f1cfe0f2d5d5 100644 (file)
@@ -260,11 +260,26 @@ static int v3d_measure_clock(struct seq_file *m, void *unused)
        return 0;
 }
 
+static int v3d_debugfs_mm(struct seq_file *m, void *unused)
+{
+       struct drm_printer p = drm_seq_file_printer(m);
+       struct drm_debugfs_entry *entry = m->private;
+       struct drm_device *dev = entry->dev;
+       struct v3d_dev *v3d = to_v3d_dev(dev);
+
+       spin_lock(&v3d->mm_lock);
+       drm_mm_print(&v3d->mm, &p);
+       spin_unlock(&v3d->mm_lock);
+
+       return 0;
+}
+
 static const struct drm_debugfs_info v3d_debugfs_list[] = {
        {"v3d_ident", v3d_v3d_debugfs_ident, 0},
        {"v3d_regs", v3d_v3d_debugfs_regs, 0},
        {"measure_clock", v3d_measure_clock, 0},
        {"bo_stats", v3d_debugfs_bo_stats, 0},
+       {"v3d_mm", v3d_debugfs_mm, 0},
 };
 
 void
index f05e2c95a60d7175d0fb4f1b13a195e6237c310e..34f807ed1c315e3cb0cd53a59d34eb36c3bceec4 100644 (file)
@@ -35,6 +35,7 @@
 #include <drm/display/drm_scdc_helper.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_drv.h>
+#include <drm/drm_edid.h>
 #include <drm/drm_probe_helper.h>
 #include <drm/drm_simple_kms_helper.h>
 #include <linux/clk.h>
index 00e713faecd5acf1e6e79f618da534c82aba72ba..07caf2a47c6cef2ff8a4ccbea0f5d6ee87218a66 100644 (file)
@@ -1497,16 +1497,16 @@ static int vc4_prepare_fb(struct drm_plane *plane,
                          struct drm_plane_state *state)
 {
        struct vc4_bo *bo;
+       int ret;
 
        if (!state->fb)
                return 0;
 
        bo = to_vc4_bo(&drm_fb_dma_get_gem_obj(state->fb, 0)->base);
 
-       drm_gem_plane_helper_prepare_fb(plane, state);
-
-       if (plane->state->fb == state->fb)
-               return 0;
+       ret = drm_gem_plane_helper_prepare_fb(plane, state);
+       if (ret)
+               return ret;
 
        return vc4_bo_inc_usecnt(bo);
 }
@@ -1516,7 +1516,7 @@ static void vc4_cleanup_fb(struct drm_plane *plane,
 {
        struct vc4_bo *bo;
 
-       if (plane->state->fb == state->fb || !state->fb)
+       if (!state->fb)
                return;
 
        bo = to_vc4_bo(&drm_fb_dma_get_gem_obj(state->fb, 0)->base);
index 5c514946bbad974cdb05ee8ee6f456066b741255..1c7c7f61a222895dc5bcef38d5f82132e818c9a1 100644 (file)
@@ -99,8 +99,8 @@ virtio_gpu_parse_deps(struct virtio_gpu_submit *submit)
                return 0;
 
        /*
-        * kvalloc at first tries to allocate memory using kmalloc and
-        * falls back to vmalloc only on failure. It also uses __GFP_NOWARN
+        * kvmalloc() at first tries to allocate memory using kmalloc() and
+        * falls back to vmalloc() only on failure. It also uses __GFP_NOWARN
         * internally for allocations larger than a page size, preventing
         * storm of KMSG warnings.
         */
@@ -529,7 +529,7 @@ int virtio_gpu_execbuffer_ioctl(struct drm_device *dev, void *data,
        virtio_gpu_submit(&submit);
 
        /*
-        * Set up usr-out data after submitting the job to optimize
+        * Set up user-out data after submitting the job to optimize
         * the job submission path.
         */
        virtio_gpu_install_out_fence_fd(&submit);
diff --git a/drivers/gpu/drm/vkms/Kconfig b/drivers/gpu/drm/vkms/Kconfig
new file mode 100644 (file)
index 0000000..b9ecdeb
--- /dev/null
@@ -0,0 +1,15 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+config DRM_VKMS
+       tristate "Virtual KMS (EXPERIMENTAL)"
+       depends on DRM && MMU
+       select DRM_KMS_HELPER
+       select DRM_GEM_SHMEM_HELPER
+       select CRC32
+       default n
+       help
+         Virtual Kernel Mode-Setting (VKMS) is used for testing or for
+         running GPU in a headless machines. Choose this option to get
+         a VKMS.
+
+         If M is selected the module will be called vkms.
index 3c99fb8b54e2df54ab26f8b6b15b4fd30d41183f..e7441b227b3cea351291749002ae1296e77b62e5 100644 (file)
@@ -123,6 +123,8 @@ static u16 apply_lut_to_channel_value(const struct vkms_color_lut *lut, u16 chan
                                      enum lut_channel channel)
 {
        s64 lut_index = get_lut_index(lut, channel_value);
+       u16 *floor_lut_value, *ceil_lut_value;
+       u16 floor_channel_value, ceil_channel_value;
 
        /*
         * This checks if `struct drm_color_lut` has any gap added by the compiler
@@ -130,11 +132,15 @@ static u16 apply_lut_to_channel_value(const struct vkms_color_lut *lut, u16 chan
         */
        static_assert(sizeof(struct drm_color_lut) == sizeof(__u16) * 4);
 
-       u16 *floor_lut_value = (__u16 *)&lut->base[drm_fixp2int(lut_index)];
-       u16 *ceil_lut_value = (__u16 *)&lut->base[drm_fixp2int_ceil(lut_index)];
+       floor_lut_value = (__u16 *)&lut->base[drm_fixp2int(lut_index)];
+       if (drm_fixp2int(lut_index) == (lut->lut_length - 1))
+               /* We're at the end of the LUT array, use same value for ceil and floor */
+               ceil_lut_value = floor_lut_value;
+       else
+               ceil_lut_value = (__u16 *)&lut->base[drm_fixp2int_ceil(lut_index)];
 
-       u16 floor_channel_value = floor_lut_value[channel];
-       u16 ceil_channel_value = ceil_lut_value[channel];
+       floor_channel_value = floor_lut_value[channel];
+       ceil_channel_value = ceil_lut_value[channel];
 
        return lerp_u16(floor_channel_value, ceil_channel_value,
                        lut_index & DRM_FIXED_DECIMAL_MASK);
index 2bfac3aad7b7d6327b552b550f656973fd8758eb..bfd41ce3c8f4fca1f5a659e4513e08f72ea95966 100644 (file)
@@ -742,9 +742,21 @@ void vmw_bo_move_notify(struct ttm_buffer_object *bo,
                vmw_resource_unbind_list(vbo);
 }
 
+static u32 placement_flags(u32 domain, u32 desired, u32 fallback)
+{
+       if (desired & fallback & domain)
+               return 0;
+
+       if (desired & domain)
+               return TTM_PL_FLAG_DESIRED;
+
+       return TTM_PL_FLAG_FALLBACK;
+}
+
 static u32
-set_placement_list(struct ttm_place *pl, u32 domain)
+set_placement_list(struct ttm_place *pl, u32 desired, u32 fallback)
 {
+       u32 domain = desired | fallback;
        u32 n = 0;
 
        /*
@@ -752,35 +764,40 @@ set_placement_list(struct ttm_place *pl, u32 domain)
         */
        if (domain & VMW_BO_DOMAIN_MOB) {
                pl[n].mem_type = VMW_PL_MOB;
-               pl[n].flags = 0;
+               pl[n].flags = placement_flags(VMW_BO_DOMAIN_MOB, desired,
+                                             fallback);
                pl[n].fpfn = 0;
                pl[n].lpfn = 0;
                n++;
        }
        if (domain & VMW_BO_DOMAIN_GMR) {
                pl[n].mem_type = VMW_PL_GMR;
-               pl[n].flags = 0;
+               pl[n].flags = placement_flags(VMW_BO_DOMAIN_GMR, desired,
+                                             fallback);
                pl[n].fpfn = 0;
                pl[n].lpfn = 0;
                n++;
        }
        if (domain & VMW_BO_DOMAIN_VRAM) {
                pl[n].mem_type = TTM_PL_VRAM;
-               pl[n].flags = 0;
+               pl[n].flags = placement_flags(VMW_BO_DOMAIN_VRAM, desired,
+                                             fallback);
                pl[n].fpfn = 0;
                pl[n].lpfn = 0;
                n++;
        }
        if (domain & VMW_BO_DOMAIN_WAITABLE_SYS) {
                pl[n].mem_type = VMW_PL_SYSTEM;
-               pl[n].flags = 0;
+               pl[n].flags = placement_flags(VMW_BO_DOMAIN_WAITABLE_SYS,
+                                             desired, fallback);
                pl[n].fpfn = 0;
                pl[n].lpfn = 0;
                n++;
        }
        if (domain & VMW_BO_DOMAIN_SYS) {
                pl[n].mem_type = TTM_PL_SYSTEM;
-               pl[n].flags = 0;
+               pl[n].flags = placement_flags(VMW_BO_DOMAIN_SYS, desired,
+                                             fallback);
                pl[n].fpfn = 0;
                pl[n].lpfn = 0;
                n++;
@@ -806,7 +823,7 @@ void vmw_bo_placement_set(struct vmw_bo *bo, u32 domain, u32 busy_domain)
        u32 i;
 
        pl->placement = bo->places;
-       pl->num_placement = set_placement_list(bo->places, domain);
+       pl->num_placement = set_placement_list(bo->places, domain, busy_domain);
 
        if (drm_debug_enabled(DRM_UT_DRIVER) && bo->tbo.resource) {
                for (i = 0; i < pl->num_placement; ++i) {
@@ -821,8 +838,6 @@ void vmw_bo_placement_set(struct vmw_bo *bo, u32 domain, u32 busy_domain)
                                 __func__, bo->tbo.resource->mem_type, domain);
        }
 
-       pl->busy_placement = bo->busy_places;
-       pl->num_busy_placement = set_placement_list(bo->busy_places, busy_domain);
 }
 
 void vmw_bo_placement_set_default_accelerated(struct vmw_bo *bo)
index 3cd5090dedfc5b0571b4f4f1a1a1ac6a0d5b0638..12efecc17df664968056906da40cdd46b5665ddf 100644 (file)
@@ -942,7 +942,6 @@ vmw_is_cursor_bypass3_enabled(const struct vmw_private *dev_priv)
 
 extern const size_t vmw_tt_size;
 extern struct ttm_placement vmw_vram_placement;
-extern struct ttm_placement vmw_vram_gmr_placement;
 extern struct ttm_placement vmw_sys_placement;
 extern struct ttm_device_funcs vmw_bo_driver;
 extern const struct vmw_sg_table *
index 36987ef3fc300623eae6caff131f4d89ac4d1450..cc3086e649eb5cb7c9a8ba3a54aa5745d05700ce 100644 (file)
@@ -447,7 +447,7 @@ static int vmw_resource_context_res_add(struct vmw_private *dev_priv,
            vmw_res_type(ctx) == vmw_res_dx_context) {
                for (i = 0; i < cotable_max; ++i) {
                        res = vmw_context_cotable(ctx, i);
-                       if (IS_ERR(res))
+                       if (IS_ERR_OR_NULL(res))
                                continue;
 
                        ret = vmw_execbuf_res_val_add(sw_context, res,
@@ -621,10 +621,10 @@ static int vmw_resources_reserve(struct vmw_sw_context *sw_context)
  * @sw_context: Pointer to the software context.
  * @res_type: Resource type.
  * @dirty: Whether to change dirty status.
- * @converter: User-space visisble type specific information.
+ * @converter: User-space visible type specific information.
  * @id_loc: Pointer to the location in the command buffer currently being parsed
  * from where the user-space resource id handle is located.
- * @p_res: Pointer to pointer to resource validalidation node. Populated on
+ * @p_res: Pointer to pointer to resource validation node. Populated on
  * exit.
  */
 static int
@@ -1266,6 +1266,8 @@ static int vmw_cmd_dx_define_query(struct vmw_private *dev_priv,
                return -EINVAL;
 
        cotable_res = vmw_context_cotable(ctx_node->ctx, SVGA_COTABLE_DXQUERY);
+       if (IS_ERR_OR_NULL(cotable_res))
+               return cotable_res ? PTR_ERR(cotable_res) : -EINVAL;
        ret = vmw_cotable_notify(cotable_res, cmd->body.queryId);
 
        return ret;
@@ -2484,6 +2486,8 @@ static int vmw_cmd_dx_view_define(struct vmw_private *dev_priv,
                return ret;
 
        res = vmw_context_cotable(ctx_node->ctx, vmw_view_cotables[view_type]);
+       if (IS_ERR_OR_NULL(res))
+               return res ? PTR_ERR(res) : -EINVAL;
        ret = vmw_cotable_notify(res, cmd->defined_id);
        if (unlikely(ret != 0))
                return ret;
@@ -2569,8 +2573,8 @@ static int vmw_cmd_dx_so_define(struct vmw_private *dev_priv,
 
        so_type = vmw_so_cmd_to_type(header->id);
        res = vmw_context_cotable(ctx_node->ctx, vmw_so_cotables[so_type]);
-       if (IS_ERR(res))
-               return PTR_ERR(res);
+       if (IS_ERR_OR_NULL(res))
+               return res ? PTR_ERR(res) : -EINVAL;
        cmd = container_of(header, typeof(*cmd), header);
        ret = vmw_cotable_notify(res, cmd->defined_id);
 
@@ -2689,6 +2693,8 @@ static int vmw_cmd_dx_define_shader(struct vmw_private *dev_priv,
                return -EINVAL;
 
        res = vmw_context_cotable(ctx_node->ctx, SVGA_COTABLE_DXSHADER);
+       if (IS_ERR_OR_NULL(res))
+               return res ? PTR_ERR(res) : -EINVAL;
        ret = vmw_cotable_notify(res, cmd->body.shaderId);
        if (ret)
                return ret;
@@ -3010,6 +3016,8 @@ static int vmw_cmd_dx_define_streamoutput(struct vmw_private *dev_priv,
        }
 
        res = vmw_context_cotable(ctx_node->ctx, SVGA_COTABLE_STREAMOUTPUT);
+       if (IS_ERR_OR_NULL(res))
+               return res ? PTR_ERR(res) : -EINVAL;
        ret = vmw_cotable_notify(res, cmd->body.soid);
        if (ret)
                return ret;
@@ -3603,6 +3611,8 @@ static const struct vmw_cmd_entry vmw_cmd_entries[SVGA_3D_CMD_MAX] = {
                    &vmw_cmd_dx_bind_streamoutput, true, false, true),
        VMW_CMD_DEF(SVGA_3D_CMD_DX_DEFINE_RASTERIZER_STATE_V2,
                    &vmw_cmd_dx_so_define, true, false, true),
+       VMW_CMD_DEF(SVGA_3D_CMD_DEFINE_GB_SURFACE_V4,
+                   &vmw_cmd_invalid, false, false, true),
 };
 
 bool vmw_cmd_describe(const void *buf, u32 *size, char const **cmd)
index ceb4d3d3b965aacb7c0794b9dc7d9a6ad09b4098..a0b47c9b33f552a6d8022596c4acd6ec3420909d 100644 (file)
@@ -64,8 +64,11 @@ static int vmw_gmrid_man_get_node(struct ttm_resource_manager *man,
        ttm_resource_init(bo, place, *res);
 
        id = ida_alloc_max(&gman->gmr_ida, gman->max_gmr_ids - 1, GFP_KERNEL);
-       if (id < 0)
+       if (id < 0) {
+               ttm_resource_fini(man, *res);
+               kfree(*res);
                return id;
+       }
 
        spin_lock(&gman->lock);
 
index 5fd0ccaa0b41b71adb6cdeacab7eae3062fcadf7..8589a1c3cc36b91e67cd7ecb958c33901e073c59 100644 (file)
@@ -694,6 +694,10 @@ vmw_du_cursor_plane_prepare_fb(struct drm_plane *plane,
        int ret = 0;
 
        if (vps->surf) {
+               if (vps->surf_mapped) {
+                       vmw_bo_unmap(vps->surf->res.guest_memory_bo);
+                       vps->surf_mapped = false;
+               }
                vmw_surface_unreference(&vps->surf);
                vps->surf = NULL;
        }
index ba0c0e12cfe9d02b838e071929a6ec1a62af3e62..6bc23bdf32c2479eb25c8217e05a3fee8eb2b16c 100644 (file)
@@ -53,7 +53,6 @@ enum stdu_content_type {
  * struct vmw_stdu_dirty - closure structure for the update functions
  *
  * @base: The base type we derive from. Used by vmw_kms_helper_dirty().
- * @transfer: Transfer direction for DMA command.
  * @left: Left side of bounding box.
  * @right: Right side of bounding box.
  * @top: Top side of bounding box.
@@ -100,7 +99,7 @@ struct vmw_stdu_update_gb_image {
 };
 
 /**
- * struct vmw_screen_target_display_unit
+ * struct vmw_screen_target_display_unit - conglomerated STDU structure
  *
  * @base: VMW specific DU structure
  * @display_srf: surface to be displayed.  The dimension of this will always
@@ -208,6 +207,8 @@ static int vmw_stdu_define_st(struct vmw_private *dev_priv,
  * @res: Buffer to bind to the screen target.  Set to NULL to blank screen.
  *
  * Binding a surface to a Screen Target the same as flipping
+ *
+ * Returns: %0 on success or -errno code on failure
  */
 static int vmw_stdu_bind_st(struct vmw_private *dev_priv,
                            struct vmw_screen_target_display_unit *stdu,
@@ -314,6 +315,9 @@ static int vmw_stdu_update_st(struct vmw_private *dev_priv,
  *
  * @dev_priv:  VMW DRM device
  * @stdu: display unit to destroy
+ *
+ * Returns: %0 on success, negative error code on failure. -ERESTARTSYS if
+ * interrupted.
  */
 static int vmw_stdu_destroy_st(struct vmw_private *dev_priv,
                               struct vmw_screen_target_display_unit *stdu)
@@ -536,7 +540,8 @@ static void vmw_stdu_bo_cpu_commit(struct vmw_kms_dirty *dirty)
  * If DMA-ing till the screen target system, the function will also notify
  * the screen target system that a bounding box of the cliprects has been
  * updated.
- * Returns 0 on success, negative error code on failure. -ERESTARTSYS if
+ *
+ * Returns: %0 on success, negative error code on failure. -ERESTARTSYS if
  * interrupted.
  */
 int vmw_kms_stdu_readback(struct vmw_private *dev_priv,
@@ -703,7 +708,7 @@ static void vmw_kms_stdu_surface_fifo_commit(struct vmw_kms_dirty *dirty)
  * case the device has already synchronized.
  * @crtc: If crtc is passed, perform surface dirty on that crtc only.
  *
- * Returns 0 on success, negative error code on failure. -ERESTARTSYS if
+ * Returns: %0 on success, negative error code on failure. -ERESTARTSYS if
  * interrupted.
  */
 int vmw_kms_stdu_surface_dirty(struct vmw_private *dev_priv,
@@ -887,7 +892,7 @@ vmw_stdu_primary_plane_cleanup_fb(struct drm_plane *plane,
  * backed by a buffer object.  The display surface is pinned here, and it'll
  * be unpinned in .cleanup_fb()
  *
- * Returns 0 on success
+ * Returns: %0 on success
  */
 static int
 vmw_stdu_primary_plane_prepare_fb(struct drm_plane *plane,
@@ -1465,6 +1470,8 @@ static const struct drm_crtc_helper_funcs vmw_stdu_crtc_helper_funcs = {
  * This function is called once per CRTC, and allocates one Screen Target
  * display unit to represent that CRTC.  Since the SVGA device does not separate
  * out encoder and connector, they are represented as part of the STDU as well.
+ *
+ * Returns: %0 on success or -errno code on failure
  */
 static int vmw_stdu_init(struct vmw_private *dev_priv, unsigned unit)
 {
index 680441bb1786db124882cf5142cb82b41894ae19..10498725034cb102a530cbee0fec9ebeabea7052 100644 (file)
@@ -44,7 +44,6 @@
  * struct vmw_user_surface - User-space visible surface resource
  *
  * @prime:          The TTM prime object.
- * @base:           The TTM base object handling user-space visibility.
  * @srf:            The surface metadata.
  * @master:         Master of the creating client. Used for security check.
  */
index af8562c95cc35b85048f2b9c64bcde55ed374f73..4d23d0a70bcb7ef4901e9128b84cd7112ae8913a 100644 (file)
@@ -43,46 +43,14 @@ static const struct ttm_place sys_placement_flags = {
        .flags = 0
 };
 
-static const struct ttm_place gmr_placement_flags = {
-       .fpfn = 0,
-       .lpfn = 0,
-       .mem_type = VMW_PL_GMR,
-       .flags = 0
-};
-
 struct ttm_placement vmw_vram_placement = {
        .num_placement = 1,
        .placement = &vram_placement_flags,
-       .num_busy_placement = 1,
-       .busy_placement = &vram_placement_flags
-};
-
-static const struct ttm_place vram_gmr_placement_flags[] = {
-       {
-               .fpfn = 0,
-               .lpfn = 0,
-               .mem_type = TTM_PL_VRAM,
-               .flags = 0
-       }, {
-               .fpfn = 0,
-               .lpfn = 0,
-               .mem_type = VMW_PL_GMR,
-               .flags = 0
-       }
-};
-
-struct ttm_placement vmw_vram_gmr_placement = {
-       .num_placement = 2,
-       .placement = vram_gmr_placement_flags,
-       .num_busy_placement = 1,
-       .busy_placement = &gmr_placement_flags
 };
 
 struct ttm_placement vmw_sys_placement = {
        .num_placement = 1,
        .placement = &sys_placement_flags,
-       .num_busy_placement = 1,
-       .busy_placement = &sys_placement_flags
 };
 
 const size_t vmw_tt_size = sizeof(struct vmw_ttm_tt);
index 2785935da497b865f1bf5831d6785350d55747a5..558152575d1022df74deed355eeee5c6f80b3cd1 100644 (file)
@@ -2091,9 +2091,6 @@ static int tc358743_probe(struct i2c_client *client)
        state->mbus_fmt_code = MEDIA_BUS_FMT_RGB888_1X24;
 
        sd->dev = &client->dev;
-       err = v4l2_async_register_subdev(sd);
-       if (err < 0)
-               goto err_hdl;
 
        mutex_init(&state->confctl_mutex);
 
@@ -2151,6 +2148,10 @@ static int tc358743_probe(struct i2c_client *client)
        if (err)
                goto err_work_queues;
 
+       err = v4l2_async_register_subdev(sd);
+       if (err < 0)
+               goto err_work_queues;
+
        v4l2_info(sd, "%s found @ 0x%x (%s)\n", client->name,
                  client->addr << 1, client->adapter->name);
 
index ab3d9b057d56bdcbdfed039ddc330ebc1e008c86..08bcccdd0f1c4994c50f6a5f773352b8ad149e52 100644 (file)
@@ -6,7 +6,6 @@ config FB_SM750
        select FB_CFB_FILLRECT
        select FB_CFB_COPYAREA
        select FB_CFB_IMAGEBLIT
-       select VIDEO_NOMODESET
        help
          Frame buffer driver for the Silicon Motion SM750 chip
          with 2D acceleration and dual head support.
index b694d7669d3200b148c5575a468f9464192114c0..130ebccb833804588f5f54a5d4cb7f16e995d7f8 100644 (file)
@@ -18,10 +18,7 @@ config STI_CORE
          STI refers to the HP "Standard Text Interface" which is a set of
          BIOS routines contained in a ROM chip in HP PA-RISC based machines.
 
-config VIDEO_CMDLINE
-       bool
-
-config VIDEO_NOMODESET
+config VIDEO
        bool
        default n
 
index 6bbc039508995ee9b027ab19571d9db53c75e6d9..9eb5557911de566fbcdae48b37748bda77ab4c4f 100644 (file)
@@ -3,8 +3,7 @@
 obj-$(CONFIG_APERTURE_HELPERS)    += aperture.o
 obj-$(CONFIG_STI_CORE)            += sticore.o
 obj-$(CONFIG_VGASTATE)            += vgastate.o
-obj-$(CONFIG_VIDEO_CMDLINE)       += cmdline.o
-obj-$(CONFIG_VIDEO_NOMODESET)     += nomodeset.o
+obj-$(CONFIG_VIDEO)               += cmdline.o nomodeset.o
 obj-$(CONFIG_HDMI)                += hdmi.o
 
 obj-$(CONFIG_VT)                 += console/
index d3d257489c3d51f2bf638ce8979be2a4e7c8fc82..49ee3fb4951a55b3cbe11c387191a70cc0c162c8 100644 (file)
@@ -80,6 +80,7 @@ const char *video_get_options(const char *name)
 }
 EXPORT_SYMBOL(video_get_options);
 
+#if IS_ENABLED(CONFIG_FB_CORE)
 bool __video_get_options(const char *name, const char **options, bool is_of)
 {
        bool enabled = true;
@@ -96,6 +97,7 @@ bool __video_get_options(const char *name, const char **options, bool is_of)
        return enabled;
 }
 EXPORT_SYMBOL(__video_get_options);
+#endif
 
 /*
  * Process command line options for video adapters. This function is
index 2d0bcc1d786e50bbeb8fadf7a5bde73403beef0d..a61b8260b8f36c4f311490813ac6c22c584a20e9 100644 (file)
@@ -75,7 +75,6 @@ config FB_CIRRUS
        select FB_CFB_COPYAREA
        select FB_CFB_IMAGEBLIT
        select FB_IOMEM_FOPS
-       select VIDEO_NOMODESET
        help
          This enables support for Cirrus Logic GD542x/543x based boards on
          Amiga: SD64, Piccolo, Picasso II/II+, Picasso IV, or EGS Spectrum.
@@ -95,7 +94,6 @@ config FB_PM2
        select FB_CFB_COPYAREA
        select FB_CFB_IMAGEBLIT
        select FB_IOMEM_FOPS
-       select VIDEO_NOMODESET
        help
          This is the frame buffer device driver for cards based on
          the 3D Labs Permedia, Permedia 2 and Permedia 2V chips.
@@ -161,7 +159,6 @@ config FB_CYBER2000
        tristate "CyberPro 2000/2010/5000 support"
        depends on FB && PCI && (BROKEN || !SPARC64)
        select FB_IOMEM_HELPERS
-       select VIDEO_NOMODESET
        help
          This enables support for the Integraphics CyberPro 20x0 and 5000
          VGA chips used in the Rebel.com Netwinder and other machines.
@@ -312,7 +309,6 @@ config FB_CT65550
        bool "Chips 65550 display support"
        depends on (FB = y) && PPC32 && PCI
        select FB_IOMEM_HELPERS
-       select VIDEO_NOMODESET
        help
          This is the frame buffer device driver for the Chips & Technologies
          65550 graphics chip in PowerBooks.
@@ -321,7 +317,6 @@ config FB_ASILIANT
        bool "Asiliant (Chips) 69000 display support"
        depends on (FB = y) && PCI
        select FB_IOMEM_HELPERS
-       select VIDEO_NOMODESET
        help
          This is the frame buffer device driver for the Asiliant 69030 chipset
 
@@ -331,7 +326,6 @@ config FB_IMSTT
        select FB_CFB_IMAGEBLIT
        select FB_IOMEM_FOPS
        select FB_MACMODES if PPC_PMAC
-       select VIDEO_NOMODESET
        help
          The IMS Twin Turbo is a PCI-based frame buffer card bundled with
          many Macintosh and compatible computers.
@@ -396,7 +390,6 @@ config FB_TGA
        select FB_CFB_COPYAREA
        select FB_CFB_IMAGEBLIT
        select FB_IOMEM_FOPS
-       select VIDEO_NOMODESET
        help
          This is the frame buffer device driver for generic TGA and SFB+
          graphic cards.  These include DEC ZLXp-E1, -E2 and -E3 PCI cards,
@@ -573,7 +566,6 @@ config FB_XVR500
        select FB_CFB_COPYAREA
        select FB_CFB_IMAGEBLIT
        select FB_IOMEM_FOPS
-       select VIDEO_NOMODESET
        help
          This is the framebuffer device for the Sun XVR-500 and similar
          graphics cards based upon the 3DLABS Wildcat chipset.  The driver
@@ -585,7 +577,6 @@ config FB_XVR2500
        bool "Sun XVR-2500 3DLABS Wildcat support"
        depends on (FB = y) && PCI && SPARC64
        select FB_IOMEM_HELPERS
-       select VIDEO_NOMODESET
        help
          This is the framebuffer device for the Sun XVR-2500 and similar
          graphics cards based upon the 3DLABS Wildcat chipset.  The driver
@@ -611,7 +602,6 @@ config FB_PVR2
        select FB_CFB_COPYAREA
        select FB_CFB_IMAGEBLIT
        select FB_IOMEM_FOPS
-       select VIDEO_NOMODESET
        help
          Say Y here if you have a PowerVR 2 card in your box.  If you plan to
          run linux on your Dreamcast, you will have to say Y here.
@@ -674,7 +664,6 @@ config FB_NVIDIA
        select FB_IOMEM_FOPS
        select BITREVERSE
        select VGASTATE
-       select VIDEO_NOMODESET
        help
          This driver supports graphics boards with the nVidia chips, TNT
          and newer. For very old chipsets, such as the RIVA128, then use
@@ -723,7 +712,6 @@ config FB_RIVA
        select FB_MODE_HELPERS
        select BITREVERSE
        select VGASTATE
-       select VIDEO_NOMODESET
        help
          This driver supports graphics boards with the nVidia Riva/Geforce
          chips.
@@ -766,7 +754,6 @@ config FB_I740
        select FB_IOMEM_HELPERS
        select FB_MODE_HELPERS
        select VGASTATE
-       select VIDEO_NOMODESET
        select FB_DDC
        help
          This driver supports graphics cards based on Intel740 chip.
@@ -777,7 +764,6 @@ config FB_I810
        select FB_IOMEM_FOPS
        select FB_MODE_HELPERS
        select VGASTATE
-       select VIDEO_NOMODESET
        help
          This driver supports the on-board graphics built in to the Intel 810
          and 815 chipsets.  Say Y if you have and plan to use such a board.
@@ -830,7 +816,6 @@ config FB_MATROX
        select FB_IOMEM_FOPS
        select FB_TILEBLITTING
        select FB_MACMODES if PPC_PMAC
-       select VIDEO_NOMODESET
        help
          Say Y here if you have a Matrox Millennium, Matrox Millennium II,
          Matrox Mystique, Matrox Mystique 220, Matrox Productiva G100, Matrox
@@ -953,7 +938,6 @@ config FB_RADEON
        select FB_IOMEM_FOPS
        select FB_MACMODES if PPC
        select FB_MODE_HELPERS
-       select VIDEO_NOMODESET
        help
          Choose this option if you want to use an ATI Radeon graphics card as
          a framebuffer device.  There are both PCI and AGP versions.  You
@@ -991,7 +975,6 @@ config FB_ATY128
        select FB_BACKLIGHT if FB_ATY128_BACKLIGHT
        select FB_IOMEM_HELPERS
        select FB_MACMODES if PPC_PMAC
-       select VIDEO_NOMODESET
        help
          This driver supports graphics boards with the ATI Rage128 chips.
          Say Y if you have such a graphics board and read
@@ -1017,7 +1000,6 @@ config FB_ATY
        select FB_IOMEM_FOPS
        select FB_MACMODES if PPC
        select FB_ATY_CT if SPARC64 && PCI
-       select VIDEO_NOMODESET
        help
          This driver supports graphics boards with the ATI Mach64 chips.
          Say Y if you have such a graphics board.
@@ -1069,7 +1051,6 @@ config FB_S3
        select FB_TILEBLITTING
        select FB_SVGALIB
        select VGASTATE
-       select VIDEO_NOMODESET
        select FONT_8x16 if FRAMEBUFFER_CONSOLE
        help
          Driver for graphics boards with S3 Trio / S3 Virge chip.
@@ -1091,7 +1072,6 @@ config FB_SAVAGE
        select FB_IOMEM_FOPS
        select FB_MODE_HELPERS
        select VGASTATE
-       select VIDEO_NOMODESET
        help
          This driver supports notebooks and computers with S3 Savage PCI/AGP
          chips.
@@ -1131,7 +1111,6 @@ config FB_SIS
        select FB_CFB_IMAGEBLIT
        select FB_IOMEM_FOPS
        select FB_SIS_300 if !FB_SIS_315
-       select VIDEO_NOMODESET
        help
          This is the frame buffer device driver for the SiS 300, 315, 330
          and 340 series as well as XGI V3XT, V5, V8, Z7 graphics chipsets.
@@ -1162,7 +1141,6 @@ config FB_VIA
        select FB_CFB_IMAGEBLIT
        select FB_IOMEM_FOPS
        select I2C_ALGOBIT
-       select VIDEO_NOMODESET
        help
          This is the frame buffer device driver for Graphics chips of VIA
          UniChrome (Pro) Family (CLE266,PM800/CN400,P4M800CE/P4M800Pro/
@@ -1203,7 +1181,6 @@ config FB_NEOMAGIC
        select FB_IOMEM_FOPS
        select FB_MODE_HELPERS
        select VGASTATE
-       select VIDEO_NOMODESET
        help
          This driver supports notebooks with NeoMagic PCI chips.
          Say Y if you have such a graphics card.
@@ -1215,7 +1192,6 @@ config FB_KYRO
        tristate "IMG Kyro support"
        depends on FB && PCI
        select FB_IOMEM_HELPERS
-       select VIDEO_NOMODESET
        help
          Say Y here if you have a STG4000 / Kyro / PowerVR 3 based
          graphics board.
@@ -1231,7 +1207,6 @@ config FB_3DFX
        select FB_CFB_IMAGEBLIT
        select FB_IOMEM_FOPS
        select FB_MODE_HELPERS
-       select VIDEO_NOMODESET
        help
          This driver supports graphics boards with the 3Dfx Banshee,
          Voodoo3 or VSA-100 (aka Voodoo4/5) chips. Say Y if you have
@@ -1260,7 +1235,6 @@ config FB_VOODOO1
        depends on FB && PCI
        depends on FB_DEVICE
        select FB_IOMEM_HELPERS
-       select VIDEO_NOMODESET
        help
          Say Y here if you have a 3Dfx Voodoo Graphics (Voodoo1/sst1) or
          Voodoo2 (cvg) based graphics card.
@@ -1283,7 +1257,6 @@ config FB_VT8623
        select FB_TILEBLITTING
        select FB_SVGALIB
        select VGASTATE
-       select VIDEO_NOMODESET
        select FONT_8x16 if FRAMEBUFFER_CONSOLE
        help
          Driver for CastleRock integrated graphics core in the
@@ -1298,7 +1271,6 @@ config FB_TRIDENT
        select FB_DDC
        select FB_IOMEM_FOPS
        select FB_MODE_HELPERS
-       select VIDEO_NOMODESET
        help
          This is the frame buffer device driver for Trident PCI/AGP chipsets.
          Supported chipset families are TGUI 9440/96XX, 3DImage, Blade3D
@@ -1323,7 +1295,6 @@ config FB_ARK
        select FB_TILEBLITTING
        select FB_SVGALIB
        select VGASTATE
-       select VIDEO_NOMODESET
        select FONT_8x16 if FRAMEBUFFER_CONSOLE
        help
          Driver for PCI graphics boards with ARK 2000PV chip
@@ -1336,7 +1307,6 @@ config FB_PM3
        select FB_CFB_COPYAREA
        select FB_CFB_IMAGEBLIT
        select FB_IOMEM_FOPS
-       select VIDEO_NOMODESET
        help
          This is the frame buffer device driver for the 3DLabs Permedia3
          chipset, used in Formac ProFormance III, 3DLabs Oxygen VX1 &
@@ -1347,7 +1317,6 @@ config FB_CARMINE
        tristate "Fujitsu carmine frame buffer support"
        depends on FB && PCI
        select FB_IOMEM_HELPERS
-       select VIDEO_NOMODESET
        help
          This is the frame buffer device driver for the Fujitsu Carmine chip.
          The driver provides two independent frame buffer devices.
@@ -1629,7 +1598,6 @@ config FB_IBM_GXT4500
        tristate "Framebuffer support for IBM GXT4000P/4500P/6000P/6500P adaptors"
        depends on FB
        select FB_IOMEM_HELPERS
-       select VIDEO_NOMODESET
        help
          Say Y here to enable support for the IBM GXT4000P/6000P and
          GXT4500P/6500P display adaptor based on Raster Engine RC1000,
@@ -1747,7 +1715,6 @@ config FB_MB862XX
        depends on FB
        depends on PCI || (OF && PPC)
        select FB_IOMEM_HELPERS
-       select VIDEO_NOMODESET
        help
          Frame buffer driver for Fujitsu Carmine/Coral-P(A)/Lime controllers.
 
@@ -1813,7 +1780,6 @@ config FB_HYPERV
        depends on FB && HYPERV
        select DMA_CMA if HAVE_DMA_CONTIGUOUS && CMA
        select FB_IOMEM_HELPERS_DEFERRED
-       select VIDEO_NOMODESET
        help
          This framebuffer driver supports Microsoft Hyper-V Synthetic Video.
 
@@ -1847,7 +1813,6 @@ config FB_SM712
        tristate "Silicon Motion SM712 framebuffer support"
        depends on FB && PCI
        select FB_IOMEM_HELPERS
-       select VIDEO_NOMODESET
        help
          Frame buffer driver for the Silicon Motion SM710, SM712, SM721
          and SM722 chips.
index 21053bf00dc58cbe9e67d6780ccf66007e7b0817..db09fe87fcd4fe635f27a08f21b069bf76146632 100644 (file)
@@ -4,7 +4,7 @@
 #
 
 config FB_CORE
-       select VIDEO_CMDLINE
+       select VIDEO
        tristate
 
 config FB_NOTIFY
index fc206755f5f6da99cc7e29216ea6451ad45d3138..48287366e0d4a1925211ec9c29a3a1c425640308 100644 (file)
@@ -645,7 +645,6 @@ int fb_new_modelist(struct fb_info *info)
        return 0;
 }
 
-#if defined(CONFIG_VIDEO_NOMODESET)
 bool fb_modesetting_disabled(const char *drvname)
 {
        bool fwonly = video_firmware_drivers_only();
@@ -657,6 +656,5 @@ bool fb_modesetting_disabled(const char *drvname)
        return fwonly;
 }
 EXPORT_SYMBOL(fb_modesetting_disabled);
-#endif
 
 MODULE_LICENSE("GPL");
index f9b4ddd592ce4deecb803d2fcc07b02031dae85f..10fc14ad5d12728dfb6a41d465442a9a405092a1 100644 (file)
@@ -108,7 +108,7 @@ static int efifb_setcolreg(unsigned regno, unsigned red, unsigned green,
  */
 #if defined CONFIG_FRAMEBUFFER_CONSOLE_DEFERRED_TAKEOVER && \
     defined CONFIG_ACPI_BGRT
-static void efifb_copy_bmp(u8 *src, u32 *dst, int width, struct screen_info *si)
+static void efifb_copy_bmp(u8 *src, u32 *dst, int width, const struct screen_info *si)
 {
        u8 r, g, b;
 
@@ -130,7 +130,7 @@ static void efifb_copy_bmp(u8 *src, u32 *dst, int width, struct screen_info *si)
  * resolution still fits, it will be displayed very close to the right edge of
  * the display looking quite bad. This function checks for this.
  */
-static bool efifb_bgrt_sanity_check(struct screen_info *si, u32 bmp_width)
+static bool efifb_bgrt_sanity_check(const struct screen_info *si, u32 bmp_width)
 {
        /*
         * All x86 firmwares horizontally center the image (the yoffset
@@ -141,16 +141,15 @@ static bool efifb_bgrt_sanity_check(struct screen_info *si, u32 bmp_width)
        return bgrt_tab.image_offset_x == expected_xoffset;
 }
 #else
-static bool efifb_bgrt_sanity_check(struct screen_info *si, u32 bmp_width)
+static bool efifb_bgrt_sanity_check(const struct screen_info *si, u32 bmp_width)
 {
        return true;
 }
 #endif
 
-static void efifb_show_boot_graphics(struct fb_info *info)
+static void efifb_show_boot_graphics(struct fb_info *info, const struct screen_info *si)
 {
        u32 bmp_width, bmp_height, bmp_pitch, dst_x, y, src_y;
-       struct screen_info *si = &screen_info;
        struct bmp_file_header *file_header;
        struct bmp_dib_header *dib_header;
        void *bgrt_image = NULL;
@@ -247,7 +246,8 @@ error:
        pr_warn("efifb: Ignoring BGRT: unexpected or invalid BMP data\n");
 }
 #else
-static inline void efifb_show_boot_graphics(struct fb_info *info) {}
+static inline void efifb_show_boot_graphics(struct fb_info *info, const struct screen_info *si)
+{ }
 #endif
 
 /*
@@ -282,7 +282,7 @@ static const struct fb_ops efifb_ops = {
        .fb_setcolreg   = efifb_setcolreg,
 };
 
-static int efifb_setup(char *options)
+static int efifb_setup(struct screen_info *si, char *options)
 {
        char *this_opt;
 
@@ -290,16 +290,16 @@ static int efifb_setup(char *options)
                while ((this_opt = strsep(&options, ",")) != NULL) {
                        if (!*this_opt) continue;
 
-                       efifb_setup_from_dmi(&screen_info, this_opt);
+                       efifb_setup_from_dmi(si, this_opt);
 
                        if (!strncmp(this_opt, "base:", 5))
-                               screen_info.lfb_base = simple_strtoul(this_opt+5, NULL, 0);
+                               si->lfb_base = simple_strtoul(this_opt+5, NULL, 0);
                        else if (!strncmp(this_opt, "stride:", 7))
-                               screen_info.lfb_linelength = simple_strtoul(this_opt+7, NULL, 0) * 4;
+                               si->lfb_linelength = simple_strtoul(this_opt+7, NULL, 0) * 4;
                        else if (!strncmp(this_opt, "height:", 7))
-                               screen_info.lfb_height = simple_strtoul(this_opt+7, NULL, 0);
+                               si->lfb_height = simple_strtoul(this_opt+7, NULL, 0);
                        else if (!strncmp(this_opt, "width:", 6))
-                               screen_info.lfb_width = simple_strtoul(this_opt+6, NULL, 0);
+                               si->lfb_width = simple_strtoul(this_opt+6, NULL, 0);
                        else if (!strcmp(this_opt, "nowc"))
                                mem_flags &= ~EFI_MEMORY_WC;
                        else if (!strcmp(this_opt, "nobgrt"))
@@ -310,15 +310,15 @@ static int efifb_setup(char *options)
        return 0;
 }
 
-static inline bool fb_base_is_valid(void)
+static inline bool fb_base_is_valid(struct screen_info *si)
 {
-       if (screen_info.lfb_base)
+       if (si->lfb_base)
                return true;
 
-       if (!(screen_info.capabilities & VIDEO_CAPABILITY_64BIT_BASE))
+       if (!(si->capabilities & VIDEO_CAPABILITY_64BIT_BASE))
                return false;
 
-       if (screen_info.ext_lfb_base)
+       if (si->ext_lfb_base)
                return true;
 
        return false;
@@ -329,7 +329,10 @@ static ssize_t name##_show(struct device *dev,                             \
                           struct device_attribute *attr,               \
                           char *buf)                                   \
 {                                                                      \
-       return sprintf(buf, fmt "\n", (screen_info.lfb_##name));        \
+       struct screen_info *si = dev_get_platdata(dev);                 \
+       if (!si)                                                        \
+               return -ENODEV;                                         \
+       return sprintf(buf, fmt "\n", (si->lfb_##name));                \
 }                                                                      \
 static DEVICE_ATTR_RO(name)
 
@@ -356,6 +359,7 @@ static u64 bar_offset;
 
 static int efifb_probe(struct platform_device *dev)
 {
+       struct screen_info *si;
        struct fb_info *info;
        struct efifb_par *par;
        int err, orientation;
@@ -365,48 +369,60 @@ static int efifb_probe(struct platform_device *dev)
        char *option = NULL;
        efi_memory_desc_t md;
 
-       if (screen_info.orig_video_isVGA != VIDEO_TYPE_EFI || pci_dev_disabled)
+       /*
+        * If we fail probing the device, the kernel might try a different
+        * driver. We get a copy of the attached screen_info, so that we can
+        * modify its values without affecting later drivers.
+        */
+       si = dev_get_platdata(&dev->dev);
+       if (!si)
+               return -ENODEV;
+       si = devm_kmemdup(&dev->dev, si, sizeof(*si), GFP_KERNEL);
+       if (!si)
+               return -ENOMEM;
+
+       if (si->orig_video_isVGA != VIDEO_TYPE_EFI || pci_dev_disabled)
                return -ENODEV;
 
        if (fb_get_options("efifb", &option))
                return -ENODEV;
-       efifb_setup(option);
+       efifb_setup(si, option);
 
        /* We don't get linelength from UGA Draw Protocol, only from
         * EFI Graphics Protocol.  So if it's not in DMI, and it's not
         * passed in from the user, we really can't use the framebuffer.
         */
-       if (!screen_info.lfb_linelength)
+       if (!si->lfb_linelength)
                return -ENODEV;
 
-       if (!screen_info.lfb_depth)
-               screen_info.lfb_depth = 32;
-       if (!screen_info.pages)
-               screen_info.pages = 1;
-       if (!fb_base_is_valid()) {
+       if (!si->lfb_depth)
+               si->lfb_depth = 32;
+       if (!si->pages)
+               si->pages = 1;
+       if (!fb_base_is_valid(si)) {
                printk(KERN_DEBUG "efifb: invalid framebuffer address\n");
                return -ENODEV;
        }
        printk(KERN_INFO "efifb: probing for efifb\n");
 
        /* just assume they're all unset if any are */
-       if (!screen_info.blue_size) {
-               screen_info.blue_size = 8;
-               screen_info.blue_pos = 0;
-               screen_info.green_size = 8;
-               screen_info.green_pos = 8;
-               screen_info.red_size = 8;
-               screen_info.red_pos = 16;
-               screen_info.rsvd_size = 8;
-               screen_info.rsvd_pos = 24;
+       if (!si->blue_size) {
+               si->blue_size = 8;
+               si->blue_pos = 0;
+               si->green_size = 8;
+               si->green_pos = 8;
+               si->red_size = 8;
+               si->red_pos = 16;
+               si->rsvd_size = 8;
+               si->rsvd_pos = 24;
        }
 
-       efifb_fix.smem_start = screen_info.lfb_base;
+       efifb_fix.smem_start = si->lfb_base;
 
-       if (screen_info.capabilities & VIDEO_CAPABILITY_64BIT_BASE) {
+       if (si->capabilities & VIDEO_CAPABILITY_64BIT_BASE) {
                u64 ext_lfb_base;
 
-               ext_lfb_base = (u64)(unsigned long)screen_info.ext_lfb_base << 32;
+               ext_lfb_base = (u64)(unsigned long)si->ext_lfb_base << 32;
                efifb_fix.smem_start |= ext_lfb_base;
        }
 
@@ -417,10 +433,10 @@ static int efifb_probe(struct platform_device *dev)
                efifb_fix.smem_start = bar_resource->start + bar_offset;
        }
 
-       efifb_defined.bits_per_pixel = screen_info.lfb_depth;
-       efifb_defined.xres = screen_info.lfb_width;
-       efifb_defined.yres = screen_info.lfb_height;
-       efifb_fix.line_length = screen_info.lfb_linelength;
+       efifb_defined.bits_per_pixel = si->lfb_depth;
+       efifb_defined.xres = si->lfb_width;
+       efifb_defined.yres = si->lfb_height;
+       efifb_fix.line_length = si->lfb_linelength;
 
        /*   size_vmode -- that is the amount of memory needed for the
         *                 used video mode, i.e. the minimum amount of
@@ -430,7 +446,7 @@ static int efifb_probe(struct platform_device *dev)
        /*   size_total -- all video memory we have. Used for
         *                 entries, ressource allocation and bounds
         *                 checking. */
-       size_total = screen_info.lfb_size;
+       size_total = si->lfb_size;
        if (size_total < size_vmode)
                size_total = size_vmode;
 
@@ -505,14 +521,14 @@ static int efifb_probe(struct platform_device *dev)
                goto err_release_fb;
        }
 
-       efifb_show_boot_graphics(info);
+       efifb_show_boot_graphics(info, si);
 
        pr_info("efifb: framebuffer at 0x%lx, using %dk, total %dk\n",
               efifb_fix.smem_start, size_remap/1024, size_total/1024);
        pr_info("efifb: mode is %dx%dx%d, linelength=%d, pages=%d\n",
               efifb_defined.xres, efifb_defined.yres,
               efifb_defined.bits_per_pixel, efifb_fix.line_length,
-              screen_info.pages);
+              si->pages);
 
        efifb_defined.xres_virtual = efifb_defined.xres;
        efifb_defined.yres_virtual = efifb_fix.smem_len /
@@ -526,26 +542,26 @@ static int efifb_probe(struct platform_device *dev)
        efifb_defined.left_margin  = (efifb_defined.xres / 8) & 0xf8;
        efifb_defined.hsync_len    = (efifb_defined.xres / 8) & 0xf8;
 
-       efifb_defined.red.offset    = screen_info.red_pos;
-       efifb_defined.red.length    = screen_info.red_size;
-       efifb_defined.green.offset  = screen_info.green_pos;
-       efifb_defined.green.length  = screen_info.green_size;
-       efifb_defined.blue.offset   = screen_info.blue_pos;
-       efifb_defined.blue.length   = screen_info.blue_size;
-       efifb_defined.transp.offset = screen_info.rsvd_pos;
-       efifb_defined.transp.length = screen_info.rsvd_size;
+       efifb_defined.red.offset    = si->red_pos;
+       efifb_defined.red.length    = si->red_size;
+       efifb_defined.green.offset  = si->green_pos;
+       efifb_defined.green.length  = si->green_size;
+       efifb_defined.blue.offset   = si->blue_pos;
+       efifb_defined.blue.length   = si->blue_size;
+       efifb_defined.transp.offset = si->rsvd_pos;
+       efifb_defined.transp.length = si->rsvd_size;
 
        pr_info("efifb: %s: "
               "size=%d:%d:%d:%d, shift=%d:%d:%d:%d\n",
               "Truecolor",
-              screen_info.rsvd_size,
-              screen_info.red_size,
-              screen_info.green_size,
-              screen_info.blue_size,
-              screen_info.rsvd_pos,
-              screen_info.red_pos,
-              screen_info.green_pos,
-              screen_info.blue_pos);
+              si->rsvd_size,
+              si->red_size,
+              si->green_size,
+              si->blue_size,
+              si->rsvd_pos,
+              si->red_pos,
+              si->green_pos,
+              si->blue_pos);
 
        efifb_fix.ypanstep  = 0;
        efifb_fix.ywrapstep = 0;
index 9a49916e0492961502ff92b491886e2c1bc1c7f5..3b20420cc94d3115d8413d805818526818a36cb8 100644 (file)
@@ -14,7 +14,6 @@ config FB_GEODE_LX
        tristate "AMD Geode LX framebuffer support"
        depends on FB && FB_GEODE
        select FB_IOMEM_HELPERS
-       select VIDEO_NOMODESET
        help
          Framebuffer driver for the display controller integrated into the
          AMD Geode LX processors.
@@ -28,7 +27,6 @@ config FB_GEODE_GX
        tristate "AMD Geode GX framebuffer support"
        depends on FB && FB_GEODE
        select FB_IOMEM_HELPERS
-       select VIDEO_NOMODESET
        help
          Framebuffer driver for the display controller integrated into the
          AMD Geode GX processors.
@@ -42,7 +40,6 @@ config FB_GEODE_GX1
        tristate "AMD Geode GX1 framebuffer support"
        depends on FB && FB_GEODE
        select FB_IOMEM_HELPERS
-       select VIDEO_NOMODESET
        help
          Framebuffer driver for the display controller integrated into the
          AMD Geode GX1 processor.
index 6f58ee276ad1b0e0ebe9dd97358feef70bad160f..028a565250476c5f58434b68a6ea5152e4ccd606 100644 (file)
@@ -470,7 +470,7 @@ static int simplefb_attach_genpds(struct simplefb_par *par,
                if (err == -ENOENT)
                        return 0;
 
-               dev_info(dev, "failed to parse power-domains: %d\n", err);
+               dev_err(dev, "failed to parse power-domains: %d\n", err);
                return err;
        }
 
index c0edceea0a7934f37c5d2f49874e76948c6eef1e..8ab64ae4cad3ec4215852bb79a74de62c7c6f69a 100644 (file)
@@ -243,6 +243,7 @@ static int vesafb_setup(char *options)
 
 static int vesafb_probe(struct platform_device *dev)
 {
+       struct screen_info *si;
        struct fb_info *info;
        struct vesafb_par *par;
        int i, err;
@@ -251,21 +252,33 @@ static int vesafb_probe(struct platform_device *dev)
        unsigned int size_total;
        char *option = NULL;
 
+       /*
+        * If we fail probing the device, the kernel might try a different
+        * driver. We get a copy of the attached screen_info, so that we can
+        * modify its values without affecting later drivers.
+        */
+       si = dev_get_platdata(&dev->dev);
+       if (!si)
+               return -ENODEV;
+       si = devm_kmemdup(&dev->dev, si, sizeof(*si), GFP_KERNEL);
+       if (!si)
+               return -ENOMEM;
+
        /* ignore error return of fb_get_options */
        fb_get_options("vesafb", &option);
        vesafb_setup(option);
 
-       if (screen_info.orig_video_isVGA != VIDEO_TYPE_VLFB)
+       if (si->orig_video_isVGA != VIDEO_TYPE_VLFB)
                return -ENODEV;
 
-       vga_compat = (screen_info.capabilities & 2) ? 0 : 1;
-       vesafb_fix.smem_start = screen_info.lfb_base;
-       vesafb_defined.bits_per_pixel = screen_info.lfb_depth;
+       vga_compat = (si->capabilities & 2) ? 0 : 1;
+       vesafb_fix.smem_start = si->lfb_base;
+       vesafb_defined.bits_per_pixel = si->lfb_depth;
        if (15 == vesafb_defined.bits_per_pixel)
                vesafb_defined.bits_per_pixel = 16;
-       vesafb_defined.xres = screen_info.lfb_width;
-       vesafb_defined.yres = screen_info.lfb_height;
-       vesafb_fix.line_length = screen_info.lfb_linelength;
+       vesafb_defined.xres = si->lfb_width;
+       vesafb_defined.yres = si->lfb_height;
+       vesafb_fix.line_length = si->lfb_linelength;
        vesafb_fix.visual   = (vesafb_defined.bits_per_pixel == 8) ?
                FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
 
@@ -277,7 +290,7 @@ static int vesafb_probe(struct platform_device *dev)
        /*   size_total -- all video memory we have. Used for mtrr
         *                 entries, resource allocation and bounds
         *                 checking. */
-       size_total = screen_info.lfb_size * 65536;
+       size_total = si->lfb_size * 65536;
        if (vram_total)
                size_total = vram_total * 1024 * 1024;
        if (size_total < size_vmode)
@@ -297,7 +310,7 @@ static int vesafb_probe(struct platform_device *dev)
        vesafb_fix.smem_len = size_remap;
 
 #ifndef __i386__
-       screen_info.vesapm_seg = 0;
+       si->vesapm_seg = 0;
 #endif
 
        if (!request_mem_region(vesafb_fix.smem_start, size_total, "vesafb")) {
@@ -317,23 +330,26 @@ static int vesafb_probe(struct platform_device *dev)
        par = info->par;
        info->pseudo_palette = par->pseudo_palette;
 
-       par->base = screen_info.lfb_base;
+       par->base = si->lfb_base;
        par->size = size_total;
 
        printk(KERN_INFO "vesafb: mode is %dx%dx%d, linelength=%d, pages=%d\n",
-              vesafb_defined.xres, vesafb_defined.yres, vesafb_defined.bits_per_pixel, vesafb_fix.line_length, screen_info.pages);
+              vesafb_defined.xres, vesafb_defined.yres, vesafb_defined.bits_per_pixel,
+              vesafb_fix.line_length, si->pages);
 
-       if (screen_info.vesapm_seg) {
+       if (si->vesapm_seg) {
                printk(KERN_INFO "vesafb: protected mode interface info at %04x:%04x\n",
-                      screen_info.vesapm_seg,screen_info.vesapm_off);
+                      si->vesapm_seg, si->vesapm_off);
        }
 
-       if (screen_info.vesapm_seg < 0xc000)
+       if (si->vesapm_seg < 0xc000)
                ypan = pmi_setpal = 0; /* not available or some DOS TSR ... */
 
        if (ypan || pmi_setpal) {
+               unsigned long pmi_phys;
                unsigned short *pmi_base;
-               pmi_base  = (unsigned short*)phys_to_virt(((unsigned long)screen_info.vesapm_seg << 4) + screen_info.vesapm_off);
+               pmi_phys  = ((unsigned long)si->vesapm_seg << 4) + si->vesapm_off;
+               pmi_base  = (unsigned short *)phys_to_virt(pmi_phys);
                pmi_start = (void*)((char*)pmi_base + pmi_base[1]);
                pmi_pal   = (void*)((char*)pmi_base + pmi_base[2]);
                printk(KERN_INFO "vesafb: pmi: set display start = %p, set palette = %p\n",pmi_start,pmi_pal);
@@ -377,14 +393,14 @@ static int vesafb_probe(struct platform_device *dev)
        vesafb_defined.left_margin  = (vesafb_defined.xres / 8) & 0xf8;
        vesafb_defined.hsync_len    = (vesafb_defined.xres / 8) & 0xf8;
 
-       vesafb_defined.red.offset    = screen_info.red_pos;
-       vesafb_defined.red.length    = screen_info.red_size;
-       vesafb_defined.green.offset  = screen_info.green_pos;
-       vesafb_defined.green.length  = screen_info.green_size;
-       vesafb_defined.blue.offset   = screen_info.blue_pos;
-       vesafb_defined.blue.length   = screen_info.blue_size;
-       vesafb_defined.transp.offset = screen_info.rsvd_pos;
-       vesafb_defined.transp.length = screen_info.rsvd_size;
+       vesafb_defined.red.offset    = si->red_pos;
+       vesafb_defined.red.length    = si->red_size;
+       vesafb_defined.green.offset  = si->green_pos;
+       vesafb_defined.green.length  = si->green_size;
+       vesafb_defined.blue.offset   = si->blue_pos;
+       vesafb_defined.blue.length   = si->blue_size;
+       vesafb_defined.transp.offset = si->rsvd_pos;
+       vesafb_defined.transp.length = si->rsvd_size;
 
        if (vesafb_defined.bits_per_pixel <= 8) {
                depth = vesafb_defined.green.length;
@@ -399,14 +415,14 @@ static int vesafb_probe(struct platform_device *dev)
               (vesafb_defined.bits_per_pixel > 8) ?
               "Truecolor" : (vga_compat || pmi_setpal) ?
               "Pseudocolor" : "Static Pseudocolor",
-              screen_info.rsvd_size,
-              screen_info.red_size,
-              screen_info.green_size,
-              screen_info.blue_size,
-              screen_info.rsvd_pos,
-              screen_info.red_pos,
-              screen_info.green_pos,
-              screen_info.blue_pos);
+              si->rsvd_size,
+              si->red_size,
+              si->green_size,
+              si->blue_size,
+              si->rsvd_pos,
+              si->red_pos,
+              si->green_pos,
+              si->blue_pos);
 
        vesafb_fix.ypanstep  = ypan     ? 1 : 0;
        vesafb_fix.ywrapstep = (ypan>1) ? 1 : 0;
index cf8e1220a4ac4a0a465d4d4a6dad7624b1314ee6..4d7f4c5f20018566401973136d55721f1dd545b9 100644 (file)
@@ -346,25 +346,29 @@ struct __drm_private_objs_state {
 };
 
 /**
- * struct drm_atomic_state - the global state object for atomic updates
- * @ref: count of all references to this state (will not be freed until zero)
- * @dev: parent DRM device
- * @async_update: hint for asynchronous plane update
- * @planes: pointer to array of structures with per-plane data
- * @crtcs: pointer to array of CRTC pointers
- * @num_connector: size of the @connectors and @connector_states arrays
- * @connectors: pointer to array of structures with per-connector data
- * @num_private_objs: size of the @private_objs array
- * @private_objs: pointer to array of private object pointers
- * @acquire_ctx: acquire context for this atomic modeset state update
+ * struct drm_atomic_state - Atomic commit structure
+ *
+ * This structure is the kernel counterpart of @drm_mode_atomic and represents
+ * an atomic commit that transitions from an old to a new display state. It
+ * contains all the objects affected by the atomic commit and both the new
+ * state structures and pointers to the old state structures for
+ * these.
  *
  * States are added to an atomic update by calling drm_atomic_get_crtc_state(),
  * drm_atomic_get_plane_state(), drm_atomic_get_connector_state(), or for
  * private state structures, drm_atomic_get_private_obj_state().
  */
 struct drm_atomic_state {
+       /**
+        * @ref:
+        *
+        * Count of all references to this update (will not be freed until zero).
+        */
        struct kref ref;
 
+       /**
+        * @dev: Parent DRM Device.
+        */
        struct drm_device *dev;
 
        /**
@@ -388,7 +392,12 @@ struct drm_atomic_state {
         * flag are not allowed.
         */
        bool legacy_cursor_update : 1;
+
+       /**
+        * @async_update: hint for asynchronous plane update
+        */
        bool async_update : 1;
+
        /**
         * @duplicated:
         *
@@ -398,13 +407,52 @@ struct drm_atomic_state {
         * states.
         */
        bool duplicated : 1;
+
+       /**
+        * @planes:
+        *
+        * Pointer to array of @drm_plane and @drm_plane_state part of this
+        * update.
+        */
        struct __drm_planes_state *planes;
+
+       /**
+        * @crtcs:
+        *
+        * Pointer to array of @drm_crtc and @drm_crtc_state part of this
+        * update.
+        */
        struct __drm_crtcs_state *crtcs;
+
+       /**
+        * @num_connector: size of the @connectors array
+        */
        int num_connector;
+
+       /**
+        * @connectors:
+        *
+        * Pointer to array of @drm_connector and @drm_connector_state part of
+        * this update.
+        */
        struct __drm_connnectors_state *connectors;
+
+       /**
+        * @num_private_objs: size of the @private_objs array
+        */
        int num_private_objs;
+
+       /**
+        * @private_objs:
+        *
+        * Pointer to array of @drm_private_obj and @drm_private_obj_state part
+        * of this update.
+        */
        struct __drm_private_objs_state *private_objs;
 
+       /**
+        * @acquire_ctx: acquire context for this atomic modeset state update
+        */
        struct drm_modeset_acquire_ctx *acquire_ctx;
 
        /**
index 518d1b8106c7675bbcec0c2867caeff2fab52ca0..7923bc00dc7a4386ef641c04d4e4d141b186b211 100644 (file)
 #define __DRM_EDID_H__
 
 #include <linux/types.h>
-#include <linux/hdmi.h>
-#include <drm/drm_mode.h>
 
+enum hdmi_quantization_range;
+struct drm_connector;
 struct drm_device;
+struct drm_display_mode;
 struct drm_edid;
+struct hdmi_avi_infoframe;
+struct hdmi_vendor_infoframe;
 struct i2c_adapter;
 
 #define EDID_LENGTH 128
@@ -46,7 +49,7 @@ struct est_timings {
        u8 t1;
        u8 t2;
        u8 mfg_rsvd;
-} __attribute__((packed));
+} __packed;
 
 /* 00=16:10, 01=4:3, 10=5:4, 11=16:9 */
 #define EDID_TIMING_ASPECT_SHIFT 6
@@ -59,7 +62,7 @@ struct est_timings {
 struct std_timing {
        u8 hsize; /* need to multiply by 8 then add 248 */
        u8 vfreq_aspect;
-} __attribute__((packed));
+} __packed;
 
 #define DRM_EDID_PT_HSYNC_POSITIVE (1 << 1)
 #define DRM_EDID_PT_VSYNC_POSITIVE (1 << 2)
@@ -85,12 +88,12 @@ struct detailed_pixel_timing {
        u8 hborder;
        u8 vborder;
        u8 misc;
-} __attribute__((packed));
+} __packed;
 
 /* If it's not pixel timing, it'll be one of the below */
 struct detailed_data_string {
        u8 str[13];
-} __attribute__((packed));
+} __packed;
 
 #define DRM_EDID_RANGE_OFFSET_MIN_VFREQ (1 << 0) /* 1.4 */
 #define DRM_EDID_RANGE_OFFSET_MAX_VFREQ (1 << 1) /* 1.4 */
@@ -120,7 +123,7 @@ struct detailed_data_monitor_range {
                        __le16 m;
                        u8 k;
                        u8 j; /* need to divide by 2 */
-               } __attribute__((packed)) gtf2;
+               } __packed gtf2;
                struct {
                        u8 version;
                        u8 data1; /* high 6 bits: extra clock resolution */
@@ -129,27 +132,27 @@ struct detailed_data_monitor_range {
                        u8 flags; /* preferred aspect and blanking support */
                        u8 supported_scalings;
                        u8 preferred_refresh;
-               } __attribute__((packed)) cvt;
-       } __attribute__((packed)) formula;
-} __attribute__((packed));
+               } __packed cvt;
+       } __packed formula;
+} __packed;
 
 struct detailed_data_wpindex {
        u8 white_yx_lo; /* Lower 2 bits each */
        u8 white_x_hi;
        u8 white_y_hi;
        u8 gamma; /* need to divide by 100 then add 1 */
-} __attribute__((packed));
+} __packed;
 
 struct detailed_data_color_point {
        u8 windex1;
        u8 wpindex1[3];
        u8 windex2;
        u8 wpindex2[3];
-} __attribute__((packed));
+} __packed;
 
 struct cvt_timing {
        u8 code[3];
-} __attribute__((packed));
+} __packed;
 
 struct detailed_non_pixel {
        u8 pad1;
@@ -163,8 +166,8 @@ struct detailed_non_pixel {
                struct detailed_data_wpindex color;
                struct std_timing timings[6];
                struct cvt_timing cvt[4];
-       } __attribute__((packed)) data;
-} __attribute__((packed));
+       } __packed data;
+} __packed;
 
 #define EDID_DETAIL_EST_TIMINGS 0xf7
 #define EDID_DETAIL_CVT_3BYTE 0xf8
@@ -181,8 +184,8 @@ struct detailed_timing {
        union {
                struct detailed_pixel_timing pixel_data;
                struct detailed_non_pixel other_data;
-       } __attribute__((packed)) data;
-} __attribute__((packed));
+       } __packed data;
+} __packed;
 
 #define DRM_EDID_INPUT_SERRATION_VSYNC (1 << 0)
 #define DRM_EDID_INPUT_SYNC_ON_GREEN   (1 << 1)
@@ -307,7 +310,7 @@ struct edid {
        u8 extensions;
        /* Checksum */
        u8 checksum;
-} __attribute__((packed));
+} __packed;
 
 #define EDID_PRODUCT_ID(e) ((e)->prod_code[0] | ((e)->prod_code[1] << 8))
 
@@ -319,11 +322,6 @@ struct cea_sad {
        u8 byte2; /* meaning depends on format */
 };
 
-struct drm_encoder;
-struct drm_connector;
-struct drm_connector_state;
-struct drm_display_mode;
-
 int drm_edid_to_sad(const struct edid *edid, struct cea_sad **sads);
 int drm_edid_to_speaker_allocation(const struct edid *edid, u8 **sadb);
 int drm_av_sync_delay(struct drm_connector *connector,
@@ -426,8 +424,6 @@ enum hdmi_quantization_range
 drm_default_rgb_quant_range(const struct drm_display_mode *mode);
 int drm_add_modes_noedid(struct drm_connector *connector,
                         int hdisplay, int vdisplay);
-void drm_set_preferred_mode(struct drm_connector *connector,
-                           int hpref, int vpref);
 
 int drm_edid_header_is_valid(const void *edid);
 bool drm_edid_block_valid(u8 *raw_edid, int block, bool print_bad_edid,
index f1a66c0487217b71ef9ab2b369817a5833799db5..aa786b828a0a412744ff724d4326fd8c56538d71 100644 (file)
@@ -18,7 +18,7 @@ struct drm_exec {
        /**
         * @flags: Flags to control locking behavior
         */
-       uint32_t                flags;
+       u32                     flags;
 
        /**
         * @ticket: WW ticket used for acquiring locks
@@ -135,7 +135,7 @@ static inline bool drm_exec_is_contended(struct drm_exec *exec)
        return !!exec->contended;
 }
 
-void drm_exec_init(struct drm_exec *exec, uint32_t flags, unsigned nr);
+void drm_exec_init(struct drm_exec *exec, u32 flags, unsigned nr);
 void drm_exec_fini(struct drm_exec *exec);
 bool drm_exec_cleanup(struct drm_exec *exec);
 int drm_exec_lock_obj(struct drm_exec *exec, struct drm_gem_object *obj);
index 6ea339d5de088424676e7a0abf4bb06eecfaefa9..0c9f917a4d4be956d50c587a8c7b90011335c9ce 100644 (file)
@@ -95,7 +95,7 @@ static inline int drm_fixp2int_round(s64 a)
 
 static inline int drm_fixp2int_ceil(s64 a)
 {
-       if (a > 0)
+       if (a >= 0)
                return drm_fixp2int(a + DRM_FIXED_ALMOST_ONE);
        else
                return drm_fixp2int(a - DRM_FIXED_ALMOST_ONE);
index 9060f9fae6f12c5c67dd96ecdb977196bf084884..00d4e43b76b6c12e10e422d250ab0ac1c9009bc5 100644 (file)
@@ -518,7 +518,7 @@ struct drm_gpuvm_exec {
        /**
         * @flags: the flags for the struct drm_exec
         */
-       uint32_t flags;
+       u32 flags;
 
        /**
         * @vm: the &drm_gpuvm to lock its DMA reservations
index ad08f834af408f7d8b01d3335a1332601766eb03..f547b09ca0239dd7c4fb734038bae4438321395c 100644 (file)
@@ -45,6 +45,10 @@ int __must_check __drmm_add_action_or_reset(struct drm_device *dev,
                                            drmres_release_t action,
                                            void *data, const char *name);
 
+void drmm_release_action(struct drm_device *dev,
+                        drmres_release_t action,
+                        void *data);
+
 void *drmm_kmalloc(struct drm_device *dev, size_t size, gfp_t gfp) __malloc;
 
 /**
index c613f0abe9dceca89ae399b796feb3f2e222e6f2..b9bb92e4b0295a5cbe0eb0da13e77449ff04f51d 100644 (file)
@@ -467,6 +467,8 @@ bool drm_mode_is_420_also(const struct drm_display_info *display,
                          const struct drm_display_mode *mode);
 bool drm_mode_is_420(const struct drm_display_info *display,
                     const struct drm_display_mode *mode);
+void drm_set_preferred_mode(struct drm_connector *connector,
+                           int hpref, int vpref);
 
 struct drm_display_mode *drm_analog_tv_mode(struct drm_device *dev,
                                            enum drm_connector_tv_mode mode,
index fad3c4003b2b5bf329d8bc2c83965aa6124ab0b0..62741a88796bb462b1d7e3970fa99ac6919860ed 100644 (file)
@@ -32,7 +32,6 @@ enum drm_mode_status drm_crtc_helper_mode_valid_fixed(struct drm_crtc *crtc,
                                                      const struct drm_display_mode *mode,
                                                      const struct drm_display_mode *fixed_mode);
 
-int drm_connector_helper_get_modes_from_ddc(struct drm_connector *connector);
 int drm_connector_helper_get_modes_fixed(struct drm_connector *connector,
                                         const struct drm_display_mode *fixed_mode);
 int drm_connector_helper_get_modes(struct drm_connector *connector);
index 8074d0f6cae558da181c3316b5ad547199ab8dde..b510a4812609fa44a92b27a2350e3a30bc3486f5 100644 (file)
 /* For multihop handling */
 #define TTM_PL_FLAG_TEMPORARY   (1 << 2)
 
+/* Placement is never used during eviction */
+#define TTM_PL_FLAG_DESIRED    (1 << 3)
+
+/* Placement is only used during eviction */
+#define TTM_PL_FLAG_FALLBACK   (1 << 4)
+
 /**
  * struct ttm_place
  *
@@ -86,16 +92,12 @@ struct ttm_place {
  *
  * @num_placement:     number of preferred placements
  * @placement:         preferred placements
- * @num_busy_placement:        number of preferred placements when need to evict buffer
- * @busy_placement:    preferred placements when need to evict buffer
  *
  * Structure indicating the placement you request for an object.
  */
 struct ttm_placement {
        unsigned                num_placement;
        const struct ttm_place  *placement;
-       unsigned                num_busy_placement;
-       const struct ttm_place  *busy_placement;
 };
 
 #endif
index 78a226eba953cc7d58b0e4e33015d33ede086150..1afa13f0c22b2133ec6cb3db01dadbcf3fef9226 100644 (file)
@@ -365,12 +365,8 @@ bool ttm_resource_intersects(struct ttm_device *bdev,
                             struct ttm_resource *res,
                             const struct ttm_place *place,
                             size_t size);
-bool ttm_resource_compatible(struct ttm_device *bdev,
-                            struct ttm_resource *res,
-                            const struct ttm_place *place,
-                            size_t size);
-bool ttm_resource_compat(struct ttm_resource *res,
-                        struct ttm_placement *placement);
+bool ttm_resource_compatible(struct ttm_resource *res,
+                            struct ttm_placement *placement);
 void ttm_resource_set_bo(struct ttm_resource *res,
                         struct ttm_buffer_object *bo);
 
index a4eff85b1f4498d33cdb78ddbc11c036f160cdbb..2b9d856ff388d886692fbefd6f5fc2bad4557e8f 100644 (file)
@@ -79,6 +79,12 @@ struct ttm_tt {
         *   page_flags = TTM_TT_FLAG_EXTERNAL |
         *                TTM_TT_FLAG_EXTERNAL_MAPPABLE;
         *
+        * TTM_TT_FLAG_DECRYPTED: The mapped ttm pages should be marked as
+        * not encrypted. The framework will try to match what the dma layer
+        * is doing, but note that it is a little fragile because ttm page
+        * fault handling abuses the DMA api a bit and dma_map_attrs can't be
+        * used to assure pgprot always matches.
+        *
         * TTM_TT_FLAG_PRIV_POPULATED: TTM internal only. DO NOT USE. This is
         * set by TTM after ttm_tt_populate() has successfully returned, and is
         * then unset when TTM calls ttm_tt_unpopulate().
@@ -87,8 +93,9 @@ struct ttm_tt {
 #define TTM_TT_FLAG_ZERO_ALLOC         BIT(1)
 #define TTM_TT_FLAG_EXTERNAL           BIT(2)
 #define TTM_TT_FLAG_EXTERNAL_MAPPABLE  BIT(3)
+#define TTM_TT_FLAG_DECRYPTED          BIT(4)
 
-#define TTM_TT_FLAG_PRIV_POPULATED     BIT(4)
+#define TTM_TT_FLAG_PRIV_POPULATED     BIT(5)
        uint32_t page_flags;
        /** @num_pages: Number of pages in the page array. */
        uint32_t num_pages;
index 05dc9624897df9fe01b06ab18bea1ea23b53ecda..2ce2f5c2fca9aec8b271c68d9cb1d4bb0dc2d53d 100644 (file)
@@ -840,14 +840,7 @@ extern int fb_find_mode(struct fb_var_screeninfo *var,
                        const struct fb_videomode *default_mode,
                        unsigned int default_bpp);
 
-#if defined(CONFIG_VIDEO_NOMODESET)
 bool fb_modesetting_disabled(const char *drvname);
-#else
-static inline bool fb_modesetting_disabled(const char *drvname)
-{
-       return false;
-}
-#endif
 
 /*
  * Convenience logging macros
index 9b162ac1e08e04ee37f49911ba72ef8c3e13fc0b..5e1a9eafd10f5d4f831abbb6f4c0fff661909584 100644 (file)
@@ -12,7 +12,6 @@
 
 #include <linux/of_graph.h>
 #include <linux/hdmi.h>
-#include <drm/drm_edid.h>
 #include <sound/asoundef.h>
 #include <sound/soc.h>
 #include <uapi/sound/asound.h>
index 0bade1592f34f21690eab41de48595d7aaa24fe4..c95ef8a4d94a48ddcae055e536c9a4431f83dcae 100644 (file)
@@ -238,34 +238,32 @@ struct drm_nouveau_vm_init {
 struct drm_nouveau_vm_bind_op {
        /**
         * @op: the operation type
+        *
+        * Supported values:
+        *
+        * %DRM_NOUVEAU_VM_BIND_OP_MAP - Map a GEM object to the GPU's VA
+        * space. Optionally, the &DRM_NOUVEAU_VM_BIND_SPARSE flag can be
+        * passed to instruct the kernel to create sparse mappings for the
+        * given range.
+        *
+        * %DRM_NOUVEAU_VM_BIND_OP_UNMAP - Unmap an existing mapping in the
+        * GPU's VA space. If the region the mapping is located in is a
+        * sparse region, new sparse mappings are created where the unmapped
+        * (memory backed) mapping was mapped previously. To remove a sparse
+        * region the &DRM_NOUVEAU_VM_BIND_SPARSE must be set.
         */
        __u32 op;
-/**
- * @DRM_NOUVEAU_VM_BIND_OP_MAP:
- *
- * Map a GEM object to the GPU's VA space. Optionally, the
- * &DRM_NOUVEAU_VM_BIND_SPARSE flag can be passed to instruct the kernel to
- * create sparse mappings for the given range.
- */
 #define DRM_NOUVEAU_VM_BIND_OP_MAP 0x0
-/**
- * @DRM_NOUVEAU_VM_BIND_OP_UNMAP:
- *
- * Unmap an existing mapping in the GPU's VA space. If the region the mapping
- * is located in is a sparse region, new sparse mappings are created where the
- * unmapped (memory backed) mapping was mapped previously. To remove a sparse
- * region the &DRM_NOUVEAU_VM_BIND_SPARSE must be set.
- */
 #define DRM_NOUVEAU_VM_BIND_OP_UNMAP 0x1
        /**
         * @flags: the flags for a &drm_nouveau_vm_bind_op
+        *
+        * Supported values:
+        *
+        * %DRM_NOUVEAU_VM_BIND_SPARSE - Indicates that an allocated VA
+        * space region should be sparse.
         */
        __u32 flags;
-/**
- * @DRM_NOUVEAU_VM_BIND_SPARSE:
- *
- * Indicates that an allocated VA space region should be sparse.
- */
 #define DRM_NOUVEAU_VM_BIND_SPARSE (1 << 8)
        /**
         * @handle: the handle of the DRM GEM object to map
@@ -301,17 +299,17 @@ struct drm_nouveau_vm_bind {
        __u32 op_count;
        /**
         * @flags: the flags for a &drm_nouveau_vm_bind ioctl
+        *
+        * Supported values:
+        *
+        * %DRM_NOUVEAU_VM_BIND_RUN_ASYNC - Indicates that the given VM_BIND
+        * operation should be executed asynchronously by the kernel.
+        *
+        * If this flag is not supplied the kernel executes the associated
+        * operations synchronously and doesn't accept any &drm_nouveau_sync
+        * objects.
         */
        __u32 flags;
-/**
- * @DRM_NOUVEAU_VM_BIND_RUN_ASYNC:
- *
- * Indicates that the given VM_BIND operation should be executed asynchronously
- * by the kernel.
- *
- * If this flag is not supplied the kernel executes the associated operations
- * synchronously and doesn't accept any &drm_nouveau_sync objects.
- */
 #define DRM_NOUVEAU_VM_BIND_RUN_ASYNC 0x1
        /**
         * @wait_count: the number of wait &drm_nouveau_syncs
index 9dab32316aee40f0a8d732f9d77972292b6a088b..d3ca876a08e921bab4723281986b837e6f381369 100644 (file)
@@ -242,18 +242,7 @@ struct qaic_attach_slice_entry {
  * @dbc_id: In. Associate the sliced BO with this DBC.
  * @handle: In. GEM handle of the BO to slice.
  * @dir: In. Direction of data flow. 1 = DMA_TO_DEVICE, 2 = DMA_FROM_DEVICE
- * @size: In. Total length of BO being used. This should not exceed base
- *       size of BO (struct drm_gem_object.base)
- *       For BOs being allocated using DRM_IOCTL_QAIC_CREATE_BO, size of
- *       BO requested is PAGE_SIZE aligned then allocated hence allocated
- *       BO size maybe bigger. This size should not exceed the new
- *       PAGE_SIZE aligned BO size.
- * @dev_addr: In. Device address this slice pushes to or pulls from.
- * @db_addr: In. Address of the doorbell to ring.
- * @db_data: In. Data to write to the doorbell.
- * @db_len: In. Size of the doorbell data in bits - 32, 16, or 8.  0 is for
- *         inactive doorbells.
- * @offset: In. Start of this slice as an offset from the start of the BO.
+ * @size: Deprecated. This value is ignored and size of @handle is used instead.
  */
 struct qaic_attach_slice_hdr {
        __u32 count;
index f556fde07b76b89b6bb4a1660dedd31b889dc407..0e21f39981086bbcbd93ba51c91e8dc1faf371a0 100644 (file)
@@ -309,6 +309,8 @@ struct virtio_gpu_cmd_submit {
 
 #define VIRTIO_GPU_CAPSET_VIRGL 1
 #define VIRTIO_GPU_CAPSET_VIRGL2 2
+/* 3 is reserved for gfxstream */
+#define VIRTIO_GPU_CAPSET_VENUS 4
 
 /* VIRTIO_GPU_CMD_GET_CAPSET_INFO */
 struct virtio_gpu_get_capset_info {
index 26b80cdaef7970f0acae91dc728ce67fadfa480d..76649465bb084fa15ecde4e3ab918c9a9ca347f0 100644 (file)
@@ -3,18 +3,14 @@
 #ifndef VIDEO_CMDLINE_H
 #define VIDEO_CMDLINE_H
 
+#include <linux/kconfig.h>
 #include <linux/types.h>
 
-#if defined(CONFIG_VIDEO_CMDLINE)
 const char *video_get_options(const char *name);
 
+#if IS_ENABLED(CONFIG_FB_CORE)
 /* exported for compatibility with fbdev; don't use in new code */
 bool __video_get_options(const char *name, const char **option, bool is_of);
-#else
-static inline const char *video_get_options(const char *name)
-{
-       return NULL;
-}
 #endif
 
 #endif