History

Merge tag 'drm-misc-next-2019-05-24' of git://anongit.freedesktop.org/drm/drm-misc into drm-next

drm-misc-next for v5.3, try #2: UAPI Changes: - Add HDR source metadata property. - Make drm.h compile on GNU/kFreeBSD by including stdint.h - Clarify how the userspace reviewer has to review new kernel UAPI. - Clarify that for using new UAPI, merging to drm-next or drm-misc-next should be enough. Cross-subsystem Changes: - video/hdmi: Add unpack function for DRM infoframes. - Device tree bindings: * Updating a property for Mali Midgard GPUs * Updating a property for STM32 DSI panel * Adding support for FriendlyELEC HD702E 800x1280 panel * Adding support for Evervision VGG804821 800x480 5.0" WVGA TFT panel * Adding support for the EDT ET035012DM6 3.5" 320x240 QVGA 24-bit RGB TFT. * Adding support for Three Five displays TFC S9700RTWV43TR-01B 800x480 panel with resistive touch found on TI's AM335X-EVM. * Adding support for EDT ETM0430G0DH6 480x272 panel. - Add OSD101T2587-53TS driver with DT bindings. - Add Samsung S6E63M0 panel driver with DT bindings. - Add VXT VL050-8048NT-C01 800x480 panel with DT bindings. - Dma-buf: - Make mmap callback actually optional. - Documentation updates. - Fix debugfs refcount inbalance. - Remove unused sync_dump function. - Fix device tree bindings in drm-misc-next after a botched merge. Core Changes: - Add support for HDR infoframes and related EDID parsing. - Remove prime sg_table caching, now done inside dma-buf. - Add shiny new drm_gem_vram helpers for simple VRAM drivers; with some fixes to the new API on top. - Small fix to job cleanup without timeout handler. - Documentation fixes to drm_fourcc. - Replace lookups of drm_format with struct drm_format_info; remove functions that become obsolete by this conversion. - Remove double include in bridge/panel.c and some drivers. - Remove drmP.h include from drm/edid and drm/dp. - Fix null pointer deref in drm_fb_helper_hotplug_event(). - Remove most members from drm_fb_helper_crtc, only mode_set is kept. - Remove race of fb helpers with userspace; only restore mode when userspace is not master. - Move legacy setup from drm_file.c to drm_legacy_misc.c - Rework scheduler job destruction. - drm/bus was removed, remove from TODO. - Add __drm_atomic_helper_crtc_reset() to subclass crtc_state, and convert some drivers to use it (conversion is not complete yet). - Bump vblank timeout wait to 100 ms for atomic. - Docbook fix for drm_hdmi_infoframe_set_hdr_metadata. Driver Changes: - sun4i: Use DRM_GEM_CMA_VMAP_DRIVER_OPS instead of definining manually. - v3d: Small cleanups, adding support for compute shaders, reservation/synchronization fixes and job management refactoring, fixes MMU and debugfs. - lima: Fix null pointer in irq handler on startup, set default timeout for scheduled jobs. - stm/ltdc: Assorted fixes and adding FB modifier support. - amdgpu: Avoid hw reset if guilty job was already signaled. - virtio: Add seqno to fences, add trace events, use correct flags for fence allocation. - Convert AST, bochs, mgag200, vboxvideo, hisilicon to the new drm_gem_vram API. - sun6i_mipi_dsi: Support DSI GENERIC_SHORT_WRITE_2 transfers. - bochs: Small fix to use PTR_RET_OR_ZERO and driver unload. - gma500: header fixes - cirrus: Remove unused files. - mediatek: Fix compiler warning after merging the HDR series. - vc4: Rework binner bo handling. Signed-off-by: Dave Airlie <airlied@redhat.com>

Dave Airlie committed 7 years ago

Commit 88cd7a22 parents cd6c84d 909fa33220 files · +5943 −4593Browse files

Unified · Split

220 files
  1. Documentation/devicetree/bindings/display/panel/edt,et-series.txt +16 −0
  2. Documentation/devicetree/bindings/display/panel/evervision,vgg804821.txt +12 −0
  3. Documentation/devicetree/bindings/display/panel/friendlyarm,hd702e.txt +32 −0
  4. Documentation/devicetree/bindings/display/panel/osddisplays,osd101t2045-53ts.txt +11 −0
  5. Documentation/devicetree/bindings/display/panel/osddisplays,osd101t2587-53ts.txt +14 −0
  6. Documentation/devicetree/bindings/display/panel/samsung,s6e63m0.txt +33 −0
  7. Documentation/devicetree/bindings/display/panel/tfc,s9700rtwv43tr-01b.txt +15 −0
  8. Documentation/devicetree/bindings/display/panel/vl050_8048nt_c01.txt +12 −0
  9. Documentation/devicetree/bindings/display/st,stm32-ltdc.txt +3 −0
  10. Documentation/devicetree/bindings/gpu/arm,mali-midgard.txt +18 −1
  11. Documentation/devicetree/bindings/vendor-prefixes.yaml +6 −0
  12. Documentation/gpu/drm-mm.rst +33 −1
  13. Documentation/gpu/drm-uapi.rst +6 −4
  14. Documentation/gpu/todo.rst +8 −19
  15. MAINTAINERS +1 −1
  16. drivers/dma-buf/dma-buf.c +35 −4
  17. drivers/dma-buf/sync_debug.c +0 −26
  18. drivers/dma-buf/sync_debug.h +0 −1
  19. drivers/gpu/drm/Kconfig +7 −0
  20. drivers/gpu/drm/Makefile +5 −0
  21. drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +95 −51
  22. drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c +3 −1
  23. drivers/gpu/drm/arm/malidp_crtc.c +11 −17
  24. drivers/gpu/drm/arm/malidp_hw.c +2 −1
  25. drivers/gpu/drm/arm/malidp_mw.c +1 −1
  26. drivers/gpu/drm/arm/malidp_planes.c +3 −5
  27. drivers/gpu/drm/armada/armada_fb.c +2 −1
  28. drivers/gpu/drm/ast/Kconfig +1 −2
  29. drivers/gpu/drm/ast/ast_drv.c +2 −11
  30. drivers/gpu/drm/ast/ast_drv.h +3 −68
  31. drivers/gpu/drm/ast/ast_fb.c +24 −17
  32. drivers/gpu/drm/ast/ast_main.c +5 −72
  33. drivers/gpu/drm/ast/ast_mode.c +77 −55
  34. drivers/gpu/drm/ast/ast_ttm.c +8 −294
  35. drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c +2 −7
  36. drivers/gpu/drm/bochs/Kconfig +1 −1
  37. drivers/gpu/drm/bochs/bochs.h +2 −52
  38. drivers/gpu/drm/bochs/bochs_drv.c +5 −19
  39. drivers/gpu/drm/bochs/bochs_kms.c +9 −9
  40. drivers/gpu/drm/bochs/bochs_mm.c +7 −420
  41. drivers/gpu/drm/bridge/panel.c +1 −2
  42. drivers/gpu/drm/cirrus/cirrus_drv.h +0 −250
  43. drivers/gpu/drm/cirrus/cirrus_ttm.c +0 −337
  44. drivers/gpu/drm/drm_atomic_helper.c +1 −1
  45. drivers/gpu/drm/drm_atomic_state_helper.c +34 −7
  46. drivers/gpu/drm/drm_atomic_uapi.c +12 −0
  47. drivers/gpu/drm/drm_auth.c +20 −0
  48. drivers/gpu/drm/drm_client.c +2 −1
  49. drivers/gpu/drm/drm_connector.c +6 −0
  50. drivers/gpu/drm/drm_dp_aux_dev.c +5 −3
  51. drivers/gpu/drm/drm_dp_dual_mode_helper.c +3 −1
  52. drivers/gpu/drm/drm_dp_helper.c +7 −5
  53. drivers/gpu/drm/drm_dp_mst_topology.c +7 −6
  54. drivers/gpu/drm/drm_edid.c +131 −4
  55. drivers/gpu/drm/drm_edid_load.c +5 −2
  56. drivers/gpu/drm/drm_fb_helper.c +125 −121
  57. drivers/gpu/drm/drm_file.c +50 −72
  58. drivers/gpu/drm/drm_format_helper.c +2 −2
  59. drivers/gpu/drm/drm_fourcc.c +0 −118
  60. drivers/gpu/drm/drm_gem_vram_helper.c +772 −0
  61. drivers/gpu/drm/drm_internal.h +2 −0
  62. drivers/gpu/drm/drm_legacy.h +2 −0
  63. drivers/gpu/drm/drm_legacy_misc.c +20 −0
  64. drivers/gpu/drm/drm_prime.c +17 −60
  65. drivers/gpu/drm/drm_vram_helper_common.c +96 −0
  66. drivers/gpu/drm/drm_vram_mm_helper.c +295 −0
  67. drivers/gpu/drm/etnaviv/etnaviv_dump.c +0 −5
  68. drivers/gpu/drm/etnaviv/etnaviv_sched.c +1 −1
  69. drivers/gpu/drm/gma500/accel_2d.c +9 −9
  70. drivers/gpu/drm/gma500/blitter.h +2 −0
  71. drivers/gpu/drm/gma500/cdv_device.c +7 −6
  72. drivers/gpu/drm/gma500/cdv_device.h +4 −0
  73. drivers/gpu/drm/gma500/cdv_intel_crt.c +4 −4
  74. drivers/gpu/drm/gma500/cdv_intel_display.c +6 −4
  75. drivers/gpu/drm/gma500/cdv_intel_dp.c +5 −4
  76. drivers/gpu/drm/gma500/cdv_intel_hdmi.c +5 −4
  77. drivers/gpu/drm/gma500/cdv_intel_lvds.c +4 −5
  78. drivers/gpu/drm/gma500/framebuffer.c +13 −13
  79. drivers/gpu/drm/gma500/framebuffer.h +0 −1
  80. drivers/gpu/drm/gma500/gem.c +3 −2
  81. drivers/gpu/drm/gma500/gma_device.c +0 −1
  82. drivers/gpu/drm/gma500/gma_device.h +1 −0
  83. drivers/gpu/drm/gma500/gma_display.c +9 −3
  84. drivers/gpu/drm/gma500/gma_display.h +3 −0
  85. drivers/gpu/drm/gma500/gtt.c +3 −2
  86. drivers/gpu/drm/gma500/gtt.h +0 −1
  87. drivers/gpu/drm/gma500/intel_bios.c +3 −3
  88. drivers/gpu/drm/gma500/intel_bios.h +1 −2
  89. drivers/gpu/drm/gma500/intel_gmbus.c +6 −5
  90. drivers/gpu/drm/gma500/intel_i2c.c +3 −1
  91. drivers/gpu/drm/gma500/mdfld_device.c +9 −7
  92. drivers/gpu/drm/gma500/mdfld_dsi_dpi.c +3 −1
  93. drivers/gpu/drm/gma500/mdfld_dsi_output.c +7 −5
  94. drivers/gpu/drm/gma500/mdfld_dsi_output.h +4 −4
  95. drivers/gpu/drm/gma500/mdfld_dsi_pkg_sender.c +3 −1
  96. drivers/gpu/drm/gma500/mdfld_intel_display.c +7 −4
  97. drivers/gpu/drm/gma500/mdfld_tmd_vid.c +2 −0
  98. drivers/gpu/drm/gma500/mid_bios.c +2 −3
  99. drivers/gpu/drm/gma500/mid_bios.h +1 −0
  100. drivers/gpu/drm/gma500/mmu.c +4 −2
  101. drivers/gpu/drm/gma500/oaktrail.h +2 −0
  102. drivers/gpu/drm/gma500/oaktrail_crtc.c +5 −3
  103. drivers/gpu/drm/gma500/oaktrail_device.c +11 −9
  104. drivers/gpu/drm/gma500/oaktrail_hdmi.c +5 −3
  105. drivers/gpu/drm/gma500/oaktrail_lvds.c +3 −3
  106. drivers/gpu/drm/gma500/oaktrail_lvds_i2c.c +5 −6
  107. drivers/gpu/drm/gma500/power.h +3 −1
  108. drivers/gpu/drm/gma500/psb_device.c +6 −6
  109. drivers/gpu/drm/gma500/psb_drv.c +21 −12
  110. drivers/gpu/drm/gma500/psb_drv.h +8 −8
  111. drivers/gpu/drm/gma500/psb_intel_display.c +4 −3
  112. drivers/gpu/drm/gma500/psb_intel_lvds.c +2 −3
  113. drivers/gpu/drm/gma500/psb_intel_modes.c +1 −1
  114. drivers/gpu/drm/gma500/psb_intel_sdvo.c +8 −7
  115. drivers/gpu/drm/gma500/psb_irq.c +5 −4
  116. drivers/gpu/drm/gma500/psb_irq.h +1 −1
  117. drivers/gpu/drm/gma500/psb_lid.c +3 −3
  118. drivers/gpu/drm/gma500/tc35876x-dsi-lvds.c +8 −5
  119. drivers/gpu/drm/hisilicon/hibmc/Kconfig +1 −1
  120. drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c +9 −10
  121. drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c +4 −10
  122. drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h +2 −31
  123. drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_fbdev.c +12 −25
  124. drivers/gpu/drm/hisilicon/hibmc/hibmc_ttm.c +16 −325
  125. drivers/gpu/drm/i915/intel_display.c +2 −3
  126. drivers/gpu/drm/i915/intel_sprite.c +2 −1
  127. drivers/gpu/drm/imx/ipuv3-plane.c +6 −9
  128. drivers/gpu/drm/lima/lima_drv.c +1 −1
  129. drivers/gpu/drm/lima/lima_pp.c +7 −1
  130. drivers/gpu/drm/lima/lima_sched.c +5 −8
  131. drivers/gpu/drm/mediatek/mtk_drm_fb.c +5 −3
  132. drivers/gpu/drm/mediatek/mtk_hdmi.c +3 −0
  133. drivers/gpu/drm/meson/meson_overlay.c +7 −7
  134. drivers/gpu/drm/mgag200/Kconfig +1 −1
  135. drivers/gpu/drm/mgag200/mgag200_cursor.c +53 −43
  136. drivers/gpu/drm/mgag200/mgag200_drv.c +2 −11
  137. drivers/gpu/drm/mgag200/mgag200_drv.h +10 −64
  138. drivers/gpu/drm/mgag200/mgag200_fb.c +24 −17
  139. drivers/gpu/drm/mgag200/mgag200_main.c +12 −75
  140. drivers/gpu/drm/mgag200/mgag200_mode.c +30 −29
  141. drivers/gpu/drm/mgag200/mgag200_ttm.c +8 −293
  142. drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c +2 −4
  143. drivers/gpu/drm/msm/disp/dpu1/dpu_formats.c +6 −3
  144. drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c +2 −7
  145. drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c +13 −18
  146. drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c +10 −14
  147. drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c +4 −3
  148. drivers/gpu/drm/msm/msm_fb.c +9 −9
  149. drivers/gpu/drm/nouveau/dispnv50/head.c +3 −10
  150. drivers/gpu/drm/nouveau/nvkm/subdev/bus/nv04.c +0 −2
  151. drivers/gpu/drm/omapdrm/omap_fb.c +4 −2
  152. drivers/gpu/drm/panel/Kconfig +18 −0
  153. drivers/gpu/drm/panel/Makefile +2 −0
  154. drivers/gpu/drm/panel/panel-osd-osd101t2587-53ts.c +254 −0
  155. drivers/gpu/drm/panel/panel-raspberrypi-touchscreen.c +0 −1
  156. drivers/gpu/drm/panel/panel-samsung-s6e63m0.c +514 −0
  157. drivers/gpu/drm/panel/panel-simple.c +211 −1
  158. drivers/gpu/drm/panfrost/panfrost_device.c +22 −0
  159. drivers/gpu/drm/panfrost/panfrost_device.h +1 −0
  160. drivers/gpu/drm/panfrost/panfrost_job.c +1 −1
  161. drivers/gpu/drm/radeon/radeon_fb.c +3 −1
  162. drivers/gpu/drm/rockchip/rockchip_drm_fb.c +6 −11
  163. drivers/gpu/drm/rockchip/rockchip_drm_vop.c +17 −22
  164. drivers/gpu/drm/scheduler/sched_main.c +108 −66
  165. drivers/gpu/drm/stm/dw_mipi_dsi-stm.c +49 −11
  166. drivers/gpu/drm/stm/ltdc.c +47 −20
  167. drivers/gpu/drm/sun4i/sun4i_drv.c +1 −15
  168. drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c +1 −0
  169. drivers/gpu/drm/tegra/dc.c +6 −11
  170. drivers/gpu/drm/tegra/fb.c +6 −8
  171. drivers/gpu/drm/v3d/v3d_debugfs.c +32 −3
  172. drivers/gpu/drm/v3d/v3d_drv.c +13 −4
  173. drivers/gpu/drm/v3d/v3d_drv.h +66 −40
  174. drivers/gpu/drm/v3d/v3d_fence.c +2 −0
  175. drivers/gpu/drm/v3d/v3d_gem.c +355 −197
  176. drivers/gpu/drm/v3d/v3d_irq.c +44 −11
  177. drivers/gpu/drm/v3d/v3d_mmu.c +5 −2
  178. drivers/gpu/drm/v3d/v3d_regs.h +121 −1
  179. drivers/gpu/drm/v3d/v3d_sched.c +250 −132
  180. drivers/gpu/drm/v3d/v3d_trace.h +94 −0
  181. drivers/gpu/drm/vboxvideo/Kconfig +1 −1
  182. drivers/gpu/drm/vboxvideo/vbox_drv.c +2 −10
  183. drivers/gpu/drm/vboxvideo/vbox_drv.h +2 −73
  184. drivers/gpu/drm/vboxvideo/vbox_fb.c +11 −11
  185. drivers/gpu/drm/vboxvideo/vbox_main.c +6 −69
  186. drivers/gpu/drm/vboxvideo/vbox_mode.c +19 −17
  187. drivers/gpu/drm/vboxvideo/vbox_ttm.c +8 −347
  188. drivers/gpu/drm/vc4/vc4_bo.c +30 −1
  189. drivers/gpu/drm/vc4/vc4_drv.c +6 −0
  190. drivers/gpu/drm/vc4/vc4_drv.h +14 −0
  191. drivers/gpu/drm/vc4/vc4_gem.c +11 −0
  192. drivers/gpu/drm/vc4/vc4_irq.c +16 −4
  193. drivers/gpu/drm/vc4/vc4_plane.c +5 −10
  194. drivers/gpu/drm/vc4/vc4_v3d.c +55 −17
  195. drivers/gpu/drm/virtio/Makefile +1 −1
  196. drivers/gpu/drm/virtio/virtgpu_drv.h +1 −2
  197. drivers/gpu/drm/virtio/virtgpu_fence.c +15 −10
  198. drivers/gpu/drm/virtio/virtgpu_ioctl.c +9 −9
  199. drivers/gpu/drm/virtio/virtgpu_trace.h +52 −0
  200. drivers/gpu/drm/virtio/virtgpu_trace_points.c +5 −0
  201. drivers/gpu/drm/virtio/virtgpu_vq.c +10 −0
  202. drivers/gpu/drm/vkms/vkms_crtc.c +13 −20
  203. drivers/gpu/drm/zte/zx_plane.c +2 −4
  204. drivers/video/hdmi.c +257 −0
  205. include/drm/drm_atomic_state_helper.h +2 −0
  206. include/drm/drm_connector.h +14 −0
  207. include/drm/drm_device.h +4 −0
  208. include/drm/drm_edid.h +5 −0
  209. include/drm/drm_fb_helper.h +0 −10
  210. include/drm/drm_fourcc.h +44 −6
  211. include/drm/drm_gem_vram_helper.h +162 −0
  212. include/drm/drm_mode_config.h +7 −0
  213. include/drm/drm_vram_mm_helper.h +102 −0
  214. include/drm/gma_drm.h +0 −25
  215. include/drm/gpu_scheduler.h +3 −5
  216. include/linux/dma-buf.h +38 −9
  217. include/linux/hdmi.h +55 −0
  218. include/uapi/drm/drm.h +1 −0
  219. include/uapi/drm/drm_mode.h +23 −0
  220. include/uapi/drm/v3d_drm.h +28 −0
Documentation/devicetree/bindings/display/panel/edt,et-series.txt+16−0
@@ -6,6 +6,22 @@ Display bindings for EDT Display Technology Corp. Displays which are · 5 unmodified lines
6compatible with the simple-panel binding, which is specified in6compatible with the simple-panel binding, which is specified in
7simple-panel.txt7simple-panel.txt
8 8
93,5" QVGA TFT Panels
10--------------------
11+-----------------+---------------------+-------------------------------------+
12| Identifier | compatbile | description |
13+=================+=====================+=====================================+
14| ET035012DM6 | edt,et035012dm6 | 3.5" QVGA TFT LCD panel |
15+-----------------+---------------------+-------------------------------------+
16
174,3" WVGA TFT Panels
18--------------------
19
20+-----------------+---------------------+-------------------------------------+
21| Identifier | compatbile | description |
22+=================+=====================+=====================================+
23| ETM0430G0DH6 | edt,etm0430g0dh6 | 480x272 TFT Display |
24+-----------------+---------------------+-------------------------------------+
9 25
105,7" WVGA TFT Panels265,7" WVGA TFT Panels
11--------------------27--------------------
Documentation/devicetree/bindings/display/panel/evervision,vgg804821.txt+12−0
@@ -0,0 +1,12 @@
1Evervision Electronics Co. Ltd. VGG804821 5.0" WVGA TFT LCD Panel
2
3Required properties:
4- compatible: should be "evervision,vgg804821"
5- power-supply: See simple-panel.txt
6
7Optional properties:
8- backlight: See simple-panel.txt
9- enable-gpios: See simple-panel.txt
10
11This binding is compatible with the simple-panel binding, which is specified
12in simple-panel.txt in this directory.
Documentation/devicetree/bindings/display/panel/friendlyarm,hd702e.txt+32−0
@@ -0,0 +1,32 @@
1FriendlyELEC HD702E 800x1280 LCD panel
2
3HD702E lcd is FriendlyELEC developed eDP LCD panel with 800x1280
4resolution. It has built in Goodix, GT9271 captive touchscreen
5with backlight adjustable via PWM.
6
7Required properties:
8- compatible: should be "friendlyarm,hd702e"
9- power-supply: regulator to provide the supply voltage
10
11Optional properties:
12- backlight: phandle of the backlight device attached to the panel
13
14Optional nodes:
15- Video port for LCD panel input.
16
17This binding is compatible with the simple-panel binding, which is specified
18in simple-panel.txt in this directory.
19
20Example:
21
22 panel {
23 compatible ="friendlyarm,hd702e", "simple-panel";
24 backlight = <&backlight>;
25 power-supply = <&vcc3v3_sys>;
26
27 port {
28 panel_in_edp: endpoint {
29 remote-endpoint = <&edp_out_panel>;
30 };
31 };
32 };
Documentation/devicetree/bindings/display/panel/osddisplays,osd101t2045-53ts.txt+11−0
@@ -0,0 +1,11 @@
1One Stop Displays OSD101T2045-53TS 10.1" 1920x1200 panel
2
3Required properties:
4- compatible: should be "osddisplays,osd101t2045-53ts"
5- power-supply: as specified in the base binding
6
7Optional properties:
8- backlight: as specified in the base binding
9
10This binding is compatible with the simple-panel binding, which is specified
11in simple-panel.txt in this directory.
Documentation/devicetree/bindings/display/panel/osddisplays,osd101t2587-53ts.txt+14−0
@@ -0,0 +1,14 @@
1One Stop Displays OSD101T2587-53TS 10.1" 1920x1200 panel
2
3The panel is similar to OSD101T2045-53TS, but it needs additional
4MIPI_DSI_TURN_ON_PERIPHERAL message from the host.
5
6Required properties:
7- compatible: should be "osddisplays,osd101t2587-53ts"
8- power-supply: as specified in the base binding
9
10Optional properties:
11- backlight: as specified in the base binding
12
13This binding is compatible with the simple-panel binding, which is specified
14in simple-panel.txt in this directory.
Documentation/devicetree/bindings/display/panel/samsung,s6e63m0.txt+33−0
@@ -0,0 +1,33 @@
1Samsung s6e63m0 AMOLED LCD panel
2
3Required properties:
4 - compatible: "samsung,s6e63m0"
5 - reset-gpios: GPIO spec for reset pin
6 - vdd3-supply: VDD regulator
7 - vci-supply: VCI regulator
8
9The panel must obey rules for SPI slave device specified in document [1].
10
11The device node can contain one 'port' child node with one child
12'endpoint' node, according to the bindings defined in [2]. This
13node should describe panel's video bus.
14
15[1]: Documentation/devicetree/bindings/spi/spi-bus.txt
16[2]: Documentation/devicetree/bindings/media/video-interfaces.txt
17
18Example:
19
20 s6e63m0: display@0 {
21 compatible = "samsung,s6e63m0";
22 reg = <0>;
23 reset-gpio = <&mp05 5 1>;
24 vdd3-supply = <&ldo12_reg>;
25 vci-supply = <&ldo11_reg>;
26 spi-max-frequency = <1200000>;
27
28 port {
29 lcd_ep: endpoint {
30 remote-endpoint = <&fimd_ep>;
31 };
32 };
33 };
Documentation/devicetree/bindings/display/panel/tfc,s9700rtwv43tr-01b.txt+15−0
@@ -0,0 +1,15 @@
1TFC S9700RTWV43TR-01B 7" Three Five Corp 800x480 LCD panel with
2resistive touch
3
4The panel is found on TI AM335x-evm.
5
6Required properties:
7- compatible: should be "tfc,s9700rtwv43tr-01b"
8- power-supply: See panel-common.txt
9
10Optional properties:
11- enable-gpios: GPIO pin to enable or disable the panel, if there is one
12- backlight: phandle of the backlight device attached to the panel
13
14This binding is compatible with the simple-panel binding, which is specified
15in simple-panel.txt in this directory.
Documentation/devicetree/bindings/display/panel/vl050_8048nt_c01.txt+12−0
@@ -0,0 +1,12 @@
1VXT 800x480 color TFT LCD panel
2
3Required properties:
4- compatible: should be "vxt,vl050-8048nt-c01"
5- power-supply: as specified in the base binding
6
7Optional properties:
8- backlight: as specified in the base binding
9- enable-gpios: as specified in the base binding
10
11This binding is compatible with the simple-panel binding, which is specified
12in simple-panel.txt in this directory.
Documentation/devicetree/bindings/display/st,stm32-ltdc.txt+3−0
@@ -40,6 +40,8 @@ Mandatory nodes specific to STM32 DSI: · 39 unmodified lines
40- panel or bridge node: A node containing the panel or bridge description as40- panel or bridge node: A node containing the panel or bridge description as
41 documented in [6].41 documented in [6].
42 - port: panel or bridge port node, connected to the DSI output port (port@1).42 - port: panel or bridge port node, connected to the DSI output port (port@1).
43Optional properties:
44- phy-dsi-supply: phandle of the regulator that provides the supply voltage.
43 45
44Note: You can find more documentation in the following references46Note: You can find more documentation in the following references
45[1] Documentation/devicetree/bindings/clock/clock-bindings.txt47[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
@@ -101,6 +103,7 @@ Example 2: DSI panel · 55 unmodified lines
101 clock-names = "pclk", "ref";103 clock-names = "pclk", "ref";
102 resets = <&rcc STM32F4_APB2_RESET(DSI)>;104 resets = <&rcc STM32F4_APB2_RESET(DSI)>;
103 reset-names = "apb";105 reset-names = "apb";
106 phy-dsi-supply = <&reg18>;
104 107
105 ports {108 ports {
106 #address-cells = <1>;109 #address-cells = <1>;
Documentation/devicetree/bindings/gpu/arm,mali-midgard.txt+18−1
@@ -15,6 +15,7 @@ Required properties: · 14 unmodified lines
15 + "arm,mali-t860"15 + "arm,mali-t860"
16 + "arm,mali-t880"16 + "arm,mali-t880"
17 * which must be preceded by one of the following vendor specifics:17 * which must be preceded by one of the following vendor specifics:
18 + "allwinner,sun50i-h6-mali"
18 + "amlogic,meson-gxm-mali"19 + "amlogic,meson-gxm-mali"
19 + "rockchip,rk3288-mali"20 + "rockchip,rk3288-mali"
20 + "rockchip,rk3399-mali"21 + "rockchip,rk3399-mali"
@@ -31,21 +32,36 @@ Optional properties: · 10 unmodified lines
31 32
32- clocks : Phandle to clock for the Mali Midgard device.33- clocks : Phandle to clock for the Mali Midgard device.
33 34
35- clock-names : Specify the names of the clocks specified in clocks
36 when multiple clocks are present.
37 * core: clock driving the GPU itself (When only one clock is present,
38 assume it's this clock.)
39 * bus: bus clock for the GPU
40
34- mali-supply : Phandle to regulator for the Mali device. Refer to41- mali-supply : Phandle to regulator for the Mali device. Refer to
35 Documentation/devicetree/bindings/regulator/regulator.txt for details.42 Documentation/devicetree/bindings/regulator/regulator.txt for details.
36 43
37- operating-points-v2 : Refer to Documentation/devicetree/bindings/opp/opp.txt44- operating-points-v2 : Refer to Documentation/devicetree/bindings/opp/opp.txt
38 for details.45 for details.
39 46
47- #cooling-cells: Refer to Documentation/devicetree/bindings/thermal/thermal.txt
48 for details.
49
40- resets : Phandle of the GPU reset line.50- resets : Phandle of the GPU reset line.
41 51
42Vendor-specific bindings52Vendor-specific bindings
43------------------------53------------------------
44 54
45The Mali GPU is integrated very differently from one SoC to55The Mali GPU is integrated very differently from one SoC to
46another. In order to accomodate those differences, you have the option56another. In order to accommodate those differences, you have the option
47to specify one more vendor-specific compatible, among:57to specify one more vendor-specific compatible, among:
48 58
59- "allwinner,sun50i-h6-mali"
60 Required properties:
61 - clocks : phandles to core and bus clocks
62 - clock-names : must contain "core" and "bus"
63 - resets: phandle to GPU reset line
64
49- "amlogic,meson-gxm-mali"65- "amlogic,meson-gxm-mali"
50 Required properties:66 Required properties:
51 - resets : Should contain phandles of :67 - resets : Should contain phandles of :
@@ -65,6 +81,7 @@ gpu@ffa30000 { · 13 unmodified lines
65 mali-supply = <&vdd_gpu>;81 mali-supply = <&vdd_gpu>;
66 operating-points-v2 = <&gpu_opp_table>;82 operating-points-v2 = <&gpu_opp_table>;
67 power-domains = <&power RK3288_PD_GPU>;83 power-domains = <&power RK3288_PD_GPU>;
84 #cooling-cells = <2>;
68};85};
69 86
70gpu_opp_table: opp_table0 {87gpu_opp_table: opp_table0 {
Documentation/devicetree/bindings/vendor-prefixes.yaml+6−0
@@ -287,6 +287,8 @@ patternProperties: · 286 unmodified lines
287 description: Everest Semiconductor Co. Ltd.287 description: Everest Semiconductor Co. Ltd.
288 "^everspin,.*":288 "^everspin,.*":
289 description: Everspin Technologies, Inc.289 description: Everspin Technologies, Inc.
290 "^evervision,.*":
291 description: Evervision Electronics Co. Ltd.
290 "^exar,.*":292 "^exar,.*":
291 description: Exar Corporation293 description: Exar Corporation
292 "^excito,.*":294 "^excito,.*":
@@ -849,6 +851,8 @@ patternProperties: · 556 unmodified lines
849 description: Shenzhen Techstar Electronics Co., Ltd.851 description: Shenzhen Techstar Electronics Co., Ltd.
850 "^terasic,.*":852 "^terasic,.*":
851 description: Terasic Inc.853 description: Terasic Inc.
854 "^tfc,.*":
855 description: Three Five Corp
852 "^thine,.*":856 "^thine,.*":
853 description: THine Electronics, Inc.857 description: THine Electronics, Inc.
854 "^ti,.*":858 "^ti,.*":
@@ -923,6 +927,8 @@ patternProperties: · 68 unmodified lines
923 description: Voipac Technologies s.r.o.927 description: Voipac Technologies s.r.o.
924 "^vot,.*":928 "^vot,.*":
925 description: Vision Optical Technology Co., Ltd.929 description: Vision Optical Technology Co., Ltd.
930 "^vxt,.*":
931 description: VXT Ltd
926 "^wd,.*":932 "^wd,.*":
927 description: Western Digital Corp.933 description: Western Digital Corp.
928 "^wetek,.*":934 "^wetek,.*":
Documentation/gpu/drm-mm.rst+33−1
@@ -79,7 +79,6 @@ count for the TTM, which will call your initialization function. · 78 unmodified lines
79 79
80See the radeon_ttm.c file for an example of usage.80See the radeon_ttm.c file for an example of usage.
81 81
82
83The Graphics Execution Manager (GEM)82The Graphics Execution Manager (GEM)
84====================================83====================================
85 84
@@ -380,6 +379,39 @@ GEM CMA Helper Functions Reference · 294 unmodified lines
380.. kernel-doc:: drivers/gpu/drm/drm_gem_cma_helper.c379.. kernel-doc:: drivers/gpu/drm/drm_gem_cma_helper.c
381 :export:380 :export:
382 381
382VRAM Helper Function Reference
383==============================
384
385.. kernel-doc:: drivers/gpu/drm/drm_vram_helper_common.c
386 :doc: overview
387
388.. kernel-doc:: include/drm/drm_gem_vram_helper.h
389 :internal:
390
391GEM VRAM Helper Functions Reference
392-----------------------------------
393
394.. kernel-doc:: drivers/gpu/drm/drm_gem_vram_helper.c
395 :doc: overview
396
397.. kernel-doc:: include/drm/drm_gem_vram_helper.h
398 :internal:
399
400.. kernel-doc:: drivers/gpu/drm/drm_gem_vram_helper.c
401 :export:
402
403VRAM MM Helper Functions Reference
404----------------------------------
405
406.. kernel-doc:: drivers/gpu/drm/drm_vram_mm_helper.c
407 :doc: overview
408
409.. kernel-doc:: include/drm/drm_vram_mm_helper.h
410 :internal:
411
412.. kernel-doc:: drivers/gpu/drm/drm_vram_mm_helper.c
413 :export:
414
383VMA Offset Manager415VMA Offset Manager
384==================416==================
385 417
Documentation/gpu/drm-uapi.rst+6−4
@@ -85,16 +85,18 @@ leads to a few additional requirements: · 84 unmodified lines
85- The userspace side must be fully reviewed and tested to the standards of that85- The userspace side must be fully reviewed and tested to the standards of that
86 userspace project. For e.g. mesa this means piglit testcases and review on the86 userspace project. For e.g. mesa this means piglit testcases and review on the
87 mailing list. This is again to ensure that the new interface actually gets the87 mailing list. This is again to ensure that the new interface actually gets the
88 job done.88 job done. The userspace-side reviewer should also provide at least an
89 Acked-by on the kernel uAPI patch indicating that they've looked at how the
90 kernel side is implementing the new feature being used.
89 91
90- The userspace patches must be against the canonical upstream, not some vendor92- The userspace patches must be against the canonical upstream, not some vendor
91 fork. This is to make sure that no one cheats on the review and testing93 fork. This is to make sure that no one cheats on the review and testing
92 requirements by doing a quick fork.94 requirements by doing a quick fork.
93 95
94- The kernel patch can only be merged after all the above requirements are met,96- The kernel patch can only be merged after all the above requirements are met,
95 but it **must** be merged **before** the userspace patches land. uAPI always flows97 but it **must** be merged to either drm-next or drm-misc-next **before** the
96 from the kernel, doing things the other way round risks divergence of the uAPI98 userspace patches land. uAPI always flows from the kernel, doing things the
97 definitions and header files.99 other way round risks divergence of the uAPI definitions and header files.
98 100
99These are fairly steep requirements, but have grown out from years of shared101These are fairly steep requirements, but have grown out from years of shared
100pain and experience with uAPI added hastily, and almost always regretted about102pain and experience with uAPI added hastily, and almost always regretted about
Documentation/gpu/todo.rst+8−19
@@ -10,25 +10,6 @@ graphics subsystem useful as newbie projects. Or for slow rainy days. · 9 unmodified lines
10Subsystem-wide refactorings10Subsystem-wide refactorings
11===========================11===========================
12 12
13De-midlayer drivers
14-------------------
15
16With the recent ``drm_bus`` cleanup patches for 3.17 it is no longer required
17to have a ``drm_bus`` structure set up. Drivers can directly set up the
18``drm_device`` structure instead of relying on bus methods in ``drm_usb.c``
19and ``drm_pci.c``. The goal is to get rid of the driver's ``->load`` /
20``->unload`` callbacks and open-code the load/unload sequence properly, using
21the new two-stage ``drm_device`` setup/teardown.
22
23Once all existing drivers are converted we can also remove those bus support
24files for USB and platform devices.
25
26All you need is a GPU for a non-converted driver (currently almost all of
27them, but also all the virtual ones used by KVM, so everyone qualifies).
28
29Contact: Daniel Vetter, Thierry Reding, respective driver maintainers
30
31
32Remove custom dumb_map_offset implementations13Remove custom dumb_map_offset implementations
33---------------------------------------------14---------------------------------------------
34 15
@@ -300,6 +281,14 @@ it to use drm_mode_hsync() instead. · 265 unmodified lines
300 281
301Contact: Sean Paul282Contact: Sean Paul
302 283
284drm_fb_helper tasks
285-------------------
286
287- drm_fb_helper_restore_fbdev_mode_unlocked() should call restore_fbdev_mode()
288 not the _force variant so it can bail out if there is a master. But first
289 these igt tests need to be fixed: kms_fbcon_fbt@psr and
290 kms_fbcon_fbt@psr-suspend.
291
303Core refactorings292Core refactorings
304=================293=================
305 294
MAINTAINERS+1−1
@@ -5413,6 +5413,7 @@ T: git git://anongit.freedesktop.org/drm/drm-misc · 5412 unmodified lines
5413 5413
5414DRM PANEL DRIVERS5414DRM PANEL DRIVERS
5415M: Thierry Reding <thierry.reding@gmail.com>5415M: Thierry Reding <thierry.reding@gmail.com>
5416R: Sam Ravnborg <sam@ravnborg.org>
5416L: dri-devel@lists.freedesktop.org5417L: dri-devel@lists.freedesktop.org
5417T: git git://anongit.freedesktop.org/drm/drm-misc5418T: git git://anongit.freedesktop.org/drm/drm-misc
5418S: Maintained5419S: Maintained
@@ -5441,7 +5442,6 @@ F: Documentation/gpu/xen-front.rst · 22 unmodified lines
5441DRM TTM SUBSYSTEM5442DRM TTM SUBSYSTEM
5442M: Christian Koenig <christian.koenig@amd.com>5443M: Christian Koenig <christian.koenig@amd.com>
5443M: Huang Rui <ray.huang@amd.com>5444M: Huang Rui <ray.huang@amd.com>
5444M: Junwei Zhang <Jerry.Zhang@amd.com>
5445T: git git://people.freedesktop.org/~agd5f/linux5445T: git git://people.freedesktop.org/~agd5f/linux
5446S: Maintained5446S: Maintained
5447L: dri-devel@lists.freedesktop.org5447L: dri-devel@lists.freedesktop.org
drivers/dma-buf/dma-buf.c+35−4
@@ -90,6 +90,10 @@ static int dma_buf_mmap_internal(struct file *file, struct vm_area_struct *vma) · 89 unmodified lines
90 90
91 dmabuf = file->private_data;91 dmabuf = file->private_data;
92 92
93 /* check if buffer supports mmap */
94 if (!dmabuf->ops->mmap)
95 return -EINVAL;
96
93 /* check for overflowing the buffer's size */97 /* check for overflowing the buffer's size */
94 if (vma->vm_pgoff + vma_pages(vma) >98 if (vma->vm_pgoff + vma_pages(vma) >
95 dmabuf->size >> PAGE_SHIFT)99 dmabuf->size >> PAGE_SHIFT)
@@ -404,8 +408,7 @@ struct dma_buf *dma_buf_export(const struct dma_buf_export_info *exp_info) · 308 unmodified lines
404 || !exp_info->ops408 || !exp_info->ops
405 || !exp_info->ops->map_dma_buf409 || !exp_info->ops->map_dma_buf
406 || !exp_info->ops->unmap_dma_buf410 || !exp_info->ops->unmap_dma_buf
407 || !exp_info->ops->release411 || !exp_info->ops->release)) {
408 || !exp_info->ops->mmap)) {
409 return ERR_PTR(-EINVAL);412 return ERR_PTR(-EINVAL);
410 }413 }
411 414
@@ -573,6 +576,7 @@ struct dma_buf_attachment *dma_buf_attach(struct dma_buf *dmabuf, · 161 unmodified lines
573 list_add(&attach->node, &dmabuf->attachments);576 list_add(&attach->node, &dmabuf->attachments);
574 577
575 mutex_unlock(&dmabuf->lock);578 mutex_unlock(&dmabuf->lock);
579
576 return attach;580 return attach;
577 581
578err_attach:582err_attach:
@@ -595,6 +599,9 @@ void dma_buf_detach(struct dma_buf *dmabuf, struct dma_buf_attachment *attach) · 16 unmodified lines
595 if (WARN_ON(!dmabuf || !attach))599 if (WARN_ON(!dmabuf || !attach))
596 return;600 return;
597 601
602 if (attach->sgt)
603 dmabuf->ops->unmap_dma_buf(attach, attach->sgt, attach->dir);
604
598 mutex_lock(&dmabuf->lock);605 mutex_lock(&dmabuf->lock);
599 list_del(&attach->node);606 list_del(&attach->node);
600 if (dmabuf->ops->detach)607 if (dmabuf->ops->detach)
@@ -630,10 +637,27 @@ struct sg_table *dma_buf_map_attachment(struct dma_buf_attachment *attach, · 29 unmodified lines
630 if (WARN_ON(!attach || !attach->dmabuf))637 if (WARN_ON(!attach || !attach->dmabuf))
631 return ERR_PTR(-EINVAL);638 return ERR_PTR(-EINVAL);
632 639
640 if (attach->sgt) {
641 /*
642 * Two mappings with different directions for the same
643 * attachment are not allowed.
644 */
645 if (attach->dir != direction &&
646 attach->dir != DMA_BIDIRECTIONAL)
647 return ERR_PTR(-EBUSY);
648
649 return attach->sgt;
650 }
651
633 sg_table = attach->dmabuf->ops->map_dma_buf(attach, direction);652 sg_table = attach->dmabuf->ops->map_dma_buf(attach, direction);
634 if (!sg_table)653 if (!sg_table)
635 sg_table = ERR_PTR(-ENOMEM);654 sg_table = ERR_PTR(-ENOMEM);
636 655
656 if (!IS_ERR(sg_table) && attach->dmabuf->ops->cache_sgt_mapping) {
657 attach->sgt = sg_table;
658 attach->dir = direction;
659 }
660
637 return sg_table;661 return sg_table;
638}662}
639EXPORT_SYMBOL_GPL(dma_buf_map_attachment);663EXPORT_SYMBOL_GPL(dma_buf_map_attachment);
@@ -657,8 +681,10 @@ void dma_buf_unmap_attachment(struct dma_buf_attachment *attach, · 17 unmodified lines
657 if (WARN_ON(!attach || !attach->dmabuf || !sg_table))681 if (WARN_ON(!attach || !attach->dmabuf || !sg_table))
658 return;682 return;
659 683
660 attach->dmabuf->ops->unmap_dma_buf(attach, sg_table,684 if (attach->sgt == sg_table)
661 direction);685 return;
686
687 attach->dmabuf->ops->unmap_dma_buf(attach, sg_table, direction);
662}688}
663EXPORT_SYMBOL_GPL(dma_buf_unmap_attachment);689EXPORT_SYMBOL_GPL(dma_buf_unmap_attachment);
664 690
@@ -906,6 +932,10 @@ int dma_buf_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma, · 241 unmodified lines
906 if (WARN_ON(!dmabuf || !vma))932 if (WARN_ON(!dmabuf || !vma))
907 return -EINVAL;933 return -EINVAL;
908 934
935 /* check if buffer supports mmap */
936 if (!dmabuf->ops->mmap)
937 return -EINVAL;
938
909 /* check for offset overflow */939 /* check for offset overflow */
910 if (pgoff + vma_pages(vma) < pgoff)940 if (pgoff + vma_pages(vma) < pgoff)
911 return -EOVERFLOW;941 return -EOVERFLOW;
@@ -1068,6 +1098,7 @@ static int dma_buf_debug_show(struct seq_file *s, void *unused) · 156 unmodified lines
1068 fence->ops->get_driver_name(fence),1098 fence->ops->get_driver_name(fence),
1069 fence->ops->get_timeline_name(fence),1099 fence->ops->get_timeline_name(fence),
1070 dma_fence_is_signaled(fence) ? "" : "un");1100 dma_fence_is_signaled(fence) ? "" : "un");
1101 dma_fence_put(fence);
1071 }1102 }
1072 rcu_read_unlock();1103 rcu_read_unlock();
1073 1104
drivers/dma-buf/sync_debug.c+0−26
@@ -197,29 +197,3 @@ static __init int sync_debugfs_init(void) · 196 unmodified lines
197 return 0;197 return 0;
198}198}
199late_initcall(sync_debugfs_init);199late_initcall(sync_debugfs_init);
200
201#define DUMP_CHUNK 256
202static char sync_dump_buf[64 * 1024];
203void sync_dump(void)
204{
205 struct seq_file s = {
206 .buf = sync_dump_buf,
207 .size = sizeof(sync_dump_buf) - 1,
208 };
209 int i;
210
211 sync_info_debugfs_show(&s, NULL);
212
213 for (i = 0; i < s.count; i += DUMP_CHUNK) {
214 if ((s.count - i) > DUMP_CHUNK) {
215 char c = s.buf[i + DUMP_CHUNK];
216
217 s.buf[i + DUMP_CHUNK] = 0;
218 pr_cont("%s", s.buf + i);
219 s.buf[i + DUMP_CHUNK] = c;
220 } else {
221 s.buf[s.count] = 0;
222 pr_cont("%s", s.buf + i);
223 }
224 }
225}
drivers/dma-buf/sync_debug.h+0−1
@@ -68,6 +68,5 @@ void sync_timeline_debug_add(struct sync_timeline *obj); · 67 unmodified lines
68void sync_timeline_debug_remove(struct sync_timeline *obj);68void sync_timeline_debug_remove(struct sync_timeline *obj);
69void sync_file_debug_add(struct sync_file *fence);69void sync_file_debug_add(struct sync_file *fence);
70void sync_file_debug_remove(struct sync_file *fence);70void sync_file_debug_remove(struct sync_file *fence);
71void sync_dump(void);
72 71
73#endif /* _LINUX_SYNC_H */72#endif /* _LINUX_SYNC_H */
drivers/gpu/drm/Kconfig+7−0
@@ -161,6 +161,13 @@ config DRM_TTM · 160 unmodified lines
161 GPU memory types. Will be enabled automatically if a device driver161 GPU memory types. Will be enabled automatically if a device driver
162 uses it.162 uses it.
163 163
164config DRM_VRAM_HELPER
165 tristate
166 depends on DRM
167 select DRM_TTM
168 help
169 Helpers for VRAM memory management
170
164config DRM_GEM_CMA_HELPER171config DRM_GEM_CMA_HELPER
165 bool172 bool
166 depends on DRM173 depends on DRM
drivers/gpu/drm/Makefile+5−0
@@ -32,6 +32,11 @@ drm-$(CONFIG_AGP) += drm_agpsupport.o · 31 unmodified lines
32drm-$(CONFIG_DEBUG_FS) += drm_debugfs.o drm_debugfs_crc.o32drm-$(CONFIG_DEBUG_FS) += drm_debugfs.o drm_debugfs_crc.o
33drm-$(CONFIG_DRM_LOAD_EDID_FIRMWARE) += drm_edid_load.o33drm-$(CONFIG_DRM_LOAD_EDID_FIRMWARE) += drm_edid_load.o
34 34
35drm_vram_helper-y := drm_gem_vram_helper.o \
36 drm_vram_helper_common.o \
37 drm_vram_mm_helper.o
38obj-$(CONFIG_DRM_VRAM_HELPER) += drm_vram_helper.o
39
35drm_kms_helper-y := drm_crtc_helper.o drm_dp_helper.o drm_dsc.o drm_probe_helper.o \40drm_kms_helper-y := drm_crtc_helper.o drm_dp_helper.o drm_dsc.o drm_probe_helper.o \
36 drm_plane_helper.o drm_dp_mst_topology.o drm_atomic_helper.o \41 drm_plane_helper.o drm_dp_mst_topology.o drm_atomic_helper.o \
37 drm_kms_helper_common.o drm_dp_dual_mode_helper.o \42 drm_kms_helper_common.o drm_dp_dual_mode_helper.o \
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c+95−51
@@ -3341,8 +3341,6 @@ static int amdgpu_device_pre_asic_reset(struct amdgpu_device *adev, · 3340 unmodified lines
3341 if (!ring || !ring->sched.thread)3341 if (!ring || !ring->sched.thread)
3342 continue;3342 continue;
3343 3343
3344 drm_sched_stop(&ring->sched);
3345
3346 /* after all hw jobs are reset, hw fence is meaningless, so force_completion */3344 /* after all hw jobs are reset, hw fence is meaningless, so force_completion */
3347 amdgpu_fence_driver_force_completion(ring);3345 amdgpu_fence_driver_force_completion(ring);
3348 }3346 }
@@ -3350,8 +3348,7 @@ static int amdgpu_device_pre_asic_reset(struct amdgpu_device *adev, · 1 unmodified line
3350 if(job)3348 if(job)
3351 drm_sched_increase_karma(&job->base);3349 drm_sched_increase_karma(&job->base);
3352 3350
3353 3351 /* Don't suspend on bare metal if we are not going to HW reset the ASIC */
3354
3355 if (!amdgpu_sriov_vf(adev)) {3352 if (!amdgpu_sriov_vf(adev)) {
3356 3353
3357 if (!need_full_reset)3354 if (!need_full_reset)
@@ -3489,38 +3486,21 @@ end: · 131 unmodified lines
3489 return r;3486 return r;
3490}3487}
3491 3488
3492static void amdgpu_device_post_asic_reset(struct amdgpu_device *adev,3489static bool amdgpu_device_lock_adev(struct amdgpu_device *adev, bool trylock)
3493 struct amdgpu_job *job)
3494{3490{
3495 int i;3491 if (trylock) {
3496 3492 if (!mutex_trylock(&adev->lock_reset))
3497 for (i = 0; i < AMDGPU_MAX_RINGS; ++i) {3493 return false;
3498 struct amdgpu_ring *ring = adev->rings[i];3494 } else
3499 3495 mutex_lock(&adev->lock_reset);
3500 if (!ring || !ring->sched.thread)
3501 continue;
3502 3496
3503 if (!adev->asic_reset_res)
3504 drm_sched_resubmit_jobs(&ring->sched);
3505
3506 drm_sched_start(&ring->sched, !adev->asic_reset_res);
3507 }
3508
3509 if (!amdgpu_device_has_dc_support(adev)) {
3510 drm_helper_resume_force_mode(adev->ddev);
3511 }
3512
3513 adev->asic_reset_res = 0;
3514}
3515
3516static void amdgpu_device_lock_adev(struct amdgpu_device *adev)
3517{
3518 mutex_lock(&adev->lock_reset);
3519 atomic_inc(&adev->gpu_reset_counter);3497 atomic_inc(&adev->gpu_reset_counter);
3520 adev->in_gpu_reset = 1;3498 adev->in_gpu_reset = 1;
3521 /* Block kfd: SRIOV would do it separately */3499 /* Block kfd: SRIOV would do it separately */
3522 if (!amdgpu_sriov_vf(adev))3500 if (!amdgpu_sriov_vf(adev))
3523 amdgpu_amdkfd_pre_reset(adev);3501 amdgpu_amdkfd_pre_reset(adev);
3502
3503 return true;
3524}3504}
3525 3505
3526static void amdgpu_device_unlock_adev(struct amdgpu_device *adev)3506static void amdgpu_device_unlock_adev(struct amdgpu_device *adev)
@@ -3548,40 +3528,42 @@ static void amdgpu_device_unlock_adev(struct amdgpu_device *adev) · 21 unmodified lines
3548int amdgpu_device_gpu_recover(struct amdgpu_device *adev,3528int amdgpu_device_gpu_recover(struct amdgpu_device *adev,
3549 struct amdgpu_job *job)3529 struct amdgpu_job *job)
3550{3530{
3551 int r;3531 struct list_head device_list, *device_list_handle = NULL;
3532 bool need_full_reset, job_signaled;
3552 struct amdgpu_hive_info *hive = NULL;3533 struct amdgpu_hive_info *hive = NULL;
3553 bool need_full_reset = false;
3554 struct amdgpu_device *tmp_adev = NULL;3534 struct amdgpu_device *tmp_adev = NULL;
3555 struct list_head device_list, *device_list_handle = NULL;3535 int i, r = 0;
3556 3536
3537 need_full_reset = job_signaled = false;
3557 INIT_LIST_HEAD(&device_list);3538 INIT_LIST_HEAD(&device_list);
3558 3539
3559 dev_info(adev->dev, "GPU reset begin!\n");3540 dev_info(adev->dev, "GPU reset begin!\n");
3560 3541
3542 hive = amdgpu_get_xgmi_hive(adev, false);
3543
3561 /*3544 /*
3562 * In case of XGMI hive disallow concurrent resets to be triggered3545 * Here we trylock to avoid chain of resets executing from
3563 * by different nodes. No point also since the one node already executing3546 * either trigger by jobs on different adevs in XGMI hive or jobs on
3564 * reset will also reset all the other nodes in the hive.3547 * different schedulers for same device while this TO handler is running.
3548 * We always reset all schedulers for device and all devices for XGMI
3549 * hive so that should take care of them too.
3565 */3550 */
3566 hive = amdgpu_get_xgmi_hive(adev, 0);3551
3567 if (hive && adev->gmc.xgmi.num_physical_nodes > 1 &&3552 if (hive && !mutex_trylock(&hive->reset_lock)) {
3568 !mutex_trylock(&hive->reset_lock))3553 DRM_INFO("Bailing on TDR for s_job:%llx, hive: %llx as another already in progress",
3554 job->base.id, hive->hive_id);
3569 return 0;3555 return 0;
3556 }
3570 3557
3571 /* Start with adev pre asic reset first for soft reset check.*/3558 /* Start with adev pre asic reset first for soft reset check.*/
3572 amdgpu_device_lock_adev(adev);3559 if (!amdgpu_device_lock_adev(adev, !hive)) {
3573 r = amdgpu_device_pre_asic_reset(adev,3560 DRM_INFO("Bailing on TDR for s_job:%llx, as another already in progress",
3574 job,3561 job->base.id);
3575 &need_full_reset);3562 return 0;
3576 if (r) {
3577 /*TODO Should we stop ?*/
3578 DRM_ERROR("GPU pre asic reset failed with err, %d for drm dev, %s ",
3579 r, adev->ddev->unique);
3580 adev->asic_reset_res = r;
3581 }3563 }
3582 3564
3583 /* Build list of devices to reset */3565 /* Build list of devices to reset */
3584 if (need_full_reset && adev->gmc.xgmi.num_physical_nodes > 1) {3566 if (adev->gmc.xgmi.num_physical_nodes > 1) {
3585 if (!hive) {3567 if (!hive) {
3586 amdgpu_device_unlock_adev(adev);3568 amdgpu_device_unlock_adev(adev);
3587 return -ENODEV;3569 return -ENODEV;
@@ -3598,13 +3580,56 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev, · 10 unmodified lines
3598 device_list_handle = &device_list;3580 device_list_handle = &device_list;
3599 }3581 }
3600 3582
3583 /* block all schedulers and reset given job's ring */
3584 list_for_each_entry(tmp_adev, device_list_handle, gmc.xgmi.head) {
3585 for (i = 0; i < AMDGPU_MAX_RINGS; ++i) {
3586 struct amdgpu_ring *ring = tmp_adev->rings[i];
3587
3588 if (!ring || !ring->sched.thread)
3589 continue;
3590
3591 drm_sched_stop(&ring->sched, &job->base);
3592 }
3593 }
3594
3595
3596 /*
3597 * Must check guilty signal here since after this point all old
3598 * HW fences are force signaled.
3599 *
3600 * job->base holds a reference to parent fence
3601 */
3602 if (job && job->base.s_fence->parent &&
3603 dma_fence_is_signaled(job->base.s_fence->parent))
3604 job_signaled = true;
3605
3606 if (!amdgpu_device_ip_need_full_reset(adev))
3607 device_list_handle = &device_list;
3608
3609 if (job_signaled) {
3610 dev_info(adev->dev, "Guilty job already signaled, skipping HW reset");
3611 goto skip_hw_reset;
3612 }
3613
3614
3615 /* Guilty job will be freed after this*/
3616 r = amdgpu_device_pre_asic_reset(adev,
3617 job,
3618 &need_full_reset);
3619 if (r) {
3620 /*TODO Should we stop ?*/
3621 DRM_ERROR("GPU pre asic reset failed with err, %d for drm dev, %s ",
3622 r, adev->ddev->unique);
3623 adev->asic_reset_res = r;
3624 }
3625
3601retry: /* Rest of adevs pre asic reset from XGMI hive. */3626retry: /* Rest of adevs pre asic reset from XGMI hive. */
3602 list_for_each_entry(tmp_adev, device_list_handle, gmc.xgmi.head) {3627 list_for_each_entry(tmp_adev, device_list_handle, gmc.xgmi.head) {
3603 3628
3604 if (tmp_adev == adev)3629 if (tmp_adev == adev)
3605 continue;3630 continue;
3606 3631
3607 amdgpu_device_lock_adev(tmp_adev);3632 amdgpu_device_lock_adev(tmp_adev, false);
3608 r = amdgpu_device_pre_asic_reset(tmp_adev,3633 r = amdgpu_device_pre_asic_reset(tmp_adev,
3609 NULL,3634 NULL,
3610 &need_full_reset);3635 &need_full_reset);
@@ -3628,9 +3653,28 @@ retry: /* Rest of adevs pre asic reset from XGMI hive. */ · 17 unmodified lines
3628 goto retry;3653 goto retry;
3629 }3654 }
3630 3655
3656skip_hw_reset:
3657
3631 /* Post ASIC reset for all devs .*/3658 /* Post ASIC reset for all devs .*/
3632 list_for_each_entry(tmp_adev, device_list_handle, gmc.xgmi.head) {3659 list_for_each_entry(tmp_adev, device_list_handle, gmc.xgmi.head) {
3633 amdgpu_device_post_asic_reset(tmp_adev, tmp_adev == adev ? job : NULL);3660 for (i = 0; i < AMDGPU_MAX_RINGS; ++i) {
3661 struct amdgpu_ring *ring = tmp_adev->rings[i];
3662
3663 if (!ring || !ring->sched.thread)
3664 continue;
3665
3666 /* No point to resubmit jobs if we didn't HW reset*/
3667 if (!tmp_adev->asic_reset_res && !job_signaled)
3668 drm_sched_resubmit_jobs(&ring->sched);
3669
3670 drm_sched_start(&ring->sched, !tmp_adev->asic_reset_res);
3671 }
3672
3673 if (!amdgpu_device_has_dc_support(tmp_adev) && !job_signaled) {
3674 drm_helper_resume_force_mode(tmp_adev->ddev);
3675 }
3676
3677 tmp_adev->asic_reset_res = 0;
3634 3678
3635 if (r) {3679 if (r) {
3636 /* bad news, how to tell it to userspace ? */3680 /* bad news, how to tell it to userspace ? */
@@ -3643,7 +3687,7 @@ retry: /* Rest of adevs pre asic reset from XGMI hive. */ · 6 unmodified lines
3643 amdgpu_device_unlock_adev(tmp_adev);3687 amdgpu_device_unlock_adev(tmp_adev);
3644 }3688 }
3645 3689
3646 if (hive && adev->gmc.xgmi.num_physical_nodes > 1)3690 if (hive)
3647 mutex_unlock(&hive->reset_lock);3691 mutex_unlock(&hive->reset_lock);
3648 3692
3649 if (r)3693 if (r)
drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c+3−1
@@ -121,6 +121,7 @@ static int amdgpufb_create_pinned_object(struct amdgpu_fbdev *rfbdev, · 120 unmodified lines
121 struct drm_mode_fb_cmd2 *mode_cmd,121 struct drm_mode_fb_cmd2 *mode_cmd,
122 struct drm_gem_object **gobj_p)122 struct drm_gem_object **gobj_p)
123{123{
124 const struct drm_format_info *info;
124 struct amdgpu_device *adev = rfbdev->adev;125 struct amdgpu_device *adev = rfbdev->adev;
125 struct drm_gem_object *gobj = NULL;126 struct drm_gem_object *gobj = NULL;
126 struct amdgpu_bo *abo = NULL;127 struct amdgpu_bo *abo = NULL;
@@ -131,7 +132,8 @@ static int amdgpufb_create_pinned_object(struct amdgpu_fbdev *rfbdev, · 4 unmodified lines
131 int height = mode_cmd->height;132 int height = mode_cmd->height;
132 u32 cpp;133 u32 cpp;
133 134
134 cpp = drm_format_plane_cpp(mode_cmd->pixel_format, 0);135 info = drm_get_format_info(adev->ddev, mode_cmd);
136 cpp = info->cpp[0];
135 137
136 /* need to align pitch with crtc limits */138 /* need to align pitch with crtc limits */
137 mode_cmd->pitches[0] = amdgpu_align_pitch(adev, mode_cmd->width, cpp,139 mode_cmd->pitches[0] = amdgpu_align_pitch(adev, mode_cmd->width, cpp,
drivers/gpu/drm/arm/malidp_crtc.c+11−17
@@ -463,23 +463,6 @@ static struct drm_crtc_state *malidp_crtc_duplicate_state(struct drm_crtc *crtc) · 462 unmodified lines
463 return &state->base;463 return &state->base;
464}464}
465 465
466static void malidp_crtc_reset(struct drm_crtc *crtc)
467{
468 struct malidp_crtc_state *state = NULL;
469
470 if (crtc->state) {
471 state = to_malidp_crtc_state(crtc->state);
472 __drm_atomic_helper_crtc_destroy_state(crtc->state);
473 }
474
475 kfree(state);
476 state = kzalloc(sizeof(*state), GFP_KERNEL);
477 if (state) {
478 crtc->state = &state->base;
479 crtc->state->crtc = crtc;
480 }
481}
482
483static void malidp_crtc_destroy_state(struct drm_crtc *crtc,466static void malidp_crtc_destroy_state(struct drm_crtc *crtc,
484 struct drm_crtc_state *state)467 struct drm_crtc_state *state)
485{468{
@@ -493,6 +476,17 @@ static void malidp_crtc_destroy_state(struct drm_crtc *crtc, · 7 unmodified lines
493 kfree(mali_state);476 kfree(mali_state);
494}477}
495 478
479static void malidp_crtc_reset(struct drm_crtc *crtc)
480{
481 struct malidp_crtc_state *state =
482 kzalloc(sizeof(*state), GFP_KERNEL);
483
484 if (crtc->state)
485 malidp_crtc_destroy_state(crtc, crtc->state);
486
487 __drm_atomic_helper_crtc_reset(crtc, &state->base);
488}
489
496static int malidp_crtc_enable_vblank(struct drm_crtc *crtc)490static int malidp_crtc_enable_vblank(struct drm_crtc *crtc)
497{491{
498 struct malidp_drm *malidp = crtc_to_malidp_device(crtc);492 struct malidp_drm *malidp = crtc_to_malidp_device(crtc);
drivers/gpu/drm/arm/malidp_hw.c+2−1
@@ -382,7 +382,8 @@ static void malidp500_modeset(struct malidp_hw_device *hwdev, struct videomode * · 381 unmodified lines
382 382
383int malidp_format_get_bpp(u32 fmt)383int malidp_format_get_bpp(u32 fmt)
384{384{
385 int bpp = drm_format_plane_cpp(fmt, 0) * 8;385 const struct drm_format_info *info = drm_format_info(fmt);
386 int bpp = info->cpp[0] * 8;
386 387
387 if (bpp == 0) {388 if (bpp == 0) {
388 switch (fmt) {389 switch (fmt) {
drivers/gpu/drm/arm/malidp_mw.c+1−1
@@ -158,7 +158,7 @@ malidp_mw_encoder_atomic_check(struct drm_encoder *encoder, · 157 unmodified lines
158 return -EINVAL;158 return -EINVAL;
159 }159 }
160 160
161 n_planes = drm_format_num_planes(fb->format->format);161 n_planes = fb->format->num_planes;
162 for (i = 0; i < n_planes; i++) {162 for (i = 0; i < n_planes; i++) {
163 struct drm_gem_cma_object *obj = drm_fb_cma_get_gem_obj(fb, i);163 struct drm_gem_cma_object *obj = drm_fb_cma_get_gem_obj(fb, i);
164 /* memory write buffers are never rotated */164 /* memory write buffers are never rotated */
drivers/gpu/drm/arm/malidp_planes.c+3−5
@@ -227,14 +227,13 @@ bool malidp_format_mod_supported(struct drm_device *drm, · 226 unmodified lines
227 227
228 if (modifier & AFBC_SPLIT) {228 if (modifier & AFBC_SPLIT) {
229 if (!info->is_yuv) {229 if (!info->is_yuv) {
230 if (drm_format_plane_cpp(format, 0) <= 2) {230 if (info->cpp[0] <= 2) {
231 DRM_DEBUG_KMS("RGB formats <= 16bpp are not supported with SPLIT\n");231 DRM_DEBUG_KMS("RGB formats <= 16bpp are not supported with SPLIT\n");
232 return false;232 return false;
233 }233 }
234 }234 }
235 235
236 if ((drm_format_horz_chroma_subsampling(format) != 1) ||236 if ((info->hsub != 1) || (info->vsub != 1)) {
237 (drm_format_vert_chroma_subsampling(format) != 1)) {
238 if (!(format == DRM_FORMAT_YUV420_10BIT &&237 if (!(format == DRM_FORMAT_YUV420_10BIT &&
239 (map->features & MALIDP_DEVICE_AFBC_YUV_420_10_SUPPORT_SPLIT))) {238 (map->features & MALIDP_DEVICE_AFBC_YUV_420_10_SUPPORT_SPLIT))) {
240 DRM_DEBUG_KMS("Formats which are sub-sampled should never be split\n");239 DRM_DEBUG_KMS("Formats which are sub-sampled should never be split\n");
@@ -244,8 +243,7 @@ bool malidp_format_mod_supported(struct drm_device *drm, · 3 unmodified lines
244 }243 }
245 244
246 if (modifier & AFBC_CBR) {245 if (modifier & AFBC_CBR) {
247 if ((drm_format_horz_chroma_subsampling(format) == 1) ||246 if ((info->hsub == 1) || (info->vsub == 1)) {
248 (drm_format_vert_chroma_subsampling(format) == 1)) {
249 DRM_DEBUG_KMS("Formats which are not sub-sampled should not have CBR set\n");247 DRM_DEBUG_KMS("Formats which are not sub-sampled should not have CBR set\n");
250 return false;248 return false;
251 }249 }
drivers/gpu/drm/armada/armada_fb.c+2−1
@@ -87,6 +87,7 @@ struct armada_framebuffer *armada_framebuffer_create(struct drm_device *dev, · 86 unmodified lines
87struct drm_framebuffer *armada_fb_create(struct drm_device *dev,87struct drm_framebuffer *armada_fb_create(struct drm_device *dev,
88 struct drm_file *dfile, const struct drm_mode_fb_cmd2 *mode)88 struct drm_file *dfile, const struct drm_mode_fb_cmd2 *mode)
89{89{
90 const struct drm_format_info *info = drm_get_format_info(dev, mode);
90 struct armada_gem_object *obj;91 struct armada_gem_object *obj;
91 struct armada_framebuffer *dfb;92 struct armada_framebuffer *dfb;
92 int ret;93 int ret;
@@ -97,7 +98,7 @@ struct drm_framebuffer *armada_fb_create(struct drm_device *dev, · 4 unmodified lines
97 mode->pitches[2]);98 mode->pitches[2]);
98 99
99 /* We can only handle a single plane at the moment */100 /* We can only handle a single plane at the moment */
100 if (drm_format_num_planes(mode->pixel_format) > 1 &&101 if (info->num_planes > 1 &&
101 (mode->handles[0] != mode->handles[1] ||102 (mode->handles[0] != mode->handles[1] ||
102 mode->handles[0] != mode->handles[2])) {103 mode->handles[0] != mode->handles[2])) {
103 ret = -EINVAL;104 ret = -EINVAL;
drivers/gpu/drm/ast/Kconfig+1−2
@@ -2,9 +2,8 @@ · 1 unmodified line
2config DRM_AST2config DRM_AST
3 tristate "AST server chips"3 tristate "AST server chips"
4 depends on DRM && PCI && MMU4 depends on DRM && PCI && MMU
5 select DRM_TTM
6 select DRM_KMS_HELPER5 select DRM_KMS_HELPER
7 select DRM_TTM6 select DRM_VRAM_HELPER
8 help7 help
9 Say yes for experimental AST GPU driver. Do not enable8 Say yes for experimental AST GPU driver. Do not enable
10 this driver without having a working -modesetting,9 this driver without having a working -modesetting,
drivers/gpu/drm/ast/ast_drv.c+2−11
@@ -205,13 +205,7 @@ static struct pci_driver ast_pci_driver = { · 204 unmodified lines
205 205
206static const struct file_operations ast_fops = {206static const struct file_operations ast_fops = {
207 .owner = THIS_MODULE,207 .owner = THIS_MODULE,
208 .open = drm_open,208 DRM_VRAM_MM_FILE_OPERATIONS
209 .release = drm_release,
210 .unlocked_ioctl = drm_ioctl,
211 .mmap = ast_mmap,
212 .poll = drm_poll,
213 .compat_ioctl = drm_compat_ioctl,
214 .read = drm_read,
215};209};
216 210
217static struct drm_driver driver = {211static struct drm_driver driver = {
@@ -228,10 +222,7 @@ static struct drm_driver driver = { · 10 unmodified lines
228 .minor = DRIVER_MINOR,222 .minor = DRIVER_MINOR,
229 .patchlevel = DRIVER_PATCHLEVEL,223 .patchlevel = DRIVER_PATCHLEVEL,
230 224
231 .gem_free_object_unlocked = ast_gem_free_object,225 DRM_GEM_VRAM_DRIVER
232 .dumb_create = ast_dumb_create,
233 .dumb_map_offset = ast_dumb_mmap_offset,
234
235};226};
236 227
237static int __init ast_init(void)228static int __init ast_init(void)
drivers/gpu/drm/ast/ast_drv.h+3−68
@@ -31,13 +31,10 @@ · 30 unmodified lines
31#include <drm/drm_encoder.h>31#include <drm/drm_encoder.h>
32#include <drm/drm_fb_helper.h>32#include <drm/drm_fb_helper.h>
33 33
34#include <drm/ttm/ttm_bo_api.h>
35#include <drm/ttm/ttm_bo_driver.h>
36#include <drm/ttm/ttm_placement.h>
37#include <drm/ttm/ttm_memory.h>
38#include <drm/ttm/ttm_module.h>
39
40#include <drm/drm_gem.h>34#include <drm/drm_gem.h>
35#include <drm/drm_gem_vram_helper.h>
36
37#include <drm/drm_vram_mm_helper.h>
41 38
42#include <linux/i2c.h>39#include <linux/i2c.h>
43#include <linux/i2c-algo-bit.h>40#include <linux/i2c-algo-bit.h>
@@ -103,10 +100,6 @@ struct ast_private { · 59 unmodified lines
103 100
104 int fb_mtrr;101 int fb_mtrr;
105 102
106 struct {
107 struct ttm_bo_device bdev;
108 } ttm;
109
110 struct drm_gem_object *cursor_cache;103 struct drm_gem_object *cursor_cache;
111 uint64_t cursor_cache_gpu_addr;104 uint64_t cursor_cache_gpu_addr;
112 /* Acces to this cache is protected by the crtc->mutex of the only crtc105 /* Acces to this cache is protected by the crtc->mutex of the only crtc
@@ -263,7 +256,6 @@ struct ast_fbdev { · 150 unmodified lines
263 struct ast_framebuffer afb;256 struct ast_framebuffer afb;
264 void *sysram;257 void *sysram;
265 int size;258 int size;
266 struct ttm_bo_kmap_obj mapping;
267 int x1, y1, x2, y2; /* dirty rect */259 int x1, y1, x2, y2; /* dirty rect */
268 spinlock_t dirty_lock;260 spinlock_t dirty_lock;
269};261};
@@ -321,73 +313,16 @@ void ast_fbdev_fini(struct drm_device *dev); · 51 unmodified lines
321void ast_fbdev_set_suspend(struct drm_device *dev, int state);313void ast_fbdev_set_suspend(struct drm_device *dev, int state);
322void ast_fbdev_set_base(struct ast_private *ast, unsigned long gpu_addr);314void ast_fbdev_set_base(struct ast_private *ast, unsigned long gpu_addr);
323 315
324struct ast_bo {
325 struct ttm_buffer_object bo;
326 struct ttm_placement placement;
327 struct ttm_bo_kmap_obj kmap;
328 struct drm_gem_object gem;
329 struct ttm_place placements[3];
330 int pin_count;
331};
332#define gem_to_ast_bo(gobj) container_of((gobj), struct ast_bo, gem)
333
334static inline struct ast_bo *
335ast_bo(struct ttm_buffer_object *bo)
336{
337 return container_of(bo, struct ast_bo, bo);
338}
339
340
341#define to_ast_obj(x) container_of(x, struct ast_gem_object, base)
342
343#define AST_MM_ALIGN_SHIFT 4316#define AST_MM_ALIGN_SHIFT 4
344#define AST_MM_ALIGN_MASK ((1 << AST_MM_ALIGN_SHIFT) - 1)317#define AST_MM_ALIGN_MASK ((1 << AST_MM_ALIGN_SHIFT) - 1)
345 318
346extern int ast_dumb_create(struct drm_file *file,
347 struct drm_device *dev,
348 struct drm_mode_create_dumb *args);
349
350extern void ast_gem_free_object(struct drm_gem_object *obj);
351extern int ast_dumb_mmap_offset(struct drm_file *file,
352 struct drm_device *dev,
353 uint32_t handle,
354 uint64_t *offset);
355
356int ast_mm_init(struct ast_private *ast);319int ast_mm_init(struct ast_private *ast);
357void ast_mm_fini(struct ast_private *ast);320void ast_mm_fini(struct ast_private *ast);
358 321
359int ast_bo_create(struct drm_device *dev, int size, int align,
360 uint32_t flags, struct ast_bo **pastbo);
361
362int ast_gem_create(struct drm_device *dev,322int ast_gem_create(struct drm_device *dev,
363 u32 size, bool iskernel,323 u32 size, bool iskernel,
364 struct drm_gem_object **obj);324 struct drm_gem_object **obj);
365 325
366int ast_bo_pin(struct ast_bo *bo, u32 pl_flag, u64 *gpu_addr);
367int ast_bo_unpin(struct ast_bo *bo);
368
369static inline int ast_bo_reserve(struct ast_bo *bo, bool no_wait)
370{
371 int ret;
372
373 ret = ttm_bo_reserve(&bo->bo, true, no_wait, NULL);
374 if (ret) {
375 if (ret != -ERESTARTSYS && ret != -EBUSY)
376 DRM_ERROR("reserve failed %p\n", bo);
377 return ret;
378 }
379 return 0;
380}
381
382static inline void ast_bo_unreserve(struct ast_bo *bo)
383{
384 ttm_bo_unreserve(&bo->bo);
385}
386
387void ast_ttm_placement(struct ast_bo *bo, int domain);
388int ast_bo_push_sysram(struct ast_bo *bo);
389int ast_mmap(struct file *filp, struct vm_area_struct *vma);
390
391/* ast post */326/* ast post */
392void ast_enable_vga(struct drm_device *dev);327void ast_enable_vga(struct drm_device *dev);
393void ast_enable_mmio(struct drm_device *dev);328void ast_enable_mmio(struct drm_device *dev);
drivers/gpu/drm/ast/ast_fb.c+24−17
@@ -49,25 +49,25 @@ static void ast_dirty_update(struct ast_fbdev *afbdev, · 48 unmodified lines
49{49{
50 int i;50 int i;
51 struct drm_gem_object *obj;51 struct drm_gem_object *obj;
52 struct ast_bo *bo;52 struct drm_gem_vram_object *gbo;
53 int src_offset, dst_offset;53 int src_offset, dst_offset;
54 int bpp = afbdev->afb.base.format->cpp[0];54 int bpp = afbdev->afb.base.format->cpp[0];
55 int ret = -EBUSY;55 int ret = -EBUSY;
56 u8 *dst;
56 bool unmap = false;57 bool unmap = false;
57 bool store_for_later = false;58 bool store_for_later = false;
58 int x2, y2;59 int x2, y2;
59 unsigned long flags;60 unsigned long flags;
60 61
61 obj = afbdev->afb.obj;62 obj = afbdev->afb.obj;
62 bo = gem_to_ast_bo(obj);63 gbo = drm_gem_vram_of_gem(obj);
63 64
64 /*65 /* Try to lock the BO. If we fail with -EBUSY then
65 * try and reserve the BO, if we fail with busy66 * the BO is being moved and we should store up the
66 * then the BO is being moved and we should67 * damage until later.
67 * store up the damage until later.
68 */68 */
69 if (drm_can_sleep())69 if (drm_can_sleep())
70 ret = ast_bo_reserve(bo, true);70 ret = drm_gem_vram_lock(gbo, true);
71 if (ret) {71 if (ret) {
72 if (ret != -EBUSY)72 if (ret != -EBUSY)
73 return;73 return;
@@ -101,25 +101,32 @@ static void ast_dirty_update(struct ast_fbdev *afbdev, · 27 unmodified lines
101 afbdev->x2 = afbdev->y2 = 0;101 afbdev->x2 = afbdev->y2 = 0;
102 spin_unlock_irqrestore(&afbdev->dirty_lock, flags);102 spin_unlock_irqrestore(&afbdev->dirty_lock, flags);
103 103
104 if (!bo->kmap.virtual) {104 dst = drm_gem_vram_kmap(gbo, false, NULL);
105 ret = ttm_bo_kmap(&bo->bo, 0, bo->bo.num_pages, &bo->kmap);105 if (IS_ERR(dst)) {
106 if (ret) {106 DRM_ERROR("failed to kmap fb updates\n");
107 goto out;
108 } else if (!dst) {
109 dst = drm_gem_vram_kmap(gbo, true, NULL);
110 if (IS_ERR(dst)) {
107 DRM_ERROR("failed to kmap fb updates\n");111 DRM_ERROR("failed to kmap fb updates\n");
108 ast_bo_unreserve(bo);112 goto out;
109 return;
110 }113 }
111 unmap = true;114 unmap = true;
112 }115 }
116
113 for (i = y; i <= y2; i++) {117 for (i = y; i <= y2; i++) {
114 /* assume equal stride for now */118 /* assume equal stride for now */
115 src_offset = dst_offset = i * afbdev->afb.base.pitches[0] + (x * bpp);119 src_offset = dst_offset =
116 memcpy_toio(bo->kmap.virtual + src_offset, afbdev->sysram + src_offset, (x2 - x + 1) * bpp);120 i * afbdev->afb.base.pitches[0] + (x * bpp);
117 121 memcpy_toio(dst + dst_offset, afbdev->sysram + src_offset,
122 (x2 - x + 1) * bpp);
118 }123 }
124
119 if (unmap)125 if (unmap)
120 ttm_bo_kunmap(&bo->kmap);126 drm_gem_vram_kunmap(gbo);
121 127
122 ast_bo_unreserve(bo);128out:
129 drm_gem_vram_unlock(gbo);
123}130}
124 131
125static void ast_fillrect(struct fb_info *info,132static void ast_fillrect(struct fb_info *info,
drivers/gpu/drm/ast/ast_main.c+5−72
@@ -593,7 +593,7 @@ int ast_gem_create(struct drm_device *dev, · 592 unmodified lines
593 u32 size, bool iskernel,593 u32 size, bool iskernel,
594 struct drm_gem_object **obj)594 struct drm_gem_object **obj)
595{595{
596 struct ast_bo *astbo;596 struct drm_gem_vram_object *gbo;
597 int ret;597 int ret;
598 598
599 *obj = NULL;599 *obj = NULL;
@@ -602,80 +602,13 @@ int ast_gem_create(struct drm_device *dev, · 2 unmodified lines
602 if (size == 0)602 if (size == 0)
603 return -EINVAL;603 return -EINVAL;
604 604
605 ret = ast_bo_create(dev, size, 0, 0, &astbo);605 gbo = drm_gem_vram_create(dev, &dev->vram_mm->bdev, size, 0, false);
606 if (ret) {606 if (IS_ERR(gbo)) {
607 ret = PTR_ERR(gbo);
607 if (ret != -ERESTARTSYS)608 if (ret != -ERESTARTSYS)
608 DRM_ERROR("failed to allocate GEM object\n");609 DRM_ERROR("failed to allocate GEM object\n");
609 return ret;610 return ret;
610 }611 }
611 *obj = &astbo->gem;612 *obj = &gbo->gem;
612 return 0;613 return 0;
613}614}
614
615int ast_dumb_create(struct drm_file *file,
616 struct drm_device *dev,
617 struct drm_mode_create_dumb *args)
618{
619 int ret;
620 struct drm_gem_object *gobj;
621 u32 handle;
622
623 args->pitch = args->width * ((args->bpp + 7) / 8);
624 args->size = args->pitch * args->height;
625
626 ret = ast_gem_create(dev, args->size, false,
627 &gobj);
628 if (ret)
629 return ret;
630
631 ret = drm_gem_handle_create(file, gobj, &handle);
632 drm_gem_object_put_unlocked(gobj);
633 if (ret)
634 return ret;
635
636 args->handle = handle;
637 return 0;
638}
639
640static void ast_bo_unref(struct ast_bo **bo)
641{
642 if ((*bo) == NULL)
643 return;
644 ttm_bo_put(&((*bo)->bo));
645 *bo = NULL;
646}
647
648void ast_gem_free_object(struct drm_gem_object *obj)
649{
650 struct ast_bo *ast_bo = gem_to_ast_bo(obj);
651
652 ast_bo_unref(&ast_bo);
653}
654
655
656static inline u64 ast_bo_mmap_offset(struct ast_bo *bo)
657{
658 return drm_vma_node_offset_addr(&bo->bo.vma_node);
659}
660int
661ast_dumb_mmap_offset(struct drm_file *file,
662 struct drm_device *dev,
663 uint32_t handle,
664 uint64_t *offset)
665{
666 struct drm_gem_object *obj;
667 struct ast_bo *bo;
668
669 obj = drm_gem_object_lookup(file, handle);
670 if (obj == NULL)
671 return -ENOENT;
672
673 bo = gem_to_ast_bo(obj);
674 *offset = ast_bo_mmap_offset(bo);
675
676 drm_gem_object_put_unlocked(obj);
677
678 return 0;
679
680}
681
drivers/gpu/drm/ast/ast_mode.c+77−55
@@ -521,7 +521,6 @@ static void ast_crtc_dpms(struct drm_crtc *crtc, int mode) · 520 unmodified lines
521 }521 }
522}522}
523 523
524/* ast is different - we will force move buffers out of VRAM */
525static int ast_crtc_do_set_base(struct drm_crtc *crtc,524static int ast_crtc_do_set_base(struct drm_crtc *crtc,
526 struct drm_framebuffer *fb,525 struct drm_framebuffer *fb,
527 int x, int y, int atomic)526 int x, int y, int atomic)
@@ -529,50 +528,54 @@ static int ast_crtc_do_set_base(struct drm_crtc *crtc, · 1 unmodified line
529 struct ast_private *ast = crtc->dev->dev_private;528 struct ast_private *ast = crtc->dev->dev_private;
530 struct drm_gem_object *obj;529 struct drm_gem_object *obj;
531 struct ast_framebuffer *ast_fb;530 struct ast_framebuffer *ast_fb;
532 struct ast_bo *bo;531 struct drm_gem_vram_object *gbo;
533 int ret;532 int ret;
534 u64 gpu_addr;533 s64 gpu_addr;
534 void *base;
535 535
536 /* push the previous fb to system ram */
537 if (!atomic && fb) {536 if (!atomic && fb) {
538 ast_fb = to_ast_framebuffer(fb);537 ast_fb = to_ast_framebuffer(fb);
539 obj = ast_fb->obj;538 obj = ast_fb->obj;
540 bo = gem_to_ast_bo(obj);539 gbo = drm_gem_vram_of_gem(obj);
541 ret = ast_bo_reserve(bo, false);540
542 if (ret)541 /* unmap if console */
543 return ret;542 if (&ast->fbdev->afb == ast_fb)
544 ast_bo_push_sysram(bo);543 drm_gem_vram_kunmap(gbo);
545 ast_bo_unreserve(bo);544 drm_gem_vram_unpin(gbo);
546 }545 }
547 546
548 ast_fb = to_ast_framebuffer(crtc->primary->fb);547 ast_fb = to_ast_framebuffer(crtc->primary->fb);
549 obj = ast_fb->obj;548 obj = ast_fb->obj;
550 bo = gem_to_ast_bo(obj);549 gbo = drm_gem_vram_of_gem(obj);
551 550
552 ret = ast_bo_reserve(bo, false);551 ret = drm_gem_vram_pin(gbo, DRM_GEM_VRAM_PL_FLAG_VRAM);
553 if (ret)552 if (ret)
554 return ret;553 return ret;
555 554 gpu_addr = drm_gem_vram_offset(gbo);
556 ret = ast_bo_pin(bo, TTM_PL_FLAG_VRAM, &gpu_addr);555 if (gpu_addr < 0) {
557 if (ret) {556 ret = (int)gpu_addr;
558 ast_bo_unreserve(bo);557 goto err_drm_gem_vram_unpin;
559 return ret;
560 }558 }
561 559
562 if (&ast->fbdev->afb == ast_fb) {560 if (&ast->fbdev->afb == ast_fb) {
563 /* if pushing console in kmap it */561 /* if pushing console in kmap it */
564 ret = ttm_bo_kmap(&bo->bo, 0, bo->bo.num_pages, &bo->kmap);562 base = drm_gem_vram_kmap(gbo, true, NULL);
565 if (ret)563 if (IS_ERR(base)) {
564 ret = PTR_ERR(base);
566 DRM_ERROR("failed to kmap fbcon\n");565 DRM_ERROR("failed to kmap fbcon\n");
567 else566 } else {
568 ast_fbdev_set_base(ast, gpu_addr);567 ast_fbdev_set_base(ast, gpu_addr);
568 }
569 }569 }
570 ast_bo_unreserve(bo);
571 570
572 ast_set_offset_reg(crtc);571 ast_set_offset_reg(crtc);
573 ast_set_start_address_crt1(crtc, (u32)gpu_addr);572 ast_set_start_address_crt1(crtc, (u32)gpu_addr);
574 573
575 return 0;574 return 0;
575
576err_drm_gem_vram_unpin:
577 drm_gem_vram_unpin(gbo);
578 return ret;
576}579}
577 580
578static int ast_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,581static int ast_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
@@ -618,21 +621,18 @@ static int ast_crtc_mode_set(struct drm_crtc *crtc, · 39 unmodified lines
618 621
619static void ast_crtc_disable(struct drm_crtc *crtc)622static void ast_crtc_disable(struct drm_crtc *crtc)
620{623{
621 int ret;
622
623 DRM_DEBUG_KMS("\n");624 DRM_DEBUG_KMS("\n");
624 ast_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);625 ast_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
625 if (crtc->primary->fb) {626 if (crtc->primary->fb) {
627 struct ast_private *ast = crtc->dev->dev_private;
626 struct ast_framebuffer *ast_fb = to_ast_framebuffer(crtc->primary->fb);628 struct ast_framebuffer *ast_fb = to_ast_framebuffer(crtc->primary->fb);
627 struct drm_gem_object *obj = ast_fb->obj;629 struct drm_gem_object *obj = ast_fb->obj;
628 struct ast_bo *bo = gem_to_ast_bo(obj);630 struct drm_gem_vram_object *gbo = drm_gem_vram_of_gem(obj);
629
630 ret = ast_bo_reserve(bo, false);
631 if (ret)
632 return;
633 631
634 ast_bo_push_sysram(bo);632 /* unmap if console */
635 ast_bo_unreserve(bo);633 if (&ast->fbdev->afb == ast_fb)
634 drm_gem_vram_kunmap(gbo);
635 drm_gem_vram_unpin(gbo);
636 }636 }
637 crtc->primary->fb = NULL;637 crtc->primary->fb = NULL;
638}638}
@@ -918,28 +918,32 @@ static int ast_cursor_init(struct drm_device *dev) · 279 unmodified lines
918 int size;918 int size;
919 int ret;919 int ret;
920 struct drm_gem_object *obj;920 struct drm_gem_object *obj;
921 struct ast_bo *bo;921 struct drm_gem_vram_object *gbo;
922 uint64_t gpu_addr;922 s64 gpu_addr;
923 void *base;
923 924
924 size = (AST_HWC_SIZE + AST_HWC_SIGNATURE_SIZE) * AST_DEFAULT_HWC_NUM;925 size = (AST_HWC_SIZE + AST_HWC_SIGNATURE_SIZE) * AST_DEFAULT_HWC_NUM;
925 926
926 ret = ast_gem_create(dev, size, true, &obj);927 ret = ast_gem_create(dev, size, true, &obj);
927 if (ret)928 if (ret)
928 return ret;929 return ret;
929 bo = gem_to_ast_bo(obj);930 gbo = drm_gem_vram_of_gem(obj);
930 ret = ast_bo_reserve(bo, false);931 ret = drm_gem_vram_pin(gbo, DRM_GEM_VRAM_PL_FLAG_VRAM);
931 if (unlikely(ret != 0))
932 goto fail;
933
934 ret = ast_bo_pin(bo, TTM_PL_FLAG_VRAM, &gpu_addr);
935 ast_bo_unreserve(bo);
936 if (ret)932 if (ret)
937 goto fail;933 goto fail;
934 gpu_addr = drm_gem_vram_offset(gbo);
935 if (gpu_addr < 0) {
936 drm_gem_vram_unpin(gbo);
937 ret = (int)gpu_addr;
938 goto fail;
939 }
938 940
939 /* kmap the object */941 /* kmap the object */
940 ret = ttm_bo_kmap(&bo->bo, 0, bo->bo.num_pages, &ast->cache_kmap);942 base = drm_gem_vram_kmap_at(gbo, true, NULL, &ast->cache_kmap);
941 if (ret)943 if (IS_ERR(base)) {
944 ret = PTR_ERR(base);
942 goto fail;945 goto fail;
946 }
943 947
944 ast->cursor_cache = obj;948 ast->cursor_cache = obj;
945 ast->cursor_cache_gpu_addr = gpu_addr;949 ast->cursor_cache_gpu_addr = gpu_addr;
@@ -952,7 +956,9 @@ fail: · 6 unmodified lines
952static void ast_cursor_fini(struct drm_device *dev)956static void ast_cursor_fini(struct drm_device *dev)
953{957{
954 struct ast_private *ast = dev->dev_private;958 struct ast_private *ast = dev->dev_private;
955 ttm_bo_kunmap(&ast->cache_kmap);959 struct drm_gem_vram_object *gbo =
960 drm_gem_vram_of_gem(ast->cursor_cache);
961 drm_gem_vram_kunmap_at(gbo, &ast->cache_kmap);
956 drm_gem_object_put_unlocked(ast->cursor_cache);962 drm_gem_object_put_unlocked(ast->cursor_cache);
957}963}
958 964
@@ -1173,8 +1179,8 @@ static int ast_cursor_set(struct drm_crtc *crtc, · 214 unmodified lines
1173 struct ast_private *ast = crtc->dev->dev_private;1179 struct ast_private *ast = crtc->dev->dev_private;
1174 struct ast_crtc *ast_crtc = to_ast_crtc(crtc);1180 struct ast_crtc *ast_crtc = to_ast_crtc(crtc);
1175 struct drm_gem_object *obj;1181 struct drm_gem_object *obj;
1176 struct ast_bo *bo;1182 struct drm_gem_vram_object *gbo;
1177 uint64_t gpu_addr;1183 s64 gpu_addr;
1178 u32 csum;1184 u32 csum;
1179 int ret;1185 int ret;
1180 struct ttm_bo_kmap_obj uobj_map;1186 struct ttm_bo_kmap_obj uobj_map;
@@ -1193,19 +1199,27 @@ static int ast_cursor_set(struct drm_crtc *crtc, · 12 unmodified lines
1193 DRM_ERROR("Cannot find cursor object %x for crtc\n", handle);1199 DRM_ERROR("Cannot find cursor object %x for crtc\n", handle);
1194 return -ENOENT;1200 return -ENOENT;
1195 }1201 }
1196 bo = gem_to_ast_bo(obj);1202 gbo = drm_gem_vram_of_gem(obj);
1197 1203
1198 ret = ast_bo_reserve(bo, false);1204 ret = drm_gem_vram_lock(gbo, false);
1199 if (ret)1205 if (ret)
1200 goto fail;1206 goto fail;
1201 1207
1202 ret = ttm_bo_kmap(&bo->bo, 0, bo->bo.num_pages, &uobj_map);1208 memset(&uobj_map, 0, sizeof(uobj_map));
1203 1209 src = drm_gem_vram_kmap_at(gbo, true, &src_isiomem, &uobj_map);
1204 src = ttm_kmap_obj_virtual(&uobj_map, &src_isiomem);1210 if (IS_ERR(src)) {
1205 dst = ttm_kmap_obj_virtual(&ast->cache_kmap, &dst_isiomem);1211 ret = PTR_ERR(src);
1206 1212 goto fail_unlock;
1213 }
1207 if (src_isiomem == true)1214 if (src_isiomem == true)
1208 DRM_ERROR("src cursor bo should be in main memory\n");1215 DRM_ERROR("src cursor bo should be in main memory\n");
1216
1217 dst = drm_gem_vram_kmap_at(drm_gem_vram_of_gem(ast->cursor_cache),
1218 false, &dst_isiomem, &ast->cache_kmap);
1219 if (IS_ERR(dst)) {
1220 ret = PTR_ERR(dst);
1221 goto fail_unlock;
1222 }
1209 if (dst_isiomem == false)1223 if (dst_isiomem == false)
1210 DRM_ERROR("dst bo should be in VRAM\n");1224 DRM_ERROR("dst bo should be in VRAM\n");
1211 1225
@@ -1214,11 +1228,14 @@ static int ast_cursor_set(struct drm_crtc *crtc, · 2 unmodified lines
1214 /* do data transfer to cursor cache */1228 /* do data transfer to cursor cache */
1215 csum = copy_cursor_image(src, dst, width, height);1229 csum = copy_cursor_image(src, dst, width, height);
1216 1230
1231 drm_gem_vram_kunmap_at(gbo, &uobj_map);
1232 drm_gem_vram_unlock(gbo);
1233
1217 /* write checksum + signature */1234 /* write checksum + signature */
1218 ttm_bo_kunmap(&uobj_map);
1219 ast_bo_unreserve(bo);
1220 {1235 {
1221 u8 *dst = (u8 *)ast->cache_kmap.virtual + (AST_HWC_SIZE + AST_HWC_SIGNATURE_SIZE)*ast->next_cursor + AST_HWC_SIZE;1236 u8 *dst = drm_gem_vram_kmap_at(drm_gem_vram_of_gem(ast->cursor_cache),
1237 false, NULL, &ast->cache_kmap);
1238 dst += (AST_HWC_SIZE + AST_HWC_SIGNATURE_SIZE)*ast->next_cursor + AST_HWC_SIZE;
1222 writel(csum, dst);1239 writel(csum, dst);
1223 writel(width, dst + AST_HWC_SIGNATURE_SizeX);1240 writel(width, dst + AST_HWC_SIGNATURE_SizeX);
1224 writel(height, dst + AST_HWC_SIGNATURE_SizeY);1241 writel(height, dst + AST_HWC_SIGNATURE_SizeY);
@@ -1244,6 +1261,9 @@ static int ast_cursor_set(struct drm_crtc *crtc, · 19 unmodified lines
1244 1261
1245 drm_gem_object_put_unlocked(obj);1262 drm_gem_object_put_unlocked(obj);
1246 return 0;1263 return 0;
1264
1265fail_unlock:
1266 drm_gem_vram_unlock(gbo);
1247fail:1267fail:
1248 drm_gem_object_put_unlocked(obj);1268 drm_gem_object_put_unlocked(obj);
1249 return ret;1269 return ret;
@@ -1257,7 +1277,9 @@ static int ast_cursor_move(struct drm_crtc *crtc, · 7 unmodified lines
1257 int x_offset, y_offset;1277 int x_offset, y_offset;
1258 u8 *sig;1278 u8 *sig;
1259 1279
1260 sig = (u8 *)ast->cache_kmap.virtual + (AST_HWC_SIZE + AST_HWC_SIGNATURE_SIZE)*ast->next_cursor + AST_HWC_SIZE;1280 sig = drm_gem_vram_kmap_at(drm_gem_vram_of_gem(ast->cursor_cache),
1281 false, NULL, &ast->cache_kmap);
1282 sig += (AST_HWC_SIZE + AST_HWC_SIGNATURE_SIZE)*ast->next_cursor + AST_HWC_SIZE;
1261 writel(x, sig + AST_HWC_SIGNATURE_X);1283 writel(x, sig + AST_HWC_SIGNATURE_X);
1262 writel(y, sig + AST_HWC_SIGNATURE_Y);1284 writel(y, sig + AST_HWC_SIGNATURE_Y);
1263 1285
drivers/gpu/drm/ast/ast_ttm.c+8−294
@@ -26,168 +26,21 @@ · 25 unmodified lines
26 * Authors: Dave Airlie <airlied@redhat.com>26 * Authors: Dave Airlie <airlied@redhat.com>
27 */27 */
28#include <drm/drmP.h>28#include <drm/drmP.h>
29#include <drm/ttm/ttm_page_alloc.h>
30 29
31#include "ast_drv.h"30#include "ast_drv.h"
32 31
33static inline struct ast_private *
34ast_bdev(struct ttm_bo_device *bd)
35{
36 return container_of(bd, struct ast_private, ttm.bdev);
37}
38
39static void ast_bo_ttm_destroy(struct ttm_buffer_object *tbo)
40{
41 struct ast_bo *bo;
42
43 bo = container_of(tbo, struct ast_bo, bo);
44
45 drm_gem_object_release(&bo->gem);
46 kfree(bo);
47}
48
49static bool ast_ttm_bo_is_ast_bo(struct ttm_buffer_object *bo)
50{
51 if (bo->destroy == &ast_bo_ttm_destroy)
52 return true;
53 return false;
54}
55
56static int
57ast_bo_init_mem_type(struct ttm_bo_device *bdev, uint32_t type,
58 struct ttm_mem_type_manager *man)
59{
60 switch (type) {
61 case TTM_PL_SYSTEM:
62 man->flags = TTM_MEMTYPE_FLAG_MAPPABLE;
63 man->available_caching = TTM_PL_MASK_CACHING;
64 man->default_caching = TTM_PL_FLAG_CACHED;
65 break;
66 case TTM_PL_VRAM:
67 man->func = &ttm_bo_manager_func;
68 man->flags = TTM_MEMTYPE_FLAG_FIXED |
69 TTM_MEMTYPE_FLAG_MAPPABLE;
70 man->available_caching = TTM_PL_FLAG_UNCACHED |
71 TTM_PL_FLAG_WC;
72 man->default_caching = TTM_PL_FLAG_WC;
73 break;
74 default:
75 DRM_ERROR("Unsupported memory type %u\n", (unsigned)type);
76 return -EINVAL;
77 }
78 return 0;
79}
80
81static void
82ast_bo_evict_flags(struct ttm_buffer_object *bo, struct ttm_placement *pl)
83{
84 struct ast_bo *astbo = ast_bo(bo);
85
86 if (!ast_ttm_bo_is_ast_bo(bo))
87 return;
88
89 ast_ttm_placement(astbo, TTM_PL_FLAG_SYSTEM);
90 *pl = astbo->placement;
91}
92
93static int ast_bo_verify_access(struct ttm_buffer_object *bo, struct file *filp)
94{
95 struct ast_bo *astbo = ast_bo(bo);
96
97 return drm_vma_node_verify_access(&astbo->gem.vma_node,
98 filp->private_data);
99}
100
101static int ast_ttm_io_mem_reserve(struct ttm_bo_device *bdev,
102 struct ttm_mem_reg *mem)
103{
104 struct ttm_mem_type_manager *man = &bdev->man[mem->mem_type];
105 struct ast_private *ast = ast_bdev(bdev);
106
107 mem->bus.addr = NULL;
108 mem->bus.offset = 0;
109 mem->bus.size = mem->num_pages << PAGE_SHIFT;
110 mem->bus.base = 0;
111 mem->bus.is_iomem = false;
112 if (!(man->flags & TTM_MEMTYPE_FLAG_MAPPABLE))
113 return -EINVAL;
114 switch (mem->mem_type) {
115 case TTM_PL_SYSTEM:
116 /* system memory */
117 return 0;
118 case TTM_PL_VRAM:
119 mem->bus.offset = mem->start << PAGE_SHIFT;
120 mem->bus.base = pci_resource_start(ast->dev->pdev, 0);
121 mem->bus.is_iomem = true;
122 break;
123 default:
124 return -EINVAL;
125 break;
126 }
127 return 0;
128}
129
130static void ast_ttm_io_mem_free(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem)
131{
132}
133
134static void ast_ttm_backend_destroy(struct ttm_tt *tt)
135{
136 ttm_tt_fini(tt);
137 kfree(tt);
138}
139
140static struct ttm_backend_func ast_tt_backend_func = {
141 .destroy = &ast_ttm_backend_destroy,
142};
143
144
145static struct ttm_tt *ast_ttm_tt_create(struct ttm_buffer_object *bo,
146 uint32_t page_flags)
147{
148 struct ttm_tt *tt;
149
150 tt = kzalloc(sizeof(struct ttm_tt), GFP_KERNEL);
151 if (tt == NULL)
152 return NULL;
153 tt->func = &ast_tt_backend_func;
154 if (ttm_tt_init(tt, bo, page_flags)) {
155 kfree(tt);
156 return NULL;
157 }
158 return tt;
159}
160
161struct ttm_bo_driver ast_bo_driver = {
162 .ttm_tt_create = ast_ttm_tt_create,
163 .init_mem_type = ast_bo_init_mem_type,
164 .eviction_valuable = ttm_bo_eviction_valuable,
165 .evict_flags = ast_bo_evict_flags,
166 .move = NULL,
167 .verify_access = ast_bo_verify_access,
168 .io_mem_reserve = &ast_ttm_io_mem_reserve,
169 .io_mem_free = &ast_ttm_io_mem_free,
170};
171
172int ast_mm_init(struct ast_private *ast)32int ast_mm_init(struct ast_private *ast)
173{33{
34 struct drm_vram_mm *vmm;
174 int ret;35 int ret;
175 struct drm_device *dev = ast->dev;36 struct drm_device *dev = ast->dev;
176 struct ttm_bo_device *bdev = &ast->ttm.bdev;
177
178 ret = ttm_bo_device_init(&ast->ttm.bdev,
179 &ast_bo_driver,
180 dev->anon_inode->i_mapping,
181 true);
182 if (ret) {
183 DRM_ERROR("Error initialising bo driver; %d\n", ret);
184 return ret;
185 }
186 37
187 ret = ttm_bo_init_mm(bdev, TTM_PL_VRAM,38 vmm = drm_vram_helper_alloc_mm(
188 ast->vram_size >> PAGE_SHIFT);39 dev, pci_resource_start(dev->pdev, 0),
189 if (ret) {40 ast->vram_size, &drm_gem_vram_mm_funcs);
190 DRM_ERROR("Failed ttm VRAM init: %d\n", ret);41 if (IS_ERR(vmm)) {
42 ret = PTR_ERR(vmm);
43 DRM_ERROR("Error initializing VRAM MM; %d\n", ret);
191 return ret;44 return ret;
192 }45 }
193 46
@@ -203,148 +56,9 @@ void ast_mm_fini(struct ast_private *ast) · 9 unmodified lines
203{56{
204 struct drm_device *dev = ast->dev;57 struct drm_device *dev = ast->dev;
205 58
206 ttm_bo_device_release(&ast->ttm.bdev);59 drm_vram_helper_release_mm(dev);
207 60
208 arch_phys_wc_del(ast->fb_mtrr);61 arch_phys_wc_del(ast->fb_mtrr);
209 arch_io_free_memtype_wc(pci_resource_start(dev->pdev, 0),62 arch_io_free_memtype_wc(pci_resource_start(dev->pdev, 0),
210 pci_resource_len(dev->pdev, 0));63 pci_resource_len(dev->pdev, 0));
211}64}
212
213void ast_ttm_placement(struct ast_bo *bo, int domain)
214{
215 u32 c = 0;
216 unsigned i;
217
218 bo->placement.placement = bo->placements;
219 bo->placement.busy_placement = bo->placements;
220 if (domain & TTM_PL_FLAG_VRAM)
221 bo->placements[c++].flags = TTM_PL_FLAG_WC | TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_VRAM;
222 if (domain & TTM_PL_FLAG_SYSTEM)
223 bo->placements[c++].flags = TTM_PL_FLAG_CACHED | TTM_PL_FLAG_SYSTEM;
224 if (!c)
225 bo->placements[c++].flags = TTM_PL_FLAG_CACHED | TTM_PL_FLAG_SYSTEM;
226 bo->placement.num_placement = c;
227 bo->placement.num_busy_placement = c;
228 for (i = 0; i < c; ++i) {
229 bo->placements[i].fpfn = 0;
230 bo->placements[i].lpfn = 0;
231 }
232}
233
234int ast_bo_create(struct drm_device *dev, int size, int align,
235 uint32_t flags, struct ast_bo **pastbo)
236{
237 struct ast_private *ast = dev->dev_private;
238 struct ast_bo *astbo;
239 size_t acc_size;
240 int ret;
241
242 astbo = kzalloc(sizeof(struct ast_bo), GFP_KERNEL);
243 if (!astbo)
244 return -ENOMEM;
245
246 ret = drm_gem_object_init(dev, &astbo->gem, size);
247 if (ret)
248 goto error;
249
250 astbo->bo.bdev = &ast->ttm.bdev;
251
252 ast_ttm_placement(astbo, TTM_PL_FLAG_VRAM | TTM_PL_FLAG_SYSTEM);
253
254 acc_size = ttm_bo_dma_acc_size(&ast->ttm.bdev, size,
255 sizeof(struct ast_bo));
256
257 ret = ttm_bo_init(&ast->ttm.bdev, &astbo->bo, size,
258 ttm_bo_type_device, &astbo->placement,
259 align >> PAGE_SHIFT, false, acc_size,
260 NULL, NULL, ast_bo_ttm_destroy);
261 if (ret)
262 goto error;
263
264 *pastbo = astbo;
265 return 0;
266error:
267 kfree(astbo);
268 return ret;
269}
270
271static inline u64 ast_bo_gpu_offset(struct ast_bo *bo)
272{
273 return bo->bo.offset;
274}
275
276int ast_bo_pin(struct ast_bo *bo, u32 pl_flag, u64 *gpu_addr)
277{
278 struct ttm_operation_ctx ctx = { false, false };
279 int i, ret;
280
281 if (bo->pin_count) {
282 bo->pin_count++;
283 if (gpu_addr)
284 *gpu_addr = ast_bo_gpu_offset(bo);
285 }
286
287 ast_ttm_placement(bo, pl_flag);
288 for (i = 0; i < bo->placement.num_placement; i++)
289 bo->placements[i].flags |= TTM_PL_FLAG_NO_EVICT;
290 ret = ttm_bo_validate(&bo->bo, &bo->placement, &ctx);
291 if (ret)
292 return ret;
293
294 bo->pin_count = 1;
295 if (gpu_addr)
296 *gpu_addr = ast_bo_gpu_offset(bo);
297 return 0;
298}
299
300int ast_bo_unpin(struct ast_bo *bo)
301{
302 struct ttm_operation_ctx ctx = { false, false };
303 int i;
304 if (!bo->pin_count) {
305 DRM_ERROR("unpin bad %p\n", bo);
306 return 0;
307 }
308 bo->pin_count--;
309 if (bo->pin_count)
310 return 0;
311
312 for (i = 0; i < bo->placement.num_placement ; i++)
313 bo->placements[i].flags &= ~TTM_PL_FLAG_NO_EVICT;
314 return ttm_bo_validate(&bo->bo, &bo->placement, &ctx);
315}
316
317int ast_bo_push_sysram(struct ast_bo *bo)
318{
319 struct ttm_operation_ctx ctx = { false, false };
320 int i, ret;
321 if (!bo->pin_count) {
322 DRM_ERROR("unpin bad %p\n", bo);
323 return 0;
324 }
325 bo->pin_count--;
326 if (bo->pin_count)
327 return 0;
328
329 if (bo->kmap.virtual)
330 ttm_bo_kunmap(&bo->kmap);
331
332 ast_ttm_placement(bo, TTM_PL_FLAG_SYSTEM);
333 for (i = 0; i < bo->placement.num_placement ; i++)
334 bo->placements[i].flags |= TTM_PL_FLAG_NO_EVICT;
335
336 ret = ttm_bo_validate(&bo->bo, &bo->placement, &ctx);
337 if (ret) {
338 DRM_ERROR("pushing to VRAM failed\n");
339 return ret;
340 }
341 return 0;
342}
343
344int ast_mmap(struct file *filp, struct vm_area_struct *vma)
345{
346 struct drm_file *file_priv = filp->private_data;
347 struct ast_private *ast = file_priv->minor->dev->dev_private;
348
349 return ttm_bo_mmap(filp, vma, &ast->ttm.bdev);
350}
drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c+2−7
@@ -603,8 +603,6 @@ static int atmel_hlcdc_plane_atomic_check(struct drm_plane *p, · 602 unmodified lines
603 const struct drm_display_mode *mode;603 const struct drm_display_mode *mode;
604 struct drm_crtc_state *crtc_state;604 struct drm_crtc_state *crtc_state;
605 unsigned int tmp;605 unsigned int tmp;
606 int hsub = 1;
607 int vsub = 1;
608 int ret;606 int ret;
609 int i;607 int i;
610 608
@@ -642,13 +640,10 @@ static int atmel_hlcdc_plane_atomic_check(struct drm_plane *p, · 31 unmodified lines
642 if (state->nplanes > ATMEL_HLCDC_LAYER_MAX_PLANES)640 if (state->nplanes > ATMEL_HLCDC_LAYER_MAX_PLANES)
643 return -EINVAL;641 return -EINVAL;
644 642
645 hsub = drm_format_horz_chroma_subsampling(fb->format->format);
646 vsub = drm_format_vert_chroma_subsampling(fb->format->format);
647
648 for (i = 0; i < state->nplanes; i++) {643 for (i = 0; i < state->nplanes; i++) {
649 unsigned int offset = 0;644 unsigned int offset = 0;
650 int xdiv = i ? hsub : 1;645 int xdiv = i ? fb->format->hsub : 1;
651 int ydiv = i ? vsub : 1;646 int ydiv = i ? fb->format->vsub : 1;
652 647
653 state->bpp[i] = fb->format->cpp[i];648 state->bpp[i] = fb->format->cpp[i];
654 if (!state->bpp[i])649 if (!state->bpp[i])
drivers/gpu/drm/bochs/Kconfig+1−1
@@ -3,7 +3,7 @@ config DRM_BOCHS · 2 unmodified lines
3 tristate "DRM Support for bochs dispi vga interface (qemu stdvga)"3 tristate "DRM Support for bochs dispi vga interface (qemu stdvga)"
4 depends on DRM && PCI && MMU4 depends on DRM && PCI && MMU
5 select DRM_KMS_HELPER5 select DRM_KMS_HELPER
6 select DRM_TTM6 select DRM_VRAM_HELPER
7 help7 help
8 Choose this option for qemu.8 Choose this option for qemu.
9 If M is selected the module will be called bochs-drm.9 If M is selected the module will be called bochs-drm.
drivers/gpu/drm/bochs/bochs.h+2−52
@@ -10,9 +10,9 @@ · 9 unmodified lines
10#include <drm/drm_simple_kms_helper.h>10#include <drm/drm_simple_kms_helper.h>
11 11
12#include <drm/drm_gem.h>12#include <drm/drm_gem.h>
13#include <drm/drm_gem_vram_helper.h>
13 14
14#include <drm/ttm/ttm_bo_driver.h>15#include <drm/drm_vram_mm_helper.h>
15#include <drm/ttm/ttm_page_alloc.h>
16 16
17/* ---------------------------------------------------------------------- */17/* ---------------------------------------------------------------------- */
18 18
@@ -73,38 +73,8 @@ struct bochs_device { · 54 unmodified lines
73 struct drm_device *dev;73 struct drm_device *dev;
74 struct drm_simple_display_pipe pipe;74 struct drm_simple_display_pipe pipe;
75 struct drm_connector connector;75 struct drm_connector connector;
76
77 /* ttm */
78 struct {
79 struct ttm_bo_device bdev;
80 bool initialized;
81 } ttm;
82};
83
84struct bochs_bo {
85 struct ttm_buffer_object bo;
86 struct ttm_placement placement;
87 struct ttm_bo_kmap_obj kmap;
88 struct drm_gem_object gem;
89 struct ttm_place placements[3];
90 int pin_count;
91};76};
92 77
93static inline struct bochs_bo *bochs_bo(struct ttm_buffer_object *bo)
94{
95 return container_of(bo, struct bochs_bo, bo);
96}
97
98static inline struct bochs_bo *gem_to_bochs_bo(struct drm_gem_object *gem)
99{
100 return container_of(gem, struct bochs_bo, gem);
101}
102
103static inline u64 bochs_bo_mmap_offset(struct bochs_bo *bo)
104{
105 return drm_vma_node_offset_addr(&bo->bo.vma_node);
106}
107
108/* ---------------------------------------------------------------------- */78/* ---------------------------------------------------------------------- */
109 79
110/* bochs_hw.c */80/* bochs_hw.c */
@@ -122,26 +92,6 @@ int bochs_hw_load_edid(struct bochs_device *bochs); · 11 unmodified lines
122/* bochs_mm.c */92/* bochs_mm.c */
123int bochs_mm_init(struct bochs_device *bochs);93int bochs_mm_init(struct bochs_device *bochs);
124void bochs_mm_fini(struct bochs_device *bochs);94void bochs_mm_fini(struct bochs_device *bochs);
125int bochs_mmap(struct file *filp, struct vm_area_struct *vma);
126
127int bochs_gem_create(struct drm_device *dev, u32 size, bool iskernel,
128 struct drm_gem_object **obj);
129int bochs_gem_init_object(struct drm_gem_object *obj);
130void bochs_gem_free_object(struct drm_gem_object *obj);
131int bochs_dumb_create(struct drm_file *file, struct drm_device *dev,
132 struct drm_mode_create_dumb *args);
133int bochs_dumb_mmap_offset(struct drm_file *file, struct drm_device *dev,
134 uint32_t handle, uint64_t *offset);
135
136int bochs_bo_pin(struct bochs_bo *bo, u32 pl_flag);
137int bochs_bo_unpin(struct bochs_bo *bo);
138
139int bochs_gem_prime_pin(struct drm_gem_object *obj);
140void bochs_gem_prime_unpin(struct drm_gem_object *obj);
141void *bochs_gem_prime_vmap(struct drm_gem_object *obj);
142void bochs_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr);
143int bochs_gem_prime_mmap(struct drm_gem_object *obj,
144 struct vm_area_struct *vma);
145 95
146/* bochs_kms.c */96/* bochs_kms.c */
147int bochs_kms_init(struct bochs_device *bochs);97int bochs_kms_init(struct bochs_device *bochs);
drivers/gpu/drm/bochs/bochs_drv.c+5−19
@@ -10,6 +10,7 @@ · 9 unmodified lines
10#include <linux/slab.h>10#include <linux/slab.h>
11#include <drm/drm_fb_helper.h>11#include <drm/drm_fb_helper.h>
12#include <drm/drm_probe_helper.h>12#include <drm/drm_probe_helper.h>
13#include <drm/drm_atomic_helper.h>
13 14
14#include "bochs.h"15#include "bochs.h"
15 16
@@ -63,14 +64,7 @@ err: · 47 unmodified lines
63 64
64static const struct file_operations bochs_fops = {65static const struct file_operations bochs_fops = {
65 .owner = THIS_MODULE,66 .owner = THIS_MODULE,
66 .open = drm_open,67 DRM_VRAM_MM_FILE_OPERATIONS
67 .release = drm_release,
68 .unlocked_ioctl = drm_ioctl,
69 .compat_ioctl = drm_compat_ioctl,
70 .poll = drm_poll,
71 .read = drm_read,
72 .llseek = no_llseek,
73 .mmap = bochs_mmap,
74};68};
75 69
76static struct drm_driver bochs_driver = {70static struct drm_driver bochs_driver = {
@@ -82,17 +76,8 @@ static struct drm_driver bochs_driver = { · 5 unmodified lines
82 .date = "20130925",76 .date = "20130925",
83 .major = 1,77 .major = 1,
84 .minor = 0,78 .minor = 0,
85 .gem_free_object_unlocked = bochs_gem_free_object,79 DRM_GEM_VRAM_DRIVER,
86 .dumb_create = bochs_dumb_create,80 DRM_GEM_VRAM_DRIVER_PRIME,
87 .dumb_map_offset = bochs_dumb_mmap_offset,
88
89 .gem_prime_export = drm_gem_prime_export,
90 .gem_prime_import = drm_gem_prime_import,
91 .gem_prime_pin = bochs_gem_prime_pin,
92 .gem_prime_unpin = bochs_gem_prime_unpin,
93 .gem_prime_vmap = bochs_gem_prime_vmap,
94 .gem_prime_vunmap = bochs_gem_prime_vunmap,
95 .gem_prime_mmap = bochs_gem_prime_mmap,
96};81};
97 82
98/* ---------------------------------------------------------------------- */83/* ---------------------------------------------------------------------- */
@@ -174,6 +159,7 @@ static void bochs_pci_remove(struct pci_dev *pdev) · 75 unmodified lines
174{159{
175 struct drm_device *dev = pci_get_drvdata(pdev);160 struct drm_device *dev = pci_get_drvdata(pdev);
176 161
162 drm_atomic_helper_shutdown(dev);
177 drm_dev_unregister(dev);163 drm_dev_unregister(dev);
178 bochs_unload(dev);164 bochs_unload(dev);
179 drm_dev_put(dev);165 drm_dev_put(dev);
drivers/gpu/drm/bochs/bochs_kms.c+9−9
@@ -30,16 +30,16 @@ static const uint32_t bochs_formats[] = { · 29 unmodified lines
30static void bochs_plane_update(struct bochs_device *bochs,30static void bochs_plane_update(struct bochs_device *bochs,
31 struct drm_plane_state *state)31 struct drm_plane_state *state)
32{32{
33 struct bochs_bo *bo;33 struct drm_gem_vram_object *gbo;
34 34
35 if (!state->fb || !bochs->stride)35 if (!state->fb || !bochs->stride)
36 return;36 return;
37 37
38 bo = gem_to_bochs_bo(state->fb->obj[0]);38 gbo = drm_gem_vram_of_gem(state->fb->obj[0]);
39 bochs_hw_setbase(bochs,39 bochs_hw_setbase(bochs,
40 state->crtc_x,40 state->crtc_x,
41 state->crtc_y,41 state->crtc_y,
42 bo->bo.offset);42 gbo->bo.offset);
43 bochs_hw_setformat(bochs, state->fb->format);43 bochs_hw_setformat(bochs, state->fb->format);
44}44}
45 45
@@ -72,23 +72,23 @@ static void bochs_pipe_update(struct drm_simple_display_pipe *pipe, · 26 unmodified lines
72static int bochs_pipe_prepare_fb(struct drm_simple_display_pipe *pipe,72static int bochs_pipe_prepare_fb(struct drm_simple_display_pipe *pipe,
73 struct drm_plane_state *new_state)73 struct drm_plane_state *new_state)
74{74{
75 struct bochs_bo *bo;75 struct drm_gem_vram_object *gbo;
76 76
77 if (!new_state->fb)77 if (!new_state->fb)
78 return 0;78 return 0;
79 bo = gem_to_bochs_bo(new_state->fb->obj[0]);79 gbo = drm_gem_vram_of_gem(new_state->fb->obj[0]);
80 return bochs_bo_pin(bo, TTM_PL_FLAG_VRAM);80 return drm_gem_vram_pin(gbo, DRM_GEM_VRAM_PL_FLAG_VRAM);
81}81}
82 82
83static void bochs_pipe_cleanup_fb(struct drm_simple_display_pipe *pipe,83static void bochs_pipe_cleanup_fb(struct drm_simple_display_pipe *pipe,
84 struct drm_plane_state *old_state)84 struct drm_plane_state *old_state)
85{85{
86 struct bochs_bo *bo;86 struct drm_gem_vram_object *gbo;
87 87
88 if (!old_state->fb)88 if (!old_state->fb)
89 return;89 return;
90 bo = gem_to_bochs_bo(old_state->fb->obj[0]);90 gbo = drm_gem_vram_of_gem(old_state->fb->obj[0]);
91 bochs_bo_unpin(bo);91 drm_gem_vram_unpin(gbo);
92}92}
93 93
94static const struct drm_simple_display_pipe_funcs bochs_pipe_funcs = {94static const struct drm_simple_display_pipe_funcs bochs_pipe_funcs = {
drivers/gpu/drm/bochs/bochs_mm.c+7−420
@@ -7,435 +7,22 @@ · 6 unmodified lines
7 7
8#include "bochs.h"8#include "bochs.h"
9 9
10static void bochs_ttm_placement(struct bochs_bo *bo, int domain);
11
12/* ---------------------------------------------------------------------- */10/* ---------------------------------------------------------------------- */
13 11
14static inline struct bochs_device *bochs_bdev(struct ttm_bo_device *bd)
15{
16 return container_of(bd, struct bochs_device, ttm.bdev);
17}
18
19static void bochs_bo_ttm_destroy(struct ttm_buffer_object *tbo)
20{
21 struct bochs_bo *bo;
22
23 bo = container_of(tbo, struct bochs_bo, bo);
24 drm_gem_object_release(&bo->gem);
25 kfree(bo);
26}
27
28static bool bochs_ttm_bo_is_bochs_bo(struct ttm_buffer_object *bo)
29{
30 if (bo->destroy == &bochs_bo_ttm_destroy)
31 return true;
32 return false;
33}
34
35static int bochs_bo_init_mem_type(struct ttm_bo_device *bdev, uint32_t type,
36 struct ttm_mem_type_manager *man)
37{
38 switch (type) {
39 case TTM_PL_SYSTEM:
40 man->flags = TTM_MEMTYPE_FLAG_MAPPABLE;
41 man->available_caching = TTM_PL_MASK_CACHING;
42 man->default_caching = TTM_PL_FLAG_CACHED;
43 break;
44 case TTM_PL_VRAM:
45 man->func = &ttm_bo_manager_func;
46 man->flags = TTM_MEMTYPE_FLAG_FIXED |
47 TTM_MEMTYPE_FLAG_MAPPABLE;
48 man->available_caching = TTM_PL_FLAG_UNCACHED |
49 TTM_PL_FLAG_WC;
50 man->default_caching = TTM_PL_FLAG_WC;
51 break;
52 default:
53 DRM_ERROR("Unsupported memory type %u\n", (unsigned)type);
54 return -EINVAL;
55 }
56 return 0;
57}
58
59static void
60bochs_bo_evict_flags(struct ttm_buffer_object *bo, struct ttm_placement *pl)
61{
62 struct bochs_bo *bochsbo = bochs_bo(bo);
63
64 if (!bochs_ttm_bo_is_bochs_bo(bo))
65 return;
66
67 bochs_ttm_placement(bochsbo, TTM_PL_FLAG_SYSTEM);
68 *pl = bochsbo->placement;
69}
70
71static int bochs_bo_verify_access(struct ttm_buffer_object *bo,
72 struct file *filp)
73{
74 struct bochs_bo *bochsbo = bochs_bo(bo);
75
76 return drm_vma_node_verify_access(&bochsbo->gem.vma_node,
77 filp->private_data);
78}
79
80static int bochs_ttm_io_mem_reserve(struct ttm_bo_device *bdev,
81 struct ttm_mem_reg *mem)
82{
83 struct ttm_mem_type_manager *man = &bdev->man[mem->mem_type];
84 struct bochs_device *bochs = bochs_bdev(bdev);
85
86 mem->bus.addr = NULL;
87 mem->bus.offset = 0;
88 mem->bus.size = mem->num_pages << PAGE_SHIFT;
89 mem->bus.base = 0;
90 mem->bus.is_iomem = false;
91 if (!(man->flags & TTM_MEMTYPE_FLAG_MAPPABLE))
92 return -EINVAL;
93 switch (mem->mem_type) {
94 case TTM_PL_SYSTEM:
95 /* system memory */
96 return 0;
97 case TTM_PL_VRAM:
98 mem->bus.offset = mem->start << PAGE_SHIFT;
99 mem->bus.base = bochs->fb_base;
100 mem->bus.is_iomem = true;
101 break;
102 default:
103 return -EINVAL;
104 break;
105 }
106 return 0;
107}
108
109static void bochs_ttm_io_mem_free(struct ttm_bo_device *bdev,
110 struct ttm_mem_reg *mem)
111{
112}
113
114static void bochs_ttm_backend_destroy(struct ttm_tt *tt)
115{
116 ttm_tt_fini(tt);
117 kfree(tt);
118}
119
120static struct ttm_backend_func bochs_tt_backend_func = {
121 .destroy = &bochs_ttm_backend_destroy,
122};
123
124static struct ttm_tt *bochs_ttm_tt_create(struct ttm_buffer_object *bo,
125 uint32_t page_flags)
126{
127 struct ttm_tt *tt;
128
129 tt = kzalloc(sizeof(struct ttm_tt), GFP_KERNEL);
130 if (tt == NULL)
131 return NULL;
132 tt->func = &bochs_tt_backend_func;
133 if (ttm_tt_init(tt, bo, page_flags)) {
134 kfree(tt);
135 return NULL;
136 }
137 return tt;
138}
139
140static struct ttm_bo_driver bochs_bo_driver = {
141 .ttm_tt_create = bochs_ttm_tt_create,
142 .init_mem_type = bochs_bo_init_mem_type,
143 .eviction_valuable = ttm_bo_eviction_valuable,
144 .evict_flags = bochs_bo_evict_flags,
145 .move = NULL,
146 .verify_access = bochs_bo_verify_access,
147 .io_mem_reserve = &bochs_ttm_io_mem_reserve,
148 .io_mem_free = &bochs_ttm_io_mem_free,
149};
150
151int bochs_mm_init(struct bochs_device *bochs)12int bochs_mm_init(struct bochs_device *bochs)
152{13{
153 struct ttm_bo_device *bdev = &bochs->ttm.bdev;14 struct drm_vram_mm *vmm;
154 int ret;
155 15
156 ret = ttm_bo_device_init(&bochs->ttm.bdev,16 vmm = drm_vram_helper_alloc_mm(bochs->dev, bochs->fb_base,
157 &bochs_bo_driver,17 bochs->fb_size,
158 bochs->dev->anon_inode->i_mapping,18 &drm_gem_vram_mm_funcs);
159 true);19 return PTR_ERR_OR_ZERO(vmm);
160 if (ret) {
161 DRM_ERROR("Error initialising bo driver; %d\n", ret);
162 return ret;
163 }
164
165 ret = ttm_bo_init_mm(bdev, TTM_PL_VRAM,
166 bochs->fb_size >> PAGE_SHIFT);
167 if (ret) {
168 DRM_ERROR("Failed ttm VRAM init: %d\n", ret);
169 return ret;
170 }
171
172 bochs->ttm.initialized = true;
173 return 0;
174}20}
175 21
176void bochs_mm_fini(struct bochs_device *bochs)22void bochs_mm_fini(struct bochs_device *bochs)
177{23{
178 if (!bochs->ttm.initialized)24 if (!bochs->dev->vram_mm)
179 return;25 return;
180 26
181 ttm_bo_device_release(&bochs->ttm.bdev);27 drm_vram_helper_release_mm(bochs->dev);
182 bochs->ttm.initialized = false;
183}
184
185static void bochs_ttm_placement(struct bochs_bo *bo, int domain)
186{
187 unsigned i;
188 u32 c = 0;
189 bo->placement.placement = bo->placements;
190 bo->placement.busy_placement = bo->placements;
191 if (domain & TTM_PL_FLAG_VRAM) {
192 bo->placements[c++].flags = TTM_PL_FLAG_WC
193 | TTM_PL_FLAG_UNCACHED
194 | TTM_PL_FLAG_VRAM;
195 }
196 if (domain & TTM_PL_FLAG_SYSTEM) {
197 bo->placements[c++].flags = TTM_PL_MASK_CACHING
198 | TTM_PL_FLAG_SYSTEM;
199 }
200 if (!c) {
201 bo->placements[c++].flags = TTM_PL_MASK_CACHING
202 | TTM_PL_FLAG_SYSTEM;
203 }
204 for (i = 0; i < c; ++i) {
205 bo->placements[i].fpfn = 0;
206 bo->placements[i].lpfn = 0;
207 }
208 bo->placement.num_placement = c;
209 bo->placement.num_busy_placement = c;
210}
211
212int bochs_bo_pin(struct bochs_bo *bo, u32 pl_flag)
213{
214 struct ttm_operation_ctx ctx = { false, false };
215 int i, ret;
216
217 if (bo->pin_count) {
218 bo->pin_count++;
219 return 0;
220 }
221
222 bochs_ttm_placement(bo, pl_flag);
223 for (i = 0; i < bo->placement.num_placement; i++)
224 bo->placements[i].flags |= TTM_PL_FLAG_NO_EVICT;
225 ret = ttm_bo_reserve(&bo->bo, true, false, NULL);
226 if (ret)
227 return ret;
228 ret = ttm_bo_validate(&bo->bo, &bo->placement, &ctx);
229 ttm_bo_unreserve(&bo->bo);
230 if (ret)
231 return ret;
232
233 bo->pin_count = 1;
234 return 0;
235}
236
237int bochs_bo_unpin(struct bochs_bo *bo)
238{
239 struct ttm_operation_ctx ctx = { false, false };
240 int i, ret;
241
242 if (!bo->pin_count) {
243 DRM_ERROR("unpin bad %p\n", bo);
244 return 0;
245 }
246 bo->pin_count--;
247
248 if (bo->pin_count)
249 return 0;
250
251 for (i = 0; i < bo->placement.num_placement; i++)
252 bo->placements[i].flags &= ~TTM_PL_FLAG_NO_EVICT;
253 ret = ttm_bo_reserve(&bo->bo, true, false, NULL);
254 if (ret)
255 return ret;
256 ret = ttm_bo_validate(&bo->bo, &bo->placement, &ctx);
257 ttm_bo_unreserve(&bo->bo);
258 if (ret)
259 return ret;
260
261 return 0;
262}
263
264int bochs_mmap(struct file *filp, struct vm_area_struct *vma)
265{
266 struct drm_file *file_priv = filp->private_data;
267 struct bochs_device *bochs = file_priv->minor->dev->dev_private;
268
269 return ttm_bo_mmap(filp, vma, &bochs->ttm.bdev);
270}
271
272/* ---------------------------------------------------------------------- */
273
274static int bochs_bo_create(struct drm_device *dev, int size, int align,
275 uint32_t flags, struct bochs_bo **pbochsbo)
276{
277 struct bochs_device *bochs = dev->dev_private;
278 struct bochs_bo *bochsbo;
279 size_t acc_size;
280 int ret;
281
282 bochsbo = kzalloc(sizeof(struct bochs_bo), GFP_KERNEL);
283 if (!bochsbo)
284 return -ENOMEM;
285
286 ret = drm_gem_object_init(dev, &bochsbo->gem, size);
287 if (ret) {
288 kfree(bochsbo);
289 return ret;
290 }
291
292 bochsbo->bo.bdev = &bochs->ttm.bdev;
293 bochsbo->bo.bdev->dev_mapping = dev->anon_inode->i_mapping;
294
295 bochs_ttm_placement(bochsbo, TTM_PL_FLAG_VRAM | TTM_PL_FLAG_SYSTEM);
296
297 acc_size = ttm_bo_dma_acc_size(&bochs->ttm.bdev, size,
298 sizeof(struct bochs_bo));
299
300 ret = ttm_bo_init(&bochs->ttm.bdev, &bochsbo->bo, size,
301 ttm_bo_type_device, &bochsbo->placement,
302 align >> PAGE_SHIFT, false, acc_size,
303 NULL, NULL, bochs_bo_ttm_destroy);
304 if (ret)
305 return ret;
306
307 *pbochsbo = bochsbo;
308 return 0;
309}
310
311int bochs_gem_create(struct drm_device *dev, u32 size, bool iskernel,
312 struct drm_gem_object **obj)
313{
314 struct bochs_bo *bochsbo;
315 int ret;
316
317 *obj = NULL;
318
319 size = PAGE_ALIGN(size);
320 if (size == 0)
321 return -EINVAL;
322
323 ret = bochs_bo_create(dev, size, 0, 0, &bochsbo);
324 if (ret) {
325 if (ret != -ERESTARTSYS)
326 DRM_ERROR("failed to allocate GEM object\n");
327 return ret;
328 }
329 *obj = &bochsbo->gem;
330 return 0;
331}
332
333int bochs_dumb_create(struct drm_file *file, struct drm_device *dev,
334 struct drm_mode_create_dumb *args)
335{
336 struct drm_gem_object *gobj;
337 u32 handle;
338 int ret;
339
340 args->pitch = args->width * ((args->bpp + 7) / 8);
341 args->size = args->pitch * args->height;
342
343 ret = bochs_gem_create(dev, args->size, false,
344 &gobj);
345 if (ret)
346 return ret;
347
348 ret = drm_gem_handle_create(file, gobj, &handle);
349 drm_gem_object_put_unlocked(gobj);
350 if (ret)
351 return ret;
352
353 args->handle = handle;
354 return 0;
355}
356
357static void bochs_bo_unref(struct bochs_bo **bo)
358{
359 struct ttm_buffer_object *tbo;
360
361 if ((*bo) == NULL)
362 return;
363
364 tbo = &((*bo)->bo);
365 ttm_bo_put(tbo);
366 *bo = NULL;
367}
368
369void bochs_gem_free_object(struct drm_gem_object *obj)
370{
371 struct bochs_bo *bochs_bo = gem_to_bochs_bo(obj);
372
373 bochs_bo_unref(&bochs_bo);
374}
375
376int bochs_dumb_mmap_offset(struct drm_file *file, struct drm_device *dev,
377 uint32_t handle, uint64_t *offset)
378{
379 struct drm_gem_object *obj;
380 struct bochs_bo *bo;
381
382 obj = drm_gem_object_lookup(file, handle);
383 if (obj == NULL)
384 return -ENOENT;
385
386 bo = gem_to_bochs_bo(obj);
387 *offset = bochs_bo_mmap_offset(bo);
388
389 drm_gem_object_put_unlocked(obj);
390 return 0;
391}
392
393/* ---------------------------------------------------------------------- */
394
395int bochs_gem_prime_pin(struct drm_gem_object *obj)
396{
397 struct bochs_bo *bo = gem_to_bochs_bo(obj);
398
399 return bochs_bo_pin(bo, TTM_PL_FLAG_VRAM);
400}
401
402void bochs_gem_prime_unpin(struct drm_gem_object *obj)
403{
404 struct bochs_bo *bo = gem_to_bochs_bo(obj);
405
406 bochs_bo_unpin(bo);
407}
408
409void *bochs_gem_prime_vmap(struct drm_gem_object *obj)
410{
411 struct bochs_bo *bo = gem_to_bochs_bo(obj);
412 bool is_iomem;
413 int ret;
414
415 ret = bochs_bo_pin(bo, TTM_PL_FLAG_VRAM);
416 if (ret)
417 return NULL;
418 ret = ttm_bo_kmap(&bo->bo, 0, bo->bo.num_pages, &bo->kmap);
419 if (ret) {
420 bochs_bo_unpin(bo);
421 return NULL;
422 }
423 return ttm_kmap_obj_virtual(&bo->kmap, &is_iomem);
424}
425
426void bochs_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr)
427{
428 struct bochs_bo *bo = gem_to_bochs_bo(obj);
429
430 ttm_bo_kunmap(&bo->kmap);
431 bochs_bo_unpin(bo);
432}
433
434int bochs_gem_prime_mmap(struct drm_gem_object *obj,
435 struct vm_area_struct *vma)
436{
437 struct bochs_bo *bo = gem_to_bochs_bo(obj);
438
439 bo->gem.vma_node.vm_node.start = bo->bo.vma_node.vm_node.start;
440 return drm_gem_prime_mmap(obj, vma);
441}28}
drivers/gpu/drm/bridge/panel.c+1−2
@@ -9,13 +9,12 @@ · 8 unmodified lines
9 */9 */
10 10
11#include <drm/drmP.h>11#include <drm/drmP.h>
12#include <drm/drm_panel.h>
13#include <drm/drm_atomic_helper.h>12#include <drm/drm_atomic_helper.h>
14#include <drm/drm_connector.h>13#include <drm/drm_connector.h>
15#include <drm/drm_encoder.h>14#include <drm/drm_encoder.h>
16#include <drm/drm_modeset_helper_vtables.h>15#include <drm/drm_modeset_helper_vtables.h>
17#include <drm/drm_probe_helper.h>
18#include <drm/drm_panel.h>16#include <drm/drm_panel.h>
17#include <drm/drm_probe_helper.h>
19 18
20struct panel_bridge {19struct panel_bridge {
21 struct drm_bridge bridge;20 struct drm_bridge bridge;
drivers/gpu/drm/cirrus/cirrus_drv.h+0−250
@@ -1,250 +0,0 @@
1/*
2 * Copyright 2012 Red Hat
3 *
4 * This file is subject to the terms and conditions of the GNU General
5 * Public License version 2. See the file COPYING in the main
6 * directory of this archive for more details.
7 *
8 * Authors: Matthew Garrett
9 * Dave Airlie
10 */
11#ifndef __CIRRUS_DRV_H__
12#define __CIRRUS_DRV_H__
13
14#include <video/vga.h>
15
16#include <drm/drm_encoder.h>
17#include <drm/drm_fb_helper.h>
18
19#include <drm/ttm/ttm_bo_api.h>
20#include <drm/ttm/ttm_bo_driver.h>
21#include <drm/ttm/ttm_placement.h>
22#include <drm/ttm/ttm_memory.h>
23#include <drm/ttm/ttm_module.h>
24
25#include <drm/drm_gem.h>
26
27#define DRIVER_AUTHOR "Matthew Garrett"
28
29#define DRIVER_NAME "cirrus"
30#define DRIVER_DESC "qemu Cirrus emulation"
31#define DRIVER_DATE "20110418"
32
33#define DRIVER_MAJOR 1
34#define DRIVER_MINOR 0
35#define DRIVER_PATCHLEVEL 0
36
37#define CIRRUSFB_CONN_LIMIT 1
38
39#define RREG8(reg) ioread8(((void __iomem *)cdev->rmmio) + (reg))
40#define WREG8(reg, v) iowrite8(v, ((void __iomem *)cdev->rmmio) + (reg))
41#define RREG32(reg) ioread32(((void __iomem *)cdev->rmmio) + (reg))
42#define WREG32(reg, v) iowrite32(v, ((void __iomem *)cdev->rmmio) + (reg))
43
44#define SEQ_INDEX 4
45#define SEQ_DATA 5
46
47#define WREG_SEQ(reg, v) \
48 do { \
49 WREG8(SEQ_INDEX, reg); \
50 WREG8(SEQ_DATA, v); \
51 } while (0) \
52
53#define CRT_INDEX 0x14
54#define CRT_DATA 0x15
55
56#define WREG_CRT(reg, v) \
57 do { \
58 WREG8(CRT_INDEX, reg); \
59 WREG8(CRT_DATA, v); \
60 } while (0) \
61
62#define GFX_INDEX 0xe
63#define GFX_DATA 0xf
64
65#define WREG_GFX(reg, v) \
66 do { \
67 WREG8(GFX_INDEX, reg); \
68 WREG8(GFX_DATA, v); \
69 } while (0) \
70
71/*
72 * Cirrus has a "hidden" DAC register that can be accessed by writing to
73 * the pixel mask register to reset the state, then reading from the register
74 * four times. The next write will then pass to the DAC
75 */
76#define VGA_DAC_MASK 0x6
77
78#define WREG_HDR(v) \
79 do { \
80 RREG8(VGA_DAC_MASK); \
81 RREG8(VGA_DAC_MASK); \
82 RREG8(VGA_DAC_MASK); \
83 RREG8(VGA_DAC_MASK); \
84 WREG8(VGA_DAC_MASK, v); \
85 } while (0) \
86
87
88#define CIRRUS_MAX_FB_HEIGHT 4096
89#define CIRRUS_MAX_FB_WIDTH 4096
90
91#define CIRRUS_DPMS_CLEARED (-1)
92
93#define to_cirrus_crtc(x) container_of(x, struct cirrus_crtc, base)
94#define to_cirrus_encoder(x) container_of(x, struct cirrus_encoder, base)
95
96struct cirrus_crtc {
97 struct drm_crtc base;
98 int last_dpms;
99 bool enabled;
100};
101
102struct cirrus_fbdev;
103struct cirrus_mode_info {
104 struct cirrus_crtc *crtc;
105 /* pointer to fbdev info structure */
106 struct cirrus_fbdev *gfbdev;
107};
108
109struct cirrus_encoder {
110 struct drm_encoder base;
111 int last_dpms;
112};
113
114struct cirrus_connector {
115 struct drm_connector base;
116};
117
118struct cirrus_mc {
119 resource_size_t vram_size;
120 resource_size_t vram_base;
121};
122
123struct cirrus_device {
124 struct drm_device *dev;
125 unsigned long flags;
126
127 resource_size_t rmmio_base;
128 resource_size_t rmmio_size;
129 void __iomem *rmmio;
130
131 struct cirrus_mc mc;
132 struct cirrus_mode_info mode_info;
133
134 int num_crtc;
135 int fb_mtrr;
136
137 struct {
138 struct ttm_bo_device bdev;
139 } ttm;
140 bool mm_inited;
141};
142
143
144struct cirrus_fbdev {
145 struct drm_fb_helper helper; /* must be first */
146 struct drm_framebuffer *gfb;
147 void *sysram;
148 int size;
149 int x1, y1, x2, y2; /* dirty rect */
150 spinlock_t dirty_lock;
151};
152
153struct cirrus_bo {
154 struct ttm_buffer_object bo;
155 struct ttm_placement placement;
156 struct ttm_bo_kmap_obj kmap;
157 struct drm_gem_object gem;
158 struct ttm_place placements[3];
159 int pin_count;
160};
161#define gem_to_cirrus_bo(gobj) container_of((gobj), struct cirrus_bo, gem)
162
163static inline struct cirrus_bo *
164cirrus_bo(struct ttm_buffer_object *bo)
165{
166 return container_of(bo, struct cirrus_bo, bo);
167}
168
169
170#define to_cirrus_obj(x) container_of(x, struct cirrus_gem_object, base)
171
172 /* cirrus_main.c */
173int cirrus_device_init(struct cirrus_device *cdev,
174 struct drm_device *ddev,
175 struct pci_dev *pdev,
176 uint32_t flags);
177void cirrus_device_fini(struct cirrus_device *cdev);
178void cirrus_gem_free_object(struct drm_gem_object *obj);
179int cirrus_dumb_mmap_offset(struct drm_file *file,
180 struct drm_device *dev,
181 uint32_t handle,
182 uint64_t *offset);
183int cirrus_gem_create(struct drm_device *dev,
184 u32 size, bool iskernel,
185 struct drm_gem_object **obj);
186int cirrus_dumb_create(struct drm_file *file,
187 struct drm_device *dev,
188 struct drm_mode_create_dumb *args);
189
190int cirrus_framebuffer_init(struct drm_device *dev,
191 struct drm_framebuffer *gfb,
192 const struct drm_mode_fb_cmd2 *mode_cmd,
193 struct drm_gem_object *obj);
194
195bool cirrus_check_framebuffer(struct cirrus_device *cdev, int width, int height,
196 int bpp, int pitch);
197
198 /* cirrus_display.c */
199int cirrus_modeset_init(struct cirrus_device *cdev);
200void cirrus_modeset_fini(struct cirrus_device *cdev);
201
202 /* cirrus_fbdev.c */
203int cirrus_fbdev_init(struct cirrus_device *cdev);
204void cirrus_fbdev_fini(struct cirrus_device *cdev);
205
206
207
208 /* cirrus_irq.c */
209void cirrus_driver_irq_preinstall(struct drm_device *dev);
210int cirrus_driver_irq_postinstall(struct drm_device *dev);
211void cirrus_driver_irq_uninstall(struct drm_device *dev);
212irqreturn_t cirrus_driver_irq_handler(int irq, void *arg);
213
214 /* cirrus_kms.c */
215int cirrus_driver_load(struct drm_device *dev, unsigned long flags);
216void cirrus_driver_unload(struct drm_device *dev);
217extern struct drm_ioctl_desc cirrus_ioctls[];
218extern int cirrus_max_ioctl;
219
220int cirrus_mm_init(struct cirrus_device *cirrus);
221void cirrus_mm_fini(struct cirrus_device *cirrus);
222void cirrus_ttm_placement(struct cirrus_bo *bo, int domain);
223int cirrus_bo_create(struct drm_device *dev, int size, int align,
224 uint32_t flags, struct cirrus_bo **pcirrusbo);
225int cirrus_mmap(struct file *filp, struct vm_area_struct *vma);
226
227static inline int cirrus_bo_reserve(struct cirrus_bo *bo, bool no_wait)
228{
229 int ret;
230
231 ret = ttm_bo_reserve(&bo->bo, true, no_wait, NULL);
232 if (ret) {
233 if (ret != -ERESTARTSYS && ret != -EBUSY)
234 DRM_ERROR("reserve failed %p\n", bo);
235 return ret;
236 }
237 return 0;
238}
239
240static inline void cirrus_bo_unreserve(struct cirrus_bo *bo)
241{
242 ttm_bo_unreserve(&bo->bo);
243}
244
245int cirrus_bo_push_sysram(struct cirrus_bo *bo);
246int cirrus_bo_pin(struct cirrus_bo *bo, u32 pl_flag, u64 *gpu_addr);
247
248extern int cirrus_bpp;
249
250#endif /* __CIRRUS_DRV_H__ */
drivers/gpu/drm/cirrus/cirrus_ttm.c+0−337
@@ -1,337 +0,0 @@
1/*
2 * Copyright 2012 Red Hat Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the
6 * "Software"), to deal in the Software without restriction, including
7 * without limitation the rights to use, copy, modify, merge, publish,
8 * distribute, sub license, and/or sell copies of the Software, and to
9 * permit persons to whom the Software is furnished to do so, subject to
10 * the following conditions:
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
13 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
14 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
15 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
16 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
17 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
18 * USE OR OTHER DEALINGS IN THE SOFTWARE.
19 *
20 * The above copyright notice and this permission notice (including the
21 * next paragraph) shall be included in all copies or substantial portions
22 * of the Software.
23 *
24 */
25/*
26 * Authors: Dave Airlie <airlied@redhat.com>
27 */
28#include <drm/drmP.h>
29#include <drm/ttm/ttm_page_alloc.h>
30
31#include "cirrus_drv.h"
32
33static inline struct cirrus_device *
34cirrus_bdev(struct ttm_bo_device *bd)
35{
36 return container_of(bd, struct cirrus_device, ttm.bdev);
37}
38
39static void cirrus_bo_ttm_destroy(struct ttm_buffer_object *tbo)
40{
41 struct cirrus_bo *bo;
42
43 bo = container_of(tbo, struct cirrus_bo, bo);
44
45 drm_gem_object_release(&bo->gem);
46 kfree(bo);
47}
48
49static bool cirrus_ttm_bo_is_cirrus_bo(struct ttm_buffer_object *bo)
50{
51 if (bo->destroy == &cirrus_bo_ttm_destroy)
52 return true;
53 return false;
54}
55
56static int
57cirrus_bo_init_mem_type(struct ttm_bo_device *bdev, uint32_t type,
58 struct ttm_mem_type_manager *man)
59{
60 switch (type) {
61 case TTM_PL_SYSTEM:
62 man->flags = TTM_MEMTYPE_FLAG_MAPPABLE;
63 man->available_caching = TTM_PL_MASK_CACHING;
64 man->default_caching = TTM_PL_FLAG_CACHED;
65 break;
66 case TTM_PL_VRAM:
67 man->func = &ttm_bo_manager_func;
68 man->flags = TTM_MEMTYPE_FLAG_FIXED |
69 TTM_MEMTYPE_FLAG_MAPPABLE;
70 man->available_caching = TTM_PL_FLAG_UNCACHED |
71 TTM_PL_FLAG_WC;
72 man->default_caching = TTM_PL_FLAG_WC;
73 break;
74 default:
75 DRM_ERROR("Unsupported memory type %u\n", (unsigned)type);
76 return -EINVAL;
77 }
78 return 0;
79}
80
81static void
82cirrus_bo_evict_flags(struct ttm_buffer_object *bo, struct ttm_placement *pl)
83{
84 struct cirrus_bo *cirrusbo = cirrus_bo(bo);
85
86 if (!cirrus_ttm_bo_is_cirrus_bo(bo))
87 return;
88
89 cirrus_ttm_placement(cirrusbo, TTM_PL_FLAG_SYSTEM);
90 *pl = cirrusbo->placement;
91}
92
93static int cirrus_bo_verify_access(struct ttm_buffer_object *bo, struct file *filp)
94{
95 struct cirrus_bo *cirrusbo = cirrus_bo(bo);
96
97 return drm_vma_node_verify_access(&cirrusbo->gem.vma_node,
98 filp->private_data);
99}
100
101static int cirrus_ttm_io_mem_reserve(struct ttm_bo_device *bdev,
102 struct ttm_mem_reg *mem)
103{
104 struct ttm_mem_type_manager *man = &bdev->man[mem->mem_type];
105 struct cirrus_device *cirrus = cirrus_bdev(bdev);
106
107 mem->bus.addr = NULL;
108 mem->bus.offset = 0;
109 mem->bus.size = mem->num_pages << PAGE_SHIFT;
110 mem->bus.base = 0;
111 mem->bus.is_iomem = false;
112 if (!(man->flags & TTM_MEMTYPE_FLAG_MAPPABLE))
113 return -EINVAL;
114 switch (mem->mem_type) {
115 case TTM_PL_SYSTEM:
116 /* system memory */
117 return 0;
118 case TTM_PL_VRAM:
119 mem->bus.offset = mem->start << PAGE_SHIFT;
120 mem->bus.base = pci_resource_start(cirrus->dev->pdev, 0);
121 mem->bus.is_iomem = true;
122 break;
123 default:
124 return -EINVAL;
125 break;
126 }
127 return 0;
128}
129
130static void cirrus_ttm_io_mem_free(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem)
131{
132}
133
134static void cirrus_ttm_backend_destroy(struct ttm_tt *tt)
135{
136 ttm_tt_fini(tt);
137 kfree(tt);
138}
139
140static struct ttm_backend_func cirrus_tt_backend_func = {
141 .destroy = &cirrus_ttm_backend_destroy,
142};
143
144
145static struct ttm_tt *cirrus_ttm_tt_create(struct ttm_buffer_object *bo,
146 uint32_t page_flags)
147{
148 struct ttm_tt *tt;
149
150 tt = kzalloc(sizeof(struct ttm_tt), GFP_KERNEL);
151 if (tt == NULL)
152 return NULL;
153 tt->func = &cirrus_tt_backend_func;
154 if (ttm_tt_init(tt, bo, page_flags)) {
155 kfree(tt);
156 return NULL;
157 }
158 return tt;
159}
160
161struct ttm_bo_driver cirrus_bo_driver = {
162 .ttm_tt_create = cirrus_ttm_tt_create,
163 .init_mem_type = cirrus_bo_init_mem_type,
164 .eviction_valuable = ttm_bo_eviction_valuable,
165 .evict_flags = cirrus_bo_evict_flags,
166 .move = NULL,
167 .verify_access = cirrus_bo_verify_access,
168 .io_mem_reserve = &cirrus_ttm_io_mem_reserve,
169 .io_mem_free = &cirrus_ttm_io_mem_free,
170};
171
172int cirrus_mm_init(struct cirrus_device *cirrus)
173{
174 int ret;
175 struct drm_device *dev = cirrus->dev;
176 struct ttm_bo_device *bdev = &cirrus->ttm.bdev;
177
178 ret = ttm_bo_device_init(&cirrus->ttm.bdev,
179 &cirrus_bo_driver,
180 dev->anon_inode->i_mapping,
181 true);
182 if (ret) {
183 DRM_ERROR("Error initialising bo driver; %d\n", ret);
184 return ret;
185 }
186
187 ret = ttm_bo_init_mm(bdev, TTM_PL_VRAM,
188 cirrus->mc.vram_size >> PAGE_SHIFT);
189 if (ret) {
190 DRM_ERROR("Failed ttm VRAM init: %d\n", ret);
191 return ret;
192 }
193
194 arch_io_reserve_memtype_wc(pci_resource_start(dev->pdev, 0),
195 pci_resource_len(dev->pdev, 0));
196
197 cirrus->fb_mtrr = arch_phys_wc_add(pci_resource_start(dev->pdev, 0),
198 pci_resource_len(dev->pdev, 0));
199
200 cirrus->mm_inited = true;
201 return 0;
202}
203
204void cirrus_mm_fini(struct cirrus_device *cirrus)
205{
206 struct drm_device *dev = cirrus->dev;
207
208 if (!cirrus->mm_inited)
209 return;
210
211 ttm_bo_device_release(&cirrus->ttm.bdev);
212
213 arch_phys_wc_del(cirrus->fb_mtrr);
214 cirrus->fb_mtrr = 0;
215 arch_io_free_memtype_wc(pci_resource_start(dev->pdev, 0),
216 pci_resource_len(dev->pdev, 0));
217}
218
219void cirrus_ttm_placement(struct cirrus_bo *bo, int domain)
220{
221 u32 c = 0;
222 unsigned i;
223 bo->placement.placement = bo->placements;
224 bo->placement.busy_placement = bo->placements;
225 if (domain & TTM_PL_FLAG_VRAM)
226 bo->placements[c++].flags = TTM_PL_FLAG_WC | TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_VRAM;
227 if (domain & TTM_PL_FLAG_SYSTEM)
228 bo->placements[c++].flags = TTM_PL_MASK_CACHING | TTM_PL_FLAG_SYSTEM;
229 if (!c)
230 bo->placements[c++].flags = TTM_PL_MASK_CACHING | TTM_PL_FLAG_SYSTEM;
231 bo->placement.num_placement = c;
232 bo->placement.num_busy_placement = c;
233 for (i = 0; i < c; ++i) {
234 bo->placements[i].fpfn = 0;
235 bo->placements[i].lpfn = 0;
236 }
237}
238
239int cirrus_bo_create(struct drm_device *dev, int size, int align,
240 uint32_t flags, struct cirrus_bo **pcirrusbo)
241{
242 struct cirrus_device *cirrus = dev->dev_private;
243 struct cirrus_bo *cirrusbo;
244 size_t acc_size;
245 int ret;
246
247 cirrusbo = kzalloc(sizeof(struct cirrus_bo), GFP_KERNEL);
248 if (!cirrusbo)
249 return -ENOMEM;
250
251 ret = drm_gem_object_init(dev, &cirrusbo->gem, size);
252 if (ret) {
253 kfree(cirrusbo);
254 return ret;
255 }
256
257 cirrusbo->bo.bdev = &cirrus->ttm.bdev;
258
259 cirrus_ttm_placement(cirrusbo, TTM_PL_FLAG_VRAM | TTM_PL_FLAG_SYSTEM);
260
261 acc_size = ttm_bo_dma_acc_size(&cirrus->ttm.bdev, size,
262 sizeof(struct cirrus_bo));
263
264 ret = ttm_bo_init(&cirrus->ttm.bdev, &cirrusbo->bo, size,
265 ttm_bo_type_device, &cirrusbo->placement,
266 align >> PAGE_SHIFT, false, acc_size,
267 NULL, NULL, cirrus_bo_ttm_destroy);
268 if (ret)
269 return ret;
270
271 *pcirrusbo = cirrusbo;
272 return 0;
273}
274
275static inline u64 cirrus_bo_gpu_offset(struct cirrus_bo *bo)
276{
277 return bo->bo.offset;
278}
279
280int cirrus_bo_pin(struct cirrus_bo *bo, u32 pl_flag, u64 *gpu_addr)
281{
282 struct ttm_operation_ctx ctx = { false, false };
283 int i, ret;
284
285 if (bo->pin_count) {
286 bo->pin_count++;
287 if (gpu_addr)
288 *gpu_addr = cirrus_bo_gpu_offset(bo);
289 }
290
291 cirrus_ttm_placement(bo, pl_flag);
292 for (i = 0; i < bo->placement.num_placement; i++)
293 bo->placements[i].flags |= TTM_PL_FLAG_NO_EVICT;
294 ret = ttm_bo_validate(&bo->bo, &bo->placement, &ctx);
295 if (ret)
296 return ret;
297
298 bo->pin_count = 1;
299 if (gpu_addr)
300 *gpu_addr = cirrus_bo_gpu_offset(bo);
301 return 0;
302}
303
304int cirrus_bo_push_sysram(struct cirrus_bo *bo)
305{
306 struct ttm_operation_ctx ctx = { false, false };
307 int i, ret;
308 if (!bo->pin_count) {
309 DRM_ERROR("unpin bad %p\n", bo);
310 return 0;
311 }
312 bo->pin_count--;
313 if (bo->pin_count)
314 return 0;
315
316 if (bo->kmap.virtual)
317 ttm_bo_kunmap(&bo->kmap);
318
319 cirrus_ttm_placement(bo, TTM_PL_FLAG_SYSTEM);
320 for (i = 0; i < bo->placement.num_placement ; i++)
321 bo->placements[i].flags |= TTM_PL_FLAG_NO_EVICT;
322
323 ret = ttm_bo_validate(&bo->bo, &bo->placement, &ctx);
324 if (ret) {
325 DRM_ERROR("pushing to VRAM failed\n");
326 return ret;
327 }
328 return 0;
329}
330
331int cirrus_mmap(struct file *filp, struct vm_area_struct *vma)
332{
333 struct drm_file *file_priv = filp->private_data;
334 struct cirrus_device *cirrus = file_priv->minor->dev->dev_private;
335
336 return ttm_bo_mmap(filp, vma, &cirrus->ttm.bdev);
337}
drivers/gpu/drm/drm_atomic_helper.c+1−1
@@ -1423,7 +1423,7 @@ drm_atomic_helper_wait_for_vblanks(struct drm_device *dev, · 1422 unmodified lines
1423 ret = wait_event_timeout(dev->vblank[i].queue,1423 ret = wait_event_timeout(dev->vblank[i].queue,
1424 old_state->crtcs[i].last_vblank_count !=1424 old_state->crtcs[i].last_vblank_count !=
1425 drm_crtc_vblank_count(crtc),1425 drm_crtc_vblank_count(crtc),
1426 msecs_to_jiffies(50));1426 msecs_to_jiffies(100));
1427 1427
1428 WARN(!ret, "[CRTC:%d:%s] vblank wait timed out\n",1428 WARN(!ret, "[CRTC:%d:%s] vblank wait timed out\n",
1429 crtc->base.id, crtc->name);1429 crtc->base.id, crtc->name);
drivers/gpu/drm/drm_atomic_state_helper.c+34−7
@@ -56,6 +56,29 @@ · 55 unmodified lines
56 * for these functions.56 * for these functions.
57 */57 */
58 58
59/**
60 * __drm_atomic_helper_crtc_reset - reset state on CRTC
61 * @crtc: drm CRTC
62 * @crtc_state: CRTC state to assign
63 *
64 * Initializes the newly allocated @crtc_state and assigns it to
65 * the &drm_crtc->state pointer of @crtc, usually required when
66 * initializing the drivers or when called from the &drm_crtc_funcs.reset
67 * hook.
68 *
69 * This is useful for drivers that subclass the CRTC state.
70 */
71void
72__drm_atomic_helper_crtc_reset(struct drm_crtc *crtc,
73 struct drm_crtc_state *crtc_state)
74{
75 if (crtc_state)
76 crtc_state->crtc = crtc;
77
78 crtc->state = crtc_state;
79}
80EXPORT_SYMBOL(__drm_atomic_helper_crtc_reset);
81
59/**82/**
60 * drm_atomic_helper_crtc_reset - default &drm_crtc_funcs.reset hook for CRTCs83 * drm_atomic_helper_crtc_reset - default &drm_crtc_funcs.reset hook for CRTCs
61 * @crtc: drm CRTC84 * @crtc: drm CRTC
@@ -65,14 +88,13 @@ · 3 unmodified lines
65 */88 */
66void drm_atomic_helper_crtc_reset(struct drm_crtc *crtc)89void drm_atomic_helper_crtc_reset(struct drm_crtc *crtc)
67{90{
68 if (crtc->state)91 struct drm_crtc_state *crtc_state =
69 __drm_atomic_helper_crtc_destroy_state(crtc->state);92 kzalloc(sizeof(*crtc->state), GFP_KERNEL);
70
71 kfree(crtc->state);
72 crtc->state = kzalloc(sizeof(*crtc->state), GFP_KERNEL);
73 93
74 if (crtc->state)94 if (crtc->state)
75 crtc->state->crtc = crtc;95 crtc->funcs->atomic_destroy_state(crtc, crtc->state);
96
97 __drm_atomic_helper_crtc_reset(crtc, crtc_state);
76}98}
77EXPORT_SYMBOL(drm_atomic_helper_crtc_reset);99EXPORT_SYMBOL(drm_atomic_helper_crtc_reset);
78 100
@@ -314,7 +336,7 @@ EXPORT_SYMBOL(drm_atomic_helper_plane_destroy_state); · 235 unmodified lines
314 * @conn_state: connector state to assign336 * @conn_state: connector state to assign
315 *337 *
316 * Initializes the newly allocated @conn_state and assigns it to338 * Initializes the newly allocated @conn_state and assigns it to
317 * the &drm_conector->state pointer of @connector, usually required when339 * the &drm_connector->state pointer of @connector, usually required when
318 * initializing the drivers or when called from the &drm_connector_funcs.reset340 * initializing the drivers or when called from the &drm_connector_funcs.reset
319 * hook.341 * hook.
320 *342 *
@@ -369,6 +391,9 @@ __drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector, · 48 unmodified lines
369 drm_connector_get(connector);391 drm_connector_get(connector);
370 state->commit = NULL;392 state->commit = NULL;
371 393
394 if (state->hdr_output_metadata)
395 drm_property_blob_get(state->hdr_output_metadata);
396
372 /* Don't copy over a writeback job, they are used only once */397 /* Don't copy over a writeback job, they are used only once */
373 state->writeback_job = NULL;398 state->writeback_job = NULL;
374}399}
@@ -416,6 +441,8 @@ __drm_atomic_helper_connector_destroy_state(struct drm_connector_state *state) · 41 unmodified lines
416 441
417 if (state->writeback_job)442 if (state->writeback_job)
418 drm_writeback_cleanup_job(state->writeback_job);443 drm_writeback_cleanup_job(state->writeback_job);
444
445 drm_property_blob_put(state->hdr_output_metadata);
419}446}
420EXPORT_SYMBOL(__drm_atomic_helper_connector_destroy_state);447EXPORT_SYMBOL(__drm_atomic_helper_connector_destroy_state);
421 448
drivers/gpu/drm/drm_atomic_uapi.c+12−0
@@ -676,6 +676,8 @@ static int drm_atomic_connector_set_property(struct drm_connector *connector, · 675 unmodified lines
676{676{
677 struct drm_device *dev = connector->dev;677 struct drm_device *dev = connector->dev;
678 struct drm_mode_config *config = &dev->mode_config;678 struct drm_mode_config *config = &dev->mode_config;
679 bool replaced = false;
680 int ret;
679 681
680 if (property == config->prop_crtc_id) {682 if (property == config->prop_crtc_id) {
681 struct drm_crtc *crtc = drm_crtc_find(dev, file_priv, val);683 struct drm_crtc *crtc = drm_crtc_find(dev, file_priv, val);
@@ -726,6 +728,13 @@ static int drm_atomic_connector_set_property(struct drm_connector *connector, · 44 unmodified lines
726 */728 */
727 if (state->link_status != DRM_LINK_STATUS_GOOD)729 if (state->link_status != DRM_LINK_STATUS_GOOD)
728 state->link_status = val;730 state->link_status = val;
731 } else if (property == config->hdr_output_metadata_property) {
732 ret = drm_atomic_replace_property_blob_from_id(dev,
733 &state->hdr_output_metadata,
734 val,
735 sizeof(struct hdr_output_metadata), -1,
736 &replaced);
737 return ret;
729 } else if (property == config->aspect_ratio_property) {738 } else if (property == config->aspect_ratio_property) {
730 state->picture_aspect_ratio = val;739 state->picture_aspect_ratio = val;
731 } else if (property == config->content_type_property) {740 } else if (property == config->content_type_property) {
@@ -814,6 +823,9 @@ drm_atomic_connector_get_property(struct drm_connector *connector, · 82 unmodified lines
814 *val = state->colorspace;823 *val = state->colorspace;
815 } else if (property == connector->scaling_mode_property) {824 } else if (property == connector->scaling_mode_property) {
816 *val = state->scaling_mode;825 *val = state->scaling_mode;
826 } else if (property == config->hdr_output_metadata_property) {
827 *val = state->hdr_output_metadata ?
828 state->hdr_output_metadata->base.id : 0;
817 } else if (property == connector->content_protection_property) {829 } else if (property == connector->content_protection_property) {
818 *val = state->content_protection;830 *val = state->content_protection;
819 } else if (property == config->writeback_fb_id_property) {831 } else if (property == config->writeback_fb_id_property) {
drivers/gpu/drm/drm_auth.c+20−0
@@ -351,3 +351,23 @@ void drm_master_put(struct drm_master **master) · 350 unmodified lines
351 *master = NULL;351 *master = NULL;
352}352}
353EXPORT_SYMBOL(drm_master_put);353EXPORT_SYMBOL(drm_master_put);
354
355/* Used by drm_client and drm_fb_helper */
356bool drm_master_internal_acquire(struct drm_device *dev)
357{
358 mutex_lock(&dev->master_mutex);
359 if (dev->master) {
360 mutex_unlock(&dev->master_mutex);
361 return false;
362 }
363
364 return true;
365}
366EXPORT_SYMBOL(drm_master_internal_acquire);
367
368/* Used by drm_client and drm_fb_helper */
369void drm_master_internal_release(struct drm_device *dev)
370{
371 mutex_unlock(&dev->master_mutex);
372}
373EXPORT_SYMBOL(drm_master_internal_release);
drivers/gpu/drm/drm_client.c+2−1
@@ -243,6 +243,7 @@ static void drm_client_buffer_delete(struct drm_client_buffer *buffer) · 242 unmodified lines
243static struct drm_client_buffer *243static struct drm_client_buffer *
244drm_client_buffer_create(struct drm_client_dev *client, u32 width, u32 height, u32 format)244drm_client_buffer_create(struct drm_client_dev *client, u32 width, u32 height, u32 format)
245{245{
246 const struct drm_format_info *info = drm_format_info(format);
246 struct drm_mode_create_dumb dumb_args = { };247 struct drm_mode_create_dumb dumb_args = { };
247 struct drm_device *dev = client->dev;248 struct drm_device *dev = client->dev;
248 struct drm_client_buffer *buffer;249 struct drm_client_buffer *buffer;
@@ -258,7 +259,7 @@ drm_client_buffer_create(struct drm_client_dev *client, u32 width, u32 height, u · 9 unmodified lines
258 259
259 dumb_args.width = width;260 dumb_args.width = width;
260 dumb_args.height = height;261 dumb_args.height = height;
261 dumb_args.bpp = drm_format_plane_cpp(format, 0) * 8;262 dumb_args.bpp = info->cpp[0] * 8;
262 ret = drm_mode_create_dumb(dev, &dumb_args, client->file);263 ret = drm_mode_create_dumb(dev, &dumb_args, client->file);
263 if (ret)264 if (ret)
264 goto err_delete;265 goto err_delete;
drivers/gpu/drm/drm_connector.c+6−0
@@ -1058,6 +1058,12 @@ int drm_connector_create_standard_properties(struct drm_device *dev) · 1057 unmodified lines
1058 return -ENOMEM;1058 return -ENOMEM;
1059 dev->mode_config.non_desktop_property = prop;1059 dev->mode_config.non_desktop_property = prop;
1060 1060
1061 prop = drm_property_create(dev, DRM_MODE_PROP_BLOB,
1062 "HDR_OUTPUT_METADATA", 0);
1063 if (!prop)
1064 return -ENOMEM;
1065 dev->mode_config.hdr_output_metadata_property = prop;
1066
1061 return 0;1067 return 0;
1062}1068}
1063 1069
drivers/gpu/drm/drm_dp_aux_dev.c+5−3
@@ -27,15 +27,17 @@ · 26 unmodified lines
27 27
28#include <linux/device.h>28#include <linux/device.h>
29#include <linux/fs.h>29#include <linux/fs.h>
30#include <linux/slab.h>
31#include <linux/init.h>30#include <linux/init.h>
32#include <linux/kernel.h>31#include <linux/kernel.h>
33#include <linux/module.h>32#include <linux/module.h>
33#include <linux/sched/signal.h>
34#include <linux/slab.h>
34#include <linux/uaccess.h>35#include <linux/uaccess.h>
35#include <linux/uio.h>36#include <linux/uio.h>
36#include <drm/drm_dp_helper.h>37
37#include <drm/drm_crtc.h>38#include <drm/drm_crtc.h>
38#include <drm/drmP.h>39#include <drm/drm_dp_helper.h>
40#include <drm/drm_print.h>
39 41
40#include "drm_crtc_helper_internal.h"42#include "drm_crtc_helper_internal.h"
41 43
drivers/gpu/drm/drm_dp_dual_mode_helper.c+3−1
@@ -20,13 +20,15 @@ · 19 unmodified lines
20 * OTHER DEALINGS IN THE SOFTWARE.20 * OTHER DEALINGS IN THE SOFTWARE.
21 */21 */
22 22
23#include <linux/delay.h>
23#include <linux/errno.h>24#include <linux/errno.h>
24#include <linux/export.h>25#include <linux/export.h>
25#include <linux/i2c.h>26#include <linux/i2c.h>
26#include <linux/slab.h>27#include <linux/slab.h>
27#include <linux/string.h>28#include <linux/string.h>
29
28#include <drm/drm_dp_dual_mode_helper.h>30#include <drm/drm_dp_dual_mode_helper.h>
29#include <drm/drmP.h>31#include <drm/drm_print.h>
30 32
31/**33/**
32 * DOC: dp dual mode helpers34 * DOC: dp dual mode helpers
drivers/gpu/drm/drm_dp_helper.c+7−5
@@ -20,16 +20,18 @@ · 19 unmodified lines
20 * OF THIS SOFTWARE.20 * OF THIS SOFTWARE.
21 */21 */
22 22
23#include <linux/kernel.h>
24#include <linux/module.h>
25#include <linux/delay.h>23#include <linux/delay.h>
26#include <linux/init.h>
27#include <linux/errno.h>24#include <linux/errno.h>
28#include <linux/sched.h>
29#include <linux/i2c.h>25#include <linux/i2c.h>
26#include <linux/init.h>
27#include <linux/kernel.h>
28#include <linux/module.h>
29#include <linux/sched.h>
30#include <linux/seq_file.h>30#include <linux/seq_file.h>
31
31#include <drm/drm_dp_helper.h>32#include <drm/drm_dp_helper.h>
32#include <drm/drmP.h>33#include <drm/drm_print.h>
34#include <drm/drm_vblank.h>
33 35
34#include "drm_crtc_helper_internal.h"36#include "drm_crtc_helper_internal.h"
35 37
drivers/gpu/drm/drm_dp_mst_topology.c+7−6
@@ -20,19 +20,20 @@ · 19 unmodified lines
20 * OF THIS SOFTWARE.20 * OF THIS SOFTWARE.
21 */21 */
22 22
23#include <linux/kernel.h>
24#include <linux/delay.h>23#include <linux/delay.h>
25#include <linux/init.h>
26#include <linux/errno.h>24#include <linux/errno.h>
25#include <linux/i2c.h>
26#include <linux/init.h>
27#include <linux/kernel.h>
27#include <linux/sched.h>28#include <linux/sched.h>
28#include <linux/seq_file.h>29#include <linux/seq_file.h>
29#include <linux/i2c.h>
30#include <drm/drm_dp_mst_helper.h>
31#include <drm/drmP.h>
32 30
33#include <drm/drm_fixed.h>
34#include <drm/drm_atomic.h>31#include <drm/drm_atomic.h>
35#include <drm/drm_atomic_helper.h>32#include <drm/drm_atomic_helper.h>
33#include <drm/drm_dp_mst_helper.h>
34#include <drm/drm_drv.h>
35#include <drm/drm_fixed.h>
36#include <drm/drm_print.h>
36#include <drm/drm_probe_helper.h>37#include <drm/drm_probe_helper.h>
37 38
38/**39/**
drivers/gpu/drm/drm_edid.c+131−4
@@ -27,16 +27,19 @@ · 26 unmodified lines
27 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER27 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
28 * DEALINGS IN THE SOFTWARE.28 * DEALINGS IN THE SOFTWARE.
29 */29 */
30#include <linux/kernel.h>30
31#include <linux/slab.h>
32#include <linux/hdmi.h>31#include <linux/hdmi.h>
33#include <linux/i2c.h>32#include <linux/i2c.h>
33#include <linux/kernel.h>
34#include <linux/module.h>34#include <linux/module.h>
35#include <linux/slab.h>
35#include <linux/vga_switcheroo.h>36#include <linux/vga_switcheroo.h>
36#include <drm/drmP.h>37
38#include <drm/drm_displayid.h>
39#include <drm/drm_drv.h>
37#include <drm/drm_edid.h>40#include <drm/drm_edid.h>
38#include <drm/drm_encoder.h>41#include <drm/drm_encoder.h>
39#include <drm/drm_displayid.h>42#include <drm/drm_print.h>
40#include <drm/drm_scdc_helper.h>43#include <drm/drm_scdc_helper.h>
41 44
42#include "drm_crtc_internal.h"45#include "drm_crtc_internal.h"
@@ -2849,6 +2852,7 @@ add_detailed_modes(struct drm_connector *connector, struct edid *edid, · 2806 unmodified lines
2849#define VIDEO_BLOCK 0x022852#define VIDEO_BLOCK 0x02
2850#define VENDOR_BLOCK 0x032853#define VENDOR_BLOCK 0x03
2851#define SPEAKER_BLOCK 0x042854#define SPEAKER_BLOCK 0x04
2855#define HDR_STATIC_METADATA_BLOCK 0x6
2852#define USE_EXTENDED_TAG 0x072856#define USE_EXTENDED_TAG 0x07
2853#define EXT_VIDEO_CAPABILITY_BLOCK 0x002857#define EXT_VIDEO_CAPABILITY_BLOCK 0x00
2854#define EXT_VIDEO_DATA_BLOCK_420 0x0E2858#define EXT_VIDEO_DATA_BLOCK_420 0x0E
@@ -3831,6 +3835,55 @@ static void fixup_detailed_cea_mode_clock(struct drm_display_mode *mode) · 976 unmodified lines
3831 mode->clock = clock;3835 mode->clock = clock;
3832}3836}
3833 3837
3838static bool cea_db_is_hdmi_hdr_metadata_block(const u8 *db)
3839{
3840 if (cea_db_tag(db) != USE_EXTENDED_TAG)
3841 return false;
3842
3843 if (db[1] != HDR_STATIC_METADATA_BLOCK)
3844 return false;
3845
3846 if (cea_db_payload_len(db) < 3)
3847 return false;
3848
3849 return true;
3850}
3851
3852static uint8_t eotf_supported(const u8 *edid_ext)
3853{
3854 return edid_ext[2] &
3855 (BIT(HDMI_EOTF_TRADITIONAL_GAMMA_SDR) |
3856 BIT(HDMI_EOTF_TRADITIONAL_GAMMA_HDR) |
3857 BIT(HDMI_EOTF_SMPTE_ST2084) |
3858 BIT(HDMI_EOTF_BT_2100_HLG));
3859}
3860
3861static uint8_t hdr_metadata_type(const u8 *edid_ext)
3862{
3863 return edid_ext[3] &
3864 BIT(HDMI_STATIC_METADATA_TYPE1);
3865}
3866
3867static void
3868drm_parse_hdr_metadata_block(struct drm_connector *connector, const u8 *db)
3869{
3870 u16 len;
3871
3872 len = cea_db_payload_len(db);
3873
3874 connector->hdr_sink_metadata.hdmi_type1.eotf =
3875 eotf_supported(db);
3876 connector->hdr_sink_metadata.hdmi_type1.metadata_type =
3877 hdr_metadata_type(db);
3878
3879 if (len >= 4)
3880 connector->hdr_sink_metadata.hdmi_type1.max_cll = db[4];
3881 if (len >= 5)
3882 connector->hdr_sink_metadata.hdmi_type1.max_fall = db[5];
3883 if (len >= 6)
3884 connector->hdr_sink_metadata.hdmi_type1.min_cll = db[6];
3885}
3886
3834static void3887static void
3835drm_parse_hdmi_vsdb_audio(struct drm_connector *connector, const u8 *db)3888drm_parse_hdmi_vsdb_audio(struct drm_connector *connector, const u8 *db)
3836{3889{
@@ -4458,6 +4511,8 @@ static void drm_parse_cea_ext(struct drm_connector *connector, · 621 unmodified lines
4458 drm_parse_y420cmdb_bitmap(connector, db);4511 drm_parse_y420cmdb_bitmap(connector, db);
4459 if (cea_db_is_vcdb(db))4512 if (cea_db_is_vcdb(db))
4460 drm_parse_vcdb(connector, db);4513 drm_parse_vcdb(connector, db);
4514 if (cea_db_is_hdmi_hdr_metadata_block(db))
4515 drm_parse_hdr_metadata_block(connector, db);
4461 }4516 }
4462}4517}
4463 4518
@@ -4850,6 +4905,78 @@ static bool is_hdmi2_sink(struct drm_connector *connector) · 386 unmodified lines
4850 connector->display_info.color_formats & DRM_COLOR_FORMAT_YCRCB420;4905 connector->display_info.color_formats & DRM_COLOR_FORMAT_YCRCB420;
4851}4906}
4852 4907
4908static inline bool is_eotf_supported(u8 output_eotf, u8 sink_eotf)
4909{
4910 return sink_eotf & BIT(output_eotf);
4911}
4912
4913/**
4914 * drm_hdmi_infoframe_set_hdr_metadata() - fill an HDMI DRM infoframe with
4915 * HDR metadata from userspace
4916 * @frame: HDMI DRM infoframe
4917 * @conn_state: Connector state containing HDR metadata
4918 *
4919 * Return: 0 on success or a negative error code on failure.
4920 */
4921int
4922drm_hdmi_infoframe_set_hdr_metadata(struct hdmi_drm_infoframe *frame,
4923 const struct drm_connector_state *conn_state)
4924{
4925 struct drm_connector *connector;
4926 struct hdr_output_metadata *hdr_metadata;
4927 int err;
4928
4929 if (!frame || !conn_state)
4930 return -EINVAL;
4931
4932 connector = conn_state->connector;
4933
4934 if (!conn_state->hdr_output_metadata)
4935 return -EINVAL;
4936
4937 hdr_metadata = conn_state->hdr_output_metadata->data;
4938
4939 if (!hdr_metadata || !connector)
4940 return -EINVAL;
4941
4942 /* Sink EOTF is Bit map while infoframe is absolute values */
4943 if (!is_eotf_supported(hdr_metadata->hdmi_metadata_type1.eotf,
4944 connector->hdr_sink_metadata.hdmi_type1.eotf)) {
4945 DRM_DEBUG_KMS("EOTF Not Supported\n");
4946 return -EINVAL;
4947 }
4948
4949 err = hdmi_drm_infoframe_init(frame);
4950 if (err < 0)
4951 return err;
4952
4953 frame->eotf = hdr_metadata->hdmi_metadata_type1.eotf;
4954 frame->metadata_type = hdr_metadata->hdmi_metadata_type1.metadata_type;
4955
4956 BUILD_BUG_ON(sizeof(frame->display_primaries) !=
4957 sizeof(hdr_metadata->hdmi_metadata_type1.display_primaries));
4958 BUILD_BUG_ON(sizeof(frame->white_point) !=
4959 sizeof(hdr_metadata->hdmi_metadata_type1.white_point));
4960
4961 memcpy(&frame->display_primaries,
4962 &hdr_metadata->hdmi_metadata_type1.display_primaries,
4963 sizeof(frame->display_primaries));
4964
4965 memcpy(&frame->white_point,
4966 &hdr_metadata->hdmi_metadata_type1.white_point,
4967 sizeof(frame->white_point));
4968
4969 frame->max_display_mastering_luminance =
4970 hdr_metadata->hdmi_metadata_type1.max_display_mastering_luminance;
4971 frame->min_display_mastering_luminance =
4972 hdr_metadata->hdmi_metadata_type1.min_display_mastering_luminance;
4973 frame->max_fall = hdr_metadata->hdmi_metadata_type1.max_fall;
4974 frame->max_cll = hdr_metadata->hdmi_metadata_type1.max_cll;
4975
4976 return 0;
4977}
4978EXPORT_SYMBOL(drm_hdmi_infoframe_set_hdr_metadata);
4979
4853/**4980/**
4854 * drm_hdmi_avi_infoframe_from_display_mode() - fill an HDMI AVI infoframe with4981 * drm_hdmi_avi_infoframe_from_display_mode() - fill an HDMI AVI infoframe with
4855 * data from a DRM display mode4982 * data from a DRM display mode
drivers/gpu/drm/drm_edid_load.c+5−2
@@ -7,12 +7,15 @@ · 6 unmodified lines
7 7
8*/8*/
9 9
10#include <linux/module.h>
11#include <linux/firmware.h>10#include <linux/firmware.h>
12#include <drm/drmP.h>11#include <linux/module.h>
12#include <linux/platform_device.h>
13
13#include <drm/drm_crtc.h>14#include <drm/drm_crtc.h>
14#include <drm/drm_crtc_helper.h>15#include <drm/drm_crtc_helper.h>
16#include <drm/drm_drv.h>
15#include <drm/drm_edid.h>17#include <drm/drm_edid.h>
18#include <drm/drm_print.h>
16 19
17static char edid_firmware[PATH_MAX];20static char edid_firmware[PATH_MAX];
18module_param_string(edid_firmware, edid_firmware, sizeof(edid_firmware), 0644);21module_param_string(edid_firmware, edid_firmware, sizeof(edid_firmware), 0644);
drivers/gpu/drm/drm_fb_helper.c+125−121
@@ -44,6 +44,7 @@ · 43 unmodified lines
44 44
45#include "drm_crtc_internal.h"45#include "drm_crtc_internal.h"
46#include "drm_crtc_helper_internal.h"46#include "drm_crtc_helper_internal.h"
47#include "drm_internal.h"
47 48
48static bool drm_fbdev_emulation = true;49static bool drm_fbdev_emulation = true;
49module_param_named(fbdev_emulation, drm_fbdev_emulation, bool, 0600);50module_param_named(fbdev_emulation, drm_fbdev_emulation, bool, 0600);
@@ -387,6 +388,49 @@ int drm_fb_helper_debug_leave(struct fb_info *info) · 337 unmodified lines
387}388}
388EXPORT_SYMBOL(drm_fb_helper_debug_leave);389EXPORT_SYMBOL(drm_fb_helper_debug_leave);
389 390
391/* Check if the plane can hw rotate to match panel orientation */
392static bool drm_fb_helper_panel_rotation(struct drm_mode_set *modeset,
393 unsigned int *rotation)
394{
395 struct drm_connector *connector = modeset->connectors[0];
396 struct drm_plane *plane = modeset->crtc->primary;
397 u64 valid_mask = 0;
398 unsigned int i;
399
400 if (!modeset->num_connectors)
401 return false;
402
403 switch (connector->display_info.panel_orientation) {
404 case DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP:
405 *rotation = DRM_MODE_ROTATE_180;
406 break;
407 case DRM_MODE_PANEL_ORIENTATION_LEFT_UP:
408 *rotation = DRM_MODE_ROTATE_90;
409 break;
410 case DRM_MODE_PANEL_ORIENTATION_RIGHT_UP:
411 *rotation = DRM_MODE_ROTATE_270;
412 break;
413 default:
414 *rotation = DRM_MODE_ROTATE_0;
415 }
416
417 /*
418 * TODO: support 90 / 270 degree hardware rotation,
419 * depending on the hardware this may require the framebuffer
420 * to be in a specific tiling format.
421 */
422 if (*rotation != DRM_MODE_ROTATE_180 || !plane->rotation_property)
423 return false;
424
425 for (i = 0; i < plane->rotation_property->num_values; i++)
426 valid_mask |= (1ULL << plane->rotation_property->values[i]);
427
428 if (!(*rotation & valid_mask))
429 return false;
430
431 return true;
432}
433
390static int restore_fbdev_mode_atomic(struct drm_fb_helper *fb_helper, bool active)434static int restore_fbdev_mode_atomic(struct drm_fb_helper *fb_helper, bool active)
391{435{
392 struct drm_device *dev = fb_helper->dev;436 struct drm_device *dev = fb_helper->dev;
@@ -427,10 +471,13 @@ retry: · 34 unmodified lines
427 for (i = 0; i < fb_helper->crtc_count; i++) {471 for (i = 0; i < fb_helper->crtc_count; i++) {
428 struct drm_mode_set *mode_set = &fb_helper->crtc_info[i].mode_set;472 struct drm_mode_set *mode_set = &fb_helper->crtc_info[i].mode_set;
429 struct drm_plane *primary = mode_set->crtc->primary;473 struct drm_plane *primary = mode_set->crtc->primary;
474 unsigned int rotation;
430 475
431 /* Cannot fail as we've already gotten the plane state above */476 if (drm_fb_helper_panel_rotation(mode_set, &rotation)) {
432 plane_state = drm_atomic_get_new_plane_state(state, primary);477 /* Cannot fail as we've already gotten the plane state above */
433 plane_state->rotation = fb_helper->crtc_info[i].rotation;478 plane_state = drm_atomic_get_new_plane_state(state, primary);
479 plane_state->rotation = rotation;
480 }
434 481
435 ret = __drm_atomic_helper_set_config(mode_set, state);482 ret = __drm_atomic_helper_set_config(mode_set, state);
436 if (ret != 0)483 if (ret != 0)
@@ -509,7 +556,7 @@ out: · 72 unmodified lines
509 return ret;556 return ret;
510}557}
511 558
512static int restore_fbdev_mode(struct drm_fb_helper *fb_helper)559static int restore_fbdev_mode_force(struct drm_fb_helper *fb_helper)
513{560{
514 struct drm_device *dev = fb_helper->dev;561 struct drm_device *dev = fb_helper->dev;
515 562
@@ -519,6 +566,21 @@ static int restore_fbdev_mode(struct drm_fb_helper *fb_helper) · 3 unmodified lines
519 return restore_fbdev_mode_legacy(fb_helper);566 return restore_fbdev_mode_legacy(fb_helper);
520}567}
521 568
569static int restore_fbdev_mode(struct drm_fb_helper *fb_helper)
570{
571 struct drm_device *dev = fb_helper->dev;
572 int ret;
573
574 if (!drm_master_internal_acquire(dev))
575 return -EBUSY;
576
577 ret = restore_fbdev_mode_force(fb_helper);
578
579 drm_master_internal_release(dev);
580
581 return ret;
582}
583
522/**584/**
523 * drm_fb_helper_restore_fbdev_mode_unlocked - restore fbdev configuration585 * drm_fb_helper_restore_fbdev_mode_unlocked - restore fbdev configuration
524 * @fb_helper: driver-allocated fbdev helper, can be NULL586 * @fb_helper: driver-allocated fbdev helper, can be NULL
@@ -542,7 +604,17 @@ int drm_fb_helper_restore_fbdev_mode_unlocked(struct drm_fb_helper *fb_helper) · 17 unmodified lines
542 return 0;604 return 0;
543 605
544 mutex_lock(&fb_helper->lock);606 mutex_lock(&fb_helper->lock);
545 ret = restore_fbdev_mode(fb_helper);607 /*
608 * TODO:
609 * We should bail out here if there is a master by dropping _force.
610 * Currently these igt tests fail if we do that:
611 * - kms_fbcon_fbt@psr
612 * - kms_fbcon_fbt@psr-suspend
613 *
614 * So first these tests need to be fixed so they drop master or don't
615 * have an fd open.
616 */
617 ret = restore_fbdev_mode_force(fb_helper);
546 618
547 do_delayed = fb_helper->delayed_hotplug;619 do_delayed = fb_helper->delayed_hotplug;
548 if (do_delayed)620 if (do_delayed)
@@ -556,34 +628,6 @@ int drm_fb_helper_restore_fbdev_mode_unlocked(struct drm_fb_helper *fb_helper) · 7 unmodified lines
556}628}
557EXPORT_SYMBOL(drm_fb_helper_restore_fbdev_mode_unlocked);629EXPORT_SYMBOL(drm_fb_helper_restore_fbdev_mode_unlocked);
558 630
559static bool drm_fb_helper_is_bound(struct drm_fb_helper *fb_helper)
560{
561 struct drm_device *dev = fb_helper->dev;
562 struct drm_crtc *crtc;
563 int bound = 0, crtcs_bound = 0;
564
565 /*
566 * Sometimes user space wants everything disabled, so don't steal the
567 * display if there's a master.
568 */
569 if (READ_ONCE(dev->master))
570 return false;
571
572 drm_for_each_crtc(crtc, dev) {
573 drm_modeset_lock(&crtc->mutex, NULL);
574 if (crtc->primary->fb)
575 crtcs_bound++;
576 if (crtc->primary->fb == fb_helper->fb)
577 bound++;
578 drm_modeset_unlock(&crtc->mutex);
579 }
580
581 if (bound < crtcs_bound)
582 return false;
583
584 return true;
585}
586
587#ifdef CONFIG_MAGIC_SYSRQ631#ifdef CONFIG_MAGIC_SYSRQ
588/*632/*
589 * restore fbcon display for all kms driver's using this helper, used for sysrq633 * restore fbcon display for all kms driver's using this helper, used for sysrq
@@ -604,7 +648,7 @@ static bool drm_fb_helper_force_kernel_mode(void) · 14 unmodified lines
604 continue;648 continue;
605 649
606 mutex_lock(&helper->lock);650 mutex_lock(&helper->lock);
607 ret = restore_fbdev_mode(helper);651 ret = restore_fbdev_mode_force(helper);
608 if (ret)652 if (ret)
609 error = true;653 error = true;
610 mutex_unlock(&helper->lock);654 mutex_unlock(&helper->lock);
@@ -663,20 +707,22 @@ static void dpms_legacy(struct drm_fb_helper *fb_helper, int dpms_mode) · 52 unmodified lines
663static void drm_fb_helper_dpms(struct fb_info *info, int dpms_mode)707static void drm_fb_helper_dpms(struct fb_info *info, int dpms_mode)
664{708{
665 struct drm_fb_helper *fb_helper = info->par;709 struct drm_fb_helper *fb_helper = info->par;
710 struct drm_device *dev = fb_helper->dev;
666 711
667 /*712 /*
668 * For each CRTC in this fb, turn the connectors on/off.713 * For each CRTC in this fb, turn the connectors on/off.
669 */714 */
670 mutex_lock(&fb_helper->lock);715 mutex_lock(&fb_helper->lock);
671 if (!drm_fb_helper_is_bound(fb_helper)) {716 if (!drm_master_internal_acquire(dev))
672 mutex_unlock(&fb_helper->lock);717 goto unlock;
673 return;
674 }
675 718
676 if (drm_drv_uses_atomic_modeset(fb_helper->dev))719 if (drm_drv_uses_atomic_modeset(dev))
677 restore_fbdev_mode_atomic(fb_helper, dpms_mode == DRM_MODE_DPMS_ON);720 restore_fbdev_mode_atomic(fb_helper, dpms_mode == DRM_MODE_DPMS_ON);
678 else721 else
679 dpms_legacy(fb_helper, dpms_mode);722 dpms_legacy(fb_helper, dpms_mode);
723
724 drm_master_internal_release(dev);
725unlock:
680 mutex_unlock(&fb_helper->lock);726 mutex_unlock(&fb_helper->lock);
681}727}
682 728
@@ -767,7 +813,7 @@ static void drm_fb_helper_dirty_blit_real(struct drm_fb_helper *fb_helper, · 84 unmodified lines
767 struct drm_clip_rect *clip)813 struct drm_clip_rect *clip)
768{814{
769 struct drm_framebuffer *fb = fb_helper->fb;815 struct drm_framebuffer *fb = fb_helper->fb;
770 unsigned int cpp = drm_format_plane_cpp(fb->format->format, 0);816 unsigned int cpp = fb->format->cpp[0];
771 size_t offset = clip->y1 * fb->pitches[0] + clip->x1 * cpp;817 size_t offset = clip->y1 * fb->pitches[0] + clip->x1 * cpp;
772 void *src = fb_helper->fbdev->screen_buffer + offset;818 void *src = fb_helper->fbdev->screen_buffer + offset;
773 void *dst = fb_helper->buffer->vaddr + offset;819 void *dst = fb_helper->buffer->vaddr + offset;
@@ -881,7 +927,6 @@ int drm_fb_helper_init(struct drm_device *dev, · 107 unmodified lines
881 if (!fb_helper->crtc_info[i].mode_set.connectors)927 if (!fb_helper->crtc_info[i].mode_set.connectors)
882 goto out_free;928 goto out_free;
883 fb_helper->crtc_info[i].mode_set.num_connectors = 0;929 fb_helper->crtc_info[i].mode_set.num_connectors = 0;
884 fb_helper->crtc_info[i].rotation = DRM_MODE_ROTATE_0;
885 }930 }
886 931
887 i = 0;932 i = 0;
@@ -1509,6 +1554,7 @@ backoff: · 621 unmodified lines
1509int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info)1554int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info)
1510{1555{
1511 struct drm_fb_helper *fb_helper = info->par;1556 struct drm_fb_helper *fb_helper = info->par;
1557 struct drm_device *dev = fb_helper->dev;
1512 int ret;1558 int ret;
1513 1559
1514 if (oops_in_progress)1560 if (oops_in_progress)
@@ -1516,9 +1562,9 @@ int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info) · 1 unmodified line
1516 1562
1517 mutex_lock(&fb_helper->lock);1563 mutex_lock(&fb_helper->lock);
1518 1564
1519 if (!drm_fb_helper_is_bound(fb_helper)) {1565 if (!drm_master_internal_acquire(dev)) {
1520 ret = -EBUSY;1566 ret = -EBUSY;
1521 goto out;1567 goto unlock;
1522 }1568 }
1523 1569
1524 if (info->fix.visual == FB_VISUAL_TRUECOLOR)1570 if (info->fix.visual == FB_VISUAL_TRUECOLOR)
@@ -1528,7 +1574,8 @@ int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info) · 3 unmodified lines
1528 else1574 else
1529 ret = setcmap_legacy(cmap, info);1575 ret = setcmap_legacy(cmap, info);
1530 1576
1531out:1577 drm_master_internal_release(dev);
1578unlock:
1532 mutex_unlock(&fb_helper->lock);1579 mutex_unlock(&fb_helper->lock);
1533 1580
1534 return ret;1581 return ret;
@@ -1548,12 +1595,13 @@ int drm_fb_helper_ioctl(struct fb_info *info, unsigned int cmd, · 13 unmodified lines
1548 unsigned long arg)1595 unsigned long arg)
1549{1596{
1550 struct drm_fb_helper *fb_helper = info->par;1597 struct drm_fb_helper *fb_helper = info->par;
1598 struct drm_device *dev = fb_helper->dev;
1551 struct drm_mode_set *mode_set;1599 struct drm_mode_set *mode_set;
1552 struct drm_crtc *crtc;1600 struct drm_crtc *crtc;
1553 int ret = 0;1601 int ret = 0;
1554 1602
1555 mutex_lock(&fb_helper->lock);1603 mutex_lock(&fb_helper->lock);
1556 if (!drm_fb_helper_is_bound(fb_helper)) {1604 if (!drm_master_internal_acquire(dev)) {
1557 ret = -EBUSY;1605 ret = -EBUSY;
1558 goto unlock;1606 goto unlock;
1559 }1607 }
@@ -1591,11 +1639,12 @@ int drm_fb_helper_ioctl(struct fb_info *info, unsigned int cmd, · 31 unmodified lines
1591 }1639 }
1592 1640
1593 ret = 0;1641 ret = 0;
1594 goto unlock;1642 break;
1595 default:1643 default:
1596 ret = -ENOTTY;1644 ret = -ENOTTY;
1597 }1645 }
1598 1646
1647 drm_master_internal_release(dev);
1599unlock:1648unlock:
1600 mutex_unlock(&fb_helper->lock);1649 mutex_unlock(&fb_helper->lock);
1601 return ret;1650 return ret;
@@ -1847,15 +1896,18 @@ int drm_fb_helper_pan_display(struct fb_var_screeninfo *var, · 245 unmodified lines
1847 return -EBUSY;1896 return -EBUSY;
1848 1897
1849 mutex_lock(&fb_helper->lock);1898 mutex_lock(&fb_helper->lock);
1850 if (!drm_fb_helper_is_bound(fb_helper)) {1899 if (!drm_master_internal_acquire(dev)) {
1851 mutex_unlock(&fb_helper->lock);1900 ret = -EBUSY;
1852 return -EBUSY;1901 goto unlock;
1853 }1902 }
1854 1903
1855 if (drm_drv_uses_atomic_modeset(dev))1904 if (drm_drv_uses_atomic_modeset(dev))
1856 ret = pan_display_atomic(var, info);1905 ret = pan_display_atomic(var, info);
1857 else1906 else
1858 ret = pan_display_legacy(var, info);1907 ret = pan_display_legacy(var, info);
1908
1909 drm_master_internal_release(dev);
1910unlock:
1859 mutex_unlock(&fb_helper->lock);1911 mutex_unlock(&fb_helper->lock);
1860 1912
1861 return ret;1913 return ret;
@@ -1979,16 +2031,16 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper, · 117 unmodified lines
1979 */2031 */
1980 bool lastv = true, lasth = true;2032 bool lastv = true, lasth = true;
1981 2033
1982 desired_mode = fb_helper->crtc_info[i].desired_mode;
1983 mode_set = &fb_helper->crtc_info[i].mode_set;2034 mode_set = &fb_helper->crtc_info[i].mode_set;
2035 desired_mode = mode_set->mode;
1984 2036
1985 if (!desired_mode)2037 if (!desired_mode)
1986 continue;2038 continue;
1987 2039
1988 crtc_count++;2040 crtc_count++;
1989 2041
1990 x = fb_helper->crtc_info[i].x;2042 x = mode_set->x;
1991 y = fb_helper->crtc_info[i].y;2043 y = mode_set->y;
1992 2044
1993 sizes.surface_width = max_t(u32, desired_mode->hdisplay + x, sizes.surface_width);2045 sizes.surface_width = max_t(u32, desired_mode->hdisplay + x, sizes.surface_width);
1994 sizes.surface_height = max_t(u32, desired_mode->vdisplay + y, sizes.surface_height);2046 sizes.surface_height = max_t(u32, desired_mode->vdisplay + y, sizes.surface_height);
@@ -2014,7 +2066,7 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper, · 19 unmodified lines
2014 DRM_INFO("Cannot find any crtc or sizes\n");2066 DRM_INFO("Cannot find any crtc or sizes\n");
2015 2067
2016 /* First time: disable all crtc's.. */2068 /* First time: disable all crtc's.. */
2017 if (!fb_helper->deferred_setup && !READ_ONCE(fb_helper->dev->master))2069 if (!fb_helper->deferred_setup)
2018 restore_fbdev_mode(fb_helper);2070 restore_fbdev_mode(fb_helper);
2019 return -EAGAIN;2071 return -EAGAIN;
2020 }2072 }
@@ -2503,62 +2555,6 @@ static int drm_pick_crtcs(struct drm_fb_helper *fb_helper, · 482 unmodified lines
2503 return best_score;2555 return best_score;
2504}2556}
2505 2557
2506/*
2507 * This function checks if rotation is necessary because of panel orientation
2508 * and if it is, if it is supported.
2509 * If rotation is necessary and supported, it gets set in fb_crtc.rotation.
2510 * If rotation is necessary but not supported, a DRM_MODE_ROTATE_* flag gets
2511 * or-ed into fb_helper->sw_rotations. In drm_setup_crtcs_fb() we check if only
2512 * one bit is set and then we set fb_info.fbcon_rotate_hint to make fbcon do
2513 * the unsupported rotation.
2514 */
2515static void drm_setup_crtc_rotation(struct drm_fb_helper *fb_helper,
2516 struct drm_fb_helper_crtc *fb_crtc,
2517 struct drm_connector *connector)
2518{
2519 struct drm_plane *plane = fb_crtc->mode_set.crtc->primary;
2520 uint64_t valid_mask = 0;
2521 int i, rotation;
2522
2523 fb_crtc->rotation = DRM_MODE_ROTATE_0;
2524
2525 switch (connector->display_info.panel_orientation) {
2526 case DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP:
2527 rotation = DRM_MODE_ROTATE_180;
2528 break;
2529 case DRM_MODE_PANEL_ORIENTATION_LEFT_UP:
2530 rotation = DRM_MODE_ROTATE_90;
2531 break;
2532 case DRM_MODE_PANEL_ORIENTATION_RIGHT_UP:
2533 rotation = DRM_MODE_ROTATE_270;
2534 break;
2535 default:
2536 rotation = DRM_MODE_ROTATE_0;
2537 }
2538
2539 /*
2540 * TODO: support 90 / 270 degree hardware rotation,
2541 * depending on the hardware this may require the framebuffer
2542 * to be in a specific tiling format.
2543 */
2544 if (rotation != DRM_MODE_ROTATE_180 || !plane->rotation_property) {
2545 fb_helper->sw_rotations |= rotation;
2546 return;
2547 }
2548
2549 for (i = 0; i < plane->rotation_property->num_values; i++)
2550 valid_mask |= (1ULL << plane->rotation_property->values[i]);
2551
2552 if (!(rotation & valid_mask)) {
2553 fb_helper->sw_rotations |= rotation;
2554 return;
2555 }
2556
2557 fb_crtc->rotation = rotation;
2558 /* Rotating in hardware, fbcon should not rotate */
2559 fb_helper->sw_rotations |= DRM_MODE_ROTATE_0;
2560}
2561
2562static struct drm_fb_helper_crtc *2558static struct drm_fb_helper_crtc *
2563drm_fb_helper_crtc(struct drm_fb_helper *fb_helper, struct drm_crtc *crtc)2559drm_fb_helper_crtc(struct drm_fb_helper *fb_helper, struct drm_crtc *crtc)
2564{2560{
@@ -2805,7 +2801,6 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper, · 240 unmodified lines
2805 drm_fb_helper_modeset_release(fb_helper,2801 drm_fb_helper_modeset_release(fb_helper,
2806 &fb_helper->crtc_info[i].mode_set);2802 &fb_helper->crtc_info[i].mode_set);
2807 2803
2808 fb_helper->sw_rotations = 0;
2809 drm_fb_helper_for_each_connector(fb_helper, i) {2804 drm_fb_helper_for_each_connector(fb_helper, i) {
2810 struct drm_display_mode *mode = modes[i];2805 struct drm_display_mode *mode = modes[i];
2811 struct drm_fb_helper_crtc *fb_crtc = crtcs[i];2806 struct drm_fb_helper_crtc *fb_crtc = crtcs[i];
@@ -2819,13 +2814,8 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper, · 7 unmodified lines
2819 DRM_DEBUG_KMS("desired mode %s set on crtc %d (%d,%d)\n",2814 DRM_DEBUG_KMS("desired mode %s set on crtc %d (%d,%d)\n",
2820 mode->name, fb_crtc->mode_set.crtc->base.id, offset->x, offset->y);2815 mode->name, fb_crtc->mode_set.crtc->base.id, offset->x, offset->y);
2821 2816
2822 fb_crtc->desired_mode = mode;2817 modeset->mode = drm_mode_duplicate(dev, mode);
2823 fb_crtc->x = offset->x;
2824 fb_crtc->y = offset->y;
2825 modeset->mode = drm_mode_duplicate(dev,
2826 fb_crtc->desired_mode);
2827 drm_connector_get(connector);2818 drm_connector_get(connector);
2828 drm_setup_crtc_rotation(fb_helper, fb_crtc, connector);
2829 modeset->connectors[modeset->num_connectors++] = connector;2819 modeset->connectors[modeset->num_connectors++] = connector;
2830 modeset->x = offset->x;2820 modeset->x = offset->x;
2831 modeset->y = offset->y;2821 modeset->y = offset->y;
@@ -2848,11 +2838,23 @@ out: · 16 unmodified lines
2848static void drm_setup_crtcs_fb(struct drm_fb_helper *fb_helper)2838static void drm_setup_crtcs_fb(struct drm_fb_helper *fb_helper)
2849{2839{
2850 struct fb_info *info = fb_helper->fbdev;2840 struct fb_info *info = fb_helper->fbdev;
2841 unsigned int rotation, sw_rotations = 0;
2851 int i;2842 int i;
2852 2843
2853 for (i = 0; i < fb_helper->crtc_count; i++)2844 for (i = 0; i < fb_helper->crtc_count; i++) {
2854 if (fb_helper->crtc_info[i].mode_set.num_connectors)2845 struct drm_mode_set *modeset = &fb_helper->crtc_info[i].mode_set;
2855 fb_helper->crtc_info[i].mode_set.fb = fb_helper->fb;2846
2847 if (!modeset->num_connectors)
2848 continue;
2849
2850 modeset->fb = fb_helper->fb;
2851
2852 if (drm_fb_helper_panel_rotation(modeset, &rotation))
2853 /* Rotating in hardware, fbcon should not rotate */
2854 sw_rotations |= DRM_MODE_ROTATE_0;
2855 else
2856 sw_rotations |= rotation;
2857 }
2856 2858
2857 mutex_lock(&fb_helper->dev->mode_config.mutex);2859 mutex_lock(&fb_helper->dev->mode_config.mutex);
2858 drm_fb_helper_for_each_connector(fb_helper, i) {2860 drm_fb_helper_for_each_connector(fb_helper, i) {
@@ -2868,7 +2870,7 @@ static void drm_setup_crtcs_fb(struct drm_fb_helper *fb_helper) · 9 unmodified lines
2868 }2870 }
2869 mutex_unlock(&fb_helper->dev->mode_config.mutex);2871 mutex_unlock(&fb_helper->dev->mode_config.mutex);
2870 2872
2871 switch (fb_helper->sw_rotations) {2873 switch (sw_rotations) {
2872 case DRM_MODE_ROTATE_0:2874 case DRM_MODE_ROTATE_0:
2873 info->fbcon_rotate_hint = FB_ROTATE_UR;2875 info->fbcon_rotate_hint = FB_ROTATE_UR;
2874 break;2876 break;
@@ -3041,12 +3043,14 @@ int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper) · 166 unmodified lines
3041 return err;3043 return err;
3042 }3044 }
3043 3045
3044 if (!fb_helper->fb || !drm_fb_helper_is_bound(fb_helper)) {3046 if (!fb_helper->fb || !drm_master_internal_acquire(fb_helper->dev)) {
3045 fb_helper->delayed_hotplug = true;3047 fb_helper->delayed_hotplug = true;
3046 mutex_unlock(&fb_helper->lock);3048 mutex_unlock(&fb_helper->lock);
3047 return err;3049 return err;
3048 }3050 }
3049 3051
3052 drm_master_internal_release(fb_helper->dev);
3053
3050 DRM_DEBUG_KMS("\n");3054 DRM_DEBUG_KMS("\n");
3051 3055
3052 drm_setup_crtcs(fb_helper, fb_helper->fb->width, fb_helper->fb->height);3056 drm_setup_crtcs(fb_helper, fb_helper->fb->width, fb_helper->fb->height);
drivers/gpu/drm/drm_file.c+50−72
@@ -100,8 +100,6 @@ DEFINE_MUTEX(drm_global_mutex); · 99 unmodified lines
100 * :ref:`IOCTL support in the userland interfaces chapter<drm_driver_ioctl>`.100 * :ref:`IOCTL support in the userland interfaces chapter<drm_driver_ioctl>`.
101 */101 */
102 102
103static int drm_open_helper(struct file *filp, struct drm_minor *minor);
104
105/**103/**
106 * drm_file_alloc - allocate file context104 * drm_file_alloc - allocate file context
107 * @minor: minor to allocate on105 * @minor: minor to allocate on
@@ -273,76 +271,6 @@ static void drm_close_helper(struct file *filp) · 165 unmodified lines
273 drm_file_free(file_priv);271 drm_file_free(file_priv);
274}272}
275 273
276static int drm_setup(struct drm_device * dev)
277{
278 int ret;
279
280 if (dev->driver->firstopen &&
281 drm_core_check_feature(dev, DRIVER_LEGACY)) {
282 ret = dev->driver->firstopen(dev);
283 if (ret != 0)
284 return ret;
285 }
286
287 ret = drm_legacy_dma_setup(dev);
288 if (ret < 0)
289 return ret;
290
291
292 DRM_DEBUG("\n");
293 return 0;
294}
295
296/**
297 * drm_open - open method for DRM file
298 * @inode: device inode
299 * @filp: file pointer.
300 *
301 * This function must be used by drivers as their &file_operations.open method.
302 * It looks up the correct DRM device and instantiates all the per-file
303 * resources for it. It also calls the &drm_driver.open driver callback.
304 *
305 * RETURNS:
306 *
307 * 0 on success or negative errno value on falure.
308 */
309int drm_open(struct inode *inode, struct file *filp)
310{
311 struct drm_device *dev;
312 struct drm_minor *minor;
313 int retcode;
314 int need_setup = 0;
315
316 minor = drm_minor_acquire(iminor(inode));
317 if (IS_ERR(minor))
318 return PTR_ERR(minor);
319
320 dev = minor->dev;
321 if (!dev->open_count++)
322 need_setup = 1;
323
324 /* share address_space across all char-devs of a single device */
325 filp->f_mapping = dev->anon_inode->i_mapping;
326
327 retcode = drm_open_helper(filp, minor);
328 if (retcode)
329 goto err_undo;
330 if (need_setup) {
331 retcode = drm_setup(dev);
332 if (retcode) {
333 drm_close_helper(filp);
334 goto err_undo;
335 }
336 }
337 return 0;
338
339err_undo:
340 dev->open_count--;
341 drm_minor_release(minor);
342 return retcode;
343}
344EXPORT_SYMBOL(drm_open);
345
346/*274/*
347 * Check whether DRI will run on this CPU.275 * Check whether DRI will run on this CPU.
348 *276 *
@@ -424,6 +352,56 @@ static int drm_open_helper(struct file *filp, struct drm_minor *minor) · 75 unmodified lines
424 return 0;352 return 0;
425}353}
426 354
355/**
356 * drm_open - open method for DRM file
357 * @inode: device inode
358 * @filp: file pointer.
359 *
360 * This function must be used by drivers as their &file_operations.open method.
361 * It looks up the correct DRM device and instantiates all the per-file
362 * resources for it. It also calls the &drm_driver.open driver callback.
363 *
364 * RETURNS:
365 *
366 * 0 on success or negative errno value on falure.
367 */
368int drm_open(struct inode *inode, struct file *filp)
369{
370 struct drm_device *dev;
371 struct drm_minor *minor;
372 int retcode;
373 int need_setup = 0;
374
375 minor = drm_minor_acquire(iminor(inode));
376 if (IS_ERR(minor))
377 return PTR_ERR(minor);
378
379 dev = minor->dev;
380 if (!dev->open_count++)
381 need_setup = 1;
382
383 /* share address_space across all char-devs of a single device */
384 filp->f_mapping = dev->anon_inode->i_mapping;
385
386 retcode = drm_open_helper(filp, minor);
387 if (retcode)
388 goto err_undo;
389 if (need_setup) {
390 retcode = drm_legacy_setup(dev);
391 if (retcode) {
392 drm_close_helper(filp);
393 goto err_undo;
394 }
395 }
396 return 0;
397
398err_undo:
399 dev->open_count--;
400 drm_minor_release(minor);
401 return retcode;
402}
403EXPORT_SYMBOL(drm_open);
404
427void drm_lastclose(struct drm_device * dev)405void drm_lastclose(struct drm_device * dev)
428{406{
429 DRM_DEBUG("\n");407 DRM_DEBUG("\n");
drivers/gpu/drm/drm_format_helper.c+2−2
@@ -36,7 +36,7 @@ static unsigned int clip_offset(struct drm_rect *clip, · 35 unmodified lines
36void drm_fb_memcpy(void *dst, void *vaddr, struct drm_framebuffer *fb,36void drm_fb_memcpy(void *dst, void *vaddr, struct drm_framebuffer *fb,
37 struct drm_rect *clip)37 struct drm_rect *clip)
38{38{
39 unsigned int cpp = drm_format_plane_cpp(fb->format->format, 0);39 unsigned int cpp = fb->format->cpp[0];
40 size_t len = (clip->x2 - clip->x1) * cpp;40 size_t len = (clip->x2 - clip->x1) * cpp;
41 unsigned int y, lines = clip->y2 - clip->y1;41 unsigned int y, lines = clip->y2 - clip->y1;
42 42
@@ -63,7 +63,7 @@ void drm_fb_memcpy_dstclip(void __iomem *dst, void *vaddr, · 20 unmodified lines
63 struct drm_framebuffer *fb,63 struct drm_framebuffer *fb,
64 struct drm_rect *clip)64 struct drm_rect *clip)
65{65{
66 unsigned int cpp = drm_format_plane_cpp(fb->format->format, 0);66 unsigned int cpp = fb->format->cpp[0];
67 unsigned int offset = clip_offset(clip, fb->pitches[0], cpp);67 unsigned int offset = clip_offset(clip, fb->pitches[0], cpp);
68 size_t len = (clip->x2 - clip->x1) * cpp;68 size_t len = (clip->x2 - clip->x1) * cpp;
69 unsigned int y, lines = clip->y2 - clip->y1;69 unsigned int y, lines = clip->y2 - clip->y1;
drivers/gpu/drm/drm_fourcc.c+0−118
@@ -332,124 +332,6 @@ drm_get_format_info(struct drm_device *dev, · 331 unmodified lines
332}332}
333EXPORT_SYMBOL(drm_get_format_info);333EXPORT_SYMBOL(drm_get_format_info);
334 334
335/**
336 * drm_format_num_planes - get the number of planes for format
337 * @format: pixel format (DRM_FORMAT_*)
338 *
339 * Returns:
340 * The number of planes used by the specified pixel format.
341 */
342int drm_format_num_planes(uint32_t format)
343{
344 const struct drm_format_info *info;
345
346 info = drm_format_info(format);
347 return info ? info->num_planes : 1;
348}
349EXPORT_SYMBOL(drm_format_num_planes);
350
351/**
352 * drm_format_plane_cpp - determine the bytes per pixel value
353 * @format: pixel format (DRM_FORMAT_*)
354 * @plane: plane index
355 *
356 * Returns:
357 * The bytes per pixel value for the specified plane.
358 */
359int drm_format_plane_cpp(uint32_t format, int plane)
360{
361 const struct drm_format_info *info;
362
363 info = drm_format_info(format);
364 if (!info || plane >= info->num_planes)
365 return 0;
366
367 return info->cpp[plane];
368}
369EXPORT_SYMBOL(drm_format_plane_cpp);
370
371/**
372 * drm_format_horz_chroma_subsampling - get the horizontal chroma subsampling factor
373 * @format: pixel format (DRM_FORMAT_*)
374 *
375 * Returns:
376 * The horizontal chroma subsampling factor for the
377 * specified pixel format.
378 */
379int drm_format_horz_chroma_subsampling(uint32_t format)
380{
381 const struct drm_format_info *info;
382
383 info = drm_format_info(format);
384 return info ? info->hsub : 1;
385}
386EXPORT_SYMBOL(drm_format_horz_chroma_subsampling);
387
388/**
389 * drm_format_vert_chroma_subsampling - get the vertical chroma subsampling factor
390 * @format: pixel format (DRM_FORMAT_*)
391 *
392 * Returns:
393 * The vertical chroma subsampling factor for the
394 * specified pixel format.
395 */
396int drm_format_vert_chroma_subsampling(uint32_t format)
397{
398 const struct drm_format_info *info;
399
400 info = drm_format_info(format);
401 return info ? info->vsub : 1;
402}
403EXPORT_SYMBOL(drm_format_vert_chroma_subsampling);
404
405/**
406 * drm_format_plane_width - width of the plane given the first plane
407 * @width: width of the first plane
408 * @format: pixel format
409 * @plane: plane index
410 *
411 * Returns:
412 * The width of @plane, given that the width of the first plane is @width.
413 */
414int drm_format_plane_width(int width, uint32_t format, int plane)
415{
416 const struct drm_format_info *info;
417
418 info = drm_format_info(format);
419 if (!info || plane >= info->num_planes)
420 return 0;
421
422 if (plane == 0)
423 return width;
424
425 return width / info->hsub;
426}
427EXPORT_SYMBOL(drm_format_plane_width);
428
429/**
430 * drm_format_plane_height - height of the plane given the first plane
431 * @height: height of the first plane
432 * @format: pixel format
433 * @plane: plane index
434 *
435 * Returns:
436 * The height of @plane, given that the height of the first plane is @height.
437 */
438int drm_format_plane_height(int height, uint32_t format, int plane)
439{
440 const struct drm_format_info *info;
441
442 info = drm_format_info(format);
443 if (!info || plane >= info->num_planes)
444 return 0;
445
446 if (plane == 0)
447 return height;
448
449 return height / info->vsub;
450}
451EXPORT_SYMBOL(drm_format_plane_height);
452
453/**335/**
454 * drm_format_info_block_width - width in pixels of block.336 * drm_format_info_block_width - width in pixels of block.
455 * @info: pixel format info337 * @info: pixel format info
drivers/gpu/drm/drm_gem_vram_helper.c+772−0
@@ -0,0 +1,772 @@
1// SPDX-License-Identifier: GPL-2.0-or-later
2
3#include <drm/drm_gem_vram_helper.h>
4#include <drm/drm_device.h>
5#include <drm/drm_mode.h>
6#include <drm/drm_prime.h>
7#include <drm/drm_vram_mm_helper.h>
8#include <drm/ttm/ttm_page_alloc.h>
9
10/**
11 * DOC: overview
12 *
13 * This library provides a GEM buffer object that is backed by video RAM
14 * (VRAM). It can be used for framebuffer devices with dedicated memory.
15 */
16
17/*
18 * Buffer-objects helpers
19 */
20
21static void drm_gem_vram_cleanup(struct drm_gem_vram_object *gbo)
22{
23 /* We got here via ttm_bo_put(), which means that the
24 * TTM buffer object in 'bo' has already been cleaned
25 * up; only release the GEM object.
26 */
27 drm_gem_object_release(&gbo->gem);
28}
29
30static void drm_gem_vram_destroy(struct drm_gem_vram_object *gbo)
31{
32 drm_gem_vram_cleanup(gbo);
33 kfree(gbo);
34}
35
36static void ttm_buffer_object_destroy(struct ttm_buffer_object *bo)
37{
38 struct drm_gem_vram_object *gbo = drm_gem_vram_of_bo(bo);
39
40 drm_gem_vram_destroy(gbo);
41}
42
43static void drm_gem_vram_placement(struct drm_gem_vram_object *gbo,
44 unsigned long pl_flag)
45{
46 unsigned int i;
47 unsigned int c = 0;
48
49 gbo->placement.placement = gbo->placements;
50 gbo->placement.busy_placement = gbo->placements;
51
52 if (pl_flag & TTM_PL_FLAG_VRAM)
53 gbo->placements[c++].flags = TTM_PL_FLAG_WC |
54 TTM_PL_FLAG_UNCACHED |
55 TTM_PL_FLAG_VRAM;
56
57 if (pl_flag & TTM_PL_FLAG_SYSTEM)
58 gbo->placements[c++].flags = TTM_PL_MASK_CACHING |
59 TTM_PL_FLAG_SYSTEM;
60
61 if (!c)
62 gbo->placements[c++].flags = TTM_PL_MASK_CACHING |
63 TTM_PL_FLAG_SYSTEM;
64
65 gbo->placement.num_placement = c;
66 gbo->placement.num_busy_placement = c;
67
68 for (i = 0; i < c; ++i) {
69 gbo->placements[i].fpfn = 0;
70 gbo->placements[i].lpfn = 0;
71 }
72}
73
74static int drm_gem_vram_init(struct drm_device *dev,
75 struct ttm_bo_device *bdev,
76 struct drm_gem_vram_object *gbo,
77 size_t size, unsigned long pg_align,
78 bool interruptible)
79{
80 int ret;
81 size_t acc_size;
82
83 ret = drm_gem_object_init(dev, &gbo->gem, size);
84 if (ret)
85 return ret;
86
87 acc_size = ttm_bo_dma_acc_size(bdev, size, sizeof(*gbo));
88
89 gbo->bo.bdev = bdev;
90 drm_gem_vram_placement(gbo, TTM_PL_FLAG_VRAM | TTM_PL_FLAG_SYSTEM);
91
92 ret = ttm_bo_init(bdev, &gbo->bo, size, ttm_bo_type_device,
93 &gbo->placement, pg_align, interruptible, acc_size,
94 NULL, NULL, ttm_buffer_object_destroy);
95 if (ret)
96 goto err_drm_gem_object_release;
97
98 return 0;
99
100err_drm_gem_object_release:
101 drm_gem_object_release(&gbo->gem);
102 return ret;
103}
104
105/**
106 * drm_gem_vram_create() - Creates a VRAM-backed GEM object
107 * @dev: the DRM device
108 * @bdev: the TTM BO device backing the object
109 * @size: the buffer size in bytes
110 * @pg_align: the buffer's alignment in multiples of the page size
111 * @interruptible: sleep interruptible if waiting for memory
112 *
113 * Returns:
114 * A new instance of &struct drm_gem_vram_object on success, or
115 * an ERR_PTR()-encoded error code otherwise.
116 */
117struct drm_gem_vram_object *drm_gem_vram_create(struct drm_device *dev,
118 struct ttm_bo_device *bdev,
119 size_t size,
120 unsigned long pg_align,
121 bool interruptible)
122{
123 struct drm_gem_vram_object *gbo;
124 int ret;
125
126 gbo = kzalloc(sizeof(*gbo), GFP_KERNEL);
127 if (!gbo)
128 return ERR_PTR(-ENOMEM);
129
130 ret = drm_gem_vram_init(dev, bdev, gbo, size, pg_align, interruptible);
131 if (ret < 0)
132 goto err_kfree;
133
134 return gbo;
135
136err_kfree:
137 kfree(gbo);
138 return ERR_PTR(ret);
139}
140EXPORT_SYMBOL(drm_gem_vram_create);
141
142/**
143 * drm_gem_vram_put() - Releases a reference to a VRAM-backed GEM object
144 * @gbo: the GEM VRAM object
145 *
146 * See ttm_bo_put() for more information.
147 */
148void drm_gem_vram_put(struct drm_gem_vram_object *gbo)
149{
150 ttm_bo_put(&gbo->bo);
151}
152EXPORT_SYMBOL(drm_gem_vram_put);
153
154/**
155 * drm_gem_vram_lock() - Locks a VRAM-backed GEM object
156 * @gbo: the GEM VRAM object
157 * @no_wait: don't wait for buffer object to become available
158 *
159 * See ttm_bo_reserve() for more information.
160 *
161 * Returns:
162 * 0 on success, or
163 * a negative error code otherwise
164 */
165int drm_gem_vram_lock(struct drm_gem_vram_object *gbo, bool no_wait)
166{
167 return ttm_bo_reserve(&gbo->bo, true, no_wait, NULL);
168}
169EXPORT_SYMBOL(drm_gem_vram_lock);
170
171/**
172 * drm_gem_vram_unlock() - \
173 Release a reservation acquired by drm_gem_vram_lock()
174 * @gbo: the GEM VRAM object
175 *
176 * See ttm_bo_unreserve() for more information.
177 */
178void drm_gem_vram_unlock(struct drm_gem_vram_object *gbo)
179{
180 ttm_bo_unreserve(&gbo->bo);
181}
182EXPORT_SYMBOL(drm_gem_vram_unlock);
183
184/**
185 * drm_gem_vram_mmap_offset() - Returns a GEM VRAM object's mmap offset
186 * @gbo: the GEM VRAM object
187 *
188 * See drm_vma_node_offset_addr() for more information.
189 *
190 * Returns:
191 * The buffer object's offset for userspace mappings on success, or
192 * 0 if no offset is allocated.
193 */
194u64 drm_gem_vram_mmap_offset(struct drm_gem_vram_object *gbo)
195{
196 return drm_vma_node_offset_addr(&gbo->bo.vma_node);
197}
198EXPORT_SYMBOL(drm_gem_vram_mmap_offset);
199
200/**
201 * drm_gem_vram_offset() - \
202 Returns a GEM VRAM object's offset in video memory
203 * @gbo: the GEM VRAM object
204 *
205 * This function returns the buffer object's offset in the device's video
206 * memory. The buffer object has to be pinned to %TTM_PL_VRAM.
207 *
208 * Returns:
209 * The buffer object's offset in video memory on success, or
210 * a negative errno code otherwise.
211 */
212s64 drm_gem_vram_offset(struct drm_gem_vram_object *gbo)
213{
214 if (WARN_ON_ONCE(!gbo->pin_count))
215 return (s64)-ENODEV;
216 return gbo->bo.offset;
217}
218EXPORT_SYMBOL(drm_gem_vram_offset);
219
220/**
221 * drm_gem_vram_pin() - Pins a GEM VRAM object in a region.
222 * @gbo: the GEM VRAM object
223 * @pl_flag: a bitmask of possible memory regions
224 *
225 * Pinning a buffer object ensures that it is not evicted from
226 * a memory region. A pinned buffer object has to be unpinned before
227 * it can be pinned to another region.
228 *
229 * Returns:
230 * 0 on success, or
231 * a negative error code otherwise.
232 */
233int drm_gem_vram_pin(struct drm_gem_vram_object *gbo, unsigned long pl_flag)
234{
235 int i, ret;
236 struct ttm_operation_ctx ctx = { false, false };
237
238 ret = ttm_bo_reserve(&gbo->bo, true, false, NULL);
239 if (ret < 0)
240 return ret;
241
242 if (gbo->pin_count)
243 goto out;
244
245 drm_gem_vram_placement(gbo, pl_flag);
246 for (i = 0; i < gbo->placement.num_placement; ++i)
247 gbo->placements[i].flags |= TTM_PL_FLAG_NO_EVICT;
248
249 ret = ttm_bo_validate(&gbo->bo, &gbo->placement, &ctx);
250 if (ret < 0)
251 goto err_ttm_bo_unreserve;
252
253out:
254 ++gbo->pin_count;
255 ttm_bo_unreserve(&gbo->bo);
256
257 return 0;
258
259err_ttm_bo_unreserve:
260 ttm_bo_unreserve(&gbo->bo);
261 return ret;
262}
263EXPORT_SYMBOL(drm_gem_vram_pin);
264
265/**
266 * drm_gem_vram_pin_locked() - Pins a GEM VRAM object in a region.
267 * @gbo: the GEM VRAM object
268 * @pl_flag: a bitmask of possible memory regions
269 *
270 * Pinning a buffer object ensures that it is not evicted from
271 * a memory region. A pinned buffer object has to be unpinned before
272 * it can be pinned to another region.
273 *
274 * This function pins a GEM VRAM object that has already been
275 * locked. Use drm_gem_vram_pin() if possible.
276 *
277 * Returns:
278 * 0 on success, or
279 * a negative error code otherwise.
280 */
281int drm_gem_vram_pin_locked(struct drm_gem_vram_object *gbo,
282 unsigned long pl_flag)
283{
284 int i, ret;
285 struct ttm_operation_ctx ctx = { false, false };
286
287 lockdep_assert_held(&gbo->bo.resv->lock.base);
288
289 if (gbo->pin_count) {
290 ++gbo->pin_count;
291 return 0;
292 }
293
294 drm_gem_vram_placement(gbo, pl_flag);
295 for (i = 0; i < gbo->placement.num_placement; ++i)
296 gbo->placements[i].flags |= TTM_PL_FLAG_NO_EVICT;
297
298 ret = ttm_bo_validate(&gbo->bo, &gbo->placement, &ctx);
299 if (ret < 0)
300 return ret;
301
302 gbo->pin_count = 1;
303
304 return 0;
305}
306EXPORT_SYMBOL(drm_gem_vram_pin_locked);
307
308/**
309 * drm_gem_vram_unpin() - Unpins a GEM VRAM object
310 * @gbo: the GEM VRAM object
311 *
312 * Returns:
313 * 0 on success, or
314 * a negative error code otherwise.
315 */
316int drm_gem_vram_unpin(struct drm_gem_vram_object *gbo)
317{
318 int i, ret;
319 struct ttm_operation_ctx ctx = { false, false };
320
321 ret = ttm_bo_reserve(&gbo->bo, true, false, NULL);
322 if (ret < 0)
323 return ret;
324
325 if (WARN_ON_ONCE(!gbo->pin_count))
326 goto out;
327
328 --gbo->pin_count;
329 if (gbo->pin_count)
330 goto out;
331
332 for (i = 0; i < gbo->placement.num_placement ; ++i)
333 gbo->placements[i].flags &= ~TTM_PL_FLAG_NO_EVICT;
334
335 ret = ttm_bo_validate(&gbo->bo, &gbo->placement, &ctx);
336 if (ret < 0)
337 goto err_ttm_bo_unreserve;
338
339out:
340 ttm_bo_unreserve(&gbo->bo);
341
342 return 0;
343
344err_ttm_bo_unreserve:
345 ttm_bo_unreserve(&gbo->bo);
346 return ret;
347}
348EXPORT_SYMBOL(drm_gem_vram_unpin);
349
350/**
351 * drm_gem_vram_unpin_locked() - Unpins a GEM VRAM object
352 * @gbo: the GEM VRAM object
353 *
354 * This function unpins a GEM VRAM object that has already been
355 * locked. Use drm_gem_vram_unpin() if possible.
356 *
357 * Returns:
358 * 0 on success, or
359 * a negative error code otherwise.
360 */
361int drm_gem_vram_unpin_locked(struct drm_gem_vram_object *gbo)
362{
363 int i, ret;
364 struct ttm_operation_ctx ctx = { false, false };
365
366 lockdep_assert_held(&gbo->bo.resv->lock.base);
367
368 if (WARN_ON_ONCE(!gbo->pin_count))
369 return 0;
370
371 --gbo->pin_count;
372 if (gbo->pin_count)
373 return 0;
374
375 for (i = 0; i < gbo->placement.num_placement ; ++i)
376 gbo->placements[i].flags &= ~TTM_PL_FLAG_NO_EVICT;
377
378 ret = ttm_bo_validate(&gbo->bo, &gbo->placement, &ctx);
379 if (ret < 0)
380 return ret;
381
382 return 0;
383}
384EXPORT_SYMBOL(drm_gem_vram_unpin_locked);
385
386/**
387 * drm_gem_vram_kmap_at() - Maps a GEM VRAM object into kernel address space
388 * @gbo: the GEM VRAM object
389 * @map: establish a mapping if necessary
390 * @is_iomem: returns true if the mapped memory is I/O memory, or false \
391 otherwise; can be NULL
392 * @kmap: the mapping's kmap object
393 *
394 * This function maps the buffer object into the kernel's address space
395 * or returns the current mapping. If the parameter map is false, the
396 * function only queries the current mapping, but does not establish a
397 * new one.
398 *
399 * Returns:
400 * The buffers virtual address if mapped, or
401 * NULL if not mapped, or
402 * an ERR_PTR()-encoded error code otherwise.
403 */
404void *drm_gem_vram_kmap_at(struct drm_gem_vram_object *gbo, bool map,
405 bool *is_iomem, struct ttm_bo_kmap_obj *kmap)
406{
407 int ret;
408
409 if (kmap->virtual || !map)
410 goto out;
411
412 ret = ttm_bo_kmap(&gbo->bo, 0, gbo->bo.num_pages, kmap);
413 if (ret)
414 return ERR_PTR(ret);
415
416out:
417 if (!is_iomem)
418 return kmap->virtual;
419 if (!kmap->virtual) {
420 *is_iomem = false;
421 return NULL;
422 }
423 return ttm_kmap_obj_virtual(kmap, is_iomem);
424}
425EXPORT_SYMBOL(drm_gem_vram_kmap_at);
426
427/**
428 * drm_gem_vram_kmap() - Maps a GEM VRAM object into kernel address space
429 * @gbo: the GEM VRAM object
430 * @map: establish a mapping if necessary
431 * @is_iomem: returns true if the mapped memory is I/O memory, or false \
432 otherwise; can be NULL
433 *
434 * This function maps the buffer object into the kernel's address space
435 * or returns the current mapping. If the parameter map is false, the
436 * function only queries the current mapping, but does not establish a
437 * new one.
438 *
439 * Returns:
440 * The buffers virtual address if mapped, or
441 * NULL if not mapped, or
442 * an ERR_PTR()-encoded error code otherwise.
443 */
444void *drm_gem_vram_kmap(struct drm_gem_vram_object *gbo, bool map,
445 bool *is_iomem)
446{
447 return drm_gem_vram_kmap_at(gbo, map, is_iomem, &gbo->kmap);
448}
449EXPORT_SYMBOL(drm_gem_vram_kmap);
450
451/**
452 * drm_gem_vram_kunmap_at() - Unmaps a GEM VRAM object
453 * @gbo: the GEM VRAM object
454 * @kmap: the mapping's kmap object
455 */
456void drm_gem_vram_kunmap_at(struct drm_gem_vram_object *gbo,
457 struct ttm_bo_kmap_obj *kmap)
458{
459 if (!kmap->virtual)
460 return;
461
462 ttm_bo_kunmap(kmap);
463 kmap->virtual = NULL;
464}
465EXPORT_SYMBOL(drm_gem_vram_kunmap_at);
466
467/**
468 * drm_gem_vram_kunmap() - Unmaps a GEM VRAM object
469 * @gbo: the GEM VRAM object
470 */
471void drm_gem_vram_kunmap(struct drm_gem_vram_object *gbo)
472{
473 drm_gem_vram_kunmap_at(gbo, &gbo->kmap);
474}
475EXPORT_SYMBOL(drm_gem_vram_kunmap);
476
477/**
478 * drm_gem_vram_fill_create_dumb() - \
479 Helper for implementing &struct drm_driver.dumb_create
480 * @file: the DRM file
481 * @dev: the DRM device
482 * @bdev: the TTM BO device managing the buffer object
483 * @pg_align: the buffer's alignment in multiples of the page size
484 * @interruptible: sleep interruptible if waiting for memory
485 * @args: the arguments as provided to \
486 &struct drm_driver.dumb_create
487 *
488 * This helper function fills &struct drm_mode_create_dumb, which is used
489 * by &struct drm_driver.dumb_create. Implementations of this interface
490 * should forwards their arguments to this helper, plus the driver-specific
491 * parameters.
492 *
493 * Returns:
494 * 0 on success, or
495 * a negative error code otherwise.
496 */
497int drm_gem_vram_fill_create_dumb(struct drm_file *file,
498 struct drm_device *dev,
499 struct ttm_bo_device *bdev,
500 unsigned long pg_align,
501 bool interruptible,
502 struct drm_mode_create_dumb *args)
503{
504 size_t pitch, size;
505 struct drm_gem_vram_object *gbo;
506 int ret;
507 u32 handle;
508
509 pitch = args->width * ((args->bpp + 7) / 8);
510 size = pitch * args->height;
511
512 size = roundup(size, PAGE_SIZE);
513 if (!size)
514 return -EINVAL;
515
516 gbo = drm_gem_vram_create(dev, bdev, size, pg_align, interruptible);
517 if (IS_ERR(gbo))
518 return PTR_ERR(gbo);
519
520 ret = drm_gem_handle_create(file, &gbo->gem, &handle);
521 if (ret)
522 goto err_drm_gem_object_put_unlocked;
523
524 drm_gem_object_put_unlocked(&gbo->gem);
525
526 args->pitch = pitch;
527 args->size = size;
528 args->handle = handle;
529
530 return 0;
531
532err_drm_gem_object_put_unlocked:
533 drm_gem_object_put_unlocked(&gbo->gem);
534 return ret;
535}
536EXPORT_SYMBOL(drm_gem_vram_fill_create_dumb);
537
538/*
539 * Helpers for struct ttm_bo_driver
540 */
541
542static bool drm_is_gem_vram(struct ttm_buffer_object *bo)
543{
544 return (bo->destroy == ttm_buffer_object_destroy);
545}
546
547/**
548 * drm_gem_vram_bo_driver_evict_flags() - \
549 Implements &struct ttm_bo_driver.evict_flags
550 * @bo: TTM buffer object. Refers to &struct drm_gem_vram_object.bo
551 * @pl: TTM placement information.
552 */
553void drm_gem_vram_bo_driver_evict_flags(struct ttm_buffer_object *bo,
554 struct ttm_placement *pl)
555{
556 struct drm_gem_vram_object *gbo;
557
558 /* TTM may pass BOs that are not GEM VRAM BOs. */
559 if (!drm_is_gem_vram(bo))
560 return;
561
562 gbo = drm_gem_vram_of_bo(bo);
563 drm_gem_vram_placement(gbo, TTM_PL_FLAG_SYSTEM);
564 *pl = gbo->placement;
565}
566EXPORT_SYMBOL(drm_gem_vram_bo_driver_evict_flags);
567
568/**
569 * drm_gem_vram_bo_driver_verify_access() - \
570 Implements &struct ttm_bo_driver.verify_access
571 * @bo: TTM buffer object. Refers to &struct drm_gem_vram_object.bo
572 * @filp: File pointer.
573 *
574 * Returns:
575 * 0 on success, or
576 * a negative errno code otherwise.
577 */
578int drm_gem_vram_bo_driver_verify_access(struct ttm_buffer_object *bo,
579 struct file *filp)
580{
581 struct drm_gem_vram_object *gbo = drm_gem_vram_of_bo(bo);
582
583 return drm_vma_node_verify_access(&gbo->gem.vma_node,
584 filp->private_data);
585}
586EXPORT_SYMBOL(drm_gem_vram_bo_driver_verify_access);
587
588/**
589 * drm_gem_vram_mm_funcs - Functions for &struct drm_vram_mm
590 *
591 * Most users of @struct drm_gem_vram_object will also use
592 * @struct drm_vram_mm. This instance of &struct drm_vram_mm_funcs
593 * can be used to connect both.
594 */
595const struct drm_vram_mm_funcs drm_gem_vram_mm_funcs = {
596 .evict_flags = drm_gem_vram_bo_driver_evict_flags,
597 .verify_access = drm_gem_vram_bo_driver_verify_access
598};
599EXPORT_SYMBOL(drm_gem_vram_mm_funcs);
600
601/*
602 * Helpers for struct drm_driver
603 */
604
605/**
606 * drm_gem_vram_driver_gem_free_object_unlocked() - \
607 Implements &struct drm_driver.gem_free_object_unlocked
608 * @gem: GEM object. Refers to &struct drm_gem_vram_object.gem
609 */
610void drm_gem_vram_driver_gem_free_object_unlocked(struct drm_gem_object *gem)
611{
612 struct drm_gem_vram_object *gbo = drm_gem_vram_of_gem(gem);
613
614 drm_gem_vram_put(gbo);
615}
616EXPORT_SYMBOL(drm_gem_vram_driver_gem_free_object_unlocked);
617
618/**
619 * drm_gem_vram_driver_create_dumb() - \
620 Implements &struct drm_driver.dumb_create
621 * @file: the DRM file
622 * @dev: the DRM device
623 * @args: the arguments as provided to \
624 &struct drm_driver.dumb_create
625 *
626 * This function requires the driver to use @drm_device.vram_mm for its
627 * instance of VRAM MM.
628 *
629 * Returns:
630 * 0 on success, or
631 * a negative error code otherwise.
632 */
633int drm_gem_vram_driver_dumb_create(struct drm_file *file,
634 struct drm_device *dev,
635 struct drm_mode_create_dumb *args)
636{
637 if (WARN_ONCE(!dev->vram_mm, "VRAM MM not initialized"))
638 return -EINVAL;
639
640 return drm_gem_vram_fill_create_dumb(file, dev, &dev->vram_mm->bdev, 0,
641 false, args);
642}
643EXPORT_SYMBOL(drm_gem_vram_driver_dumb_create);
644
645/**
646 * drm_gem_vram_driver_dumb_mmap_offset() - \
647 Implements &struct drm_driver.dumb_mmap_offset
648 * @file: DRM file pointer.
649 * @dev: DRM device.
650 * @handle: GEM handle
651 * @offset: Returns the mapping's memory offset on success
652 *
653 * Returns:
654 * 0 on success, or
655 * a negative errno code otherwise.
656 */
657int drm_gem_vram_driver_dumb_mmap_offset(struct drm_file *file,
658 struct drm_device *dev,
659 uint32_t handle, uint64_t *offset)
660{
661 struct drm_gem_object *gem;
662 struct drm_gem_vram_object *gbo;
663
664 gem = drm_gem_object_lookup(file, handle);
665 if (!gem)
666 return -ENOENT;
667
668 gbo = drm_gem_vram_of_gem(gem);
669 *offset = drm_gem_vram_mmap_offset(gbo);
670
671 drm_gem_object_put_unlocked(gem);
672
673 return 0;
674}
675EXPORT_SYMBOL(drm_gem_vram_driver_dumb_mmap_offset);
676
677/*
678 * PRIME helpers for struct drm_driver
679 */
680
681/**
682 * drm_gem_vram_driver_gem_prime_pin() - \
683 Implements &struct drm_driver.gem_prime_pin
684 * @gem: The GEM object to pin
685 *
686 * Returns:
687 * 0 on success, or
688 * a negative errno code otherwise.
689 */
690int drm_gem_vram_driver_gem_prime_pin(struct drm_gem_object *gem)
691{
692 struct drm_gem_vram_object *gbo = drm_gem_vram_of_gem(gem);
693
694 return drm_gem_vram_pin(gbo, DRM_GEM_VRAM_PL_FLAG_VRAM);
695}
696EXPORT_SYMBOL(drm_gem_vram_driver_gem_prime_pin);
697
698/**
699 * drm_gem_vram_driver_gem_prime_unpin() - \
700 Implements &struct drm_driver.gem_prime_unpin
701 * @gem: The GEM object to unpin
702 */
703void drm_gem_vram_driver_gem_prime_unpin(struct drm_gem_object *gem)
704{
705 struct drm_gem_vram_object *gbo = drm_gem_vram_of_gem(gem);
706
707 drm_gem_vram_unpin(gbo);
708}
709EXPORT_SYMBOL(drm_gem_vram_driver_gem_prime_unpin);
710
711/**
712 * drm_gem_vram_driver_gem_prime_vmap() - \
713 Implements &struct drm_driver.gem_prime_vmap
714 * @gem: The GEM object to map
715 *
716 * Returns:
717 * The buffers virtual address on success, or
718 * NULL otherwise.
719 */
720void *drm_gem_vram_driver_gem_prime_vmap(struct drm_gem_object *gem)
721{
722 struct drm_gem_vram_object *gbo = drm_gem_vram_of_gem(gem);
723 int ret;
724 void *base;
725
726 ret = drm_gem_vram_pin(gbo, DRM_GEM_VRAM_PL_FLAG_VRAM);
727 if (ret)
728 return NULL;
729 base = drm_gem_vram_kmap(gbo, true, NULL);
730 if (IS_ERR(base)) {
731 drm_gem_vram_unpin(gbo);
732 return NULL;
733 }
734 return base;
735}
736EXPORT_SYMBOL(drm_gem_vram_driver_gem_prime_vmap);
737
738/**
739 * drm_gem_vram_driver_gem_prime_vunmap() - \
740 Implements &struct drm_driver.gem_prime_vunmap
741 * @gem: The GEM object to unmap
742 * @vaddr: The mapping's base address
743 */
744void drm_gem_vram_driver_gem_prime_vunmap(struct drm_gem_object *gem,
745 void *vaddr)
746{
747 struct drm_gem_vram_object *gbo = drm_gem_vram_of_gem(gem);
748
749 drm_gem_vram_kunmap(gbo);
750 drm_gem_vram_unpin(gbo);
751}
752EXPORT_SYMBOL(drm_gem_vram_driver_gem_prime_vunmap);
753
754/**
755 * drm_gem_vram_driver_gem_prime_mmap() - \
756 Implements &struct drm_driver.gem_prime_mmap
757 * @gem: The GEM object to map
758 * @vma: The VMA describing the mapping
759 *
760 * Returns:
761 * 0 on success, or
762 * a negative errno code otherwise.
763 */
764int drm_gem_vram_driver_gem_prime_mmap(struct drm_gem_object *gem,
765 struct vm_area_struct *vma)
766{
767 struct drm_gem_vram_object *gbo = drm_gem_vram_of_gem(gem);
768
769 gbo->gem.vma_node.vm_node.start = gbo->bo.vma_node.vm_node.start;
770 return drm_gem_prime_mmap(gem, vma);
771}
772EXPORT_SYMBOL(drm_gem_vram_driver_gem_prime_mmap);
drivers/gpu/drm/drm_internal.h+2−0
@@ -93,6 +93,8 @@ int drm_dropmaster_ioctl(struct drm_device *dev, void *data, · 92 unmodified lines
93 struct drm_file *file_priv);93 struct drm_file *file_priv);
94int drm_master_open(struct drm_file *file_priv);94int drm_master_open(struct drm_file *file_priv);
95void drm_master_release(struct drm_file *file_priv);95void drm_master_release(struct drm_file *file_priv);
96bool drm_master_internal_acquire(struct drm_device *dev);
97void drm_master_internal_release(struct drm_device *dev);
96 98
97/* drm_sysfs.c */99/* drm_sysfs.c */
98extern struct class *drm_class;100extern struct class *drm_class;
drivers/gpu/drm/drm_legacy.h+2−0
@@ -187,10 +187,12 @@ int drm_legacy_sg_free(struct drm_device *dev, void *data, · 186 unmodified lines
187void drm_legacy_init_members(struct drm_device *dev);187void drm_legacy_init_members(struct drm_device *dev);
188void drm_legacy_destroy_members(struct drm_device *dev);188void drm_legacy_destroy_members(struct drm_device *dev);
189void drm_legacy_dev_reinit(struct drm_device *dev);189void drm_legacy_dev_reinit(struct drm_device *dev);
190int drm_legacy_setup(struct drm_device * dev);
190#else191#else
191static inline void drm_legacy_init_members(struct drm_device *dev) {}192static inline void drm_legacy_init_members(struct drm_device *dev) {}
192static inline void drm_legacy_destroy_members(struct drm_device *dev) {}193static inline void drm_legacy_destroy_members(struct drm_device *dev) {}
193static inline void drm_legacy_dev_reinit(struct drm_device *dev) {}194static inline void drm_legacy_dev_reinit(struct drm_device *dev) {}
195static inline int drm_legacy_setup(struct drm_device * dev) { return 0; }
194#endif196#endif
195 197
196#if IS_ENABLED(CONFIG_DRM_LEGACY)198#if IS_ENABLED(CONFIG_DRM_LEGACY)
drivers/gpu/drm/drm_legacy_misc.c+20−0
@@ -51,6 +51,26 @@ void drm_legacy_destroy_members(struct drm_device *dev) · 50 unmodified lines
51 mutex_destroy(&dev->ctxlist_mutex);51 mutex_destroy(&dev->ctxlist_mutex);
52}52}
53 53
54int drm_legacy_setup(struct drm_device * dev)
55{
56 int ret;
57
58 if (dev->driver->firstopen &&
59 drm_core_check_feature(dev, DRIVER_LEGACY)) {
60 ret = dev->driver->firstopen(dev);
61 if (ret != 0)
62 return ret;
63 }
64
65 ret = drm_legacy_dma_setup(dev);
66 if (ret < 0)
67 return ret;
68
69
70 DRM_DEBUG("\n");
71 return 0;
72}
73
54void drm_legacy_dev_reinit(struct drm_device *dev)74void drm_legacy_dev_reinit(struct drm_device *dev)
55{75{
56 if (dev->irq_enabled)76 if (dev->irq_enabled)
drivers/gpu/drm/drm_prime.c+17−60
@@ -86,11 +86,6 @@ struct drm_prime_member { · 85 unmodified lines
86 struct rb_node handle_rb;86 struct rb_node handle_rb;
87};87};
88 88
89struct drm_prime_attachment {
90 struct sg_table *sgt;
91 enum dma_data_direction dir;
92};
93
94static int drm_prime_add_buf_handle(struct drm_prime_file_private *prime_fpriv,89static int drm_prime_add_buf_handle(struct drm_prime_file_private *prime_fpriv,
95 struct dma_buf *dma_buf, uint32_t handle)90 struct dma_buf *dma_buf, uint32_t handle)
96{91{
@@ -188,25 +183,16 @@ static int drm_prime_lookup_buf_handle(struct drm_prime_file_private *prime_fpri · 91 unmodified lines
188 * @dma_buf: buffer to attach device to183 * @dma_buf: buffer to attach device to
189 * @attach: buffer attachment data184 * @attach: buffer attachment data
190 *185 *
191 * Allocates &drm_prime_attachment and calls &drm_driver.gem_prime_pin for186 * Calls &drm_driver.gem_prime_pin for device specific handling. This can be
192 * device specific attachment. This can be used as the &dma_buf_ops.attach187 * used as the &dma_buf_ops.attach callback.
193 * callback.
194 *188 *
195 * Returns 0 on success, negative error code on failure.189 * Returns 0 on success, negative error code on failure.
196 */190 */
197int drm_gem_map_attach(struct dma_buf *dma_buf,191int drm_gem_map_attach(struct dma_buf *dma_buf,
198 struct dma_buf_attachment *attach)192 struct dma_buf_attachment *attach)
199{193{
200 struct drm_prime_attachment *prime_attach;
201 struct drm_gem_object *obj = dma_buf->priv;194 struct drm_gem_object *obj = dma_buf->priv;
202 195
203 prime_attach = kzalloc(sizeof(*prime_attach), GFP_KERNEL);
204 if (!prime_attach)
205 return -ENOMEM;
206
207 prime_attach->dir = DMA_NONE;
208 attach->priv = prime_attach;
209
210 return drm_gem_pin(obj);196 return drm_gem_pin(obj);
211}197}
212EXPORT_SYMBOL(drm_gem_map_attach);198EXPORT_SYMBOL(drm_gem_map_attach);
@@ -222,26 +208,8 @@ EXPORT_SYMBOL(drm_gem_map_attach); · 9 unmodified lines
222void drm_gem_map_detach(struct dma_buf *dma_buf,208void drm_gem_map_detach(struct dma_buf *dma_buf,
223 struct dma_buf_attachment *attach)209 struct dma_buf_attachment *attach)
224{210{
225 struct drm_prime_attachment *prime_attach = attach->priv;
226 struct drm_gem_object *obj = dma_buf->priv;211 struct drm_gem_object *obj = dma_buf->priv;
227 212
228 if (prime_attach) {
229 struct sg_table *sgt = prime_attach->sgt;
230
231 if (sgt) {
232 if (prime_attach->dir != DMA_NONE)
233 dma_unmap_sg_attrs(attach->dev, sgt->sgl,
234 sgt->nents,
235 prime_attach->dir,
236 DMA_ATTR_SKIP_CPU_SYNC);
237 sg_free_table(sgt);
238 }
239
240 kfree(sgt);
241 kfree(prime_attach);
242 attach->priv = NULL;
243 }
244
245 drm_gem_unpin(obj);213 drm_gem_unpin(obj);
246}214}
247EXPORT_SYMBOL(drm_gem_map_detach);215EXPORT_SYMBOL(drm_gem_map_detach);
@@ -286,39 +254,22 @@ void drm_prime_remove_buf_handle_locked(struct drm_prime_file_private *prime_fpr · 38 unmodified lines
286struct sg_table *drm_gem_map_dma_buf(struct dma_buf_attachment *attach,254struct sg_table *drm_gem_map_dma_buf(struct dma_buf_attachment *attach,
287 enum dma_data_direction dir)255 enum dma_data_direction dir)
288{256{
289 struct drm_prime_attachment *prime_attach = attach->priv;
290 struct drm_gem_object *obj = attach->dmabuf->priv;257 struct drm_gem_object *obj = attach->dmabuf->priv;
291 struct sg_table *sgt;258 struct sg_table *sgt;
292 259
293 if (WARN_ON(dir == DMA_NONE || !prime_attach))260 if (WARN_ON(dir == DMA_NONE))
294 return ERR_PTR(-EINVAL);261 return ERR_PTR(-EINVAL);
295 262
296 /* return the cached mapping when possible */
297 if (prime_attach->dir == dir)
298 return prime_attach->sgt;
299
300 /*
301 * two mappings with different directions for the same attachment are
302 * not allowed
303 */
304 if (WARN_ON(prime_attach->dir != DMA_NONE))
305 return ERR_PTR(-EBUSY);
306
307 if (obj->funcs)263 if (obj->funcs)
308 sgt = obj->funcs->get_sg_table(obj);264 sgt = obj->funcs->get_sg_table(obj);
309 else265 else
310 sgt = obj->dev->driver->gem_prime_get_sg_table(obj);266 sgt = obj->dev->driver->gem_prime_get_sg_table(obj);
311 267
312 if (!IS_ERR(sgt)) {268 if (!dma_map_sg_attrs(attach->dev, sgt->sgl, sgt->nents, dir,
313 if (!dma_map_sg_attrs(attach->dev, sgt->sgl, sgt->nents, dir,269 DMA_ATTR_SKIP_CPU_SYNC)) {
314 DMA_ATTR_SKIP_CPU_SYNC)) {270 sg_free_table(sgt);
315 sg_free_table(sgt);271 kfree(sgt);
316 kfree(sgt);272 sgt = ERR_PTR(-ENOMEM);
317 sgt = ERR_PTR(-ENOMEM);
318 } else {
319 prime_attach->sgt = sgt;
320 prime_attach->dir = dir;
321 }
322 }273 }
323 274
324 return sgt;275 return sgt;
@@ -331,14 +282,19 @@ EXPORT_SYMBOL(drm_gem_map_dma_buf); · 6 unmodified lines
331 * @sgt: scatterlist info of the buffer to unmap282 * @sgt: scatterlist info of the buffer to unmap
332 * @dir: direction of DMA transfer283 * @dir: direction of DMA transfer
333 *284 *
334 * Not implemented. The unmap is done at drm_gem_map_detach(). This can be285 * This can be used as the &dma_buf_ops.unmap_dma_buf callback.
335 * used as the &dma_buf_ops.unmap_dma_buf callback.
336 */286 */
337void drm_gem_unmap_dma_buf(struct dma_buf_attachment *attach,287void drm_gem_unmap_dma_buf(struct dma_buf_attachment *attach,
338 struct sg_table *sgt,288 struct sg_table *sgt,
339 enum dma_data_direction dir)289 enum dma_data_direction dir)
340{290{
341 /* nothing to be done here */291 if (!sgt)
292 return;
293
294 dma_unmap_sg_attrs(attach->dev, sgt->sgl, sgt->nents, dir,
295 DMA_ATTR_SKIP_CPU_SYNC);
296 sg_free_table(sgt);
297 kfree(sgt);
342}298}
343EXPORT_SYMBOL(drm_gem_unmap_dma_buf);299EXPORT_SYMBOL(drm_gem_unmap_dma_buf);
344 300
@@ -452,6 +408,7 @@ int drm_gem_dmabuf_mmap(struct dma_buf *dma_buf, struct vm_area_struct *vma) · 107 unmodified lines
452EXPORT_SYMBOL(drm_gem_dmabuf_mmap);408EXPORT_SYMBOL(drm_gem_dmabuf_mmap);
453 409
454static const struct dma_buf_ops drm_gem_prime_dmabuf_ops = {410static const struct dma_buf_ops drm_gem_prime_dmabuf_ops = {
411 .cache_sgt_mapping = true,
455 .attach = drm_gem_map_attach,412 .attach = drm_gem_map_attach,
456 .detach = drm_gem_map_detach,413 .detach = drm_gem_map_detach,
457 .map_dma_buf = drm_gem_map_dma_buf,414 .map_dma_buf = drm_gem_map_dma_buf,
drivers/gpu/drm/drm_vram_helper_common.c+96−0
@@ -0,0 +1,96 @@
1// SPDX-License-Identifier: GPL-2.0-or-later
2
3#include <linux/module.h>
4
5/**
6 * DOC: overview
7 *
8 * This library provides &struct drm_gem_vram_object (GEM VRAM), a GEM
9 * buffer object that is backed by video RAM. It can be used for
10 * framebuffer devices with dedicated memory. The video RAM can be
11 * managed with &struct drm_vram_mm (VRAM MM). Both data structures are
12 * supposed to be used together, but can also be used individually.
13 *
14 * With the GEM interface userspace applications create, manage and destroy
15 * graphics buffers, such as an on-screen framebuffer. GEM does not provide
16 * an implementation of these interfaces. It's up to the DRM driver to
17 * provide an implementation that suits the hardware. If the hardware device
18 * contains dedicated video memory, the DRM driver can use the VRAM helper
19 * library. Each active buffer object is stored in video RAM. Active
20 * buffer are used for drawing the current frame, typically something like
21 * the frame's scanout buffer or the cursor image. If there's no more space
22 * left in VRAM, inactive GEM objects can be moved to system memory.
23 *
24 * The easiest way to use the VRAM helper library is to call
25 * drm_vram_helper_alloc_mm(). The function allocates and initializes an
26 * instance of &struct drm_vram_mm in &struct drm_device.vram_mm . Use
27 * &DRM_GEM_VRAM_DRIVER to initialize &struct drm_driver and
28 * &DRM_VRAM_MM_FILE_OPERATIONS to initialize &struct file_operations;
29 * as illustrated below.
30 *
31 * .. code-block:: c
32 *
33 * struct file_operations fops ={
34 * .owner = THIS_MODULE,
35 * DRM_VRAM_MM_FILE_OPERATION
36 * };
37 * struct drm_driver drv = {
38 * .driver_feature = DRM_ ... ,
39 * .fops = &fops,
40 * DRM_GEM_VRAM_DRIVER
41 * };
42 *
43 * int init_drm_driver()
44 * {
45 * struct drm_device *dev;
46 * uint64_t vram_base;
47 * unsigned long vram_size;
48 * int ret;
49 *
50 * // setup device, vram base and size
51 * // ...
52 *
53 * ret = drm_vram_helper_alloc_mm(dev, vram_base, vram_size,
54 * &drm_gem_vram_mm_funcs);
55 * if (ret)
56 * return ret;
57 * return 0;
58 * }
59 *
60 * This creates an instance of &struct drm_vram_mm, exports DRM userspace
61 * interfaces for GEM buffer management and initializes file operations to
62 * allow for accessing created GEM buffers. With this setup, the DRM driver
63 * manages an area of video RAM with VRAM MM and provides GEM VRAM objects
64 * to userspace.
65 *
66 * To clean up the VRAM memory management, call drm_vram_helper_release_mm()
67 * in the driver's clean-up code.
68 *
69 * .. code-block:: c
70 *
71 * void fini_drm_driver()
72 * {
73 * struct drm_device *dev = ...;
74 *
75 * drm_vram_helper_release_mm(dev);
76 * }
77 *
78 * For drawing or scanout operations, buffer object have to be pinned in video
79 * RAM. Call drm_gem_vram_pin() with &DRM_GEM_VRAM_PL_FLAG_VRAM or
80 * &DRM_GEM_VRAM_PL_FLAG_SYSTEM to pin a buffer object in video RAM or system
81 * memory. Call drm_gem_vram_unpin() to release the pinned object afterwards.
82 *
83 * A buffer object that is pinned in video RAM has a fixed address within that
84 * memory region. Call drm_gem_vram_offset() to retrieve this value. Typically
85 * it's used to program the hardware's scanout engine for framebuffers, set
86 * the cursor overlay's image for a mouse cursor, or use it as input to the
87 * hardware's draing engine.
88 *
89 * To access a buffer object's memory from the DRM driver, call
90 * drm_gem_vram_kmap(). It (optionally) maps the buffer into kernel address
91 * space and returns the memory address. Use drm_gem_vram_kunmap() to
92 * release the mapping.
93 */
94
95MODULE_DESCRIPTION("DRM VRAM memory-management helpers");
96MODULE_LICENSE("GPL");
drivers/gpu/drm/drm_vram_mm_helper.c+295−0
@@ -0,0 +1,295 @@
1// SPDX-License-Identifier: GPL-2.0-or-later
2
3#include <drm/drm_vram_mm_helper.h>
4#include <drm/drmP.h>
5#include <drm/ttm/ttm_page_alloc.h>
6
7/**
8 * DOC: overview
9 *
10 * The data structure &struct drm_vram_mm and its helpers implement a memory
11 * manager for simple framebuffer devices with dedicated video memory. Buffer
12 * objects are either placed in video RAM or evicted to system memory. These
13 * helper functions work well with &struct drm_gem_vram_object.
14 */
15
16/*
17 * TTM TT
18 */
19
20static void backend_func_destroy(struct ttm_tt *tt)
21{
22 ttm_tt_fini(tt);
23 kfree(tt);
24}
25
26static struct ttm_backend_func backend_func = {
27 .destroy = backend_func_destroy
28};
29
30/*
31 * TTM BO device
32 */
33
34static struct ttm_tt *bo_driver_ttm_tt_create(struct ttm_buffer_object *bo,
35 uint32_t page_flags)
36{
37 struct ttm_tt *tt;
38 int ret;
39
40 tt = kzalloc(sizeof(*tt), GFP_KERNEL);
41 if (!tt)
42 return NULL;
43
44 tt->func = &backend_func;
45
46 ret = ttm_tt_init(tt, bo, page_flags);
47 if (ret < 0)
48 goto err_ttm_tt_init;
49
50 return tt;
51
52err_ttm_tt_init:
53 kfree(tt);
54 return NULL;
55}
56
57static int bo_driver_init_mem_type(struct ttm_bo_device *bdev, uint32_t type,
58 struct ttm_mem_type_manager *man)
59{
60 switch (type) {
61 case TTM_PL_SYSTEM:
62 man->flags = TTM_MEMTYPE_FLAG_MAPPABLE;
63 man->available_caching = TTM_PL_MASK_CACHING;
64 man->default_caching = TTM_PL_FLAG_CACHED;
65 break;
66 case TTM_PL_VRAM:
67 man->func = &ttm_bo_manager_func;
68 man->flags = TTM_MEMTYPE_FLAG_FIXED |
69 TTM_MEMTYPE_FLAG_MAPPABLE;
70 man->available_caching = TTM_PL_FLAG_UNCACHED |
71 TTM_PL_FLAG_WC;
72 man->default_caching = TTM_PL_FLAG_WC;
73 break;
74 default:
75 return -EINVAL;
76 }
77 return 0;
78}
79
80static void bo_driver_evict_flags(struct ttm_buffer_object *bo,
81 struct ttm_placement *placement)
82{
83 struct drm_vram_mm *vmm = drm_vram_mm_of_bdev(bo->bdev);
84
85 if (vmm->funcs && vmm->funcs->evict_flags)
86 vmm->funcs->evict_flags(bo, placement);
87}
88
89static int bo_driver_verify_access(struct ttm_buffer_object *bo,
90 struct file *filp)
91{
92 struct drm_vram_mm *vmm = drm_vram_mm_of_bdev(bo->bdev);
93
94 if (!vmm->funcs || !vmm->funcs->verify_access)
95 return 0;
96 return vmm->funcs->verify_access(bo, filp);
97}
98
99static int bo_driver_io_mem_reserve(struct ttm_bo_device *bdev,
100 struct ttm_mem_reg *mem)
101{
102 struct ttm_mem_type_manager *man = bdev->man + mem->mem_type;
103 struct drm_vram_mm *vmm = drm_vram_mm_of_bdev(bdev);
104
105 if (!(man->flags & TTM_MEMTYPE_FLAG_MAPPABLE))
106 return -EINVAL;
107
108 mem->bus.addr = NULL;
109 mem->bus.size = mem->num_pages << PAGE_SHIFT;
110
111 switch (mem->mem_type) {
112 case TTM_PL_SYSTEM: /* nothing to do */
113 mem->bus.offset = 0;
114 mem->bus.base = 0;
115 mem->bus.is_iomem = false;
116 break;
117 case TTM_PL_VRAM:
118 mem->bus.offset = mem->start << PAGE_SHIFT;
119 mem->bus.base = vmm->vram_base;
120 mem->bus.is_iomem = true;
121 break;
122 default:
123 return -EINVAL;
124 }
125
126 return 0;
127}
128
129static void bo_driver_io_mem_free(struct ttm_bo_device *bdev,
130 struct ttm_mem_reg *mem)
131{ }
132
133static struct ttm_bo_driver bo_driver = {
134 .ttm_tt_create = bo_driver_ttm_tt_create,
135 .ttm_tt_populate = ttm_pool_populate,
136 .ttm_tt_unpopulate = ttm_pool_unpopulate,
137 .init_mem_type = bo_driver_init_mem_type,
138 .eviction_valuable = ttm_bo_eviction_valuable,
139 .evict_flags = bo_driver_evict_flags,
140 .verify_access = bo_driver_verify_access,
141 .io_mem_reserve = bo_driver_io_mem_reserve,
142 .io_mem_free = bo_driver_io_mem_free,
143};
144
145/*
146 * struct drm_vram_mm
147 */
148
149/**
150 * drm_vram_mm_init() - Initialize an instance of VRAM MM.
151 * @vmm: the VRAM MM instance to initialize
152 * @dev: the DRM device
153 * @vram_base: the base address of the video memory
154 * @vram_size: the size of the video memory in bytes
155 * @funcs: callback functions for buffer objects
156 *
157 * Returns:
158 * 0 on success, or
159 * a negative error code otherwise.
160 */
161int drm_vram_mm_init(struct drm_vram_mm *vmm, struct drm_device *dev,
162 uint64_t vram_base, size_t vram_size,
163 const struct drm_vram_mm_funcs *funcs)
164{
165 int ret;
166
167 vmm->vram_base = vram_base;
168 vmm->vram_size = vram_size;
169 vmm->funcs = funcs;
170
171 ret = ttm_bo_device_init(&vmm->bdev, &bo_driver,
172 dev->anon_inode->i_mapping,
173 true);
174 if (ret)
175 return ret;
176
177 ret = ttm_bo_init_mm(&vmm->bdev, TTM_PL_VRAM, vram_size >> PAGE_SHIFT);
178 if (ret)
179 return ret;
180
181 return 0;
182}
183EXPORT_SYMBOL(drm_vram_mm_init);
184
185/**
186 * drm_vram_mm_cleanup() - Cleans up an initialized instance of VRAM MM.
187 * @vmm: the VRAM MM instance to clean up
188 */
189void drm_vram_mm_cleanup(struct drm_vram_mm *vmm)
190{
191 ttm_bo_device_release(&vmm->bdev);
192}
193EXPORT_SYMBOL(drm_vram_mm_cleanup);
194
195/**
196 * drm_vram_mm_mmap() - Helper for implementing &struct file_operations.mmap()
197 * @filp: the mapping's file structure
198 * @vma: the mapping's memory area
199 * @vmm: the VRAM MM instance
200 *
201 * Returns:
202 * 0 on success, or
203 * a negative error code otherwise.
204 */
205int drm_vram_mm_mmap(struct file *filp, struct vm_area_struct *vma,
206 struct drm_vram_mm *vmm)
207{
208 return ttm_bo_mmap(filp, vma, &vmm->bdev);
209}
210EXPORT_SYMBOL(drm_vram_mm_mmap);
211
212/*
213 * Helpers for integration with struct drm_device
214 */
215
216/**
217 * drm_vram_helper_alloc_mm - Allocates a device's instance of \
218 &struct drm_vram_mm
219 * @dev: the DRM device
220 * @vram_base: the base address of the video memory
221 * @vram_size: the size of the video memory in bytes
222 * @funcs: callback functions for buffer objects
223 *
224 * Returns:
225 * The new instance of &struct drm_vram_mm on success, or
226 * an ERR_PTR()-encoded errno code otherwise.
227 */
228struct drm_vram_mm *drm_vram_helper_alloc_mm(
229 struct drm_device *dev, uint64_t vram_base, size_t vram_size,
230 const struct drm_vram_mm_funcs *funcs)
231{
232 int ret;
233
234 if (WARN_ON(dev->vram_mm))
235 return dev->vram_mm;
236
237 dev->vram_mm = kzalloc(sizeof(*dev->vram_mm), GFP_KERNEL);
238 if (!dev->vram_mm)
239 return ERR_PTR(-ENOMEM);
240
241 ret = drm_vram_mm_init(dev->vram_mm, dev, vram_base, vram_size, funcs);
242 if (ret)
243 goto err_kfree;
244
245 return dev->vram_mm;
246
247err_kfree:
248 kfree(dev->vram_mm);
249 dev->vram_mm = NULL;
250 return ERR_PTR(ret);
251}
252EXPORT_SYMBOL(drm_vram_helper_alloc_mm);
253
254/**
255 * drm_vram_helper_release_mm - Releases a device's instance of \
256 &struct drm_vram_mm
257 * @dev: the DRM device
258 */
259void drm_vram_helper_release_mm(struct drm_device *dev)
260{
261 if (!dev->vram_mm)
262 return;
263
264 drm_vram_mm_cleanup(dev->vram_mm);
265 kfree(dev->vram_mm);
266 dev->vram_mm = NULL;
267}
268EXPORT_SYMBOL(drm_vram_helper_release_mm);
269
270/*
271 * Helpers for &struct file_operations
272 */
273
274/**
275 * drm_vram_mm_file_operations_mmap() - \
276 Implements &struct file_operations.mmap()
277 * @filp: the mapping's file structure
278 * @vma: the mapping's memory area
279 *
280 * Returns:
281 * 0 on success, or
282 * a negative error code otherwise.
283 */
284int drm_vram_mm_file_operations_mmap(
285 struct file *filp, struct vm_area_struct *vma)
286{
287 struct drm_file *file_priv = filp->private_data;
288 struct drm_device *dev = file_priv->minor->dev;
289
290 if (WARN_ONCE(!dev->vram_mm, "VRAM MM not initialized"))
291 return -EINVAL;
292
293 return drm_vram_mm_mmap(filp, vma, dev->vram_mm);
294}
295EXPORT_SYMBOL(drm_vram_mm_file_operations_mmap);
drivers/gpu/drm/etnaviv/etnaviv_dump.c+0−5
@@ -118,7 +118,6 @@ void etnaviv_core_dump(struct etnaviv_gpu *gpu) · 117 unmodified lines
118 unsigned int n_obj, n_bomap_pages;118 unsigned int n_obj, n_bomap_pages;
119 size_t file_size, mmu_size;119 size_t file_size, mmu_size;
120 __le64 *bomap, *bomap_start;120 __le64 *bomap, *bomap_start;
121 unsigned long flags;
122 121
123 /* Only catch the first event, or when manually re-armed */122 /* Only catch the first event, or when manually re-armed */
124 if (!etnaviv_dump_core)123 if (!etnaviv_dump_core)
@@ -135,13 +134,11 @@ void etnaviv_core_dump(struct etnaviv_gpu *gpu) · 10 unmodified lines
135 mmu_size + gpu->buffer.size;134 mmu_size + gpu->buffer.size;
136 135
137 /* Add in the active command buffers */136 /* Add in the active command buffers */
138 spin_lock_irqsave(&gpu->sched.job_list_lock, flags);
139 list_for_each_entry(s_job, &gpu->sched.ring_mirror_list, node) {137 list_for_each_entry(s_job, &gpu->sched.ring_mirror_list, node) {
140 submit = to_etnaviv_submit(s_job);138 submit = to_etnaviv_submit(s_job);
141 file_size += submit->cmdbuf.size;139 file_size += submit->cmdbuf.size;
142 n_obj++;140 n_obj++;
143 }141 }
144 spin_unlock_irqrestore(&gpu->sched.job_list_lock, flags);
145 142
146 /* Add in the active buffer objects */143 /* Add in the active buffer objects */
147 list_for_each_entry(vram, &gpu->mmu->mappings, mmu_node) {144 list_for_each_entry(vram, &gpu->mmu->mappings, mmu_node) {
@@ -183,14 +180,12 @@ void etnaviv_core_dump(struct etnaviv_gpu *gpu) · 35 unmodified lines
183 gpu->buffer.size,180 gpu->buffer.size,
184 etnaviv_cmdbuf_get_va(&gpu->buffer));181 etnaviv_cmdbuf_get_va(&gpu->buffer));
185 182
186 spin_lock_irqsave(&gpu->sched.job_list_lock, flags);
187 list_for_each_entry(s_job, &gpu->sched.ring_mirror_list, node) {183 list_for_each_entry(s_job, &gpu->sched.ring_mirror_list, node) {
188 submit = to_etnaviv_submit(s_job);184 submit = to_etnaviv_submit(s_job);
189 etnaviv_core_dump_mem(&iter, ETDUMP_BUF_CMD,185 etnaviv_core_dump_mem(&iter, ETDUMP_BUF_CMD,
190 submit->cmdbuf.vaddr, submit->cmdbuf.size,186 submit->cmdbuf.vaddr, submit->cmdbuf.size,
191 etnaviv_cmdbuf_get_va(&submit->cmdbuf));187 etnaviv_cmdbuf_get_va(&submit->cmdbuf));
192 }188 }
193 spin_unlock_irqrestore(&gpu->sched.job_list_lock, flags);
194 189
195 /* Reserve space for the bomap */190 /* Reserve space for the bomap */
196 if (n_bomap_pages) {191 if (n_bomap_pages) {
drivers/gpu/drm/etnaviv/etnaviv_sched.c+1−1
@@ -109,7 +109,7 @@ static void etnaviv_sched_timedout_job(struct drm_sched_job *sched_job) · 108 unmodified lines
109 }109 }
110 110
111 /* block scheduler */111 /* block scheduler */
112 drm_sched_stop(&gpu->sched);112 drm_sched_stop(&gpu->sched, sched_job);
113 113
114 if(sched_job)114 if(sched_job)
115 drm_sched_increase_karma(sched_job);115 drm_sched_increase_karma(sched_job);
drivers/gpu/drm/gma500/accel_2d.c+9−9
@@ -20,24 +20,24 @@ · 19 unmodified lines
20 *20 *
21 **************************************************************************/21 **************************************************************************/
22 22
23#include <linux/module.h>23#include <linux/console.h>
24#include <linux/kernel.h>24#include <linux/delay.h>
25#include <linux/errno.h>25#include <linux/errno.h>
26#include <linux/string.h>26#include <linux/init.h>
27#include <linux/kernel.h>
27#include <linux/mm.h>28#include <linux/mm.h>
28#include <linux/tty.h>29#include <linux/module.h>
29#include <linux/slab.h>30#include <linux/slab.h>
30#include <linux/delay.h>31#include <linux/string.h>
31#include <linux/init.h>32#include <linux/tty.h>
32#include <linux/console.h>
33 33
34#include <drm/drmP.h>
35#include <drm/drm.h>34#include <drm/drm.h>
36#include <drm/drm_crtc.h>35#include <drm/drm_crtc.h>
36#include <drm/drm_fourcc.h>
37 37
38#include "framebuffer.h"
38#include "psb_drv.h"39#include "psb_drv.h"
39#include "psb_reg.h"40#include "psb_reg.h"
40#include "framebuffer.h"
41 41
42/**42/**
43 * psb_spank - reset the 2D engine43 * psb_spank - reset the 2D engine
drivers/gpu/drm/gma500/blitter.h+2−0
@@ -17,6 +17,8 @@ · 16 unmodified lines
17#ifndef __BLITTER_H17#ifndef __BLITTER_H
18#define __BLITTER_H18#define __BLITTER_H
19 19
20struct drm_psb_private;
21
20extern int gma_blt_wait_idle(struct drm_psb_private *dev_priv);22extern int gma_blt_wait_idle(struct drm_psb_private *dev_priv);
21 23
22#endif24#endif
drivers/gpu/drm/gma500/cdv_device.c+7−6
@@ -18,15 +18,16 @@ · 17 unmodified lines
18 **************************************************************************/18 **************************************************************************/
19 19
20#include <linux/backlight.h>20#include <linux/backlight.h>
21#include <drm/drmP.h>21#include <linux/delay.h>
22
22#include <drm/drm.h>23#include <drm/drm.h>
23#include <drm/gma_drm.h>24
24#include "psb_drv.h"
25#include "psb_reg.h"
26#include "psb_intel_reg.h"
27#include "intel_bios.h"
28#include "cdv_device.h"25#include "cdv_device.h"
29#include "gma_device.h"26#include "gma_device.h"
27#include "intel_bios.h"
28#include "psb_drv.h"
29#include "psb_intel_reg.h"
30#include "psb_reg.h"
30 31
31#define VGA_SR_INDEX 0x3c432#define VGA_SR_INDEX 0x3c4
32#define VGA_SR_DATA 0x3c533#define VGA_SR_DATA 0x3c5
drivers/gpu/drm/gma500/cdv_device.h+4−0
@@ -15,6 +15,10 @@ · 14 unmodified lines
15 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.15 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
16 */16 */
17 17
18struct drm_crtc;
19struct drm_device;
20struct psb_intel_mode_device;
21
18extern const struct drm_crtc_helper_funcs cdv_intel_helper_funcs;22extern const struct drm_crtc_helper_funcs cdv_intel_helper_funcs;
19extern const struct drm_crtc_funcs cdv_intel_crtc_funcs;23extern const struct drm_crtc_funcs cdv_intel_crtc_funcs;
20extern const struct gma_clock_funcs cdv_clock_funcs;24extern const struct gma_clock_funcs cdv_clock_funcs;
drivers/gpu/drm/gma500/cdv_intel_crt.c+4−4
@@ -24,16 +24,16 @@ · 23 unmodified lines
24 * Eric Anholt <eric@anholt.net>24 * Eric Anholt <eric@anholt.net>
25 */25 */
26 26
27#include <linux/delay.h>
27#include <linux/i2c.h>28#include <linux/i2c.h>
28#include <drm/drmP.h>29#include <linux/pm_runtime.h>
29 30
31#include "cdv_device.h"
30#include "intel_bios.h"32#include "intel_bios.h"
33#include "power.h"
31#include "psb_drv.h"34#include "psb_drv.h"
32#include "psb_intel_drv.h"35#include "psb_intel_drv.h"
33#include "psb_intel_reg.h"36#include "psb_intel_reg.h"
34#include "power.h"
35#include "cdv_device.h"
36#include <linux/pm_runtime.h>
37 37
38 38
39static void cdv_intel_crt_dpms(struct drm_encoder *encoder, int mode)39static void cdv_intel_crt_dpms(struct drm_encoder *encoder, int mode)
drivers/gpu/drm/gma500/cdv_intel_display.c+6−4
@@ -18,16 +18,18 @@ · 17 unmodified lines
18 * Eric Anholt <eric@anholt.net>18 * Eric Anholt <eric@anholt.net>
19 */19 */
20 20
21#include <linux/delay.h>
21#include <linux/i2c.h>22#include <linux/i2c.h>
22 23
23#include <drm/drmP.h>24#include <drm/drm_crtc.h>
25
26#include "cdv_device.h"
24#include "framebuffer.h"27#include "framebuffer.h"
28#include "gma_display.h"
29#include "power.h"
25#include "psb_drv.h"30#include "psb_drv.h"
26#include "psb_intel_drv.h"31#include "psb_intel_drv.h"
27#include "psb_intel_reg.h"32#include "psb_intel_reg.h"
28#include "gma_display.h"
29#include "power.h"
30#include "cdv_device.h"
31 33
32static bool cdv_intel_find_dp_pll(const struct gma_limit_t *limit,34static bool cdv_intel_find_dp_pll(const struct gma_limit_t *limit,
33 struct drm_crtc *crtc, int target,35 struct drm_crtc *crtc, int target,
drivers/gpu/drm/gma500/cdv_intel_dp.c+5−4
@@ -26,16 +26,17 @@ · 25 unmodified lines
26 */26 */
27 27
28#include <linux/i2c.h>28#include <linux/i2c.h>
29#include <linux/slab.h>
30#include <linux/module.h>29#include <linux/module.h>
31#include <drm/drmP.h>30#include <linux/slab.h>
31
32#include <drm/drm_crtc.h>32#include <drm/drm_crtc.h>
33#include <drm/drm_crtc_helper.h>33#include <drm/drm_crtc_helper.h>
34#include <drm/drm_dp_helper.h>
35
36#include "gma_display.h"
34#include "psb_drv.h"37#include "psb_drv.h"
35#include "psb_intel_drv.h"38#include "psb_intel_drv.h"
36#include "psb_intel_reg.h"39#include "psb_intel_reg.h"
37#include "gma_display.h"
38#include <drm/drm_dp_helper.h>
39 40
40/**41/**
41 * struct i2c_algo_dp_aux_data - driver interface structure for i2c over dp42 * struct i2c_algo_dp_aux_data - driver interface structure for i2c over dp
drivers/gpu/drm/gma500/cdv_intel_hdmi.c+5−4
@@ -27,15 +27,16 @@ · 26 unmodified lines
27 * We should probably make this generic and share it with Medfield27 * We should probably make this generic and share it with Medfield
28 */28 */
29 29
30#include <drm/drmP.h>30#include <linux/pm_runtime.h>
31
31#include <drm/drm.h>32#include <drm/drm.h>
32#include <drm/drm_crtc.h>33#include <drm/drm_crtc.h>
33#include <drm/drm_edid.h>34#include <drm/drm_edid.h>
34#include "psb_intel_drv.h"35
36#include "cdv_device.h"
35#include "psb_drv.h"37#include "psb_drv.h"
38#include "psb_intel_drv.h"
36#include "psb_intel_reg.h"39#include "psb_intel_reg.h"
37#include "cdv_device.h"
38#include <linux/pm_runtime.h>
39 40
40/* hdmi control bits */41/* hdmi control bits */
41#define HDMI_NULL_PACKETS_DURING_VSYNC (1 << 9)42#define HDMI_NULL_PACKETS_DURING_VSYNC (1 << 9)
drivers/gpu/drm/gma500/cdv_intel_lvds.c+4−5
@@ -20,17 +20,16 @@ · 19 unmodified lines
20 * Jesse Barnes <jesse.barnes@intel.com>20 * Jesse Barnes <jesse.barnes@intel.com>
21 */21 */
22 22
23#include <linux/i2c.h>
24#include <linux/dmi.h>23#include <linux/dmi.h>
25#include <drm/drmP.h>24#include <linux/i2c.h>
25#include <linux/pm_runtime.h>
26 26
27#include "cdv_device.h"
27#include "intel_bios.h"28#include "intel_bios.h"
29#include "power.h"
28#include "psb_drv.h"30#include "psb_drv.h"
29#include "psb_intel_drv.h"31#include "psb_intel_drv.h"
30#include "psb_intel_reg.h"32#include "psb_intel_reg.h"
31#include "power.h"
32#include <linux/pm_runtime.h>
33#include "cdv_device.h"
34 33
35/**34/**
36 * LVDS I2C backlight control macros35 * LVDS I2C backlight control macros
drivers/gpu/drm/gma500/framebuffer.c+13−13
@@ -17,29 +17,29 @@ · 16 unmodified lines
17 *17 *
18 **************************************************************************/18 **************************************************************************/
19 19
20#include <linux/module.h>20#include <linux/console.h>
21#include <linux/kernel.h>21#include <linux/delay.h>
22#include <linux/errno.h>22#include <linux/errno.h>
23#include <linux/string.h>23#include <linux/init.h>
24#include <linux/pfn_t.h>24#include <linux/kernel.h>
25#include <linux/mm.h>25#include <linux/mm.h>
26#include <linux/tty.h>26#include <linux/module.h>
27#include <linux/pfn_t.h>
27#include <linux/slab.h>28#include <linux/slab.h>
28#include <linux/delay.h>29#include <linux/string.h>
29#include <linux/init.h>30#include <linux/tty.h>
30#include <linux/console.h>
31 31
32#include <drm/drmP.h>
33#include <drm/drm.h>32#include <drm/drm.h>
34#include <drm/drm_crtc.h>33#include <drm/drm_crtc.h>
35#include <drm/drm_fb_helper.h>34#include <drm/drm_fb_helper.h>
35#include <drm/drm_fourcc.h>
36#include <drm/drm_gem_framebuffer_helper.h>36#include <drm/drm_gem_framebuffer_helper.h>
37 37
38#include "psb_drv.h"
39#include "psb_intel_reg.h"
40#include "psb_intel_drv.h"
41#include "framebuffer.h"38#include "framebuffer.h"
42#include "gtt.h"39#include "gtt.h"
40#include "psb_drv.h"
41#include "psb_intel_drv.h"
42#include "psb_intel_reg.h"
43 43
44static const struct drm_framebuffer_funcs psb_fb_funcs = {44static const struct drm_framebuffer_funcs psb_fb_funcs = {
45 .destroy = drm_gem_fb_destroy,45 .destroy = drm_gem_fb_destroy,
@@ -232,7 +232,7 @@ static int psb_framebuffer_init(struct drm_device *dev, · 186 unmodified lines
232 * Reject unknown formats, YUV formats, and formats with more than232 * Reject unknown formats, YUV formats, and formats with more than
233 * 4 bytes per pixel.233 * 4 bytes per pixel.
234 */234 */
235 info = drm_format_info(mode_cmd->pixel_format);235 info = drm_get_format_info(dev, mode_cmd);
236 if (!info || !info->depth || info->cpp[0] > 4)236 if (!info || !info->depth || info->cpp[0] > 4)
237 return -EINVAL;237 return -EINVAL;
238 238
drivers/gpu/drm/gma500/framebuffer.h+0−1
@@ -22,7 +22,6 @@ · 21 unmodified lines
22#ifndef _FRAMEBUFFER_H_22#ifndef _FRAMEBUFFER_H_
23#define _FRAMEBUFFER_H_23#define _FRAMEBUFFER_H_
24 24
25#include <drm/drmP.h>
26#include <drm/drm_fb_helper.h>25#include <drm/drm_fb_helper.h>
27 26
28#include "psb_drv.h"27#include "psb_drv.h"
drivers/gpu/drm/gma500/gem.c+3−2
@@ -23,10 +23,11 @@ · 22 unmodified lines
23 * accelerated operations on a GEM object)23 * accelerated operations on a GEM object)
24 */24 */
25 25
26#include <drm/drmP.h>26#include <linux/pagemap.h>
27
27#include <drm/drm.h>28#include <drm/drm.h>
28#include <drm/gma_drm.h>
29#include <drm/drm_vma_manager.h>29#include <drm/drm_vma_manager.h>
30
30#include "psb_drv.h"31#include "psb_drv.h"
31 32
32void psb_gem_free_object(struct drm_gem_object *obj)33void psb_gem_free_object(struct drm_gem_object *obj)
drivers/gpu/drm/gma500/gma_device.c+0−1
@@ -13,7 +13,6 @@ · 12 unmodified lines
13 *13 *
14 **************************************************************************/14 **************************************************************************/
15 15
16#include <drm/drmP.h>
17#include "psb_drv.h"16#include "psb_drv.h"
18 17
19void gma_get_core_freq(struct drm_device *dev)18void gma_get_core_freq(struct drm_device *dev)
drivers/gpu/drm/gma500/gma_device.h+1−0
@@ -15,6 +15,7 @@ · 14 unmodified lines
15 15
16#ifndef _GMA_DEVICE_H16#ifndef _GMA_DEVICE_H
17#define _GMA_DEVICE_H17#define _GMA_DEVICE_H
18struct drm_device;
18 19
19extern void gma_get_core_freq(struct drm_device *dev);20extern void gma_get_core_freq(struct drm_device *dev);
20 21
drivers/gpu/drm/gma500/gma_display.c+9−3
@@ -19,12 +19,18 @@ · 18 unmodified lines
19 * Patrik Jakobsson <patrik.r.jakobsson@gmail.com>19 * Patrik Jakobsson <patrik.r.jakobsson@gmail.com>
20 */20 */
21 21
22#include <drm/drmP.h>22#include <linux/delay.h>
23#include <linux/highmem.h>
24
25#include <drm/drm_crtc.h>
26#include <drm/drm_fourcc.h>
27#include <drm/drm_vblank.h>
28
29#include "framebuffer.h"
23#include "gma_display.h"30#include "gma_display.h"
31#include "psb_drv.h"
24#include "psb_intel_drv.h"32#include "psb_intel_drv.h"
25#include "psb_intel_reg.h"33#include "psb_intel_reg.h"
26#include "psb_drv.h"
27#include "framebuffer.h"
28 34
29/**35/**
30 * Returns whether any output on the specified pipe is of the specified type36 * Returns whether any output on the specified pipe is of the specified type
drivers/gpu/drm/gma500/gma_display.h+3−0
@@ -24,6 +24,9 @@ · 23 unmodified lines
24 24
25#include <linux/pm_runtime.h>25#include <linux/pm_runtime.h>
26 26
27struct drm_encoder;
28struct drm_mode_set;
29
27struct gma_clock_t {30struct gma_clock_t {
28 /* given values */31 /* given values */
29 int n;32 int n;
drivers/gpu/drm/gma500/gtt.c+3−2
@@ -19,11 +19,12 @@ · 18 unmodified lines
19 * Alan Cox <alan@linux.intel.com>19 * Alan Cox <alan@linux.intel.com>
20 */20 */
21 21
22#include <drm/drmP.h>
23#include <linux/shmem_fs.h>22#include <linux/shmem_fs.h>
23
24#include <asm/set_memory.h>24#include <asm/set_memory.h>
25#include "psb_drv.h"25
26#include "blitter.h"26#include "blitter.h"
27#include "psb_drv.h"
27 28
28 29
29/*30/*
drivers/gpu/drm/gma500/gtt.h+0−1
@@ -20,7 +20,6 @@ · 19 unmodified lines
20#ifndef _PSB_GTT_H_20#ifndef _PSB_GTT_H_
21#define _PSB_GTT_H_21#define _PSB_GTT_H_
22 22
23#include <drm/drmP.h>
24#include <drm/drm_gem.h>23#include <drm/drm_gem.h>
25 24
26/* This wants cleaning up with respect to the psb_dev and un-needed stuff */25/* This wants cleaning up with respect to the psb_dev and un-needed stuff */
drivers/gpu/drm/gma500/intel_bios.c+3−3
@@ -18,13 +18,13 @@ · 17 unmodified lines
18 * Eric Anholt <eric@anholt.net>18 * Eric Anholt <eric@anholt.net>
19 *19 *
20 */20 */
21#include <drm/drmP.h>
22#include <drm/drm.h>21#include <drm/drm.h>
23#include <drm/gma_drm.h>22#include <drm/drm_dp_helper.h>
23
24#include "intel_bios.h"
24#include "psb_drv.h"25#include "psb_drv.h"
25#include "psb_intel_drv.h"26#include "psb_intel_drv.h"
26#include "psb_intel_reg.h"27#include "psb_intel_reg.h"
27#include "intel_bios.h"
28 28
29#define SLAVE_ADDR1 0x7029#define SLAVE_ADDR1 0x70
30#define SLAVE_ADDR2 0x7230#define SLAVE_ADDR2 0x72
drivers/gpu/drm/gma500/intel_bios.h+1−2
@@ -22,8 +22,7 @@ · 21 unmodified lines
22#ifndef _INTEL_BIOS_H_22#ifndef _INTEL_BIOS_H_
23#define _INTEL_BIOS_H_23#define _INTEL_BIOS_H_
24 24
25#include <drm/drmP.h>25struct drm_device;
26#include <drm/drm_dp_helper.h>
27 26
28struct vbt_header {27struct vbt_header {
29 u8 signature[20]; /**< Always starts with 'VBT$' */28 u8 signature[20]; /**< Always starts with 'VBT$' */
drivers/gpu/drm/gma500/intel_gmbus.c+6−5
@@ -26,13 +26,14 @@ · 25 unmodified lines
26 * Eric Anholt <eric@anholt.net>26 * Eric Anholt <eric@anholt.net>
27 * Chris Wilson <chris@chris-wilson.co.uk>27 * Chris Wilson <chris@chris-wilson.co.uk>
28 */28 */
29#include <linux/module.h>29
30#include <linux/i2c.h>30#include <linux/delay.h>
31#include <linux/i2c-algo-bit.h>31#include <linux/i2c-algo-bit.h>
32#include <drm/drmP.h>32#include <linux/i2c.h>
33#include "psb_intel_drv.h"33#include <linux/module.h>
34#include <drm/gma_drm.h>34
35#include "psb_drv.h"35#include "psb_drv.h"
36#include "psb_intel_drv.h"
36#include "psb_intel_reg.h"37#include "psb_intel_reg.h"
37 38
38#define _wait_for(COND, MS, W) ({ \39#define _wait_for(COND, MS, W) ({ \
drivers/gpu/drm/gma500/intel_i2c.c+3−1
@@ -17,9 +17,11 @@ · 16 unmodified lines
17 * Authors:17 * Authors:
18 * Eric Anholt <eric@anholt.net>18 * Eric Anholt <eric@anholt.net>
19 */19 */
20
21#include <linux/delay.h>
20#include <linux/export.h>22#include <linux/export.h>
21#include <linux/i2c.h>
22#include <linux/i2c-algo-bit.h>23#include <linux/i2c-algo-bit.h>
24#include <linux/i2c.h>
23 25
24#include "psb_drv.h"26#include "psb_drv.h"
25#include "psb_intel_reg.h"27#include "psb_intel_reg.h"
drivers/gpu/drm/gma500/mdfld_device.c+9−7
@@ -17,14 +17,16 @@ · 16 unmodified lines
17 *17 *
18 **************************************************************************/18 **************************************************************************/
19 19
20#include "psb_drv.h"20#include <linux/delay.h>
21#include "mid_bios.h"
22#include "mdfld_output.h"
23#include "mdfld_dsi_output.h"
24#include "tc35876x-dsi-lvds.h"
25 21
26#include <asm/intel_scu_ipc.h>22#include <asm/intel_scu_ipc.h>
27 23
24#include "mdfld_dsi_output.h"
25#include "mdfld_output.h"
26#include "mid_bios.h"
27#include "psb_drv.h"
28#include "tc35876x-dsi-lvds.h"
29
28#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE30#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
29 31
30#define MRST_BLC_MAX_PWM_REG_FREQ 0xFFFF32#define MRST_BLC_MAX_PWM_REG_FREQ 0xFFFF
@@ -342,7 +344,7 @@ static int mdfld_restore_display_registers(struct drm_device *dev, int pipenum) · 311 unmodified lines
342 344
343 if (pipenum == 1) {345 if (pipenum == 1) {
344 /* restore palette (gamma) */346 /* restore palette (gamma) */
345 /*DRM_UDELAY(50000); */347 /* udelay(50000); */
346 for (i = 0; i < 256; i++)348 for (i = 0; i < 256; i++)
347 PSB_WVDC32(pipe->palette[i], map->palette + (i << 2));349 PSB_WVDC32(pipe->palette[i], map->palette + (i << 2));
348 350
@@ -404,7 +406,7 @@ static int mdfld_restore_display_registers(struct drm_device *dev, int pipenum) · 55 unmodified lines
404 PSB_WVDC32(pipe->conf, map->conf);406 PSB_WVDC32(pipe->conf, map->conf);
405 407
406 /* restore palette (gamma) */408 /* restore palette (gamma) */
407 /*DRM_UDELAY(50000); */409 /* udelay(50000); */
408 for (i = 0; i < 256; i++)410 for (i = 0; i < 256; i++)
409 PSB_WVDC32(pipe->palette[i], map->palette + (i << 2));411 PSB_WVDC32(pipe->palette[i], map->palette + (i << 2));
410 412
drivers/gpu/drm/gma500/mdfld_dsi_dpi.c+3−1
@@ -25,9 +25,11 @@ · 24 unmodified lines
25 * Jackie Li<yaodong.li@intel.com>25 * Jackie Li<yaodong.li@intel.com>
26 */26 */
27 27
28#include <linux/delay.h>
29
28#include "mdfld_dsi_dpi.h"30#include "mdfld_dsi_dpi.h"
29#include "mdfld_output.h"
30#include "mdfld_dsi_pkg_sender.h"31#include "mdfld_dsi_pkg_sender.h"
32#include "mdfld_output.h"
31#include "psb_drv.h"33#include "psb_drv.h"
32#include "tc35876x-dsi-lvds.h"34#include "tc35876x-dsi-lvds.h"
33 35
drivers/gpu/drm/gma500/mdfld_dsi_output.c+7−5
@@ -25,15 +25,17 @@ · 24 unmodified lines
25 * Jackie Li<yaodong.li@intel.com>25 * Jackie Li<yaodong.li@intel.com>
26 */26 */
27 27
28#include <linux/module.h>28#include <linux/delay.h>
29#include <linux/moduleparam.h>
30#include <linux/pm_runtime.h>
31
32#include <asm/intel_scu_ipc.h>
29 33
30#include "mdfld_dsi_output.h"
31#include "mdfld_dsi_dpi.h"34#include "mdfld_dsi_dpi.h"
32#include "mdfld_output.h"35#include "mdfld_dsi_output.h"
33#include "mdfld_dsi_pkg_sender.h"36#include "mdfld_dsi_pkg_sender.h"
37#include "mdfld_output.h"
34#include "tc35876x-dsi-lvds.h"38#include "tc35876x-dsi-lvds.h"
35#include <linux/pm_runtime.h>
36#include <asm/intel_scu_ipc.h>
37 39
38/* get the LABC from command line. */40/* get the LABC from command line. */
39static int LABC_control = 1;41static int LABC_control = 1;
drivers/gpu/drm/gma500/mdfld_dsi_output.h+4−4
@@ -29,17 +29,17 @@ · 28 unmodified lines
29#define __MDFLD_DSI_OUTPUT_H__29#define __MDFLD_DSI_OUTPUT_H__
30 30
31#include <linux/backlight.h>31#include <linux/backlight.h>
32#include <drm/drmP.h>32
33#include <asm/intel-mid.h>
34
33#include <drm/drm.h>35#include <drm/drm.h>
34#include <drm/drm_crtc.h>36#include <drm/drm_crtc.h>
35#include <drm/drm_edid.h>37#include <drm/drm_edid.h>
36 38
39#include "mdfld_output.h"
37#include "psb_drv.h"40#include "psb_drv.h"
38#include "psb_intel_drv.h"41#include "psb_intel_drv.h"
39#include "psb_intel_reg.h"42#include "psb_intel_reg.h"
40#include "mdfld_output.h"
41
42#include <asm/intel-mid.h>
43 43
44#define FLD_MASK(start, end) (((1 << ((start) - (end) + 1)) - 1) << (end))44#define FLD_MASK(start, end) (((1 << ((start) - (end) + 1)) - 1) << (end))
45#define FLD_VAL(val, start, end) (((val) << (end)) & FLD_MASK(start, end))45#define FLD_VAL(val, start, end) (((val) << (end)) & FLD_MASK(start, end))
drivers/gpu/drm/gma500/mdfld_dsi_pkg_sender.c+3−1
@@ -24,12 +24,14 @@ · 23 unmodified lines
24 * Jackie Li<yaodong.li@intel.com>24 * Jackie Li<yaodong.li@intel.com>
25 */25 */
26 26
27#include <linux/delay.h>
27#include <linux/freezer.h>28#include <linux/freezer.h>
29
28#include <video/mipi_display.h>30#include <video/mipi_display.h>
29 31
32#include "mdfld_dsi_dpi.h"
30#include "mdfld_dsi_output.h"33#include "mdfld_dsi_output.h"
31#include "mdfld_dsi_pkg_sender.h"34#include "mdfld_dsi_pkg_sender.h"
32#include "mdfld_dsi_dpi.h"
33 35
34#define MDFLD_DSI_READ_MAX_COUNT 500036#define MDFLD_DSI_READ_MAX_COUNT 5000
35 37
drivers/gpu/drm/gma500/mdfld_intel_display.c+7−4
@@ -18,15 +18,18 @@ · 17 unmodified lines
18 * Eric Anholt <eric@anholt.net>18 * Eric Anholt <eric@anholt.net>
19 */19 */
20 20
21#include <linux/delay.h>
21#include <linux/i2c.h>22#include <linux/i2c.h>
22#include <linux/pm_runtime.h>23#include <linux/pm_runtime.h>
23 24
24#include <drm/drmP.h>25#include <drm/drm_crtc.h>
25#include "psb_intel_reg.h"26#include <drm/drm_fourcc.h>
26#include "gma_display.h"27
27#include "framebuffer.h"28#include "framebuffer.h"
28#include "mdfld_output.h"29#include "gma_display.h"
29#include "mdfld_dsi_output.h"30#include "mdfld_dsi_output.h"
31#include "mdfld_output.h"
32#include "psb_intel_reg.h"
30 33
31/* Hardcoded currently */34/* Hardcoded currently */
32static int ksel = KSEL_CRYSTAL_19;35static int ksel = KSEL_CRYSTAL_19;
drivers/gpu/drm/gma500/mdfld_tmd_vid.c+2−0
@@ -27,6 +27,8 @@ · 26 unmodified lines
27 * Scott Rowe <scott.m.rowe@intel.com>27 * Scott Rowe <scott.m.rowe@intel.com>
28 */28 */
29 29
30#include <linux/delay.h>
31
30#include "mdfld_dsi_dpi.h"32#include "mdfld_dsi_dpi.h"
31#include "mdfld_dsi_pkg_sender.h"33#include "mdfld_dsi_pkg_sender.h"
32 34
drivers/gpu/drm/gma500/mid_bios.c+2−3
@@ -23,11 +23,10 @@ · 22 unmodified lines
23 * - Check ioremap failures23 * - Check ioremap failures
24 */24 */
25 25
26#include <drm/drmP.h>
27#include <drm/drm.h>26#include <drm/drm.h>
28#include <drm/gma_drm.h>27
29#include "psb_drv.h"
30#include "mid_bios.h"28#include "mid_bios.h"
29#include "psb_drv.h"
31 30
32static void mid_get_fuse_settings(struct drm_device *dev)31static void mid_get_fuse_settings(struct drm_device *dev)
33{32{
drivers/gpu/drm/gma500/mid_bios.h+1−0
@@ -16,6 +16,7 @@ · 15 unmodified lines
16 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.16 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
17 *17 *
18 **************************************************************************/18 **************************************************************************/
19struct drm_device;
19 20
20extern int mid_chip_setup(struct drm_device *dev);21extern int mid_chip_setup(struct drm_device *dev);
21 22
drivers/gpu/drm/gma500/mmu.c+4−2
@@ -15,10 +15,12 @@ · 14 unmodified lines
15 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.15 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
16 *16 *
17 **************************************************************************/17 **************************************************************************/
18#include <drm/drmP.h>18
19#include <linux/highmem.h>
20
21#include "mmu.h"
19#include "psb_drv.h"22#include "psb_drv.h"
20#include "psb_reg.h"23#include "psb_reg.h"
21#include "mmu.h"
22 24
23/*25/*
24 * Code for the SGX MMU:26 * Code for the SGX MMU:
drivers/gpu/drm/gma500/oaktrail.h+2−0
@@ -17,6 +17,8 @@ · 16 unmodified lines
17 *17 *
18 **************************************************************************/18 **************************************************************************/
19 19
20struct psb_intel_mode_device;
21
20/* MID device specific descriptors */22/* MID device specific descriptors */
21 23
22struct oaktrail_timing_info {24struct oaktrail_timing_info {
drivers/gpu/drm/gma500/oaktrail_crtc.c+5−3
@@ -15,16 +15,18 @@ · 14 unmodified lines
15 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.15 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
16 */16 */
17 17
18#include <linux/delay.h>
18#include <linux/i2c.h>19#include <linux/i2c.h>
19#include <linux/pm_runtime.h>20#include <linux/pm_runtime.h>
20 21
21#include <drm/drmP.h>22#include <drm/drm_fourcc.h>
23
22#include "framebuffer.h"24#include "framebuffer.h"
25#include "gma_display.h"
26#include "power.h"
23#include "psb_drv.h"27#include "psb_drv.h"
24#include "psb_intel_drv.h"28#include "psb_intel_drv.h"
25#include "psb_intel_reg.h"29#include "psb_intel_reg.h"
26#include "gma_display.h"
27#include "power.h"
28 30
29#define MRST_LIMIT_LVDS_100L 031#define MRST_LIMIT_LVDS_100L 0
30#define MRST_LIMIT_LVDS_83 132#define MRST_LIMIT_LVDS_83 1
drivers/gpu/drm/gma500/oaktrail_device.c+11−9
@@ -18,18 +18,20 @@ · 17 unmodified lines
18 **************************************************************************/18 **************************************************************************/
19 19
20#include <linux/backlight.h>20#include <linux/backlight.h>
21#include <linux/module.h>21#include <linux/delay.h>
22#include <linux/dmi.h>22#include <linux/dmi.h>
23#include <drm/drmP.h>23#include <linux/module.h>
24#include <drm/drm.h>24
25#include <drm/gma_drm.h>
26#include "psb_drv.h"
27#include "psb_reg.h"
28#include "psb_intel_reg.h"
29#include <asm/intel-mid.h>25#include <asm/intel-mid.h>
30#include <asm/intel_scu_ipc.h>26#include <asm/intel_scu_ipc.h>
31#include "mid_bios.h"27
28#include <drm/drm.h>
29
32#include "intel_bios.h"30#include "intel_bios.h"
31#include "mid_bios.h"
32#include "psb_drv.h"
33#include "psb_intel_reg.h"
34#include "psb_reg.h"
33 35
34static int oaktrail_output_init(struct drm_device *dev)36static int oaktrail_output_init(struct drm_device *dev)
35{37{
@@ -327,7 +329,7 @@ static int oaktrail_restore_display_registers(struct drm_device *dev) · 291 unmodified lines
327 329
328 /* Actually enable it */330 /* Actually enable it */
329 PSB_WVDC32(p->dpll, MRST_DPLL_A);331 PSB_WVDC32(p->dpll, MRST_DPLL_A);
330 DRM_UDELAY(150);332 udelay(150);
331 333
332 /* Restore mode */334 /* Restore mode */
333 PSB_WVDC32(p->htotal, HTOTAL_A);335 PSB_WVDC32(p->htotal, HTOTAL_A);
drivers/gpu/drm/gma500/oaktrail_hdmi.c+5−3
@@ -24,11 +24,13 @@ · 23 unmodified lines
24 * Li Peng <peng.li@intel.com>24 * Li Peng <peng.li@intel.com>
25 */25 */
26 26
27#include <drm/drmP.h>27#include <linux/delay.h>
28
28#include <drm/drm.h>29#include <drm/drm.h>
30
31#include "psb_drv.h"
29#include "psb_intel_drv.h"32#include "psb_intel_drv.h"
30#include "psb_intel_reg.h"33#include "psb_intel_reg.h"
31#include "psb_drv.h"
32 34
33#define HDMI_READ(reg) readl(hdmi_dev->regs + (reg))35#define HDMI_READ(reg) readl(hdmi_dev->regs + (reg))
34#define HDMI_WRITE(reg, val) writel(val, hdmi_dev->regs + (reg))36#define HDMI_WRITE(reg, val) writel(val, hdmi_dev->regs + (reg))
@@ -815,7 +817,7 @@ void oaktrail_hdmi_restore(struct drm_device *dev) · 780 unmodified lines
815 PSB_WVDC32(hdmi_dev->saveDPLL_ADJUST, DPLL_ADJUST);817 PSB_WVDC32(hdmi_dev->saveDPLL_ADJUST, DPLL_ADJUST);
816 PSB_WVDC32(hdmi_dev->saveDPLL_UPDATE, DPLL_UPDATE);818 PSB_WVDC32(hdmi_dev->saveDPLL_UPDATE, DPLL_UPDATE);
817 PSB_WVDC32(hdmi_dev->saveDPLL_CLK_ENABLE, DPLL_CLK_ENABLE);819 PSB_WVDC32(hdmi_dev->saveDPLL_CLK_ENABLE, DPLL_CLK_ENABLE);
818 DRM_UDELAY(150);820 udelay(150);
819 821
820 /* pipe */822 /* pipe */
821 PSB_WVDC32(pipeb->src, PIPEBSRC);823 PSB_WVDC32(pipeb->src, PIPEBSRC);
drivers/gpu/drm/gma500/oaktrail_lvds.c+3−3
@@ -21,15 +21,15 @@ · 20 unmodified lines
21 */21 */
22 22
23#include <linux/i2c.h>23#include <linux/i2c.h>
24#include <drm/drmP.h>24#include <linux/pm_runtime.h>
25
25#include <asm/intel-mid.h>26#include <asm/intel-mid.h>
26 27
27#include "intel_bios.h"28#include "intel_bios.h"
29#include "power.h"
28#include "psb_drv.h"30#include "psb_drv.h"
29#include "psb_intel_drv.h"31#include "psb_intel_drv.h"
30#include "psb_intel_reg.h"32#include "psb_intel_reg.h"
31#include "power.h"
32#include <linux/pm_runtime.h>
33 33
34/* The max/min PWM frequency in BPCR[31:17] - */34/* The max/min PWM frequency in BPCR[31:17] - */
35/* The smallest number is 1 (not 0) that can fit in the35/* The smallest number is 1 (not 0) that can fit in the
drivers/gpu/drm/gma500/oaktrail_lvds_i2c.c+5−6
@@ -23,17 +23,16 @@ · 22 unmodified lines
23 *23 *
24 */24 */
25 25
26#include <linux/delay.h>
27#include <linux/i2c-algo-bit.h>
28#include <linux/i2c.h>
29#include <linux/init.h>
30#include <linux/io.h>
26#include <linux/kernel.h>31#include <linux/kernel.h>
27#include <linux/module.h>32#include <linux/module.h>
28#include <linux/pci.h>33#include <linux/pci.h>
29#include <linux/types.h>34#include <linux/types.h>
30#include <linux/i2c.h>
31#include <linux/i2c-algo-bit.h>
32#include <linux/init.h>
33#include <linux/io.h>
34#include <linux/delay.h>
35 35
36#include <drm/drmP.h>
37#include "psb_drv.h"36#include "psb_drv.h"
38#include "psb_intel_reg.h"37#include "psb_intel_reg.h"
39 38
drivers/gpu/drm/gma500/power.h+3−1
@@ -31,7 +31,9 @@ · 30 unmodified lines
31#define _PSB_POWERMGMT_H_31#define _PSB_POWERMGMT_H_
32 32
33#include <linux/pci.h>33#include <linux/pci.h>
34#include <drm/drmP.h>34
35struct device;
36struct drm_device;
35 37
36void gma_power_init(struct drm_device *dev);38void gma_power_init(struct drm_device *dev);
37void gma_power_uninit(struct drm_device *dev);39void gma_power_uninit(struct drm_device *dev);
drivers/gpu/drm/gma500/psb_device.c+6−6
@@ -18,15 +18,15 @@ · 17 unmodified lines
18 **************************************************************************/18 **************************************************************************/
19 19
20#include <linux/backlight.h>20#include <linux/backlight.h>
21#include <drm/drmP.h>21
22#include <drm/drm.h>22#include <drm/drm.h>
23#include <drm/gma_drm.h>23
24#include "psb_drv.h"24#include "gma_device.h"
25#include "psb_reg.h"
26#include "psb_intel_reg.h"
27#include "intel_bios.h"25#include "intel_bios.h"
28#include "psb_device.h"26#include "psb_device.h"
29#include "gma_device.h"27#include "psb_drv.h"
28#include "psb_intel_reg.h"
29#include "psb_reg.h"
30 30
31static int psb_output_init(struct drm_device *dev)31static int psb_output_init(struct drm_device *dev)
32{32{
drivers/gpu/drm/gma500/psb_drv.c+21−12
@@ -19,23 +19,32 @@ · 18 unmodified lines
19 *19 *
20 **************************************************************************/20 **************************************************************************/
21 21
22#include <drm/drmP.h>22#include <linux/cpu.h>
23#include <linux/module.h>
24#include <linux/notifier.h>
25#include <linux/pm_runtime.h>
26#include <linux/spinlock.h>
27
28#include <asm/set_memory.h>
29
30#include <acpi/video.h>
31
23#include <drm/drm.h>32#include <drm/drm.h>
24#include "psb_drv.h"33#include <drm/drm_drv.h>
34#include <drm/drm_file.h>
35#include <drm/drm_ioctl.h>
36#include <drm/drm_irq.h>
37#include <drm/drm_pci.h>
38#include <drm/drm_pciids.h>
39#include <drm/drm_vblank.h>
40
25#include "framebuffer.h"41#include "framebuffer.h"
26#include "psb_reg.h"
27#include "psb_intel_reg.h"
28#include "intel_bios.h"42#include "intel_bios.h"
29#include "mid_bios.h"43#include "mid_bios.h"
30#include <drm/drm_pciids.h>
31#include "power.h"44#include "power.h"
32#include <linux/cpu.h>45#include "psb_drv.h"
33#include <linux/notifier.h>46#include "psb_intel_reg.h"
34#include <linux/spinlock.h>47#include "psb_reg.h"
35#include <linux/pm_runtime.h>
36#include <acpi/video.h>
37#include <linux/module.h>
38#include <asm/set_memory.h>
39 48
40static struct drm_driver driver;49static struct drm_driver driver;
41static int psb_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent);50static int psb_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent);
drivers/gpu/drm/gma500/psb_drv.h+8−8
@@ -23,17 +23,17 @@ · 22 unmodified lines
23#include <linux/kref.h>23#include <linux/kref.h>
24#include <linux/mm_types.h>24#include <linux/mm_types.h>
25 25
26#include <drm/drmP.h>26#include <drm/drm_device.h>
27#include <drm/gma_drm.h>27
28#include "psb_reg.h"
29#include "psb_intel_drv.h"
30#include "gma_display.h"28#include "gma_display.h"
31#include "intel_bios.h"
32#include "gtt.h"29#include "gtt.h"
33#include "power.h"30#include "intel_bios.h"
34#include "opregion.h"
35#include "oaktrail.h"
36#include "mmu.h"31#include "mmu.h"
32#include "oaktrail.h"
33#include "opregion.h"
34#include "power.h"
35#include "psb_intel_drv.h"
36#include "psb_reg.h"
37 37
38#define DRIVER_AUTHOR "Alan Cox <alan@linux.intel.com> and others"38#define DRIVER_AUTHOR "Alan Cox <alan@linux.intel.com> and others"
39 39
drivers/gpu/drm/gma500/psb_intel_display.c+4−3
@@ -18,16 +18,17 @@ · 17 unmodified lines
18 * Eric Anholt <eric@anholt.net>18 * Eric Anholt <eric@anholt.net>
19 */19 */
20 20
21#include <linux/delay.h>
21#include <linux/i2c.h>22#include <linux/i2c.h>
22 23
23#include <drm/drmP.h>
24#include <drm/drm_plane_helper.h>24#include <drm/drm_plane_helper.h>
25
25#include "framebuffer.h"26#include "framebuffer.h"
27#include "gma_display.h"
28#include "power.h"
26#include "psb_drv.h"29#include "psb_drv.h"
27#include "psb_intel_drv.h"30#include "psb_intel_drv.h"
28#include "psb_intel_reg.h"31#include "psb_intel_reg.h"
29#include "gma_display.h"
30#include "power.h"
31 32
32#define INTEL_LIMIT_I9XX_SDVO_DAC 033#define INTEL_LIMIT_I9XX_SDVO_DAC 0
33#define INTEL_LIMIT_I9XX_LVDS 134#define INTEL_LIMIT_I9XX_LVDS 1
drivers/gpu/drm/gma500/psb_intel_lvds.c+2−3
@@ -21,14 +21,13 @@ · 20 unmodified lines
21 */21 */
22 22
23#include <linux/i2c.h>23#include <linux/i2c.h>
24#include <drm/drmP.h>24#include <linux/pm_runtime.h>
25 25
26#include "intel_bios.h"26#include "intel_bios.h"
27#include "power.h"
27#include "psb_drv.h"28#include "psb_drv.h"
28#include "psb_intel_drv.h"29#include "psb_intel_drv.h"
29#include "psb_intel_reg.h"30#include "psb_intel_reg.h"
30#include "power.h"
31#include <linux/pm_runtime.h>
32 31
33/*32/*
34 * LVDS I2C backlight control macros33 * LVDS I2C backlight control macros
drivers/gpu/drm/gma500/psb_intel_modes.c+1−1
@@ -18,7 +18,7 @@ · 17 unmodified lines
18 */18 */
19 19
20#include <linux/i2c.h>20#include <linux/i2c.h>
21#include <drm/drmP.h>21
22#include "psb_intel_drv.h"22#include "psb_intel_drv.h"
23 23
24/**24/**
drivers/gpu/drm/gma500/psb_intel_sdvo.c+8−7
@@ -25,19 +25,20 @@ · 24 unmodified lines
25 * Authors:25 * Authors:
26 * Eric Anholt <eric@anholt.net>26 * Eric Anholt <eric@anholt.net>
27 */27 */
28#include <linux/module.h>28
29#include <linux/delay.h>
29#include <linux/i2c.h>30#include <linux/i2c.h>
31#include <linux/kernel.h>
32#include <linux/module.h>
30#include <linux/slab.h>33#include <linux/slab.h>
31#include <linux/delay.h>34
32#include <drm/drmP.h>
33#include <drm/drm_crtc.h>35#include <drm/drm_crtc.h>
34#include <drm/drm_edid.h>36#include <drm/drm_edid.h>
35#include "psb_intel_drv.h"37
36#include <drm/gma_drm.h>
37#include "psb_drv.h"38#include "psb_drv.h"
38#include "psb_intel_sdvo_regs.h"39#include "psb_intel_drv.h"
39#include "psb_intel_reg.h"40#include "psb_intel_reg.h"
40#include <linux/kernel.h>41#include "psb_intel_sdvo_regs.h"
41 42
42#define SDVO_TMDS_MASK (SDVO_OUTPUT_TMDS0 | SDVO_OUTPUT_TMDS1)43#define SDVO_TMDS_MASK (SDVO_OUTPUT_TMDS0 | SDVO_OUTPUT_TMDS1)
43#define SDVO_RGB_MASK (SDVO_OUTPUT_RGB0 | SDVO_OUTPUT_RGB1)44#define SDVO_RGB_MASK (SDVO_OUTPUT_RGB0 | SDVO_OUTPUT_RGB1)
drivers/gpu/drm/gma500/psb_irq.c+5−4
@@ -22,13 +22,14 @@ · 21 unmodified lines
22/*22/*
23 */23 */
24 24
25#include <drm/drmP.h>25#include <drm/drm_vblank.h>
26
27#include "mdfld_output.h"
28#include "power.h"
26#include "psb_drv.h"29#include "psb_drv.h"
27#include "psb_reg.h"
28#include "psb_intel_reg.h"30#include "psb_intel_reg.h"
29#include "power.h"
30#include "psb_irq.h"31#include "psb_irq.h"
31#include "mdfld_output.h"32#include "psb_reg.h"
32 33
33/*34/*
34 * inline functions35 * inline functions
drivers/gpu/drm/gma500/psb_irq.h+1−1
@@ -24,7 +24,7 @@ · 23 unmodified lines
24#ifndef _PSB_IRQ_H_24#ifndef _PSB_IRQ_H_
25#define _PSB_IRQ_H_25#define _PSB_IRQ_H_
26 26
27#include <drm/drmP.h>27struct drm_device;
28 28
29bool sysirq_init(struct drm_device *dev);29bool sysirq_init(struct drm_device *dev);
30void sysirq_uninit(struct drm_device *dev);30void sysirq_uninit(struct drm_device *dev);
drivers/gpu/drm/gma500/psb_lid.c+3−3
@@ -17,11 +17,11 @@ · 16 unmodified lines
17 * Authors: Thomas Hellstrom <thomas-at-tungstengraphics-dot-com>17 * Authors: Thomas Hellstrom <thomas-at-tungstengraphics-dot-com>
18 **************************************************************************/18 **************************************************************************/
19 19
20#include <drm/drmP.h>20#include <linux/spinlock.h>
21
21#include "psb_drv.h"22#include "psb_drv.h"
22#include "psb_reg.h"
23#include "psb_intel_reg.h"23#include "psb_intel_reg.h"
24#include <linux/spinlock.h>24#include "psb_reg.h"
25 25
26static void psb_lid_timer_func(struct timer_list *t)26static void psb_lid_timer_func(struct timer_list *t)
27{27{
drivers/gpu/drm/gma500/tc35876x-dsi-lvds.c+8−5
@@ -22,15 +22,18 @@ · 21 unmodified lines
22 *22 *
23 */23 */
24 24
25#include "mdfld_dsi_dpi.h"25#include <linux/delay.h>
26#include "mdfld_output.h"
27#include "mdfld_dsi_pkg_sender.h"
28#include "tc35876x-dsi-lvds.h"
29#include <linux/platform_data/tc35876x.h>
30#include <linux/kernel.h>26#include <linux/kernel.h>
31#include <linux/module.h>27#include <linux/module.h>
28#include <linux/platform_data/tc35876x.h>
29
32#include <asm/intel_scu_ipc.h>30#include <asm/intel_scu_ipc.h>
33 31
32#include "mdfld_dsi_dpi.h"
33#include "mdfld_dsi_pkg_sender.h"
34#include "mdfld_output.h"
35#include "tc35876x-dsi-lvds.h"
36
34static struct i2c_client *tc35876x_client;37static struct i2c_client *tc35876x_client;
35static struct i2c_client *cmi_lcd_i2c_client;38static struct i2c_client *cmi_lcd_i2c_client;
36 39
drivers/gpu/drm/hisilicon/hibmc/Kconfig+1−1
@@ -3,7 +3,7 @@ config DRM_HISI_HIBMC · 2 unmodified lines
3 tristate "DRM Support for Hisilicon Hibmc"3 tristate "DRM Support for Hisilicon Hibmc"
4 depends on DRM && PCI && MMU4 depends on DRM && PCI && MMU
5 select DRM_KMS_HELPER5 select DRM_KMS_HELPER
6 select DRM_TTM6 select DRM_VRAM_HELPER
7 7
8 help8 help
9 Choose this option if you have a Hisilicon Hibmc soc chipset.9 Choose this option if you have a Hisilicon Hibmc soc chipset.
drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c+9−10
@@ -96,27 +96,26 @@ static void hibmc_plane_atomic_update(struct drm_plane *plane, · 95 unmodified lines
96 struct drm_plane_state *state = plane->state;96 struct drm_plane_state *state = plane->state;
97 u32 reg;97 u32 reg;
98 int ret;98 int ret;
99 u64 gpu_addr = 0;99 s64 gpu_addr = 0;
100 unsigned int line_l;100 unsigned int line_l;
101 struct hibmc_drm_private *priv = plane->dev->dev_private;101 struct hibmc_drm_private *priv = plane->dev->dev_private;
102 struct hibmc_framebuffer *hibmc_fb;102 struct hibmc_framebuffer *hibmc_fb;
103 struct hibmc_bo *bo;103 struct drm_gem_vram_object *gbo;
104 104
105 if (!state->fb)105 if (!state->fb)
106 return;106 return;
107 107
108 hibmc_fb = to_hibmc_framebuffer(state->fb);108 hibmc_fb = to_hibmc_framebuffer(state->fb);
109 bo = gem_to_hibmc_bo(hibmc_fb->obj);109 gbo = drm_gem_vram_of_gem(hibmc_fb->obj);
110 ret = ttm_bo_reserve(&bo->bo, true, false, NULL);110
111 ret = drm_gem_vram_pin(gbo, DRM_GEM_VRAM_PL_FLAG_VRAM);
111 if (ret) {112 if (ret) {
112 DRM_ERROR("failed to reserve ttm_bo: %d", ret);113 DRM_ERROR("failed to pin bo: %d", ret);
113 return;114 return;
114 }115 }
115 116 gpu_addr = drm_gem_vram_offset(gbo);
116 ret = hibmc_bo_pin(bo, TTM_PL_FLAG_VRAM, &gpu_addr);117 if (gpu_addr < 0) {
117 ttm_bo_unreserve(&bo->bo);118 drm_gem_vram_unpin(gbo);
118 if (ret) {
119 DRM_ERROR("failed to pin hibmc_bo: %d", ret);
120 return;119 return;
121 }120 }
122 121
drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c+4−10
@@ -27,14 +27,7 @@ · 26 unmodified lines
27 27
28static const struct file_operations hibmc_fops = {28static const struct file_operations hibmc_fops = {
29 .owner = THIS_MODULE,29 .owner = THIS_MODULE,
30 .open = drm_open,30 DRM_VRAM_MM_FILE_OPERATIONS
31 .release = drm_release,
32 .unlocked_ioctl = drm_ioctl,
33 .compat_ioctl = drm_compat_ioctl,
34 .mmap = hibmc_mmap,
35 .poll = drm_poll,
36 .read = drm_read,
37 .llseek = no_llseek,
38};31};
39 32
40static irqreturn_t hibmc_drm_interrupt(int irq, void *arg)33static irqreturn_t hibmc_drm_interrupt(int irq, void *arg)
@@ -63,9 +56,10 @@ static struct drm_driver hibmc_driver = { · 22 unmodified lines
63 .desc = "hibmc drm driver",56 .desc = "hibmc drm driver",
64 .major = 1,57 .major = 1,
65 .minor = 0,58 .minor = 0,
66 .gem_free_object_unlocked = hibmc_gem_free_object,59 .gem_free_object_unlocked =
60 drm_gem_vram_driver_gem_free_object_unlocked,
67 .dumb_create = hibmc_dumb_create,61 .dumb_create = hibmc_dumb_create,
68 .dumb_map_offset = hibmc_dumb_mmap_offset,62 .dumb_map_offset = drm_gem_vram_driver_dumb_mmap_offset,
69 .irq_handler = hibmc_drm_interrupt,63 .irq_handler = hibmc_drm_interrupt,
70};64};
71 65
drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h+2−31
@@ -23,7 +23,8 @@ · 22 unmodified lines
23#include <drm/drm_atomic.h>23#include <drm/drm_atomic.h>
24#include <drm/drm_fb_helper.h>24#include <drm/drm_fb_helper.h>
25#include <drm/drm_gem.h>25#include <drm/drm_gem.h>
26#include <drm/ttm/ttm_bo_driver.h>26#include <drm/drm_gem_vram_helper.h>
27#include <drm/drm_vram_mm_helper.h>
27 28
28struct hibmc_framebuffer {29struct hibmc_framebuffer {
29 struct drm_framebuffer fb;30 struct drm_framebuffer fb;
@@ -48,36 +49,12 @@ struct hibmc_drm_private { · 18 unmodified lines
48 struct drm_device *dev;49 struct drm_device *dev;
49 bool mode_config_initialized;50 bool mode_config_initialized;
50 51
51 /* ttm */
52 struct ttm_bo_device bdev;
53 bool initialized;
54
55 /* fbdev */52 /* fbdev */
56 struct hibmc_fbdev *fbdev;53 struct hibmc_fbdev *fbdev;
57 bool mm_inited;
58};54};
59 55
60#define to_hibmc_framebuffer(x) container_of(x, struct hibmc_framebuffer, fb)56#define to_hibmc_framebuffer(x) container_of(x, struct hibmc_framebuffer, fb)
61 57
62struct hibmc_bo {
63 struct ttm_buffer_object bo;
64 struct ttm_placement placement;
65 struct ttm_bo_kmap_obj kmap;
66 struct drm_gem_object gem;
67 struct ttm_place placements[3];
68 int pin_count;
69};
70
71static inline struct hibmc_bo *hibmc_bo(struct ttm_buffer_object *bo)
72{
73 return container_of(bo, struct hibmc_bo, bo);
74}
75
76static inline struct hibmc_bo *gem_to_hibmc_bo(struct drm_gem_object *gem)
77{
78 return container_of(gem, struct hibmc_bo, gem);
79}
80
81void hibmc_set_power_mode(struct hibmc_drm_private *priv,58void hibmc_set_power_mode(struct hibmc_drm_private *priv,
82 unsigned int power_mode);59 unsigned int power_mode);
83void hibmc_set_current_gate(struct hibmc_drm_private *priv,60void hibmc_set_current_gate(struct hibmc_drm_private *priv,
@@ -97,14 +74,8 @@ hibmc_framebuffer_init(struct drm_device *dev, · 13 unmodified lines
97 74
98int hibmc_mm_init(struct hibmc_drm_private *hibmc);75int hibmc_mm_init(struct hibmc_drm_private *hibmc);
99void hibmc_mm_fini(struct hibmc_drm_private *hibmc);76void hibmc_mm_fini(struct hibmc_drm_private *hibmc);
100int hibmc_bo_pin(struct hibmc_bo *bo, u32 pl_flag, u64 *gpu_addr);
101int hibmc_bo_unpin(struct hibmc_bo *bo);
102void hibmc_gem_free_object(struct drm_gem_object *obj);
103int hibmc_dumb_create(struct drm_file *file, struct drm_device *dev,77int hibmc_dumb_create(struct drm_file *file, struct drm_device *dev,
104 struct drm_mode_create_dumb *args);78 struct drm_mode_create_dumb *args);
105int hibmc_dumb_mmap_offset(struct drm_file *file, struct drm_device *dev,
106 u32 handle, u64 *offset);
107int hibmc_mmap(struct file *filp, struct vm_area_struct *vma);
108 79
109extern const struct drm_mode_config_funcs hibmc_mode_funcs;80extern const struct drm_mode_config_funcs hibmc_mode_funcs;
110 81
drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_fbdev.c+12−25
@@ -63,10 +63,10 @@ static int hibmc_drm_fb_create(struct drm_fb_helper *helper, · 62 unmodified lines
63 struct drm_mode_fb_cmd2 mode_cmd;63 struct drm_mode_fb_cmd2 mode_cmd;
64 struct drm_gem_object *gobj = NULL;64 struct drm_gem_object *gobj = NULL;
65 int ret = 0;65 int ret = 0;
66 int ret1;
67 size_t size;66 size_t size;
68 unsigned int bytes_per_pixel;67 unsigned int bytes_per_pixel;
69 struct hibmc_bo *bo = NULL;68 struct drm_gem_vram_object *gbo = NULL;
69 void *base;
70 70
71 DRM_DEBUG_DRIVER("surface width(%d), height(%d) and bpp(%d)\n",71 DRM_DEBUG_DRIVER("surface width(%d), height(%d) and bpp(%d)\n",
72 sizes->surface_width, sizes->surface_height,72 sizes->surface_width, sizes->surface_height,
@@ -88,26 +88,20 @@ static int hibmc_drm_fb_create(struct drm_fb_helper *helper, · 15 unmodified lines
88 return -ENOMEM;88 return -ENOMEM;
89 }89 }
90 90
91 bo = gem_to_hibmc_bo(gobj);91 gbo = drm_gem_vram_of_gem(gobj);
92 92
93 ret = ttm_bo_reserve(&bo->bo, true, false, NULL);93 ret = drm_gem_vram_pin(gbo, DRM_GEM_VRAM_PL_FLAG_VRAM);
94 if (ret) {
95 DRM_ERROR("failed to reserve ttm_bo: %d\n", ret);
96 goto out_unref_gem;
97 }
98
99 ret = hibmc_bo_pin(bo, TTM_PL_FLAG_VRAM, NULL);
100 if (ret) {94 if (ret) {
101 DRM_ERROR("failed to pin fbcon: %d\n", ret);95 DRM_ERROR("failed to pin fbcon: %d\n", ret);
102 goto out_unreserve_ttm_bo;96 goto out_unref_gem;
103 }97 }
104 98
105 ret = ttm_bo_kmap(&bo->bo, 0, bo->bo.num_pages, &bo->kmap);99 base = drm_gem_vram_kmap(gbo, true, NULL);
106 if (ret) {100 if (IS_ERR(base)) {
101 ret = PTR_ERR(base);
107 DRM_ERROR("failed to kmap fbcon: %d\n", ret);102 DRM_ERROR("failed to kmap fbcon: %d\n", ret);
108 goto out_unpin_bo;103 goto out_unpin_bo;
109 }104 }
110 ttm_bo_unreserve(&bo->bo);
111 105
112 info = drm_fb_helper_alloc_fbi(helper);106 info = drm_fb_helper_alloc_fbi(helper);
113 if (IS_ERR(info)) {107 if (IS_ERR(info)) {
@@ -131,24 +125,17 @@ static int hibmc_drm_fb_create(struct drm_fb_helper *helper, · 17 unmodified lines
131 125
132 drm_fb_helper_fill_info(info, &priv->fbdev->helper, sizes);126 drm_fb_helper_fill_info(info, &priv->fbdev->helper, sizes);
133 127
134 info->screen_base = bo->kmap.virtual;128 info->screen_base = base;
135 info->screen_size = size;129 info->screen_size = size;
136 130
137 info->fix.smem_start = bo->bo.mem.bus.offset + bo->bo.mem.bus.base;131 info->fix.smem_start = gbo->bo.mem.bus.offset + gbo->bo.mem.bus.base;
138 info->fix.smem_len = size;132 info->fix.smem_len = size;
139 return 0;133 return 0;
140 134
141out_release_fbi:135out_release_fbi:
142 ret1 = ttm_bo_reserve(&bo->bo, true, false, NULL);136 drm_gem_vram_kunmap(gbo);
143 if (ret1) {
144 DRM_ERROR("failed to rsv ttm_bo when release fbi: %d\n", ret1);
145 goto out_unref_gem;
146 }
147 ttm_bo_kunmap(&bo->kmap);
148out_unpin_bo:137out_unpin_bo:
149 hibmc_bo_unpin(bo);138 drm_gem_vram_unpin(gbo);
150out_unreserve_ttm_bo:
151 ttm_bo_unreserve(&bo->bo);
152out_unref_gem:139out_unref_gem:
153 drm_gem_object_put_unlocked(gobj);140 drm_gem_object_put_unlocked(gobj);
154 141
drivers/gpu/drm/hisilicon/hibmc/hibmc_ttm.c+16−325
@@ -17,335 +17,55 @@ · 16 unmodified lines
17 */17 */
18 18
19#include <drm/drm_atomic_helper.h>19#include <drm/drm_atomic_helper.h>
20#include <drm/ttm/ttm_page_alloc.h>
21 20
22#include "hibmc_drm_drv.h"21#include "hibmc_drm_drv.h"
23 22
24static inline struct hibmc_drm_private *
25hibmc_bdev(struct ttm_bo_device *bd)
26{
27 return container_of(bd, struct hibmc_drm_private, bdev);
28}
29
30static void hibmc_bo_ttm_destroy(struct ttm_buffer_object *tbo)
31{
32 struct hibmc_bo *bo = container_of(tbo, struct hibmc_bo, bo);
33
34 drm_gem_object_release(&bo->gem);
35 kfree(bo);
36}
37
38static bool hibmc_ttm_bo_is_hibmc_bo(struct ttm_buffer_object *bo)
39{
40 return bo->destroy == &hibmc_bo_ttm_destroy;
41}
42
43static int
44hibmc_bo_init_mem_type(struct ttm_bo_device *bdev, u32 type,
45 struct ttm_mem_type_manager *man)
46{
47 switch (type) {
48 case TTM_PL_SYSTEM:
49 man->flags = TTM_MEMTYPE_FLAG_MAPPABLE;
50 man->available_caching = TTM_PL_MASK_CACHING;
51 man->default_caching = TTM_PL_FLAG_CACHED;
52 break;
53 case TTM_PL_VRAM:
54 man->func = &ttm_bo_manager_func;
55 man->flags = TTM_MEMTYPE_FLAG_FIXED |
56 TTM_MEMTYPE_FLAG_MAPPABLE;
57 man->available_caching = TTM_PL_FLAG_UNCACHED |
58 TTM_PL_FLAG_WC;
59 man->default_caching = TTM_PL_FLAG_WC;
60 break;
61 default:
62 DRM_ERROR("unsupported memory type %u\n", type);
63 return -EINVAL;
64 }
65 return 0;
66}
67
68void hibmc_ttm_placement(struct hibmc_bo *bo, int domain)
69{
70 u32 count = 0;
71 u32 i;
72
73 bo->placement.placement = bo->placements;
74 bo->placement.busy_placement = bo->placements;
75 if (domain & TTM_PL_FLAG_VRAM)
76 bo->placements[count++].flags = TTM_PL_FLAG_WC |
77 TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_VRAM;
78 if (domain & TTM_PL_FLAG_SYSTEM)
79 bo->placements[count++].flags = TTM_PL_MASK_CACHING |
80 TTM_PL_FLAG_SYSTEM;
81 if (!count)
82 bo->placements[count++].flags = TTM_PL_MASK_CACHING |
83 TTM_PL_FLAG_SYSTEM;
84
85 bo->placement.num_placement = count;
86 bo->placement.num_busy_placement = count;
87 for (i = 0; i < count; i++) {
88 bo->placements[i].fpfn = 0;
89 bo->placements[i].lpfn = 0;
90 }
91}
92
93static void
94hibmc_bo_evict_flags(struct ttm_buffer_object *bo, struct ttm_placement *pl)
95{
96 struct hibmc_bo *hibmcbo = hibmc_bo(bo);
97
98 if (!hibmc_ttm_bo_is_hibmc_bo(bo))
99 return;
100
101 hibmc_ttm_placement(hibmcbo, TTM_PL_FLAG_SYSTEM);
102 *pl = hibmcbo->placement;
103}
104
105static int hibmc_bo_verify_access(struct ttm_buffer_object *bo,
106 struct file *filp)
107{
108 struct hibmc_bo *hibmcbo = hibmc_bo(bo);
109
110 return drm_vma_node_verify_access(&hibmcbo->gem.vma_node,
111 filp->private_data);
112}
113
114static int hibmc_ttm_io_mem_reserve(struct ttm_bo_device *bdev,
115 struct ttm_mem_reg *mem)
116{
117 struct ttm_mem_type_manager *man = &bdev->man[mem->mem_type];
118 struct hibmc_drm_private *hibmc = hibmc_bdev(bdev);
119
120 mem->bus.addr = NULL;
121 mem->bus.offset = 0;
122 mem->bus.size = mem->num_pages << PAGE_SHIFT;
123 mem->bus.base = 0;
124 mem->bus.is_iomem = false;
125 if (!(man->flags & TTM_MEMTYPE_FLAG_MAPPABLE))
126 return -EINVAL;
127 switch (mem->mem_type) {
128 case TTM_PL_SYSTEM:
129 /* system memory */
130 return 0;
131 case TTM_PL_VRAM:
132 mem->bus.offset = mem->start << PAGE_SHIFT;
133 mem->bus.base = pci_resource_start(hibmc->dev->pdev, 0);
134 mem->bus.is_iomem = true;
135 break;
136 default:
137 return -EINVAL;
138 }
139 return 0;
140}
141
142static void hibmc_ttm_backend_destroy(struct ttm_tt *tt)
143{
144 ttm_tt_fini(tt);
145 kfree(tt);
146}
147
148static struct ttm_backend_func hibmc_tt_backend_func = {
149 .destroy = &hibmc_ttm_backend_destroy,
150};
151
152static struct ttm_tt *hibmc_ttm_tt_create(struct ttm_buffer_object *bo,
153 u32 page_flags)
154{
155 struct ttm_tt *tt;
156 int ret;
157
158 tt = kzalloc(sizeof(*tt), GFP_KERNEL);
159 if (!tt) {
160 DRM_ERROR("failed to allocate ttm_tt\n");
161 return NULL;
162 }
163 tt->func = &hibmc_tt_backend_func;
164 ret = ttm_tt_init(tt, bo, page_flags);
165 if (ret) {
166 DRM_ERROR("failed to initialize ttm_tt: %d\n", ret);
167 kfree(tt);
168 return NULL;
169 }
170 return tt;
171}
172
173struct ttm_bo_driver hibmc_bo_driver = {
174 .ttm_tt_create = hibmc_ttm_tt_create,
175 .init_mem_type = hibmc_bo_init_mem_type,
176 .evict_flags = hibmc_bo_evict_flags,
177 .move = NULL,
178 .verify_access = hibmc_bo_verify_access,
179 .io_mem_reserve = &hibmc_ttm_io_mem_reserve,
180 .io_mem_free = NULL,
181};
182
183int hibmc_mm_init(struct hibmc_drm_private *hibmc)23int hibmc_mm_init(struct hibmc_drm_private *hibmc)
184{24{
25 struct drm_vram_mm *vmm;
185 int ret;26 int ret;
186 struct drm_device *dev = hibmc->dev;27 struct drm_device *dev = hibmc->dev;
187 struct ttm_bo_device *bdev = &hibmc->bdev;
188 28
189 ret = ttm_bo_device_init(&hibmc->bdev,29 vmm = drm_vram_helper_alloc_mm(dev,
190 &hibmc_bo_driver,30 pci_resource_start(dev->pdev, 0),
191 dev->anon_inode->i_mapping,31 hibmc->fb_size, &drm_gem_vram_mm_funcs);
192 true);32 if (IS_ERR(vmm)) {
193 if (ret) {33 ret = PTR_ERR(vmm);
194 DRM_ERROR("error initializing bo driver: %d\n", ret);34 DRM_ERROR("Error initializing VRAM MM; %d\n", ret);
195 return ret;35 return ret;
196 }36 }
197 37
198 ret = ttm_bo_init_mm(bdev, TTM_PL_VRAM,
199 hibmc->fb_size >> PAGE_SHIFT);
200 if (ret) {
201 DRM_ERROR("failed ttm VRAM init: %d\n", ret);
202 return ret;
203 }
204
205 hibmc->mm_inited = true;
206 return 0;38 return 0;
207}39}
208 40
209void hibmc_mm_fini(struct hibmc_drm_private *hibmc)41void hibmc_mm_fini(struct hibmc_drm_private *hibmc)
210{42{
211 if (!hibmc->mm_inited)43 if (!hibmc->dev->vram_mm)
212 return;
213
214 ttm_bo_device_release(&hibmc->bdev);
215 hibmc->mm_inited = false;
216}
217
218static void hibmc_bo_unref(struct hibmc_bo **bo)
219{
220 struct ttm_buffer_object *tbo;
221
222 if ((*bo) == NULL)
223 return;44 return;
224 45
225 tbo = &((*bo)->bo);46 drm_vram_helper_release_mm(hibmc->dev);
226 ttm_bo_put(tbo);
227 *bo = NULL;
228}
229
230int hibmc_bo_create(struct drm_device *dev, int size, int align,
231 u32 flags, struct hibmc_bo **phibmcbo)
232{
233 struct hibmc_drm_private *hibmc = dev->dev_private;
234 struct hibmc_bo *hibmcbo;
235 size_t acc_size;
236 int ret;
237
238 hibmcbo = kzalloc(sizeof(*hibmcbo), GFP_KERNEL);
239 if (!hibmcbo) {
240 DRM_ERROR("failed to allocate hibmcbo\n");
241 return -ENOMEM;
242 }
243 ret = drm_gem_object_init(dev, &hibmcbo->gem, size);
244 if (ret) {
245 DRM_ERROR("failed to initialize drm gem object: %d\n", ret);
246 kfree(hibmcbo);
247 return ret;
248 }
249
250 hibmcbo->bo.bdev = &hibmc->bdev;
251
252 hibmc_ttm_placement(hibmcbo, TTM_PL_FLAG_VRAM | TTM_PL_FLAG_SYSTEM);
253
254 acc_size = ttm_bo_dma_acc_size(&hibmc->bdev, size,
255 sizeof(struct hibmc_bo));
256
257 ret = ttm_bo_init(&hibmc->bdev, &hibmcbo->bo, size,
258 ttm_bo_type_device, &hibmcbo->placement,
259 align >> PAGE_SHIFT, false, acc_size,
260 NULL, NULL, hibmc_bo_ttm_destroy);
261 if (ret) {
262 hibmc_bo_unref(&hibmcbo);
263 DRM_ERROR("failed to initialize ttm_bo: %d\n", ret);
264 return ret;
265 }
266
267 *phibmcbo = hibmcbo;
268 return 0;
269}
270
271int hibmc_bo_pin(struct hibmc_bo *bo, u32 pl_flag, u64 *gpu_addr)
272{
273 struct ttm_operation_ctx ctx = { false, false };
274 int i, ret;
275
276 if (bo->pin_count) {
277 bo->pin_count++;
278 if (gpu_addr)
279 *gpu_addr = bo->bo.offset;
280 return 0;
281 }
282
283 hibmc_ttm_placement(bo, pl_flag);
284 for (i = 0; i < bo->placement.num_placement; i++)
285 bo->placements[i].flags |= TTM_PL_FLAG_NO_EVICT;
286 ret = ttm_bo_validate(&bo->bo, &bo->placement, &ctx);
287 if (ret)
288 return ret;
289
290 bo->pin_count = 1;
291 if (gpu_addr)
292 *gpu_addr = bo->bo.offset;
293 return 0;
294}
295
296int hibmc_bo_unpin(struct hibmc_bo *bo)
297{
298 struct ttm_operation_ctx ctx = { false, false };
299 int i, ret;
300
301 if (!bo->pin_count) {
302 DRM_ERROR("unpin bad %p\n", bo);
303 return 0;
304 }
305 bo->pin_count--;
306 if (bo->pin_count)
307 return 0;
308
309 for (i = 0; i < bo->placement.num_placement ; i++)
310 bo->placements[i].flags &= ~TTM_PL_FLAG_NO_EVICT;
311 ret = ttm_bo_validate(&bo->bo, &bo->placement, &ctx);
312 if (ret) {
313 DRM_ERROR("validate failed for unpin: %d\n", ret);
314 return ret;
315 }
316
317 return 0;
318}
319
320int hibmc_mmap(struct file *filp, struct vm_area_struct *vma)
321{
322 struct drm_file *file_priv = filp->private_data;
323 struct hibmc_drm_private *hibmc = file_priv->minor->dev->dev_private;
324
325 return ttm_bo_mmap(filp, vma, &hibmc->bdev);
326}47}
327 48
328int hibmc_gem_create(struct drm_device *dev, u32 size, bool iskernel,49int hibmc_gem_create(struct drm_device *dev, u32 size, bool iskernel,
329 struct drm_gem_object **obj)50 struct drm_gem_object **obj)
330{51{
331 struct hibmc_bo *hibmcbo;52 struct drm_gem_vram_object *gbo;
332 int ret;53 int ret;
333 54
334 *obj = NULL;55 *obj = NULL;
335 56
336 size = PAGE_ALIGN(size);57 size = roundup(size, PAGE_SIZE);
337 if (size == 0) {58 if (size == 0)
338 DRM_ERROR("error: zero size\n");
339 return -EINVAL;59 return -EINVAL;
340 }
341 60
342 ret = hibmc_bo_create(dev, size, 0, 0, &hibmcbo);61 gbo = drm_gem_vram_create(dev, &dev->vram_mm->bdev, size, 0, false);
343 if (ret) {62 if (IS_ERR(gbo)) {
63 ret = PTR_ERR(gbo);
344 if (ret != -ERESTARTSYS)64 if (ret != -ERESTARTSYS)
345 DRM_ERROR("failed to allocate GEM object: %d\n", ret);65 DRM_ERROR("failed to allocate GEM object: %d\n", ret);
346 return ret;66 return ret;
347 }67 }
348 *obj = &hibmcbo->gem;68 *obj = &gbo->gem;
349 return 0;69 return 0;
350}70}
351 71
@@ -377,35 +97,6 @@ int hibmc_dumb_create(struct drm_file *file, struct drm_device *dev, · 25 unmodified lines
377 return 0;97 return 0;
378}98}
379 99
380void hibmc_gem_free_object(struct drm_gem_object *obj)
381{
382 struct hibmc_bo *hibmcbo = gem_to_hibmc_bo(obj);
383
384 hibmc_bo_unref(&hibmcbo);
385}
386
387static u64 hibmc_bo_mmap_offset(struct hibmc_bo *bo)
388{
389 return drm_vma_node_offset_addr(&bo->bo.vma_node);
390}
391
392int hibmc_dumb_mmap_offset(struct drm_file *file, struct drm_device *dev,
393 u32 handle, u64 *offset)
394{
395 struct drm_gem_object *obj;
396 struct hibmc_bo *bo;
397
398 obj = drm_gem_object_lookup(file, handle);
399 if (!obj)
400 return -ENOENT;
401
402 bo = gem_to_hibmc_bo(obj);
403 *offset = hibmc_bo_mmap_offset(bo);
404
405 drm_gem_object_put_unlocked(obj);
406 return 0;
407}
408
409static void hibmc_user_framebuffer_destroy(struct drm_framebuffer *fb)100static void hibmc_user_framebuffer_destroy(struct drm_framebuffer *fb)
410{101{
411 struct hibmc_framebuffer *hibmc_fb = to_hibmc_framebuffer(fb);102 struct hibmc_framebuffer *hibmc_fb = to_hibmc_framebuffer(fb);
drivers/gpu/drm/i915/intel_display.c+2−3
@@ -14605,9 +14605,8 @@ static int intel_crtc_init(struct drm_i915_private *dev_priv, enum pipe pipe) · 14604 unmodified lines
14605 ret = -ENOMEM;14605 ret = -ENOMEM;
14606 goto fail;14606 goto fail;
14607 }14607 }
14608 __drm_atomic_helper_crtc_reset(&intel_crtc->base, &crtc_state->base);
14608 intel_crtc->config = crtc_state;14609 intel_crtc->config = crtc_state;
14609 intel_crtc->base.state = &crtc_state->base;
14610 crtc_state->base.crtc = &intel_crtc->base;
14611 14610
14612 primary = intel_primary_plane_create(dev_priv, pipe);14611 primary = intel_primary_plane_create(dev_priv, pipe);
14613 if (IS_ERR(primary)) {14612 if (IS_ERR(primary)) {
@@ -16149,7 +16148,7 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev) · 1535 unmodified lines
16149 16148
16150 __drm_atomic_helper_crtc_destroy_state(&crtc_state->base);16149 __drm_atomic_helper_crtc_destroy_state(&crtc_state->base);
16151 memset(crtc_state, 0, sizeof(*crtc_state));16150 memset(crtc_state, 0, sizeof(*crtc_state));
16152 crtc_state->base.crtc = &crtc->base;16151 __drm_atomic_helper_crtc_reset(&crtc->base, &crtc_state->base);
16153 16152
16154 crtc_state->base.active = crtc_state->base.enable =16153 crtc_state->base.active = crtc_state->base.enable =
16155 dev_priv->display.get_pipe_config(crtc, crtc_state);16154 dev_priv->display.get_pipe_config(crtc, crtc_state);
drivers/gpu/drm/i915/intel_sprite.c+2−1
@@ -325,7 +325,8 @@ skl_plane_max_stride(struct intel_plane *plane, · 324 unmodified lines
325 u32 pixel_format, u64 modifier,325 u32 pixel_format, u64 modifier,
326 unsigned int rotation)326 unsigned int rotation)
327{327{
328 int cpp = drm_format_plane_cpp(pixel_format, 0);328 const struct drm_format_info *info = drm_format_info(pixel_format);
329 int cpp = info->cpp[0];
329 330
330 /*331 /*
331 * "The stride in bytes must not exceed the332 * "The stride in bytes must not exceed the
drivers/gpu/drm/imx/ipuv3-plane.c+6−9
@@ -115,8 +115,8 @@ drm_plane_state_to_ubo(struct drm_plane_state *state) · 114 unmodified lines
115 cma_obj = drm_fb_cma_get_gem_obj(fb, 1);115 cma_obj = drm_fb_cma_get_gem_obj(fb, 1);
116 BUG_ON(!cma_obj);116 BUG_ON(!cma_obj);
117 117
118 x /= drm_format_horz_chroma_subsampling(fb->format->format);118 x /= fb->format->hsub;
119 y /= drm_format_vert_chroma_subsampling(fb->format->format);119 y /= fb->format->vsub;
120 120
121 return cma_obj->paddr + fb->offsets[1] + fb->pitches[1] * y +121 return cma_obj->paddr + fb->offsets[1] + fb->pitches[1] * y +
122 fb->format->cpp[1] * x - eba;122 fb->format->cpp[1] * x - eba;
@@ -134,8 +134,8 @@ drm_plane_state_to_vbo(struct drm_plane_state *state) · 11 unmodified lines
134 cma_obj = drm_fb_cma_get_gem_obj(fb, 2);134 cma_obj = drm_fb_cma_get_gem_obj(fb, 2);
135 BUG_ON(!cma_obj);135 BUG_ON(!cma_obj);
136 136
137 x /= drm_format_horz_chroma_subsampling(fb->format->format);137 x /= fb->format->hsub;
138 y /= drm_format_vert_chroma_subsampling(fb->format->format);138 y /= fb->format->vsub;
139 139
140 return cma_obj->paddr + fb->offsets[2] + fb->pitches[2] * y +140 return cma_obj->paddr + fb->offsets[2] + fb->pitches[2] * y +
141 fb->format->cpp[2] * x - eba;141 fb->format->cpp[2] * x - eba;
@@ -352,7 +352,6 @@ static int ipu_plane_atomic_check(struct drm_plane *plane, · 210 unmodified lines
352 struct drm_framebuffer *old_fb = old_state->fb;352 struct drm_framebuffer *old_fb = old_state->fb;
353 unsigned long eba, ubo, vbo, old_ubo, old_vbo, alpha_eba;353 unsigned long eba, ubo, vbo, old_ubo, old_vbo, alpha_eba;
354 bool can_position = (plane->type == DRM_PLANE_TYPE_OVERLAY);354 bool can_position = (plane->type == DRM_PLANE_TYPE_OVERLAY);
355 int hsub, vsub;
356 int ret;355 int ret;
357 356
358 /* Ok to disable */357 /* Ok to disable */
@@ -471,10 +470,8 @@ static int ipu_plane_atomic_check(struct drm_plane *plane, · 112 unmodified lines
471 * The x/y offsets must be even in case of horizontal/vertical470 * The x/y offsets must be even in case of horizontal/vertical
472 * chroma subsampling.471 * chroma subsampling.
473 */472 */
474 hsub = drm_format_horz_chroma_subsampling(fb->format->format);473 if (((state->src.x1 >> 16) & (fb->format->hsub - 1)) ||
475 vsub = drm_format_vert_chroma_subsampling(fb->format->format);474 ((state->src.y1 >> 16) & (fb->format->vsub - 1)))
476 if (((state->src.x1 >> 16) & (hsub - 1)) ||
477 ((state->src.y1 >> 16) & (vsub - 1)))
478 return -EINVAL;475 return -EINVAL;
479 break;476 break;
480 case DRM_FORMAT_RGB565_A8:477 case DRM_FORMAT_RGB565_A8:
drivers/gpu/drm/lima/lima_drv.c+1−1
@@ -17,7 +17,7 @@ · 16 unmodified lines
17 17
18int lima_sched_timeout_ms;18int lima_sched_timeout_ms;
19 19
20MODULE_PARM_DESC(sched_timeout_ms, "task run timeout in ms (0 = no timeout (default))");20MODULE_PARM_DESC(sched_timeout_ms, "task run timeout in ms");
21module_param_named(sched_timeout_ms, lima_sched_timeout_ms, int, 0444);21module_param_named(sched_timeout_ms, lima_sched_timeout_ms, int, 0444);
22 22
23static int lima_ioctl_get_param(struct drm_device *dev, void *data, struct drm_file *file)23static int lima_ioctl_get_param(struct drm_device *dev, void *data, struct drm_file *file)
drivers/gpu/drm/lima/lima_pp.c+7−1
@@ -64,7 +64,13 @@ static irqreturn_t lima_pp_bcast_irq_handler(int irq, void *data) · 63 unmodified lines
64 struct lima_ip *pp_bcast = data;64 struct lima_ip *pp_bcast = data;
65 struct lima_device *dev = pp_bcast->dev;65 struct lima_device *dev = pp_bcast->dev;
66 struct lima_sched_pipe *pipe = dev->pipe + lima_pipe_pp;66 struct lima_sched_pipe *pipe = dev->pipe + lima_pipe_pp;
67 struct drm_lima_m450_pp_frame *frame = pipe->current_task->frame;67 struct drm_lima_m450_pp_frame *frame;
68
69 /* for shared irq case */
70 if (!pipe->current_task)
71 return IRQ_NONE;
72
73 frame = pipe->current_task->frame;
68 74
69 for (i = 0; i < frame->num_pp; i++) {75 for (i = 0; i < frame->num_pp; i++) {
70 struct lima_ip *ip = pipe->processor[i];76 struct lima_ip *ip = pipe->processor[i];
drivers/gpu/drm/lima/lima_sched.c+5−8
@@ -258,7 +258,7 @@ static struct dma_fence *lima_sched_run_job(struct drm_sched_job *job) · 257 unmodified lines
258static void lima_sched_handle_error_task(struct lima_sched_pipe *pipe,258static void lima_sched_handle_error_task(struct lima_sched_pipe *pipe,
259 struct lima_sched_task *task)259 struct lima_sched_task *task)
260{260{
261 drm_sched_stop(&pipe->base);261 drm_sched_stop(&pipe->base, &task->base);
262 262
263 if (task)263 if (task)
264 drm_sched_increase_karma(&task->base);264 drm_sched_increase_karma(&task->base);
@@ -329,19 +329,16 @@ static void lima_sched_error_work(struct work_struct *work) · 64 unmodified lines
329 329
330int lima_sched_pipe_init(struct lima_sched_pipe *pipe, const char *name)330int lima_sched_pipe_init(struct lima_sched_pipe *pipe, const char *name)
331{331{
332 long timeout;332 unsigned int timeout = lima_sched_timeout_ms > 0 ?
333 333 lima_sched_timeout_ms : 500;
334 if (lima_sched_timeout_ms <= 0)
335 timeout = MAX_SCHEDULE_TIMEOUT;
336 else
337 timeout = msecs_to_jiffies(lima_sched_timeout_ms);
338 334
339 pipe->fence_context = dma_fence_context_alloc(1);335 pipe->fence_context = dma_fence_context_alloc(1);
340 spin_lock_init(&pipe->fence_lock);336 spin_lock_init(&pipe->fence_lock);
341 337
342 INIT_WORK(&pipe->error_work, lima_sched_error_work);338 INIT_WORK(&pipe->error_work, lima_sched_error_work);
343 339
344 return drm_sched_init(&pipe->base, &lima_sched_ops, 1, 0, timeout, name);340 return drm_sched_init(&pipe->base, &lima_sched_ops, 1, 0,
341 msecs_to_jiffies(timeout), name);
345}342}
346 343
347void lima_sched_pipe_fini(struct lima_sched_pipe *pipe)344void lima_sched_pipe_fini(struct lima_sched_pipe *pipe)
drivers/gpu/drm/mediatek/mtk_drm_fb.c+5−3
@@ -32,10 +32,11 @@ static struct drm_framebuffer *mtk_drm_framebuffer_init(struct drm_device *dev, · 31 unmodified lines
32 const struct drm_mode_fb_cmd2 *mode,32 const struct drm_mode_fb_cmd2 *mode,
33 struct drm_gem_object *obj)33 struct drm_gem_object *obj)
34{34{
35 const struct drm_format_info *info = drm_get_format_info(dev, mode);
35 struct drm_framebuffer *fb;36 struct drm_framebuffer *fb;
36 int ret;37 int ret;
37 38
38 if (drm_format_num_planes(mode->pixel_format) != 1)39 if (info->num_planes != 1)
39 return ERR_PTR(-EINVAL);40 return ERR_PTR(-EINVAL);
40 41
41 fb = kzalloc(sizeof(*fb), GFP_KERNEL);42 fb = kzalloc(sizeof(*fb), GFP_KERNEL);
@@ -88,6 +89,7 @@ struct drm_framebuffer *mtk_drm_mode_fb_create(struct drm_device *dev, · 46 unmodified lines
88 struct drm_file *file,89 struct drm_file *file,
89 const struct drm_mode_fb_cmd2 *cmd)90 const struct drm_mode_fb_cmd2 *cmd)
90{91{
92 const struct drm_format_info *info = drm_get_format_info(dev, cmd);
91 struct drm_framebuffer *fb;93 struct drm_framebuffer *fb;
92 struct drm_gem_object *gem;94 struct drm_gem_object *gem;
93 unsigned int width = cmd->width;95 unsigned int width = cmd->width;
@@ -95,14 +97,14 @@ struct drm_framebuffer *mtk_drm_mode_fb_create(struct drm_device *dev, · 1 unmodified line
95 unsigned int size, bpp;97 unsigned int size, bpp;
96 int ret;98 int ret;
97 99
98 if (drm_format_num_planes(cmd->pixel_format) != 1)100 if (info->num_planes != 1)
99 return ERR_PTR(-EINVAL);101 return ERR_PTR(-EINVAL);
100 102
101 gem = drm_gem_object_lookup(file, cmd->handles[0]);103 gem = drm_gem_object_lookup(file, cmd->handles[0]);
102 if (!gem)104 if (!gem)
103 return ERR_PTR(-ENOENT);105 return ERR_PTR(-ENOENT);
104 106
105 bpp = drm_format_plane_cpp(cmd->pixel_format, 0);107 bpp = info->cpp[0];
106 size = (height - 1) * cmd->pitches[0] + width * bpp;108 size = (height - 1) * cmd->pitches[0] + width * bpp;
107 size += cmd->offsets[0];109 size += cmd->offsets[0];
108 110
drivers/gpu/drm/mediatek/mtk_hdmi.c+3−0
@@ -341,6 +341,9 @@ static void mtk_hdmi_hw_send_info_frame(struct mtk_hdmi *hdmi, u8 *buffer, · 340 unmodified lines
341 ctrl_frame_en = VS_EN;341 ctrl_frame_en = VS_EN;
342 ctrl_reg = GRL_ACP_ISRC_CTRL;342 ctrl_reg = GRL_ACP_ISRC_CTRL;
343 break;343 break;
344 default:
345 dev_err(hdmi->dev, "Unknown infoframe type %d\n", frame_type);
346 return;
344 }347 }
345 mtk_hdmi_clear_bits(hdmi, ctrl_reg, ctrl_frame_en);348 mtk_hdmi_clear_bits(hdmi, ctrl_reg, ctrl_frame_en);
346 mtk_hdmi_write(hdmi, GRL_INFOFRM_TYPE, frame_type);349 mtk_hdmi_write(hdmi, GRL_INFOFRM_TYPE, frame_type);
drivers/gpu/drm/meson/meson_overlay.c+7−7
@@ -458,7 +458,7 @@ static void meson_overlay_atomic_update(struct drm_plane *plane, · 457 unmodified lines
458 }458 }
459 459
460 /* Update Canvas with buffer address */460 /* Update Canvas with buffer address */
461 priv->viu.vd1_planes = drm_format_num_planes(fb->format->format);461 priv->viu.vd1_planes = fb->format->num_planes;
462 462
463 switch (priv->viu.vd1_planes) {463 switch (priv->viu.vd1_planes) {
464 case 3:464 case 3:
@@ -466,8 +466,8 @@ static void meson_overlay_atomic_update(struct drm_plane *plane, · 1 unmodified line
466 priv->viu.vd1_addr2 = gem->paddr + fb->offsets[2];466 priv->viu.vd1_addr2 = gem->paddr + fb->offsets[2];
467 priv->viu.vd1_stride2 = fb->pitches[2];467 priv->viu.vd1_stride2 = fb->pitches[2];
468 priv->viu.vd1_height2 =468 priv->viu.vd1_height2 =
469 drm_format_plane_height(fb->height,469 drm_format_info_plane_height(fb->format,
470 fb->format->format, 2);470 fb->height, 2);
471 DRM_DEBUG("plane 2 addr 0x%x stride %d height %d\n",471 DRM_DEBUG("plane 2 addr 0x%x stride %d height %d\n",
472 priv->viu.vd1_addr2,472 priv->viu.vd1_addr2,
473 priv->viu.vd1_stride2,473 priv->viu.vd1_stride2,
@@ -478,8 +478,8 @@ static void meson_overlay_atomic_update(struct drm_plane *plane, · 4 unmodified lines
478 priv->viu.vd1_addr1 = gem->paddr + fb->offsets[1];478 priv->viu.vd1_addr1 = gem->paddr + fb->offsets[1];
479 priv->viu.vd1_stride1 = fb->pitches[1];479 priv->viu.vd1_stride1 = fb->pitches[1];
480 priv->viu.vd1_height1 =480 priv->viu.vd1_height1 =
481 drm_format_plane_height(fb->height,481 drm_format_info_plane_height(fb->format,
482 fb->format->format, 1);482 fb->height, 1);
483 DRM_DEBUG("plane 1 addr 0x%x stride %d height %d\n",483 DRM_DEBUG("plane 1 addr 0x%x stride %d height %d\n",
484 priv->viu.vd1_addr1,484 priv->viu.vd1_addr1,
485 priv->viu.vd1_stride1,485 priv->viu.vd1_stride1,
@@ -490,8 +490,8 @@ static void meson_overlay_atomic_update(struct drm_plane *plane, · 4 unmodified lines
490 priv->viu.vd1_addr0 = gem->paddr + fb->offsets[0];490 priv->viu.vd1_addr0 = gem->paddr + fb->offsets[0];
491 priv->viu.vd1_stride0 = fb->pitches[0];491 priv->viu.vd1_stride0 = fb->pitches[0];
492 priv->viu.vd1_height0 =492 priv->viu.vd1_height0 =
493 drm_format_plane_height(fb->height,493 drm_format_info_plane_height(fb->format,
494 fb->format->format, 0);494 fb->height, 0);
495 DRM_DEBUG("plane 0 addr 0x%x stride %d height %d\n",495 DRM_DEBUG("plane 0 addr 0x%x stride %d height %d\n",
496 priv->viu.vd1_addr0,496 priv->viu.vd1_addr0,
497 priv->viu.vd1_stride0,497 priv->viu.vd1_stride0,
drivers/gpu/drm/mgag200/Kconfig+1−1
@@ -3,7 +3,7 @@ config DRM_MGAG200 · 2 unmodified lines
3 tristate "Kernel modesetting driver for MGA G200 server engines"3 tristate "Kernel modesetting driver for MGA G200 server engines"
4 depends on DRM && PCI && MMU4 depends on DRM && PCI && MMU
5 select DRM_KMS_HELPER5 select DRM_KMS_HELPER
6 select DRM_TTM6 select DRM_VRAM_HELPER
7 help7 help
8 This is a KMS driver for the MGA G200 server chips, it8 This is a KMS driver for the MGA G200 server chips, it
9 does not support the original MGA G200 or any of the desktop9 does not support the original MGA G200 or any of the desktop
drivers/gpu/drm/mgag200/mgag200_cursor.c+53−43
@@ -23,9 +23,9 @@ static void mga_hide_cursor(struct mga_device *mdev) · 22 unmodified lines
23 WREG8(MGA_CURPOSXL, 0);23 WREG8(MGA_CURPOSXL, 0);
24 WREG8(MGA_CURPOSXH, 0);24 WREG8(MGA_CURPOSXH, 0);
25 if (mdev->cursor.pixels_1->pin_count)25 if (mdev->cursor.pixels_1->pin_count)
26 mgag200_bo_unpin(mdev->cursor.pixels_1);26 drm_gem_vram_unpin_locked(mdev->cursor.pixels_1);
27 if (mdev->cursor.pixels_2->pin_count)27 if (mdev->cursor.pixels_2->pin_count)
28 mgag200_bo_unpin(mdev->cursor.pixels_2);28 drm_gem_vram_unpin_locked(mdev->cursor.pixels_2);
29}29}
30 30
31int mga_crtc_cursor_set(struct drm_crtc *crtc,31int mga_crtc_cursor_set(struct drm_crtc *crtc,
@@ -36,13 +36,14 @@ int mga_crtc_cursor_set(struct drm_crtc *crtc, · 4 unmodified lines
36{36{
37 struct drm_device *dev = crtc->dev;37 struct drm_device *dev = crtc->dev;
38 struct mga_device *mdev = (struct mga_device *)dev->dev_private;38 struct mga_device *mdev = (struct mga_device *)dev->dev_private;
39 struct mgag200_bo *pixels_1 = mdev->cursor.pixels_1;39 struct drm_gem_vram_object *pixels_1 = mdev->cursor.pixels_1;
40 struct mgag200_bo *pixels_2 = mdev->cursor.pixels_2;40 struct drm_gem_vram_object *pixels_2 = mdev->cursor.pixels_2;
41 struct mgag200_bo *pixels_current = mdev->cursor.pixels_current;41 struct drm_gem_vram_object *pixels_current = mdev->cursor.pixels_current;
42 struct mgag200_bo *pixels_prev = mdev->cursor.pixels_prev;42 struct drm_gem_vram_object *pixels_prev = mdev->cursor.pixels_prev;
43 struct drm_gem_object *obj;43 struct drm_gem_object *obj;
44 struct mgag200_bo *bo = NULL;44 struct drm_gem_vram_object *gbo = NULL;
45 int ret = 0;45 int ret = 0;
46 u8 *src, *dst;
46 unsigned int i, row, col;47 unsigned int i, row, col;
47 uint32_t colour_set[16];48 uint32_t colour_set[16];
48 uint32_t *next_space = &colour_set[0];49 uint32_t *next_space = &colour_set[0];
@@ -50,7 +51,7 @@ int mga_crtc_cursor_set(struct drm_crtc *crtc, · 1 unmodified line
50 uint32_t this_colour;51 uint32_t this_colour;
51 bool found = false;52 bool found = false;
52 int colour_count = 0;53 int colour_count = 0;
53 u64 gpu_addr;54 s64 gpu_addr;
54 u8 reg_index;55 u8 reg_index;
55 u8 this_row[48];56 u8 this_row[48];
56 57
@@ -79,54 +80,66 @@ int mga_crtc_cursor_set(struct drm_crtc *crtc, · 22 unmodified lines
79 if (!obj)80 if (!obj)
80 return -ENOENT;81 return -ENOENT;
81 82
82 ret = mgag200_bo_reserve(pixels_1, true);83 ret = drm_gem_vram_lock(pixels_1, true);
83 if (ret) {84 if (ret) {
84 WREG8(MGA_CURPOSXL, 0);85 WREG8(MGA_CURPOSXL, 0);
85 WREG8(MGA_CURPOSXH, 0);86 WREG8(MGA_CURPOSXH, 0);
86 goto out_unref;87 goto out_unref;
87 }88 }
88 ret = mgag200_bo_reserve(pixels_2, true);89 ret = drm_gem_vram_lock(pixels_2, true);
89 if (ret) {90 if (ret) {
90 WREG8(MGA_CURPOSXL, 0);91 WREG8(MGA_CURPOSXL, 0);
91 WREG8(MGA_CURPOSXH, 0);92 WREG8(MGA_CURPOSXH, 0);
92 mgag200_bo_unreserve(pixels_1);93 drm_gem_vram_unlock(pixels_1);
93 goto out_unreserve1;94 goto out_unlock1;
94 }95 }
95 96
96 /* Move cursor buffers into VRAM if they aren't already */97 /* Move cursor buffers into VRAM if they aren't already */
97 if (!pixels_1->pin_count) {98 if (!pixels_1->pin_count) {
98 ret = mgag200_bo_pin(pixels_1, TTM_PL_FLAG_VRAM,99 ret = drm_gem_vram_pin_locked(pixels_1,
99 &mdev->cursor.pixels_1_gpu_addr);100 DRM_GEM_VRAM_PL_FLAG_VRAM);
100 if (ret)101 if (ret)
101 goto out1;102 goto out1;
103 gpu_addr = drm_gem_vram_offset(pixels_1);
104 if (gpu_addr < 0) {
105 drm_gem_vram_unpin_locked(pixels_1);
106 goto out1;
107 }
108 mdev->cursor.pixels_1_gpu_addr = gpu_addr;
102 }109 }
103 if (!pixels_2->pin_count) {110 if (!pixels_2->pin_count) {
104 ret = mgag200_bo_pin(pixels_2, TTM_PL_FLAG_VRAM,111 ret = drm_gem_vram_pin_locked(pixels_2,
105 &mdev->cursor.pixels_2_gpu_addr);112 DRM_GEM_VRAM_PL_FLAG_VRAM);
106 if (ret) {113 if (ret) {
107 mgag200_bo_unpin(pixels_1);114 drm_gem_vram_unpin_locked(pixels_1);
108 goto out1;115 goto out1;
109 }116 }
117 gpu_addr = drm_gem_vram_offset(pixels_2);
118 if (gpu_addr < 0) {
119 drm_gem_vram_unpin_locked(pixels_1);
120 drm_gem_vram_unpin_locked(pixels_2);
121 goto out1;
122 }
123 mdev->cursor.pixels_2_gpu_addr = gpu_addr;
110 }124 }
111 125
112 bo = gem_to_mga_bo(obj);126 gbo = drm_gem_vram_of_gem(obj);
113 ret = mgag200_bo_reserve(bo, true);127 ret = drm_gem_vram_lock(gbo, true);
114 if (ret) {128 if (ret) {
115 dev_err(&dev->pdev->dev, "failed to reserve user bo\n");129 dev_err(&dev->pdev->dev, "failed to lock user bo\n");
116 goto out1;130 goto out1;
117 }131 }
118 if (!bo->kmap.virtual) {132 src = drm_gem_vram_kmap(gbo, true, NULL);
119 ret = ttm_bo_kmap(&bo->bo, 0, bo->bo.num_pages, &bo->kmap);133 if (IS_ERR(src)) {
120 if (ret) {134 ret = PTR_ERR(src);
121 dev_err(&dev->pdev->dev, "failed to kmap user buffer updates\n");135 dev_err(&dev->pdev->dev, "failed to kmap user buffer updates\n");
122 goto out2;136 goto out2;
123 }
124 }137 }
125 138
126 memset(&colour_set[0], 0, sizeof(uint32_t)*16);139 memset(&colour_set[0], 0, sizeof(uint32_t)*16);
127 /* width*height*4 = 16384 */140 /* width*height*4 = 16384 */
128 for (i = 0; i < 16384; i += 4) {141 for (i = 0; i < 16384; i += 4) {
129 this_colour = ioread32(bo->kmap.virtual + i);142 this_colour = ioread32(src + i);
130 /* No transparency */143 /* No transparency */
131 if (this_colour>>24 != 0xff &&144 if (this_colour>>24 != 0xff &&
132 this_colour>>24 != 0x0) {145 this_colour>>24 != 0x0) {
@@ -178,21 +191,18 @@ int mga_crtc_cursor_set(struct drm_crtc *crtc, · 45 unmodified lines
178 }191 }
179 192
180 /* Map up-coming buffer to write colour indices */193 /* Map up-coming buffer to write colour indices */
181 if (!pixels_prev->kmap.virtual) {194 dst = drm_gem_vram_kmap(pixels_prev, true, NULL);
182 ret = ttm_bo_kmap(&pixels_prev->bo, 0,195 if (IS_ERR(dst)) {
183 pixels_prev->bo.num_pages,196 ret = PTR_ERR(dst);
184 &pixels_prev->kmap);197 dev_err(&dev->pdev->dev, "failed to kmap cursor updates\n");
185 if (ret) {198 goto out3;
186 dev_err(&dev->pdev->dev, "failed to kmap cursor updates\n");
187 goto out3;
188 }
189 }199 }
190 200
191 /* now write colour indices into hardware cursor buffer */201 /* now write colour indices into hardware cursor buffer */
192 for (row = 0; row < 64; row++) {202 for (row = 0; row < 64; row++) {
193 memset(&this_row[0], 0, 48);203 memset(&this_row[0], 0, 48);
194 for (col = 0; col < 64; col++) {204 for (col = 0; col < 64; col++) {
195 this_colour = ioread32(bo->kmap.virtual + 4*(col + 64*row));205 this_colour = ioread32(src + 4*(col + 64*row));
196 /* write transparent pixels */206 /* write transparent pixels */
197 if (this_colour>>24 == 0x0) {207 if (this_colour>>24 == 0x0) {
198 this_row[47 - col/8] |= 0x80>>(col%8);208 this_row[47 - col/8] |= 0x80>>(col%8);
@@ -210,7 +220,7 @@ int mga_crtc_cursor_set(struct drm_crtc *crtc, · 11 unmodified lines
210 }220 }
211 }221 }
212 }222 }
213 memcpy_toio(pixels_prev->kmap.virtual + row*48, &this_row[0], 48);223 memcpy_toio(dst + row*48, &this_row[0], 48);
214 }224 }
215 225
216 /* Program gpu address of cursor buffer */226 /* Program gpu address of cursor buffer */
@@ -236,17 +246,17 @@ int mga_crtc_cursor_set(struct drm_crtc *crtc, · 19 unmodified lines
236 }246 }
237 ret = 0;247 ret = 0;
238 248
239 ttm_bo_kunmap(&pixels_prev->kmap);249 drm_gem_vram_kunmap(pixels_prev);
240 out3:250 out3:
241 ttm_bo_kunmap(&bo->kmap);251 drm_gem_vram_kunmap(gbo);
242 out2:252 out2:
243 mgag200_bo_unreserve(bo);253 drm_gem_vram_unlock(gbo);
244 out1:254 out1:
245 if (ret)255 if (ret)
246 mga_hide_cursor(mdev);256 mga_hide_cursor(mdev);
247 mgag200_bo_unreserve(pixels_1);257 drm_gem_vram_unlock(pixels_1);
248out_unreserve1:258out_unlock1:
249 mgag200_bo_unreserve(pixels_2);259 drm_gem_vram_unlock(pixels_2);
250out_unref:260out_unref:
251 drm_gem_object_put_unlocked(obj);261 drm_gem_object_put_unlocked(obj);
252 262
drivers/gpu/drm/mgag200/mgag200_drv.c+2−11
@@ -59,13 +59,7 @@ static void mga_pci_remove(struct pci_dev *pdev) · 58 unmodified lines
59 59
60static const struct file_operations mgag200_driver_fops = {60static const struct file_operations mgag200_driver_fops = {
61 .owner = THIS_MODULE,61 .owner = THIS_MODULE,
62 .open = drm_open,62 DRM_VRAM_MM_FILE_OPERATIONS
63 .release = drm_release,
64 .unlocked_ioctl = drm_ioctl,
65 .mmap = mgag200_mmap,
66 .poll = drm_poll,
67 .compat_ioctl = drm_compat_ioctl,
68 .read = drm_read,
69};63};
70 64
71static struct drm_driver driver = {65static struct drm_driver driver = {
@@ -79,10 +73,7 @@ static struct drm_driver driver = { · 7 unmodified lines
79 .major = DRIVER_MAJOR,73 .major = DRIVER_MAJOR,
80 .minor = DRIVER_MINOR,74 .minor = DRIVER_MINOR,
81 .patchlevel = DRIVER_PATCHLEVEL,75 .patchlevel = DRIVER_PATCHLEVEL,
82 76 DRM_GEM_VRAM_DRIVER
83 .gem_free_object_unlocked = mgag200_gem_free_object,
84 .dumb_create = mgag200_dumb_create,
85 .dumb_map_offset = mgag200_dumb_mmap_offset,
86};77};
87 78
88static struct pci_driver mgag200_pci_driver = {79static struct pci_driver mgag200_pci_driver = {
drivers/gpu/drm/mgag200/mgag200_drv.h+10−64
@@ -1,6 +1,6 @@
1/*1/*
2 * Copyright 2010 Matt Turner.2 * Copyright 2010 Matt Turner.
3 * Copyright 2012 Red Hat 3 * Copyright 2012 Red Hat
4 *4 *
5 * This file is subject to the terms and conditions of the GNU General5 * This file is subject to the terms and conditions of the GNU General
6 * Public License version 2. See the file COPYING in the main6 * Public License version 2. See the file COPYING in the main
@@ -17,13 +17,11 @@ · 10 unmodified lines
17 17
18#include <drm/drm_encoder.h>18#include <drm/drm_encoder.h>
19#include <drm/drm_fb_helper.h>19#include <drm/drm_fb_helper.h>
20#include <drm/ttm/ttm_bo_api.h>
21#include <drm/ttm/ttm_bo_driver.h>
22#include <drm/ttm/ttm_placement.h>
23#include <drm/ttm/ttm_memory.h>
24#include <drm/ttm/ttm_module.h>
25 20
26#include <drm/drm_gem.h>21#include <drm/drm_gem.h>
22#include <drm/drm_gem_vram_helper.h>
23
24#include <drm/drm_vram_mm_helper.h>
27 25
28#include <linux/i2c.h>26#include <linux/i2c.h>
29#include <linux/i2c-algo-bit.h>27#include <linux/i2c-algo-bit.h>
@@ -117,7 +115,6 @@ struct mga_fbdev { · 87 unmodified lines
117 struct mga_framebuffer mfb;115 struct mga_framebuffer mfb;
118 void *sysram;116 void *sysram;
119 int size;117 int size;
120 struct ttm_bo_kmap_obj mapping;
121 int x1, y1, x2, y2; /* dirty rect */118 int x1, y1, x2, y2; /* dirty rect */
122 spinlock_t dirty_lock;119 spinlock_t dirty_lock;
123};120};
@@ -159,13 +156,13 @@ struct mga_cursor { · 35 unmodified lines
159 If either of these is NULL, then don't do hardware cursors, and156 If either of these is NULL, then don't do hardware cursors, and
160 fall back to software.157 fall back to software.
161 */158 */
162 struct mgag200_bo *pixels_1;159 struct drm_gem_vram_object *pixels_1;
163 struct mgag200_bo *pixels_2;160 struct drm_gem_vram_object *pixels_2;
164 u64 pixels_1_gpu_addr, pixels_2_gpu_addr;161 u64 pixels_1_gpu_addr, pixels_2_gpu_addr;
165 /* The currently displayed icon, this points to one of pixels_1, or pixels_2 */162 /* The currently displayed icon, this points to one of pixels_1, or pixels_2 */
166 struct mgag200_bo *pixels_current;163 struct drm_gem_vram_object *pixels_current;
167 /* The previously displayed icon */164 /* The previously displayed icon */
168 struct mgag200_bo *pixels_prev;165 struct drm_gem_vram_object *pixels_prev;
169};166};
170 167
171struct mga_mc {168struct mga_mc {
@@ -211,31 +208,10 @@ struct mga_device { · 39 unmodified lines
211 208
212 int fb_mtrr;209 int fb_mtrr;
213 210
214 struct {
215 struct ttm_bo_device bdev;
216 } ttm;
217
218 /* SE model number stored in reg 0x1e24 */211 /* SE model number stored in reg 0x1e24 */
219 u32 unique_rev_id;212 u32 unique_rev_id;
220};213};
221 214
222
223struct mgag200_bo {
224 struct ttm_buffer_object bo;
225 struct ttm_placement placement;
226 struct ttm_bo_kmap_obj kmap;
227 struct drm_gem_object gem;
228 struct ttm_place placements[3];
229 int pin_count;
230};
231#define gem_to_mga_bo(gobj) container_of((gobj), struct mgag200_bo, gem)
232
233static inline struct mgag200_bo *
234mgag200_bo(struct ttm_buffer_object *bo)
235{
236 return container_of(bo, struct mgag200_bo, bo);
237}
238
239 /* mgag200_mode.c */215 /* mgag200_mode.c */
240int mgag200_modeset_init(struct mga_device *mdev);216int mgag200_modeset_init(struct mga_device *mdev);
241void mgag200_modeset_fini(struct mga_device *mdev);217void mgag200_modeset_fini(struct mga_device *mdev);
@@ -259,45 +235,15 @@ int mgag200_gem_create(struct drm_device *dev, · 17 unmodified lines
259int mgag200_dumb_create(struct drm_file *file,235int mgag200_dumb_create(struct drm_file *file,
260 struct drm_device *dev,236 struct drm_device *dev,
261 struct drm_mode_create_dumb *args);237 struct drm_mode_create_dumb *args);
262void mgag200_gem_free_object(struct drm_gem_object *obj);238
263int
264mgag200_dumb_mmap_offset(struct drm_file *file,
265 struct drm_device *dev,
266 uint32_t handle,
267 uint64_t *offset);
268 /* mgag200_i2c.c */239 /* mgag200_i2c.c */
269struct mga_i2c_chan *mgag200_i2c_create(struct drm_device *dev);240struct mga_i2c_chan *mgag200_i2c_create(struct drm_device *dev);
270void mgag200_i2c_destroy(struct mga_i2c_chan *i2c);241void mgag200_i2c_destroy(struct mga_i2c_chan *i2c);
271 242
272void mgag200_ttm_placement(struct mgag200_bo *bo, int domain);
273
274static inline int mgag200_bo_reserve(struct mgag200_bo *bo, bool no_wait)
275{
276 int ret;
277
278 ret = ttm_bo_reserve(&bo->bo, true, no_wait, NULL);
279 if (ret) {
280 if (ret != -ERESTARTSYS && ret != -EBUSY)
281 DRM_ERROR("reserve failed %p\n", bo);
282 return ret;
283 }
284 return 0;
285}
286
287static inline void mgag200_bo_unreserve(struct mgag200_bo *bo)
288{
289 ttm_bo_unreserve(&bo->bo);
290}
291
292int mgag200_bo_create(struct drm_device *dev, int size, int align,
293 uint32_t flags, struct mgag200_bo **pastbo);
294int mgag200_mm_init(struct mga_device *mdev);243int mgag200_mm_init(struct mga_device *mdev);
295void mgag200_mm_fini(struct mga_device *mdev);244void mgag200_mm_fini(struct mga_device *mdev);
296int mgag200_mmap(struct file *filp, struct vm_area_struct *vma);245int mgag200_mmap(struct file *filp, struct vm_area_struct *vma);
297int mgag200_bo_pin(struct mgag200_bo *bo, u32 pl_flag, u64 *gpu_addr);246
298int mgag200_bo_unpin(struct mgag200_bo *bo);
299int mgag200_bo_push_sysram(struct mgag200_bo *bo);
300 /* mgag200_cursor.c */
301int mga_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv,247int mga_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv,
302 uint32_t handle, uint32_t width, uint32_t height);248 uint32_t handle, uint32_t width, uint32_t height);
303int mga_crtc_cursor_move(struct drm_crtc *crtc, int x, int y);249int mga_crtc_cursor_move(struct drm_crtc *crtc, int x, int y);
drivers/gpu/drm/mgag200/mgag200_fb.c+24−17
@@ -23,25 +23,25 @@ static void mga_dirty_update(struct mga_fbdev *mfbdev, · 22 unmodified lines
23{23{
24 int i;24 int i;
25 struct drm_gem_object *obj;25 struct drm_gem_object *obj;
26 struct mgag200_bo *bo;26 struct drm_gem_vram_object *gbo;
27 int src_offset, dst_offset;27 int src_offset, dst_offset;
28 int bpp = mfbdev->mfb.base.format->cpp[0];28 int bpp = mfbdev->mfb.base.format->cpp[0];
29 int ret = -EBUSY;29 int ret = -EBUSY;
30 u8 *dst;
30 bool unmap = false;31 bool unmap = false;
31 bool store_for_later = false;32 bool store_for_later = false;
32 int x2, y2;33 int x2, y2;
33 unsigned long flags;34 unsigned long flags;
34 35
35 obj = mfbdev->mfb.obj;36 obj = mfbdev->mfb.obj;
36 bo = gem_to_mga_bo(obj);37 gbo = drm_gem_vram_of_gem(obj);
37 38
38 /*39 /* Try to lock the BO. If we fail with -EBUSY then
39 * try and reserve the BO, if we fail with busy40 * the BO is being moved and we should store up the
40 * then the BO is being moved and we should41 * damage until later.
41 * store up the damage until later.
42 */42 */
43 if (drm_can_sleep())43 if (drm_can_sleep())
44 ret = mgag200_bo_reserve(bo, true);44 ret = drm_gem_vram_lock(gbo, true);
45 if (ret) {45 if (ret) {
46 if (ret != -EBUSY)46 if (ret != -EBUSY)
47 return;47 return;
@@ -75,25 +75,32 @@ static void mga_dirty_update(struct mga_fbdev *mfbdev, · 27 unmodified lines
75 mfbdev->x2 = mfbdev->y2 = 0;75 mfbdev->x2 = mfbdev->y2 = 0;
76 spin_unlock_irqrestore(&mfbdev->dirty_lock, flags);76 spin_unlock_irqrestore(&mfbdev->dirty_lock, flags);
77 77
78 if (!bo->kmap.virtual) {78 dst = drm_gem_vram_kmap(gbo, false, NULL);
79 ret = ttm_bo_kmap(&bo->bo, 0, bo->bo.num_pages, &bo->kmap);79 if (IS_ERR(dst)) {
80 if (ret) {80 DRM_ERROR("failed to kmap fb updates\n");
81 goto out;
82 } else if (!dst) {
83 dst = drm_gem_vram_kmap(gbo, true, NULL);
84 if (IS_ERR(dst)) {
81 DRM_ERROR("failed to kmap fb updates\n");85 DRM_ERROR("failed to kmap fb updates\n");
82 mgag200_bo_unreserve(bo);86 goto out;
83 return;
84 }87 }
85 unmap = true;88 unmap = true;
86 }89 }
90
87 for (i = y; i <= y2; i++) {91 for (i = y; i <= y2; i++) {
88 /* assume equal stride for now */92 /* assume equal stride for now */
89 src_offset = dst_offset = i * mfbdev->mfb.base.pitches[0] + (x * bpp);93 src_offset = dst_offset =
90 memcpy_toio(bo->kmap.virtual + src_offset, mfbdev->sysram + src_offset, (x2 - x + 1) * bpp);94 i * mfbdev->mfb.base.pitches[0] + (x * bpp);
91 95 memcpy_toio(dst + dst_offset, mfbdev->sysram + src_offset,
96 (x2 - x + 1) * bpp);
92 }97 }
98
93 if (unmap)99 if (unmap)
94 ttm_bo_kunmap(&bo->kmap);100 drm_gem_vram_kunmap(gbo);
95 101
96 mgag200_bo_unreserve(bo);102out:
103 drm_gem_vram_unlock(gbo);
97}104}
98 105
99static void mga_fillrect(struct fb_info *info,106static void mga_fillrect(struct fb_info *info,
drivers/gpu/drm/mgag200/mgag200_main.c+12−75
@@ -230,11 +230,13 @@ int mgag200_driver_load(struct drm_device *dev, unsigned long flags) · 229 unmodified lines
230 }230 }
231 231
232 /* Make small buffers to store a hardware cursor (double buffered icon updates) */232 /* Make small buffers to store a hardware cursor (double buffered icon updates) */
233 mgag200_bo_create(dev, roundup(48*64, PAGE_SIZE), 0, 0,233 mdev->cursor.pixels_1 = drm_gem_vram_create(dev, &dev->vram_mm->bdev,
234 &mdev->cursor.pixels_1);234 roundup(48*64, PAGE_SIZE),
235 mgag200_bo_create(dev, roundup(48*64, PAGE_SIZE), 0, 0,235 0, 0);
236 &mdev->cursor.pixels_2);236 mdev->cursor.pixels_2 = drm_gem_vram_create(dev, &dev->vram_mm->bdev,
237 if (!mdev->cursor.pixels_2 || !mdev->cursor.pixels_1) {237 roundup(48*64, PAGE_SIZE),
238 0, 0);
239 if (IS_ERR(mdev->cursor.pixels_2) || IS_ERR(mdev->cursor.pixels_1)) {
238 mdev->cursor.pixels_1 = NULL;240 mdev->cursor.pixels_1 = NULL;
239 mdev->cursor.pixels_2 = NULL;241 mdev->cursor.pixels_2 = NULL;
240 dev_warn(&dev->pdev->dev,242 dev_warn(&dev->pdev->dev,
@@ -272,7 +274,7 @@ int mgag200_gem_create(struct drm_device *dev, · 31 unmodified lines
272 u32 size, bool iskernel,274 u32 size, bool iskernel,
273 struct drm_gem_object **obj)275 struct drm_gem_object **obj)
274{276{
275 struct mgag200_bo *astbo;277 struct drm_gem_vram_object *gbo;
276 int ret;278 int ret;
277 279
278 *obj = NULL;280 *obj = NULL;
@@ -281,78 +283,13 @@ int mgag200_gem_create(struct drm_device *dev, · 2 unmodified lines
281 if (size == 0)283 if (size == 0)
282 return -EINVAL;284 return -EINVAL;
283 285
284 ret = mgag200_bo_create(dev, size, 0, 0, &astbo);286 gbo = drm_gem_vram_create(dev, &dev->vram_mm->bdev, size, 0, false);
285 if (ret) {287 if (IS_ERR(gbo)) {
288 ret = PTR_ERR(gbo);
286 if (ret != -ERESTARTSYS)289 if (ret != -ERESTARTSYS)
287 DRM_ERROR("failed to allocate GEM object\n");290 DRM_ERROR("failed to allocate GEM object\n");
288 return ret;291 return ret;
289 }292 }
290 *obj = &astbo->gem;293 *obj = &gbo->gem;
291 return 0;
292}
293
294int mgag200_dumb_create(struct drm_file *file,
295 struct drm_device *dev,
296 struct drm_mode_create_dumb *args)
297{
298 int ret;
299 struct drm_gem_object *gobj;
300 u32 handle;
301
302 args->pitch = args->width * ((args->bpp + 7) / 8);
303 args->size = args->pitch * args->height;
304
305 ret = mgag200_gem_create(dev, args->size, false,
306 &gobj);
307 if (ret)
308 return ret;
309
310 ret = drm_gem_handle_create(file, gobj, &handle);
311 drm_gem_object_put_unlocked(gobj);
312 if (ret)
313 return ret;
314
315 args->handle = handle;
316 return 0;
317}
318
319static void mgag200_bo_unref(struct mgag200_bo **bo)
320{
321 if ((*bo) == NULL)
322 return;
323 ttm_bo_put(&((*bo)->bo));
324 *bo = NULL;
325}
326
327void mgag200_gem_free_object(struct drm_gem_object *obj)
328{
329 struct mgag200_bo *mgag200_bo = gem_to_mga_bo(obj);
330
331 mgag200_bo_unref(&mgag200_bo);
332}
333
334
335static inline u64 mgag200_bo_mmap_offset(struct mgag200_bo *bo)
336{
337 return drm_vma_node_offset_addr(&bo->bo.vma_node);
338}
339
340int
341mgag200_dumb_mmap_offset(struct drm_file *file,
342 struct drm_device *dev,
343 uint32_t handle,
344 uint64_t *offset)
345{
346 struct drm_gem_object *obj;
347 struct mgag200_bo *bo;
348
349 obj = drm_gem_object_lookup(file, handle);
350 if (obj == NULL)
351 return -ENOENT;
352
353 bo = gem_to_mga_bo(obj);
354 *offset = mgag200_bo_mmap_offset(bo);
355
356 drm_gem_object_put_unlocked(obj);
357 return 0;294 return 0;
358}295}
drivers/gpu/drm/mgag200/mgag200_mode.c+30−29
@@ -858,8 +858,6 @@ static void mga_set_start_address(struct drm_crtc *crtc, unsigned offset) · 857 unmodified lines
858 WREG_ECRT(0x0, ((u8)(addr >> 16) & 0xf) | crtcext0);858 WREG_ECRT(0x0, ((u8)(addr >> 16) & 0xf) | crtcext0);
859}859}
860 860
861
862/* ast is different - we will force move buffers out of VRAM */
863static int mga_crtc_do_set_base(struct drm_crtc *crtc,861static int mga_crtc_do_set_base(struct drm_crtc *crtc,
864 struct drm_framebuffer *fb,862 struct drm_framebuffer *fb,
865 int x, int y, int atomic)863 int x, int y, int atomic)
@@ -867,48 +865,51 @@ static int mga_crtc_do_set_base(struct drm_crtc *crtc, · 1 unmodified line
867 struct mga_device *mdev = crtc->dev->dev_private;865 struct mga_device *mdev = crtc->dev->dev_private;
868 struct drm_gem_object *obj;866 struct drm_gem_object *obj;
869 struct mga_framebuffer *mga_fb;867 struct mga_framebuffer *mga_fb;
870 struct mgag200_bo *bo;868 struct drm_gem_vram_object *gbo;
871 int ret;869 int ret;
872 u64 gpu_addr;870 s64 gpu_addr;
871 void *base;
873 872
874 /* push the previous fb to system ram */
875 if (!atomic && fb) {873 if (!atomic && fb) {
876 mga_fb = to_mga_framebuffer(fb);874 mga_fb = to_mga_framebuffer(fb);
877 obj = mga_fb->obj;875 obj = mga_fb->obj;
878 bo = gem_to_mga_bo(obj);876 gbo = drm_gem_vram_of_gem(obj);
879 ret = mgag200_bo_reserve(bo, false);877
880 if (ret)878 /* unmap if console */
881 return ret;879 if (&mdev->mfbdev->mfb == mga_fb)
882 mgag200_bo_push_sysram(bo);880 drm_gem_vram_kunmap(gbo);
883 mgag200_bo_unreserve(bo);881 drm_gem_vram_unpin(gbo);
884 }882 }
885 883
886 mga_fb = to_mga_framebuffer(crtc->primary->fb);884 mga_fb = to_mga_framebuffer(crtc->primary->fb);
887 obj = mga_fb->obj;885 obj = mga_fb->obj;
888 bo = gem_to_mga_bo(obj);886 gbo = drm_gem_vram_of_gem(obj);
889 887
890 ret = mgag200_bo_reserve(bo, false);888 ret = drm_gem_vram_pin(gbo, DRM_GEM_VRAM_PL_FLAG_VRAM);
891 if (ret)889 if (ret)
892 return ret;890 return ret;
893 891 gpu_addr = drm_gem_vram_offset(gbo);
894 ret = mgag200_bo_pin(bo, TTM_PL_FLAG_VRAM, &gpu_addr);892 if (gpu_addr < 0) {
895 if (ret) {893 ret = (int)gpu_addr;
896 mgag200_bo_unreserve(bo);894 goto err_drm_gem_vram_unpin;
897 return ret;
898 }895 }
899 896
900 if (&mdev->mfbdev->mfb == mga_fb) {897 if (&mdev->mfbdev->mfb == mga_fb) {
901 /* if pushing console in kmap it */898 /* if pushing console in kmap it */
902 ret = ttm_bo_kmap(&bo->bo, 0, bo->bo.num_pages, &bo->kmap);899 base = drm_gem_vram_kmap(gbo, true, NULL);
903 if (ret)900 if (IS_ERR(base)) {
901 ret = PTR_ERR(base);
904 DRM_ERROR("failed to kmap fbcon\n");902 DRM_ERROR("failed to kmap fbcon\n");
905 903 }
906 }904 }
907 mgag200_bo_unreserve(bo);
908 905
909 mga_set_start_address(crtc, (u32)gpu_addr);906 mga_set_start_address(crtc, (u32)gpu_addr);
910 907
911 return 0;908 return 0;
909
910err_drm_gem_vram_unpin:
911 drm_gem_vram_unpin(gbo);
912 return ret;
912}913}
913 914
914static int mga_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,915static int mga_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
@@ -1422,18 +1423,18 @@ static void mga_crtc_destroy(struct drm_crtc *crtc) · 507 unmodified lines
1422 1423
1423static void mga_crtc_disable(struct drm_crtc *crtc)1424static void mga_crtc_disable(struct drm_crtc *crtc)
1424{1425{
1425 int ret;
1426 DRM_DEBUG_KMS("\n");1426 DRM_DEBUG_KMS("\n");
1427 mga_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);1427 mga_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
1428 if (crtc->primary->fb) {1428 if (crtc->primary->fb) {
1429 struct mga_device *mdev = crtc->dev->dev_private;
1429 struct mga_framebuffer *mga_fb = to_mga_framebuffer(crtc->primary->fb);1430 struct mga_framebuffer *mga_fb = to_mga_framebuffer(crtc->primary->fb);
1430 struct drm_gem_object *obj = mga_fb->obj;1431 struct drm_gem_object *obj = mga_fb->obj;
1431 struct mgag200_bo *bo = gem_to_mga_bo(obj);1432 struct drm_gem_vram_object *gbo = drm_gem_vram_of_gem(obj);
1432 ret = mgag200_bo_reserve(bo, false);1433
1433 if (ret)1434 /* unmap if console */
1434 return;1435 if (&mdev->mfbdev->mfb == mga_fb)
1435 mgag200_bo_push_sysram(bo);1436 drm_gem_vram_kunmap(gbo);
1436 mgag200_bo_unreserve(bo);1437 drm_gem_vram_unpin(gbo);
1437 }1438 }
1438 crtc->primary->fb = NULL;1439 crtc->primary->fb = NULL;
1439}1440}
drivers/gpu/drm/mgag200/mgag200_ttm.c+8−293
@@ -26,167 +26,21 @@ · 25 unmodified lines
26 * Authors: Dave Airlie <airlied@redhat.com>26 * Authors: Dave Airlie <airlied@redhat.com>
27 */27 */
28#include <drm/drmP.h>28#include <drm/drmP.h>
29#include <drm/ttm/ttm_page_alloc.h>
30 29
31#include "mgag200_drv.h"30#include "mgag200_drv.h"
32 31
33static inline struct mga_device *
34mgag200_bdev(struct ttm_bo_device *bd)
35{
36 return container_of(bd, struct mga_device, ttm.bdev);
37}
38
39static void mgag200_bo_ttm_destroy(struct ttm_buffer_object *tbo)
40{
41 struct mgag200_bo *bo;
42
43 bo = container_of(tbo, struct mgag200_bo, bo);
44
45 drm_gem_object_release(&bo->gem);
46 kfree(bo);
47}
48
49static bool mgag200_ttm_bo_is_mgag200_bo(struct ttm_buffer_object *bo)
50{
51 if (bo->destroy == &mgag200_bo_ttm_destroy)
52 return true;
53 return false;
54}
55
56static int
57mgag200_bo_init_mem_type(struct ttm_bo_device *bdev, uint32_t type,
58 struct ttm_mem_type_manager *man)
59{
60 switch (type) {
61 case TTM_PL_SYSTEM:
62 man->flags = TTM_MEMTYPE_FLAG_MAPPABLE;
63 man->available_caching = TTM_PL_MASK_CACHING;
64 man->default_caching = TTM_PL_FLAG_CACHED;
65 break;
66 case TTM_PL_VRAM:
67 man->func = &ttm_bo_manager_func;
68 man->flags = TTM_MEMTYPE_FLAG_FIXED |
69 TTM_MEMTYPE_FLAG_MAPPABLE;
70 man->available_caching = TTM_PL_FLAG_UNCACHED |
71 TTM_PL_FLAG_WC;
72 man->default_caching = TTM_PL_FLAG_WC;
73 break;
74 default:
75 DRM_ERROR("Unsupported memory type %u\n", (unsigned)type);
76 return -EINVAL;
77 }
78 return 0;
79}
80
81static void
82mgag200_bo_evict_flags(struct ttm_buffer_object *bo, struct ttm_placement *pl)
83{
84 struct mgag200_bo *mgabo = mgag200_bo(bo);
85
86 if (!mgag200_ttm_bo_is_mgag200_bo(bo))
87 return;
88
89 mgag200_ttm_placement(mgabo, TTM_PL_FLAG_SYSTEM);
90 *pl = mgabo->placement;
91}
92
93static int mgag200_bo_verify_access(struct ttm_buffer_object *bo, struct file *filp)
94{
95 struct mgag200_bo *mgabo = mgag200_bo(bo);
96
97 return drm_vma_node_verify_access(&mgabo->gem.vma_node,
98 filp->private_data);
99}
100
101static int mgag200_ttm_io_mem_reserve(struct ttm_bo_device *bdev,
102 struct ttm_mem_reg *mem)
103{
104 struct ttm_mem_type_manager *man = &bdev->man[mem->mem_type];
105 struct mga_device *mdev = mgag200_bdev(bdev);
106
107 mem->bus.addr = NULL;
108 mem->bus.offset = 0;
109 mem->bus.size = mem->num_pages << PAGE_SHIFT;
110 mem->bus.base = 0;
111 mem->bus.is_iomem = false;
112 if (!(man->flags & TTM_MEMTYPE_FLAG_MAPPABLE))
113 return -EINVAL;
114 switch (mem->mem_type) {
115 case TTM_PL_SYSTEM:
116 /* system memory */
117 return 0;
118 case TTM_PL_VRAM:
119 mem->bus.offset = mem->start << PAGE_SHIFT;
120 mem->bus.base = pci_resource_start(mdev->dev->pdev, 0);
121 mem->bus.is_iomem = true;
122 break;
123 default:
124 return -EINVAL;
125 break;
126 }
127 return 0;
128}
129
130static void mgag200_ttm_io_mem_free(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem)
131{
132}
133
134static void mgag200_ttm_backend_destroy(struct ttm_tt *tt)
135{
136 ttm_tt_fini(tt);
137 kfree(tt);
138}
139
140static struct ttm_backend_func mgag200_tt_backend_func = {
141 .destroy = &mgag200_ttm_backend_destroy,
142};
143
144
145static struct ttm_tt *mgag200_ttm_tt_create(struct ttm_buffer_object *bo,
146 uint32_t page_flags)
147{
148 struct ttm_tt *tt;
149
150 tt = kzalloc(sizeof(struct ttm_tt), GFP_KERNEL);
151 if (tt == NULL)
152 return NULL;
153 tt->func = &mgag200_tt_backend_func;
154 if (ttm_tt_init(tt, bo, page_flags)) {
155 kfree(tt);
156 return NULL;
157 }
158 return tt;
159}
160
161struct ttm_bo_driver mgag200_bo_driver = {
162 .ttm_tt_create = mgag200_ttm_tt_create,
163 .init_mem_type = mgag200_bo_init_mem_type,
164 .eviction_valuable = ttm_bo_eviction_valuable,
165 .evict_flags = mgag200_bo_evict_flags,
166 .move = NULL,
167 .verify_access = mgag200_bo_verify_access,
168 .io_mem_reserve = &mgag200_ttm_io_mem_reserve,
169 .io_mem_free = &mgag200_ttm_io_mem_free,
170};
171
172int mgag200_mm_init(struct mga_device *mdev)32int mgag200_mm_init(struct mga_device *mdev)
173{33{
34 struct drm_vram_mm *vmm;
174 int ret;35 int ret;
175 struct drm_device *dev = mdev->dev;36 struct drm_device *dev = mdev->dev;
176 struct ttm_bo_device *bdev = &mdev->ttm.bdev;
177
178 ret = ttm_bo_device_init(&mdev->ttm.bdev,
179 &mgag200_bo_driver,
180 dev->anon_inode->i_mapping,
181 true);
182 if (ret) {
183 DRM_ERROR("Error initialising bo driver; %d\n", ret);
184 return ret;
185 }
186 37
187 ret = ttm_bo_init_mm(bdev, TTM_PL_VRAM, mdev->mc.vram_size >> PAGE_SHIFT);38 vmm = drm_vram_helper_alloc_mm(dev, pci_resource_start(dev->pdev, 0),
188 if (ret) {39 mdev->mc.vram_size,
189 DRM_ERROR("Failed ttm VRAM init: %d\n", ret);40 &drm_gem_vram_mm_funcs);
41 if (IS_ERR(vmm)) {
42 ret = PTR_ERR(vmm);
43 DRM_ERROR("Error initializing VRAM MM; %d\n", ret);
190 return ret;44 return ret;
191 }45 }
192 46
@@ -203,149 +57,10 @@ void mgag200_mm_fini(struct mga_device *mdev) · 10 unmodified lines
203{57{
204 struct drm_device *dev = mdev->dev;58 struct drm_device *dev = mdev->dev;
205 59
206 ttm_bo_device_release(&mdev->ttm.bdev);60 drm_vram_helper_release_mm(dev);
207 61
208 arch_io_free_memtype_wc(pci_resource_start(dev->pdev, 0),62 arch_io_free_memtype_wc(pci_resource_start(dev->pdev, 0),
209 pci_resource_len(dev->pdev, 0));63 pci_resource_len(dev->pdev, 0));
210 arch_phys_wc_del(mdev->fb_mtrr);64 arch_phys_wc_del(mdev->fb_mtrr);
211 mdev->fb_mtrr = 0;65 mdev->fb_mtrr = 0;
212}66}
213
214void mgag200_ttm_placement(struct mgag200_bo *bo, int domain)
215{
216 u32 c = 0;
217 unsigned i;
218
219 bo->placement.placement = bo->placements;
220 bo->placement.busy_placement = bo->placements;
221 if (domain & TTM_PL_FLAG_VRAM)
222 bo->placements[c++].flags = TTM_PL_FLAG_WC | TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_VRAM;
223 if (domain & TTM_PL_FLAG_SYSTEM)
224 bo->placements[c++].flags = TTM_PL_MASK_CACHING | TTM_PL_FLAG_SYSTEM;
225 if (!c)
226 bo->placements[c++].flags = TTM_PL_MASK_CACHING | TTM_PL_FLAG_SYSTEM;
227 bo->placement.num_placement = c;
228 bo->placement.num_busy_placement = c;
229 for (i = 0; i < c; ++i) {
230 bo->placements[i].fpfn = 0;
231 bo->placements[i].lpfn = 0;
232 }
233}
234
235int mgag200_bo_create(struct drm_device *dev, int size, int align,
236 uint32_t flags, struct mgag200_bo **pmgabo)
237{
238 struct mga_device *mdev = dev->dev_private;
239 struct mgag200_bo *mgabo;
240 size_t acc_size;
241 int ret;
242
243 mgabo = kzalloc(sizeof(struct mgag200_bo), GFP_KERNEL);
244 if (!mgabo)
245 return -ENOMEM;
246
247 ret = drm_gem_object_init(dev, &mgabo->gem, size);
248 if (ret) {
249 kfree(mgabo);
250 return ret;
251 }
252
253 mgabo->bo.bdev = &mdev->ttm.bdev;
254
255 mgag200_ttm_placement(mgabo, TTM_PL_FLAG_VRAM | TTM_PL_FLAG_SYSTEM);
256
257 acc_size = ttm_bo_dma_acc_size(&mdev->ttm.bdev, size,
258 sizeof(struct mgag200_bo));
259
260 ret = ttm_bo_init(&mdev->ttm.bdev, &mgabo->bo, size,
261 ttm_bo_type_device, &mgabo->placement,
262 align >> PAGE_SHIFT, false, acc_size,
263 NULL, NULL, mgag200_bo_ttm_destroy);
264 if (ret)
265 return ret;
266
267 *pmgabo = mgabo;
268 return 0;
269}
270
271static inline u64 mgag200_bo_gpu_offset(struct mgag200_bo *bo)
272{
273 return bo->bo.offset;
274}
275
276int mgag200_bo_pin(struct mgag200_bo *bo, u32 pl_flag, u64 *gpu_addr)
277{
278 struct ttm_operation_ctx ctx = { false, false };
279 int i, ret;
280
281 if (bo->pin_count) {
282 bo->pin_count++;
283 if (gpu_addr)
284 *gpu_addr = mgag200_bo_gpu_offset(bo);
285 return 0;
286 }
287
288 mgag200_ttm_placement(bo, pl_flag);
289 for (i = 0; i < bo->placement.num_placement; i++)
290 bo->placements[i].flags |= TTM_PL_FLAG_NO_EVICT;
291 ret = ttm_bo_validate(&bo->bo, &bo->placement, &ctx);
292 if (ret)
293 return ret;
294
295 bo->pin_count = 1;
296 if (gpu_addr)
297 *gpu_addr = mgag200_bo_gpu_offset(bo);
298 return 0;
299}
300
301int mgag200_bo_unpin(struct mgag200_bo *bo)
302{
303 struct ttm_operation_ctx ctx = { false, false };
304 int i;
305 if (!bo->pin_count) {
306 DRM_ERROR("unpin bad %p\n", bo);
307 return 0;
308 }
309 bo->pin_count--;
310 if (bo->pin_count)
311 return 0;
312
313 for (i = 0; i < bo->placement.num_placement ; i++)
314 bo->placements[i].flags &= ~TTM_PL_FLAG_NO_EVICT;
315 return ttm_bo_validate(&bo->bo, &bo->placement, &ctx);
316}
317
318int mgag200_bo_push_sysram(struct mgag200_bo *bo)
319{
320 struct ttm_operation_ctx ctx = { false, false };
321 int i, ret;
322 if (!bo->pin_count) {
323 DRM_ERROR("unpin bad %p\n", bo);
324 return 0;
325 }
326 bo->pin_count--;
327 if (bo->pin_count)
328 return 0;
329
330 if (bo->kmap.virtual)
331 ttm_bo_kunmap(&bo->kmap);
332
333 mgag200_ttm_placement(bo, TTM_PL_FLAG_SYSTEM);
334 for (i = 0; i < bo->placement.num_placement ; i++)
335 bo->placements[i].flags |= TTM_PL_FLAG_NO_EVICT;
336
337 ret = ttm_bo_validate(&bo->bo, &bo->placement, &ctx);
338 if (ret) {
339 DRM_ERROR("pushing to VRAM failed\n");
340 return ret;
341 }
342 return 0;
343}
344
345int mgag200_mmap(struct file *filp, struct vm_area_struct *vma)
346{
347 struct drm_file *file_priv = filp->private_data;
348 struct mga_device *mdev = file_priv->minor->dev->dev_private;
349
350 return ttm_bo_mmap(filp, vma, &mdev->ttm.bdev);
351}
drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c+2−4
@@ -694,14 +694,12 @@ end: · 693 unmodified lines
694 694
695static void dpu_crtc_reset(struct drm_crtc *crtc)695static void dpu_crtc_reset(struct drm_crtc *crtc)
696{696{
697 struct dpu_crtc_state *cstate;697 struct dpu_crtc_state *cstate = kzalloc(sizeof(*cstate), GFP_KERNEL);
698 698
699 if (crtc->state)699 if (crtc->state)
700 dpu_crtc_destroy_state(crtc, crtc->state);700 dpu_crtc_destroy_state(crtc, crtc->state);
701 701
702 crtc->state = kzalloc(sizeof(*cstate), GFP_KERNEL);702 __drm_atomic_helper_crtc_reset(crtc, &cstate->base);
703 if (crtc->state)
704 crtc->state->crtc = crtc;
705}703}
706 704
707/**705/**
drivers/gpu/drm/msm/disp/dpu1/dpu_formats.c+6−3
@@ -1040,10 +1040,11 @@ int dpu_format_check_modified_format( · 1039 unmodified lines
1040 const struct drm_mode_fb_cmd2 *cmd,1040 const struct drm_mode_fb_cmd2 *cmd,
1041 struct drm_gem_object **bos)1041 struct drm_gem_object **bos)
1042{1042{
1043 int ret, i, num_base_fmt_planes;1043 const struct drm_format_info *info;
1044 const struct dpu_format *fmt;1044 const struct dpu_format *fmt;
1045 struct dpu_hw_fmt_layout layout;1045 struct dpu_hw_fmt_layout layout;
1046 uint32_t bos_total_size = 0;1046 uint32_t bos_total_size = 0;
1047 int ret, i;
1047 1048
1048 if (!msm_fmt || !cmd || !bos) {1049 if (!msm_fmt || !cmd || !bos) {
1049 DRM_ERROR("invalid arguments\n");1050 DRM_ERROR("invalid arguments\n");
@@ -1051,14 +1052,16 @@ int dpu_format_check_modified_format( · 1 unmodified line
1051 }1052 }
1052 1053
1053 fmt = to_dpu_format(msm_fmt);1054 fmt = to_dpu_format(msm_fmt);
1054 num_base_fmt_planes = drm_format_num_planes(fmt->base.pixel_format);1055 info = drm_format_info(fmt->base.pixel_format);
1056 if (!info)
1057 return -EINVAL;
1055 1058
1056 ret = dpu_format_get_plane_sizes(fmt, cmd->width, cmd->height,1059 ret = dpu_format_get_plane_sizes(fmt, cmd->width, cmd->height,
1057 &layout, cmd->pitches);1060 &layout, cmd->pitches);
1058 if (ret)1061 if (ret)
1059 return ret;1062 return ret;
1060 1063
1061 for (i = 0; i < num_base_fmt_planes; i++) {1064 for (i = 0; i < info->num_planes; i++) {
1062 if (!bos[i]) {1065 if (!bos[i]) {
1063 DRM_ERROR("invalid handle for plane %d\n", i);1066 DRM_ERROR("invalid handle for plane %d\n", i);
1064 return -EINVAL;1067 return -EINVAL;
drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c+2−7
@@ -557,14 +557,9 @@ static void _dpu_plane_setup_scaler(struct dpu_plane *pdpu, · 556 unmodified lines
557 struct dpu_plane_state *pstate,557 struct dpu_plane_state *pstate,
558 const struct dpu_format *fmt, bool color_fill)558 const struct dpu_format *fmt, bool color_fill)
559{559{
560 uint32_t chroma_subsmpl_h, chroma_subsmpl_v;560 const struct drm_format_info *info = drm_format_info(fmt->base.pixel_format);
561 561
562 /* don't chroma subsample if decimating */562 /* don't chroma subsample if decimating */
563 chroma_subsmpl_h =
564 drm_format_horz_chroma_subsampling(fmt->base.pixel_format);
565 chroma_subsmpl_v =
566 drm_format_vert_chroma_subsampling(fmt->base.pixel_format);
567
568 /* update scaler. calculate default config for QSEED3 */563 /* update scaler. calculate default config for QSEED3 */
569 _dpu_plane_setup_scaler3(pdpu, pstate,564 _dpu_plane_setup_scaler3(pdpu, pstate,
570 drm_rect_width(&pdpu->pipe_cfg.src_rect),565 drm_rect_width(&pdpu->pipe_cfg.src_rect),
@@ -572,7 +567,7 @@ static void _dpu_plane_setup_scaler(struct dpu_plane *pdpu, · 1 unmodified line
572 drm_rect_width(&pdpu->pipe_cfg.dst_rect),567 drm_rect_width(&pdpu->pipe_cfg.dst_rect),
573 drm_rect_height(&pdpu->pipe_cfg.dst_rect),568 drm_rect_height(&pdpu->pipe_cfg.dst_rect),
574 &pstate->scaler3_cfg, fmt,569 &pstate->scaler3_cfg, fmt,
575 chroma_subsmpl_h, chroma_subsmpl_v);570 info->hsub, info->vsub);
576}571}
577 572
578/**573/**
drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c+13−18
@@ -782,6 +782,7 @@ static void get_roi(struct drm_crtc *crtc, uint32_t *roi_w, uint32_t *roi_h) · 781 unmodified lines
782 782
783static void mdp5_crtc_restore_cursor(struct drm_crtc *crtc)783static void mdp5_crtc_restore_cursor(struct drm_crtc *crtc)
784{784{
785 const struct drm_format_info *info = drm_format_info(DRM_FORMAT_ARGB8888);
785 struct mdp5_crtc_state *mdp5_cstate = to_mdp5_crtc_state(crtc->state);786 struct mdp5_crtc_state *mdp5_cstate = to_mdp5_crtc_state(crtc->state);
786 struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);787 struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
787 struct mdp5_kms *mdp5_kms = get_kms(crtc);788 struct mdp5_kms *mdp5_kms = get_kms(crtc);
@@ -800,7 +801,7 @@ static void mdp5_crtc_restore_cursor(struct drm_crtc *crtc) · 12 unmodified lines
800 width = mdp5_crtc->cursor.width;801 width = mdp5_crtc->cursor.width;
801 height = mdp5_crtc->cursor.height;802 height = mdp5_crtc->cursor.height;
802 803
803 stride = width * drm_format_plane_cpp(DRM_FORMAT_ARGB8888, 0);804 stride = width * info->cpp[0];
804 805
805 get_roi(crtc, &roi_w, &roi_h);806 get_roi(crtc, &roi_w, &roi_h);
806 807
@@ -1002,23 +1003,6 @@ mdp5_crtc_atomic_print_state(struct drm_printer *p, · 195 unmodified lines
1002 drm_printf(p, "\tcmd_mode=%d\n", mdp5_cstate->cmd_mode);1003 drm_printf(p, "\tcmd_mode=%d\n", mdp5_cstate->cmd_mode);
1003}1004}
1004 1005
1005static void mdp5_crtc_reset(struct drm_crtc *crtc)
1006{
1007 struct mdp5_crtc_state *mdp5_cstate;
1008
1009 if (crtc->state) {
1010 __drm_atomic_helper_crtc_destroy_state(crtc->state);
1011 kfree(to_mdp5_crtc_state(crtc->state));
1012 }
1013
1014 mdp5_cstate = kzalloc(sizeof(*mdp5_cstate), GFP_KERNEL);
1015
1016 if (mdp5_cstate) {
1017 mdp5_cstate->base.crtc = crtc;
1018 crtc->state = &mdp5_cstate->base;
1019 }
1020}
1021
1022static struct drm_crtc_state *1006static struct drm_crtc_state *
1023mdp5_crtc_duplicate_state(struct drm_crtc *crtc)1007mdp5_crtc_duplicate_state(struct drm_crtc *crtc)
1024{1008{
@@ -1046,6 +1030,17 @@ static void mdp5_crtc_destroy_state(struct drm_crtc *crtc, struct drm_crtc_state · 21 unmodified lines
1046 kfree(mdp5_cstate);1030 kfree(mdp5_cstate);
1047}1031}
1048 1032
1033static void mdp5_crtc_reset(struct drm_crtc *crtc)
1034{
1035 struct mdp5_crtc_state *mdp5_cstate =
1036 kzalloc(sizeof(*mdp5_cstate), GFP_KERNEL);
1037
1038 if (crtc->state)
1039 mdp5_crtc_destroy_state(crtc, crtc->state);
1040
1041 __drm_atomic_helper_crtc_reset(crtc, &mdp5_cstate->base);
1042}
1043
1049static const struct drm_crtc_funcs mdp5_crtc_funcs = {1044static const struct drm_crtc_funcs mdp5_crtc_funcs = {
1050 .set_config = drm_atomic_helper_set_config,1045 .set_config = drm_atomic_helper_set_config,
1051 .destroy = mdp5_crtc_destroy,1046 .destroy = mdp5_crtc_destroy,
drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c+10−14
@@ -650,10 +650,10 @@ static int calc_scalex_steps(struct drm_plane *plane, · 649 unmodified lines
650 uint32_t pixel_format, uint32_t src, uint32_t dest,650 uint32_t pixel_format, uint32_t src, uint32_t dest,
651 uint32_t phasex_steps[COMP_MAX])651 uint32_t phasex_steps[COMP_MAX])
652{652{
653 const struct drm_format_info *info = drm_format_info(pixel_format);
653 struct mdp5_kms *mdp5_kms = get_kms(plane);654 struct mdp5_kms *mdp5_kms = get_kms(plane);
654 struct device *dev = mdp5_kms->dev->dev;655 struct device *dev = mdp5_kms->dev->dev;
655 uint32_t phasex_step;656 uint32_t phasex_step;
656 unsigned int hsub;
657 int ret;657 int ret;
658 658
659 ret = calc_phase_step(src, dest, &phasex_step);659 ret = calc_phase_step(src, dest, &phasex_step);
@@ -662,11 +662,9 @@ static int calc_scalex_steps(struct drm_plane *plane, · 2 unmodified lines
662 return ret;662 return ret;
663 }663 }
664 664
665 hsub = drm_format_horz_chroma_subsampling(pixel_format);
666
667 phasex_steps[COMP_0] = phasex_step;665 phasex_steps[COMP_0] = phasex_step;
668 phasex_steps[COMP_3] = phasex_step;666 phasex_steps[COMP_3] = phasex_step;
669 phasex_steps[COMP_1_2] = phasex_step / hsub;667 phasex_steps[COMP_1_2] = phasex_step / info->hsub;
670 668
671 return 0;669 return 0;
672}670}
@@ -675,10 +673,10 @@ static int calc_scaley_steps(struct drm_plane *plane, · 2 unmodified lines
675 uint32_t pixel_format, uint32_t src, uint32_t dest,673 uint32_t pixel_format, uint32_t src, uint32_t dest,
676 uint32_t phasey_steps[COMP_MAX])674 uint32_t phasey_steps[COMP_MAX])
677{675{
676 const struct drm_format_info *info = drm_format_info(pixel_format);
678 struct mdp5_kms *mdp5_kms = get_kms(plane);677 struct mdp5_kms *mdp5_kms = get_kms(plane);
679 struct device *dev = mdp5_kms->dev->dev;678 struct device *dev = mdp5_kms->dev->dev;
680 uint32_t phasey_step;679 uint32_t phasey_step;
681 unsigned int vsub;
682 int ret;680 int ret;
683 681
684 ret = calc_phase_step(src, dest, &phasey_step);682 ret = calc_phase_step(src, dest, &phasey_step);
@@ -687,11 +685,9 @@ static int calc_scaley_steps(struct drm_plane *plane, · 2 unmodified lines
687 return ret;685 return ret;
688 }686 }
689 687
690 vsub = drm_format_vert_chroma_subsampling(pixel_format);
691
692 phasey_steps[COMP_0] = phasey_step;688 phasey_steps[COMP_0] = phasey_step;
693 phasey_steps[COMP_3] = phasey_step;689 phasey_steps[COMP_3] = phasey_step;
694 phasey_steps[COMP_1_2] = phasey_step / vsub;690 phasey_steps[COMP_1_2] = phasey_step / info->vsub;
695 691
696 return 0;692 return 0;
697}693}
@@ -699,8 +695,9 @@ static int calc_scaley_steps(struct drm_plane *plane, · 1 unmodified line
699static uint32_t get_scale_config(const struct mdp_format *format,695static uint32_t get_scale_config(const struct mdp_format *format,
700 uint32_t src, uint32_t dst, bool horz)696 uint32_t src, uint32_t dst, bool horz)
701{697{
698 const struct drm_format_info *info = drm_format_info(format->base.pixel_format);
702 bool scaling = format->is_yuv ? true : (src != dst);699 bool scaling = format->is_yuv ? true : (src != dst);
703 uint32_t sub, pix_fmt = format->base.pixel_format;700 uint32_t sub;
704 uint32_t ya_filter, uv_filter;701 uint32_t ya_filter, uv_filter;
705 bool yuv = format->is_yuv;702 bool yuv = format->is_yuv;
706 703
@@ -708,8 +705,7 @@ static uint32_t get_scale_config(const struct mdp_format *format, · 1 unmodified line
708 return 0;705 return 0;
709 706
710 if (yuv) {707 if (yuv) {
711 sub = horz ? drm_format_horz_chroma_subsampling(pix_fmt) :708 sub = horz ? info->hsub : info->vsub;
712 drm_format_vert_chroma_subsampling(pix_fmt);
713 uv_filter = ((src / sub) <= dst) ?709 uv_filter = ((src / sub) <= dst) ?
714 SCALE_FILTER_BIL : SCALE_FILTER_PCMN;710 SCALE_FILTER_BIL : SCALE_FILTER_PCMN;
715 }711 }
@@ -754,7 +750,7 @@ static void mdp5_write_pixel_ext(struct mdp5_kms *mdp5_kms, enum mdp5_pipe pipe, · 38 unmodified lines
754 uint32_t src_w, int pe_left[COMP_MAX], int pe_right[COMP_MAX],750 uint32_t src_w, int pe_left[COMP_MAX], int pe_right[COMP_MAX],
755 uint32_t src_h, int pe_top[COMP_MAX], int pe_bottom[COMP_MAX])751 uint32_t src_h, int pe_top[COMP_MAX], int pe_bottom[COMP_MAX])
756{752{
757 uint32_t pix_fmt = format->base.pixel_format;753 const struct drm_format_info *info = drm_format_info(format->base.pixel_format);
758 uint32_t lr, tb, req;754 uint32_t lr, tb, req;
759 int i;755 int i;
760 756
@@ -763,8 +759,8 @@ static void mdp5_write_pixel_ext(struct mdp5_kms *mdp5_kms, enum mdp5_pipe pipe, · 2 unmodified lines
763 uint32_t roi_h = src_h;759 uint32_t roi_h = src_h;
764 760
765 if (format->is_yuv && i == COMP_1_2) {761 if (format->is_yuv && i == COMP_1_2) {
766 roi_w /= drm_format_horz_chroma_subsampling(pix_fmt);762 roi_w /= info->hsub;
767 roi_h /= drm_format_vert_chroma_subsampling(pix_fmt);763 roi_h /= info->vsub;
768 }764 }
769 765
770 lr = (pe_left[i] >= 0) ?766 lr = (pe_left[i] >= 0) ?
drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c+4−3
@@ -127,14 +127,15 @@ uint32_t mdp5_smp_calculate(struct mdp5_smp *smp, · 126 unmodified lines
127 const struct mdp_format *format,127 const struct mdp_format *format,
128 u32 width, bool hdecim)128 u32 width, bool hdecim)
129{129{
130 const struct drm_format_info *info = drm_format_info(format->base.pixel_format);
130 struct mdp5_kms *mdp5_kms = get_kms(smp);131 struct mdp5_kms *mdp5_kms = get_kms(smp);
131 int rev = mdp5_cfg_get_hw_rev(mdp5_kms->cfg);132 int rev = mdp5_cfg_get_hw_rev(mdp5_kms->cfg);
132 int i, hsub, nplanes, nlines;133 int i, hsub, nplanes, nlines;
133 u32 fmt = format->base.pixel_format;134 u32 fmt = format->base.pixel_format;
134 uint32_t blkcfg = 0;135 uint32_t blkcfg = 0;
135 136
136 nplanes = drm_format_num_planes(fmt);137 nplanes = info->num_planes;
137 hsub = drm_format_horz_chroma_subsampling(fmt);138 hsub = info->hsub;
138 139
139 /* different if BWC (compressed framebuffer?) enabled: */140 /* different if BWC (compressed framebuffer?) enabled: */
140 nlines = 2;141 nlines = 2;
@@ -157,7 +158,7 @@ uint32_t mdp5_smp_calculate(struct mdp5_smp *smp, · 16 unmodified lines
157 for (i = 0; i < nplanes; i++) {158 for (i = 0; i < nplanes; i++) {
158 int n, fetch_stride, cpp;159 int n, fetch_stride, cpp;
159 160
160 cpp = drm_format_plane_cpp(fmt, i);161 cpp = info->cpp[i];
161 fetch_stride = width * cpp / (i ? hsub : 1);162 fetch_stride = width * cpp / (i ? hsub : 1);
162 163
163 n = DIV_ROUND_UP(fetch_stride * nlines, smp->blk_size);164 n = DIV_ROUND_UP(fetch_stride * nlines, smp->blk_size);
drivers/gpu/drm/msm/msm_fb.c+9−9
@@ -106,9 +106,11 @@ const struct msm_format *msm_framebuffer_format(struct drm_framebuffer *fb) · 105 unmodified lines
106struct drm_framebuffer *msm_framebuffer_create(struct drm_device *dev,106struct drm_framebuffer *msm_framebuffer_create(struct drm_device *dev,
107 struct drm_file *file, const struct drm_mode_fb_cmd2 *mode_cmd)107 struct drm_file *file, const struct drm_mode_fb_cmd2 *mode_cmd)
108{108{
109 const struct drm_format_info *info = drm_get_format_info(dev,
110 mode_cmd);
109 struct drm_gem_object *bos[4] = {0};111 struct drm_gem_object *bos[4] = {0};
110 struct drm_framebuffer *fb;112 struct drm_framebuffer *fb;
111 int ret, i, n = drm_format_num_planes(mode_cmd->pixel_format);113 int ret, i, n = info->num_planes;
112 114
113 for (i = 0; i < n; i++) {115 for (i = 0; i < n; i++) {
114 bos[i] = drm_gem_object_lookup(file, mode_cmd->handles[i]);116 bos[i] = drm_gem_object_lookup(file, mode_cmd->handles[i]);
@@ -135,22 +137,20 @@ out_unref: · 20 unmodified lines
135static struct drm_framebuffer *msm_framebuffer_init(struct drm_device *dev,137static struct drm_framebuffer *msm_framebuffer_init(struct drm_device *dev,
136 const struct drm_mode_fb_cmd2 *mode_cmd, struct drm_gem_object **bos)138 const struct drm_mode_fb_cmd2 *mode_cmd, struct drm_gem_object **bos)
137{139{
140 const struct drm_format_info *info = drm_get_format_info(dev,
141 mode_cmd);
138 struct msm_drm_private *priv = dev->dev_private;142 struct msm_drm_private *priv = dev->dev_private;
139 struct msm_kms *kms = priv->kms;143 struct msm_kms *kms = priv->kms;
140 struct msm_framebuffer *msm_fb = NULL;144 struct msm_framebuffer *msm_fb = NULL;
141 struct drm_framebuffer *fb;145 struct drm_framebuffer *fb;
142 const struct msm_format *format;146 const struct msm_format *format;
143 int ret, i, n;147 int ret, i, n;
144 unsigned int hsub, vsub;
145 148
146 DBG("create framebuffer: dev=%p, mode_cmd=%p (%dx%d@%4.4s)",149 DBG("create framebuffer: dev=%p, mode_cmd=%p (%dx%d@%4.4s)",
147 dev, mode_cmd, mode_cmd->width, mode_cmd->height,150 dev, mode_cmd, mode_cmd->width, mode_cmd->height,
148 (char *)&mode_cmd->pixel_format);151 (char *)&mode_cmd->pixel_format);
149 152
150 n = drm_format_num_planes(mode_cmd->pixel_format);153 n = info->num_planes;
151 hsub = drm_format_horz_chroma_subsampling(mode_cmd->pixel_format);
152 vsub = drm_format_vert_chroma_subsampling(mode_cmd->pixel_format);
153
154 format = kms->funcs->get_format(kms, mode_cmd->pixel_format,154 format = kms->funcs->get_format(kms, mode_cmd->pixel_format,
155 mode_cmd->modifier[0]);155 mode_cmd->modifier[0]);
156 if (!format) {156 if (!format) {
@@ -176,12 +176,12 @@ static struct drm_framebuffer *msm_framebuffer_init(struct drm_device *dev, · 19 unmodified lines
176 }176 }
177 177
178 for (i = 0; i < n; i++) {178 for (i = 0; i < n; i++) {
179 unsigned int width = mode_cmd->width / (i ? hsub : 1);179 unsigned int width = mode_cmd->width / (i ? info->hsub : 1);
180 unsigned int height = mode_cmd->height / (i ? vsub : 1);180 unsigned int height = mode_cmd->height / (i ? info->vsub : 1);
181 unsigned int min_size;181 unsigned int min_size;
182 182
183 min_size = (height - 1) * mode_cmd->pitches[i]183 min_size = (height - 1) * mode_cmd->pitches[i]
184 + width * drm_format_plane_cpp(mode_cmd->pixel_format, i)184 + width * info->cpp[i]
185 + mode_cmd->offsets[i];185 + mode_cmd->offsets[i];
186 186
187 if (bos[i]->size < min_size) {187 if (bos[i]->size < min_size) {
drivers/gpu/drm/nouveau/dispnv50/head.c+3−10
@@ -420,16 +420,6 @@ nv50_head_atomic_duplicate_state(struct drm_crtc *crtc) · 419 unmodified lines
420 return &asyh->state;420 return &asyh->state;
421}421}
422 422
423static void
424__drm_atomic_helper_crtc_reset(struct drm_crtc *crtc,
425 struct drm_crtc_state *state)
426{
427 if (crtc->state)
428 crtc->funcs->atomic_destroy_state(crtc, crtc->state);
429 crtc->state = state;
430 crtc->state->crtc = crtc;
431}
432
433static void423static void
434nv50_head_reset(struct drm_crtc *crtc)424nv50_head_reset(struct drm_crtc *crtc)
435{425{
@@ -438,6 +428,9 @@ nv50_head_reset(struct drm_crtc *crtc) · 2 unmodified lines
438 if (WARN_ON(!(asyh = kzalloc(sizeof(*asyh), GFP_KERNEL))))428 if (WARN_ON(!(asyh = kzalloc(sizeof(*asyh), GFP_KERNEL))))
439 return;429 return;
440 430
431 if (crtc->state)
432 nv50_head_atomic_destroy_state(crtc, crtc->state);
433
441 __drm_atomic_helper_crtc_reset(crtc, &asyh->state);434 __drm_atomic_helper_crtc_reset(crtc, &asyh->state);
442}435}
443 436
drivers/gpu/drm/nouveau/nvkm/subdev/bus/nv04.c+0−2
@@ -26,8 +26,6 @@ · 25 unmodified lines
26 26
27#include <subdev/gpio.h>27#include <subdev/gpio.h>
28 28
29#include <subdev/gpio.h>
30
31static void29static void
32nv04_bus_intr(struct nvkm_bus *bus)30nv04_bus_intr(struct nvkm_bus *bus)
33{31{
drivers/gpu/drm/omapdrm/omap_fb.c+4−2
@@ -298,7 +298,9 @@ void omap_framebuffer_describe(struct drm_framebuffer *fb, struct seq_file *m) · 297 unmodified lines
298struct drm_framebuffer *omap_framebuffer_create(struct drm_device *dev,298struct drm_framebuffer *omap_framebuffer_create(struct drm_device *dev,
299 struct drm_file *file, const struct drm_mode_fb_cmd2 *mode_cmd)299 struct drm_file *file, const struct drm_mode_fb_cmd2 *mode_cmd)
300{300{
301 unsigned int num_planes = drm_format_num_planes(mode_cmd->pixel_format);301 const struct drm_format_info *info = drm_get_format_info(dev,
302 mode_cmd);
303 unsigned int num_planes = info->num_planes;
302 struct drm_gem_object *bos[4];304 struct drm_gem_object *bos[4];
303 struct drm_framebuffer *fb;305 struct drm_framebuffer *fb;
304 int i;306 int i;
@@ -337,7 +339,7 @@ struct drm_framebuffer *omap_framebuffer_init(struct drm_device *dev, · 32 unmodified lines
337 dev, mode_cmd, mode_cmd->width, mode_cmd->height,339 dev, mode_cmd, mode_cmd->width, mode_cmd->height,
338 (char *)&mode_cmd->pixel_format);340 (char *)&mode_cmd->pixel_format);
339 341
340 format = drm_format_info(mode_cmd->pixel_format);342 format = drm_get_format_info(dev, mode_cmd);
341 343
342 for (i = 0; i < ARRAY_SIZE(formats); i++) {344 for (i = 0; i < ARRAY_SIZE(formats); i++) {
343 if (formats[i] == mode_cmd->pixel_format)345 if (formats[i] == mode_cmd->pixel_format)
drivers/gpu/drm/panel/Kconfig+18−0
@@ -132,6 +132,15 @@ config DRM_PANEL_ORISETECH_OTM8009A · 131 unmodified lines
132 Say Y here if you want to enable support for Orise Technology132 Say Y here if you want to enable support for Orise Technology
133 otm8009a 480x800 dsi 2dl panel.133 otm8009a 480x800 dsi 2dl panel.
134 134
135config DRM_PANEL_OSD_OSD101T2587_53TS
136 tristate "OSD OSD101T2587-53TS DSI 1920x1200 video mode panel"
137 depends on OF
138 depends on DRM_MIPI_DSI
139 depends on BACKLIGHT_CLASS_DEVICE
140 help
141 Say Y here if you want to enable support for One Stop Displays
142 OSD101T2587-53TS 10.1" 1920x1200 dsi panel.
143
135config DRM_PANEL_PANASONIC_VVX10F034N00144config DRM_PANEL_PANASONIC_VVX10F034N00
136 tristate "Panasonic VVX10F034N00 1920x1200 video mode panel"145 tristate "Panasonic VVX10F034N00 1920x1200 video mode panel"
137 depends on OF146 depends on OF
@@ -201,6 +210,15 @@ config DRM_PANEL_SAMSUNG_S6E63J0X03 · 63 unmodified lines
201 depends on BACKLIGHT_CLASS_DEVICE210 depends on BACKLIGHT_CLASS_DEVICE
202 select VIDEOMODE_HELPERS211 select VIDEOMODE_HELPERS
203 212
213config DRM_PANEL_SAMSUNG_S6E63M0
214 tristate "Samsung S6E63M0 RGB/SPI panel"
215 depends on OF
216 depends on SPI
217 depends on BACKLIGHT_CLASS_DEVICE
218 help
219 Say Y here if you want to enable support for Samsung S6E63M0
220 AMOLED LCD panel.
221
204config DRM_PANEL_SAMSUNG_S6E8AA0222config DRM_PANEL_SAMSUNG_S6E8AA0
205 tristate "Samsung S6E8AA0 DSI video mode panel"223 tristate "Samsung S6E8AA0 DSI video mode panel"
206 depends on OF224 depends on OF
drivers/gpu/drm/panel/Makefile+2−0
@@ -11,6 +11,7 @@ obj-$(CONFIG_DRM_PANEL_KINGDISPLAY_KD097D04) += panel-kingdisplay-kd097d04.o · 10 unmodified lines
11obj-$(CONFIG_DRM_PANEL_LG_LG4573) += panel-lg-lg4573.o11obj-$(CONFIG_DRM_PANEL_LG_LG4573) += panel-lg-lg4573.o
12obj-$(CONFIG_DRM_PANEL_OLIMEX_LCD_OLINUXINO) += panel-olimex-lcd-olinuxino.o12obj-$(CONFIG_DRM_PANEL_OLIMEX_LCD_OLINUXINO) += panel-olimex-lcd-olinuxino.o
13obj-$(CONFIG_DRM_PANEL_ORISETECH_OTM8009A) += panel-orisetech-otm8009a.o13obj-$(CONFIG_DRM_PANEL_ORISETECH_OTM8009A) += panel-orisetech-otm8009a.o
14obj-$(CONFIG_DRM_PANEL_OSD_OSD101T2587_53TS) += panel-osd-osd101t2587-53ts.o
14obj-$(CONFIG_DRM_PANEL_PANASONIC_VVX10F034N00) += panel-panasonic-vvx10f034n00.o15obj-$(CONFIG_DRM_PANEL_PANASONIC_VVX10F034N00) += panel-panasonic-vvx10f034n00.o
15obj-$(CONFIG_DRM_PANEL_RASPBERRYPI_TOUCHSCREEN) += panel-raspberrypi-touchscreen.o16obj-$(CONFIG_DRM_PANEL_RASPBERRYPI_TOUCHSCREEN) += panel-raspberrypi-touchscreen.o
16obj-$(CONFIG_DRM_PANEL_RAYDIUM_RM68200) += panel-raydium-rm68200.o17obj-$(CONFIG_DRM_PANEL_RAYDIUM_RM68200) += panel-raydium-rm68200.o
@@ -20,6 +21,7 @@ obj-$(CONFIG_DRM_PANEL_SAMSUNG_LD9040) += panel-samsung-ld9040.o · 3 unmodified lines
20obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6D16D0) += panel-samsung-s6d16d0.o21obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6D16D0) += panel-samsung-s6d16d0.o
21obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E3HA2) += panel-samsung-s6e3ha2.o22obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E3HA2) += panel-samsung-s6e3ha2.o
22obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E63J0X03) += panel-samsung-s6e63j0x03.o23obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E63J0X03) += panel-samsung-s6e63j0x03.o
24obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E63M0) += panel-samsung-s6e63m0.o
23obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E8AA0) += panel-samsung-s6e8aa0.o25obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E8AA0) += panel-samsung-s6e8aa0.o
24obj-$(CONFIG_DRM_PANEL_SEIKO_43WVF1G) += panel-seiko-43wvf1g.o26obj-$(CONFIG_DRM_PANEL_SEIKO_43WVF1G) += panel-seiko-43wvf1g.o
25obj-$(CONFIG_DRM_PANEL_SHARP_LQ101R1SX01) += panel-sharp-lq101r1sx01.o27obj-$(CONFIG_DRM_PANEL_SHARP_LQ101R1SX01) += panel-sharp-lq101r1sx01.o
drivers/gpu/drm/panel/panel-osd-osd101t2587-53ts.c+254−0
@@ -0,0 +1,254 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com
4 * Author: Peter Ujfalusi <peter.ujfalusi@ti.com>
5 */
6
7#include <linux/backlight.h>
8#include <linux/module.h>
9#include <linux/of.h>
10#include <linux/regulator/consumer.h>
11
12#include <drm/drm_crtc.h>
13#include <drm/drm_device.h>
14#include <drm/drm_mipi_dsi.h>
15#include <drm/drm_panel.h>
16
17#include <video/mipi_display.h>
18
19struct osd101t2587_panel {
20 struct drm_panel base;
21 struct mipi_dsi_device *dsi;
22
23 struct backlight_device *backlight;
24 struct regulator *supply;
25
26 bool prepared;
27 bool enabled;
28
29 const struct drm_display_mode *default_mode;
30};
31
32static inline struct osd101t2587_panel *ti_osd_panel(struct drm_panel *panel)
33{
34 return container_of(panel, struct osd101t2587_panel, base);
35}
36
37static int osd101t2587_panel_disable(struct drm_panel *panel)
38{
39 struct osd101t2587_panel *osd101t2587 = ti_osd_panel(panel);
40 int ret;
41
42 if (!osd101t2587->enabled)
43 return 0;
44
45 backlight_disable(osd101t2587->backlight);
46
47 ret = mipi_dsi_shutdown_peripheral(osd101t2587->dsi);
48
49 osd101t2587->enabled = false;
50
51 return ret;
52}
53
54static int osd101t2587_panel_unprepare(struct drm_panel *panel)
55{
56 struct osd101t2587_panel *osd101t2587 = ti_osd_panel(panel);
57
58 if (!osd101t2587->prepared)
59 return 0;
60
61 regulator_disable(osd101t2587->supply);
62 osd101t2587->prepared = false;
63
64 return 0;
65}
66
67static int osd101t2587_panel_prepare(struct drm_panel *panel)
68{
69 struct osd101t2587_panel *osd101t2587 = ti_osd_panel(panel);
70 int ret;
71
72 if (osd101t2587->prepared)
73 return 0;
74
75 ret = regulator_enable(osd101t2587->supply);
76 if (!ret)
77 osd101t2587->prepared = true;
78
79 return ret;
80}
81
82static int osd101t2587_panel_enable(struct drm_panel *panel)
83{
84 struct osd101t2587_panel *osd101t2587 = ti_osd_panel(panel);
85 int ret;
86
87 if (osd101t2587->enabled)
88 return 0;
89
90 ret = mipi_dsi_turn_on_peripheral(osd101t2587->dsi);
91 if (ret)
92 return ret;
93
94 backlight_enable(osd101t2587->backlight);
95
96 osd101t2587->enabled = true;
97
98 return ret;
99}
100
101static const struct drm_display_mode default_mode_osd101t2587 = {
102 .clock = 164400,
103 .hdisplay = 1920,
104 .hsync_start = 1920 + 152,
105 .hsync_end = 1920 + 152 + 52,
106 .htotal = 1920 + 152 + 52 + 20,
107 .vdisplay = 1200,
108 .vsync_start = 1200 + 24,
109 .vsync_end = 1200 + 24 + 6,
110 .vtotal = 1200 + 24 + 6 + 48,
111 .vrefresh = 60,
112 .flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC,
113};
114
115static int osd101t2587_panel_get_modes(struct drm_panel *panel)
116{
117 struct osd101t2587_panel *osd101t2587 = ti_osd_panel(panel);
118 struct drm_display_mode *mode;
119
120 mode = drm_mode_duplicate(panel->drm, osd101t2587->default_mode);
121 if (!mode) {
122 dev_err(panel->drm->dev, "failed to add mode %ux%ux@%u\n",
123 osd101t2587->default_mode->hdisplay,
124 osd101t2587->default_mode->vdisplay,
125 osd101t2587->default_mode->vrefresh);
126 return -ENOMEM;
127 }
128
129 drm_mode_set_name(mode);
130
131 drm_mode_probed_add(panel->connector, mode);
132
133 panel->connector->display_info.width_mm = 217;
134 panel->connector->display_info.height_mm = 136;
135
136 return 1;
137}
138
139static const struct drm_panel_funcs osd101t2587_panel_funcs = {
140 .disable = osd101t2587_panel_disable,
141 .unprepare = osd101t2587_panel_unprepare,
142 .prepare = osd101t2587_panel_prepare,
143 .enable = osd101t2587_panel_enable,
144 .get_modes = osd101t2587_panel_get_modes,
145};
146
147static const struct of_device_id osd101t2587_of_match[] = {
148 {
149 .compatible = "osddisplays,osd101t2587-53ts",
150 .data = &default_mode_osd101t2587,
151 }, {
152 /* sentinel */
153 }
154};
155MODULE_DEVICE_TABLE(of, osd101t2587_of_match);
156
157static int osd101t2587_panel_add(struct osd101t2587_panel *osd101t2587)
158{
159 struct device *dev = &osd101t2587->dsi->dev;
160
161 osd101t2587->supply = devm_regulator_get(dev, "power");
162 if (IS_ERR(osd101t2587->supply))
163 return PTR_ERR(osd101t2587->supply);
164
165 osd101t2587->backlight = devm_of_find_backlight(dev);
166 if (IS_ERR(osd101t2587->backlight))
167 return PTR_ERR(osd101t2587->backlight);
168
169 drm_panel_init(&osd101t2587->base);
170 osd101t2587->base.funcs = &osd101t2587_panel_funcs;
171 osd101t2587->base.dev = &osd101t2587->dsi->dev;
172
173 return drm_panel_add(&osd101t2587->base);
174}
175
176static int osd101t2587_panel_probe(struct mipi_dsi_device *dsi)
177{
178 struct osd101t2587_panel *osd101t2587;
179 const struct of_device_id *id;
180 int ret;
181
182 id = of_match_node(osd101t2587_of_match, dsi->dev.of_node);
183 if (!id)
184 return -ENODEV;
185
186 dsi->lanes = 4;
187 dsi->format = MIPI_DSI_FMT_RGB888;
188 dsi->mode_flags = MIPI_DSI_MODE_VIDEO |
189 MIPI_DSI_MODE_VIDEO_BURST |
190 MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
191 MIPI_DSI_MODE_EOT_PACKET;
192
193 osd101t2587 = devm_kzalloc(&dsi->dev, sizeof(*osd101t2587), GFP_KERNEL);
194 if (!osd101t2587)
195 return -ENOMEM;
196
197 mipi_dsi_set_drvdata(dsi, osd101t2587);
198
199 osd101t2587->dsi = dsi;
200 osd101t2587->default_mode = id->data;
201
202 ret = osd101t2587_panel_add(osd101t2587);
203 if (ret < 0)
204 return ret;
205
206 ret = mipi_dsi_attach(dsi);
207 if (ret)
208 drm_panel_remove(&osd101t2587->base);
209
210 return ret;
211}
212
213static int osd101t2587_panel_remove(struct mipi_dsi_device *dsi)
214{
215 struct osd101t2587_panel *osd101t2587 = mipi_dsi_get_drvdata(dsi);
216 int ret;
217
218 ret = osd101t2587_panel_disable(&osd101t2587->base);
219 if (ret < 0)
220 dev_warn(&dsi->dev, "failed to disable panel: %d\n", ret);
221
222 osd101t2587_panel_unprepare(&osd101t2587->base);
223
224 drm_panel_remove(&osd101t2587->base);
225
226 ret = mipi_dsi_detach(dsi);
227 if (ret < 0)
228 dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", ret);
229
230 return ret;
231}
232
233static void osd101t2587_panel_shutdown(struct mipi_dsi_device *dsi)
234{
235 struct osd101t2587_panel *osd101t2587 = mipi_dsi_get_drvdata(dsi);
236
237 osd101t2587_panel_disable(&osd101t2587->base);
238 osd101t2587_panel_unprepare(&osd101t2587->base);
239}
240
241static struct mipi_dsi_driver osd101t2587_panel_driver = {
242 .driver = {
243 .name = "panel-osd-osd101t2587-53ts",
244 .of_match_table = osd101t2587_of_match,
245 },
246 .probe = osd101t2587_panel_probe,
247 .remove = osd101t2587_panel_remove,
248 .shutdown = osd101t2587_panel_shutdown,
249};
250module_mipi_dsi_driver(osd101t2587_panel_driver);
251
252MODULE_AUTHOR("Peter Ujfalusi <peter.ujfalusi@ti.com>");
253MODULE_DESCRIPTION("OSD101T2587-53TS DSI panel");
254MODULE_LICENSE("GPL v2");
drivers/gpu/drm/panel/panel-raspberrypi-touchscreen.c+0−1
@@ -57,7 +57,6 @@ · 56 unmodified lines
57#include <drm/drmP.h>57#include <drm/drmP.h>
58#include <drm/drm_crtc.h>58#include <drm/drm_crtc.h>
59#include <drm/drm_mipi_dsi.h>59#include <drm/drm_mipi_dsi.h>
60#include <drm/drm_panel.h>
61 60
62#define RPI_DSI_DRIVER_NAME "rpi-ts-dsi"61#define RPI_DSI_DRIVER_NAME "rpi-ts-dsi"
63 62
drivers/gpu/drm/panel/panel-samsung-s6e63m0.c+514−0
@@ -0,0 +1,514 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * S6E63M0 AMOLED LCD drm_panel driver.
4 *
5 * Copyright (C) 2019 Paweł Chmiel <pawel.mikolaj.chmiel@gmail.com>
6 * Derived from drivers/gpu/drm/panel-samsung-ld9040.c
7 *
8 * Andrzej Hajda <a.hajda@samsung.com>
9 */
10
11#include <drm/drm_modes.h>
12#include <drm/drm_panel.h>
13#include <drm/drm_print.h>
14
15#include <linux/backlight.h>
16#include <linux/delay.h>
17#include <linux/gpio/consumer.h>
18#include <linux/module.h>
19#include <linux/regulator/consumer.h>
20#include <linux/spi/spi.h>
21
22#include <video/mipi_display.h>
23
24/* Manufacturer Command Set */
25#define MCS_ELVSS_ON 0xb1
26#define MCS_MIECTL1 0xc0
27#define MCS_BCMODE 0xc1
28#define MCS_DISCTL 0xf2
29#define MCS_SRCCTL 0xf6
30#define MCS_IFCTL 0xf7
31#define MCS_PANELCTL 0xF8
32#define MCS_PGAMMACTL 0xfa
33
34#define NUM_GAMMA_LEVELS 11
35#define GAMMA_TABLE_COUNT 23
36
37#define DATA_MASK 0x100
38
39#define MAX_BRIGHTNESS (NUM_GAMMA_LEVELS - 1)
40
41/* array of gamma tables for gamma value 2.2 */
42static u8 const s6e63m0_gamma_22[NUM_GAMMA_LEVELS][GAMMA_TABLE_COUNT] = {
43 { MCS_PGAMMACTL, 0x00,
44 0x18, 0x08, 0x24, 0x78, 0xEC, 0x3D, 0xC8,
45 0xC2, 0xB6, 0xC4, 0xC7, 0xB6, 0xD5, 0xD7,
46 0xCC, 0x00, 0x39, 0x00, 0x36, 0x00, 0x51 },
47 { MCS_PGAMMACTL, 0x00,
48 0x18, 0x08, 0x24, 0x73, 0x4A, 0x3D, 0xC0,
49 0xC2, 0xB1, 0xBB, 0xBE, 0xAC, 0xCE, 0xCF,
50 0xC5, 0x00, 0x5D, 0x00, 0x5E, 0x00, 0x82 },
51 { MCS_PGAMMACTL, 0x00,
52 0x18, 0x08, 0x24, 0x70, 0x51, 0x3E, 0xBF,
53 0xC1, 0xAF, 0xB9, 0xBC, 0xAB, 0xCC, 0xCC,
54 0xC2, 0x00, 0x65, 0x00, 0x67, 0x00, 0x8D },
55 { MCS_PGAMMACTL, 0x00,
56 0x18, 0x08, 0x24, 0x6C, 0x54, 0x3A, 0xBC,
57 0xBF, 0xAC, 0xB7, 0xBB, 0xA9, 0xC9, 0xC9,
58 0xBE, 0x00, 0x71, 0x00, 0x73, 0x00, 0x9E },
59 { MCS_PGAMMACTL, 0x00,
60 0x18, 0x08, 0x24, 0x69, 0x54, 0x37, 0xBB,
61 0xBE, 0xAC, 0xB4, 0xB7, 0xA6, 0xC7, 0xC8,
62 0xBC, 0x00, 0x7B, 0x00, 0x7E, 0x00, 0xAB },
63 { MCS_PGAMMACTL, 0x00,
64 0x18, 0x08, 0x24, 0x66, 0x55, 0x34, 0xBA,
65 0xBD, 0xAB, 0xB1, 0xB5, 0xA3, 0xC5, 0xC6,
66 0xB9, 0x00, 0x85, 0x00, 0x88, 0x00, 0xBA },
67 { MCS_PGAMMACTL, 0x00,
68 0x18, 0x08, 0x24, 0x63, 0x53, 0x31, 0xB8,
69 0xBC, 0xA9, 0xB0, 0xB5, 0xA2, 0xC4, 0xC4,
70 0xB8, 0x00, 0x8B, 0x00, 0x8E, 0x00, 0xC2 },
71 { MCS_PGAMMACTL, 0x00,
72 0x18, 0x08, 0x24, 0x62, 0x54, 0x30, 0xB9,
73 0xBB, 0xA9, 0xB0, 0xB3, 0xA1, 0xC1, 0xC3,
74 0xB7, 0x00, 0x91, 0x00, 0x95, 0x00, 0xDA },
75 { MCS_PGAMMACTL, 0x00,
76 0x18, 0x08, 0x24, 0x66, 0x58, 0x34, 0xB6,
77 0xBA, 0xA7, 0xAF, 0xB3, 0xA0, 0xC1, 0xC2,
78 0xB7, 0x00, 0x97, 0x00, 0x9A, 0x00, 0xD1 },
79 { MCS_PGAMMACTL, 0x00,
80 0x18, 0x08, 0x24, 0x64, 0x56, 0x33, 0xB6,
81 0xBA, 0xA8, 0xAC, 0xB1, 0x9D, 0xC1, 0xC1,
82 0xB7, 0x00, 0x9C, 0x00, 0x9F, 0x00, 0xD6 },
83 { MCS_PGAMMACTL, 0x00,
84 0x18, 0x08, 0x24, 0x5f, 0x50, 0x2d, 0xB6,
85 0xB9, 0xA7, 0xAd, 0xB1, 0x9f, 0xbe, 0xC0,
86 0xB5, 0x00, 0xa0, 0x00, 0xa4, 0x00, 0xdb },
87};
88
89struct s6e63m0 {
90 struct device *dev;
91 struct drm_panel panel;
92 struct backlight_device *bl_dev;
93
94 struct regulator_bulk_data supplies[2];
95 struct gpio_desc *reset_gpio;
96
97 bool prepared;
98 bool enabled;
99
100 /*
101 * This field is tested by functions directly accessing bus before
102 * transfer, transfer is skipped if it is set. In case of transfer
103 * failure or unexpected response the field is set to error value.
104 * Such construct allows to eliminate many checks in higher level
105 * functions.
106 */
107 int error;
108};
109
110static const struct drm_display_mode default_mode = {
111 .clock = 25628,
112 .hdisplay = 480,
113 .hsync_start = 480 + 16,
114 .hsync_end = 480 + 16 + 2,
115 .htotal = 480 + 16 + 2 + 16,
116 .vdisplay = 800,
117 .vsync_start = 800 + 28,
118 .vsync_end = 800 + 28 + 2,
119 .vtotal = 800 + 28 + 2 + 1,
120 .vrefresh = 60,
121 .width_mm = 53,
122 .height_mm = 89,
123 .flags = DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC,
124};
125
126static inline struct s6e63m0 *panel_to_s6e63m0(struct drm_panel *panel)
127{
128 return container_of(panel, struct s6e63m0, panel);
129}
130
131static int s6e63m0_clear_error(struct s6e63m0 *ctx)
132{
133 int ret = ctx->error;
134
135 ctx->error = 0;
136 return ret;
137}
138
139static int s6e63m0_spi_write_word(struct s6e63m0 *ctx, u16 data)
140{
141 struct spi_device *spi = to_spi_device(ctx->dev);
142 struct spi_transfer xfer = {
143 .len = 2,
144 .tx_buf = &data,
145 };
146 struct spi_message msg;
147
148 spi_message_init(&msg);
149 spi_message_add_tail(&xfer, &msg);
150
151 return spi_sync(spi, &msg);
152}
153
154static void s6e63m0_dcs_write(struct s6e63m0 *ctx, const u8 *data, size_t len)
155{
156 int ret = 0;
157
158 if (ctx->error < 0 || len == 0)
159 return;
160
161 DRM_DEV_DEBUG(ctx->dev, "writing dcs seq: %*ph\n", (int)len, data);
162 ret = s6e63m0_spi_write_word(ctx, *data);
163
164 while (!ret && --len) {
165 ++data;
166 ret = s6e63m0_spi_write_word(ctx, *data | DATA_MASK);
167 }
168
169 if (ret) {
170 DRM_DEV_ERROR(ctx->dev, "error %d writing dcs seq: %*ph\n", ret,
171 (int)len, data);
172 ctx->error = ret;
173 }
174
175 usleep_range(300, 310);
176}
177
178#define s6e63m0_dcs_write_seq_static(ctx, seq ...) \
179 ({ \
180 static const u8 d[] = { seq }; \
181 s6e63m0_dcs_write(ctx, d, ARRAY_SIZE(d)); \
182 })
183
184static void s6e63m0_init(struct s6e63m0 *ctx)
185{
186 s6e63m0_dcs_write_seq_static(ctx, MCS_PANELCTL,
187 0x01, 0x27, 0x27, 0x07, 0x07, 0x54, 0x9f,
188 0x63, 0x86, 0x1a, 0x33, 0x0d, 0x00, 0x00);
189
190 s6e63m0_dcs_write_seq_static(ctx, MCS_DISCTL,
191 0x02, 0x03, 0x1c, 0x10, 0x10);
192 s6e63m0_dcs_write_seq_static(ctx, MCS_IFCTL,
193 0x03, 0x00, 0x00);
194
195 s6e63m0_dcs_write_seq_static(ctx, MCS_PGAMMACTL,
196 0x00, 0x18, 0x08, 0x24, 0x64, 0x56, 0x33,
197 0xb6, 0xba, 0xa8, 0xac, 0xb1, 0x9d, 0xc1,
198 0xc1, 0xb7, 0x00, 0x9c, 0x00, 0x9f, 0x00,
199 0xd6);
200 s6e63m0_dcs_write_seq_static(ctx, MCS_PGAMMACTL,
201 0x01);
202
203 s6e63m0_dcs_write_seq_static(ctx, MCS_SRCCTL,
204 0x00, 0x8c, 0x07);
205 s6e63m0_dcs_write_seq_static(ctx, 0xb3,
206 0xc);
207
208 s6e63m0_dcs_write_seq_static(ctx, 0xb5,
209 0x2c, 0x12, 0x0c, 0x0a, 0x10, 0x0e, 0x17,
210 0x13, 0x1f, 0x1a, 0x2a, 0x24, 0x1f, 0x1b,
211 0x1a, 0x17, 0x2b, 0x26, 0x22, 0x20, 0x3a,
212 0x34, 0x30, 0x2c, 0x29, 0x26, 0x25, 0x23,
213 0x21, 0x20, 0x1e, 0x1e);
214
215 s6e63m0_dcs_write_seq_static(ctx, 0xb6,
216 0x00, 0x00, 0x11, 0x22, 0x33, 0x44, 0x44,
217 0x44, 0x55, 0x55, 0x66, 0x66, 0x66, 0x66,
218 0x66, 0x66);
219
220 s6e63m0_dcs_write_seq_static(ctx, 0xb7,
221 0x2c, 0x12, 0x0c, 0x0a, 0x10, 0x0e, 0x17,
222 0x13, 0x1f, 0x1a, 0x2a, 0x24, 0x1f, 0x1b,
223 0x1a, 0x17, 0x2b, 0x26, 0x22, 0x20, 0x3a,
224 0x34, 0x30, 0x2c, 0x29, 0x26, 0x25, 0x23,
225 0x21, 0x20, 0x1e, 0x1e, 0x00, 0x00, 0x11,
226 0x22, 0x33, 0x44, 0x44, 0x44, 0x55, 0x55,
227 0x66, 0x66, 0x66, 0x66, 0x66, 0x66);
228
229 s6e63m0_dcs_write_seq_static(ctx, 0xb9,
230 0x2c, 0x12, 0x0c, 0x0a, 0x10, 0x0e, 0x17,
231 0x13, 0x1f, 0x1a, 0x2a, 0x24, 0x1f, 0x1b,
232 0x1a, 0x17, 0x2b, 0x26, 0x22, 0x20, 0x3a,
233 0x34, 0x30, 0x2c, 0x29, 0x26, 0x25, 0x23,
234 0x21, 0x20, 0x1e, 0x1e);
235
236 s6e63m0_dcs_write_seq_static(ctx, 0xba,
237 0x00, 0x00, 0x11, 0x22, 0x33, 0x44, 0x44,
238 0x44, 0x55, 0x55, 0x66, 0x66, 0x66, 0x66,
239 0x66, 0x66);
240
241 s6e63m0_dcs_write_seq_static(ctx, MCS_BCMODE,
242 0x4d, 0x96, 0x1d, 0x00, 0x00, 0x01, 0xdf,
243 0x00, 0x00, 0x03, 0x1f, 0x00, 0x00, 0x00,
244 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x06,
245 0x09, 0x0d, 0x0f, 0x12, 0x15, 0x18);
246
247 s6e63m0_dcs_write_seq_static(ctx, 0xb2,
248 0x10, 0x10, 0x0b, 0x05);
249
250 s6e63m0_dcs_write_seq_static(ctx, MCS_MIECTL1,
251 0x01);
252
253 s6e63m0_dcs_write_seq_static(ctx, MCS_ELVSS_ON,
254 0x0b);
255
256 s6e63m0_dcs_write_seq_static(ctx, MIPI_DCS_EXIT_SLEEP_MODE);
257}
258
259static int s6e63m0_power_on(struct s6e63m0 *ctx)
260{
261 int ret;
262
263 ret = regulator_bulk_enable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
264 if (ret < 0)
265 return ret;
266
267 msleep(25);
268
269 gpiod_set_value(ctx->reset_gpio, 0);
270 msleep(120);
271
272 return 0;
273}
274
275static int s6e63m0_power_off(struct s6e63m0 *ctx)
276{
277 int ret;
278
279 gpiod_set_value(ctx->reset_gpio, 1);
280 msleep(120);
281
282 ret = regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
283 if (ret < 0)
284 return ret;
285
286 return 0;
287}
288
289static int s6e63m0_disable(struct drm_panel *panel)
290{
291 struct s6e63m0 *ctx = panel_to_s6e63m0(panel);
292
293 if (!ctx->enabled)
294 return 0;
295
296 backlight_disable(ctx->bl_dev);
297
298 s6e63m0_dcs_write_seq_static(ctx, MIPI_DCS_ENTER_SLEEP_MODE);
299 msleep(200);
300
301 ctx->enabled = false;
302
303 return 0;
304}
305
306static int s6e63m0_unprepare(struct drm_panel *panel)
307{
308 struct s6e63m0 *ctx = panel_to_s6e63m0(panel);
309 int ret;
310
311 if (!ctx->prepared)
312 return 0;
313
314 s6e63m0_clear_error(ctx);
315
316 ret = s6e63m0_power_off(ctx);
317 if (ret < 0)
318 return ret;
319
320 ctx->prepared = false;
321
322 return 0;
323}
324
325static int s6e63m0_prepare(struct drm_panel *panel)
326{
327 struct s6e63m0 *ctx = panel_to_s6e63m0(panel);
328 int ret;
329
330 if (ctx->prepared)
331 return 0;
332
333 ret = s6e63m0_power_on(ctx);
334 if (ret < 0)
335 return ret;
336
337 s6e63m0_init(ctx);
338
339 ret = s6e63m0_clear_error(ctx);
340
341 if (ret < 0)
342 s6e63m0_unprepare(panel);
343
344 ctx->prepared = true;
345
346 return ret;
347}
348
349static int s6e63m0_enable(struct drm_panel *panel)
350{
351 struct s6e63m0 *ctx = panel_to_s6e63m0(panel);
352
353 if (ctx->enabled)
354 return 0;
355
356 s6e63m0_dcs_write_seq_static(ctx, MIPI_DCS_SET_DISPLAY_ON);
357
358 backlight_enable(ctx->bl_dev);
359
360 ctx->enabled = true;
361
362 return 0;
363}
364
365static int s6e63m0_get_modes(struct drm_panel *panel)
366{
367 struct drm_connector *connector = panel->connector;
368 struct drm_display_mode *mode;
369
370 mode = drm_mode_duplicate(panel->drm, &default_mode);
371 if (!mode) {
372 DRM_ERROR("failed to add mode %ux%ux@%u\n",
373 default_mode.hdisplay, default_mode.vdisplay,
374 default_mode.vrefresh);
375 return -ENOMEM;
376 }
377
378 drm_mode_set_name(mode);
379
380 mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
381 drm_mode_probed_add(connector, mode);
382
383 return 1;
384}
385
386static const struct drm_panel_funcs s6e63m0_drm_funcs = {
387 .disable = s6e63m0_disable,
388 .unprepare = s6e63m0_unprepare,
389 .prepare = s6e63m0_prepare,
390 .enable = s6e63m0_enable,
391 .get_modes = s6e63m0_get_modes,
392};
393
394static int s6e63m0_set_brightness(struct backlight_device *bd)
395{
396 struct s6e63m0 *ctx = bl_get_data(bd);
397
398 int brightness = bd->props.brightness;
399
400 /* disable and set new gamma */
401 s6e63m0_dcs_write(ctx, s6e63m0_gamma_22[brightness],
402 ARRAY_SIZE(s6e63m0_gamma_22[brightness]));
403
404 /* update gamma table. */
405 s6e63m0_dcs_write_seq_static(ctx, MCS_PGAMMACTL, 0x01);
406
407 return s6e63m0_clear_error(ctx);
408}
409
410static const struct backlight_ops s6e63m0_backlight_ops = {
411 .update_status = s6e63m0_set_brightness,
412};
413
414static int s6e63m0_backlight_register(struct s6e63m0 *ctx)
415{
416 struct backlight_properties props = {
417 .type = BACKLIGHT_RAW,
418 .brightness = MAX_BRIGHTNESS,
419 .max_brightness = MAX_BRIGHTNESS
420 };
421 struct device *dev = ctx->dev;
422 int ret = 0;
423
424 ctx->bl_dev = devm_backlight_device_register(dev, "panel", dev, ctx,
425 &s6e63m0_backlight_ops,
426 &props);
427 if (IS_ERR(ctx->bl_dev)) {
428 ret = PTR_ERR(ctx->bl_dev);
429 DRM_DEV_ERROR(dev, "error registering backlight device (%d)\n",
430 ret);
431 }
432
433 return ret;
434}
435
436static int s6e63m0_probe(struct spi_device *spi)
437{
438 struct device *dev = &spi->dev;
439 struct s6e63m0 *ctx;
440 int ret;
441
442 ctx = devm_kzalloc(dev, sizeof(struct s6e63m0), GFP_KERNEL);
443 if (!ctx)
444 return -ENOMEM;
445
446 spi_set_drvdata(spi, ctx);
447
448 ctx->dev = dev;
449 ctx->enabled = false;
450 ctx->prepared = false;
451
452 ctx->supplies[0].supply = "vdd3";
453 ctx->supplies[1].supply = "vci";
454 ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(ctx->supplies),
455 ctx->supplies);
456 if (ret < 0) {
457 DRM_DEV_ERROR(dev, "failed to get regulators: %d\n", ret);
458 return ret;
459 }
460
461 ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
462 if (IS_ERR(ctx->reset_gpio)) {
463 DRM_DEV_ERROR(dev, "cannot get reset-gpios %ld\n",
464 PTR_ERR(ctx->reset_gpio));
465 return PTR_ERR(ctx->reset_gpio);
466 }
467
468 spi->bits_per_word = 9;
469 spi->mode = SPI_MODE_3;
470 ret = spi_setup(spi);
471 if (ret < 0) {
472 DRM_DEV_ERROR(dev, "spi setup failed.\n");
473 return ret;
474 }
475
476 drm_panel_init(&ctx->panel);
477 ctx->panel.dev = dev;
478 ctx->panel.funcs = &s6e63m0_drm_funcs;
479
480 ret = s6e63m0_backlight_register(ctx);
481 if (ret < 0)
482 return ret;
483
484 return drm_panel_add(&ctx->panel);
485}
486
487static int s6e63m0_remove(struct spi_device *spi)
488{
489 struct s6e63m0 *ctx = spi_get_drvdata(spi);
490
491 drm_panel_remove(&ctx->panel);
492
493 return 0;
494}
495
496static const struct of_device_id s6e63m0_of_match[] = {
497 { .compatible = "samsung,s6e63m0" },
498 { /* sentinel */ }
499};
500MODULE_DEVICE_TABLE(of, s6e63m0_of_match);
501
502static struct spi_driver s6e63m0_driver = {
503 .probe = s6e63m0_probe,
504 .remove = s6e63m0_remove,
505 .driver = {
506 .name = "panel-samsung-s6e63m0",
507 .of_match_table = s6e63m0_of_match,
508 },
509};
510module_spi_driver(s6e63m0_driver);
511
512MODULE_AUTHOR("Paweł Chmiel <pawel.mikolaj.chmiel@gmail.com>");
513MODULE_DESCRIPTION("s6e63m0 LCD Driver");
514MODULE_LICENSE("GPL v2");
drivers/gpu/drm/panel/panel-simple.c+211−1
@@ -1096,6 +1096,56 @@ static const struct panel_desc dlc_dlc1010gig = { · 1095 unmodified lines
1096 .bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG,1096 .bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG,
1097};1097};
1098 1098
1099static const struct drm_display_mode edt_et035012dm6_mode = {
1100 .clock = 6500,
1101 .hdisplay = 320,
1102 .hsync_start = 320 + 20,
1103 .hsync_end = 320 + 20 + 30,
1104 .htotal = 320 + 20 + 68,
1105 .vdisplay = 240,
1106 .vsync_start = 240 + 4,
1107 .vsync_end = 240 + 4 + 4,
1108 .vtotal = 240 + 4 + 4 + 14,
1109 .vrefresh = 60,
1110 .flags = DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC,
1111};
1112
1113static const struct panel_desc edt_et035012dm6 = {
1114 .modes = &edt_et035012dm6_mode,
1115 .num_modes = 1,
1116 .bpc = 8,
1117 .size = {
1118 .width = 70,
1119 .height = 52,
1120 },
1121 .bus_format = MEDIA_BUS_FMT_RGB888_1X24,
1122 .bus_flags = DRM_BUS_FLAG_DE_LOW | DRM_BUS_FLAG_PIXDATA_NEGEDGE,
1123};
1124
1125static const struct drm_display_mode edt_etm0430g0dh6_mode = {
1126 .clock = 9000,
1127 .hdisplay = 480,
1128 .hsync_start = 480 + 2,
1129 .hsync_end = 480 + 2 + 41,
1130 .htotal = 480 + 2 + 41 + 2,
1131 .vdisplay = 272,
1132 .vsync_start = 272 + 2,
1133 .vsync_end = 272 + 2 + 10,
1134 .vtotal = 272 + 2 + 10 + 2,
1135 .vrefresh = 60,
1136 .flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC,
1137};
1138
1139static const struct panel_desc edt_etm0430g0dh6 = {
1140 .modes = &edt_etm0430g0dh6_mode,
1141 .num_modes = 1,
1142 .bpc = 6,
1143 .size = {
1144 .width = 95,
1145 .height = 54,
1146 },
1147};
1148
1099static const struct drm_display_mode edt_et057090dhu_mode = {1149static const struct drm_display_mode edt_et057090dhu_mode = {
1100 .clock = 25175,1150 .clock = 25175,
1101 .hdisplay = 640,1151 .hdisplay = 640,
@@ -1160,6 +1210,33 @@ static const struct panel_desc edt_etm0700g0bdh6 = { · 58 unmodified lines
1160 .bus_flags = DRM_BUS_FLAG_DE_HIGH | DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE,1210 .bus_flags = DRM_BUS_FLAG_DE_HIGH | DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE,
1161};1211};
1162 1212
1213static const struct display_timing evervision_vgg804821_timing = {
1214 .pixelclock = { 27600000, 33300000, 50000000 },
1215 .hactive = { 800, 800, 800 },
1216 .hfront_porch = { 40, 66, 70 },
1217 .hback_porch = { 40, 67, 70 },
1218 .hsync_len = { 40, 67, 70 },
1219 .vactive = { 480, 480, 480 },
1220 .vfront_porch = { 6, 10, 10 },
1221 .vback_porch = { 7, 11, 11 },
1222 .vsync_len = { 7, 11, 11 },
1223 .flags = DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_HIGH |
1224 DISPLAY_FLAGS_DE_HIGH | DISPLAY_FLAGS_PIXDATA_NEGEDGE |
1225 DISPLAY_FLAGS_SYNC_NEGEDGE,
1226};
1227
1228static const struct panel_desc evervision_vgg804821 = {
1229 .timings = &evervision_vgg804821_timing,
1230 .num_timings = 1,
1231 .bpc = 8,
1232 .size = {
1233 .width = 108,
1234 .height = 64,
1235 },
1236 .bus_format = MEDIA_BUS_FMT_RGB888_1X24,
1237 .bus_flags = DRM_BUS_FLAG_DE_HIGH | DRM_BUS_FLAG_PIXDATA_NEGEDGE,
1238};
1239
1163static const struct drm_display_mode foxlink_fl500wvr00_a0t_mode = {1240static const struct drm_display_mode foxlink_fl500wvr00_a0t_mode = {
1164 .clock = 32260,1241 .clock = 32260,
1165 .hdisplay = 800,1242 .hdisplay = 800,
@@ -1184,6 +1261,29 @@ static const struct panel_desc foxlink_fl500wvr00_a0t = { · 18 unmodified lines
1184 .bus_format = MEDIA_BUS_FMT_RGB888_1X24,1261 .bus_format = MEDIA_BUS_FMT_RGB888_1X24,
1185};1262};
1186 1263
1264static const struct drm_display_mode friendlyarm_hd702e_mode = {
1265 .clock = 67185,
1266 .hdisplay = 800,
1267 .hsync_start = 800 + 20,
1268 .hsync_end = 800 + 20 + 24,
1269 .htotal = 800 + 20 + 24 + 20,
1270 .vdisplay = 1280,
1271 .vsync_start = 1280 + 4,
1272 .vsync_end = 1280 + 4 + 8,
1273 .vtotal = 1280 + 4 + 8 + 4,
1274 .vrefresh = 60,
1275 .flags = DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC,
1276};
1277
1278static const struct panel_desc friendlyarm_hd702e = {
1279 .modes = &friendlyarm_hd702e_mode,
1280 .num_modes = 1,
1281 .size = {
1282 .width = 94,
1283 .height = 151,
1284 },
1285};
1286
1187static const struct drm_display_mode giantplus_gpg482739qs5_mode = {1287static const struct drm_display_mode giantplus_gpg482739qs5_mode = {
1188 .clock = 9000,1288 .clock = 9000,
1189 .hdisplay = 480,1289 .hdisplay = 480,
@@ -2355,6 +2455,31 @@ static const struct panel_desc starry_kr122ea0sra = { · 1165 unmodified lines
2355 },2455 },
2356};2456};
2357 2457
2458static const struct drm_display_mode tfc_s9700rtwv43tr_01b_mode = {
2459 .clock = 30000,
2460 .hdisplay = 800,
2461 .hsync_start = 800 + 39,
2462 .hsync_end = 800 + 39 + 47,
2463 .htotal = 800 + 39 + 47 + 39,
2464 .vdisplay = 480,
2465 .vsync_start = 480 + 13,
2466 .vsync_end = 480 + 13 + 2,
2467 .vtotal = 480 + 13 + 2 + 29,
2468 .vrefresh = 62,
2469};
2470
2471static const struct panel_desc tfc_s9700rtwv43tr_01b = {
2472 .modes = &tfc_s9700rtwv43tr_01b_mode,
2473 .num_modes = 1,
2474 .bpc = 8,
2475 .size = {
2476 .width = 155,
2477 .height = 90,
2478 },
2479 .bus_format = MEDIA_BUS_FMT_RGB888_1X24,
2480 .bus_flags = DRM_BUS_FLAG_DE_HIGH | DRM_BUS_FLAG_PIXDATA_POSEDGE,
2481};
2482
2358static const struct display_timing tianma_tm070jdhg30_timing = {2483static const struct display_timing tianma_tm070jdhg30_timing = {
2359 .pixelclock = { 62600000, 68200000, 78100000 },2484 .pixelclock = { 62600000, 68200000, 78100000 },
2360 .hactive = { 1280, 1280, 1280 },2485 .hactive = { 1280, 1280, 1280 },
@@ -2508,6 +2633,32 @@ static const struct panel_desc urt_umsh_8596md_parallel = { · 147 unmodified lines
2508 .bus_format = MEDIA_BUS_FMT_RGB666_1X18,2633 .bus_format = MEDIA_BUS_FMT_RGB666_1X18,
2509};2634};
2510 2635
2636static const struct drm_display_mode vl050_8048nt_c01_mode = {
2637 .clock = 33333,
2638 .hdisplay = 800,
2639 .hsync_start = 800 + 210,
2640 .hsync_end = 800 + 210 + 20,
2641 .htotal = 800 + 210 + 20 + 46,
2642 .vdisplay = 480,
2643 .vsync_start = 480 + 22,
2644 .vsync_end = 480 + 22 + 10,
2645 .vtotal = 480 + 22 + 10 + 23,
2646 .vrefresh = 60,
2647 .flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC,
2648};
2649
2650static const struct panel_desc vl050_8048nt_c01 = {
2651 .modes = &vl050_8048nt_c01_mode,
2652 .num_modes = 1,
2653 .bpc = 8,
2654 .size = {
2655 .width = 120,
2656 .height = 76,
2657 },
2658 .bus_format = MEDIA_BUS_FMT_RGB888_1X24,
2659 .bus_flags = DRM_BUS_FLAG_DE_HIGH | DRM_BUS_FLAG_PIXDATA_POSEDGE,
2660};
2661
2511static const struct drm_display_mode winstar_wf35ltiacd_mode = {2662static const struct drm_display_mode winstar_wf35ltiacd_mode = {
2512 .clock = 6410,2663 .clock = 6410,
2513 .hdisplay = 320,2664 .hdisplay = 320,
@@ -2645,6 +2796,12 @@ static const struct of_device_id platform_of_match[] = { · 131 unmodified lines
2645 }, {2796 }, {
2646 .compatible = "dlc,dlc1010gig",2797 .compatible = "dlc,dlc1010gig",
2647 .data = &dlc_dlc1010gig,2798 .data = &dlc_dlc1010gig,
2799 }, {
2800 .compatible = "edt,et035012dm6",
2801 .data = &edt_et035012dm6,
2802 }, {
2803 .compatible = "edt,etm0430g0dh6",
2804 .data = &edt_etm0430g0dh6,
2648 }, {2805 }, {
2649 .compatible = "edt,et057090dhu",2806 .compatible = "edt,et057090dhu",
2650 .data = &edt_et057090dhu,2807 .data = &edt_et057090dhu,
@@ -2660,9 +2817,15 @@ static const struct of_device_id platform_of_match[] = { · 9 unmodified lines
2660 }, {2817 }, {
2661 .compatible = "edt,etm0700g0edh6",2818 .compatible = "edt,etm0700g0edh6",
2662 .data = &edt_etm0700g0bdh6,2819 .data = &edt_etm0700g0bdh6,
2820 }, {
2821 .compatible = "evervision,vgg804821",
2822 .data = &evervision_vgg804821,
2663 }, {2823 }, {
2664 .compatible = "foxlink,fl500wvr00-a0t",2824 .compatible = "foxlink,fl500wvr00-a0t",
2665 .data = &foxlink_fl500wvr00_a0t,2825 .data = &foxlink_fl500wvr00_a0t,
2826 }, {
2827 .compatible = "friendlyarm,hd702e",
2828 .data = &friendlyarm_hd702e,
2666 }, {2829 }, {
2667 .compatible = "giantplus,gpg482739qs5",2830 .compatible = "giantplus,gpg482739qs5",
2668 .data = &giantplus_gpg482739qs52831 .data = &giantplus_gpg482739qs5
@@ -2801,6 +2964,9 @@ static const struct of_device_id platform_of_match[] = { · 132 unmodified lines
2801 }, {2964 }, {
2802 .compatible = "starry,kr122ea0sra",2965 .compatible = "starry,kr122ea0sra",
2803 .data = &starry_kr122ea0sra,2966 .data = &starry_kr122ea0sra,
2967 }, {
2968 .compatible = "tfc,s9700rtwv43tr-01b",
2969 .data = &tfc_s9700rtwv43tr_01b,
2804 }, {2970 }, {
2805 .compatible = "tianma,tm070jdhg30",2971 .compatible = "tianma,tm070jdhg30",
2806 .data = &tianma_tm070jdhg30,2972 .data = &tianma_tm070jdhg30,
@@ -2834,6 +3000,9 @@ static const struct of_device_id platform_of_match[] = { · 27 unmodified lines
2834 }, {3000 }, {
2835 .compatible = "urt,umsh-8596md-20t",3001 .compatible = "urt,umsh-8596md-20t",
2836 .data = &urt_umsh_8596md_parallel,3002 .data = &urt_umsh_8596md_parallel,
3003 }, {
3004 .compatible = "vxt,vl050-8048nt-c01",
3005 .data = &vl050_8048nt_c01,
2837 }, {3006 }, {
2838 .compatible = "winstar,wf35ltiacd",3007 .compatible = "winstar,wf35ltiacd",
2839 .data = &winstar_wf35ltiacd,3008 .data = &winstar_wf35ltiacd,
@@ -3053,6 +3222,37 @@ static const struct panel_desc_dsi lg_acx467akm_7 = { · 213 unmodified lines
3053 .lanes = 4,3222 .lanes = 4,
3054};3223};
3055 3224
3225static const struct drm_display_mode osd101t2045_53ts_mode = {
3226 .clock = 154500,
3227 .hdisplay = 1920,
3228 .hsync_start = 1920 + 112,
3229 .hsync_end = 1920 + 112 + 16,
3230 .htotal = 1920 + 112 + 16 + 32,
3231 .vdisplay = 1200,
3232 .vsync_start = 1200 + 16,
3233 .vsync_end = 1200 + 16 + 2,
3234 .vtotal = 1200 + 16 + 2 + 16,
3235 .vrefresh = 60,
3236 .flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC,
3237};
3238
3239static const struct panel_desc_dsi osd101t2045_53ts = {
3240 .desc = {
3241 .modes = &osd101t2045_53ts_mode,
3242 .num_modes = 1,
3243 .bpc = 8,
3244 .size = {
3245 .width = 217,
3246 .height = 136,
3247 },
3248 },
3249 .flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST |
3250 MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
3251 MIPI_DSI_MODE_EOT_PACKET,
3252 .format = MIPI_DSI_FMT_RGB888,
3253 .lanes = 4,
3254};
3255
3056static const struct of_device_id dsi_of_match[] = {3256static const struct of_device_id dsi_of_match[] = {
3057 {3257 {
3058 .compatible = "auo,b080uan01",3258 .compatible = "auo,b080uan01",
@@ -3072,6 +3272,9 @@ static const struct of_device_id dsi_of_match[] = { · 13 unmodified lines
3072 }, {3272 }, {
3073 .compatible = "lg,acx467akm-7",3273 .compatible = "lg,acx467akm-7",
3074 .data = &lg_acx467akm_73274 .data = &lg_acx467akm_7
3275 }, {
3276 .compatible = "osddisplays,osd101t2045-53ts",
3277 .data = &osd101t2045_53ts
3075 }, {3278 }, {
3076 /* sentinel */3279 /* sentinel */
3077 }3280 }
@@ -3098,7 +3301,14 @@ static int panel_simple_dsi_probe(struct mipi_dsi_device *dsi) · 20 unmodified lines
3098 dsi->format = desc->format;3301 dsi->format = desc->format;
3099 dsi->lanes = desc->lanes;3302 dsi->lanes = desc->lanes;
3100 3303
3101 return mipi_dsi_attach(dsi);3304 err = mipi_dsi_attach(dsi);
3305 if (err) {
3306 struct panel_simple *panel = dev_get_drvdata(&dsi->dev);
3307
3308 drm_panel_remove(&panel->base);
3309 }
3310
3311 return err;
3102}3312}
3103 3313
3104static int panel_simple_dsi_remove(struct mipi_dsi_device *dsi)3314static int panel_simple_dsi_remove(struct mipi_dsi_device *dsi)
drivers/gpu/drm/panfrost/panfrost_device.c+22−0
@@ -55,11 +55,33 @@ static int panfrost_clk_init(struct panfrost_device *pfdev) · 54 unmodified lines
55 if (err)55 if (err)
56 return err;56 return err;
57 57
58 pfdev->bus_clock = devm_clk_get_optional(pfdev->dev, "bus");
59 if (IS_ERR(pfdev->bus_clock)) {
60 dev_err(pfdev->dev, "get bus_clock failed %ld\n",
61 PTR_ERR(pfdev->bus_clock));
62 return PTR_ERR(pfdev->bus_clock);
63 }
64
65 if (pfdev->bus_clock) {
66 rate = clk_get_rate(pfdev->bus_clock);
67 dev_info(pfdev->dev, "bus_clock rate = %lu\n", rate);
68
69 err = clk_prepare_enable(pfdev->bus_clock);
70 if (err)
71 goto disable_clock;
72 }
73
58 return 0;74 return 0;
75
76disable_clock:
77 clk_disable_unprepare(pfdev->clock);
78
79 return err;
59}80}
60 81
61static void panfrost_clk_fini(struct panfrost_device *pfdev)82static void panfrost_clk_fini(struct panfrost_device *pfdev)
62{83{
84 clk_disable_unprepare(pfdev->bus_clock);
63 clk_disable_unprepare(pfdev->clock);85 clk_disable_unprepare(pfdev->clock);
64}86}
65 87
drivers/gpu/drm/panfrost/panfrost_device.h+1−0
@@ -66,6 +66,7 @@ struct panfrost_device { · 65 unmodified lines
66 66
67 void __iomem *iomem;67 void __iomem *iomem;
68 struct clk *clock;68 struct clk *clock;
69 struct clk *bus_clock;
69 struct regulator *regulator;70 struct regulator *regulator;
70 struct reset_control *rstc;71 struct reset_control *rstc;
71 72
drivers/gpu/drm/panfrost/panfrost_job.c+1−1
@@ -387,7 +387,7 @@ static void panfrost_job_timedout(struct drm_sched_job *sched_job) · 386 unmodified lines
387 mutex_lock(&pfdev->reset_lock);387 mutex_lock(&pfdev->reset_lock);
388 388
389 for (i = 0; i < NUM_JOB_SLOTS; i++)389 for (i = 0; i < NUM_JOB_SLOTS; i++)
390 drm_sched_stop(&pfdev->js->queue[i].sched);390 drm_sched_stop(&pfdev->js->queue[i].sched, sched_job);
391 391
392 if (sched_job)392 if (sched_job)
393 drm_sched_increase_karma(sched_job);393 drm_sched_increase_karma(sched_job);
drivers/gpu/drm/radeon/radeon_fb.c+3−1
@@ -125,6 +125,7 @@ static int radeonfb_create_pinned_object(struct radeon_fbdev *rfbdev, · 124 unmodified lines
125 struct drm_mode_fb_cmd2 *mode_cmd,125 struct drm_mode_fb_cmd2 *mode_cmd,
126 struct drm_gem_object **gobj_p)126 struct drm_gem_object **gobj_p)
127{127{
128 const struct drm_format_info *info;
128 struct radeon_device *rdev = rfbdev->rdev;129 struct radeon_device *rdev = rfbdev->rdev;
129 struct drm_gem_object *gobj = NULL;130 struct drm_gem_object *gobj = NULL;
130 struct radeon_bo *rbo = NULL;131 struct radeon_bo *rbo = NULL;
@@ -135,7 +136,8 @@ static int radeonfb_create_pinned_object(struct radeon_fbdev *rfbdev, · 4 unmodified lines
135 int height = mode_cmd->height;136 int height = mode_cmd->height;
136 u32 cpp;137 u32 cpp;
137 138
138 cpp = drm_format_plane_cpp(mode_cmd->pixel_format, 0);139 info = drm_get_format_info(rdev->ddev, mode_cmd);
140 cpp = info->cpp[0];
139 141
140 /* need to align pitch with crtc limits */142 /* need to align pitch with crtc limits */
141 mode_cmd->pitches[0] = radeon_align_pitch(rdev, mode_cmd->width, cpp,143 mode_cmd->pitches[0] = radeon_align_pitch(rdev, mode_cmd->width, cpp,
drivers/gpu/drm/rockchip/rockchip_drm_fb.c+6−11
@@ -74,23 +74,18 @@ static struct drm_framebuffer * · 73 unmodified lines
74rockchip_user_fb_create(struct drm_device *dev, struct drm_file *file_priv,74rockchip_user_fb_create(struct drm_device *dev, struct drm_file *file_priv,
75 const struct drm_mode_fb_cmd2 *mode_cmd)75 const struct drm_mode_fb_cmd2 *mode_cmd)
76{76{
77 const struct drm_format_info *info = drm_get_format_info(dev,
78 mode_cmd);
77 struct drm_framebuffer *fb;79 struct drm_framebuffer *fb;
78 struct drm_gem_object *objs[ROCKCHIP_MAX_FB_BUFFER];80 struct drm_gem_object *objs[ROCKCHIP_MAX_FB_BUFFER];
79 struct drm_gem_object *obj;81 struct drm_gem_object *obj;
80 unsigned int hsub;82 int num_planes = min_t(int, info->num_planes, ROCKCHIP_MAX_FB_BUFFER);
81 unsigned int vsub;
82 int num_planes;
83 int ret;83 int ret;
84 int i;84 int i;
85 85
86 hsub = drm_format_horz_chroma_subsampling(mode_cmd->pixel_format);
87 vsub = drm_format_vert_chroma_subsampling(mode_cmd->pixel_format);
88 num_planes = min(drm_format_num_planes(mode_cmd->pixel_format),
89 ROCKCHIP_MAX_FB_BUFFER);
90
91 for (i = 0; i < num_planes; i++) {86 for (i = 0; i < num_planes; i++) {
92 unsigned int width = mode_cmd->width / (i ? hsub : 1);87 unsigned int width = mode_cmd->width / (i ? info->hsub : 1);
93 unsigned int height = mode_cmd->height / (i ? vsub : 1);88 unsigned int height = mode_cmd->height / (i ? info->vsub : 1);
94 unsigned int min_size;89 unsigned int min_size;
95 90
96 obj = drm_gem_object_lookup(file_priv, mode_cmd->handles[i]);91 obj = drm_gem_object_lookup(file_priv, mode_cmd->handles[i]);
@@ -103,7 +98,7 @@ rockchip_user_fb_create(struct drm_device *dev, struct drm_file *file_priv, · 6 unmodified lines
103 98
104 min_size = (height - 1) * mode_cmd->pitches[i] +99 min_size = (height - 1) * mode_cmd->pitches[i] +
105 mode_cmd->offsets[i] +100 mode_cmd->offsets[i] +
106 width * drm_format_plane_cpp(mode_cmd->pixel_format, i);101 width * info->cpp[i];
107 102
108 if (obj->size < min_size) {103 if (obj->size < min_size) {
109 drm_gem_object_put_unlocked(obj);104 drm_gem_object_put_unlocked(obj);
drivers/gpu/drm/rockchip/rockchip_drm_vop.c+17−22
@@ -315,24 +315,19 @@ static uint16_t scl_vop_cal_scale(enum scale_mode mode, uint32_t src, · 314 unmodified lines
315 315
316static void scl_vop_cal_scl_fac(struct vop *vop, const struct vop_win_data *win,316static void scl_vop_cal_scl_fac(struct vop *vop, const struct vop_win_data *win,
317 uint32_t src_w, uint32_t src_h, uint32_t dst_w,317 uint32_t src_w, uint32_t src_h, uint32_t dst_w,
318 uint32_t dst_h, uint32_t pixel_format)318 uint32_t dst_h, const struct drm_format_info *info)
319{319{
320 uint16_t yrgb_hor_scl_mode, yrgb_ver_scl_mode;320 uint16_t yrgb_hor_scl_mode, yrgb_ver_scl_mode;
321 uint16_t cbcr_hor_scl_mode = SCALE_NONE;321 uint16_t cbcr_hor_scl_mode = SCALE_NONE;
322 uint16_t cbcr_ver_scl_mode = SCALE_NONE;322 uint16_t cbcr_ver_scl_mode = SCALE_NONE;
323 int hsub = drm_format_horz_chroma_subsampling(pixel_format);
324 int vsub = drm_format_vert_chroma_subsampling(pixel_format);
325 const struct drm_format_info *info;
326 bool is_yuv = false;323 bool is_yuv = false;
327 uint16_t cbcr_src_w = src_w / hsub;324 uint16_t cbcr_src_w = src_w / info->hsub;
328 uint16_t cbcr_src_h = src_h / vsub;325 uint16_t cbcr_src_h = src_h / info->vsub;
329 uint16_t vsu_mode;326 uint16_t vsu_mode;
330 uint16_t lb_mode;327 uint16_t lb_mode;
331 uint32_t val;328 uint32_t val;
332 int vskiplines;329 int vskiplines;
333 330
334 info = drm_format_info(pixel_format);
335
336 if (info->is_yuv)331 if (info->is_yuv)
337 is_yuv = true;332 is_yuv = true;
338 333
@@ -831,8 +826,8 @@ static void vop_plane_atomic_update(struct drm_plane *plane, · 492 unmodified lines
831 (state->rotation & DRM_MODE_REFLECT_X) ? 1 : 0);826 (state->rotation & DRM_MODE_REFLECT_X) ? 1 : 0);
832 827
833 if (is_yuv) {828 if (is_yuv) {
834 int hsub = drm_format_horz_chroma_subsampling(fb->format->format);829 int hsub = fb->format->hsub;
835 int vsub = drm_format_vert_chroma_subsampling(fb->format->format);830 int vsub = fb->format->vsub;
836 int bpp = fb->format->cpp[1];831 int bpp = fb->format->cpp[1];
837 832
838 uv_obj = fb->obj[1];833 uv_obj = fb->obj[1];
@@ -856,7 +851,7 @@ static void vop_plane_atomic_update(struct drm_plane *plane, · 17 unmodified lines
856 if (win->phy->scl)851 if (win->phy->scl)
857 scl_vop_cal_scl_fac(vop, win, actual_w, actual_h,852 scl_vop_cal_scl_fac(vop, win, actual_w, actual_h,
858 drm_rect_width(dest), drm_rect_height(dest),853 drm_rect_width(dest), drm_rect_height(dest),
859 fb->format->format);854 fb->format);
860 855
861 VOP_WIN_SET(vop, win, act_info, act_info);856 VOP_WIN_SET(vop, win, act_info, act_info);
862 VOP_WIN_SET(vop, win, dsp_info, dsp_info);857 VOP_WIN_SET(vop, win, dsp_info, dsp_info);
@@ -1222,17 +1217,6 @@ static void vop_crtc_destroy(struct drm_crtc *crtc) · 359 unmodified lines
1222 drm_crtc_cleanup(crtc);1217 drm_crtc_cleanup(crtc);
1223}1218}
1224 1219
1225static void vop_crtc_reset(struct drm_crtc *crtc)
1226{
1227 if (crtc->state)
1228 __drm_atomic_helper_crtc_destroy_state(crtc->state);
1229 kfree(crtc->state);
1230
1231 crtc->state = kzalloc(sizeof(struct rockchip_crtc_state), GFP_KERNEL);
1232 if (crtc->state)
1233 crtc->state->crtc = crtc;
1234}
1235
1236static struct drm_crtc_state *vop_crtc_duplicate_state(struct drm_crtc *crtc)1220static struct drm_crtc_state *vop_crtc_duplicate_state(struct drm_crtc *crtc)
1237{1221{
1238 struct rockchip_crtc_state *rockchip_state;1222 struct rockchip_crtc_state *rockchip_state;
@@ -1254,6 +1238,17 @@ static void vop_crtc_destroy_state(struct drm_crtc *crtc, · 15 unmodified lines
1254 kfree(s);1238 kfree(s);
1255}1239}
1256 1240
1241static void vop_crtc_reset(struct drm_crtc *crtc)
1242{
1243 struct rockchip_crtc_state *crtc_state =
1244 kzalloc(sizeof(*crtc_state), GFP_KERNEL);
1245
1246 if (crtc->state)
1247 vop_crtc_destroy_state(crtc, crtc->state);
1248
1249 __drm_atomic_helper_crtc_reset(crtc, &crtc_state->base);
1250}
1251
1257#ifdef CONFIG_DRM_ANALOGIX_DP1252#ifdef CONFIG_DRM_ANALOGIX_DP
1258static struct drm_connector *vop_get_edp_connector(struct vop *vop)1253static struct drm_connector *vop_get_edp_connector(struct vop *vop)
1259{1254{
drivers/gpu/drm/scheduler/sched_main.c+108−66
@@ -265,32 +265,6 @@ void drm_sched_resume_timeout(struct drm_gpu_scheduler *sched, · 264 unmodified lines
265}265}
266EXPORT_SYMBOL(drm_sched_resume_timeout);266EXPORT_SYMBOL(drm_sched_resume_timeout);
267 267
268/* job_finish is called after hw fence signaled
269 */
270static void drm_sched_job_finish(struct work_struct *work)
271{
272 struct drm_sched_job *s_job = container_of(work, struct drm_sched_job,
273 finish_work);
274 struct drm_gpu_scheduler *sched = s_job->sched;
275 unsigned long flags;
276
277 /*
278 * Canceling the timeout without removing our job from the ring mirror
279 * list is safe, as we will only end up in this worker if our jobs
280 * finished fence has been signaled. So even if some another worker
281 * manages to find this job as the next job in the list, the fence
282 * signaled check below will prevent the timeout to be restarted.
283 */
284 cancel_delayed_work_sync(&sched->work_tdr);
285
286 spin_lock_irqsave(&sched->job_list_lock, flags);
287 /* queue TDR for next job */
288 drm_sched_start_timeout(sched);
289 spin_unlock_irqrestore(&sched->job_list_lock, flags);
290
291 sched->ops->free_job(s_job);
292}
293
294static void drm_sched_job_begin(struct drm_sched_job *s_job)268static void drm_sched_job_begin(struct drm_sched_job *s_job)
295{269{
296 struct drm_gpu_scheduler *sched = s_job->sched;270 struct drm_gpu_scheduler *sched = s_job->sched;
@@ -315,6 +289,15 @@ static void drm_sched_job_timedout(struct work_struct *work) · 18 unmodified lines
315 if (job)289 if (job)
316 job->sched->ops->timedout_job(job);290 job->sched->ops->timedout_job(job);
317 291
292 /*
293 * Guilty job did complete and hence needs to be manually removed
294 * See drm_sched_stop doc.
295 */
296 if (sched->free_guilty) {
297 job->sched->ops->free_job(job);
298 sched->free_guilty = false;
299 }
300
318 spin_lock_irqsave(&sched->job_list_lock, flags);301 spin_lock_irqsave(&sched->job_list_lock, flags);
319 drm_sched_start_timeout(sched);302 drm_sched_start_timeout(sched);
320 spin_unlock_irqrestore(&sched->job_list_lock, flags);303 spin_unlock_irqrestore(&sched->job_list_lock, flags);
@@ -370,40 +353,66 @@ EXPORT_SYMBOL(drm_sched_increase_karma); · 49 unmodified lines
370 *353 *
371 * @sched: scheduler instance354 * @sched: scheduler instance
372 *355 *
356 * Stop the scheduler and also removes and frees all completed jobs.
357 * Note: bad job will not be freed as it might be used later and so it's
358 * callers responsibility to release it manually if it's not part of the
359 * mirror list any more.
360 *
373 */361 */
374void drm_sched_stop(struct drm_gpu_scheduler *sched)362void drm_sched_stop(struct drm_gpu_scheduler *sched, struct drm_sched_job *bad)
375{363{
376 struct drm_sched_job *s_job;364 struct drm_sched_job *s_job, *tmp;
377 unsigned long flags;365 unsigned long flags;
378 struct dma_fence *last_fence = NULL;
379 366
380 kthread_park(sched->thread);367 kthread_park(sched->thread);
381 368
382 /*369 /*
383 * Verify all the signaled jobs in mirror list are removed from the ring370 * Iterate the job list from later to earlier one and either deactive
384 * by waiting for the latest job to enter the list. This should insure that371 * their HW callbacks or remove them from mirror list if they already
385 * also all the previous jobs that were in flight also already singaled372 * signaled.
386 * and removed from the list.373 * This iteration is thread safe as sched thread is stopped.
387 */374 */
388 spin_lock_irqsave(&sched->job_list_lock, flags);375 list_for_each_entry_safe_reverse(s_job, tmp, &sched->ring_mirror_list, node) {
389 list_for_each_entry_reverse(s_job, &sched->ring_mirror_list, node) {
390 if (s_job->s_fence->parent &&376 if (s_job->s_fence->parent &&
391 dma_fence_remove_callback(s_job->s_fence->parent,377 dma_fence_remove_callback(s_job->s_fence->parent,
392 &s_job->cb)) {378 &s_job->cb)) {
393 dma_fence_put(s_job->s_fence->parent);
394 s_job->s_fence->parent = NULL;
395 atomic_dec(&sched->hw_rq_count);379 atomic_dec(&sched->hw_rq_count);
396 } else {380 } else {
397 last_fence = dma_fence_get(&s_job->s_fence->finished);381 /*
398 break;382 * remove job from ring_mirror_list.
383 * Locking here is for concurrent resume timeout
384 */
385 spin_lock_irqsave(&sched->job_list_lock, flags);
386 list_del_init(&s_job->node);
387 spin_unlock_irqrestore(&sched->job_list_lock, flags);
388
389 /*
390 * Wait for job's HW fence callback to finish using s_job
391 * before releasing it.
392 *
393 * Job is still alive so fence refcount at least 1
394 */
395 dma_fence_wait(&s_job->s_fence->finished, false);
396
397 /*
398 * We must keep bad job alive for later use during
399 * recovery by some of the drivers but leave a hint
400 * that the guilty job must be released.
401 */
402 if (bad != s_job)
403 sched->ops->free_job(s_job);
404 else
405 sched->free_guilty = true;
399 }406 }
400 }407 }
401 spin_unlock_irqrestore(&sched->job_list_lock, flags);
402 408
403 if (last_fence) {409 /*
404 dma_fence_wait(last_fence, false);410 * Stop pending timer in flight as we rearm it in drm_sched_start. This
405 dma_fence_put(last_fence);411 * avoids the pending timeout work in progress to fire right away after
406 }412 * this TDR finished and before the newly restarted jobs had a
413 * chance to complete.
414 */
415 cancel_delayed_work(&sched->work_tdr);
407}416}
408 417
409EXPORT_SYMBOL(drm_sched_stop);418EXPORT_SYMBOL(drm_sched_stop);
@@ -417,21 +426,22 @@ EXPORT_SYMBOL(drm_sched_stop); · 7 unmodified lines
417void drm_sched_start(struct drm_gpu_scheduler *sched, bool full_recovery)426void drm_sched_start(struct drm_gpu_scheduler *sched, bool full_recovery)
418{427{
419 struct drm_sched_job *s_job, *tmp;428 struct drm_sched_job *s_job, *tmp;
429 unsigned long flags;
420 int r;430 int r;
421 431
422 if (!full_recovery)
423 goto unpark;
424
425 /*432 /*
426 * Locking the list is not required here as the sched thread is parked433 * Locking the list is not required here as the sched thread is parked
427 * so no new jobs are being pushed in to HW and in drm_sched_stop we434 * so no new jobs are being inserted or removed. Also concurrent
428 * flushed all the jobs who were still in mirror list but who already
429 * signaled and removed them self from the list. Also concurrent
430 * GPU recovers can't run in parallel.435 * GPU recovers can't run in parallel.
431 */436 */
432 list_for_each_entry_safe(s_job, tmp, &sched->ring_mirror_list, node) {437 list_for_each_entry_safe(s_job, tmp, &sched->ring_mirror_list, node) {
433 struct dma_fence *fence = s_job->s_fence->parent;438 struct dma_fence *fence = s_job->s_fence->parent;
434 439
440 atomic_inc(&sched->hw_rq_count);
441
442 if (!full_recovery)
443 continue;
444
435 if (fence) {445 if (fence) {
436 r = dma_fence_add_callback(fence, &s_job->cb,446 r = dma_fence_add_callback(fence, &s_job->cb,
437 drm_sched_process_job);447 drm_sched_process_job);
@@ -444,9 +454,12 @@ void drm_sched_start(struct drm_gpu_scheduler *sched, bool full_recovery) · 6 unmodified lines
444 drm_sched_process_job(NULL, &s_job->cb);454 drm_sched_process_job(NULL, &s_job->cb);
445 }455 }
446 456
447 drm_sched_start_timeout(sched);457 if (full_recovery) {
458 spin_lock_irqsave(&sched->job_list_lock, flags);
459 drm_sched_start_timeout(sched);
460 spin_unlock_irqrestore(&sched->job_list_lock, flags);
461 }
448 462
449unpark:
450 kthread_unpark(sched->thread);463 kthread_unpark(sched->thread);
451}464}
452EXPORT_SYMBOL(drm_sched_start);465EXPORT_SYMBOL(drm_sched_start);
@@ -463,7 +476,6 @@ void drm_sched_resubmit_jobs(struct drm_gpu_scheduler *sched) · 10 unmodified lines
463 uint64_t guilty_context;476 uint64_t guilty_context;
464 bool found_guilty = false;477 bool found_guilty = false;
465 478
466 /*TODO DO we need spinlock here ? */
467 list_for_each_entry_safe(s_job, tmp, &sched->ring_mirror_list, node) {479 list_for_each_entry_safe(s_job, tmp, &sched->ring_mirror_list, node) {
468 struct drm_sched_fence *s_fence = s_job->s_fence;480 struct drm_sched_fence *s_fence = s_job->s_fence;
469 481
@@ -475,8 +487,8 @@ void drm_sched_resubmit_jobs(struct drm_gpu_scheduler *sched) · 5 unmodified lines
475 if (found_guilty && s_job->s_fence->scheduled.context == guilty_context)487 if (found_guilty && s_job->s_fence->scheduled.context == guilty_context)
476 dma_fence_set_error(&s_fence->finished, -ECANCELED);488 dma_fence_set_error(&s_fence->finished, -ECANCELED);
477 489
490 dma_fence_put(s_job->s_fence->parent);
478 s_job->s_fence->parent = sched->ops->run_job(s_job);491 s_job->s_fence->parent = sched->ops->run_job(s_job);
479 atomic_inc(&sched->hw_rq_count);
480 }492 }
481}493}
482EXPORT_SYMBOL(drm_sched_resubmit_jobs);494EXPORT_SYMBOL(drm_sched_resubmit_jobs);
@@ -513,7 +525,6 @@ int drm_sched_job_init(struct drm_sched_job *job, · 30 unmodified lines
513 return -ENOMEM;525 return -ENOMEM;
514 job->id = atomic64_inc_return(&sched->job_id_count);526 job->id = atomic64_inc_return(&sched->job_id_count);
515 527
516 INIT_WORK(&job->finish_work, drm_sched_job_finish);
517 INIT_LIST_HEAD(&job->node);528 INIT_LIST_HEAD(&job->node);
518 529
519 return 0;530 return 0;
@@ -596,24 +607,54 @@ static void drm_sched_process_job(struct dma_fence *f, struct dma_fence_cb *cb) · 76 unmodified lines
596 struct drm_sched_job *s_job = container_of(cb, struct drm_sched_job, cb);607 struct drm_sched_job *s_job = container_of(cb, struct drm_sched_job, cb);
597 struct drm_sched_fence *s_fence = s_job->s_fence;608 struct drm_sched_fence *s_fence = s_job->s_fence;
598 struct drm_gpu_scheduler *sched = s_fence->sched;609 struct drm_gpu_scheduler *sched = s_fence->sched;
599 unsigned long flags;
600
601 cancel_delayed_work(&sched->work_tdr);
602 610
603 atomic_dec(&sched->hw_rq_count);611 atomic_dec(&sched->hw_rq_count);
604 atomic_dec(&sched->num_jobs);612 atomic_dec(&sched->num_jobs);
605 613
606 spin_lock_irqsave(&sched->job_list_lock, flags);614 trace_drm_sched_process_job(s_fence);
607 /* remove job from ring_mirror_list */
608 list_del_init(&s_job->node);
609 spin_unlock_irqrestore(&sched->job_list_lock, flags);
610 615
611 drm_sched_fence_finished(s_fence);616 drm_sched_fence_finished(s_fence);
612
613 trace_drm_sched_process_job(s_fence);
614 wake_up_interruptible(&sched->wake_up_worker);617 wake_up_interruptible(&sched->wake_up_worker);
618}
619
620/**
621 * drm_sched_cleanup_jobs - destroy finished jobs
622 *
623 * @sched: scheduler instance
624 *
625 * Remove all finished jobs from the mirror list and destroy them.
626 */
627static void drm_sched_cleanup_jobs(struct drm_gpu_scheduler *sched)
628{
629 unsigned long flags;
630
631 /* Don't destroy jobs while the timeout worker is running */
632 if (sched->timeout != MAX_SCHEDULE_TIMEOUT &&
633 !cancel_delayed_work(&sched->work_tdr))
634 return;
635
636
637 while (!list_empty(&sched->ring_mirror_list)) {
638 struct drm_sched_job *job;
639
640 job = list_first_entry(&sched->ring_mirror_list,
641 struct drm_sched_job, node);
642 if (!dma_fence_is_signaled(&job->s_fence->finished))
643 break;
644
645 spin_lock_irqsave(&sched->job_list_lock, flags);
646 /* remove job from ring_mirror_list */
647 list_del_init(&job->node);
648 spin_unlock_irqrestore(&sched->job_list_lock, flags);
649
650 sched->ops->free_job(job);
651 }
652
653 /* queue timeout for next job */
654 spin_lock_irqsave(&sched->job_list_lock, flags);
655 drm_sched_start_timeout(sched);
656 spin_unlock_irqrestore(&sched->job_list_lock, flags);
615 657
616 schedule_work(&s_job->finish_work);
617}658}
618 659
619/**660/**
@@ -655,9 +696,10 @@ static int drm_sched_main(void *param) · 35 unmodified lines
655 struct dma_fence *fence;696 struct dma_fence *fence;
656 697
657 wait_event_interruptible(sched->wake_up_worker,698 wait_event_interruptible(sched->wake_up_worker,
699 (drm_sched_cleanup_jobs(sched),
658 (!drm_sched_blocked(sched) &&700 (!drm_sched_blocked(sched) &&
659 (entity = drm_sched_select_entity(sched))) ||701 (entity = drm_sched_select_entity(sched))) ||
660 kthread_should_stop());702 kthread_should_stop()));
661 703
662 if (!entity)704 if (!entity)
663 continue;705 continue;
drivers/gpu/drm/stm/dw_mipi_dsi-stm.c+49−11
@@ -9,6 +9,7 @@ · 8 unmodified lines
9#include <linux/clk.h>9#include <linux/clk.h>
10#include <linux/iopoll.h>10#include <linux/iopoll.h>
11#include <linux/module.h>11#include <linux/module.h>
12#include <linux/regulator/consumer.h>
12#include <drm/drmP.h>13#include <drm/drmP.h>
13#include <drm/drm_mipi_dsi.h>14#include <drm/drm_mipi_dsi.h>
14#include <drm/bridge/dw_mipi_dsi.h>15#include <drm/bridge/dw_mipi_dsi.h>
@@ -76,6 +77,7 @@ struct dw_mipi_dsi_stm { · 61 unmodified lines
76 u32 hw_version;77 u32 hw_version;
77 int lane_min_kbps;78 int lane_min_kbps;
78 int lane_max_kbps;79 int lane_max_kbps;
80 struct regulator *vdd_supply;
79};81};
80 82
81static inline void dsi_write(struct dw_mipi_dsi_stm *dsi, u32 reg, u32 val)83static inline void dsi_write(struct dw_mipi_dsi_stm *dsi, u32 reg, u32 val)
@@ -314,21 +316,36 @@ static int dw_mipi_dsi_stm_probe(struct platform_device *pdev) · 232 unmodified lines
314 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);316 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
315 dsi->base = devm_ioremap_resource(dev, res);317 dsi->base = devm_ioremap_resource(dev, res);
316 if (IS_ERR(dsi->base)) {318 if (IS_ERR(dsi->base)) {
317 DRM_ERROR("Unable to get dsi registers\n");319 ret = PTR_ERR(dsi->base);
318 return PTR_ERR(dsi->base);320 DRM_ERROR("Unable to get dsi registers %d\n", ret);
321 return ret;
322 }
323
324 dsi->vdd_supply = devm_regulator_get(dev, "phy-dsi");
325 if (IS_ERR(dsi->vdd_supply)) {
326 ret = PTR_ERR(dsi->vdd_supply);
327 if (ret != -EPROBE_DEFER)
328 DRM_ERROR("Failed to request regulator: %d\n", ret);
329 return ret;
330 }
331
332 ret = regulator_enable(dsi->vdd_supply);
333 if (ret) {
334 DRM_ERROR("Failed to enable regulator: %d\n", ret);
335 return ret;
319 }336 }
320 337
321 dsi->pllref_clk = devm_clk_get(dev, "ref");338 dsi->pllref_clk = devm_clk_get(dev, "ref");
322 if (IS_ERR(dsi->pllref_clk)) {339 if (IS_ERR(dsi->pllref_clk)) {
323 ret = PTR_ERR(dsi->pllref_clk);340 ret = PTR_ERR(dsi->pllref_clk);
324 dev_err(dev, "Unable to get pll reference clock: %d\n", ret);341 DRM_ERROR("Unable to get pll reference clock: %d\n", ret);
325 return ret;342 goto err_clk_get;
326 }343 }
327 344
328 ret = clk_prepare_enable(dsi->pllref_clk);345 ret = clk_prepare_enable(dsi->pllref_clk);
329 if (ret) {346 if (ret) {
330 dev_err(dev, "%s: Failed to enable pllref_clk\n", __func__);347 DRM_ERROR("Failed to enable pllref_clk: %d\n", ret);
331 return ret;348 goto err_clk_get;
332 }349 }
333 350
334 dw_mipi_dsi_stm_plat_data.base = dsi->base;351 dw_mipi_dsi_stm_plat_data.base = dsi->base;
@@ -338,20 +355,28 @@ static int dw_mipi_dsi_stm_probe(struct platform_device *pdev) · 3 unmodified lines
338 355
339 dsi->dsi = dw_mipi_dsi_probe(pdev, &dw_mipi_dsi_stm_plat_data);356 dsi->dsi = dw_mipi_dsi_probe(pdev, &dw_mipi_dsi_stm_plat_data);
340 if (IS_ERR(dsi->dsi)) {357 if (IS_ERR(dsi->dsi)) {
341 DRM_ERROR("Failed to initialize mipi dsi host\n");358 ret = PTR_ERR(dsi->dsi);
342 clk_disable_unprepare(dsi->pllref_clk);359 DRM_ERROR("Failed to initialize mipi dsi host: %d\n", ret);
343 return PTR_ERR(dsi->dsi);360 goto err_dsi_probe;
344 }361 }
345 362
346 return 0;363 return 0;
364
365err_dsi_probe:
366 clk_disable_unprepare(dsi->pllref_clk);
367err_clk_get:
368 regulator_disable(dsi->vdd_supply);
369
370 return ret;
347}371}
348 372
349static int dw_mipi_dsi_stm_remove(struct platform_device *pdev)373static int dw_mipi_dsi_stm_remove(struct platform_device *pdev)
350{374{
351 struct dw_mipi_dsi_stm *dsi = platform_get_drvdata(pdev);375 struct dw_mipi_dsi_stm *dsi = platform_get_drvdata(pdev);
352 376
353 clk_disable_unprepare(dsi->pllref_clk);
354 dw_mipi_dsi_remove(dsi->dsi);377 dw_mipi_dsi_remove(dsi->dsi);
378 clk_disable_unprepare(dsi->pllref_clk);
379 regulator_disable(dsi->vdd_supply);
355 380
356 return 0;381 return 0;
357}382}
@@ -363,6 +388,7 @@ static int __maybe_unused dw_mipi_dsi_stm_suspend(struct device *dev) · 5 unmodified lines
363 DRM_DEBUG_DRIVER("\n");388 DRM_DEBUG_DRIVER("\n");
364 389
365 clk_disable_unprepare(dsi->pllref_clk);390 clk_disable_unprepare(dsi->pllref_clk);
391 regulator_disable(dsi->vdd_supply);
366 392
367 return 0;393 return 0;
368}394}
@@ -370,10 +396,22 @@ static int __maybe_unused dw_mipi_dsi_stm_suspend(struct device *dev) · 1 unmodified line
370static int __maybe_unused dw_mipi_dsi_stm_resume(struct device *dev)396static int __maybe_unused dw_mipi_dsi_stm_resume(struct device *dev)
371{397{
372 struct dw_mipi_dsi_stm *dsi = dw_mipi_dsi_stm_plat_data.priv_data;398 struct dw_mipi_dsi_stm *dsi = dw_mipi_dsi_stm_plat_data.priv_data;
399 int ret;
373 400
374 DRM_DEBUG_DRIVER("\n");401 DRM_DEBUG_DRIVER("\n");
375 402
376 clk_prepare_enable(dsi->pllref_clk);403 ret = regulator_enable(dsi->vdd_supply);
404 if (ret) {
405 DRM_ERROR("Failed to enable regulator: %d\n", ret);
406 return ret;
407 }
408
409 ret = clk_prepare_enable(dsi->pllref_clk);
410 if (ret) {
411 regulator_disable(dsi->vdd_supply);
412 DRM_ERROR("Failed to enable pllref_clk: %d\n", ret);
413 return ret;
414 }
377 415
378 return 0;416 return 0;
379}417}
drivers/gpu/drm/stm/ltdc.c+47−20
@@ -232,6 +232,11 @@ static const enum ltdc_pix_fmt ltdc_pix_fmt_a1[NB_PF] = { · 231 unmodified lines
232 PF_ARGB4444 /* 0x07 */232 PF_ARGB4444 /* 0x07 */
233};233};
234 234
235static const u64 ltdc_format_modifiers[] = {
236 DRM_FORMAT_MOD_LINEAR,
237 DRM_FORMAT_MOD_INVALID
238};
239
235static inline u32 reg_read(void __iomem *base, u32 reg)240static inline u32 reg_read(void __iomem *base, u32 reg)
236{241{
237 return readl_relaxed(base + reg);242 return readl_relaxed(base + reg);
@@ -426,8 +431,8 @@ static void ltdc_crtc_atomic_enable(struct drm_crtc *crtc, · 188 unmodified lines
426 /* Enable IRQ */431 /* Enable IRQ */
427 reg_set(ldev->regs, LTDC_IER, IER_RRIE | IER_FUIE | IER_TERRIE);432 reg_set(ldev->regs, LTDC_IER, IER_RRIE | IER_FUIE | IER_TERRIE);
428 433
429 /* Immediately commit the planes */434 /* Commit shadow registers = update planes at next vblank */
430 reg_set(ldev->regs, LTDC_SRCR, SRCR_IMR);435 reg_set(ldev->regs, LTDC_SRCR, SRCR_VBR);
431 436
432 /* Enable LTDC */437 /* Enable LTDC */
433 reg_set(ldev->regs, LTDC_GCR, GCR_LTDCEN);438 reg_set(ldev->regs, LTDC_GCR, GCR_LTDCEN);
@@ -555,7 +560,7 @@ static void ltdc_crtc_mode_set_nofb(struct drm_crtc *crtc) · 121 unmodified lines
555 if (vm.flags & DISPLAY_FLAGS_VSYNC_HIGH)560 if (vm.flags & DISPLAY_FLAGS_VSYNC_HIGH)
556 val |= GCR_VSPOL;561 val |= GCR_VSPOL;
557 562
558 if (vm.flags & DISPLAY_FLAGS_DE_HIGH)563 if (vm.flags & DISPLAY_FLAGS_DE_LOW)
559 val |= GCR_DEPOL;564 val |= GCR_DEPOL;
560 565
561 if (vm.flags & DISPLAY_FLAGS_PIXDATA_NEGEDGE)566 if (vm.flags & DISPLAY_FLAGS_PIXDATA_NEGEDGE)
@@ -779,7 +784,7 @@ static void ltdc_plane_atomic_update(struct drm_plane *plane, · 217 unmodified lines
779 784
780 /* Configures the color frame buffer pitch in bytes & line length */785 /* Configures the color frame buffer pitch in bytes & line length */
781 pitch_in_bytes = fb->pitches[0];786 pitch_in_bytes = fb->pitches[0];
782 line_length = drm_format_plane_cpp(fb->format->format, 0) *787 line_length = fb->format->cpp[0] *
783 (x1 - x0 + 1) + (ldev->caps.bus_width >> 3) - 1;788 (x1 - x0 + 1) + (ldev->caps.bus_width >> 3) - 1;
784 val = ((pitch_in_bytes << 16) | line_length);789 val = ((pitch_in_bytes << 16) | line_length);
785 reg_update_bits(ldev->regs, LTDC_L1CFBLR + lofs,790 reg_update_bits(ldev->regs, LTDC_L1CFBLR + lofs,
@@ -822,11 +827,11 @@ static void ltdc_plane_atomic_update(struct drm_plane *plane, · 36 unmodified lines
822 827
823 mutex_lock(&ldev->err_lock);828 mutex_lock(&ldev->err_lock);
824 if (ldev->error_status & ISR_FUIF) {829 if (ldev->error_status & ISR_FUIF) {
825 DRM_DEBUG_DRIVER("Fifo underrun\n");830 DRM_WARN("ltdc fifo underrun: please verify display mode\n");
826 ldev->error_status &= ~ISR_FUIF;831 ldev->error_status &= ~ISR_FUIF;
827 }832 }
828 if (ldev->error_status & ISR_TERRIF) {833 if (ldev->error_status & ISR_TERRIF) {
829 DRM_DEBUG_DRIVER("Transfer error\n");834 DRM_WARN("ltdc transfer error\n");
830 ldev->error_status &= ~ISR_TERRIF;835 ldev->error_status &= ~ISR_TERRIF;
831 }836 }
832 mutex_unlock(&ldev->err_lock);837 mutex_unlock(&ldev->err_lock);
@@ -864,6 +869,16 @@ static void ltdc_plane_atomic_print_state(struct drm_printer *p, · 31 unmodified lines
864 fpsi->counter = 0;869 fpsi->counter = 0;
865}870}
866 871
872static bool ltdc_plane_format_mod_supported(struct drm_plane *plane,
873 u32 format,
874 u64 modifier)
875{
876 if (modifier == DRM_FORMAT_MOD_LINEAR)
877 return true;
878
879 return false;
880}
881
867static const struct drm_plane_funcs ltdc_plane_funcs = {882static const struct drm_plane_funcs ltdc_plane_funcs = {
868 .update_plane = drm_atomic_helper_update_plane,883 .update_plane = drm_atomic_helper_update_plane,
869 .disable_plane = drm_atomic_helper_disable_plane,884 .disable_plane = drm_atomic_helper_disable_plane,
@@ -872,6 +887,7 @@ static const struct drm_plane_funcs ltdc_plane_funcs = { · 2 unmodified lines
872 .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,887 .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
873 .atomic_destroy_state = drm_atomic_helper_plane_destroy_state,888 .atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
874 .atomic_print_state = ltdc_plane_atomic_print_state,889 .atomic_print_state = ltdc_plane_atomic_print_state,
890 .format_mod_supported = ltdc_plane_format_mod_supported,
875};891};
876 892
877static const struct drm_plane_helper_funcs ltdc_plane_helper_funcs = {893static const struct drm_plane_helper_funcs ltdc_plane_helper_funcs = {
@@ -890,6 +906,7 @@ static struct drm_plane *ltdc_plane_create(struct drm_device *ddev, · 12 unmodified lines
890 unsigned int i, nb_fmt = 0;906 unsigned int i, nb_fmt = 0;
891 u32 formats[NB_PF * 2];907 u32 formats[NB_PF * 2];
892 u32 drm_fmt, drm_fmt_no_alpha;908 u32 drm_fmt, drm_fmt_no_alpha;
909 const u64 *modifiers = ltdc_format_modifiers;
893 int ret;910 int ret;
894 911
895 /* Get supported pixel formats */912 /* Get supported pixel formats */
@@ -918,7 +935,7 @@ static struct drm_plane *ltdc_plane_create(struct drm_device *ddev, · 22 unmodified lines
918 935
919 ret = drm_universal_plane_init(ddev, plane, possible_crtcs,936 ret = drm_universal_plane_init(ddev, plane, possible_crtcs,
920 &ltdc_plane_funcs, formats, nb_fmt,937 &ltdc_plane_funcs, formats, nb_fmt,
921 NULL, type, NULL);938 modifiers, type, NULL);
922 if (ret < 0)939 if (ret < 0)
923 return NULL;940 return NULL;
924 941
@@ -1021,10 +1038,13 @@ static int ltdc_get_caps(struct drm_device *ddev) · 96 unmodified lines
1021 struct ltdc_device *ldev = ddev->dev_private;1038 struct ltdc_device *ldev = ddev->dev_private;
1022 u32 bus_width_log2, lcr, gc2r;1039 u32 bus_width_log2, lcr, gc2r;
1023 1040
1024 /* at least 1 layer must be managed */1041 /*
1042 * at least 1 layer must be managed & the number of layers
1043 * must not exceed LTDC_MAX_LAYER
1044 */
1025 lcr = reg_read(ldev->regs, LTDC_LCR);1045 lcr = reg_read(ldev->regs, LTDC_LCR);
1026 1046
1027 ldev->caps.nb_layers = max_t(int, lcr, 1);1047 ldev->caps.nb_layers = clamp((int)lcr, 1, LTDC_MAX_LAYER);
1028 1048
1029 /* set data bus width */1049 /* set data bus width */
1030 gc2r = reg_read(ldev->regs, LTDC_GC2R);1050 gc2r = reg_read(ldev->regs, LTDC_GC2R);
@@ -1125,8 +1145,9 @@ int ltdc_load(struct drm_device *ddev) · 94 unmodified lines
1125 1145
1126 ldev->pixel_clk = devm_clk_get(dev, "lcd");1146 ldev->pixel_clk = devm_clk_get(dev, "lcd");
1127 if (IS_ERR(ldev->pixel_clk)) {1147 if (IS_ERR(ldev->pixel_clk)) {
1128 DRM_ERROR("Unable to get lcd clock\n");1148 if (PTR_ERR(ldev->pixel_clk) != -EPROBE_DEFER)
1129 return -ENODEV;1149 DRM_ERROR("Unable to get lcd clock\n");
1150 return PTR_ERR(ldev->pixel_clk);
1130 }1151 }
1131 1152
1132 if (clk_prepare_enable(ldev->pixel_clk)) {1153 if (clk_prepare_enable(ldev->pixel_clk)) {
@@ -1134,6 +1155,12 @@ int ltdc_load(struct drm_device *ddev) · 1 unmodified line
1134 return -ENODEV;1155 return -ENODEV;
1135 }1156 }
1136 1157
1158 if (!IS_ERR(rstc)) {
1159 reset_control_assert(rstc);
1160 usleep_range(10, 20);
1161 reset_control_deassert(rstc);
1162 }
1163
1137 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);1164 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1138 ldev->regs = devm_ioremap_resource(dev, res);1165 ldev->regs = devm_ioremap_resource(dev, res);
1139 if (IS_ERR(ldev->regs)) {1166 if (IS_ERR(ldev->regs)) {
@@ -1142,8 +1169,15 @@ int ltdc_load(struct drm_device *ddev) · 2 unmodified lines
1142 goto err;1169 goto err;
1143 }1170 }
1144 1171
1172 /* Disable interrupts */
1173 reg_clear(ldev->regs, LTDC_IER,
1174 IER_LIE | IER_RRIE | IER_FUIE | IER_TERRIE);
1175
1145 for (i = 0; i < MAX_IRQ; i++) {1176 for (i = 0; i < MAX_IRQ; i++) {
1146 irq = platform_get_irq(pdev, i);1177 irq = platform_get_irq(pdev, i);
1178 if (irq == -EPROBE_DEFER)
1179 goto err;
1180
1147 if (irq < 0)1181 if (irq < 0)
1148 continue;1182 continue;
1149 1183
@@ -1156,15 +1190,6 @@ int ltdc_load(struct drm_device *ddev) · 6 unmodified lines
1156 }1190 }
1157 }1191 }
1158 1192
1159 if (!IS_ERR(rstc)) {
1160 reset_control_assert(rstc);
1161 usleep_range(10, 20);
1162 reset_control_deassert(rstc);
1163 }
1164
1165 /* Disable interrupts */
1166 reg_clear(ldev->regs, LTDC_IER,
1167 IER_LIE | IER_RRIE | IER_FUIE | IER_TERRIE);
1168 1193
1169 ret = ltdc_get_caps(ddev);1194 ret = ltdc_get_caps(ddev);
1170 if (ret) {1195 if (ret) {
@@ -1203,6 +1228,8 @@ int ltdc_load(struct drm_device *ddev) · 32 unmodified lines
1203 goto err;1228 goto err;
1204 }1229 }
1205 1230
1231 ddev->mode_config.allow_fb_modifiers = true;
1232
1206 ret = ltdc_crtc_init(ddev, crtc);1233 ret = ltdc_crtc_init(ddev, crtc);
1207 if (ret) {1234 if (ret) {
1208 DRM_ERROR("Failed to init crtc\n");1235 DRM_ERROR("Failed to init crtc\n");
drivers/gpu/drm/sun4i/sun4i_drv.c+1−15
@@ -53,22 +53,8 @@ static struct drm_driver sun4i_drv_driver = { · 52 unmodified lines
53 .minor = 0,53 .minor = 0,
54 54
55 /* GEM Operations */55 /* GEM Operations */
56 DRM_GEM_CMA_VMAP_DRIVER_OPS,
56 .dumb_create = drm_sun4i_gem_dumb_create,57 .dumb_create = drm_sun4i_gem_dumb_create,
57 .gem_free_object_unlocked = drm_gem_cma_free_object,
58 .gem_vm_ops = &drm_gem_cma_vm_ops,
59
60 /* PRIME Operations */
61 .prime_handle_to_fd = drm_gem_prime_handle_to_fd,
62 .prime_fd_to_handle = drm_gem_prime_fd_to_handle,
63 .gem_prime_import = drm_gem_prime_import,
64 .gem_prime_export = drm_gem_prime_export,
65 .gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table,
66 .gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table,
67 .gem_prime_vmap = drm_gem_cma_prime_vmap,
68 .gem_prime_vunmap = drm_gem_cma_prime_vunmap,
69 .gem_prime_mmap = drm_gem_cma_prime_mmap,
70
71 /* Frame Buffer Operations */
72};58};
73 59
74static int sun4i_drv_bind(struct device *dev)60static int sun4i_drv_bind(struct device *dev)
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c+1−0
@@ -980,6 +980,7 @@ static ssize_t sun6i_dsi_transfer(struct mipi_dsi_host *host, · 979 unmodified lines
980 switch (msg->type) {980 switch (msg->type) {
981 case MIPI_DSI_DCS_SHORT_WRITE:981 case MIPI_DSI_DCS_SHORT_WRITE:
982 case MIPI_DSI_DCS_SHORT_WRITE_PARAM:982 case MIPI_DSI_DCS_SHORT_WRITE_PARAM:
983 case MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM:
983 ret = sun6i_dsi_dcs_write_short(dsi, msg);984 ret = sun6i_dsi_dcs_write_short(dsi, msg);
984 break;985 break;
985 986
drivers/gpu/drm/tegra/dc.c+6−11
@@ -26,6 +26,9 @@ · 25 unmodified lines
26#include <drm/drm_atomic_helper.h>26#include <drm/drm_atomic_helper.h>
27#include <drm/drm_plane_helper.h>27#include <drm/drm_plane_helper.h>
28 28
29static void tegra_crtc_atomic_destroy_state(struct drm_crtc *crtc,
30 struct drm_crtc_state *state);
31
29static void tegra_dc_stats_reset(struct tegra_dc_stats *stats)32static void tegra_dc_stats_reset(struct tegra_dc_stats *stats)
30{33{
31 stats->frames = 0;34 stats->frames = 0;
@@ -1155,20 +1158,12 @@ static void tegra_dc_destroy(struct drm_crtc *crtc) · 1123 unmodified lines
1155 1158
1156static void tegra_crtc_reset(struct drm_crtc *crtc)1159static void tegra_crtc_reset(struct drm_crtc *crtc)
1157{1160{
1158 struct tegra_dc_state *state;1161 struct tegra_dc_state *state = kzalloc(sizeof(*state), GFP_KERNEL);
1159 1162
1160 if (crtc->state)1163 if (crtc->state)
1161 __drm_atomic_helper_crtc_destroy_state(crtc->state);1164 tegra_crtc_atomic_destroy_state(crtc, crtc->state);
1162
1163 kfree(crtc->state);
1164 crtc->state = NULL;
1165
1166 state = kzalloc(sizeof(*state), GFP_KERNEL);
1167 if (state) {
1168 crtc->state = &state->base;
1169 crtc->state->crtc = crtc;
1170 }
1171 1165
1166 __drm_atomic_helper_crtc_reset(crtc, &state->base);
1172 drm_crtc_vblank_reset(crtc);1167 drm_crtc_vblank_reset(crtc);
1173}1168}
1174 1169
drivers/gpu/drm/tegra/fb.c+6−8
@@ -131,18 +131,16 @@ struct drm_framebuffer *tegra_fb_create(struct drm_device *drm, · 130 unmodified lines
131 struct drm_file *file,131 struct drm_file *file,
132 const struct drm_mode_fb_cmd2 *cmd)132 const struct drm_mode_fb_cmd2 *cmd)
133{133{
134 unsigned int hsub, vsub, i;134 const struct drm_format_info *info = drm_get_format_info(drm, cmd);
135 struct tegra_bo *planes[4];135 struct tegra_bo *planes[4];
136 struct drm_gem_object *gem;136 struct drm_gem_object *gem;
137 struct drm_framebuffer *fb;137 struct drm_framebuffer *fb;
138 unsigned int i;
138 int err;139 int err;
139 140
140 hsub = drm_format_horz_chroma_subsampling(cmd->pixel_format);141 for (i = 0; i < info->num_planes; i++) {
141 vsub = drm_format_vert_chroma_subsampling(cmd->pixel_format);142 unsigned int width = cmd->width / (i ? info->hsub : 1);
142 143 unsigned int height = cmd->height / (i ? info->vsub : 1);
143 for (i = 0; i < drm_format_num_planes(cmd->pixel_format); i++) {
144 unsigned int width = cmd->width / (i ? hsub : 1);
145 unsigned int height = cmd->height / (i ? vsub : 1);
146 unsigned int size, bpp;144 unsigned int size, bpp;
147 145
148 gem = drm_gem_object_lookup(file, cmd->handles[i]);146 gem = drm_gem_object_lookup(file, cmd->handles[i]);
@@ -151,7 +149,7 @@ struct drm_framebuffer *tegra_fb_create(struct drm_device *drm, · 2 unmodified lines
151 goto unreference;149 goto unreference;
152 }150 }
153 151
154 bpp = drm_format_plane_cpp(cmd->pixel_format, i);152 bpp = info->cpp[i];
155 153
156 size = (height - 1) * cmd->pitches[i] +154 size = (height - 1) * cmd->pitches[i] +
157 width * bpp + cmd->offsets[i];155 width * bpp + cmd->offsets[i];
drivers/gpu/drm/v3d/v3d_debugfs.c+32−3
@@ -26,6 +26,11 @@ static const struct v3d_reg_def v3d_hub_reg_defs[] = { · 25 unmodified lines
26 REGDEF(V3D_HUB_IDENT3),26 REGDEF(V3D_HUB_IDENT3),
27 REGDEF(V3D_HUB_INT_STS),27 REGDEF(V3D_HUB_INT_STS),
28 REGDEF(V3D_HUB_INT_MSK_STS),28 REGDEF(V3D_HUB_INT_MSK_STS),
29
30 REGDEF(V3D_MMU_CTL),
31 REGDEF(V3D_MMU_VIO_ADDR),
32 REGDEF(V3D_MMU_VIO_ID),
33 REGDEF(V3D_MMU_DEBUG_INFO),
29};34};
30 35
31static const struct v3d_reg_def v3d_gca_reg_defs[] = {36static const struct v3d_reg_def v3d_gca_reg_defs[] = {
@@ -50,12 +55,25 @@ static const struct v3d_reg_def v3d_core_reg_defs[] = { · 18 unmodified lines
50 REGDEF(V3D_PTB_BPCA),55 REGDEF(V3D_PTB_BPCA),
51 REGDEF(V3D_PTB_BPCS),56 REGDEF(V3D_PTB_BPCS),
52 57
53 REGDEF(V3D_MMU_CTL),
54 REGDEF(V3D_MMU_VIO_ADDR),
55
56 REGDEF(V3D_GMP_STATUS),58 REGDEF(V3D_GMP_STATUS),
57 REGDEF(V3D_GMP_CFG),59 REGDEF(V3D_GMP_CFG),
58 REGDEF(V3D_GMP_VIO_ADDR),60 REGDEF(V3D_GMP_VIO_ADDR),
61
62 REGDEF(V3D_ERR_FDBGO),
63 REGDEF(V3D_ERR_FDBGB),
64 REGDEF(V3D_ERR_FDBGS),
65 REGDEF(V3D_ERR_STAT),
66};
67
68static const struct v3d_reg_def v3d_csd_reg_defs[] = {
69 REGDEF(V3D_CSD_STATUS),
70 REGDEF(V3D_CSD_CURRENT_CFG0),
71 REGDEF(V3D_CSD_CURRENT_CFG1),
72 REGDEF(V3D_CSD_CURRENT_CFG2),
73 REGDEF(V3D_CSD_CURRENT_CFG3),
74 REGDEF(V3D_CSD_CURRENT_CFG4),
75 REGDEF(V3D_CSD_CURRENT_CFG5),
76 REGDEF(V3D_CSD_CURRENT_CFG6),
59};77};
60 78
61static int v3d_v3d_debugfs_regs(struct seq_file *m, void *unused)79static int v3d_v3d_debugfs_regs(struct seq_file *m, void *unused)
@@ -89,6 +107,17 @@ static int v3d_v3d_debugfs_regs(struct seq_file *m, void *unused) · 27 unmodified lines
89 V3D_CORE_READ(core,107 V3D_CORE_READ(core,
90 v3d_core_reg_defs[i].reg));108 v3d_core_reg_defs[i].reg));
91 }109 }
110
111 if (v3d_has_csd(v3d)) {
112 for (i = 0; i < ARRAY_SIZE(v3d_csd_reg_defs); i++) {
113 seq_printf(m, "core %d %s (0x%04x): 0x%08x\n",
114 core,
115 v3d_csd_reg_defs[i].name,
116 v3d_csd_reg_defs[i].reg,
117 V3D_CORE_READ(core,
118 v3d_csd_reg_defs[i].reg));
119 }
120 }
92 }121 }
93 122
94 return 0;123 return 0;
drivers/gpu/drm/v3d/v3d_drv.c+13−4
@@ -7,9 +7,9 @@ · 6 unmodified lines
7 * This driver supports the Broadcom V3D 3.3 and 4.1 OpenGL ES GPUs.7 * This driver supports the Broadcom V3D 3.3 and 4.1 OpenGL ES GPUs.
8 * For V3D 2.x support, see the VC4 driver.8 * For V3D 2.x support, see the VC4 driver.
9 *9 *
10 * Currently only single-core rendering using the binner and renderer,10 * The V3D GPU includes a tiled render (composed of a bin and render
11 * along with TFU (texture formatting unit) rendering is supported.11 * pipelines), the TFU (texture formatting unit), and the CSD (compute
12 * V3D 4.x's CSD (compute shader dispatch) is not yet supported.12 * shader dispatch).
13 */13 */
14 14
15#include <linux/clk.h>15#include <linux/clk.h>
@@ -120,6 +120,9 @@ static int v3d_get_param_ioctl(struct drm_device *dev, void *data, · 104 unmodified lines
120 case DRM_V3D_PARAM_SUPPORTS_TFU:120 case DRM_V3D_PARAM_SUPPORTS_TFU:
121 args->value = 1;121 args->value = 1;
122 return 0;122 return 0;
123 case DRM_V3D_PARAM_SUPPORTS_CSD:
124 args->value = v3d_has_csd(v3d);
125 return 0;
123 default:126 default:
124 DRM_DEBUG("Unknown parameter %d\n", args->param);127 DRM_DEBUG("Unknown parameter %d\n", args->param);
125 return -EINVAL;128 return -EINVAL;
@@ -179,6 +182,7 @@ static const struct drm_ioctl_desc v3d_drm_ioctls[] = { · 53 unmodified lines
179 DRM_IOCTL_DEF_DRV(V3D_GET_PARAM, v3d_get_param_ioctl, DRM_RENDER_ALLOW),182 DRM_IOCTL_DEF_DRV(V3D_GET_PARAM, v3d_get_param_ioctl, DRM_RENDER_ALLOW),
180 DRM_IOCTL_DEF_DRV(V3D_GET_BO_OFFSET, v3d_get_bo_offset_ioctl, DRM_RENDER_ALLOW),183 DRM_IOCTL_DEF_DRV(V3D_GET_BO_OFFSET, v3d_get_bo_offset_ioctl, DRM_RENDER_ALLOW),
181 DRM_IOCTL_DEF_DRV(V3D_SUBMIT_TFU, v3d_submit_tfu_ioctl, DRM_RENDER_ALLOW | DRM_AUTH),184 DRM_IOCTL_DEF_DRV(V3D_SUBMIT_TFU, v3d_submit_tfu_ioctl, DRM_RENDER_ALLOW | DRM_AUTH),
185 DRM_IOCTL_DEF_DRV(V3D_SUBMIT_CSD, v3d_submit_csd_ioctl, DRM_RENDER_ALLOW | DRM_AUTH),
182};186};
183 187
184static struct drm_driver v3d_drm_driver = {188static struct drm_driver v3d_drm_driver = {
@@ -235,9 +239,9 @@ static int v3d_platform_drm_probe(struct platform_device *pdev) · 50 unmodified lines
235 struct drm_device *drm;239 struct drm_device *drm;
236 struct v3d_dev *v3d;240 struct v3d_dev *v3d;
237 int ret;241 int ret;
242 u32 mmu_debug;
238 u32 ident1;243 u32 ident1;
239 244
240 dev->coherent_dma_mask = DMA_BIT_MASK(36);
241 245
242 v3d = kzalloc(sizeof(*v3d), GFP_KERNEL);246 v3d = kzalloc(sizeof(*v3d), GFP_KERNEL);
243 if (!v3d)247 if (!v3d)
@@ -254,6 +258,11 @@ static int v3d_platform_drm_probe(struct platform_device *pdev) · 10 unmodified lines
254 if (ret)258 if (ret)
255 goto dev_free;259 goto dev_free;
256 260
261 mmu_debug = V3D_READ(V3D_MMU_DEBUG_INFO);
262 dev->coherent_dma_mask =
263 DMA_BIT_MASK(30 + V3D_GET_FIELD(mmu_debug, V3D_MMU_PA_WIDTH));
264 v3d->va_width = 30 + V3D_GET_FIELD(mmu_debug, V3D_MMU_VA_WIDTH);
265
257 ident1 = V3D_READ(V3D_HUB_IDENT1);266 ident1 = V3D_READ(V3D_HUB_IDENT1);
258 v3d->ver = (V3D_GET_FIELD(ident1, V3D_HUB_IDENT1_TVER) * 10 +267 v3d->ver = (V3D_GET_FIELD(ident1, V3D_HUB_IDENT1_TVER) * 10 +
259 V3D_GET_FIELD(ident1, V3D_HUB_IDENT1_REV));268 V3D_GET_FIELD(ident1, V3D_HUB_IDENT1_REV));
drivers/gpu/drm/v3d/v3d_drv.h+66−40
@@ -16,9 +16,11 @@ enum v3d_queue { · 15 unmodified lines
16 V3D_BIN,16 V3D_BIN,
17 V3D_RENDER,17 V3D_RENDER,
18 V3D_TFU,18 V3D_TFU,
19 V3D_CSD,
20 V3D_CACHE_CLEAN,
19};21};
20 22
21#define V3D_MAX_QUEUES (V3D_TFU + 1)23#define V3D_MAX_QUEUES (V3D_CACHE_CLEAN + 1)
22 24
23struct v3d_queue_state {25struct v3d_queue_state {
24 struct drm_gpu_scheduler sched;26 struct drm_gpu_scheduler sched;
@@ -55,6 +57,8 @@ struct v3d_dev { · 30 unmodified lines
55 */57 */
56 void *mmu_scratch;58 void *mmu_scratch;
57 dma_addr_t mmu_scratch_paddr;59 dma_addr_t mmu_scratch_paddr;
60 /* virtual address bits from V3D to the MMU. */
61 int va_width;
58 62
59 /* Number of V3D cores. */63 /* Number of V3D cores. */
60 u32 cores;64 u32 cores;
@@ -67,9 +71,10 @@ struct v3d_dev { · 6 unmodified lines
67 71
68 struct work_struct overflow_mem_work;72 struct work_struct overflow_mem_work;
69 73
70 struct v3d_exec_info *bin_job;74 struct v3d_bin_job *bin_job;
71 struct v3d_exec_info *render_job;75 struct v3d_render_job *render_job;
72 struct v3d_tfu_job *tfu_job;76 struct v3d_tfu_job *tfu_job;
77 struct v3d_csd_job *csd_job;
73 78
74 struct v3d_queue_state queue[V3D_MAX_QUEUES];79 struct v3d_queue_state queue[V3D_MAX_QUEUES];
75 80
@@ -92,6 +97,12 @@ struct v3d_dev { · 16 unmodified lines
92 */97 */
93 struct mutex sched_lock;98 struct mutex sched_lock;
94 99
100 /* Lock taken during a cache clean and when initiating an L2
101 * flush, to keep L2 flushes from interfering with the
102 * synchronous L2 cleans.
103 */
104 struct mutex cache_clean_lock;
105
95 struct {106 struct {
96 u32 num_allocated;107 u32 num_allocated;
97 u32 pages_allocated;108 u32 pages_allocated;
@@ -104,6 +115,12 @@ to_v3d_dev(struct drm_device *dev) · 6 unmodified lines
104 return (struct v3d_dev *)dev->dev_private;115 return (struct v3d_dev *)dev->dev_private;
105}116}
106 117
118static inline bool
119v3d_has_csd(struct v3d_dev *v3d)
120{
121 return v3d->ver >= 41;
122}
123
107/* The per-fd struct, which tracks the MMU mappings. */124/* The per-fd struct, which tracks the MMU mappings. */
108struct v3d_file_priv {125struct v3d_file_priv {
109 struct v3d_dev *v3d;126 struct v3d_dev *v3d;
@@ -117,7 +134,7 @@ struct v3d_bo { · 7 unmodified lines
117 struct drm_mm_node node;134 struct drm_mm_node node;
118 135
119 /* List entry for the BO's position in136 /* List entry for the BO's position in
120 * v3d_exec_info->unref_list137 * v3d_render_job->unref_list
121 */138 */
122 struct list_head unref_head;139 struct list_head unref_head;
123};140};
@@ -157,67 +174,74 @@ to_v3d_fence(struct dma_fence *fence) · 33 unmodified lines
157struct v3d_job {174struct v3d_job {
158 struct drm_sched_job base;175 struct drm_sched_job base;
159 176
160 struct v3d_exec_info *exec;177 struct kref refcount;
161 178
162 /* An optional fence userspace can pass in for the job to depend on. */179 struct v3d_dev *v3d;
163 struct dma_fence *in_fence;180
181 /* This is the array of BOs that were looked up at the start
182 * of submission.
183 */
184 struct drm_gem_object **bo;
185 u32 bo_count;
186
187 /* Array of struct dma_fence * to block on before submitting this job.
188 */
189 struct xarray deps;
190 unsigned long last_dep;
164 191
165 /* v3d fence to be signaled by IRQ handler when the job is complete. */192 /* v3d fence to be signaled by IRQ handler when the job is complete. */
166 struct dma_fence *irq_fence;193 struct dma_fence *irq_fence;
167 194
195 /* scheduler fence for when the job is considered complete and
196 * the BO reservations can be released.
197 */
198 struct dma_fence *done_fence;
199
200 /* Callback for the freeing of the job on refcount going to 0. */
201 void (*free)(struct kref *ref);
202};
203
204struct v3d_bin_job {
205 struct v3d_job base;
206
168 /* GPU virtual addresses of the start/end of the CL job. */207 /* GPU virtual addresses of the start/end of the CL job. */
169 u32 start, end;208 u32 start, end;
170 209
171 u32 timedout_ctca, timedout_ctra;210 u32 timedout_ctca, timedout_ctra;
172};
173 211
174struct v3d_exec_info {212 /* Corresponding render job, for attaching our overflow memory. */
175 struct v3d_dev *v3d;213 struct v3d_render_job *render;
176 214
177 struct v3d_job bin, render;215 /* Submitted tile memory allocation start/size, tile state. */
178 216 u32 qma, qms, qts;
179 /* Fence for when the scheduler considers the binner to be217};
180 * done, for render to depend on.
181 */
182 struct dma_fence *bin_done_fence;
183 218
184 /* Fence for when the scheduler considers the render to be219struct v3d_render_job {
185 * done, for when the BOs reservations should be complete.220 struct v3d_job base;
186 */
187 struct dma_fence *render_done_fence;
188 221
189 struct kref refcount;222 /* GPU virtual addresses of the start/end of the CL job. */
223 u32 start, end;
190 224
191 /* This is the array of BOs that were looked up at the start of exec. */225 u32 timedout_ctca, timedout_ctra;
192 struct v3d_bo **bo;
193 u32 bo_count;
194 226
195 /* List of overflow BOs used in the job that need to be227 /* List of overflow BOs used in the job that need to be
196 * released once the job is complete.228 * released once the job is complete.
197 */229 */
198 struct list_head unref_list;230 struct list_head unref_list;
199
200 /* Submitted tile memory allocation start/size, tile state. */
201 u32 qma, qms, qts;
202};231};
203 232
204struct v3d_tfu_job {233struct v3d_tfu_job {
205 struct drm_sched_job base;234 struct v3d_job base;
206 235
207 struct drm_v3d_submit_tfu args;236 struct drm_v3d_submit_tfu args;
237};
208 238
209 /* An optional fence userspace can pass in for the job to depend on. */239struct v3d_csd_job {
210 struct dma_fence *in_fence;240 struct v3d_job base;
211
212 /* v3d fence to be signaled by IRQ handler when the job is complete. */
213 struct dma_fence *irq_fence;
214
215 struct v3d_dev *v3d;
216 241
217 struct kref refcount;242 u32 timedout_batches;
218 243
219 /* This is the array of BOs that were looked up at the start of exec. */244 struct drm_v3d_submit_csd args;
220 struct v3d_bo *bo[4];
221};245};
222 246
223/**247/**
@@ -281,12 +305,14 @@ int v3d_submit_cl_ioctl(struct drm_device *dev, void *data, · 57 unmodified lines
281 struct drm_file *file_priv);305 struct drm_file *file_priv);
282int v3d_submit_tfu_ioctl(struct drm_device *dev, void *data,306int v3d_submit_tfu_ioctl(struct drm_device *dev, void *data,
283 struct drm_file *file_priv);307 struct drm_file *file_priv);
308int v3d_submit_csd_ioctl(struct drm_device *dev, void *data,
309 struct drm_file *file_priv);
284int v3d_wait_bo_ioctl(struct drm_device *dev, void *data,310int v3d_wait_bo_ioctl(struct drm_device *dev, void *data,
285 struct drm_file *file_priv);311 struct drm_file *file_priv);
286void v3d_exec_put(struct v3d_exec_info *exec);312void v3d_job_put(struct v3d_job *job);
287void v3d_tfu_job_put(struct v3d_tfu_job *exec);
288void v3d_reset(struct v3d_dev *v3d);313void v3d_reset(struct v3d_dev *v3d);
289void v3d_invalidate_caches(struct v3d_dev *v3d);314void v3d_invalidate_caches(struct v3d_dev *v3d);
315void v3d_clean_caches(struct v3d_dev *v3d);
290 316
291/* v3d_irq.c */317/* v3d_irq.c */
292int v3d_irq_init(struct v3d_dev *v3d);318int v3d_irq_init(struct v3d_dev *v3d);
drivers/gpu/drm/v3d/v3d_fence.c+2−0
@@ -36,6 +36,8 @@ static const char *v3d_fence_get_timeline_name(struct dma_fence *fence) · 35 unmodified lines
36 return "v3d-render";36 return "v3d-render";
37 case V3D_TFU:37 case V3D_TFU:
38 return "v3d-tfu";38 return "v3d-tfu";
39 case V3D_CSD:
40 return "v3d-csd";
39 default:41 default:
40 return NULL;42 return NULL;
41 }43 }
drivers/gpu/drm/v3d/v3d_gem.c+355−197
@@ -109,7 +109,9 @@ v3d_reset(struct v3d_dev *v3d) · 108 unmodified lines
109{109{
110 struct drm_device *dev = &v3d->drm;110 struct drm_device *dev = &v3d->drm;
111 111
112 DRM_ERROR("Resetting GPU.\n");112 DRM_DEV_ERROR(dev->dev, "Resetting GPU for hang.\n");
113 DRM_DEV_ERROR(dev->dev, "V3D_ERR_STAT: 0x%08x\n",
114 V3D_CORE_READ(0, V3D_ERR_STAT));
113 trace_v3d_reset_begin(dev);115 trace_v3d_reset_begin(dev);
114 116
115 /* XXX: only needed for safe powerdown, not reset. */117 /* XXX: only needed for safe powerdown, not reset. */
@@ -162,10 +164,52 @@ v3d_flush_l2t(struct v3d_dev *v3d, int core) · 46 unmodified lines
162 /* While there is a busy bit (V3D_L2TCACTL_L2TFLS), we don't164 /* While there is a busy bit (V3D_L2TCACTL_L2TFLS), we don't
163 * need to wait for completion before dispatching the job --165 * need to wait for completion before dispatching the job --
164 * L2T accesses will be stalled until the flush has completed.166 * L2T accesses will be stalled until the flush has completed.
167 * However, we do need to make sure we don't try to trigger a
168 * new flush while the L2_CLEAN queue is trying to
169 * synchronously clean after a job.
165 */170 */
171 mutex_lock(&v3d->cache_clean_lock);
166 V3D_CORE_WRITE(core, V3D_CTL_L2TCACTL,172 V3D_CORE_WRITE(core, V3D_CTL_L2TCACTL,
167 V3D_L2TCACTL_L2TFLS |173 V3D_L2TCACTL_L2TFLS |
168 V3D_SET_FIELD(V3D_L2TCACTL_FLM_FLUSH, V3D_L2TCACTL_FLM));174 V3D_SET_FIELD(V3D_L2TCACTL_FLM_FLUSH, V3D_L2TCACTL_FLM));
175 mutex_unlock(&v3d->cache_clean_lock);
176}
177
178/* Cleans texture L1 and L2 cachelines (writing back dirty data).
179 *
180 * For cleaning, which happens from the CACHE_CLEAN queue after CSD has
181 * executed, we need to make sure that the clean is done before
182 * signaling job completion. So, we synchronously wait before
183 * returning, and we make sure that L2 invalidates don't happen in the
184 * meantime to confuse our are-we-done checks.
185 */
186void
187v3d_clean_caches(struct v3d_dev *v3d)
188{
189 struct drm_device *dev = &v3d->drm;
190 int core = 0;
191
192 trace_v3d_cache_clean_begin(dev);
193
194 V3D_CORE_WRITE(core, V3D_CTL_L2TCACTL, V3D_L2TCACTL_TMUWCF);
195 if (wait_for(!(V3D_CORE_READ(core, V3D_CTL_L2TCACTL) &
196 V3D_L2TCACTL_L2TFLS), 100)) {
197 DRM_ERROR("Timeout waiting for L1T write combiner flush\n");
198 }
199
200 mutex_lock(&v3d->cache_clean_lock);
201 V3D_CORE_WRITE(core, V3D_CTL_L2TCACTL,
202 V3D_L2TCACTL_L2TFLS |
203 V3D_SET_FIELD(V3D_L2TCACTL_FLM_CLEAN, V3D_L2TCACTL_FLM));
204
205 if (wait_for(!(V3D_CORE_READ(core, V3D_CTL_L2TCACTL) &
206 V3D_L2TCACTL_L2TFLS), 100)) {
207 DRM_ERROR("Timeout waiting for L2T clean\n");
208 }
209
210 mutex_unlock(&v3d->cache_clean_lock);
211
212 trace_v3d_cache_clean_end(dev);
169}213}
170 214
171/* Invalidates the slice caches. These are read-only caches. */215/* Invalidates the slice caches. These are read-only caches. */
@@ -193,28 +237,6 @@ v3d_invalidate_caches(struct v3d_dev *v3d) · 21 unmodified lines
193 v3d_invalidate_slices(v3d, 0);237 v3d_invalidate_slices(v3d, 0);
194}238}
195 239
196static void
197v3d_attach_object_fences(struct v3d_bo **bos, int bo_count,
198 struct dma_fence *fence)
199{
200 int i;
201
202 for (i = 0; i < bo_count; i++) {
203 /* XXX: Use shared fences for read-only objects. */
204 reservation_object_add_excl_fence(bos[i]->base.base.resv,
205 fence);
206 }
207}
208
209static void
210v3d_unlock_bo_reservations(struct v3d_bo **bos,
211 int bo_count,
212 struct ww_acquire_ctx *acquire_ctx)
213{
214 drm_gem_unlock_reservations((struct drm_gem_object **)bos, bo_count,
215 acquire_ctx);
216}
217
218/* Takes the reservation lock on all the BOs being referenced, so that240/* Takes the reservation lock on all the BOs being referenced, so that
219 * at queue submit time we can update the reservations.241 * at queue submit time we can update the reservations.
220 *242 *
@@ -223,26 +245,21 @@ v3d_unlock_bo_reservations(struct v3d_bo **bos, · 2 unmodified lines
223 * to v3d, so we don't attach dma-buf fences to them.245 * to v3d, so we don't attach dma-buf fences to them.
224 */246 */
225static int247static int
226v3d_lock_bo_reservations(struct v3d_bo **bos,248v3d_lock_bo_reservations(struct v3d_job *job,
227 int bo_count,
228 struct ww_acquire_ctx *acquire_ctx)249 struct ww_acquire_ctx *acquire_ctx)
229{250{
230 int i, ret;251 int i, ret;
231 252
232 ret = drm_gem_lock_reservations((struct drm_gem_object **)bos,253 ret = drm_gem_lock_reservations(job->bo, job->bo_count, acquire_ctx);
233 bo_count, acquire_ctx);
234 if (ret)254 if (ret)
235 return ret;255 return ret;
236 256
237 /* Reserve space for our shared (read-only) fence references,257 for (i = 0; i < job->bo_count; i++) {
238 * before we commit the CL to the hardware.258 ret = drm_gem_fence_array_add_implicit(&job->deps,
239 */259 job->bo[i], true);
240 for (i = 0; i < bo_count; i++) {
241 ret = reservation_object_reserve_shared(bos[i]->base.base.resv,
242 1);
243 if (ret) {260 if (ret) {
244 v3d_unlock_bo_reservations(bos, bo_count,261 drm_gem_unlock_reservations(job->bo, job->bo_count,
245 acquire_ctx);262 acquire_ctx);
246 return ret;263 return ret;
247 }264 }
248 }265 }
@@ -251,11 +268,11 @@ v3d_lock_bo_reservations(struct v3d_bo **bos, · 2 unmodified lines
251}268}
252 269
253/**270/**
254 * v3d_cl_lookup_bos() - Sets up exec->bo[] with the GEM objects271 * v3d_lookup_bos() - Sets up job->bo[] with the GEM objects
255 * referenced by the job.272 * referenced by the job.
256 * @dev: DRM device273 * @dev: DRM device
257 * @file_priv: DRM file for this fd274 * @file_priv: DRM file for this fd
258 * @exec: V3D job being set up275 * @job: V3D job being set up
259 *276 *
260 * The command validator needs to reference BOs by their index within277 * The command validator needs to reference BOs by their index within
261 * the submitted job's BO list. This does the validation of the job's278 * the submitted job's BO list. This does the validation of the job's
@@ -265,18 +282,19 @@ v3d_lock_bo_reservations(struct v3d_bo **bos, · 3 unmodified lines
265 * failure, because that will happen at v3d_exec_cleanup() time.282 * failure, because that will happen at v3d_exec_cleanup() time.
266 */283 */
267static int284static int
268v3d_cl_lookup_bos(struct drm_device *dev,285v3d_lookup_bos(struct drm_device *dev,
269 struct drm_file *file_priv,286 struct drm_file *file_priv,
270 struct drm_v3d_submit_cl *args,287 struct v3d_job *job,
271 struct v3d_exec_info *exec)288 u64 bo_handles,
289 u32 bo_count)
272{290{
273 u32 *handles;291 u32 *handles;
274 int ret = 0;292 int ret = 0;
275 int i;293 int i;
276 294
277 exec->bo_count = args->bo_handle_count;295 job->bo_count = bo_count;
278 296
279 if (!exec->bo_count) {297 if (!job->bo_count) {
280 /* See comment on bo_index for why we have to check298 /* See comment on bo_index for why we have to check
281 * this.299 * this.
282 */300 */
@@ -284,15 +302,15 @@ v3d_cl_lookup_bos(struct drm_device *dev, · 1 unmodified line
284 return -EINVAL;302 return -EINVAL;
285 }303 }
286 304
287 exec->bo = kvmalloc_array(exec->bo_count,305 job->bo = kvmalloc_array(job->bo_count,
288 sizeof(struct drm_gem_cma_object *),306 sizeof(struct drm_gem_cma_object *),
289 GFP_KERNEL | __GFP_ZERO);307 GFP_KERNEL | __GFP_ZERO);
290 if (!exec->bo) {308 if (!job->bo) {
291 DRM_DEBUG("Failed to allocate validated BO pointers\n");309 DRM_DEBUG("Failed to allocate validated BO pointers\n");
292 return -ENOMEM;310 return -ENOMEM;
293 }311 }
294 312
295 handles = kvmalloc_array(exec->bo_count, sizeof(u32), GFP_KERNEL);313 handles = kvmalloc_array(job->bo_count, sizeof(u32), GFP_KERNEL);
296 if (!handles) {314 if (!handles) {
297 ret = -ENOMEM;315 ret = -ENOMEM;
298 DRM_DEBUG("Failed to allocate incoming GEM handles\n");316 DRM_DEBUG("Failed to allocate incoming GEM handles\n");
@@ -300,15 +318,15 @@ v3d_cl_lookup_bos(struct drm_device *dev, · 1 unmodified line
300 }318 }
301 319
302 if (copy_from_user(handles,320 if (copy_from_user(handles,
303 (void __user *)(uintptr_t)args->bo_handles,321 (void __user *)(uintptr_t)bo_handles,
304 exec->bo_count * sizeof(u32))) {322 job->bo_count * sizeof(u32))) {
305 ret = -EFAULT;323 ret = -EFAULT;
306 DRM_DEBUG("Failed to copy in GEM handles\n");324 DRM_DEBUG("Failed to copy in GEM handles\n");
307 goto fail;325 goto fail;
308 }326 }
309 327
310 spin_lock(&file_priv->table_lock);328 spin_lock(&file_priv->table_lock);
311 for (i = 0; i < exec->bo_count; i++) {329 for (i = 0; i < job->bo_count; i++) {
312 struct drm_gem_object *bo = idr_find(&file_priv->object_idr,330 struct drm_gem_object *bo = idr_find(&file_priv->object_idr,
313 handles[i]);331 handles[i]);
314 if (!bo) {332 if (!bo) {
@@ -319,7 +337,7 @@ v3d_cl_lookup_bos(struct drm_device *dev, · 4 unmodified lines
319 goto fail;337 goto fail;
320 }338 }
321 drm_gem_object_get(bo);339 drm_gem_object_get(bo);
322 exec->bo[i] = to_v3d_bo(bo);340 job->bo[i] = bo;
323 }341 }
324 spin_unlock(&file_priv->table_lock);342 spin_unlock(&file_priv->table_lock);
325 343
@@ -329,67 +347,50 @@ fail: · 3 unmodified lines
329}347}
330 348
331static void349static void
332v3d_exec_cleanup(struct kref *ref)350v3d_job_free(struct kref *ref)
333{351{
334 struct v3d_exec_info *exec = container_of(ref, struct v3d_exec_info,352 struct v3d_job *job = container_of(ref, struct v3d_job, refcount);
335 refcount);353 unsigned long index;
336 struct v3d_dev *v3d = exec->v3d;354 struct dma_fence *fence;
337 unsigned int i;355 int i;
338 struct v3d_bo *bo, *save;
339
340 dma_fence_put(exec->bin.in_fence);
341 dma_fence_put(exec->render.in_fence);
342
343 dma_fence_put(exec->bin.irq_fence);
344 dma_fence_put(exec->render.irq_fence);
345
346 dma_fence_put(exec->bin_done_fence);
347 dma_fence_put(exec->render_done_fence);
348 356
349 for (i = 0; i < exec->bo_count; i++)357 for (i = 0; i < job->bo_count; i++) {
350 drm_gem_object_put_unlocked(&exec->bo[i]->base.base);358 if (job->bo[i])
351 kvfree(exec->bo);359 drm_gem_object_put_unlocked(job->bo[i]);
360 }
361 kvfree(job->bo);
352 362
353 list_for_each_entry_safe(bo, save, &exec->unref_list, unref_head) {363 xa_for_each(&job->deps, index, fence) {
354 drm_gem_object_put_unlocked(&bo->base.base);364 dma_fence_put(fence);
355 }365 }
366 xa_destroy(&job->deps);
356 367
357 pm_runtime_mark_last_busy(v3d->dev);368 dma_fence_put(job->irq_fence);
358 pm_runtime_put_autosuspend(v3d->dev);369 dma_fence_put(job->done_fence);
359 370
360 kfree(exec);371 pm_runtime_mark_last_busy(job->v3d->dev);
361}372 pm_runtime_put_autosuspend(job->v3d->dev);
362 373
363void v3d_exec_put(struct v3d_exec_info *exec)374 kfree(job);
364{
365 kref_put(&exec->refcount, v3d_exec_cleanup);
366}375}
367 376
368static void377static void
369v3d_tfu_job_cleanup(struct kref *ref)378v3d_render_job_free(struct kref *ref)
370{379{
371 struct v3d_tfu_job *job = container_of(ref, struct v3d_tfu_job,380 struct v3d_render_job *job = container_of(ref, struct v3d_render_job,
372 refcount);381 base.refcount);
373 struct v3d_dev *v3d = job->v3d;382 struct v3d_bo *bo, *save;
374 unsigned int i;
375
376 dma_fence_put(job->in_fence);
377 dma_fence_put(job->irq_fence);
378 383
379 for (i = 0; i < ARRAY_SIZE(job->bo); i++) {384 list_for_each_entry_safe(bo, save, &job->unref_list, unref_head) {
380 if (job->bo[i])385 drm_gem_object_put_unlocked(&bo->base.base);
381 drm_gem_object_put_unlocked(&job->bo[i]->base.base);
382 }386 }
383 387
384 pm_runtime_mark_last_busy(v3d->dev);388 v3d_job_free(ref);
385 pm_runtime_put_autosuspend(v3d->dev);
386
387 kfree(job);
388}389}
389 390
390void v3d_tfu_job_put(struct v3d_tfu_job *job)391void v3d_job_put(struct v3d_job *job)
391{392{
392 kref_put(&job->refcount, v3d_tfu_job_cleanup);393 kref_put(&job->refcount, job->free);
393}394}
394 395
395int396int
@@ -425,6 +426,87 @@ v3d_wait_bo_ioctl(struct drm_device *dev, void *data, · 29 unmodified lines
425 return ret;426 return ret;
426}427}
427 428
429static int
430v3d_job_init(struct v3d_dev *v3d, struct drm_file *file_priv,
431 struct v3d_job *job, void (*free)(struct kref *ref),
432 u32 in_sync)
433{
434 struct dma_fence *in_fence = NULL;
435 int ret;
436
437 job->v3d = v3d;
438 job->free = free;
439
440 ret = pm_runtime_get_sync(v3d->dev);
441 if (ret < 0)
442 return ret;
443
444 xa_init_flags(&job->deps, XA_FLAGS_ALLOC);
445
446 ret = drm_syncobj_find_fence(file_priv, in_sync, 0, 0, &in_fence);
447 if (ret == -EINVAL)
448 goto fail;
449
450 ret = drm_gem_fence_array_add(&job->deps, in_fence);
451 if (ret)
452 goto fail;
453
454 kref_init(&job->refcount);
455
456 return 0;
457fail:
458 xa_destroy(&job->deps);
459 pm_runtime_put_autosuspend(v3d->dev);
460 return ret;
461}
462
463static int
464v3d_push_job(struct v3d_file_priv *v3d_priv,
465 struct v3d_job *job, enum v3d_queue queue)
466{
467 int ret;
468
469 ret = drm_sched_job_init(&job->base, &v3d_priv->sched_entity[queue],
470 v3d_priv);
471 if (ret)
472 return ret;
473
474 job->done_fence = dma_fence_get(&job->base.s_fence->finished);
475
476 /* put by scheduler job completion */
477 kref_get(&job->refcount);
478
479 drm_sched_entity_push_job(&job->base, &v3d_priv->sched_entity[queue]);
480
481 return 0;
482}
483
484static void
485v3d_attach_fences_and_unlock_reservation(struct drm_file *file_priv,
486 struct v3d_job *job,
487 struct ww_acquire_ctx *acquire_ctx,
488 u32 out_sync,
489 struct dma_fence *done_fence)
490{
491 struct drm_syncobj *sync_out;
492 int i;
493
494 for (i = 0; i < job->bo_count; i++) {
495 /* XXX: Use shared fences for read-only objects. */
496 reservation_object_add_excl_fence(job->bo[i]->resv,
497 job->done_fence);
498 }
499
500 drm_gem_unlock_reservations(job->bo, job->bo_count, acquire_ctx);
501
502 /* Update the return sync object for the job */
503 sync_out = drm_syncobj_find(file_priv, out_sync);
504 if (sync_out) {
505 drm_syncobj_replace_fence(sync_out, done_fence);
506 drm_syncobj_put(sync_out);
507 }
508}
509
428/**510/**
429 * v3d_submit_cl_ioctl() - Submits a job (frame) to the V3D.511 * v3d_submit_cl_ioctl() - Submits a job (frame) to the V3D.
430 * @dev: DRM device512 * @dev: DRM device
@@ -444,9 +526,9 @@ v3d_submit_cl_ioctl(struct drm_device *dev, void *data, · 13 unmodified lines
444 struct v3d_dev *v3d = to_v3d_dev(dev);526 struct v3d_dev *v3d = to_v3d_dev(dev);
445 struct v3d_file_priv *v3d_priv = file_priv->driver_priv;527 struct v3d_file_priv *v3d_priv = file_priv->driver_priv;
446 struct drm_v3d_submit_cl *args = data;528 struct drm_v3d_submit_cl *args = data;
447 struct v3d_exec_info *exec;529 struct v3d_bin_job *bin = NULL;
530 struct v3d_render_job *render;
448 struct ww_acquire_ctx acquire_ctx;531 struct ww_acquire_ctx acquire_ctx;
449 struct drm_syncobj *sync_out;
450 int ret = 0;532 int ret = 0;
451 533
452 trace_v3d_submit_cl_ioctl(&v3d->drm, args->rcl_start, args->rcl_end);534 trace_v3d_submit_cl_ioctl(&v3d->drm, args->rcl_start, args->rcl_end);
@@ -456,100 +538,87 @@ v3d_submit_cl_ioctl(struct drm_device *dev, void *data, · 3 unmodified lines
456 return -EINVAL;538 return -EINVAL;
457 }539 }
458 540
459 exec = kcalloc(1, sizeof(*exec), GFP_KERNEL);541 render = kcalloc(1, sizeof(*render), GFP_KERNEL);
460 if (!exec)542 if (!render)
461 return -ENOMEM;543 return -ENOMEM;
462 544
463 ret = pm_runtime_get_sync(v3d->dev);545 render->start = args->rcl_start;
464 if (ret < 0) {546 render->end = args->rcl_end;
465 kfree(exec);547 INIT_LIST_HEAD(&render->unref_list);
548
549 ret = v3d_job_init(v3d, file_priv, &render->base,
550 v3d_render_job_free, args->in_sync_rcl);
551 if (ret) {
552 kfree(render);
466 return ret;553 return ret;
467 }554 }
468 555
469 kref_init(&exec->refcount);556 if (args->bcl_start != args->bcl_end) {
557 bin = kcalloc(1, sizeof(*bin), GFP_KERNEL);
558 if (!bin)
559 return -ENOMEM;
470 560
471 ret = drm_syncobj_find_fence(file_priv, args->in_sync_bcl,561 ret = v3d_job_init(v3d, file_priv, &bin->base,
472 0, 0, &exec->bin.in_fence);562 v3d_job_free, args->in_sync_bcl);
473 if (ret == -EINVAL)563 if (ret) {
474 goto fail;564 v3d_job_put(&render->base);
565 return ret;
566 }
475 567
476 ret = drm_syncobj_find_fence(file_priv, args->in_sync_rcl,568 bin->start = args->bcl_start;
477 0, 0, &exec->render.in_fence);569 bin->end = args->bcl_end;
478 if (ret == -EINVAL)570 bin->qma = args->qma;
479 goto fail;571 bin->qms = args->qms;
572 bin->qts = args->qts;
573 bin->render = render;
574 }
480 575
481 exec->qma = args->qma;576 ret = v3d_lookup_bos(dev, file_priv, &render->base,
482 exec->qms = args->qms;577 args->bo_handles, args->bo_handle_count);
483 exec->qts = args->qts;
484 exec->bin.exec = exec;
485 exec->bin.start = args->bcl_start;
486 exec->bin.end = args->bcl_end;
487 exec->render.exec = exec;
488 exec->render.start = args->rcl_start;
489 exec->render.end = args->rcl_end;
490 exec->v3d = v3d;
491 INIT_LIST_HEAD(&exec->unref_list);
492
493 ret = v3d_cl_lookup_bos(dev, file_priv, args, exec);
494 if (ret)578 if (ret)
495 goto fail;579 goto fail;
496 580
497 ret = v3d_lock_bo_reservations(exec->bo, exec->bo_count,581 ret = v3d_lock_bo_reservations(&render->base, &acquire_ctx);
498 &acquire_ctx);
499 if (ret)582 if (ret)
500 goto fail;583 goto fail;
501 584
502 mutex_lock(&v3d->sched_lock);585 mutex_lock(&v3d->sched_lock);
503 if (exec->bin.start != exec->bin.end) {586 if (bin) {
504 ret = drm_sched_job_init(&exec->bin.base,587 ret = v3d_push_job(v3d_priv, &bin->base, V3D_BIN);
505 &v3d_priv->sched_entity[V3D_BIN],
506 v3d_priv);
507 if (ret)588 if (ret)
508 goto fail_unreserve;589 goto fail_unreserve;
509 590
510 exec->bin_done_fence =591 ret = drm_gem_fence_array_add(&render->base.deps,
511 dma_fence_get(&exec->bin.base.s_fence->finished);592 dma_fence_get(bin->base.done_fence));
512 593 if (ret)
513 kref_get(&exec->refcount); /* put by scheduler job completion */594 goto fail_unreserve;
514 drm_sched_entity_push_job(&exec->bin.base,
515 &v3d_priv->sched_entity[V3D_BIN]);
516 }595 }
517 596
518 ret = drm_sched_job_init(&exec->render.base,597 ret = v3d_push_job(v3d_priv, &render->base, V3D_RENDER);
519 &v3d_priv->sched_entity[V3D_RENDER],
520 v3d_priv);
521 if (ret)598 if (ret)
522 goto fail_unreserve;599 goto fail_unreserve;
523
524 exec->render_done_fence =
525 dma_fence_get(&exec->render.base.s_fence->finished);
526
527 kref_get(&exec->refcount); /* put by scheduler job completion */
528 drm_sched_entity_push_job(&exec->render.base,
529 &v3d_priv->sched_entity[V3D_RENDER]);
530 mutex_unlock(&v3d->sched_lock);600 mutex_unlock(&v3d->sched_lock);
531 601
532 v3d_attach_object_fences(exec->bo, exec->bo_count,602 v3d_attach_fences_and_unlock_reservation(file_priv,
533 exec->render_done_fence);603 &render->base,
534 604 &acquire_ctx,
535 v3d_unlock_bo_reservations(exec->bo, exec->bo_count, &acquire_ctx);605 args->out_sync,
536 606 render->base.done_fence);
537 /* Update the return sync object for the */
538 sync_out = drm_syncobj_find(file_priv, args->out_sync);
539 if (sync_out) {
540 drm_syncobj_replace_fence(sync_out, exec->render_done_fence);
541 drm_syncobj_put(sync_out);
542 }
543 607
544 v3d_exec_put(exec);608 if (bin)
609 v3d_job_put(&bin->base);
610 v3d_job_put(&render->base);
545 611
546 return 0;612 return 0;
547 613
548fail_unreserve:614fail_unreserve:
549 mutex_unlock(&v3d->sched_lock);615 mutex_unlock(&v3d->sched_lock);
550 v3d_unlock_bo_reservations(exec->bo, exec->bo_count, &acquire_ctx);616 drm_gem_unlock_reservations(render->base.bo,
617 render->base.bo_count, &acquire_ctx);
551fail:618fail:
552 v3d_exec_put(exec);619 if (bin)
620 v3d_job_put(&bin->base);
621 v3d_job_put(&render->base);
553 622
554 return ret;623 return ret;
555}624}
@@ -572,10 +641,7 @@ v3d_submit_tfu_ioctl(struct drm_device *dev, void *data, · 16 unmodified lines
572 struct drm_v3d_submit_tfu *args = data;641 struct drm_v3d_submit_tfu *args = data;
573 struct v3d_tfu_job *job;642 struct v3d_tfu_job *job;
574 struct ww_acquire_ctx acquire_ctx;643 struct ww_acquire_ctx acquire_ctx;
575 struct drm_syncobj *sync_out;
576 struct dma_fence *sched_done_fence;
577 int ret = 0;644 int ret = 0;
578 int bo_count;
579 645
580 trace_v3d_submit_tfu_ioctl(&v3d->drm, args->iia);646 trace_v3d_submit_tfu_ioctl(&v3d->drm, args->iia);
581 647
@@ -583,81 +649,172 @@ v3d_submit_tfu_ioctl(struct drm_device *dev, void *data, · 1 unmodified line
583 if (!job)649 if (!job)
584 return -ENOMEM;650 return -ENOMEM;
585 651
586 ret = pm_runtime_get_sync(v3d->dev);652 ret = v3d_job_init(v3d, file_priv, &job->base,
587 if (ret < 0) {653 v3d_job_free, args->in_sync);
654 if (ret) {
588 kfree(job);655 kfree(job);
589 return ret;656 return ret;
590 }657 }
591 658
592 kref_init(&job->refcount);659 job->base.bo = kcalloc(ARRAY_SIZE(args->bo_handles),
593 660 sizeof(*job->base.bo), GFP_KERNEL);
594 ret = drm_syncobj_find_fence(file_priv, args->in_sync,661 if (!job->base.bo) {
595 0, 0, &job->in_fence);662 v3d_job_put(&job->base);
596 if (ret == -EINVAL)663 return -ENOMEM;
597 goto fail;664 }
598 665
599 job->args = *args;666 job->args = *args;
600 job->v3d = v3d;
601 667
602 spin_lock(&file_priv->table_lock);668 spin_lock(&file_priv->table_lock);
603 for (bo_count = 0; bo_count < ARRAY_SIZE(job->bo); bo_count++) {669 for (job->base.bo_count = 0;
670 job->base.bo_count < ARRAY_SIZE(args->bo_handles);
671 job->base.bo_count++) {
604 struct drm_gem_object *bo;672 struct drm_gem_object *bo;
605 673
606 if (!args->bo_handles[bo_count])674 if (!args->bo_handles[job->base.bo_count])
607 break;675 break;
608 676
609 bo = idr_find(&file_priv->object_idr,677 bo = idr_find(&file_priv->object_idr,
610 args->bo_handles[bo_count]);678 args->bo_handles[job->base.bo_count]);
611 if (!bo) {679 if (!bo) {
612 DRM_DEBUG("Failed to look up GEM BO %d: %d\n",680 DRM_DEBUG("Failed to look up GEM BO %d: %d\n",
613 bo_count, args->bo_handles[bo_count]);681 job->base.bo_count,
682 args->bo_handles[job->base.bo_count]);
614 ret = -ENOENT;683 ret = -ENOENT;
615 spin_unlock(&file_priv->table_lock);684 spin_unlock(&file_priv->table_lock);
616 goto fail;685 goto fail;
617 }686 }
618 drm_gem_object_get(bo);687 drm_gem_object_get(bo);
619 job->bo[bo_count] = to_v3d_bo(bo);688 job->base.bo[job->base.bo_count] = bo;
620 }689 }
621 spin_unlock(&file_priv->table_lock);690 spin_unlock(&file_priv->table_lock);
622 691
623 ret = v3d_lock_bo_reservations(job->bo, bo_count, &acquire_ctx);692 ret = v3d_lock_bo_reservations(&job->base, &acquire_ctx);
624 if (ret)693 if (ret)
625 goto fail;694 goto fail;
626 695
627 mutex_lock(&v3d->sched_lock);696 mutex_lock(&v3d->sched_lock);
628 ret = drm_sched_job_init(&job->base,697 ret = v3d_push_job(v3d_priv, &job->base, V3D_TFU);
629 &v3d_priv->sched_entity[V3D_TFU],
630 v3d_priv);
631 if (ret)698 if (ret)
632 goto fail_unreserve;699 goto fail_unreserve;
700 mutex_unlock(&v3d->sched_lock);
633 701
634 sched_done_fence = dma_fence_get(&job->base.s_fence->finished);702 v3d_attach_fences_and_unlock_reservation(file_priv,
703 &job->base, &acquire_ctx,
704 args->out_sync,
705 job->base.done_fence);
635 706
636 kref_get(&job->refcount); /* put by scheduler job completion */707 v3d_job_put(&job->base);
637 drm_sched_entity_push_job(&job->base, &v3d_priv->sched_entity[V3D_TFU]);708
709 return 0;
710
711fail_unreserve:
638 mutex_unlock(&v3d->sched_lock);712 mutex_unlock(&v3d->sched_lock);
713 drm_gem_unlock_reservations(job->base.bo, job->base.bo_count,
714 &acquire_ctx);
715fail:
716 v3d_job_put(&job->base);
639 717
640 v3d_attach_object_fences(job->bo, bo_count, sched_done_fence);718 return ret;
719}
641 720
642 v3d_unlock_bo_reservations(job->bo, bo_count, &acquire_ctx);721/**
722 * v3d_submit_csd_ioctl() - Submits a CSD (texture formatting) job to the V3D.
723 * @dev: DRM device
724 * @data: ioctl argument
725 * @file_priv: DRM file for this fd
726 *
727 * Userspace provides the register setup for the CSD, which we don't
728 * need to validate since the CSD is behind the MMU.
729 */
730int
731v3d_submit_csd_ioctl(struct drm_device *dev, void *data,
732 struct drm_file *file_priv)
733{
734 struct v3d_dev *v3d = to_v3d_dev(dev);
735 struct v3d_file_priv *v3d_priv = file_priv->driver_priv;
736 struct drm_v3d_submit_csd *args = data;
737 struct v3d_csd_job *job;
738 struct v3d_job *clean_job;
739 struct ww_acquire_ctx acquire_ctx;
740 int ret;
643 741
644 /* Update the return sync object */742 trace_v3d_submit_csd_ioctl(&v3d->drm, args->cfg[5], args->cfg[6]);
645 sync_out = drm_syncobj_find(file_priv, args->out_sync);743
646 if (sync_out) {744 if (!v3d_has_csd(v3d)) {
647 drm_syncobj_replace_fence(sync_out, sched_done_fence);745 DRM_DEBUG("Attempting CSD submit on non-CSD hardware\n");
648 drm_syncobj_put(sync_out);746 return -EINVAL;
747 }
748
749 job = kcalloc(1, sizeof(*job), GFP_KERNEL);
750 if (!job)
751 return -ENOMEM;
752
753 ret = v3d_job_init(v3d, file_priv, &job->base,
754 v3d_job_free, args->in_sync);
755 if (ret) {
756 kfree(job);
757 return ret;
758 }
759
760 clean_job = kcalloc(1, sizeof(*clean_job), GFP_KERNEL);
761 if (!clean_job) {
762 v3d_job_put(&job->base);
763 kfree(job);
764 return -ENOMEM;
649 }765 }
650 dma_fence_put(sched_done_fence);
651 766
652 v3d_tfu_job_put(job);767 ret = v3d_job_init(v3d, file_priv, clean_job, v3d_job_free, 0);
768 if (ret) {
769 v3d_job_put(&job->base);
770 kfree(clean_job);
771 return ret;
772 }
773
774 job->args = *args;
775
776 ret = v3d_lookup_bos(dev, file_priv, clean_job,
777 args->bo_handles, args->bo_handle_count);
778 if (ret)
779 goto fail;
780
781 ret = v3d_lock_bo_reservations(clean_job, &acquire_ctx);
782 if (ret)
783 goto fail;
784
785 mutex_lock(&v3d->sched_lock);
786 ret = v3d_push_job(v3d_priv, &job->base, V3D_CSD);
787 if (ret)
788 goto fail_unreserve;
789
790 ret = drm_gem_fence_array_add(&clean_job->deps,
791 dma_fence_get(job->base.done_fence));
792 if (ret)
793 goto fail_unreserve;
794
795 ret = v3d_push_job(v3d_priv, clean_job, V3D_CACHE_CLEAN);
796 if (ret)
797 goto fail_unreserve;
798 mutex_unlock(&v3d->sched_lock);
799
800 v3d_attach_fences_and_unlock_reservation(file_priv,
801 clean_job,
802 &acquire_ctx,
803 args->out_sync,
804 clean_job->done_fence);
805
806 v3d_job_put(&job->base);
807 v3d_job_put(clean_job);
653 808
654 return 0;809 return 0;
655 810
656fail_unreserve:811fail_unreserve:
657 mutex_unlock(&v3d->sched_lock);812 mutex_unlock(&v3d->sched_lock);
658 v3d_unlock_bo_reservations(job->bo, bo_count, &acquire_ctx);813 drm_gem_unlock_reservations(clean_job->bo, clean_job->bo_count,
814 &acquire_ctx);
659fail:815fail:
660 v3d_tfu_job_put(job);816 v3d_job_put(&job->base);
817 v3d_job_put(clean_job);
661 818
662 return ret;819 return ret;
663}820}
@@ -677,6 +834,7 @@ v3d_gem_init(struct drm_device *dev) · 13 unmodified lines
677 mutex_init(&v3d->bo_lock);834 mutex_init(&v3d->bo_lock);
678 mutex_init(&v3d->reset_lock);835 mutex_init(&v3d->reset_lock);
679 mutex_init(&v3d->sched_lock);836 mutex_init(&v3d->sched_lock);
837 mutex_init(&v3d->cache_clean_lock);
680 838
681 /* Note: We don't allocate address 0. Various bits of HW839 /* Note: We don't allocate address 0. Various bits of HW
682 * treat 0 as special, such as the occlusion query counters840 * treat 0 as special, such as the occlusion query counters
@@ -715,7 +873,7 @@ v3d_gem_destroy(struct drm_device *dev) · 32 unmodified lines
715 873
716 v3d_sched_fini(v3d);874 v3d_sched_fini(v3d);
717 875
718 /* Waiting for exec to finish would need to be done before876 /* Waiting for jobs to finish would need to be done before
719 * unregistering V3D.877 * unregistering V3D.
720 */878 */
721 WARN_ON(v3d->bin_job);879 WARN_ON(v3d->bin_job);
drivers/gpu/drm/v3d/v3d_irq.c+44−11
@@ -4,9 +4,9 @@ · 3 unmodified lines
4/**4/**
5 * DOC: Interrupt management for the V3D engine5 * DOC: Interrupt management for the V3D engine
6 *6 *
7 * When we take a bin, render, or TFU done interrupt, we need to7 * When we take a bin, render, TFU done, or CSD done interrupt, we
8 * signal the fence for that job so that the scheduler can queue up8 * need to signal the fence for that job so that the scheduler can
9 * the next one and unblock any waiters.9 * queue up the next one and unblock any waiters.
10 *10 *
11 * When we take the binner out of memory interrupt, we need to11 * When we take the binner out of memory interrupt, we need to
12 * allocate some new memory and pass it to the binner so that the12 * allocate some new memory and pass it to the binner so that the
@@ -20,6 +20,7 @@ · 7 unmodified lines
20#define V3D_CORE_IRQS ((u32)(V3D_INT_OUTOMEM | \20#define V3D_CORE_IRQS ((u32)(V3D_INT_OUTOMEM | \
21 V3D_INT_FLDONE | \21 V3D_INT_FLDONE | \
22 V3D_INT_FRDONE | \22 V3D_INT_FRDONE | \
23 V3D_INT_CSDDONE | \
23 V3D_INT_GMPV))24 V3D_INT_GMPV))
24 25
25#define V3D_HUB_IRQS ((u32)(V3D_HUB_INT_MMU_WRV | \26#define V3D_HUB_IRQS ((u32)(V3D_HUB_INT_MMU_WRV | \
@@ -62,7 +63,7 @@ v3d_overflow_mem_work(struct work_struct *work) · 36 unmodified lines
62 }63 }
63 64
64 drm_gem_object_get(obj);65 drm_gem_object_get(obj);
65 list_add_tail(&bo->unref_head, &v3d->bin_job->unref_list);66 list_add_tail(&bo->unref_head, &v3d->bin_job->render->unref_list);
66 spin_unlock_irqrestore(&v3d->job_lock, irqflags);67 spin_unlock_irqrestore(&v3d->job_lock, irqflags);
67 68
68 V3D_CORE_WRITE(0, V3D_PTB_BPOA, bo->node.start << PAGE_SHIFT);69 V3D_CORE_WRITE(0, V3D_PTB_BPOA, bo->node.start << PAGE_SHIFT);
@@ -96,7 +97,7 @@ v3d_irq(int irq, void *arg) · 27 unmodified lines
96 97
97 if (intsts & V3D_INT_FLDONE) {98 if (intsts & V3D_INT_FLDONE) {
98 struct v3d_fence *fence =99 struct v3d_fence *fence =
99 to_v3d_fence(v3d->bin_job->bin.irq_fence);100 to_v3d_fence(v3d->bin_job->base.irq_fence);
100 101
101 trace_v3d_bcl_irq(&v3d->drm, fence->seqno);102 trace_v3d_bcl_irq(&v3d->drm, fence->seqno);
102 dma_fence_signal(&fence->base);103 dma_fence_signal(&fence->base);
@@ -105,13 +106,22 @@ v3d_irq(int irq, void *arg) · 2 unmodified lines
105 106
106 if (intsts & V3D_INT_FRDONE) {107 if (intsts & V3D_INT_FRDONE) {
107 struct v3d_fence *fence =108 struct v3d_fence *fence =
108 to_v3d_fence(v3d->render_job->render.irq_fence);109 to_v3d_fence(v3d->render_job->base.irq_fence);
109 110
110 trace_v3d_rcl_irq(&v3d->drm, fence->seqno);111 trace_v3d_rcl_irq(&v3d->drm, fence->seqno);
111 dma_fence_signal(&fence->base);112 dma_fence_signal(&fence->base);
112 status = IRQ_HANDLED;113 status = IRQ_HANDLED;
113 }114 }
114 115
116 if (intsts & V3D_INT_CSDDONE) {
117 struct v3d_fence *fence =
118 to_v3d_fence(v3d->csd_job->base.irq_fence);
119
120 trace_v3d_csd_irq(&v3d->drm, fence->seqno);
121 dma_fence_signal(&fence->base);
122 status = IRQ_HANDLED;
123 }
124
115 /* We shouldn't be triggering these if we have GMP in125 /* We shouldn't be triggering these if we have GMP in
116 * always-allowed mode.126 * always-allowed mode.
117 */127 */
@@ -141,7 +151,7 @@ v3d_hub_irq(int irq, void *arg) · 23 unmodified lines
141 151
142 if (intsts & V3D_HUB_INT_TFUC) {152 if (intsts & V3D_HUB_INT_TFUC) {
143 struct v3d_fence *fence =153 struct v3d_fence *fence =
144 to_v3d_fence(v3d->tfu_job->irq_fence);154 to_v3d_fence(v3d->tfu_job->base.irq_fence);
145 155
146 trace_v3d_tfu_irq(&v3d->drm, fence->seqno);156 trace_v3d_tfu_irq(&v3d->drm, fence->seqno);
147 dma_fence_signal(&fence->base);157 dma_fence_signal(&fence->base);
@@ -152,10 +162,33 @@ v3d_hub_irq(int irq, void *arg) · 4 unmodified lines
152 V3D_HUB_INT_MMU_PTI |162 V3D_HUB_INT_MMU_PTI |
153 V3D_HUB_INT_MMU_CAP)) {163 V3D_HUB_INT_MMU_CAP)) {
154 u32 axi_id = V3D_READ(V3D_MMU_VIO_ID);164 u32 axi_id = V3D_READ(V3D_MMU_VIO_ID);
155 u64 vio_addr = (u64)V3D_READ(V3D_MMU_VIO_ADDR) << 8;165 u64 vio_addr = ((u64)V3D_READ(V3D_MMU_VIO_ADDR) <<
156 166 (v3d->va_width - 32));
157 dev_err(v3d->dev, "MMU error from client %d at 0x%08llx%s%s%s\n",167 static const char *const v3d41_axi_ids[] = {
158 axi_id, (long long)vio_addr,168 "L2T",
169 "PTB",
170 "PSE",
171 "TLB",
172 "CLE",
173 "TFU",
174 "MMU",
175 "GMP",
176 };
177 const char *client = "?";
178
179 V3D_WRITE(V3D_MMU_CTL,
180 V3D_READ(V3D_MMU_CTL) & (V3D_MMU_CTL_CAP_EXCEEDED |
181 V3D_MMU_CTL_PT_INVALID |
182 V3D_MMU_CTL_WRITE_VIOLATION));
183
184 if (v3d->ver >= 41) {
185 axi_id = axi_id >> 5;
186 if (axi_id < ARRAY_SIZE(v3d41_axi_ids))
187 client = v3d41_axi_ids[axi_id];
188 }
189
190 dev_err(v3d->dev, "MMU error from client %s (%d) at 0x%llx%s%s%s\n",
191 client, axi_id, (long long)vio_addr,
159 ((intsts & V3D_HUB_INT_MMU_WRV) ?192 ((intsts & V3D_HUB_INT_MMU_WRV) ?
160 ", write violation" : ""),193 ", write violation" : ""),
161 ((intsts & V3D_HUB_INT_MMU_PTI) ?194 ((intsts & V3D_HUB_INT_MMU_PTI) ?
drivers/gpu/drm/v3d/v3d_mmu.c+5−2
@@ -69,10 +69,13 @@ int v3d_mmu_set_page_table(struct v3d_dev *v3d) · 68 unmodified lines
69 V3D_WRITE(V3D_MMU_PT_PA_BASE, v3d->pt_paddr >> V3D_MMU_PAGE_SHIFT);69 V3D_WRITE(V3D_MMU_PT_PA_BASE, v3d->pt_paddr >> V3D_MMU_PAGE_SHIFT);
70 V3D_WRITE(V3D_MMU_CTL,70 V3D_WRITE(V3D_MMU_CTL,
71 V3D_MMU_CTL_ENABLE |71 V3D_MMU_CTL_ENABLE |
72 V3D_MMU_CTL_PT_INVALID |72 V3D_MMU_CTL_PT_INVALID_ENABLE |
73 V3D_MMU_CTL_PT_INVALID_ABORT |73 V3D_MMU_CTL_PT_INVALID_ABORT |
74 V3D_MMU_CTL_PT_INVALID_INT |
74 V3D_MMU_CTL_WRITE_VIOLATION_ABORT |75 V3D_MMU_CTL_WRITE_VIOLATION_ABORT |
75 V3D_MMU_CTL_CAP_EXCEEDED_ABORT);76 V3D_MMU_CTL_WRITE_VIOLATION_INT |
77 V3D_MMU_CTL_CAP_EXCEEDED_ABORT |
78 V3D_MMU_CTL_CAP_EXCEEDED_INT);
76 V3D_WRITE(V3D_MMU_ILLEGAL_ADDR,79 V3D_WRITE(V3D_MMU_ILLEGAL_ADDR,
77 (v3d->mmu_scratch_paddr >> V3D_MMU_PAGE_SHIFT) |80 (v3d->mmu_scratch_paddr >> V3D_MMU_PAGE_SHIFT) |
78 V3D_MMU_ILLEGAL_ADDR_ENABLE);81 V3D_MMU_ILLEGAL_ADDR_ENABLE);
drivers/gpu/drm/v3d/v3d_regs.h+121−1
@@ -152,7 +152,8 @@ · 151 unmodified lines
152# define V3D_MMU_CTL_PT_INVALID_ABORT BIT(19)152# define V3D_MMU_CTL_PT_INVALID_ABORT BIT(19)
153# define V3D_MMU_CTL_PT_INVALID_INT BIT(18)153# define V3D_MMU_CTL_PT_INVALID_INT BIT(18)
154# define V3D_MMU_CTL_PT_INVALID_EXCEPTION BIT(17)154# define V3D_MMU_CTL_PT_INVALID_EXCEPTION BIT(17)
155# define V3D_MMU_CTL_WRITE_VIOLATION BIT(16)155# define V3D_MMU_CTL_PT_INVALID_ENABLE BIT(16)
156# define V3D_MMU_CTL_WRITE_VIOLATION BIT(12)
156# define V3D_MMU_CTL_WRITE_VIOLATION_ABORT BIT(11)157# define V3D_MMU_CTL_WRITE_VIOLATION_ABORT BIT(11)
157# define V3D_MMU_CTL_WRITE_VIOLATION_INT BIT(10)158# define V3D_MMU_CTL_WRITE_VIOLATION_INT BIT(10)
158# define V3D_MMU_CTL_WRITE_VIOLATION_EXCEPTION BIT(9)159# define V3D_MMU_CTL_WRITE_VIOLATION_EXCEPTION BIT(9)
@@ -191,6 +192,14 @@ · 32 unmodified lines
191/* Address that faulted */192/* Address that faulted */
192#define V3D_MMU_VIO_ADDR 0x01234193#define V3D_MMU_VIO_ADDR 0x01234
193 194
195#define V3D_MMU_DEBUG_INFO 0x01238
196# define V3D_MMU_PA_WIDTH_MASK V3D_MASK(11, 8)
197# define V3D_MMU_PA_WIDTH_SHIFT 8
198# define V3D_MMU_VA_WIDTH_MASK V3D_MASK(7, 4)
199# define V3D_MMU_VA_WIDTH_SHIFT 4
200# define V3D_MMU_VERSION_MASK V3D_MASK(3, 0)
201# define V3D_MMU_VERSION_SHIFT 0
202
194/* Per-V3D-core registers */203/* Per-V3D-core registers */
195 204
196#define V3D_CTL_IDENT0 0x00000205#define V3D_CTL_IDENT0 0x00000
@@ -238,8 +247,11 @@ · 41 unmodified lines
238#define V3D_CTL_L2TCACTL 0x00030247#define V3D_CTL_L2TCACTL 0x00030
239# define V3D_L2TCACTL_TMUWCF BIT(8)248# define V3D_L2TCACTL_TMUWCF BIT(8)
240# define V3D_L2TCACTL_L2T_NO_WM BIT(4)249# define V3D_L2TCACTL_L2T_NO_WM BIT(4)
250/* Invalidates cache lines. */
241# define V3D_L2TCACTL_FLM_FLUSH 0251# define V3D_L2TCACTL_FLM_FLUSH 0
252/* Removes cachelines without writing dirty lines back. */
242# define V3D_L2TCACTL_FLM_CLEAR 1253# define V3D_L2TCACTL_FLM_CLEAR 1
254/* Writes out dirty cachelines and marks them clean, but doesn't invalidate. */
243# define V3D_L2TCACTL_FLM_CLEAN 2255# define V3D_L2TCACTL_FLM_CLEAN 2
244# define V3D_L2TCACTL_FLM_MASK V3D_MASK(2, 1)256# define V3D_L2TCACTL_FLM_MASK V3D_MASK(2, 1)
245# define V3D_L2TCACTL_FLM_SHIFT 1257# define V3D_L2TCACTL_FLM_SHIFT 1
@@ -255,6 +267,8 @@ · 9 unmodified lines
255#define V3D_CTL_INT_MSK_CLR 0x00064267#define V3D_CTL_INT_MSK_CLR 0x00064
256# define V3D_INT_QPU_MASK V3D_MASK(27, 16)268# define V3D_INT_QPU_MASK V3D_MASK(27, 16)
257# define V3D_INT_QPU_SHIFT 16269# define V3D_INT_QPU_SHIFT 16
270# define V3D_INT_CSDDONE BIT(7)
271# define V3D_INT_PCTR BIT(6)
258# define V3D_INT_GMPV BIT(5)272# define V3D_INT_GMPV BIT(5)
259# define V3D_INT_TRFB BIT(4)273# define V3D_INT_TRFB BIT(4)
260# define V3D_INT_SPILLUSE BIT(3)274# define V3D_INT_SPILLUSE BIT(3)
@@ -374,4 +388,110 @@ · 113 unmodified lines
374#define V3D_GMP_PRESERVE_LOAD 0x00818388#define V3D_GMP_PRESERVE_LOAD 0x00818
375#define V3D_GMP_VALID_LINES 0x00820389#define V3D_GMP_VALID_LINES 0x00820
376 390
391#define V3D_CSD_STATUS 0x00900
392# define V3D_CSD_STATUS_NUM_COMPLETED_MASK V3D_MASK(11, 4)
393# define V3D_CSD_STATUS_NUM_COMPLETED_SHIFT 4
394# define V3D_CSD_STATUS_NUM_ACTIVE_MASK V3D_MASK(3, 2)
395# define V3D_CSD_STATUS_NUM_ACTIVE_SHIFT 2
396# define V3D_CSD_STATUS_HAVE_CURRENT_DISPATCH BIT(1)
397# define V3D_CSD_STATUS_HAVE_QUEUED_DISPATCH BIT(0)
398
399#define V3D_CSD_QUEUED_CFG0 0x00904
400# define V3D_CSD_QUEUED_CFG0_NUM_WGS_X_MASK V3D_MASK(31, 16)
401# define V3D_CSD_QUEUED_CFG0_NUM_WGS_X_SHIFT 16
402# define V3D_CSD_QUEUED_CFG0_WG_X_OFFSET_MASK V3D_MASK(15, 0)
403# define V3D_CSD_QUEUED_CFG0_WG_X_OFFSET_SHIFT 0
404
405#define V3D_CSD_QUEUED_CFG1 0x00908
406# define V3D_CSD_QUEUED_CFG1_NUM_WGS_Y_MASK V3D_MASK(31, 16)
407# define V3D_CSD_QUEUED_CFG1_NUM_WGS_Y_SHIFT 16
408# define V3D_CSD_QUEUED_CFG1_WG_Y_OFFSET_MASK V3D_MASK(15, 0)
409# define V3D_CSD_QUEUED_CFG1_WG_Y_OFFSET_SHIFT 0
410
411#define V3D_CSD_QUEUED_CFG2 0x0090c
412# define V3D_CSD_QUEUED_CFG2_NUM_WGS_Z_MASK V3D_MASK(31, 16)
413# define V3D_CSD_QUEUED_CFG2_NUM_WGS_Z_SHIFT 16
414# define V3D_CSD_QUEUED_CFG2_WG_Z_OFFSET_MASK V3D_MASK(15, 0)
415# define V3D_CSD_QUEUED_CFG2_WG_Z_OFFSET_SHIFT 0
416
417#define V3D_CSD_QUEUED_CFG3 0x00910
418# define V3D_CSD_QUEUED_CFG3_OVERLAP_WITH_PREV BIT(26)
419# define V3D_CSD_QUEUED_CFG3_MAX_SG_ID_MASK V3D_MASK(25, 20)
420# define V3D_CSD_QUEUED_CFG3_MAX_SG_ID_SHIFT 20
421# define V3D_CSD_QUEUED_CFG3_BATCHES_PER_SG_M1_MASK V3D_MASK(19, 12)
422# define V3D_CSD_QUEUED_CFG3_BATCHES_PER_SG_M1_SHIFT 12
423# define V3D_CSD_QUEUED_CFG3_WGS_PER_SG_MASK V3D_MASK(11, 8)
424# define V3D_CSD_QUEUED_CFG3_WGS_PER_SG_SHIFT 8
425# define V3D_CSD_QUEUED_CFG3_WG_SIZE_MASK V3D_MASK(7, 0)
426# define V3D_CSD_QUEUED_CFG3_WG_SIZE_SHIFT 0
427
428/* Number of batches, minus 1 */
429#define V3D_CSD_QUEUED_CFG4 0x00914
430
431/* Shader address, pnan, singleseg, threading, like a shader record. */
432#define V3D_CSD_QUEUED_CFG5 0x00918
433
434/* Uniforms address (4 byte aligned) */
435#define V3D_CSD_QUEUED_CFG6 0x0091c
436
437#define V3D_CSD_CURRENT_CFG0 0x00920
438#define V3D_CSD_CURRENT_CFG1 0x00924
439#define V3D_CSD_CURRENT_CFG2 0x00928
440#define V3D_CSD_CURRENT_CFG3 0x0092c
441#define V3D_CSD_CURRENT_CFG4 0x00930
442#define V3D_CSD_CURRENT_CFG5 0x00934
443#define V3D_CSD_CURRENT_CFG6 0x00938
444
445#define V3D_CSD_CURRENT_ID0 0x0093c
446# define V3D_CSD_CURRENT_ID0_WG_X_MASK V3D_MASK(31, 16)
447# define V3D_CSD_CURRENT_ID0_WG_X_SHIFT 16
448# define V3D_CSD_CURRENT_ID0_WG_IN_SG_MASK V3D_MASK(11, 8)
449# define V3D_CSD_CURRENT_ID0_WG_IN_SG_SHIFT 8
450# define V3D_CSD_CURRENT_ID0_L_IDX_MASK V3D_MASK(7, 0)
451# define V3D_CSD_CURRENT_ID0_L_IDX_SHIFT 0
452
453#define V3D_CSD_CURRENT_ID1 0x00940
454# define V3D_CSD_CURRENT_ID0_WG_Z_MASK V3D_MASK(31, 16)
455# define V3D_CSD_CURRENT_ID0_WG_Z_SHIFT 16
456# define V3D_CSD_CURRENT_ID0_WG_Y_MASK V3D_MASK(15, 0)
457# define V3D_CSD_CURRENT_ID0_WG_Y_SHIFT 0
458
459#define V3D_ERR_FDBGO 0x00f04
460#define V3D_ERR_FDBGB 0x00f08
461#define V3D_ERR_FDBGR 0x00f0c
462
463#define V3D_ERR_FDBGS 0x00f10
464# define V3D_ERR_FDBGS_INTERPZ_IP_STALL BIT(17)
465# define V3D_ERR_FDBGS_DEPTHO_FIFO_IP_STALL BIT(16)
466# define V3D_ERR_FDBGS_XYNRM_IP_STALL BIT(14)
467# define V3D_ERR_FDBGS_EZREQ_FIFO_OP_VALID BIT(13)
468# define V3D_ERR_FDBGS_QXYF_FIFO_OP_VALID BIT(12)
469# define V3D_ERR_FDBGS_QXYF_FIFO_OP_LAST BIT(11)
470# define V3D_ERR_FDBGS_EZTEST_ANYQVALID BIT(7)
471# define V3D_ERR_FDBGS_EZTEST_PASS BIT(6)
472# define V3D_ERR_FDBGS_EZTEST_QREADY BIT(5)
473# define V3D_ERR_FDBGS_EZTEST_VLF_OKNOVALID BIT(4)
474# define V3D_ERR_FDBGS_EZTEST_QSTALL BIT(3)
475# define V3D_ERR_FDBGS_EZTEST_IP_VLFSTALL BIT(2)
476# define V3D_ERR_FDBGS_EZTEST_IP_PRSTALL BIT(1)
477# define V3D_ERR_FDBGS_EZTEST_IP_QSTALL BIT(0)
478
479#define V3D_ERR_STAT 0x00f20
480# define V3D_ERR_L2CARE BIT(15)
481# define V3D_ERR_VCMBE BIT(14)
482# define V3D_ERR_VCMRE BIT(13)
483# define V3D_ERR_VCDI BIT(12)
484# define V3D_ERR_VCDE BIT(11)
485# define V3D_ERR_VDWE BIT(10)
486# define V3D_ERR_VPMEAS BIT(9)
487# define V3D_ERR_VPMEFNA BIT(8)
488# define V3D_ERR_VPMEWNA BIT(7)
489# define V3D_ERR_VPMERNA BIT(6)
490# define V3D_ERR_VPMERR BIT(5)
491# define V3D_ERR_VPMEWR BIT(4)
492# define V3D_ERR_VPAERRGL BIT(3)
493# define V3D_ERR_VPAEBRGL BIT(2)
494# define V3D_ERR_VPAERGS BIT(1)
495# define V3D_ERR_VPAEABB BIT(0)
496
377#endif /* V3D_REGS_H */497#endif /* V3D_REGS_H */
drivers/gpu/drm/v3d/v3d_sched.c+250−132
@@ -30,158 +30,152 @@ to_v3d_job(struct drm_sched_job *sched_job) · 29 unmodified lines
30 return container_of(sched_job, struct v3d_job, base);30 return container_of(sched_job, struct v3d_job, base);
31}31}
32 32
33static struct v3d_tfu_job *33static struct v3d_bin_job *
34to_tfu_job(struct drm_sched_job *sched_job)34to_bin_job(struct drm_sched_job *sched_job)
35{35{
36 return container_of(sched_job, struct v3d_tfu_job, base);36 return container_of(sched_job, struct v3d_bin_job, base.base);
37}37}
38 38
39static void39static struct v3d_render_job *
40v3d_job_free(struct drm_sched_job *sched_job)40to_render_job(struct drm_sched_job *sched_job)
41{41{
42 struct v3d_job *job = to_v3d_job(sched_job);42 return container_of(sched_job, struct v3d_render_job, base.base);
43}
43 44
44 drm_sched_job_cleanup(sched_job);45static struct v3d_tfu_job *
46to_tfu_job(struct drm_sched_job *sched_job)
47{
48 return container_of(sched_job, struct v3d_tfu_job, base.base);
49}
45 50
46 v3d_exec_put(job->exec);51static struct v3d_csd_job *
52to_csd_job(struct drm_sched_job *sched_job)
53{
54 return container_of(sched_job, struct v3d_csd_job, base.base);
47}55}
48 56
49static void57static void
50v3d_tfu_job_free(struct drm_sched_job *sched_job)58v3d_job_free(struct drm_sched_job *sched_job)
51{59{
52 struct v3d_tfu_job *job = to_tfu_job(sched_job);60 struct v3d_job *job = to_v3d_job(sched_job);
53 61
54 drm_sched_job_cleanup(sched_job);62 drm_sched_job_cleanup(sched_job);
55 63 v3d_job_put(job);
56 v3d_tfu_job_put(job);
57}64}
58 65
59/**66/**
60 * Returns the fences that the bin or render job depends on, one by one.67 * Returns the fences that the job depends on, one by one.
61 * v3d_job_run() won't be called until all of them have been signaled.68 *
69 * If placed in the scheduler's .dependency method, the corresponding
70 * .run_job won't be called until all of them have been signaled.
62 */71 */
63static struct dma_fence *72static struct dma_fence *
64v3d_job_dependency(struct drm_sched_job *sched_job,73v3d_job_dependency(struct drm_sched_job *sched_job,
65 struct drm_sched_entity *s_entity)74 struct drm_sched_entity *s_entity)
66{75{
67 struct v3d_job *job = to_v3d_job(sched_job);76 struct v3d_job *job = to_v3d_job(sched_job);
68 struct v3d_exec_info *exec = job->exec;
69 enum v3d_queue q = job == &exec->bin ? V3D_BIN : V3D_RENDER;
70 struct dma_fence *fence;
71
72 fence = job->in_fence;
73 if (fence) {
74 job->in_fence = NULL;
75 return fence;
76 }
77
78 if (q == V3D_RENDER) {
79 /* If we had a bin job, the render job definitely depends on
80 * it. We first have to wait for bin to be scheduled, so that
81 * its done_fence is created.
82 */
83 fence = exec->bin_done_fence;
84 if (fence) {
85 exec->bin_done_fence = NULL;
86 return fence;
87 }
88 }
89 77
90 /* XXX: Wait on a fence for switching the GMP if necessary,78 /* XXX: Wait on a fence for switching the GMP if necessary,
91 * and then do so.79 * and then do so.
92 */80 */
93 81
94 return fence;82 if (!xa_empty(&job->deps))
95}83 return xa_erase(&job->deps, job->last_dep++);
96
97/**
98 * Returns the fences that the TFU job depends on, one by one.
99 * v3d_tfu_job_run() won't be called until all of them have been
100 * signaled.
101 */
102static struct dma_fence *
103v3d_tfu_job_dependency(struct drm_sched_job *sched_job,
104 struct drm_sched_entity *s_entity)
105{
106 struct v3d_tfu_job *job = to_tfu_job(sched_job);
107 struct dma_fence *fence;
108
109 fence = job->in_fence;
110 if (fence) {
111 job->in_fence = NULL;
112 return fence;
113 }
114 84
115 return NULL;85 return NULL;
116}86}
117 87
118static struct dma_fence *v3d_job_run(struct drm_sched_job *sched_job)88static struct dma_fence *v3d_bin_job_run(struct drm_sched_job *sched_job)
119{89{
120 struct v3d_job *job = to_v3d_job(sched_job);90 struct v3d_bin_job *job = to_bin_job(sched_job);
121 struct v3d_exec_info *exec = job->exec;91 struct v3d_dev *v3d = job->base.v3d;
122 enum v3d_queue q = job == &exec->bin ? V3D_BIN : V3D_RENDER;
123 struct v3d_dev *v3d = exec->v3d;
124 struct drm_device *dev = &v3d->drm;92 struct drm_device *dev = &v3d->drm;
125 struct dma_fence *fence;93 struct dma_fence *fence;
126 unsigned long irqflags;94 unsigned long irqflags;
127 95
128 if (unlikely(job->base.s_fence->finished.error))96 if (unlikely(job->base.base.s_fence->finished.error))
129 return NULL;97 return NULL;
130 98
131 /* Lock required around bin_job update vs99 /* Lock required around bin_job update vs
132 * v3d_overflow_mem_work().100 * v3d_overflow_mem_work().
133 */101 */
134 spin_lock_irqsave(&v3d->job_lock, irqflags);102 spin_lock_irqsave(&v3d->job_lock, irqflags);
135 if (q == V3D_BIN) {103 v3d->bin_job = job;
136 v3d->bin_job = job->exec;104 /* Clear out the overflow allocation, so we don't
137 105 * reuse the overflow attached to a previous job.
138 /* Clear out the overflow allocation, so we don't106 */
139 * reuse the overflow attached to a previous job.107 V3D_CORE_WRITE(0, V3D_PTB_BPOS, 0);
140 */
141 V3D_CORE_WRITE(0, V3D_PTB_BPOS, 0);
142 } else {
143 v3d->render_job = job->exec;
144 }
145 spin_unlock_irqrestore(&v3d->job_lock, irqflags);108 spin_unlock_irqrestore(&v3d->job_lock, irqflags);
146 109
147 /* Can we avoid this flush when q==RENDER? We need to be110 v3d_invalidate_caches(v3d);
148 * careful of scheduling, though -- imagine job0 rendering to111
149 * texture and job1 reading, and them being executed as bin0,112 fence = v3d_fence_create(v3d, V3D_BIN);
150 * bin1, render0, render1, so that render1's flush at bin time113 if (IS_ERR(fence))
114 return NULL;
115
116 if (job->base.irq_fence)
117 dma_fence_put(job->base.irq_fence);
118 job->base.irq_fence = dma_fence_get(fence);
119
120 trace_v3d_submit_cl(dev, false, to_v3d_fence(fence)->seqno,
121 job->start, job->end);
122
123 /* Set the current and end address of the control list.
124 * Writing the end register is what starts the job.
125 */
126 if (job->qma) {
127 V3D_CORE_WRITE(0, V3D_CLE_CT0QMA, job->qma);
128 V3D_CORE_WRITE(0, V3D_CLE_CT0QMS, job->qms);
129 }
130 if (job->qts) {
131 V3D_CORE_WRITE(0, V3D_CLE_CT0QTS,
132 V3D_CLE_CT0QTS_ENABLE |
133 job->qts);
134 }
135 V3D_CORE_WRITE(0, V3D_CLE_CT0QBA, job->start);
136 V3D_CORE_WRITE(0, V3D_CLE_CT0QEA, job->end);
137
138 return fence;
139}
140
141static struct dma_fence *v3d_render_job_run(struct drm_sched_job *sched_job)
142{
143 struct v3d_render_job *job = to_render_job(sched_job);
144 struct v3d_dev *v3d = job->base.v3d;
145 struct drm_device *dev = &v3d->drm;
146 struct dma_fence *fence;
147
148 if (unlikely(job->base.base.s_fence->finished.error))
149 return NULL;
150
151 v3d->render_job = job;
152
153 /* Can we avoid this flush? We need to be careful of
154 * scheduling, though -- imagine job0 rendering to texture and
155 * job1 reading, and them being executed as bin0, bin1,
156 * render0, render1, so that render1's flush at bin time
151 * wasn't enough.157 * wasn't enough.
152 */158 */
153 v3d_invalidate_caches(v3d);159 v3d_invalidate_caches(v3d);
154 160
155 fence = v3d_fence_create(v3d, q);161 fence = v3d_fence_create(v3d, V3D_RENDER);
156 if (IS_ERR(fence))162 if (IS_ERR(fence))
157 return NULL;163 return NULL;
158 164
159 if (job->irq_fence)165 if (job->base.irq_fence)
160 dma_fence_put(job->irq_fence);166 dma_fence_put(job->base.irq_fence);
161 job->irq_fence = dma_fence_get(fence);167 job->base.irq_fence = dma_fence_get(fence);
162 168
163 trace_v3d_submit_cl(dev, q == V3D_RENDER, to_v3d_fence(fence)->seqno,169 trace_v3d_submit_cl(dev, true, to_v3d_fence(fence)->seqno,
164 job->start, job->end);170 job->start, job->end);
165 171
166 if (q == V3D_BIN) {172 /* XXX: Set the QCFG */
167 if (exec->qma) {
168 V3D_CORE_WRITE(0, V3D_CLE_CT0QMA, exec->qma);
169 V3D_CORE_WRITE(0, V3D_CLE_CT0QMS, exec->qms);
170 }
171 if (exec->qts) {
172 V3D_CORE_WRITE(0, V3D_CLE_CT0QTS,
173 V3D_CLE_CT0QTS_ENABLE |
174 exec->qts);
175 }
176 } else {
177 /* XXX: Set the QCFG */
178 }
179 173
180 /* Set the current and end address of the control list.174 /* Set the current and end address of the control list.
181 * Writing the end register is what starts the job.175 * Writing the end register is what starts the job.
182 */176 */
183 V3D_CORE_WRITE(0, V3D_CLE_CTNQBA(q), job->start);177 V3D_CORE_WRITE(0, V3D_CLE_CT1QBA, job->start);
184 V3D_CORE_WRITE(0, V3D_CLE_CTNQEA(q), job->end);178 V3D_CORE_WRITE(0, V3D_CLE_CT1QEA, job->end);
185 179
186 return fence;180 return fence;
187}181}
@@ -190,7 +184,7 @@ static struct dma_fence * · 2 unmodified lines
190v3d_tfu_job_run(struct drm_sched_job *sched_job)184v3d_tfu_job_run(struct drm_sched_job *sched_job)
191{185{
192 struct v3d_tfu_job *job = to_tfu_job(sched_job);186 struct v3d_tfu_job *job = to_tfu_job(sched_job);
193 struct v3d_dev *v3d = job->v3d;187 struct v3d_dev *v3d = job->base.v3d;
194 struct drm_device *dev = &v3d->drm;188 struct drm_device *dev = &v3d->drm;
195 struct dma_fence *fence;189 struct dma_fence *fence;
196 190
@@ -199,9 +193,9 @@ v3d_tfu_job_run(struct drm_sched_job *sched_job) · 2 unmodified lines
199 return NULL;193 return NULL;
200 194
201 v3d->tfu_job = job;195 v3d->tfu_job = job;
202 if (job->irq_fence)196 if (job->base.irq_fence)
203 dma_fence_put(job->irq_fence);197 dma_fence_put(job->base.irq_fence);
204 job->irq_fence = dma_fence_get(fence);198 job->base.irq_fence = dma_fence_get(fence);
205 199
206 trace_v3d_submit_tfu(dev, to_v3d_fence(fence)->seqno);200 trace_v3d_submit_tfu(dev, to_v3d_fence(fence)->seqno);
207 201
@@ -223,6 +217,48 @@ v3d_tfu_job_run(struct drm_sched_job *sched_job) · 15 unmodified lines
223 return fence;217 return fence;
224}218}
225 219
220static struct dma_fence *
221v3d_csd_job_run(struct drm_sched_job *sched_job)
222{
223 struct v3d_csd_job *job = to_csd_job(sched_job);
224 struct v3d_dev *v3d = job->base.v3d;
225 struct drm_device *dev = &v3d->drm;
226 struct dma_fence *fence;
227 int i;
228
229 v3d->csd_job = job;
230
231 v3d_invalidate_caches(v3d);
232
233 fence = v3d_fence_create(v3d, V3D_CSD);
234 if (IS_ERR(fence))
235 return NULL;
236
237 if (job->base.irq_fence)
238 dma_fence_put(job->base.irq_fence);
239 job->base.irq_fence = dma_fence_get(fence);
240
241 trace_v3d_submit_csd(dev, to_v3d_fence(fence)->seqno);
242
243 for (i = 1; i <= 6; i++)
244 V3D_CORE_WRITE(0, V3D_CSD_QUEUED_CFG0 + 4 * i, job->args.cfg[i]);
245 /* CFG0 write kicks off the job. */
246 V3D_CORE_WRITE(0, V3D_CSD_QUEUED_CFG0, job->args.cfg[0]);
247
248 return fence;
249}
250
251static struct dma_fence *
252v3d_cache_clean_job_run(struct drm_sched_job *sched_job)
253{
254 struct v3d_job *job = to_v3d_job(sched_job);
255 struct v3d_dev *v3d = job->v3d;
256
257 v3d_clean_caches(v3d);
258
259 return NULL;
260}
261
226static void262static void
227v3d_gpu_reset_for_timeout(struct v3d_dev *v3d, struct drm_sched_job *sched_job)263v3d_gpu_reset_for_timeout(struct v3d_dev *v3d, struct drm_sched_job *sched_job)
228{264{
@@ -232,7 +268,7 @@ v3d_gpu_reset_for_timeout(struct v3d_dev *v3d, struct drm_sched_job *sched_job) · 3 unmodified lines
232 268
233 /* block scheduler */269 /* block scheduler */
234 for (q = 0; q < V3D_MAX_QUEUES; q++)270 for (q = 0; q < V3D_MAX_QUEUES; q++)
235 drm_sched_stop(&v3d->queue[q].sched);271 drm_sched_stop(&v3d->queue[q].sched, sched_job);
236 272
237 if (sched_job)273 if (sched_job)
238 drm_sched_increase_karma(sched_job);274 drm_sched_increase_karma(sched_job);
@@ -251,25 +287,23 @@ v3d_gpu_reset_for_timeout(struct v3d_dev *v3d, struct drm_sched_job *sched_job) · 12 unmodified lines
251 mutex_unlock(&v3d->reset_lock);287 mutex_unlock(&v3d->reset_lock);
252}288}
253 289
290/* If the current address or return address have changed, then the GPU
291 * has probably made progress and we should delay the reset. This
292 * could fail if the GPU got in an infinite loop in the CL, but that
293 * is pretty unlikely outside of an i-g-t testcase.
294 */
254static void295static void
255v3d_job_timedout(struct drm_sched_job *sched_job)296v3d_cl_job_timedout(struct drm_sched_job *sched_job, enum v3d_queue q,
297 u32 *timedout_ctca, u32 *timedout_ctra)
256{298{
257 struct v3d_job *job = to_v3d_job(sched_job);299 struct v3d_job *job = to_v3d_job(sched_job);
258 struct v3d_exec_info *exec = job->exec;300 struct v3d_dev *v3d = job->v3d;
259 struct v3d_dev *v3d = exec->v3d;301 u32 ctca = V3D_CORE_READ(0, V3D_CLE_CTNCA(q));
260 enum v3d_queue job_q = job == &exec->bin ? V3D_BIN : V3D_RENDER;302 u32 ctra = V3D_CORE_READ(0, V3D_CLE_CTNRA(q));
261 u32 ctca = V3D_CORE_READ(0, V3D_CLE_CTNCA(job_q));303
262 u32 ctra = V3D_CORE_READ(0, V3D_CLE_CTNRA(job_q));304 if (*timedout_ctca != ctca || *timedout_ctra != ctra) {
263 305 *timedout_ctca = ctca;
264 /* If the current address or return address have changed, then306 *timedout_ctra = ctra;
265 * the GPU has probably made progress and we should delay the
266 * reset. This could fail if the GPU got in an infinite loop
267 * in the CL, but that is pretty unlikely outside of an i-g-t
268 * testcase.
269 */
270 if (job->timedout_ctca != ctca || job->timedout_ctra != ctra) {
271 job->timedout_ctca = ctca;
272 job->timedout_ctra = ctra;
273 return;307 return;
274 }308 }
275 309
@@ -277,25 +311,82 @@ v3d_job_timedout(struct drm_sched_job *sched_job) · 1 unmodified line
277}311}
278 312
279static void313static void
280v3d_tfu_job_timedout(struct drm_sched_job *sched_job)314v3d_bin_job_timedout(struct drm_sched_job *sched_job)
281{315{
282 struct v3d_tfu_job *job = to_tfu_job(sched_job);316 struct v3d_bin_job *job = to_bin_job(sched_job);
317
318 v3d_cl_job_timedout(sched_job, V3D_BIN,
319 &job->timedout_ctca, &job->timedout_ctra);
320}
321
322static void
323v3d_render_job_timedout(struct drm_sched_job *sched_job)
324{
325 struct v3d_render_job *job = to_render_job(sched_job);
326
327 v3d_cl_job_timedout(sched_job, V3D_RENDER,
328 &job->timedout_ctca, &job->timedout_ctra);
329}
330
331static void
332v3d_generic_job_timedout(struct drm_sched_job *sched_job)
333{
334 struct v3d_job *job = to_v3d_job(sched_job);
283 335
284 v3d_gpu_reset_for_timeout(job->v3d, sched_job);336 v3d_gpu_reset_for_timeout(job->v3d, sched_job);
285}337}
286 338
287static const struct drm_sched_backend_ops v3d_sched_ops = {339static void
340v3d_csd_job_timedout(struct drm_sched_job *sched_job)
341{
342 struct v3d_csd_job *job = to_csd_job(sched_job);
343 struct v3d_dev *v3d = job->base.v3d;
344 u32 batches = V3D_CORE_READ(0, V3D_CSD_CURRENT_CFG4);
345
346 /* If we've made progress, skip reset and let the timer get
347 * rearmed.
348 */
349 if (job->timedout_batches != batches) {
350 job->timedout_batches = batches;
351 return;
352 }
353
354 v3d_gpu_reset_for_timeout(v3d, sched_job);
355}
356
357static const struct drm_sched_backend_ops v3d_bin_sched_ops = {
288 .dependency = v3d_job_dependency,358 .dependency = v3d_job_dependency,
289 .run_job = v3d_job_run,359 .run_job = v3d_bin_job_run,
290 .timedout_job = v3d_job_timedout,360 .timedout_job = v3d_bin_job_timedout,
291 .free_job = v3d_job_free361 .free_job = v3d_job_free,
362};
363
364static const struct drm_sched_backend_ops v3d_render_sched_ops = {
365 .dependency = v3d_job_dependency,
366 .run_job = v3d_render_job_run,
367 .timedout_job = v3d_render_job_timedout,
368 .free_job = v3d_job_free,
292};369};
293 370
294static const struct drm_sched_backend_ops v3d_tfu_sched_ops = {371static const struct drm_sched_backend_ops v3d_tfu_sched_ops = {
295 .dependency = v3d_tfu_job_dependency,372 .dependency = v3d_job_dependency,
296 .run_job = v3d_tfu_job_run,373 .run_job = v3d_tfu_job_run,
297 .timedout_job = v3d_tfu_job_timedout,374 .timedout_job = v3d_generic_job_timedout,
298 .free_job = v3d_tfu_job_free375 .free_job = v3d_job_free,
376};
377
378static const struct drm_sched_backend_ops v3d_csd_sched_ops = {
379 .dependency = v3d_job_dependency,
380 .run_job = v3d_csd_job_run,
381 .timedout_job = v3d_csd_job_timedout,
382 .free_job = v3d_job_free
383};
384
385static const struct drm_sched_backend_ops v3d_cache_clean_sched_ops = {
386 .dependency = v3d_job_dependency,
387 .run_job = v3d_cache_clean_job_run,
388 .timedout_job = v3d_generic_job_timedout,
389 .free_job = v3d_job_free
299};390};
300 391
301int392int
@@ -307,7 +398,7 @@ v3d_sched_init(struct v3d_dev *v3d) · 5 unmodified lines
307 int ret;398 int ret;
308 399
309 ret = drm_sched_init(&v3d->queue[V3D_BIN].sched,400 ret = drm_sched_init(&v3d->queue[V3D_BIN].sched,
310 &v3d_sched_ops,401 &v3d_bin_sched_ops,
311 hw_jobs_limit, job_hang_limit,402 hw_jobs_limit, job_hang_limit,
312 msecs_to_jiffies(hang_limit_ms),403 msecs_to_jiffies(hang_limit_ms),
313 "v3d_bin");404 "v3d_bin");
@@ -317,14 +408,14 @@ v3d_sched_init(struct v3d_dev *v3d) · 3 unmodified lines
317 }408 }
318 409
319 ret = drm_sched_init(&v3d->queue[V3D_RENDER].sched,410 ret = drm_sched_init(&v3d->queue[V3D_RENDER].sched,
320 &v3d_sched_ops,411 &v3d_render_sched_ops,
321 hw_jobs_limit, job_hang_limit,412 hw_jobs_limit, job_hang_limit,
322 msecs_to_jiffies(hang_limit_ms),413 msecs_to_jiffies(hang_limit_ms),
323 "v3d_render");414 "v3d_render");
324 if (ret) {415 if (ret) {
325 dev_err(v3d->dev, "Failed to create render scheduler: %d.",416 dev_err(v3d->dev, "Failed to create render scheduler: %d.",
326 ret);417 ret);
327 drm_sched_fini(&v3d->queue[V3D_BIN].sched);418 v3d_sched_fini(v3d);
328 return ret;419 return ret;
329 }420 }
330 421
@@ -336,11 +427,36 @@ v3d_sched_init(struct v3d_dev *v3d) · 5 unmodified lines
336 if (ret) {427 if (ret) {
337 dev_err(v3d->dev, "Failed to create TFU scheduler: %d.",428 dev_err(v3d->dev, "Failed to create TFU scheduler: %d.",
338 ret);429 ret);
339 drm_sched_fini(&v3d->queue[V3D_RENDER].sched);430 v3d_sched_fini(v3d);
340 drm_sched_fini(&v3d->queue[V3D_BIN].sched);
341 return ret;431 return ret;
342 }432 }
343 433
434 if (v3d_has_csd(v3d)) {
435 ret = drm_sched_init(&v3d->queue[V3D_CSD].sched,
436 &v3d_csd_sched_ops,
437 hw_jobs_limit, job_hang_limit,
438 msecs_to_jiffies(hang_limit_ms),
439 "v3d_csd");
440 if (ret) {
441 dev_err(v3d->dev, "Failed to create CSD scheduler: %d.",
442 ret);
443 v3d_sched_fini(v3d);
444 return ret;
445 }
446
447 ret = drm_sched_init(&v3d->queue[V3D_CACHE_CLEAN].sched,
448 &v3d_cache_clean_sched_ops,
449 hw_jobs_limit, job_hang_limit,
450 msecs_to_jiffies(hang_limit_ms),
451 "v3d_cache_clean");
452 if (ret) {
453 dev_err(v3d->dev, "Failed to create CACHE_CLEAN scheduler: %d.",
454 ret);
455 v3d_sched_fini(v3d);
456 return ret;
457 }
458 }
459
344 return 0;460 return 0;
345}461}
346 462
@@ -349,6 +465,8 @@ v3d_sched_fini(struct v3d_dev *v3d) · 2 unmodified lines
349{465{
350 enum v3d_queue q;466 enum v3d_queue q;
351 467
352 for (q = 0; q < V3D_MAX_QUEUES; q++)468 for (q = 0; q < V3D_MAX_QUEUES; q++) {
353 drm_sched_fini(&v3d->queue[q].sched);469 if (v3d->queue[q].sched.ready)
470 drm_sched_fini(&v3d->queue[q].sched);
471 }
354}472}
drivers/gpu/drm/v3d/v3d_trace.h+94−0
@@ -124,6 +124,26 @@ TRACE_EVENT(v3d_tfu_irq, · 123 unmodified lines
124 __entry->seqno)124 __entry->seqno)
125);125);
126 126
127TRACE_EVENT(v3d_csd_irq,
128 TP_PROTO(struct drm_device *dev,
129 uint64_t seqno),
130 TP_ARGS(dev, seqno),
131
132 TP_STRUCT__entry(
133 __field(u32, dev)
134 __field(u64, seqno)
135 ),
136
137 TP_fast_assign(
138 __entry->dev = dev->primary->index;
139 __entry->seqno = seqno;
140 ),
141
142 TP_printk("dev=%u, seqno=%llu",
143 __entry->dev,
144 __entry->seqno)
145);
146
127TRACE_EVENT(v3d_submit_tfu_ioctl,147TRACE_EVENT(v3d_submit_tfu_ioctl,
128 TP_PROTO(struct drm_device *dev, u32 iia),148 TP_PROTO(struct drm_device *dev, u32 iia),
129 TP_ARGS(dev, iia),149 TP_ARGS(dev, iia),
@@ -163,6 +183,80 @@ TRACE_EVENT(v3d_submit_tfu, · 33 unmodified lines
163 __entry->seqno)183 __entry->seqno)
164);184);
165 185
186TRACE_EVENT(v3d_submit_csd_ioctl,
187 TP_PROTO(struct drm_device *dev, u32 cfg5, u32 cfg6),
188 TP_ARGS(dev, cfg5, cfg6),
189
190 TP_STRUCT__entry(
191 __field(u32, dev)
192 __field(u32, cfg5)
193 __field(u32, cfg6)
194 ),
195
196 TP_fast_assign(
197 __entry->dev = dev->primary->index;
198 __entry->cfg5 = cfg5;
199 __entry->cfg6 = cfg6;
200 ),
201
202 TP_printk("dev=%u, CFG5 0x%08x, CFG6 0x%08x",
203 __entry->dev,
204 __entry->cfg5,
205 __entry->cfg6)
206);
207
208TRACE_EVENT(v3d_submit_csd,
209 TP_PROTO(struct drm_device *dev,
210 uint64_t seqno),
211 TP_ARGS(dev, seqno),
212
213 TP_STRUCT__entry(
214 __field(u32, dev)
215 __field(u64, seqno)
216 ),
217
218 TP_fast_assign(
219 __entry->dev = dev->primary->index;
220 __entry->seqno = seqno;
221 ),
222
223 TP_printk("dev=%u, seqno=%llu",
224 __entry->dev,
225 __entry->seqno)
226);
227
228TRACE_EVENT(v3d_cache_clean_begin,
229 TP_PROTO(struct drm_device *dev),
230 TP_ARGS(dev),
231
232 TP_STRUCT__entry(
233 __field(u32, dev)
234 ),
235
236 TP_fast_assign(
237 __entry->dev = dev->primary->index;
238 ),
239
240 TP_printk("dev=%u",
241 __entry->dev)
242);
243
244TRACE_EVENT(v3d_cache_clean_end,
245 TP_PROTO(struct drm_device *dev),
246 TP_ARGS(dev),
247
248 TP_STRUCT__entry(
249 __field(u32, dev)
250 ),
251
252 TP_fast_assign(
253 __entry->dev = dev->primary->index;
254 ),
255
256 TP_printk("dev=%u",
257 __entry->dev)
258);
259
166TRACE_EVENT(v3d_reset_begin,260TRACE_EVENT(v3d_reset_begin,
167 TP_PROTO(struct drm_device *dev),261 TP_PROTO(struct drm_device *dev),
168 TP_ARGS(dev),262 TP_ARGS(dev),
drivers/gpu/drm/vboxvideo/Kconfig+1−1
@@ -3,7 +3,7 @@ config DRM_VBOXVIDEO · 2 unmodified lines
3 tristate "Virtual Box Graphics Card"3 tristate "Virtual Box Graphics Card"
4 depends on DRM && X86 && PCI4 depends on DRM && X86 && PCI
5 select DRM_KMS_HELPER5 select DRM_KMS_HELPER
6 select DRM_TTM6 select DRM_VRAM_HELPER
7 select GENERIC_ALLOCATOR7 select GENERIC_ALLOCATOR
8 help8 help
9 This is a KMS driver for the virtual Graphics Card used in9 This is a KMS driver for the virtual Graphics Card used in
drivers/gpu/drm/vboxvideo/vbox_drv.c+2−10
@@ -191,13 +191,7 @@ static struct pci_driver vbox_pci_driver = { · 190 unmodified lines
191 191
192static const struct file_operations vbox_fops = {192static const struct file_operations vbox_fops = {
193 .owner = THIS_MODULE,193 .owner = THIS_MODULE,
194 .open = drm_open,194 DRM_VRAM_MM_FILE_OPERATIONS
195 .release = drm_release,
196 .unlocked_ioctl = drm_ioctl,
197 .compat_ioctl = drm_compat_ioctl,
198 .mmap = vbox_mmap,
199 .poll = drm_poll,
200 .read = drm_read,
201};195};
202 196
203static struct drm_driver driver = {197static struct drm_driver driver = {
@@ -215,9 +209,7 @@ static struct drm_driver driver = { · 11 unmodified lines
215 .minor = DRIVER_MINOR,209 .minor = DRIVER_MINOR,
216 .patchlevel = DRIVER_PATCHLEVEL,210 .patchlevel = DRIVER_PATCHLEVEL,
217 211
218 .gem_free_object_unlocked = vbox_gem_free_object,212 DRM_GEM_VRAM_DRIVER,
219 .dumb_create = vbox_dumb_create,
220 .dumb_map_offset = vbox_dumb_mmap_offset,
221 .prime_handle_to_fd = drm_gem_prime_handle_to_fd,213 .prime_handle_to_fd = drm_gem_prime_handle_to_fd,
222 .prime_fd_to_handle = drm_gem_prime_fd_to_handle,214 .prime_fd_to_handle = drm_gem_prime_fd_to_handle,
223 .gem_prime_export = drm_gem_prime_export,215 .gem_prime_export = drm_gem_prime_export,
drivers/gpu/drm/vboxvideo/vbox_drv.h+2−73
@@ -18,12 +18,9 @@ · 17 unmodified lines
18#include <drm/drm_encoder.h>18#include <drm/drm_encoder.h>
19#include <drm/drm_fb_helper.h>19#include <drm/drm_fb_helper.h>
20#include <drm/drm_gem.h>20#include <drm/drm_gem.h>
21#include <drm/drm_gem_vram_helper.h>
21 22
22#include <drm/ttm/ttm_bo_api.h>23#include <drm/drm_vram_mm_helper.h>
23#include <drm/ttm/ttm_bo_driver.h>
24#include <drm/ttm/ttm_placement.h>
25#include <drm/ttm/ttm_memory.h>
26#include <drm/ttm/ttm_module.h>
27 24
28#include "vboxvideo_guest.h"25#include "vboxvideo_guest.h"
29#include "vboxvideo_vbe.h"26#include "vboxvideo_vbe.h"
@@ -77,10 +74,6 @@ struct vbox_private { · 47 unmodified lines
77 74
78 int fb_mtrr;75 int fb_mtrr;
79 76
80 struct {
81 struct ttm_bo_device bdev;
82 } ttm;
83
84 struct mutex hw_mutex; /* protects modeset and accel/vbva accesses */77 struct mutex hw_mutex; /* protects modeset and accel/vbva accesses */
85 struct work_struct hotplug_work;78 struct work_struct hotplug_work;
86 u32 input_mapping_width;79 u32 input_mapping_width;
@@ -96,8 +89,6 @@ struct vbox_private { · 9 unmodified lines
96#undef CURSOR_PIXEL_COUNT89#undef CURSOR_PIXEL_COUNT
97#undef CURSOR_DATA_SIZE90#undef CURSOR_DATA_SIZE
98 91
99struct vbox_gem_object;
100
101struct vbox_connector {92struct vbox_connector {
102 struct drm_connector base;93 struct drm_connector base;
103 char name[32];94 char name[32];
@@ -170,74 +161,12 @@ int vboxfb_create(struct drm_fb_helper *helper, · 66 unmodified lines
170 struct drm_fb_helper_surface_size *sizes);161 struct drm_fb_helper_surface_size *sizes);
171void vbox_fbdev_fini(struct vbox_private *vbox);162void vbox_fbdev_fini(struct vbox_private *vbox);
172 163
173struct vbox_bo {
174 struct ttm_buffer_object bo;
175 struct ttm_placement placement;
176 struct ttm_bo_kmap_obj kmap;
177 struct drm_gem_object gem;
178 struct ttm_place placements[3];
179 int pin_count;
180};
181
182#define gem_to_vbox_bo(gobj) container_of((gobj), struct vbox_bo, gem)
183
184static inline struct vbox_bo *vbox_bo(struct ttm_buffer_object *bo)
185{
186 return container_of(bo, struct vbox_bo, bo);
187}
188
189#define to_vbox_obj(x) container_of(x, struct vbox_gem_object, base)
190
191static inline u64 vbox_bo_gpu_offset(struct vbox_bo *bo)
192{
193 return bo->bo.offset;
194}
195
196int vbox_dumb_create(struct drm_file *file,
197 struct drm_device *dev,
198 struct drm_mode_create_dumb *args);
199
200void vbox_gem_free_object(struct drm_gem_object *obj);
201int vbox_dumb_mmap_offset(struct drm_file *file,
202 struct drm_device *dev,
203 u32 handle, u64 *offset);
204
205int vbox_mm_init(struct vbox_private *vbox);164int vbox_mm_init(struct vbox_private *vbox);
206void vbox_mm_fini(struct vbox_private *vbox);165void vbox_mm_fini(struct vbox_private *vbox);
207 166
208int vbox_bo_create(struct vbox_private *vbox, int size, int align,
209 u32 flags, struct vbox_bo **pvboxbo);
210
211int vbox_gem_create(struct vbox_private *vbox,167int vbox_gem_create(struct vbox_private *vbox,
212 u32 size, bool iskernel, struct drm_gem_object **obj);168 u32 size, bool iskernel, struct drm_gem_object **obj);
213 169
214int vbox_bo_pin(struct vbox_bo *bo, u32 pl_flag);
215int vbox_bo_unpin(struct vbox_bo *bo);
216
217static inline int vbox_bo_reserve(struct vbox_bo *bo, bool no_wait)
218{
219 int ret;
220
221 ret = ttm_bo_reserve(&bo->bo, true, no_wait, NULL);
222 if (ret) {
223 if (ret != -ERESTARTSYS && ret != -EBUSY)
224 DRM_ERROR("reserve failed %p\n", bo);
225 return ret;
226 }
227 return 0;
228}
229
230static inline void vbox_bo_unreserve(struct vbox_bo *bo)
231{
232 ttm_bo_unreserve(&bo->bo);
233}
234
235void vbox_ttm_placement(struct vbox_bo *bo, int domain);
236int vbox_bo_push_sysram(struct vbox_bo *bo);
237int vbox_mmap(struct file *filp, struct vm_area_struct *vma);
238void *vbox_bo_kmap(struct vbox_bo *bo);
239void vbox_bo_kunmap(struct vbox_bo *bo);
240
241/* vbox_prime.c */170/* vbox_prime.c */
242int vbox_gem_prime_pin(struct drm_gem_object *obj);171int vbox_gem_prime_pin(struct drm_gem_object *obj);
243void vbox_gem_prime_unpin(struct drm_gem_object *obj);172void vbox_gem_prime_unpin(struct drm_gem_object *obj);
drivers/gpu/drm/vboxvideo/vbox_fb.c+11−11
@@ -51,9 +51,9 @@ int vboxfb_create(struct drm_fb_helper *helper, · 50 unmodified lines
51 struct drm_framebuffer *fb;51 struct drm_framebuffer *fb;
52 struct fb_info *info;52 struct fb_info *info;
53 struct drm_gem_object *gobj;53 struct drm_gem_object *gobj;
54 struct vbox_bo *bo;54 struct drm_gem_vram_object *gbo;
55 int size, ret;55 int size, ret;
56 u64 gpu_addr;56 s64 gpu_addr;
57 u32 pitch;57 u32 pitch;
58 58
59 mode_cmd.width = sizes->surface_width;59 mode_cmd.width = sizes->surface_width;
@@ -75,9 +75,9 @@ int vboxfb_create(struct drm_fb_helper *helper, · 15 unmodified lines
75 if (ret)75 if (ret)
76 return ret;76 return ret;
77 77
78 bo = gem_to_vbox_bo(gobj);78 gbo = drm_gem_vram_of_gem(gobj);
79 79
80 ret = vbox_bo_pin(bo, TTM_PL_FLAG_VRAM);80 ret = drm_gem_vram_pin(gbo, DRM_GEM_VRAM_PL_FLAG_VRAM);
81 if (ret)81 if (ret)
82 return ret;82 return ret;
83 83
@@ -86,7 +86,7 @@ int vboxfb_create(struct drm_fb_helper *helper, · 2 unmodified lines
86 return PTR_ERR(info);86 return PTR_ERR(info);
87 87
88 info->screen_size = size;88 info->screen_size = size;
89 info->screen_base = (char __iomem *)vbox_bo_kmap(bo);89 info->screen_base = (char __iomem *)drm_gem_vram_kmap(gbo, true, NULL);
90 if (IS_ERR(info->screen_base))90 if (IS_ERR(info->screen_base))
91 return PTR_ERR(info->screen_base);91 return PTR_ERR(info->screen_base);
92 92
@@ -104,7 +104,9 @@ int vboxfb_create(struct drm_fb_helper *helper, · 11 unmodified lines
104 104
105 drm_fb_helper_fill_info(info, helper, sizes);105 drm_fb_helper_fill_info(info, helper, sizes);
106 106
107 gpu_addr = vbox_bo_gpu_offset(bo);107 gpu_addr = drm_gem_vram_offset(gbo);
108 if (gpu_addr < 0)
109 return (int)gpu_addr;
108 info->fix.smem_start = info->apertures->ranges[0].base + gpu_addr;110 info->fix.smem_start = info->apertures->ranges[0].base + gpu_addr;
109 info->fix.smem_len = vbox->available_vram_size - gpu_addr;111 info->fix.smem_len = vbox->available_vram_size - gpu_addr;
110 112
@@ -132,12 +134,10 @@ void vbox_fbdev_fini(struct vbox_private *vbox) · 21 unmodified lines
132 drm_fb_helper_unregister_fbi(&vbox->fb_helper);134 drm_fb_helper_unregister_fbi(&vbox->fb_helper);
133 135
134 if (afb->obj) {136 if (afb->obj) {
135 struct vbox_bo *bo = gem_to_vbox_bo(afb->obj);137 struct drm_gem_vram_object *gbo = drm_gem_vram_of_gem(afb->obj);
136 138
137 vbox_bo_kunmap(bo);139 drm_gem_vram_kunmap(gbo);
138 140 drm_gem_vram_unpin(gbo);
139 if (bo->pin_count)
140 vbox_bo_unpin(bo);
141 141
142 drm_gem_object_put_unlocked(afb->obj);142 drm_gem_object_put_unlocked(afb->obj);
143 afb->obj = NULL;143 afb->obj = NULL;
drivers/gpu/drm/vboxvideo/vbox_main.c+6−69
@@ -274,7 +274,7 @@ void vbox_hw_fini(struct vbox_private *vbox) · 273 unmodified lines
274int vbox_gem_create(struct vbox_private *vbox,274int vbox_gem_create(struct vbox_private *vbox,
275 u32 size, bool iskernel, struct drm_gem_object **obj)275 u32 size, bool iskernel, struct drm_gem_object **obj)
276{276{
277 struct vbox_bo *vboxbo;277 struct drm_gem_vram_object *gbo;
278 int ret;278 int ret;
279 279
280 *obj = NULL;280 *obj = NULL;
@@ -283,79 +283,16 @@ int vbox_gem_create(struct vbox_private *vbox, · 2 unmodified lines
283 if (size == 0)283 if (size == 0)
284 return -EINVAL;284 return -EINVAL;
285 285
286 ret = vbox_bo_create(vbox, size, 0, 0, &vboxbo);286 gbo = drm_gem_vram_create(&vbox->ddev, &vbox->ddev.vram_mm->bdev,
287 if (ret) {287 size, 0, false);
288 if (IS_ERR(gbo)) {
289 ret = PTR_ERR(gbo);
288 if (ret != -ERESTARTSYS)290 if (ret != -ERESTARTSYS)
289 DRM_ERROR("failed to allocate GEM object\n");291 DRM_ERROR("failed to allocate GEM object\n");
290 return ret;292 return ret;
291 }293 }
292 294
293 *obj = &vboxbo->gem;295 *obj = &gbo->gem;
294
295 return 0;
296}
297
298int vbox_dumb_create(struct drm_file *file,
299 struct drm_device *dev, struct drm_mode_create_dumb *args)
300{
301 struct vbox_private *vbox =
302 container_of(dev, struct vbox_private, ddev);
303 struct drm_gem_object *gobj;
304 u32 handle;
305 int ret;
306
307 args->pitch = args->width * ((args->bpp + 7) / 8);
308 args->size = args->pitch * args->height;
309
310 ret = vbox_gem_create(vbox, args->size, false, &gobj);
311 if (ret)
312 return ret;
313
314 ret = drm_gem_handle_create(file, gobj, &handle);
315 drm_gem_object_put_unlocked(gobj);
316 if (ret)
317 return ret;
318
319 args->handle = handle;
320 296
321 return 0;297 return 0;
322}298}
323
324void vbox_gem_free_object(struct drm_gem_object *obj)
325{
326 struct vbox_bo *vbox_bo = gem_to_vbox_bo(obj);
327
328 ttm_bo_put(&vbox_bo->bo);
329}
330
331static inline u64 vbox_bo_mmap_offset(struct vbox_bo *bo)
332{
333 return drm_vma_node_offset_addr(&bo->bo.vma_node);
334}
335
336int
337vbox_dumb_mmap_offset(struct drm_file *file,
338 struct drm_device *dev,
339 u32 handle, u64 *offset)
340{
341 struct drm_gem_object *obj;
342 int ret;
343 struct vbox_bo *bo;
344
345 mutex_lock(&dev->struct_mutex);
346 obj = drm_gem_object_lookup(file, handle);
347 if (!obj) {
348 ret = -ENOENT;
349 goto out_unlock;
350 }
351
352 bo = gem_to_vbox_bo(obj);
353 *offset = vbox_bo_mmap_offset(bo);
354
355 drm_gem_object_put(obj);
356 ret = 0;
357
358out_unlock:
359 mutex_unlock(&dev->struct_mutex);
360 return ret;
361}
drivers/gpu/drm/vboxvideo/vbox_mode.c+19−17
@@ -172,7 +172,8 @@ static void vbox_crtc_set_base_and_mode(struct drm_crtc *crtc, · 171 unmodified lines
172 struct drm_framebuffer *fb,172 struct drm_framebuffer *fb,
173 int x, int y)173 int x, int y)
174{174{
175 struct vbox_bo *bo = gem_to_vbox_bo(to_vbox_framebuffer(fb)->obj);175 struct drm_gem_vram_object *gbo =
176 drm_gem_vram_of_gem(to_vbox_framebuffer(fb)->obj);
176 struct vbox_private *vbox = crtc->dev->dev_private;177 struct vbox_private *vbox = crtc->dev->dev_private;
177 struct vbox_crtc *vbox_crtc = to_vbox_crtc(crtc);178 struct vbox_crtc *vbox_crtc = to_vbox_crtc(crtc);
178 bool needs_modeset = drm_atomic_crtc_needs_modeset(crtc->state);179 bool needs_modeset = drm_atomic_crtc_needs_modeset(crtc->state);
@@ -186,7 +187,7 @@ static void vbox_crtc_set_base_and_mode(struct drm_crtc *crtc, · 7 unmodified lines
186 187
187 vbox_crtc->x = x;188 vbox_crtc->x = x;
188 vbox_crtc->y = y;189 vbox_crtc->y = y;
189 vbox_crtc->fb_offset = vbox_bo_gpu_offset(bo);190 vbox_crtc->fb_offset = drm_gem_vram_offset(gbo);
190 191
191 /* vbox_do_modeset() checks vbox->single_framebuffer so update it now */192 /* vbox_do_modeset() checks vbox->single_framebuffer so update it now */
192 if (needs_modeset && vbox_set_up_input_mapping(vbox)) {193 if (needs_modeset && vbox_set_up_input_mapping(vbox)) {
@@ -302,14 +303,14 @@ static void vbox_primary_atomic_disable(struct drm_plane *plane, · 109 unmodified lines
302static int vbox_primary_prepare_fb(struct drm_plane *plane,303static int vbox_primary_prepare_fb(struct drm_plane *plane,
303 struct drm_plane_state *new_state)304 struct drm_plane_state *new_state)
304{305{
305 struct vbox_bo *bo;306 struct drm_gem_vram_object *gbo;
306 int ret;307 int ret;
307 308
308 if (!new_state->fb)309 if (!new_state->fb)
309 return 0;310 return 0;
310 311
311 bo = gem_to_vbox_bo(to_vbox_framebuffer(new_state->fb)->obj);312 gbo = drm_gem_vram_of_gem(to_vbox_framebuffer(new_state->fb)->obj);
312 ret = vbox_bo_pin(bo, TTM_PL_FLAG_VRAM);313 ret = drm_gem_vram_pin(gbo, DRM_GEM_VRAM_PL_FLAG_VRAM);
313 if (ret)314 if (ret)
314 DRM_WARN("Error %d pinning new fb, out of video mem?\n", ret);315 DRM_WARN("Error %d pinning new fb, out of video mem?\n", ret);
315 316
@@ -319,13 +320,13 @@ static int vbox_primary_prepare_fb(struct drm_plane *plane, · 3 unmodified lines
319static void vbox_primary_cleanup_fb(struct drm_plane *plane,320static void vbox_primary_cleanup_fb(struct drm_plane *plane,
320 struct drm_plane_state *old_state)321 struct drm_plane_state *old_state)
321{322{
322 struct vbox_bo *bo;323 struct drm_gem_vram_object *gbo;
323 324
324 if (!old_state->fb)325 if (!old_state->fb)
325 return;326 return;
326 327
327 bo = gem_to_vbox_bo(to_vbox_framebuffer(old_state->fb)->obj);328 gbo = drm_gem_vram_of_gem(to_vbox_framebuffer(old_state->fb)->obj);
328 vbox_bo_unpin(bo);329 drm_gem_vram_unpin(gbo);
329}330}
330 331
331static int vbox_cursor_atomic_check(struct drm_plane *plane,332static int vbox_cursor_atomic_check(struct drm_plane *plane,
@@ -385,7 +386,8 @@ static void vbox_cursor_atomic_update(struct drm_plane *plane, · 53 unmodified lines
385 container_of(plane->dev, struct vbox_private, ddev);386 container_of(plane->dev, struct vbox_private, ddev);
386 struct vbox_crtc *vbox_crtc = to_vbox_crtc(plane->state->crtc);387 struct vbox_crtc *vbox_crtc = to_vbox_crtc(plane->state->crtc);
387 struct drm_framebuffer *fb = plane->state->fb;388 struct drm_framebuffer *fb = plane->state->fb;
388 struct vbox_bo *bo = gem_to_vbox_bo(to_vbox_framebuffer(fb)->obj);389 struct drm_gem_vram_object *gbo =
390 drm_gem_vram_of_gem(to_vbox_framebuffer(fb)->obj);
389 u32 width = plane->state->crtc_w;391 u32 width = plane->state->crtc_w;
390 u32 height = plane->state->crtc_h;392 u32 height = plane->state->crtc_h;
391 size_t data_size, mask_size;393 size_t data_size, mask_size;
@@ -404,7 +406,7 @@ static void vbox_cursor_atomic_update(struct drm_plane *plane, · 12 unmodified lines
404 vbox_crtc->cursor_enabled = true;406 vbox_crtc->cursor_enabled = true;
405 407
406 /* pinning is done in prepare/cleanup framebuffer */408 /* pinning is done in prepare/cleanup framebuffer */
407 src = vbox_bo_kmap(bo);409 src = drm_gem_vram_kmap(gbo, true, NULL);
408 if (IS_ERR(src)) {410 if (IS_ERR(src)) {
409 mutex_unlock(&vbox->hw_mutex);411 mutex_unlock(&vbox->hw_mutex);
410 DRM_WARN("Could not kmap cursor bo, skipping update\n");412 DRM_WARN("Could not kmap cursor bo, skipping update\n");
@@ -420,7 +422,7 @@ static void vbox_cursor_atomic_update(struct drm_plane *plane, · 9 unmodified lines
420 data_size = width * height * 4 + mask_size;422 data_size = width * height * 4 + mask_size;
421 423
422 copy_cursor_image(src, vbox->cursor_data, width, height, mask_size);424 copy_cursor_image(src, vbox->cursor_data, width, height, mask_size);
423 vbox_bo_kunmap(bo);425 drm_gem_vram_kunmap(gbo);
424 426
425 flags = VBOX_MOUSE_POINTER_VISIBLE | VBOX_MOUSE_POINTER_SHAPE |427 flags = VBOX_MOUSE_POINTER_VISIBLE | VBOX_MOUSE_POINTER_SHAPE |
426 VBOX_MOUSE_POINTER_ALPHA;428 VBOX_MOUSE_POINTER_ALPHA;
@@ -460,25 +462,25 @@ static void vbox_cursor_atomic_disable(struct drm_plane *plane, · 33 unmodified lines
460static int vbox_cursor_prepare_fb(struct drm_plane *plane,462static int vbox_cursor_prepare_fb(struct drm_plane *plane,
461 struct drm_plane_state *new_state)463 struct drm_plane_state *new_state)
462{464{
463 struct vbox_bo *bo;465 struct drm_gem_vram_object *gbo;
464 466
465 if (!new_state->fb)467 if (!new_state->fb)
466 return 0;468 return 0;
467 469
468 bo = gem_to_vbox_bo(to_vbox_framebuffer(new_state->fb)->obj);470 gbo = drm_gem_vram_of_gem(to_vbox_framebuffer(new_state->fb)->obj);
469 return vbox_bo_pin(bo, TTM_PL_FLAG_SYSTEM);471 return drm_gem_vram_pin(gbo, DRM_GEM_VRAM_PL_FLAG_SYSTEM);
470}472}
471 473
472static void vbox_cursor_cleanup_fb(struct drm_plane *plane,474static void vbox_cursor_cleanup_fb(struct drm_plane *plane,
473 struct drm_plane_state *old_state)475 struct drm_plane_state *old_state)
474{476{
475 struct vbox_bo *bo;477 struct drm_gem_vram_object *gbo;
476 478
477 if (!plane->state->fb)479 if (!plane->state->fb)
478 return;480 return;
479 481
480 bo = gem_to_vbox_bo(to_vbox_framebuffer(plane->state->fb)->obj);482 gbo = drm_gem_vram_of_gem(to_vbox_framebuffer(plane->state->fb)->obj);
481 vbox_bo_unpin(bo);483 drm_gem_vram_unpin(gbo);
482}484}
483 485
484static const u32 vbox_cursor_plane_formats[] = {486static const u32 vbox_cursor_plane_formats[] = {
drivers/gpu/drm/vboxvideo/vbox_ttm.c+8−347
@@ -8,167 +8,23 @@ · 7 unmodified lines
8 */8 */
9#include <linux/pci.h>9#include <linux/pci.h>
10#include <drm/drm_file.h>10#include <drm/drm_file.h>
11#include <drm/ttm/ttm_page_alloc.h>
12#include "vbox_drv.h"11#include "vbox_drv.h"
13 12
14static inline struct vbox_private *vbox_bdev(struct ttm_bo_device *bd)
15{
16 return container_of(bd, struct vbox_private, ttm.bdev);
17}
18
19static void vbox_bo_ttm_destroy(struct ttm_buffer_object *tbo)
20{
21 struct vbox_bo *bo;
22
23 bo = container_of(tbo, struct vbox_bo, bo);
24
25 drm_gem_object_release(&bo->gem);
26 kfree(bo);
27}
28
29static bool vbox_ttm_bo_is_vbox_bo(struct ttm_buffer_object *bo)
30{
31 if (bo->destroy == &vbox_bo_ttm_destroy)
32 return true;
33
34 return false;
35}
36
37static int
38vbox_bo_init_mem_type(struct ttm_bo_device *bdev, u32 type,
39 struct ttm_mem_type_manager *man)
40{
41 switch (type) {
42 case TTM_PL_SYSTEM:
43 man->flags = TTM_MEMTYPE_FLAG_MAPPABLE;
44 man->available_caching = TTM_PL_MASK_CACHING;
45 man->default_caching = TTM_PL_FLAG_CACHED;
46 break;
47 case TTM_PL_VRAM:
48 man->func = &ttm_bo_manager_func;
49 man->flags = TTM_MEMTYPE_FLAG_FIXED | TTM_MEMTYPE_FLAG_MAPPABLE;
50 man->available_caching = TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_WC;
51 man->default_caching = TTM_PL_FLAG_WC;
52 break;
53 default:
54 DRM_ERROR("Unsupported memory type %u\n", (unsigned int)type);
55 return -EINVAL;
56 }
57
58 return 0;
59}
60
61static void
62vbox_bo_evict_flags(struct ttm_buffer_object *bo, struct ttm_placement *pl)
63{
64 struct vbox_bo *vboxbo = vbox_bo(bo);
65
66 if (!vbox_ttm_bo_is_vbox_bo(bo))
67 return;
68
69 vbox_ttm_placement(vboxbo, TTM_PL_FLAG_SYSTEM);
70 *pl = vboxbo->placement;
71}
72
73static int vbox_bo_verify_access(struct ttm_buffer_object *bo,
74 struct file *filp)
75{
76 return 0;
77}
78
79static int vbox_ttm_io_mem_reserve(struct ttm_bo_device *bdev,
80 struct ttm_mem_reg *mem)
81{
82 struct ttm_mem_type_manager *man = &bdev->man[mem->mem_type];
83 struct vbox_private *vbox = vbox_bdev(bdev);
84
85 mem->bus.addr = NULL;
86 mem->bus.offset = 0;
87 mem->bus.size = mem->num_pages << PAGE_SHIFT;
88 mem->bus.base = 0;
89 mem->bus.is_iomem = false;
90 if (!(man->flags & TTM_MEMTYPE_FLAG_MAPPABLE))
91 return -EINVAL;
92 switch (mem->mem_type) {
93 case TTM_PL_SYSTEM:
94 /* system memory */
95 return 0;
96 case TTM_PL_VRAM:
97 mem->bus.offset = mem->start << PAGE_SHIFT;
98 mem->bus.base = pci_resource_start(vbox->ddev.pdev, 0);
99 mem->bus.is_iomem = true;
100 break;
101 default:
102 return -EINVAL;
103 }
104 return 0;
105}
106
107static void vbox_ttm_io_mem_free(struct ttm_bo_device *bdev,
108 struct ttm_mem_reg *mem)
109{
110}
111
112static void vbox_ttm_backend_destroy(struct ttm_tt *tt)
113{
114 ttm_tt_fini(tt);
115 kfree(tt);
116}
117
118static struct ttm_backend_func vbox_tt_backend_func = {
119 .destroy = &vbox_ttm_backend_destroy,
120};
121
122static struct ttm_tt *vbox_ttm_tt_create(struct ttm_buffer_object *bo,
123 u32 page_flags)
124{
125 struct ttm_tt *tt;
126
127 tt = kzalloc(sizeof(*tt), GFP_KERNEL);
128 if (!tt)
129 return NULL;
130
131 tt->func = &vbox_tt_backend_func;
132 if (ttm_tt_init(tt, bo, page_flags)) {
133 kfree(tt);
134 return NULL;
135 }
136
137 return tt;
138}
139
140static struct ttm_bo_driver vbox_bo_driver = {
141 .ttm_tt_create = vbox_ttm_tt_create,
142 .init_mem_type = vbox_bo_init_mem_type,
143 .eviction_valuable = ttm_bo_eviction_valuable,
144 .evict_flags = vbox_bo_evict_flags,
145 .verify_access = vbox_bo_verify_access,
146 .io_mem_reserve = &vbox_ttm_io_mem_reserve,
147 .io_mem_free = &vbox_ttm_io_mem_free,
148};
149
150int vbox_mm_init(struct vbox_private *vbox)13int vbox_mm_init(struct vbox_private *vbox)
151{14{
15 struct drm_vram_mm *vmm;
152 int ret;16 int ret;
153 struct drm_device *dev = &vbox->ddev;17 struct drm_device *dev = &vbox->ddev;
154 struct ttm_bo_device *bdev = &vbox->ttm.bdev;
155 18
156 ret = ttm_bo_device_init(&vbox->ttm.bdev,19 vmm = drm_vram_helper_alloc_mm(dev, pci_resource_start(dev->pdev, 0),
157 &vbox_bo_driver,20 vbox->available_vram_size,
158 dev->anon_inode->i_mapping,21 &drm_gem_vram_mm_funcs);
159 true);22 if (IS_ERR(vmm)) {
160 if (ret) {23 ret = PTR_ERR(vmm);
161 DRM_ERROR("Error initialising bo driver; %d\n", ret);24 DRM_ERROR("Error initializing VRAM MM; %d\n", ret);
162 return ret;25 return ret;
163 }26 }
164 27
165 ret = ttm_bo_init_mm(bdev, TTM_PL_VRAM,
166 vbox->available_vram_size >> PAGE_SHIFT);
167 if (ret) {
168 DRM_ERROR("Failed ttm VRAM init: %d\n", ret);
169 goto err_device_release;
170 }
171
172#ifdef DRM_MTRR_WC28#ifdef DRM_MTRR_WC
173 vbox->fb_mtrr = drm_mtrr_add(pci_resource_start(dev->pdev, 0),29 vbox->fb_mtrr = drm_mtrr_add(pci_resource_start(dev->pdev, 0),
174 pci_resource_len(dev->pdev, 0),30 pci_resource_len(dev->pdev, 0),
@@ -178,10 +34,6 @@ int vbox_mm_init(struct vbox_private *vbox) · 3 unmodified lines
178 pci_resource_len(dev->pdev, 0));34 pci_resource_len(dev->pdev, 0));
179#endif35#endif
180 return 0;36 return 0;
181
182err_device_release:
183 ttm_bo_device_release(&vbox->ttm.bdev);
184 return ret;
185}37}
186 38
187void vbox_mm_fini(struct vbox_private *vbox)39void vbox_mm_fini(struct vbox_private *vbox)
@@ -193,196 +45,5 @@ void vbox_mm_fini(struct vbox_private *vbox) · 5 unmodified lines
193#else45#else
194 arch_phys_wc_del(vbox->fb_mtrr);46 arch_phys_wc_del(vbox->fb_mtrr);
195#endif47#endif
196 ttm_bo_device_release(&vbox->ttm.bdev);48 drm_vram_helper_release_mm(&vbox->ddev);
197}
198
199void vbox_ttm_placement(struct vbox_bo *bo, int domain)
200{
201 unsigned int i;
202 u32 c = 0;
203
204 bo->placement.placement = bo->placements;
205 bo->placement.busy_placement = bo->placements;
206
207 if (domain & TTM_PL_FLAG_VRAM)
208 bo->placements[c++].flags =
209 TTM_PL_FLAG_WC | TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_VRAM;
210 if (domain & TTM_PL_FLAG_SYSTEM)
211 bo->placements[c++].flags =
212 TTM_PL_MASK_CACHING | TTM_PL_FLAG_SYSTEM;
213 if (!c)
214 bo->placements[c++].flags =
215 TTM_PL_MASK_CACHING | TTM_PL_FLAG_SYSTEM;
216
217 bo->placement.num_placement = c;
218 bo->placement.num_busy_placement = c;
219
220 for (i = 0; i < c; ++i) {
221 bo->placements[i].fpfn = 0;
222 bo->placements[i].lpfn = 0;
223 }
224}
225
226int vbox_bo_create(struct vbox_private *vbox, int size, int align,
227 u32 flags, struct vbox_bo **pvboxbo)
228{
229 struct vbox_bo *vboxbo;
230 size_t acc_size;
231 int ret;
232
233 vboxbo = kzalloc(sizeof(*vboxbo), GFP_KERNEL);
234 if (!vboxbo)
235 return -ENOMEM;
236
237 ret = drm_gem_object_init(&vbox->ddev, &vboxbo->gem, size);
238 if (ret)
239 goto err_free_vboxbo;
240
241 vboxbo->bo.bdev = &vbox->ttm.bdev;
242
243 vbox_ttm_placement(vboxbo, TTM_PL_FLAG_VRAM | TTM_PL_FLAG_SYSTEM);
244
245 acc_size = ttm_bo_dma_acc_size(&vbox->ttm.bdev, size,
246 sizeof(struct vbox_bo));
247
248 ret = ttm_bo_init(&vbox->ttm.bdev, &vboxbo->bo, size,
249 ttm_bo_type_device, &vboxbo->placement,
250 align >> PAGE_SHIFT, false, acc_size,
251 NULL, NULL, vbox_bo_ttm_destroy);
252 if (ret)
253 goto err_free_vboxbo;
254
255 *pvboxbo = vboxbo;
256
257 return 0;
258
259err_free_vboxbo:
260 kfree(vboxbo);
261 return ret;
262}
263
264int vbox_bo_pin(struct vbox_bo *bo, u32 pl_flag)
265{
266 struct ttm_operation_ctx ctx = { false, false };
267 int i, ret;
268
269 if (bo->pin_count) {
270 bo->pin_count++;
271 return 0;
272 }
273
274 ret = vbox_bo_reserve(bo, false);
275 if (ret)
276 return ret;
277
278 vbox_ttm_placement(bo, pl_flag);
279
280 for (i = 0; i < bo->placement.num_placement; i++)
281 bo->placements[i].flags |= TTM_PL_FLAG_NO_EVICT;
282
283 ret = ttm_bo_validate(&bo->bo, &bo->placement, &ctx);
284 if (ret == 0)
285 bo->pin_count = 1;
286
287 vbox_bo_unreserve(bo);
288
289 return ret;
290}
291
292int vbox_bo_unpin(struct vbox_bo *bo)
293{
294 struct ttm_operation_ctx ctx = { false, false };
295 int i, ret;
296
297 if (!bo->pin_count) {
298 DRM_ERROR("unpin bad %p\n", bo);
299 return 0;
300 }
301 bo->pin_count--;
302 if (bo->pin_count)
303 return 0;
304
305 ret = vbox_bo_reserve(bo, false);
306 if (ret) {
307 DRM_ERROR("Error %d reserving bo, leaving it pinned\n", ret);
308 return ret;
309 }
310
311 for (i = 0; i < bo->placement.num_placement; i++)
312 bo->placements[i].flags &= ~TTM_PL_FLAG_NO_EVICT;
313
314 ret = ttm_bo_validate(&bo->bo, &bo->placement, &ctx);
315
316 vbox_bo_unreserve(bo);
317
318 return ret;
319}
320
321/*
322 * Move a vbox-owned buffer object to system memory if no one else has it
323 * pinned. The caller must have pinned it previously, and this call will
324 * release the caller's pin.
325 */
326int vbox_bo_push_sysram(struct vbox_bo *bo)
327{
328 struct ttm_operation_ctx ctx = { false, false };
329 int i, ret;
330
331 if (!bo->pin_count) {
332 DRM_ERROR("unpin bad %p\n", bo);
333 return 0;
334 }
335 bo->pin_count--;
336 if (bo->pin_count)
337 return 0;
338
339 if (bo->kmap.virtual) {
340 ttm_bo_kunmap(&bo->kmap);
341 bo->kmap.virtual = NULL;
342 }
343
344 vbox_ttm_placement(bo, TTM_PL_FLAG_SYSTEM);
345
346 for (i = 0; i < bo->placement.num_placement; i++)
347 bo->placements[i].flags |= TTM_PL_FLAG_NO_EVICT;
348
349 ret = ttm_bo_validate(&bo->bo, &bo->placement, &ctx);
350 if (ret) {
351 DRM_ERROR("pushing to VRAM failed\n");
352 return ret;
353 }
354
355 return 0;
356}
357
358int vbox_mmap(struct file *filp, struct vm_area_struct *vma)
359{
360 struct drm_file *file_priv = filp->private_data;
361 struct vbox_private *vbox = file_priv->minor->dev->dev_private;
362
363 return ttm_bo_mmap(filp, vma, &vbox->ttm.bdev);
364}
365
366void *vbox_bo_kmap(struct vbox_bo *bo)
367{
368 int ret;
369
370 if (bo->kmap.virtual)
371 return bo->kmap.virtual;
372
373 ret = ttm_bo_kmap(&bo->bo, 0, bo->bo.num_pages, &bo->kmap);
374 if (ret) {
375 DRM_ERROR("Error kmapping bo: %d\n", ret);
376 return NULL;
377 }
378
379 return bo->kmap.virtual;
380}
381
382void vbox_bo_kunmap(struct vbox_bo *bo)
383{
384 if (bo->kmap.virtual) {
385 ttm_bo_kunmap(&bo->kmap);
386 bo->kmap.virtual = NULL;
387 }
388}49}
drivers/gpu/drm/vc4/vc4_bo.c+30−1
@@ -799,13 +799,36 @@ vc4_prime_import_sg_table(struct drm_device *dev, · 798 unmodified lines
799 return obj;799 return obj;
800}800}
801 801
802static int vc4_grab_bin_bo(struct vc4_dev *vc4, struct vc4_file *vc4file)
803{
804 int ret;
805
806 if (!vc4->v3d)
807 return -ENODEV;
808
809 if (vc4file->bin_bo_used)
810 return 0;
811
812 ret = vc4_v3d_bin_bo_get(vc4, &vc4file->bin_bo_used);
813 if (ret)
814 return ret;
815
816 return 0;
817}
818
802int vc4_create_bo_ioctl(struct drm_device *dev, void *data,819int vc4_create_bo_ioctl(struct drm_device *dev, void *data,
803 struct drm_file *file_priv)820 struct drm_file *file_priv)
804{821{
805 struct drm_vc4_create_bo *args = data;822 struct drm_vc4_create_bo *args = data;
823 struct vc4_file *vc4file = file_priv->driver_priv;
824 struct vc4_dev *vc4 = to_vc4_dev(dev);
806 struct vc4_bo *bo = NULL;825 struct vc4_bo *bo = NULL;
807 int ret;826 int ret;
808 827
828 ret = vc4_grab_bin_bo(vc4, vc4file);
829 if (ret)
830 return ret;
831
809 /*832 /*
810 * We can't allocate from the BO cache, because the BOs don't833 * We can't allocate from the BO cache, because the BOs don't
811 * get zeroed, and that might leak data between users.834 * get zeroed, and that might leak data between users.
@@ -846,6 +869,8 @@ vc4_create_shader_bo_ioctl(struct drm_device *dev, void *data, · 34 unmodified lines
846 struct drm_file *file_priv)869 struct drm_file *file_priv)
847{870{
848 struct drm_vc4_create_shader_bo *args = data;871 struct drm_vc4_create_shader_bo *args = data;
872 struct vc4_file *vc4file = file_priv->driver_priv;
873 struct vc4_dev *vc4 = to_vc4_dev(dev);
849 struct vc4_bo *bo = NULL;874 struct vc4_bo *bo = NULL;
850 int ret;875 int ret;
851 876
@@ -865,6 +890,10 @@ vc4_create_shader_bo_ioctl(struct drm_device *dev, void *data, · 13 unmodified lines
865 return -EINVAL;890 return -EINVAL;
866 }891 }
867 892
893 ret = vc4_grab_bin_bo(vc4, vc4file);
894 if (ret)
895 return ret;
896
868 bo = vc4_bo_create(dev, args->size, true, VC4_BO_TYPE_V3D_SHADER);897 bo = vc4_bo_create(dev, args->size, true, VC4_BO_TYPE_V3D_SHADER);
869 if (IS_ERR(bo))898 if (IS_ERR(bo))
870 return PTR_ERR(bo);899 return PTR_ERR(bo);
@@ -894,7 +923,7 @@ vc4_create_shader_bo_ioctl(struct drm_device *dev, void *data, · 23 unmodified lines
894 */923 */
895 ret = drm_gem_handle_create(file_priv, &bo->base.base, &args->handle);924 ret = drm_gem_handle_create(file_priv, &bo->base.base, &args->handle);
896 925
897 fail:926fail:
898 drm_gem_object_put_unlocked(&bo->base.base);927 drm_gem_object_put_unlocked(&bo->base.base);
899 928
900 return ret;929 return ret;
drivers/gpu/drm/vc4/vc4_drv.c+6−0
@@ -128,8 +128,12 @@ static int vc4_open(struct drm_device *dev, struct drm_file *file) · 127 unmodified lines
128 128
129static void vc4_close(struct drm_device *dev, struct drm_file *file)129static void vc4_close(struct drm_device *dev, struct drm_file *file)
130{130{
131 struct vc4_dev *vc4 = to_vc4_dev(dev);
131 struct vc4_file *vc4file = file->driver_priv;132 struct vc4_file *vc4file = file->driver_priv;
132 133
134 if (vc4file->bin_bo_used)
135 vc4_v3d_bin_bo_put(vc4);
136
133 vc4_perfmon_close_file(vc4file);137 vc4_perfmon_close_file(vc4file);
134 kfree(vc4file);138 kfree(vc4file);
135}139}
@@ -274,6 +278,8 @@ static int vc4_drm_bind(struct device *dev) · 138 unmodified lines
274 drm->dev_private = vc4;278 drm->dev_private = vc4;
275 INIT_LIST_HEAD(&vc4->debugfs_list);279 INIT_LIST_HEAD(&vc4->debugfs_list);
276 280
281 mutex_init(&vc4->bin_bo_lock);
282
277 ret = vc4_bo_cache_init(drm);283 ret = vc4_bo_cache_init(drm);
278 if (ret)284 if (ret)
279 goto dev_put;285 goto dev_put;
drivers/gpu/drm/vc4/vc4_drv.h+14−0
@@ -216,6 +216,11 @@ struct vc4_dev { · 215 unmodified lines
216 * the minor is available (after drm_dev_register()).216 * the minor is available (after drm_dev_register()).
217 */217 */
218 struct list_head debugfs_list;218 struct list_head debugfs_list;
219
220 /* Mutex for binner bo allocation. */
221 struct mutex bin_bo_lock;
222 /* Reference count for our binner bo. */
223 struct kref bin_bo_kref;
219};224};
220 225
221static inline struct vc4_dev *226static inline struct vc4_dev *
@@ -584,6 +589,11 @@ struct vc4_exec_info { · 362 unmodified lines
584 * NULL otherwise.589 * NULL otherwise.
585 */590 */
586 struct vc4_perfmon *perfmon;591 struct vc4_perfmon *perfmon;
592
593 /* Whether the exec has taken a reference to the binner BO, which should
594 * happen with a VC4_PACKET_TILE_BINNING_MODE_CONFIG packet.
595 */
596 bool bin_bo_used;
587};597};
588 598
589/* Per-open file private data. Any driver-specific resource that has to be599/* Per-open file private data. Any driver-specific resource that has to be
@@ -594,6 +604,8 @@ struct vc4_file { · 4 unmodified lines
594 struct idr idr;604 struct idr idr;
595 struct mutex lock;605 struct mutex lock;
596 } perfmon;606 } perfmon;
607
608 bool bin_bo_used;
597};609};
598 610
599static inline struct vc4_exec_info *611static inline struct vc4_exec_info *
@@ -833,6 +845,8 @@ void vc4_plane_async_set_fb(struct drm_plane *plane, · 233 unmodified lines
833extern struct platform_driver vc4_v3d_driver;845extern struct platform_driver vc4_v3d_driver;
834extern const struct of_device_id vc4_v3d_dt_match[];846extern const struct of_device_id vc4_v3d_dt_match[];
835int vc4_v3d_get_bin_slot(struct vc4_dev *vc4);847int vc4_v3d_get_bin_slot(struct vc4_dev *vc4);
848int vc4_v3d_bin_bo_get(struct vc4_dev *vc4, bool *used);
849void vc4_v3d_bin_bo_put(struct vc4_dev *vc4);
836int vc4_v3d_pm_get(struct vc4_dev *vc4);850int vc4_v3d_pm_get(struct vc4_dev *vc4);
837void vc4_v3d_pm_put(struct vc4_dev *vc4);851void vc4_v3d_pm_put(struct vc4_dev *vc4);
838 852
drivers/gpu/drm/vc4/vc4_gem.c+11−0
@@ -820,6 +820,7 @@ static int · 819 unmodified lines
820vc4_get_bcl(struct drm_device *dev, struct vc4_exec_info *exec)820vc4_get_bcl(struct drm_device *dev, struct vc4_exec_info *exec)
821{821{
822 struct drm_vc4_submit_cl *args = exec->args;822 struct drm_vc4_submit_cl *args = exec->args;
823 struct vc4_dev *vc4 = to_vc4_dev(dev);
823 void *temp = NULL;824 void *temp = NULL;
824 void *bin;825 void *bin;
825 int ret = 0;826 int ret = 0;
@@ -918,6 +919,12 @@ vc4_get_bcl(struct drm_device *dev, struct vc4_exec_info *exec) · 92 unmodified lines
918 if (ret)919 if (ret)
919 goto fail;920 goto fail;
920 921
922 if (exec->found_tile_binning_mode_config_packet) {
923 ret = vc4_v3d_bin_bo_get(vc4, &exec->bin_bo_used);
924 if (ret)
925 goto fail;
926 }
927
921 /* Block waiting on any previous rendering into the CS's VBO,928 /* Block waiting on any previous rendering into the CS's VBO,
922 * IB, or textures, so that pixels are actually written by the929 * IB, or textures, so that pixels are actually written by the
923 * time we try to read them.930 * time we try to read them.
@@ -966,6 +973,10 @@ vc4_complete_exec(struct drm_device *dev, struct vc4_exec_info *exec) · 42 unmodified lines
966 vc4->bin_alloc_used &= ~exec->bin_slots;973 vc4->bin_alloc_used &= ~exec->bin_slots;
967 spin_unlock_irqrestore(&vc4->job_lock, irqflags);974 spin_unlock_irqrestore(&vc4->job_lock, irqflags);
968 975
976 /* Release the reference on the binner BO if needed. */
977 if (exec->bin_bo_used)
978 vc4_v3d_bin_bo_put(vc4);
979
969 /* Release the reference we had on the perf monitor. */980 /* Release the reference we had on the perf monitor. */
970 vc4_perfmon_put(exec->perfmon);981 vc4_perfmon_put(exec->perfmon);
971 982
drivers/gpu/drm/vc4/vc4_irq.c+16−4
@@ -59,15 +59,22 @@ vc4_overflow_mem_work(struct work_struct *work) · 58 unmodified lines
59{59{
60 struct vc4_dev *vc4 =60 struct vc4_dev *vc4 =
61 container_of(work, struct vc4_dev, overflow_mem_work);61 container_of(work, struct vc4_dev, overflow_mem_work);
62 struct vc4_bo *bo = vc4->bin_bo;62 struct vc4_bo *bo;
63 int bin_bo_slot;63 int bin_bo_slot;
64 struct vc4_exec_info *exec;64 struct vc4_exec_info *exec;
65 unsigned long irqflags;65 unsigned long irqflags;
66 66
67 mutex_lock(&vc4->bin_bo_lock);
68
69 if (!vc4->bin_bo)
70 goto complete;
71
72 bo = vc4->bin_bo;
73
67 bin_bo_slot = vc4_v3d_get_bin_slot(vc4);74 bin_bo_slot = vc4_v3d_get_bin_slot(vc4);
68 if (bin_bo_slot < 0) {75 if (bin_bo_slot < 0) {
69 DRM_ERROR("Couldn't allocate binner overflow mem\n");76 DRM_ERROR("Couldn't allocate binner overflow mem\n");
70 return;77 goto complete;
71 }78 }
72 79
73 spin_lock_irqsave(&vc4->job_lock, irqflags);80 spin_lock_irqsave(&vc4->job_lock, irqflags);
@@ -98,6 +105,9 @@ vc4_overflow_mem_work(struct work_struct *work) · 24 unmodified lines
98 V3D_WRITE(V3D_INTCTL, V3D_INT_OUTOMEM);105 V3D_WRITE(V3D_INTCTL, V3D_INT_OUTOMEM);
99 V3D_WRITE(V3D_INTENA, V3D_INT_OUTOMEM);106 V3D_WRITE(V3D_INTENA, V3D_INT_OUTOMEM);
100 spin_unlock_irqrestore(&vc4->job_lock, irqflags);107 spin_unlock_irqrestore(&vc4->job_lock, irqflags);
108
109complete:
110 mutex_unlock(&vc4->bin_bo_lock);
101}111}
102 112
103static void113static void
@@ -249,8 +259,10 @@ vc4_irq_postinstall(struct drm_device *dev) · 145 unmodified lines
249 if (!vc4->v3d)259 if (!vc4->v3d)
250 return 0;260 return 0;
251 261
252 /* Enable both the render done and out of memory interrupts. */262 /* Enable the render done interrupts. The out-of-memory interrupt is
253 V3D_WRITE(V3D_INTENA, V3D_DRIVER_IRQS);263 * enabled as soon as we have a binner BO allocated.
264 */
265 V3D_WRITE(V3D_INTENA, V3D_INT_FLDONE | V3D_INT_FRDONE);
254 266
255 return 0;267 return 0;
256}268}
drivers/gpu/drm/vc4/vc4_plane.c+5−10
@@ -310,10 +310,10 @@ static int vc4_plane_setup_clipping_and_scaling(struct drm_plane_state *state) · 309 unmodified lines
310 struct drm_framebuffer *fb = state->fb;310 struct drm_framebuffer *fb = state->fb;
311 struct drm_gem_cma_object *bo = drm_fb_cma_get_gem_obj(fb, 0);311 struct drm_gem_cma_object *bo = drm_fb_cma_get_gem_obj(fb, 0);
312 u32 subpixel_src_mask = (1 << 16) - 1;312 u32 subpixel_src_mask = (1 << 16) - 1;
313 u32 format = fb->format->format;
314 int num_planes = fb->format->num_planes;313 int num_planes = fb->format->num_planes;
315 struct drm_crtc_state *crtc_state;314 struct drm_crtc_state *crtc_state;
316 u32 h_subsample, v_subsample;315 u32 h_subsample = fb->format->hsub;
316 u32 v_subsample = fb->format->vsub;
317 int i, ret;317 int i, ret;
318 318
319 crtc_state = drm_atomic_get_existing_crtc_state(state->state,319 crtc_state = drm_atomic_get_existing_crtc_state(state->state,
@@ -328,9 +328,6 @@ static int vc4_plane_setup_clipping_and_scaling(struct drm_plane_state *state) · 8 unmodified lines
328 if (ret)328 if (ret)
329 return ret;329 return ret;
330 330
331 h_subsample = drm_format_horz_chroma_subsampling(format);
332 v_subsample = drm_format_vert_chroma_subsampling(format);
333
334 for (i = 0; i < num_planes; i++)331 for (i = 0; i < num_planes; i++)
335 vc4_state->offsets[i] = bo->paddr + fb->offsets[i];332 vc4_state->offsets[i] = bo->paddr + fb->offsets[i];
336 333
@@ -592,8 +589,9 @@ static int vc4_plane_mode_set(struct drm_plane *plane, · 255 unmodified lines
592 u32 ctl0_offset = vc4_state->dlist_count;589 u32 ctl0_offset = vc4_state->dlist_count;
593 const struct hvs_format *format = vc4_get_hvs_format(fb->format->format);590 const struct hvs_format *format = vc4_get_hvs_format(fb->format->format);
594 u64 base_format_mod = fourcc_mod_broadcom_mod(fb->modifier);591 u64 base_format_mod = fourcc_mod_broadcom_mod(fb->modifier);
595 int num_planes = drm_format_num_planes(format->drm);592 int num_planes = fb->format->num_planes;
596 u32 h_subsample, v_subsample;593 u32 h_subsample = fb->format->hsub;
594 u32 v_subsample = fb->format->vsub;
597 bool mix_plane_alpha;595 bool mix_plane_alpha;
598 bool covers_screen;596 bool covers_screen;
599 u32 scl0, scl1, pitch0;597 u32 scl0, scl1, pitch0;
@@ -623,9 +621,6 @@ static int vc4_plane_mode_set(struct drm_plane *plane, · 23 unmodified lines
623 scl1 = vc4_get_scl_field(state, 0);621 scl1 = vc4_get_scl_field(state, 0);
624 }622 }
625 623
626 h_subsample = drm_format_horz_chroma_subsampling(format->drm);
627 v_subsample = drm_format_vert_chroma_subsampling(format->drm);
628
629 rotation = drm_rotation_simplify(state->rotation,624 rotation = drm_rotation_simplify(state->rotation,
630 DRM_MODE_ROTATE_0 |625 DRM_MODE_ROTATE_0 |
631 DRM_MODE_REFLECT_X |626 DRM_MODE_REFLECT_X |
drivers/gpu/drm/vc4/vc4_v3d.c+55−17
@@ -213,7 +213,7 @@ try_again: · 212 unmodified lines
213}213}
214 214
215/**215/**
216 * vc4_allocate_bin_bo() - allocates the memory that will be used for216 * bin_bo_alloc() - allocates the memory that will be used for
217 * tile binning.217 * tile binning.
218 *218 *
219 * The binner has a limitation that the addresses in the tile state219 * The binner has a limitation that the addresses in the tile state
@@ -234,14 +234,16 @@ try_again: · 14 unmodified lines
234 * overall CMA pool before they make scenes complicated enough to run234 * overall CMA pool before they make scenes complicated enough to run
235 * out of bin space.235 * out of bin space.
236 */236 */
237static int vc4_allocate_bin_bo(struct drm_device *drm)237static int bin_bo_alloc(struct vc4_dev *vc4)
238{238{
239 struct vc4_dev *vc4 = to_vc4_dev(drm);
240 struct vc4_v3d *v3d = vc4->v3d;239 struct vc4_v3d *v3d = vc4->v3d;
241 uint32_t size = 16 * 1024 * 1024;240 uint32_t size = 16 * 1024 * 1024;
242 int ret = 0;241 int ret = 0;
243 struct list_head list;242 struct list_head list;
244 243
244 if (!v3d)
245 return -ENODEV;
246
245 /* We may need to try allocating more than once to get a BO247 /* We may need to try allocating more than once to get a BO
246 * that doesn't cross 256MB. Track the ones we've allocated248 * that doesn't cross 256MB. Track the ones we've allocated
247 * that failed so far, so that we can free them when we've got249 * that failed so far, so that we can free them when we've got
@@ -251,7 +253,7 @@ static int vc4_allocate_bin_bo(struct drm_device *drm) · 3 unmodified lines
251 INIT_LIST_HEAD(&list);253 INIT_LIST_HEAD(&list);
252 254
253 while (true) {255 while (true) {
254 struct vc4_bo *bo = vc4_bo_create(drm, size, true,256 struct vc4_bo *bo = vc4_bo_create(vc4->dev, size, true,
255 VC4_BO_TYPE_BIN);257 VC4_BO_TYPE_BIN);
256 258
257 if (IS_ERR(bo)) {259 if (IS_ERR(bo)) {
@@ -292,6 +294,14 @@ static int vc4_allocate_bin_bo(struct drm_device *drm) · 34 unmodified lines
292 WARN_ON_ONCE(sizeof(vc4->bin_alloc_used) * 8 !=294 WARN_ON_ONCE(sizeof(vc4->bin_alloc_used) * 8 !=
293 bo->base.base.size / vc4->bin_alloc_size);295 bo->base.base.size / vc4->bin_alloc_size);
294 296
297 kref_init(&vc4->bin_bo_kref);
298
299 /* Enable the out-of-memory interrupt to set our
300 * newly-allocated binner BO, potentially from an
301 * already-pending-but-masked interrupt.
302 */
303 V3D_WRITE(V3D_INTENA, V3D_INT_OUTOMEM);
304
295 break;305 break;
296 }306 }
297 307
@@ -311,6 +321,47 @@ static int vc4_allocate_bin_bo(struct drm_device *drm) · 13 unmodified lines
311 return ret;321 return ret;
312}322}
313 323
324int vc4_v3d_bin_bo_get(struct vc4_dev *vc4, bool *used)
325{
326 int ret = 0;
327
328 mutex_lock(&vc4->bin_bo_lock);
329
330 if (used && *used)
331 goto complete;
332
333 if (vc4->bin_bo)
334 kref_get(&vc4->bin_bo_kref);
335 else
336 ret = bin_bo_alloc(vc4);
337
338 if (ret == 0 && used)
339 *used = true;
340
341complete:
342 mutex_unlock(&vc4->bin_bo_lock);
343
344 return ret;
345}
346
347static void bin_bo_release(struct kref *ref)
348{
349 struct vc4_dev *vc4 = container_of(ref, struct vc4_dev, bin_bo_kref);
350
351 if (WARN_ON_ONCE(!vc4->bin_bo))
352 return;
353
354 drm_gem_object_put_unlocked(&vc4->bin_bo->base.base);
355 vc4->bin_bo = NULL;
356}
357
358void vc4_v3d_bin_bo_put(struct vc4_dev *vc4)
359{
360 mutex_lock(&vc4->bin_bo_lock);
361 kref_put(&vc4->bin_bo_kref, bin_bo_release);
362 mutex_unlock(&vc4->bin_bo_lock);
363}
364
314#ifdef CONFIG_PM365#ifdef CONFIG_PM
315static int vc4_v3d_runtime_suspend(struct device *dev)366static int vc4_v3d_runtime_suspend(struct device *dev)
316{367{
@@ -319,9 +370,6 @@ static int vc4_v3d_runtime_suspend(struct device *dev) · 2 unmodified lines
319 370
320 vc4_irq_uninstall(vc4->dev);371 vc4_irq_uninstall(vc4->dev);
321 372
322 drm_gem_object_put_unlocked(&vc4->bin_bo->base.base);
323 vc4->bin_bo = NULL;
324
325 clk_disable_unprepare(v3d->clk);373 clk_disable_unprepare(v3d->clk);
326 374
327 return 0;375 return 0;
@@ -333,10 +381,6 @@ static int vc4_v3d_runtime_resume(struct device *dev) · 5 unmodified lines
333 struct vc4_dev *vc4 = v3d->vc4;381 struct vc4_dev *vc4 = v3d->vc4;
334 int ret;382 int ret;
335 383
336 ret = vc4_allocate_bin_bo(vc4->dev);
337 if (ret)
338 return ret;
339
340 ret = clk_prepare_enable(v3d->clk);384 ret = clk_prepare_enable(v3d->clk);
341 if (ret != 0)385 if (ret != 0)
342 return ret;386 return ret;
@@ -403,12 +447,6 @@ static int vc4_v3d_bind(struct device *dev, struct device *master, void *data) · 60 unmodified lines
403 if (ret != 0)447 if (ret != 0)
404 return ret;448 return ret;
405 449
406 ret = vc4_allocate_bin_bo(drm);
407 if (ret) {
408 clk_disable_unprepare(v3d->clk);
409 return ret;
410 }
411
412 /* Reset the binner overflow address/size at setup, to be sure450 /* Reset the binner overflow address/size at setup, to be sure
413 * we don't reuse an old one.451 * we don't reuse an old one.
414 */452 */
drivers/gpu/drm/virtio/Makefile+1−1
@@ -6,6 +6,6 @@ · 5 unmodified lines
6virtio-gpu-y := virtgpu_drv.o virtgpu_kms.o virtgpu_gem.o \6virtio-gpu-y := virtgpu_drv.o virtgpu_kms.o virtgpu_gem.o \
7 virtgpu_fb.o virtgpu_display.o virtgpu_vq.o virtgpu_ttm.o \7 virtgpu_fb.o virtgpu_display.o virtgpu_vq.o virtgpu_ttm.o \
8 virtgpu_fence.o virtgpu_object.o virtgpu_debugfs.o virtgpu_plane.o \8 virtgpu_fence.o virtgpu_object.o virtgpu_debugfs.o virtgpu_plane.o \
9 virtgpu_ioctl.o virtgpu_prime.o9 virtgpu_ioctl.o virtgpu_prime.o virtgpu_trace_points.o
10 10
11obj-$(CONFIG_DRM_VIRTIO_GPU) += virtio-gpu.o11obj-$(CONFIG_DRM_VIRTIO_GPU) += virtio-gpu.o
drivers/gpu/drm/virtio/virtgpu_drv.h+1−2
@@ -102,7 +102,6 @@ struct virtio_gpu_fence { · 101 unmodified lines
102 struct dma_fence f;102 struct dma_fence f;
103 struct virtio_gpu_fence_driver *drv;103 struct virtio_gpu_fence_driver *drv;
104 struct list_head node;104 struct list_head node;
105 uint64_t seq;
106};105};
107#define to_virtio_fence(x) \106#define to_virtio_fence(x) \
108 container_of(x, struct virtio_gpu_fence, f)107 container_of(x, struct virtio_gpu_fence, f)
@@ -356,7 +355,7 @@ int virtio_gpu_mmap(struct file *filp, struct vm_area_struct *vma); · 247 unmodified lines
356bool virtio_fence_signaled(struct dma_fence *f);355bool virtio_fence_signaled(struct dma_fence *f);
357struct virtio_gpu_fence *virtio_gpu_fence_alloc(356struct virtio_gpu_fence *virtio_gpu_fence_alloc(
358 struct virtio_gpu_device *vgdev);357 struct virtio_gpu_device *vgdev);
359int virtio_gpu_fence_emit(struct virtio_gpu_device *vgdev,358void virtio_gpu_fence_emit(struct virtio_gpu_device *vgdev,
360 struct virtio_gpu_ctrl_hdr *cmd_hdr,359 struct virtio_gpu_ctrl_hdr *cmd_hdr,
361 struct virtio_gpu_fence *fence);360 struct virtio_gpu_fence *fence);
362void virtio_gpu_fence_event_process(struct virtio_gpu_device *vdev,361void virtio_gpu_fence_event_process(struct virtio_gpu_device *vdev,
drivers/gpu/drm/virtio/virtgpu_fence.c+15−10
@@ -24,6 +24,7 @@ · 23 unmodified lines
24 */24 */
25 25
26#include <drm/drmP.h>26#include <drm/drmP.h>
27#include <trace/events/dma_fence.h>
27#include "virtgpu_drv.h"28#include "virtgpu_drv.h"
28 29
29static const char *virtio_get_driver_name(struct dma_fence *f)30static const char *virtio_get_driver_name(struct dma_fence *f)
@@ -40,16 +41,14 @@ bool virtio_fence_signaled(struct dma_fence *f) · 10 unmodified lines
40{41{
41 struct virtio_gpu_fence *fence = to_virtio_fence(f);42 struct virtio_gpu_fence *fence = to_virtio_fence(f);
42 43
43 if (atomic64_read(&fence->drv->last_seq) >= fence->seq)44 if (atomic64_read(&fence->drv->last_seq) >= fence->f.seqno)
44 return true;45 return true;
45 return false;46 return false;
46}47}
47 48
48static void virtio_fence_value_str(struct dma_fence *f, char *str, int size)49static void virtio_fence_value_str(struct dma_fence *f, char *str, int size)
49{50{
50 struct virtio_gpu_fence *fence = to_virtio_fence(f);51 snprintf(str, size, "%llu", f->seqno);
51
52 snprintf(str, size, "%llu", fence->seq);
53}52}
54 53
55static void virtio_timeline_value_str(struct dma_fence *f, char *str, int size)54static void virtio_timeline_value_str(struct dma_fence *f, char *str, int size)
@@ -71,17 +70,22 @@ struct virtio_gpu_fence *virtio_gpu_fence_alloc(struct virtio_gpu_device *vgdev) · 15 unmodified lines
71{70{
72 struct virtio_gpu_fence_driver *drv = &vgdev->fence_drv;71 struct virtio_gpu_fence_driver *drv = &vgdev->fence_drv;
73 struct virtio_gpu_fence *fence = kzalloc(sizeof(struct virtio_gpu_fence),72 struct virtio_gpu_fence *fence = kzalloc(sizeof(struct virtio_gpu_fence),
74 GFP_ATOMIC);73 GFP_KERNEL);
75 if (!fence)74 if (!fence)
76 return fence;75 return fence;
77 76
78 fence->drv = drv;77 fence->drv = drv;
78
79 /* This only partially initializes the fence because the seqno is
80 * unknown yet. The fence must not be used outside of the driver
81 * until virtio_gpu_fence_emit is called.
82 */
79 dma_fence_init(&fence->f, &virtio_fence_ops, &drv->lock, drv->context, 0);83 dma_fence_init(&fence->f, &virtio_fence_ops, &drv->lock, drv->context, 0);
80 84
81 return fence;85 return fence;
82}86}
83 87
84int virtio_gpu_fence_emit(struct virtio_gpu_device *vgdev,88void virtio_gpu_fence_emit(struct virtio_gpu_device *vgdev,
85 struct virtio_gpu_ctrl_hdr *cmd_hdr,89 struct virtio_gpu_ctrl_hdr *cmd_hdr,
86 struct virtio_gpu_fence *fence)90 struct virtio_gpu_fence *fence)
87{91{
@@ -89,14 +93,15 @@ int virtio_gpu_fence_emit(struct virtio_gpu_device *vgdev, · 1 unmodified line
89 unsigned long irq_flags;93 unsigned long irq_flags;
90 94
91 spin_lock_irqsave(&drv->lock, irq_flags);95 spin_lock_irqsave(&drv->lock, irq_flags);
92 fence->seq = ++drv->sync_seq;96 fence->f.seqno = ++drv->sync_seq;
93 dma_fence_get(&fence->f);97 dma_fence_get(&fence->f);
94 list_add_tail(&fence->node, &drv->fences);98 list_add_tail(&fence->node, &drv->fences);
95 spin_unlock_irqrestore(&drv->lock, irq_flags);99 spin_unlock_irqrestore(&drv->lock, irq_flags);
96 100
101 trace_dma_fence_emit(&fence->f);
102
97 cmd_hdr->flags |= cpu_to_le32(VIRTIO_GPU_FLAG_FENCE);103 cmd_hdr->flags |= cpu_to_le32(VIRTIO_GPU_FLAG_FENCE);
98 cmd_hdr->fence_id = cpu_to_le64(fence->seq);104 cmd_hdr->fence_id = cpu_to_le64(fence->f.seqno);
99 return 0;
100}105}
101 106
102void virtio_gpu_fence_event_process(struct virtio_gpu_device *vgdev,107void virtio_gpu_fence_event_process(struct virtio_gpu_device *vgdev,
@@ -109,7 +114,7 @@ void virtio_gpu_fence_event_process(struct virtio_gpu_device *vgdev, · 6 unmodified lines
109 spin_lock_irqsave(&drv->lock, irq_flags);114 spin_lock_irqsave(&drv->lock, irq_flags);
110 atomic64_set(&vgdev->fence_drv.last_seq, last_seq);115 atomic64_set(&vgdev->fence_drv.last_seq, last_seq);
111 list_for_each_entry_safe(fence, tmp, &drv->fences, node) {116 list_for_each_entry_safe(fence, tmp, &drv->fences, node) {
112 if (last_seq < fence->seq)117 if (last_seq < fence->f.seqno)
113 continue;118 continue;
114 dma_fence_signal_locked(&fence->f);119 dma_fence_signal_locked(&fence->f);
115 list_del(&fence->node);120 list_del(&fence->node);
drivers/gpu/drm/virtio/virtgpu_ioctl.c+9−9
@@ -553,34 +553,34 @@ copy_exit: · 552 unmodified lines
553 553
554struct drm_ioctl_desc virtio_gpu_ioctls[DRM_VIRTIO_NUM_IOCTLS] = {554struct drm_ioctl_desc virtio_gpu_ioctls[DRM_VIRTIO_NUM_IOCTLS] = {
555 DRM_IOCTL_DEF_DRV(VIRTGPU_MAP, virtio_gpu_map_ioctl,555 DRM_IOCTL_DEF_DRV(VIRTGPU_MAP, virtio_gpu_map_ioctl,
556 DRM_AUTH | DRM_UNLOCKED | DRM_RENDER_ALLOW),556 DRM_AUTH | DRM_RENDER_ALLOW),
557 557
558 DRM_IOCTL_DEF_DRV(VIRTGPU_EXECBUFFER, virtio_gpu_execbuffer_ioctl,558 DRM_IOCTL_DEF_DRV(VIRTGPU_EXECBUFFER, virtio_gpu_execbuffer_ioctl,
559 DRM_AUTH | DRM_UNLOCKED | DRM_RENDER_ALLOW),559 DRM_AUTH | DRM_RENDER_ALLOW),
560 560
561 DRM_IOCTL_DEF_DRV(VIRTGPU_GETPARAM, virtio_gpu_getparam_ioctl,561 DRM_IOCTL_DEF_DRV(VIRTGPU_GETPARAM, virtio_gpu_getparam_ioctl,
562 DRM_AUTH | DRM_UNLOCKED | DRM_RENDER_ALLOW),562 DRM_AUTH | DRM_RENDER_ALLOW),
563 563
564 DRM_IOCTL_DEF_DRV(VIRTGPU_RESOURCE_CREATE,564 DRM_IOCTL_DEF_DRV(VIRTGPU_RESOURCE_CREATE,
565 virtio_gpu_resource_create_ioctl,565 virtio_gpu_resource_create_ioctl,
566 DRM_AUTH | DRM_UNLOCKED | DRM_RENDER_ALLOW),566 DRM_AUTH | DRM_RENDER_ALLOW),
567 567
568 DRM_IOCTL_DEF_DRV(VIRTGPU_RESOURCE_INFO, virtio_gpu_resource_info_ioctl,568 DRM_IOCTL_DEF_DRV(VIRTGPU_RESOURCE_INFO, virtio_gpu_resource_info_ioctl,
569 DRM_AUTH | DRM_UNLOCKED | DRM_RENDER_ALLOW),569 DRM_AUTH | DRM_RENDER_ALLOW),
570 570
571 /* make transfer async to the main ring? - no sure, can we571 /* make transfer async to the main ring? - no sure, can we
572 * thread these in the underlying GL572 * thread these in the underlying GL
573 */573 */
574 DRM_IOCTL_DEF_DRV(VIRTGPU_TRANSFER_FROM_HOST,574 DRM_IOCTL_DEF_DRV(VIRTGPU_TRANSFER_FROM_HOST,
575 virtio_gpu_transfer_from_host_ioctl,575 virtio_gpu_transfer_from_host_ioctl,
576 DRM_AUTH | DRM_UNLOCKED | DRM_RENDER_ALLOW),576 DRM_AUTH | DRM_RENDER_ALLOW),
577 DRM_IOCTL_DEF_DRV(VIRTGPU_TRANSFER_TO_HOST,577 DRM_IOCTL_DEF_DRV(VIRTGPU_TRANSFER_TO_HOST,
578 virtio_gpu_transfer_to_host_ioctl,578 virtio_gpu_transfer_to_host_ioctl,
579 DRM_AUTH | DRM_UNLOCKED | DRM_RENDER_ALLOW),579 DRM_AUTH | DRM_RENDER_ALLOW),
580 580
581 DRM_IOCTL_DEF_DRV(VIRTGPU_WAIT, virtio_gpu_wait_ioctl,581 DRM_IOCTL_DEF_DRV(VIRTGPU_WAIT, virtio_gpu_wait_ioctl,
582 DRM_AUTH | DRM_UNLOCKED | DRM_RENDER_ALLOW),582 DRM_AUTH | DRM_RENDER_ALLOW),
583 583
584 DRM_IOCTL_DEF_DRV(VIRTGPU_GET_CAPS, virtio_gpu_get_caps_ioctl,584 DRM_IOCTL_DEF_DRV(VIRTGPU_GET_CAPS, virtio_gpu_get_caps_ioctl,
585 DRM_AUTH | DRM_UNLOCKED | DRM_RENDER_ALLOW),585 DRM_AUTH | DRM_RENDER_ALLOW),
586};586};
drivers/gpu/drm/virtio/virtgpu_trace.h+52−0
@@ -0,0 +1,52 @@
1/* SPDX-License-Identifier: GPL-2.0 */
2#if !defined(_VIRTGPU_TRACE_H_) || defined(TRACE_HEADER_MULTI_READ)
3#define _VIRTGPU_TRACE_H_
4
5#include <linux/tracepoint.h>
6
7#undef TRACE_SYSTEM
8#define TRACE_SYSTEM virtio_gpu
9#define TRACE_INCLUDE_FILE virtgpu_trace
10
11DECLARE_EVENT_CLASS(virtio_gpu_cmd,
12 TP_PROTO(struct virtqueue *vq, struct virtio_gpu_ctrl_hdr *hdr),
13 TP_ARGS(vq, hdr),
14 TP_STRUCT__entry(
15 __field(int, dev)
16 __field(unsigned int, vq)
17 __field(const char *, name)
18 __field(u32, type)
19 __field(u32, flags)
20 __field(u64, fence_id)
21 __field(u32, ctx_id)
22 ),
23 TP_fast_assign(
24 __entry->dev = vq->vdev->index;
25 __entry->vq = vq->index;
26 __entry->name = vq->name;
27 __entry->type = le32_to_cpu(hdr->type);
28 __entry->flags = le32_to_cpu(hdr->flags);
29 __entry->fence_id = le64_to_cpu(hdr->fence_id);
30 __entry->ctx_id = le32_to_cpu(hdr->ctx_id);
31 ),
32 TP_printk("vdev=%d vq=%u name=%s type=0x%x flags=0x%x fence_id=%llu ctx_id=%u",
33 __entry->dev, __entry->vq, __entry->name,
34 __entry->type, __entry->flags, __entry->fence_id,
35 __entry->ctx_id)
36);
37
38DEFINE_EVENT(virtio_gpu_cmd, virtio_gpu_cmd_queue,
39 TP_PROTO(struct virtqueue *vq, struct virtio_gpu_ctrl_hdr *hdr),
40 TP_ARGS(vq, hdr)
41);
42
43DEFINE_EVENT(virtio_gpu_cmd, virtio_gpu_cmd_response,
44 TP_PROTO(struct virtqueue *vq, struct virtio_gpu_ctrl_hdr *hdr),
45 TP_ARGS(vq, hdr)
46);
47
48#endif
49
50#undef TRACE_INCLUDE_PATH
51#define TRACE_INCLUDE_PATH ../../drivers/gpu/drm/virtio
52#include <trace/define_trace.h>
drivers/gpu/drm/virtio/virtgpu_trace_points.c+5−0
@@ -0,0 +1,5 @@
1// SPDX-License-Identifier: GPL-2.0
2#include "virtgpu_drv.h"
3
4#define CREATE_TRACE_POINTS
5#include "virtgpu_trace.h"
drivers/gpu/drm/virtio/virtgpu_vq.c+10−0
@@ -28,6 +28,7 @@ · 27 unmodified lines
28 28
29#include <drm/drmP.h>29#include <drm/drmP.h>
30#include "virtgpu_drv.h"30#include "virtgpu_drv.h"
31#include "virtgpu_trace.h"
31#include <linux/virtio.h>32#include <linux/virtio.h>
32#include <linux/virtio_config.h>33#include <linux/virtio_config.h>
33#include <linux/virtio_ring.h>34#include <linux/virtio_ring.h>
@@ -192,6 +193,9 @@ void virtio_gpu_dequeue_ctrl_func(struct work_struct *work) · 158 unmodified lines
192 193
193 list_for_each_entry_safe(entry, tmp, &reclaim_list, list) {194 list_for_each_entry_safe(entry, tmp, &reclaim_list, list) {
194 resp = (struct virtio_gpu_ctrl_hdr *)entry->resp_buf;195 resp = (struct virtio_gpu_ctrl_hdr *)entry->resp_buf;
196
197 trace_virtio_gpu_cmd_response(vgdev->ctrlq.vq, resp);
198
195 if (resp->type != cpu_to_le32(VIRTIO_GPU_RESP_OK_NODATA)) {199 if (resp->type != cpu_to_le32(VIRTIO_GPU_RESP_OK_NODATA)) {
196 if (resp->type >= cpu_to_le32(VIRTIO_GPU_RESP_ERR_UNSPEC)) {200 if (resp->type >= cpu_to_le32(VIRTIO_GPU_RESP_ERR_UNSPEC)) {
197 struct virtio_gpu_ctrl_hdr *cmd;201 struct virtio_gpu_ctrl_hdr *cmd;
@@ -284,6 +288,9 @@ retry: · 86 unmodified lines
284 spin_lock(&vgdev->ctrlq.qlock);288 spin_lock(&vgdev->ctrlq.qlock);
285 goto retry;289 goto retry;
286 } else {290 } else {
291 trace_virtio_gpu_cmd_queue(vq,
292 (struct virtio_gpu_ctrl_hdr *)vbuf->buf);
293
287 virtqueue_kick(vq);294 virtqueue_kick(vq);
288 }295 }
289 296
@@ -359,6 +366,9 @@ retry: · 69 unmodified lines
359 spin_lock(&vgdev->cursorq.qlock);366 spin_lock(&vgdev->cursorq.qlock);
360 goto retry;367 goto retry;
361 } else {368 } else {
369 trace_virtio_gpu_cmd_queue(vq,
370 (struct virtio_gpu_ctrl_hdr *)vbuf->buf);
371
362 virtqueue_kick(vq);372 virtqueue_kick(vq);
363 }373 }
364 374
drivers/gpu/drm/vkms/vkms_crtc.c+13−20
@@ -83,26 +83,6 @@ bool vkms_get_vblank_timestamp(struct drm_device *dev, unsigned int pipe, · 82 unmodified lines
83 return true;83 return true;
84}84}
85 85
86static void vkms_atomic_crtc_reset(struct drm_crtc *crtc)
87{
88 struct vkms_crtc_state *vkms_state = NULL;
89
90 if (crtc->state) {
91 vkms_state = to_vkms_crtc_state(crtc->state);
92 __drm_atomic_helper_crtc_destroy_state(crtc->state);
93 kfree(vkms_state);
94 crtc->state = NULL;
95 }
96
97 vkms_state = kzalloc(sizeof(*vkms_state), GFP_KERNEL);
98 if (!vkms_state)
99 return;
100 INIT_WORK(&vkms_state->crc_work, vkms_crc_work_handle);
101
102 crtc->state = &vkms_state->base;
103 crtc->state->crtc = crtc;
104}
105
106static struct drm_crtc_state *86static struct drm_crtc_state *
107vkms_atomic_crtc_duplicate_state(struct drm_crtc *crtc)87vkms_atomic_crtc_duplicate_state(struct drm_crtc *crtc)
108{88{
@@ -135,6 +115,19 @@ static void vkms_atomic_crtc_destroy_state(struct drm_crtc *crtc, · 26 unmodified lines
135 }115 }
136}116}
137 117
118static void vkms_atomic_crtc_reset(struct drm_crtc *crtc)
119{
120 struct vkms_crtc_state *vkms_state =
121 kzalloc(sizeof(*vkms_state), GFP_KERNEL);
122
123 if (crtc->state)
124 vkms_atomic_crtc_destroy_state(crtc, crtc->state);
125
126 __drm_atomic_helper_crtc_reset(crtc, &vkms_state->base);
127 if (vkms_state)
128 INIT_WORK(&vkms_state->crc_work, vkms_crc_work_handle);
129}
130
138static const struct drm_crtc_funcs vkms_crtc_funcs = {131static const struct drm_crtc_funcs vkms_crtc_funcs = {
139 .set_config = drm_atomic_helper_set_config,132 .set_config = drm_atomic_helper_set_config,
140 .destroy = drm_crtc_cleanup,133 .destroy = drm_crtc_cleanup,
drivers/gpu/drm/zte/zx_plane.c+2−4
@@ -199,7 +199,6 @@ static void zx_vl_plane_atomic_update(struct drm_plane *plane, · 198 unmodified lines
199 u32 dst_x, dst_y, dst_w, dst_h;199 u32 dst_x, dst_y, dst_w, dst_h;
200 uint32_t format;200 uint32_t format;
201 int fmt;201 int fmt;
202 int num_planes;
203 int i;202 int i;
204 203
205 if (!fb)204 if (!fb)
@@ -218,13 +217,12 @@ static void zx_vl_plane_atomic_update(struct drm_plane *plane, · 12 unmodified lines
218 dst_h = drm_rect_height(dst);217 dst_h = drm_rect_height(dst);
219 218
220 /* Set up data address registers for Y, Cb and Cr planes */219 /* Set up data address registers for Y, Cb and Cr planes */
221 num_planes = drm_format_num_planes(format);
222 paddr_reg = layer + VL_Y;220 paddr_reg = layer + VL_Y;
223 for (i = 0; i < num_planes; i++) {221 for (i = 0; i < fb->format->num_planes; i++) {
224 cma_obj = drm_fb_cma_get_gem_obj(fb, i);222 cma_obj = drm_fb_cma_get_gem_obj(fb, i);
225 paddr = cma_obj->paddr + fb->offsets[i];223 paddr = cma_obj->paddr + fb->offsets[i];
226 paddr += src_y * fb->pitches[i];224 paddr += src_y * fb->pitches[i];
227 paddr += src_x * drm_format_plane_cpp(format, i);225 paddr += src_x * fb->format->cpp[i];
228 zx_writel(paddr_reg, paddr);226 zx_writel(paddr_reg, paddr);
229 paddr_reg += 4;227 paddr_reg += 4;
230 }228 }
drivers/video/hdmi.c+257−0
@@ -650,6 +650,150 @@ hdmi_vendor_any_infoframe_check_only(const union hdmi_vendor_any_infoframe *fram · 649 unmodified lines
650 return 0;650 return 0;
651}651}
652 652
653/**
654 * hdmi_drm_infoframe_init() - initialize an HDMI Dynaminc Range and
655 * mastering infoframe
656 * @frame: HDMI DRM infoframe
657 *
658 * Returns 0 on success or a negative error code on failure.
659 */
660int hdmi_drm_infoframe_init(struct hdmi_drm_infoframe *frame)
661{
662 memset(frame, 0, sizeof(*frame));
663
664 frame->type = HDMI_INFOFRAME_TYPE_DRM;
665 frame->version = 1;
666 frame->length = HDMI_DRM_INFOFRAME_SIZE;
667
668 return 0;
669}
670EXPORT_SYMBOL(hdmi_drm_infoframe_init);
671
672static int hdmi_drm_infoframe_check_only(const struct hdmi_drm_infoframe *frame)
673{
674 if (frame->type != HDMI_INFOFRAME_TYPE_DRM ||
675 frame->version != 1)
676 return -EINVAL;
677
678 if (frame->length != HDMI_DRM_INFOFRAME_SIZE)
679 return -EINVAL;
680
681 return 0;
682}
683
684/**
685 * hdmi_drm_infoframe_check() - check a HDMI DRM infoframe
686 * @frame: HDMI DRM infoframe
687 *
688 * Validates that the infoframe is consistent.
689 * Returns 0 on success or a negative error code on failure.
690 */
691int hdmi_drm_infoframe_check(struct hdmi_drm_infoframe *frame)
692{
693 return hdmi_drm_infoframe_check_only(frame);
694}
695EXPORT_SYMBOL(hdmi_drm_infoframe_check);
696
697/**
698 * hdmi_drm_infoframe_pack_only() - write HDMI DRM infoframe to binary buffer
699 * @frame: HDMI DRM infoframe
700 * @buffer: destination buffer
701 * @size: size of buffer
702 *
703 * Packs the information contained in the @frame structure into a binary
704 * representation that can be written into the corresponding controller
705 * registers. Also computes the checksum as required by section 5.3.5 of
706 * the HDMI 1.4 specification.
707 *
708 * Returns the number of bytes packed into the binary buffer or a negative
709 * error code on failure.
710 */
711ssize_t hdmi_drm_infoframe_pack_only(const struct hdmi_drm_infoframe *frame,
712 void *buffer, size_t size)
713{
714 u8 *ptr = buffer;
715 size_t length;
716 int i;
717
718 length = HDMI_INFOFRAME_HEADER_SIZE + frame->length;
719
720 if (size < length)
721 return -ENOSPC;
722
723 memset(buffer, 0, size);
724
725 ptr[0] = frame->type;
726 ptr[1] = frame->version;
727 ptr[2] = frame->length;
728 ptr[3] = 0; /* checksum */
729
730 /* start infoframe payload */
731 ptr += HDMI_INFOFRAME_HEADER_SIZE;
732
733 *ptr++ = frame->eotf;
734 *ptr++ = frame->metadata_type;
735
736 for (i = 0; i < 3; i++) {
737 *ptr++ = frame->display_primaries[i].x;
738 *ptr++ = frame->display_primaries[i].x >> 8;
739 *ptr++ = frame->display_primaries[i].y;
740 *ptr++ = frame->display_primaries[i].y >> 8;
741 }
742
743 *ptr++ = frame->white_point.x;
744 *ptr++ = frame->white_point.x >> 8;
745
746 *ptr++ = frame->white_point.y;
747 *ptr++ = frame->white_point.y >> 8;
748
749 *ptr++ = frame->max_display_mastering_luminance;
750 *ptr++ = frame->max_display_mastering_luminance >> 8;
751
752 *ptr++ = frame->min_display_mastering_luminance;
753 *ptr++ = frame->min_display_mastering_luminance >> 8;
754
755 *ptr++ = frame->max_cll;
756 *ptr++ = frame->max_cll >> 8;
757
758 *ptr++ = frame->max_fall;
759 *ptr++ = frame->max_fall >> 8;
760
761 hdmi_infoframe_set_checksum(buffer, length);
762
763 return length;
764}
765EXPORT_SYMBOL(hdmi_drm_infoframe_pack_only);
766
767/**
768 * hdmi_drm_infoframe_pack() - check a HDMI DRM infoframe,
769 * and write it to binary buffer
770 * @frame: HDMI DRM infoframe
771 * @buffer: destination buffer
772 * @size: size of buffer
773 *
774 * Validates that the infoframe is consistent and updates derived fields
775 * (eg. length) based on other fields, after which it packs the information
776 * contained in the @frame structure into a binary representation that
777 * can be written into the corresponding controller registers. This function
778 * also computes the checksum as required by section 5.3.5 of the HDMI 1.4
779 * specification.
780 *
781 * Returns the number of bytes packed into the binary buffer or a negative
782 * error code on failure.
783 */
784ssize_t hdmi_drm_infoframe_pack(struct hdmi_drm_infoframe *frame,
785 void *buffer, size_t size)
786{
787 int ret;
788
789 ret = hdmi_drm_infoframe_check(frame);
790 if (ret)
791 return ret;
792
793 return hdmi_drm_infoframe_pack_only(frame, buffer, size);
794}
795EXPORT_SYMBOL(hdmi_drm_infoframe_pack);
796
653/*797/*
654 * hdmi_vendor_any_infoframe_check() - check a vendor infoframe798 * hdmi_vendor_any_infoframe_check() - check a vendor infoframe
655 */799 */
@@ -758,6 +902,10 @@ hdmi_infoframe_pack_only(const union hdmi_infoframe *frame, void *buffer, size_t · 102 unmodified lines
758 length = hdmi_avi_infoframe_pack_only(&frame->avi,902 length = hdmi_avi_infoframe_pack_only(&frame->avi,
759 buffer, size);903 buffer, size);
760 break;904 break;
905 case HDMI_INFOFRAME_TYPE_DRM:
906 length = hdmi_drm_infoframe_pack_only(&frame->drm,
907 buffer, size);
908 break;
761 case HDMI_INFOFRAME_TYPE_SPD:909 case HDMI_INFOFRAME_TYPE_SPD:
762 length = hdmi_spd_infoframe_pack_only(&frame->spd,910 length = hdmi_spd_infoframe_pack_only(&frame->spd,
763 buffer, size);911 buffer, size);
@@ -806,6 +954,9 @@ hdmi_infoframe_pack(union hdmi_infoframe *frame, · 42 unmodified lines
806 case HDMI_INFOFRAME_TYPE_AVI:954 case HDMI_INFOFRAME_TYPE_AVI:
807 length = hdmi_avi_infoframe_pack(&frame->avi, buffer, size);955 length = hdmi_avi_infoframe_pack(&frame->avi, buffer, size);
808 break;956 break;
957 case HDMI_INFOFRAME_TYPE_DRM:
958 length = hdmi_drm_infoframe_pack(&frame->drm, buffer, size);
959 break;
809 case HDMI_INFOFRAME_TYPE_SPD:960 case HDMI_INFOFRAME_TYPE_SPD:
810 length = hdmi_spd_infoframe_pack(&frame->spd, buffer, size);961 length = hdmi_spd_infoframe_pack(&frame->spd, buffer, size);
811 break;962 break;
@@ -838,6 +989,8 @@ static const char *hdmi_infoframe_type_get_name(enum hdmi_infoframe_type type) · 26 unmodified lines
838 return "Source Product Description (SPD)";989 return "Source Product Description (SPD)";
839 case HDMI_INFOFRAME_TYPE_AUDIO:990 case HDMI_INFOFRAME_TYPE_AUDIO:
840 return "Audio";991 return "Audio";
992 case HDMI_INFOFRAME_TYPE_DRM:
993 return "Dynamic Range and Mastering";
841 }994 }
842 return "Reserved";995 return "Reserved";
843}996}
@@ -1284,6 +1437,40 @@ static void hdmi_audio_infoframe_log(const char *level, · 440 unmodified lines
1284 frame->downmix_inhibit ? "Yes" : "No");1437 frame->downmix_inhibit ? "Yes" : "No");
1285}1438}
1286 1439
1440/**
1441 * hdmi_drm_infoframe_log() - log info of HDMI DRM infoframe
1442 * @level: logging level
1443 * @dev: device
1444 * @frame: HDMI DRM infoframe
1445 */
1446static void hdmi_drm_infoframe_log(const char *level,
1447 struct device *dev,
1448 const struct hdmi_drm_infoframe *frame)
1449{
1450 int i;
1451
1452 hdmi_infoframe_log_header(level, dev,
1453 (struct hdmi_any_infoframe *)frame);
1454 hdmi_log("length: %d\n", frame->length);
1455 hdmi_log("metadata type: %d\n", frame->metadata_type);
1456 hdmi_log("eotf: %d\n", frame->eotf);
1457 for (i = 0; i < 3; i++) {
1458 hdmi_log("x[%d]: %d\n", i, frame->display_primaries[i].x);
1459 hdmi_log("y[%d]: %d\n", i, frame->display_primaries[i].y);
1460 }
1461
1462 hdmi_log("white point x: %d\n", frame->white_point.x);
1463 hdmi_log("white point y: %d\n", frame->white_point.y);
1464
1465 hdmi_log("max_display_mastering_luminance: %d\n",
1466 frame->max_display_mastering_luminance);
1467 hdmi_log("min_display_mastering_luminance: %d\n",
1468 frame->min_display_mastering_luminance);
1469
1470 hdmi_log("max_cll: %d\n", frame->max_cll);
1471 hdmi_log("max_fall: %d\n", frame->max_fall);
1472}
1473
1287static const char *1474static const char *
1288hdmi_3d_structure_get_name(enum hdmi_3d_structure s3d_struct)1475hdmi_3d_structure_get_name(enum hdmi_3d_structure s3d_struct)
1289{1476{
@@ -1372,6 +1559,9 @@ void hdmi_infoframe_log(const char *level, · 82 unmodified lines
1372 case HDMI_INFOFRAME_TYPE_VENDOR:1559 case HDMI_INFOFRAME_TYPE_VENDOR:
1373 hdmi_vendor_any_infoframe_log(level, dev, &frame->vendor);1560 hdmi_vendor_any_infoframe_log(level, dev, &frame->vendor);
1374 break;1561 break;
1562 case HDMI_INFOFRAME_TYPE_DRM:
1563 hdmi_drm_infoframe_log(level, dev, &frame->drm);
1564 break;
1375 }1565 }
1376}1566}
1377EXPORT_SYMBOL(hdmi_infoframe_log);1567EXPORT_SYMBOL(hdmi_infoframe_log);
@@ -1614,6 +1804,70 @@ hdmi_vendor_any_infoframe_unpack(union hdmi_vendor_any_infoframe *frame, · 236 unmodified lines
1614 return 0;1804 return 0;
1615}1805}
1616 1806
1807/**
1808 * hdmi_drm_infoframe_unpack() - unpack binary buffer to a HDMI DRM infoframe
1809 * @frame: HDMI DRM infoframe
1810 * @buffer: source buffer
1811 * @size: size of buffer
1812 *
1813 * Unpacks the information contained in binary @buffer into a structured
1814 * @frame of the HDMI Dynamic Range and Mastering (DRM) information frame.
1815 * Also verifies the checksum as required by section 5.3.5 of the HDMI 1.4
1816 * specification.
1817 *
1818 * Returns 0 on success or a negative error code on failure.
1819 */
1820static int hdmi_drm_infoframe_unpack(struct hdmi_drm_infoframe *frame,
1821 const void *buffer, size_t size)
1822{
1823 const u8 *ptr = buffer;
1824 const u8 *temp;
1825 u8 x_lsb, x_msb;
1826 u8 y_lsb, y_msb;
1827 int ret;
1828 int i;
1829
1830 if (size < HDMI_INFOFRAME_SIZE(DRM))
1831 return -EINVAL;
1832
1833 if (ptr[0] != HDMI_INFOFRAME_TYPE_DRM ||
1834 ptr[1] != 1 ||
1835 ptr[2] != HDMI_DRM_INFOFRAME_SIZE)
1836 return -EINVAL;
1837
1838 if (hdmi_infoframe_checksum(buffer, HDMI_INFOFRAME_SIZE(DRM)) != 0)
1839 return -EINVAL;
1840
1841 ret = hdmi_drm_infoframe_init(frame);
1842 if (ret)
1843 return ret;
1844
1845 ptr += HDMI_INFOFRAME_HEADER_SIZE;
1846
1847 frame->eotf = ptr[0] & 0x7;
1848 frame->metadata_type = ptr[1] & 0x7;
1849
1850 temp = ptr + 2;
1851 for (i = 0; i < 3; i++) {
1852 x_lsb = *temp++;
1853 x_msb = *temp++;
1854 frame->display_primaries[i].x = (x_msb << 8) | x_lsb;
1855 y_lsb = *temp++;
1856 y_msb = *temp++;
1857 frame->display_primaries[i].y = (y_msb << 8) | y_lsb;
1858 }
1859
1860 frame->white_point.x = (ptr[15] << 8) | ptr[14];
1861 frame->white_point.y = (ptr[17] << 8) | ptr[16];
1862
1863 frame->max_display_mastering_luminance = (ptr[19] << 8) | ptr[18];
1864 frame->min_display_mastering_luminance = (ptr[21] << 8) | ptr[20];
1865 frame->max_cll = (ptr[23] << 8) | ptr[22];
1866 frame->max_fall = (ptr[25] << 8) | ptr[24];
1867
1868 return 0;
1869}
1870
1617/**1871/**
1618 * hdmi_infoframe_unpack() - unpack binary buffer to a HDMI infoframe1872 * hdmi_infoframe_unpack() - unpack binary buffer to a HDMI infoframe
1619 * @frame: HDMI infoframe1873 * @frame: HDMI infoframe
@@ -1640,6 +1894,9 @@ int hdmi_infoframe_unpack(union hdmi_infoframe *frame, · 20 unmodified lines
1640 case HDMI_INFOFRAME_TYPE_AVI:1894 case HDMI_INFOFRAME_TYPE_AVI:
1641 ret = hdmi_avi_infoframe_unpack(&frame->avi, buffer, size);1895 ret = hdmi_avi_infoframe_unpack(&frame->avi, buffer, size);
1642 break;1896 break;
1897 case HDMI_INFOFRAME_TYPE_DRM:
1898 ret = hdmi_drm_infoframe_unpack(&frame->drm, buffer, size);
1899 break;
1643 case HDMI_INFOFRAME_TYPE_SPD:1900 case HDMI_INFOFRAME_TYPE_SPD:
1644 ret = hdmi_spd_infoframe_unpack(&frame->spd, buffer, size);1901 ret = hdmi_spd_infoframe_unpack(&frame->spd, buffer, size);
1645 break;1902 break;
include/drm/drm_atomic_state_helper.h+2−0
@@ -37,6 +37,8 @@ struct drm_private_state; · 36 unmodified lines
37struct drm_modeset_acquire_ctx;37struct drm_modeset_acquire_ctx;
38struct drm_device;38struct drm_device;
39 39
40void __drm_atomic_helper_crtc_reset(struct drm_crtc *crtc,
41 struct drm_crtc_state *state);
40void drm_atomic_helper_crtc_reset(struct drm_crtc *crtc);42void drm_atomic_helper_crtc_reset(struct drm_crtc *crtc);
41void __drm_atomic_helper_crtc_duplicate_state(struct drm_crtc *crtc,43void __drm_atomic_helper_crtc_duplicate_state(struct drm_crtc *crtc,
42 struct drm_crtc_state *state);44 struct drm_crtc_state *state);
include/drm/drm_connector.h+14−0
@@ -517,6 +517,10 @@ struct drm_connector_state { · 516 unmodified lines
517 * Used by the atomic helpers to select the encoder, through the517 * Used by the atomic helpers to select the encoder, through the
518 * &drm_connector_helper_funcs.atomic_best_encoder or518 * &drm_connector_helper_funcs.atomic_best_encoder or
519 * &drm_connector_helper_funcs.best_encoder callbacks.519 * &drm_connector_helper_funcs.best_encoder callbacks.
520 *
521 * NOTE: Atomic drivers must fill this out (either themselves or through
522 * helpers), for otherwise the GETCONNECTOR and GETENCODER IOCTLs will
523 * not return correct data to userspace.
520 */524 */
521 struct drm_encoder *best_encoder;525 struct drm_encoder *best_encoder;
522 526
@@ -599,6 +603,12 @@ struct drm_connector_state { · 76 unmodified lines
599 * and the connector bpc limitations obtained from edid.603 * and the connector bpc limitations obtained from edid.
600 */604 */
601 u8 max_bpc;605 u8 max_bpc;
606
607 /**
608 * @hdr_output_metadata:
609 * DRM blob property for HDR output metadata
610 */
611 struct drm_property_blob *hdr_output_metadata;
602};612};
603 613
604/**614/**
@@ -1239,6 +1249,10 @@ struct drm_connector { · 634 unmodified lines
1239 * &drm_mode_config.connector_free_work.1249 * &drm_mode_config.connector_free_work.
1240 */1250 */
1241 struct llist_node free_node;1251 struct llist_node free_node;
1252
1253 /* HDR metdata */
1254 struct hdr_output_metadata hdr_output_metadata;
1255 struct hdr_sink_metadata hdr_sink_metadata;
1242};1256};
1243 1257
1244#define obj_to_connector(x) container_of(x, struct drm_connector, base)1258#define obj_to_connector(x) container_of(x, struct drm_connector, base)
include/drm/drm_device.h+4−0
@@ -17,6 +17,7 @@ struct drm_vblank_crtc; · 16 unmodified lines
17struct drm_sg_mem;17struct drm_sg_mem;
18struct drm_local_map;18struct drm_local_map;
19struct drm_vma_offset_manager;19struct drm_vma_offset_manager;
20struct drm_vram_mm;
20struct drm_fb_helper;21struct drm_fb_helper;
21 22
22struct inode;23struct inode;
@@ -286,6 +287,9 @@ struct drm_device { · 263 unmodified lines
286 /** @vma_offset_manager: GEM information */287 /** @vma_offset_manager: GEM information */
287 struct drm_vma_offset_manager *vma_offset_manager;288 struct drm_vma_offset_manager *vma_offset_manager;
288 289
290 /** @vram_mm: VRAM MM memory manager */
291 struct drm_vram_mm *vram_mm;
292
289 /**293 /**
290 * @switch_power_state:294 * @switch_power_state:
291 *295 *
include/drm/drm_edid.h+5−0
@@ -25,6 +25,7 @@ · 24 unmodified lines
25 25
26#include <linux/types.h>26#include <linux/types.h>
27#include <linux/hdmi.h>27#include <linux/hdmi.h>
28#include <drm/drm_mode.h>
28 29
29struct drm_device;30struct drm_device;
30struct i2c_adapter;31struct i2c_adapter;
@@ -370,6 +371,10 @@ drm_hdmi_avi_infoframe_quant_range(struct hdmi_avi_infoframe *frame, · 339 unmodified lines
370 const struct drm_display_mode *mode,371 const struct drm_display_mode *mode,
371 enum hdmi_quantization_range rgb_quant_range);372 enum hdmi_quantization_range rgb_quant_range);
372 373
374int
375drm_hdmi_infoframe_set_hdr_metadata(struct hdmi_drm_infoframe *frame,
376 const struct drm_connector_state *conn_state);
377
373/**378/**
374 * drm_eld_mnl - Get ELD monitor name length in bytes.379 * drm_eld_mnl - Get ELD monitor name length in bytes.
375 * @eld: pointer to an eld memory structure with mnl set380 * @eld: pointer to an eld memory structure with mnl set
include/drm/drm_fb_helper.h+0−10
@@ -49,9 +49,6 @@ struct drm_fb_offset { · 48 unmodified lines
49 49
50struct drm_fb_helper_crtc {50struct drm_fb_helper_crtc {
51 struct drm_mode_set mode_set;51 struct drm_mode_set mode_set;
52 struct drm_display_mode *desired_mode;
53 int x, y;
54 int rotation;
55};52};
56 53
57/**54/**
@@ -151,13 +148,6 @@ struct drm_fb_helper { · 93 unmodified lines
151 struct drm_fb_helper_crtc *crtc_info;148 struct drm_fb_helper_crtc *crtc_info;
152 int connector_count;149 int connector_count;
153 int connector_info_alloc_count;150 int connector_info_alloc_count;
154 /**
155 * @sw_rotations:
156 * Bitmask of all rotations requested for panel-orientation which
157 * could not be handled in hardware. If only one bit is set
158 * fbdev->fbcon_rotate_hint gets set to the requested rotation.
159 */
160 int sw_rotations;
161 /**151 /**
162 * @connector_info:152 * @connector_info:
163 *153 *
include/drm/drm_fourcc.h+44−6
@@ -260,6 +260,50 @@ drm_format_info_is_yuv_sampling_444(const struct drm_format_info *info) · 259 unmodified lines
260 return info->is_yuv && info->hsub == 1 && info->vsub == 1;260 return info->is_yuv && info->hsub == 1 && info->vsub == 1;
261}261}
262 262
263/**
264 * drm_format_info_plane_width - width of the plane given the first plane
265 * @info: pixel format info
266 * @width: width of the first plane
267 * @plane: plane index
268 *
269 * Returns:
270 * The width of @plane, given that the width of the first plane is @width.
271 */
272static inline
273int drm_format_info_plane_width(const struct drm_format_info *info, int width,
274 int plane)
275{
276 if (!info || plane >= info->num_planes)
277 return 0;
278
279 if (plane == 0)
280 return width;
281
282 return width / info->hsub;
283}
284
285/**
286 * drm_format_info_plane_height - height of the plane given the first plane
287 * @info: pixel format info
288 * @height: height of the first plane
289 * @plane: plane index
290 *
291 * Returns:
292 * The height of @plane, given that the height of the first plane is @height.
293 */
294static inline
295int drm_format_info_plane_height(const struct drm_format_info *info, int height,
296 int plane)
297{
298 if (!info || plane >= info->num_planes)
299 return 0;
300
301 if (plane == 0)
302 return height;
303
304 return height / info->vsub;
305}
306
263const struct drm_format_info *__drm_format_info(u32 format);307const struct drm_format_info *__drm_format_info(u32 format);
264const struct drm_format_info *drm_format_info(u32 format);308const struct drm_format_info *drm_format_info(u32 format);
265const struct drm_format_info *309const struct drm_format_info *
@@ -268,12 +312,6 @@ drm_get_format_info(struct drm_device *dev, · 2 unmodified lines
268uint32_t drm_mode_legacy_fb_format(uint32_t bpp, uint32_t depth);312uint32_t drm_mode_legacy_fb_format(uint32_t bpp, uint32_t depth);
269uint32_t drm_driver_legacy_fb_format(struct drm_device *dev,313uint32_t drm_driver_legacy_fb_format(struct drm_device *dev,
270 uint32_t bpp, uint32_t depth);314 uint32_t bpp, uint32_t depth);
271int drm_format_num_planes(uint32_t format);
272int drm_format_plane_cpp(uint32_t format, int plane);
273int drm_format_horz_chroma_subsampling(uint32_t format);
274int drm_format_vert_chroma_subsampling(uint32_t format);
275int drm_format_plane_width(int width, uint32_t format, int plane);
276int drm_format_plane_height(int height, uint32_t format, int plane);
277unsigned int drm_format_info_block_width(const struct drm_format_info *info,315unsigned int drm_format_info_block_width(const struct drm_format_info *info,
278 int plane);316 int plane);
279unsigned int drm_format_info_block_height(const struct drm_format_info *info,317unsigned int drm_format_info_block_height(const struct drm_format_info *info,
include/drm/drm_gem_vram_helper.h+162−0
@@ -0,0 +1,162 @@
1/* SPDX-License-Identifier: GPL-2.0-or-later */
2
3#ifndef DRM_GEM_VRAM_HELPER_H
4#define DRM_GEM_VRAM_HELPER_H
5
6#include <drm/drm_gem.h>
7#include <drm/ttm/ttm_bo_api.h>
8#include <drm/ttm/ttm_placement.h>
9#include <linux/kernel.h> /* for container_of() */
10
11struct drm_mode_create_dumb;
12struct drm_vram_mm_funcs;
13struct filp;
14struct vm_area_struct;
15
16#define DRM_GEM_VRAM_PL_FLAG_VRAM TTM_PL_FLAG_VRAM
17#define DRM_GEM_VRAM_PL_FLAG_SYSTEM TTM_PL_FLAG_SYSTEM
18
19/*
20 * Buffer-object helpers
21 */
22
23/**
24 * struct drm_gem_vram_object - GEM object backed by VRAM
25 * @gem: GEM object
26 * @bo: TTM buffer object
27 * @kmap: Mapping information for @bo
28 * @placement: TTM placement information. Supported placements are \
29 %TTM_PL_VRAM and %TTM_PL_SYSTEM
30 * @placements: TTM placement information.
31 * @pin_count: Pin counter
32 *
33 * The type struct drm_gem_vram_object represents a GEM object that is
34 * backed by VRAM. It can be used for simple framebuffer devices with
35 * dedicated memory. The buffer object can be evicted to system memory if
36 * video memory becomes scarce.
37 */
38struct drm_gem_vram_object {
39 struct drm_gem_object gem;
40 struct ttm_buffer_object bo;
41 struct ttm_bo_kmap_obj kmap;
42
43 /* Supported placements are %TTM_PL_VRAM and %TTM_PL_SYSTEM */
44 struct ttm_placement placement;
45 struct ttm_place placements[2];
46
47 int pin_count;
48};
49
50/**
51 * Returns the container of type &struct drm_gem_vram_object
52 * for field bo.
53 * @bo: the VRAM buffer object
54 * Returns: The containing GEM VRAM object
55 */
56static inline struct drm_gem_vram_object *drm_gem_vram_of_bo(
57 struct ttm_buffer_object *bo)
58{
59 return container_of(bo, struct drm_gem_vram_object, bo);
60}
61
62/**
63 * Returns the container of type &struct drm_gem_vram_object
64 * for field gem.
65 * @gem: the GEM object
66 * Returns: The containing GEM VRAM object
67 */
68static inline struct drm_gem_vram_object *drm_gem_vram_of_gem(
69 struct drm_gem_object *gem)
70{
71 return container_of(gem, struct drm_gem_vram_object, gem);
72}
73
74struct drm_gem_vram_object *drm_gem_vram_create(struct drm_device *dev,
75 struct ttm_bo_device *bdev,
76 size_t size,
77 unsigned long pg_align,
78 bool interruptible);
79void drm_gem_vram_put(struct drm_gem_vram_object *gbo);
80int drm_gem_vram_lock(struct drm_gem_vram_object *gbo, bool no_wait);
81void drm_gem_vram_unlock(struct drm_gem_vram_object *gbo);
82u64 drm_gem_vram_mmap_offset(struct drm_gem_vram_object *gbo);
83s64 drm_gem_vram_offset(struct drm_gem_vram_object *gbo);
84int drm_gem_vram_pin(struct drm_gem_vram_object *gbo, unsigned long pl_flag);
85int drm_gem_vram_pin_locked(struct drm_gem_vram_object *gbo,
86 unsigned long pl_flag);
87int drm_gem_vram_unpin(struct drm_gem_vram_object *gbo);
88int drm_gem_vram_unpin_locked(struct drm_gem_vram_object *gbo);
89void *drm_gem_vram_kmap_at(struct drm_gem_vram_object *gbo, bool map,
90 bool *is_iomem, struct ttm_bo_kmap_obj *kmap);
91void *drm_gem_vram_kmap(struct drm_gem_vram_object *gbo, bool map,
92 bool *is_iomem);
93void drm_gem_vram_kunmap_at(struct drm_gem_vram_object *gbo,
94 struct ttm_bo_kmap_obj *kmap);
95void drm_gem_vram_kunmap(struct drm_gem_vram_object *gbo);
96
97int drm_gem_vram_fill_create_dumb(struct drm_file *file,
98 struct drm_device *dev,
99 struct ttm_bo_device *bdev,
100 unsigned long pg_align,
101 bool interruptible,
102 struct drm_mode_create_dumb *args);
103
104/*
105 * Helpers for struct ttm_bo_driver
106 */
107
108void drm_gem_vram_bo_driver_evict_flags(struct ttm_buffer_object *bo,
109 struct ttm_placement *pl);
110
111int drm_gem_vram_bo_driver_verify_access(struct ttm_buffer_object *bo,
112 struct file *filp);
113
114extern const struct drm_vram_mm_funcs drm_gem_vram_mm_funcs;
115
116/*
117 * Helpers for struct drm_driver
118 */
119
120void drm_gem_vram_driver_gem_free_object_unlocked(struct drm_gem_object *gem);
121int drm_gem_vram_driver_dumb_create(struct drm_file *file,
122 struct drm_device *dev,
123 struct drm_mode_create_dumb *args);
124int drm_gem_vram_driver_dumb_mmap_offset(struct drm_file *file,
125 struct drm_device *dev,
126 uint32_t handle, uint64_t *offset);
127
128/**
129 * define DRM_GEM_VRAM_DRIVER - default callback functions for \
130 &struct drm_driver
131 *
132 * Drivers that use VRAM MM and GEM VRAM can use this macro to initialize
133 * &struct drm_driver with default functions.
134 */
135#define DRM_GEM_VRAM_DRIVER \
136 .gem_free_object_unlocked = \
137 drm_gem_vram_driver_gem_free_object_unlocked, \
138 .dumb_create = drm_gem_vram_driver_dumb_create, \
139 .dumb_map_offset = drm_gem_vram_driver_dumb_mmap_offset
140
141/*
142 * PRIME helpers for struct drm_driver
143 */
144
145int drm_gem_vram_driver_gem_prime_pin(struct drm_gem_object *obj);
146void drm_gem_vram_driver_gem_prime_unpin(struct drm_gem_object *obj);
147void *drm_gem_vram_driver_gem_prime_vmap(struct drm_gem_object *obj);
148void drm_gem_vram_driver_gem_prime_vunmap(struct drm_gem_object *obj,
149 void *vaddr);
150int drm_gem_vram_driver_gem_prime_mmap(struct drm_gem_object *obj,
151 struct vm_area_struct *vma);
152
153#define DRM_GEM_VRAM_DRIVER_PRIME \
154 .gem_prime_export = drm_gem_prime_export, \
155 .gem_prime_import = drm_gem_prime_import, \
156 .gem_prime_pin = drm_gem_vram_driver_gem_prime_pin, \
157 .gem_prime_unpin = drm_gem_vram_driver_gem_prime_unpin, \
158 .gem_prime_vmap = drm_gem_vram_driver_gem_prime_vmap, \
159 .gem_prime_vunmap = drm_gem_vram_driver_gem_prime_vunmap, \
160 .gem_prime_mmap = drm_gem_vram_driver_gem_prime_mmap
161
162#endif
include/drm/drm_mode_config.h+7−0
@@ -836,6 +836,13 @@ struct drm_mode_config { · 835 unmodified lines
836 */836 */
837 struct drm_property *writeback_out_fence_ptr_property;837 struct drm_property *writeback_out_fence_ptr_property;
838 838
839 /**
840 * hdr_output_metadata_property: Connector property containing hdr
841 * metatda. This will be provided by userspace compositors based
842 * on HDR content
843 */
844 struct drm_property *hdr_output_metadata_property;
845
839 /* dumb ioctl parameters */846 /* dumb ioctl parameters */
840 uint32_t preferred_depth, prefer_shadow;847 uint32_t preferred_depth, prefer_shadow;
841 848
include/drm/drm_vram_mm_helper.h+102−0
@@ -0,0 +1,102 @@
1/* SPDX-License-Identifier: GPL-2.0-or-later */
2
3#ifndef DRM_VRAM_MM_HELPER_H
4#define DRM_VRAM_MM_HELPER_H
5
6#include <drm/ttm/ttm_bo_driver.h>
7
8struct drm_device;
9
10/**
11 * struct drm_vram_mm_funcs - Callback functions for &struct drm_vram_mm
12 * @evict_flags: Provides an implementation for struct \
13 &ttm_bo_driver.evict_flags
14 * @verify_access: Provides an implementation for \
15 struct &ttm_bo_driver.verify_access
16 *
17 * These callback function integrate VRAM MM with TTM buffer objects. New
18 * functions can be added if necessary.
19 */
20struct drm_vram_mm_funcs {
21 void (*evict_flags)(struct ttm_buffer_object *bo,
22 struct ttm_placement *placement);
23 int (*verify_access)(struct ttm_buffer_object *bo, struct file *filp);
24};
25
26/**
27 * struct drm_vram_mm - An instance of VRAM MM
28 * @vram_base: Base address of the managed video memory
29 * @vram_size: Size of the managed video memory in bytes
30 * @bdev: The TTM BO device.
31 * @funcs: TTM BO functions
32 *
33 * The fields &struct drm_vram_mm.vram_base and
34 * &struct drm_vram_mm.vrm_size are managed by VRAM MM, but are
35 * available for public read access. Use the field
36 * &struct drm_vram_mm.bdev to access the TTM BO device.
37 */
38struct drm_vram_mm {
39 uint64_t vram_base;
40 size_t vram_size;
41
42 struct ttm_bo_device bdev;
43
44 const struct drm_vram_mm_funcs *funcs;
45};
46
47/**
48 * drm_vram_mm_of_bdev() - \
49 Returns the container of type &struct ttm_bo_device for field bdev.
50 * @bdev: the TTM BO device
51 *
52 * Returns:
53 * The containing instance of &struct drm_vram_mm
54 */
55static inline struct drm_vram_mm *drm_vram_mm_of_bdev(
56 struct ttm_bo_device *bdev)
57{
58 return container_of(bdev, struct drm_vram_mm, bdev);
59}
60
61int drm_vram_mm_init(struct drm_vram_mm *vmm, struct drm_device *dev,
62 uint64_t vram_base, size_t vram_size,
63 const struct drm_vram_mm_funcs *funcs);
64void drm_vram_mm_cleanup(struct drm_vram_mm *vmm);
65
66int drm_vram_mm_mmap(struct file *filp, struct vm_area_struct *vma,
67 struct drm_vram_mm *vmm);
68
69/*
70 * Helpers for integration with struct drm_device
71 */
72
73struct drm_vram_mm *drm_vram_helper_alloc_mm(
74 struct drm_device *dev, uint64_t vram_base, size_t vram_size,
75 const struct drm_vram_mm_funcs *funcs);
76void drm_vram_helper_release_mm(struct drm_device *dev);
77
78/*
79 * Helpers for &struct file_operations
80 */
81
82int drm_vram_mm_file_operations_mmap(
83 struct file *filp, struct vm_area_struct *vma);
84
85/**
86 * define DRM_VRAM_MM_FILE_OPERATIONS - default callback functions for \
87 &struct file_operations
88 *
89 * Drivers that use VRAM MM can use this macro to initialize
90 * &struct file_operations with default functions.
91 */
92#define DRM_VRAM_MM_FILE_OPERATIONS \
93 .llseek = no_llseek, \
94 .read = drm_read, \
95 .poll = drm_poll, \
96 .unlocked_ioctl = drm_ioctl, \
97 .compat_ioctl = drm_compat_ioctl, \
98 .mmap = drm_vram_mm_file_operations_mmap, \
99 .open = drm_open, \
100 .release = drm_release \
101
102#endif
include/drm/gma_drm.h+0−25
@@ -1,25 +0,0 @@
1/**************************************************************************
2 * Copyright (c) 2007-2011, Intel Corporation.
3 * All Rights Reserved.
4 * Copyright (c) 2008, Tungsten Graphics Inc. Cedar Park, TX., USA.
5 * All Rights Reserved.
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms and conditions of the GNU General Public License,
9 * version 2, as published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
15 *
16 * You should have received a copy of the GNU General Public License along with
17 * this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
19 *
20 **************************************************************************/
21
22#ifndef _GMA_DRM_H_
23#define _GMA_DRM_H_
24
25#endif
include/drm/gpu_scheduler.h+3−5
@@ -167,9 +167,6 @@ struct drm_sched_fence *to_drm_sched_fence(struct dma_fence *f); · 166 unmodified lines
167 * @sched: the scheduler instance on which this job is scheduled.167 * @sched: the scheduler instance on which this job is scheduled.
168 * @s_fence: contains the fences for the scheduling of job.168 * @s_fence: contains the fences for the scheduling of job.
169 * @finish_cb: the callback for the finished fence.169 * @finish_cb: the callback for the finished fence.
170 * @finish_work: schedules the function @drm_sched_job_finish once the job has
171 * finished to remove the job from the
172 * @drm_gpu_scheduler.ring_mirror_list.
173 * @node: used to append this struct to the @drm_gpu_scheduler.ring_mirror_list.170 * @node: used to append this struct to the @drm_gpu_scheduler.ring_mirror_list.
174 * @id: a unique id assigned to each job scheduled on the scheduler.171 * @id: a unique id assigned to each job scheduled on the scheduler.
175 * @karma: increment on every hang caused by this job. If this exceeds the hang172 * @karma: increment on every hang caused by this job. If this exceeds the hang
@@ -188,7 +185,6 @@ struct drm_sched_job { · 12 unmodified lines
188 struct drm_gpu_scheduler *sched;185 struct drm_gpu_scheduler *sched;
189 struct drm_sched_fence *s_fence;186 struct drm_sched_fence *s_fence;
190 struct dma_fence_cb finish_cb;187 struct dma_fence_cb finish_cb;
191 struct work_struct finish_work;
192 struct list_head node;188 struct list_head node;
193 uint64_t id;189 uint64_t id;
194 atomic_t karma;190 atomic_t karma;
@@ -263,6 +259,7 @@ struct drm_sched_backend_ops { · 68 unmodified lines
263 * guilty and it will be considered for scheduling further.259 * guilty and it will be considered for scheduling further.
264 * @num_jobs: the number of jobs in queue in the scheduler260 * @num_jobs: the number of jobs in queue in the scheduler
265 * @ready: marks if the underlying HW is ready to work261 * @ready: marks if the underlying HW is ready to work
262 * @free_guilty: A hit to time out handler to free the guilty job.
266 *263 *
267 * One scheduler is implemented for each hardware ring.264 * One scheduler is implemented for each hardware ring.
268 */265 */
@@ -283,6 +280,7 @@ struct drm_gpu_scheduler { · 14 unmodified lines
283 int hang_limit;280 int hang_limit;
284 atomic_t num_jobs;281 atomic_t num_jobs;
285 bool ready;282 bool ready;
283 bool free_guilty;
286};284};
287 285
288int drm_sched_init(struct drm_gpu_scheduler *sched,286int drm_sched_init(struct drm_gpu_scheduler *sched,
@@ -296,7 +294,7 @@ int drm_sched_job_init(struct drm_sched_job *job, · 7 unmodified lines
296 void *owner);294 void *owner);
297void drm_sched_job_cleanup(struct drm_sched_job *job);295void drm_sched_job_cleanup(struct drm_sched_job *job);
298void drm_sched_wakeup(struct drm_gpu_scheduler *sched);296void drm_sched_wakeup(struct drm_gpu_scheduler *sched);
299void drm_sched_stop(struct drm_gpu_scheduler *sched);297void drm_sched_stop(struct drm_gpu_scheduler *sched, struct drm_sched_job *bad);
300void drm_sched_start(struct drm_gpu_scheduler *sched, bool full_recovery);298void drm_sched_start(struct drm_gpu_scheduler *sched, bool full_recovery);
301void drm_sched_resubmit_jobs(struct drm_gpu_scheduler *sched);299void drm_sched_resubmit_jobs(struct drm_gpu_scheduler *sched);
302void drm_sched_increase_karma(struct drm_sched_job *bad);300void drm_sched_increase_karma(struct drm_sched_job *bad);
include/linux/dma-buf.h+38−9
@@ -39,18 +39,20 @@ struct dma_buf_attachment; · 38 unmodified lines
39 39
40/**40/**
41 * struct dma_buf_ops - operations possible on struct dma_buf41 * struct dma_buf_ops - operations possible on struct dma_buf
42 * @map_atomic: [optional] maps a page from the buffer into kernel address
43 * space, users may not block until the subsequent unmap call.
44 * This callback must not sleep.
45 * @unmap_atomic: [optional] unmaps a atomically mapped page from the buffer.
46 * This Callback must not sleep.
47 * @map: [optional] maps a page from the buffer into kernel address space.
48 * @unmap: [optional] unmaps a page from the buffer.
49 * @vmap: [optional] creates a virtual mapping for the buffer into kernel42 * @vmap: [optional] creates a virtual mapping for the buffer into kernel
50 * address space. Same restrictions as for vmap and friends apply.43 * address space. Same restrictions as for vmap and friends apply.
51 * @vunmap: [optional] unmaps a vmap from the buffer44 * @vunmap: [optional] unmaps a vmap from the buffer
52 */45 */
53struct dma_buf_ops {46struct dma_buf_ops {
47 /**
48 * @cache_sgt_mapping:
49 *
50 * If true the framework will cache the first mapping made for each
51 * attachment. This avoids creating mappings for attachments multiple
52 * times.
53 */
54 bool cache_sgt_mapping;
55
54 /**56 /**
55 * @attach:57 * @attach:
56 *58 *
@@ -205,8 +207,6 @@ struct dma_buf_ops { · 148 unmodified lines
205 * to be restarted.207 * to be restarted.
206 */208 */
207 int (*end_cpu_access)(struct dma_buf *, enum dma_data_direction);209 int (*end_cpu_access)(struct dma_buf *, enum dma_data_direction);
208 void *(*map)(struct dma_buf *, unsigned long);
209 void (*unmap)(struct dma_buf *, unsigned long, void *);
210 210
211 /**211 /**
212 * @mmap:212 * @mmap:
@@ -245,6 +245,31 @@ struct dma_buf_ops { · 32 unmodified lines
245 */245 */
246 int (*mmap)(struct dma_buf *, struct vm_area_struct *vma);246 int (*mmap)(struct dma_buf *, struct vm_area_struct *vma);
247 247
248 /**
249 * @map:
250 *
251 * Maps a page from the buffer into kernel address space. The page is
252 * specified by offset into the buffer in PAGE_SIZE units.
253 *
254 * This callback is optional.
255 *
256 * Returns:
257 *
258 * Virtual address pointer where requested page can be accessed. NULL
259 * on error or when this function is unimplemented by the exporter.
260 */
261 void *(*map)(struct dma_buf *, unsigned long);
262
263 /**
264 * @unmap:
265 *
266 * Unmaps a page from the buffer. Page offset and address pointer should
267 * be the same as the one passed to and returned by matching call to map.
268 *
269 * This callback is optional.
270 */
271 void (*unmap)(struct dma_buf *, unsigned long, void *);
272
248 void *(*vmap)(struct dma_buf *);273 void *(*vmap)(struct dma_buf *);
249 void (*vunmap)(struct dma_buf *, void *vaddr);274 void (*vunmap)(struct dma_buf *, void *vaddr);
250};275};
@@ -307,6 +332,8 @@ struct dma_buf { · 56 unmodified lines
307 * @dmabuf: buffer for this attachment.332 * @dmabuf: buffer for this attachment.
308 * @dev: device attached to the buffer.333 * @dev: device attached to the buffer.
309 * @node: list of dma_buf_attachment.334 * @node: list of dma_buf_attachment.
335 * @sgt: cached mapping.
336 * @dir: direction of cached mapping.
310 * @priv: exporter specific attachment data.337 * @priv: exporter specific attachment data.
311 *338 *
312 * This structure holds the attachment information between the dma_buf buffer339 * This structure holds the attachment information between the dma_buf buffer
@@ -322,6 +349,8 @@ struct dma_buf_attachment { · 9 unmodified lines
322 struct dma_buf *dmabuf;349 struct dma_buf *dmabuf;
323 struct device *dev;350 struct device *dev;
324 struct list_head node;351 struct list_head node;
352 struct sg_table *sgt;
353 enum dma_data_direction dir;
325 void *priv;354 void *priv;
326};355};
327 356
include/linux/hdmi.h+55−0
@@ -47,6 +47,7 @@ enum hdmi_infoframe_type { · 46 unmodified lines
47 HDMI_INFOFRAME_TYPE_AVI = 0x82,47 HDMI_INFOFRAME_TYPE_AVI = 0x82,
48 HDMI_INFOFRAME_TYPE_SPD = 0x83,48 HDMI_INFOFRAME_TYPE_SPD = 0x83,
49 HDMI_INFOFRAME_TYPE_AUDIO = 0x84,49 HDMI_INFOFRAME_TYPE_AUDIO = 0x84,
50 HDMI_INFOFRAME_TYPE_DRM = 0x87,
50};51};
51 52
52#define HDMI_IEEE_OUI 0x000c0353#define HDMI_IEEE_OUI 0x000c03
@@ -55,6 +56,7 @@ enum hdmi_infoframe_type { · 2 unmodified lines
55#define HDMI_AVI_INFOFRAME_SIZE 1356#define HDMI_AVI_INFOFRAME_SIZE 13
56#define HDMI_SPD_INFOFRAME_SIZE 2557#define HDMI_SPD_INFOFRAME_SIZE 25
57#define HDMI_AUDIO_INFOFRAME_SIZE 1058#define HDMI_AUDIO_INFOFRAME_SIZE 10
59#define HDMI_DRM_INFOFRAME_SIZE 26
58 60
59#define HDMI_INFOFRAME_SIZE(type) \61#define HDMI_INFOFRAME_SIZE(type) \
60 (HDMI_INFOFRAME_HEADER_SIZE + HDMI_ ## type ## _INFOFRAME_SIZE)62 (HDMI_INFOFRAME_HEADER_SIZE + HDMI_ ## type ## _INFOFRAME_SIZE)
@@ -152,6 +154,17 @@ enum hdmi_content_type { · 91 unmodified lines
152 HDMI_CONTENT_TYPE_GAME,154 HDMI_CONTENT_TYPE_GAME,
153};155};
154 156
157enum hdmi_metadata_type {
158 HDMI_STATIC_METADATA_TYPE1 = 1,
159};
160
161enum hdmi_eotf {
162 HDMI_EOTF_TRADITIONAL_GAMMA_SDR,
163 HDMI_EOTF_TRADITIONAL_GAMMA_HDR,
164 HDMI_EOTF_SMPTE_ST2084,
165 HDMI_EOTF_BT_2100_HLG,
166};
167
155struct hdmi_avi_infoframe {168struct hdmi_avi_infoframe {
156 enum hdmi_infoframe_type type;169 enum hdmi_infoframe_type type;
157 unsigned char version;170 unsigned char version;
@@ -175,12 +188,37 @@ struct hdmi_avi_infoframe { · 17 unmodified lines
175 unsigned short right_bar;188 unsigned short right_bar;
176};189};
177 190
191/* DRM Infoframe as per CTA 861.G spec */
192struct hdmi_drm_infoframe {
193 enum hdmi_infoframe_type type;
194 unsigned char version;
195 unsigned char length;
196 enum hdmi_eotf eotf;
197 enum hdmi_metadata_type metadata_type;
198 struct {
199 u16 x, y;
200 } display_primaries[3];
201 struct {
202 u16 x, y;
203 } white_point;
204 u16 max_display_mastering_luminance;
205 u16 min_display_mastering_luminance;
206 u16 max_cll;
207 u16 max_fall;
208};
209
178int hdmi_avi_infoframe_init(struct hdmi_avi_infoframe *frame);210int hdmi_avi_infoframe_init(struct hdmi_avi_infoframe *frame);
179ssize_t hdmi_avi_infoframe_pack(struct hdmi_avi_infoframe *frame, void *buffer,211ssize_t hdmi_avi_infoframe_pack(struct hdmi_avi_infoframe *frame, void *buffer,
180 size_t size);212 size_t size);
181ssize_t hdmi_avi_infoframe_pack_only(const struct hdmi_avi_infoframe *frame,213ssize_t hdmi_avi_infoframe_pack_only(const struct hdmi_avi_infoframe *frame,
182 void *buffer, size_t size);214 void *buffer, size_t size);
183int hdmi_avi_infoframe_check(struct hdmi_avi_infoframe *frame);215int hdmi_avi_infoframe_check(struct hdmi_avi_infoframe *frame);
216int hdmi_drm_infoframe_init(struct hdmi_drm_infoframe *frame);
217ssize_t hdmi_drm_infoframe_pack(struct hdmi_drm_infoframe *frame, void *buffer,
218 size_t size);
219ssize_t hdmi_drm_infoframe_pack_only(const struct hdmi_drm_infoframe *frame,
220 void *buffer, size_t size);
221int hdmi_drm_infoframe_check(struct hdmi_drm_infoframe *frame);
184 222
185enum hdmi_spd_sdi {223enum hdmi_spd_sdi {
186 HDMI_SPD_SDI_UNKNOWN,224 HDMI_SPD_SDI_UNKNOWN,
@@ -320,6 +358,22 @@ struct hdmi_vendor_infoframe { · 133 unmodified lines
320 unsigned int s3d_ext_data;358 unsigned int s3d_ext_data;
321};359};
322 360
361/* HDR Metadata as per 861.G spec */
362struct hdr_static_metadata {
363 __u8 eotf;
364 __u8 metadata_type;
365 __u16 max_cll;
366 __u16 max_fall;
367 __u16 min_cll;
368};
369
370struct hdr_sink_metadata {
371 __u32 metadata_type;
372 union {
373 struct hdr_static_metadata hdmi_type1;
374 };
375};
376
323int hdmi_vendor_infoframe_init(struct hdmi_vendor_infoframe *frame);377int hdmi_vendor_infoframe_init(struct hdmi_vendor_infoframe *frame);
324ssize_t hdmi_vendor_infoframe_pack(struct hdmi_vendor_infoframe *frame,378ssize_t hdmi_vendor_infoframe_pack(struct hdmi_vendor_infoframe *frame,
325 void *buffer, size_t size);379 void *buffer, size_t size);
@@ -355,6 +409,7 @@ union hdmi_infoframe { · 29 unmodified lines
355 struct hdmi_spd_infoframe spd;409 struct hdmi_spd_infoframe spd;
356 union hdmi_vendor_any_infoframe vendor;410 union hdmi_vendor_any_infoframe vendor;
357 struct hdmi_audio_infoframe audio;411 struct hdmi_audio_infoframe audio;
412 struct hdmi_drm_infoframe drm;
358};413};
359 414
360ssize_t hdmi_infoframe_pack(union hdmi_infoframe *frame, void *buffer,415ssize_t hdmi_infoframe_pack(union hdmi_infoframe *frame, void *buffer,
include/uapi/drm/drm.h+1−0
@@ -50,6 +50,7 @@ typedef unsigned int drm_handle_t; · 49 unmodified lines
50 50
51#else /* One of the BSDs */51#else /* One of the BSDs */
52 52
53#include <stdint.h>
53#include <sys/ioccom.h>54#include <sys/ioccom.h>
54#include <sys/types.h>55#include <sys/types.h>
55typedef int8_t __s8;56typedef int8_t __s8;
include/uapi/drm/drm_mode.h+23−0
@@ -630,6 +630,29 @@ struct drm_color_lut { · 629 unmodified lines
630 __u16 reserved;630 __u16 reserved;
631};631};
632 632
633/* HDR Metadata Infoframe as per 861.G spec */
634struct hdr_metadata_infoframe {
635 __u8 eotf;
636 __u8 metadata_type;
637 struct {
638 __u16 x, y;
639 } display_primaries[3];
640 struct {
641 __u16 x, y;
642 } white_point;
643 __u16 max_display_mastering_luminance;
644 __u16 min_display_mastering_luminance;
645 __u16 max_cll;
646 __u16 max_fall;
647};
648
649struct hdr_output_metadata {
650 __u32 metadata_type;
651 union {
652 struct hdr_metadata_infoframe hdmi_metadata_type1;
653 };
654};
655
633#define DRM_MODE_PAGE_FLIP_EVENT 0x01656#define DRM_MODE_PAGE_FLIP_EVENT 0x01
634#define DRM_MODE_PAGE_FLIP_ASYNC 0x02657#define DRM_MODE_PAGE_FLIP_ASYNC 0x02
635#define DRM_MODE_PAGE_FLIP_TARGET_ABSOLUTE 0x4658#define DRM_MODE_PAGE_FLIP_TARGET_ABSOLUTE 0x4
include/uapi/drm/v3d_drm.h+28−0
@@ -37,6 +37,7 @@ extern "C" { · 36 unmodified lines
37#define DRM_V3D_GET_PARAM 0x0437#define DRM_V3D_GET_PARAM 0x04
38#define DRM_V3D_GET_BO_OFFSET 0x0538#define DRM_V3D_GET_BO_OFFSET 0x05
39#define DRM_V3D_SUBMIT_TFU 0x0639#define DRM_V3D_SUBMIT_TFU 0x06
40#define DRM_V3D_SUBMIT_CSD 0x07
40 41
41#define DRM_IOCTL_V3D_SUBMIT_CL DRM_IOWR(DRM_COMMAND_BASE + DRM_V3D_SUBMIT_CL, struct drm_v3d_submit_cl)42#define DRM_IOCTL_V3D_SUBMIT_CL DRM_IOWR(DRM_COMMAND_BASE + DRM_V3D_SUBMIT_CL, struct drm_v3d_submit_cl)
42#define DRM_IOCTL_V3D_WAIT_BO DRM_IOWR(DRM_COMMAND_BASE + DRM_V3D_WAIT_BO, struct drm_v3d_wait_bo)43#define DRM_IOCTL_V3D_WAIT_BO DRM_IOWR(DRM_COMMAND_BASE + DRM_V3D_WAIT_BO, struct drm_v3d_wait_bo)
@@ -45,6 +46,7 @@ extern "C" { · 2 unmodified lines
45#define DRM_IOCTL_V3D_GET_PARAM DRM_IOWR(DRM_COMMAND_BASE + DRM_V3D_GET_PARAM, struct drm_v3d_get_param)46#define DRM_IOCTL_V3D_GET_PARAM DRM_IOWR(DRM_COMMAND_BASE + DRM_V3D_GET_PARAM, struct drm_v3d_get_param)
46#define DRM_IOCTL_V3D_GET_BO_OFFSET DRM_IOWR(DRM_COMMAND_BASE + DRM_V3D_GET_BO_OFFSET, struct drm_v3d_get_bo_offset)47#define DRM_IOCTL_V3D_GET_BO_OFFSET DRM_IOWR(DRM_COMMAND_BASE + DRM_V3D_GET_BO_OFFSET, struct drm_v3d_get_bo_offset)
47#define DRM_IOCTL_V3D_SUBMIT_TFU DRM_IOW(DRM_COMMAND_BASE + DRM_V3D_SUBMIT_TFU, struct drm_v3d_submit_tfu)48#define DRM_IOCTL_V3D_SUBMIT_TFU DRM_IOW(DRM_COMMAND_BASE + DRM_V3D_SUBMIT_TFU, struct drm_v3d_submit_tfu)
49#define DRM_IOCTL_V3D_SUBMIT_CSD DRM_IOW(DRM_COMMAND_BASE + DRM_V3D_SUBMIT_CSD, struct drm_v3d_submit_csd)
48 50
49/**51/**
50 * struct drm_v3d_submit_cl - ioctl argument for submitting commands to the 3D52 * struct drm_v3d_submit_cl - ioctl argument for submitting commands to the 3D
@@ -190,6 +192,7 @@ enum drm_v3d_param { · 139 unmodified lines
190 DRM_V3D_PARAM_V3D_CORE0_IDENT1,192 DRM_V3D_PARAM_V3D_CORE0_IDENT1,
191 DRM_V3D_PARAM_V3D_CORE0_IDENT2,193 DRM_V3D_PARAM_V3D_CORE0_IDENT2,
192 DRM_V3D_PARAM_SUPPORTS_TFU,194 DRM_V3D_PARAM_SUPPORTS_TFU,
195 DRM_V3D_PARAM_SUPPORTS_CSD,
193};196};
194 197
195struct drm_v3d_get_param {198struct drm_v3d_get_param {
@@ -230,6 +233,31 @@ struct drm_v3d_submit_tfu { · 34 unmodified lines
230 __u32 out_sync;233 __u32 out_sync;
231};234};
232 235
236/* Submits a compute shader for dispatch. This job will block on any
237 * previous compute shaders submitted on this fd, and any other
238 * synchronization must be performed with in_sync/out_sync.
239 */
240struct drm_v3d_submit_csd {
241 __u32 cfg[7];
242 __u32 coef[4];
243
244 /* Pointer to a u32 array of the BOs that are referenced by the job.
245 */
246 __u64 bo_handles;
247
248 /* Number of BO handles passed in (size is that times 4). */
249 __u32 bo_handle_count;
250
251 /* sync object to block on before running the CSD job. Each
252 * CSD job will execute in the order submitted to its FD.
253 * Synchronization against rendering/TFU jobs or CSD from
254 * other fds requires using sync objects.
255 */
256 __u32 in_sync;
257 /* Sync object to signal when the CSD job is done. */
258 __u32 out_sync;
259};
260
233#if defined(__cplusplus)261#if defined(__cplusplus)
234}262}
235#endif263#endif