History

Merge tag 'drm-misc-next-2021-09-16' of git://anongit.freedesktop.org/drm/drm-misc into drm-next

drm-misc-next for $kernel-version: UAPI Changes: Cross-subsystem Changes: - dma-buf: Avoid a warning with some allocations, Remove DMA_FENCE_TRACE macros Core Changes: - bridge: New helper to git rid of panels in drivers - fence: Improve dma_fence_add_callback documentation, Improve dma_fence_ops->wait documentation - ioctl: Unexport drm_ioctl_permit - lease: Documentation improvements - fourcc: Add new macro to determine the modifier vendor - quirks: Add the Steam Deck, Chuwi HiBook, Chuwi Hi10 Pro, Samsung Galaxy Book 10.6, KD Kurio Smart C15200 2-in-1, Lenovo Ideapad D330 - resv: Improve the documentation - shmem-helpers: Allocate WC pages on x86, Switch to vmf_insert_pfn - sched: Fix for a timer being canceled too soon, Avoid null pointer derefence if the fence is null in drm_sched_fence_free, Convert drivers to rely on its dependency tracking - ttm: Switch to kerneldoc, new helper to clear all DMA mappings, pool shrinker optitimization, Remove ttm_tt_destroy_common, Fix for unbinding on multiple drivers Driver Changes: - bochs: New PCI IDs - msm: Fence ordering impromevemnts - stm: Add layer alpha support, zpos - v3d: Fix for a Vulkan CTS failure - vc4: Conversion to the new bridge helpers - vgem: Use shmem helpers - virtio: Support mapping exported vram - zte: Remove obsolete driver - bridge: Probe improvements for it66121, enable DSI EOTP for anx7625, errors propagation improvements for anx7625 - panels: 60fps mode for otm8009a, New driver for Samsung S6D27A1 Signed-off-by: Dave Airlie <airlied@redhat.com> # gpg: Signature made Thu 16 Sep 2021 17:30:50 AEST # gpg: using EDDSA key 5C1337A45ECA9AEB89060E9EE3EF0D6F671851C5 # gpg: Can't check signature: No public key From: Maxime Ripard <maxime@cerno.tech> Link: https://patchwork.freedesktop.org/patch/msgid/20210916073132.ptbbmjetm7v3ufq3@gilmour

Dave Airlie committed 5 years ago

Commit 0dfc7082 parents e4e737b e4f8681145 files · +2080 −5441Browse files

Unified · Split

145 files
  1. Documentation/devicetree/bindings/display/panel/ilitek,ili9341.yaml +1 −1
  2. Documentation/devicetree/bindings/display/panel/samsung,s6d27a1.yaml +98 −0
  3. Documentation/driver-api/dma-buf.rst +0 −6
  4. Documentation/gpu/drm-mm.rst +42 −42
  5. MAINTAINERS +6 −0
  6. drivers/dma-buf/Makefile +1 −1
  7. drivers/dma-buf/dma-buf.c +1 −0
  8. drivers/dma-buf/dma-fence.c +5 −8
  9. drivers/dma-buf/dma-resv.c +18 −6
  10. drivers/dma-buf/heaps/system_heap.c +3 −2
  11. drivers/dma-buf/seqno-fence.c +0 −71
  12. drivers/gpu/drm/Kconfig +4 −5
  13. drivers/gpu/drm/Makefile +0 −1
  14. drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +3 −1
  15. drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c +1 −9
  16. drivers/gpu/drm/amd/amdgpu/amdgpu_job.c +3 −1
  17. drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +2 −2
  18. drivers/gpu/drm/arm/malidp_planes.c +1 −1
  19. drivers/gpu/drm/bridge/adv7511/adv7511_cec.c +1 −14
  20. drivers/gpu/drm/bridge/analogix/anx7625.c +18 −9
  21. drivers/gpu/drm/bridge/cdns-dsi.c +1 −3
  22. drivers/gpu/drm/bridge/ite-it66121.c +4 −1
  23. drivers/gpu/drm/bridge/parade-ps8640.c +10 −8
  24. drivers/gpu/drm/drm_bridge.c +37 −4
  25. drivers/gpu/drm/drm_connector.c +79 −0
  26. drivers/gpu/drm/drm_crtc_internal.h +2 −0
  27. drivers/gpu/drm/drm_gem_shmem_helper.c +21 −2
  28. drivers/gpu/drm/drm_gem_vram_helper.c +0 −1
  29. drivers/gpu/drm/drm_ioctl.c +4 −17
  30. drivers/gpu/drm/drm_kms_helper_common.c +0 −11
  31. drivers/gpu/drm/drm_of.c +3 −0
  32. drivers/gpu/drm/drm_panel_orientation_quirks.c +47 −2
  33. drivers/gpu/drm/drm_sysfs.c +74 −13
  34. drivers/gpu/drm/etnaviv/etnaviv_sched.c +3 −1
  35. drivers/gpu/drm/gud/Kconfig +1 −1
  36. drivers/gpu/drm/i915/gem/i915_gem_ttm.c +0 −1
  37. drivers/gpu/drm/lima/lima_gem.c +5 −4
  38. drivers/gpu/drm/lima/lima_sched.c +4 −24
  39. drivers/gpu/drm/lima/lima_sched.h +1 −5
  40. drivers/gpu/drm/mcde/mcde_drv.c +1 −3
  41. drivers/gpu/drm/mcde/mcde_dsi.c +1 −3
  42. drivers/gpu/drm/meson/meson_drv.c +1 −2
  43. drivers/gpu/drm/meson/meson_dw_hdmi.c +1 −3
  44. drivers/gpu/drm/msm/msm_gem.h +0 −5
  45. drivers/gpu/drm/msm/msm_gem_submit.c +14 −21
  46. drivers/gpu/drm/msm/msm_ringbuffer.c +0 −12
  47. drivers/gpu/drm/nouveau/nouveau_bo.c +2 −2
  48. drivers/gpu/drm/nouveau/nouveau_sgdma.c +0 −2
  49. drivers/gpu/drm/omapdrm/Kconfig +0 −1
  50. drivers/gpu/drm/panel/Kconfig +11 −0
  51. drivers/gpu/drm/panel/Makefile +1 −0
  52. drivers/gpu/drm/panel/panel-orisetech-otm8009a.c +56 −29
  53. drivers/gpu/drm/panel/panel-samsung-s6d27a1.c +320 −0
  54. drivers/gpu/drm/panel/panel-simple.c +13 −13
  55. drivers/gpu/drm/panfrost/panfrost_device.c +1 −3
  56. drivers/gpu/drm/panfrost/panfrost_drv.c +19 −10
  57. drivers/gpu/drm/panfrost/panfrost_job.c +11 −37
  58. drivers/gpu/drm/panfrost/panfrost_job.h +1 −4
  59. drivers/gpu/drm/panfrost/panfrost_mmu.c +6 −6
  60. drivers/gpu/drm/panfrost/panfrost_perfcnt.c +2 −2
  61. drivers/gpu/drm/qxl/qxl_release.c +2 −2
  62. drivers/gpu/drm/qxl/qxl_ttm.c +0 −1
  63. drivers/gpu/drm/r128/ati_pcigart.c +6 −5
  64. drivers/gpu/drm/radeon/radeon_fence.c +4 −20
  65. drivers/gpu/drm/radeon/radeon_ttm.c +2 −5
  66. drivers/gpu/drm/rockchip/Kconfig +0 −1
  67. drivers/gpu/drm/scheduler/sched_entity.c +69 −71
  68. drivers/gpu/drm/scheduler/sched_fence.c +31 −31
  69. drivers/gpu/drm/scheduler/sched_main.c +171 −28
  70. drivers/gpu/drm/stm/ltdc.c +6 −1
  71. drivers/gpu/drm/sun4i/sun4i_backend.c +1 −3
  72. drivers/gpu/drm/sun4i/sun4i_frontend.c +1 −3
  73. drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c +1 −3
  74. drivers/gpu/drm/sun4i/sun4i_tcon.c +1 −3
  75. drivers/gpu/drm/sun4i/sun4i_tv.c +1 −3
  76. drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c +1 −3
  77. drivers/gpu/drm/sun4i/sun8i_csc.h +2 −2
  78. drivers/gpu/drm/sun4i/sun8i_mixer.c +1 −3
  79. drivers/gpu/drm/sun4i/sun8i_tcon_top.c +1 −3
  80. drivers/gpu/drm/tegra/fb.c +1 −1
  81. drivers/gpu/drm/tegra/plane.c +1 −1
  82. drivers/gpu/drm/tiny/Kconfig +2 −2
  83. drivers/gpu/drm/tiny/bochs.c +8 −0
  84. drivers/gpu/drm/ttm/ttm_bo.c +16 −51
  85. drivers/gpu/drm/ttm/ttm_device.c +48 −0
  86. drivers/gpu/drm/ttm/ttm_module.c +12 −0
  87. drivers/gpu/drm/ttm/ttm_pool.c +22 −18
  88. drivers/gpu/drm/ttm/ttm_range_manager.c +4 −4
  89. drivers/gpu/drm/ttm/ttm_resource.c +49 −0
  90. drivers/gpu/drm/ttm/ttm_tt.c +6 −11
  91. drivers/gpu/drm/udl/Kconfig +1 −0
  92. drivers/gpu/drm/v3d/Kconfig +1 −1
  93. drivers/gpu/drm/v3d/v3d_drv.h +1 −5
  94. drivers/gpu/drm/v3d/v3d_gem.c +49 −69
  95. drivers/gpu/drm/v3d/v3d_sched.c +8 −36
  96. drivers/gpu/drm/vc4/vc4_dpi.c +4 −11
  97. drivers/gpu/drm/vc4/vc4_drv.c +2 −4
  98. drivers/gpu/drm/vc4/vc4_dsi.c +4 −24
  99. drivers/gpu/drm/vgem/vgem_drv.c +13 −329
  100. drivers/gpu/drm/virtio/virtgpu_drv.h +8 −0
  101. drivers/gpu/drm/virtio/virtgpu_prime.c +30 −2
  102. drivers/gpu/drm/virtio/virtgpu_vram.c +61 −0
  103. drivers/gpu/drm/vmwgfx/vmwgfx_bo.c +6 −9
  104. drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c +3 −7
  105. drivers/gpu/drm/zte/Kconfig +0 −10
  106. drivers/gpu/drm/zte/Makefile +0 −10
  107. drivers/gpu/drm/zte/zx_common_regs.h +0 −28
  108. drivers/gpu/drm/zte/zx_drm_drv.c +0 −184
  109. drivers/gpu/drm/zte/zx_drm_drv.h +0 −34
  110. drivers/gpu/drm/zte/zx_hdmi.c +0 −760
  111. drivers/gpu/drm/zte/zx_hdmi_regs.h +0 −66
  112. drivers/gpu/drm/zte/zx_plane.c +0 −537
  113. drivers/gpu/drm/zte/zx_plane.h +0 −26
  114. drivers/gpu/drm/zte/zx_plane_regs.h +0 −120
  115. drivers/gpu/drm/zte/zx_tvenc.c +0 −400
  116. drivers/gpu/drm/zte/zx_tvenc_regs.h +0 −27
  117. drivers/gpu/drm/zte/zx_vga.c +0 −527
  118. drivers/gpu/drm/zte/zx_vga_regs.h +0 −33
  119. drivers/gpu/drm/zte/zx_vou.c +0 −921
  120. drivers/gpu/drm/zte/zx_vou.h +0 −64
  121. drivers/gpu/drm/zte/zx_vou_regs.h +0 −212
  122. drivers/usb/typec/altmodes/Kconfig +1 −0
  123. drivers/usb/typec/altmodes/displayport.c +36 −22
  124. include/drm/drm_bridge.h +2 −0
  125. include/drm/drm_connector.h +25 −0
  126. include/drm/drm_ioctl.h +0 −1
  127. include/drm/drm_mode_config.h +6 −7
  128. include/drm/drm_plane.h +1 −1
  129. include/drm/gpu_scheduler.h +155 −33
  130. include/drm/ttm/ttm_bo_api.h +0 −12
  131. include/drm/ttm/ttm_caching.h +17 −0
  132. include/drm/ttm/ttm_device.h +44 −33
  133. include/drm/ttm/ttm_placement.h +1 −0
  134. include/drm/ttm/ttm_pool.h +3 −2
  135. include/drm/ttm/ttm_range_manager.h +16 −2
  136. include/drm/ttm/ttm_resource.h +5 −4
  137. include/drm/ttm/ttm_tt.h +8 −10
  138. include/linux/dma-buf.h +7 −0
  139. include/linux/dma-fence.h +3 −29
  140. include/linux/dma-resv.h +99 −5
  141. include/linux/seqno-fence.h +0 −109
  142. include/linux/shrinker.h +1 −0
  143. include/uapi/drm/drm_fourcc.h +6 −0
  144. include/uapi/drm/drm_mode.h +3 −0
  145. mm/vmscan.c +15 −0
Documentation/devicetree/bindings/display/panel/ilitek,ili9341.yaml+1−1
@@ -22,7 +22,7 @@ properties: · 21 unmodified lines
22 items:22 items:
23 - enum:23 - enum:
24 # ili9341 240*320 Color on stm32f429-disco board24 # ili9341 240*320 Color on stm32f429-disco board
25 - st,sf-tc240t-9370-t25 - st,sf-tc240t-9370-t
26 - const: ilitek,ili934126 - const: ilitek,ili9341
27 27
28 reg: true28 reg: true
Documentation/devicetree/bindings/display/panel/samsung,s6d27a1.yaml+98−0
@@ -0,0 +1,98 @@
1# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
2%YAML 1.2
3---
4$id: http://devicetree.org/schemas/display/panel/samsung,s6d27a1.yaml#
5$schema: http://devicetree.org/meta-schemas/core.yaml#
6
7title: Samsung S6D27A1 display panel
8
9description: The S6D27A1 is a 480x800 DPI display panel from Samsung Mobile
10 Displays (SMD). The panel must obey the rules for a SPI slave device
11 as specified in spi/spi-controller.yaml
12
13maintainers:
14 - Markuss Broks <markuss.broks@gmail.com>
15
16allOf:
17 - $ref: panel-common.yaml#
18
19properties:
20 compatible:
21 const: samsung,s6d27a1
22
23 reg: true
24
25 interrupts:
26 description: provides an optional ESD (electrostatic discharge)
27 interrupt that signals abnormalities in the display hardware.
28 This can also be raised for other reasons like erroneous
29 configuration.
30 maxItems: 1
31
32 reset-gpios: true
33
34 vci-supply:
35 description: regulator that supplies the VCI analog voltage
36 usually around 3.0 V
37
38 vccio-supply:
39 description: regulator that supplies the VCCIO voltage usually
40 around 1.8 V
41
42 backlight: true
43
44 spi-cpha: true
45
46 spi-cpol: true
47
48 spi-max-frequency:
49 maximum: 1200000
50
51 port: true
52
53required:
54 - compatible
55 - reg
56 - vci-supply
57 - vccio-supply
58 - spi-cpha
59 - spi-cpol
60 - port
61
62unevaluatedProperties: false
63
64examples:
65 - |
66 #include <dt-bindings/gpio/gpio.h>
67 #include <dt-bindings/interrupt-controller/irq.h>
68
69 spi {
70 compatible = "spi-gpio";
71 sck-gpios = <&gpio 0 GPIO_ACTIVE_HIGH>;
72 miso-gpios = <&gpio 1 GPIO_ACTIVE_HIGH>;
73 mosi-gpios = <&gpio 2 GPIO_ACTIVE_HIGH>;
74 cs-gpios = <&gpio 3 GPIO_ACTIVE_HIGH>;
75 num-chipselects = <1>;
76 #address-cells = <1>;
77 #size-cells = <0>;
78 panel@0 {
79 compatible = "samsung,s6d27a1";
80 spi-max-frequency = <1200000>;
81 spi-cpha;
82 spi-cpol;
83 reg = <0>;
84 vci-supply = <&lcd_3v0_reg>;
85 vccio-supply = <&lcd_1v8_reg>;
86 reset-gpios = <&gpio 4 GPIO_ACTIVE_LOW>;
87 interrupt-parent = <&gpio>;
88 interrupts = <5 IRQ_TYPE_EDGE_RISING>;
89
90 port {
91 panel_in: endpoint {
92 remote-endpoint = <&display_out>;
93 };
94 };
95 };
96 };
97
98...
Documentation/driver-api/dma-buf.rst+0−6
@@ -176,12 +176,6 @@ DMA Fences Functions Reference · 175 unmodified lines
176.. kernel-doc:: include/linux/dma-fence.h176.. kernel-doc:: include/linux/dma-fence.h
177 :internal:177 :internal:
178 178
179Seqno Hardware Fences
180~~~~~~~~~~~~~~~~~~~~~
181
182.. kernel-doc:: include/linux/seqno-fence.h
183 :internal:
184
185DMA Fence Array179DMA Fence Array
186~~~~~~~~~~~~~~~180~~~~~~~~~~~~~~~
187 181
Documentation/gpu/drm-mm.rst+42−42
@@ -28,56 +28,53 @@ UMA devices. · 27 unmodified lines
28The Translation Table Manager (TTM)28The Translation Table Manager (TTM)
29===================================29===================================
30 30
31TTM design background and information belongs here.31.. kernel-doc:: drivers/gpu/drm/ttm/ttm_module.c
32 :doc: TTM
32 33
33TTM initialization34.. kernel-doc:: include/drm/ttm/ttm_caching.h
34------------------35 :internal:
35 36
36 **Warning**37TTM device object reference
37 This section is outdated.38---------------------------
38 39
39Drivers wishing to support TTM must pass a filled :c:type:`ttm_bo_driver40.. kernel-doc:: include/drm/ttm/ttm_device.h
40<ttm_bo_driver>` structure to ttm_device_init, together with an41 :internal:
41initialized global reference to the memory manager. The ttm_bo_driver
42structure contains several fields with function pointers for
43initializing the TTM, allocating and freeing memory, waiting for command
44completion and fence synchronization, and memory migration.
45 42
46The :c:type:`struct drm_global_reference <drm_global_reference>` is made43.. kernel-doc:: drivers/gpu/drm/ttm/ttm_device.c
47up of several fields:44 :export:
48 45
49.. code-block:: c46TTM resource placement reference
47--------------------------------
50 48
51 struct drm_global_reference {49.. kernel-doc:: include/drm/ttm/ttm_placement.h
52 enum ttm_global_types global_type;50 :internal:
53 size_t size;51
54 void *object;52TTM resource object reference
55 int (*init) (struct drm_global_reference *);53-----------------------------
56 void (*release) (struct drm_global_reference *);54
57 };55.. kernel-doc:: include/drm/ttm/ttm_resource.h
58 56 :internal:
59
60There should be one global reference structure for your memory manager
61as a whole, and there will be others for each object created by the
62memory manager at runtime. Your global TTM should have a type of
63TTM_GLOBAL_TTM_MEM. The size field for the global object should be
64sizeof(struct ttm_mem_global), and the init and release hooks should
65point at your driver-specific init and release routines, which probably
66eventually call ttm_mem_global_init and ttm_mem_global_release,
67respectively.
68 57
69Once your global TTM accounting structure is set up and initialized by58.. kernel-doc:: drivers/gpu/drm/ttm/ttm_resource.c
70calling ttm_global_item_ref() on it, you need to create a buffer59 :export:
71object TTM to provide a pool for buffer object allocation by clients and60
72the kernel itself. The type of this object should be61TTM TT object reference
73TTM_GLOBAL_TTM_BO, and its size should be sizeof(struct62-----------------------
74ttm_bo_global). Again, driver-specific init and release functions may63
75be provided, likely eventually calling ttm_bo_global_ref_init() and64.. kernel-doc:: include/drm/ttm/ttm_tt.h
76ttm_bo_global_ref_release(), respectively. Also, like the previous65 :internal:
77object, ttm_global_item_ref() is used to create an initial reference66
78count for the TTM, which will call your initialization function.67.. kernel-doc:: drivers/gpu/drm/ttm/ttm_tt.c
68 :export:
79 69
80See the radeon_ttm.c file for an example of usage.70TTM page pool reference
71-----------------------
72
73.. kernel-doc:: include/drm/ttm/ttm_pool.h
74 :internal:
75
76.. kernel-doc:: drivers/gpu/drm/ttm/ttm_pool.c
77 :export:
81 78
82The Graphics Execution Manager (GEM)79The Graphics Execution Manager (GEM)
83====================================80====================================
@@ -504,3 +501,6 @@ Scheduler Function References · 420 unmodified lines
504 501
505.. kernel-doc:: drivers/gpu/drm/scheduler/sched_main.c502.. kernel-doc:: drivers/gpu/drm/scheduler/sched_main.c
506 :export:503 :export:
504
505.. kernel-doc:: drivers/gpu/drm/scheduler/sched_entity.c
506 :export:
MAINTAINERS+6−0
@@ -6018,6 +6018,12 @@ T: git git://anongit.freedesktop.org/drm/drm-misc · 6017 unmodified lines
6018F: Documentation/devicetree/bindings/display/panel/samsung,lms397kf04.yaml6018F: Documentation/devicetree/bindings/display/panel/samsung,lms397kf04.yaml
6019F: drivers/gpu/drm/panel/panel-samsung-db7430.c6019F: drivers/gpu/drm/panel/panel-samsung-db7430.c
6020 6020
6021DRM DRIVER FOR SAMSUNG S6D27A1 PANELS
6022M: Markuss Broks <markuss.broks@gmail.com>
6023S: Maintained
6024F: Documentation/devicetree/bindings/display/panel/samsung,s6d27a1.yaml
6025F: driver/gpu/drm/panel/panel-samsung-s6d27a1.c
6026
6021DRM DRIVER FOR SITRONIX ST7703 PANELS6027DRM DRIVER FOR SITRONIX ST7703 PANELS
6022M: Guido Günther <agx@sigxcpu.org>6028M: Guido Günther <agx@sigxcpu.org>
6023R: Purism Kernel Team <kernel@puri.sm>6029R: Purism Kernel Team <kernel@puri.sm>
drivers/dma-buf/Makefile+1−1
@@ -1,6 +1,6 @@
1# SPDX-License-Identifier: GPL-2.0-only1# SPDX-License-Identifier: GPL-2.0-only
2obj-y := dma-buf.o dma-fence.o dma-fence-array.o dma-fence-chain.o \2obj-y := dma-buf.o dma-fence.o dma-fence-array.o dma-fence-chain.o \
3 dma-resv.o seqno-fence.o3 dma-resv.o
4obj-$(CONFIG_DMABUF_HEAPS) += dma-heap.o4obj-$(CONFIG_DMABUF_HEAPS) += dma-heap.o
5obj-$(CONFIG_DMABUF_HEAPS) += heaps/5obj-$(CONFIG_DMABUF_HEAPS) += heaps/
6obj-$(CONFIG_SYNC_FILE) += sync_file.o6obj-$(CONFIG_SYNC_FILE) += sync_file.o
drivers/dma-buf/dma-buf.c+1−0
@@ -82,6 +82,7 @@ static void dma_buf_release(struct dentry *dentry) · 81 unmodified lines
82 if (dmabuf->resv == (struct dma_resv *)&dmabuf[1])82 if (dmabuf->resv == (struct dma_resv *)&dmabuf[1])
83 dma_resv_fini(dmabuf->resv);83 dma_resv_fini(dmabuf->resv);
84 84
85 WARN_ON(!list_empty(&dmabuf->attachments));
85 module_put(dmabuf->owner);86 module_put(dmabuf->owner);
86 kfree(dmabuf->name);87 kfree(dmabuf->name);
87 kfree(dmabuf);88 kfree(dmabuf);
drivers/dma-buf/dma-fence.c+5−8
@@ -616,20 +616,17 @@ EXPORT_SYMBOL(dma_fence_enable_sw_signaling); · 615 unmodified lines
616 * @cb: the callback to register616 * @cb: the callback to register
617 * @func: the function to call617 * @func: the function to call
618 *618 *
619 * Add a software callback to the fence. The caller should keep a reference to
620 * the fence.
621 *
619 * @cb will be initialized by dma_fence_add_callback(), no initialization622 * @cb will be initialized by dma_fence_add_callback(), no initialization
620 * by the caller is required. Any number of callbacks can be registered623 * by the caller is required. Any number of callbacks can be registered
621 * to a fence, but a callback can only be registered to one fence at a time.624 * to a fence, but a callback can only be registered to one fence at a time.
622 *625 *
623 * Note that the callback can be called from an atomic context. If626 * If fence is already signaled, this function will return -ENOENT (and
624 * fence is already signaled, this function will return -ENOENT (and
625 * *not* call the callback).627 * *not* call the callback).
626 *628 *
627 * Add a software callback to the fence. Same restrictions apply to629 * Note that the callback can be called from an atomic context or irq context.
628 * refcount as it does to dma_fence_wait(), however the caller doesn't need to
629 * keep a refcount to fence afterward dma_fence_add_callback() has returned:
630 * when software access is enabled, the creator of the fence is required to keep
631 * the fence alive until after it signals with dma_fence_signal(). The callback
632 * itself can be called from irq context.
633 *630 *
634 * Returns 0 in case of success, -ENOENT if the fence is already signaled631 * Returns 0 in case of success, -ENOENT if the fence is already signaled
635 * and -EINVAL in case of error.632 * and -EINVAL in case of error.
drivers/dma-buf/dma-resv.c+18−6
@@ -48,6 +48,8 @@ · 47 unmodified lines
48 * write operations) or N shared fences (read operations). The RCU48 * write operations) or N shared fences (read operations). The RCU
49 * mechanism is used to protect read access to fences from locked49 * mechanism is used to protect read access to fences from locked
50 * write-side updates.50 * write-side updates.
51 *
52 * See struct dma_resv for more details.
51 */53 */
52 54
53DEFINE_WD_CLASS(reservation_ww_class);55DEFINE_WD_CLASS(reservation_ww_class);
@@ -137,7 +139,11 @@ EXPORT_SYMBOL(dma_resv_fini); · 83 unmodified lines
137 * @num_fences: number of fences we want to add139 * @num_fences: number of fences we want to add
138 *140 *
139 * Should be called before dma_resv_add_shared_fence(). Must141 * Should be called before dma_resv_add_shared_fence(). Must
140 * be called with obj->lock held.142 * be called with @obj locked through dma_resv_lock().
143 *
144 * Note that the preallocated slots need to be re-reserved if @obj is unlocked
145 * at any time before calling dma_resv_add_shared_fence(). This is validated
146 * when CONFIG_DEBUG_MUTEXES is enabled.
141 *147 *
142 * RETURNS148 * RETURNS
143 * Zero for success, or -errno149 * Zero for success, or -errno
@@ -234,8 +240,10 @@ EXPORT_SYMBOL(dma_resv_reset_shared_max); · 90 unmodified lines
234 * @obj: the reservation object240 * @obj: the reservation object
235 * @fence: the shared fence to add241 * @fence: the shared fence to add
236 *242 *
237 * Add a fence to a shared slot, obj->lock must be held, and243 * Add a fence to a shared slot, @obj must be locked with dma_resv_lock(), and
238 * dma_resv_reserve_shared() has been called.244 * dma_resv_reserve_shared() has been called.
245 *
246 * See also &dma_resv.fence for a discussion of the semantics.
239 */247 */
240void dma_resv_add_shared_fence(struct dma_resv *obj, struct dma_fence *fence)248void dma_resv_add_shared_fence(struct dma_resv *obj, struct dma_fence *fence)
241{249{
@@ -278,9 +286,11 @@ EXPORT_SYMBOL(dma_resv_add_shared_fence); · 36 unmodified lines
278/**286/**
279 * dma_resv_add_excl_fence - Add an exclusive fence.287 * dma_resv_add_excl_fence - Add an exclusive fence.
280 * @obj: the reservation object288 * @obj: the reservation object
281 * @fence: the shared fence to add289 * @fence: the exclusive fence to add
282 *290 *
283 * Add a fence to the exclusive slot. The obj->lock must be held.291 * Add a fence to the exclusive slot. @obj must be locked with dma_resv_lock().
292 * Note that this function replaces all fences attached to @obj, see also
293 * &dma_resv.fence_excl for a discussion of the semantics.
284 */294 */
285void dma_resv_add_excl_fence(struct dma_resv *obj, struct dma_fence *fence)295void dma_resv_add_excl_fence(struct dma_resv *obj, struct dma_fence *fence)
286{296{
@@ -609,9 +619,11 @@ static inline int dma_resv_test_signaled_single(struct dma_fence *passed_fence) · 322 unmodified lines
609 * fence619 * fence
610 *620 *
611 * Callers are not required to hold specific locks, but maybe hold621 * Callers are not required to hold specific locks, but maybe hold
612 * dma_resv_lock() already622 * dma_resv_lock() already.
623 *
613 * RETURNS624 * RETURNS
614 * true if all fences signaled, else false625 *
626 * True if all fences signaled, else false.
615 */627 */
616bool dma_resv_test_signaled(struct dma_resv *obj, bool test_all)628bool dma_resv_test_signaled(struct dma_resv *obj, bool test_all)
617{629{
drivers/dma-buf/heaps/system_heap.c+3−2
@@ -40,11 +40,12 @@ struct dma_heap_attachment { · 39 unmodified lines
40 bool mapped;40 bool mapped;
41};41};
42 42
43#define LOW_ORDER_GFP (GFP_HIGHUSER | __GFP_ZERO | __GFP_COMP)
44#define MID_ORDER_GFP (LOW_ORDER_GFP | __GFP_NOWARN)
43#define HIGH_ORDER_GFP (((GFP_HIGHUSER | __GFP_ZERO | __GFP_NOWARN \45#define HIGH_ORDER_GFP (((GFP_HIGHUSER | __GFP_ZERO | __GFP_NOWARN \
44 | __GFP_NORETRY) & ~__GFP_RECLAIM) \46 | __GFP_NORETRY) & ~__GFP_RECLAIM) \
45 | __GFP_COMP)47 | __GFP_COMP)
46#define LOW_ORDER_GFP (GFP_HIGHUSER | __GFP_ZERO | __GFP_COMP)48static gfp_t order_flags[] = {HIGH_ORDER_GFP, MID_ORDER_GFP, LOW_ORDER_GFP};
47static gfp_t order_flags[] = {HIGH_ORDER_GFP, LOW_ORDER_GFP, LOW_ORDER_GFP};
48/*49/*
49 * The selection of the orders used for allocation (1MB, 64K, 4K) is designed50 * The selection of the orders used for allocation (1MB, 64K, 4K) is designed
50 * to match with the sizes often found in IOMMUs. Using order 4 pages instead51 * to match with the sizes often found in IOMMUs. Using order 4 pages instead
drivers/dma-buf/seqno-fence.c+0−71
@@ -1,71 +0,0 @@
1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * seqno-fence, using a dma-buf to synchronize fencing
4 *
5 * Copyright (C) 2012 Texas Instruments
6 * Copyright (C) 2012-2014 Canonical Ltd
7 * Authors:
8 * Rob Clark <robdclark@gmail.com>
9 * Maarten Lankhorst <maarten.lankhorst@canonical.com>
10 */
11
12#include <linux/slab.h>
13#include <linux/export.h>
14#include <linux/seqno-fence.h>
15
16static const char *seqno_fence_get_driver_name(struct dma_fence *fence)
17{
18 struct seqno_fence *seqno_fence = to_seqno_fence(fence);
19
20 return seqno_fence->ops->get_driver_name(fence);
21}
22
23static const char *seqno_fence_get_timeline_name(struct dma_fence *fence)
24{
25 struct seqno_fence *seqno_fence = to_seqno_fence(fence);
26
27 return seqno_fence->ops->get_timeline_name(fence);
28}
29
30static bool seqno_enable_signaling(struct dma_fence *fence)
31{
32 struct seqno_fence *seqno_fence = to_seqno_fence(fence);
33
34 return seqno_fence->ops->enable_signaling(fence);
35}
36
37static bool seqno_signaled(struct dma_fence *fence)
38{
39 struct seqno_fence *seqno_fence = to_seqno_fence(fence);
40
41 return seqno_fence->ops->signaled && seqno_fence->ops->signaled(fence);
42}
43
44static void seqno_release(struct dma_fence *fence)
45{
46 struct seqno_fence *f = to_seqno_fence(fence);
47
48 dma_buf_put(f->sync_buf);
49 if (f->ops->release)
50 f->ops->release(fence);
51 else
52 dma_fence_free(&f->base);
53}
54
55static signed long seqno_wait(struct dma_fence *fence, bool intr,
56 signed long timeout)
57{
58 struct seqno_fence *f = to_seqno_fence(fence);
59
60 return f->ops->wait(fence, intr, timeout);
61}
62
63const struct dma_fence_ops seqno_fence_ops = {
64 .get_driver_name = seqno_fence_get_driver_name,
65 .get_timeline_name = seqno_fence_get_timeline_name,
66 .enable_signaling = seqno_enable_signaling,
67 .signaled = seqno_signaled,
68 .wait = seqno_wait,
69 .release = seqno_release,
70};
71EXPORT_SYMBOL(seqno_fence_ops);
drivers/gpu/drm/Kconfig+4−5
@@ -211,7 +211,7 @@ config DRM_KMS_CMA_HELPER · 210 unmodified lines
211 211
212config DRM_GEM_SHMEM_HELPER212config DRM_GEM_SHMEM_HELPER
213 bool213 bool
214 depends on DRM214 depends on DRM && MMU
215 help215 help
216 Choose this if you need the GEM shmem helper functions216 Choose this if you need the GEM shmem helper functions
217 217
@@ -271,7 +271,8 @@ source "drivers/gpu/drm/kmb/Kconfig" · 53 unmodified lines
271 271
272config DRM_VGEM272config DRM_VGEM
273 tristate "Virtual GEM provider"273 tristate "Virtual GEM provider"
274 depends on DRM274 depends on DRM && MMU
275 select DRM_GEM_SHMEM_HELPER
275 help276 help
276 Choose this option to get a virtual graphics memory manager,277 Choose this option to get a virtual graphics memory manager,
277 as used by Mesa's software renderer for enhanced performance.278 as used by Mesa's software renderer for enhanced performance.
@@ -279,7 +280,7 @@ config DRM_VGEM · 1 unmodified line
279 280
280config DRM_VKMS281config DRM_VKMS
281 tristate "Virtual KMS (EXPERIMENTAL)"282 tristate "Virtual KMS (EXPERIMENTAL)"
282 depends on DRM283 depends on DRM && MMU
283 select DRM_KMS_HELPER284 select DRM_KMS_HELPER
284 select DRM_GEM_SHMEM_HELPER285 select DRM_GEM_SHMEM_HELPER
285 select CRC32286 select CRC32
@@ -351,8 +352,6 @@ source "drivers/gpu/drm/hisilicon/Kconfig" · 65 unmodified lines
351 352
352source "drivers/gpu/drm/mediatek/Kconfig"353source "drivers/gpu/drm/mediatek/Kconfig"
353 354
354source "drivers/gpu/drm/zte/Kconfig"
355
356source "drivers/gpu/drm/mxsfb/Kconfig"355source "drivers/gpu/drm/mxsfb/Kconfig"
357 356
358source "drivers/gpu/drm/meson/Kconfig"357source "drivers/gpu/drm/meson/Kconfig"
drivers/gpu/drm/Makefile+0−1
@@ -113,7 +113,6 @@ obj-y += bridge/ · 112 unmodified lines
113obj-$(CONFIG_DRM_FSL_DCU) += fsl-dcu/113obj-$(CONFIG_DRM_FSL_DCU) += fsl-dcu/
114obj-$(CONFIG_DRM_ETNAVIV) += etnaviv/114obj-$(CONFIG_DRM_ETNAVIV) += etnaviv/
115obj-y += hisilicon/115obj-y += hisilicon/
116obj-$(CONFIG_DRM_ZTE) += zte/
117obj-$(CONFIG_DRM_MXSFB) += mxsfb/116obj-$(CONFIG_DRM_MXSFB) += mxsfb/
118obj-y += tiny/117obj-y += tiny/
119obj-$(CONFIG_DRM_PL111) += pl111/118obj-$(CONFIG_DRM_PL111) += pl111/
drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c+3−1
@@ -1222,6 +1222,8 @@ static int amdgpu_cs_submit(struct amdgpu_cs_parser *p, · 1221 unmodified lines
1222 if (r)1222 if (r)
1223 goto error_unlock;1223 goto error_unlock;
1224 1224
1225 drm_sched_job_arm(&job->base);
1226
1225 /* No memory allocation is allowed while holding the notifier lock.1227 /* No memory allocation is allowed while holding the notifier lock.
1226 * The lock is held until amdgpu_cs_submit is finished and fence is1228 * The lock is held until amdgpu_cs_submit is finished and fence is
1227 * added to BOs.1229 * added to BOs.
@@ -1259,7 +1261,7 @@ static int amdgpu_cs_submit(struct amdgpu_cs_parser *p, · 31 unmodified lines
1259 1261
1260 trace_amdgpu_cs_ioctl(job);1262 trace_amdgpu_cs_ioctl(job);
1261 amdgpu_vm_bo_trace_cs(&fpriv->vm, &p->ticket);1263 amdgpu_vm_bo_trace_cs(&fpriv->vm, &p->ticket);
1262 drm_sched_entity_push_job(&job->base, entity);1264 drm_sched_entity_push_job(&job->base);
1263 1265
1264 amdgpu_vm_move_to_lru_tail(p->adev, &fpriv->vm);1266 amdgpu_vm_move_to_lru_tail(p->adev, &fpriv->vm);
1265 1267
drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c+1−9
@@ -266,7 +266,6 @@ bool amdgpu_fence_process(struct amdgpu_ring *ring) · 265 unmodified lines
266 struct amdgpu_fence_driver *drv = &ring->fence_drv;266 struct amdgpu_fence_driver *drv = &ring->fence_drv;
267 struct amdgpu_device *adev = ring->adev;267 struct amdgpu_device *adev = ring->adev;
268 uint32_t seq, last_seq;268 uint32_t seq, last_seq;
269 int r;
270 269
271 do {270 do {
272 last_seq = atomic_read(&ring->fence_drv.last_seq);271 last_seq = atomic_read(&ring->fence_drv.last_seq);
@@ -298,12 +297,7 @@ bool amdgpu_fence_process(struct amdgpu_ring *ring) · 25 unmodified lines
298 if (!fence)297 if (!fence)
299 continue;298 continue;
300 299
301 r = dma_fence_signal(fence);300 dma_fence_signal(fence);
302 if (!r)
303 DMA_FENCE_TRACE(fence, "signaled from irq context\n");
304 else
305 BUG();
306
307 dma_fence_put(fence);301 dma_fence_put(fence);
308 pm_runtime_mark_last_busy(adev_to_drm(adev)->dev);302 pm_runtime_mark_last_busy(adev_to_drm(adev)->dev);
309 pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);303 pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
@@ -684,8 +678,6 @@ static bool amdgpu_fence_enable_signaling(struct dma_fence *f) · 374 unmodified lines
684 if (!timer_pending(&ring->fence_drv.fallback_timer))678 if (!timer_pending(&ring->fence_drv.fallback_timer))
685 amdgpu_fence_schedule_fallback(ring);679 amdgpu_fence_schedule_fallback(ring);
686 680
687 DMA_FENCE_TRACE(f, "armed on ring %i!\n", ring->idx);
688
689 return true;681 return true;
690}682}
691 683
drivers/gpu/drm/amd/amdgpu/amdgpu_job.c+3−1
@@ -182,9 +182,11 @@ int amdgpu_job_submit(struct amdgpu_job *job, struct drm_sched_entity *entity, · 181 unmodified lines
182 if (r)182 if (r)
183 return r;183 return r;
184 184
185 drm_sched_job_arm(&job->base);
186
185 *f = dma_fence_get(&job->base.s_fence->finished);187 *f = dma_fence_get(&job->base.s_fence->finished);
186 amdgpu_job_free_resources(job);188 amdgpu_job_free_resources(job);
187 drm_sched_entity_push_job(&job->base, entity);189 drm_sched_entity_push_job(&job->base);
188 190
189 return 0;191 return 0;
190}192}
drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c+2−2
@@ -1066,8 +1066,6 @@ static void amdgpu_ttm_backend_destroy(struct ttm_device *bdev, · 1065 unmodified lines
1066{1066{
1067 struct amdgpu_ttm_tt *gtt = (void *)ttm;1067 struct amdgpu_ttm_tt *gtt = (void *)ttm;
1068 1068
1069 amdgpu_ttm_backend_unbind(bdev, ttm);
1070 ttm_tt_destroy_common(bdev, ttm);
1071 if (gtt->usertask)1069 if (gtt->usertask)
1072 put_task_struct(gtt->usertask);1070 put_task_struct(gtt->usertask);
1073 1071
@@ -1148,6 +1146,8 @@ static void amdgpu_ttm_tt_unpopulate(struct ttm_device *bdev, · 74 unmodified lines
1148 struct amdgpu_ttm_tt *gtt = (void *)ttm;1146 struct amdgpu_ttm_tt *gtt = (void *)ttm;
1149 struct amdgpu_device *adev;1147 struct amdgpu_device *adev;
1150 1148
1149 amdgpu_ttm_backend_unbind(bdev, ttm);
1150
1151 if (gtt->userptr) {1151 if (gtt->userptr) {
1152 amdgpu_ttm_tt_set_user_pages(ttm, NULL);1152 amdgpu_ttm_tt_set_user_pages(ttm, NULL);
1153 kfree(ttm->sg);1153 kfree(ttm->sg);
drivers/gpu/drm/arm/malidp_planes.c+1−1
@@ -165,7 +165,7 @@ bool malidp_format_mod_supported(struct drm_device *drm, · 164 unmodified lines
165 return !malidp_hw_format_is_afbc_only(format);165 return !malidp_hw_format_is_afbc_only(format);
166 }166 }
167 167
168 if ((modifier >> 56) != DRM_FORMAT_MOD_VENDOR_ARM) {168 if (!fourcc_mod_is_vendor(modifier, ARM)) {
169 DRM_ERROR("Unknown modifier (not Arm)\n");169 DRM_ERROR("Unknown modifier (not Arm)\n");
170 return false;170 return false;
171 }171 }
drivers/gpu/drm/bridge/adv7511/adv7511_cec.c+1−14
@@ -1,21 +1,8 @@
1// SPDX-License-Identifier: GPL-2.0-only
1/*2/*
2 * adv7511_cec.c - Analog Devices ADV7511/33 cec driver3 * adv7511_cec.c - Analog Devices ADV7511/33 cec driver
3 *4 *
4 * Copyright 2017 Cisco Systems, Inc. and/or its affiliates. All rights reserved.5 * Copyright 2017 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
5 *
6 * This program is free software; you may redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
11 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
12 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
13 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
14 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
15 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
16 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
17 * SOFTWARE.
18 *
19 */6 */
20 7
21#include <linux/device.h>8#include <linux/device.h>
drivers/gpu/drm/bridge/analogix/anx7625.c+18−9
@@ -720,7 +720,7 @@ static int edid_read(struct anx7625_data *ctx, · 719 unmodified lines
720 ret = sp_tx_aux_rd(ctx, 0xf1);720 ret = sp_tx_aux_rd(ctx, 0xf1);
721 721
722 if (ret) {722 if (ret) {
723 sp_tx_rst_aux(ctx);723 ret = sp_tx_rst_aux(ctx);
724 DRM_DEV_DEBUG_DRIVER(dev, "edid read fail, reset!\n");724 DRM_DEV_DEBUG_DRIVER(dev, "edid read fail, reset!\n");
725 } else {725 } else {
726 ret = anx7625_reg_block_read(ctx, ctx->i2c.rx_p0_client,726 ret = anx7625_reg_block_read(ctx, ctx->i2c.rx_p0_client,
@@ -735,7 +735,7 @@ static int edid_read(struct anx7625_data *ctx, · 8 unmodified lines
735 if (cnt > EDID_TRY_CNT)735 if (cnt > EDID_TRY_CNT)
736 return -EIO;736 return -EIO;
737 737
738 return 0;738 return ret;
739}739}
740 740
741static int segments_edid_read(struct anx7625_data *ctx,741static int segments_edid_read(struct anx7625_data *ctx,
@@ -785,7 +785,7 @@ static int segments_edid_read(struct anx7625_data *ctx, · 43 unmodified lines
785 if (cnt > EDID_TRY_CNT)785 if (cnt > EDID_TRY_CNT)
786 return -EIO;786 return -EIO;
787 787
788 return 0;788 return ret;
789}789}
790 790
791static int sp_tx_edid_read(struct anx7625_data *ctx,791static int sp_tx_edid_read(struct anx7625_data *ctx,
@@ -845,8 +845,11 @@ static int sp_tx_edid_read(struct anx7625_data *ctx, · 53 unmodified lines
845 if (g_edid_break == 1)845 if (g_edid_break == 1)
846 break;846 break;
847 847
848 segments_edid_read(ctx, count / 2,848 ret = segments_edid_read(ctx, count / 2,
849 pblock_buf, offset);849 pblock_buf, offset);
850 if (ret < 0)
851 return ret;
852
850 memcpy(&pedid_blocks_buf[edid_pos],853 memcpy(&pedid_blocks_buf[edid_pos],
851 pblock_buf,854 pblock_buf,
852 MAX_DPCD_BUFFER_SIZE);855 MAX_DPCD_BUFFER_SIZE);
@@ -863,8 +866,11 @@ static int sp_tx_edid_read(struct anx7625_data *ctx, · 10 unmodified lines
863 if (g_edid_break == 1)866 if (g_edid_break == 1)
864 break;867 break;
865 868
866 segments_edid_read(ctx, count / 2,869 ret = segments_edid_read(ctx, count / 2,
867 pblock_buf, offset);870 pblock_buf, offset);
871 if (ret < 0)
872 return ret;
873
868 memcpy(&pedid_blocks_buf[edid_pos],874 memcpy(&pedid_blocks_buf[edid_pos],
869 pblock_buf,875 pblock_buf,
870 MAX_DPCD_BUFFER_SIZE);876 MAX_DPCD_BUFFER_SIZE);
@@ -887,7 +893,11 @@ static int sp_tx_edid_read(struct anx7625_data *ctx, · 16 unmodified lines
887 }893 }
888 894
889 /* Reset aux channel */895 /* Reset aux channel */
890 sp_tx_rst_aux(ctx);896 ret = sp_tx_rst_aux(ctx);
897 if (ret < 0) {
898 DRM_DEV_ERROR(dev, "Failed to reset aux channel!\n");
899 return ret;
900 }
891 901
892 return (blocks_num + 1);902 return (blocks_num + 1);
893}903}
@@ -1325,7 +1335,6 @@ static int anx7625_attach_dsi(struct anx7625_data *ctx) · 431 unmodified lines
1325 dsi->format = MIPI_DSI_FMT_RGB888;1335 dsi->format = MIPI_DSI_FMT_RGB888;
1326 dsi->mode_flags = MIPI_DSI_MODE_VIDEO |1336 dsi->mode_flags = MIPI_DSI_MODE_VIDEO |
1327 MIPI_DSI_MODE_VIDEO_SYNC_PULSE |1337 MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
1328 MIPI_DSI_MODE_NO_EOT_PACKET |
1329 MIPI_DSI_MODE_VIDEO_HSE;1338 MIPI_DSI_MODE_VIDEO_HSE;
1330 1339
1331 if (mipi_dsi_attach(dsi) < 0) {1340 if (mipi_dsi_attach(dsi) < 0) {
drivers/gpu/drm/bridge/cdns-dsi.c+1−3
@@ -1171,7 +1171,6 @@ static int cdns_dsi_drm_probe(struct platform_device *pdev) · 1170 unmodified lines
1171{1171{
1172 struct cdns_dsi *dsi;1172 struct cdns_dsi *dsi;
1173 struct cdns_dsi_input *input;1173 struct cdns_dsi_input *input;
1174 struct resource *res;
1175 int ret, irq;1174 int ret, irq;
1176 u32 val;1175 u32 val;
1177 1176
@@ -1183,8 +1182,7 @@ static int cdns_dsi_drm_probe(struct platform_device *pdev) · 5 unmodified lines
1183 1182
1184 input = &dsi->input;1183 input = &dsi->input;
1185 1184
1186 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);1185 dsi->regs = devm_platform_ioremap_resource(pdev, 0);
1187 dsi->regs = devm_ioremap_resource(&pdev->dev, res);
1188 if (IS_ERR(dsi->regs))1186 if (IS_ERR(dsi->regs))
1189 return PTR_ERR(dsi->regs);1187 return PTR_ERR(dsi->regs);
1190 1188
drivers/gpu/drm/bridge/ite-it66121.c+4−1
@@ -889,7 +889,7 @@ unlock: · 888 unmodified lines
889static int it66121_probe(struct i2c_client *client,889static int it66121_probe(struct i2c_client *client,
890 const struct i2c_device_id *id)890 const struct i2c_device_id *id)
891{891{
892 u32 vendor_ids[2], device_ids[2], revision_id;892 u32 revision_id, vendor_ids[2] = { 0 }, device_ids[2] = { 0 };
893 struct device_node *ep;893 struct device_node *ep;
894 int ret;894 int ret;
895 struct it66121_ctx *ctx;895 struct it66121_ctx *ctx;
@@ -924,6 +924,9 @@ static int it66121_probe(struct i2c_client *client, · 28 unmodified lines
924 ctx->next_bridge = of_drm_find_bridge(ep);924 ctx->next_bridge = of_drm_find_bridge(ep);
925 of_node_put(ep);925 of_node_put(ep);
926 926
927 if (!ctx->next_bridge)
928 return -EPROBE_DEFER;
929
927 i2c_set_clientdata(client, ctx);930 i2c_set_clientdata(client, ctx);
928 mutex_init(&ctx->lock);931 mutex_init(&ctx->lock);
929 932
drivers/gpu/drm/bridge/parade-ps8640.c+10−8
@@ -18,16 +18,18 @@ · 17 unmodified lines
18#include <drm/drm_print.h>18#include <drm/drm_print.h>
19 19
20#define PAGE2_GPIO_H 0xa720#define PAGE2_GPIO_H 0xa7
21#define PS_GPIO9 BIT(1)21#define PS_GPIO9 BIT(1)
22#define PAGE2_I2C_BYPASS 0xea22#define PAGE2_I2C_BYPASS 0xea
23#define I2C_BYPASS_EN 0xd023#define I2C_BYPASS_EN 0xd0
24#define PAGE2_MCS_EN 0xf324#define PAGE2_MCS_EN 0xf3
25#define MCS_EN BIT(0)25#define MCS_EN BIT(0)
26
26#define PAGE3_SET_ADD 0xfe27#define PAGE3_SET_ADD 0xfe
27#define VDO_CTL_ADD 0x1328#define VDO_CTL_ADD 0x13
28#define VDO_DIS 0x1829#define VDO_DIS 0x18
29#define VDO_EN 0x1c30#define VDO_EN 0x1c
30#define DP_NUM_LANES 431
32#define NUM_MIPI_LANES 4
31 33
32/*34/*
33 * PS8640 uses multiple addresses:35 * PS8640 uses multiple addresses:
@@ -254,7 +256,7 @@ static int ps8640_bridge_attach(struct drm_bridge *bridge, · 220 unmodified lines
254 dsi->mode_flags = MIPI_DSI_MODE_VIDEO |256 dsi->mode_flags = MIPI_DSI_MODE_VIDEO |
255 MIPI_DSI_MODE_VIDEO_SYNC_PULSE;257 MIPI_DSI_MODE_VIDEO_SYNC_PULSE;
256 dsi->format = MIPI_DSI_FMT_RGB888;258 dsi->format = MIPI_DSI_FMT_RGB888;
257 dsi->lanes = DP_NUM_LANES;259 dsi->lanes = NUM_MIPI_LANES;
258 ret = mipi_dsi_attach(dsi);260 ret = mipi_dsi_attach(dsi);
259 if (ret)261 if (ret)
260 goto err_dsi_attach;262 goto err_dsi_attach;
drivers/gpu/drm/drm_bridge.c+37−4
@@ -28,6 +28,7 @@ · 27 unmodified lines
28#include <drm/drm_atomic_state_helper.h>28#include <drm/drm_atomic_state_helper.h>
29#include <drm/drm_bridge.h>29#include <drm/drm_bridge.h>
30#include <drm/drm_encoder.h>30#include <drm/drm_encoder.h>
31#include <drm/drm_of.h>
31#include <drm/drm_print.h>32#include <drm/drm_print.h>
32 33
33#include "drm_crtc_internal.h"34#include "drm_crtc_internal.h"
@@ -51,10 +52,8 @@ · 17 unmodified lines
51 *52 *
52 * Display drivers are responsible for linking encoders with the first bridge53 * Display drivers are responsible for linking encoders with the first bridge
53 * in the chains. This is done by acquiring the appropriate bridge with54 * in the chains. This is done by acquiring the appropriate bridge with
54 * of_drm_find_bridge() or drm_of_find_panel_or_bridge(), or creating it for a55 * devm_drm_of_get_bridge(). Once acquired, the bridge shall be attached to the
55 * panel with drm_panel_bridge_add_typed() (or the managed version56 * encoder with a call to drm_bridge_attach().
56 * devm_drm_panel_bridge_add_typed()). Once acquired, the bridge shall be
57 * attached to the encoder with a call to drm_bridge_attach().
58 *57 *
59 * Bridges are responsible for linking themselves with the next bridge in the58 * Bridges are responsible for linking themselves with the next bridge in the
60 * chain, if any. This is done the same way as for encoders, with the call to59 * chain, if any. This is done the same way as for encoders, with the call to
@@ -1233,6 +1232,40 @@ struct drm_bridge *of_drm_find_bridge(struct device_node *np) · 1172 unmodified lines
1233 return NULL;1232 return NULL;
1234}1233}
1235EXPORT_SYMBOL(of_drm_find_bridge);1234EXPORT_SYMBOL(of_drm_find_bridge);
1235
1236/**
1237 * devm_drm_of_get_bridge - Return next bridge in the chain
1238 * @dev: device to tie the bridge lifetime to
1239 * @np: device tree node containing encoder output ports
1240 * @port: port in the device tree node
1241 * @endpoint: endpoint in the device tree node
1242 *
1243 * Given a DT node's port and endpoint number, finds the connected node
1244 * and returns the associated bridge if any, or creates and returns a
1245 * drm panel bridge instance if a panel is connected.
1246 *
1247 * Returns a pointer to the bridge if successful, or an error pointer
1248 * otherwise.
1249 */
1250struct drm_bridge *devm_drm_of_get_bridge(struct device *dev,
1251 struct device_node *np,
1252 u32 port, u32 endpoint)
1253{
1254 struct drm_bridge *bridge;
1255 struct drm_panel *panel;
1256 int ret;
1257
1258 ret = drm_of_find_panel_or_bridge(np, port, endpoint,
1259 &panel, &bridge);
1260 if (ret)
1261 return ERR_PTR(ret);
1262
1263 if (panel)
1264 bridge = devm_drm_panel_bridge_add(dev, panel);
1265
1266 return bridge;
1267}
1268EXPORT_SYMBOL(devm_drm_of_get_bridge);
1236#endif1269#endif
1237 1270
1238MODULE_AUTHOR("Ajay Kumar <ajaykumar.rs@samsung.com>");1271MODULE_AUTHOR("Ajay Kumar <ajaykumar.rs@samsung.com>");
drivers/gpu/drm/drm_connector.c+79−0
@@ -65,6 +65,14 @@ · 64 unmodified lines
65 * support can instead use e.g. drm_helper_hpd_irq_event().65 * support can instead use e.g. drm_helper_hpd_irq_event().
66 */66 */
67 67
68/*
69 * Global connector list for drm_connector_find_by_fwnode().
70 * Note drm_connector_[un]register() first take connector->lock and then
71 * take the connector_list_lock.
72 */
73static DEFINE_MUTEX(connector_list_lock);
74static LIST_HEAD(connector_list);
75
68struct drm_conn_prop_enum_list {76struct drm_conn_prop_enum_list {
69 int type;77 int type;
70 const char *name;78 const char *name;
@@ -267,6 +275,7 @@ int drm_connector_init(struct drm_device *dev, · 196 unmodified lines
267 goto out_put_type_id;275 goto out_put_type_id;
268 }276 }
269 277
278 INIT_LIST_HEAD(&connector->global_connector_list_entry);
270 INIT_LIST_HEAD(&connector->probed_modes);279 INIT_LIST_HEAD(&connector->probed_modes);
271 INIT_LIST_HEAD(&connector->modes);280 INIT_LIST_HEAD(&connector->modes);
272 mutex_init(&connector->mutex);281 mutex_init(&connector->mutex);
@@ -474,6 +483,8 @@ void drm_connector_cleanup(struct drm_connector *connector) · 201 unmodified lines
474 drm_mode_object_unregister(dev, &connector->base);483 drm_mode_object_unregister(dev, &connector->base);
475 kfree(connector->name);484 kfree(connector->name);
476 connector->name = NULL;485 connector->name = NULL;
486 fwnode_handle_put(connector->fwnode);
487 connector->fwnode = NULL;
477 spin_lock_irq(&dev->mode_config.connector_list_lock);488 spin_lock_irq(&dev->mode_config.connector_list_lock);
478 list_del(&connector->head);489 list_del(&connector->head);
479 dev->mode_config.num_connector--;490 dev->mode_config.num_connector--;
@@ -532,6 +543,9 @@ int drm_connector_register(struct drm_connector *connector) · 52 unmodified lines
532 /* Let userspace know we have a new connector */543 /* Let userspace know we have a new connector */
533 drm_sysfs_hotplug_event(connector->dev);544 drm_sysfs_hotplug_event(connector->dev);
534 545
546 mutex_lock(&connector_list_lock);
547 list_add_tail(&connector->global_connector_list_entry, &connector_list);
548 mutex_unlock(&connector_list_lock);
535 goto unlock;549 goto unlock;
536 550
537err_debugfs:551err_debugfs:
@@ -560,6 +574,10 @@ void drm_connector_unregister(struct drm_connector *connector) · 22 unmodified lines
560 return;574 return;
561 }575 }
562 576
577 mutex_lock(&connector_list_lock);
578 list_del_init(&connector->global_connector_list_entry);
579 mutex_unlock(&connector_list_lock);
580
563 if (connector->funcs->early_unregister)581 if (connector->funcs->early_unregister)
564 connector->funcs->early_unregister(connector);582 connector->funcs->early_unregister(connector);
565 583
@@ -2543,6 +2561,67 @@ out: · 1977 unmodified lines
2543 return ret;2561 return ret;
2544}2562}
2545 2563
2564/**
2565 * drm_connector_find_by_fwnode - Find a connector based on the associated fwnode
2566 * @fwnode: fwnode for which to find the matching drm_connector
2567 *
2568 * This functions looks up a drm_connector based on its associated fwnode. When
2569 * a connector is found a reference to the connector is returned. The caller must
2570 * call drm_connector_put() to release this reference when it is done with the
2571 * connector.
2572 *
2573 * Returns: A reference to the found connector or an ERR_PTR().
2574 */
2575struct drm_connector *drm_connector_find_by_fwnode(struct fwnode_handle *fwnode)
2576{
2577 struct drm_connector *connector, *found = ERR_PTR(-ENODEV);
2578
2579 if (!fwnode)
2580 return ERR_PTR(-ENODEV);
2581
2582 mutex_lock(&connector_list_lock);
2583
2584 list_for_each_entry(connector, &connector_list, global_connector_list_entry) {
2585 if (connector->fwnode == fwnode ||
2586 (connector->fwnode && connector->fwnode->secondary == fwnode)) {
2587 drm_connector_get(connector);
2588 found = connector;
2589 break;
2590 }
2591 }
2592
2593 mutex_unlock(&connector_list_lock);
2594
2595 return found;
2596}
2597
2598/**
2599 * drm_connector_oob_hotplug_event - Report out-of-band hotplug event to connector
2600 * @connector: connector to report the event on
2601 *
2602 * On some hardware a hotplug event notification may come from outside the display
2603 * driver / device. An example of this is some USB Type-C setups where the hardware
2604 * muxes the DisplayPort data and aux-lines but does not pass the altmode HPD
2605 * status bit to the GPU's DP HPD pin.
2606 *
2607 * This function can be used to report these out-of-band events after obtaining
2608 * a drm_connector reference through calling drm_connector_find_by_fwnode().
2609 */
2610void drm_connector_oob_hotplug_event(struct fwnode_handle *connector_fwnode)
2611{
2612 struct drm_connector *connector;
2613
2614 connector = drm_connector_find_by_fwnode(connector_fwnode);
2615 if (IS_ERR(connector))
2616 return;
2617
2618 if (connector->funcs->oob_hotplug_event)
2619 connector->funcs->oob_hotplug_event(connector);
2620
2621 drm_connector_put(connector);
2622}
2623EXPORT_SYMBOL(drm_connector_oob_hotplug_event);
2624
2546 2625
2547/**2626/**
2548 * DOC: Tile group2627 * DOC: Tile group
drivers/gpu/drm/drm_crtc_internal.h+2−0
@@ -58,6 +58,7 @@ struct drm_property; · 57 unmodified lines
58struct edid;58struct edid;
59struct kref;59struct kref;
60struct work_struct;60struct work_struct;
61struct fwnode_handle;
61 62
62/* drm_crtc.c */63/* drm_crtc.c */
63int drm_mode_crtc_set_obj_prop(struct drm_mode_object *obj,64int drm_mode_crtc_set_obj_prop(struct drm_mode_object *obj,
@@ -186,6 +187,7 @@ int drm_connector_set_obj_prop(struct drm_mode_object *obj, · 122 unmodified lines
186int drm_connector_create_standard_properties(struct drm_device *dev);187int drm_connector_create_standard_properties(struct drm_device *dev);
187const char *drm_get_connector_force_name(enum drm_connector_force force);188const char *drm_get_connector_force_name(enum drm_connector_force force);
188void drm_connector_free_work_fn(struct work_struct *work);189void drm_connector_free_work_fn(struct work_struct *work);
190struct drm_connector *drm_connector_find_by_fwnode(struct fwnode_handle *fwnode);
189 191
190/* IOCTL */192/* IOCTL */
191int drm_connector_property_set_ioctl(struct drm_device *dev,193int drm_connector_property_set_ioctl(struct drm_device *dev,
drivers/gpu/drm/drm_gem_shmem_helper.c+21−2
@@ -10,6 +10,10 @@ · 9 unmodified lines
10#include <linux/slab.h>10#include <linux/slab.h>
11#include <linux/vmalloc.h>11#include <linux/vmalloc.h>
12 12
13#ifdef CONFIG_X86
14#include <asm/set_memory.h>
15#endif
16
13#include <drm/drm.h>17#include <drm/drm.h>
14#include <drm/drm_device.h>18#include <drm/drm_device.h>
15#include <drm/drm_drv.h>19#include <drm/drm_drv.h>
@@ -162,6 +166,16 @@ static int drm_gem_shmem_get_pages_locked(struct drm_gem_shmem_object *shmem) · 146 unmodified lines
162 return PTR_ERR(pages);166 return PTR_ERR(pages);
163 }167 }
164 168
169 /*
170 * TODO: Allocating WC pages which are correctly flushed is only
171 * supported on x86. Ideal solution would be a GFP_WC flag, which also
172 * ttm_pool.c could use.
173 */
174#ifdef CONFIG_X86
175 if (shmem->map_wc)
176 set_pages_array_wc(pages, obj->size >> PAGE_SHIFT);
177#endif
178
165 shmem->pages = pages;179 shmem->pages = pages;
166 180
167 return 0;181 return 0;
@@ -203,6 +217,11 @@ static void drm_gem_shmem_put_pages_locked(struct drm_gem_shmem_object *shmem) · 35 unmodified lines
203 if (--shmem->pages_use_count > 0)217 if (--shmem->pages_use_count > 0)
204 return;218 return;
205 219
220#ifdef CONFIG_X86
221 if (shmem->map_wc)
222 set_pages_array_wb(shmem->pages, obj->size >> PAGE_SHIFT);
223#endif
224
206 drm_gem_put_pages(obj, shmem->pages,225 drm_gem_put_pages(obj, shmem->pages,
207 shmem->pages_mark_dirty_on_put,226 shmem->pages_mark_dirty_on_put,
208 shmem->pages_mark_accessed_on_put);227 shmem->pages_mark_accessed_on_put);
@@ -542,7 +561,7 @@ static vm_fault_t drm_gem_shmem_fault(struct vm_fault *vmf) · 333 unmodified lines
542 } else {561 } else {
543 page = shmem->pages[page_offset];562 page = shmem->pages[page_offset];
544 563
545 ret = vmf_insert_page(vma, vmf->address, page);564 ret = vmf_insert_pfn(vma, vmf->address, page_to_pfn(page));
546 }565 }
547 566
548 mutex_unlock(&shmem->pages_lock);567 mutex_unlock(&shmem->pages_lock);
@@ -612,7 +631,7 @@ int drm_gem_shmem_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma) · 63 unmodified lines
612 return ret;631 return ret;
613 }632 }
614 633
615 vma->vm_flags |= VM_MIXEDMAP | VM_DONTEXPAND;634 vma->vm_flags |= VM_PFNMAP | VM_DONTEXPAND;
616 vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);635 vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
617 if (shmem->map_wc)636 if (shmem->map_wc)
618 vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);637 vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
drivers/gpu/drm/drm_gem_vram_helper.c+0−1
@@ -846,7 +846,6 @@ static const struct drm_gem_object_funcs drm_gem_vram_object_funcs = { · 845 unmodified lines
846 846
847static void bo_driver_ttm_tt_destroy(struct ttm_device *bdev, struct ttm_tt *tt)847static void bo_driver_ttm_tt_destroy(struct ttm_device *bdev, struct ttm_tt *tt)
848{848{
849 ttm_tt_destroy_common(bdev, tt);
850 ttm_tt_fini(tt);849 ttm_tt_fini(tt);
851 kfree(tt);850 kfree(tt);
852}851}
drivers/gpu/drm/drm_ioctl.c+4−17
@@ -522,19 +522,7 @@ int drm_version(struct drm_device *dev, void *data, · 521 unmodified lines
522 return err;522 return err;
523}523}
524 524
525/**525static int drm_ioctl_permit(u32 flags, struct drm_file *file_priv)
526 * drm_ioctl_permit - Check ioctl permissions against caller
527 *
528 * @flags: ioctl permission flags.
529 * @file_priv: Pointer to struct drm_file identifying the caller.
530 *
531 * Checks whether the caller is allowed to run an ioctl with the
532 * indicated permissions.
533 *
534 * Returns:
535 * Zero if allowed, -EACCES otherwise.
536 */
537int drm_ioctl_permit(u32 flags, struct drm_file *file_priv)
538{526{
539 /* ROOT_ONLY is only for CAP_SYS_ADMIN */527 /* ROOT_ONLY is only for CAP_SYS_ADMIN */
540 if (unlikely((flags & DRM_ROOT_ONLY) && !capable(CAP_SYS_ADMIN)))528 if (unlikely((flags & DRM_ROOT_ONLY) && !capable(CAP_SYS_ADMIN)))
@@ -557,7 +545,6 @@ int drm_ioctl_permit(u32 flags, struct drm_file *file_priv) · 16 unmodified lines
557 545
558 return 0;546 return 0;
559}547}
560EXPORT_SYMBOL(drm_ioctl_permit);
561 548
562#define DRM_IOCTL_DEF(ioctl, _func, _flags) \549#define DRM_IOCTL_DEF(ioctl, _func, _flags) \
563 [DRM_IOCTL_NR(ioctl)] = { \550 [DRM_IOCTL_NR(ioctl)] = { \
@@ -725,7 +712,7 @@ static const struct drm_ioctl_desc drm_ioctls[] = { · 161 unmodified lines
725 DRM_IOCTL_DEF(DRM_IOCTL_MODE_REVOKE_LEASE, drm_mode_revoke_lease_ioctl, DRM_MASTER),712 DRM_IOCTL_DEF(DRM_IOCTL_MODE_REVOKE_LEASE, drm_mode_revoke_lease_ioctl, DRM_MASTER),
726};713};
727 714
728#define DRM_CORE_IOCTL_COUNT ARRAY_SIZE( drm_ioctls )715#define DRM_CORE_IOCTL_COUNT ARRAY_SIZE(drm_ioctls)
729 716
730/**717/**
731 * DOC: driver specific ioctls718 * DOC: driver specific ioctls
@@ -834,8 +821,8 @@ long drm_ioctl(struct file *filp, · 102 unmodified lines
834 if (drm_dev_is_unplugged(dev))821 if (drm_dev_is_unplugged(dev))
835 return -ENODEV;822 return -ENODEV;
836 823
837 if (DRM_IOCTL_TYPE(cmd) != DRM_IOCTL_BASE)824 if (DRM_IOCTL_TYPE(cmd) != DRM_IOCTL_BASE)
838 return -ENOTTY;825 return -ENOTTY;
839 826
840 is_driver_ioctl = nr >= DRM_COMMAND_BASE && nr < DRM_COMMAND_END;827 is_driver_ioctl = nr >= DRM_COMMAND_BASE && nr < DRM_COMMAND_END;
841 828
drivers/gpu/drm/drm_kms_helper_common.c+0−11
@@ -64,17 +64,6 @@ MODULE_PARM_DESC(edid_firmware, · 63 unmodified lines
64 64
65static int __init drm_kms_helper_init(void)65static int __init drm_kms_helper_init(void)
66{66{
67 /*
68 * The Kconfig DRM_KMS_HELPER selects FRAMEBUFFER_CONSOLE (if !EXPERT)
69 * but the module doesn't depend on any fb console symbols. At least
70 * attempt to load fbcon to avoid leaving the system without a usable
71 * console.
72 */
73 if (IS_ENABLED(CONFIG_DRM_FBDEV_EMULATION) &&
74 IS_MODULE(CONFIG_FRAMEBUFFER_CONSOLE) &&
75 !IS_ENABLED(CONFIG_EXPERT))
76 request_module_nowait("fbcon");
77
78 return drm_dp_aux_dev_init();67 return drm_dp_aux_dev_init();
79}68}
80 69
drivers/gpu/drm/drm_of.c+3−0
@@ -231,6 +231,9 @@ EXPORT_SYMBOL_GPL(drm_of_encoder_active_endpoint); · 230 unmodified lines
231 * return either the associated struct drm_panel or drm_bridge device. Either231 * return either the associated struct drm_panel or drm_bridge device. Either
232 * @panel or @bridge must not be NULL.232 * @panel or @bridge must not be NULL.
233 *233 *
234 * This function is deprecated and should not be used in new drivers. Use
235 * devm_drm_of_get_bridge() instead.
236 *
234 * Returns zero if successful, or one of the standard error codes if it fails.237 * Returns zero if successful, or one of the standard error codes if it fails.
235 */238 */
236int drm_of_find_panel_or_bridge(const struct device_node *np,239int drm_of_find_panel_or_bridge(const struct device_node *np,
drivers/gpu/drm/drm_panel_orientation_quirks.c+47−2
@@ -109,6 +109,12 @@ static const struct drm_dmi_panel_orientation_data lcd1200x1920_rightside_up = { · 108 unmodified lines
109 .orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP,109 .orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP,
110};110};
111 111
112static const struct drm_dmi_panel_orientation_data lcd1280x1920_rightside_up = {
113 .width = 1280,
114 .height = 1920,
115 .orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP,
116};
117
112static const struct dmi_system_id orientation_data[] = {118static const struct dmi_system_id orientation_data[] = {
113 { /* Acer One 10 (S1003) */119 { /* Acer One 10 (S1003) */
114 .matches = {120 .matches = {
@@ -134,6 +140,20 @@ static const struct dmi_system_id orientation_data[] = { · 19 unmodified lines
134 DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "T103HAF"),140 DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "T103HAF"),
135 },141 },
136 .driver_data = (void *)&lcd800x1280_rightside_up,142 .driver_data = (void *)&lcd800x1280_rightside_up,
143 }, { /* Chuwi HiBook (CWI514) */
144 .matches = {
145 DMI_MATCH(DMI_BOARD_VENDOR, "Hampoo"),
146 DMI_MATCH(DMI_BOARD_NAME, "Cherry Trail CR"),
147 /* Above matches are too generic, add bios-date match */
148 DMI_MATCH(DMI_BIOS_DATE, "05/07/2016"),
149 },
150 .driver_data = (void *)&lcd1200x1920_rightside_up,
151 }, { /* Chuwi Hi10 Pro (CWI529) */
152 .matches = {
153 DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "Hampoo"),
154 DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Hi10 pro tablet"),
155 },
156 .driver_data = (void *)&lcd1200x1920_rightside_up,
137 }, { /* GPD MicroPC (generic strings, also match on bios date) */157 }, { /* GPD MicroPC (generic strings, also match on bios date) */
138 .matches = {158 .matches = {
139 DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Default string"),159 DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Default string"),
@@ -193,6 +213,13 @@ static const struct dmi_system_id orientation_data[] = { · 53 unmodified lines
193 DMI_EXACT_MATCH(DMI_BOARD_NAME, "TW891"),213 DMI_EXACT_MATCH(DMI_BOARD_NAME, "TW891"),
194 },214 },
195 .driver_data = (void *)&itworks_tw891,215 .driver_data = (void *)&itworks_tw891,
216 }, { /* KD Kurio Smart C15200 2-in-1 */
217 .matches = {
218 DMI_EXACT_MATCH(DMI_SYS_VENDOR, "KD Interactive"),
219 DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Kurio Smart"),
220 DMI_EXACT_MATCH(DMI_BOARD_NAME, "KDM960BCP"),
221 },
222 .driver_data = (void *)&lcd800x1280_rightside_up,
196 }, { /*223 }, { /*
197 * Lenovo Ideapad Miix 310 laptop, only some production batches224 * Lenovo Ideapad Miix 310 laptop, only some production batches
198 * have a portrait screen, the resolution checks makes the quirk225 * have a portrait screen, the resolution checks makes the quirk
@@ -211,10 +238,15 @@ static const struct dmi_system_id orientation_data[] = { · 12 unmodified lines
211 DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "Lenovo MIIX 320-10ICR"),238 DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "Lenovo MIIX 320-10ICR"),
212 },239 },
213 .driver_data = (void *)&lcd800x1280_rightside_up,240 .driver_data = (void *)&lcd800x1280_rightside_up,
214 }, { /* Lenovo Ideapad D330 */241 }, { /* Lenovo Ideapad D330-10IGM (HD) */
242 .matches = {
243 DMI_EXACT_MATCH(DMI_SYS_VENDOR, "LENOVO"),
244 DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "Lenovo ideapad D330-10IGM"),
245 },
246 .driver_data = (void *)&lcd800x1280_rightside_up,
247 }, { /* Lenovo Ideapad D330-10IGM (FHD) */
215 .matches = {248 .matches = {
216 DMI_EXACT_MATCH(DMI_SYS_VENDOR, "LENOVO"),249 DMI_EXACT_MATCH(DMI_SYS_VENDOR, "LENOVO"),
217 DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "81H3"),
218 DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "Lenovo ideapad D330-10IGM"),250 DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "Lenovo ideapad D330-10IGM"),
219 },251 },
220 .driver_data = (void *)&lcd1200x1920_rightside_up,252 .driver_data = (void *)&lcd1200x1920_rightside_up,
@@ -225,6 +257,19 @@ static const struct dmi_system_id orientation_data[] = { · 4 unmodified lines
225 DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "Default string"),257 DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "Default string"),
226 },258 },
227 .driver_data = (void *)&onegx1_pro,259 .driver_data = (void *)&onegx1_pro,
260 }, { /* Samsung GalaxyBook 10.6 */
261 .matches = {
262 DMI_EXACT_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
263 DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Galaxy Book 10.6"),
264 },
265 .driver_data = (void *)&lcd1280x1920_rightside_up,
266 }, { /* Valve Steam Deck */
267 .matches = {
268 DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Valve"),
269 DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Jupiter"),
270 DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "1"),
271 },
272 .driver_data = (void *)&lcd800x1280_rightside_up,
228 }, { /* VIOS LTH17 */273 }, { /* VIOS LTH17 */
229 .matches = {274 .matches = {
230 DMI_EXACT_MATCH(DMI_SYS_VENDOR, "VIOS"),275 DMI_EXACT_MATCH(DMI_SYS_VENDOR, "VIOS"),
drivers/gpu/drm/drm_sysfs.c+74−13
@@ -10,6 +10,7 @@ · 9 unmodified lines
10 * Copyright (c) 2003-2004 IBM Corp.10 * Copyright (c) 2003-2004 IBM Corp.
11 */11 */
12 12
13#include <linux/acpi.h>
13#include <linux/device.h>14#include <linux/device.h>
14#include <linux/err.h>15#include <linux/err.h>
15#include <linux/export.h>16#include <linux/export.h>
@@ -50,8 +51,45 @@ static struct device_type drm_sysfs_device_minor = { · 34 unmodified lines
50 .name = "drm_minor"51 .name = "drm_minor"
51};52};
52 53
54static struct device_type drm_sysfs_device_connector = {
55 .name = "drm_connector",
56};
57
53struct class *drm_class;58struct class *drm_class;
54 59
60#ifdef CONFIG_ACPI
61static bool drm_connector_acpi_bus_match(struct device *dev)
62{
63 return dev->type == &drm_sysfs_device_connector;
64}
65
66static struct acpi_device *drm_connector_acpi_find_companion(struct device *dev)
67{
68 struct drm_connector *connector = to_drm_connector(dev);
69
70 return to_acpi_device_node(connector->fwnode);
71}
72
73static struct acpi_bus_type drm_connector_acpi_bus = {
74 .name = "drm_connector",
75 .match = drm_connector_acpi_bus_match,
76 .find_companion = drm_connector_acpi_find_companion,
77};
78
79static void drm_sysfs_acpi_register(void)
80{
81 register_acpi_bus_type(&drm_connector_acpi_bus);
82}
83
84static void drm_sysfs_acpi_unregister(void)
85{
86 unregister_acpi_bus_type(&drm_connector_acpi_bus);
87}
88#else
89static void drm_sysfs_acpi_register(void) { }
90static void drm_sysfs_acpi_unregister(void) { }
91#endif
92
55static char *drm_devnode(struct device *dev, umode_t *mode)93static char *drm_devnode(struct device *dev, umode_t *mode)
56{94{
57 return kasprintf(GFP_KERNEL, "dri/%s", dev_name(dev));95 return kasprintf(GFP_KERNEL, "dri/%s", dev_name(dev));
@@ -85,6 +123,8 @@ int drm_sysfs_init(void) · 27 unmodified lines
85 }123 }
86 124
87 drm_class->devnode = drm_devnode;125 drm_class->devnode = drm_devnode;
126
127 drm_sysfs_acpi_register();
88 return 0;128 return 0;
89}129}
90 130
@@ -97,11 +137,17 @@ void drm_sysfs_destroy(void) · 6 unmodified lines
97{137{
98 if (IS_ERR_OR_NULL(drm_class))138 if (IS_ERR_OR_NULL(drm_class))
99 return;139 return;
140 drm_sysfs_acpi_unregister();
100 class_remove_file(drm_class, &class_attr_version.attr);141 class_remove_file(drm_class, &class_attr_version.attr);
101 class_destroy(drm_class);142 class_destroy(drm_class);
102 drm_class = NULL;143 drm_class = NULL;
103}144}
104 145
146static void drm_sysfs_release(struct device *dev)
147{
148 kfree(dev);
149}
150
105/*151/*
106 * Connector properties152 * Connector properties
107 */153 */
@@ -273,27 +319,47 @@ static const struct attribute_group *connector_dev_groups[] = { · 165 unmodified lines
273int drm_sysfs_connector_add(struct drm_connector *connector)319int drm_sysfs_connector_add(struct drm_connector *connector)
274{320{
275 struct drm_device *dev = connector->dev;321 struct drm_device *dev = connector->dev;
322 struct device *kdev;
323 int r;
276 324
277 if (connector->kdev)325 if (connector->kdev)
278 return 0;326 return 0;
279 327
280 connector->kdev =328 kdev = kzalloc(sizeof(*kdev), GFP_KERNEL);
281 device_create_with_groups(drm_class, dev->primary->kdev, 0,329 if (!kdev)
282 connector, connector_dev_groups,330 return -ENOMEM;
283 "card%d-%s", dev->primary->index,331
284 connector->name);332 device_initialize(kdev);
333 kdev->class = drm_class;
334 kdev->type = &drm_sysfs_device_connector;
335 kdev->parent = dev->primary->kdev;
336 kdev->groups = connector_dev_groups;
337 kdev->release = drm_sysfs_release;
338 dev_set_drvdata(kdev, connector);
339
340 r = dev_set_name(kdev, "card%d-%s", dev->primary->index, connector->name);
341 if (r)
342 goto err_free;
343
285 DRM_DEBUG("adding \"%s\" to sysfs\n",344 DRM_DEBUG("adding \"%s\" to sysfs\n",
286 connector->name);345 connector->name);
287 346
288 if (IS_ERR(connector->kdev)) {347 r = device_add(kdev);
289 DRM_ERROR("failed to register connector device: %ld\n", PTR_ERR(connector->kdev));348 if (r) {
290 return PTR_ERR(connector->kdev);349 drm_err(dev, "failed to register connector device: %d\n", r);
350 goto err_free;
291 }351 }
292 352
353 connector->kdev = kdev;
354
293 if (connector->ddc)355 if (connector->ddc)
294 return sysfs_create_link(&connector->kdev->kobj,356 return sysfs_create_link(&connector->kdev->kobj,
295 &connector->ddc->dev.kobj, "ddc");357 &connector->ddc->dev.kobj, "ddc");
296 return 0;358 return 0;
359
360err_free:
361 put_device(kdev);
362 return r;
297}363}
298 364
299void drm_sysfs_connector_remove(struct drm_connector *connector)365void drm_sysfs_connector_remove(struct drm_connector *connector)
@@ -374,11 +440,6 @@ void drm_sysfs_connector_status_event(struct drm_connector *connector, · 74 unmodified lines
374}440}
375EXPORT_SYMBOL(drm_sysfs_connector_status_event);441EXPORT_SYMBOL(drm_sysfs_connector_status_event);
376 442
377static void drm_sysfs_release(struct device *dev)
378{
379 kfree(dev);
380}
381
382struct device *drm_sysfs_minor_alloc(struct drm_minor *minor)443struct device *drm_sysfs_minor_alloc(struct drm_minor *minor)
383{444{
384 const char *minor_str;445 const char *minor_str;
drivers/gpu/drm/etnaviv/etnaviv_sched.c+3−1
@@ -163,6 +163,8 @@ int etnaviv_sched_push_job(struct drm_sched_entity *sched_entity, · 162 unmodified lines
163 if (ret)163 if (ret)
164 goto out_unlock;164 goto out_unlock;
165 165
166 drm_sched_job_arm(&submit->sched_job);
167
166 submit->out_fence = dma_fence_get(&submit->sched_job.s_fence->finished);168 submit->out_fence = dma_fence_get(&submit->sched_job.s_fence->finished);
167 submit->out_fence_id = idr_alloc_cyclic(&submit->gpu->fence_idr,169 submit->out_fence_id = idr_alloc_cyclic(&submit->gpu->fence_idr,
168 submit->out_fence, 0,170 submit->out_fence, 0,
@@ -176,7 +178,7 @@ int etnaviv_sched_push_job(struct drm_sched_entity *sched_entity, · 7 unmodified lines
176 /* the scheduler holds on to the job now */178 /* the scheduler holds on to the job now */
177 kref_get(&submit->refcount);179 kref_get(&submit->refcount);
178 180
179 drm_sched_entity_push_job(&submit->sched_job, sched_entity);181 drm_sched_entity_push_job(&submit->sched_job);
180 182
181out_unlock:183out_unlock:
182 mutex_unlock(&submit->gpu->fence_lock);184 mutex_unlock(&submit->gpu->fence_lock);
drivers/gpu/drm/gud/Kconfig+1−1
@@ -2,7 +2,7 @@ · 1 unmodified line
2 2
3config DRM_GUD3config DRM_GUD
4 tristate "GUD USB Display"4 tristate "GUD USB Display"
5 depends on DRM && USB5 depends on DRM && USB && MMU
6 select LZ4_COMPRESS6 select LZ4_COMPRESS
7 select DRM_KMS_HELPER7 select DRM_KMS_HELPER
8 select DRM_GEM_SHMEM_HELPER8 select DRM_GEM_SHMEM_HELPER
drivers/gpu/drm/i915/gem/i915_gem_ttm.c+0−1
@@ -214,7 +214,6 @@ static void i915_ttm_tt_destroy(struct ttm_device *bdev, struct ttm_tt *ttm) · 213 unmodified lines
214{214{
215 struct i915_ttm_tt *i915_tt = container_of(ttm, typeof(*i915_tt), ttm);215 struct i915_ttm_tt *i915_tt = container_of(ttm, typeof(*i915_tt), ttm);
216 216
217 ttm_tt_destroy_common(bdev, ttm);
218 ttm_tt_fini(ttm);217 ttm_tt_fini(ttm);
219 kfree(i915_tt);218 kfree(i915_tt);
220}219}
drivers/gpu/drm/lima/lima_gem.c+5−4
@@ -267,7 +267,9 @@ static int lima_gem_sync_bo(struct lima_sched_task *task, struct lima_bo *bo, · 266 unmodified lines
267 if (explicit)267 if (explicit)
268 return 0;268 return 0;
269 269
270 return drm_gem_fence_array_add_implicit(&task->deps, &bo->base.base, write);270 return drm_sched_job_add_implicit_dependencies(&task->base,
271 &bo->base.base,
272 write);
271}273}
272 274
273static int lima_gem_add_deps(struct drm_file *file, struct lima_submit *submit)275static int lima_gem_add_deps(struct drm_file *file, struct lima_submit *submit)
@@ -285,7 +287,7 @@ static int lima_gem_add_deps(struct drm_file *file, struct lima_submit *submit) · 11 unmodified lines
285 if (err)287 if (err)
286 return err;288 return err;
287 289
288 err = drm_gem_fence_array_add(&submit->task->deps, fence);290 err = drm_sched_job_add_dependency(&submit->task->base, fence);
289 if (err) {291 if (err) {
290 dma_fence_put(fence);292 dma_fence_put(fence);
291 return err;293 return err;
@@ -359,8 +361,7 @@ int lima_gem_submit(struct drm_file *file, struct lima_submit *submit) · 67 unmodified lines
359 goto err_out2;361 goto err_out2;
360 }362 }
361 363
362 fence = lima_sched_context_queue_task(364 fence = lima_sched_context_queue_task(submit->task);
363 submit->ctx->context + submit->pipe, submit->task);
364 365
365 for (i = 0; i < submit->nr_bos; i++) {366 for (i = 0; i < submit->nr_bos; i++) {
366 if (submit->bos[i].flags & LIMA_SUBMIT_BO_WRITE)367 if (submit->bos[i].flags & LIMA_SUBMIT_BO_WRITE)
drivers/gpu/drm/lima/lima_sched.c+4−24
@@ -129,27 +129,20 @@ int lima_sched_task_init(struct lima_sched_task *task, · 128 unmodified lines
129 return err;129 return err;
130 }130 }
131 131
132 drm_sched_job_arm(&task->base);
133
132 task->num_bos = num_bos;134 task->num_bos = num_bos;
133 task->vm = lima_vm_get(vm);135 task->vm = lima_vm_get(vm);
134 136
135 xa_init_flags(&task->deps, XA_FLAGS_ALLOC);
136
137 return 0;137 return 0;
138}138}
139 139
140void lima_sched_task_fini(struct lima_sched_task *task)140void lima_sched_task_fini(struct lima_sched_task *task)
141{141{
142 struct dma_fence *fence;
143 unsigned long index;
144 int i;142 int i;
145 143
146 drm_sched_job_cleanup(&task->base);144 drm_sched_job_cleanup(&task->base);
147 145
148 xa_for_each(&task->deps, index, fence) {
149 dma_fence_put(fence);
150 }
151 xa_destroy(&task->deps);
152
153 if (task->bos) {146 if (task->bos) {
154 for (i = 0; i < task->num_bos; i++)147 for (i = 0; i < task->num_bos; i++)
155 drm_gem_object_put(&task->bos[i]->base.base);148 drm_gem_object_put(&task->bos[i]->base.base);
@@ -175,27 +168,15 @@ void lima_sched_context_fini(struct lima_sched_pipe *pipe, · 19 unmodified lines
175 drm_sched_entity_fini(&context->base);168 drm_sched_entity_fini(&context->base);
176}169}
177 170
178struct dma_fence *lima_sched_context_queue_task(struct lima_sched_context *context,171struct dma_fence *lima_sched_context_queue_task(struct lima_sched_task *task)
179 struct lima_sched_task *task)
180{172{
181 struct dma_fence *fence = dma_fence_get(&task->base.s_fence->finished);173 struct dma_fence *fence = dma_fence_get(&task->base.s_fence->finished);
182 174
183 trace_lima_task_submit(task);175 trace_lima_task_submit(task);
184 drm_sched_entity_push_job(&task->base, &context->base);176 drm_sched_entity_push_job(&task->base);
185 return fence;177 return fence;
186}178}
187 179
188static struct dma_fence *lima_sched_dependency(struct drm_sched_job *job,
189 struct drm_sched_entity *entity)
190{
191 struct lima_sched_task *task = to_lima_task(job);
192
193 if (!xa_empty(&task->deps))
194 return xa_erase(&task->deps, task->last_dep++);
195
196 return NULL;
197}
198
199static int lima_pm_busy(struct lima_device *ldev)180static int lima_pm_busy(struct lima_device *ldev)
200{181{
201 int ret;182 int ret;
@@ -471,7 +452,6 @@ static void lima_sched_free_job(struct drm_sched_job *job) · 269 unmodified lines
471}452}
472 453
473static const struct drm_sched_backend_ops lima_sched_ops = {454static const struct drm_sched_backend_ops lima_sched_ops = {
474 .dependency = lima_sched_dependency,
475 .run_job = lima_sched_run_job,455 .run_job = lima_sched_run_job,
476 .timedout_job = lima_sched_timedout_job,456 .timedout_job = lima_sched_timedout_job,
477 .free_job = lima_sched_free_job,457 .free_job = lima_sched_free_job,
drivers/gpu/drm/lima/lima_sched.h+1−5
@@ -23,9 +23,6 @@ struct lima_sched_task { · 22 unmodified lines
23 struct lima_vm *vm;23 struct lima_vm *vm;
24 void *frame;24 void *frame;
25 25
26 struct xarray deps;
27 unsigned long last_dep;
28
29 struct lima_bo **bos;26 struct lima_bo **bos;
30 int num_bos;27 int num_bos;
31 28
@@ -98,8 +95,7 @@ int lima_sched_context_init(struct lima_sched_pipe *pipe, · 66 unmodified lines
98 atomic_t *guilty);95 atomic_t *guilty);
99void lima_sched_context_fini(struct lima_sched_pipe *pipe,96void lima_sched_context_fini(struct lima_sched_pipe *pipe,
100 struct lima_sched_context *context);97 struct lima_sched_context *context);
101struct dma_fence *lima_sched_context_queue_task(struct lima_sched_context *context,98struct dma_fence *lima_sched_context_queue_task(struct lima_sched_task *task);
102 struct lima_sched_task *task);
103 99
104int lima_sched_pipe_init(struct lima_sched_pipe *pipe, const char *name);100int lima_sched_pipe_init(struct lima_sched_pipe *pipe, const char *name);
105void lima_sched_pipe_fini(struct lima_sched_pipe *pipe);101void lima_sched_pipe_fini(struct lima_sched_pipe *pipe);
drivers/gpu/drm/mcde/mcde_drv.c+1−3
@@ -276,7 +276,6 @@ static int mcde_probe(struct platform_device *pdev) · 275 unmodified lines
276 struct drm_device *drm;276 struct drm_device *drm;
277 struct mcde *mcde;277 struct mcde *mcde;
278 struct component_match *match = NULL;278 struct component_match *match = NULL;
279 struct resource *res;
280 u32 pid;279 u32 pid;
281 int irq;280 int irq;
282 int ret;281 int ret;
@@ -344,8 +343,7 @@ static int mcde_probe(struct platform_device *pdev) · 61 unmodified lines
344 goto clk_disable;343 goto clk_disable;
345 }344 }
346 345
347 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);346 mcde->regs = devm_platform_ioremap_resource(pdev, 0);
348 mcde->regs = devm_ioremap_resource(dev, res);
349 if (IS_ERR(mcde->regs)) {347 if (IS_ERR(mcde->regs)) {
350 dev_err(dev, "no MCDE regs\n");348 dev_err(dev, "no MCDE regs\n");
351 ret = -EINVAL;349 ret = -EINVAL;
drivers/gpu/drm/mcde/mcde_dsi.c+1−3
@@ -1169,7 +1169,6 @@ static int mcde_dsi_probe(struct platform_device *pdev) · 1168 unmodified lines
1169 struct device *dev = &pdev->dev;1169 struct device *dev = &pdev->dev;
1170 struct mcde_dsi *d;1170 struct mcde_dsi *d;
1171 struct mipi_dsi_host *host;1171 struct mipi_dsi_host *host;
1172 struct resource *res;
1173 u32 dsi_id;1172 u32 dsi_id;
1174 int ret;1173 int ret;
1175 1174
@@ -1187,8 +1186,7 @@ static int mcde_dsi_probe(struct platform_device *pdev) · 11 unmodified lines
1187 return PTR_ERR(d->prcmu);1186 return PTR_ERR(d->prcmu);
1188 }1187 }
1189 1188
1190 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);1189 d->regs = devm_platform_ioremap_resource(pdev, 0);
1191 d->regs = devm_ioremap_resource(dev, res);
1192 if (IS_ERR(d->regs))1190 if (IS_ERR(d->regs))
1193 return PTR_ERR(d->regs);1191 return PTR_ERR(d->regs);
1194 1192
drivers/gpu/drm/meson/meson_drv.c+1−2
@@ -206,8 +206,7 @@ static int meson_drv_bind_master(struct device *dev, bool has_components) · 205 unmodified lines
206 priv->compat = match->compat;206 priv->compat = match->compat;
207 priv->afbcd.ops = match->afbcd_ops;207 priv->afbcd.ops = match->afbcd_ops;
208 208
209 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "vpu");209 regs = devm_platform_ioremap_resource_byname(pdev, "vpu");
210 regs = devm_ioremap_resource(dev, res);
211 if (IS_ERR(regs)) {210 if (IS_ERR(regs)) {
212 ret = PTR_ERR(regs);211 ret = PTR_ERR(regs);
213 goto free_drm;212 goto free_drm;
drivers/gpu/drm/meson/meson_dw_hdmi.c+1−3
@@ -978,7 +978,6 @@ static int meson_dw_hdmi_bind(struct device *dev, struct device *master, · 977 unmodified lines
978 struct dw_hdmi_plat_data *dw_plat_data;978 struct dw_hdmi_plat_data *dw_plat_data;
979 struct drm_bridge *next_bridge;979 struct drm_bridge *next_bridge;
980 struct drm_encoder *encoder;980 struct drm_encoder *encoder;
981 struct resource *res;
982 int irq;981 int irq;
983 int ret;982 int ret;
984 983
@@ -1042,8 +1041,7 @@ static int meson_dw_hdmi_bind(struct device *dev, struct device *master, · 57 unmodified lines
1042 return PTR_ERR(meson_dw_hdmi->hdmitx_phy);1041 return PTR_ERR(meson_dw_hdmi->hdmitx_phy);
1043 }1042 }
1044 1043
1045 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);1044 meson_dw_hdmi->hdmitx = devm_platform_ioremap_resource(pdev, 0);
1046 meson_dw_hdmi->hdmitx = devm_ioremap_resource(dev, res);
1047 if (IS_ERR(meson_dw_hdmi->hdmitx))1045 if (IS_ERR(meson_dw_hdmi->hdmitx))
1048 return PTR_ERR(meson_dw_hdmi->hdmitx);1046 return PTR_ERR(meson_dw_hdmi->hdmitx);
1049 1047
drivers/gpu/drm/msm/msm_gem.h+0−5
@@ -309,11 +309,6 @@ struct msm_gem_submit { · 308 unmodified lines
309 struct ww_acquire_ctx ticket;309 struct ww_acquire_ctx ticket;
310 uint32_t seqno; /* Sequence number of the submit on the ring */310 uint32_t seqno; /* Sequence number of the submit on the ring */
311 311
312 /* Array of struct dma_fence * to block on before submitting this job.
313 */
314 struct xarray deps;
315 unsigned long last_dep;
316
317 /* Hw fence, which is created when the scheduler executes the job, and312 /* Hw fence, which is created when the scheduler executes the job, and
318 * is signaled when the hw finishes (via seqno write from cmdstream)313 * is signaled when the hw finishes (via seqno write from cmdstream)
319 */314 */
drivers/gpu/drm/msm/msm_gem_submit.c+14−21
@@ -52,8 +52,6 @@ static struct msm_gem_submit *submit_create(struct drm_device *dev, · 51 unmodified lines
52 return ERR_PTR(ret);52 return ERR_PTR(ret);
53 }53 }
54 54
55 xa_init_flags(&submit->deps, XA_FLAGS_ALLOC);
56
57 kref_init(&submit->ref);55 kref_init(&submit->ref);
58 submit->dev = dev;56 submit->dev = dev;
59 submit->aspace = queue->ctx->aspace;57 submit->aspace = queue->ctx->aspace;
@@ -72,8 +70,6 @@ void __msm_gem_submit_destroy(struct kref *kref) · 12 unmodified lines
72{70{
73 struct msm_gem_submit *submit =71 struct msm_gem_submit *submit =
74 container_of(kref, struct msm_gem_submit, ref);72 container_of(kref, struct msm_gem_submit, ref);
75 unsigned long index;
76 struct dma_fence *fence;
77 unsigned i;73 unsigned i;
78 74
79 if (submit->fence_id) {75 if (submit->fence_id) {
@@ -82,12 +78,6 @@ void __msm_gem_submit_destroy(struct kref *kref) · 2 unmodified lines
82 mutex_unlock(&submit->queue->lock);78 mutex_unlock(&submit->queue->lock);
83 }79 }
84 80
85 xa_for_each (&submit->deps, index, fence) {
86 dma_fence_put(fence);
87 }
88
89 xa_destroy(&submit->deps);
90
91 dma_fence_put(submit->user_fence);81 dma_fence_put(submit->user_fence);
92 dma_fence_put(submit->hw_fence);82 dma_fence_put(submit->hw_fence);
93 83
@@ -340,11 +330,13 @@ static int submit_fence_sync(struct msm_gem_submit *submit, bool no_implicit) · 246 unmodified lines
340 return ret;330 return ret;
341 }331 }
342 332
343 if (no_implicit)333 /* exclusive fences must be ordered */
334 if (no_implicit && !write)
344 continue;335 continue;
345 336
346 ret = drm_gem_fence_array_add_implicit(&submit->deps, obj,337 ret = drm_sched_job_add_implicit_dependencies(&submit->base,
347 write);338 obj,
339 write);
348 if (ret)340 if (ret)
349 break;341 break;
350 }342 }
@@ -588,7 +580,7 @@ static struct drm_syncobj **msm_parse_deps(struct msm_gem_submit *submit, · 237 unmodified lines
588 if (ret)580 if (ret)
589 break;581 break;
590 582
591 ret = drm_gem_fence_array_add(&submit->deps, fence);583 ret = drm_sched_job_add_dependency(&submit->base, fence);
592 if (ret)584 if (ret)
593 break;585 break;
594 586
@@ -798,7 +790,7 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data, · 203 unmodified lines
798 goto out_unlock;790 goto out_unlock;
799 }791 }
800 792
801 ret = drm_gem_fence_array_add(&submit->deps, in_fence);793 ret = drm_sched_job_add_dependency(&submit->base, in_fence);
802 if (ret)794 if (ret)
803 goto out_unlock;795 goto out_unlock;
804 }796 }
@@ -878,6 +870,8 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data, · 73 unmodified lines
878 870
879 submit->nr_cmds = i;871 submit->nr_cmds = i;
880 872
873 drm_sched_job_arm(&submit->base);
874
881 submit->user_fence = dma_fence_get(&submit->base.s_fence->finished);875 submit->user_fence = dma_fence_get(&submit->base.s_fence->finished);
882 876
883 /*877 /*
@@ -889,17 +883,16 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data, · 5 unmodified lines
889 if (submit->fence_id < 0) {883 if (submit->fence_id < 0) {
890 ret = submit->fence_id = 0;884 ret = submit->fence_id = 0;
891 submit->fence_id = 0;885 submit->fence_id = 0;
892 goto out;
893 }886 }
894 887
895 if (args->flags & MSM_SUBMIT_FENCE_FD_OUT) {888 if (ret == 0 && args->flags & MSM_SUBMIT_FENCE_FD_OUT) {
896 struct sync_file *sync_file = sync_file_create(submit->user_fence);889 struct sync_file *sync_file = sync_file_create(submit->user_fence);
897 if (!sync_file) {890 if (!sync_file) {
898 ret = -ENOMEM;891 ret = -ENOMEM;
899 goto out;892 } else {
893 fd_install(out_fence_fd, sync_file->file);
894 args->fence_fd = out_fence_fd;
900 }895 }
901 fd_install(out_fence_fd, sync_file->file);
902 args->fence_fd = out_fence_fd;
903 }896 }
904 897
905 submit_attach_object_fences(submit);898 submit_attach_object_fences(submit);
@@ -907,7 +900,7 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data, · 1 unmodified line
907 /* The scheduler owns a ref now: */900 /* The scheduler owns a ref now: */
908 msm_gem_submit_get(submit);901 msm_gem_submit_get(submit);
909 902
910 drm_sched_entity_push_job(&submit->base, &queue->entity);903 drm_sched_entity_push_job(&submit->base);
911 904
912 args->fence = submit->fence_id;905 args->fence = submit->fence_id;
913 906
drivers/gpu/drm/msm/msm_ringbuffer.c+0−12
@@ -11,17 +11,6 @@ static uint num_hw_submissions = 8; · 10 unmodified lines
11MODULE_PARM_DESC(num_hw_submissions, "The max # of jobs to write into ringbuffer (default 8)");11MODULE_PARM_DESC(num_hw_submissions, "The max # of jobs to write into ringbuffer (default 8)");
12module_param(num_hw_submissions, uint, 0600);12module_param(num_hw_submissions, uint, 0600);
13 13
14static struct dma_fence *msm_job_dependency(struct drm_sched_job *job,
15 struct drm_sched_entity *s_entity)
16{
17 struct msm_gem_submit *submit = to_msm_submit(job);
18
19 if (!xa_empty(&submit->deps))
20 return xa_erase(&submit->deps, submit->last_dep++);
21
22 return NULL;
23}
24
25static struct dma_fence *msm_job_run(struct drm_sched_job *job)14static struct dma_fence *msm_job_run(struct drm_sched_job *job)
26{15{
27 struct msm_gem_submit *submit = to_msm_submit(job);16 struct msm_gem_submit *submit = to_msm_submit(job);
@@ -52,7 +41,6 @@ static void msm_job_free(struct drm_sched_job *job) · 24 unmodified lines
52}41}
53 42
54const struct drm_sched_backend_ops msm_sched_ops = {43const struct drm_sched_backend_ops msm_sched_ops = {
55 .dependency = msm_job_dependency,
56 .run_job = msm_job_run,44 .run_job = msm_job_run,
57 .free_job = msm_job_free45 .free_job = msm_job_free
58};46};
drivers/gpu/drm/nouveau/nouveau_bo.c+2−2
@@ -1277,6 +1277,8 @@ nouveau_ttm_tt_unpopulate(struct ttm_device *bdev, · 1276 unmodified lines
1277 if (slave)1277 if (slave)
1278 return;1278 return;
1279 1279
1280 nouveau_ttm_tt_unbind(bdev, ttm);
1281
1280 drm = nouveau_bdev(bdev);1282 drm = nouveau_bdev(bdev);
1281 dev = drm->dev->dev;1283 dev = drm->dev->dev;
1282 1284
@@ -1290,8 +1292,6 @@ nouveau_ttm_tt_destroy(struct ttm_device *bdev, · 7 unmodified lines
1290#if IS_ENABLED(CONFIG_AGP)1292#if IS_ENABLED(CONFIG_AGP)
1291 struct nouveau_drm *drm = nouveau_bdev(bdev);1293 struct nouveau_drm *drm = nouveau_bdev(bdev);
1292 if (drm->agp.bridge) {1294 if (drm->agp.bridge) {
1293 ttm_agp_unbind(ttm);
1294 ttm_tt_destroy_common(bdev, ttm);
1295 ttm_agp_destroy(ttm);1295 ttm_agp_destroy(ttm);
1296 return;1296 return;
1297 }1297 }
drivers/gpu/drm/nouveau/nouveau_sgdma.c+0−2
@@ -21,8 +21,6 @@ nouveau_sgdma_destroy(struct ttm_device *bdev, struct ttm_tt *ttm) · 20 unmodified lines
21 struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)ttm;21 struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)ttm;
22 22
23 if (ttm) {23 if (ttm) {
24 nouveau_sgdma_unbind(bdev, ttm);
25 ttm_tt_destroy_common(bdev, ttm);
26 ttm_tt_fini(&nvbe->ttm);24 ttm_tt_fini(&nvbe->ttm);
27 kfree(nvbe);25 kfree(nvbe);
28 }26 }
drivers/gpu/drm/omapdrm/Kconfig+0−1
@@ -3,7 +3,6 @@ config DRM_OMAP · 2 unmodified lines
3 tristate "OMAP DRM"3 tristate "OMAP DRM"
4 depends on DRM4 depends on DRM
5 depends on ARCH_OMAP2PLUS || ARCH_MULTIPLATFORM5 depends on ARCH_OMAP2PLUS || ARCH_MULTIPLATFORM
6 select OMAP2_DSS
7 select DRM_KMS_HELPER6 select DRM_KMS_HELPER
8 select VIDEOMODE_HELPERS7 select VIDEOMODE_HELPERS
9 select HDMI8 select HDMI
drivers/gpu/drm/panel/Kconfig+11−0
@@ -392,6 +392,17 @@ config DRM_PANEL_SAMSUNG_S6D16D0 · 391 unmodified lines
392 depends on DRM_MIPI_DSI392 depends on DRM_MIPI_DSI
393 select VIDEOMODE_HELPERS393 select VIDEOMODE_HELPERS
394 394
395config DRM_PANEL_SAMSUNG_S6D27A1
396 tristate "Samsung S6D27A1 DPI panel driver"
397 depends on OF && SPI && GPIOLIB
398 select DRM_MIPI_DBI
399 help
400 Say Y here if you want to enable support for the Samsung
401 S6D27A1 DPI 480x800 panel.
402
403 This panel can be found in Samsung Galaxy Ace 2
404 GT-I8160 mobile phone.
405
395config DRM_PANEL_SAMSUNG_S6E3HA2406config DRM_PANEL_SAMSUNG_S6E3HA2
396 tristate "Samsung S6E3HA2 DSI video mode panel"407 tristate "Samsung S6E3HA2 DSI video mode panel"
397 depends on OF408 depends on OF
drivers/gpu/drm/panel/Makefile+1−0
@@ -39,6 +39,7 @@ obj-$(CONFIG_DRM_PANEL_SAMSUNG_ATNA33XC20) += panel-samsung-atna33xc20.o · 38 unmodified lines
39obj-$(CONFIG_DRM_PANEL_SAMSUNG_DB7430) += panel-samsung-db7430.o39obj-$(CONFIG_DRM_PANEL_SAMSUNG_DB7430) += panel-samsung-db7430.o
40obj-$(CONFIG_DRM_PANEL_SAMSUNG_LD9040) += panel-samsung-ld9040.o40obj-$(CONFIG_DRM_PANEL_SAMSUNG_LD9040) += panel-samsung-ld9040.o
41obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6D16D0) += panel-samsung-s6d16d0.o41obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6D16D0) += panel-samsung-s6d16d0.o
42obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6D27A1) += panel-samsung-s6d27a1.o
42obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E3HA2) += panel-samsung-s6e3ha2.o43obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E3HA2) += panel-samsung-s6e3ha2.o
43obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E63J0X03) += panel-samsung-s6e63j0x03.o44obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E63J0X03) += panel-samsung-s6e63j0x03.o
44obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E63M0) += panel-samsung-s6e63m0.o45obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E63M0) += panel-samsung-s6e63m0.o
drivers/gpu/drm/panel/panel-orisetech-otm8009a.c+56−29
@@ -60,6 +60,9 @@ · 59 unmodified lines
60#define MCS_CMD2_ENA1 0xFF00 /* Enable Access Command2 "CMD2" */60#define MCS_CMD2_ENA1 0xFF00 /* Enable Access Command2 "CMD2" */
61#define MCS_CMD2_ENA2 0xFF80 /* Enable Access Orise Command2 */61#define MCS_CMD2_ENA2 0xFF80 /* Enable Access Orise Command2 */
62 62
63#define OTM8009A_HDISPLAY 480
64#define OTM8009A_VDISPLAY 800
65
63struct otm8009a {66struct otm8009a {
64 struct device *dev;67 struct device *dev;
65 struct drm_panel panel;68 struct drm_panel panel;
@@ -70,19 +73,35 @@ struct otm8009a { · 4 unmodified lines
70 bool enabled;73 bool enabled;
71};74};
72 75
73static const struct drm_display_mode default_mode = {76static const struct drm_display_mode modes[] = {
74 .clock = 29700,77 { /* 50 Hz, preferred */
75 .hdisplay = 480,78 .clock = 29700,
76 .hsync_start = 480 + 98,79 .hdisplay = 480,
77 .hsync_end = 480 + 98 + 32,80 .hsync_start = 480 + 98,
78 .htotal = 480 + 98 + 32 + 98,81 .hsync_end = 480 + 98 + 32,
79 .vdisplay = 800,82 .htotal = 480 + 98 + 32 + 98,
80 .vsync_start = 800 + 15,83 .vdisplay = 800,
81 .vsync_end = 800 + 15 + 10,84 .vsync_start = 800 + 15,
82 .vtotal = 800 + 15 + 10 + 14,85 .vsync_end = 800 + 15 + 10,
83 .flags = 0,86 .vtotal = 800 + 15 + 10 + 14,
84 .width_mm = 52,87 .flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC,
85 .height_mm = 86,88 .width_mm = 52,
89 .height_mm = 86,
90 },
91 { /* 60 Hz */
92 .clock = 33000,
93 .hdisplay = 480,
94 .hsync_start = 480 + 70,
95 .hsync_end = 480 + 70 + 32,
96 .htotal = 480 + 70 + 32 + 72,
97 .vdisplay = 800,
98 .vsync_start = 800 + 15,
99 .vsync_end = 800 + 15 + 10,
100 .vtotal = 800 + 15 + 10 + 16,
101 .flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC,
102 .width_mm = 52,
103 .height_mm = 86,
104 },
86};105};
87 106
88static inline struct otm8009a *panel_to_otm8009a(struct drm_panel *panel)107static inline struct otm8009a *panel_to_otm8009a(struct drm_panel *panel)
@@ -208,12 +227,11 @@ static int otm8009a_init_sequence(struct otm8009a *ctx) · 119 unmodified lines
208 /* Default portrait 480x800 rgb24 */227 /* Default portrait 480x800 rgb24 */
209 dcs_write_seq(ctx, MIPI_DCS_SET_ADDRESS_MODE, 0x00);228 dcs_write_seq(ctx, MIPI_DCS_SET_ADDRESS_MODE, 0x00);
210 229
211 ret = mipi_dsi_dcs_set_column_address(dsi, 0,230 ret = mipi_dsi_dcs_set_column_address(dsi, 0, OTM8009A_HDISPLAY - 1);
212 default_mode.hdisplay - 1);
213 if (ret)231 if (ret)
214 return ret;232 return ret;
215 233
216 ret = mipi_dsi_dcs_set_page_address(dsi, 0, default_mode.vdisplay - 1);234 ret = mipi_dsi_dcs_set_page_address(dsi, 0, OTM8009A_VDISPLAY - 1);
217 if (ret)235 if (ret)
218 return ret;236 return ret;
219 237
@@ -337,24 +355,33 @@ static int otm8009a_get_modes(struct drm_panel *panel, · 117 unmodified lines
337 struct drm_connector *connector)355 struct drm_connector *connector)
338{356{
339 struct drm_display_mode *mode;357 struct drm_display_mode *mode;
340 358 unsigned int num_modes = ARRAY_SIZE(modes);
341 mode = drm_mode_duplicate(connector->dev, &default_mode);359 unsigned int i;
342 if (!mode) {360
343 dev_err(panel->dev, "failed to add mode %ux%u@%u\n",361 for (i = 0; i < num_modes; i++) {
344 default_mode.hdisplay, default_mode.vdisplay,362 mode = drm_mode_duplicate(connector->dev, &modes[i]);
345 drm_mode_vrefresh(&default_mode));363 if (!mode) {
346 return -ENOMEM;364 dev_err(panel->dev, "failed to add mode %ux%u@%u\n",
365 modes[i].hdisplay,
366 modes[i].vdisplay,
367 drm_mode_vrefresh(&modes[i]));
368 return -ENOMEM;
369 }
370
371 mode->type = DRM_MODE_TYPE_DRIVER;
372
373 /* Setting first mode as preferred */
374 if (!i)
375 mode->type |= DRM_MODE_TYPE_PREFERRED;
376
377 drm_mode_set_name(mode);
378 drm_mode_probed_add(connector, mode);
347 }379 }
348 380
349 drm_mode_set_name(mode);
350
351 mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
352 drm_mode_probed_add(connector, mode);
353
354 connector->display_info.width_mm = mode->width_mm;381 connector->display_info.width_mm = mode->width_mm;
355 connector->display_info.height_mm = mode->height_mm;382 connector->display_info.height_mm = mode->height_mm;
356 383
357 return 1;384 return num_modes;
358}385}
359 386
360static const struct drm_panel_funcs otm8009a_drm_funcs = {387static const struct drm_panel_funcs otm8009a_drm_funcs = {
drivers/gpu/drm/panel/panel-samsung-s6d27a1.c+320−0
@@ -0,0 +1,320 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Panel driver for the Samsung S6D27A1 480x800 DPI RGB panel.
4 * Found in the Samsung Galaxy Ace 2 GT-I8160 mobile phone.
5 */
6
7#include <drm/drm_mipi_dbi.h>
8#include <drm/drm_modes.h>
9#include <drm/drm_panel.h>
10
11#include <linux/delay.h>
12#include <linux/gpio/consumer.h>
13#include <linux/init.h>
14#include <linux/kernel.h>
15#include <linux/media-bus-format.h>
16#include <linux/module.h>
17#include <linux/of.h>
18#include <linux/regulator/consumer.h>
19#include <linux/spi/spi.h>
20
21#include <video/mipi_display.h>
22
23#define S6D27A1_PASSWD_L2 0xF0 /* Password Command for Level 2 Control */
24#define S6D27A1_RESCTL 0xB3 /* Resolution Select Control */
25#define S6D27A1_PANELCTL2 0xB4 /* ASG Signal Control */
26#define S6D27A1_READID1 0xDA /* Read panel ID 1 */
27#define S6D27A1_READID2 0xDB /* Read panel ID 2 */
28#define S6D27A1_READID3 0xDC /* Read panel ID 3 */
29#define S6D27A1_DISPCTL 0xF2 /* Display Control */
30#define S6D27A1_MANPWR 0xF3 /* Manual Control */
31#define S6D27A1_PWRCTL1 0xF4 /* Power Control */
32#define S6D27A1_SRCCTL 0xF6 /* Source Control */
33#define S6D27A1_PANELCTL 0xF7 /* Panel Control*/
34
35static const u8 s6d27a1_dbi_read_commands[] = {
36 S6D27A1_READID1,
37 S6D27A1_READID2,
38 S6D27A1_READID3,
39 0, /* sentinel */
40};
41
42struct s6d27a1 {
43 struct device *dev;
44 struct mipi_dbi dbi;
45 struct drm_panel panel;
46 struct gpio_desc *reset;
47 struct regulator_bulk_data regulators[2];
48};
49
50static const struct drm_display_mode s6d27a1_480_800_mode = {
51 /*
52 * The vendor driver states that the S6D27A1 panel
53 * has a pixel clock frequency of 49920000 Hz / 2 = 24960000 Hz.
54 */
55 .clock = 24960,
56 .hdisplay = 480,
57 .hsync_start = 480 + 63,
58 .hsync_end = 480 + 63 + 2,
59 .htotal = 480 + 63 + 2 + 63,
60 .vdisplay = 800,
61 .vsync_start = 800 + 11,
62 .vsync_end = 800 + 11 + 2,
63 .vtotal = 800 + 11 + 2 + 10,
64 .width_mm = 50,
65 .height_mm = 84,
66 .flags = DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC,
67};
68
69static inline struct s6d27a1 *to_s6d27a1(struct drm_panel *panel)
70{
71 return container_of(panel, struct s6d27a1, panel);
72}
73
74static void s6d27a1_read_mtp_id(struct s6d27a1 *ctx)
75{
76 struct mipi_dbi *dbi = &ctx->dbi;
77 u8 id1, id2, id3;
78 int ret;
79
80 ret = mipi_dbi_command_read(dbi, S6D27A1_READID1, &id1);
81 if (ret) {
82 dev_err(ctx->dev, "unable to read MTP ID 1\n");
83 return;
84 }
85 ret = mipi_dbi_command_read(dbi, S6D27A1_READID2, &id2);
86 if (ret) {
87 dev_err(ctx->dev, "unable to read MTP ID 2\n");
88 return;
89 }
90 ret = mipi_dbi_command_read(dbi, S6D27A1_READID3, &id3);
91 if (ret) {
92 dev_err(ctx->dev, "unable to read MTP ID 3\n");
93 return;
94 }
95 dev_info(ctx->dev, "MTP ID: %02x %02x %02x\n", id1, id2, id3);
96}
97
98static int s6d27a1_power_on(struct s6d27a1 *ctx)
99{
100 struct mipi_dbi *dbi = &ctx->dbi;
101 int ret;
102
103 /* Power up */
104 ret = regulator_bulk_enable(ARRAY_SIZE(ctx->regulators),
105 ctx->regulators);
106 if (ret) {
107 dev_err(ctx->dev, "failed to enable regulators: %d\n", ret);
108 return ret;
109 }
110
111 msleep(20);
112
113 /* Assert reset >=1 ms */
114 gpiod_set_value_cansleep(ctx->reset, 1);
115 usleep_range(1000, 5000);
116 /* De-assert reset */
117 gpiod_set_value_cansleep(ctx->reset, 0);
118 /* Wait >= 10 ms */
119 msleep(20);
120
121 /*
122 * Exit sleep mode and initialize display - some hammering is
123 * necessary.
124 */
125 mipi_dbi_command(dbi, MIPI_DCS_EXIT_SLEEP_MODE);
126 mipi_dbi_command(dbi, MIPI_DCS_EXIT_SLEEP_MODE);
127 msleep(120);
128
129 /* Magic to unlock level 2 control of the display */
130 mipi_dbi_command(dbi, S6D27A1_PASSWD_L2, 0x5A, 0x5A);
131
132 /* Configure resolution to 480RGBx800 */
133 mipi_dbi_command(dbi, S6D27A1_RESCTL, 0x22);
134
135 mipi_dbi_command(dbi, S6D27A1_PANELCTL2, 0x00, 0x02, 0x03, 0x04, 0x05, 0x08, 0x00, 0x0c);
136
137 mipi_dbi_command(dbi, S6D27A1_MANPWR, 0x01, 0x00, 0x00, 0x08, 0x08, 0x02, 0x00);
138
139 mipi_dbi_command(dbi, S6D27A1_DISPCTL, 0x19, 0x00, 0x08, 0x0D, 0x03, 0x41, 0x3F);
140
141 mipi_dbi_command(dbi, S6D27A1_PWRCTL1, 0x00, 0x00, 0x00, 0x00, 0x55,
142 0x44, 0x05, 0x88, 0x4B, 0x50);
143
144 mipi_dbi_command(dbi, S6D27A1_SRCCTL, 0x03, 0x09, 0x8A, 0x00, 0x01, 0x16);
145
146 mipi_dbi_command(dbi, S6D27A1_PANELCTL, 0x00, 0x05, 0x06, 0x07, 0x08,
147 0x01, 0x09, 0x0D, 0x0A, 0x0E,
148 0x0B, 0x0F, 0x0C, 0x10, 0x01,
149 0x11, 0x12, 0x13, 0x14, 0x05,
150 0x06, 0x07, 0x08, 0x01, 0x09,
151 0x0D, 0x0A, 0x0E, 0x0B, 0x0F,
152 0x0C, 0x10, 0x01, 0x11, 0x12,
153 0x13, 0x14);
154
155 /* lock the level 2 control */
156 mipi_dbi_command(dbi, S6D27A1_PASSWD_L2, 0xA5, 0xA5);
157
158 s6d27a1_read_mtp_id(ctx);
159
160 return 0;
161}
162
163static int s6d27a1_power_off(struct s6d27a1 *ctx)
164{
165 /* Go into RESET and disable regulators */
166 gpiod_set_value_cansleep(ctx->reset, 1);
167 return regulator_bulk_disable(ARRAY_SIZE(ctx->regulators),
168 ctx->regulators);
169}
170
171static int s6d27a1_unprepare(struct drm_panel *panel)
172{
173 struct s6d27a1 *ctx = to_s6d27a1(panel);
174 struct mipi_dbi *dbi = &ctx->dbi;
175
176 mipi_dbi_command(dbi, MIPI_DCS_ENTER_SLEEP_MODE);
177 msleep(120);
178 return s6d27a1_power_off(to_s6d27a1(panel));
179}
180
181static int s6d27a1_disable(struct drm_panel *panel)
182{
183 struct s6d27a1 *ctx = to_s6d27a1(panel);
184 struct mipi_dbi *dbi = &ctx->dbi;
185
186 mipi_dbi_command(dbi, MIPI_DCS_SET_DISPLAY_OFF);
187 msleep(25);
188
189 return 0;
190}
191
192static int s6d27a1_prepare(struct drm_panel *panel)
193{
194 return s6d27a1_power_on(to_s6d27a1(panel));
195}
196
197static int s6d27a1_enable(struct drm_panel *panel)
198{
199 struct s6d27a1 *ctx = to_s6d27a1(panel);
200 struct mipi_dbi *dbi = &ctx->dbi;
201
202 mipi_dbi_command(dbi, MIPI_DCS_SET_DISPLAY_ON);
203
204 return 0;
205}
206
207static int s6d27a1_get_modes(struct drm_panel *panel,
208 struct drm_connector *connector)
209{
210 struct s6d27a1 *ctx = to_s6d27a1(panel);
211 struct drm_display_mode *mode;
212 static const u32 bus_format = MEDIA_BUS_FMT_RGB888_1X24;
213
214 mode = drm_mode_duplicate(connector->dev, &s6d27a1_480_800_mode);
215 if (!mode) {
216 dev_err(ctx->dev, "failed to add mode\n");
217 return -ENOMEM;
218 }
219
220 connector->display_info.bpc = 8;
221 connector->display_info.width_mm = mode->width_mm;
222 connector->display_info.height_mm = mode->height_mm;
223 connector->display_info.bus_flags =
224 DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE;
225 drm_display_info_set_bus_formats(&connector->display_info,
226 &bus_format, 1);
227
228 drm_mode_set_name(mode);
229 mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
230
231 drm_mode_probed_add(connector, mode);
232
233 return 1;
234}
235
236static const struct drm_panel_funcs s6d27a1_drm_funcs = {
237 .disable = s6d27a1_disable,
238 .unprepare = s6d27a1_unprepare,
239 .prepare = s6d27a1_prepare,
240 .enable = s6d27a1_enable,
241 .get_modes = s6d27a1_get_modes,
242};
243
244static int s6d27a1_probe(struct spi_device *spi)
245{
246 struct device *dev = &spi->dev;
247 struct s6d27a1 *ctx;
248 int ret;
249
250 ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
251 if (!ctx)
252 return -ENOMEM;
253
254 ctx->dev = dev;
255
256 /*
257 * VCI is the analog voltage supply
258 * VCCIO is the digital I/O voltage supply
259 */
260 ctx->regulators[0].supply = "vci";
261 ctx->regulators[1].supply = "vccio";
262 ret = devm_regulator_bulk_get(dev,
263 ARRAY_SIZE(ctx->regulators),
264 ctx->regulators);
265 if (ret)
266 return dev_err_probe(dev, ret, "failed to get regulators\n");
267
268 ctx->reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
269 if (IS_ERR(ctx->reset)) {
270 ret = PTR_ERR(ctx->reset);
271 return dev_err_probe(dev, ret, "no RESET GPIO\n");
272 }
273
274 ret = mipi_dbi_spi_init(spi, &ctx->dbi, NULL);
275 if (ret)
276 return dev_err_probe(dev, ret, "MIPI DBI init failed\n");
277
278 ctx->dbi.read_commands = s6d27a1_dbi_read_commands;
279
280 drm_panel_init(&ctx->panel, dev, &s6d27a1_drm_funcs,
281 DRM_MODE_CONNECTOR_DPI);
282
283 ret = drm_panel_of_backlight(&ctx->panel);
284 if (ret)
285 return dev_err_probe(dev, ret, "failed to add backlight\n");
286
287 spi_set_drvdata(spi, ctx);
288
289 drm_panel_add(&ctx->panel);
290
291 return 0;
292}
293
294static int s6d27a1_remove(struct spi_device *spi)
295{
296 struct s6d27a1 *ctx = spi_get_drvdata(spi);
297
298 drm_panel_remove(&ctx->panel);
299 return 0;
300}
301
302static const struct of_device_id s6d27a1_match[] = {
303 { .compatible = "samsung,s6d27a1", },
304 { /* sentinel */ },
305};
306MODULE_DEVICE_TABLE(of, s6d27a1_match);
307
308static struct spi_driver s6d27a1_driver = {
309 .probe = s6d27a1_probe,
310 .remove = s6d27a1_remove,
311 .driver = {
312 .name = "s6d27a1-panel",
313 .of_match_table = s6d27a1_match,
314 },
315};
316module_spi_driver(s6d27a1_driver);
317
318MODULE_AUTHOR("Markuss Broks <markuss.broks@gmail.com>");
319MODULE_DESCRIPTION("Samsung S6D27A1 panel driver");
320MODULE_LICENSE("GPL v2");
drivers/gpu/drm/panel/panel-simple.c+13−13
@@ -3158,19 +3158,6 @@ static const struct panel_desc logictechno_lttd800480070_l6wh_rt = { · 3157 unmodified lines
3158 .connector_type = DRM_MODE_CONNECTOR_DPI,3158 .connector_type = DRM_MODE_CONNECTOR_DPI,
3159};3159};
3160 3160
3161static const struct drm_display_mode mitsubishi_aa070mc01_mode = {
3162 .clock = 30400,
3163 .hdisplay = 800,
3164 .hsync_start = 800 + 0,
3165 .hsync_end = 800 + 1,
3166 .htotal = 800 + 0 + 1 + 160,
3167 .vdisplay = 480,
3168 .vsync_start = 480 + 0,
3169 .vsync_end = 480 + 48 + 1,
3170 .vtotal = 480 + 48 + 1 + 0,
3171 .flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC,
3172};
3173
3174static const struct drm_display_mode logicpd_type_28_mode = {3161static const struct drm_display_mode logicpd_type_28_mode = {
3175 .clock = 9107,3162 .clock = 9107,
3176 .hdisplay = 480,3163 .hdisplay = 480,
@@ -3205,6 +3192,19 @@ static const struct panel_desc logicpd_type_28 = { · 28 unmodified lines
3205 .connector_type = DRM_MODE_CONNECTOR_DPI,3192 .connector_type = DRM_MODE_CONNECTOR_DPI,
3206};3193};
3207 3194
3195static const struct drm_display_mode mitsubishi_aa070mc01_mode = {
3196 .clock = 30400,
3197 .hdisplay = 800,
3198 .hsync_start = 800 + 0,
3199 .hsync_end = 800 + 1,
3200 .htotal = 800 + 0 + 1 + 160,
3201 .vdisplay = 480,
3202 .vsync_start = 480 + 0,
3203 .vsync_end = 480 + 48 + 1,
3204 .vtotal = 480 + 48 + 1 + 0,
3205 .flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC,
3206};
3207
3208static const struct panel_desc mitsubishi_aa070mc01 = {3208static const struct panel_desc mitsubishi_aa070mc01 = {
3209 .modes = &mitsubishi_aa070mc01_mode,3209 .modes = &mitsubishi_aa070mc01_mode,
3210 .num_modes = 1,3210 .num_modes = 1,
drivers/gpu/drm/panfrost/panfrost_device.c+1−3
@@ -198,7 +198,6 @@ err: · 197 unmodified lines
198int panfrost_device_init(struct panfrost_device *pfdev)198int panfrost_device_init(struct panfrost_device *pfdev)
199{199{
200 int err;200 int err;
201 struct resource *res;
202 201
203 mutex_init(&pfdev->sched_lock);202 mutex_init(&pfdev->sched_lock);
204 INIT_LIST_HEAD(&pfdev->scheduled_jobs);203 INIT_LIST_HEAD(&pfdev->scheduled_jobs);
@@ -236,8 +235,7 @@ int panfrost_device_init(struct panfrost_device *pfdev) · 31 unmodified lines
236 if (err)235 if (err)
237 goto out_reset;236 goto out_reset;
238 237
239 res = platform_get_resource(pfdev->pdev, IORESOURCE_MEM, 0);238 pfdev->iomem = devm_platform_ioremap_resource(pfdev->pdev, 0);
240 pfdev->iomem = devm_ioremap_resource(pfdev->dev, res);
241 if (IS_ERR(pfdev->iomem)) {239 if (IS_ERR(pfdev->iomem)) {
242 err = PTR_ERR(pfdev->iomem);240 err = PTR_ERR(pfdev->iomem);
243 goto out_pm_domain;241 goto out_pm_domain;
drivers/gpu/drm/panfrost/panfrost_drv.c+19−10
@@ -218,7 +218,7 @@ panfrost_copy_in_sync(struct drm_device *dev, · 217 unmodified lines
218 if (ret)218 if (ret)
219 goto fail;219 goto fail;
220 220
221 ret = drm_gem_fence_array_add(&job->deps, fence);221 ret = drm_sched_job_add_dependency(&job->base, fence);
222 222
223 if (ret)223 if (ret)
224 goto fail;224 goto fail;
@@ -236,7 +236,7 @@ static int panfrost_ioctl_submit(struct drm_device *dev, void *data, · 11 unmodified lines
236 struct drm_panfrost_submit *args = data;236 struct drm_panfrost_submit *args = data;
237 struct drm_syncobj *sync_out = NULL;237 struct drm_syncobj *sync_out = NULL;
238 struct panfrost_job *job;238 struct panfrost_job *job;
239 int ret = 0;239 int ret = 0, slot;
240 240
241 if (!args->jc)241 if (!args->jc)
242 return -EINVAL;242 return -EINVAL;
@@ -253,38 +253,47 @@ static int panfrost_ioctl_submit(struct drm_device *dev, void *data, · 10 unmodified lines
253 job = kzalloc(sizeof(*job), GFP_KERNEL);253 job = kzalloc(sizeof(*job), GFP_KERNEL);
254 if (!job) {254 if (!job) {
255 ret = -ENOMEM;255 ret = -ENOMEM;
256 goto fail_out_sync;256 goto out_put_syncout;
257 }257 }
258 258
259 kref_init(&job->refcount);259 kref_init(&job->refcount);
260 260
261 xa_init_flags(&job->deps, XA_FLAGS_ALLOC);
262
263 job->pfdev = pfdev;261 job->pfdev = pfdev;
264 job->jc = args->jc;262 job->jc = args->jc;
265 job->requirements = args->requirements;263 job->requirements = args->requirements;
266 job->flush_id = panfrost_gpu_get_latest_flush_id(pfdev);264 job->flush_id = panfrost_gpu_get_latest_flush_id(pfdev);
267 job->file_priv = file->driver_priv;265 job->file_priv = file->driver_priv;
268 266
267 slot = panfrost_job_get_slot(job);
268
269 ret = drm_sched_job_init(&job->base,
270 &job->file_priv->sched_entity[slot],
271 NULL);
272 if (ret)
273 goto out_put_job;
274
269 ret = panfrost_copy_in_sync(dev, file, args, job);275 ret = panfrost_copy_in_sync(dev, file, args, job);
270 if (ret)276 if (ret)
271 goto fail_job;277 goto out_cleanup_job;
272 278
273 ret = panfrost_lookup_bos(dev, file, args, job);279 ret = panfrost_lookup_bos(dev, file, args, job);
274 if (ret)280 if (ret)
275 goto fail_job;281 goto out_cleanup_job;
276 282
277 ret = panfrost_job_push(job);283 ret = panfrost_job_push(job);
278 if (ret)284 if (ret)
279 goto fail_job;285 goto out_cleanup_job;
280 286
281 /* Update the return sync object for the job */287 /* Update the return sync object for the job */
282 if (sync_out)288 if (sync_out)
283 drm_syncobj_replace_fence(sync_out, job->render_done_fence);289 drm_syncobj_replace_fence(sync_out, job->render_done_fence);
284 290
285fail_job:291out_cleanup_job:
292 if (ret)
293 drm_sched_job_cleanup(&job->base);
294out_put_job:
286 panfrost_job_put(job);295 panfrost_job_put(job);
287fail_out_sync:296out_put_syncout:
288 if (sync_out)297 if (sync_out)
289 drm_syncobj_put(sync_out);298 drm_syncobj_put(sync_out);
290 299
drivers/gpu/drm/panfrost/panfrost_job.c+11−37
@@ -102,7 +102,7 @@ static struct dma_fence *panfrost_fence_create(struct panfrost_device *pfdev, in · 101 unmodified lines
102 return &fence->base;102 return &fence->base;
103}103}
104 104
105static int panfrost_job_get_slot(struct panfrost_job *job)105int panfrost_job_get_slot(struct panfrost_job *job)
106{106{
107 /* JS0: fragment jobs.107 /* JS0: fragment jobs.
108 * JS1: vertex/tiler jobs108 * JS1: vertex/tiler jobs
@@ -137,8 +137,8 @@ static void panfrost_job_write_affinity(struct panfrost_device *pfdev, · 28 unmodified lines
137 */137 */
138 affinity = pfdev->features.shader_present;138 affinity = pfdev->features.shader_present;
139 139
140 job_write(pfdev, JS_AFFINITY_NEXT_LO(js), affinity & 0xFFFFFFFF);140 job_write(pfdev, JS_AFFINITY_NEXT_LO(js), lower_32_bits(affinity));
141 job_write(pfdev, JS_AFFINITY_NEXT_HI(js), affinity >> 32);141 job_write(pfdev, JS_AFFINITY_NEXT_HI(js), upper_32_bits(affinity));
142}142}
143 143
144static u32144static u32
@@ -203,8 +203,8 @@ static void panfrost_job_hw_submit(struct panfrost_job *job, int js) · 58 unmodified lines
203 203
204 cfg = panfrost_mmu_as_get(pfdev, job->file_priv->mmu);204 cfg = panfrost_mmu_as_get(pfdev, job->file_priv->mmu);
205 205
206 job_write(pfdev, JS_HEAD_NEXT_LO(js), jc_head & 0xFFFFFFFF);206 job_write(pfdev, JS_HEAD_NEXT_LO(js), lower_32_bits(jc_head));
207 job_write(pfdev, JS_HEAD_NEXT_HI(js), jc_head >> 32);207 job_write(pfdev, JS_HEAD_NEXT_HI(js), upper_32_bits(jc_head));
208 208
209 panfrost_job_write_affinity(pfdev, job->requirements, js);209 panfrost_job_write_affinity(pfdev, job->requirements, js);
210 210
@@ -242,13 +242,14 @@ static void panfrost_job_hw_submit(struct panfrost_job *job, int js) · 31 unmodified lines
242 242
243static int panfrost_acquire_object_fences(struct drm_gem_object **bos,243static int panfrost_acquire_object_fences(struct drm_gem_object **bos,
244 int bo_count,244 int bo_count,
245 struct xarray *deps)245 struct drm_sched_job *job)
246{246{
247 int i, ret;247 int i, ret;
248 248
249 for (i = 0; i < bo_count; i++) {249 for (i = 0; i < bo_count; i++) {
250 /* panfrost always uses write mode in its current uapi */250 /* panfrost always uses write mode in its current uapi */
251 ret = drm_gem_fence_array_add_implicit(deps, bos[i], true);251 ret = drm_sched_job_add_implicit_dependencies(job, bos[i],
252 true);
252 if (ret)253 if (ret)
253 return ret;254 return ret;
254 }255 }
@@ -269,29 +270,21 @@ static void panfrost_attach_object_fences(struct drm_gem_object **bos, · 14 unmodified lines
269int panfrost_job_push(struct panfrost_job *job)270int panfrost_job_push(struct panfrost_job *job)
270{271{
271 struct panfrost_device *pfdev = job->pfdev;272 struct panfrost_device *pfdev = job->pfdev;
272 int slot = panfrost_job_get_slot(job);
273 struct drm_sched_entity *entity = &job->file_priv->sched_entity[slot];
274 struct ww_acquire_ctx acquire_ctx;273 struct ww_acquire_ctx acquire_ctx;
275 int ret = 0;274 int ret = 0;
276 275
277
278 ret = drm_gem_lock_reservations(job->bos, job->bo_count,276 ret = drm_gem_lock_reservations(job->bos, job->bo_count,
279 &acquire_ctx);277 &acquire_ctx);
280 if (ret)278 if (ret)
281 return ret;279 return ret;
282 280
283 mutex_lock(&pfdev->sched_lock);281 mutex_lock(&pfdev->sched_lock);
284 282 drm_sched_job_arm(&job->base);
285 ret = drm_sched_job_init(&job->base, entity, NULL);
286 if (ret) {
287 mutex_unlock(&pfdev->sched_lock);
288 goto unlock;
289 }
290 283
291 job->render_done_fence = dma_fence_get(&job->base.s_fence->finished);284 job->render_done_fence = dma_fence_get(&job->base.s_fence->finished);
292 285
293 ret = panfrost_acquire_object_fences(job->bos, job->bo_count,286 ret = panfrost_acquire_object_fences(job->bos, job->bo_count,
294 &job->deps);287 &job->base);
295 if (ret) {288 if (ret) {
296 mutex_unlock(&pfdev->sched_lock);289 mutex_unlock(&pfdev->sched_lock);
297 goto unlock;290 goto unlock;
@@ -299,7 +292,7 @@ int panfrost_job_push(struct panfrost_job *job) · 1 unmodified line
299 292
300 kref_get(&job->refcount); /* put by scheduler job completion */293 kref_get(&job->refcount); /* put by scheduler job completion */
301 294
302 drm_sched_entity_push_job(&job->base, entity);295 drm_sched_entity_push_job(&job->base);
303 296
304 mutex_unlock(&pfdev->sched_lock);297 mutex_unlock(&pfdev->sched_lock);
305 298
@@ -316,15 +309,8 @@ static void panfrost_job_cleanup(struct kref *ref) · 10 unmodified lines
316{309{
317 struct panfrost_job *job = container_of(ref, struct panfrost_job,310 struct panfrost_job *job = container_of(ref, struct panfrost_job,
318 refcount);311 refcount);
319 struct dma_fence *fence;
320 unsigned long index;
321 unsigned int i;312 unsigned int i;
322 313
323 xa_for_each(&job->deps, index, fence) {
324 dma_fence_put(fence);
325 }
326 xa_destroy(&job->deps);
327
328 dma_fence_put(job->done_fence);314 dma_fence_put(job->done_fence);
329 dma_fence_put(job->render_done_fence);315 dma_fence_put(job->render_done_fence);
330 316
@@ -363,17 +349,6 @@ static void panfrost_job_free(struct drm_sched_job *sched_job) · 32 unmodified lines
363 panfrost_job_put(job);349 panfrost_job_put(job);
364}350}
365 351
366static struct dma_fence *panfrost_job_dependency(struct drm_sched_job *sched_job,
367 struct drm_sched_entity *s_entity)
368{
369 struct panfrost_job *job = to_panfrost_job(sched_job);
370
371 if (!xa_empty(&job->deps))
372 return xa_erase(&job->deps, job->last_dep++);
373
374 return NULL;
375}
376
377static struct dma_fence *panfrost_job_run(struct drm_sched_job *sched_job)352static struct dma_fence *panfrost_job_run(struct drm_sched_job *sched_job)
378{353{
379 struct panfrost_job *job = to_panfrost_job(sched_job);354 struct panfrost_job *job = to_panfrost_job(sched_job);
@@ -763,7 +738,6 @@ static void panfrost_reset_work(struct work_struct *work) · 383 unmodified lines
763}738}
764 739
765static const struct drm_sched_backend_ops panfrost_sched_ops = {740static const struct drm_sched_backend_ops panfrost_sched_ops = {
766 .dependency = panfrost_job_dependency,
767 .run_job = panfrost_job_run,741 .run_job = panfrost_job_run,
768 .timedout_job = panfrost_job_timedout,742 .timedout_job = panfrost_job_timedout,
769 .free_job = panfrost_job_free743 .free_job = panfrost_job_free
drivers/gpu/drm/panfrost/panfrost_job.h+1−4
@@ -19,10 +19,6 @@ struct panfrost_job { · 18 unmodified lines
19 struct panfrost_device *pfdev;19 struct panfrost_device *pfdev;
20 struct panfrost_file_priv *file_priv;20 struct panfrost_file_priv *file_priv;
21 21
22 /* Contains both explicit and implicit fences */
23 struct xarray deps;
24 unsigned long last_dep;
25
26 /* Fence to be signaled by IRQ handler when the job is complete. */22 /* Fence to be signaled by IRQ handler when the job is complete. */
27 struct dma_fence *done_fence;23 struct dma_fence *done_fence;
28 24
@@ -42,6 +38,7 @@ int panfrost_job_init(struct panfrost_device *pfdev); · 13 unmodified lines
42void panfrost_job_fini(struct panfrost_device *pfdev);38void panfrost_job_fini(struct panfrost_device *pfdev);
43int panfrost_job_open(struct panfrost_file_priv *panfrost_priv);39int panfrost_job_open(struct panfrost_file_priv *panfrost_priv);
44void panfrost_job_close(struct panfrost_file_priv *panfrost_priv);40void panfrost_job_close(struct panfrost_file_priv *panfrost_priv);
41int panfrost_job_get_slot(struct panfrost_job *job);
45int panfrost_job_push(struct panfrost_job *job);42int panfrost_job_push(struct panfrost_job *job);
46void panfrost_job_put(struct panfrost_job *job);43void panfrost_job_put(struct panfrost_job *job);
47void panfrost_job_enable_interrupts(struct panfrost_device *pfdev);44void panfrost_job_enable_interrupts(struct panfrost_device *pfdev);
drivers/gpu/drm/panfrost/panfrost_mmu.c+6−6
@@ -71,8 +71,8 @@ static void lock_region(struct panfrost_device *pfdev, u32 as_nr, · 70 unmodified lines
71 region |= region_width;71 region |= region_width;
72 72
73 /* Lock the region that needs to be updated */73 /* Lock the region that needs to be updated */
74 mmu_write(pfdev, AS_LOCKADDR_LO(as_nr), region & 0xFFFFFFFFUL);74 mmu_write(pfdev, AS_LOCKADDR_LO(as_nr), lower_32_bits(region));
75 mmu_write(pfdev, AS_LOCKADDR_HI(as_nr), (region >> 32) & 0xFFFFFFFFUL);75 mmu_write(pfdev, AS_LOCKADDR_HI(as_nr), upper_32_bits(region));
76 write_cmd(pfdev, as_nr, AS_COMMAND_LOCK);76 write_cmd(pfdev, as_nr, AS_COMMAND_LOCK);
77}77}
78 78
@@ -114,14 +114,14 @@ static void panfrost_mmu_enable(struct panfrost_device *pfdev, struct panfrost_m · 35 unmodified lines
114 114
115 mmu_hw_do_operation_locked(pfdev, as_nr, 0, ~0ULL, AS_COMMAND_FLUSH_MEM);115 mmu_hw_do_operation_locked(pfdev, as_nr, 0, ~0ULL, AS_COMMAND_FLUSH_MEM);
116 116
117 mmu_write(pfdev, AS_TRANSTAB_LO(as_nr), transtab & 0xffffffffUL);117 mmu_write(pfdev, AS_TRANSTAB_LO(as_nr), lower_32_bits(transtab));
118 mmu_write(pfdev, AS_TRANSTAB_HI(as_nr), transtab >> 32);118 mmu_write(pfdev, AS_TRANSTAB_HI(as_nr), upper_32_bits(transtab));
119 119
120 /* Need to revisit mem attrs.120 /* Need to revisit mem attrs.
121 * NC is the default, Mali driver is inner WT.121 * NC is the default, Mali driver is inner WT.
122 */122 */
123 mmu_write(pfdev, AS_MEMATTR_LO(as_nr), memattr & 0xffffffffUL);123 mmu_write(pfdev, AS_MEMATTR_LO(as_nr), lower_32_bits(memattr));
124 mmu_write(pfdev, AS_MEMATTR_HI(as_nr), memattr >> 32);124 mmu_write(pfdev, AS_MEMATTR_HI(as_nr), upper_32_bits(memattr));
125 125
126 write_cmd(pfdev, as_nr, AS_COMMAND_UPDATE);126 write_cmd(pfdev, as_nr, AS_COMMAND_UPDATE);
127}127}
drivers/gpu/drm/panfrost/panfrost_perfcnt.c+2−2
@@ -51,8 +51,8 @@ static int panfrost_perfcnt_dump_locked(struct panfrost_device *pfdev) · 50 unmodified lines
51 51
52 reinit_completion(&pfdev->perfcnt->dump_comp);52 reinit_completion(&pfdev->perfcnt->dump_comp);
53 gpuva = pfdev->perfcnt->mapping->mmnode.start << PAGE_SHIFT;53 gpuva = pfdev->perfcnt->mapping->mmnode.start << PAGE_SHIFT;
54 gpu_write(pfdev, GPU_PERFCNT_BASE_LO, gpuva);54 gpu_write(pfdev, GPU_PERFCNT_BASE_LO, lower_32_bits(gpuva));
55 gpu_write(pfdev, GPU_PERFCNT_BASE_HI, gpuva >> 32);55 gpu_write(pfdev, GPU_PERFCNT_BASE_HI, upper_32_bits(gpuva));
56 gpu_write(pfdev, GPU_INT_CLEAR,56 gpu_write(pfdev, GPU_INT_CLEAR,
57 GPU_IRQ_CLEAN_CACHES_COMPLETED |57 GPU_IRQ_CLEAN_CACHES_COMPLETED |
58 GPU_IRQ_PERFCNT_SAMPLE_COMPLETED);58 GPU_IRQ_PERFCNT_SAMPLE_COMPLETED);
drivers/gpu/drm/qxl/qxl_release.c+2−2
@@ -36,10 +36,10 @@ · 35 unmodified lines
36/* manage releaseables */36/* manage releaseables */
37/* stack them 16 high for now -drawable object is 191 */37/* stack them 16 high for now -drawable object is 191 */
38#define RELEASE_SIZE 25638#define RELEASE_SIZE 256
39#define RELEASES_PER_BO (4096 / RELEASE_SIZE)39#define RELEASES_PER_BO (PAGE_SIZE / RELEASE_SIZE)
40/* put an alloc/dealloc surface cmd into one bo and round up to 128 */40/* put an alloc/dealloc surface cmd into one bo and round up to 128 */
41#define SURFACE_RELEASE_SIZE 12841#define SURFACE_RELEASE_SIZE 128
42#define SURFACE_RELEASES_PER_BO (4096 / SURFACE_RELEASE_SIZE)42#define SURFACE_RELEASES_PER_BO (PAGE_SIZE / SURFACE_RELEASE_SIZE)
43 43
44static const int release_size_per_bo[] = { RELEASE_SIZE, SURFACE_RELEASE_SIZE, RELEASE_SIZE };44static const int release_size_per_bo[] = { RELEASE_SIZE, SURFACE_RELEASE_SIZE, RELEASE_SIZE };
45static const int releases_per_bo[] = { RELEASES_PER_BO, SURFACE_RELEASES_PER_BO, RELEASES_PER_BO };45static const int releases_per_bo[] = { RELEASES_PER_BO, SURFACE_RELEASES_PER_BO, RELEASES_PER_BO };
drivers/gpu/drm/qxl/qxl_ttm.c+0−1
@@ -101,7 +101,6 @@ int qxl_ttm_io_mem_reserve(struct ttm_device *bdev, · 100 unmodified lines
101 */101 */
102static void qxl_ttm_backend_destroy(struct ttm_device *bdev, struct ttm_tt *ttm)102static void qxl_ttm_backend_destroy(struct ttm_device *bdev, struct ttm_tt *ttm)
103{103{
104 ttm_tt_destroy_common(bdev, ttm);
105 ttm_tt_fini(ttm);104 ttm_tt_fini(ttm);
106 kfree(ttm);105 kfree(ttm);
107}106}
drivers/gpu/drm/r128/ati_pcigart.c+6−5
@@ -99,7 +99,8 @@ int drm_ati_pcigart_cleanup(struct drm_device *dev, struct drm_ati_pcigart_info · 98 unmodified lines
99 for (i = 0; i < pages; i++) {99 for (i = 0; i < pages; i++) {
100 if (!entry->busaddr[i])100 if (!entry->busaddr[i])
101 break;101 break;
102 pci_unmap_page(pdev, entry->busaddr[i], PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);102 dma_unmap_page(&pdev->dev, entry->busaddr[i],
103 PAGE_SIZE, DMA_BIDIRECTIONAL);
103 }104 }
104 105
105 if (gart_info->gart_table_location == DRM_ATI_GART_MAIN)106 if (gart_info->gart_table_location == DRM_ATI_GART_MAIN)
@@ -134,7 +135,7 @@ int drm_ati_pcigart_init(struct drm_device *dev, struct drm_ati_pcigart_info *ga · 28 unmodified lines
134 if (gart_info->gart_table_location == DRM_ATI_GART_MAIN) {135 if (gart_info->gart_table_location == DRM_ATI_GART_MAIN) {
135 DRM_DEBUG("PCI: no table in VRAM: using normal RAM\n");136 DRM_DEBUG("PCI: no table in VRAM: using normal RAM\n");
136 137
137 if (pci_set_dma_mask(pdev, gart_info->table_mask)) {138 if (dma_set_mask(&pdev->dev, gart_info->table_mask)) {
138 DRM_ERROR("fail to set dma mask to 0x%Lx\n",139 DRM_ERROR("fail to set dma mask to 0x%Lx\n",
139 (unsigned long long)gart_info->table_mask);140 (unsigned long long)gart_info->table_mask);
140 ret = -EFAULT;141 ret = -EFAULT;
@@ -173,9 +174,9 @@ int drm_ati_pcigart_init(struct drm_device *dev, struct drm_ati_pcigart_info *ga · 32 unmodified lines
173 gart_idx = 0;174 gart_idx = 0;
174 for (i = 0; i < pages; i++) {175 for (i = 0; i < pages; i++) {
175 /* we need to support large memory configurations */176 /* we need to support large memory configurations */
176 entry->busaddr[i] = pci_map_page(pdev, entry->pagelist[i],177 entry->busaddr[i] = dma_map_page(&pdev->dev, entry->pagelist[i],
177 0, PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);178 0, PAGE_SIZE, DMA_BIDIRECTIONAL);
178 if (pci_dma_mapping_error(pdev, entry->busaddr[i])) {179 if (dma_mapping_error(&pdev->dev, entry->busaddr[i])) {
179 DRM_ERROR("unable to map PCIGART pages!\n");180 DRM_ERROR("unable to map PCIGART pages!\n");
180 drm_ati_pcigart_cleanup(dev, gart_info);181 drm_ati_pcigart_cleanup(dev, gart_info);
181 address = NULL;182 address = NULL;
drivers/gpu/drm/radeon/radeon_fence.c+4−20
@@ -176,18 +176,11 @@ static int radeon_fence_check_signaled(wait_queue_entry_t *wait, unsigned mode, · 175 unmodified lines
176 */176 */
177 seq = atomic64_read(&fence->rdev->fence_drv[fence->ring].last_seq);177 seq = atomic64_read(&fence->rdev->fence_drv[fence->ring].last_seq);
178 if (seq >= fence->seq) {178 if (seq >= fence->seq) {
179 int ret = dma_fence_signal_locked(&fence->base);179 dma_fence_signal_locked(&fence->base);
180
181 if (!ret)
182 DMA_FENCE_TRACE(&fence->base, "signaled from irq context\n");
183 else
184 DMA_FENCE_TRACE(&fence->base, "was already signaled\n");
185
186 radeon_irq_kms_sw_irq_put(fence->rdev, fence->ring);180 radeon_irq_kms_sw_irq_put(fence->rdev, fence->ring);
187 __remove_wait_queue(&fence->rdev->fence_queue, &fence->fence_wake);181 __remove_wait_queue(&fence->rdev->fence_queue, &fence->fence_wake);
188 dma_fence_put(&fence->base);182 dma_fence_put(&fence->base);
189 } else183 }
190 DMA_FENCE_TRACE(&fence->base, "pending\n");
191 return 0;184 return 0;
192}185}
193 186
@@ -422,8 +415,6 @@ static bool radeon_fence_enable_signaling(struct dma_fence *f) · 228 unmodified lines
422 fence->fence_wake.func = radeon_fence_check_signaled;415 fence->fence_wake.func = radeon_fence_check_signaled;
423 __add_wait_queue(&rdev->fence_queue, &fence->fence_wake);416 __add_wait_queue(&rdev->fence_queue, &fence->fence_wake);
424 dma_fence_get(f);417 dma_fence_get(f);
425
426 DMA_FENCE_TRACE(&fence->base, "armed on ring %i!\n", fence->ring);
427 return true;418 return true;
428}419}
429 420
@@ -441,11 +432,7 @@ bool radeon_fence_signaled(struct radeon_fence *fence) · 11 unmodified lines
441 return true;432 return true;
442 433
443 if (radeon_fence_seq_signaled(fence->rdev, fence->seq, fence->ring)) {434 if (radeon_fence_seq_signaled(fence->rdev, fence->seq, fence->ring)) {
444 int ret;435 dma_fence_signal(&fence->base);
445
446 ret = dma_fence_signal(&fence->base);
447 if (!ret)
448 DMA_FENCE_TRACE(&fence->base, "signaled from radeon_fence_signaled\n");
449 return true;436 return true;
450 }437 }
451 return false;438 return false;
@@ -550,7 +537,6 @@ long radeon_fence_wait_timeout(struct radeon_fence *fence, bool intr, long timeo · 98 unmodified lines
550{537{
551 uint64_t seq[RADEON_NUM_RINGS] = {};538 uint64_t seq[RADEON_NUM_RINGS] = {};
552 long r;539 long r;
553 int r_sig;
554 540
555 /*541 /*
556 * This function should not be called on !radeon fences.542 * This function should not be called on !radeon fences.
@@ -567,9 +553,7 @@ long radeon_fence_wait_timeout(struct radeon_fence *fence, bool intr, long timeo · 10 unmodified lines
567 return r;553 return r;
568 }554 }
569 555
570 r_sig = dma_fence_signal(&fence->base);556 dma_fence_signal(&fence->base);
571 if (!r_sig)
572 DMA_FENCE_TRACE(&fence->base, "signaled from fence_wait\n");
573 return r;557 return r;
574}558}
575 559
drivers/gpu/drm/radeon/radeon_ttm.c+2−5
@@ -488,9 +488,6 @@ static void radeon_ttm_backend_destroy(struct ttm_device *bdev, struct ttm_tt *t · 487 unmodified lines
488{488{
489 struct radeon_ttm_tt *gtt = (void *)ttm;489 struct radeon_ttm_tt *gtt = (void *)ttm;
490 490
491 radeon_ttm_backend_unbind(bdev, ttm);
492 ttm_tt_destroy_common(bdev, ttm);
493
494 ttm_tt_fini(&gtt->ttm);491 ttm_tt_fini(&gtt->ttm);
495 kfree(gtt);492 kfree(gtt);
496}493}
@@ -574,6 +571,8 @@ static void radeon_ttm_tt_unpopulate(struct ttm_device *bdev, struct ttm_tt *ttm · 77 unmodified lines
574 struct radeon_ttm_tt *gtt = radeon_ttm_tt_to_gtt(rdev, ttm);571 struct radeon_ttm_tt *gtt = radeon_ttm_tt_to_gtt(rdev, ttm);
575 bool slave = !!(ttm->page_flags & TTM_PAGE_FLAG_SG);572 bool slave = !!(ttm->page_flags & TTM_PAGE_FLAG_SG);
576 573
574 radeon_ttm_tt_unbind(bdev, ttm);
575
577 if (gtt && gtt->userptr) {576 if (gtt && gtt->userptr) {
578 kfree(ttm->sg);577 kfree(ttm->sg);
579 ttm->page_flags &= ~TTM_PAGE_FLAG_SG;578 ttm->page_flags &= ~TTM_PAGE_FLAG_SG;
@@ -651,8 +650,6 @@ static void radeon_ttm_tt_destroy(struct ttm_device *bdev, · 71 unmodified lines
651 struct radeon_device *rdev = radeon_get_rdev(bdev);650 struct radeon_device *rdev = radeon_get_rdev(bdev);
652 651
653 if (rdev->flags & RADEON_IS_AGP) {652 if (rdev->flags & RADEON_IS_AGP) {
654 ttm_agp_unbind(ttm);
655 ttm_tt_destroy_common(bdev, ttm);
656 ttm_agp_destroy(ttm);653 ttm_agp_destroy(ttm);
657 return;654 return;
658 }655 }
drivers/gpu/drm/rockchip/Kconfig+0−1
@@ -9,7 +9,6 @@ config DRM_ROCKCHIP · 8 unmodified lines
9 select DRM_ANALOGIX_DP if ROCKCHIP_ANALOGIX_DP9 select DRM_ANALOGIX_DP if ROCKCHIP_ANALOGIX_DP
10 select DRM_DW_HDMI if ROCKCHIP_DW_HDMI10 select DRM_DW_HDMI if ROCKCHIP_DW_HDMI
11 select DRM_DW_MIPI_DSI if ROCKCHIP_DW_MIPI_DSI11 select DRM_DW_MIPI_DSI if ROCKCHIP_DW_MIPI_DSI
12 select DRM_RGB if ROCKCHIP_RGB
13 select GENERIC_PHY if ROCKCHIP_DW_MIPI_DSI12 select GENERIC_PHY if ROCKCHIP_DW_MIPI_DSI
14 select GENERIC_PHY_MIPI_DPHY if ROCKCHIP_DW_MIPI_DSI13 select GENERIC_PHY_MIPI_DPHY if ROCKCHIP_DW_MIPI_DSI
15 select SND_SOC_HDMI_CODEC if ROCKCHIP_CDN_DP && SND_SOC14 select SND_SOC_HDMI_CODEC if ROCKCHIP_CDN_DP && SND_SOC
drivers/gpu/drm/scheduler/sched_entity.c+69−71
@@ -45,8 +45,14 @@ · 44 unmodified lines
45 * @guilty: atomic_t set to 1 when a job on this queue45 * @guilty: atomic_t set to 1 when a job on this queue
46 * is found to be guilty causing a timeout46 * is found to be guilty causing a timeout
47 *47 *
48 * Note: the sched_list should have at least one element to schedule48 * Note that the &sched_list must have at least one element to schedule the entity.
49 * the entity49 *
50 * For changing @priority later on at runtime see
51 * drm_sched_entity_set_priority(). For changing the set of schedulers
52 * @sched_list at runtime see drm_sched_entity_modify_sched().
53 *
54 * An entity is cleaned up by callind drm_sched_entity_fini(). See also
55 * drm_sched_entity_destroy().
50 *56 *
51 * Returns 0 on success or a negative error code on failure.57 * Returns 0 on success or a negative error code on failure.
52 */58 */
@@ -92,6 +98,11 @@ EXPORT_SYMBOL(drm_sched_entity_init); · 39 unmodified lines
92 * @sched_list: the list of new drm scheds which will replace98 * @sched_list: the list of new drm scheds which will replace
93 * existing entity->sched_list99 * existing entity->sched_list
94 * @num_sched_list: number of drm sched in sched_list100 * @num_sched_list: number of drm sched in sched_list
101 *
102 * Note that this must be called under the same common lock for @entity as
103 * drm_sched_job_arm() and drm_sched_entity_push_job(), or the driver needs to
104 * guarantee through some other means that this is never called while new jobs
105 * can be pushed to @entity.
95 */106 */
96void drm_sched_entity_modify_sched(struct drm_sched_entity *entity,107void drm_sched_entity_modify_sched(struct drm_sched_entity *entity,
97 struct drm_gpu_scheduler **sched_list,108 struct drm_gpu_scheduler **sched_list,
@@ -104,13 +115,6 @@ void drm_sched_entity_modify_sched(struct drm_sched_entity *entity, · 6 unmodified lines
104}115}
105EXPORT_SYMBOL(drm_sched_entity_modify_sched);116EXPORT_SYMBOL(drm_sched_entity_modify_sched);
106 117
107/**
108 * drm_sched_entity_is_idle - Check if entity is idle
109 *
110 * @entity: scheduler entity
111 *
112 * Returns true if the entity does not have any unscheduled jobs.
113 */
114static bool drm_sched_entity_is_idle(struct drm_sched_entity *entity)118static bool drm_sched_entity_is_idle(struct drm_sched_entity *entity)
115{119{
116 rmb(); /* for list_empty to work without lock */120 rmb(); /* for list_empty to work without lock */
@@ -123,13 +127,7 @@ static bool drm_sched_entity_is_idle(struct drm_sched_entity *entity) · 6 unmodified lines
123 return false;127 return false;
124}128}
125 129
126/**130/* Return true if entity could provide a job. */
127 * drm_sched_entity_is_ready - Check if entity is ready
128 *
129 * @entity: scheduler entity
130 *
131 * Return true if entity could provide a job.
132 */
133bool drm_sched_entity_is_ready(struct drm_sched_entity *entity)131bool drm_sched_entity_is_ready(struct drm_sched_entity *entity)
134{132{
135 if (spsc_queue_peek(&entity->job_queue) == NULL)133 if (spsc_queue_peek(&entity->job_queue) == NULL)
@@ -192,14 +190,7 @@ long drm_sched_entity_flush(struct drm_sched_entity *entity, long timeout) · 56 unmodified lines
192}190}
193EXPORT_SYMBOL(drm_sched_entity_flush);191EXPORT_SYMBOL(drm_sched_entity_flush);
194 192
195/**193/* Signal the scheduler finished fence when the entity in question is killed. */
196 * drm_sched_entity_kill_jobs_cb - helper for drm_sched_entity_kill_jobs
197 *
198 * @f: signaled fence
199 * @cb: our callback structure
200 *
201 * Signal the scheduler finished fence when the entity in question is killed.
202 */
203static void drm_sched_entity_kill_jobs_cb(struct dma_fence *f,194static void drm_sched_entity_kill_jobs_cb(struct dma_fence *f,
204 struct dma_fence_cb *cb)195 struct dma_fence_cb *cb)
205{196{
@@ -211,14 +202,19 @@ static void drm_sched_entity_kill_jobs_cb(struct dma_fence *f, · 5 unmodified lines
211 job->sched->ops->free_job(job);202 job->sched->ops->free_job(job);
212}203}
213 204
214/**205static struct dma_fence *
215 * drm_sched_entity_kill_jobs - Make sure all remaining jobs are killed206drm_sched_job_dependency(struct drm_sched_job *job,
216 *207 struct drm_sched_entity *entity)
217 * @entity: entity which is cleaned up208{
218 *209 if (!xa_empty(&job->dependencies))
219 * Makes sure that all remaining jobs in an entity are killed before it is210 return xa_erase(&job->dependencies, job->last_dependency++);
220 * destroyed.211
221 */212 if (job->sched->ops->dependency)
213 return job->sched->ops->dependency(job, entity);
214
215 return NULL;
216}
217
222static void drm_sched_entity_kill_jobs(struct drm_sched_entity *entity)218static void drm_sched_entity_kill_jobs(struct drm_sched_entity *entity)
223{219{
224 struct drm_sched_job *job;220 struct drm_sched_job *job;
@@ -229,7 +225,7 @@ static void drm_sched_entity_kill_jobs(struct drm_sched_entity *entity) · 4 unmodified lines
229 struct drm_sched_fence *s_fence = job->s_fence;225 struct drm_sched_fence *s_fence = job->s_fence;
230 226
231 /* Wait for all dependencies to avoid data corruptions */227 /* Wait for all dependencies to avoid data corruptions */
232 while ((f = job->sched->ops->dependency(job, entity)))228 while ((f = drm_sched_job_dependency(job, entity)))
233 dma_fence_wait(f, false);229 dma_fence_wait(f, false);
234 230
235 drm_sched_fence_scheduled(s_fence);231 drm_sched_fence_scheduled(s_fence);
@@ -260,9 +256,11 @@ static void drm_sched_entity_kill_jobs(struct drm_sched_entity *entity) · 24 unmodified lines
260 *256 *
261 * @entity: scheduler entity257 * @entity: scheduler entity
262 *258 *
263 * This should be called after @drm_sched_entity_do_release. It goes over the259 * Cleanups up @entity which has been initialized by drm_sched_entity_init().
264 * entity and signals all jobs with an error code if the process was killed.
265 *260 *
261 * If there are potentially job still in flight or getting newly queued
262 * drm_sched_entity_flush() must be called first. This function then goes over
263 * the entity and signals all jobs with an error code if the process was killed.
266 */264 */
267void drm_sched_entity_fini(struct drm_sched_entity *entity)265void drm_sched_entity_fini(struct drm_sched_entity *entity)
268{266{
@@ -302,10 +300,10 @@ EXPORT_SYMBOL(drm_sched_entity_fini); · 33 unmodified lines
302 300
303/**301/**
304 * drm_sched_entity_destroy - Destroy a context entity302 * drm_sched_entity_destroy - Destroy a context entity
305 *
306 * @entity: scheduler entity303 * @entity: scheduler entity
307 *304 *
308 * Calls drm_sched_entity_do_release() and drm_sched_entity_cleanup()305 * Calls drm_sched_entity_flush() and drm_sched_entity_fini() as a
306 * convenience wrapper.
309 */307 */
310void drm_sched_entity_destroy(struct drm_sched_entity *entity)308void drm_sched_entity_destroy(struct drm_sched_entity *entity)
311{309{
@@ -314,9 +312,7 @@ void drm_sched_entity_destroy(struct drm_sched_entity *entity) · 2 unmodified lines
314}312}
315EXPORT_SYMBOL(drm_sched_entity_destroy);313EXPORT_SYMBOL(drm_sched_entity_destroy);
316 314
317/*315/* drm_sched_entity_clear_dep - callback to clear the entities dependency */
318 * drm_sched_entity_clear_dep - callback to clear the entities dependency
319 */
320static void drm_sched_entity_clear_dep(struct dma_fence *f,316static void drm_sched_entity_clear_dep(struct dma_fence *f,
321 struct dma_fence_cb *cb)317 struct dma_fence_cb *cb)
322{318{
@@ -358,11 +354,7 @@ void drm_sched_entity_set_priority(struct drm_sched_entity *entity, · 35 unmodified lines
358}354}
359EXPORT_SYMBOL(drm_sched_entity_set_priority);355EXPORT_SYMBOL(drm_sched_entity_set_priority);
360 356
361/**357/*
362 * drm_sched_entity_add_dependency_cb - add callback for the entities dependency
363 *
364 * @entity: entity with dependency
365 *
366 * Add a callback to the current dependency of the entity to wake up the358 * Add a callback to the current dependency of the entity to wake up the
367 * scheduler when the entity becomes available.359 * scheduler when the entity becomes available.
368 */360 */
@@ -410,16 +402,8 @@ static bool drm_sched_entity_add_dependency_cb(struct drm_sched_entity *entity) · 41 unmodified lines
410 return false;402 return false;
411}403}
412 404
413/**
414 * drm_sched_entity_pop_job - get a ready to be scheduled job from the entity
415 *
416 * @entity: entity to get the job from
417 *
418 * Process all dependencies and try to get one job from the entities queue.
419 */
420struct drm_sched_job *drm_sched_entity_pop_job(struct drm_sched_entity *entity)405struct drm_sched_job *drm_sched_entity_pop_job(struct drm_sched_entity *entity)
421{406{
422 struct drm_gpu_scheduler *sched = entity->rq->sched;
423 struct drm_sched_job *sched_job;407 struct drm_sched_job *sched_job;
424 408
425 sched_job = to_drm_sched_job(spsc_queue_peek(&entity->job_queue));409 sched_job = to_drm_sched_job(spsc_queue_peek(&entity->job_queue));
@@ -427,7 +411,7 @@ struct drm_sched_job *drm_sched_entity_pop_job(struct drm_sched_entity *entity) · 1 unmodified line
427 return NULL;411 return NULL;
428 412
429 while ((entity->dependency =413 while ((entity->dependency =
430 sched->ops->dependency(sched_job, entity))) {414 drm_sched_job_dependency(sched_job, entity))) {
431 trace_drm_sched_job_wait_dep(sched_job, entity->dependency);415 trace_drm_sched_job_wait_dep(sched_job, entity->dependency);
432 416
433 if (drm_sched_entity_add_dependency_cb(entity))417 if (drm_sched_entity_add_dependency_cb(entity))
@@ -439,30 +423,45 @@ struct drm_sched_job *drm_sched_entity_pop_job(struct drm_sched_entity *entity) · 5 unmodified lines
439 dma_fence_set_error(&sched_job->s_fence->finished, -ECANCELED);423 dma_fence_set_error(&sched_job->s_fence->finished, -ECANCELED);
440 424
441 dma_fence_put(entity->last_scheduled);425 dma_fence_put(entity->last_scheduled);
426
442 entity->last_scheduled = dma_fence_get(&sched_job->s_fence->finished);427 entity->last_scheduled = dma_fence_get(&sched_job->s_fence->finished);
443 428
429 /*
430 * If the queue is empty we allow drm_sched_entity_select_rq() to
431 * locklessly access ->last_scheduled. This only works if we set the
432 * pointer before we dequeue and if we a write barrier here.
433 */
434 smp_wmb();
435
444 spsc_queue_pop(&entity->job_queue);436 spsc_queue_pop(&entity->job_queue);
445 return sched_job;437 return sched_job;
446}438}
447 439
448/**
449 * drm_sched_entity_select_rq - select a new rq for the entity
450 *
451 * @entity: scheduler entity
452 *
453 * Check all prerequisites and select a new rq for the entity for load
454 * balancing.
455 */
456void drm_sched_entity_select_rq(struct drm_sched_entity *entity)440void drm_sched_entity_select_rq(struct drm_sched_entity *entity)
457{441{
458 struct dma_fence *fence;442 struct dma_fence *fence;
459 struct drm_gpu_scheduler *sched;443 struct drm_gpu_scheduler *sched;
460 struct drm_sched_rq *rq;444 struct drm_sched_rq *rq;
461 445
462 if (spsc_queue_count(&entity->job_queue) || !entity->sched_list)446 /* single possible engine and already selected */
447 if (!entity->sched_list)
463 return;448 return;
464 449
465 fence = READ_ONCE(entity->last_scheduled);450 /* queue non-empty, stay on the same engine */
451 if (spsc_queue_count(&entity->job_queue))
452 return;
453
454 /*
455 * Only when the queue is empty are we guaranteed that the scheduler
456 * thread cannot change ->last_scheduled. To enforce ordering we need
457 * a read barrier here. See drm_sched_entity_pop_job() for the other
458 * side.
459 */
460 smp_rmb();
461
462 fence = entity->last_scheduled;
463
464 /* stay on the same engine if the previous job hasn't finished */
466 if (fence && !dma_fence_is_signaled(fence))465 if (fence && !dma_fence_is_signaled(fence))
467 return;466 return;
468 467
@@ -481,19 +480,18 @@ void drm_sched_entity_select_rq(struct drm_sched_entity *entity) · 12 unmodified lines
481 480
482/**481/**
483 * drm_sched_entity_push_job - Submit a job to the entity's job queue482 * drm_sched_entity_push_job - Submit a job to the entity's job queue
484 *
485 * @sched_job: job to submit483 * @sched_job: job to submit
486 * @entity: scheduler entity
487 *484 *
488 * Note: To guarantee that the order of insertion to queue matches485 * Note: To guarantee that the order of insertion to queue matches the job's
489 * the job's fence sequence number this function should be486 * fence sequence number this function should be called with drm_sched_job_arm()
490 * called with drm_sched_job_init under common lock.487 * under common lock for the struct drm_sched_entity that was set up for
488 * @sched_job in drm_sched_job_init().
491 *489 *
492 * Returns 0 for success, negative error code otherwise.490 * Returns 0 for success, negative error code otherwise.
493 */491 */
494void drm_sched_entity_push_job(struct drm_sched_job *sched_job,492void drm_sched_entity_push_job(struct drm_sched_job *sched_job)
495 struct drm_sched_entity *entity)
496{493{
494 struct drm_sched_entity *entity = sched_job->entity;
497 bool first;495 bool first;
498 496
499 trace_drm_sched_job(sched_job, entity);497 trace_drm_sched_job(sched_job, entity);
drivers/gpu/drm/scheduler/sched_fence.c+31−31
@@ -50,26 +50,12 @@ static void __exit drm_sched_fence_slab_fini(void) · 49 unmodified lines
50 50
51void drm_sched_fence_scheduled(struct drm_sched_fence *fence)51void drm_sched_fence_scheduled(struct drm_sched_fence *fence)
52{52{
53 int ret = dma_fence_signal(&fence->scheduled);53 dma_fence_signal(&fence->scheduled);
54
55 if (!ret)
56 DMA_FENCE_TRACE(&fence->scheduled,
57 "signaled from irq context\n");
58 else
59 DMA_FENCE_TRACE(&fence->scheduled,
60 "was already signaled\n");
61}54}
62 55
63void drm_sched_fence_finished(struct drm_sched_fence *fence)56void drm_sched_fence_finished(struct drm_sched_fence *fence)
64{57{
65 int ret = dma_fence_signal(&fence->finished);58 dma_fence_signal(&fence->finished);
66
67 if (!ret)
68 DMA_FENCE_TRACE(&fence->finished,
69 "signaled from irq context\n");
70 else
71 DMA_FENCE_TRACE(&fence->finished,
72 "was already signaled\n");
73}59}
74 60
75static const char *drm_sched_fence_get_driver_name(struct dma_fence *fence)61static const char *drm_sched_fence_get_driver_name(struct dma_fence *fence)
@@ -83,19 +69,28 @@ static const char *drm_sched_fence_get_timeline_name(struct dma_fence *f) · 7 unmodified lines
83 return (const char *)fence->sched->name;69 return (const char *)fence->sched->name;
84}70}
85 71
72static void drm_sched_fence_free_rcu(struct rcu_head *rcu)
73{
74 struct dma_fence *f = container_of(rcu, struct dma_fence, rcu);
75 struct drm_sched_fence *fence = to_drm_sched_fence(f);
76
77 if (!WARN_ON_ONCE(!fence))
78 kmem_cache_free(sched_fence_slab, fence);
79}
80
86/**81/**
87 * drm_sched_fence_free - free up the fence memory82 * drm_sched_fence_free - free up an uninitialized fence
88 *83 *
89 * @rcu: RCU callback head84 * @fence: fence to free
90 *85 *
91 * Free up the fence memory after the RCU grace period.86 * Free up the fence memory. Should only be used if drm_sched_fence_init()
87 * has not been called yet.
92 */88 */
93static void drm_sched_fence_free(struct rcu_head *rcu)89void drm_sched_fence_free(struct drm_sched_fence *fence)
94{90{
95 struct dma_fence *f = container_of(rcu, struct dma_fence, rcu);91 /* This function should not be called if the fence has been initialized. */
96 struct drm_sched_fence *fence = to_drm_sched_fence(f);92 if (!WARN_ON_ONCE(fence->sched))
97 93 kmem_cache_free(sched_fence_slab, fence);
98 kmem_cache_free(sched_fence_slab, fence);
99}94}
100 95
101/**96/**
@@ -111,7 +106,7 @@ static void drm_sched_fence_release_scheduled(struct dma_fence *f) · 9 unmodified lines
111 struct drm_sched_fence *fence = to_drm_sched_fence(f);106 struct drm_sched_fence *fence = to_drm_sched_fence(f);
112 107
113 dma_fence_put(fence->parent);108 dma_fence_put(fence->parent);
114 call_rcu(&fence->finished.rcu, drm_sched_fence_free);109 call_rcu(&fence->finished.rcu, drm_sched_fence_free_rcu);
115}110}
116 111
117/**112/**
@@ -152,27 +147,32 @@ struct drm_sched_fence *to_drm_sched_fence(struct dma_fence *f) · 34 unmodified lines
152}147}
153EXPORT_SYMBOL(to_drm_sched_fence);148EXPORT_SYMBOL(to_drm_sched_fence);
154 149
155struct drm_sched_fence *drm_sched_fence_create(struct drm_sched_entity *entity,150struct drm_sched_fence *drm_sched_fence_alloc(struct drm_sched_entity *entity,
156 void *owner)151 void *owner)
157{152{
158 struct drm_sched_fence *fence = NULL;153 struct drm_sched_fence *fence = NULL;
159 unsigned seq;
160 154
161 fence = kmem_cache_zalloc(sched_fence_slab, GFP_KERNEL);155 fence = kmem_cache_zalloc(sched_fence_slab, GFP_KERNEL);
162 if (fence == NULL)156 if (fence == NULL)
163 return NULL;157 return NULL;
164 158
165 fence->owner = owner;159 fence->owner = owner;
166 fence->sched = entity->rq->sched;
167 spin_lock_init(&fence->lock);160 spin_lock_init(&fence->lock);
168 161
162 return fence;
163}
164
165void drm_sched_fence_init(struct drm_sched_fence *fence,
166 struct drm_sched_entity *entity)
167{
168 unsigned seq;
169
170 fence->sched = entity->rq->sched;
169 seq = atomic_inc_return(&entity->fence_seq);171 seq = atomic_inc_return(&entity->fence_seq);
170 dma_fence_init(&fence->scheduled, &drm_sched_fence_ops_scheduled,172 dma_fence_init(&fence->scheduled, &drm_sched_fence_ops_scheduled,
171 &fence->lock, entity->fence_context, seq);173 &fence->lock, entity->fence_context, seq);
172 dma_fence_init(&fence->finished, &drm_sched_fence_ops_finished,174 dma_fence_init(&fence->finished, &drm_sched_fence_ops_finished,
173 &fence->lock, entity->fence_context + 1, seq);175 &fence->lock, entity->fence_context + 1, seq);
174
175 return fence;
176}176}
177 177
178module_init(drm_sched_fence_slab_init);178module_init(drm_sched_fence_slab_init);
drivers/gpu/drm/scheduler/sched_main.c+171−28
@@ -48,9 +48,11 @@ · 47 unmodified lines
48#include <linux/wait.h>48#include <linux/wait.h>
49#include <linux/sched.h>49#include <linux/sched.h>
50#include <linux/completion.h>50#include <linux/completion.h>
51#include <linux/dma-resv.h>
51#include <uapi/linux/sched/types.h>52#include <uapi/linux/sched/types.h>
52 53
53#include <drm/drm_print.h>54#include <drm/drm_print.h>
55#include <drm/drm_gem.h>
54#include <drm/gpu_scheduler.h>56#include <drm/gpu_scheduler.h>
55#include <drm/spsc_queue.h>57#include <drm/spsc_queue.h>
56 58
@@ -564,7 +566,6 @@ EXPORT_SYMBOL(drm_sched_resubmit_jobs_ext); · 507 unmodified lines
564 566
565/**567/**
566 * drm_sched_job_init - init a scheduler job568 * drm_sched_job_init - init a scheduler job
567 *
568 * @job: scheduler job to init569 * @job: scheduler job to init
569 * @entity: scheduler entity to use570 * @entity: scheduler entity to use
570 * @owner: job owner for debugging571 * @owner: job owner for debugging
@@ -572,43 +573,193 @@ EXPORT_SYMBOL(drm_sched_resubmit_jobs_ext); · 1 unmodified line
572 * Refer to drm_sched_entity_push_job() documentation573 * Refer to drm_sched_entity_push_job() documentation
573 * for locking considerations.574 * for locking considerations.
574 *575 *
576 * Drivers must make sure drm_sched_job_cleanup() if this function returns
577 * successfully, even when @job is aborted before drm_sched_job_arm() is called.
578 *
579 * WARNING: amdgpu abuses &drm_sched.ready to signal when the hardware
580 * has died, which can mean that there's no valid runqueue for a @entity.
581 * This function returns -ENOENT in this case (which probably should be -EIO as
582 * a more meanigful return value).
583 *
575 * Returns 0 for success, negative error code otherwise.584 * Returns 0 for success, negative error code otherwise.
576 */585 */
577int drm_sched_job_init(struct drm_sched_job *job,586int drm_sched_job_init(struct drm_sched_job *job,
578 struct drm_sched_entity *entity,587 struct drm_sched_entity *entity,
579 void *owner)588 void *owner)
580{589{
581 struct drm_gpu_scheduler *sched;
582
583 drm_sched_entity_select_rq(entity);590 drm_sched_entity_select_rq(entity);
584 if (!entity->rq)591 if (!entity->rq)
585 return -ENOENT;592 return -ENOENT;
586 593
587 sched = entity->rq->sched;
588
589 job->sched = sched;
590 job->entity = entity;594 job->entity = entity;
591 job->s_priority = entity->rq - sched->sched_rq;595 job->s_fence = drm_sched_fence_alloc(entity, owner);
592 job->s_fence = drm_sched_fence_create(entity, owner);
593 if (!job->s_fence)596 if (!job->s_fence)
594 return -ENOMEM;597 return -ENOMEM;
595 job->id = atomic64_inc_return(&sched->job_id_count);
596 598
597 INIT_LIST_HEAD(&job->list);599 INIT_LIST_HEAD(&job->list);
598 600
601 xa_init_flags(&job->dependencies, XA_FLAGS_ALLOC);
602
599 return 0;603 return 0;
600}604}
601EXPORT_SYMBOL(drm_sched_job_init);605EXPORT_SYMBOL(drm_sched_job_init);
602 606
603/**607/**
604 * drm_sched_job_cleanup - clean up scheduler job resources608 * drm_sched_job_arm - arm a scheduler job for execution
609 * @job: scheduler job to arm
610 *
611 * This arms a scheduler job for execution. Specifically it initializes the
612 * &drm_sched_job.s_fence of @job, so that it can be attached to struct dma_resv
613 * or other places that need to track the completion of this job.
614 *
615 * Refer to drm_sched_entity_push_job() documentation for locking
616 * considerations.
617 *
618 * This can only be called if drm_sched_job_init() succeeded.
619 */
620void drm_sched_job_arm(struct drm_sched_job *job)
621{
622 struct drm_gpu_scheduler *sched;
623 struct drm_sched_entity *entity = job->entity;
624
625 BUG_ON(!entity);
626
627 sched = entity->rq->sched;
628
629 job->sched = sched;
630 job->s_priority = entity->rq - sched->sched_rq;
631 job->id = atomic64_inc_return(&sched->job_id_count);
632
633 drm_sched_fence_init(job->s_fence, job->entity);
634}
635EXPORT_SYMBOL(drm_sched_job_arm);
636
637/**
638 * drm_sched_job_add_dependency - adds the fence as a job dependency
639 * @job: scheduler job to add the dependencies to
640 * @fence: the dma_fence to add to the list of dependencies.
641 *
642 * Note that @fence is consumed in both the success and error cases.
643 *
644 * Returns:
645 * 0 on success, or an error on failing to expand the array.
646 */
647int drm_sched_job_add_dependency(struct drm_sched_job *job,
648 struct dma_fence *fence)
649{
650 struct dma_fence *entry;
651 unsigned long index;
652 u32 id = 0;
653 int ret;
654
655 if (!fence)
656 return 0;
657
658 /* Deduplicate if we already depend on a fence from the same context.
659 * This lets the size of the array of deps scale with the number of
660 * engines involved, rather than the number of BOs.
661 */
662 xa_for_each(&job->dependencies, index, entry) {
663 if (entry->context != fence->context)
664 continue;
665
666 if (dma_fence_is_later(fence, entry)) {
667 dma_fence_put(entry);
668 xa_store(&job->dependencies, index, fence, GFP_KERNEL);
669 } else {
670 dma_fence_put(fence);
671 }
672 return 0;
673 }
674
675 ret = xa_alloc(&job->dependencies, &id, fence, xa_limit_32b, GFP_KERNEL);
676 if (ret != 0)
677 dma_fence_put(fence);
678
679 return ret;
680}
681EXPORT_SYMBOL(drm_sched_job_add_dependency);
682
683/**
684 * drm_sched_job_add_implicit_dependencies - adds implicit dependencies as job
685 * dependencies
686 * @job: scheduler job to add the dependencies to
687 * @obj: the gem object to add new dependencies from.
688 * @write: whether the job might write the object (so we need to depend on
689 * shared fences in the reservation object).
605 *690 *
691 * This should be called after drm_gem_lock_reservations() on your array of
692 * GEM objects used in the job but before updating the reservations with your
693 * own fences.
694 *
695 * Returns:
696 * 0 on success, or an error on failing to expand the array.
697 */
698int drm_sched_job_add_implicit_dependencies(struct drm_sched_job *job,
699 struct drm_gem_object *obj,
700 bool write)
701{
702 int ret;
703 struct dma_fence **fences;
704 unsigned int i, fence_count;
705
706 if (!write) {
707 struct dma_fence *fence = dma_resv_get_excl_unlocked(obj->resv);
708
709 return drm_sched_job_add_dependency(job, fence);
710 }
711
712 ret = dma_resv_get_fences(obj->resv, NULL, &fence_count, &fences);
713 if (ret || !fence_count)
714 return ret;
715
716 for (i = 0; i < fence_count; i++) {
717 ret = drm_sched_job_add_dependency(job, fences[i]);
718 if (ret)
719 break;
720 }
721
722 for (; i < fence_count; i++)
723 dma_fence_put(fences[i]);
724 kfree(fences);
725 return ret;
726}
727EXPORT_SYMBOL(drm_sched_job_add_implicit_dependencies);
728
729
730/**
731 * drm_sched_job_cleanup - clean up scheduler job resources
606 * @job: scheduler job to clean up732 * @job: scheduler job to clean up
733 *
734 * Cleans up the resources allocated with drm_sched_job_init().
735 *
736 * Drivers should call this from their error unwind code if @job is aborted
737 * before drm_sched_job_arm() is called.
738 *
739 * After that point of no return @job is committed to be executed by the
740 * scheduler, and this function should be called from the
741 * &drm_sched_backend_ops.free_job callback.
607 */742 */
608void drm_sched_job_cleanup(struct drm_sched_job *job)743void drm_sched_job_cleanup(struct drm_sched_job *job)
609{744{
610 dma_fence_put(&job->s_fence->finished);745 struct dma_fence *fence;
746 unsigned long index;
747
748 if (kref_read(&job->s_fence->finished.refcount)) {
749 /* drm_sched_job_arm() has been called */
750 dma_fence_put(&job->s_fence->finished);
751 } else {
752 /* aborted job before committing to run it */
753 drm_sched_fence_free(job->s_fence);
754 }
755
611 job->s_fence = NULL;756 job->s_fence = NULL;
757
758 xa_for_each(&job->dependencies, index, fence) {
759 dma_fence_put(fence);
760 }
761 xa_destroy(&job->dependencies);
762
612}763}
613EXPORT_SYMBOL(drm_sched_job_cleanup);764EXPORT_SYMBOL(drm_sched_job_cleanup);
614 765
@@ -676,15 +827,6 @@ drm_sched_get_cleanup_job(struct drm_gpu_scheduler *sched) · 61 unmodified lines
676{827{
677 struct drm_sched_job *job, *next;828 struct drm_sched_job *job, *next;
678 829
679 /*
680 * Don't destroy jobs while the timeout worker is running OR thread
681 * is being parked and hence assumed to not touch pending_list
682 */
683 if ((sched->timeout != MAX_SCHEDULE_TIMEOUT &&
684 !cancel_delayed_work(&sched->work_tdr)) ||
685 kthread_should_park())
686 return NULL;
687
688 spin_lock(&sched->job_list_lock);830 spin_lock(&sched->job_list_lock);
689 831
690 job = list_first_entry_or_null(&sched->pending_list,832 job = list_first_entry_or_null(&sched->pending_list,
@@ -693,17 +835,21 @@ drm_sched_get_cleanup_job(struct drm_gpu_scheduler *sched) · 2 unmodified lines
693 if (job && dma_fence_is_signaled(&job->s_fence->finished)) {835 if (job && dma_fence_is_signaled(&job->s_fence->finished)) {
694 /* remove job from pending_list */836 /* remove job from pending_list */
695 list_del_init(&job->list);837 list_del_init(&job->list);
838
839 /* cancel this job's TO timer */
840 cancel_delayed_work(&sched->work_tdr);
696 /* make the scheduled timestamp more accurate */841 /* make the scheduled timestamp more accurate */
697 next = list_first_entry_or_null(&sched->pending_list,842 next = list_first_entry_or_null(&sched->pending_list,
698 typeof(*next), list);843 typeof(*next), list);
699 if (next)844
845 if (next) {
700 next->s_fence->scheduled.timestamp =846 next->s_fence->scheduled.timestamp =
701 job->s_fence->finished.timestamp;847 job->s_fence->finished.timestamp;
702 848 /* start TO timer for next job */
849 drm_sched_start_timeout(sched);
850 }
703 } else {851 } else {
704 job = NULL;852 job = NULL;
705 /* queue timeout for next job */
706 drm_sched_start_timeout(sched);
707 }853 }
708 854
709 spin_unlock(&sched->job_list_lock);855 spin_unlock(&sched->job_list_lock);
@@ -791,11 +937,8 @@ static int drm_sched_main(void *param) · 81 unmodified lines
791 (entity = drm_sched_select_entity(sched))) ||937 (entity = drm_sched_select_entity(sched))) ||
792 kthread_should_stop());938 kthread_should_stop());
793 939
794 if (cleanup_job) {940 if (cleanup_job)
795 sched->ops->free_job(cleanup_job);941 sched->ops->free_job(cleanup_job);
796 /* queue timeout for next job */
797 drm_sched_start_timeout(sched);
798 }
799 942
800 if (!entity)943 if (!entity)
801 continue;944 continue;
drivers/gpu/drm/stm/ltdc.c+6−1
@@ -845,7 +845,7 @@ static void ltdc_plane_atomic_update(struct drm_plane *plane, · 844 unmodified lines
845 LXCFBLR_CFBLL | LXCFBLR_CFBP, val);845 LXCFBLR_CFBLL | LXCFBLR_CFBP, val);
846 846
847 /* Specifies the constant alpha value */847 /* Specifies the constant alpha value */
848 val = CONSTA_MAX;848 val = newstate->alpha >> 8;
849 reg_update_bits(ldev->regs, LTDC_L1CACR + lofs, LXCACR_CONSTA, val);849 reg_update_bits(ldev->regs, LTDC_L1CACR + lofs, LXCACR_CONSTA, val);
850 850
851 /* Specifies the blending factors */851 /* Specifies the blending factors */
@@ -997,6 +997,8 @@ static struct drm_plane *ltdc_plane_create(struct drm_device *ddev, · 145 unmodified lines
997 997
998 drm_plane_helper_add(plane, &ltdc_plane_helper_funcs);998 drm_plane_helper_add(plane, &ltdc_plane_helper_funcs);
999 999
1000 drm_plane_create_alpha_property(plane);
1001
1000 DRM_DEBUG_DRIVER("plane:%d created\n", plane->base.id);1002 DRM_DEBUG_DRIVER("plane:%d created\n", plane->base.id);
1001 1003
1002 return plane;1004 return plane;
@@ -1024,6 +1026,8 @@ static int ltdc_crtc_init(struct drm_device *ddev, struct drm_crtc *crtc) · 21 unmodified lines
1024 return -EINVAL;1026 return -EINVAL;
1025 }1027 }
1026 1028
1029 drm_plane_create_zpos_immutable_property(primary, 0);
1030
1027 ret = drm_crtc_init_with_planes(ddev, crtc, primary, NULL,1031 ret = drm_crtc_init_with_planes(ddev, crtc, primary, NULL,
1028 &ltdc_crtc_funcs, NULL);1032 &ltdc_crtc_funcs, NULL);
1029 if (ret) {1033 if (ret) {
@@ -1046,6 +1050,7 @@ static int ltdc_crtc_init(struct drm_device *ddev, struct drm_crtc *crtc) · 16 unmodified lines
1046 DRM_ERROR("Can not create overlay plane %d\n", i);1050 DRM_ERROR("Can not create overlay plane %d\n", i);
1047 goto cleanup;1051 goto cleanup;
1048 }1052 }
1053 drm_plane_create_zpos_immutable_property(overlay, i);
1049 }1054 }
1050 1055
1051 return 0;1056 return 0;
drivers/gpu/drm/sun4i/sun4i_backend.c+1−3
@@ -782,7 +782,6 @@ static int sun4i_backend_bind(struct device *dev, struct device *master, · 781 unmodified lines
782 struct sun4i_drv *drv = drm->dev_private;782 struct sun4i_drv *drv = drm->dev_private;
783 struct sun4i_backend *backend;783 struct sun4i_backend *backend;
784 const struct sun4i_backend_quirks *quirks;784 const struct sun4i_backend_quirks *quirks;
785 struct resource *res;
786 void __iomem *regs;785 void __iomem *regs;
787 int i, ret;786 int i, ret;
788 787
@@ -815,8 +814,7 @@ static int sun4i_backend_bind(struct device *dev, struct device *master, · 26 unmodified lines
815 if (IS_ERR(backend->frontend))814 if (IS_ERR(backend->frontend))
816 dev_warn(dev, "Couldn't find matching frontend, frontend features disabled\n");815 dev_warn(dev, "Couldn't find matching frontend, frontend features disabled\n");
817 816
818 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);817 regs = devm_platform_ioremap_resource(pdev, 0);
819 regs = devm_ioremap_resource(dev, res);
820 if (IS_ERR(regs))818 if (IS_ERR(regs))
821 return PTR_ERR(regs);819 return PTR_ERR(regs);
822 820
drivers/gpu/drm/sun4i/sun4i_frontend.c+1−3
@@ -561,7 +561,6 @@ static int sun4i_frontend_bind(struct device *dev, struct device *master, · 560 unmodified lines
561 struct sun4i_frontend *frontend;561 struct sun4i_frontend *frontend;
562 struct drm_device *drm = data;562 struct drm_device *drm = data;
563 struct sun4i_drv *drv = drm->dev_private;563 struct sun4i_drv *drv = drm->dev_private;
564 struct resource *res;
565 void __iomem *regs;564 void __iomem *regs;
566 565
567 frontend = devm_kzalloc(dev, sizeof(*frontend), GFP_KERNEL);566 frontend = devm_kzalloc(dev, sizeof(*frontend), GFP_KERNEL);
@@ -576,8 +575,7 @@ static int sun4i_frontend_bind(struct device *dev, struct device *master, · 8 unmodified lines
576 if (!frontend->data)575 if (!frontend->data)
577 return -ENODEV;576 return -ENODEV;
578 577
579 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);578 regs = devm_platform_ioremap_resource(pdev, 0);
580 regs = devm_ioremap_resource(dev, res);
581 if (IS_ERR(regs))579 if (IS_ERR(regs))
582 return PTR_ERR(regs);580 return PTR_ERR(regs);
583 581
drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c+1−3
@@ -489,7 +489,6 @@ static int sun4i_hdmi_bind(struct device *dev, struct device *master, · 488 unmodified lines
489 struct cec_connector_info conn_info;489 struct cec_connector_info conn_info;
490 struct sun4i_drv *drv = drm->dev_private;490 struct sun4i_drv *drv = drm->dev_private;
491 struct sun4i_hdmi *hdmi;491 struct sun4i_hdmi *hdmi;
492 struct resource *res;
493 u32 reg;492 u32 reg;
494 int ret;493 int ret;
495 494
@@ -504,8 +503,7 @@ static int sun4i_hdmi_bind(struct device *dev, struct device *master, · 8 unmodified lines
504 if (!hdmi->variant)503 if (!hdmi->variant)
505 return -EINVAL;504 return -EINVAL;
506 505
507 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);506 hdmi->base = devm_platform_ioremap_resource(pdev, 0);
508 hdmi->base = devm_ioremap_resource(dev, res);
509 if (IS_ERR(hdmi->base)) {507 if (IS_ERR(hdmi->base)) {
510 dev_err(dev, "Couldn't map the HDMI encoder registers\n");508 dev_err(dev, "Couldn't map the HDMI encoder registers\n");
511 return PTR_ERR(hdmi->base);509 return PTR_ERR(hdmi->base);
drivers/gpu/drm/sun4i/sun4i_tcon.c+1−3
@@ -841,11 +841,9 @@ static int sun4i_tcon_init_regmap(struct device *dev, · 840 unmodified lines
841 struct sun4i_tcon *tcon)841 struct sun4i_tcon *tcon)
842{842{
843 struct platform_device *pdev = to_platform_device(dev);843 struct platform_device *pdev = to_platform_device(dev);
844 struct resource *res;
845 void __iomem *regs;844 void __iomem *regs;
846 845
847 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);846 regs = devm_platform_ioremap_resource(pdev, 0);
848 regs = devm_ioremap_resource(dev, res);
849 if (IS_ERR(regs))847 if (IS_ERR(regs))
850 return PTR_ERR(regs);848 return PTR_ERR(regs);
851 849
drivers/gpu/drm/sun4i/sun4i_tv.c+1−3
@@ -538,7 +538,6 @@ static int sun4i_tv_bind(struct device *dev, struct device *master, · 537 unmodified lines
538 struct drm_device *drm = data;538 struct drm_device *drm = data;
539 struct sun4i_drv *drv = drm->dev_private;539 struct sun4i_drv *drv = drm->dev_private;
540 struct sun4i_tv *tv;540 struct sun4i_tv *tv;
541 struct resource *res;
542 void __iomem *regs;541 void __iomem *regs;
543 int ret;542 int ret;
544 543
@@ -548,8 +547,7 @@ static int sun4i_tv_bind(struct device *dev, struct device *master, · 3 unmodified lines
548 tv->drv = drv;547 tv->drv = drv;
549 dev_set_drvdata(dev, tv);548 dev_set_drvdata(dev, tv);
550 549
551 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);550 regs = devm_platform_ioremap_resource(pdev, 0);
552 regs = devm_ioremap_resource(dev, res);
553 if (IS_ERR(regs)) {551 if (IS_ERR(regs)) {
554 dev_err(dev, "Couldn't map the TV encoder registers\n");552 dev_err(dev, "Couldn't map the TV encoder registers\n");
555 return PTR_ERR(regs);553 return PTR_ERR(regs);
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c+1−3
@@ -1104,7 +1104,6 @@ static int sun6i_dsi_probe(struct platform_device *pdev) · 1103 unmodified lines
1104 struct device *dev = &pdev->dev;1104 struct device *dev = &pdev->dev;
1105 const char *bus_clk_name = NULL;1105 const char *bus_clk_name = NULL;
1106 struct sun6i_dsi *dsi;1106 struct sun6i_dsi *dsi;
1107 struct resource *res;
1108 void __iomem *base;1107 void __iomem *base;
1109 int ret;1108 int ret;
1110 1109
@@ -1120,8 +1119,7 @@ static int sun6i_dsi_probe(struct platform_device *pdev) · 9 unmodified lines
1120 "allwinner,sun6i-a31-mipi-dsi"))1119 "allwinner,sun6i-a31-mipi-dsi"))
1121 bus_clk_name = "bus";1120 bus_clk_name = "bus";
1122 1121
1123 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);1122 base = devm_platform_ioremap_resource(pdev, 0);
1124 base = devm_ioremap_resource(dev, res);
1125 if (IS_ERR(base)) {1123 if (IS_ERR(base)) {
1126 dev_err(dev, "Couldn't map the DSI encoder registers\n");1124 dev_err(dev, "Couldn't map the DSI encoder registers\n");
1127 return PTR_ERR(base);1125 return PTR_ERR(base);
drivers/gpu/drm/sun4i/sun8i_csc.h+2−2
@@ -16,8 +16,8 @@ struct sun8i_mixer; · 15 unmodified lines
16#define CCSC10_OFFSET 0xA000016#define CCSC10_OFFSET 0xA0000
17#define CCSC11_OFFSET 0xF000017#define CCSC11_OFFSET 0xF0000
18 18
19#define SUN8I_CSC_CTRL(base) (base + 0x0)19#define SUN8I_CSC_CTRL(base) ((base) + 0x0)
20#define SUN8I_CSC_COEFF(base, i) (base + 0x10 + 4 * i)20#define SUN8I_CSC_COEFF(base, i) ((base) + 0x10 + 4 * (i))
21 21
22#define SUN8I_CSC_CTRL_EN BIT(0)22#define SUN8I_CSC_CTRL_EN BIT(0)
23 23
drivers/gpu/drm/sun4i/sun8i_mixer.c+1−3
@@ -337,7 +337,6 @@ static int sun8i_mixer_bind(struct device *dev, struct device *master, · 336 unmodified lines
337 struct drm_device *drm = data;337 struct drm_device *drm = data;
338 struct sun4i_drv *drv = drm->dev_private;338 struct sun4i_drv *drv = drm->dev_private;
339 struct sun8i_mixer *mixer;339 struct sun8i_mixer *mixer;
340 struct resource *res;
341 void __iomem *regs;340 void __iomem *regs;
342 unsigned int base;341 unsigned int base;
343 int plane_cnt;342 int plane_cnt;
@@ -390,8 +389,7 @@ static int sun8i_mixer_bind(struct device *dev, struct device *master, · 46 unmodified lines
390 if (!mixer->cfg)389 if (!mixer->cfg)
391 return -EINVAL;390 return -EINVAL;
392 391
393 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);392 regs = devm_platform_ioremap_resource(pdev, 0);
394 regs = devm_ioremap_resource(dev, res);
395 if (IS_ERR(regs))393 if (IS_ERR(regs))
396 return PTR_ERR(regs);394 return PTR_ERR(regs);
397 395
drivers/gpu/drm/sun4i/sun8i_tcon_top.c+1−3
@@ -128,7 +128,6 @@ static int sun8i_tcon_top_bind(struct device *dev, struct device *master, · 127 unmodified lines
128 struct clk_hw_onecell_data *clk_data;128 struct clk_hw_onecell_data *clk_data;
129 struct sun8i_tcon_top *tcon_top;129 struct sun8i_tcon_top *tcon_top;
130 const struct sun8i_tcon_top_quirks *quirks;130 const struct sun8i_tcon_top_quirks *quirks;
131 struct resource *res;
132 void __iomem *regs;131 void __iomem *regs;
133 int ret, i;132 int ret, i;
134 133
@@ -158,8 +157,7 @@ static int sun8i_tcon_top_bind(struct device *dev, struct device *master, · 23 unmodified lines
158 return PTR_ERR(tcon_top->bus);157 return PTR_ERR(tcon_top->bus);
159 }158 }
160 159
161 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);160 regs = devm_platform_ioremap_resource(pdev, 0);
162 regs = devm_ioremap_resource(dev, res);
163 tcon_top->regs = regs;161 tcon_top->regs = regs;
164 if (IS_ERR(regs))162 if (IS_ERR(regs))
165 return PTR_ERR(regs);163 return PTR_ERR(regs);
drivers/gpu/drm/tegra/fb.c+1−1
@@ -44,7 +44,7 @@ int tegra_fb_get_tiling(struct drm_framebuffer *framebuffer, · 43 unmodified lines
44{44{
45 uint64_t modifier = framebuffer->modifier;45 uint64_t modifier = framebuffer->modifier;
46 46
47 if ((modifier >> 56) == DRM_FORMAT_MOD_VENDOR_NVIDIA) {47 if (fourcc_mod_is_vendor(modifier, NVIDIA)) {
48 if ((modifier & DRM_FORMAT_MOD_NVIDIA_SECTOR_LAYOUT) == 0)48 if ((modifier & DRM_FORMAT_MOD_NVIDIA_SECTOR_LAYOUT) == 0)
49 tiling->sector_layout = TEGRA_BO_SECTOR_LAYOUT_TEGRA;49 tiling->sector_layout = TEGRA_BO_SECTOR_LAYOUT_TEGRA;
50 else50 else
drivers/gpu/drm/tegra/plane.c+1−1
@@ -113,7 +113,7 @@ static bool tegra_plane_format_mod_supported(struct drm_plane *plane, · 112 unmodified lines
113 return true;113 return true;
114 114
115 /* check for the sector layout bit */115 /* check for the sector layout bit */
116 if ((modifier >> 56) == DRM_FORMAT_MOD_VENDOR_NVIDIA) {116 if (fourcc_mod_is_vendor(modifier, NVIDIA)) {
117 if (modifier & DRM_FORMAT_MOD_NVIDIA_SECTOR_LAYOUT) {117 if (modifier & DRM_FORMAT_MOD_NVIDIA_SECTOR_LAYOUT) {
118 if (!tegra_plane_supports_sector_layout(plane))118 if (!tegra_plane_supports_sector_layout(plane))
119 return false;119 return false;
drivers/gpu/drm/tiny/Kconfig+2−2
@@ -44,7 +44,7 @@ config DRM_CIRRUS_QEMU · 43 unmodified lines
44 44
45config DRM_GM12U32045config DRM_GM12U320
46 tristate "GM12U320 driver for USB projectors"46 tristate "GM12U320 driver for USB projectors"
47 depends on DRM && USB47 depends on DRM && USB && MMU
48 select DRM_KMS_HELPER48 select DRM_KMS_HELPER
49 select DRM_GEM_SHMEM_HELPER49 select DRM_GEM_SHMEM_HELPER
50 help50 help
@@ -53,7 +53,7 @@ config DRM_GM12U320 · 2 unmodified lines
53 53
54config DRM_SIMPLEDRM54config DRM_SIMPLEDRM
55 tristate "Simple framebuffer driver"55 tristate "Simple framebuffer driver"
56 depends on DRM56 depends on DRM && MMU
57 select DRM_GEM_SHMEM_HELPER57 select DRM_GEM_SHMEM_HELPER
58 select DRM_KMS_HELPER58 select DRM_KMS_HELPER
59 help59 help
drivers/gpu/drm/tiny/bochs.c+8−0
@@ -63,6 +63,7 @@ MODULE_PARM_DESC(defy, "default y resolution"); · 62 unmodified lines
63 63
64enum bochs_types {64enum bochs_types {
65 BOCHS_QEMU_STDVGA,65 BOCHS_QEMU_STDVGA,
66 BOCHS_SIMICS,
66 BOCHS_UNKNOWN,67 BOCHS_UNKNOWN,
67};68};
68 69
@@ -695,6 +696,13 @@ static const struct pci_device_id bochs_pci_tbl[] = { · 626 unmodified lines
695 .subdevice = PCI_ANY_ID,696 .subdevice = PCI_ANY_ID,
696 .driver_data = BOCHS_UNKNOWN,697 .driver_data = BOCHS_UNKNOWN,
697 },698 },
699 {
700 .vendor = 0x4321,
701 .device = 0x1111,
702 .subvendor = PCI_ANY_ID,
703 .subdevice = PCI_ANY_ID,
704 .driver_data = BOCHS_SIMICS,
705 },
698 { /* end of list */ }706 { /* end of list */ }
699};707};
700 708
drivers/gpu/drm/ttm/ttm_bo.c+16−51
@@ -69,7 +69,17 @@ static void ttm_bo_mem_space_debug(struct ttm_buffer_object *bo, · 68 unmodified lines
69 }69 }
70}70}
71 71
72static void ttm_bo_del_from_lru(struct ttm_buffer_object *bo)72static inline void ttm_bo_move_to_pinned(struct ttm_buffer_object *bo)
73{
74 struct ttm_device *bdev = bo->bdev;
75
76 list_move_tail(&bo->lru, &bdev->pinned);
77
78 if (bdev->funcs->del_from_lru_notify)
79 bdev->funcs->del_from_lru_notify(bo);
80}
81
82static inline void ttm_bo_del_from_lru(struct ttm_buffer_object *bo)
73{83{
74 struct ttm_device *bdev = bo->bdev;84 struct ttm_device *bdev = bo->bdev;
75 85
@@ -98,7 +108,7 @@ void ttm_bo_move_to_lru_tail(struct ttm_buffer_object *bo, · 22 unmodified lines
98 dma_resv_assert_held(bo->base.resv);108 dma_resv_assert_held(bo->base.resv);
99 109
100 if (bo->pin_count) {110 if (bo->pin_count) {
101 ttm_bo_del_from_lru(bo);111 ttm_bo_move_to_pinned(bo);
102 return;112 return;
103 }113 }
104 114
@@ -342,7 +352,7 @@ static int ttm_bo_cleanup_refs(struct ttm_buffer_object *bo, · 237 unmodified lines
342 return ret;352 return ret;
343 }353 }
344 354
345 ttm_bo_del_from_lru(bo);355 ttm_bo_move_to_pinned(bo);
346 list_del_init(&bo->ddestroy);356 list_del_init(&bo->ddestroy);
347 spin_unlock(&bo->bdev->lru_lock);357 spin_unlock(&bo->bdev->lru_lock);
348 ttm_bo_cleanup_memtype_use(bo);358 ttm_bo_cleanup_memtype_use(bo);
@@ -914,57 +924,11 @@ out: · 565 unmodified lines
914 return ret;924 return ret;
915}925}
916 926
917static bool ttm_bo_places_compat(const struct ttm_place *places,
918 unsigned num_placement,
919 struct ttm_resource *mem,
920 uint32_t *new_flags)
921{
922 unsigned i;
923
924 if (mem->placement & TTM_PL_FLAG_TEMPORARY)
925 return false;
926
927 for (i = 0; i < num_placement; i++) {
928 const struct ttm_place *heap = &places[i];
929
930 if ((mem->start < heap->fpfn ||
931 (heap->lpfn != 0 && (mem->start + mem->num_pages) > heap->lpfn)))
932 continue;
933
934 *new_flags = heap->flags;
935 if ((mem->mem_type == heap->mem_type) &&
936 (!(*new_flags & TTM_PL_FLAG_CONTIGUOUS) ||
937 (mem->placement & TTM_PL_FLAG_CONTIGUOUS)))
938 return true;
939 }
940 return false;
941}
942
943bool ttm_bo_mem_compat(struct ttm_placement *placement,
944 struct ttm_resource *mem,
945 uint32_t *new_flags)
946{
947 if (ttm_bo_places_compat(placement->placement, placement->num_placement,
948 mem, new_flags))
949 return true;
950
951 if ((placement->busy_placement != placement->placement ||
952 placement->num_busy_placement > placement->num_placement) &&
953 ttm_bo_places_compat(placement->busy_placement,
954 placement->num_busy_placement,
955 mem, new_flags))
956 return true;
957
958 return false;
959}
960EXPORT_SYMBOL(ttm_bo_mem_compat);
961
962int ttm_bo_validate(struct ttm_buffer_object *bo,927int ttm_bo_validate(struct ttm_buffer_object *bo,
963 struct ttm_placement *placement,928 struct ttm_placement *placement,
964 struct ttm_operation_ctx *ctx)929 struct ttm_operation_ctx *ctx)
965{930{
966 int ret;931 int ret;
967 uint32_t new_flags;
968 932
969 dma_resv_assert_held(bo->base.resv);933 dma_resv_assert_held(bo->base.resv);
970 934
@@ -977,7 +941,7 @@ int ttm_bo_validate(struct ttm_buffer_object *bo, · 6 unmodified lines
977 /*941 /*
978 * Check whether we need to move buffer.942 * Check whether we need to move buffer.
979 */943 */
980 if (!ttm_bo_mem_compat(placement, bo->resource, &new_flags)) {944 if (!ttm_resource_compat(bo->resource, placement)) {
981 ret = ttm_bo_move_buffer(bo, placement, ctx);945 ret = ttm_bo_move_buffer(bo, placement, ctx);
982 if (ret)946 if (ret)
983 return ret;947 return ret;
@@ -1165,7 +1129,7 @@ int ttm_bo_swapout(struct ttm_buffer_object *bo, struct ttm_operation_ctx *ctx, · 181 unmodified lines
1165 return ret == -EBUSY ? -ENOSPC : ret;1129 return ret == -EBUSY ? -ENOSPC : ret;
1166 }1130 }
1167 1131
1168 ttm_bo_del_from_lru(bo);1132 ttm_bo_move_to_pinned(bo);
1169 /* TODO: Cleanup the locking */1133 /* TODO: Cleanup the locking */
1170 spin_unlock(&bo->bdev->lru_lock);1134 spin_unlock(&bo->bdev->lru_lock);
1171 1135
@@ -1224,6 +1188,7 @@ void ttm_bo_tt_destroy(struct ttm_buffer_object *bo) · 52 unmodified lines
1224 if (bo->ttm == NULL)1188 if (bo->ttm == NULL)
1225 return;1189 return;
1226 1190
1191 ttm_tt_unpopulate(bo->bdev, bo->ttm);
1227 ttm_tt_destroy(bo->bdev, bo->ttm);1192 ttm_tt_destroy(bo->bdev, bo->ttm);
1228 bo->ttm = NULL;1193 bo->ttm = NULL;
1229}1194}
drivers/gpu/drm/ttm/ttm_device.c+48−0
@@ -220,6 +220,7 @@ int ttm_device_init(struct ttm_device *bdev, struct ttm_device_funcs *funcs, · 219 unmodified lines
220 INIT_DELAYED_WORK(&bdev->wq, ttm_device_delayed_workqueue);220 INIT_DELAYED_WORK(&bdev->wq, ttm_device_delayed_workqueue);
221 spin_lock_init(&bdev->lru_lock);221 spin_lock_init(&bdev->lru_lock);
222 INIT_LIST_HEAD(&bdev->ddestroy);222 INIT_LIST_HEAD(&bdev->ddestroy);
223 INIT_LIST_HEAD(&bdev->pinned);
223 bdev->dev_mapping = mapping;224 bdev->dev_mapping = mapping;
224 mutex_lock(&ttm_global_mutex);225 mutex_lock(&ttm_global_mutex);
225 list_add_tail(&bdev->device_list, &glob->device_list);226 list_add_tail(&bdev->device_list, &glob->device_list);
@@ -257,3 +258,50 @@ void ttm_device_fini(struct ttm_device *bdev) · 31 unmodified lines
257 ttm_global_release();258 ttm_global_release();
258}259}
259EXPORT_SYMBOL(ttm_device_fini);260EXPORT_SYMBOL(ttm_device_fini);
261
262void ttm_device_clear_dma_mappings(struct ttm_device *bdev)
263{
264 struct ttm_resource_manager *man;
265 struct ttm_buffer_object *bo;
266 unsigned int i, j;
267
268 spin_lock(&bdev->lru_lock);
269 while (!list_empty(&bdev->pinned)) {
270 bo = list_first_entry(&bdev->pinned, struct ttm_buffer_object, lru);
271 /* Take ref against racing releases once lru_lock is unlocked */
272 if (ttm_bo_get_unless_zero(bo)) {
273 list_del_init(&bo->lru);
274 spin_unlock(&bdev->lru_lock);
275
276 if (bo->ttm)
277 ttm_tt_unpopulate(bo->bdev, bo->ttm);
278
279 ttm_bo_put(bo);
280 spin_lock(&bdev->lru_lock);
281 }
282 }
283
284 for (i = TTM_PL_SYSTEM; i < TTM_NUM_MEM_TYPES; ++i) {
285 man = ttm_manager_type(bdev, i);
286 if (!man || !man->use_tt)
287 continue;
288
289 for (j = 0; j < TTM_MAX_BO_PRIORITY; ++j) {
290 while (!list_empty(&man->lru[j])) {
291 bo = list_first_entry(&man->lru[j], struct ttm_buffer_object, lru);
292 if (ttm_bo_get_unless_zero(bo)) {
293 list_del_init(&bo->lru);
294 spin_unlock(&bdev->lru_lock);
295
296 if (bo->ttm)
297 ttm_tt_unpopulate(bo->bdev, bo->ttm);
298
299 ttm_bo_put(bo);
300 spin_lock(&bdev->lru_lock);
301 }
302 }
303 }
304 }
305 spin_unlock(&bdev->lru_lock);
306}
307EXPORT_SYMBOL(ttm_device_clear_dma_mappings);
drivers/gpu/drm/ttm/ttm_module.c+12−0
@@ -39,6 +39,18 @@ · 38 unmodified lines
39 39
40#include "ttm_module.h"40#include "ttm_module.h"
41 41
42/**
43 * DOC: TTM
44 *
45 * TTM is a memory manager for accelerator devices with dedicated memory.
46 *
47 * The basic idea is that resources are grouped together in buffer objects of
48 * certain size and TTM handles lifetime, movement and CPU mappings of those
49 * objects.
50 *
51 * TODO: Add more design background and information here.
52 */
53
42/**54/**
43 * ttm_prot_from_caching - Modify the page protection according to the55 * ttm_prot_from_caching - Modify the page protection according to the
44 * ttm cacing mode56 * ttm cacing mode
drivers/gpu/drm/ttm/ttm_pool.c+22−18
@@ -70,7 +70,7 @@ static struct ttm_pool_type global_uncached[MAX_ORDER]; · 69 unmodified lines
70static struct ttm_pool_type global_dma32_write_combined[MAX_ORDER];70static struct ttm_pool_type global_dma32_write_combined[MAX_ORDER];
71static struct ttm_pool_type global_dma32_uncached[MAX_ORDER];71static struct ttm_pool_type global_dma32_uncached[MAX_ORDER];
72 72
73static struct mutex shrinker_lock;73static spinlock_t shrinker_lock;
74static struct list_head shrinker_list;74static struct list_head shrinker_list;
75static struct shrinker mm_shrinker;75static struct shrinker mm_shrinker;
76 76
@@ -263,9 +263,9 @@ static void ttm_pool_type_init(struct ttm_pool_type *pt, struct ttm_pool *pool, · 186 unmodified lines
263 spin_lock_init(&pt->lock);263 spin_lock_init(&pt->lock);
264 INIT_LIST_HEAD(&pt->pages);264 INIT_LIST_HEAD(&pt->pages);
265 265
266 mutex_lock(&shrinker_lock);266 spin_lock(&shrinker_lock);
267 list_add_tail(&pt->shrinker_list, &shrinker_list);267 list_add_tail(&pt->shrinker_list, &shrinker_list);
268 mutex_unlock(&shrinker_lock);268 spin_unlock(&shrinker_lock);
269}269}
270 270
271/* Remove a pool_type from the global shrinker list and free all pages */271/* Remove a pool_type from the global shrinker list and free all pages */
@@ -273,9 +273,9 @@ static void ttm_pool_type_fini(struct ttm_pool_type *pt) · 1 unmodified line
273{273{
274 struct page *p;274 struct page *p;
275 275
276 mutex_lock(&shrinker_lock);276 spin_lock(&shrinker_lock);
277 list_del(&pt->shrinker_list);277 list_del(&pt->shrinker_list);
278 mutex_unlock(&shrinker_lock);278 spin_unlock(&shrinker_lock);
279 279
280 while ((p = ttm_pool_type_take(pt)))280 while ((p = ttm_pool_type_take(pt)))
281 ttm_pool_free_page(pt->pool, pt->caching, pt->order, p);281 ttm_pool_free_page(pt->pool, pt->caching, pt->order, p);
@@ -313,24 +313,23 @@ static struct ttm_pool_type *ttm_pool_select_type(struct ttm_pool *pool, · 31 unmodified lines
313static unsigned int ttm_pool_shrink(void)313static unsigned int ttm_pool_shrink(void)
314{314{
315 struct ttm_pool_type *pt;315 struct ttm_pool_type *pt;
316 unsigned int num_freed;316 unsigned int num_pages;
317 struct page *p;317 struct page *p;
318 318
319 mutex_lock(&shrinker_lock);319 spin_lock(&shrinker_lock);
320 pt = list_first_entry(&shrinker_list, typeof(*pt), shrinker_list);320 pt = list_first_entry(&shrinker_list, typeof(*pt), shrinker_list);
321 list_move_tail(&pt->shrinker_list, &shrinker_list);
322 spin_unlock(&shrinker_lock);
321 323
322 p = ttm_pool_type_take(pt);324 p = ttm_pool_type_take(pt);
323 if (p) {325 if (p) {
324 ttm_pool_free_page(pt->pool, pt->caching, pt->order, p);326 ttm_pool_free_page(pt->pool, pt->caching, pt->order, p);
325 num_freed = 1 << pt->order;327 num_pages = 1 << pt->order;
326 } else {328 } else {
327 num_freed = 0;329 num_pages = 0;
328 }330 }
329 331
330 list_move_tail(&pt->shrinker_list, &shrinker_list);332 return num_pages;
331 mutex_unlock(&shrinker_lock);
332
333 return num_freed;
334}333}
335 334
336/* Return the allocation order based for a page */335/* Return the allocation order based for a page */
@@ -531,6 +530,11 @@ void ttm_pool_fini(struct ttm_pool *pool) · 194 unmodified lines
531 for (j = 0; j < MAX_ORDER; ++j)530 for (j = 0; j < MAX_ORDER; ++j)
532 ttm_pool_type_fini(&pool->caching[i].orders[j]);531 ttm_pool_type_fini(&pool->caching[i].orders[j]);
533 }532 }
533
534 /* We removed the pool types from the LRU, but we need to also make sure
535 * that no shrinker is concurrently freeing pages from the pool.
536 */
537 synchronize_shrinkers();
534}538}
535 539
536/* As long as pages are available make sure to release at least one */540/* As long as pages are available make sure to release at least one */
@@ -605,7 +609,7 @@ static int ttm_pool_debugfs_globals_show(struct seq_file *m, void *data) · 68 unmodified lines
605{609{
606 ttm_pool_debugfs_header(m);610 ttm_pool_debugfs_header(m);
607 611
608 mutex_lock(&shrinker_lock);612 spin_lock(&shrinker_lock);
609 seq_puts(m, "wc\t:");613 seq_puts(m, "wc\t:");
610 ttm_pool_debugfs_orders(global_write_combined, m);614 ttm_pool_debugfs_orders(global_write_combined, m);
611 seq_puts(m, "uc\t:");615 seq_puts(m, "uc\t:");
@@ -614,7 +618,7 @@ static int ttm_pool_debugfs_globals_show(struct seq_file *m, void *data) · 2 unmodified lines
614 ttm_pool_debugfs_orders(global_dma32_write_combined, m);618 ttm_pool_debugfs_orders(global_dma32_write_combined, m);
615 seq_puts(m, "uc 32\t:");619 seq_puts(m, "uc 32\t:");
616 ttm_pool_debugfs_orders(global_dma32_uncached, m);620 ttm_pool_debugfs_orders(global_dma32_uncached, m);
617 mutex_unlock(&shrinker_lock);621 spin_unlock(&shrinker_lock);
618 622
619 ttm_pool_debugfs_footer(m);623 ttm_pool_debugfs_footer(m);
620 624
@@ -641,7 +645,7 @@ int ttm_pool_debugfs(struct ttm_pool *pool, struct seq_file *m) · 20 unmodified lines
641 645
642 ttm_pool_debugfs_header(m);646 ttm_pool_debugfs_header(m);
643 647
644 mutex_lock(&shrinker_lock);648 spin_lock(&shrinker_lock);
645 for (i = 0; i < TTM_NUM_CACHING_TYPES; ++i) {649 for (i = 0; i < TTM_NUM_CACHING_TYPES; ++i) {
646 seq_puts(m, "DMA ");650 seq_puts(m, "DMA ");
647 switch (i) {651 switch (i) {
@@ -657,7 +661,7 @@ int ttm_pool_debugfs(struct ttm_pool *pool, struct seq_file *m) · 9 unmodified lines
657 }661 }
658 ttm_pool_debugfs_orders(pool->caching[i].orders, m);662 ttm_pool_debugfs_orders(pool->caching[i].orders, m);
659 }663 }
660 mutex_unlock(&shrinker_lock);664 spin_unlock(&shrinker_lock);
661 665
662 ttm_pool_debugfs_footer(m);666 ttm_pool_debugfs_footer(m);
663 return 0;667 return 0;
@@ -694,7 +698,7 @@ int ttm_pool_mgr_init(unsigned long num_pages) · 30 unmodified lines
694 if (!page_pool_size)698 if (!page_pool_size)
695 page_pool_size = num_pages;699 page_pool_size = num_pages;
696 700
697 mutex_init(&shrinker_lock);701 spin_lock_init(&shrinker_lock);
698 INIT_LIST_HEAD(&shrinker_list);702 INIT_LIST_HEAD(&shrinker_list);
699 703
700 for (i = 0; i < MAX_ORDER; ++i) {704 for (i = 0; i < MAX_ORDER; ++i) {
drivers/gpu/drm/ttm/ttm_range_manager.c+4−4
@@ -138,7 +138,7 @@ static const struct ttm_resource_manager_func ttm_range_manager_func = { · 137 unmodified lines
138 * Initialise a generic range manager for the selected memory type.138 * Initialise a generic range manager for the selected memory type.
139 * The range manager is installed for this device in the type slot.139 * The range manager is installed for this device in the type slot.
140 */140 */
141int ttm_range_man_init(struct ttm_device *bdev,141int ttm_range_man_init_nocheck(struct ttm_device *bdev,
142 unsigned type, bool use_tt,142 unsigned type, bool use_tt,
143 unsigned long p_size)143 unsigned long p_size)
144{144{
@@ -163,7 +163,7 @@ int ttm_range_man_init(struct ttm_device *bdev, · 18 unmodified lines
163 ttm_resource_manager_set_used(man, true);163 ttm_resource_manager_set_used(man, true);
164 return 0;164 return 0;
165}165}
166EXPORT_SYMBOL(ttm_range_man_init);166EXPORT_SYMBOL(ttm_range_man_init_nocheck);
167 167
168/**168/**
169 * ttm_range_man_fini169 * ttm_range_man_fini
@@ -173,7 +173,7 @@ EXPORT_SYMBOL(ttm_range_man_init); · 3 unmodified lines
173 *173 *
174 * Remove the generic range manager from a slot and tear it down.174 * Remove the generic range manager from a slot and tear it down.
175 */175 */
176int ttm_range_man_fini(struct ttm_device *bdev,176int ttm_range_man_fini_nocheck(struct ttm_device *bdev,
177 unsigned type)177 unsigned type)
178{178{
179 struct ttm_resource_manager *man = ttm_manager_type(bdev, type);179 struct ttm_resource_manager *man = ttm_manager_type(bdev, type);
@@ -200,4 +200,4 @@ int ttm_range_man_fini(struct ttm_device *bdev, · 20 unmodified lines
200 kfree(rman);200 kfree(rman);
201 return 0;201 return 0;
202}202}
203EXPORT_SYMBOL(ttm_range_man_fini);203EXPORT_SYMBOL(ttm_range_man_fini_nocheck);
drivers/gpu/drm/ttm/ttm_resource.c+49−0
@@ -67,6 +67,55 @@ void ttm_resource_free(struct ttm_buffer_object *bo, struct ttm_resource **res) · 66 unmodified lines
67}67}
68EXPORT_SYMBOL(ttm_resource_free);68EXPORT_SYMBOL(ttm_resource_free);
69 69
70static bool ttm_resource_places_compat(struct ttm_resource *res,
71 const struct ttm_place *places,
72 unsigned num_placement)
73{
74 unsigned i;
75
76 if (res->placement & TTM_PL_FLAG_TEMPORARY)
77 return false;
78
79 for (i = 0; i < num_placement; i++) {
80 const struct ttm_place *heap = &places[i];
81
82 if (res->start < heap->fpfn || (heap->lpfn &&
83 (res->start + res->num_pages) > heap->lpfn))
84 continue;
85
86 if ((res->mem_type == heap->mem_type) &&
87 (!(heap->flags & TTM_PL_FLAG_CONTIGUOUS) ||
88 (res->placement & TTM_PL_FLAG_CONTIGUOUS)))
89 return true;
90 }
91 return false;
92}
93
94/**
95 * ttm_resource_compat - check if resource is compatible with placement
96 *
97 * @res: the resource to check
98 * @placement: the placement to check against
99 *
100 * Returns true if the placement is compatible.
101 */
102bool ttm_resource_compat(struct ttm_resource *res,
103 struct ttm_placement *placement)
104{
105 if (ttm_resource_places_compat(res, placement->placement,
106 placement->num_placement))
107 return true;
108
109 if ((placement->busy_placement != placement->placement ||
110 placement->num_busy_placement > placement->num_placement) &&
111 ttm_resource_places_compat(res, placement->busy_placement,
112 placement->num_busy_placement))
113 return true;
114
115 return false;
116}
117EXPORT_SYMBOL(ttm_resource_compat);
118
70/**119/**
71 * ttm_resource_manager_init120 * ttm_resource_manager_init
72 *121 *
drivers/gpu/drm/ttm/ttm_tt.c+6−11
@@ -122,17 +122,6 @@ static int ttm_sg_tt_alloc_page_directory(struct ttm_tt *ttm) · 121 unmodified lines
122 return 0;122 return 0;
123}123}
124 124
125void ttm_tt_destroy_common(struct ttm_device *bdev, struct ttm_tt *ttm)
126{
127 ttm_tt_unpopulate(bdev, ttm);
128
129 if (ttm->swap_storage)
130 fput(ttm->swap_storage);
131
132 ttm->swap_storage = NULL;
133}
134EXPORT_SYMBOL(ttm_tt_destroy_common);
135
136void ttm_tt_destroy(struct ttm_device *bdev, struct ttm_tt *ttm)125void ttm_tt_destroy(struct ttm_device *bdev, struct ttm_tt *ttm)
137{126{
138 bdev->funcs->ttm_tt_destroy(bdev, ttm);127 bdev->funcs->ttm_tt_destroy(bdev, ttm);
@@ -167,6 +156,12 @@ EXPORT_SYMBOL(ttm_tt_init); · 28 unmodified lines
167 156
168void ttm_tt_fini(struct ttm_tt *ttm)157void ttm_tt_fini(struct ttm_tt *ttm)
169{158{
159 WARN_ON(ttm->page_flags & TTM_PAGE_FLAG_PRIV_POPULATED);
160
161 if (ttm->swap_storage)
162 fput(ttm->swap_storage);
163 ttm->swap_storage = NULL;
164
170 if (ttm->pages)165 if (ttm->pages)
171 kvfree(ttm->pages);166 kvfree(ttm->pages);
172 else167 else
drivers/gpu/drm/udl/Kconfig+1−0
@@ -4,6 +4,7 @@ config DRM_UDL · 3 unmodified lines
4 depends on DRM4 depends on DRM
5 depends on USB5 depends on USB
6 depends on USB_ARCH_HAS_HCD6 depends on USB_ARCH_HAS_HCD
7 depends on MMU
7 select DRM_GEM_SHMEM_HELPER8 select DRM_GEM_SHMEM_HELPER
8 select DRM_KMS_HELPER9 select DRM_KMS_HELPER
9 help10 help
drivers/gpu/drm/v3d/Kconfig+1−1
@@ -1,7 +1,7 @@
1# SPDX-License-Identifier: GPL-2.0-only1# SPDX-License-Identifier: GPL-2.0-only
2config DRM_V3D2config DRM_V3D
3 tristate "Broadcom V3D 3.x and newer"3 tristate "Broadcom V3D 3.x and newer"
4 depends on ARCH_BCM || ARCH_BCMSTB || COMPILE_TEST4 depends on ARCH_BCM || ARCH_BRCMSTB || COMPILE_TEST
5 depends on DRM5 depends on DRM
6 depends on COMMON_CLK6 depends on COMMON_CLK
7 depends on MMU7 depends on MMU
drivers/gpu/drm/v3d/v3d_drv.h+1−5
@@ -234,11 +234,6 @@ struct v3d_job { · 233 unmodified lines
234 struct drm_gem_object **bo;234 struct drm_gem_object **bo;
235 u32 bo_count;235 u32 bo_count;
236 236
237 /* Array of struct dma_fence * to block on before submitting this job.
238 */
239 struct xarray deps;
240 unsigned long last_dep;
241
242 /* v3d fence to be signaled by IRQ handler when the job is complete. */237 /* v3d fence to be signaled by IRQ handler when the job is complete. */
243 struct dma_fence *irq_fence;238 struct dma_fence *irq_fence;
244 239
@@ -379,6 +374,7 @@ int v3d_submit_csd_ioctl(struct drm_device *dev, void *data, · 134 unmodified lines
379 struct drm_file *file_priv);374 struct drm_file *file_priv);
380int v3d_wait_bo_ioctl(struct drm_device *dev, void *data,375int v3d_wait_bo_ioctl(struct drm_device *dev, void *data,
381 struct drm_file *file_priv);376 struct drm_file *file_priv);
377void v3d_job_cleanup(struct v3d_job *job);
382void v3d_job_put(struct v3d_job *job);378void v3d_job_put(struct v3d_job *job);
383void v3d_reset(struct v3d_dev *v3d);379void v3d_reset(struct v3d_dev *v3d);
384void v3d_invalidate_caches(struct v3d_dev *v3d);380void v3d_invalidate_caches(struct v3d_dev *v3d);
drivers/gpu/drm/v3d/v3d_gem.c+49−69
@@ -197,8 +197,8 @@ v3d_clean_caches(struct v3d_dev *v3d) · 196 unmodified lines
197 197
198 V3D_CORE_WRITE(core, V3D_CTL_L2TCACTL, V3D_L2TCACTL_TMUWCF);198 V3D_CORE_WRITE(core, V3D_CTL_L2TCACTL, V3D_L2TCACTL_TMUWCF);
199 if (wait_for(!(V3D_CORE_READ(core, V3D_CTL_L2TCACTL) &199 if (wait_for(!(V3D_CORE_READ(core, V3D_CTL_L2TCACTL) &
200 V3D_L2TCACTL_L2TFLS), 100)) {200 V3D_L2TCACTL_TMUWCF), 100)) {
201 DRM_ERROR("Timeout waiting for L1T write combiner flush\n");201 DRM_ERROR("Timeout waiting for TMU write combiner flush\n");
202 }202 }
203 203
204 mutex_lock(&v3d->cache_clean_lock);204 mutex_lock(&v3d->cache_clean_lock);
@@ -259,8 +259,8 @@ v3d_lock_bo_reservations(struct v3d_job *job, · 54 unmodified lines
259 return ret;259 return ret;
260 260
261 for (i = 0; i < job->bo_count; i++) {261 for (i = 0; i < job->bo_count; i++) {
262 ret = drm_gem_fence_array_add_implicit(&job->deps,262 ret = drm_sched_job_add_implicit_dependencies(&job->base,
263 job->bo[i], true);263 job->bo[i], true);
264 if (ret) {264 if (ret) {
265 drm_gem_unlock_reservations(job->bo, job->bo_count,265 drm_gem_unlock_reservations(job->bo, job->bo_count,
266 acquire_ctx);266 acquire_ctx);
@@ -356,8 +356,6 @@ static void · 89 unmodified lines
356v3d_job_free(struct kref *ref)356v3d_job_free(struct kref *ref)
357{357{
358 struct v3d_job *job = container_of(ref, struct v3d_job, refcount);358 struct v3d_job *job = container_of(ref, struct v3d_job, refcount);
359 unsigned long index;
360 struct dma_fence *fence;
361 int i;359 int i;
362 360
363 for (i = 0; i < job->bo_count; i++) {361 for (i = 0; i < job->bo_count; i++) {
@@ -366,11 +364,6 @@ v3d_job_free(struct kref *ref) · 2 unmodified lines
366 }364 }
367 kvfree(job->bo);365 kvfree(job->bo);
368 366
369 xa_for_each(&job->deps, index, fence) {
370 dma_fence_put(fence);
371 }
372 xa_destroy(&job->deps);
373
374 dma_fence_put(job->irq_fence);367 dma_fence_put(job->irq_fence);
375 dma_fence_put(job->done_fence);368 dma_fence_put(job->done_fence);
376 369
@@ -397,6 +390,12 @@ v3d_render_job_free(struct kref *ref) · 20 unmodified lines
397 v3d_job_free(ref);390 v3d_job_free(ref);
398}391}
399 392
393void v3d_job_cleanup(struct v3d_job *job)
394{
395 drm_sched_job_cleanup(&job->base);
396 v3d_job_put(job);
397}
398
400void v3d_job_put(struct v3d_job *job)399void v3d_job_put(struct v3d_job *job)
401{400{
402 kref_put(&job->refcount, job->free);401 kref_put(&job->refcount, job->free);
@@ -438,9 +437,10 @@ v3d_wait_bo_ioctl(struct drm_device *dev, void *data, · 35 unmodified lines
438static int437static int
439v3d_job_init(struct v3d_dev *v3d, struct drm_file *file_priv,438v3d_job_init(struct v3d_dev *v3d, struct drm_file *file_priv,
440 struct v3d_job *job, void (*free)(struct kref *ref),439 struct v3d_job *job, void (*free)(struct kref *ref),
441 u32 in_sync)440 u32 in_sync, enum v3d_queue queue)
442{441{
443 struct dma_fence *in_fence = NULL;442 struct dma_fence *in_fence = NULL;
443 struct v3d_file_priv *v3d_priv = file_priv->driver_priv;
444 int ret;444 int ret;
445 445
446 job->v3d = v3d;446 job->v3d = v3d;
@@ -450,44 +450,40 @@ v3d_job_init(struct v3d_dev *v3d, struct drm_file *file_priv, · 3 unmodified lines
450 if (ret < 0)450 if (ret < 0)
451 return ret;451 return ret;
452 452
453 xa_init_flags(&job->deps, XA_FLAGS_ALLOC);453 ret = drm_sched_job_init(&job->base, &v3d_priv->sched_entity[queue],
454 v3d_priv);
455 if (ret)
456 goto fail;
454 457
455 ret = drm_syncobj_find_fence(file_priv, in_sync, 0, 0, &in_fence);458 ret = drm_syncobj_find_fence(file_priv, in_sync, 0, 0, &in_fence);
456 if (ret == -EINVAL)459 if (ret == -EINVAL)
457 goto fail;460 goto fail_job;
458 461
459 ret = drm_gem_fence_array_add(&job->deps, in_fence);462 ret = drm_sched_job_add_dependency(&job->base, in_fence);
460 if (ret)463 if (ret)
461 goto fail;464 goto fail_job;
462 465
463 kref_init(&job->refcount);466 kref_init(&job->refcount);
464 467
465 return 0;468 return 0;
469fail_job:
470 drm_sched_job_cleanup(&job->base);
466fail:471fail:
467 xa_destroy(&job->deps);
468 pm_runtime_put_autosuspend(v3d->drm.dev);472 pm_runtime_put_autosuspend(v3d->drm.dev);
469 return ret;473 return ret;
470}474}
471 475
472static int476static void
473v3d_push_job(struct v3d_file_priv *v3d_priv,477v3d_push_job(struct v3d_job *job)
474 struct v3d_job *job, enum v3d_queue queue)
475{478{
476 int ret;479 drm_sched_job_arm(&job->base);
477
478 ret = drm_sched_job_init(&job->base, &v3d_priv->sched_entity[queue],
479 v3d_priv);
480 if (ret)
481 return ret;
482 480
483 job->done_fence = dma_fence_get(&job->base.s_fence->finished);481 job->done_fence = dma_fence_get(&job->base.s_fence->finished);
484 482
485 /* put by scheduler job completion */483 /* put by scheduler job completion */
486 kref_get(&job->refcount);484 kref_get(&job->refcount);
487 485
488 drm_sched_entity_push_job(&job->base, &v3d_priv->sched_entity[queue]);486 drm_sched_entity_push_job(&job->base);
489
490 return 0;
491}487}
492 488
493static void489static void
@@ -562,7 +558,7 @@ v3d_submit_cl_ioctl(struct drm_device *dev, void *data, · 68 unmodified lines
562 INIT_LIST_HEAD(&render->unref_list);558 INIT_LIST_HEAD(&render->unref_list);
563 559
564 ret = v3d_job_init(v3d, file_priv, &render->base,560 ret = v3d_job_init(v3d, file_priv, &render->base,
565 v3d_render_job_free, args->in_sync_rcl);561 v3d_render_job_free, args->in_sync_rcl, V3D_RENDER);
566 if (ret) {562 if (ret) {
567 kfree(render);563 kfree(render);
568 return ret;564 return ret;
@@ -576,7 +572,7 @@ v3d_submit_cl_ioctl(struct drm_device *dev, void *data, · 7 unmodified lines
576 }572 }
577 573
578 ret = v3d_job_init(v3d, file_priv, &bin->base,574 ret = v3d_job_init(v3d, file_priv, &bin->base,
579 v3d_job_free, args->in_sync_bcl);575 v3d_job_free, args->in_sync_bcl, V3D_BIN);
580 if (ret) {576 if (ret) {
581 v3d_job_put(&render->base);577 v3d_job_put(&render->base);
582 kfree(bin);578 kfree(bin);
@@ -598,7 +594,7 @@ v3d_submit_cl_ioctl(struct drm_device *dev, void *data, · 15 unmodified lines
598 goto fail;594 goto fail;
599 }595 }
600 596
601 ret = v3d_job_init(v3d, file_priv, clean_job, v3d_job_free, 0);597 ret = v3d_job_init(v3d, file_priv, clean_job, v3d_job_free, 0, V3D_CACHE_CLEAN);
602 if (ret) {598 if (ret) {
603 kfree(clean_job);599 kfree(clean_job);
604 clean_job = NULL;600 clean_job = NULL;
@@ -633,31 +629,26 @@ v3d_submit_cl_ioctl(struct drm_device *dev, void *data, · 28 unmodified lines
633 if (bin) {629 if (bin) {
634 bin->base.perfmon = render->base.perfmon;630 bin->base.perfmon = render->base.perfmon;
635 v3d_perfmon_get(bin->base.perfmon);631 v3d_perfmon_get(bin->base.perfmon);
636 ret = v3d_push_job(v3d_priv, &bin->base, V3D_BIN);632 v3d_push_job(&bin->base);
637 if (ret)
638 goto fail_unreserve;
639 633
640 ret = drm_gem_fence_array_add(&render->base.deps,634 ret = drm_sched_job_add_dependency(&render->base.base,
641 dma_fence_get(bin->base.done_fence));635 dma_fence_get(bin->base.done_fence));
642 if (ret)636 if (ret)
643 goto fail_unreserve;637 goto fail_unreserve;
644 }638 }
645 639
646 ret = v3d_push_job(v3d_priv, &render->base, V3D_RENDER);640 v3d_push_job(&render->base);
647 if (ret)
648 goto fail_unreserve;
649 641
650 if (clean_job) {642 if (clean_job) {
651 struct dma_fence *render_fence =643 struct dma_fence *render_fence =
652 dma_fence_get(render->base.done_fence);644 dma_fence_get(render->base.done_fence);
653 ret = drm_gem_fence_array_add(&clean_job->deps, render_fence);645 ret = drm_sched_job_add_dependency(&clean_job->base,
646 render_fence);
654 if (ret)647 if (ret)
655 goto fail_unreserve;648 goto fail_unreserve;
656 clean_job->perfmon = render->base.perfmon;649 clean_job->perfmon = render->base.perfmon;
657 v3d_perfmon_get(clean_job->perfmon);650 v3d_perfmon_get(clean_job->perfmon);
658 ret = v3d_push_job(v3d_priv, clean_job, V3D_CACHE_CLEAN);651 v3d_push_job(clean_job);
659 if (ret)
660 goto fail_unreserve;
661 }652 }
662 653
663 mutex_unlock(&v3d->sched_lock);654 mutex_unlock(&v3d->sched_lock);
@@ -682,10 +673,10 @@ fail_unreserve: · 18 unmodified lines
682 last_job->bo_count, &acquire_ctx);673 last_job->bo_count, &acquire_ctx);
683fail:674fail:
684 if (bin)675 if (bin)
685 v3d_job_put(&bin->base);676 v3d_job_cleanup(&bin->base);
686 v3d_job_put(&render->base);677 v3d_job_cleanup(&render->base);
687 if (clean_job)678 if (clean_job)
688 v3d_job_put(clean_job);679 v3d_job_cleanup(clean_job);
689 680
690 return ret;681 return ret;
691}682}
@@ -704,7 +695,6 @@ v3d_submit_tfu_ioctl(struct drm_device *dev, void *data, · 12 unmodified lines
704 struct drm_file *file_priv)695 struct drm_file *file_priv)
705{696{
706 struct v3d_dev *v3d = to_v3d_dev(dev);697 struct v3d_dev *v3d = to_v3d_dev(dev);
707 struct v3d_file_priv *v3d_priv = file_priv->driver_priv;
708 struct drm_v3d_submit_tfu *args = data;698 struct drm_v3d_submit_tfu *args = data;
709 struct v3d_tfu_job *job;699 struct v3d_tfu_job *job;
710 struct ww_acquire_ctx acquire_ctx;700 struct ww_acquire_ctx acquire_ctx;
@@ -717,7 +707,7 @@ v3d_submit_tfu_ioctl(struct drm_device *dev, void *data, · 6 unmodified lines
717 return -ENOMEM;707 return -ENOMEM;
718 708
719 ret = v3d_job_init(v3d, file_priv, &job->base,709 ret = v3d_job_init(v3d, file_priv, &job->base,
720 v3d_job_free, args->in_sync);710 v3d_job_free, args->in_sync, V3D_TFU);
721 if (ret) {711 if (ret) {
722 kfree(job);712 kfree(job);
723 return ret;713 return ret;
@@ -761,9 +751,7 @@ v3d_submit_tfu_ioctl(struct drm_device *dev, void *data, · 37 unmodified lines
761 goto fail;751 goto fail;
762 752
763 mutex_lock(&v3d->sched_lock);753 mutex_lock(&v3d->sched_lock);
764 ret = v3d_push_job(v3d_priv, &job->base, V3D_TFU);754 v3d_push_job(&job->base);
765 if (ret)
766 goto fail_unreserve;
767 mutex_unlock(&v3d->sched_lock);755 mutex_unlock(&v3d->sched_lock);
768 756
769 v3d_attach_fences_and_unlock_reservation(file_priv,757 v3d_attach_fences_and_unlock_reservation(file_priv,
@@ -775,12 +763,8 @@ v3d_submit_tfu_ioctl(struct drm_device *dev, void *data, · 5 unmodified lines
775 763
776 return 0;764 return 0;
777 765
778fail_unreserve:
779 mutex_unlock(&v3d->sched_lock);
780 drm_gem_unlock_reservations(job->base.bo, job->base.bo_count,
781 &acquire_ctx);
782fail:766fail:
783 v3d_job_put(&job->base);767 v3d_job_cleanup(&job->base);
784 768
785 return ret;769 return ret;
786}770}
@@ -818,7 +802,7 @@ v3d_submit_csd_ioctl(struct drm_device *dev, void *data, · 31 unmodified lines
818 return -ENOMEM;802 return -ENOMEM;
819 803
820 ret = v3d_job_init(v3d, file_priv, &job->base,804 ret = v3d_job_init(v3d, file_priv, &job->base,
821 v3d_job_free, args->in_sync);805 v3d_job_free, args->in_sync, V3D_CSD);
822 if (ret) {806 if (ret) {
823 kfree(job);807 kfree(job);
824 return ret;808 return ret;
@@ -831,7 +815,7 @@ v3d_submit_csd_ioctl(struct drm_device *dev, void *data, · 6 unmodified lines
831 return -ENOMEM;815 return -ENOMEM;
832 }816 }
833 817
834 ret = v3d_job_init(v3d, file_priv, clean_job, v3d_job_free, 0);818 ret = v3d_job_init(v3d, file_priv, clean_job, v3d_job_free, 0, V3D_CACHE_CLEAN);
835 if (ret) {819 if (ret) {
836 v3d_job_put(&job->base);820 v3d_job_put(&job->base);
837 kfree(clean_job);821 kfree(clean_job);
@@ -859,18 +843,14 @@ v3d_submit_csd_ioctl(struct drm_device *dev, void *data, · 21 unmodified lines
859 }843 }
860 844
861 mutex_lock(&v3d->sched_lock);845 mutex_lock(&v3d->sched_lock);
862 ret = v3d_push_job(v3d_priv, &job->base, V3D_CSD);846 v3d_push_job(&job->base);
863 if (ret)
864 goto fail_unreserve;
865 847
866 ret = drm_gem_fence_array_add(&clean_job->deps,848 ret = drm_sched_job_add_dependency(&clean_job->base,
867 dma_fence_get(job->base.done_fence));849 dma_fence_get(job->base.done_fence));
868 if (ret)850 if (ret)
869 goto fail_unreserve;851 goto fail_unreserve;
870 852
871 ret = v3d_push_job(v3d_priv, clean_job, V3D_CACHE_CLEAN);853 v3d_push_job(clean_job);
872 if (ret)
873 goto fail_unreserve;
874 mutex_unlock(&v3d->sched_lock);854 mutex_unlock(&v3d->sched_lock);
875 855
876 v3d_attach_fences_and_unlock_reservation(file_priv,856 v3d_attach_fences_and_unlock_reservation(file_priv,
@@ -889,8 +869,8 @@ fail_unreserve: · 12 unmodified lines
889 drm_gem_unlock_reservations(clean_job->bo, clean_job->bo_count,869 drm_gem_unlock_reservations(clean_job->bo, clean_job->bo_count,
890 &acquire_ctx);870 &acquire_ctx);
891fail:871fail:
892 v3d_job_put(&job->base);872 v3d_job_cleanup(&job->base);
893 v3d_job_put(clean_job);873 v3d_job_cleanup(clean_job);
894 874
895 return ret;875 return ret;
896}876}
drivers/gpu/drm/v3d/v3d_sched.c+8−36
@@ -13,7 +13,7 @@ · 12 unmodified lines
13 * jobs when bulk background jobs are queued up, we submit a new job13 * jobs when bulk background jobs are queued up, we submit a new job
14 * to the HW only when it has completed the last one, instead of14 * to the HW only when it has completed the last one, instead of
15 * filling up the CT[01]Q FIFOs with jobs. Similarly, we use15 * filling up the CT[01]Q FIFOs with jobs. Similarly, we use
16 * v3d_job_dependency() to manage the dependency between bin and16 * drm_sched_job_add_dependency() to manage the dependency between bin and
17 * render, instead of having the clients submit jobs using the HW's17 * render, instead of having the clients submit jobs using the HW's
18 * semaphores to interlock between them.18 * semaphores to interlock between them.
19 */19 */
@@ -55,12 +55,11 @@ to_csd_job(struct drm_sched_job *sched_job) · 35 unmodified lines
55}55}
56 56
57static void57static void
58v3d_job_free(struct drm_sched_job *sched_job)58v3d_sched_job_free(struct drm_sched_job *sched_job)
59{59{
60 struct v3d_job *job = to_v3d_job(sched_job);60 struct v3d_job *job = to_v3d_job(sched_job);
61 61
62 drm_sched_job_cleanup(sched_job);62 v3d_job_cleanup(job);
63 v3d_job_put(job);
64}63}
65 64
66static void65static void
@@ -73,28 +72,6 @@ v3d_switch_perfmon(struct v3d_dev *v3d, struct v3d_job *job) · 6 unmodified lines
73 v3d_perfmon_start(v3d, job->perfmon);72 v3d_perfmon_start(v3d, job->perfmon);
74}73}
75 74
76/*
77 * Returns the fences that the job depends on, one by one.
78 *
79 * If placed in the scheduler's .dependency method, the corresponding
80 * .run_job won't be called until all of them have been signaled.
81 */
82static struct dma_fence *
83v3d_job_dependency(struct drm_sched_job *sched_job,
84 struct drm_sched_entity *s_entity)
85{
86 struct v3d_job *job = to_v3d_job(sched_job);
87
88 /* XXX: Wait on a fence for switching the GMP if necessary,
89 * and then do so.
90 */
91
92 if (!xa_empty(&job->deps))
93 return xa_erase(&job->deps, job->last_dep++);
94
95 return NULL;
96}
97
98static struct dma_fence *v3d_bin_job_run(struct drm_sched_job *sched_job)75static struct dma_fence *v3d_bin_job_run(struct drm_sched_job *sched_job)
99{76{
100 struct v3d_bin_job *job = to_bin_job(sched_job);77 struct v3d_bin_job *job = to_bin_job(sched_job);
@@ -373,38 +350,33 @@ v3d_csd_job_timedout(struct drm_sched_job *sched_job) · 272 unmodified lines
373}350}
374 351
375static const struct drm_sched_backend_ops v3d_bin_sched_ops = {352static const struct drm_sched_backend_ops v3d_bin_sched_ops = {
376 .dependency = v3d_job_dependency,
377 .run_job = v3d_bin_job_run,353 .run_job = v3d_bin_job_run,
378 .timedout_job = v3d_bin_job_timedout,354 .timedout_job = v3d_bin_job_timedout,
379 .free_job = v3d_job_free,355 .free_job = v3d_sched_job_free,
380};356};
381 357
382static const struct drm_sched_backend_ops v3d_render_sched_ops = {358static const struct drm_sched_backend_ops v3d_render_sched_ops = {
383 .dependency = v3d_job_dependency,
384 .run_job = v3d_render_job_run,359 .run_job = v3d_render_job_run,
385 .timedout_job = v3d_render_job_timedout,360 .timedout_job = v3d_render_job_timedout,
386 .free_job = v3d_job_free,361 .free_job = v3d_sched_job_free,
387};362};
388 363
389static const struct drm_sched_backend_ops v3d_tfu_sched_ops = {364static const struct drm_sched_backend_ops v3d_tfu_sched_ops = {
390 .dependency = v3d_job_dependency,
391 .run_job = v3d_tfu_job_run,365 .run_job = v3d_tfu_job_run,
392 .timedout_job = v3d_generic_job_timedout,366 .timedout_job = v3d_generic_job_timedout,
393 .free_job = v3d_job_free,367 .free_job = v3d_sched_job_free,
394};368};
395 369
396static const struct drm_sched_backend_ops v3d_csd_sched_ops = {370static const struct drm_sched_backend_ops v3d_csd_sched_ops = {
397 .dependency = v3d_job_dependency,
398 .run_job = v3d_csd_job_run,371 .run_job = v3d_csd_job_run,
399 .timedout_job = v3d_csd_job_timedout,372 .timedout_job = v3d_csd_job_timedout,
400 .free_job = v3d_job_free373 .free_job = v3d_sched_job_free
401};374};
402 375
403static const struct drm_sched_backend_ops v3d_cache_clean_sched_ops = {376static const struct drm_sched_backend_ops v3d_cache_clean_sched_ops = {
404 .dependency = v3d_job_dependency,
405 .run_job = v3d_cache_clean_job_run,377 .run_job = v3d_cache_clean_job_run,
406 .timedout_job = v3d_generic_job_timedout,378 .timedout_job = v3d_generic_job_timedout,
407 .free_job = v3d_job_free379 .free_job = v3d_sched_job_free
408};380};
409 381
410int382int
drivers/gpu/drm/vc4/vc4_dpi.c+4−11
@@ -229,26 +229,19 @@ static const struct of_device_id vc4_dpi_dt_match[] = { · 228 unmodified lines
229static int vc4_dpi_init_bridge(struct vc4_dpi *dpi)229static int vc4_dpi_init_bridge(struct vc4_dpi *dpi)
230{230{
231 struct device *dev = &dpi->pdev->dev;231 struct device *dev = &dpi->pdev->dev;
232 struct drm_panel *panel;
233 struct drm_bridge *bridge;232 struct drm_bridge *bridge;
234 int ret;
235 233
236 ret = drm_of_find_panel_or_bridge(dev->of_node, 0, 0,234 bridge = devm_drm_of_get_bridge(dev, dev->of_node, 0, 0);
237 &panel, &bridge);235 if (IS_ERR(bridge)) {
238 if (ret) {
239 /* If nothing was connected in the DT, that's not an236 /* If nothing was connected in the DT, that's not an
240 * error.237 * error.
241 */238 */
242 if (ret == -ENODEV)239 if (PTR_ERR(bridge) == -ENODEV)
243 return 0;240 return 0;
244 else241 else
245 return ret;242 return PTR_ERR(bridge);
246 }243 }
247 244
248 if (panel)
249 bridge = drm_panel_bridge_add_typed(panel,
250 DRM_MODE_CONNECTOR_DPI);
251
252 return drm_bridge_attach(dpi->encoder, bridge, NULL, 0);245 return drm_bridge_attach(dpi->encoder, bridge, NULL, 0);
253}246}
254 247
drivers/gpu/drm/vc4/vc4_drv.c+2−4
@@ -50,13 +50,11 @@ · 49 unmodified lines
50#define DRIVER_PATCHLEVEL 050#define DRIVER_PATCHLEVEL 0
51 51
52/* Helper function for mapping the regs on a platform device. */52/* Helper function for mapping the regs on a platform device. */
53void __iomem *vc4_ioremap_regs(struct platform_device *dev, int index)53void __iomem *vc4_ioremap_regs(struct platform_device *pdev, int index)
54{54{
55 struct resource *res;
56 void __iomem *map;55 void __iomem *map;
57 56
58 res = platform_get_resource(dev, IORESOURCE_MEM, index);57 map = devm_platform_ioremap_resource(pdev, index);
59 map = devm_ioremap_resource(&dev->dev, res);
60 if (IS_ERR(map))58 if (IS_ERR(map))
61 return map;59 return map;
62 60
drivers/gpu/drm/vc4/vc4_dsi.c+4−24
@@ -1497,7 +1497,6 @@ static int vc4_dsi_bind(struct device *dev, struct device *master, void *data) · 1496 unmodified lines
1497 struct drm_device *drm = dev_get_drvdata(master);1497 struct drm_device *drm = dev_get_drvdata(master);
1498 struct vc4_dsi *dsi = dev_get_drvdata(dev);1498 struct vc4_dsi *dsi = dev_get_drvdata(dev);
1499 struct vc4_dsi_encoder *vc4_dsi_encoder;1499 struct vc4_dsi_encoder *vc4_dsi_encoder;
1500 struct drm_panel *panel;
1501 const struct of_device_id *match;1500 const struct of_device_id *match;
1502 dma_cap_mask_t dma_mask;1501 dma_cap_mask_t dma_mask;
1503 int ret;1502 int ret;
@@ -1609,27 +1608,9 @@ static int vc4_dsi_bind(struct device *dev, struct device *master, void *data) · 105 unmodified lines
1609 return ret;1608 return ret;
1610 }1609 }
1611 1610
1612 ret = drm_of_find_panel_or_bridge(dev->of_node, 0, 0,1611 dsi->bridge = devm_drm_of_get_bridge(dev, dev->of_node, 0, 0);
1613 &panel, &dsi->bridge);1612 if (IS_ERR(dsi->bridge))
1614 if (ret) {1613 return PTR_ERR(dsi->bridge);
1615 /* If the bridge or panel pointed by dev->of_node is not
1616 * enabled, just return 0 here so that we don't prevent the DRM
1617 * dev from being registered. Of course that means the DSI
1618 * encoder won't be exposed, but that's not a problem since
1619 * nothing is connected to it.
1620 */
1621 if (ret == -ENODEV)
1622 return 0;
1623
1624 return ret;
1625 }
1626
1627 if (panel) {
1628 dsi->bridge = devm_drm_panel_bridge_add_typed(dev, panel,
1629 DRM_MODE_CONNECTOR_DSI);
1630 if (IS_ERR(dsi->bridge))
1631 return PTR_ERR(dsi->bridge);
1632 }
1633 1614
1634 /* The esc clock rate is supposed to always be 100Mhz. */1615 /* The esc clock rate is supposed to always be 100Mhz. */
1635 ret = clk_set_rate(dsi->escape_clock, 100 * 1000000);1616 ret = clk_set_rate(dsi->escape_clock, 100 * 1000000);
@@ -1667,8 +1648,7 @@ static void vc4_dsi_unbind(struct device *dev, struct device *master, · 31 unmodified lines
1667{1648{
1668 struct vc4_dsi *dsi = dev_get_drvdata(dev);1649 struct vc4_dsi *dsi = dev_get_drvdata(dev);
1669 1650
1670 if (dsi->bridge)1651 pm_runtime_disable(dev);
1671 pm_runtime_disable(dev);
1672 1652
1673 /*1653 /*
1674 * Restore the bridge_chain so the bridge detach procedure can happen1654 * Restore the bridge_chain so the bridge detach procedure can happen
drivers/gpu/drm/vgem/vgem_drv.c+13−329
@@ -38,6 +38,7 @@ · 37 unmodified lines
38 38
39#include <drm/drm_drv.h>39#include <drm/drm_drv.h>
40#include <drm/drm_file.h>40#include <drm/drm_file.h>
41#include <drm/drm_gem_shmem_helper.h>
41#include <drm/drm_ioctl.h>42#include <drm/drm_ioctl.h>
42#include <drm/drm_managed.h>43#include <drm/drm_managed.h>
43#include <drm/drm_prime.h>44#include <drm/drm_prime.h>
@@ -50,87 +51,11 @@ · 6 unmodified lines
50#define DRIVER_MAJOR 151#define DRIVER_MAJOR 1
51#define DRIVER_MINOR 052#define DRIVER_MINOR 0
52 53
53static const struct drm_gem_object_funcs vgem_gem_object_funcs;
54
55static struct vgem_device {54static struct vgem_device {
56 struct drm_device drm;55 struct drm_device drm;
57 struct platform_device *platform;56 struct platform_device *platform;
58} *vgem_device;57} *vgem_device;
59 58
60static void vgem_gem_free_object(struct drm_gem_object *obj)
61{
62 struct drm_vgem_gem_object *vgem_obj = to_vgem_bo(obj);
63
64 kvfree(vgem_obj->pages);
65 mutex_destroy(&vgem_obj->pages_lock);
66
67 if (obj->import_attach)
68 drm_prime_gem_destroy(obj, vgem_obj->table);
69
70 drm_gem_object_release(obj);
71 kfree(vgem_obj);
72}
73
74static vm_fault_t vgem_gem_fault(struct vm_fault *vmf)
75{
76 struct vm_area_struct *vma = vmf->vma;
77 struct drm_vgem_gem_object *obj = vma->vm_private_data;
78 /* We don't use vmf->pgoff since that has the fake offset */
79 unsigned long vaddr = vmf->address;
80 vm_fault_t ret = VM_FAULT_SIGBUS;
81 loff_t num_pages;
82 pgoff_t page_offset;
83 page_offset = (vaddr - vma->vm_start) >> PAGE_SHIFT;
84
85 num_pages = DIV_ROUND_UP(obj->base.size, PAGE_SIZE);
86
87 if (page_offset >= num_pages)
88 return VM_FAULT_SIGBUS;
89
90 mutex_lock(&obj->pages_lock);
91 if (obj->pages) {
92 get_page(obj->pages[page_offset]);
93 vmf->page = obj->pages[page_offset];
94 ret = 0;
95 }
96 mutex_unlock(&obj->pages_lock);
97 if (ret) {
98 struct page *page;
99
100 page = shmem_read_mapping_page(
101 file_inode(obj->base.filp)->i_mapping,
102 page_offset);
103 if (!IS_ERR(page)) {
104 vmf->page = page;
105 ret = 0;
106 } else switch (PTR_ERR(page)) {
107 case -ENOSPC:
108 case -ENOMEM:
109 ret = VM_FAULT_OOM;
110 break;
111 case -EBUSY:
112 ret = VM_FAULT_RETRY;
113 break;
114 case -EFAULT:
115 case -EINVAL:
116 ret = VM_FAULT_SIGBUS;
117 break;
118 default:
119 WARN_ON(PTR_ERR(page));
120 ret = VM_FAULT_SIGBUS;
121 break;
122 }
123
124 }
125 return ret;
126}
127
128static const struct vm_operations_struct vgem_gem_vm_ops = {
129 .fault = vgem_gem_fault,
130 .open = drm_gem_vm_open,
131 .close = drm_gem_vm_close,
132};
133
134static int vgem_open(struct drm_device *dev, struct drm_file *file)59static int vgem_open(struct drm_device *dev, struct drm_file *file)
135{60{
136 struct vgem_file *vfile;61 struct vgem_file *vfile;
@@ -159,266 +84,30 @@ static void vgem_postclose(struct drm_device *dev, struct drm_file *file) · 22 unmodified lines
159 kfree(vfile);84 kfree(vfile);
160}85}
161 86
162static struct drm_vgem_gem_object *__vgem_gem_create(struct drm_device *dev,
163 unsigned long size)
164{
165 struct drm_vgem_gem_object *obj;
166 int ret;
167
168 obj = kzalloc(sizeof(*obj), GFP_KERNEL);
169 if (!obj)
170 return ERR_PTR(-ENOMEM);
171
172 obj->base.funcs = &vgem_gem_object_funcs;
173
174 ret = drm_gem_object_init(dev, &obj->base, roundup(size, PAGE_SIZE));
175 if (ret) {
176 kfree(obj);
177 return ERR_PTR(ret);
178 }
179
180 mutex_init(&obj->pages_lock);
181
182 return obj;
183}
184
185static void __vgem_gem_destroy(struct drm_vgem_gem_object *obj)
186{
187 drm_gem_object_release(&obj->base);
188 kfree(obj);
189}
190
191static struct drm_gem_object *vgem_gem_create(struct drm_device *dev,
192 struct drm_file *file,
193 unsigned int *handle,
194 unsigned long size)
195{
196 struct drm_vgem_gem_object *obj;
197 int ret;
198
199 obj = __vgem_gem_create(dev, size);
200 if (IS_ERR(obj))
201 return ERR_CAST(obj);
202
203 ret = drm_gem_handle_create(file, &obj->base, handle);
204 if (ret) {
205 drm_gem_object_put(&obj->base);
206 return ERR_PTR(ret);
207 }
208
209 return &obj->base;
210}
211
212static int vgem_gem_dumb_create(struct drm_file *file, struct drm_device *dev,
213 struct drm_mode_create_dumb *args)
214{
215 struct drm_gem_object *gem_object;
216 u64 pitch, size;
217
218 pitch = args->width * DIV_ROUND_UP(args->bpp, 8);
219 size = args->height * pitch;
220 if (size == 0)
221 return -EINVAL;
222
223 gem_object = vgem_gem_create(dev, file, &args->handle, size);
224 if (IS_ERR(gem_object))
225 return PTR_ERR(gem_object);
226
227 args->size = gem_object->size;
228 args->pitch = pitch;
229
230 drm_gem_object_put(gem_object);
231
232 DRM_DEBUG("Created object of size %llu\n", args->size);
233
234 return 0;
235}
236
237static struct drm_ioctl_desc vgem_ioctls[] = {87static struct drm_ioctl_desc vgem_ioctls[] = {
238 DRM_IOCTL_DEF_DRV(VGEM_FENCE_ATTACH, vgem_fence_attach_ioctl, DRM_RENDER_ALLOW),88 DRM_IOCTL_DEF_DRV(VGEM_FENCE_ATTACH, vgem_fence_attach_ioctl, DRM_RENDER_ALLOW),
239 DRM_IOCTL_DEF_DRV(VGEM_FENCE_SIGNAL, vgem_fence_signal_ioctl, DRM_RENDER_ALLOW),89 DRM_IOCTL_DEF_DRV(VGEM_FENCE_SIGNAL, vgem_fence_signal_ioctl, DRM_RENDER_ALLOW),
240};90};
241 91
242static int vgem_mmap(struct file *filp, struct vm_area_struct *vma)92DEFINE_DRM_GEM_FOPS(vgem_driver_fops);
243{
244 unsigned long flags = vma->vm_flags;
245 int ret;
246
247 ret = drm_gem_mmap(filp, vma);
248 if (ret)
249 return ret;
250
251 /* Keep the WC mmaping set by drm_gem_mmap() but our pages
252 * are ordinary and not special.
253 */
254 vma->vm_flags = flags | VM_DONTEXPAND | VM_DONTDUMP;
255 return 0;
256}
257 93
258static const struct file_operations vgem_driver_fops = {94static struct drm_gem_object *vgem_gem_create_object(struct drm_device *dev, size_t size)
259 .owner = THIS_MODULE,
260 .open = drm_open,
261 .mmap = vgem_mmap,
262 .poll = drm_poll,
263 .read = drm_read,
264 .unlocked_ioctl = drm_ioctl,
265 .compat_ioctl = drm_compat_ioctl,
266 .release = drm_release,
267};
268
269static struct page **vgem_pin_pages(struct drm_vgem_gem_object *bo)
270{
271 mutex_lock(&bo->pages_lock);
272 if (bo->pages_pin_count++ == 0) {
273 struct page **pages;
274
275 pages = drm_gem_get_pages(&bo->base);
276 if (IS_ERR(pages)) {
277 bo->pages_pin_count--;
278 mutex_unlock(&bo->pages_lock);
279 return pages;
280 }
281
282 bo->pages = pages;
283 }
284 mutex_unlock(&bo->pages_lock);
285
286 return bo->pages;
287}
288
289static void vgem_unpin_pages(struct drm_vgem_gem_object *bo)
290{
291 mutex_lock(&bo->pages_lock);
292 if (--bo->pages_pin_count == 0) {
293 drm_gem_put_pages(&bo->base, bo->pages, true, true);
294 bo->pages = NULL;
295 }
296 mutex_unlock(&bo->pages_lock);
297}
298
299static int vgem_prime_pin(struct drm_gem_object *obj)
300{95{
301 struct drm_vgem_gem_object *bo = to_vgem_bo(obj);96 struct drm_gem_shmem_object *obj;
302 long n_pages = obj->size >> PAGE_SHIFT;
303 struct page **pages;
304 97
305 pages = vgem_pin_pages(bo);98 obj = kzalloc(sizeof(*obj), GFP_KERNEL);
306 if (IS_ERR(pages))99 if (!obj)
307 return PTR_ERR(pages);100 return NULL;
308 101
309 /* Flush the object from the CPU cache so that importers can rely102 /*
310 * on coherent indirect access via the exported dma-address.103 * vgem doesn't have any begin/end cpu access ioctls, therefore must use
104 * coherent memory or dma-buf sharing just wont work.
311 */105 */
312 drm_clflush_pages(pages, n_pages);106 obj->map_wc = true;
313
314 return 0;
315}
316
317static void vgem_prime_unpin(struct drm_gem_object *obj)
318{
319 struct drm_vgem_gem_object *bo = to_vgem_bo(obj);
320
321 vgem_unpin_pages(bo);
322}
323
324static struct sg_table *vgem_prime_get_sg_table(struct drm_gem_object *obj)
325{
326 struct drm_vgem_gem_object *bo = to_vgem_bo(obj);
327
328 return drm_prime_pages_to_sg(obj->dev, bo->pages, bo->base.size >> PAGE_SHIFT);
329}
330
331static struct drm_gem_object* vgem_prime_import(struct drm_device *dev,
332 struct dma_buf *dma_buf)
333{
334 struct vgem_device *vgem = container_of(dev, typeof(*vgem), drm);
335
336 return drm_gem_prime_import_dev(dev, dma_buf, &vgem->platform->dev);
337}
338
339static struct drm_gem_object *vgem_prime_import_sg_table(struct drm_device *dev,
340 struct dma_buf_attachment *attach, struct sg_table *sg)
341{
342 struct drm_vgem_gem_object *obj;
343 int npages;
344
345 obj = __vgem_gem_create(dev, attach->dmabuf->size);
346 if (IS_ERR(obj))
347 return ERR_CAST(obj);
348 107
349 npages = PAGE_ALIGN(attach->dmabuf->size) / PAGE_SIZE;
350
351 obj->table = sg;
352 obj->pages = kvmalloc_array(npages, sizeof(struct page *), GFP_KERNEL);
353 if (!obj->pages) {
354 __vgem_gem_destroy(obj);
355 return ERR_PTR(-ENOMEM);
356 }
357
358 obj->pages_pin_count++; /* perma-pinned */
359 drm_prime_sg_to_page_array(obj->table, obj->pages, npages);
360 return &obj->base;108 return &obj->base;
361}109}
362 110
363static int vgem_prime_vmap(struct drm_gem_object *obj, struct dma_buf_map *map)
364{
365 struct drm_vgem_gem_object *bo = to_vgem_bo(obj);
366 long n_pages = obj->size >> PAGE_SHIFT;
367 struct page **pages;
368 void *vaddr;
369
370 pages = vgem_pin_pages(bo);
371 if (IS_ERR(pages))
372 return PTR_ERR(pages);
373
374 vaddr = vmap(pages, n_pages, 0, pgprot_writecombine(PAGE_KERNEL));
375 if (!vaddr)
376 return -ENOMEM;
377 dma_buf_map_set_vaddr(map, vaddr);
378
379 return 0;
380}
381
382static void vgem_prime_vunmap(struct drm_gem_object *obj, struct dma_buf_map *map)
383{
384 struct drm_vgem_gem_object *bo = to_vgem_bo(obj);
385
386 vunmap(map->vaddr);
387 vgem_unpin_pages(bo);
388}
389
390static int vgem_prime_mmap(struct drm_gem_object *obj,
391 struct vm_area_struct *vma)
392{
393 int ret;
394
395 if (obj->size < vma->vm_end - vma->vm_start)
396 return -EINVAL;
397
398 if (!obj->filp)
399 return -ENODEV;
400
401 ret = call_mmap(obj->filp, vma);
402 if (ret)
403 return ret;
404
405 vma_set_file(vma, obj->filp);
406 vma->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP;
407 vma->vm_page_prot = pgprot_writecombine(vm_get_page_prot(vma->vm_flags));
408
409 return 0;
410}
411
412static const struct drm_gem_object_funcs vgem_gem_object_funcs = {
413 .free = vgem_gem_free_object,
414 .pin = vgem_prime_pin,
415 .unpin = vgem_prime_unpin,
416 .get_sg_table = vgem_prime_get_sg_table,
417 .vmap = vgem_prime_vmap,
418 .vunmap = vgem_prime_vunmap,
419 .vm_ops = &vgem_gem_vm_ops,
420};
421
422static const struct drm_driver vgem_driver = {111static const struct drm_driver vgem_driver = {
423 .driver_features = DRIVER_GEM | DRIVER_RENDER,112 .driver_features = DRIVER_GEM | DRIVER_RENDER,
424 .open = vgem_open,113 .open = vgem_open,
@@ -427,13 +116,8 @@ static const struct drm_driver vgem_driver = { · 2 unmodified lines
427 .num_ioctls = ARRAY_SIZE(vgem_ioctls),116 .num_ioctls = ARRAY_SIZE(vgem_ioctls),
428 .fops = &vgem_driver_fops,117 .fops = &vgem_driver_fops,
429 118
430 .dumb_create = vgem_gem_dumb_create,119 DRM_GEM_SHMEM_DRIVER_OPS,
431 120 .gem_create_object = vgem_gem_create_object,
432 .prime_handle_to_fd = drm_gem_prime_handle_to_fd,
433 .prime_fd_to_handle = drm_gem_prime_fd_to_handle,
434 .gem_prime_import = vgem_prime_import,
435 .gem_prime_import_sg_table = vgem_prime_import_sg_table,
436 .gem_prime_mmap = vgem_prime_mmap,
437 121
438 .name = DRIVER_NAME,122 .name = DRIVER_NAME,
439 .desc = DRIVER_DESC,123 .desc = DRIVER_DESC,
drivers/gpu/drm/virtio/virtgpu_drv.h+8−0
@@ -26,6 +26,7 @@ · 25 unmodified lines
26#ifndef VIRTIO_DRV_H26#ifndef VIRTIO_DRV_H
27#define VIRTIO_DRV_H27#define VIRTIO_DRV_H
28 28
29#include <linux/dma-direction.h>
29#include <linux/virtio.h>30#include <linux/virtio.h>
30#include <linux/virtio_ids.h>31#include <linux/virtio_ids.h>
31#include <linux/virtio_config.h>32#include <linux/virtio_config.h>
@@ -459,4 +460,11 @@ bool virtio_gpu_is_vram(struct virtio_gpu_object *bo); · 427 unmodified lines
459int virtio_gpu_vram_create(struct virtio_gpu_device *vgdev,460int virtio_gpu_vram_create(struct virtio_gpu_device *vgdev,
460 struct virtio_gpu_object_params *params,461 struct virtio_gpu_object_params *params,
461 struct virtio_gpu_object **bo_ptr);462 struct virtio_gpu_object **bo_ptr);
463struct sg_table *virtio_gpu_vram_map_dma_buf(struct virtio_gpu_object *bo,
464 struct device *dev,
465 enum dma_data_direction dir);
466void virtio_gpu_vram_unmap_dma_buf(struct device *dev,
467 struct sg_table *sgt,
468 enum dma_data_direction dir);
469
462#endif470#endif
drivers/gpu/drm/virtio/virtgpu_prime.c+30−2
@@ -43,13 +43,41 @@ static int virtgpu_virtio_get_uuid(struct dma_buf *buf, · 42 unmodified lines
43 return 0;43 return 0;
44}44}
45 45
46static struct sg_table *
47virtgpu_gem_map_dma_buf(struct dma_buf_attachment *attach,
48 enum dma_data_direction dir)
49{
50 struct drm_gem_object *obj = attach->dmabuf->priv;
51 struct virtio_gpu_object *bo = gem_to_virtio_gpu_obj(obj);
52
53 if (virtio_gpu_is_vram(bo))
54 return virtio_gpu_vram_map_dma_buf(bo, attach->dev, dir);
55
56 return drm_gem_map_dma_buf(attach, dir);
57}
58
59static void virtgpu_gem_unmap_dma_buf(struct dma_buf_attachment *attach,
60 struct sg_table *sgt,
61 enum dma_data_direction dir)
62{
63 struct drm_gem_object *obj = attach->dmabuf->priv;
64 struct virtio_gpu_object *bo = gem_to_virtio_gpu_obj(obj);
65
66 if (virtio_gpu_is_vram(bo)) {
67 virtio_gpu_vram_unmap_dma_buf(attach->dev, sgt, dir);
68 return;
69 }
70
71 drm_gem_unmap_dma_buf(attach, sgt, dir);
72}
73
46static const struct virtio_dma_buf_ops virtgpu_dmabuf_ops = {74static const struct virtio_dma_buf_ops virtgpu_dmabuf_ops = {
47 .ops = {75 .ops = {
48 .cache_sgt_mapping = true,76 .cache_sgt_mapping = true,
49 .attach = virtio_dma_buf_attach,77 .attach = virtio_dma_buf_attach,
50 .detach = drm_gem_map_detach,78 .detach = drm_gem_map_detach,
51 .map_dma_buf = drm_gem_map_dma_buf,79 .map_dma_buf = virtgpu_gem_map_dma_buf,
52 .unmap_dma_buf = drm_gem_unmap_dma_buf,80 .unmap_dma_buf = virtgpu_gem_unmap_dma_buf,
53 .release = drm_gem_dmabuf_release,81 .release = drm_gem_dmabuf_release,
54 .mmap = drm_gem_dmabuf_mmap,82 .mmap = drm_gem_dmabuf_mmap,
55 .vmap = drm_gem_dmabuf_vmap,83 .vmap = drm_gem_dmabuf_vmap,
drivers/gpu/drm/virtio/virtgpu_vram.c+61−0
@@ -1,6 +1,8 @@
1// SPDX-License-Identifier: GPL-2.01// SPDX-License-Identifier: GPL-2.0
2#include "virtgpu_drv.h"2#include "virtgpu_drv.h"
3 3
4#include <linux/dma-mapping.h>
5
4static void virtio_gpu_vram_free(struct drm_gem_object *obj)6static void virtio_gpu_vram_free(struct drm_gem_object *obj)
5{7{
6 struct virtio_gpu_object *bo = gem_to_virtio_gpu_obj(obj);8 struct virtio_gpu_object *bo = gem_to_virtio_gpu_obj(obj);
@@ -64,6 +66,65 @@ static int virtio_gpu_vram_mmap(struct drm_gem_object *obj, · 57 unmodified lines
64 return ret;66 return ret;
65}67}
66 68
69struct sg_table *virtio_gpu_vram_map_dma_buf(struct virtio_gpu_object *bo,
70 struct device *dev,
71 enum dma_data_direction dir)
72{
73 struct virtio_gpu_device *vgdev = bo->base.base.dev->dev_private;
74 struct virtio_gpu_object_vram *vram = to_virtio_gpu_vram(bo);
75 struct sg_table *sgt;
76 dma_addr_t addr;
77 int ret;
78
79 sgt = kzalloc(sizeof(*sgt), GFP_KERNEL);
80 if (!sgt)
81 return ERR_PTR(-ENOMEM);
82
83 if (!(bo->blob_flags & VIRTGPU_BLOB_FLAG_USE_MAPPABLE)) {
84 // Virtio devices can access the dma-buf via its UUID. Return a stub
85 // sg_table so the dma-buf API still works.
86 if (!is_virtio_device(dev) || !vgdev->has_resource_assign_uuid) {
87 ret = -EIO;
88 goto out;
89 }
90 return sgt;
91 }
92
93 ret = sg_alloc_table(sgt, 1, GFP_KERNEL);
94 if (ret)
95 goto out;
96
97 addr = dma_map_resource(dev, vram->vram_node.start,
98 vram->vram_node.size, dir,
99 DMA_ATTR_SKIP_CPU_SYNC);
100 ret = dma_mapping_error(dev, addr);
101 if (ret)
102 goto out;
103
104 sg_set_page(sgt->sgl, NULL, vram->vram_node.size, 0);
105 sg_dma_address(sgt->sgl) = addr;
106 sg_dma_len(sgt->sgl) = vram->vram_node.size;
107
108 return sgt;
109out:
110 sg_free_table(sgt);
111 kfree(sgt);
112 return ERR_PTR(ret);
113}
114
115void virtio_gpu_vram_unmap_dma_buf(struct device *dev,
116 struct sg_table *sgt,
117 enum dma_data_direction dir)
118{
119 if (sgt->nents) {
120 dma_unmap_resource(dev, sg_dma_address(sgt->sgl),
121 sg_dma_len(sgt->sgl), dir,
122 DMA_ATTR_SKIP_CPU_SYNC);
123 }
124 sg_free_table(sgt);
125 kfree(sgt);
126}
127
67static const struct drm_gem_object_funcs virtio_gpu_vram_funcs = {128static const struct drm_gem_object_funcs virtio_gpu_vram_funcs = {
68 .open = virtio_gpu_gem_object_open,129 .open = virtio_gpu_gem_object_open,
69 .close = virtio_gpu_gem_object_close,130 .close = virtio_gpu_gem_object_close,
drivers/gpu/drm/vmwgfx/vmwgfx_bo.c+6−9
@@ -94,7 +94,6 @@ int vmw_bo_pin_in_placement(struct vmw_private *dev_priv, · 93 unmodified lines
94 struct ttm_operation_ctx ctx = {interruptible, false };94 struct ttm_operation_ctx ctx = {interruptible, false };
95 struct ttm_buffer_object *bo = &buf->base;95 struct ttm_buffer_object *bo = &buf->base;
96 int ret;96 int ret;
97 uint32_t new_flags;
98 97
99 vmw_execbuf_release_pinned_bo(dev_priv);98 vmw_execbuf_release_pinned_bo(dev_priv);
100 99
@@ -103,8 +102,8 @@ int vmw_bo_pin_in_placement(struct vmw_private *dev_priv, · 2 unmodified lines
103 goto err;102 goto err;
104 103
105 if (buf->base.pin_count > 0)104 if (buf->base.pin_count > 0)
106 ret = ttm_bo_mem_compat(placement, bo->resource,105 ret = ttm_resource_compat(bo->resource, placement)
107 &new_flags) == true ? 0 : -EINVAL;106 ? 0 : -EINVAL;
108 else107 else
109 ret = ttm_bo_validate(bo, placement, &ctx);108 ret = ttm_bo_validate(bo, placement, &ctx);
110 109
@@ -136,7 +135,6 @@ int vmw_bo_pin_in_vram_or_gmr(struct vmw_private *dev_priv, · 25 unmodified lines
136 struct ttm_operation_ctx ctx = {interruptible, false };135 struct ttm_operation_ctx ctx = {interruptible, false };
137 struct ttm_buffer_object *bo = &buf->base;136 struct ttm_buffer_object *bo = &buf->base;
138 int ret;137 int ret;
139 uint32_t new_flags;
140 138
141 vmw_execbuf_release_pinned_bo(dev_priv);139 vmw_execbuf_release_pinned_bo(dev_priv);
142 140
@@ -145,8 +143,8 @@ int vmw_bo_pin_in_vram_or_gmr(struct vmw_private *dev_priv, · 2 unmodified lines
145 goto err;143 goto err;
146 144
147 if (buf->base.pin_count > 0) {145 if (buf->base.pin_count > 0) {
148 ret = ttm_bo_mem_compat(&vmw_vram_gmr_placement, bo->resource,146 ret = ttm_resource_compat(bo->resource, &vmw_vram_gmr_placement)
149 &new_flags) == true ? 0 : -EINVAL;147 ? 0 : -EINVAL;
150 goto out_unreserve;148 goto out_unreserve;
151 }149 }
152 150
@@ -208,7 +206,6 @@ int vmw_bo_pin_in_start_of_vram(struct vmw_private *dev_priv, · 55 unmodified lines
208 struct ttm_placement placement;206 struct ttm_placement placement;
209 struct ttm_place place;207 struct ttm_place place;
210 int ret = 0;208 int ret = 0;
211 uint32_t new_flags;
212 209
213 place = vmw_vram_placement.placement[0];210 place = vmw_vram_placement.placement[0];
214 place.lpfn = bo->resource->num_pages;211 place.lpfn = bo->resource->num_pages;
@@ -236,8 +233,8 @@ int vmw_bo_pin_in_start_of_vram(struct vmw_private *dev_priv, · 21 unmodified lines
236 }233 }
237 234
238 if (buf->base.pin_count > 0)235 if (buf->base.pin_count > 0)
239 ret = ttm_bo_mem_compat(&placement, bo->resource,236 ret = ttm_resource_compat(bo->resource, &placement)
240 &new_flags) == true ? 0 : -EINVAL;237 ? 0 : -EINVAL;
241 else238 else
242 ret = ttm_bo_validate(bo, &placement, &ctx);239 ret = ttm_bo_validate(bo, &placement, &ctx);
243 240
drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c+3−7
@@ -522,14 +522,8 @@ static void vmw_ttm_destroy(struct ttm_device *bdev, struct ttm_tt *ttm) · 521 unmodified lines
522 struct vmw_ttm_tt *vmw_be =522 struct vmw_ttm_tt *vmw_be =
523 container_of(ttm, struct vmw_ttm_tt, dma_ttm);523 container_of(ttm, struct vmw_ttm_tt, dma_ttm);
524 524
525 vmw_ttm_unbind(bdev, ttm);
526 ttm_tt_destroy_common(bdev, ttm);
527 vmw_ttm_unmap_dma(vmw_be);525 vmw_ttm_unmap_dma(vmw_be);
528 if (vmw_be->dev_priv->map_mode == vmw_dma_alloc_coherent)526 ttm_tt_fini(ttm);
529 ttm_tt_fini(&vmw_be->dma_ttm);
530 else
531 ttm_tt_fini(ttm);
532
533 if (vmw_be->mob)527 if (vmw_be->mob)
534 vmw_mob_destroy(vmw_be->mob);528 vmw_mob_destroy(vmw_be->mob);
535 529
@@ -574,6 +568,8 @@ static void vmw_ttm_unpopulate(struct ttm_device *bdev, · 38 unmodified lines
574 dma_ttm);568 dma_ttm);
575 unsigned int i;569 unsigned int i;
576 570
571 vmw_ttm_unbind(bdev, ttm);
572
577 if (vmw_tt->mob) {573 if (vmw_tt->mob) {
578 vmw_mob_destroy(vmw_tt->mob);574 vmw_mob_destroy(vmw_tt->mob);
579 vmw_tt->mob = NULL;575 vmw_tt->mob = NULL;
drivers/gpu/drm/zte/Kconfig+0−10
@@ -1,10 +0,0 @@
1# SPDX-License-Identifier: GPL-2.0-only
2config DRM_ZTE
3 tristate "DRM Support for ZTE SoCs"
4 depends on DRM && ARCH_ZX
5 select DRM_KMS_CMA_HELPER
6 select DRM_KMS_HELPER
7 select SND_SOC_HDMI_CODEC if SND_SOC
8 select VIDEOMODE_HELPERS
9 help
10 Choose this option to enable DRM on ZTE ZX SoCs.
drivers/gpu/drm/zte/Makefile+0−10
@@ -1,10 +0,0 @@
1# SPDX-License-Identifier: GPL-2.0
2zxdrm-y := \
3 zx_drm_drv.o \
4 zx_hdmi.o \
5 zx_plane.o \
6 zx_tvenc.o \
7 zx_vga.o \
8 zx_vou.o
9
10obj-$(CONFIG_DRM_ZTE) += zxdrm.o
drivers/gpu/drm/zte/zx_common_regs.h+0−28
@@ -1,28 +0,0 @@
1/* SPDX-License-Identifier: GPL-2.0-only */
2/*
3 * Copyright (C) 2017 Sanechips Technology Co., Ltd.
4 * Copyright 2017 Linaro Ltd.
5 */
6
7#ifndef __ZX_COMMON_REGS_H__
8#define __ZX_COMMON_REGS_H__
9
10/* CSC registers */
11#define CSC_CTRL0 0x30
12#define CSC_COV_MODE_SHIFT 16
13#define CSC_COV_MODE_MASK (0xffff << CSC_COV_MODE_SHIFT)
14#define CSC_BT601_IMAGE_RGB2YCBCR 0
15#define CSC_BT601_IMAGE_YCBCR2RGB 1
16#define CSC_BT601_VIDEO_RGB2YCBCR 2
17#define CSC_BT601_VIDEO_YCBCR2RGB 3
18#define CSC_BT709_IMAGE_RGB2YCBCR 4
19#define CSC_BT709_IMAGE_YCBCR2RGB 5
20#define CSC_BT709_VIDEO_RGB2YCBCR 6
21#define CSC_BT709_VIDEO_YCBCR2RGB 7
22#define CSC_BT2020_IMAGE_RGB2YCBCR 8
23#define CSC_BT2020_IMAGE_YCBCR2RGB 9
24#define CSC_BT2020_VIDEO_RGB2YCBCR 10
25#define CSC_BT2020_VIDEO_YCBCR2RGB 11
26#define CSC_WORK_ENABLE BIT(0)
27
28#endif /* __ZX_COMMON_REGS_H__ */
drivers/gpu/drm/zte/zx_drm_drv.c+0−184
@@ -1,184 +0,0 @@
1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * Copyright 2016 Linaro Ltd.
4 * Copyright 2016 ZTE Corporation.
5 */
6
7#include <linux/clk.h>
8#include <linux/component.h>
9#include <linux/list.h>
10#include <linux/module.h>
11#include <linux/of_graph.h>
12#include <linux/of_platform.h>
13#include <linux/spinlock.h>
14
15#include <drm/drm_atomic_helper.h>
16#include <drm/drm_crtc.h>
17#include <drm/drm_drv.h>
18#include <drm/drm_fb_cma_helper.h>
19#include <drm/drm_fb_helper.h>
20#include <drm/drm_gem_cma_helper.h>
21#include <drm/drm_gem_framebuffer_helper.h>
22#include <drm/drm_of.h>
23#include <drm/drm_probe_helper.h>
24#include <drm/drm_vblank.h>
25
26#include "zx_drm_drv.h"
27#include "zx_vou.h"
28
29static const struct drm_mode_config_funcs zx_drm_mode_config_funcs = {
30 .fb_create = drm_gem_fb_create,
31 .atomic_check = drm_atomic_helper_check,
32 .atomic_commit = drm_atomic_helper_commit,
33};
34
35DEFINE_DRM_GEM_CMA_FOPS(zx_drm_fops);
36
37static const struct drm_driver zx_drm_driver = {
38 .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
39 DRM_GEM_CMA_DRIVER_OPS,
40 .fops = &zx_drm_fops,
41 .name = "zx-vou",
42 .desc = "ZTE VOU Controller DRM",
43 .date = "20160811",
44 .major = 1,
45 .minor = 0,
46};
47
48static int zx_drm_bind(struct device *dev)
49{
50 struct drm_device *drm;
51 int ret;
52
53 drm = drm_dev_alloc(&zx_drm_driver, dev);
54 if (IS_ERR(drm))
55 return PTR_ERR(drm);
56
57 dev_set_drvdata(dev, drm);
58
59 drm_mode_config_init(drm);
60 drm->mode_config.min_width = 16;
61 drm->mode_config.min_height = 16;
62 drm->mode_config.max_width = 4096;
63 drm->mode_config.max_height = 4096;
64 drm->mode_config.funcs = &zx_drm_mode_config_funcs;
65
66 ret = component_bind_all(dev, drm);
67 if (ret) {
68 DRM_DEV_ERROR(dev, "failed to bind all components: %d\n", ret);
69 goto out_unregister;
70 }
71
72 ret = drm_vblank_init(drm, drm->mode_config.num_crtc);
73 if (ret < 0) {
74 DRM_DEV_ERROR(dev, "failed to init vblank: %d\n", ret);
75 goto out_unbind;
76 }
77
78 drm_mode_config_reset(drm);
79 drm_kms_helper_poll_init(drm);
80
81 ret = drm_dev_register(drm, 0);
82 if (ret)
83 goto out_poll_fini;
84
85 drm_fbdev_generic_setup(drm, 32);
86
87 return 0;
88
89out_poll_fini:
90 drm_kms_helper_poll_fini(drm);
91 drm_mode_config_cleanup(drm);
92out_unbind:
93 component_unbind_all(dev, drm);
94out_unregister:
95 dev_set_drvdata(dev, NULL);
96 drm_dev_put(drm);
97 return ret;
98}
99
100static void zx_drm_unbind(struct device *dev)
101{
102 struct drm_device *drm = dev_get_drvdata(dev);
103
104 drm_dev_unregister(drm);
105 drm_kms_helper_poll_fini(drm);
106 drm_atomic_helper_shutdown(drm);
107 drm_mode_config_cleanup(drm);
108 component_unbind_all(dev, drm);
109 dev_set_drvdata(dev, NULL);
110 drm_dev_put(drm);
111}
112
113static const struct component_master_ops zx_drm_master_ops = {
114 .bind = zx_drm_bind,
115 .unbind = zx_drm_unbind,
116};
117
118static int compare_of(struct device *dev, void *data)
119{
120 return dev->of_node == data;
121}
122
123static int zx_drm_probe(struct platform_device *pdev)
124{
125 struct device *dev = &pdev->dev;
126 struct device_node *parent = dev->of_node;
127 struct device_node *child;
128 struct component_match *match = NULL;
129 int ret;
130
131 ret = devm_of_platform_populate(dev);
132 if (ret)
133 return ret;
134
135 for_each_available_child_of_node(parent, child)
136 component_match_add(dev, &match, compare_of, child);
137
138 return component_master_add_with_match(dev, &zx_drm_master_ops, match);
139}
140
141static int zx_drm_remove(struct platform_device *pdev)
142{
143 component_master_del(&pdev->dev, &zx_drm_master_ops);
144 return 0;
145}
146
147static const struct of_device_id zx_drm_of_match[] = {
148 { .compatible = "zte,zx296718-vou", },
149 { /* end */ },
150};
151MODULE_DEVICE_TABLE(of, zx_drm_of_match);
152
153static struct platform_driver zx_drm_platform_driver = {
154 .probe = zx_drm_probe,
155 .remove = zx_drm_remove,
156 .driver = {
157 .name = "zx-drm",
158 .of_match_table = zx_drm_of_match,
159 },
160};
161
162static struct platform_driver *drivers[] = {
163 &zx_crtc_driver,
164 &zx_hdmi_driver,
165 &zx_tvenc_driver,
166 &zx_vga_driver,
167 &zx_drm_platform_driver,
168};
169
170static int zx_drm_init(void)
171{
172 return platform_register_drivers(drivers, ARRAY_SIZE(drivers));
173}
174module_init(zx_drm_init);
175
176static void zx_drm_exit(void)
177{
178 platform_unregister_drivers(drivers, ARRAY_SIZE(drivers));
179}
180module_exit(zx_drm_exit);
181
182MODULE_AUTHOR("Shawn Guo <shawn.guo@linaro.org>");
183MODULE_DESCRIPTION("ZTE ZX VOU DRM driver");
184MODULE_LICENSE("GPL v2");
drivers/gpu/drm/zte/zx_drm_drv.h+0−34
@@ -1,34 +0,0 @@
1/* SPDX-License-Identifier: GPL-2.0-only */
2/*
3 * Copyright 2016 Linaro Ltd.
4 * Copyright 2016 ZTE Corporation.
5 */
6
7#ifndef __ZX_DRM_DRV_H__
8#define __ZX_DRM_DRV_H__
9
10extern struct platform_driver zx_crtc_driver;
11extern struct platform_driver zx_hdmi_driver;
12extern struct platform_driver zx_tvenc_driver;
13extern struct platform_driver zx_vga_driver;
14
15static inline u32 zx_readl(void __iomem *reg)
16{
17 return readl_relaxed(reg);
18}
19
20static inline void zx_writel(void __iomem *reg, u32 val)
21{
22 writel_relaxed(val, reg);
23}
24
25static inline void zx_writel_mask(void __iomem *reg, u32 mask, u32 val)
26{
27 u32 tmp;
28
29 tmp = zx_readl(reg);
30 tmp = (tmp & ~mask) | (val & mask);
31 zx_writel(reg, tmp);
32}
33
34#endif /* __ZX_DRM_DRV_H__ */
drivers/gpu/drm/zte/zx_hdmi.c+0−760
@@ -1,760 +0,0 @@
1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * Copyright 2016 Linaro Ltd.
4 * Copyright 2016 ZTE Corporation.
5 */
6
7#include <linux/clk.h>
8#include <linux/component.h>
9#include <linux/delay.h>
10#include <linux/err.h>
11#include <linux/hdmi.h>
12#include <linux/irq.h>
13#include <linux/mfd/syscon.h>
14#include <linux/module.h>
15#include <linux/mutex.h>
16#include <linux/of_device.h>
17
18#include <drm/drm_atomic_helper.h>
19#include <drm/drm_edid.h>
20#include <drm/drm_of.h>
21#include <drm/drm_probe_helper.h>
22#include <drm/drm_print.h>
23#include <drm/drm_simple_kms_helper.h>
24
25#include <sound/hdmi-codec.h>
26
27#include "zx_hdmi_regs.h"
28#include "zx_vou.h"
29
30#define ZX_HDMI_INFOFRAME_SIZE 31
31#define DDC_SEGMENT_ADDR 0x30
32
33struct zx_hdmi_i2c {
34 struct i2c_adapter adap;
35 struct mutex lock;
36};
37
38struct zx_hdmi {
39 struct drm_connector connector;
40 struct drm_encoder encoder;
41 struct zx_hdmi_i2c *ddc;
42 struct device *dev;
43 struct drm_device *drm;
44 void __iomem *mmio;
45 struct clk *cec_clk;
46 struct clk *osc_clk;
47 struct clk *xclk;
48 bool sink_is_hdmi;
49 bool sink_has_audio;
50 struct platform_device *audio_pdev;
51};
52
53#define to_zx_hdmi(x) container_of(x, struct zx_hdmi, x)
54
55static inline u8 hdmi_readb(struct zx_hdmi *hdmi, u16 offset)
56{
57 return readl_relaxed(hdmi->mmio + offset * 4);
58}
59
60static inline void hdmi_writeb(struct zx_hdmi *hdmi, u16 offset, u8 val)
61{
62 writel_relaxed(val, hdmi->mmio + offset * 4);
63}
64
65static inline void hdmi_writeb_mask(struct zx_hdmi *hdmi, u16 offset,
66 u8 mask, u8 val)
67{
68 u8 tmp;
69
70 tmp = hdmi_readb(hdmi, offset);
71 tmp = (tmp & ~mask) | (val & mask);
72 hdmi_writeb(hdmi, offset, tmp);
73}
74
75static int zx_hdmi_infoframe_trans(struct zx_hdmi *hdmi,
76 union hdmi_infoframe *frame, u8 fsel)
77{
78 u8 buffer[ZX_HDMI_INFOFRAME_SIZE];
79 int num;
80 int i;
81
82 hdmi_writeb(hdmi, TPI_INFO_FSEL, fsel);
83
84 num = hdmi_infoframe_pack(frame, buffer, ZX_HDMI_INFOFRAME_SIZE);
85 if (num < 0) {
86 DRM_DEV_ERROR(hdmi->dev, "failed to pack infoframe: %d\n", num);
87 return num;
88 }
89
90 for (i = 0; i < num; i++)
91 hdmi_writeb(hdmi, TPI_INFO_B0 + i, buffer[i]);
92
93 hdmi_writeb_mask(hdmi, TPI_INFO_EN, TPI_INFO_TRANS_RPT,
94 TPI_INFO_TRANS_RPT);
95 hdmi_writeb_mask(hdmi, TPI_INFO_EN, TPI_INFO_TRANS_EN,
96 TPI_INFO_TRANS_EN);
97
98 return num;
99}
100
101static int zx_hdmi_config_video_vsi(struct zx_hdmi *hdmi,
102 struct drm_display_mode *mode)
103{
104 union hdmi_infoframe frame;
105 int ret;
106
107 ret = drm_hdmi_vendor_infoframe_from_display_mode(&frame.vendor.hdmi,
108 &hdmi->connector,
109 mode);
110 if (ret) {
111 DRM_DEV_ERROR(hdmi->dev, "failed to get vendor infoframe: %d\n",
112 ret);
113 return ret;
114 }
115
116 return zx_hdmi_infoframe_trans(hdmi, &frame, FSEL_VSIF);
117}
118
119static int zx_hdmi_config_video_avi(struct zx_hdmi *hdmi,
120 struct drm_display_mode *mode)
121{
122 union hdmi_infoframe frame;
123 int ret;
124
125 ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi,
126 &hdmi->connector,
127 mode);
128 if (ret) {
129 DRM_DEV_ERROR(hdmi->dev, "failed to get avi infoframe: %d\n",
130 ret);
131 return ret;
132 }
133
134 /* We always use YUV444 for HDMI output. */
135 frame.avi.colorspace = HDMI_COLORSPACE_YUV444;
136
137 return zx_hdmi_infoframe_trans(hdmi, &frame, FSEL_AVI);
138}
139
140static void zx_hdmi_encoder_mode_set(struct drm_encoder *encoder,
141 struct drm_display_mode *mode,
142 struct drm_display_mode *adj_mode)
143{
144 struct zx_hdmi *hdmi = to_zx_hdmi(encoder);
145
146 if (hdmi->sink_is_hdmi) {
147 zx_hdmi_config_video_avi(hdmi, mode);
148 zx_hdmi_config_video_vsi(hdmi, mode);
149 }
150}
151
152static void zx_hdmi_phy_start(struct zx_hdmi *hdmi)
153{
154 /* Copy from ZTE BSP code */
155 hdmi_writeb(hdmi, 0x222, 0x0);
156 hdmi_writeb(hdmi, 0x224, 0x4);
157 hdmi_writeb(hdmi, 0x909, 0x0);
158 hdmi_writeb(hdmi, 0x7b0, 0x90);
159 hdmi_writeb(hdmi, 0x7b1, 0x00);
160 hdmi_writeb(hdmi, 0x7b2, 0xa7);
161 hdmi_writeb(hdmi, 0x7b8, 0xaa);
162 hdmi_writeb(hdmi, 0x7b2, 0xa7);
163 hdmi_writeb(hdmi, 0x7b3, 0x0f);
164 hdmi_writeb(hdmi, 0x7b4, 0x0f);
165 hdmi_writeb(hdmi, 0x7b5, 0x55);
166 hdmi_writeb(hdmi, 0x7b7, 0x03);
167 hdmi_writeb(hdmi, 0x7b9, 0x12);
168 hdmi_writeb(hdmi, 0x7ba, 0x32);
169 hdmi_writeb(hdmi, 0x7bc, 0x68);
170 hdmi_writeb(hdmi, 0x7be, 0x40);
171 hdmi_writeb(hdmi, 0x7bf, 0x84);
172 hdmi_writeb(hdmi, 0x7c1, 0x0f);
173 hdmi_writeb(hdmi, 0x7c8, 0x02);
174 hdmi_writeb(hdmi, 0x7c9, 0x03);
175 hdmi_writeb(hdmi, 0x7ca, 0x40);
176 hdmi_writeb(hdmi, 0x7dc, 0x31);
177 hdmi_writeb(hdmi, 0x7e2, 0x04);
178 hdmi_writeb(hdmi, 0x7e0, 0x06);
179 hdmi_writeb(hdmi, 0x7cb, 0x68);
180 hdmi_writeb(hdmi, 0x7f9, 0x02);
181 hdmi_writeb(hdmi, 0x7b6, 0x02);
182 hdmi_writeb(hdmi, 0x7f3, 0x0);
183}
184
185static void zx_hdmi_hw_enable(struct zx_hdmi *hdmi)
186{
187 /* Enable pclk */
188 hdmi_writeb_mask(hdmi, CLKPWD, CLKPWD_PDIDCK, CLKPWD_PDIDCK);
189
190 /* Enable HDMI for TX */
191 hdmi_writeb_mask(hdmi, FUNC_SEL, FUNC_HDMI_EN, FUNC_HDMI_EN);
192
193 /* Enable deep color packet */
194 hdmi_writeb_mask(hdmi, P2T_CTRL, P2T_DC_PKT_EN, P2T_DC_PKT_EN);
195
196 /* Enable HDMI/MHL mode for output */
197 hdmi_writeb_mask(hdmi, TEST_TXCTRL, TEST_TXCTRL_HDMI_MODE,
198 TEST_TXCTRL_HDMI_MODE);
199
200 /* Configure reg_qc_sel */
201 hdmi_writeb(hdmi, HDMICTL4, 0x3);
202
203 /* Enable interrupt */
204 hdmi_writeb_mask(hdmi, INTR1_MASK, INTR1_MONITOR_DETECT,
205 INTR1_MONITOR_DETECT);
206
207 /* Start up phy */
208 zx_hdmi_phy_start(hdmi);
209}
210
211static void zx_hdmi_hw_disable(struct zx_hdmi *hdmi)
212{
213 /* Disable interrupt */
214 hdmi_writeb_mask(hdmi, INTR1_MASK, INTR1_MONITOR_DETECT, 0);
215
216 /* Disable deep color packet */
217 hdmi_writeb_mask(hdmi, P2T_CTRL, P2T_DC_PKT_EN, P2T_DC_PKT_EN);
218
219 /* Disable HDMI for TX */
220 hdmi_writeb_mask(hdmi, FUNC_SEL, FUNC_HDMI_EN, 0);
221
222 /* Disable pclk */
223 hdmi_writeb_mask(hdmi, CLKPWD, CLKPWD_PDIDCK, 0);
224}
225
226static void zx_hdmi_encoder_enable(struct drm_encoder *encoder)
227{
228 struct zx_hdmi *hdmi = to_zx_hdmi(encoder);
229
230 clk_prepare_enable(hdmi->cec_clk);
231 clk_prepare_enable(hdmi->osc_clk);
232 clk_prepare_enable(hdmi->xclk);
233
234 zx_hdmi_hw_enable(hdmi);
235
236 vou_inf_enable(VOU_HDMI, encoder->crtc);
237}
238
239static void zx_hdmi_encoder_disable(struct drm_encoder *encoder)
240{
241 struct zx_hdmi *hdmi = to_zx_hdmi(encoder);
242
243 vou_inf_disable(VOU_HDMI, encoder->crtc);
244
245 zx_hdmi_hw_disable(hdmi);
246
247 clk_disable_unprepare(hdmi->xclk);
248 clk_disable_unprepare(hdmi->osc_clk);
249 clk_disable_unprepare(hdmi->cec_clk);
250}
251
252static const struct drm_encoder_helper_funcs zx_hdmi_encoder_helper_funcs = {
253 .enable = zx_hdmi_encoder_enable,
254 .disable = zx_hdmi_encoder_disable,
255 .mode_set = zx_hdmi_encoder_mode_set,
256};
257
258static int zx_hdmi_connector_get_modes(struct drm_connector *connector)
259{
260 struct zx_hdmi *hdmi = to_zx_hdmi(connector);
261 struct edid *edid;
262 int ret;
263
264 edid = drm_get_edid(connector, &hdmi->ddc->adap);
265 if (!edid)
266 return 0;
267
268 hdmi->sink_is_hdmi = drm_detect_hdmi_monitor(edid);
269 hdmi->sink_has_audio = drm_detect_monitor_audio(edid);
270 drm_connector_update_edid_property(connector, edid);
271 ret = drm_add_edid_modes(connector, edid);
272 kfree(edid);
273
274 return ret;
275}
276
277static enum drm_mode_status
278zx_hdmi_connector_mode_valid(struct drm_connector *connector,
279 struct drm_display_mode *mode)
280{
281 return MODE_OK;
282}
283
284static struct drm_connector_helper_funcs zx_hdmi_connector_helper_funcs = {
285 .get_modes = zx_hdmi_connector_get_modes,
286 .mode_valid = zx_hdmi_connector_mode_valid,
287};
288
289static enum drm_connector_status
290zx_hdmi_connector_detect(struct drm_connector *connector, bool force)
291{
292 struct zx_hdmi *hdmi = to_zx_hdmi(connector);
293
294 return (hdmi_readb(hdmi, TPI_HPD_RSEN) & TPI_HPD_CONNECTION) ?
295 connector_status_connected : connector_status_disconnected;
296}
297
298static const struct drm_connector_funcs zx_hdmi_connector_funcs = {
299 .fill_modes = drm_helper_probe_single_connector_modes,
300 .detect = zx_hdmi_connector_detect,
301 .destroy = drm_connector_cleanup,
302 .reset = drm_atomic_helper_connector_reset,
303 .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
304 .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
305};
306
307static int zx_hdmi_register(struct drm_device *drm, struct zx_hdmi *hdmi)
308{
309 struct drm_encoder *encoder = &hdmi->encoder;
310
311 encoder->possible_crtcs = VOU_CRTC_MASK;
312
313 drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_TMDS);
314 drm_encoder_helper_add(encoder, &zx_hdmi_encoder_helper_funcs);
315
316 hdmi->connector.polled = DRM_CONNECTOR_POLL_HPD;
317
318 drm_connector_init_with_ddc(drm, &hdmi->connector,
319 &zx_hdmi_connector_funcs,
320 DRM_MODE_CONNECTOR_HDMIA,
321 &hdmi->ddc->adap);
322 drm_connector_helper_add(&hdmi->connector,
323 &zx_hdmi_connector_helper_funcs);
324
325 drm_connector_attach_encoder(&hdmi->connector, encoder);
326
327 return 0;
328}
329
330static irqreturn_t zx_hdmi_irq_thread(int irq, void *dev_id)
331{
332 struct zx_hdmi *hdmi = dev_id;
333
334 drm_helper_hpd_irq_event(hdmi->connector.dev);
335
336 return IRQ_HANDLED;
337}
338
339static irqreturn_t zx_hdmi_irq_handler(int irq, void *dev_id)
340{
341 struct zx_hdmi *hdmi = dev_id;
342 u8 lstat;
343
344 lstat = hdmi_readb(hdmi, L1_INTR_STAT);
345
346 /* Monitor detect/HPD interrupt */
347 if (lstat & L1_INTR_STAT_INTR1) {
348 u8 stat;
349
350 stat = hdmi_readb(hdmi, INTR1_STAT);
351 hdmi_writeb(hdmi, INTR1_STAT, stat);
352
353 if (stat & INTR1_MONITOR_DETECT)
354 return IRQ_WAKE_THREAD;
355 }
356
357 return IRQ_NONE;
358}
359
360static int zx_hdmi_audio_startup(struct device *dev, void *data)
361{
362 struct zx_hdmi *hdmi = dev_get_drvdata(dev);
363 struct drm_encoder *encoder = &hdmi->encoder;
364
365 vou_inf_hdmi_audio_sel(encoder->crtc, VOU_HDMI_AUD_SPDIF);
366
367 return 0;
368}
369
370static void zx_hdmi_audio_shutdown(struct device *dev, void *data)
371{
372 struct zx_hdmi *hdmi = dev_get_drvdata(dev);
373
374 /* Disable audio input */
375 hdmi_writeb_mask(hdmi, AUD_EN, AUD_IN_EN, 0);
376}
377
378static inline int zx_hdmi_audio_get_n(unsigned int fs)
379{
380 unsigned int n;
381
382 if (fs && (fs % 44100) == 0)
383 n = 6272 * (fs / 44100);
384 else
385 n = fs * 128 / 1000;
386
387 return n;
388}
389
390static int zx_hdmi_audio_hw_params(struct device *dev,
391 void *data,
392 struct hdmi_codec_daifmt *daifmt,
393 struct hdmi_codec_params *params)
394{
395 struct zx_hdmi *hdmi = dev_get_drvdata(dev);
396 struct hdmi_audio_infoframe *cea = &params->cea;
397 union hdmi_infoframe frame;
398 int n;
399
400 /* We only support spdif for now */
401 if (daifmt->fmt != HDMI_SPDIF) {
402 DRM_DEV_ERROR(hdmi->dev, "invalid daifmt %d\n", daifmt->fmt);
403 return -EINVAL;
404 }
405
406 switch (params->sample_width) {
407 case 16:
408 hdmi_writeb_mask(hdmi, TPI_AUD_CONFIG, SPDIF_SAMPLE_SIZE_MASK,
409 SPDIF_SAMPLE_SIZE_16BIT);
410 break;
411 case 20:
412 hdmi_writeb_mask(hdmi, TPI_AUD_CONFIG, SPDIF_SAMPLE_SIZE_MASK,
413 SPDIF_SAMPLE_SIZE_20BIT);
414 break;
415 case 24:
416 hdmi_writeb_mask(hdmi, TPI_AUD_CONFIG, SPDIF_SAMPLE_SIZE_MASK,
417 SPDIF_SAMPLE_SIZE_24BIT);
418 break;
419 default:
420 DRM_DEV_ERROR(hdmi->dev, "invalid sample width %d\n",
421 params->sample_width);
422 return -EINVAL;
423 }
424
425 /* CTS is calculated by hardware, and we only need to take care of N */
426 n = zx_hdmi_audio_get_n(params->sample_rate);
427 hdmi_writeb(hdmi, N_SVAL1, n & 0xff);
428 hdmi_writeb(hdmi, N_SVAL2, (n >> 8) & 0xff);
429 hdmi_writeb(hdmi, N_SVAL3, (n >> 16) & 0xf);
430
431 /* Enable spdif mode */
432 hdmi_writeb_mask(hdmi, AUD_MODE, SPDIF_EN, SPDIF_EN);
433
434 /* Enable audio input */
435 hdmi_writeb_mask(hdmi, AUD_EN, AUD_IN_EN, AUD_IN_EN);
436
437 memcpy(&frame.audio, cea, sizeof(*cea));
438
439 return zx_hdmi_infoframe_trans(hdmi, &frame, FSEL_AUDIO);
440}
441
442static int zx_hdmi_audio_mute(struct device *dev, void *data,
443 bool enable, int direction)
444{
445 struct zx_hdmi *hdmi = dev_get_drvdata(dev);
446
447 if (enable)
448 hdmi_writeb_mask(hdmi, TPI_AUD_CONFIG, TPI_AUD_MUTE,
449 TPI_AUD_MUTE);
450 else
451 hdmi_writeb_mask(hdmi, TPI_AUD_CONFIG, TPI_AUD_MUTE, 0);
452
453 return 0;
454}
455
456static int zx_hdmi_audio_get_eld(struct device *dev, void *data,
457 uint8_t *buf, size_t len)
458{
459 struct zx_hdmi *hdmi = dev_get_drvdata(dev);
460 struct drm_connector *connector = &hdmi->connector;
461
462 memcpy(buf, connector->eld, min(sizeof(connector->eld), len));
463
464 return 0;
465}
466
467static const struct hdmi_codec_ops zx_hdmi_codec_ops = {
468 .audio_startup = zx_hdmi_audio_startup,
469 .hw_params = zx_hdmi_audio_hw_params,
470 .audio_shutdown = zx_hdmi_audio_shutdown,
471 .mute_stream = zx_hdmi_audio_mute,
472 .get_eld = zx_hdmi_audio_get_eld,
473 .no_capture_mute = 1,
474};
475
476static struct hdmi_codec_pdata zx_hdmi_codec_pdata = {
477 .ops = &zx_hdmi_codec_ops,
478 .spdif = 1,
479};
480
481static int zx_hdmi_audio_register(struct zx_hdmi *hdmi)
482{
483 struct platform_device *pdev;
484
485 pdev = platform_device_register_data(hdmi->dev, HDMI_CODEC_DRV_NAME,
486 PLATFORM_DEVID_AUTO,
487 &zx_hdmi_codec_pdata,
488 sizeof(zx_hdmi_codec_pdata));
489 if (IS_ERR(pdev))
490 return PTR_ERR(pdev);
491
492 hdmi->audio_pdev = pdev;
493
494 return 0;
495}
496
497static int zx_hdmi_i2c_read(struct zx_hdmi *hdmi, struct i2c_msg *msg)
498{
499 int len = msg->len;
500 u8 *buf = msg->buf;
501 int retry = 0;
502 int ret = 0;
503
504 /* Bits [9:8] of bytes */
505 hdmi_writeb(hdmi, ZX_DDC_DIN_CNT2, (len >> 8) & 0xff);
506 /* Bits [7:0] of bytes */
507 hdmi_writeb(hdmi, ZX_DDC_DIN_CNT1, len & 0xff);
508
509 /* Clear FIFO */
510 hdmi_writeb_mask(hdmi, ZX_DDC_CMD, DDC_CMD_MASK, DDC_CMD_CLEAR_FIFO);
511
512 /* Kick off the read */
513 hdmi_writeb_mask(hdmi, ZX_DDC_CMD, DDC_CMD_MASK,
514 DDC_CMD_SEQUENTIAL_READ);
515
516 while (len > 0) {
517 int cnt, i;
518
519 /* FIFO needs some time to get ready */
520 usleep_range(500, 1000);
521
522 cnt = hdmi_readb(hdmi, ZX_DDC_DOUT_CNT) & DDC_DOUT_CNT_MASK;
523 if (cnt == 0) {
524 if (++retry > 5) {
525 DRM_DEV_ERROR(hdmi->dev,
526 "DDC FIFO read timed out!");
527 return -ETIMEDOUT;
528 }
529 continue;
530 }
531
532 for (i = 0; i < cnt; i++)
533 *buf++ = hdmi_readb(hdmi, ZX_DDC_DATA);
534 len -= cnt;
535 }
536
537 return ret;
538}
539
540static int zx_hdmi_i2c_write(struct zx_hdmi *hdmi, struct i2c_msg *msg)
541{
542 /*
543 * The DDC I2C adapter is only for reading EDID data, so we assume
544 * that the write to this adapter must be the EDID data offset.
545 */
546 if ((msg->len != 1) ||
547 ((msg->addr != DDC_ADDR) && (msg->addr != DDC_SEGMENT_ADDR)))
548 return -EINVAL;
549
550 if (msg->addr == DDC_SEGMENT_ADDR)
551 hdmi_writeb(hdmi, ZX_DDC_SEGM, msg->addr << 1);
552 else if (msg->addr == DDC_ADDR)
553 hdmi_writeb(hdmi, ZX_DDC_ADDR, msg->addr << 1);
554
555 hdmi_writeb(hdmi, ZX_DDC_OFFSET, msg->buf[0]);
556
557 return 0;
558}
559
560static int zx_hdmi_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
561 int num)
562{
563 struct zx_hdmi *hdmi = i2c_get_adapdata(adap);
564 struct zx_hdmi_i2c *ddc = hdmi->ddc;
565 int i, ret = 0;
566
567 mutex_lock(&ddc->lock);
568
569 /* Enable DDC master access */
570 hdmi_writeb_mask(hdmi, TPI_DDC_MASTER_EN, HW_DDC_MASTER, HW_DDC_MASTER);
571
572 for (i = 0; i < num; i++) {
573 DRM_DEV_DEBUG(hdmi->dev,
574 "xfer: num: %d/%d, len: %d, flags: %#x\n",
575 i + 1, num, msgs[i].len, msgs[i].flags);
576
577 if (msgs[i].flags & I2C_M_RD)
578 ret = zx_hdmi_i2c_read(hdmi, &msgs[i]);
579 else
580 ret = zx_hdmi_i2c_write(hdmi, &msgs[i]);
581
582 if (ret < 0)
583 break;
584 }
585
586 if (!ret)
587 ret = num;
588
589 /* Disable DDC master access */
590 hdmi_writeb_mask(hdmi, TPI_DDC_MASTER_EN, HW_DDC_MASTER, 0);
591
592 mutex_unlock(&ddc->lock);
593
594 return ret;
595}
596
597static u32 zx_hdmi_i2c_func(struct i2c_adapter *adapter)
598{
599 return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
600}
601
602static const struct i2c_algorithm zx_hdmi_algorithm = {
603 .master_xfer = zx_hdmi_i2c_xfer,
604 .functionality = zx_hdmi_i2c_func,
605};
606
607static int zx_hdmi_ddc_register(struct zx_hdmi *hdmi)
608{
609 struct i2c_adapter *adap;
610 struct zx_hdmi_i2c *ddc;
611 int ret;
612
613 ddc = devm_kzalloc(hdmi->dev, sizeof(*ddc), GFP_KERNEL);
614 if (!ddc)
615 return -ENOMEM;
616
617 hdmi->ddc = ddc;
618 mutex_init(&ddc->lock);
619
620 adap = &ddc->adap;
621 adap->owner = THIS_MODULE;
622 adap->class = I2C_CLASS_DDC;
623 adap->dev.parent = hdmi->dev;
624 adap->algo = &zx_hdmi_algorithm;
625 snprintf(adap->name, sizeof(adap->name), "zx hdmi i2c");
626
627 ret = i2c_add_adapter(adap);
628 if (ret) {
629 DRM_DEV_ERROR(hdmi->dev, "failed to add I2C adapter: %d\n",
630 ret);
631 return ret;
632 }
633
634 i2c_set_adapdata(adap, hdmi);
635
636 return 0;
637}
638
639static int zx_hdmi_bind(struct device *dev, struct device *master, void *data)
640{
641 struct platform_device *pdev = to_platform_device(dev);
642 struct drm_device *drm = data;
643 struct resource *res;
644 struct zx_hdmi *hdmi;
645 int irq;
646 int ret;
647
648 hdmi = devm_kzalloc(dev, sizeof(*hdmi), GFP_KERNEL);
649 if (!hdmi)
650 return -ENOMEM;
651
652 hdmi->dev = dev;
653 hdmi->drm = drm;
654
655 dev_set_drvdata(dev, hdmi);
656
657 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
658 hdmi->mmio = devm_ioremap_resource(dev, res);
659 if (IS_ERR(hdmi->mmio)) {
660 ret = PTR_ERR(hdmi->mmio);
661 DRM_DEV_ERROR(dev, "failed to remap hdmi region: %d\n", ret);
662 return ret;
663 }
664
665 irq = platform_get_irq(pdev, 0);
666 if (irq < 0)
667 return irq;
668
669 hdmi->cec_clk = devm_clk_get(hdmi->dev, "osc_cec");
670 if (IS_ERR(hdmi->cec_clk)) {
671 ret = PTR_ERR(hdmi->cec_clk);
672 DRM_DEV_ERROR(dev, "failed to get cec_clk: %d\n", ret);
673 return ret;
674 }
675
676 hdmi->osc_clk = devm_clk_get(hdmi->dev, "osc_clk");
677 if (IS_ERR(hdmi->osc_clk)) {
678 ret = PTR_ERR(hdmi->osc_clk);
679 DRM_DEV_ERROR(dev, "failed to get osc_clk: %d\n", ret);
680 return ret;
681 }
682
683 hdmi->xclk = devm_clk_get(hdmi->dev, "xclk");
684 if (IS_ERR(hdmi->xclk)) {
685 ret = PTR_ERR(hdmi->xclk);
686 DRM_DEV_ERROR(dev, "failed to get xclk: %d\n", ret);
687 return ret;
688 }
689
690 ret = zx_hdmi_ddc_register(hdmi);
691 if (ret) {
692 DRM_DEV_ERROR(dev, "failed to register ddc: %d\n", ret);
693 return ret;
694 }
695
696 ret = zx_hdmi_audio_register(hdmi);
697 if (ret) {
698 DRM_DEV_ERROR(dev, "failed to register audio: %d\n", ret);
699 return ret;
700 }
701
702 ret = zx_hdmi_register(drm, hdmi);
703 if (ret) {
704 DRM_DEV_ERROR(dev, "failed to register hdmi: %d\n", ret);
705 return ret;
706 }
707
708 ret = devm_request_threaded_irq(dev, irq, zx_hdmi_irq_handler,
709 zx_hdmi_irq_thread, IRQF_SHARED,
710 dev_name(dev), hdmi);
711 if (ret) {
712 DRM_DEV_ERROR(dev, "failed to request threaded irq: %d\n", ret);
713 return ret;
714 }
715
716 return 0;
717}
718
719static void zx_hdmi_unbind(struct device *dev, struct device *master,
720 void *data)
721{
722 struct zx_hdmi *hdmi = dev_get_drvdata(dev);
723
724 hdmi->connector.funcs->destroy(&hdmi->connector);
725 hdmi->encoder.funcs->destroy(&hdmi->encoder);
726
727 if (hdmi->audio_pdev)
728 platform_device_unregister(hdmi->audio_pdev);
729}
730
731static const struct component_ops zx_hdmi_component_ops = {
732 .bind = zx_hdmi_bind,
733 .unbind = zx_hdmi_unbind,
734};
735
736static int zx_hdmi_probe(struct platform_device *pdev)
737{
738 return component_add(&pdev->dev, &zx_hdmi_component_ops);
739}
740
741static int zx_hdmi_remove(struct platform_device *pdev)
742{
743 component_del(&pdev->dev, &zx_hdmi_component_ops);
744 return 0;
745}
746
747static const struct of_device_id zx_hdmi_of_match[] = {
748 { .compatible = "zte,zx296718-hdmi", },
749 { /* end */ },
750};
751MODULE_DEVICE_TABLE(of, zx_hdmi_of_match);
752
753struct platform_driver zx_hdmi_driver = {
754 .probe = zx_hdmi_probe,
755 .remove = zx_hdmi_remove,
756 .driver = {
757 .name = "zx-hdmi",
758 .of_match_table = zx_hdmi_of_match,
759 },
760};
drivers/gpu/drm/zte/zx_hdmi_regs.h+0−66
@@ -1,66 +0,0 @@
1/* SPDX-License-Identifier: GPL-2.0-only */
2/*
3 * Copyright 2016 Linaro Ltd.
4 * Copyright 2016 ZTE Corporation.
5 */
6
7#ifndef __ZX_HDMI_REGS_H__
8#define __ZX_HDMI_REGS_H__
9
10#define FUNC_SEL 0x000b
11#define FUNC_HDMI_EN BIT(0)
12#define CLKPWD 0x000d
13#define CLKPWD_PDIDCK BIT(2)
14#define P2T_CTRL 0x0066
15#define P2T_DC_PKT_EN BIT(7)
16#define L1_INTR_STAT 0x007e
17#define L1_INTR_STAT_INTR1 BIT(0)
18#define INTR1_STAT 0x008f
19#define INTR1_MASK 0x0095
20#define INTR1_MONITOR_DETECT (BIT(5) | BIT(6))
21#define ZX_DDC_ADDR 0x00ed
22#define ZX_DDC_SEGM 0x00ee
23#define ZX_DDC_OFFSET 0x00ef
24#define ZX_DDC_DIN_CNT1 0x00f0
25#define ZX_DDC_DIN_CNT2 0x00f1
26#define ZX_DDC_CMD 0x00f3
27#define DDC_CMD_MASK 0xf
28#define DDC_CMD_CLEAR_FIFO 0x9
29#define DDC_CMD_SEQUENTIAL_READ 0x2
30#define ZX_DDC_DATA 0x00f4
31#define ZX_DDC_DOUT_CNT 0x00f5
32#define DDC_DOUT_CNT_MASK 0x1f
33#define TEST_TXCTRL 0x00f7
34#define TEST_TXCTRL_HDMI_MODE BIT(1)
35#define HDMICTL4 0x0235
36#define TPI_HPD_RSEN 0x063b
37#define TPI_HPD_CONNECTION (BIT(1) | BIT(2))
38#define TPI_INFO_FSEL 0x06bf
39#define FSEL_AVI 0
40#define FSEL_GBD 1
41#define FSEL_AUDIO 2
42#define FSEL_SPD 3
43#define FSEL_MPEG 4
44#define FSEL_VSIF 5
45#define TPI_INFO_B0 0x06c0
46#define TPI_INFO_EN 0x06df
47#define TPI_INFO_TRANS_EN BIT(7)
48#define TPI_INFO_TRANS_RPT BIT(6)
49#define TPI_DDC_MASTER_EN 0x06f8
50#define HW_DDC_MASTER BIT(7)
51#define N_SVAL1 0xa03
52#define N_SVAL2 0xa04
53#define N_SVAL3 0xa05
54#define AUD_EN 0xa13
55#define AUD_IN_EN BIT(0)
56#define AUD_MODE 0xa14
57#define SPDIF_EN BIT(1)
58#define TPI_AUD_CONFIG 0xa62
59#define SPDIF_SAMPLE_SIZE_SHIFT 6
60#define SPDIF_SAMPLE_SIZE_MASK (0x3 << SPDIF_SAMPLE_SIZE_SHIFT)
61#define SPDIF_SAMPLE_SIZE_16BIT (0x1 << SPDIF_SAMPLE_SIZE_SHIFT)
62#define SPDIF_SAMPLE_SIZE_20BIT (0x2 << SPDIF_SAMPLE_SIZE_SHIFT)
63#define SPDIF_SAMPLE_SIZE_24BIT (0x3 << SPDIF_SAMPLE_SIZE_SHIFT)
64#define TPI_AUD_MUTE BIT(4)
65
66#endif /* __ZX_HDMI_REGS_H__ */
drivers/gpu/drm/zte/zx_plane.c+0−537
@@ -1,537 +0,0 @@
1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * Copyright 2016 Linaro Ltd.
4 * Copyright 2016 ZTE Corporation.
5 */
6
7#include <drm/drm_atomic.h>
8#include <drm/drm_atomic_helper.h>
9#include <drm/drm_fb_cma_helper.h>
10#include <drm/drm_fourcc.h>
11#include <drm/drm_gem_cma_helper.h>
12#include <drm/drm_modeset_helper_vtables.h>
13#include <drm/drm_plane_helper.h>
14
15#include "zx_common_regs.h"
16#include "zx_drm_drv.h"
17#include "zx_plane.h"
18#include "zx_plane_regs.h"
19#include "zx_vou.h"
20
21static const uint32_t gl_formats[] = {
22 DRM_FORMAT_ARGB8888,
23 DRM_FORMAT_XRGB8888,
24 DRM_FORMAT_RGB888,
25 DRM_FORMAT_RGB565,
26 DRM_FORMAT_ARGB1555,
27 DRM_FORMAT_ARGB4444,
28};
29
30static const uint32_t vl_formats[] = {
31 DRM_FORMAT_NV12, /* Semi-planar YUV420 */
32 DRM_FORMAT_YUV420, /* Planar YUV420 */
33 DRM_FORMAT_YUYV, /* Packed YUV422 */
34 DRM_FORMAT_YVYU,
35 DRM_FORMAT_UYVY,
36 DRM_FORMAT_VYUY,
37 DRM_FORMAT_YUV444, /* YUV444 8bit */
38 /*
39 * TODO: add formats below that HW supports:
40 * - YUV420 P010
41 * - YUV420 Hantro
42 * - YUV444 10bit
43 */
44};
45
46#define FRAC_16_16(mult, div) (((mult) << 16) / (div))
47
48static int zx_vl_plane_atomic_check(struct drm_plane *plane,
49 struct drm_atomic_state *state)
50{
51 struct drm_plane_state *plane_state = drm_atomic_get_new_plane_state(state,
52 plane);
53 struct drm_framebuffer *fb = plane_state->fb;
54 struct drm_crtc *crtc = plane_state->crtc;
55 struct drm_crtc_state *crtc_state;
56 int min_scale = FRAC_16_16(1, 8);
57 int max_scale = FRAC_16_16(8, 1);
58
59 if (!crtc || WARN_ON(!fb))
60 return 0;
61
62 crtc_state = drm_atomic_get_existing_crtc_state(state,
63 crtc);
64 if (WARN_ON(!crtc_state))
65 return -EINVAL;
66
67 /* nothing to check when disabling or disabled */
68 if (!crtc_state->enable)
69 return 0;
70
71 /* plane must be enabled */
72 if (!plane_state->crtc)
73 return -EINVAL;
74
75 return drm_atomic_helper_check_plane_state(plane_state, crtc_state,
76 min_scale, max_scale,
77 true, true);
78}
79
80static int zx_vl_get_fmt(uint32_t format)
81{
82 switch (format) {
83 case DRM_FORMAT_NV12:
84 return VL_FMT_YUV420;
85 case DRM_FORMAT_YUV420:
86 return VL_YUV420_PLANAR | VL_FMT_YUV420;
87 case DRM_FORMAT_YUYV:
88 return VL_YUV422_YUYV | VL_FMT_YUV422;
89 case DRM_FORMAT_YVYU:
90 return VL_YUV422_YVYU | VL_FMT_YUV422;
91 case DRM_FORMAT_UYVY:
92 return VL_YUV422_UYVY | VL_FMT_YUV422;
93 case DRM_FORMAT_VYUY:
94 return VL_YUV422_VYUY | VL_FMT_YUV422;
95 case DRM_FORMAT_YUV444:
96 return VL_FMT_YUV444_8BIT;
97 default:
98 WARN_ONCE(1, "invalid pixel format %d\n", format);
99 return -EINVAL;
100 }
101}
102
103static inline void zx_vl_set_update(struct zx_plane *zplane)
104{
105 void __iomem *layer = zplane->layer;
106
107 zx_writel_mask(layer + VL_CTRL0, VL_UPDATE, VL_UPDATE);
108}
109
110static inline void zx_vl_rsz_set_update(struct zx_plane *zplane)
111{
112 zx_writel(zplane->rsz + RSZ_VL_ENABLE_CFG, 1);
113}
114
115static int zx_vl_rsz_get_fmt(uint32_t format)
116{
117 switch (format) {
118 case DRM_FORMAT_NV12:
119 case DRM_FORMAT_YUV420:
120 return RSZ_VL_FMT_YCBCR420;
121 case DRM_FORMAT_YUYV:
122 case DRM_FORMAT_YVYU:
123 case DRM_FORMAT_UYVY:
124 case DRM_FORMAT_VYUY:
125 return RSZ_VL_FMT_YCBCR422;
126 case DRM_FORMAT_YUV444:
127 return RSZ_VL_FMT_YCBCR444;
128 default:
129 WARN_ONCE(1, "invalid pixel format %d\n", format);
130 return -EINVAL;
131 }
132}
133
134static inline u32 rsz_step_value(u32 src, u32 dst)
135{
136 u32 val = 0;
137
138 if (src == dst)
139 val = 0;
140 else if (src < dst)
141 val = RSZ_PARA_STEP((src << 16) / dst);
142 else if (src > dst)
143 val = RSZ_DATA_STEP(src / dst) |
144 RSZ_PARA_STEP(((src << 16) / dst) & 0xffff);
145
146 return val;
147}
148
149static void zx_vl_rsz_setup(struct zx_plane *zplane, uint32_t format,
150 u32 src_w, u32 src_h, u32 dst_w, u32 dst_h)
151{
152 void __iomem *rsz = zplane->rsz;
153 u32 src_chroma_w = src_w;
154 u32 src_chroma_h = src_h;
155 int fmt;
156
157 /* Set up source and destination resolution */
158 zx_writel(rsz + RSZ_SRC_CFG, RSZ_VER(src_h - 1) | RSZ_HOR(src_w - 1));
159 zx_writel(rsz + RSZ_DEST_CFG, RSZ_VER(dst_h - 1) | RSZ_HOR(dst_w - 1));
160
161 /* Configure data format for VL RSZ */
162 fmt = zx_vl_rsz_get_fmt(format);
163 if (fmt >= 0)
164 zx_writel_mask(rsz + RSZ_VL_CTRL_CFG, RSZ_VL_FMT_MASK, fmt);
165
166 /* Calculate Chroma height and width */
167 if (fmt == RSZ_VL_FMT_YCBCR420) {
168 src_chroma_w = src_w >> 1;
169 src_chroma_h = src_h >> 1;
170 } else if (fmt == RSZ_VL_FMT_YCBCR422) {
171 src_chroma_w = src_w >> 1;
172 }
173
174 /* Set up Luma and Chroma step registers */
175 zx_writel(rsz + RSZ_VL_LUMA_HOR, rsz_step_value(src_w, dst_w));
176 zx_writel(rsz + RSZ_VL_LUMA_VER, rsz_step_value(src_h, dst_h));
177 zx_writel(rsz + RSZ_VL_CHROMA_HOR, rsz_step_value(src_chroma_w, dst_w));
178 zx_writel(rsz + RSZ_VL_CHROMA_VER, rsz_step_value(src_chroma_h, dst_h));
179
180 zx_vl_rsz_set_update(zplane);
181}
182
183static void zx_vl_plane_atomic_update(struct drm_plane *plane,
184 struct drm_atomic_state *state)
185{
186 struct zx_plane *zplane = to_zx_plane(plane);
187 struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state,
188 plane);
189 struct drm_framebuffer *fb = new_state->fb;
190 struct drm_rect *src = &new_state->src;
191 struct drm_rect *dst = &new_state->dst;
192 struct drm_gem_cma_object *cma_obj;
193 void __iomem *layer = zplane->layer;
194 void __iomem *hbsc = zplane->hbsc;
195 void __iomem *paddr_reg;
196 dma_addr_t paddr;
197 u32 src_x, src_y, src_w, src_h;
198 u32 dst_x, dst_y, dst_w, dst_h;
199 uint32_t format;
200 int fmt;
201 int i;
202
203 if (!fb)
204 return;
205
206 format = fb->format->format;
207
208 src_x = src->x1 >> 16;
209 src_y = src->y1 >> 16;
210 src_w = drm_rect_width(src) >> 16;
211 src_h = drm_rect_height(src) >> 16;
212
213 dst_x = dst->x1;
214 dst_y = dst->y1;
215 dst_w = drm_rect_width(dst);
216 dst_h = drm_rect_height(dst);
217
218 /* Set up data address registers for Y, Cb and Cr planes */
219 paddr_reg = layer + VL_Y;
220 for (i = 0; i < fb->format->num_planes; i++) {
221 cma_obj = drm_fb_cma_get_gem_obj(fb, i);
222 paddr = cma_obj->paddr + fb->offsets[i];
223 paddr += src_y * fb->pitches[i];
224 paddr += src_x * fb->format->cpp[i];
225 zx_writel(paddr_reg, paddr);
226 paddr_reg += 4;
227 }
228
229 /* Set up source height/width register */
230 zx_writel(layer + VL_SRC_SIZE, GL_SRC_W(src_w) | GL_SRC_H(src_h));
231
232 /* Set up start position register */
233 zx_writel(layer + VL_POS_START, GL_POS_X(dst_x) | GL_POS_Y(dst_y));
234
235 /* Set up end position register */
236 zx_writel(layer + VL_POS_END,
237 GL_POS_X(dst_x + dst_w) | GL_POS_Y(dst_y + dst_h));
238
239 /* Strides of Cb and Cr planes should be identical */
240 zx_writel(layer + VL_STRIDE, LUMA_STRIDE(fb->pitches[0]) |
241 CHROMA_STRIDE(fb->pitches[1]));
242
243 /* Set up video layer data format */
244 fmt = zx_vl_get_fmt(format);
245 if (fmt >= 0)
246 zx_writel(layer + VL_CTRL1, fmt);
247
248 /* Always use scaler since it exists (set for not bypass) */
249 zx_writel_mask(layer + VL_CTRL2, VL_SCALER_BYPASS_MODE,
250 VL_SCALER_BYPASS_MODE);
251
252 zx_vl_rsz_setup(zplane, format, src_w, src_h, dst_w, dst_h);
253
254 /* Enable HBSC block */
255 zx_writel_mask(hbsc + HBSC_CTRL0, HBSC_CTRL_EN, HBSC_CTRL_EN);
256
257 zx_vou_layer_enable(plane);
258
259 zx_vl_set_update(zplane);
260}
261
262static void zx_plane_atomic_disable(struct drm_plane *plane,
263 struct drm_atomic_state *state)
264{
265 struct drm_plane_state *old_state = drm_atomic_get_old_plane_state(state,
266 plane);
267 struct zx_plane *zplane = to_zx_plane(plane);
268 void __iomem *hbsc = zplane->hbsc;
269
270 zx_vou_layer_disable(plane, old_state);
271
272 /* Disable HBSC block */
273 zx_writel_mask(hbsc + HBSC_CTRL0, HBSC_CTRL_EN, 0);
274}
275
276static const struct drm_plane_helper_funcs zx_vl_plane_helper_funcs = {
277 .atomic_check = zx_vl_plane_atomic_check,
278 .atomic_update = zx_vl_plane_atomic_update,
279 .atomic_disable = zx_plane_atomic_disable,
280};
281
282static int zx_gl_plane_atomic_check(struct drm_plane *plane,
283 struct drm_atomic_state *state)
284{
285 struct drm_plane_state *plane_state = drm_atomic_get_new_plane_state(state,
286 plane);
287 struct drm_framebuffer *fb = plane_state->fb;
288 struct drm_crtc *crtc = plane_state->crtc;
289 struct drm_crtc_state *crtc_state;
290
291 if (!crtc || WARN_ON(!fb))
292 return 0;
293
294 crtc_state = drm_atomic_get_existing_crtc_state(state,
295 crtc);
296 if (WARN_ON(!crtc_state))
297 return -EINVAL;
298
299 /* nothing to check when disabling or disabled */
300 if (!crtc_state->enable)
301 return 0;
302
303 /* plane must be enabled */
304 if (!plane_state->crtc)
305 return -EINVAL;
306
307 return drm_atomic_helper_check_plane_state(plane_state, crtc_state,
308 DRM_PLANE_HELPER_NO_SCALING,
309 DRM_PLANE_HELPER_NO_SCALING,
310 false, true);
311}
312
313static int zx_gl_get_fmt(uint32_t format)
314{
315 switch (format) {
316 case DRM_FORMAT_ARGB8888:
317 case DRM_FORMAT_XRGB8888:
318 return GL_FMT_ARGB8888;
319 case DRM_FORMAT_RGB888:
320 return GL_FMT_RGB888;
321 case DRM_FORMAT_RGB565:
322 return GL_FMT_RGB565;
323 case DRM_FORMAT_ARGB1555:
324 return GL_FMT_ARGB1555;
325 case DRM_FORMAT_ARGB4444:
326 return GL_FMT_ARGB4444;
327 default:
328 WARN_ONCE(1, "invalid pixel format %d\n", format);
329 return -EINVAL;
330 }
331}
332
333static inline void zx_gl_set_update(struct zx_plane *zplane)
334{
335 void __iomem *layer = zplane->layer;
336
337 zx_writel_mask(layer + GL_CTRL0, GL_UPDATE, GL_UPDATE);
338}
339
340static inline void zx_gl_rsz_set_update(struct zx_plane *zplane)
341{
342 zx_writel(zplane->rsz + RSZ_ENABLE_CFG, 1);
343}
344
345static void zx_gl_rsz_setup(struct zx_plane *zplane, u32 src_w, u32 src_h,
346 u32 dst_w, u32 dst_h)
347{
348 void __iomem *rsz = zplane->rsz;
349
350 zx_writel(rsz + RSZ_SRC_CFG, RSZ_VER(src_h - 1) | RSZ_HOR(src_w - 1));
351 zx_writel(rsz + RSZ_DEST_CFG, RSZ_VER(dst_h - 1) | RSZ_HOR(dst_w - 1));
352
353 zx_gl_rsz_set_update(zplane);
354}
355
356static void zx_gl_plane_atomic_update(struct drm_plane *plane,
357 struct drm_atomic_state *state)
358{
359 struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state,
360 plane);
361 struct zx_plane *zplane = to_zx_plane(plane);
362 struct drm_framebuffer *fb = new_state->fb;
363 struct drm_gem_cma_object *cma_obj;
364 void __iomem *layer = zplane->layer;
365 void __iomem *csc = zplane->csc;
366 void __iomem *hbsc = zplane->hbsc;
367 u32 src_x, src_y, src_w, src_h;
368 u32 dst_x, dst_y, dst_w, dst_h;
369 unsigned int bpp;
370 uint32_t format;
371 dma_addr_t paddr;
372 u32 stride;
373 int fmt;
374
375 if (!fb)
376 return;
377
378 format = fb->format->format;
379 stride = fb->pitches[0];
380
381 src_x = new_state->src_x >> 16;
382 src_y = new_state->src_y >> 16;
383 src_w = new_state->src_w >> 16;
384 src_h = new_state->src_h >> 16;
385
386 dst_x = new_state->crtc_x;
387 dst_y = new_state->crtc_y;
388 dst_w = new_state->crtc_w;
389 dst_h = new_state->crtc_h;
390
391 bpp = fb->format->cpp[0];
392
393 cma_obj = drm_fb_cma_get_gem_obj(fb, 0);
394 paddr = cma_obj->paddr + fb->offsets[0];
395 paddr += src_y * stride + src_x * bpp / 8;
396 zx_writel(layer + GL_ADDR, paddr);
397
398 /* Set up source height/width register */
399 zx_writel(layer + GL_SRC_SIZE, GL_SRC_W(src_w) | GL_SRC_H(src_h));
400
401 /* Set up start position register */
402 zx_writel(layer + GL_POS_START, GL_POS_X(dst_x) | GL_POS_Y(dst_y));
403
404 /* Set up end position register */
405 zx_writel(layer + GL_POS_END,
406 GL_POS_X(dst_x + dst_w) | GL_POS_Y(dst_y + dst_h));
407
408 /* Set up stride register */
409 zx_writel(layer + GL_STRIDE, stride & 0xffff);
410
411 /* Set up graphic layer data format */
412 fmt = zx_gl_get_fmt(format);
413 if (fmt >= 0)
414 zx_writel_mask(layer + GL_CTRL1, GL_DATA_FMT_MASK,
415 fmt << GL_DATA_FMT_SHIFT);
416
417 /* Initialize global alpha with a sane value */
418 zx_writel_mask(layer + GL_CTRL2, GL_GLOBAL_ALPHA_MASK,
419 0xff << GL_GLOBAL_ALPHA_SHIFT);
420
421 /* Setup CSC for the GL */
422 if (dst_h > 720)
423 zx_writel_mask(csc + CSC_CTRL0, CSC_COV_MODE_MASK,
424 CSC_BT709_IMAGE_RGB2YCBCR << CSC_COV_MODE_SHIFT);
425 else
426 zx_writel_mask(csc + CSC_CTRL0, CSC_COV_MODE_MASK,
427 CSC_BT601_IMAGE_RGB2YCBCR << CSC_COV_MODE_SHIFT);
428 zx_writel_mask(csc + CSC_CTRL0, CSC_WORK_ENABLE, CSC_WORK_ENABLE);
429
430 /* Always use scaler since it exists (set for not bypass) */
431 zx_writel_mask(layer + GL_CTRL3, GL_SCALER_BYPASS_MODE,
432 GL_SCALER_BYPASS_MODE);
433
434 zx_gl_rsz_setup(zplane, src_w, src_h, dst_w, dst_h);
435
436 /* Enable HBSC block */
437 zx_writel_mask(hbsc + HBSC_CTRL0, HBSC_CTRL_EN, HBSC_CTRL_EN);
438
439 zx_vou_layer_enable(plane);
440
441 zx_gl_set_update(zplane);
442}
443
444static const struct drm_plane_helper_funcs zx_gl_plane_helper_funcs = {
445 .atomic_check = zx_gl_plane_atomic_check,
446 .atomic_update = zx_gl_plane_atomic_update,
447 .atomic_disable = zx_plane_atomic_disable,
448};
449
450static const struct drm_plane_funcs zx_plane_funcs = {
451 .update_plane = drm_atomic_helper_update_plane,
452 .disable_plane = drm_atomic_helper_disable_plane,
453 .destroy = drm_plane_cleanup,
454 .reset = drm_atomic_helper_plane_reset,
455 .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
456 .atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
457};
458
459void zx_plane_set_update(struct drm_plane *plane)
460{
461 struct zx_plane *zplane = to_zx_plane(plane);
462
463 /* Do nothing if the plane is not enabled */
464 if (!plane->state->crtc)
465 return;
466
467 switch (plane->type) {
468 case DRM_PLANE_TYPE_PRIMARY:
469 zx_gl_rsz_set_update(zplane);
470 zx_gl_set_update(zplane);
471 break;
472 case DRM_PLANE_TYPE_OVERLAY:
473 zx_vl_rsz_set_update(zplane);
474 zx_vl_set_update(zplane);
475 break;
476 default:
477 WARN_ONCE(1, "unsupported plane type %d\n", plane->type);
478 }
479}
480
481static void zx_plane_hbsc_init(struct zx_plane *zplane)
482{
483 void __iomem *hbsc = zplane->hbsc;
484
485 /*
486 * Initialize HBSC block with a sane configuration per recommedation
487 * from ZTE BSP code.
488 */
489 zx_writel(hbsc + HBSC_SATURATION, 0x200);
490 zx_writel(hbsc + HBSC_HUE, 0x0);
491 zx_writel(hbsc + HBSC_BRIGHT, 0x0);
492 zx_writel(hbsc + HBSC_CONTRAST, 0x200);
493
494 zx_writel(hbsc + HBSC_THRESHOLD_COL1, (0x3ac << 16) | 0x40);
495 zx_writel(hbsc + HBSC_THRESHOLD_COL2, (0x3c0 << 16) | 0x40);
496 zx_writel(hbsc + HBSC_THRESHOLD_COL3, (0x3c0 << 16) | 0x40);
497}
498
499int zx_plane_init(struct drm_device *drm, struct zx_plane *zplane,
500 enum drm_plane_type type)
501{
502 const struct drm_plane_helper_funcs *helper;
503 struct drm_plane *plane = &zplane->plane;
504 struct device *dev = zplane->dev;
505 const uint32_t *formats;
506 unsigned int format_count;
507 int ret;
508
509 zx_plane_hbsc_init(zplane);
510
511 switch (type) {
512 case DRM_PLANE_TYPE_PRIMARY:
513 helper = &zx_gl_plane_helper_funcs;
514 formats = gl_formats;
515 format_count = ARRAY_SIZE(gl_formats);
516 break;
517 case DRM_PLANE_TYPE_OVERLAY:
518 helper = &zx_vl_plane_helper_funcs;
519 formats = vl_formats;
520 format_count = ARRAY_SIZE(vl_formats);
521 break;
522 default:
523 return -ENODEV;
524 }
525
526 ret = drm_universal_plane_init(drm, plane, VOU_CRTC_MASK,
527 &zx_plane_funcs, formats, format_count,
528 NULL, type, NULL);
529 if (ret) {
530 DRM_DEV_ERROR(dev, "failed to init universal plane: %d\n", ret);
531 return ret;
532 }
533
534 drm_plane_helper_add(plane, helper);
535
536 return 0;
537}
drivers/gpu/drm/zte/zx_plane.h+0−26
@@ -1,26 +0,0 @@
1/* SPDX-License-Identifier: GPL-2.0-only */
2/*
3 * Copyright 2016 Linaro Ltd.
4 * Copyright 2016 ZTE Corporation.
5 */
6
7#ifndef __ZX_PLANE_H__
8#define __ZX_PLANE_H__
9
10struct zx_plane {
11 struct drm_plane plane;
12 struct device *dev;
13 void __iomem *layer;
14 void __iomem *csc;
15 void __iomem *hbsc;
16 void __iomem *rsz;
17 const struct vou_layer_bits *bits;
18};
19
20#define to_zx_plane(plane) container_of(plane, struct zx_plane, plane)
21
22int zx_plane_init(struct drm_device *drm, struct zx_plane *zplane,
23 enum drm_plane_type type);
24void zx_plane_set_update(struct drm_plane *plane);
25
26#endif /* __ZX_PLANE_H__ */
drivers/gpu/drm/zte/zx_plane_regs.h+0−120
@@ -1,120 +0,0 @@
1/* SPDX-License-Identifier: GPL-2.0-only */
2/*
3 * Copyright 2016 Linaro Ltd.
4 * Copyright 2016 ZTE Corporation.
5 */
6
7#ifndef __ZX_PLANE_REGS_H__
8#define __ZX_PLANE_REGS_H__
9
10/* GL registers */
11#define GL_CTRL0 0x00
12#define GL_UPDATE BIT(5)
13#define GL_CTRL1 0x04
14#define GL_DATA_FMT_SHIFT 0
15#define GL_DATA_FMT_MASK (0xf << GL_DATA_FMT_SHIFT)
16#define GL_FMT_ARGB8888 0
17#define GL_FMT_RGB888 1
18#define GL_FMT_RGB565 2
19#define GL_FMT_ARGB1555 3
20#define GL_FMT_ARGB4444 4
21#define GL_CTRL2 0x08
22#define GL_GLOBAL_ALPHA_SHIFT 8
23#define GL_GLOBAL_ALPHA_MASK (0xff << GL_GLOBAL_ALPHA_SHIFT)
24#define GL_CTRL3 0x0c
25#define GL_SCALER_BYPASS_MODE BIT(0)
26#define GL_STRIDE 0x18
27#define GL_ADDR 0x1c
28#define GL_SRC_SIZE 0x38
29#define GL_SRC_W_SHIFT 16
30#define GL_SRC_W_MASK (0x3fff << GL_SRC_W_SHIFT)
31#define GL_SRC_H_SHIFT 0
32#define GL_SRC_H_MASK (0x3fff << GL_SRC_H_SHIFT)
33#define GL_POS_START 0x9c
34#define GL_POS_END 0xa0
35#define GL_POS_X_SHIFT 16
36#define GL_POS_X_MASK (0x1fff << GL_POS_X_SHIFT)
37#define GL_POS_Y_SHIFT 0
38#define GL_POS_Y_MASK (0x1fff << GL_POS_Y_SHIFT)
39
40#define GL_SRC_W(x) (((x) << GL_SRC_W_SHIFT) & GL_SRC_W_MASK)
41#define GL_SRC_H(x) (((x) << GL_SRC_H_SHIFT) & GL_SRC_H_MASK)
42#define GL_POS_X(x) (((x) << GL_POS_X_SHIFT) & GL_POS_X_MASK)
43#define GL_POS_Y(x) (((x) << GL_POS_Y_SHIFT) & GL_POS_Y_MASK)
44
45/* VL registers */
46#define VL_CTRL0 0x00
47#define VL_UPDATE BIT(3)
48#define VL_CTRL1 0x04
49#define VL_YUV420_PLANAR BIT(5)
50#define VL_YUV422_SHIFT 3
51#define VL_YUV422_YUYV (0 << VL_YUV422_SHIFT)
52#define VL_YUV422_YVYU (1 << VL_YUV422_SHIFT)
53#define VL_YUV422_UYVY (2 << VL_YUV422_SHIFT)
54#define VL_YUV422_VYUY (3 << VL_YUV422_SHIFT)
55#define VL_FMT_YUV420 0
56#define VL_FMT_YUV422 1
57#define VL_FMT_YUV420_P010 2
58#define VL_FMT_YUV420_HANTRO 3
59#define VL_FMT_YUV444_8BIT 4
60#define VL_FMT_YUV444_10BIT 5
61#define VL_CTRL2 0x08
62#define VL_SCALER_BYPASS_MODE BIT(0)
63#define VL_STRIDE 0x0c
64#define LUMA_STRIDE_SHIFT 16
65#define LUMA_STRIDE_MASK (0xffff << LUMA_STRIDE_SHIFT)
66#define CHROMA_STRIDE_SHIFT 0
67#define CHROMA_STRIDE_MASK (0xffff << CHROMA_STRIDE_SHIFT)
68#define VL_SRC_SIZE 0x10
69#define VL_Y 0x14
70#define VL_POS_START 0x30
71#define VL_POS_END 0x34
72
73#define LUMA_STRIDE(x) (((x) << LUMA_STRIDE_SHIFT) & LUMA_STRIDE_MASK)
74#define CHROMA_STRIDE(x) (((x) << CHROMA_STRIDE_SHIFT) & CHROMA_STRIDE_MASK)
75
76/* RSZ registers */
77#define RSZ_SRC_CFG 0x00
78#define RSZ_DEST_CFG 0x04
79#define RSZ_ENABLE_CFG 0x14
80
81#define RSZ_VL_LUMA_HOR 0x08
82#define RSZ_VL_LUMA_VER 0x0c
83#define RSZ_VL_CHROMA_HOR 0x10
84#define RSZ_VL_CHROMA_VER 0x14
85#define RSZ_VL_CTRL_CFG 0x18
86#define RSZ_VL_FMT_SHIFT 3
87#define RSZ_VL_FMT_MASK (0x3 << RSZ_VL_FMT_SHIFT)
88#define RSZ_VL_FMT_YCBCR420 (0x0 << RSZ_VL_FMT_SHIFT)
89#define RSZ_VL_FMT_YCBCR422 (0x1 << RSZ_VL_FMT_SHIFT)
90#define RSZ_VL_FMT_YCBCR444 (0x2 << RSZ_VL_FMT_SHIFT)
91#define RSZ_VL_ENABLE_CFG 0x1c
92
93#define RSZ_VER_SHIFT 16
94#define RSZ_VER_MASK (0xffff << RSZ_VER_SHIFT)
95#define RSZ_HOR_SHIFT 0
96#define RSZ_HOR_MASK (0xffff << RSZ_HOR_SHIFT)
97
98#define RSZ_VER(x) (((x) << RSZ_VER_SHIFT) & RSZ_VER_MASK)
99#define RSZ_HOR(x) (((x) << RSZ_HOR_SHIFT) & RSZ_HOR_MASK)
100
101#define RSZ_DATA_STEP_SHIFT 16
102#define RSZ_DATA_STEP_MASK (0xffff << RSZ_DATA_STEP_SHIFT)
103#define RSZ_PARA_STEP_SHIFT 0
104#define RSZ_PARA_STEP_MASK (0xffff << RSZ_PARA_STEP_SHIFT)
105
106#define RSZ_DATA_STEP(x) (((x) << RSZ_DATA_STEP_SHIFT) & RSZ_DATA_STEP_MASK)
107#define RSZ_PARA_STEP(x) (((x) << RSZ_PARA_STEP_SHIFT) & RSZ_PARA_STEP_MASK)
108
109/* HBSC registers */
110#define HBSC_SATURATION 0x00
111#define HBSC_HUE 0x04
112#define HBSC_BRIGHT 0x08
113#define HBSC_CONTRAST 0x0c
114#define HBSC_THRESHOLD_COL1 0x10
115#define HBSC_THRESHOLD_COL2 0x14
116#define HBSC_THRESHOLD_COL3 0x18
117#define HBSC_CTRL0 0x28
118#define HBSC_CTRL_EN BIT(2)
119
120#endif /* __ZX_PLANE_REGS_H__ */
drivers/gpu/drm/zte/zx_tvenc.c+0−400
@@ -1,400 +0,0 @@
1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * Copyright 2017 Linaro Ltd.
4 * Copyright 2017 ZTE Corporation.
5 */
6
7#include <linux/clk.h>
8#include <linux/component.h>
9#include <linux/mfd/syscon.h>
10#include <linux/module.h>
11#include <linux/platform_device.h>
12#include <linux/regmap.h>
13
14#include <drm/drm_atomic_helper.h>
15#include <drm/drm_print.h>
16#include <drm/drm_probe_helper.h>
17#include <drm/drm_simple_kms_helper.h>
18
19#include "zx_drm_drv.h"
20#include "zx_tvenc_regs.h"
21#include "zx_vou.h"
22
23struct zx_tvenc_pwrctrl {
24 struct regmap *regmap;
25 u32 reg;
26 u32 mask;
27};
28
29struct zx_tvenc {
30 struct drm_connector connector;
31 struct drm_encoder encoder;
32 struct device *dev;
33 void __iomem *mmio;
34 const struct vou_inf *inf;
35 struct zx_tvenc_pwrctrl pwrctrl;
36};
37
38#define to_zx_tvenc(x) container_of(x, struct zx_tvenc, x)
39
40struct zx_tvenc_mode {
41 struct drm_display_mode mode;
42 u32 video_info;
43 u32 video_res;
44 u32 field1_param;
45 u32 field2_param;
46 u32 burst_line_odd1;
47 u32 burst_line_even1;
48 u32 burst_line_odd2;
49 u32 burst_line_even2;
50 u32 line_timing_param;
51 u32 weight_value;
52 u32 blank_black_level;
53 u32 burst_level;
54 u32 control_param;
55 u32 sub_carrier_phase1;
56 u32 phase_line_incr_cvbs;
57};
58
59/*
60 * The CRM cannot directly provide a suitable frequency, and we have to
61 * ask a multiplied rate from CRM and use the divider in VOU to get the
62 * desired one.
63 */
64#define TVENC_CLOCK_MULTIPLIER 4
65
66static const struct zx_tvenc_mode tvenc_mode_pal = {
67 .mode = {
68 .clock = 13500 * TVENC_CLOCK_MULTIPLIER,
69 .hdisplay = 720,
70 .hsync_start = 720 + 12,
71 .hsync_end = 720 + 12 + 2,
72 .htotal = 720 + 12 + 2 + 130,
73 .vdisplay = 576,
74 .vsync_start = 576 + 2,
75 .vsync_end = 576 + 2 + 2,
76 .vtotal = 576 + 2 + 2 + 20,
77 .flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
78 DRM_MODE_FLAG_INTERLACE,
79 },
80 .video_info = 0x00040040,
81 .video_res = 0x05a9c760,
82 .field1_param = 0x0004d416,
83 .field2_param = 0x0009b94f,
84 .burst_line_odd1 = 0x0004d406,
85 .burst_line_even1 = 0x0009b53e,
86 .burst_line_odd2 = 0x0004d805,
87 .burst_line_even2 = 0x0009b93f,
88 .line_timing_param = 0x06a96fdf,
89 .weight_value = 0x00c188a0,
90 .blank_black_level = 0x0000fcfc,
91 .burst_level = 0x00001595,
92 .control_param = 0x00000001,
93 .sub_carrier_phase1 = 0x1504c566,
94 .phase_line_incr_cvbs = 0xc068db8c,
95};
96
97static const struct zx_tvenc_mode tvenc_mode_ntsc = {
98 .mode = {
99 .clock = 13500 * TVENC_CLOCK_MULTIPLIER,
100 .hdisplay = 720,
101 .hsync_start = 720 + 16,
102 .hsync_end = 720 + 16 + 2,
103 .htotal = 720 + 16 + 2 + 120,
104 .vdisplay = 480,
105 .vsync_start = 480 + 3,
106 .vsync_end = 480 + 3 + 2,
107 .vtotal = 480 + 3 + 2 + 17,
108 .flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
109 DRM_MODE_FLAG_INTERLACE,
110 },
111 .video_info = 0x00040080,
112 .video_res = 0x05a8375a,
113 .field1_param = 0x00041817,
114 .field2_param = 0x0008351e,
115 .burst_line_odd1 = 0x00041006,
116 .burst_line_even1 = 0x0008290d,
117 .burst_line_odd2 = 0x00000000,
118 .burst_line_even2 = 0x00000000,
119 .line_timing_param = 0x06a8ef9e,
120 .weight_value = 0x00b68197,
121 .blank_black_level = 0x0000f0f0,
122 .burst_level = 0x0000009c,
123 .control_param = 0x00000001,
124 .sub_carrier_phase1 = 0x10f83e10,
125 .phase_line_incr_cvbs = 0x80000000,
126};
127
128static const struct zx_tvenc_mode *tvenc_modes[] = {
129 &tvenc_mode_pal,
130 &tvenc_mode_ntsc,
131};
132
133static const struct zx_tvenc_mode *
134zx_tvenc_find_zmode(struct drm_display_mode *mode)
135{
136 int i;
137
138 for (i = 0; i < ARRAY_SIZE(tvenc_modes); i++) {
139 const struct zx_tvenc_mode *zmode = tvenc_modes[i];
140
141 if (drm_mode_equal(mode, &zmode->mode))
142 return zmode;
143 }
144
145 return NULL;
146}
147
148static void zx_tvenc_encoder_mode_set(struct drm_encoder *encoder,
149 struct drm_display_mode *mode,
150 struct drm_display_mode *adj_mode)
151{
152 struct zx_tvenc *tvenc = to_zx_tvenc(encoder);
153 const struct zx_tvenc_mode *zmode;
154 struct vou_div_config configs[] = {
155 { VOU_DIV_INF, VOU_DIV_4 },
156 { VOU_DIV_TVENC, VOU_DIV_1 },
157 { VOU_DIV_LAYER, VOU_DIV_2 },
158 };
159
160 zx_vou_config_dividers(encoder->crtc, configs, ARRAY_SIZE(configs));
161
162 zmode = zx_tvenc_find_zmode(mode);
163 if (!zmode) {
164 DRM_DEV_ERROR(tvenc->dev, "failed to find zmode\n");
165 return;
166 }
167
168 zx_writel(tvenc->mmio + VENC_VIDEO_INFO, zmode->video_info);
169 zx_writel(tvenc->mmio + VENC_VIDEO_RES, zmode->video_res);
170 zx_writel(tvenc->mmio + VENC_FIELD1_PARAM, zmode->field1_param);
171 zx_writel(tvenc->mmio + VENC_FIELD2_PARAM, zmode->field2_param);
172 zx_writel(tvenc->mmio + VENC_LINE_O_1, zmode->burst_line_odd1);
173 zx_writel(tvenc->mmio + VENC_LINE_E_1, zmode->burst_line_even1);
174 zx_writel(tvenc->mmio + VENC_LINE_O_2, zmode->burst_line_odd2);
175 zx_writel(tvenc->mmio + VENC_LINE_E_2, zmode->burst_line_even2);
176 zx_writel(tvenc->mmio + VENC_LINE_TIMING_PARAM,
177 zmode->line_timing_param);
178 zx_writel(tvenc->mmio + VENC_WEIGHT_VALUE, zmode->weight_value);
179 zx_writel(tvenc->mmio + VENC_BLANK_BLACK_LEVEL,
180 zmode->blank_black_level);
181 zx_writel(tvenc->mmio + VENC_BURST_LEVEL, zmode->burst_level);
182 zx_writel(tvenc->mmio + VENC_CONTROL_PARAM, zmode->control_param);
183 zx_writel(tvenc->mmio + VENC_SUB_CARRIER_PHASE1,
184 zmode->sub_carrier_phase1);
185 zx_writel(tvenc->mmio + VENC_PHASE_LINE_INCR_CVBS,
186 zmode->phase_line_incr_cvbs);
187}
188
189static void zx_tvenc_encoder_enable(struct drm_encoder *encoder)
190{
191 struct zx_tvenc *tvenc = to_zx_tvenc(encoder);
192 struct zx_tvenc_pwrctrl *pwrctrl = &tvenc->pwrctrl;
193
194 /* Set bit to power up TVENC DAC */
195 regmap_update_bits(pwrctrl->regmap, pwrctrl->reg, pwrctrl->mask,
196 pwrctrl->mask);
197
198 vou_inf_enable(VOU_TV_ENC, encoder->crtc);
199
200 zx_writel(tvenc->mmio + VENC_ENABLE, 1);
201}
202
203static void zx_tvenc_encoder_disable(struct drm_encoder *encoder)
204{
205 struct zx_tvenc *tvenc = to_zx_tvenc(encoder);
206 struct zx_tvenc_pwrctrl *pwrctrl = &tvenc->pwrctrl;
207
208 zx_writel(tvenc->mmio + VENC_ENABLE, 0);
209
210 vou_inf_disable(VOU_TV_ENC, encoder->crtc);
211
212 /* Clear bit to power down TVENC DAC */
213 regmap_update_bits(pwrctrl->regmap, pwrctrl->reg, pwrctrl->mask, 0);
214}
215
216static const struct drm_encoder_helper_funcs zx_tvenc_encoder_helper_funcs = {
217 .enable = zx_tvenc_encoder_enable,
218 .disable = zx_tvenc_encoder_disable,
219 .mode_set = zx_tvenc_encoder_mode_set,
220};
221
222static int zx_tvenc_connector_get_modes(struct drm_connector *connector)
223{
224 struct zx_tvenc *tvenc = to_zx_tvenc(connector);
225 struct device *dev = tvenc->dev;
226 int i;
227
228 for (i = 0; i < ARRAY_SIZE(tvenc_modes); i++) {
229 const struct zx_tvenc_mode *zmode = tvenc_modes[i];
230 struct drm_display_mode *mode;
231
232 mode = drm_mode_duplicate(connector->dev, &zmode->mode);
233 if (!mode) {
234 DRM_DEV_ERROR(dev, "failed to duplicate drm mode\n");
235 continue;
236 }
237
238 drm_mode_set_name(mode);
239 drm_mode_probed_add(connector, mode);
240 }
241
242 return i;
243}
244
245static enum drm_mode_status
246zx_tvenc_connector_mode_valid(struct drm_connector *connector,
247 struct drm_display_mode *mode)
248{
249 struct zx_tvenc *tvenc = to_zx_tvenc(connector);
250 const struct zx_tvenc_mode *zmode;
251
252 zmode = zx_tvenc_find_zmode(mode);
253 if (!zmode) {
254 DRM_DEV_ERROR(tvenc->dev, "unsupported mode: %s\n", mode->name);
255 return MODE_NOMODE;
256 }
257
258 return MODE_OK;
259}
260
261static struct drm_connector_helper_funcs zx_tvenc_connector_helper_funcs = {
262 .get_modes = zx_tvenc_connector_get_modes,
263 .mode_valid = zx_tvenc_connector_mode_valid,
264};
265
266static const struct drm_connector_funcs zx_tvenc_connector_funcs = {
267 .fill_modes = drm_helper_probe_single_connector_modes,
268 .destroy = drm_connector_cleanup,
269 .reset = drm_atomic_helper_connector_reset,
270 .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
271 .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
272};
273
274static int zx_tvenc_register(struct drm_device *drm, struct zx_tvenc *tvenc)
275{
276 struct drm_encoder *encoder = &tvenc->encoder;
277 struct drm_connector *connector = &tvenc->connector;
278
279 /*
280 * The tvenc is designed to use aux channel, as there is a deflicker
281 * block for the channel.
282 */
283 encoder->possible_crtcs = BIT(1);
284
285 drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_TVDAC);
286 drm_encoder_helper_add(encoder, &zx_tvenc_encoder_helper_funcs);
287
288 connector->interlace_allowed = true;
289
290 drm_connector_init(drm, connector, &zx_tvenc_connector_funcs,
291 DRM_MODE_CONNECTOR_Composite);
292 drm_connector_helper_add(connector, &zx_tvenc_connector_helper_funcs);
293
294 drm_connector_attach_encoder(connector, encoder);
295
296 return 0;
297}
298
299static int zx_tvenc_pwrctrl_init(struct zx_tvenc *tvenc)
300{
301 struct zx_tvenc_pwrctrl *pwrctrl = &tvenc->pwrctrl;
302 struct device *dev = tvenc->dev;
303 struct of_phandle_args out_args;
304 struct regmap *regmap;
305 int ret;
306
307 ret = of_parse_phandle_with_fixed_args(dev->of_node,
308 "zte,tvenc-power-control", 2, 0, &out_args);
309 if (ret)
310 return ret;
311
312 regmap = syscon_node_to_regmap(out_args.np);
313 if (IS_ERR(regmap)) {
314 ret = PTR_ERR(regmap);
315 goto out;
316 }
317
318 pwrctrl->regmap = regmap;
319 pwrctrl->reg = out_args.args[0];
320 pwrctrl->mask = out_args.args[1];
321
322out:
323 of_node_put(out_args.np);
324 return ret;
325}
326
327static int zx_tvenc_bind(struct device *dev, struct device *master, void *data)
328{
329 struct platform_device *pdev = to_platform_device(dev);
330 struct drm_device *drm = data;
331 struct resource *res;
332 struct zx_tvenc *tvenc;
333 int ret;
334
335 tvenc = devm_kzalloc(dev, sizeof(*tvenc), GFP_KERNEL);
336 if (!tvenc)
337 return -ENOMEM;
338
339 tvenc->dev = dev;
340 dev_set_drvdata(dev, tvenc);
341
342 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
343 tvenc->mmio = devm_ioremap_resource(dev, res);
344 if (IS_ERR(tvenc->mmio)) {
345 ret = PTR_ERR(tvenc->mmio);
346 DRM_DEV_ERROR(dev, "failed to remap tvenc region: %d\n", ret);
347 return ret;
348 }
349
350 ret = zx_tvenc_pwrctrl_init(tvenc);
351 if (ret) {
352 DRM_DEV_ERROR(dev, "failed to init power control: %d\n", ret);
353 return ret;
354 }
355
356 ret = zx_tvenc_register(drm, tvenc);
357 if (ret) {
358 DRM_DEV_ERROR(dev, "failed to register tvenc: %d\n", ret);
359 return ret;
360 }
361
362 return 0;
363}
364
365static void zx_tvenc_unbind(struct device *dev, struct device *master,
366 void *data)
367{
368 /* Nothing to do */
369}
370
371static const struct component_ops zx_tvenc_component_ops = {
372 .bind = zx_tvenc_bind,
373 .unbind = zx_tvenc_unbind,
374};
375
376static int zx_tvenc_probe(struct platform_device *pdev)
377{
378 return component_add(&pdev->dev, &zx_tvenc_component_ops);
379}
380
381static int zx_tvenc_remove(struct platform_device *pdev)
382{
383 component_del(&pdev->dev, &zx_tvenc_component_ops);
384 return 0;
385}
386
387static const struct of_device_id zx_tvenc_of_match[] = {
388 { .compatible = "zte,zx296718-tvenc", },
389 { /* end */ },
390};
391MODULE_DEVICE_TABLE(of, zx_tvenc_of_match);
392
393struct platform_driver zx_tvenc_driver = {
394 .probe = zx_tvenc_probe,
395 .remove = zx_tvenc_remove,
396 .driver = {
397 .name = "zx-tvenc",
398 .of_match_table = zx_tvenc_of_match,
399 },
400};
drivers/gpu/drm/zte/zx_tvenc_regs.h+0−27
@@ -1,27 +0,0 @@
1/* SPDX-License-Identifier: GPL-2.0-only */
2/*
3 * Copyright 2017 Linaro Ltd.
4 * Copyright 2017 ZTE Corporation.
5 */
6
7#ifndef __ZX_TVENC_REGS_H__
8#define __ZX_TVENC_REGS_H__
9
10#define VENC_VIDEO_INFO 0x04
11#define VENC_VIDEO_RES 0x08
12#define VENC_FIELD1_PARAM 0x10
13#define VENC_FIELD2_PARAM 0x14
14#define VENC_LINE_O_1 0x18
15#define VENC_LINE_E_1 0x1c
16#define VENC_LINE_O_2 0x20
17#define VENC_LINE_E_2 0x24
18#define VENC_LINE_TIMING_PARAM 0x28
19#define VENC_WEIGHT_VALUE 0x2c
20#define VENC_BLANK_BLACK_LEVEL 0x30
21#define VENC_BURST_LEVEL 0x34
22#define VENC_CONTROL_PARAM 0x3c
23#define VENC_SUB_CARRIER_PHASE1 0x40
24#define VENC_PHASE_LINE_INCR_CVBS 0x48
25#define VENC_ENABLE 0xa8
26
27#endif /* __ZX_TVENC_REGS_H__ */
drivers/gpu/drm/zte/zx_vga.c+0−527
@@ -1,527 +0,0 @@
1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * Copyright (C) 2017 Sanechips Technology Co., Ltd.
4 * Copyright 2017 Linaro Ltd.
5 */
6
7#include <linux/clk.h>
8#include <linux/component.h>
9#include <linux/mfd/syscon.h>
10#include <linux/module.h>
11#include <linux/platform_device.h>
12#include <linux/regmap.h>
13
14#include <drm/drm_atomic_helper.h>
15#include <drm/drm_print.h>
16#include <drm/drm_probe_helper.h>
17#include <drm/drm_simple_kms_helper.h>
18
19#include "zx_drm_drv.h"
20#include "zx_vga_regs.h"
21#include "zx_vou.h"
22
23struct zx_vga_pwrctrl {
24 struct regmap *regmap;
25 u32 reg;
26 u32 mask;
27};
28
29struct zx_vga_i2c {
30 struct i2c_adapter adap;
31 struct mutex lock;
32};
33
34struct zx_vga {
35 struct drm_connector connector;
36 struct drm_encoder encoder;
37 struct zx_vga_i2c *ddc;
38 struct device *dev;
39 void __iomem *mmio;
40 struct clk *i2c_wclk;
41 struct zx_vga_pwrctrl pwrctrl;
42 struct completion complete;
43 bool connected;
44};
45
46#define to_zx_vga(x) container_of(x, struct zx_vga, x)
47
48static void zx_vga_encoder_enable(struct drm_encoder *encoder)
49{
50 struct zx_vga *vga = to_zx_vga(encoder);
51 struct zx_vga_pwrctrl *pwrctrl = &vga->pwrctrl;
52
53 /* Set bit to power up VGA DACs */
54 regmap_update_bits(pwrctrl->regmap, pwrctrl->reg, pwrctrl->mask,
55 pwrctrl->mask);
56
57 vou_inf_enable(VOU_VGA, encoder->crtc);
58}
59
60static void zx_vga_encoder_disable(struct drm_encoder *encoder)
61{
62 struct zx_vga *vga = to_zx_vga(encoder);
63 struct zx_vga_pwrctrl *pwrctrl = &vga->pwrctrl;
64
65 vou_inf_disable(VOU_VGA, encoder->crtc);
66
67 /* Clear bit to power down VGA DACs */
68 regmap_update_bits(pwrctrl->regmap, pwrctrl->reg, pwrctrl->mask, 0);
69}
70
71static const struct drm_encoder_helper_funcs zx_vga_encoder_helper_funcs = {
72 .enable = zx_vga_encoder_enable,
73 .disable = zx_vga_encoder_disable,
74};
75
76static int zx_vga_connector_get_modes(struct drm_connector *connector)
77{
78 struct zx_vga *vga = to_zx_vga(connector);
79 struct edid *edid;
80 int ret;
81
82 /*
83 * Clear both detection bits to switch I2C bus from device
84 * detecting to EDID reading.
85 */
86 zx_writel(vga->mmio + VGA_AUTO_DETECT_SEL, 0);
87
88 edid = drm_get_edid(connector, &vga->ddc->adap);
89 if (!edid) {
90 /*
91 * If EDID reading fails, we set the device state into
92 * disconnected. Locking is not required here, since the
93 * VGA_AUTO_DETECT_SEL register write in irq handler cannot
94 * be triggered when both detection bits are cleared as above.
95 */
96 zx_writel(vga->mmio + VGA_AUTO_DETECT_SEL,
97 VGA_DETECT_SEL_NO_DEVICE);
98 vga->connected = false;
99 return 0;
100 }
101
102 /*
103 * As edid reading succeeds, device must be connected, so we set
104 * up detection bit for unplug interrupt here.
105 */
106 zx_writel(vga->mmio + VGA_AUTO_DETECT_SEL, VGA_DETECT_SEL_HAS_DEVICE);
107
108 drm_connector_update_edid_property(connector, edid);
109 ret = drm_add_edid_modes(connector, edid);
110 kfree(edid);
111
112 return ret;
113}
114
115static enum drm_mode_status
116zx_vga_connector_mode_valid(struct drm_connector *connector,
117 struct drm_display_mode *mode)
118{
119 return MODE_OK;
120}
121
122static struct drm_connector_helper_funcs zx_vga_connector_helper_funcs = {
123 .get_modes = zx_vga_connector_get_modes,
124 .mode_valid = zx_vga_connector_mode_valid,
125};
126
127static enum drm_connector_status
128zx_vga_connector_detect(struct drm_connector *connector, bool force)
129{
130 struct zx_vga *vga = to_zx_vga(connector);
131
132 return vga->connected ? connector_status_connected :
133 connector_status_disconnected;
134}
135
136static const struct drm_connector_funcs zx_vga_connector_funcs = {
137 .fill_modes = drm_helper_probe_single_connector_modes,
138 .detect = zx_vga_connector_detect,
139 .destroy = drm_connector_cleanup,
140 .reset = drm_atomic_helper_connector_reset,
141 .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
142 .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
143};
144
145static int zx_vga_register(struct drm_device *drm, struct zx_vga *vga)
146{
147 struct drm_encoder *encoder = &vga->encoder;
148 struct drm_connector *connector = &vga->connector;
149 struct device *dev = vga->dev;
150 int ret;
151
152 encoder->possible_crtcs = VOU_CRTC_MASK;
153
154 ret = drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_DAC);
155 if (ret) {
156 DRM_DEV_ERROR(dev, "failed to init encoder: %d\n", ret);
157 return ret;
158 }
159
160 drm_encoder_helper_add(encoder, &zx_vga_encoder_helper_funcs);
161
162 vga->connector.polled = DRM_CONNECTOR_POLL_HPD;
163
164 ret = drm_connector_init_with_ddc(drm, connector,
165 &zx_vga_connector_funcs,
166 DRM_MODE_CONNECTOR_VGA,
167 &vga->ddc->adap);
168 if (ret) {
169 DRM_DEV_ERROR(dev, "failed to init connector: %d\n", ret);
170 goto clean_encoder;
171 }
172
173 drm_connector_helper_add(connector, &zx_vga_connector_helper_funcs);
174
175 ret = drm_connector_attach_encoder(connector, encoder);
176 if (ret) {
177 DRM_DEV_ERROR(dev, "failed to attach encoder: %d\n", ret);
178 goto clean_connector;
179 }
180
181 return 0;
182
183clean_connector:
184 drm_connector_cleanup(connector);
185clean_encoder:
186 drm_encoder_cleanup(encoder);
187 return ret;
188}
189
190static int zx_vga_pwrctrl_init(struct zx_vga *vga)
191{
192 struct zx_vga_pwrctrl *pwrctrl = &vga->pwrctrl;
193 struct device *dev = vga->dev;
194 struct of_phandle_args out_args;
195 struct regmap *regmap;
196 int ret;
197
198 ret = of_parse_phandle_with_fixed_args(dev->of_node,
199 "zte,vga-power-control", 2, 0, &out_args);
200 if (ret)
201 return ret;
202
203 regmap = syscon_node_to_regmap(out_args.np);
204 if (IS_ERR(regmap)) {
205 ret = PTR_ERR(regmap);
206 goto out;
207 }
208
209 pwrctrl->regmap = regmap;
210 pwrctrl->reg = out_args.args[0];
211 pwrctrl->mask = out_args.args[1];
212
213out:
214 of_node_put(out_args.np);
215 return ret;
216}
217
218static int zx_vga_i2c_read(struct zx_vga *vga, struct i2c_msg *msg)
219{
220 int len = msg->len;
221 u8 *buf = msg->buf;
222 u32 offset = 0;
223 int i;
224
225 reinit_completion(&vga->complete);
226
227 /* Select combo write */
228 zx_writel_mask(vga->mmio + VGA_CMD_CFG, VGA_CMD_COMBO, VGA_CMD_COMBO);
229 zx_writel_mask(vga->mmio + VGA_CMD_CFG, VGA_CMD_RW, 0);
230
231 while (len > 0) {
232 u32 cnt;
233
234 /* Clear RX FIFO */
235 zx_writel_mask(vga->mmio + VGA_RXF_CTRL, VGA_RX_FIFO_CLEAR,
236 VGA_RX_FIFO_CLEAR);
237
238 /* Data offset to read from */
239 zx_writel(vga->mmio + VGA_SUB_ADDR, offset);
240
241 /* Kick off the transfer */
242 zx_writel_mask(vga->mmio + VGA_CMD_CFG, VGA_CMD_TRANS,
243 VGA_CMD_TRANS);
244
245 if (!wait_for_completion_timeout(&vga->complete,
246 msecs_to_jiffies(1000))) {
247 DRM_DEV_ERROR(vga->dev, "transfer timeout\n");
248 return -ETIMEDOUT;
249 }
250
251 cnt = zx_readl(vga->mmio + VGA_RXF_STATUS);
252 cnt = (cnt & VGA_RXF_COUNT_MASK) >> VGA_RXF_COUNT_SHIFT;
253 /* FIFO status may report more data than we need to read */
254 cnt = min_t(u32, len, cnt);
255
256 for (i = 0; i < cnt; i++)
257 *buf++ = zx_readl(vga->mmio + VGA_DATA);
258
259 len -= cnt;
260 offset += cnt;
261 }
262
263 return 0;
264}
265
266static int zx_vga_i2c_write(struct zx_vga *vga, struct i2c_msg *msg)
267{
268 /*
269 * The DDC I2C adapter is only for reading EDID data, so we assume
270 * that the write to this adapter must be the EDID data offset.
271 */
272 if ((msg->len != 1) || ((msg->addr != DDC_ADDR)))
273 return -EINVAL;
274
275 /* Hardware will take care of the slave address shifting */
276 zx_writel(vga->mmio + VGA_DEVICE_ADDR, msg->addr);
277
278 return 0;
279}
280
281static int zx_vga_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
282 int num)
283{
284 struct zx_vga *vga = i2c_get_adapdata(adap);
285 struct zx_vga_i2c *ddc = vga->ddc;
286 int ret = 0;
287 int i;
288
289 mutex_lock(&ddc->lock);
290
291 for (i = 0; i < num; i++) {
292 if (msgs[i].flags & I2C_M_RD)
293 ret = zx_vga_i2c_read(vga, &msgs[i]);
294 else
295 ret = zx_vga_i2c_write(vga, &msgs[i]);
296
297 if (ret < 0)
298 break;
299 }
300
301 if (!ret)
302 ret = num;
303
304 mutex_unlock(&ddc->lock);
305
306 return ret;
307}
308
309static u32 zx_vga_i2c_func(struct i2c_adapter *adapter)
310{
311 return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
312}
313
314static const struct i2c_algorithm zx_vga_algorithm = {
315 .master_xfer = zx_vga_i2c_xfer,
316 .functionality = zx_vga_i2c_func,
317};
318
319static int zx_vga_ddc_register(struct zx_vga *vga)
320{
321 struct device *dev = vga->dev;
322 struct i2c_adapter *adap;
323 struct zx_vga_i2c *ddc;
324 int ret;
325
326 ddc = devm_kzalloc(dev, sizeof(*ddc), GFP_KERNEL);
327 if (!ddc)
328 return -ENOMEM;
329
330 vga->ddc = ddc;
331 mutex_init(&ddc->lock);
332
333 adap = &ddc->adap;
334 adap->owner = THIS_MODULE;
335 adap->class = I2C_CLASS_DDC;
336 adap->dev.parent = dev;
337 adap->algo = &zx_vga_algorithm;
338 snprintf(adap->name, sizeof(adap->name), "zx vga i2c");
339
340 ret = i2c_add_adapter(adap);
341 if (ret) {
342 DRM_DEV_ERROR(dev, "failed to add I2C adapter: %d\n", ret);
343 return ret;
344 }
345
346 i2c_set_adapdata(adap, vga);
347
348 return 0;
349}
350
351static irqreturn_t zx_vga_irq_thread(int irq, void *dev_id)
352{
353 struct zx_vga *vga = dev_id;
354
355 drm_helper_hpd_irq_event(vga->connector.dev);
356
357 return IRQ_HANDLED;
358}
359
360static irqreturn_t zx_vga_irq_handler(int irq, void *dev_id)
361{
362 struct zx_vga *vga = dev_id;
363 u32 status;
364
365 status = zx_readl(vga->mmio + VGA_I2C_STATUS);
366
367 /* Clear interrupt status */
368 zx_writel_mask(vga->mmio + VGA_I2C_STATUS, VGA_CLEAR_IRQ,
369 VGA_CLEAR_IRQ);
370
371 if (status & VGA_DEVICE_CONNECTED) {
372 /*
373 * Since VGA_DETECT_SEL bits need to be reset for switching DDC
374 * bus from device detection to EDID read, rather than setting
375 * up HAS_DEVICE bit here, we need to do that in .get_modes
376 * hook for unplug detecting after EDID read succeeds.
377 */
378 vga->connected = true;
379 return IRQ_WAKE_THREAD;
380 }
381
382 if (status & VGA_DEVICE_DISCONNECTED) {
383 zx_writel(vga->mmio + VGA_AUTO_DETECT_SEL,
384 VGA_DETECT_SEL_NO_DEVICE);
385 vga->connected = false;
386 return IRQ_WAKE_THREAD;
387 }
388
389 if (status & VGA_TRANS_DONE) {
390 complete(&vga->complete);
391 return IRQ_HANDLED;
392 }
393
394 return IRQ_NONE;
395}
396
397static void zx_vga_hw_init(struct zx_vga *vga)
398{
399 unsigned long ref = clk_get_rate(vga->i2c_wclk);
400 int div;
401
402 /*
403 * Set up I2C fast speed divider per formula below to get 400kHz.
404 * scl = ref / ((div + 1) * 4)
405 */
406 div = DIV_ROUND_UP(ref / 1000, 400 * 4) - 1;
407 zx_writel(vga->mmio + VGA_CLK_DIV_FS, div);
408
409 /* Set up device detection */
410 zx_writel(vga->mmio + VGA_AUTO_DETECT_PARA, 0x80);
411 zx_writel(vga->mmio + VGA_AUTO_DETECT_SEL, VGA_DETECT_SEL_NO_DEVICE);
412
413 /*
414 * We need to poke monitor via DDC bus to get connection irq
415 * start working.
416 */
417 zx_writel(vga->mmio + VGA_DEVICE_ADDR, DDC_ADDR);
418 zx_writel_mask(vga->mmio + VGA_CMD_CFG, VGA_CMD_TRANS, VGA_CMD_TRANS);
419}
420
421static int zx_vga_bind(struct device *dev, struct device *master, void *data)
422{
423 struct platform_device *pdev = to_platform_device(dev);
424 struct drm_device *drm = data;
425 struct resource *res;
426 struct zx_vga *vga;
427 int irq;
428 int ret;
429
430 vga = devm_kzalloc(dev, sizeof(*vga), GFP_KERNEL);
431 if (!vga)
432 return -ENOMEM;
433
434 vga->dev = dev;
435 dev_set_drvdata(dev, vga);
436
437 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
438 vga->mmio = devm_ioremap_resource(dev, res);
439 if (IS_ERR(vga->mmio))
440 return PTR_ERR(vga->mmio);
441
442 irq = platform_get_irq(pdev, 0);
443 if (irq < 0)
444 return irq;
445
446 vga->i2c_wclk = devm_clk_get(dev, "i2c_wclk");
447 if (IS_ERR(vga->i2c_wclk)) {
448 ret = PTR_ERR(vga->i2c_wclk);
449 DRM_DEV_ERROR(dev, "failed to get i2c_wclk: %d\n", ret);
450 return ret;
451 }
452
453 ret = zx_vga_pwrctrl_init(vga);
454 if (ret) {
455 DRM_DEV_ERROR(dev, "failed to init power control: %d\n", ret);
456 return ret;
457 }
458
459 ret = zx_vga_ddc_register(vga);
460 if (ret) {
461 DRM_DEV_ERROR(dev, "failed to register ddc: %d\n", ret);
462 return ret;
463 }
464
465 ret = zx_vga_register(drm, vga);
466 if (ret) {
467 DRM_DEV_ERROR(dev, "failed to register vga: %d\n", ret);
468 return ret;
469 }
470
471 init_completion(&vga->complete);
472
473 ret = devm_request_threaded_irq(dev, irq, zx_vga_irq_handler,
474 zx_vga_irq_thread, IRQF_SHARED,
475 dev_name(dev), vga);
476 if (ret) {
477 DRM_DEV_ERROR(dev, "failed to request threaded irq: %d\n", ret);
478 return ret;
479 }
480
481 ret = clk_prepare_enable(vga->i2c_wclk);
482 if (ret)
483 return ret;
484
485 zx_vga_hw_init(vga);
486
487 return 0;
488}
489
490static void zx_vga_unbind(struct device *dev, struct device *master,
491 void *data)
492{
493 struct zx_vga *vga = dev_get_drvdata(dev);
494
495 clk_disable_unprepare(vga->i2c_wclk);
496}
497
498static const struct component_ops zx_vga_component_ops = {
499 .bind = zx_vga_bind,
500 .unbind = zx_vga_unbind,
501};
502
503static int zx_vga_probe(struct platform_device *pdev)
504{
505 return component_add(&pdev->dev, &zx_vga_component_ops);
506}
507
508static int zx_vga_remove(struct platform_device *pdev)
509{
510 component_del(&pdev->dev, &zx_vga_component_ops);
511 return 0;
512}
513
514static const struct of_device_id zx_vga_of_match[] = {
515 { .compatible = "zte,zx296718-vga", },
516 { /* end */ },
517};
518MODULE_DEVICE_TABLE(of, zx_vga_of_match);
519
520struct platform_driver zx_vga_driver = {
521 .probe = zx_vga_probe,
522 .remove = zx_vga_remove,
523 .driver = {
524 .name = "zx-vga",
525 .of_match_table = zx_vga_of_match,
526 },
527};
drivers/gpu/drm/zte/zx_vga_regs.h+0−33
@@ -1,33 +0,0 @@
1/* SPDX-License-Identifier: GPL-2.0-only */
2/*
3 * Copyright (C) 2017 Sanechips Technology Co., Ltd.
4 * Copyright 2017 Linaro Ltd.
5 */
6
7#ifndef __ZX_VGA_REGS_H__
8#define __ZX_VGA_REGS_H__
9
10#define VGA_CMD_CFG 0x04
11#define VGA_CMD_TRANS BIT(6)
12#define VGA_CMD_COMBO BIT(5)
13#define VGA_CMD_RW BIT(4)
14#define VGA_SUB_ADDR 0x0c
15#define VGA_DEVICE_ADDR 0x10
16#define VGA_CLK_DIV_FS 0x14
17#define VGA_RXF_CTRL 0x20
18#define VGA_RX_FIFO_CLEAR BIT(7)
19#define VGA_DATA 0x24
20#define VGA_I2C_STATUS 0x28
21#define VGA_DEVICE_DISCONNECTED BIT(7)
22#define VGA_DEVICE_CONNECTED BIT(6)
23#define VGA_CLEAR_IRQ BIT(4)
24#define VGA_TRANS_DONE BIT(0)
25#define VGA_RXF_STATUS 0x30
26#define VGA_RXF_COUNT_SHIFT 2
27#define VGA_RXF_COUNT_MASK GENMASK(7, 2)
28#define VGA_AUTO_DETECT_PARA 0x34
29#define VGA_AUTO_DETECT_SEL 0x38
30#define VGA_DETECT_SEL_HAS_DEVICE BIT(1)
31#define VGA_DETECT_SEL_NO_DEVICE BIT(0)
32
33#endif /* __ZX_VGA_REGS_H__ */
drivers/gpu/drm/zte/zx_vou.c+0−921
@@ -1,921 +0,0 @@
1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * Copyright 2016 Linaro Ltd.
4 * Copyright 2016 ZTE Corporation.
5 */
6
7#include <linux/clk.h>
8#include <linux/component.h>
9#include <linux/module.h>
10#include <linux/of_address.h>
11#include <linux/platform_device.h>
12
13#include <video/videomode.h>
14
15#include <drm/drm_atomic_helper.h>
16#include <drm/drm_crtc.h>
17#include <drm/drm_fb_cma_helper.h>
18#include <drm/drm_fb_helper.h>
19#include <drm/drm_gem_cma_helper.h>
20#include <drm/drm_of.h>
21#include <drm/drm_plane_helper.h>
22#include <drm/drm_probe_helper.h>
23#include <drm/drm_vblank.h>
24
25#include "zx_common_regs.h"
26#include "zx_drm_drv.h"
27#include "zx_plane.h"
28#include "zx_vou.h"
29#include "zx_vou_regs.h"
30
31#define GL_NUM 2
32#define VL_NUM 3
33
34enum vou_chn_type {
35 VOU_CHN_MAIN,
36 VOU_CHN_AUX,
37};
38
39struct zx_crtc_regs {
40 u32 fir_active;
41 u32 fir_htiming;
42 u32 fir_vtiming;
43 u32 sec_vtiming;
44 u32 timing_shift;
45 u32 timing_pi_shift;
46};
47
48static const struct zx_crtc_regs main_crtc_regs = {
49 .fir_active = FIR_MAIN_ACTIVE,
50 .fir_htiming = FIR_MAIN_H_TIMING,
51 .fir_vtiming = FIR_MAIN_V_TIMING,
52 .sec_vtiming = SEC_MAIN_V_TIMING,
53 .timing_shift = TIMING_MAIN_SHIFT,
54 .timing_pi_shift = TIMING_MAIN_PI_SHIFT,
55};
56
57static const struct zx_crtc_regs aux_crtc_regs = {
58 .fir_active = FIR_AUX_ACTIVE,
59 .fir_htiming = FIR_AUX_H_TIMING,
60 .fir_vtiming = FIR_AUX_V_TIMING,
61 .sec_vtiming = SEC_AUX_V_TIMING,
62 .timing_shift = TIMING_AUX_SHIFT,
63 .timing_pi_shift = TIMING_AUX_PI_SHIFT,
64};
65
66struct zx_crtc_bits {
67 u32 polarity_mask;
68 u32 polarity_shift;
69 u32 int_frame_mask;
70 u32 tc_enable;
71 u32 sec_vactive_shift;
72 u32 sec_vactive_mask;
73 u32 interlace_select;
74 u32 pi_enable;
75 u32 div_vga_shift;
76 u32 div_pic_shift;
77 u32 div_tvenc_shift;
78 u32 div_hdmi_pnx_shift;
79 u32 div_hdmi_shift;
80 u32 div_inf_shift;
81 u32 div_layer_shift;
82};
83
84static const struct zx_crtc_bits main_crtc_bits = {
85 .polarity_mask = MAIN_POL_MASK,
86 .polarity_shift = MAIN_POL_SHIFT,
87 .int_frame_mask = TIMING_INT_MAIN_FRAME,
88 .tc_enable = MAIN_TC_EN,
89 .sec_vactive_shift = SEC_VACT_MAIN_SHIFT,
90 .sec_vactive_mask = SEC_VACT_MAIN_MASK,
91 .interlace_select = MAIN_INTERLACE_SEL,
92 .pi_enable = MAIN_PI_EN,
93 .div_vga_shift = VGA_MAIN_DIV_SHIFT,
94 .div_pic_shift = PIC_MAIN_DIV_SHIFT,
95 .div_tvenc_shift = TVENC_MAIN_DIV_SHIFT,
96 .div_hdmi_pnx_shift = HDMI_MAIN_PNX_DIV_SHIFT,
97 .div_hdmi_shift = HDMI_MAIN_DIV_SHIFT,
98 .div_inf_shift = INF_MAIN_DIV_SHIFT,
99 .div_layer_shift = LAYER_MAIN_DIV_SHIFT,
100};
101
102static const struct zx_crtc_bits aux_crtc_bits = {
103 .polarity_mask = AUX_POL_MASK,
104 .polarity_shift = AUX_POL_SHIFT,
105 .int_frame_mask = TIMING_INT_AUX_FRAME,
106 .tc_enable = AUX_TC_EN,
107 .sec_vactive_shift = SEC_VACT_AUX_SHIFT,
108 .sec_vactive_mask = SEC_VACT_AUX_MASK,
109 .interlace_select = AUX_INTERLACE_SEL,
110 .pi_enable = AUX_PI_EN,
111 .div_vga_shift = VGA_AUX_DIV_SHIFT,
112 .div_pic_shift = PIC_AUX_DIV_SHIFT,
113 .div_tvenc_shift = TVENC_AUX_DIV_SHIFT,
114 .div_hdmi_pnx_shift = HDMI_AUX_PNX_DIV_SHIFT,
115 .div_hdmi_shift = HDMI_AUX_DIV_SHIFT,
116 .div_inf_shift = INF_AUX_DIV_SHIFT,
117 .div_layer_shift = LAYER_AUX_DIV_SHIFT,
118};
119
120struct zx_crtc {
121 struct drm_crtc crtc;
122 struct drm_plane *primary;
123 struct zx_vou_hw *vou;
124 void __iomem *chnreg;
125 void __iomem *chncsc;
126 void __iomem *dither;
127 const struct zx_crtc_regs *regs;
128 const struct zx_crtc_bits *bits;
129 enum vou_chn_type chn_type;
130 struct clk *pixclk;
131};
132
133#define to_zx_crtc(x) container_of(x, struct zx_crtc, crtc)
134
135struct vou_layer_bits {
136 u32 enable;
137 u32 chnsel;
138 u32 clksel;
139};
140
141static const struct vou_layer_bits zx_gl_bits[GL_NUM] = {
142 {
143 .enable = OSD_CTRL0_GL0_EN,
144 .chnsel = OSD_CTRL0_GL0_SEL,
145 .clksel = VOU_CLK_GL0_SEL,
146 }, {
147 .enable = OSD_CTRL0_GL1_EN,
148 .chnsel = OSD_CTRL0_GL1_SEL,
149 .clksel = VOU_CLK_GL1_SEL,
150 },
151};
152
153static const struct vou_layer_bits zx_vl_bits[VL_NUM] = {
154 {
155 .enable = OSD_CTRL0_VL0_EN,
156 .chnsel = OSD_CTRL0_VL0_SEL,
157 .clksel = VOU_CLK_VL0_SEL,
158 }, {
159 .enable = OSD_CTRL0_VL1_EN,
160 .chnsel = OSD_CTRL0_VL1_SEL,
161 .clksel = VOU_CLK_VL1_SEL,
162 }, {
163 .enable = OSD_CTRL0_VL2_EN,
164 .chnsel = OSD_CTRL0_VL2_SEL,
165 .clksel = VOU_CLK_VL2_SEL,
166 },
167};
168
169struct zx_vou_hw {
170 struct device *dev;
171 void __iomem *osd;
172 void __iomem *timing;
173 void __iomem *vouctl;
174 void __iomem *otfppu;
175 void __iomem *dtrc;
176 struct clk *axi_clk;
177 struct clk *ppu_clk;
178 struct clk *main_clk;
179 struct clk *aux_clk;
180 struct zx_crtc *main_crtc;
181 struct zx_crtc *aux_crtc;
182};
183
184enum vou_inf_data_sel {
185 VOU_YUV444 = 0,
186 VOU_RGB_101010 = 1,
187 VOU_RGB_888 = 2,
188 VOU_RGB_666 = 3,
189};
190
191struct vou_inf {
192 enum vou_inf_id id;
193 enum vou_inf_data_sel data_sel;
194 u32 clocks_en_bits;
195 u32 clocks_sel_bits;
196};
197
198static struct vou_inf vou_infs[] = {
199 [VOU_HDMI] = {
200 .data_sel = VOU_YUV444,
201 .clocks_en_bits = BIT(24) | BIT(18) | BIT(6),
202 .clocks_sel_bits = BIT(13) | BIT(2),
203 },
204 [VOU_TV_ENC] = {
205 .data_sel = VOU_YUV444,
206 .clocks_en_bits = BIT(15),
207 .clocks_sel_bits = BIT(11) | BIT(0),
208 },
209 [VOU_VGA] = {
210 .data_sel = VOU_RGB_888,
211 .clocks_en_bits = BIT(1),
212 .clocks_sel_bits = BIT(10),
213 },
214};
215
216static inline struct zx_vou_hw *crtc_to_vou(struct drm_crtc *crtc)
217{
218 struct zx_crtc *zcrtc = to_zx_crtc(crtc);
219
220 return zcrtc->vou;
221}
222
223void vou_inf_hdmi_audio_sel(struct drm_crtc *crtc,
224 enum vou_inf_hdmi_audio aud)
225{
226 struct zx_crtc *zcrtc = to_zx_crtc(crtc);
227 struct zx_vou_hw *vou = zcrtc->vou;
228
229 zx_writel_mask(vou->vouctl + VOU_INF_HDMI_CTRL, VOU_HDMI_AUD_MASK, aud);
230}
231
232void vou_inf_enable(enum vou_inf_id id, struct drm_crtc *crtc)
233{
234 struct zx_crtc *zcrtc = to_zx_crtc(crtc);
235 struct zx_vou_hw *vou = zcrtc->vou;
236 struct vou_inf *inf = &vou_infs[id];
237 void __iomem *dither = zcrtc->dither;
238 void __iomem *csc = zcrtc->chncsc;
239 bool is_main = zcrtc->chn_type == VOU_CHN_MAIN;
240 u32 data_sel_shift = id << 1;
241
242 if (inf->data_sel != VOU_YUV444) {
243 /* Enable channel CSC for RGB output */
244 zx_writel_mask(csc + CSC_CTRL0, CSC_COV_MODE_MASK,
245 CSC_BT709_IMAGE_YCBCR2RGB << CSC_COV_MODE_SHIFT);
246 zx_writel_mask(csc + CSC_CTRL0, CSC_WORK_ENABLE,
247 CSC_WORK_ENABLE);
248
249 /* Bypass Dither block for RGB output */
250 zx_writel_mask(dither + OSD_DITHER_CTRL0, DITHER_BYSPASS,
251 DITHER_BYSPASS);
252 } else {
253 zx_writel_mask(csc + CSC_CTRL0, CSC_WORK_ENABLE, 0);
254 zx_writel_mask(dither + OSD_DITHER_CTRL0, DITHER_BYSPASS, 0);
255 }
256
257 /* Select data format */
258 zx_writel_mask(vou->vouctl + VOU_INF_DATA_SEL, 0x3 << data_sel_shift,
259 inf->data_sel << data_sel_shift);
260
261 /* Select channel */
262 zx_writel_mask(vou->vouctl + VOU_INF_CH_SEL, 0x1 << id,
263 zcrtc->chn_type << id);
264
265 /* Select interface clocks */
266 zx_writel_mask(vou->vouctl + VOU_CLK_SEL, inf->clocks_sel_bits,
267 is_main ? 0 : inf->clocks_sel_bits);
268
269 /* Enable interface clocks */
270 zx_writel_mask(vou->vouctl + VOU_CLK_EN, inf->clocks_en_bits,
271 inf->clocks_en_bits);
272
273 /* Enable the device */
274 zx_writel_mask(vou->vouctl + VOU_INF_EN, 1 << id, 1 << id);
275}
276
277void vou_inf_disable(enum vou_inf_id id, struct drm_crtc *crtc)
278{
279 struct zx_vou_hw *vou = crtc_to_vou(crtc);
280 struct vou_inf *inf = &vou_infs[id];
281
282 /* Disable the device */
283 zx_writel_mask(vou->vouctl + VOU_INF_EN, 1 << id, 0);
284
285 /* Disable interface clocks */
286 zx_writel_mask(vou->vouctl + VOU_CLK_EN, inf->clocks_en_bits, 0);
287}
288
289void zx_vou_config_dividers(struct drm_crtc *crtc,
290 struct vou_div_config *configs, int num)
291{
292 struct zx_crtc *zcrtc = to_zx_crtc(crtc);
293 struct zx_vou_hw *vou = zcrtc->vou;
294 const struct zx_crtc_bits *bits = zcrtc->bits;
295 int i;
296
297 /* Clear update flag bit */
298 zx_writel_mask(vou->vouctl + VOU_DIV_PARA, DIV_PARA_UPDATE, 0);
299
300 for (i = 0; i < num; i++) {
301 struct vou_div_config *cfg = configs + i;
302 u32 reg, shift;
303
304 switch (cfg->id) {
305 case VOU_DIV_VGA:
306 reg = VOU_CLK_SEL;
307 shift = bits->div_vga_shift;
308 break;
309 case VOU_DIV_PIC:
310 reg = VOU_CLK_SEL;
311 shift = bits->div_pic_shift;
312 break;
313 case VOU_DIV_TVENC:
314 reg = VOU_DIV_PARA;
315 shift = bits->div_tvenc_shift;
316 break;
317 case VOU_DIV_HDMI_PNX:
318 reg = VOU_DIV_PARA;
319 shift = bits->div_hdmi_pnx_shift;
320 break;
321 case VOU_DIV_HDMI:
322 reg = VOU_DIV_PARA;
323 shift = bits->div_hdmi_shift;
324 break;
325 case VOU_DIV_INF:
326 reg = VOU_DIV_PARA;
327 shift = bits->div_inf_shift;
328 break;
329 case VOU_DIV_LAYER:
330 reg = VOU_DIV_PARA;
331 shift = bits->div_layer_shift;
332 break;
333 default:
334 continue;
335 }
336
337 /* Each divider occupies 3 bits */
338 zx_writel_mask(vou->vouctl + reg, 0x7 << shift,
339 cfg->val << shift);
340 }
341
342 /* Set update flag bit to get dividers effected */
343 zx_writel_mask(vou->vouctl + VOU_DIV_PARA, DIV_PARA_UPDATE,
344 DIV_PARA_UPDATE);
345}
346
347static inline void vou_chn_set_update(struct zx_crtc *zcrtc)
348{
349 zx_writel(zcrtc->chnreg + CHN_UPDATE, 1);
350}
351
352static void zx_crtc_atomic_enable(struct drm_crtc *crtc,
353 struct drm_atomic_state *state)
354{
355 struct drm_display_mode *mode = &crtc->state->adjusted_mode;
356 bool interlaced = mode->flags & DRM_MODE_FLAG_INTERLACE;
357 struct zx_crtc *zcrtc = to_zx_crtc(crtc);
358 struct zx_vou_hw *vou = zcrtc->vou;
359 const struct zx_crtc_regs *regs = zcrtc->regs;
360 const struct zx_crtc_bits *bits = zcrtc->bits;
361 struct videomode vm;
362 u32 scan_mask;
363 u32 pol = 0;
364 u32 val;
365 int ret;
366
367 drm_display_mode_to_videomode(mode, &vm);
368
369 /* Set up timing parameters */
370 val = V_ACTIVE((interlaced ? vm.vactive / 2 : vm.vactive) - 1);
371 val |= H_ACTIVE(vm.hactive - 1);
372 zx_writel(vou->timing + regs->fir_active, val);
373
374 val = SYNC_WIDE(vm.hsync_len - 1);
375 val |= BACK_PORCH(vm.hback_porch - 1);
376 val |= FRONT_PORCH(vm.hfront_porch - 1);
377 zx_writel(vou->timing + regs->fir_htiming, val);
378
379 val = SYNC_WIDE(vm.vsync_len - 1);
380 val |= BACK_PORCH(vm.vback_porch - 1);
381 val |= FRONT_PORCH(vm.vfront_porch - 1);
382 zx_writel(vou->timing + regs->fir_vtiming, val);
383
384 if (interlaced) {
385 u32 shift = bits->sec_vactive_shift;
386 u32 mask = bits->sec_vactive_mask;
387
388 val = zx_readl(vou->timing + SEC_V_ACTIVE);
389 val &= ~mask;
390 val |= ((vm.vactive / 2 - 1) << shift) & mask;
391 zx_writel(vou->timing + SEC_V_ACTIVE, val);
392
393 val = SYNC_WIDE(vm.vsync_len - 1);
394 /*
395 * The vback_porch for the second field needs to shift one on
396 * the value for the first field.
397 */
398 val |= BACK_PORCH(vm.vback_porch);
399 val |= FRONT_PORCH(vm.vfront_porch - 1);
400 zx_writel(vou->timing + regs->sec_vtiming, val);
401 }
402
403 /* Set up polarities */
404 if (vm.flags & DISPLAY_FLAGS_VSYNC_LOW)
405 pol |= 1 << POL_VSYNC_SHIFT;
406 if (vm.flags & DISPLAY_FLAGS_HSYNC_LOW)
407 pol |= 1 << POL_HSYNC_SHIFT;
408
409 zx_writel_mask(vou->timing + TIMING_CTRL, bits->polarity_mask,
410 pol << bits->polarity_shift);
411
412 /* Setup SHIFT register by following what ZTE BSP does */
413 val = H_SHIFT_VAL;
414 if (interlaced)
415 val |= V_SHIFT_VAL << 16;
416 zx_writel(vou->timing + regs->timing_shift, val);
417 zx_writel(vou->timing + regs->timing_pi_shift, H_PI_SHIFT_VAL);
418
419 /* Progressive or interlace scan select */
420 scan_mask = bits->interlace_select | bits->pi_enable;
421 zx_writel_mask(vou->timing + SCAN_CTRL, scan_mask,
422 interlaced ? scan_mask : 0);
423
424 /* Enable TIMING_CTRL */
425 zx_writel_mask(vou->timing + TIMING_TC_ENABLE, bits->tc_enable,
426 bits->tc_enable);
427
428 /* Configure channel screen size */
429 zx_writel_mask(zcrtc->chnreg + CHN_CTRL1, CHN_SCREEN_W_MASK,
430 vm.hactive << CHN_SCREEN_W_SHIFT);
431 zx_writel_mask(zcrtc->chnreg + CHN_CTRL1, CHN_SCREEN_H_MASK,
432 vm.vactive << CHN_SCREEN_H_SHIFT);
433
434 /* Configure channel interlace buffer control */
435 zx_writel_mask(zcrtc->chnreg + CHN_INTERLACE_BUF_CTRL, CHN_INTERLACE_EN,
436 interlaced ? CHN_INTERLACE_EN : 0);
437
438 /* Update channel */
439 vou_chn_set_update(zcrtc);
440
441 /* Enable channel */
442 zx_writel_mask(zcrtc->chnreg + CHN_CTRL0, CHN_ENABLE, CHN_ENABLE);
443
444 drm_crtc_vblank_on(crtc);
445
446 ret = clk_set_rate(zcrtc->pixclk, mode->clock * 1000);
447 if (ret) {
448 DRM_DEV_ERROR(vou->dev, "failed to set pixclk rate: %d\n", ret);
449 return;
450 }
451
452 ret = clk_prepare_enable(zcrtc->pixclk);
453 if (ret)
454 DRM_DEV_ERROR(vou->dev, "failed to enable pixclk: %d\n", ret);
455}
456
457static void zx_crtc_atomic_disable(struct drm_crtc *crtc,
458 struct drm_atomic_state *state)
459{
460 struct zx_crtc *zcrtc = to_zx_crtc(crtc);
461 const struct zx_crtc_bits *bits = zcrtc->bits;
462 struct zx_vou_hw *vou = zcrtc->vou;
463
464 clk_disable_unprepare(zcrtc->pixclk);
465
466 drm_crtc_vblank_off(crtc);
467
468 /* Disable channel */
469 zx_writel_mask(zcrtc->chnreg + CHN_CTRL0, CHN_ENABLE, 0);
470
471 /* Disable TIMING_CTRL */
472 zx_writel_mask(vou->timing + TIMING_TC_ENABLE, bits->tc_enable, 0);
473}
474
475static void zx_crtc_atomic_flush(struct drm_crtc *crtc,
476 struct drm_atomic_state *state)
477{
478 struct drm_pending_vblank_event *event = crtc->state->event;
479
480 if (!event)
481 return;
482
483 crtc->state->event = NULL;
484
485 spin_lock_irq(&crtc->dev->event_lock);
486 if (drm_crtc_vblank_get(crtc) == 0)
487 drm_crtc_arm_vblank_event(crtc, event);
488 else
489 drm_crtc_send_vblank_event(crtc, event);
490 spin_unlock_irq(&crtc->dev->event_lock);
491}
492
493static const struct drm_crtc_helper_funcs zx_crtc_helper_funcs = {
494 .atomic_flush = zx_crtc_atomic_flush,
495 .atomic_enable = zx_crtc_atomic_enable,
496 .atomic_disable = zx_crtc_atomic_disable,
497};
498
499static int zx_vou_enable_vblank(struct drm_crtc *crtc)
500{
501 struct zx_crtc *zcrtc = to_zx_crtc(crtc);
502 struct zx_vou_hw *vou = crtc_to_vou(crtc);
503 u32 int_frame_mask = zcrtc->bits->int_frame_mask;
504
505 zx_writel_mask(vou->timing + TIMING_INT_CTRL, int_frame_mask,
506 int_frame_mask);
507
508 return 0;
509}
510
511static void zx_vou_disable_vblank(struct drm_crtc *crtc)
512{
513 struct zx_crtc *zcrtc = to_zx_crtc(crtc);
514 struct zx_vou_hw *vou = crtc_to_vou(crtc);
515
516 zx_writel_mask(vou->timing + TIMING_INT_CTRL,
517 zcrtc->bits->int_frame_mask, 0);
518}
519
520static const struct drm_crtc_funcs zx_crtc_funcs = {
521 .destroy = drm_crtc_cleanup,
522 .set_config = drm_atomic_helper_set_config,
523 .page_flip = drm_atomic_helper_page_flip,
524 .reset = drm_atomic_helper_crtc_reset,
525 .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
526 .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
527 .enable_vblank = zx_vou_enable_vblank,
528 .disable_vblank = zx_vou_disable_vblank,
529};
530
531static int zx_crtc_init(struct drm_device *drm, struct zx_vou_hw *vou,
532 enum vou_chn_type chn_type)
533{
534 struct device *dev = vou->dev;
535 struct zx_plane *zplane;
536 struct zx_crtc *zcrtc;
537 int ret;
538
539 zcrtc = devm_kzalloc(dev, sizeof(*zcrtc), GFP_KERNEL);
540 if (!zcrtc)
541 return -ENOMEM;
542
543 zcrtc->vou = vou;
544 zcrtc->chn_type = chn_type;
545
546 zplane = devm_kzalloc(dev, sizeof(*zplane), GFP_KERNEL);
547 if (!zplane)
548 return -ENOMEM;
549
550 zplane->dev = dev;
551
552 if (chn_type == VOU_CHN_MAIN) {
553 zplane->layer = vou->osd + MAIN_GL_OFFSET;
554 zplane->csc = vou->osd + MAIN_GL_CSC_OFFSET;
555 zplane->hbsc = vou->osd + MAIN_HBSC_OFFSET;
556 zplane->rsz = vou->otfppu + MAIN_RSZ_OFFSET;
557 zplane->bits = &zx_gl_bits[0];
558 zcrtc->chnreg = vou->osd + OSD_MAIN_CHN;
559 zcrtc->chncsc = vou->osd + MAIN_CHN_CSC_OFFSET;
560 zcrtc->dither = vou->osd + MAIN_DITHER_OFFSET;
561 zcrtc->regs = &main_crtc_regs;
562 zcrtc->bits = &main_crtc_bits;
563 } else {
564 zplane->layer = vou->osd + AUX_GL_OFFSET;
565 zplane->csc = vou->osd + AUX_GL_CSC_OFFSET;
566 zplane->hbsc = vou->osd + AUX_HBSC_OFFSET;
567 zplane->rsz = vou->otfppu + AUX_RSZ_OFFSET;
568 zplane->bits = &zx_gl_bits[1];
569 zcrtc->chnreg = vou->osd + OSD_AUX_CHN;
570 zcrtc->chncsc = vou->osd + AUX_CHN_CSC_OFFSET;
571 zcrtc->dither = vou->osd + AUX_DITHER_OFFSET;
572 zcrtc->regs = &aux_crtc_regs;
573 zcrtc->bits = &aux_crtc_bits;
574 }
575
576 zcrtc->pixclk = devm_clk_get(dev, (chn_type == VOU_CHN_MAIN) ?
577 "main_wclk" : "aux_wclk");
578 if (IS_ERR(zcrtc->pixclk)) {
579 ret = PTR_ERR(zcrtc->pixclk);
580 DRM_DEV_ERROR(dev, "failed to get pix clk: %d\n", ret);
581 return ret;
582 }
583
584 ret = zx_plane_init(drm, zplane, DRM_PLANE_TYPE_PRIMARY);
585 if (ret) {
586 DRM_DEV_ERROR(dev, "failed to init primary plane: %d\n", ret);
587 return ret;
588 }
589
590 zcrtc->primary = &zplane->plane;
591
592 ret = drm_crtc_init_with_planes(drm, &zcrtc->crtc, zcrtc->primary, NULL,
593 &zx_crtc_funcs, NULL);
594 if (ret) {
595 DRM_DEV_ERROR(dev, "failed to init drm crtc: %d\n", ret);
596 return ret;
597 }
598
599 drm_crtc_helper_add(&zcrtc->crtc, &zx_crtc_helper_funcs);
600
601 if (chn_type == VOU_CHN_MAIN)
602 vou->main_crtc = zcrtc;
603 else
604 vou->aux_crtc = zcrtc;
605
606 return 0;
607}
608
609void zx_vou_layer_enable(struct drm_plane *plane)
610{
611 struct zx_crtc *zcrtc = to_zx_crtc(plane->state->crtc);
612 struct zx_vou_hw *vou = zcrtc->vou;
613 struct zx_plane *zplane = to_zx_plane(plane);
614 const struct vou_layer_bits *bits = zplane->bits;
615
616 if (zcrtc->chn_type == VOU_CHN_MAIN) {
617 zx_writel_mask(vou->osd + OSD_CTRL0, bits->chnsel, 0);
618 zx_writel_mask(vou->vouctl + VOU_CLK_SEL, bits->clksel, 0);
619 } else {
620 zx_writel_mask(vou->osd + OSD_CTRL0, bits->chnsel,
621 bits->chnsel);
622 zx_writel_mask(vou->vouctl + VOU_CLK_SEL, bits->clksel,
623 bits->clksel);
624 }
625
626 zx_writel_mask(vou->osd + OSD_CTRL0, bits->enable, bits->enable);
627}
628
629void zx_vou_layer_disable(struct drm_plane *plane,
630 struct drm_plane_state *old_state)
631{
632 struct zx_crtc *zcrtc = to_zx_crtc(old_state->crtc);
633 struct zx_vou_hw *vou = zcrtc->vou;
634 struct zx_plane *zplane = to_zx_plane(plane);
635 const struct vou_layer_bits *bits = zplane->bits;
636
637 zx_writel_mask(vou->osd + OSD_CTRL0, bits->enable, 0);
638}
639
640static void zx_overlay_init(struct drm_device *drm, struct zx_vou_hw *vou)
641{
642 struct device *dev = vou->dev;
643 struct zx_plane *zplane;
644 int i;
645 int ret;
646
647 /*
648 * VL0 has some quirks on scaling support which need special handling.
649 * Let's leave it out for now.
650 */
651 for (i = 1; i < VL_NUM; i++) {
652 zplane = devm_kzalloc(dev, sizeof(*zplane), GFP_KERNEL);
653 if (!zplane) {
654 DRM_DEV_ERROR(dev, "failed to allocate zplane %d\n", i);
655 return;
656 }
657
658 zplane->layer = vou->osd + OSD_VL_OFFSET(i);
659 zplane->hbsc = vou->osd + HBSC_VL_OFFSET(i);
660 zplane->rsz = vou->otfppu + RSZ_VL_OFFSET(i);
661 zplane->bits = &zx_vl_bits[i];
662
663 ret = zx_plane_init(drm, zplane, DRM_PLANE_TYPE_OVERLAY);
664 if (ret) {
665 DRM_DEV_ERROR(dev, "failed to init overlay %d\n", i);
666 continue;
667 }
668 }
669}
670
671static inline void zx_osd_int_update(struct zx_crtc *zcrtc)
672{
673 struct drm_crtc *crtc = &zcrtc->crtc;
674 struct drm_plane *plane;
675
676 vou_chn_set_update(zcrtc);
677
678 drm_for_each_plane_mask(plane, crtc->dev, crtc->state->plane_mask)
679 zx_plane_set_update(plane);
680}
681
682static irqreturn_t vou_irq_handler(int irq, void *dev_id)
683{
684 struct zx_vou_hw *vou = dev_id;
685 u32 state;
686
687 /* Handle TIMING_CTRL frame interrupts */
688 state = zx_readl(vou->timing + TIMING_INT_STATE);
689 zx_writel(vou->timing + TIMING_INT_STATE, state);
690
691 if (state & TIMING_INT_MAIN_FRAME)
692 drm_crtc_handle_vblank(&vou->main_crtc->crtc);
693
694 if (state & TIMING_INT_AUX_FRAME)
695 drm_crtc_handle_vblank(&vou->aux_crtc->crtc);
696
697 /* Handle OSD interrupts */
698 state = zx_readl(vou->osd + OSD_INT_STA);
699 zx_writel(vou->osd + OSD_INT_CLRSTA, state);
700
701 if (state & OSD_INT_MAIN_UPT)
702 zx_osd_int_update(vou->main_crtc);
703
704 if (state & OSD_INT_AUX_UPT)
705 zx_osd_int_update(vou->aux_crtc);
706
707 if (state & OSD_INT_ERROR)
708 DRM_DEV_ERROR(vou->dev, "OSD ERROR: 0x%08x!\n", state);
709
710 return IRQ_HANDLED;
711}
712
713static void vou_dtrc_init(struct zx_vou_hw *vou)
714{
715 /* Clear bit for bypass by ID */
716 zx_writel_mask(vou->dtrc + DTRC_DETILE_CTRL,
717 TILE2RASTESCAN_BYPASS_MODE, 0);
718
719 /* Select ARIDR mode */
720 zx_writel_mask(vou->dtrc + DTRC_DETILE_CTRL, DETILE_ARIDR_MODE_MASK,
721 DETILE_ARID_IN_ARIDR);
722
723 /* Bypass decompression for both frames */
724 zx_writel_mask(vou->dtrc + DTRC_F0_CTRL, DTRC_DECOMPRESS_BYPASS,
725 DTRC_DECOMPRESS_BYPASS);
726 zx_writel_mask(vou->dtrc + DTRC_F1_CTRL, DTRC_DECOMPRESS_BYPASS,
727 DTRC_DECOMPRESS_BYPASS);
728
729 /* Set up ARID register */
730 zx_writel(vou->dtrc + DTRC_ARID, DTRC_ARID3(0xf) | DTRC_ARID2(0xe) |
731 DTRC_ARID1(0xf) | DTRC_ARID0(0xe));
732}
733
734static void vou_hw_init(struct zx_vou_hw *vou)
735{
736 /* Release reset for all VOU modules */
737 zx_writel(vou->vouctl + VOU_SOFT_RST, ~0);
738
739 /* Enable all VOU module clocks */
740 zx_writel(vou->vouctl + VOU_CLK_EN, ~0);
741
742 /* Clear both OSD and TIMING_CTRL interrupt state */
743 zx_writel(vou->osd + OSD_INT_CLRSTA, ~0);
744 zx_writel(vou->timing + TIMING_INT_STATE, ~0);
745
746 /* Enable OSD and TIMING_CTRL interrrupts */
747 zx_writel(vou->osd + OSD_INT_MSK, OSD_INT_ENABLE);
748 zx_writel(vou->timing + TIMING_INT_CTRL, TIMING_INT_ENABLE);
749
750 /* Select GPC as input to gl/vl scaler as a sane default setting */
751 zx_writel(vou->otfppu + OTFPPU_RSZ_DATA_SOURCE, 0x2a);
752
753 /*
754 * Needs to reset channel and layer logic per frame when frame starts
755 * to get VOU work properly.
756 */
757 zx_writel_mask(vou->osd + OSD_RST_CLR, RST_PER_FRAME, RST_PER_FRAME);
758
759 vou_dtrc_init(vou);
760}
761
762static int zx_crtc_bind(struct device *dev, struct device *master, void *data)
763{
764 struct platform_device *pdev = to_platform_device(dev);
765 struct drm_device *drm = data;
766 struct zx_vou_hw *vou;
767 struct resource *res;
768 int irq;
769 int ret;
770
771 vou = devm_kzalloc(dev, sizeof(*vou), GFP_KERNEL);
772 if (!vou)
773 return -ENOMEM;
774
775 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "osd");
776 vou->osd = devm_ioremap_resource(dev, res);
777 if (IS_ERR(vou->osd)) {
778 ret = PTR_ERR(vou->osd);
779 DRM_DEV_ERROR(dev, "failed to remap osd region: %d\n", ret);
780 return ret;
781 }
782
783 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "timing_ctrl");
784 vou->timing = devm_ioremap_resource(dev, res);
785 if (IS_ERR(vou->timing)) {
786 ret = PTR_ERR(vou->timing);
787 DRM_DEV_ERROR(dev, "failed to remap timing_ctrl region: %d\n",
788 ret);
789 return ret;
790 }
791
792 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dtrc");
793 vou->dtrc = devm_ioremap_resource(dev, res);
794 if (IS_ERR(vou->dtrc)) {
795 ret = PTR_ERR(vou->dtrc);
796 DRM_DEV_ERROR(dev, "failed to remap dtrc region: %d\n", ret);
797 return ret;
798 }
799
800 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "vou_ctrl");
801 vou->vouctl = devm_ioremap_resource(dev, res);
802 if (IS_ERR(vou->vouctl)) {
803 ret = PTR_ERR(vou->vouctl);
804 DRM_DEV_ERROR(dev, "failed to remap vou_ctrl region: %d\n",
805 ret);
806 return ret;
807 }
808
809 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "otfppu");
810 vou->otfppu = devm_ioremap_resource(dev, res);
811 if (IS_ERR(vou->otfppu)) {
812 ret = PTR_ERR(vou->otfppu);
813 DRM_DEV_ERROR(dev, "failed to remap otfppu region: %d\n", ret);
814 return ret;
815 }
816
817 irq = platform_get_irq(pdev, 0);
818 if (irq < 0)
819 return irq;
820
821 vou->axi_clk = devm_clk_get(dev, "aclk");
822 if (IS_ERR(vou->axi_clk)) {
823 ret = PTR_ERR(vou->axi_clk);
824 DRM_DEV_ERROR(dev, "failed to get axi_clk: %d\n", ret);
825 return ret;
826 }
827
828 vou->ppu_clk = devm_clk_get(dev, "ppu_wclk");
829 if (IS_ERR(vou->ppu_clk)) {
830 ret = PTR_ERR(vou->ppu_clk);
831 DRM_DEV_ERROR(dev, "failed to get ppu_clk: %d\n", ret);
832 return ret;
833 }
834
835 ret = clk_prepare_enable(vou->axi_clk);
836 if (ret) {
837 DRM_DEV_ERROR(dev, "failed to enable axi_clk: %d\n", ret);
838 return ret;
839 }
840
841 clk_prepare_enable(vou->ppu_clk);
842 if (ret) {
843 DRM_DEV_ERROR(dev, "failed to enable ppu_clk: %d\n", ret);
844 goto disable_axi_clk;
845 }
846
847 vou->dev = dev;
848 dev_set_drvdata(dev, vou);
849
850 vou_hw_init(vou);
851
852 ret = devm_request_irq(dev, irq, vou_irq_handler, 0, "zx_vou", vou);
853 if (ret < 0) {
854 DRM_DEV_ERROR(dev, "failed to request vou irq: %d\n", ret);
855 goto disable_ppu_clk;
856 }
857
858 ret = zx_crtc_init(drm, vou, VOU_CHN_MAIN);
859 if (ret) {
860 DRM_DEV_ERROR(dev, "failed to init main channel crtc: %d\n",
861 ret);
862 goto disable_ppu_clk;
863 }
864
865 ret = zx_crtc_init(drm, vou, VOU_CHN_AUX);
866 if (ret) {
867 DRM_DEV_ERROR(dev, "failed to init aux channel crtc: %d\n",
868 ret);
869 goto disable_ppu_clk;
870 }
871
872 zx_overlay_init(drm, vou);
873
874 return 0;
875
876disable_ppu_clk:
877 clk_disable_unprepare(vou->ppu_clk);
878disable_axi_clk:
879 clk_disable_unprepare(vou->axi_clk);
880 return ret;
881}
882
883static void zx_crtc_unbind(struct device *dev, struct device *master,
884 void *data)
885{
886 struct zx_vou_hw *vou = dev_get_drvdata(dev);
887
888 clk_disable_unprepare(vou->axi_clk);
889 clk_disable_unprepare(vou->ppu_clk);
890}
891
892static const struct component_ops zx_crtc_component_ops = {
893 .bind = zx_crtc_bind,
894 .unbind = zx_crtc_unbind,
895};
896
897static int zx_crtc_probe(struct platform_device *pdev)
898{
899 return component_add(&pdev->dev, &zx_crtc_component_ops);
900}
901
902static int zx_crtc_remove(struct platform_device *pdev)
903{
904 component_del(&pdev->dev, &zx_crtc_component_ops);
905 return 0;
906}
907
908static const struct of_device_id zx_crtc_of_match[] = {
909 { .compatible = "zte,zx296718-dpc", },
910 { /* end */ },
911};
912MODULE_DEVICE_TABLE(of, zx_crtc_of_match);
913
914struct platform_driver zx_crtc_driver = {
915 .probe = zx_crtc_probe,
916 .remove = zx_crtc_remove,
917 .driver = {
918 .name = "zx-crtc",
919 .of_match_table = zx_crtc_of_match,
920 },
921};
drivers/gpu/drm/zte/zx_vou.h+0−64
@@ -1,64 +0,0 @@
1/* SPDX-License-Identifier: GPL-2.0-only */
2/*
3 * Copyright 2016 Linaro Ltd.
4 * Copyright 2016 ZTE Corporation.
5 */
6
7#ifndef __ZX_VOU_H__
8#define __ZX_VOU_H__
9
10#define VOU_CRTC_MASK 0x3
11
12/* VOU output interfaces */
13enum vou_inf_id {
14 VOU_HDMI = 0,
15 VOU_RGB_LCD = 1,
16 VOU_TV_ENC = 2,
17 VOU_MIPI_DSI = 3,
18 VOU_LVDS = 4,
19 VOU_VGA = 5,
20};
21
22enum vou_inf_hdmi_audio {
23 VOU_HDMI_AUD_SPDIF = BIT(0),
24 VOU_HDMI_AUD_I2S = BIT(1),
25 VOU_HDMI_AUD_DSD = BIT(2),
26 VOU_HDMI_AUD_HBR = BIT(3),
27 VOU_HDMI_AUD_PARALLEL = BIT(4),
28};
29
30void vou_inf_hdmi_audio_sel(struct drm_crtc *crtc,
31 enum vou_inf_hdmi_audio aud);
32void vou_inf_enable(enum vou_inf_id id, struct drm_crtc *crtc);
33void vou_inf_disable(enum vou_inf_id id, struct drm_crtc *crtc);
34
35enum vou_div_id {
36 VOU_DIV_VGA,
37 VOU_DIV_PIC,
38 VOU_DIV_TVENC,
39 VOU_DIV_HDMI_PNX,
40 VOU_DIV_HDMI,
41 VOU_DIV_INF,
42 VOU_DIV_LAYER,
43};
44
45enum vou_div_val {
46 VOU_DIV_1 = 0,
47 VOU_DIV_2 = 1,
48 VOU_DIV_4 = 3,
49 VOU_DIV_8 = 7,
50};
51
52struct vou_div_config {
53 enum vou_div_id id;
54 enum vou_div_val val;
55};
56
57void zx_vou_config_dividers(struct drm_crtc *crtc,
58 struct vou_div_config *configs, int num);
59
60void zx_vou_layer_enable(struct drm_plane *plane);
61void zx_vou_layer_disable(struct drm_plane *plane,
62 struct drm_plane_state *old_state);
63
64#endif /* __ZX_VOU_H__ */
drivers/gpu/drm/zte/zx_vou_regs.h+0−212
@@ -1,212 +0,0 @@
1/* SPDX-License-Identifier: GPL-2.0-only */
2/*
3 * Copyright 2016 Linaro Ltd.
4 * Copyright 2016 ZTE Corporation.
5 */
6
7#ifndef __ZX_VOU_REGS_H__
8#define __ZX_VOU_REGS_H__
9
10/* Sub-module offset */
11#define MAIN_GL_OFFSET 0x130
12#define MAIN_GL_CSC_OFFSET 0x580
13#define MAIN_CHN_CSC_OFFSET 0x6c0
14#define MAIN_HBSC_OFFSET 0x820
15#define MAIN_DITHER_OFFSET 0x960
16#define MAIN_RSZ_OFFSET 0x600 /* OTFPPU sub-module */
17
18#define AUX_GL_OFFSET 0x200
19#define AUX_GL_CSC_OFFSET 0x5d0
20#define AUX_CHN_CSC_OFFSET 0x710
21#define AUX_HBSC_OFFSET 0x860
22#define AUX_DITHER_OFFSET 0x970
23#define AUX_RSZ_OFFSET 0x800
24
25#define OSD_VL0_OFFSET 0x040
26#define OSD_VL_OFFSET(i) (OSD_VL0_OFFSET + 0x050 * (i))
27
28#define HBSC_VL0_OFFSET 0x760
29#define HBSC_VL_OFFSET(i) (HBSC_VL0_OFFSET + 0x040 * (i))
30
31#define RSZ_VL1_U0 0xa00
32#define RSZ_VL_OFFSET(i) (RSZ_VL1_U0 + 0x200 * (i))
33
34/* OSD (GPC_GLOBAL) registers */
35#define OSD_INT_STA 0x04
36#define OSD_INT_CLRSTA 0x08
37#define OSD_INT_MSK 0x0c
38#define OSD_INT_AUX_UPT BIT(14)
39#define OSD_INT_MAIN_UPT BIT(13)
40#define OSD_INT_GL1_LBW BIT(10)
41#define OSD_INT_GL0_LBW BIT(9)
42#define OSD_INT_VL2_LBW BIT(8)
43#define OSD_INT_VL1_LBW BIT(7)
44#define OSD_INT_VL0_LBW BIT(6)
45#define OSD_INT_BUS_ERR BIT(3)
46#define OSD_INT_CFG_ERR BIT(2)
47#define OSD_INT_ERROR (\
48 OSD_INT_GL1_LBW | OSD_INT_GL0_LBW | \
49 OSD_INT_VL2_LBW | OSD_INT_VL1_LBW | OSD_INT_VL0_LBW | \
50 OSD_INT_BUS_ERR | OSD_INT_CFG_ERR \
51)
52#define OSD_INT_ENABLE (OSD_INT_ERROR | OSD_INT_AUX_UPT | OSD_INT_MAIN_UPT)
53#define OSD_CTRL0 0x10
54#define OSD_CTRL0_VL0_EN BIT(13)
55#define OSD_CTRL0_VL0_SEL BIT(12)
56#define OSD_CTRL0_VL1_EN BIT(11)
57#define OSD_CTRL0_VL1_SEL BIT(10)
58#define OSD_CTRL0_VL2_EN BIT(9)
59#define OSD_CTRL0_VL2_SEL BIT(8)
60#define OSD_CTRL0_GL0_EN BIT(7)
61#define OSD_CTRL0_GL0_SEL BIT(6)
62#define OSD_CTRL0_GL1_EN BIT(5)
63#define OSD_CTRL0_GL1_SEL BIT(4)
64#define OSD_RST_CLR 0x1c
65#define RST_PER_FRAME BIT(19)
66
67/* Main/Aux channel registers */
68#define OSD_MAIN_CHN 0x470
69#define OSD_AUX_CHN 0x4d0
70#define CHN_CTRL0 0x00
71#define CHN_ENABLE BIT(0)
72#define CHN_CTRL1 0x04
73#define CHN_SCREEN_W_SHIFT 18
74#define CHN_SCREEN_W_MASK (0x1fff << CHN_SCREEN_W_SHIFT)
75#define CHN_SCREEN_H_SHIFT 5
76#define CHN_SCREEN_H_MASK (0x1fff << CHN_SCREEN_H_SHIFT)
77#define CHN_UPDATE 0x08
78#define CHN_INTERLACE_BUF_CTRL 0x24
79#define CHN_INTERLACE_EN BIT(2)
80
81/* Dither registers */
82#define OSD_DITHER_CTRL0 0x00
83#define DITHER_BYSPASS BIT(31)
84
85/* TIMING_CTRL registers */
86#define TIMING_TC_ENABLE 0x04
87#define AUX_TC_EN BIT(1)
88#define MAIN_TC_EN BIT(0)
89#define FIR_MAIN_ACTIVE 0x08
90#define FIR_AUX_ACTIVE 0x0c
91#define V_ACTIVE_SHIFT 16
92#define V_ACTIVE_MASK (0xffff << V_ACTIVE_SHIFT)
93#define H_ACTIVE_SHIFT 0
94#define H_ACTIVE_MASK (0xffff << H_ACTIVE_SHIFT)
95#define FIR_MAIN_H_TIMING 0x10
96#define FIR_MAIN_V_TIMING 0x14
97#define FIR_AUX_H_TIMING 0x18
98#define FIR_AUX_V_TIMING 0x1c
99#define SYNC_WIDE_SHIFT 22
100#define SYNC_WIDE_MASK (0x3ff << SYNC_WIDE_SHIFT)
101#define BACK_PORCH_SHIFT 11
102#define BACK_PORCH_MASK (0x7ff << BACK_PORCH_SHIFT)
103#define FRONT_PORCH_SHIFT 0
104#define FRONT_PORCH_MASK (0x7ff << FRONT_PORCH_SHIFT)
105#define TIMING_CTRL 0x20
106#define AUX_POL_SHIFT 3
107#define AUX_POL_MASK (0x7 << AUX_POL_SHIFT)
108#define MAIN_POL_SHIFT 0
109#define MAIN_POL_MASK (0x7 << MAIN_POL_SHIFT)
110#define POL_DE_SHIFT 2
111#define POL_VSYNC_SHIFT 1
112#define POL_HSYNC_SHIFT 0
113#define TIMING_INT_CTRL 0x24
114#define TIMING_INT_STATE 0x28
115#define TIMING_INT_AUX_FRAME BIT(3)
116#define TIMING_INT_MAIN_FRAME BIT(1)
117#define TIMING_INT_AUX_FRAME_SEL_VSW (0x2 << 10)
118#define TIMING_INT_MAIN_FRAME_SEL_VSW (0x2 << 6)
119#define TIMING_INT_ENABLE (\
120 TIMING_INT_MAIN_FRAME_SEL_VSW | TIMING_INT_AUX_FRAME_SEL_VSW | \
121 TIMING_INT_MAIN_FRAME | TIMING_INT_AUX_FRAME \
122)
123#define TIMING_MAIN_SHIFT 0x2c
124#define TIMING_AUX_SHIFT 0x30
125#define H_SHIFT_VAL 0x0048
126#define V_SHIFT_VAL 0x0001
127#define SCAN_CTRL 0x34
128#define AUX_PI_EN BIT(19)
129#define MAIN_PI_EN BIT(18)
130#define AUX_INTERLACE_SEL BIT(1)
131#define MAIN_INTERLACE_SEL BIT(0)
132#define SEC_V_ACTIVE 0x38
133#define SEC_VACT_MAIN_SHIFT 0
134#define SEC_VACT_MAIN_MASK (0xffff << SEC_VACT_MAIN_SHIFT)
135#define SEC_VACT_AUX_SHIFT 16
136#define SEC_VACT_AUX_MASK (0xffff << SEC_VACT_AUX_SHIFT)
137#define SEC_MAIN_V_TIMING 0x3c
138#define SEC_AUX_V_TIMING 0x40
139#define TIMING_MAIN_PI_SHIFT 0x68
140#define TIMING_AUX_PI_SHIFT 0x6c
141#define H_PI_SHIFT_VAL 0x000f
142
143#define V_ACTIVE(x) (((x) << V_ACTIVE_SHIFT) & V_ACTIVE_MASK)
144#define H_ACTIVE(x) (((x) << H_ACTIVE_SHIFT) & H_ACTIVE_MASK)
145
146#define SYNC_WIDE(x) (((x) << SYNC_WIDE_SHIFT) & SYNC_WIDE_MASK)
147#define BACK_PORCH(x) (((x) << BACK_PORCH_SHIFT) & BACK_PORCH_MASK)
148#define FRONT_PORCH(x) (((x) << FRONT_PORCH_SHIFT) & FRONT_PORCH_MASK)
149
150/* DTRC registers */
151#define DTRC_F0_CTRL 0x2c
152#define DTRC_F1_CTRL 0x5c
153#define DTRC_DECOMPRESS_BYPASS BIT(17)
154#define DTRC_DETILE_CTRL 0x68
155#define TILE2RASTESCAN_BYPASS_MODE BIT(30)
156#define DETILE_ARIDR_MODE_MASK (0x3 << 0)
157#define DETILE_ARID_ALL 0
158#define DETILE_ARID_IN_ARIDR 1
159#define DETILE_ARID_BYP_BUT_ARIDR 2
160#define DETILE_ARID_IN_ARIDR2 3
161#define DTRC_ARID 0x6c
162#define DTRC_ARID3_SHIFT 24
163#define DTRC_ARID3_MASK (0xff << DTRC_ARID3_SHIFT)
164#define DTRC_ARID2_SHIFT 16
165#define DTRC_ARID2_MASK (0xff << DTRC_ARID2_SHIFT)
166#define DTRC_ARID1_SHIFT 8
167#define DTRC_ARID1_MASK (0xff << DTRC_ARID1_SHIFT)
168#define DTRC_ARID0_SHIFT 0
169#define DTRC_ARID0_MASK (0xff << DTRC_ARID0_SHIFT)
170#define DTRC_DEC2DDR_ARID 0x70
171
172#define DTRC_ARID3(x) (((x) << DTRC_ARID3_SHIFT) & DTRC_ARID3_MASK)
173#define DTRC_ARID2(x) (((x) << DTRC_ARID2_SHIFT) & DTRC_ARID2_MASK)
174#define DTRC_ARID1(x) (((x) << DTRC_ARID1_SHIFT) & DTRC_ARID1_MASK)
175#define DTRC_ARID0(x) (((x) << DTRC_ARID0_SHIFT) & DTRC_ARID0_MASK)
176
177/* VOU_CTRL registers */
178#define VOU_INF_EN 0x00
179#define VOU_INF_CH_SEL 0x04
180#define VOU_INF_DATA_SEL 0x08
181#define VOU_SOFT_RST 0x14
182#define VOU_CLK_SEL 0x18
183#define VGA_AUX_DIV_SHIFT 29
184#define VGA_MAIN_DIV_SHIFT 26
185#define PIC_MAIN_DIV_SHIFT 23
186#define PIC_AUX_DIV_SHIFT 20
187#define VOU_CLK_VL2_SEL BIT(8)
188#define VOU_CLK_VL1_SEL BIT(7)
189#define VOU_CLK_VL0_SEL BIT(6)
190#define VOU_CLK_GL1_SEL BIT(5)
191#define VOU_CLK_GL0_SEL BIT(4)
192#define VOU_DIV_PARA 0x1c
193#define DIV_PARA_UPDATE BIT(31)
194#define TVENC_AUX_DIV_SHIFT 28
195#define HDMI_AUX_PNX_DIV_SHIFT 25
196#define HDMI_MAIN_PNX_DIV_SHIFT 22
197#define HDMI_AUX_DIV_SHIFT 19
198#define HDMI_MAIN_DIV_SHIFT 16
199#define TVENC_MAIN_DIV_SHIFT 13
200#define INF_AUX_DIV_SHIFT 9
201#define INF_MAIN_DIV_SHIFT 6
202#define LAYER_AUX_DIV_SHIFT 3
203#define LAYER_MAIN_DIV_SHIFT 0
204#define VOU_CLK_REQEN 0x20
205#define VOU_CLK_EN 0x24
206#define VOU_INF_HDMI_CTRL 0x30
207#define VOU_HDMI_AUD_MASK 0x1f
208
209/* OTFPPU_CTRL registers */
210#define OTFPPU_RSZ_DATA_SOURCE 0x04
211
212#endif /* __ZX_VOU_REGS_H__ */
drivers/usb/typec/altmodes/Kconfig+1−0
@@ -4,6 +4,7 @@ menu "USB Type-C Alternate Mode drivers" · 3 unmodified lines
4 4
5config TYPEC_DP_ALTMODE5config TYPEC_DP_ALTMODE
6 tristate "DisplayPort Alternate Mode driver"6 tristate "DisplayPort Alternate Mode driver"
7 depends on DRM
7 help8 help
8 DisplayPort USB Type-C Alternate Mode allows DisplayPort9 DisplayPort USB Type-C Alternate Mode allows DisplayPort
9 displays and adapters to be attached to the USB Type-C10 displays and adapters to be attached to the USB Type-C
drivers/usb/typec/altmodes/displayport.c+36−22
@@ -11,8 +11,10 @@ · 10 unmodified lines
11#include <linux/delay.h>11#include <linux/delay.h>
12#include <linux/mutex.h>12#include <linux/mutex.h>
13#include <linux/module.h>13#include <linux/module.h>
14#include <linux/property.h>
14#include <linux/usb/pd_vdo.h>15#include <linux/usb/pd_vdo.h>
15#include <linux/usb/typec_dp.h>16#include <linux/usb/typec_dp.h>
17#include <drm/drm_connector.h>
16#include "displayport.h"18#include "displayport.h"
17 19
18#define DP_HEADER(_dp, ver, cmd) (VDO((_dp)->alt->svid, 1, ver, cmd) \20#define DP_HEADER(_dp, ver, cmd) (VDO((_dp)->alt->svid, 1, ver, cmd) \
@@ -57,19 +59,28 @@ struct dp_altmode { · 38 unmodified lines
57 struct typec_displayport_data data;59 struct typec_displayport_data data;
58 60
59 enum dp_state state;61 enum dp_state state;
62 bool hpd;
60 63
61 struct mutex lock; /* device lock */64 struct mutex lock; /* device lock */
62 struct work_struct work;65 struct work_struct work;
63 struct typec_altmode *alt;66 struct typec_altmode *alt;
64 const struct typec_altmode *port;67 const struct typec_altmode *port;
68 struct fwnode_handle *connector_fwnode;
65};69};
66 70
67static int dp_altmode_notify(struct dp_altmode *dp)71static int dp_altmode_notify(struct dp_altmode *dp)
68{72{
69 u8 state = get_count_order(DP_CONF_GET_PIN_ASSIGN(dp->data.conf));73 unsigned long conf;
74 u8 state;
75
76 if (dp->data.conf) {
77 state = get_count_order(DP_CONF_GET_PIN_ASSIGN(dp->data.conf));
78 conf = TYPEC_MODAL_STATE(state);
79 } else {
80 conf = TYPEC_STATE_USB;
81 }
70 82
71 return typec_altmode_notify(dp->alt, TYPEC_MODAL_STATE(state),83 return typec_altmode_notify(dp->alt, conf, &dp->data);
72 &dp->data);
73}84}
74 85
75static int dp_altmode_configure(struct dp_altmode *dp, u8 con)86static int dp_altmode_configure(struct dp_altmode *dp, u8 con)
@@ -118,6 +129,7 @@ static int dp_altmode_configure(struct dp_altmode *dp, u8 con) · 42 unmodified lines
118static int dp_altmode_status_update(struct dp_altmode *dp)129static int dp_altmode_status_update(struct dp_altmode *dp)
119{130{
120 bool configured = !!DP_CONF_GET_PIN_ASSIGN(dp->data.conf);131 bool configured = !!DP_CONF_GET_PIN_ASSIGN(dp->data.conf);
132 bool hpd = !!(dp->data.status & DP_STATUS_HPD_STATE);
121 u8 con = DP_STATUS_CONNECTION(dp->data.status);133 u8 con = DP_STATUS_CONNECTION(dp->data.status);
122 int ret = 0;134 int ret = 0;
123 135
@@ -130,6 +142,11 @@ static int dp_altmode_status_update(struct dp_altmode *dp) · 6 unmodified lines
130 ret = dp_altmode_configure(dp, con);142 ret = dp_altmode_configure(dp, con);
131 if (!ret)143 if (!ret)
132 dp->state = DP_STATE_CONFIGURE;144 dp->state = DP_STATE_CONFIGURE;
145 } else {
146 if (dp->hpd != hpd) {
147 drm_connector_oob_hotplug_event(dp->connector_fwnode);
148 dp->hpd = hpd;
149 }
133 }150 }
134 151
135 return ret;152 return ret;
@@ -137,21 +154,10 @@ static int dp_altmode_status_update(struct dp_altmode *dp) · 1 unmodified line
137 154
138static int dp_altmode_configured(struct dp_altmode *dp)155static int dp_altmode_configured(struct dp_altmode *dp)
139{156{
140 int ret;
141
142 sysfs_notify(&dp->alt->dev.kobj, "displayport", "configuration");157 sysfs_notify(&dp->alt->dev.kobj, "displayport", "configuration");
143
144 if (!dp->data.conf)
145 return typec_altmode_notify(dp->alt, TYPEC_STATE_USB,
146 &dp->data);
147
148 ret = dp_altmode_notify(dp);
149 if (ret)
150 return ret;
151
152 sysfs_notify(&dp->alt->dev.kobj, "displayport", "pin_assignment");158 sysfs_notify(&dp->alt->dev.kobj, "displayport", "pin_assignment");
153 159
154 return 0;160 return dp_altmode_notify(dp);
155}161}
156 162
157static int dp_altmode_configure_vdm(struct dp_altmode *dp, u32 conf)163static int dp_altmode_configure_vdm(struct dp_altmode *dp, u32 conf)
@@ -172,13 +178,8 @@ static int dp_altmode_configure_vdm(struct dp_altmode *dp, u32 conf) · 14 unmodified lines
172 }178 }
173 179
174 ret = typec_altmode_vdm(dp->alt, header, &conf, 2);180 ret = typec_altmode_vdm(dp->alt, header, &conf, 2);
175 if (ret) {181 if (ret)
176 if (DP_CONF_GET_PIN_ASSIGN(dp->data.conf))182 dp_altmode_notify(dp);
177 dp_altmode_notify(dp);
178 else
179 typec_altmode_notify(dp->alt, TYPEC_STATE_USB,
180 &dp->data);
181 }
182 183
183 return ret;184 return ret;
184}185}
@@ -521,6 +522,7 @@ static const struct attribute_group dp_altmode_group = { · 336 unmodified lines
521int dp_altmode_probe(struct typec_altmode *alt)522int dp_altmode_probe(struct typec_altmode *alt)
522{523{
523 const struct typec_altmode *port = typec_altmode_get_partner(alt);524 const struct typec_altmode *port = typec_altmode_get_partner(alt);
525 struct fwnode_handle *fwnode;
524 struct dp_altmode *dp;526 struct dp_altmode *dp;
525 int ret;527 int ret;
526 528
@@ -549,6 +551,11 @@ int dp_altmode_probe(struct typec_altmode *alt) · 22 unmodified lines
549 alt->desc = "DisplayPort";551 alt->desc = "DisplayPort";
550 alt->ops = &dp_altmode_ops;552 alt->ops = &dp_altmode_ops;
551 553
554 fwnode = dev_fwnode(alt->dev.parent->parent); /* typec_port fwnode */
555 dp->connector_fwnode = fwnode_find_reference(fwnode, "displayport", 0);
556 if (IS_ERR(dp->connector_fwnode))
557 dp->connector_fwnode = NULL;
558
552 typec_altmode_set_drvdata(alt, dp);559 typec_altmode_set_drvdata(alt, dp);
553 560
554 dp->state = DP_STATE_ENTER;561 dp->state = DP_STATE_ENTER;
@@ -564,6 +571,13 @@ void dp_altmode_remove(struct typec_altmode *alt) · 9 unmodified lines
564 571
565 sysfs_remove_group(&alt->dev.kobj, &dp_altmode_group);572 sysfs_remove_group(&alt->dev.kobj, &dp_altmode_group);
566 cancel_work_sync(&dp->work);573 cancel_work_sync(&dp->work);
574
575 if (dp->connector_fwnode) {
576 if (dp->hpd)
577 drm_connector_oob_hotplug_event(dp->connector_fwnode);
578
579 fwnode_handle_put(dp->connector_fwnode);
580 }
567}581}
568EXPORT_SYMBOL_GPL(dp_altmode_remove);582EXPORT_SYMBOL_GPL(dp_altmode_remove);
569 583
include/drm/drm_bridge.h+2−0
@@ -911,6 +911,8 @@ struct drm_bridge *devm_drm_panel_bridge_add(struct device *dev, · 910 unmodified lines
911struct drm_bridge *devm_drm_panel_bridge_add_typed(struct device *dev,911struct drm_bridge *devm_drm_panel_bridge_add_typed(struct device *dev,
912 struct drm_panel *panel,912 struct drm_panel *panel,
913 u32 connector_type);913 u32 connector_type);
914struct drm_bridge *devm_drm_of_get_bridge(struct device *dev, struct device_node *node,
915 u32 port, u32 endpoint);
914struct drm_connector *drm_panel_bridge_connector(struct drm_bridge *bridge);916struct drm_connector *drm_panel_bridge_connector(struct drm_bridge *bridge);
915#endif917#endif
916 918
include/drm/drm_connector.h+25−0
@@ -1084,6 +1084,14 @@ struct drm_connector_funcs { · 1083 unmodified lines
1084 */1084 */
1085 void (*atomic_print_state)(struct drm_printer *p,1085 void (*atomic_print_state)(struct drm_printer *p,
1086 const struct drm_connector_state *state);1086 const struct drm_connector_state *state);
1087
1088 /**
1089 * @oob_hotplug_event:
1090 *
1091 * This will get called when a hotplug-event for a drm-connector
1092 * has been received from a source outside the display driver / device.
1093 */
1094 void (*oob_hotplug_event)(struct drm_connector *connector);
1087};1095};
1088 1096
1089/**1097/**
@@ -1228,6 +1236,14 @@ struct drm_connector { · 138 unmodified lines
1228 struct device *kdev;1236 struct device *kdev;
1229 /** @attr: sysfs attributes */1237 /** @attr: sysfs attributes */
1230 struct device_attribute *attr;1238 struct device_attribute *attr;
1239 /**
1240 * @fwnode: associated fwnode supplied by platform firmware
1241 *
1242 * Drivers can set this to associate a fwnode with a connector, drivers
1243 * are expected to get a reference on the fwnode when setting this.
1244 * drm_connector_cleanup() will call fwnode_handle_put() on this.
1245 */
1246 struct fwnode_handle *fwnode;
1231 1247
1232 /**1248 /**
1233 * @head:1249 * @head:
@@ -1239,6 +1255,14 @@ struct drm_connector { · 5 unmodified lines
1239 */1255 */
1240 struct list_head head;1256 struct list_head head;
1241 1257
1258 /**
1259 * @global_connector_list_entry:
1260 *
1261 * Connector entry in the global connector-list, used by
1262 * drm_connector_find_by_fwnode().
1263 */
1264 struct list_head global_connector_list_entry;
1265
1242 /** @base: base KMS object */1266 /** @base: base KMS object */
1243 struct drm_mode_object base;1267 struct drm_mode_object base;
1244 1268
@@ -1650,6 +1674,7 @@ drm_connector_is_unregistered(struct drm_connector *connector) · 405 unmodified lines
1650 DRM_CONNECTOR_UNREGISTERED;1674 DRM_CONNECTOR_UNREGISTERED;
1651}1675}
1652 1676
1677void drm_connector_oob_hotplug_event(struct fwnode_handle *connector_fwnode);
1653const char *drm_get_connector_type_name(unsigned int connector_type);1678const char *drm_get_connector_type_name(unsigned int connector_type);
1654const char *drm_get_connector_status_name(enum drm_connector_status status);1679const char *drm_get_connector_status_name(enum drm_connector_status status);
1655const char *drm_get_subpixel_order_name(enum subpixel_order order);1680const char *drm_get_subpixel_order_name(enum subpixel_order order);
include/drm/drm_ioctl.h+0−1
@@ -167,7 +167,6 @@ struct drm_ioctl_desc { · 166 unmodified lines
167 .name = #ioctl \167 .name = #ioctl \
168 }168 }
169 169
170int drm_ioctl_permit(u32 flags, struct drm_file *file_priv);
171long drm_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);170long drm_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
172long drm_ioctl_kernel(struct file *, drm_ioctl_t, void *, u32);171long drm_ioctl_kernel(struct file *, drm_ioctl_t, void *, u32);
173#ifdef CONFIG_COMPAT172#ifdef CONFIG_COMPAT
include/drm/drm_mode_config.h+6−7
@@ -103,14 +103,13 @@ struct drm_mode_config_funcs { · 102 unmodified lines
103 * Callback used by helpers to inform the driver of output configuration103 * Callback used by helpers to inform the driver of output configuration
104 * changes.104 * changes.
105 *105 *
106 * Drivers implementing fbdev emulation with the helpers can call106 * Drivers implementing fbdev emulation use drm_kms_helper_hotplug_event()
107 * drm_fb_helper_hotplug_changed from this hook to inform the fbdev107 * to call this hook to inform the fbdev helper of output changes.
108 * helper of output changes.
109 *108 *
110 * FIXME:109 * This hook is deprecated, drivers should instead use
111 *110 * drm_fbdev_generic_setup() which takes care of any necessary
112 * Except that there's no vtable for device-level helper callbacks111 * hotplug event forwarding already without further involvement by
113 * there's no reason this is a core function.112 * the driver.
114 */113 */
115 void (*output_poll_changed)(struct drm_device *dev);114 void (*output_poll_changed)(struct drm_device *dev);
116 115
include/drm/drm_plane.h+1−1
@@ -43,7 +43,7 @@ enum drm_scaling_filter { · 42 unmodified lines
43/**43/**
44 * struct drm_plane_state - mutable plane state44 * struct drm_plane_state - mutable plane state
45 *45 *
46 * Please not that the destination coordinates @crtc_x, @crtc_y, @crtc_h and46 * Please note that the destination coordinates @crtc_x, @crtc_y, @crtc_h and
47 * @crtc_w and the source coordinates @src_x, @src_y, @src_h and @src_w are the47 * @crtc_w and the source coordinates @src_x, @src_y, @src_h and @src_w are the
48 * raw coordinates provided by userspace. Drivers should use48 * raw coordinates provided by userspace. Drivers should use
49 * drm_atomic_helper_check_plane_state() and only use the derived rectangles in49 * drm_atomic_helper_check_plane_state() and only use the derived rectangles in
include/drm/gpu_scheduler.h+155−33
@@ -27,9 +27,12 @@ · 26 unmodified lines
27#include <drm/spsc_queue.h>27#include <drm/spsc_queue.h>
28#include <linux/dma-fence.h>28#include <linux/dma-fence.h>
29#include <linux/completion.h>29#include <linux/completion.h>
30#include <linux/xarray.h>
30 31
31#define MAX_WAIT_SCHED_ENTITY_Q_EMPTY msecs_to_jiffies(1000)32#define MAX_WAIT_SCHED_ENTITY_Q_EMPTY msecs_to_jiffies(1000)
32 33
34struct drm_gem_object;
35
33struct drm_gpu_scheduler;36struct drm_gpu_scheduler;
34struct drm_sched_rq;37struct drm_sched_rq;
35 38
@@ -50,56 +53,147 @@ enum drm_sched_priority { · 14 unmodified lines
50 * struct drm_sched_entity - A wrapper around a job queue (typically53 * struct drm_sched_entity - A wrapper around a job queue (typically
51 * attached to the DRM file_priv).54 * attached to the DRM file_priv).
52 *55 *
53 * @list: used to append this struct to the list of entities in the
54 * runqueue.
55 * @rq: runqueue on which this entity is currently scheduled.
56 * @sched_list: A list of schedulers (drm_gpu_schedulers).
57 * Jobs from this entity can be scheduled on any scheduler
58 * on this list.
59 * @num_sched_list: number of drm_gpu_schedulers in the sched_list.
60 * @priority: priority of the entity
61 * @rq_lock: lock to modify the runqueue to which this entity belongs.
62 * @job_queue: the list of jobs of this entity.
63 * @fence_seq: a linearly increasing seqno incremented with each
64 * new &drm_sched_fence which is part of the entity.
65 * @fence_context: a unique context for all the fences which belong
66 * to this entity.
67 * The &drm_sched_fence.scheduled uses the
68 * fence_context but &drm_sched_fence.finished uses
69 * fence_context + 1.
70 * @dependency: the dependency fence of the job which is on the top
71 * of the job queue.
72 * @cb: callback for the dependency fence above.
73 * @guilty: points to ctx's guilty.
74 * @fini_status: contains the exit status in case the process was signalled.
75 * @last_scheduled: points to the finished fence of the last scheduled job.
76 * @last_user: last group leader pushing a job into the entity.
77 * @stopped: Marks the enity as removed from rq and destined for termination.
78 * @entity_idle: Signals when enityt is not in use
79 *
80 * Entities will emit jobs in order to their corresponding hardware56 * Entities will emit jobs in order to their corresponding hardware
81 * ring, and the scheduler will alternate between entities based on57 * ring, and the scheduler will alternate between entities based on
82 * scheduling policy.58 * scheduling policy.
83 */59 */
84struct drm_sched_entity {60struct drm_sched_entity {
61 /**
62 * @list:
63 *
64 * Used to append this struct to the list of entities in the runqueue
65 * @rq under &drm_sched_rq.entities.
66 *
67 * Protected by &drm_sched_rq.lock of @rq.
68 */
85 struct list_head list;69 struct list_head list;
70
71 /**
72 * @rq:
73 *
74 * Runqueue on which this entity is currently scheduled.
75 *
76 * FIXME: Locking is very unclear for this. Writers are protected by
77 * @rq_lock, but readers are generally lockless and seem to just race
78 * with not even a READ_ONCE.
79 */
86 struct drm_sched_rq *rq;80 struct drm_sched_rq *rq;
81
82 /**
83 * @sched_list:
84 *
85 * A list of schedulers (struct drm_gpu_scheduler). Jobs from this entity can
86 * be scheduled on any scheduler on this list.
87 *
88 * This can be modified by calling drm_sched_entity_modify_sched().
89 * Locking is entirely up to the driver, see the above function for more
90 * details.
91 *
92 * This will be set to NULL if &num_sched_list equals 1 and @rq has been
93 * set already.
94 *
95 * FIXME: This means priority changes through
96 * drm_sched_entity_set_priority() will be lost henceforth in this case.
97 */
87 struct drm_gpu_scheduler **sched_list;98 struct drm_gpu_scheduler **sched_list;
99
100 /**
101 * @num_sched_list:
102 *
103 * Number of drm_gpu_schedulers in the @sched_list.
104 */
88 unsigned int num_sched_list;105 unsigned int num_sched_list;
106
107 /**
108 * @priority:
109 *
110 * Priority of the entity. This can be modified by calling
111 * drm_sched_entity_set_priority(). Protected by &rq_lock.
112 */
89 enum drm_sched_priority priority;113 enum drm_sched_priority priority;
114
115 /**
116 * @rq_lock:
117 *
118 * Lock to modify the runqueue to which this entity belongs.
119 */
90 spinlock_t rq_lock;120 spinlock_t rq_lock;
91 121
122 /**
123 * @job_queue: the list of jobs of this entity.
124 */
92 struct spsc_queue job_queue;125 struct spsc_queue job_queue;
93 126
127 /**
128 * @fence_seq:
129 *
130 * A linearly increasing seqno incremented with each new
131 * &drm_sched_fence which is part of the entity.
132 *
133 * FIXME: Callers of drm_sched_job_arm() need to ensure correct locking,
134 * this doesn't need to be atomic.
135 */
94 atomic_t fence_seq;136 atomic_t fence_seq;
137
138 /**
139 * @fence_context:
140 *
141 * A unique context for all the fences which belong to this entity. The
142 * &drm_sched_fence.scheduled uses the fence_context but
143 * &drm_sched_fence.finished uses fence_context + 1.
144 */
95 uint64_t fence_context;145 uint64_t fence_context;
96 146
147 /**
148 * @dependency:
149 *
150 * The dependency fence of the job which is on the top of the job queue.
151 */
97 struct dma_fence *dependency;152 struct dma_fence *dependency;
153
154 /**
155 * @cb:
156 *
157 * Callback for the dependency fence above.
158 */
98 struct dma_fence_cb cb;159 struct dma_fence_cb cb;
160
161 /**
162 * @guilty:
163 *
164 * Points to entities' guilty.
165 */
99 atomic_t *guilty;166 atomic_t *guilty;
167
168 /**
169 * @last_scheduled:
170 *
171 * Points to the finished fence of the last scheduled job. Only written
172 * by the scheduler thread, can be accessed locklessly from
173 * drm_sched_job_arm() iff the queue is empty.
174 */
100 struct dma_fence *last_scheduled;175 struct dma_fence *last_scheduled;
176
177 /**
178 * @last_user: last group leader pushing a job into the entity.
179 */
101 struct task_struct *last_user;180 struct task_struct *last_user;
181
182 /**
183 * @stopped:
184 *
185 * Marks the enity as removed from rq and destined for
186 * termination. This is set by calling drm_sched_entity_flush() and by
187 * drm_sched_fini().
188 */
102 bool stopped;189 bool stopped;
190
191 /**
192 * @entity_idle:
193 *
194 * Signals when entity is not in use, used to sequence entity cleanup in
195 * drm_sched_entity_fini().
196 */
103 struct completion entity_idle;197 struct completion entity_idle;
104};198};
105 199
@@ -198,6 +292,17 @@ struct drm_sched_job { · 92 unmodified lines
198 enum drm_sched_priority s_priority;292 enum drm_sched_priority s_priority;
199 struct drm_sched_entity *entity;293 struct drm_sched_entity *entity;
200 struct dma_fence_cb cb;294 struct dma_fence_cb cb;
295 /**
296 * @dependencies:
297 *
298 * Contains the dependencies as struct dma_fence for this job, see
299 * drm_sched_job_add_dependency() and
300 * drm_sched_job_add_implicit_dependencies().
301 */
302 struct xarray dependencies;
303
304 /** @last_dependency: tracks @dependencies as they signal */
305 unsigned long last_dependency;
201};306};
202 307
203static inline bool drm_sched_invalidate_job(struct drm_sched_job *s_job,308static inline bool drm_sched_invalidate_job(struct drm_sched_job *s_job,
@@ -220,9 +325,15 @@ enum drm_gpu_sched_stat { · 16 unmodified lines
220 */325 */
221struct drm_sched_backend_ops {326struct drm_sched_backend_ops {
222 /**327 /**
223 * @dependency: Called when the scheduler is considering scheduling328 * @dependency:
224 * this job next, to get another struct dma_fence for this job to329 *
225 * block on. Once it returns NULL, run_job() may be called.330 * Called when the scheduler is considering scheduling this job next, to
331 * get another struct dma_fence for this job to block on. Once it
332 * returns NULL, run_job() may be called.
333 *
334 * If a driver exclusively uses drm_sched_job_add_dependency() and
335 * drm_sched_job_add_implicit_dependencies() this can be ommitted and
336 * left as NULL.
226 */337 */
227 struct dma_fence *(*dependency)(struct drm_sched_job *sched_job,338 struct dma_fence *(*dependency)(struct drm_sched_job *sched_job,
228 struct drm_sched_entity *s_entity);339 struct drm_sched_entity *s_entity);
@@ -348,6 +459,14 @@ void drm_sched_fini(struct drm_gpu_scheduler *sched); · 119 unmodified lines
348int drm_sched_job_init(struct drm_sched_job *job,459int drm_sched_job_init(struct drm_sched_job *job,
349 struct drm_sched_entity *entity,460 struct drm_sched_entity *entity,
350 void *owner);461 void *owner);
462void drm_sched_job_arm(struct drm_sched_job *job);
463int drm_sched_job_add_dependency(struct drm_sched_job *job,
464 struct dma_fence *fence);
465int drm_sched_job_add_implicit_dependencies(struct drm_sched_job *job,
466 struct drm_gem_object *obj,
467 bool write);
468
469
351void drm_sched_entity_modify_sched(struct drm_sched_entity *entity,470void drm_sched_entity_modify_sched(struct drm_sched_entity *entity,
352 struct drm_gpu_scheduler **sched_list,471 struct drm_gpu_scheduler **sched_list,
353 unsigned int num_sched_list);472 unsigned int num_sched_list);
@@ -381,14 +500,17 @@ void drm_sched_entity_fini(struct drm_sched_entity *entity); · 27 unmodified lines
381void drm_sched_entity_destroy(struct drm_sched_entity *entity);500void drm_sched_entity_destroy(struct drm_sched_entity *entity);
382void drm_sched_entity_select_rq(struct drm_sched_entity *entity);501void drm_sched_entity_select_rq(struct drm_sched_entity *entity);
383struct drm_sched_job *drm_sched_entity_pop_job(struct drm_sched_entity *entity);502struct drm_sched_job *drm_sched_entity_pop_job(struct drm_sched_entity *entity);
384void drm_sched_entity_push_job(struct drm_sched_job *sched_job,503void drm_sched_entity_push_job(struct drm_sched_job *sched_job);
385 struct drm_sched_entity *entity);
386void drm_sched_entity_set_priority(struct drm_sched_entity *entity,504void drm_sched_entity_set_priority(struct drm_sched_entity *entity,
387 enum drm_sched_priority priority);505 enum drm_sched_priority priority);
388bool drm_sched_entity_is_ready(struct drm_sched_entity *entity);506bool drm_sched_entity_is_ready(struct drm_sched_entity *entity);
389 507
390struct drm_sched_fence *drm_sched_fence_create(508struct drm_sched_fence *drm_sched_fence_alloc(
391 struct drm_sched_entity *s_entity, void *owner);509 struct drm_sched_entity *s_entity, void *owner);
510void drm_sched_fence_init(struct drm_sched_fence *fence,
511 struct drm_sched_entity *entity);
512void drm_sched_fence_free(struct drm_sched_fence *fence);
513
392void drm_sched_fence_scheduled(struct drm_sched_fence *fence);514void drm_sched_fence_scheduled(struct drm_sched_fence *fence);
393void drm_sched_fence_finished(struct drm_sched_fence *fence);515void drm_sched_fence_finished(struct drm_sched_fence *fence);
394 516
include/drm/ttm/ttm_bo_api.h+0−12
@@ -264,18 +264,6 @@ static inline int ttm_bo_wait_ctx(struct ttm_buffer_object *bo, struct ttm_opera · 263 unmodified lines
264 return ttm_bo_wait(bo, ctx->interruptible, ctx->no_wait_gpu);264 return ttm_bo_wait(bo, ctx->interruptible, ctx->no_wait_gpu);
265}265}
266 266
267/**
268 * ttm_bo_mem_compat - Check if proposed placement is compatible with a bo
269 *
270 * @placement: Return immediately if buffer is busy.
271 * @mem: The struct ttm_resource indicating the region where the bo resides
272 * @new_flags: Describes compatible placement found
273 *
274 * Returns true if the placement is compatible
275 */
276bool ttm_bo_mem_compat(struct ttm_placement *placement, struct ttm_resource *mem,
277 uint32_t *new_flags);
278
279/**267/**
280 * ttm_bo_validate268 * ttm_bo_validate
281 *269 *
include/drm/ttm/ttm_caching.h+17−0
@@ -27,9 +27,26 @@ · 26 unmodified lines
27 27
28#define TTM_NUM_CACHING_TYPES 328#define TTM_NUM_CACHING_TYPES 3
29 29
30/**
31 * enum ttm_caching - CPU caching and BUS snooping behavior.
32 */
30enum ttm_caching {33enum ttm_caching {
34 /**
35 * @ttm_uncached: Most defensive option for device mappings,
36 * don't even allow write combining.
37 */
31 ttm_uncached,38 ttm_uncached,
39
40 /**
41 * @ttm_write_combined: Don't cache read accesses, but allow at least
42 * writes to be combined.
43 */
32 ttm_write_combined,44 ttm_write_combined,
45
46 /**
47 * @ttm_cached: Fully cached like normal system memory, requires that
48 * devices snoop the CPU cache on accesses.
49 */
33 ttm_cached50 ttm_cached
34};51};
35 52
include/drm/ttm/ttm_device.h+44−33
@@ -39,31 +39,23 @@ struct ttm_operation_ctx; · 38 unmodified lines
39 39
40/**40/**
41 * struct ttm_global - Buffer object driver global data.41 * struct ttm_global - Buffer object driver global data.
42 *
43 * @dummy_read_page: Pointer to a dummy page used for mapping requests
44 * of unpopulated pages.
45 * @shrink: A shrink callback object used for buffer object swap.
46 * @device_list_mutex: Mutex protecting the device list.
47 * This mutex is held while traversing the device list for pm options.
48 * @lru_lock: Spinlock protecting the bo subsystem lru lists.
49 * @device_list: List of buffer object devices.
50 * @swap_lru: Lru list of buffer objects used for swapping.
51 */42 */
52extern struct ttm_global {43extern struct ttm_global {
53 44
54 /**45 /**
55 * Constant after init.46 * @dummy_read_page: Pointer to a dummy page used for mapping requests
47 * of unpopulated pages. Constant after init.
56 */48 */
57
58 struct page *dummy_read_page;49 struct page *dummy_read_page;
59 50
60 /**51 /**
61 * Protected by ttm_global_mutex.52 * @device_list: List of buffer object devices. Protected by
53 * ttm_global_mutex.
62 */54 */
63 struct list_head device_list;55 struct list_head device_list;
64 56
65 /**57 /**
66 * Internal protection.58 * @bo_count: Number of buffer objects allocated by devices.
67 */59 */
68 atomic_t bo_count;60 atomic_t bo_count;
69} ttm_glob;61} ttm_glob;
@@ -230,49 +222,64 @@ struct ttm_device_funcs { · 160 unmodified lines
230 222
231/**223/**
232 * struct ttm_device - Buffer object driver device-specific data.224 * struct ttm_device - Buffer object driver device-specific data.
233 *
234 * @device_list: Our entry in the global device list.
235 * @funcs: Function table for the device.
236 * @sysman: Resource manager for the system domain.
237 * @man_drv: An array of resource_managers.
238 * @vma_manager: Address space manager.
239 * @pool: page pool for the device.
240 * @dev_mapping: A pointer to the struct address_space representing the
241 * device address space.
242 * @wq: Work queue structure for the delayed delete workqueue.
243 */225 */
244struct ttm_device {226struct ttm_device {
245 /*227 /**
228 * @device_list: Our entry in the global device list.
246 * Constant after bo device init229 * Constant after bo device init
247 */230 */
248 struct list_head device_list;231 struct list_head device_list;
232
233 /**
234 * @funcs: Function table for the device.
235 * Constant after bo device init
236 */
249 struct ttm_device_funcs *funcs;237 struct ttm_device_funcs *funcs;
250 238
251 /*239 /**
240 * @sysman: Resource manager for the system domain.
252 * Access via ttm_manager_type.241 * Access via ttm_manager_type.
253 */242 */
254 struct ttm_resource_manager sysman;243 struct ttm_resource_manager sysman;
244
245 /**
246 * @man_drv: An array of resource_managers, one per resource type.
247 */
255 struct ttm_resource_manager *man_drv[TTM_NUM_MEM_TYPES];248 struct ttm_resource_manager *man_drv[TTM_NUM_MEM_TYPES];
256 249
257 /*250 /**
258 * Protected by internal locks.251 * @vma_manager: Address space manager for finding BOs to mmap.
259 */252 */
260 struct drm_vma_offset_manager *vma_manager;253 struct drm_vma_offset_manager *vma_manager;
254
255 /**
256 * @pool: page pool for the device.
257 */
261 struct ttm_pool pool;258 struct ttm_pool pool;
262 259
263 /*260 /**
264 * Protection for the per manager LRU and ddestroy lists.261 * @lru_lock: Protection for the per manager LRU and ddestroy lists.
265 */262 */
266 spinlock_t lru_lock;263 spinlock_t lru_lock;
264
265 /**
266 * @ddestroy: Destroyed but not yet cleaned up buffer objects.
267 */
267 struct list_head ddestroy;268 struct list_head ddestroy;
268 269
269 /*270 /**
270 * Protected by load / firstopen / lastclose /unload sync.271 * @pinned: Buffer objects which are pinned and so not on any LRU list.
272 */
273 struct list_head pinned;
274
275 /**
276 * @dev_mapping: A pointer to the struct address_space for invalidating
277 * CPU mappings on buffer move. Protected by load/unload sync.
271 */278 */
272 struct address_space *dev_mapping;279 struct address_space *dev_mapping;
273 280
274 /*281 /**
275 * Internal protection.282 * @wq: Work queue structure for the delayed delete workqueue.
276 */283 */
277 struct delayed_work wq;284 struct delayed_work wq;
278};285};
@@ -284,12 +291,15 @@ int ttm_device_swapout(struct ttm_device *bdev, struct ttm_operation_ctx *ctx, · 5 unmodified lines
284static inline struct ttm_resource_manager *291static inline struct ttm_resource_manager *
285ttm_manager_type(struct ttm_device *bdev, int mem_type)292ttm_manager_type(struct ttm_device *bdev, int mem_type)
286{293{
294 BUILD_BUG_ON(__builtin_constant_p(mem_type)
295 && mem_type >= TTM_NUM_MEM_TYPES);
287 return bdev->man_drv[mem_type];296 return bdev->man_drv[mem_type];
288}297}
289 298
290static inline void ttm_set_driver_manager(struct ttm_device *bdev, int type,299static inline void ttm_set_driver_manager(struct ttm_device *bdev, int type,
291 struct ttm_resource_manager *manager)300 struct ttm_resource_manager *manager)
292{301{
302 BUILD_BUG_ON(__builtin_constant_p(type) && type >= TTM_NUM_MEM_TYPES);
293 bdev->man_drv[type] = manager;303 bdev->man_drv[type] = manager;
294}304}
295 305
@@ -298,5 +308,6 @@ int ttm_device_init(struct ttm_device *bdev, struct ttm_device_funcs *funcs, · 2 unmodified lines
298 struct drm_vma_offset_manager *vma_manager,308 struct drm_vma_offset_manager *vma_manager,
299 bool use_dma_alloc, bool use_dma32);309 bool use_dma_alloc, bool use_dma32);
300void ttm_device_fini(struct ttm_device *bdev);310void ttm_device_fini(struct ttm_device *bdev);
311void ttm_device_clear_dma_mappings(struct ttm_device *bdev);
301 312
302#endif313#endif
include/drm/ttm/ttm_placement.h+1−0
@@ -58,6 +58,7 @@ · 57 unmodified lines
58 *58 *
59 * @fpfn: first valid page frame number to put the object59 * @fpfn: first valid page frame number to put the object
60 * @lpfn: last valid page frame number to put the object60 * @lpfn: last valid page frame number to put the object
61 * @mem_type: One of TTM_PL_* where the resource should be allocated from.
61 * @flags: memory domain and caching flags for the object62 * @flags: memory domain and caching flags for the object
62 *63 *
63 * Structure indicating a possible place to put an object.64 * Structure indicating a possible place to put an object.
include/drm/ttm/ttm_pool.h+3−2
@@ -37,7 +37,7 @@ struct ttm_pool; · 36 unmodified lines
37struct ttm_operation_ctx;37struct ttm_operation_ctx;
38 38
39/**39/**
40 * ttm_pool_type - Pool for a certain memory type40 * struct ttm_pool_type - Pool for a certain memory type
41 *41 *
42 * @pool: the pool we belong to, might be NULL for the global ones42 * @pool: the pool we belong to, might be NULL for the global ones
43 * @order: the allocation order our pages have43 * @order: the allocation order our pages have
@@ -58,8 +58,9 @@ struct ttm_pool_type { · 14 unmodified lines
58};58};
59 59
60/**60/**
61 * ttm_pool - Pool for all caching and orders61 * struct ttm_pool - Pool for all caching and orders
62 *62 *
63 * @dev: the device we allocate pages for
63 * @use_dma_alloc: if coherent DMA allocations should be used64 * @use_dma_alloc: if coherent DMA allocations should be used
64 * @use_dma32: if GFP_DMA32 should be used65 * @use_dma32: if GFP_DMA32 should be used
65 * @caching: pools for each caching/order66 * @caching: pools for each caching/order
include/drm/ttm/ttm_range_manager.h+16−2
@@ -4,6 +4,7 @@ · 3 unmodified lines
4#define _TTM_RANGE_MANAGER_H_4#define _TTM_RANGE_MANAGER_H_
5 5
6#include <drm/ttm/ttm_resource.h>6#include <drm/ttm/ttm_resource.h>
7#include <drm/ttm/ttm_device.h>
7#include <drm/drm_mm.h>8#include <drm/drm_mm.h>
8 9
9/**10/**
@@ -33,10 +34,23 @@ to_ttm_range_mgr_node(struct ttm_resource *res) · 23 unmodified lines
33 return container_of(res, struct ttm_range_mgr_node, base);34 return container_of(res, struct ttm_range_mgr_node, base);
34}35}
35 36
36int ttm_range_man_init(struct ttm_device *bdev,37int ttm_range_man_init_nocheck(struct ttm_device *bdev,
37 unsigned type, bool use_tt,38 unsigned type, bool use_tt,
38 unsigned long p_size);39 unsigned long p_size);
39int ttm_range_man_fini(struct ttm_device *bdev,40int ttm_range_man_fini_nocheck(struct ttm_device *bdev,
40 unsigned type);41 unsigned type);
42static __always_inline int ttm_range_man_init(struct ttm_device *bdev,
43 unsigned int type, bool use_tt,
44 unsigned long p_size)
45{
46 BUILD_BUG_ON(__builtin_constant_p(type) && type >= TTM_NUM_MEM_TYPES);
47 return ttm_range_man_init_nocheck(bdev, type, use_tt, p_size);
48}
41 49
50static __always_inline int ttm_range_man_fini(struct ttm_device *bdev,
51 unsigned int type)
52{
53 BUILD_BUG_ON(__builtin_constant_p(type) && type >= TTM_NUM_MEM_TYPES);
54 return ttm_range_man_fini_nocheck(bdev, type);
55}
42#endif56#endif
include/drm/ttm/ttm_resource.h+5−4
@@ -40,6 +40,7 @@ struct ttm_resource_manager; · 39 unmodified lines
40struct ttm_resource;40struct ttm_resource;
41struct ttm_place;41struct ttm_place;
42struct ttm_buffer_object;42struct ttm_buffer_object;
43struct ttm_placement;
43struct dma_buf_map;44struct dma_buf_map;
44struct io_mapping;45struct io_mapping;
45struct sg_table;46struct sg_table;
@@ -102,10 +103,7 @@ struct ttm_resource_manager_func { · 56 unmodified lines
102 * struct ttm_resource_manager103 * struct ttm_resource_manager
103 *104 *
104 * @use_type: The memory type is enabled.105 * @use_type: The memory type is enabled.
105 * @flags: TTM_MEMTYPE_XX flags identifying the traits of the memory106 * @use_tt: If a TT object should be used for the backing store.
106 * managed by this memory type.
107 * @gpu_offset: If used, the GPU offset of the first managed page of
108 * fixed memory or the first managed location in an aperture.
109 * @size: Size of the managed region.107 * @size: Size of the managed region.
110 * @func: structure pointer implementing the range manager. See above108 * @func: structure pointer implementing the range manager. See above
111 * @move_lock: lock for move fence109 * @move_lock: lock for move fence
@@ -143,6 +141,7 @@ struct ttm_resource_manager { · 31 unmodified lines
143 * @addr: mapped virtual address141 * @addr: mapped virtual address
144 * @offset: physical addr142 * @offset: physical addr
145 * @is_iomem: is this io memory ?143 * @is_iomem: is this io memory ?
144 * @caching: See enum ttm_caching
146 *145 *
147 * Structure indicating the bus placement of an object.146 * Structure indicating the bus placement of an object.
148 */147 */
@@ -266,6 +265,8 @@ int ttm_resource_alloc(struct ttm_buffer_object *bo, · 117 unmodified lines
266 const struct ttm_place *place,265 const struct ttm_place *place,
267 struct ttm_resource **res);266 struct ttm_resource **res);
268void ttm_resource_free(struct ttm_buffer_object *bo, struct ttm_resource **res);267void ttm_resource_free(struct ttm_buffer_object *bo, struct ttm_resource **res);
268bool ttm_resource_compat(struct ttm_resource *res,
269 struct ttm_placement *placement);
269 270
270void ttm_resource_manager_init(struct ttm_resource_manager *man,271void ttm_resource_manager_init(struct ttm_resource_manager *man,
271 unsigned long p_size);272 unsigned long p_size);
include/drm/ttm/ttm_tt.h+8−10
@@ -55,7 +55,7 @@ struct ttm_operation_ctx; · 54 unmodified lines
55 * @dma_address: The DMA (bus) addresses of the pages55 * @dma_address: The DMA (bus) addresses of the pages
56 * @swap_storage: Pointer to shmem struct file for swap storage.56 * @swap_storage: Pointer to shmem struct file for swap storage.
57 * @pages_list: used by some page allocation backend57 * @pages_list: used by some page allocation backend
58 * @caching: The current caching state of the pages.58 * @caching: The current caching state of the pages, see enum ttm_caching.
59 *59 *
60 * This is a structure holding the pages, caching- and aperture binding60 * This is a structure holding the pages, caching- and aperture binding
61 * status for a buffer object that isn't backed by fixed (VRAM / AGP)61 * status for a buffer object that isn't backed by fixed (VRAM / AGP)
@@ -127,21 +127,15 @@ int ttm_sg_tt_init(struct ttm_tt *ttm_dma, struct ttm_buffer_object *bo, · 65 unmodified lines
127void ttm_tt_fini(struct ttm_tt *ttm);127void ttm_tt_fini(struct ttm_tt *ttm);
128 128
129/**129/**
130 * ttm_ttm_destroy:130 * ttm_tt_destroy:
131 *131 *
132 * @bdev: the ttm_device this object belongs to
132 * @ttm: The struct ttm_tt.133 * @ttm: The struct ttm_tt.
133 *134 *
134 * Unbind, unpopulate and destroy common struct ttm_tt.135 * Unbind, unpopulate and destroy common struct ttm_tt.
135 */136 */
136void ttm_tt_destroy(struct ttm_device *bdev, struct ttm_tt *ttm);137void ttm_tt_destroy(struct ttm_device *bdev, struct ttm_tt *ttm);
137 138
138/**
139 * ttm_tt_destroy_common:
140 *
141 * Called from driver to destroy common path.
142 */
143void ttm_tt_destroy_common(struct ttm_device *bdev, struct ttm_tt *ttm);
144
145/**139/**
146 * ttm_tt_swapin:140 * ttm_tt_swapin:
147 *141 *
@@ -156,15 +150,19 @@ int ttm_tt_swapout(struct ttm_device *bdev, struct ttm_tt *ttm, · 8 unmodified lines
156/**150/**
157 * ttm_tt_populate - allocate pages for a ttm151 * ttm_tt_populate - allocate pages for a ttm
158 *152 *
153 * @bdev: the ttm_device this object belongs to
159 * @ttm: Pointer to the ttm_tt structure154 * @ttm: Pointer to the ttm_tt structure
155 * @ctx: operation context for populating the tt object.
160 *156 *
161 * Calls the driver method to allocate pages for a ttm157 * Calls the driver method to allocate pages for a ttm
162 */158 */
163int ttm_tt_populate(struct ttm_device *bdev, struct ttm_tt *ttm, struct ttm_operation_ctx *ctx);159int ttm_tt_populate(struct ttm_device *bdev, struct ttm_tt *ttm,
160 struct ttm_operation_ctx *ctx);
164 161
165/**162/**
166 * ttm_tt_unpopulate - free pages from a ttm163 * ttm_tt_unpopulate - free pages from a ttm
167 *164 *
165 * @bdev: the ttm_device this object belongs to
168 * @ttm: Pointer to the ttm_tt structure166 * @ttm: Pointer to the ttm_tt structure
169 *167 *
170 * Calls the driver method to free all pages from a ttm168 * Calls the driver method to free all pages from a ttm
include/linux/dma-buf.h+7−0
@@ -420,6 +420,13 @@ struct dma_buf { · 419 unmodified lines
420 * - Dynamic importers should set fences for any access that they can't420 * - Dynamic importers should set fences for any access that they can't
421 * disable immediately from their &dma_buf_attach_ops.move_notify421 * disable immediately from their &dma_buf_attach_ops.move_notify
422 * callback.422 * callback.
423 *
424 * IMPORTANT:
425 *
426 * All drivers must obey the struct dma_resv rules, specifically the
427 * rules for updating fences, see &dma_resv.fence_excl and
428 * &dma_resv.fence. If these dependency rules are broken access tracking
429 * can be lost resulting in use after free issues.
423 */430 */
424 struct dma_resv *resv;431 struct dma_resv *resv;
425 432
include/linux/dma-fence.h+3−29
@@ -214,19 +214,15 @@ struct dma_fence_ops { · 213 unmodified lines
214 * Custom wait implementation, defaults to dma_fence_default_wait() if214 * Custom wait implementation, defaults to dma_fence_default_wait() if
215 * not set.215 * not set.
216 *216 *
217 * The dma_fence_default_wait implementation should work for any fence, as long217 * Deprecated and should not be used by new implementations. Only used
218 * as @enable_signaling works correctly. This hook allows drivers to218 * by existing implementations which need special handling for their
219 * have an optimized version for the case where a process context is219 * hardware reset procedure.
220 * already available, e.g. if @enable_signaling for the general case
221 * needs to set up a worker thread.
222 *220 *
223 * Must return -ERESTARTSYS if the wait is intr = true and the wait was221 * Must return -ERESTARTSYS if the wait is intr = true and the wait was
224 * interrupted, and remaining jiffies if fence has signaled, or 0 if wait222 * interrupted, and remaining jiffies if fence has signaled, or 0 if wait
225 * timed out. Can also return other error values on custom implementations,223 * timed out. Can also return other error values on custom implementations,
226 * which should be treated as if the fence is signaled. For example a hardware224 * which should be treated as if the fence is signaled. For example a hardware
227 * lockup could be reported like that.225 * lockup could be reported like that.
228 *
229 * This callback is optional.
230 */226 */
231 signed long (*wait)(struct dma_fence *fence,227 signed long (*wait)(struct dma_fence *fence,
232 bool intr, signed long timeout);228 bool intr, signed long timeout);
@@ -590,26 +586,4 @@ struct dma_fence *dma_fence_get_stub(void); · 357 unmodified lines
590struct dma_fence *dma_fence_allocate_private_stub(void);586struct dma_fence *dma_fence_allocate_private_stub(void);
591u64 dma_fence_context_alloc(unsigned num);587u64 dma_fence_context_alloc(unsigned num);
592 588
593#define DMA_FENCE_TRACE(f, fmt, args...) \
594 do { \
595 struct dma_fence *__ff = (f); \
596 if (IS_ENABLED(CONFIG_DMA_FENCE_TRACE)) \
597 pr_info("f %llu#%llu: " fmt, \
598 __ff->context, __ff->seqno, ##args); \
599 } while (0)
600
601#define DMA_FENCE_WARN(f, fmt, args...) \
602 do { \
603 struct dma_fence *__ff = (f); \
604 pr_warn("f %llu#%llu: " fmt, __ff->context, __ff->seqno,\
605 ##args); \
606 } while (0)
607
608#define DMA_FENCE_ERR(f, fmt, args...) \
609 do { \
610 struct dma_fence *__ff = (f); \
611 pr_err("f %llu#%llu: " fmt, __ff->context, __ff->seqno, \
612 ##args); \
613 } while (0)
614
615#endif /* __LINUX_DMA_FENCE_H */589#endif /* __LINUX_DMA_FENCE_H */
include/linux/dma-resv.h+99−5
@@ -62,16 +62,90 @@ struct dma_resv_list { · 61 unmodified lines
62 62
63/**63/**
64 * struct dma_resv - a reservation object manages fences for a buffer64 * struct dma_resv - a reservation object manages fences for a buffer
65 * @lock: update side lock65 *
66 * @seq: sequence count for managing RCU read-side synchronization66 * There are multiple uses for this, with sometimes slightly different rules in
67 * @fence_excl: the exclusive fence, if there is one currently67 * how the fence slots are used.
68 * @fence: list of current shared fences68 *
69 * One use is to synchronize cross-driver access to a struct dma_buf, either for
70 * dynamic buffer management or just to handle implicit synchronization between
71 * different users of the buffer in userspace. See &dma_buf.resv for a more
72 * in-depth discussion.
73 *
74 * The other major use is to manage access and locking within a driver in a
75 * buffer based memory manager. struct ttm_buffer_object is the canonical
76 * example here, since this is where reservation objects originated from. But
77 * use in drivers is spreading and some drivers also manage struct
78 * drm_gem_object with the same scheme.
69 */79 */
70struct dma_resv {80struct dma_resv {
81 /**
82 * @lock:
83 *
84 * Update side lock. Don't use directly, instead use the wrapper
85 * functions like dma_resv_lock() and dma_resv_unlock().
86 *
87 * Drivers which use the reservation object to manage memory dynamically
88 * also use this lock to protect buffer object state like placement,
89 * allocation policies or throughout command submission.
90 */
71 struct ww_mutex lock;91 struct ww_mutex lock;
92
93 /**
94 * @seq:
95 *
96 * Sequence count for managing RCU read-side synchronization, allows
97 * read-only access to @fence_excl and @fence while ensuring we take a
98 * consistent snapshot.
99 */
72 seqcount_ww_mutex_t seq;100 seqcount_ww_mutex_t seq;
73 101
102 /**
103 * @fence_excl:
104 *
105 * The exclusive fence, if there is one currently.
106 *
107 * There are two ways to update this fence:
108 *
109 * - First by calling dma_resv_add_excl_fence(), which replaces all
110 * fences attached to the reservation object. To guarantee that no
111 * fences are lost, this new fence must signal only after all previous
112 * fences, both shared and exclusive, have signalled. In some cases it
113 * is convenient to achieve that by attaching a struct dma_fence_array
114 * with all the new and old fences.
115 *
116 * - Alternatively the fence can be set directly, which leaves the
117 * shared fences unchanged. To guarantee that no fences are lost, this
118 * new fence must signal only after the previous exclusive fence has
119 * signalled. Since the shared fences are staying intact, it is not
120 * necessary to maintain any ordering against those. If semantically
121 * only a new access is added without actually treating the previous
122 * one as a dependency the exclusive fences can be strung together
123 * using struct dma_fence_chain.
124 *
125 * Note that actual semantics of what an exclusive or shared fence mean
126 * is defined by the user, for reservation objects shared across drivers
127 * see &dma_buf.resv.
128 */
74 struct dma_fence __rcu *fence_excl;129 struct dma_fence __rcu *fence_excl;
130
131 /**
132 * @fence:
133 *
134 * List of current shared fences.
135 *
136 * There are no ordering constraints of shared fences against the
137 * exclusive fence slot. If a waiter needs to wait for all access, it
138 * has to wait for both sets of fences to signal.
139 *
140 * A new fence is added by calling dma_resv_add_shared_fence(). Since
141 * this often needs to be done past the point of no return in command
142 * submission it cannot fail, and therefore sufficient slots need to be
143 * reserved by calling dma_resv_reserve_shared().
144 *
145 * Note that actual semantics of what an exclusive or shared fence mean
146 * is defined by the user, for reservation objects shared across drivers
147 * see &dma_buf.resv.
148 */
75 struct dma_resv_list __rcu *fence;149 struct dma_resv_list __rcu *fence;
76};150};
77 151
@@ -98,6 +172,13 @@ static inline void dma_resv_reset_shared_max(struct dma_resv *obj) {} · 20 unmodified lines
98 * undefined order, a #ww_acquire_ctx is passed to unwind if a cycle172 * undefined order, a #ww_acquire_ctx is passed to unwind if a cycle
99 * is detected. See ww_mutex_lock() and ww_acquire_init(). A reservation173 * is detected. See ww_mutex_lock() and ww_acquire_init(). A reservation
100 * object may be locked by itself by passing NULL as @ctx.174 * object may be locked by itself by passing NULL as @ctx.
175 *
176 * When a die situation is indicated by returning -EDEADLK all locks held by
177 * @ctx must be unlocked and then dma_resv_lock_slow() called on @obj.
178 *
179 * Unlocked by calling dma_resv_unlock().
180 *
181 * See also dma_resv_lock_interruptible() for the interruptible variant.
101 */182 */
102static inline int dma_resv_lock(struct dma_resv *obj,183static inline int dma_resv_lock(struct dma_resv *obj,
103 struct ww_acquire_ctx *ctx)184 struct ww_acquire_ctx *ctx)
@@ -119,6 +200,12 @@ static inline int dma_resv_lock(struct dma_resv *obj, · 15 unmodified lines
119 * undefined order, a #ww_acquire_ctx is passed to unwind if a cycle200 * undefined order, a #ww_acquire_ctx is passed to unwind if a cycle
120 * is detected. See ww_mutex_lock() and ww_acquire_init(). A reservation201 * is detected. See ww_mutex_lock() and ww_acquire_init(). A reservation
121 * object may be locked by itself by passing NULL as @ctx.202 * object may be locked by itself by passing NULL as @ctx.
203 *
204 * When a die situation is indicated by returning -EDEADLK all locks held by
205 * @ctx must be unlocked and then dma_resv_lock_slow_interruptible() called on
206 * @obj.
207 *
208 * Unlocked by calling dma_resv_unlock().
122 */209 */
123static inline int dma_resv_lock_interruptible(struct dma_resv *obj,210static inline int dma_resv_lock_interruptible(struct dma_resv *obj,
124 struct ww_acquire_ctx *ctx)211 struct ww_acquire_ctx *ctx)
@@ -134,6 +221,8 @@ static inline int dma_resv_lock_interruptible(struct dma_resv *obj, · 9 unmodified lines
134 * Acquires the reservation object after a die case. This function221 * Acquires the reservation object after a die case. This function
135 * will sleep until the lock becomes available. See dma_resv_lock() as222 * will sleep until the lock becomes available. See dma_resv_lock() as
136 * well.223 * well.
224 *
225 * See also dma_resv_lock_slow_interruptible() for the interruptible variant.
137 */226 */
138static inline void dma_resv_lock_slow(struct dma_resv *obj,227static inline void dma_resv_lock_slow(struct dma_resv *obj,
139 struct ww_acquire_ctx *ctx)228 struct ww_acquire_ctx *ctx)
@@ -167,7 +256,7 @@ static inline int dma_resv_lock_slow_interruptible(struct dma_resv *obj, · 27 unmodified lines
167 * if they overlap with a writer.256 * if they overlap with a writer.
168 *257 *
169 * Also note that since no context is provided, no deadlock protection is258 * Also note that since no context is provided, no deadlock protection is
170 * possible.259 * possible, which is also not needed for a trylock.
171 *260 *
172 * Returns true if the lock was acquired, false otherwise.261 * Returns true if the lock was acquired, false otherwise.
173 */262 */
@@ -193,6 +282,11 @@ static inline bool dma_resv_is_locked(struct dma_resv *obj) · 19 unmodified lines
193 *282 *
194 * Returns the context used to lock a reservation object or NULL if no context283 * Returns the context used to lock a reservation object or NULL if no context
195 * was used or the object is not locked at all.284 * was used or the object is not locked at all.
285 *
286 * WARNING: This interface is pretty horrible, but TTM needs it because it
287 * doesn't pass the struct ww_acquire_ctx around in some very long callchains.
288 * Everyone else just uses it to check whether they're holding a reservation or
289 * not.
196 */290 */
197static inline struct ww_acquire_ctx *dma_resv_locking_ctx(struct dma_resv *obj)291static inline struct ww_acquire_ctx *dma_resv_locking_ctx(struct dma_resv *obj)
198{292{
include/linux/seqno-fence.h+0−109
@@ -1,109 +0,0 @@
1/* SPDX-License-Identifier: GPL-2.0-only */
2/*
3 * seqno-fence, using a dma-buf to synchronize fencing
4 *
5 * Copyright (C) 2012 Texas Instruments
6 * Copyright (C) 2012 Canonical Ltd
7 * Authors:
8 * Rob Clark <robdclark@gmail.com>
9 * Maarten Lankhorst <maarten.lankhorst@canonical.com>
10 */
11
12#ifndef __LINUX_SEQNO_FENCE_H
13#define __LINUX_SEQNO_FENCE_H
14
15#include <linux/dma-fence.h>
16#include <linux/dma-buf.h>
17
18enum seqno_fence_condition {
19 SEQNO_FENCE_WAIT_GEQUAL,
20 SEQNO_FENCE_WAIT_NONZERO
21};
22
23struct seqno_fence {
24 struct dma_fence base;
25
26 const struct dma_fence_ops *ops;
27 struct dma_buf *sync_buf;
28 uint32_t seqno_ofs;
29 enum seqno_fence_condition condition;
30};
31
32extern const struct dma_fence_ops seqno_fence_ops;
33
34/**
35 * to_seqno_fence - cast a fence to a seqno_fence
36 * @fence: fence to cast to a seqno_fence
37 *
38 * Returns NULL if the fence is not a seqno_fence,
39 * or the seqno_fence otherwise.
40 */
41static inline struct seqno_fence *
42to_seqno_fence(struct dma_fence *fence)
43{
44 if (fence->ops != &seqno_fence_ops)
45 return NULL;
46 return container_of(fence, struct seqno_fence, base);
47}
48
49/**
50 * seqno_fence_init - initialize a seqno fence
51 * @fence: seqno_fence to initialize
52 * @lock: pointer to spinlock to use for fence
53 * @sync_buf: buffer containing the memory location to signal on
54 * @context: the execution context this fence is a part of
55 * @seqno_ofs: the offset within @sync_buf
56 * @seqno: the sequence # to signal on
57 * @cond: fence wait condition
58 * @ops: the fence_ops for operations on this seqno fence
59 *
60 * This function initializes a struct seqno_fence with passed parameters,
61 * and takes a reference on sync_buf which is released on fence destruction.
62 *
63 * A seqno_fence is a dma_fence which can complete in software when
64 * enable_signaling is called, but it also completes when
65 * (s32)((sync_buf)[seqno_ofs] - seqno) >= 0 is true
66 *
67 * The seqno_fence will take a refcount on the sync_buf until it's
68 * destroyed, but actual lifetime of sync_buf may be longer if one of the
69 * callers take a reference to it.
70 *
71 * Certain hardware have instructions to insert this type of wait condition
72 * in the command stream, so no intervention from software would be needed.
73 * This type of fence can be destroyed before completed, however a reference
74 * on the sync_buf dma-buf can be taken. It is encouraged to re-use the same
75 * dma-buf for sync_buf, since mapping or unmapping the sync_buf to the
76 * device's vm can be expensive.
77 *
78 * It is recommended for creators of seqno_fence to call dma_fence_signal()
79 * before destruction. This will prevent possible issues from wraparound at
80 * time of issue vs time of check, since users can check dma_fence_is_signaled()
81 * before submitting instructions for the hardware to wait on the fence.
82 * However, when ops.enable_signaling is not called, it doesn't have to be
83 * done as soon as possible, just before there's any real danger of seqno
84 * wraparound.
85 */
86static inline void
87seqno_fence_init(struct seqno_fence *fence, spinlock_t *lock,
88 struct dma_buf *sync_buf, uint32_t context,
89 uint32_t seqno_ofs, uint32_t seqno,
90 enum seqno_fence_condition cond,
91 const struct dma_fence_ops *ops)
92{
93 BUG_ON(!fence || !sync_buf || !ops);
94 BUG_ON(!ops->wait || !ops->enable_signaling ||
95 !ops->get_driver_name || !ops->get_timeline_name);
96
97 /*
98 * ops is used in dma_fence_init for get_driver_name, so needs to be
99 * initialized first
100 */
101 fence->ops = ops;
102 dma_fence_init(&fence->base, &seqno_fence_ops, lock, context, seqno);
103 get_dma_buf(sync_buf);
104 fence->sync_buf = sync_buf;
105 fence->seqno_ofs = seqno_ofs;
106 fence->condition = cond;
107}
108
109#endif /* __LINUX_SEQNO_FENCE_H */
include/linux/shrinker.h+1−0
@@ -93,4 +93,5 @@ extern void register_shrinker_prepared(struct shrinker *shrinker); · 92 unmodified lines
93extern int register_shrinker(struct shrinker *shrinker);93extern int register_shrinker(struct shrinker *shrinker);
94extern void unregister_shrinker(struct shrinker *shrinker);94extern void unregister_shrinker(struct shrinker *shrinker);
95extern void free_prealloced_shrinker(struct shrinker *shrinker);95extern void free_prealloced_shrinker(struct shrinker *shrinker);
96extern void synchronize_shrinkers(void);
96#endif97#endif
include/uapi/drm/drm_fourcc.h+6−0
@@ -373,6 +373,12 @@ extern "C" { · 372 unmodified lines
373 373
374#define DRM_FORMAT_RESERVED ((1ULL << 56) - 1)374#define DRM_FORMAT_RESERVED ((1ULL << 56) - 1)
375 375
376#define fourcc_mod_get_vendor(modifier) \
377 (((modifier) >> 56) & 0xff)
378
379#define fourcc_mod_is_vendor(modifier, vendor) \
380 (fourcc_mod_get_vendor(modifier) == DRM_FORMAT_MOD_VENDOR_## vendor)
381
376#define fourcc_mod_code(vendor, val) \382#define fourcc_mod_code(vendor, val) \
377 ((((__u64)DRM_FORMAT_MOD_VENDOR_## vendor) << 56) | ((val) & 0x00ffffffffffffffULL))383 ((((__u64)DRM_FORMAT_MOD_VENDOR_## vendor) << 56) | ((val) & 0x00ffffffffffffffULL))
378 384
include/uapi/drm/drm_mode.h+3−0
@@ -1110,6 +1110,9 @@ struct drm_mode_destroy_blob { · 1109 unmodified lines
1110 * struct drm_mode_create_lease - Create lease1110 * struct drm_mode_create_lease - Create lease
1111 *1111 *
1112 * Lease mode resources, creating another drm_master.1112 * Lease mode resources, creating another drm_master.
1113 *
1114 * The @object_ids array must reference at least one CRTC, one connector and
1115 * one plane if &DRM_CLIENT_CAP_UNIVERSAL_PLANES is enabled.
1113 */1116 */
1114struct drm_mode_create_lease {1117struct drm_mode_create_lease {
1115 /** @object_ids: Pointer to array of object ids (__u32) */1118 /** @object_ids: Pointer to array of object ids (__u32) */
mm/vmscan.c+15−0
@@ -687,6 +687,21 @@ void unregister_shrinker(struct shrinker *shrinker) · 686 unmodified lines
687}687}
688EXPORT_SYMBOL(unregister_shrinker);688EXPORT_SYMBOL(unregister_shrinker);
689 689
690/**
691 * synchronize_shrinkers - Wait for all running shrinkers to complete.
692 *
693 * This is equivalent to calling unregister_shrink() and register_shrinker(),
694 * but atomically and with less overhead. This is useful to guarantee that all
695 * shrinker invocations have seen an update, before freeing memory, similar to
696 * rcu.
697 */
698void synchronize_shrinkers(void)
699{
700 down_write(&shrinker_rwsem);
701 up_write(&shrinker_rwsem);
702}
703EXPORT_SYMBOL(synchronize_shrinkers);
704
690#define SHRINK_BATCH 128705#define SHRINK_BATCH 128
691 706
692static unsigned long do_shrink_slab(struct shrink_control *shrinkctl,707static unsigned long do_shrink_slab(struct shrink_control *shrinkctl,